summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-12-13 00:07:19 +0800
committerchai <chaifix@163.com>2021-12-13 00:07:19 +0800
commit60cbbdec07ab7a5636eac5b3c024ae44e937f4d4 (patch)
treeb2c7b0a868f18159dbc43d8954e1bd7668549a88
+init
-rw-r--r--.gitignore0
-rw-r--r--Client/.gitignore8
-rw-r--r--Client/Art/Avatar/test.pdnbin0 -> 134769 bytes
-rw-r--r--Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj130
-rw-r--r--Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.filters17
-rw-r--r--Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.user4
-rw-r--r--Client/Project/VisualStudio/Ragdolls/Ragdolls.sln48
-rw-r--r--Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj256
-rw-r--r--Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.filters382
-rw-r--r--Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.user4
-rw-r--r--Client/Project/VisualStudio/Ragdolls/Ragdolls/imgui.ini34
-rw-r--r--Client/Source/Common/DataBuffer.cpp0
-rw-r--r--Client/Source/Common/DataBuffer.h29
-rw-r--r--Client/Source/Debug/Log.cpp164
-rw-r--r--Client/Source/Debug/Log.h14
-rw-r--r--Client/Source/GUI/Font.cpp302
-rw-r--r--Client/Source/GUI/Font.h149
-rw-r--r--Client/Source/GUI/TextMeshGenerator.cpp89
-rw-r--r--Client/Source/GUI/TextMeshGenerator.h31
-rw-r--r--Client/Source/GUI/UI9Slicing.cpp112
-rw-r--r--Client/Source/GUI/UI9Slicing.h25
-rw-r--r--Client/Source/GUI/UILine.cpp48
-rw-r--r--Client/Source/GUI/UILine.h21
-rw-r--r--Client/Source/GUI/UIMesh.cpp15
-rw-r--r--Client/Source/GUI/UIMesh.h42
-rw-r--r--Client/Source/GUI/UIQuad.cpp64
-rw-r--r--Client/Source/GUI/UIQuad.h21
-rw-r--r--Client/Source/GUI/UISquare.cpp53
-rw-r--r--Client/Source/GUI/UISquare.h22
-rw-r--r--Client/Source/GUI/UITextMesh.cpp278
-rw-r--r--Client/Source/GUI/UITextMesh.h69
-rw-r--r--Client/Source/GUI/freetype.h4
-rw-r--r--Client/Source/GUI/utf8.cpp415
-rw-r--r--Client/Source/GUI/utf8.h113
-rw-r--r--Client/Source/Graphics/Color.cpp4
-rw-r--r--Client/Source/Graphics/Color.h48
-rw-r--r--Client/Source/Graphics/CustomVertexLayout.cpp23
-rw-r--r--Client/Source/Graphics/CustomVertexLayout.h33
-rw-r--r--Client/Source/Graphics/DefaultVertexLayout.cpp119
-rw-r--r--Client/Source/Graphics/DefaultVertexLayout.h55
-rw-r--r--Client/Source/Graphics/DeviceDefine.h69
-rw-r--r--Client/Source/Graphics/DynamicMesh.h13
-rw-r--r--Client/Source/Graphics/DynamicVertexBuffer.cpp260
-rw-r--r--Client/Source/Graphics/DynamicVertexBuffer.h54
-rw-r--r--Client/Source/Graphics/FrameBuffer.cpp12
-rw-r--r--Client/Source/Graphics/FrameBuffer.h35
-rw-r--r--Client/Source/Graphics/GPUDataBuffer.cpp207
-rw-r--r--Client/Source/Graphics/GPUDataBuffer.h75
-rw-r--r--Client/Source/Graphics/GfxDevice.cpp169
-rw-r--r--Client/Source/Graphics/GfxDevice.h109
-rw-r--r--Client/Source/Graphics/GlyphAtlas.cpp0
-rw-r--r--Client/Source/Graphics/GlyphAtlas.h6
-rw-r--r--Client/Source/Graphics/ImageData.cpp2
-rw-r--r--Client/Source/Graphics/ImageData.h39
-rw-r--r--Client/Source/Graphics/OpenGL.cpp7
-rw-r--r--Client/Source/Graphics/OpenGL.h41
-rw-r--r--Client/Source/Graphics/Point.cpp0
-rw-r--r--Client/Source/Graphics/Point.h0
-rw-r--r--Client/Source/Graphics/PolyLine.cpp9
-rw-r--r--Client/Source/Graphics/PolyLine.h18
-rw-r--r--Client/Source/Graphics/Primitive.h8
-rw-r--r--Client/Source/Graphics/Quad.cpp62
-rw-r--r--Client/Source/Graphics/Quad.h26
-rw-r--r--Client/Source/Graphics/RenderCommands.cpp9
-rw-r--r--Client/Source/Graphics/RenderCommands.h164
-rw-r--r--Client/Source/Graphics/RenderTexture.cpp0
-rw-r--r--Client/Source/Graphics/RenderTexture.h16
-rw-r--r--Client/Source/Graphics/Shader.cpp154
-rw-r--r--Client/Source/Graphics/Shader.h47
-rw-r--r--Client/Source/Graphics/ShaderCompiler.cpp347
-rw-r--r--Client/Source/Graphics/ShaderCompiler.h55
-rw-r--r--Client/Source/Graphics/Texture.cpp230
-rw-r--r--Client/Source/Graphics/Texture.h94
-rw-r--r--Client/Source/Graphics/VertexAttribute.cpp20
-rw-r--r--Client/Source/Graphics/VertexAttribute.h52
-rw-r--r--Client/Source/Graphics/VertexBuffer.cpp109
-rw-r--r--Client/Source/Graphics/VertexBuffer.h52
-rw-r--r--Client/Source/Math/Functions.cpp0
-rw-r--r--Client/Source/Math/Functions.h30
-rw-r--r--Client/Source/Math/Math.h6
-rw-r--r--Client/Source/Math/Matrix22.h10
-rw-r--r--Client/Source/Math/Matrix44.h8
-rw-r--r--Client/Source/Math/Rect.h13
-rw-r--r--Client/Source/Math/Vector2.hpp67
-rw-r--r--Client/Source/Math/Vector3.hpp32
-rw-r--r--Client/Source/Math/Vector4.hpp33
-rw-r--r--Client/Source/RagdollMain.cpp89
-rw-r--r--Client/Source/Threading/Job.cpp13
-rw-r--r--Client/Source/Threading/Job.h17
-rw-r--r--Client/Source/Threading/JobSystem.cpp56
-rw-r--r--Client/Source/Threading/JobSystem.h25
-rw-r--r--Client/Source/Threading/Mutex.cpp27
-rw-r--r--Client/Source/Threading/Mutex.h39
-rw-r--r--Client/Source/Threading/Semaphore.cpp0
-rw-r--r--Client/Source/Threading/Semaphore.h0
-rw-r--r--Client/Source/Threading/Thread.cpp70
-rw-r--r--Client/Source/Threading/Thread.h71
-rw-r--r--Client/Source/Threading/WorkThread.cpp50
-rw-r--r--Client/Source/Utilities/Assert.h11
-rw-r--r--Client/Source/Utilities/AutoInvoke.h27
-rw-r--r--Client/Source/Utilities/Exception.h12
-rw-r--r--Client/Source/Utilities/Singleton.h43
-rw-r--r--Client/Source/Utilities/StaticInitiator.h30
-rw-r--r--Client/Source/Utilities/Type.h25
-rw-r--r--Client/Source/Utilities/UIDGenerator.h20
-rw-r--r--Client/Source/Utilities/UtilMacros.h19
-rw-r--r--Client/ThirdParty/Box2D/.gitignore7
-rw-r--r--Client/ThirdParty/Box2D/.travis.yml32
-rw-r--r--Client/ThirdParty/Box2D/CHANGELOG.md60
-rw-r--r--Client/ThirdParty/Box2D/CMakeLists.txt65
-rw-r--r--Client/ThirdParty/Box2D/LICENSE21
-rw-r--r--Client/ThirdParty/Box2D/README.md115
-rw-r--r--Client/ThirdParty/Box2D/build.bat7
-rw-r--r--Client/ThirdParty/Box2D/build.sh8
-rw-r--r--Client/ThirdParty/Box2D/build_docs.sh8
-rw-r--r--Client/ThirdParty/Box2D/deploy_docs.sh4
-rw-r--r--Client/ThirdParty/Box2D/docs/CMakeLists.txt32
-rw-r--r--Client/ThirdParty/Box2D/docs/Doxyfile.in2578
-rw-r--r--Client/ThirdParty/Box2D/docs/FAQ.md146
-rw-r--r--Client/ThirdParty/Box2D/docs/collision.md433
-rw-r--r--Client/ThirdParty/Box2D/docs/common.md66
-rw-r--r--Client/ThirdParty/Box2D/docs/copycss.sh2
-rw-r--r--Client/ThirdParty/Box2D/docs/dynamics.md1674
-rw-r--r--Client/ThirdParty/Box2D/docs/extra.css605
-rw-r--r--Client/ThirdParty/Box2D/docs/hello.md246
-rw-r--r--Client/ThirdParty/Box2D/docs/images/body_origin.gifbin0 -> 912 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/captured_toi.svg124
-rw-r--r--Client/ThirdParty/Box2D/docs/images/chain_loop_inwards.svg310
-rw-r--r--Client/ThirdParty/Box2D/docs/images/chain_loop_outwards.svg310
-rw-r--r--Client/ThirdParty/Box2D/docs/images/chain_shape.svg198
-rw-r--r--Client/ThirdParty/Box2D/docs/images/convex_concave.gifbin0 -> 2303 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/debug_draw.pngbin0 -> 48950 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/distance.svg178
-rw-r--r--Client/ThirdParty/Box2D/docs/images/distance_joint.gifbin0 -> 2358 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/gear_joint.gifbin0 -> 2119 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/ghost_collision.svg237
-rw-r--r--Client/ThirdParty/Box2D/docs/images/ghost_vertices.svg265
-rw-r--r--Client/ThirdParty/Box2D/docs/images/logo.svg126
-rw-r--r--Client/ThirdParty/Box2D/docs/images/manifolds.svg256
-rw-r--r--Client/ThirdParty/Box2D/docs/images/missed_toi.svg153
-rw-r--r--Client/ThirdParty/Box2D/docs/images/modules.svg222
-rw-r--r--Client/ThirdParty/Box2D/docs/images/overlap_test.svg148
-rw-r--r--Client/ThirdParty/Box2D/docs/images/prismatic_joint.gifbin0 -> 2298 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/pulley_joint.gifbin0 -> 3526 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/raycast.svg151
-rw-r--r--Client/ThirdParty/Box2D/docs/images/revolute_joint.gifbin0 -> 1920 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/self_intersect.svg149
-rw-r--r--Client/ThirdParty/Box2D/docs/images/skin_collision.svg140
-rw-r--r--Client/ThirdParty/Box2D/docs/images/skinned_polygon.svg181
-rw-r--r--Client/ThirdParty/Box2D/docs/images/testbed.pngbin0 -> 42221 bytes
-rw-r--r--Client/ThirdParty/Box2D/docs/images/tunneling1.svg162
-rw-r--r--Client/ThirdParty/Box2D/docs/images/tunneling2.svg140
-rw-r--r--Client/ThirdParty/Box2D/docs/images/wheel_joint.svg193
-rw-r--r--Client/ThirdParty/Box2D/docs/images/winding.svg241
-rw-r--r--Client/ThirdParty/Box2D/docs/loose_ends.md214
-rw-r--r--Client/ThirdParty/Box2D/docs/overview.md216
-rw-r--r--Client/ThirdParty/Box2D/docs/references.md4
-rw-r--r--Client/ThirdParty/Box2D/docs/testbed.md21
-rw-r--r--Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt11
-rw-r--r--Client/ThirdParty/Box2D/extern/glad/include/KHR/khrplatform.h290
-rw-r--r--Client/ThirdParty/Box2D/extern/glad/include/glad/gl.h2114
-rw-r--r--Client/ThirdParty/Box2D/extern/glad/src/gl.c949
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt92
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3.h5556
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3native.h525
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_init.m403
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.h50
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.m462
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_monitor.m527
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_platform.h169
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_time.c60
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/cocoa_window.m1855
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/context.c758
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/egl_context.c786
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/egl_context.h215
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/glfw_config.h45
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/glx_context.c698
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/glx_context.h181
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/init.c338
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/input.c1307
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/internal.h772
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.c434
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.h62
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/mappings.h478
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/mappings.h.in73
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/monitor.c517
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.h56
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.m340
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/null_init.c50
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.c42
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.h31
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/null_monitor.c69
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/null_platform.h62
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/null_window.c321
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.c370
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.h94
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.c103
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.h51
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/posix_time.c85
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/posix_time.h44
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/vulkan.c326
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.c732
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.h159
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_init.c627
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.c753
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.h56
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_monitor.c515
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_platform.h449
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_thread.c97
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_time.c74
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/win32_window.c2205
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/window.c1113
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/wl_init.c1318
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/wl_monitor.c208
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/wl_platform.h359
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/wl_window.c1857
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/x11_init.c1096
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/x11_monitor.c517
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/x11_platform.h444
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/x11_window.c3066
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.c940
-rw-r--r--Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.h28
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt19
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imconfig.h73
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imgui.cpp9349
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imgui.h2130
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imgui_demo.cpp4211
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imgui_draw.cpp3199
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imgui_internal.h1466
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imgui_widgets.cpp6557
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imstb_rectpack.h623
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imstb_textedit.h1409
-rw-r--r--Client/ThirdParty/Box2D/extern/imgui/imstb_truetype.h4854
-rw-r--r--Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt10
-rw-r--r--Client/ThirdParty/Box2D/extern/sajson/sajson.cpp2
-rw-r--r--Client/ThirdParty/Box2D/extern/sajson/sajson.h2493
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_api.h52
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_block_allocator.h60
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_body.h878
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_broad_phase.h238
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_chain_shape.h101
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_circle_shape.h67
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_collision.h283
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_common.h138
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_contact.h386
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_contact_manager.h57
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_distance.h171
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_distance_joint.h176
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_draw.h102
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_dynamic_tree.h308
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_edge_shape.h86
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_fixture.h365
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_friction_joint.h124
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_gear_joint.h130
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_growable_stack.h91
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_joint.h228
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_math.h715
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_motor_joint.h138
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_mouse_joint.h134
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_polygon_shape.h95
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_prismatic_joint.h205
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_pulley_joint.h157
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_revolute_joint.h211
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_rope.h153
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_settings.h127
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_shape.h110
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_stack_allocator.h65
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_time_of_impact.h63
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_time_step.h74
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_timer.h55
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_types.h33
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_weld_joint.h133
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_wheel_joint.h240
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_world.h345
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/b2_world_callbacks.h161
-rw-r--r--Client/ThirdParty/Box2D/include/box2d/box2d.h58
-rw-r--r--Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj201
-rw-r--r--Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj.filters8
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeCache.txt441
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/049e1eb7380682ec4cf9a2c62dad57db/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/14f8a92cc8883d19b638672092016c39/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCCompiler.cmake72
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCXXCompiler.cmake83
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_C.binbin0 -> 35840 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_CXX.binbin0 -> 35840 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeRCCompiler.cmake6
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeSystem.cmake15
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CMakeCCompilerId.c803
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.exebin0 -> 11264 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.vcxproj71
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CMakeCCompilerId.objbin0 -> 1949 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.command.1.tlogbin0 -> 906 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.read.1.tlogbin0 -> 668 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.write.1.tlogbin0 -> 544 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CompilerIdC.lastbuildstate2
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.command.1.tlogbin0 -> 1122 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.read.1.tlogbin0 -> 3730 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.write.1.tlogbin0 -> 538 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CMakeCXXCompilerId.cpp791
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.exebin0 -> 11264 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.vcxproj71
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CMakeCXXCompilerId.objbin0 -> 1967 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlogbin0 -> 930 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlogbin0 -> 680 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlogbin0 -> 564 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate2
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlogbin0 -> 1146 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlogbin0 -> 3746 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlogbin0 -> 554 bytes
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate2
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.txt1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.vcxproj28
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/generate.stamp.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/455517aeb2285a20077dbce51065d1ef/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/5db6461968e3a28c7176c305697cc35c/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/6ddefecedef78174b7ed9b2bc8a1e035/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/9ab13db7d2176474a16e440b6b1b97a8/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeError.log16
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeOutput.log123
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/TargetDirectories.txt17
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/bfe9de955132cd9d067c24acf7d98bef/INSTALL_force.rule1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/cmake.check_cache1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.depend96
-rw-r--r--Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.list8
-rw-r--r--Client/ThirdParty/Box2D/proj/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj167
-rw-r--r--Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/box2d.sln164
-rw-r--r--Client/ThirdParty/Box2D/proj/cmake_install.cmake60
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp.depend2
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/cmake_install.cmake34
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj279
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj.filters33
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp.depend10
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/cmake_install.cmake34
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj300
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj.filters93
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp.depend2
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/cmake_install.cmake34
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj286
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj.filters22
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp.depend2
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/cmake_install.cmake34
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj278
-rw-r--r--Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj.filters14
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-debug.cmake19
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-minsizerel.cmake19
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-release.cmake19
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-relwithdebinfo.cmake19
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig.cmake94
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp.depend5
-rw-r--r--Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/src/box2d.vcxproj374
-rw-r--r--Client/ThirdParty/Box2D/proj/src/box2d.vcxproj.filters315
-rw-r--r--Client/ThirdParty/Box2D/proj/src/box2dConfigVersion.cmake70
-rw-r--r--Client/ThirdParty/Box2D/proj/src/cmake_install.cmake90
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp.depend2
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/cmake_install.cmake34
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj465
-rw-r--r--Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj.filters200
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp1
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp.depend2
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj193
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj.filters13
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/cmake_install.cmake34
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj334
-rw-r--r--Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj.filters18
-rw-r--r--Client/ThirdParty/Box2D/src/CMakeLists.txt163
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_broad_phase.cpp131
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_chain_shape.cpp185
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_circle_shape.cpp105
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_collide_circle.cpp158
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_collide_edge.cpp524
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_collide_polygon.cpp243
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_collision.cpp258
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_distance.cpp746
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_dynamic_tree.cpp801
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_edge_shape.cpp158
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_polygon_shape.cpp459
-rw-r--r--Client/ThirdParty/Box2D/src/collision/b2_time_of_impact.cpp490
-rw-r--r--Client/ThirdParty/Box2D/src/common/b2_block_allocator.cpp230
-rw-r--r--Client/ThirdParty/Box2D/src/common/b2_draw.cpp47
-rw-r--r--Client/ThirdParty/Box2D/src/common/b2_math.cpp98
-rw-r--r--Client/ThirdParty/Box2D/src/common/b2_settings.cpp74
-rw-r--r--Client/ThirdParty/Box2D/src/common/b2_stack_allocator.cpp87
-rw-r--r--Client/ThirdParty/Box2D/src/common/b2_timer.cpp125
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_body.cpp565
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.cpp57
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.h43
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.cpp57
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.h43
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.cpp56
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.h43
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_contact.cpp252
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_contact_manager.cpp293
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.cpp843
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.h100
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_distance_joint.cpp421
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.cpp54
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.h43
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.cpp54
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.h43
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_fixture.cpp305
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_friction_joint.cpp255
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_gear_joint.cpp429
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_island.cpp544
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_island.h97
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_joint.cpp301
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_motor_joint.cpp311
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_mouse_joint.cpp192
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.cpp54
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.h42
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.cpp57
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.h43
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_prismatic_joint.cpp643
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_pulley_joint.cpp352
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_revolute_joint.cpp501
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_weld_joint.cpp344
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_wheel_joint.cpp672
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_world.cpp1322
-rw-r--r--Client/ThirdParty/Box2D/src/dynamics/b2_world_callbacks.cpp40
-rw-r--r--Client/ThirdParty/Box2D/src/rope/b2_rope.cpp809
-rw-r--r--Client/ThirdParty/Box2D/testbed/CMakeLists.txt92
-rw-r--r--Client/ThirdParty/Box2D/testbed/MacOSXBundleInfo.plist.in41
-rw-r--r--Client/ThirdParty/Box2D/testbed/data/droid_sans.ttfbin0 -> 190044 bytes
-rw-r--r--Client/ThirdParty/Box2D/testbed/draw.cpp829
-rw-r--r--Client/ThirdParty/Box2D/testbed/draw.h102
-rw-r--r--Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.cpp324
-rw-r--r--Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.h33
-rw-r--r--Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.cpp556
-rw-r--r--Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.h44
-rw-r--r--Client/ThirdParty/Box2D/testbed/main.cpp651
-rw-r--r--Client/ThirdParty/Box2D/testbed/settings.cpp176
-rw-r--r--Client/ThirdParty/Box2D/testbed/settings.h83
-rw-r--r--Client/ThirdParty/Box2D/testbed/test.cpp469
-rw-r--r--Client/ThirdParty/Box2D/testbed/test.h156
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/add_pair.cpp71
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/apply_force.cpp203
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/body_types.cpp163
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/box_stack.cpp174
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/breakable.cpp158
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/bridge.cpp128
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/bullet_test.cpp139
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/cantilever.cpp218
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/car.cpp284
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/chain.cpp92
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/chain_problem.cpp94
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/character_collision.cpp256
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/circle_stack.cpp89
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/collision_filtering.cpp179
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/collision_processing.cpp191
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/compound_shapes.cpp227
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/confined.cpp170
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/continuous_test.cpp160
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/convex_hull.cpp112
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/conveyor_belt.cpp101
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/distance_joint.cpp123
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/distance_test.cpp139
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/dominos.cpp220
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/dump_loader.cpp88
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/dynamic_tree.cpp360
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/edge_shapes.cpp253
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/edge_test.cpp282
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/friction.cpp127
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/gear_joint.cpp180
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/heavy1.cpp61
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/heavy2.cpp94
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/mobile_balanced.cpp108
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/mobile_unbalanced.cpp105
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/motor_joint.cpp118
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/pinball.cpp170
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/platformer.cpp133
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/polygon_collision.cpp127
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/polygon_shapes.cpp265
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/prismatic_joint.cpp118
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/pulley_joint.cpp96
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/pyramid.cpp92
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/ray_cast.cpp479
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/restitution.cpp79
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/revolute_joint.cpp162
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/rope.cpp286
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/sensor.cpp195
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/shape_cast.cpp193
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/shape_editing.cpp108
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/skier.cpp150
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/slider_crank_1.cpp106
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/slider_crank_2.cpp160
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/theo_jansen.cpp266
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/tiles.cpp159
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/time_of_impact.cpp131
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/tumbler.cpp102
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/web.cpp218
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/wheel_joint.cpp126
-rw-r--r--Client/ThirdParty/Box2D/testbed/tests/wrecking_ball.cpp165
-rw-r--r--Client/ThirdParty/Box2D/unit-test/CMakeLists.txt18
-rw-r--r--Client/ThirdParty/Box2D/unit-test/collision_test.cpp81
-rw-r--r--Client/ThirdParty/Box2D/unit-test/doctest.h6580
-rw-r--r--Client/ThirdParty/Box2D/unit-test/hello_world.cpp112
-rw-r--r--Client/ThirdParty/Box2D/unit-test/joint_test.cpp106
-rw-r--r--Client/ThirdParty/Box2D/unit-test/math_test.cpp54
-rw-r--r--Client/ThirdParty/Box2D/unit-test/world_test.cpp73
-rw-r--r--Client/ThirdParty/SDL2/BUGS.txt16
-rw-r--r--Client/ThirdParty/SDL2/COPYING.txt20
-rw-r--r--Client/ThirdParty/SDL2/README-SDL.txt13
-rw-r--r--Client/ThirdParty/SDL2/README.txt21
-rw-r--r--Client/ThirdParty/SDL2/SDL.h221
-rw-r--r--Client/ThirdParty/SDL2/SDL_assert.h318
-rw-r--r--Client/ThirdParty/SDL2/SDL_atomic.h379
-rw-r--r--Client/ThirdParty/SDL2/SDL_audio.h1185
-rw-r--r--Client/ThirdParty/SDL2/SDL_bits.h126
-rw-r--r--Client/ThirdParty/SDL2/SDL_blendmode.h200
-rw-r--r--Client/ThirdParty/SDL2/SDL_clipboard.h89
-rw-r--r--Client/ThirdParty/SDL2/SDL_config.h299
-rw-r--r--Client/ThirdParty/SDL2/SDL_config.h.cmake445
-rw-r--r--Client/ThirdParty/SDL2/SDL_config.h.in389
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_android.h157
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_iphoneos.h166
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_macosx.h197
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_macosx.h.orig197
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_minimal.h82
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_pandora.h128
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_psp.h144
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_windows.h225
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_winrt.h215
-rw-r--r--Client/ThirdParty/SDL2/SDL_config_wiz.h121
-rw-r--r--Client/ThirdParty/SDL2/SDL_copying.h20
-rw-r--r--Client/ThirdParty/SDL2/SDL_cpuinfo.h524
-rw-r--r--Client/ThirdParty/SDL2/SDL_egl.h1676
-rw-r--r--Client/ThirdParty/SDL2/SDL_endian.h316
-rw-r--r--Client/ThirdParty/SDL2/SDL_error.h155
-rw-r--r--Client/ThirdParty/SDL2/SDL_events.h1098
-rw-r--r--Client/ThirdParty/SDL2/SDL_filesystem.h145
-rw-r--r--Client/ThirdParty/SDL2/SDL_gamecontroller.h870
-rw-r--r--Client/ThirdParty/SDL2/SDL_gesture.h117
-rw-r--r--Client/ThirdParty/SDL2/SDL_haptic.h1320
-rw-r--r--Client/ThirdParty/SDL2/SDL_hints.h1840
-rw-r--r--Client/ThirdParty/SDL2/SDL_joystick.h821
-rw-r--r--Client/ThirdParty/SDL2/SDL_keyboard.h294
-rw-r--r--Client/ThirdParty/SDL2/SDL_keycode.h351
-rw-r--r--Client/ThirdParty/SDL2/SDL_loadso.h109
-rw-r--r--Client/ThirdParty/SDL2/SDL_locale.h101
-rw-r--r--Client/ThirdParty/SDL2/SDL_log.h376
-rw-r--r--Client/ThirdParty/SDL2/SDL_main.h186
-rw-r--r--Client/ThirdParty/SDL2/SDL_messagebox.h191
-rw-r--r--Client/ThirdParty/SDL2/SDL_metal.h104
-rw-r--r--Client/ThirdParty/SDL2/SDL_misc.h79
-rw-r--r--Client/ThirdParty/SDL2/SDL_mouse.h432
-rw-r--r--Client/ThirdParty/SDL2/SDL_mutex.h435
-rw-r--r--Client/ThirdParty/SDL2/SDL_name.h33
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengl.h2183
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengl_glext.h11180
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengles.h39
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengles2.h52
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengles2_gl2.h621
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengles2_gl2ext.h2050
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengles2_gl2platform.h30
-rw-r--r--Client/ThirdParty/SDL2/SDL_opengles2_khrplatform.h282
-rw-r--r--Client/ThirdParty/SDL2/SDL_pixels.h613
-rw-r--r--Client/ThirdParty/SDL2/SDL_platform.h233
-rw-r--r--Client/ThirdParty/SDL2/SDL_power.h86
-rw-r--r--Client/ThirdParty/SDL2/SDL_quit.h58
-rw-r--r--Client/ThirdParty/SDL2/SDL_rect.h218
-rw-r--r--Client/ThirdParty/SDL2/SDL_render.h1625
-rw-r--r--Client/ThirdParty/SDL2/SDL_revision.h2
-rw-r--r--Client/ThirdParty/SDL2/SDL_rwops.h412
-rw-r--r--Client/ThirdParty/SDL2/SDL_scancode.h413
-rw-r--r--Client/ThirdParty/SDL2/SDL_sensor.h271
-rw-r--r--Client/ThirdParty/SDL2/SDL_shape.h147
-rw-r--r--Client/ThirdParty/SDL2/SDL_stdinc.h694
-rw-r--r--Client/ThirdParty/SDL2/SDL_surface.h887
-rw-r--r--Client/ThirdParty/SDL2/SDL_system.h475
-rw-r--r--Client/ThirdParty/SDL2/SDL_syswm.h378
-rw-r--r--Client/ThirdParty/SDL2/SDL_test.h69
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_assert.h105
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_common.h230
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_compare.h69
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_crc32.h124
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_font.h81
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_fuzzer.h386
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_harness.h134
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_images.h78
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_log.h67
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_md5.h129
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_memory.h63
-rw-r--r--Client/ThirdParty/SDL2/SDL_test_random.h115
-rw-r--r--Client/ThirdParty/SDL2/SDL_thread.h454
-rw-r--r--Client/ThirdParty/SDL2/SDL_timer.h172
-rw-r--r--Client/ThirdParty/SDL2/SDL_touch.h138
-rw-r--r--Client/ThirdParty/SDL2/SDL_types.h29
-rw-r--r--Client/ThirdParty/SDL2/SDL_version.h172
-rw-r--r--Client/ThirdParty/SDL2/SDL_video.h1901
-rw-r--r--Client/ThirdParty/SDL2/SDL_vulkan.h213
-rw-r--r--Client/ThirdParty/SDL2/WhatsNew.txt643
-rw-r--r--Client/ThirdParty/SDL2/begin_code.h166
-rw-r--r--Client/ThirdParty/SDL2/close_code.h40
-rw-r--r--Client/ThirdParty/SDL2/docs/README-android.md472
-rw-r--r--Client/ThirdParty/SDL2/docs/README-cmake.md84
-rw-r--r--Client/ThirdParty/SDL2/docs/README-directfb.md107
-rw-r--r--Client/ThirdParty/SDL2/docs/README-dynapi.md138
-rw-r--r--Client/ThirdParty/SDL2/docs/README-emscripten.md35
-rw-r--r--Client/ThirdParty/SDL2/docs/README-gesture.md71
-rw-r--r--Client/ThirdParty/SDL2/docs/README-git.md19
-rw-r--r--Client/ThirdParty/SDL2/docs/README-hg.md4
-rw-r--r--Client/ThirdParty/SDL2/docs/README-ios.md295
-rw-r--r--Client/ThirdParty/SDL2/docs/README-kmsbsd.md27
-rw-r--r--Client/ThirdParty/SDL2/docs/README-linux.md83
-rw-r--r--Client/ThirdParty/SDL2/docs/README-macosx.md240
-rw-r--r--Client/ThirdParty/SDL2/docs/README-nacl.md103
-rw-r--r--Client/ThirdParty/SDL2/docs/README-os2.md54
-rw-r--r--Client/ThirdParty/SDL2/docs/README-pandora.md17
-rw-r--r--Client/ThirdParty/SDL2/docs/README-platforms.md8
-rw-r--r--Client/ThirdParty/SDL2/docs/README-porting.md68
-rw-r--r--Client/ThirdParty/SDL2/docs/README-psp.md19
-rw-r--r--Client/ThirdParty/SDL2/docs/README-raspberrypi.md188
-rw-r--r--Client/ThirdParty/SDL2/docs/README-touch.md86
-rw-r--r--Client/ThirdParty/SDL2/docs/README-visualc.md114
-rw-r--r--Client/ThirdParty/SDL2/docs/README-vita.md25
-rw-r--r--Client/ThirdParty/SDL2/docs/README-wince.md10
-rw-r--r--Client/ThirdParty/SDL2/docs/README-windows.md45
-rw-r--r--Client/ThirdParty/SDL2/docs/README-winrt.md550
-rw-r--r--Client/ThirdParty/SDL2/docs/README.md65
-rw-r--r--Client/ThirdParty/SDL2/docs/doxyfile1560
-rw-r--r--Client/ThirdParty/SDL2/include/SDL.h221
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_assert.h318
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_atomic.h379
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_audio.h1185
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_bits.h126
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_blendmode.h200
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_clipboard.h89
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config.h299
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config.h.cmake445
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config.h.in389
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_android.h157
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_iphoneos.h166
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_macosx.h197
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_macosx.h.orig197
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_minimal.h82
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_pandora.h128
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_psp.h144
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_windows.h225
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_winrt.h215
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_config_wiz.h121
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_copying.h20
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_cpuinfo.h524
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_egl.h1676
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_endian.h316
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_error.h155
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_events.h1098
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_filesystem.h145
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_gamecontroller.h870
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_gesture.h117
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_haptic.h1320
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_hints.h1840
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_joystick.h821
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_keyboard.h294
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_keycode.h351
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_loadso.h109
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_locale.h101
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_log.h376
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_main.h186
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_messagebox.h191
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_metal.h104
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_misc.h79
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_mouse.h432
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_mutex.h435
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_name.h33
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengl.h2183
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengl_glext.h11180
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengles.h39
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengles2.h52
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengles2_gl2.h621
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengles2_gl2ext.h2050
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengles2_gl2platform.h30
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_opengles2_khrplatform.h282
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_pixels.h613
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_platform.h233
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_power.h86
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_quit.h58
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_rect.h218
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_render.h1625
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_revision.h2
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_rwops.h412
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_scancode.h413
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_sensor.h271
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_shape.h147
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_stdinc.h694
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_surface.h887
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_system.h475
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_syswm.h378
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test.h69
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_assert.h105
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_common.h230
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_compare.h69
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_crc32.h124
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_font.h81
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_fuzzer.h386
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_harness.h134
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_images.h78
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_log.h67
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_md5.h129
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_memory.h63
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_test_random.h115
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_thread.h454
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_timer.h172
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_touch.h138
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_types.h29
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_version.h172
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_video.h1901
-rw-r--r--Client/ThirdParty/SDL2/include/SDL_vulkan.h213
-rw-r--r--Client/ThirdParty/SDL2/include/begin_code.h166
-rw-r--r--Client/ThirdParty/SDL2/include/close_code.h40
-rw-r--r--Client/ThirdParty/SDL2/lib/x64/SDL2.dllbin0 -> 1609728 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x64/SDL2.libbin0 -> 165034 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x64/SDL2main.libbin0 -> 42892 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x64/SDL2test.libbin0 -> 979548 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x86/SDL2.dllbin0 -> 1398272 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x86/SDL2.libbin0 -> 168866 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x86/SDL2main.libbin0 -> 41534 bytes
-rw-r--r--Client/ThirdParty/SDL2/lib/x86/SDL2test.libbin0 -> 934890 bytes
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.cpp43
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.h36
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyTemplate.h48
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.cpp76
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.sln20
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.vcproj229
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.cpp8
-rw-r--r--Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.h24
-rw-r--r--Client/ThirdParty/StaticConstructor/include/StaticConstructor.h126
-rw-r--r--Client/ThirdParty/freetype/ChangeLog7815
-rw-r--r--Client/ThirdParty/freetype/FTL.TXT169
-rw-r--r--Client/ThirdParty/freetype/GPLv2.TXT340
-rw-r--r--Client/ThirdParty/freetype/LICENSE.TXT42
-rw-r--r--Client/ThirdParty/freetype/README.md23
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/ftconfig.h51
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/ftheader.h824
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/ftmodule.h32
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/ftoption.h1011
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/ftstdlib.h175
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/integer-types.h245
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/mac-support.h49
-rw-r--r--Client/ThirdParty/freetype/include/freetype/config/public-macros.h120
-rw-r--r--Client/ThirdParty/freetype/include/freetype/freetype.h4833
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftadvanc.h188
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftbbox.h101
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftbdf.h212
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftbitmap.h329
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftbzip2.h102
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftcache.h1087
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftchapters.h147
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftcid.h167
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftcolor.h1609
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftdriver.h1193
-rw-r--r--Client/ThirdParty/freetype/include/freetype/fterrdef.h279
-rw-r--r--Client/ThirdParty/freetype/include/freetype/fterrors.h296
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftfntfmt.h93
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftgasp.h143
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftglyph.h664
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftgxval.h354
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftgzip.h151
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftimage.h1276
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftincrem.h348
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftlcdfil.h323
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftlist.h296
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftlogging.h184
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftlzw.h100
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftmac.h289
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftmm.h752
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftmodapi.h806
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftmoderr.h204
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftotval.h206
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftoutln.h586
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftparams.h203
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftpfr.h179
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftrender.h244
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftsizes.h159
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftsnames.h272
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftstroke.h773
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftsynth.h83
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftsystem.h352
-rw-r--r--Client/ThirdParty/freetype/include/freetype/fttrigon.h350
-rw-r--r--Client/ThirdParty/freetype/include/freetype/fttypes.h615
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ftwinfnt.h276
-rw-r--r--Client/ThirdParty/freetype/include/freetype/t1tables.h773
-rw-r--r--Client/ThirdParty/freetype/include/freetype/ttnameid.h1235
-rw-r--r--Client/ThirdParty/freetype/include/freetype/tttables.h855
-rw-r--r--Client/ThirdParty/freetype/include/freetype/tttags.h123
-rw-r--r--Client/ThirdParty/freetype/include/ft2build.h42
-rw-r--r--Client/ThirdParty/freetype/release dll/win32/freetype.dllbin0 -> 706048 bytes
-rw-r--r--Client/ThirdParty/freetype/release dll/win32/freetype.libbin0 -> 49486 bytes
-rw-r--r--Client/ThirdParty/freetype/release dll/win64/freetype.dllbin0 -> 868352 bytes
-rw-r--r--Client/ThirdParty/freetype/release dll/win64/freetype.libbin0 -> 48402 bytes
-rw-r--r--Client/ThirdParty/freetype/release static/README.TXT1
-rw-r--r--Client/ThirdParty/freetype/release static/vs2015-2019/win32/freetype.libbin0 -> 3689862 bytes
-rw-r--r--Client/ThirdParty/freetype/release static/vs2015-2019/win64/freetype.libbin0 -> 4124048 bytes
-rw-r--r--Client/ThirdParty/glad/glad.c1850
-rw-r--r--Client/ThirdParty/glad/glad.h3621
-rw-r--r--Client/ThirdParty/glad/khrplatform.h290
-rw-r--r--Client/ThirdParty/imgui/.editorconfig24
-rw-r--r--Client/ThirdParty/imgui/.gitattributes30
-rw-r--r--Client/ThirdParty/imgui/.github/FUNDING.yml1
-rw-r--r--Client/ThirdParty/imgui/.github/issue_template.md46
-rw-r--r--Client/ThirdParty/imgui/.github/pull_request_template.md6
-rw-r--r--Client/ThirdParty/imgui/.github/workflows/build.yml530
-rw-r--r--Client/ThirdParty/imgui/.github/workflows/scheduled.yml15
-rw-r--r--Client/ThirdParty/imgui/.github/workflows/static-analysis.yml77
-rw-r--r--Client/ThirdParty/imgui/.gitignore53
-rw-r--r--Client/ThirdParty/imgui/LICENSE.txt21
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_allegro5.cpp478
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_allegro5.h31
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_android.cpp187
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_android.h27
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx10.cpp578
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx10.h25
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx11.cpp594
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx11.h26
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx12.cpp746
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx12.h39
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx9.cpp378
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_dx9.h25
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_glfw.cpp454
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_glfw.h41
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_glut.cpp217
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_glut.h37
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_marmalade.cpp318
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_marmalade.h28
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_metal.h29
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_metal.mm556
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_opengl2.cpp285
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_opengl2.h32
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_opengl3.cpp778
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_opengl3.h55
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_opengl3_loader.h752
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_osx.h24
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_osx.mm387
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_sdl.cpp449
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_sdl.h35
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.cpp238
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.h27
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_vulkan.cpp1474
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_vulkan.h149
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_wgpu.cpp717
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_wgpu.h25
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_win32.cpp616
-rw-r--r--Client/ThirdParty/imgui/backends/imgui_impl_win32.h42
-rw-r--r--Client/ThirdParty/imgui/backends/vulkan/generate_spv.sh6
-rw-r--r--Client/ThirdParty/imgui/backends/vulkan/glsl_shader.frag14
-rw-r--r--Client/ThirdParty/imgui/backends/vulkan/glsl_shader.vert25
-rw-r--r--Client/ThirdParty/imgui/docs/BACKENDS.md142
-rw-r--r--Client/ThirdParty/imgui/docs/CHANGELOG.txt3338
-rw-r--r--Client/ThirdParty/imgui/docs/EXAMPLES.md246
-rw-r--r--Client/ThirdParty/imgui/docs/FAQ.md676
-rw-r--r--Client/ThirdParty/imgui/docs/FONTS.md397
-rw-r--r--Client/ThirdParty/imgui/docs/README.md243
-rw-r--r--Client/ThirdParty/imgui/docs/TODO.txt404
-rw-r--r--Client/ThirdParty/imgui/examples/README.txt9
-rw-r--r--Client/ThirdParty/imgui/examples/example_allegro5/README.md36
-rw-r--r--Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj180
-rw-r--r--Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj.filters58
-rw-r--r--Client/ThirdParty/imgui/examples/example_allegro5/imconfig_allegro5.h11
-rw-r--r--Client/ThirdParty/imgui/examples/example_allegro5/main.cpp144
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/CMakeLists.txt40
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/android/.gitignore12
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/build.gradle34
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml24
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/java/MainActivity.kt40
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/android/build.gradle24
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/android/settings.gradle1
-rw-r--r--Client/ThirdParty/imgui/examples/example_android_opengl3/main.cpp369
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/README.md10
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj499
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/iOS/Info-iOS.plist49
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/iOS/LaunchScreen.storyboard27
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/macOS/Info-macOS.plist30
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/macOS/MainMenu.storyboard93
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_metal/main.mm356
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_opengl2/example_apple_opengl2.xcodeproj/project.pbxproj328
-rw-r--r--Client/ThirdParty/imgui/examples/example_apple_opengl2/main.mm282
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_opengl3/Makefile91
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_opengl3/README.md26
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_opengl3/main.cpp174
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_opengl3/shell_minimal.html64
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_wgpu/Makefile88
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_wgpu/README.md24
-rw-r--r--Client/ThirdParty/imgui/examples/example_emscripten_wgpu/main.cpp245
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_metal/Makefile46
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_metal/main.mm172
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl2/Makefile81
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl2/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj181
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl2/main.cpp159
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl3/Makefile89
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl3/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj182
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj.filters64
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_opengl3/main.cpp172
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_vulkan/CMakeLists.txt43
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win32.bat14
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win64.bat13
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj181
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_glfw_vulkan/main.cpp558
-rw-r--r--Client/ThirdParty/imgui/examples/example_glut_opengl2/Makefile75
-rw-r--r--Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj181
-rw-r--r--Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_glut_opengl2/main.cpp155
-rw-r--r--Client/ThirdParty/imgui/examples/example_marmalade/data/app.icf32
-rw-r--r--Client/ThirdParty/imgui/examples/example_marmalade/main.cpp124
-rw-r--r--Client/ThirdParty/imgui/examples/example_marmalade/marmalade_example.mkb47
-rw-r--r--Client/ThirdParty/imgui/examples/example_null/Makefile92
-rw-r--r--Client/ThirdParty/imgui/examples/example_null/build_win32.bat3
-rw-r--r--Client/ThirdParty/imgui/examples/example_null/main.cpp37
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_directx11/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj182
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters60
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_directx11/main.cpp230
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_metal/Makefile47
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_metal/main.mm181
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl2/Makefile79
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl2/README.md29
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl2/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj181
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl2/main.cpp157
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl3/Makefile91
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl3/README.md29
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl3/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj182
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters64
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_opengl3/main.cpp178
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/Makefile79
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/README.md25
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj181
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/main.cpp161
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_vulkan/build_win32.bat10
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj181
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_sdl_vulkan/main.cpp559
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx10/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj171
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj.filters60
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx10/main.cpp242
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx11/build_win32.bat9
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj170
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters60
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx11/main.cpp246
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx12/build_win32.bat9
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj172
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj.filters57
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx12/main.cpp464
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx9/build_win32.bat8
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj171
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj.filters61
-rw-r--r--Client/ThirdParty/imgui/examples/example_win32_directx9/main.cpp236
-rw-r--r--Client/ThirdParty/imgui/examples/imgui_examples.sln88
-rw-r--r--Client/ThirdParty/imgui/examples/libs/glfw/COPYING.txt22
-rw-r--r--Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3.h4227
-rw-r--r--Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3native.h456
-rw-r--r--Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.libbin0 -> 187376 bytes
-rw-r--r--Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.libbin0 -> 291120 bytes
-rw-r--r--Client/ThirdParty/imgui/examples/libs/usynergy/README.txt8
-rw-r--r--Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.c636
-rw-r--r--Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.h420
-rw-r--r--Client/ThirdParty/imgui/imconfig.h123
-rw-r--r--Client/ThirdParty/imgui/imgui.cpp12388
-rw-r--r--Client/ThirdParty/imgui/imgui.h2916
-rw-r--r--Client/ThirdParty/imgui/imgui_demo.cpp7849
-rw-r--r--Client/ThirdParty/imgui/imgui_draw.cpp4179
-rw-r--r--Client/ThirdParty/imgui/imgui_internal.h2841
-rw-r--r--Client/ThirdParty/imgui/imgui_tables.cpp4049
-rw-r--r--Client/ThirdParty/imgui/imgui_widgets.cpp8247
-rw-r--r--Client/ThirdParty/imgui/imstb_rectpack.h639
-rw-r--r--Client/ThirdParty/imgui/imstb_textedit.h1449
-rw-r--r--Client/ThirdParty/imgui/imstb_truetype.h4903
-rw-r--r--Client/ThirdParty/imgui/misc/README.txt23
-rw-r--r--Client/ThirdParty/imgui/misc/cpp/README.txt13
-rw-r--r--Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.cpp76
-rw-r--r--Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.h22
-rw-r--r--Client/ThirdParty/imgui/misc/debuggers/README.txt16
-rw-r--r--Client/ThirdParty/imgui/misc/debuggers/imgui.gdb12
-rw-r--r--Client/ThirdParty/imgui/misc/debuggers/imgui.natstepfilter30
-rw-r--r--Client/ThirdParty/imgui/misc/debuggers/imgui.natvis58
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/Cousine-Regular.ttfbin0 -> 43912 bytes
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/DroidSans.ttfbin0 -> 190044 bytes
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/Karla-Regular.ttfbin0 -> 16848 bytes
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/ProggyClean.ttfbin0 -> 41208 bytes
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/ProggyTiny.ttfbin0 -> 35656 bytes
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/Roboto-Medium.ttfbin0 -> 162588 bytes
-rw-r--r--Client/ThirdParty/imgui/misc/fonts/binary_to_compressed_c.cpp385
-rw-r--r--Client/ThirdParty/imgui/misc/freetype/README.md37
-rw-r--r--Client/ThirdParty/imgui/misc/freetype/imgui_freetype.cpp779
-rw-r--r--Client/ThirdParty/imgui/misc/freetype/imgui_freetype.h50
-rw-r--r--Client/ThirdParty/imgui/misc/single_file/imgui_single_file.h18
-rw-r--r--Client/ThirdParty/json/json.hpp26750
-rw-r--r--Documents/设计/~$设计.xlsxbin0 -> 165 bytes
-rw-r--r--Documents/设计/设计.xlsxbin0 -> 8446381 bytes
1018 files changed, 391445 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.gitignore
diff --git a/Client/.gitignore b/Client/.gitignore
new file mode 100644
index 0000000..3c403b0
--- /dev/null
+++ b/Client/.gitignore
@@ -0,0 +1,8 @@
+/Build
+/Project/VisualStudio/Ragdolls/.vs
+/Project/VisualStudio/Ragdolls/x64
+/Project/VisualStudio/Ragdolls/*/x64
+/Project/VisualStudio/Ragdolls/*/CmakeFiles/
+/Project/VisualStudio/Ragdolls/Win32
+/Project/VisualStudio/Ragdolls/*/Win32
+.vs \ No newline at end of file
diff --git a/Client/Art/Avatar/test.pdn b/Client/Art/Avatar/test.pdn
new file mode 100644
index 0000000..d664792
--- /dev/null
+++ b/Client/Art/Avatar/test.pdn
Binary files differ
diff --git a/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj b/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj
new file mode 100644
index 0000000..37aad1b
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{C16CF3E1-0B6C-4166-A89C-846F7B28CA42}</ProjectGuid>
+ <RootNamespace>MeshBuilder</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.filters b/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.filters
new file mode 100644
index 0000000..3c6f4fd
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.filters
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="源文件">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="头文件">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+ </Filter>
+ <Filter Include="资源文件">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.user b/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/MeshBuilder/MeshBuilder.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ No newline at end of file
diff --git a/Client/Project/VisualStudio/Ragdolls/Ragdolls.sln b/Client/Project/VisualStudio/Ragdolls/Ragdolls.sln
new file mode 100644
index 0000000..2126b83
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/Ragdolls.sln
@@ -0,0 +1,48 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.1500
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{CCEAD487-2900-4EC3-BA6C-663849A5517E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{DA076690-8AD4-41EF-A512-A2883924E841}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshBuilder", "MeshBuilder\MeshBuilder.vcxproj", "{C16CF3E1-0B6C-4166-A89C-846F7B28CA42}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ragdolls", "Ragdolls\Ragdolls.vcxproj", "{2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Debug|x64.ActiveCfg = Debug|x64
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Debug|x64.Build.0 = Debug|x64
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Debug|x86.ActiveCfg = Debug|Win32
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Debug|x86.Build.0 = Debug|Win32
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Release|x64.ActiveCfg = Release|x64
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Release|x64.Build.0 = Release|x64
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Release|x86.ActiveCfg = Release|Win32
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42}.Release|x86.Build.0 = Release|Win32
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Debug|x64.ActiveCfg = Debug|x64
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Debug|x64.Build.0 = Debug|x64
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Debug|x86.ActiveCfg = Debug|Win32
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Debug|x86.Build.0 = Debug|Win32
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Release|x64.ActiveCfg = Release|x64
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Release|x64.Build.0 = Release|x64
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Release|x86.ActiveCfg = Release|Win32
+ {2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {C16CF3E1-0B6C-4166-A89C-846F7B28CA42} = {DA076690-8AD4-41EF-A512-A2883924E841}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4711990F-AE3C-42FE-8E31-1AB4861146E0}
+ EndGlobalSection
+EndGlobal
diff --git a/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj b/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj
new file mode 100644
index 0000000..0ad9b2c
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <VCProjectVersion>15.0</VCProjectVersion>
+ <ProjectGuid>{2F2534C8-5E6C-4F97-A0E6-17A523FD8AED}</ProjectGuid>
+ <RootNamespace>Ragdolls</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v141</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(SolutionDir)..\..\..\Build</OutDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(SolutionDir)..\..\..\Build</OutDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\ThirdParty;$(SolutionDir)..\..\..\ThirdParty\imgui;$(SolutionDir)..\..\..\ThirdParty\SDL2\include;$(SolutionDir)..\..\..\ThirdParty\freetype\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>RAGDOLL_WIN;_CRT_SECURE_NO_WARNINGS;RAGDOLL_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\ThirdParty\SDL2\lib\x64;$(SolutionDir)..\..\..\ThirdParty\freetype\release static\vs2015-2019\win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2main.lib;SDL2.lib;OpenGL32.lib;freetype.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <PreprocessorDefinitions>RAGDOLL_DEBUG;RAGDOLL_WIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <PreprocessorDefinitions>RAGDOLL_DEBUG;RAGDOLL_WIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <ConformanceMode>true</ConformanceMode>
+ <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\ThirdParty;$(SolutionDir)..\..\..\ThirdParty\imgui;$(SolutionDir)..\..\..\ThirdParty\SDL2\include;$(SolutionDir)..\..\..\ThirdParty\freetype\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>RAGDOLL_WIN;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\ThirdParty\SDL2\lib\x64;$(SolutionDir)..\..\..\ThirdParty\freetype\release static\vs2015-2019\win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2main.lib;SDL2.lib;OpenGL32.lib;freetype.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\Source\Common\DataBuffer.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Debug\Log.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\Color.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\CustomVertexLayout.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\DefaultVertexLayout.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\DynamicVertexBuffer.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\FrameBuffer.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\GfxDevice.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\GlyphAtlas.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\GPUDataBuffer.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\ImageData.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\OpenGL.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\Point.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\PolyLine.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\Quad.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\RenderCommands.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\RenderTexture.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\Shader.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\ShaderCompiler.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\Texture.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\VertexAttribute.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\VertexBuffer.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\Font.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\TextMeshGenerator.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\UI9Slicing.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\UILine.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\UIMesh.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\UIQuad.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\UISquare.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\UITextMesh.cpp" />
+ <ClCompile Include="..\..\..\..\Source\GUI\utf8.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Math\Functions.cpp" />
+ <ClCompile Include="..\..\..\..\Source\RagdollMain.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Threading\Job.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Threading\JobSystem.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Threading\Mutex.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Threading\Semaphore.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Threading\Thread.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Threading\WorkThread.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\glad\glad.c" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_opengl2.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_sdl.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_demo.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_draw.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_tables.cpp" />
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_widgets.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\Source\Common\DataBuffer.h" />
+ <ClInclude Include="..\..\..\..\Source\Debug\Log.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\Color.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\CustomVertexLayout.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\DefaultVertexLayout.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\DeviceDefine.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\DynamicMesh.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\DynamicVertexBuffer.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\FrameBuffer.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\GfxDevice.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\GlyphAtlas.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\GPUDataBuffer.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\ImageData.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\OpenGL.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\Point.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\PolyLine.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\Primitive.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\Quad.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\RenderCommands.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\RenderTexture.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\Shader.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\ShaderCompiler.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\Texture.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\VertexAttribute.h" />
+ <ClInclude Include="..\..\..\..\Source\Graphics\VertexBuffer.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\Font.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\freetype.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\TextMeshGenerator.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\UI9Slicing.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\UILine.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\UIMesh.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\UIQuad.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\UISquare.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\UITextMesh.h" />
+ <ClInclude Include="..\..\..\..\Source\GUI\utf8.h" />
+ <ClInclude Include="..\..\..\..\Source\Math\Functions.h" />
+ <ClInclude Include="..\..\..\..\Source\Math\Math.h" />
+ <ClInclude Include="..\..\..\..\Source\Math\Matrix22.h" />
+ <ClInclude Include="..\..\..\..\Source\Math\Matrix44.h" />
+ <ClInclude Include="..\..\..\..\Source\Math\Rect.h" />
+ <ClInclude Include="..\..\..\..\Source\Math\Vector2.hpp" />
+ <ClInclude Include="..\..\..\..\Source\Math\Vector3.hpp" />
+ <ClInclude Include="..\..\..\..\Source\Math\Vector4.hpp" />
+ <ClInclude Include="..\..\..\..\Source\Threading\Job.h" />
+ <ClInclude Include="..\..\..\..\Source\Threading\JobSystem.h" />
+ <ClInclude Include="..\..\..\..\Source\Threading\Mutex.h" />
+ <ClInclude Include="..\..\..\..\Source\Threading\Semaphore.h" />
+ <ClInclude Include="..\..\..\..\Source\Threading\Thread.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\Assert.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\AutoInvoke.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\Exception.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\Singleton.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\StaticInitiator.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\Type.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\UIDGenerator.h" />
+ <ClInclude Include="..\..\..\..\Source\Utilities\UtilMacros.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\glad\glad.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\glad\khrplatform.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_opengl2.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_sdl.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imconfig.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imgui.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imgui_internal.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imstb_rectpack.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imstb_textedit.h" />
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imstb_truetype.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.filters b/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.filters
new file mode 100644
index 0000000..52c6542
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.filters
@@ -0,0 +1,382 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="ThirdParty">
+ <UniqueIdentifier>{1f77a406-ef5a-499b-9ca8-d24663dbad62}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="ThirdParty\glad">
+ <UniqueIdentifier>{6b71c85a-273e-4337-b0df-9d736ef367bf}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="ThirdParty\imgui">
+ <UniqueIdentifier>{8645b107-8283-49b4-8433-d499800122d6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Graphics">
+ <UniqueIdentifier>{a5de18e0-e161-4ae6-bc2f-005636ec0903}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Input">
+ <UniqueIdentifier>{277eb251-3130-46f1-a047-4da6cddf5917}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="ThirdParty\lua51">
+ <UniqueIdentifier>{24b129f5-2de6-47e3-9f11-f1de0ee308a5}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Math">
+ <UniqueIdentifier>{aa992e90-3b5b-405d-b72a-8dda570502e8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="GUI">
+ <UniqueIdentifier>{1c125d38-ee4b-4e91-88dd-0116bbe704cb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Utilities">
+ <UniqueIdentifier>{0993b33f-0262-42a0-9481-dc5cce4945c6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Debug">
+ <UniqueIdentifier>{f5224050-f441-4f8a-807a-c63600ef81d7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Threading">
+ <UniqueIdentifier>{196504c3-0cb5-4ad9-8022-0c17d665a73b}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Common">
+ <UniqueIdentifier>{7ba5ea51-ff9a-4edb-a192-c40276aefa3e}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\..\..\ThirdParty\glad\glad.c">
+ <Filter>ThirdParty\glad</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_widgets.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_tables.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_draw.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui_demo.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\imgui.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_opengl2.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_sdl.cpp">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\RagdollMain.cpp" />
+ <ClCompile Include="..\..\..\..\Source\Graphics\Texture.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\Color.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\CustomVertexLayout.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\DefaultVertexLayout.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\DynamicVertexBuffer.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\FrameBuffer.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\GfxDevice.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\GlyphAtlas.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\GPUDataBuffer.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\ImageData.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\OpenGL.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\Point.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\PolyLine.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\RenderCommands.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\RenderTexture.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\Shader.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\ShaderCompiler.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\VertexAttribute.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\VertexBuffer.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Debug\Log.cpp">
+ <Filter>Debug</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Threading\Job.cpp">
+ <Filter>Threading</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Threading\JobSystem.cpp">
+ <Filter>Threading</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Threading\Mutex.cpp">
+ <Filter>Threading</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Threading\Semaphore.cpp">
+ <Filter>Threading</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Threading\Thread.cpp">
+ <Filter>Threading</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Threading\WorkThread.cpp">
+ <Filter>Threading</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\Font.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\TextMeshGenerator.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\UI9Slicing.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\UILine.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\UIMesh.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\UIQuad.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\UISquare.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\UITextMesh.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\GUI\utf8.cpp">
+ <Filter>GUI</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Common\DataBuffer.cpp">
+ <Filter>Common</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Math\Functions.cpp">
+ <Filter>Math</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\..\Source\Graphics\Quad.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\..\..\ThirdParty\glad\glad.h">
+ <Filter>ThirdParty\glad</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\glad\khrplatform.h">
+ <Filter>ThirdParty\glad</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imstb_truetype.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imstb_textedit.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imstb_rectpack.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imgui_internal.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imgui.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\imconfig.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_opengl2.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\ThirdParty\imgui\backends\imgui_impl_sdl.h">
+ <Filter>ThirdParty\imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\Texture.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Vector2.hpp">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Math.h">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Matrix44.h">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Matrix22.h">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\Color.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\CustomVertexLayout.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\DefaultVertexLayout.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\DeviceDefine.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\DynamicVertexBuffer.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\FrameBuffer.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\GfxDevice.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\GlyphAtlas.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\GPUDataBuffer.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\ImageData.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\OpenGL.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\Point.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\PolyLine.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\Primitive.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\RenderCommands.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\RenderTexture.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\Shader.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\ShaderCompiler.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\VertexAttribute.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\VertexBuffer.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\Assert.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\Type.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\UtilMacros.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Vector3.hpp">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Vector4.hpp">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\Singleton.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Debug\Log.h">
+ <Filter>Debug</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Threading\Job.h">
+ <Filter>Threading</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Threading\JobSystem.h">
+ <Filter>Threading</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Threading\Mutex.h">
+ <Filter>Threading</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Threading\Semaphore.h">
+ <Filter>Threading</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Threading\Thread.h">
+ <Filter>Threading</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Rect.h">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\UIDGenerator.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\Font.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\freetype.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\TextMeshGenerator.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\UI9Slicing.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\UILine.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\UIMesh.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\UIQuad.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\UISquare.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\UITextMesh.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\GUI\utf8.h">
+ <Filter>GUI</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Common\DataBuffer.h">
+ <Filter>Common</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Math\Functions.h">
+ <Filter>Math</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\DynamicMesh.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Graphics\Quad.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\StaticInitiator.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\Exception.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\..\Source\Utilities\AutoInvoke.h">
+ <Filter>Utilities</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.user b/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.user
new file mode 100644
index 0000000..be25078
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/Ragdolls/Ragdolls.vcxproj.user
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup />
+</Project> \ No newline at end of file
diff --git a/Client/Project/VisualStudio/Ragdolls/Ragdolls/imgui.ini b/Client/Project/VisualStudio/Ragdolls/Ragdolls/imgui.ini
new file mode 100644
index 0000000..cb3db17
--- /dev/null
+++ b/Client/Project/VisualStudio/Ragdolls/Ragdolls/imgui.ini
@@ -0,0 +1,34 @@
+[Window][Debug##Default]
+Pos=60,60
+Size=400,400
+Collapsed=0
+
+[Window][Hello, world!]
+Pos=69,248
+Size=399,197
+Collapsed=0
+
+[Window][Dear ImGui Demo]
+Pos=1154,114
+Size=531,795
+Collapsed=0
+
+[Table][0x49F8DCEA,3]
+RefScale=13
+Column 0 Weight=1.0000
+Column 1 Width=84
+Column 2 Width=126
+
+[Table][0xC9935533,3]
+Column 0 Weight=1.0000
+Column 1 Weight=1.0000
+Column 2 Weight=1.0000
+
+[Table][0x8DFA6E86,2]
+Column 0 Weight=1.0000
+Column 1 Weight=1.0000
+
+[Table][0xFABAAEF7,2]
+Column 0 Weight=1.0000
+Column 1 Weight=1.0000
+
diff --git a/Client/Source/Common/DataBuffer.cpp b/Client/Source/Common/DataBuffer.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Common/DataBuffer.cpp
diff --git a/Client/Source/Common/DataBuffer.h b/Client/Source/Common/DataBuffer.h
new file mode 100644
index 0000000..02bfc2b
--- /dev/null
+++ b/Client/Source/Common/DataBuffer.h
@@ -0,0 +1,29 @@
+#pragma once
+
+enum EDataBufferType
+{
+ DataBufferMode_Binary, // \0β\0
+ DataBufferMode_Text, // \0β\0
+};
+
+// ڴ󣬻Ϊ
+// 1. ̶߳ȡļķ
+class DataBuffer
+{
+public:
+ DataBuffer()
+ {}
+ ~DataBuffer()
+ {
+ delete data;
+ }
+
+ union {
+ char* data;
+ unsigned char* udata;
+ char* sdata;
+ };
+ int length;
+ EDataBufferType type;
+
+}; \ No newline at end of file
diff --git a/Client/Source/Debug/Log.cpp b/Client/Source/Debug/Log.cpp
new file mode 100644
index 0000000..1b0ddf4
--- /dev/null
+++ b/Client/Source/Debug/Log.cpp
@@ -0,0 +1,164 @@
+#include "../Threading/Mutex.h"
+#include "log.h"
+#include <iostream>
+#include <ctime>
+#include <unordered_set>
+#include <stdarg.h>
+
+using namespace std;
+
+#ifdef RAGDOLL_WIN
+#include <windows.h>
+static HANDLE s_ConsoleHandle = 0;
+#endif
+
+unordered_set<string> s_OpenTags;
+
+Mutex s_Mutex;
+
+#ifdef RAGDOLL_DEBUG
+// https://stackoverflow.com/questions/997946/how-to-get-current-time-and-date-in-c
+// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
+const std::string currentDateTime() {
+ time_t now = time(0);
+ struct tm tstruct;
+ char buf[80];
+ tstruct = *localtime(&now);
+ // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
+ // for more information about date/time format
+ strftime(buf, sizeof(buf), "%Y-%m-%d %X", &tstruct);
+
+ return buf;
+}
+
+static void SetOutputColor(int i) {
+ if (s_ConsoleHandle == 0) {
+ s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ }
+ if (i == 0) {
+ SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ }
+ else if(i == 1) {
+ SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+ }
+ else {
+ SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_INTENSITY);
+ }
+}
+
+void log_error_null_param(const char* funcName, const char* param)
+{
+ log_error("Null parameter in %s called %s", funcName, param);
+}
+
+void log_open_tag(const char* tag)
+{
+ s_OpenTags.insert(tag);
+}
+
+void log_info(const char* fmt, ...)
+{
+ Lock(s_Mutex) {
+ SetOutputColor(0);
+ va_list pArgs = NULL;
+ va_start(pArgs, fmt);
+ printf("%s [Info] ", currentDateTime().c_str());
+ vprintf(fmt, pArgs);
+ printf("\n");
+ va_end(pArgs);
+ }
+}
+
+void log_warning(const char* fmt, ...)
+{
+ Lock(s_Mutex) {
+ SetOutputColor(1);
+ va_list pArgs = NULL;
+ va_start(pArgs, fmt);
+ printf("%s [Warning] ", currentDateTime().c_str());
+ vprintf(fmt, pArgs);
+ printf("\n");
+ va_end(pArgs);
+ }
+}
+
+void log_error(const char* fmt, ...)
+{
+ Lock(s_Mutex) {
+ SetOutputColor(2);
+ va_list pArgs = NULL;
+ va_start(pArgs, fmt);
+ printf("%s [Error] ", currentDateTime().c_str());
+ vprintf(fmt, pArgs);
+ printf("\n");
+ va_end(pArgs);
+ }
+}
+
+#define CHECK_TAG(tag)\
+if (s_OpenTags.count(tag) == 0)\
+ return;
+
+void log_info_tag(const char* tag, const char* fmt, ...)
+{
+ CHECK_TAG(tag);
+
+ Lock(s_Mutex) {
+ SetOutputColor(0);
+ va_list pArgs = NULL;
+ va_start(pArgs, fmt);
+ printf("%s [Info] [%s] ", currentDateTime().c_str(), tag);
+ vprintf(fmt, pArgs);
+ printf("\n");
+ va_end(pArgs);
+ }
+}
+
+void log_warning_tag(const char* tag, const char* fmt, ...)
+{
+ CHECK_TAG(tag);
+
+ Lock(s_Mutex) {
+ SetOutputColor(1);
+ va_list pArgs = NULL;
+ va_start(pArgs, fmt);
+ printf("%s [Warning] [%s] ", currentDateTime().c_str(), tag);
+ vprintf(fmt, pArgs);
+ printf("\n");
+ va_end(pArgs);
+ }
+}
+
+void log_error_tag(const char* tag, const char* fmt, ...)
+{
+ CHECK_TAG(tag);
+
+ Lock(s_Mutex) {
+ SetOutputColor(2);
+ va_list pArgs = NULL;
+ va_start(pArgs, fmt);
+ printf("%s [Error] [%s] ", currentDateTime().c_str(), tag);
+ vprintf(fmt, pArgs);
+ printf("\n");
+ va_end(pArgs);
+ }
+}
+
+#else
+void log_open_tag(std::string tag) {}
+void log_info(std::string log) {}
+void log_warning(std::string log){}
+void log_error(std::string log){}
+void log_error_null_param(std::string funcName, std::string param){}
+void log_info(string tag, std::string log) {}
+void log_warning(string tag, std::string log) {}
+void log_error(string tag, std::string log) {}
+
+void log_open_tag(const char* tag) {}
+void log_info(const char* log, ...) {}
+void log_warning(const char* log, ...) {}
+void log_error(const char* log, ...) {}
+void log_info(const char* tag, const char* log, ...) {}
+void log_warning(const char* tag, const char* log, ...) {}
+void log_error(const char* tag, const char* log, ...) {}
+#endif \ No newline at end of file
diff --git a/Client/Source/Debug/Log.h b/Client/Source/Debug/Log.h
new file mode 100644
index 0000000..8547102
--- /dev/null
+++ b/Client/Source/Debug/Log.h
@@ -0,0 +1,14 @@
+#pragma once
+#include <string>
+
+void log_open_tag(const char* tag);
+
+void log_info(const char* fmt, ...);
+void log_warning(const char* fmt, ...);
+void log_error(const char* fmt, ...);
+
+void log_error_null_param(const char* funcName, const char* param);
+
+void log_info_tag(const char* tag, const char* fmt, ...);
+void log_warning_tag(const char* tag, const char* fmt, ...);
+void log_error_tag(const char* tag, const char* fmt, ...);
diff --git a/Client/Source/GUI/Font.cpp b/Client/Source/GUI/Font.cpp
new file mode 100644
index 0000000..1efe551
--- /dev/null
+++ b/Client/Source/GUI/Font.cpp
@@ -0,0 +1,302 @@
+#include "freetype.h"
+#include "Font.h"
+
+#include "../Math/Functions.h"
+#include "../Math/Math.h"
+#include "../Debug/Log.h"
+#include "../Utilities/Assert.h"
+#include "../Graphics/ImageData.h"
+
+using namespace character;
+
+/*
+* http://madig.github.io/freetype-web/documentation/tutorial/
+* https://unicode-table.com/en/#cjk-unified-ideographs-extension-a
+* https://learnopengl.com/In-Practice/Text-Rendering
+* https://www.zhihu.com/question/294660079
+* https://baike.baidu.com/item/%E5%9F%BA%E6%9C%AC%E5%A4%9A%E6%96%87%E7%A7%8D%E5%B9%B3%E9%9D%A2/10788078
+* https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme
+*/
+
+static std::string s_FontError;
+
+static std::vector<unsigned char> s_PixelBuffer;
+static const int s_SizePerPixel = sizeof(unsigned char);
+
+Font::Font(std::string path, TextGeneratingSettings settings)
+ : m_Characters()
+{
+ m_AtlasMargin = settings.margin;
+ m_GlyphPadding = settings.padding;
+ m_AtlasSize = settings.atlasSize;
+
+ if (FT_Init_FreeType(&m_FTLibrary))
+ {
+ s_FontError = "Init freetype error. Font path " + path;
+ throw FontException(s_FontError.c_str());
+ }
+
+ if (FT_New_Face(m_FTLibrary, path.c_str(), 0, &m_FTFace))
+ {
+ s_FontError = "Create freetype face error. Font path " + path;
+ throw FontException(s_FontError.c_str());
+ }
+}
+
+Font::Font(DataBuffer* db, TextGeneratingSettings settings)
+ : m_Characters()
+{
+ m_AtlasMargin = settings.margin;
+ m_GlyphPadding = settings.padding;
+ m_AtlasSize = settings.atlasSize;
+
+ if (FT_Init_FreeType(&m_FTLibrary))
+ {
+ s_FontError = "Init freetype error.";
+ throw FontException(s_FontError.c_str());
+ }
+
+ if (FT_New_Memory_Face(m_FTLibrary, db->udata, db->length, 0, &m_FTFace))
+ {
+ s_FontError = "Create freetype face error.";
+ throw FontException(s_FontError.c_str());
+ }
+}
+
+character::Hash Font::GetHash(Unicode codepoint, int pixelSize)
+{
+ character::Hash hash;
+ hash.codepoint = codepoint;
+ hash.size = pixelSize;
+ return hash;
+}
+
+const Character* Font::GetCharacter(character::Unicode codepoint, int pixelSize)
+{
+ character::Hash hash = GetHash(codepoint, pixelSize);
+ auto iter = m_Characters.find(hash.hashCode);
+ if (iter == m_Characters.end())
+ {
+ if (RenderCharacter(codepoint, pixelSize))
+ {
+ iter = m_Characters.find(hash.hashCode);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ Assert(iter != m_Characters.end());
+ return &iter->second;
+}
+
+void Font::RenderCharacters(character::Unicode* codepoint, int n, int pixelSize)
+{
+ for (int i = 0; i < n; ++i)
+ {
+ RenderCharacter(codepoint[i], pixelSize);
+ }
+}
+
+void Font::RenderCharacters(std::vector<character::Unicode>& codepoint, int pixelSize)
+{
+ int n = codepoint.size();
+ for (int i = 0; i < n; ++i)
+ {
+ RenderCharacter(codepoint[i], pixelSize);
+ }
+}
+
+bool Font::RenderCharacter(character::Unicode codepoint, int pixelSize)
+{
+ character::Hash hash = GetHash(codepoint, pixelSize);
+ if (m_Characters.size() > 0 && m_Characters.count(hash.hashCode) != 0)
+ return true;
+ FT_Set_Pixel_Sizes(m_FTFace, 0, pixelSize);
+
+ // bug: ʱȾĽFT_PIXEL_MODE_MONO1-bits)ԹͬflagsϻDzԣֶתΪ8-bits
+
+ FT_Int32 flags = FT_LOAD_RENDER;
+ if (FT_Load_Char(m_FTFace, codepoint, flags))
+ return false;
+
+ Character character;
+
+ int w = m_FTFace->glyph->bitmap.width;
+ int h = m_FTFace->glyph->bitmap.rows;
+
+ const unsigned char* pixels = m_FTFace->glyph->bitmap.buffer;
+ if (pixels != NULL) // Щspacetabûε
+ {
+ s_PixelBuffer.resize(w * h);
+ if (m_FTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
+ {
+ // 1-bit monochrome
+ int pitch = m_FTFace->glyph->bitmap.pitch;
+ for (int y = 0; y < h; ++y)
+ {
+ for (int x = 0; x < w; ++x)
+ {
+ int index = x + y * w;
+ s_PixelBuffer[index] = ((pixels[pitch * y + x / 8]) & (1 << (7 - x % 8))) ? 255 : 0;
+ }
+ }
+ }
+ else if (m_FTFace->glyph->bitmap.pixel_mode)
+ {
+ // 8-bit grayscale
+ memcpy(&s_PixelBuffer[0], pixels, s_SizePerPixel * w * h);
+ }
+
+ //TextHelper::print_glyph(&s_PixelBuffer[0], w, h);
+
+ GlyphAtals* atlas = RequestAtlas(pixelSize, Vector2f(w, h));
+ Assert(atlas);
+
+ Rect rect = GetRenderChartAndMove(atlas, Vector2f(w, h));
+
+ try
+ {
+ atlas->altas->UpdateSubImage(rect, EPixelFormat::PixelFormat_R, EPixelElementType::PixelType_UNSIGNED_BYTE, &s_PixelBuffer[0]);
+ }
+ catch (TextureException& e)
+ {
+ s_PixelBuffer.clear();
+ std::string error = e.what();
+ error = "Render Character Error: " + error;
+ log_error(e.what());
+ return false;
+ }
+ s_PixelBuffer.clear();
+
+ character.atlas = atlas->index;
+ character.position = rect;
+ character.bearing = Vector2f(m_FTFace->glyph->bitmap_left, m_FTFace->glyph->bitmap_top);
+ }
+ else // spacetab
+ {
+ character.atlas = FONT_NOT_IN_ATLAS_PLACEHOLDER;
+ character.position = Rect(0,0,0,0);
+ character.bearing = Vector2f(0, 0);
+ }
+
+ character.advance = m_FTFace->glyph->advance.x * 1/64.f;
+
+ m_Characters.insert(std::pair<unsigned int, Character>(hash.hashCode, character));
+
+ return true;
+}
+
+const GlyphAtals* Font::GetGlyphAtlas(int index)
+{
+ if (index >= m_Atlases.size())
+ return NULL;
+ return &m_Atlases[index];
+}
+
+Rect Font::GetRenderChartAndMove(GlyphAtals* atlas, Vector2f preferSize)
+{
+ Rect rect;
+ Vector2f space;
+ space.x = atlas->width - atlas->cursor.x - m_AtlasMargin;
+ space.y = atlas->height - atlas->cursor.y - m_AtlasMargin;
+ if (space.x > preferSize.x && space.y > preferSize.y)
+ {
+ rect.x = atlas->cursor.x;
+ rect.y = atlas->cursor.y;
+ rect.width = preferSize.x;
+ rect.height = preferSize.y;
+ atlas->cursor.x += rect.width + m_GlyphPadding;
+ atlas->rowHeight = MathUtils::Max((float)atlas->rowHeight, preferSize.y);
+ }
+ else if (space.y - atlas->rowHeight - m_GlyphPadding - m_AtlasMargin > preferSize.y)
+ {
+ rect.x = m_AtlasMargin;
+ rect.y = atlas->cursor.y + m_GlyphPadding + atlas->rowHeight;
+ rect.width = preferSize.x;
+ rect.height = preferSize.y;
+ atlas->cursor.x = m_AtlasMargin;
+ atlas->cursor.y += atlas->rowHeight + m_GlyphPadding;
+ atlas->rowHeight = rect.height;
+ }
+ else
+ {
+ Assert(false);
+ }
+ return rect;
+}
+
+GlyphAtals* Font::RequestAtlas(int pixelSize, Vector2f preferSize)
+{
+ GlyphAtals* atlas = NULL;
+ auto iter = m_AtlasCache.find(pixelSize);
+ if (iter == m_AtlasCache.end() || !HasEnoughSpace(iter->second, preferSize))
+ {
+ Assert(m_Atlases.size() < FONT_NOT_IN_ATLAS_PLACEHOLDER);
+
+ Texture* tex = CreateAtlas();
+ GlyphAtals newAtlas = GlyphAtals();
+ newAtlas.altas = tex;
+ newAtlas.width = m_AtlasSize.x;
+ newAtlas.height = m_AtlasSize.y;
+ newAtlas.index = m_Atlases.size();
+ newAtlas.cursor = Vector2f(m_AtlasMargin, m_AtlasMargin);
+
+ m_Atlases.push_back(newAtlas);
+ atlas = &m_Atlases[m_Atlases.size() - 1];
+
+ if (iter != m_AtlasCache.end())
+ m_AtlasCache.erase(pixelSize);
+ m_AtlasCache.insert(std::pair<int, GlyphAtals*>(pixelSize, atlas));
+ }
+ else
+ {
+ atlas = iter->second;
+ }
+ Assert(atlas);
+ return atlas;
+}
+
+Texture* Font::CreateAtlas()
+{
+ TextureSetting setting;
+ setting.filterMode = ETextureFilterMode::Nearest;
+ setting.wrapMode = ETextureWrapMode::Clamp;
+ setting.format = ETextureFormat::R8;
+ setting.type = ETextureType::TEX_2D;
+ setting.keepImageData = false;
+ Texture* tex = new Texture(setting, m_AtlasSize.x, m_AtlasSize.y);
+ return tex;
+}
+
+bool Font::HasEnoughSpace(GlyphAtals* atlas, Vector2f preferSize)
+{
+ if (atlas == NULL)
+ return false;
+ Vector2f space;
+ space.x = atlas->width - atlas->cursor.x - m_AtlasMargin;
+ space.y = atlas->height - atlas->cursor.y - m_AtlasMargin;
+ if (space.x > preferSize.x && space.y > preferSize.y)
+ return true;
+ if (space.y - atlas->rowHeight - m_GlyphPadding - m_AtlasMargin > preferSize.y)
+ return true;
+ return false;
+}
+
+Character GetCharacter(character::Unicode Unicode, int pixelSize)
+{
+ return Character();
+}
+
+void TextHelper::print_glyph(unsigned char* glyph, int width, int height)
+{
+ for (int r = 0; r < height; ++r)
+ {
+ for (int c = 0; c < width; ++c)
+ {
+ unsigned char ch = glyph[c + r * width];
+ printf("%c", ch == 0 ? ' ' : '+');
+ }
+ printf("\n");
+ }
+}
diff --git a/Client/Source/GUI/Font.h b/Client/Source/GUI/Font.h
new file mode 100644
index 0000000..6fd3c19
--- /dev/null
+++ b/Client/Source/GUI/Font.h
@@ -0,0 +1,149 @@
+#pragma once
+
+#include "../Utilities/Singleton.h"
+#include "../Graphics/Texture.h"
+#include "../Common/DataBuffer.h"
+#include "../Math/Math.h"
+
+#include "freetype.h"
+
+#include <string>
+#include <unordered_map>
+#include <exception>
+#include <vector>
+
+//https://github.com/kaienfr/Font
+
+struct Character {
+ unsigned int atlas; // atlas
+ Rect position; // altasλãϽΪԭģGLY
+ Vector2f bearing; // Ͻԭƫ
+ unsigned int advance; // ܿ˼
+};
+
+namespace character
+{
+#if GAMELAB_WIN
+ typedef unsigned short Unicode; // unicode codepointBMPU+0000U+FFFF)
+#else
+ typedef unsigned int Unicode; // unicode codepointBMPU+0000U+FFFF)
+#endif
+
+#pragma pack(1)
+ union Hash {
+ unsigned int hashCode;
+ struct {
+ Unicode codepoint;
+ unsigned short size;//С
+ };
+#pragma pack(pop)
+
+ bool operator==(const Hash &other) const
+ {
+ return codepoint == other.codepoint && size == other.size;
+ }
+ };
+}
+
+struct UnicodeString
+{
+ character::Unicode* str;
+ int length;
+};
+
+namespace std
+{
+ template <>
+ struct hash<character::Hash>
+ {
+ std::size_t operator()(const character::Hash& k) const
+ {
+ return k.hashCode;
+ }
+ };
+}
+
+struct GlyphAtals
+{
+ int index;
+ Texture* altas; // ͼ
+ int width, height; // ߴ
+
+ Vector2f cursor; // α꣬Ͻǣ0,0ʼ
+ int rowHeight; // ǰеĸ߶
+};
+
+struct TextGeneratingSettings
+{
+ Vector2f atlasSize; // atlasijߴ
+ int margin; // atlası߽
+ int padding; // glyph໥֮ļֹ࣬ʱԽ
+};
+
+class FontException : public std::exception
+{
+public:
+ FontException(const char* what)
+ : std::exception(what)
+ {
+ }
+};
+
+enum EEncoding
+{
+ Encoding_ASCII,
+ Encoding_UTF8,
+ Encoding_UTF16,
+};
+
+// ûΣadvance֣spacetab
+#define FONT_NOT_IN_ATLAS_PLACEHOLDER (INT_MAX)
+
+//
+class Font
+{
+public:
+ Font(std::string path, TextGeneratingSettings setting)/*throw FontException*/;
+ Font(DataBuffer* db, TextGeneratingSettings setting)/*throw FontException*/;
+
+ const Character* GetCharacter(character::Unicode codepoint, int pixelSize);
+ const GlyphAtals* GetGlyphAtlas(int index);
+
+ // pre-bake
+ bool RenderCharacter(character::Unicode codepoint, int pixelSize);
+ void RenderCharacters(character::Unicode* codepoint, int n, int pixelSize);
+ void RenderCharacters(std::vector<character::Unicode>& codepoint, int pixelSize);
+
+ GET(Vector2f, AtlasSize, m_AtlasSize);
+
+private:
+ Texture* CreateAtlas();
+ GlyphAtals* RequestAtlas(int pixelSize, Vector2f preferSize);
+ Rect GetRenderChartAndMove(GlyphAtals* atlas, Vector2f preferSize);
+ bool HasEnoughSpace(GlyphAtals* atlas, Vector2f preferSize);
+ character::Hash GetHash(character::Unicode Unicode, int pixelSize);
+
+ //-------------------------------------------------------------------------
+
+ std::unordered_map<unsigned int , Character> m_Characters; // Ⱦ
+
+ std::vector<GlyphAtals> m_Atlases; // ǰеatlasfontȫӵȨlightuserdata
+ std::unordered_map<int/*pixelSize*/, GlyphAtals*> m_AtlasCache; // ҵõatlas
+
+ bool m_IsEnabled;
+
+ Vector2f m_AtlasSize;
+ int m_AtlasMargin;
+ int m_GlyphPadding;
+
+ FT_Library m_FTLibrary;
+ FT_Face m_FTFace;
+
+};
+
+namespace TextHelper
+{
+
+ void print_glyph(unsigned char* glyph, int width, int height);
+
+}
diff --git a/Client/Source/GUI/TextMeshGenerator.cpp b/Client/Source/GUI/TextMeshGenerator.cpp
new file mode 100644
index 0000000..766a9b0
--- /dev/null
+++ b/Client/Source/GUI/TextMeshGenerator.cpp
@@ -0,0 +1,89 @@
+#include "TextMeshGenerator.h"
+
+// һϣֵ
+static uint32_t GetStrHash(const UnicodeString& str)
+{
+ if (str.length == 0)
+ return 0;
+
+ int len = str.length;
+ uint32_t hash = (uint32_t)len; // seed
+ size_t step = (len >> 5) + 1;
+ for (int l = len; l >= step; l -= step)
+ {
+ unsigned short unicode = str.str[l - 1];
+ unsigned char hicode = *((unsigned char*)&unicode);
+ unsigned char locode = *(((unsigned char*)&unicode) + 1);
+ hash = hash ^ ((hash << 5) + (hash >> 2) + hicode + locode);
+ }
+ return hash;
+}
+
+const UITextMesh* TextMeshGenerator::GetTextMesh(
+ const UnicodeString& str
+ , Font* font
+ , int pixelSize
+ , int lineHeight
+ , Color32 col32
+ , ETextAnchor anchor
+ , ETextAlignment alignment
+ , bool wordwrap
+ , float preferred
+){
+ uint32_t hash = GetStrHash(str);
+ UITextMeshList* tm = NULL;
+ bool hasHash = m_TextMeshes.count(hash);
+ if (hasHash)
+ {
+ tm = m_TextMeshes[hash];
+ while (tm)
+ {
+ UITextMesh* mesh = tm->mesh;
+ if (mesh->GetFont() != font
+ || mesh->GetPixelSize() != pixelSize
+ || mesh->GetLineHeight() != lineHeight
+ || mesh->GetAnchor() != anchor
+ || mesh->GetAlignment() != alignment
+ || mesh->GetWordwrap() != wordwrap
+ || mesh->GetPreferred() != preferred
+ || mesh->GetColor() != col32
+ ){
+ tm = tm->next;
+ continue;
+ }
+ const UnicodeString& content = mesh->GetContent();
+ if (content.length != str.length)
+ {
+ tm = tm->next;
+ continue;
+ }
+ if (memcmp(str.str, content.str, sizeof(character::Unicode) * str.length) == 0)
+ {
+ return tm->mesh;
+ }
+ tm = tm->next;
+ }
+ }
+ tm = new UITextMeshList();
+ try {
+ tm->mesh = new UITextMesh(str, font, pixelSize, lineHeight, col32, anchor, alignment, wordwrap, preferred);
+ log_info("Text", "New UITextMesh");
+ }
+ catch(TextMeshException& e)
+ {
+ delete tm;
+ throw;
+ }
+ if (hasHash)
+ {
+ UITextMeshList* list = m_TextMeshes[hash];
+ tm->next = list;
+ m_TextMeshes[hash] = tm;
+ }
+ else
+ {
+ tm->next = NULL;
+ m_TextMeshes.insert(std::pair<uint32_t, UITextMeshList*>(hash, tm));
+ }
+ return tm->mesh;
+}
diff --git a/Client/Source/GUI/TextMeshGenerator.h b/Client/Source/GUI/TextMeshGenerator.h
new file mode 100644
index 0000000..acc0a0a
--- /dev/null
+++ b/Client/Source/GUI/TextMeshGenerator.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <vector>
+#include <unordered_map>
+
+#include "../Debug/Log.h"
+#include "../Graphics/Color.h"
+
+#include "UITextMesh.h"
+#include "Font.h"
+
+// 𲽻ճûõtextmesh
+class GraduallyReleaseTextMesh
+{
+};
+
+struct UITextMeshList {
+ UITextMesh* mesh;
+ UITextMeshList* next;
+};
+
+class TextMeshGenerator : public Singleton<TextMeshGenerator>
+{
+public:
+ const UITextMesh* GetTextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 col32, ETextAnchor anchor, ETextAlignment alignment, bool wordwrap, float preferred);
+
+private:
+ std::unordered_map<uint32_t, UITextMeshList*> m_TextMeshes;
+};
+
+#define g_TextMeshGenerator (*TextMeshGenerator::Instance()) \ No newline at end of file
diff --git a/Client/Source/GUI/UI9Slicing.cpp b/Client/Source/GUI/UI9Slicing.cpp
new file mode 100644
index 0000000..c0d8f60
--- /dev/null
+++ b/Client/Source/GUI/UI9Slicing.cpp
@@ -0,0 +1,112 @@
+#include "../Math/Math.h"
+
+#include "UI9Slicing.h"
+
+#include <cstring>
+#include <vector>
+
+using namespace std;
+
+static vector<UIVertexLayout> s_Vertices;
+static vector<UIIndex> s_Indices;
+
+UI9Slicing::UI9Slicing(int mode, Vector2f horizontal, Vector2f vertical, Vector2f texPixelSize, Vector2f size)
+{
+ m_Slicing = mode;
+ m_Horizontal = horizontal.Clamp(0, texPixelSize.x, 0, texPixelSize.x);
+ m_Vertical = vertical.Clamp(0, texPixelSize.y, 0, texPixelSize.y);
+
+ if (m_Horizontal[0] + m_Horizontal[1] > texPixelSize.x || m_Vertical[0] + m_Vertical[1] > texPixelSize.y)
+ {
+ throw UIMeshException("UI9Slicing wrong parameter.");
+ }
+ m_TexSize = texPixelSize;
+ m_Size = size;
+}
+
+void UI9Slicing::Draw()
+{
+ s_Indices.clear();
+ s_Vertices.clear();
+
+ Vector2f tileSize = Vector2f(m_TexSize.x - m_Horizontal[0] - m_Horizontal[1], m_TexSize.y - m_Vertical[0] - m_Vertical[1]);
+ Vector2f fillSize = Vector2f(m_Size.x - m_Horizontal[0] - m_Horizontal[1], m_Size.y - m_Vertical[0] - m_Vertical[1]);
+ // horizonalverticalӦuvעuv½ǣmeshϽ
+ Vector2f tileUVx = Vector2f(m_Horizontal[0] / m_TexSize.x, (m_TexSize.x - m_Horizontal[1]) / m_TexSize.x);
+ Vector2f tileUVy = Vector2f((m_TexSize.y - m_Vertical[0]) / m_TexSize.y, m_Vertical[1] / m_TexSize.y);
+
+ // fill vertices
+ int row = 2 + ((fillSize.y <= 0) ? 0 : (m_Slicing == Slicing_Simple ? 2 : ceilf((float)fillSize.y / tileSize.y) + 1));
+ int colum = 2 + ((fillSize.x <= 0) ? 0 : (m_Slicing == Slicing_Simple ? 2 : ceilf((float)fillSize.x / tileSize.x) + 1));
+
+ for (int r = 0; r < row; ++r)
+ {
+ UIVertexLayout vert;
+ vert.color = Color32::white;
+ if (r == 0)
+ {
+ vert.position.y = 0;
+ vert.uv.y = 1;
+ }
+ else if (r == row - 1)
+ {
+ vert.position.y = m_Size.y;
+ vert.uv.y = 0;
+ }
+ else {
+ if (m_Slicing == Slicing_Tiled) {
+ vert.position.y = clamp(m_Vertical[0] + (r - 1) * tileSize.y, m_Vertical[0], m_Size.y - m_Vertical[1]);
+ vert.uv.y = odd(r - 1) ? tileUVy[1] : tileUVy[0];
+ } else {
+ vert.position.y = odd(r - 1) ? m_Size.y - m_Vertical[1] : m_Vertical[0];
+ vert.uv.y = odd(r - 1) ? tileUVy[1] : tileUVy[0];
+ }
+ }
+ for (int c = 0; c < colum; ++c)
+ {
+ if (c == 0)
+ {
+ vert.position.x = 0;
+ vert.uv.x = 0;
+ }
+ else if (c == colum - 1)
+ {
+ vert.position.x = m_Size.x;
+ vert.uv.x = 1;
+ }
+ else {
+ if (m_Slicing == Slicing_Tiled) {
+ vert.position.x = clamp(m_Horizontal[0] + (c - 1) * tileSize.x, m_Horizontal[0], m_Size.x - m_Horizontal[0]);
+ vert.uv.x = odd(c - 1) ? tileUVx[1] : tileUVx[0];
+ } else {
+ vert.position.x = odd(c - 1) ? (m_Size.x - m_Horizontal[1]) : m_Horizontal[0];
+ vert.uv.x = odd(c - 1) ? tileUVx[1] : tileUVx[0];
+ }
+ }
+ s_Vertices.push_back(vert);
+
+ if (c < colum - 1 && r < row - 1) {
+ int index = c + r * colum;
+ s_Indices.push_back(index); s_Indices.push_back(index + colum); s_Indices.push_back(index + colum + 1);
+ s_Indices.push_back(index + colum + 1); s_Indices.push_back(index + 1); s_Indices.push_back(index);
+ }
+ }
+ }
+
+ void* vb;
+ void* ib;
+
+ int vertCount = s_Vertices.size();
+ int indicesCount = s_Indices.size();
+
+ g_SharedVBO.GetChunk(sizeof(UIVertexLayout), sizeof(UIIndex), vertCount, indicesCount, Primitive_Triangle, &vb, &ib);
+
+ memcpy(vb, &s_Vertices[0], vertCount * sizeof(UIVertexLayout));
+ memcpy(ib, &s_Indices[0], indicesCount* sizeof(UIIndex));
+
+ s_Indices.resize(0);
+ s_Vertices.resize(0);
+
+ g_SharedVBO.ReleaseChunk(vertCount, indicesCount);
+ g_SharedVBO.DrawChunk(s_UIVertexLayout);
+} \ No newline at end of file
diff --git a/Client/Source/GUI/UI9Slicing.h b/Client/Source/GUI/UI9Slicing.h
new file mode 100644
index 0000000..6a37447
--- /dev/null
+++ b/Client/Source/GUI/UI9Slicing.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "UIMesh.h"
+
+enum ESlicing
+{
+ Slicing_Simple,
+ Slicing_Tiled,
+};
+
+// Ź
+class UI9Slicing : public UIMesh
+{
+public:
+ UI9Slicing(int mode, Vector2f horizontal, Vector2f vertical, Vector2f texPixelSize, Vector2f size)/*throw UIMeshException*/;
+
+ void Draw() override;
+
+private:
+ int m_Slicing;
+ Vector2f m_Horizontal; // иߵߺұߵľ
+ Vector2f m_Vertical; // иߵµľ
+ Vector2f m_TexSize;
+ Vector2f m_Size;
+};
diff --git a/Client/Source/GUI/UILine.cpp b/Client/Source/GUI/UILine.cpp
new file mode 100644
index 0000000..8aa8c1d
--- /dev/null
+++ b/Client/Source/GUI/UILine.cpp
@@ -0,0 +1,48 @@
+#include "UILine.h"
+
+struct UILineLayout
+{
+ Vector2f position;
+};
+
+static CustomVertexLayout layout;
+
+InitializeStaticVariables([]() {
+ VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(UILineLayout));
+
+ layout.attributes.push_back(POSITION);
+});
+
+void UILine::Draw()
+{
+ const int nVerts = 2;
+ const int nIndices = 2;
+
+ float pos[] = {
+ m_From.x, m_From.y,
+ m_To.x, m_To.y,
+ };
+
+ uint16 indices[] = {
+ 0, 1
+ };
+
+
+ uint8* vb;
+ uint16* ib;
+
+ g_SharedVBO.GetChunk(sizeof(UILineLayout), sizeof(uint16), nVerts, nIndices, Primitive_Line, (void**)&vb, (void**)&ib);
+
+ UILineLayout* dst = (UILineLayout*)vb;
+
+ for (int i = 0; i < nVerts; ++i)
+ {
+ dst[i].position.Set(pos[2 * i], pos[2 * i + 1]);
+ }
+
+ for (int i = 0; i < nIndices; ++i)
+ ib[i] = indices[i];
+
+ g_SharedVBO.ReleaseChunk(nVerts, nIndices);
+ g_SharedVBO.DrawChunk(layout);
+} \ No newline at end of file
diff --git a/Client/Source/GUI/UILine.h b/Client/Source/GUI/UILine.h
new file mode 100644
index 0000000..a47b1f1
--- /dev/null
+++ b/Client/Source/GUI/UILine.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "../Utilities/StaticInitiator.h"
+#include "UIMesh.h"
+
+class UILine : public UIMesh
+{
+public:
+ UILine(Vector2f from, Vector2f to)
+ {
+ m_From = from;
+ m_To = to;
+ }
+
+ void Draw() override;
+
+private:
+ Vector2f m_From;
+ Vector2f m_To;
+
+};
diff --git a/Client/Source/GUI/UIMesh.cpp b/Client/Source/GUI/UIMesh.cpp
new file mode 100644
index 0000000..9616c46
--- /dev/null
+++ b/Client/Source/GUI/UIMesh.cpp
@@ -0,0 +1,15 @@
+#include "UIMesh.h"
+
+CustomVertexLayout UIMesh::s_UIVertexLayout;
+unsigned int UIMesh::s_SizePerVertex;
+
+InitializeStaticVariables([]() {
+ VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(UIVertexLayout));
+ VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector2f), 2, VertexAttrFormat_Float, sizeof(UIVertexLayout));
+ VertexAttributeDescriptor COLOR = VertexAttributeDescriptor(sizeof(Vector2f) * 2, 4, VertexAttrFormat_Unsigned_Byte, sizeof(UIVertexLayout), true);
+ UIMesh::s_UIVertexLayout.attributes.push_back(POSITION);
+ UIMesh::s_UIVertexLayout.attributes.push_back(UV);
+ UIMesh::s_UIVertexLayout.attributes.push_back(COLOR);
+
+ UIMesh::s_SizePerVertex = sizeof(UIVertexLayout);
+});
diff --git a/Client/Source/GUI/UIMesh.h b/Client/Source/GUI/UIMesh.h
new file mode 100644
index 0000000..11f157a
--- /dev/null
+++ b/Client/Source/GUI/UIMesh.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "../Utilities/Exception.h"
+#include "../Graphics/DynamicMesh.h"
+#include "../Math/Math.h"
+#include "../Utilities/StaticInitiator.h"
+#include "../Graphics/CustomVertexLayout.h"
+#include "../Graphics/DefaultVertexLayout.h"
+#include "../Graphics/Color.h"
+#include "../Graphics/GfxDevice.h"
+
+// UIĬϵĶ㲼
+struct UIVertexLayout
+{
+ UIVertexLayout(Vector2f pos = Vector2f::zero, Vector2f texCoord = Vector2f::zero, Color32 col = Color32())
+ {
+ position = pos;
+ uv = texCoord;
+ color = col;
+ }
+
+ Vector2f position;
+ Vector2f uv;
+ Color32 color;
+};
+
+typedef uint16 UIIndex;
+
+CustomException(UIMeshException);
+
+// еUIMeshϽΪԭ
+class UIMesh : public DynamicMesh
+{
+public:
+ UIMesh() : DynamicMesh() {}
+ virtual ~UIMesh() {}
+
+ virtual void Draw() = 0;
+
+ static CustomVertexLayout s_UIVertexLayout;
+ static unsigned int s_SizePerVertex;
+};
diff --git a/Client/Source/GUI/UIQuad.cpp b/Client/Source/GUI/UIQuad.cpp
new file mode 100644
index 0000000..d3c7825
--- /dev/null
+++ b/Client/Source/GUI/UIQuad.cpp
@@ -0,0 +1,64 @@
+#include "../Math/Math.h"
+#include "../Graphics/GfxDevice.h"
+
+#include "UIQuad.h"
+
+struct UIQuadLayout
+{
+ Vector2f position;
+ Vector2f uv;
+};
+
+static CustomVertexLayout layout;
+
+InitializeStaticVariables([]() {
+ VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(UIQuadLayout));
+ VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector2f), 2, VertexAttrFormat_Float, sizeof(UIQuadLayout));
+
+ layout.attributes.push_back(POSITION);
+ layout.attributes.push_back(UV);
+});
+
+void UIQuad::Draw()
+{
+ const int nVerts = 4;
+ const int nIndices = 6;
+
+ float pos[] = {
+ m_Left, m_Bottom, // left-bottom
+ m_Right, m_Bottom, // right-bottom
+ m_Right, m_Top, // right-top
+ m_Left, m_Top, // top-left
+ };
+
+ float uv[] = {
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1,
+ };
+
+ uint16 indices[] = {
+ 0, 1, 3, // right-top
+ 1, 2, 3, // left-bottom
+ };
+
+ uint8* vb;
+ uint16* ib;
+
+ g_SharedVBO.GetChunk(sizeof(UIQuadLayout), sizeof(uint16), nVerts, nIndices, Primitive_Triangle, (void**)&vb, (void**)&ib);
+
+ UIQuadLayout* dst = (UIQuadLayout*)vb;
+
+ for (int i = 0; i < nVerts; ++i)
+ {
+ dst[i].position.Set(pos[2 * i], pos[2 * i + 1]);
+ dst[i].uv.Set(uv[2 * i], uv[2 * i + 1]);
+ }
+
+ for (int i = 0; i < nIndices; ++i)
+ ib[i] = indices[i];
+
+ g_SharedVBO.ReleaseChunk(nVerts, nIndices);
+ g_SharedVBO.DrawChunk(layout);
+} \ No newline at end of file
diff --git a/Client/Source/GUI/UIQuad.h b/Client/Source/GUI/UIQuad.h
new file mode 100644
index 0000000..278848a
--- /dev/null
+++ b/Client/Source/GUI/UIQuad.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "../Utilities/StaticInitiator.h"
+#include "UIMesh.h"
+
+class UIQuad : public UIMesh
+{
+public :
+ UIQuad(float l, float r, float t, float b)
+ {
+ m_Left = l;
+ m_Right = r;
+ m_Top = t;
+ m_Bottom = b;
+ }
+
+ void Draw() override;
+
+private:
+ float m_Left, m_Right, m_Top, m_Bottom;
+
+};
diff --git a/Client/Source/GUI/UISquare.cpp b/Client/Source/GUI/UISquare.cpp
new file mode 100644
index 0000000..f5c3702
--- /dev/null
+++ b/Client/Source/GUI/UISquare.cpp
@@ -0,0 +1,53 @@
+#include "../Math/Math.h"
+#include "../Graphics/GfxDevice.h"
+
+#include "UISquare.h"
+
+struct UISquareLayout
+{
+ Vector2f position;
+};
+
+static CustomVertexLayout layout;
+
+InitializeStaticVariables([]() {
+ VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(UISquareLayout));
+
+ layout.attributes.push_back(POSITION);
+});
+
+void UISquare::Draw()
+{
+ const int nVerts = 4;
+ const int nIndices = 6;
+
+ float pos[] = {
+ m_Left, m_Bottom, // left-bottom
+ m_Right, m_Bottom, // right-bottom
+ m_Right, m_Top, // right-top
+ m_Left, m_Top, // top-left
+ };
+
+ int indices[] = {
+ 0, 1, 3, // right-top
+ 1, 2, 3, // left-bottom
+ };
+
+ uint8* vb;
+ uint16* ib;
+
+ g_SharedVBO.GetChunk(sizeof(UISquareLayout), sizeof(uint16), 4, 6, Primitive_Triangle, (void**)&vb, (void**)&ib);
+
+ UISquareLayout* dst = (UISquareLayout*)vb;
+
+ for (int i = 0; i < nVerts; ++i)
+ {
+ dst[i].position.Set(pos[2 * i], pos[2 * i + 1]);
+ }
+
+ for (int i = 0; i < nIndices; ++i)
+ ib[i] = indices[i];
+
+ g_SharedVBO.ReleaseChunk(4, 6);
+ g_SharedVBO.DrawChunk(layout);
+}
diff --git a/Client/Source/GUI/UISquare.h b/Client/Source/GUI/UISquare.h
new file mode 100644
index 0000000..8de07f0
--- /dev/null
+++ b/Client/Source/GUI/UISquare.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "../Utilities/StaticInitiator.h"
+#include "UIMesh.h"
+
+// ɫ
+class UISquare : public UIMesh
+{
+public:
+ UISquare(float l, float r, float t, float b)
+ {
+ m_Left = l;
+ m_Right = r;
+ m_Top = t;
+ m_Bottom = b;
+ }
+
+ void Draw() override;
+
+private:
+ float m_Left, m_Right, m_Top, m_Bottom;
+
+};
diff --git a/Client/Source/GUI/UITextMesh.cpp b/Client/Source/GUI/UITextMesh.cpp
new file mode 100644
index 0000000..13bd8dc
--- /dev/null
+++ b/Client/Source/GUI/UITextMesh.cpp
@@ -0,0 +1,278 @@
+#include "../Graphics/CustomVertexLayout.h"
+#include "../Utilities/StaticInitiator.h"
+#include "../Math/Math.h"
+#include "../Graphics/Color.h"
+#include "../Graphics/GfxDevice.h"
+#include "../Utilities/AutoInvoke.h"
+#include "../Graphics/DefaultVertexLayout.h"
+#include "../Debug/Log.h"
+
+#include "UITextMesh.h"
+
+#include <vector>
+#include <unordered_map>
+
+using namespace std;
+
+struct TextMeshVBOLayout
+{
+ Vector2f position;
+ Vector2f uv;
+ Color32 color;
+};
+
+static CustomVertexLayout s_TextMeshVBOLayout;
+
+static unsigned int s_VertexPerText;
+static unsigned int s_SizePerVertex;
+static unsigned int s_SizePerText;
+static unsigned int s_SizePerIndex;
+static unsigned int s_IndicesPerText;
+
+struct TextInfo {
+ const Character* ch;
+ float offset;
+ int line; // 0ʼ
+};
+
+InitializeStaticVariables([]() {
+ VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout));
+ VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector2f), 2, VertexAttrFormat_Float, sizeof(TextMeshVBOLayout));
+ VertexAttributeDescriptor COLOR = VertexAttributeDescriptor(sizeof(Vector2f)*2, 4, VertexAttrFormat_Unsigned_Byte, sizeof(TextMeshVBOLayout), true);
+ s_TextMeshVBOLayout.attributes.push_back(POSITION);
+ s_TextMeshVBOLayout.attributes.push_back(UV);
+ s_TextMeshVBOLayout.attributes.push_back(COLOR);
+
+ s_VertexPerText = 4;
+ s_SizePerVertex = sizeof(TextMeshVBOLayout);
+
+ s_IndicesPerText = 6;
+ s_SizePerIndex = VertexLayout::GetDefaultIndexSize();
+
+ s_SizePerText = sizeof(TextMeshVBOLayout) * 4;
+});
+
+UITextMesh::UITextMesh(
+ const UnicodeString& str // ı
+ , Font* font //
+ , int pixelSize // С
+ , int lineHeight // и
+ , Color32 color32 // ɫ
+ , ETextAnchor anchor // ê
+ , ETextAlignment alignment // 뷽ʽ
+ , bool wordwrap // Զ
+ , float preferred // ԶС
+){
+ m_Font = font;
+ m_PixelSize = pixelSize;
+ m_LineHeight = lineHeight;
+ m_Color = color32;
+ m_Alignment = alignment;
+ m_Anchor = anchor;
+ m_Wordwrap = wordwrap;
+ m_Preferred = preferred;
+ m_Content.length = str.length;
+ m_Content.str = (character::Unicode*)malloc(str.length * sizeof(character::Unicode));
+ memcpy(m_Content.str, str.str, str.length * sizeof(character::Unicode));
+
+ // ¼ıatlas
+ static unordered_map<unsigned int, vector<TextInfo>> s_TextInfos;
+ s_TextInfos.clear();
+
+ // ¼ıÿеij
+ static unordered_map<int, int> s_LineWidths;
+ s_LineWidths.clear();
+
+ // ¼ÿеƫƳ
+ static unordered_map<int, int> s_LineOffsets;
+ s_LineOffsets.clear();
+
+ InvokeWhenLeave([]() {
+ s_LineWidths.clear();
+ s_LineOffsets.clear();
+ s_TextInfos.clear();
+ });
+
+ const Vector2f atlasSize = font->GetAtlasSize();
+
+ //-----------------------------------------------------------------
+ // ˻кԶ֮ıС
+ Vector2f textRegion;
+ // ղͬatlasൽs_TextInfos
+ float offset = 0;
+ int line = 0;
+ for (int i = 0; i < str.length; ++i)
+ {
+ character::Unicode c = str.str[i];
+ const Character* ch = font->GetCharacter(c, pixelSize);
+ if (ch == NULL)
+ continue;
+
+ if (wordwrap) // Զ
+ {
+ if (offset + ch->bearing.x + ch->position.width > preferred)
+ {
+
+ ++line;
+ offset = 0;
+ }
+ }
+
+ unsigned int atlasIndex = ch->atlas;
+ if (atlasIndex != FONT_NOT_IN_ATLAS_PLACEHOLDER) //ǿո
+ {
+// зUnix'\n', Windows'\r\n', MacOS '\r'
+#define CHECK_BREAKS() \
+ if (c == '\n' || c == '\r') \
+ { \
+ ++line; \
+ offset = 0; \
+ if (c == '\r' && ((i + 1) < str.length && str.str[i + 1] == '\n')) /*skip\n*/ \
+ ++i; \
+ continue; \
+ }
+
+ CHECK_BREAKS();
+
+ TextInfo info;
+ info.ch = ch;
+ info.offset = offset;
+ info.line = line;
+
+ auto list = s_TextInfos.find(atlasIndex);
+ if (list == s_TextInfos.end())
+ s_TextInfos.insert(std::pair<unsigned int, vector<TextInfo>>(atlasIndex, vector<TextInfo>()));
+
+ vector<TextInfo>& v = s_TextInfos[atlasIndex];
+ v.push_back(info);
+ }
+ else
+ {
+ // Щ廻ûΣҲҪﴦ
+ CHECK_BREAKS();
+ }
+
+ offset += ch->advance;
+
+ textRegion.x = max(offset, textRegion.x);
+
+ if (s_LineWidths.count(line) == 0)
+ s_LineWidths.insert(std::pair<int, int>(line, 0));
+ s_LineWidths[line] = max(offset, s_LineWidths[line]);
+ }
+
+ textRegion.y = (line + 1) * lineHeight;
+
+ if (s_TextInfos.size() == 0)
+ {
+ return;
+ }
+
+ Vector2i textOffset;
+ Vector2f halfRegion = Vector2f(textRegion.x/ 2.f, textRegion.y / 2.f);
+ switch (anchor)
+ {
+ case TextAnchor_UpperLeft: textOffset.Set(0, 0); break;
+ case TextAnchor_UpperCenter: textOffset.Set(-halfRegion.x, 0); break;
+ case TextAnchor_UpperRight: textOffset.Set(-textRegion.x, 0); break;
+ case TextAnchor_MiddleLeft: textOffset.Set(0, -halfRegion.y); break;
+ case TextAnchor_MiddleCenter: textOffset.Set(-halfRegion.x, -halfRegion.y); break;
+ case TextAnchor_MiddleRight: textOffset.Set(-textRegion.x, -halfRegion.y); break;
+ case TextAnchor_LowerLeft: textOffset.Set(0, -textRegion.y); break;
+ case TextAnchor_LowerCenter: textOffset.Set(-halfRegion.x, -textRegion.y); break;
+ case TextAnchor_LowerRight: textOffset.Set(-textRegion.x, -textRegion.y); break;
+ }
+
+ for (int i = 0; i < line; ++i)
+ {
+ int lineLen = s_LineWidths.count(i) != 0 ? s_LineWidths[i] : 0;
+ int lineOffset = 0;
+ switch (alignment)
+ {
+ case TextAlignment_Left: lineOffset = 0; break;
+ case TextAlignment_Center: lineOffset = (textRegion.x - lineLen)/2.f; break;
+ case TextAlignment_Right: lineOffset = textRegion.x - lineLen; break;
+ }
+ s_LineOffsets.insert(std::pair<int, int>(i, lineOffset));
+ }
+
+ //-----------------------------------------------------------------
+
+ // VBOIBO
+ for (auto iter : s_TextInfos) {
+ unsigned int atlasIndex = iter.first; // atlas atlasIndex
+ vector<TextInfo>& texts = iter.second;
+ int textCount = texts.size();
+
+ VertexBuffer* vb = new VertexBuffer(textCount * s_SizePerText, textCount * s_IndicesPerText * s_SizePerIndex, VertexBuffer::VertexBufferType_Static);
+ void* pVB;
+ uint16* pIB;
+
+ vb->GetChunk(s_SizePerVertex, s_SizePerIndex, s_VertexPerText * textCount, s_IndicesPerText * textCount, EPrimitive::Primitive_Triangle, &pVB,(void**) &pIB);
+
+ TextMeshVBOLayout* dst = (TextMeshVBOLayout*)pVB;
+ for (int i = 0; i < textCount; ++i)
+ {
+ TextInfo& text = texts[i];
+
+ int vOff = i * s_VertexPerText;
+ int lineXOff = s_LineOffsets.count(text.line) ? s_LineOffsets[text.line] : 0;
+ int lineYOff = text.line * lineHeight;
+ // Ͻԭ
+ float pos[] = {
+ textOffset.x + lineXOff + text.offset + text.ch->bearing.x, textOffset.y + lineYOff + pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-left
+ textOffset.x + lineXOff + text.offset + text.ch->bearing.x + text.ch->position.width, textOffset.y + lineYOff + pixelSize - text.ch->bearing.y + text.ch->position.height, // bottom-right
+ textOffset.x + lineXOff + text.offset + text.ch->bearing.x + text.ch->position.width, textOffset.y + lineYOff + pixelSize - text.ch->bearing.y, // top-right
+ textOffset.x + lineXOff + text.offset + text.ch->bearing.x, textOffset.y + lineYOff + pixelSize - text.ch->bearing.y, // top-left
+ };
+ Vector4f uvQuad = Vector4f(text.ch->position.x / atlasSize.x, text.ch->position.y / atlasSize.y, text.ch->position.width / atlasSize.x, text.ch->position.height / atlasSize.y);
+ float uv[] = {
+ uvQuad.x, uvQuad.y + uvQuad.w,
+ uvQuad.x + uvQuad.z, uvQuad.y + uvQuad.w,
+ uvQuad.x + uvQuad.z, uvQuad.y,
+ uvQuad.x, uvQuad.y,
+ };
+ for (int j = 0; j < s_VertexPerText; ++j)
+ {
+ dst[vOff + j].position.Set(pos[2 * j], pos[2 * j + 1]);
+ dst[vOff + j].uv.Set(uv[2 * j], uv[2 * j + 1]);
+ dst[vOff + j].color = color32;
+ }
+
+ int iOff = i * s_IndicesPerText;
+ int indices[] = {
+ 0, 1, 3, // right-top
+ 1, 2, 3, // left-bottom
+ };
+ for (int j = 0; j < s_IndicesPerText; ++j)
+ pIB[iOff + j] = vOff + indices[j];
+ }
+
+ vb->FlushChunk(s_VertexPerText * textCount, s_IndicesPerText * textCount);
+
+ m_VBOs.insert(std::pair<int, VertexBuffer*>(atlasIndex, vb));
+ }
+
+ WipeGLError();
+}
+
+void UITextMesh::Draw() const
+{
+ for (auto subText : m_VBOs)
+ {
+ int atlasIndex = subText.first; // atlasIndex of atlas
+ VertexBuffer* vbo = subText.second;
+
+ const GlyphAtals* atlas = m_Font->GetGlyphAtlas(atlasIndex);
+ if (atlas == NULL)
+ {
+ log_error("Render text failed, no glyph atlas.");
+ continue;
+ }
+
+ g_GfxDevice.SetUniformTexture("gamelab_main_tex", atlas->altas);
+
+ WipeGLError();
+ vbo->Draw(s_TextMeshVBOLayout);
+ }
+}
diff --git a/Client/Source/GUI/UITextMesh.h b/Client/Source/GUI/UITextMesh.h
new file mode 100644
index 0000000..869db80
--- /dev/null
+++ b/Client/Source/GUI/UITextMesh.h
@@ -0,0 +1,69 @@
+#pragma once
+
+#include "../Graphics/VertexBuffer.h"
+#include "../Utilities/Exception.h"
+#include "../Graphics/Color.h"
+
+#include "Font.h"
+
+#include <unordered_map>
+
+CustomException(TextMeshException);
+
+enum ETextAnchor
+{
+ TextAnchor_UpperLeft,
+ TextAnchor_UpperCenter,
+ TextAnchor_UpperRight,
+ TextAnchor_MiddleLeft,
+ TextAnchor_MiddleCenter,
+ TextAnchor_MiddleRight,
+ TextAnchor_LowerLeft,
+ TextAnchor_LowerCenter,
+ TextAnchor_LowerRight,
+};
+
+enum ETextAlignment {
+ TextAlignment_Left,
+ TextAlignment_Center,
+ TextAlignment_Right,
+};
+
+namespace TextHelper
+{
+}
+
+class UITextMesh
+{
+public:
+ void Draw() const;
+
+private:
+ friend class TextMeshGenerator;
+
+ UITextMesh(const UnicodeString& str, Font* font, int pixelSize, int lineHeight, Color32 color32 = Color32::white, ETextAnchor anchor = TextAnchor_UpperLeft, ETextAlignment alignment = TextAlignment_Left, bool wordwrap = false, float preferred = 0)/*throw TextMeshException*/;
+ ~UITextMesh();
+
+ GET(const Font*, Font, m_Font);
+ GET(int, PixelSize, m_PixelSize);
+ GET(int, LineHeight, m_LineHeight);
+ GET(Color32, Color, m_Color);
+ GET(ETextAlignment, Alignment, m_Alignment);
+ GET(ETextAnchor, Anchor, m_Anchor);
+ GET(bool, Wordwrap, m_Wordwrap);
+ GET(float, Preferred, m_Preferred);
+ GET(const UnicodeString&, Content, m_Content);
+
+ std::unordered_map<int, VertexBuffer*> m_VBOs;
+
+ Font* m_Font;
+ UnicodeString m_Content;
+ int m_PixelSize;
+ int m_LineHeight;
+ Color32 m_Color;
+ ETextAlignment m_Alignment;
+ ETextAnchor m_Anchor;
+ bool m_Wordwrap;
+ float m_Preferred;
+
+}; \ No newline at end of file
diff --git a/Client/Source/GUI/freetype.h b/Client/Source/GUI/freetype.h
new file mode 100644
index 0000000..4b54e20
--- /dev/null
+++ b/Client/Source/GUI/freetype.h
@@ -0,0 +1,4 @@
+#pragma once
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
diff --git a/Client/Source/GUI/utf8.cpp b/Client/Source/GUI/utf8.cpp
new file mode 100644
index 0000000..8a3a086
--- /dev/null
+++ b/Client/Source/GUI/utf8.cpp
@@ -0,0 +1,415 @@
+/*
+ * Description: UTF-8 字符串的解码和编码函数
+ * unicode 字符处理函数
+ * History: yang@haipo.me, 2013/05/29, create
+ *
+ * This code is in the public domain.
+ * You may use this code any way you wish, private, educational,
+ * or commercial. It's free.
+ */
+
+# include <stdint.h>
+# include <stddef.h>
+
+# include "utf8.h"
+
+namespace utf8
+{
+
+ ucs4_t getu8c(char **src, int *illegal)
+ {
+ static char umap[256] = { 0 };
+ static int umap_init_flag = 0;
+
+ if (umap_init_flag == 0)
+ {
+ int i;
+
+ for (i = 0; i < 0x100; ++i)
+ {
+ if (i < 0x80)
+ {
+ umap[i] = 1;
+ }
+ else if (i >= 0xc0 && i < 0xe0)
+ {
+ umap[i] = 2;
+ }
+ else if (i >= 0xe0 && i < 0xf0)
+ {
+ umap[i] = 3;
+ }
+ else if (i >= 0xf0 && i < 0xf8)
+ {
+ umap[i] = 4;
+ }
+ else if (i >= 0xf8 && i < 0xfc)
+ {
+ umap[i] = 5;
+ }
+ else if (i >= 0xfc && i < 0xfe)
+ {
+ umap[i] = 6;
+ }
+ else
+ {
+ umap[i] = 0;
+ }
+ }
+
+ umap_init_flag = 1;
+ }
+
+ uint8_t *s = (uint8_t *)(*src);
+ int r_illegal = 0;
+
+ while (umap[*s] == 0)
+ {
+ ++s;
+ ++r_illegal;
+ }
+
+ uint8_t *t;
+ int byte_num;
+ uint32_t uc;
+ int i;
+
+ repeat_label:
+ t = s;
+ byte_num = umap[*s];
+ uc = *s++ & (0xff >> byte_num);
+
+ for (i = 1; i < byte_num; ++i)
+ {
+ if (umap[*s])
+ {
+ r_illegal += s - t;
+ goto repeat_label;
+ }
+ else
+ {
+ uc = (uc << 6) + (*s & 0x3f);
+ s += 1;
+ }
+ }
+
+ *src = (char *)s;
+ if (illegal)
+ {
+ *illegal = r_illegal;
+ }
+
+ return uc;
+ }
+
+ size_t u8decode(char const *str, ucs4_t *des, size_t n, int *illegal)
+ {
+ if (n == 0)
+ return 0;
+
+ char *s = (char *)str;
+ size_t i = 0;
+ ucs4_t uc = 0;
+ int r_illegal_all = 0, r_illegal;
+
+ while ((uc = getu8c(&s, &r_illegal)))
+ {
+ if (i < (n - 1))
+ {
+ des[i++] = uc;
+ r_illegal_all += r_illegal;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ des[i] = 0;
+ if (illegal)
+ {
+ *illegal = r_illegal_all + r_illegal;
+ }
+
+ return i;
+ }
+
+# define IF_CAN_HOLD(left, n) do { \
+ size_t m = (size_t)(n); \
+ if ((size_t)(left) < (m + 1)) return -2; \
+ (left) -= m; \
+} while (0)
+
+ int putu8c(ucs4_t uc, char **des, size_t *left)
+ {
+ if (uc < 0)
+ return -1;
+
+ if (uc < (0x1 << 7))
+ {
+ IF_CAN_HOLD(*left, 1);
+
+ **des = (char)uc;
+ *des += 1;
+ **des = 0;
+
+ return 1;
+ }
+
+ int byte_num;
+
+ if (uc < (0x1 << 11))
+ {
+ byte_num = 2;
+ }
+ else if (uc < (0x1 << 16))
+ {
+ byte_num = 3;
+ }
+ else if (uc < (0x1 << 21))
+ {
+ byte_num = 4;
+ }
+ else if (uc < (0x1 << 26))
+ {
+ byte_num = 5;
+ }
+ else
+ {
+ byte_num = 6;
+ }
+
+ IF_CAN_HOLD(*left, byte_num);
+
+ int i;
+ for (i = byte_num - 1; i > 0; --i)
+ {
+ *(uint8_t *)(*des + i) = (uc & 0x3f) | 0x80;
+ uc >>= 6;
+ }
+
+ *(uint8_t *)(*des) = uc | (0xff << (8 - byte_num));
+
+ *des += byte_num;
+ **des = 0;
+
+ return byte_num;
+ }
+
+ size_t u8encode(ucs4_t *us, char *des, size_t n, int *illegal)
+ {
+ if (n == 0)
+ return 0;
+
+ char *s = des;
+ size_t left = n;
+ size_t len = 0;
+ int r_illegal = 0;
+
+ *s = 0;
+ while (*us)
+ {
+ int ret = putu8c(*us, &s, &left);
+ if (ret > 0)
+ {
+ len += ret;
+ }
+ else if (ret == -1)
+ {
+ r_illegal += 1;
+ }
+ else
+ {
+ break;
+ }
+
+ ++us;
+ }
+
+ if (illegal)
+ {
+ *illegal = r_illegal;
+ }
+
+ return len;
+ }
+
+ /* 全角字符 */
+ int isufullwidth(ucs4_t uc)
+ {
+ if (uc == 0x3000)
+ return 1;
+
+ if (uc >= 0xff01 && uc <= 0xff5e)
+ return 1;
+
+ return 0;
+ }
+
+ /* 全角字母 */
+ int isufullwidthalpha(ucs4_t uc)
+ {
+ if (uc >= 0xff21 && uc <= 0xff3a)
+ return 1;
+
+ if (uc >= 0xff41 && uc <= 0xff5a)
+ return 2;
+
+ return 0;
+ }
+
+ /* 全角数字 */
+ int isufullwidthdigit(ucs4_t uc)
+ {
+ if (uc >= 0xff10 && uc <= 0xff19)
+ return 1;
+
+ return 0;
+ }
+
+ /* 全角转半角 */
+ ucs4_t ufull2half(ucs4_t uc)
+ {
+ if (uc == 0x3000)
+ return ' ';
+
+ if (uc >= 0xff01 && uc <= 0xff5e)
+ return uc - 0xfee0;
+
+ return uc;
+ }
+
+ /* 半角转全角 */
+ ucs4_t uhalf2full(ucs4_t uc)
+ {
+ if (uc == ' ')
+ return 0x3000;
+
+ if (uc >= 0x21 && uc <= 0x7e)
+ return uc + 0xfee0;
+
+ return uc;
+ }
+
+ /* 中日韩越统一表意文字 */
+ int isuchiness(ucs4_t uc)
+ {
+ /* 最初期统一汉字 */
+ if (uc >= 0x4e00 && uc <= 0x9fcc)
+ return 1;
+
+ /* 扩展 A 区 */
+ if (uc >= 0x3400 && uc <= 0x4db5)
+ return 2;
+
+ /* 扩展 B 区 */
+ if (uc >= 0x20000 && uc <= 0x2a6d6)
+ return 3;
+
+ /* 扩展 C 区 */
+ if (uc >= 0x2a700 && uc <= 0x2b734)
+ return 4;
+
+ /* 扩展 D 区 */
+ if (uc >= 0x2b740 && uc <= 0x2b81f)
+ return 5;
+
+ /* 扩展 E 区 */
+ if (uc >= 0x2b820 && uc <= 0x2f7ff)
+ return 6;
+
+ /* 台湾兼容汉字 */
+ if (uc >= 0x2f800 && uc <= 0x2fa1d)
+ return 7;
+
+ /* 北朝鲜兼容汉字 */
+ if (uc >= 0xfa70 && uc <= 0xfad9)
+ return 8;
+
+ /* 兼容汉字 */
+ if (uc >= 0xf900 && uc <= 0xfa2d)
+ return 9;
+
+ /* 兼容汉字 */
+ if (uc >= 0xfa30 && uc <= 0xfa6d)
+ return 10;
+
+ return 0;
+ }
+
+ /* 中文标点 */
+ int isuzhpunct(ucs4_t uc)
+ {
+ if (uc >= 0x3001 && uc <= 0x3002)
+ return 1;
+
+ if (uc >= 0x3008 && uc <= 0x300f)
+ return 1;
+
+ if (uc >= 0xff01 && uc <= 0xff0f)
+ return 1;
+
+ if (uc >= 0xff1a && uc <= 0xff20)
+ return 1;
+
+ if (uc >= 0xff3b && uc <= 0xff40)
+ return 1;
+
+ if (uc >= 0xff5b && uc <= 0xff5e)
+ return 1;
+
+ if (uc >= 0x2012 && uc <= 0x201f)
+ return 1;
+
+ if (uc >= 0xfe41 && uc <= 0xfe44)
+ return 1;
+
+ if (uc >= 0xfe49 && uc <= 0xfe4f)
+ return 1;
+
+ if (uc >= 0x3010 && uc <= 0x3017)
+ return 1;
+
+ return 0;
+ }
+
+ /* 日文平假名 */
+ int isuhiragana(ucs4_t uc)
+ {
+ if (uc >= 0x3040 && uc <= 0x309f)
+ return 1;
+
+ return 0;
+ }
+
+ /* 日文片假名 */
+ int isukatakana(ucs4_t uc)
+ {
+ if (uc >= 0x30a0 && uc <= 0x30ff)
+ return 1;
+
+ if (uc >= 0x31f0 && uc <= 0x31ff)
+ return 2;
+
+ return 0;
+ }
+
+ /* 韩文 */
+ int isukorean(ucs4_t uc)
+ {
+ /* 韩文拼音 */
+ if (uc >= 0xac00 && uc <= 0xd7af)
+ return 1;
+
+ /* 韩文字母 */
+ if (uc >= 0x1100 && uc <= 0x11ff)
+ return 2;
+
+ /* 韩文兼容字母 */
+ if (uc >= 0x3130 && uc <= 0x318f)
+ return 3;
+
+ return 0;
+ }
+
+}
diff --git a/Client/Source/GUI/utf8.h b/Client/Source/GUI/utf8.h
new file mode 100644
index 0000000..b561b44
--- /dev/null
+++ b/Client/Source/GUI/utf8.h
@@ -0,0 +1,113 @@
+/*
+ * Description: UTF-8 字符串的解码和编码函数
+ * unicode 字符处理函数
+ * History: yang@haipo.me, 2013/05/29, create
+ *
+ * This code is in the public domain.
+ * You may use this code any way you wish, private, educational,
+ * or commercial. It's free.
+ */
+
+# pragma once
+
+# include <stdint.h>
+# include <stddef.h>
+
+namespace utf8
+{
+
+
+ /*
+ * 标准 C 并没有规定 wchar_t 的位数。但 GNU C Lib 保证 wchar_t 是 32 位的,
+ * 所以可以用 wchar.h 中定义的函数来像 wchar_t 一样操纵 ucs4_t.
+ * http://www.gnu.org/software/libc/manual/html_node/Extended-Char-Intro.html
+ */
+ typedef int32_t ucs4_t;
+
+ /*
+ * 从 UTF-8 编码的字符串 *src 中读取一个 unicode 字符,并更新 *src 的值。
+ *
+ * 如果遇到非法 UTF-8 编码,则跳过非法部分。
+ * 如果 illegal 参数不为 NULL, 则 *illegal 表示非法 UTF-8 编码字节数。
+ */
+ ucs4_t getu8c(char **src, int *illegal);
+
+ /*
+ * 将 src 指向的 UTF-8 编码字符串解码为 unicode,放在长度为 n 的数组 des 中,
+ * 并在末尾添加 0. 如果 des 不足以存放所有的字符,则最多保存 n - 1 个 unicode
+ * 字符并补 0.
+ *
+ * 如果遇到非法 UTF-8 编码,则跳过非法部分。
+ * 如果 illegal 不为 NULL, 则 *illegal 表示非法 UTF-8 编码的字节数。
+ */
+ size_t u8decode(char const *str, ucs4_t *des, size_t n, int *illegal);
+
+ /*
+ * 将 unicode 字符 uc 编码为 UTF-8 编码,放到长度为 *left 的字符串 *des 中。
+ *
+ * 如果 *des 不足以存放 uc 对应的 UTF-8 字符串,返回一个负值。
+ * 如果成功,更新 *des 和 *left 的值。
+ */
+ int putu8c(ucs4_t uc, char **des, size_t *left);
+
+ /*
+ * 将以 0 结尾的 unicode 数组 us 编码为 UTF-8 字符串,放到长度为 n 的字符串 des 中。
+ *
+ * 负数为非法的 unicode 字符。
+ * 如果 illegal 不为 NULL,则 *illegal 表示非法的 unicode 字符数。
+ */
+ size_t u8encode(ucs4_t *us, char *des, size_t n, int *illegal);
+
+ /*
+ * 判断是否为全角字符
+ */
+ int isufullwidth(ucs4_t uc);
+
+ /*
+ * 判断是否为全角字母
+ */
+ int isufullwidthalpha(ucs4_t uc);
+
+ /*
+ * 判断是否为全角数字
+ */
+ int isufullwidthdigit(ucs4_t uc);
+
+ /*
+ * 全角字符转半角字符。
+ * 如果 uc 为全角字符,则返回对应的半角字符,否则返回 uc 本身。
+ */
+ ucs4_t ufull2half(ucs4_t uc);
+
+ /*
+ * 半角字符转全角字符
+ * 如果 uc 为半角字符,则返回对应的全角字符,否则返回 uc 本身。
+ */
+ ucs4_t uhalf2full(ucs4_t uc);
+
+ /*
+ * 判断是否为汉字字符(中日韩越统一表意文字)
+ */
+ int isuchiness(ucs4_t uc);
+
+ /*
+ * 判断是否为中文标点
+ */
+ int isuzhpunct(ucs4_t uc);
+
+ /*
+ * 判断是否为日文平假名字符
+ */
+ int isuhiragana(ucs4_t uc);
+
+ /*
+ * 判断是否为日文片假名字符
+ */
+ int isukatakana(ucs4_t uc);
+
+ /*
+ * 判断是否为韩文字符
+ */
+ int isukorean(ucs4_t uc);
+
+}
diff --git a/Client/Source/Graphics/Color.cpp b/Client/Source/Graphics/Color.cpp
new file mode 100644
index 0000000..88b1ed8
--- /dev/null
+++ b/Client/Source/Graphics/Color.cpp
@@ -0,0 +1,4 @@
+#include "Color.h"
+
+const Color32 Color32::white = Color32(255, 255, 255, 255);
+
diff --git a/Client/Source/Graphics/Color.h b/Client/Source/Graphics/Color.h
new file mode 100644
index 0000000..f7bb937
--- /dev/null
+++ b/Client/Source/Graphics/Color.h
@@ -0,0 +1,48 @@
+#pragma once
+
+struct Color
+{
+ Color(float r = 0, float g = 0, float b = 0, float a = 0)
+ {
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+ }
+ void Set(float r = 0, float g = 0, float b = 0, float a = 0)
+ {
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+ }
+ float r, g, b, a;
+};
+
+struct Color32
+{
+ Color32(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 0)
+ {
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+ }
+ void Set(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 0)
+ {
+ this->r = r;
+ this->g = g;
+ this->b = b;
+ this->a = a;
+ }
+
+ bool operator !=(const Color32& col)
+ {
+ return !(r == col.r && g == col.g && b == col.b && a == col.a);
+ }
+
+ unsigned char r, g, b, a;
+
+ static const Color32 white;
+};
+
diff --git a/Client/Source/Graphics/CustomVertexLayout.cpp b/Client/Source/Graphics/CustomVertexLayout.cpp
new file mode 100644
index 0000000..aa6be9b
--- /dev/null
+++ b/Client/Source/Graphics/CustomVertexLayout.cpp
@@ -0,0 +1,23 @@
+#include "CustomVertexLayout.h"
+
+namespace VertexLayout
+{
+
+ void SetupCustomVertexLayout(CustomVertexLayout& info)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, info.buffer);
+ for (int i = 0; i < info.attributes.size(); ++i)
+ {
+ VertexAttributeDescriptor& attr = info.attributes[i];
+ glEnableVertexAttribArray(i);
+ int numCompo = attr.componentNum;
+ GLenum compoType = VertexAttribute::ConvertAttrFormatToGLFormat(attr.componentFormat);
+ bool normalized = attr.normalize;
+ uint stride = attr.stride;
+ const void* pointer = attr.pointer;
+
+ glVertexAttribPointer(i, numCompo, compoType, normalized ? GL_TRUE : GL_FALSE, stride, pointer);
+ }
+ }
+
+}
diff --git a/Client/Source/Graphics/CustomVertexLayout.h b/Client/Source/Graphics/CustomVertexLayout.h
new file mode 100644
index 0000000..3b54039
--- /dev/null
+++ b/Client/Source/Graphics/CustomVertexLayout.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <vector>
+#include "OpenGL.h"
+#include "GPUDataBuffer.h"
+#include "VertexAttribute.h"
+
+struct CustomVertexLayout
+{
+ GLuint buffer; // ʱ
+ std::vector<VertexAttributeDescriptor> attributes;
+
+ CustomVertexLayout()
+ {
+ int n = buffer;
+ }
+
+ // pointerstartOffsetΪ0
+ void RestorePointer()
+ {
+ for (int i = 0; i < attributes.size(); ++i)
+ {
+ attributes[i].pointer = 0;
+ }
+ }
+};
+
+namespace VertexLayout
+{
+
+ extern void SetupCustomVertexLayout(CustomVertexLayout& layout);
+
+}
diff --git a/Client/Source/Graphics/DefaultVertexLayout.cpp b/Client/Source/Graphics/DefaultVertexLayout.cpp
new file mode 100644
index 0000000..a468100
--- /dev/null
+++ b/Client/Source/Graphics/DefaultVertexLayout.cpp
@@ -0,0 +1,119 @@
+#include "DefaultVertexLayout.h"
+
+namespace VertexLayout
+{
+ // Ĭvertex layout
+ static const int kVertexAttrSize[VertexAttr_Count] = {
+ 3 * sizeof(float), // position
+ 3 * sizeof(float), // normal
+ 4 * sizeof(float), // tangent
+ 4 * sizeof(byte), // color
+ 2 * sizeof(float), // uv
+ 2 * sizeof(float), // uv2
+ 2 * sizeof(float), // uv3
+ 2 * sizeof(float), // uv4
+ };
+
+ static const int kVertexAttrDimension[VertexAttr_Count] = {
+ 3, // position
+ 3, // normal
+ 4, // tangent
+ 4, // color
+ 2, // uv
+ 2, // uv2
+ 2, // uv3
+ 2, // uv4
+ };
+
+ bool IsGLVertexAttrNeedNormalized(uint attr/*, uint format*/)
+ {
+ if (attr == VertexAttr_Color)
+ return true;
+ /*
+ if (format == VertexAttrFormat_Color || format == VertexAttrFormat_Byte)
+ return true;
+ */
+ return false;
+ }
+
+ uint GetDefaultShaderChannelFormat(uint attr)
+ {
+ return attr == VertexAttr_Color ? VertexAttrFormat_Color : VertexAttrFormat_Float;
+ }
+
+ uint32 GetDefaultVertexAttrSize(int attr)
+ {
+ return kVertexAttrSize[attr];
+ }
+
+ uint GetDefaultVertexAttrDimension(uint attr)
+ {
+ return kVertexAttrDimension[attr];
+ }
+
+ uint GetDefaultShaderChannelDimension(uint attr)
+ {
+ return attr == VertexAttr_Color ? 4 : GetDefaultVertexAttrDimension(attr);
+ }
+
+ GLenum GetDefaultVertexAttrcomponentFormat(uint attr)
+ {
+ uint componentFormat = GetDefaultShaderChannelFormat(attr);
+ return VertexAttribute::ConvertAttrFormatToGLFormat(componentFormat);
+ }
+
+ uint32 GetDynamicChunkStride(uint32 vertexAttrMask)
+ {
+ uint32 stride = 0;
+ for (int i = 0; i < vertexAttrMask; ++i)
+ {
+ if (vertexAttrMask & Mask(i))
+ stride += VertexLayout::GetDefaultVertexAttrSize(i);
+ }
+ return stride;
+ }
+
+ static uint32 sEnabledArrays = 0;
+
+ void SetupDefaultVertexLayout(const DefaultVertexLayout& info)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, info.buffer);
+
+ for (int attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx)
+ {
+ if (info.enableMask & Mask(attrIdx))
+ {
+ if (!sEnabledArrays & Mask(attrIdx))
+ glEnableVertexAttribArray(attrIdx);
+ int numCompo = info.attributes[attrIdx].componentNum;
+ GLenum compoType = VertexLayout::GetDefaultVertexAttrcomponentFormat(attrIdx);
+ bool normalized = VertexLayout::IsGLVertexAttrNeedNormalized(attrIdx);
+ uint stride = info.attributes[attrIdx].stride;
+ const void* pointer = info.attributes[attrIdx].pointer;
+
+ glVertexAttribPointer(attrIdx, numCompo, compoType, normalized ? GL_TRUE : GL_FALSE, stride, pointer);
+ }
+ else if (sEnabledArrays & Mask(attrIdx))
+ glDisableVertexAttribArray(attrIdx);
+ }
+ sEnabledArrays = info.enableMask;
+ }
+
+ void InvalidateVertexInputCache()
+ {
+ sEnabledArrays = 0;
+ for (int attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx)
+ glDisableVertexAttribArray(attrIdx);
+ }
+
+ // Ϊ unsgined short (GL_UNSIGNED_SHORT)
+ uint GetDefaultIndexSize()
+ {
+ return sizeof(uint16);
+ }
+ GLenum GetDefaultIndexFormat()
+ {
+ return GL_UNSIGNED_SHORT;
+ }
+
+}
diff --git a/Client/Source/Graphics/DefaultVertexLayout.h b/Client/Source/Graphics/DefaultVertexLayout.h
new file mode 100644
index 0000000..2222ff1
--- /dev/null
+++ b/Client/Source/Graphics/DefaultVertexLayout.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <vector>
+
+#include "../Utilities/Type.h"
+#include "../Utilities/UtilMacros.h"
+
+#include "OpenGL.h"
+#include "GPUDataBuffer.h"
+#include "VertexAttribute.h"
+
+// ĬϵĶ㲼֣MeshĽԱshaderһ
+// Ҫ޸IJ,༭UIУCustomVertexLayout
+
+// ĬϵĶԼ˳
+enum EVertexAttr
+{
+ VertexAttr_Position = 0,
+ VertexAttr_Normal,
+ VertexAttr_Tangent,
+ VertexAttr_Color,
+ VertexAttr_UV,
+ VertexAttr_UV2,
+ VertexAttr_UV3,
+ VertexAttr_UV4,
+
+ VertexAttr_Count
+};
+
+// GPUĬ϶
+struct DefaultVertexLayout
+{
+ uint32 enableMask;
+ GLuint buffer; // vbo0(pinned memory)
+ VertexAttributeDescriptor attributes[VertexAttr_Count];
+};
+
+namespace VertexLayout
+{
+ // ibodefaultcustomֶshort
+ uint GetDefaultIndexSize();
+ GLenum GetDefaultIndexFormat();
+
+ uint32 GetDynamicChunkStride(uint32 vertexAttrMask);
+ bool IsGLVertexAttrNeedNormalized(uint attr);
+ uint GetDefaultShaderChannelFormat(uint attr);
+ uint32 GetDefaultVertexAttrSize(int attr);
+ uint GetDefaultVertexAttrDimension(uint attr);
+ uint GetDefaultShaderChannelDimension(uint attr);
+ GLenum GetDefaultVertexAttrComponentType(uint attr);
+
+ void SetupDefaultVertexLayout(const DefaultVertexLayout& info);
+ void InvalidateVertexInputCache();
+
+}
diff --git a/Client/Source/Graphics/DeviceDefine.h b/Client/Source/Graphics/DeviceDefine.h
new file mode 100644
index 0000000..db1c138
--- /dev/null
+++ b/Client/Source/Graphics/DeviceDefine.h
@@ -0,0 +1,69 @@
+#ifndef DEVICE_DEFINE_H
+#define DEVICE_DEFINE_H
+
+enum EDeviceEnable
+{
+ Enable_DepthTest = 1,
+ Enable_DepthWrite = 1 << 1,
+ Enable_StencilTest = 1 << 2,
+ Enable_StencilWrite = 1 << 3,
+ Enable_Cull = 1 << 4,
+ Enable_Blend = 1 << 5,
+ Enable_AntiAliasing = 1 << 6,
+};
+
+enum EDepthTest
+{
+ DepthTest_Greater = 1,
+ DepthTest_GreaterEqual,
+ DepthTest_Less,
+ DepthTest_LessEqual,
+ DepthTest_Equal,
+ DepthTest_NotEqual,
+ DepthTest_Always,
+};
+
+enum EStencilTest {
+ StencilTest_Always,
+ StencilTest_Never,
+ StencilTest_Less,
+ StencilTest_Equal,
+ StencilTest_NotEqual,
+ StencilTest_LessEqual,
+ StencilTest_Greater,
+ StencilTest_GreaterEqual,
+};
+
+enum EStencilOp {
+ StencilOp_Keep,
+ StencilOp_Zero,
+ StencilOp_Replace,
+ StencilOp_Incr,
+ StencilOp_IncrWrap,
+ StencilOp_Decr,
+ StencilOp_DecrWrap,
+ StencilOp_Invert,
+};
+
+enum EDeviceClear
+{
+ Clear_DepthBuffer = 1,
+ Clear_StencilBuffer = 1 << 1,
+ Clear_ColorBuffer = 1 << 2,
+};
+
+enum ECullFace
+{
+ Cull_Front = 1,
+ Cull_Back = 2,
+ Cull_None = 3,
+ Cull_All = 4,
+};
+
+enum EBlendMode
+{
+ Blend_Additive = 1,
+ Blend_Substract = 1,
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/DynamicMesh.h b/Client/Source/Graphics/DynamicMesh.h
new file mode 100644
index 0000000..94fef4d
--- /dev/null
+++ b/Client/Source/Graphics/DynamicMesh.h
@@ -0,0 +1,13 @@
+#pragma once
+#include "../Utilities/StaticInitiator.h"
+
+// g_SharedVBOĶ̬mesh
+class DynamicMesh
+{
+public:
+ DynamicMesh() {};
+ virtual ~DynamicMesh() {};
+
+ virtual void Draw() = 0;
+
+};
diff --git a/Client/Source/Graphics/DynamicVertexBuffer.cpp b/Client/Source/Graphics/DynamicVertexBuffer.cpp
new file mode 100644
index 0000000..8041e30
--- /dev/null
+++ b/Client/Source/Graphics/DynamicVertexBuffer.cpp
@@ -0,0 +1,260 @@
+#include "DynamicVertexBuffer.h"
+#include "CustomVertexLayout.h"
+
+DynamicVertexBuffer::DynamicVertexBuffer()
+{
+}
+
+DynamicVertexBuffer::~DynamicVertexBuffer()
+{
+}
+
+//------------------------------------------------------------------------------------------------------------
+// Defualt Vertex Layout
+
+//GetChunk
+//-> ReleaseChunk
+//-> DrawChunk
+
+void DynamicVertexBuffer::GetChunk(uint attrsMask, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib)
+{
+ Assert(out_vb && out_ib);
+
+ uint stride = VertexLayout::GetDynamicChunkStride(attrsMask); // data size of single vertex
+ GetChunk(stride, maxVerts, VertexLayout::GetDefaultIndexSize(), maxIndices, primitive, out_vb, out_ib);
+
+ // default layout
+ m_CurAttrMask = attrsMask;
+ m_CurStride = stride;
+}
+
+void DynamicVertexBuffer::DrawChunk()
+{
+ DefaultVertexLayout vertexArray;
+ FillDefaultVertexLayout(vertexArray);
+
+ // bind vertex attributes data
+ VertexLayout::SetupDefaultVertexLayout(vertexArray);
+
+ const void* indexPtr = m_CurIB ? 0 : (m_CurIBData.empty() ? 0 : &m_CurIBData[0]);
+
+ if (m_CurIB)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CurIB->GetHandle());
+
+ GLenum indexFormat = VertexLayout::GetDefaultIndexFormat();
+
+ switch (m_CurPrimitive)
+ {
+ case Primitive_Triangle:
+ glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ case Primitive_Line:
+ glDrawElements(GL_LINE, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ case Primitive_Point:
+ glDrawElements(GL_POINT, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ }
+
+ if (m_CurIB)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ // End draw
+ Clean();
+}
+
+void DynamicVertexBuffer::FillDefaultVertexLayout(DefaultVertexLayout& dst)
+{
+ const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0];
+ const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0;
+
+ int attrOffsets[VertexAttr_Count] = { 0 };
+ {
+ uint32 curOffset = 0;
+ for (uint idx = 0; idx < VertexAttr_Count; ++idx)
+ {
+ if (m_CurAttrMask & Mask(idx))
+ {
+ attrOffsets[idx] = curOffset;
+ curOffset += VertexLayout::GetDefaultVertexAttrSize(idx);
+ }
+ }
+ }
+
+ dst.buffer = buffer;
+
+ for (uint32 attrIdx = 0; attrIdx < VertexAttr_Count; ++attrIdx)
+ {
+ if (m_CurAttrMask & Mask(attrIdx))
+ {
+ dst.attributes[attrIdx].pointer = basepointer + attrOffsets[attrIdx];
+ dst.attributes[attrIdx].componentFormat = VertexLayout::GetDefaultShaderChannelFormat(attrIdx);
+ dst.attributes[attrIdx].componentNum = VertexLayout::GetDefaultShaderChannelDimension(attrIdx);
+ dst.attributes[attrIdx].stride = m_CurStride;
+
+ dst.enableMask |= Mask(attrIdx);
+ }
+ }
+}
+
+//------------------------------------------------------------------------------------------------------------
+// Custom Vertex Layout
+
+// buffersizeΪݾvbopinned memory
+void DynamicVertexBuffer::GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib)
+{
+ Assert(out_vb && out_ib);
+
+ m_CurStride = sizePerVert;
+ uint vbufferSize = sizePerVert * maxVerts;
+ uint ibufferSize = sizePerIndex * maxIndices;
+
+ const bool mapVertexBuffer = vbufferSize >= kDataBufferThreshold;
+ const bool mapIndexBuffer = ibufferSize >= kDataBufferThreshold;
+
+ GLenum usage = GL_STREAM_DRAW;
+
+ GPU::DataBuffer* vertexBuffer = mapVertexBuffer ? GPU::ClaimBuffer(vbufferSize, usage) : 0;
+ GPU::DataBuffer* indexBuffer = mapIndexBuffer ? GPU::ClaimBuffer(ibufferSize, usage) : 0;
+
+ if (vertexBuffer && vertexBuffer->GetSize() < vbufferSize)
+ vertexBuffer->Restore(vbufferSize, usage);
+
+ if (indexBuffer && indexBuffer->GetSize() < ibufferSize)
+ indexBuffer->Restore(ibufferSize, usage);
+
+ if (!mapVertexBuffer && m_CurVBData.size() < vbufferSize)
+ m_CurVBData.resize(vbufferSize);
+
+ if (!mapIndexBuffer && m_CurIBData.size() < ibufferSize)
+ m_CurIBData.resize(ibufferSize);
+
+ const GLenum access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+
+ if (vertexBuffer)
+ *out_vb = vertexBuffer->MapRange(0, vbufferSize, access);
+ else
+ *out_vb = &m_CurVBData[0];
+
+ if (indexBuffer)
+ *out_ib = indexBuffer->MapRange(0, ibufferSize, access);
+ else
+ *out_ib = &m_CurIBData[0];
+
+ m_CurVB = vertexBuffer;
+ m_CurIB = indexBuffer;
+
+ m_CurPrimitive = primitive;
+}
+
+void DynamicVertexBuffer::FillCustomVertexLayout(CustomVertexLayout& dst)
+{
+ const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0];
+ const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0;
+
+ dst.buffer = buffer;
+
+ for (int i = 0; i < dst.attributes.size(); ++i)
+ {
+ int offset = dst.attributes[i].startOffset;
+ dst.attributes[i].pointer = basepointer + offset;
+ }
+}
+
+void DynamicVertexBuffer::DrawChunk(CustomVertexLayout& layout)
+{
+ const byte* basepointer = m_CurVB ? 0 : &m_CurVBData[0];
+ const GLuint buffer = m_CurVB ? m_CurVB->GetHandle() : 0;
+
+ FillCustomVertexLayout(layout);
+
+ VertexLayout::SetupCustomVertexLayout(layout);
+
+ layout.RestorePointer();
+
+ const void* indexPtr = m_CurIB ? 0 : (m_CurIBData.empty() ? 0 : &m_CurIBData[0]);
+
+ if (m_CurIB)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CurIB->GetHandle());
+
+ GLenum indexFormat = VertexLayout::GetDefaultIndexFormat();
+
+ switch (m_CurPrimitive)
+ {
+ case Primitive_Triangle:
+ glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ case Primitive_Line:
+ glDrawElements(GL_LINES, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ case Primitive_Point:
+ glDrawElements(GL_POINTS, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ }
+
+ if (m_CurIB)
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ // End draw
+ Clean();
+}
+
+//------------------------------------------------------------------------------------------------------------
+// Both Default and Custom Vertex Layout
+
+void DynamicVertexBuffer::ReleaseChunk(int actualVerts, int actualIndices)
+{
+ int actualVBufferSize = m_CurStride * actualVerts;
+ int actualIBufferSize = VertexLayout::GetDefaultIndexSize() * actualIndices;
+
+ const GLenum usage = GL_STREAM_DRAW;
+
+ if (m_CurVB)
+ {
+ m_CurVB->FlushMapedRange(0, actualVBufferSize);
+ m_CurVB->UnMap();
+ }
+ else if (actualVBufferSize >= kDataBufferThreshold)
+ {
+ m_CurVB = GPU::ClaimBuffer(actualVBufferSize, usage);
+ m_CurVB->RestoreWithData(actualVBufferSize, usage, &m_CurVBData[0]);
+ }
+
+ if (m_CurIB)
+ {
+ m_CurIB->FlushMapedRange(0, actualIBufferSize);
+ m_CurIB->UnMap();
+ }
+ else if (actualIBufferSize >= kDataBufferThreshold)
+ {
+ m_CurIB = GPU::ClaimBuffer(0, usage);
+ m_CurIB->RestoreWithData(0, usage, &m_CurIBData[0]);
+ }
+
+ m_CurVertexCount = actualVerts;
+ m_CurIndexCount = actualIndices;
+}
+
+void DynamicVertexBuffer::Clean()
+{
+ if (m_CurVB)
+ {
+ GPU::ReleaseBuffer(m_CurVB);
+ m_CurVB = 0;
+ }
+
+ if (m_CurIB)
+ {
+ GPU::ReleaseBuffer(m_CurIB);
+ m_CurIB = 0;
+ }
+
+ m_CurPrimitive = Primitive_Triangle;
+ m_CurAttrMask = 0;
+ m_CurStride = 0;
+ m_CurVertexCount = 0;
+ m_CurIndexCount = 0;
+
+ m_CurVBData.clear();
+ m_CurIBData.clear();
+}
diff --git a/Client/Source/Graphics/DynamicVertexBuffer.h b/Client/Source/Graphics/DynamicVertexBuffer.h
new file mode 100644
index 0000000..ad65d80
--- /dev/null
+++ b/Client/Source/Graphics/DynamicVertexBuffer.h
@@ -0,0 +1,54 @@
+#pragma once
+#include <vector>
+
+#include "../Utilities/UtilMacros.h"
+
+#include "OpenGL.h"
+#include "GPUDataBuffer.h"
+#include "DefaultVertexLayout.h"
+#include "CustomVertexLayout.h"
+#include "Primitive.h"
+
+// ̬VBO
+class DynamicVertexBuffer
+{
+public:
+ DynamicVertexBuffer();
+ ~DynamicVertexBuffer();
+
+ // default layout
+ void GetChunk(uint attrs, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib);
+ void DrawChunk();
+
+ // custom layout
+ void GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib);
+ void DrawChunk(CustomVertexLayout& layout);
+
+ // common
+ void ReleaseChunk(int actualVerts, int actualIndices);
+
+private:
+
+ void FillCustomVertexLayout(CustomVertexLayout& dst);
+ void FillDefaultVertexLayout(DefaultVertexLayout& dst);
+
+ void Clean();
+
+ // ݴССƣڴݣglBufferData
+ static const int kDataBufferThreshold = 1024;
+
+ GPU::DataBuffer *m_CurVB;
+ GPU::DataBuffer *m_CurIB;
+
+ std::vector<byte> m_CurVBData;
+ std::vector<uint16> m_CurIBData;
+
+ EPrimitive m_CurPrimitive;
+
+ uint m_CurAttrMask; // default layout only
+ uint m_CurStride; // default layout only
+
+ uint m_CurVertexCount;
+ uint m_CurIndexCount;
+
+}; \ No newline at end of file
diff --git a/Client/Source/Graphics/FrameBuffer.cpp b/Client/Source/Graphics/FrameBuffer.cpp
new file mode 100644
index 0000000..af4d831
--- /dev/null
+++ b/Client/Source/Graphics/FrameBuffer.cpp
@@ -0,0 +1,12 @@
+#include "FrameBuffer.h"
+
+// Щ汾OpenGLְ֧󶨶RT
+bool FrameBuffer::BindRenderTexture(RenderTexture* rt, int location /* = 0 */)
+{
+ return false;
+}
+
+bool FrameBuffer::Blit(FrameBuffer* target)
+{
+ return false;
+}
diff --git a/Client/Source/Graphics/FrameBuffer.h b/Client/Source/Graphics/FrameBuffer.h
new file mode 100644
index 0000000..4b9104b
--- /dev/null
+++ b/Client/Source/Graphics/FrameBuffer.h
@@ -0,0 +1,35 @@
+#ifndef FRAME_BUFFER_H
+#define FRAME_BUFFER_H
+
+#include "OpenGL.h"
+#include "RenderTexture.h"
+
+// Fboа󶨵texturerenderbuffertargetǿɶдGL_FRAMEBUFFER
+class FrameBuffer
+{
+public:
+ enum FrameBufferUsage
+ {
+ FrameBufferUsage_None = 0,
+ FrameBufferUsage_Depth = 1,
+ FrameBufferUsage_Stencil = 2,
+ FrameBufferUsage_DepthStencil = 3,
+ };
+
+ FrameBuffer(FrameBufferUsage usage, int width, int height);
+ ~FrameBuffer();
+
+ bool Blit(FrameBuffer* target);
+
+ bool BindRenderTexture(RenderTexture* rt, int location = 0);
+
+ GET(int, Width, m_Width);
+ GET(int, Height, m_Height);
+
+private:
+ int m_Width, m_Height;
+ FrameBufferUsage m_Usage;
+
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/GPUDataBuffer.cpp b/Client/Source/Graphics/GPUDataBuffer.cpp
new file mode 100644
index 0000000..f5149d9
--- /dev/null
+++ b/Client/Source/Graphics/GPUDataBuffer.cpp
@@ -0,0 +1,207 @@
+#include <math.h>
+
+#include "GPUDataBuffer.h"
+
+namespace GPU
+{
+
+ // ޸bufferҪ󶨵ĿϣGetHandle()󶨵Ŀ
+ // GL_COPY_READ_BUFFER
+ static const GLenum kBufferTarget = GL_COPY_WRITE_BUFFER;
+
+ DataBuffer::DataBuffer()
+ {
+ glGenBuffers(1, &m_Handle);
+ m_Size = 0;
+ }
+
+ DataBuffer::~DataBuffer()
+ {
+ glDeleteBuffers(1, &m_Handle);
+ }
+
+ void DataBuffer::Restore(int size, GLenum usage)
+ {
+ RestoreWithData(size, usage, 0);
+ }
+
+ void DataBuffer::RestoreWithData(int size, GLenum usage, const void* data)
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ glBufferData(kBufferTarget, size, data, usage);
+ glBindBuffer(kBufferTarget, 0);
+ m_Size = size;
+ m_Usage = usage;
+ }
+
+ // glBufferSubData
+ // glMapBuffer
+ // glMapBufferRange (best one)
+
+ void DataBuffer::Upload(int offset, int size, const void* data)
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ glBufferSubData(kBufferTarget, offset, size, data);
+ glBindBuffer(kBufferTarget, 0);
+ }
+
+ void* DataBuffer::Map(uint32 access)
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ void* ptr = glMapBuffer(kBufferTarget, access);
+ glBindBuffer(kBufferTarget, 0);
+ return ptr;
+ }
+
+ void* DataBuffer::MapRange(int offset, int size, uint32 access)
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ void* ptr = glMapBufferRange(kBufferTarget, offset, size, access);
+ glBindBuffer(kBufferTarget, 0);
+ return ptr;
+ }
+
+ void DataBuffer::FlushMapedRange(int offset, int size)
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ glFlushMappedBufferRange(kBufferTarget, offset, size);
+ glBindBuffer(kBufferTarget, 0);
+ }
+
+ void DataBuffer::UnMap()
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ glUnmapBuffer(kBufferTarget);
+ glBindBuffer(kBufferTarget, 0);
+ }
+
+ void DataBuffer::Orphan()
+ {
+ glBindBuffer(kBufferTarget, m_Handle);
+ glBufferData(kBufferTarget, 0, 0, GL_STREAM_DRAW);
+ glBindBuffer(kBufferTarget, 0);
+ }
+
+//---------------------------------------------------------------------------------------
+
+ static bool IsBufferPoolCreated = false;
+
+ BufferPool::BufferPool()
+ :m_LiveBuffers()
+ {
+ Assert(!IsBufferPoolCreated);
+ IsBufferPoolCreated = true;
+ }
+
+ BufferPool::~BufferPool()
+ {
+ }
+
+ static const float kBufferAllocateWeight = 10.0f; //! Default weight for buffer allocation from scratch.
+ static const float kBufferSizeWeightFactor = 1.f / 8096.f; //!< Weight factor for size difference.
+ static const float kBufferUsageDiffWeight = 8.f; //!< Weight factor for usage difference.
+
+ static int ComputeBufferWeight(DataBuffer* buffer, int desiredSize, GLenum desiredUsage)
+ {
+ const int bufferSize = buffer->GetSize();
+ const GLenum bufferUsage = buffer->GetUsage();
+
+ if (bufferSize == 0)
+ return kBufferAllocateWeight;
+
+ const int sizeDiff = std::abs(bufferSize - desiredSize);
+
+ return float(sizeDiff)*kBufferSizeWeightFactor + ((bufferUsage != desiredUsage) ? kBufferUsageDiffWeight : 0.f);
+ }
+
+ DataBuffer* BufferPool::ClaimBuffer(int size, GLenum usage)
+ {
+ const float maxWeight = kBufferAllocateWeight;
+ const int maxCandidates = 5; // Number of potential candidates to consider actually.
+
+ const int sizeClass = GetSizeClass(size);
+ int numCandidates = 0; // Number of potential candidates considered
+ int bestBufferNdx = -1;
+ float bestWeight = std::numeric_limits<float>::infinity();
+
+ for (int idx = 0; idx < m_LiveBuffers[sizeClass].size(); ++idx)
+ {
+ DataBuffer* buffer = m_LiveBuffers[sizeClass][idx];
+ const float weight = ComputeBufferWeight(buffer, size, usage);
+
+ if (weight < maxWeight && weight < bestWeight)
+ {
+ bestWeight = weight;
+ bestBufferNdx = idx;
+ ++numCandidates;
+ }
+
+ if (numCandidates >= maxCandidates)
+ break; // Do not try other buffers, sorry.
+ }
+
+ if (bestBufferNdx >= 0)
+ {
+ DataBuffer* selectedBuffer = m_LiveBuffers[sizeClass][bestBufferNdx];
+
+ if (bestBufferNdx + 1 != m_LiveBuffers[sizeClass].size())
+ std::swap(m_LiveBuffers[sizeClass][bestBufferNdx], m_LiveBuffers[sizeClass].back());
+ m_LiveBuffers[sizeClass].pop_back();
+
+ return selectedBuffer;
+ }
+ else
+ return new DataBuffer();
+
+ }
+
+ void BufferPool::ReleaseBuffer(DataBuffer* buffer)
+ {
+ InsertToLive(buffer);
+ }
+
+ void BufferPool::OnEndFrame()
+ {
+ UpdatePendingBuffersArray();
+ }
+
+ void BufferPool::UpdatePendingBuffersArray()
+ {
+ }
+
+ void BufferPool::InsertToLive(DataBuffer* buffer)
+ {
+ const int bufferSize = buffer->GetSize();
+ const int sizeClass = GetSizeClass(bufferSize);
+
+ m_LiveBuffers[sizeClass].push_back(buffer);
+ }
+
+ uint BufferPool::GetSizeClass(uint bufferSize)
+ {
+ for (int idx = 0; idx < kSizeClassCount; ++idx)
+ {
+ if (bufferSize < GetSizeClassLimit(idx))
+ return idx;
+ }
+ Assert(false);
+ return 0;
+ }
+
+ DataBuffer* ClaimBuffer(int size, GLenum usage)
+ {
+ return BufferPool::Instance()->ClaimBuffer(size, usage);
+ }
+
+ void ReleaseBuffer(DataBuffer* buffer)
+ {
+ BufferPool::Instance()->ReleaseBuffer(buffer);
+ }
+
+ int BufferPool::GetSizeClassLimit(int classNdx)
+ {
+ // (0, 2^10] 2^11 2^12 2^13 2^14 2^15 INT_MAX
+ return classNdx + 1 < kSizeClassCount ? (1 << (classNdx*kSizeClassStepLog2 + kSizeClassBaseLog2)) : INT_MAX;
+ }
+
+}
diff --git a/Client/Source/Graphics/GPUDataBuffer.h b/Client/Source/Graphics/GPUDataBuffer.h
new file mode 100644
index 0000000..3d24514
--- /dev/null
+++ b/Client/Source/Graphics/GPUDataBuffer.h
@@ -0,0 +1,75 @@
+#ifndef GPU_DATABUFFER_H
+#define GPU_DATABUFFER_H
+
+#include <vector>
+
+#include "../Utilities/Type.h"
+#include "../Utilities/Singleton.h"
+#include "../Utilities/UtilMacros.h"
+#include "../Utilities/Assert.h"
+#include "OpenGL.h"
+
+namespace GPU
+{
+
+ class DataBuffer
+ {
+ public:
+ DataBuffer();
+ ~DataBuffer();
+
+ void Upload(int offset, int size, const void* data);
+ void* Map(uint32 access);
+ void* MapRange(int offset, int size, uint32 access); //
+ void FlushMapedRange(int offset, int size);
+
+ void UnMap();
+
+ void Orphan();
+
+ void Restore(int size, GLenum usage);
+ void RestoreWithData(int size, GLenum usage, const void* data);
+
+ GET(int, Size, m_Size);
+ GET(GLenum, Usage, m_Usage);
+ GET(GLuint, Handle, m_Handle);
+
+ private:
+ friend class BufferPool;
+
+ GLuint m_Handle;
+ int m_Size;
+ GLenum m_Usage;
+ };
+
+ class BufferPool : public Singleton<BufferPool>
+ {
+ public:
+ BufferPool();
+ ~BufferPool();
+
+ DataBuffer* ClaimBuffer(int size, GLenum usage);
+ void ReleaseBuffer(DataBuffer* buffer);
+
+ void OnEndFrame();
+
+ private:
+ static const int kSizeClassBaseLog2 = 10;
+ static const int kSizeClassStepLog2 = 1;
+ static const int kSizeClassCount = 7;
+
+ int GetSizeClassLimit(int classNdx);
+ void UpdatePendingBuffersArray();
+ void InsertToLive(DataBuffer* buffer);
+ uint GetSizeClass(uint bufferSize);
+
+ std::vector<DataBuffer*> m_LiveBuffers[kSizeClassCount];
+
+ };
+
+ DataBuffer* ClaimBuffer(int size = 0, GLenum usage = GL_ARRAY_BUFFER);
+ void ReleaseBuffer(DataBuffer* buffer);
+
+}
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/GfxDevice.cpp b/Client/Source/Graphics/GfxDevice.cpp
new file mode 100644
index 0000000..231ee71
--- /dev/null
+++ b/Client/Source/Graphics/GfxDevice.cpp
@@ -0,0 +1,169 @@
+#include <vector>
+#include "GfxDevice.h"
+#include "../Math/Math.h"
+
+static bool deviceInited = false;
+//
+//static const std::vector<byte> s_AvailableTextureUnitPreset = {0,1,2,3,4,5,6,7}; // ֧8ͼ
+//static std::vector<byte> s_TextureUnitBucket = s_AvailableTextureUnitPreset;
+
+static const int kMaxAvailableTextureUnitCount = 8; // ֧8ͼ
+static int s_CurAvailableTextureUnit = 0;
+
+static int ClaimTextureUnit()
+{
+ int unit = s_CurAvailableTextureUnit;
+ s_CurAvailableTextureUnit = (s_CurAvailableTextureUnit + 1) % kMaxAvailableTextureUnitCount;
+ return unit;
+}
+
+GfxDevice g_GfxDevice;
+
+GfxDevice::GfxDevice()
+{
+ Assert(!deviceInited);
+ deviceInited = true;
+}
+
+GfxDevice::~GfxDevice()
+{
+}
+
+void GfxDevice::Initialize(GfxDeviceSetting setting)
+{
+}
+
+void GfxDevice::Enable(EDeviceEnable enabled)
+{
+
+}
+
+void GfxDevice::Disable(EDeviceEnable enabled)
+{
+
+}
+
+void GfxDevice::IsEnable(uint flag)
+{
+
+}
+
+void GfxDevice::SetDepthTest(EDepthTest testing)
+{
+
+}
+
+void GfxDevice::SetCullFace(ECullFace face)
+{
+
+}
+
+void GfxDevice::SetStencilMask(byte stencilMask)
+{
+
+}
+
+void GfxDevice::SetStencilOp(EStencilOp op)
+{
+
+}
+
+void GfxDevice::SetAntiAliasing(int level /*= 0*/)
+{
+
+}
+
+void GfxDevice::Clear(int clearFlag)
+{
+
+}
+
+void GfxDevice::UseShader(Shader* shader, int idx)
+{
+ if (shader == NULL)
+ return;
+
+ GLuint id = shader->GetID();
+ if (id == 0)
+ return;
+
+ glUseProgram(id);
+
+ shader->ExecuteCommand();
+
+ m_Shader.shader = shader;
+}
+
+void GfxDevice::UnuseShader()
+{
+ if (m_Shader)
+ {
+ m_Shader.shader = NULL;
+ }
+ glUseProgram(0);
+}
+
+void GfxDevice::SetUniformVec2(const char* name, Vector2f vec2)
+{
+ if (!m_Shader)
+ return;
+ GLint loc = glGetUniformLocation(m_Shader.GetID(), name);
+ glUniform2f(loc, vec2.x, vec2.y);
+}
+
+void GfxDevice::SetUniformVec3(const char* name, Vector3f vec3)
+{
+ if (!m_Shader)
+ return;
+ GLint loc = glGetUniformLocation(m_Shader.GetID(), name);
+ glUniform3f(loc, vec3.x, vec3.y, vec3.z);
+}
+
+void GfxDevice::SetUniformVec4(const char* name, Vector4f vec4)
+{
+ if (!m_Shader)
+ return;
+ GLint loc = glGetUniformLocation(m_Shader.GetID(), name);
+ glUniform4f(loc, vec4.x, vec4.y, vec4.z, vec4.w);
+}
+
+void GfxDevice::SetUniformMat4(const char* name, Matrix44 mat4)
+{
+ if (!m_Shader)
+ return;
+ GLint loc = glGetUniformLocation(m_Shader.GetID(), name);
+ glUniformMatrix4fv(loc, 1, GL_TRUE, &mat4.m[0][0]);
+}
+
+void GfxDevice::SetUniformTexture(const char* name, Texture* texture)
+{
+ int texUnit = ClaimTextureUnit();
+ glActiveTexture(GL_TEXTURE0 + texUnit);
+ glBindTexture(GL_TEXTURE_2D, texture->GetGpuID());
+
+ GLint loc = glGetUniformLocation(m_Shader.GetID(), name);
+ glUniform1i(loc, texUnit);
+}
+
+void GfxDevice::BeginFrame()
+{
+ m_IsInsideFrame = true;
+
+}
+
+void GfxDevice::EndFrame()
+{
+ //GPU::BufferPool::Instance()->OnEndFrame();
+
+ m_IsInsideFrame = false;
+}
+
+void GfxDevice::PresentFrame()
+{
+// swap buffers
+}
+
+bool GfxDevice::IsInsideFrame()
+{
+ return m_IsInsideFrame;
+}
diff --git a/Client/Source/Graphics/GfxDevice.h b/Client/Source/Graphics/GfxDevice.h
new file mode 100644
index 0000000..d81d574
--- /dev/null
+++ b/Client/Source/Graphics/GfxDevice.h
@@ -0,0 +1,109 @@
+#ifndef DEVICE_H
+#define DEVICE_H
+#include "../Math/Math.h"
+
+#include "../Utilities/Type.h"
+#include "../Utilities/Assert.h"
+#include "../Graphics/Shader.h"
+#include "../Math/Vector2.hpp"
+#include "../Math/Vector3.hpp"
+#include "../Math/Vector4.hpp"
+#include "../Math/Matrix44.h"
+
+#include "Shader.h"
+#include "Texture.h"
+#include "DeviceDefine.h"
+#include "VertexBuffer.h"
+#include "DynamicVertexBuffer.h"
+#include "Color.h"
+
+struct GfxDeviceSetting
+{
+ ETextureFilterMode filterMode; // Ĭϵͼģʽ
+ ETextureWrapMode wrapMode; // Ĭϵͼƽģʽ
+};
+
+// ǰ󶨵shader
+struct ShaderState
+{
+ Shader* shader;
+ operator bool()
+ {
+ return shader != NULL;
+ }
+ GLuint GetID() {
+ if (shader == nullptr)
+ return 0;
+ GLint id = shader->GetID();
+ return id;
+ }
+};
+
+// ȾAPIķװ
+class GfxDevice
+{
+public:
+ GfxDevice();
+ ~GfxDevice();
+
+ void Initialize(GfxDeviceSetting setting);
+
+ void Enable(EDeviceEnable enabled);
+ void Disable(EDeviceEnable enabled);
+ void IsEnable(uint flag);
+
+ void SetDepthTest(EDepthTest testing);
+ void SetCullFace(ECullFace face);
+ void SetStencilMask(byte stencilMask);
+ void SetStencilOp(EStencilOp op);
+
+ void SetAntiAliasing(int level = 0);
+
+ void Clear(int clearFlag);
+
+ void UseShader(Shader* shader, int idx);
+ void UnuseShader();
+ void SetUniformVec2(const char* name, Vector2f vec2);
+ void SetUniformVec3(const char* name, Vector3f vec3);
+ void SetUniformVec4(const char* name, Vector4f vec4);
+ void SetUniformMat4(const char* name, Matrix44 mat4);
+ void SetUniformTexture(const char* name, Texture* texture);
+
+ void BeginFrame();
+ void EndFrame();
+ void PresentFrame();
+
+ bool IsInsideFrame();
+
+ DynamicVertexBuffer* GetSharedVBO() { return &m_DynamicVBO; }
+
+ GET_SET(Color, ClearColor, m_ClearColor);
+ GET_SET(ETextureFilterMode, DefaultFilterMode, m_DefaultFilterMode);
+ GET_SET(ETextureWrapMode, DefaultWrapMode, m_DefaultWrapMode);
+
+private:
+ bool m_IsInsideFrame;
+
+ // Ⱦ״̬
+ uint m_EnableFlag;
+ Color m_ClearColor;
+ EDepthTest m_DepthTest;
+ EStencilTest m_StencilTest;
+ EStencilOp m_StencilOp;
+ byte m_StencilMask;
+
+ ShaderState m_Shader; // ǰ󶨵shader
+
+ // ͼĬ
+ ETextureFilterMode m_DefaultFilterMode;
+ ETextureWrapMode m_DefaultWrapMode;
+
+ DynamicVertexBuffer m_DynamicVBO; // VBOȾ
+
+};
+
+extern GfxDevice g_GfxDevice;
+
+#define g_SharedVBO (*g_GfxDevice.GetSharedVBO())
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/GlyphAtlas.cpp b/Client/Source/Graphics/GlyphAtlas.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Graphics/GlyphAtlas.cpp
diff --git a/Client/Source/Graphics/GlyphAtlas.h b/Client/Source/Graphics/GlyphAtlas.h
new file mode 100644
index 0000000..b0ab858
--- /dev/null
+++ b/Client/Source/Graphics/GlyphAtlas.h
@@ -0,0 +1,6 @@
+#ifndef TEXT_ATLAS_H
+#define TEXT_ATLAS_H
+
+
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/ImageData.cpp b/Client/Source/Graphics/ImageData.cpp
new file mode 100644
index 0000000..8e2e4bf
--- /dev/null
+++ b/Client/Source/Graphics/ImageData.cpp
@@ -0,0 +1,2 @@
+#include "ImageData.h"
+
diff --git a/Client/Source/Graphics/ImageData.h b/Client/Source/Graphics/ImageData.h
new file mode 100644
index 0000000..9ebc738
--- /dev/null
+++ b/Client/Source/Graphics/ImageData.h
@@ -0,0 +1,39 @@
+#ifndef IMAGE_DATA_H
+#define IMAGE_DATA_H
+
+#include <vector>
+
+enum EPixelFormat
+{
+ PixelFormat_RGBA,
+ PixelFormat_RGB,
+ PixelFormat_R,
+ PixelFormat_RG,
+ PixelFormat_BGR,
+ PixelFormat_BGRA
+};
+
+enum EPixelElementType
+{
+ PixelType_UNSIGNED_BYTE,
+ PixelType_UNSIGNED_INT,
+ PixelType_BYTE,
+ PixelType_INT,
+ PixelType_FLOAT,
+};
+
+// ͼƬ
+class ImageData
+{
+public:
+ ImageData()
+ {
+ }
+
+ void* pixels; // ݣʽͲο http://docs.gl/gl3/glTexImage2D pixel dataformattype
+ EPixelFormat format;
+ EPixelElementType type;
+ int width, height;
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/OpenGL.cpp b/Client/Source/Graphics/OpenGL.cpp
new file mode 100644
index 0000000..9ed2e50
--- /dev/null
+++ b/Client/Source/Graphics/OpenGL.cpp
@@ -0,0 +1,7 @@
+#include "OpenGL.h"
+
+#pragma comment(lib, "opengl32.lib")
+
+std::string g_sharedGLErrorMsg = "";
+
+
diff --git a/Client/Source/Graphics/OpenGL.h b/Client/Source/Graphics/OpenGL.h
new file mode 100644
index 0000000..d93fb5a
--- /dev/null
+++ b/Client/Source/Graphics/OpenGL.h
@@ -0,0 +1,41 @@
+#ifndef OPENGL_H
+#define OPENGL_H
+
+#include "glad/glad.h"
+#include <string>
+#include <exception>
+
+//http://docs.gl/gl3/glClear
+
+#define CheckGLError(action)\
+if(true){ \
+ GLenum error; \
+ while ((error = glGetError()) != GL_NO_ERROR) { \
+ action \
+ } \
+}
+
+#define WipeGLError() \
+if(true){\
+ GLenum error; \
+ while ((error = glGetError()) != GL_NO_ERROR) { \
+ throw GLException(error); \
+ } \
+}
+
+extern std::string g_sharedGLErrorMsg;
+
+class GLException : public std::exception
+{
+public:
+ GLException(const char* what)
+ : std::exception(what)
+ {}
+ GLException(int glError)
+ {
+ g_sharedGLErrorMsg = std::to_string(glError);
+ std::exception(g_sharedGLErrorMsg.c_str());
+ }
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/Point.cpp b/Client/Source/Graphics/Point.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Graphics/Point.cpp
diff --git a/Client/Source/Graphics/Point.h b/Client/Source/Graphics/Point.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Graphics/Point.h
diff --git a/Client/Source/Graphics/PolyLine.cpp b/Client/Source/Graphics/PolyLine.cpp
new file mode 100644
index 0000000..911b3e5
--- /dev/null
+++ b/Client/Source/Graphics/PolyLine.cpp
@@ -0,0 +1,9 @@
+#include "PolyLine.h"
+#include "Color.h"
+#include "../Math/Math.h"
+
+struct PolyLineVBOLayout
+{
+ Vector3f position;
+ Color32 color;
+};
diff --git a/Client/Source/Graphics/PolyLine.h b/Client/Source/Graphics/PolyLine.h
new file mode 100644
index 0000000..816d18e
--- /dev/null
+++ b/Client/Source/Graphics/PolyLine.h
@@ -0,0 +1,18 @@
+#ifndef POLY_LINE_H
+#define POLY_LINE_H
+
+#include "../Math/Vector3.hpp"
+
+class PolyLine
+{
+public:
+ PolyLine();
+ ~PolyLine();
+
+ void Draw();
+
+private:
+
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/Primitive.h b/Client/Source/Graphics/Primitive.h
new file mode 100644
index 0000000..6636221
--- /dev/null
+++ b/Client/Source/Graphics/Primitive.h
@@ -0,0 +1,8 @@
+#pragma once
+
+enum EPrimitive
+{
+ Primitive_Triangle = 1,
+ Primitive_Line = 2,
+ Primitive_Point = 3,
+};
diff --git a/Client/Source/Graphics/Quad.cpp b/Client/Source/Graphics/Quad.cpp
new file mode 100644
index 0000000..40c896d
--- /dev/null
+++ b/Client/Source/Graphics/Quad.cpp
@@ -0,0 +1,62 @@
+#include "../Graphics/GfxDevice.h"
+#include "../Math/Math.h"
+#include "../Math/Math.h"
+
+#include "Quad.h"
+
+struct QuadVBOLayout
+{
+ Vector3f position;
+ Vector2f uv;
+};
+
+static CustomVertexLayout layout;
+
+InitializeStaticVariables([]() {
+ VertexAttributeDescriptor POSITION = VertexAttributeDescriptor(0, 3, VertexAttrFormat_Float, sizeof(QuadVBOLayout));
+ VertexAttributeDescriptor UV = VertexAttributeDescriptor(sizeof(Vector3f), 2, VertexAttrFormat_Float, sizeof(QuadVBOLayout));
+
+ layout.attributes.push_back(POSITION);
+ layout.attributes.push_back(UV);
+});
+
+void Quad::Draw()
+{
+ const int nVerts = 4;
+ const int nIndices = 6;
+
+ float pos[] = {
+ m_Left, m_Bottom, 0, // left-bottom
+ m_Right, m_Bottom, 0, // right-bottom
+ m_Right, m_Top, 0, // right-top
+ m_Left, m_Top, 0, // top-left
+ };
+ float uv[] = {
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1,
+ };
+ int indices[] = {
+ 0, 1, 3, // right-top
+ 1, 2, 3, // left-bottom
+ };
+
+ uint8* vb;
+ uint16* ib;
+
+ g_SharedVBO.GetChunk(sizeof(QuadVBOLayout), sizeof(uint16), 4, 6, Primitive_Triangle, (void**)&vb, (void**)&ib);
+
+ QuadVBOLayout* dst = (QuadVBOLayout*)vb;
+ for (int i = 0; i < nVerts; ++i)
+ {
+ dst[i].position.Set(pos[3 * i], pos[3 * i + 1], pos[3 * i + 2]);
+ dst[i].uv.Set(uv[2 * i], uv[2 * i + 1]);
+ }
+
+ for (int i = 0; i < nIndices; ++i)
+ ib[i] = indices[i];
+
+ g_SharedVBO.ReleaseChunk(4, 6);
+ g_SharedVBO.DrawChunk(layout);
+}
diff --git a/Client/Source/Graphics/Quad.h b/Client/Source/Graphics/Quad.h
new file mode 100644
index 0000000..ee6c5be
--- /dev/null
+++ b/Client/Source/Graphics/Quad.h
@@ -0,0 +1,26 @@
+#ifndef QUAD_H
+#define QUAD_H
+
+#include "../Utilities/UtilMacros.h"
+#include "DynamicMesh.h"
+
+class Quad : public DynamicMesh
+{
+public:
+ Quad(float l, float r, float t, float b);
+
+ void Set(float l, float r, float t, float b);
+
+ GET_SET(float, Left, m_Left);
+ GET_SET(float, Right, m_Right);
+ GET_SET(float, Top, m_Top);
+ GET_SET(float, Bottom, m_Bottom);
+
+ void Draw() override;
+
+private:
+ float m_Left, m_Right, m_Top, m_Bottom;
+
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/RenderCommands.cpp b/Client/Source/Graphics/RenderCommands.cpp
new file mode 100644
index 0000000..336bf20
--- /dev/null
+++ b/Client/Source/Graphics/RenderCommands.cpp
@@ -0,0 +1,9 @@
+#include "RenderCommands.h"
+
+void ReleaseRenderCommandGroup(RenderCommandGroup& group)
+{
+ for (int i = 0; i < group.size(); ++i)
+ {
+ delete group[i];
+ }
+}
diff --git a/Client/Source/Graphics/RenderCommands.h b/Client/Source/Graphics/RenderCommands.h
new file mode 100644
index 0000000..f66b4e2
--- /dev/null
+++ b/Client/Source/Graphics/RenderCommands.h
@@ -0,0 +1,164 @@
+#pragma once
+#include "OpenGL.h"
+#include <vector>
+
+struct RenderCommand
+{
+ virtual void Execute() = 0;
+};
+
+typedef std::vector<RenderCommand*> RenderCommandGroup;
+void ReleaseRenderCommandGroup(RenderCommandGroup& group);
+
+// Cull Off|Front|Back|Both
+struct Cmd_Cull : RenderCommand
+{
+ enum ECullFace {
+ Cull_Disable,
+ Cull_Front,
+ Cull_Back,
+ Cull_Both,
+ };
+
+ ECullFace cull;
+
+ void Execute() override
+ {
+ if (cull == ECullFace::Cull_Disable)
+ {
+ glDisable(GL_CULL_FACE);
+ return;
+ }
+ glEnable(GL_CULL_FACE);
+ switch (cull)
+ {
+ case ECullFace::Cull_Front: glCullFace(GL_FRONT); break;
+ case ECullFace::Cull_Back: glCullFace(GL_BACK); break;
+ case ECullFace::Cull_Both: glCullFace(GL_FRONT_AND_BACK); break;
+ }
+ }
+};
+
+// Blend Off
+// Blend <srcFac> <dstFac>
+struct Cmd_Blend : RenderCommand
+{
+ enum EBlend
+ {
+ Blend_Zero, // 0
+ Blend_One, // 1
+ Blend_Src_Color, // 源颜色向量C¯source
+ Blend_One_Minus_Src_Color, // 1−C¯source
+ Blend_Dst_Color, // 目标颜色向量C¯destination
+ Blend_One_Minus_Dst_Color, // 1−C¯destination
+ Blend_Src_Alpha, // C¯source的alpha值
+ Blend_One_Minus_Src_Alpha, // 1− C¯source的alpha值
+ Blend_Dst_Alpha, // C¯destination的alpha值
+ Blend_One_Minus_Dst_Alpha, // 1− C¯destination的alpha值
+ Blend_Constant_Color, // 常颜色向量C¯constant
+ Blend_One_Minus_Constant_Color, // 1−C¯constant
+ Blend_Constant_Alpha, // C¯constant的alpha值
+ Blend_One_Minus_Constant_Alpha, // 1− C¯constant的alpha值
+ };
+
+ bool enable;
+ EBlend srcFac;
+ EBlend dstFac;
+
+ void Execute() override
+ {
+ if (!enable)
+ glDisable(GL_BLEND);
+ glEnable(GL_BLEND);
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+ GLenum src, dst;
+ switch (srcFac)
+ {
+ case EBlend::Blend_Zero: src = GL_ZERO; break;
+ case EBlend::Blend_One: src = GL_ONE; break;
+ case EBlend::Blend_Src_Color: src = GL_SRC_COLOR; break;
+ case EBlend::Blend_One_Minus_Src_Color: src = GL_ONE_MINUS_SRC_COLOR; break;
+ case EBlend::Blend_Dst_Color: src = GL_DST_COLOR; break;
+ case EBlend::Blend_One_Minus_Dst_Color: src = GL_ONE_MINUS_DST_COLOR; break;
+ case EBlend::Blend_Src_Alpha: src = GL_SRC_ALPHA; break;
+ case EBlend::Blend_One_Minus_Src_Alpha: src = GL_ONE_MINUS_SRC_ALPHA; break;
+ case EBlend::Blend_Dst_Alpha: src = GL_DST_ALPHA; break;
+ case EBlend::Blend_One_Minus_Dst_Alpha: src = GL_ONE_MINUS_DST_ALPHA; break;
+ case EBlend::Blend_Constant_Color: src = GL_CONSTANT_COLOR; break;
+ case EBlend::Blend_One_Minus_Constant_Color: src = GL_ONE_MINUS_CONSTANT_COLOR; break;
+ case EBlend::Blend_Constant_Alpha: src = GL_CONSTANT_ALPHA; break;
+ case EBlend::Blend_One_Minus_Constant_Alpha: src = GL_ONE_MINUS_CONSTANT_ALPHA; break;
+ }
+ switch (dstFac)
+ {
+ case EBlend::Blend_Zero: dst = GL_ZERO; break;
+ case EBlend::Blend_One: dst = GL_ONE; break;
+ case EBlend::Blend_Src_Color: dst = GL_SRC_COLOR; break;
+ case EBlend::Blend_One_Minus_Src_Color: dst = GL_ONE_MINUS_SRC_COLOR; break;
+ case EBlend::Blend_Dst_Color: dst = GL_DST_COLOR; break;
+ case EBlend::Blend_One_Minus_Dst_Color: dst = GL_ONE_MINUS_DST_COLOR; break;
+ case EBlend::Blend_Src_Alpha: dst = GL_SRC_ALPHA; break;
+ case EBlend::Blend_One_Minus_Src_Alpha: dst = GL_ONE_MINUS_SRC_ALPHA; break;
+ case EBlend::Blend_Dst_Alpha: dst = GL_DST_ALPHA; break;
+ case EBlend::Blend_One_Minus_Dst_Alpha: dst = GL_ONE_MINUS_DST_ALPHA; break;
+ case EBlend::Blend_Constant_Color: dst = GL_CONSTANT_COLOR; break;
+ case EBlend::Blend_One_Minus_Constant_Color: dst = GL_ONE_MINUS_CONSTANT_COLOR; break;
+ case EBlend::Blend_Constant_Alpha: dst = GL_CONSTANT_ALPHA; break;
+ case EBlend::Blend_One_Minus_Constant_Alpha: dst = GL_ONE_MINUS_CONSTANT_ALPHA; break;
+ }
+ glBlendFunc(src, dst);
+ }
+};
+
+// DepthTest Off|<func>
+struct Cmd_DepthTest : RenderCommand
+{
+ enum EDepthTest
+ {
+ DepthTest_Off, // 不进行深度测试
+ DepthTest_Always, // 永远通过测试
+ DepthTest_Never, // 永远不通过测试
+ DepthTest_Less, // 在片段深度值小于缓冲区的深度时通过测试
+ DepthTest_Equal, // 在片段深度值等于缓冲区的深度时通过测试
+ DepthTest_Lequal, // 在片段深度值小于等于缓冲区的深度时通过测试
+ DepthTest_Greater, // 在片段深度值大于缓冲区的深度时通过测试
+ DepthTest_Notequal, // 在片段深度值不等于缓冲区的深度时通过测试
+ DepthTest_Gequal, // 在片段深度值大于等于缓冲区的深度时通过测试
+ };
+
+ EDepthTest test;
+
+ void Execute() override
+ {
+ if (test == EDepthTest::DepthTest_Off)
+ {
+ glDisable(GL_DEPTH_TEST);
+ return;
+ }
+ glEnable(GL_DEPTH_TEST);
+ switch (test)
+ {
+ case EDepthTest::DepthTest_Always: glDepthFunc(GL_ALWAYS); break;
+ case EDepthTest::DepthTest_Never: glDepthFunc(GL_NEVER); break;
+ case EDepthTest::DepthTest_Less: glDepthFunc(GL_LESS); break;
+ case EDepthTest::DepthTest_Equal: glDepthFunc(GL_EQUAL); break;
+ case EDepthTest::DepthTest_Lequal: glDepthFunc(GL_LEQUAL); break;
+ case EDepthTest::DepthTest_Greater: glDepthFunc(GL_GREATER); break;
+ case EDepthTest::DepthTest_Notequal: glDepthFunc(GL_NOTEQUAL); break;
+ case EDepthTest::DepthTest_Gequal: glDepthFunc(GL_GEQUAL); break;
+ }
+ }
+};
+
+// DepthWrite Off|On
+struct Cmd_DepthWrite : RenderCommand
+{
+ bool write;
+ void Execute() override
+ {
+ if(write)
+ glDepthMask(GL_TRUE);
+ else
+ glDepthMask(GL_FALSE);
+ }
+};
diff --git a/Client/Source/Graphics/RenderTexture.cpp b/Client/Source/Graphics/RenderTexture.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Graphics/RenderTexture.cpp
diff --git a/Client/Source/Graphics/RenderTexture.h b/Client/Source/Graphics/RenderTexture.h
new file mode 100644
index 0000000..a501f50
--- /dev/null
+++ b/Client/Source/Graphics/RenderTexture.h
@@ -0,0 +1,16 @@
+#ifndef RENDER_TEXTURE_H
+#define RENDER_TEXTURE_H
+
+#include "Texture.h"
+
+// Ⱦ
+class RenderTexture : public Texture
+{
+public:
+ RenderTexture(ETextureFormat format);
+
+};
+
+RenderTexture* CreateRenderTexture(int width, int height, ETextureFormat format);
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Graphics/Shader.cpp b/Client/Source/Graphics/Shader.cpp
new file mode 100644
index 0000000..899578b
--- /dev/null
+++ b/Client/Source/Graphics/Shader.cpp
@@ -0,0 +1,154 @@
+#include <exception>
+
+#include "../Debug/log.h"
+#include "Shader.h"
+#include "OpenGL.h"
+#include "ShaderCompiler.h"
+
+using namespace std;
+
+std::string shaderError = "";
+void checkCompileshaderErrorors(GLuint shader, std::string type)
+{
+ GLint success;
+ GLchar infoLog[1024];
+ if (type != "PROGRAM")
+ {
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
+ if (!success)
+ {
+ glGetShaderInfoLog(shader, 1024, NULL, infoLog);
+ shaderError = "ERROR::SHADER_COMPILATION_ERROR of type: " + type + "\n" + infoLog;
+ }
+ }
+ else
+ {
+ glGetProgramiv(shader, GL_LINK_STATUS, &success);
+ if (!success)
+ {
+ glGetProgramInfoLog(shader, 1024, NULL, infoLog);
+ shaderError = "ERROR::SHADER_COMPILATION_ERROR of type: " + type + "\n" + infoLog;
+ }
+ }
+ if (!success)
+ {
+ throw ShaderCompileExecption(shaderError.c_str());
+ }
+}
+
+Shader::Shader()
+{
+}
+
+Shader::Shader(std::string& glsllShader)
+{
+ // stlstringڴСֵջ䣬RAII֤ͷ
+ std::string vsh ;
+ std::string fsh ;
+ try
+ {
+ GLSLCompiler::Compile(glsllShader, vsh, fsh, m_Commands);
+ }
+ catch (GLSLCompileException& e)
+ {
+ ReleaseRenderCommandGroup(m_Commands);
+ throw ShaderCompileExecption(e.what());
+ }
+ CompileProgram(vsh.c_str(), fsh.c_str());
+}
+
+Shader::Shader(const char* vert, const char* frag)
+{
+ CompileProgram(vert, frag);
+}
+
+void Shader::CompileProgram(const char* vert, const char* frag, bool keepSrc)
+{
+ const char* vertCode = vert;
+ const char* fragCode = frag;
+ // vertex shader
+ m_VertID = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(m_VertID, 1, &vertCode, NULL);//Ϊ֧עͣȴNULL
+ glCompileShader(m_VertID);
+ checkCompileshaderErrorors(m_VertID, "VERTEX");
+ // fragment Shader
+ m_FragID = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(m_FragID, 1, &fragCode, NULL);
+ glCompileShader(m_FragID);
+ checkCompileshaderErrorors(m_FragID, "FRAGMENT");
+ // create program
+ m_ProgramID = glCreateProgram();
+ glAttachShader(m_ProgramID, m_VertID);
+ glAttachShader(m_ProgramID, m_FragID);
+ glLinkProgram(m_ProgramID);
+ checkCompileshaderErrorors(m_ProgramID, "PROGRAM");
+}
+
+Shader::~Shader()
+{
+ glDeleteProgram(m_ProgramID);
+ glDeleteShader(m_VertID);
+ glDeleteShader(m_FragID);
+}
+
+void Shader::ReCompile(std::string& vert, std::string frag)
+{
+ const char* vertCode = vert.c_str();
+ const char* fragCode = frag.c_str();
+ // vertex shader
+ glShaderSource(m_VertID, 1, &vertCode, NULL);
+ glCompileShader(m_VertID);
+ checkCompileshaderErrorors(m_VertID, "VERTEX");
+ // fragment Shader
+ glShaderSource(m_FragID, 1, &fragCode, NULL);
+ glCompileShader(m_FragID);
+ checkCompileshaderErrorors(m_FragID, "FRAGMENT");
+ // create program
+ glAttachShader(m_ProgramID, m_VertID);
+ glAttachShader(m_ProgramID, m_FragID);
+ glLinkProgram(m_ProgramID);
+ checkCompileshaderErrorors(m_FragID, "PROGRAM");
+}
+
+void Shader::ReCompileVert(std::string& vert)
+{
+ glDeleteShader(m_VertID);
+ const char* vertCode = vert.c_str();
+ // vertex shader
+ glShaderSource(m_VertID, 1, &vertCode, NULL);
+ glCompileShader(m_VertID);
+ checkCompileshaderErrorors(m_VertID, "VERTEX");
+ // create program
+ glAttachShader(m_ProgramID, m_VertID);
+ glAttachShader(m_ProgramID, m_FragID);
+ glLinkProgram(m_ProgramID);
+ checkCompileshaderErrorors(m_FragID, "PROGRAM");
+}
+
+void Shader::ReCompileFrag(std::string frag)
+{
+ glDeleteShader(m_FragID);
+ const char* fragCode = frag.c_str();
+ // fragment Shader
+ glShaderSource(m_FragID, 1, &fragCode, NULL);
+ glCompileShader(m_FragID);
+ checkCompileshaderErrorors(m_FragID, "FRAGMENT");
+ // create program
+ glAttachShader(m_ProgramID, m_VertID);
+ glAttachShader(m_ProgramID, m_FragID);
+ glLinkProgram(m_ProgramID);
+ checkCompileshaderErrorors(m_FragID, "PROGRAM");
+}
+
+bool Shader::IsValid()
+{
+ return m_ProgramID != 0;
+}
+
+void Shader::ExecuteCommand()
+{
+ for (int i = 0; i < m_Commands.size(); ++i)
+ {
+ m_Commands[i]->Execute();
+ }
+} \ No newline at end of file
diff --git a/Client/Source/Graphics/Shader.h b/Client/Source/Graphics/Shader.h
new file mode 100644
index 0000000..8d5fc0e
--- /dev/null
+++ b/Client/Source/Graphics/Shader.h
@@ -0,0 +1,47 @@
+#pragma once
+#include <string>
+#include <exception>
+#include "OpenGL.h"
+#include "../Utilities/UtilMacros.h"
+#include "../Utilities/Assert.h"
+#include "../Debug/Log.h"
+#include "RenderCommands.h"
+
+// ɫ
+class Shader
+{
+public:
+ Shader()/*throw(ShaderCompileExecption)*/;
+ Shader(std::string& glsllShader)/*throw(ShaderCompileExecption)*/;
+ Shader(const char* vert, const char* frag)/*throw(ShaderCompileExecption)*/;
+ ~Shader();
+
+ void ReCompile(std::string& vert, std::string frag)/*throw(ShaderCompileExecption)*/;
+ void ReCompileVert(std::string& vert)/*throw(ShaderCompileExecption)*/;
+ void ReCompileFrag(std::string frag)/*throw(ShaderCompileExecption)*/;
+
+ bool IsValid();
+
+ void ExecuteCommand();
+
+ GET(GLint, ID, m_ProgramID);
+
+private:
+ void CompileProgram(const char* vert, const char* frag, bool keepSrc = false);
+
+ RenderCommandGroup m_Commands; // Ⱦǰ״̬
+
+ GLint m_ProgramID;
+ GLint m_FragID;
+ GLint m_VertID;
+
+};
+
+class ShaderCompileExecption : public std::exception
+{
+public:
+ ShaderCompileExecption(const char* what)
+ : std::exception(what)
+ {
+ }
+};
diff --git a/Client/Source/Graphics/ShaderCompiler.cpp b/Client/Source/Graphics/ShaderCompiler.cpp
new file mode 100644
index 0000000..362b28e
--- /dev/null
+++ b/Client/Source/Graphics/ShaderCompiler.cpp
@@ -0,0 +1,347 @@
+#include "ShaderCompiler.h"
+#include <sstream>
+#include <algorithm>
+
+using namespace std;
+
+static const char* VSH_BEGIN = "VSH_BEGIN";
+static const char* VSH_END = "VSH_END";
+static const char* FSH_BEGIN = "FSH_BEGIN";
+static const char* FSH_END = "FSH_END";
+static const char* CMD_BEGIN = "CMD_BEGIN";
+static const char* CMD_END = "CMD_END";
+
+std::string s_CompileError = "";
+
+// GLSLΪIJ
+// * CMD_BEGIN CMD_END ֮
+// * VERTEX_SHADER_BEGIN VERTEX_SHADER_END֮Ķɫ
+// * FRAGMENT_SHADER_BEGIN FRAGMENT_SHADER_END֮Ƭɫ
+// * ֮Ĺ
+void GLSLCompiler::Compile(std::string& src, std::string& vsh, std::string& fsh, RenderCommandGroup& group)/*throw GLSLCompileException*/
+{
+#define CheckLabel(label) {\
+ int pos = src.find(label);\
+ if(pos == string::npos || !IsLabelActive(src, label)) {\
+ s_CompileError = std::string("Compile Shader Error: No ") + #label + " label";\
+ throw GLSLCompileException(s_CompileError.c_str());\
+ }}
+
+ CheckLabel(VSH_BEGIN);
+ CheckLabel(VSH_END);
+ CheckLabel(FSH_BEGIN);
+ CheckLabel(FSH_END);
+
+ vsh = GetContent(src, VSH_BEGIN, VSH_END);
+ fsh = GetContent(src, FSH_BEGIN, FSH_END);
+
+ bool hasCmd = IsLabelActive(src, CMD_BEGIN) && IsLabelActive(src, CMD_END);
+ if (hasCmd)
+ {
+ string cmd = GetContent(src, CMD_BEGIN, CMD_END);
+ if (cmd.size() > 0)
+ {
+ ParseCmd(cmd, group);
+ }
+ else
+ {
+ hasCmd = false;
+ }
+ }
+
+ string common;
+ common = TrimContent(src, VSH_BEGIN, VSH_END);
+ common = TrimContent(common, FSH_BEGIN, FSH_END);
+ if (hasCmd)
+ common = TrimContent(common, CMD_BEGIN, CMD_END);
+
+ vsh = common + vsh;
+ fsh = common + fsh;
+}
+
+std::string GLSLCompiler::GetContent(std::string& src, const char* from, const char* to)
+{
+ int begin = src.find(from);
+ int end = src.find(to);
+ if (begin == string::npos || end == string::npos)
+ {
+ return "";
+ }
+ std::string content = src.substr(begin + strlen(from), end - begin - strlen(from));
+ return content;
+}
+
+std::string GLSLCompiler::TrimContent(std::string& src, const char* from, const char* to)
+{
+ int begin = src.find(from);
+ int end = src.find(to);
+ string result = src.erase(begin, end + strlen(to) - begin);
+ return result;
+}
+
+bool GLSLCompiler::IsLabelActive(std::string& src, const char* label)
+{
+ int pos = src.find(label);
+ if (pos == string::npos)
+ return false;
+ for (int i = pos - 1; i >= 0; --i)
+ {
+ int second = i;
+ int first = i - 1;
+ if (first < 0)
+ break;
+ if (src[second] == '\n' || src[first] == '\r')
+ break;
+ if (src[first] == '/' && src[second] == '/')
+ return false;
+ }
+ return true;
+}
+
+bool GLSLCompiler::IsCommandActive(std::string& src, const char* label)
+{
+ int pos = src.find(label);
+ if (pos == string::npos)
+ return false;
+ for (int i = pos - 1; i >= 0; --i)
+ {
+ int second = i;
+ int first = i - 1;
+ if (first < 0)
+ break;
+ if (src[second] == '\n' || src[first] == '\r')
+ break;
+ if (src[first] == '/' && src[second] == '/')
+ return false;
+ }
+ return true;
+}
+
+void GLSLCompiler::ParseCmd(std::string& cmds, RenderCommandGroup& group)
+{
+ istringstream ss = istringstream(cmds);
+ string line;
+ while (getline(ss, line))
+ {
+ if(line.find('\r') != string::npos)
+ line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
+ if (IsLineCommentd(line))
+ continue;
+ int cb, ce; // cmd begin, end
+ if (!FindCmdPos(line, &cb, &ce))
+ continue;
+ string cmdName = line.substr(cb, ce - cb + 1);
+ string cmdValue = line.substr(ce + 1, line.size() - ce - 1);
+ if (cmdName == "Cull") CommandCull(cmdValue, group);
+ else if (cmdName == "Blend") CommandBlend(cmdValue, group);
+ else if (cmdName == "DepthTest") CommandDepthTest(cmdValue, group);
+ else if (cmdName == "DepthWrite") CommandDepthWrite(cmdValue, group);
+ else
+ {
+ s_CompileError = string("Unknown command " + cmdName);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ }
+}
+
+#define IsSeperator(c) (c == ' ' || c == '\r' || c == '\n' || c == /*tab*/9)
+
+// ҵڵĵһʣΪ
+bool GLSLCompiler::FindCmdPos(std::string& line, int* start, int* end)
+{
+ for (int i = 0; i < line.size(); ++i)
+ {
+ if (IsSeperator(line[i]))
+ continue;
+ *start = i;
+ for (int j = i + 1; j < line.size(); ++j)
+ {
+ if (IsSeperator(line[j]))
+ {
+ *end = j - 1;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool GLSLCompiler::IsLineCommentd(std::string& line)
+{
+ for (int i = 0; i < line.size(); ++i)
+ {
+ if (IsSeperator(line[i]))
+ continue;
+ int first = i;
+ int second = i + 1;
+ if (second == line.size())
+ return false;
+ if (line[first] == '/' && line[second] == '/')
+ return true;
+ return false;
+ }
+ return false;
+}
+
+#define MAX_PARAM 2
+
+void GLSLCompiler::CommandCull(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[1];
+ GetParams("Cull", p, params, 1);
+
+ Cmd_Cull* pCull = new Cmd_Cull();
+ Cmd_Cull& cull = *pCull;
+ if (params[0] == "Off") cull.cull = Cmd_Cull::Cull_Disable;
+ else if (params[0] == "Front") cull.cull = Cmd_Cull::Cull_Front;
+ else if (params[0] == "Back") cull.cull = Cmd_Cull::Cull_Back;
+ else if (params[0] == "Both") cull.cull = Cmd_Cull::Cull_Both;
+ else
+ {
+ delete pCull;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Cull: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ group.push_back(pCull);
+}
+
+void GLSLCompiler::CommandBlend(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[2];
+ GetParams("Blend", p, params, 2);
+
+ Cmd_Blend* pblend = new Cmd_Blend();
+ Cmd_Blend& blend = *pblend;
+ if (params[0] == "Off")
+ {
+ blend.enable = false;
+ group.push_back(pblend);
+ return;
+ }
+
+ blend.enable = true;
+
+ if (params[0] == "Zero") blend.srcFac = Cmd_Blend::Blend_Zero;
+ else if (params[0] == "One") blend.srcFac = Cmd_Blend::Blend_One;
+ else if (params[0] == "SrcColor") blend.srcFac = Cmd_Blend::Blend_Src_Color;
+ else if (params[0] == "OneMinusSrcColor") blend.srcFac = Cmd_Blend::Blend_One_Minus_Src_Color;
+ else if (params[0] == "DstColor") blend.srcFac = Cmd_Blend::Blend_Dst_Color;
+ else if (params[0] == "OneMinusDstColor") blend.srcFac = Cmd_Blend::Blend_One_Minus_Dst_Color;
+ else if (params[0] == "SrcAlpha") blend.srcFac = Cmd_Blend::Blend_Src_Alpha;
+ else if (params[0] == "OneMinusSrcAlpha") blend.srcFac = Cmd_Blend::Blend_One_Minus_Src_Alpha;
+ else if (params[0] == "DstAlpha") blend.srcFac = Cmd_Blend::Blend_Dst_Alpha;
+ else if (params[0] == "OneMinusDstAlpha") blend.srcFac = Cmd_Blend::Blend_One_Minus_Dst_Alpha;
+ else if (params[0] == "ConstantColor") blend.srcFac = Cmd_Blend::Blend_Constant_Color;
+ else if (params[0] == "OneMinusConstantColor") blend.srcFac = Cmd_Blend::Blend_One_Minus_Constant_Color;
+ else if (params[0] == "ConstantAlpha") blend.srcFac = Cmd_Blend::Blend_Constant_Alpha;
+ else if (params[0] == "OneMinusConstantAlpha") blend.srcFac = Cmd_Blend::Blend_One_Minus_Constant_Alpha;
+ else
+ {
+ delete pblend;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Blend: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+
+ if (params[1] == "Zero") blend.dstFac = Cmd_Blend::Blend_Zero;
+ else if (params[1] == "One") blend.dstFac = Cmd_Blend::Blend_One;
+ else if (params[1] == "SrcColor") blend.dstFac = Cmd_Blend::Blend_Src_Color;
+ else if (params[1] == "OneMinusSrcColor") blend.dstFac = Cmd_Blend::Blend_One_Minus_Src_Color;
+ else if (params[1] == "DstColor") blend.dstFac = Cmd_Blend::Blend_Dst_Color;
+ else if (params[1] == "OneMinusDstColor") blend.dstFac = Cmd_Blend::Blend_One_Minus_Dst_Color;
+ else if (params[1] == "SrcAlpha") blend.dstFac = Cmd_Blend::Blend_Src_Alpha;
+ else if (params[1] == "OneMinusSrcAlpha") blend.dstFac = Cmd_Blend::Blend_One_Minus_Src_Alpha;
+ else if (params[1] == "DstAlpha") blend.dstFac = Cmd_Blend::Blend_Dst_Alpha;
+ else if (params[1] == "OneMinusDstAlpha") blend.dstFac = Cmd_Blend::Blend_One_Minus_Dst_Alpha;
+ else if (params[1] == "ConstantColor") blend.dstFac = Cmd_Blend::Blend_Constant_Color;
+ else if (params[1] == "OneMinusConstantColor") blend.dstFac = Cmd_Blend::Blend_One_Minus_Constant_Color;
+ else if (params[1] == "ConstantAlpha") blend.dstFac = Cmd_Blend::Blend_Constant_Alpha;
+ else if (params[1] == "OneMinusConstantAlpha") blend.dstFac = Cmd_Blend::Blend_One_Minus_Constant_Alpha;
+ else
+ {
+ delete pblend;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of Blend: " + params[1]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+
+ group.push_back(pblend);
+}
+
+void GLSLCompiler::CommandDepthTest(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[1];
+ GetParams("DepthTest", p, params, 1);
+
+ Cmd_DepthTest* pTest = new Cmd_DepthTest();
+ Cmd_DepthTest& test = *pTest;
+ if (params[0] == "Off") test.test = Cmd_DepthTest::DepthTest_Off;
+ else if (params[0] == "Always") test.test = Cmd_DepthTest::DepthTest_Always;
+ else if (params[0] == "Never") test.test = Cmd_DepthTest::DepthTest_Never;
+ else if (params[0] == "Less") test.test = Cmd_DepthTest::DepthTest_Less;
+ else if (params[0] == "Equal") test.test = Cmd_DepthTest::DepthTest_Equal;
+ else if (params[0] == "LEqual") test.test = Cmd_DepthTest::DepthTest_Lequal;
+ else if (params[0] == "Greater") test.test = Cmd_DepthTest::DepthTest_Greater;
+ else if (params[0] == "NotEqual") test.test = Cmd_DepthTest::DepthTest_Notequal;
+ else if (params[0] == "GEqual") test.test = Cmd_DepthTest::DepthTest_Gequal;
+ else
+ {
+ delete pTest;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of DepthTest: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ group.push_back(pTest);
+}
+
+void GLSLCompiler::CommandDepthWrite(std::string& p, RenderCommandGroup& group)
+{
+ std::string params[1];
+ GetParams("DepthWrite", p, params, 1);
+
+ Cmd_DepthWrite* pwrite = new Cmd_DepthWrite();
+ Cmd_DepthWrite& write = *pwrite;
+ if (params[0] == "Off") write.write = false;
+ else if (params[0] == "On") write.write = true;
+ else
+ {
+ delete pwrite;
+ s_CompileError = string("Compile Shader Error: Invalid parameter of DepthWrite: " + params[0]);
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ group.push_back(pwrite);
+}
+
+void GLSLCompiler::GetParams(const char* cmdName, std::string& params, std::string* out, int n)
+{
+ int index = 0;
+ for (int i = 0; i < params.size(); ++i)
+ {
+ if (IsSeperator(params[i]))
+ continue;
+ int j = i + 1;
+ for (; j < params.size(); ++j)
+ {
+ if (j == params.size() - 1)
+ {
+ if (index >= n)
+ {
+ s_CompileError = string("Compile Shader Error: Invalid parameter count of ") + cmdName +" : " + params;
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ if(!IsSeperator(params[j]))
+ out[index++] = params.substr(i, j - i + 1);
+ else
+ out[index++] = params.substr(i, j - i);
+ return;
+ }
+ if (!IsSeperator(params[j]))
+ continue;
+ if (index >= n)
+ {
+ s_CompileError = string("Compile Shader Error: Invalid parameter count of ") + cmdName + " : " + params;
+ throw GLSLCompileException(s_CompileError.c_str());
+ }
+ out[index++] = params.substr(i, j - i);
+ break;
+ }
+ i = j;
+ }
+}
diff --git a/Client/Source/Graphics/ShaderCompiler.h b/Client/Source/Graphics/ShaderCompiler.h
new file mode 100644
index 0000000..f374567
--- /dev/null
+++ b/Client/Source/Graphics/ShaderCompiler.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <exception>
+#include <string>
+#include "../Threading/Mutex.h"
+#include "../Threading/Job.h"
+#include "../Graphics/RenderCommands.h"
+
+// GLSL(GameLab Shader)
+
+// in: .glsl path
+// out: vsh & fsh
+class CompileGLSLJob : public Job
+{
+
+};
+
+// in: glsl shader
+// out: vsh & fsh
+class CompileGLSLShaderJob : public Job
+{
+
+};
+
+class GLSLCompileException : public std::exception
+{
+public:
+ GLSLCompileException(const char* what)
+ : std::exception(what)
+ {
+ }
+
+};
+
+class GLSLCompiler
+{
+public:
+ static void Compile(std::string& src, std::string& vsh, std::string& fsh, RenderCommandGroup& cmd)/*throw GLSLCompileException*/;
+
+private:
+ static std::string GetContent(std::string& src, const char* from, const char* to);
+ static std::string TrimContent(std::string& src, const char* from, const char* to);
+ static bool IsLabelActive(std::string& src, const char* label);
+
+ static void ParseCmd(std::string& cmd, RenderCommandGroup& group);
+ static bool IsCommandActive(std::string& src, const char* label);
+ static bool FindCmdPos(std::string& line, int* start, int* end);
+ static bool IsLineCommentd(std::string& line);
+ static void CommandCull(std::string& params, RenderCommandGroup& group);
+ static void CommandBlend(std::string& params, RenderCommandGroup& group);
+ static void CommandDepthTest(std::string& params, RenderCommandGroup& group);
+ static void CommandDepthWrite(std::string& params, RenderCommandGroup& group);
+ static void GetParams(const char* cmdName, std::string& params, std::string* out, int n);
+
+};
diff --git a/Client/Source/Graphics/Texture.cpp b/Client/Source/Graphics/Texture.cpp
new file mode 100644
index 0000000..79dd5ea
--- /dev/null
+++ b/Client/Source/Graphics/Texture.cpp
@@ -0,0 +1,230 @@
+#include "../Math/Math.h"
+
+#include "ImageData.h"
+#include "Texture.h"
+
+Texture::Texture(TextureSetting setting, ImageData* imgData)
+{
+ Init(setting, imgData);
+ // force not keep imgData
+ m_KeepPixelData = false;
+}
+
+void Texture::Init(TextureSetting setting, ImageData* imgData)
+{
+ m_Width = imgData->width;
+ m_Height = imgData->height;
+ m_Type = setting.type;
+ m_Format = setting.format;
+ m_WrapMode = setting.wrapMode;
+ m_FilterMode = setting.filterMode;
+ m_KeepPixelData = setting.keepImageData;
+
+ glGenTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, m_GPUID);
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ switch (m_WrapMode) {
+ case ETextureWrapMode::Clamp:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ break;
+ case ETextureWrapMode::Repeat:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ break;
+ case ETextureWrapMode::Mirror:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+ break;
+ default:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ break;
+ }
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ switch (m_FilterMode) {
+ case ETextureFilterMode::Linear:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ case ETextureFilterMode::Nearest:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ break;
+ default:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ }
+
+ GLint srcFormat = GL_RGB;
+ switch (imgData->format)
+ {
+ case PixelFormat_R: srcFormat = GL_RED; break;
+ case PixelFormat_RGB: srcFormat = GL_RGB; break;
+ case PixelFormat_RGBA: srcFormat = GL_RGBA; break;
+ default: Assert(false);
+ }
+ GLint srcType = GL_UNSIGNED_BYTE;
+ switch (imgData->type)
+ {
+ case PixelType_UNSIGNED_BYTE: srcType = GL_UNSIGNED_BYTE; break;
+ default: Assert(false);
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imgData->width, imgData->height, 0, srcFormat, srcType, imgData->pixels);
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+}
+
+Texture::Texture(TextureSetting setting, int w, int h)
+{
+ m_KeepPixelData = false;
+
+ m_Width = w;
+ m_Height = h;
+ m_Type = setting.type;
+ m_Format = setting.format;
+ m_WrapMode = setting.wrapMode;
+ m_FilterMode = setting.filterMode;
+ m_KeepPixelData = setting.keepImageData;
+
+ WipeGLError();
+
+ glGenTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, m_GPUID);
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ switch (m_WrapMode) {
+ case ETextureWrapMode::Clamp:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ break;
+ case ETextureWrapMode::Repeat:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ break;
+ case ETextureWrapMode::Mirror:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+ break;
+ default:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ break;
+ }
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ switch (m_FilterMode) {
+ case ETextureFilterMode::Linear:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ case ETextureFilterMode::Nearest:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ break;
+ default:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ }
+ GLenum internalFormat = GL_RGB;
+ if (m_Format == ETextureFormat::R8)
+ {
+ internalFormat = GL_RED;
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ }
+
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+Texture::~Texture()
+{
+ glDeleteTextures(1, &m_GPUID);
+}
+
+void Texture::UpdateSubImage(Rect rect, int format, int type, const void* data)
+{
+ glBindTexture(GL_TEXTURE_2D, m_GPUID);
+
+ CheckGLError(
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ int alignment = 4;
+ if (m_Format == ETextureFormat::R8)
+ {
+ alignment = 1;
+ }
+
+ GLenum fmt = GL_RED;
+ switch (format)
+ {
+ case EPixelFormat::PixelFormat_BGR: fmt = GL_BGR; break;
+ case EPixelFormat::PixelFormat_BGRA:fmt = GL_BGRA; break;
+ case EPixelFormat::PixelFormat_R: fmt = GL_RED; break;
+ case EPixelFormat::PixelFormat_RG: fmt = GL_RG; break;
+ case EPixelFormat::PixelFormat_RGB: fmt = GL_RGB; break;
+ case EPixelFormat::PixelFormat_RGBA: fmt = GL_RGBA; break;
+ }
+ GLenum t = GL_UNSIGNED_BYTE;
+ switch (type)
+ {
+ case EPixelElementType::PixelType_UNSIGNED_BYTE: t = GL_UNSIGNED_BYTE; break;
+ case EPixelElementType::PixelType_UNSIGNED_INT: t = GL_UNSIGNED_INT; break;
+ case EPixelElementType::PixelType_BYTE: t = GL_BYTE; break;
+ case EPixelElementType::PixelType_INT: t = GL_INT; break;
+ case EPixelElementType::PixelType_FLOAT: t = GL_FLOAT; break;
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, rect.height, fmt, t, data);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ CheckGLError(
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+} \ No newline at end of file
diff --git a/Client/Source/Graphics/Texture.h b/Client/Source/Graphics/Texture.h
new file mode 100644
index 0000000..cf423e1
--- /dev/null
+++ b/Client/Source/Graphics/Texture.h
@@ -0,0 +1,94 @@
+#pragma once
+#include <exception>
+#include <string>
+
+#include "../Math/Math.h"
+#include "../Utilities/UtilMacros.h"
+#include "../Utilities/Assert.h"
+
+#include "OpenGL.h"
+
+class ImageData;
+
+enum ETextureType
+{
+ TEX_2D,
+ TEX_CUBE,
+};
+
+enum ETextureFormat
+{
+ RGBA32,
+ RGB24,
+ RGB16,
+ R8,
+ A8,
+};
+
+enum ETextureWrapMode
+{
+ Clamp,
+ Repeat,
+ Mirror,
+};
+
+enum ETextureFilterMode
+{
+ Nearest,
+ Linear,
+};
+
+// GPUĵ
+struct TextureSetting
+{
+ bool keepImageData; // Ƿ񱣴ͼƬ
+ int type; // ͼƬ
+ int format; // ڲʽ
+ int wrapMode; // Χ
+ int filterMode; // ˲
+};
+
+class TextureException : public std::exception
+{
+public:
+ TextureException(const char* what)
+ : std::exception(what)
+ {}
+ TextureException(int glError)
+ {
+ g_sharedGLErrorMsg = std::to_string(glError);
+ std::exception(g_sharedGLErrorMsg.c_str());
+ }
+};
+
+class Texture
+{
+public:
+ Texture(TextureSetting setting, int width, int height)/*throw TextureException*/; // ͼ
+ Texture(TextureSetting setting, ImageData* imgData)/*throw TextureException*/;
+ ~Texture();
+
+ void UpdateSubImage(Rect rect, int format, int type, const void* data);
+
+ GET(int, Width, m_Width);
+ GET(int, Height, m_Height);
+
+ GET(GLuint, GpuID, m_GPUID);
+
+private:
+ void Init(TextureSetting setting, ImageData* imgData);
+
+ //------------------------------------------------------------------------------
+
+ GLuint m_GPUID;
+
+ int m_Width, m_Height;
+
+ int m_Type;
+ int m_Format;
+ int m_FilterMode;
+ int m_WrapMode;
+
+ bool m_KeepPixelData; // Ƿ񱣴ͼݣĬϵ󲻱
+
+}; \ No newline at end of file
diff --git a/Client/Source/Graphics/VertexAttribute.cpp b/Client/Source/Graphics/VertexAttribute.cpp
new file mode 100644
index 0000000..e5f2ea7
--- /dev/null
+++ b/Client/Source/Graphics/VertexAttribute.cpp
@@ -0,0 +1,20 @@
+#include "VertexAttribute.h"
+
+namespace VertexAttribute
+{
+
+ // map VertexAttrFormat to OpenGL type
+ static GLenum kGLVertexAttrFormat[VertexAttrFormat_Count] = {
+ GL_FLOAT, // VertexAttrFormat_Float
+ GL_HALF_FLOAT, // VertexAttrFormat_Float16
+ GL_UNSIGNED_BYTE, // VertexAttrFormat_Color
+ GL_BYTE, // VertexAttrFormat_Byte
+ GL_UNSIGNED_BYTE, // VertexAttrFormat_Unsigned_Byte
+ };
+
+ GLenum ConvertAttrFormatToGLFormat(uint fmt)
+ {
+ return kGLVertexAttrFormat[fmt];
+ }
+
+} \ No newline at end of file
diff --git a/Client/Source/Graphics/VertexAttribute.h b/Client/Source/Graphics/VertexAttribute.h
new file mode 100644
index 0000000..8f7bc82
--- /dev/null
+++ b/Client/Source/Graphics/VertexAttribute.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <vector>
+
+#include "../Utilities/UtilMacros.h"
+
+#include "OpenGL.h"
+#include "GPUDataBuffer.h"
+
+// component format
+enum VertexAttrFormat
+{
+ VertexAttrFormat_Float = 0, // position\normal\tangent\uv\uv2\uv3\uv4
+ VertexAttrFormat_Float16,
+ VertexAttrFormat_Color, // color
+ VertexAttrFormat_Byte,
+ VertexAttrFormat_Unsigned_Byte,
+
+ VertexAttrFormat_Count
+};
+
+struct VertexAttributeDescriptor
+{
+ //union {
+ const void* pointer; // ڴַմʱ
+ int startOffset; // ԴVBOƫֵ
+ //};
+ uint componentNum; // ά1,2,3,4
+ uint componentFormat; // ÿ
+ uint16 stride; //
+ bool normalize; // ǷһֻCustomVertexLayout
+
+ // for default vertex layout
+ VertexAttributeDescriptor() {}
+ // for custom vertex layout
+ VertexAttributeDescriptor(int startOff, uint num, uint fmt, uint16 strd, bool normalized = false)
+ {
+ startOffset = startOff;
+ componentNum = num;
+ componentFormat = fmt;
+ stride = strd;
+ normalize = normalized;
+ }
+
+};
+
+namespace VertexAttribute
+{
+
+ extern GLenum ConvertAttrFormatToGLFormat(uint fmt);
+
+}
diff --git a/Client/Source/Graphics/VertexBuffer.cpp b/Client/Source/Graphics/VertexBuffer.cpp
new file mode 100644
index 0000000..d95bf58
--- /dev/null
+++ b/Client/Source/Graphics/VertexBuffer.cpp
@@ -0,0 +1,109 @@
+#include "VertexBuffer.h"
+
+VertexBuffer::VertexBuffer(int vbSize, int ibSize, VertexBufferType type)
+{
+ m_VB = GPU::ClaimBuffer(vbSize, GL_STATIC_DRAW);
+ m_IB = GPU::ClaimBuffer(ibSize, GL_STATIC_DRAW);
+}
+
+VertexBuffer::~VertexBuffer()
+{
+ GPU::ReleaseBuffer(m_VB);
+ GPU::ReleaseBuffer(m_IB);
+}
+// GetChunk
+// <fill>
+// FlushChunk
+// DrawChunk
+void VertexBuffer::GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib)
+{
+ m_SizePerVertex = sizePerVert;
+
+ uint vbufferSize = sizePerVert * maxVerts;
+ uint ibufferSize = sizePerIndex * maxIndices;
+
+ GLenum usage = GL_STATIC_DRAW;
+ m_VB->Restore(vbufferSize, usage);
+ m_IB->Restore(ibufferSize, usage);
+
+ const GLenum access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
+
+ *out_vb = m_VB->MapRange(0, vbufferSize, access);
+ *out_ib = m_IB->MapRange(0, ibufferSize, access);
+
+ m_Primitive = primitive;
+
+ WipeGLError();
+}
+
+void VertexBuffer::FlushChunk(int actualVerts, int actualIndices)
+{
+ int actualVBufferSize = m_SizePerVertex * actualVerts;
+ int actualIBufferSize = VertexLayout::GetDefaultIndexSize() * actualIndices;
+
+ m_CurIndexCount = actualIndices;
+
+ m_VB->FlushMapedRange(0, actualVBufferSize);
+ m_IB->FlushMapedRange(0, actualIBufferSize);
+
+ m_VB->UnMap();
+ m_IB->UnMap();
+
+ WipeGLError();
+}
+
+void VertexBuffer::Draw(CustomVertexLayout& layout)
+{
+ const byte* basepointer = 0;
+ const GLuint buffer = m_VB->GetHandle();
+
+ FillCustomVertexLayout(layout);
+
+ VertexLayout::SetupCustomVertexLayout(layout);
+
+ layout.RestorePointer();
+
+ const void* indexPtr = 0;
+
+ CheckGLError(
+ throw GLException(error);
+ );
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IB->GetHandle());
+
+ CheckGLError(
+ throw GLException(error);
+ );
+ GLenum indexFormat = VertexLayout::GetDefaultIndexFormat();
+
+ switch (m_Primitive)
+ {
+ case Primitive_Triangle:
+ glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ case Primitive_Line:
+ glDrawElements(GL_LINE, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ case Primitive_Point:
+ glDrawElements(GL_POINT, m_CurIndexCount, indexFormat, indexPtr);
+ break;
+ }
+
+ CheckGLError(
+ throw GLException(error);
+ );
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}
+
+void VertexBuffer::FillCustomVertexLayout(CustomVertexLayout& dst)
+{
+ const byte* basepointer = 0;
+ const GLuint buffer = m_VB->GetHandle();
+
+ dst.buffer = buffer;
+
+ for (int i = 0; i < dst.attributes.size(); ++i)
+ {
+ int offset = dst.attributes[i].startOffset;
+ dst.attributes[i].pointer = basepointer + offset;
+ }
+} \ No newline at end of file
diff --git a/Client/Source/Graphics/VertexBuffer.h b/Client/Source/Graphics/VertexBuffer.h
new file mode 100644
index 0000000..b907337
--- /dev/null
+++ b/Client/Source/Graphics/VertexBuffer.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <vector>
+
+#include "../Utilities/UtilMacros.h"
+
+#include "OpenGL.h"
+#include "GPUDataBuffer.h"
+#include "DefaultVertexLayout.h"
+#include "CustomVertexLayout.h"
+#include "Primitive.h"
+
+// ʵʹùУͨһVBOһIBOһsubmeshӦIBOеIJͬĶΣDzͬIBO
+
+class VertexBuffer
+{
+public:
+ enum VertexBufferType
+ {
+ VertexBufferType_Static, // device
+ VertexBufferType_Stream, // pinned (best performance)
+ VertexBufferType_Dynamic,// device
+ };
+
+ VertexBuffer(int vbSize, int ibSize, VertexBufferType type);
+ ~VertexBuffer();
+
+ //
+ void GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib);
+ // ύ
+ void FlushChunk(int actualVerts, int actualIndices);
+
+ GET(GPU::DataBuffer*, VB, m_VB);
+ GET(GPU::DataBuffer*, IB, m_IB);
+
+ void Draw(CustomVertexLayout& layout);
+
+private:
+ void FillCustomVertexLayout(CustomVertexLayout& dst);
+
+ VertexBufferType m_Type;
+
+ GPU::DataBuffer* m_VB;
+ GPU::DataBuffer* m_IB;
+
+ int m_SizePerVertex;
+
+ int m_CurIndexCount;
+
+ EPrimitive m_Primitive;
+
+};
diff --git a/Client/Source/Math/Functions.cpp b/Client/Source/Math/Functions.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Math/Functions.cpp
diff --git a/Client/Source/Math/Functions.h b/Client/Source/Math/Functions.h
new file mode 100644
index 0000000..3dd17dd
--- /dev/null
+++ b/Client/Source/Math/Functions.h
@@ -0,0 +1,30 @@
+#pragma once
+
+namespace MathUtils
+{
+ template <typename T>
+ inline T Max(T a, T b)
+ {
+ return a < b ? b : a;
+ }
+
+ template <typename T>
+ inline T Min(T a, T b)
+ {
+ return a < b ? a : b;
+ }
+
+}
+
+#define max(a, b)\
+((a)>(b)?(a):(b))
+
+#define min(a, b)\
+(a)<(b)?(a):(b)
+
+#define clamp(v, lo, hi)\
+max((lo), min((v), (hi)))
+
+// 10
+#define odd(n) \
+(((n)&1)?1:0)
diff --git a/Client/Source/Math/Math.h b/Client/Source/Math/Math.h
new file mode 100644
index 0000000..0cd7d84
--- /dev/null
+++ b/Client/Source/Math/Math.h
@@ -0,0 +1,6 @@
+#include "Vector2.hpp"
+#include "Matrix22.h"
+#include "Matrix44.h"
+#include "rect.h"
+#include "Functions.h"
+
diff --git a/Client/Source/Math/Matrix22.h b/Client/Source/Math/Matrix22.h
new file mode 100644
index 0000000..c777084
--- /dev/null
+++ b/Client/Source/Math/Matrix22.h
@@ -0,0 +1,10 @@
+#pragma once
+
+class Matrix22
+{
+public:
+ float m[2][2]; // row major
+
+
+
+};
diff --git a/Client/Source/Math/Matrix44.h b/Client/Source/Math/Matrix44.h
new file mode 100644
index 0000000..562ac54
--- /dev/null
+++ b/Client/Source/Math/Matrix44.h
@@ -0,0 +1,8 @@
+#pragma once
+
+class Matrix44
+{
+public:
+ float m[4][4]; // row major
+
+};
diff --git a/Client/Source/Math/Rect.h b/Client/Source/Math/Rect.h
new file mode 100644
index 0000000..63c6aa1
--- /dev/null
+++ b/Client/Source/Math/Rect.h
@@ -0,0 +1,13 @@
+#pragma once
+
+struct Rect
+{
+ Rect(float x = 0, float y = 0, float w = 0, float h = 0)
+ {
+ this->x = x;
+ this->y = y;
+ this->width = w;
+ this->height = h;
+ }
+ float x, y, width, height;
+};
diff --git a/Client/Source/Math/Vector2.hpp b/Client/Source/Math/Vector2.hpp
new file mode 100644
index 0000000..65f2c10
--- /dev/null
+++ b/Client/Source/Math/Vector2.hpp
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "../Utilities/Assert.h"
+#include "../Math/Functions.h"
+
+template <typename T>
+class Vector2Template
+{
+public:
+ Vector2Template(T x = 0, T y = 0)
+ {
+ this->x = x;
+ this->y = y;
+ }
+ inline void Set(T x, T y)
+ {
+ this->x = x;
+ this->y = y;
+ }
+
+ Vector2Template Clamp(T xmin, T xmax, T ymin, T ymax)
+ {
+ Vector2Template v;
+ v.x = clamp(x, xmin, xmax);
+ v.y = clamp(y, ymin, ymax);
+ return v;
+ }
+
+ T operator[](int i)
+ {
+ if (i == 0) return x;
+ else if (i == 1) return y;
+ Assert(false);
+ }
+
+ bool operator == (const Vector2Template& v) const
+ {
+ return v.x == x && v.y == y;
+ }
+
+ bool operator != (const Vector2Template& v) const
+ {
+ return v.x != x || v.y != y;
+ }
+
+ Vector2Template<T> operator - (const Vector2Template& v) const
+ {
+ Vector2Template<T> res = Vector2Template<T>(x - v.x, y - v.y);
+ return res;
+ }
+
+
+ float x, y;
+
+ static Vector2Template<T> zero;
+ static Vector2Template<T> one ;
+
+};
+
+using Vector2f = Vector2Template<float>;
+using Vector2i = Vector2Template<int>;
+
+
+template<typename T>
+Vector2Template<T> Vector2Template<T>::zero = Vector2Template(0, 0);
+template<typename T>
+Vector2Template<T> Vector2Template<T>::one = Vector2Template(1, 1);
diff --git a/Client/Source/Math/Vector3.hpp b/Client/Source/Math/Vector3.hpp
new file mode 100644
index 0000000..eee913b
--- /dev/null
+++ b/Client/Source/Math/Vector3.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+template<typename T>
+struct Vector3Template
+{
+ T x, y, z;
+ Vector3Template(T x = 0, T y = 0, T z = 0)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ }
+ inline void Set(T x, T y, T z)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ }
+
+
+ static Vector3Template zero;
+ static Vector3Template one;
+
+};
+
+template<typename T>
+Vector3Template<T> Vector3Template<T>::zero = Vector3Template(0, 0, 0);
+template<typename T>
+Vector3Template<T> Vector3Template<T>::one = Vector3Template(1, 1, 1);
+
+using Vector3f = Vector3Template<float>;
+
diff --git a/Client/Source/Math/Vector4.hpp b/Client/Source/Math/Vector4.hpp
new file mode 100644
index 0000000..8fbf7e6
--- /dev/null
+++ b/Client/Source/Math/Vector4.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+template<typename T>
+struct Vector4Template
+{
+ T x, y, z, w;
+
+ Vector4Template(T x = 0, T y = 0, T z = 0, T w = 0)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->w = w;
+ }
+
+ inline void Set(T x, T y, T z, T w)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->w = w;
+ }
+
+ static Vector4Template zero;
+ static Vector4Template one;
+};
+
+template<typename T>
+Vector4Template<T> Vector4Template<T>::zero = Vector4Template(0, 0, 0, 0);
+template<typename T>
+Vector4Template<T> Vector4Template<T>::one = Vector4Template(1, 1, 1, 1);
+
+using Vector4f = Vector4Template<float>; \ No newline at end of file
diff --git a/Client/Source/RagdollMain.cpp b/Client/Source/RagdollMain.cpp
new file mode 100644
index 0000000..acf70c8
--- /dev/null
+++ b/Client/Source/RagdollMain.cpp
@@ -0,0 +1,89 @@
+// python -m glad --out-path=build --api="gl=2.1" --extensions="" --generator="c"
+// g++ example/c++/sdl.cpp build/src/glad.c -Ibuild/include -lSDL2 -ldl
+
+#include <iostream>
+
+#include <glad/glad.h>
+#include <SDL2/SDL.h>
+
+int main(int argc, char **argv) {
+
+ if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ std::cerr << "SDL2 video subsystem couldn't be initialized. Error: "
+ << SDL_GetError()
+ << std::endl;
+ exit(1);
+ }
+
+ SDL_Window* window = SDL_CreateWindow("Glad Sample",
+ SDL_WINDOWPOS_CENTERED,
+ SDL_WINDOWPOS_CENTERED,
+ 800, 600, SDL_WINDOW_SHOWN |
+ SDL_WINDOW_OPENGL);
+
+ SDL_Renderer* renderer = SDL_CreateRenderer(window, -1,
+ SDL_RENDERER_ACCELERATED);
+
+ if (renderer == nullptr) {
+ std::cerr << "SDL2 Renderer couldn't be created. Error: "
+ << SDL_GetError()
+ << std::endl;
+ exit(1);
+ }
+
+ // Create a OpenGL context on SDL2
+ SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+
+ // Load GL extensions using glad
+ if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
+ std::cerr << "Failed to initialize the OpenGL context." << std::endl;
+ exit(1);
+ }
+
+ // Loaded OpenGL successfully.
+ std::cout << "OpenGL version loaded: " << GLVersion.major << "."
+ << GLVersion.minor << std::endl;
+
+ // Create an event handler
+ SDL_Event event;
+ // Loop condition
+ bool running = true;
+
+ while (running) {
+ SDL_PollEvent(&event);
+
+ switch (event.type) {
+ case SDL_QUIT:
+ running = false;
+ break;
+
+ case SDL_KEYDOWN:
+ switch (event.key.keysym.sym) {
+ case SDLK_ESCAPE:
+ running = false;
+ break;
+ }
+ }
+
+ glClearColor(0, 0, 0, 1);
+
+ // You'd want to use modern OpenGL here
+ glColor3d(0, 1, 0);
+ glBegin(GL_TRIANGLES);
+ glVertex2f(.2, 0);
+ glVertex2f(.01, .2);
+ glVertex2f(-.2, 0);
+ glEnd();
+
+ SDL_GL_SwapWindow(window);
+ }
+
+ // Destroy everything to not leak memory.
+ SDL_GL_DeleteContext(gl_context);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/Client/Source/Threading/Job.cpp b/Client/Source/Threading/Job.cpp
new file mode 100644
index 0000000..3bfdb4d
--- /dev/null
+++ b/Client/Source/Threading/Job.cpp
@@ -0,0 +1,13 @@
+#include "Job.h"
+#include "../Utilities/UIDGenerator.h"
+
+static UIDGenerator s_JobIDGenerator;
+
+Job::Job()
+ : m_ID(s_JobIDGenerator.GenUID())
+{
+}
+
+Job::~Job()
+{
+}
diff --git a/Client/Source/Threading/Job.h b/Client/Source/Threading/Job.h
new file mode 100644
index 0000000..db89feb
--- /dev/null
+++ b/Client/Source/Threading/Job.h
@@ -0,0 +1,17 @@
+#pragma once
+
+// ij
+class Job
+{
+public:
+ Job();
+ virtual ~Job();
+
+ virtual void Process() = 0;
+ virtual bool IsFinished() = 0;
+ virtual void Dispacth(void* param) = 0; // call in main thread
+
+protected:
+ int m_ID; // Job ID
+
+}; \ No newline at end of file
diff --git a/Client/Source/Threading/JobSystem.cpp b/Client/Source/Threading/JobSystem.cpp
new file mode 100644
index 0000000..378d74f
--- /dev/null
+++ b/Client/Source/Threading/JobSystem.cpp
@@ -0,0 +1,56 @@
+#include "JobSystem.h"
+#include "../Debug/Log.h"
+
+JobSystem::JobSystem()
+ : m_Initialized(false)
+{
+
+}
+
+JobSystem::~JobSystem()
+{
+
+}
+
+void JobSystem::Initilize(int workThreadCount)
+{
+ if (m_Initialized)
+ {
+ log_error("JobSystem has already initialized.");
+ return;
+ }
+
+ if (workThreadCount <= 0)
+ return;
+
+ m_ThreadCount = workThreadCount;
+ m_Cur = 0;
+
+ for (int i = 0; i < workThreadCount; ++i)
+ {
+ WorkThread* thread = new WorkThread();
+ thread->Resume();
+ m_Threads.push_back(thread);
+ }
+
+ m_Initialized = true;
+}
+
+void JobSystem::Dispatch(void* param)
+{
+ for (int i = 0; i < m_Threads.size(); ++i)
+ {
+ m_Threads[i]->Dispatch(param);
+ }
+}
+
+void JobSystem::AddJobAtEnd(Job* job)
+{
+ WorkThread* thread = SelectThread();
+ thread->AddJobAtEnd(job);
+}
+
+WorkThread* JobSystem::SelectThread()
+{
+ return m_Threads[(++m_Cur)% m_ThreadCount];
+} \ No newline at end of file
diff --git a/Client/Source/Threading/JobSystem.h b/Client/Source/Threading/JobSystem.h
new file mode 100644
index 0000000..ded4370
--- /dev/null
+++ b/Client/Source/Threading/JobSystem.h
@@ -0,0 +1,25 @@
+#pragma once
+#include "../Utilities/Singleton.h"
+#include "../Threading/Thread.h"
+#include <vector>
+
+class JobSystem : public Singleton<JobSystem>
+{
+public:
+ JobSystem();
+ ~JobSystem();
+
+ void AddJobAtEnd(Job* job);
+
+ void Initilize(int workThreadCount = 1);
+ void Dispatch(void* param);
+
+private:
+ WorkThread* SelectThread();
+
+ bool m_Initialized;
+ std::vector<WorkThread*> m_Threads;
+ int m_Cur;
+ int m_ThreadCount;
+
+}; \ No newline at end of file
diff --git a/Client/Source/Threading/Mutex.cpp b/Client/Source/Threading/Mutex.cpp
new file mode 100644
index 0000000..cda7e89
--- /dev/null
+++ b/Client/Source/Threading/Mutex.cpp
@@ -0,0 +1,27 @@
+#include "Thread.h"
+#include "Mutex.h"
+
+#include "../Utilities/Type.h"
+
+Mutex::Mutex()
+{
+ m_Handle = ::CreateMutex(NULL, FALSE, NULL);
+ if (!m_Handle)
+ throw ThreadException("Cant use win32 mutex.");
+}
+
+Mutex::~Mutex()
+{
+ ::CloseHandle(m_Handle);
+ m_Handle = NULL;
+}
+
+void Mutex::LockSelf()
+{
+ ::WaitForSingleObject(m_Handle, (~(uint32)0));
+}
+
+void Mutex::UnlockSelf()
+{
+ ::ReleaseMutex(m_Handle);
+} \ No newline at end of file
diff --git a/Client/Source/Threading/Mutex.h b/Client/Source/Threading/Mutex.h
new file mode 100644
index 0000000..eed69aa
--- /dev/null
+++ b/Client/Source/Threading/Mutex.h
@@ -0,0 +1,39 @@
+#pragma once
+#include <windows.h>
+
+class Mutex
+{
+public:
+ Mutex();
+ ~Mutex();
+
+ void LockSelf();
+ void UnlockSelf();
+
+private:
+ HANDLE m_Handle;
+
+};
+
+
+class MutexLocker
+{
+public:
+ MutexLocker(Mutex& mutex)
+ : m(mutex)
+ {
+ m.LockSelf();
+ };
+ ~MutexLocker()
+ {
+ m.UnlockSelf();
+ }
+ operator bool() { return false; };
+private:
+ void* operator new(size_t);
+ Mutex& m;
+};
+
+#define Lock(m) \
+if(MutexLocker lock_##m = m){} else
+
diff --git a/Client/Source/Threading/Semaphore.cpp b/Client/Source/Threading/Semaphore.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Threading/Semaphore.cpp
diff --git a/Client/Source/Threading/Semaphore.h b/Client/Source/Threading/Semaphore.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Client/Source/Threading/Semaphore.h
diff --git a/Client/Source/Threading/Thread.cpp b/Client/Source/Threading/Thread.cpp
new file mode 100644
index 0000000..0bede98
--- /dev/null
+++ b/Client/Source/Threading/Thread.cpp
@@ -0,0 +1,70 @@
+#include <string>
+#include "Thread.h"
+#include "../Utilities/Assert.h"
+#include "../Utilities/Type.h"
+
+static std::string s_ThreadErr;
+
+static DWORD WINAPI ThreadMain(LPVOID param)
+{
+ Thread* thread = (Thread*)param;
+ thread->Run();
+ return NULL;
+}
+
+Thread::Thread(uint32 stacksize)
+{
+ m_Handle = ::CreateThread(
+ NULL
+ , stacksize
+ , ThreadMain
+ , this
+ , CREATE_SUSPENDED
+ , NULL);
+ if (m_Handle == 0)
+ {
+ s_ThreadErr = "Create Thread Failed. ErrorCode=" + std::to_string(GetLastError());
+ throw ThreadException(s_ThreadErr.c_str());
+ }
+}
+
+Thread::~Thread()
+{
+ CloseHandle(m_Handle);
+}
+
+void Thread::Resume()
+{
+ ::ResumeThread(m_Handle);
+}
+
+bool Thread::IsRunning()
+{
+ if (m_Handle) {
+ DWORD exitCode = 0;
+ // https://blog.csdn.net/yuanmeng567/article/details/19485719
+ ::GetExitCodeThread(m_Handle, &exitCode);
+ return exitCode == STILL_ACTIVE;
+ }
+ return false;
+}
+
+void Thread::Join()
+{
+ ::WaitForSingleObject(m_Handle, INFINITE);
+}
+
+void Thread::Kill()
+{
+ ::TerminateThread(m_Handle, FALSE);
+}
+
+void Thread::Sleep(uint ms)
+{
+ ::Sleep(ms);
+}
+
+bool Thread::IsCurrent()
+{
+ return m_Handle == ::GetCurrentThread();
+}
diff --git a/Client/Source/Threading/Thread.h b/Client/Source/Threading/Thread.h
new file mode 100644
index 0000000..77d8dff
--- /dev/null
+++ b/Client/Source/Threading/Thread.h
@@ -0,0 +1,71 @@
+#pragma once
+#include <windows.h>
+#include <vector>
+#include <exception>
+
+#include "../Utilities/Type.h"
+
+#include "Job.h"
+#include "Mutex.h"
+
+class ThreadException : public std::exception
+{
+public:
+ ThreadException(const char* what)
+ : std::exception(what)
+ {
+ }
+};
+
+class Thread
+{
+public:
+ Thread(uint32 stacksize = 0)/*throw ThreadExeception*/;
+ virtual ~Thread();
+
+ virtual void Run() = 0;
+
+ virtual void Resume();
+ virtual void Join() ;
+ virtual void Kill() ;
+
+ virtual void Sleep(uint ms) ;
+
+ virtual bool IsRunning() ;
+ virtual bool IsCurrent() ;
+
+protected:
+ HANDLE m_Handle;
+
+};
+
+// ϵͳ߳
+class WorkThread : public Thread
+{
+public:
+ void Run() override;
+ void Dispatch(void* param); // call in main thread
+
+ void AddJobAtEnd(Job* job);
+
+private:
+ Mutex m_PendingMutex;
+ Mutex m_FinishedMutex;
+
+ std::vector<Job*> m_PendingJobs;
+ std::vector<Job*> m_FinishedJobs;
+
+};
+
+// ִСδ߳
+class CodePieceThread : public Thread
+{
+public:
+ typedef void(*CodePiece)();
+
+ void Run() override;
+
+private:
+ std::vector<CodePiece> m_CodePieces;
+
+}; \ No newline at end of file
diff --git a/Client/Source/Threading/WorkThread.cpp b/Client/Source/Threading/WorkThread.cpp
new file mode 100644
index 0000000..4ea6262
--- /dev/null
+++ b/Client/Source/Threading/WorkThread.cpp
@@ -0,0 +1,50 @@
+#include "Thread.h"
+
+#include "../Debug/Log.h"
+
+void WorkThread::Run()
+{
+ while (true)
+ {
+ Lock(m_PendingMutex)
+ {
+ for (auto iter = m_PendingJobs.begin(); iter != m_PendingJobs.end();)
+ {
+ Job* job = *iter;
+ job->Process();
+ if (job->IsFinished())
+ {
+ Lock(m_FinishedMutex) {
+ m_FinishedJobs.push_back(job);
+ }
+ iter = m_PendingJobs.erase(iter);
+ continue;
+ }
+ ++iter;
+ }
+ if (m_PendingJobs.size() == 0)
+ ::Sleep(100);
+ }
+ }
+}
+
+void WorkThread::Dispatch(void* param)
+{
+ Lock(m_FinishedMutex)
+ {
+ for (int i = 0; i < m_FinishedJobs.size(); ++i)
+ {
+ m_FinishedJobs[i]->Dispacth(param);
+ delete m_FinishedJobs[i];
+ }
+ m_FinishedJobs.clear();
+ }
+}
+
+void WorkThread::AddJobAtEnd(Job* job)
+{
+ Lock(m_PendingMutex)
+ {
+ m_PendingJobs.push_back(job);
+ }
+} \ No newline at end of file
diff --git a/Client/Source/Utilities/Assert.h b/Client/Source/Utilities/Assert.h
new file mode 100644
index 0000000..526ca32
--- /dev/null
+++ b/Client/Source/Utilities/Assert.h
@@ -0,0 +1,11 @@
+#ifndef ASSERT_H
+#define ASSERT_H
+
+#include <assert.h>
+
+#define Assert(c) assert((c))
+
+#define DebugAssertIf(c) assert(c)
+#define AssertIf(c) assert(c)
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Utilities/AutoInvoke.h b/Client/Source/Utilities/AutoInvoke.h
new file mode 100644
index 0000000..7d9bb83
--- /dev/null
+++ b/Client/Source/Utilities/AutoInvoke.h
@@ -0,0 +1,27 @@
+#pragma once
+
+typedef void(*AutoInvokeAction)();
+
+// RAII auto call
+class AutoInvokerWhenLeave
+{
+public:
+ AutoInvokerWhenLeave(AutoInvokeAction func)
+ {
+ m_Func = func;
+ };
+ ~AutoInvokerWhenLeave()
+ {
+ if (m_Func)
+ {
+ m_Func();
+ }
+ }
+private:
+ AutoInvokeAction m_Func;
+
+};
+
+#define InvokeWhenLeave(func) \
+AutoInvokerWhenLeave auto_invoker = AutoInvokerWhenLeave(func);
+
diff --git a/Client/Source/Utilities/Exception.h b/Client/Source/Utilities/Exception.h
new file mode 100644
index 0000000..3795bc6
--- /dev/null
+++ b/Client/Source/Utilities/Exception.h
@@ -0,0 +1,12 @@
+#pragma once
+#include <exception>
+
+#define CustomException(Name) \
+class Name : public std::exception \
+{ \
+public: \
+ Name(const char* what) \
+ : std::exception(what) \
+ { \
+ } \
+}
diff --git a/Client/Source/Utilities/Singleton.h b/Client/Source/Utilities/Singleton.h
new file mode 100644
index 0000000..f864a42
--- /dev/null
+++ b/Client/Source/Utilities/Singleton.h
@@ -0,0 +1,43 @@
+#ifndef SINGLETON_H
+#define SINGLETON_H
+
+template<class T>
+class Singleton
+{
+public:
+
+ static T* Instance()
+ {
+ if (!instance) instance = new T;
+ return instance;
+ }
+
+ static void Destroy()
+ {
+ delete instance;
+ instance = nullptr;
+ }
+
+protected:
+
+ Singleton()
+ {
+ instance = static_cast<T*>(this);
+ };
+
+ virtual ~Singleton() {};
+
+ static T* instance;
+
+private:
+
+ Singleton(const Singleton& singleton);
+
+ Singleton& operator = (const Singleton& singleton);
+
+};
+
+template<class T>
+T* Singleton<T>::instance = nullptr;
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Utilities/StaticInitiator.h b/Client/Source/Utilities/StaticInitiator.h
new file mode 100644
index 0000000..af264af
--- /dev/null
+++ b/Client/Source/Utilities/StaticInitiator.h
@@ -0,0 +1,30 @@
+#pragma once
+
+//https://stackoverflow.com/questions/1005685/c-static-initialization-order
+//https://stackoverflow.com/questions/211237/static-variables-initialisation-order
+
+// ̬캯
+#include "StaticConstructor/include/StaticConstructor.h"
+
+typedef void(*StaticFunc) ();
+
+// Զʼ̬
+class StaticFuncInvoker
+{
+public:
+ // Default Constructor:
+ StaticFuncInvoker(StaticFunc func)
+ {
+ if (func)
+ func();
+ }
+};
+
+// þstatic
+#define InvokeStaticFunc(func)\
+ static StaticFuncInvoker staticInvokerOf_##func(func);
+
+// ʼǰcppľ̬Ҫעstaticʼ˳Static Initialization Order
+#define InitializeStaticVariables(lambda)\
+ static StaticFuncInvoker staticInvoker(lambda);
+
diff --git a/Client/Source/Utilities/Type.h b/Client/Source/Utilities/Type.h
new file mode 100644
index 0000000..da6208d
--- /dev/null
+++ b/Client/Source/Utilities/Type.h
@@ -0,0 +1,25 @@
+#ifndef TYPE_H
+#define TYPE_H
+
+#include <cstdlib>
+#include <stdint.h>
+
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef unsigned char byte;
+typedef char sbyte;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef uint16_t UInt16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef uint32_t UInt32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+typedef uint64_t UInt64;
+
+typedef uint32_t uint;
+typedef int32_t sint;
+typedef int32_t SInt32;
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Utilities/UIDGenerator.h b/Client/Source/Utilities/UIDGenerator.h
new file mode 100644
index 0000000..81918f0
--- /dev/null
+++ b/Client/Source/Utilities/UIDGenerator.h
@@ -0,0 +1,20 @@
+#ifndef UID_GENERATOR_H
+#define UID_GENERATOR_H
+
+class UIDGenerator
+{
+public:
+ UIDGenerator(int from = 0)
+ : m_Index(from)
+ {
+ };
+ ~UIDGenerator(){};
+
+ int GenUID(){return m_Index++;};
+
+private:
+ int m_Index;
+
+};
+
+#endif \ No newline at end of file
diff --git a/Client/Source/Utilities/UtilMacros.h b/Client/Source/Utilities/UtilMacros.h
new file mode 100644
index 0000000..29bb7b0
--- /dev/null
+++ b/Client/Source/Utilities/UtilMacros.h
@@ -0,0 +1,19 @@
+#ifndef UTIL_MACROS_H
+#define UTIL_MACROS_H
+
+#define GET_SET(TYPE,PROP,VAR) \
+ inline void Set##PROP (TYPE val) { VAR = val; } \
+ inline TYPE Get##PROP () {return VAR; }
+
+#define GET(TYPE, PROP, VAR) \
+ inline TYPE Get##PROP () {return VAR; }
+
+#define SET(TYPE, PROP, VAR) \
+ inline void Set##PROP (TYPE val) { VAR = val; } \
+
+#define Mask(v) (1 << v)
+
+#define cast(T, v) \
+((T)(v))
+
+#endif \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/.gitignore b/Client/ThirdParty/Box2D/.gitignore
new file mode 100644
index 0000000..8b45738
--- /dev/null
+++ b/Client/ThirdParty/Box2D/.gitignore
@@ -0,0 +1,7 @@
+build/
+imgui.ini
+settings.ini
+.vscode/
+CMakeSettings.json
+out/
+.vs/
diff --git a/Client/ThirdParty/Box2D/.travis.yml b/Client/ThirdParty/Box2D/.travis.yml
new file mode 100644
index 0000000..6c67aec
--- /dev/null
+++ b/Client/ThirdParty/Box2D/.travis.yml
@@ -0,0 +1,32 @@
+language: cpp
+
+dist: bionic
+
+# This is clang on macOS
+compiler: gcc
+
+branches:
+ only:
+ - master
+
+addons:
+ apt:
+ packages:
+ - libxrandr-dev
+ - libxinerama-dev
+ - libxcursor-dev
+ - libxi-dev
+
+jobs:
+ include:
+ - os: linux
+ env:
+ - os: osx
+ env:
+
+script:
+ - mkdir build
+ - cd build
+ - cmake ..
+ - cmake --build .
+ - ./bin/unit_test
diff --git a/Client/ThirdParty/Box2D/CHANGELOG.md b/Client/ThirdParty/Box2D/CHANGELOG.md
new file mode 100644
index 0000000..c192fb9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/CHANGELOG.md
@@ -0,0 +1,60 @@
+# Changes for version 2.4.1
+
+## API Changes
+- Extended distance joint to have a minimum and maximum limit.
+- Removed rope joint. Use the distance joint instead.
+- B2_USER_SETTINGS and b2_user_settings.h can control user data, length units, and maximum polygon vertices.
+- Default user data is now uintptr_t instead of void*
+- b2FixtureDef::restitutionThreshold lets you set the restitution velocity threshold per fixture.
+
+## BREAKING Changes
+- BREAKING: distance joint 0 stiffness now means the spring is turned off rather than making the joint rigid.
+- BREAKING: distance joint minimum and maximum must be set correctly to get old behavior.
+
+## Infrastructure
+- Library installation function available in CMake.
+- Shared library (DLL) option available.
+- Bug fixes
+
+# Changes for version 2.4.0
+
+## Infrastructure
+- Documentation in Doxygen format
+- CMake build system
+- Unit test support
+- Continuous integration testing using Travis CI
+- Limited use of C++11 (nullptr and override)
+- Restructured folders and renamed files to better match open-source standards
+- MIT License
+- Removed float32 and float64
+- Linked the Box2D project to GitHub Sponsors
+
+## Collision
+- Chain and edge shape must now be one-sided to eliminate ghost collisions
+- Broad-phase optimizations
+- Added b2ShapeCast for linear shape casting
+
+## Dynamics
+- Joint limits are now predictive and not stateful
+- Experimental 2D cloth (rope)
+- b2Body::SetActive -> b2Body::SetEnabled
+- Better support for running multiple worlds
+- Handle zero density better
+ - The body behaves like a static body
+ - The body is drawn with a red color
+- Added translation limit to wheel joint
+- World dump now writes to box2d_dump.inl
+- Static bodies are never awake
+- All joints with spring-dampers now use stiffness and damping
+- Added utility functions to convert frequency and damping ratio to stiffness and damping
+
+## Testbed
+- Testbed uses dear imgui
+- glad OpenGL loader
+- OpenGL 3.3 required
+
+# Changes for version 2.3.0
+- Polygon creation now computes the convex hull. Vertices no longer need to be ordered.
+- The convex hull code will merge vertices closer than dm_linearSlop. This may lead to failure on very small polygons.
+- Added b2MotorJoint.
+- Bug fixes.
diff --git a/Client/ThirdParty/Box2D/CMakeLists.txt b/Client/ThirdParty/Box2D/CMakeLists.txt
new file mode 100644
index 0000000..c38243c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/CMakeLists.txt
@@ -0,0 +1,65 @@
+cmake_minimum_required(VERSION 3.8)
+
+# https://cmake.org/cmake/help/latest/command/project.html
+project(box2d VERSION 2.4.1)
+
+# set(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo" CACHE STRING "" FORCE)
+
+set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
+
+option(BOX2D_BUILD_UNIT_TESTS "Build the Box2D unit tests" ON)
+option(BOX2D_BUILD_TESTBED "Build the Box2D testbed" ON)
+option(BOX2D_BUILD_DOCS "Build the Box2D documentation" OFF)
+option(BOX2D_USER_SETTINGS "Override Box2D settings with b2UserSettings.h" OFF)
+
+option(BUILD_SHARED_LIBS "Build Box2D as a shared library" OFF)
+
+set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
+
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
+
+include(GNUInstallDirs)
+
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+if (BOX2D_USER_SETTINGS)
+ add_compile_definitions(B2_USER_SETTINGS)
+endif()
+
+add_subdirectory(src)
+
+if (BOX2D_BUILD_DOCS)
+ set(DOXYGEN_SKIP_DOT TRUE)
+ find_package(Doxygen)
+endif()
+
+if (DOXYGEN_FOUND AND BOX2D_BUILD_DOCS)
+ add_subdirectory(docs)
+endif()
+
+if (BOX2D_BUILD_UNIT_TESTS)
+ add_subdirectory(unit-test)
+endif()
+
+if (BOX2D_BUILD_TESTBED)
+ add_subdirectory(extern/glad)
+ add_subdirectory(extern/glfw)
+ add_subdirectory(extern/imgui)
+ add_subdirectory(extern/sajson)
+ add_subdirectory(testbed)
+
+ # default startup project for Visual Studio
+ if (MSVC)
+ set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT testbed)
+ set_property(TARGET testbed PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/testbed")
+ endif()
+endif()
+
+install(
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/box2d"
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+)
diff --git a/Client/ThirdParty/Box2D/LICENSE b/Client/ThirdParty/Box2D/LICENSE
new file mode 100644
index 0000000..3600714
--- /dev/null
+++ b/Client/ThirdParty/Box2D/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Erin Catto
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/README.md b/Client/ThirdParty/Box2D/README.md
new file mode 100644
index 0000000..e016563
--- /dev/null
+++ b/Client/ThirdParty/Box2D/README.md
@@ -0,0 +1,115 @@
+![Box2D Logo](https://box2d.org/images/logo.svg)
+
+# Build Status
+[![Build Status](https://travis-ci.org/erincatto/box2d.svg?branch=master)](https://travis-ci.org/erincatto/box2d)
+
+# Box2D
+
+Box2D is a 2D physics engine for games.
+
+## Contributing
+
+Please do not submit pull requests with new features or core library changes. Instead, please file an issue first for discussion. For bugs, I prefer detailed bug reports over pull requests.
+
+## Features
+
+### Collision
+- Continuous collision detection
+- Contact callbacks: begin, end, pre-solve, post-solve
+- Convex polygons and circles
+- Multiple shapes per body
+- One-shot contact manifolds
+- Dynamic tree broadphase
+- Efficient pair management
+- Fast broadphase AABB queries
+- Collision groups and categories
+
+### Physics
+- Continuous physics with time of impact solver
+- Persistent body-joint-contact graph
+- Island solution and sleep management
+- Contact, friction, and restitution
+- Stable stacking with a linear-time solver
+- Revolute, prismatic, distance, pulley, gear, mouse joint, and other joint types
+- Joint limits, motors, and friction
+- Momentum decoupled position correction
+- Fairly accurate reaction forces/impulses
+
+### System
+- Small block and stack allocators
+- Centralized tuning parameters
+- Highly portable C++ with no use of STL containers
+
+### Testbed
+- OpenGL with GLFW
+- Graphical user interface with imgui
+- Extensible test framework
+- Support for loading world dumps
+
+## Building
+- Install [CMake](https://cmake.org/)
+- Ensure CMake is in the user `PATH`
+- Visual Studio: run `build.bat` from the command prompt
+- Otherwise: run `build.sh` from a bash shell
+- Results are in the build sub-folder
+- On Windows you can open box2d.sln
+
+## Building Box2D - Using vcpkg
+You can download and install Box2D using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
+
+- git clone https://github.com/Microsoft/vcpkg.git
+- cd vcpkg
+- ./bootstrap-vcpkg.sh
+- ./vcpkg integrate install
+- ./vcpkg install box2d
+
+The Box2D port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+
+Note: vcpkg support is not provided by the Box2D project
+
+## Building for Xcode
+- Install [CMake](https://cmake.org)
+- Add Cmake to the path in .zprofile (the default Terminal shell is zsh)
+ - export PATH="/Applications/CMake.app/Contents/bin:$PATH"
+- mkdir build
+- cd build
+- cmake -G Xcode ..
+- open box2d.xcodeproj
+- Select the testbed scheme
+- Edit the scheme to set a custom working directory, make this be in box2d/testbed
+- You can now build and run the testbed
+
+## Installing using CMake
+You can use the CMake install feature to deploy the library to a central location that can
+be accessed using:
+```
+find_package(box2d REQUIRED)
+target_link_libraries(mytarget PRIVATE box2d)
+```
+You can build and install the library and docs using this command sequence (requires Doxygen):
+```
+mkdir build
+cd build
+cmake -DBOX2D_BUILD_DOCS=ON ..
+cmake --build .
+cmake --build . --target INSTALL
+```
+On Windows this tries to install in `Program Files` and thus requires admin privileges. Alternatively you can target another directory using something like this:
+```
+mkdir build
+cd build
+cmake -DBOX2D_BUILD_DOCS=ON -DCMAKE_INSTALL_PREFIX="C:/packages" ..
+cmake --build .
+cmake --build . --target INSTALL
+```
+
+## Documentation
+- [Manual](https://box2d.org/documentation/)
+- [reddit](https://www.reddit.com/r/box2d/)
+- [Discord](https://discord.gg/NKYgCBP)
+
+## License
+Box2D is developed by Erin Catto, and uses the [MIT license](https://en.wikipedia.org/wiki/MIT_License).
+
+## Sponsorship
+Support development of Box2D through [Github Sponsors](https://github.com/sponsors/erincatto)
diff --git a/Client/ThirdParty/Box2D/build.bat b/Client/ThirdParty/Box2D/build.bat
new file mode 100644
index 0000000..216561a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/build.bat
@@ -0,0 +1,7 @@
+rem Use this batch file to build box2d for Visual Studio
+rmdir /s /q build
+mkdir build
+cd build
+cmake ..
+cmake --build .
+start box2d.sln
diff --git a/Client/ThirdParty/Box2D/build.sh b/Client/ThirdParty/Box2D/build.sh
new file mode 100644
index 0000000..3433595
--- /dev/null
+++ b/Client/ThirdParty/Box2D/build.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+# Use this to build box2d on any system with a bash shell
+rm -rf build
+mkdir build
+cd build
+cmake -DBOX2D_BUILD_DOCS=OFF ..
+cmake --build .
diff --git a/Client/ThirdParty/Box2D/build_docs.sh b/Client/ThirdParty/Box2D/build_docs.sh
new file mode 100644
index 0000000..93e124d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/build_docs.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+# Builds Box2D along with documentation
+rm -rf build
+mkdir build
+cd build
+cmake -DBOX2D_BUILD_DOCS=ON ..
+cmake --build .
diff --git a/Client/ThirdParty/Box2D/deploy_docs.sh b/Client/ThirdParty/Box2D/deploy_docs.sh
new file mode 100644
index 0000000..1813f85
--- /dev/null
+++ b/Client/ThirdParty/Box2D/deploy_docs.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+
+# Copies documentation to blog
+cp -R build/docs/html/. ../blog/public/documentation/
diff --git a/Client/ThirdParty/Box2D/docs/CMakeLists.txt b/Client/ThirdParty/Box2D/docs/CMakeLists.txt
new file mode 100644
index 0000000..edffb4e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/CMakeLists.txt
@@ -0,0 +1,32 @@
+
+# NOTE: The order of this list determines the order of items in the Guides
+# (i.e. Pages) list in the generated documentation
+
+set(BOX2D_DOXYGEN_SOURCES
+ "include/box2d"
+ "docs/overview.md"
+ "docs/hello.md"
+ "docs/testbed.md"
+ "docs/common.md"
+ "docs/collision.md"
+ "docs/dynamics.md"
+ "docs/loose_ends.md"
+ "docs/references.md"
+ "docs/FAQ.md")
+
+# Format the source list into a Doxyfile INPUT value that Doxygen can parse
+foreach(path IN LISTS BOX2D_DOXYGEN_SOURCES)
+ set(BOX2D_DOXYGEN_INPUT "${BOX2D_DOXYGEN_INPUT} \\\n\"${CMAKE_SOURCE_DIR}/${path}\"")
+endforeach()
+
+# https://cmake.org/cmake/help/latest/command/configure_file.html
+configure_file(Doxyfile.in Doxyfile @ONLY)
+
+add_custom_target(docs ALL "${DOXYGEN_EXECUTABLE}"
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/docs"
+ COMMENT "Generating HTML documentation" VERBATIM)
+
+install(
+ DIRECTORY "${CMAKE_BINARY_DIR}/docs/html"
+ DESTINATION "${CMAKE_INSTALL_DOCDIR}"
+)
diff --git a/Client/ThirdParty/Box2D/docs/Doxyfile.in b/Client/ThirdParty/Box2D/docs/Doxyfile.in
new file mode 100644
index 0000000..523c925
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/Doxyfile.in
@@ -0,0 +1,2578 @@
+# Doxyfile 1.8.17
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "Box2D"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = @CMAKE_PROJECT_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "A 2D physics engine for games"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO = "@CMAKE_SOURCE_DIR@/docs/images/logo.svg"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = "@CMAKE_BINARY_DIR@/docs"
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all generated output in the proper direction.
+# Possible values are: None, LTR, RTL and Context.
+# The default value is: None.
+
+OUTPUT_TEXT_DIRECTION = None
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines (in the resulting output). You can put ^^ in the value part of an
+# alias to insert a newline as if a physical newline was in the original file.
+# When you need a literal { or } or , in the value part of an alias you have to
+# escape them by means of a backslash (\), this can lead to conflicts with the
+# commands \{ and \} for these it is advised to use the version @{ and @} or use
+# a double escape (\\{ and \\})
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is
+# Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# (including Cygwin) ands Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation. If
+# EXTRACT_ALL is set to YES then this flag will automatically be disabled.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE = "@BOX2D_BINARY_DIR@/docs/warnings.txt"
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = @BOX2D_DOXYGEN_INPUT@
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: https://www.gnu.org/software/libiconv/) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment),
+# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen
+# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.idl \
+ *.ddl \
+ *.odl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.cs \
+ *.d \
+ *.php \
+ *.php4 \
+ *.php5 \
+ *.phtml \
+ *.inc \
+ *.m \
+ *.markdown \
+ *.md \
+ *.mm \
+ *.dox \
+ *.doc \
+ *.txt \
+ *.py \
+ *.pyw \
+ *.f90 \
+ *.f95 \
+ *.f03 \
+ *.f08 \
+ *.f \
+ *.for \
+ *.tcl \
+ *.vhd \
+ *.vhdl \
+ *.ucf \
+ *.qsf \
+ *.ice
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = "@CMAKE_SOURCE_DIR@/docs/images"
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = "@CMAKE_SOURCE_DIR@/docs/overview.md"
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+# If clang assisted parsing is enabled you can provide the clang parser with the
+# path to the compilation database (see:
+# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files
+# were built. This is equivalent to specifying the "-p" option to a clang tool,
+# such as clang-check. These options will then be passed to the parser.
+# Note: The availability of this option depends on whether or not doxygen was
+# generated with the -Duse_libclang=ON option for CMake.
+
+CLANG_DATABASE_PATH =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = "@CMAKE_SOURCE_DIR@/docs/extra.css"
+
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: https://developer.apple.com/xcode/), introduced with OSX
+# 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANSPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment.
+# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: https://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME =
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_TIMESTAMP = NO
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/Client/ThirdParty/Box2D/docs/FAQ.md b/Client/ThirdParty/Box2D/docs/FAQ.md
new file mode 100644
index 0000000..7f18a3c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/FAQ.md
@@ -0,0 +1,146 @@
+# FAQ
+
+## What is Box2D?
+
+Box2D is a feature rich 2D rigid body physics engine, written in C++ by Erin Catto. It has been used in many games, including Crayon Physics Deluxe, winner of the 2008 Independant Game Festival Grand Prize.
+
+Box2D uses the [MIT license](https://en.wikipedia.org/wiki/MIT_License) license and can be used free of charge.
+
+## What platforms does Box2D support?
+
+Box2D is developed on Windows using Visual C++. Ports are also available for Flash, Java, C#, Python.
+
+Erin Catto maintains the C++ version, but provides no support for other languages. Other languages are supported by the community and possibly by the authors of those ports.
+
+## Who makes it?
+
+Erin Catto is the driving force behind Box2D, with various others supporting the ports. Box2D is an open source project, and accepts community feedback.
+
+## How do I get help?
+
+You should read the documentation and the rest of this FAQ first. Also, you should study the examples included in the source distribution. Then you can visit the [subreddit](https://www.reddit.com/r/box2d/) to ask any remaining questions.
+
+Please to not PM or email Erin Catto for support. It is best to ask questions in the forum so that everyone can benefit from the discussion.
+
+## Documentation
+
+### Why isn't feature foo documented?
+
+If you grab the latest code from the git master branch you will likely find features that are not documented in the manual. New features are added to the manual after they are mature and a new point release is imminent. However, all major features added to Box2D are accompanied by example code in the testbed to test the feature and show the intended usage.
+
+## Prerequisites
+
+### Programming
+
+You should have a working knowledge of C++ before you use Box2D. You should understand classes, inheritance, and pointers. There are plenty of resources on the web for learning C++. You should also understand your development environment: compilation, linking, and debugging.
+
+### Math and Physics
+
+You should have a basic knowledge of rigid bodies, force, torque, and impulses. If you come across a math or physics concept you don't understand, please read about it on Wikipedia. Visit this [page](http://box2d.org/publications/) if you want a deeper knowledge of the algorithms used in Box2D.
+
+## API
+
+### What units does Box2D use?
+
+Box2D is tuned for meters-kilograms-seconds (MKS). Your moving objects should be between 0.1 - 10 meters. Do not use pixels as units! You will get a jittery simulation.
+
+### How do I convert pixels to meters?
+
+Suppose you have a sprite for a character that is 100x100 pixels. You decide to use a scaling factor that is 0.01. This will make the character physics box 1m x 1m. So go make a physics box that is 1x1. Now suppose the character starts out at pixel coordinate (345,679). So position the physics box at (3.45,6.79). Now simulate the physics world. Suppose the character physics box moves to (2.31,4.98), so move your character sprite to pixel coordinates (231,498).
+Now the only tricky part is choosing a scaling factor. This really depends on your game. You should try to get your moving objects in the range 0.1 - 10 meters, with 1 meter being the sweet spot.
+
+### Why don't you use this awesome C++ feature?
+
+Box2D is designed to be portable, so I try to keep the C++ usage simple. Also, I don't use the STL (except sort) or other libraries to keep the dependencies low. I keep template usage low and don't use name spaces. Remember, just because a C++ feature exists, that doesn't mean you need to use it.
+
+The many ports of Box2D to other languages platforms shows that this strategy has been successful.
+
+### Can I use Box2D in a DLL?
+
+Box2D was not designed to be used in a DLL. You may have to change how static data is used to make this work.
+
+### Is Box2D thread-safe?
+
+No. Box2D will likely never be thread-safe. Box2D has a large API and trying to make such an API thread-safe would have a large performance and complexity impact.
+
+## Build Issues
+
+### Why doesn't my code compile and/or link?
+
+There are many reasons why a build can go bad. Here are a few that have come up:
+
+* Using old Box2D headers with new code
+* Not linking the Box2D library with your application
+* Using old project files that don't include some new source files
+
+## Rendering
+
+### What are Box2D's rendering capabilities?
+
+Box2D is only a physics engine. How you draw stuff is up to you.
+
+### But the Testbed draws stuff
+
+Visualization is very important for debugging collision and physics. I wrote the test bed to help me test Box2D and give you examples of how to use Box2D. The TestBed is not part of the Box2D library.
+
+### How do I draw shapes?
+
+Drawing shapes is not supported and shape internal data is likely to change. Instead you should implement the `b2DebugDraw` interface.
+
+## Accuracy
+
+Box2D uses approximate methods for a few reasons.
+
+* Performance
+* Some differential equations don't have known solutions
+* Some constraints cannot be determined uniquely
+
+What this means is that constraints are not perfectly rigid and sometimes you will see some bounce even when the restitution is zero.
+Box2D uses Gauss-Seidel to approximately solve constraints.
+Box2D also uses Semi-implicit Euler to approximately solve the differential equations.
+Box2D also does not have exact collision. Polygons are covered with a thin skin (around 0.5cm thick) to avoid numerical problems. This can sometimes lead to unexpected contact normals. Also, some shapes may begin to overlap and then be pushed apart by the solver.
+
+## Making Games
+
+### Worms Clones
+
+Making a worms clone requires arbitrarily destructible terrain. This is beyond the scope of Box2D, so you will have to figure out how to do this on your own.
+
+### Tile Based Environment
+
+Using many boxes for your terrain may not work well because box-like characters can get snagged on internal corners. A future update to Box2D should allow for smooth motion over edge chains. In general you should avoid using a rectangular character because collision tolerances will still lead to undesirable snagging.
+
+### Asteroid Type Coordinate Systems
+
+Box2D does not have any support for coordinate frame wrapping. You would likely need to customize Box2D for this purpose. You may need to use a different broad-phase for this to work.
+
+## Determinism
+
+### Is Box2D deterministic?
+
+For the same input, and same binary, Box2D will reproduce any simulation. Box2D does not use any random numbers nor base any computation on random events (such as timers, etc).
+
+However, people often want more stringent determinism. People often want to know if Box2D can produce identical results on different binaries and on different platforms. The answer is no. The reason for this answer has to do with how floating point math is implemented in many compilers and processors. I recommend reading this article if you are curious: http://www.yosefk.com/blog/consistency-how-to-defeat-the-purpose-of-ieee-floating-point.html
+
+### But I really want determinism
+
+This naturally leads to the question of fixed-point math. Box2D does not support fixed-point math. In the past Box2D was ported to the NDS in fixed-point and apparently it worked okay. Fixed-point math is slower and more tedious to develop, so I have chosen not to use fixed-point for the development of Box2D.
+
+## Why is the restitution/friction mixing inaccurate?
+
+A physically correct restitution value must be measured in experiments. But as soon as you change the geometry from the experiment then the value is wrong. Next, adding simultaneous collision makes the answer worse. We've been down this road before.
+
+So the question of accuracy has been answered: failure.
+
+The only remaining question is how do we make it convenient. On this opinions may vary.
+
+`b2Settings` is just that. Settings you can adjust if you know what you are doing.
+
+## What are the biggest mistakes made by new users?
+
+* Using pixels for length instead of meters.
+* Expecting Box2D to give pixel perfect results.
+* Using b2Polygon to create concave polygons.
+* Testing their code in release mode.
+* Not learning C++ before using Box2D.
+* Not reading this FAQ. :)
diff --git a/Client/ThirdParty/Box2D/docs/collision.md b/Client/ThirdParty/Box2D/docs/collision.md
new file mode 100644
index 0000000..fe00aa4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/collision.md
@@ -0,0 +1,433 @@
+# Collision Module
+The Collision module contains shapes and functions that operate on them.
+The module also contains a dynamic tree and broad-phase to acceleration
+collision processing of large systems.
+
+The collision module is designed to be usable outside of the dynamic
+system. For example, you can use the dynamic tree for other aspects of
+your game besides physics.
+
+However, the main purpose of Box2D is to provide a rigid body physics
+engine, so the using the collision module by itself may feel limited for
+some applications. Likewise, I will not make a strong effort to document
+it or polish the APIs.
+
+## Shapes
+Shapes describe collision geometry and may be used independently of
+physics simulation. At a minimum, you should understand how to create
+shapes that can be later attached to rigid bodies.
+
+Box2D shapes implement the b2Shape base class. The base class defines
+functions to:
+- Test a point for overlap with the shape.
+- Perform a ray cast against the shape.
+- Compute the shape's AABB.
+- Compute the mass properties of the shape.
+
+In addition, each shape has a type member and a radius. The radius even
+applies to polygons, as discussed below.
+
+Keep in mind that a shape does not know about bodies and stand apart
+from the dynamics system. Shapes are stored in a compact form that is
+optimized for size and performance. As such, shapes are not easily moved
+around. You have to manually set the shape vertex positions to move a
+shape. However, when a shape is attached to a body using a fixture, the
+shapes move rigidly with the host body. In summary:
+- When a shape is **not** attached to a body, you can view it's vertices as being expressed in world-space.
+- When a shape is attached to a body, you can view it's vertices as being expressed in local coordinates.
+
+### Circle Shapes
+Circle shapes have a position and radius. Circles are solid. You cannot
+make a hollow circle using the circle shape.
+
+```cpp
+b2CircleShape circle;
+circle.m_p.Set(2.0f, 3.0f);
+circle.m_radius = 0.5f;
+```
+
+### Polygon Shapes
+Polygon shapes are solid convex polygons. A polygon is convex when all
+line segments connecting two points in the interior do not cross any
+edge of the polygon. Polygons are solid and never hollow. A polygon must
+have 3 or more vertices.
+
+![Convex and Concave Polygons](images/convex_concave.gif)
+
+Polygons vertices are stored with a counter clockwise winding (CCW). We
+must be careful because the notion of CCW is with respect to a
+right-handed coordinate system with the z-axis pointing out of the
+plane. This might turn out to be clockwise on your screen, depending on
+your coordinate system conventions.
+
+![Polygon Winding Order](images/winding.svg)
+
+The polygon members are public, but you should use initialization
+functions to create a polygon. The initialization functions create
+normal vectors and perform validation.
+
+You can create a polygon shape by passing in a vertex array. The maximal
+size of the array is controlled by `b2_maxPolygonVertices` which has a
+default value of 8. This is sufficient to describe most convex polygons.
+
+The `b2PolygonShape::Set` function automatically computes the convex hull
+and establishes the proper winding order. This function is fast when the
+number of vertices is low. If you increase `b2_maxPolygonVertices`, then
+the convex hull computation might become slow. Also note that the convex
+hull function may eliminate and/or re-order the points you provide.
+Vertices that are closer than `b2_linearSlop` may be merged.
+
+```cpp
+// This defines a triangle in CCW order.
+b2Vec2 vertices[3];
+vertices[0].Set(0.0f, 0.0f);
+vertices[1].Set(1.0f, 0.0f);
+vertices[2].Set(0.0f, 1.0f);
+
+int32 count = 3;
+b2PolygonShape polygon;
+polygon.Set(vertices, count);
+```
+
+The polygon shape has some convenience functions to create boxes.
+
+```cpp
+void SetAsBox(float hx, float hy);
+void SetAsBox(float hx, float hy, const b2Vec2& center, float angle);
+```
+
+Polygons inherit a radius from b2Shape. The radius creates a skin around
+the polygon. The skin is used in stacking scenarios to keep polygons
+slightly separated. This allows continuous collision to work against the
+core polygon.
+
+![Polygon Skin](images/skinned_polygon.svg)
+
+The polygon skin helps prevent tunneling by keeping the polygons
+separated. This results in small gaps between the shapes. Your visual
+representation can be larger than the polygon to hide any gaps.
+
+![Skin Collision](images/skin_collision.svg)
+
+Not that polygon skin is only provided to help with continuous collision.
+The purpose is not to simulate rounded polygons.
+
+### Edge Shapes
+Edge shapes are line segments. These are provided to assist in making a
+free-form static environment for your game. A major limitation of edge
+shapes is that they can collide with circles and polygons but not with
+themselves. The collision algorithms used by Box2D require that at least
+one of two colliding shapes have volume. Edge shapes have no volume, so
+edge-edge collision is not possible.
+
+```cpp
+// This an edge shape.
+b2Vec2 v1(0.0f, 0.0f);
+b2Vec2 v2(1.0f, 0.0f);
+
+b2EdgeShape edge;
+edge.SetTwoSided(v1, v2);
+```
+
+In many cases a game environment is constructed by connecting several
+edge shapes end-to-end. This can give rise to an unexpected artifact
+when a polygon slides along the chain of edges. In the figure below we
+see a box colliding with an internal vertex. These *ghost* collisions
+are caused when the polygon collides with an internal vertex generating
+an internal collision normal.
+
+![Ghost Collision](images/ghost_collision.svg)
+
+If edge1 did not exist this collision would seem fine. With edge1
+present, the internal collision seems like a bug. But normally when
+Box2D collides two shapes, it views them in isolation.
+
+Fortunately, the edge shape provides a mechanism for eliminating ghost
+collisions by storing the adjacent *ghost* vertices. Box2D uses these
+ghost vertices to prevent internal collisions.
+
+![Ghost Vertices](images/ghost_vertices.svg)
+
+The Box2D algorithm for dealing with ghost collisions only supports
+one-sided collision. The front face is to the right when looking from the first
+vertex towards the second vertex. This matches the CCW winding order
+used by polygons.
+
+```cpp
+// This is an edge shape with ghost vertices.
+b2Vec2 v0(1.7f, 0.0f);
+b2Vec2 v1(1.0f, 0.25f);
+b2Vec2 v2(0.0f, 0.0f);
+b2Vec2 v3(-1.7f, 0.4f);
+
+b2EdgeShape edge;
+edge.SetOneSided(v0, v1, v2, v3);
+```
+
+In general stitching edges together this way is a bit wasteful and
+tedious. This brings us to chain shapes.
+
+### Chain Shapes
+
+The chain shape provides an efficient way to connect many edges together
+to construct your static game worlds. Chain shapes automatically
+eliminate ghost collisions and provide one-sided collision. The collision is
+one-sided to eliminate ghost collisions.
+
+If you don't care about ghost collisions, you can just create a bunch of
+two-sided edge shapes. The efficiency is similar.
+
+The simplest way to use chain shapes is to create loops. Simply provide an
+array of vertices.
+
+```cpp
+b2Vec2 vs[4];
+vs[0].Set(1.7f, 0.0f);
+vs[1].Set(1.0f, 0.25f);
+vs[2].Set(0.0f, 0.0f);
+vs[3].Set(-1.7f, 0.4f);
+
+b2ChainShape chain;
+chain.CreateLoop(vs, 4);
+```
+
+The edge normal depends on the winding order. A counter-clockwise winding order orients the normal outwards and a clockwise winding order orients the normal inwards.
+
+![Chain Shape Outwards Loop](images/chain_loop_outwards.svg)
+
+![Chain Shape Inwards Loop](images/chain_loop_inwards.svg)
+
+You may have a scrolling game world and would like to connect several chains together.
+You can connect chains together using ghost vertices, like we did with b2EdgeShape.
+
+![Chain Shape](images/chain_shape.svg)
+
+```cpp
+b2ChainShape::CreateChain(const b2Vec2* vertices, int32 count,
+ const b2Vec2& prevVertex, const b2Vec2& nextVertex);
+```
+
+Self-intersection of chain shapes is not supported. It might work, it
+might not. The code that prevents ghost collisions assumes there are no
+self-intersections of the chain. Also, very close vertices can cause
+problems. Make sure all your edges are longer than b2_linearSlop (5mm).
+
+![Self Intersection is Bad](images/self_intersect.svg)
+
+Each edge in the chain is treated as a child shape and can be accessed
+by index. When a chain shape is connected to a body, each edge gets its
+own bounding box in the broad-phase collision tree.
+
+```cpp
+// Visit each child edge.
+for (int32 i = 0; i \< chain.GetChildCount(); ++i)
+{
+ b2EdgeShape edge;
+ chain.GetChildEdge(&edge, i);
+
+ ...
+}
+```
+
+## Geometric Queries
+You can perform a couple geometric queries on a single shape.
+
+### Shape Point Test
+You can test a point for overlap with a shape. You provide a transform
+for the shape and a world point.
+
+```cpp
+b2Transform transform;
+transform.SetIdentity();
+b2Vec2 point(5.0f, 2.0f);
+
+bool hit = shape->TestPoint(transform, point);
+```
+
+Edge and chain shapes always return false, even if the chain is a loop.
+
+### Shape Ray Cast
+You can cast a ray at a shape to get the point of first intersection and normal vector. A child index is included for chain shapes because the ray cast will only check a single edge at a time.
+
+> **Caution**:
+> No hit will register if the ray starts inside a convex shape like a circle or polygon. This is consistent with Box2D treating convex shapes as solid.
+>
+
+```cpp
+b2Transfrom transform;
+transform.SetIdentity();
+
+b2RayCastInput input;
+input.p1.Set(0.0f, 0.0f);
+input.p2.Set(1.0f, 0.0f);
+input.maxFraction = 1.0f;
+int32 childIndex = 0;
+
+b2RayCastOutput output;
+bool hit = shape->RayCast(&output, input, transform, childIndex);
+
+if (hit)
+{
+ b2Vec2 hitPoint = input.p1 + output.fraction * (input.p2 -- input.p1);
+ ...
+}
+```
+
+## Pairwise Functions
+The Collision module contains functions that take a pair of shapes and compute some results. These include:
+- Overlap
+- Contact manifolds
+- Distance
+- Time of impact
+
+### Overlap
+You can test two shapes for overlap using this function:
+
+```cpp
+b2Transform xfA = ..., xfB = ...;
+bool overlap = b2TestOverlap(shapeA, indexA, shapeB, indexB, xfA, xfB);
+```
+
+Again you must provide child indices to for the case of chain shapes.
+
+### Contact Manifolds
+Box2D has functions to compute contact points for overlapping shapes. If
+we consider circle-circle or circle-polygon, we can only get one contact
+point and normal. In the case of polygon-polygon we can get two points.
+These points share the same normal vector so Box2D groups them into a
+manifold structure. The contact solver takes advantage of this to
+improve stacking stability.
+
+![Contact Manifold](images/manifolds.svg)
+
+Normally you don't need to compute contact manifolds directly, however
+you will likely use the results produced in the simulation.
+
+The b2Manifold structure holds a normal vector and up to two contact
+points. The normal and points are held in local coordinates. As a
+convenience for the contact solver, each point stores the normal and
+tangential (friction) impulses.
+
+The data stored in b2Manifold is optimized for internal use. If you need
+this data, it is usually best to use the b2WorldManifold structure to
+generate the world coordinates of the contact normal and points. You
+need to provide a b2Manifold and the shape transforms and radii.
+
+```cpp
+b2WorldManifold worldManifold;
+worldManifold.Initialize(&manifold, transformA, shapeA.m_radius,
+transformB, shapeB.m_radius);
+
+for (int32 i = 0; i \< manifold.pointCount; ++i)
+{
+ b2Vec2 point = worldManifold.points[i];
+ ...
+}
+```
+
+Notice that the world manifold uses the point count from the original
+manifold.
+
+During simulation shapes may move and the manifolds may change. Points
+may be added or removed. You can detect this using b2GetPointStates.
+
+```cpp
+b2PointState state1[2], state2[2];
+b2GetPointStates(state1, state2, &manifold1, &manifold2);
+
+if (state1[0] == b2_removeState)
+{
+ // process event
+}
+```
+
+### Distance
+The `b2Distance` function can be used to compute the distance between two
+shapes. The distance function needs both shapes to be converted into a
+b2DistanceProxy. There is also some caching used to warm start the
+distance function for repeated calls.
+
+![Distance Function](images/distance.svg)
+
+### Time of Impact
+If two shapes are moving fast, they may *tunnel* through each other in a
+single time step.
+
+![Tunneling](images/tunneling2.svg)
+
+The `b2TimeOfImpact` function is used to determine the time when two
+moving shapes collide. This is called the *time of impact* (TOI). The
+main purpose of `b2TimeOfImpact` is for tunnel prevention. In particular,
+it is designed to prevent moving objects from tunneling outside of
+static level geometry.
+
+This function accounts for rotation and translation of both shapes,
+however if the rotations are large enough, then the function may miss a
+collision. However the function will still report a non-overlapped time
+and will capture all translational collisions.
+
+The time of impact function identities an initial separating axis and
+ensures the shapes do not cross on that axis. This might miss collisions
+that are clear at the final positions. While this approach may miss some
+collisions, it is very fast and adequate for tunnel prevention.
+
+![Captured Collision](images/captured_toi.svg)
+
+![Missed Collision](images/missed_toi.svg)
+
+It is difficult to put a restriction on the rotation magnitude. There
+may be cases where collisions are missed for small rotations. Normally,
+these missed rotational collisions should not harm game play. They tend
+to be glancing collisions.
+
+The function requires two shapes (converted to b2DistanceProxy) and two
+b2Sweep structures. The sweep structure defines the initial and final
+transforms of the shapes.
+
+You can use fixed rotations to perform a *shape cast*. In this case, the
+time of impact function will not miss any collisions.
+
+## Dynamic Tree
+The b2DynamicTree class is used by Box2D to organize large numbers of
+shapes efficiently. The class does not know about shapes. Instead it
+operates on axis-aligned bounding boxes (AABBs) with user data pointers.
+
+The dynamic tree is a hierarchical AABB tree. Each internal node in the
+tree has two children. A leaf node is a single user AABB. The tree uses
+rotations to keep the tree balanced, even in the case of degenerate
+input.
+
+The tree structure allows for efficient ray casts and region queries.
+For example, you may have hundreds of shapes in your scene. You could
+perform a ray cast against the scene in a brute force manner by ray
+casting each shape. This would be inefficient because it does not take
+advantage of shapes being spread out. Instead, you can maintain a
+dynamic tree and perform ray casts against the tree. This traverses the
+ray through the tree skipping large numbers of shapes.
+
+A region query uses the tree to find all leaf AABBs that overlap a query
+AABB. This is faster than a brute force approach because many shapes can
+be skipped.
+
+![Raycast](images/raycast.svg)
+
+![Overlap Test](images/overlap_test.svg)
+
+Normally you will not use the dynamic tree directly. Rather you will go
+through the b2World class for ray casts and region queries. If you plan
+to instantiate your own dynamic tree, you can learn how to use it by
+looking at how Box2D uses it.
+
+## Broad-phase
+Collision processing in a physics step can be divided into narrow-phase
+and broad-phase. In the narrow-phase we compute contact points between
+pairs of shapes. Imagine we have N shapes. Using brute force, we would
+need to perform the narrow-phase for N*N/2 pairs.
+
+The b2BroadPhase class reduces this load by using a dynamic tree for
+pair management. This greatly reduces the number of narrow-phase calls.
+
+Normally you do not interact with the broad-phase directly. Instead,
+Box2D creates and manages a broad-phase internally. Also, b2BroadPhase
+is designed with Box2D's simulation loop in mind, so it is likely not
+suited for other use cases.
diff --git a/Client/ThirdParty/Box2D/docs/common.md b/Client/ThirdParty/Box2D/docs/common.md
new file mode 100644
index 0000000..0534ff7
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/common.md
@@ -0,0 +1,66 @@
+# Common Module
+The Common module contains settings, memory management, and vector math.
+
+## Settings
+The header b2Settings.h contains:
+- Types such as int32 and float
+- Constants
+- Allocation wrappers
+- The version number
+
+### Types
+Box2D defines various types such as int8, etc. to make it easy
+to determine the size of structures.
+
+### Constants
+Box2D defines several constants. These are all documented in
+b2Settings.h. Normally you do not need to adjust these constants.
+
+Box2D uses floating point math for collision and simulation. Due to
+round-off error some numerical tolerances are defined. Some tolerances
+are absolute and some are relative. Absolute tolerances use MKS units.
+
+### Allocation wrappers
+The settings file defines b2Alloc and b2Free for large allocations. You
+may forward these calls to your own memory management system.
+
+### Version
+The b2Version structure holds the current version so you can query this
+at run-time.
+
+## Memory Management
+A large number of the decisions about the design of Box2D were based on
+the need for quick and efficient use of memory. In this section I will
+discuss how and why Box2D allocates memory.
+
+Box2D tends to allocate a large number of small objects (around 50-300
+bytes). Using the system heap through malloc or new for small objects is
+inefficient and can cause fragmentation. Many of these small objects may
+have a short life span, such as contacts, but can persist for several
+time steps. So we need an allocator that can efficiently provide heap
+memory for these objects.
+
+Box2D's solution is to use a small object allocator (SOA) called
+b2BlockAllocator. The SOA keeps a number of growable pools of varying
+sizes. When a request is made for memory, the SOA returns a block of
+memory that best fits the requested size. When a block is freed, it is
+returned to the pool. Both of these operations are fast and cause little
+heap traffic.
+
+Since Box2D uses a SOA, you should never new or malloc a body, fixture,
+or joint. However, you do have to allocate a b2World on your own. The
+b2World class provides factories for you to create bodies, fixtures, and
+joints. This allows Box2D to use the SOA and hide the gory details from
+you. Never, call delete or free on a body, fixture, or joint.
+
+While executing a time step, Box2D needs some temporary workspace
+memory. For this, it uses a stack allocator called b2StackAllocator to
+avoid per-step heap allocations. You don't need to interact with the
+stack allocator, but it's good to know it's there.
+
+## Math
+Box2D includes a simple small vector and matrix module. This has been
+designed to suit the internal needs of Box2D and the API. All the
+members are exposed, so you may use them freely in your application.
+
+The math library is kept simple to make Box2D easy to port and maintain.
diff --git a/Client/ThirdParty/Box2D/docs/copycss.sh b/Client/ThirdParty/Box2D/docs/copycss.sh
new file mode 100644
index 0000000..989a774
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/copycss.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+cp *.css ../build/docs/html/
diff --git a/Client/ThirdParty/Box2D/docs/dynamics.md b/Client/ThirdParty/Box2D/docs/dynamics.md
new file mode 100644
index 0000000..e8b45fc
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/dynamics.md
@@ -0,0 +1,1674 @@
+# Dynamics Module
+The Dynamics module is the most complex part of Box2D and is the part
+you likely interact with the most. The Dynamics module sits on top of
+the Common and Collision modules, so you should be somewhat familiar
+with those by now.
+
+The Dynamics module contains:
+- fixture class
+- rigid body class
+- contact class
+- joint classes
+- world class
+- listener classes
+
+There are many dependencies between these classes so it is difficult to
+describe one class without referring to another. In the following, you
+may see some references to classes that have not been described yet.
+Therefore, you may want to quickly skim this chapter before reading it
+closely.
+
+The dynamics module is covered in the following chapters.
+
+## Bodies
+Bodies have position and velocity. You can apply forces, torques, and
+impulses to bodies. Bodies can be static, kinematic, or dynamic. Here
+are the body type definitions:
+
+#### b2_staticBody
+A static body does not move under simulation and behaves as if it has
+infinite mass. Internally, Box2D stores zero for the mass and the
+inverse mass. Static bodies can be moved manually by the user. A static
+body has zero velocity. Static bodies do not collide with other static
+or kinematic bodies.
+
+#### b2_kinematicBody
+A kinematic body moves under simulation according to its velocity.
+Kinematic bodies do not respond to forces. They can be moved manually by
+the user, but normally a kinematic body is moved by setting its
+velocity. A kinematic body behaves as if it has infinite mass, however,
+Box2D stores zero for the mass and the inverse mass. Kinematic bodies do
+not collide with other kinematic or static bodies.
+
+#### b2_dynamicBody
+A dynamic body is fully simulated. They can be moved manually by the
+user, but normally they move according to forces. A dynamic body can
+collide with all body types. A dynamic body always has finite, non-zero
+mass. If you try to set the mass of a dynamic body to zero, it will
+automatically acquire a mass of one kilogram and it won't rotate.
+
+Bodies are the backbone for fixtures (shapes). Bodies carry fixtures and
+move them around in the world. Bodies are always rigid bodies in Box2D.
+That means that two fixtures attached to the same rigid body never move
+relative to each other and fixtures attached to the same body don't
+collide.
+
+Fixtures have collision geometry and density. Normally, bodies acquire
+their mass properties from the fixtures. However, you can override the
+mass properties after a body is constructed.
+
+You usually keep pointers to all the bodies you create. This way you can
+query the body positions to update the positions of your graphical
+entities. You should also keep body pointers so you can destroy them
+when you are done with them.
+
+### Body Definition
+Before a body is created you must create a body definition (b2BodyDef).
+The body definition holds the data needed to create and initialize a
+body.
+
+Box2D copies the data out of the body definition; it does not keep a
+pointer to the body definition. This means you can recycle a body
+definition to create multiple bodies.
+
+Let's go over some of the key members of the body definition.
+
+### Body Type
+As discussed at the beginning of this chapter, there are three different
+body types: static, kinematic, and dynamic. You should establish the
+body type at creation because changing the body type later is expensive.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.type = b2_dynamicBody;
+```
+
+Setting the body type is mandatory.
+
+### Position and Angle
+The body definition gives you the chance to initialize the position of
+the body on creation. This has far better performance than creating the
+body at the world origin and then moving the body.
+
+> **Caution**:
+> Do not create a body at the origin and then move it. If you create
+> several bodies at the origin, then performance will suffer.
+
+A body has two main points of interest. The first point is the body's
+origin. Fixtures and joints are attached relative to the body's origin.
+The second point of interest is the center of mass. The center of mass
+is determined from mass distribution of the attached shapes or is
+explicitly set with b2MassData. Much of Box2D's internal computations
+use the center of mass position. For example b2Body stores the linear
+velocity for the center of mass.
+
+When you are building the body definition, you may not know where the
+center of mass is located. Therefore you specify the position of the
+body's origin. You may also specify the body's angle in radians, which
+is not affected by the position of the center of mass. If you later
+change the mass properties of the body, then the center of mass may move
+on the body, but the origin position does not change and the attached
+shapes and joints do not move.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.position.Set(0.0f, 2.0f); // the body's origin position.
+bodyDef.angle = 0.25f * b2_pi; // the body's angle in radians.
+```
+
+A rigid body is also a frame of reference. You can define fixtures and
+joints in that frame. Those fixtures and joint anchors never move in the
+local frame of the body.
+
+### Damping
+Damping is used to reduce the world velocity of bodies. Damping is
+different than friction because friction only occurs with contact.
+Damping is not a replacement for friction and the two effects should be
+used together.
+
+Damping parameters should be between 0 and infinity, with 0 meaning no
+damping, and infinity meaning full damping. Normally you will use a
+damping value between 0 and 0.1. I generally do not use linear damping
+because it makes bodies look like they are floating.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.linearDamping = 0.0f;
+bodyDef.angularDamping = 0.01f;
+```
+
+Damping is approximated for stability and performance. At small damping
+values the damping effect is mostly independent of the time step. At
+larger damping values, the damping effect will vary with the time step.
+This is not an issue if you use a fixed time step (recommended).
+
+### Gravity Scale
+You can use the gravity scale to adjust the gravity on a single body. Be
+careful though, increased gravity can decrease stability.
+
+```cpp
+// Set the gravity scale to zero so this body will float
+b2BodyDef bodyDef;
+bodyDef.gravityScale = 0.0f;
+```
+
+### Sleep Parameters
+What does sleep mean? Well it is expensive to simulate bodies, so the
+less we have to simulate the better. When a body comes to rest we would
+like to stop simulating it.
+
+When Box2D determines that a body (or group of bodies) has come to rest,
+the body enters a sleep state which has very little CPU overhead. If a
+body is awake and collides with a sleeping body, then the sleeping body
+wakes up. Bodies will also wake up if a joint or contact attached to
+them is destroyed. You can also wake a body manually.
+
+The body definition lets you specify whether a body can sleep and
+whether a body is created sleeping.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.allowSleep = true;
+bodyDef.awake = true;
+```
+
+### Fixed Rotation
+You may want a rigid body, such as a character, to have a fixed
+rotation. Such a body should not rotate, even under load. You can use
+the fixed rotation setting to achieve this:
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.fixedRotation = true;
+```
+
+The fixed rotation flag causes the rotational inertia and its inverse to
+be set to zero.
+
+### Bullets
+Game simulation usually generates a sequence of images that are played
+at some frame rate. This is called discrete simulation. In discrete
+simulation, rigid bodies can move by a large amount in one time step. If
+a physics engine doesn't account for the large motion, you may see some
+objects incorrectly pass through each other. This effect is called
+tunneling.
+
+By default, Box2D uses continuous collision detection (CCD) to prevent
+dynamic bodies from tunneling through static bodies. This is done by
+sweeping shapes from their old position to their new positions. The
+engine looks for new collisions during the sweep and computes the time
+of impact (TOI) for these collisions. Bodies are moved to their first
+TOI and then the solver performs a sub-step to complete the full time
+step. There may be additional TOI events within a sub-step.
+
+Normally CCD is not used between dynamic bodies. This is done to keep
+performance reasonable. In some game scenarios you need dynamic bodies
+to use CCD. For example, you may want to shoot a high speed bullet at a
+stack of dynamic bricks. Without CCD, the bullet might tunnel through
+the bricks.
+
+Fast moving objects in Box2D can be labeled as bullets. Bullets will
+perform CCD with both static and dynamic bodies. You should decide what
+bodies should be bullets based on your game design. If you decide a body
+should be treated as a bullet, use the following setting.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.bullet = true;
+```
+
+The bullet flag only affects dynamic bodies.
+
+### Activation
+You may wish a body to be created but not participate in collision or
+dynamics. This state is similar to sleeping except the body will not be
+woken by other bodies and the body's fixtures will not be placed in the
+broad-phase. This means the body will not participate in collisions, ray
+casts, etc.
+
+You can create a body in an inactive state and later re-activate it.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.active = true;
+```
+
+Joints may be connected to inactive bodies. These joints will not be
+simulated. You should be careful when you activate a body that its
+joints are not distorted.
+
+Note that activating a body is almost as expensive as creating the body
+from scratch. So you should not use activation for streaming worlds. Use
+creation/destruction for streaming worlds to save memory.
+
+### User Data
+User data is a void pointer. This gives you a hook to link your
+application objects to bodies. You should be consistent to use the same
+object type for all body user data.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.userData.pointer = reinterpret_cast<uintptr_t>(&myActor);
+```
+
+### Body Factory
+Bodies are created and destroyed using a body factory provided by the
+world class. This lets the world create the body with an efficient
+allocator and add the body to the world data structure.
+
+```cpp
+b2World* myWorld;
+b2Body* dynamicBody = myWorld->CreateBody(&bodyDef);
+
+// ... do stuff ...
+
+myWorld->DestroyBody(dynamicBody);
+dynamicBody = nullptr;
+```
+
+> **Caution**:
+> You should never use new or malloc to create a body. The world won't
+> know about the body and the body won't be properly initialized.
+
+Box2D does not keep a reference to the body definition or any of the
+data it holds (except user data pointers). So you can create temporary
+body definitions and reuse the same body definitions.
+
+Box2D allows you to avoid destroying bodies by deleting your b2World
+object, which does all the cleanup work for you. However, you should be
+mindful to nullify body pointers that you keep in your game engine.
+
+When you destroy a body, the attached fixtures and joints are
+automatically destroyed. This has important implications for how you
+manage shape and joint pointers.
+
+### Using a Body
+After creating a body, there are many operations you can perform on the
+body. These include setting mass properties, accessing position and
+velocity, applying forces, and transforming points and vectors.
+
+### Mass Data
+A body has mass (scalar), center of mass (2-vector), and rotational
+inertia (scalar). For static bodies, the mass and rotational inertia are
+set to zero. When a body has fixed rotation, its rotational inertia is
+zero.
+
+Normally the mass properties of a body are established automatically
+when fixtures are added to the body. You can also adjust the mass of a
+body at run-time. This is usually done when you have special game
+scenarios that require altering the mass.
+
+```cpp
+void b2Body::SetMassData(const b2MassData* data);
+```
+
+After setting a body's mass directly, you may wish to revert to the
+natural mass dictated by the fixtures. You can do this with:
+
+```cpp
+void b2Body::ResetMassData();
+```
+
+The body's mass data is available through the following functions:
+
+```cpp
+float b2Body::GetMass() const;
+float b2Body::GetInertia() const;
+const b2Vec2& b2Body::GetLocalCenter() const;
+void b2Body::GetMassData(b2MassData* data) const;
+```
+
+### State Information
+There are many aspects to the body's state. You can access this state
+data efficiently through the following functions:
+
+```cpp
+void b2Body::SetType(b2BodyType type);
+b2BodyType b2Body::GetType();
+void b2Body::SetBullet(bool flag);
+bool b2Body::IsBullet() const;
+void b2Body::SetSleepingAllowed(bool flag);
+bool b2Body::IsSleepingAllowed() const;
+void b2Body::SetAwake(bool flag);
+bool b2Body::IsAwake() const;
+void b2Body::SetEnabled(bool flag);
+bool b2Body::IsEnabled() const;
+void b2Body::SetFixedRotation(bool flag);
+bool b2Body::IsFixedRotation() const;
+```
+
+### Position and Velocity
+You can access the position and rotation of a body. This is common when
+rendering your associated game actor. You can also set the position,
+although this is less common since you will normally use Box2D to
+simulate movement.
+
+```cpp
+bool b2Body::SetTransform(const b2Vec2& position, float angle);
+const b2Transform& b2Body::GetTransform() const;
+const b2Vec2& b2Body::GetPosition() const;
+float b2Body::GetAngle() const;
+```
+
+You can access the center of mass position in local and world
+coordinates. Much of the internal simulation in Box2D uses the center of
+mass. However, you should normally not need to access it. Instead you
+will usually work with the body transform. For example, you may have a
+body that is square. The body origin might be a corner of the square,
+while the center of mass is located at the center of the square.
+
+```cpp
+const b2Vec2& b2Body::GetWorldCenter() const;
+const b2Vec2& b2Body::GetLocalCenter() const;
+```
+
+You can access the linear and angular velocity. The linear velocity is
+for the center of mass. Therefore, the linear velocity may change if the
+mass properties change.
+
+### Forces and Impulses
+You can apply forces, torques, and impulses to a body. When you apply a
+force or an impulse, you provide a world point where the load is
+applied. This often results in a torque about the center of mass.
+
+```cpp
+void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point);
+void b2Body::ApplyTorque(float torque);
+void b2Body::ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point);
+void b2Body::ApplyAngularImpulse(float impulse);
+```
+
+Applying a force, torque, or impulse wakes the body. Sometimes this is
+undesirable. For example, you may be applying a steady force and want to
+allow the body to sleep to improve performance. In this case you can use
+the following code.
+
+```cpp
+if (myBody->IsAwake() == true)
+{
+ myBody->ApplyForce(myForce, myPoint);
+}
+```
+
+### Coordinate Transformations
+The body class has some utility functions to help you transform points
+and vectors between local and world space. If you don't understand
+these concepts, please read \"Essential Mathematics for Games and
+Interactive Applications\" by Jim Van Verth and Lars Bishop. These
+functions are efficient (when inlined).
+
+```cpp
+b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint);
+b2Vec2 b2Body::GetWorldVector(const b2Vec2& localVector);
+b2Vec2 b2Body::GetLocalPoint(const b2Vec2& worldPoint);
+b2Vec2 b2Body::GetLocalVector(const b2Vec2& worldVector);
+```
+
+### Acessing Fixtures, Joints, and Contacts
+You can iterate over a body's fixtures. This is mainly useful if you
+need to access the fixture's user data.
+
+```cpp
+for (b2Fixture* f = body->GetFixtureList(); f; f = f->GetNext())
+{
+ MyFixtureData* data = (MyFixtureData*)f->GetUserData();
+ // do something with data ...
+}
+```
+
+You can similarly iterate over the body's joint list.
+
+The body also provides a list of associated contacts. You can use this
+to get information about the current contacts. Be careful, because the
+contact list may not contain all the contacts that existed during the
+previous time step.
+
+## Fixtures
+Recall that shapes don't know about bodies and may be used independently
+of the physics simulation. Therefore Box2D provides the b2Fixture class
+to attach shapes to bodies. A body may have zero or more fixtures. A
+body with multiple fixtures is sometimes called a *compound body.*
+
+Fixtures hold the following:
+- a single shape
+- broad-phase proxies
+- density, friction, and restitution
+- collision filtering flags
+- back pointer to the parent body
+- user data
+- sensor flag
+
+These are described in the following sections.
+
+### Fixture Creation
+Fixtures are created by initializing a fixture definition and then
+passing the definition to the parent body.
+
+```cpp
+b2Body* myBody;
+b2FixtureDef fixtureDef;
+fixtureDef.shape = &myShape;
+fixtureDef.density = 1.0f;
+b2Fixture* myFixture = myBody->CreateFixture(&fixtureDef);
+```
+
+This creates the fixture and attaches it to the body. You do not need to
+store the fixture pointer since the fixture will automatically be
+destroyed when the parent body is destroyed. You can create multiple
+fixtures on a single body.
+
+You can destroy a fixture on the parent body. You may do this to model a
+breakable object. Otherwise you can just leave the fixture alone and let
+the body destruction take care of destroying the attached fixtures.
+
+```cpp
+myBody->DestroyFixture(myFixture);
+```
+
+### Density
+The fixture density is used to compute the mass properties of the parent
+body. The density can be zero or positive. You should generally use
+similar densities for all your fixtures. This will improve stacking
+stability.
+
+The mass of a body is not adjusted when you set the density. You must
+call ResetMassData for this to occur.
+
+```cpp
+b2Fixture* fixture;
+fixture->SetDensity(5.0f);
+b2Body*
+body->ResetMassData();
+```
+
+### Friction
+Friction is used to make objects slide along each other realistically.
+Box2D supports static and dynamic friction, but uses the same parameter
+for both. Friction is simulated accurately in Box2D and the friction
+strength is proportional to the normal force (this is called Coulomb
+friction). The friction parameter is usually set between 0 and 1, but
+can be any non-negative value. A friction value of 0 turns off friction
+and a value of 1 makes the friction strong. When the friction force is
+computed between two shapes, Box2D must combine the friction parameters
+of the two parent fixtures. This is done with the geometric mean:
+
+```cpp
+b2Fixture* fixtureA;
+b2Fixture* fixtureB;
+float friction;
+friction = sqrtf(fixtureA->friction * fixtureB->friction);
+```
+
+So if one fixture has zero friction then the contact will have zero
+friction.
+
+You can override the default mixed friction using
+`b2Contact::SetFriction`. This is usually done in the `b2ContactListener`
+callback.
+
+### Restitution
+Restitution is used to make objects bounce. The restitution value is
+usually set to be between 0 and 1. Consider dropping a ball on a table.
+A value of zero means the ball won't bounce. This is called an
+inelastic collision. A value of one means the ball's velocity will be
+exactly reflected. This is called a perfectly elastic collision.
+Restitution is combined using the following formula.
+
+```cpp
+b2Fixture* fixtureA;
+b2Fixture* fixtureB;
+float restitution;
+restitution = b2Max(fixtureA->restitution, fixtureB->restitution);
+```
+
+Restitution is combined this way so that you can have a bouncy super
+ball without having a bouncy floor.
+
+You can override the default mixed restitution using
+`b2Contact::SetRestitution`. This is usually done in the b2ContactListener
+callback.
+
+When a shape develops multiple contacts, restitution is simulated
+approximately. This is because Box2D uses an iterative solver. Box2D
+also uses inelastic collisions when the collision velocity is small.
+This is done to prevent jitter. See `b2_velocityThreshold`.
+
+### Filtering
+Collision filtering allows you to prevent collision between fixtures.
+For example, say you make a character that rides a bicycle. You want the
+bicycle to collide with the terrain and the character to collide with
+the terrain, but you don't want the character to collide with the
+bicycle (because they must overlap). Box2D supports such collision
+filtering using categories and groups.
+
+Box2D supports 16 collision categories. For each fixture you can specify
+which category it belongs to. You also specify what other categories
+this fixture can collide with. For example, you could specify in a
+multiplayer game that all players don't collide with each other and
+monsters don't collide with each other, but players and monsters should
+collide. This is done with masking bits. For example:
+
+```cpp
+b2FixtureDef playerFixtureDef, monsterFixtureDef;
+playerFixtureDef.filter.categoryBits = 0x0002;
+monsterFixtureDef.filter.categoryBits = 0x0004;
+playerFixtureDef.filter.maskBits = 0x0004;
+monsterFixtureDef.filter.maskBits = 0x0002;
+```
+
+Here is the rule for a collision to occur:
+
+```cpp
+uint16 catA = fixtureA.filter.categoryBits;
+uint16 maskA = fixtureA.filter.maskBits;
+uint16 catB = fixtureB.filter.categoryBits;
+uint16 maskB = fixtureB.filter.maskBits;
+
+if ((catA & maskB) != 0 && (catB & maskA) != 0)
+{
+ // fixtures can collide
+}
+```
+
+Collision groups let you specify an integral group index. You can have
+all fixtures with the same group index always collide (positive index)
+or never collide (negative index). Group indices are usually used for
+things that are somehow related, like the parts of a bicycle. In the
+following example, fixture1 and fixture2 always collide, but fixture3
+and fixture4 never collide.
+
+```cpp
+fixture1Def.filter.groupIndex = 2;
+fixture2Def.filter.groupIndex = 2;
+fixture3Def.filter.groupIndex = -8;
+fixture4Def.filter.groupIndex = -8;
+```
+
+Collisions between fixtures of different group indices are filtered
+according the category and mask bits. In other words, group filtering
+has higher precedence than category filtering.
+
+Note that additional collision filtering occurs in Box2D. Here is a
+list:
+- A fixture on a static body can only collide with a dynamic body.
+- A fixture on a kinematic body can only collide with a dynamic body.
+- Fixtures on the same body never collide with each other.
+- You can optionally enable/disable collision between fixtures on bodies connected by a joint.
+
+Sometimes you might need to change collision filtering after a fixture
+has already been created. You can get and set the b2Filter structure on
+an existing fixture using b2Fixture::GetFilterData and
+b2Fixture::SetFilterData. Note that changing the filter data will not
+add or remove contacts until the next time step (see the World class).
+
+### Sensors
+Sometimes game logic needs to know when two fixtures overlap yet there
+should be no collision response. This is done by using sensors. A sensor
+is a fixture that detects collision but does not produce a response.
+
+You can flag any fixture as being a sensor. Sensors may be static,
+kinematic, or dynamic. Remember that you may have multiple fixtures per
+body and you can have any mix of sensors and solid fixtures. Also,
+sensors only form contacts when at least one body is dynamic, so you
+will not get a contact for kinematic versus kinematic, kinematic versus
+static, or static versus static.
+
+Sensors do not generate contact points. There are two ways to get the
+state of a sensor:
+1. `b2Contact::IsTouching`
+2. `b2ContactListener::BeginContact` and `b2ContactListener::EndContact`
+
+## Joints
+Joints are used to constrain bodies to the world or to each other.
+Typical examples in games include ragdolls, teeters, and pulleys. Joints
+can be combined in many different ways to create interesting motions.
+
+Some joints provide limits so you can control the range of motion. Some
+joint provide motors which can be used to drive the joint at a
+prescribed speed until a prescribed force/torque is exceeded.
+
+Joint motors can be used in many ways. You can use motors to control
+position by specifying a joint velocity that is proportional to the
+difference between the actual and desired position. You can also use
+motors to simulate joint friction: set the joint velocity to zero and
+provide a small, but significant maximum motor force/torque. Then the
+motor will attempt to keep the joint from moving until the load becomes
+too strong.
+
+### Joint Definition
+Each joint type has a definition that derives from b2JointDef. All
+joints are connected between two different bodies. One body may static.
+Joints between static and/or kinematic bodies are allowed, but have no
+effect and use some processing time.
+
+You can specify user data for any joint type and you can provide a flag
+to prevent the attached bodies from colliding with each other. This is
+actually the default behavior and you must set the collideConnected
+Boolean to allow collision between to connected bodies.
+
+Many joint definitions require that you provide some geometric data.
+Often a joint will be defined by anchor points. These are points fixed
+in the attached bodies. Box2D requires these points to be specified in
+local coordinates. This way the joint can be specified even when the
+current body transforms violate the joint constraint \-\-- a common
+occurrence when a game is saved and reloaded. Additionally, some joint
+definitions need to know the default relative angle between the bodies.
+This is necessary to constrain rotation correctly.
+
+Initializing the geometric data can be tedious, so many joints have
+initialization functions that use the current body transforms to remove
+much of the work. However, these initialization functions should usually
+only be used for prototyping. Production code should define the geometry
+directly. This will make joint behavior more robust.
+
+The rest of the joint definition data depends on the joint type. We
+cover these now.
+
+### Joint Factory
+Joints are created and destroyed using the world factory methods. This
+brings up an old issue:
+
+> **Caution**:
+> Don't try to create a joint on the stack or on the heap using new or
+> malloc. You must create and destroy bodies and joints using the create
+> and destroy methods of the b2World class.
+
+Here's an example of the lifetime of a revolute joint:
+
+```cpp
+b2World* myWorld;
+b2RevoluteJointDef jointDef;
+jointDef.bodyA = myBodyA;
+jointDef.bodyB = myBodyB;
+jointDef.anchorPoint = myBodyA->GetCenterPosition();
+
+b2RevoluteJoint* joint = (b2RevoluteJoint*)myWorld->CreateJoint(&jointDef);
+
+// ... do stuff ...
+
+myWorld->DestroyJoint(joint);
+joint = nullptr;
+```
+
+It is always good to nullify your pointer after they are destroyed. This
+will make the program crash in a controlled manner if you try to reuse
+the pointer.
+
+The lifetime of a joint is not simple. Heed this warning well:
+
+> **Caution**:
+> Joints are destroyed when an attached body is destroyed.
+
+This precaution is not always necessary. You may organize your game
+engine so that joints are always destroyed before the attached bodies.
+In this case you don't need to implement the listener class. See the
+section on Implicit Destruction for details.
+
+### Using Joints
+Many simulations create the joints and don't access them again until
+they are destroyed. However, there is a lot of useful data contained in
+joints that you can use to create a rich simulation.
+
+First of all, you can get the bodies, anchor points, and user data from
+a joint.
+
+```cpp
+b2Body* b2Joint::GetBodyA();
+b2Body* b2Joint::GetBodyB();
+b2Vec2 b2Joint::GetAnchorA();
+b2Vec2 b2Joint::GetAnchorB();
+void* b2Joint::GetUserData();
+```
+
+All joints have a reaction force and torque. This the reaction force
+applied to body 2 at the anchor point. You can use reaction forces to
+break joints or trigger other game events. These functions may do some
+computations, so don't call them if you don't need the result.
+
+```cpp
+b2Vec2 b2Joint::GetReactionForce();
+float b2Joint::GetReactionTorque();
+```
+
+### Distance Joint
+One of the simplest joint is a distance joint which says that the
+distance between two points on two bodies must be constant. When you
+specify a distance joint the two bodies should already be in place. Then
+you specify the two anchor points in world coordinates. The first anchor
+point is connected to body 1, and the second anchor point is connected
+to body 2. These points imply the length of the distance constraint.
+
+![Distance Joint](images/distance_joint.gif)
+
+Here is an example of a distance joint definition. In this case we
+decide to allow the bodies to collide.
+
+```cpp
+b2DistanceJointDef jointDef;
+jointDef.Initialize(myBodyA, myBodyB, worldAnchorOnBodyA,
+worldAnchorOnBodyB);
+jointDef.collideConnected = true;
+```
+
+The distance joint can also be made soft, like a spring-damper
+connection. See the Web example in the testbed to see how this behaves.
+
+Softness is achieved by tuning two constants in the definition:
+stiffness and damping. It can be non-intuitive setting these values directly
+since they have units in terms on Newtons. Box2D provides and API to compute
+these values in terms of frequency and damping ratio.
+```cpp
+void b2LinearStiffness(float& stiffness, float& damping,
+ float frequencyHertz, float dampingRatio,
+ const b2Body* bodyA, const b2Body* bodyB);
+```
+
+Think of the frequency as the frequency of a harmonic oscillator (like a
+guitar string). The frequency is specified in Hertz. Typically the frequency
+should be less than a half the frequency of the time step. So if you are using
+a 60Hz time step, the frequency of the distance joint should be less than 30Hz.
+The reason is related to the Nyquist frequency.
+
+The damping ratio is non-dimensional and is typically between 0 and 1,
+but can be larger. At 1, the damping is critical (all oscillations
+should vanish).
+
+```cpp
+float frequencyHz = 4.0f;
+float dampingRatio = 0.5f;
+b2LinearStiffness(jointDef.stiffness, jointDef.damping, frequencyHz, dampingRatio, jointDef.bodyA, jointDef.bodyB);
+```
+
+It is also possible to define a minimum and maximum length for the distance joint.
+See `b2DistanceJointDef` for details.
+
+### Revolute Joint
+A revolute joint forces two bodies to share a common anchor point, often
+called a hinge point. The revolute joint has a single degree of freedom:
+the relative rotation of the two bodies. This is called the joint angle.
+
+![Revolute Joint](images/revolute_joint.gif)
+
+To specify a revolute you need to provide two bodies and a single anchor
+point in world space. The initialization function assumes that the
+bodies are already in the correct position.
+
+In this example, two bodies are connected by a revolute joint at the
+first body's center of mass.
+
+```cpp
+b2RevoluteJointDef jointDef;
+jointDef.Initialize(myBodyA, myBodyB, myBodyA->GetWorldCenter());
+```
+
+The revolute joint angle is positive when bodyB rotates CCW about the
+angle point. Like all angles in Box2D, the revolute angle is measured in
+radians. By convention the revolute joint angle is zero when the joint
+is created using Initialize(), regardless of the current rotation of the
+two bodies.
+
+In some cases you might wish to control the joint angle. For this, the
+revolute joint can optionally simulate a joint limit and/or a motor.
+
+A joint limit forces the joint angle to remain between a lower and upper
+bound. The limit will apply as much torque as needed to make this
+happen. The limit range should include zero, otherwise the joint will
+lurch when the simulation begins.
+
+A joint motor allows you to specify the joint speed (the time derivative
+of the angle). The speed can be negative or positive. A motor can have
+infinite force, but this is usually not desirable. Recall the eternal
+question:
+
+> *What happens when an irresistible force meets an immovable object?*
+
+I can tell you it's not pretty. So you can provide a maximum torque for
+the joint motor. The joint motor will maintain the specified speed
+unless the required torque exceeds the specified maximum. When the
+maximum torque is exceeded, the joint will slow down and can even
+reverse.
+
+You can use a joint motor to simulate joint friction. Just set the joint
+speed to zero, and set the maximum torque to some small, but significant
+value. The motor will try to prevent the joint from rotating, but will
+yield to a significant load.
+
+Here's a revision of the revolute joint definition above; this time the
+joint has a limit and a motor enabled. The motor is setup to simulate
+joint friction.
+
+```cpp
+b2RevoluteJointDef jointDef;
+jointDef.Initialize(bodyA, bodyB, myBodyA->GetWorldCenter());
+jointDef.lowerAngle = -0.5f * b2_pi; // -90 degrees
+jointDef.upperAngle = 0.25f * b2_pi; // 45 degrees
+jointDef.enableLimit = true;
+jointDef.maxMotorTorque = 10.0f;
+jointDef.motorSpeed = 0.0f;
+jointDef.enableMotor = true;
+```
+You can access a revolute joint's angle, speed, and motor torque.
+
+```cpp
+float b2RevoluteJoint::GetJointAngle() const;
+float b2RevoluteJoint::GetJointSpeed() const;
+float b2RevoluteJoint::GetMotorTorque() const;
+```
+
+You also update the motor parameters each step.
+
+```cpp
+void b2RevoluteJoint::SetMotorSpeed(float speed);
+void b2RevoluteJoint::SetMaxMotorTorque(float torque);
+```
+
+Joint motors have some interesting abilities. You can update the joint
+speed every time step so you can make the joint move back-and-forth like
+a sine-wave or according to whatever function you want.
+
+```cpp
+// ... Game Loop Begin ...
+
+myJoint->SetMotorSpeed(cosf(0.5f * time));
+
+// ... Game Loop End ...
+```
+
+You can also use joint motors to track a desired joint angle. For example:
+
+```cpp
+// ... Game Loop Begin ...
+
+float angleError = myJoint->GetJointAngle() - angleTarget;
+float gain = 0.1f;
+myJoint->SetMotorSpeed(-gain * angleError);
+
+// ... Game Loop End ...
+```
+
+Generally your gain parameter should not be too large. Otherwise your
+joint may become unstable.
+
+### Prismatic Joint
+A prismatic joint allows for relative translation of two bodies along a
+specified axis. A prismatic joint prevents relative rotation. Therefore,
+a prismatic joint has a single degree of freedom.
+
+![Prismatic Joint](images/prismatic_joint.gif)
+
+The prismatic joint definition is similar to the revolute joint
+description; just substitute translation for angle and force for torque.
+Using this analogy provides an example prismatic joint definition with a
+joint limit and a friction motor:
+
+```cpp
+b2PrismaticJointDef jointDef;
+b2Vec2 worldAxis(1.0f, 0.0f);
+jointDef.Initialize(myBodyA, myBodyB, myBodyA->GetWorldCenter(), worldAxis);
+jointDef.lowerTranslation = -5.0f;
+jointDef.upperTranslation = 2.5f;
+jointDef.enableLimit = true;
+jointDef.maxMotorForce = 1.0f;
+jointDef.motorSpeed = 0.0f;
+jointDef.enableMotor = true;
+```
+
+The revolute joint has an implicit axis coming out of the screen. The
+prismatic joint needs an explicit axis parallel to the screen. This axis
+is fixed in the two bodies and follows their motion.
+
+Like the revolute joint, the prismatic joint translation is zero when
+the joint is created using Initialize(). So be sure zero is between your
+lower and upper translation limits.
+
+Using a prismatic joint is similar to using a revolute joint. Here are
+the relevant member functions:
+
+```cpp
+float PrismaticJoint::GetJointTranslation() const;
+float PrismaticJoint::GetJointSpeed() const;
+float PrismaticJoint::GetMotorForce() const;
+void PrismaticJoint::SetMotorSpeed(float speed);
+void PrismaticJoint::SetMotorForce(float force);
+```
+
+### Pulley Joint
+A pulley is used to create an idealized pulley. The pulley connects two
+bodies to ground and to each other. As one body goes up, the other goes
+down. The total length of the pulley rope is conserved according to the
+initial configuration.
+
+```
+length1 + length2 == constant
+```
+
+You can supply a ratio that simulates a block and tackle. This causes
+one side of the pulley to extend faster than the other. At the same time
+the constraint force is smaller on one side than the other. You can use
+this to create mechanical leverage.
+
+```
+length1 + ratio * length2 == constant
+```
+
+For example, if the ratio is 2, then length1 will vary at twice the rate
+of length2. Also the force in the rope attached to body1 will have half
+the constraint force as the rope attached to body2.
+
+![Pulley Joint](images/pulley_joint.gif)
+
+Pulleys can be troublesome when one side is fully extended. The rope on
+the other side will have zero length. At this point the constraint
+equations become singular (bad). You should configure collision shapes
+to prevent this.
+
+Here is an example pulley definition:
+
+```cpp
+b2Vec2 anchor1 = myBody1->GetWorldCenter();
+b2Vec2 anchor2 = myBody2->GetWorldCenter();
+
+b2Vec2 groundAnchor1(p1.x, p1.y + 10.0f);
+b2Vec2 groundAnchor2(p2.x, p2.y + 12.0f);
+
+float ratio = 1.0f;
+
+b2PulleyJointDef jointDef;
+jointDef.Initialize(myBody1, myBody2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio);
+```
+
+Pulley joints provide the current lengths.
+
+```cpp
+float PulleyJoint::GetLengthA() const;
+float PulleyJoint::GetLengthB() const;
+```
+
+### Gear Joint
+If you want to create a sophisticated mechanical contraption you might
+want to use gears. In principle you can create gears in Box2D by using
+compound shapes to model gear teeth. This is not very efficient and
+might be tedious to author. You also have to be careful to line up the
+gears so the teeth mesh smoothly. Box2D has a simpler method of creating
+gears: the gear joint.
+
+![Gear Joint](images/gear_joint.gif)
+
+The gear joint can only connect revolute and/or prismatic joints.
+
+Like the pulley ratio, you can specify a gear ratio. However, in this
+case the gear ratio can be negative. Also keep in mind that when one
+joint is a revolute joint (angular) and the other joint is prismatic
+(translation), and then the gear ratio will have units of length or one
+over length.
+
+```
+coordinate1 + ratio * coordinate2 == constant
+```
+
+Here is an example gear joint. The bodies myBodyA and myBodyB are any
+bodies from the two joints, as long as they are not the same bodies.
+
+```cpp
+b2GearJointDef jointDef;
+jointDef.bodyA = myBodyA;
+jointDef.bodyB = myBodyB;
+jointDef.joint1 = myRevoluteJoint;
+jointDef.joint2 = myPrismaticJoint;
+jointDef.ratio = 2.0f * b2_pi / myLength;
+```
+
+Note that the gear joint depends on two other joints. This creates a
+fragile situation. What happens if those joints are deleted?
+
+> **Caution**:
+> Always delete gear joints before the revolute/prismatic joints on the
+> gears. Otherwise your code will crash in a bad way due to the orphaned
+> joint pointers in the gear joint. You should also delete the gear joint
+> before you delete any of the bodies involved.
+
+### Mouse Joint
+The mouse joint is used in the testbed to manipulate bodies with the
+mouse. It attempts to drive a point on a body towards the current
+position of the cursor. There is no restriction on rotation.
+
+The mouse joint definition has a target point, maximum force, frequency,
+and damping ratio. The target point initially coincides with the body's
+anchor point. The maximum force is used to prevent violent reactions
+when multiple dynamic bodies interact. You can make this as large as you
+like. The frequency and damping ratio are used to create a spring/damper
+effect similar to the distance joint.
+
+Many users have tried to adapt the mouse joint for game play. Users
+often want to achieve precise positioning and instantaneous response.
+The mouse joint doesn't work very well in that context. You may wish to
+consider using kinematic bodies instead.
+
+### Wheel Joint
+The wheel joint restricts a point on bodyB to a line on bodyA. The wheel
+joint also provides a suspension spring. See b2WheelJoint.h and Car.h
+for details.
+
+![Wheel Joint](images/wheel_joint.svg)
+
+### Weld Joint
+The weld joint attempts to constrain all relative motion between two
+bodies. See the Cantilever.h in the testbed to see how the weld joint
+behaves.
+
+It is tempting to use the weld joint to define breakable structures.
+However, the Box2D solver is iterative so the joints are a bit soft. So
+chains of bodies connected by weld joints will flex.
+
+Instead it is better to create breakable bodies starting with a single
+body with multiple fixtures. When the body breaks, you can destroy a
+fixture and recreate it on a new body. See the Breakable example in the
+testbed.
+
+### Rope Joint
+The rope joint restricts the maximum distance between two points. This
+can be useful to prevent chains of bodies from stretching, even under
+high load. See b2RopeJoint.h and rope_joint.cpp for details.
+
+### Friction Joint
+The friction joint is used for top-down friction. The joint provides 2D
+translational friction and angular friction. See b2FrictionJoint.h and
+apply_force.cpp for details.
+
+### Motor Joint
+A motor joint lets you control the motion of a body by specifying target
+position and rotation offsets. You can set the maximum motor force and
+torque that will be applied to reach the target position and rotation.
+If the body is blocked, it will stop and the contact forces will be
+proportional the maximum motor force and torque. See b2MotorJoint and
+motor_joint.cpp for details.
+
+### Wheel Joint
+The wheel joint is designed specifically for vehicles. It provides a translation
+and rotation. The translation has a spring and damper to simulate the vehicle
+suspension. The rotation allows the wheel to rotate. You can specify an rotational
+motor to drive the wheel and to apply braking. See b2WheelJoint, wheel_joint.cpp,
+and car.cpp for details.
+
+## Contacts
+Contacts are objects created by Box2D to manage collision between two
+fixtures. If the fixture has children, such as a chain shape, then a
+contact exists for each relevant child. There are different kinds of
+contacts, derived from b2Contact, for managing contact between different
+kinds of fixtures. For example there is a contact class for managing
+polygon-polygon collision and another contact class for managing
+circle-circle collision.
+
+Here is some terminology associated with contacts.
+
+##### contact point
+A contact point is a point where two shapes touch. Box2D approximates
+contact with a small number of points.
+
+##### contact normal
+A contact normal is a unit vector that points from one shape to another.
+By convention, the normal points from fixtureA to fixtureB.
+
+##### contact separation
+Separation is the opposite of penetration. Separation is negative when
+shapes overlap. It is possible that future versions of Box2D will create
+contact points with positive separation, so you may want to check the
+sign when contact points are reported.
+
+##### contact manifold
+Contact between two convex polygons may generate up to 2 contact points.
+Both of these points use the same normal, so they are grouped into a
+contact manifold, which is an approximation of a continuous region of
+contact.
+
+##### normal impulse
+The normal force is the force applied at a contact point to prevent the
+shapes from penetrating. For convenience, Box2D works with impulses. The
+normal impulse is just the normal force multiplied by the time step.
+
+##### tangent impulse
+The tangent force is generated at a contact point to simulate friction.
+For convenience, this is stored as an impulse.
+
+##### contact ids
+Box2D tries to re-use the contact force results from a time step as the
+initial guess for the next time step. Box2D uses contact ids to match
+contact points across time steps. The ids contain geometric features
+indices that help to distinguish one contact point from another.
+
+Contacts are created when two fixture's AABBs overlap. Sometimes
+collision filtering will prevent the creation of contacts. Contacts are
+destroyed with the AABBs cease to overlap.
+
+So you might gather that there may be contacts created for fixtures that
+are not touching (just their AABBs). Well, this is correct. It's a
+\"chicken or egg\" problem. We don't know if we need a contact object
+until one is created to analyze the collision. We could delete the
+contact right away if the shapes are not touching, or we can just wait
+until the AABBs stop overlapping. Box2D takes the latter approach
+because it lets the system cache information to improve performance.
+
+### Contact Class
+As mentioned before, the contact class is created and destroyed by
+Box2D. Contact objects are not created by the user. However, you are
+able to access the contact class and interact with it.
+
+You can access the raw contact manifold:
+
+```cpp
+b2Manifold* b2Contact::GetManifold();
+const b2Manifold* b2Contact::GetManifold() const;
+```
+
+You can potentially modify the manifold, but this is generally not
+supported and is for advanced usage.
+
+There is a helper function to get the `b2WorldManifold`:
+
+```cpp
+void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const;
+```
+
+This uses the current positions of the bodies to compute world positions
+of the contact points.
+
+Sensors do not create manifolds, so for them use:
+
+```cpp
+bool touching = sensorContact->IsTouching();
+```
+
+This function also works for non-sensors.
+
+You can get the fixtures from a contact. From those you can get the
+bodies.
+
+```cpp
+b2Fixture* fixtureA = myContact->GetFixtureA();
+b2Body* bodyA = fixtureA->GetBody();
+MyActor* actorA = (MyActor*)bodyA->GetUserData().pointer;
+```
+
+You can disable a contact. This only works inside the
+b2ContactListener::PreSolve event, discussed below.
+
+### Accessing Contacts
+You can get access to contacts in several ways. You can access the
+contacts directly on the world and body structures. You can also
+implement a contact listener.
+
+You can iterate over all contacts in the world:
+
+```cpp
+for (b2Contact* c = myWorld->GetContactList(); c; c = c->GetNext())
+{
+ // process c
+}
+```
+
+You can also iterate over all the contacts on a body. These are stored
+in a graph using a contact edge structure.
+
+```cpp
+for (b2ContactEdge* ce = myBody->GetContactList(); ce; ce = ce->next)
+{
+ b2Contact* c = ce->contact;
+ // process c
+}
+```
+
+You can also access contacts using the contact listener that is
+described below.
+
+> **Caution**:
+> Accessing contacts off b2World and b2Body may miss some transient
+> contacts that occur in the middle of the time step. Use
+> b2ContactListener to get the most accurate results.
+
+### Contact Listener
+You can receive contact data by implementing b2ContactListener. The
+contact listener supports several events: begin, end, pre-solve, and
+post-solve.
+
+```cpp
+class MyContactListener : public b2ContactListener
+{
+public:
+
+void BeginContact(b2Contact* contact)
+{ /* handle begin event */ }
+
+void EndContact(b2Contact* contact)
+{ /* handle end event */ }
+
+void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+{ /* handle pre-solve event */ }
+
+void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
+{ /* handle post-solve event */ }
+};
+```
+
+> **Caution**:
+> Do not keep a reference to the pointers sent to b2ContactListener.
+> Instead make a deep copy of the contact point data into your own buffer.
+> The example below shows one way of doing this.
+
+At run-time you can create an instance of the listener and register it
+with b2World::SetContactListener. Be sure your listener remains in scope
+while the world object exists.
+
+#### Begin Contact Event
+This is called when two fixtures begin to overlap. This is called for
+sensors and non-sensors. This event can only occur inside the time step.
+
+#### End Contact Event
+This is called when two fixtures cease to overlap. This is called for
+sensors and non-sensors. This may be called when a body is destroyed, so
+this event can occur outside the time step.
+
+#### Pre-Solve Event
+This is called after collision detection, but before collision
+resolution. This gives you a chance to disable the contact based on the
+current configuration. For example, you can implement a one-sided
+platform using this callback and calling b2Contact::SetEnabled(false).
+The contact will be re-enabled each time through collision processing,
+so you will need to disable the contact every time-step. The pre-solve
+event may be fired multiple times per time step per contact due to
+continuous collision detection.
+
+```cpp
+void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+{
+ b2WorldManifold worldManifold;
+ contact->GetWorldManifold(&worldManifold);
+ if (worldManifold.normal.y < -0.5f)
+ {
+ contact->SetEnabled(false);
+ }
+}
+```
+
+The pre-solve event is also a good place to determine the point state
+and the approach velocity of collisions.
+
+```cpp
+void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+{
+ b2WorldManifold worldManifold;
+ contact->GetWorldManifold(&worldManifold);
+
+ b2PointState state1[2], state2[2];
+ b2GetPointStates(state1, state2, oldManifold, contact->GetManifold());
+
+ if (state2[0] == b2_addState)
+ {
+ const b2Body* bodyA = contact->GetFixtureA()->GetBody();
+ const b2Body* bodyB = contact->GetFixtureB()->GetBody();
+ b2Vec2 point = worldManifold.points[0];
+ b2Vec2 vA = bodyA->GetLinearVelocityFromWorldPoint(point);
+ b2Vec2 vB = bodyB->GetLinearVelocityFromWorldPoint(point);
+
+ float approachVelocity = b2Dot(vB -- vA, worldManifold.normal);
+
+ if (approachVelocity > 1.0f)
+ {
+ MyPlayCollisionSound();
+ }
+ }
+}
+```
+
+#### Post-Solve Event
+The post solve event is where you can gather collision impulse results.
+If you don't care about the impulses, you should probably just implement
+the pre-solve event.
+
+It is tempting to implement game logic that alters the physics world
+inside a contact callback. For example, you may have a collision that
+applies damage and try to destroy the associated actor and its rigid
+body. However, Box2D does not allow you to alter the physics world
+inside a callback because you might destroy objects that Box2D is
+currently processing, leading to orphaned pointers.
+
+The recommended practice for processing contact points is to buffer all
+contact data that you care about and process it after the time step. You
+should always process the contact points immediately after the time
+step; otherwise some other client code might alter the physics world,
+invalidating the contact buffer. When you process the contact buffer you
+can alter the physics world, but you still need to be careful that you
+don't orphan pointers stored in the contact point buffer. The testbed
+has example contact point processing that is safe from orphaned
+pointers.
+
+This code from the CollisionProcessing test shows how to handle orphaned
+bodies when processing the contact buffer. Here is an excerpt. Be sure
+to read the comments in the listing. This code assumes that all contact
+points have been buffered in the b2ContactPoint array m_points.
+
+```cpp
+// We are going to destroy some bodies according to contact
+// points. We must buffer the bodies that should be destroyed
+// because they may belong to multiple contact points.
+const int32 k_maxNuke = 6;
+b2Body* nuke[k_maxNuke];
+int32 nukeCount = 0;
+
+// Traverse the contact buffer. Destroy bodies that
+// are touching heavier bodies.
+for (int32 i = 0; i < m_pointCount; ++i)
+{
+ ContactPoint* point = m_points + i;
+ b2Body* bodyA = point->fixtureA->GetBody();
+ b2Body* bodyB = point->FixtureB->GetBody();
+ float massA = bodyA->GetMass();
+ float massB = bodyB->GetMass();
+
+ if (massA > 0.0f && massB > 0.0f)
+ {
+ if (massB > massA)
+ {
+ nuke[nukeCount++] = bodyA;
+ }
+ else
+ {
+ nuke[nukeCount++] = bodyB;
+ }
+
+ if (nukeCount == k_maxNuke)
+ {
+ break;
+ }
+ }
+}
+
+// Sort the nuke array to group duplicates.
+std::sort(nuke, nuke + nukeCount);
+
+// Destroy the bodies, skipping duplicates.
+int32 i = 0;
+while (i < nukeCount)
+{
+ b2Body* b = nuke[i++];
+ while (i < nukeCount && nuke[i] == b)
+ {
+ ++i;
+ }
+
+ m_world->DestroyBody(b);
+}
+```
+
+### Contact Filtering
+Often in a game you don't want all objects to collide. For example, you
+may want to create a door that only certain characters can pass through.
+This is called contact filtering, because some interactions are filtered
+out.
+
+Box2D allows you to achieve custom contact filtering by implementing a
+b2ContactFilter class. This class requires you to implement a
+ShouldCollide function that receives two b2Shape pointers. Your function
+returns true if the shapes should collide.
+
+The default implementation of ShouldCollide uses the b2FilterData
+defined in Chapter 6, Fixtures.
+
+```cpp
+bool b2ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
+{
+ const b2Filter& filterA = fixtureA->GetFilterData();
+ const b2Filter& filterB = fixtureB->GetFilterData();
+
+ if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0)
+ {
+ return filterA.groupIndex > 0;
+ }
+
+ bool collideA = (filterA.maskBits & filterB.categoryBits) != 0;
+ bool collideB = (filterA.categoryBits & filterB.maskBits) != 0
+ bool collide = collideA && collideB;
+ return collide;
+}
+```
+
+At run-time you can create an instance of your contact filter and
+register it with b2World::SetContactFilter. Make sure your filter stays
+in scope while the world exists.
+
+```cpp
+MyContactFilter filter;
+world->SetContactFilter(&filter);
+// filter remains in scope ...
+```
+
+## World
+The `b2World` class contains the bodies and joints. It manages all aspects
+of the simulation and allows for asynchronous queries (like AABB queries
+and ray-casts). Much of your interactions with Box2D will be with a
+b2World object.
+
+### Creating and Destroying a World
+Creating a world is fairly simple. You just need to provide a gravity
+vector and a Boolean indicating if bodies can sleep. Usually you will
+create and destroy a world using new and delete.
+
+```cpp
+b2World* myWorld = new b2World(gravity, doSleep);
+
+// ... do stuff ...
+
+delete myWorld;
+```
+
+### Using a World
+The world class contains factories for creating and destroying bodies
+and joints. These factories are discussed later in the sections on
+bodies and joints. There are some other interactions with b2World that I
+will cover now.
+
+### Simulation
+The world class is used to drive the simulation. You specify a time step
+and a velocity and position iteration count. For example:
+
+```cpp
+float timeStep = 1.0f / 60.f;
+int32 velocityIterations = 10;
+int32 positionIterations = 8;
+myWorld->Step(timeStep, velocityIterations, positionIterations);
+```
+
+After the time step you can examine your bodies and joints for
+information. Most likely you will grab the position off the bodies so
+that you can update your actors and render them. You can perform the
+time step anywhere in your game loop, but you should be aware of the
+order of things. For example, you must create bodies before the time
+step if you want to get collision results for the new bodies in that
+frame.
+
+As I discussed above in the HelloWorld tutorial, you should use a fixed
+time step. By using a larger time step you can improve performance in
+low frame rate scenarios. But generally you should use a time step no
+larger than 1/30 seconds. A time step of 1/60 seconds will usually
+deliver a high quality simulation.
+
+The iteration count controls how many times the constraint solver sweeps
+over all the contacts and joints in the world. More iteration always
+yields a better simulation. But don't trade a small time step for a
+large iteration count. 60Hz and 10 iterations is far better than 30Hz
+and 20 iterations.
+
+After stepping, you should clear any forces you have applied to your
+bodies. This is done with the command `b2World::ClearForces`. This lets
+you take multiple sub-steps with the same force field.
+
+```cpp
+myWorld->ClearForces();
+```
+
+### Exploring the World
+The world is a container for bodies, contacts, and joints. You can grab
+the body, contact, and joint lists off the world and iterate over them.
+For example, this code wakes up all the bodies in the world:
+
+```cpp
+for (b2Body* b = myWorld->GetBodyList(); b; b = b->GetNext())
+{
+ b->SetAwake(true);
+}
+```
+
+Unfortunately real programs can be more complicated. For example, the
+following code is broken:
+
+```cpp
+for (b2Body* b = myWorld->GetBodyList(); b; b = b->GetNext())
+{
+ GameActor* myActor = (GameActor*)b->GetUserData().pointer;
+ if (myActor->IsDead())
+ {
+ myWorld->DestroyBody(b); // ERROR: now GetNext returns garbage.
+ }
+}
+```
+
+Everything goes ok until a body is destroyed. Once a body is destroyed,
+its next pointer becomes invalid. So the call to `b2Body::GetNext()` will
+return garbage. The solution to this is to copy the next pointer before
+destroying the body.
+
+```cpp
+b2Body* node = myWorld->GetBodyList();
+while (node)
+{
+ b2Body* b = node;
+ node = node->GetNext();
+
+ GameActor* myActor = (GameActor*)b->GetUserData().pointer;
+ if (myActor->IsDead())
+ {
+ myWorld->DestroyBody(b);
+ }
+}
+```
+
+This safely destroys the current body. However, you may want to call a
+game function that may destroy multiple bodies. In this case you need to
+be very careful. The solution is application specific, but for
+convenience I'll show one method of solving the problem.
+
+```cpp
+b2Body* node = myWorld->GetBodyList();
+while (node)
+{
+ b2Body* b = node;
+ node = node->GetNext();
+
+ GameActor* myActor = (GameActor*)b->GetUserData().pointer;
+ if (myActor->IsDead())
+ {
+ bool otherBodiesDestroyed = GameCrazyBodyDestroyer(b);
+ if (otherBodiesDestroyed)
+ {
+ node = myWorld->GetBodyList();
+ }
+ }
+}
+```
+
+Obviously to make this work, GameCrazyBodyDestroyer must be honest about
+what it has destroyed.
+
+### AABB Queries
+Sometimes you want to determine all the shapes in a region. The b2World
+class has a fast log(N) method for this using the broad-phase data
+structure. You provide an AABB in world coordinates and an
+implementation of b2QueryCallback. The world calls your class with each
+fixture whose AABB overlaps the query AABB. Return true to continue the
+query, otherwise return false. For example, the following code finds all
+the fixtures that potentially intersect a specified AABB and wakes up
+all of the associated bodies.
+
+```cpp
+class MyQueryCallback : public b2QueryCallback
+{
+public:
+ bool ReportFixture(b2Fixture* fixture)
+ {
+ b2Body* body = fixture->GetBody();
+ body->SetAwake(true);
+
+ // Return true to continue the query.
+ return true;
+ }
+};
+
+// Elsewhere ...
+MyQueryCallback callback;
+b2AABB aabb;
+
+aabb.lowerBound.Set(-1.0f, -1.0f);
+aabb.upperBound.Set(1.0f, 1.0f);
+myWorld->Query(&callback, aabb);
+```
+
+You cannot make any assumptions about the order of the callbacks.
+
+### Ray Casts
+You can use ray casts to do line-of-sight checks, fire guns, etc. You
+perform a ray cast by implementing a callback class and providing the
+start and end points. The world class calls your class with each fixture
+hit by the ray. Your callback is provided with the fixture, the point of
+intersection, the unit normal vector, and the fractional distance along
+the ray. You cannot make any assumptions about the order of the
+callbacks.
+
+You control the continuation of the ray cast by returning a fraction.
+Returning a fraction of zero indicates the ray cast should be
+terminated. A fraction of one indicates the ray cast should continue as
+if no hit occurred. If you return the fraction from the argument list,
+the ray will be clipped to the current intersection point. So you can
+ray cast any shape, ray cast all shapes, or ray cast the closest shape
+by returning the appropriate fraction.
+
+You may also return of fraction of -1 to filter the fixture. Then the
+ray cast will proceed as if the fixture does not exist.
+
+Here is an example:
+
+```cpp
+// This class captures the closest hit shape.
+class MyRayCastCallback : public b2RayCastCallback
+{
+public:
+ MyRayCastCallback()
+ {
+ m_fixture = NULL;
+ }
+
+ float ReportFixture(b2Fixture* fixture, const b2Vec2& point,
+ const b2Vec2& normal, float fraction)
+ {
+ m_fixture = fixture;
+ m_point = point;
+ m_normal = normal;
+ m_fraction = fraction;
+ return fraction;
+ }
+
+ b2Fixture* m_fixture;
+ b2Vec2 m_point;
+ b2Vec2 m_normal;
+ float m_fraction;
+};
+
+// Elsewhere ...
+MyRayCastCallback callback;
+b2Vec2 point1(-1.0f, 0.0f);
+b2Vec2 point2(3.0f, 1.0f);
+myWorld->RayCast(&callback, point1, point2);
+```
+
+> **Caution**:
+> Due to round-off errors, ray casts can sneak through small cracks
+> between polygons in your static environment. If this is not acceptable
+> in your application, trying slightly overlapping your polygons.
diff --git a/Client/ThirdParty/Box2D/docs/extra.css b/Client/ThirdParty/Box2D/docs/extra.css
new file mode 100644
index 0000000..bf67831
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/extra.css
@@ -0,0 +1,605 @@
+/*
+Doxygen CSS overrides
+Adapted from: https://github.com/MaJerle/doxygen-dark-theme
+blog-light: #fafafa
+blog-dark: #252627
+Dark background: #353629;
+New light dark background #32363d
+Light background: #dfe5f2;
+*/
+
+body {
+ background: #292a2d;
+ background-image: none;
+ color: #D8D8D8;
+}
+
+#titlearea {
+ border-bottom: 1px solid #32363d;
+}
+
+div.contents {
+ max-width: 900px;
+}
+
+.image {
+ background-color: #CCCCCC;
+ border: 10px solid #CCCCCC;
+ margin: 0px;
+ padding: 0px;
+}
+
+/*
+.image img, object {
+ padding: 10px;
+ margin: 10px 0px;
+ background-color: white;
+ border: 1px solid #000000;
+}
+*/
+
+.caption {
+ padding-top: 10px;
+ color: black;
+}
+
+div.fragment, pre.fragment {
+ margin: 20px 0px;
+ padding: 10px;
+}
+
+blockquote.doxtable {
+ border: 1px solid #000000;
+ background: #32363d;
+ background-color: #bf5f82;
+ background-color: #456114;
+ margin: 10px 24px 10px 4px;
+}
+
+div.toc {
+ margin: 0 !important;
+ border-radius: 4px !important;
+}
+
+div.toc h3 {
+ font-size: 150%;
+ color: inherit;
+}
+
+.contents table.doxtable {
+ margin: 0 auto;
+}
+
+.fieldtable {
+ box-shadow: none !important;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+}
+
+.memitem,
+.memproto,
+.memdoc {
+ box-shadow: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ background-image: none;
+}
+
+.tablist a:hover,
+.tablist li.current a {
+ text-shadow: none;
+ -moz-text-shadow: none;
+ -webkit-text-shadow: none;
+}
+
+.textblock h1 {
+ border-bottom: 1px solid #32363d;
+ border-left: 3px solid #32363d;
+ margin: 40px 0px 10px 0px;
+ padding-bottom: 10px;
+ padding-top: 10px;
+ padding-left: 5px;
+}
+
+.textblock h1:first-child {
+ margin-top: 10px;
+}
+
+dl.note,
+dl.warning,
+dl.todo,
+dl.deprecated,
+dl.reflist {
+ border: 0;
+ padding: 0px;
+ margin: 4px 0px 4px 0px;
+ border-radius: 4px;
+}
+
+dl.note dt,
+dl.warning dt,
+dl.todo dt,
+dl.deprecated dt,
+dl.reflist dt {
+ margin: 0;
+ font-size: 14px;
+ padding: 2px 4px;
+
+ border: none;
+ border-top-left-radius: 0px;
+ border-top-right-radius:0px;
+
+ font-weight: bold;
+ text-transform: uppercase;
+ color: #FFFFFF !important;
+
+ box-shadow: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ text-shadow: none;
+}
+
+dl.note dd,
+dl.warning dd,
+dl.todo dd,
+dl.deprecated dd,
+dl.reflist dd {
+ margin: 0;
+ padding: 4px;
+ background: none;
+
+ color: #222222;
+
+ border: 1px solid;
+ border-bottom-left-radius: 0px;
+ border-bottom-right-radius: 0px;
+ border-top: none;
+
+ box-shadow: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ text-shadow: none;
+}
+
+dl.reflist dd {
+ margin-bottom: 15px;
+}
+
+dl.note dt {
+ background-color: #cbc693;
+}
+
+dl.warning dt {
+ background-color: #bf5f82;
+}
+
+dl.todo dt {
+ background-color: #82b3c9;
+}
+
+dl.deprecated dt {
+ background-color: #af8eb5;
+}
+
+dl.reflist dt {
+ background-color: #cbae82;
+}
+
+dl.note dd {
+ background-color: #fff9c4;
+ border-color: #cbc693;
+}
+
+dl.warning dd {
+ background-color: #f48fb1;
+ border-color: #bf5f82;
+}
+
+dl.todo dd {
+ background-color: #b3e5fc;
+ border-color: #82b3c9;
+}
+
+dl.deprecated dd {
+ background-color: #e1bee7;
+ border-color: #af8eb5;
+}
+
+dl.reflist dd {
+ background-color: #ffe0b2;
+ border-color: #cbae82;
+}
+
+#docs_list {
+ padding: 0 10px;
+}
+
+#docs_list ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+
+#docs_list ul li {
+ display: inline-block;
+ border-right: 1px solid #BFBFBF;
+}
+
+#docs_list ul li:last-child {
+ border-right: none;
+}
+
+#docs_list ul li a {
+ display: block;
+ padding: 8px 13px;
+ font-weight: bold;
+ font-size: 15px;
+}
+
+#docs_list ul li a:hover,
+#docs_list ul li a.docs_current {
+ text-decoration: underline;
+}
+
+.ui-resizable-e {
+ width: 3px;
+}
+
+.download_url {
+ font-weight: bold;
+ font-size: 150%;
+ line-height: 150%;
+}
+
+span.lineno a {
+ text-decoration: none;
+}
+
+.directory .arrow {
+ height: initial;
+}
+
+.directory td.entry {
+ padding: 3px 6px;
+}
+
+.memproto table td {
+ font-family: monospace, fixed !important;
+}
+
+td.memItemLeft, td.memItemRight {
+ font-family: monospace, fixed;
+}
+
+.paramname, .paramname em {
+ font-style: italic;
+}
+
+.memdoc {
+ text-shadow: none;
+}
+
+.memItem {
+ font-family: monospace, fixed;
+}
+
+.memItem table {
+ font-family: inherit;
+}
+
+img.footer {
+ height: 22px;
+}
+
+.sm-dox {
+ background: #dfe5f2 !important;
+}
+
+.sm-dox a {
+ background: none;
+}
+
+div.fragment, pre.fragment {
+ border: 1px solid #000000;
+ background: #32363d;
+}
+
+a, a:link, a:visited {
+ color: #67d8ef !important;
+}
+
+.highlighted {
+ background: none !important;
+}
+
+a.highlighted {
+ background: none !important;
+}
+
+#main-nav {
+ border-bottom: 1px solid #32363d;
+}
+
+#main-nav .sm-dox {
+ background: transparent !important;
+}
+
+.sm-dox a {
+ text-shadow: none !important;
+ background: transparent !important;
+}
+
+.sm-dox a:hover {
+ background: #282923 !important;
+}
+
+.sm-dox {
+ text-shadow: none !important;
+ box-shadow: none !important;
+}
+
+.sm-dox ul {
+ border: 1px solid #000000;
+ background: #32363d;
+}
+
+.directory tr.even {
+ background: #32363d;
+}
+
+#MSearchSelectWindow {
+ border: 1px solid #000000;
+ background: #32363d;
+}
+
+a.selectItem {
+ padding: 3px;
+}
+
+a.SelectItem:hover {
+ background: #282923 !important;
+}
+
+#MSearchResultsWindow {
+ border: 1px solid #000000;
+ background: #32363d;
+ color: #67d8ef !important;;
+}
+
+#nav-tree {
+ background: transparent;
+}
+
+#nav-tree .selected {
+ background-image: none;
+ background: #32363d;
+}
+
+
+div.toc {
+ background: #32363d;
+ border: 1px solid #000000;
+}
+
+div.toc h3 {
+ font-size: 150%;
+ color: inherit;
+}
+
+table.doxtable tr:nth-child(even) td {
+ background: #32363d;
+}
+
+div.header {
+ background: transparent;
+ border-bottom: 1px solid #32363d;
+}
+
+.fieldtable th {
+ background: #282923;
+ color: inherit;
+}
+
+.memdoc {
+ border: 1px solid #A8B8D9;
+}
+
+.tabs, .tabs2, .tabs3 {
+ background: #DDDDDD;
+}
+
+.tablist li {
+ background: transparent !important;
+}
+
+.tablist a {
+ background-image: none;
+ border-right: 1px solid #999999;
+
+ color: #32363d;
+}
+
+.tablist a:hover,
+.tablist li.current a {
+ text-decoration: none;
+ color: #000000;
+ background: #CCCCCC;
+ background-image: none;
+}
+
+#docs_list {
+ background: #32363d;
+}
+
+#docs_list ul li {
+ border-right: 1px solid #BFBFBF;
+}
+
+#docs_list ul li a {
+ color: #1b1e21;
+}
+
+#docs_list ul li a:hover,
+#docs_list ul li a.docs_current {
+ background: #282923;
+}
+
+.ui-resizable-e {
+ background: #32363d;
+}
+
+div.line {
+ background: transparent;
+ color: inherit;
+}
+
+div.line a {
+ text-decoration: underline;
+ color: inherit;
+}
+
+span.keyword {
+ color: #f92472;
+ font-style: italic;
+}
+
+span.keywordtype {
+ color: #67cfc1;
+ font-style: italic;
+}
+
+span.keywordflow {
+ color: #f92472;
+ font-style: italic;
+}
+
+span.comment {
+ color: #74705a;
+}
+
+span.preprocessor {
+ color: #a6e22b;
+}
+
+span.stringliteral {
+ color: #e7db74;
+}
+
+span.charliteral {
+ color: #e7db74;
+}
+
+span.vhdldigit {
+ color: #ff00ff;
+}
+
+span.vhdlchar {
+ color: #000000;
+}
+
+span.vhdlkeyword {
+ color: #700070;
+}
+
+span.vhdllogic {
+ color: #ff0000;
+}
+
+span.lineno {
+ background: transparent;
+}
+
+span.lineno a {
+ background: transparent;
+}
+
+.mdescLeft, .mdescRight, .memItemLeft, .memItemRight,
+.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
+ background: #32363d;
+ color: inherit;
+}
+
+.memSeparator {
+ border: none;
+ background: transparent;
+}
+
+h2.groupheader {
+ color: #67d8ef;
+}
+
+.memtitle {
+ background: #32363d !important;
+ border-color: #000000;
+}
+
+.memitem {
+ background: #32363d !important;
+ color: inherit;
+ text-shadow: none;
+}
+
+.memproto {
+ background: inherit;
+ border-color: #000000;
+ color: inherit;
+ text-shadow: none;
+}
+
+.memproto table td {
+ font-family: monospace, fixed !important;
+}
+
+td.memItemLeft, td.memItemRight {
+ font-family: monospace, fixed;
+}
+
+.paramname, .paramname em {
+ color: #bf5f82;
+}
+
+.memdoc {
+ background: inherit;
+ border-color: #000000;
+}
+
+#nav-path {
+ background: transparent;
+}
+
+#nav-path ul {
+ background: transparent;
+ color: inherit;
+ border: none;
+ border-top: 1px solid #32363d;
+}
+
+.navpath li.footer {
+ color: inherit;
+}
+
+.navpath li.navelem a {
+ text-shadow: none;
+}
+
+::-webkit-scrollbar {
+ width: 10px;
+}
+
+::-webkit-scrollbar-track {
+ border-radius: 10px;
+}
+
+::-webkit-scrollbar-thumb {
+ background: #234567;
+ border: none;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: #32363d;
+}
+
+h1.glow, h2.glow, h3.glow,
+h4.glow, h5.glow, h6.glow {
+ text-shadow: 0 0 15px #67d8ef;
+}
diff --git a/Client/ThirdParty/Box2D/docs/hello.md b/Client/ThirdParty/Box2D/docs/hello.md
new file mode 100644
index 0000000..40d8de6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/hello.md
@@ -0,0 +1,246 @@
+# Hello Box2D
+In the distribution of Box2D is a Hello World project. The program
+creates a large ground box and a small dynamic box. This code does not
+contain any graphics. All you will see is text output in the console of
+the box's position over time.
+
+This is a good example of how to get up and running with Box2D.
+
+## Creating a World
+Every Box2D program begins with the creation of a b2World object.
+b2World is the physics hub that manages memory, objects, and simulation.
+You can allocate the physics world on the stack, heap, or data section.
+
+It is easy to create a Box2D world. First, we define the gravity vector.
+
+```cpp
+b2Vec2 gravity(0.0f, -10.0f);
+```
+
+Now we create the world object. Note that we are creating the world on
+the stack, so the world must remain in scope.
+
+```cpp
+b2World world(gravity);
+```
+
+So now we have our physics world, let's start adding some stuff to it.
+
+## Creating a Ground Box
+Bodies are built using the following steps:
+1. Define a body with position, damping, etc.
+2. Use the world object to create the body.
+3. Define fixtures with a shape, friction, density, etc.
+4. Create fixtures on the body.
+
+For step 1 we create the ground body. For this we need a body
+definition. With the body definition we specify the initial position of
+the ground body.
+
+```cpp
+b2BodyDef groundBodyDef;
+groundBodyDef.position.Set(0.0f, -10.0f);
+```
+
+For step 2 the body definition is passed to the world object to create
+the ground body. The world object does not keep a reference to the body
+definition. Bodies are static by default. Static bodies don't collide
+with other static bodies and are immovable.
+
+```cpp
+b2Body* groundBody = world.CreateBody(&groundBodyDef);
+```
+
+For step 3 we create a ground polygon. We use the SetAsBox shortcut to
+form the ground polygon into a box shape, with the box centered on the
+origin of the parent body.
+
+```cpp
+b2PolygonShape groundBox;
+groundBox.SetAsBox(50.0f, 10.0f);
+```
+
+The SetAsBox function takes the **half**-**width** and
+**half**-**height** (extents). So in this case the ground box is 100
+units wide (x-axis) and 20 units tall (y-axis). Box2D is tuned for
+meters, kilograms, and seconds. So you can consider the extents to be in
+meters. Box2D generally works best when objects are the size of typical
+real world objects. For example, a barrel is about 1 meter tall. Due to
+the limitations of floating point arithmetic, using Box2D to model the
+movement of glaciers or dust particles is not a good idea.
+
+We finish the ground body in step 4 by creating the shape fixture. For
+this step we have a shortcut. We do not have a need to alter the default
+fixture material properties, so we can pass the shape directly to the
+body without creating a fixture definition. Later we will see how to use
+a fixture definition for customized material properties. The second
+parameter is the shape density in kilograms per meter squared. A static
+body has zero mass by definition, so the density is not used in this
+case.
+
+```cpp
+groundBody->CreateFixture(&groundBox, 0.0f);
+```
+
+Box2D does not keep a reference to the shape. It clones the data into a
+new b2Shape object.
+
+Note that every fixture must have a parent body, even fixtures that are
+static. However, you can attach all static fixtures to a single static
+body.
+
+When you attach a shape to a body using a fixture, the shape's
+coordinates become local to the body. So when the body moves, so does
+the shape. A fixture's world transform is inherited from the parent
+body. A fixture does not have a transform independent of the body. So we
+don't move a shape around on the body. Moving or modifying a shape that
+is on a body is not supported. The reason is simple: a body with
+morphing shapes is not a rigid body, but Box2D is a rigid body engine.
+Many of the assumptions made in Box2D are based on the rigid body model.
+If this is violated many things will break
+
+## Creating a Dynamic Body
+So now we have a ground body. We can use the same technique to create a
+dynamic body. The main difference, besides dimensions, is that we must
+establish the dynamic body's mass properties.
+
+First we create the body using CreateBody. By default bodies are static,
+so we should set the b2BodyType at construction time to make the body
+dynamic.
+
+```cpp
+b2BodyDef bodyDef;
+bodyDef.type = b2_dynamicBody;
+bodyDef.position.Set(0.0f, 4.0f);
+b2Body* body = world.CreateBody(&bodyDef);
+```
+
+> **Caution**:
+> You must set the body type to b2_dynamicBody if you want the body to
+> move in response to forces.
+
+Next we create and attach a polygon shape using a fixture definition.
+First we create a box shape:
+
+```cpp
+b2PolygonShape dynamicBox;
+dynamicBox.SetAsBox(1.0f, 1.0f);
+```
+
+Next we create a fixture definition using the box. Notice that we set
+density to 1. The default density is zero. Also, the friction on the
+shape is set to 0.3.
+
+```cpp
+b2FixtureDef fixtureDef;
+fixtureDef.shape = &dynamicBox;
+fixtureDef.density = 1.0f;
+fixtureDef.friction = 0.3f;
+```
+
+> **Caution**:
+> A dynamic body should have at least one fixture with a non-zero density.
+> Otherwise you will get strange behavior.
+
+Using the fixture definition we can now create the fixture. This
+automatically updates the mass of the body. You can add as many fixtures
+as you like to a body. Each one contributes to the total mass.
+
+```cpp
+body->CreateFixture(&fixtureDef);
+```
+
+That's it for initialization. We are now ready to begin simulating.
+
+## Simulating the World
+So we have initialized the ground box and a dynamic box. Now we are
+ready to set Newton loose to do his thing. We just have a couple more
+issues to consider.
+
+Box2D uses a computational algorithm called an integrator. Integrators
+simulate the physics equations at discrete points of time. This goes
+along with the traditional game loop where we essentially have a flip
+book of movement on the screen. So we need to pick a time step for
+Box2D. Generally physics engines for games like a time step at least as
+fast as 60Hz or 1/60 seconds. You can get away with larger time steps,
+but you will have to be more careful about setting up the definitions
+for your world. We also don't like the time step to change much. A
+variable time step produces variable results, which makes it difficult
+to debug. So don't tie the time step to your frame rate (unless you
+really, really have to). Without further ado, here is the time step.
+
+```cpp
+float timeStep = 1.0f / 60.0f;
+```
+
+In addition to the integrator, Box2D also uses a larger bit of code
+called a constraint solver. The constraint solver solves all the
+constraints in the simulation, one at a time. A single constraint can be
+solved perfectly. However, when we solve one constraint, we slightly
+disrupt other constraints. To get a good solution, we need to iterate
+over all constraints a number of times.
+
+There are two phases in the constraint solver: a velocity phase and a
+position phase. In the velocity phase the solver computes the impulses
+necessary for the bodies to move correctly. In the position phase the
+solver adjusts the positions of the bodies to reduce overlap and joint
+detachment. Each phase has its own iteration count. In addition, the
+position phase may exit iterations early if the errors are small.
+
+The suggested iteration count for Box2D is 8 for velocity and 3 for
+position. You can tune this number to your liking, just keep in mind
+that this has a trade-off between performance and accuracy. Using fewer
+iterations increases performance but accuracy suffers. Likewise, using
+more iterations decreases performance but improves the quality of your
+simulation. For this simple example, we don't need much iteration. Here
+are our chosen iteration counts.
+
+```cpp
+int32 velocityIterations = 6;
+int32 positionIterations = 2;
+```
+
+Note that the time step and the iteration count are completely
+unrelated. An iteration is not a sub-step. One solver iteration is a
+single pass over all the constraints within a time step. You can have
+multiple passes over the constraints within a single time step.
+
+We are now ready to begin the simulation loop. In your game the
+simulation loop can be merged with your game loop. In each pass through
+your game loop you call b2World::Step. Just one call is usually enough,
+depending on your frame rate and your physics time step.
+
+The Hello World program was designed to be simple, so it has no
+graphical output. The code prints out the position and rotation of the
+dynamic body. Here is the simulation loop that simulates 60 time steps
+for a total of 1 second of simulated time.
+
+```cpp
+for (int32 i = 0; i < 60; ++i)
+{
+ world.Step(timeStep, velocityIterations, positionIterations);
+ b2Vec2 position = body->GetPosition();
+ float angle = body->GetAngle();
+ printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
+}
+```
+
+The output shows the box falling and landing on the ground box. Your
+output should look like this:
+
+```
+0.00 4.00 0.00
+0.00 3.99 0.00
+0.00 3.98 0.00
+...
+0.00 1.25 0.00
+0.00 1.13 0.00
+0.00 1.01 0.00
+```
+
+## Cleanup
+When a world leaves scope or is deleted by calling delete on a pointer,
+all the memory reserved for bodies, fixtures, and joints is freed. This
+is done to improve performance and make your life easier. However, you
+will need to nullify any body, fixture, or joint pointers you have
+because they will become invalid.
diff --git a/Client/ThirdParty/Box2D/docs/images/body_origin.gif b/Client/ThirdParty/Box2D/docs/images/body_origin.gif
new file mode 100644
index 0000000..cef1707
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/body_origin.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/captured_toi.svg b/Client/ThirdParty/Box2D/docs/images/captured_toi.svg
new file mode 100644
index 0000000..e5d951d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/captured_toi.svg
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="296.5"
+ height="142.84351"
+ id="svg4080"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="captured.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\captured.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4082">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective4088" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4142136"
+ inkscape:cx="-105.19711"
+ inkscape:cy="-99.626528"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1138"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata4085">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-245,-431.01868)">
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4090"
+ width="295.5"
+ height="17"
+ x="245.5"
+ y="556.36218" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4602"
+ width="8"
+ height="134"
+ x="565.5022"
+ y="92.054398"
+ transform="rotate(39.650005)" />
+ <rect
+ y="502.45367"
+ x="298.04913"
+ height="134"
+ width="8"
+ id="rect4604"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ transform="rotate(-11.210987)" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="328"
+ y="465.36218"
+ id="text4608"><tspan
+ sodipodi:role="line"
+ id="tspan4610"
+ x="328"
+ y="465.36218"
+ style="font-size:12px;line-height:1.25">t=0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="419.5"
+ y="465.33875"
+ id="text4612"><tspan
+ sodipodi:role="line"
+ id="tspan4614"
+ x="419.5"
+ y="465.33875"
+ style="font-size:12px;line-height:1.25">t=1</tspan></text>
+ <rect
+ transform="rotate(30.564716)"
+ y="182.57234"
+ x="547.54456"
+ height="134"
+ width="8"
+ id="rect2822"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/chain_loop_inwards.svg b/Client/ThirdParty/Box2D/docs/images/chain_loop_inwards.svg
new file mode 100644
index 0000000..9fea243
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/chain_loop_inwards.svg
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="385.42209"
+ height="201.11388"
+ id="svg9044"
+ version="1.1"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ sodipodi:docname="chain_loop.svg">
+ <defs
+ id="defs9046">
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="Arrow1Mend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend">
+ <path
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill:#767676;fill-opacity:1;fill-rule:evenodd;stroke:#767676;stroke-width:1pt;stroke-opacity:1"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path911" />
+ </marker>
+ <marker
+ inkscape:isstock="true"
+ style="overflow:visible"
+ id="Arrow2Lend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend">
+ <path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#767676;fill-opacity:1;fill-rule:evenodd;stroke:#767676;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path923" />
+ </marker>
+ <linearGradient
+ id="linearGradient9562"
+ osb:paint="solid">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop9564" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="168.58169"
+ inkscape:cy="-21.83025"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1359"
+ inkscape:window-height="1041"
+ inkscape:window-x="150"
+ inkscape:window-y="60"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:document-rotation="0" />
+ <metadata
+ id="metadata9049">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-194.29952,-275.90446)">
+ <path
+ id="path848"
+ d="m 229.2724,347.82772 0.71428,70 60,54.28571 125,-30 122.14286,32.14286 39.28571,-103.57143 -49.28571,-92.14286 -97.14286,47.85715 -104.28571,-47.14286 -128.57143,2.85714 z"
+ style="fill:none;stroke:#767676;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path6867"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="228.97542"
+ cy="348.89066"
+ r="2.5253813" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9620"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="230.76782"
+ cy="418.05508"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9622"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="290.03033"
+ cy="471.81509"
+ r="2.5253813" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9624"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="413.70074"
+ cy="443.18237"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9626"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="430.03122"
+ cy="326.42294"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9628"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="536.83978"
+ cy="473.99295"
+ r="2.5253813" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9630"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="526.38983"
+ cy="278.92984"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9632"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="576.69623"
+ cy="371.42444"
+ r="2.5253813" />
+ <path
+ id="path850"
+ d="m 253.47669,467.02956 v 0"
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="279.28699"
+ cx="324.60413"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="circle852"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="circle854"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="197.32491"
+ cy="281.81238"
+ r="2.5253813" />
+ <text
+ id="text862"
+ y="344.07681"
+ x="425.94608"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="344.07681"
+ x="425.94608"
+ id="tspan860"
+ sodipodi:role="line">1</tspan></text>
+ <text
+ id="text866"
+ y="295.57101"
+ x="519.9389"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="295.57101"
+ x="519.9389"
+ id="tspan864"
+ sodipodi:role="line">2</tspan></text>
+ <text
+ id="text870"
+ y="376.38321"
+ x="558.82983"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="376.38321"
+ x="558.82983"
+ id="tspan868"
+ sodipodi:role="line">3</tspan></text>
+ <text
+ id="text874"
+ y="463.25635"
+ x="524.98969"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="463.25635"
+ x="524.98969"
+ id="tspan872"
+ sodipodi:role="line">4</tspan></text>
+ <text
+ id="text878"
+ y="430.93146"
+ x="408.82214"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="430.93146"
+ x="408.82214"
+ id="tspan876"
+ sodipodi:role="line">5</tspan></text>
+ <text
+ id="text882"
+ y="460.73096"
+ x="289.11905"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="460.73096"
+ x="289.11905"
+ id="tspan880"
+ sodipodi:role="line">6</tspan></text>
+ <text
+ id="text886"
+ y="417.2944"
+ x="241.1368"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="417.2944"
+ x="241.1368"
+ id="tspan884"
+ sodipodi:role="line">7</tspan></text>
+ <text
+ id="text890"
+ y="354.15985"
+ x="236.08604"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="354.15985"
+ x="236.08604"
+ id="tspan888"
+ sodipodi:role="line">8</tspan></text>
+ <text
+ id="text894"
+ y="299.6116"
+ x="212.34746"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="299.6116"
+ x="212.34746"
+ id="tspan892"
+ sodipodi:role="line">9</tspan></text>
+ <text
+ id="text898"
+ y="301.63193"
+ x="313.36273"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="301.63193"
+ x="313.36273"
+ id="tspan896"
+ sodipodi:role="line">10</tspan></text>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path900"
+ d="m 479.45824,302.18069 17.90441,37.1805"
+ style="fill:none;stroke:#767676;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)" />
+ <text
+ id="text1200"
+ y="354.91748"
+ x="473.72443"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ y="354.91748"
+ x="473.72443"
+ id="tspan1198"
+ sodipodi:role="line">normal</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/chain_loop_outwards.svg b/Client/ThirdParty/Box2D/docs/images/chain_loop_outwards.svg
new file mode 100644
index 0000000..1f03926
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/chain_loop_outwards.svg
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="chain_loop_reversed.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ version="1.1"
+ id="svg9044"
+ height="204.77463"
+ width="385.42209">
+ <defs
+ id="defs9046">
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path911"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill:#767676;fill-opacity:1;fill-rule:evenodd;stroke:#767676;stroke-width:1pt;stroke-opacity:1"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path923"
+ style="fill:#767676;fill-opacity:1;fill-rule:evenodd;stroke:#767676;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <linearGradient
+ osb:paint="solid"
+ id="linearGradient9562">
+ <stop
+ id="stop9564"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-rotation="0"
+ fit-margin-bottom="0"
+ fit-margin-right="0"
+ fit-margin-left="0"
+ fit-margin-top="0"
+ inkscape:window-maximized="0"
+ inkscape:window-y="60"
+ inkscape:window-x="150"
+ inkscape:window-height="1041"
+ inkscape:window-width="1359"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="px"
+ inkscape:cy="79.63377"
+ inkscape:cx="82.971281"
+ inkscape:zoom="2.8"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <metadata
+ id="metadata9049">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(-194.29952,-272.2437)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ style="fill:none;stroke:#767676;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 229.2724,347.82772 0.71428,70 60,54.28571 125,-30 122.14286,32.14286 39.28571,-103.57143 -49.28571,-92.14286 -97.14286,47.85715 -104.28571,-47.14286 -128.57143,2.85714 z"
+ id="path848" />
+ <circle
+ r="2.5253813"
+ cy="348.89066"
+ cx="228.97542"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path6867"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="418.05508"
+ cx="230.76782"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9620"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="471.81509"
+ cx="290.03033"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9622"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="443.18237"
+ cx="413.70074"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9624"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="326.42294"
+ cx="430.03122"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9626"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="473.99295"
+ cx="536.83978"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9628"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="278.92984"
+ cx="526.38983"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9630"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="371.42444"
+ cx="576.69623"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="path9632"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 253.47669,467.02956 v 0"
+ id="path850" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="circle852"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="324.60413"
+ cy="279.28699"
+ r="2.5253813" />
+ <circle
+ r="2.5253813"
+ cy="281.81238"
+ cx="197.32491"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="circle854"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="425.94608"
+ y="344.07681"
+ id="text862"><tspan
+ sodipodi:role="line"
+ id="tspan860"
+ x="425.94608"
+ y="344.07681">1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="316.62775"
+ y="298.60147"
+ id="text866"><tspan
+ sodipodi:role="line"
+ id="tspan864"
+ x="316.62775"
+ y="298.60147">2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="211.25813"
+ y="296.85907"
+ id="text870"><tspan
+ sodipodi:role="line"
+ id="tspan868"
+ x="211.25813"
+ y="296.85907">3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="236.15477"
+ y="352.01703"
+ id="text874"><tspan
+ sodipodi:role="line"
+ id="tspan872"
+ x="236.15477"
+ y="352.01703">4</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="239.87413"
+ y="418.30457"
+ id="text878"><tspan
+ sodipodi:role="line"
+ id="tspan876"
+ x="239.87413"
+ y="418.30457">5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="289.11905"
+ y="460.73096"
+ id="text882"><tspan
+ sodipodi:role="line"
+ id="tspan880"
+ x="289.11905"
+ y="460.73096">6</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="413.11526"
+ y="434.21445"
+ id="text886"><tspan
+ sodipodi:role="line"
+ id="tspan884"
+ x="413.11526"
+ y="434.21445">7</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="528.52521"
+ y="464.51904"
+ id="text890"><tspan
+ sodipodi:role="line"
+ id="tspan888"
+ x="528.52521"
+ y="464.51904">8</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="558.0722"
+ y="376.88828"
+ id="text894"><tspan
+ sodipodi:role="line"
+ id="tspan892"
+ x="558.0722"
+ y="376.88828">9</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="513.62549"
+ y="300.36923"
+ id="text898"><tspan
+ sodipodi:role="line"
+ id="tspan896"
+ x="513.62549"
+ y="300.36923">10</tspan></text>
+ <path
+ style="fill:none;stroke:#767676;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+ d="M 383.79198,305.30043 397.6917,274.04436"
+ id="path900"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3333px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="400.48837"
+ y="290.26773"
+ id="text1200"><tspan
+ sodipodi:role="line"
+ id="tspan1198"
+ x="400.48837"
+ y="290.26773">normal</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/chain_shape.svg b/Client/ThirdParty/Box2D/docs/images/chain_shape.svg
new file mode 100644
index 0000000..04ea959
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/chain_shape.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="chain_shape.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ version="1.1"
+ id="svg9044"
+ height="225.19205"
+ width="402.73563">
+ <defs
+ id="defs9046">
+ <linearGradient
+ osb:paint="solid"
+ id="linearGradient9562">
+ <stop
+ id="stop9564"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ inkscape:document-rotation="0"
+ fit-margin-bottom="0"
+ fit-margin-right="0"
+ fit-margin-left="0"
+ fit-margin-top="0"
+ inkscape:window-maximized="0"
+ inkscape:window-y="60"
+ inkscape:window-x="150"
+ inkscape:window-height="1041"
+ inkscape:window-width="1359"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="px"
+ inkscape:cy="186.37568"
+ inkscape:cx="193.56931"
+ inkscape:zoom="2.8"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <metadata
+ id="metadata9049">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(-183.55811,-264.25629)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ sodipodi:nodetypes="csccc"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:connector-curvature="0"
+ id="path9052"
+ d="m 323.77573,448.72257 c 17.00369,9.32859 68.03674,37.35768 70.04901,38.08934 4.02453,1.46331 83.91263,-37.80722 83.91263,-37.80722 l 105.40088,-34.7384 -76.62636,-97.92976"
+ style="fill:none;stroke:#767676;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ id="path845"
+ d="m 506.51189,316.33653 58.7583,-35.85104"
+ style="fill:none;stroke:#767676;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4, 4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path847"
+ d="M 253.47669,467.02956 187.05916,434.70468"
+ style="fill:none;stroke:#767676;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:4, 4;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ id="path849"
+ d="m 253.47669,467.02956 70.29904,-18.30699"
+ style="fill:none;stroke:#767676;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ transform="translate(-54.372373,-177.18205)"
+ id="path6867"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9620"
+ transform="translate(11.817253,-145.14071)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ transform="translate(81.49165,-163.51344)"
+ id="path9622"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9624"
+ transform="translate(235.87634,-162.86043)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ transform="translate(152.3854,-125.51272)"
+ id="path9626"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ transform="translate(341.33682,-197.58559)"
+ id="path9628"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9630"
+ transform="translate(265.17257,-295.86296)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ transform="translate(323.65299,-332.43511)"
+ id="path9632"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ id="text9634"
+ y="426.1131"
+ x="183.1958"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-size:14px;line-height:1.25"
+ y="426.1131"
+ x="183.1958"
+ id="tspan9636"
+ sodipodi:role="line">ghost</tspan></text>
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Chain1.png"
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="549.41998"
+ y="273.77875"
+ id="text9638"><tspan
+ style="font-size:14px;line-height:1.25"
+ sodipodi:role="line"
+ id="tspan9640"
+ x="549.41998"
+ y="273.77875">ghost</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/convex_concave.gif b/Client/ThirdParty/Box2D/docs/images/convex_concave.gif
new file mode 100644
index 0000000..feefdf0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/convex_concave.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/debug_draw.png b/Client/ThirdParty/Box2D/docs/images/debug_draw.png
new file mode 100644
index 0000000..8b4d56f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/debug_draw.png
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/distance.svg b/Client/ThirdParty/Box2D/docs/images/distance.svg
new file mode 100644
index 0000000..afefe85
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/distance.svg
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="271.28311"
+ height="111.33035"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="distance.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\distance.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3696"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3690"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2830"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective2852"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3648"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective4310"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend-0"
+ style="overflow:visible">
+ <path
+ id="path3696-9"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ id="perspective4342"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="26.976981"
+ inkscape:cy="-103.40251"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1467"
+ inkscape:window-height="1068"
+ inkscape:window-x="196"
+ inkscape:window-y="16"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-209.30148,-534.31362)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.21355975;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.21355975, 2.4271195;stroke-dashoffset:0;stroke-opacity:1;marker-end:none"
+ d="m 388,603.62582 -62,0.47272"
+ id="path3664"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 387,546.86218 79,-1 14,56 -91,43 z"
+ id="path2816"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 246.19848,535.12334 80.64122,69.26034 -116.72691,8.47526 z"
+ id="path2818"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#00ff00;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820"
+ width="7"
+ height="7"
+ x="385.5"
+ y="599.36218" />
+ <rect
+ style="fill:#00ff00;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820-1"
+ width="7"
+ height="7"
+ x="323"
+ y="599.86218" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/distance_joint.gif b/Client/ThirdParty/Box2D/docs/images/distance_joint.gif
new file mode 100644
index 0000000..3fd44a4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/distance_joint.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/gear_joint.gif b/Client/ThirdParty/Box2D/docs/images/gear_joint.gif
new file mode 100644
index 0000000..9737d7d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/gear_joint.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/ghost_collision.svg b/Client/ThirdParty/Box2D/docs/images/ghost_collision.svg
new file mode 100644
index 0000000..8ca172c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/ghost_collision.svg
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="262.62952"
+ height="103.72113"
+ id="svg6349"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="ghost_collision.svg">
+ <defs
+ id="defs6351">
+ <marker
+ inkscape:stockid="Arrow1Send"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Send"
+ style="overflow:visible">
+ <path
+ id="path4500"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path4494"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path4488"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path4628"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="scale(0.8)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="16.976506"
+ inkscape:cy="8.3597391"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1413"
+ inkscape:window-height="1038"
+ inkscape:window-x="408"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata6354">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-286.8884,-532.20758)">
+ <path
+ style="fill:none;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 289.91378,613.4509 255.55849,1.51523"
+ id="path6357"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path6867"
+ transform="translate(47.982246,1.5152288)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path6867-1"
+ transform="translate(181.32238,2.525385)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path6867-1-9"
+ transform="translate(304.561,3.5355374)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect6905"
+ width="47.982246"
+ height="41.921329"
+ x="375.23105"
+ y="569.50922"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send)"
+ d="m 373.75644,552.33667 h 51.0127"
+ id="path6907"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)"
+ d="M 454.54834,609.91537 H 426.26407"
+ id="path7843"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="370.22092"
+ y="541.73004"
+ id="text8977"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ id="tspan8979"
+ x="370.22092"
+ y="541.73004"
+ style="font-size:14px;line-height:1.25">box motion</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="439.28574"
+ y="606.29077"
+ id="text8981"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ id="tspan8983"
+ x="439.28574"
+ y="606.29077"
+ style="font-size:14px;line-height:1.25">internal normal</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="328.92856"
+ y="633.43359"
+ id="text8985"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ id="tspan8987"
+ x="328.92856"
+ y="633.43359"
+ style="font-size:14px;line-height:1.25">edge1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="460.78262"
+ y="633.36218"
+ id="text8985-3"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ x="460.78262"
+ y="633.36218"
+ id="tspan9010"
+ style="font-size:14px;line-height:1.25">edge2 </tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/ghost_vertices.svg b/Client/ThirdParty/Box2D/docs/images/ghost_vertices.svg
new file mode 100644
index 0000000..0777123
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/ghost_vertices.svg
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="ghost_vertices.svg"
+ inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+ version="1.1"
+ id="svg6349"
+ height="95.10083"
+ width="249.00421">
+ <defs
+ id="defs6351">
+ <marker
+ style="overflow:visible"
+ id="Arrow1Send"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Send">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4500" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="Arrow1Mend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Mend">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4494" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lend">
+ <path
+ inkscape:connector-curvature="0"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ id="path4488" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleOutL"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="TriangleOutL">
+ <path
+ inkscape:connector-curvature="0"
+ transform="scale(0.8)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path4628" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ lock-margins="true"
+ inkscape:document-rotation="0"
+ fit-margin-bottom="0.5"
+ fit-margin-right="0.5"
+ fit-margin-left="0.5"
+ fit-margin-top="0.5"
+ inkscape:window-maximized="0"
+ inkscape:window-y="66"
+ inkscape:window-x="1946"
+ inkscape:window-height="1038"
+ inkscape:window-width="1413"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:document-units="px"
+ inkscape:cy="-1.4711953"
+ inkscape:cx="34.170039"
+ inkscape:zoom="2.8"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <metadata
+ id="metadata6354">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(-269.69485,-530.99694)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ inkscape:connector-curvature="0"
+ id="path9018"
+ d="m 291.78571,534.50504 66.42858,52.5"
+ style="fill:none;stroke:#7d7d7d;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ inkscape:connector-curvature="0"
+ id="path9020"
+ d="m 358.21429,586.6479 80.71429,-26.07143"
+ style="fill:none;stroke:#7d7d7d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ inkscape:connector-curvature="0"
+ id="path9022"
+ d="m 438.57143,560.57647 56.78572,32.14286"
+ style="fill:none;stroke:#7d7d7d;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ transform="translate(49.053675,-77.413343)"
+ id="path6867"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ transform="translate(116.32238,-24.974615)"
+ id="path6867-1"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9012"
+ transform="translate(254.91814,-18.60732)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ r="2.5253813"
+ cy="611.93567"
+ cx="241.93153"
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ transform="translate(197.06099,-51.10732)"
+ id="path9014"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ id="text9024"
+ y="610.57648"
+ x="492.14285"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-size:14px;line-height:1.25"
+ y="610.57648"
+ x="492.14285"
+ id="tspan9026"
+ sodipodi:role="line">v0</tspan></text>
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="432.5"
+ y="577.36218"
+ id="text9028"><tspan
+ style="font-size:14px;line-height:1.25"
+ sodipodi:role="line"
+ id="tspan9030"
+ x="432.5"
+ y="577.36218">v1</tspan></text>
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ id="text9032"
+ y="602.7193"
+ x="349.64285"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-size:14px;line-height:1.25"
+ y="602.7193"
+ x="349.64285"
+ id="tspan9034"
+ sodipodi:role="line">v2</tspan></text>
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="283.92856"
+ y="552.00507"
+ id="text9036"><tspan
+ style="font-size:14px;line-height:1.25"
+ sodipodi:role="line"
+ id="tspan9038"
+ x="283.92856"
+ y="552.00507">v3</tspan></text>
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ id="text9040"
+ y="565.93359"
+ x="269.28568"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-size:14px;line-height:1.25"
+ y="565.93359"
+ x="269.28568"
+ id="tspan9042"
+ sodipodi:role="line">(ghost)</tspan></text>
+ <text
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\GhostVertices.png"
+ id="text9040-2"
+ y="623.10266"
+ x="479.21371"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ style="font-size:14px;line-height:1.25"
+ y="623.10266"
+ x="479.21371"
+ id="tspan9042-0"
+ sodipodi:role="line">(ghost)</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/logo.svg b/Client/ThirdParty/Box2D/docs/images/logo.svg
new file mode 100644
index 0000000..f002689
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/logo.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="23.160606mm"
+ height="19.770294mm"
+ viewBox="0 0 23.160606 19.770294"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="Logo.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="91.164312"
+ inkscape:cy="2.0199043"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:snap-grids="false"
+ inkscape:snap-to-guides="false"
+ inkscape:snap-others="false"
+ inkscape:object-nodes="false"
+ inkscape:snap-nodes="false"
+ inkscape:snap-global="false"
+ inkscape:window-width="2560"
+ inkscape:window-height="1377"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-4.3336132,-2.5558382)">
+ <rect
+ id="rect3724"
+ width="5.3740902"
+ height="4.9586015"
+ x="12.262583"
+ y="10.94324"
+ style="fill:none;stroke:#30aebf;stroke-width:0.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ inkscape:export-xdpi="208.37"
+ inkscape:export-ydpi="208.37" />
+ <rect
+ id="rect3724-5"
+ width="5.3740902"
+ height="4.9586015"
+ x="15.178779"
+ y="16.447105"
+ style="fill:none;stroke:#30aebf;stroke-width:0.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ id="rect3724-7"
+ width="5.3740902"
+ height="4.9586015"
+ x="9.251893"
+ y="16.447105"
+ style="fill:none;stroke:#30aebf;stroke-width:0.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ style="fill:none;stroke:#8cc924;stroke-width:0.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 4.3348411,22.026134 21.1823269,-0.0867"
+ id="path4552"
+ inkscape:connector-curvature="0"
+ inkscape:export-xdpi="208.37"
+ inkscape:export-ydpi="208.37" />
+ <circle
+ style="fill:none;stroke:#dc3132;stroke-width:0.60000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path4554"
+ cx="21.845764"
+ cy="8.3044558"
+ r="2.5724692"
+ inkscape:export-xdpi="208.37"
+ inkscape:export-ydpi="208.37" />
+ <path
+ style="fill:none;stroke:#eb8788;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 22.547358,4.9301842 2.104747,-2.07134"
+ id="path4556"
+ inkscape:connector-curvature="0"
+ inkscape:export-xdpi="208.37"
+ inkscape:export-ydpi="208.37" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4558"
+ d="m 24.184383,5.7319842 2.104747,-2.07134"
+ style="fill:none;stroke:#eb8788;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ inkscape:export-xdpi="208.37"
+ inkscape:export-ydpi="208.37" />
+ <path
+ style="fill:none;stroke:#eb8788;stroke-width:0.60000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 25.086418,7.1685542 2.104747,-2.07134"
+ id="path4562"
+ inkscape:connector-curvature="0"
+ inkscape:export-xdpi="208.37"
+ inkscape:export-ydpi="208.37" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/manifolds.svg b/Client/ThirdParty/Box2D/docs/images/manifolds.svg
new file mode 100644
index 0000000..564fe9f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/manifolds.svg
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="278.64941"
+ height="199.68138"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="manifolds.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3696"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3690"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2830"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective2852"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3648"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective4310"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend-0"
+ style="overflow:visible">
+ <path
+ id="path3696-9"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ id="perspective4342"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="107.80664"
+ inkscape:cy="78.632812"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1097"
+ inkscape:window-height="1068"
+ inkscape:window-x="214"
+ inkscape:window-y="23"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-208.19336,-534.31362)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 227,602.36218 79,-1 14,56 -91,43 z"
+ id="path2816"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 246.19848,535.12334 80.64122,69.26034 -116.72691,8.47526 z"
+ id="path2818"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"
+ inkscape:connector-curvature="0" />
+ <rect
+ style="fill:#00ff00;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820"
+ width="7"
+ height="7"
+ x="224"
+ y="608.36218"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958" />
+ <rect
+ style="fill:#00ff00;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820-1"
+ width="7"
+ height="7"
+ x="303.5"
+ y="602.36218"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 386,601.86218 79,-1 14,56 -91,43 z"
+ id="path2816-7"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"
+ inkscape:connector-curvature="0" />
+ <circle
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path2866"
+ transform="translate(-2,14)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"
+ cx="428.75"
+ cy="556.61218"
+ r="34.75" />
+ <rect
+ style="fill:#00ff00;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820-4"
+ width="7"
+ height="7"
+ x="424.5"
+ y="602.86218"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 264,601.36218 v -26.5"
+ id="path3664"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 427.50961,601.02437 v -26.5"
+ id="path3664-4"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="208"
+ y="731.86218"
+ id="text4330"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"><tspan
+ sodipodi:role="line"
+ id="tspan4332"
+ x="208"
+ y="731.86218"
+ style="font-size:12px;line-height:1.25">two points, one normal</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="378.83105"
+ y="731.86218"
+ id="text4330-8"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\manifolds.png"
+ inkscape:export-xdpi="180.11958"
+ inkscape:export-ydpi="180.11958"><tspan
+ sodipodi:role="line"
+ id="tspan4332-8"
+ x="378.83105"
+ y="731.86218"
+ style="font-size:12px;line-height:1.25">one point, one normal</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/missed_toi.svg b/Client/ThirdParty/Box2D/docs/images/missed_toi.svg
new file mode 100644
index 0000000..a8fbbe4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/missed_toi.svg
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="296.5"
+ height="148.6571"
+ id="svg4080"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="missed_toi.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\missed.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4082">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3626"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective4088" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="-118.5"
+ inkscape:cy="37.499998"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1138"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata4085">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-245,-425.20508)">
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4090"
+ width="295.5"
+ height="17"
+ x="245.5"
+ y="556.36218" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4602"
+ width="8"
+ height="134"
+ x="506.24817"
+ y="262.38239"
+ transform="rotate(20.920228)" />
+ <rect
+ y="542.29114"
+ x="223.04268"
+ height="134"
+ width="8"
+ id="rect4604"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ transform="rotate(-20.611746)" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:2, 4;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4606"
+ width="8"
+ height="134"
+ x="389"
+ y="429.36218" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="340.5"
+ y="466.36218"
+ id="text4608"><tspan
+ sodipodi:role="line"
+ id="tspan4610"
+ x="340.5"
+ y="466.36218"
+ style="font-size:12px;line-height:1.25">t=0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="432.5"
+ y="466.33875"
+ id="text4612"><tspan
+ sodipodi:role="line"
+ id="tspan4614"
+ x="432.5"
+ y="466.33875"
+ style="font-size:12px;line-height:1.25">t=1</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 500.5,556.36218 v -40.5"
+ id="path2822"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="462.5"
+ y="507.86218"
+ id="text4044"><tspan
+ sodipodi:role="line"
+ id="tspan4046"
+ x="462.5"
+ y="507.86218"
+ style="font-size:12px;line-height:1.25">separating axis</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/modules.svg b/Client/ThirdParty/Box2D/docs/images/modules.svg
new file mode 100644
index 0000000..08200be
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/modules.svg
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="216.625"
+ height="229"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="modules.svg">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3683"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2838"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective2860"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective2888"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective2845"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective2867"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="-354.80283"
+ inkscape:cy="43.76881"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1138"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-183,-324.36218)">
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820-7-9-1-7"
+ width="120"
+ height="46"
+ x="183"
+ y="416.36218"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820-7-9-1"
+ width="120"
+ height="46"
+ x="279.625"
+ y="324.36218"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="310.13672"
+ y="351.92664"
+ id="text2826"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2828"
+ x="310.13672"
+ y="351.92664"
+ style="font-size:16px;line-height:1.25">Common</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="215.79297"
+ y="442.92664"
+ id="text2826-4"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2828-0"
+ x="215.79297"
+ y="442.92664"
+ style="font-size:16px;line-height:1.25">Collision</tspan></text>
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect2820-7-9"
+ width="120"
+ height="46"
+ x="279.625"
+ y="507.36218"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="307.94531"
+ y="535.92664"
+ id="text2826-4-4"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ sodipodi:role="line"
+ id="tspan2828-0-8"
+ x="307.94531"
+ y="535.92664"
+ style="font-size:16px;line-height:1.25">Dynamics</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
+ d="m 315.46875,370.36218 -48.3125,46"
+ id="path2881"
+ inkscape:connector-type="polyline"
+ inkscape:connection-start="#rect2820-7-9-1"
+ inkscape:connection-end="#rect2820-7-9-1-7"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
+ d="m 267.4217,462.36218 47.7816,45"
+ id="path2883"
+ inkscape:connector-type="polyline"
+ inkscape:connection-start="#rect2820-7-9-1-7"
+ inkscape:connection-end="#rect2820-7-9"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)"
+ d="m 339.625,370.36218 v 137"
+ id="path2885"
+ inkscape:connector-type="polyline"
+ inkscape:connection-start="#rect2820-7-9-1"
+ inkscape:connection-end="#rect2820-7-9"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\modules.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/overlap_test.svg b/Client/ThirdParty/Box2D/docs/images/overlap_test.svg
new file mode 100644
index 0000000..be78e9b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/overlap_test.svg
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="231.14912"
+ height="184.62988"
+ id="svg3598"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="overlap_test.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\regionquery.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs3600">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path4314"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective3606" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.3325546"
+ inkscape:cx="115.57456"
+ inkscape:cy="79.495605"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1138"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata3603">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-209.87013,-406.2323)">
+ <rect
+ y="473.70428"
+ x="232.34212"
+ height="16.815773"
+ width="19.815773"
+ id="rect4120"
+ style="fill:none;stroke:#00d200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="429.19492"
+ x="378.33273"
+ height="36.334541"
+ width="54.334541"
+ id="rect4122"
+ style="fill:none;stroke:#00d200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="548.88507"
+ x="222.02287"
+ height="21.954247"
+ width="35.454247"
+ id="rect4124"
+ style="fill:none;stroke:#00d200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="508.34296"
+ x="408.48077"
+ height="20.538485"
+ width="32.038483"
+ id="rect4126"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="524.32886"
+ x="306.46667"
+ height="61.066628"
+ width="43.566628"
+ id="rect4128"
+ style="fill:none;stroke:#00d200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="429.74796"
+ x="292.88577"
+ height="66.228439"
+ width="33.728436"
+ id="rect4130"
+ style="fill:none;stroke:#00d200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ style="fill:none;stroke:#00d200;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4276"
+ width="33.790939"
+ height="30.790941"
+ x="374.60455"
+ y="547.46674" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4278"
+ width="49.259716"
+ height="43.759716"
+ x="210.37013"
+ y="406.7323" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:2, 4;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2826"
+ width="149.5"
+ height="128"
+ x="248"
+ y="462.36218" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/prismatic_joint.gif b/Client/ThirdParty/Box2D/docs/images/prismatic_joint.gif
new file mode 100644
index 0000000..ac2037f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/prismatic_joint.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/pulley_joint.gif b/Client/ThirdParty/Box2D/docs/images/pulley_joint.gif
new file mode 100644
index 0000000..ad8d4fb
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/pulley_joint.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/raycast.svg b/Client/ThirdParty/Box2D/docs/images/raycast.svg
new file mode 100644
index 0000000..78ac5df
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/raycast.svg
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="248.01385"
+ height="218.69197"
+ id="svg3598"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="raycast.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\raycast.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs3600">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path4314"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective3606" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.6543567"
+ inkscape:cx="124.00693"
+ inkscape:cy="94.046232"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1246"
+ inkscape:window-height="849"
+ inkscape:window-x="100"
+ inkscape:window-y="100"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata3603">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-193.0054,-367.20351)">
+ <rect
+ y="473.70428"
+ x="232.34212"
+ height="16.815773"
+ width="19.815773"
+ id="rect4120"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="429.19492"
+ x="378.33273"
+ height="36.334541"
+ width="54.334541"
+ id="rect4122"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="548.88507"
+ x="222.02287"
+ height="21.954247"
+ width="35.454247"
+ id="rect4124"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="508.34296"
+ x="408.48077"
+ height="20.538485"
+ width="32.038483"
+ id="rect4126"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="524.32886"
+ x="306.46667"
+ height="61.066628"
+ width="43.566628"
+ id="rect4128"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="429.74796"
+ x="292.88577"
+ height="66.228439"
+ width="33.728436"
+ id="rect4130"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4276"
+ width="33.790939"
+ height="30.790941"
+ x="374.60455"
+ y="547.46674" />
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4278"
+ width="49.259716"
+ height="43.759716"
+ x="210.37013"
+ y="406.7323" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1, 2;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 413.96525,367.89693 -219.9305,175.4305"
+ id="path4282"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path4732"
+ d="m 414.26779,367.59439 -86.85587,69.28175"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/revolute_joint.gif b/Client/ThirdParty/Box2D/docs/images/revolute_joint.gif
new file mode 100644
index 0000000..39b74e2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/revolute_joint.gif
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/self_intersect.svg b/Client/ThirdParty/Box2D/docs/images/self_intersect.svg
new file mode 100644
index 0000000..9970d4b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/self_intersect.svg
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="335.57034"
+ height="156.77301"
+ id="svg9044"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="self_intersect.svg">
+ <defs
+ id="defs9046">
+ <linearGradient
+ id="linearGradient9562"
+ osb:paint="solid">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop9564" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.3657018"
+ inkscape:cx="167.78516"
+ inkscape:cy="67.620514"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1359"
+ inkscape:window-height="1041"
+ inkscape:window-x="150"
+ inkscape:window-y="60"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata9049">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-250.72341,-313.04733)">
+ <path
+ style="fill:none;stroke:#767676;stroke-width:0.7596947px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 253.77069,466.3256 70.02703,-17.5597 c 0,0 71.55832,-119.48587 75.58286,-118.02256 4.02453,1.46331 78.86187,117.75627 78.86187,117.75627 l 104.73573,-34.12145 -76.46629,-98.04163 -191.10691,74.53424 z"
+ id="path9052"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ sodipodi:nodetypes="ccsccccc" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ transform="translate(11.817253,-145.14071)"
+ id="path9620"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9622"
+ transform="translate(81.49165,-163.51344)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ transform="translate(235.87634,-162.86043)"
+ id="path9624"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9626"
+ transform="translate(72.583349,-220.46706)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9628"
+ transform="translate(341.33682,-197.58559)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ inkscape:export-ydpi="179.94545"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ transform="translate(265.17257,-295.86296)"
+ id="path9630"
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ <circle
+ style="fill:#b0ddb3;fill-opacity:1;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path9632"
+ transform="translate(157.4829,-281.42241)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SelfIntersect.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="241.93153"
+ cy="611.93567"
+ r="2.5253813" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/skin_collision.svg b/Client/ThirdParty/Box2D/docs/images/skin_collision.svg
new file mode 100644
index 0000000..29ac847
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/skin_collision.svg
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="322.26855"
+ height="108.76013"
+ id="svg5128"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="skin-collision.svg">
+ <defs
+ id="defs5130" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="149.63278"
+ inkscape:cy="38.587018"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1148"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata5133">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-178.07143,-467.67348)">
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5140"
+ width="56.568542"
+ height="42.426407"
+ x="314.03363"
+ y="471.8606"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="3.2142856"
+ inkscape:original="M 329.9375 406.5 L 329.9375 448.9375 L 386.5 448.9375 L 386.5 406.5 L 329.9375 406.5 z "
+ style="fill:none;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5700"
+ d="M 329.9375,403.28516 A 3.214607,3.214607 0 0 0 326.72266,406.5 v 42.4375 a 3.214607,3.214607 0 0 0 3.21484,3.21484 H 386.5 a 3.214607,3.214607 0 0 0 3.21484,-3.21484 V 406.5 A 3.214607,3.214607 0 0 0 386.5,403.28516 Z"
+ transform="translate(-15.980776,64.888322)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5138"
+ width="53.538086"
+ height="47.477169"
+ x="319.46075"
+ y="520.26434"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="3.2926946"
+ inkscape:original="M 319.75 426.21875 L 319.75 473.6875 L 373.28125 473.6875 L 373.28125 426.21875 L 319.75 426.21875 z "
+ style="fill:none;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5720"
+ d="m 319.75,422.92578 a 3.2930238,3.2930238 0 0 0 -3.29297,3.29297 v 47.46875 a 3.2930238,3.2930238 0 0 0 3.29297,3.29297 h 53.53125 a 3.2930238,3.2930238 0 0 0 3.29297,-3.29297 v -47.46875 a 3.2930238,3.2930238 0 0 0 -3.29297,-3.29297 z"
+ transform="translate(-0.59098611,95.046407)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 181.82746,572.53972 H 494.97475"
+ id="path5136"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <rect
+ style="fill:none;stroke:#7d7d7d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5750"
+ width="321.26855"
+ height="6.0714283"
+ x="178.57143"
+ y="569.86218"
+ ry="3.0357141"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="393.9595"
+ y="501.07144"
+ id="text5770"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinCollision.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ id="tspan5772"
+ x="393.9595"
+ y="501.07144"
+ style="font-size:14px;line-height:1.25">Polygons collide</tspan><tspan
+ sodipodi:role="line"
+ x="393.9595"
+ y="518.57141"
+ id="tspan5774"
+ style="font-size:14px;line-height:1.25">with their skin</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/skinned_polygon.svg b/Client/ThirdParty/Box2D/docs/images/skinned_polygon.svg
new file mode 100644
index 0000000..d93934c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/skinned_polygon.svg
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="174.87"
+ height="149.37024"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="skinned_polygon.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path3660"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3663"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path3645"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3657"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3639"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ id="path3654"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(1.1,0,0,1.1,1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2835"
+ inkscape:persp3d-origin="292.5 : 75.212601 : 1"
+ inkscape:vp_z="585 : 112.8189 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 112.8189 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8284271"
+ inkscape:cx="64.699886"
+ inkscape:cy="74.828007"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1737"
+ inkscape:window-height="1054"
+ inkscape:window-x="65"
+ inkscape:window-y="121"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-283.1327,-415.03117)">
+ <path
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 289.5,466.36218 26,47.5 57.5,43.5 77.5,-70 -17,-61.5 -70.5,-4 z"
+ id="path5829"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinnedPolygon.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:type="inkscape:offset"
+ inkscape:radius="6.4355307"
+ inkscape:original="M 486.25 547.125 L 412.75 591.625 L 438.75 639.125 L 496.25 682.625 L 573.75 612.625 L 556.75 551.125 L 486.25 547.125 z "
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1, 4;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3928"
+ d="m 485.9707,540.69531 a 6.4361742,6.4361742 0 0 0 -3.05468,0.92383 l -73.5,44.5 a 6.4361742,6.4361742 0 0 0 -2.31055,8.5957 l 26,47.5 a 6.4361742,6.4361742 0 0 0 1.76172,2.04297 l 57.5,43.5 a 6.4361742,6.4361742 0 0 0 8.19726,-0.35742 l 77.5,-70 a 6.4361742,6.4361742 0 0 0 1.88867,-6.49023 l -17,-61.5 a 6.4361742,6.4361742 0 0 0 -5.83789,-4.71094 l -70.5,-4 a 6.4361742,6.4361742 0 0 0 -0.64453,-0.004 z"
+ transform="translate(-122.68303,-125.1579)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\SkinnedPolygon.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/testbed.png b/Client/ThirdParty/Box2D/docs/images/testbed.png
new file mode 100644
index 0000000..e2de2ad
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/testbed.png
Binary files differ
diff --git a/Client/ThirdParty/Box2D/docs/images/tunneling1.svg b/Client/ThirdParty/Box2D/docs/images/tunneling1.svg
new file mode 100644
index 0000000..b6d68b0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/tunneling1.svg
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="274.69003"
+ height="244.50266"
+ id="svg3938"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="tunnel1.svg">
+ <defs
+ id="defs3940">
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path4488"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="42.598267"
+ inkscape:cy="2.3289626"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1402"
+ inkscape:window-height="1069"
+ inkscape:window-x="299"
+ inkscape:window-y="26"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata3943">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-241.98927,-300.82514)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 348.57143,300.93361 54.28571,244.28572"
+ id="path3946"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Tunnel1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3952"
+ sodipodi:sides="5"
+ sodipodi:cx="144.28571"
+ sodipodi:cy="343.79074"
+ sodipodi:r1="37.252586"
+ sodipodi:r2="30.137976"
+ sodipodi:arg1="1.0040671"
+ sodipodi:arg2="1.6323856"
+ inkscape:flatsided="true"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 164.28571,375.21931 -43.71001,-2.69547 -10.94359,-42.40364 36.94651,-23.51141 33.77777,27.87278 z"
+ inkscape:transform-center-x="-0.70854843"
+ inkscape:transform-center-y="-2.876691"
+ transform="translate(132.85715,125.71429)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Tunnel1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3952-2"
+ sodipodi:sides="5"
+ sodipodi:cx="144.28571"
+ sodipodi:cy="343.79074"
+ sodipodi:r1="37.252586"
+ sodipodi:r2="30.137976"
+ sodipodi:arg1="1.0040671"
+ sodipodi:arg2="1.6323856"
+ inkscape:flatsided="true"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 164.28571,375.21931 -43.71001,-2.69547 -10.94359,-42.40364 36.94651,-23.51141 33.77777,27.87278 z"
+ inkscape:transform-center-x="-1.9942167"
+ inkscape:transform-center-y="1.6069069"
+ transform="rotate(22.495262,160.88661,1216.0763)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Tunnel1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.79999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:7.19999981, 7.19999981;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+ d="m 290,413.79075 c 27.14286,-48.57142 84.28571,-68.57142 144.28571,-51.42857"
+ id="path4480"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Tunnel1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="260"
+ y="533.79077"
+ id="text5108"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Tunnel1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ id="tspan5110"
+ x="260"
+ y="533.79077"
+ style="font-size:14px;line-height:1.25">time0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="466.85715"
+ y="472.07648"
+ id="text5112"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\Tunnel1.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"><tspan
+ sodipodi:role="line"
+ id="tspan5114"
+ x="466.85715"
+ y="472.07648"
+ style="font-size:14px;line-height:1.25">time1</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/tunneling2.svg b/Client/ThirdParty/Box2D/docs/images/tunneling2.svg
new file mode 100644
index 0000000..fa6d609
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/tunneling2.svg
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="234"
+ height="101.75"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="tunneling2.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\tunneling.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3648"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3602"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="-68"
+ inkscape:cy="83.750001"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1390"
+ inkscape:window-height="1038"
+ inkscape:window-x="50"
+ inkscape:window-y="50"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-210,-490.36218)">
+ <rect
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect2816"
+ width="233"
+ height="13.5"
+ x="210.5"
+ y="541.86218" />
+ <circle
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3592"
+ transform="translate(7.5,3)"
+ cx="295.25"
+ cy="494.11218"
+ r="6.25" />
+ <circle
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3592-1"
+ transform="translate(7.5,91.25)"
+ cx="295.25"
+ cy="494.11218"
+ r="6.25" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.93691868;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.93691866, 1.87383732;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="M 302.99984,505.33064 V 577.0062"
+ id="path3616"
+ inkscape:connector-curvature="0" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ x="319"
+ y="499.86218"
+ id="text4066"><tspan
+ sodipodi:role="line"
+ id="tspan4068"
+ x="319"
+ y="499.86218"
+ style="font-size:12px;line-height:1.25">t=0</tspan></text>
+ <text
+ id="text4070"
+ y="587.86218"
+ x="319"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+ xml:space="preserve"><tspan
+ sodipodi:role="line"
+ id="tspan4074"
+ x="319"
+ y="587.86218"
+ style="font-size:12px;line-height:1.25">t=1</tspan></text>
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/wheel_joint.svg b/Client/ThirdParty/Box2D/docs/images/wheel_joint.svg
new file mode 100644
index 0000000..9e61929
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/wheel_joint.svg
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="69.631729"
+ height="119.93737"
+ id="svg5128"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="wheel-joint.svg">
+ <defs
+ id="defs5130">
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3807"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3789"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ id="path3804"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(1.1,0,0,1.1,1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mstart"
+ style="overflow:visible">
+ <path
+ id="path3792"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(0.4,0,0,0.4,4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3786"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(0.8,0,0,0.8,10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="-0.64333643"
+ inkscape:cy="-13.952543"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1359"
+ inkscape:window-height="1041"
+ inkscape:window-x="150"
+ inkscape:window-y="60"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata5133">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-313.07066,-471.3606)">
+ <rect
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#767676;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect5140"
+ width="56.568542"
+ height="42.426407"
+ x="314.03363"
+ y="471.8606"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\WheelJoint.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#767676;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2997"
+ transform="translate(-8.5714286,-2.8571429)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\WheelJoint.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="351.25"
+ cy="560.75507"
+ r="16.964285" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 341.78571,492.36218 1.42858,98.92857"
+ id="path3767"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\WheelJoint.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <circle
+ transform="translate(134.22402,67.175144)"
+ id="path3779"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\WheelJoint.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545"
+ cx="208.57143"
+ cy="490.93362"
+ r="2.1428571" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-mid:none;marker-end:url(#Arrow2Lend)"
+ d="m 377.85714,506.46933 0.53571,45"
+ id="path3781"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\WheelJoint.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ <path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#767676;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)"
+ id="path5547"
+ sodipodi:cx="313.57144"
+ sodipodi:cy="555.39789"
+ sodipodi:rx="23.392857"
+ sodipodi:ry="23.392857"
+ d="M 308.31133,578.19168 A 23.392857,23.392857 0 0 1 290.45762,559.00025 23.392857,23.392857 0 0 1 301.62433,535.2859"
+ sodipodi:start="1.7975952"
+ sodipodi:end="4.1763713"
+ sodipodi:open="true"
+ transform="translate(23.392857,2.5)"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\WheelJoint.png"
+ inkscape:export-xdpi="179.94545"
+ inkscape:export-ydpi="179.94545" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/images/winding.svg b/Client/ThirdParty/Box2D/docs/images/winding.svg
new file mode 100644
index 0000000..e543df0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/images/winding.svg
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="236.53163"
+ height="176.41858"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="winding.svg"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Mstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mstart"
+ style="overflow:visible">
+ <path
+ id="path3660"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path3663"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path3645"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3657"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3639"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lstart"
+ style="overflow:visible">
+ <path
+ id="path3654"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(1.1,0,0,1.1,1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2835"
+ inkscape:persp3d-origin="292.5 : 75.212601 : 1"
+ inkscape:vp_z="585 : 112.8189 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 112.8189 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.70710678"
+ inkscape:cx="-672.64537"
+ inkscape:cy="145.50488"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1737"
+ inkscape:window-height="1054"
+ inkscape:window-x="25"
+ inkscape:window-y="25"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-245.94154,-381.59189)">
+ <text
+ id="6"
+ xml:space="preserve"
+ x="476.47318"
+ y="507.86407"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">x</text>
+ <text
+ id="7"
+ xml:space="preserve"
+ x="482.47318"
+ y="507.86407"
+ style="font-style:normal;font-weight:normal;font-size:13.80000019px;line-height:0%;font-family:Calibri;text-align:start;text-anchor:start;fill:#000000"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"> </text>
+ <text
+ id="8"
+ xml:space="preserve"
+ x="387.67319"
+ y="387.19345"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">y</text>
+ <text
+ id="9"
+ xml:space="preserve"
+ x="396.32318"
+ y="383.19345"
+ style="font-style:normal;font-weight:normal;font-size:13.80000019px;line-height:0%;font-family:Calibri;text-align:start;text-anchor:start;fill:#000000"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"> </text>
+ <text
+ id="11"
+ xml:space="preserve"
+ x="245.37318"
+ y="420.09586"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:0%;font-family:Calibri;-inkscape-font-specification:Calibri;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">CCW winding</text>
+ <text
+ id="12"
+ xml:space="preserve"
+ x="294.62317"
+ y="397.59586"
+ style="font-style:normal;font-weight:normal;font-size:13.80000019px;line-height:0%;font-family:Calibri;text-align:start;text-anchor:start;fill:#000000"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"> </text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Mend)"
+ d="m 345.5,414.36218 -56.5,34"
+ id="path4267"
+ sodipodi:nodetypes="cc"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#d7e3f4;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 289.5,466.36218 26,47.5 57.5,43.5 77.5,-70 -17,-61.5 -70.5,-4 z"
+ id="path5829"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend)"
+ d="m 384,392.86218 v 101 h 95.5"
+ id="path5241"
+ inkscape:export-filename="D:\Development\Box2D\Box2D\Documentation\images\winding.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:connector-curvature="0" />
+ </g>
+</svg>
diff --git a/Client/ThirdParty/Box2D/docs/loose_ends.md b/Client/ThirdParty/Box2D/docs/loose_ends.md
new file mode 100644
index 0000000..249beef
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/loose_ends.md
@@ -0,0 +1,214 @@
+# Loose Ends
+
+## User Data
+The `b2Fixture`, `b2Body`, and `b2Joint` classes allow you to attach user data
+as a uintptr_t. This is handy when you are examining Box2D data
+structures and you want to determine how they relate to the objects in
+your game engine.
+
+For example, it is typical to attach an actor pointer to the rigid body
+on that actor. This sets up a circular reference. If you have the actor,
+you can get the body. If you have the body, you can get the actor.
+
+```cpp
+GameActor* actor = GameCreateActor();
+b2BodyDef bodyDef;
+bodyDef.userData.pointer = reinterpret_cast<uintptr_t>(actor);
+actor->body = myWorld->CreateBody(&bodyDef);
+```
+
+You can also use this to hold an integral value rather than a pointer.
+
+Here are some examples of cases where you would need the user data:
+- Applying damage to an actor using a collision result.
+- Playing a scripted event if the player is inside an axis-aligned box.
+- Accessing a game structure when Box2D notifies you that a joint is
+ going to be destroyed.
+
+Keep in mind that user data is optional and you can put anything in it.
+However, you should be consistent. For example, if you want to store an
+actor pointer on one body, you should keep an actor pointer on all
+bodies. Don't store an actor pointer on one body, and a foo pointer on
+another body. Casting an actor pointer to a foo pointer may lead to a
+crash.
+
+User data pointers are 0 by default.
+
+For fixtures you might consider defining a user data structure that lets
+you store game specific information, such as material type, effects
+hooks, sound hooks, etc.
+
+```cpp
+struct FixtureUserData
+{
+ int materialIndex;
+ // ...
+};
+
+FixtureUserData myData = new FixtureUserData;
+myData->materialIndex = 2;
+
+b2FixtureDef fixtureDef;
+fixtureDef.shape = &someShape;
+fixtureDef.userData.pointer = reinterpret_cast<uintptr_t>(myData);
+
+b2Fixture* fixture = body->CreateFixture(&fixtureDef);
+// ...
+
+delete fixture->GetUserData();
+body->DestroyFixture(fixture);
+```
+
+## Custom User Data
+You can define custom data structures that are embedded in the Box2D data
+structures. This is done by defining `B2_USER_SETTINGS` and providing the
+file `b2_user_settings.h`. See `b2_settings.h` for details.
+
+## Implicit Destruction
+Box2D doesn't use reference counting. So if you destroy a body it is
+really gone. Accessing a pointer to a destroyed body has undefined
+behavior. In other words, your program will likely crash and burn. To
+help fix these problems, the debug build memory manager fills destroyed
+entities with FDFDFDFD. This can help find problems more easily in some
+cases.
+
+If you destroy a Box2D entity, it is up to you to make sure you remove
+all references to the destroyed object. This is easy if you only have a
+single reference to the entity. If you have multiple references, you
+might consider implementing a handle class to wrap the raw pointer.
+
+Often when using Box2D you will create and destroy many bodies, shapes,
+and joints. Managing these entities is somewhat automated by Box2D. If
+you destroy a body then all associated shapes and joints are
+automatically destroyed. This is called implicit destruction.
+
+When you destroy a body, all its attached shapes, joints, and contacts
+are destroyed. This is called implicit destruction. Any body connected
+to one of those joints and/or contacts is woken. This process is usually
+convenient. However, you must be aware of one crucial issue:
+
+> **Caution**:
+> When a body is destroyed, all fixtures and joints attached to the body
+> are automatically destroyed. You must nullify any pointers you have to
+> those shapes and joints. Otherwise, your program will die horribly if
+> you try to access or destroy those shapes or joints later.
+
+To help you nullify your joint pointers, Box2D provides a listener class
+named b2DestructionListener that you can implement and provide to your
+world object. Then the world object will notify you when a joint is
+going to be implicitly destroyed
+
+Note that there no notification when a joint or fixture is explicitly
+destroyed. In this case ownership is clear and you can perform the
+necessary cleanup on the spot. If you like, you can call your own
+implementation of b2DestructionListener to keep cleanup code
+centralized.
+
+Implicit destruction is a great convenience in many cases. It can also
+make your program fall apart. You may store pointers to shapes and
+joints somewhere in your code. These pointers become orphaned when an
+associated body is destroyed. The situation becomes worse when you
+consider that joints are often created by a part of the code unrelated
+to management of the associated body. For example, the testbed creates a
+b2MouseJoint for interactive manipulation of bodies on the screen.
+
+Box2D provides a callback mechanism to inform your application when
+implicit destruction occurs. This gives your application a chance to
+nullify the orphaned pointers. This callback mechanism is described
+later in this manual.
+
+You can implement a `b2DestructionListener` that allows b2World to inform
+you when a shape or joint is implicitly destroyed because an associated
+body was destroyed. This will help prevent your code from accessing
+orphaned pointers.
+
+```cpp
+class MyDestructionListener : public b2DestructionListener
+{
+ void SayGoodbye(b2Joint* joint)
+ {
+ // remove all references to joint.
+ }
+};
+```
+
+You can then register an instance of your destruction listener with your
+world object. You should do this during world initialization.
+
+```cpp
+myWorld->SetListener(myDestructionListener);
+```
+
+## Pixels and Coordinate Systems
+Recall that Box2D uses MKS (meters, kilograms, and seconds) units and
+radians for angles. You may have trouble working with meters because
+your game is expressed in terms of pixels. To deal with this in the
+testbed I have the whole *game* work in meters and just use an OpenGL
+viewport transformation to scale the world into screen space.
+
+```cpp
+float lowerX = -25.0f, upperX = 25.0f, lowerY = -5.0f, upperY = 25.0f;
+gluOrtho2D(lowerX, upperX, lowerY, upperY);
+```
+
+If your game must work in pixel units then you should convert your
+length units from pixels to meters when passing values from Box2D.
+Likewise you should convert the values received from Box2D from meters
+to pixels. This will improve the stability of the physics simulation.
+
+You have to come up with a reasonable conversion factor. I suggest
+making this choice based on the size of your characters. Suppose you
+have determined to use 50 pixels per meter (because your character is 75
+pixels tall). Then you can convert from pixels to meters using these
+formulas:
+
+```cpp
+xMeters = 0.02f * xPixels;
+yMeters = 0.02f * yPixels;
+```
+
+In reverse:
+
+```cpp
+xPixels = 50.0f * xMeters;
+yPixels = 50.0f * yMeters;
+```
+
+You should consider using MKS units in your game code and just convert
+to pixels when you render. This will simplify your game logic and reduce
+the chance for errors since the rendering conversion can be isolated to
+a small amount of code.
+
+If you use a conversion factor, you should try tweaking it globally to
+make sure nothing breaks. You can also try adjusting it to improve
+stability.
+
+## Debug Drawing
+You can implement the b2DebugDraw class to get detailed drawing of the
+physics world. Here are the available entities:
+- shape outlines
+- joint connectivity
+- broad-phase axis-aligned bounding boxes (AABBs)
+- center of mass
+
+![Debug Draw](images/debug_draw.png)
+
+This is the preferred method of drawing these physics entities, rather
+than accessing the data directly. The reason is that much of the
+necessary data is internal and subject to change.
+
+The testbed draws physics entities using the debug draw facility and the
+contact listener, so it serves as the primary example of how to
+implement debug drawing as well as how to draw contact points.
+
+## Limitations
+Box2D uses several approximations to simulate rigid body physics
+efficiently. This brings some limitations.
+
+Here are the current limitations:
+1. Stacking heavy bodies on top of much lighter bodies is not stable. Stability degrades as the mass ratio passes 10:1.
+2. Chains of bodies connected by joints may stretch if a lighter body is supporting a heavier body. For example, a wrecking ball connect to a chain of light weight bodies may not be stable. Stability degrades as the mass ratio passes 10:1.
+3. There is typically around 0.5cm of slop in shape versus shape collision.
+4. Continuous collision does not handle joints. So you may see joint stretching on fast moving objects.
+5. Box2D uses the symplectic Euler integration scheme. It does not reproduce parabolic motion of projectiles and has only first-order accuracy. However it is fast and has good stability.
+6. Box2D uses an iterative solver to provide real-time performance. You will not get precisely rigid collisions or pixel perfect accuracy. Increasing the iterations will improve accuracy.
diff --git a/Client/ThirdParty/Box2D/docs/overview.md b/Client/ThirdParty/Box2D/docs/overview.md
new file mode 100644
index 0000000..99142f3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/overview.md
@@ -0,0 +1,216 @@
+# Overview
+Box2D is a 2D rigid body simulation library for games. Programmers can
+use it in their games to make objects move in realistic ways and make
+the game world more interactive. From the game engine's point of view,
+a physics engine is just a system for procedural animation.
+
+Box2D is written in portable C++. Most of the types defined in the
+engine begin with the b2 prefix. Hopefully this is sufficient to avoid
+name clashing with your game engine.
+
+## Prerequisites
+In this manual I'll assume you are familiar with basic physics
+concepts, such as mass, force, torque, and impulses. If not, please
+first consult Google search and Wikipedia.
+
+Box2D was created as part of a physics tutorial at the Game Developer
+Conference. You can get these tutorials from the download section of
+box2d.org.
+
+Since Box2D is written in C++, you are expected to be experienced in C++
+programming. Box2D should not be your first C++ programming project! You
+should be comfortable with compiling, linking, and debugging.
+
+> **Caution**:
+> Box2D should not be your first C++ project. Please learn C++
+> programming, compiling, linking, and debugging before working with
+> Box2D. There are many resources for this on the net.
+
+## Scope
+This manual covers the majority of the Box2D API. However, not every
+aspect is covered. Please look at the testbed included
+with Box2D to learn more.
+
+This manual is only updated with new releases. The latest version of
+Box2D may be out of sync with this manual.
+
+## Feedback and Bugs
+Please file bugs and feature requests here:
+[Box2D Issues](https://github.com/erincatto/box2d/issues)
+
+You can help to ensure your issue gets fixed if you provide sufficient
+detail. A testbed example that reproduces the problem is ideal. You can
+read about the testbed later in this document.
+
+There is also a [Discord server](https://discord.gg/NKYgCBP) and a
+[subreddit](https://reddit.com/r/box2d) for Box2D.
+
+## Core Concepts
+Box2D works with several fundamental concepts and objects. We briefly
+define these objects here and more details are given later in this
+document.
+
+#### shape
+A shape is 2D geometrical object, such as a circle or polygon.
+
+#### rigid body
+A chunk of matter that is so strong that the distance between any two
+bits of matter on the chunk is constant. They are hard like a diamond.
+In the following discussion we use body interchangeably with rigid body.
+
+#### fixture
+A fixture binds a shape to a body and adds material properties such as
+density, friction, and restitution. A fixture puts a shape into the
+collision system (broad-phase) so that it can collide with other shapes.
+
+#### constraint
+A constraint is a physical connection that removes degrees of freedom
+from bodies. A 2D body has 3 degrees of freedom (two translation
+coordinates and one rotation coordinate). If we take a body and pin it
+to the wall (like a pendulum) we have constrained the body to the wall.
+At this point the body can only rotate about the pin, so the constraint
+has removed 2 degrees of freedom.
+
+#### contact constraint
+A special constraint designed to prevent penetration of rigid bodies and
+to simulate friction and restitution. You do not create contact
+constraints; they are created automatically by Box2D.
+
+#### joint
+This is a constraint used to hold two or more bodies together. Box2D
+supports several joint types: revolute, prismatic, distance, and more.
+Some joints may have limits and motors.
+
+#### joint limit
+A joint limit restricts the range of motion of a joint. For example, the
+human elbow only allows a certain range of angles.
+
+#### joint motor
+A joint motor drives the motion of the connected bodies according to the
+joint's degrees of freedom. For example, you can use a motor to drive
+the rotation of an elbow.
+
+#### world
+A physics world is a collection of bodies, fixtures, and constraints
+that interact together. Box2D supports the creation of multiple worlds,
+but this is usually not necessary or desirable.
+
+#### solver
+The physics world has a solver that is used to advance time and to
+resolve contact and joint constraints. The Box2D solver is a high
+performance iterative solver that operates in order N time, where N is
+the number of constraints.
+
+#### continuous collision
+The solver advances bodies in time using discrete time steps. Without
+intervention this can lead to tunneling.
+![Tunneling Effect](images/tunneling1.svg)
+
+Box2D contains specialized algorithms to deal with tunneling. First, the
+collision algorithms can interpolate the motion of two bodies to find
+the first time of impact (TOI). Second, there is a sub-stepping solver
+that moves bodies to their first time of impact and then resolves the
+collision.
+
+## Modules
+Box2D is composed of three modules: Common, Collision, and Dynamics. The
+Common module has code for allocation, math, and settings. The Collision
+module defines shapes, a broad-phase, and collision functions/queries.
+Finally the Dynamics module provides the simulation world, bodies,
+fixtures, and joints.
+![Box2D Modules](images/modules.svg)
+
+## Units
+Box2D works with floating point numbers and tolerances have to be used
+to make Box2D perform well. These tolerances have been tuned to work
+well with meters-kilogram-second (MKS) units. In particular, Box2D has
+been tuned to work well with moving shapes between 0.1 and 10 meters. So
+this means objects between soup cans and buses in size should work well.
+Static shapes may be up to 50 meters long without trouble.
+
+Being a 2D physics engine, it is tempting to use pixels as your units.
+Unfortunately this will lead to a poor simulation and possibly weird
+behavior. An object of length 200 pixels would be seen by Box2D as the
+size of a 45 story building.
+
+> **Caution**:
+> Box2D is tuned for MKS units. Keep the size of moving objects roughly
+> between 0.1 and 10 meters. You'll need to use some scaling system when
+> you render your environment and actors. The Box2D testbed does this by
+> using an OpenGL viewport transform. DO NOT USE PIXELS.
+
+It is best to think of Box2D bodies as moving billboards upon which you
+attach your artwork. The billboard may move in a unit system of meters,
+but you can convert that to pixel coordinates with a simple scaling
+factor. You can then use those pixel coordinates to place your sprites,
+etc. You can also account for flipped coordinate axes.
+
+Another limitation to consider is overall world size. If your world units
+become larger than 2 kilometers or so, then the lost precision can affect
+stability.
+
+> **Caution**:
+> Box2D works best with world sizes less than 2 kilometers. Use
+> b2World::ShiftOrigin to support larger worlds.
+
+If you need to have a larger game world, consider using
+b2World::ShiftOrigin to keep the world origin close to your player. I recommend
+to use grid lines along with some hysteresis for triggering calls to ShiftOrigin.
+This call should be made infrequently because it is has CPU cost. You may
+need to store a physics offset when translating between game units and Box2D units.
+
+Box2D uses radians for angles. The body rotation is stored in radians
+and may grow unbounded. Consider normalizing the angle of your bodies if
+the magnitude of the angle becomes too large (use `b2Body::SetTransform`).
+
+> **Caution**:
+> Box2D uses radians, not degrees.
+
+## Changing the length units
+Advanced users may change the length unit modifying `b2_lengthUnitsPerMeter`.
+You can avoid merge conflicts by defining `B2_USER_SETTINGS` and providing
+`b2_user_settings.h`. See the file `b2_settings.h` for details.
+
+## Factories and Definitions
+Fast memory management plays a central role in the design of the Box2D
+API. So when you create a b2Body or a b2Joint, you need to call the
+factory functions on b2World. You should never try to allocate these
+types in another manner.
+
+There are creation functions:
+
+```cpp
+b2Body* b2World::CreateBody(const b2BodyDef* def)
+b2Joint* b2World::CreateJoint(const b2JointDef* def)
+```
+
+And there are corresponding destruction functions:
+
+```cpp
+void b2World::DestroyBody(b2Body* body)
+void b2World::DestroyJoint(b2Joint* joint)
+```
+
+When you create a body or joint, you need to provide a definition. These
+definitions contain all the information needed to build the body or
+joint. By using this approach we can prevent construction errors, keep
+the number of function parameters small, provide sensible defaults, and
+reduce the number of accessors.
+
+Since fixtures (shapes) must be parented to a body, they are created and
+destroyed using a factory method on b2Body:
+
+```cpp
+b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)
+void b2Body::DestroyFixture(b2Fixture* fixture)
+```
+
+There is also shortcut to create a fixture directly from the shape and
+density.
+
+```cpp
+b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float density)
+```
+
+Factories do not retain references to the definitions. So you can create
+definitions on the stack and keep them in temporary resources.
diff --git a/Client/ThirdParty/Box2D/docs/references.md b/Client/ThirdParty/Box2D/docs/references.md
new file mode 100644
index 0000000..4d2aa5a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/references.md
@@ -0,0 +1,4 @@
+# References
+- [Erin Catto's Publications](https://box2d.org/publications/)
+- Collision Detection in Interactive 3D Environments, Gino van den Bergen, 2004
+- Real-Time Collision Detection, Christer Ericson, 2005
diff --git a/Client/ThirdParty/Box2D/docs/testbed.md b/Client/ThirdParty/Box2D/docs/testbed.md
new file mode 100644
index 0000000..a6f2233
--- /dev/null
+++ b/Client/ThirdParty/Box2D/docs/testbed.md
@@ -0,0 +1,21 @@
+# Testbed
+Once you have conquered the HelloWorld example, you should start looking
+at Box2D's testbed. The testbed is a testing framework and demo
+environment. Here are some of the features:
+- Camera with pan and zoom.
+- Mouse picking of shapes attached to dynamic bodies.
+- Extensible set of tests.
+- GUI for selecting tests, parameter tuning, and debug drawing options.
+- Pause and single step simulation.
+- Text rendering.
+
+![Box2D Testbed](images/testbed.png)
+
+The testbed has many examples of Box2D usage in the test cases and the
+framework itself. I encourage you to explore and tinker with the testbed
+as you learn Box2D.
+
+Note: the testbed is written using [GLFW](https://www.glfw.org) and
+[imgui](https://github.com/ocornut/imgui). The testbed is not part of the
+Box2D library. The Box2D library is agnostic about rendering. As shown by
+the HelloWorld example, you don't need a renderer to use Box2D.
diff --git a/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt b/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt
new file mode 100644
index 0000000..f7e0b8b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(GLAD_SOURCE_FILES
+ src/gl.c)
+
+set(GLAD_HEADER_FILES
+ include/glad/gl.h
+ include/KHR/khrplatform.h)
+
+add_library(glad STATIC ${GLAD_SOURCE_FILES} ${GLAD_HEADER_FILES})
+target_include_directories(glad PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${GLAD_SOURCE_FILES} ${GLAD_HEADER_FILES})
diff --git a/Client/ThirdParty/Box2D/extern/glad/include/KHR/khrplatform.h b/Client/ThirdParty/Box2D/extern/glad/include/KHR/khrplatform.h
new file mode 100644
index 0000000..5b55ea2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glad/include/KHR/khrplatform.h
@@ -0,0 +1,290 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ * 67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
+# define KHRONOS_STATIC 1
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(KHRONOS_STATIC)
+ /* If the preprocessor constant KHRONOS_STATIC is defined, make the
+ * header compatible with static linking. */
+# define KHRONOS_APICALL
+#elif defined(_WIN32)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+# define KHRONOS_APICALL __attribute__((visibility("default")))
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(KHRONOS_STATIC)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/Client/ThirdParty/Box2D/extern/glad/include/glad/gl.h b/Client/ThirdParty/Box2D/extern/glad/include/glad/gl.h
new file mode 100644
index 0000000..0910038
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glad/include/glad/gl.h
@@ -0,0 +1,2114 @@
+/**
+ * Loader generated by glad 2.0.0-beta on Fri Dec 27 01:40:51 2019
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 0
+ *
+ * APIs:
+ * - gl:core=3.3
+ *
+ * Options:
+ * - MX_GLOBAL = False
+ * - ON_DEMAND = False
+ * - LOADER = False
+ * - ALIAS = False
+ * - HEADER_ONLY = False
+ * - DEBUG = False
+ * - MX = False
+ *
+ * Commandline:
+ * --api='gl:core=3.3' --extensions='' c
+ *
+ * Online:
+ * http://glad.sh/#api=gl%3Acore%3D3.3&extensions=&generator=c&options=
+ *
+ */
+
+#ifndef GLAD_GL_H_
+#define GLAD_GL_H_
+
+#ifdef __gl_h_
+ #error OpenGL header already included (API: gl), remove previous include!
+#endif
+#define __gl_h_ 1
+
+
+#define GLAD_GL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+ #define GLAD_PLATFORM_WIN32 1
+ #else
+ #define GLAD_PLATFORM_WIN32 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+ #ifdef __APPLE__
+ #define GLAD_PLATFORM_APPLE 1
+ #else
+ #define GLAD_PLATFORM_APPLE 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+ #ifdef __EMSCRIPTEN__
+ #define GLAD_PLATFORM_EMSCRIPTEN 1
+ #else
+ #define GLAD_PLATFORM_EMSCRIPTEN 0
+ #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+ #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+ #ifdef __has_include
+ #if __has_include(<winapifamily.h>)
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+ #endif
+ #endif
+
+ #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+ #include <winapifamily.h>
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define GLAD_PLATFORM_UWP 1
+ #endif
+ #endif
+
+ #ifndef GLAD_PLATFORM_UWP
+ #define GLAD_PLATFORM_UWP 0
+ #endif
+#endif
+
+#ifdef __GNUC__
+ #define GLAD_GNUC_EXTENSION __extension__
+#else
+ #define GLAD_GNUC_EXTENSION
+#endif
+
+#ifndef GLAD_API_CALL
+ #if defined(GLAD_API_CALL_EXPORT)
+ #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+ #if defined(GLAD_API_CALL_EXPORT_BUILD)
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllexport) extern
+ #endif
+ #else
+ #if defined(__GNUC__)
+ #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+ #else
+ #define GLAD_API_CALL __declspec(dllimport) extern
+ #endif
+ #endif
+ #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+ #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+ #else
+ #define GLAD_API_CALL extern
+ #endif
+#endif
+
+#ifdef APIENTRY
+ #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+ #define GLAD_API_PTR __stdcall
+#else
+ #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+#define GLAD_GENERATOR_VERSION "2.0.0-beta"
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALPHA 0x1906
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_ALWAYS 0x0207
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLUE 0x1905
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BYTE 0x1400
+#define GL_CCW 0x0901
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLEAR 0x1500
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_COLOR 0x1800
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CW 0x0900
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH 0x1801
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DITHER 0x0BD0
+#define GL_DONT_CARE 0x1100
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EXTENSIONS 0x1F03
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FILL 0x1B02
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FIXED_ONLY 0x891D
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEQUAL 0x0206
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_HALF_FLOAT 0x140B
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INT 0x1404
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_INDEX 0xFFFFFFFF
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINK_STATUS 0x8B82
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MIN 0x8007
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MULTISAMPLE 0x809D
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_OBJECT_TYPE 0x9112
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OR 0x1507
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R16_SNORM 0x8F98
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R3_G3_B2 0x2A10
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_BUFFER 0x0C02
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_WRITE 0x88BA
+#define GL_RED 0x1903
+#define GL_RED_INTEGER 0x8D94
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB10_A2UI 0x906F
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB16F 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB32F 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA2 0x8055
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RG_INTEGER 0x8228
+#define GL_RIGHT 0x0407
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_SET 0x150F
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHORT 0x1402
+#define GL_SIGNALED 0x9119
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC1_COLOR 0x88F9
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_TRUE 1
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VIEWPORT 0x0BA2
+#define GL_WAIT_FAILED 0x911D
+#define GL_WRITE_ONLY 0x88B9
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+
+
+#include <KHR/khrplatform.h>
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void);
+
+
+#define GL_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_0;
+#define GL_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_1;
+#define GL_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_2;
+#define GL_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_3;
+#define GL_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_4;
+#define GL_VERSION_1_5 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_5;
+#define GL_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_0;
+#define GL_VERSION_2_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_1;
+#define GL_VERSION_3_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_0;
+#define GL_VERSION_3_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_1;
+#define GL_VERSION_3_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_2;
+#define GL_VERSION_3_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_3;
+
+
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
+typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble depth);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s);
+typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void);
+typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img);
+typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data);
+typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
+typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values);
+typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name);
+typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint sampler);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat size);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
+typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint * param);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
+#define glBeginConditionalRender glad_glBeginConditionalRender
+GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery;
+#define glBeginQuery glad_glBeginQuery
+GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
+#define glBeginTransformFeedback glad_glBeginTransformFeedback
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
+#define glBindBufferBase glad_glBindBufferBase
+GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
+#define glBindBufferRange glad_glBindBufferRange
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
+#define glBindFragDataLocation glad_glBindFragDataLocation
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
+#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler;
+#define glBindSampler glad_glBindSampler
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
+#define glBindVertexArray glad_glBindVertexArray
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
+#define glBlitFramebuffer glad_glBlitFramebuffer
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor;
+#define glClampColor glad_glClampColor
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
+#define glClearBufferfi glad_glClearBufferfi
+GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
+#define glClearBufferfv glad_glClearBufferfv
+GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
+#define glClearBufferiv glad_glClearBufferiv
+GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
+#define glClearBufferuiv glad_glClearBufferuiv
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth;
+#define glClearDepth glad_glClearDepth
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
+#define glClientWaitSync glad_glClientWaitSync
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski;
+#define glColorMaski glad_glColorMaski
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
+#define glCompressedTexImage1D glad_glCompressedTexImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
+#define glCompressedTexImage3D glad_glCompressedTexImage3D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
+#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
+#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
+GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
+#define glCopyBufferSubData glad_glCopyBufferSubData
+GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
+#define glCopyTexImage1D glad_glCopyTexImage1D
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
+#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
+#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
+#define glDeleteQueries glad_glDeleteQueries
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
+#define glDeleteSamplers glad_glDeleteSamplers
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync;
+#define glDeleteSync glad_glDeleteSync
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
+#define glDeleteVertexArrays glad_glDeleteVertexArrays
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange;
+#define glDepthRange glad_glDepthRange
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei;
+#define glDisablei glad_glDisablei
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
+#define glDrawArraysInstanced glad_glDrawArraysInstanced
+GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
+#define glDrawBuffer glad_glDrawBuffer
+GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
+#define glDrawBuffers glad_glDrawBuffers
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
+#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
+#define glDrawElementsInstanced glad_glDrawElementsInstanced
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
+#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
+#define glDrawRangeElements glad_glDrawRangeElements
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
+#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei;
+#define glEnablei glad_glEnablei
+GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
+#define glEndConditionalRender glad_glEndConditionalRender
+GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery;
+#define glEndQuery glad_glEndQuery
+GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
+#define glEndTransformFeedback glad_glEndTransformFeedback
+GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync;
+#define glFenceSync glad_glFenceSync
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
+#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
+#define glFramebufferTexture glad_glFramebufferTexture
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
+#define glFramebufferTexture1D glad_glFramebufferTexture1D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
+#define glFramebufferTexture3D glad_glFramebufferTexture3D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
+#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries;
+#define glGenQueries glad_glGenQueries
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers;
+#define glGenSamplers glad_glGenSamplers
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
+#define glGenVertexArrays glad_glGenVertexArrays
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
+#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
+#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
+#define glGetActiveUniformName glad_glGetActiveUniformName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
+#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
+#define glGetBooleani_v glad_glGetBooleani_v
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
+#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
+#define glGetBufferPointerv glad_glGetBufferPointerv
+GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
+#define glGetBufferSubData glad_glGetBufferSubData
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
+#define glGetCompressedTexImage glad_glGetCompressedTexImage
+GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev;
+#define glGetDoublev glad_glGetDoublev
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
+#define glGetFragDataIndex glad_glGetFragDataIndex
+GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
+#define glGetFragDataLocation glad_glGetFragDataLocation
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
+#define glGetInteger64i_v glad_glGetInteger64i_v
+GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
+#define glGetInteger64v glad_glGetInteger64v
+GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
+#define glGetIntegeri_v glad_glGetIntegeri_v
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
+#define glGetMultisamplefv glad_glGetMultisamplefv
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
+#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
+#define glGetQueryObjectiv glad_glGetQueryObjectiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
+#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
+#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
+GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv;
+#define glGetQueryiv glad_glGetQueryiv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
+#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
+#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
+#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
+#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi;
+#define glGetStringi glad_glGetStringi
+GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv;
+#define glGetSynciv glad_glGetSynciv
+GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
+#define glGetTexImage glad_glGetTexImage
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
+#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
+#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
+#define glGetTexParameterIiv glad_glGetTexParameterIiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
+#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
+#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
+GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
+#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
+GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
+#define glGetUniformIndices glad_glGetUniformIndices
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
+#define glGetUniformuiv glad_glGetUniformuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
+#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
+#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
+#define glGetVertexAttribdv glad_glGetVertexAttribdv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi;
+#define glIsEnabledi glad_glIsEnabledi
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery;
+#define glIsQuery glad_glIsQuery
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler;
+#define glIsSampler glad_glIsSampler
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync;
+#define glIsSync glad_glIsSync
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
+#define glIsVertexArray glad_glIsVertexArray
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp;
+#define glLogicOp glad_glLogicOp
+GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer;
+#define glMapBuffer glad_glMapBuffer
+GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
+#define glMapBufferRange glad_glMapBufferRange
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
+#define glMultiDrawArrays glad_glMultiDrawArrays
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
+#define glMultiDrawElements glad_glMultiDrawElements
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
+#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
+GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref;
+#define glPixelStoref glad_glPixelStoref
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
+#define glPointParameterf glad_glPointParameterf
+GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
+#define glPointParameterfv glad_glPointParameterfv
+GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
+#define glPointParameteri glad_glPointParameteri
+GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
+#define glPointParameteriv glad_glPointParameteriv
+GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize;
+#define glPointSize glad_glPointSize
+GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode;
+#define glPolygonMode glad_glPolygonMode
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
+#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
+GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
+#define glProvokingVertex glad_glProvokingVertex
+GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
+#define glQueryCounter glad_glQueryCounter
+GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer;
+#define glReadBuffer glad_glReadBuffer
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
+#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
+#define glSampleMaski glad_glSampleMaski
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
+#define glSamplerParameterIiv glad_glSamplerParameterIiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
+#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
+#define glSamplerParameterf glad_glSamplerParameterf
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
+#define glSamplerParameterfv glad_glSamplerParameterfv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
+#define glSamplerParameteri glad_glSamplerParameteri
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
+#define glSamplerParameteriv glad_glSamplerParameteriv
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer;
+#define glTexBuffer glad_glTexBuffer
+GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
+#define glTexImage1D glad_glTexImage1D
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
+#define glTexImage2DMultisample glad_glTexImage2DMultisample
+GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
+#define glTexImage3D glad_glTexImage3D
+GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
+#define glTexImage3DMultisample glad_glTexImage3DMultisample
+GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
+#define glTexParameterIiv glad_glTexParameterIiv
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
+#define glTexParameterIuiv glad_glTexParameterIuiv
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
+#define glTexSubImage1D glad_glTexSubImage1D
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
+#define glTexSubImage3D glad_glTexSubImage3D
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
+#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui;
+#define glUniform1ui glad_glUniform1ui
+GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
+#define glUniform1uiv glad_glUniform1uiv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui;
+#define glUniform2ui glad_glUniform2ui
+GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
+#define glUniform2uiv glad_glUniform2uiv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui;
+#define glUniform3ui glad_glUniform3ui
+GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
+#define glUniform3uiv glad_glUniform3uiv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui;
+#define glUniform4ui glad_glUniform4ui
+GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
+#define glUniform4uiv glad_glUniform4uiv
+GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
+#define glUniformBlockBinding glad_glUniformBlockBinding
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
+#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
+#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
+#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
+#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
+#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
+#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
+GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
+#define glUnmapBuffer glad_glUnmapBuffer
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
+#define glVertexAttrib1d glad_glVertexAttrib1d
+GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
+#define glVertexAttrib1dv glad_glVertexAttrib1dv
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
+#define glVertexAttrib1s glad_glVertexAttrib1s
+GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
+#define glVertexAttrib1sv glad_glVertexAttrib1sv
+GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
+#define glVertexAttrib2d glad_glVertexAttrib2d
+GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
+#define glVertexAttrib2dv glad_glVertexAttrib2dv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
+#define glVertexAttrib2s glad_glVertexAttrib2s
+GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
+#define glVertexAttrib2sv glad_glVertexAttrib2sv
+GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
+#define glVertexAttrib3d glad_glVertexAttrib3d
+GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
+#define glVertexAttrib3dv glad_glVertexAttrib3dv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
+#define glVertexAttrib3s glad_glVertexAttrib3s
+GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
+#define glVertexAttrib3sv glad_glVertexAttrib3sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
+#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
+#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
+#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
+#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
+#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
+#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
+#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
+GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
+#define glVertexAttrib4bv glad_glVertexAttrib4bv
+GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
+#define glVertexAttrib4d glad_glVertexAttrib4d
+GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
+#define glVertexAttrib4dv glad_glVertexAttrib4dv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
+#define glVertexAttrib4iv glad_glVertexAttrib4iv
+GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
+#define glVertexAttrib4s glad_glVertexAttrib4s
+GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
+#define glVertexAttrib4sv glad_glVertexAttrib4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
+#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
+#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
+#define glVertexAttrib4usv glad_glVertexAttrib4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
+#define glVertexAttribDivisor glad_glVertexAttribDivisor
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
+#define glVertexAttribI1i glad_glVertexAttribI1i
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
+#define glVertexAttribI1iv glad_glVertexAttribI1iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
+#define glVertexAttribI1ui glad_glVertexAttribI1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
+#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
+#define glVertexAttribI2i glad_glVertexAttribI2i
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
+#define glVertexAttribI2iv glad_glVertexAttribI2iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
+#define glVertexAttribI2ui glad_glVertexAttribI2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
+#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
+#define glVertexAttribI3i glad_glVertexAttribI3i
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
+#define glVertexAttribI3iv glad_glVertexAttribI3iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
+#define glVertexAttribI3ui glad_glVertexAttribI3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
+#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
+#define glVertexAttribI4bv glad_glVertexAttribI4bv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
+#define glVertexAttribI4i glad_glVertexAttribI4i
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
+#define glVertexAttribI4iv glad_glVertexAttribI4iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
+#define glVertexAttribI4sv glad_glVertexAttribI4sv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
+#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
+#define glVertexAttribI4ui glad_glVertexAttribI4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
+#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
+#define glVertexAttribI4usv glad_glVertexAttribI4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
+#define glVertexAttribIPointer glad_glVertexAttribIPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
+#define glVertexAttribP1ui glad_glVertexAttribP1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
+#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
+#define glVertexAttribP2ui glad_glVertexAttribP2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
+#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
+#define glVertexAttribP3ui glad_glVertexAttribP3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
+#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
+#define glVertexAttribP4ui glad_glVertexAttribP4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
+#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync;
+#define glWaitSync glad_glWaitSync
+
+
+
+
+
+GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Client/ThirdParty/Box2D/extern/glad/src/gl.c b/Client/ThirdParty/Box2D/extern/glad/src/gl.c
new file mode 100644
index 0000000..071ff2a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glad/src/gl.c
@@ -0,0 +1,949 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/gl.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+
+
+
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+
+
+static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_0) return;
+ glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc");
+ glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear");
+ glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor");
+ glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth");
+ glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil");
+ glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask");
+ glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace");
+ glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc");
+ glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask");
+ glad_glDepthRange = (PFNGLDEPTHRANGEPROC) load(userptr, "glDepthRange");
+ glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable");
+ glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC) load(userptr, "glDrawBuffer");
+ glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable");
+ glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish");
+ glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush");
+ glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace");
+ glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv");
+ glad_glGetDoublev = (PFNGLGETDOUBLEVPROC) load(userptr, "glGetDoublev");
+ glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError");
+ glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv");
+ glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv");
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC) load(userptr, "glGetTexImage");
+ glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv");
+ glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv");
+ glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv");
+ glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv");
+ glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint");
+ glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled");
+ glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth");
+ glad_glLogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp");
+ glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref");
+ glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei");
+ glad_glPointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize");
+ glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode");
+ glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer");
+ glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels");
+ glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor");
+ glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc");
+ glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask");
+ glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp");
+ glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC) load(userptr, "glTexImage1D");
+ glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D");
+ glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf");
+ glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv");
+ glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri");
+ glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv");
+ glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport");
+}
+static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_1) return;
+ glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture");
+ glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load(userptr, "glCopyTexImage1D");
+ glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D");
+ glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load(userptr, "glCopyTexSubImage1D");
+ glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D");
+ glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures");
+ glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays");
+ glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements");
+ glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures");
+ glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture");
+ glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset");
+ glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D");
+ glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D");
+}
+static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_2) return;
+ glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D");
+ glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements");
+ glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D");
+ glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D");
+}
+static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_3) return;
+ glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture");
+ glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load(userptr, "glCompressedTexImage1D");
+ glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D");
+ glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D");
+ glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load(userptr, "glCompressedTexSubImage1D");
+ glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D");
+ glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D");
+ glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetCompressedTexImage");
+ glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage");
+}
+static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_4) return;
+ glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor");
+ glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation");
+ glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate");
+ glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load(userptr, "glMultiDrawArrays");
+ glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load(userptr, "glMultiDrawElements");
+ glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load(userptr, "glPointParameterf");
+ glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load(userptr, "glPointParameterfv");
+ glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load(userptr, "glPointParameteri");
+ glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load(userptr, "glPointParameteriv");
+}
+static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_1_5) return;
+ glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery");
+ glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer");
+ glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData");
+ glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData");
+ glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers");
+ glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries");
+ glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery");
+ glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers");
+ glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries");
+ glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv");
+ glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv");
+ glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load(userptr, "glGetBufferSubData");
+ glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load(userptr, "glGetQueryObjectiv");
+ glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv");
+ glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv");
+ glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer");
+ glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery");
+ glad_glMapBuffer = (PFNGLMAPBUFFERPROC) load(userptr, "glMapBuffer");
+ glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer");
+}
+static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_0) return;
+ glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader");
+ glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation");
+ glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate");
+ glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader");
+ glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram");
+ glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader");
+ glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram");
+ glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader");
+ glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader");
+ glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray");
+ glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers");
+ glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray");
+ glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib");
+ glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform");
+ glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders");
+ glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation");
+ glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog");
+ glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv");
+ glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog");
+ glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource");
+ glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv");
+ glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation");
+ glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv");
+ glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv");
+ glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv");
+ glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load(userptr, "glGetVertexAttribdv");
+ glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv");
+ glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv");
+ glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram");
+ glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader");
+ glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram");
+ glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource");
+ glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate");
+ glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate");
+ glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate");
+ glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f");
+ glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv");
+ glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i");
+ glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv");
+ glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f");
+ glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv");
+ glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i");
+ glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv");
+ glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f");
+ glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv");
+ glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i");
+ glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv");
+ glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f");
+ glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv");
+ glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i");
+ glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv");
+ glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv");
+ glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv");
+ glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv");
+ glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram");
+ glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram");
+ glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load(userptr, "glVertexAttrib1d");
+ glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load(userptr, "glVertexAttrib1dv");
+ glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f");
+ glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv");
+ glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load(userptr, "glVertexAttrib1s");
+ glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load(userptr, "glVertexAttrib1sv");
+ glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load(userptr, "glVertexAttrib2d");
+ glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load(userptr, "glVertexAttrib2dv");
+ glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f");
+ glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv");
+ glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load(userptr, "glVertexAttrib2s");
+ glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load(userptr, "glVertexAttrib2sv");
+ glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load(userptr, "glVertexAttrib3d");
+ glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load(userptr, "glVertexAttrib3dv");
+ glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f");
+ glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv");
+ glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load(userptr, "glVertexAttrib3s");
+ glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load(userptr, "glVertexAttrib3sv");
+ glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load(userptr, "glVertexAttrib4Nbv");
+ glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load(userptr, "glVertexAttrib4Niv");
+ glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load(userptr, "glVertexAttrib4Nsv");
+ glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load(userptr, "glVertexAttrib4Nub");
+ glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load(userptr, "glVertexAttrib4Nubv");
+ glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load(userptr, "glVertexAttrib4Nuiv");
+ glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load(userptr, "glVertexAttrib4Nusv");
+ glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load(userptr, "glVertexAttrib4bv");
+ glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load(userptr, "glVertexAttrib4d");
+ glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load(userptr, "glVertexAttrib4dv");
+ glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f");
+ glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv");
+ glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load(userptr, "glVertexAttrib4iv");
+ glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load(userptr, "glVertexAttrib4s");
+ glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load(userptr, "glVertexAttrib4sv");
+ glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load(userptr, "glVertexAttrib4ubv");
+ glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load(userptr, "glVertexAttrib4uiv");
+ glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load(userptr, "glVertexAttrib4usv");
+ glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer");
+}
+static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_2_1) return;
+ glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv");
+ glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv");
+ glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv");
+ glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv");
+ glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv");
+ glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv");
+}
+static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_0) return;
+ glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load(userptr, "glBeginConditionalRender");
+ glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback");
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load(userptr, "glBindFragDataLocation");
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer");
+ glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus");
+ glad_glClampColor = (PFNGLCLAMPCOLORPROC) load(userptr, "glClampColor");
+ glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi");
+ glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv");
+ glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv");
+ glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv");
+ glad_glColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers");
+ glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays");
+ glad_glDisablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei");
+ glad_glEnablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei");
+ glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load(userptr, "glEndConditionalRender");
+ glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback");
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers");
+ glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap");
+ glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v");
+ glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv");
+ glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi");
+ glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv");
+ glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv");
+ glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying");
+ glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv");
+ glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv");
+ glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv");
+ glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer");
+ glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray");
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample");
+ glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv");
+ glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv");
+ glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings");
+ glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui");
+ glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv");
+ glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui");
+ glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv");
+ glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui");
+ glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv");
+ glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui");
+ glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv");
+ glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load(userptr, "glVertexAttribI1i");
+ glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load(userptr, "glVertexAttribI1iv");
+ glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load(userptr, "glVertexAttribI1ui");
+ glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load(userptr, "glVertexAttribI1uiv");
+ glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load(userptr, "glVertexAttribI2i");
+ glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load(userptr, "glVertexAttribI2iv");
+ glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load(userptr, "glVertexAttribI2ui");
+ glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load(userptr, "glVertexAttribI2uiv");
+ glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load(userptr, "glVertexAttribI3i");
+ glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load(userptr, "glVertexAttribI3iv");
+ glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load(userptr, "glVertexAttribI3ui");
+ glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load(userptr, "glVertexAttribI3uiv");
+ glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load(userptr, "glVertexAttribI4bv");
+ glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i");
+ glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv");
+ glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load(userptr, "glVertexAttribI4sv");
+ glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load(userptr, "glVertexAttribI4ubv");
+ glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui");
+ glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv");
+ glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load(userptr, "glVertexAttribI4usv");
+ glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer");
+}
+static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_1) return;
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange");
+ glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData");
+ glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced");
+ glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced");
+ glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName");
+ glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv");
+ glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName");
+ glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v");
+ glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex");
+ glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices");
+ glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load(userptr, "glPrimitiveRestartIndex");
+ glad_glTexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer");
+ glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding");
+}
+static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_2) return;
+ glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync");
+ glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync");
+ glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex");
+ glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex");
+ glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex");
+ glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync");
+ glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture");
+ glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v");
+ glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v");
+ glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v");
+ glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv");
+ glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv");
+ glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync");
+ glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex");
+ glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex");
+ glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski");
+ glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample");
+ glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample");
+ glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync");
+}
+static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) {
+ if(!GLAD_GL_VERSION_3_3) return;
+ glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load(userptr, "glBindFragDataLocationIndexed");
+ glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler");
+ glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers");
+ glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers");
+ glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load(userptr, "glGetFragDataIndex");
+ glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
+ glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
+ glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load(userptr, "glGetSamplerParameterIiv");
+ glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load(userptr, "glGetSamplerParameterIuiv");
+ glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv");
+ glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv");
+ glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler");
+ glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
+ glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load(userptr, "glSamplerParameterIiv");
+ glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load(userptr, "glSamplerParameterIuiv");
+ glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf");
+ glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv");
+ glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri");
+ glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv");
+ glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor");
+ glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load(userptr, "glVertexAttribP1ui");
+ glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load(userptr, "glVertexAttribP1uiv");
+ glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load(userptr, "glVertexAttribP2ui");
+ glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load(userptr, "glVertexAttribP2uiv");
+ glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load(userptr, "glVertexAttribP3ui");
+ glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load(userptr, "glVertexAttribP3uiv");
+ glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load(userptr, "glVertexAttribP4ui");
+ glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load(userptr, "glVertexAttribP4uiv");
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+ (void) version;
+ (void) out_num_exts_i;
+ (void) out_exts_i;
+#endif
+ if (glad_glGetString == NULL) {
+ return 0;
+ }
+ *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+ } else {
+ unsigned int index = 0;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) {
+ return 0;
+ }
+ glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+ if (num_exts_i > 0) {
+ exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
+ }
+ if (exts_i == NULL) {
+ return 0;
+ }
+ for(index = 0; index < num_exts_i; index++) {
+ const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index);
+ size_t len = strlen(gl_str_tmp) + 1;
+
+ char *local_str = (char*) malloc(len * sizeof(char));
+ if(local_str != NULL) {
+ memcpy(local_str, gl_str_tmp, len * sizeof(char));
+ }
+
+ exts_i[index] = local_str;
+ }
+
+ *out_num_exts_i = num_exts_i;
+ *out_exts_i = exts_i;
+ }
+#endif
+ return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+ if (exts_i != NULL) {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ free((void *) (exts_i[index]));
+ }
+ free((void *)exts_i);
+ exts_i = NULL;
+ }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+ if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+ const char *extensions;
+ const char *loc;
+ const char *terminator;
+ extensions = exts;
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL) {
+ return 0;
+ }
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+ } else {
+ unsigned int index;
+ for(index = 0; index < num_exts_i; index++) {
+ const char *e = exts_i[index];
+ if(strcmp(e, ext) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) {
+ return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gl( int version) {
+ const char *exts = NULL;
+ unsigned int num_exts_i = 0;
+ char **exts_i = NULL;
+ if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+ (void) glad_gl_has_extension;
+
+ glad_gl_free_extensions(exts_i, num_exts_i);
+
+ return 1;
+}
+
+static int glad_gl_find_core_gl(void) {
+ int i, major, minor;
+ const char* version;
+ const char* prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ NULL
+ };
+ version = (const char*) glad_glGetString(GL_VERSION);
+ if (!version) return 0;
+ for (i = 0; prefixes[i]; i++) {
+ const size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+
+ GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+ GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
+ GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+ GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
+ GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
+ GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
+ GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
+ GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
+
+ return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
+ int version;
+
+ glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString");
+ if(glad_glGetString == NULL) return 0;
+ if(glad_glGetString(GL_VERSION) == NULL) return 0;
+ version = glad_gl_find_core_gl();
+
+ glad_gl_load_GL_VERSION_1_0(load, userptr);
+ glad_gl_load_GL_VERSION_1_1(load, userptr);
+ glad_gl_load_GL_VERSION_1_2(load, userptr);
+ glad_gl_load_GL_VERSION_1_3(load, userptr);
+ glad_gl_load_GL_VERSION_1_4(load, userptr);
+ glad_gl_load_GL_VERSION_1_5(load, userptr);
+ glad_gl_load_GL_VERSION_2_0(load, userptr);
+ glad_gl_load_GL_VERSION_2_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_0(load, userptr);
+ glad_gl_load_GL_VERSION_3_1(load, userptr);
+ glad_gl_load_GL_VERSION_3_2(load, userptr);
+ glad_gl_load_GL_VERSION_3_3(load, userptr);
+
+ if (!glad_gl_find_extensions_gl(version)) return 0;
+
+
+
+ return version;
+}
+
+
+int gladLoadGL( GLADloadfunc load) {
+ return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt b/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt
new file mode 100644
index 0000000..f95070e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt
@@ -0,0 +1,92 @@
+find_package(Threads REQUIRED)
+
+# Establish target libraries and include directories
+if (APPLE)
+
+ list(APPEND glfw_LIBRARIES
+ "-framework Cocoa"
+ "-framework IOKit"
+ "-framework CoreFoundation"
+ "-framework CoreVideo")
+
+elseif (UNIX)
+ find_library(RT_LIBRARY rt)
+ if (RT_LIBRARY)
+ list(APPEND glfw_LIBRARIES "${RT_LIBRARY}")
+ endif()
+
+ find_library(MATH_LIBRARY m)
+ if (MATH_LIBRARY)
+ list(APPEND glfw_LIBRARIES "${MATH_LIBRARY}")
+ endif()
+
+ if (CMAKE_DL_LIBS)
+ list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}")
+ endif()
+
+ find_package(X11 REQUIRED)
+
+ # Set up library and include paths
+ list(APPEND glfw_INCLUDE_DIRS "${X11_X11_INCLUDE_PATH}")
+ list(APPEND glfw_LIBRARIES "${X11_X11_LIB}" "${CMAKE_THREAD_LIBS_INIT}")
+
+ # Check for XRandR (modern resolution switching and gamma control)
+ if (NOT X11_Xrandr_FOUND)
+ message(FATAL_ERROR "The RandR headers were not found")
+ endif()
+
+ # Check for Xinerama (legacy multi-monitor support)
+ if (NOT X11_Xinerama_FOUND)
+ message(FATAL_ERROR "The Xinerama headers were not found")
+ endif()
+
+ # Check for Xkb (X keyboard extension)
+ if (NOT X11_Xkb_FOUND)
+ message(FATAL_ERROR "The X keyboard extension headers were not found")
+ endif()
+
+ # Check for Xcursor (cursor creation from RGBA images)
+ if (NOT X11_Xcursor_FOUND)
+ message(FATAL_ERROR "The Xcursor headers were not found")
+ endif()
+
+ list(APPEND glfw_INCLUDE_DIRS "${X11_Xrandr_INCLUDE_PATH}"
+ "${X11_Xinerama_INCLUDE_PATH}"
+ "${X11_Xkb_INCLUDE_PATH}"
+ "${X11_Xcursor_INCLUDE_PATH}")
+endif()
+
+set(common_HEADERS src/internal.h src/mappings.h
+ include/GLFW/glfw3.h
+ include/GLFW/glfw3native.h)
+set(common_SOURCES src/context.c src/init.c src/input.c src/monitor.c src/vulkan.c src/window.c)
+
+if (APPLE)
+ set(glfw_HEADERS ${common_HEADERS} src/cocoa_platform.h src/cocoa_joystick.h
+ src/posix_thread.h src/nsgl_context.h src/egl_context.h src/osmesa_context.h)
+ set(glfw_SOURCES ${common_SOURCES} src/cocoa_init.m src/cocoa_joystick.m
+ src/cocoa_monitor.m src/cocoa_window.m src/cocoa_time.c src/posix_thread.c
+ src/nsgl_context.m src/egl_context.c src/osmesa_context.c)
+ set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
+elseif (WIN32)
+ set(glfw_HEADERS ${common_HEADERS} src/win32_platform.h src/win32_joystick.h
+ src/wgl_context.h src/egl_context.h src/osmesa_context.h)
+ set(glfw_SOURCES ${common_SOURCES} src/win32_init.c src/win32_joystick.c
+ src/win32_monitor.c src/win32_time.c src/win32_thread.c src/win32_window.c
+ src/wgl_context.c src/egl_context.c src/osmesa_context.c)
+elseif (UNIX)
+ set(glfw_HEADERS ${common_HEADERS} src/x11_platform.h src/xkb_unicode.h src/posix_time.h
+ src/posix_thread.h src/glx_context.h src/egl_context.h src/osmesa_context.h)
+ set(glfw_SOURCES ${common_SOURCES} src/x11_init.c src/x11_monitor.c src/x11_window.c
+ src/xkb_unicode.c src/posix_time.c src/posix_thread.c src/glx_context.c
+ src/egl_context.c src/osmesa_context.c)
+ set(glfw_HEADERS ${glfw_HEADERS} src/linux_joystick.h)
+ set(glfw_SOURCES ${glfw_SOURCES} src/linux_joystick.c)
+endif()
+
+add_library(glfw STATIC ${glfw_SOURCES} ${glfw_HEADERS})
+target_include_directories(glfw PUBLIC include)
+target_include_directories(glfw PRIVATE ${glfw_INCLUDE_DIRS})
+target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${glfw_SOURCES} ${glfw_HEADERS})
diff --git a/Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3.h b/Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3.h
new file mode 100644
index 0000000..099cd8e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3.h
@@ -0,0 +1,5556 @@
+/*************************************************************************
+ * GLFW 3.3 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would
+ * be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ *************************************************************************/
+
+#ifndef _glfw3_h_
+#define _glfw3_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Doxygen documentation
+ *************************************************************************/
+
+/*! @file glfw3.h
+ * @brief The header of the GLFW 3 API.
+ *
+ * This is the header file of the GLFW 3 API. It defines all its types and
+ * declares all its functions.
+ *
+ * For more information about how to use this file, see @ref build_include.
+ */
+/*! @defgroup context Context reference
+ * @brief Functions and types related to OpenGL and OpenGL ES contexts.
+ *
+ * This is the reference documentation for OpenGL and OpenGL ES context related
+ * functions. For more task-oriented information, see the @ref context_guide.
+ */
+/*! @defgroup vulkan Vulkan reference
+ * @brief Functions and types related to Vulkan.
+ *
+ * This is the reference documentation for Vulkan related functions and types.
+ * For more task-oriented information, see the @ref vulkan_guide.
+ */
+/*! @defgroup init Initialization, version and error reference
+ * @brief Functions and types related to initialization and error handling.
+ *
+ * This is the reference documentation for initialization and termination of
+ * the library, version management and error handling. For more task-oriented
+ * information, see the @ref intro_guide.
+ */
+/*! @defgroup input Input reference
+ * @brief Functions and types related to input handling.
+ *
+ * This is the reference documentation for input related functions and types.
+ * For more task-oriented information, see the @ref input_guide.
+ */
+/*! @defgroup monitor Monitor reference
+ * @brief Functions and types related to monitors.
+ *
+ * This is the reference documentation for monitor related functions and types.
+ * For more task-oriented information, see the @ref monitor_guide.
+ */
+/*! @defgroup window Window reference
+ * @brief Functions and types related to windows.
+ *
+ * This is the reference documentation for window related functions and types,
+ * including creation, deletion and event polling. For more task-oriented
+ * information, see the @ref window_guide.
+ */
+
+
+/*************************************************************************
+ * Compiler- and platform-specific preprocessor work
+ *************************************************************************/
+
+/* If we are we on Windows, we want a single define for it.
+ */
+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
+ #define _WIN32
+#endif /* _WIN32 */
+
+/* It is customary to use APIENTRY for OpenGL function pointer declarations on
+ * all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
+ */
+#ifndef APIENTRY
+ #ifdef _WIN32
+ #define APIENTRY __stdcall
+ #else
+ #define APIENTRY
+ #endif
+ #define GLFW_APIENTRY_DEFINED
+#endif /* APIENTRY */
+
+/* Some Windows OpenGL headers need this.
+ */
+#if !defined(WINGDIAPI) && defined(_WIN32)
+ #define WINGDIAPI __declspec(dllimport)
+ #define GLFW_WINGDIAPI_DEFINED
+#endif /* WINGDIAPI */
+
+/* Some Windows GLU headers need this.
+ */
+#if !defined(CALLBACK) && defined(_WIN32)
+ #define CALLBACK __stdcall
+ #define GLFW_CALLBACK_DEFINED
+#endif /* CALLBACK */
+
+/* Include because most Windows GLU headers need wchar_t and
+ * the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h.
+ * Include it unconditionally to avoid surprising side-effects.
+ */
+#include <stddef.h>
+
+/* Include because it is needed by Vulkan and related functions.
+ * Include it unconditionally to avoid surprising side-effects.
+ */
+#include <stdint.h>
+
+/* Include the chosen OpenGL or OpenGL ES headers.
+ */
+#if defined(GLFW_INCLUDE_ES1)
+
+ #include <GLES/gl.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES/glext.h>
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES2)
+
+ #include <GLES2/gl2.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES3)
+
+ #include <GLES3/gl3.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES31)
+
+ #include <GLES3/gl31.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+
+#elif defined(GLFW_INCLUDE_ES32)
+
+ #include <GLES3/gl32.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+
+#elif defined(GLFW_INCLUDE_GLCOREARB)
+
+ #if defined(__APPLE__)
+
+ #include <OpenGL/gl3.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <OpenGL/gl3ext.h>
+ #endif /*GLFW_INCLUDE_GLEXT*/
+
+ #else /*__APPLE__*/
+
+ #include <GL/glcorearb.h>
+
+ #endif /*__APPLE__*/
+
+#elif !defined(GLFW_INCLUDE_NONE)
+
+ #if defined(__APPLE__)
+
+ #if !defined(GLFW_INCLUDE_GLEXT)
+ #define GL_GLEXT_LEGACY
+ #endif
+ #include <OpenGL/gl.h>
+ #if defined(GLFW_INCLUDE_GLU)
+ #include <OpenGL/glu.h>
+ #endif
+
+ #else /*__APPLE__*/
+
+ #include <GL/gl.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GL/glext.h>
+ #endif
+ #if defined(GLFW_INCLUDE_GLU)
+ #include <GL/glu.h>
+ #endif
+
+ #endif /*__APPLE__*/
+
+#endif /* OpenGL and OpenGL ES headers */
+
+#if defined(GLFW_INCLUDE_VULKAN)
+ #include <vulkan/vulkan.h>
+#endif /* Vulkan header */
+
+#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
+ /* GLFW_DLL must be defined by applications that are linking against the DLL
+ * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW
+ * configuration header when compiling the DLL version of the library.
+ */
+ #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined"
+#endif
+
+/* GLFWAPI is used to declare public API functions for export
+ * from the DLL / shared library / dynamic library.
+ */
+#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)
+ /* We are building GLFW as a Win32 DLL */
+ #define GLFWAPI __declspec(dllexport)
+#elif defined(_WIN32) && defined(GLFW_DLL)
+ /* We are calling GLFW as a Win32 DLL */
+ #define GLFWAPI __declspec(dllimport)
+#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
+ /* We are building GLFW as a shared / dynamic library */
+ #define GLFWAPI __attribute__((visibility("default")))
+#else
+ /* We are building or calling GLFW as a static library */
+ #define GLFWAPI
+#endif
+
+
+/*************************************************************************
+ * GLFW API tokens
+ *************************************************************************/
+
+/*! @name GLFW version macros
+ * @{ */
+/*! @brief The major version number of the GLFW library.
+ *
+ * This is incremented when the API is changed in non-compatible ways.
+ * @ingroup init
+ */
+#define GLFW_VERSION_MAJOR 3
+/*! @brief The minor version number of the GLFW library.
+ *
+ * This is incremented when features are added to the API but it remains
+ * backward-compatible.
+ * @ingroup init
+ */
+#define GLFW_VERSION_MINOR 3
+/*! @brief The revision number of the GLFW library.
+ *
+ * This is incremented when a bug fix release is made that does not contain any
+ * API changes.
+ * @ingroup init
+ */
+#define GLFW_VERSION_REVISION 0
+/*! @} */
+
+/*! @brief One.
+ *
+ * This is only semantic sugar for the number 1. You can instead use `1` or
+ * `true` or `_True` or `GL_TRUE` or anything else that is equal to one.
+ *
+ * @ingroup init
+ */
+#define GLFW_TRUE 1
+/*! @brief Zero.
+ *
+ * This is only semantic sugar for the number 0. You can instead use `0` or
+ * `false` or `_False` or `GL_FALSE` or anything else that is equal to zero.
+ *
+ * @ingroup init
+ */
+#define GLFW_FALSE 0
+
+/*! @name Key and button actions
+ * @{ */
+/*! @brief The key or mouse button was released.
+ *
+ * The key or mouse button was released.
+ *
+ * @ingroup input
+ */
+#define GLFW_RELEASE 0
+/*! @brief The key or mouse button was pressed.
+ *
+ * The key or mouse button was pressed.
+ *
+ * @ingroup input
+ */
+#define GLFW_PRESS 1
+/*! @brief The key was held down until it repeated.
+ *
+ * The key was held down until it repeated.
+ *
+ * @ingroup input
+ */
+#define GLFW_REPEAT 2
+/*! @} */
+
+/*! @defgroup hat_state Joystick hat states
+ * @brief Joystick hat states.
+ *
+ * See [joystick hat input](@ref joystick_hat) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_HAT_CENTERED 0
+#define GLFW_HAT_UP 1
+#define GLFW_HAT_RIGHT 2
+#define GLFW_HAT_DOWN 4
+#define GLFW_HAT_LEFT 8
+#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP)
+#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
+#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP)
+#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN)
+/*! @} */
+
+/*! @defgroup keys Keyboard keys
+ * @brief Keyboard key IDs.
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
+ * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60),
+ * but re-arranged to map to 7-bit ASCII for printable keys (function keys are
+ * put in the 256+ range).
+ *
+ * The naming of the key codes follow these rules:
+ * - The US keyboard layout is used
+ * - Names of printable alpha-numeric characters are used (e.g. "A", "R",
+ * "3", etc.)
+ * - For non-alphanumeric characters, Unicode:ish names are used (e.g.
+ * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not
+ * correspond to the Unicode standard (usually for brevity)
+ * - Keys that lack a clear US mapping are named "WORLD_x"
+ * - For non-printable keys, custom names are used (e.g. "F4",
+ * "BACKSPACE", etc.)
+ *
+ * @ingroup input
+ * @{
+ */
+
+/* The unknown key */
+#define GLFW_KEY_UNKNOWN -1
+
+/* Printable keys */
+#define GLFW_KEY_SPACE 32
+#define GLFW_KEY_APOSTROPHE 39 /* ' */
+#define GLFW_KEY_COMMA 44 /* , */
+#define GLFW_KEY_MINUS 45 /* - */
+#define GLFW_KEY_PERIOD 46 /* . */
+#define GLFW_KEY_SLASH 47 /* / */
+#define GLFW_KEY_0 48
+#define GLFW_KEY_1 49
+#define GLFW_KEY_2 50
+#define GLFW_KEY_3 51
+#define GLFW_KEY_4 52
+#define GLFW_KEY_5 53
+#define GLFW_KEY_6 54
+#define GLFW_KEY_7 55
+#define GLFW_KEY_8 56
+#define GLFW_KEY_9 57
+#define GLFW_KEY_SEMICOLON 59 /* ; */
+#define GLFW_KEY_EQUAL 61 /* = */
+#define GLFW_KEY_A 65
+#define GLFW_KEY_B 66
+#define GLFW_KEY_C 67
+#define GLFW_KEY_D 68
+#define GLFW_KEY_E 69
+#define GLFW_KEY_F 70
+#define GLFW_KEY_G 71
+#define GLFW_KEY_H 72
+#define GLFW_KEY_I 73
+#define GLFW_KEY_J 74
+#define GLFW_KEY_K 75
+#define GLFW_KEY_L 76
+#define GLFW_KEY_M 77
+#define GLFW_KEY_N 78
+#define GLFW_KEY_O 79
+#define GLFW_KEY_P 80
+#define GLFW_KEY_Q 81
+#define GLFW_KEY_R 82
+#define GLFW_KEY_S 83
+#define GLFW_KEY_T 84
+#define GLFW_KEY_U 85
+#define GLFW_KEY_V 86
+#define GLFW_KEY_W 87
+#define GLFW_KEY_X 88
+#define GLFW_KEY_Y 89
+#define GLFW_KEY_Z 90
+#define GLFW_KEY_LEFT_BRACKET 91 /* [ */
+#define GLFW_KEY_BACKSLASH 92 /* \ */
+#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
+#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
+#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
+#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
+
+/* Function keys */
+#define GLFW_KEY_ESCAPE 256
+#define GLFW_KEY_ENTER 257
+#define GLFW_KEY_TAB 258
+#define GLFW_KEY_BACKSPACE 259
+#define GLFW_KEY_INSERT 260
+#define GLFW_KEY_DELETE 261
+#define GLFW_KEY_RIGHT 262
+#define GLFW_KEY_LEFT 263
+#define GLFW_KEY_DOWN 264
+#define GLFW_KEY_UP 265
+#define GLFW_KEY_PAGE_UP 266
+#define GLFW_KEY_PAGE_DOWN 267
+#define GLFW_KEY_HOME 268
+#define GLFW_KEY_END 269
+#define GLFW_KEY_CAPS_LOCK 280
+#define GLFW_KEY_SCROLL_LOCK 281
+#define GLFW_KEY_NUM_LOCK 282
+#define GLFW_KEY_PRINT_SCREEN 283
+#define GLFW_KEY_PAUSE 284
+#define GLFW_KEY_F1 290
+#define GLFW_KEY_F2 291
+#define GLFW_KEY_F3 292
+#define GLFW_KEY_F4 293
+#define GLFW_KEY_F5 294
+#define GLFW_KEY_F6 295
+#define GLFW_KEY_F7 296
+#define GLFW_KEY_F8 297
+#define GLFW_KEY_F9 298
+#define GLFW_KEY_F10 299
+#define GLFW_KEY_F11 300
+#define GLFW_KEY_F12 301
+#define GLFW_KEY_F13 302
+#define GLFW_KEY_F14 303
+#define GLFW_KEY_F15 304
+#define GLFW_KEY_F16 305
+#define GLFW_KEY_F17 306
+#define GLFW_KEY_F18 307
+#define GLFW_KEY_F19 308
+#define GLFW_KEY_F20 309
+#define GLFW_KEY_F21 310
+#define GLFW_KEY_F22 311
+#define GLFW_KEY_F23 312
+#define GLFW_KEY_F24 313
+#define GLFW_KEY_F25 314
+#define GLFW_KEY_KP_0 320
+#define GLFW_KEY_KP_1 321
+#define GLFW_KEY_KP_2 322
+#define GLFW_KEY_KP_3 323
+#define GLFW_KEY_KP_4 324
+#define GLFW_KEY_KP_5 325
+#define GLFW_KEY_KP_6 326
+#define GLFW_KEY_KP_7 327
+#define GLFW_KEY_KP_8 328
+#define GLFW_KEY_KP_9 329
+#define GLFW_KEY_KP_DECIMAL 330
+#define GLFW_KEY_KP_DIVIDE 331
+#define GLFW_KEY_KP_MULTIPLY 332
+#define GLFW_KEY_KP_SUBTRACT 333
+#define GLFW_KEY_KP_ADD 334
+#define GLFW_KEY_KP_ENTER 335
+#define GLFW_KEY_KP_EQUAL 336
+#define GLFW_KEY_LEFT_SHIFT 340
+#define GLFW_KEY_LEFT_CONTROL 341
+#define GLFW_KEY_LEFT_ALT 342
+#define GLFW_KEY_LEFT_SUPER 343
+#define GLFW_KEY_RIGHT_SHIFT 344
+#define GLFW_KEY_RIGHT_CONTROL 345
+#define GLFW_KEY_RIGHT_ALT 346
+#define GLFW_KEY_RIGHT_SUPER 347
+#define GLFW_KEY_MENU 348
+
+#define GLFW_KEY_LAST GLFW_KEY_MENU
+
+/*! @} */
+
+/*! @defgroup mods Modifier key flags
+ * @brief Modifier key flags.
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+
+/*! @brief If this bit is set one or more Shift keys were held down.
+ *
+ * If this bit is set one or more Shift keys were held down.
+ */
+#define GLFW_MOD_SHIFT 0x0001
+/*! @brief If this bit is set one or more Control keys were held down.
+ *
+ * If this bit is set one or more Control keys were held down.
+ */
+#define GLFW_MOD_CONTROL 0x0002
+/*! @brief If this bit is set one or more Alt keys were held down.
+ *
+ * If this bit is set one or more Alt keys were held down.
+ */
+#define GLFW_MOD_ALT 0x0004
+/*! @brief If this bit is set one or more Super keys were held down.
+ *
+ * If this bit is set one or more Super keys were held down.
+ */
+#define GLFW_MOD_SUPER 0x0008
+/*! @brief If this bit is set the Caps Lock key is enabled.
+ *
+ * If this bit is set the Caps Lock key is enabled and the @ref
+ * GLFW_LOCK_KEY_MODS input mode is set.
+ */
+#define GLFW_MOD_CAPS_LOCK 0x0010
+/*! @brief If this bit is set the Num Lock key is enabled.
+ *
+ * If this bit is set the Num Lock key is enabled and the @ref
+ * GLFW_LOCK_KEY_MODS input mode is set.
+ */
+#define GLFW_MOD_NUM_LOCK 0x0020
+
+/*! @} */
+
+/*! @defgroup buttons Mouse buttons
+ * @brief Mouse button IDs.
+ *
+ * See [mouse button input](@ref input_mouse_button) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_MOUSE_BUTTON_1 0
+#define GLFW_MOUSE_BUTTON_2 1
+#define GLFW_MOUSE_BUTTON_3 2
+#define GLFW_MOUSE_BUTTON_4 3
+#define GLFW_MOUSE_BUTTON_5 4
+#define GLFW_MOUSE_BUTTON_6 5
+#define GLFW_MOUSE_BUTTON_7 6
+#define GLFW_MOUSE_BUTTON_8 7
+#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
+#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
+#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
+#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
+/*! @} */
+
+/*! @defgroup joysticks Joysticks
+ * @brief Joystick IDs.
+ *
+ * See [joystick input](@ref joystick) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_JOYSTICK_1 0
+#define GLFW_JOYSTICK_2 1
+#define GLFW_JOYSTICK_3 2
+#define GLFW_JOYSTICK_4 3
+#define GLFW_JOYSTICK_5 4
+#define GLFW_JOYSTICK_6 5
+#define GLFW_JOYSTICK_7 6
+#define GLFW_JOYSTICK_8 7
+#define GLFW_JOYSTICK_9 8
+#define GLFW_JOYSTICK_10 9
+#define GLFW_JOYSTICK_11 10
+#define GLFW_JOYSTICK_12 11
+#define GLFW_JOYSTICK_13 12
+#define GLFW_JOYSTICK_14 13
+#define GLFW_JOYSTICK_15 14
+#define GLFW_JOYSTICK_16 15
+#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16
+/*! @} */
+
+/*! @defgroup gamepad_buttons Gamepad buttons
+ * @brief Gamepad buttons.
+ *
+ * See @ref gamepad for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_GAMEPAD_BUTTON_A 0
+#define GLFW_GAMEPAD_BUTTON_B 1
+#define GLFW_GAMEPAD_BUTTON_X 2
+#define GLFW_GAMEPAD_BUTTON_Y 3
+#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4
+#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5
+#define GLFW_GAMEPAD_BUTTON_BACK 6
+#define GLFW_GAMEPAD_BUTTON_START 7
+#define GLFW_GAMEPAD_BUTTON_GUIDE 8
+#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9
+#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10
+#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11
+#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12
+#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13
+#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14
+#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT
+
+#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A
+#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B
+#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X
+#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y
+/*! @} */
+
+/*! @defgroup gamepad_axes Gamepad axes
+ * @brief Gamepad axes.
+ *
+ * See @ref gamepad for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_GAMEPAD_AXIS_LEFT_X 0
+#define GLFW_GAMEPAD_AXIS_LEFT_Y 1
+#define GLFW_GAMEPAD_AXIS_RIGHT_X 2
+#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3
+#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4
+#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5
+#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
+/*! @} */
+
+/*! @defgroup errors Error codes
+ * @brief Error codes.
+ *
+ * See [error handling](@ref error_handling) for how these are used.
+ *
+ * @ingroup init
+ * @{ */
+/*! @brief No error has occurred.
+ *
+ * No error has occurred.
+ *
+ * @analysis Yay.
+ */
+#define GLFW_NO_ERROR 0
+/*! @brief GLFW has not been initialized.
+ *
+ * This occurs if a GLFW function was called that must not be called unless the
+ * library is [initialized](@ref intro_init).
+ *
+ * @analysis Application programmer error. Initialize GLFW before calling any
+ * function that requires initialization.
+ */
+#define GLFW_NOT_INITIALIZED 0x00010001
+/*! @brief No context is current for this thread.
+ *
+ * This occurs if a GLFW function was called that needs and operates on the
+ * current OpenGL or OpenGL ES context but no context is current on the calling
+ * thread. One such function is @ref glfwSwapInterval.
+ *
+ * @analysis Application programmer error. Ensure a context is current before
+ * calling functions that require a current context.
+ */
+#define GLFW_NO_CURRENT_CONTEXT 0x00010002
+/*! @brief One of the arguments to the function was an invalid enum value.
+ *
+ * One of the arguments to the function was an invalid enum value, for example
+ * requesting @ref GLFW_RED_BITS with @ref glfwGetWindowAttrib.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_INVALID_ENUM 0x00010003
+/*! @brief One of the arguments to the function was an invalid value.
+ *
+ * One of the arguments to the function was an invalid value, for example
+ * requesting a non-existent OpenGL or OpenGL ES version like 2.7.
+ *
+ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead
+ * result in a @ref GLFW_VERSION_UNAVAILABLE error.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_INVALID_VALUE 0x00010004
+/*! @brief A memory allocation failed.
+ *
+ * A memory allocation failed.
+ *
+ * @analysis A bug in GLFW or the underlying operating system. Report the bug
+ * to our [issue tracker](https://github.com/glfw/glfw/issues).
+ */
+#define GLFW_OUT_OF_MEMORY 0x00010005
+/*! @brief GLFW could not find support for the requested API on the system.
+ *
+ * GLFW could not find support for the requested API on the system.
+ *
+ * @analysis The installed graphics driver does not support the requested
+ * API, or does not support it via the chosen context creation backend.
+ * Below are a few examples.
+ *
+ * @par
+ * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
+ * supports OpenGL ES via EGL, while Nvidia and Intel only support it via
+ * a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa
+ * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
+ * driver. Older graphics drivers do not support Vulkan.
+ */
+#define GLFW_API_UNAVAILABLE 0x00010006
+/*! @brief The requested OpenGL or OpenGL ES version is not available.
+ *
+ * The requested OpenGL or OpenGL ES version (including any requested context
+ * or framebuffer hints) is not available on this machine.
+ *
+ * @analysis The machine does not support your requirements. If your
+ * application is sufficiently flexible, downgrade your requirements and try
+ * again. Otherwise, inform the user that their machine does not match your
+ * requirements.
+ *
+ * @par
+ * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0
+ * comes out before the 4.x series gets that far, also fail with this error and
+ * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions
+ * will exist.
+ */
+#define GLFW_VERSION_UNAVAILABLE 0x00010007
+/*! @brief A platform-specific error occurred that does not match any of the
+ * more specific categories.
+ *
+ * A platform-specific error occurred that does not match any of the more
+ * specific categories.
+ *
+ * @analysis A bug or configuration error in GLFW, the underlying operating
+ * system or its drivers, or a lack of required resources. Report the issue to
+ * our [issue tracker](https://github.com/glfw/glfw/issues).
+ */
+#define GLFW_PLATFORM_ERROR 0x00010008
+/*! @brief The requested format is not supported or available.
+ *
+ * If emitted during window creation, the requested pixel format is not
+ * supported.
+ *
+ * If emitted when querying the clipboard, the contents of the clipboard could
+ * not be converted to the requested format.
+ *
+ * @analysis If emitted during window creation, one or more
+ * [hard constraints](@ref window_hints_hard) did not match any of the
+ * available pixel formats. If your application is sufficiently flexible,
+ * downgrade your requirements and try again. Otherwise, inform the user that
+ * their machine does not match your requirements.
+ *
+ * @par
+ * If emitted when querying the clipboard, ignore the error or report it to
+ * the user, as appropriate.
+ */
+#define GLFW_FORMAT_UNAVAILABLE 0x00010009
+/*! @brief The specified window does not have an OpenGL or OpenGL ES context.
+ *
+ * A window that does not have an OpenGL or OpenGL ES context was passed to
+ * a function that requires it to have one.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
+/*! @} */
+
+/*! @addtogroup window
+ * @{ */
+/*! @brief Input focus window hint and attribute
+ *
+ * Input focus [window hint](@ref GLFW_FOCUSED_hint) or
+ * [window attribute](@ref GLFW_FOCUSED_attrib).
+ */
+#define GLFW_FOCUSED 0x00020001
+/*! @brief Window iconification window attribute
+ *
+ * Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib).
+ */
+#define GLFW_ICONIFIED 0x00020002
+/*! @brief Window resize-ability window hint and attribute
+ *
+ * Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and
+ * [window attribute](@ref GLFW_RESIZABLE_attrib).
+ */
+#define GLFW_RESIZABLE 0x00020003
+/*! @brief Window visibility window hint and attribute
+ *
+ * Window visibility [window hint](@ref GLFW_VISIBLE_hint) and
+ * [window attribute](@ref GLFW_VISIBLE_attrib).
+ */
+#define GLFW_VISIBLE 0x00020004
+/*! @brief Window decoration window hint and attribute
+ *
+ * Window decoration [window hint](@ref GLFW_DECORATED_hint) and
+ * [window attribute](@ref GLFW_DECORATED_attrib).
+ */
+#define GLFW_DECORATED 0x00020005
+/*! @brief Window auto-iconification window hint and attribute
+ *
+ * Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and
+ * [window attribute](@ref GLFW_AUTO_ICONIFY_attrib).
+ */
+#define GLFW_AUTO_ICONIFY 0x00020006
+/*! @brief Window decoration window hint and attribute
+ *
+ * Window decoration [window hint](@ref GLFW_FLOATING_hint) and
+ * [window attribute](@ref GLFW_FLOATING_attrib).
+ */
+#define GLFW_FLOATING 0x00020007
+/*! @brief Window maximization window hint and attribute
+ *
+ * Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and
+ * [window attribute](@ref GLFW_MAXIMIZED_attrib).
+ */
+#define GLFW_MAXIMIZED 0x00020008
+/*! @brief Cursor centering window hint
+ *
+ * Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
+ */
+#define GLFW_CENTER_CURSOR 0x00020009
+/*! @brief Window framebuffer transparency hint and attribute
+ *
+ * Window framebuffer transparency
+ * [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and
+ * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
+ */
+#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
+/*! @brief Mouse cursor hover window attribute.
+ *
+ * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
+ */
+#define GLFW_HOVERED 0x0002000B
+/*! @brief Input focus on calling show window hint and attribute
+ *
+ * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or
+ * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
+ */
+#define GLFW_FOCUS_ON_SHOW 0x0002000C
+
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
+ */
+#define GLFW_RED_BITS 0x00021001
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS).
+ */
+#define GLFW_GREEN_BITS 0x00021002
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS).
+ */
+#define GLFW_BLUE_BITS 0x00021003
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS).
+ */
+#define GLFW_ALPHA_BITS 0x00021004
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS).
+ */
+#define GLFW_DEPTH_BITS 0x00021005
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS).
+ */
+#define GLFW_STENCIL_BITS 0x00021006
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS).
+ */
+#define GLFW_ACCUM_RED_BITS 0x00021007
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS).
+ */
+#define GLFW_ACCUM_GREEN_BITS 0x00021008
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS).
+ */
+#define GLFW_ACCUM_BLUE_BITS 0x00021009
+/*! @brief Framebuffer bit depth hint.
+ *
+ * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS).
+ */
+#define GLFW_ACCUM_ALPHA_BITS 0x0002100A
+/*! @brief Framebuffer auxiliary buffer hint.
+ *
+ * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS).
+ */
+#define GLFW_AUX_BUFFERS 0x0002100B
+/*! @brief OpenGL stereoscopic rendering hint.
+ *
+ * OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO).
+ */
+#define GLFW_STEREO 0x0002100C
+/*! @brief Framebuffer MSAA samples hint.
+ *
+ * Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES).
+ */
+#define GLFW_SAMPLES 0x0002100D
+/*! @brief Framebuffer sRGB hint.
+ *
+ * Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE).
+ */
+#define GLFW_SRGB_CAPABLE 0x0002100E
+/*! @brief Monitor refresh rate hint.
+ *
+ * Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE).
+ */
+#define GLFW_REFRESH_RATE 0x0002100F
+/*! @brief Framebuffer double buffering hint.
+ *
+ * Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER).
+ */
+#define GLFW_DOUBLEBUFFER 0x00021010
+
+/*! @brief Context client API hint and attribute.
+ *
+ * Context client API [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CLIENT_API 0x00022001
+/*! @brief Context client API major version hint and attribute.
+ *
+ * Context client API major version [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002
+/*! @brief Context client API minor version hint and attribute.
+ *
+ * Context client API minor version [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_VERSION_MINOR 0x00022003
+/*! @brief Context client API revision number hint and attribute.
+ *
+ * Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_REVISION 0x00022004
+/*! @brief Context robustness hint and attribute.
+ *
+ * Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_ROBUSTNESS 0x00022005
+/*! @brief OpenGL forward-compatibility hint and attribute.
+ *
+ * OpenGL forward-compatibility [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
+/*! @brief OpenGL debug context hint and attribute.
+ *
+ * OpenGL debug context [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
+/*! @brief OpenGL profile hint and attribute.
+ *
+ * OpenGL profile [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_OPENGL_PROFILE 0x00022008
+/*! @brief Context flush-on-release hint and attribute.
+ *
+ * Context flush-on-release [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
+/*! @brief Context error suppression hint and attribute.
+ *
+ * Context error suppression [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_NO_ERROR 0x0002200A
+/*! @brief Context creation API hint and attribute.
+ *
+ * Context creation API [hint](@ref GLFW_CLIENT_API_hint) and
+ * [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CONTEXT_CREATION_API 0x0002200B
+/*! @brief Window content area scaling window
+ * [window hint](@ref GLFW_SCALE_TO_MONITOR).
+ */
+#define GLFW_SCALE_TO_MONITOR 0x0002200C
+
+#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
+#define GLFW_COCOA_FRAME_NAME 0x00023002
+#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
+
+#define GLFW_X11_CLASS_NAME 0x00024001
+#define GLFW_X11_INSTANCE_NAME 0x00024002
+/*! @} */
+
+#define GLFW_NO_API 0
+#define GLFW_OPENGL_API 0x00030001
+#define GLFW_OPENGL_ES_API 0x00030002
+
+#define GLFW_NO_ROBUSTNESS 0
+#define GLFW_NO_RESET_NOTIFICATION 0x00031001
+#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002
+
+#define GLFW_OPENGL_ANY_PROFILE 0
+#define GLFW_OPENGL_CORE_PROFILE 0x00032001
+#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002
+
+#define GLFW_CURSOR 0x00033001
+#define GLFW_STICKY_KEYS 0x00033002
+#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
+#define GLFW_LOCK_KEY_MODS 0x00033004
+
+#define GLFW_CURSOR_NORMAL 0x00034001
+#define GLFW_CURSOR_HIDDEN 0x00034002
+#define GLFW_CURSOR_DISABLED 0x00034003
+
+#define GLFW_ANY_RELEASE_BEHAVIOR 0
+#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
+#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
+
+#define GLFW_NATIVE_CONTEXT_API 0x00036001
+#define GLFW_EGL_CONTEXT_API 0x00036002
+#define GLFW_OSMESA_CONTEXT_API 0x00036003
+
+/*! @defgroup shapes Standard cursor shapes
+ * @brief Standard system cursor shapes.
+ *
+ * See [standard cursor creation](@ref cursor_standard) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+
+/*! @brief The regular arrow cursor shape.
+ *
+ * The regular arrow cursor.
+ */
+#define GLFW_ARROW_CURSOR 0x00036001
+/*! @brief The text input I-beam cursor shape.
+ *
+ * The text input I-beam cursor shape.
+ */
+#define GLFW_IBEAM_CURSOR 0x00036002
+/*! @brief The crosshair shape.
+ *
+ * The crosshair shape.
+ */
+#define GLFW_CROSSHAIR_CURSOR 0x00036003
+/*! @brief The hand shape.
+ *
+ * The hand shape.
+ */
+#define GLFW_HAND_CURSOR 0x00036004
+/*! @brief The horizontal resize arrow shape.
+ *
+ * The horizontal resize arrow shape.
+ */
+#define GLFW_HRESIZE_CURSOR 0x00036005
+/*! @brief The vertical resize arrow shape.
+ *
+ * The vertical resize arrow shape.
+ */
+#define GLFW_VRESIZE_CURSOR 0x00036006
+/*! @} */
+
+#define GLFW_CONNECTED 0x00040001
+#define GLFW_DISCONNECTED 0x00040002
+
+/*! @addtogroup init
+ * @{ */
+/*! @brief Joystick hat buttons init hint.
+ *
+ * Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS)
+ */
+#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
+/*! @brief macOS specific init hint.
+ *
+ * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES)
+ */
+#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
+/*! @brief macOS specific init hint.
+ *
+ * macOS specific [init hint](@ref GLFW_COCOA_MENUBAR)
+ */
+#define GLFW_COCOA_MENUBAR 0x00051002
+/*! @} */
+
+#define GLFW_DONT_CARE -1
+
+
+/*************************************************************************
+ * GLFW API types
+ *************************************************************************/
+
+/*! @brief Client API function pointer type.
+ *
+ * Generic function pointer used for returning client API function pointers
+ * without forcing a cast from a regular pointer.
+ *
+ * @sa @ref context_glext
+ * @sa @ref glfwGetProcAddress
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+typedef void (*GLFWglproc)(void);
+
+/*! @brief Vulkan API function pointer type.
+ *
+ * Generic function pointer used for returning Vulkan API function pointers
+ * without forcing a cast from a regular pointer.
+ *
+ * @sa @ref vulkan_proc
+ * @sa @ref glfwGetInstanceProcAddress
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+typedef void (*GLFWvkproc)(void);
+
+/*! @brief Opaque monitor object.
+ *
+ * Opaque monitor object.
+ *
+ * @see @ref monitor_object
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWmonitor GLFWmonitor;
+
+/*! @brief Opaque window object.
+ *
+ * Opaque window object.
+ *
+ * @see @ref window_object
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef struct GLFWwindow GLFWwindow;
+
+/*! @brief Opaque cursor object.
+ *
+ * Opaque cursor object.
+ *
+ * @see @ref cursor_object
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef struct GLFWcursor GLFWcursor;
+
+/*! @brief The function signature for error callbacks.
+ *
+ * This is the function signature for error callback functions.
+ *
+ * @param[in] error An [error code](@ref errors).
+ * @param[in] description A UTF-8 encoded string describing the error.
+ *
+ * @sa @ref error_handling
+ * @sa @ref glfwSetErrorCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+typedef void (* GLFWerrorfun)(int,const char*);
+
+/*! @brief The function signature for window position callbacks.
+ *
+ * This is the function signature for window position callback functions.
+ *
+ * @param[in] window The window that was moved.
+ * @param[in] xpos The new x-coordinate, in screen coordinates, of the
+ * upper-left corner of the client area of the window.
+ * @param[in] ypos The new y-coordinate, in screen coordinates, of the
+ * upper-left corner of the client area of the window.
+ *
+ * @sa @ref window_pos
+ * @sa @ref glfwSetWindowPosCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
+
+/*! @brief The function signature for window resize callbacks.
+ *
+ * This is the function signature for window size callback functions.
+ *
+ * @param[in] window The window that was resized.
+ * @param[in] width The new width, in screen coordinates, of the window.
+ * @param[in] height The new height, in screen coordinates, of the window.
+ *
+ * @sa @ref window_size
+ * @sa @ref glfwSetWindowSizeCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
+
+/*! @brief The function signature for window close callbacks.
+ *
+ * This is the function signature for window close callback functions.
+ *
+ * @param[in] window The window that the user attempted to close.
+ *
+ * @sa @ref window_close
+ * @sa @ref glfwSetWindowCloseCallback
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowclosefun)(GLFWwindow*);
+
+/*! @brief The function signature for window content refresh callbacks.
+ *
+ * This is the function signature for window refresh callback functions.
+ *
+ * @param[in] window The window whose content needs to be refreshed.
+ *
+ * @sa @ref window_refresh
+ * @sa @ref glfwSetWindowRefreshCallback
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
+
+/*! @brief The function signature for window focus/defocus callbacks.
+ *
+ * This is the function signature for window focus callback functions.
+ *
+ * @param[in] window The window that gained or lost input focus.
+ * @param[in] focused `GLFW_TRUE` if the window was given input focus, or
+ * `GLFW_FALSE` if it lost it.
+ *
+ * @sa @ref window_focus
+ * @sa @ref glfwSetWindowFocusCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
+
+/*! @brief The function signature for window iconify/restore callbacks.
+ *
+ * This is the function signature for window iconify/restore callback
+ * functions.
+ *
+ * @param[in] window The window that was iconified or restored.
+ * @param[in] iconified `GLFW_TRUE` if the window was iconified, or
+ * `GLFW_FALSE` if it was restored.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwSetWindowIconifyCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
+
+/*! @brief The function signature for window maximize/restore callbacks.
+ *
+ * This is the function signature for window maximize/restore callback
+ * functions.
+ *
+ * @param[in] window The window that was maximized or restored.
+ * @param[in] iconified `GLFW_TRUE` if the window was maximized, or
+ * `GLFW_FALSE` if it was restored.
+ *
+ * @sa @ref window_maximize
+ * @sa glfwSetWindowMaximizeCallback
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
+
+/*! @brief The function signature for framebuffer resize callbacks.
+ *
+ * This is the function signature for framebuffer resize callback
+ * functions.
+ *
+ * @param[in] window The window whose framebuffer was resized.
+ * @param[in] width The new width, in pixels, of the framebuffer.
+ * @param[in] height The new height, in pixels, of the framebuffer.
+ *
+ * @sa @ref window_fbsize
+ * @sa @ref glfwSetFramebufferSizeCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
+
+/*! @brief The function signature for window content scale callbacks.
+ *
+ * This is the function signature for window content scale callback
+ * functions.
+ *
+ * @param[in] window The window whose content scale changed.
+ * @param[in] xscale The new x-axis content scale of the window.
+ * @param[in] yscale The new y-axis content scale of the window.
+ *
+ * @sa @ref window_scale
+ * @sa @ref glfwSetWindowContentScaleCallback
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);
+
+/*! @brief The function signature for mouse button callbacks.
+ *
+ * This is the function signature for mouse button callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] button The [mouse button](@ref buttons) that was pressed or
+ * released.
+ * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_mouse_button
+ * @sa @ref glfwSetMouseButtonCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle and modifier mask parameters.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
+
+/*! @brief The function signature for cursor position callbacks.
+ *
+ * This is the function signature for cursor position callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] xpos The new cursor x-coordinate, relative to the left edge of
+ * the client area.
+ * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
+ * client area.
+ *
+ * @sa @ref cursor_pos
+ * @sa @ref glfwSetCursorPosCallback
+ *
+ * @since Added in version 3.0. Replaces `GLFWmouseposfun`.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
+
+/*! @brief The function signature for cursor enter/leave callbacks.
+ *
+ * This is the function signature for cursor enter/leave callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client
+ * area, or `GLFW_FALSE` if it left it.
+ *
+ * @sa @ref cursor_enter
+ * @sa @ref glfwSetCursorEnterCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
+
+/*! @brief The function signature for scroll callbacks.
+ *
+ * This is the function signature for scroll callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] xoffset The scroll offset along the x-axis.
+ * @param[in] yoffset The scroll offset along the y-axis.
+ *
+ * @sa @ref scrolling
+ * @sa @ref glfwSetScrollCallback
+ *
+ * @since Added in version 3.0. Replaces `GLFWmousewheelfun`.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
+
+/*! @brief The function signature for keyboard key callbacks.
+ *
+ * This is the function signature for keyboard key callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] key The [keyboard key](@ref keys) that was pressed or released.
+ * @param[in] scancode The system-specific scancode of the key.
+ * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_key
+ * @sa @ref glfwSetKeyCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle, scancode and modifier mask parameters.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);
+
+/*! @brief The function signature for Unicode character callbacks.
+ *
+ * This is the function signature for Unicode character callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the character.
+ *
+ * @sa @ref input_char
+ * @sa @ref glfwSetCharCallback
+ *
+ * @since Added in version 2.4.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
+
+/*! @brief The function signature for Unicode character with modifiers
+ * callbacks.
+ *
+ * This is the function signature for Unicode character with modifiers callback
+ * functions. It is called for each input character, regardless of what
+ * modifier keys are held down.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the character.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_char
+ * @sa @ref glfwSetCharModsCallback
+ *
+ * @deprecated Scheduled for removal in version 4.0.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
+
+/*! @brief The function signature for file drop callbacks.
+ *
+ * This is the function signature for file drop callbacks.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] count The number of dropped files.
+ * @param[in] paths The UTF-8 encoded file and/or directory path names.
+ *
+ * @sa @ref path_drop
+ * @sa @ref glfwSetDropCallback
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
+
+/*! @brief The function signature for monitor configuration callbacks.
+ *
+ * This is the function signature for monitor configuration callback functions.
+ *
+ * @param[in] monitor The monitor that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining
+ * values reserved for future use.
+ *
+ * @sa @ref monitor_event
+ * @sa @ref glfwSetMonitorCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
+
+/*! @brief The function signature for joystick configuration callbacks.
+ *
+ * This is the function signature for joystick configuration callback
+ * functions.
+ *
+ * @param[in] jid The joystick that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Remaining
+ * values reserved for future use.
+ *
+ * @sa @ref joystick_event
+ * @sa @ref glfwSetJoystickCallback
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWjoystickfun)(int,int);
+
+/*! @brief Video mode type.
+ *
+ * This describes a single video mode.
+ *
+ * @sa @ref monitor_modes
+ * @sa @ref glfwGetVideoMode
+ * @sa @ref glfwGetVideoModes
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added refresh rate member.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWvidmode
+{
+ /*! The width, in screen coordinates, of the video mode.
+ */
+ int width;
+ /*! The height, in screen coordinates, of the video mode.
+ */
+ int height;
+ /*! The bit depth of the red channel of the video mode.
+ */
+ int redBits;
+ /*! The bit depth of the green channel of the video mode.
+ */
+ int greenBits;
+ /*! The bit depth of the blue channel of the video mode.
+ */
+ int blueBits;
+ /*! The refresh rate, in Hz, of the video mode.
+ */
+ int refreshRate;
+} GLFWvidmode;
+
+/*! @brief Gamma ramp.
+ *
+ * This describes the gamma ramp for a monitor.
+ *
+ * @sa @ref monitor_gamma
+ * @sa @ref glfwGetGammaRamp
+ * @sa @ref glfwSetGammaRamp
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWgammaramp
+{
+ /*! An array of value describing the response of the red channel.
+ */
+ unsigned short* red;
+ /*! An array of value describing the response of the green channel.
+ */
+ unsigned short* green;
+ /*! An array of value describing the response of the blue channel.
+ */
+ unsigned short* blue;
+ /*! The number of elements in each array.
+ */
+ unsigned int size;
+} GLFWgammaramp;
+
+/*! @brief Image data.
+ *
+ * This describes a single 2D image. See the documentation for each related
+ * function what the expected pixel format is.
+ *
+ * @sa @ref cursor_custom
+ * @sa @ref window_icon
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Removed format and bytes-per-pixel members.
+ *
+ * @ingroup window
+ */
+typedef struct GLFWimage
+{
+ /*! The width, in pixels, of this image.
+ */
+ int width;
+ /*! The height, in pixels, of this image.
+ */
+ int height;
+ /*! The pixel data of this image, arranged left-to-right, top-to-bottom.
+ */
+ unsigned char* pixels;
+} GLFWimage;
+
+/*! @brief Gamepad input state
+ *
+ * This describes the input state of a gamepad.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwGetGamepadState
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+typedef struct GLFWgamepadstate
+{
+ /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS`
+ * or `GLFW_RELEASE`.
+ */
+ unsigned char buttons[15];
+ /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0
+ * to 1.0 inclusive.
+ */
+ float axes[6];
+} GLFWgamepadstate;
+
+
+/*************************************************************************
+ * GLFW API functions
+ *************************************************************************/
+
+/*! @brief Initializes the GLFW library.
+ *
+ * This function initializes the GLFW library. Before most GLFW functions can
+ * be used, GLFW must be initialized, and before an application terminates GLFW
+ * should be terminated in order to free any resources allocated during or
+ * after initialization.
+ *
+ * If this function fails, it calls @ref glfwTerminate before returning. If it
+ * succeeds, you should call @ref glfwTerminate before the application exits.
+ *
+ * Additional calls to this function after successful initialization but before
+ * termination will return `GLFW_TRUE` immediately.
+ *
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos This function will change the current directory of the
+ * application to the `Contents/Resources` subdirectory of the application's
+ * bundle, if present. This can be disabled with the @ref
+ * GLFW_COCOA_CHDIR_RESOURCES init hint.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref intro_init
+ * @sa @ref glfwTerminate
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwInit(void);
+
+/*! @brief Terminates the GLFW library.
+ *
+ * This function destroys all remaining windows and cursors, restores any
+ * modified gamma ramps and frees any other allocated resources. Once this
+ * function is called, you must again call @ref glfwInit successfully before
+ * you will be able to use most GLFW functions.
+ *
+ * If GLFW has been successfully initialized, this function should be called
+ * before the application exits. If initialization fails, there is no need to
+ * call this function, as it is called by @ref glfwInit before it returns
+ * failure.
+ *
+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @warning The contexts of any remaining windows must not be current on any
+ * other thread when this function is called.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref intro_init
+ * @sa @ref glfwInit
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwTerminate(void);
+
+/*! @brief Sets the specified init hint to the desired value.
+ *
+ * This function sets hints for the next initialization of GLFW.
+ *
+ * The values you set hints to are never reset by GLFW, but they only take
+ * effect during initialization. Once GLFW has been initialized, any values
+ * you set will be ignored until the library is terminated and initialized
+ * again.
+ *
+ * Some hints are platform specific. These may be set on any platform but they
+ * will only affect their specific platform. Other platforms will ignore them.
+ * Setting these hints requires no platform specific headers or functions.
+ *
+ * @param[in] hint The [init hint](@ref init_hints) to set.
+ * @param[in] value The new value of the init hint.
+ *
+ * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @remarks This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa init_hints
+ * @sa glfwInit
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwInitHint(int hint, int value);
+
+/*! @brief Retrieves the version of the GLFW library.
+ *
+ * This function retrieves the major, minor and revision numbers of the GLFW
+ * library. It is intended for when you are using GLFW as a shared library and
+ * want to ensure that you are using the minimum required version.
+ *
+ * Any or all of the version arguments may be `NULL`.
+ *
+ * @param[out] major Where to store the major version number, or `NULL`.
+ * @param[out] minor Where to store the minor version number, or `NULL`.
+ * @param[out] rev Where to store the revision number, or `NULL`.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref intro_version
+ * @sa @ref glfwGetVersionString
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);
+
+/*! @brief Returns a string describing the compile-time configuration.
+ *
+ * This function returns the compile-time generated
+ * [version string](@ref intro_version_string) of the GLFW library binary. It
+ * describes the version, platform, compiler and any platform-specific
+ * compile-time options. It should not be confused with the OpenGL or OpenGL
+ * ES version string, queried with `glGetString`.
+ *
+ * __Do not use the version string__ to parse the GLFW library version. The
+ * @ref glfwGetVersion function provides the version of the running library
+ * binary in numerical format.
+ *
+ * @return The ASCII encoded GLFW version string.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @pointer_lifetime The returned string is static and compile-time generated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref intro_version
+ * @sa @ref glfwGetVersion
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI const char* glfwGetVersionString(void);
+
+/*! @brief Returns and clears the last error for the calling thread.
+ *
+ * This function returns and clears the [error code](@ref errors) of the last
+ * error that occurred on the calling thread, and optionally a UTF-8 encoded
+ * human-readable description of it. If no error has occurred since the last
+ * call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is
+ * set to `NULL`.
+ *
+ * @param[in] description Where to store the error description pointer, or `NULL`.
+ * @return The last error code for the calling thread, or @ref GLFW_NO_ERROR
+ * (zero).
+ *
+ * @errors None.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * next error occurs or the library is terminated.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref error_handling
+ * @sa @ref glfwSetErrorCallback
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwGetError(const char** description);
+
+/*! @brief Sets the error callback.
+ *
+ * This function sets the error callback, which is called with an error code
+ * and a human-readable description each time a GLFW error occurs.
+ *
+ * The error code is set before the callback is called. Calling @ref
+ * glfwGetError from the error callback will return the same value as the error
+ * code argument.
+ *
+ * The error callback is called on the thread where the error occurred. If you
+ * are using GLFW from multiple threads, your error callback needs to be
+ * written accordingly.
+ *
+ * Because the description string may have been generated specifically for that
+ * error, it is not guaranteed to be valid after the callback has returned. If
+ * you wish to use it after the callback returns, you need to make a copy.
+ *
+ * Once set, the error callback remains set even after the library has been
+ * terminated.
+ *
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref error_handling
+ * @sa @ref glfwGetError
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
+
+/*! @brief Returns the currently connected monitors.
+ *
+ * This function returns an array of handles for all currently connected
+ * monitors. The primary monitor is always first in the returned array. If no
+ * monitors were found, this function returns `NULL`.
+ *
+ * @param[out] count Where to store the number of monitors in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of monitor handles, or `NULL` if no monitors were found or
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * monitor configuration changes or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_monitors
+ * @sa @ref monitor_event
+ * @sa @ref glfwGetPrimaryMonitor
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
+
+/*! @brief Returns the primary monitor.
+ *
+ * This function returns the primary monitor. This is usually the monitor
+ * where elements like the task bar or global menu bar are located.
+ *
+ * @return The primary monitor, or `NULL` if no monitors were found or if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @remark The primary monitor is always first in the array returned by @ref
+ * glfwGetMonitors.
+ *
+ * @sa @ref monitor_monitors
+ * @sa @ref glfwGetMonitors
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
+
+/*! @brief Returns the position of the monitor's viewport on the virtual screen.
+ *
+ * This function returns the position, in screen coordinates, of the upper-left
+ * corner of the specified monitor.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.
+ * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
+
+/*! @brief Returns the physical size of the monitor.
+ *
+ * This function returns the size, in millimetres, of the display area of the
+ * specified monitor.
+ *
+ * Some systems do not provide accurate monitor size information, either
+ * because the monitor
+ * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data)
+ * data is incorrect or because the driver does not report it accurately.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] widthMM Where to store the width, in millimetres, of the
+ * monitor's display area, or `NULL`.
+ * @param[out] heightMM Where to store the height, in millimetres, of the
+ * monitor's display area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @win32 calculates the returned physical size from the
+ * current resolution and system DPI instead of querying the monitor EDID data.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);
+
+/*! @brief Retrieves the content scale for the specified monitor.
+ *
+ * This function retrieves the content scale for the specified monitor. The
+ * content scale is the ratio between the current DPI and the platform's
+ * default DPI. If you scale all pixel dimensions by this scale then your
+ * content should appear at an appropriate size. This is especially important
+ * for text and any UI elements.
+ *
+ * The content scale may depend on both the monitor resolution and pixel
+ * density and on user settings. It may be very different from the raw DPI
+ * calculated from the physical size and current resolution.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] xscale Where to store the x-axis content scale, or `NULL`.
+ * @param[out] yscale Where to store the y-axis content scale, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_scale
+ * @sa @ref glfwGetWindowContentScale
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale);
+
+/*! @brief Returns the name of the specified monitor.
+ *
+ * This function returns a human-readable name, encoded as UTF-8, of the
+ * specified monitor. The name typically reflects the make and model of the
+ * monitor and is not guaranteed to be unique among the connected monitors.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The UTF-8 encoded name of the monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
+
+/*! @brief Sets the user pointer of the specified monitor.
+ *
+ * This function sets the user-defined pointer of the specified monitor. The
+ * current value is retained until the monitor is disconnected. The initial
+ * value is `NULL`.
+ *
+ * This function may be called from the monitor callback, even for a monitor
+ * that is being disconnected.
+ *
+ * @param[in] monitor The monitor whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref monitor_userptr
+ * @sa @ref glfwGetMonitorUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer);
+
+/*! @brief Returns the user pointer of the specified monitor.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified monitor. The initial value is `NULL`.
+ *
+ * This function may be called from the monitor callback, even for a monitor
+ * that is being disconnected.
+ *
+ * @param[in] monitor The monitor whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref monitor_userptr
+ * @sa @ref glfwSetMonitorUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor);
+
+/*! @brief Sets the monitor configuration callback.
+ *
+ * This function sets the monitor configuration callback, or removes the
+ * currently set callback. This is called when a monitor is connected to or
+ * disconnected from the system.
+ *
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_event
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun);
+
+/*! @brief Returns the available video modes for the specified monitor.
+ *
+ * This function returns an array of all video modes supported by the specified
+ * monitor. The returned array is sorted in ascending order, first by color
+ * bit depth (the sum of all channel depths) and then by resolution area (the
+ * product of width and height).
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] count Where to store the number of video modes in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of video modes, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected, this function is called again for that monitor or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_modes
+ * @sa @ref glfwGetVideoMode
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Changed to return an array of modes for a specific monitor.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count);
+
+/*! @brief Returns the current mode of the specified monitor.
+ *
+ * This function returns the current video mode of the specified monitor. If
+ * you have created a full screen window for that monitor, the return value
+ * will depend on whether that window is iconified.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The current mode of the monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_modes
+ * @sa @ref glfwGetVideoModes
+ *
+ * @since Added in version 3.0. Replaces `glfwGetDesktopMode`.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
+
+/*! @brief Generates a gamma ramp and sets it for the specified monitor.
+ *
+ * This function generates an appropriately sized gamma ramp from the specified
+ * exponent and then calls @ref glfwSetGammaRamp with it. The value must be
+ * a finite number greater than zero.
+ *
+ * The software controlled gamma ramp is applied _in addition_ to the hardware
+ * gamma correction, which today is usually an approximation of sRGB gamma.
+ * This means that setting a perfectly linear ramp, or gamma 1.0, will produce
+ * the default (usually sRGB-like) behavior.
+ *
+ * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
+ * GLFW_SRGB_CAPABLE hint.
+ *
+ * @param[in] monitor The monitor whose gamma ramp to set.
+ * @param[in] gamma The desired exponent.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland Gamma handling is a priviledged protocol, this function
+ * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
+
+/*! @brief Returns the current gamma ramp for the specified monitor.
+ *
+ * This function returns the current gamma ramp of the specified monitor.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The current gamma ramp, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland Gamma handling is a priviledged protocol, this function
+ * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while
+ * returning `NULL`.
+ *
+ * @pointer_lifetime The returned structure and its arrays are allocated and
+ * freed by GLFW. You should not free them yourself. They are valid until the
+ * specified monitor is disconnected, this function is called again for that
+ * monitor or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
+
+/*! @brief Sets the current gamma ramp for the specified monitor.
+ *
+ * This function sets the current gamma ramp for the specified monitor. The
+ * original gamma ramp for that monitor is saved by GLFW the first time this
+ * function is called and is restored by @ref glfwTerminate.
+ *
+ * The software controlled gamma ramp is applied _in addition_ to the hardware
+ * gamma correction, which today is usually an approximation of sRGB gamma.
+ * This means that setting a perfectly linear ramp, or gamma 1.0, will produce
+ * the default (usually sRGB-like) behavior.
+ *
+ * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
+ * GLFW_SRGB_CAPABLE hint.
+ *
+ * @param[in] monitor The monitor whose gamma ramp to set.
+ * @param[in] ramp The gamma ramp to use.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark The size of the specified gamma ramp should match the size of the
+ * current ramp for that monitor.
+ *
+ * @remark @win32 The gamma ramp size must be 256.
+ *
+ * @remark @wayland Gamma handling is a priviledged protocol, this function
+ * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified gamma ramp is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
+
+/*! @brief Resets all window hints to their default values.
+ *
+ * This function resets all window hints to their
+ * [default values](@ref window_hints_values).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa @ref glfwWindowHint
+ * @sa @ref glfwWindowHintString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwDefaultWindowHints(void);
+
+/*! @brief Sets the specified window hint to the desired value.
+ *
+ * This function sets hints for the next call to @ref glfwCreateWindow. The
+ * hints, once set, retain their values until changed by a call to this
+ * function or @ref glfwDefaultWindowHints, or until the library is terminated.
+ *
+ * Only integer value hints can be set with this function. String value hints
+ * are set with @ref glfwWindowHintString.
+ *
+ * This function does not check whether the specified hint values are valid.
+ * If you set hints to invalid values this will instead be reported by the next
+ * call to @ref glfwCreateWindow.
+ *
+ * Some hints are platform specific. These may be set on any platform but they
+ * will only affect their specific platform. Other platforms will ignore them.
+ * Setting these hints requires no platform specific headers or functions.
+ *
+ * @param[in] hint The [window hint](@ref window_hints) to set.
+ * @param[in] value The new value of the window hint.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa @ref glfwWindowHintString
+ * @sa @ref glfwDefaultWindowHints
+ *
+ * @since Added in version 3.0. Replaces `glfwOpenWindowHint`.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWindowHint(int hint, int value);
+
+/*! @brief Sets the specified window hint to the desired value.
+ *
+ * This function sets hints for the next call to @ref glfwCreateWindow. The
+ * hints, once set, retain their values until changed by a call to this
+ * function or @ref glfwDefaultWindowHints, or until the library is terminated.
+ *
+ * Only string type hints can be set with this function. Integer value hints
+ * are set with @ref glfwWindowHint.
+ *
+ * This function does not check whether the specified hint values are valid.
+ * If you set hints to invalid values this will instead be reported by the next
+ * call to @ref glfwCreateWindow.
+ *
+ * Some hints are platform specific. These may be set on any platform but they
+ * will only affect their specific platform. Other platforms will ignore them.
+ * Setting these hints requires no platform specific headers or functions.
+ *
+ * @param[in] hint The [window hint](@ref window_hints) to set.
+ * @param[in] value The new value of the window hint.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa @ref glfwWindowHint
+ * @sa @ref glfwDefaultWindowHints
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWindowHintString(int hint, const char* value);
+
+/*! @brief Creates a window and its associated context.
+ *
+ * This function creates a window and its associated OpenGL or OpenGL ES
+ * context. Most of the options controlling how the window and its context
+ * should be created are specified with [window hints](@ref window_hints).
+ *
+ * Successful creation does not change which context is current. Before you
+ * can use the newly created context, you need to
+ * [make it current](@ref context_current). For information about the `share`
+ * parameter, see @ref context_sharing.
+ *
+ * The created window, framebuffer and context may differ from what you
+ * requested, as not all parameters and hints are
+ * [hard constraints](@ref window_hints_hard). This includes the size of the
+ * window, especially for full screen windows. To query the actual attributes
+ * of the created window, framebuffer and context, see @ref
+ * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
+ *
+ * To create a full screen window, you need to specify the monitor the window
+ * will cover. If no monitor is specified, the window will be windowed mode.
+ * Unless you have a way for the user to choose a specific monitor, it is
+ * recommended that you pick the primary monitor. For more information on how
+ * to query connected monitors, see @ref monitor_monitors.
+ *
+ * For full screen windows, the specified size becomes the resolution of the
+ * window's _desired video mode_. As long as a full screen window is not
+ * iconified, the supported video mode most closely matching the desired video
+ * mode is set for the specified monitor. For more information about full
+ * screen windows, including the creation of so called _windowed full screen_
+ * or _borderless full screen_ windows, see @ref window_windowed_full_screen.
+ *
+ * Once you have created the window, you can switch it between windowed and
+ * full screen mode with @ref glfwSetWindowMonitor. This will not affect its
+ * OpenGL or OpenGL ES context.
+ *
+ * By default, newly created windows use the placement recommended by the
+ * window system. To create the window at a specific position, make it
+ * initially invisible using the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window
+ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide)
+ * it.
+ *
+ * As long as at least one full screen window is not iconified, the screensaver
+ * is prohibited from starting.
+ *
+ * Window systems put limits on window sizes. Very large or very small window
+ * dimensions may be overridden by the window system on creation. Check the
+ * actual [size](@ref window_size) after creation.
+ *
+ * The [swap interval](@ref buffer_swap) is not set during window creation and
+ * the initial value may vary depending on driver settings and defaults.
+ *
+ * @param[in] width The desired width, in screen coordinates, of the window.
+ * This must be greater than zero.
+ * @param[in] height The desired height, in screen coordinates, of the window.
+ * This must be greater than zero.
+ * @param[in] title The initial, UTF-8 encoded window title.
+ * @param[in] monitor The monitor to use for full screen mode, or `NULL` for
+ * windowed mode.
+ * @param[in] share The window whose context to share resources with, or `NULL`
+ * to not share resources.
+ * @return The handle of the created window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref
+ * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @win32 Window creation will fail if the Microsoft GDI software
+ * OpenGL implementation is the only one available.
+ *
+ * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it
+ * will be set as the initial icon for the window. If no such icon is present,
+ * the `IDI_APPLICATION` icon will be used instead. To set a different icon,
+ * see @ref glfwSetWindowIcon.
+ *
+ * @remark @win32 The context to share resources with must not be current on
+ * any other thread.
+ *
+ * @remark @macos The OS only supports forward-compatible core profile contexts
+ * for OpenGL versions 3.2 and later. Before creating an OpenGL context of
+ * version 3.2 or later you must set the
+ * [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and
+ * [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly.
+ * OpenGL 3.0 and 3.1 contexts are not supported at all on macOS.
+ *
+ * @remark @macos The GLFW window has no icon, as it is not a document
+ * window, but the dock icon will be the same as the application bundle's icon.
+ * For more information on bundles, see the
+ * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
+ * in the Mac Developer Library.
+ *
+ * @remark @macos The first time a window is created the menu bar is created.
+ * If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu
+ * bar. Otherwise a minimal menu bar is created manually with common commands
+ * like Hide, Quit and About. The About entry opens a minimal about dialog
+ * with information from the application's bundle. Menu bar creation can be
+ * disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint.
+ *
+ * @remark @macos On OS X 10.10 and later the window frame will not be rendered
+ * at full resolution on Retina displays unless the
+ * [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
+ * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
+ * application bundle's `Info.plist`. For more information, see
+ * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
+ * in the Mac Developer Library. The GLFW test and example programs use
+ * a custom `Info.plist` template for this, which can be found as
+ * `CMake/MacOSXBundleInfo.plist.in` in the source tree.
+ *
+ * @remark @macos When activating frame autosaving with
+ * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
+ * window size and position may be overriden by previously saved values.
+ *
+ * @remark @x11 Some window managers will not respect the placement of
+ * initially hidden windows.
+ *
+ * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for
+ * a window to reach its requested state. This means you may not be able to
+ * query the final size, position or other attributes directly after window
+ * creation.
+ *
+ * @remark @x11 The class part of the `WM_CLASS` window property will by
+ * default be set to the window title passed to this function. The instance
+ * part will use the contents of the `RESOURCE_NAME` environment variable, if
+ * present and not empty, or fall back to the window title. Set the @ref
+ * GLFW_X11_CLASS_NAME and @ref GLFW_X11_INSTANCE_NAME window hints to override
+ * this.
+ *
+ * @remark @wayland The window frame is currently very simple, only allowing
+ * window resize or move. A compositor can still emit close, maximize or
+ * fullscreen events, using for example a keybind mechanism. Additionally,
+ * the wp_viewporter protocol is required for this feature, otherwise the
+ * window will not be decorated.
+ *
+ * @remark @wayland A full screen window will not attempt to change the mode,
+ * no matter what the requested size or refresh rate.
+ *
+ * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol
+ * to be implemented in the user's compositor.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_creation
+ * @sa @ref glfwDestroyWindow
+ *
+ * @since Added in version 3.0. Replaces `glfwOpenWindow`.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
+
+/*! @brief Destroys the specified window and its context.
+ *
+ * This function destroys the specified window and its context. On calling
+ * this function, no further callbacks will be called for that window.
+ *
+ * If the context of the specified window is current on the main thread, it is
+ * detached before being destroyed.
+ *
+ * @param[in] window The window to destroy.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @note The context of the specified window must not be current on any other
+ * thread when this function is called.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_creation
+ * @sa @ref glfwCreateWindow
+ *
+ * @since Added in version 3.0. Replaces `glfwCloseWindow`.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwDestroyWindow(GLFWwindow* window);
+
+/*! @brief Checks the close flag of the specified window.
+ *
+ * This function returns the value of the close flag of the specified window.
+ *
+ * @param[in] window The window to query.
+ * @return The value of the close flag.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);
+
+/*! @brief Sets the close flag of the specified window.
+ *
+ * This function sets the value of the close flag of the specified window.
+ * This can be used to override the user's attempt to close the window, or
+ * to signal that it should be closed.
+ *
+ * @param[in] window The window whose flag to change.
+ * @param[in] value The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
+
+/*! @brief Sets the title of the specified window.
+ *
+ * This function sets the window title, encoded as UTF-8, of the specified
+ * window.
+ *
+ * @param[in] window The window whose title to change.
+ * @param[in] title The UTF-8 encoded window title.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos The window title will not be updated until the next time you
+ * process events.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_title
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
+
+/*! @brief Sets the icon for the specified window.
+ *
+ * This function sets the icon of the specified window. If passed an array of
+ * candidate images, those of or closest to the sizes desired by the system are
+ * selected. If no images are specified, the window reverts to its default
+ * icon.
+ *
+ * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+ * bits per channel with the red channel first. They are arranged canonically
+ * as packed sequential rows, starting from the top-left corner.
+ *
+ * The desired image sizes varies depending on platform and system settings.
+ * The selected images will be rescaled as needed. Good sizes include 16x16,
+ * 32x32 and 48x48.
+ *
+ * @param[in] window The window whose icon to set.
+ * @param[in] count The number of images in the specified array, or zero to
+ * revert to the default window icon.
+ * @param[in] images The images to create the icon from. This is ignored if
+ * count is zero.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified image data is copied before this function
+ * returns.
+ *
+ * @remark @macos The GLFW window has no icon, as it is not a document
+ * window, so this function does nothing. The dock icon will be the same as
+ * the application bundle's icon. For more information on bundles, see the
+ * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
+ * in the Mac Developer Library.
+ *
+ * @remark @wayland There is no existing protocol to change an icon, the
+ * window will thus inherit the one defined in the application's desktop file.
+ * This function always emits @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_icon
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
+
+/*! @brief Retrieves the position of the client area of the specified window.
+ *
+ * This function retrieves the position, in screen coordinates, of the
+ * upper-left corner of the client area of the specified window.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] window The window to query.
+ * @param[out] xpos Where to store the x-coordinate of the upper-left corner of
+ * the client area, or `NULL`.
+ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of
+ * the client area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland There is no way for an application to retrieve the global
+ * position of its windows, this function will always emit @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ * @sa @ref glfwSetWindowPos
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
+
+/*! @brief Sets the position of the client area of the specified window.
+ *
+ * This function sets the position, in screen coordinates, of the upper-left
+ * corner of the client area of the specified windowed mode window. If the
+ * window is a full screen window, this function does nothing.
+ *
+ * __Do not use this function__ to move an already visible window unless you
+ * have very good reasons for doing so, as it will confuse and annoy the user.
+ *
+ * The window manager may put limits on what positions are allowed. GLFW
+ * cannot and should not override these limits.
+ *
+ * @param[in] window The window to query.
+ * @param[in] xpos The x-coordinate of the upper-left corner of the client area.
+ * @param[in] ypos The y-coordinate of the upper-left corner of the client area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland There is no way for an application to set the global
+ * position of its windows, this function will always emit @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ * @sa @ref glfwGetWindowPos
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
+
+/*! @brief Retrieves the size of the client area of the specified window.
+ *
+ * This function retrieves the size, in screen coordinates, of the client area
+ * of the specified window. If you wish to retrieve the size of the
+ * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose size to retrieve.
+ * @param[out] width Where to store the width, in screen coordinates, of the
+ * client area, or `NULL`.
+ * @param[out] height Where to store the height, in screen coordinates, of the
+ * client area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ * @sa @ref glfwSetWindowSize
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
+
+/*! @brief Sets the size limits of the specified window.
+ *
+ * This function sets the size limits of the client area of the specified
+ * window. If the window is full screen, the size limits only take effect
+ * once it is made windowed. If the window is not resizable, this function
+ * does nothing.
+ *
+ * The size limits are applied immediately to a windowed mode window and may
+ * cause it to be resized.
+ *
+ * The maximum dimensions must be greater than or equal to the minimum
+ * dimensions and all must be greater than or equal to zero.
+ *
+ * @param[in] window The window to set limits for.
+ * @param[in] minwidth The minimum width, in screen coordinates, of the client
+ * area, or `GLFW_DONT_CARE`.
+ * @param[in] minheight The minimum height, in screen coordinates, of the
+ * client area, or `GLFW_DONT_CARE`.
+ * @param[in] maxwidth The maximum width, in screen coordinates, of the client
+ * area, or `GLFW_DONT_CARE`.
+ * @param[in] maxheight The maximum height, in screen coordinates, of the
+ * client area, or `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark If you set size limits and an aspect ratio that conflict, the
+ * results are undefined.
+ *
+ * @remark @wayland The size limits will not be applied until the window is
+ * actually resized, either by the user or by the compositor.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_sizelimits
+ * @sa @ref glfwSetWindowAspectRatio
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
+
+/*! @brief Sets the aspect ratio of the specified window.
+ *
+ * This function sets the required aspect ratio of the client area of the
+ * specified window. If the window is full screen, the aspect ratio only takes
+ * effect once it is made windowed. If the window is not resizable, this
+ * function does nothing.
+ *
+ * The aspect ratio is specified as a numerator and a denominator and both
+ * values must be greater than zero. For example, the common 16:9 aspect ratio
+ * is specified as 16 and 9, respectively.
+ *
+ * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect
+ * ratio limit is disabled.
+ *
+ * The aspect ratio is applied immediately to a windowed mode window and may
+ * cause it to be resized.
+ *
+ * @param[in] window The window to set limits for.
+ * @param[in] numer The numerator of the desired aspect ratio, or
+ * `GLFW_DONT_CARE`.
+ * @param[in] denom The denominator of the desired aspect ratio, or
+ * `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark If you set size limits and an aspect ratio that conflict, the
+ * results are undefined.
+ *
+ * @remark @wayland The aspect ratio will not be applied until the window is
+ * actually resized, either by the user or by the compositor.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_sizelimits
+ * @sa @ref glfwSetWindowSizeLimits
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
+
+/*! @brief Sets the size of the client area of the specified window.
+ *
+ * This function sets the size, in screen coordinates, of the client area of
+ * the specified window.
+ *
+ * For full screen windows, this function updates the resolution of its desired
+ * video mode and switches to the video mode closest to it, without affecting
+ * the window's context. As the context is unaffected, the bit depths of the
+ * framebuffer remain unchanged.
+ *
+ * If you wish to update the refresh rate of the desired video mode in addition
+ * to its resolution, see @ref glfwSetWindowMonitor.
+ *
+ * The window manager may put limits on what sizes are allowed. GLFW cannot
+ * and should not override these limits.
+ *
+ * @param[in] window The window to resize.
+ * @param[in] width The desired width, in screen coordinates, of the window
+ * client area.
+ * @param[in] height The desired height, in screen coordinates, of the window
+ * client area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland A full screen window will not attempt to change the mode,
+ * no matter what the requested size.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ * @sa @ref glfwGetWindowSize
+ * @sa @ref glfwSetWindowMonitor
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);
+
+/*! @brief Retrieves the size of the framebuffer of the specified window.
+ *
+ * This function retrieves the size, in pixels, of the framebuffer of the
+ * specified window. If you wish to retrieve the size of the window in screen
+ * coordinates, see @ref glfwGetWindowSize.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose framebuffer to query.
+ * @param[out] width Where to store the width, in pixels, of the framebuffer,
+ * or `NULL`.
+ * @param[out] height Where to store the height, in pixels, of the framebuffer,
+ * or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_fbsize
+ * @sa @ref glfwSetFramebufferSizeCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height);
+
+/*! @brief Retrieves the size of the frame of the window.
+ *
+ * This function retrieves the size, in screen coordinates, of each edge of the
+ * frame of the specified window. This size includes the title bar, if the
+ * window has one. The size of the frame may vary depending on the
+ * [window-related hints](@ref window_hints_wnd) used to create it.
+ *
+ * Because this function retrieves the size of each window frame edge and not
+ * the offset along a particular coordinate axis, the retrieved values will
+ * always be zero or positive.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose frame size to query.
+ * @param[out] left Where to store the size, in screen coordinates, of the left
+ * edge of the window frame, or `NULL`.
+ * @param[out] top Where to store the size, in screen coordinates, of the top
+ * edge of the window frame, or `NULL`.
+ * @param[out] right Where to store the size, in screen coordinates, of the
+ * right edge of the window frame, or `NULL`.
+ * @param[out] bottom Where to store the size, in screen coordinates, of the
+ * bottom edge of the window frame, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);
+
+/*! @brief Retrieves the content scale for the specified window.
+ *
+ * This function retrieves the content scale for the specified window. The
+ * content scale is the ratio between the current DPI and the platform's
+ * default DPI. If you scale all pixel dimensions by this scale then your
+ * content should appear at an appropriate size. This is especially important
+ * for text and any UI elements.
+ *
+ * On systems where each monitors can have its own content scale, the window
+ * content scale will depend on which monitor the system considers the window
+ * to be on.
+ *
+ * @param[in] window The window to query.
+ * @param[out] xscale Where to store the x-axis content scale, or `NULL`.
+ * @param[out] yscale Where to store the y-axis content scale, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_scale
+ * @sa @ref glfwSetWindowContentScaleCallback
+ * @sa @ref glfwGetMonitorContentScale
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
+
+/*! @brief Returns the opacity of the whole window.
+ *
+ * This function returns the opacity of the window, including any decorations.
+ *
+ * The opacity (or alpha) value is a positive finite number between zero and
+ * one, where zero is fully transparent and one is fully opaque. If the system
+ * does not support whole window transparency, this function always returns one.
+ *
+ * The initial opacity value for newly created windows is one.
+ *
+ * @param[in] window The window to query.
+ * @return The opacity value of the specified window.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_transparency
+ * @sa @ref glfwSetWindowOpacity
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
+
+/*! @brief Sets the opacity of the whole window.
+ *
+ * This function sets the opacity of the window, including any decorations.
+ *
+ * The opacity (or alpha) value is a positive finite number between zero and
+ * one, where zero is fully transparent and one is fully opaque.
+ *
+ * The initial opacity value for newly created windows is one.
+ *
+ * A window created with framebuffer transparency may not use whole window
+ * transparency. The results of doing this are undefined.
+ *
+ * @param[in] window The window to set the opacity for.
+ * @param[in] opacity The desired opacity of the specified window.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_transparency
+ * @sa @ref glfwGetWindowOpacity
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
+
+/*! @brief Iconifies the specified window.
+ *
+ * This function iconifies (minimizes) the specified window if it was
+ * previously restored. If the window is already iconified, this function does
+ * nothing.
+ *
+ * If the specified window is a full screen window, the original monitor
+ * resolution is restored until the window is restored.
+ *
+ * @param[in] window The window to iconify.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland There is no concept of iconification in wl_shell, this
+ * function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
+ * protocol.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwRestoreWindow
+ * @sa @ref glfwMaximizeWindow
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
+
+/*! @brief Restores the specified window.
+ *
+ * This function restores the specified window if it was previously iconified
+ * (minimized) or maximized. If the window is already restored, this function
+ * does nothing.
+ *
+ * If the specified window is a full screen window, the resolution chosen for
+ * the window is restored on the selected monitor.
+ *
+ * @param[in] window The window to restore.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwIconifyWindow
+ * @sa @ref glfwMaximizeWindow
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwRestoreWindow(GLFWwindow* window);
+
+/*! @brief Maximizes the specified window.
+ *
+ * This function maximizes the specified window if it was previously not
+ * maximized. If the window is already maximized, this function does nothing.
+ *
+ * If the specified window is a full screen window, this function does nothing.
+ *
+ * @param[in] window The window to maximize.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @par Thread Safety
+ * This function may only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa @ref glfwIconifyWindow
+ * @sa @ref glfwRestoreWindow
+ *
+ * @since Added in GLFW 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
+
+/*! @brief Makes the specified window visible.
+ *
+ * This function makes the specified window visible if it was previously
+ * hidden. If the window is already visible or is in full screen mode, this
+ * function does nothing.
+ *
+ * By default, windowed mode windows are focused when shown
+ * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint
+ * to change this behavior for all newly created windows, or change the
+ * behavior for an existing window with @ref glfwSetWindowAttrib.
+ *
+ * @param[in] window The window to make visible.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hide
+ * @sa @ref glfwHideWindow
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwShowWindow(GLFWwindow* window);
+
+/*! @brief Hides the specified window.
+ *
+ * This function hides the specified window if it was previously visible. If
+ * the window is already hidden or is in full screen mode, this function does
+ * nothing.
+ *
+ * @param[in] window The window to hide.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hide
+ * @sa @ref glfwShowWindow
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwHideWindow(GLFWwindow* window);
+
+/*! @brief Brings the specified window to front and sets input focus.
+ *
+ * This function brings the specified window to front and sets input focus.
+ * The window should already be visible and not iconified.
+ *
+ * By default, both windowed and full screen mode windows are focused when
+ * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to
+ * disable this behavior.
+ *
+ * Also by default, windowed mode windows are focused when shown
+ * with @ref glfwShowWindow. Set the
+ * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior.
+ *
+ * __Do not use this function__ to steal focus from other applications unless
+ * you are certain that is what the user wants. Focus stealing can be
+ * extremely disruptive.
+ *
+ * For a less disruptive way of getting the user's attention, see
+ * [attention requests](@ref window_attention).
+ *
+ * @param[in] window The window to give input focus.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland It is not possible for an application to bring its windows
+ * to front, this function will always emit @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_focus
+ * @sa @ref window_attention
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwFocusWindow(GLFWwindow* window);
+
+/*! @brief Requests user attention to the specified window.
+ *
+ * This function requests user attention to the specified window. On
+ * platforms where this is not supported, attention is requested to the
+ * application as a whole.
+ *
+ * Once the user has given attention, usually by focusing the window or
+ * application, the system will end the request automatically.
+ *
+ * @param[in] window The window to request attention to.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos Attention is requested to the application as a whole, not the
+ * specific window.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attention
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window);
+
+/*! @brief Returns the monitor that the window uses for full screen mode.
+ *
+ * This function returns the handle of the monitor that the specified window is
+ * in full screen on.
+ *
+ * @param[in] window The window to query.
+ * @return The monitor, or `NULL` if the window is in windowed mode or an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_monitor
+ * @sa @ref glfwSetWindowMonitor
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
+
+/*! @brief Sets the mode, monitor, video mode and placement of a window.
+ *
+ * This function sets the monitor that the window uses for full screen mode or,
+ * if the monitor is `NULL`, makes it windowed mode.
+ *
+ * When setting a monitor, this function updates the width, height and refresh
+ * rate of the desired video mode and switches to the video mode closest to it.
+ * The window position is ignored when setting a monitor.
+ *
+ * When the monitor is `NULL`, the position, width and height are used to
+ * place the window client area. The refresh rate is ignored when no monitor
+ * is specified.
+ *
+ * If you only wish to update the resolution of a full screen window or the
+ * size of a windowed mode window, see @ref glfwSetWindowSize.
+ *
+ * When a window transitions from full screen to windowed mode, this function
+ * restores any previous window settings such as whether it is decorated,
+ * floating, resizable, has size or aspect ratio limits, etc.
+ *
+ * @param[in] window The window whose monitor, size or video mode to set.
+ * @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
+ * @param[in] xpos The desired x-coordinate of the upper-left corner of the
+ * client area.
+ * @param[in] ypos The desired y-coordinate of the upper-left corner of the
+ * client area.
+ * @param[in] width The desired with, in screen coordinates, of the client area
+ * or video mode.
+ * @param[in] height The desired height, in screen coordinates, of the client
+ * area or video mode.
+ * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode,
+ * or `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise
+ * affected by any resizing or mode switching, although you may need to update
+ * your viewport if the framebuffer size has changed.
+ *
+ * @remark @wayland The desired window position is ignored, as there is no way
+ * for an application to set this property.
+ *
+ * @remark @wayland Setting the window to full screen will not attempt to
+ * change the mode, no matter what the requested size or refresh rate.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_monitor
+ * @sa @ref window_full_screen
+ * @sa @ref glfwGetWindowMonitor
+ * @sa @ref glfwSetWindowSize
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
+
+/*! @brief Returns an attribute of the specified window.
+ *
+ * This function returns the value of an attribute of the specified window or
+ * its OpenGL or OpenGL ES context.
+ *
+ * @param[in] window The window to query.
+ * @param[in] attrib The [window attribute](@ref window_attribs) whose value to
+ * return.
+ * @return The value of the attribute, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark Framebuffer related hints are not window attributes. See @ref
+ * window_attribs_fb for more information.
+ *
+ * @remark Zero is a valid value for many window and context related
+ * attributes so you cannot use a return value of zero as an indication of
+ * errors. However, this function should not fail as long as it is passed
+ * valid arguments and the library has been [initialized](@ref intro_init).
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attribs
+ * @sa @ref glfwSetWindowAttrib
+ *
+ * @since Added in version 3.0. Replaces `glfwGetWindowParam` and
+ * `glfwGetGLVersion`.
+ *
+ * @ingroup window
+ */
+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
+
+/*! @brief Sets an attribute of the specified window.
+ *
+ * This function sets the value of an attribute of the specified window.
+ *
+ * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
+ * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
+ * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
+ * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
+ * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
+ *
+ * Some of these attributes are ignored for full screen windows. The new
+ * value will take effect if the window is later made windowed.
+ *
+ * Some of these attributes are ignored for windowed mode windows. The new
+ * value will take effect if the window is later made full screen.
+ *
+ * @param[in] window The window to set the attribute for.
+ * @param[in] attrib A supported window attribute.
+ * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark Calling @ref glfwGetWindowAttrib will always return the latest
+ * value, even if that value is ignored by the current mode of the window.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attribs
+ * @sa @ref glfwGetWindowAttrib
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value);
+
+/*! @brief Sets the user pointer of the specified window.
+ *
+ * This function sets the user-defined pointer of the specified window. The
+ * current value is retained until the window is destroyed. The initial value
+ * is `NULL`.
+ *
+ * @param[in] window The window whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_userptr
+ * @sa @ref glfwGetWindowUserPointer
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);
+
+/*! @brief Returns the user pointer of the specified window.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified window. The initial value is `NULL`.
+ *
+ * @param[in] window The window whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_userptr
+ * @sa @ref glfwSetWindowUserPointer
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
+
+/*! @brief Sets the position callback for the specified window.
+ *
+ * This function sets the position callback of the specified window, which is
+ * called when the window is moved. The callback is provided with the
+ * position, in screen coordinates, of the upper-left corner of the client area
+ * of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @wayland This callback will never be called, as there is no way for
+ * an application to know its global position.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun cbfun);
+
+/*! @brief Sets the size callback for the specified window.
+ *
+ * This function sets the size callback of the specified window, which is
+ * called when the window is resized. The callback is provided with the size,
+ * in screen coordinates, of the client area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbfun);
+
+/*! @brief Sets the close callback for the specified window.
+ *
+ * This function sets the close callback of the specified window, which is
+ * called when the user attempts to close the window, for example by clicking
+ * the close widget in the title bar.
+ *
+ * The close flag is set before this callback is called, but you can modify it
+ * at any time with @ref glfwSetWindowShouldClose.
+ *
+ * The close callback is not triggered by @ref glfwDestroyWindow.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @macos Selecting Quit from the application menu will trigger the
+ * close callback for all windows.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun);
+
+/*! @brief Sets the refresh callback for the specified window.
+ *
+ * This function sets the refresh callback of the specified window, which is
+ * called when the client area of the window needs to be redrawn, for example
+ * if the window has been exposed after having been covered by another window.
+ *
+ * On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
+ * the window contents are saved off-screen, this callback may be called only
+ * very infrequently or never at all.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_refresh
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun cbfun);
+
+/*! @brief Sets the focus callback for the specified window.
+ *
+ * This function sets the focus callback of the specified window, which is
+ * called when the window gains or loses input focus.
+ *
+ * After the focus callback is called for a window that lost input focus,
+ * synthetic key and mouse button release events will be generated for all such
+ * that had been pressed. For more information, see @ref glfwSetKeyCallback
+ * and @ref glfwSetMouseButtonCallback.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_focus
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);
+
+/*! @brief Sets the iconify callback for the specified window.
+ *
+ * This function sets the iconification callback of the specified window, which
+ * is called when the window is iconified or restored.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @wayland The wl_shell protocol has no concept of iconification,
+ * this callback will never be called when using this deprecated protocol.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);
+
+/*! @brief Sets the maximize callback for the specified window.
+ *
+ * This function sets the maximization callback of the specified window, which
+ * is called when the window is maximized or restored.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_maximize
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun cbfun);
+
+/*! @brief Sets the framebuffer resize callback for the specified window.
+ *
+ * This function sets the framebuffer resize callback of the specified window,
+ * which is called when the framebuffer of the specified window is resized.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_fbsize
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
+
+/*! @brief Sets the window content scale callback for the specified window.
+ *
+ * This function sets the window content scale callback of the specified window,
+ * which is called when the content scale of the specified window changes.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_scale
+ * @sa @ref glfwGetWindowContentScale
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun);
+
+/*! @brief Processes all pending events.
+ *
+ * This function processes only those events that are already in the event
+ * queue and then returns immediately. Processing events will cause the window
+ * and input callbacks associated with those events to be called.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * Do not assume that callbacks you set will _only_ be called in response to
+ * event processing functions like this one. While it is necessary to poll for
+ * events, window systems that require GLFW to register callbacks of its own
+ * can pass events to GLFW in response to many window system function calls.
+ * GLFW will pass those events on to the application callbacks before
+ * returning.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwWaitEvents
+ * @sa @ref glfwWaitEventsTimeout
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwPollEvents(void);
+
+/*! @brief Waits until events are queued and processes them.
+ *
+ * This function puts the calling thread to sleep until at least one event is
+ * available in the event queue. Once one or more events are available,
+ * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue
+ * are processed and the function then returns immediately. Processing events
+ * will cause the window and input callbacks associated with those events to be
+ * called.
+ *
+ * Since not all events are associated with callbacks, this function may return
+ * without a callback having been called even if you are monitoring all
+ * callbacks.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * Do not assume that callbacks you set will _only_ be called in response to
+ * event processing functions like this one. While it is necessary to poll for
+ * events, window systems that require GLFW to register callbacks of its own
+ * can pass events to GLFW in response to many window system function calls.
+ * GLFW will pass those events on to the application callbacks before
+ * returning.
+ *
+ * If no windows exist, this function returns immediately. For synchronization
+ * of threads in applications that do not create windows, use your threading
+ * library of choice.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwPollEvents
+ * @sa @ref glfwWaitEventsTimeout
+ *
+ * @since Added in version 2.5.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWaitEvents(void);
+
+/*! @brief Waits with timeout until events are queued and processes them.
+ *
+ * This function puts the calling thread to sleep until at least one event is
+ * available in the event queue, or until the specified timeout is reached. If
+ * one or more events are available, it behaves exactly like @ref
+ * glfwPollEvents, i.e. the events in the queue are processed and the function
+ * then returns immediately. Processing events will cause the window and input
+ * callbacks associated with those events to be called.
+ *
+ * The timeout value must be a positive finite number.
+ *
+ * Since not all events are associated with callbacks, this function may return
+ * without a callback having been called even if you are monitoring all
+ * callbacks.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * Do not assume that callbacks you set will _only_ be called in response to
+ * event processing functions like this one. While it is necessary to poll for
+ * events, window systems that require GLFW to register callbacks of its own
+ * can pass events to GLFW in response to many window system function calls.
+ * GLFW will pass those events on to the application callbacks before
+ * returning.
+ *
+ * If no windows exist, this function returns immediately. For synchronization
+ * of threads in applications that do not create windows, use your threading
+ * library of choice.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @param[in] timeout The maximum amount of time, in seconds, to wait.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwPollEvents
+ * @sa @ref glfwWaitEvents
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWaitEventsTimeout(double timeout);
+
+/*! @brief Posts an empty event to the event queue.
+ *
+ * This function posts an empty event from the current thread to the event
+ * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return.
+ *
+ * If no windows exist, this function returns immediately. For synchronization
+ * of threads in applications that do not create windows, use your threading
+ * library of choice.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref events
+ * @sa @ref glfwWaitEvents
+ * @sa @ref glfwWaitEventsTimeout
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwPostEmptyEvent(void);
+
+/*! @brief Returns the value of an input option for the specified window.
+ *
+ * This function returns the value of an input option for the specified window.
+ * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
+ * @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS.
+ *
+ * @param[in] window The window to query.
+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
+ * `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref glfwSetInputMode
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
+
+/*! @brief Sets an input option for the specified window.
+ *
+ * This function sets an input mode option for the specified window. The mode
+ * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
+ * @ref GLFW_STICKY_MOUSE_BUTTONS or @ref GLFW_LOCK_KEY_MODS.
+ *
+ * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
+ * modes:
+ * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.
+ * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client
+ * area of the window but does not restrict the cursor from leaving.
+ * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
+ * and unlimited cursor movement. This is useful for implementing for
+ * example 3D camera controls.
+ *
+ * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
+ * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
+ * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`
+ * the next time it is called even if the key had been released before the
+ * call. This is useful when you are only interested in whether keys have been
+ * pressed but not when or in which order.
+ *
+ * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either
+ * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it.
+ * If sticky mouse buttons are enabled, a mouse button press will ensure that
+ * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even
+ * if the mouse button had been released before the call. This is useful when
+ * you are only interested in whether mouse buttons have been pressed but not
+ * when or in which order.
+ *
+ * If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
+ * enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled,
+ * callbacks that receive modifier bits will also have the @ref
+ * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
+ * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
+ *
+ * @param[in] window The window whose input mode to set.
+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
+ * `GLFW_STICKY_MOUSE_BUTTONS` or `GLFW_LOCK_KEY_MODS`.
+ * @param[in] value The new value of the specified input mode.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref glfwGetInputMode
+ *
+ * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
+
+/*! @brief Returns the layout-specific name of the specified printable key.
+ *
+ * This function returns the name of the specified printable key, encoded as
+ * UTF-8. This is typically the character that key would produce without any
+ * modifier keys, intended for displaying key bindings to the user. For dead
+ * keys, it is typically the diacritic it would add to a character.
+ *
+ * __Do not use this function__ for [text input](@ref input_char). You will
+ * break text input for many languages even if it happens to work for yours.
+ *
+ * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key,
+ * otherwise the scancode is ignored. If you specify a non-printable key, or
+ * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this
+ * function returns `NULL` but does not emit an error.
+ *
+ * This behavior allows you to always pass in the arguments in the
+ * [key callback](@ref input_key) without modification.
+ *
+ * The printable keys are:
+ * - `GLFW_KEY_APOSTROPHE`
+ * - `GLFW_KEY_COMMA`
+ * - `GLFW_KEY_MINUS`
+ * - `GLFW_KEY_PERIOD`
+ * - `GLFW_KEY_SLASH`
+ * - `GLFW_KEY_SEMICOLON`
+ * - `GLFW_KEY_EQUAL`
+ * - `GLFW_KEY_LEFT_BRACKET`
+ * - `GLFW_KEY_RIGHT_BRACKET`
+ * - `GLFW_KEY_BACKSLASH`
+ * - `GLFW_KEY_WORLD_1`
+ * - `GLFW_KEY_WORLD_2`
+ * - `GLFW_KEY_0` to `GLFW_KEY_9`
+ * - `GLFW_KEY_A` to `GLFW_KEY_Z`
+ * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`
+ * - `GLFW_KEY_KP_DECIMAL`
+ * - `GLFW_KEY_KP_DIVIDE`
+ * - `GLFW_KEY_KP_MULTIPLY`
+ * - `GLFW_KEY_KP_SUBTRACT`
+ * - `GLFW_KEY_KP_ADD`
+ * - `GLFW_KEY_KP_EQUAL`
+ *
+ * Names for printable keys depend on keyboard layout, while names for
+ * non-printable keys are the same across layouts but depend on the application
+ * language and should be localized along with other user interface text.
+ *
+ * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
+ * @param[in] scancode The scancode of the key to query.
+ * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetKeyName, or until the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key_name
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetKeyName(int key, int scancode);
+
+/*! @brief Returns the platform-specific scancode of the specified key.
+ *
+ * This function returns the platform-specific scancode of the specified key.
+ *
+ * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this
+ * method will return `-1`.
+ *
+ * @param[in] key Any [named key](@ref keys).
+ * @return The platform-specific scancode for the key, or `-1` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetKeyScancode(int key);
+
+/*! @brief Returns the last reported state of a keyboard key for the specified
+ * window.
+ *
+ * This function returns the last state reported for the specified key to the
+ * specified window. The returned state is one of `GLFW_PRESS` or
+ * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to
+ * the key callback.
+ *
+ * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns
+ * `GLFW_PRESS` the first time you call it for a key that was pressed, even if
+ * that key has already been released.
+ *
+ * The key functions deal with physical keys, with [key tokens](@ref keys)
+ * named after their use on the standard US keyboard layout. If you want to
+ * input text, use the Unicode character callback instead.
+ *
+ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be
+ * used with this function.
+ *
+ * __Do not use this function__ to implement [text input](@ref input_char).
+ *
+ * @param[in] window The desired window.
+ * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is
+ * not a valid key for this function.
+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
+
+/*! @brief Returns the last reported state of a mouse button for the specified
+ * window.
+ *
+ * This function returns the last state reported for the specified mouse button
+ * to the specified window. The returned state is one of `GLFW_PRESS` or
+ * `GLFW_RELEASE`.
+ *
+ * If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function
+ * returns `GLFW_PRESS` the first time you call it for a mouse button that was
+ * pressed, even if that mouse button has already been released.
+ *
+ * @param[in] window The desired window.
+ * @param[in] button The desired [mouse button](@ref buttons).
+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_mouse_button
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
+
+/*! @brief Retrieves the position of the cursor relative to the client area of
+ * the window.
+ *
+ * This function returns the position of the cursor, in screen coordinates,
+ * relative to the upper-left corner of the client area of the specified
+ * window.
+ *
+ * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
+ * position is unbounded and limited only by the minimum and maximum values of
+ * a `double`.
+ *
+ * The coordinate can be converted to their integer equivalents with the
+ * `floor` function. Casting directly to an integer type works for positive
+ * coordinates, but fails for negative ones.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] window The desired window.
+ * @param[out] xpos Where to store the cursor x-coordinate, relative to the
+ * left edge of the client area, or `NULL`.
+ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to
+ * top edge of the client area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ * @sa @ref glfwSetCursorPos
+ *
+ * @since Added in version 3.0. Replaces `glfwGetMousePos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
+
+/*! @brief Sets the position of the cursor, relative to the client area of the
+ * window.
+ *
+ * This function sets the position, in screen coordinates, of the cursor
+ * relative to the upper-left corner of the client area of the specified
+ * window. The window must have input focus. If the window does not have
+ * input focus when this function is called, it fails silently.
+ *
+ * __Do not use this function__ to implement things like camera controls. GLFW
+ * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the
+ * cursor, transparently re-centers it and provides unconstrained cursor
+ * motion. See @ref glfwSetInputMode for more information.
+ *
+ * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is
+ * unconstrained and limited only by the minimum and maximum values of
+ * a `double`.
+ *
+ * @param[in] window The desired window.
+ * @param[in] xpos The desired x-coordinate, relative to the left edge of the
+ * client area.
+ * @param[in] ypos The desired y-coordinate, relative to the top edge of the
+ * client area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @wayland This function will only work when the cursor mode is
+ * `GLFW_CURSOR_DISABLED`, otherwise it will do nothing.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ * @sa @ref glfwGetCursorPos
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMousePos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
+
+/*! @brief Creates a custom cursor.
+ *
+ * Creates a new custom cursor image that can be set for a window with @ref
+ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
+ * Any remaining cursors are destroyed by @ref glfwTerminate.
+ *
+ * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+ * bits per channel with the red channel first. They are arranged canonically
+ * as packed sequential rows, starting from the top-left corner.
+ *
+ * The cursor hotspot is specified in pixels, relative to the upper-left corner
+ * of the cursor image. Like all other coordinate systems in GLFW, the X-axis
+ * points to the right and the Y-axis points down.
+ *
+ * @param[in] image The desired cursor image.
+ * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot.
+ * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.
+ * @return The handle of the created cursor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified image data is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa @ref glfwDestroyCursor
+ * @sa @ref glfwCreateStandardCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);
+
+/*! @brief Creates a cursor with a standard shape.
+ *
+ * Returns a cursor with a [standard shape](@ref shapes), that can be set for
+ * a window with @ref glfwSetCursor.
+ *
+ * @param[in] shape One of the [standard shapes](@ref shapes).
+ * @return A new cursor ready to use or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa @ref glfwCreateCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
+
+/*! @brief Destroys a cursor.
+ *
+ * This function destroys a cursor previously created with @ref
+ * glfwCreateCursor. Any remaining cursors will be destroyed by @ref
+ * glfwTerminate.
+ *
+ * If the specified cursor is current for any window, that window will be
+ * reverted to the default cursor. This does not affect the cursor mode.
+ *
+ * @param[in] cursor The cursor object to destroy.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa @ref glfwCreateCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
+
+/*! @brief Sets the cursor for the window.
+ *
+ * This function sets the cursor image to be used when the cursor is over the
+ * client area of the specified window. The set cursor will only be visible
+ * when the [cursor mode](@ref cursor_mode) of the window is
+ * `GLFW_CURSOR_NORMAL`.
+ *
+ * On some platforms, the set cursor may not be visible unless the window also
+ * has input focus.
+ *
+ * @param[in] window The window to set the cursor for.
+ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default
+ * arrow cursor.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
+
+/*! @brief Sets the key callback.
+ *
+ * This function sets the key callback of the specified window, which is called
+ * when a key is pressed, repeated or released.
+ *
+ * The key functions deal with physical keys, with layout independent
+ * [key tokens](@ref keys) named after their values in the standard US keyboard
+ * layout. If you want to input text, use the
+ * [character callback](@ref glfwSetCharCallback) instead.
+ *
+ * When a window loses input focus, it will generate synthetic key release
+ * events for all pressed keys. You can tell these events from user-generated
+ * events by the fact that the synthetic ones are generated after the focus
+ * loss event has been processed, i.e. after the
+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
+ *
+ * The scancode of a key is specific to that platform or sometimes even to that
+ * machine. Scancodes are intended to allow users to bind keys that don't have
+ * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their
+ * state is not saved and so it cannot be queried with @ref glfwGetKey.
+ *
+ * Sometimes GLFW needs to generate synthetic key events, in which case the
+ * scancode may be zero.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new key callback, or `NULL` to remove the currently
+ * set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
+
+/*! @brief Sets the Unicode character callback.
+ *
+ * This function sets the character callback of the specified window, which is
+ * called when a Unicode character is input.
+ *
+ * The character callback is intended for Unicode text input. As it deals with
+ * characters, it is keyboard layout dependent, whereas the
+ * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1
+ * to physical keys, as a key may produce zero, one or more characters. If you
+ * want to know whether a specific physical key was pressed or released, see
+ * the key callback instead.
+ *
+ * The character callback behaves as system text input normally does and will
+ * not be called if modifier keys are held down that would prevent normal text
+ * input on that platform, for example a Super (Command) key on macOS or Alt key
+ * on Windows.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_char
+ *
+ * @since Added in version 2.4.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);
+
+/*! @brief Sets the Unicode character with modifiers callback.
+ *
+ * This function sets the character with modifiers callback of the specified
+ * window, which is called when a Unicode character is input regardless of what
+ * modifier keys are used.
+ *
+ * The character with modifiers callback is intended for implementing custom
+ * Unicode character input. For regular Unicode text input, see the
+ * [character callback](@ref glfwSetCharCallback). Like the character
+ * callback, the character with modifiers callback deals with characters and is
+ * keyboard layout dependent. Characters do not map 1:1 to physical keys, as
+ * a key may produce zero, one or more characters. If you want to know whether
+ * a specific physical key was pressed or released, see the
+ * [key callback](@ref glfwSetKeyCallback) instead.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or an
+ * [error](@ref error_handling) occurred.
+ *
+ * @deprecated Scheduled for removal in version 4.0.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_char
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun);
+
+/*! @brief Sets the mouse button callback.
+ *
+ * This function sets the mouse button callback of the specified window, which
+ * is called when a mouse button is pressed or released.
+ *
+ * When a window loses input focus, it will generate synthetic mouse button
+ * release events for all pressed mouse buttons. You can tell these events
+ * from user-generated events by the fact that the synthetic ones are generated
+ * after the focus loss event has been processed, i.e. after the
+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_mouse_button
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun);
+
+/*! @brief Sets the cursor position callback.
+ *
+ * This function sets the cursor position callback of the specified window,
+ * which is called when the cursor is moved. The callback is provided with the
+ * position, in screen coordinates, relative to the upper-left corner of the
+ * client area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun);
+
+/*! @brief Sets the cursor enter/exit callback.
+ *
+ * This function sets the cursor boundary crossing callback of the specified
+ * window, which is called when the cursor enters or leaves the client area of
+ * the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_enter
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun);
+
+/*! @brief Sets the scroll callback.
+ *
+ * This function sets the scroll callback of the specified window, which is
+ * called when a scrolling device is used, such as a mouse wheel or scrolling
+ * area of a touchpad.
+ *
+ * The scroll callback receives all scrolling input, like that from a mouse
+ * wheel or a touchpad scrolling area.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently
+ * set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref scrolling
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun);
+
+/*! @brief Sets the file drop callback.
+ *
+ * This function sets the file drop callback of the specified window, which is
+ * called when one or more dragged files are dropped on the window.
+ *
+ * Because the path array and its strings may have been generated specifically
+ * for that event, they are not guaranteed to be valid after the callback has
+ * returned. If you wish to use them after the callback returns, you need to
+ * make a deep copy.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new file drop callback, or `NULL` to remove the
+ * currently set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @wayland File drop is currently unimplemented.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref path_drop
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
+
+/*! @brief Returns whether the specified joystick is present.
+ *
+ * This function returns whether the specified joystick is present.
+ *
+ * There is no need to call this function before other functions that accept
+ * a joystick ID, as they all check for presence before performing any other
+ * work.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick
+ *
+ * @since Added in version 3.0. Replaces `glfwGetJoystickParam`.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwJoystickPresent(int jid);
+
+/*! @brief Returns the values of all axes of the specified joystick.
+ *
+ * This function returns the values of all axes of the specified joystick.
+ * Each element in the array is a value between -1.0 and 1.0.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of axis values in the returned
+ * array. This is set to zero if the joystick is not present or an error
+ * occurred.
+ * @return An array of axis values, or `NULL` if the joystick is not present or
+ * an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_axis
+ *
+ * @since Added in version 3.0. Replaces `glfwGetJoystickPos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
+
+/*! @brief Returns the state of all buttons of the specified joystick.
+ *
+ * This function returns the state of all buttons of the specified joystick.
+ * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * For backward compatibility with earlier versions that did not have @ref
+ * glfwGetJoystickHats, the button array also includes all hats, each
+ * represented as four buttons. The hats are in the same order as returned by
+ * __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and
+ * _left_. To disable these extra buttons, set the @ref
+ * GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of button states in the returned
+ * array. This is set to zero if the joystick is not present or an error
+ * occurred.
+ * @return An array of button states, or `NULL` if the joystick is not present
+ * or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_button
+ *
+ * @since Added in version 2.2.
+ * @glfw3 Changed to return a dynamic array.
+ *
+ * @ingroup input
+ */
+GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
+
+/*! @brief Returns the state of all hats of the specified joystick.
+ *
+ * This function returns the state of all hats of the specified joystick.
+ * Each element in the array is one of the following values:
+ *
+ * Name | Value
+ * ---- | -----
+ * `GLFW_HAT_CENTERED` | 0
+ * `GLFW_HAT_UP` | 1
+ * `GLFW_HAT_RIGHT` | 2
+ * `GLFW_HAT_DOWN` | 4
+ * `GLFW_HAT_LEFT` | 8
+ * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
+ * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
+ * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
+ * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
+ *
+ * The diagonal directions are bitwise combinations of the primary (up, right,
+ * down and left) directions and you can test for these individually by ANDing
+ * it with the corresponding direction.
+ *
+ * @code
+ * if (hats[2] & GLFW_HAT_RIGHT)
+ * {
+ * // State of hat 2 could be right-up, right or right-down
+ * }
+ * @endcode
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of hat states in the returned
+ * array. This is set to zero if the joystick is not present or an error
+ * occurred.
+ * @return An array of hat states, or `NULL` if the joystick is not present
+ * or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, this function is called again for that joystick or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_hat
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count);
+
+/*! @brief Returns the name of the specified joystick.
+ *
+ * This function returns the name, encoded as UTF-8, of the specified joystick.
+ * The returned string is allocated and freed by GLFW. You should not free it
+ * yourself.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
+ * is not present or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_name
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetJoystickName(int jid);
+
+/*! @brief Returns the SDL comaptible GUID of the specified joystick.
+ *
+ * This function returns the SDL compatible GUID, as a UTF-8 encoded
+ * hexadecimal string, of the specified joystick. The returned string is
+ * allocated and freed by GLFW. You should not free it yourself.
+ *
+ * The GUID is what connects a joystick to a gamepad mapping. A connected
+ * joystick will always have a GUID even if there is no gamepad mapping
+ * assigned to it.
+ *
+ * If the specified joystick is not present this function will return `NULL`
+ * but will not generate an error. This can be used instead of first calling
+ * @ref glfwJoystickPresent.
+ *
+ * The GUID uses the format introduced in SDL 2.0.5. This GUID tries to
+ * uniquely identify the make and model of a joystick but does not identify
+ * a specific unit, e.g. all wired Xbox 360 controllers will have the same
+ * GUID on that platform. The GUID for a unit may vary between platforms
+ * depending on what hardware information the platform specific APIs provide.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded GUID of the joystick, or `NULL` if the joystick
+ * is not present or an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetJoystickGUID(int jid);
+
+/*! @brief Sets the user pointer of the specified joystick.
+ *
+ * This function sets the user-defined pointer of the specified joystick. The
+ * current value is retained until the joystick is disconnected. The initial
+ * value is `NULL`.
+ *
+ * This function may be called from the joystick callback, even for a joystick
+ * that is being disconnected.
+ *
+ * @param[in] jid The joystick whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref joystick_userptr
+ * @sa @ref glfwGetJoystickUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
+
+/*! @brief Returns the user pointer of the specified joystick.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified joystick. The initial value is `NULL`.
+ *
+ * This function may be called from the joystick callback, even for a joystick
+ * that is being disconnected.
+ *
+ * @param[in] jid The joystick whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref joystick_userptr
+ * @sa @ref glfwSetJoystickUserPointer
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI void* glfwGetJoystickUserPointer(int jid);
+
+/*! @brief Returns whether the specified joystick has a gamepad mapping.
+ *
+ * This function returns whether the specified joystick is both present and has
+ * a gamepad mapping.
+ *
+ * If the specified joystick is present but does not have a gamepad mapping
+ * this function will return `GLFW_FALSE` but will not generate an error. Call
+ * @ref glfwJoystickPresent to check if a joystick is present regardless of
+ * whether it has a mapping.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
+ * or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwGetGamepadState
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwJoystickIsGamepad(int jid);
+
+/*! @brief Sets the joystick configuration callback.
+ *
+ * This function sets the joystick configuration callback, or removes the
+ * currently set callback. This is called when a joystick is connected to or
+ * disconnected from the system.
+ *
+ * For joystick connection and disconnection events to be delivered on all
+ * platforms, you need to call one of the [event processing](@ref events)
+ * functions. Joystick disconnection may also be detected and the callback
+ * called by joystick functions. The function will then return whatever it
+ * returns if the joystick is not present.
+ *
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_event
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
+
+/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings.
+ *
+ * This function parses the specified ASCII encoded string and updates the
+ * internal list with any gamepad mappings it finds. This string may
+ * contain either a single gamepad mapping or many mappings separated by
+ * newlines. The parser supports the full format of the `gamecontrollerdb.txt`
+ * source file including empty lines and comments.
+ *
+ * See @ref gamepad_mapping for a description of the format.
+ *
+ * If there is already a gamepad mapping for a given GUID in the internal list,
+ * it will be replaced by the one passed to this function. If the library is
+ * terminated and re-initialized the internal list will revert to the built-in
+ * default.
+ *
+ * @param[in] string The string containing the gamepad mappings.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwJoystickIsGamepad
+ * @sa @ref glfwGetGamepadName
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwUpdateGamepadMappings(const char* string);
+
+/*! @brief Returns the human-readable gamepad name for the specified joystick.
+ *
+ * This function returns the human-readable name of the gamepad from the
+ * gamepad mapping assigned to the specified joystick.
+ *
+ * If the specified joystick is not present or does not have a gamepad mapping
+ * this function will return `NULL` but will not generate an error. Call
+ * @ref glfwJoystickPresent to check whether it is present regardless of
+ * whether it has a mapping.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded name of the gamepad, or `NULL` if the
+ * joystick is not present, does not have a mapping or an
+ * [error](@ref error_handling) occurred.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, the gamepad mappings are updated or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwJoystickIsGamepad
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetGamepadName(int jid);
+
+/*! @brief Retrieves the state of the specified joystick remapped as a gamepad.
+ *
+ * This function retrives the state of the specified joystick remapped to
+ * an Xbox-like gamepad.
+ *
+ * If the specified joystick is not present or does not have a gamepad mapping
+ * this function will return `GLFW_FALSE` but will not generate an error. Call
+ * @ref glfwJoystickPresent to check whether it is present regardless of
+ * whether it has a mapping.
+ *
+ * The Guide button may not be available for input as it is often hooked by the
+ * system or the Steam client.
+ *
+ * Not all devices have all the buttons or axes provided by @ref
+ * GLFWgamepadstate. Unavailable buttons and axes will always report
+ * `GLFW_RELEASE` and 0.0 respectively.
+ *
+ * @param[in] jid The [joystick](@ref joysticks) to query.
+ * @param[out] state The gamepad input state of the joystick.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is
+ * connected, it has no gamepad mapping or an [error](@ref error_handling)
+ * occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref gamepad
+ * @sa @ref glfwUpdateGamepadMappings
+ * @sa @ref glfwJoystickIsGamepad
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
+
+/*! @brief Sets the clipboard to the specified string.
+ *
+ * This function sets the system clipboard to the specified, UTF-8 encoded
+ * string.
+ *
+ * @param[in] window Deprecated. Any valid window or `NULL`.
+ * @param[in] string A UTF-8 encoded string.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa @ref glfwGetClipboardString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
+
+/*! @brief Returns the contents of the clipboard as a string.
+ *
+ * This function returns the contents of the system clipboard, if it contains
+ * or is convertible to a UTF-8 encoded string. If the clipboard is empty or
+ * if its contents cannot be converted, `NULL` is returned and a @ref
+ * GLFW_FORMAT_UNAVAILABLE error is generated.
+ *
+ * @param[in] window Deprecated. Any valid window or `NULL`.
+ * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa @ref glfwSetClipboardString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
+
+/*! @brief Returns the value of the GLFW timer.
+ *
+ * This function returns the value of the GLFW timer. Unless the timer has
+ * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW
+ * was initialized.
+ *
+ * The resolution of the timer is system dependent, but is usually on the order
+ * of a few micro- or nanoseconds. It uses the highest-resolution monotonic
+ * time source on each supported platform.
+ *
+ * @return The current value, in seconds, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Reading and
+ * writing of the internal timer offset is not atomic, so it needs to be
+ * externally synchronized with calls to @ref glfwSetTime.
+ *
+ * @sa @ref time
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI double glfwGetTime(void);
+
+/*! @brief Sets the GLFW timer.
+ *
+ * This function sets the value of the GLFW timer. It then continues to count
+ * up from that value. The value must be a positive finite number less than
+ * or equal to 18446744073.0, which is approximately 584.5 years.
+ *
+ * @param[in] time The new value, in seconds.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @remark The upper limit of the timer is calculated as
+ * floor((2<sup>64</sup> - 1) / 10<sup>9</sup>) and is due to implementations
+ * storing nanoseconds in 64 bits. The limit may be increased in the future.
+ *
+ * @thread_safety This function may be called from any thread. Reading and
+ * writing of the internal timer offset is not atomic, so it needs to be
+ * externally synchronized with calls to @ref glfwGetTime.
+ *
+ * @sa @ref time
+ *
+ * @since Added in version 2.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetTime(double time);
+
+/*! @brief Returns the current value of the raw timer.
+ *
+ * This function returns the current value of the raw timer, measured in
+ * 1&nbsp;/&nbsp;frequency seconds. To get the frequency, call @ref
+ * glfwGetTimerFrequency.
+ *
+ * @return The value of the timer, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref time
+ * @sa @ref glfwGetTimerFrequency
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI uint64_t glfwGetTimerValue(void);
+
+/*! @brief Returns the frequency, in Hz, of the raw timer.
+ *
+ * This function returns the frequency, in Hz, of the raw timer.
+ *
+ * @return The frequency of the timer, in Hz, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref time
+ * @sa @ref glfwGetTimerValue
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI uint64_t glfwGetTimerFrequency(void);
+
+/*! @brief Makes the context of the specified window current for the calling
+ * thread.
+ *
+ * This function makes the OpenGL or OpenGL ES context of the specified window
+ * current on the calling thread. A context must only be made current on
+ * a single thread at a time and each thread can have only a single current
+ * context at a time.
+ *
+ * When moving a context between threads, you must make it non-current on the
+ * old thread before making it current on the new one.
+ *
+ * By default, making a context non-current implicitly forces a pipeline flush.
+ * On machines that support `GL_KHR_context_flush_control`, you can control
+ * whether a context performs this flush by setting the
+ * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint)
+ * hint.
+ *
+ * The specified window must have an OpenGL or OpenGL ES context. Specifying
+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
+ * error.
+ *
+ * @param[in] window The window whose context to make current, or `NULL` to
+ * detach the current context.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_current
+ * @sa @ref glfwGetCurrentContext
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);
+
+/*! @brief Returns the window whose context is current on the calling thread.
+ *
+ * This function returns the window whose OpenGL or OpenGL ES context is
+ * current on the calling thread.
+ *
+ * @return The window whose context is current, or `NULL` if no window's
+ * context is current.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_current
+ * @sa @ref glfwMakeContextCurrent
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
+
+/*! @brief Swaps the front and back buffers of the specified window.
+ *
+ * This function swaps the front and back buffers of the specified window when
+ * rendering with OpenGL or OpenGL ES. If the swap interval is greater than
+ * zero, the GPU driver waits the specified number of screen updates before
+ * swapping the buffers.
+ *
+ * The specified window must have an OpenGL or OpenGL ES context. Specifying
+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
+ * error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see `vkQueuePresentKHR` instead.
+ *
+ * @param[in] window The window whose buffers to swap.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark __EGL:__ The context of the specified window must be current on the
+ * calling thread.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref buffer_swap
+ * @sa @ref glfwSwapInterval
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
+
+/*! @brief Sets the swap interval for the current context.
+ *
+ * This function sets the swap interval for the current OpenGL or OpenGL ES
+ * context, i.e. the number of screen updates to wait from the time @ref
+ * glfwSwapBuffers was called before swapping the buffers and returning. This
+ * is sometimes called _vertical synchronization_, _vertical retrace
+ * synchronization_ or just _vsync_.
+ *
+ * A context that supports either of the `WGL_EXT_swap_control_tear` and
+ * `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap
+ * intervals, which allows the driver to swap immediately even if a frame
+ * arrives a little bit late. You can check for these extensions with @ref
+ * glfwExtensionSupported.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see the present mode of your swapchain instead.
+ *
+ * @param[in] interval The minimum number of screen updates to wait for
+ * until the buffers are swapped by @ref glfwSwapBuffers.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark This function is not called during context creation, leaving the
+ * swap interval set to whatever is the default on that platform. This is done
+ * because some swap interval extensions used by GLFW do not allow the swap
+ * interval to be reset to zero once it has been set to a non-zero value.
+ *
+ * @remark Some GPU drivers do not honor the requested swap interval, either
+ * because of a user setting that overrides the application's request or due to
+ * bugs in the driver.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref buffer_swap
+ * @sa @ref glfwSwapBuffers
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI void glfwSwapInterval(int interval);
+
+/*! @brief Returns whether the specified extension is available.
+ *
+ * This function returns whether the specified
+ * [API extension](@ref context_glext) is supported by the current OpenGL or
+ * OpenGL ES context. It searches both for client API extension and context
+ * creation API extensions.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * As this functions retrieves and searches one or more extension strings each
+ * call, it is recommended that you cache its results if it is going to be used
+ * frequently. The extension strings will not change during the lifetime of
+ * a context, so there is no danger in doing this.
+ *
+ * This function does not apply to Vulkan. If you are using Vulkan, see @ref
+ * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties`
+ * and `vkEnumerateDeviceExtensionProperties` instead.
+ *
+ * @param[in] extension The ASCII encoded name of the extension.
+ * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
+ * otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_glext
+ * @sa @ref glfwGetProcAddress
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI int glfwExtensionSupported(const char* extension);
+
+/*! @brief Returns the address of the specified function for the current
+ * context.
+ *
+ * This function returns the address of the specified OpenGL or OpenGL ES
+ * [core or extension function](@ref context_glext), if it is supported
+ * by the current context.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and
+ * `vkGetDeviceProcAddr` instead.
+ *
+ * @param[in] procname The ASCII encoded name of the function.
+ * @return The address of the function, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark The address of a given function is not guaranteed to be the same
+ * between contexts.
+ *
+ * @remark This function may return a non-`NULL` address despite the
+ * associated version or extension not being available. Always check the
+ * context version or extension string first.
+ *
+ * @pointer_lifetime The returned function pointer is valid until the context
+ * is destroyed or the library is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_glext
+ * @sa @ref glfwExtensionSupported
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
+
+/*! @brief Returns whether the Vulkan loader and an ICD have been found.
+ *
+ * This function returns whether the Vulkan loader and any minimally functional
+ * ICD have been found.
+ *
+ * The availability of a Vulkan loader and even an ICD does not by itself
+ * guarantee that surface creation or even instance creation is possible.
+ * For example, on Fermi systems Nvidia will install an ICD that provides no
+ * actual Vulkan support. Call @ref glfwGetRequiredInstanceExtensions to check
+ * whether the extensions necessary for Vulkan surface creation are available
+ * and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue
+ * family of a physical device supports image presentation.
+ *
+ * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE`
+ * otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_support
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI int glfwVulkanSupported(void);
+
+/*! @brief Returns the Vulkan instance extensions required by GLFW.
+ *
+ * This function returns an array of names of Vulkan instance extensions required
+ * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the
+ * list will always contains `VK_KHR_surface`, so if you don't require any
+ * additional extensions you can pass this list directly to the
+ * `VkInstanceCreateInfo` struct.
+ *
+ * If Vulkan is not available on the machine, this function returns `NULL` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is at least minimally available.
+ *
+ * If Vulkan is available but no set of extensions allowing window surface
+ * creation was found, this function returns `NULL`. You may still use Vulkan
+ * for off-screen rendering and compute work.
+ *
+ * @param[out] count Where to store the number of extensions in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of ASCII encoded extension names, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_API_UNAVAILABLE.
+ *
+ * @remark Additional extensions may be required by future versions of GLFW.
+ * You should check if any extensions you wish to enable are already in the
+ * returned array, as it is an error to specify an extension more than once in
+ * the `VkInstanceCreateInfo` struct.
+ *
+ * @remark @macos This function currently only supports the
+ * `VK_MVK_macos_surface` extension from MoltenVK.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * library is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_ext
+ * @sa @ref glfwCreateWindowSurface
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count);
+
+#if defined(VK_VERSION_1_0)
+
+/*! @brief Returns the address of the specified Vulkan instance function.
+ *
+ * This function returns the address of the specified Vulkan core or extension
+ * function for the specified instance. If instance is set to `NULL` it can
+ * return any function exported from the Vulkan loader, including at least the
+ * following functions:
+ *
+ * - `vkEnumerateInstanceExtensionProperties`
+ * - `vkEnumerateInstanceLayerProperties`
+ * - `vkCreateInstance`
+ * - `vkGetInstanceProcAddr`
+ *
+ * If Vulkan is not available on the machine, this function returns `NULL` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is at least minimally available.
+ *
+ * This function is equivalent to calling `vkGetInstanceProcAddr` with
+ * a platform-specific query of the Vulkan loader as a fallback.
+ *
+ * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve
+ * functions related to instance creation.
+ * @param[in] procname The ASCII encoded name of the function.
+ * @return The address of the function, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_API_UNAVAILABLE.
+ *
+ * @pointer_lifetime The returned function pointer is valid until the library
+ * is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_proc
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname);
+
+/*! @brief Returns whether the specified queue family can present images.
+ *
+ * This function returns whether the specified queue family of the specified
+ * physical device supports presentation to the platform GLFW was built for.
+ *
+ * If Vulkan or the required window surface creation instance extensions are
+ * not available on the machine, or if the specified instance was not created
+ * with the required extensions, this function returns `GLFW_FALSE` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is at least minimally available and @ref
+ * glfwGetRequiredInstanceExtensions to check what instance extensions are
+ * required.
+ *
+ * @param[in] instance The instance that the physical device belongs to.
+ * @param[in] device The physical device that the queue family belongs to.
+ * @param[in] queuefamily The index of the queue family to query.
+ * @return `GLFW_TRUE` if the queue family supports presentation, or
+ * `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @macos This function currently always returns `GLFW_TRUE`, as the
+ * `VK_MVK_macos_surface` extension does not provide
+ * a `vkGetPhysicalDevice*PresentationSupport` type function.
+ *
+ * @thread_safety This function may be called from any thread. For
+ * synchronization details of Vulkan objects, see the Vulkan specification.
+ *
+ * @sa @ref vulkan_present
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
+
+/*! @brief Creates a Vulkan surface for the specified window.
+ *
+ * This function creates a Vulkan surface for the specified window.
+ *
+ * If the Vulkan loader or at least one minimally functional ICD were not found,
+ * this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref
+ * GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported to check whether
+ * Vulkan is at least minimally available.
+ *
+ * If the required window surface creation instance extensions are not
+ * available or if the specified instance was not created with these extensions
+ * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref
+ * glfwGetRequiredInstanceExtensions to check what instance extensions are
+ * required.
+ *
+ * The window surface cannot be shared with another API so the window must
+ * have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib)
+ * set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error
+ * and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`.
+ *
+ * The window surface must be destroyed before the specified Vulkan instance.
+ * It is the responsibility of the caller to destroy the window surface. GLFW
+ * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the
+ * surface.
+ *
+ * @param[in] instance The Vulkan instance to create the surface in.
+ * @param[in] window The window to create the surface for.
+ * @param[in] allocator The allocator to use, or `NULL` to use the default
+ * allocator.
+ * @param[out] surface Where to store the handle of the surface. This is set
+ * to `VK_NULL_HANDLE` if an error occurred.
+ * @return `VK_SUCCESS` if successful, or a Vulkan error code if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE
+ *
+ * @remark If an error occurs before the creation call is made, GLFW returns
+ * the Vulkan error code most appropriate for the error. Appropriate use of
+ * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
+ * eliminate almost all occurrences of these errors.
+ *
+ * @remark @macos This function currently only supports the
+ * `VK_MVK_macos_surface` extension from MoltenVK.
+ *
+ * @remark @macos This function creates and sets a `CAMetalLayer` instance for
+ * the window content view, which is required for MoltenVK to function.
+ *
+ * @thread_safety This function may be called from any thread. For
+ * synchronization details of Vulkan objects, see the Vulkan specification.
+ *
+ * @sa @ref vulkan_surface
+ * @sa @ref glfwGetRequiredInstanceExtensions
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+
+#endif /*VK_VERSION_1_0*/
+
+
+/*************************************************************************
+ * Global definition cleanup
+ *************************************************************************/
+
+/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
+
+#ifdef GLFW_WINGDIAPI_DEFINED
+ #undef WINGDIAPI
+ #undef GLFW_WINGDIAPI_DEFINED
+#endif
+
+#ifdef GLFW_CALLBACK_DEFINED
+ #undef CALLBACK
+ #undef GLFW_CALLBACK_DEFINED
+#endif
+
+/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally
+ * defined by some gl.h variants (OpenBSD) so define it after if needed.
+ */
+#ifndef GLAPIENTRY
+ #define GLAPIENTRY APIENTRY
+#endif
+
+/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_h_ */
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3native.h b/Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3native.h
new file mode 100644
index 0000000..6bddc43
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/include/GLFW/glfw3native.h
@@ -0,0 +1,525 @@
+/*************************************************************************
+ * GLFW 3.3 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would
+ * be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ *************************************************************************/
+
+#ifndef _glfw3_native_h_
+#define _glfw3_native_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Doxygen documentation
+ *************************************************************************/
+
+/*! @file glfw3native.h
+ * @brief The header of the native access functions.
+ *
+ * This is the header file of the native access functions. See @ref native for
+ * more information.
+ */
+/*! @defgroup native Native access
+ * @brief Functions related to accessing native handles.
+ *
+ * **By using the native access functions you assert that you know what you're
+ * doing and how to fix problems caused by using them. If you don't, you
+ * shouldn't be using them.**
+ *
+ * Before the inclusion of @ref glfw3native.h, you may define zero or more
+ * window system API macro and zero or more context creation API macros.
+ *
+ * The chosen backends must match those the library was compiled for. Failure
+ * to do this will cause a link-time error.
+ *
+ * The available window API macros are:
+ * * `GLFW_EXPOSE_NATIVE_WIN32`
+ * * `GLFW_EXPOSE_NATIVE_COCOA`
+ * * `GLFW_EXPOSE_NATIVE_X11`
+ * * `GLFW_EXPOSE_NATIVE_WAYLAND`
+ *
+ * The available context API macros are:
+ * * `GLFW_EXPOSE_NATIVE_WGL`
+ * * `GLFW_EXPOSE_NATIVE_NSGL`
+ * * `GLFW_EXPOSE_NATIVE_GLX`
+ * * `GLFW_EXPOSE_NATIVE_EGL`
+ * * `GLFW_EXPOSE_NATIVE_OSMESA`
+ *
+ * These macros select which of the native access functions that are declared
+ * and which platform-specific headers to include. It is then up your (by
+ * definition platform-specific) code to handle which of these should be
+ * defined.
+ */
+
+
+/*************************************************************************
+ * System headers and types
+ *************************************************************************/
+
+#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
+ // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
+ // example to allow applications to correctly declare a GL_ARB_debug_output
+ // callback) but windows.h assumes no one will define APIENTRY before it does
+ #if defined(GLFW_APIENTRY_DEFINED)
+ #undef APIENTRY
+ #undef GLFW_APIENTRY_DEFINED
+ #endif
+ #include <windows.h>
+#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
+ #if defined(__OBJC__)
+ #import <Cocoa/Cocoa.h>
+ #else
+ #include <ApplicationServices/ApplicationServices.h>
+ typedef void* id;
+ #endif
+#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
+ #include <X11/Xlib.h>
+ #include <X11/extensions/Xrandr.h>
+#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+ #include <wayland-client.h>
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WGL)
+ /* WGL is declared by windows.h */
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_NSGL)
+ /* NSGL is declared by Cocoa.h */
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_GLX)
+ #include <GL/glx.h>
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_EGL)
+ #include <EGL/egl.h>
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
+ #include <GL/osmesa.h>
+#endif
+
+
+/*************************************************************************
+ * Functions
+ *************************************************************************/
+
+#if defined(GLFW_EXPOSE_NATIVE_WIN32)
+/*! @brief Returns the adapter device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
+ * of the specified monitor, or `NULL` if an [error](@ref error_handling)
+ * occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the display device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded display device name (for example
+ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `HWND` of the specified window.
+ *
+ * @return The `HWND` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WGL)
+/*! @brief Returns the `HGLRC` of the specified window.
+ *
+ * @return The `HGLRC` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_COCOA)
+/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
+ *
+ * @return The `CGDirectDisplayID` of the specified monitor, or
+ * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `NSWindow` of the specified window.
+ *
+ * @return The `NSWindow` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_NSGL)
+/*! @brief Returns the `NSOpenGLContext` of the specified window.
+ *
+ * @return The `NSOpenGLContext` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_X11)
+/*! @brief Returns the `Display` used by GLFW.
+ *
+ * @return The `Display` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI Display* glfwGetX11Display(void);
+
+/*! @brief Returns the `RRCrtc` of the specified monitor.
+ *
+ * @return The `RRCrtc` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the `RROutput` of the specified monitor.
+ *
+ * @return The `RROutput` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `Window` of the specified window.
+ *
+ * @return The `Window` of the specified window, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
+
+/*! @brief Sets the current primary selection to the specified string.
+ *
+ * @param[in] string A UTF-8 encoded string.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa glfwGetX11SelectionString
+ * @sa glfwSetClipboardString
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI void glfwSetX11SelectionString(const char* string);
+
+/*! @brief Returns the contents of the current primary selection as a string.
+ *
+ * If the selection is empty or if its contents cannot be converted, `NULL`
+ * is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
+ *
+ * @return The contents of the selection as a UTF-8 encoded string, or `NULL`
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
+ * library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa glfwSetX11SelectionString
+ * @sa glfwGetClipboardString
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetX11SelectionString(void);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_GLX)
+/*! @brief Returns the `GLXContext` of the specified window.
+ *
+ * @return The `GLXContext` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
+
+/*! @brief Returns the `GLXWindow` of the specified window.
+ *
+ * @return The `GLXWindow` of the specified window, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+/*! @brief Returns the `struct wl_display*` used by GLFW.
+ *
+ * @return The `struct wl_display*` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
+
+/*! @brief Returns the `struct wl_output*` of the specified monitor.
+ *
+ * @return The `struct wl_output*` of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the main `struct wl_surface*` of the specified window.
+ *
+ * @return The main `struct wl_surface*` of the specified window, or `NULL` if
+ * an [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_EGL)
+/*! @brief Returns the `EGLDisplay` used by GLFW.
+ *
+ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
+
+/*! @brief Returns the `EGLContext` of the specified window.
+ *
+ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
+
+/*! @brief Returns the `EGLSurface` of the specified window.
+ *
+ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
+/*! @brief Retrieves the color buffer associated with the specified window.
+ *
+ * @param[in] window The window whose color buffer to retrieve.
+ * @param[out] width Where to store the width of the color buffer, or `NULL`.
+ * @param[out] height Where to store the height of the color buffer, or `NULL`.
+ * @param[out] format Where to store the OSMesa pixel format of the color
+ * buffer, or `NULL`.
+ * @param[out] buffer Where to store the address of the color buffer, or
+ * `NULL`.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
+
+/*! @brief Retrieves the depth buffer associated with the specified window.
+ *
+ * @param[in] window The window whose depth buffer to retrieve.
+ * @param[out] width Where to store the width of the depth buffer, or `NULL`.
+ * @param[out] height Where to store the height of the depth buffer, or `NULL`.
+ * @param[out] bytesPerValue Where to store the number of bytes per depth
+ * buffer element, or `NULL`.
+ * @param[out] buffer Where to store the address of the depth buffer, or
+ * `NULL`.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
+
+/*! @brief Returns the `OSMesaContext` of the specified window.
+ *
+ * @return The `OSMesaContext` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.3.
+ *
+ * @ingroup native
+ */
+GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_native_h_ */
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_init.m b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_init.m
new file mode 100644
index 0000000..f3c4795
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_init.m
@@ -0,0 +1,403 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+#include <sys/param.h> // For MAXPATHLEN
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
+ #define NSEventMaskKeyUp NSKeyUpMask
+ #define NSEventModifierFlagCommand NSCommandKeyMask
+#endif
+
+// Change to our application bundle's resources directory, if present
+//
+static void changeToResourcesDirectory(void)
+{
+ char resourcesPath[MAXPATHLEN];
+
+ CFBundleRef bundle = CFBundleGetMainBundle();
+ if (!bundle)
+ return;
+
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
+
+ CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
+ if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
+ {
+ CFRelease(last);
+ CFRelease(resourcesURL);
+ return;
+ }
+
+ CFRelease(last);
+
+ if (!CFURLGetFileSystemRepresentation(resourcesURL,
+ true,
+ (UInt8*) resourcesPath,
+ MAXPATHLEN))
+ {
+ CFRelease(resourcesURL);
+ return;
+ }
+
+ CFRelease(resourcesURL);
+
+ chdir(resourcesPath);
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode;
+
+ memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
+ memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
+
+ _glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
+ _glfw.ns.keycodes[0x12] = GLFW_KEY_1;
+ _glfw.ns.keycodes[0x13] = GLFW_KEY_2;
+ _glfw.ns.keycodes[0x14] = GLFW_KEY_3;
+ _glfw.ns.keycodes[0x15] = GLFW_KEY_4;
+ _glfw.ns.keycodes[0x17] = GLFW_KEY_5;
+ _glfw.ns.keycodes[0x16] = GLFW_KEY_6;
+ _glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
+ _glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
+ _glfw.ns.keycodes[0x19] = GLFW_KEY_9;
+ _glfw.ns.keycodes[0x00] = GLFW_KEY_A;
+ _glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
+ _glfw.ns.keycodes[0x08] = GLFW_KEY_C;
+ _glfw.ns.keycodes[0x02] = GLFW_KEY_D;
+ _glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
+ _glfw.ns.keycodes[0x03] = GLFW_KEY_F;
+ _glfw.ns.keycodes[0x05] = GLFW_KEY_G;
+ _glfw.ns.keycodes[0x04] = GLFW_KEY_H;
+ _glfw.ns.keycodes[0x22] = GLFW_KEY_I;
+ _glfw.ns.keycodes[0x26] = GLFW_KEY_J;
+ _glfw.ns.keycodes[0x28] = GLFW_KEY_K;
+ _glfw.ns.keycodes[0x25] = GLFW_KEY_L;
+ _glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
+ _glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
+ _glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
+ _glfw.ns.keycodes[0x23] = GLFW_KEY_P;
+ _glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
+ _glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
+ _glfw.ns.keycodes[0x01] = GLFW_KEY_S;
+ _glfw.ns.keycodes[0x11] = GLFW_KEY_T;
+ _glfw.ns.keycodes[0x20] = GLFW_KEY_U;
+ _glfw.ns.keycodes[0x09] = GLFW_KEY_V;
+ _glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
+ _glfw.ns.keycodes[0x07] = GLFW_KEY_X;
+ _glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
+ _glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
+
+ _glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
+ _glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
+ _glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
+ _glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
+ _glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
+ _glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
+ _glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
+ _glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
+ _glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
+
+ _glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
+ _glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
+ _glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
+ _glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
+ _glfw.ns.keycodes[0x77] = GLFW_KEY_END;
+ _glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
+ _glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
+ _glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
+ _glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
+ _glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
+ _glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
+ _glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
+ _glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
+ _glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
+ _glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
+ _glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
+ _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
+ _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
+ _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
+ _glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
+ _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
+ _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
+ _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
+ _glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
+ _glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
+ _glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
+ _glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
+ _glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
+ _glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
+ _glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
+ _glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
+ _glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
+ _glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
+ _glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
+ _glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
+ _glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
+ _glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
+ _glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
+ _glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
+ _glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
+ _glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
+
+ _glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
+ _glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
+ _glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
+ _glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
+ _glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
+ _glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
+ _glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
+ _glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
+ _glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
+ _glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
+ _glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
+ _glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
+ _glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
+ _glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
+ _glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
+ _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
+
+ for (scancode = 0; scancode < 256; scancode++)
+ {
+ // Store the reverse translation for faster key name lookup
+ if (_glfw.ns.keycodes[scancode] >= 0)
+ _glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
+ }
+}
+
+// Retrieve Unicode data for the current keyboard layout
+//
+static GLFWbool updateUnicodeDataNS(void)
+{
+ if (_glfw.ns.inputSource)
+ {
+ CFRelease(_glfw.ns.inputSource);
+ _glfw.ns.inputSource = NULL;
+ _glfw.ns.unicodeData = nil;
+ }
+
+ _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource();
+ if (!_glfw.ns.inputSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve keyboard layout input source");
+ return GLFW_FALSE;
+ }
+
+ _glfw.ns.unicodeData =
+ TISGetInputSourceProperty(_glfw.ns.inputSource,
+ kTISPropertyUnicodeKeyLayoutData);
+ if (!_glfw.ns.unicodeData)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve keyboard layout Unicode data");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Load HIToolbox.framework and the TIS symbols we need from it
+//
+static GLFWbool initializeTIS(void)
+{
+ // This works only because Cocoa has already loaded it properly
+ _glfw.ns.tis.bundle =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
+ if (!_glfw.ns.tis.bundle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to load HIToolbox.framework");
+ return GLFW_FALSE;
+ }
+
+ CFStringRef* kPropertyUnicodeKeyLayoutData =
+ CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("kTISPropertyUnicodeKeyLayoutData"));
+ _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
+ _glfw.ns.tis.GetInputSourceProperty =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("TISGetInputSourceProperty"));
+ _glfw.ns.tis.GetKbdType =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("LMGetKbdType"));
+
+ if (!kPropertyUnicodeKeyLayoutData ||
+ !TISCopyCurrentKeyboardLayoutInputSource ||
+ !TISGetInputSourceProperty ||
+ !LMGetKbdType)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to load TIS API symbols");
+ return GLFW_FALSE;
+ }
+
+ _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
+ *kPropertyUnicodeKeyLayoutData;
+
+ return updateUnicodeDataNS();
+}
+
+@interface GLFWHelper : NSObject
+@end
+
+@implementation GLFWHelper
+
+- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
+{
+ updateUnicodeDataNS();
+}
+
+- (void)doNothing:(id)object
+{
+}
+
+@end // GLFWHelper
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+ _glfw.ns.helper = [[GLFWHelper alloc] init];
+
+ [NSThread detachNewThreadSelector:@selector(doNothing:)
+ toTarget:_glfw.ns.helper
+ withObject:nil];
+
+ [NSApplication sharedApplication];
+
+ NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
+ {
+ if ([event modifierFlags] & NSEventModifierFlagCommand)
+ [[NSApp keyWindow] sendEvent:event];
+
+ return event;
+ };
+
+ _glfw.ns.keyUpMonitor =
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
+ handler:block];
+
+ if (_glfw.hints.init.ns.chdir)
+ changeToResourcesDirectory();
+
+ [[NSNotificationCenter defaultCenter]
+ addObserver:_glfw.ns.helper
+ selector:@selector(selectedKeyboardInputSourceChanged:)
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+
+ createKeyTables();
+
+ _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+ if (!_glfw.ns.eventSource)
+ return GLFW_FALSE;
+
+ CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
+
+ if (!initializeTIS())
+ return GLFW_FALSE;
+
+ _glfwInitTimerNS();
+ _glfwInitJoysticksNS();
+
+ _glfwPollMonitorsNS();
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ if (_glfw.ns.inputSource)
+ {
+ CFRelease(_glfw.ns.inputSource);
+ _glfw.ns.inputSource = NULL;
+ _glfw.ns.unicodeData = nil;
+ }
+
+ if (_glfw.ns.eventSource)
+ {
+ CFRelease(_glfw.ns.eventSource);
+ _glfw.ns.eventSource = NULL;
+ }
+
+ if (_glfw.ns.delegate)
+ {
+ [NSApp setDelegate:nil];
+ [_glfw.ns.delegate release];
+ _glfw.ns.delegate = nil;
+ }
+
+ if (_glfw.ns.helper)
+ {
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:_glfw.ns.helper
+ name:NSTextInputContextKeyboardSelectionDidChangeNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:_glfw.ns.helper];
+ [_glfw.ns.helper release];
+ _glfw.ns.helper = nil;
+ }
+
+ if (_glfw.ns.keyUpMonitor)
+ [NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
+
+ free(_glfw.ns.clipboardString);
+
+ _glfwTerminateNSGL();
+ _glfwTerminateJoysticksNS();
+
+ [_glfw.ns.autoreleasePool release];
+ _glfw.ns.autoreleasePool = nil;
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Cocoa NSGL"
+#if defined(_GLFW_BUILD_DLL)
+ " dynamic"
+#endif
+ ;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.h b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.h
new file mode 100644
index 0000000..d18d032
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.h
@@ -0,0 +1,50 @@
+//========================================================================
+// GLFW 3.3 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDKeys.h>
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
+
+#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
+
+// Cocoa-specific per-joystick data
+//
+typedef struct _GLFWjoystickNS
+{
+ IOHIDDeviceRef device;
+ CFMutableArrayRef axes;
+ CFMutableArrayRef buttons;
+ CFMutableArrayRef hats;
+} _GLFWjoystickNS;
+
+
+void _glfwInitJoysticksNS(void);
+void _glfwTerminateJoysticksNS(void);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.m b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.m
new file mode 100644
index 0000000..0831809
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_joystick.m
@@ -0,0 +1,462 @@
+//========================================================================
+// GLFW 3.3 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
+
+
+// Joystick element information
+//
+typedef struct _GLFWjoyelementNS
+{
+ IOHIDElementRef native;
+ uint32_t usage;
+ int index;
+ long minimum;
+ long maximum;
+
+} _GLFWjoyelementNS;
+
+
+// Returns the value of the specified element of the specified joystick
+//
+static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
+{
+ IOHIDValueRef valueRef;
+ long value = 0;
+
+ if (js->ns.device)
+ {
+ if (IOHIDDeviceGetValue(js->ns.device,
+ element->native,
+ &valueRef) == kIOReturnSuccess)
+ {
+ value = IOHIDValueGetIntegerValue(valueRef);
+ }
+ }
+
+ return value;
+}
+
+// Comparison function for matching the SDL element order
+//
+static CFComparisonResult compareElements(const void* fp,
+ const void* sp,
+ void* user)
+{
+ const _GLFWjoyelementNS* fe = fp;
+ const _GLFWjoyelementNS* se = sp;
+ if (fe->usage < se->usage)
+ return kCFCompareLessThan;
+ if (fe->usage > se->usage)
+ return kCFCompareGreaterThan;
+ if (fe->index < se->index)
+ return kCFCompareLessThan;
+ if (fe->index > se->index)
+ return kCFCompareGreaterThan;
+ return kCFCompareEqualTo;
+}
+
+// Removes the specified joystick
+//
+static void closeJoystick(_GLFWjoystick* js)
+{
+ int i;
+
+ if (!js->present)
+ return;
+
+ for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
+ free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
+ CFRelease(js->ns.axes);
+
+ for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
+ free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
+ CFRelease(js->ns.buttons);
+
+ for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
+ free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
+ CFRelease(js->ns.hats);
+
+ _glfwFreeJoystick(js);
+ _glfwInputJoystick(js, GLFW_DISCONNECTED);
+}
+
+// Callback for user-initiated joystick addition
+//
+static void matchCallback(void* context,
+ IOReturn result,
+ void* sender,
+ IOHIDDeviceRef device)
+{
+ int jid;
+ char name[256];
+ char guid[33];
+ CFIndex i;
+ CFTypeRef property;
+ uint32_t vendor = 0, product = 0, version = 0;
+ _GLFWjoystick* js;
+ CFMutableArrayRef axes, buttons, hats;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ if (_glfw.joysticks[jid].ns.device == device)
+ return;
+ }
+
+ axes = CFArrayCreateMutable(NULL, 0, NULL);
+ buttons = CFArrayCreateMutable(NULL, 0, NULL);
+ hats = CFArrayCreateMutable(NULL, 0, NULL);
+
+ property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
+ if (property)
+ {
+ CFStringGetCString(property,
+ name,
+ sizeof(name),
+ kCFStringEncodingUTF8);
+ }
+ else
+ strncpy(name, "Unknown", sizeof(name));
+
+ property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
+ if (property)
+ CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
+
+ property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
+ if (property)
+ CFNumberGetValue(property, kCFNumberSInt32Type, &product);
+
+ property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
+ if (property)
+ CFNumberGetValue(property, kCFNumberSInt32Type, &version);
+
+ // Generate a joystick GUID that matches the SDL 2.0.5+ one
+ if (vendor && product)
+ {
+ sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
+ (uint8_t) vendor, (uint8_t) (vendor >> 8),
+ (uint8_t) product, (uint8_t) (product >> 8),
+ (uint8_t) version, (uint8_t) (version >> 8));
+ }
+ else
+ {
+ sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
+ name[0], name[1], name[2], name[3],
+ name[4], name[5], name[6], name[7],
+ name[8], name[9], name[10]);
+ }
+
+ CFArrayRef elements =
+ IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
+
+ for (i = 0; i < CFArrayGetCount(elements); i++)
+ {
+ IOHIDElementRef native = (IOHIDElementRef)
+ CFArrayGetValueAtIndex(elements, i);
+ if (CFGetTypeID(native) != IOHIDElementGetTypeID())
+ continue;
+
+ const IOHIDElementType type = IOHIDElementGetType(native);
+ if ((type != kIOHIDElementTypeInput_Axis) &&
+ (type != kIOHIDElementTypeInput_Button) &&
+ (type != kIOHIDElementTypeInput_Misc))
+ {
+ continue;
+ }
+
+ CFMutableArrayRef target = NULL;
+
+ const uint32_t usage = IOHIDElementGetUsage(native);
+ const uint32_t page = IOHIDElementGetUsagePage(native);
+ if (page == kHIDPage_GenericDesktop)
+ {
+ switch (usage)
+ {
+ case kHIDUsage_GD_X:
+ case kHIDUsage_GD_Y:
+ case kHIDUsage_GD_Z:
+ case kHIDUsage_GD_Rx:
+ case kHIDUsage_GD_Ry:
+ case kHIDUsage_GD_Rz:
+ case kHIDUsage_GD_Slider:
+ case kHIDUsage_GD_Dial:
+ case kHIDUsage_GD_Wheel:
+ target = axes;
+ break;
+ case kHIDUsage_GD_Hatswitch:
+ target = hats;
+ break;
+ }
+ }
+ else if (page == kHIDPage_Button)
+ target = buttons;
+
+ if (target)
+ {
+ _GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
+ element->native = native;
+ element->usage = usage;
+ element->index = (int) CFArrayGetCount(target);
+ element->minimum = IOHIDElementGetLogicalMin(native);
+ element->maximum = IOHIDElementGetLogicalMax(native);
+ CFArrayAppendValue(target, element);
+ }
+ }
+
+ CFRelease(elements);
+
+ CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
+ compareElements, NULL);
+ CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
+ compareElements, NULL);
+ CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
+ compareElements, NULL);
+
+ js = _glfwAllocJoystick(name, guid,
+ (int) CFArrayGetCount(axes),
+ (int) CFArrayGetCount(buttons),
+ (int) CFArrayGetCount(hats));
+
+ js->ns.device = device;
+ js->ns.axes = axes;
+ js->ns.buttons = buttons;
+ js->ns.hats = hats;
+
+ _glfwInputJoystick(js, GLFW_CONNECTED);
+}
+
+// Callback for user-initiated joystick removal
+//
+static void removeCallback(void* context,
+ IOReturn result,
+ void* sender,
+ IOHIDDeviceRef device)
+{
+ int jid;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ if (_glfw.joysticks[jid].ns.device == device)
+ {
+ closeJoystick(_glfw.joysticks + jid);
+ break;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+void _glfwInitJoysticksNS(void)
+{
+ CFMutableArrayRef matching;
+ const long usages[] =
+ {
+ kHIDUsage_GD_Joystick,
+ kHIDUsage_GD_GamePad,
+ kHIDUsage_GD_MultiAxisController
+ };
+
+ _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
+ kIOHIDOptionsTypeNone);
+
+ matching = CFArrayCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeArrayCallBacks);
+ if (!matching)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
+ return;
+ }
+
+ for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
+ {
+ const long page = kHIDPage_GenericDesktop;
+
+ CFMutableDictionaryRef dict =
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ if (!dict)
+ continue;
+
+ CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
+ kCFNumberLongType,
+ &page);
+ CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
+ kCFNumberLongType,
+ &usages[i]);
+ if (pageRef && usageRef)
+ {
+ CFDictionarySetValue(dict,
+ CFSTR(kIOHIDDeviceUsagePageKey),
+ pageRef);
+ CFDictionarySetValue(dict,
+ CFSTR(kIOHIDDeviceUsageKey),
+ usageRef);
+ CFArrayAppendValue(matching, dict);
+ }
+
+ if (pageRef)
+ CFRelease(pageRef);
+ if (usageRef)
+ CFRelease(usageRef);
+
+ CFRelease(dict);
+ }
+
+ IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
+ CFRelease(matching);
+
+ IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
+ &matchCallback, NULL);
+ IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
+ &removeCallback, NULL);
+ IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
+ CFRunLoopGetMain(),
+ kCFRunLoopDefaultMode);
+ IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
+
+ // Execute the run loop once in order to register any initially-attached
+ // joysticks
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksNS(void)
+{
+ int jid;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ closeJoystick(_glfw.joysticks + jid);
+
+ CFRelease(_glfw.ns.hidManager);
+ _glfw.ns.hidManager = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+ if (mode & _GLFW_POLL_AXES)
+ {
+ CFIndex i;
+
+ for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
+ {
+ _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
+ CFArrayGetValueAtIndex(js->ns.axes, i);
+
+ const long raw = getElementValue(js, axis);
+ // Perform auto calibration
+ if (raw < axis->minimum)
+ axis->minimum = raw;
+ if (raw > axis->maximum)
+ axis->maximum = raw;
+
+ const long delta = axis->maximum - axis->minimum;
+ if (delta == 0)
+ _glfwInputJoystickAxis(js, (int) i, 0.f);
+ else
+ {
+ const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
+ _glfwInputJoystickAxis(js, (int) i, value);
+ }
+ }
+ }
+
+ if (mode & _GLFW_POLL_BUTTONS)
+ {
+ CFIndex i;
+
+ for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
+ {
+ _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
+ CFArrayGetValueAtIndex(js->ns.buttons, i);
+ const char value = getElementValue(js, button) - button->minimum;
+ _glfwInputJoystickButton(js, (int) i, value);
+ }
+
+ for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
+ {
+ const int states[9] =
+ {
+ GLFW_HAT_UP,
+ GLFW_HAT_RIGHT_UP,
+ GLFW_HAT_RIGHT,
+ GLFW_HAT_RIGHT_DOWN,
+ GLFW_HAT_DOWN,
+ GLFW_HAT_LEFT_DOWN,
+ GLFW_HAT_LEFT,
+ GLFW_HAT_LEFT_UP,
+ GLFW_HAT_CENTERED
+ };
+
+ _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
+ CFArrayGetValueAtIndex(js->ns.hats, i);
+ long state = getElementValue(js, hat) - hat->minimum;
+ if (state < 0 || state > 8)
+ state = 8;
+
+ _glfwInputJoystickHat(js, (int) i, states[state]);
+ }
+ }
+
+ return js->present;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+ if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
+ (strncmp(guid + 20, "000000000000", 12) == 0))
+ {
+ char original[33];
+ strcpy(original, guid);
+ sprintf(guid, "03000000%.4s0000%.4s000000000000",
+ original, original + 16);
+ }
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_monitor.m b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_monitor.m
new file mode 100644
index 0000000..39fff6f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_monitor.m
@@ -0,0 +1,527 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <IOKit/graphics/IOGraphicsLib.h>
+#include <CoreVideo/CVBase.h>
+#include <CoreVideo/CVDisplayLink.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+
+// Get the name of the specified display, or NULL
+//
+static char* getDisplayName(CGDirectDisplayID displayID)
+{
+ io_iterator_t it;
+ io_service_t service;
+ CFDictionaryRef info;
+
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault,
+ IOServiceMatching("IODisplayConnect"),
+ &it) != 0)
+ {
+ // This may happen if a desktop Mac is running headless
+ return NULL;
+ }
+
+ while ((service = IOIteratorNext(it)) != 0)
+ {
+ info = IODisplayCreateInfoDictionary(service,
+ kIODisplayOnlyPreferredName);
+
+ CFNumberRef vendorIDRef =
+ CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
+ CFNumberRef productIDRef =
+ CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
+ if (!vendorIDRef || !productIDRef)
+ {
+ CFRelease(info);
+ continue;
+ }
+
+ unsigned int vendorID, productID;
+ CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
+ CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
+
+ if (CGDisplayVendorNumber(displayID) == vendorID &&
+ CGDisplayModelNumber(displayID) == productID)
+ {
+ // Info dictionary is used and freed below
+ break;
+ }
+
+ CFRelease(info);
+ }
+
+ IOObjectRelease(it);
+
+ if (!service)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to find service port for display");
+ return NULL;
+ }
+
+ CFDictionaryRef names =
+ CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
+
+ CFStringRef nameRef;
+
+ if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
+ (const void**) &nameRef))
+ {
+ // This may happen if a desktop Mac is running headless
+ CFRelease(info);
+ return NULL;
+ }
+
+ const CFIndex size =
+ CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
+ kCFStringEncodingUTF8);
+ char* name = calloc(size + 1, 1);
+ CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
+
+ CFRelease(info);
+ return name;
+}
+
+// Check whether the display mode should be included in enumeration
+//
+static GLFWbool modeIsGood(CGDisplayModeRef mode)
+{
+ uint32_t flags = CGDisplayModeGetIOFlags(mode);
+
+ if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
+ return GLFW_FALSE;
+ if (flags & kDisplayModeInterlacedFlag)
+ return GLFW_FALSE;
+ if (flags & kDisplayModeStretchedFlag)
+ return GLFW_FALSE;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
+ CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+ if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
+ CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
+ {
+ CFRelease(format);
+ return GLFW_FALSE;
+ }
+
+ CFRelease(format);
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+ return GLFW_TRUE;
+}
+
+// Convert Core Graphics display mode to GLFW video mode
+//
+static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
+ CVDisplayLinkRef link)
+{
+ GLFWvidmode result;
+ result.width = (int) CGDisplayModeGetWidth(mode);
+ result.height = (int) CGDisplayModeGetHeight(mode);
+ result.refreshRate = (int) CGDisplayModeGetRefreshRate(mode);
+
+ if (result.refreshRate == 0)
+ {
+ const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
+ if (!(time.flags & kCVTimeIsIndefinite))
+ result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
+ }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
+ CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+ if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
+ {
+ result.redBits = 5;
+ result.greenBits = 5;
+ result.blueBits = 5;
+ }
+ else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+ {
+ result.redBits = 8;
+ result.greenBits = 8;
+ result.blueBits = 8;
+ }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
+ CFRelease(format);
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+ return result;
+}
+
+// Starts reservation for display fading
+//
+static CGDisplayFadeReservationToken beginFadeReservation(void)
+{
+ CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
+
+ if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
+ {
+ CGDisplayFade(token, 0.3,
+ kCGDisplayBlendNormal,
+ kCGDisplayBlendSolidColor,
+ 0.0, 0.0, 0.0,
+ TRUE);
+ }
+
+ return token;
+}
+
+// Ends reservation for display fading
+//
+static void endFadeReservation(CGDisplayFadeReservationToken token)
+{
+ if (token != kCGDisplayFadeReservationInvalidToken)
+ {
+ CGDisplayFade(token, 0.5,
+ kCGDisplayBlendSolidColor,
+ kCGDisplayBlendNormal,
+ 0.0, 0.0, 0.0,
+ FALSE);
+ CGReleaseDisplayFadeReservation(token);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Poll for changes in the set of connected monitors
+//
+void _glfwPollMonitorsNS(void)
+{
+ uint32_t i, j, displayCount, disconnectedCount;
+ CGDirectDisplayID* displays;
+ _GLFWmonitor** disconnected = NULL;
+
+ CGGetOnlineDisplayList(0, NULL, &displayCount);
+ displays = calloc(displayCount, sizeof(CGDirectDisplayID));
+ CGGetOnlineDisplayList(displayCount, displays, &displayCount);
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ _glfw.monitors[i]->ns.screen = nil;
+
+ disconnectedCount = _glfw.monitorCount;
+ if (disconnectedCount)
+ {
+ disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
+ memcpy(disconnected,
+ _glfw.monitors,
+ _glfw.monitorCount * sizeof(_GLFWmonitor*));
+ }
+
+ for (i = 0; i < displayCount; i++)
+ {
+ _GLFWmonitor* monitor;
+ const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
+
+ if (CGDisplayIsAsleep(displays[i]))
+ continue;
+
+ for (j = 0; j < disconnectedCount; j++)
+ {
+ // HACK: Compare unit numbers instead of display IDs to work around
+ // display replacement on machines with automatic graphics
+ // switching
+ if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
+ {
+ disconnected[j] = NULL;
+ break;
+ }
+ }
+
+ const CGSize size = CGDisplayScreenSize(displays[i]);
+ char* name = getDisplayName(displays[i]);
+ if (!name)
+ name = _glfw_strdup("Unknown");
+
+ monitor = _glfwAllocMonitor(name, size.width, size.height);
+ monitor->ns.displayID = displays[i];
+ monitor->ns.unitNumber = unitNumber;
+
+ free(name);
+
+ _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
+ }
+
+ for (i = 0; i < disconnectedCount; i++)
+ {
+ if (disconnected[i])
+ _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
+ }
+
+ free(disconnected);
+ free(displays);
+}
+
+// Change the current video mode
+//
+void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+ CFArrayRef modes;
+ CFIndex count, i;
+ CVDisplayLinkRef link;
+ CGDisplayModeRef native = NULL;
+ GLFWvidmode current;
+ const GLFWvidmode* best;
+
+ best = _glfwChooseVideoMode(monitor, desired);
+ _glfwPlatformGetVideoMode(monitor, &current);
+ if (_glfwCompareVideoModes(&current, best) == 0)
+ return;
+
+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
+
+ modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
+ count = CFArrayGetCount(modes);
+
+ for (i = 0; i < count; i++)
+ {
+ CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+ if (!modeIsGood(dm))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
+ if (_glfwCompareVideoModes(best, &mode) == 0)
+ {
+ native = dm;
+ break;
+ }
+ }
+
+ if (native)
+ {
+ if (monitor->ns.previousMode == NULL)
+ monitor->ns.previousMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
+
+ CGDisplayFadeReservationToken token = beginFadeReservation();
+ CGDisplaySetDisplayMode(monitor->ns.displayID, native, NULL);
+ endFadeReservation(token);
+ }
+
+ CFRelease(modes);
+ CVDisplayLinkRelease(link);
+}
+
+// Restore the previously saved (original) video mode
+//
+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
+{
+ if (monitor->ns.previousMode)
+ {
+ CGDisplayFadeReservationToken token = beginFadeReservation();
+ CGDisplaySetDisplayMode(monitor->ns.displayID,
+ monitor->ns.previousMode, NULL);
+ endFadeReservation(token);
+
+ CGDisplayModeRelease(monitor->ns.previousMode);
+ monitor->ns.previousMode = NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
+
+ if (xpos)
+ *xpos = (int) bounds.origin.x;
+ if (ypos)
+ *ypos = (int) bounds.origin.y;
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+ float* xscale, float* yscale)
+{
+ if (!monitor->ns.screen)
+ {
+ NSUInteger i;
+ NSArray* screens = [NSScreen screens];
+
+ for (i = 0; i < [screens count]; i++)
+ {
+ NSScreen* screen = [screens objectAtIndex:i];
+ NSNumber* displayID =
+ [[screen deviceDescription] objectForKey:@"NSScreenNumber"];
+
+ // HACK: Compare unit numbers instead of display IDs to work around
+ // display replacement on machines with automatic graphics
+ // switching
+ if (monitor->ns.unitNumber ==
+ CGDisplayUnitNumber([displayID unsignedIntValue]))
+ {
+ monitor->ns.screen = screen;
+ break;
+ }
+ }
+
+ if (i == [screens count])
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to find a screen for monitor");
+ return;
+ }
+ }
+
+ const NSRect points = [monitor->ns.screen frame];
+ const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
+
+ if (xscale)
+ *xscale = (float) (pixels.size.width / points.size.width);
+ if (yscale)
+ *yscale = (float) (pixels.size.height / points.size.height);
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+ CFArrayRef modes;
+ CFIndex found, i, j;
+ GLFWvidmode* result;
+ CVDisplayLinkRef link;
+
+ *count = 0;
+
+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
+
+ modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
+ found = CFArrayGetCount(modes);
+ result = calloc(found, sizeof(GLFWvidmode));
+
+ for (i = 0; i < found; i++)
+ {
+ CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+ if (!modeIsGood(dm))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
+
+ for (j = 0; j < *count; j++)
+ {
+ if (_glfwCompareVideoModes(result + j, &mode) == 0)
+ break;
+ }
+
+ // Skip duplicate modes
+ if (i < *count)
+ continue;
+
+ (*count)++;
+ result[*count - 1] = mode;
+ }
+
+ CFRelease(modes);
+ CVDisplayLinkRelease(link);
+ return result;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
+{
+ CGDisplayModeRef displayMode;
+ CVDisplayLinkRef link;
+
+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
+
+ displayMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
+ *mode = vidmodeFromCGDisplayMode(displayMode, link);
+ CGDisplayModeRelease(displayMode);
+
+ CVDisplayLinkRelease(link);
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
+ CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
+
+ CGGetDisplayTransferByTable(monitor->ns.displayID,
+ size,
+ values,
+ values + size,
+ values + size * 2,
+ &size);
+
+ _glfwAllocGammaArrays(ramp, size);
+
+ for (i = 0; i < size; i++)
+ {
+ ramp->red[i] = (unsigned short) (values[i] * 65535);
+ ramp->green[i] = (unsigned short) (values[i + size] * 65535);
+ ramp->blue[i] = (unsigned short) (values[i + size * 2] * 65535);
+ }
+
+ free(values);
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ int i;
+ CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
+
+ for (i = 0; i < ramp->size; i++)
+ {
+ values[i] = ramp->red[i] / 65535.f;
+ values[i + ramp->size] = ramp->green[i] / 65535.f;
+ values[i + ramp->size * 2] = ramp->blue[i] / 65535.f;
+ }
+
+ CGSetDisplayTransferByTable(monitor->ns.displayID,
+ ramp->size,
+ values,
+ values + ramp->size,
+ values + ramp->size * 2);
+
+ free(values);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay);
+ return monitor->ns.displayID;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_platform.h b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_platform.h
new file mode 100644
index 0000000..13adaa9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_platform.h
@@ -0,0 +1,169 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <stdint.h>
+#include <dlfcn.h>
+
+#include <Carbon/Carbon.h>
+#if defined(__OBJC__)
+#import <Cocoa/Cocoa.h>
+#else
+typedef void* id;
+#endif
+
+typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
+
+typedef struct VkMacOSSurfaceCreateInfoMVK
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkMacOSSurfaceCreateFlagsMVK flags;
+ const void* pView;
+} VkMacOSSurfaceCreateInfoMVK;
+
+typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+
+#include "posix_thread.h"
+#include "cocoa_joystick.h"
+#include "nsgl_context.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+
+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+#define _glfw_dlclose(handle) dlclose(handle)
+#define _glfw_dlsym(handle, name) dlsym(handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.view)
+#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
+#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
+
+// HIToolbox.framework pointer typedefs
+#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
+typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
+#define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource
+typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
+#define TISGetInputSourceProperty _glfw.ns.tis.GetInputSourceProperty
+typedef UInt8 (*PFN_LMGetKbdType)(void);
+#define LMGetKbdType _glfw.ns.tis.GetKbdType
+
+
+// Cocoa-specific per-window data
+//
+typedef struct _GLFWwindowNS
+{
+ id object;
+ id delegate;
+ id view;
+ id layer;
+
+ GLFWbool maximized;
+
+ // Cached window properties to filter out duplicate events
+ int width, height;
+ int fbWidth, fbHeight;
+ float xscale, yscale;
+
+ // The total sum of the distances the cursor has been warped
+ // since the last cursor motion event was processed
+ // This is kept to counteract Cocoa doing the same internally
+ double cursorWarpDeltaX, cursorWarpDeltaY;
+
+} _GLFWwindowNS;
+
+// Cocoa-specific global data
+//
+typedef struct _GLFWlibraryNS
+{
+ CGEventSourceRef eventSource;
+ id delegate;
+ id autoreleasePool;
+ GLFWbool cursorHidden;
+ TISInputSourceRef inputSource;
+ IOHIDManagerRef hidManager;
+ id unicodeData;
+ id helper;
+ id keyUpMonitor;
+ id nibObjects;
+
+ char keyName[64];
+ short int keycodes[256];
+ short int scancodes[GLFW_KEY_LAST + 1];
+ char* clipboardString;
+ CGPoint cascadePoint;
+ // Where to place the cursor when re-enabled
+ double restoreCursorPosX, restoreCursorPosY;
+ // The window whose disabled cursor mode is active
+ _GLFWwindow* disabledCursorWindow;
+
+ struct {
+ CFBundleRef bundle;
+ PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;
+ PFN_TISGetInputSourceProperty GetInputSourceProperty;
+ PFN_LMGetKbdType GetKbdType;
+ CFStringRef kPropertyUnicodeKeyLayoutData;
+ } tis;
+
+} _GLFWlibraryNS;
+
+// Cocoa-specific per-monitor data
+//
+typedef struct _GLFWmonitorNS
+{
+ CGDirectDisplayID displayID;
+ CGDisplayModeRef previousMode;
+ uint32_t unitNumber;
+ id screen;
+
+} _GLFWmonitorNS;
+
+// Cocoa-specific per-cursor data
+//
+typedef struct _GLFWcursorNS
+{
+ id object;
+
+} _GLFWcursorNS;
+
+// Cocoa-specific global timer data
+//
+typedef struct _GLFWtimerNS
+{
+ uint64_t frequency;
+
+} _GLFWtimerNS;
+
+
+void _glfwInitTimerNS(void);
+
+void _glfwPollMonitorsNS(void);
+void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_time.c b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_time.c
new file mode 100644
index 0000000..3b27035
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_time.c
@@ -0,0 +1,60 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <mach/mach_time.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerNS(void)
+{
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+
+ _glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+ return mach_absolute_time();
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+ return _glfw.timer.ns.frequency;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_window.m b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_window.m
new file mode 100644
index 0000000..db9935c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/cocoa_window.m
@@ -0,0 +1,1855 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <float.h>
+#include <string.h>
+
+// Needed for _NSGetProgname
+#include <crt_externs.h>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
+ #define NSWindowStyleMaskBorderless NSBorderlessWindowMask
+ #define NSWindowStyleMaskClosable NSClosableWindowMask
+ #define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
+ #define NSWindowStyleMaskResizable NSResizableWindowMask
+ #define NSWindowStyleMaskTitled NSTitledWindowMask
+ #define NSEventModifierFlagCommand NSCommandKeyMask
+ #define NSEventModifierFlagControl NSControlKeyMask
+ #define NSEventModifierFlagOption NSAlternateKeyMask
+ #define NSEventModifierFlagShift NSShiftKeyMask
+ #define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
+ #define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
+ #define NSEventMaskAny NSAnyEventMask
+ #define NSEventTypeApplicationDefined NSApplicationDefined
+ #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
+#endif
+
+// Returns the style mask corresponding to the window settings
+//
+static NSUInteger getStyleMask(_GLFWwindow* window)
+{
+ NSUInteger styleMask = 0;
+
+ if (window->monitor || !window->decorated)
+ styleMask |= NSWindowStyleMaskBorderless;
+ else
+ {
+ styleMask |= NSWindowStyleMaskTitled |
+ NSWindowStyleMaskClosable |
+ NSWindowStyleMaskMiniaturizable;
+
+ if (window->resizable)
+ styleMask |= NSWindowStyleMaskResizable;
+ }
+
+ return styleMask;
+}
+
+// Center the cursor in the view of the window
+//
+static void centerCursor(_GLFWwindow *window)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+// Returns whether the cursor is in the client area of the specified window
+//
+static GLFWbool cursorInClientArea(_GLFWwindow* window)
+{
+ const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+ return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
+}
+
+// Hides the cursor if not already hidden
+//
+static void hideCursor(_GLFWwindow* window)
+{
+ if (!_glfw.ns.cursorHidden)
+ {
+ [NSCursor hide];
+ _glfw.ns.cursorHidden = GLFW_TRUE;
+ }
+}
+
+// Shows the cursor if not already shown
+//
+static void showCursor(_GLFWwindow* window)
+{
+ if (_glfw.ns.cursorHidden)
+ {
+ [NSCursor unhide];
+ _glfw.ns.cursorHidden = GLFW_FALSE;
+ }
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ showCursor(window);
+
+ if (window->cursor)
+ [(NSCursor*) window->cursor->ns.object set];
+ else
+ [[NSCursor arrowCursor] set];
+ }
+ else
+ hideCursor(window);
+}
+
+// Apply chosen cursor mode to a focused window
+//
+static void updateCursorMode(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ _glfw.ns.disabledCursorWindow = window;
+ _glfwPlatformGetCursorPos(window,
+ &_glfw.ns.restoreCursorPosX,
+ &_glfw.ns.restoreCursorPosY);
+ centerCursor(window);
+ CGAssociateMouseAndMouseCursorPosition(false);
+ }
+ else if (_glfw.ns.disabledCursorWindow == window)
+ {
+ _glfw.ns.disabledCursorWindow = NULL;
+ CGAssociateMouseAndMouseCursorPosition(true);
+ _glfwPlatformSetCursorPos(window,
+ _glfw.ns.restoreCursorPosX,
+ _glfw.ns.restoreCursorPosY);
+ }
+
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+// Transforms the specified y-coordinate between the CG display and NS screen
+// coordinate systems
+//
+static float transformY(float y)
+{
+ return CGDisplayBounds(CGMainDisplayID()).size.height - y;
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_GLFWwindow* window)
+{
+ _glfwSetVideoModeNS(window->monitor, &window->videoMode);
+ const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
+ const NSRect frame = NSMakeRect(bounds.origin.x,
+ transformY(bounds.origin.y + bounds.size.height),
+ bounds.size.width,
+ bounds.size.height);
+
+ [window->ns.object setFrame:frame display:YES];
+
+ _glfwInputMonitorWindow(window->monitor, window);
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+ if (window->monitor->window != window)
+ return;
+
+ _glfwInputMonitorWindow(window->monitor, NULL);
+ _glfwRestoreVideoModeNS(window->monitor);
+}
+
+// Translates macOS key modifiers into GLFW ones
+//
+static int translateFlags(NSUInteger flags)
+{
+ int mods = 0;
+
+ if (flags & NSEventModifierFlagShift)
+ mods |= GLFW_MOD_SHIFT;
+ if (flags & NSEventModifierFlagControl)
+ mods |= GLFW_MOD_CONTROL;
+ if (flags & NSEventModifierFlagOption)
+ mods |= GLFW_MOD_ALT;
+ if (flags & NSEventModifierFlagCommand)
+ mods |= GLFW_MOD_SUPER;
+ if (flags & NSEventModifierFlagCapsLock)
+ mods |= GLFW_MOD_CAPS_LOCK;
+
+ return mods;
+}
+
+// Translates a macOS keycode to a GLFW keycode
+//
+static int translateKey(unsigned int key)
+{
+ if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
+ return GLFW_KEY_UNKNOWN;
+
+ return _glfw.ns.keycodes[key];
+}
+
+// Translate a GLFW keycode to a Cocoa modifier flag
+//
+static NSUInteger translateKeyToModifierFlag(int key)
+{
+ switch (key)
+ {
+ case GLFW_KEY_LEFT_SHIFT:
+ case GLFW_KEY_RIGHT_SHIFT:
+ return NSEventModifierFlagShift;
+ case GLFW_KEY_LEFT_CONTROL:
+ case GLFW_KEY_RIGHT_CONTROL:
+ return NSEventModifierFlagControl;
+ case GLFW_KEY_LEFT_ALT:
+ case GLFW_KEY_RIGHT_ALT:
+ return NSEventModifierFlagOption;
+ case GLFW_KEY_LEFT_SUPER:
+ case GLFW_KEY_RIGHT_SUPER:
+ return NSEventModifierFlagCommand;
+ case GLFW_KEY_CAPS_LOCK:
+ return NSEventModifierFlagCapsLock;
+ }
+
+ return 0;
+}
+
+// Defines a constant for empty ranges in NSTextInputClient
+//
+static const NSRange kEmptyRange = { NSNotFound, 0 };
+
+
+//------------------------------------------------------------------------
+// Delegate for window related notifications
+//------------------------------------------------------------------------
+
+@interface GLFWWindowDelegate : NSObject
+{
+ _GLFWwindow* window;
+}
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
+
+@end
+
+@implementation GLFWWindowDelegate
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
+{
+ self = [super init];
+ if (self != nil)
+ window = initWindow;
+
+ return self;
+}
+
+- (BOOL)windowShouldClose:(id)sender
+{
+ _glfwInputWindowCloseRequest(window);
+ return NO;
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+ if (window->context.client != GLFW_NO_API)
+ [window->context.nsgl.object update];
+
+ if (_glfw.ns.disabledCursorWindow == window)
+ centerCursor(window);
+
+ const int maximized = [window->ns.object isZoomed];
+ if (window->ns.maximized != maximized)
+ {
+ window->ns.maximized = maximized;
+ _glfwInputWindowMaximize(window, maximized);
+ }
+
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+ if (fbRect.size.width != window->ns.fbWidth ||
+ fbRect.size.height != window->ns.fbHeight)
+ {
+ window->ns.fbWidth = fbRect.size.width;
+ window->ns.fbHeight = fbRect.size.height;
+ _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
+ }
+
+ if (contentRect.size.width != window->ns.width ||
+ contentRect.size.height != window->ns.height)
+ {
+ window->ns.width = contentRect.size.width;
+ window->ns.height = contentRect.size.height;
+ _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
+ }
+}
+
+- (void)windowDidMove:(NSNotification *)notification
+{
+ if (window->context.client != GLFW_NO_API)
+ [window->context.nsgl.object update];
+
+ if (_glfw.ns.disabledCursorWindow == window)
+ centerCursor(window);
+
+ int x, y;
+ _glfwPlatformGetWindowPos(window, &x, &y);
+ _glfwInputWindowPos(window, x, y);
+}
+
+- (void)windowDidMiniaturize:(NSNotification *)notification
+{
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowIconify(window, GLFW_TRUE);
+}
+
+- (void)windowDidDeminiaturize:(NSNotification *)notification
+{
+ if (window->monitor)
+ acquireMonitor(window);
+
+ _glfwInputWindowIconify(window, GLFW_FALSE);
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)notification
+{
+ if (_glfw.ns.disabledCursorWindow == window)
+ centerCursor(window);
+
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+ updateCursorMode(window);
+}
+
+- (void)windowDidResignKey:(NSNotification *)notification
+{
+ if (window->monitor && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// Delegate for application related notifications
+//------------------------------------------------------------------------
+
+@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
+@end
+
+@implementation GLFWApplicationDelegate
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ _GLFWwindow* window;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ _glfwInputWindowCloseRequest(window);
+
+ return NSTerminateCancel;
+}
+
+- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
+{
+ _GLFWwindow* window;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ {
+ if (window->context.client != GLFW_NO_API)
+ [window->context.nsgl.object update];
+ }
+
+ _glfwPollMonitorsNS();
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ [NSApp stop:nil];
+
+ _glfwPlatformPostEmptyEvent();
+}
+
+- (void)applicationDidHide:(NSNotification *)notification
+{
+ int i;
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ _glfwRestoreVideoModeNS(_glfw.monitors[i]);
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// Content view class for the GLFW window
+//------------------------------------------------------------------------
+
+@interface GLFWContentView : NSView <NSTextInputClient>
+{
+ _GLFWwindow* window;
+ NSTrackingArea* trackingArea;
+ NSMutableAttributedString* markedText;
+}
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
+
+@end
+
+@implementation GLFWContentView
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
+{
+ self = [super init];
+ if (self != nil)
+ {
+ window = initWindow;
+ trackingArea = nil;
+ markedText = [[NSMutableAttributedString alloc] init];
+
+ [self updateTrackingAreas];
+ // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
+ // on 10.7 without having been deprecated yet
+ [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [trackingArea release];
+ [markedText release];
+ [super dealloc];
+}
+
+- (BOOL)isOpaque
+{
+ return [window->ns.object isOpaque];
+}
+
+- (BOOL)canBecomeKeyView
+{
+ return YES;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL)wantsUpdateLayer
+{
+ return YES;
+}
+
+- (void)updateLayer
+{
+ if (window->context.client != GLFW_NO_API)
+ [window->context.nsgl.object update];
+
+ _glfwInputWindowDamage(window);
+}
+
+- (id)makeBackingLayer
+{
+ if (window->ns.layer)
+ return window->ns.layer;
+
+ return [super makeBackingLayer];
+}
+
+- (void)cursorUpdate:(NSEvent *)event
+{
+ updateCursorImage(window);
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)event
+{
+ return YES;
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_PRESS,
+ translateFlags([event modifierFlags]));
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+ [self mouseMoved:event];
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_RELEASE,
+ translateFlags([event modifierFlags]));
+}
+
+- (void)mouseMoved:(NSEvent *)event
+{
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ const double dx = [event deltaX] - window->ns.cursorWarpDeltaX;
+ const double dy = [event deltaY] - window->ns.cursorWarpDeltaY;
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + dx,
+ window->virtualCursorPosY + dy);
+ }
+ else
+ {
+ const NSRect contentRect = [window->ns.view frame];
+ const NSPoint pos = [event locationInWindow];
+
+ _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
+ }
+
+ window->ns.cursorWarpDeltaX = 0;
+ window->ns.cursorWarpDeltaY = 0;
+}
+
+- (void)rightMouseDown:(NSEvent *)event
+{
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_RIGHT,
+ GLFW_PRESS,
+ translateFlags([event modifierFlags]));
+}
+
+- (void)rightMouseDragged:(NSEvent *)event
+{
+ [self mouseMoved:event];
+}
+
+- (void)rightMouseUp:(NSEvent *)event
+{
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_RIGHT,
+ GLFW_RELEASE,
+ translateFlags([event modifierFlags]));
+}
+
+- (void)otherMouseDown:(NSEvent *)event
+{
+ _glfwInputMouseClick(window,
+ (int) [event buttonNumber],
+ GLFW_PRESS,
+ translateFlags([event modifierFlags]));
+}
+
+- (void)otherMouseDragged:(NSEvent *)event
+{
+ [self mouseMoved:event];
+}
+
+- (void)otherMouseUp:(NSEvent *)event
+{
+ _glfwInputMouseClick(window,
+ (int) [event buttonNumber],
+ GLFW_RELEASE,
+ translateFlags([event modifierFlags]));
+}
+
+- (void)mouseExited:(NSEvent *)event
+{
+ if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+ showCursor(window);
+
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+}
+
+- (void)mouseEntered:(NSEvent *)event
+{
+ if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+ hideCursor(window);
+
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+}
+
+- (void)viewDidChangeBackingProperties
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+ if (fbRect.size.width != window->ns.fbWidth ||
+ fbRect.size.height != window->ns.fbHeight)
+ {
+ window->ns.fbWidth = fbRect.size.width;
+ window->ns.fbHeight = fbRect.size.height;
+ _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
+ }
+
+ const float xscale = fbRect.size.width / contentRect.size.width;
+ const float yscale = fbRect.size.height / contentRect.size.height;
+
+ if (xscale != window->ns.xscale || yscale != window->ns.yscale)
+ {
+ window->ns.xscale = xscale;
+ window->ns.yscale = yscale;
+ _glfwInputWindowContentScale(window, xscale, yscale);
+
+ if (window->ns.layer)
+ [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
+ }
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ _glfwInputWindowDamage(window);
+}
+
+- (void)updateTrackingAreas
+{
+ if (trackingArea != nil)
+ {
+ [self removeTrackingArea:trackingArea];
+ [trackingArea release];
+ }
+
+ const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow |
+ NSTrackingEnabledDuringMouseDrag |
+ NSTrackingCursorUpdate |
+ NSTrackingInVisibleRect |
+ NSTrackingAssumeInside;
+
+ trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
+ options:options
+ owner:self
+ userInfo:nil];
+
+ [self addTrackingArea:trackingArea];
+ [super updateTrackingAreas];
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+ const int key = translateKey([event keyCode]);
+ const int mods = translateFlags([event modifierFlags]);
+
+ _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
+
+ [self interpretKeyEvents:@[event]];
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+ int action;
+ const unsigned int modifierFlags =
+ [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
+ const int key = translateKey([event keyCode]);
+ const int mods = translateFlags(modifierFlags);
+ const NSUInteger keyFlag = translateKeyToModifierFlag(key);
+
+ if (keyFlag & modifierFlags)
+ {
+ if (window->keys[key] == GLFW_PRESS)
+ action = GLFW_RELEASE;
+ else
+ action = GLFW_PRESS;
+ }
+ else
+ action = GLFW_RELEASE;
+
+ _glfwInputKey(window, key, [event keyCode], action, mods);
+}
+
+- (void)keyUp:(NSEvent *)event
+{
+ const int key = translateKey([event keyCode]);
+ const int mods = translateFlags([event modifierFlags]);
+ _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
+}
+
+- (void)scrollWheel:(NSEvent *)event
+{
+ double deltaX, deltaY;
+
+ deltaX = [event scrollingDeltaX];
+ deltaY = [event scrollingDeltaY];
+
+ if ([event hasPreciseScrollingDeltas])
+ {
+ deltaX *= 0.1;
+ deltaY *= 0.1;
+ }
+
+ if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0)
+ _glfwInputScroll(window, deltaX, deltaY);
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+ // HACK: We don't know what to say here because we don't know what the
+ // application wants to do with the paths
+ return NSDragOperationGeneric;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ const NSRect contentRect = [window->ns.view frame];
+ _glfwInputCursorPos(window,
+ [sender draggingLocation].x,
+ contentRect.size.height - [sender draggingLocation].y);
+
+ NSPasteboard* pasteboard = [sender draggingPasteboard];
+ NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES};
+ NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
+ options:options];
+ const NSUInteger count = [urls count];
+ if (count)
+ {
+ char** paths = calloc(count, sizeof(char*));
+
+ for (NSUInteger i = 0; i < count; i++)
+ paths[i] = _glfw_strdup([[urls objectAtIndex:i] fileSystemRepresentation]);
+
+ _glfwInputDrop(window, (int) count, (const char**) paths);
+
+ for (NSUInteger i = 0; i < count; i++)
+ free(paths[i]);
+ free(paths);
+ }
+
+ return YES;
+}
+
+- (BOOL)hasMarkedText
+{
+ return [markedText length] > 0;
+}
+
+- (NSRange)markedRange
+{
+ if ([markedText length] > 0)
+ return NSMakeRange(0, [markedText length] - 1);
+ else
+ return kEmptyRange;
+}
+
+- (NSRange)selectedRange
+{
+ return kEmptyRange;
+}
+
+- (void)setMarkedText:(id)string
+ selectedRange:(NSRange)selectedRange
+ replacementRange:(NSRange)replacementRange
+{
+ [markedText release];
+ if ([string isKindOfClass:[NSAttributedString class]])
+ markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
+ else
+ markedText = [[NSMutableAttributedString alloc] initWithString:string];
+}
+
+- (void)unmarkText
+{
+ [[markedText mutableString] setString:@""];
+}
+
+- (NSArray*)validAttributesForMarkedText
+{
+ return [NSArray array];
+}
+
+- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
+ actualRange:(NSRangePointer)actualRange
+{
+ return nil;
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)point
+{
+ return 0;
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)range
+ actualRange:(NSRangePointer)actualRange
+{
+ int xpos, ypos;
+ _glfwPlatformGetWindowPos(window, &xpos, &ypos);
+ const NSRect contentRect = [window->ns.view frame];
+ return NSMakeRect(xpos, transformY(ypos + contentRect.size.height), 0.0, 0.0);
+}
+
+- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
+{
+ NSString* characters;
+ NSEvent* event = [NSApp currentEvent];
+ const int mods = translateFlags([event modifierFlags]);
+ const int plain = !(mods & GLFW_MOD_SUPER);
+
+ if ([string isKindOfClass:[NSAttributedString class]])
+ characters = [string string];
+ else
+ characters = (NSString*) string;
+
+ NSUInteger i, length = [characters length];
+
+ for (i = 0; i < length; i++)
+ {
+ const unichar codepoint = [characters characterAtIndex:i];
+ if ((codepoint & 0xff00) == 0xf700)
+ continue;
+
+ _glfwInputChar(window, codepoint, mods, plain);
+ }
+}
+
+- (void)doCommandBySelector:(SEL)selector
+{
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// GLFW window class
+//------------------------------------------------------------------------
+
+@interface GLFWWindow : NSWindow {}
+@end
+
+@implementation GLFWWindow
+
+- (BOOL)canBecomeKeyWindow
+{
+ // Required for NSWindowStyleMaskBorderless windows
+ return YES;
+}
+
+- (BOOL)canBecomeMainWindow
+{
+ return YES;
+}
+
+@end
+
+
+// Set up the menu bar (manually)
+// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
+// could go away at any moment, lots of stuff that really should be
+// localize(d|able), etc. Add a nib to save us this horror.
+//
+static void createMenuBar(void)
+{
+ size_t i;
+ NSString* appName = nil;
+ NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
+ NSString* nameKeys[] =
+ {
+ @"CFBundleDisplayName",
+ @"CFBundleName",
+ @"CFBundleExecutable",
+ };
+
+ // Try to figure out what the calling application is called
+
+ for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
+ {
+ id name = [bundleInfo objectForKey:nameKeys[i]];
+ if (name &&
+ [name isKindOfClass:[NSString class]] &&
+ ![name isEqualToString:@""])
+ {
+ appName = name;
+ break;
+ }
+ }
+
+ if (!appName)
+ {
+ char** progname = _NSGetProgname();
+ if (progname && *progname)
+ appName = [NSString stringWithUTF8String:*progname];
+ else
+ appName = @"GLFW Application";
+ }
+
+ NSMenu* bar = [[NSMenu alloc] init];
+ [NSApp setMainMenu:bar];
+
+ NSMenuItem* appMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ NSMenu* appMenu = [[NSMenu alloc] init];
+ [appMenuItem setSubmenu:appMenu];
+
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
+ action:@selector(orderFrontStandardAboutPanel:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ NSMenu* servicesMenu = [[NSMenu alloc] init];
+ [NSApp setServicesMenu:servicesMenu];
+ [[appMenu addItemWithTitle:@"Services"
+ action:NULL
+ keyEquivalent:@""] setSubmenu:servicesMenu];
+ [servicesMenu release];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
+ action:@selector(hide:)
+ keyEquivalent:@"h"];
+ [[appMenu addItemWithTitle:@"Hide Others"
+ action:@selector(hideOtherApplications:)
+ keyEquivalent:@"h"]
+ setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
+ [appMenu addItemWithTitle:@"Show All"
+ action:@selector(unhideAllApplications:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
+ action:@selector(terminate:)
+ keyEquivalent:@"q"];
+
+ NSMenuItem* windowMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ [bar release];
+ NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+ [NSApp setWindowsMenu:windowMenu];
+ [windowMenuItem setSubmenu:windowMenu];
+
+ [windowMenu addItemWithTitle:@"Minimize"
+ action:@selector(performMiniaturize:)
+ keyEquivalent:@"m"];
+ [windowMenu addItemWithTitle:@"Zoom"
+ action:@selector(performZoom:)
+ keyEquivalent:@""];
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [windowMenu addItemWithTitle:@"Bring All to Front"
+ action:@selector(arrangeInFront:)
+ keyEquivalent:@""];
+
+ // TODO: Make this appear at the bottom of the menu (for consistency)
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [[windowMenu addItemWithTitle:@"Enter Full Screen"
+ action:@selector(toggleFullScreen:)
+ keyEquivalent:@"f"]
+ setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
+
+ // Prior to Snow Leopard, we need to use this oddly-named semi-private API
+ // to get the application menu working properly.
+ SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
+ [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
+}
+
+// Initialize the Cocoa Application Kit
+//
+static GLFWbool initializeAppKit(void)
+{
+ if (_glfw.ns.delegate)
+ return GLFW_TRUE;
+
+ // There can only be one application delegate, but we allocate it the
+ // first time a window is created to keep all window code in this file
+ _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
+ if (_glfw.ns.delegate == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create application delegate");
+ return GLFW_FALSE;
+ }
+
+ [NSApp setDelegate:_glfw.ns.delegate];
+
+ if (_glfw.hints.init.ns.menubar)
+ {
+ // In case we are unbundled, make us a proper UI application
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+ // Menu bar setup must go between sharedApplication above and
+ // finishLaunching below, in order to properly emulate the behavior
+ // of NSApplicationMain
+
+ if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+ [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
+ owner:NSApp
+ topLevelObjects:&_glfw.ns.nibObjects];
+#else
+ [[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
+#endif
+ }
+ else
+ createMenuBar();
+ }
+
+ [NSApp run];
+
+ // Press and Hold prevents some keys from emitting repeated characters
+ NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
+ [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
+
+ return GLFW_TRUE;
+}
+
+// Create the Cocoa window
+//
+static GLFWbool createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
+ if (window->ns.delegate == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create window delegate");
+ return GLFW_FALSE;
+ }
+
+ NSRect contentRect;
+
+ if (window->monitor)
+ {
+ GLFWvidmode mode;
+ int xpos, ypos;
+
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+
+ contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);
+ }
+ else
+ contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
+
+ window->ns.object = [[GLFWWindow alloc]
+ initWithContentRect:contentRect
+ styleMask:getStyleMask(window)
+ backing:NSBackingStoreBuffered
+ defer:NO];
+
+ if (window->ns.object == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window");
+ return GLFW_FALSE;
+ }
+
+ if (window->monitor)
+ [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
+ else
+ {
+ [window->ns.object center];
+ _glfw.ns.cascadePoint =
+ NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
+ NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
+
+ if (wndconfig->resizable)
+ {
+ const NSWindowCollectionBehavior behavior =
+ NSWindowCollectionBehaviorFullScreenPrimary |
+ NSWindowCollectionBehaviorManaged;
+ [window->ns.object setCollectionBehavior:behavior];
+ }
+
+ if (wndconfig->floating)
+ [window->ns.object setLevel:NSFloatingWindowLevel];
+
+ if (wndconfig->maximized)
+ [window->ns.object zoom:nil];
+ }
+
+ if (strlen(wndconfig->ns.frameName))
+ [window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->ns.frameName]];
+
+ window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
+
+ if (wndconfig->ns.retina)
+ [window->ns.view setWantsBestResolutionOpenGLSurface:YES];
+
+ if (fbconfig->transparent)
+ {
+ [window->ns.object setOpaque:NO];
+ [window->ns.object setBackgroundColor:[NSColor clearColor]];
+ }
+
+ [window->ns.object setContentView:window->ns.view];
+ [window->ns.object makeFirstResponder:window->ns.view];
+ [window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
+ [window->ns.object setDelegate:window->ns.delegate];
+ [window->ns.object setAcceptsMouseMovedEvents:YES];
+ [window->ns.object setRestorable:NO];
+
+ _glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
+ _glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!initializeAppKit())
+ return GLFW_FALSE;
+
+ if (!createNativeWindow(window, wndconfig, fbconfig))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwInitNSGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ if (!_glfwInitOSMesa())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->monitor)
+ {
+ _glfwPlatformShowWindow(window);
+ _glfwPlatformFocusWindow(window);
+ acquireMonitor(window);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (_glfw.ns.disabledCursorWindow == window)
+ _glfw.ns.disabledCursorWindow = NULL;
+
+ [window->ns.object orderOut:nil];
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+
+ [window->ns.object setDelegate:nil];
+ [window->ns.delegate release];
+ window->ns.delegate = nil;
+
+ [window->ns.view release];
+ window->ns.view = nil;
+
+ [window->ns.object close];
+ window->ns.object = nil;
+
+ [_glfw.ns.autoreleasePool drain];
+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
+{
+ NSString* string = [NSString stringWithUTF8String:title];
+ [window->ns.object setTitle:string];
+ // HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
+ // if the window lacks NSWindowStyleMaskTitled
+ [window->ns.object setMiniwindowTitle:string];
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ // Regular windows do not have icons
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ const NSRect contentRect =
+ [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
+
+ if (xpos)
+ *xpos = contentRect.origin.x;
+ if (ypos)
+ *ypos = transformY(contentRect.origin.y + contentRect.size.height);
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect dummyRect = NSMakeRect(x, transformY(y + contentRect.size.height), 0, 0);
+ const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
+ [window->ns.object setFrameOrigin:frameRect.origin];
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ const NSRect contentRect = [window->ns.view frame];
+
+ if (width)
+ *width = contentRect.size.width;
+ if (height)
+ *height = contentRect.size.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->monitor)
+ {
+ if (window->monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ [window->ns.object setContentSize:NSMakeSize(width, height)];
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
+ [window->ns.object setContentMinSize:NSMakeSize(0, 0)];
+ else
+ [window->ns.object setContentMinSize:NSMakeSize(minwidth, minheight)];
+
+ if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
+ [window->ns.object setContentMaxSize:NSMakeSize(DBL_MAX, DBL_MAX)];
+ else
+ [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)];
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
+ [window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
+ else
+ [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+ if (width)
+ *width = (int) fbRect.size.width;
+ if (height)
+ *height = (int) fbRect.size.height;
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect];
+
+ if (left)
+ *left = contentRect.origin.x - frameRect.origin.x;
+ if (top)
+ *top = frameRect.origin.y + frameRect.size.height -
+ contentRect.origin.y - contentRect.size.height;
+ if (right)
+ *right = frameRect.origin.x + frameRect.size.width -
+ contentRect.origin.x - contentRect.size.width;
+ if (bottom)
+ *bottom = contentRect.origin.y - frameRect.origin.y;
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+ float* xscale, float* yscale)
+{
+ const NSRect points = [window->ns.view frame];
+ const NSRect pixels = [window->ns.view convertRectToBacking:points];
+
+ if (xscale)
+ *xscale = (float) (pixels.size.width / points.size.width);
+ if (yscale)
+ *yscale = (float) (pixels.size.height / points.size.height);
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ [window->ns.object miniaturize:nil];
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ if ([window->ns.object isMiniaturized])
+ [window->ns.object deminiaturize:nil];
+ else if ([window->ns.object isZoomed])
+ [window->ns.object zoom:nil];
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ if (![window->ns.object isZoomed])
+ [window->ns.object zoom:nil];
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ [window->ns.object orderFront:nil];
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ [window->ns.object orderOut:nil];
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+ [NSApp requestUserAttention:NSInformationalRequest];
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ // Make us the active application
+ // HACK: This has been moved here from initializeAppKit to prevent
+ // applications using only hidden windows from being activated, but
+ // should probably not be done every time any window is shown
+ [NSApp activateIgnoringOtherApps:YES];
+
+ [window->ns.object makeKeyAndOrderFront:nil];
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (window->monitor == monitor)
+ {
+ if (monitor)
+ {
+ if (monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ const NSRect contentRect =
+ NSMakeRect(xpos, transformY(ypos + height), width, height);
+ const NSRect frameRect =
+ [window->ns.object frameRectForContentRect:contentRect
+ styleMask:getStyleMask(window)];
+
+ [window->ns.object setFrame:frameRect display:YES];
+ }
+
+ return;
+ }
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowMonitor(window, monitor);
+
+ // HACK: Allow the state cached in Cocoa to catch up to reality
+ // TODO: Solve this in a less terrible way
+ _glfwPlatformPollEvents();
+
+ const NSUInteger styleMask = getStyleMask(window);
+ [window->ns.object setStyleMask:styleMask];
+ // HACK: Changing the style mask can cause the first responder to be cleared
+ [window->ns.object makeFirstResponder:window->ns.view];
+
+ if (monitor)
+ {
+ [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
+ [window->ns.object setHasShadow:NO];
+
+ acquireMonitor(window);
+ }
+ else
+ {
+ NSRect contentRect = NSMakeRect(xpos, transformY(ypos + height),
+ width, height);
+ NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
+ styleMask:styleMask];
+ [window->ns.object setFrame:frameRect display:YES];
+
+ if (window->numer != GLFW_DONT_CARE &&
+ window->denom != GLFW_DONT_CARE)
+ {
+ [window->ns.object setContentAspectRatio:NSMakeSize(window->numer,
+ window->denom)];
+ }
+
+ if (window->minwidth != GLFW_DONT_CARE &&
+ window->minheight != GLFW_DONT_CARE)
+ {
+ [window->ns.object setContentMinSize:NSMakeSize(window->minwidth,
+ window->minheight)];
+ }
+
+ if (window->maxwidth != GLFW_DONT_CARE &&
+ window->maxheight != GLFW_DONT_CARE)
+ {
+ [window->ns.object setContentMaxSize:NSMakeSize(window->maxwidth,
+ window->maxheight)];
+ }
+
+ if (window->floating)
+ [window->ns.object setLevel:NSFloatingWindowLevel];
+ else
+ [window->ns.object setLevel:NSNormalWindowLevel];
+
+ [window->ns.object setHasShadow:YES];
+ // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
+ // title property but the miniwindow title property is unaffected
+ [window->ns.object setTitle:[window->ns.object miniwindowTitle]];
+ }
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return [window->ns.object isKeyWindow];
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return [window->ns.object isMiniaturized];
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return [window->ns.object isVisible];
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return [window->ns.object isZoomed];
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+ const NSPoint point = [NSEvent mouseLocation];
+
+ if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
+ [window->ns.object windowNumber])
+ {
+ return GLFW_FALSE;
+ }
+
+ return NSPointInRect(point,
+ [window->ns.object convertRectToScreen:[window->ns.view bounds]]);
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+ return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+ [window->ns.object setStyleMask:getStyleMask(window)];
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+ [window->ns.object setStyleMask:getStyleMask(window)];
+ [window->ns.object makeFirstResponder:window->ns.view];
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+ if (enabled)
+ [window->ns.object setLevel:NSFloatingWindowLevel];
+ else
+ [window->ns.object setLevel:NSNormalWindowLevel];
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+ return (float) [window->ns.object alphaValue];
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+ [window->ns.object setAlphaValue:opacity];
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ for (;;)
+ {
+ NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event == nil)
+ break;
+
+ [NSApp sendEvent:event];
+ }
+
+ [_glfw.ns.autoreleasePool drain];
+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ // I wanted to pass NO to dequeue:, and rely on PollEvents to
+ // dequeue and send. For reasons not at all clear to me, passing
+ // NO to dequeue: causes this method never to return.
+ NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ [NSApp sendEvent:event];
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
+ NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
+ untilDate:date
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event)
+ [NSApp sendEvent:event];
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
+ location:NSMakePoint(0, 0)
+ modifierFlags:0
+ timestamp:0
+ windowNumber:0
+ context:nil
+ subtype:0
+ data1:0
+ data2:0];
+ [NSApp postEvent:event atStart:YES];
+ [pool drain];
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+
+ if (xpos)
+ *xpos = pos.x;
+ if (ypos)
+ *ypos = contentRect.size.height - pos.y - 1;
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+ updateCursorImage(window);
+
+ const NSRect contentRect = [window->ns.view frame];
+ const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+
+ window->ns.cursorWarpDeltaX += x - pos.x;
+ window->ns.cursorWarpDeltaY += y - contentRect.size.height + pos.y;
+
+ if (window->monitor)
+ {
+ CGDisplayMoveCursorToPoint(window->monitor->ns.displayID,
+ CGPointMake(x, y));
+ }
+ else
+ {
+ const NSRect localRect = NSMakeRect(x, contentRect.size.height - y - 1, 0, 0);
+ const NSRect globalRect = [window->ns.object convertRectToScreen:localRect];
+ const NSPoint globalPoint = globalRect.origin;
+
+ CGWarpMouseCursorPosition(CGPointMake(globalPoint.x,
+ transformY(globalPoint.y)));
+ }
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ if (_glfwPlatformWindowFocused(window))
+ updateCursorMode(window);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+ UInt32 deadKeyState = 0;
+ UniChar characters[8];
+ UniCharCount characterCount = 0;
+
+ if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes],
+ scancode,
+ kUCKeyActionDisplay,
+ 0,
+ LMGetKbdType(),
+ kUCKeyTranslateNoDeadKeysBit,
+ &deadKeyState,
+ sizeof(characters) / sizeof(characters[0]),
+ &characterCount,
+ characters) != noErr)
+ {
+ return NULL;
+ }
+
+ if (!characterCount)
+ return NULL;
+
+ CFStringRef string = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
+ characters,
+ characterCount,
+ kCFAllocatorNull);
+ CFStringGetCString(string,
+ _glfw.ns.keyName,
+ sizeof(_glfw.ns.keyName),
+ kCFStringEncodingUTF8);
+ CFRelease(string);
+
+ return _glfw.ns.keyName;
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+ return _glfw.ns.scancodes[key];
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ NSImage* native;
+ NSBitmapImageRep* rep;
+
+ rep = [[NSBitmapImageRep alloc]
+ initWithBitmapDataPlanes:NULL
+ pixelsWide:image->width
+ pixelsHigh:image->height
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSCalibratedRGBColorSpace
+ bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
+ bytesPerRow:image->width * 4
+ bitsPerPixel:32];
+
+ if (rep == nil)
+ return GLFW_FALSE;
+
+ memcpy([rep bitmapData], image->pixels, image->width * image->height * 4);
+
+ native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];
+ [native addRepresentation:rep];
+
+ cursor->ns.object = [[NSCursor alloc] initWithImage:native
+ hotSpot:NSMakePoint(xhot, yhot)];
+
+ [native release];
+ [rep release];
+
+ if (cursor->ns.object == nil)
+ return GLFW_FALSE;
+
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ if (shape == GLFW_ARROW_CURSOR)
+ cursor->ns.object = [NSCursor arrowCursor];
+ else if (shape == GLFW_IBEAM_CURSOR)
+ cursor->ns.object = [NSCursor IBeamCursor];
+ else if (shape == GLFW_CROSSHAIR_CURSOR)
+ cursor->ns.object = [NSCursor crosshairCursor];
+ else if (shape == GLFW_HAND_CURSOR)
+ cursor->ns.object = [NSCursor pointingHandCursor];
+ else if (shape == GLFW_HRESIZE_CURSOR)
+ cursor->ns.object = [NSCursor resizeLeftRightCursor];
+ else if (shape == GLFW_VRESIZE_CURSOR)
+ cursor->ns.object = [NSCursor resizeUpDownCursor];
+
+ if (!cursor->ns.object)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve standard cursor");
+ return GLFW_FALSE;
+ }
+
+ [cursor->ns.object retain];
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->ns.object)
+ [(NSCursor*) cursor->ns.object release];
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+ NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+ [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
+ [pasteboard setString:[NSString stringWithUTF8String:string]
+ forType:NSPasteboardTypeString];
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+ NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+
+ if (![[pasteboard types] containsObject:NSPasteboardTypeString])
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "Cocoa: Failed to retrieve string from pasteboard");
+ return NULL;
+ }
+
+ NSString* object = [pasteboard stringForType:NSPasteboardTypeString];
+ if (!object)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve object from pasteboard");
+ return NULL;
+ }
+
+ free(_glfw.ns.clipboardString);
+ _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
+
+ return _glfw.ns.clipboardString;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+ if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface)
+ return;
+
+ extensions[0] = "VK_KHR_surface";
+ extensions[1] = "VK_MVK_macos_surface";
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ return GLFW_TRUE;
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
+ VkResult err;
+ VkMacOSSurfaceCreateInfoMVK sci;
+ PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
+
+ vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
+ vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
+ if (!vkCreateMacOSSurfaceMVK)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ // HACK: Dynamically load Core Animation to avoid adding an extra
+ // dependency for the majority who don't use MoltenVK
+ NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
+ if (!bundle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to find QuartzCore.framework");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ // NOTE: Create the layer here as makeBackingLayer should not return nil
+ window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
+ if (!window->ns.layer)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create layer for view");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
+ [window->ns.view setWantsLayer:YES];
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+ sci.pView = window->ns.view;
+
+ err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create Vulkan surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+#else
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(nil);
+ return window->ns.object;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/context.c b/Client/ThirdParty/Box2D/extern/glfw/src/context.c
new file mode 100644
index 0000000..fd344cf
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/context.c
@@ -0,0 +1,758 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Checks whether the desired context attributes are valid
+//
+// This function checks things like whether the specified client API version
+// exists and whether all relevant options have supported and non-conflicting
+// values
+//
+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
+{
+ if (ctxconfig->share)
+ {
+ if (ctxconfig->client == GLFW_NO_API ||
+ ctxconfig->share->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
+ ctxconfig->source != GLFW_EGL_CONTEXT_API &&
+ ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid context creation API 0x%08X",
+ ctxconfig->source);
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->client != GLFW_NO_API &&
+ ctxconfig->client != GLFW_OPENGL_API &&
+ ctxconfig->client != GLFW_OPENGL_ES_API)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid client API 0x%08X",
+ ctxconfig->client);
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
+ (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
+ (ctxconfig->major == 2 && ctxconfig->minor > 1) ||
+ (ctxconfig->major == 3 && ctxconfig->minor > 3))
+ {
+ // OpenGL 1.0 is the smallest valid version
+ // OpenGL 1.x series ended with version 1.5
+ // OpenGL 2.x series ended with version 2.1
+ // OpenGL 3.x series ended with version 3.3
+ // For now, let everything else through
+
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid OpenGL version %i.%i",
+ ctxconfig->major, ctxconfig->minor);
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->profile)
+ {
+ if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
+ ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid OpenGL profile 0x%08X",
+ ctxconfig->profile);
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->major <= 2 ||
+ (ctxconfig->major == 3 && ctxconfig->minor < 2))
+ {
+ // Desktop OpenGL context profiles are only defined for version 3.2
+ // and above
+
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Context profiles are only defined for OpenGL version 3.2 and above");
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->forward && ctxconfig->major <= 2)
+ {
+ // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Forward-compatibility is only defined for OpenGL version 3.0 and above");
+ return GLFW_FALSE;
+ }
+ }
+ else if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
+ (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
+ (ctxconfig->major == 2 && ctxconfig->minor > 0))
+ {
+ // OpenGL ES 1.0 is the smallest valid version
+ // OpenGL ES 1.x series ended with version 1.1
+ // OpenGL ES 2.x series ended with version 2.0
+ // For now, let everything else through
+
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid OpenGL ES version %i.%i",
+ ctxconfig->major, ctxconfig->minor);
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->robustness)
+ {
+ if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
+ ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid context robustness mode 0x%08X",
+ ctxconfig->robustness);
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->release)
+ {
+ if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
+ ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid context release behavior 0x%08X",
+ ctxconfig->release);
+ return GLFW_FALSE;
+ }
+ }
+
+ return GLFW_TRUE;
+}
+
+// Chooses the framebuffer config that best matches the desired one
+//
+const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
+ const _GLFWfbconfig* alternatives,
+ unsigned int count)
+{
+ unsigned int i;
+ unsigned int missing, leastMissing = UINT_MAX;
+ unsigned int colorDiff, leastColorDiff = UINT_MAX;
+ unsigned int extraDiff, leastExtraDiff = UINT_MAX;
+ const _GLFWfbconfig* current;
+ const _GLFWfbconfig* closest = NULL;
+
+ for (i = 0; i < count; i++)
+ {
+ current = alternatives + i;
+
+ if (desired->stereo > 0 && current->stereo == 0)
+ {
+ // Stereo is a hard constraint
+ continue;
+ }
+
+ if (desired->doublebuffer != current->doublebuffer)
+ {
+ // Double buffering is a hard constraint
+ continue;
+ }
+
+ // Count number of missing buffers
+ {
+ missing = 0;
+
+ if (desired->alphaBits > 0 && current->alphaBits == 0)
+ missing++;
+
+ if (desired->depthBits > 0 && current->depthBits == 0)
+ missing++;
+
+ if (desired->stencilBits > 0 && current->stencilBits == 0)
+ missing++;
+
+ if (desired->auxBuffers > 0 &&
+ current->auxBuffers < desired->auxBuffers)
+ {
+ missing += desired->auxBuffers - current->auxBuffers;
+ }
+
+ if (desired->samples > 0 && current->samples == 0)
+ {
+ // Technically, several multisampling buffers could be
+ // involved, but that's a lower level implementation detail and
+ // not important to us here, so we count them as one
+ missing++;
+ }
+
+ if (desired->transparent != current->transparent)
+ missing++;
+ }
+
+ // These polynomials make many small channel size differences matter
+ // less than one large channel size difference
+
+ // Calculate color channel size difference value
+ {
+ colorDiff = 0;
+
+ if (desired->redBits != GLFW_DONT_CARE)
+ {
+ colorDiff += (desired->redBits - current->redBits) *
+ (desired->redBits - current->redBits);
+ }
+
+ if (desired->greenBits != GLFW_DONT_CARE)
+ {
+ colorDiff += (desired->greenBits - current->greenBits) *
+ (desired->greenBits - current->greenBits);
+ }
+
+ if (desired->blueBits != GLFW_DONT_CARE)
+ {
+ colorDiff += (desired->blueBits - current->blueBits) *
+ (desired->blueBits - current->blueBits);
+ }
+ }
+
+ // Calculate non-color channel size difference value
+ {
+ extraDiff = 0;
+
+ if (desired->alphaBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->alphaBits - current->alphaBits) *
+ (desired->alphaBits - current->alphaBits);
+ }
+
+ if (desired->depthBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->depthBits - current->depthBits) *
+ (desired->depthBits - current->depthBits);
+ }
+
+ if (desired->stencilBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->stencilBits - current->stencilBits) *
+ (desired->stencilBits - current->stencilBits);
+ }
+
+ if (desired->accumRedBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->accumRedBits - current->accumRedBits) *
+ (desired->accumRedBits - current->accumRedBits);
+ }
+
+ if (desired->accumGreenBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
+ (desired->accumGreenBits - current->accumGreenBits);
+ }
+
+ if (desired->accumBlueBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
+ (desired->accumBlueBits - current->accumBlueBits);
+ }
+
+ if (desired->accumAlphaBits != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
+ (desired->accumAlphaBits - current->accumAlphaBits);
+ }
+
+ if (desired->samples != GLFW_DONT_CARE)
+ {
+ extraDiff += (desired->samples - current->samples) *
+ (desired->samples - current->samples);
+ }
+
+ if (desired->sRGB && !current->sRGB)
+ extraDiff++;
+ }
+
+ // Figure out if the current one is better than the best one found so far
+ // Least number of missing buffers is the most important heuristic,
+ // then color buffer size match and lastly size match for other buffers
+
+ if (missing < leastMissing)
+ closest = current;
+ else if (missing == leastMissing)
+ {
+ if ((colorDiff < leastColorDiff) ||
+ (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
+ {
+ closest = current;
+ }
+ }
+
+ if (current == closest)
+ {
+ leastMissing = missing;
+ leastColorDiff = colorDiff;
+ leastExtraDiff = extraDiff;
+ }
+ }
+
+ return closest;
+}
+
+// Retrieves the attributes of the current context
+//
+GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig)
+{
+ int i;
+ _GLFWwindow* previous;
+ const char* version;
+ const char* prefixes[] =
+ {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ NULL
+ };
+
+ window->context.source = ctxconfig->source;
+ window->context.client = GLFW_OPENGL_API;
+
+ previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
+ glfwMakeContextCurrent((GLFWwindow*) window);
+
+ window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
+ window->context.getProcAddress("glGetIntegerv");
+ window->context.GetString = (PFNGLGETSTRINGPROC)
+ window->context.getProcAddress("glGetString");
+ if (!window->context.GetIntegerv || !window->context.GetString)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ return GLFW_FALSE;
+ }
+
+ version = (const char*) window->context.GetString(GL_VERSION);
+ if (!version)
+ {
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "OpenGL version string retrieval is broken");
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "OpenGL ES version string retrieval is broken");
+ }
+
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ return GLFW_FALSE;
+ }
+
+ for (i = 0; prefixes[i]; i++)
+ {
+ const size_t length = strlen(prefixes[i]);
+
+ if (strncmp(version, prefixes[i], length) == 0)
+ {
+ version += length;
+ window->context.client = GLFW_OPENGL_ES_API;
+ break;
+ }
+ }
+
+ if (!sscanf(version, "%d.%d.%d",
+ &window->context.major,
+ &window->context.minor,
+ &window->context.revision))
+ {
+ if (window->context.client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "No version found in OpenGL version string");
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "No version found in OpenGL ES version string");
+ }
+
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ return GLFW_FALSE;
+ }
+
+ if (window->context.major < ctxconfig->major ||
+ (window->context.major == ctxconfig->major &&
+ window->context.minor < ctxconfig->minor))
+ {
+ // The desired OpenGL version is greater than the actual version
+ // This only happens if the machine lacks {GLX|WGL}_ARB_create_context
+ // /and/ the user has requested an OpenGL version greater than 1.0
+
+ // For API consistency, we emulate the behavior of the
+ // {GLX|WGL}_ARB_create_context extension and fail here
+
+ if (window->context.client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "Requested OpenGL version %i.%i, got version %i.%i",
+ ctxconfig->major, ctxconfig->minor,
+ window->context.major, window->context.minor);
+ }
+ else
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "Requested OpenGL ES version %i.%i, got version %i.%i",
+ ctxconfig->major, ctxconfig->minor,
+ window->context.major, window->context.minor);
+ }
+
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ return GLFW_FALSE;
+ }
+
+ if (window->context.major >= 3)
+ {
+ // OpenGL 3.0+ uses a different function for extension string retrieval
+ // We cache it here instead of in glfwExtensionSupported mostly to alert
+ // users as early as possible that their build may be broken
+
+ window->context.GetStringi = (PFNGLGETSTRINGIPROC)
+ window->context.getProcAddress("glGetStringi");
+ if (!window->context.GetStringi)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Entry point retrieval is broken");
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->context.client == GLFW_OPENGL_API)
+ {
+ // Read back context flags (OpenGL 3.0 and above)
+ if (window->context.major >= 3)
+ {
+ GLint flags;
+ window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
+
+ if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
+ window->context.forward = GLFW_TRUE;
+
+ if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
+ window->context.debug = GLFW_TRUE;
+ else if (glfwExtensionSupported("GL_ARB_debug_output") &&
+ ctxconfig->debug)
+ {
+ // HACK: This is a workaround for older drivers (pre KHR_debug)
+ // not setting the debug bit in the context flags for
+ // debug contexts
+ window->context.debug = GLFW_TRUE;
+ }
+
+ if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
+ window->context.noerror = GLFW_TRUE;
+ }
+
+ // Read back OpenGL context profile (OpenGL 3.2 and above)
+ if (window->context.major >= 4 ||
+ (window->context.major == 3 && window->context.minor >= 2))
+ {
+ GLint mask;
+ window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
+
+ if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+ window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
+ else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
+ window->context.profile = GLFW_OPENGL_CORE_PROFILE;
+ else if (glfwExtensionSupported("GL_ARB_compatibility"))
+ {
+ // HACK: This is a workaround for the compatibility profile bit
+ // not being set in the context flags if an OpenGL 3.2+
+ // context was created without having requested a specific
+ // version
+ window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
+ }
+ }
+
+ // Read back robustness strategy
+ if (glfwExtensionSupported("GL_ARB_robustness"))
+ {
+ // NOTE: We avoid using the context flags for detection, as they are
+ // only present from 3.0 while the extension applies from 1.1
+
+ GLint strategy;
+ window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
+ &strategy);
+
+ if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
+ window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
+ else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
+ window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
+ }
+ }
+ else
+ {
+ // Read back robustness strategy
+ if (glfwExtensionSupported("GL_EXT_robustness"))
+ {
+ // NOTE: The values of these constants match those of the OpenGL ARB
+ // one, so we can reuse them here
+
+ GLint strategy;
+ window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
+ &strategy);
+
+ if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
+ window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
+ else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
+ window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
+ }
+ }
+
+ if (glfwExtensionSupported("GL_KHR_context_flush_control"))
+ {
+ GLint behavior;
+ window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
+
+ if (behavior == GL_NONE)
+ window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
+ else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
+ window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
+ }
+
+ // Clearing the front buffer to black to avoid garbage pixels left over from
+ // previous uses of our bit of VRAM
+ {
+ PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
+ window->context.getProcAddress("glClear");
+ glClear(GL_COLOR_BUFFER_BIT);
+ window->context.swapBuffers(window);
+ }
+
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ return GLFW_TRUE;
+}
+
+// Searches an extension string for the specified extension
+//
+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
+{
+ const char* start = extensions;
+
+ for (;;)
+ {
+ const char* where;
+ const char* terminator;
+
+ where = strstr(start, string);
+ if (!where)
+ return GLFW_FALSE;
+
+ terminator = where + strlen(string);
+ if (where == start || *(where - 1) == ' ')
+ {
+ if (*terminator == ' ' || *terminator == '\0')
+ break;
+ }
+
+ start = terminator;
+ }
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window && window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
+ "Cannot make current with a window that has no OpenGL or OpenGL ES context");
+ return;
+ }
+
+ if (previous)
+ {
+ if (!window || window->context.source != previous->context.source)
+ previous->context.makeCurrent(NULL);
+ }
+
+ if (window)
+ window->context.makeCurrent(window);
+}
+
+GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfwPlatformGetTls(&_glfw.contextSlot);
+}
+
+GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
+ "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
+ return;
+ }
+
+ window->context.swapBuffers(window);
+}
+
+GLFWAPI void glfwSwapInterval(int interval)
+{
+ _GLFWwindow* window;
+
+ _GLFW_REQUIRE_INIT();
+
+ window = _glfwPlatformGetTls(&_glfw.contextSlot);
+ if (!window)
+ {
+ _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
+ "Cannot set swap interval without a current OpenGL or OpenGL ES context");
+ return;
+ }
+
+ window->context.swapInterval(interval);
+}
+
+GLFWAPI int glfwExtensionSupported(const char* extension)
+{
+ _GLFWwindow* window;
+ assert(extension != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ window = _glfwPlatformGetTls(&_glfw.contextSlot);
+ if (!window)
+ {
+ _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
+ "Cannot query extension without a current OpenGL or OpenGL ES context");
+ return GLFW_FALSE;
+ }
+
+ if (*extension == '\0')
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
+ return GLFW_FALSE;
+ }
+
+ if (window->context.major >= 3)
+ {
+ int i;
+ GLint count;
+
+ // Check if extension is in the modern OpenGL extensions string list
+
+ window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
+
+ for (i = 0; i < count; i++)
+ {
+ const char* en = (const char*)
+ window->context.GetStringi(GL_EXTENSIONS, i);
+ if (!en)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Extension string retrieval is broken");
+ return GLFW_FALSE;
+ }
+
+ if (strcmp(en, extension) == 0)
+ return GLFW_TRUE;
+ }
+ }
+ else
+ {
+ // Check if extension is in the old style OpenGL extensions string
+
+ const char* extensions = (const char*)
+ window->context.GetString(GL_EXTENSIONS);
+ if (!extensions)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Extension string retrieval is broken");
+ return GLFW_FALSE;
+ }
+
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+
+ // Check if extension is in the platform-specific string
+ return window->context.extensionSupported(extension);
+}
+
+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
+{
+ _GLFWwindow* window;
+ assert(procname != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ window = _glfwPlatformGetTls(&_glfw.contextSlot);
+ if (!window)
+ {
+ _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
+ "Cannot query entry point without a current OpenGL or OpenGL ES context");
+ return NULL;
+ }
+
+ return window->context.getProcAddress(procname);
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/egl_context.c b/Client/ThirdParty/Box2D/extern/glfw/src/egl_context.c
new file mode 100644
index 0000000..b2d11a4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/egl_context.c
@@ -0,0 +1,786 @@
+//========================================================================
+// GLFW 3.3 EGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+
+// Return a description of the specified EGL error
+//
+static const char* getEGLErrorString(EGLint error)
+{
+ switch (error)
+ {
+ case EGL_SUCCESS:
+ return "Success";
+ case EGL_NOT_INITIALIZED:
+ return "EGL is not or could not be initialized";
+ case EGL_BAD_ACCESS:
+ return "EGL cannot access a requested resource";
+ case EGL_BAD_ALLOC:
+ return "EGL failed to allocate resources for the requested operation";
+ case EGL_BAD_ATTRIBUTE:
+ return "An unrecognized attribute or attribute value was passed in the attribute list";
+ case EGL_BAD_CONTEXT:
+ return "An EGLContext argument does not name a valid EGL rendering context";
+ case EGL_BAD_CONFIG:
+ return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
+ case EGL_BAD_DISPLAY:
+ return "An EGLDisplay argument does not name a valid EGL display connection";
+ case EGL_BAD_SURFACE:
+ return "An EGLSurface argument does not name a valid surface configured for GL rendering";
+ case EGL_BAD_MATCH:
+ return "Arguments are inconsistent";
+ case EGL_BAD_PARAMETER:
+ return "One or more argument values are invalid";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "A NativePixmapType argument does not refer to a valid native pixmap";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "A NativeWindowType argument does not refer to a valid native window";
+ case EGL_CONTEXT_LOST:
+ return "The application must destroy all contexts and reinitialise";
+ default:
+ return "ERROR: UNKNOWN EGL ERROR";
+ }
+}
+
+// Returns the specified attribute of the specified EGLConfig
+//
+static int getEGLConfigAttrib(EGLConfig config, int attrib)
+{
+ int value;
+ eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
+ return value;
+}
+
+// Return the EGLConfig most closely matching the specified hints
+//
+static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* desired,
+ EGLConfig* result)
+{
+ EGLConfig* nativeConfigs;
+ _GLFWfbconfig* usableConfigs;
+ const _GLFWfbconfig* closest;
+ int i, nativeCount, usableCount;
+
+ eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
+ if (!nativeCount)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
+ return GLFW_FALSE;
+ }
+
+ nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
+ eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
+
+ usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+ usableCount = 0;
+
+ for (i = 0; i < nativeCount; i++)
+ {
+ const EGLConfig n = nativeConfigs[i];
+ _GLFWfbconfig* u = usableConfigs + usableCount;
+
+ // Only consider RGB(A) EGLConfigs
+ if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
+ continue;
+
+ // Only consider window EGLConfigs
+ if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
+ continue;
+
+#if defined(_GLFW_X11)
+ XVisualInfo vi = {0};
+
+ // Only consider EGLConfigs with associated Visuals
+ vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
+ if (!vi.visualid)
+ continue;
+
+ if (desired->transparent)
+ {
+ int count;
+ XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
+ VisualIDMask, &vi,
+ &count);
+ if (vis)
+ {
+ u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
+ XFree(vis);
+ }
+ }
+#endif // _GLFW_X11
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ if (ctxconfig->major == 1)
+ {
+ if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
+ continue;
+ }
+ else
+ {
+ if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
+ continue;
+ }
+ }
+ else if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
+ continue;
+ }
+
+ u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
+ u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
+ u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
+
+ u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
+ u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
+ u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
+
+ u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
+ u->doublebuffer = GLFW_TRUE;
+
+ u->handle = (uintptr_t) n;
+ usableCount++;
+ }
+
+ closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
+ if (closest)
+ *result = (EGLConfig) closest->handle;
+
+ free(nativeConfigs);
+ free(usableConfigs);
+
+ return closest != NULL;
+}
+
+static void makeContextCurrentEGL(_GLFWwindow* window)
+{
+ if (window)
+ {
+ if (!eglMakeCurrent(_glfw.egl.display,
+ window->context.egl.surface,
+ window->context.egl.surface,
+ window->context.egl.handle))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: Failed to make context current: %s",
+ getEGLErrorString(eglGetError()));
+ return;
+ }
+ }
+ else
+ {
+ if (!eglMakeCurrent(_glfw.egl.display,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ EGL_NO_CONTEXT))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: Failed to clear current context: %s",
+ getEGLErrorString(eglGetError()));
+ return;
+ }
+ }
+
+ _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static void swapBuffersEGL(_GLFWwindow* window)
+{
+ if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: The context must be current on the calling thread when swapping buffers");
+ return;
+ }
+
+ eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
+}
+
+static void swapIntervalEGL(int interval)
+{
+ eglSwapInterval(_glfw.egl.display, interval);
+}
+
+static int extensionSupportedEGL(const char* extension)
+{
+ const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
+ if (extensions)
+ {
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressEGL(const char* procname)
+{
+ _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+ if (window->context.egl.client)
+ {
+ GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
+ procname);
+ if (proc)
+ return proc;
+ }
+
+ return eglGetProcAddress(procname);
+}
+
+static void destroyContextEGL(_GLFWwindow* window)
+{
+#if defined(_GLFW_X11)
+ // NOTE: Do not unload libGL.so.1 while the X11 display is still open,
+ // as it will make XCloseDisplay segfault
+ if (window->context.client != GLFW_OPENGL_API)
+#endif // _GLFW_X11
+ {
+ if (window->context.egl.client)
+ {
+ _glfw_dlclose(window->context.egl.client);
+ window->context.egl.client = NULL;
+ }
+ }
+
+ if (window->context.egl.surface)
+ {
+ eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
+ window->context.egl.surface = EGL_NO_SURFACE;
+ }
+
+ if (window->context.egl.handle)
+ {
+ eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
+ window->context.egl.handle = EGL_NO_CONTEXT;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize EGL
+//
+GLFWbool _glfwInitEGL(void)
+{
+ int i;
+ const char* sonames[] =
+ {
+#if defined(_GLFW_EGL_LIBRARY)
+ _GLFW_EGL_LIBRARY,
+#elif defined(_GLFW_WIN32)
+ "libEGL.dll",
+ "EGL.dll",
+#elif defined(_GLFW_COCOA)
+ "libEGL.dylib",
+#elif defined(__CYGWIN__)
+ "libEGL-1.so",
+#else
+ "libEGL.so.1",
+#endif
+ NULL
+ };
+
+ if (_glfw.egl.handle)
+ return GLFW_TRUE;
+
+ for (i = 0; sonames[i]; i++)
+ {
+ _glfw.egl.handle = _glfw_dlopen(sonames[i]);
+ if (_glfw.egl.handle)
+ break;
+ }
+
+ if (!_glfw.egl.handle)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
+ return GLFW_FALSE;
+ }
+
+ _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
+
+ _glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
+ _glfw.egl.GetConfigs = (PFN_eglGetConfigs)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
+ _glfw.egl.GetDisplay = (PFN_eglGetDisplay)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
+ _glfw.egl.GetError = (PFN_eglGetError)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetError");
+ _glfw.egl.Initialize = (PFN_eglInitialize)
+ _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
+ _glfw.egl.Terminate = (PFN_eglTerminate)
+ _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
+ _glfw.egl.BindAPI = (PFN_eglBindAPI)
+ _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
+ _glfw.egl.CreateContext = (PFN_eglCreateContext)
+ _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
+ _glfw.egl.DestroySurface = (PFN_eglDestroySurface)
+ _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
+ _glfw.egl.DestroyContext = (PFN_eglDestroyContext)
+ _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
+ _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
+ _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
+ _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
+ _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
+ _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
+ _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
+ _glfw.egl.SwapInterval = (PFN_eglSwapInterval)
+ _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
+ _glfw.egl.QueryString = (PFN_eglQueryString)
+ _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
+ _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
+
+ if (!_glfw.egl.GetConfigAttrib ||
+ !_glfw.egl.GetConfigs ||
+ !_glfw.egl.GetDisplay ||
+ !_glfw.egl.GetError ||
+ !_glfw.egl.Initialize ||
+ !_glfw.egl.Terminate ||
+ !_glfw.egl.BindAPI ||
+ !_glfw.egl.CreateContext ||
+ !_glfw.egl.DestroySurface ||
+ !_glfw.egl.DestroyContext ||
+ !_glfw.egl.CreateWindowSurface ||
+ !_glfw.egl.MakeCurrent ||
+ !_glfw.egl.SwapBuffers ||
+ !_glfw.egl.SwapInterval ||
+ !_glfw.egl.QueryString ||
+ !_glfw.egl.GetProcAddress)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: Failed to load required entry points");
+
+ _glfwTerminateEGL();
+ return GLFW_FALSE;
+ }
+
+ _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
+ if (_glfw.egl.display == EGL_NO_DISPLAY)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "EGL: Failed to get EGL display: %s",
+ getEGLErrorString(eglGetError()));
+
+ _glfwTerminateEGL();
+ return GLFW_FALSE;
+ }
+
+ if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "EGL: Failed to initialize EGL: %s",
+ getEGLErrorString(eglGetError()));
+
+ _glfwTerminateEGL();
+ return GLFW_FALSE;
+ }
+
+ _glfw.egl.KHR_create_context =
+ extensionSupportedEGL("EGL_KHR_create_context");
+ _glfw.egl.KHR_create_context_no_error =
+ extensionSupportedEGL("EGL_KHR_create_context_no_error");
+ _glfw.egl.KHR_gl_colorspace =
+ extensionSupportedEGL("EGL_KHR_gl_colorspace");
+ _glfw.egl.KHR_get_all_proc_addresses =
+ extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
+ _glfw.egl.KHR_context_flush_control =
+ extensionSupportedEGL("EGL_KHR_context_flush_control");
+
+ return GLFW_TRUE;
+}
+
+// Terminate EGL
+//
+void _glfwTerminateEGL(void)
+{
+ if (_glfw.egl.display)
+ {
+ eglTerminate(_glfw.egl.display);
+ _glfw.egl.display = EGL_NO_DISPLAY;
+ }
+
+ if (_glfw.egl.handle)
+ {
+ _glfw_dlclose(_glfw.egl.handle);
+ _glfw.egl.handle = NULL;
+ }
+}
+
+#define setAttrib(a, v) \
+{ \
+ assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[index++] = a; \
+ attribs[index++] = v; \
+}
+
+// Create the OpenGL or OpenGL ES context
+//
+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ EGLint attribs[40];
+ EGLConfig config;
+ EGLContext share = NULL;
+ int index = 0;
+
+ if (!_glfw.egl.display)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->share)
+ share = ctxconfig->share->context.egl.handle;
+
+ if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "EGL: Failed to find a suitable EGLConfig");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ if (!eglBindAPI(EGL_OPENGL_ES_API))
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "EGL: Failed to bind OpenGL ES: %s",
+ getEGLErrorString(eglGetError()));
+ return GLFW_FALSE;
+ }
+ }
+ else
+ {
+ if (!eglBindAPI(EGL_OPENGL_API))
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "EGL: Failed to bind OpenGL: %s",
+ getEGLErrorString(eglGetError()));
+ return GLFW_FALSE;
+ }
+ }
+
+ if (_glfw.egl.KHR_create_context)
+ {
+ int mask = 0, flags = 0;
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (ctxconfig->forward)
+ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
+
+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
+ mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
+ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
+ mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
+ }
+
+ if (ctxconfig->debug)
+ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+
+ if (ctxconfig->robustness)
+ {
+ if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+ {
+ setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
+ EGL_NO_RESET_NOTIFICATION_KHR);
+ }
+ else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
+ EGL_LOSE_CONTEXT_ON_RESET_KHR);
+ }
+
+ flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+ }
+
+ if (ctxconfig->noerror)
+ {
+ if (_glfw.egl.KHR_create_context_no_error)
+ setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
+ }
+
+ if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+ {
+ setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
+ setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
+ }
+
+ if (mask)
+ setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
+
+ if (flags)
+ setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
+ }
+ else
+ {
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
+ }
+
+ if (_glfw.egl.KHR_context_flush_control)
+ {
+ if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
+ {
+ setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
+ EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
+ }
+ else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+ {
+ setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
+ EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
+ }
+ }
+
+ setAttrib(EGL_NONE, EGL_NONE);
+
+ window->context.egl.handle = eglCreateContext(_glfw.egl.display,
+ config, share, attribs);
+
+ if (window->context.egl.handle == EGL_NO_CONTEXT)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "EGL: Failed to create context: %s",
+ getEGLErrorString(eglGetError()));
+ return GLFW_FALSE;
+ }
+
+ // Set up attributes for surface creation
+ {
+ int index = 0;
+
+ if (fbconfig->sRGB)
+ {
+ if (_glfw.egl.KHR_gl_colorspace)
+ setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
+ }
+
+ setAttrib(EGL_NONE, EGL_NONE);
+ }
+
+ window->context.egl.surface =
+ eglCreateWindowSurface(_glfw.egl.display,
+ config,
+ _GLFW_EGL_NATIVE_WINDOW,
+ attribs);
+ if (window->context.egl.surface == EGL_NO_SURFACE)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: Failed to create window surface: %s",
+ getEGLErrorString(eglGetError()));
+ return GLFW_FALSE;
+ }
+
+ window->context.egl.config = config;
+
+ // Load the appropriate client library
+ if (!_glfw.egl.KHR_get_all_proc_addresses)
+ {
+ int i;
+ const char** sonames;
+ const char* es1sonames[] =
+ {
+#if defined(_GLFW_GLESV1_LIBRARY)
+ _GLFW_GLESV1_LIBRARY,
+#elif defined(_GLFW_WIN32)
+ "GLESv1_CM.dll",
+ "libGLES_CM.dll",
+#elif defined(_GLFW_COCOA)
+ "libGLESv1_CM.dylib",
+#else
+ "libGLESv1_CM.so.1",
+ "libGLES_CM.so.1",
+#endif
+ NULL
+ };
+ const char* es2sonames[] =
+ {
+#if defined(_GLFW_GLESV2_LIBRARY)
+ _GLFW_GLESV2_LIBRARY,
+#elif defined(_GLFW_WIN32)
+ "GLESv2.dll",
+ "libGLESv2.dll",
+#elif defined(_GLFW_COCOA)
+ "libGLESv2.dylib",
+#elif defined(__CYGWIN__)
+ "libGLESv2-2.so",
+#else
+ "libGLESv2.so.2",
+#endif
+ NULL
+ };
+ const char* glsonames[] =
+ {
+#if defined(_GLFW_OPENGL_LIBRARY)
+ _GLFW_OPENGL_LIBRARY,
+#elif defined(_GLFW_WIN32)
+#elif defined(_GLFW_COCOA)
+#else
+ "libGL.so.1",
+#endif
+ NULL
+ };
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ if (ctxconfig->major == 1)
+ sonames = es1sonames;
+ else
+ sonames = es2sonames;
+ }
+ else
+ sonames = glsonames;
+
+ for (i = 0; sonames[i]; i++)
+ {
+ // HACK: Match presence of lib prefix to increase chance of finding
+ // a matching pair in the jungle that is Win32 EGL/GLES
+ if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
+ continue;
+
+ window->context.egl.client = _glfw_dlopen(sonames[i]);
+ if (window->context.egl.client)
+ break;
+ }
+
+ if (!window->context.egl.client)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "EGL: Failed to load client library");
+ return GLFW_FALSE;
+ }
+ }
+
+ window->context.makeCurrent = makeContextCurrentEGL;
+ window->context.swapBuffers = swapBuffersEGL;
+ window->context.swapInterval = swapIntervalEGL;
+ window->context.extensionSupported = extensionSupportedEGL;
+ window->context.getProcAddress = getProcAddressEGL;
+ window->context.destroy = destroyContextEGL;
+
+ return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+// Returns the Visual and depth of the chosen EGLConfig
+//
+#if defined(_GLFW_X11)
+GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth)
+{
+ XVisualInfo* result;
+ XVisualInfo desired;
+ EGLConfig native;
+ EGLint visualID = 0, count = 0;
+ const long vimask = VisualScreenMask | VisualIDMask;
+
+ if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "EGL: Failed to find a suitable EGLConfig");
+ return GLFW_FALSE;
+ }
+
+ eglGetConfigAttrib(_glfw.egl.display, native,
+ EGL_NATIVE_VISUAL_ID, &visualID);
+
+ desired.screen = _glfw.x11.screen;
+ desired.visualid = visualID;
+
+ result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
+ if (!result)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: Failed to retrieve Visual for EGLConfig");
+ return GLFW_FALSE;
+ }
+
+ *visual = result->visual;
+ *depth = result->depth;
+
+ XFree(result);
+ return GLFW_TRUE;
+}
+#endif // _GLFW_X11
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
+ return _glfw.egl.display;
+}
+
+GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return EGL_NO_CONTEXT;
+ }
+
+ return window->context.egl.handle;
+}
+
+GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return EGL_NO_SURFACE;
+ }
+
+ return window->context.egl.surface;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/egl_context.h b/Client/ThirdParty/Box2D/extern/glfw/src/egl_context.h
new file mode 100644
index 0000000..8f3d075
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/egl_context.h
@@ -0,0 +1,215 @@
+//========================================================================
+// GLFW 3.3 EGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#if defined(_GLFW_USE_EGLPLATFORM_H)
+ #include <EGL/eglplatform.h>
+#elif defined(_GLFW_WIN32)
+ #define EGLAPIENTRY __stdcall
+typedef HDC EGLNativeDisplayType;
+typedef HWND EGLNativeWindowType;
+#elif defined(_GLFW_COCOA)
+ #define EGLAPIENTRY
+typedef void* EGLNativeDisplayType;
+typedef id EGLNativeWindowType;
+#elif defined(_GLFW_X11)
+ #define EGLAPIENTRY
+typedef Display* EGLNativeDisplayType;
+typedef Window EGLNativeWindowType;
+#elif defined(_GLFW_WAYLAND)
+ #define EGLAPIENTRY
+typedef struct wl_display* EGLNativeDisplayType;
+typedef struct wl_egl_window* EGLNativeWindowType;
+#else
+ #error "No supported EGL platform selected"
+#endif
+
+#define EGL_SUCCESS 0x3000
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300a
+#define EGL_BAD_NATIVE_WINDOW 0x300b
+#define EGL_BAD_PARAMETER 0x300c
+#define EGL_BAD_SURFACE 0x300d
+#define EGL_CONTEXT_LOST 0x300e
+#define EGL_COLOR_BUFFER_TYPE 0x303f
+#define EGL_RGB_BUFFER 0x308e
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_WINDOW_BIT 0x0004
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_OPENGL_ES_BIT 0x0001
+#define EGL_OPENGL_ES2_BIT 0x0004
+#define EGL_OPENGL_BIT 0x0008
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_RED_SIZE 0x3024
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_SAMPLES 0x3031
+#define EGL_OPENGL_ES_API 0x30a0
+#define EGL_OPENGL_API 0x30a2
+#define EGL_NONE 0x3038
+#define EGL_EXTENSIONS 0x3055
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+#define EGL_NATIVE_VISUAL_ID 0x302e
+#define EGL_NO_SURFACE ((EGLSurface) 0)
+#define EGL_NO_DISPLAY ((EGLDisplay) 0)
+#define EGL_NO_CONTEXT ((EGLContext) 0)
+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
+
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd
+#define EGL_NO_RESET_NOTIFICATION_KHR 0x31be
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd
+#define EGL_CONTEXT_FLAGS_KHR 0x30fc
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
+#define EGL_GL_COLORSPACE_KHR 0x309d
+#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+
+typedef int EGLint;
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef void* EGLConfig;
+typedef void* EGLContext;
+typedef void* EGLDisplay;
+typedef void* EGLSurface;
+
+// EGL function pointer typedefs
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
+typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
+typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
+typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
+typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
+typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
+typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
+#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
+#define eglGetConfigs _glfw.egl.GetConfigs
+#define eglGetDisplay _glfw.egl.GetDisplay
+#define eglGetError _glfw.egl.GetError
+#define eglInitialize _glfw.egl.Initialize
+#define eglTerminate _glfw.egl.Terminate
+#define eglBindAPI _glfw.egl.BindAPI
+#define eglCreateContext _glfw.egl.CreateContext
+#define eglDestroySurface _glfw.egl.DestroySurface
+#define eglDestroyContext _glfw.egl.DestroyContext
+#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
+#define eglMakeCurrent _glfw.egl.MakeCurrent
+#define eglSwapBuffers _glfw.egl.SwapBuffers
+#define eglSwapInterval _glfw.egl.SwapInterval
+#define eglQueryString _glfw.egl.QueryString
+#define eglGetProcAddress _glfw.egl.GetProcAddress
+
+#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
+
+
+// EGL-specific per-context data
+//
+typedef struct _GLFWcontextEGL
+{
+ EGLConfig config;
+ EGLContext handle;
+ EGLSurface surface;
+
+ void* client;
+
+} _GLFWcontextEGL;
+
+// EGL-specific global data
+//
+typedef struct _GLFWlibraryEGL
+{
+ EGLDisplay display;
+ EGLint major, minor;
+ GLFWbool prefix;
+
+ GLFWbool KHR_create_context;
+ GLFWbool KHR_create_context_no_error;
+ GLFWbool KHR_gl_colorspace;
+ GLFWbool KHR_get_all_proc_addresses;
+ GLFWbool KHR_context_flush_control;
+
+ void* handle;
+
+ PFN_eglGetConfigAttrib GetConfigAttrib;
+ PFN_eglGetConfigs GetConfigs;
+ PFN_eglGetDisplay GetDisplay;
+ PFN_eglGetError GetError;
+ PFN_eglInitialize Initialize;
+ PFN_eglTerminate Terminate;
+ PFN_eglBindAPI BindAPI;
+ PFN_eglCreateContext CreateContext;
+ PFN_eglDestroySurface DestroySurface;
+ PFN_eglDestroyContext DestroyContext;
+ PFN_eglCreateWindowSurface CreateWindowSurface;
+ PFN_eglMakeCurrent MakeCurrent;
+ PFN_eglSwapBuffers SwapBuffers;
+ PFN_eglSwapInterval SwapInterval;
+ PFN_eglQueryString QueryString;
+ PFN_eglGetProcAddress GetProcAddress;
+
+} _GLFWlibraryEGL;
+
+
+GLFWbool _glfwInitEGL(void);
+void _glfwTerminateEGL(void);
+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+#if defined(_GLFW_X11)
+GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth);
+#endif /*_GLFW_X11*/
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/glfw_config.h b/Client/ThirdParty/Box2D/extern/glfw/src/glfw_config.h
new file mode 100644
index 0000000..96d7b7f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/glfw_config.h
@@ -0,0 +1,45 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2010-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+// As glfw_config.h.in, this file is used by CMake to produce the
+// glfw_config.h configuration header file. If you are adding a feature
+// requiring conditional compilation, this is where to add the macro.
+//========================================================================
+// As glfw_config.h, this file defines compile-time option macros for a
+// specific platform and development environment. If you are using the
+// GLFW CMake files, modify glfw_config.h.in instead of this file. If you
+// are using your own build system, make this file define the appropriate
+// macros in whatever way is suitable.
+//========================================================================
+
+// MODIFIED_ERIN
+#ifdef _WIN32
+ #define _GLFW_WIN32
+ #define _CRT_SECURE_NO_WARNINGS
+#elif __APPLE__
+ #define _GLFW_COCOA
+#else
+ #define _GLFW_X11
+#endif
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/glx_context.c b/Client/ThirdParty/Box2D/extern/glfw/src/glx_context.c
new file mode 100644
index 0000000..adace82
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/glx_context.c
@@ -0,0 +1,698 @@
+//========================================================================
+// GLFW 3.3 GLX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifndef GLXBadProfileARB
+ #define GLXBadProfileARB 13
+#endif
+
+
+// Returns the specified attribute of the specified GLXFBConfig
+//
+static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
+{
+ int value;
+ glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
+ return value;
+}
+
+// Return the GLXFBConfig most closely matching the specified hints
+//
+static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
+ GLXFBConfig* result)
+{
+ GLXFBConfig* nativeConfigs;
+ _GLFWfbconfig* usableConfigs;
+ const _GLFWfbconfig* closest;
+ int i, nativeCount, usableCount;
+ const char* vendor;
+ GLFWbool trustWindowBit = GLFW_TRUE;
+
+ // HACK: This is a (hopefully temporary) workaround for Chromium
+ // (VirtualBox GL) not setting the window bit on any GLXFBConfigs
+ vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
+ if (vendor && strcmp(vendor, "Chromium") == 0)
+ trustWindowBit = GLFW_FALSE;
+
+ nativeConfigs =
+ glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
+ if (!nativeConfigs || !nativeCount)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
+ return GLFW_FALSE;
+ }
+
+ usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+ usableCount = 0;
+
+ for (i = 0; i < nativeCount; i++)
+ {
+ const GLXFBConfig n = nativeConfigs[i];
+ _GLFWfbconfig* u = usableConfigs + usableCount;
+
+ // Only consider RGBA GLXFBConfigs
+ if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
+ continue;
+
+ // Only consider window GLXFBConfigs
+ if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
+ {
+ if (trustWindowBit)
+ continue;
+ }
+
+ if (desired->transparent)
+ {
+ XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
+ if (vi)
+ {
+ u->transparent = _glfwIsVisualTransparentX11(vi->visual);
+ XFree(vi);
+ }
+ }
+
+ u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
+ u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
+ u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
+
+ u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
+ u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
+ u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
+
+ u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
+ u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
+ u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
+ u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
+
+ u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
+
+ if (getGLXFBConfigAttrib(n, GLX_STEREO))
+ u->stereo = GLFW_TRUE;
+ if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
+ u->doublebuffer = GLFW_TRUE;
+
+ if (_glfw.glx.ARB_multisample)
+ u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
+
+ if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
+ u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+
+ u->handle = (uintptr_t) n;
+ usableCount++;
+ }
+
+ closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
+ if (closest)
+ *result = (GLXFBConfig) closest->handle;
+
+ XFree(nativeConfigs);
+ free(usableConfigs);
+
+ return closest != NULL;
+}
+
+// Create the OpenGL context using legacy API
+//
+static GLXContext createLegacyContextGLX(_GLFWwindow* window,
+ GLXFBConfig fbconfig,
+ GLXContext share)
+{
+ return glXCreateNewContext(_glfw.x11.display,
+ fbconfig,
+ GLX_RGBA_TYPE,
+ share,
+ True);
+}
+
+static void makeContextCurrentGLX(_GLFWwindow* window)
+{
+ if (window)
+ {
+ if (!glXMakeCurrent(_glfw.x11.display,
+ window->context.glx.window,
+ window->context.glx.handle))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "GLX: Failed to make context current");
+ return;
+ }
+ }
+ else
+ {
+ if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "GLX: Failed to clear current context");
+ return;
+ }
+ }
+
+ _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static void swapBuffersGLX(_GLFWwindow* window)
+{
+ glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
+}
+
+static void swapIntervalGLX(int interval)
+{
+ _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+ if (_glfw.glx.EXT_swap_control)
+ {
+ _glfw.glx.SwapIntervalEXT(_glfw.x11.display,
+ window->context.glx.window,
+ interval);
+ }
+ else if (_glfw.glx.MESA_swap_control)
+ _glfw.glx.SwapIntervalMESA(interval);
+ else if (_glfw.glx.SGI_swap_control)
+ {
+ if (interval > 0)
+ _glfw.glx.SwapIntervalSGI(interval);
+ }
+}
+
+static int extensionSupportedGLX(const char* extension)
+{
+ const char* extensions =
+ glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
+ if (extensions)
+ {
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressGLX(const char* procname)
+{
+ if (_glfw.glx.GetProcAddress)
+ return _glfw.glx.GetProcAddress((const GLubyte*) procname);
+ else if (_glfw.glx.GetProcAddressARB)
+ return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
+ else
+ return _glfw_dlsym(_glfw.glx.handle, procname);
+}
+
+// Destroy the OpenGL context
+//
+static void destroyContextGLX(_GLFWwindow* window)
+{
+ if (window->context.glx.window)
+ {
+ glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
+ window->context.glx.window = None;
+ }
+
+ if (window->context.glx.handle)
+ {
+ glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
+ window->context.glx.handle = NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize GLX
+//
+GLFWbool _glfwInitGLX(void)
+{
+ int i;
+ const char* sonames[] =
+ {
+#if defined(_GLFW_GLX_LIBRARY)
+ _GLFW_GLX_LIBRARY,
+#elif defined(__CYGWIN__)
+ "libGL-1.so",
+#else
+ "libGL.so.1",
+ "libGL.so",
+#endif
+ NULL
+ };
+
+ if (_glfw.glx.handle)
+ return GLFW_TRUE;
+
+ for (i = 0; sonames[i]; i++)
+ {
+ _glfw.glx.handle = _glfw_dlopen(sonames[i]);
+ if (_glfw.glx.handle)
+ break;
+ }
+
+ if (!_glfw.glx.handle)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
+ return GLFW_FALSE;
+ }
+
+ _glfw.glx.GetFBConfigs =
+ _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
+ _glfw.glx.GetFBConfigAttrib =
+ _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
+ _glfw.glx.GetClientString =
+ _glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
+ _glfw.glx.QueryExtension =
+ _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
+ _glfw.glx.QueryVersion =
+ _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
+ _glfw.glx.DestroyContext =
+ _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
+ _glfw.glx.MakeCurrent =
+ _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
+ _glfw.glx.SwapBuffers =
+ _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
+ _glfw.glx.QueryExtensionsString =
+ _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
+ _glfw.glx.CreateNewContext =
+ _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
+ _glfw.glx.CreateWindow =
+ _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
+ _glfw.glx.DestroyWindow =
+ _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
+ _glfw.glx.GetProcAddress =
+ _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
+ _glfw.glx.GetProcAddressARB =
+ _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
+ _glfw.glx.GetVisualFromFBConfig =
+ _glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
+
+ if (!_glfw.glx.GetFBConfigs ||
+ !_glfw.glx.GetFBConfigAttrib ||
+ !_glfw.glx.GetClientString ||
+ !_glfw.glx.QueryExtension ||
+ !_glfw.glx.QueryVersion ||
+ !_glfw.glx.DestroyContext ||
+ !_glfw.glx.MakeCurrent ||
+ !_glfw.glx.SwapBuffers ||
+ !_glfw.glx.QueryExtensionsString ||
+ !_glfw.glx.CreateNewContext ||
+ !_glfw.glx.CreateWindow ||
+ !_glfw.glx.DestroyWindow ||
+ !_glfw.glx.GetProcAddress ||
+ !_glfw.glx.GetProcAddressARB ||
+ !_glfw.glx.GetVisualFromFBConfig)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "GLX: Failed to load required entry points");
+ return GLFW_FALSE;
+ }
+
+ if (!glXQueryExtension(_glfw.x11.display,
+ &_glfw.glx.errorBase,
+ &_glfw.glx.eventBase))
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
+ return GLFW_FALSE;
+ }
+
+ if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "GLX: Failed to query GLX version");
+ return GLFW_FALSE;
+ }
+
+ if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "GLX: GLX version 1.3 is required");
+ return GLFW_FALSE;
+ }
+
+ if (extensionSupportedGLX("GLX_EXT_swap_control"))
+ {
+ _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
+ getProcAddressGLX("glXSwapIntervalEXT");
+
+ if (_glfw.glx.SwapIntervalEXT)
+ _glfw.glx.EXT_swap_control = GLFW_TRUE;
+ }
+
+ if (extensionSupportedGLX("GLX_SGI_swap_control"))
+ {
+ _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
+ getProcAddressGLX("glXSwapIntervalSGI");
+
+ if (_glfw.glx.SwapIntervalSGI)
+ _glfw.glx.SGI_swap_control = GLFW_TRUE;
+ }
+
+ if (extensionSupportedGLX("GLX_MESA_swap_control"))
+ {
+ _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
+ getProcAddressGLX("glXSwapIntervalMESA");
+
+ if (_glfw.glx.SwapIntervalMESA)
+ _glfw.glx.MESA_swap_control = GLFW_TRUE;
+ }
+
+ if (extensionSupportedGLX("GLX_ARB_multisample"))
+ _glfw.glx.ARB_multisample = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
+ _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
+ _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_ARB_create_context"))
+ {
+ _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+ getProcAddressGLX("glXCreateContextAttribsARB");
+
+ if (_glfw.glx.CreateContextAttribsARB)
+ _glfw.glx.ARB_create_context = GLFW_TRUE;
+ }
+
+ if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
+ _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
+ _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
+ _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
+ _glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
+
+ if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
+ _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
+
+ return GLFW_TRUE;
+}
+
+// Terminate GLX
+//
+void _glfwTerminateGLX(void)
+{
+ // NOTE: This function must not call any X11 functions, as it is called
+ // after XCloseDisplay (see _glfwPlatformTerminate for details)
+
+ if (_glfw.glx.handle)
+ {
+ _glfw_dlclose(_glfw.glx.handle);
+ _glfw.glx.handle = NULL;
+ }
+}
+
+#define setAttrib(a, v) \
+{ \
+ assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[index++] = a; \
+ attribs[index++] = v; \
+}
+
+// Create the OpenGL or OpenGL ES context
+//
+GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ int attribs[40];
+ GLXFBConfig native = NULL;
+ GLXContext share = NULL;
+
+ if (ctxconfig->share)
+ share = ctxconfig->share->context.glx.handle;
+
+ if (!chooseGLXFBConfig(fbconfig, &native))
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "GLX: Failed to find a suitable GLXFBConfig");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ if (!_glfw.glx.ARB_create_context ||
+ !_glfw.glx.ARB_create_context_profile ||
+ !_glfw.glx.EXT_create_context_es2_profile)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->forward)
+ {
+ if (!_glfw.glx.ARB_create_context)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->profile)
+ {
+ if (!_glfw.glx.ARB_create_context ||
+ !_glfw.glx.ARB_create_context_profile)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
+ return GLFW_FALSE;
+ }
+ }
+
+ _glfwGrabErrorHandlerX11();
+
+ if (_glfw.glx.ARB_create_context)
+ {
+ int index = 0, mask = 0, flags = 0;
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (ctxconfig->forward)
+ flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+
+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
+ mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
+ mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+ else
+ mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
+
+ if (ctxconfig->debug)
+ flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
+
+ if (ctxconfig->robustness)
+ {
+ if (_glfw.glx.ARB_create_context_robustness)
+ {
+ if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+ {
+ setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ GLX_NO_RESET_NOTIFICATION_ARB);
+ }
+ else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ GLX_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
+ }
+ }
+
+ if (ctxconfig->release)
+ {
+ if (_glfw.glx.ARB_context_flush_control)
+ {
+ if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
+ {
+ setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+ }
+ else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+ {
+ setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+ }
+ }
+ }
+
+ if (ctxconfig->noerror)
+ {
+ if (_glfw.glx.ARB_create_context_no_error)
+ setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
+ }
+
+ // NOTE: Only request an explicitly versioned context when necessary, as
+ // explicitly requesting version 1.0 does not always return the
+ // highest version supported by the driver
+ if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+ {
+ setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
+ setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
+ }
+
+ if (mask)
+ setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
+
+ if (flags)
+ setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
+
+ setAttrib(None, None);
+
+ window->context.glx.handle =
+ _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
+ native,
+ share,
+ True,
+ attribs);
+
+ // HACK: This is a fallback for broken versions of the Mesa
+ // implementation of GLX_ARB_create_context_profile that fail
+ // default 1.0 context creation with a GLXBadProfileARB error in
+ // violation of the extension spec
+ if (!window->context.glx.handle)
+ {
+ if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
+ ctxconfig->client == GLFW_OPENGL_API &&
+ ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
+ ctxconfig->forward == GLFW_FALSE)
+ {
+ window->context.glx.handle =
+ createLegacyContextGLX(window, native, share);
+ }
+ }
+ }
+ else
+ {
+ window->context.glx.handle =
+ createLegacyContextGLX(window, native, share);
+ }
+
+ _glfwReleaseErrorHandlerX11();
+
+ if (!window->context.glx.handle)
+ {
+ _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
+ return GLFW_FALSE;
+ }
+
+ window->context.glx.window =
+ glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
+ if (!window->context.glx.window)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
+ return GLFW_FALSE;
+ }
+
+ window->context.makeCurrent = makeContextCurrentGLX;
+ window->context.swapBuffers = swapBuffersGLX;
+ window->context.swapInterval = swapIntervalGLX;
+ window->context.extensionSupported = extensionSupportedGLX;
+ window->context.getProcAddress = getProcAddressGLX;
+ window->context.destroy = destroyContextGLX;
+
+ return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+// Returns the Visual and depth of the chosen GLXFBConfig
+//
+GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth)
+{
+ GLXFBConfig native;
+ XVisualInfo* result;
+
+ if (!chooseGLXFBConfig(fbconfig, &native))
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "GLX: Failed to find a suitable GLXFBConfig");
+ return GLFW_FALSE;
+ }
+
+ result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
+ if (!result)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "GLX: Failed to retrieve Visual for GLXFBConfig");
+ return GLFW_FALSE;
+ }
+
+ *visual = result->visual;
+ *depth = result->depth;
+
+ XFree(result);
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return NULL;
+ }
+
+ return window->context.glx.handle;
+}
+
+GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(None);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return None;
+ }
+
+ return window->context.glx.window;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/glx_context.h b/Client/ThirdParty/Box2D/extern/glfw/src/glx_context.h
new file mode 100644
index 0000000..f767cb1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/glx_context.h
@@ -0,0 +1,181 @@
+//========================================================================
+// GLFW 3.3 GLX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define GLX_VENDOR 1
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_SAMPLES 0x186a1
+#define GLX_VISUAL_ID 0x800b
+
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
+
+typedef XID GLXWindow;
+typedef XID GLXDrawable;
+typedef struct __GLXFBConfig* GLXFBConfig;
+typedef struct __GLXcontext* GLXContext;
+typedef void (*__GLXextproc)(void);
+
+typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
+typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
+typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
+typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
+typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext);
+typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext);
+typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);
+typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);
+typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*);
+typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool);
+typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName);
+typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
+typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
+typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
+typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
+
+typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
+typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
+
+// libGL.so function pointer typedefs
+#define glXGetFBConfigs _glfw.glx.GetFBConfigs
+#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
+#define glXGetClientString _glfw.glx.GetClientString
+#define glXQueryExtension _glfw.glx.QueryExtension
+#define glXQueryVersion _glfw.glx.QueryVersion
+#define glXDestroyContext _glfw.glx.DestroyContext
+#define glXMakeCurrent _glfw.glx.MakeCurrent
+#define glXSwapBuffers _glfw.glx.SwapBuffers
+#define glXQueryExtensionsString _glfw.glx.QueryExtensionsString
+#define glXCreateNewContext _glfw.glx.CreateNewContext
+#define glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig
+#define glXCreateWindow _glfw.glx.CreateWindow
+#define glXDestroyWindow _glfw.glx.DestroyWindow
+
+#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx
+
+
+// GLX-specific per-context data
+//
+typedef struct _GLFWcontextGLX
+{
+ GLXContext handle;
+ GLXWindow window;
+
+} _GLFWcontextGLX;
+
+// GLX-specific global data
+//
+typedef struct _GLFWlibraryGLX
+{
+ int major, minor;
+ int eventBase;
+ int errorBase;
+
+ // dlopen handle for libGL.so.1
+ void* handle;
+
+ // GLX 1.3 functions
+ PFNGLXGETFBCONFIGSPROC GetFBConfigs;
+ PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;
+ PFNGLXGETCLIENTSTRINGPROC GetClientString;
+ PFNGLXQUERYEXTENSIONPROC QueryExtension;
+ PFNGLXQUERYVERSIONPROC QueryVersion;
+ PFNGLXDESTROYCONTEXTPROC DestroyContext;
+ PFNGLXMAKECURRENTPROC MakeCurrent;
+ PFNGLXSWAPBUFFERSPROC SwapBuffers;
+ PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString;
+ PFNGLXCREATENEWCONTEXTPROC CreateNewContext;
+ PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig;
+ PFNGLXCREATEWINDOWPROC CreateWindow;
+ PFNGLXDESTROYWINDOWPROC DestroyWindow;
+
+ // GLX 1.4 and extension functions
+ PFNGLXGETPROCADDRESSPROC GetProcAddress;
+ PFNGLXGETPROCADDRESSPROC GetProcAddressARB;
+ PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
+ PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
+ PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
+ PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
+ GLFWbool SGI_swap_control;
+ GLFWbool EXT_swap_control;
+ GLFWbool MESA_swap_control;
+ GLFWbool ARB_multisample;
+ GLFWbool ARB_framebuffer_sRGB;
+ GLFWbool EXT_framebuffer_sRGB;
+ GLFWbool ARB_create_context;
+ GLFWbool ARB_create_context_profile;
+ GLFWbool ARB_create_context_robustness;
+ GLFWbool EXT_create_context_es2_profile;
+ GLFWbool ARB_create_context_no_error;
+ GLFWbool ARB_context_flush_control;
+
+} _GLFWlibraryGLX;
+
+GLFWbool _glfwInitGLX(void);
+void _glfwTerminateGLX(void);
+GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+void _glfwDestroyContextGLX(_GLFWwindow* window);
+GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/init.c b/Client/ThirdParty/Box2D/extern/glfw/src/init.c
new file mode 100644
index 0000000..4f424c4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/init.c
@@ -0,0 +1,338 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+#include "mappings.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+
+// The global variables below comprise all mutable global data in GLFW
+//
+// Any other global variable is a bug
+
+// Global state shared between compilation units of GLFW
+//
+_GLFWlibrary _glfw = { GLFW_FALSE };
+
+// These are outside of _glfw so they can be used before initialization and
+// after termination
+//
+static _GLFWerror _glfwMainThreadError;
+static GLFWerrorfun _glfwErrorCallback;
+static _GLFWinitconfig _glfwInitHints =
+{
+ GLFW_TRUE, // hat buttons
+ {
+ GLFW_TRUE, // macOS menu bar
+ GLFW_TRUE // macOS bundle chdir
+ }
+};
+
+// Terminate the library
+//
+static void terminate(void)
+{
+ int i;
+
+ memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
+
+ while (_glfw.windowListHead)
+ glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
+
+ while (_glfw.cursorListHead)
+ glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ {
+ _GLFWmonitor* monitor = _glfw.monitors[i];
+ if (monitor->originalRamp.size)
+ _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
+ _glfwFreeMonitor(monitor);
+ }
+
+ free(_glfw.monitors);
+ _glfw.monitors = NULL;
+ _glfw.monitorCount = 0;
+
+ free(_glfw.mappings);
+ _glfw.mappings = NULL;
+ _glfw.mappingCount = 0;
+
+ _glfwTerminateVulkan();
+ _glfwPlatformTerminate();
+
+ _glfw.initialized = GLFW_FALSE;
+
+ while (_glfw.errorListHead)
+ {
+ _GLFWerror* error = _glfw.errorListHead;
+ _glfw.errorListHead = error->next;
+ free(error);
+ }
+
+ _glfwPlatformDestroyTls(&_glfw.contextSlot);
+ _glfwPlatformDestroyTls(&_glfw.errorSlot);
+ _glfwPlatformDestroyMutex(&_glfw.errorLock);
+
+ memset(&_glfw, 0, sizeof(_glfw));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+char* _glfw_strdup(const char* source)
+{
+ const size_t length = strlen(source);
+ char* result = calloc(length + 1, 1);
+ strcpy(result, source);
+ return result;
+}
+
+float _glfw_fminf(float a, float b)
+{
+ if (a != a)
+ return b;
+ else if (b != b)
+ return a;
+ else if (a < b)
+ return a;
+ else
+ return b;
+}
+
+float _glfw_fmaxf(float a, float b)
+{
+ if (a != a)
+ return b;
+ else if (b != b)
+ return a;
+ else if (a > b)
+ return a;
+ else
+ return b;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code of an error
+//
+void _glfwInputError(int code, const char* format, ...)
+{
+ _GLFWerror* error;
+ char description[_GLFW_MESSAGE_SIZE];
+
+ if (format)
+ {
+ va_list vl;
+
+ va_start(vl, format);
+ vsnprintf(description, sizeof(description), format, vl);
+ va_end(vl);
+
+ description[sizeof(description) - 1] = '\0';
+ }
+ else
+ {
+ if (code == GLFW_NOT_INITIALIZED)
+ strcpy(description, "The GLFW library is not initialized");
+ else if (code == GLFW_NO_CURRENT_CONTEXT)
+ strcpy(description, "There is no current context");
+ else if (code == GLFW_INVALID_ENUM)
+ strcpy(description, "Invalid argument for enum parameter");
+ else if (code == GLFW_INVALID_VALUE)
+ strcpy(description, "Invalid value for parameter");
+ else if (code == GLFW_OUT_OF_MEMORY)
+ strcpy(description, "Out of memory");
+ else if (code == GLFW_API_UNAVAILABLE)
+ strcpy(description, "The requested API is unavailable");
+ else if (code == GLFW_VERSION_UNAVAILABLE)
+ strcpy(description, "The requested API version is unavailable");
+ else if (code == GLFW_PLATFORM_ERROR)
+ strcpy(description, "A platform-specific error occurred");
+ else if (code == GLFW_FORMAT_UNAVAILABLE)
+ strcpy(description, "The requested format is unavailable");
+ else if (code == GLFW_NO_WINDOW_CONTEXT)
+ strcpy(description, "The specified window has no context");
+ else
+ strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
+ }
+
+ if (_glfw.initialized)
+ {
+ error = _glfwPlatformGetTls(&_glfw.errorSlot);
+ if (!error)
+ {
+ error = calloc(1, sizeof(_GLFWerror));
+ _glfwPlatformSetTls(&_glfw.errorSlot, error);
+ _glfwPlatformLockMutex(&_glfw.errorLock);
+ error->next = _glfw.errorListHead;
+ _glfw.errorListHead = error;
+ _glfwPlatformUnlockMutex(&_glfw.errorLock);
+ }
+ }
+ else
+ error = &_glfwMainThreadError;
+
+ error->code = code;
+ strcpy(error->description, description);
+
+ if (_glfwErrorCallback)
+ _glfwErrorCallback(code, description);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwInit(void)
+{
+ if (_glfw.initialized)
+ return GLFW_TRUE;
+
+ memset(&_glfw, 0, sizeof(_glfw));
+ _glfw.hints.init = _glfwInitHints;
+
+ if (!_glfwPlatformInit())
+ {
+ terminate();
+ return GLFW_FALSE;
+ }
+
+ if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
+ !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
+ !_glfwPlatformCreateTls(&_glfw.contextSlot))
+ {
+ terminate();
+ return GLFW_FALSE;
+ }
+
+ _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
+
+ _glfw.initialized = GLFW_TRUE;
+ _glfw.timer.offset = _glfwPlatformGetTimerValue();
+
+ glfwDefaultWindowHints();
+
+ {
+ int i;
+
+ for (i = 0; _glfwDefaultMappings[i]; i++)
+ {
+ if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
+ {
+ terminate();
+ return GLFW_FALSE;
+ }
+ }
+ }
+
+ return GLFW_TRUE;
+}
+
+GLFWAPI void glfwTerminate(void)
+{
+ if (!_glfw.initialized)
+ return;
+
+ terminate();
+}
+
+GLFWAPI void glfwInitHint(int hint, int value)
+{
+ switch (hint)
+ {
+ case GLFW_JOYSTICK_HAT_BUTTONS:
+ _glfwInitHints.hatButtons = value;
+ return;
+ case GLFW_COCOA_CHDIR_RESOURCES:
+ _glfwInitHints.ns.chdir = value;
+ return;
+ case GLFW_COCOA_MENUBAR:
+ _glfwInitHints.ns.menubar = value;
+ return;
+ }
+
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid init hint 0x%08X", hint);
+}
+
+GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
+{
+ if (major != NULL)
+ *major = GLFW_VERSION_MAJOR;
+ if (minor != NULL)
+ *minor = GLFW_VERSION_MINOR;
+ if (rev != NULL)
+ *rev = GLFW_VERSION_REVISION;
+}
+
+GLFWAPI const char* glfwGetVersionString(void)
+{
+ return _glfwPlatformGetVersionString();
+}
+
+GLFWAPI int glfwGetError(const char** description)
+{
+ _GLFWerror* error;
+ int code = GLFW_NO_ERROR;
+
+ if (description)
+ *description = NULL;
+
+ if (_glfw.initialized)
+ error = _glfwPlatformGetTls(&_glfw.errorSlot);
+ else
+ error = &_glfwMainThreadError;
+
+ if (error)
+ {
+ code = error->code;
+ error->code = GLFW_NO_ERROR;
+ if (description && code)
+ *description = error->description;
+ }
+
+ return code;
+}
+
+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
+{
+ _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
+ return cbfun;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/input.c b/Client/ThirdParty/Box2D/extern/glfw/src/input.c
new file mode 100644
index 0000000..460e9f3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/input.c
@@ -0,0 +1,1307 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Internal key state used for sticky keys
+#define _GLFW_STICK 3
+
+// Internal constants for gamepad mapping source types
+#define _GLFW_JOYSTICK_AXIS 1
+#define _GLFW_JOYSTICK_BUTTON 2
+#define _GLFW_JOYSTICK_HATBIT 3
+
+// Finds a mapping based on joystick GUID
+//
+static _GLFWmapping* findMapping(const char* guid)
+{
+ int i;
+
+ for (i = 0; i < _glfw.mappingCount; i++)
+ {
+ if (strcmp(_glfw.mappings[i].guid, guid) == 0)
+ return _glfw.mappings + i;
+ }
+
+ return NULL;
+}
+
+// Checks whether a gamepad mapping element is present in the hardware
+//
+static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
+ const _GLFWjoystick* js)
+{
+ if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
+ return GLFW_FALSE;
+ else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
+ return GLFW_FALSE;
+ else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
+ return GLFW_FALSE;
+
+ return GLFW_TRUE;
+}
+
+// Finds a mapping based on joystick GUID and verifies element indices
+//
+static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
+{
+ _GLFWmapping* mapping = findMapping(js->guid);
+ if (mapping)
+ {
+ int i;
+
+ for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
+ {
+ if (!isValidElementForJoystick(mapping->buttons + i, js))
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid button in gamepad mapping %s (%s)",
+ mapping->guid,
+ mapping->name);
+ return NULL;
+ }
+ }
+
+ for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
+ {
+ if (!isValidElementForJoystick(mapping->axes + i, js))
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid axis in gamepad mapping %s (%s)",
+ mapping->guid,
+ mapping->name);
+ return NULL;
+ }
+ }
+ }
+
+ return mapping;
+}
+
+// Parses an SDL_GameControllerDB line and adds it to the mapping list
+//
+static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
+{
+ const char* c = string;
+ size_t i, length;
+ struct
+ {
+ const char* name;
+ _GLFWmapelement* element;
+ } fields[] =
+ {
+ { "platform", NULL },
+ { "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
+ { "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
+ { "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
+ { "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
+ { "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
+ { "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
+ { "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
+ { "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
+ { "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
+ { "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
+ { "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
+ { "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
+ { "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
+ { "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
+ { "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
+ { "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
+ { "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
+ { "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
+ { "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
+ { "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
+ { "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
+ };
+
+ length = strcspn(c, ",");
+ if (length != 32 || c[length] != ',')
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, NULL);
+ return GLFW_FALSE;
+ }
+
+ memcpy(mapping->guid, c, length);
+ c += length + 1;
+
+ length = strcspn(c, ",");
+ if (length >= sizeof(mapping->name) || c[length] != ',')
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, NULL);
+ return GLFW_FALSE;
+ }
+
+ memcpy(mapping->name, c, length);
+ c += length + 1;
+
+ while (*c)
+ {
+ // TODO: Implement output modifiers
+ if (*c == '+' || *c == '-')
+ return GLFW_FALSE;
+
+ for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
+ {
+ length = strlen(fields[i].name);
+ if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
+ continue;
+
+ c += length + 1;
+
+ if (fields[i].element)
+ {
+ _GLFWmapelement* e = fields[i].element;
+ int8_t minimum = -1;
+ int8_t maximum = 1;
+
+ if (*c == '+')
+ {
+ minimum = 0;
+ c += 1;
+ }
+ else if (*c == '-')
+ {
+ maximum = 0;
+ c += 1;
+ }
+
+ if (*c == 'a')
+ e->type = _GLFW_JOYSTICK_AXIS;
+ else if (*c == 'b')
+ e->type = _GLFW_JOYSTICK_BUTTON;
+ else if (*c == 'h')
+ e->type = _GLFW_JOYSTICK_HATBIT;
+ else
+ break;
+
+ if (e->type == _GLFW_JOYSTICK_HATBIT)
+ {
+ const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
+ const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
+ e->index = (uint8_t) ((hat << 4) | bit);
+ }
+ else
+ e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
+
+ if (e->type == _GLFW_JOYSTICK_AXIS)
+ {
+ e->axisScale = 2 / (maximum - minimum);
+ e->axisOffset = -(maximum + minimum);
+
+ if (*c == '~')
+ {
+ e->axisScale = -e->axisScale;
+ e->axisOffset = -e->axisOffset;
+ }
+ }
+ }
+ else
+ {
+ length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
+ if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
+ return GLFW_FALSE;
+ }
+
+ break;
+ }
+
+ c += strcspn(c, ",");
+ c += strspn(c, ",");
+ }
+
+ for (i = 0; i < 32; i++)
+ {
+ if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
+ mapping->guid[i] += 'a' - 'A';
+ }
+
+ _glfwPlatformUpdateGamepadGUID(mapping->guid);
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code of a physical key event
+//
+void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+ if (key >= 0 && key <= GLFW_KEY_LAST)
+ {
+ GLFWbool repeated = GLFW_FALSE;
+
+ if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
+ return;
+
+ if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
+ repeated = GLFW_TRUE;
+
+ if (action == GLFW_RELEASE && window->stickyKeys)
+ window->keys[key] = _GLFW_STICK;
+ else
+ window->keys[key] = (char) action;
+
+ if (repeated)
+ action = GLFW_REPEAT;
+ }
+
+ if (!window->lockKeyMods)
+ mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
+
+ if (window->callbacks.key)
+ window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
+}
+
+// Notifies shared code of a Unicode codepoint input event
+// The 'plain' parameter determines whether to emit a regular character event
+//
+void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
+{
+ if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
+ return;
+
+ if (!window->lockKeyMods)
+ mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
+
+ if (window->callbacks.charmods)
+ window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
+
+ if (plain)
+ {
+ if (window->callbacks.character)
+ window->callbacks.character((GLFWwindow*) window, codepoint);
+ }
+}
+
+// Notifies shared code of a scroll event
+//
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
+{
+ if (window->callbacks.scroll)
+ window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
+}
+
+// Notifies shared code of a mouse button click event
+//
+void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
+{
+ if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
+ return;
+
+ if (!window->lockKeyMods)
+ mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
+
+ if (action == GLFW_RELEASE && window->stickyMouseButtons)
+ window->mouseButtons[button] = _GLFW_STICK;
+ else
+ window->mouseButtons[button] = (char) action;
+
+ if (window->callbacks.mouseButton)
+ window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
+}
+
+// Notifies shared code of a cursor motion event
+// The position is specified in client-area relative screen coordinates
+//
+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
+{
+ if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
+ return;
+
+ window->virtualCursorPosX = xpos;
+ window->virtualCursorPosY = ypos;
+
+ if (window->callbacks.cursorPos)
+ window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
+}
+
+// Notifies shared code of a cursor enter/leave event
+//
+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
+{
+ if (window->callbacks.cursorEnter)
+ window->callbacks.cursorEnter((GLFWwindow*) window, entered);
+}
+
+// Notifies shared code of files or directories dropped on a window
+//
+void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
+{
+ if (window->callbacks.drop)
+ window->callbacks.drop((GLFWwindow*) window, count, paths);
+}
+
+// Notifies shared code of a joystick connection or disconnection
+//
+void _glfwInputJoystick(_GLFWjoystick* js, int event)
+{
+ const int jid = (int) (js - _glfw.joysticks);
+
+ if (_glfw.callbacks.joystick)
+ _glfw.callbacks.joystick(jid, event);
+}
+
+// Notifies shared code of the new value of a joystick axis
+//
+void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
+{
+ js->axes[axis] = value;
+}
+
+// Notifies shared code of the new value of a joystick button
+//
+void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
+{
+ js->buttons[button] = value;
+}
+
+// Notifies shared code of the new value of a joystick hat
+//
+void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
+{
+ const int base = js->buttonCount + hat * 4;
+
+ js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
+ js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
+ js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
+ js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
+
+ js->hats[hat] = value;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Returns an available joystick object with arrays and name allocated
+//
+_GLFWjoystick* _glfwAllocJoystick(const char* name,
+ const char* guid,
+ int axisCount,
+ int buttonCount,
+ int hatCount)
+{
+ int jid;
+ _GLFWjoystick* js;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ if (!_glfw.joysticks[jid].present)
+ break;
+ }
+
+ if (jid > GLFW_JOYSTICK_LAST)
+ return NULL;
+
+ js = _glfw.joysticks + jid;
+ js->present = GLFW_TRUE;
+ js->name = _glfw_strdup(name);
+ js->axes = calloc(axisCount, sizeof(float));
+ js->buttons = calloc(buttonCount + hatCount * 4, 1);
+ js->hats = calloc(hatCount, 1);
+ js->axisCount = axisCount;
+ js->buttonCount = buttonCount;
+ js->hatCount = hatCount;
+
+ strcpy(js->guid, guid);
+ js->mapping = findValidMapping(js);
+
+ return js;
+}
+
+// Frees arrays and name and flags the joystick object as unused
+//
+void _glfwFreeJoystick(_GLFWjoystick* js)
+{
+ free(js->name);
+ free(js->axes);
+ free(js->buttons);
+ free(js->hats);
+ memset(js, 0, sizeof(_GLFWjoystick));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+
+ switch (mode)
+ {
+ case GLFW_CURSOR:
+ return window->cursorMode;
+ case GLFW_STICKY_KEYS:
+ return window->stickyKeys;
+ case GLFW_STICKY_MOUSE_BUTTONS:
+ return window->stickyMouseButtons;
+ case GLFW_LOCK_KEY_MODS:
+ return window->lockKeyMods;
+ }
+
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
+ return 0;
+}
+
+GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (mode == GLFW_CURSOR)
+ {
+ if (value != GLFW_CURSOR_NORMAL &&
+ value != GLFW_CURSOR_HIDDEN &&
+ value != GLFW_CURSOR_DISABLED)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid cursor mode 0x%08X",
+ value);
+ return;
+ }
+
+ if (window->cursorMode == value)
+ return;
+
+ window->cursorMode = value;
+
+ _glfwPlatformGetCursorPos(window,
+ &window->virtualCursorPosX,
+ &window->virtualCursorPosY);
+ _glfwPlatformSetCursorMode(window, value);
+ }
+ else if (mode == GLFW_STICKY_KEYS)
+ {
+ value = value ? GLFW_TRUE : GLFW_FALSE;
+ if (window->stickyKeys == value)
+ return;
+
+ if (!value)
+ {
+ int i;
+
+ // Release all sticky keys
+ for (i = 0; i <= GLFW_KEY_LAST; i++)
+ {
+ if (window->keys[i] == _GLFW_STICK)
+ window->keys[i] = GLFW_RELEASE;
+ }
+ }
+
+ window->stickyKeys = value;
+ }
+ else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
+ {
+ value = value ? GLFW_TRUE : GLFW_FALSE;
+ if (window->stickyMouseButtons == value)
+ return;
+
+ if (!value)
+ {
+ int i;
+
+ // Release all sticky mouse buttons
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
+ {
+ if (window->mouseButtons[i] == _GLFW_STICK)
+ window->mouseButtons[i] = GLFW_RELEASE;
+ }
+ }
+
+ window->stickyMouseButtons = value;
+ }
+ else if (mode == GLFW_LOCK_KEY_MODS)
+ window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
+ else
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
+}
+
+GLFWAPI const char* glfwGetKeyName(int key, int scancode)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (key != GLFW_KEY_UNKNOWN)
+ {
+ if (key != GLFW_KEY_KP_EQUAL &&
+ (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
+ (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
+ {
+ return NULL;
+ }
+
+ scancode = _glfwPlatformGetKeyScancode(key);
+ }
+
+ return _glfwPlatformGetScancodeName(scancode);
+}
+
+GLFWAPI int glfwGetKeyScancode(int key)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(-1);
+
+ if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
+ return GLFW_RELEASE;
+ }
+
+ return _glfwPlatformGetKeyScancode(key);
+}
+
+GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
+
+ if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
+ return GLFW_RELEASE;
+ }
+
+ if (window->keys[key] == _GLFW_STICK)
+ {
+ // Sticky mode: release key now
+ window->keys[key] = GLFW_RELEASE;
+ return GLFW_PRESS;
+ }
+
+ return (int) window->keys[key];
+}
+
+GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
+
+ if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
+ return GLFW_RELEASE;
+ }
+
+ if (window->mouseButtons[button] == _GLFW_STICK)
+ {
+ // Sticky mode: release mouse button now
+ window->mouseButtons[button] = GLFW_RELEASE;
+ return GLFW_PRESS;
+ }
+
+ return (int) window->mouseButtons[button];
+}
+
+GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ if (xpos)
+ *xpos = 0;
+ if (ypos)
+ *ypos = 0;
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ if (xpos)
+ *xpos = window->virtualCursorPosX;
+ if (ypos)
+ *ypos = window->virtualCursorPosY;
+ }
+ else
+ _glfwPlatformGetCursorPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
+ ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid cursor position %f %f",
+ xpos, ypos);
+ return;
+ }
+
+ if (!_glfwPlatformWindowFocused(window))
+ return;
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ // Only update the accumulated position if the cursor is disabled
+ window->virtualCursorPosX = xpos;
+ window->virtualCursorPosY = ypos;
+ }
+ else
+ {
+ // Update system cursor position
+ _glfwPlatformSetCursorPos(window, xpos, ypos);
+ }
+}
+
+GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
+{
+ _GLFWcursor* cursor;
+
+ assert(image != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ cursor = calloc(1, sizeof(_GLFWcursor));
+ cursor->next = _glfw.cursorListHead;
+ _glfw.cursorListHead = cursor;
+
+ if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot))
+ {
+ glfwDestroyCursor((GLFWcursor*) cursor);
+ return NULL;
+ }
+
+ return (GLFWcursor*) cursor;
+}
+
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
+{
+ _GLFWcursor* cursor;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (shape != GLFW_ARROW_CURSOR &&
+ shape != GLFW_IBEAM_CURSOR &&
+ shape != GLFW_CROSSHAIR_CURSOR &&
+ shape != GLFW_HAND_CURSOR &&
+ shape != GLFW_HRESIZE_CURSOR &&
+ shape != GLFW_VRESIZE_CURSOR)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
+ return NULL;
+ }
+
+ cursor = calloc(1, sizeof(_GLFWcursor));
+ cursor->next = _glfw.cursorListHead;
+ _glfw.cursorListHead = cursor;
+
+ if (!_glfwPlatformCreateStandardCursor(cursor, shape))
+ {
+ glfwDestroyCursor((GLFWcursor*) cursor);
+ return NULL;
+ }
+
+ return (GLFWcursor*) cursor;
+}
+
+GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
+{
+ _GLFWcursor* cursor = (_GLFWcursor*) handle;
+
+ _GLFW_REQUIRE_INIT();
+
+ if (cursor == NULL)
+ return;
+
+ // Make sure the cursor is not being used by any window
+ {
+ _GLFWwindow* window;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ {
+ if (window->cursor == cursor)
+ glfwSetCursor((GLFWwindow*) window, NULL);
+ }
+ }
+
+ _glfwPlatformDestroyCursor(cursor);
+
+ // Unlink cursor from global linked list
+ {
+ _GLFWcursor** prev = &_glfw.cursorListHead;
+
+ while (*prev != cursor)
+ prev = &((*prev)->next);
+
+ *prev = cursor->next;
+ }
+
+ free(cursor);
+}
+
+GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) windowHandle;
+ _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ window->cursor = cursor;
+
+ _glfwPlatformSetCursor(window, cursor);
+}
+
+GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.key, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.character, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
+ GLFWmousebuttonfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
+ GLFWcursorposfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
+ GLFWcursorenterfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
+ GLFWscrollfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun);
+ return cbfun;
+}
+
+GLFWAPI int glfwJoystickPresent(int jid)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return GLFW_FALSE;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return GLFW_FALSE;
+
+ return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
+}
+
+GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+ assert(count != NULL);
+
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return NULL;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
+ return NULL;
+
+ *count = js->axisCount;
+ return js->axes;
+}
+
+GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+ assert(count != NULL);
+
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return NULL;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
+ return NULL;
+
+ if (_glfw.hints.init.hatButtons)
+ *count = js->buttonCount + js->hatCount * 4;
+ else
+ *count = js->buttonCount;
+
+ return js->buttons;
+}
+
+GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+ assert(count != NULL);
+
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return NULL;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
+ return NULL;
+
+ *count = js->hatCount;
+ return js->hats;
+}
+
+GLFWAPI const char* glfwGetJoystickName(int jid)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return NULL;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+ return NULL;
+
+ return js->name;
+}
+
+GLFWAPI const char* glfwGetJoystickGUID(int jid)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return NULL;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+ return NULL;
+
+ return js->guid;
+}
+
+GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT();
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return;
+
+ js->userPointer = pointer;
+}
+
+GLFWAPI void* glfwGetJoystickUserPointer(int jid)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ return js->userPointer;
+}
+
+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
+ return cbfun;
+}
+
+GLFWAPI int glfwUpdateGamepadMappings(const char* string)
+{
+ int jid;
+ const char* c = string;
+
+ assert(string != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ while (*c)
+ {
+ if ((*c >= '0' && *c <= '9') ||
+ (*c >= 'a' && *c <= 'f') ||
+ (*c >= 'A' && *c <= 'F'))
+ {
+ char line[1024];
+
+ const size_t length = strcspn(c, "\r\n");
+ if (length < sizeof(line))
+ {
+ _GLFWmapping mapping = {{0}};
+
+ memcpy(line, c, length);
+ line[length] = '\0';
+
+ if (parseMapping(&mapping, line))
+ {
+ _GLFWmapping* previous = findMapping(mapping.guid);
+ if (previous)
+ *previous = mapping;
+ else
+ {
+ _glfw.mappingCount++;
+ _glfw.mappings =
+ realloc(_glfw.mappings,
+ sizeof(_GLFWmapping) * _glfw.mappingCount);
+ _glfw.mappings[_glfw.mappingCount - 1] = mapping;
+ }
+ }
+ }
+
+ c += length;
+ }
+ else
+ {
+ c += strcspn(c, "\r\n");
+ c += strspn(c, "\r\n");
+ }
+ }
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ _GLFWjoystick* js = _glfw.joysticks + jid;
+ if (js->present)
+ js->mapping = findValidMapping(js);
+ }
+
+ return GLFW_TRUE;
+}
+
+GLFWAPI int glfwJoystickIsGamepad(int jid)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return GLFW_FALSE;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return GLFW_FALSE;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+ return GLFW_FALSE;
+
+ return js->mapping != NULL;
+}
+
+GLFWAPI const char* glfwGetGamepadName(int jid)
+{
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return NULL;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return NULL;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+ return NULL;
+
+ if (!js->mapping)
+ return NULL;
+
+ return js->mapping->name;
+}
+
+GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
+{
+ int i;
+ _GLFWjoystick* js;
+
+ assert(jid >= GLFW_JOYSTICK_1);
+ assert(jid <= GLFW_JOYSTICK_LAST);
+ assert(state != NULL);
+
+ memset(state, 0, sizeof(GLFWgamepadstate));
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+ return GLFW_FALSE;
+ }
+
+ js = _glfw.joysticks + jid;
+ if (!js->present)
+ return GLFW_FALSE;
+
+ if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
+ return GLFW_FALSE;
+
+ if (!js->mapping)
+ return GLFW_FALSE;
+
+ for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
+ {
+ const _GLFWmapelement* e = js->mapping->buttons + i;
+ if (e->type == _GLFW_JOYSTICK_AXIS)
+ {
+ const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
+ if (value > 0.f)
+ state->buttons[i] = GLFW_PRESS;
+ }
+ else if (e->type == _GLFW_JOYSTICK_HATBIT)
+ {
+ const unsigned int hat = e->index >> 4;
+ const unsigned int bit = e->index & 0xf;
+ if (js->hats[hat] & bit)
+ state->buttons[i] = GLFW_PRESS;
+ }
+ else if (e->type == _GLFW_JOYSTICK_BUTTON)
+ state->buttons[i] = js->buttons[e->index];
+ }
+
+ for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
+ {
+ const _GLFWmapelement* e = js->mapping->axes + i;
+ if (e->type == _GLFW_JOYSTICK_AXIS)
+ {
+ const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
+ state->axes[i] = _glfw_fminf(_glfw_fmaxf(value, -1.f), 1.f);
+ }
+ else if (e->type == _GLFW_JOYSTICK_HATBIT)
+ {
+ const unsigned int hat = e->index >> 4;
+ const unsigned int bit = e->index & 0xf;
+ if (js->hats[hat] & bit)
+ state->axes[i] = 1.f;
+ }
+ else if (e->type == _GLFW_JOYSTICK_BUTTON)
+ state->axes[i] = (float) js->buttons[e->index];
+ }
+
+ return GLFW_TRUE;
+}
+
+GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
+{
+ assert(string != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformSetClipboardString(string);
+}
+
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfwPlatformGetClipboardString();
+}
+
+GLFWAPI double glfwGetTime(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
+ return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
+ _glfwPlatformGetTimerFrequency();
+}
+
+GLFWAPI void glfwSetTime(double time)
+{
+ _GLFW_REQUIRE_INIT();
+
+ if (time != time || time < 0.0 || time > 18446744073.0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
+ return;
+ }
+
+ _glfw.timer.offset = _glfwPlatformGetTimerValue() -
+ (uint64_t) (time * _glfwPlatformGetTimerFrequency());
+}
+
+GLFWAPI uint64_t glfwGetTimerValue(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+ return _glfwPlatformGetTimerValue();
+}
+
+GLFWAPI uint64_t glfwGetTimerFrequency(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+ return _glfwPlatformGetTimerFrequency();
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/internal.h b/Client/ThirdParty/Box2D/extern/glfw/src/internal.h
new file mode 100644
index 0000000..c80b518
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/internal.h
@@ -0,0 +1,772 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#pragma once
+
+// MODIFIED_ERIN
+//#if defined(_GLFW_USE_CONFIG_H)
+ #include "glfw_config.h"
+//#endif
+
+#if defined(GLFW_INCLUDE_GLCOREARB) || \
+ defined(GLFW_INCLUDE_ES1) || \
+ defined(GLFW_INCLUDE_ES2) || \
+ defined(GLFW_INCLUDE_ES3) || \
+ defined(GLFW_INCLUDE_ES31) || \
+ defined(GLFW_INCLUDE_ES32) || \
+ defined(GLFW_INCLUDE_NONE) || \
+ defined(GLFW_INCLUDE_GLEXT) || \
+ defined(GLFW_INCLUDE_GLU) || \
+ defined(GLFW_INCLUDE_VULKAN) || \
+ defined(GLFW_DLL)
+ #error "You must not define any header option macros when compiling GLFW"
+#endif
+
+#define GLFW_INCLUDE_NONE
+#include "../include/GLFW/glfw3.h"
+
+#define _GLFW_INSERT_FIRST 0
+#define _GLFW_INSERT_LAST 1
+
+#define _GLFW_POLL_PRESENCE 0
+#define _GLFW_POLL_AXES 1
+#define _GLFW_POLL_BUTTONS 2
+#define _GLFW_POLL_ALL (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
+
+#define _GLFW_MESSAGE_SIZE 1024
+
+typedef int GLFWbool;
+
+typedef struct _GLFWerror _GLFWerror;
+typedef struct _GLFWinitconfig _GLFWinitconfig;
+typedef struct _GLFWwndconfig _GLFWwndconfig;
+typedef struct _GLFWctxconfig _GLFWctxconfig;
+typedef struct _GLFWfbconfig _GLFWfbconfig;
+typedef struct _GLFWcontext _GLFWcontext;
+typedef struct _GLFWwindow _GLFWwindow;
+typedef struct _GLFWlibrary _GLFWlibrary;
+typedef struct _GLFWmonitor _GLFWmonitor;
+typedef struct _GLFWcursor _GLFWcursor;
+typedef struct _GLFWmapelement _GLFWmapelement;
+typedef struct _GLFWmapping _GLFWmapping;
+typedef struct _GLFWjoystick _GLFWjoystick;
+typedef struct _GLFWtls _GLFWtls;
+typedef struct _GLFWmutex _GLFWmutex;
+
+typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
+typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
+typedef void (* _GLFWswapintervalfun)(int);
+typedef int (* _GLFWextensionsupportedfun)(const char*);
+typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
+typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
+
+#define GL_VERSION 0x1f02
+#define GL_NONE 0
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_EXTENSIONS 0x1f03
+#define GL_NUM_EXTENSIONS 0x821d
+#define GL_CONTEXT_FLAGS 0x821e
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82fb
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef unsigned int GLenum;
+typedef unsigned int GLbitfield;
+typedef unsigned char GLubyte;
+
+typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
+typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
+typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
+typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
+
+#define VK_NULL_HANDLE 0
+
+typedef void* VkInstance;
+typedef void* VkPhysicalDevice;
+typedef uint64_t VkSurfaceKHR;
+typedef uint32_t VkFlags;
+typedef uint32_t VkBool32;
+
+typedef enum VkStructureType
+{
+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
+ VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
+ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
+ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
+ VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkStructureType;
+
+typedef enum VkResult
+{
+ VK_SUCCESS = 0,
+ VK_NOT_READY = 1,
+ VK_TIMEOUT = 2,
+ VK_EVENT_SET = 3,
+ VK_EVENT_RESET = 4,
+ VK_INCOMPLETE = 5,
+ VK_ERROR_OUT_OF_HOST_MEMORY = -1,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
+ VK_ERROR_INITIALIZATION_FAILED = -3,
+ VK_ERROR_DEVICE_LOST = -4,
+ VK_ERROR_MEMORY_MAP_FAILED = -5,
+ VK_ERROR_LAYER_NOT_PRESENT = -6,
+ VK_ERROR_EXTENSION_NOT_PRESENT = -7,
+ VK_ERROR_FEATURE_NOT_PRESENT = -8,
+ VK_ERROR_INCOMPATIBLE_DRIVER = -9,
+ VK_ERROR_TOO_MANY_OBJECTS = -10,
+ VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
+ VK_ERROR_SURFACE_LOST_KHR = -1000000000,
+ VK_SUBOPTIMAL_KHR = 1000001003,
+ VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
+ VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
+ VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
+ VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
+ VK_RESULT_MAX_ENUM = 0x7FFFFFFF
+} VkResult;
+
+typedef struct VkAllocationCallbacks VkAllocationCallbacks;
+
+typedef struct VkExtensionProperties
+{
+ char extensionName[256];
+ uint32_t specVersion;
+} VkExtensionProperties;
+
+typedef void (APIENTRY * PFN_vkVoidFunction)(void);
+
+#if defined(_GLFW_VULKAN_STATIC)
+ PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);
+ VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);
+#else
+ typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
+ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
+ #define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
+ #define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
+#endif
+
+#if defined(_GLFW_COCOA)
+ #include "cocoa_platform.h"
+#elif defined(_GLFW_WIN32)
+ #include "win32_platform.h"
+#elif defined(_GLFW_X11)
+ #include "x11_platform.h"
+#elif defined(_GLFW_WAYLAND)
+ #include "wl_platform.h"
+#elif defined(_GLFW_OSMESA)
+ #include "null_platform.h"
+#else
+ #error "No supported window creation API selected"
+#endif
+
+// Constructs a version number string from the public header macros
+#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
+#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
+#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \
+ GLFW_VERSION_MINOR, \
+ GLFW_VERSION_REVISION)
+
+// Checks for whether the library has been initialized
+#define _GLFW_REQUIRE_INIT() \
+ if (!_glfw.initialized) \
+ { \
+ _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
+ return; \
+ }
+#define _GLFW_REQUIRE_INIT_OR_RETURN(x) \
+ if (!_glfw.initialized) \
+ { \
+ _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
+ return x; \
+ }
+
+// Swaps the provided pointers
+#define _GLFW_SWAP_POINTERS(x, y) \
+ { \
+ void* t; \
+ t = x; \
+ x = y; \
+ y = t; \
+ }
+
+// Per-thread error structure
+//
+struct _GLFWerror
+{
+ _GLFWerror* next;
+ int code;
+ char description[_GLFW_MESSAGE_SIZE];
+};
+
+// Initialization configuration
+//
+// Parameters relating to the initialization of the library
+//
+struct _GLFWinitconfig
+{
+ GLFWbool hatButtons;
+ struct {
+ GLFWbool menubar;
+ GLFWbool chdir;
+ } ns;
+};
+
+// Window configuration
+//
+// Parameters relating to the creation of the window but not directly related
+// to the framebuffer. This is used to pass window creation parameters from
+// shared code to the platform API.
+//
+struct _GLFWwndconfig
+{
+ int width;
+ int height;
+ const char* title;
+ GLFWbool resizable;
+ GLFWbool visible;
+ GLFWbool decorated;
+ GLFWbool focused;
+ GLFWbool autoIconify;
+ GLFWbool floating;
+ GLFWbool maximized;
+ GLFWbool centerCursor;
+ GLFWbool focusOnShow;
+ GLFWbool scaleToMonitor;
+ struct {
+ GLFWbool retina;
+ char frameName[256];
+ } ns;
+ struct {
+ char className[256];
+ char instanceName[256];
+ } x11;
+};
+
+// Context configuration
+//
+// Parameters relating to the creation of the context but not directly related
+// to the framebuffer. This is used to pass context creation parameters from
+// shared code to the platform API.
+//
+struct _GLFWctxconfig
+{
+ int client;
+ int source;
+ int major;
+ int minor;
+ GLFWbool forward;
+ GLFWbool debug;
+ GLFWbool noerror;
+ int profile;
+ int robustness;
+ int release;
+ _GLFWwindow* share;
+ struct {
+ GLFWbool offline;
+ } nsgl;
+};
+
+// Framebuffer configuration
+//
+// This describes buffers and their sizes. It also contains
+// a platform-specific ID used to map back to the backend API object.
+//
+// It is used to pass framebuffer parameters from shared code to the platform
+// API and also to enumerate and select available framebuffer configs.
+//
+struct _GLFWfbconfig
+{
+ int redBits;
+ int greenBits;
+ int blueBits;
+ int alphaBits;
+ int depthBits;
+ int stencilBits;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ GLFWbool stereo;
+ int samples;
+ GLFWbool sRGB;
+ GLFWbool doublebuffer;
+ GLFWbool transparent;
+ uintptr_t handle;
+};
+
+// Context structure
+//
+struct _GLFWcontext
+{
+ int client;
+ int source;
+ int major, minor, revision;
+ GLFWbool forward, debug, noerror;
+ int profile;
+ int robustness;
+ int release;
+
+ PFNGLGETSTRINGIPROC GetStringi;
+ PFNGLGETINTEGERVPROC GetIntegerv;
+ PFNGLGETSTRINGPROC GetString;
+
+ _GLFWmakecontextcurrentfun makeCurrent;
+ _GLFWswapbuffersfun swapBuffers;
+ _GLFWswapintervalfun swapInterval;
+ _GLFWextensionsupportedfun extensionSupported;
+ _GLFWgetprocaddressfun getProcAddress;
+ _GLFWdestroycontextfun destroy;
+
+ // This is defined in the context API's context.h
+ _GLFW_PLATFORM_CONTEXT_STATE;
+ // This is defined in egl_context.h
+ _GLFW_EGL_CONTEXT_STATE;
+ // This is defined in osmesa_context.h
+ _GLFW_OSMESA_CONTEXT_STATE;
+};
+
+// Window and context structure
+//
+struct _GLFWwindow
+{
+ struct _GLFWwindow* next;
+
+ // Window settings and state
+ GLFWbool resizable;
+ GLFWbool decorated;
+ GLFWbool autoIconify;
+ GLFWbool floating;
+ GLFWbool focusOnShow;
+ GLFWbool shouldClose;
+ void* userPointer;
+ GLFWvidmode videoMode;
+ _GLFWmonitor* monitor;
+ _GLFWcursor* cursor;
+
+ int minwidth, minheight;
+ int maxwidth, maxheight;
+ int numer, denom;
+
+ GLFWbool stickyKeys;
+ GLFWbool stickyMouseButtons;
+ GLFWbool lockKeyMods;
+ int cursorMode;
+ char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
+ char keys[GLFW_KEY_LAST + 1];
+ // Virtual cursor position when cursor is disabled
+ double virtualCursorPosX, virtualCursorPosY;
+
+ _GLFWcontext context;
+
+ struct {
+ GLFWwindowposfun pos;
+ GLFWwindowsizefun size;
+ GLFWwindowclosefun close;
+ GLFWwindowrefreshfun refresh;
+ GLFWwindowfocusfun focus;
+ GLFWwindowiconifyfun iconify;
+ GLFWwindowmaximizefun maximize;
+ GLFWframebuffersizefun fbsize;
+ GLFWwindowcontentscalefun scale;
+ GLFWmousebuttonfun mouseButton;
+ GLFWcursorposfun cursorPos;
+ GLFWcursorenterfun cursorEnter;
+ GLFWscrollfun scroll;
+ GLFWkeyfun key;
+ GLFWcharfun character;
+ GLFWcharmodsfun charmods;
+ GLFWdropfun drop;
+ } callbacks;
+
+ // This is defined in the window API's platform.h
+ _GLFW_PLATFORM_WINDOW_STATE;
+};
+
+// Monitor structure
+//
+struct _GLFWmonitor
+{
+ char* name;
+ void* userPointer;
+
+ // Physical dimensions in millimeters.
+ int widthMM, heightMM;
+
+ // The window whose video mode is current on this monitor
+ _GLFWwindow* window;
+
+ GLFWvidmode* modes;
+ int modeCount;
+ GLFWvidmode currentMode;
+
+ GLFWgammaramp originalRamp;
+ GLFWgammaramp currentRamp;
+
+ // This is defined in the window API's platform.h
+ _GLFW_PLATFORM_MONITOR_STATE;
+};
+
+// Cursor structure
+//
+struct _GLFWcursor
+{
+ _GLFWcursor* next;
+
+ // This is defined in the window API's platform.h
+ _GLFW_PLATFORM_CURSOR_STATE;
+};
+
+// Gamepad mapping element structure
+//
+struct _GLFWmapelement
+{
+ uint8_t type;
+ uint8_t index;
+ int8_t axisScale;
+ int8_t axisOffset;
+};
+
+// Gamepad mapping structure
+//
+struct _GLFWmapping
+{
+ char name[128];
+ char guid[33];
+ _GLFWmapelement buttons[15];
+ _GLFWmapelement axes[6];
+};
+
+// Joystick structure
+//
+struct _GLFWjoystick
+{
+ GLFWbool present;
+ float* axes;
+ int axisCount;
+ unsigned char* buttons;
+ int buttonCount;
+ unsigned char* hats;
+ int hatCount;
+ char* name;
+ void* userPointer;
+ char guid[33];
+ _GLFWmapping* mapping;
+
+ // This is defined in the joystick API's joystick.h
+ _GLFW_PLATFORM_JOYSTICK_STATE;
+};
+
+// Thread local storage structure
+//
+struct _GLFWtls
+{
+ // This is defined in the platform's thread.h
+ _GLFW_PLATFORM_TLS_STATE;
+};
+
+// Mutex structure
+//
+struct _GLFWmutex
+{
+ // This is defined in the platform's thread.h
+ _GLFW_PLATFORM_MUTEX_STATE;
+};
+
+// Library global data
+//
+struct _GLFWlibrary
+{
+ GLFWbool initialized;
+
+ struct {
+ _GLFWinitconfig init;
+ _GLFWfbconfig framebuffer;
+ _GLFWwndconfig window;
+ _GLFWctxconfig context;
+ int refreshRate;
+ } hints;
+
+ _GLFWerror* errorListHead;
+ _GLFWcursor* cursorListHead;
+ _GLFWwindow* windowListHead;
+
+ _GLFWmonitor** monitors;
+ int monitorCount;
+
+ _GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
+ _GLFWmapping* mappings;
+ int mappingCount;
+
+ _GLFWtls errorSlot;
+ _GLFWtls contextSlot;
+ _GLFWmutex errorLock;
+
+ struct {
+ uint64_t offset;
+ // This is defined in the platform's time.h
+ _GLFW_PLATFORM_LIBRARY_TIMER_STATE;
+ } timer;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ char* extensions[2];
+#if !defined(_GLFW_VULKAN_STATIC)
+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+#endif
+ GLFWbool KHR_surface;
+#if defined(_GLFW_WIN32)
+ GLFWbool KHR_win32_surface;
+#elif defined(_GLFW_COCOA)
+ GLFWbool MVK_macos_surface;
+#elif defined(_GLFW_X11)
+ GLFWbool KHR_xlib_surface;
+ GLFWbool KHR_xcb_surface;
+#elif defined(_GLFW_WAYLAND)
+ GLFWbool KHR_wayland_surface;
+#endif
+ } vk;
+
+ struct {
+ GLFWmonitorfun monitor;
+ GLFWjoystickfun joystick;
+ } callbacks;
+
+ // This is defined in the window API's platform.h
+ _GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
+ // This is defined in the context API's context.h
+ _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
+ // This is defined in the platform's joystick.h
+ _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
+ // This is defined in egl_context.h
+ _GLFW_EGL_LIBRARY_CONTEXT_STATE;
+ // This is defined in osmesa_context.h
+ _GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
+};
+
+// Global state shared between compilation units of GLFW
+//
+extern _GLFWlibrary _glfw;
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void);
+void _glfwPlatformTerminate(void);
+const char* _glfwPlatformGetVersionString(void);
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image, int xhot, int yhot);
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
+
+const char* _glfwPlatformGetScancodeName(int scancode);
+int _glfwPlatformGetKeyScancode(int key);
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+ float* xscale, float* yscale);
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
+
+void _glfwPlatformSetClipboardString(const char* string);
+const char* _glfwPlatformGetClipboardString(void);
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
+void _glfwPlatformUpdateGamepadGUID(char* guid);
+
+uint64_t _glfwPlatformGetTimerValue(void);
+uint64_t _glfwPlatformGetTimerFrequency(void);
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+void _glfwPlatformDestroyWindow(_GLFWwindow* window);
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images);
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight);
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom);
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+ float* xscale, float* yscale);
+void _glfwPlatformIconifyWindow(_GLFWwindow* window);
+void _glfwPlatformRestoreWindow(_GLFWwindow* window);
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
+void _glfwPlatformShowWindow(_GLFWwindow* window);
+void _glfwPlatformHideWindow(_GLFWwindow* window);
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
+void _glfwPlatformFocusWindow(_GLFWwindow* window);
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
+ int xpos, int ypos, int width, int height,
+ int refreshRate);
+int _glfwPlatformWindowFocused(_GLFWwindow* window);
+int _glfwPlatformWindowIconified(_GLFWwindow* window);
+int _glfwPlatformWindowVisible(_GLFWwindow* window);
+int _glfwPlatformWindowMaximized(_GLFWwindow* window);
+int _glfwPlatformWindowHovered(_GLFWwindow* window);
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
+
+void _glfwPlatformPollEvents(void);
+void _glfwPlatformWaitEvents(void);
+void _glfwPlatformWaitEventsTimeout(double timeout);
+void _glfwPlatformPostEmptyEvent(void);
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily);
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface);
+
+GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
+void _glfwPlatformDestroyTls(_GLFWtls* tls);
+void* _glfwPlatformGetTls(_GLFWtls* tls);
+void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
+
+GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
+void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
+void _glfwPlatformLockMutex(_GLFWmutex* mutex);
+void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
+void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
+void _glfwInputWindowContentScale(_GLFWwindow* window,
+ float xscale, float yscale);
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
+void _glfwInputWindowDamage(_GLFWwindow* window);
+void _glfwInputWindowCloseRequest(_GLFWwindow* window);
+void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
+
+void _glfwInputKey(_GLFWwindow* window,
+ int key, int scancode, int action, int mods);
+void _glfwInputChar(_GLFWwindow* window,
+ unsigned int codepoint, int mods, GLFWbool plain);
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
+void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
+void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
+void _glfwInputJoystick(_GLFWjoystick* js, int event);
+void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
+void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
+void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
+
+void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
+void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
+
+#if defined(__GNUC__)
+void _glfwInputError(int code, const char* format, ...)
+ __attribute__((format(printf, 2, 3)));
+#else
+void _glfwInputError(int code, const char* format, ...);
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
+const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
+ const _GLFWfbconfig* alternatives,
+ unsigned int count);
+GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig);
+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
+
+const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
+ const GLFWvidmode* desired);
+int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
+_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
+void _glfwFreeMonitor(_GLFWmonitor* monitor);
+void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
+void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
+void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
+
+_GLFWjoystick* _glfwAllocJoystick(const char* name,
+ const char* guid,
+ int axisCount,
+ int buttonCount,
+ int hatCount);
+void _glfwFreeJoystick(_GLFWjoystick* js);
+
+GLFWbool _glfwInitVulkan(int mode);
+void _glfwTerminateVulkan(void);
+const char* _glfwGetVulkanResultString(VkResult result);
+
+char* _glfw_strdup(const char* source);
+float _glfw_fminf(float a, float b);
+float _glfw_fmaxf(float a, float b);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.c b/Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.c
new file mode 100644
index 0000000..baa3651
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.c
@@ -0,0 +1,434 @@
+//========================================================================
+// GLFW 3.3 Linux - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/inotify.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef SYN_DROPPED // < v2.6.39 kernel headers
+// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32
+#define SYN_DROPPED 3
+#endif
+
+// Apply an EV_KEY event to the specified joystick
+//
+static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
+{
+ _glfwInputJoystickButton(js,
+ js->linjs.keyMap[code - BTN_MISC],
+ value ? GLFW_PRESS : GLFW_RELEASE);
+}
+
+// Apply an EV_ABS event to the specified joystick
+//
+static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
+{
+ const int index = js->linjs.absMap[code];
+
+ if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
+ {
+ static const char stateMap[3][3] =
+ {
+ { GLFW_HAT_CENTERED, GLFW_HAT_UP, GLFW_HAT_DOWN },
+ { GLFW_HAT_LEFT, GLFW_HAT_LEFT_UP, GLFW_HAT_LEFT_DOWN },
+ { GLFW_HAT_RIGHT, GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
+ };
+
+ const int hat = (code - ABS_HAT0X) / 2;
+ const int axis = (code - ABS_HAT0X) % 2;
+ int* state = js->linjs.hats[hat];
+
+ // NOTE: Looking at several input drivers, it seems all hat events use
+ // -1 for left / up, 0 for centered and 1 for right / down
+ if (value == 0)
+ state[axis] = 0;
+ else if (value < 0)
+ state[axis] = 1;
+ else if (value > 0)
+ state[axis] = 2;
+
+ _glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
+ }
+ else
+ {
+ const struct input_absinfo* info = &js->linjs.absInfo[code];
+ float normalized = value;
+
+ const int range = info->maximum - info->minimum;
+ if (range)
+ {
+ // Normalize to 0.0 -> 1.0
+ normalized = (normalized - info->minimum) / range;
+ // Normalize to -1.0 -> 1.0
+ normalized = normalized * 2.0f - 1.0f;
+ }
+
+ _glfwInputJoystickAxis(js, index, normalized);
+ }
+}
+
+// Poll state of absolute axes
+//
+static void pollAbsState(_GLFWjoystick* js)
+{
+ int code;
+
+ for (code = 0; code < ABS_CNT; code++)
+ {
+ if (js->linjs.absMap[code] < 0)
+ continue;
+
+ struct input_absinfo* info = &js->linjs.absInfo[code];
+
+ if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
+ continue;
+
+ handleAbsEvent(js, code, info->value);
+ }
+}
+
+#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
+
+// Attempt to open the specified joystick device
+//
+static GLFWbool openJoystickDevice(const char* path)
+{
+ int jid, code;
+ char name[256] = "";
+ char guid[33] = "";
+ char evBits[(EV_CNT + 7) / 8] = {0};
+ char keyBits[(KEY_CNT + 7) / 8] = {0};
+ char absBits[(ABS_CNT + 7) / 8] = {0};
+ int axisCount = 0, buttonCount = 0, hatCount = 0;
+ struct input_id id;
+ _GLFWjoystickLinux linjs = {0};
+ _GLFWjoystick* js = NULL;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ if (!_glfw.joysticks[jid].present)
+ continue;
+ if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
+ return GLFW_FALSE;
+ }
+
+ linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
+ if (linjs.fd == -1)
+ return GLFW_FALSE;
+
+ if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
+ ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
+ ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
+ ioctl(linjs.fd, EVIOCGID, &id) < 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Linux: Failed to query input device: %s",
+ strerror(errno));
+ close(linjs.fd);
+ return GLFW_FALSE;
+ }
+
+ // Ensure this device supports the events expected of a joystick
+ if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
+ {
+ close(linjs.fd);
+ return GLFW_FALSE;
+ }
+
+ if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
+ strncpy(name, "Unknown", sizeof(name));
+
+ // Generate a joystick GUID that matches the SDL 2.0.5+ one
+ if (id.vendor && id.product && id.version)
+ {
+ sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
+ id.bustype & 0xff, id.bustype >> 8,
+ id.vendor & 0xff, id.vendor >> 8,
+ id.product & 0xff, id.product >> 8,
+ id.version & 0xff, id.version >> 8);
+ }
+ else
+ {
+ sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
+ id.bustype & 0xff, id.bustype >> 8,
+ name[0], name[1], name[2], name[3],
+ name[4], name[5], name[6], name[7],
+ name[8], name[9], name[10]);
+ }
+
+ for (code = BTN_MISC; code < KEY_CNT; code++)
+ {
+ if (!isBitSet(code, keyBits))
+ continue;
+
+ linjs.keyMap[code - BTN_MISC] = buttonCount;
+ buttonCount++;
+ }
+
+ for (code = 0; code < ABS_CNT; code++)
+ {
+ linjs.absMap[code] = -1;
+ if (!isBitSet(code, absBits))
+ continue;
+
+ if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
+ {
+ linjs.absMap[code] = hatCount;
+ hatCount++;
+ // Skip the Y axis
+ code++;
+ }
+ else
+ {
+ if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
+ continue;
+
+ linjs.absMap[code] = axisCount;
+ axisCount++;
+ }
+ }
+
+ js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
+ if (!js)
+ {
+ close(linjs.fd);
+ return GLFW_FALSE;
+ }
+
+ strncpy(linjs.path, path, sizeof(linjs.path) - 1);
+ memcpy(&js->linjs, &linjs, sizeof(linjs));
+
+ pollAbsState(js);
+
+ _glfwInputJoystick(js, GLFW_CONNECTED);
+ return GLFW_TRUE;
+}
+
+#undef isBitSet
+
+// Frees all resources associated with the specified joystick
+//
+static void closeJoystick(_GLFWjoystick* js)
+{
+ close(js->linjs.fd);
+ _glfwFreeJoystick(js);
+ _glfwInputJoystick(js, GLFW_DISCONNECTED);
+}
+
+// Lexically compare joysticks by name; used by qsort
+//
+static int compareJoysticks(const void* fp, const void* sp)
+{
+ const _GLFWjoystick* fj = fp;
+ const _GLFWjoystick* sj = sp;
+ return strcmp(fj->linjs.path, sj->linjs.path);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+GLFWbool _glfwInitJoysticksLinux(void)
+{
+ DIR* dir;
+ int count = 0;
+ const char* dirname = "/dev/input";
+
+ _glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ if (_glfw.linjs.inotify > 0)
+ {
+ // HACK: Register for IN_ATTRIB to get notified when udev is done
+ // This works well in practice but the true way is libudev
+
+ _glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
+ dirname,
+ IN_CREATE | IN_ATTRIB | IN_DELETE);
+ }
+
+ // Continue without device connection notifications if inotify fails
+
+ if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
+ return GLFW_FALSE;
+ }
+
+ dir = opendir(dirname);
+ if (dir)
+ {
+ struct dirent* entry;
+
+ while ((entry = readdir(dir)))
+ {
+ regmatch_t match;
+
+ if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
+ continue;
+
+ char path[PATH_MAX];
+
+ snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
+
+ if (openJoystickDevice(path))
+ count++;
+ }
+
+ closedir(dir);
+ }
+
+ // Continue with no joysticks if enumeration fails
+
+ qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
+ return GLFW_TRUE;
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksLinux(void)
+{
+ int jid;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ _GLFWjoystick* js = _glfw.joysticks + jid;
+ if (js->present)
+ closeJoystick(js);
+ }
+
+ regfree(&_glfw.linjs.regex);
+
+ if (_glfw.linjs.inotify > 0)
+ {
+ if (_glfw.linjs.watch > 0)
+ inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
+
+ close(_glfw.linjs.inotify);
+ }
+}
+
+void _glfwDetectJoystickConnectionLinux(void)
+{
+ ssize_t offset = 0;
+ char buffer[16384];
+
+ if (_glfw.linjs.inotify <= 0)
+ return;
+
+ const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
+
+ while (size > offset)
+ {
+ regmatch_t match;
+ const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
+
+ offset += sizeof(struct inotify_event) + e->len;
+
+ if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
+ continue;
+
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), "/dev/input/%s", e->name);
+
+ if (e->mask & (IN_CREATE | IN_ATTRIB))
+ openJoystickDevice(path);
+ else if (e->mask & IN_DELETE)
+ {
+ int jid;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
+ {
+ closeJoystick(_glfw.joysticks + jid);
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+ // Read all queued events (non-blocking)
+ for (;;)
+ {
+ struct input_event e;
+
+ errno = 0;
+ if (read(js->linjs.fd, &e, sizeof(e)) < 0)
+ {
+ // Reset the joystick slot if the device was disconnected
+ if (errno == ENODEV)
+ closeJoystick(js);
+
+ break;
+ }
+
+ if (e.type == EV_SYN)
+ {
+ if (e.code == SYN_DROPPED)
+ _glfw.linjs.dropped = GLFW_TRUE;
+ else if (e.code == SYN_REPORT)
+ {
+ _glfw.linjs.dropped = GLFW_FALSE;
+ pollAbsState(js);
+ }
+ }
+
+ if (_glfw.linjs.dropped)
+ continue;
+
+ if (e.type == EV_KEY)
+ handleKeyEvent(js, e.code, e.value);
+ else if (e.type == EV_ABS)
+ handleAbsEvent(js, e.code, e.value);
+ }
+
+ return js->present;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.h b/Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.h
new file mode 100644
index 0000000..2eabfa1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/linux_joystick.h
@@ -0,0 +1,62 @@
+//========================================================================
+// GLFW 3.3 Linux - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <linux/input.h>
+#include <linux/limits.h>
+#include <regex.h>
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
+
+#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
+
+// Linux-specific joystick data
+//
+typedef struct _GLFWjoystickLinux
+{
+ int fd;
+ char path[PATH_MAX];
+ int keyMap[KEY_CNT - BTN_MISC];
+ int absMap[ABS_CNT];
+ struct input_absinfo absInfo[ABS_CNT];
+ int hats[4][2];
+} _GLFWjoystickLinux;
+
+// Linux-specific joystick API data
+//
+typedef struct _GLFWlibraryLinux
+{
+ int inotify;
+ int watch;
+ regex_t regex;
+ GLFWbool dropped;
+} _GLFWlibraryLinux;
+
+
+GLFWbool _glfwInitJoysticksLinux(void);
+void _glfwTerminateJoysticksLinux(void);
+void _glfwDetectJoystickConnectionLinux(void);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/mappings.h b/Client/ThirdParty/Box2D/extern/glfw/src/mappings.h
new file mode 100644
index 0000000..97073db
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/mappings.h
@@ -0,0 +1,478 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+// As mappings.h.in, this file is used by CMake to produce the mappings.h
+// header file. If you are adding a GLFW specific gamepad mapping, this is
+// where to put it.
+//========================================================================
+// As mappings.h, this provides all pre-defined gamepad mappings, including
+// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
+// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
+// This file can be re-generated from mappings.h.in and the upstream
+// gamecontrollerdb.txt with the GenerateMappings.cmake script.
+//========================================================================
+
+// All gamepad mappings not labeled GLFW are copied from the
+// SDL_GameControllerDB project under the following license:
+//
+// Simple DirectMedia Layer
+// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the
+// use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+const char* _glfwDefaultMappings[] =
+{
+"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
+"03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
+"03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
+"03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",
+"03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",
+"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",
+"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,",
+"03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000790000000600000000000000,G-Shark GS-GP702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,",
+"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,",
+"030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",
+"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",
+"030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,",
+"030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,",
+"03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,",
+"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",
+"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
+"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,",
+"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
+"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
+"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
+"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
+"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,",
+"03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
+"03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,",
+"03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
+"030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
+"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
+"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
+"030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",
+"03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",
+"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",
+"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,",
+"03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
+"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,",
+"030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
+"03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
+"03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,",
+"03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",
+"030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,",
+"03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000790000000600000000000000,G-Shark GP-702,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
+"030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,",
+"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
+"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
+"030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,",
+"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,",
+"03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
+"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
+"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
+"030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,",
+"03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,",
+"030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
+"03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
+"030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,",
+"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,",
+"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,",
+"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,",
+"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,",
+"030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",
+"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
+"03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
+"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
+"05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
+"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",
+"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,",
+"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,",
+"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,",
+"030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
+"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,",
+"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
+"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,",
+"03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,",
+"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,",
+"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
+"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,",
+"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,",
+"03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
+"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",
+"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",
+"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
+"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
+"05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",
+"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,",
+"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,",
+"05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,",
+"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
+"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
+"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
+"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
+"030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,",
+"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,",
+"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
+"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
+"030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
+"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,",
+"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
+"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,",
+"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",
+"03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
+"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
+"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
+"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
+"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,",
+"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,",
+"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,",
+"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,",
+"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",
+"03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,",
+"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
+"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,",
+"61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
+"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
+"37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
+"35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,",
+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,",
+"5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,",
+"34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,",
+"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,",
+"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,",
+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,",
+
+"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+NULL
+};
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/mappings.h.in b/Client/ThirdParty/Box2D/extern/glfw/src/mappings.h.in
new file mode 100644
index 0000000..eb6c32f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/mappings.h.in
@@ -0,0 +1,73 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+// As mappings.h.in, this file is used by CMake to produce the mappings.h
+// header file. If you are adding a GLFW specific gamepad mapping, this is
+// where to put it.
+//========================================================================
+// As mappings.h, this provides all pre-defined gamepad mappings, including
+// all available in SDL_GameControllerDB. Do not edit this file. Any gamepad
+// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
+// This file can be re-generated from mappings.h.in and the upstream
+// gamecontrollerdb.txt with the GenerateMappings.cmake script.
+//========================================================================
+
+// All gamepad mappings not labeled GLFW are copied from the
+// SDL_GameControllerDB project under the following license:
+//
+// Simple DirectMedia Layer
+// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+//
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors be held liable for any damages arising from the
+// use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be
+// misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+const char* _glfwDefaultMappings[] =
+{
+@GLFW_GAMEPAD_MAPPINGS@
+"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+NULL
+};
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/monitor.c b/Client/ThirdParty/Box2D/extern/glfw/src/monitor.c
new file mode 100644
index 0000000..0ab865e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/monitor.c
@@ -0,0 +1,517 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+
+
+// Lexically compare video modes, used by qsort
+//
+static int compareVideoModes(const void* fp, const void* sp)
+{
+ const GLFWvidmode* fm = fp;
+ const GLFWvidmode* sm = sp;
+ const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;
+ const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;
+ const int farea = fm->width * fm->height;
+ const int sarea = sm->width * sm->height;
+
+ // First sort on color bits per pixel
+ if (fbpp != sbpp)
+ return fbpp - sbpp;
+
+ // Then sort on screen area
+ if (farea != sarea)
+ return farea - sarea;
+
+ // Lastly sort on refresh rate
+ return fm->refreshRate - sm->refreshRate;
+}
+
+// Retrieves the available modes for the specified monitor
+//
+static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
+{
+ int modeCount;
+ GLFWvidmode* modes;
+
+ if (monitor->modes)
+ return GLFW_TRUE;
+
+ modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
+ if (!modes)
+ return GLFW_FALSE;
+
+ qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
+
+ free(monitor->modes);
+ monitor->modes = modes;
+ monitor->modeCount = modeCount;
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code of a monitor connection or disconnection
+//
+void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
+{
+ if (action == GLFW_CONNECTED)
+ {
+ _glfw.monitorCount++;
+ _glfw.monitors =
+ realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
+
+ if (placement == _GLFW_INSERT_FIRST)
+ {
+ memmove(_glfw.monitors + 1,
+ _glfw.monitors,
+ (_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
+ _glfw.monitors[0] = monitor;
+ }
+ else
+ _glfw.monitors[_glfw.monitorCount - 1] = monitor;
+ }
+ else if (action == GLFW_DISCONNECTED)
+ {
+ int i;
+ _GLFWwindow* window;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ {
+ if (window->monitor == monitor)
+ {
+ int width, height, xoff, yoff;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
+ _glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
+ _glfwPlatformSetWindowPos(window, xoff, yoff);
+ }
+ }
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ {
+ if (_glfw.monitors[i] == monitor)
+ {
+ _glfw.monitorCount--;
+ memmove(_glfw.monitors + i,
+ _glfw.monitors + i + 1,
+ (_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
+ break;
+ }
+ }
+ }
+
+ if (_glfw.callbacks.monitor)
+ _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
+
+ if (action == GLFW_DISCONNECTED)
+ _glfwFreeMonitor(monitor);
+}
+
+// Notifies shared code that a full screen window has acquired or released
+// a monitor
+//
+void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
+{
+ monitor->window = window;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Allocates and returns a monitor object with the specified name and dimensions
+//
+_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
+{
+ _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
+ monitor->widthMM = widthMM;
+ monitor->heightMM = heightMM;
+
+ if (name)
+ monitor->name = _glfw_strdup(name);
+
+ return monitor;
+}
+
+// Frees a monitor object and any data associated with it
+//
+void _glfwFreeMonitor(_GLFWmonitor* monitor)
+{
+ if (monitor == NULL)
+ return;
+
+ _glfwPlatformFreeMonitor(monitor);
+
+ _glfwFreeGammaArrays(&monitor->originalRamp);
+ _glfwFreeGammaArrays(&monitor->currentRamp);
+
+ free(monitor->modes);
+ free(monitor->name);
+ free(monitor);
+}
+
+// Allocates red, green and blue value arrays of the specified size
+//
+void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
+{
+ ramp->red = calloc(size, sizeof(unsigned short));
+ ramp->green = calloc(size, sizeof(unsigned short));
+ ramp->blue = calloc(size, sizeof(unsigned short));
+ ramp->size = size;
+}
+
+// Frees the red, green and blue value arrays and clears the struct
+//
+void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
+{
+ free(ramp->red);
+ free(ramp->green);
+ free(ramp->blue);
+
+ memset(ramp, 0, sizeof(GLFWgammaramp));
+}
+
+// Chooses the video mode most closely matching the desired one
+//
+const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
+ const GLFWvidmode* desired)
+{
+ int i;
+ unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
+ unsigned int rateDiff, leastRateDiff = UINT_MAX;
+ unsigned int colorDiff, leastColorDiff = UINT_MAX;
+ const GLFWvidmode* current;
+ const GLFWvidmode* closest = NULL;
+
+ if (!refreshVideoModes(monitor))
+ return NULL;
+
+ for (i = 0; i < monitor->modeCount; i++)
+ {
+ current = monitor->modes + i;
+
+ colorDiff = 0;
+
+ if (desired->redBits != GLFW_DONT_CARE)
+ colorDiff += abs(current->redBits - desired->redBits);
+ if (desired->greenBits != GLFW_DONT_CARE)
+ colorDiff += abs(current->greenBits - desired->greenBits);
+ if (desired->blueBits != GLFW_DONT_CARE)
+ colorDiff += abs(current->blueBits - desired->blueBits);
+
+ sizeDiff = abs((current->width - desired->width) *
+ (current->width - desired->width) +
+ (current->height - desired->height) *
+ (current->height - desired->height));
+
+ if (desired->refreshRate != GLFW_DONT_CARE)
+ rateDiff = abs(current->refreshRate - desired->refreshRate);
+ else
+ rateDiff = UINT_MAX - current->refreshRate;
+
+ if ((colorDiff < leastColorDiff) ||
+ (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
+ (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
+ {
+ closest = current;
+ leastSizeDiff = sizeDiff;
+ leastRateDiff = rateDiff;
+ leastColorDiff = colorDiff;
+ }
+ }
+
+ return closest;
+}
+
+// Performs lexical comparison between two @ref GLFWvidmode structures
+//
+int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
+{
+ return compareVideoModes(fm, sm);
+}
+
+// Splits a color depth into red, green and blue bit depths
+//
+void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
+{
+ int delta;
+
+ // We assume that by 32 the user really meant 24
+ if (bpp == 32)
+ bpp = 24;
+
+ // Convert "bits per pixel" to red, green & blue sizes
+
+ *red = *green = *blue = bpp / 3;
+ delta = bpp - (*red * 3);
+ if (delta >= 1)
+ *green = *green + 1;
+
+ if (delta == 2)
+ *red = *red + 1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
+{
+ assert(count != NULL);
+
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ *count = _glfw.monitorCount;
+ return (GLFWmonitor**) _glfw.monitors;
+}
+
+GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (!_glfw.monitorCount)
+ return NULL;
+
+ return (GLFWmonitor*) _glfw.monitors[0];
+}
+
+GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ if (xpos)
+ *xpos = 0;
+ if (ypos)
+ *ypos = 0;
+
+ _GLFW_REQUIRE_INIT();
+
+ _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
+}
+
+GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ if (widthMM)
+ *widthMM = 0;
+ if (heightMM)
+ *heightMM = 0;
+
+ _GLFW_REQUIRE_INIT();
+
+ if (widthMM)
+ *widthMM = monitor->widthMM;
+ if (heightMM)
+ *heightMM = monitor->heightMM;
+}
+
+GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
+ float* xscale, float* yscale)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ if (xscale)
+ *xscale = 0.f;
+ if (yscale)
+ *yscale = 0.f;
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
+}
+
+GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->name;
+}
+
+GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ monitor->userPointer = pointer;
+}
+
+GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->userPointer;
+}
+
+GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
+ return cbfun;
+}
+
+GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+ assert(count != NULL);
+
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (!refreshVideoModes(monitor))
+ return NULL;
+
+ *count = monitor->modeCount;
+ return monitor->modes;
+}
+
+GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ _glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
+ return &monitor->currentMode;
+}
+
+GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
+{
+ unsigned int i;
+ unsigned short* values;
+ GLFWgammaramp ramp;
+ const GLFWgammaramp* original;
+ assert(handle != NULL);
+ assert(gamma > 0.f);
+ assert(gamma <= FLT_MAX);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
+ return;
+ }
+
+ original = glfwGetGammaRamp(handle);
+ if (!original)
+ return;
+
+ values = calloc(original->size, sizeof(unsigned short));
+
+ for (i = 0; i < original->size; i++)
+ {
+ float value;
+
+ // Calculate intensity
+ value = i / (float) (original->size - 1);
+ // Apply gamma curve
+ value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
+ // Clamp to value range
+ value = _glfw_fminf(value, 65535.f);
+
+ values[i] = (unsigned short) value;
+ }
+
+ ramp.red = values;
+ ramp.green = values;
+ ramp.blue = values;
+ ramp.size = original->size;
+
+ glfwSetGammaRamp(handle, &ramp);
+ free(values);
+}
+
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ _glfwFreeGammaArrays(&monitor->currentRamp);
+ if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
+ return NULL;
+
+ return &monitor->currentRamp;
+}
+
+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+ assert(ramp != NULL);
+ assert(ramp->size > 0);
+ assert(ramp->red != NULL);
+ assert(ramp->green != NULL);
+ assert(ramp->blue != NULL);
+
+ if (ramp->size <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid gamma ramp size %i",
+ ramp->size);
+ return;
+ }
+
+ _GLFW_REQUIRE_INIT();
+
+ if (!monitor->originalRamp.size)
+ {
+ if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
+ return;
+ }
+
+ _glfwPlatformSetGammaRamp(monitor, ramp);
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.h b/Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.h
new file mode 100644
index 0000000..18042de
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.h
@@ -0,0 +1,56 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
+
+
+// NSGL-specific per-context data
+//
+typedef struct _GLFWcontextNSGL
+{
+ id pixelFormat;
+ id object;
+
+} _GLFWcontextNSGL;
+
+// NSGL-specific global data
+//
+typedef struct _GLFWlibraryNSGL
+{
+ // dlopen handle for OpenGL.framework (for glfwGetProcAddress)
+ CFBundleRef framework;
+
+} _GLFWlibraryNSGL;
+
+
+GLFWbool _glfwInitNSGL(void);
+void _glfwTerminateNSGL(void);
+GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+void _glfwDestroyContextNSGL(_GLFWwindow* window);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.m b/Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.m
new file mode 100644
index 0000000..ec1012e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/nsgl_context.m
@@ -0,0 +1,340 @@
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
+ #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
+ #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
+#endif
+
+static void makeContextCurrentNSGL(_GLFWwindow* window)
+{
+ if (window)
+ [window->context.nsgl.object makeCurrentContext];
+ else
+ [NSOpenGLContext clearCurrentContext];
+
+ _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static void swapBuffersNSGL(_GLFWwindow* window)
+{
+ // ARP appears to be unnecessary, but this is future-proof
+ [window->context.nsgl.object flushBuffer];
+}
+
+static void swapIntervalNSGL(int interval)
+{
+ _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+ GLint sync = interval;
+ [window->context.nsgl.object setValues:&sync
+ forParameter:NSOpenGLContextParameterSwapInterval];
+}
+
+static int extensionSupportedNSGL(const char* extension)
+{
+ // There are no NSGL extensions
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressNSGL(const char* procname)
+{
+ CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
+ procname,
+ kCFStringEncodingASCII);
+
+ GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
+ symbolName);
+
+ CFRelease(symbolName);
+
+ return symbol;
+}
+
+// Destroy the OpenGL context
+//
+static void destroyContextNSGL(_GLFWwindow* window)
+{
+ [window->context.nsgl.pixelFormat release];
+ window->context.nsgl.pixelFormat = nil;
+
+ [window->context.nsgl.object release];
+ window->context.nsgl.object = nil;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize OpenGL support
+//
+GLFWbool _glfwInitNSGL(void)
+{
+ if (_glfw.nsgl.framework)
+ return GLFW_TRUE;
+
+ _glfw.nsgl.framework =
+ CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ if (_glfw.nsgl.framework == NULL)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "NSGL: Failed to locate OpenGL framework");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Terminate OpenGL support
+//
+void _glfwTerminateNSGL(void)
+{
+}
+
+// Create the OpenGL context
+//
+GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "NSGL: OpenGL ES is not available on macOS");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->major > 2)
+ {
+ if (ctxconfig->major == 3 && ctxconfig->minor < 2)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
+ return GLFW_FALSE;
+ }
+
+ if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above");
+ return GLFW_FALSE;
+ }
+ }
+
+ // Context robustness modes (GL_KHR_robustness) are not yet supported by
+ // macOS but are not a hard constraint, so ignore and continue
+
+ // Context release behaviors (GL_KHR_context_flush_control) are not yet
+ // supported by macOS but are not a hard constraint, so ignore and continue
+
+ // Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
+ // a hard constraint, so ignore and continue
+
+ // No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
+ // are not a hard constraint, so ignore and continue
+
+#define addAttrib(a) \
+{ \
+ assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[index++] = a; \
+}
+#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
+
+ NSOpenGLPixelFormatAttribute attribs[40];
+ int index = 0;
+
+ addAttrib(NSOpenGLPFAAccelerated);
+ addAttrib(NSOpenGLPFAClosestPolicy);
+
+ if (ctxconfig->nsgl.offline)
+ {
+ addAttrib(NSOpenGLPFAAllowOfflineRenderers);
+ // NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
+ // Info.plist for unbundled applications
+ // HACK: This assumes that NSOpenGLPixelFormat will remain
+ // a straightforward wrapper of its CGL counterpart
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
+ addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
+#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+ }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+ if (ctxconfig->major >= 4)
+ {
+ setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
+ }
+ else
+#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+ if (ctxconfig->major >= 3)
+ {
+ setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
+ }
+
+ if (ctxconfig->major <= 2)
+ {
+ if (fbconfig->auxBuffers != GLFW_DONT_CARE)
+ setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
+
+ if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
+ fbconfig->accumGreenBits != GLFW_DONT_CARE &&
+ fbconfig->accumBlueBits != GLFW_DONT_CARE &&
+ fbconfig->accumAlphaBits != GLFW_DONT_CARE)
+ {
+ const int accumBits = fbconfig->accumRedBits +
+ fbconfig->accumGreenBits +
+ fbconfig->accumBlueBits +
+ fbconfig->accumAlphaBits;
+
+ setAttrib(NSOpenGLPFAAccumSize, accumBits);
+ }
+ }
+
+ if (fbconfig->redBits != GLFW_DONT_CARE &&
+ fbconfig->greenBits != GLFW_DONT_CARE &&
+ fbconfig->blueBits != GLFW_DONT_CARE)
+ {
+ int colorBits = fbconfig->redBits +
+ fbconfig->greenBits +
+ fbconfig->blueBits;
+
+ // macOS needs non-zero color size, so set reasonable values
+ if (colorBits == 0)
+ colorBits = 24;
+ else if (colorBits < 15)
+ colorBits = 15;
+
+ setAttrib(NSOpenGLPFAColorSize, colorBits);
+ }
+
+ if (fbconfig->alphaBits != GLFW_DONT_CARE)
+ setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
+
+ if (fbconfig->depthBits != GLFW_DONT_CARE)
+ setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
+
+ if (fbconfig->stencilBits != GLFW_DONT_CARE)
+ setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
+
+ if (fbconfig->stereo)
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "NSGL: Stereo rendering is deprecated");
+ return GLFW_FALSE;
+#else
+ addAttrib(NSOpenGLPFAStereo);
+#endif
+ }
+
+ if (fbconfig->doublebuffer)
+ addAttrib(NSOpenGLPFADoubleBuffer);
+
+ if (fbconfig->samples != GLFW_DONT_CARE)
+ {
+ if (fbconfig->samples == 0)
+ {
+ setAttrib(NSOpenGLPFASampleBuffers, 0);
+ }
+ else
+ {
+ setAttrib(NSOpenGLPFASampleBuffers, 1);
+ setAttrib(NSOpenGLPFASamples, fbconfig->samples);
+ }
+ }
+
+ // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
+ // framebuffer, so there's no need (and no way) to request it
+
+ addAttrib(0);
+
+#undef addAttrib
+#undef setAttrib
+
+ window->context.nsgl.pixelFormat =
+ [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ if (window->context.nsgl.pixelFormat == nil)
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "NSGL: Failed to find a suitable pixel format");
+ return GLFW_FALSE;
+ }
+
+ NSOpenGLContext* share = NULL;
+
+ if (ctxconfig->share)
+ share = ctxconfig->share->context.nsgl.object;
+
+ window->context.nsgl.object =
+ [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat
+ shareContext:share];
+ if (window->context.nsgl.object == nil)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "NSGL: Failed to create OpenGL context");
+ return GLFW_FALSE;
+ }
+
+ if (fbconfig->transparent)
+ {
+ GLint opaque = 0;
+ [window->context.nsgl.object setValues:&opaque
+ forParameter:NSOpenGLContextParameterSurfaceOpacity];
+ }
+
+ [window->context.nsgl.object setView:window->ns.view];
+
+ window->context.makeCurrent = makeContextCurrentNSGL;
+ window->context.swapBuffers = swapBuffersNSGL;
+ window->context.swapInterval = swapIntervalNSGL;
+ window->context.extensionSupported = extensionSupportedNSGL;
+ window->context.getProcAddress = getProcAddressNSGL;
+ window->context.destroy = destroyContextNSGL;
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(nil);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return NULL;
+ }
+
+ return window->context.nsgl.object;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/null_init.c b/Client/ThirdParty/Box2D/extern/glfw/src/null_init.c
new file mode 100644
index 0000000..3414738
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/null_init.c
@@ -0,0 +1,50 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ _glfwInitTimerPOSIX();
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ _glfwTerminateOSMesa();
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " null OSMesa";
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.c b/Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.c
new file mode 100644
index 0000000..afd65e1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.c
@@ -0,0 +1,42 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.h b/Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.h
new file mode 100644
index 0000000..3075815
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/null_joystick.h
@@ -0,0 +1,31 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs
+
+#define _GLFW_PLATFORM_MAPPING_NAME ""
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/null_monitor.c b/Client/ThirdParty/Box2D/extern/glfw/src/null_monitor.c
new file mode 100644
index 0000000..45c4a10
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/null_monitor.c
@@ -0,0 +1,69 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+ float* xscale, float* yscale)
+{
+ if (xscale)
+ *xscale = 1.f;
+ if (yscale)
+ *yscale = 1.f;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+ return NULL;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/null_platform.h b/Client/ThirdParty/Box2D/extern/glfw/src/null_platform.h
new file mode 100644
index 0000000..2d67c50
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/null_platform.h
@@ -0,0 +1,62 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <dlfcn.h>
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
+
+#define _GLFW_PLATFORM_CONTEXT_STATE
+#define _GLFW_PLATFORM_MONITOR_STATE
+#define _GLFW_PLATFORM_CURSOR_STATE
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
+#define _GLFW_EGL_CONTEXT_STATE
+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
+
+#include "osmesa_context.h"
+#include "posix_time.h"
+#include "posix_thread.h"
+#include "null_joystick.h"
+
+#if defined(_GLFW_WIN32)
+ #define _glfw_dlopen(name) LoadLibraryA(name)
+ #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
+ #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
+#else
+ #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+ #define _glfw_dlclose(handle) dlclose(handle)
+ #define _glfw_dlsym(handle, name) dlsym(handle, name)
+#endif
+
+// Null-specific per-window data
+//
+typedef struct _GLFWwindowNull
+{
+ int width;
+ int height;
+} _GLFWwindowNull;
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/null_window.c b/Client/ThirdParty/Box2D/extern/glfw/src/null_window.c
new file mode 100644
index 0000000..6a54cfe
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/null_window.c
@@ -0,0 +1,321 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+static int createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig)
+{
+ window->null.width = wndconfig->width;
+ window->null.height = wndconfig->height;
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!createNativeWindow(window, wndconfig))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
+ ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ if (!_glfwInitOSMesa())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
+ return GLFW_FALSE;
+ }
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (window->context.destroy)
+ window->context.destroy(window);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
+ const GLFWimage* images)
+{
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->null.width;
+ if (height)
+ *height = window->null.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ window->null.width = width;
+ window->null.height = height;
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
+{
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->null.width;
+ if (height)
+ *height = window->null.height;
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+ float* xscale, float* yscale)
+{
+ if (xscale)
+ *xscale = 1.f;
+ if (yscale)
+ *yscale = 1.f;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+ return 1.f;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+}
+
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformUnhideWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+ return NULL;
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+ return "";
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+ return -1;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ return GLFW_FALSE;
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ // This seems like the most appropriate error to return here
+ return VK_ERROR_INITIALIZATION_FAILED;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.c b/Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.c
new file mode 100644
index 0000000..03651eb
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.c
@@ -0,0 +1,370 @@
+//========================================================================
+// GLFW 3.3 OSMesa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "internal.h"
+
+
+static void makeContextCurrentOSMesa(_GLFWwindow* window)
+{
+ if (window)
+ {
+ int width, height;
+ _glfwPlatformGetFramebufferSize(window, &width, &height);
+
+ // Check to see if we need to allocate a new buffer
+ if ((window->context.osmesa.buffer == NULL) ||
+ (width != window->context.osmesa.width) ||
+ (height != window->context.osmesa.height))
+ {
+ free(window->context.osmesa.buffer);
+
+ // Allocate the new buffer (width * height * 8-bit RGBA)
+ window->context.osmesa.buffer = calloc(4, width * height);
+ window->context.osmesa.width = width;
+ window->context.osmesa.height = height;
+ }
+
+ if (!OSMesaMakeCurrent(window->context.osmesa.handle,
+ window->context.osmesa.buffer,
+ GL_UNSIGNED_BYTE,
+ width, height))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "OSMesa: Failed to make context current");
+ return;
+ }
+ }
+
+ _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static GLFWglproc getProcAddressOSMesa(const char* procname)
+{
+ return (GLFWglproc) OSMesaGetProcAddress(procname);
+}
+
+static void destroyContextOSMesa(_GLFWwindow* window)
+{
+ if (window->context.osmesa.handle)
+ {
+ OSMesaDestroyContext(window->context.osmesa.handle);
+ window->context.osmesa.handle = NULL;
+ }
+
+ if (window->context.osmesa.buffer)
+ {
+ free(window->context.osmesa.buffer);
+ window->context.osmesa.width = 0;
+ window->context.osmesa.height = 0;
+ }
+}
+
+static void swapBuffersOSMesa(_GLFWwindow* window)
+{
+ // No double buffering on OSMesa
+}
+
+static void swapIntervalOSMesa(int interval)
+{
+ // No swap interval on OSMesa
+}
+
+static int extensionSupportedOSMesa(const char* extension)
+{
+ // OSMesa does not have extensions
+ return GLFW_FALSE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitOSMesa(void)
+{
+ int i;
+ const char* sonames[] =
+ {
+#if defined(_GLFW_OSMESA_LIBRARY)
+ _GLFW_OSMESA_LIBRARY,
+#elif defined(_WIN32)
+ "libOSMesa.dll",
+ "OSMesa.dll",
+#elif defined(__APPLE__)
+ "libOSMesa.8.dylib",
+#elif defined(__CYGWIN__)
+ "libOSMesa-8.so",
+#else
+ "libOSMesa.so.8",
+ "libOSMesa.so.6",
+#endif
+ NULL
+ };
+
+ if (_glfw.osmesa.handle)
+ return GLFW_TRUE;
+
+ for (i = 0; sonames[i]; i++)
+ {
+ _glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
+ if (_glfw.osmesa.handle)
+ break;
+ }
+
+ if (!_glfw.osmesa.handle)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
+ return GLFW_FALSE;
+ }
+
+ _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
+ _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
+ _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
+ _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
+ _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
+ _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
+ _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
+ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
+
+ if (!_glfw.osmesa.CreateContextExt ||
+ !_glfw.osmesa.DestroyContext ||
+ !_glfw.osmesa.MakeCurrent ||
+ !_glfw.osmesa.GetColorBuffer ||
+ !_glfw.osmesa.GetDepthBuffer ||
+ !_glfw.osmesa.GetProcAddress)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "OSMesa: Failed to load required entry points");
+
+ _glfwTerminateOSMesa();
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwTerminateOSMesa(void)
+{
+ if (_glfw.osmesa.handle)
+ {
+ _glfw_dlclose(_glfw.osmesa.handle);
+ _glfw.osmesa.handle = NULL;
+ }
+}
+
+#define setAttrib(a, v) \
+{ \
+ assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[index++] = a; \
+ attribs[index++] = v; \
+}
+
+GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ OSMesaContext share = NULL;
+ const int accumBits = fbconfig->accumRedBits +
+ fbconfig->accumGreenBits +
+ fbconfig->accumBlueBits +
+ fbconfig->accumAlphaBits;
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "OSMesa: OpenGL ES is not available on OSMesa");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->share)
+ share = ctxconfig->share->context.osmesa.handle;
+
+ if (OSMesaCreateContextAttribs)
+ {
+ int index = 0, attribs[40];
+
+ setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
+ setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
+ setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
+ setAttrib(OSMESA_ACCUM_BITS, accumBits);
+
+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
+ {
+ setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
+ }
+ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
+ {
+ setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
+ }
+
+ if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+ {
+ setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
+ setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
+ }
+
+ if (ctxconfig->forward)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "OSMesa: Forward-compatible contexts not supported");
+ return GLFW_FALSE;
+ }
+
+ setAttrib(0, 0);
+
+ window->context.osmesa.handle =
+ OSMesaCreateContextAttribs(attribs, share);
+ }
+ else
+ {
+ if (ctxconfig->profile)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "OSMesa: OpenGL profiles unavailable");
+ return GLFW_FALSE;
+ }
+
+ window->context.osmesa.handle =
+ OSMesaCreateContextExt(OSMESA_RGBA,
+ fbconfig->depthBits,
+ fbconfig->stencilBits,
+ accumBits,
+ share);
+ }
+
+ if (window->context.osmesa.handle == NULL)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "OSMesa: Failed to create context");
+ return GLFW_FALSE;
+ }
+
+ window->context.makeCurrent = makeContextCurrentOSMesa;
+ window->context.swapBuffers = swapBuffersOSMesa;
+ window->context.swapInterval = swapIntervalOSMesa;
+ window->context.extensionSupported = extensionSupportedOSMesa;
+ window->context.getProcAddress = getProcAddressOSMesa;
+ window->context.destroy = destroyContextOSMesa;
+
+ return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
+ int* height, int* format, void** buffer)
+{
+ void* mesaBuffer;
+ GLint mesaWidth, mesaHeight, mesaFormat;
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
+ &mesaWidth, &mesaHeight,
+ &mesaFormat, &mesaBuffer))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "OSMesa: Failed to retrieve color buffer");
+ return GLFW_FALSE;
+ }
+
+ if (width)
+ *width = mesaWidth;
+ if (height)
+ *height = mesaHeight;
+ if (format)
+ *format = mesaFormat;
+ if (buffer)
+ *buffer = mesaBuffer;
+
+ return GLFW_TRUE;
+}
+
+GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
+ int* width, int* height,
+ int* bytesPerValue,
+ void** buffer)
+{
+ void* mesaBuffer;
+ GLint mesaWidth, mesaHeight, mesaBytes;
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
+ &mesaWidth, &mesaHeight,
+ &mesaBytes, &mesaBuffer))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "OSMesa: Failed to retrieve depth buffer");
+ return GLFW_FALSE;
+ }
+
+ if (width)
+ *width = mesaWidth;
+ if (height)
+ *height = mesaHeight;
+ if (bytesPerValue)
+ *bytesPerValue = mesaBytes;
+ if (buffer)
+ *buffer = mesaBuffer;
+
+ return GLFW_TRUE;
+}
+
+GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return NULL;
+ }
+
+ return window->context.osmesa.handle;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.h b/Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.h
new file mode 100644
index 0000000..07bb469
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/osmesa_context.h
@@ -0,0 +1,94 @@
+//========================================================================
+// GLFW 3.3 OSMesa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define OSMESA_RGBA 0x1908
+#define OSMESA_FORMAT 0x22
+#define OSMESA_DEPTH_BITS 0x30
+#define OSMESA_STENCIL_BITS 0x31
+#define OSMESA_ACCUM_BITS 0x32
+#define OSMESA_PROFILE 0x33
+#define OSMESA_CORE_PROFILE 0x34
+#define OSMESA_COMPAT_PROFILE 0x35
+#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
+#define OSMESA_CONTEXT_MINOR_VERSION 0x37
+
+typedef void* OSMesaContext;
+typedef void (*OSMESAproc)(void);
+
+typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
+typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
+typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
+typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
+typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
+typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
+typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
+#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
+#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
+#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
+#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
+#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
+#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
+#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
+
+#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
+#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
+
+
+// OSMesa-specific per-context data
+//
+typedef struct _GLFWcontextOSMesa
+{
+ OSMesaContext handle;
+ int width;
+ int height;
+ void* buffer;
+
+} _GLFWcontextOSMesa;
+
+// OSMesa-specific global data
+//
+typedef struct _GLFWlibraryOSMesa
+{
+ void* handle;
+
+ PFN_OSMesaCreateContextExt CreateContextExt;
+ PFN_OSMesaCreateContextAttribs CreateContextAttribs;
+ PFN_OSMesaDestroyContext DestroyContext;
+ PFN_OSMesaMakeCurrent MakeCurrent;
+ PFN_OSMesaGetColorBuffer GetColorBuffer;
+ PFN_OSMesaGetDepthBuffer GetDepthBuffer;
+ PFN_OSMesaGetProcAddress GetProcAddress;
+
+} _GLFWlibraryOSMesa;
+
+
+GLFWbool _glfwInitOSMesa(void);
+void _glfwTerminateOSMesa(void);
+GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.c b/Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.c
new file mode 100644
index 0000000..ce0bc39
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.c
@@ -0,0 +1,103 @@
+//========================================================================
+// GLFW 3.3 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
+{
+ assert(tls->posix.allocated == GLFW_FALSE);
+
+ if (pthread_key_create(&tls->posix.key, NULL) != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "POSIX: Failed to create context TLS");
+ return GLFW_FALSE;
+ }
+
+ tls->posix.allocated = GLFW_TRUE;
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyTls(_GLFWtls* tls)
+{
+ if (tls->posix.allocated)
+ pthread_key_delete(tls->posix.key);
+ memset(tls, 0, sizeof(_GLFWtls));
+}
+
+void* _glfwPlatformGetTls(_GLFWtls* tls)
+{
+ assert(tls->posix.allocated == GLFW_TRUE);
+ return pthread_getspecific(tls->posix.key);
+}
+
+void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
+{
+ assert(tls->posix.allocated == GLFW_TRUE);
+ pthread_setspecific(tls->posix.key, value);
+}
+
+GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
+{
+ assert(mutex->posix.allocated == GLFW_FALSE);
+
+ if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
+ return GLFW_FALSE;
+ }
+
+ return mutex->posix.allocated = GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
+{
+ if (mutex->posix.allocated)
+ pthread_mutex_destroy(&mutex->posix.handle);
+ memset(mutex, 0, sizeof(_GLFWmutex));
+}
+
+void _glfwPlatformLockMutex(_GLFWmutex* mutex)
+{
+ assert(mutex->posix.allocated == GLFW_TRUE);
+ pthread_mutex_lock(&mutex->posix.handle);
+}
+
+void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
+{
+ assert(mutex->posix.allocated == GLFW_TRUE);
+ pthread_mutex_unlock(&mutex->posix.handle);
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.h b/Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.h
new file mode 100644
index 0000000..bdddf41
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/posix_thread.h
@@ -0,0 +1,51 @@
+//========================================================================
+// GLFW 3.3 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <pthread.h>
+
+#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix
+#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexPOSIX posix
+
+
+// POSIX-specific thread local storage data
+//
+typedef struct _GLFWtlsPOSIX
+{
+ GLFWbool allocated;
+ pthread_key_t key;
+
+} _GLFWtlsPOSIX;
+
+// POSIX-specific mutex data
+//
+typedef struct _GLFWmutexPOSIX
+{
+ GLFWbool allocated;
+ pthread_mutex_t handle;
+
+} _GLFWmutexPOSIX;
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/posix_time.c b/Client/ThirdParty/Box2D/extern/glfw/src/posix_time.c
new file mode 100644
index 0000000..00b2831
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/posix_time.c
@@ -0,0 +1,85 @@
+//========================================================================
+// GLFW 3.3 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <sys/time.h>
+#include <time.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerPOSIX(void)
+{
+#if defined(CLOCK_MONOTONIC)
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ {
+ _glfw.timer.posix.monotonic = GLFW_TRUE;
+ _glfw.timer.posix.frequency = 1000000000;
+ }
+ else
+#endif
+ {
+ _glfw.timer.posix.monotonic = GLFW_FALSE;
+ _glfw.timer.posix.frequency = 1000000;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+#if defined(CLOCK_MONOTONIC)
+ if (_glfw.timer.posix.monotonic)
+ {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
+ }
+ else
+#endif
+ {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
+ }
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+ return _glfw.timer.posix.frequency;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/posix_time.h b/Client/ThirdParty/Box2D/extern/glfw/src/posix_time.h
new file mode 100644
index 0000000..f1a69eb
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/posix_time.h
@@ -0,0 +1,44 @@
+//========================================================================
+// GLFW 3.3 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
+
+#include <stdint.h>
+
+
+// POSIX-specific global timer data
+//
+typedef struct _GLFWtimerPOSIX
+{
+ GLFWbool monotonic;
+ uint64_t frequency;
+
+} _GLFWtimerPOSIX;
+
+
+void _glfwInitTimerPOSIX(void);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/vulkan.c b/Client/ThirdParty/Box2D/extern/glfw/src/vulkan.c
new file mode 100644
index 0000000..b8f752f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/vulkan.c
@@ -0,0 +1,326 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GLFW_FIND_LOADER 1
+#define _GLFW_REQUIRE_LOADER 2
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitVulkan(int mode)
+{
+ VkResult err;
+ VkExtensionProperties* ep;
+ uint32_t i, count;
+
+ if (_glfw.vk.available)
+ return GLFW_TRUE;
+
+#if !defined(_GLFW_VULKAN_STATIC)
+#if defined(_GLFW_VULKAN_LIBRARY)
+ _glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
+#elif defined(_GLFW_WIN32)
+ _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
+#elif defined(_GLFW_COCOA)
+ _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
+#else
+ _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
+#endif
+ if (!_glfw.vk.handle)
+ {
+ if (mode == _GLFW_REQUIRE_LOADER)
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
+
+ return GLFW_FALSE;
+ }
+
+ _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
+ _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
+ if (!_glfw.vk.GetInstanceProcAddr)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Loader does not export vkGetInstanceProcAddr");
+
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+
+ _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
+ vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
+ if (!_glfw.vk.EnumerateInstanceExtensionProperties)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
+
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+#endif // _GLFW_VULKAN_STATIC
+
+ err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
+ if (err)
+ {
+ // NOTE: This happens on systems with a loader but without any Vulkan ICD
+ if (mode == _GLFW_REQUIRE_LOADER)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Failed to query instance extension count: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+
+ ep = calloc(count, sizeof(VkExtensionProperties));
+
+ err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
+ if (err)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Failed to query instance extensions: %s",
+ _glfwGetVulkanResultString(err));
+
+ free(ep);
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
+ _glfw.vk.KHR_surface = GLFW_TRUE;
+#if defined(_GLFW_WIN32)
+ else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
+ _glfw.vk.KHR_win32_surface = GLFW_TRUE;
+#elif defined(_GLFW_COCOA)
+ else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
+ _glfw.vk.MVK_macos_surface = GLFW_TRUE;
+#elif defined(_GLFW_X11)
+ else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
+ _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
+ else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
+ _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
+#elif defined(_GLFW_WAYLAND)
+ else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
+ _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
+#endif
+ }
+
+ free(ep);
+
+ _glfw.vk.available = GLFW_TRUE;
+
+ _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
+
+ return GLFW_TRUE;
+}
+
+void _glfwTerminateVulkan(void)
+{
+#if !defined(_GLFW_VULKAN_STATIC)
+ if (_glfw.vk.handle)
+ _glfw_dlclose(_glfw.vk.handle);
+#endif
+}
+
+const char* _glfwGetVulkanResultString(VkResult result)
+{
+ switch (result)
+ {
+ case VK_SUCCESS:
+ return "Success";
+ case VK_NOT_READY:
+ return "A fence or query has not yet completed";
+ case VK_TIMEOUT:
+ return "A wait operation has not completed in the specified time";
+ case VK_EVENT_SET:
+ return "An event is signaled";
+ case VK_EVENT_RESET:
+ return "An event is unsignaled";
+ case VK_INCOMPLETE:
+ return "A return array was too small for the result";
+ case VK_ERROR_OUT_OF_HOST_MEMORY:
+ return "A host memory allocation has failed";
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+ return "A device memory allocation has failed";
+ case VK_ERROR_INITIALIZATION_FAILED:
+ return "Initialization of an object could not be completed for implementation-specific reasons";
+ case VK_ERROR_DEVICE_LOST:
+ return "The logical or physical device has been lost";
+ case VK_ERROR_MEMORY_MAP_FAILED:
+ return "Mapping of a memory object has failed";
+ case VK_ERROR_LAYER_NOT_PRESENT:
+ return "A requested layer is not present or could not be loaded";
+ case VK_ERROR_EXTENSION_NOT_PRESENT:
+ return "A requested extension is not supported";
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ return "A requested feature is not supported";
+ case VK_ERROR_INCOMPATIBLE_DRIVER:
+ return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
+ case VK_ERROR_TOO_MANY_OBJECTS:
+ return "Too many objects of the type have already been created";
+ case VK_ERROR_FORMAT_NOT_SUPPORTED:
+ return "A requested format is not supported on this device";
+ case VK_ERROR_SURFACE_LOST_KHR:
+ return "A surface is no longer available";
+ case VK_SUBOPTIMAL_KHR:
+ return "A swapchain no longer matches the surface properties exactly, but can still be used";
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ return "A surface has changed in such a way that it is no longer compatible with the swapchain";
+ case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
+ return "The display used by a swapchain does not use the same presentable image layout";
+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
+ return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
+ case VK_ERROR_VALIDATION_FAILED_EXT:
+ return "A validation layer found an error";
+ default:
+ return "ERROR: UNKNOWN VULKAN ERROR";
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwVulkanSupported(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+ return _glfwInitVulkan(_GLFW_FIND_LOADER);
+}
+
+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
+{
+ assert(count != NULL);
+
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+ return NULL;
+
+ if (!_glfw.vk.extensions[0])
+ return NULL;
+
+ *count = 2;
+ return (const char**) _glfw.vk.extensions;
+}
+
+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
+ const char* procname)
+{
+ GLFWvkproc proc;
+ assert(procname != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+ return NULL;
+
+ proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
+#if defined(_GLFW_VULKAN_STATIC)
+ if (!proc)
+ {
+ if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
+ return (GLFWvkproc) vkGetInstanceProcAddr;
+ }
+#else
+ if (!proc)
+ proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
+#endif
+
+ return proc;
+}
+
+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ assert(instance != VK_NULL_HANDLE);
+ assert(device != VK_NULL_HANDLE);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+ return GLFW_FALSE;
+
+ if (!_glfw.vk.extensions[0])
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Window surface creation extensions not found");
+ return GLFW_FALSE;
+ }
+
+ return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
+ device,
+ queuefamily);
+}
+
+GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
+ GLFWwindow* handle,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(instance != VK_NULL_HANDLE);
+ assert(window != NULL);
+ assert(surface != NULL);
+
+ *surface = VK_NULL_HANDLE;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
+
+ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+ return VK_ERROR_INITIALIZATION_FAILED;
+
+ if (!_glfw.vk.extensions[0])
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Window surface creation extensions not found");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ if (window->context.client != GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
+ return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
+ }
+
+ return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.c b/Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.c
new file mode 100644
index 0000000..06ba8b5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.c
@@ -0,0 +1,732 @@
+//========================================================================
+// GLFW 3.3 WGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <assert.h>
+
+
+// Returns the specified attribute of the specified pixel format
+//
+static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
+{
+ int value = 0;
+
+ assert(_glfw.wgl.ARB_pixel_format);
+
+ if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
+ pixelFormat,
+ 0, 1, &attrib, &value))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve pixel format attribute");
+ return 0;
+ }
+
+ return value;
+}
+
+// Return a list of available and usable framebuffer configs
+//
+static int choosePixelFormat(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ _GLFWfbconfig* usableConfigs;
+ const _GLFWfbconfig* closest;
+ int i, pixelFormat, nativeCount, usableCount;
+
+ if (_glfw.wgl.ARB_pixel_format)
+ {
+ nativeCount = getPixelFormatAttrib(window,
+ 1,
+ WGL_NUMBER_PIXEL_FORMATS_ARB);
+ }
+ else
+ {
+ nativeCount = DescribePixelFormat(window->context.wgl.dc,
+ 1,
+ sizeof(PIXELFORMATDESCRIPTOR),
+ NULL);
+ }
+
+ usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+ usableCount = 0;
+
+ for (i = 0; i < nativeCount; i++)
+ {
+ const int n = i + 1;
+ _GLFWfbconfig* u = usableConfigs + usableCount;
+
+ if (_glfw.wgl.ARB_pixel_format)
+ {
+ // Get pixel format attributes through "modern" extension
+
+ if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
+ !getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
+ {
+ continue;
+ }
+
+ if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
+ WGL_TYPE_RGBA_ARB)
+ {
+ continue;
+ }
+
+ if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
+ WGL_NO_ACCELERATION_ARB)
+ {
+ continue;
+ }
+
+ u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
+ u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
+ u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
+ u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
+
+ u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
+ u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
+
+ u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
+ u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
+ u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
+ u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
+
+ u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
+
+ if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
+ u->stereo = GLFW_TRUE;
+ if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
+ u->doublebuffer = GLFW_TRUE;
+
+ if (_glfw.wgl.ARB_multisample)
+ u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (_glfw.wgl.ARB_framebuffer_sRGB ||
+ _glfw.wgl.EXT_framebuffer_sRGB)
+ {
+ if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
+ u->sRGB = GLFW_TRUE;
+ }
+ }
+ else
+ {
+ if (_glfw.wgl.EXT_colorspace)
+ {
+ if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
+ WGL_COLORSPACE_SRGB_EXT)
+ {
+ u->sRGB = GLFW_TRUE;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Get pixel format attributes through legacy PFDs
+
+ PIXELFORMATDESCRIPTOR pfd;
+
+ if (!DescribePixelFormat(window->context.wgl.dc,
+ n,
+ sizeof(PIXELFORMATDESCRIPTOR),
+ &pfd))
+ {
+ continue;
+ }
+
+ if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
+ !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ {
+ continue;
+ }
+
+ if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
+ (pfd.dwFlags & PFD_GENERIC_FORMAT))
+ {
+ continue;
+ }
+
+ if (pfd.iPixelType != PFD_TYPE_RGBA)
+ continue;
+
+ u->redBits = pfd.cRedBits;
+ u->greenBits = pfd.cGreenBits;
+ u->blueBits = pfd.cBlueBits;
+ u->alphaBits = pfd.cAlphaBits;
+
+ u->depthBits = pfd.cDepthBits;
+ u->stencilBits = pfd.cStencilBits;
+
+ u->accumRedBits = pfd.cAccumRedBits;
+ u->accumGreenBits = pfd.cAccumGreenBits;
+ u->accumBlueBits = pfd.cAccumBlueBits;
+ u->accumAlphaBits = pfd.cAccumAlphaBits;
+
+ u->auxBuffers = pfd.cAuxBuffers;
+
+ if (pfd.dwFlags & PFD_STEREO)
+ u->stereo = GLFW_TRUE;
+ if (pfd.dwFlags & PFD_DOUBLEBUFFER)
+ u->doublebuffer = GLFW_TRUE;
+ }
+
+ u->handle = n;
+ usableCount++;
+ }
+
+ if (!usableCount)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "WGL: The driver does not appear to support OpenGL");
+
+ free(usableConfigs);
+ return 0;
+ }
+
+ closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
+ if (!closest)
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "WGL: Failed to find a suitable pixel format");
+
+ free(usableConfigs);
+ return 0;
+ }
+
+ pixelFormat = (int) closest->handle;
+ free(usableConfigs);
+
+ return pixelFormat;
+}
+
+static void makeContextCurrentWGL(_GLFWwindow* window)
+{
+ if (window)
+ {
+ if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
+ _glfwPlatformSetTls(&_glfw.contextSlot, window);
+ else
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to make context current");
+ _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
+ }
+ }
+ else
+ {
+ if (!wglMakeCurrent(NULL, NULL))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to clear current context");
+ }
+
+ _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
+ }
+}
+
+static void swapBuffersWGL(_GLFWwindow* window)
+{
+ if (!window->monitor)
+ {
+ if (IsWindowsVistaOrGreater())
+ {
+ BOOL enabled;
+
+ // HACK: Use DwmFlush when desktop composition is enabled
+ if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
+ {
+ int count = abs(window->context.wgl.interval);
+ while (count--)
+ DwmFlush();
+ }
+ }
+ }
+
+ SwapBuffers(window->context.wgl.dc);
+}
+
+static void swapIntervalWGL(int interval)
+{
+ _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+ window->context.wgl.interval = interval;
+
+ if (!window->monitor)
+ {
+ if (IsWindowsVistaOrGreater())
+ {
+ BOOL enabled;
+
+ // HACK: Disable WGL swap interval when desktop composition is enabled to
+ // avoid interfering with DWM vsync
+ if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
+ interval = 0;
+ }
+ }
+
+ if (_glfw.wgl.EXT_swap_control)
+ _glfw.wgl.SwapIntervalEXT(interval);
+}
+
+static int extensionSupportedWGL(const char* extension)
+{
+ const char* extensions = NULL;
+
+ if (_glfw.wgl.GetExtensionsStringARB)
+ extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
+ else if (_glfw.wgl.GetExtensionsStringEXT)
+ extensions = _glfw.wgl.GetExtensionsStringEXT();
+
+ if (!extensions)
+ return GLFW_FALSE;
+
+ return _glfwStringInExtensionString(extension, extensions);
+}
+
+static GLFWglproc getProcAddressWGL(const char* procname)
+{
+ const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
+ if (proc)
+ return proc;
+
+ return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
+}
+
+// Destroy the OpenGL context
+//
+static void destroyContextWGL(_GLFWwindow* window)
+{
+ if (window->context.wgl.handle)
+ {
+ wglDeleteContext(window->context.wgl.handle);
+ window->context.wgl.handle = NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize WGL
+//
+GLFWbool _glfwInitWGL(void)
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ HGLRC prc, rc;
+ HDC pdc, dc;
+
+ if (_glfw.wgl.instance)
+ return GLFW_TRUE;
+
+ _glfw.wgl.instance = LoadLibraryA("opengl32.dll");
+ if (!_glfw.wgl.instance)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to load opengl32.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.wgl.CreateContext = (PFN_wglCreateContext)
+ GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
+ _glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
+ GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
+ _glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
+ GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
+ _glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
+ GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
+ _glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
+ GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
+ _glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
+ GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
+ _glfw.wgl.ShareLists = (PFN_wglShareLists)
+ GetProcAddress(_glfw.wgl.instance, "wglShareLists");
+
+ // NOTE: A dummy context has to be created for opengl32.dll to load the
+ // OpenGL ICD, from which we can then query WGL extensions
+ // NOTE: This code will accept the Microsoft GDI ICD; accelerated context
+ // creation failure occurs during manual pixel format enumeration
+
+ dc = GetDC(_glfw.win32.helperWindowHandle);;
+
+ ZeroMemory(&pfd, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+
+ if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to set pixel format for dummy context");
+ return GLFW_FALSE;
+ }
+
+ rc = wglCreateContext(dc);
+ if (!rc)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to create dummy context");
+ return GLFW_FALSE;
+ }
+
+ pdc = wglGetCurrentDC();
+ prc = wglGetCurrentContext();
+
+ if (!wglMakeCurrent(dc, rc))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to make dummy context current");
+ wglMakeCurrent(pdc, prc);
+ wglDeleteContext(rc);
+ return GLFW_FALSE;
+ }
+
+ // NOTE: Functions must be loaded first as they're needed to retrieve the
+ // extension string that tells us whether the functions are supported
+ _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
+ wglGetProcAddress("wglGetExtensionsStringEXT");
+ _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
+ wglGetProcAddress("wglGetExtensionsStringARB");
+ _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
+ wglGetProcAddress("wglCreateContextAttribsARB");
+ _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
+ wglGetProcAddress("wglSwapIntervalEXT");
+ _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
+ wglGetProcAddress("wglGetPixelFormatAttribivARB");
+
+ // NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
+ // checked below as we are already using them
+ _glfw.wgl.ARB_multisample =
+ extensionSupportedWGL("WGL_ARB_multisample");
+ _glfw.wgl.ARB_framebuffer_sRGB =
+ extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
+ _glfw.wgl.EXT_framebuffer_sRGB =
+ extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
+ _glfw.wgl.ARB_create_context =
+ extensionSupportedWGL("WGL_ARB_create_context");
+ _glfw.wgl.ARB_create_context_profile =
+ extensionSupportedWGL("WGL_ARB_create_context_profile");
+ _glfw.wgl.EXT_create_context_es2_profile =
+ extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
+ _glfw.wgl.ARB_create_context_robustness =
+ extensionSupportedWGL("WGL_ARB_create_context_robustness");
+ _glfw.wgl.ARB_create_context_no_error =
+ extensionSupportedWGL("WGL_ARB_create_context_no_error");
+ _glfw.wgl.EXT_swap_control =
+ extensionSupportedWGL("WGL_EXT_swap_control");
+ _glfw.wgl.EXT_colorspace =
+ extensionSupportedWGL("WGL_EXT_colorspace");
+ _glfw.wgl.ARB_pixel_format =
+ extensionSupportedWGL("WGL_ARB_pixel_format");
+ _glfw.wgl.ARB_context_flush_control =
+ extensionSupportedWGL("WGL_ARB_context_flush_control");
+
+ wglMakeCurrent(pdc, prc);
+ wglDeleteContext(rc);
+ return GLFW_TRUE;
+}
+
+// Terminate WGL
+//
+void _glfwTerminateWGL(void)
+{
+ if (_glfw.wgl.instance)
+ FreeLibrary(_glfw.wgl.instance);
+}
+
+#define setAttrib(a, v) \
+{ \
+ assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+ attribs[index++] = a; \
+ attribs[index++] = v; \
+}
+
+// Create the OpenGL or OpenGL ES context
+//
+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ int attribs[40];
+ int pixelFormat;
+ PIXELFORMATDESCRIPTOR pfd;
+ HGLRC share = NULL;
+
+ if (ctxconfig->share)
+ share = ctxconfig->share->context.wgl.handle;
+
+ window->context.wgl.dc = GetDC(window->win32.handle);
+ if (!window->context.wgl.dc)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve DC for window");
+ return GLFW_FALSE;
+ }
+
+ pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
+ if (!pixelFormat)
+ return GLFW_FALSE;
+
+ if (!DescribePixelFormat(window->context.wgl.dc,
+ pixelFormat, sizeof(pfd), &pfd))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve PFD for selected pixel format");
+ return GLFW_FALSE;
+ }
+
+ if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to set selected pixel format");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (ctxconfig->forward)
+ {
+ if (!_glfw.wgl.ARB_create_context)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->profile)
+ {
+ if (!_glfw.wgl.ARB_create_context_profile)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
+ return GLFW_FALSE;
+ }
+ }
+ }
+ else
+ {
+ if (!_glfw.wgl.ARB_create_context ||
+ !_glfw.wgl.ARB_create_context_profile ||
+ !_glfw.wgl.EXT_create_context_es2_profile)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
+ return GLFW_FALSE;
+ }
+ }
+
+ if (_glfw.wgl.ARB_create_context)
+ {
+ int index = 0, mask = 0, flags = 0;
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if (ctxconfig->forward)
+ flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+
+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
+ mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
+ mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+ else
+ mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
+
+ if (ctxconfig->debug)
+ flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
+
+ if (ctxconfig->robustness)
+ {
+ if (_glfw.wgl.ARB_create_context_robustness)
+ {
+ if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+ {
+ setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ WGL_NO_RESET_NOTIFICATION_ARB);
+ }
+ else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ WGL_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
+ }
+ }
+
+ if (ctxconfig->release)
+ {
+ if (_glfw.wgl.ARB_context_flush_control)
+ {
+ if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
+ {
+ setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+ }
+ else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+ {
+ setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+ }
+ }
+ }
+
+ if (ctxconfig->noerror)
+ {
+ if (_glfw.wgl.ARB_create_context_no_error)
+ setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
+ }
+
+ // NOTE: Only request an explicitly versioned context when necessary, as
+ // explicitly requesting version 1.0 does not always return the
+ // highest version supported by the driver
+ if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+ {
+ setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
+ setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
+ }
+
+ if (flags)
+ setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
+
+ if (mask)
+ setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
+
+ setAttrib(0, 0);
+
+ window->context.wgl.handle =
+ _glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
+ share, attribs);
+ if (!window->context.wgl.handle)
+ {
+ const DWORD error = GetLastError();
+
+ if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
+ {
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Driver does not support OpenGL version %i.%i",
+ ctxconfig->major,
+ ctxconfig->minor);
+ }
+ else
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Driver does not support OpenGL ES version %i.%i",
+ ctxconfig->major,
+ ctxconfig->minor);
+ }
+ }
+ else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Driver does not support the requested OpenGL profile");
+ }
+ else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "WGL: The share context is not compatible with the requested context");
+ }
+ else
+ {
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Failed to create OpenGL context");
+ }
+ else
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Failed to create OpenGL ES context");
+ }
+ }
+
+ return GLFW_FALSE;
+ }
+ }
+ else
+ {
+ window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
+ if (!window->context.wgl.handle)
+ {
+ _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Failed to create OpenGL context");
+ return GLFW_FALSE;
+ }
+
+ if (share)
+ {
+ if (!wglShareLists(share, window->context.wgl.handle))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to enable sharing with specified OpenGL context");
+ return GLFW_FALSE;
+ }
+ }
+ }
+
+ window->context.makeCurrent = makeContextCurrentWGL;
+ window->context.swapBuffers = swapBuffersWGL;
+ window->context.swapInterval = swapIntervalWGL;
+ window->context.extensionSupported = extensionSupportedWGL;
+ window->context.getProcAddress = getProcAddressWGL;
+ window->context.destroy = destroyContextWGL;
+
+ return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return NULL;
+ }
+
+ return window->context.wgl.handle;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.h b/Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.h
new file mode 100644
index 0000000..c754038
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/wgl_context.h
@@ -0,0 +1,159 @@
+//========================================================================
+// GLFW 3.3 WGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_TYPE_RGBA_ARB 0x202b
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201a
+#define WGL_ALPHA_BITS_ARB 0x201b
+#define WGL_ALPHA_SHIFT_ARB 0x201c
+#define WGL_ACCUM_BITS_ARB 0x201d
+#define WGL_ACCUM_RED_BITS_ARB 0x201e
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_STEREO_ARB 0x2012
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_SAMPLES_ARB 0x2042
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
+#define WGL_COLORSPACE_EXT 0x309d
+#define WGL_COLORSPACE_SRGB_EXT 0x3089
+
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#define ERROR_INVALID_PROFILE_ARB 0x2096
+#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
+
+typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
+typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
+typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
+typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
+typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
+typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
+typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
+
+// opengl32.dll function pointer typedefs
+#define wglCreateContext _glfw.wgl.CreateContext
+#define wglDeleteContext _glfw.wgl.DeleteContext
+#define wglGetProcAddress _glfw.wgl.GetProcAddress
+#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
+#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
+#define wglMakeCurrent _glfw.wgl.MakeCurrent
+#define wglShareLists _glfw.wgl.ShareLists
+
+#define _GLFW_RECREATION_NOT_NEEDED 0
+#define _GLFW_RECREATION_REQUIRED 1
+#define _GLFW_RECREATION_IMPOSSIBLE 2
+
+#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
+
+
+// WGL-specific per-context data
+//
+typedef struct _GLFWcontextWGL
+{
+ HDC dc;
+ HGLRC handle;
+ int interval;
+
+} _GLFWcontextWGL;
+
+// WGL-specific global data
+//
+typedef struct _GLFWlibraryWGL
+{
+ HINSTANCE instance;
+ PFN_wglCreateContext CreateContext;
+ PFN_wglDeleteContext DeleteContext;
+ PFN_wglGetProcAddress GetProcAddress;
+ PFN_wglGetCurrentDC GetCurrentDC;
+ PFN_wglGetCurrentContext GetCurrentContext;
+ PFN_wglMakeCurrent MakeCurrent;
+ PFN_wglShareLists ShareLists;
+
+ PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
+ PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
+ PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
+ PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
+ GLFWbool EXT_swap_control;
+ GLFWbool EXT_colorspace;
+ GLFWbool ARB_multisample;
+ GLFWbool ARB_framebuffer_sRGB;
+ GLFWbool EXT_framebuffer_sRGB;
+ GLFWbool ARB_pixel_format;
+ GLFWbool ARB_create_context;
+ GLFWbool ARB_create_context_profile;
+ GLFWbool EXT_create_context_es2_profile;
+ GLFWbool ARB_create_context_robustness;
+ GLFWbool ARB_create_context_no_error;
+ GLFWbool ARB_context_flush_control;
+
+} _GLFWlibraryWGL;
+
+
+GLFWbool _glfwInitWGL(void);
+void _glfwTerminateWGL(void);
+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_init.c b/Client/ThirdParty/Box2D/extern/glfw/src/win32_init.c
new file mode 100644
index 0000000..3ee5eb8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_init.c
@@ -0,0 +1,627 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+
+static const GUID _glfw_GUID_DEVINTERFACE_HID =
+ {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
+
+#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
+
+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
+
+// Executables (but not DLLs) exporting this symbol with this value will be
+// automatically directed to the high-performance GPU on Nvidia Optimus systems
+// with up-to-date drivers
+//
+__declspec(dllexport) DWORD NvOptimusEnablement = 1;
+
+// Executables (but not DLLs) exporting this symbol with this value will be
+// automatically directed to the high-performance GPU on AMD PowerXpress systems
+// with up-to-date drivers
+//
+__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
+
+#endif // _GLFW_USE_HYBRID_HPG
+
+#if defined(_GLFW_BUILD_DLL)
+
+// GLFW DLL entry point
+//
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ return TRUE;
+}
+
+#endif // _GLFW_BUILD_DLL
+
+// Load necessary libraries (DLLs)
+//
+static GLFWbool loadLibraries(void)
+{
+ _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
+ if (!_glfw.win32.winmm.instance)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to load winmm.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32.winmm.GetTime = (PFN_timeGetTime)
+ GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
+
+ _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
+ if (!_glfw.win32.user32.instance)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to load user32.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
+ GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
+ _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
+ GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
+ _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
+ GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
+ _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
+ GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
+ _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
+ GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
+ _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
+ GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
+
+ _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
+ if (_glfw.win32.dinput8.instance)
+ {
+ _glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
+ GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
+ }
+
+ {
+ int i;
+ const char* names[] =
+ {
+ "xinput1_4.dll",
+ "xinput1_3.dll",
+ "xinput9_1_0.dll",
+ "xinput1_2.dll",
+ "xinput1_1.dll",
+ NULL
+ };
+
+ for (i = 0; names[i]; i++)
+ {
+ _glfw.win32.xinput.instance = LoadLibraryA(names[i]);
+ if (_glfw.win32.xinput.instance)
+ {
+ _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
+ GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
+ _glfw.win32.xinput.GetState = (PFN_XInputGetState)
+ GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
+
+ break;
+ }
+ }
+ }
+
+ _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
+ if (_glfw.win32.dwmapi.instance)
+ {
+ _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
+ GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
+ _glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
+ GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
+ _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
+ GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
+ }
+
+ _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
+ if (_glfw.win32.shcore.instance)
+ {
+ _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
+ GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
+ _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
+ GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
+ }
+
+ _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
+ if (_glfw.win32.ntdll.instance)
+ {
+ _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
+ GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
+ }
+
+ return GLFW_TRUE;
+}
+
+// Unload used libraries (DLLs)
+//
+static void freeLibraries(void)
+{
+ if (_glfw.win32.xinput.instance)
+ FreeLibrary(_glfw.win32.xinput.instance);
+
+ if (_glfw.win32.dinput8.instance)
+ FreeLibrary(_glfw.win32.dinput8.instance);
+
+ if (_glfw.win32.winmm.instance)
+ FreeLibrary(_glfw.win32.winmm.instance);
+
+ if (_glfw.win32.user32.instance)
+ FreeLibrary(_glfw.win32.user32.instance);
+
+ if (_glfw.win32.dwmapi.instance)
+ FreeLibrary(_glfw.win32.dwmapi.instance);
+
+ if (_glfw.win32.shcore.instance)
+ FreeLibrary(_glfw.win32.shcore.instance);
+
+ if (_glfw.win32.ntdll.instance)
+ FreeLibrary(_glfw.win32.ntdll.instance);
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode;
+
+ memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
+ memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
+
+ _glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
+ _glfw.win32.keycodes[0x002] = GLFW_KEY_1;
+ _glfw.win32.keycodes[0x003] = GLFW_KEY_2;
+ _glfw.win32.keycodes[0x004] = GLFW_KEY_3;
+ _glfw.win32.keycodes[0x005] = GLFW_KEY_4;
+ _glfw.win32.keycodes[0x006] = GLFW_KEY_5;
+ _glfw.win32.keycodes[0x007] = GLFW_KEY_6;
+ _glfw.win32.keycodes[0x008] = GLFW_KEY_7;
+ _glfw.win32.keycodes[0x009] = GLFW_KEY_8;
+ _glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
+ _glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
+ _glfw.win32.keycodes[0x030] = GLFW_KEY_B;
+ _glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
+ _glfw.win32.keycodes[0x020] = GLFW_KEY_D;
+ _glfw.win32.keycodes[0x012] = GLFW_KEY_E;
+ _glfw.win32.keycodes[0x021] = GLFW_KEY_F;
+ _glfw.win32.keycodes[0x022] = GLFW_KEY_G;
+ _glfw.win32.keycodes[0x023] = GLFW_KEY_H;
+ _glfw.win32.keycodes[0x017] = GLFW_KEY_I;
+ _glfw.win32.keycodes[0x024] = GLFW_KEY_J;
+ _glfw.win32.keycodes[0x025] = GLFW_KEY_K;
+ _glfw.win32.keycodes[0x026] = GLFW_KEY_L;
+ _glfw.win32.keycodes[0x032] = GLFW_KEY_M;
+ _glfw.win32.keycodes[0x031] = GLFW_KEY_N;
+ _glfw.win32.keycodes[0x018] = GLFW_KEY_O;
+ _glfw.win32.keycodes[0x019] = GLFW_KEY_P;
+ _glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
+ _glfw.win32.keycodes[0x013] = GLFW_KEY_R;
+ _glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
+ _glfw.win32.keycodes[0x014] = GLFW_KEY_T;
+ _glfw.win32.keycodes[0x016] = GLFW_KEY_U;
+ _glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
+ _glfw.win32.keycodes[0x011] = GLFW_KEY_W;
+ _glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
+ _glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
+ _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
+
+ _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
+ _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
+ _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
+ _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
+ _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
+ _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
+ _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
+ _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
+ _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
+
+ _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
+ _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
+ _glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
+ _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
+ _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
+ _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
+ _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
+ _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
+ _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
+ _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
+ _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
+ _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
+ _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
+ _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
+ _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
+ _glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
+ _glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
+ _glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
+ _glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
+ _glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
+ _glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
+ _glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
+ _glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
+ _glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
+ _glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
+ _glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
+ _glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
+ _glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
+ _glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
+ _glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
+ _glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
+ _glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
+ _glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
+ _glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
+ _glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
+ _glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
+ _glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
+ _glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
+ _glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
+ _glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
+ _glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
+ _glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
+ _glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
+ _glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
+ _glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
+ _glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
+ _glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
+ _glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
+
+ _glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
+ _glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
+ _glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
+ _glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
+ _glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
+ _glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
+ _glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
+ _glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
+ _glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
+ _glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
+ _glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
+ _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
+ _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
+ _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
+ _glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
+ _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
+
+ for (scancode = 0; scancode < 512; scancode++)
+ {
+ if (_glfw.win32.keycodes[scancode] > 0)
+ _glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
+ }
+}
+
+// Creates a dummy window for behind-the-scenes work
+//
+static HWND createHelperWindow(void)
+{
+ MSG msg;
+ HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
+ _GLFW_WNDCLASSNAME,
+ L"GLFW message window",
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ 0, 0, 1, 1,
+ NULL, NULL,
+ GetModuleHandleW(NULL),
+ NULL);
+ if (!window)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create helper window");
+ return NULL;
+ }
+
+ // HACK: The command to the first ShowWindow call is ignored if the parent
+ // process passed along a STARTUPINFO, so clear that with a no-op call
+ ShowWindow(window, SW_HIDE);
+
+ // Register for HID device notifications
+ {
+ DEV_BROADCAST_DEVICEINTERFACE_W dbi;
+ ZeroMemory(&dbi, sizeof(dbi));
+ dbi.dbcc_size = sizeof(dbi);
+ dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
+
+ _glfw.win32.deviceNotificationHandle =
+ RegisterDeviceNotificationW(window,
+ (DEV_BROADCAST_HDR*) &dbi,
+ DEVICE_NOTIFY_WINDOW_HANDLE);
+ }
+
+ while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+
+ return window;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Returns a wide string version of the specified UTF-8 string
+//
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
+{
+ WCHAR* target;
+ int count;
+
+ count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
+ if (!count)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string from UTF-8");
+ return NULL;
+ }
+
+ target = calloc(count, sizeof(WCHAR));
+
+ if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string from UTF-8");
+ free(target);
+ return NULL;
+ }
+
+ return target;
+}
+
+// Returns a UTF-8 string version of the specified wide string
+//
+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
+{
+ char* target;
+ int size;
+
+ size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+ if (!size)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string to UTF-8");
+ return NULL;
+ }
+
+ target = calloc(size, 1);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string to UTF-8");
+ free(target);
+ return NULL;
+ }
+
+ return target;
+}
+
+// Reports the specified error, appending information about the last Win32 error
+//
+void _glfwInputErrorWin32(int error, const char* description)
+{
+ WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
+ char message[_GLFW_MESSAGE_SIZE] = "";
+
+ FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL,
+ GetLastError() & 0xffff,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ buffer,
+ sizeof(buffer),
+ NULL);
+ WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
+
+ _glfwInputError(error, "%s: %s", description, message);
+}
+
+// Updates key names according to the current keyboard layout
+//
+void _glfwUpdateKeyNamesWin32(void)
+{
+ int key;
+ BYTE state[256] = {0};
+
+ memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
+
+ for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
+ {
+ UINT vk;
+ int scancode, length;
+ WCHAR chars[16];
+
+ scancode = _glfw.win32.scancodes[key];
+ if (scancode == -1)
+ continue;
+
+ if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
+ {
+ const UINT vks[] = {
+ VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
+ VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
+ VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
+ VK_MULTIPLY, VK_SUBTRACT, VK_ADD
+ };
+
+ vk = vks[key - GLFW_KEY_KP_0];
+ }
+ else
+ vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
+
+ length = ToUnicode(vk, scancode, state,
+ chars, sizeof(chars) / sizeof(WCHAR),
+ 0);
+
+ if (length == -1)
+ {
+ length = ToUnicode(vk, scancode, state,
+ chars, sizeof(chars) / sizeof(WCHAR),
+ 0);
+ }
+
+ if (length < 1)
+ continue;
+
+ WideCharToMultiByte(CP_UTF8, 0, chars, 1,
+ _glfw.win32.keynames[key],
+ sizeof(_glfw.win32.keynames[key]),
+ NULL, NULL);
+ }
+}
+
+// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
+//
+BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
+{
+ OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
+ DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
+ ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
+ // latter lies unless the user knew to embedd a non-default manifest
+ // announcing support for Windows 10 via supportedOS GUID
+ return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
+}
+
+// Checks whether we are on at least the specified build of Windows 10
+//
+BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
+{
+ OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
+ DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
+ ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
+ // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
+ // latter lies unless the user knew to embedd a non-default manifest
+ // announcing support for Windows 10 via supportedOS GUID
+ return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ // To make SetForegroundWindow work as we want, we need to fiddle
+ // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
+ // as possible in the hope of still being the foreground process)
+ SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
+ &_glfw.win32.foregroundLockTimeout, 0);
+ SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
+ SPIF_SENDCHANGE);
+
+ if (!loadLibraries())
+ return GLFW_FALSE;
+
+ createKeyTables();
+ _glfwUpdateKeyNamesWin32();
+
+ if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
+ SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+ else if (IsWindows8Point1OrGreater())
+ SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
+ else if (IsWindowsVistaOrGreater())
+ SetProcessDPIAware();
+
+ if (!_glfwRegisterWindowClassWin32())
+ return GLFW_FALSE;
+
+ _glfw.win32.helperWindowHandle = createHelperWindow();
+ if (!_glfw.win32.helperWindowHandle)
+ return GLFW_FALSE;
+
+ _glfwInitTimerWin32();
+ _glfwInitJoysticksWin32();
+
+ _glfwPollMonitorsWin32();
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ if (_glfw.win32.deviceNotificationHandle)
+ UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
+
+ if (_glfw.win32.helperWindowHandle)
+ DestroyWindow(_glfw.win32.helperWindowHandle);
+
+ _glfwUnregisterWindowClassWin32();
+
+ // Restore previous foreground lock timeout system setting
+ SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
+ UIntToPtr(_glfw.win32.foregroundLockTimeout),
+ SPIF_SENDCHANGE);
+
+ free(_glfw.win32.clipboardString);
+ free(_glfw.win32.rawInput);
+
+ _glfwTerminateWGL();
+ _glfwTerminateEGL();
+
+ _glfwTerminateJoysticksWin32();
+
+ freeLibraries();
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
+#if defined(__MINGW32__)
+ " MinGW"
+#elif defined(_MSC_VER)
+ " VisualC"
+#endif
+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
+ " hybrid-GPU"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " DLL"
+#endif
+ ;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.c b/Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.c
new file mode 100644
index 0000000..5812396
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.c
@@ -0,0 +1,753 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <math.h>
+
+#define _GLFW_TYPE_AXIS 0
+#define _GLFW_TYPE_SLIDER 1
+#define _GLFW_TYPE_BUTTON 2
+#define _GLFW_TYPE_POV 3
+
+// Data produced with DirectInput device object enumeration
+//
+typedef struct _GLFWobjenumWin32
+{
+ IDirectInputDevice8W* device;
+ _GLFWjoyobjectWin32* objects;
+ int objectCount;
+ int axisCount;
+ int sliderCount;
+ int buttonCount;
+ int povCount;
+} _GLFWobjenumWin32;
+
+// Define local copies of the necessary GUIDs
+//
+static const GUID _glfw_IID_IDirectInput8W =
+ {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
+static const GUID _glfw_GUID_XAxis =
+ {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_YAxis =
+ {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_ZAxis =
+ {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_RxAxis =
+ {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_RyAxis =
+ {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_RzAxis =
+ {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_Slider =
+ {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_POV =
+ {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+
+#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
+#define GUID_XAxis _glfw_GUID_XAxis
+#define GUID_YAxis _glfw_GUID_YAxis
+#define GUID_ZAxis _glfw_GUID_ZAxis
+#define GUID_RxAxis _glfw_GUID_RxAxis
+#define GUID_RyAxis _glfw_GUID_RyAxis
+#define GUID_RzAxis _glfw_GUID_RzAxis
+#define GUID_Slider _glfw_GUID_Slider
+#define GUID_POV _glfw_GUID_POV
+
+// Object data array for our clone of c_dfDIJoystick
+// Generated with https://github.com/elmindreda/c_dfDIJoystick2
+//
+static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
+{
+ { &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+};
+
+// Our clone of c_dfDIJoystick
+//
+static const DIDATAFORMAT _glfwDataFormat =
+{
+ sizeof(DIDATAFORMAT),
+ sizeof(DIOBJECTDATAFORMAT),
+ DIDFT_ABSAXIS,
+ sizeof(DIJOYSTATE),
+ sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
+ _glfwObjectDataFormats
+};
+
+// Returns a description fitting the specified XInput capabilities
+//
+static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
+{
+ switch (xic->SubType)
+ {
+ case XINPUT_DEVSUBTYPE_WHEEL:
+ return "XInput Wheel";
+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:
+ return "XInput Arcade Stick";
+ case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
+ return "XInput Flight Stick";
+ case XINPUT_DEVSUBTYPE_DANCE_PAD:
+ return "XInput Dance Pad";
+ case XINPUT_DEVSUBTYPE_GUITAR:
+ return "XInput Guitar";
+ case XINPUT_DEVSUBTYPE_DRUM_KIT:
+ return "XInput Drum Kit";
+ case XINPUT_DEVSUBTYPE_GAMEPAD:
+ {
+ if (xic->Flags & XINPUT_CAPS_WIRELESS)
+ return "Wireless Xbox Controller";
+ else
+ return "Xbox Controller";
+ }
+ }
+
+ return "Unknown XInput Device";
+}
+
+// Lexically compare device objects
+//
+static int compareJoystickObjects(const void* first, const void* second)
+{
+ const _GLFWjoyobjectWin32* fo = first;
+ const _GLFWjoyobjectWin32* so = second;
+
+ if (fo->type != so->type)
+ return fo->type - so->type;
+
+ return fo->offset - so->offset;
+}
+
+// Checks whether the specified device supports XInput
+// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
+//
+static GLFWbool supportsXInput(const GUID* guid)
+{
+ UINT i, count = 0;
+ RAWINPUTDEVICELIST* ridl;
+ GLFWbool result = GLFW_FALSE;
+
+ if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
+ return GLFW_FALSE;
+
+ ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
+
+ if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
+ {
+ free(ridl);
+ return GLFW_FALSE;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ RID_DEVICE_INFO rdi;
+ char name[256];
+ UINT size;
+
+ if (ridl[i].dwType != RIM_TYPEHID)
+ continue;
+
+ ZeroMemory(&rdi, sizeof(rdi));
+ rdi.cbSize = sizeof(rdi);
+ size = sizeof(rdi);
+
+ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
+ RIDI_DEVICEINFO,
+ &rdi, &size) == -1)
+ {
+ continue;
+ }
+
+ if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
+ continue;
+
+ memset(name, 0, sizeof(name));
+ size = sizeof(name);
+
+ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
+ RIDI_DEVICENAME,
+ name, &size) == -1)
+ {
+ break;
+ }
+
+ name[sizeof(name) - 1] = '\0';
+ if (strstr(name, "IG_"))
+ {
+ result = GLFW_TRUE;
+ break;
+ }
+ }
+
+ free(ridl);
+ return result;
+}
+
+// Frees all resources associated with the specified joystick
+//
+static void closeJoystick(_GLFWjoystick* js)
+{
+ if (js->win32.device)
+ {
+ IDirectInputDevice8_Unacquire(js->win32.device);
+ IDirectInputDevice8_Release(js->win32.device);
+ }
+
+ free(js->win32.objects);
+
+ _glfwFreeJoystick(js);
+ _glfwInputJoystick(js, GLFW_DISCONNECTED);
+}
+
+// DirectInput device object enumeration callback
+// Insights gleaned from SDL
+//
+static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
+ void* user)
+{
+ _GLFWobjenumWin32* data = user;
+ _GLFWjoyobjectWin32* object = data->objects + data->objectCount;
+
+ if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
+ {
+ DIPROPRANGE dipr;
+
+ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_SLIDER(data->sliderCount);
+ else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_X;
+ else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_Y;
+ else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_Z;
+ else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_RX;
+ else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_RY;
+ else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_RZ;
+ else
+ return DIENUM_CONTINUE;
+
+ ZeroMemory(&dipr, sizeof(dipr));
+ dipr.diph.dwSize = sizeof(dipr);
+ dipr.diph.dwHeaderSize = sizeof(dipr.diph);
+ dipr.diph.dwObj = doi->dwType;
+ dipr.diph.dwHow = DIPH_BYID;
+ dipr.lMin = -32768;
+ dipr.lMax = 32767;
+
+ if (FAILED(IDirectInputDevice8_SetProperty(data->device,
+ DIPROP_RANGE,
+ &dipr.diph)))
+ {
+ return DIENUM_CONTINUE;
+ }
+
+ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
+ {
+ object->type = _GLFW_TYPE_SLIDER;
+ data->sliderCount++;
+ }
+ else
+ {
+ object->type = _GLFW_TYPE_AXIS;
+ data->axisCount++;
+ }
+ }
+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
+ {
+ object->offset = DIJOFS_BUTTON(data->buttonCount);
+ object->type = _GLFW_TYPE_BUTTON;
+ data->buttonCount++;
+ }
+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
+ {
+ object->offset = DIJOFS_POV(data->povCount);
+ object->type = _GLFW_TYPE_POV;
+ data->povCount++;
+ }
+
+ data->objectCount++;
+ return DIENUM_CONTINUE;
+}
+
+// DirectInput device enumeration callback
+//
+static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
+{
+ int jid = 0;
+ DIDEVCAPS dc;
+ DIPROPDWORD dipd;
+ IDirectInputDevice8* device;
+ _GLFWobjenumWin32 data;
+ _GLFWjoystick* js;
+ char guid[33];
+ char name[256];
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ _GLFWjoystick* js = _glfw.joysticks + jid;
+ if (js->present)
+ {
+ if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
+ return DIENUM_CONTINUE;
+ }
+ }
+
+ if (supportsXInput(&di->guidProduct))
+ return DIENUM_CONTINUE;
+
+ if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
+ &di->guidInstance,
+ &device,
+ NULL)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
+ return DIENUM_CONTINUE;
+ }
+
+ if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to set device data format");
+
+ IDirectInputDevice8_Release(device);
+ return DIENUM_CONTINUE;
+ }
+
+ ZeroMemory(&dc, sizeof(dc));
+ dc.dwSize = sizeof(dc);
+
+ if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to query device capabilities");
+
+ IDirectInputDevice8_Release(device);
+ return DIENUM_CONTINUE;
+ }
+
+ ZeroMemory(&dipd, sizeof(dipd));
+ dipd.diph.dwSize = sizeof(dipd);
+ dipd.diph.dwHeaderSize = sizeof(dipd.diph);
+ dipd.diph.dwHow = DIPH_DEVICE;
+ dipd.dwData = DIPROPAXISMODE_ABS;
+
+ if (FAILED(IDirectInputDevice8_SetProperty(device,
+ DIPROP_AXISMODE,
+ &dipd.diph)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to set device axis mode");
+
+ IDirectInputDevice8_Release(device);
+ return DIENUM_CONTINUE;
+ }
+
+ memset(&data, 0, sizeof(data));
+ data.device = device;
+ data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs,
+ sizeof(_GLFWjoyobjectWin32));
+
+ if (FAILED(IDirectInputDevice8_EnumObjects(device,
+ deviceObjectCallback,
+ &data,
+ DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to enumerate device objects");
+
+ IDirectInputDevice8_Release(device);
+ free(data.objects);
+ return DIENUM_CONTINUE;
+ }
+
+ qsort(data.objects, data.objectCount,
+ sizeof(_GLFWjoyobjectWin32),
+ compareJoystickObjects);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0,
+ di->tszInstanceName, -1,
+ name, sizeof(name),
+ NULL, NULL))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert joystick name to UTF-8");
+
+ IDirectInputDevice8_Release(device);
+ free(data.objects);
+ return DIENUM_STOP;
+ }
+
+ // Generate a joystick GUID that matches the SDL 2.0.5+ one
+ if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
+ {
+ sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
+ (uint8_t) di->guidProduct.Data1,
+ (uint8_t) (di->guidProduct.Data1 >> 8),
+ (uint8_t) (di->guidProduct.Data1 >> 16),
+ (uint8_t) (di->guidProduct.Data1 >> 24));
+ }
+ else
+ {
+ sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
+ name[0], name[1], name[2], name[3],
+ name[4], name[5], name[6], name[7],
+ name[8], name[9], name[10]);
+ }
+
+ js = _glfwAllocJoystick(name, guid,
+ data.axisCount + data.sliderCount,
+ data.buttonCount,
+ data.povCount);
+ if (!js)
+ {
+ IDirectInputDevice8_Release(device);
+ free(data.objects);
+ return DIENUM_STOP;
+ }
+
+ js->win32.device = device;
+ js->win32.guid = di->guidInstance;
+ js->win32.objects = data.objects;
+ js->win32.objectCount = data.objectCount;
+
+ _glfwInputJoystick(js, GLFW_CONNECTED);
+ return DIENUM_CONTINUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+void _glfwInitJoysticksWin32(void)
+{
+ if (_glfw.win32.dinput8.instance)
+ {
+ if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
+ DIRECTINPUT_VERSION,
+ &IID_IDirectInput8W,
+ (void**) &_glfw.win32.dinput8.api,
+ NULL)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create interface");
+ }
+ }
+
+ _glfwDetectJoystickConnectionWin32();
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksWin32(void)
+{
+ int jid;
+
+ for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
+ closeJoystick(_glfw.joysticks + jid);
+
+ if (_glfw.win32.dinput8.api)
+ IDirectInput8_Release(_glfw.win32.dinput8.api);
+}
+
+// Checks for new joysticks after DBT_DEVICEARRIVAL
+//
+void _glfwDetectJoystickConnectionWin32(void)
+{
+ if (_glfw.win32.xinput.instance)
+ {
+ DWORD index;
+
+ for (index = 0; index < XUSER_MAX_COUNT; index++)
+ {
+ int jid;
+ char guid[33];
+ XINPUT_CAPABILITIES xic;
+ _GLFWjoystick* js;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ if (_glfw.joysticks[jid].present &&
+ _glfw.joysticks[jid].win32.device == NULL &&
+ _glfw.joysticks[jid].win32.index == index)
+ {
+ break;
+ }
+ }
+
+ if (jid <= GLFW_JOYSTICK_LAST)
+ continue;
+
+ if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
+ continue;
+
+ // Generate a joystick GUID that matches the SDL 2.0.5+ one
+ sprintf(guid, "78696e707574%02x000000000000000000",
+ xic.SubType & 0xff);
+
+ js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
+ if (!js)
+ continue;
+
+ js->win32.index = index;
+
+ _glfwInputJoystick(js, GLFW_CONNECTED);
+ }
+ }
+
+ if (_glfw.win32.dinput8.api)
+ {
+ if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
+ DI8DEVCLASS_GAMECTRL,
+ deviceCallback,
+ NULL,
+ DIEDFL_ALLDEVICES)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Failed to enumerate DirectInput8 devices");
+ return;
+ }
+ }
+}
+
+// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
+//
+void _glfwDetectJoystickDisconnectionWin32(void)
+{
+ int jid;
+
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
+ {
+ _GLFWjoystick* js = _glfw.joysticks + jid;
+ if (js->present)
+ _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+ if (js->win32.device)
+ {
+ int i, ai = 0, bi = 0, pi = 0;
+ HRESULT result;
+ DIJOYSTATE state;
+
+ IDirectInputDevice8_Poll(js->win32.device);
+ result = IDirectInputDevice8_GetDeviceState(js->win32.device,
+ sizeof(state),
+ &state);
+ if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
+ {
+ IDirectInputDevice8_Acquire(js->win32.device);
+ IDirectInputDevice8_Poll(js->win32.device);
+ result = IDirectInputDevice8_GetDeviceState(js->win32.device,
+ sizeof(state),
+ &state);
+ }
+
+ if (FAILED(result))
+ {
+ closeJoystick(js);
+ return GLFW_FALSE;
+ }
+
+ if (mode == _GLFW_POLL_PRESENCE)
+ return GLFW_TRUE;
+
+ for (i = 0; i < js->win32.objectCount; i++)
+ {
+ const void* data = (char*) &state + js->win32.objects[i].offset;
+
+ switch (js->win32.objects[i].type)
+ {
+ case _GLFW_TYPE_AXIS:
+ case _GLFW_TYPE_SLIDER:
+ {
+ const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
+ _glfwInputJoystickAxis(js, ai, value);
+ ai++;
+ break;
+ }
+
+ case _GLFW_TYPE_BUTTON:
+ {
+ const char value = (*((BYTE*) data) & 0x80) != 0;
+ _glfwInputJoystickButton(js, bi, value);
+ bi++;
+ break;
+ }
+
+ case _GLFW_TYPE_POV:
+ {
+ const int states[9] =
+ {
+ GLFW_HAT_UP,
+ GLFW_HAT_RIGHT_UP,
+ GLFW_HAT_RIGHT,
+ GLFW_HAT_RIGHT_DOWN,
+ GLFW_HAT_DOWN,
+ GLFW_HAT_LEFT_DOWN,
+ GLFW_HAT_LEFT,
+ GLFW_HAT_LEFT_UP,
+ GLFW_HAT_CENTERED
+ };
+
+ // Screams of horror are appropriate at this point
+ int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
+ if (state < 0 || state > 8)
+ state = 8;
+
+ _glfwInputJoystickHat(js, pi, states[state]);
+ pi++;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ int i, dpad = 0;
+ DWORD result;
+ XINPUT_STATE xis;
+ const WORD buttons[10] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_BACK,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB
+ };
+
+ result = XInputGetState(js->win32.index, &xis);
+ if (result != ERROR_SUCCESS)
+ {
+ if (result == ERROR_DEVICE_NOT_CONNECTED)
+ closeJoystick(js);
+
+ return GLFW_FALSE;
+ }
+
+ if (mode == _GLFW_POLL_PRESENCE)
+ return GLFW_TRUE;
+
+ _glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
+ _glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
+ _glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
+ _glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
+ _glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
+ _glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
+
+ for (i = 0; i < 10; i++)
+ {
+ const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
+ _glfwInputJoystickButton(js, i, value);
+ }
+
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
+ dpad |= GLFW_HAT_UP;
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
+ dpad |= GLFW_HAT_RIGHT;
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
+ dpad |= GLFW_HAT_DOWN;
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
+ dpad |= GLFW_HAT_LEFT;
+
+ _glfwInputJoystickHat(js, 0, dpad);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+ if (strcmp(guid + 20, "504944564944") == 0)
+ {
+ char original[33];
+ strcpy(original, guid);
+ sprintf(guid, "03000000%.4s0000%.4s000000000000",
+ original, original + 4);
+ }
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.h b/Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.h
new file mode 100644
index 0000000..9156f6c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_joystick.h
@@ -0,0 +1,56 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
+
+#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
+
+// Joystick element (axis, button or slider)
+//
+typedef struct _GLFWjoyobjectWin32
+{
+ int offset;
+ int type;
+} _GLFWjoyobjectWin32;
+
+// Win32-specific per-joystick data
+//
+typedef struct _GLFWjoystickWin32
+{
+ _GLFWjoyobjectWin32* objects;
+ int objectCount;
+ IDirectInputDevice8W* device;
+ DWORD index;
+ GUID guid;
+} _GLFWjoystickWin32;
+
+
+void _glfwInitJoysticksWin32(void);
+void _glfwTerminateJoysticksWin32(void);
+void _glfwDetectJoystickConnectionWin32(void);
+void _glfwDetectJoystickDisconnectionWin32(void);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_monitor.c b/Client/ThirdParty/Box2D/extern/glfw/src/win32_monitor.c
new file mode 100644
index 0000000..07b3614
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_monitor.c
@@ -0,0 +1,515 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <malloc.h>
+
+
+// Callback for EnumDisplayMonitors in createMonitor
+//
+static BOOL CALLBACK monitorCallback(HMONITOR handle,
+ HDC dc,
+ RECT* rect,
+ LPARAM data)
+{
+ MONITORINFOEXW mi;
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+
+ if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
+ {
+ _GLFWmonitor* monitor = (_GLFWmonitor*) data;
+ if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
+ monitor->win32.handle = handle;
+ }
+
+ return TRUE;
+}
+
+// Create monitor from an adapter and (optionally) a display
+//
+static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
+ DISPLAY_DEVICEW* display)
+{
+ _GLFWmonitor* monitor;
+ int widthMM, heightMM;
+ char* name;
+ HDC dc;
+ DEVMODEW dm;
+ RECT rect;
+
+ if (display)
+ name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
+ else
+ name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
+ if (!name)
+ return NULL;
+
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+ EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
+
+ dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
+
+ if (IsWindows8Point1OrGreater())
+ {
+ widthMM = GetDeviceCaps(dc, HORZSIZE);
+ heightMM = GetDeviceCaps(dc, VERTSIZE);
+ }
+ else
+ {
+ widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
+ heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
+ }
+
+ DeleteDC(dc);
+
+ monitor = _glfwAllocMonitor(name, widthMM, heightMM);
+ free(name);
+
+ if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
+ monitor->win32.modesPruned = GLFW_TRUE;
+
+ wcscpy(monitor->win32.adapterName, adapter->DeviceName);
+ WideCharToMultiByte(CP_UTF8, 0,
+ adapter->DeviceName, -1,
+ monitor->win32.publicAdapterName,
+ sizeof(monitor->win32.publicAdapterName),
+ NULL, NULL);
+
+ if (display)
+ {
+ wcscpy(monitor->win32.displayName, display->DeviceName);
+ WideCharToMultiByte(CP_UTF8, 0,
+ display->DeviceName, -1,
+ monitor->win32.publicDisplayName,
+ sizeof(monitor->win32.publicDisplayName),
+ NULL, NULL);
+ }
+
+ rect.left = dm.dmPosition.x;
+ rect.top = dm.dmPosition.y;
+ rect.right = dm.dmPosition.x + dm.dmPelsWidth;
+ rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
+
+ EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
+ return monitor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Poll for changes in the set of connected monitors
+//
+void _glfwPollMonitorsWin32(void)
+{
+ int i, disconnectedCount;
+ _GLFWmonitor** disconnected = NULL;
+ DWORD adapterIndex, displayIndex;
+ DISPLAY_DEVICEW adapter, display;
+ _GLFWmonitor* monitor;
+
+ disconnectedCount = _glfw.monitorCount;
+ if (disconnectedCount)
+ {
+ disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
+ memcpy(disconnected,
+ _glfw.monitors,
+ _glfw.monitorCount * sizeof(_GLFWmonitor*));
+ }
+
+ for (adapterIndex = 0; ; adapterIndex++)
+ {
+ int type = _GLFW_INSERT_LAST;
+
+ ZeroMemory(&adapter, sizeof(adapter));
+ adapter.cb = sizeof(adapter);
+
+ if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
+ break;
+
+ if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
+ continue;
+
+ if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+ type = _GLFW_INSERT_FIRST;
+
+ for (displayIndex = 0; ; displayIndex++)
+ {
+ ZeroMemory(&display, sizeof(display));
+ display.cb = sizeof(display);
+
+ if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
+ break;
+
+ if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
+ continue;
+
+ for (i = 0; i < disconnectedCount; i++)
+ {
+ if (disconnected[i] &&
+ wcscmp(disconnected[i]->win32.displayName,
+ display.DeviceName) == 0)
+ {
+ disconnected[i] = NULL;
+ break;
+ }
+ }
+
+ if (i < disconnectedCount)
+ continue;
+
+ monitor = createMonitor(&adapter, &display);
+ if (!monitor)
+ {
+ free(disconnected);
+ return;
+ }
+
+ _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
+
+ type = _GLFW_INSERT_LAST;
+ }
+
+ // HACK: If an active adapter does not have any display devices
+ // (as sometimes happens), add it directly as a monitor
+ if (displayIndex == 0)
+ {
+ for (i = 0; i < disconnectedCount; i++)
+ {
+ if (disconnected[i] &&
+ wcscmp(disconnected[i]->win32.adapterName,
+ adapter.DeviceName) == 0)
+ {
+ disconnected[i] = NULL;
+ break;
+ }
+ }
+
+ if (i < disconnectedCount)
+ continue;
+
+ monitor = createMonitor(&adapter, NULL);
+ if (!monitor)
+ {
+ free(disconnected);
+ return;
+ }
+
+ _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
+ }
+ }
+
+ for (i = 0; i < disconnectedCount; i++)
+ {
+ if (disconnected[i])
+ _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
+ }
+
+ free(disconnected);
+}
+
+// Change the current video mode
+//
+void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+ GLFWvidmode current;
+ const GLFWvidmode* best;
+ DEVMODEW dm;
+ LONG result;
+
+ best = _glfwChooseVideoMode(monitor, desired);
+ _glfwPlatformGetVideoMode(monitor, &current);
+ if (_glfwCompareVideoModes(&current, best) == 0)
+ return;
+
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+ dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
+ DM_DISPLAYFREQUENCY;
+ dm.dmPelsWidth = best->width;
+ dm.dmPelsHeight = best->height;
+ dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits;
+ dm.dmDisplayFrequency = best->refreshRate;
+
+ if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
+ dm.dmBitsPerPel = 32;
+
+ result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
+ &dm,
+ NULL,
+ CDS_FULLSCREEN,
+ NULL);
+ if (result == DISP_CHANGE_SUCCESSFUL)
+ monitor->win32.modeChanged = GLFW_TRUE;
+ else
+ {
+ const char* description = "Unknown error";
+
+ if (result == DISP_CHANGE_BADDUALVIEW)
+ description = "The system uses DualView";
+ else if (result == DISP_CHANGE_BADFLAGS)
+ description = "Invalid flags";
+ else if (result == DISP_CHANGE_BADMODE)
+ description = "Graphics mode not supported";
+ else if (result == DISP_CHANGE_BADPARAM)
+ description = "Invalid parameter";
+ else if (result == DISP_CHANGE_FAILED)
+ description = "Graphics mode failed";
+ else if (result == DISP_CHANGE_NOTUPDATED)
+ description = "Failed to write to registry";
+ else if (result == DISP_CHANGE_RESTART)
+ description = "Computer restart required";
+
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to set video mode: %s",
+ description);
+ }
+}
+
+// Restore the previously saved (original) video mode
+//
+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
+{
+ if (monitor->win32.modeChanged)
+ {
+ ChangeDisplaySettingsExW(monitor->win32.adapterName,
+ NULL, NULL, CDS_FULLSCREEN, NULL);
+ monitor->win32.modeChanged = GLFW_FALSE;
+ }
+}
+
+void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
+{
+ UINT xdpi, ydpi;
+
+ if (IsWindows8Point1OrGreater())
+ GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
+ else
+ {
+ const HDC dc = GetDC(NULL);
+ xdpi = GetDeviceCaps(dc, LOGPIXELSX);
+ ydpi = GetDeviceCaps(dc, LOGPIXELSY);
+ ReleaseDC(NULL, dc);
+ }
+
+ if (xscale)
+ *xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
+ if (yscale)
+ *yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ DEVMODEW dm;
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ EnumDisplaySettingsExW(monitor->win32.adapterName,
+ ENUM_CURRENT_SETTINGS,
+ &dm,
+ EDS_ROTATEDMODE);
+
+ if (xpos)
+ *xpos = dm.dmPosition.x;
+ if (ypos)
+ *ypos = dm.dmPosition.y;
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+ float* xscale, float* yscale)
+{
+ _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+ int modeIndex = 0, size = 0;
+ GLFWvidmode* result = NULL;
+
+ *count = 0;
+
+ for (;;)
+ {
+ int i;
+ GLFWvidmode mode;
+ DEVMODEW dm;
+
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
+ break;
+
+ modeIndex++;
+
+ // Skip modes with less than 15 BPP
+ if (dm.dmBitsPerPel < 15)
+ continue;
+
+ mode.width = dm.dmPelsWidth;
+ mode.height = dm.dmPelsHeight;
+ mode.refreshRate = dm.dmDisplayFrequency;
+ _glfwSplitBPP(dm.dmBitsPerPel,
+ &mode.redBits,
+ &mode.greenBits,
+ &mode.blueBits);
+
+ for (i = 0; i < *count; i++)
+ {
+ if (_glfwCompareVideoModes(result + i, &mode) == 0)
+ break;
+ }
+
+ // Skip duplicate modes
+ if (i < *count)
+ continue;
+
+ if (monitor->win32.modesPruned)
+ {
+ // Skip modes not supported by the connected displays
+ if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
+ &dm,
+ NULL,
+ CDS_TEST,
+ NULL) != DISP_CHANGE_SUCCESSFUL)
+ {
+ continue;
+ }
+ }
+
+ if (*count == size)
+ {
+ size += 128;
+ result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
+ }
+
+ (*count)++;
+ result[*count - 1] = mode;
+ }
+
+ if (!*count)
+ {
+ // HACK: Report the current mode if no valid modes were found
+ result = calloc(1, sizeof(GLFWvidmode));
+ _glfwPlatformGetVideoMode(monitor, result);
+ *count = 1;
+ }
+
+ return result;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+ DEVMODEW dm;
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(dm);
+
+ EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
+
+ mode->width = dm.dmPelsWidth;
+ mode->height = dm.dmPelsHeight;
+ mode->refreshRate = dm.dmDisplayFrequency;
+ _glfwSplitBPP(dm.dmBitsPerPel,
+ &mode->redBits,
+ &mode->greenBits,
+ &mode->blueBits);
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ HDC dc;
+ WORD values[768];
+
+ dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
+ GetDeviceGammaRamp(dc, values);
+ DeleteDC(dc);
+
+ _glfwAllocGammaArrays(ramp, 256);
+
+ memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short));
+ memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
+ memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short));
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ HDC dc;
+ WORD values[768];
+
+ if (ramp->size != 256)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Gamma ramp size must be 256");
+ return;
+ }
+
+ memcpy(values + 0, ramp->red, 256 * sizeof(unsigned short));
+ memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short));
+ memcpy(values + 512, ramp->blue, 256 * sizeof(unsigned short));
+
+ dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
+ SetDeviceGammaRamp(dc, values);
+ DeleteDC(dc);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->win32.publicAdapterName;
+}
+
+GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->win32.publicDisplayName;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_platform.h b/Client/ThirdParty/Box2D/extern/glfw/src/win32_platform.h
new file mode 100644
index 0000000..712de7f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_platform.h
@@ -0,0 +1,449 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+// We don't need all the fancy stuff
+#ifndef NOMINMAX
+ #define NOMINMAX
+#endif
+
+#ifndef VC_EXTRALEAN
+ #define VC_EXTRALEAN
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+#endif
+
+// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
+// example to allow applications to correctly declare a GL_ARB_debug_output
+// callback) but windows.h assumes no one will define APIENTRY before it does
+#undef APIENTRY
+
+// GLFW on Windows is Unicode only and does not work in MBCS mode
+#ifndef UNICODE
+ #define UNICODE
+#endif
+
+// GLFW requires Windows XP or later
+#if WINVER < 0x0501
+ #undef WINVER
+ #define WINVER 0x0501
+#endif
+#if _WIN32_WINNT < 0x0501
+ #undef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0501
+#endif
+
+// GLFW uses DirectInput8 interfaces
+#define DIRECTINPUT_VERSION 0x0800
+
+#include <wctype.h>
+#include <windows.h>
+#include <dinput.h>
+#include <xinput.h>
+#include <dbt.h>
+
+// HACK: Define macros that some windows.h variants don't
+#ifndef WM_MOUSEHWHEEL
+ #define WM_MOUSEHWHEEL 0x020E
+#endif
+#ifndef WM_DWMCOMPOSITIONCHANGED
+ #define WM_DWMCOMPOSITIONCHANGED 0x031E
+#endif
+#ifndef WM_COPYGLOBALDATA
+ #define WM_COPYGLOBALDATA 0x0049
+#endif
+#ifndef WM_UNICHAR
+ #define WM_UNICHAR 0x0109
+#endif
+#ifndef UNICODE_NOCHAR
+ #define UNICODE_NOCHAR 0xFFFF
+#endif
+#ifndef WM_DPICHANGED
+ #define WM_DPICHANGED 0x02E0
+#endif
+#ifndef GET_XBUTTON_WPARAM
+ #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
+#endif
+#ifndef EDS_ROTATEDMODE
+ #define EDS_ROTATEDMODE 0x00000004
+#endif
+#ifndef DISPLAY_DEVICE_ACTIVE
+ #define DISPLAY_DEVICE_ACTIVE 0x00000001
+#endif
+#ifndef _WIN32_WINNT_WINBLUE
+ #define _WIN32_WINNT_WINBLUE 0x0602
+#endif
+#ifndef WM_GETDPISCALEDSIZE
+ #define WM_GETDPISCALEDSIZE 0x02e4
+#endif
+#ifndef USER_DEFAULT_SCREEN_DPI
+ #define USER_DEFAULT_SCREEN_DPI 96
+#endif
+
+#if WINVER < 0x0601
+typedef struct
+{
+ DWORD cbSize;
+ DWORD ExtStatus;
+} CHANGEFILTERSTRUCT;
+#ifndef MSGFLT_ALLOW
+ #define MSGFLT_ALLOW 1
+#endif
+#endif /*Windows 7*/
+
+#if WINVER < 0x0600
+#define DWM_BB_ENABLE 0x00000001
+#define DWM_BB_BLURREGION 0x00000002
+typedef struct
+{
+ DWORD dwFlags;
+ BOOL fEnable;
+ HRGN hRgnBlur;
+ BOOL fTransitionOnMaximized;
+} DWM_BLURBEHIND;
+#else
+ #include <dwmapi.h>
+#endif /*Windows Vista*/
+
+#ifndef DPI_ENUMS_DECLARED
+typedef enum
+{
+ PROCESS_DPI_UNAWARE = 0,
+ PROCESS_SYSTEM_DPI_AWARE = 1,
+ PROCESS_PER_MONITOR_DPI_AWARE = 2
+} PROCESS_DPI_AWARENESS;
+typedef enum
+{
+ MDT_EFFECTIVE_DPI = 0,
+ MDT_ANGULAR_DPI = 1,
+ MDT_RAW_DPI = 2,
+ MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+#endif /*DPI_ENUMS_DECLARED*/
+
+#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
+#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
+
+// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
+#define IsWindowsXPOrGreater() \
+ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
+ LOBYTE(_WIN32_WINNT_WINXP), 0)
+#define IsWindowsVistaOrGreater() \
+ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
+ LOBYTE(_WIN32_WINNT_VISTA), 0)
+#define IsWindows7OrGreater() \
+ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
+ LOBYTE(_WIN32_WINNT_WIN7), 0)
+#define IsWindows8OrGreater() \
+ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
+ LOBYTE(_WIN32_WINNT_WIN8), 0)
+#define IsWindows8Point1OrGreater() \
+ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
+ LOBYTE(_WIN32_WINNT_WINBLUE), 0)
+
+#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
+ _glfwIsWindows10BuildOrGreaterWin32(14393)
+#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
+ _glfwIsWindows10BuildOrGreaterWin32(15063)
+
+// HACK: Define macros that some xinput.h variants don't
+#ifndef XINPUT_CAPS_WIRELESS
+ #define XINPUT_CAPS_WIRELESS 0x0002
+#endif
+#ifndef XINPUT_DEVSUBTYPE_WHEEL
+ #define XINPUT_DEVSUBTYPE_WHEEL 0x02
+#endif
+#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
+ #define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
+#endif
+#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
+ #define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
+#endif
+#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
+ #define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
+#endif
+#ifndef XINPUT_DEVSUBTYPE_GUITAR
+ #define XINPUT_DEVSUBTYPE_GUITAR 0x06
+#endif
+#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
+ #define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
+#endif
+#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
+ #define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
+#endif
+#ifndef XUSER_MAX_COUNT
+ #define XUSER_MAX_COUNT 4
+#endif
+
+// HACK: Define macros that some dinput.h variants don't
+#ifndef DIDFT_OPTIONAL
+ #define DIDFT_OPTIONAL 0x80000000
+#endif
+
+// winmm.dll function pointer typedefs
+typedef DWORD (WINAPI * PFN_timeGetTime)(void);
+#define timeGetTime _glfw.win32.winmm.GetTime
+
+// xinput.dll function pointer typedefs
+typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
+typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
+#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
+#define XInputGetState _glfw.win32.xinput.GetState
+
+// dinput8.dll function pointer typedefs
+typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
+#define DirectInput8Create _glfw.win32.dinput8.Create
+
+// user32.dll function pointer typedefs
+typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
+typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
+typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
+typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
+typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
+typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
+#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
+#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
+#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
+#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
+#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
+#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
+
+// dwmapi.dll function pointer typedefs
+typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
+typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
+typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
+#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
+#define DwmFlush _glfw.win32.dwmapi.Flush
+#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
+
+// shcore.dll function pointer typedefs
+typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
+typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
+#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
+#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
+
+// ntdll.dll function pointer typedefs
+typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
+#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
+
+typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
+
+typedef struct VkWin32SurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkWin32SurfaceCreateFlagsKHR flags;
+ HINSTANCE hinstance;
+ HWND hwnd;
+} VkWin32SurfaceCreateInfoKHR;
+
+typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
+
+#include "win32_joystick.h"
+#include "wgl_context.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+
+#if !defined(_GLFW_WNDCLASSNAME)
+ #define _GLFW_WNDCLASSNAME L"GLFW30"
+#endif
+
+#define _glfw_dlopen(name) LoadLibraryA(name)
+#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
+#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
+#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
+#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
+#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
+#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
+
+
+// Win32-specific per-window data
+//
+typedef struct _GLFWwindowWin32
+{
+ HWND handle;
+ HICON bigIcon;
+ HICON smallIcon;
+
+ GLFWbool cursorTracked;
+ GLFWbool frameAction;
+ GLFWbool iconified;
+ GLFWbool maximized;
+ // Whether to enable framebuffer transparency on DWM
+ GLFWbool transparent;
+ GLFWbool scaleToMonitor;
+
+ // The last received cursor position, regardless of source
+ int lastCursorPosX, lastCursorPosY;
+
+} _GLFWwindowWin32;
+
+// Win32-specific global data
+//
+typedef struct _GLFWlibraryWin32
+{
+ HWND helperWindowHandle;
+ HDEVNOTIFY deviceNotificationHandle;
+ DWORD foregroundLockTimeout;
+ int acquiredMonitorCount;
+ char* clipboardString;
+ short int keycodes[512];
+ short int scancodes[GLFW_KEY_LAST + 1];
+ char keynames[GLFW_KEY_LAST + 1][5];
+ // Where to place the cursor when re-enabled
+ double restoreCursorPosX, restoreCursorPosY;
+ // The window whose disabled cursor mode is active
+ _GLFWwindow* disabledCursorWindow;
+ RAWINPUT* rawInput;
+ int rawInputSize;
+ UINT mouseTrailSize;
+
+ struct {
+ HINSTANCE instance;
+ PFN_timeGetTime GetTime;
+ } winmm;
+
+ struct {
+ HINSTANCE instance;
+ PFN_DirectInput8Create Create;
+ IDirectInput8W* api;
+ } dinput8;
+
+ struct {
+ HINSTANCE instance;
+ PFN_XInputGetCapabilities GetCapabilities;
+ PFN_XInputGetState GetState;
+ } xinput;
+
+ struct {
+ HINSTANCE instance;
+ PFN_SetProcessDPIAware SetProcessDPIAware_;
+ PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
+ PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
+ PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
+ PFN_GetDpiForWindow GetDpiForWindow_;
+ PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
+ } user32;
+
+ struct {
+ HINSTANCE instance;
+ PFN_DwmIsCompositionEnabled IsCompositionEnabled;
+ PFN_DwmFlush Flush;
+ PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
+ } dwmapi;
+
+ struct {
+ HINSTANCE instance;
+ PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
+ PFN_GetDpiForMonitor GetDpiForMonitor_;
+ } shcore;
+
+ struct {
+ HINSTANCE instance;
+ PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
+ } ntdll;
+
+} _GLFWlibraryWin32;
+
+// Win32-specific per-monitor data
+//
+typedef struct _GLFWmonitorWin32
+{
+ HMONITOR handle;
+ // This size matches the static size of DISPLAY_DEVICE.DeviceName
+ WCHAR adapterName[32];
+ WCHAR displayName[32];
+ char publicAdapterName[32];
+ char publicDisplayName[32];
+ GLFWbool modesPruned;
+ GLFWbool modeChanged;
+
+} _GLFWmonitorWin32;
+
+// Win32-specific per-cursor data
+//
+typedef struct _GLFWcursorWin32
+{
+ HCURSOR handle;
+
+} _GLFWcursorWin32;
+
+// Win32-specific global timer data
+//
+typedef struct _GLFWtimerWin32
+{
+ GLFWbool hasPC;
+ uint64_t frequency;
+
+} _GLFWtimerWin32;
+
+// Win32-specific thread local storage data
+//
+typedef struct _GLFWtlsWin32
+{
+ GLFWbool allocated;
+ DWORD index;
+
+} _GLFWtlsWin32;
+
+// Win32-specific mutex data
+//
+typedef struct _GLFWmutexWin32
+{
+ GLFWbool allocated;
+ CRITICAL_SECTION section;
+
+} _GLFWmutexWin32;
+
+
+GLFWbool _glfwRegisterWindowClassWin32(void);
+void _glfwUnregisterWindowClassWin32(void);
+
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
+BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
+BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
+void _glfwInputErrorWin32(int error, const char* description);
+void _glfwUpdateKeyNamesWin32(void);
+
+void _glfwInitTimerWin32(void);
+
+void _glfwPollMonitorsWin32(void);
+void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
+void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_thread.c b/Client/ThirdParty/Box2D/extern/glfw/src/win32_thread.c
new file mode 100644
index 0000000..98231c1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_thread.c
@@ -0,0 +1,97 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
+{
+ assert(tls->win32.allocated == GLFW_FALSE);
+
+ tls->win32.index = TlsAlloc();
+ if (tls->win32.index == TLS_OUT_OF_INDEXES)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to allocate TLS index");
+ return GLFW_FALSE;
+ }
+
+ tls->win32.allocated = GLFW_TRUE;
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyTls(_GLFWtls* tls)
+{
+ if (tls->win32.allocated)
+ TlsFree(tls->win32.index);
+ memset(tls, 0, sizeof(_GLFWtls));
+}
+
+void* _glfwPlatformGetTls(_GLFWtls* tls)
+{
+ assert(tls->win32.allocated == GLFW_TRUE);
+ return TlsGetValue(tls->win32.index);
+}
+
+void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
+{
+ assert(tls->win32.allocated == GLFW_TRUE);
+ TlsSetValue(tls->win32.index, value);
+}
+
+GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
+{
+ assert(mutex->win32.allocated == GLFW_FALSE);
+ InitializeCriticalSection(&mutex->win32.section);
+ return mutex->win32.allocated = GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
+{
+ if (mutex->win32.allocated)
+ DeleteCriticalSection(&mutex->win32.section);
+ memset(mutex, 0, sizeof(_GLFWmutex));
+}
+
+void _glfwPlatformLockMutex(_GLFWmutex* mutex)
+{
+ assert(mutex->win32.allocated == GLFW_TRUE);
+ EnterCriticalSection(&mutex->win32.section);
+}
+
+void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
+{
+ assert(mutex->win32.allocated == GLFW_TRUE);
+ LeaveCriticalSection(&mutex->win32.section);
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_time.c b/Client/ThirdParty/Box2D/extern/glfw/src/win32_time.c
new file mode 100644
index 0000000..f333cd4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_time.c
@@ -0,0 +1,74 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerWin32(void)
+{
+ uint64_t frequency;
+
+ if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
+ {
+ _glfw.timer.win32.hasPC = GLFW_TRUE;
+ _glfw.timer.win32.frequency = frequency;
+ }
+ else
+ {
+ _glfw.timer.win32.hasPC = GLFW_FALSE;
+ _glfw.timer.win32.frequency = 1000;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+ if (_glfw.timer.win32.hasPC)
+ {
+ uint64_t value;
+ QueryPerformanceCounter((LARGE_INTEGER*) &value);
+ return value;
+ }
+ else
+ return (uint64_t) timeGetTime();
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+ return _glfw.timer.win32.frequency;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/win32_window.c b/Client/ThirdParty/Box2D/extern/glfw/src/win32_window.c
new file mode 100644
index 0000000..a0abca0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/win32_window.c
@@ -0,0 +1,2205 @@
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <windowsx.h>
+#include <shellapi.h>
+
+#define _GLFW_KEY_INVALID -2
+
+// Returns the window style for the specified window
+//
+static DWORD getWindowStyle(const _GLFWwindow* window)
+{
+ DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+ if (window->monitor)
+ style |= WS_POPUP;
+ else
+ {
+ style |= WS_SYSMENU | WS_MINIMIZEBOX;
+
+ if (window->decorated)
+ {
+ style |= WS_CAPTION;
+
+ if (window->resizable)
+ style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
+ }
+ else
+ style |= WS_POPUP;
+ }
+
+ return style;
+}
+
+// Returns the extended window style for the specified window
+//
+static DWORD getWindowExStyle(const _GLFWwindow* window)
+{
+ DWORD style = WS_EX_APPWINDOW;
+
+ if (window->monitor || window->floating)
+ style |= WS_EX_TOPMOST;
+
+ return style;
+}
+
+// Returns the image whose area most closely matches the desired one
+//
+static const GLFWimage* chooseImage(int count, const GLFWimage* images,
+ int width, int height)
+{
+ int i, leastDiff = INT_MAX;
+ const GLFWimage* closest = NULL;
+
+ for (i = 0; i < count; i++)
+ {
+ const int currDiff = abs(images[i].width * images[i].height -
+ width * height);
+ if (currDiff < leastDiff)
+ {
+ closest = images + i;
+ leastDiff = currDiff;
+ }
+ }
+
+ return closest;
+}
+
+// Creates an RGBA icon or cursor
+//
+static HICON createIcon(const GLFWimage* image,
+ int xhot, int yhot, GLFWbool icon)
+{
+ int i;
+ HDC dc;
+ HICON handle;
+ HBITMAP color, mask;
+ BITMAPV5HEADER bi;
+ ICONINFO ii;
+ unsigned char* target = NULL;
+ unsigned char* source = image->pixels;
+
+ ZeroMemory(&bi, sizeof(bi));
+ bi.bV5Size = sizeof(bi);
+ bi.bV5Width = image->width;
+ bi.bV5Height = -image->height;
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ bi.bV5RedMask = 0x00ff0000;
+ bi.bV5GreenMask = 0x0000ff00;
+ bi.bV5BlueMask = 0x000000ff;
+ bi.bV5AlphaMask = 0xff000000;
+
+ dc = GetDC(NULL);
+ color = CreateDIBSection(dc,
+ (BITMAPINFO*) &bi,
+ DIB_RGB_COLORS,
+ (void**) &target,
+ NULL,
+ (DWORD) 0);
+ ReleaseDC(NULL, dc);
+
+ if (!color)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create RGBA bitmap");
+ return NULL;
+ }
+
+ mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
+ if (!mask)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create mask bitmap");
+ DeleteObject(color);
+ return NULL;
+ }
+
+ for (i = 0; i < image->width * image->height; i++)
+ {
+ target[0] = source[2];
+ target[1] = source[1];
+ target[2] = source[0];
+ target[3] = source[3];
+ target += 4;
+ source += 4;
+ }
+
+ ZeroMemory(&ii, sizeof(ii));
+ ii.fIcon = icon;
+ ii.xHotspot = xhot;
+ ii.yHotspot = yhot;
+ ii.hbmMask = mask;
+ ii.hbmColor = color;
+
+ handle = CreateIconIndirect(&ii);
+
+ DeleteObject(color);
+ DeleteObject(mask);
+
+ if (!handle)
+ {
+ if (icon)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create icon");
+ }
+ else
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create cursor");
+ }
+ }
+
+ return handle;
+}
+
+// Translate client window size to full window size according to styles and DPI
+//
+static void getFullWindowSize(DWORD style, DWORD exStyle,
+ int clientWidth, int clientHeight,
+ int* fullWidth, int* fullHeight,
+ UINT dpi)
+{
+ RECT rect = { 0, 0, clientWidth, clientHeight };
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
+ else
+ AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+ *fullWidth = rect.right - rect.left;
+ *fullHeight = rect.bottom - rect.top;
+}
+
+// Enforce the client rect aspect ratio based on which edge is being dragged
+//
+static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
+{
+ int xoff, yoff;
+ UINT dpi = USER_DEFAULT_SCREEN_DPI;
+ const float ratio = (float) window->numer / (float) window->denom;
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ dpi = GetDpiForWindow(window->win32.handle);
+
+ getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
+ 0, 0, &xoff, &yoff, dpi);
+
+ if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
+ edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
+ {
+ area->bottom = area->top + yoff +
+ (int) ((area->right - area->left - xoff) / ratio);
+ }
+ else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
+ {
+ area->top = area->bottom - yoff -
+ (int) ((area->right - area->left - xoff) / ratio);
+ }
+ else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
+ {
+ area->right = area->left + xoff +
+ (int) ((area->bottom - area->top - yoff) * ratio);
+ }
+}
+
+// Centers the cursor over the window client area
+//
+static void centerCursor(_GLFWwindow* window)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ if (window->cursor)
+ SetCursor(window->cursor->win32.handle);
+ else
+ SetCursor(LoadCursorW(NULL, IDC_ARROW));
+ }
+ else
+ SetCursor(NULL);
+}
+
+// Updates the cursor clip rect
+//
+static void updateClipRect(_GLFWwindow* window)
+{
+ if (window)
+ {
+ RECT clipRect;
+ GetClientRect(window->win32.handle, &clipRect);
+ ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
+ ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
+ ClipCursor(&clipRect);
+ }
+ else
+ ClipCursor(NULL);
+}
+
+// Apply disabled cursor mode to a focused window
+//
+static void disableCursor(_GLFWwindow* window)
+{
+ const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
+
+ _glfw.win32.disabledCursorWindow = window;
+ _glfwPlatformGetCursorPos(window,
+ &_glfw.win32.restoreCursorPosX,
+ &_glfw.win32.restoreCursorPosY);
+ updateCursorImage(window);
+ centerCursor(window);
+ updateClipRect(window);
+
+ if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to register raw input device");
+ }
+}
+
+// Exit disabled cursor mode for the specified window
+//
+static void enableCursor(_GLFWwindow* window)
+{
+ const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
+
+ _glfw.win32.disabledCursorWindow = NULL;
+ updateClipRect(NULL);
+ _glfwPlatformSetCursorPos(window,
+ _glfw.win32.restoreCursorPosX,
+ _glfw.win32.restoreCursorPosY);
+ updateCursorImage(window);
+
+ if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to remove raw input device");
+ }
+}
+
+// Returns whether the cursor is in the client area of the specified window
+//
+static GLFWbool cursorInClientArea(_GLFWwindow* window)
+{
+ RECT area;
+ POINT pos;
+
+ if (!GetCursorPos(&pos))
+ return GLFW_FALSE;
+
+ if (WindowFromPoint(pos) != window->win32.handle)
+ return GLFW_FALSE;
+
+ GetClientRect(window->win32.handle, &area);
+ ClientToScreen(window->win32.handle, (POINT*) &area.left);
+ ClientToScreen(window->win32.handle, (POINT*) &area.right);
+
+ return PtInRect(&area, pos);
+}
+
+// Update native window styles to match attributes
+//
+static void updateWindowStyles(const _GLFWwindow* window)
+{
+ RECT rect;
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+ style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
+ style |= getWindowStyle(window);
+
+ GetClientRect(window->win32.handle, &rect);
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, style, FALSE,
+ getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
+
+ ClientToScreen(window->win32.handle, (POINT*) &rect.left);
+ ClientToScreen(window->win32.handle, (POINT*) &rect.right);
+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+ SetWindowPos(window->win32.handle, HWND_TOP,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+// Update window framebuffer transparency
+//
+static void updateFramebufferTransparency(const _GLFWwindow* window)
+{
+ BOOL enabled;
+
+ if (!IsWindowsVistaOrGreater())
+ return;
+
+ if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
+ {
+ HRGN region = CreateRectRgn(0, 0, -1, -1);
+ DWM_BLURBEHIND bb = {0};
+ bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+ bb.hRgnBlur = region;
+ bb.fEnable = TRUE;
+
+ if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
+ {
+ // Decorated windows don't repaint the transparent background
+ // leaving a trail behind animations
+ // HACK: Making the window layered with a transparency color key
+ // seems to fix this. Normally, when specifying
+ // a transparency color key to be used when composing the
+ // layered window, all pixels painted by the window in this
+ // color will be transparent. That doesn't seem to be the
+ // case anymore, at least when used with blur behind window
+ // plus negative region.
+ LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+ exStyle |= WS_EX_LAYERED;
+ SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
+
+ // Using a color key not equal to black to fix the trailing
+ // issue. When set to black, something is making the hit test
+ // not resize with the window frame.
+ SetLayeredWindowAttributes(window->win32.handle,
+ RGB(0, 193, 48), 255, LWA_COLORKEY);
+ }
+
+ DeleteObject(region);
+ }
+ else
+ {
+ LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+ exStyle &= ~WS_EX_LAYERED;
+ SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
+ RedrawWindow(window->win32.handle, NULL, NULL,
+ RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
+ }
+}
+
+// Retrieves and translates modifier keys
+//
+static int getKeyMods(void)
+{
+ int mods = 0;
+
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ mods |= GLFW_MOD_SHIFT;
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ mods |= GLFW_MOD_CONTROL;
+ if (GetKeyState(VK_MENU) & 0x8000)
+ mods |= GLFW_MOD_ALT;
+ if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
+ mods |= GLFW_MOD_SUPER;
+ if (GetKeyState(VK_CAPITAL) & 1)
+ mods |= GLFW_MOD_CAPS_LOCK;
+ if (GetKeyState(VK_NUMLOCK) & 1)
+ mods |= GLFW_MOD_NUM_LOCK;
+
+ return mods;
+}
+
+// Retrieves and translates modifier keys
+//
+static int getAsyncKeyMods(void)
+{
+ int mods = 0;
+
+ if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
+ mods |= GLFW_MOD_SHIFT;
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ mods |= GLFW_MOD_CONTROL;
+ if (GetAsyncKeyState(VK_MENU) & 0x8000)
+ mods |= GLFW_MOD_ALT;
+ if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & 0x8000)
+ mods |= GLFW_MOD_SUPER;
+ if (GetAsyncKeyState(VK_CAPITAL) & 1)
+ mods |= GLFW_MOD_CAPS_LOCK;
+ if (GetAsyncKeyState(VK_NUMLOCK) & 1)
+ mods |= GLFW_MOD_NUM_LOCK;
+
+ return mods;
+}
+
+// Translates a Windows key to the corresponding GLFW key
+//
+static int translateKey(WPARAM wParam, LPARAM lParam)
+{
+ // The Ctrl keys require special handling
+ if (wParam == VK_CONTROL)
+ {
+ MSG next;
+ DWORD time;
+
+ // Right side keys have the extended key bit set
+ if (lParam & 0x01000000)
+ return GLFW_KEY_RIGHT_CONTROL;
+
+ // HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence
+ // We only want the Right Alt message, so if the next message is
+ // Right Alt we ignore this (synthetic) Left Ctrl message
+ time = GetMessageTime();
+
+ if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
+ {
+ if (next.message == WM_KEYDOWN ||
+ next.message == WM_SYSKEYDOWN ||
+ next.message == WM_KEYUP ||
+ next.message == WM_SYSKEYUP)
+ {
+ if (next.wParam == VK_MENU &&
+ (next.lParam & 0x01000000) &&
+ next.time == time)
+ {
+ // Next message is Right Alt down so discard this
+ return _GLFW_KEY_INVALID;
+ }
+ }
+ }
+
+ return GLFW_KEY_LEFT_CONTROL;
+ }
+
+ if (wParam == VK_PROCESSKEY)
+ {
+ // IME notifies that keys have been filtered by setting the virtual
+ // key-code to VK_PROCESSKEY
+ return _GLFW_KEY_INVALID;
+ }
+
+ return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
+}
+
+static void fitToMonitor(_GLFWwindow* window)
+{
+ MONITORINFO mi = { sizeof(mi) };
+ GetMonitorInfo(window->monitor->win32.handle, &mi);
+ SetWindowPos(window->win32.handle, HWND_TOPMOST,
+ mi.rcMonitor.left,
+ mi.rcMonitor.top,
+ mi.rcMonitor.right - mi.rcMonitor.left,
+ mi.rcMonitor.bottom - mi.rcMonitor.top,
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_GLFWwindow* window)
+{
+ if (!_glfw.win32.acquiredMonitorCount)
+ {
+ SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
+
+ // HACK: When mouse trails are enabled the cursor becomes invisible when
+ // the OpenGL ICD switches to page flipping
+ if (IsWindowsXPOrGreater())
+ {
+ SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
+ SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
+ }
+ }
+
+ if (!window->monitor->window)
+ _glfw.win32.acquiredMonitorCount++;
+
+ _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
+ _glfwInputMonitorWindow(window->monitor, window);
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+ if (window->monitor->window != window)
+ return;
+
+ _glfw.win32.acquiredMonitorCount--;
+ if (!_glfw.win32.acquiredMonitorCount)
+ {
+ SetThreadExecutionState(ES_CONTINUOUS);
+
+ // HACK: Restore mouse trail length saved in acquireMonitor
+ if (IsWindowsXPOrGreater())
+ SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
+ }
+
+ _glfwInputMonitorWindow(window->monitor, NULL);
+ _glfwRestoreVideoModeWin32(window->monitor);
+}
+
+// Window callback function (handles window messages)
+//
+static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+{
+ _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
+ if (!window)
+ {
+ // This is the message handling for the hidden helper window
+ // and for a regular window during its initial creation
+
+ switch (uMsg)
+ {
+ case WM_NCCREATE:
+ {
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ EnableNonClientDpiScaling(hWnd);
+
+ break;
+ }
+
+ case WM_DISPLAYCHANGE:
+ _glfwPollMonitorsWin32();
+ break;
+
+ case WM_DEVICECHANGE:
+ {
+ if (wParam == DBT_DEVICEARRIVAL)
+ {
+ DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
+ if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+ _glfwDetectJoystickConnectionWin32();
+ }
+ else if (wParam == DBT_DEVICEREMOVECOMPLETE)
+ {
+ DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
+ if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+ _glfwDetectJoystickDisconnectionWin32();
+ }
+
+ break;
+ }
+ }
+
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+
+ switch (uMsg)
+ {
+ case WM_MOUSEACTIVATE:
+ {
+ // HACK: Postpone cursor disabling when the window was activated by
+ // clicking a caption button
+ if (HIWORD(lParam) == WM_LBUTTONDOWN)
+ {
+ if (LOWORD(lParam) == HTCLOSE ||
+ LOWORD(lParam) == HTMINBUTTON ||
+ LOWORD(lParam) == HTMAXBUTTON)
+ {
+ window->win32.frameAction = GLFW_TRUE;
+ }
+ }
+
+ break;
+ }
+
+ case WM_CAPTURECHANGED:
+ {
+ // HACK: Disable the cursor once the caption button action has been
+ // completed or cancelled
+ if (lParam == 0 && window->win32.frameAction)
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ disableCursor(window);
+
+ window->win32.frameAction = GLFW_FALSE;
+ }
+
+ break;
+ }
+
+ case WM_SETFOCUS:
+ {
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+
+ // HACK: Do not disable cursor while the user is interacting with
+ // a caption button
+ if (window->win32.frameAction)
+ break;
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ disableCursor(window);
+
+ return 0;
+ }
+
+ case WM_KILLFOCUS:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ enableCursor(window);
+
+ if (window->monitor && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+ return 0;
+ }
+
+ case WM_SYSCOMMAND:
+ {
+ switch (wParam & 0xfff0)
+ {
+ case SC_SCREENSAVE:
+ case SC_MONITORPOWER:
+ {
+ if (window->monitor)
+ {
+ // We are running in full screen mode, so disallow
+ // screen saver and screen blanking
+ return 0;
+ }
+ else
+ break;
+ }
+
+ // User trying to access application menu using ALT?
+ case SC_KEYMENU:
+ return 0;
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ _glfwInputWindowCloseRequest(window);
+ return 0;
+ }
+
+ case WM_INPUTLANGCHANGE:
+ {
+ _glfwUpdateKeyNamesWin32();
+ break;
+ }
+
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ case WM_UNICHAR:
+ {
+ const GLFWbool plain = (uMsg != WM_SYSCHAR);
+
+ if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
+ {
+ // WM_UNICHAR is not sent by Windows, but is sent by some
+ // third-party input method engine
+ // Returning TRUE here announces support for this message
+ return TRUE;
+ }
+
+ _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);
+ return 0;
+ }
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ const int key = translateKey(wParam, lParam);
+ const int scancode = (lParam >> 16) & 0x1ff;
+ const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;
+ const int mods = getKeyMods();
+
+ if (key == _GLFW_KEY_INVALID)
+ break;
+
+ if (action == GLFW_RELEASE && wParam == VK_SHIFT)
+ {
+ // HACK: Release both Shift keys on Shift up event, as when both
+ // are pressed the first release does not emit any event
+ // NOTE: The other half of this is in _glfwPlatformPollEvents
+ _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
+ _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
+ }
+ else if (wParam == VK_SNAPSHOT)
+ {
+ // HACK: Key down is not reported for the Print Screen key
+ _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
+ _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
+ }
+ else
+ _glfwInputKey(window, key, scancode, action, mods);
+
+ break;
+ }
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_XBUTTONUP:
+ {
+ int i, button, action;
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
+ button = GLFW_MOUSE_BUTTON_LEFT;
+ else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)
+ button = GLFW_MOUSE_BUTTON_RIGHT;
+ else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
+ button = GLFW_MOUSE_BUTTON_MIDDLE;
+ else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
+ button = GLFW_MOUSE_BUTTON_4;
+ else
+ button = GLFW_MOUSE_BUTTON_5;
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||
+ uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
+ {
+ action = GLFW_PRESS;
+ }
+ else
+ action = GLFW_RELEASE;
+
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
+ {
+ if (window->mouseButtons[i] == GLFW_PRESS)
+ break;
+ }
+
+ if (i > GLFW_MOUSE_BUTTON_LAST)
+ SetCapture(hWnd);
+
+ _glfwInputMouseClick(window, button, action, getKeyMods());
+
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
+ {
+ if (window->mouseButtons[i] == GLFW_PRESS)
+ break;
+ }
+
+ if (i > GLFW_MOUSE_BUTTON_LAST)
+ ReleaseCapture();
+
+ if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
+ return TRUE;
+
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ const int x = GET_X_LPARAM(lParam);
+ const int y = GET_Y_LPARAM(lParam);
+
+ // Disabled cursor motion input is provided by WM_INPUT
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ break;
+
+ _glfwInputCursorPos(window, x, y);
+
+ window->win32.lastCursorPosX = x;
+ window->win32.lastCursorPosY = y;
+
+ if (!window->win32.cursorTracked)
+ {
+ TRACKMOUSEEVENT tme;
+ ZeroMemory(&tme, sizeof(tme));
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = window->win32.handle;
+ TrackMouseEvent(&tme);
+
+ window->win32.cursorTracked = GLFW_TRUE;
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+ }
+
+ return 0;
+ }
+
+ case WM_INPUT:
+ {
+ UINT size;
+ HRAWINPUT ri = (HRAWINPUT) lParam;
+ RAWINPUT* data;
+ int dx, dy;
+
+ // Only process input when disabled cursor mode is applied
+ if (_glfw.win32.disabledCursorWindow != window)
+ break;
+
+ GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
+ if (size > (UINT) _glfw.win32.rawInputSize)
+ {
+ free(_glfw.win32.rawInput);
+ _glfw.win32.rawInput = calloc(size, 1);
+ _glfw.win32.rawInputSize = size;
+ }
+
+ size = _glfw.win32.rawInputSize;
+ if (GetRawInputData(ri, RID_INPUT,
+ _glfw.win32.rawInput, &size,
+ sizeof(RAWINPUTHEADER)) == (UINT) -1)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to retrieve raw input data");
+ break;
+ }
+
+ data = _glfw.win32.rawInput;
+ if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
+ {
+ dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
+ dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
+ }
+ else
+ {
+ dx = data->data.mouse.lLastX;
+ dy = data->data.mouse.lLastY;
+ }
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + dx,
+ window->virtualCursorPosY + dy);
+
+ window->win32.lastCursorPosX += dx;
+ window->win32.lastCursorPosY += dy;
+ break;
+ }
+
+ case WM_MOUSELEAVE:
+ {
+ window->win32.cursorTracked = GLFW_FALSE;
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+ return 0;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
+ return 0;
+ }
+
+ case WM_MOUSEHWHEEL:
+ {
+ // This message is only sent on Windows Vista and later
+ // NOTE: The X-axis is inverted for consistency with macOS and X11
+ _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
+ return 0;
+ }
+
+ case WM_ENTERSIZEMOVE:
+ case WM_ENTERMENULOOP:
+ {
+ // HACK: Enable the cursor while the user is moving or
+ // resizing the window or using the window menu
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ enableCursor(window);
+
+ break;
+ }
+
+ case WM_EXITSIZEMOVE:
+ case WM_EXITMENULOOP:
+ {
+ // HACK: Disable the cursor once the user is done moving or
+ // resizing the window or using the menu
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ disableCursor(window);
+
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ const GLFWbool iconified = wParam == SIZE_MINIMIZED;
+ const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
+ (window->win32.maximized &&
+ wParam != SIZE_RESTORED);
+
+ if (_glfw.win32.disabledCursorWindow == window)
+ updateClipRect(window);
+
+ if (window->win32.iconified != iconified)
+ _glfwInputWindowIconify(window, iconified);
+
+ if (window->win32.maximized != maximized)
+ _glfwInputWindowMaximize(window, maximized);
+
+ _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
+ _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
+
+ if (window->monitor && window->win32.iconified != iconified)
+ {
+ if (iconified)
+ releaseMonitor(window);
+ else
+ {
+ acquireMonitor(window);
+ fitToMonitor(window);
+ }
+ }
+
+ window->win32.iconified = iconified;
+ window->win32.maximized = maximized;
+ return 0;
+ }
+
+ case WM_MOVE:
+ {
+ if (_glfw.win32.disabledCursorWindow == window)
+ updateClipRect(window);
+
+ // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
+ // those macros do not handle negative window positions correctly
+ _glfwInputWindowPos(window,
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam));
+ return 0;
+ }
+
+ case WM_SIZING:
+ {
+ if (window->numer == GLFW_DONT_CARE ||
+ window->denom == GLFW_DONT_CARE)
+ {
+ break;
+ }
+
+ applyAspectRatio(window, (int) wParam, (RECT*) lParam);
+ return TRUE;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ int xoff, yoff;
+ UINT dpi = USER_DEFAULT_SCREEN_DPI;
+ MINMAXINFO* mmi = (MINMAXINFO*) lParam;
+
+ if (window->monitor)
+ break;
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ dpi = GetDpiForWindow(window->win32.handle);
+
+ getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
+ 0, 0, &xoff, &yoff, dpi);
+
+ if (window->minwidth != GLFW_DONT_CARE &&
+ window->minheight != GLFW_DONT_CARE)
+ {
+ mmi->ptMinTrackSize.x = window->minwidth + xoff;
+ mmi->ptMinTrackSize.y = window->minheight + yoff;
+ }
+
+ if (window->maxwidth != GLFW_DONT_CARE &&
+ window->maxheight != GLFW_DONT_CARE)
+ {
+ mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
+ mmi->ptMaxTrackSize.y = window->maxheight + yoff;
+ }
+
+ if (!window->decorated)
+ {
+ MONITORINFO mi;
+ const HMONITOR mh = MonitorFromWindow(window->win32.handle,
+ MONITOR_DEFAULTTONEAREST);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ GetMonitorInfo(mh, &mi);
+
+ mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
+ mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
+ mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
+ mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
+ }
+
+ return 0;
+ }
+
+ case WM_PAINT:
+ {
+ _glfwInputWindowDamage(window);
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ return TRUE;
+ }
+
+ case WM_NCACTIVATE:
+ case WM_NCPAINT:
+ {
+ // Prevent title bar from being drawn after restoring a minimized
+ // undecorated window
+ if (!window->decorated)
+ return TRUE;
+
+ break;
+ }
+
+ case WM_DWMCOMPOSITIONCHANGED:
+ {
+ if (window->win32.transparent)
+ updateFramebufferTransparency(window);
+ return 0;
+ }
+
+ case WM_GETDPISCALEDSIZE:
+ {
+ if (window->win32.scaleToMonitor)
+ break;
+
+ // Adjust the window size to keep the client area size constant
+ if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
+ {
+ RECT source = {0}, target = {0};
+ SIZE* size = (SIZE*) lParam;
+
+ AdjustWindowRectExForDpi(&source, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ AdjustWindowRectExForDpi(&target, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ LOWORD(wParam));
+
+ size->cx += (target.right - target.left) -
+ (source.right - source.left);
+ size->cy += (target.bottom - target.top) -
+ (source.bottom - source.top);
+ return TRUE;
+ }
+
+ break;
+ }
+
+ case WM_DPICHANGED:
+ {
+ const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
+ const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
+
+ // Only apply the suggested size if the OS is new enough to have
+ // sent a WM_GETDPISCALEDSIZE before this
+ if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
+ {
+ RECT* suggested = (RECT*) lParam;
+ SetWindowPos(window->win32.handle, HWND_TOP,
+ suggested->left,
+ suggested->top,
+ suggested->right - suggested->left,
+ suggested->bottom - suggested->top,
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ _glfwInputWindowContentScale(window, xscale, yscale);
+ break;
+ }
+
+ case WM_SETCURSOR:
+ {
+ if (LOWORD(lParam) == HTCLIENT)
+ {
+ updateCursorImage(window);
+ return TRUE;
+ }
+
+ break;
+ }
+
+ case WM_DROPFILES:
+ {
+ HDROP drop = (HDROP) wParam;
+ POINT pt;
+ int i;
+
+ const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
+ char** paths = calloc(count, sizeof(char*));
+
+ // Move the mouse to the position of the drop
+ DragQueryPoint(drop, &pt);
+ _glfwInputCursorPos(window, pt.x, pt.y);
+
+ for (i = 0; i < count; i++)
+ {
+ const UINT length = DragQueryFileW(drop, i, NULL, 0);
+ WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
+
+ DragQueryFileW(drop, i, buffer, length + 1);
+ paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
+
+ free(buffer);
+ }
+
+ _glfwInputDrop(window, count, (const char**) paths);
+
+ for (i = 0; i < count; i++)
+ free(paths[i]);
+ free(paths);
+
+ DragFinish(drop);
+ return 0;
+ }
+ }
+
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+}
+
+// Creates the GLFW window
+//
+static int createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ int xpos, ypos, fullWidth, fullHeight;
+ WCHAR* wideTitle;
+ DWORD style = getWindowStyle(window);
+ DWORD exStyle = getWindowExStyle(window);
+
+ if (window->monitor)
+ {
+ GLFWvidmode mode;
+
+ // NOTE: This window placement is temporary and approximate, as the
+ // correct position and size cannot be known until the monitor
+ // video mode has been picked in _glfwSetVideoModeWin32
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+ fullWidth = mode.width;
+ fullHeight = mode.height;
+ }
+ else
+ {
+ xpos = CW_USEDEFAULT;
+ ypos = CW_USEDEFAULT;
+
+ if (wndconfig->maximized)
+ style |= WS_MAXIMIZE;
+
+ getFullWindowSize(style, exStyle,
+ wndconfig->width, wndconfig->height,
+ &fullWidth, &fullHeight,
+ USER_DEFAULT_SCREEN_DPI);
+ }
+
+ wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
+ if (!wideTitle)
+ return GLFW_FALSE;
+
+ window->win32.handle = CreateWindowExW(exStyle,
+ _GLFW_WNDCLASSNAME,
+ wideTitle,
+ style,
+ xpos, ypos,
+ fullWidth, fullHeight,
+ NULL, // No parent window
+ NULL, // No window menu
+ GetModuleHandleW(NULL),
+ NULL);
+
+ free(wideTitle);
+
+ if (!window->win32.handle)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create window");
+ return GLFW_FALSE;
+ }
+
+ SetPropW(window->win32.handle, L"GLFW", window);
+
+ if (IsWindows7OrGreater())
+ {
+ ChangeWindowMessageFilterEx(window->win32.handle,
+ WM_DROPFILES, MSGFLT_ALLOW, NULL);
+ ChangeWindowMessageFilterEx(window->win32.handle,
+ WM_COPYDATA, MSGFLT_ALLOW, NULL);
+ ChangeWindowMessageFilterEx(window->win32.handle,
+ WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
+ }
+
+ window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
+
+ // Adjust window size to account for DPI scaling of the window frame and
+ // optionally DPI scaling of the client area
+ // This cannot be done until we know what monitor it was placed on
+ if (!window->monitor)
+ {
+ RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
+
+ if (wndconfig->scaleToMonitor)
+ {
+ float xscale, yscale;
+ _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
+ rect.right = (int) (rect.right * xscale);
+ rect.bottom = (int) (rect.bottom * yscale);
+ }
+
+ ClientToScreen(window->win32.handle, (POINT*) &rect.left);
+ ClientToScreen(window->win32.handle, (POINT*) &rect.right);
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+ SetWindowPos(window->win32.handle, NULL,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ DragAcceptFiles(window->win32.handle, TRUE);
+
+ if (fbconfig->transparent)
+ {
+ updateFramebufferTransparency(window);
+ window->win32.transparent = GLFW_TRUE;
+ }
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Registers the GLFW window class
+//
+GLFWbool _glfwRegisterWindowClassWin32(void)
+{
+ WNDCLASSEXW wc;
+
+ ZeroMemory(&wc, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC) windowProc;
+ wc.hInstance = GetModuleHandleW(NULL);
+ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
+ wc.lpszClassName = _GLFW_WNDCLASSNAME;
+
+ // Load user-provided icon if available
+ wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
+ L"GLFW_ICON", IMAGE_ICON,
+ 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ if (!wc.hIcon)
+ {
+ // No user-provided icon found, load default icon
+ wc.hIcon = LoadImageW(NULL,
+ IDI_APPLICATION, IMAGE_ICON,
+ 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ }
+
+ if (!RegisterClassExW(&wc))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to register window class");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Unregisters the GLFW window class
+//
+void _glfwUnregisterWindowClassWin32(void)
+{
+ UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!createNativeWindow(window, wndconfig, fbconfig))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwInitWGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ if (!_glfwInitOSMesa())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->monitor)
+ {
+ _glfwPlatformShowWindow(window);
+ _glfwPlatformFocusWindow(window);
+ acquireMonitor(window);
+ fitToMonitor(window);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (window->monitor)
+ releaseMonitor(window);
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+
+ if (_glfw.win32.disabledCursorWindow == window)
+ _glfw.win32.disabledCursorWindow = NULL;
+
+ if (window->win32.handle)
+ {
+ RemovePropW(window->win32.handle, L"GLFW");
+ DestroyWindow(window->win32.handle);
+ window->win32.handle = NULL;
+ }
+
+ if (window->win32.bigIcon)
+ DestroyIcon(window->win32.bigIcon);
+
+ if (window->win32.smallIcon)
+ DestroyIcon(window->win32.smallIcon);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+ WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
+ if (!wideTitle)
+ return;
+
+ SetWindowTextW(window->win32.handle, wideTitle);
+ free(wideTitle);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ HICON bigIcon = NULL, smallIcon = NULL;
+
+ if (count)
+ {
+ const GLFWimage* bigImage = chooseImage(count, images,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON));
+ const GLFWimage* smallImage = chooseImage(count, images,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON));
+
+ bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);
+ smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);
+ }
+ else
+ {
+ bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON);
+ smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
+ }
+
+ SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
+ SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
+
+ if (window->win32.bigIcon)
+ DestroyIcon(window->win32.bigIcon);
+
+ if (window->win32.smallIcon)
+ DestroyIcon(window->win32.smallIcon);
+
+ if (count)
+ {
+ window->win32.bigIcon = bigIcon;
+ window->win32.smallIcon = smallIcon;
+ }
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ POINT pos = { 0, 0 };
+ ClientToScreen(window->win32.handle, &pos);
+
+ if (xpos)
+ *xpos = pos.x;
+ if (ypos)
+ *ypos = pos.y;
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ RECT rect = { xpos, ypos, xpos, ypos };
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ {
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ }
+
+ SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ RECT area;
+ GetClientRect(window->win32.handle, &area);
+
+ if (width)
+ *width = area.right;
+ if (height)
+ *height = area.bottom;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->monitor)
+ {
+ if (window->monitor->window == window)
+ {
+ acquireMonitor(window);
+ fitToMonitor(window);
+ }
+ }
+ else
+ {
+ RECT rect = { 0, 0, width, height };
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ {
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ }
+
+ SetWindowPos(window->win32.handle, HWND_TOP,
+ 0, 0, rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
+ }
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ RECT area;
+
+ if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&
+ (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))
+ {
+ return;
+ }
+
+ GetWindowRect(window->win32.handle, &area);
+ MoveWindow(window->win32.handle,
+ area.left, area.top,
+ area.right - area.left,
+ area.bottom - area.top, TRUE);
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ RECT area;
+
+ if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
+ return;
+
+ GetWindowRect(window->win32.handle, &area);
+ applyAspectRatio(window, WMSZ_BOTTOMRIGHT, &area);
+ MoveWindow(window->win32.handle,
+ area.left, area.top,
+ area.right - area.left,
+ area.bottom - area.top, TRUE);
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ _glfwPlatformGetWindowSize(window, width, height);
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ RECT rect;
+ int width, height;
+
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ SetRect(&rect, 0, 0, width, height);
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ {
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ }
+
+ if (left)
+ *left = -rect.left;
+ if (top)
+ *top = -rect.top;
+ if (right)
+ *right = rect.right - width;
+ if (bottom)
+ *bottom = rect.bottom - height;
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+ float* xscale, float* yscale)
+{
+ const HANDLE handle = MonitorFromWindow(window->win32.handle,
+ MONITOR_DEFAULTTONEAREST);
+ _glfwGetMonitorContentScaleWin32(handle, xscale, yscale);
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_MINIMIZE);
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_RESTORE);
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_MAXIMIZE);
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_SHOWNA);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_HIDE);
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+ FlashWindow(window->win32.handle, TRUE);
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ BringWindowToTop(window->win32.handle);
+ SetForegroundWindow(window->win32.handle);
+ SetFocus(window->win32.handle);
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (window->monitor == monitor)
+ {
+ if (monitor)
+ {
+ if (monitor->window == window)
+ {
+ acquireMonitor(window);
+ fitToMonitor(window);
+ }
+ }
+ else
+ {
+ RECT rect = { xpos, ypos, xpos + width, ypos + height };
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ {
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ }
+
+ SetWindowPos(window->win32.handle, HWND_TOP,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ return;
+ }
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowMonitor(window, monitor);
+
+ if (monitor)
+ {
+ MONITORINFO mi = { sizeof(mi) };
+ UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
+
+ if (window->decorated)
+ {
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+ style &= ~WS_OVERLAPPEDWINDOW;
+ style |= getWindowStyle(window);
+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+ flags |= SWP_FRAMECHANGED;
+ }
+
+ acquireMonitor(window);
+
+ GetMonitorInfo(window->monitor->win32.handle, &mi);
+ SetWindowPos(window->win32.handle, HWND_TOPMOST,
+ mi.rcMonitor.left,
+ mi.rcMonitor.top,
+ mi.rcMonitor.right - mi.rcMonitor.left,
+ mi.rcMonitor.bottom - mi.rcMonitor.top,
+ flags);
+ }
+ else
+ {
+ HWND after;
+ RECT rect = { xpos, ypos, xpos + width, ypos + height };
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+ UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;
+
+ if (window->decorated)
+ {
+ style &= ~WS_POPUP;
+ style |= getWindowStyle(window);
+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+
+ flags |= SWP_FRAMECHANGED;
+ }
+
+ if (window->floating)
+ after = HWND_TOPMOST;
+ else
+ after = HWND_NOTOPMOST;
+
+ if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+ {
+ AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window),
+ GetDpiForWindow(window->win32.handle));
+ }
+ else
+ {
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ }
+
+ SetWindowPos(window->win32.handle, after,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ flags);
+ }
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return window->win32.handle == GetActiveWindow();
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return IsIconic(window->win32.handle);
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return IsWindowVisible(window->win32.handle);
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return IsZoomed(window->win32.handle);
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+ return cursorInClientArea(window);
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+ BOOL enabled;
+
+ if (!window->win32.transparent)
+ return GLFW_FALSE;
+
+ if (!IsWindowsVistaOrGreater())
+ return GLFW_FALSE;
+
+ return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+ updateWindowStyles(window);
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+ updateWindowStyles(window);
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+ const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
+ SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+ BYTE alpha;
+ DWORD flags;
+
+ if ((GetWindowLongW(window->win32.handle, GWL_EXSTYLE) & WS_EX_LAYERED) &&
+ GetLayeredWindowAttributes(window->win32.handle, NULL, &alpha, &flags))
+ {
+ if (flags & LWA_ALPHA)
+ return alpha / 255.f;
+ }
+
+ return 1.f;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+ if (opacity < 1.f)
+ {
+ const BYTE alpha = (BYTE) (255 * opacity);
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+ style |= WS_EX_LAYERED;
+ SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
+ SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
+ }
+ else
+ {
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+ style &= ~WS_EX_LAYERED;
+ SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
+ }
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ MSG msg;
+ HWND handle;
+ _GLFWwindow* window;
+
+ while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (msg.message == WM_QUIT)
+ {
+ // NOTE: While GLFW does not itself post WM_QUIT, other processes
+ // may post it to this one, for example Task Manager
+ // HACK: Treat WM_QUIT as a close on all windows
+
+ window = _glfw.windowListHead;
+ while (window)
+ {
+ _glfwInputWindowCloseRequest(window);
+ window = window->next;
+ }
+ }
+ else
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ }
+
+ handle = GetActiveWindow();
+ if (handle)
+ {
+ // NOTE: Shift keys on Windows tend to "stick" when both are pressed as
+ // no key up message is generated by the first key release
+ // The other half of this is in the handling of WM_KEYUP
+ // HACK: Query actual key state and synthesize release events as needed
+ window = GetPropW(handle, L"GLFW");
+ if (window)
+ {
+ const GLFWbool lshift = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
+ const GLFWbool rshift = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
+
+ if (!lshift && window->keys[GLFW_KEY_LEFT_SHIFT] == GLFW_PRESS)
+ {
+ const int mods = getAsyncKeyMods();
+ const int scancode = _glfw.win32.scancodes[GLFW_KEY_LEFT_SHIFT];
+ _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
+ }
+ else if (!rshift && window->keys[GLFW_KEY_RIGHT_SHIFT] == GLFW_PRESS)
+ {
+ const int mods = getAsyncKeyMods();
+ const int scancode = _glfw.win32.scancodes[GLFW_KEY_RIGHT_SHIFT];
+ _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);
+ }
+ }
+ }
+
+ window = _glfw.win32.disabledCursorWindow;
+ if (window)
+ {
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+
+ // NOTE: Re-center the cursor only if it has moved since the last call,
+ // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
+ if (window->win32.lastCursorPosX != width / 2 ||
+ window->win32.lastCursorPosY != height / 2)
+ {
+ _glfwPlatformSetCursorPos(window, width / 2, height / 2);
+ }
+ }
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ WaitMessage();
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ POINT pos;
+
+ if (GetCursorPos(&pos))
+ {
+ ScreenToClient(window->win32.handle, &pos);
+
+ if (xpos)
+ *xpos = pos.x;
+ if (ypos)
+ *ypos = pos.y;
+ }
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
+{
+ POINT pos = { (int) xpos, (int) ypos };
+
+ // Store the new position so it can be recognized later
+ window->win32.lastCursorPosX = pos.x;
+ window->win32.lastCursorPosY = pos.y;
+
+ ClientToScreen(window->win32.handle, &pos);
+ SetCursorPos(pos.x, pos.y);
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ if (mode == GLFW_CURSOR_DISABLED)
+ {
+ if (_glfwPlatformWindowFocused(window))
+ disableCursor(window);
+ }
+ else if (_glfw.win32.disabledCursorWindow == window)
+ enableCursor(window);
+ else if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+ return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+ return _glfw.win32.scancodes[key];
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
+ if (!cursor->win32.handle)
+ return GLFW_FALSE;
+
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ LPCWSTR name = NULL;
+
+ if (shape == GLFW_ARROW_CURSOR)
+ name = IDC_ARROW;
+ else if (shape == GLFW_IBEAM_CURSOR)
+ name = IDC_IBEAM;
+ else if (shape == GLFW_CROSSHAIR_CURSOR)
+ name = IDC_CROSS;
+ else if (shape == GLFW_HAND_CURSOR)
+ name = IDC_HAND;
+ else if (shape == GLFW_HRESIZE_CURSOR)
+ name = IDC_SIZEWE;
+ else if (shape == GLFW_VRESIZE_CURSOR)
+ name = IDC_SIZENS;
+ else
+ return GLFW_FALSE;
+
+ cursor->win32.handle = CopyCursor(LoadCursorW(NULL, name));
+ if (!cursor->win32.handle)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create standard cursor");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->win32.handle)
+ DestroyIcon((HICON) cursor->win32.handle);
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+ int characterCount;
+ HANDLE object;
+ WCHAR* buffer;
+
+ characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+ if (!characterCount)
+ return;
+
+ object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
+ if (!object)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to allocate global handle for clipboard");
+ return;
+ }
+
+ buffer = GlobalLock(object);
+ if (!buffer)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to lock global handle");
+ GlobalFree(object);
+ return;
+ }
+
+ MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
+ GlobalUnlock(object);
+
+ if (!OpenClipboard(_glfw.win32.helperWindowHandle))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to open clipboard");
+ GlobalFree(object);
+ return;
+ }
+
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, object);
+ CloseClipboard();
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+ HANDLE object;
+ WCHAR* buffer;
+
+ if (!OpenClipboard(_glfw.win32.helperWindowHandle))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to open clipboard");
+ return NULL;
+ }
+
+ object = GetClipboardData(CF_UNICODETEXT);
+ if (!object)
+ {
+ _glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
+ "Win32: Failed to convert clipboard to string");
+ CloseClipboard();
+ return NULL;
+ }
+
+ buffer = GlobalLock(object);
+ if (!buffer)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to lock global handle");
+ CloseClipboard();
+ return NULL;
+ }
+
+ free(_glfw.win32.clipboardString);
+ _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
+
+ GlobalUnlock(object);
+ CloseClipboard();
+
+ return _glfw.win32.clipboardString;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+ if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
+ return;
+
+ extensions[0] = "VK_KHR_surface";
+ extensions[1] = "VK_KHR_win32_surface";
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
+ vkGetPhysicalDeviceWin32PresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+ if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily);
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ VkResult err;
+ VkWin32SurfaceCreateInfoKHR sci;
+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
+
+ vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
+ if (!vkCreateWin32SurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ sci.hinstance = GetModuleHandle(NULL);
+ sci.hwnd = window->win32.handle;
+
+ err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create Vulkan surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return window->win32.handle;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/window.c b/Client/ThirdParty/Box2D/extern/glfw/src/window.c
new file mode 100644
index 0000000..4e365cb
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/window.c
@@ -0,0 +1,1113 @@
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code that a window has lost or received input focus
+//
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
+{
+ if (window->callbacks.focus)
+ window->callbacks.focus((GLFWwindow*) window, focused);
+
+ if (!focused)
+ {
+ int key, button;
+
+ for (key = 0; key <= GLFW_KEY_LAST; key++)
+ {
+ if (window->keys[key] == GLFW_PRESS)
+ {
+ const int scancode = _glfwPlatformGetKeyScancode(key);
+ _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
+ }
+ }
+
+ for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
+ {
+ if (window->mouseButtons[button] == GLFW_PRESS)
+ _glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
+ }
+ }
+}
+
+// Notifies shared code that a window has moved
+// The position is specified in client-area relative screen coordinates
+//
+void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
+{
+ if (window->callbacks.pos)
+ window->callbacks.pos((GLFWwindow*) window, x, y);
+}
+
+// Notifies shared code that a window has been resized
+// The size is specified in screen coordinates
+//
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->callbacks.size)
+ window->callbacks.size((GLFWwindow*) window, width, height);
+}
+
+// Notifies shared code that a window has been iconified or restored
+//
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
+{
+ if (window->callbacks.iconify)
+ window->callbacks.iconify((GLFWwindow*) window, iconified);
+}
+
+// Notifies shared code that a window has been maximized or restored
+//
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
+{
+ if (window->callbacks.maximize)
+ window->callbacks.maximize((GLFWwindow*) window, maximized);
+}
+
+// Notifies shared code that a window framebuffer has been resized
+// The size is specified in pixels
+//
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->callbacks.fbsize)
+ window->callbacks.fbsize((GLFWwindow*) window, width, height);
+}
+
+// Notifies shared code that a window content scale has changed
+// The scale is specified as the ratio between the current and default DPI
+//
+void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
+{
+ if (window->callbacks.scale)
+ window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
+}
+
+// Notifies shared code that the window contents needs updating
+//
+void _glfwInputWindowDamage(_GLFWwindow* window)
+{
+ if (window->callbacks.refresh)
+ window->callbacks.refresh((GLFWwindow*) window);
+}
+
+// Notifies shared code that the user wishes to close a window
+//
+void _glfwInputWindowCloseRequest(_GLFWwindow* window)
+{
+ window->shouldClose = GLFW_TRUE;
+
+ if (window->callbacks.close)
+ window->callbacks.close((GLFWwindow*) window);
+}
+
+// Notifies shared code that a window has changed its desired monitor
+//
+void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
+{
+ window->monitor = monitor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
+ const char* title,
+ GLFWmonitor* monitor,
+ GLFWwindow* share)
+{
+ _GLFWfbconfig fbconfig;
+ _GLFWctxconfig ctxconfig;
+ _GLFWwndconfig wndconfig;
+ _GLFWwindow* window;
+
+ assert(title != NULL);
+ assert(width >= 0);
+ assert(height >= 0);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (width <= 0 || height <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window size %ix%i",
+ width, height);
+
+ return NULL;
+ }
+
+ fbconfig = _glfw.hints.framebuffer;
+ ctxconfig = _glfw.hints.context;
+ wndconfig = _glfw.hints.window;
+
+ wndconfig.width = width;
+ wndconfig.height = height;
+ wndconfig.title = title;
+ ctxconfig.share = (_GLFWwindow*) share;
+
+ if (!_glfwIsValidContextConfig(&ctxconfig))
+ return NULL;
+
+ window = calloc(1, sizeof(_GLFWwindow));
+ window->next = _glfw.windowListHead;
+ _glfw.windowListHead = window;
+
+ window->videoMode.width = width;
+ window->videoMode.height = height;
+ window->videoMode.redBits = fbconfig.redBits;
+ window->videoMode.greenBits = fbconfig.greenBits;
+ window->videoMode.blueBits = fbconfig.blueBits;
+ window->videoMode.refreshRate = _glfw.hints.refreshRate;
+
+ window->monitor = (_GLFWmonitor*) monitor;
+ window->resizable = wndconfig.resizable;
+ window->decorated = wndconfig.decorated;
+ window->autoIconify = wndconfig.autoIconify;
+ window->floating = wndconfig.floating;
+ window->focusOnShow = wndconfig.focusOnShow;
+ window->cursorMode = GLFW_CURSOR_NORMAL;
+
+ window->minwidth = GLFW_DONT_CARE;
+ window->minheight = GLFW_DONT_CARE;
+ window->maxwidth = GLFW_DONT_CARE;
+ window->maxheight = GLFW_DONT_CARE;
+ window->numer = GLFW_DONT_CARE;
+ window->denom = GLFW_DONT_CARE;
+
+ // Open the actual window and create its context
+ if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
+ {
+ glfwDestroyWindow((GLFWwindow*) window);
+ return NULL;
+ }
+
+ if (ctxconfig.client != GLFW_NO_API)
+ {
+ if (!_glfwRefreshContextAttribs(window, &ctxconfig))
+ {
+ glfwDestroyWindow((GLFWwindow*) window);
+ return NULL;
+ }
+ }
+
+ if (window->monitor)
+ {
+ if (wndconfig.centerCursor)
+ {
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+ }
+ }
+ else
+ {
+ if (wndconfig.visible)
+ {
+ _glfwPlatformShowWindow(window);
+ if (wndconfig.focused)
+ _glfwPlatformFocusWindow(window);
+ }
+ }
+
+ return (GLFWwindow*) window;
+}
+
+void glfwDefaultWindowHints(void)
+{
+ _GLFW_REQUIRE_INIT();
+
+ // The default is OpenGL with minimum version 1.0
+ memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
+ _glfw.hints.context.client = GLFW_OPENGL_API;
+ _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
+ _glfw.hints.context.major = 1;
+ _glfw.hints.context.minor = 0;
+
+ // The default is a focused, visible, resizable window with decorations
+ memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
+ _glfw.hints.window.resizable = GLFW_TRUE;
+ _glfw.hints.window.visible = GLFW_TRUE;
+ _glfw.hints.window.decorated = GLFW_TRUE;
+ _glfw.hints.window.focused = GLFW_TRUE;
+ _glfw.hints.window.autoIconify = GLFW_TRUE;
+ _glfw.hints.window.centerCursor = GLFW_TRUE;
+ _glfw.hints.window.focusOnShow = GLFW_TRUE;
+
+ // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
+ // double buffered
+ memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
+ _glfw.hints.framebuffer.redBits = 8;
+ _glfw.hints.framebuffer.greenBits = 8;
+ _glfw.hints.framebuffer.blueBits = 8;
+ _glfw.hints.framebuffer.alphaBits = 8;
+ _glfw.hints.framebuffer.depthBits = 24;
+ _glfw.hints.framebuffer.stencilBits = 8;
+ _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
+
+ // The default is to select the highest available refresh rate
+ _glfw.hints.refreshRate = GLFW_DONT_CARE;
+
+ // The default is to use full Retina resolution framebuffers
+ _glfw.hints.window.ns.retina = GLFW_TRUE;
+}
+
+GLFWAPI void glfwWindowHint(int hint, int value)
+{
+ _GLFW_REQUIRE_INIT();
+
+ switch (hint)
+ {
+ case GLFW_RED_BITS:
+ _glfw.hints.framebuffer.redBits = value;
+ return;
+ case GLFW_GREEN_BITS:
+ _glfw.hints.framebuffer.greenBits = value;
+ return;
+ case GLFW_BLUE_BITS:
+ _glfw.hints.framebuffer.blueBits = value;
+ return;
+ case GLFW_ALPHA_BITS:
+ _glfw.hints.framebuffer.alphaBits = value;
+ return;
+ case GLFW_DEPTH_BITS:
+ _glfw.hints.framebuffer.depthBits = value;
+ return;
+ case GLFW_STENCIL_BITS:
+ _glfw.hints.framebuffer.stencilBits = value;
+ return;
+ case GLFW_ACCUM_RED_BITS:
+ _glfw.hints.framebuffer.accumRedBits = value;
+ return;
+ case GLFW_ACCUM_GREEN_BITS:
+ _glfw.hints.framebuffer.accumGreenBits = value;
+ return;
+ case GLFW_ACCUM_BLUE_BITS:
+ _glfw.hints.framebuffer.accumBlueBits = value;
+ return;
+ case GLFW_ACCUM_ALPHA_BITS:
+ _glfw.hints.framebuffer.accumAlphaBits = value;
+ return;
+ case GLFW_AUX_BUFFERS:
+ _glfw.hints.framebuffer.auxBuffers = value;
+ return;
+ case GLFW_STEREO:
+ _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_DOUBLEBUFFER:
+ _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_TRANSPARENT_FRAMEBUFFER:
+ _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_SAMPLES:
+ _glfw.hints.framebuffer.samples = value;
+ return;
+ case GLFW_SRGB_CAPABLE:
+ _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_RESIZABLE:
+ _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_DECORATED:
+ _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_FOCUSED:
+ _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_AUTO_ICONIFY:
+ _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_FLOATING:
+ _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_MAXIMIZED:
+ _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_VISIBLE:
+ _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_COCOA_RETINA_FRAMEBUFFER:
+ _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_COCOA_GRAPHICS_SWITCHING:
+ _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_SCALE_TO_MONITOR:
+ _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_CENTER_CURSOR:
+ _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_FOCUS_ON_SHOW:
+ _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_CLIENT_API:
+ _glfw.hints.context.client = value;
+ return;
+ case GLFW_CONTEXT_CREATION_API:
+ _glfw.hints.context.source = value;
+ return;
+ case GLFW_CONTEXT_VERSION_MAJOR:
+ _glfw.hints.context.major = value;
+ return;
+ case GLFW_CONTEXT_VERSION_MINOR:
+ _glfw.hints.context.minor = value;
+ return;
+ case GLFW_CONTEXT_ROBUSTNESS:
+ _glfw.hints.context.robustness = value;
+ return;
+ case GLFW_OPENGL_FORWARD_COMPAT:
+ _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_OPENGL_DEBUG_CONTEXT:
+ _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_CONTEXT_NO_ERROR:
+ _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ case GLFW_OPENGL_PROFILE:
+ _glfw.hints.context.profile = value;
+ return;
+ case GLFW_CONTEXT_RELEASE_BEHAVIOR:
+ _glfw.hints.context.release = value;
+ return;
+ case GLFW_REFRESH_RATE:
+ _glfw.hints.refreshRate = value;
+ return;
+ }
+
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
+}
+
+GLFWAPI void glfwWindowHintString(int hint, const char* value)
+{
+ assert(value != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ switch (hint)
+ {
+ case GLFW_COCOA_FRAME_NAME:
+ strncpy(_glfw.hints.window.ns.frameName, value,
+ sizeof(_glfw.hints.window.ns.frameName) - 1);
+ return;
+ case GLFW_X11_CLASS_NAME:
+ strncpy(_glfw.hints.window.x11.className, value,
+ sizeof(_glfw.hints.window.x11.className) - 1);
+ return;
+ case GLFW_X11_INSTANCE_NAME:
+ strncpy(_glfw.hints.window.x11.instanceName, value,
+ sizeof(_glfw.hints.window.x11.instanceName) - 1);
+ return;
+ }
+
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
+}
+
+GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+
+ _GLFW_REQUIRE_INIT();
+
+ // Allow closing of NULL (to match the behavior of free)
+ if (window == NULL)
+ return;
+
+ // Clear all callbacks to avoid exposing a half torn-down window object
+ memset(&window->callbacks, 0, sizeof(window->callbacks));
+
+ // The window's context must not be current on another thread when the
+ // window is destroyed
+ if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
+ glfwMakeContextCurrent(NULL);
+
+ _glfwPlatformDestroyWindow(window);
+
+ // Unlink window from global linked list
+ {
+ _GLFWwindow** prev = &_glfw.windowListHead;
+
+ while (*prev != window)
+ prev = &((*prev)->next);
+
+ *prev = window->next;
+ }
+
+ free(window);
+}
+
+GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+ return window->shouldClose;
+}
+
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ window->shouldClose = value;
+}
+
+GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(title != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformSetWindowTitle(window, title);
+}
+
+GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
+ int count, const GLFWimage* images)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(count >= 0);
+ assert(count == 0 || images != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformSetWindowIcon(window, count, images);
+}
+
+GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ if (xpos)
+ *xpos = 0;
+ if (ypos)
+ *ypos = 0;
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformGetWindowPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->monitor)
+ return;
+
+ _glfwPlatformSetWindowPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformGetWindowSize(window, width, height);
+}
+
+GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(width >= 0);
+ assert(height >= 0);
+
+ _GLFW_REQUIRE_INIT();
+
+ window->videoMode.width = width;
+ window->videoMode.height = height;
+
+ _glfwPlatformSetWindowSize(window, width, height);
+}
+
+GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE)
+ {
+ if (minwidth < 0 || minheight < 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window minimum size %ix%i",
+ minwidth, minheight);
+ return;
+ }
+ }
+
+ if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE)
+ {
+ if (maxwidth < 0 || maxheight < 0 ||
+ maxwidth < minwidth || maxheight < minheight)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window maximum size %ix%i",
+ maxwidth, maxheight);
+ return;
+ }
+ }
+
+ window->minwidth = minwidth;
+ window->minheight = minheight;
+ window->maxwidth = maxwidth;
+ window->maxheight = maxheight;
+
+ if (window->monitor || !window->resizable)
+ return;
+
+ _glfwPlatformSetWindowSizeLimits(window,
+ minwidth, minheight,
+ maxwidth, maxheight);
+}
+
+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(numer != 0);
+ assert(denom != 0);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
+ {
+ if (numer <= 0 || denom <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window aspect ratio %i:%i",
+ numer, denom);
+ return;
+ }
+ }
+
+ window->numer = numer;
+ window->denom = denom;
+
+ if (window->monitor || !window->resizable)
+ return;
+
+ _glfwPlatformSetWindowAspectRatio(window, numer, denom);
+}
+
+GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformGetFramebufferSize(window, width, height);
+}
+
+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ if (left)
+ *left = 0;
+ if (top)
+ *top = 0;
+ if (right)
+ *right = 0;
+ if (bottom)
+ *bottom = 0;
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
+}
+
+GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
+ float* xscale, float* yscale)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ if (xscale)
+ *xscale = 0.f;
+ if (yscale)
+ *yscale = 0.f;
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformGetWindowContentScale(window, xscale, yscale);
+}
+
+GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(1.f);
+ return _glfwPlatformGetWindowOpacity(window);
+}
+
+GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(opacity == opacity);
+ assert(opacity >= 0.f);
+ assert(opacity <= 1.f);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (opacity != opacity || opacity < 0.f || opacity > 1.f)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
+ return;
+ }
+
+ _glfwPlatformSetWindowOpacity(window, opacity);
+}
+
+GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformIconifyWindow(window);
+}
+
+GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformRestoreWindow(window);
+}
+
+GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->monitor)
+ return;
+
+ _glfwPlatformMaximizeWindow(window);
+}
+
+GLFWAPI void glfwShowWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->monitor)
+ return;
+
+ _glfwPlatformShowWindow(window);
+
+ if (window->focusOnShow)
+ _glfwPlatformFocusWindow(window);
+}
+
+GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ _glfwPlatformRequestWindowAttention(window);
+}
+
+GLFWAPI void glfwHideWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->monitor)
+ return;
+
+ _glfwPlatformHideWindow(window);
+}
+
+GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ _glfwPlatformFocusWindow(window);
+}
+
+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+
+ switch (attrib)
+ {
+ case GLFW_FOCUSED:
+ return _glfwPlatformWindowFocused(window);
+ case GLFW_ICONIFIED:
+ return _glfwPlatformWindowIconified(window);
+ case GLFW_VISIBLE:
+ return _glfwPlatformWindowVisible(window);
+ case GLFW_MAXIMIZED:
+ return _glfwPlatformWindowMaximized(window);
+ case GLFW_HOVERED:
+ return _glfwPlatformWindowHovered(window);
+ case GLFW_FOCUS_ON_SHOW:
+ return window->focusOnShow;
+ case GLFW_TRANSPARENT_FRAMEBUFFER:
+ return _glfwPlatformFramebufferTransparent(window);
+ case GLFW_RESIZABLE:
+ return window->resizable;
+ case GLFW_DECORATED:
+ return window->decorated;
+ case GLFW_FLOATING:
+ return window->floating;
+ case GLFW_AUTO_ICONIFY:
+ return window->autoIconify;
+ case GLFW_CLIENT_API:
+ return window->context.client;
+ case GLFW_CONTEXT_CREATION_API:
+ return window->context.source;
+ case GLFW_CONTEXT_VERSION_MAJOR:
+ return window->context.major;
+ case GLFW_CONTEXT_VERSION_MINOR:
+ return window->context.minor;
+ case GLFW_CONTEXT_REVISION:
+ return window->context.revision;
+ case GLFW_CONTEXT_ROBUSTNESS:
+ return window->context.robustness;
+ case GLFW_OPENGL_FORWARD_COMPAT:
+ return window->context.forward;
+ case GLFW_OPENGL_DEBUG_CONTEXT:
+ return window->context.debug;
+ case GLFW_OPENGL_PROFILE:
+ return window->context.profile;
+ case GLFW_CONTEXT_RELEASE_BEHAVIOR:
+ return window->context.release;
+ case GLFW_CONTEXT_NO_ERROR:
+ return window->context.noerror;
+ }
+
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
+ return 0;
+}
+
+GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ value = value ? GLFW_TRUE : GLFW_FALSE;
+
+ if (attrib == GLFW_AUTO_ICONIFY)
+ window->autoIconify = value;
+ else if (attrib == GLFW_RESIZABLE)
+ {
+ if (window->resizable == value)
+ return;
+
+ window->resizable = value;
+ if (!window->monitor)
+ _glfwPlatformSetWindowResizable(window, value);
+ }
+ else if (attrib == GLFW_DECORATED)
+ {
+ if (window->decorated == value)
+ return;
+
+ window->decorated = value;
+ if (!window->monitor)
+ _glfwPlatformSetWindowDecorated(window, value);
+ }
+ else if (attrib == GLFW_FLOATING)
+ {
+ if (window->floating == value)
+ return;
+
+ window->floating = value;
+ if (!window->monitor)
+ _glfwPlatformSetWindowFloating(window, value);
+ }
+ else if (attrib == GLFW_FOCUS_ON_SHOW)
+ window->focusOnShow = value;
+ else
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
+}
+
+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return (GLFWmonitor*) window->monitor;
+}
+
+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
+ GLFWmonitor* mh,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ _GLFWwindow* window = (_GLFWwindow*) wh;
+ _GLFWmonitor* monitor = (_GLFWmonitor*) mh;
+ assert(window != NULL);
+ assert(width >= 0);
+ assert(height >= 0);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (width <= 0 || height <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window size %ix%i",
+ width, height);
+ return;
+ }
+
+ if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid refresh rate %i",
+ refreshRate);
+ return;
+ }
+
+ window->videoMode.width = width;
+ window->videoMode.height = height;
+ window->videoMode.refreshRate = refreshRate;
+
+ _glfwPlatformSetWindowMonitor(window, monitor,
+ xpos, ypos, width, height,
+ refreshRate);
+}
+
+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ window->userPointer = pointer;
+}
+
+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return window->userPointer;
+}
+
+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
+ GLFWwindowposfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
+ GLFWwindowsizefun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
+ GLFWwindowclosefun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
+ GLFWwindowrefreshfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
+ GLFWwindowfocusfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
+ GLFWwindowiconifyfun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
+ GLFWwindowmaximizefun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
+ GLFWframebuffersizefun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
+ return cbfun;
+}
+
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
+ GLFWwindowcontentscalefun cbfun)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
+ return cbfun;
+}
+
+GLFWAPI void glfwPollEvents(void)
+{
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformPollEvents();
+}
+
+GLFWAPI void glfwWaitEvents(void)
+{
+ _GLFW_REQUIRE_INIT();
+
+ if (!_glfw.windowListHead)
+ return;
+
+ _glfwPlatformWaitEvents();
+}
+
+GLFWAPI void glfwWaitEventsTimeout(double timeout)
+{
+ _GLFW_REQUIRE_INIT();
+ assert(timeout == timeout);
+ assert(timeout >= 0.0);
+ assert(timeout <= DBL_MAX);
+
+ if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
+ return;
+ }
+
+ _glfwPlatformWaitEventsTimeout(timeout);
+}
+
+GLFWAPI void glfwPostEmptyEvent(void)
+{
+ _GLFW_REQUIRE_INIT();
+
+ if (!_glfw.windowListHead)
+ return;
+
+ _glfwPlatformPostEmptyEvent();
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/wl_init.c b/Client/ThirdParty/Box2D/extern/glfw/src/wl_init.c
new file mode 100644
index 0000000..c6b209b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/wl_init.c
@@ -0,0 +1,1318 @@
+//========================================================================
+// GLFW 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+#include <wayland-client.h>
+
+
+static inline int min(int n1, int n2)
+{
+ return n1 < n2 ? n1 : n2;
+}
+
+static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
+ int* which)
+{
+ int focus;
+ _GLFWwindow* window = _glfw.windowListHead;
+ if (!which)
+ which = &focus;
+ while (window)
+ {
+ if (surface == window->wl.decorations.top.surface)
+ {
+ *which = topDecoration;
+ break;
+ }
+ if (surface == window->wl.decorations.left.surface)
+ {
+ *which = leftDecoration;
+ break;
+ }
+ if (surface == window->wl.decorations.right.surface)
+ {
+ *which = rightDecoration;
+ break;
+ }
+ if (surface == window->wl.decorations.bottom.surface)
+ {
+ *which = bottomDecoration;
+ break;
+ }
+ window = window->next;
+ }
+ return window;
+}
+
+static void pointerHandleEnter(void* data,
+ struct wl_pointer* pointer,
+ uint32_t serial,
+ struct wl_surface* surface,
+ wl_fixed_t sx,
+ wl_fixed_t sy)
+{
+ // Happens in the case we just destroyed the surface.
+ if (!surface)
+ return;
+
+ int focus = 0;
+ _GLFWwindow* window = wl_surface_get_user_data(surface);
+ if (!window)
+ {
+ window = findWindowFromDecorationSurface(surface, &focus);
+ if (!window)
+ return;
+ }
+
+ window->wl.decorations.focus = focus;
+ _glfw.wl.serial = serial;
+ _glfw.wl.pointerFocus = window;
+
+ window->wl.hovered = GLFW_TRUE;
+
+ _glfwPlatformSetCursor(window, window->wl.currentCursor);
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+}
+
+static void pointerHandleLeave(void* data,
+ struct wl_pointer* pointer,
+ uint32_t serial,
+ struct wl_surface* surface)
+{
+ _GLFWwindow* window = _glfw.wl.pointerFocus;
+
+ if (!window)
+ return;
+
+ window->wl.hovered = GLFW_FALSE;
+
+ _glfw.wl.serial = serial;
+ _glfw.wl.pointerFocus = NULL;
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+}
+
+static void setCursor(_GLFWwindow* window, const char* name)
+{
+ struct wl_buffer* buffer;
+ struct wl_cursor* cursor;
+ struct wl_cursor_image* image;
+ struct wl_surface* surface = _glfw.wl.cursorSurface;
+ struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
+ int scale = 1;
+
+ if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
+ {
+ // We only support up to scale=2 for now, since libwayland-cursor
+ // requires us to load a different theme for each size.
+ scale = 2;
+ theme = _glfw.wl.cursorThemeHiDPI;
+ }
+
+ cursor = wl_cursor_theme_get_cursor(theme, name);
+ if (!cursor)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Standard cursor not found");
+ return;
+ }
+ // TODO: handle animated cursors too.
+ image = cursor->images[0];
+
+ if (!image)
+ return;
+
+ buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer)
+ return;
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
+ surface,
+ image->hotspot_x / scale,
+ image->hotspot_y / scale);
+ wl_surface_set_buffer_scale(surface, scale);
+ wl_surface_attach(surface, buffer, 0, 0);
+ wl_surface_damage(surface, 0, 0,
+ image->width, image->height);
+ wl_surface_commit(surface);
+}
+
+static void pointerHandleMotion(void* data,
+ struct wl_pointer* pointer,
+ uint32_t time,
+ wl_fixed_t sx,
+ wl_fixed_t sy)
+{
+ _GLFWwindow* window = _glfw.wl.pointerFocus;
+ const char* cursorName;
+
+ if (!window)
+ return;
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ return;
+ else
+ {
+ window->wl.cursorPosX = wl_fixed_to_double(sx);
+ window->wl.cursorPosY = wl_fixed_to_double(sy);
+ }
+
+ switch (window->wl.decorations.focus)
+ {
+ case mainWindow:
+ _glfwInputCursorPos(window,
+ wl_fixed_to_double(sx),
+ wl_fixed_to_double(sy));
+ return;
+ case topDecoration:
+ if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+ cursorName = "n-resize";
+ else
+ cursorName = "left_ptr";
+ break;
+ case leftDecoration:
+ if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+ cursorName = "nw-resize";
+ else
+ cursorName = "w-resize";
+ break;
+ case rightDecoration:
+ if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+ cursorName = "ne-resize";
+ else
+ cursorName = "e-resize";
+ break;
+ case bottomDecoration:
+ if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
+ cursorName = "sw-resize";
+ else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
+ cursorName = "se-resize";
+ else
+ cursorName = "s-resize";
+ break;
+ default:
+ assert(0);
+ }
+ setCursor(window, cursorName);
+}
+
+static void pointerHandleButton(void* data,
+ struct wl_pointer* pointer,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state)
+{
+ _GLFWwindow* window = _glfw.wl.pointerFocus;
+ int glfwButton;
+
+ // Both xdg-shell and wl_shell use the same values.
+ uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
+
+ if (!window)
+ return;
+ if (button == BTN_LEFT)
+ {
+ switch (window->wl.decorations.focus)
+ {
+ case mainWindow:
+ break;
+ case topDecoration:
+ if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+ edges = WL_SHELL_SURFACE_RESIZE_TOP;
+ else
+ {
+ if (window->wl.xdg.toplevel)
+ xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
+ else
+ wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
+ }
+ break;
+ case leftDecoration:
+ if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+ edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
+ else
+ edges = WL_SHELL_SURFACE_RESIZE_LEFT;
+ break;
+ case rightDecoration:
+ if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+ edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
+ else
+ edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
+ break;
+ case bottomDecoration:
+ if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
+ edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
+ else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
+ edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
+ else
+ edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
+ break;
+ default:
+ assert(0);
+ }
+ if (edges != WL_SHELL_SURFACE_RESIZE_NONE)
+ {
+ if (window->wl.xdg.toplevel)
+ xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
+ serial, edges);
+ else
+ wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
+ serial, edges);
+ }
+ }
+ else if (button == BTN_RIGHT)
+ {
+ if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
+ {
+ xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
+ _glfw.wl.seat, serial,
+ window->wl.cursorPosX,
+ window->wl.cursorPosY);
+ return;
+ }
+ }
+
+ // Don’t pass the button to the user if it was related to a decoration.
+ if (window->wl.decorations.focus != mainWindow)
+ return;
+
+ _glfw.wl.serial = serial;
+
+ /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
+ * codes. */
+ glfwButton = button - BTN_LEFT;
+
+ _glfwInputMouseClick(window,
+ glfwButton,
+ state == WL_POINTER_BUTTON_STATE_PRESSED
+ ? GLFW_PRESS
+ : GLFW_RELEASE,
+ _glfw.wl.xkb.modifiers);
+}
+
+static void pointerHandleAxis(void* data,
+ struct wl_pointer* pointer,
+ uint32_t time,
+ uint32_t axis,
+ wl_fixed_t value)
+{
+ _GLFWwindow* window = _glfw.wl.pointerFocus;
+ double x = 0.0, y = 0.0;
+ // Wayland scroll events are in pointer motion coordinate space (think two
+ // finger scroll). The factor 10 is commonly used to convert to "scroll
+ // step means 1.0.
+ const double scrollFactor = 1.0 / 10.0;
+
+ if (!window)
+ return;
+
+ assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
+ axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
+
+ if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
+ x = wl_fixed_to_double(value) * scrollFactor;
+ else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
+ y = wl_fixed_to_double(value) * scrollFactor;
+
+ _glfwInputScroll(window, x, y);
+}
+
+static const struct wl_pointer_listener pointerListener = {
+ pointerHandleEnter,
+ pointerHandleLeave,
+ pointerHandleMotion,
+ pointerHandleButton,
+ pointerHandleAxis,
+};
+
+static void keyboardHandleKeymap(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t format,
+ int fd,
+ uint32_t size)
+{
+ struct xkb_keymap* keymap;
+ struct xkb_state* state;
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ struct xkb_compose_table* composeTable;
+ struct xkb_compose_state* composeState;
+#endif
+
+ char* mapStr;
+ const char* locale;
+
+ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
+ {
+ close(fd);
+ return;
+ }
+
+ mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (mapStr == MAP_FAILED) {
+ close(fd);
+ return;
+ }
+
+ keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
+ mapStr,
+ XKB_KEYMAP_FORMAT_TEXT_V1,
+ 0);
+ munmap(mapStr, size);
+ close(fd);
+
+ if (!keymap)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to compile keymap");
+ return;
+ }
+
+ state = xkb_state_new(keymap);
+ if (!state)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to create XKB state");
+ xkb_keymap_unref(keymap);
+ return;
+ }
+
+ // Look up the preferred locale, falling back to "C" as default.
+ locale = getenv("LC_ALL");
+ if (!locale)
+ locale = getenv("LC_CTYPE");
+ if (!locale)
+ locale = getenv("LANG");
+ if (!locale)
+ locale = "C";
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ composeTable =
+ xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
+ XKB_COMPOSE_COMPILE_NO_FLAGS);
+ if (composeTable)
+ {
+ composeState =
+ xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
+ xkb_compose_table_unref(composeTable);
+ if (composeState)
+ _glfw.wl.xkb.composeState = composeState;
+ else
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to create XKB compose state");
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to create XKB compose table");
+ }
+#endif
+
+ xkb_keymap_unref(_glfw.wl.xkb.keymap);
+ xkb_state_unref(_glfw.wl.xkb.state);
+ _glfw.wl.xkb.keymap = keymap;
+ _glfw.wl.xkb.state = state;
+
+ _glfw.wl.xkb.controlMask =
+ 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
+ _glfw.wl.xkb.altMask =
+ 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
+ _glfw.wl.xkb.shiftMask =
+ 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
+ _glfw.wl.xkb.superMask =
+ 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
+ _glfw.wl.xkb.capsLockMask =
+ 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
+ _glfw.wl.xkb.numLockMask =
+ 1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
+}
+
+static void keyboardHandleEnter(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t serial,
+ struct wl_surface* surface,
+ struct wl_array* keys)
+{
+ // Happens in the case we just destroyed the surface.
+ if (!surface)
+ return;
+
+ _GLFWwindow* window = wl_surface_get_user_data(surface);
+ if (!window)
+ {
+ window = findWindowFromDecorationSurface(surface, NULL);
+ if (!window)
+ return;
+ }
+
+ _glfw.wl.serial = serial;
+ _glfw.wl.keyboardFocus = window;
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+}
+
+static void keyboardHandleLeave(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t serial,
+ struct wl_surface* surface)
+{
+ _GLFWwindow* window = _glfw.wl.keyboardFocus;
+
+ if (!window)
+ return;
+
+ _glfw.wl.serial = serial;
+ _glfw.wl.keyboardFocus = NULL;
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+static int toGLFWKeyCode(uint32_t key)
+{
+ if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
+ return _glfw.wl.keycodes[key];
+
+ return GLFW_KEY_UNKNOWN;
+}
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
+{
+ if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
+ return sym;
+ if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
+ != XKB_COMPOSE_FEED_ACCEPTED)
+ return sym;
+ switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
+ {
+ case XKB_COMPOSE_COMPOSED:
+ return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
+ case XKB_COMPOSE_COMPOSING:
+ case XKB_COMPOSE_CANCELLED:
+ return XKB_KEY_NoSymbol;
+ case XKB_COMPOSE_NOTHING:
+ default:
+ return sym;
+ }
+}
+#endif
+
+static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
+{
+ uint32_t code, numSyms;
+ long cp;
+ const xkb_keysym_t *syms;
+ xkb_keysym_t sym;
+
+ code = key + 8;
+ numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
+
+ if (numSyms == 1)
+ {
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ sym = composeSymbol(syms[0]);
+#else
+ sym = syms[0];
+#endif
+ cp = _glfwKeySym2Unicode(sym);
+ if (cp != -1)
+ {
+ const int mods = _glfw.wl.xkb.modifiers;
+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+ _glfwInputChar(window, cp, mods, plain);
+ }
+ }
+
+ return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
+}
+
+static void keyboardHandleKey(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state)
+{
+ int keyCode;
+ int action;
+ _GLFWwindow* window = _glfw.wl.keyboardFocus;
+ GLFWbool shouldRepeat;
+ struct itimerspec timer = {};
+
+ if (!window)
+ return;
+
+ keyCode = toGLFWKeyCode(key);
+ action = state == WL_KEYBOARD_KEY_STATE_PRESSED
+ ? GLFW_PRESS : GLFW_RELEASE;
+
+ _glfw.wl.serial = serial;
+ _glfwInputKey(window, keyCode, key, action,
+ _glfw.wl.xkb.modifiers);
+
+ if (action == GLFW_PRESS)
+ {
+ shouldRepeat = inputChar(window, key);
+
+ if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
+ {
+ _glfw.wl.keyboardLastKey = keyCode;
+ _glfw.wl.keyboardLastScancode = key;
+ timer.it_interval.tv_sec = _glfw.wl.keyboardRepeatRate / 1000;
+ timer.it_interval.tv_nsec = (_glfw.wl.keyboardRepeatRate % 1000) * 1000000;
+ timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
+ timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
+ }
+ }
+ timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
+}
+
+static void keyboardHandleModifiers(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t serial,
+ uint32_t modsDepressed,
+ uint32_t modsLatched,
+ uint32_t modsLocked,
+ uint32_t group)
+{
+ xkb_mod_mask_t mask;
+ unsigned int modifiers = 0;
+
+ _glfw.wl.serial = serial;
+
+ if (!_glfw.wl.xkb.keymap)
+ return;
+
+ xkb_state_update_mask(_glfw.wl.xkb.state,
+ modsDepressed,
+ modsLatched,
+ modsLocked,
+ 0,
+ 0,
+ group);
+
+ mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
+ XKB_STATE_MODS_DEPRESSED |
+ XKB_STATE_LAYOUT_DEPRESSED |
+ XKB_STATE_MODS_LATCHED |
+ XKB_STATE_LAYOUT_LATCHED);
+ if (mask & _glfw.wl.xkb.controlMask)
+ modifiers |= GLFW_MOD_CONTROL;
+ if (mask & _glfw.wl.xkb.altMask)
+ modifiers |= GLFW_MOD_ALT;
+ if (mask & _glfw.wl.xkb.shiftMask)
+ modifiers |= GLFW_MOD_SHIFT;
+ if (mask & _glfw.wl.xkb.superMask)
+ modifiers |= GLFW_MOD_SUPER;
+ if (mask & _glfw.wl.xkb.capsLockMask)
+ modifiers |= GLFW_MOD_CAPS_LOCK;
+ if (mask & _glfw.wl.xkb.numLockMask)
+ modifiers |= GLFW_MOD_NUM_LOCK;
+ _glfw.wl.xkb.modifiers = modifiers;
+}
+
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+static void keyboardHandleRepeatInfo(void* data,
+ struct wl_keyboard* keyboard,
+ int32_t rate,
+ int32_t delay)
+{
+ if (keyboard != _glfw.wl.keyboard)
+ return;
+
+ _glfw.wl.keyboardRepeatRate = rate;
+ _glfw.wl.keyboardRepeatDelay = delay;
+}
+#endif
+
+static const struct wl_keyboard_listener keyboardListener = {
+ keyboardHandleKeymap,
+ keyboardHandleEnter,
+ keyboardHandleLeave,
+ keyboardHandleKey,
+ keyboardHandleModifiers,
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+ keyboardHandleRepeatInfo,
+#endif
+};
+
+static void seatHandleCapabilities(void* data,
+ struct wl_seat* seat,
+ enum wl_seat_capability caps)
+{
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
+ {
+ _glfw.wl.pointer = wl_seat_get_pointer(seat);
+ wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
+ }
+ else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
+ {
+ wl_pointer_destroy(_glfw.wl.pointer);
+ _glfw.wl.pointer = NULL;
+ }
+
+ if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
+ {
+ _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
+ wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
+ }
+ else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
+ {
+ wl_keyboard_destroy(_glfw.wl.keyboard);
+ _glfw.wl.keyboard = NULL;
+ }
+}
+
+static void seatHandleName(void* data,
+ struct wl_seat* seat,
+ const char* name)
+{
+}
+
+static const struct wl_seat_listener seatListener = {
+ seatHandleCapabilities,
+ seatHandleName,
+};
+
+static void dataOfferHandleOffer(void* data,
+ struct wl_data_offer* dataOffer,
+ const char* mimeType)
+{
+}
+
+static const struct wl_data_offer_listener dataOfferListener = {
+ dataOfferHandleOffer,
+};
+
+static void dataDeviceHandleDataOffer(void* data,
+ struct wl_data_device* dataDevice,
+ struct wl_data_offer* id)
+{
+ if (_glfw.wl.dataOffer)
+ wl_data_offer_destroy(_glfw.wl.dataOffer);
+
+ _glfw.wl.dataOffer = id;
+ wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);
+}
+
+static void dataDeviceHandleEnter(void* data,
+ struct wl_data_device* dataDevice,
+ uint32_t serial,
+ struct wl_surface *surface,
+ wl_fixed_t x,
+ wl_fixed_t y,
+ struct wl_data_offer *id)
+{
+}
+
+static void dataDeviceHandleLeave(void* data,
+ struct wl_data_device* dataDevice)
+{
+}
+
+static void dataDeviceHandleMotion(void* data,
+ struct wl_data_device* dataDevice,
+ uint32_t time,
+ wl_fixed_t x,
+ wl_fixed_t y)
+{
+}
+
+static void dataDeviceHandleDrop(void* data,
+ struct wl_data_device* dataDevice)
+{
+}
+
+static void dataDeviceHandleSelection(void* data,
+ struct wl_data_device* dataDevice,
+ struct wl_data_offer* id)
+{
+}
+
+static const struct wl_data_device_listener dataDeviceListener = {
+ dataDeviceHandleDataOffer,
+ dataDeviceHandleEnter,
+ dataDeviceHandleLeave,
+ dataDeviceHandleMotion,
+ dataDeviceHandleDrop,
+ dataDeviceHandleSelection,
+};
+
+static void wmBaseHandlePing(void* data,
+ struct xdg_wm_base* wmBase,
+ uint32_t serial)
+{
+ xdg_wm_base_pong(wmBase, serial);
+}
+
+static const struct xdg_wm_base_listener wmBaseListener = {
+ wmBaseHandlePing
+};
+
+static void registryHandleGlobal(void* data,
+ struct wl_registry* registry,
+ uint32_t name,
+ const char* interface,
+ uint32_t version)
+{
+ if (strcmp(interface, "wl_compositor") == 0)
+ {
+ _glfw.wl.compositorVersion = min(3, version);
+ _glfw.wl.compositor =
+ wl_registry_bind(registry, name, &wl_compositor_interface,
+ _glfw.wl.compositorVersion);
+ }
+ else if (strcmp(interface, "wl_subcompositor") == 0)
+ {
+ _glfw.wl.subcompositor =
+ wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
+ }
+ else if (strcmp(interface, "wl_shm") == 0)
+ {
+ _glfw.wl.shm =
+ wl_registry_bind(registry, name, &wl_shm_interface, 1);
+ }
+ else if (strcmp(interface, "wl_shell") == 0)
+ {
+ _glfw.wl.shell =
+ wl_registry_bind(registry, name, &wl_shell_interface, 1);
+ }
+ else if (strcmp(interface, "wl_output") == 0)
+ {
+ _glfwAddOutputWayland(name, version);
+ }
+ else if (strcmp(interface, "wl_seat") == 0)
+ {
+ if (!_glfw.wl.seat)
+ {
+ _glfw.wl.seatVersion = min(4, version);
+ _glfw.wl.seat =
+ wl_registry_bind(registry, name, &wl_seat_interface,
+ _glfw.wl.seatVersion);
+ wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
+ }
+ }
+ else if (strcmp(interface, "wl_data_device_manager") == 0)
+ {
+ if (!_glfw.wl.dataDeviceManager)
+ {
+ _glfw.wl.dataDeviceManager =
+ wl_registry_bind(registry, name,
+ &wl_data_device_manager_interface, 1);
+ }
+ }
+ else if (strcmp(interface, "xdg_wm_base") == 0)
+ {
+ _glfw.wl.wmBase =
+ wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
+ xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
+ }
+ else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
+ {
+ _glfw.wl.decorationManager =
+ wl_registry_bind(registry, name,
+ &zxdg_decoration_manager_v1_interface,
+ 1);
+ }
+ else if (strcmp(interface, "wp_viewporter") == 0)
+ {
+ _glfw.wl.viewporter =
+ wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
+ }
+ else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
+ {
+ _glfw.wl.relativePointerManager =
+ wl_registry_bind(registry, name,
+ &zwp_relative_pointer_manager_v1_interface,
+ 1);
+ }
+ else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
+ {
+ _glfw.wl.pointerConstraints =
+ wl_registry_bind(registry, name,
+ &zwp_pointer_constraints_v1_interface,
+ 1);
+ }
+ else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
+ {
+ _glfw.wl.idleInhibitManager =
+ wl_registry_bind(registry, name,
+ &zwp_idle_inhibit_manager_v1_interface,
+ 1);
+ }
+}
+
+static void registryHandleGlobalRemove(void *data,
+ struct wl_registry *registry,
+ uint32_t name)
+{
+ int i;
+ _GLFWmonitor* monitor;
+
+ for (i = 0; i < _glfw.monitorCount; ++i)
+ {
+ monitor = _glfw.monitors[i];
+ if (monitor->wl.name == name)
+ {
+ _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
+ return;
+ }
+ }
+}
+
+
+static const struct wl_registry_listener registryListener = {
+ registryHandleGlobal,
+ registryHandleGlobalRemove
+};
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode;
+
+ memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
+ memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
+
+ _glfw.wl.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.wl.keycodes[KEY_1] = GLFW_KEY_1;
+ _glfw.wl.keycodes[KEY_2] = GLFW_KEY_2;
+ _glfw.wl.keycodes[KEY_3] = GLFW_KEY_3;
+ _glfw.wl.keycodes[KEY_4] = GLFW_KEY_4;
+ _glfw.wl.keycodes[KEY_5] = GLFW_KEY_5;
+ _glfw.wl.keycodes[KEY_6] = GLFW_KEY_6;
+ _glfw.wl.keycodes[KEY_7] = GLFW_KEY_7;
+ _glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
+ _glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
+ _glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
+ _glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
+ _glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
+ _glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
+ _glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
+ _glfw.wl.keycodes[KEY_W] = GLFW_KEY_W;
+ _glfw.wl.keycodes[KEY_E] = GLFW_KEY_E;
+ _glfw.wl.keycodes[KEY_R] = GLFW_KEY_R;
+ _glfw.wl.keycodes[KEY_T] = GLFW_KEY_T;
+ _glfw.wl.keycodes[KEY_Y] = GLFW_KEY_Y;
+ _glfw.wl.keycodes[KEY_U] = GLFW_KEY_U;
+ _glfw.wl.keycodes[KEY_I] = GLFW_KEY_I;
+ _glfw.wl.keycodes[KEY_O] = GLFW_KEY_O;
+ _glfw.wl.keycodes[KEY_P] = GLFW_KEY_P;
+ _glfw.wl.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.wl.keycodes[KEY_A] = GLFW_KEY_A;
+ _glfw.wl.keycodes[KEY_S] = GLFW_KEY_S;
+ _glfw.wl.keycodes[KEY_D] = GLFW_KEY_D;
+ _glfw.wl.keycodes[KEY_F] = GLFW_KEY_F;
+ _glfw.wl.keycodes[KEY_G] = GLFW_KEY_G;
+ _glfw.wl.keycodes[KEY_H] = GLFW_KEY_H;
+ _glfw.wl.keycodes[KEY_J] = GLFW_KEY_J;
+ _glfw.wl.keycodes[KEY_K] = GLFW_KEY_K;
+ _glfw.wl.keycodes[KEY_L] = GLFW_KEY_L;
+ _glfw.wl.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
+ _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
+ _glfw.wl.keycodes[KEY_Z] = GLFW_KEY_Z;
+ _glfw.wl.keycodes[KEY_X] = GLFW_KEY_X;
+ _glfw.wl.keycodes[KEY_C] = GLFW_KEY_C;
+ _glfw.wl.keycodes[KEY_V] = GLFW_KEY_V;
+ _glfw.wl.keycodes[KEY_B] = GLFW_KEY_B;
+ _glfw.wl.keycodes[KEY_N] = GLFW_KEY_N;
+ _glfw.wl.keycodes[KEY_M] = GLFW_KEY_M;
+ _glfw.wl.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
+ _glfw.wl.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
+ _glfw.wl.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
+ _glfw.wl.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
+ _glfw.wl.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
+ _glfw.wl.keycodes[KEY_TAB] = GLFW_KEY_TAB;
+ _glfw.wl.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.wl.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.wl.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.wl.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
+ _glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
+ _glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
+ _glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU;
+ _glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
+ _glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
+ _glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
+ _glfw.wl.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
+ _glfw.wl.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
+ _glfw.wl.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
+ _glfw.wl.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
+ _glfw.wl.keycodes[KEY_HOME] = GLFW_KEY_HOME;
+ _glfw.wl.keycodes[KEY_END] = GLFW_KEY_END;
+ _glfw.wl.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
+ _glfw.wl.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
+ _glfw.wl.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
+ _glfw.wl.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
+ _glfw.wl.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
+ _glfw.wl.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
+ _glfw.wl.keycodes[KEY_UP] = GLFW_KEY_UP;
+ _glfw.wl.keycodes[KEY_F1] = GLFW_KEY_F1;
+ _glfw.wl.keycodes[KEY_F2] = GLFW_KEY_F2;
+ _glfw.wl.keycodes[KEY_F3] = GLFW_KEY_F3;
+ _glfw.wl.keycodes[KEY_F4] = GLFW_KEY_F4;
+ _glfw.wl.keycodes[KEY_F5] = GLFW_KEY_F5;
+ _glfw.wl.keycodes[KEY_F6] = GLFW_KEY_F6;
+ _glfw.wl.keycodes[KEY_F7] = GLFW_KEY_F7;
+ _glfw.wl.keycodes[KEY_F8] = GLFW_KEY_F8;
+ _glfw.wl.keycodes[KEY_F9] = GLFW_KEY_F9;
+ _glfw.wl.keycodes[KEY_F10] = GLFW_KEY_F10;
+ _glfw.wl.keycodes[KEY_F11] = GLFW_KEY_F11;
+ _glfw.wl.keycodes[KEY_F12] = GLFW_KEY_F12;
+ _glfw.wl.keycodes[KEY_F13] = GLFW_KEY_F13;
+ _glfw.wl.keycodes[KEY_F14] = GLFW_KEY_F14;
+ _glfw.wl.keycodes[KEY_F15] = GLFW_KEY_F15;
+ _glfw.wl.keycodes[KEY_F16] = GLFW_KEY_F16;
+ _glfw.wl.keycodes[KEY_F17] = GLFW_KEY_F17;
+ _glfw.wl.keycodes[KEY_F18] = GLFW_KEY_F18;
+ _glfw.wl.keycodes[KEY_F19] = GLFW_KEY_F19;
+ _glfw.wl.keycodes[KEY_F20] = GLFW_KEY_F20;
+ _glfw.wl.keycodes[KEY_F21] = GLFW_KEY_F21;
+ _glfw.wl.keycodes[KEY_F22] = GLFW_KEY_F22;
+ _glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
+ _glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
+ _glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
+ _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
+ _glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
+ _glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
+ _glfw.wl.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
+ _glfw.wl.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
+ _glfw.wl.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
+ _glfw.wl.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
+ _glfw.wl.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
+ _glfw.wl.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
+ _glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
+ _glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
+ _glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
+ _glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
+ _glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
+ _glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
+
+ for (scancode = 0; scancode < 256; scancode++)
+ {
+ if (_glfw.wl.keycodes[scancode] > 0)
+ _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ const char *cursorTheme;
+ const char *cursorSizeStr;
+ char *cursorSizeEnd;
+ long cursorSizeLong;
+ int cursorSize;
+
+ _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
+ if (!_glfw.wl.cursor.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to open libwayland-cursor");
+ return GLFW_FALSE;
+ }
+
+ _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
+ _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
+ _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
+ _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
+ _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
+ _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
+ _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
+ _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
+
+ _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
+ if (!_glfw.wl.egl.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to open libwayland-egl");
+ return GLFW_FALSE;
+ }
+
+ _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
+ _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
+ _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
+ _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
+ _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
+ _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
+
+ _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
+ if (!_glfw.wl.xkb.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to open libxkbcommon");
+ return GLFW_FALSE;
+ }
+
+ _glfw.wl.xkb.context_new = (PFN_xkb_context_new)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
+ _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
+ _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
+ _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
+ _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
+ _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
+ _glfw.wl.xkb.state_new = (PFN_xkb_state_new)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
+ _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
+ _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
+ _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
+ _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
+ _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
+ _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
+ _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
+ _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
+ _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
+ _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
+ _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
+#endif
+
+ _glfw.wl.display = wl_display_connect(NULL);
+ if (!_glfw.wl.display)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to connect to display");
+ return GLFW_FALSE;
+ }
+
+ _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
+ wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
+
+ createKeyTables();
+
+ _glfw.wl.xkb.context = xkb_context_new(0);
+ if (!_glfw.wl.xkb.context)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to initialize xkb context");
+ return GLFW_FALSE;
+ }
+
+ // Sync so we got all registry objects
+ wl_display_roundtrip(_glfw.wl.display);
+
+ // Sync so we got all initial output events
+ wl_display_roundtrip(_glfw.wl.display);
+
+#ifdef __linux__
+ if (!_glfwInitJoysticksLinux())
+ return GLFW_FALSE;
+#endif
+
+ _glfwInitTimerPOSIX();
+
+ _glfw.wl.timerfd = -1;
+ if (_glfw.wl.seatVersion >= 4)
+ _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+
+ if (_glfw.wl.pointer && _glfw.wl.shm)
+ {
+ cursorTheme = getenv("XCURSOR_THEME");
+ cursorSizeStr = getenv("XCURSOR_SIZE");
+ cursorSize = 32;
+ if (cursorSizeStr)
+ {
+ errno = 0;
+ cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
+ if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
+ cursorSize = (int)cursorSizeLong;
+ }
+ _glfw.wl.cursorTheme =
+ wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
+ if (!_glfw.wl.cursorTheme)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unable to load default cursor theme");
+ return GLFW_FALSE;
+ }
+ // If this happens to be NULL, we just fallback to the scale=1 version.
+ _glfw.wl.cursorThemeHiDPI =
+ wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
+ _glfw.wl.cursorSurface =
+ wl_compositor_create_surface(_glfw.wl.compositor);
+ _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+ }
+
+ if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
+ {
+ _glfw.wl.dataDevice =
+ wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
+ _glfw.wl.seat);
+ wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
+ _glfw.wl.clipboardString = malloc(4096);
+ if (!_glfw.wl.clipboardString)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unable to allocate clipboard memory");
+ return GLFW_FALSE;
+ }
+ _glfw.wl.clipboardSize = 4096;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+#ifdef __linux__
+ _glfwTerminateJoysticksLinux();
+#endif
+ _glfwTerminateEGL();
+ if (_glfw.wl.egl.handle)
+ {
+ _glfw_dlclose(_glfw.wl.egl.handle);
+ _glfw.wl.egl.handle = NULL;
+ }
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ if (_glfw.wl.xkb.composeState)
+ xkb_compose_state_unref(_glfw.wl.xkb.composeState);
+#endif
+ if (_glfw.wl.xkb.keymap)
+ xkb_keymap_unref(_glfw.wl.xkb.keymap);
+ if (_glfw.wl.xkb.state)
+ xkb_state_unref(_glfw.wl.xkb.state);
+ if (_glfw.wl.xkb.context)
+ xkb_context_unref(_glfw.wl.xkb.context);
+ if (_glfw.wl.xkb.handle)
+ {
+ _glfw_dlclose(_glfw.wl.xkb.handle);
+ _glfw.wl.xkb.handle = NULL;
+ }
+
+ if (_glfw.wl.cursorTheme)
+ wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
+ if (_glfw.wl.cursorThemeHiDPI)
+ wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
+ if (_glfw.wl.cursor.handle)
+ {
+ _glfw_dlclose(_glfw.wl.cursor.handle);
+ _glfw.wl.cursor.handle = NULL;
+ }
+
+ if (_glfw.wl.cursorSurface)
+ wl_surface_destroy(_glfw.wl.cursorSurface);
+ if (_glfw.wl.subcompositor)
+ wl_subcompositor_destroy(_glfw.wl.subcompositor);
+ if (_glfw.wl.compositor)
+ wl_compositor_destroy(_glfw.wl.compositor);
+ if (_glfw.wl.shm)
+ wl_shm_destroy(_glfw.wl.shm);
+ if (_glfw.wl.shell)
+ wl_shell_destroy(_glfw.wl.shell);
+ if (_glfw.wl.viewporter)
+ wp_viewporter_destroy(_glfw.wl.viewporter);
+ if (_glfw.wl.decorationManager)
+ zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
+ if (_glfw.wl.wmBase)
+ xdg_wm_base_destroy(_glfw.wl.wmBase);
+ if (_glfw.wl.dataSource)
+ wl_data_source_destroy(_glfw.wl.dataSource);
+ if (_glfw.wl.dataDevice)
+ wl_data_device_destroy(_glfw.wl.dataDevice);
+ if (_glfw.wl.dataOffer)
+ wl_data_offer_destroy(_glfw.wl.dataOffer);
+ if (_glfw.wl.dataDeviceManager)
+ wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
+ if (_glfw.wl.pointer)
+ wl_pointer_destroy(_glfw.wl.pointer);
+ if (_glfw.wl.keyboard)
+ wl_keyboard_destroy(_glfw.wl.keyboard);
+ if (_glfw.wl.seat)
+ wl_seat_destroy(_glfw.wl.seat);
+ if (_glfw.wl.relativePointerManager)
+ zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
+ if (_glfw.wl.pointerConstraints)
+ zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
+ if (_glfw.wl.idleInhibitManager)
+ zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
+ if (_glfw.wl.registry)
+ wl_registry_destroy(_glfw.wl.registry);
+ if (_glfw.wl.display)
+ {
+ wl_display_flush(_glfw.wl.display);
+ wl_display_disconnect(_glfw.wl.display);
+ }
+
+ if (_glfw.wl.timerfd >= 0)
+ close(_glfw.wl.timerfd);
+ if (_glfw.wl.cursorTimerfd >= 0)
+ close(_glfw.wl.cursorTimerfd);
+
+ if (_glfw.wl.clipboardString)
+ free(_glfw.wl.clipboardString);
+ if (_glfw.wl.clipboardSendString)
+ free(_glfw.wl.clipboardSendString);
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Wayland EGL"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+ " clock_gettime"
+#else
+ " gettimeofday"
+#endif
+ " evdev"
+#if defined(_GLFW_BUILD_DLL)
+ " shared"
+#endif
+ ;
+}
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/wl_monitor.c b/Client/ThirdParty/Box2D/extern/glfw/src/wl_monitor.c
new file mode 100644
index 0000000..588f8b0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/wl_monitor.c
@@ -0,0 +1,208 @@
+//========================================================================
+// GLFW 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+
+static void outputHandleGeometry(void* data,
+ struct wl_output* output,
+ int32_t x,
+ int32_t y,
+ int32_t physicalWidth,
+ int32_t physicalHeight,
+ int32_t subpixel,
+ const char* make,
+ const char* model,
+ int32_t transform)
+{
+ struct _GLFWmonitor *monitor = data;
+ char name[1024];
+
+ monitor->wl.x = x;
+ monitor->wl.y = y;
+ monitor->widthMM = physicalWidth;
+ monitor->heightMM = physicalHeight;
+
+ snprintf(name, sizeof(name), "%s %s", make, model);
+ monitor->name = _glfw_strdup(name);
+}
+
+static void outputHandleMode(void* data,
+ struct wl_output* output,
+ uint32_t flags,
+ int32_t width,
+ int32_t height,
+ int32_t refresh)
+{
+ struct _GLFWmonitor *monitor = data;
+ GLFWvidmode mode;
+
+ mode.width = width;
+ mode.height = height;
+ mode.redBits = 8;
+ mode.greenBits = 8;
+ mode.blueBits = 8;
+ mode.refreshRate = refresh / 1000;
+
+ monitor->modeCount++;
+ monitor->modes =
+ realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode));
+ monitor->modes[monitor->modeCount - 1] = mode;
+
+ if (flags & WL_OUTPUT_MODE_CURRENT)
+ monitor->wl.currentMode = monitor->modeCount - 1;
+}
+
+static void outputHandleDone(void* data, struct wl_output* output)
+{
+ struct _GLFWmonitor *monitor = data;
+
+ _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
+}
+
+static void outputHandleScale(void* data,
+ struct wl_output* output,
+ int32_t factor)
+{
+ struct _GLFWmonitor *monitor = data;
+
+ monitor->wl.scale = factor;
+}
+
+static const struct wl_output_listener outputListener = {
+ outputHandleGeometry,
+ outputHandleMode,
+ outputHandleDone,
+ outputHandleScale,
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwAddOutputWayland(uint32_t name, uint32_t version)
+{
+ _GLFWmonitor *monitor;
+ struct wl_output *output;
+
+ if (version < 2)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unsupported output interface version");
+ return;
+ }
+
+ // The actual name of this output will be set in the geometry handler.
+ monitor = _glfwAllocMonitor(NULL, 0, 0);
+
+ output = wl_registry_bind(_glfw.wl.registry,
+ name,
+ &wl_output_interface,
+ 2);
+ if (!output)
+ {
+ _glfwFreeMonitor(monitor);
+ return;
+ }
+
+ monitor->wl.scale = 1;
+ monitor->wl.output = output;
+ monitor->wl.name = name;
+
+ wl_output_add_listener(output, &outputListener, monitor);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+ if (monitor->wl.output)
+ wl_output_destroy(monitor->wl.output);
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ if (xpos)
+ *xpos = monitor->wl.x;
+ if (ypos)
+ *ypos = monitor->wl.y;
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+ float* xscale, float* yscale)
+{
+ if (xscale)
+ *xscale = (float) monitor->wl.scale;
+ if (yscale)
+ *yscale = (float) monitor->wl.scale;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+ *found = monitor->modeCount;
+ return monitor->modes;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+ *mode = monitor->modes[monitor->wl.currentMode];
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Gamma ramp access it not available");
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
+ const GLFWgammaramp* ramp)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Gamma ramp access is not available");
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->wl.output;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/wl_platform.h b/Client/ThirdParty/Box2D/extern/glfw/src/wl_platform.h
new file mode 100644
index 0000000..c17ebe8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/wl_platform.h
@@ -0,0 +1,359 @@
+//========================================================================
+// GLFW 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <wayland-client.h>
+#include <xkbcommon/xkbcommon.h>
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+#include <xkbcommon/xkbcommon-compose.h>
+#endif
+#include <dlfcn.h>
+
+typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
+
+typedef struct VkWaylandSurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkWaylandSurfaceCreateFlagsKHR flags;
+ struct wl_display* display;
+ struct wl_surface* surface;
+} VkWaylandSurfaceCreateInfoKHR;
+
+typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
+
+#include "posix_thread.h"
+#include "posix_time.h"
+#ifdef __linux__
+#include "linux_joystick.h"
+#else
+#include "null_joystick.h"
+#endif
+#include "xkb_unicode.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+
+#include "wayland-xdg-shell-client-protocol.h"
+#include "wayland-xdg-decoration-client-protocol.h"
+#include "wayland-viewporter-client-protocol.h"
+#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
+#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
+#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
+
+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+#define _glfw_dlclose(handle) dlclose(handle)
+#define _glfw_dlsym(handle, name) dlsym(handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->wl.native)
+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.wl.display)
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWayland wl
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl
+
+#define _GLFW_PLATFORM_CONTEXT_STATE
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
+
+struct wl_cursor_image {
+ uint32_t width;
+ uint32_t height;
+ uint32_t hotspot_x;
+ uint32_t hotspot_y;
+ uint32_t delay;
+};
+struct wl_cursor {
+ unsigned int image_count;
+ struct wl_cursor_image** images;
+ char* name;
+};
+typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
+typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
+typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
+typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
+#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
+#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
+#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
+#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
+
+typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
+typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
+typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
+#define wl_egl_window_create _glfw.wl.egl.window_create
+#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
+#define wl_egl_window_resize _glfw.wl.egl.window_resize
+
+typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
+typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
+typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
+typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
+typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
+typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
+typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
+typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
+typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
+typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
+typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
+#define xkb_context_new _glfw.wl.xkb.context_new
+#define xkb_context_unref _glfw.wl.xkb.context_unref
+#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
+#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
+#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
+#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
+#define xkb_state_new _glfw.wl.xkb.state_new
+#define xkb_state_unref _glfw.wl.xkb.state_unref
+#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
+#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
+#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
+typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
+typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
+typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
+typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
+typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
+typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
+#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
+#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
+#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
+#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
+#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
+#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
+#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
+#endif
+
+#define _GLFW_DECORATION_WIDTH 4
+#define _GLFW_DECORATION_TOP 24
+#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
+#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
+
+typedef enum _GLFWdecorationSideWayland
+{
+ mainWindow,
+ topDecoration,
+ leftDecoration,
+ rightDecoration,
+ bottomDecoration,
+
+} _GLFWdecorationSideWayland;
+
+typedef struct _GLFWdecorationWayland
+{
+ struct wl_surface* surface;
+ struct wl_subsurface* subsurface;
+ struct wp_viewport* viewport;
+
+} _GLFWdecorationWayland;
+
+// Wayland-specific per-window data
+//
+typedef struct _GLFWwindowWayland
+{
+ int width, height;
+ GLFWbool visible;
+ GLFWbool maximized;
+ GLFWbool hovered;
+ GLFWbool transparent;
+ struct wl_surface* surface;
+ struct wl_egl_window* native;
+ struct wl_shell_surface* shellSurface;
+ struct wl_callback* callback;
+
+ struct {
+ struct xdg_surface* surface;
+ struct xdg_toplevel* toplevel;
+ struct zxdg_toplevel_decoration_v1* decoration;
+ } xdg;
+
+ _GLFWcursor* currentCursor;
+ double cursorPosX, cursorPosY;
+
+ char* title;
+
+ // We need to track the monitors the window spans on to calculate the
+ // optimal scaling factor.
+ int scale;
+ _GLFWmonitor** monitors;
+ int monitorsCount;
+ int monitorsSize;
+
+ struct {
+ struct zwp_relative_pointer_v1* relativePointer;
+ struct zwp_locked_pointer_v1* lockedPointer;
+ } pointerLock;
+
+ struct zwp_idle_inhibitor_v1* idleInhibitor;
+
+ // This is a hack to prevent auto-iconification on creation.
+ GLFWbool justCreated;
+
+ struct {
+ GLFWbool serverSide;
+ struct wl_buffer* buffer;
+ _GLFWdecorationWayland top, left, right, bottom;
+ int focus;
+ } decorations;
+
+} _GLFWwindowWayland;
+
+// Wayland-specific global data
+//
+typedef struct _GLFWlibraryWayland
+{
+ struct wl_display* display;
+ struct wl_registry* registry;
+ struct wl_compositor* compositor;
+ struct wl_subcompositor* subcompositor;
+ struct wl_shell* shell;
+ struct wl_shm* shm;
+ struct wl_seat* seat;
+ struct wl_pointer* pointer;
+ struct wl_keyboard* keyboard;
+ struct wl_data_device_manager* dataDeviceManager;
+ struct wl_data_device* dataDevice;
+ struct wl_data_offer* dataOffer;
+ struct wl_data_source* dataSource;
+ struct xdg_wm_base* wmBase;
+ struct zxdg_decoration_manager_v1* decorationManager;
+ struct wp_viewporter* viewporter;
+ struct zwp_relative_pointer_manager_v1* relativePointerManager;
+ struct zwp_pointer_constraints_v1* pointerConstraints;
+ struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
+
+ int compositorVersion;
+ int seatVersion;
+
+ struct wl_cursor_theme* cursorTheme;
+ struct wl_cursor_theme* cursorThemeHiDPI;
+ struct wl_surface* cursorSurface;
+ int cursorTimerfd;
+ uint32_t serial;
+
+ int32_t keyboardRepeatRate;
+ int32_t keyboardRepeatDelay;
+ int keyboardLastKey;
+ int keyboardLastScancode;
+ char* clipboardString;
+ size_t clipboardSize;
+ char* clipboardSendString;
+ size_t clipboardSendSize;
+ int timerfd;
+ short int keycodes[256];
+ short int scancodes[GLFW_KEY_LAST + 1];
+
+ struct {
+ void* handle;
+ struct xkb_context* context;
+ struct xkb_keymap* keymap;
+ struct xkb_state* state;
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ struct xkb_compose_state* composeState;
+#endif
+
+ xkb_mod_mask_t controlMask;
+ xkb_mod_mask_t altMask;
+ xkb_mod_mask_t shiftMask;
+ xkb_mod_mask_t superMask;
+ xkb_mod_mask_t capsLockMask;
+ xkb_mod_mask_t numLockMask;
+ unsigned int modifiers;
+
+ PFN_xkb_context_new context_new;
+ PFN_xkb_context_unref context_unref;
+ PFN_xkb_keymap_new_from_string keymap_new_from_string;
+ PFN_xkb_keymap_unref keymap_unref;
+ PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
+ PFN_xkb_keymap_key_repeats keymap_key_repeats;
+ PFN_xkb_state_new state_new;
+ PFN_xkb_state_unref state_unref;
+ PFN_xkb_state_key_get_syms state_key_get_syms;
+ PFN_xkb_state_update_mask state_update_mask;
+ PFN_xkb_state_serialize_mods state_serialize_mods;
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+ PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
+ PFN_xkb_compose_table_unref compose_table_unref;
+ PFN_xkb_compose_state_new compose_state_new;
+ PFN_xkb_compose_state_unref compose_state_unref;
+ PFN_xkb_compose_state_feed compose_state_feed;
+ PFN_xkb_compose_state_get_status compose_state_get_status;
+ PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
+#endif
+ } xkb;
+
+ _GLFWwindow* pointerFocus;
+ _GLFWwindow* keyboardFocus;
+
+ struct {
+ void* handle;
+
+ PFN_wl_cursor_theme_load theme_load;
+ PFN_wl_cursor_theme_destroy theme_destroy;
+ PFN_wl_cursor_theme_get_cursor theme_get_cursor;
+ PFN_wl_cursor_image_get_buffer image_get_buffer;
+ } cursor;
+
+ struct {
+ void* handle;
+
+ PFN_wl_egl_window_create window_create;
+ PFN_wl_egl_window_destroy window_destroy;
+ PFN_wl_egl_window_resize window_resize;
+ } egl;
+
+} _GLFWlibraryWayland;
+
+// Wayland-specific per-monitor data
+//
+typedef struct _GLFWmonitorWayland
+{
+ struct wl_output* output;
+ int name;
+ int currentMode;
+
+ int x;
+ int y;
+ int scale;
+
+} _GLFWmonitorWayland;
+
+// Wayland-specific per-cursor data
+//
+typedef struct _GLFWcursorWayland
+{
+ struct wl_cursor* cursor;
+ struct wl_cursor* cursorHiDPI;
+ struct wl_buffer* buffer;
+ int width, height;
+ int xhot, yhot;
+ int currentImage;
+} _GLFWcursorWayland;
+
+
+void _glfwAddOutputWayland(uint32_t name, uint32_t version);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/wl_window.c b/Client/ThirdParty/Box2D/extern/glfw/src/wl_window.c
new file mode 100644
index 0000000..98a6465
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/wl_window.c
@@ -0,0 +1,1857 @@
+//========================================================================
+// GLFW 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#define _GNU_SOURCE
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/timerfd.h>
+#include <poll.h>
+
+
+static void shellSurfaceHandlePing(void* data,
+ struct wl_shell_surface* shellSurface,
+ uint32_t serial)
+{
+ wl_shell_surface_pong(shellSurface, serial);
+}
+
+static void shellSurfaceHandleConfigure(void* data,
+ struct wl_shell_surface* shellSurface,
+ uint32_t edges,
+ int32_t width,
+ int32_t height)
+{
+ _GLFWwindow* window = data;
+ float aspectRatio;
+ float targetRatio;
+
+ if (!window->monitor)
+ {
+ if (_glfw.wl.viewporter && window->decorated)
+ {
+ width -= _GLFW_DECORATION_HORIZONTAL;
+ height -= _GLFW_DECORATION_VERTICAL;
+ }
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
+ {
+ aspectRatio = (float)width / (float)height;
+ targetRatio = (float)window->numer / (float)window->denom;
+ if (aspectRatio < targetRatio)
+ height = width / targetRatio;
+ else if (aspectRatio > targetRatio)
+ width = height * targetRatio;
+ }
+
+ if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth)
+ width = window->minwidth;
+ else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth)
+ width = window->maxwidth;
+
+ if (window->minheight != GLFW_DONT_CARE && height < window->minheight)
+ height = window->minheight;
+ else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight)
+ height = window->maxheight;
+ }
+
+ _glfwInputWindowSize(window, width, height);
+ _glfwPlatformSetWindowSize(window, width, height);
+ _glfwInputWindowDamage(window);
+}
+
+static void shellSurfaceHandlePopupDone(void* data,
+ struct wl_shell_surface* shellSurface)
+{
+}
+
+static const struct wl_shell_surface_listener shellSurfaceListener = {
+ shellSurfaceHandlePing,
+ shellSurfaceHandleConfigure,
+ shellSurfaceHandlePopupDone
+};
+
+static int createTmpfileCloexec(char* tmpname)
+{
+ int fd;
+
+ fd = mkostemp(tmpname, O_CLOEXEC);
+ if (fd >= 0)
+ unlink(tmpname);
+
+ return fd;
+}
+
+/*
+ * Create a new, unique, anonymous file of the given size, and
+ * return the file descriptor for it. The file descriptor is set
+ * CLOEXEC. The file is immediately suitable for mmap()'ing
+ * the given size at offset zero.
+ *
+ * The file should not have a permanent backing store like a disk,
+ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
+ *
+ * The file name is deleted from the file system.
+ *
+ * The file is suitable for buffer sharing between processes by
+ * transmitting the file descriptor over Unix sockets using the
+ * SCM_RIGHTS methods.
+ *
+ * posix_fallocate() is used to guarantee that disk space is available
+ * for the file at the given size. If disk space is insufficent, errno
+ * is set to ENOSPC. If posix_fallocate() is not supported, program may
+ * receive SIGBUS on accessing mmap()'ed file contents instead.
+ */
+static int createAnonymousFile(off_t size)
+{
+ static const char template[] = "/glfw-shared-XXXXXX";
+ const char* path;
+ char* name;
+ int fd;
+ int ret;
+
+#ifdef HAVE_MEMFD_CREATE
+ fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ if (fd >= 0)
+ {
+ // We can add this seal before calling posix_fallocate(), as the file
+ // is currently zero-sized anyway.
+ //
+ // There is also no need to check for the return value, we couldn’t do
+ // anything with it anyway.
+ fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
+ }
+ else
+#endif
+ {
+ path = getenv("XDG_RUNTIME_DIR");
+ if (!path)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ name = calloc(strlen(path) + sizeof(template), 1);
+ strcpy(name, path);
+ strcat(name, template);
+
+ fd = createTmpfileCloexec(name);
+ free(name);
+ if (fd < 0)
+ return -1;
+ }
+
+ ret = posix_fallocate(fd, 0, size);
+ if (ret != 0)
+ {
+ close(fd);
+ errno = ret;
+ return -1;
+ }
+ return fd;
+}
+
+static struct wl_buffer* createShmBuffer(const GLFWimage* image)
+{
+ struct wl_shm_pool* pool;
+ struct wl_buffer* buffer;
+ int stride = image->width * 4;
+ int length = image->width * image->height * 4;
+ void* data;
+ int fd, i;
+
+ fd = createAnonymousFile(length);
+ if (fd < 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Creating a buffer file for %d B failed: %m",
+ length);
+ return NULL;
+ }
+
+ data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: mmap failed: %m");
+ close(fd);
+ return NULL;
+ }
+
+ pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
+
+ close(fd);
+ unsigned char* source = (unsigned char*) image->pixels;
+ unsigned char* target = data;
+ for (i = 0; i < image->width * image->height; i++, source += 4)
+ {
+ unsigned int alpha = source[3];
+
+ *target++ = (unsigned char) ((source[2] * alpha) / 255);
+ *target++ = (unsigned char) ((source[1] * alpha) / 255);
+ *target++ = (unsigned char) ((source[0] * alpha) / 255);
+ *target++ = (unsigned char) alpha;
+ }
+
+ buffer =
+ wl_shm_pool_create_buffer(pool, 0,
+ image->width,
+ image->height,
+ stride, WL_SHM_FORMAT_ARGB8888);
+ munmap(data, length);
+ wl_shm_pool_destroy(pool);
+
+ return buffer;
+}
+
+static void createDecoration(_GLFWdecorationWayland* decoration,
+ struct wl_surface* parent,
+ struct wl_buffer* buffer, GLFWbool opaque,
+ int x, int y,
+ int width, int height)
+{
+ struct wl_region* region;
+
+ decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);
+ decoration->subsurface =
+ wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
+ decoration->surface, parent);
+ wl_subsurface_set_position(decoration->subsurface, x, y);
+ decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter,
+ decoration->surface);
+ wp_viewport_set_destination(decoration->viewport, width, height);
+ wl_surface_attach(decoration->surface, buffer, 0, 0);
+
+ if (opaque)
+ {
+ region = wl_compositor_create_region(_glfw.wl.compositor);
+ wl_region_add(region, 0, 0, width, height);
+ wl_surface_set_opaque_region(decoration->surface, region);
+ wl_surface_commit(decoration->surface);
+ wl_region_destroy(region);
+ }
+ else
+ wl_surface_commit(decoration->surface);
+}
+
+static void createDecorations(_GLFWwindow* window)
+{
+ unsigned char data[] = { 224, 224, 224, 255 };
+ const GLFWimage image = { 1, 1, data };
+ GLFWbool opaque = (data[3] == 255);
+
+ if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)
+ return;
+
+ if (!window->wl.decorations.buffer)
+ window->wl.decorations.buffer = createShmBuffer(&image);
+ if (!window->wl.decorations.buffer)
+ return;
+
+ createDecoration(&window->wl.decorations.top, window->wl.surface,
+ window->wl.decorations.buffer, opaque,
+ 0, -_GLFW_DECORATION_TOP,
+ window->wl.width, _GLFW_DECORATION_TOP);
+ createDecoration(&window->wl.decorations.left, window->wl.surface,
+ window->wl.decorations.buffer, opaque,
+ -_GLFW_DECORATION_WIDTH, -_GLFW_DECORATION_TOP,
+ _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+ createDecoration(&window->wl.decorations.right, window->wl.surface,
+ window->wl.decorations.buffer, opaque,
+ window->wl.width, -_GLFW_DECORATION_TOP,
+ _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+ createDecoration(&window->wl.decorations.bottom, window->wl.surface,
+ window->wl.decorations.buffer, opaque,
+ -_GLFW_DECORATION_WIDTH, window->wl.height,
+ window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
+}
+
+static void destroyDecoration(_GLFWdecorationWayland* decoration)
+{
+ if (decoration->surface)
+ wl_surface_destroy(decoration->surface);
+ if (decoration->subsurface)
+ wl_subsurface_destroy(decoration->subsurface);
+ if (decoration->viewport)
+ wp_viewport_destroy(decoration->viewport);
+ decoration->surface = NULL;
+ decoration->subsurface = NULL;
+ decoration->viewport = NULL;
+}
+
+static void destroyDecorations(_GLFWwindow* window)
+{
+ destroyDecoration(&window->wl.decorations.top);
+ destroyDecoration(&window->wl.decorations.left);
+ destroyDecoration(&window->wl.decorations.right);
+ destroyDecoration(&window->wl.decorations.bottom);
+}
+
+static void xdgDecorationHandleConfigure(void* data,
+ struct zxdg_toplevel_decoration_v1* decoration,
+ uint32_t mode)
+{
+ _GLFWwindow* window = data;
+
+ window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+
+ if (!window->wl.decorations.serverSide)
+ createDecorations(window);
+}
+
+static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
+ xdgDecorationHandleConfigure,
+};
+
+// Makes the surface considered as XRGB instead of ARGB.
+static void setOpaqueRegion(_GLFWwindow* window)
+{
+ struct wl_region* region;
+
+ region = wl_compositor_create_region(_glfw.wl.compositor);
+ if (!region)
+ return;
+
+ wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
+ wl_surface_set_opaque_region(window->wl.surface, region);
+ wl_surface_commit(window->wl.surface);
+ wl_region_destroy(region);
+}
+
+
+static void resizeWindow(_GLFWwindow* window)
+{
+ int scale = window->wl.scale;
+ int scaledWidth = window->wl.width * scale;
+ int scaledHeight = window->wl.height * scale;
+ wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
+ if (!window->wl.transparent)
+ setOpaqueRegion(window);
+ _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
+ _glfwInputWindowContentScale(window, scale, scale);
+
+ if (!window->wl.decorations.top.surface)
+ return;
+
+ // Top decoration.
+ wp_viewport_set_destination(window->wl.decorations.top.viewport,
+ window->wl.width, _GLFW_DECORATION_TOP);
+ wl_surface_commit(window->wl.decorations.top.surface);
+
+ // Left decoration.
+ wp_viewport_set_destination(window->wl.decorations.left.viewport,
+ _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+ wl_surface_commit(window->wl.decorations.left.surface);
+
+ // Right decoration.
+ wl_subsurface_set_position(window->wl.decorations.right.subsurface,
+ window->wl.width, -_GLFW_DECORATION_TOP);
+ wp_viewport_set_destination(window->wl.decorations.right.viewport,
+ _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+ wl_surface_commit(window->wl.decorations.right.surface);
+
+ // Bottom decoration.
+ wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,
+ -_GLFW_DECORATION_WIDTH, window->wl.height);
+ wp_viewport_set_destination(window->wl.decorations.bottom.viewport,
+ window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
+ wl_surface_commit(window->wl.decorations.bottom.surface);
+}
+
+static void checkScaleChange(_GLFWwindow* window)
+{
+ int scale = 1;
+ int i;
+ int monitorScale;
+
+ // Check if we will be able to set the buffer scale or not.
+ if (_glfw.wl.compositorVersion < 3)
+ return;
+
+ // Get the scale factor from the highest scale monitor.
+ for (i = 0; i < window->wl.monitorsCount; ++i)
+ {
+ monitorScale = window->wl.monitors[i]->wl.scale;
+ if (scale < monitorScale)
+ scale = monitorScale;
+ }
+
+ // Only change the framebuffer size if the scale changed.
+ if (scale != window->wl.scale)
+ {
+ window->wl.scale = scale;
+ wl_surface_set_buffer_scale(window->wl.surface, scale);
+ resizeWindow(window);
+ }
+}
+
+static void surfaceHandleEnter(void *data,
+ struct wl_surface *surface,
+ struct wl_output *output)
+{
+ _GLFWwindow* window = data;
+ _GLFWmonitor* monitor = wl_output_get_user_data(output);
+
+ if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)
+ {
+ ++window->wl.monitorsSize;
+ window->wl.monitors =
+ realloc(window->wl.monitors,
+ window->wl.monitorsSize * sizeof(_GLFWmonitor*));
+ }
+
+ window->wl.monitors[window->wl.monitorsCount++] = monitor;
+
+ checkScaleChange(window);
+}
+
+static void surfaceHandleLeave(void *data,
+ struct wl_surface *surface,
+ struct wl_output *output)
+{
+ _GLFWwindow* window = data;
+ _GLFWmonitor* monitor = wl_output_get_user_data(output);
+ GLFWbool found;
+ int i;
+
+ for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i)
+ {
+ if (monitor == window->wl.monitors[i])
+ found = GLFW_TRUE;
+ if (found)
+ window->wl.monitors[i] = window->wl.monitors[i + 1];
+ }
+ window->wl.monitors[--window->wl.monitorsCount] = NULL;
+
+ checkScaleChange(window);
+}
+
+static const struct wl_surface_listener surfaceListener = {
+ surfaceHandleEnter,
+ surfaceHandleLeave
+};
+
+static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
+{
+ if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
+ {
+ window->wl.idleInhibitor =
+ zwp_idle_inhibit_manager_v1_create_inhibitor(
+ _glfw.wl.idleInhibitManager, window->wl.surface);
+ if (!window->wl.idleInhibitor)
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Idle inhibitor creation failed");
+ }
+ else if (!enable && window->wl.idleInhibitor)
+ {
+ zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
+ window->wl.idleInhibitor = NULL;
+ }
+}
+
+static GLFWbool createSurface(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig)
+{
+ window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
+ if (!window->wl.surface)
+ return GLFW_FALSE;
+
+ wl_surface_add_listener(window->wl.surface,
+ &surfaceListener,
+ window);
+
+ wl_surface_set_user_data(window->wl.surface, window);
+
+ window->wl.native = wl_egl_window_create(window->wl.surface,
+ wndconfig->width,
+ wndconfig->height);
+ if (!window->wl.native)
+ return GLFW_FALSE;
+
+ window->wl.width = wndconfig->width;
+ window->wl.height = wndconfig->height;
+ window->wl.scale = 1;
+
+ if (!window->wl.transparent)
+ setOpaqueRegion(window);
+
+ return GLFW_TRUE;
+}
+
+static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
+ int refreshRate)
+{
+ if (window->wl.xdg.toplevel)
+ {
+ xdg_toplevel_set_fullscreen(
+ window->wl.xdg.toplevel,
+ monitor->wl.output);
+ }
+ else if (window->wl.shellSurface)
+ {
+ wl_shell_surface_set_fullscreen(
+ window->wl.shellSurface,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ refreshRate * 1000, // Convert Hz to mHz.
+ monitor->wl.output);
+ }
+ setIdleInhibitor(window, GLFW_TRUE);
+ if (!window->wl.decorations.serverSide)
+ destroyDecorations(window);
+}
+
+static GLFWbool createShellSurface(_GLFWwindow* window)
+{
+ if (!_glfw.wl.shell)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: wl_shell protocol not available");
+ return GLFW_FALSE;
+ }
+
+ window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
+ window->wl.surface);
+ if (!window->wl.shellSurface)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Shell surface creation failed");
+ return GLFW_FALSE;
+ }
+
+ wl_shell_surface_add_listener(window->wl.shellSurface,
+ &shellSurfaceListener,
+ window);
+
+ if (window->wl.title)
+ wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title);
+
+ if (window->monitor)
+ {
+ setFullscreen(window, window->monitor, 0);
+ }
+ else if (window->wl.maximized)
+ {
+ wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
+ setIdleInhibitor(window, GLFW_FALSE);
+ createDecorations(window);
+ }
+ else
+ {
+ wl_shell_surface_set_toplevel(window->wl.shellSurface);
+ setIdleInhibitor(window, GLFW_FALSE);
+ createDecorations(window);
+ }
+
+ wl_surface_commit(window->wl.surface);
+
+ return GLFW_TRUE;
+}
+
+static void xdgToplevelHandleConfigure(void* data,
+ struct xdg_toplevel* toplevel,
+ int32_t width,
+ int32_t height,
+ struct wl_array* states)
+{
+ _GLFWwindow* window = data;
+ float aspectRatio;
+ float targetRatio;
+ uint32_t* state;
+ GLFWbool maximized = GLFW_FALSE;
+ GLFWbool fullscreen = GLFW_FALSE;
+ GLFWbool activated = GLFW_FALSE;
+
+ wl_array_for_each(state, states)
+ {
+ switch (*state)
+ {
+ case XDG_TOPLEVEL_STATE_MAXIMIZED:
+ maximized = GLFW_TRUE;
+ break;
+ case XDG_TOPLEVEL_STATE_FULLSCREEN:
+ fullscreen = GLFW_TRUE;
+ break;
+ case XDG_TOPLEVEL_STATE_RESIZING:
+ break;
+ case XDG_TOPLEVEL_STATE_ACTIVATED:
+ activated = GLFW_TRUE;
+ break;
+ }
+ }
+
+ if (width != 0 && height != 0)
+ {
+ if (!maximized && !fullscreen)
+ {
+ if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
+ {
+ aspectRatio = (float)width / (float)height;
+ targetRatio = (float)window->numer / (float)window->denom;
+ if (aspectRatio < targetRatio)
+ height = width / targetRatio;
+ else if (aspectRatio > targetRatio)
+ width = height * targetRatio;
+ }
+ }
+
+ _glfwInputWindowSize(window, width, height);
+ _glfwPlatformSetWindowSize(window, width, height);
+ _glfwInputWindowDamage(window);
+ }
+
+ if (!window->wl.justCreated && !activated && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+ _glfwInputWindowFocus(window, activated);
+ window->wl.justCreated = GLFW_FALSE;
+}
+
+static void xdgToplevelHandleClose(void* data,
+ struct xdg_toplevel* toplevel)
+{
+ _GLFWwindow* window = data;
+ _glfwInputWindowCloseRequest(window);
+}
+
+static const struct xdg_toplevel_listener xdgToplevelListener = {
+ xdgToplevelHandleConfigure,
+ xdgToplevelHandleClose
+};
+
+static void xdgSurfaceHandleConfigure(void* data,
+ struct xdg_surface* surface,
+ uint32_t serial)
+{
+ xdg_surface_ack_configure(surface, serial);
+}
+
+static const struct xdg_surface_listener xdgSurfaceListener = {
+ xdgSurfaceHandleConfigure
+};
+
+static void setXdgDecorations(_GLFWwindow* window)
+{
+ if (_glfw.wl.decorationManager)
+ {
+ window->wl.xdg.decoration =
+ zxdg_decoration_manager_v1_get_toplevel_decoration(
+ _glfw.wl.decorationManager, window->wl.xdg.toplevel);
+ zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
+ &xdgDecorationListener,
+ window);
+ zxdg_toplevel_decoration_v1_set_mode(
+ window->wl.xdg.decoration,
+ ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+ }
+ else
+ {
+ window->wl.decorations.serverSide = GLFW_FALSE;
+ createDecorations(window);
+ }
+}
+
+static GLFWbool createXdgSurface(_GLFWwindow* window)
+{
+ window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
+ window->wl.surface);
+ if (!window->wl.xdg.surface)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: xdg-surface creation failed");
+ return GLFW_FALSE;
+ }
+
+ xdg_surface_add_listener(window->wl.xdg.surface,
+ &xdgSurfaceListener,
+ window);
+
+ window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);
+ if (!window->wl.xdg.toplevel)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: xdg-toplevel creation failed");
+ return GLFW_FALSE;
+ }
+
+ xdg_toplevel_add_listener(window->wl.xdg.toplevel,
+ &xdgToplevelListener,
+ window);
+
+ if (window->wl.title)
+ xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
+
+ if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
+ xdg_toplevel_set_min_size(window->wl.xdg.toplevel,
+ window->minwidth, window->minheight);
+ if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
+ xdg_toplevel_set_max_size(window->wl.xdg.toplevel,
+ window->maxwidth, window->maxheight);
+
+ if (window->monitor)
+ {
+ xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
+ window->monitor->wl.output);
+ setIdleInhibitor(window, GLFW_TRUE);
+ }
+ else if (window->wl.maximized)
+ {
+ xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
+ setIdleInhibitor(window, GLFW_FALSE);
+ setXdgDecorations(window);
+ }
+ else
+ {
+ setIdleInhibitor(window, GLFW_FALSE);
+ setXdgDecorations(window);
+ }
+
+ wl_surface_commit(window->wl.surface);
+ wl_display_roundtrip(_glfw.wl.display);
+
+ return GLFW_TRUE;
+}
+
+static void setCursorImage(_GLFWwindow* window,
+ _GLFWcursorWayland* cursorWayland)
+{
+ struct itimerspec timer = {};
+ struct wl_cursor* wlCursor = cursorWayland->cursor;
+ struct wl_cursor_image* image;
+ struct wl_buffer* buffer;
+ struct wl_surface* surface = _glfw.wl.cursorSurface;
+ int scale = 1;
+
+ if (!wlCursor)
+ buffer = cursorWayland->buffer;
+ else
+ {
+ if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
+ {
+ wlCursor = cursorWayland->cursorHiDPI;
+ scale = 2;
+ }
+
+ image = wlCursor->images[cursorWayland->currentImage];
+ buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer)
+ return;
+
+ timer.it_value.tv_sec = image->delay / 1000;
+ timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;
+ timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);
+
+ cursorWayland->width = image->width;
+ cursorWayland->height = image->height;
+ cursorWayland->xhot = image->hotspot_x;
+ cursorWayland->yhot = image->hotspot_y;
+ }
+
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
+ surface,
+ cursorWayland->xhot / scale,
+ cursorWayland->yhot / scale);
+ wl_surface_set_buffer_scale(surface, scale);
+ wl_surface_attach(surface, buffer, 0, 0);
+ wl_surface_damage(surface, 0, 0,
+ cursorWayland->width, cursorWayland->height);
+ wl_surface_commit(surface);
+}
+
+static void incrementCursorImage(_GLFWwindow* window)
+{
+ _GLFWcursor* cursor;
+
+ if (!window || window->wl.decorations.focus != mainWindow)
+ return;
+
+ cursor = window->wl.currentCursor;
+ if (cursor && cursor->wl.cursor)
+ {
+ cursor->wl.currentImage += 1;
+ cursor->wl.currentImage %= cursor->wl.cursor->image_count;
+ setCursorImage(window, &cursor->wl);
+ }
+}
+
+static void handleEvents(int timeout)
+{
+ struct wl_display* display = _glfw.wl.display;
+ struct pollfd fds[] = {
+ { wl_display_get_fd(display), POLLIN },
+ { _glfw.wl.timerfd, POLLIN },
+ { _glfw.wl.cursorTimerfd, POLLIN },
+ };
+ ssize_t read_ret;
+ uint64_t repeats, i;
+
+ while (wl_display_prepare_read(display) != 0)
+ wl_display_dispatch_pending(display);
+
+ // If an error different from EAGAIN happens, we have likely been
+ // disconnected from the Wayland session, try to handle that the best we
+ // can.
+ if (wl_display_flush(display) < 0 && errno != EAGAIN)
+ {
+ _GLFWwindow* window = _glfw.windowListHead;
+ while (window)
+ {
+ _glfwInputWindowCloseRequest(window);
+ window = window->next;
+ }
+ wl_display_cancel_read(display);
+ return;
+ }
+
+ if (poll(fds, 3, timeout) > 0)
+ {
+ if (fds[0].revents & POLLIN)
+ {
+ wl_display_read_events(display);
+ wl_display_dispatch_pending(display);
+ }
+ else
+ {
+ wl_display_cancel_read(display);
+ }
+
+ if (fds[1].revents & POLLIN)
+ {
+ read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
+ if (read_ret != 8)
+ return;
+
+ for (i = 0; i < repeats; ++i)
+ _glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
+ _glfw.wl.keyboardLastScancode, GLFW_REPEAT,
+ _glfw.wl.xkb.modifiers);
+ }
+
+ if (fds[2].revents & POLLIN)
+ {
+ read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
+ if (read_ret != 8)
+ return;
+
+ incrementCursorImage(_glfw.wl.pointerFocus);
+ }
+ }
+ else
+ {
+ wl_display_cancel_read(display);
+ }
+}
+
+// Translates a GLFW standard cursor to a theme cursor name
+//
+static char *translateCursorShape(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return "left_ptr";
+ case GLFW_IBEAM_CURSOR:
+ return "xterm";
+ case GLFW_CROSSHAIR_CURSOR:
+ return "crosshair";
+ case GLFW_HAND_CURSOR:
+ return "grabbing";
+ case GLFW_HRESIZE_CURSOR:
+ return "sb_h_double_arrow";
+ case GLFW_VRESIZE_CURSOR:
+ return "sb_v_double_arrow";
+ }
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ window->wl.justCreated = GLFW_TRUE;
+ window->wl.transparent = fbconfig->transparent;
+
+ if (!createSurface(window, wndconfig))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
+ ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ if (!_glfwInitOSMesa())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (wndconfig->title)
+ window->wl.title = _glfw_strdup(wndconfig->title);
+
+ if (wndconfig->visible)
+ {
+ if (_glfw.wl.wmBase)
+ {
+ if (!createXdgSurface(window))
+ return GLFW_FALSE;
+ }
+ else
+ {
+ if (!createShellSurface(window))
+ return GLFW_FALSE;
+ }
+
+ window->wl.visible = GLFW_TRUE;
+ }
+ else
+ {
+ window->wl.xdg.surface = NULL;
+ window->wl.xdg.toplevel = NULL;
+ window->wl.shellSurface = NULL;
+ window->wl.visible = GLFW_FALSE;
+ }
+
+ window->wl.currentCursor = NULL;
+
+ window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
+ window->wl.monitorsCount = 0;
+ window->wl.monitorsSize = 1;
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (window == _glfw.wl.pointerFocus)
+ {
+ _glfw.wl.pointerFocus = NULL;
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+ }
+ if (window == _glfw.wl.keyboardFocus)
+ {
+ _glfw.wl.keyboardFocus = NULL;
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+ }
+
+ if (window->wl.idleInhibitor)
+ zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+
+ destroyDecorations(window);
+ if (window->wl.xdg.decoration)
+ zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
+
+ if (window->wl.decorations.buffer)
+ wl_buffer_destroy(window->wl.decorations.buffer);
+
+ if (window->wl.native)
+ wl_egl_window_destroy(window->wl.native);
+
+ if (window->wl.shellSurface)
+ wl_shell_surface_destroy(window->wl.shellSurface);
+
+ if (window->wl.xdg.toplevel)
+ xdg_toplevel_destroy(window->wl.xdg.toplevel);
+
+ if (window->wl.xdg.surface)
+ xdg_surface_destroy(window->wl.xdg.surface);
+
+ if (window->wl.surface)
+ wl_surface_destroy(window->wl.surface);
+
+ free(window->wl.title);
+ free(window->wl.monitors);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+ if (window->wl.title)
+ free(window->wl.title);
+ window->wl.title = _glfw_strdup(title);
+ if (window->wl.xdg.toplevel)
+ xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
+ else if (window->wl.shellSurface)
+ wl_shell_surface_set_title(window->wl.shellSurface, title);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Setting window icon not supported");
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ // A Wayland client is not aware of its position, so just warn and leave it
+ // as (0, 0)
+
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Window position retrieval not supported");
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ // A Wayland client can not set its position, so just warn
+
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Window position setting not supported");
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->wl.width;
+ if (height)
+ *height = window->wl.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ window->wl.width = width;
+ window->wl.height = height;
+ resizeWindow(window);
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ if (_glfw.wl.wmBase)
+ {
+ if (window->wl.xdg.toplevel)
+ {
+ if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
+ minwidth = minheight = 0;
+ if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
+ maxwidth = maxheight = 0;
+ xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
+ xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
+ wl_surface_commit(window->wl.surface);
+ }
+ }
+ else
+ {
+ // TODO: find out how to trigger a resize.
+ // The actual limits are checked in the wl_shell_surface::configure handler.
+ }
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,
+ int numer, int denom)
+{
+ // TODO: find out how to trigger a resize.
+ // The actual limits are checked in the wl_shell_surface::configure handler.
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
+ int* width, int* height)
+{
+ _glfwPlatformGetWindowSize(window, width, height);
+ *width *= window->wl.scale;
+ *height *= window->wl.scale;
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
+ {
+ if (top)
+ *top = _GLFW_DECORATION_TOP;
+ if (left)
+ *left = _GLFW_DECORATION_WIDTH;
+ if (right)
+ *right = _GLFW_DECORATION_WIDTH;
+ if (bottom)
+ *bottom = _GLFW_DECORATION_WIDTH;
+ }
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+ float* xscale, float* yscale)
+{
+ if (xscale)
+ *xscale = (float) window->wl.scale;
+ if (yscale)
+ *yscale = (float) window->wl.scale;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ if (_glfw.wl.wmBase)
+ {
+ if (window->wl.xdg.toplevel)
+ xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Iconify window not supported on wl_shell");
+ }
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ if (window->wl.xdg.toplevel)
+ {
+ if (window->monitor)
+ xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
+ if (window->wl.maximized)
+ xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
+ // There is no way to unset minimized, or even to know if we are
+ // minimized, so there is nothing to do here.
+ }
+ else if (window->wl.shellSurface)
+ {
+ if (window->monitor || window->wl.maximized)
+ wl_shell_surface_set_toplevel(window->wl.shellSurface);
+ }
+ _glfwInputWindowMonitor(window, NULL);
+ window->wl.maximized = GLFW_FALSE;
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ if (window->wl.xdg.toplevel)
+ {
+ xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
+ }
+ else if (window->wl.shellSurface)
+ {
+ // Let the compositor select the best output.
+ wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
+ }
+ window->wl.maximized = GLFW_TRUE;
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ if (!window->wl.visible)
+ {
+ if (_glfw.wl.wmBase)
+ createXdgSurface(window);
+ else if (!window->wl.shellSurface)
+ createShellSurface(window);
+ window->wl.visible = GLFW_TRUE;
+ }
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ if (window->wl.xdg.toplevel)
+ {
+ xdg_toplevel_destroy(window->wl.xdg.toplevel);
+ xdg_surface_destroy(window->wl.xdg.surface);
+ window->wl.xdg.toplevel = NULL;
+ window->wl.xdg.surface = NULL;
+ }
+ else if (window->wl.shellSurface)
+ {
+ wl_shell_surface_destroy(window->wl.shellSurface);
+ window->wl.shellSurface = NULL;
+ }
+ window->wl.visible = GLFW_FALSE;
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Window attention request not implemented yet");
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Focusing a window requires user interaction");
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (monitor)
+ {
+ setFullscreen(window, monitor, refreshRate);
+ }
+ else
+ {
+ if (window->wl.xdg.toplevel)
+ xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
+ else if (window->wl.shellSurface)
+ wl_shell_surface_set_toplevel(window->wl.shellSurface);
+ setIdleInhibitor(window, GLFW_FALSE);
+ if (!_glfw.wl.decorationManager)
+ createDecorations(window);
+ }
+ _glfwInputWindowMonitor(window, monitor);
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return _glfw.wl.keyboardFocus == window;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give
+ // any way to request whether a surface is iconified.
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return window->wl.visible;
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return window->wl.maximized;
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+ return window->wl.hovered;
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+ return window->wl.transparent;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Window attribute setting not implemented yet");
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+ if (!window->monitor)
+ {
+ if (enabled)
+ createDecorations(window);
+ else
+ destroyDecorations(window);
+ }
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Window attribute setting not implemented yet");
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+ return 1.f;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ handleEvents(0);
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ handleEvents(-1);
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ handleEvents((int) (timeout * 1e3));
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ wl_display_sync(_glfw.wl.display);
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ if (xpos)
+ *xpos = window->wl.cursorPosX;
+ if (ypos)
+ *ypos = window->wl.cursorPosY;
+}
+
+static GLFWbool isPointerLocked(_GLFWwindow* window);
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+ if (isPointerLocked(window))
+ {
+ zwp_locked_pointer_v1_set_cursor_position_hint(
+ window->wl.pointerLock.lockedPointer,
+ wl_fixed_from_double(x), wl_fixed_from_double(y));
+ wl_surface_commit(window->wl.surface);
+ }
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ _glfwPlatformSetCursor(window, window->wl.currentCursor);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+ // TODO
+ return NULL;
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+ return _glfw.wl.scancodes[key];
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ cursor->wl.buffer = createShmBuffer(image);
+ if (!cursor->wl.buffer)
+ return GLFW_FALSE;
+
+ cursor->wl.width = image->width;
+ cursor->wl.height = image->height;
+ cursor->wl.xhot = xhot;
+ cursor->wl.yhot = yhot;
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ struct wl_cursor* standardCursor;
+
+ standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
+ translateCursorShape(shape));
+ if (!standardCursor)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Standard cursor \"%s\" not found",
+ translateCursorShape(shape));
+ return GLFW_FALSE;
+ }
+
+ cursor->wl.cursor = standardCursor;
+ cursor->wl.currentImage = 0;
+
+ if (_glfw.wl.cursorThemeHiDPI)
+ {
+ standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
+ translateCursorShape(shape));
+ cursor->wl.cursorHiDPI = standardCursor;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ // If it's a standard cursor we don't need to do anything here
+ if (cursor->wl.cursor)
+ return;
+
+ if (cursor->wl.buffer)
+ wl_buffer_destroy(cursor->wl.buffer);
+}
+
+static void relativePointerHandleRelativeMotion(void* data,
+ struct zwp_relative_pointer_v1* pointer,
+ uint32_t timeHi,
+ uint32_t timeLo,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t dxUnaccel,
+ wl_fixed_t dyUnaccel)
+{
+ _GLFWwindow* window = data;
+
+ if (window->cursorMode != GLFW_CURSOR_DISABLED)
+ return;
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + wl_fixed_to_double(dxUnaccel),
+ window->virtualCursorPosY + wl_fixed_to_double(dyUnaccel));
+}
+
+static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
+ relativePointerHandleRelativeMotion
+};
+
+static void lockedPointerHandleLocked(void* data,
+ struct zwp_locked_pointer_v1* lockedPointer)
+{
+}
+
+static void unlockPointer(_GLFWwindow* window)
+{
+ struct zwp_relative_pointer_v1* relativePointer =
+ window->wl.pointerLock.relativePointer;
+ struct zwp_locked_pointer_v1* lockedPointer =
+ window->wl.pointerLock.lockedPointer;
+
+ zwp_relative_pointer_v1_destroy(relativePointer);
+ zwp_locked_pointer_v1_destroy(lockedPointer);
+
+ window->wl.pointerLock.relativePointer = NULL;
+ window->wl.pointerLock.lockedPointer = NULL;
+}
+
+static void lockPointer(_GLFWwindow* window);
+
+static void lockedPointerHandleUnlocked(void* data,
+ struct zwp_locked_pointer_v1* lockedPointer)
+{
+}
+
+static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
+ lockedPointerHandleLocked,
+ lockedPointerHandleUnlocked
+};
+
+static void lockPointer(_GLFWwindow* window)
+{
+ struct zwp_relative_pointer_v1* relativePointer;
+ struct zwp_locked_pointer_v1* lockedPointer;
+
+ if (!_glfw.wl.relativePointerManager)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: no relative pointer manager");
+ return;
+ }
+
+ relativePointer =
+ zwp_relative_pointer_manager_v1_get_relative_pointer(
+ _glfw.wl.relativePointerManager,
+ _glfw.wl.pointer);
+ zwp_relative_pointer_v1_add_listener(relativePointer,
+ &relativePointerListener,
+ window);
+
+ lockedPointer =
+ zwp_pointer_constraints_v1_lock_pointer(
+ _glfw.wl.pointerConstraints,
+ window->wl.surface,
+ _glfw.wl.pointer,
+ NULL,
+ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ zwp_locked_pointer_v1_add_listener(lockedPointer,
+ &lockedPointerListener,
+ window);
+
+ window->wl.pointerLock.relativePointer = relativePointer;
+ window->wl.pointerLock.lockedPointer = lockedPointer;
+
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
+ NULL, 0, 0);
+}
+
+static GLFWbool isPointerLocked(_GLFWwindow* window)
+{
+ return window->wl.pointerLock.lockedPointer != NULL;
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ struct wl_cursor* defaultCursor;
+ struct wl_cursor* defaultCursorHiDPI = NULL;
+
+ if (!_glfw.wl.pointer)
+ return;
+
+ window->wl.currentCursor = cursor;
+
+ // If we're not in the correct window just save the cursor
+ // the next time the pointer enters the window the cursor will change
+ if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
+ return;
+
+ // Unlock possible pointer lock if no longer disabled.
+ if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))
+ unlockPointer(window);
+
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ if (cursor)
+ setCursorImage(window, &cursor->wl);
+ else
+ {
+ defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
+ "left_ptr");
+ if (!defaultCursor)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Standard cursor not found");
+ return;
+ }
+ if (_glfw.wl.cursorThemeHiDPI)
+ defaultCursorHiDPI =
+ wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
+ "left_ptr");
+ _GLFWcursorWayland cursorWayland = {
+ defaultCursor,
+ defaultCursorHiDPI,
+ NULL,
+ 0, 0,
+ 0, 0,
+ 0
+ };
+ setCursorImage(window, &cursorWayland);
+ }
+ }
+ else if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ if (!isPointerLocked(window))
+ lockPointer(window);
+ }
+ else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+ {
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);
+ }
+}
+
+static void dataSourceHandleTarget(void* data,
+ struct wl_data_source* dataSource,
+ const char* mimeType)
+{
+ if (_glfw.wl.dataSource != dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unknown clipboard data source");
+ return;
+ }
+}
+
+static void dataSourceHandleSend(void* data,
+ struct wl_data_source* dataSource,
+ const char* mimeType,
+ int fd)
+{
+ const char* string = _glfw.wl.clipboardSendString;
+ size_t len = _glfw.wl.clipboardSendSize;
+ int ret;
+
+ if (_glfw.wl.dataSource != dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unknown clipboard data source");
+ return;
+ }
+
+ if (!string)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Copy requested from an invalid string");
+ return;
+ }
+
+ if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Wrong MIME type asked from clipboard");
+ close(fd);
+ return;
+ }
+
+ while (len > 0)
+ {
+ ret = write(fd, string, len);
+ if (ret == -1 && errno == EINTR)
+ continue;
+ if (ret == -1)
+ {
+ // TODO: also report errno maybe.
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Error while writing the clipboard");
+ close(fd);
+ return;
+ }
+ len -= ret;
+ }
+ close(fd);
+}
+
+static void dataSourceHandleCancelled(void* data,
+ struct wl_data_source* dataSource)
+{
+ wl_data_source_destroy(dataSource);
+
+ if (_glfw.wl.dataSource != dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unknown clipboard data source");
+ return;
+ }
+
+ _glfw.wl.dataSource = NULL;
+}
+
+static const struct wl_data_source_listener dataSourceListener = {
+ dataSourceHandleTarget,
+ dataSourceHandleSend,
+ dataSourceHandleCancelled,
+};
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+ if (_glfw.wl.dataSource)
+ {
+ wl_data_source_destroy(_glfw.wl.dataSource);
+ _glfw.wl.dataSource = NULL;
+ }
+
+ if (_glfw.wl.clipboardSendString)
+ {
+ free(_glfw.wl.clipboardSendString);
+ _glfw.wl.clipboardSendString = NULL;
+ }
+
+ _glfw.wl.clipboardSendString = strdup(string);
+ if (!_glfw.wl.clipboardSendString)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to allocate clipboard string");
+ return;
+ }
+ _glfw.wl.clipboardSendSize = strlen(string);
+ _glfw.wl.dataSource =
+ wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
+ if (!_glfw.wl.dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to create clipboard source");
+ free(_glfw.wl.clipboardSendString);
+ return;
+ }
+ wl_data_source_add_listener(_glfw.wl.dataSource,
+ &dataSourceListener,
+ NULL);
+ wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
+ wl_data_device_set_selection(_glfw.wl.dataDevice,
+ _glfw.wl.dataSource,
+ _glfw.wl.serial);
+}
+
+static GLFWbool growClipboardString(void)
+{
+ char* clipboard = _glfw.wl.clipboardString;
+
+ clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
+ if (!clipboard)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to grow clipboard string");
+ return GLFW_FALSE;
+ }
+ _glfw.wl.clipboardString = clipboard;
+ _glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;
+ return GLFW_TRUE;
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+ int fds[2];
+ int ret;
+ size_t len = 0;
+
+ if (!_glfw.wl.dataOffer)
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "No clipboard data has been sent yet");
+ return NULL;
+ }
+
+ ret = pipe2(fds, O_CLOEXEC);
+ if (ret < 0)
+ {
+ // TODO: also report errno maybe?
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to create clipboard pipe fds");
+ return NULL;
+ }
+
+ wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]);
+ close(fds[1]);
+
+ // XXX: this is a huge hack, this function shouldn’t be synchronous!
+ handleEvents(-1);
+
+ while (1)
+ {
+ // Grow the clipboard if we need to paste something bigger, there is no
+ // shrink operation yet.
+ if (len + 4096 > _glfw.wl.clipboardSize)
+ {
+ if (!growClipboardString())
+ {
+ close(fds[0]);
+ return NULL;
+ }
+ }
+
+ // Then read from the fd to the clipboard, handling all known errors.
+ ret = read(fds[0], _glfw.wl.clipboardString + len, 4096);
+ if (ret == 0)
+ break;
+ if (ret == -1 && errno == EINTR)
+ continue;
+ if (ret == -1)
+ {
+ // TODO: also report errno maybe.
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to read from clipboard fd");
+ close(fds[0]);
+ return NULL;
+ }
+ len += ret;
+ }
+ close(fds[0]);
+ if (len + 1 > _glfw.wl.clipboardSize)
+ {
+ if (!growClipboardString())
+ return NULL;
+ }
+ _glfw.wl.clipboardString[len] = '\0';
+ return _glfw.wl.clipboardString;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+ if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_wayland_surface)
+ return;
+
+ extensions[0] = "VK_KHR_surface";
+ extensions[1] = "VK_KHR_wayland_surface";
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
+ vkGetPhysicalDeviceWaylandPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");
+ return VK_NULL_HANDLE;
+ }
+
+ return vkGetPhysicalDeviceWaylandPresentationSupportKHR(device,
+ queuefamily,
+ _glfw.wl.display);
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ VkResult err;
+ VkWaylandSurfaceCreateInfoKHR sci;
+ PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
+
+ vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR");
+ if (!vkCreateWaylandSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
+ sci.display = _glfw.wl.display;
+ sci.surface = window->wl.surface;
+
+ err = vkCreateWaylandSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to create Vulkan surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI struct wl_display* glfwGetWaylandDisplay(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfw.wl.display;
+}
+
+GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return window->wl.surface;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/x11_init.c b/Client/ThirdParty/Box2D/extern/glfw/src/x11_init.c
new file mode 100644
index 0000000..e3e3ad5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/x11_init.c
@@ -0,0 +1,1096 @@
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <X11/Xresource.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <locale.h>
+
+
+// Translate an X11 key code to a GLFW key code.
+//
+static int translateKeyCode(int scancode)
+{
+ int keySym;
+
+ // Valid key code range is [8,255], according to the Xlib manual
+ if (scancode < 8 || scancode > 255)
+ return GLFW_KEY_UNKNOWN;
+
+ if (_glfw.x11.xkb.available)
+ {
+ // Try secondary keysym, for numeric keypad keys
+ // Note: This way we always force "NumLock = ON", which is intentional
+ // since the returned key code should correspond to a physical
+ // location.
+ keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 1);
+ switch (keySym)
+ {
+ case XK_KP_0: return GLFW_KEY_KP_0;
+ case XK_KP_1: return GLFW_KEY_KP_1;
+ case XK_KP_2: return GLFW_KEY_KP_2;
+ case XK_KP_3: return GLFW_KEY_KP_3;
+ case XK_KP_4: return GLFW_KEY_KP_4;
+ case XK_KP_5: return GLFW_KEY_KP_5;
+ case XK_KP_6: return GLFW_KEY_KP_6;
+ case XK_KP_7: return GLFW_KEY_KP_7;
+ case XK_KP_8: return GLFW_KEY_KP_8;
+ case XK_KP_9: return GLFW_KEY_KP_9;
+ case XK_KP_Separator:
+ case XK_KP_Decimal: return GLFW_KEY_KP_DECIMAL;
+ case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
+ case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
+ default: break;
+ }
+
+ // Now try primary keysym for function keys (non-printable keys)
+ // These should not depend on the current keyboard layout
+ keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0);
+ }
+ else
+ {
+ int dummy;
+ KeySym* keySyms;
+
+ keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
+ keySym = keySyms[0];
+ XFree(keySyms);
+ }
+
+ switch (keySym)
+ {
+ case XK_Escape: return GLFW_KEY_ESCAPE;
+ case XK_Tab: return GLFW_KEY_TAB;
+ case XK_Shift_L: return GLFW_KEY_LEFT_SHIFT;
+ case XK_Shift_R: return GLFW_KEY_RIGHT_SHIFT;
+ case XK_Control_L: return GLFW_KEY_LEFT_CONTROL;
+ case XK_Control_R: return GLFW_KEY_RIGHT_CONTROL;
+ case XK_Meta_L:
+ case XK_Alt_L: return GLFW_KEY_LEFT_ALT;
+ case XK_Mode_switch: // Mapped to Alt_R on many keyboards
+ case XK_ISO_Level3_Shift: // AltGr on at least some machines
+ case XK_Meta_R:
+ case XK_Alt_R: return GLFW_KEY_RIGHT_ALT;
+ case XK_Super_L: return GLFW_KEY_LEFT_SUPER;
+ case XK_Super_R: return GLFW_KEY_RIGHT_SUPER;
+ case XK_Menu: return GLFW_KEY_MENU;
+ case XK_Num_Lock: return GLFW_KEY_NUM_LOCK;
+ case XK_Caps_Lock: return GLFW_KEY_CAPS_LOCK;
+ case XK_Print: return GLFW_KEY_PRINT_SCREEN;
+ case XK_Scroll_Lock: return GLFW_KEY_SCROLL_LOCK;
+ case XK_Pause: return GLFW_KEY_PAUSE;
+ case XK_Delete: return GLFW_KEY_DELETE;
+ case XK_BackSpace: return GLFW_KEY_BACKSPACE;
+ case XK_Return: return GLFW_KEY_ENTER;
+ case XK_Home: return GLFW_KEY_HOME;
+ case XK_End: return GLFW_KEY_END;
+ case XK_Page_Up: return GLFW_KEY_PAGE_UP;
+ case XK_Page_Down: return GLFW_KEY_PAGE_DOWN;
+ case XK_Insert: return GLFW_KEY_INSERT;
+ case XK_Left: return GLFW_KEY_LEFT;
+ case XK_Right: return GLFW_KEY_RIGHT;
+ case XK_Down: return GLFW_KEY_DOWN;
+ case XK_Up: return GLFW_KEY_UP;
+ case XK_F1: return GLFW_KEY_F1;
+ case XK_F2: return GLFW_KEY_F2;
+ case XK_F3: return GLFW_KEY_F3;
+ case XK_F4: return GLFW_KEY_F4;
+ case XK_F5: return GLFW_KEY_F5;
+ case XK_F6: return GLFW_KEY_F6;
+ case XK_F7: return GLFW_KEY_F7;
+ case XK_F8: return GLFW_KEY_F8;
+ case XK_F9: return GLFW_KEY_F9;
+ case XK_F10: return GLFW_KEY_F10;
+ case XK_F11: return GLFW_KEY_F11;
+ case XK_F12: return GLFW_KEY_F12;
+ case XK_F13: return GLFW_KEY_F13;
+ case XK_F14: return GLFW_KEY_F14;
+ case XK_F15: return GLFW_KEY_F15;
+ case XK_F16: return GLFW_KEY_F16;
+ case XK_F17: return GLFW_KEY_F17;
+ case XK_F18: return GLFW_KEY_F18;
+ case XK_F19: return GLFW_KEY_F19;
+ case XK_F20: return GLFW_KEY_F20;
+ case XK_F21: return GLFW_KEY_F21;
+ case XK_F22: return GLFW_KEY_F22;
+ case XK_F23: return GLFW_KEY_F23;
+ case XK_F24: return GLFW_KEY_F24;
+ case XK_F25: return GLFW_KEY_F25;
+
+ // Numeric keypad
+ case XK_KP_Divide: return GLFW_KEY_KP_DIVIDE;
+ case XK_KP_Multiply: return GLFW_KEY_KP_MULTIPLY;
+ case XK_KP_Subtract: return GLFW_KEY_KP_SUBTRACT;
+ case XK_KP_Add: return GLFW_KEY_KP_ADD;
+
+ // These should have been detected in secondary keysym test above!
+ case XK_KP_Insert: return GLFW_KEY_KP_0;
+ case XK_KP_End: return GLFW_KEY_KP_1;
+ case XK_KP_Down: return GLFW_KEY_KP_2;
+ case XK_KP_Page_Down: return GLFW_KEY_KP_3;
+ case XK_KP_Left: return GLFW_KEY_KP_4;
+ case XK_KP_Right: return GLFW_KEY_KP_6;
+ case XK_KP_Home: return GLFW_KEY_KP_7;
+ case XK_KP_Up: return GLFW_KEY_KP_8;
+ case XK_KP_Page_Up: return GLFW_KEY_KP_9;
+ case XK_KP_Delete: return GLFW_KEY_KP_DECIMAL;
+ case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
+ case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
+
+ // Last resort: Check for printable keys (should not happen if the XKB
+ // extension is available). This will give a layout dependent mapping
+ // (which is wrong, and we may miss some keys, especially on non-US
+ // keyboards), but it's better than nothing...
+ case XK_a: return GLFW_KEY_A;
+ case XK_b: return GLFW_KEY_B;
+ case XK_c: return GLFW_KEY_C;
+ case XK_d: return GLFW_KEY_D;
+ case XK_e: return GLFW_KEY_E;
+ case XK_f: return GLFW_KEY_F;
+ case XK_g: return GLFW_KEY_G;
+ case XK_h: return GLFW_KEY_H;
+ case XK_i: return GLFW_KEY_I;
+ case XK_j: return GLFW_KEY_J;
+ case XK_k: return GLFW_KEY_K;
+ case XK_l: return GLFW_KEY_L;
+ case XK_m: return GLFW_KEY_M;
+ case XK_n: return GLFW_KEY_N;
+ case XK_o: return GLFW_KEY_O;
+ case XK_p: return GLFW_KEY_P;
+ case XK_q: return GLFW_KEY_Q;
+ case XK_r: return GLFW_KEY_R;
+ case XK_s: return GLFW_KEY_S;
+ case XK_t: return GLFW_KEY_T;
+ case XK_u: return GLFW_KEY_U;
+ case XK_v: return GLFW_KEY_V;
+ case XK_w: return GLFW_KEY_W;
+ case XK_x: return GLFW_KEY_X;
+ case XK_y: return GLFW_KEY_Y;
+ case XK_z: return GLFW_KEY_Z;
+ case XK_1: return GLFW_KEY_1;
+ case XK_2: return GLFW_KEY_2;
+ case XK_3: return GLFW_KEY_3;
+ case XK_4: return GLFW_KEY_4;
+ case XK_5: return GLFW_KEY_5;
+ case XK_6: return GLFW_KEY_6;
+ case XK_7: return GLFW_KEY_7;
+ case XK_8: return GLFW_KEY_8;
+ case XK_9: return GLFW_KEY_9;
+ case XK_0: return GLFW_KEY_0;
+ case XK_space: return GLFW_KEY_SPACE;
+ case XK_minus: return GLFW_KEY_MINUS;
+ case XK_equal: return GLFW_KEY_EQUAL;
+ case XK_bracketleft: return GLFW_KEY_LEFT_BRACKET;
+ case XK_bracketright: return GLFW_KEY_RIGHT_BRACKET;
+ case XK_backslash: return GLFW_KEY_BACKSLASH;
+ case XK_semicolon: return GLFW_KEY_SEMICOLON;
+ case XK_apostrophe: return GLFW_KEY_APOSTROPHE;
+ case XK_grave: return GLFW_KEY_GRAVE_ACCENT;
+ case XK_comma: return GLFW_KEY_COMMA;
+ case XK_period: return GLFW_KEY_PERIOD;
+ case XK_slash: return GLFW_KEY_SLASH;
+ case XK_less: return GLFW_KEY_WORLD_1; // At least in some layouts...
+ default: break;
+ }
+
+ // No matching translation was found
+ return GLFW_KEY_UNKNOWN;
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode, key;
+
+ memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
+ memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
+
+ if (_glfw.x11.xkb.available)
+ {
+ // Use XKB to determine physical key locations independently of the
+ // current keyboard layout
+
+ char name[XkbKeyNameLength + 1];
+ XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);
+ XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc);
+
+ // Find the X11 key code -> GLFW key code mapping
+ for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++)
+ {
+ memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
+ name[XkbKeyNameLength] = '\0';
+
+ // Map the key name to a GLFW key code. Note: We only map printable
+ // keys here, and we use the US keyboard layout. The rest of the
+ // keys (function keys) are mapped using traditional KeySym
+ // translations.
+ if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
+ else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
+ else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
+ else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
+ else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
+ else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
+ else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
+ else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
+ else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
+ else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
+ else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
+ else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
+ else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
+ else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
+ else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
+ else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
+ else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
+ else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
+ else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
+ else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
+ else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
+ else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
+ else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
+ else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
+ else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
+ else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
+ else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
+ else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
+ else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
+ else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
+ else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
+ else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
+ else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
+ else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
+ else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
+ else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
+ else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
+ else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
+ else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
+ else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
+ else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
+ else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
+ else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
+ else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
+ else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
+ else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
+ else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
+ else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
+ else key = GLFW_KEY_UNKNOWN;
+
+ if ((scancode >= 0) && (scancode < 256))
+ _glfw.x11.keycodes[scancode] = key;
+ }
+
+ XkbFreeNames(desc, XkbKeyNamesMask, True);
+ XkbFreeKeyboard(desc, 0, True);
+ }
+
+ for (scancode = 0; scancode < 256; scancode++)
+ {
+ // Translate the un-translated key codes using traditional X11 KeySym
+ // lookups
+ if (_glfw.x11.keycodes[scancode] < 0)
+ _glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
+
+ // Store the reverse translation for faster key name lookup
+ if (_glfw.x11.keycodes[scancode] > 0)
+ _glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
+ }
+}
+
+// Check whether the IM has a usable style
+//
+static GLFWbool hasUsableInputMethodStyle(void)
+{
+ unsigned int i;
+ GLFWbool found = GLFW_FALSE;
+ XIMStyles* styles = NULL;
+
+ if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL)
+ return GLFW_FALSE;
+
+ for (i = 0; i < styles->count_styles; i++)
+ {
+ if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing))
+ {
+ found = GLFW_TRUE;
+ break;
+ }
+ }
+
+ XFree(styles);
+ return found;
+}
+
+// Check whether the specified atom is supported
+//
+static Atom getSupportedAtom(Atom* supportedAtoms,
+ unsigned long atomCount,
+ const char* atomName)
+{
+ unsigned long i;
+ const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
+
+ for (i = 0; i < atomCount; i++)
+ {
+ if (supportedAtoms[i] == atom)
+ return atom;
+ }
+
+ return None;
+}
+
+// Check whether the running window manager is EWMH-compliant
+//
+static void detectEWMH(void)
+{
+ Window* windowFromRoot = NULL;
+ Window* windowFromChild = NULL;
+
+ // First we need a couple of atoms
+ const Atom supportingWmCheck =
+ XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
+ const Atom wmSupported =
+ XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
+
+ // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
+ if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
+ supportingWmCheck,
+ XA_WINDOW,
+ (unsigned char**) &windowFromRoot))
+ {
+ return;
+ }
+
+ _glfwGrabErrorHandlerX11();
+
+ // It should be the ID of a child window (of the root)
+ // Then we look for the same property on the child window
+ if (!_glfwGetWindowPropertyX11(*windowFromRoot,
+ supportingWmCheck,
+ XA_WINDOW,
+ (unsigned char**) &windowFromChild))
+ {
+ XFree(windowFromRoot);
+ return;
+ }
+
+ _glfwReleaseErrorHandlerX11();
+
+ // It should be the ID of that same child window
+ if (*windowFromRoot != *windowFromChild)
+ {
+ XFree(windowFromRoot);
+ XFree(windowFromChild);
+ return;
+ }
+
+ XFree(windowFromRoot);
+ XFree(windowFromChild);
+
+ // We are now fairly sure that an EWMH-compliant window manager is running
+
+ Atom* supportedAtoms;
+ unsigned long atomCount;
+
+ // Now we need to check the _NET_SUPPORTED property of the root window
+ // It should be a list of supported WM protocol and state atoms
+ atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
+ wmSupported,
+ XA_ATOM,
+ (unsigned char**) &supportedAtoms);
+
+ // See which of the atoms we support that are supported by the WM
+ _glfw.x11.NET_WM_STATE =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
+ _glfw.x11.NET_WM_STATE_ABOVE =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE");
+ _glfw.x11.NET_WM_STATE_FULLSCREEN =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ");
+ _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
+ _glfw.x11.NET_WM_WINDOW_TYPE =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
+ _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
+ _glfw.x11.NET_ACTIVE_WINDOW =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
+ _glfw.x11.NET_FRAME_EXTENTS =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS");
+ _glfw.x11.NET_REQUEST_FRAME_EXTENTS =
+ getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
+
+ if (supportedAtoms)
+ XFree(supportedAtoms);
+}
+
+// Look for and initialize supported X11 extensions
+//
+static GLFWbool initExtensions(void)
+{
+ _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
+ if (_glfw.x11.vidmode.handle)
+ {
+ _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
+ _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
+ _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
+ _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
+ _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
+ _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
+ _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
+ _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
+
+ _glfw.x11.vidmode.available =
+ XF86VidModeQueryExtension(_glfw.x11.display,
+ &_glfw.x11.vidmode.eventBase,
+ &_glfw.x11.vidmode.errorBase);
+ }
+
+#if defined(__CYGWIN__)
+ _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
+#else
+ _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
+#endif
+ if (_glfw.x11.xi.handle)
+ {
+ _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
+ _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
+ _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
+ _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
+
+ if (XQueryExtension(_glfw.x11.display,
+ "XInputExtension",
+ &_glfw.x11.xi.majorOpcode,
+ &_glfw.x11.xi.eventBase,
+ &_glfw.x11.xi.errorBase))
+ {
+ _glfw.x11.xi.major = 2;
+ _glfw.x11.xi.minor = 0;
+
+ if (XIQueryVersion(_glfw.x11.display,
+ &_glfw.x11.xi.major,
+ &_glfw.x11.xi.minor) == Success)
+ {
+ _glfw.x11.xi.available = GLFW_TRUE;
+ }
+ }
+ }
+
+#if defined(__CYGWIN__)
+ _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
+#else
+ _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
+#endif
+ if (_glfw.x11.randr.handle)
+ {
+ _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
+ _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
+ _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
+ _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
+ _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
+ _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
+ _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
+ _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
+ _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
+ _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
+ _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
+ _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
+ _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
+ _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
+ _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
+ _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
+ _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
+ _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
+ _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
+
+ if (XRRQueryExtension(_glfw.x11.display,
+ &_glfw.x11.randr.eventBase,
+ &_glfw.x11.randr.errorBase))
+ {
+ if (XRRQueryVersion(_glfw.x11.display,
+ &_glfw.x11.randr.major,
+ &_glfw.x11.randr.minor))
+ {
+ // The GLFW RandR path requires at least version 1.3
+ if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
+ _glfw.x11.randr.available = GLFW_TRUE;
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to query RandR version");
+ }
+ }
+ }
+
+ if (_glfw.x11.randr.available)
+ {
+ XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
+ _glfw.x11.root);
+
+ if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
+ {
+ // This is likely an older Nvidia driver with broken gamma support
+ // Flag it as useless and fall back to xf86vm gamma, if available
+ _glfw.x11.randr.gammaBroken = GLFW_TRUE;
+ }
+
+ if (!sr->ncrtc)
+ {
+ // A system without CRTCs is likely a system with broken RandR
+ // Disable the RandR monitor path and fall back to core functions
+ _glfw.x11.randr.monitorBroken = GLFW_TRUE;
+ }
+
+ XRRFreeScreenResources(sr);
+ }
+
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
+ RROutputChangeNotifyMask);
+ }
+
+#if defined(__CYGWIN__)
+ _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
+#else
+ _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
+#endif
+ if (_glfw.x11.xcursor.handle)
+ {
+ _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
+ _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
+ _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
+ _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
+ _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
+ _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
+ }
+
+#if defined(__CYGWIN__)
+ _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
+#else
+ _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
+#endif
+ if (_glfw.x11.xinerama.handle)
+ {
+ _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
+ _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
+ _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
+ _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
+ _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
+ _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
+
+ if (XineramaQueryExtension(_glfw.x11.display,
+ &_glfw.x11.xinerama.major,
+ &_glfw.x11.xinerama.minor))
+ {
+ if (XineramaIsActive(_glfw.x11.display))
+ _glfw.x11.xinerama.available = GLFW_TRUE;
+ }
+ }
+
+ _glfw.x11.xkb.major = 1;
+ _glfw.x11.xkb.minor = 0;
+ _glfw.x11.xkb.available =
+ XkbQueryExtension(_glfw.x11.display,
+ &_glfw.x11.xkb.majorOpcode,
+ &_glfw.x11.xkb.eventBase,
+ &_glfw.x11.xkb.errorBase,
+ &_glfw.x11.xkb.major,
+ &_glfw.x11.xkb.minor);
+
+ if (_glfw.x11.xkb.available)
+ {
+ Bool supported;
+
+ if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported))
+ {
+ if (supported)
+ _glfw.x11.xkb.detectable = GLFW_TRUE;
+ }
+ }
+
+#if defined(__CYGWIN__)
+ _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
+#else
+ _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
+#endif
+ if (_glfw.x11.x11xcb.handle)
+ {
+ _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
+ _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
+ }
+
+#if defined(__CYGWIN__)
+ _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
+#else
+ _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
+#endif
+ if (_glfw.x11.xrender.handle)
+ {
+ _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
+ _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
+ _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
+ _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
+ _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
+ _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
+
+ if (XRenderQueryExtension(_glfw.x11.display,
+ &_glfw.x11.xrender.errorBase,
+ &_glfw.x11.xrender.eventBase))
+ {
+ if (XRenderQueryVersion(_glfw.x11.display,
+ &_glfw.x11.xrender.major,
+ &_glfw.x11.xrender.minor))
+ {
+ _glfw.x11.xrender.available = GLFW_TRUE;
+ }
+ }
+ }
+
+ // Update the key code LUT
+ // FIXME: We should listen to XkbMapNotify events to track changes to
+ // the keyboard mapping.
+ createKeyTables();
+
+ // Detect whether an EWMH-conformant window manager is running
+ detectEWMH();
+
+ // String format atoms
+ _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
+ _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
+ _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
+
+ // Custom selection property atom
+ _glfw.x11.GLFW_SELECTION =
+ XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False);
+
+ // ICCCM standard clipboard atoms
+ _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
+ _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
+ _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
+ _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
+ _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
+
+ // Clipboard manager atoms
+ _glfw.x11.CLIPBOARD_MANAGER =
+ XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False);
+ _glfw.x11.SAVE_TARGETS =
+ XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False);
+
+ // Xdnd (drag and drop) atoms
+ _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False);
+ _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False);
+ _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False);
+ _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
+ _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
+ _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
+ _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
+ _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
+ _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
+ _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
+
+ // ICCCM, EWMH and Motif window property atoms
+ // These can be set safely even without WM support
+ // The EWMH atoms that require WM support are handled in detectEWMH
+ _glfw.x11.WM_PROTOCOLS =
+ XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False);
+ _glfw.x11.WM_STATE =
+ XInternAtom(_glfw.x11.display, "WM_STATE", False);
+ _glfw.x11.WM_DELETE_WINDOW =
+ XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);
+ _glfw.x11.NET_WM_ICON =
+ XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);
+ _glfw.x11.NET_WM_PING =
+ XInternAtom(_glfw.x11.display, "_NET_WM_PING", False);
+ _glfw.x11.NET_WM_PID =
+ XInternAtom(_glfw.x11.display, "_NET_WM_PID", False);
+ _glfw.x11.NET_WM_NAME =
+ XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False);
+ _glfw.x11.NET_WM_ICON_NAME =
+ XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False);
+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR =
+ XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False);
+ _glfw.x11.NET_WM_WINDOW_OPACITY =
+ XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False);
+ _glfw.x11.MOTIF_WM_HINTS =
+ XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
+
+ // The compositing manager selection name contains the screen number
+ {
+ char name[32];
+ snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen);
+ _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
+ }
+
+ return GLFW_TRUE;
+}
+
+// Retrieve system content scale via folklore heuristics
+//
+static void getSystemContentScale(float* xscale, float* yscale)
+{
+ // NOTE: Fall back to the display-wide DPI instead of RandR monitor DPI if
+ // Xft.dpi retrieval below fails as we don't currently have an exact
+ // policy for which monitor a window is considered to "be on"
+ float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) *
+ 25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
+ float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) *
+ 25.4f / DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
+
+ // NOTE: Basing the scale on Xft.dpi where available should provide the most
+ // consistent user experience (matches Qt, Gtk, etc), although not
+ // always the most accurate one
+ char* rms = XResourceManagerString(_glfw.x11.display);
+ if (rms)
+ {
+ XrmDatabase db = XrmGetStringDatabase(rms);
+ if (db)
+ {
+ XrmValue value;
+ char* type = NULL;
+
+ if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
+ {
+ if (type && strcmp(type, "String") == 0)
+ xdpi = ydpi = atof(value.addr);
+ }
+
+ XrmDestroyDatabase(db);
+ }
+ }
+
+ *xscale = xdpi / 96.f;
+ *yscale = ydpi / 96.f;
+}
+
+// Create a blank cursor for hidden and disabled cursor modes
+//
+static Cursor createHiddenCursor(void)
+{
+ unsigned char pixels[16 * 16 * 4] = { 0 };
+ GLFWimage image = { 16, 16, pixels };
+ return _glfwCreateCursorX11(&image, 0, 0);
+}
+
+// Create a helper window for IPC
+//
+static Window createHelperWindow(void)
+{
+ XSetWindowAttributes wa;
+ wa.event_mask = PropertyChangeMask;
+
+ return XCreateWindow(_glfw.x11.display, _glfw.x11.root,
+ 0, 0, 1, 1, 0, 0,
+ InputOnly,
+ DefaultVisual(_glfw.x11.display, _glfw.x11.screen),
+ CWEventMask, &wa);
+}
+
+// X error handler
+//
+static int errorHandler(Display *display, XErrorEvent* event)
+{
+ _glfw.x11.errorCode = event->error_code;
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Sets the X error handler callback
+//
+void _glfwGrabErrorHandlerX11(void)
+{
+ _glfw.x11.errorCode = Success;
+ XSetErrorHandler(errorHandler);
+}
+
+// Clears the X error handler callback
+//
+void _glfwReleaseErrorHandlerX11(void)
+{
+ // Synchronize to make sure all commands are processed
+ XSync(_glfw.x11.display, False);
+ XSetErrorHandler(NULL);
+}
+
+// Reports the specified error, appending information about the last X error
+//
+void _glfwInputErrorX11(int error, const char* message)
+{
+ char buffer[_GLFW_MESSAGE_SIZE];
+ XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
+ buffer, sizeof(buffer));
+
+ _glfwInputError(error, "%s: %s", message, buffer);
+}
+
+// Creates a native cursor object from the specified image and hotspot
+//
+Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
+{
+ int i;
+ Cursor cursor;
+
+ if (!_glfw.x11.xcursor.handle)
+ return None;
+
+ XcursorImage* native = XcursorImageCreate(image->width, image->height);
+ if (native == NULL)
+ return None;
+
+ native->xhot = xhot;
+ native->yhot = yhot;
+
+ unsigned char* source = (unsigned char*) image->pixels;
+ XcursorPixel* target = native->pixels;
+
+ for (i = 0; i < image->width * image->height; i++, target++, source += 4)
+ {
+ unsigned int alpha = source[3];
+
+ *target = (alpha << 24) |
+ ((unsigned char) ((source[0] * alpha) / 255) << 16) |
+ ((unsigned char) ((source[1] * alpha) / 255) << 8) |
+ ((unsigned char) ((source[2] * alpha) / 255) << 0);
+ }
+
+ cursor = XcursorImageLoadCursor(_glfw.x11.display, native);
+ XcursorImageDestroy(native);
+
+ return cursor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+#if !defined(X_HAVE_UTF8_STRING)
+ // HACK: If the current locale is "C" and the Xlib UTF-8 functions are
+ // unavailable, apply the environment's locale in the hope that it's
+ // both available and not "C"
+ // This is done because the "C" locale breaks wide character input,
+ // which is what we fall back on when UTF-8 support is missing
+ if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
+ setlocale(LC_CTYPE, "");
+#endif
+
+ XInitThreads();
+ XrmInitialize();
+
+ _glfw.x11.display = XOpenDisplay(NULL);
+ if (!_glfw.x11.display)
+ {
+ const char* display = getenv("DISPLAY");
+ if (display)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to open display %s", display);
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: The DISPLAY environment variable is missing");
+ }
+
+ return GLFW_FALSE;
+ }
+
+ _glfw.x11.screen = DefaultScreen(_glfw.x11.display);
+ _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
+ _glfw.x11.context = XUniqueContext();
+
+ getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
+
+ if (!initExtensions())
+ return GLFW_FALSE;
+
+ _glfw.x11.helperWindowHandle = createHelperWindow();
+ _glfw.x11.hiddenCursorHandle = createHiddenCursor();
+
+ if (XSupportsLocale())
+ {
+ XSetLocaleModifiers("");
+
+ _glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
+ if (_glfw.x11.im)
+ {
+ if (!hasUsableInputMethodStyle())
+ {
+ XCloseIM(_glfw.x11.im);
+ _glfw.x11.im = NULL;
+ }
+ }
+ }
+
+#if defined(__linux__)
+ if (!_glfwInitJoysticksLinux())
+ return GLFW_FALSE;
+#endif
+
+ _glfwInitTimerPOSIX();
+
+ _glfwPollMonitorsX11();
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ if (_glfw.x11.helperWindowHandle)
+ {
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
+ _glfw.x11.helperWindowHandle)
+ {
+ _glfwPushSelectionToManagerX11();
+ }
+
+ XDestroyWindow(_glfw.x11.display, _glfw.x11.helperWindowHandle);
+ _glfw.x11.helperWindowHandle = None;
+ }
+
+ if (_glfw.x11.hiddenCursorHandle)
+ {
+ XFreeCursor(_glfw.x11.display, _glfw.x11.hiddenCursorHandle);
+ _glfw.x11.hiddenCursorHandle = (Cursor) 0;
+ }
+
+ free(_glfw.x11.primarySelectionString);
+ free(_glfw.x11.clipboardString);
+
+ if (_glfw.x11.im)
+ {
+ XCloseIM(_glfw.x11.im);
+ _glfw.x11.im = NULL;
+ }
+
+ if (_glfw.x11.display)
+ {
+ XCloseDisplay(_glfw.x11.display);
+ _glfw.x11.display = NULL;
+ }
+
+ if (_glfw.x11.x11xcb.handle)
+ {
+ _glfw_dlclose(_glfw.x11.x11xcb.handle);
+ _glfw.x11.x11xcb.handle = NULL;
+ }
+
+ if (_glfw.x11.xcursor.handle)
+ {
+ _glfw_dlclose(_glfw.x11.xcursor.handle);
+ _glfw.x11.xcursor.handle = NULL;
+ }
+
+ if (_glfw.x11.randr.handle)
+ {
+ _glfw_dlclose(_glfw.x11.randr.handle);
+ _glfw.x11.randr.handle = NULL;
+ }
+
+ if (_glfw.x11.xinerama.handle)
+ {
+ _glfw_dlclose(_glfw.x11.xinerama.handle);
+ _glfw.x11.xinerama.handle = NULL;
+ }
+
+ if (_glfw.x11.xrender.handle)
+ {
+ _glfw_dlclose(_glfw.x11.xrender.handle);
+ _glfw.x11.xrender.handle = NULL;
+ }
+
+ if (_glfw.x11.vidmode.handle)
+ {
+ _glfw_dlclose(_glfw.x11.vidmode.handle);
+ _glfw.x11.vidmode.handle = NULL;
+ }
+
+ if (_glfw.x11.xi.handle)
+ {
+ _glfw_dlclose(_glfw.x11.xi.handle);
+ _glfw.x11.xi.handle = NULL;
+ }
+
+ // NOTE: These need to be unloaded after XCloseDisplay, as they register
+ // cleanup callbacks that get called by that function
+ _glfwTerminateEGL();
+ _glfwTerminateGLX();
+
+#if defined(__linux__)
+ _glfwTerminateJoysticksLinux();
+#endif
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " X11 GLX EGL"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+ " clock_gettime"
+#else
+ " gettimeofday"
+#endif
+#if defined(__linux__)
+ " evdev"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " shared"
+#endif
+ ;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/x11_monitor.c b/Client/ThirdParty/Box2D/extern/glfw/src/x11_monitor.c
new file mode 100644
index 0000000..df53041
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/x11_monitor.c
@@ -0,0 +1,517 @@
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// Check whether the display mode should be included in enumeration
+//
+static GLFWbool modeIsGood(const XRRModeInfo* mi)
+{
+ return (mi->modeFlags & RR_Interlace) == 0;
+}
+
+// Calculates the refresh rate, in Hz, from the specified RandR mode info
+//
+static int calculateRefreshRate(const XRRModeInfo* mi)
+{
+ if (mi->hTotal && mi->vTotal)
+ return (int) ((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
+ else
+ return 0;
+}
+
+// Returns the mode info for a RandR mode XID
+//
+static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
+{
+ int i;
+
+ for (i = 0; i < sr->nmode; i++)
+ {
+ if (sr->modes[i].id == id)
+ return sr->modes + i;
+ }
+
+ return NULL;
+}
+
+// Convert RandR mode info to GLFW video mode
+//
+static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
+ const XRRCrtcInfo* ci)
+{
+ GLFWvidmode mode;
+
+ if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
+ {
+ mode.width = mi->height;
+ mode.height = mi->width;
+ }
+ else
+ {
+ mode.width = mi->width;
+ mode.height = mi->height;
+ }
+
+ mode.refreshRate = calculateRefreshRate(mi);
+
+ _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
+ &mode.redBits, &mode.greenBits, &mode.blueBits);
+
+ return mode;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Poll for changes in the set of connected monitors
+//
+void _glfwPollMonitorsX11(void)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ int i, j, disconnectedCount, screenCount = 0;
+ _GLFWmonitor** disconnected = NULL;
+ XineramaScreenInfo* screens = NULL;
+ XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
+ _glfw.x11.root);
+ RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
+ _glfw.x11.root);
+
+ if (_glfw.x11.xinerama.available)
+ screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
+
+ disconnectedCount = _glfw.monitorCount;
+ if (disconnectedCount)
+ {
+ disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
+ memcpy(disconnected,
+ _glfw.monitors,
+ _glfw.monitorCount * sizeof(_GLFWmonitor*));
+ }
+
+ for (i = 0; i < sr->noutput; i++)
+ {
+ int type, widthMM, heightMM;
+ XRROutputInfo* oi;
+ XRRCrtcInfo* ci;
+ _GLFWmonitor* monitor;
+
+ oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
+ if (oi->connection != RR_Connected || oi->crtc == None)
+ {
+ XRRFreeOutputInfo(oi);
+ continue;
+ }
+
+ for (j = 0; j < disconnectedCount; j++)
+ {
+ if (disconnected[j] &&
+ disconnected[j]->x11.output == sr->outputs[i])
+ {
+ disconnected[j] = NULL;
+ break;
+ }
+ }
+
+ if (j < disconnectedCount)
+ {
+ XRRFreeOutputInfo(oi);
+ continue;
+ }
+
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
+ if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
+ {
+ widthMM = oi->mm_height;
+ heightMM = oi->mm_width;
+ }
+ else
+ {
+ widthMM = oi->mm_width;
+ heightMM = oi->mm_height;
+ }
+
+ monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
+ monitor->x11.output = sr->outputs[i];
+ monitor->x11.crtc = oi->crtc;
+
+ for (j = 0; j < screenCount; j++)
+ {
+ if (screens[j].x_org == ci->x &&
+ screens[j].y_org == ci->y &&
+ screens[j].width == ci->width &&
+ screens[j].height == ci->height)
+ {
+ monitor->x11.index = j;
+ break;
+ }
+ }
+
+ if (monitor->x11.output == primary)
+ type = _GLFW_INSERT_FIRST;
+ else
+ type = _GLFW_INSERT_LAST;
+
+ _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
+
+ XRRFreeOutputInfo(oi);
+ XRRFreeCrtcInfo(ci);
+ }
+
+ XRRFreeScreenResources(sr);
+
+ if (screens)
+ XFree(screens);
+
+ for (i = 0; i < disconnectedCount; i++)
+ {
+ if (disconnected[i])
+ _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
+ }
+
+ free(disconnected);
+ }
+ else
+ {
+ const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
+ const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
+
+ _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
+ GLFW_CONNECTED,
+ _GLFW_INSERT_FIRST);
+ }
+}
+
+// Set the current video mode for the specified monitor
+//
+void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+ XRROutputInfo* oi;
+ GLFWvidmode current;
+ const GLFWvidmode* best;
+ RRMode native = None;
+ int i;
+
+ best = _glfwChooseVideoMode(monitor, desired);
+ _glfwPlatformGetVideoMode(monitor, &current);
+ if (_glfwCompareVideoModes(&current, best) == 0)
+ return;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+ oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
+
+ for (i = 0; i < oi->nmode; i++)
+ {
+ const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
+ if (!modeIsGood(mi))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
+ if (_glfwCompareVideoModes(best, &mode) == 0)
+ {
+ native = mi->id;
+ break;
+ }
+ }
+
+ if (native)
+ {
+ if (monitor->x11.oldMode == None)
+ monitor->x11.oldMode = ci->mode;
+
+ XRRSetCrtcConfig(_glfw.x11.display,
+ sr, monitor->x11.crtc,
+ CurrentTime,
+ ci->x, ci->y,
+ native,
+ ci->rotation,
+ ci->outputs,
+ ci->noutput);
+ }
+
+ XRRFreeOutputInfo(oi);
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+ }
+}
+
+// Restore the saved (original) video mode for the specified monitor
+//
+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+
+ if (monitor->x11.oldMode == None)
+ return;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+ XRRSetCrtcConfig(_glfw.x11.display,
+ sr, monitor->x11.crtc,
+ CurrentTime,
+ ci->x, ci->y,
+ monitor->x11.oldMode,
+ ci->rotation,
+ ci->outputs,
+ ci->noutput);
+
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+
+ monitor->x11.oldMode = None;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+ if (xpos)
+ *xpos = ci->x;
+ if (ypos)
+ *ypos = ci->y;
+
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+ }
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+ float* xscale, float* yscale)
+{
+ if (xscale)
+ *xscale = _glfw.x11.contentScaleX;
+ if (yscale)
+ *yscale = _glfw.x11.contentScaleY;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+ GLFWvidmode* result;
+
+ *count = 0;
+
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ int i, j;
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+ XRROutputInfo* oi;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+ oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
+
+ result = calloc(oi->nmode, sizeof(GLFWvidmode));
+
+ for (i = 0; i < oi->nmode; i++)
+ {
+ const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
+ if (!modeIsGood(mi))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
+
+ for (j = 0; j < *count; j++)
+ {
+ if (_glfwCompareVideoModes(result + j, &mode) == 0)
+ break;
+ }
+
+ // Skip duplicate modes
+ if (j < *count)
+ continue;
+
+ (*count)++;
+ result[*count - 1] = mode;
+ }
+
+ XRRFreeOutputInfo(oi);
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+ }
+ else
+ {
+ *count = 1;
+ result = calloc(1, sizeof(GLFWvidmode));
+ _glfwPlatformGetVideoMode(monitor, result);
+ }
+
+ return result;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+ *mode = vidmodeFromModeInfo(getModeInfo(sr, ci->mode), ci);
+
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+ }
+ else
+ {
+ mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
+ mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
+ mode->refreshRate = 0;
+
+ _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
+ &mode->redBits, &mode->greenBits, &mode->blueBits);
+ }
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
+ {
+ const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
+ monitor->x11.crtc);
+ XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
+ monitor->x11.crtc);
+
+ _glfwAllocGammaArrays(ramp, size);
+
+ memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
+ memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
+ memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
+
+ XRRFreeGamma(gamma);
+ return GLFW_TRUE;
+ }
+ else if (_glfw.x11.vidmode.available)
+ {
+ int size;
+ XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
+
+ _glfwAllocGammaArrays(ramp, size);
+
+ XF86VidModeGetGammaRamp(_glfw.x11.display,
+ _glfw.x11.screen,
+ ramp->size, ramp->red, ramp->green, ramp->blue);
+ return GLFW_TRUE;
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Gamma ramp access not supported by server");
+ return GLFW_FALSE;
+ }
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
+ {
+ if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Gamma ramp size must match current ramp size");
+ return;
+ }
+
+ XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
+
+ memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
+ memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
+ memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
+
+ XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
+ XRRFreeGamma(gamma);
+ }
+ else if (_glfw.x11.vidmode.available)
+ {
+ XF86VidModeSetGammaRamp(_glfw.x11.display,
+ _glfw.x11.screen,
+ ramp->size,
+ (unsigned short*) ramp->red,
+ (unsigned short*) ramp->green,
+ (unsigned short*) ramp->blue);
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Gamma ramp access not supported by server");
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(None);
+ return monitor->x11.crtc;
+}
+
+GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(None);
+ return monitor->x11.output;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/x11_platform.h b/Client/ThirdParty/Box2D/extern/glfw/src/x11_platform.h
new file mode 100644
index 0000000..c37c740
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/x11_platform.h
@@ -0,0 +1,444 @@
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdint.h>
+#include <dlfcn.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xcursor/Xcursor.h>
+
+// The XRandR extension provides mode setting and gamma control
+#include <X11/extensions/Xrandr.h>
+
+// The Xkb extension provides improved keyboard support
+#include <X11/XKBlib.h>
+
+// The Xinerama extension provides legacy monitor indices
+#include <X11/extensions/Xinerama.h>
+
+// The XInput extension provides raw mouse motion input
+#include <X11/extensions/XInput2.h>
+
+typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
+typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
+typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
+typedef void (* PFN_XRRFreeOutputInfo)(XRROutputInfo*);
+typedef void (* PFN_XRRFreeScreenResources)(XRRScreenResources*);
+typedef XRRCrtcGamma* (* PFN_XRRGetCrtcGamma)(Display*,RRCrtc);
+typedef int (* PFN_XRRGetCrtcGammaSize)(Display*,RRCrtc);
+typedef XRRCrtcInfo* (* PFN_XRRGetCrtcInfo) (Display*,XRRScreenResources*,RRCrtc);
+typedef XRROutputInfo* (* PFN_XRRGetOutputInfo)(Display*,XRRScreenResources*,RROutput);
+typedef RROutput (* PFN_XRRGetOutputPrimary)(Display*,Window);
+typedef XRRScreenResources* (* PFN_XRRGetScreenResourcesCurrent)(Display*,Window);
+typedef Bool (* PFN_XRRQueryExtension)(Display*,int*,int*);
+typedef Status (* PFN_XRRQueryVersion)(Display*,int*,int*);
+typedef void (* PFN_XRRSelectInput)(Display*,Window,int);
+typedef Status (* PFN_XRRSetCrtcConfig)(Display*,XRRScreenResources*,RRCrtc,Time,int,int,RRMode,Rotation,RROutput*,int);
+typedef void (* PFN_XRRSetCrtcGamma)(Display*,RRCrtc,XRRCrtcGamma*);
+typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
+#define XRRAllocGamma _glfw.x11.randr.AllocGamma
+#define XRRFreeCrtcInfo _glfw.x11.randr.FreeCrtcInfo
+#define XRRFreeGamma _glfw.x11.randr.FreeGamma
+#define XRRFreeOutputInfo _glfw.x11.randr.FreeOutputInfo
+#define XRRFreeScreenResources _glfw.x11.randr.FreeScreenResources
+#define XRRGetCrtcGamma _glfw.x11.randr.GetCrtcGamma
+#define XRRGetCrtcGammaSize _glfw.x11.randr.GetCrtcGammaSize
+#define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
+#define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
+#define XRRGetOutputPrimary _glfw.x11.randr.GetOutputPrimary
+#define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
+#define XRRQueryExtension _glfw.x11.randr.QueryExtension
+#define XRRQueryVersion _glfw.x11.randr.QueryVersion
+#define XRRSelectInput _glfw.x11.randr.SelectInput
+#define XRRSetCrtcConfig _glfw.x11.randr.SetCrtcConfig
+#define XRRSetCrtcGamma _glfw.x11.randr.SetCrtcGamma
+#define XRRUpdateConfiguration _glfw.x11.randr.UpdateConfiguration
+
+typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
+typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
+typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
+#define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
+#define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
+#define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
+
+typedef Bool (* PFN_XineramaIsActive)(Display*);
+typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
+typedef XineramaScreenInfo* (* PFN_XineramaQueryScreens)(Display*,int*);
+#define XineramaIsActive _glfw.x11.xinerama.IsActive
+#define XineramaQueryExtension _glfw.x11.xinerama.QueryExtension
+#define XineramaQueryScreens _glfw.x11.xinerama.QueryScreens
+
+typedef XID xcb_window_t;
+typedef XID xcb_visualid_t;
+typedef struct xcb_connection_t xcb_connection_t;
+typedef xcb_connection_t* (* PFN_XGetXCBConnection)(Display*);
+#define XGetXCBConnection _glfw.x11.x11xcb.GetXCBConnection
+
+typedef Bool (* PFN_XF86VidModeQueryExtension)(Display*,int*,int*);
+typedef Bool (* PFN_XF86VidModeGetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
+typedef Bool (* PFN_XF86VidModeSetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
+typedef Bool (* PFN_XF86VidModeGetGammaRampSize)(Display*,int,int*);
+#define XF86VidModeQueryExtension _glfw.x11.vidmode.QueryExtension
+#define XF86VidModeGetGammaRamp _glfw.x11.vidmode.GetGammaRamp
+#define XF86VidModeSetGammaRamp _glfw.x11.vidmode.SetGammaRamp
+#define XF86VidModeGetGammaRampSize _glfw.x11.vidmode.GetGammaRampSize
+
+typedef Status (* PFN_XIQueryVersion)(Display*,int*,int*);
+typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
+#define XIQueryVersion _glfw.x11.xi.QueryVersion
+#define XISelectEvents _glfw.x11.xi.SelectEvents
+
+typedef Bool (* PFN_XRenderQueryExtension)(Display*,int*,int*);
+typedef Status (* PFN_XRenderQueryVersion)(Display*dpy,int*,int*);
+typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const*);
+#define XRenderQueryExtension _glfw.x11.xrender.QueryExtension
+#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
+#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
+
+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
+typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
+
+typedef struct VkXlibSurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkXlibSurfaceCreateFlagsKHR flags;
+ Display* dpy;
+ Window window;
+} VkXlibSurfaceCreateInfoKHR;
+
+typedef struct VkXcbSurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkXcbSurfaceCreateFlagsKHR flags;
+ xcb_connection_t* connection;
+ xcb_window_t window;
+} VkXcbSurfaceCreateInfoKHR;
+
+typedef VkResult (APIENTRY *PFN_vkCreateXlibSurfaceKHR)(VkInstance,const VkXlibSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice,uint32_t,Display*,VisualID);
+typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
+
+#include "posix_thread.h"
+#include "posix_time.h"
+#include "xkb_unicode.h"
+#include "glx_context.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+#if defined(__linux__)
+#include "linux_joystick.h"
+#else
+#include "null_joystick.h"
+#endif
+
+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+#define _glfw_dlclose(handle) dlclose(handle)
+#define _glfw_dlsym(handle, name) dlsym(handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11
+
+
+// X11-specific per-window data
+//
+typedef struct _GLFWwindowX11
+{
+ Colormap colormap;
+ Window handle;
+ XIC ic;
+
+ GLFWbool overrideRedirect;
+ GLFWbool iconified;
+ GLFWbool maximized;
+
+ // Whether the visual supports framebuffer transparency
+ GLFWbool transparent;
+
+ // Cached position and size used to filter out duplicate events
+ int width, height;
+ int xpos, ypos;
+
+ // The last received cursor position, regardless of source
+ int lastCursorPosX, lastCursorPosY;
+ // The last position the cursor was warped to by GLFW
+ int warpCursorPosX, warpCursorPosY;
+
+ // The time of the last KeyPress event
+ Time lastKeyTime;
+
+} _GLFWwindowX11;
+
+// X11-specific global data
+//
+typedef struct _GLFWlibraryX11
+{
+ Display* display;
+ int screen;
+ Window root;
+
+ // System content scale
+ float contentScaleX, contentScaleY;
+ // Helper window for IPC
+ Window helperWindowHandle;
+ // Invisible cursor for hidden cursor mode
+ Cursor hiddenCursorHandle;
+ // Context for mapping window XIDs to _GLFWwindow pointers
+ XContext context;
+ // XIM input method
+ XIM im;
+ // Most recent error code received by X error handler
+ int errorCode;
+ // Primary selection string (while the primary selection is owned)
+ char* primarySelectionString;
+ // Clipboard string (while the selection is owned)
+ char* clipboardString;
+ // Key name string
+ char keyName[5];
+ // X11 keycode to GLFW key LUT
+ short int keycodes[256];
+ // GLFW key to X11 keycode LUT
+ short int scancodes[GLFW_KEY_LAST + 1];
+ // Where to place the cursor when re-enabled
+ double restoreCursorPosX, restoreCursorPosY;
+ // The window whose disabled cursor mode is active
+ _GLFWwindow* disabledCursorWindow;
+
+ // Window manager atoms
+ Atom WM_PROTOCOLS;
+ Atom WM_STATE;
+ Atom WM_DELETE_WINDOW;
+ Atom NET_WM_NAME;
+ Atom NET_WM_ICON_NAME;
+ Atom NET_WM_ICON;
+ Atom NET_WM_PID;
+ Atom NET_WM_PING;
+ Atom NET_WM_WINDOW_TYPE;
+ Atom NET_WM_WINDOW_TYPE_NORMAL;
+ Atom NET_WM_STATE;
+ Atom NET_WM_STATE_ABOVE;
+ Atom NET_WM_STATE_FULLSCREEN;
+ Atom NET_WM_STATE_MAXIMIZED_VERT;
+ Atom NET_WM_STATE_MAXIMIZED_HORZ;
+ Atom NET_WM_STATE_DEMANDS_ATTENTION;
+ Atom NET_WM_BYPASS_COMPOSITOR;
+ Atom NET_WM_FULLSCREEN_MONITORS;
+ Atom NET_WM_WINDOW_OPACITY;
+ Atom NET_WM_CM_Sx;
+ Atom NET_ACTIVE_WINDOW;
+ Atom NET_FRAME_EXTENTS;
+ Atom NET_REQUEST_FRAME_EXTENTS;
+ Atom MOTIF_WM_HINTS;
+
+ // Xdnd (drag and drop) atoms
+ Atom XdndAware;
+ Atom XdndEnter;
+ Atom XdndPosition;
+ Atom XdndStatus;
+ Atom XdndActionCopy;
+ Atom XdndDrop;
+ Atom XdndFinished;
+ Atom XdndSelection;
+ Atom XdndTypeList;
+ Atom text_uri_list;
+
+ // Selection (clipboard) atoms
+ Atom TARGETS;
+ Atom MULTIPLE;
+ Atom INCR;
+ Atom CLIPBOARD;
+ Atom PRIMARY;
+ Atom CLIPBOARD_MANAGER;
+ Atom SAVE_TARGETS;
+ Atom NULL_;
+ Atom UTF8_STRING;
+ Atom COMPOUND_STRING;
+ Atom ATOM_PAIR;
+ Atom GLFW_SELECTION;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ int eventBase;
+ int errorBase;
+ int major;
+ int minor;
+ GLFWbool gammaBroken;
+ GLFWbool monitorBroken;
+ PFN_XRRAllocGamma AllocGamma;
+ PFN_XRRFreeCrtcInfo FreeCrtcInfo;
+ PFN_XRRFreeGamma FreeGamma;
+ PFN_XRRFreeOutputInfo FreeOutputInfo;
+ PFN_XRRFreeScreenResources FreeScreenResources;
+ PFN_XRRGetCrtcGamma GetCrtcGamma;
+ PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
+ PFN_XRRGetCrtcInfo GetCrtcInfo;
+ PFN_XRRGetOutputInfo GetOutputInfo;
+ PFN_XRRGetOutputPrimary GetOutputPrimary;
+ PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
+ PFN_XRRQueryExtension QueryExtension;
+ PFN_XRRQueryVersion QueryVersion;
+ PFN_XRRSelectInput SelectInput;
+ PFN_XRRSetCrtcConfig SetCrtcConfig;
+ PFN_XRRSetCrtcGamma SetCrtcGamma;
+ PFN_XRRUpdateConfiguration UpdateConfiguration;
+ } randr;
+
+ struct {
+ GLFWbool available;
+ GLFWbool detectable;
+ int majorOpcode;
+ int eventBase;
+ int errorBase;
+ int major;
+ int minor;
+ } xkb;
+
+ struct {
+ int count;
+ int timeout;
+ int interval;
+ int blanking;
+ int exposure;
+ } saver;
+
+ struct {
+ int version;
+ Window source;
+ Atom format;
+ } xdnd;
+
+ struct {
+ void* handle;
+ PFN_XcursorImageCreate ImageCreate;
+ PFN_XcursorImageDestroy ImageDestroy;
+ PFN_XcursorImageLoadCursor ImageLoadCursor;
+ } xcursor;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ int major;
+ int minor;
+ PFN_XineramaIsActive IsActive;
+ PFN_XineramaQueryExtension QueryExtension;
+ PFN_XineramaQueryScreens QueryScreens;
+ } xinerama;
+
+ struct {
+ void* handle;
+ PFN_XGetXCBConnection GetXCBConnection;
+ } x11xcb;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ int eventBase;
+ int errorBase;
+ PFN_XF86VidModeQueryExtension QueryExtension;
+ PFN_XF86VidModeGetGammaRamp GetGammaRamp;
+ PFN_XF86VidModeSetGammaRamp SetGammaRamp;
+ PFN_XF86VidModeGetGammaRampSize GetGammaRampSize;
+ } vidmode;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ int majorOpcode;
+ int eventBase;
+ int errorBase;
+ int major;
+ int minor;
+ PFN_XIQueryVersion QueryVersion;
+ PFN_XISelectEvents SelectEvents;
+ } xi;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ int major;
+ int minor;
+ int eventBase;
+ int errorBase;
+ PFN_XRenderQueryExtension QueryExtension;
+ PFN_XRenderQueryVersion QueryVersion;
+ PFN_XRenderFindVisualFormat FindVisualFormat;
+ } xrender;
+
+} _GLFWlibraryX11;
+
+// X11-specific per-monitor data
+//
+typedef struct _GLFWmonitorX11
+{
+ RROutput output;
+ RRCrtc crtc;
+ RRMode oldMode;
+
+ // Index of corresponding Xinerama screen,
+ // for EWMH full screen window placement
+ int index;
+
+} _GLFWmonitorX11;
+
+// X11-specific per-cursor data
+//
+typedef struct _GLFWcursorX11
+{
+ Cursor handle;
+
+} _GLFWcursorX11;
+
+
+void _glfwPollMonitorsX11(void);
+void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
+
+Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);
+
+unsigned long _glfwGetWindowPropertyX11(Window window,
+ Atom property,
+ Atom type,
+ unsigned char** value);
+GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
+
+void _glfwGrabErrorHandlerX11(void);
+void _glfwReleaseErrorHandlerX11(void);
+void _glfwInputErrorX11(int error, const char* message);
+
+void _glfwPushSelectionToManagerX11(void);
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/x11_window.c b/Client/ThirdParty/Box2D/extern/glfw/src/x11_window.c
new file mode 100644
index 0000000..19ed737
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/x11_window.c
@@ -0,0 +1,3066 @@
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <X11/cursorfont.h>
+#include <X11/Xmd.h>
+
+#include <sys/select.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+
+// Action for EWMH client messages
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
+#define _NET_WM_STATE_TOGGLE 2
+
+// Additional mouse button names for XButtonEvent
+#define Button6 6
+#define Button7 7
+
+#define _GLFW_XDND_VERSION 5
+
+
+// Wait for data to arrive using select
+// This avoids blocking other threads via the per-display Xlib lock that also
+// covers GLX functions
+//
+static GLFWbool waitForEvent(double* timeout)
+{
+ fd_set fds;
+ const int fd = ConnectionNumber(_glfw.x11.display);
+ int count = fd + 1;
+
+#if defined(__linux__)
+ if (_glfw.linjs.inotify > fd)
+ count = _glfw.linjs.inotify + 1;
+#endif
+ for (;;)
+ {
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+#if defined(__linux__)
+ if (_glfw.linjs.inotify > 0)
+ FD_SET(_glfw.linjs.inotify, &fds);
+#endif
+
+ if (timeout)
+ {
+ const long seconds = (long) *timeout;
+ const long microseconds = (long) ((*timeout - seconds) * 1e6);
+ struct timeval tv = { seconds, microseconds };
+ const uint64_t base = _glfwPlatformGetTimerValue();
+
+ const int result = select(count, &fds, NULL, NULL, &tv);
+ const int error = errno;
+
+ *timeout -= (_glfwPlatformGetTimerValue() - base) /
+ (double) _glfwPlatformGetTimerFrequency();
+
+ if (result > 0)
+ return GLFW_TRUE;
+ if ((result == -1 && error == EINTR) || *timeout <= 0.0)
+ return GLFW_FALSE;
+ }
+ else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
+ return GLFW_TRUE;
+ }
+}
+
+// Waits until a VisibilityNotify event arrives for the specified window or the
+// timeout period elapses (ICCCM section 4.2.2)
+//
+static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
+{
+ XEvent dummy;
+ double timeout = 0.1;
+
+ while (!XCheckTypedWindowEvent(_glfw.x11.display,
+ window->x11.handle,
+ VisibilityNotify,
+ &dummy))
+ {
+ if (!waitForEvent(&timeout))
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Returns whether the window is iconified
+//
+static int getWindowState(_GLFWwindow* window)
+{
+ int result = WithdrawnState;
+ struct {
+ CARD32 state;
+ Window icon;
+ } *state = NULL;
+
+ if (_glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.WM_STATE,
+ _glfw.x11.WM_STATE,
+ (unsigned char**) &state) >= 2)
+ {
+ result = state->state;
+ }
+
+ if (state)
+ XFree(state);
+
+ return result;
+}
+
+// Returns whether the event is a selection event
+//
+static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
+{
+ if (event->xany.window != _glfw.x11.helperWindowHandle)
+ return False;
+
+ return event->type == SelectionRequest ||
+ event->type == SelectionNotify ||
+ event->type == SelectionClear;
+}
+
+// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window
+//
+static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer)
+{
+ _GLFWwindow* window = (_GLFWwindow*) pointer;
+ return event->type == PropertyNotify &&
+ event->xproperty.state == PropertyNewValue &&
+ event->xproperty.window == window->x11.handle &&
+ event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;
+}
+
+// Returns whether it is a property event for the specified selection transfer
+//
+static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer)
+{
+ XEvent* notification = (XEvent*) pointer;
+ return event->type == PropertyNotify &&
+ event->xproperty.state == PropertyNewValue &&
+ event->xproperty.window == notification->xselection.requestor &&
+ event->xproperty.atom == notification->xselection.property;
+}
+
+// Translates an X event modifier state mask
+//
+static int translateState(int state)
+{
+ int mods = 0;
+
+ if (state & ShiftMask)
+ mods |= GLFW_MOD_SHIFT;
+ if (state & ControlMask)
+ mods |= GLFW_MOD_CONTROL;
+ if (state & Mod1Mask)
+ mods |= GLFW_MOD_ALT;
+ if (state & Mod4Mask)
+ mods |= GLFW_MOD_SUPER;
+ if (state & LockMask)
+ mods |= GLFW_MOD_CAPS_LOCK;
+ if (state & Mod2Mask)
+ mods |= GLFW_MOD_NUM_LOCK;
+
+ return mods;
+}
+
+// Translates an X11 key code to a GLFW key token
+//
+static int translateKey(int scancode)
+{
+ // Use the pre-filled LUT (see createKeyTables() in x11_init.c)
+ if (scancode < 0 || scancode > 255)
+ return GLFW_KEY_UNKNOWN;
+
+ return _glfw.x11.keycodes[scancode];
+}
+
+// Sends an EWMH or ICCCM event to the window manager
+//
+static void sendEventToWM(_GLFWwindow* window, Atom type,
+ long a, long b, long c, long d, long e)
+{
+ XEvent event;
+ memset(&event, 0, sizeof(event));
+
+ event.type = ClientMessage;
+ event.xclient.window = window->x11.handle;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = type;
+ event.xclient.data.l[0] = a;
+ event.xclient.data.l[1] = b;
+ event.xclient.data.l[2] = c;
+ event.xclient.data.l[3] = d;
+ event.xclient.data.l[4] = e;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event);
+}
+
+// Updates the normal hints according to the window settings
+//
+static void updateNormalHints(_GLFWwindow* window, int width, int height)
+{
+ XSizeHints* hints = XAllocSizeHints();
+
+ if (!window->monitor)
+ {
+ if (window->resizable)
+ {
+ if (window->minwidth != GLFW_DONT_CARE &&
+ window->minheight != GLFW_DONT_CARE)
+ {
+ hints->flags |= PMinSize;
+ hints->min_width = window->minwidth;
+ hints->min_height = window->minheight;
+ }
+
+ if (window->maxwidth != GLFW_DONT_CARE &&
+ window->maxheight != GLFW_DONT_CARE)
+ {
+ hints->flags |= PMaxSize;
+ hints->max_width = window->maxwidth;
+ hints->max_height = window->maxheight;
+ }
+
+ if (window->numer != GLFW_DONT_CARE &&
+ window->denom != GLFW_DONT_CARE)
+ {
+ hints->flags |= PAspect;
+ hints->min_aspect.x = hints->max_aspect.x = window->numer;
+ hints->min_aspect.y = hints->max_aspect.y = window->denom;
+ }
+ }
+ else
+ {
+ hints->flags |= (PMinSize | PMaxSize);
+ hints->min_width = hints->max_width = width;
+ hints->min_height = hints->max_height = height;
+ }
+ }
+
+ hints->flags |= PWinGravity;
+ hints->win_gravity = StaticGravity;
+
+ XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
+ XFree(hints);
+}
+
+// Updates the full screen status of the window
+//
+static void updateWindowMode(_GLFWwindow* window)
+{
+ if (window->monitor)
+ {
+ if (_glfw.x11.xinerama.available &&
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS,
+ window->monitor->x11.index,
+ window->monitor->x11.index,
+ window->monitor->x11.index,
+ window->monitor->x11.index,
+ 0);
+ }
+
+ if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_ADD,
+ _glfw.x11.NET_WM_STATE_FULLSCREEN,
+ 0, 1, 0);
+ }
+ else
+ {
+ // This is the butcher's way of removing window decorations
+ // Setting the override-redirect attribute on a window makes the
+ // window manager ignore the window completely (ICCCM, section 4)
+ // The good thing is that this makes undecorated full screen windows
+ // easy to do; the bad thing is that we have to do everything
+ // manually and some things (like iconify/restore) won't work at
+ // all, as those are tasks usually performed by the window manager
+
+ XSetWindowAttributes attributes;
+ attributes.override_redirect = True;
+ XChangeWindowAttributes(_glfw.x11.display,
+ window->x11.handle,
+ CWOverrideRedirect,
+ &attributes);
+
+ window->x11.overrideRedirect = GLFW_TRUE;
+ }
+
+ // Enable compositor bypass
+ if (!window->x11.transparent)
+ {
+ const unsigned long value = 1;
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*) &value, 1);
+ }
+ }
+ else
+ {
+ if (_glfw.x11.xinerama.available &&
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
+ {
+ XDeleteProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS);
+ }
+
+ if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_REMOVE,
+ _glfw.x11.NET_WM_STATE_FULLSCREEN,
+ 0, 1, 0);
+ }
+ else
+ {
+ XSetWindowAttributes attributes;
+ attributes.override_redirect = False;
+ XChangeWindowAttributes(_glfw.x11.display,
+ window->x11.handle,
+ CWOverrideRedirect,
+ &attributes);
+
+ window->x11.overrideRedirect = GLFW_FALSE;
+ }
+
+ // Disable compositor bypass
+ if (!window->x11.transparent)
+ {
+ XDeleteProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR);
+ }
+ }
+}
+
+// Splits and translates a text/uri-list into separate file paths
+// NOTE: This function destroys the provided string
+//
+static char** parseUriList(char* text, int* count)
+{
+ const char* prefix = "file://";
+ char** paths = NULL;
+ char* line;
+
+ *count = 0;
+
+ while ((line = strtok(text, "\r\n")))
+ {
+ text = NULL;
+
+ if (line[0] == '#')
+ continue;
+
+ if (strncmp(line, prefix, strlen(prefix)) == 0)
+ {
+ line += strlen(prefix);
+ // TODO: Validate hostname
+ while (*line != '/')
+ line++;
+ }
+
+ (*count)++;
+
+ char* path = calloc(strlen(line) + 1, 1);
+ paths = realloc(paths, *count * sizeof(char*));
+ paths[*count - 1] = path;
+
+ while (*line)
+ {
+ if (line[0] == '%' && line[1] && line[2])
+ {
+ const char digits[3] = { line[1], line[2], '\0' };
+ *path = strtol(digits, NULL, 16);
+ line += 2;
+ }
+ else
+ *path = *line;
+
+ path++;
+ line++;
+ }
+ }
+
+ return paths;
+}
+
+// Encode a Unicode code point to a UTF-8 stream
+// Based on cutef8 by Jeff Bezanson (Public Domain)
+//
+static size_t encodeUTF8(char* s, unsigned int ch)
+{
+ size_t count = 0;
+
+ if (ch < 0x80)
+ s[count++] = (char) ch;
+ else if (ch < 0x800)
+ {
+ s[count++] = (ch >> 6) | 0xc0;
+ s[count++] = (ch & 0x3f) | 0x80;
+ }
+ else if (ch < 0x10000)
+ {
+ s[count++] = (ch >> 12) | 0xe0;
+ s[count++] = ((ch >> 6) & 0x3f) | 0x80;
+ s[count++] = (ch & 0x3f) | 0x80;
+ }
+ else if (ch < 0x110000)
+ {
+ s[count++] = (ch >> 18) | 0xf0;
+ s[count++] = ((ch >> 12) & 0x3f) | 0x80;
+ s[count++] = ((ch >> 6) & 0x3f) | 0x80;
+ s[count++] = (ch & 0x3f) | 0x80;
+ }
+
+ return count;
+}
+
+// Decode a Unicode code point from a UTF-8 stream
+// Based on cutef8 by Jeff Bezanson (Public Domain)
+//
+#if defined(X_HAVE_UTF8_STRING)
+static unsigned int decodeUTF8(const char** s)
+{
+ unsigned int ch = 0, count = 0;
+ static const unsigned int offsets[] =
+ {
+ 0x00000000u, 0x00003080u, 0x000e2080u,
+ 0x03c82080u, 0xfa082080u, 0x82082080u
+ };
+
+ do
+ {
+ ch = (ch << 6) + (unsigned char) **s;
+ (*s)++;
+ count++;
+ } while ((**s & 0xc0) == 0x80);
+
+ assert(count <= 6);
+ return ch - offsets[count - 1];
+}
+#endif /*X_HAVE_UTF8_STRING*/
+
+// Convert the specified Latin-1 string to UTF-8
+//
+static char* convertLatin1toUTF8(const char* source)
+{
+ size_t size = 1;
+ const char* sp;
+
+ for (sp = source; *sp; sp++)
+ size += (*sp & 0x80) ? 2 : 1;
+
+ char* target = calloc(size, 1);
+ char* tp = target;
+
+ for (sp = source; *sp; sp++)
+ tp += encodeUTF8(tp, *sp);
+
+ return target;
+}
+
+// Centers the cursor over the window client area
+//
+static void centerCursor(_GLFWwindow* window)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ if (window->cursor)
+ {
+ XDefineCursor(_glfw.x11.display, window->x11.handle,
+ window->cursor->x11.handle);
+ }
+ else
+ XUndefineCursor(_glfw.x11.display, window->x11.handle);
+ }
+ else
+ {
+ XDefineCursor(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.hiddenCursorHandle);
+ }
+}
+
+// Apply disabled cursor mode to a focused window
+//
+static void disableCursor(_GLFWwindow* window)
+{
+ if (_glfw.x11.xi.available)
+ {
+ XIEventMask em;
+ unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
+
+ em.deviceid = XIAllMasterDevices;
+ em.mask_len = sizeof(mask);
+ em.mask = mask;
+ XISetMask(mask, XI_RawMotion);
+
+ XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
+ }
+
+ _glfw.x11.disabledCursorWindow = window;
+ _glfwPlatformGetCursorPos(window,
+ &_glfw.x11.restoreCursorPosX,
+ &_glfw.x11.restoreCursorPosY);
+ updateCursorImage(window);
+ centerCursor(window);
+ XGrabPointer(_glfw.x11.display, window->x11.handle, True,
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync,
+ window->x11.handle,
+ _glfw.x11.hiddenCursorHandle,
+ CurrentTime);
+}
+
+// Exit disabled cursor mode for the specified window
+//
+static void enableCursor(_GLFWwindow* window)
+{
+ if (_glfw.x11.xi.available)
+ {
+ XIEventMask em;
+ unsigned char mask[] = { 0 };
+
+ em.deviceid = XIAllMasterDevices;
+ em.mask_len = sizeof(mask);
+ em.mask = mask;
+
+ XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
+ }
+
+ _glfw.x11.disabledCursorWindow = NULL;
+ XUngrabPointer(_glfw.x11.display, CurrentTime);
+ _glfwPlatformSetCursorPos(window,
+ _glfw.x11.restoreCursorPosX,
+ _glfw.x11.restoreCursorPosY);
+ updateCursorImage(window);
+}
+
+// Create the X11 window (and its colormap)
+//
+static GLFWbool createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ Visual* visual, int depth)
+{
+ int width = wndconfig->width;
+ int height = wndconfig->height;
+
+ if (wndconfig->scaleToMonitor)
+ {
+ width *= _glfw.x11.contentScaleX;
+ height *= _glfw.x11.contentScaleY;
+ }
+
+ // Create a colormap based on the visual used by the current context
+ window->x11.colormap = XCreateColormap(_glfw.x11.display,
+ _glfw.x11.root,
+ visual,
+ AllocNone);
+
+ window->x11.transparent = _glfwIsVisualTransparentX11(visual);
+
+ // Create the actual window
+ {
+ XSetWindowAttributes wa;
+ const unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
+
+ wa.colormap = window->x11.colormap;
+ wa.border_pixel = 0;
+ wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
+ PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
+ ExposureMask | FocusChangeMask | VisibilityChangeMask |
+ EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
+
+ _glfwGrabErrorHandlerX11();
+
+ window->x11.handle = XCreateWindow(_glfw.x11.display,
+ _glfw.x11.root,
+ 0, 0,
+ width, height,
+ 0, // Border width
+ depth, // Color depth
+ InputOutput,
+ visual,
+ wamask,
+ &wa);
+
+ _glfwReleaseErrorHandlerX11();
+
+ if (!window->x11.handle)
+ {
+ _glfwInputErrorX11(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create window");
+ return GLFW_FALSE;
+ }
+
+ XSaveContext(_glfw.x11.display,
+ window->x11.handle,
+ _glfw.x11.context,
+ (XPointer) window);
+ }
+
+ if (!wndconfig->decorated)
+ _glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
+
+ if (_glfw.x11.NET_WM_STATE && !window->monitor)
+ {
+ Atom states[3];
+ int count = 0;
+
+ if (wndconfig->floating)
+ {
+ if (_glfw.x11.NET_WM_STATE_ABOVE)
+ states[count++] = _glfw.x11.NET_WM_STATE_ABOVE;
+ }
+
+ if (wndconfig->maximized)
+ {
+ if (_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
+ states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
+ window->x11.maximized = GLFW_TRUE;
+ }
+ }
+
+ if (count)
+ {
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &states, count);
+ }
+ }
+
+ // Declare the WM protocols supported by GLFW
+ {
+ Atom protocols[] =
+ {
+ _glfw.x11.WM_DELETE_WINDOW,
+ _glfw.x11.NET_WM_PING
+ };
+
+ XSetWMProtocols(_glfw.x11.display, window->x11.handle,
+ protocols, sizeof(protocols) / sizeof(Atom));
+ }
+
+ // Declare our PID
+ {
+ const long pid = getpid();
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_PID, XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char*) &pid, 1);
+ }
+
+ if (_glfw.x11.NET_WM_WINDOW_TYPE && _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL)
+ {
+ Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL;
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &type, 1);
+ }
+
+ // Set ICCCM WM_HINTS property
+ {
+ XWMHints* hints = XAllocWMHints();
+ if (!hints)
+ {
+ _glfwInputError(GLFW_OUT_OF_MEMORY,
+ "X11: Failed to allocate WM hints");
+ return GLFW_FALSE;
+ }
+
+ hints->flags = StateHint;
+ hints->initial_state = NormalState;
+
+ XSetWMHints(_glfw.x11.display, window->x11.handle, hints);
+ XFree(hints);
+ }
+
+ updateNormalHints(window, width, height);
+
+ // Set ICCCM WM_CLASS property
+ {
+ XClassHint* hint = XAllocClassHint();
+
+ if (strlen(wndconfig->x11.instanceName) &&
+ strlen(wndconfig->x11.className))
+ {
+ hint->res_name = (char*) wndconfig->x11.instanceName;
+ hint->res_class = (char*) wndconfig->x11.className;
+ }
+ else
+ {
+ const char* resourceName = getenv("RESOURCE_NAME");
+ if (resourceName && strlen(resourceName))
+ hint->res_name = (char*) resourceName;
+ else if (strlen(wndconfig->title))
+ hint->res_name = (char*) wndconfig->title;
+ else
+ hint->res_name = (char*) "glfw-application";
+
+ if (strlen(wndconfig->title))
+ hint->res_class = (char*) wndconfig->title;
+ else
+ hint->res_class = (char*) "GLFW-Application";
+ }
+
+ XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
+ XFree(hint);
+ }
+
+ // Announce support for Xdnd (drag and drop)
+ {
+ const Atom version = _GLFW_XDND_VERSION;
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.XdndAware, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &version, 1);
+ }
+
+ _glfwPlatformSetWindowTitle(window, wndconfig->title);
+
+ if (_glfw.x11.im)
+ {
+ window->x11.ic = XCreateIC(_glfw.x11.im,
+ XNInputStyle,
+ XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow,
+ window->x11.handle,
+ XNFocusWindow,
+ window->x11.handle,
+ NULL);
+ }
+
+ _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
+ _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
+
+ return GLFW_TRUE;
+}
+
+// Set the specified property to the selection converted to the requested target
+//
+static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
+{
+ int i;
+ char* selectionString = NULL;
+ const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING };
+ const int formatCount = sizeof(formats) / sizeof(formats[0]);
+
+ if (request->selection == _glfw.x11.PRIMARY)
+ selectionString = _glfw.x11.primarySelectionString;
+ else
+ selectionString = _glfw.x11.clipboardString;
+
+ if (request->property == None)
+ {
+ // The requester is a legacy client (ICCCM section 2.2)
+ // We don't support legacy clients, so fail here
+ return None;
+ }
+
+ if (request->target == _glfw.x11.TARGETS)
+ {
+ // The list of supported targets was requested
+
+ const Atom targets[] = { _glfw.x11.TARGETS,
+ _glfw.x11.MULTIPLE,
+ _glfw.x11.UTF8_STRING,
+ XA_STRING };
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (unsigned char*) targets,
+ sizeof(targets) / sizeof(targets[0]));
+
+ return request->property;
+ }
+
+ if (request->target == _glfw.x11.MULTIPLE)
+ {
+ // Multiple conversions were requested
+
+ Atom* targets;
+ unsigned long i, count;
+
+ count = _glfwGetWindowPropertyX11(request->requestor,
+ request->property,
+ _glfw.x11.ATOM_PAIR,
+ (unsigned char**) &targets);
+
+ for (i = 0; i < count; i += 2)
+ {
+ int j;
+
+ for (j = 0; j < formatCount; j++)
+ {
+ if (targets[i] == formats[j])
+ break;
+ }
+
+ if (j < formatCount)
+ {
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ targets[i + 1],
+ targets[i],
+ 8,
+ PropModeReplace,
+ (unsigned char *) selectionString,
+ strlen(selectionString));
+ }
+ else
+ targets[i + 1] = None;
+ }
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ _glfw.x11.ATOM_PAIR,
+ 32,
+ PropModeReplace,
+ (unsigned char*) targets,
+ count);
+
+ XFree(targets);
+
+ return request->property;
+ }
+
+ if (request->target == _glfw.x11.SAVE_TARGETS)
+ {
+ // The request is a check whether we support SAVE_TARGETS
+ // It should be handled as a no-op side effect target
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ _glfw.x11.NULL_,
+ 32,
+ PropModeReplace,
+ NULL,
+ 0);
+
+ return request->property;
+ }
+
+ // Conversion to a data target was requested
+
+ for (i = 0; i < formatCount; i++)
+ {
+ if (request->target == formats[i])
+ {
+ // The requested target is one we support
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ request->target,
+ 8,
+ PropModeReplace,
+ (unsigned char *) selectionString,
+ strlen(selectionString));
+
+ return request->property;
+ }
+ }
+
+ // The requested target is not supported
+
+ return None;
+}
+
+static void handleSelectionClear(XEvent* event)
+{
+ if (event->xselectionclear.selection == _glfw.x11.PRIMARY)
+ {
+ free(_glfw.x11.primarySelectionString);
+ _glfw.x11.primarySelectionString = NULL;
+ }
+ else
+ {
+ free(_glfw.x11.clipboardString);
+ _glfw.x11.clipboardString = NULL;
+ }
+}
+
+static void handleSelectionRequest(XEvent* event)
+{
+ const XSelectionRequestEvent* request = &event->xselectionrequest;
+
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.xselection.property = writeTargetToProperty(request);
+ reply.xselection.type = SelectionNotify;
+ reply.xselection.display = request->display;
+ reply.xselection.requestor = request->requestor;
+ reply.xselection.selection = request->selection;
+ reply.xselection.target = request->target;
+ reply.xselection.time = request->time;
+
+ XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
+}
+
+static const char* getSelectionString(Atom selection)
+{
+ size_t i;
+ char** selectionString = NULL;
+ const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
+ const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
+
+ if (selection == _glfw.x11.PRIMARY)
+ selectionString = &_glfw.x11.primarySelectionString;
+ else
+ selectionString = &_glfw.x11.clipboardString;
+
+ if (XGetSelectionOwner(_glfw.x11.display, selection) ==
+ _glfw.x11.helperWindowHandle)
+ {
+ // Instead of doing a large number of X round-trips just to put this
+ // string into a window property and then read it back, just return it
+ return *selectionString;
+ }
+
+ free(*selectionString);
+ *selectionString = NULL;
+
+ for (i = 0; i < targetCount; i++)
+ {
+ char* data;
+ Atom actualType;
+ int actualFormat;
+ unsigned long itemCount, bytesAfter;
+ XEvent notification, dummy;
+
+ XConvertSelection(_glfw.x11.display,
+ selection,
+ targets[i],
+ _glfw.x11.GLFW_SELECTION,
+ _glfw.x11.helperWindowHandle,
+ CurrentTime);
+
+ while (!XCheckTypedWindowEvent(_glfw.x11.display,
+ _glfw.x11.helperWindowHandle,
+ SelectionNotify,
+ &notification))
+ {
+ waitForEvent(NULL);
+ }
+
+ if (notification.xselection.property == None)
+ continue;
+
+ XCheckIfEvent(_glfw.x11.display,
+ &dummy,
+ isSelPropNewValueNotify,
+ (XPointer) &notification);
+
+ XGetWindowProperty(_glfw.x11.display,
+ notification.xselection.requestor,
+ notification.xselection.property,
+ 0,
+ LONG_MAX,
+ True,
+ AnyPropertyType,
+ &actualType,
+ &actualFormat,
+ &itemCount,
+ &bytesAfter,
+ (unsigned char**) &data);
+
+ if (actualType == _glfw.x11.INCR)
+ {
+ size_t size = 1;
+ char* string = NULL;
+
+ for (;;)
+ {
+ while (!XCheckIfEvent(_glfw.x11.display,
+ &dummy,
+ isSelPropNewValueNotify,
+ (XPointer) &notification))
+ {
+ waitForEvent(NULL);
+ }
+
+ XFree(data);
+ XGetWindowProperty(_glfw.x11.display,
+ notification.xselection.requestor,
+ notification.xselection.property,
+ 0,
+ LONG_MAX,
+ True,
+ AnyPropertyType,
+ &actualType,
+ &actualFormat,
+ &itemCount,
+ &bytesAfter,
+ (unsigned char**) &data);
+
+ if (itemCount)
+ {
+ size += itemCount;
+ string = realloc(string, size);
+ string[size - itemCount - 1] = '\0';
+ strcat(string, data);
+ }
+
+ if (!itemCount)
+ {
+ if (targets[i] == XA_STRING)
+ {
+ *selectionString = convertLatin1toUTF8(string);
+ free(string);
+ }
+ else
+ *selectionString = string;
+
+ break;
+ }
+ }
+ }
+ else if (actualType == targets[i])
+ {
+ if (targets[i] == XA_STRING)
+ *selectionString = convertLatin1toUTF8(data);
+ else
+ *selectionString = _glfw_strdup(data);
+ }
+
+ XFree(data);
+
+ if (*selectionString)
+ break;
+ }
+
+ if (!*selectionString)
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "X11: Failed to convert selection to string");
+ }
+
+ return *selectionString;
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_GLFWwindow* window)
+{
+ if (_glfw.x11.saver.count == 0)
+ {
+ // Remember old screen saver settings
+ XGetScreenSaver(_glfw.x11.display,
+ &_glfw.x11.saver.timeout,
+ &_glfw.x11.saver.interval,
+ &_glfw.x11.saver.blanking,
+ &_glfw.x11.saver.exposure);
+
+ // Disable screen saver
+ XSetScreenSaver(_glfw.x11.display, 0, 0, DontPreferBlanking,
+ DefaultExposures);
+ }
+
+ if (!window->monitor->window)
+ _glfw.x11.saver.count++;
+
+ _glfwSetVideoModeX11(window->monitor, &window->videoMode);
+
+ if (window->x11.overrideRedirect)
+ {
+ int xpos, ypos;
+ GLFWvidmode mode;
+
+ // Manually position the window over its monitor
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+
+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+ xpos, ypos, mode.width, mode.height);
+ }
+
+ _glfwInputMonitorWindow(window->monitor, window);
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+ if (window->monitor->window != window)
+ return;
+
+ _glfwInputMonitorWindow(window->monitor, NULL);
+ _glfwRestoreVideoModeX11(window->monitor);
+
+ _glfw.x11.saver.count--;
+
+ if (_glfw.x11.saver.count == 0)
+ {
+ // Restore old screen saver settings
+ XSetScreenSaver(_glfw.x11.display,
+ _glfw.x11.saver.timeout,
+ _glfw.x11.saver.interval,
+ _glfw.x11.saver.blanking,
+ _glfw.x11.saver.exposure);
+ }
+}
+
+// Process the specified X event
+//
+static void processEvent(XEvent *event)
+{
+ _GLFWwindow* window = NULL;
+ int keycode = 0;
+ Bool filtered = False;
+
+ // HACK: Save scancode as some IMs clear the field in XFilterEvent
+ if (event->type == KeyPress || event->type == KeyRelease)
+ keycode = event->xkey.keycode;
+
+ if (_glfw.x11.im)
+ filtered = XFilterEvent(event, None);
+
+ if (_glfw.x11.randr.available)
+ {
+ if (event->type == _glfw.x11.randr.eventBase + RRNotify)
+ {
+ XRRUpdateConfiguration(event);
+ _glfwPollMonitorsX11();
+ return;
+ }
+ }
+
+ if (event->type == GenericEvent)
+ {
+ if (_glfw.x11.xi.available)
+ {
+ _GLFWwindow* window = _glfw.x11.disabledCursorWindow;
+
+ if (window &&
+ event->xcookie.extension == _glfw.x11.xi.majorOpcode &&
+ XGetEventData(_glfw.x11.display, &event->xcookie) &&
+ event->xcookie.evtype == XI_RawMotion)
+ {
+ XIRawEvent* re = event->xcookie.data;
+ if (re->valuators.mask_len)
+ {
+ const double* values = re->raw_values;
+ double xpos = window->virtualCursorPosX;
+ double ypos = window->virtualCursorPosY;
+
+ if (XIMaskIsSet(re->valuators.mask, 0))
+ {
+ xpos += *values;
+ values++;
+ }
+
+ if (XIMaskIsSet(re->valuators.mask, 1))
+ ypos += *values;
+
+ _glfwInputCursorPos(window, xpos, ypos);
+ }
+ }
+
+ XFreeEventData(_glfw.x11.display, &event->xcookie);
+ }
+
+ return;
+ }
+
+ if (event->type == SelectionClear)
+ {
+ handleSelectionClear(event);
+ return;
+ }
+ else if (event->type == SelectionRequest)
+ {
+ handleSelectionRequest(event);
+ return;
+ }
+
+ if (XFindContext(_glfw.x11.display,
+ event->xany.window,
+ _glfw.x11.context,
+ (XPointer*) &window) != 0)
+ {
+ // This is an event for a window that has already been destroyed
+ return;
+ }
+
+ switch (event->type)
+ {
+ case KeyPress:
+ {
+ const int key = translateKey(keycode);
+ const int mods = translateState(event->xkey.state);
+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+
+ if (window->x11.ic)
+ {
+ // HACK: Ignore duplicate key press events generated by ibus
+ // These have the same timestamp as the original event
+ // Corresponding release events are filtered out
+ // implicitly by the GLFW key repeat logic
+ if (window->x11.lastKeyTime < event->xkey.time)
+ {
+ if (keycode)
+ _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
+
+ window->x11.lastKeyTime = event->xkey.time;
+ }
+
+ if (!filtered)
+ {
+ int count;
+ Status status;
+#if defined(X_HAVE_UTF8_STRING)
+ char buffer[100];
+ char* chars = buffer;
+
+ count = Xutf8LookupString(window->x11.ic,
+ &event->xkey,
+ buffer, sizeof(buffer) - 1,
+ NULL, &status);
+
+ if (status == XBufferOverflow)
+ {
+ chars = calloc(count + 1, 1);
+ count = Xutf8LookupString(window->x11.ic,
+ &event->xkey,
+ chars, count,
+ NULL, &status);
+ }
+
+ if (status == XLookupChars || status == XLookupBoth)
+ {
+ const char* c = chars;
+ chars[count] = '\0';
+ while (c - chars < count)
+ _glfwInputChar(window, decodeUTF8(&c), mods, plain);
+ }
+#else /*X_HAVE_UTF8_STRING*/
+ wchar_t buffer[16];
+ wchar_t* chars = buffer;
+
+ count = XwcLookupString(window->x11.ic,
+ &event->xkey,
+ buffer,
+ sizeof(buffer) / sizeof(wchar_t),
+ NULL,
+ &status);
+
+ if (status == XBufferOverflow)
+ {
+ chars = calloc(count, sizeof(wchar_t));
+ count = XwcLookupString(window->x11.ic,
+ &event->xkey,
+ chars, count,
+ NULL, &status);
+ }
+
+ if (status == XLookupChars || status == XLookupBoth)
+ {
+ int i;
+ for (i = 0; i < count; i++)
+ _glfwInputChar(window, chars[i], mods, plain);
+ }
+#endif /*X_HAVE_UTF8_STRING*/
+
+ if (chars != buffer)
+ free(chars);
+ }
+ }
+ else
+ {
+ KeySym keysym;
+ XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
+
+ _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
+
+ const long character = _glfwKeySym2Unicode(keysym);
+ if (character != -1)
+ _glfwInputChar(window, character, mods, plain);
+ }
+
+ return;
+ }
+
+ case KeyRelease:
+ {
+ const int key = translateKey(keycode);
+ const int mods = translateState(event->xkey.state);
+
+ if (!_glfw.x11.xkb.detectable)
+ {
+ // HACK: Key repeat events will arrive as KeyRelease/KeyPress
+ // pairs with similar or identical time stamps
+ // The key repeat logic in _glfwInputKey expects only key
+ // presses to repeat, so detect and discard release events
+ if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))
+ {
+ XEvent next;
+ XPeekEvent(_glfw.x11.display, &next);
+
+ if (next.type == KeyPress &&
+ next.xkey.window == event->xkey.window &&
+ next.xkey.keycode == keycode)
+ {
+ // HACK: The time of repeat events sometimes doesn't
+ // match that of the press event, so add an
+ // epsilon
+ // Toshiyuki Takahashi can press a button
+ // 16 times per second so it's fairly safe to
+ // assume that no human is pressing the key 50
+ // times per second (value is ms)
+ if ((next.xkey.time - event->xkey.time) < 20)
+ {
+ // This is very likely a server-generated key repeat
+ // event, so ignore it
+ return;
+ }
+ }
+ }
+ }
+
+ _glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);
+ return;
+ }
+
+ case ButtonPress:
+ {
+ const int mods = translateState(event->xbutton.state);
+
+ if (event->xbutton.button == Button1)
+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
+ else if (event->xbutton.button == Button2)
+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);
+ else if (event->xbutton.button == Button3)
+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);
+
+ // Modern X provides scroll events as mouse button presses
+ else if (event->xbutton.button == Button4)
+ _glfwInputScroll(window, 0.0, 1.0);
+ else if (event->xbutton.button == Button5)
+ _glfwInputScroll(window, 0.0, -1.0);
+ else if (event->xbutton.button == Button6)
+ _glfwInputScroll(window, 1.0, 0.0);
+ else if (event->xbutton.button == Button7)
+ _glfwInputScroll(window, -1.0, 0.0);
+
+ else
+ {
+ // Additional buttons after 7 are treated as regular buttons
+ // We subtract 4 to fill the gap left by scroll input above
+ _glfwInputMouseClick(window,
+ event->xbutton.button - Button1 - 4,
+ GLFW_PRESS,
+ mods);
+ }
+
+ return;
+ }
+
+ case ButtonRelease:
+ {
+ const int mods = translateState(event->xbutton.state);
+
+ if (event->xbutton.button == Button1)
+ {
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_RELEASE,
+ mods);
+ }
+ else if (event->xbutton.button == Button2)
+ {
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_MIDDLE,
+ GLFW_RELEASE,
+ mods);
+ }
+ else if (event->xbutton.button == Button3)
+ {
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_RIGHT,
+ GLFW_RELEASE,
+ mods);
+ }
+ else if (event->xbutton.button > Button7)
+ {
+ // Additional buttons after 7 are treated as regular buttons
+ // We subtract 4 to fill the gap left by scroll input above
+ _glfwInputMouseClick(window,
+ event->xbutton.button - Button1 - 4,
+ GLFW_RELEASE,
+ mods);
+ }
+
+ return;
+ }
+
+ case EnterNotify:
+ {
+ // XEnterWindowEvent is XCrossingEvent
+ const int x = event->xcrossing.x;
+ const int y = event->xcrossing.y;
+
+ // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
+ // ignore the defined cursor for hidden cursor mode
+ if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+ updateCursorImage(window);
+
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+ _glfwInputCursorPos(window, x, y);
+
+ window->x11.lastCursorPosX = x;
+ window->x11.lastCursorPosY = y;
+ return;
+ }
+
+ case LeaveNotify:
+ {
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+ return;
+ }
+
+ case MotionNotify:
+ {
+ const int x = event->xmotion.x;
+ const int y = event->xmotion.y;
+
+ if (x != window->x11.warpCursorPosX ||
+ y != window->x11.warpCursorPosY)
+ {
+ // The cursor was moved by something other than GLFW
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ if (_glfw.x11.disabledCursorWindow != window)
+ return;
+ if (_glfw.x11.xi.available)
+ return;
+
+ const int dx = x - window->x11.lastCursorPosX;
+ const int dy = y - window->x11.lastCursorPosY;
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + dx,
+ window->virtualCursorPosY + dy);
+ }
+ else
+ _glfwInputCursorPos(window, x, y);
+ }
+
+ window->x11.lastCursorPosX = x;
+ window->x11.lastCursorPosY = y;
+ return;
+ }
+
+ case ConfigureNotify:
+ {
+ if (event->xconfigure.width != window->x11.width ||
+ event->xconfigure.height != window->x11.height)
+ {
+ _glfwInputFramebufferSize(window,
+ event->xconfigure.width,
+ event->xconfigure.height);
+
+ _glfwInputWindowSize(window,
+ event->xconfigure.width,
+ event->xconfigure.height);
+
+ window->x11.width = event->xconfigure.width;
+ window->x11.height = event->xconfigure.height;
+ }
+
+ if (event->xconfigure.x != window->x11.xpos ||
+ event->xconfigure.y != window->x11.ypos)
+ {
+ if (window->x11.overrideRedirect || event->xany.send_event)
+ {
+ _glfwInputWindowPos(window,
+ event->xconfigure.x,
+ event->xconfigure.y);
+
+ window->x11.xpos = event->xconfigure.x;
+ window->x11.ypos = event->xconfigure.y;
+ }
+ }
+
+ return;
+ }
+
+ case ClientMessage:
+ {
+ // Custom client message, probably from the window manager
+
+ if (filtered)
+ return;
+
+ if (event->xclient.message_type == None)
+ return;
+
+ if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)
+ {
+ const Atom protocol = event->xclient.data.l[0];
+ if (protocol == None)
+ return;
+
+ if (protocol == _glfw.x11.WM_DELETE_WINDOW)
+ {
+ // The window manager was asked to close the window, for
+ // example by the user pressing a 'close' window decoration
+ // button
+ _glfwInputWindowCloseRequest(window);
+ }
+ else if (protocol == _glfw.x11.NET_WM_PING)
+ {
+ // The window manager is pinging the application to ensure
+ // it's still responding to events
+
+ XEvent reply = *event;
+ reply.xclient.window = _glfw.x11.root;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &reply);
+ }
+ }
+ else if (event->xclient.message_type == _glfw.x11.XdndEnter)
+ {
+ // A drag operation has entered the window
+ unsigned long i, count;
+ Atom* formats = NULL;
+ const GLFWbool list = event->xclient.data.l[1] & 1;
+
+ _glfw.x11.xdnd.source = event->xclient.data.l[0];
+ _glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
+ _glfw.x11.xdnd.format = None;
+
+ if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
+ return;
+
+ if (list)
+ {
+ count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
+ _glfw.x11.XdndTypeList,
+ XA_ATOM,
+ (unsigned char**) &formats);
+ }
+ else
+ {
+ count = 3;
+ formats = (Atom*) event->xclient.data.l + 2;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (formats[i] == _glfw.x11.text_uri_list)
+ {
+ _glfw.x11.xdnd.format = _glfw.x11.text_uri_list;
+ break;
+ }
+ }
+
+ if (list && formats)
+ XFree(formats);
+ }
+ else if (event->xclient.message_type == _glfw.x11.XdndDrop)
+ {
+ // The drag operation has finished by dropping on the window
+ Time time = CurrentTime;
+
+ if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
+ return;
+
+ if (_glfw.x11.xdnd.format)
+ {
+ if (_glfw.x11.xdnd.version >= 1)
+ time = event->xclient.data.l[2];
+
+ // Request the chosen format from the source window
+ XConvertSelection(_glfw.x11.display,
+ _glfw.x11.XdndSelection,
+ _glfw.x11.xdnd.format,
+ _glfw.x11.XdndSelection,
+ window->x11.handle,
+ time);
+ }
+ else if (_glfw.x11.xdnd.version >= 2)
+ {
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = _glfw.x11.xdnd.source;
+ reply.xclient.message_type = _glfw.x11.XdndFinished;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = window->x11.handle;
+ reply.xclient.data.l[1] = 0; // The drag was rejected
+ reply.xclient.data.l[2] = None;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+ False, NoEventMask, &reply);
+ XFlush(_glfw.x11.display);
+ }
+ }
+ else if (event->xclient.message_type == _glfw.x11.XdndPosition)
+ {
+ // The drag operation has moved over the window
+ const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
+ const int yabs = (event->xclient.data.l[2]) & 0xffff;
+ Window dummy;
+ int xpos, ypos;
+
+ if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
+ return;
+
+ XTranslateCoordinates(_glfw.x11.display,
+ _glfw.x11.root,
+ window->x11.handle,
+ xabs, yabs,
+ &xpos, &ypos,
+ &dummy);
+
+ _glfwInputCursorPos(window, xpos, ypos);
+
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = _glfw.x11.xdnd.source;
+ reply.xclient.message_type = _glfw.x11.XdndStatus;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = window->x11.handle;
+ reply.xclient.data.l[2] = 0; // Specify an empty rectangle
+ reply.xclient.data.l[3] = 0;
+
+ if (_glfw.x11.xdnd.format)
+ {
+ // Reply that we are ready to copy the dragged data
+ reply.xclient.data.l[1] = 1; // Accept with no rectangle
+ if (_glfw.x11.xdnd.version >= 2)
+ reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
+ }
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+ False, NoEventMask, &reply);
+ XFlush(_glfw.x11.display);
+ }
+
+ return;
+ }
+
+ case SelectionNotify:
+ {
+ if (event->xselection.property == _glfw.x11.XdndSelection)
+ {
+ // The converted data from the drag operation has arrived
+ char* data;
+ const unsigned long result =
+ _glfwGetWindowPropertyX11(event->xselection.requestor,
+ event->xselection.property,
+ event->xselection.target,
+ (unsigned char**) &data);
+
+ if (result)
+ {
+ int i, count;
+ char** paths = parseUriList(data, &count);
+
+ _glfwInputDrop(window, count, (const char**) paths);
+
+ for (i = 0; i < count; i++)
+ free(paths[i]);
+ free(paths);
+ }
+
+ if (data)
+ XFree(data);
+
+ if (_glfw.x11.xdnd.version >= 2)
+ {
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = _glfw.x11.xdnd.source;
+ reply.xclient.message_type = _glfw.x11.XdndFinished;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = window->x11.handle;
+ reply.xclient.data.l[1] = result;
+ reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+ False, NoEventMask, &reply);
+ XFlush(_glfw.x11.display);
+ }
+ }
+
+ return;
+ }
+
+ case FocusIn:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ disableCursor(window);
+
+ if (event->xfocus.mode == NotifyGrab ||
+ event->xfocus.mode == NotifyUngrab)
+ {
+ // Ignore focus events from popup indicator windows, window menu
+ // key chords and window dragging
+ return;
+ }
+
+ if (window->x11.ic)
+ XSetICFocus(window->x11.ic);
+
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+ return;
+ }
+
+ case FocusOut:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ enableCursor(window);
+
+ if (event->xfocus.mode == NotifyGrab ||
+ event->xfocus.mode == NotifyUngrab)
+ {
+ // Ignore focus events from popup indicator windows, window menu
+ // key chords and window dragging
+ return;
+ }
+
+ if (window->x11.ic)
+ XUnsetICFocus(window->x11.ic);
+
+ if (window->monitor && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+ return;
+ }
+
+ case Expose:
+ {
+ _glfwInputWindowDamage(window);
+ return;
+ }
+
+ case PropertyNotify:
+ {
+ if (event->xproperty.state != PropertyNewValue)
+ return;
+
+ if (event->xproperty.atom == _glfw.x11.WM_STATE)
+ {
+ const int state = getWindowState(window);
+ if (state != IconicState && state != NormalState)
+ return;
+
+ const GLFWbool iconified = (state == IconicState);
+ if (window->x11.iconified != iconified)
+ {
+ if (window->monitor)
+ {
+ if (iconified)
+ releaseMonitor(window);
+ else
+ acquireMonitor(window);
+ }
+
+ window->x11.iconified = iconified;
+ _glfwInputWindowIconify(window, iconified);
+ }
+ }
+ else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE)
+ {
+ const GLFWbool maximized = _glfwPlatformWindowMaximized(window);
+ if (window->x11.maximized != maximized)
+ {
+ window->x11.maximized = maximized;
+ _glfwInputWindowMaximize(window, maximized);
+ }
+ }
+
+ return;
+ }
+
+ case DestroyNotify:
+ return;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Retrieve a single window property of the specified type
+// Inspired by fghGetWindowProperty from freeglut
+//
+unsigned long _glfwGetWindowPropertyX11(Window window,
+ Atom property,
+ Atom type,
+ unsigned char** value)
+{
+ Atom actualType;
+ int actualFormat;
+ unsigned long itemCount, bytesAfter;
+
+ XGetWindowProperty(_glfw.x11.display,
+ window,
+ property,
+ 0,
+ LONG_MAX,
+ False,
+ type,
+ &actualType,
+ &actualFormat,
+ &itemCount,
+ &bytesAfter,
+ value);
+
+ return itemCount;
+}
+
+GLFWbool _glfwIsVisualTransparentX11(Visual* visual)
+{
+ if (!_glfw.x11.xrender.available)
+ return GLFW_FALSE;
+
+ XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
+ return pf && pf->direct.alphaMask;
+}
+
+// Push contents of our selection to clipboard manager
+//
+void _glfwPushSelectionToManagerX11(void)
+{
+ XConvertSelection(_glfw.x11.display,
+ _glfw.x11.CLIPBOARD_MANAGER,
+ _glfw.x11.SAVE_TARGETS,
+ None,
+ _glfw.x11.helperWindowHandle,
+ CurrentTime);
+
+ for (;;)
+ {
+ XEvent event;
+
+ while (XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL))
+ {
+ switch (event.type)
+ {
+ case SelectionRequest:
+ handleSelectionRequest(&event);
+ break;
+
+ case SelectionClear:
+ handleSelectionClear(&event);
+ break;
+
+ case SelectionNotify:
+ {
+ if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
+ {
+ // This means one of two things; either the selection
+ // was not owned, which means there is no clipboard
+ // manager, or the transfer to the clipboard manager has
+ // completed
+ // In either case, it means we are done here
+ return;
+ }
+
+ break;
+ }
+ }
+ }
+
+ waitForEvent(NULL);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ Visual* visual;
+ int depth;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwInitGLX())
+ return GLFW_FALSE;
+ if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ if (!_glfwInitOSMesa())
+ return GLFW_FALSE;
+ }
+ }
+
+ if (ctxconfig->client == GLFW_NO_API ||
+ ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
+ depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
+ }
+
+ if (!createNativeWindow(window, wndconfig, visual, depth))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+ {
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+ {
+ if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->monitor)
+ {
+ _glfwPlatformShowWindow(window);
+ updateWindowMode(window);
+ acquireMonitor(window);
+ }
+
+ XFlush(_glfw.x11.display);
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (_glfw.x11.disabledCursorWindow == window)
+ _glfw.x11.disabledCursorWindow = NULL;
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ if (window->x11.ic)
+ {
+ XDestroyIC(window->x11.ic);
+ window->x11.ic = NULL;
+ }
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+
+ if (window->x11.handle)
+ {
+ XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context);
+ XUnmapWindow(_glfw.x11.display, window->x11.handle);
+ XDestroyWindow(_glfw.x11.display, window->x11.handle);
+ window->x11.handle = (Window) 0;
+ }
+
+ if (window->x11.colormap)
+ {
+ XFreeColormap(_glfw.x11.display, window->x11.colormap);
+ window->x11.colormap = (Colormap) 0;
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+#if defined(X_HAVE_UTF8_STRING)
+ Xutf8SetWMProperties(_glfw.x11.display,
+ window->x11.handle,
+ title, title,
+ NULL, 0,
+ NULL, NULL, NULL);
+#else
+ // This may be a slightly better fallback than using XStoreName and
+ // XSetIconName, which always store their arguments using STRING
+ XmbSetWMProperties(_glfw.x11.display,
+ window->x11.handle,
+ title, title,
+ NULL, 0,
+ NULL, NULL, NULL);
+#endif
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_NAME, _glfw.x11.UTF8_STRING, 8,
+ PropModeReplace,
+ (unsigned char*) title, strlen(title));
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_ICON_NAME, _glfw.x11.UTF8_STRING, 8,
+ PropModeReplace,
+ (unsigned char*) title, strlen(title));
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ if (count)
+ {
+ int i, j, longCount = 0;
+
+ for (i = 0; i < count; i++)
+ longCount += 2 + images[i].width * images[i].height;
+
+ long* icon = calloc(longCount, sizeof(long));
+ long* target = icon;
+
+ for (i = 0; i < count; i++)
+ {
+ *target++ = images[i].width;
+ *target++ = images[i].height;
+
+ for (j = 0; j < images[i].width * images[i].height; j++)
+ {
+ *target++ = (images[i].pixels[j * 4 + 0] << 16) |
+ (images[i].pixels[j * 4 + 1] << 8) |
+ (images[i].pixels[j * 4 + 2] << 0) |
+ (images[i].pixels[j * 4 + 3] << 24);
+ }
+ }
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_ICON,
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char*) icon,
+ longCount);
+
+ free(icon);
+ }
+ else
+ {
+ XDeleteProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_ICON);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ Window dummy;
+ int x, y;
+
+ XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,
+ 0, 0, &x, &y, &dummy);
+
+ if (xpos)
+ *xpos = x;
+ if (ypos)
+ *ypos = y;
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ // HACK: Explicitly setting PPosition to any value causes some WMs, notably
+ // Compiz and Metacity, to honor the position of unmapped windows
+ if (!_glfwPlatformWindowVisible(window))
+ {
+ long supplied;
+ XSizeHints* hints = XAllocSizeHints();
+
+ if (XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied))
+ {
+ hints->flags |= PPosition;
+ hints->x = hints->y = 0;
+
+ XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
+ }
+
+ XFree(hints);
+ }
+
+ XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ XWindowAttributes attribs;
+ XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs);
+
+ if (width)
+ *width = attribs.width;
+ if (height)
+ *height = attribs.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->monitor)
+ {
+ if (window->monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ if (!window->resizable)
+ updateNormalHints(window, width, height);
+
+ XResizeWindow(_glfw.x11.display, window->x11.handle, width, height);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ updateNormalHints(window, width, height);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ updateNormalHints(window, width, height);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ _glfwPlatformGetWindowSize(window, width, height);
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ long* extents = NULL;
+
+ if (window->monitor || !window->decorated)
+ return;
+
+ if (_glfw.x11.NET_FRAME_EXTENTS == None)
+ return;
+
+ if (!_glfwPlatformWindowVisible(window) &&
+ _glfw.x11.NET_REQUEST_FRAME_EXTENTS)
+ {
+ XEvent event;
+ double timeout = 0.5;
+
+ // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
+ // function before the window is mapped
+ sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
+ 0, 0, 0, 0, 0);
+
+ // HACK: Use a timeout because earlier versions of some window managers
+ // (at least Unity, Fluxbox and Xfwm) failed to send the reply
+ // They have been fixed but broken versions are still in the wild
+ // If you are affected by this and your window manager is NOT
+ // listed above, PLEASE report it to their and our issue trackers
+ while (!XCheckIfEvent(_glfw.x11.display,
+ &event,
+ isFrameExtentsEvent,
+ (XPointer) window))
+ {
+ if (!waitForEvent(&timeout))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
+ return;
+ }
+ }
+ }
+
+ if (_glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.NET_FRAME_EXTENTS,
+ XA_CARDINAL,
+ (unsigned char**) &extents) == 4)
+ {
+ if (left)
+ *left = extents[0];
+ if (top)
+ *top = extents[2];
+ if (right)
+ *right = extents[1];
+ if (bottom)
+ *bottom = extents[3];
+ }
+
+ if (extents)
+ XFree(extents);
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+ float* xscale, float* yscale)
+{
+ if (xscale)
+ *xscale = _glfw.x11.contentScaleX;
+ if (yscale)
+ *yscale = _glfw.x11.contentScaleY;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ if (window->x11.overrideRedirect)
+ {
+ // Override-redirect windows cannot be iconified or restored, as those
+ // tasks are performed by the window manager
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
+ return;
+ }
+
+ XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ if (window->x11.overrideRedirect)
+ {
+ // Override-redirect windows cannot be iconified or restored, as those
+ // tasks are performed by the window manager
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
+ return;
+ }
+
+ if (_glfwPlatformWindowIconified(window))
+ {
+ XMapWindow(_glfw.x11.display, window->x11.handle);
+ waitForVisibilityNotify(window);
+ }
+ else if (_glfwPlatformWindowVisible(window))
+ {
+ if (_glfw.x11.NET_WM_STATE &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_REMOVE,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
+ 1, 0);
+ }
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ if (_glfw.x11.NET_WM_STATE &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_ADD,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
+ 1, 0);
+ XFlush(_glfw.x11.display);
+ }
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ if (_glfwPlatformWindowVisible(window))
+ return;
+
+ XMapWindow(_glfw.x11.display, window->x11.handle);
+ waitForVisibilityNotify(window);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ XUnmapWindow(_glfw.x11.display, window->x11.handle);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_ADD,
+ _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION,
+ 0, 1, 0);
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ if (_glfw.x11.NET_ACTIVE_WINDOW)
+ sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
+ else
+ {
+ XRaiseWindow(_glfw.x11.display, window->x11.handle);
+ XSetInputFocus(_glfw.x11.display, window->x11.handle,
+ RevertToParent, CurrentTime);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (window->monitor == monitor)
+ {
+ if (monitor)
+ {
+ if (monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ if (!window->resizable)
+ updateNormalHints(window, width, height);
+
+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+ xpos, ypos, width, height);
+ }
+
+ XFlush(_glfw.x11.display);
+ return;
+ }
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowMonitor(window, monitor);
+ updateNormalHints(window, width, height);
+ updateWindowMode(window);
+
+ if (window->monitor)
+ {
+ XMapRaised(_glfw.x11.display, window->x11.handle);
+ if (waitForVisibilityNotify(window))
+ acquireMonitor(window);
+ }
+ else
+ {
+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+ xpos, ypos, width, height);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ Window focused;
+ int state;
+
+ XGetInputFocus(_glfw.x11.display, &focused, &state);
+ return window->x11.handle == focused;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return getWindowState(window) == IconicState;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ XWindowAttributes wa;
+ XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);
+ return wa.map_state == IsViewable;
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ Atom* states;
+ unsigned long i;
+ GLFWbool maximized = GLFW_FALSE;
+
+ if (!_glfw.x11.NET_WM_STATE ||
+ !_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
+ !_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ return maximized;
+ }
+
+ const unsigned long count =
+ _glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.NET_WM_STATE,
+ XA_ATOM,
+ (unsigned char**) &states);
+
+ for (i = 0; i < count; i++)
+ {
+ if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
+ states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ maximized = GLFW_TRUE;
+ break;
+ }
+ }
+
+ if (states)
+ XFree(states);
+
+ return maximized;
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+ Window w = _glfw.x11.root;
+ while (w)
+ {
+ Window root;
+ int rootX, rootY, childX, childY;
+ unsigned int mask;
+
+ if (!XQueryPointer(_glfw.x11.display, w,
+ &root, &w, &rootX, &rootY, &childX, &childY, &mask))
+ {
+ return GLFW_FALSE;
+ }
+
+ if (w == window->x11.handle)
+ return GLFW_TRUE;
+ }
+
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+ if (!window->x11.transparent)
+ return GLFW_FALSE;
+
+ return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ updateNormalHints(window, width, height);
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+ if (enabled)
+ {
+ XDeleteProperty(_glfw.x11.display,
+ window->x11.handle,
+ _glfw.x11.MOTIF_WM_HINTS);
+ }
+ else
+ {
+ struct
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long input_mode;
+ unsigned long status;
+ } hints;
+
+ hints.flags = 2; // Set decorations
+ hints.decorations = 0; // No decorations
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.MOTIF_WM_HINTS,
+ _glfw.x11.MOTIF_WM_HINTS, 32,
+ PropModeReplace,
+ (unsigned char*) &hints,
+ sizeof(hints) / sizeof(long));
+ }
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+ if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE)
+ return;
+
+ if (_glfwPlatformWindowVisible(window))
+ {
+ const Atom action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ action,
+ _glfw.x11.NET_WM_STATE_ABOVE,
+ 0, 1, 0);
+ }
+ else
+ {
+ Atom* states;
+ unsigned long i, count;
+
+ count = _glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.NET_WM_STATE,
+ XA_ATOM,
+ (unsigned char**) &states);
+ if (!states)
+ return;
+
+ if (enabled)
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
+ break;
+ }
+
+ if (i == count)
+ {
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+ PropModeAppend,
+ (unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
+ 1);
+ }
+ }
+ else
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
+ {
+ states[i] = states[count - 1];
+ count--;
+ }
+ }
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &states, count);
+ }
+
+ XFree(states);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+ float opacity = 1.f;
+
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx))
+ {
+ CARD32* value = NULL;
+
+ if (_glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.NET_WM_WINDOW_OPACITY,
+ XA_CARDINAL,
+ (unsigned char**) &value))
+ {
+ opacity = (float) (*value / (double) 0xffffffffu);
+ }
+
+ if (value)
+ XFree(value);
+ }
+
+ return opacity;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+ const CARD32 value = (CARD32) (0xffffffffu * (double) opacity);
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*) &value, 1);
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ _GLFWwindow* window;
+
+#if defined(__linux__)
+ _glfwDetectJoystickConnectionLinux();
+#endif
+ XPending(_glfw.x11.display);
+
+ while (XQLength(_glfw.x11.display))
+ {
+ XEvent event;
+ XNextEvent(_glfw.x11.display, &event);
+ processEvent(&event);
+ }
+
+ window = _glfw.x11.disabledCursorWindow;
+ if (window)
+ {
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+
+ // NOTE: Re-center the cursor only if it has moved since the last call,
+ // to avoid breaking glfwWaitEvents with MotionNotify
+ if (window->x11.lastCursorPosX != width / 2 ||
+ window->x11.lastCursorPosY != height / 2)
+ {
+ _glfwPlatformSetCursorPos(window, width / 2, height / 2);
+ }
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ while (!XPending(_glfw.x11.display))
+ waitForEvent(NULL);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ while (!XPending(_glfw.x11.display))
+ {
+ if (!waitForEvent(&timeout))
+ break;
+ }
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ XEvent event;
+
+ memset(&event, 0, sizeof(event));
+ event.type = ClientMessage;
+ event.xclient.window = _glfw.x11.helperWindowHandle;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = _glfw.x11.NULL_;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ Window root, child;
+ int rootX, rootY, childX, childY;
+ unsigned int mask;
+
+ XQueryPointer(_glfw.x11.display, window->x11.handle,
+ &root, &child,
+ &rootX, &rootY, &childX, &childY,
+ &mask);
+
+ if (xpos)
+ *xpos = childX;
+ if (ypos)
+ *ypos = childY;
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+ // Store the new position so it can be recognized later
+ window->x11.warpCursorPosX = (int) x;
+ window->x11.warpCursorPosY = (int) y;
+
+ XWarpPointer(_glfw.x11.display, None, window->x11.handle,
+ 0,0,0,0, (int) x, (int) y);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ if (mode == GLFW_CURSOR_DISABLED)
+ {
+ if (_glfwPlatformWindowFocused(window))
+ disableCursor(window);
+ }
+ else if (_glfw.x11.disabledCursorWindow == window)
+ enableCursor(window);
+ else
+ updateCursorImage(window);
+
+ XFlush(_glfw.x11.display);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+ if (!_glfw.x11.xkb.available)
+ return NULL;
+
+ const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0);
+ if (keysym == NoSymbol)
+ return NULL;
+
+ const long ch = _glfwKeySym2Unicode(keysym);
+ if (ch == -1)
+ return NULL;
+
+ const size_t count = encodeUTF8(_glfw.x11.keyName, (unsigned int) ch);
+ if (count == 0)
+ return NULL;
+
+ _glfw.x11.keyName[count] = '\0';
+ return _glfw.x11.keyName;
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+ return _glfw.x11.scancodes[key];
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
+ if (!cursor->x11.handle)
+ return GLFW_FALSE;
+
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ int native = 0;
+
+ if (shape == GLFW_ARROW_CURSOR)
+ native = XC_left_ptr;
+ else if (shape == GLFW_IBEAM_CURSOR)
+ native = XC_xterm;
+ else if (shape == GLFW_CROSSHAIR_CURSOR)
+ native = XC_crosshair;
+ else if (shape == GLFW_HAND_CURSOR)
+ native = XC_hand1;
+ else if (shape == GLFW_HRESIZE_CURSOR)
+ native = XC_sb_h_double_arrow;
+ else if (shape == GLFW_VRESIZE_CURSOR)
+ native = XC_sb_v_double_arrow;
+ else
+ return GLFW_FALSE;
+
+ cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
+ if (!cursor->x11.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create standard cursor");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->x11.handle)
+ XFreeCursor(_glfw.x11.display, cursor->x11.handle);
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ updateCursorImage(window);
+ XFlush(_glfw.x11.display);
+ }
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+ free(_glfw.x11.clipboardString);
+ _glfw.x11.clipboardString = _glfw_strdup(string);
+
+ XSetSelectionOwner(_glfw.x11.display,
+ _glfw.x11.CLIPBOARD,
+ _glfw.x11.helperWindowHandle,
+ CurrentTime);
+
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=
+ _glfw.x11.helperWindowHandle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to become owner of clipboard selection");
+ }
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+ return getSelectionString(_glfw.x11.CLIPBOARD);
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+ if (!_glfw.vk.KHR_surface)
+ return;
+
+ if (!_glfw.vk.KHR_xcb_surface || !_glfw.x11.x11xcb.handle)
+ {
+ if (!_glfw.vk.KHR_xlib_surface)
+ return;
+ }
+
+ extensions[0] = "VK_KHR_surface";
+
+ // NOTE: VK_KHR_xcb_surface is preferred due to some early ICDs exposing but
+ // not correctly implementing VK_KHR_xlib_surface
+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+ extensions[1] = "VK_KHR_xcb_surface";
+ else
+ extensions[1] = "VK_KHR_xlib_surface";
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display,
+ _glfw.x11.screen));
+
+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+ {
+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
+ vkGetPhysicalDeviceXcbPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xcb_surface extension");
+ return GLFW_FALSE;
+ }
+
+ xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
+ if (!connection)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to retrieve XCB connection");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,
+ queuefamily,
+ connection,
+ visualID);
+ }
+ else
+ {
+ PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR
+ vkGetPhysicalDeviceXlibPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xlib_surface extension");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,
+ queuefamily,
+ _glfw.x11.display,
+ visualID);
+ }
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+ {
+ VkResult err;
+ VkXcbSurfaceCreateInfoKHR sci;
+ PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
+
+ xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
+ if (!connection)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to retrieve XCB connection");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ vkCreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR");
+ if (!vkCreateXcbSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xcb_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ sci.connection = connection;
+ sci.window = window->x11.handle;
+
+ err = vkCreateXcbSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create Vulkan XCB surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+ }
+ else
+ {
+ VkResult err;
+ VkXlibSurfaceCreateInfoKHR sci;
+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
+
+ vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR");
+ if (!vkCreateXlibSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xlib_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+ sci.dpy = _glfw.x11.display;
+ sci.window = window->x11.handle;
+
+ err = vkCreateXlibSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create Vulkan X11 surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI Display* glfwGetX11Display(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfw.x11.display;
+}
+
+GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(None);
+ return window->x11.handle;
+}
+
+GLFWAPI void glfwSetX11SelectionString(const char* string)
+{
+ _GLFW_REQUIRE_INIT();
+
+ free(_glfw.x11.primarySelectionString);
+ _glfw.x11.primarySelectionString = _glfw_strdup(string);
+
+ XSetSelectionOwner(_glfw.x11.display,
+ _glfw.x11.PRIMARY,
+ _glfw.x11.helperWindowHandle,
+ CurrentTime);
+
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
+ _glfw.x11.helperWindowHandle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to become owner of primary selection");
+ }
+}
+
+GLFWAPI const char* glfwGetX11SelectionString(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return getSelectionString(_glfw.x11.PRIMARY);
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.c b/Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.c
new file mode 100644
index 0000000..ecfdc2a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.c
@@ -0,0 +1,940 @@
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+/*
+ * Marcus: This code was originally written by Markus G. Kuhn.
+ * I have made some slight changes (trimmed it down a bit from >60 KB to
+ * 20 KB), but the functionality is the same.
+ */
+
+/*
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
+ * search, therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * Original author: Markus G. Kuhn <mkuhn@acm.org>, University of
+ * Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ */
+
+
+//************************************************************************
+//**** KeySym to Unicode mapping table ****
+//************************************************************************
+
+static const struct codepair {
+ unsigned short keysym;
+ unsigned short ucs;
+} keysymtab[] = {
+ { 0x01a1, 0x0104 },
+ { 0x01a2, 0x02d8 },
+ { 0x01a3, 0x0141 },
+ { 0x01a5, 0x013d },
+ { 0x01a6, 0x015a },
+ { 0x01a9, 0x0160 },
+ { 0x01aa, 0x015e },
+ { 0x01ab, 0x0164 },
+ { 0x01ac, 0x0179 },
+ { 0x01ae, 0x017d },
+ { 0x01af, 0x017b },
+ { 0x01b1, 0x0105 },
+ { 0x01b2, 0x02db },
+ { 0x01b3, 0x0142 },
+ { 0x01b5, 0x013e },
+ { 0x01b6, 0x015b },
+ { 0x01b7, 0x02c7 },
+ { 0x01b9, 0x0161 },
+ { 0x01ba, 0x015f },
+ { 0x01bb, 0x0165 },
+ { 0x01bc, 0x017a },
+ { 0x01bd, 0x02dd },
+ { 0x01be, 0x017e },
+ { 0x01bf, 0x017c },
+ { 0x01c0, 0x0154 },
+ { 0x01c3, 0x0102 },
+ { 0x01c5, 0x0139 },
+ { 0x01c6, 0x0106 },
+ { 0x01c8, 0x010c },
+ { 0x01ca, 0x0118 },
+ { 0x01cc, 0x011a },
+ { 0x01cf, 0x010e },
+ { 0x01d0, 0x0110 },
+ { 0x01d1, 0x0143 },
+ { 0x01d2, 0x0147 },
+ { 0x01d5, 0x0150 },
+ { 0x01d8, 0x0158 },
+ { 0x01d9, 0x016e },
+ { 0x01db, 0x0170 },
+ { 0x01de, 0x0162 },
+ { 0x01e0, 0x0155 },
+ { 0x01e3, 0x0103 },
+ { 0x01e5, 0x013a },
+ { 0x01e6, 0x0107 },
+ { 0x01e8, 0x010d },
+ { 0x01ea, 0x0119 },
+ { 0x01ec, 0x011b },
+ { 0x01ef, 0x010f },
+ { 0x01f0, 0x0111 },
+ { 0x01f1, 0x0144 },
+ { 0x01f2, 0x0148 },
+ { 0x01f5, 0x0151 },
+ { 0x01f8, 0x0159 },
+ { 0x01f9, 0x016f },
+ { 0x01fb, 0x0171 },
+ { 0x01fe, 0x0163 },
+ { 0x01ff, 0x02d9 },
+ { 0x02a1, 0x0126 },
+ { 0x02a6, 0x0124 },
+ { 0x02a9, 0x0130 },
+ { 0x02ab, 0x011e },
+ { 0x02ac, 0x0134 },
+ { 0x02b1, 0x0127 },
+ { 0x02b6, 0x0125 },
+ { 0x02b9, 0x0131 },
+ { 0x02bb, 0x011f },
+ { 0x02bc, 0x0135 },
+ { 0x02c5, 0x010a },
+ { 0x02c6, 0x0108 },
+ { 0x02d5, 0x0120 },
+ { 0x02d8, 0x011c },
+ { 0x02dd, 0x016c },
+ { 0x02de, 0x015c },
+ { 0x02e5, 0x010b },
+ { 0x02e6, 0x0109 },
+ { 0x02f5, 0x0121 },
+ { 0x02f8, 0x011d },
+ { 0x02fd, 0x016d },
+ { 0x02fe, 0x015d },
+ { 0x03a2, 0x0138 },
+ { 0x03a3, 0x0156 },
+ { 0x03a5, 0x0128 },
+ { 0x03a6, 0x013b },
+ { 0x03aa, 0x0112 },
+ { 0x03ab, 0x0122 },
+ { 0x03ac, 0x0166 },
+ { 0x03b3, 0x0157 },
+ { 0x03b5, 0x0129 },
+ { 0x03b6, 0x013c },
+ { 0x03ba, 0x0113 },
+ { 0x03bb, 0x0123 },
+ { 0x03bc, 0x0167 },
+ { 0x03bd, 0x014a },
+ { 0x03bf, 0x014b },
+ { 0x03c0, 0x0100 },
+ { 0x03c7, 0x012e },
+ { 0x03cc, 0x0116 },
+ { 0x03cf, 0x012a },
+ { 0x03d1, 0x0145 },
+ { 0x03d2, 0x014c },
+ { 0x03d3, 0x0136 },
+ { 0x03d9, 0x0172 },
+ { 0x03dd, 0x0168 },
+ { 0x03de, 0x016a },
+ { 0x03e0, 0x0101 },
+ { 0x03e7, 0x012f },
+ { 0x03ec, 0x0117 },
+ { 0x03ef, 0x012b },
+ { 0x03f1, 0x0146 },
+ { 0x03f2, 0x014d },
+ { 0x03f3, 0x0137 },
+ { 0x03f9, 0x0173 },
+ { 0x03fd, 0x0169 },
+ { 0x03fe, 0x016b },
+ { 0x047e, 0x203e },
+ { 0x04a1, 0x3002 },
+ { 0x04a2, 0x300c },
+ { 0x04a3, 0x300d },
+ { 0x04a4, 0x3001 },
+ { 0x04a5, 0x30fb },
+ { 0x04a6, 0x30f2 },
+ { 0x04a7, 0x30a1 },
+ { 0x04a8, 0x30a3 },
+ { 0x04a9, 0x30a5 },
+ { 0x04aa, 0x30a7 },
+ { 0x04ab, 0x30a9 },
+ { 0x04ac, 0x30e3 },
+ { 0x04ad, 0x30e5 },
+ { 0x04ae, 0x30e7 },
+ { 0x04af, 0x30c3 },
+ { 0x04b0, 0x30fc },
+ { 0x04b1, 0x30a2 },
+ { 0x04b2, 0x30a4 },
+ { 0x04b3, 0x30a6 },
+ { 0x04b4, 0x30a8 },
+ { 0x04b5, 0x30aa },
+ { 0x04b6, 0x30ab },
+ { 0x04b7, 0x30ad },
+ { 0x04b8, 0x30af },
+ { 0x04b9, 0x30b1 },
+ { 0x04ba, 0x30b3 },
+ { 0x04bb, 0x30b5 },
+ { 0x04bc, 0x30b7 },
+ { 0x04bd, 0x30b9 },
+ { 0x04be, 0x30bb },
+ { 0x04bf, 0x30bd },
+ { 0x04c0, 0x30bf },
+ { 0x04c1, 0x30c1 },
+ { 0x04c2, 0x30c4 },
+ { 0x04c3, 0x30c6 },
+ { 0x04c4, 0x30c8 },
+ { 0x04c5, 0x30ca },
+ { 0x04c6, 0x30cb },
+ { 0x04c7, 0x30cc },
+ { 0x04c8, 0x30cd },
+ { 0x04c9, 0x30ce },
+ { 0x04ca, 0x30cf },
+ { 0x04cb, 0x30d2 },
+ { 0x04cc, 0x30d5 },
+ { 0x04cd, 0x30d8 },
+ { 0x04ce, 0x30db },
+ { 0x04cf, 0x30de },
+ { 0x04d0, 0x30df },
+ { 0x04d1, 0x30e0 },
+ { 0x04d2, 0x30e1 },
+ { 0x04d3, 0x30e2 },
+ { 0x04d4, 0x30e4 },
+ { 0x04d5, 0x30e6 },
+ { 0x04d6, 0x30e8 },
+ { 0x04d7, 0x30e9 },
+ { 0x04d8, 0x30ea },
+ { 0x04d9, 0x30eb },
+ { 0x04da, 0x30ec },
+ { 0x04db, 0x30ed },
+ { 0x04dc, 0x30ef },
+ { 0x04dd, 0x30f3 },
+ { 0x04de, 0x309b },
+ { 0x04df, 0x309c },
+ { 0x05ac, 0x060c },
+ { 0x05bb, 0x061b },
+ { 0x05bf, 0x061f },
+ { 0x05c1, 0x0621 },
+ { 0x05c2, 0x0622 },
+ { 0x05c3, 0x0623 },
+ { 0x05c4, 0x0624 },
+ { 0x05c5, 0x0625 },
+ { 0x05c6, 0x0626 },
+ { 0x05c7, 0x0627 },
+ { 0x05c8, 0x0628 },
+ { 0x05c9, 0x0629 },
+ { 0x05ca, 0x062a },
+ { 0x05cb, 0x062b },
+ { 0x05cc, 0x062c },
+ { 0x05cd, 0x062d },
+ { 0x05ce, 0x062e },
+ { 0x05cf, 0x062f },
+ { 0x05d0, 0x0630 },
+ { 0x05d1, 0x0631 },
+ { 0x05d2, 0x0632 },
+ { 0x05d3, 0x0633 },
+ { 0x05d4, 0x0634 },
+ { 0x05d5, 0x0635 },
+ { 0x05d6, 0x0636 },
+ { 0x05d7, 0x0637 },
+ { 0x05d8, 0x0638 },
+ { 0x05d9, 0x0639 },
+ { 0x05da, 0x063a },
+ { 0x05e0, 0x0640 },
+ { 0x05e1, 0x0641 },
+ { 0x05e2, 0x0642 },
+ { 0x05e3, 0x0643 },
+ { 0x05e4, 0x0644 },
+ { 0x05e5, 0x0645 },
+ { 0x05e6, 0x0646 },
+ { 0x05e7, 0x0647 },
+ { 0x05e8, 0x0648 },
+ { 0x05e9, 0x0649 },
+ { 0x05ea, 0x064a },
+ { 0x05eb, 0x064b },
+ { 0x05ec, 0x064c },
+ { 0x05ed, 0x064d },
+ { 0x05ee, 0x064e },
+ { 0x05ef, 0x064f },
+ { 0x05f0, 0x0650 },
+ { 0x05f1, 0x0651 },
+ { 0x05f2, 0x0652 },
+ { 0x06a1, 0x0452 },
+ { 0x06a2, 0x0453 },
+ { 0x06a3, 0x0451 },
+ { 0x06a4, 0x0454 },
+ { 0x06a5, 0x0455 },
+ { 0x06a6, 0x0456 },
+ { 0x06a7, 0x0457 },
+ { 0x06a8, 0x0458 },
+ { 0x06a9, 0x0459 },
+ { 0x06aa, 0x045a },
+ { 0x06ab, 0x045b },
+ { 0x06ac, 0x045c },
+ { 0x06ae, 0x045e },
+ { 0x06af, 0x045f },
+ { 0x06b0, 0x2116 },
+ { 0x06b1, 0x0402 },
+ { 0x06b2, 0x0403 },
+ { 0x06b3, 0x0401 },
+ { 0x06b4, 0x0404 },
+ { 0x06b5, 0x0405 },
+ { 0x06b6, 0x0406 },
+ { 0x06b7, 0x0407 },
+ { 0x06b8, 0x0408 },
+ { 0x06b9, 0x0409 },
+ { 0x06ba, 0x040a },
+ { 0x06bb, 0x040b },
+ { 0x06bc, 0x040c },
+ { 0x06be, 0x040e },
+ { 0x06bf, 0x040f },
+ { 0x06c0, 0x044e },
+ { 0x06c1, 0x0430 },
+ { 0x06c2, 0x0431 },
+ { 0x06c3, 0x0446 },
+ { 0x06c4, 0x0434 },
+ { 0x06c5, 0x0435 },
+ { 0x06c6, 0x0444 },
+ { 0x06c7, 0x0433 },
+ { 0x06c8, 0x0445 },
+ { 0x06c9, 0x0438 },
+ { 0x06ca, 0x0439 },
+ { 0x06cb, 0x043a },
+ { 0x06cc, 0x043b },
+ { 0x06cd, 0x043c },
+ { 0x06ce, 0x043d },
+ { 0x06cf, 0x043e },
+ { 0x06d0, 0x043f },
+ { 0x06d1, 0x044f },
+ { 0x06d2, 0x0440 },
+ { 0x06d3, 0x0441 },
+ { 0x06d4, 0x0442 },
+ { 0x06d5, 0x0443 },
+ { 0x06d6, 0x0436 },
+ { 0x06d7, 0x0432 },
+ { 0x06d8, 0x044c },
+ { 0x06d9, 0x044b },
+ { 0x06da, 0x0437 },
+ { 0x06db, 0x0448 },
+ { 0x06dc, 0x044d },
+ { 0x06dd, 0x0449 },
+ { 0x06de, 0x0447 },
+ { 0x06df, 0x044a },
+ { 0x06e0, 0x042e },
+ { 0x06e1, 0x0410 },
+ { 0x06e2, 0x0411 },
+ { 0x06e3, 0x0426 },
+ { 0x06e4, 0x0414 },
+ { 0x06e5, 0x0415 },
+ { 0x06e6, 0x0424 },
+ { 0x06e7, 0x0413 },
+ { 0x06e8, 0x0425 },
+ { 0x06e9, 0x0418 },
+ { 0x06ea, 0x0419 },
+ { 0x06eb, 0x041a },
+ { 0x06ec, 0x041b },
+ { 0x06ed, 0x041c },
+ { 0x06ee, 0x041d },
+ { 0x06ef, 0x041e },
+ { 0x06f0, 0x041f },
+ { 0x06f1, 0x042f },
+ { 0x06f2, 0x0420 },
+ { 0x06f3, 0x0421 },
+ { 0x06f4, 0x0422 },
+ { 0x06f5, 0x0423 },
+ { 0x06f6, 0x0416 },
+ { 0x06f7, 0x0412 },
+ { 0x06f8, 0x042c },
+ { 0x06f9, 0x042b },
+ { 0x06fa, 0x0417 },
+ { 0x06fb, 0x0428 },
+ { 0x06fc, 0x042d },
+ { 0x06fd, 0x0429 },
+ { 0x06fe, 0x0427 },
+ { 0x06ff, 0x042a },
+ { 0x07a1, 0x0386 },
+ { 0x07a2, 0x0388 },
+ { 0x07a3, 0x0389 },
+ { 0x07a4, 0x038a },
+ { 0x07a5, 0x03aa },
+ { 0x07a7, 0x038c },
+ { 0x07a8, 0x038e },
+ { 0x07a9, 0x03ab },
+ { 0x07ab, 0x038f },
+ { 0x07ae, 0x0385 },
+ { 0x07af, 0x2015 },
+ { 0x07b1, 0x03ac },
+ { 0x07b2, 0x03ad },
+ { 0x07b3, 0x03ae },
+ { 0x07b4, 0x03af },
+ { 0x07b5, 0x03ca },
+ { 0x07b6, 0x0390 },
+ { 0x07b7, 0x03cc },
+ { 0x07b8, 0x03cd },
+ { 0x07b9, 0x03cb },
+ { 0x07ba, 0x03b0 },
+ { 0x07bb, 0x03ce },
+ { 0x07c1, 0x0391 },
+ { 0x07c2, 0x0392 },
+ { 0x07c3, 0x0393 },
+ { 0x07c4, 0x0394 },
+ { 0x07c5, 0x0395 },
+ { 0x07c6, 0x0396 },
+ { 0x07c7, 0x0397 },
+ { 0x07c8, 0x0398 },
+ { 0x07c9, 0x0399 },
+ { 0x07ca, 0x039a },
+ { 0x07cb, 0x039b },
+ { 0x07cc, 0x039c },
+ { 0x07cd, 0x039d },
+ { 0x07ce, 0x039e },
+ { 0x07cf, 0x039f },
+ { 0x07d0, 0x03a0 },
+ { 0x07d1, 0x03a1 },
+ { 0x07d2, 0x03a3 },
+ { 0x07d4, 0x03a4 },
+ { 0x07d5, 0x03a5 },
+ { 0x07d6, 0x03a6 },
+ { 0x07d7, 0x03a7 },
+ { 0x07d8, 0x03a8 },
+ { 0x07d9, 0x03a9 },
+ { 0x07e1, 0x03b1 },
+ { 0x07e2, 0x03b2 },
+ { 0x07e3, 0x03b3 },
+ { 0x07e4, 0x03b4 },
+ { 0x07e5, 0x03b5 },
+ { 0x07e6, 0x03b6 },
+ { 0x07e7, 0x03b7 },
+ { 0x07e8, 0x03b8 },
+ { 0x07e9, 0x03b9 },
+ { 0x07ea, 0x03ba },
+ { 0x07eb, 0x03bb },
+ { 0x07ec, 0x03bc },
+ { 0x07ed, 0x03bd },
+ { 0x07ee, 0x03be },
+ { 0x07ef, 0x03bf },
+ { 0x07f0, 0x03c0 },
+ { 0x07f1, 0x03c1 },
+ { 0x07f2, 0x03c3 },
+ { 0x07f3, 0x03c2 },
+ { 0x07f4, 0x03c4 },
+ { 0x07f5, 0x03c5 },
+ { 0x07f6, 0x03c6 },
+ { 0x07f7, 0x03c7 },
+ { 0x07f8, 0x03c8 },
+ { 0x07f9, 0x03c9 },
+ { 0x08a1, 0x23b7 },
+ { 0x08a2, 0x250c },
+ { 0x08a3, 0x2500 },
+ { 0x08a4, 0x2320 },
+ { 0x08a5, 0x2321 },
+ { 0x08a6, 0x2502 },
+ { 0x08a7, 0x23a1 },
+ { 0x08a8, 0x23a3 },
+ { 0x08a9, 0x23a4 },
+ { 0x08aa, 0x23a6 },
+ { 0x08ab, 0x239b },
+ { 0x08ac, 0x239d },
+ { 0x08ad, 0x239e },
+ { 0x08ae, 0x23a0 },
+ { 0x08af, 0x23a8 },
+ { 0x08b0, 0x23ac },
+ { 0x08bc, 0x2264 },
+ { 0x08bd, 0x2260 },
+ { 0x08be, 0x2265 },
+ { 0x08bf, 0x222b },
+ { 0x08c0, 0x2234 },
+ { 0x08c1, 0x221d },
+ { 0x08c2, 0x221e },
+ { 0x08c5, 0x2207 },
+ { 0x08c8, 0x223c },
+ { 0x08c9, 0x2243 },
+ { 0x08cd, 0x21d4 },
+ { 0x08ce, 0x21d2 },
+ { 0x08cf, 0x2261 },
+ { 0x08d6, 0x221a },
+ { 0x08da, 0x2282 },
+ { 0x08db, 0x2283 },
+ { 0x08dc, 0x2229 },
+ { 0x08dd, 0x222a },
+ { 0x08de, 0x2227 },
+ { 0x08df, 0x2228 },
+ { 0x08ef, 0x2202 },
+ { 0x08f6, 0x0192 },
+ { 0x08fb, 0x2190 },
+ { 0x08fc, 0x2191 },
+ { 0x08fd, 0x2192 },
+ { 0x08fe, 0x2193 },
+ { 0x09e0, 0x25c6 },
+ { 0x09e1, 0x2592 },
+ { 0x09e2, 0x2409 },
+ { 0x09e3, 0x240c },
+ { 0x09e4, 0x240d },
+ { 0x09e5, 0x240a },
+ { 0x09e8, 0x2424 },
+ { 0x09e9, 0x240b },
+ { 0x09ea, 0x2518 },
+ { 0x09eb, 0x2510 },
+ { 0x09ec, 0x250c },
+ { 0x09ed, 0x2514 },
+ { 0x09ee, 0x253c },
+ { 0x09ef, 0x23ba },
+ { 0x09f0, 0x23bb },
+ { 0x09f1, 0x2500 },
+ { 0x09f2, 0x23bc },
+ { 0x09f3, 0x23bd },
+ { 0x09f4, 0x251c },
+ { 0x09f5, 0x2524 },
+ { 0x09f6, 0x2534 },
+ { 0x09f7, 0x252c },
+ { 0x09f8, 0x2502 },
+ { 0x0aa1, 0x2003 },
+ { 0x0aa2, 0x2002 },
+ { 0x0aa3, 0x2004 },
+ { 0x0aa4, 0x2005 },
+ { 0x0aa5, 0x2007 },
+ { 0x0aa6, 0x2008 },
+ { 0x0aa7, 0x2009 },
+ { 0x0aa8, 0x200a },
+ { 0x0aa9, 0x2014 },
+ { 0x0aaa, 0x2013 },
+ { 0x0aae, 0x2026 },
+ { 0x0aaf, 0x2025 },
+ { 0x0ab0, 0x2153 },
+ { 0x0ab1, 0x2154 },
+ { 0x0ab2, 0x2155 },
+ { 0x0ab3, 0x2156 },
+ { 0x0ab4, 0x2157 },
+ { 0x0ab5, 0x2158 },
+ { 0x0ab6, 0x2159 },
+ { 0x0ab7, 0x215a },
+ { 0x0ab8, 0x2105 },
+ { 0x0abb, 0x2012 },
+ { 0x0abc, 0x2329 },
+ { 0x0abe, 0x232a },
+ { 0x0ac3, 0x215b },
+ { 0x0ac4, 0x215c },
+ { 0x0ac5, 0x215d },
+ { 0x0ac6, 0x215e },
+ { 0x0ac9, 0x2122 },
+ { 0x0aca, 0x2613 },
+ { 0x0acc, 0x25c1 },
+ { 0x0acd, 0x25b7 },
+ { 0x0ace, 0x25cb },
+ { 0x0acf, 0x25af },
+ { 0x0ad0, 0x2018 },
+ { 0x0ad1, 0x2019 },
+ { 0x0ad2, 0x201c },
+ { 0x0ad3, 0x201d },
+ { 0x0ad4, 0x211e },
+ { 0x0ad6, 0x2032 },
+ { 0x0ad7, 0x2033 },
+ { 0x0ad9, 0x271d },
+ { 0x0adb, 0x25ac },
+ { 0x0adc, 0x25c0 },
+ { 0x0add, 0x25b6 },
+ { 0x0ade, 0x25cf },
+ { 0x0adf, 0x25ae },
+ { 0x0ae0, 0x25e6 },
+ { 0x0ae1, 0x25ab },
+ { 0x0ae2, 0x25ad },
+ { 0x0ae3, 0x25b3 },
+ { 0x0ae4, 0x25bd },
+ { 0x0ae5, 0x2606 },
+ { 0x0ae6, 0x2022 },
+ { 0x0ae7, 0x25aa },
+ { 0x0ae8, 0x25b2 },
+ { 0x0ae9, 0x25bc },
+ { 0x0aea, 0x261c },
+ { 0x0aeb, 0x261e },
+ { 0x0aec, 0x2663 },
+ { 0x0aed, 0x2666 },
+ { 0x0aee, 0x2665 },
+ { 0x0af0, 0x2720 },
+ { 0x0af1, 0x2020 },
+ { 0x0af2, 0x2021 },
+ { 0x0af3, 0x2713 },
+ { 0x0af4, 0x2717 },
+ { 0x0af5, 0x266f },
+ { 0x0af6, 0x266d },
+ { 0x0af7, 0x2642 },
+ { 0x0af8, 0x2640 },
+ { 0x0af9, 0x260e },
+ { 0x0afa, 0x2315 },
+ { 0x0afb, 0x2117 },
+ { 0x0afc, 0x2038 },
+ { 0x0afd, 0x201a },
+ { 0x0afe, 0x201e },
+ { 0x0ba3, 0x003c },
+ { 0x0ba6, 0x003e },
+ { 0x0ba8, 0x2228 },
+ { 0x0ba9, 0x2227 },
+ { 0x0bc0, 0x00af },
+ { 0x0bc2, 0x22a5 },
+ { 0x0bc3, 0x2229 },
+ { 0x0bc4, 0x230a },
+ { 0x0bc6, 0x005f },
+ { 0x0bca, 0x2218 },
+ { 0x0bcc, 0x2395 },
+ { 0x0bce, 0x22a4 },
+ { 0x0bcf, 0x25cb },
+ { 0x0bd3, 0x2308 },
+ { 0x0bd6, 0x222a },
+ { 0x0bd8, 0x2283 },
+ { 0x0bda, 0x2282 },
+ { 0x0bdc, 0x22a2 },
+ { 0x0bfc, 0x22a3 },
+ { 0x0cdf, 0x2017 },
+ { 0x0ce0, 0x05d0 },
+ { 0x0ce1, 0x05d1 },
+ { 0x0ce2, 0x05d2 },
+ { 0x0ce3, 0x05d3 },
+ { 0x0ce4, 0x05d4 },
+ { 0x0ce5, 0x05d5 },
+ { 0x0ce6, 0x05d6 },
+ { 0x0ce7, 0x05d7 },
+ { 0x0ce8, 0x05d8 },
+ { 0x0ce9, 0x05d9 },
+ { 0x0cea, 0x05da },
+ { 0x0ceb, 0x05db },
+ { 0x0cec, 0x05dc },
+ { 0x0ced, 0x05dd },
+ { 0x0cee, 0x05de },
+ { 0x0cef, 0x05df },
+ { 0x0cf0, 0x05e0 },
+ { 0x0cf1, 0x05e1 },
+ { 0x0cf2, 0x05e2 },
+ { 0x0cf3, 0x05e3 },
+ { 0x0cf4, 0x05e4 },
+ { 0x0cf5, 0x05e5 },
+ { 0x0cf6, 0x05e6 },
+ { 0x0cf7, 0x05e7 },
+ { 0x0cf8, 0x05e8 },
+ { 0x0cf9, 0x05e9 },
+ { 0x0cfa, 0x05ea },
+ { 0x0da1, 0x0e01 },
+ { 0x0da2, 0x0e02 },
+ { 0x0da3, 0x0e03 },
+ { 0x0da4, 0x0e04 },
+ { 0x0da5, 0x0e05 },
+ { 0x0da6, 0x0e06 },
+ { 0x0da7, 0x0e07 },
+ { 0x0da8, 0x0e08 },
+ { 0x0da9, 0x0e09 },
+ { 0x0daa, 0x0e0a },
+ { 0x0dab, 0x0e0b },
+ { 0x0dac, 0x0e0c },
+ { 0x0dad, 0x0e0d },
+ { 0x0dae, 0x0e0e },
+ { 0x0daf, 0x0e0f },
+ { 0x0db0, 0x0e10 },
+ { 0x0db1, 0x0e11 },
+ { 0x0db2, 0x0e12 },
+ { 0x0db3, 0x0e13 },
+ { 0x0db4, 0x0e14 },
+ { 0x0db5, 0x0e15 },
+ { 0x0db6, 0x0e16 },
+ { 0x0db7, 0x0e17 },
+ { 0x0db8, 0x0e18 },
+ { 0x0db9, 0x0e19 },
+ { 0x0dba, 0x0e1a },
+ { 0x0dbb, 0x0e1b },
+ { 0x0dbc, 0x0e1c },
+ { 0x0dbd, 0x0e1d },
+ { 0x0dbe, 0x0e1e },
+ { 0x0dbf, 0x0e1f },
+ { 0x0dc0, 0x0e20 },
+ { 0x0dc1, 0x0e21 },
+ { 0x0dc2, 0x0e22 },
+ { 0x0dc3, 0x0e23 },
+ { 0x0dc4, 0x0e24 },
+ { 0x0dc5, 0x0e25 },
+ { 0x0dc6, 0x0e26 },
+ { 0x0dc7, 0x0e27 },
+ { 0x0dc8, 0x0e28 },
+ { 0x0dc9, 0x0e29 },
+ { 0x0dca, 0x0e2a },
+ { 0x0dcb, 0x0e2b },
+ { 0x0dcc, 0x0e2c },
+ { 0x0dcd, 0x0e2d },
+ { 0x0dce, 0x0e2e },
+ { 0x0dcf, 0x0e2f },
+ { 0x0dd0, 0x0e30 },
+ { 0x0dd1, 0x0e31 },
+ { 0x0dd2, 0x0e32 },
+ { 0x0dd3, 0x0e33 },
+ { 0x0dd4, 0x0e34 },
+ { 0x0dd5, 0x0e35 },
+ { 0x0dd6, 0x0e36 },
+ { 0x0dd7, 0x0e37 },
+ { 0x0dd8, 0x0e38 },
+ { 0x0dd9, 0x0e39 },
+ { 0x0dda, 0x0e3a },
+ { 0x0ddf, 0x0e3f },
+ { 0x0de0, 0x0e40 },
+ { 0x0de1, 0x0e41 },
+ { 0x0de2, 0x0e42 },
+ { 0x0de3, 0x0e43 },
+ { 0x0de4, 0x0e44 },
+ { 0x0de5, 0x0e45 },
+ { 0x0de6, 0x0e46 },
+ { 0x0de7, 0x0e47 },
+ { 0x0de8, 0x0e48 },
+ { 0x0de9, 0x0e49 },
+ { 0x0dea, 0x0e4a },
+ { 0x0deb, 0x0e4b },
+ { 0x0dec, 0x0e4c },
+ { 0x0ded, 0x0e4d },
+ { 0x0df0, 0x0e50 },
+ { 0x0df1, 0x0e51 },
+ { 0x0df2, 0x0e52 },
+ { 0x0df3, 0x0e53 },
+ { 0x0df4, 0x0e54 },
+ { 0x0df5, 0x0e55 },
+ { 0x0df6, 0x0e56 },
+ { 0x0df7, 0x0e57 },
+ { 0x0df8, 0x0e58 },
+ { 0x0df9, 0x0e59 },
+ { 0x0ea1, 0x3131 },
+ { 0x0ea2, 0x3132 },
+ { 0x0ea3, 0x3133 },
+ { 0x0ea4, 0x3134 },
+ { 0x0ea5, 0x3135 },
+ { 0x0ea6, 0x3136 },
+ { 0x0ea7, 0x3137 },
+ { 0x0ea8, 0x3138 },
+ { 0x0ea9, 0x3139 },
+ { 0x0eaa, 0x313a },
+ { 0x0eab, 0x313b },
+ { 0x0eac, 0x313c },
+ { 0x0ead, 0x313d },
+ { 0x0eae, 0x313e },
+ { 0x0eaf, 0x313f },
+ { 0x0eb0, 0x3140 },
+ { 0x0eb1, 0x3141 },
+ { 0x0eb2, 0x3142 },
+ { 0x0eb3, 0x3143 },
+ { 0x0eb4, 0x3144 },
+ { 0x0eb5, 0x3145 },
+ { 0x0eb6, 0x3146 },
+ { 0x0eb7, 0x3147 },
+ { 0x0eb8, 0x3148 },
+ { 0x0eb9, 0x3149 },
+ { 0x0eba, 0x314a },
+ { 0x0ebb, 0x314b },
+ { 0x0ebc, 0x314c },
+ { 0x0ebd, 0x314d },
+ { 0x0ebe, 0x314e },
+ { 0x0ebf, 0x314f },
+ { 0x0ec0, 0x3150 },
+ { 0x0ec1, 0x3151 },
+ { 0x0ec2, 0x3152 },
+ { 0x0ec3, 0x3153 },
+ { 0x0ec4, 0x3154 },
+ { 0x0ec5, 0x3155 },
+ { 0x0ec6, 0x3156 },
+ { 0x0ec7, 0x3157 },
+ { 0x0ec8, 0x3158 },
+ { 0x0ec9, 0x3159 },
+ { 0x0eca, 0x315a },
+ { 0x0ecb, 0x315b },
+ { 0x0ecc, 0x315c },
+ { 0x0ecd, 0x315d },
+ { 0x0ece, 0x315e },
+ { 0x0ecf, 0x315f },
+ { 0x0ed0, 0x3160 },
+ { 0x0ed1, 0x3161 },
+ { 0x0ed2, 0x3162 },
+ { 0x0ed3, 0x3163 },
+ { 0x0ed4, 0x11a8 },
+ { 0x0ed5, 0x11a9 },
+ { 0x0ed6, 0x11aa },
+ { 0x0ed7, 0x11ab },
+ { 0x0ed8, 0x11ac },
+ { 0x0ed9, 0x11ad },
+ { 0x0eda, 0x11ae },
+ { 0x0edb, 0x11af },
+ { 0x0edc, 0x11b0 },
+ { 0x0edd, 0x11b1 },
+ { 0x0ede, 0x11b2 },
+ { 0x0edf, 0x11b3 },
+ { 0x0ee0, 0x11b4 },
+ { 0x0ee1, 0x11b5 },
+ { 0x0ee2, 0x11b6 },
+ { 0x0ee3, 0x11b7 },
+ { 0x0ee4, 0x11b8 },
+ { 0x0ee5, 0x11b9 },
+ { 0x0ee6, 0x11ba },
+ { 0x0ee7, 0x11bb },
+ { 0x0ee8, 0x11bc },
+ { 0x0ee9, 0x11bd },
+ { 0x0eea, 0x11be },
+ { 0x0eeb, 0x11bf },
+ { 0x0eec, 0x11c0 },
+ { 0x0eed, 0x11c1 },
+ { 0x0eee, 0x11c2 },
+ { 0x0eef, 0x316d },
+ { 0x0ef0, 0x3171 },
+ { 0x0ef1, 0x3178 },
+ { 0x0ef2, 0x317f },
+ { 0x0ef3, 0x3181 },
+ { 0x0ef4, 0x3184 },
+ { 0x0ef5, 0x3186 },
+ { 0x0ef6, 0x318d },
+ { 0x0ef7, 0x318e },
+ { 0x0ef8, 0x11eb },
+ { 0x0ef9, 0x11f0 },
+ { 0x0efa, 0x11f9 },
+ { 0x0eff, 0x20a9 },
+ { 0x13a4, 0x20ac },
+ { 0x13bc, 0x0152 },
+ { 0x13bd, 0x0153 },
+ { 0x13be, 0x0178 },
+ { 0x20ac, 0x20ac },
+ { 0xfe50, '`' },
+ { 0xfe51, 0x00b4 },
+ { 0xfe52, '^' },
+ { 0xfe53, '~' },
+ { 0xfe54, 0x00af },
+ { 0xfe55, 0x02d8 },
+ { 0xfe56, 0x02d9 },
+ { 0xfe57, 0x00a8 },
+ { 0xfe58, 0x02da },
+ { 0xfe59, 0x02dd },
+ { 0xfe5a, 0x02c7 },
+ { 0xfe5b, 0x00b8 },
+ { 0xfe5c, 0x02db },
+ { 0xfe5d, 0x037a },
+ { 0xfe5e, 0x309b },
+ { 0xfe5f, 0x309c },
+ { 0xfe63, '/' },
+ { 0xfe64, 0x02bc },
+ { 0xfe65, 0x02bd },
+ { 0xfe66, 0x02f5 },
+ { 0xfe67, 0x02f3 },
+ { 0xfe68, 0x02cd },
+ { 0xfe69, 0xa788 },
+ { 0xfe6a, 0x02f7 },
+ { 0xfe6e, ',' },
+ { 0xfe6f, 0x00a4 },
+ { 0xfe80, 'a' }, // XK_dead_a
+ { 0xfe81, 'A' }, // XK_dead_A
+ { 0xfe82, 'e' }, // XK_dead_e
+ { 0xfe83, 'E' }, // XK_dead_E
+ { 0xfe84, 'i' }, // XK_dead_i
+ { 0xfe85, 'I' }, // XK_dead_I
+ { 0xfe86, 'o' }, // XK_dead_o
+ { 0xfe87, 'O' }, // XK_dead_O
+ { 0xfe88, 'u' }, // XK_dead_u
+ { 0xfe89, 'U' }, // XK_dead_U
+ { 0xfe8a, 0x0259 },
+ { 0xfe8b, 0x018f },
+ { 0xfe8c, 0x00b5 },
+ { 0xfe90, '_' },
+ { 0xfe91, 0x02c8 },
+ { 0xfe92, 0x02cc },
+ { 0xff80 /*XKB_KEY_KP_Space*/, ' ' },
+ { 0xff95 /*XKB_KEY_KP_7*/, 0x0037 },
+ { 0xff96 /*XKB_KEY_KP_4*/, 0x0034 },
+ { 0xff97 /*XKB_KEY_KP_8*/, 0x0038 },
+ { 0xff98 /*XKB_KEY_KP_6*/, 0x0036 },
+ { 0xff99 /*XKB_KEY_KP_2*/, 0x0032 },
+ { 0xff9a /*XKB_KEY_KP_9*/, 0x0039 },
+ { 0xff9b /*XKB_KEY_KP_3*/, 0x0033 },
+ { 0xff9c /*XKB_KEY_KP_1*/, 0x0031 },
+ { 0xff9d /*XKB_KEY_KP_5*/, 0x0035 },
+ { 0xff9e /*XKB_KEY_KP_0*/, 0x0030 },
+ { 0xffaa /*XKB_KEY_KP_Multiply*/, '*' },
+ { 0xffab /*XKB_KEY_KP_Add*/, '+' },
+ { 0xffac /*XKB_KEY_KP_Separator*/, ',' },
+ { 0xffad /*XKB_KEY_KP_Subtract*/, '-' },
+ { 0xffae /*XKB_KEY_KP_Decimal*/, '.' },
+ { 0xffaf /*XKB_KEY_KP_Divide*/, '/' },
+ { 0xffb0 /*XKB_KEY_KP_0*/, 0x0030 },
+ { 0xffb1 /*XKB_KEY_KP_1*/, 0x0031 },
+ { 0xffb2 /*XKB_KEY_KP_2*/, 0x0032 },
+ { 0xffb3 /*XKB_KEY_KP_3*/, 0x0033 },
+ { 0xffb4 /*XKB_KEY_KP_4*/, 0x0034 },
+ { 0xffb5 /*XKB_KEY_KP_5*/, 0x0035 },
+ { 0xffb6 /*XKB_KEY_KP_6*/, 0x0036 },
+ { 0xffb7 /*XKB_KEY_KP_7*/, 0x0037 },
+ { 0xffb8 /*XKB_KEY_KP_8*/, 0x0038 },
+ { 0xffb9 /*XKB_KEY_KP_9*/, 0x0039 },
+ { 0xffbd /*XKB_KEY_KP_Equal*/, '=' }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Convert XKB KeySym to Unicode
+//
+long _glfwKeySym2Unicode(unsigned int keysym)
+{
+ int min = 0;
+ int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+ int mid;
+
+ // First check for Latin-1 characters (1:1 mapping)
+ if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+ (keysym >= 0x00a0 && keysym <= 0x00ff))
+ {
+ return keysym;
+ }
+
+ // Also check for directly encoded 24-bit UCS characters
+ if ((keysym & 0xff000000) == 0x01000000)
+ return keysym & 0x00ffffff;
+
+ // Binary search in table
+ while (max >= min)
+ {
+ mid = (min + max) / 2;
+ if (keysymtab[mid].keysym < keysym)
+ min = mid + 1;
+ else if (keysymtab[mid].keysym > keysym)
+ max = mid - 1;
+ else
+ return keysymtab[mid].ucs;
+ }
+
+ // No matching Unicode value found
+ return -1;
+}
+
diff --git a/Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.h b/Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.h
new file mode 100644
index 0000000..f95e14f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/glfw/src/xkb_unicode.h
@@ -0,0 +1,28 @@
+//========================================================================
+// GLFW 3.3 Linux - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+long _glfwKeySym2Unicode(unsigned int keysym);
+
diff --git a/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt b/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt
new file mode 100644
index 0000000..c42dcc9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt
@@ -0,0 +1,19 @@
+# dear imgui
+set(IMGUI_SOURCE_FILES
+ imgui.cpp
+ imgui_demo.cpp
+ imgui_draw.cpp
+ imgui_widgets.cpp)
+
+set(IMGUI_HEADER_FILES
+ imconfig.h
+ imgui.h
+ imgui_internal.h
+ imstb_rectpack.h
+ imstb_textedit.h
+ imstb_truetype.h)
+
+add_library(imgui STATIC ${IMGUI_SOURCE_FILES} ${IMGUI_HEADER_FILES})
+target_include_directories(imgui PUBLIC ..)
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${IMGUI_SOURCE_FILES} ${IMGUI_HEADER_FILES})
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imconfig.h b/Client/ThirdParty/Box2D/extern/imgui/imconfig.h
new file mode 100644
index 0000000..825505b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imconfig.h
@@ -0,0 +1,73 @@
+//-----------------------------------------------------------------------------
+// COMPILE-TIME OPTIONS FOR DEAR IMGUI
+// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
+// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
+//-----------------------------------------------------------------------------
+// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h)
+// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
+// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include
+// the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures.
+// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
+// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+//---- Define assertion handler. Defaults to calling assert().
+//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
+//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
+
+//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
+//#define IMGUI_API __declspec( dllexport )
+//#define IMGUI_API __declspec( dllimport )
+
+//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
+//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
+//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
+//#define IMGUI_DISABLE_DEMO_WINDOWS
+
+//---- Don't implement some functions to reduce linkage requirements.
+//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
+//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
+//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function.
+//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf.
+//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h.
+//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
+
+//---- Include imgui_user.h at the end of imgui.h as a convenience
+//#define IMGUI_INCLUDE_IMGUI_USER_H
+
+//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
+//#define IMGUI_USE_BGRA_PACKED_COLOR
+
+//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
+// By default the embedded implementations are declared static and not available outside of imgui cpp files.
+//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
+//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
+//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
+//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
+
+//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
+// This will be inlined as part of ImVec2 and ImVec4 class declarations.
+/*
+#define IM_VEC2_CLASS_EXTRA \
+ ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
+ operator MyVec2() const { return MyVec2(x,y); }
+
+#define IM_VEC4_CLASS_EXTRA \
+ ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
+ operator MyVec4() const { return MyVec4(x,y,z,w); }
+*/
+
+//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it.
+//#define ImDrawIdx unsigned int
+
+//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
+/*
+namespace ImGui
+{
+ void MyFunction(const char* name, const MyMatrix44& v);
+}
+*/
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imgui.cpp b/Client/ThirdParty/Box2D/extern/imgui/imgui.cpp
new file mode 100644
index 0000000..8c11891
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imgui.cpp
@@ -0,0 +1,9349 @@
+// dear imgui, v1.67 WIP
+// (main code and documentation)
+
+// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code.
+// Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
+// Get latest version at https://github.com/ocornut/imgui
+// Releases change-log at https://github.com/ocornut/imgui/releases
+// Technical Support for Getting Started https://discourse.dearimgui.org/c/getting-started
+// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269
+
+// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
+// See LICENSE.txt for copyright and licensing details (standard MIT License).
+// This library is free but I need your support to sustain development and maintenance.
+// Businesses: you can support continued maintenance and development via support contracts or sponsoring, see docs/README.
+// Individuals: you can support continued maintenance and development via donations or Patreon https://www.patreon.com/imgui.
+
+// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library.
+// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without
+// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't
+// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you
+// to a better solution or official support for them.
+
+/*
+
+Index of this file:
+
+DOCUMENTATION
+
+- MISSION STATEMENT
+- END-USER GUIDE
+- PROGRAMMER GUIDE (read me!)
+ - Read first.
+ - How to update to a newer version of Dear ImGui.
+ - Getting started with integrating Dear ImGui in your code/engine.
+ - This is how a simple application may look like (2 variations).
+ - This is how a simple rendering function may look like.
+ - Using gamepad/keyboard navigation controls.
+- API BREAKING CHANGES (read me when you update!)
+- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
+ - How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
+ - How can I display an image? What is ImTextureID, how does it works?
+ - How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.
+ - How can I use my own math types instead of ImVec2/ImVec4?
+ - How can I load a different font than the default?
+ - How can I easily use icons in my application?
+ - How can I load multiple fonts?
+ - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
+ - How can I interact with standard C++ types (such as std::string and std::vector)?
+ - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
+ - How can I use Dear ImGui on a platform that doesn't have a mouse or a keyboard? (input share, remoting, gamepad)
+ - I integrated Dear ImGui in my engine and the text or lines are blurry..
+ - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
+ - How can I help?
+
+CODE
+(search for "[SECTION]" in the code to find them)
+
+// [SECTION] FORWARD DECLARATIONS
+// [SECTION] CONTEXT AND MEMORY ALLOCATORS
+// [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
+// [SECTION] MISC HELPER/UTILITIES (Maths, String, Format, Hash, File functions)
+// [SECTION] MISC HELPER/UTILITIES (ImText* functions)
+// [SECTION] MISC HELPER/UTILITIES (Color functions)
+// [SECTION] ImGuiStorage
+// [SECTION] ImGuiTextFilter
+// [SECTION] ImGuiTextBuffer
+// [SECTION] ImGuiListClipper
+// [SECTION] RENDER HELPERS
+// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
+// [SECTION] TOOLTIPS
+// [SECTION] POPUPS
+// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
+// [SECTION] COLUMNS
+// [SECTION] DRAG AND DROP
+// [SECTION] LOGGING/CAPTURING
+// [SECTION] SETTINGS
+// [SECTION] PLATFORM DEPENDENT HELPERS
+// [SECTION] METRICS/DEBUG WINDOW
+
+*/
+
+//-----------------------------------------------------------------------------
+// DOCUMENTATION
+//-----------------------------------------------------------------------------
+
+/*
+
+ MISSION STATEMENT
+ =================
+
+ - Easy to use to create code-driven and data-driven tools.
+ - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools.
+ - Easy to hack and improve.
+ - Minimize screen real-estate usage.
+ - Minimize setup and maintenance.
+ - Minimize state storage on user side.
+ - Portable, minimize dependencies, run on target (consoles, phones, etc.).
+ - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,.
+ opening a tree node for the first time, etc. but a typical frame should not allocate anything).
+
+ Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
+ - Doesn't look fancy, doesn't animate.
+ - Limited layout features, intricate layouts are typically crafted in code.
+
+
+ END-USER GUIDE
+ ==============
+
+ - Double-click on title bar to collapse window.
+ - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
+ - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
+ - Click and drag on any empty space to move window.
+ - TAB/SHIFT+TAB to cycle through keyboard editable fields.
+ - CTRL+Click on a slider or drag box to input value as text.
+ - Use mouse wheel to scroll.
+ - Text editor:
+ - Hold SHIFT or use mouse to select text.
+ - CTRL+Left/Right to word jump.
+ - CTRL+Shift+Left/Right to select words.
+ - CTRL+A our Double-Click to select all.
+ - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
+ - CTRL+Z,CTRL+Y to undo/redo.
+ - ESCAPE to revert text to its original value.
+ - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
+ - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
+ - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
+ - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW
+
+
+ PROGRAMMER GUIDE
+ ================
+
+ READ FIRST:
+
+ - Read the FAQ below this section!
+ - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction
+ or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, less bugs.
+ - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
+ - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
+ - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
+ You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links docs/README.md.
+ - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances.
+ For every application frame your UI code will be called only once. This is in contrast to e.g. Unity's own implementation of an IMGUI,
+ where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches.
+ - Our origin are on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right.
+ - This codebase is also optimized to yield decent performances with typical "Debug" builds settings.
+ - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected).
+ If you get an assert, read the messages and comments around the assert.
+ - C++: this is a very C-ish codebase: we don't rely on C++11, we don't include any C++ headers, and ImGui:: is a namespace.
+ - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types.
+ See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that.
+ However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase.
+ - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!).
+
+ HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI:
+
+ - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
+ - Or maintain your own branch where you have imconfig.h modified.
+ - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
+ If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
+ from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
+ likely be a comment about it. Please report any issue to the GitHub page!
+ - Try to keep your copy of dear imgui reasonably up to date.
+
+ GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE:
+
+ - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library.
+ - Add the Dear ImGui source files to your projects or using your preferred build system.
+ It is recommended you build and statically link the .cpp files as part of your project and not as shared library (DLL).
+ - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating imgui types with your own maths types.
+ - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
+ - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide.
+ Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render"
+ phases of your own application. All rendering informatioe are stored into command-lists that you will retrieve after calling ImGui::Render().
+ - Refer to the bindings and demo applications in the examples/ folder for instruction on how to setup your code.
+ - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder.
+
+ HOW A SIMPLE APPLICATION MAY LOOK LIKE:
+ EXHIBIT 1: USING THE EXAMPLE BINDINGS (imgui_impl_XXX.cpp files from the examples/ folder).
+
+ // Application init: create a dear imgui context, setup some options, load fonts
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+ // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
+ // TODO: Fill optional fields of the io structure later.
+ // TODO: Load TTF/OTF fonts if you don't want to use the default font.
+
+ // Initialize helper Platform and Renderer bindings (here we are using imgui_impl_win32 and imgui_impl_dx11)
+ ImGui_ImplWin32_Init(hwnd);
+ ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
+
+ // Application main loop
+ while (true)
+ {
+ // Feed inputs to dear imgui, start new frame
+ ImGui_ImplDX11_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // Any application code here
+ ImGui::Text("Hello, world!");
+
+ // Render dear imgui into screen
+ ImGui::Render();
+ ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+ g_pSwapChain->Present(1, 0);
+ }
+
+ // Shutdown
+ ImGui_ImplDX11_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ HOW A SIMPLE APPLICATION MAY LOOK LIKE:
+ EXHIBIT 2: IMPLEMENTING CUSTOM BINDING / CUSTOM ENGINE.
+
+ // Application init: create a dear imgui context, setup some options, load fonts
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+ // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
+ // TODO: Fill optional fields of the io structure later.
+ // TODO: Load TTF/OTF fonts if you don't want to use the default font.
+
+ // Build and load the texture atlas into a texture
+ // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer)
+ int width, height;
+ unsigned char* pixels = NULL;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // At this point you've got the texture data and you need to upload that your your graphic system:
+ // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
+ // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ below for details about ImTextureID.
+ MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
+ io.Fonts->TexID = (void*)texture;
+
+ // Application main loop
+ while (true)
+ {
+ // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc.
+ // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform bindings)
+ io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds)
+ io.DisplaySize.x = 1920.0f; // set the current display width
+ io.DisplaySize.y = 1280.0f; // set the current display height here
+ io.MousePos = my_mouse_pos; // set the mouse position
+ io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states
+ io.MouseDown[1] = my_mouse_buttons[1];
+
+ // Call NewFrame(), after this point you can use ImGui::* functions anytime
+ // (So you want to try calling NewFrame() as early as you can in your mainloop to be able to use imgui everywhere)
+ ImGui::NewFrame();
+
+ // Most of your application code here
+ ImGui::Text("Hello, world!");
+ MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
+ MyGameRender(); // may use any ImGui functions as well!
+
+ // Render imgui, swap buffers
+ // (You want to try calling EndFrame/Render as late as you can, to be able to use imgui in your own game rendering code)
+ ImGui::EndFrame();
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+ MyImGuiRenderFunction(draw_data);
+ SwapBuffers();
+ }
+
+ // Shutdown
+ ImGui::DestroyContext();
+
+ HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE:
+
+ void void MyImGuiRenderFunction(ImDrawData* draw_data)
+ {
+ // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
+ // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
+ // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
+ // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by ImGui
+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by ImGui
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // The texture for the draw call is specified by pcmd->TextureId.
+ // The vast majority of draw calls will use the imgui texture atlas, which value you have set yourself during initialization.
+ MyEngineBindTexture((MyTexture*)pcmd->TextureId);
+
+ // We are using scissoring to clip some objects. All low-level graphics API should supports it.
+ // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
+ // (some elements visible outside their bounds) but you can fix that once everything else works!
+ // - Clipping coordinates are provided in imgui coordinates space (from draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize)
+ // In a single viewport application, draw_data->DisplayPos will always be (0,0) and draw_data->DisplaySize will always be == io.DisplaySize.
+ // However, in the interest of supporting multi-viewport applications in the future (see 'viewport' branch on github),
+ // always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
+ // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
+ ImVec2 pos = draw_data->DisplayPos;
+ MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y));
+
+ // Render 'pcmd->ElemCount/3' indexed triangles.
+ // By default the indices ImDrawIdx are 16-bits, you can change them to 32-bits in imconfig.h if your engine doesn't support 16-bits indices.
+ MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
+ }
+ idx_buffer += pcmd->ElemCount;
+ }
+ }
+ }
+
+ - The examples/ folders contains many actual implementation of the pseudo-codes above.
+ - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated.
+ They tell you if Dear ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs
+ from the rest of your application. In every cases you need to pass on the inputs to imgui. Refer to the FAQ for more information.
+ - Please read the FAQ below!. Amusingly, it is called a FAQ because people frequently run into the same issues!
+
+ USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
+
+ - The gamepad/keyboard navigation is fairly functional and keeps being improved.
+ - Gamepad support is particularly useful to use dear imgui on a console system (e.g. PS4, Switch, XB1) without a mouse!
+ - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787
+ - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
+ - Gamepad:
+ - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
+ - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
+ Note that io.NavInputs[] is cleared by EndFrame().
+ - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
+ 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
+ - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
+ Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.).
+ - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://goo.gl/9LgVZW.
+ - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo
+ to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
+ - Keyboard:
+ - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
+ NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
+ - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
+ will be set. For more advanced uses, you may want to read from:
+ - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
+ - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
+ - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
+ Please reach out if you think the game vs navigation input sharing could be improved.
+ - Mouse:
+ - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
+ - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard.
+ - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag.
+ Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
+ When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved.
+ When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that.
+ (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse as moving back and forth!)
+ (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want
+ to set a boolean to ignore your other external mouse positions until the external source is moved again.)
+
+
+ API BREAKING CHANGES
+ ====================
+
+ Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.
+ Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code.
+ When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
+ You can read releases logs https://github.com/ocornut/imgui/releases for more details.
+
+ - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead!
+ - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Keep redirection typedef (will obsolete).
+ - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags.
+ - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files.
+ - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete).
+ - 2018/09/06 (1.65) - renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and stb_rect_pack.h to imstb_rectpack.h.
+ If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths.
+ - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427)
+ - 2018/08/31 (1.64) - added imgui_widgets.cpp file, extracted and moved widgets code out of imgui.cpp into imgui_widgets.cpp. Re-ordered some of the code remaining in imgui.cpp.
+ NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED.
+ Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions.
+ - 2018/08/22 (1.63) - renamed IsItemDeactivatedAfterChange() to IsItemDeactivatedAfterEdit() for consistency with new IsItemEdited() API. Kept redirection function (will obsolete soonish as IsItemDeactivatedAfterChange() is very recent).
+ - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete).
+ - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly).
+ - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges [update 1.67 renamed to ConfigWindowsResizeFromEdges] to enable the feature.
+ - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency.
+ - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time.
+ - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete).
+ - 2018/06/08 (1.62) - examples: the imgui_impl_xxx files have been split to separate platform (Win32, Glfw, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.).
+ old binding will still work as is, however prefer using the separated bindings as they will be updated to be multi-viewport conformant.
+ when adopting new bindings follow the main.cpp code of your preferred examples/ folder to know which functions to call.
+ - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
+ - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
+ - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more.
+ If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format.
+ To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code.
+ If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them.
+ - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format",
+ consistent with other functions. Kept redirection functions (will obsolete).
+ - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value.
+ - 2018/03/20 (1.60) - renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch).
+ - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
+ - 2018/03/08 (1.60) - changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically.
+ - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
+ - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment.
+ - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display.
+ - 2018/02/07 (1.60) - reorganized context handling to be more explicit,
+ - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
+ - removed Shutdown() function, as DestroyContext() serve this purpose.
+ - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
+ - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
+ - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
+ - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths.
+ - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
+ - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
+ - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
+ - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side.
+ - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete).
+ - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags
+ - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame.
+ - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set.
+ - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete).
+ - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete).
+ - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete).
+ - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete).
+ - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete).
+ - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed.
+ - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up.
+ Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions.
+ - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
+ - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
+ - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
+ - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
+ - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency.
+ - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it.
+ - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details.
+ removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
+ - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
+ - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
+ - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Keep redirection typedef (will obsolete).
+ - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete).
+ - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
+ - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
+ - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
+ - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
+ - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
+ - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.
+ - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.
+ - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.
+ - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).
+ - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).
+ - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
+ - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.
+ - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
+ - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))'
+ - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
+ - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
+ - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
+ - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().
+ - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
+ - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
+ - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
+ - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
+ If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you.
+ If your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
+ This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color.
+ ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
+ {
+ float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;
+ return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a);
+ }
+ If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.
+ - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
+ - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
+ - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).
+ - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDrawList::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.
+ - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).
+ - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
+ - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
+ - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
+ - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
+ - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
+ - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
+ - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
+ GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.
+ GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out!
+ - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
+ - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project.
+ - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason
+ - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.
+ you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
+ - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
+ this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
+ - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.
+ - the signature of the io.RenderDrawListsFn handler has changed!
+ old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
+ new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
+ parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount'
+ ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new.
+ ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'.
+ - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.
+ - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
+ - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
+ - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
+ - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
+ - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
+ - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
+ - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry!
+ - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
+ - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
+ - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.
+ - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened.
+ - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
+ - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
+ - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
+ - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
+ - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
+ - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
+ - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
+ - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
+ - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
+ - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
+ - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
+ - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
+ - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
+ - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
+ - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
+ - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
+ - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
+ (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
+ font init: { const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..>; }
+ became: { unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; }
+ you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
+ it is now recommended that you sample the font texture with bilinear interpolation.
+ (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
+ (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
+ (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
+ - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
+ - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
+ - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
+ - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
+ - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly)
+ - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
+ - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
+ - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
+ - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
+ - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
+ - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
+
+
+ FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
+ ======================================
+
+ Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
+ A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } )
+ - When 'io.WantCaptureMouse' is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application.
+ - When 'io.WantCaptureKeyboard' is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application.
+ - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
+ Note: you should always pass your mouse/keyboard inputs to imgui, even when the io.WantCaptureXXX flag are set false.
+ This is because imgui needs to detect that you clicked in the void to unfocus its own windows.
+ Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!).
+ It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs.
+ Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also
+ perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to UpdateHoveredWindowAndCaptureFlags().
+ Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically
+ have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs
+ were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
+
+ Q: How can I display an image? What is ImTextureID, how does it works?
+ A: Short explanation:
+ - You may use functions such as ImGui::Image(), ImGui::ImageButton() or lower-level ImDrawList::AddImage() to emit draw calls that will use your own textures.
+ - Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
+ - Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
+ Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.
+
+ Long explanation:
+ - Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices.
+ At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code
+ to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
+ - Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
+ We carry the information to identify a "texture" in the ImTextureID type.
+ ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice.
+ Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
+ - In the examples/ bindings, for each graphics API binding we decided on a type that is likely to be a good representation for specifying
+ an image from the end-user perspective. This is what the _examples_ rendering functions are using:
+
+ OpenGL: ImTextureID = GLuint (see ImGui_ImplGlfwGL3_RenderDrawData() function in imgui_impl_glfw_gl3.cpp)
+ DirectX9: ImTextureID = LPDIRECT3DTEXTURE9 (see ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp)
+ DirectX11: ImTextureID = ID3D11ShaderResourceView* (see ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp)
+ DirectX12: ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE (see ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp)
+
+ For example, in the OpenGL example binding we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
+ Whereas in the DirectX11 example binding we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure
+ tying together both the texture and information about its format and how to read it.
+ - If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about
+ the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase
+ is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
+ If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID
+ representation suggested by the example bindings is probably the best choice.
+ (Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
+
+ User code may do:
+
+ // Cast our texture type to ImTextureID / void*
+ MyTexture* texture = g_CoffeeTableTexture;
+ ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
+
+ The renderer function called after ImGui::Render() will receive that same value that the user code passed:
+
+ // Cast ImTextureID / void* stored in the draw command as our texture type
+ MyTexture* texture = (MyTexture*)pcmd->TextureId;
+ MyEngineBindTexture2D(texture);
+
+ Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
+ This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them.
+ If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using.
+
+ Here's a simplified OpenGL example using stb_image.h:
+
+ // Use stb_image.h to load a PNG from disk and turn it into raw RGBA pixel data:
+ #define STB_IMAGE_IMPLEMENTATION
+ #include <stb_image.h>
+ [...]
+ int my_image_width, my_image_height;
+ unsigned char* my_image_data = stbi_load("my_image.png", &my_image_width, &my_image_height, NULL, 4);
+
+ // Turn the RGBA pixel data into an OpenGL texture:
+ GLuint my_opengl_texture;
+ glGenTextures(1, &my_opengl_texture);
+ glBindTexture(GL_TEXTURE_2D, my_opengl_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
+
+ // Now that we have an OpenGL texture, assuming our imgui rendering function (imgui_impl_xxx.cpp file) takes GLuint as ImTextureID, we can display it:
+ ImGui::Image((void*)(intptr_t)my_opengl_texture, ImVec2(my_image_width, my_image_height));
+
+ C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTexture / void*, and vice-versa.
+ Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTexture / void*.
+ Examples:
+
+ GLuint my_tex = XXX;
+ void* my_void_ptr;
+ my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
+ my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint
+
+ ID3D11ShaderResourceView* my_dx11_srv = XXX;
+ void* my_void_ptr;
+ my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void*
+ my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView*
+
+ Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated.
+
+ Q: How can I have multiple widgets with the same label or with an empty label?
+ Q: I have multiple widgets with the same label, and only the first one works. Why is that?
+ A: A primer on labels and the ID Stack...
+
+ Dear ImGui internally need to uniquely identify UI elements.
+ Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
+ Interactive widgets (such as calls to Button buttons) need a unique ID.
+ Unique ID are used internally to track active widgets and occasionally associate state to widgets.
+ Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.
+
+ - Unique ID are often derived from a string label:
+
+ Button("OK"); // Label = "OK", ID = hash of (..., "OK")
+ Button("Cancel"); // Label = "Cancel", ID = hash of (..., "Cancel")
+
+ - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having
+ two buttons labeled "OK" in different windows or different tree locations is fine.
+ We used "..." above to signify whatever was already pushed to the ID stack previously:
+
+ Begin("MyWindow");
+ Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK")
+ End();
+ Begin("MyOtherWindow");
+ Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
+ End();
+
+ - If you have a same ID twice in the same location, you'll have a conflict:
+
+ Button("OK");
+ Button("OK"); // ID collision! Interacting with either button will trigger the first one.
+
+ Fear not! this is easy to solve and there are many ways to solve it!
+
+ - Solving ID conflict in a simple/local context:
+ When passing a label you can optionally specify extra ID information within string itself.
+ Use "##" to pass a complement to the ID that won't be visible to the end-user.
+ This helps solving the simple collision cases when you know e.g. at compilation time which items
+ are going to be created:
+
+ Begin("MyWindow");
+ Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
+ Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from above
+ Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from above
+ End();
+
+ - If you want to completely hide the label, but still need an ID:
+
+ Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
+
+ - Occasionally/rarely you might want change a label while preserving a constant ID. This allows
+ you to animate labels. For example you may want to include varying information in a window title bar,
+ but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
+
+ Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "ID")
+ Button("World###ID"); // Label = "World", ID = hash of (..., "ID") // Same as above, even though the label looks different
+
+ sprintf(buf, "My game (%f FPS)###MyGame", fps);
+ Begin(buf); // Variable title, ID = hash of "MyGame"
+
+ - Solving ID conflict in a more general manner:
+ Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts
+ within the same window. This is the most convenient way of distinguishing ID when iterating and
+ creating many UI elements programmatically.
+ You can push a pointer, a string or an integer value into the ID stack.
+ Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
+ At each level of the stack we store the seed used for items at this level of the ID stack.
+
+ Begin("Window");
+ for (int i = 0; i < 100; i++)
+ {
+ PushID(i); // Push i to the id tack
+ Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
+ PopID();
+ }
+ for (int i = 0; i < 100; i++)
+ {
+ MyObject* obj = Objects[i];
+ PushID(obj);
+ Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click")
+ PopID();
+ }
+ for (int i = 0; i < 100; i++)
+ {
+ MyObject* obj = Objects[i];
+ PushID(obj->Name);
+ Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
+ PopID();
+ }
+ End();
+
+ - You can stack multiple prefixes into the ID stack:
+
+ Button("Click"); // Label = "Click", ID = hash of (..., "Click")
+ PushID("node");
+ Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
+ PushID(my_ptr);
+ Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click")
+ PopID();
+ PopID();
+
+ - Tree nodes implicitly creates a scope for you by calling PushID().
+
+ Button("Click"); // Label = "Click", ID = hash of (..., "Click")
+ if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
+ {
+ Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
+ TreePop();
+ }
+
+ - When working with trees, ID are used to preserve the open/close state of each tree node.
+ Depending on your use cases you may want to use strings, indices or pointers as ID.
+ e.g. when following a single pointer that may change over time, using a static string as ID
+ will preserve your node open/closed state when the targeted object change.
+ e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
+ node open/closed state differently. See what makes more sense in your situation!
+
+ Q: How can I use my own math types instead of ImVec2/ImVec4?
+ A: You can edit imconfig.h and setup the IM_VEC2_CLASS_EXTRA/IM_VEC4_CLASS_EXTRA macros to add implicit type conversions.
+ This way you'll be able to use your own types everywhere, e.g. passsing glm::vec2 to ImGui functions instead of ImVec2.
+
+ Q: How can I load a different font than the default?
+ A: Use the font atlas to load the TTF/OTF file you want:
+ ImGuiIO& io = ImGui::GetIO();
+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
+ io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
+ Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
+ (Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
+ (Read the 'misc/fonts/README.txt' file for more details about font loading.)
+
+ New programmers: remember that in C/C++ and most programming languages if you want to use a
+ backslash \ within a string literal, you need to write it double backslash "\\":
+ io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG (you are escape the M here!)
+ io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT
+ io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT
+
+ Q: How can I easily use icons in my application?
+ A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you
+ main font. Then you can refer to icons within your strings.
+ You may want to see ImFontConfig::GlyphMinAdvanceX to make your icon look monospace to facilitate alignment.
+ (Read the 'misc/fonts/README.txt' file for more details about icons font loading.)
+
+ Q: How can I load multiple fonts?
+ A: Use the font atlas to pack them into a single texture:
+ (Read the 'misc/fonts/README.txt' file and the code in ImFontAtlas for more details.)
+
+ ImGuiIO& io = ImGui::GetIO();
+ ImFont* font0 = io.Fonts->AddFontDefault();
+ ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
+ ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
+ io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
+ // the first loaded font gets used by default
+ // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
+
+ // Options
+ ImFontConfig config;
+ config.OversampleH = 3;
+ config.OversampleV = 1;
+ config.GlyphOffset.y -= 2.0f; // Move everything by 2 pixels up
+ config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
+
+ // Combine multiple fonts into one (e.g. for icon fonts)
+ static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
+ ImFontConfig config;
+ config.MergeMode = true;
+ io.Fonts->AddFontDefault();
+ io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
+
+ Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
+ A: When loading a font, pass custom Unicode ranges to specify the glyphs to load.
+
+ // Add default Japanese ranges
+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
+
+ // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
+ ImVector<ImWchar> ranges;
+ ImFontGlyphRangesBuilder builder;
+ builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
+ builder.AddChar(0x7262); // Add a specific character
+ builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
+ builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
+ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
+
+ All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
+ by using the u8"hello" syntax. Specifying literal in your source code using a local code page
+ (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
+ Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
+
+ Text input: it is up to your application to pass the right character code by calling io.AddInputCharacter().
+ The applications in examples/ are doing that.
+ Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode).
+ You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
+ Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
+ the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
+
+ Q: How can I interact with standard C++ types (such as std::string and std::vector)?
+ A: - Being highly portable (bindings for several languages, frameworks, programming style, obscure or older platforms/compilers),
+ and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use
+ any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
+ - To use ImGui::InputText() with a std::string or any resizable string class, see misc/cpp/imgui_stdlib.h.
+ - To use combo boxes and list boxes with std::vector or any other data structure: the BeginCombo()/EndCombo() API
+ lets you iterate and submit items yourself, so does the ListBoxHeader()/ListBoxFooter() API.
+ Prefer using them over the old and awkward Combo()/ListBox() api.
+ - Generally for most high-level types you should be able to access the underlying data type.
+ You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
+ - Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
+ to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application.
+ Please bear in mind that using std::string on applications with large amount of UI may incur unsatisfactory performances.
+ Modern implementations of std::string often include small-string optimization (which is often a local buffer) but those
+ are not configurable and not the same across implementations.
+ - If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
+ of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
+ is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
+ One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
+ This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
+ provide similar or better string helpers.
+
+ Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
+ A: - You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags.
+ (The ImGuiWindowFlags_NoDecoration flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse)
+ Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
+ - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows.
+ - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create
+ your own ImDrawListSharedData, and then call your rendered code with your own ImDrawList or ImDrawData data.
+
+ Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
+ A: - You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls".
+ (short version: map gamepad inputs into the io.NavInputs[] array + set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad)
+ - You can share your computer mouse seamlessly with your console/tablet/phone using Synergy (https://symless.com/synergy)
+ This is the preferred solution for developer productivity.
+ In particular, the "micro-synergy-client" repository (https://github.com/symless/micro-synergy-client) has simple
+ and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
+ to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
+ Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
+ - You may also use a third party solution such as Remote ImGui (https://github.com/JordiRos/remoteimgui) which sends
+ the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine.
+ - For touch inputs, you can increase the hit box of widgets (via the style.TouchPadding setting) to accommodate
+ for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing
+ for screen real-estate and precision.
+
+ Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
+ A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
+ Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
+
+ Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
+ A: You are probably mishandling the clipping rectangles in your render function.
+ Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).
+
+ Q: How can I help?
+ A: - If you are experienced with Dear ImGui and C++, look at the github issues, look at the Wiki, read docs/TODO.txt
+ and see how you want to help and can help!
+ - Businesses: convince your company to fund development via support contracts/sponsoring! This is among the most useful thing you can do for dear imgui.
+ - Individuals: you can also become a Patron (http://www.patreon.com/imgui) or donate on PayPal! See README.
+ - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
+ You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1902). Visuals are ideal as they inspire other programmers.
+ But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
+ - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately).
+
+ - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
+ this is also useful to set yourself in the context of another window (to get/set other settings)
+ - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
+ - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle
+ of a deep nested inner loop in your code.
+ - tip: you can call Render() multiple times (e.g for VR renders).
+ - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui!
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+#include <ctype.h> // toupper, isprint
+#include <stdio.h> // vsnprintf, sscanf, printf
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// Debug options
+#define IMGUI_DEBUG_NAV_SCORING 0
+#define IMGUI_DEBUG_NAV_RECTS 0
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#endif
+
+// Clang/GCC warnings with -Weverything
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great!
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
+#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
+#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
+#pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
+#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
+#if __GNUC__ >= 8
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+#endif
+
+// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
+static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
+static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
+
+// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by back-end)
+static const float WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS = 4.0f; // Extend outside and inside windows. Affect FindHoveredWindow().
+static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
+
+//-------------------------------------------------------------------------
+// [SECTION] FORWARD DECLARATIONS
+//-------------------------------------------------------------------------
+
+static void SetCurrentWindow(ImGuiWindow* window);
+static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
+static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
+static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);
+static void FindHoveredWindow();
+static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
+static void CheckStacksSize(ImGuiWindow* window, bool write);
+static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
+
+static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
+static void AddWindowToDrawData(ImVector<ImDrawList*>* out_list, ImGuiWindow* window);
+static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
+
+static ImRect GetViewportRect();
+
+// Settings
+static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
+static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
+static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
+
+// Platform Dependents default implementation for IO functions
+static const char* GetClipboardTextFn_DefaultImpl(void* user_data);
+static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
+static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
+
+namespace ImGui
+{
+static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags);
+
+// Navigation
+static void NavUpdate();
+static void NavUpdateWindowing();
+static void NavUpdateWindowingList();
+static void NavUpdateMoveResult();
+static float NavUpdatePageUpPageDown(int allowed_dir_flags);
+static inline void NavUpdateAnyRequestFlag();
+static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
+static ImVec2 NavCalcPreferredRefPos();
+static void NavSaveLastChildNavWindow(ImGuiWindow* nav_window);
+static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
+
+// Misc
+static void UpdateMouseInputs();
+static void UpdateMouseWheel();
+static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] CONTEXT AND MEMORY ALLOCATORS
+//-----------------------------------------------------------------------------
+
+// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
+// CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext().
+// If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file.
+// ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can:
+// - Change this variable to use thread local storage. You may #define GImGui in imconfig.h for that purpose. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
+// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)
+#ifndef GImGui
+ImGuiContext* GImGui = NULL;
+#endif
+
+// Memory Allocator functions. Use SetAllocatorFunctions() to change them.
+// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file.
+// Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
+#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
+static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); }
+static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; free(ptr); }
+#else
+static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; (void)size; IM_ASSERT(0); return NULL; }
+static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; (void)ptr; IM_ASSERT(0); }
+#endif
+
+static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper;
+static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper;
+static void* GImAllocatorUserData = NULL;
+
+//-----------------------------------------------------------------------------
+// [SECTION] MAIN USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
+//-----------------------------------------------------------------------------
+
+ImGuiStyle::ImGuiStyle()
+{
+ Alpha = 1.0f; // Global alpha applies to everything in ImGui
+ WindowPadding = ImVec2(8,8); // Padding within a window
+ WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
+ WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
+ WindowMinSize = ImVec2(32,32); // Minimum window size
+ WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
+ ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
+ ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
+ PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
+ PopupBorderSize = 1.0f; // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested.
+ FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
+ FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
+ FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
+ ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
+ ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
+ TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
+ IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
+ ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
+ ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
+ ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
+ GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
+ GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
+ TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
+ TabBorderSize = 0.0f; // Thickness of border around tabs.
+ ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
+ DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows.
+ DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
+ MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
+ AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
+ AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
+ CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
+
+ // Default theme
+ ImGui::StyleColorsDark(this);
+}
+
+// To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you.
+// Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times.
+void ImGuiStyle::ScaleAllSizes(float scale_factor)
+{
+ WindowPadding = ImFloor(WindowPadding * scale_factor);
+ WindowRounding = ImFloor(WindowRounding * scale_factor);
+ WindowMinSize = ImFloor(WindowMinSize * scale_factor);
+ ChildRounding = ImFloor(ChildRounding * scale_factor);
+ PopupRounding = ImFloor(PopupRounding * scale_factor);
+ FramePadding = ImFloor(FramePadding * scale_factor);
+ FrameRounding = ImFloor(FrameRounding * scale_factor);
+ TabRounding = ImFloor(TabRounding * scale_factor);
+ ItemSpacing = ImFloor(ItemSpacing * scale_factor);
+ ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
+ TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
+ IndentSpacing = ImFloor(IndentSpacing * scale_factor);
+ ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
+ ScrollbarSize = ImFloor(ScrollbarSize * scale_factor);
+ ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
+ GrabMinSize = ImFloor(GrabMinSize * scale_factor);
+ GrabRounding = ImFloor(GrabRounding * scale_factor);
+ DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
+ DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
+ MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
+}
+
+ImGuiIO::ImGuiIO()
+{
+ // Most fields are initialized with zero
+ memset(this, 0, sizeof(*this));
+
+ // Settings
+ ConfigFlags = ImGuiConfigFlags_None;
+ BackendFlags = ImGuiBackendFlags_None;
+ DisplaySize = ImVec2(-1.0f, -1.0f);
+ DeltaTime = 1.0f/60.0f;
+ IniSavingRate = 5.0f;
+ IniFilename = "imgui.ini";
+ LogFilename = "imgui_log.txt";
+ MouseDoubleClickTime = 0.30f;
+ MouseDoubleClickMaxDist = 6.0f;
+ for (int i = 0; i < ImGuiKey_COUNT; i++)
+ KeyMap[i] = -1;
+ KeyRepeatDelay = 0.250f;
+ KeyRepeatRate = 0.050f;
+ UserData = NULL;
+
+ Fonts = NULL;
+ FontGlobalScale = 1.0f;
+ FontDefault = NULL;
+ FontAllowUserScaling = false;
+ DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
+ DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f);
+
+ // Miscellaneous configuration options
+#ifdef __APPLE__
+ ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag
+#else
+ ConfigMacOSXBehaviors = false;
+#endif
+ ConfigInputTextCursorBlink = true;
+ ConfigWindowsResizeFromEdges = true;
+ ConfigWindowsMoveFromTitleBarOnly = false;
+
+ // Platform Functions
+ BackendPlatformName = BackendRendererName = NULL;
+ BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
+ GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
+ SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
+ ClipboardUserData = NULL;
+ ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
+ ImeWindowHandle = NULL;
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ RenderDrawListsFn = NULL;
+#endif
+
+ // Input (NB: we already have memset zero the entire structure!)
+ MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+ MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
+ MouseDragThreshold = 6.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
+}
+
+// Pass in translated ASCII characters for text input.
+// - with glfw you can get those from the callback set in glfwSetCharCallback()
+// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
+void ImGuiIO::AddInputCharacter(ImWchar c)
+{
+ InputQueueCharacters.push_back(c);
+}
+
+void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
+{
+ while (*utf8_chars != 0)
+ {
+ unsigned int c = 0;
+ utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
+ if (c > 0 && c <= 0xFFFF)
+ InputQueueCharacters.push_back((ImWchar)c);
+ }
+}
+
+void ImGuiIO::ClearInputCharacters()
+{
+ InputQueueCharacters.resize(0);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPER/UTILITIES (Maths, String, Format, Hash, File functions)
+//-----------------------------------------------------------------------------
+
+ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
+{
+ ImVec2 ap = p - a;
+ ImVec2 ab_dir = b - a;
+ float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
+ if (dot < 0.0f)
+ return a;
+ float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
+ if (dot > ab_len_sqr)
+ return b;
+ return a + ab_dir * dot / ab_len_sqr;
+}
+
+bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
+{
+ bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
+ bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
+ bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
+ return ((b1 == b2) && (b2 == b3));
+}
+
+void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)
+{
+ ImVec2 v0 = b - a;
+ ImVec2 v1 = c - a;
+ ImVec2 v2 = p - a;
+ const float denom = v0.x * v1.y - v1.x * v0.y;
+ out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
+ out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
+ out_u = 1.0f - out_v - out_w;
+}
+
+ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
+{
+ ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
+ ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
+ ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
+ float dist2_ab = ImLengthSqr(p - proj_ab);
+ float dist2_bc = ImLengthSqr(p - proj_bc);
+ float dist2_ca = ImLengthSqr(p - proj_ca);
+ float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
+ if (m == dist2_ab)
+ return proj_ab;
+ if (m == dist2_bc)
+ return proj_bc;
+ return proj_ca;
+}
+
+int ImStricmp(const char* str1, const char* str2)
+{
+ int d;
+ while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
+ return d;
+}
+
+int ImStrnicmp(const char* str1, const char* str2, size_t count)
+{
+ int d = 0;
+ while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
+ return d;
+}
+
+void ImStrncpy(char* dst, const char* src, size_t count)
+{
+ if (count < 1) return;
+ strncpy(dst, src, count);
+ dst[count-1] = 0;
+}
+
+char* ImStrdup(const char* str)
+{
+ size_t len = strlen(str);
+ void* buf = ImGui::MemAlloc(len + 1);
+ return (char*)memcpy(buf, (const void*)str, len + 1);
+}
+
+char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
+{
+ size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
+ size_t src_size = strlen(src) + 1;
+ if (dst_buf_size < src_size)
+ {
+ ImGui::MemFree(dst);
+ dst = (char*)ImGui::MemAlloc(src_size);
+ if (p_dst_size)
+ *p_dst_size = src_size;
+ }
+ return (char*)memcpy(dst, (const void*)src, src_size);
+}
+
+const char* ImStrchrRange(const char* str, const char* str_end, char c)
+{
+ const char* p = (const char*)memchr(str, (int)c, str_end - str);
+ return p;
+}
+
+int ImStrlenW(const ImWchar* str)
+{
+ //return (int)wcslen((const wchar_t*)str); // FIXME-OPT: Could use this when wchar_t are 16-bits
+ int n = 0;
+ while (*str++) n++;
+ return n;
+}
+
+// Find end-of-line. Return pointer will point to either first \n, either str_end.
+const char* ImStreolRange(const char* str, const char* str_end)
+{
+ const char* p = (const char*)memchr(str, '\n', str_end - str);
+ return p ? p : str_end;
+}
+
+const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
+{
+ while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
+ buf_mid_line--;
+ return buf_mid_line;
+}
+
+const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
+{
+ if (!needle_end)
+ needle_end = needle + strlen(needle);
+
+ const char un0 = (char)toupper(*needle);
+ while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
+ {
+ if (toupper(*haystack) == un0)
+ {
+ const char* b = needle + 1;
+ for (const char* a = haystack + 1; b < needle_end; a++, b++)
+ if (toupper(*a) != toupper(*b))
+ break;
+ if (b == needle_end)
+ return haystack;
+ }
+ haystack++;
+ }
+ return NULL;
+}
+
+// Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible.
+void ImStrTrimBlanks(char* buf)
+{
+ char* p = buf;
+ while (p[0] == ' ' || p[0] == '\t') // Leading blanks
+ p++;
+ char* p_start = p;
+ while (*p != 0) // Find end of string
+ p++;
+ while (p > p_start && (p[-1] == ' ' || p[-1] == '\t')) // Trailing blanks
+ p--;
+ if (p_start != buf) // Copy memory if we had leading blanks
+ memmove(buf, p_start, p - p_start);
+ buf[p - p_start] = 0; // Zero terminate
+}
+
+// A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size).
+// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm.
+// B) When buf==NULL vsnprintf() will return the output size.
+#ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
+
+//#define IMGUI_USE_STB_SPRINTF
+#ifdef IMGUI_USE_STB_SPRINTF
+#define STB_SPRINTF_IMPLEMENTATION
+#include "imstb_sprintf.h"
+#endif
+
+#if defined(_MSC_VER) && !defined(vsnprintf)
+#define vsnprintf _vsnprintf
+#endif
+
+int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+#ifdef IMGUI_USE_STB_SPRINTF
+ int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
+#else
+ int w = vsnprintf(buf, buf_size, fmt, args);
+#endif
+ va_end(args);
+ if (buf == NULL)
+ return w;
+ if (w == -1 || w >= (int)buf_size)
+ w = (int)buf_size - 1;
+ buf[w] = 0;
+ return w;
+}
+
+int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
+{
+#ifdef IMGUI_USE_STB_SPRINTF
+ int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
+#else
+ int w = vsnprintf(buf, buf_size, fmt, args);
+#endif
+ if (buf == NULL)
+ return w;
+ if (w == -1 || w >= (int)buf_size)
+ w = (int)buf_size - 1;
+ buf[w] = 0;
+ return w;
+}
+#endif // #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
+
+// Pass data_size == 0 for zero-terminated strings, data_size > 0 for non-string data.
+// Pay attention that data_size==0 will yield different results than passing strlen(data) because the zero-terminated codepath handles ###.
+// This should technically be split into two distinct functions (ImHashData/ImHashStr), perhaps once we remove the silly static variable.
+// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
+ImU32 ImHash(const void* data, int data_size, ImU32 seed)
+{
+ static ImU32 crc32_lut[256] = { 0 };
+ if (!crc32_lut[1])
+ {
+ const ImU32 polynomial = 0xEDB88320;
+ for (ImU32 i = 0; i < 256; i++)
+ {
+ ImU32 crc = i;
+ for (ImU32 j = 0; j < 8; j++)
+ crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);
+ crc32_lut[i] = crc;
+ }
+ }
+
+ seed = ~seed;
+ ImU32 crc = seed;
+ const unsigned char* current = (const unsigned char*)data;
+
+ if (data_size > 0)
+ {
+ // Known size
+ while (data_size--)
+ crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
+ }
+ else
+ {
+ // Zero-terminated string
+ while (unsigned char c = *current++)
+ {
+ // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
+ // Because this syntax is rarely used we are optimizing for the common case.
+ // - If we reach ### in the string we discard the hash so far and reset to the seed.
+ // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
+ if (c == '#' && current[0] == '#' && current[1] == '#')
+ crc = seed;
+ crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
+ }
+ }
+ return ~crc;
+}
+
+FILE* ImFileOpen(const char* filename, const char* mode)
+{
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__GNUC__)
+ // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can)
+ const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;
+ const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;
+ ImVector<ImWchar> buf;
+ buf.resize(filename_wsize + mode_wsize);
+ ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);
+ ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);
+ return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);
+#else
+ return fopen(filename, mode);
+#endif
+}
+
+// Load file content into memory
+// Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
+void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size, int padding_bytes)
+{
+ IM_ASSERT(filename && file_open_mode);
+ if (out_file_size)
+ *out_file_size = 0;
+
+ FILE* f;
+ if ((f = ImFileOpen(filename, file_open_mode)) == NULL)
+ return NULL;
+
+ long file_size_signed;
+ if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))
+ {
+ fclose(f);
+ return NULL;
+ }
+
+ size_t file_size = (size_t)file_size_signed;
+ void* file_data = ImGui::MemAlloc(file_size + padding_bytes);
+ if (file_data == NULL)
+ {
+ fclose(f);
+ return NULL;
+ }
+ if (fread(file_data, 1, file_size, f) != file_size)
+ {
+ fclose(f);
+ ImGui::MemFree(file_data);
+ return NULL;
+ }
+ if (padding_bytes > 0)
+ memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes);
+
+ fclose(f);
+ if (out_file_size)
+ *out_file_size = file_size;
+
+ return file_data;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
+//-----------------------------------------------------------------------------
+
+// Convert UTF-8 to 32-bits character, process single character input.
+// Based on stb_from_utf8() from github.com/nothings/stb/
+// We handle UTF-8 decoding error by skipping forward.
+int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
+{
+ unsigned int c = (unsigned int)-1;
+ const unsigned char* str = (const unsigned char*)in_text;
+ if (!(*str & 0x80))
+ {
+ c = (unsigned int)(*str++);
+ *out_char = c;
+ return 1;
+ }
+ if ((*str & 0xe0) == 0xc0)
+ {
+ *out_char = 0xFFFD; // will be invalid but not end of string
+ if (in_text_end && in_text_end - (const char*)str < 2) return 1;
+ if (*str < 0xc2) return 2;
+ c = (unsigned int)((*str++ & 0x1f) << 6);
+ if ((*str & 0xc0) != 0x80) return 2;
+ c += (*str++ & 0x3f);
+ *out_char = c;
+ return 2;
+ }
+ if ((*str & 0xf0) == 0xe0)
+ {
+ *out_char = 0xFFFD; // will be invalid but not end of string
+ if (in_text_end && in_text_end - (const char*)str < 3) return 1;
+ if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
+ if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
+ c = (unsigned int)((*str++ & 0x0f) << 12);
+ if ((*str & 0xc0) != 0x80) return 3;
+ c += (unsigned int)((*str++ & 0x3f) << 6);
+ if ((*str & 0xc0) != 0x80) return 3;
+ c += (*str++ & 0x3f);
+ *out_char = c;
+ return 3;
+ }
+ if ((*str & 0xf8) == 0xf0)
+ {
+ *out_char = 0xFFFD; // will be invalid but not end of string
+ if (in_text_end && in_text_end - (const char*)str < 4) return 1;
+ if (*str > 0xf4) return 4;
+ if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
+ if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
+ c = (unsigned int)((*str++ & 0x07) << 18);
+ if ((*str & 0xc0) != 0x80) return 4;
+ c += (unsigned int)((*str++ & 0x3f) << 12);
+ if ((*str & 0xc0) != 0x80) return 4;
+ c += (unsigned int)((*str++ & 0x3f) << 6);
+ if ((*str & 0xc0) != 0x80) return 4;
+ c += (*str++ & 0x3f);
+ // utf-8 encodings of values used in surrogate pairs are invalid
+ if ((c & 0xFFFFF800) == 0xD800) return 4;
+ *out_char = c;
+ return 4;
+ }
+ *out_char = 0;
+ return 0;
+}
+
+int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
+{
+ ImWchar* buf_out = buf;
+ ImWchar* buf_end = buf + buf_size;
+ while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c;
+ in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
+ if (c == 0)
+ break;
+ if (c < 0x10000) // FIXME: Losing characters that don't fit in 2 bytes
+ *buf_out++ = (ImWchar)c;
+ }
+ *buf_out = 0;
+ if (in_text_remaining)
+ *in_text_remaining = in_text;
+ return (int)(buf_out - buf);
+}
+
+int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
+{
+ int char_count = 0;
+ while ((!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c;
+ in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
+ if (c == 0)
+ break;
+ if (c < 0x10000)
+ char_count++;
+ }
+ return char_count;
+}
+
+// Based on stb_to_utf8() from github.com/nothings/stb/
+static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
+{
+ if (c < 0x80)
+ {
+ buf[0] = (char)c;
+ return 1;
+ }
+ if (c < 0x800)
+ {
+ if (buf_size < 2) return 0;
+ buf[0] = (char)(0xc0 + (c >> 6));
+ buf[1] = (char)(0x80 + (c & 0x3f));
+ return 2;
+ }
+ if (c >= 0xdc00 && c < 0xe000)
+ {
+ return 0;
+ }
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ if (buf_size < 4) return 0;
+ buf[0] = (char)(0xf0 + (c >> 18));
+ buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
+ buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
+ buf[3] = (char)(0x80 + ((c ) & 0x3f));
+ return 4;
+ }
+ //else if (c < 0x10000)
+ {
+ if (buf_size < 3) return 0;
+ buf[0] = (char)(0xe0 + (c >> 12));
+ buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
+ buf[2] = (char)(0x80 + ((c ) & 0x3f));
+ return 3;
+ }
+}
+
+// Not optimal but we very rarely use this function.
+int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end)
+{
+ unsigned int dummy = 0;
+ return ImTextCharFromUtf8(&dummy, in_text, in_text_end);
+}
+
+static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
+{
+ if (c < 0x80) return 1;
+ if (c < 0x800) return 2;
+ if (c >= 0xdc00 && c < 0xe000) return 0;
+ if (c >= 0xd800 && c < 0xdc00) return 4;
+ return 3;
+}
+
+int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
+{
+ char* buf_out = buf;
+ const char* buf_end = buf + buf_size;
+ while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c = (unsigned int)(*in_text++);
+ if (c < 0x80)
+ *buf_out++ = (char)c;
+ else
+ buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c);
+ }
+ *buf_out = 0;
+ return (int)(buf_out - buf);
+}
+
+int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
+{
+ int bytes_count = 0;
+ while ((!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c = (unsigned int)(*in_text++);
+ if (c < 0x80)
+ bytes_count++;
+ else
+ bytes_count += ImTextCountUtf8BytesFromChar(c);
+ }
+ return bytes_count;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPER/UTILTIES (Color functions)
+// Note: The Convert functions are early design which are not consistent with other API.
+//-----------------------------------------------------------------------------
+
+ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
+{
+ float s = 1.0f/255.0f;
+ return ImVec4(
+ ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
+ ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
+ ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
+ ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
+}
+
+ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
+{
+ ImU32 out;
+ out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
+ out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
+ out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
+ out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
+ return out;
+}
+
+// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
+// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
+void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
+{
+ float K = 0.f;
+ if (g < b)
+ {
+ ImSwap(g, b);
+ K = -1.f;
+ }
+ if (r < g)
+ {
+ ImSwap(r, g);
+ K = -2.f / 6.f - K;
+ }
+
+ const float chroma = r - (g < b ? g : b);
+ out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
+ out_s = chroma / (r + 1e-20f);
+ out_v = r;
+}
+
+// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
+// also http://en.wikipedia.org/wiki/HSL_and_HSV
+void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
+{
+ if (s == 0.0f)
+ {
+ // gray
+ out_r = out_g = out_b = v;
+ return;
+ }
+
+ h = ImFmod(h, 1.0f) / (60.0f/360.0f);
+ int i = (int)h;
+ float f = h - (float)i;
+ float p = v * (1.0f - s);
+ float q = v * (1.0f - s * f);
+ float t = v * (1.0f - s * (1.0f - f));
+
+ switch (i)
+ {
+ case 0: out_r = v; out_g = t; out_b = p; break;
+ case 1: out_r = q; out_g = v; out_b = p; break;
+ case 2: out_r = p; out_g = v; out_b = t; break;
+ case 3: out_r = p; out_g = q; out_b = v; break;
+ case 4: out_r = t; out_g = p; out_b = v; break;
+ case 5: default: out_r = v; out_g = p; out_b = q; break;
+ }
+}
+
+ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
+{
+ ImGuiStyle& style = GImGui->Style;
+ ImVec4 c = style.Colors[idx];
+ c.w *= style.Alpha * alpha_mul;
+ return ColorConvertFloat4ToU32(c);
+}
+
+ImU32 ImGui::GetColorU32(const ImVec4& col)
+{
+ ImGuiStyle& style = GImGui->Style;
+ ImVec4 c = col;
+ c.w *= style.Alpha;
+ return ColorConvertFloat4ToU32(c);
+}
+
+const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
+{
+ ImGuiStyle& style = GImGui->Style;
+ return style.Colors[idx];
+}
+
+ImU32 ImGui::GetColorU32(ImU32 col)
+{
+ float style_alpha = GImGui->Style.Alpha;
+ if (style_alpha >= 1.0f)
+ return col;
+ ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
+ a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
+ return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiStorage
+// Helper: Key->value storage
+//-----------------------------------------------------------------------------
+
+// std::lower_bound but without the bullshit
+static ImGuiStorage::Pair* LowerBound(ImVector<ImGuiStorage::Pair>& data, ImGuiID key)
+{
+ ImGuiStorage::Pair* first = data.Data;
+ ImGuiStorage::Pair* last = data.Data + data.Size;
+ size_t count = (size_t)(last - first);
+ while (count > 0)
+ {
+ size_t count2 = count >> 1;
+ ImGuiStorage::Pair* mid = first + count2;
+ if (mid->key < key)
+ {
+ first = ++mid;
+ count -= count2 + 1;
+ }
+ else
+ {
+ count = count2;
+ }
+ }
+ return first;
+}
+
+// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
+void ImGuiStorage::BuildSortByKey()
+{
+ struct StaticFunc
+ {
+ static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs)
+ {
+ // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
+ if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1;
+ if (((const Pair*)lhs)->key < ((const Pair*)rhs)->key) return -1;
+ return 0;
+ }
+ };
+ if (Data.Size > 1)
+ ImQsort(Data.Data, (size_t)Data.Size, sizeof(Pair), StaticFunc::PairCompareByID);
+}
+
+int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
+{
+ ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
+ if (it == Data.end() || it->key != key)
+ return default_val;
+ return it->val_i;
+}
+
+bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
+{
+ return GetInt(key, default_val ? 1 : 0) != 0;
+}
+
+float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
+{
+ ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
+ if (it == Data.end() || it->key != key)
+ return default_val;
+ return it->val_f;
+}
+
+void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
+{
+ ImGuiStorage::Pair* it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
+ if (it == Data.end() || it->key != key)
+ return NULL;
+ return it->val_p;
+}
+
+// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
+int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
+{
+ ImGuiStorage::Pair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ it = Data.insert(it, Pair(key, default_val));
+ return &it->val_i;
+}
+
+bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
+{
+ return (bool*)GetIntRef(key, default_val ? 1 : 0);
+}
+
+float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
+{
+ ImGuiStorage::Pair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ it = Data.insert(it, Pair(key, default_val));
+ return &it->val_f;
+}
+
+void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
+{
+ ImGuiStorage::Pair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ it = Data.insert(it, Pair(key, default_val));
+ return &it->val_p;
+}
+
+// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
+void ImGuiStorage::SetInt(ImGuiID key, int val)
+{
+ ImGuiStorage::Pair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ {
+ Data.insert(it, Pair(key, val));
+ return;
+ }
+ it->val_i = val;
+}
+
+void ImGuiStorage::SetBool(ImGuiID key, bool val)
+{
+ SetInt(key, val ? 1 : 0);
+}
+
+void ImGuiStorage::SetFloat(ImGuiID key, float val)
+{
+ ImGuiStorage::Pair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ {
+ Data.insert(it, Pair(key, val));
+ return;
+ }
+ it->val_f = val;
+}
+
+void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
+{
+ ImGuiStorage::Pair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ {
+ Data.insert(it, Pair(key, val));
+ return;
+ }
+ it->val_p = val;
+}
+
+void ImGuiStorage::SetAllInt(int v)
+{
+ for (int i = 0; i < Data.Size; i++)
+ Data[i].val_i = v;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiTextFilter
+//-----------------------------------------------------------------------------
+
+// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
+ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
+{
+ if (default_filter)
+ {
+ ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
+ Build();
+ }
+ else
+ {
+ InputBuf[0] = 0;
+ CountGrep = 0;
+ }
+}
+
+bool ImGuiTextFilter::Draw(const char* label, float width)
+{
+ if (width != 0.0f)
+ ImGui::PushItemWidth(width);
+ bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
+ if (width != 0.0f)
+ ImGui::PopItemWidth();
+ if (value_changed)
+ Build();
+ return value_changed;
+}
+
+void ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>* out) const
+{
+ out->resize(0);
+ const char* wb = b;
+ const char* we = wb;
+ while (we < e)
+ {
+ if (*we == separator)
+ {
+ out->push_back(TextRange(wb, we));
+ wb = we + 1;
+ }
+ we++;
+ }
+ if (wb != we)
+ out->push_back(TextRange(wb, we));
+}
+
+void ImGuiTextFilter::Build()
+{
+ Filters.resize(0);
+ TextRange input_range(InputBuf, InputBuf+strlen(InputBuf));
+ input_range.split(',', &Filters);
+
+ CountGrep = 0;
+ for (int i = 0; i != Filters.Size; i++)
+ {
+ TextRange& f = Filters[i];
+ while (f.b < f.e && ImCharIsBlankA(f.b[0]))
+ f.b++;
+ while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
+ f.e--;
+ if (f.empty())
+ continue;
+ if (Filters[i].b[0] != '-')
+ CountGrep += 1;
+ }
+}
+
+bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
+{
+ if (Filters.empty())
+ return true;
+
+ if (text == NULL)
+ text = "";
+
+ for (int i = 0; i != Filters.Size; i++)
+ {
+ const TextRange& f = Filters[i];
+ if (f.empty())
+ continue;
+ if (f.b[0] == '-')
+ {
+ // Subtract
+ if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL)
+ return false;
+ }
+ else
+ {
+ // Grep
+ if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)
+ return true;
+ }
+ }
+
+ // Implicit * grep
+ if (CountGrep == 0)
+ return true;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiTextBuffer
+//-----------------------------------------------------------------------------
+
+// On some platform vsnprintf() takes va_list by reference and modifies it.
+// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
+#ifndef va_copy
+#if defined(__GNUC__) || defined(__clang__)
+#define va_copy(dest, src) __builtin_va_copy(dest, src)
+#else
+#define va_copy(dest, src) (dest = src)
+#endif
+#endif
+
+char ImGuiTextBuffer::EmptyString[1] = { 0 };
+
+// Helper: Text buffer for logging/accumulating text
+void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
+{
+ va_list args_copy;
+ va_copy(args_copy, args);
+
+ int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
+ if (len <= 0)
+ {
+ va_end(args_copy);
+ return;
+ }
+
+ // Add zero-terminator the first time
+ const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
+ const int needed_sz = write_off + len;
+ if (write_off + len >= Buf.Capacity)
+ {
+ int double_capacity = Buf.Capacity * 2;
+ Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity);
+ }
+
+ Buf.resize(needed_sz);
+ ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy);
+ va_end(args_copy);
+}
+
+void ImGuiTextBuffer::appendf(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ appendfv(fmt, args);
+ va_end(args);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiListClipper
+// This is currently not as flexible/powerful as it should be, needs some rework (see TODO)
+//-----------------------------------------------------------------------------
+
+static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
+{
+ // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor.
+ // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
+ // The clipper should probably have a 4th step to display the last item in a regular manner.
+ ImGui::SetCursorPosY(pos_y);
+ ImGuiWindow* window = ImGui::GetCurrentWindow();
+ window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
+ window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
+ if (window->DC.ColumnsSet)
+ window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
+}
+
+// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1
+// Use case B: Begin() called from constructor with items_height>0
+// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style.
+void ImGuiListClipper::Begin(int count, float items_height)
+{
+ StartPosY = ImGui::GetCursorPosY();
+ ItemsHeight = items_height;
+ ItemsCount = count;
+ StepNo = 0;
+ DisplayEnd = DisplayStart = -1;
+ if (ItemsHeight > 0.0f)
+ {
+ ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display
+ if (DisplayStart > 0)
+ SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor
+ StepNo = 2;
+ }
+}
+
+void ImGuiListClipper::End()
+{
+ if (ItemsCount < 0)
+ return;
+ // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user.
+ if (ItemsCount < INT_MAX)
+ SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor
+ ItemsCount = -1;
+ StepNo = 3;
+}
+
+bool ImGuiListClipper::Step()
+{
+ if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)
+ {
+ ItemsCount = -1;
+ return false;
+ }
+ if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height.
+ {
+ DisplayStart = 0;
+ DisplayEnd = 1;
+ StartPosY = ImGui::GetCursorPosY();
+ StepNo = 1;
+ return true;
+ }
+ if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
+ {
+ if (ItemsCount == 1) { ItemsCount = -1; return false; }
+ float items_height = ImGui::GetCursorPosY() - StartPosY;
+ IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically
+ Begin(ItemsCount-1, items_height);
+ DisplayStart++;
+ DisplayEnd++;
+ StepNo = 3;
+ return true;
+ }
+ if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3.
+ {
+ IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0);
+ StepNo = 3;
+ return true;
+ }
+ if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
+ End();
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] RENDER HELPERS
+// Those (internal) functions are currently quite a legacy mess - their signature and behavior will change.
+// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: state.
+//-----------------------------------------------------------------------------
+
+const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
+{
+ const char* text_display_end = text;
+ if (!text_end)
+ text_end = (const char*)-1;
+
+ while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
+ text_display_end++;
+ return text_display_end;
+}
+
+// Internal ImGui functions to render text
+// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
+void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // Hide anything after a '##' string
+ const char* text_display_end;
+ if (hide_text_after_hash)
+ {
+ text_display_end = FindRenderedTextEnd(text, text_end);
+ }
+ else
+ {
+ if (!text_end)
+ text_end = text + strlen(text); // FIXME-OPT
+ text_display_end = text_end;
+ }
+
+ if (text != text_display_end)
+ {
+ window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
+ if (g.LogEnabled)
+ LogRenderedText(&pos, text, text_display_end);
+ }
+}
+
+void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (!text_end)
+ text_end = text + strlen(text); // FIXME-OPT
+
+ if (text != text_end)
+ {
+ window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
+ if (g.LogEnabled)
+ LogRenderedText(&pos, text, text_end);
+ }
+}
+
+// Default clip_rect uses (pos_min,pos_max)
+// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
+void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
+{
+ // Perform CPU side clipping for single clipped element to avoid using scissor state
+ ImVec2 pos = pos_min;
+ const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);
+
+ const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
+ const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
+ bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
+ if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
+ need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
+
+ // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
+ if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
+ if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
+
+ // Render
+ if (need_clipping)
+ {
+ ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
+ draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
+ }
+ else
+ {
+ draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
+ }
+}
+
+void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
+{
+ // Hide anything after a '##' string
+ const char* text_display_end = FindRenderedTextEnd(text, text_end);
+ const int text_len = (int)(text_display_end - text);
+ if (text_len == 0)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
+ if (g.LogEnabled)
+ LogRenderedText(&pos_min, text, text_display_end);
+}
+
+// Render a rectangle shaped with optional rounding and borders
+void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
+ const float border_size = g.Style.FrameBorderSize;
+ if (border && border_size > 0.0f)
+ {
+ window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ }
+}
+
+void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ const float border_size = g.Style.FrameBorderSize;
+ if (border_size > 0.0f)
+ {
+ window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
+ }
+}
+
+// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state
+void ImGui::RenderArrow(ImVec2 p_min, ImGuiDir dir, float scale)
+{
+ ImGuiContext& g = *GImGui;
+
+ const float h = g.FontSize * 1.00f;
+ float r = h * 0.40f * scale;
+ ImVec2 center = p_min + ImVec2(h * 0.50f, h * 0.50f * scale);
+
+ ImVec2 a, b, c;
+ switch (dir)
+ {
+ case ImGuiDir_Up:
+ case ImGuiDir_Down:
+ if (dir == ImGuiDir_Up) r = -r;
+ a = ImVec2(+0.000f,+0.750f) * r;
+ b = ImVec2(-0.866f,-0.750f) * r;
+ c = ImVec2(+0.866f,-0.750f) * r;
+ break;
+ case ImGuiDir_Left:
+ case ImGuiDir_Right:
+ if (dir == ImGuiDir_Left) r = -r;
+ a = ImVec2(+0.750f,+0.000f) * r;
+ b = ImVec2(-0.750f,+0.866f) * r;
+ c = ImVec2(-0.750f,-0.866f) * r;
+ break;
+ case ImGuiDir_None:
+ case ImGuiDir_COUNT:
+ IM_ASSERT(0);
+ break;
+ }
+
+ g.CurrentWindow->DrawList->AddTriangleFilled(center + a, center + b, center + c, GetColorU32(ImGuiCol_Text));
+}
+
+void ImGui::RenderBullet(ImVec2 pos)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ window->DrawList->AddCircleFilled(pos, g.FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);
+}
+
+void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col, float sz)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ float thickness = ImMax(sz / 5.0f, 1.0f);
+ sz -= thickness*0.5f;
+ pos += ImVec2(thickness*0.25f, thickness*0.25f);
+
+ float third = sz / 3.0f;
+ float bx = pos.x + third;
+ float by = pos.y + sz - third*0.5f;
+ window->DrawList->PathLineTo(ImVec2(bx - third, by - third));
+ window->DrawList->PathLineTo(ImVec2(bx, by));
+ window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2));
+ window->DrawList->PathStroke(col, false, thickness);
+}
+
+void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (id != g.NavId)
+ return;
+ if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
+ return;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->DC.NavHideHighlightOneFrame)
+ return;
+
+ float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
+ ImRect display_rect = bb;
+ display_rect.ClipWith(window->ClipRect);
+ if (flags & ImGuiNavHighlightFlags_TypeDefault)
+ {
+ const float THICKNESS = 2.0f;
+ const float DISTANCE = 3.0f + THICKNESS * 0.5f;
+ display_rect.Expand(ImVec2(DISTANCE,DISTANCE));
+ bool fully_visible = window->ClipRect.Contains(display_rect);
+ if (!fully_visible)
+ window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
+ window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS);
+ if (!fully_visible)
+ window->DrawList->PopClipRect();
+ }
+ if (flags & ImGuiNavHighlightFlags_TypeThin)
+ {
+ window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
+//-----------------------------------------------------------------------------
+
+// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
+ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
+ : DrawListInst(&context->DrawListSharedData)
+{
+ Name = ImStrdup(name);
+ ID = ImHash(name, 0);
+ IDStack.push_back(ID);
+ Flags = ImGuiWindowFlags_None;
+ Pos = ImVec2(0.0f, 0.0f);
+ Size = SizeFull = ImVec2(0.0f, 0.0f);
+ SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);
+ WindowPadding = ImVec2(0.0f, 0.0f);
+ WindowRounding = 0.0f;
+ WindowBorderSize = 0.0f;
+ NameBufLen = (int)strlen(name) + 1;
+ MoveId = GetID("#MOVE");
+ ChildId = 0;
+ Scroll = ImVec2(0.0f, 0.0f);
+ ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
+ ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
+ ScrollbarSizes = ImVec2(0.0f, 0.0f);
+ ScrollbarX = ScrollbarY = false;
+ Active = WasActive = false;
+ WriteAccessed = false;
+ Collapsed = false;
+ WantCollapseToggle = false;
+ SkipItems = false;
+ Appearing = false;
+ Hidden = false;
+ HasCloseButton = false;
+ BeginCount = 0;
+ BeginOrderWithinParent = -1;
+ BeginOrderWithinContext = -1;
+ PopupId = 0;
+ AutoFitFramesX = AutoFitFramesY = -1;
+ AutoFitOnlyGrows = false;
+ AutoFitChildAxises = 0x00;
+ AutoPosLastDirection = ImGuiDir_None;
+ HiddenFramesRegular = HiddenFramesForResize = 0;
+ SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
+ SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
+
+ LastFrameActive = -1;
+ ItemWidthDefault = 0.0f;
+ FontWindowScale = 1.0f;
+ SettingsIdx = -1;
+
+ DrawList = &DrawListInst;
+ DrawList->_OwnerName = Name;
+ ParentWindow = NULL;
+ RootWindow = NULL;
+ RootWindowForTitleBarHighlight = NULL;
+ RootWindowForNav = NULL;
+
+ NavLastIds[0] = NavLastIds[1] = 0;
+ NavRectRel[0] = NavRectRel[1] = ImRect();
+ NavLastChildNavWindow = NULL;
+
+ FocusIdxAllCounter = FocusIdxTabCounter = -1;
+ FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
+ FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;
+}
+
+ImGuiWindow::~ImGuiWindow()
+{
+ IM_ASSERT(DrawList == &DrawListInst);
+ IM_DELETE(Name);
+ for (int i = 0; i != ColumnsStorage.Size; i++)
+ ColumnsStorage[i].~ImGuiColumnsSet();
+}
+
+ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
+ ImGui::KeepAliveID(id);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetID(const void* ptr)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHash(&ptr, sizeof(void*), seed);
+ ImGui::KeepAliveID(id);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
+{
+ ImGuiID seed = IDStack.back();
+ return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
+}
+
+ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
+{
+ ImGuiID seed = IDStack.back();
+ return ImHash(&ptr, sizeof(void*), seed);
+}
+
+// This is only used in rare/specific situations to manufacture an ID out of nowhere.
+ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs)
+{
+ ImGuiID seed = IDStack.back();
+ const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) };
+ ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed);
+ ImGui::KeepAliveID(id);
+ return id;
+}
+
+static void SetCurrentWindow(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ g.CurrentWindow = window;
+ if (window)
+ g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
+}
+
+void ImGui::SetNavID(ImGuiID id, int nav_layer)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindow);
+ IM_ASSERT(nav_layer == 0 || nav_layer == 1);
+ g.NavId = id;
+ g.NavWindow->NavLastIds[nav_layer] = id;
+}
+
+void ImGui::SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel)
+{
+ ImGuiContext& g = *GImGui;
+ SetNavID(id, nav_layer);
+ g.NavWindow->NavRectRel[nav_layer] = rect_rel;
+ g.NavMousePosDirty = true;
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = true;
+}
+
+void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ g.ActiveIdIsJustActivated = (g.ActiveId != id);
+ if (g.ActiveIdIsJustActivated)
+ {
+ g.ActiveIdTimer = 0.0f;
+ g.ActiveIdHasBeenEdited = false;
+ if (id != 0)
+ {
+ g.LastActiveId = id;
+ g.LastActiveIdTimer = 0.0f;
+ }
+ }
+ g.ActiveId = id;
+ g.ActiveIdAllowNavDirFlags = 0;
+ g.ActiveIdAllowOverlap = false;
+ g.ActiveIdWindow = window;
+ if (id)
+ {
+ g.ActiveIdIsAlive = id;
+ g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
+ }
+}
+
+// FIXME-NAV: The existence of SetNavID/SetNavIDWithRectRel/SetFocusID is incredibly messy and confusing and needs some explanation or refactoring.
+void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(id != 0);
+
+ // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it.
+ const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
+ if (g.NavWindow != window)
+ g.NavInitRequest = false;
+ g.NavId = id;
+ g.NavWindow = window;
+ g.NavLayer = nav_layer;
+ window->NavLastIds[nav_layer] = id;
+ if (window->DC.LastItemId == id)
+ window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);
+
+ if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ g.NavDisableMouseHover = true;
+ else
+ g.NavDisableHighlight = true;
+}
+
+void ImGui::ClearActiveID()
+{
+ SetActiveID(0, NULL);
+}
+
+void ImGui::SetHoveredID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ g.HoveredId = id;
+ g.HoveredIdAllowOverlap = false;
+ if (id != 0 && g.HoveredIdPreviousFrame != id)
+ g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
+}
+
+ImGuiID ImGui::GetHoveredID()
+{
+ ImGuiContext& g = *GImGui;
+ return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
+}
+
+void ImGui::KeepAliveID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId == id)
+ g.ActiveIdIsAlive = id;
+ if (g.ActiveIdPreviousFrame == id)
+ g.ActiveIdPreviousFrameIsAlive = true;
+}
+
+void ImGui::MarkItemEdited(ImGuiID id)
+{
+ // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
+ // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data.
+ (void)id; // Avoid unused variable warnings when asserts are compiled out.
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
+ //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
+ g.ActiveIdHasBeenEdited = true;
+ g.CurrentWindow->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;
+}
+
+static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
+{
+ // An active popup disable hovering on other windows (apart from its own children)
+ // FIXME-OPT: This could be cached/stored within the window.
+ ImGuiContext& g = *GImGui;
+ if (g.NavWindow)
+ if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
+ if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
+ {
+ // For the purpose of those flags we differentiate "standard popup" from "modal popup"
+ // NB: The order of those two tests is important because Modal windows are also Popups.
+ if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
+ return false;
+ if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ return false;
+ }
+
+ return true;
+}
+
+// Advance cursor given item size for layout.
+void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ // Always align ourselves on pixel boundaries
+ const float line_height = ImMax(window->DC.CurrentLineSize.y, size.y);
+ const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
+ //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
+ window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
+ window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+ window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y);
+ window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
+ window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
+ //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
+
+ window->DC.PrevLineSize.y = line_height;
+ window->DC.PrevLineTextBaseOffset = text_base_offset;
+ window->DC.CurrentLineSize.y = window->DC.CurrentLineTextBaseOffset = 0.0f;
+
+ // Horizontal layout mode
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
+ SameLine();
+}
+
+void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
+{
+ ItemSize(bb.GetSize(), text_offset_y);
+}
+
+// Declare item bounding box for clipping and interaction.
+// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
+// declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
+bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (id != 0)
+ {
+ // Navigation processing runs prior to clipping early-out
+ // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
+ // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window.
+ // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame.
+ // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick)
+ window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask;
+ if (g.NavId == id || g.NavAnyRequest)
+ if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
+ if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
+ NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id);
+ }
+
+ window->DC.LastItemId = id;
+ window->DC.LastItemRect = bb;
+ window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ if (id != 0)
+ ImGuiTestEngineHook_ItemAdd(&g, bb, id);
+#endif
+
+ // Clipping test
+ const bool is_clipped = IsClippedEx(bb, id, false);
+ if (is_clipped)
+ return false;
+ //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
+
+ // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
+ if (IsMouseHoveringRect(bb.Min, bb.Max))
+ window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;
+ return true;
+}
+
+// This is roughly matching the behavior of internal-facing ItemHoverable()
+// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()
+// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
+bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.NavDisableMouseHover && !g.NavDisableHighlight)
+ return IsItemFocused();
+
+ // Test for bounding box overlap, as updated as ItemAdd()
+ if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
+ return false;
+ IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
+
+ // Test if we are hovering the right window (our window could be behind another window)
+ // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself.
+ // Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
+ //if (g.HoveredWindow != window)
+ // return false;
+ if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
+ return false;
+
+ // Test if another item is active (e.g. being dragged)
+ if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
+ return false;
+
+ // Test if interactions on this window are blocked by an active popup or modal
+ if (!IsWindowContentHoverable(window, flags))
+ return false;
+
+ // Test if the item is disabled
+ if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
+ return false;
+
+ // Special handling for the 1st item after Begin() which represent the title bar. When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect tht case.
+ if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
+ return false;
+ return true;
+}
+
+// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
+bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
+ return false;
+
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.HoveredWindow != window)
+ return false;
+ if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
+ return false;
+ if (!IsMouseHoveringRect(bb.Min, bb.Max))
+ return false;
+ if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
+ return false;
+ if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
+ return false;
+
+ SetHoveredID(id);
+ return true;
+}
+
+bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!bb.Overlaps(window->ClipRect))
+ if (id == 0 || id != g.ActiveId)
+ if (clip_even_when_logged || !g.LogEnabled)
+ return true;
+ return false;
+}
+
+bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
+{
+ ImGuiContext& g = *GImGui;
+
+ const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
+ window->FocusIdxAllCounter++;
+ if (is_tab_stop)
+ window->FocusIdxTabCounter++;
+
+ // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item.
+ // Note that we can always TAB out of a widget that doesn't allow tabbing in.
+ if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
+ window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
+
+ if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
+ return true;
+ if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
+ {
+ g.NavJustTabbedId = id;
+ return true;
+ }
+
+ return false;
+}
+
+void ImGui::FocusableItemUnregister(ImGuiWindow* window)
+{
+ window->FocusIdxAllCounter--;
+ window->FocusIdxTabCounter--;
+}
+
+ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 content_max;
+ if (size.x < 0.0f || size.y < 0.0f)
+ content_max = g.CurrentWindow->Pos + GetContentRegionMax();
+ if (size.x <= 0.0f)
+ size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
+ if (size.y <= 0.0f)
+ size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
+ return size;
+}
+
+float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
+{
+ if (wrap_pos_x < 0.0f)
+ return 0.0f;
+
+ ImGuiWindow* window = GetCurrentWindowRead();
+ if (wrap_pos_x == 0.0f)
+ wrap_pos_x = GetContentRegionMax().x + window->Pos.x;
+ else if (wrap_pos_x > 0.0f)
+ wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
+
+ return ImMax(wrap_pos_x - pos.x, 1.0f);
+}
+
+void* ImGui::MemAlloc(size_t size)
+{
+ if (ImGuiContext* ctx = GImGui)
+ ctx->IO.MetricsActiveAllocations++;
+ return GImAllocatorAllocFunc(size, GImAllocatorUserData);
+}
+
+void ImGui::MemFree(void* ptr)
+{
+ if (ptr)
+ if (ImGuiContext* ctx = GImGui)
+ ctx->IO.MetricsActiveAllocations--;
+ return GImAllocatorFreeFunc(ptr, GImAllocatorUserData);
+}
+
+const char* ImGui::GetClipboardText()
+{
+ return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : "";
+}
+
+void ImGui::SetClipboardText(const char* text)
+{
+ if (GImGui->IO.SetClipboardTextFn)
+ GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);
+}
+
+const char* ImGui::GetVersion()
+{
+ return IMGUI_VERSION;
+}
+
+// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
+// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module
+ImGuiContext* ImGui::GetCurrentContext()
+{
+ return GImGui;
+}
+
+void ImGui::SetCurrentContext(ImGuiContext* ctx)
+{
+#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
+ IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
+#else
+ GImGui = ctx;
+#endif
+}
+
+// Helper function to verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
+// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. you may see different structures from what imgui.cpp sees which is highly problematic.
+bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert)
+{
+ bool error = false;
+ if (strcmp(version, IMGUI_VERSION)!=0) { error = true; IM_ASSERT(strcmp(version,IMGUI_VERSION)==0 && "Mismatched version string!"); }
+ if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); }
+ if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); }
+ if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); }
+ if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); }
+ if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); }
+ return !error;
+}
+
+void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data)
+{
+ GImAllocatorAllocFunc = alloc_func;
+ GImAllocatorFreeFunc = free_func;
+ GImAllocatorUserData = user_data;
+}
+
+ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
+{
+ ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
+ if (GImGui == NULL)
+ SetCurrentContext(ctx);
+ Initialize(ctx);
+ return ctx;
+}
+
+void ImGui::DestroyContext(ImGuiContext* ctx)
+{
+ if (ctx == NULL)
+ ctx = GImGui;
+ Shutdown(ctx);
+ if (GImGui == ctx)
+ SetCurrentContext(NULL);
+ IM_DELETE(ctx);
+}
+
+ImGuiIO& ImGui::GetIO()
+{
+ IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
+ return GImGui->IO;
+}
+
+ImGuiStyle& ImGui::GetStyle()
+{
+ IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
+ return GImGui->Style;
+}
+
+// Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame()
+ImDrawData* ImGui::GetDrawData()
+{
+ ImGuiContext& g = *GImGui;
+ return g.DrawData.Valid ? &g.DrawData : NULL;
+}
+
+double ImGui::GetTime()
+{
+ return GImGui->Time;
+}
+
+int ImGui::GetFrameCount()
+{
+ return GImGui->FrameCount;
+}
+
+static ImDrawList* GetOverlayDrawList(ImGuiWindow*)
+{
+ // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'viewport' branches.
+ return &GImGui->OverlayDrawList;
+}
+
+ImDrawList* ImGui::GetOverlayDrawList()
+{
+ return &GImGui->OverlayDrawList;
+}
+
+ImDrawListSharedData* ImGui::GetDrawListSharedData()
+{
+ return &GImGui->DrawListSharedData;
+}
+
+void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
+{
+ // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows.
+ // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward.
+ // This is because we want ActiveId to be set even when the window is stuck from moving.
+ ImGuiContext& g = *GImGui;
+ FocusWindow(window);
+ SetActiveID(window->MoveId, window);
+ g.NavDisableHighlight = true;
+ g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
+ if (!(window->Flags & ImGuiWindowFlags_NoMove) && !(window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
+ g.MovingWindow = window;
+}
+
+// Handle mouse moving window
+// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
+void ImGui::UpdateMouseMovingWindowNewFrame()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.MovingWindow != NULL)
+ {
+ // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
+ // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
+ KeepAliveID(g.ActiveId);
+ IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow);
+ ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
+ if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
+ {
+ ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
+ if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
+ {
+ MarkIniSettingsDirty(moving_window);
+ SetWindowPos(moving_window, pos, ImGuiCond_Always);
+ }
+ FocusWindow(g.MovingWindow);
+ }
+ else
+ {
+ ClearActiveID();
+ g.MovingWindow = NULL;
+ }
+ }
+ else
+ {
+ // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others.
+ if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId)
+ {
+ KeepAliveID(g.ActiveId);
+ if (!g.IO.MouseDown[0])
+ ClearActiveID();
+ }
+ }
+}
+
+// Initiate moving window, handle left-click and right-click focus
+void ImGui::UpdateMouseMovingWindowEndFrame()
+{
+ // Initiate moving window
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId != 0 || g.HoveredId != 0)
+ return;
+
+ // Unless we just made a window/popup appear
+ if (g.NavWindow && g.NavWindow->Appearing)
+ return;
+
+ // Click to focus window and start moving (after we're done with all our widgets)
+ if (g.IO.MouseClicked[0])
+ {
+ if (g.HoveredRootWindow != NULL)
+ {
+ StartMouseMovingWindow(g.HoveredWindow);
+ if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoTitleBar))
+ if (!g.HoveredRootWindow->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
+ g.MovingWindow = NULL;
+ }
+ else if (g.NavWindow != NULL && GetFrontMostPopupModal() == NULL)
+ {
+ FocusWindow(NULL); // Clicking on void disable focus
+ }
+ }
+
+ // With right mouse button we close popups without changing focus
+ // (The left mouse button path calls FocusWindow which will lead NewFrame->ClosePopupsOverWindow to trigger)
+ if (g.IO.MouseClicked[1])
+ {
+ // Find the top-most window between HoveredWindow and the front most Modal Window.
+ // This is where we can trim the popup stack.
+ ImGuiWindow* modal = GetFrontMostPopupModal();
+ bool hovered_window_above_modal = false;
+ if (modal == NULL)
+ hovered_window_above_modal = true;
+ for (int i = g.Windows.Size - 1; i >= 0 && hovered_window_above_modal == false; i--)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (window == modal)
+ break;
+ if (window == g.HoveredWindow)
+ hovered_window_above_modal = true;
+ }
+ ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal);
+ }
+}
+
+static bool IsWindowActiveAndVisible(ImGuiWindow* window)
+{
+ return (window->Active) && (!window->Hidden);
+}
+
+static void ImGui::UpdateMouseInputs()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
+ if (IsMousePosValid(&g.IO.MousePos))
+ g.IO.MousePos = g.LastValidMousePos = ImFloor(g.IO.MousePos);
+
+ // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
+ if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev))
+ g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
+ else
+ g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
+ if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)
+ g.NavDisableMouseHover = false;
+
+ g.IO.MousePosPrev = g.IO.MousePos;
+ for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
+ {
+ g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
+ g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
+ g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
+ g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
+ g.IO.MouseDoubleClicked[i] = false;
+ if (g.IO.MouseClicked[i])
+ {
+ if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime)
+ {
+ ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
+ if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
+ g.IO.MouseDoubleClicked[i] = true;
+ g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click
+ }
+ else
+ {
+ g.IO.MouseClickedTime[i] = g.Time;
+ }
+ g.IO.MouseClickedPos[i] = g.IO.MousePos;
+ g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
+ g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
+ }
+ else if (g.IO.MouseDown[i])
+ {
+ // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold
+ ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
+ g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
+ g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
+ g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
+ }
+ if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
+ g.NavDisableMouseHover = false;
+ }
+}
+
+void ImGui::UpdateMouseWheel()
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.HoveredWindow || g.HoveredWindow->Collapsed)
+ return;
+ if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
+ return;
+
+ // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set).
+ ImGuiWindow* window = g.HoveredWindow;
+ ImGuiWindow* scroll_window = window;
+ while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoMouseInputs) && scroll_window->ParentWindow)
+ scroll_window = scroll_window->ParentWindow;
+ const bool scroll_allowed = !(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoMouseInputs);
+
+ if (g.IO.MouseWheel != 0.0f)
+ {
+ if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
+ {
+ // Zoom / Scale window
+ const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
+ const float scale = new_font_scale / window->FontWindowScale;
+ window->FontWindowScale = new_font_scale;
+
+ const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
+ window->Pos += offset;
+ window->Size *= scale;
+ window->SizeFull *= scale;
+ }
+ else if (!g.IO.KeyCtrl && scroll_allowed)
+ {
+ // Mouse wheel vertical scrolling
+ float scroll_amount = 5 * scroll_window->CalcFontSize();
+ scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f);
+ SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount);
+ }
+ }
+ if (g.IO.MouseWheelH != 0.0f && scroll_allowed && !g.IO.KeyCtrl)
+ {
+ // Mouse wheel horizontal scrolling (for hardware that supports it)
+ float scroll_amount = scroll_window->CalcFontSize();
+ SetWindowScrollX(scroll_window, scroll_window->Scroll.x - g.IO.MouseWheelH * scroll_amount);
+ }
+}
+
+// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
+void ImGui::UpdateHoveredWindowAndCaptureFlags()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Find the window hovered by mouse:
+ // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
+ // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
+ // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
+ FindHoveredWindow();
+
+ // Modal windows prevents cursor from hovering behind them.
+ ImGuiWindow* modal_window = GetFrontMostPopupModal();
+ if (modal_window)
+ if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
+ g.HoveredRootWindow = g.HoveredWindow = NULL;
+
+ // Disabled mouse?
+ if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse)
+ g.HoveredWindow = g.HoveredRootWindow = NULL;
+
+ // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward.
+ int mouse_earliest_button_down = -1;
+ bool mouse_any_down = false;
+ for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
+ {
+ if (g.IO.MouseClicked[i])
+ g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
+ mouse_any_down |= g.IO.MouseDown[i];
+ if (g.IO.MouseDown[i])
+ if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
+ mouse_earliest_button_down = i;
+ }
+ const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];
+
+ // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
+ // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02)
+ const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
+ if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload)
+ g.HoveredWindow = g.HoveredRootWindow = NULL;
+
+ // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app)
+ if (g.WantCaptureMouseNextFrame != -1)
+ g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
+ else
+ g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
+
+ // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to imgui + app)
+ if (g.WantCaptureKeyboardNextFrame != -1)
+ g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
+ else
+ g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
+ if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
+ g.IO.WantCaptureKeyboard = true;
+
+ // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible
+ g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
+}
+
+void ImGui::NewFrame()
+{
+ IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
+ ImGuiContext& g = *GImGui;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ ImGuiTestEngineHook_PreNewFrame(&g);
+#endif
+
+ // Check user data
+ // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument)
+ IM_ASSERT(g.Initialized);
+ IM_ASSERT(g.IO.DeltaTime >= 0.0f && "Need a positive DeltaTime (zero is tolerated but will cause some timing issues)");
+ IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value");
+ IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
+ IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?");
+ IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting");
+ IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)");
+ IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
+ for (int n = 0; n < ImGuiKey_COUNT; n++)
+ IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
+
+ // Perform simple check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only recently added in 1.60 WIP)
+ if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
+ IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
+
+ // Perform simple check: the beta io.ConfigWindowsResizeFromEdges option requires back-end to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
+ if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
+ g.IO.ConfigWindowsResizeFromEdges = false;
+
+ // Load settings on first frame (if not explicitly loaded manually before)
+ if (!g.SettingsLoaded)
+ {
+ IM_ASSERT(g.SettingsWindows.empty());
+ if (g.IO.IniFilename)
+ LoadIniSettingsFromDisk(g.IO.IniFilename);
+ g.SettingsLoaded = true;
+ }
+
+ // Save settings (with a delay after the last modification, so we don't spam disk too much)
+ if (g.SettingsDirtyTimer > 0.0f)
+ {
+ g.SettingsDirtyTimer -= g.IO.DeltaTime;
+ if (g.SettingsDirtyTimer <= 0.0f)
+ {
+ if (g.IO.IniFilename != NULL)
+ SaveIniSettingsToDisk(g.IO.IniFilename);
+ else
+ g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves.
+ g.SettingsDirtyTimer = 0.0f;
+ }
+ }
+
+ g.Time += g.IO.DeltaTime;
+ g.FrameScopeActive = true;
+ g.FrameCount += 1;
+ g.TooltipOverrideCount = 0;
+ g.WindowsActiveCount = 0;
+
+ // Setup current font and draw list
+ g.IO.Fonts->Locked = true;
+ SetCurrentFont(GetDefaultFont());
+ IM_ASSERT(g.Font->IsLoaded());
+ g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
+ g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
+
+ g.OverlayDrawList.Clear();
+ g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID);
+ g.OverlayDrawList.PushClipRectFullScreen();
+ g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
+
+ // Mark rendering data as invalid to prevent user who may have a handle on it to use it
+ g.DrawData.Clear();
+
+ // Drag and drop keep the source ID alive so even if the source disappear our state is consistent
+ if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
+ KeepAliveID(g.DragDropPayload.SourceId);
+
+ // Clear reference to active widget if the widget isn't alive anymore
+ if (!g.HoveredIdPreviousFrame)
+ g.HoveredIdTimer = 0.0f;
+ if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId))
+ g.HoveredIdNotActiveTimer = 0.0f;
+ if (g.HoveredId)
+ g.HoveredIdTimer += g.IO.DeltaTime;
+ if (g.HoveredId && g.ActiveId != g.HoveredId)
+ g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
+ g.HoveredIdPreviousFrame = g.HoveredId;
+ g.HoveredId = 0;
+ g.HoveredIdAllowOverlap = false;
+ if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
+ ClearActiveID();
+ if (g.ActiveId)
+ g.ActiveIdTimer += g.IO.DeltaTime;
+ g.LastActiveIdTimer += g.IO.DeltaTime;
+ g.ActiveIdPreviousFrame = g.ActiveId;
+ g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
+ g.ActiveIdPreviousFrameHasBeenEdited = g.ActiveIdHasBeenEdited;
+ g.ActiveIdIsAlive = 0;
+ g.ActiveIdPreviousFrameIsAlive = false;
+ g.ActiveIdIsJustActivated = false;
+ if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)
+ g.ScalarAsInputTextId = 0;
+
+ // Drag and drop
+ g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
+ g.DragDropAcceptIdCurr = 0;
+ g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
+ g.DragDropWithinSourceOrTarget = false;
+
+ // Update keyboard input state
+ memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));
+ for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
+ g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f;
+
+ // Update gamepad/keyboard directional navigation
+ NavUpdate();
+
+ // Update mouse input state
+ UpdateMouseInputs();
+
+ // Calculate frame-rate for the user, as a purely luxurious feature
+ g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
+ g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
+ g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
+ g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame))) : FLT_MAX;
+
+ // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
+ UpdateMouseMovingWindowNewFrame();
+ UpdateHoveredWindowAndCaptureFlags();
+
+ // Background darkening/whitening
+ if (GetFrontMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f))
+ g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f);
+ else
+ g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f);
+
+ g.MouseCursor = ImGuiMouseCursor_Arrow;
+ g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
+ g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
+
+ // Mouse wheel scrolling, scale
+ UpdateMouseWheel();
+
+ // Pressing TAB activate widget focus
+ if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false))
+ {
+ if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
+ g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1);
+ else
+ g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0;
+ }
+ g.NavIdTabCounter = INT_MAX;
+
+ // Mark all windows as not visible
+ IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size);
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ window->WasActive = window->Active;
+ window->Active = false;
+ window->WriteAccessed = false;
+ }
+
+ // Closing the focused window restore focus to the first active root window in descending z-order
+ if (g.NavWindow && !g.NavWindow->WasActive)
+ FocusPreviousWindowIgnoringOne(NULL);
+
+ // No window should be open at the beginning of the frame.
+ // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
+ g.CurrentWindowStack.resize(0);
+ g.BeginPopupStack.resize(0);
+ ClosePopupsOverWindow(g.NavWindow);
+
+ // Create implicit/fallback window - which we will only render it if the user has added something to it.
+ // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
+ // This fallback is particularly important as it avoid ImGui:: calls from crashing.
+ SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);
+ Begin("Debug##Default");
+ g.FrameScopePushedImplicitWindow = true;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ ImGuiTestEngineHook_PostNewFrame(&g);
+#endif
+}
+
+void ImGui::Initialize(ImGuiContext* context)
+{
+ ImGuiContext& g = *context;
+ IM_ASSERT(!g.Initialized && !g.SettingsLoaded);
+
+ // Add .ini handle for ImGuiWindow type
+ ImGuiSettingsHandler ini_handler;
+ ini_handler.TypeName = "Window";
+ ini_handler.TypeHash = ImHash("Window", 0, 0);
+ ini_handler.ReadOpenFn = SettingsHandlerWindow_ReadOpen;
+ ini_handler.ReadLineFn = SettingsHandlerWindow_ReadLine;
+ ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll;
+ g.SettingsHandlers.push_front(ini_handler);
+
+ g.Initialized = true;
+}
+
+// This function is merely here to free heap allocations.
+void ImGui::Shutdown(ImGuiContext* context)
+{
+ // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
+ ImGuiContext& g = *context;
+ if (g.IO.Fonts && g.FontAtlasOwnedByContext)
+ {
+ g.IO.Fonts->Locked = false;
+ IM_DELETE(g.IO.Fonts);
+ }
+ g.IO.Fonts = NULL;
+
+ // Cleanup of other data are conditional on actually having initialized ImGui.
+ if (!g.Initialized)
+ return;
+
+ // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file)
+ if (g.SettingsLoaded && g.IO.IniFilename != NULL)
+ {
+ ImGuiContext* backup_context = GImGui;
+ SetCurrentContext(context);
+ SaveIniSettingsToDisk(g.IO.IniFilename);
+ SetCurrentContext(backup_context);
+ }
+
+ // Clear everything else
+ for (int i = 0; i < g.Windows.Size; i++)
+ IM_DELETE(g.Windows[i]);
+ g.Windows.clear();
+ g.WindowsFocusOrder.clear();
+ g.WindowsSortBuffer.clear();
+ g.CurrentWindow = NULL;
+ g.CurrentWindowStack.clear();
+ g.WindowsById.Clear();
+ g.NavWindow = NULL;
+ g.HoveredWindow = NULL;
+ g.HoveredRootWindow = NULL;
+ g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
+ g.MovingWindow = NULL;
+ g.ColorModifiers.clear();
+ g.StyleModifiers.clear();
+ g.FontStack.clear();
+ g.OpenPopupStack.clear();
+ g.BeginPopupStack.clear();
+ g.DrawDataBuilder.ClearFreeMemory();
+ g.OverlayDrawList.ClearFreeMemory();
+ g.PrivateClipboard.clear();
+ g.InputTextState.TextW.clear();
+ g.InputTextState.InitialText.clear();
+ g.InputTextState.TempBuffer.clear();
+
+ for (int i = 0; i < g.SettingsWindows.Size; i++)
+ IM_DELETE(g.SettingsWindows[i].Name);
+ g.SettingsWindows.clear();
+ g.SettingsHandlers.clear();
+
+ if (g.LogFile && g.LogFile != stdout)
+ {
+ fclose(g.LogFile);
+ g.LogFile = NULL;
+ }
+ g.LogClipboard.clear();
+
+ g.Initialized = false;
+}
+
+// FIXME: Add a more explicit sort order in the window structure.
+static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs)
+{
+ const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs;
+ const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs;
+ if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
+ return d;
+ if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
+ return d;
+ return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
+}
+
+static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
+{
+ out_sorted_windows->push_back(window);
+ if (window->Active)
+ {
+ int count = window->DC.ChildWindows.Size;
+ if (count > 1)
+ ImQsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);
+ for (int i = 0; i < count; i++)
+ {
+ ImGuiWindow* child = window->DC.ChildWindows[i];
+ if (child->Active)
+ AddWindowToSortBuffer(out_sorted_windows, child);
+ }
+ }
+}
+
+static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
+{
+ if (draw_list->CmdBuffer.empty())
+ return;
+
+ // Remove trailing command if unused
+ ImDrawCmd& last_cmd = draw_list->CmdBuffer.back();
+ if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL)
+ {
+ draw_list->CmdBuffer.pop_back();
+ if (draw_list->CmdBuffer.empty())
+ return;
+ }
+
+ // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly.
+ IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
+ IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
+ IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
+
+ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
+ // If this assert triggers because you are drawing lots of stuff manually:
+ // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents.
+ // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes.
+ // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing:
+ // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
+ // Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API.
+ // C) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists.
+ if (sizeof(ImDrawIdx) == 2)
+ IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
+
+ out_list->push_back(draw_list);
+}
+
+static void AddWindowToDrawData(ImVector<ImDrawList*>* out_render_list, ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ g.IO.MetricsRenderWindows++;
+ AddDrawListToDrawData(out_render_list, window->DrawList);
+ for (int i = 0; i < window->DC.ChildWindows.Size; i++)
+ {
+ ImGuiWindow* child = window->DC.ChildWindows[i];
+ if (IsWindowActiveAndVisible(child)) // clipped children may have been marked not active
+ AddWindowToDrawData(out_render_list, child);
+ }
+}
+
+static void AddWindowToDrawDataSelectLayer(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (window->Flags & ImGuiWindowFlags_Tooltip)
+ AddWindowToDrawData(&g.DrawDataBuilder.Layers[1], window);
+ else
+ AddWindowToDrawData(&g.DrawDataBuilder.Layers[0], window);
+}
+
+void ImDrawDataBuilder::FlattenIntoSingleLayer()
+{
+ int n = Layers[0].Size;
+ int size = n;
+ for (int i = 1; i < IM_ARRAYSIZE(Layers); i++)
+ size += Layers[i].Size;
+ Layers[0].resize(size);
+ for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++)
+ {
+ ImVector<ImDrawList*>& layer = Layers[layer_n];
+ if (layer.empty())
+ continue;
+ memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
+ n += layer.Size;
+ layer.resize(0);
+ }
+}
+
+static void SetupDrawData(ImVector<ImDrawList*>* draw_lists, ImDrawData* draw_data)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ draw_data->Valid = true;
+ draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL;
+ draw_data->CmdListsCount = draw_lists->Size;
+ draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
+ draw_data->DisplayPos = ImVec2(0.0f, 0.0f);
+ draw_data->DisplaySize = io.DisplaySize;
+ for (int n = 0; n < draw_lists->Size; n++)
+ {
+ draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size;
+ draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size;
+ }
+}
+
+// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result.
+void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
+ window->ClipRect = window->DrawList->_ClipRectStack.back();
+}
+
+void ImGui::PopClipRect()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DrawList->PopClipRect();
+ window->ClipRect = window->DrawList->_ClipRectStack.back();
+}
+
+// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
+void ImGui::EndFrame()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Initialized);
+ if (g.FrameCountEnded == g.FrameCount) // Don't process EndFrame() multiple times.
+ return;
+ IM_ASSERT(g.FrameScopeActive && "Forgot to call ImGui::NewFrame()?");
+
+ // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
+ if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f)
+ {
+ g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImePos.y);
+ g.PlatformImeLastPos = g.PlatformImePos;
+ }
+
+ // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
+ // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
+ if (g.CurrentWindowStack.Size != 1)
+ {
+ if (g.CurrentWindowStack.Size > 1)
+ {
+ IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
+ while (g.CurrentWindowStack.Size > 1) // FIXME-ERRORHANDLING
+ End();
+ }
+ else
+ {
+ IM_ASSERT(g.CurrentWindowStack.Size == 1 && "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
+ }
+ }
+
+ // Hide implicit/fallback "Debug" window if it hasn't been used
+ g.FrameScopePushedImplicitWindow = false;
+ if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
+ g.CurrentWindow->Active = false;
+ End();
+
+ // Show CTRL+TAB list window
+ if (g.NavWindowingTarget)
+ NavUpdateWindowingList();
+
+ // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
+ if (g.DragDropActive)
+ {
+ bool is_delivered = g.DragDropPayload.Delivery;
+ bool is_elapsed = (g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) && ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(g.DragDropMouseButton));
+ if (is_delivered || is_elapsed)
+ ClearDragDrop();
+ }
+
+ // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing.
+ if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount)
+ {
+ g.DragDropWithinSourceOrTarget = true;
+ SetTooltip("...");
+ g.DragDropWithinSourceOrTarget = false;
+ }
+
+ // End frame
+ g.FrameScopeActive = false;
+ g.FrameCountEnded = g.FrameCount;
+
+ // Initiate moving window + handle left-click and right-click focus
+ UpdateMouseMovingWindowEndFrame();
+
+ // Sort the window list so that all child windows are after their parent
+ // We cannot do that on FocusWindow() because childs may not exist yet
+ g.WindowsSortBuffer.resize(0);
+ g.WindowsSortBuffer.reserve(g.Windows.Size);
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
+ continue;
+ AddWindowToSortBuffer(&g.WindowsSortBuffer, window);
+ }
+
+ IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong
+ g.Windows.swap(g.WindowsSortBuffer);
+ g.IO.MetricsActiveWindows = g.WindowsActiveCount;
+
+ // Unlock font atlas
+ g.IO.Fonts->Locked = false;
+
+ // Clear Input data for next frame
+ g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f;
+ g.IO.InputQueueCharacters.resize(0);
+ memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs));
+}
+
+void ImGui::Render()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Initialized);
+
+ if (g.FrameCountEnded != g.FrameCount)
+ EndFrame();
+ g.FrameCountRendered = g.FrameCount;
+
+ // Gather ImDrawList to render (for each active window)
+ g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsRenderWindows = 0;
+ g.DrawDataBuilder.Clear();
+ ImGuiWindow* windows_to_render_front_most[2];
+ windows_to_render_front_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
+ windows_to_render_front_most[1] = g.NavWindowingTarget ? g.NavWindowingList : NULL;
+ for (int n = 0; n != g.Windows.Size; n++)
+ {
+ ImGuiWindow* window = g.Windows[n];
+ if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1])
+ AddWindowToDrawDataSelectLayer(window);
+ }
+ for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_front_most); n++)
+ if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window
+ AddWindowToDrawDataSelectLayer(windows_to_render_front_most[n]);
+ g.DrawDataBuilder.FlattenIntoSingleLayer();
+
+ // Draw software mouse cursor if requested
+ if (g.IO.MouseDrawCursor)
+ RenderMouseCursor(&g.OverlayDrawList, g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor);
+
+ if (!g.OverlayDrawList.VtxBuffer.empty())
+ AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList);
+
+ // Setup ImDrawData structure for end-user
+ SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData);
+ g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount;
+ g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount;
+
+ // (Legacy) Call the Render callback function. The current prefer way is to let the user retrieve GetDrawData() and call the render function themselves.
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
+ g.IO.RenderDrawListsFn(&g.DrawData);
+#endif
+}
+
+// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
+// CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize)
+ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
+{
+ ImGuiContext& g = *GImGui;
+
+ const char* text_display_end;
+ if (hide_text_after_double_hash)
+ text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string
+ else
+ text_display_end = text_end;
+
+ ImFont* font = g.Font;
+ const float font_size = g.FontSize;
+ if (text == text_display_end)
+ return ImVec2(0.0f, font_size);
+ ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
+
+ // Cancel out character spacing for the last character of a line (it is baked into glyph->AdvanceX field)
+ const float font_scale = font_size / font->FontSize;
+ const float character_spacing_x = 1.0f * font_scale;
+ if (text_size.x > 0.0f)
+ text_size.x -= character_spacing_x;
+ text_size.x = (float)(int)(text_size.x + 0.95f);
+
+ return text_size;
+}
+
+// Helper to calculate coarse clipping of large list of evenly sized items.
+// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.
+// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
+void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.LogEnabled)
+ {
+ // If logging is active, do not perform any clipping
+ *out_items_display_start = 0;
+ *out_items_display_end = items_count;
+ return;
+ }
+ if (window->SkipItems)
+ {
+ *out_items_display_start = *out_items_display_end = 0;
+ return;
+ }
+
+ // We create the union of the ClipRect and the NavScoringRect which at worst should be 1 page away from ClipRect
+ ImRect unclipped_rect = window->ClipRect;
+ if (g.NavMoveRequest)
+ unclipped_rect.Add(g.NavScoringRectScreen);
+
+ const ImVec2 pos = window->DC.CursorPos;
+ int start = (int)((unclipped_rect.Min.y - pos.y) / items_height);
+ int end = (int)((unclipped_rect.Max.y - pos.y) / items_height);
+
+ // When performing a navigation request, ensure we have one item extra in the direction we are moving to
+ if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Up)
+ start--;
+ if (g.NavMoveRequest && g.NavMoveClipDir == ImGuiDir_Down)
+ end++;
+
+ start = ImClamp(start, 0, items_count);
+ end = ImClamp(end + 1, start, items_count);
+ *out_items_display_start = start;
+ *out_items_display_end = end;
+}
+
+// Find window given position, search front-to-back
+// FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programatically
+// with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is
+// called, aka before the next Begin(). Moving window isn't affected.
+static void FindHoveredWindow()
+{
+ ImGuiContext& g = *GImGui;
+
+ ImGuiWindow* hovered_window = NULL;
+ if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
+ hovered_window = g.MovingWindow;
+
+ ImVec2 padding_regular = g.Style.TouchExtraPadding;
+ ImVec2 padding_for_resize_from_edges = g.IO.ConfigWindowsResizeFromEdges ? ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS)) : padding_regular;
+ for (int i = g.Windows.Size - 1; i >= 0; i--)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (!window->Active || window->Hidden)
+ continue;
+ if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
+ continue;
+
+ // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
+ ImRect bb(window->OuterRectClipped);
+ if ((window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_NoResize))
+ bb.Expand(padding_regular);
+ else
+ bb.Expand(padding_for_resize_from_edges);
+ if (!bb.Contains(g.IO.MousePos))
+ continue;
+
+ // Those seemingly unnecessary extra tests are because the code here is a little different in viewport/docking branches.
+ if (hovered_window == NULL)
+ hovered_window = window;
+ if (hovered_window)
+ break;
+ }
+
+ g.HoveredWindow = hovered_window;
+ g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
+
+}
+
+// Test if mouse cursor is hovering given rectangle
+// NB- Rectangle is clipped by our current clip setting
+// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
+bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Clip
+ ImRect rect_clipped(r_min, r_max);
+ if (clip)
+ rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
+
+ // Expand for touch input
+ const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
+ if (!rect_for_touch.Contains(g.IO.MousePos))
+ return false;
+ return true;
+}
+
+int ImGui::GetKeyIndex(ImGuiKey imgui_key)
+{
+ IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
+ return GImGui->IO.KeyMap[imgui_key];
+}
+
+// Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]!
+bool ImGui::IsKeyDown(int user_key_index)
+{
+ if (user_key_index < 0) return false;
+ IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown));
+ return GImGui->IO.KeysDown[user_key_index];
+}
+
+int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate)
+{
+ if (t == 0.0f)
+ return 1;
+ if (t <= repeat_delay || repeat_rate <= 0.0f)
+ return 0;
+ const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate);
+ return (count > 0) ? count : 0;
+}
+
+int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
+{
+ ImGuiContext& g = *GImGui;
+ if (key_index < 0) return false;
+ IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ const float t = g.IO.KeysDownDuration[key_index];
+ return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate);
+}
+
+bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
+{
+ ImGuiContext& g = *GImGui;
+ if (user_key_index < 0) return false;
+ IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ const float t = g.IO.KeysDownDuration[user_key_index];
+ if (t == 0.0f)
+ return true;
+ if (repeat && t > g.IO.KeyRepeatDelay)
+ return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
+ return false;
+}
+
+bool ImGui::IsKeyReleased(int user_key_index)
+{
+ ImGuiContext& g = *GImGui;
+ if (user_key_index < 0) return false;
+ IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index];
+}
+
+bool ImGui::IsMouseDown(int button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseDown[button];
+}
+
+bool ImGui::IsAnyMouseDown()
+{
+ ImGuiContext& g = *GImGui;
+ for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
+ if (g.IO.MouseDown[n])
+ return true;
+ return false;
+}
+
+bool ImGui::IsMouseClicked(int button, bool repeat)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ const float t = g.IO.MouseDownDuration[button];
+ if (t == 0.0f)
+ return true;
+
+ if (repeat && t > g.IO.KeyRepeatDelay)
+ {
+ float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate;
+ if ((ImFmod(t - delay, rate) > rate*0.5f) != (ImFmod(t - delay - g.IO.DeltaTime, rate) > rate*0.5f))
+ return true;
+ }
+
+ return false;
+}
+
+bool ImGui::IsMouseReleased(int button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseReleased[button];
+}
+
+bool ImGui::IsMouseDoubleClicked(int button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseDoubleClicked[button];
+}
+
+bool ImGui::IsMouseDragging(int button, float lock_threshold)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ if (!g.IO.MouseDown[button])
+ return false;
+ if (lock_threshold < 0.0f)
+ lock_threshold = g.IO.MouseDragThreshold;
+ return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
+}
+
+ImVec2 ImGui::GetMousePos()
+{
+ return GImGui->IO.MousePos;
+}
+
+// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
+ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.BeginPopupStack.Size > 0)
+ return g.OpenPopupStack[g.BeginPopupStack.Size-1].OpenMousePos;
+ return g.IO.MousePos;
+}
+
+// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position
+bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
+{
+ if (mouse_pos == NULL)
+ mouse_pos = &GImGui->IO.MousePos;
+ const float MOUSE_INVALID = -256000.0f;
+ return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID;
+}
+
+// Return the delta from the initial clicking position.
+// This is locked and return 0.0f until the mouse moves past a distance threshold at least once.
+// NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window.
+ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ if (lock_threshold < 0.0f)
+ lock_threshold = g.IO.MouseDragThreshold;
+ if (g.IO.MouseDown[button])
+ if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
+ return g.IO.MousePos - g.IO.MouseClickedPos[button]; // Assume we can only get active with left-mouse button (at the moment).
+ return ImVec2(0.0f, 0.0f);
+}
+
+void ImGui::ResetMouseDragDelta(int button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
+ g.IO.MouseClickedPos[button] = g.IO.MousePos;
+}
+
+ImGuiMouseCursor ImGui::GetMouseCursor()
+{
+ return GImGui->MouseCursor;
+}
+
+void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
+{
+ GImGui->MouseCursor = cursor_type;
+}
+
+void ImGui::CaptureKeyboardFromApp(bool capture)
+{
+ GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0;
+}
+
+void ImGui::CaptureMouseFromApp(bool capture)
+{
+ GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0;
+}
+
+bool ImGui::IsItemActive()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId)
+ {
+ ImGuiWindow* window = g.CurrentWindow;
+ return g.ActiveId == window->DC.LastItemId;
+ }
+ return false;
+}
+
+bool ImGui::IsItemDeactivated()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
+}
+
+bool ImGui::IsItemDeactivatedAfterEdit()
+{
+ ImGuiContext& g = *GImGui;
+ return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEdited || (g.ActiveId == 0 && g.ActiveIdHasBeenEdited));
+}
+
+bool ImGui::IsItemFocused()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ return g.NavId && !g.NavDisableHighlight && g.NavId == window->DC.LastItemId;
+}
+
+bool ImGui::IsItemClicked(int mouse_button)
+{
+ return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
+}
+
+bool ImGui::IsAnyItemHovered()
+{
+ ImGuiContext& g = *GImGui;
+ return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0;
+}
+
+bool ImGui::IsAnyItemActive()
+{
+ ImGuiContext& g = *GImGui;
+ return g.ActiveId != 0;
+}
+
+bool ImGui::IsAnyItemFocused()
+{
+ ImGuiContext& g = *GImGui;
+ return g.NavId != 0 && !g.NavDisableHighlight;
+}
+
+bool ImGui::IsItemVisible()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->ClipRect.Overlaps(window->DC.LastItemRect);
+}
+
+bool ImGui::IsItemEdited()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0;
+}
+
+// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
+void ImGui::SetItemAllowOverlap()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.HoveredId == g.CurrentWindow->DC.LastItemId)
+ g.HoveredIdAllowOverlap = true;
+ if (g.ActiveId == g.CurrentWindow->DC.LastItemId)
+ g.ActiveIdAllowOverlap = true;
+}
+
+ImVec2 ImGui::GetItemRectMin()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.LastItemRect.Min;
+}
+
+ImVec2 ImGui::GetItemRectMax()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.LastItemRect.Max;
+}
+
+ImVec2 ImGui::GetItemRectSize()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.LastItemRect.GetSize();
+}
+
+static ImRect GetViewportRect()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
+ return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax);
+ return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
+}
+
+static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* parent_window = g.CurrentWindow;
+
+ flags |= ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow;
+ flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
+
+ // Size
+ const ImVec2 content_avail = GetContentRegionAvail();
+ ImVec2 size = ImFloor(size_arg);
+ const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
+ if (size.x <= 0.0f)
+ size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues)
+ if (size.y <= 0.0f)
+ size.y = ImMax(content_avail.y + size.y, 4.0f);
+ SetNextWindowSize(size);
+
+ // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
+ char title[256];
+ if (name)
+ ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s_%08X", parent_window->Name, name, id);
+ else
+ ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id);
+
+ const float backup_border_size = g.Style.ChildBorderSize;
+ if (!border)
+ g.Style.ChildBorderSize = 0.0f;
+ bool ret = Begin(title, NULL, flags);
+ g.Style.ChildBorderSize = backup_border_size;
+
+ ImGuiWindow* child_window = g.CurrentWindow;
+ child_window->ChildId = id;
+ child_window->AutoFitChildAxises = auto_fit_axises;
+
+ // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
+ // While this is not really documented/defined, it seems that the expected thing to do.
+ parent_window->DC.CursorPos = child_window->Pos;
+
+ // Process navigation-in immediately so NavInit can run on first frame
+ if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll))
+ {
+ FocusWindow(child_window);
+ NavInitWindow(child_window, false);
+ SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item
+ g.ActiveIdSource = ImGuiInputSource_Nav;
+ }
+ return ret;
+}
+
+bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
+}
+
+bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
+{
+ IM_ASSERT(id != 0);
+ return BeginChildEx(NULL, id, size_arg, border, extra_flags);
+}
+
+void ImGui::EndChild()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss
+ if (window->BeginCount > 1)
+ {
+ End();
+ }
+ else
+ {
+ ImVec2 sz = window->Size;
+ if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
+ sz.x = ImMax(4.0f, sz.x);
+ if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
+ sz.y = ImMax(4.0f, sz.y);
+ End();
+
+ ImGuiWindow* parent_window = g.CurrentWindow;
+ ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
+ ItemSize(sz);
+ if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
+ {
+ ItemAdd(bb, window->ChildId);
+ RenderNavHighlight(bb, window->ChildId);
+
+ // When browsing a window that has no activable items (scroll only) we keep a highlight on the child
+ if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow)
+ RenderNavHighlight(ImRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
+ }
+ else
+ {
+ // Not navigable into
+ ItemAdd(bb, 0);
+ }
+ }
+}
+
+// Helper to create a child window / scrolling region that looks like a normal widget frame.
+bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
+ PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
+ PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
+ PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
+ bool ret = BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);
+ PopStyleVar(3);
+ PopStyleColor();
+ return ret;
+}
+
+void ImGui::EndChildFrame()
+{
+ EndChild();
+}
+
+// Save and compare stack sizes on Begin()/End() to detect usage errors
+static void CheckStacksSize(ImGuiWindow* window, bool write)
+{
+ // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
+ ImGuiContext& g = *GImGui;
+ short* p_backup = &window->DC.StackSizesBackup[0];
+ { int current = window->IDStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop()
+ { int current = window->DC.GroupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup()
+ { int current = g.BeginPopupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginMenu/EndMenu or BeginPopup/EndPopup Mismatch"); p_backup++;}// Too few or too many EndMenu()/EndPopup()
+ // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
+ { int current = g.ColorModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleColor/PopStyleColor Mismatch!"); p_backup++; } // Too few or too many PopStyleColor()
+ { int current = g.StyleModifiers.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushStyleVar/PopStyleVar Mismatch!"); p_backup++; } // Too few or too many PopStyleVar()
+ { int current = g.FontStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup >= current && "PushFont/PopFont Mismatch!"); p_backup++; } // Too few or too many PopFont()
+ IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
+}
+
+static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
+{
+ window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
+ window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
+ window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
+}
+
+ImGuiWindow* ImGui::FindWindowByID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id);
+}
+
+ImGuiWindow* ImGui::FindWindowByName(const char* name)
+{
+ ImGuiID id = ImHash(name, 0);
+ return FindWindowByID(id);
+}
+
+static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Create window the first time
+ ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
+ window->Flags = flags;
+ g.WindowsById.SetVoidPtr(window->ID, window);
+
+ // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
+ window->Pos = ImVec2(60, 60);
+
+ // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
+ if (!(flags & ImGuiWindowFlags_NoSavedSettings))
+ if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
+ {
+ // Retrieve settings from .ini file
+ window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
+ SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
+ window->Pos = ImFloor(settings->Pos);
+ window->Collapsed = settings->Collapsed;
+ if (ImLengthSqr(settings->Size) > 0.00001f)
+ size = ImFloor(settings->Size);
+ }
+ window->Size = window->SizeFull = window->SizeFullAtLastBegin = ImFloor(size);
+ window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values
+
+ if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
+ {
+ window->AutoFitFramesX = window->AutoFitFramesY = 2;
+ window->AutoFitOnlyGrows = false;
+ }
+ else
+ {
+ if (window->Size.x <= 0.0f)
+ window->AutoFitFramesX = 2;
+ if (window->Size.y <= 0.0f)
+ window->AutoFitFramesY = 2;
+ window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
+ }
+
+ g.WindowsFocusOrder.push_back(window);
+ if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
+ g.Windows.push_front(window); // Quite slow but rare and only once
+ else
+ g.Windows.push_back(window);
+ return window;
+}
+
+static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.NextWindowData.SizeConstraintCond != 0)
+ {
+ // Using -1,-1 on either X/Y axis to preserve the current size.
+ ImRect cr = g.NextWindowData.SizeConstraintRect;
+ new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
+ new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
+ if (g.NextWindowData.SizeCallback)
+ {
+ ImGuiSizeCallbackData data;
+ data.UserData = g.NextWindowData.SizeCallbackUserData;
+ data.Pos = window->Pos;
+ data.CurrentSize = window->SizeFull;
+ data.DesiredSize = new_size;
+ g.NextWindowData.SizeCallback(&data);
+ new_size = data.DesiredSize;
+ }
+ }
+
+ // Minimum size
+ if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
+ {
+ new_size = ImMax(new_size, g.Style.WindowMinSize);
+ new_size.y = ImMax(new_size.y, window->TitleBarHeight() + window->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows
+ }
+ return new_size;
+}
+
+static ImVec2 CalcSizeContents(ImGuiWindow* window)
+{
+ if (window->Collapsed)
+ return window->SizeContents;
+ if (window->Hidden && window->HiddenFramesForResize == 0 && window->HiddenFramesRegular > 0)
+ return window->SizeContents;
+
+ ImVec2 sz;
+ sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x));
+ sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y));
+ return sz + window->WindowPadding;
+}
+
+static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ if (window->Flags & ImGuiWindowFlags_Tooltip)
+ {
+ // Tooltip always resize
+ return size_contents;
+ }
+ else
+ {
+ // When the window cannot fit all contents (either because of constraints, either because screen is too small): we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than DisplaySize-WindowPadding.
+ const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0;
+ const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0;
+ ImVec2 size_min = style.WindowMinSize;
+ if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups)
+ size_min = ImMin(size_min, ImVec2(4.0f, 4.0f));
+ ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f));
+ ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit);
+ if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar))
+ size_auto_fit.y += style.ScrollbarSize;
+ if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
+ size_auto_fit.x += style.ScrollbarSize;
+ return size_auto_fit;
+ }
+}
+
+ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window)
+{
+ ImVec2 size_contents = CalcSizeContents(window);
+ return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents));
+}
+
+float ImGui::GetWindowScrollMaxX(ImGuiWindow* window)
+{
+ return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));
+}
+
+float ImGui::GetWindowScrollMaxY(ImGuiWindow* window)
+{
+ return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));
+}
+
+static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 scroll = window->Scroll;
+ if (window->ScrollTarget.x < FLT_MAX)
+ {
+ float cr_x = window->ScrollTargetCenterRatio.x;
+ scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);
+ }
+ if (window->ScrollTarget.y < FLT_MAX)
+ {
+ // 'snap_on_edges' allows for a discontinuity at the edge of scrolling limits to take account of WindowPadding so that scrolling to make the last item visible scroll far enough to see the padding.
+ float cr_y = window->ScrollTargetCenterRatio.y;
+ float target_y = window->ScrollTarget.y;
+ if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y)
+ target_y = 0.0f;
+ if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y - window->WindowPadding.y + g.Style.ItemSpacing.y)
+ target_y = window->SizeContents.y;
+ scroll.y = target_y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y);
+ }
+ scroll = ImMax(scroll, ImVec2(0.0f, 0.0f));
+ if (!window->Collapsed && !window->SkipItems)
+ {
+ scroll.x = ImMin(scroll.x, ImGui::GetWindowScrollMaxX(window));
+ scroll.y = ImMin(scroll.y, ImGui::GetWindowScrollMaxY(window));
+ }
+ return scroll;
+}
+
+static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags)
+{
+ if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
+ return ImGuiCol_PopupBg;
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ return ImGuiCol_ChildBg;
+ return ImGuiCol_WindowBg;
+}
+
+static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
+{
+ ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left
+ ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right
+ ImVec2 size_expected = pos_max - pos_min;
+ ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected);
+ *out_pos = pos_min;
+ if (corner_norm.x == 0.0f)
+ out_pos->x -= (size_constrained.x - size_expected.x);
+ if (corner_norm.y == 0.0f)
+ out_pos->y -= (size_constrained.y - size_expected.y);
+ *out_size = size_constrained;
+}
+
+struct ImGuiResizeGripDef
+{
+ ImVec2 CornerPos;
+ ImVec2 InnerDir;
+ int AngleMin12, AngleMax12;
+};
+
+const ImGuiResizeGripDef resize_grip_def[4] =
+{
+ { ImVec2(1,1), ImVec2(-1,-1), 0, 3 }, // Lower right
+ { ImVec2(0,1), ImVec2(+1,-1), 3, 6 }, // Lower left
+ { ImVec2(0,0), ImVec2(+1,+1), 6, 9 }, // Upper left
+ { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper right
+};
+
+static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
+{
+ ImRect rect = window->Rect();
+ if (thickness == 0.0f) rect.Max -= ImVec2(1,1);
+ if (border_n == 0) return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness);
+ if (border_n == 1) return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding);
+ if (border_n == 2) return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness);
+ if (border_n == 3) return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding);
+ IM_ASSERT(0);
+ return ImRect();
+}
+
+// Handle resize for: Resize Grips, Borders, Gamepad
+static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindowFlags flags = window->Flags;
+ if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
+ return;
+ if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window.
+ return;
+
+ const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0;
+ const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
+ const float grip_hover_inner_size = (float)(int)(grip_draw_size * 0.75f);
+ const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS : 0.0f;
+
+ ImVec2 pos_target(FLT_MAX, FLT_MAX);
+ ImVec2 size_target(FLT_MAX, FLT_MAX);
+
+ // Manual resize grips
+ PushID("#RESIZE");
+ for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
+ {
+ const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
+ const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos);
+
+ // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
+ ImRect resize_rect(corner - grip.InnerDir * grip_hover_outer_size, corner + grip.InnerDir * grip_hover_inner_size);
+ if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
+ if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
+ bool hovered, held;
+ ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
+ //GetOverlayDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
+ if (hovered || held)
+ g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
+
+ if (held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0)
+ {
+ // Manual auto-fit when double-clicking
+ size_target = CalcSizeAfterConstraint(window, size_auto_fit);
+ ClearActiveID();
+ }
+ else if (held)
+ {
+ // Resize from any of the four corners
+ // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
+ ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(grip.InnerDir * grip_hover_outer_size, grip.InnerDir * -grip_hover_inner_size, grip.CornerPos); // Corner of the window corresponding to our corner grip
+ CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target);
+ }
+ if (resize_grip_n == 0 || held || hovered)
+ resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
+ }
+ for (int border_n = 0; border_n < resize_border_count; border_n++)
+ {
+ bool hovered, held;
+ ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS);
+ ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
+ //GetOverlayDrawList(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
+ if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held)
+ {
+ g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
+ if (held) *border_held = border_n;
+ }
+ if (held)
+ {
+ ImVec2 border_target = window->Pos;
+ ImVec2 border_posn;
+ if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
+ if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
+ if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
+ if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS); }
+ CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
+ }
+ }
+ PopID();
+
+ // Navigation resize (keyboard/gamepad)
+ if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
+ {
+ ImVec2 nav_resize_delta;
+ if (g.NavInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift)
+ nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
+ if (g.NavInputSource == ImGuiInputSource_NavGamepad)
+ nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down);
+ if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
+ {
+ const float NAV_RESIZE_SPEED = 600.0f;
+ nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
+ g.NavWindowingToggleLayer = false;
+ g.NavDisableMouseHover = true;
+ resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
+ // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
+ size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta);
+ }
+ }
+
+ // Apply back modified position/size to window
+ if (size_target.x != FLT_MAX)
+ {
+ window->SizeFull = size_target;
+ MarkIniSettingsDirty(window);
+ }
+ if (pos_target.x != FLT_MAX)
+ {
+ window->Pos = ImFloor(pos_target);
+ MarkIniSettingsDirty(window);
+ }
+
+ window->Size = window->SizeFull;
+}
+
+void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
+{
+ window->ParentWindow = parent_window;
+ window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
+ if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
+ window->RootWindow = parent_window->RootWindow;
+ if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
+ window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
+ while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened)
+ window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
+}
+
+// Push a new ImGui window to add widgets to.
+// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
+// - Begin/End can be called multiple times during the frame with the same window name to append content.
+// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
+// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file.
+// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned.
+// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed.
+bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ IM_ASSERT(name != NULL && name[0] != '\0'); // Window name required
+ IM_ASSERT(g.FrameScopeActive); // Forgot to call ImGui::NewFrame()
+ IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
+
+ // Find or create
+ ImGuiWindow* window = FindWindowByName(name);
+ const bool window_just_created = (window == NULL);
+ if (window_just_created)
+ {
+ ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
+ window = CreateNewWindow(name, size_on_first_use, flags);
+ }
+
+ // Automatically disable manual moving/resizing when NoInputs is set
+ if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
+ flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
+
+ if (flags & ImGuiWindowFlags_NavFlattened)
+ IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow);
+
+ const int current_frame = g.FrameCount;
+ const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
+
+ // Update Flags, LastFrameActive, BeginOrderXXX fields
+ if (first_begin_of_the_frame)
+ window->Flags = (ImGuiWindowFlags)flags;
+ else
+ flags = window->Flags;
+
+ // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
+ ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back();
+ ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
+ IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
+ window->HasCloseButton = (p_open != NULL);
+
+ // Update the Appearing flag
+ bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
+ const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0);
+ if (flags & ImGuiWindowFlags_Popup)
+ {
+ ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
+ window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed
+ window_just_activated_by_user |= (window != popup_ref.Window);
+ }
+ window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize);
+ if (window->Appearing)
+ SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true);
+
+ // Add to stack
+ g.CurrentWindowStack.push_back(window);
+ SetCurrentWindow(window);
+ CheckStacksSize(window, true);
+ if (flags & ImGuiWindowFlags_Popup)
+ {
+ ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
+ popup_ref.Window = window;
+ g.BeginPopupStack.push_back(popup_ref);
+ window->PopupId = popup_ref.PopupId;
+ }
+
+ if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow))
+ window->NavLastIds[0] = 0;
+
+ // Process SetNextWindow***() calls
+ bool window_pos_set_by_api = false;
+ bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
+ if (g.NextWindowData.PosCond)
+ {
+ window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
+ if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
+ {
+ // May be processed on the next frame if this is our first frame and we are measuring size
+ // FIXME: Look into removing the branch so everything can go through this same code path for consistency.
+ window->SetWindowPosVal = g.NextWindowData.PosVal;
+ window->SetWindowPosPivot = g.NextWindowData.PosPivotVal;
+ window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+ }
+ else
+ {
+ SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
+ }
+ }
+ if (g.NextWindowData.SizeCond)
+ {
+ window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
+ window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
+ SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
+ }
+ if (g.NextWindowData.ContentSizeCond)
+ {
+ // Adjust passed "client size" to become a "window size"
+ window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal;
+ if (window->SizeContentsExplicit.y != 0.0f)
+ window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight();
+ }
+ else if (first_begin_of_the_frame)
+ {
+ window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
+ }
+ if (g.NextWindowData.CollapsedCond)
+ SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
+ if (g.NextWindowData.FocusCond)
+ FocusWindow(window);
+ if (window->Appearing)
+ SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
+
+ // When reusing window again multiple times a frame, just append content (don't need to setup again)
+ if (first_begin_of_the_frame)
+ {
+ // Initialize
+ const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
+ UpdateWindowParentAndRootLinks(window, flags, parent_window);
+
+ window->Active = true;
+ window->BeginOrderWithinParent = 0;
+ window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++);
+ window->BeginCount = 0;
+ window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
+ window->LastFrameActive = current_frame;
+ window->IDStack.resize(1);
+
+ // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged).
+ // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere.
+ bool window_title_visible_elsewhere = false;
+ if (g.NavWindowingList != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB
+ window_title_visible_elsewhere = true;
+ if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
+ {
+ size_t buf_len = (size_t)window->NameBufLen;
+ window->Name = ImStrdupcpy(window->Name, &buf_len, name);
+ window->NameBufLen = (int)buf_len;
+ }
+
+ // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
+
+ // Update contents size from last frame for auto-fitting (or use explicit size)
+ window->SizeContents = CalcSizeContents(window);
+ if (window->HiddenFramesRegular > 0)
+ window->HiddenFramesRegular--;
+ if (window->HiddenFramesForResize > 0)
+ window->HiddenFramesForResize--;
+
+ // Hide new windows for one frame until they calculate their size
+ if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
+ window->HiddenFramesForResize = 1;
+
+ // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
+ // We reset Size/SizeContents for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
+ if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
+ {
+ window->HiddenFramesForResize = 1;
+ if (flags & ImGuiWindowFlags_AlwaysAutoResize)
+ {
+ if (!window_size_x_set_by_api)
+ window->Size.x = window->SizeFull.x = 0.f;
+ if (!window_size_y_set_by_api)
+ window->Size.y = window->SizeFull.y = 0.f;
+ window->SizeContents = ImVec2(0.f, 0.f);
+ }
+ }
+
+ SetCurrentWindow(window);
+
+ // Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies)
+ window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
+ window->WindowPadding = style.WindowPadding;
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
+ window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
+ window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
+ window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
+
+ // Collapse window by double-clicking on title bar
+ // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
+ if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
+ {
+ // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar.
+ ImRect title_bar_rect = window->TitleBarRect();
+ if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])
+ window->WantCollapseToggle = true;
+ if (window->WantCollapseToggle)
+ {
+ window->Collapsed = !window->Collapsed;
+ MarkIniSettingsDirty(window);
+ FocusWindow(window);
+ }
+ }
+ else
+ {
+ window->Collapsed = false;
+ }
+ window->WantCollapseToggle = false;
+
+ // SIZE
+
+ // Calculate auto-fit size, handle automatic resize
+ const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
+ ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
+ if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
+ {
+ // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
+ if (!window_size_x_set_by_api)
+ window->SizeFull.x = size_full_modified.x = size_auto_fit.x;
+ if (!window_size_y_set_by_api)
+ window->SizeFull.y = size_full_modified.y = size_auto_fit.y;
+ }
+ else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
+ {
+ // Auto-fit may only grow window during the first few frames
+ // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
+ if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
+ window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
+ if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
+ window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
+ if (!window->Collapsed)
+ MarkIniSettingsDirty(window);
+ }
+
+ // Apply minimum/maximum window size constraints and final size
+ window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull);
+ window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
+
+ // SCROLLBAR STATUS
+
+ // Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size).
+ if (!window->Collapsed)
+ {
+ // When reading the current size we need to read it after size constraints have been applied
+ float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x;
+ float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y;
+ window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
+ window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
+ if (window->ScrollbarX && !window->ScrollbarY)
+ window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
+ window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
+ }
+
+ // POSITION
+
+ // Popup latch its initial position, will position itself when it appears next frame
+ if (window_just_activated_by_user)
+ {
+ window->AutoPosLastDirection = ImGuiDir_None;
+ if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api)
+ window->Pos = g.BeginPopupStack.back().OpenPopupPos;
+ }
+
+ // Position child window
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ {
+ IM_ASSERT(parent_window->Active);
+ window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
+ parent_window->DC.ChildWindows.push_back(window);
+ if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
+ window->Pos = parent_window->DC.CursorPos;
+ }
+
+ const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesForResize == 0);
+ if (window_pos_with_pivot)
+ SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering)
+ else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
+ window->Pos = FindBestWindowPosForPopup(window);
+ else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
+ window->Pos = FindBestWindowPosForPopup(window);
+ else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
+ window->Pos = FindBestWindowPosForPopup(window);
+
+ // Clamp position so it stays visible
+ if (!(flags & ImGuiWindowFlags_ChildWindow))
+ {
+ if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
+ {
+ ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
+ ImVec2 size_for_clamping = ((g.IO.ConfigWindowsMoveFromTitleBarOnly) && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size;
+ window->Pos = ImMax(window->Pos + size_for_clamping, padding) - size_for_clamping;
+ window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding);
+ }
+ }
+ window->Pos = ImFloor(window->Pos);
+
+ // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
+ window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
+
+ // Prepare for item focus requests
+ window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
+ window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
+ window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
+ window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
+
+ // Apply scrolling
+ window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
+ window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
+
+ // Apply window focus (new and reactivated windows are moved to front)
+ bool want_focus = false;
+ if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
+ if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup))
+ want_focus = true;
+
+ // Handle manual resize: Resize Grips, Borders, Gamepad
+ int border_held = -1;
+ ImU32 resize_grip_col[4] = { 0 };
+ const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4
+ const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
+ if (!window->Collapsed)
+ UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
+
+ // Default item width. Make it proportional to window size if window manually resizes
+ if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
+ window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
+ else
+ window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);
+
+ // DRAWING
+
+ // Setup draw list and outer clipping rectangle
+ window->DrawList->Clear();
+ window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
+ window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
+ ImRect viewport_rect(GetViewportRect());
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
+ PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true);
+ else
+ PushClipRect(viewport_rect.Min, viewport_rect.Max, true);
+
+ // Draw modal window background (darkens what is behind them, all viewports)
+ const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesForResize <= 0;
+ const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow);
+ if (dim_bg_for_modal || dim_bg_for_window_list)
+ {
+ const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
+ window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col);
+ }
+
+ // Draw navigation selection/windowing rectangle background
+ if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim)
+ {
+ ImRect bb = window->Rect();
+ bb.Expand(g.FontSize);
+ if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway
+ window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding);
+ }
+
+ // Draw window + handle manual resize
+ const float window_rounding = window->WindowRounding;
+ const float window_border_size = window->WindowBorderSize;
+ const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
+ const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
+ const ImRect title_bar_rect = window->TitleBarRect();
+ if (window->Collapsed)
+ {
+ // Title bar only
+ float backup_border_size = style.FrameBorderSize;
+ g.Style.FrameBorderSize = window->WindowBorderSize;
+ ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
+ RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
+ g.Style.FrameBorderSize = backup_border_size;
+ }
+ else
+ {
+ // Window background
+ if (!(flags & ImGuiWindowFlags_NoBackground))
+ {
+ ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
+ if (g.NextWindowData.BgAlphaCond != 0)
+ bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(g.NextWindowData.BgAlphaVal) << IM_COL32_A_SHIFT);
+ window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
+ }
+ g.NextWindowData.BgAlphaCond = 0;
+
+ // Title bar
+ if (!(flags & ImGuiWindowFlags_NoTitleBar))
+ {
+ ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
+ window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
+ }
+
+ // Menu bar
+ if (flags & ImGuiWindowFlags_MenuBar)
+ {
+ ImRect menu_bar_rect = window->MenuBarRect();
+ menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
+ window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
+ if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
+ window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
+ }
+
+ // Scrollbars
+ if (window->ScrollbarX)
+ Scrollbar(ImGuiLayoutType_Horizontal);
+ if (window->ScrollbarY)
+ Scrollbar(ImGuiLayoutType_Vertical);
+
+ // Render resize grips (after their input handling so we don't have a frame of latency)
+ if (!(flags & ImGuiWindowFlags_NoResize))
+ {
+ for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
+ {
+ const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
+ const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos);
+ window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size)));
+ window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size)));
+ window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
+ window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
+ }
+ }
+
+ // Borders
+ if (window_border_size > 0.0f && !(flags & ImGuiWindowFlags_NoBackground))
+ window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), window_rounding, ImDrawCornerFlags_All, window_border_size);
+ if (border_held != -1)
+ {
+ ImRect border = GetResizeBorderRect(window, border_held, grip_draw_size, 0.0f);
+ window->DrawList->AddLine(border.Min, border.Max, GetColorU32(ImGuiCol_SeparatorActive), ImMax(1.0f, window_border_size));
+ }
+ if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar))
+ window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(style.WindowBorderSize, -1), title_bar_rect.GetBR() + ImVec2(-style.WindowBorderSize, -1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
+ }
+
+ // Draw navigation selection/windowing rectangle border
+ if (g.NavWindowingTargetAnim == window)
+ {
+ float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
+ ImRect bb = window->Rect();
+ bb.Expand(g.FontSize);
+ if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward
+ {
+ bb.Expand(-g.FontSize - 1.0f);
+ rounding = window->WindowRounding;
+ }
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f);
+ }
+
+ // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars.
+ window->SizeFullAtLastBegin = window->SizeFull;
+
+ // Update various regions. Variables they depends on are set above in this function.
+ // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
+ window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
+ window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
+ window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x));
+ window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y));
+
+ // Setup drawing context
+ // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.)
+ window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
+ window->DC.GroupOffset.x = 0.0f;
+ window->DC.ColumnsOffset.x = 0.0f;
+ window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y);
+ window->DC.CursorPos = window->DC.CursorStartPos;
+ window->DC.CursorPosPrevLine = window->DC.CursorPos;
+ window->DC.CursorMaxPos = window->DC.CursorStartPos;
+ window->DC.CurrentLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
+ window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
+ window->DC.NavHideHighlightOneFrame = false;
+ window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
+ window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
+ window->DC.NavLayerActiveMaskNext = 0x00;
+ window->DC.MenuBarAppending = false;
+ window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
+ window->DC.ChildWindows.resize(0);
+ window->DC.LayoutType = ImGuiLayoutType_Vertical;
+ window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
+ window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
+ window->DC.ItemWidth = window->ItemWidthDefault;
+ window->DC.TextWrapPos = -1.0f; // disabled
+ window->DC.ItemFlagsStack.resize(0);
+ window->DC.ItemWidthStack.resize(0);
+ window->DC.TextWrapPosStack.resize(0);
+ window->DC.ColumnsSet = NULL;
+ window->DC.TreeDepth = 0;
+ window->DC.TreeDepthMayJumpToParentOnPop = 0x00;
+ window->DC.StateStorage = &window->StateStorage;
+ window->DC.GroupStack.resize(0);
+ window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);
+
+ if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags))
+ {
+ window->DC.ItemFlags = parent_window->DC.ItemFlags;
+ window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
+ }
+
+ if (window->AutoFitFramesX > 0)
+ window->AutoFitFramesX--;
+ if (window->AutoFitFramesY > 0)
+ window->AutoFitFramesY--;
+
+ // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)
+ if (want_focus)
+ {
+ FocusWindow(window);
+ NavInitWindow(window, false);
+ }
+
+ // Title bar
+ if (!(flags & ImGuiWindowFlags_NoTitleBar))
+ {
+ // Close & collapse button are on layer 1 (same as menus) and don't default focus
+ const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
+ window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
+ window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
+
+ // Collapse button
+ if (!(flags & ImGuiWindowFlags_NoCollapse))
+ if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos))
+ window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
+
+ // Close button
+ if (p_open != NULL)
+ {
+ const float pad = style.FramePadding.y;
+ const float rad = g.FontSize * 0.5f;
+ if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1))
+ *p_open = false;
+ }
+
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+ window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
+ window->DC.ItemFlags = item_flags_backup;
+
+ // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
+ // FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
+ const char* UNSAVED_DOCUMENT_MARKER = "*";
+ float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
+ ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
+ ImRect text_r = title_bar_rect;
+ float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
+ float pad_right = (p_open == NULL) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
+ if (style.WindowTitleAlign.x > 0.0f)
+ pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
+ text_r.Min.x += pad_left;
+ text_r.Max.x -= pad_right;
+ ImRect clip_rect = text_r;
+ clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
+ RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
+ if (flags & ImGuiWindowFlags_UnsavedDocument)
+ {
+ ImVec2 marker_pos = ImVec2(ImMax(text_r.Min.x, text_r.Min.x + (text_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, text_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
+ ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
+ RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
+ }
+ }
+
+ // Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
+ window->OuterRectClipped = window->Rect();
+ window->OuterRectClipped.ClipWith(window->ClipRect);
+
+ // Pressing CTRL+C while holding on a window copy its content to the clipboard
+ // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.
+ // Maybe we can support CTRL+C on every element?
+ /*
+ if (g.ActiveId == move_id)
+ if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
+ LogToClipboard();
+ */
+
+ // Inner rectangle
+ // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
+ // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
+ window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
+ window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
+ window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - window->WindowBorderSize;
+ window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize;
+ //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE);
+
+ // Inner clipping rectangle
+ // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
+ window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
+ window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
+ window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
+ window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
+
+ // After Begin() we fill the last item / hovered data based on title bar data. It is a standard behavior (to allow creation of context menus on title bar only, etc.).
+ window->DC.LastItemId = window->MoveId;
+ window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
+ window->DC.LastItemRect = title_bar_rect;
+ }
+
+ PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
+
+ // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
+ if (first_begin_of_the_frame)
+ window->WriteAccessed = false;
+
+ window->BeginCount++;
+ g.NextWindowData.Clear();
+
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ {
+ // Child window can be out of sight and have "negative" clip windows.
+ // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar).
+ IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0);
+
+ if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
+ if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
+ window->HiddenFramesRegular = 1;
+
+ // Completely hide along with parent or if parent is collapsed
+ if (parent_window && (parent_window->Collapsed || parent_window->Hidden))
+ window->HiddenFramesRegular = 1;
+ }
+
+ // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point)
+ if (style.Alpha <= 0.0f)
+ window->HiddenFramesRegular = 1;
+
+ // Update the Hidden flag
+ window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize > 0);
+
+ // Return false if we don't intend to display anything to allow user to perform an early out optimization
+ window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0;
+
+ return !window->SkipItems;
+}
+
+// Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()/SetNextWindowBgAlpha() + Begin() instead.
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, float bg_alpha_override, ImGuiWindowFlags flags)
+{
+ // Old API feature: we could pass the initial window size as a parameter. This was misleading because it only had an effect if the window didn't have data in the .ini file.
+ if (size_first_use.x != 0.0f || size_first_use.y != 0.0f)
+ SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver);
+
+ // Old API feature: override the window background alpha with a parameter.
+ if (bg_alpha_override >= 0.0f)
+ SetNextWindowBgAlpha(bg_alpha_override);
+
+ return Begin(name, p_open, flags);
+}
+#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+void ImGui::End()
+{
+ ImGuiContext& g = *GImGui;
+
+ if (g.CurrentWindowStack.Size <= 1 && g.FrameScopePushedImplicitWindow)
+ {
+ IM_ASSERT(g.CurrentWindowStack.Size > 1 && "Calling End() too many times!");
+ return; // FIXME-ERRORHANDLING
+ }
+ IM_ASSERT(g.CurrentWindowStack.Size > 0);
+
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (window->DC.ColumnsSet != NULL)
+ EndColumns();
+ PopClipRect(); // Inner window clip rectangle
+
+ // Stop logging
+ if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
+ LogFinish();
+
+ // Pop from window stack
+ g.CurrentWindowStack.pop_back();
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ g.BeginPopupStack.pop_back();
+ CheckStacksSize(window, false);
+ SetCurrentWindow(g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back());
+}
+
+void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.WindowsFocusOrder.back() == window)
+ return;
+ for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the front most window
+ if (g.WindowsFocusOrder[i] == window)
+ {
+ memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*));
+ g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window;
+ break;
+ }
+}
+
+void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* current_front_window = g.Windows.back();
+ if (current_front_window == window || current_front_window->RootWindow == window)
+ return;
+ for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window
+ if (g.Windows[i] == window)
+ {
+ memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*));
+ g.Windows[g.Windows.Size - 1] = window;
+ break;
+ }
+}
+
+void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.Windows[0] == window)
+ return;
+ for (int i = 0; i < g.Windows.Size; i++)
+ if (g.Windows[i] == window)
+ {
+ memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*));
+ g.Windows[0] = window;
+ break;
+ }
+}
+
+// Moving window to front of display and set focus (which happens to be back of our sorted list)
+void ImGui::FocusWindow(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+
+ if (g.NavWindow != window)
+ {
+ g.NavWindow = window;
+ if (window && g.NavDisableMouseHover)
+ g.NavMousePosDirty = true;
+ g.NavInitRequest = false;
+ g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
+ g.NavIdIsAlive = false;
+ g.NavLayer = ImGuiNavLayer_Main;
+ //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", g.FrameCount, window ? window->Name : NULL);
+ }
+
+ // Passing NULL allow to disable keyboard focus
+ if (!window)
+ return;
+
+ // Move the root window to the top of the pile
+ if (window->RootWindow)
+ window = window->RootWindow;
+
+ // Steal focus on active widgets
+ if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..
+ if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
+ ClearActiveID();
+
+ // Bring to front
+ BringWindowToFocusFront(window);
+ if (!(window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus))
+ BringWindowToDisplayFront(window);
+}
+
+void ImGui::FocusPreviousWindowIgnoringOne(ImGuiWindow* ignore_window)
+{
+ ImGuiContext& g = *GImGui;
+ for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--)
+ {
+ // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
+ ImGuiWindow* window = g.WindowsFocusOrder[i];
+ if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow))
+ if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
+ {
+ ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
+ FocusWindow(focus_window);
+ return;
+ }
+ }
+}
+
+void ImGui::PushItemWidth(float item_width)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
+ window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
+}
+
+void ImGui::PushMultiItemsWidths(int components, float w_full)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ const ImGuiStyle& style = GImGui->Style;
+ if (w_full <= 0.0f)
+ w_full = CalcItemWidth();
+ const float w_item_one = ImMax(1.0f, (float)(int)((w_full - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
+ const float w_item_last = ImMax(1.0f, (float)(int)(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
+ window->DC.ItemWidthStack.push_back(w_item_last);
+ for (int i = 0; i < components-1; i++)
+ window->DC.ItemWidthStack.push_back(w_item_one);
+ window->DC.ItemWidth = window->DC.ItemWidthStack.back();
+}
+
+void ImGui::PopItemWidth()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.ItemWidthStack.pop_back();
+ window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
+}
+
+float ImGui::CalcItemWidth()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ float w = window->DC.ItemWidth;
+ if (w < 0.0f)
+ {
+ // Align to a right-side limit. We include 1 frame padding in the calculation because this is how the width is always used (we add 2 frame padding to it), but we could move that responsibility to the widget as well.
+ float width_to_right_edge = GetContentRegionAvail().x;
+ w = ImMax(1.0f, width_to_right_edge + w);
+ }
+ w = (float)(int)w;
+ return w;
+}
+
+void ImGui::SetCurrentFont(ImFont* font)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
+ IM_ASSERT(font->Scale > 0.0f);
+ g.Font = font;
+ g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
+ g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
+
+ ImFontAtlas* atlas = g.Font->ContainerAtlas;
+ g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
+ g.DrawListSharedData.Font = g.Font;
+ g.DrawListSharedData.FontSize = g.FontSize;
+}
+
+void ImGui::PushFont(ImFont* font)
+{
+ ImGuiContext& g = *GImGui;
+ if (!font)
+ font = GetDefaultFont();
+ SetCurrentFont(font);
+ g.FontStack.push_back(font);
+ g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
+}
+
+void ImGui::PopFont()
+{
+ ImGuiContext& g = *GImGui;
+ g.CurrentWindow->DrawList->PopTextureID();
+ g.FontStack.pop_back();
+ SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back());
+}
+
+void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (enabled)
+ window->DC.ItemFlags |= option;
+ else
+ window->DC.ItemFlags &= ~option;
+ window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
+}
+
+void ImGui::PopItemFlag()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.ItemFlagsStack.pop_back();
+ window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();
+}
+
+// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
+void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)
+{
+ PushItemFlag(ImGuiItemFlags_NoTabStop, !allow_keyboard_focus);
+}
+
+void ImGui::PopAllowKeyboardFocus()
+{
+ PopItemFlag();
+}
+
+void ImGui::PushButtonRepeat(bool repeat)
+{
+ PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat);
+}
+
+void ImGui::PopButtonRepeat()
+{
+ PopItemFlag();
+}
+
+void ImGui::PushTextWrapPos(float wrap_pos_x)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.TextWrapPos = wrap_pos_x;
+ window->DC.TextWrapPosStack.push_back(wrap_pos_x);
+}
+
+void ImGui::PopTextWrapPos()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.TextWrapPosStack.pop_back();
+ window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back();
+}
+
+// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32
+void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiColorMod backup;
+ backup.Col = idx;
+ backup.BackupValue = g.Style.Colors[idx];
+ g.ColorModifiers.push_back(backup);
+ g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
+}
+
+void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiColorMod backup;
+ backup.Col = idx;
+ backup.BackupValue = g.Style.Colors[idx];
+ g.ColorModifiers.push_back(backup);
+ g.Style.Colors[idx] = col;
+}
+
+void ImGui::PopStyleColor(int count)
+{
+ ImGuiContext& g = *GImGui;
+ while (count > 0)
+ {
+ ImGuiColorMod& backup = g.ColorModifiers.back();
+ g.Style.Colors[backup.Col] = backup.BackupValue;
+ g.ColorModifiers.pop_back();
+ count--;
+ }
+}
+
+struct ImGuiStyleVarInfo
+{
+ ImGuiDataType Type;
+ ImU32 Count;
+ ImU32 Offset;
+ void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
+};
+
+static const ImGuiStyleVarInfo GStyleVarInfo[] =
+{
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
+};
+
+static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
+{
+ IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
+ IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
+ return &GStyleVarInfo[idx];
+}
+
+void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
+{
+ const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
+ if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
+ {
+ ImGuiContext& g = *GImGui;
+ float* pvar = (float*)var_info->GetVarPtr(&g.Style);
+ g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
+ *pvar = val;
+ return;
+ }
+ IM_ASSERT(0); // Called function with wrong-type? Variable is not a float.
+}
+
+void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
+{
+ const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
+ if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
+ {
+ ImGuiContext& g = *GImGui;
+ ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
+ g.StyleModifiers.push_back(ImGuiStyleMod(idx, *pvar));
+ *pvar = val;
+ return;
+ }
+ IM_ASSERT(0); // Called function with wrong-type? Variable is not a ImVec2.
+}
+
+void ImGui::PopStyleVar(int count)
+{
+ ImGuiContext& g = *GImGui;
+ while (count > 0)
+ {
+ // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
+ ImGuiStyleMod& backup = g.StyleModifiers.back();
+ const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
+ void* data = info->GetVarPtr(&g.Style);
+ if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; }
+ else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
+ g.StyleModifiers.pop_back();
+ count--;
+ }
+}
+
+const char* ImGui::GetStyleColorName(ImGuiCol idx)
+{
+ // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1";
+ switch (idx)
+ {
+ case ImGuiCol_Text: return "Text";
+ case ImGuiCol_TextDisabled: return "TextDisabled";
+ case ImGuiCol_WindowBg: return "WindowBg";
+ case ImGuiCol_ChildBg: return "ChildBg";
+ case ImGuiCol_PopupBg: return "PopupBg";
+ case ImGuiCol_Border: return "Border";
+ case ImGuiCol_BorderShadow: return "BorderShadow";
+ case ImGuiCol_FrameBg: return "FrameBg";
+ case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
+ case ImGuiCol_FrameBgActive: return "FrameBgActive";
+ case ImGuiCol_TitleBg: return "TitleBg";
+ case ImGuiCol_TitleBgActive: return "TitleBgActive";
+ case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
+ case ImGuiCol_MenuBarBg: return "MenuBarBg";
+ case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
+ case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab";
+ case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
+ case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
+ case ImGuiCol_CheckMark: return "CheckMark";
+ case ImGuiCol_SliderGrab: return "SliderGrab";
+ case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
+ case ImGuiCol_Button: return "Button";
+ case ImGuiCol_ButtonHovered: return "ButtonHovered";
+ case ImGuiCol_ButtonActive: return "ButtonActive";
+ case ImGuiCol_Header: return "Header";
+ case ImGuiCol_HeaderHovered: return "HeaderHovered";
+ case ImGuiCol_HeaderActive: return "HeaderActive";
+ case ImGuiCol_Separator: return "Separator";
+ case ImGuiCol_SeparatorHovered: return "SeparatorHovered";
+ case ImGuiCol_SeparatorActive: return "SeparatorActive";
+ case ImGuiCol_ResizeGrip: return "ResizeGrip";
+ case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
+ case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
+ case ImGuiCol_Tab: return "Tab";
+ case ImGuiCol_TabHovered: return "TabHovered";
+ case ImGuiCol_TabActive: return "TabActive";
+ case ImGuiCol_TabUnfocused: return "TabUnfocused";
+ case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive";
+ case ImGuiCol_PlotLines: return "PlotLines";
+ case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
+ case ImGuiCol_PlotHistogram: return "PlotHistogram";
+ case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
+ case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
+ case ImGuiCol_DragDropTarget: return "DragDropTarget";
+ case ImGuiCol_NavHighlight: return "NavHighlight";
+ case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
+ case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
+ case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
+ }
+ IM_ASSERT(0);
+ return "Unknown";
+}
+
+bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
+{
+ if (window->RootWindow == potential_parent)
+ return true;
+ while (window != NULL)
+ {
+ if (window == potential_parent)
+ return true;
+ window = window->ParentWindow;
+ }
+ return false;
+}
+
+bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
+{
+ IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function
+ ImGuiContext& g = *GImGui;
+
+ if (flags & ImGuiHoveredFlags_AnyWindow)
+ {
+ if (g.HoveredWindow == NULL)
+ return false;
+ }
+ else
+ {
+ switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows))
+ {
+ case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows:
+ if (g.HoveredRootWindow != g.CurrentWindow->RootWindow)
+ return false;
+ break;
+ case ImGuiHoveredFlags_RootWindow:
+ if (g.HoveredWindow != g.CurrentWindow->RootWindow)
+ return false;
+ break;
+ case ImGuiHoveredFlags_ChildWindows:
+ if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow))
+ return false;
+ break;
+ default:
+ if (g.HoveredWindow != g.CurrentWindow)
+ return false;
+ break;
+ }
+ }
+
+ if (!IsWindowContentHoverable(g.HoveredRootWindow, flags))
+ return false;
+ if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId)
+ return false;
+ return true;
+}
+
+bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+
+ if (flags & ImGuiFocusedFlags_AnyWindow)
+ return g.NavWindow != NULL;
+
+ IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End()
+ switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows))
+ {
+ case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows:
+ return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
+ case ImGuiFocusedFlags_RootWindow:
+ return g.NavWindow == g.CurrentWindow->RootWindow;
+ case ImGuiFocusedFlags_ChildWindows:
+ return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow);
+ default:
+ return g.NavWindow == g.CurrentWindow;
+ }
+}
+
+// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
+// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmaticaly.
+// If you want a window to never be focused, you may use the e.g. NoInputs flag.
+bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
+{
+ return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
+}
+
+float ImGui::GetWindowWidth()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->Size.x;
+}
+
+float ImGui::GetWindowHeight()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->Size.y;
+}
+
+ImVec2 ImGui::GetWindowPos()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ return window->Pos;
+}
+
+void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
+{
+ window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
+ window->Scroll.x = new_scroll_x;
+ window->DC.CursorMaxPos.x -= window->Scroll.x;
+}
+
+void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
+{
+ window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
+ window->Scroll.y = new_scroll_y;
+ window->DC.CursorMaxPos.y -= window->Scroll.y;
+}
+
+static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
+{
+ // Test condition (NB: bit 0 is always true) and clear flags for next time
+ if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
+ return;
+
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+ window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
+
+ // Set
+ const ImVec2 old_pos = window->Pos;
+ window->Pos = ImFloor(pos);
+ window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
+ window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.
+}
+
+void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ SetWindowPos(window, pos, cond);
+}
+
+void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond)
+{
+ if (ImGuiWindow* window = FindWindowByName(name))
+ SetWindowPos(window, pos, cond);
+}
+
+ImVec2 ImGui::GetWindowSize()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->Size;
+}
+
+static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond)
+{
+ // Test condition (NB: bit 0 is always true) and clear flags for next time
+ if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
+ return;
+
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+
+ // Set
+ if (size.x > 0.0f)
+ {
+ window->AutoFitFramesX = 0;
+ window->SizeFull.x = ImFloor(size.x);
+ }
+ else
+ {
+ window->AutoFitFramesX = 2;
+ window->AutoFitOnlyGrows = false;
+ }
+ if (size.y > 0.0f)
+ {
+ window->AutoFitFramesY = 0;
+ window->SizeFull.y = ImFloor(size.y);
+ }
+ else
+ {
+ window->AutoFitFramesY = 2;
+ window->AutoFitOnlyGrows = false;
+ }
+}
+
+void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond)
+{
+ SetWindowSize(GImGui->CurrentWindow, size, cond);
+}
+
+void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond)
+{
+ if (ImGuiWindow* window = FindWindowByName(name))
+ SetWindowSize(window, size, cond);
+}
+
+static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond)
+{
+ // Test condition (NB: bit 0 is always true) and clear flags for next time
+ if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
+ return;
+ window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+
+ // Set
+ window->Collapsed = collapsed;
+}
+
+void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)
+{
+ SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
+}
+
+bool ImGui::IsWindowCollapsed()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->Collapsed;
+}
+
+bool ImGui::IsWindowAppearing()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->Appearing;
+}
+
+void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
+{
+ if (ImGuiWindow* window = FindWindowByName(name))
+ SetWindowCollapsed(window, collapsed, cond);
+}
+
+void ImGui::SetWindowFocus()
+{
+ FocusWindow(GImGui->CurrentWindow);
+}
+
+void ImGui::SetWindowFocus(const char* name)
+{
+ if (name)
+ {
+ if (ImGuiWindow* window = FindWindowByName(name))
+ FocusWindow(window);
+ }
+ else
+ {
+ FocusWindow(NULL);
+ }
+}
+
+void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ g.NextWindowData.PosVal = pos;
+ g.NextWindowData.PosPivotVal = pivot;
+ g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ g.NextWindowData.SizeVal = size;
+ g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.SizeConstraintCond = ImGuiCond_Always;
+ g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
+ g.NextWindowData.SizeCallback = custom_callback;
+ g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
+}
+
+void ImGui::SetNextWindowContentSize(const ImVec2& size)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value.
+ g.NextWindowData.ContentSizeCond = ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ g.NextWindowData.CollapsedVal = collapsed;
+ g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowFocus()
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.FocusCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
+}
+
+void ImGui::SetNextWindowBgAlpha(float alpha)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.BgAlphaVal = alpha;
+ g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op)
+}
+
+// In window space (not screen space!)
+ImVec2 ImGui::GetContentRegionMax()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImVec2 mx = window->ContentsRegionRect.Max - window->Pos;
+ if (window->DC.ColumnsSet)
+ mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x;
+ return mx;
+}
+
+ImVec2 ImGui::GetContentRegionAvail()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return GetContentRegionMax() - (window->DC.CursorPos - window->Pos);
+}
+
+float ImGui::GetContentRegionAvailWidth()
+{
+ return GetContentRegionAvail().x;
+}
+
+// In window space (not screen space!)
+ImVec2 ImGui::GetWindowContentRegionMin()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->ContentsRegionRect.Min - window->Pos;
+}
+
+ImVec2 ImGui::GetWindowContentRegionMax()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->ContentsRegionRect.Max - window->Pos;
+}
+
+float ImGui::GetWindowContentRegionWidth()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->ContentsRegionRect.GetWidth();
+}
+
+float ImGui::GetTextLineHeight()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize;
+}
+
+float ImGui::GetTextLineHeightWithSpacing()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + g.Style.ItemSpacing.y;
+}
+
+float ImGui::GetFrameHeight()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + g.Style.FramePadding.y * 2.0f;
+}
+
+float ImGui::GetFrameHeightWithSpacing()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;
+}
+
+ImDrawList* ImGui::GetWindowDrawList()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ return window->DrawList;
+}
+
+ImFont* ImGui::GetFont()
+{
+ return GImGui->Font;
+}
+
+float ImGui::GetFontSize()
+{
+ return GImGui->FontSize;
+}
+
+ImVec2 ImGui::GetFontTexUvWhitePixel()
+{
+ return GImGui->DrawListSharedData.TexUvWhitePixel;
+}
+
+void ImGui::SetWindowFontScale(float scale)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ window->FontWindowScale = scale;
+ g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
+}
+
+// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.
+// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'.
+ImVec2 ImGui::GetCursorPos()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos - window->Pos + window->Scroll;
+}
+
+float ImGui::GetCursorPosX()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
+}
+
+float ImGui::GetCursorPosY()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
+}
+
+void ImGui::SetCursorPos(const ImVec2& local_pos)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
+}
+
+void ImGui::SetCursorPosX(float x)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
+ window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);
+}
+
+void ImGui::SetCursorPosY(float y)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
+ window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);
+}
+
+ImVec2 ImGui::GetCursorStartPos()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorStartPos - window->Pos;
+}
+
+ImVec2 ImGui::GetCursorScreenPos()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos;
+}
+
+void ImGui::SetCursorScreenPos(const ImVec2& pos)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos = pos;
+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
+}
+
+float ImGui::GetScrollX()
+{
+ return GImGui->CurrentWindow->Scroll.x;
+}
+
+float ImGui::GetScrollY()
+{
+ return GImGui->CurrentWindow->Scroll.y;
+}
+
+float ImGui::GetScrollMaxX()
+{
+ return GetWindowScrollMaxX(GImGui->CurrentWindow);
+}
+
+float ImGui::GetScrollMaxY()
+{
+ return GetWindowScrollMaxY(GImGui->CurrentWindow);
+}
+
+void ImGui::SetScrollX(float scroll_x)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->ScrollTarget.x = scroll_x;
+ window->ScrollTargetCenterRatio.x = 0.0f;
+}
+
+void ImGui::SetScrollY(float scroll_y)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY
+ window->ScrollTargetCenterRatio.y = 0.0f;
+}
+
+void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio)
+{
+ // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
+ ImGuiWindow* window = GetCurrentWindow();
+ IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
+ window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y);
+ window->ScrollTargetCenterRatio.y = center_y_ratio;
+}
+
+// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.
+void ImGui::SetScrollHereY(float center_y_ratio)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space
+ target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line.
+ SetScrollFromPosY(target_y, center_y_ratio);
+}
+
+void ImGui::ActivateItem(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ g.NavNextActivateId = id;
+}
+
+void ImGui::SetKeyboardFocusHere(int offset)
+{
+ IM_ASSERT(offset >= -1); // -1 is allowed but not below
+ ImGuiWindow* window = GetCurrentWindow();
+ window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
+ window->FocusIdxTabRequestNext = INT_MAX;
+}
+
+void ImGui::SetItemDefaultFocus()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!window->Appearing)
+ return;
+ if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent)
+ {
+ g.NavInitRequest = false;
+ g.NavInitResultId = g.NavWindow->DC.LastItemId;
+ g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos);
+ NavUpdateAnyRequestFlag();
+ if (!IsItemVisible())
+ SetScrollHereY();
+ }
+}
+
+void ImGui::SetStateStorage(ImGuiStorage* tree)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.StateStorage = tree ? tree : &window->StateStorage;
+}
+
+ImGuiStorage* ImGui::GetStateStorage()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.StateStorage;
+}
+
+void ImGui::PushID(const char* str_id)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ window->IDStack.push_back(window->GetIDNoKeepAlive(str_id));
+}
+
+void ImGui::PushID(const char* str_id_begin, const char* str_id_end)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end));
+}
+
+void ImGui::PushID(const void* ptr_id)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
+}
+
+void ImGui::PushID(int int_id)
+{
+ const void* ptr_id = (void*)(intptr_t)int_id;
+ ImGuiWindow* window = GetCurrentWindowRead();
+ window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
+}
+
+void ImGui::PopID()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ window->IDStack.pop_back();
+}
+
+ImGuiID ImGui::GetID(const char* str_id)
+{
+ return GImGui->CurrentWindow->GetID(str_id);
+}
+
+ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end)
+{
+ return GImGui->CurrentWindow->GetID(str_id_begin, str_id_end);
+}
+
+ImGuiID ImGui::GetID(const void* ptr_id)
+{
+ return GImGui->CurrentWindow->GetID(ptr_id);
+}
+
+bool ImGui::IsRectVisible(const ImVec2& size)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
+}
+
+bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
+}
+
+// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
+void ImGui::BeginGroup()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
+ ImGuiGroupData& group_data = window->DC.GroupStack.back();
+ group_data.BackupCursorPos = window->DC.CursorPos;
+ group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
+ group_data.BackupIndent = window->DC.Indent;
+ group_data.BackupGroupOffset = window->DC.GroupOffset;
+ group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
+ group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
+ group_data.BackupLogLinePosY = window->DC.LogLinePosY;
+ group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
+ group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
+ group_data.AdvanceCursor = true;
+
+ window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
+ window->DC.Indent = window->DC.GroupOffset;
+ window->DC.CursorMaxPos = window->DC.CursorPos;
+ window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
+ window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
+}
+
+void ImGui::EndGroup()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
+
+ ImGuiGroupData& group_data = window->DC.GroupStack.back();
+
+ ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
+ group_bb.Max = ImMax(group_bb.Min, group_bb.Max);
+
+ window->DC.CursorPos = group_data.BackupCursorPos;
+ window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
+ window->DC.Indent = group_data.BackupIndent;
+ window->DC.GroupOffset = group_data.BackupGroupOffset;
+ window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
+ window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
+ window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
+
+ if (group_data.AdvanceCursor)
+ {
+ window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
+ ItemSize(group_bb.GetSize(), group_data.BackupCurrentLineTextBaseOffset);
+ ItemAdd(group_bb, 0);
+ }
+
+ // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
+ // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
+ // (and if you grep for LastItemId you'll notice it is only used in that context.
+ if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
+ window->DC.LastItemId = g.ActiveId;
+ else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
+ window->DC.LastItemId = g.ActiveIdPreviousFrame;
+ window->DC.LastItemRect = group_bb;
+
+ window->DC.GroupStack.pop_back();
+
+ //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
+}
+
+// Gets back to previous line and continue with horizontal layout
+// pos_x == 0 : follow right after previous item
+// pos_x != 0 : align to specified x position (relative to window/group left)
+// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0
+// spacing_w >= 0 : enforce spacing amount
+void ImGui::SameLine(float pos_x, float spacing_w)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ if (pos_x != 0.0f)
+ {
+ if (spacing_w < 0.0f) spacing_w = 0.0f;
+ window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
+ window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
+ }
+ else
+ {
+ if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x;
+ window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
+ window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
+ }
+ window->DC.CurrentLineSize = window->DC.PrevLineSize;
+ window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
+}
+
+void ImGui::Indent(float indent_w)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
+ window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
+}
+
+void ImGui::Unindent(float indent_w)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
+ window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] TOOLTIPS
+//-----------------------------------------------------------------------------
+
+void ImGui::BeginTooltip()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.DragDropWithinSourceOrTarget)
+ {
+ // The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor)
+ // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor.
+ // Whatever we do we want to call SetNextWindowPos() to enforce a tooltip position and disable clipping the tooltip without our display area, like regular tooltip do.
+ //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
+ ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale);
+ SetNextWindowPos(tooltip_pos);
+ SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
+ //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :(
+ BeginTooltipEx(0, true);
+ }
+ else
+ {
+ BeginTooltipEx(0, false);
+ }
+}
+
+// Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first.
+void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip)
+{
+ ImGuiContext& g = *GImGui;
+ char window_name[16];
+ ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
+ if (override_previous_tooltip)
+ if (ImGuiWindow* window = FindWindowByName(window_name))
+ if (window->Active)
+ {
+ // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
+ window->Hidden = true;
+ window->HiddenFramesRegular = 1;
+ ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
+ }
+ ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
+ Begin(window_name, NULL, flags | extra_flags);
+}
+
+void ImGui::EndTooltip()
+{
+ IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls
+ End();
+}
+
+void ImGui::SetTooltipV(const char* fmt, va_list args)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.DragDropWithinSourceOrTarget)
+ BeginTooltip();
+ else
+ BeginTooltipEx(0, true);
+ TextV(fmt, args);
+ EndTooltip();
+}
+
+void ImGui::SetTooltip(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ SetTooltipV(fmt, args);
+ va_end(args);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] POPUPS
+//-----------------------------------------------------------------------------
+
+bool ImGui::IsPopupOpen(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
+}
+
+bool ImGui::IsPopupOpen(const char* str_id)
+{
+ ImGuiContext& g = *GImGui;
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
+}
+
+ImGuiWindow* ImGui::GetFrontMostPopupModal()
+{
+ ImGuiContext& g = *GImGui;
+ for (int n = g.OpenPopupStack.Size-1; n >= 0; n--)
+ if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window)
+ if (popup->Flags & ImGuiWindowFlags_Modal)
+ return popup;
+ return NULL;
+}
+
+void ImGui::OpenPopup(const char* str_id)
+{
+ ImGuiContext& g = *GImGui;
+ OpenPopupEx(g.CurrentWindow->GetID(str_id));
+}
+
+// Mark popup as open (toggle toward open state).
+// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.
+// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
+// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
+void ImGui::OpenPopupEx(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* parent_window = g.CurrentWindow;
+ int current_stack_size = g.BeginPopupStack.Size;
+ ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack.
+ popup_ref.PopupId = id;
+ popup_ref.Window = NULL;
+ popup_ref.ParentWindow = parent_window;
+ popup_ref.OpenFrameCount = g.FrameCount;
+ popup_ref.OpenParentId = parent_window->IDStack.back();
+ popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
+ popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
+
+ //IMGUI_DEBUG_LOG("OpenPopupEx(0x%08X)\n", g.FrameCount, id);
+ if (g.OpenPopupStack.Size < current_stack_size + 1)
+ {
+ g.OpenPopupStack.push_back(popup_ref);
+ }
+ else
+ {
+ // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui
+ // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing
+ // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand.
+ if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1)
+ {
+ g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
+ }
+ else
+ {
+ // Close child popups if any, then flag popup for open/reopen
+ g.OpenPopupStack.resize(current_stack_size + 1);
+ g.OpenPopupStack[current_stack_size] = popup_ref;
+ }
+
+ // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
+ // This is equivalent to what ClosePopupToLevel() does.
+ //if (g.OpenPopupStack[current_stack_size].PopupId == id)
+ // FocusWindow(parent_window);
+ }
+}
+
+bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ {
+ ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
+ IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
+ OpenPopupEx(id);
+ return true;
+ }
+ return false;
+}
+
+void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.OpenPopupStack.empty())
+ return;
+
+ // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
+ // Don't close our own child popup windows.
+ int popup_count_to_keep = 0;
+ if (ref_window)
+ {
+ // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow)
+ for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++)
+ {
+ ImGuiPopupRef& popup = g.OpenPopupStack[popup_count_to_keep];
+ if (!popup.Window)
+ continue;
+ IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
+ if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)
+ continue;
+
+ // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow)
+ bool popup_or_descendent_has_focus = false;
+ for (int m = popup_count_to_keep; m < g.OpenPopupStack.Size && !popup_or_descendent_has_focus; m++)
+ if (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == ref_window->RootWindow)
+ popup_or_descendent_has_focus = true;
+ if (!popup_or_descendent_has_focus)
+ break;
+ }
+ }
+ if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
+ {
+ //IMGUI_DEBUG_LOG("ClosePopupsOverWindow(%s) -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
+ ClosePopupToLevel(popup_count_to_keep, false);
+ }
+}
+
+void ImGui::ClosePopupToLevel(int remaining, bool apply_focus_to_window_under)
+{
+ IM_ASSERT(remaining >= 0);
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow;
+ g.OpenPopupStack.resize(remaining);
+
+ // FIXME: This code is faulty and we may want to eventually to replace or remove the 'apply_focus_to_window_under=true' path completely.
+ // Instead of using g.OpenPopupStack[remaining-1].Window etc. we should find the highest root window that is behind the popups we are closing.
+ // The current code will set focus to the parent of the popup window which is incorrect.
+ // It rarely manifested until now because UpdateMouseMovingWindow() would call FocusWindow() again on the clicked window,
+ // leading to a chain of focusing A (clicked window) then B (parent window of the popup) then A again.
+ // However if the clicked window has the _NoMove flag set we would be left with B focused.
+ // For now, we have disabled this path when called from ClosePopupsOverWindow() because the users of ClosePopupsOverWindow() don't need to alter focus anyway,
+ // but we should inspect and fix this properly.
+ if (apply_focus_to_window_under)
+ {
+ if (g.NavLayer == 0)
+ focus_window = NavRestoreLastChildNavWindow(focus_window);
+ FocusWindow(focus_window);
+ }
+}
+
+// Close the popup we have begin-ed into.
+void ImGui::CloseCurrentPopup()
+{
+ ImGuiContext& g = *GImGui;
+ int popup_idx = g.BeginPopupStack.Size - 1;
+ if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
+ return;
+ while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu))
+ popup_idx--;
+ ClosePopupToLevel(popup_idx, true);
+
+ // A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
+ // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window.
+ // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic.
+ if (ImGuiWindow* window = g.NavWindow)
+ window->DC.NavHideHighlightOneFrame = true;
+}
+
+bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (!IsPopupOpen(id))
+ {
+ g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
+ return false;
+ }
+
+ char name[20];
+ if (extra_flags & ImGuiWindowFlags_ChildMenu)
+ ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
+ else
+ ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
+
+ bool is_open = Begin(name, NULL, extra_flags | ImGuiWindowFlags_Popup);
+ if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
+ EndPopup();
+
+ return is_open;
+}
+
+bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
+ {
+ g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
+ return false;
+ }
+ flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
+ return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags);
+}
+
+// If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup.
+// Note that popup visibility status is owned by imgui (and manipulated with e.g. OpenPopup) so the actual value of *p_open is meaningless here.
+bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ const ImGuiID id = window->GetID(name);
+ if (!IsPopupOpen(id))
+ {
+ g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values
+ return false;
+ }
+
+ // Center modal windows by default
+ // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
+ if (g.NextWindowData.PosCond == 0)
+ SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
+
+ flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings;
+ const bool is_open = Begin(name, p_open, flags);
+ if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
+ {
+ EndPopup();
+ if (is_open)
+ ClosePopupToLevel(g.BeginPopupStack.Size, true);
+ return false;
+ }
+ return is_open;
+}
+
+void ImGui::EndPopup()
+{
+ ImGuiContext& g = *GImGui; (void)g;
+ IM_ASSERT(g.CurrentWindow->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
+ IM_ASSERT(g.BeginPopupStack.Size > 0);
+
+ // Make all menus and popups wrap around for now, may need to expose that policy.
+ NavMoveRequestTryWrapping(g.CurrentWindow, ImGuiNavMoveFlags_LoopY);
+
+ End();
+}
+
+// This is a helper to handle the simplest case of associating one named popup to one given widget.
+// You may want to handle this on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
+// You can pass a NULL str_id to use the identifier of the last item.
+bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
+ IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
+ if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ OpenPopupEx(id);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
+}
+
+bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items)
+{
+ if (!str_id)
+ str_id = "window_context";
+ ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
+ if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ if (also_over_items || !IsAnyItemHovered())
+ OpenPopupEx(id);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
+}
+
+bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button)
+{
+ if (!str_id)
+ str_id = "void_context";
+ ImGuiID id = GImGui->CurrentWindow->GetID(str_id);
+ if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
+ OpenPopupEx(id);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings);
+}
+
+ImRect ImGui::GetWindowAllowedExtentRect(ImGuiWindow*)
+{
+ ImVec2 padding = GImGui->Style.DisplaySafeAreaPadding;
+ ImRect r_screen = GetViewportRect();
+ r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
+ return r_screen;
+}
+
+// r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.)
+// r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it.
+ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
+{
+ ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
+ //GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255));
+ //GImGui->OverlayDrawList.AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255));
+
+ // Combo Box policy (we want a connecting edge)
+ if (policy == ImGuiPopupPositionPolicy_ComboBox)
+ {
+ const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
+ for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
+ {
+ const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
+ if (n != -1 && dir == *last_dir) // Already tried this direction?
+ continue;
+ ImVec2 pos;
+ if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default)
+ if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right
+ if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left
+ if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left
+ if (!r_outer.Contains(ImRect(pos, pos + size)))
+ continue;
+ *last_dir = dir;
+ return pos;
+ }
+ }
+
+ // Default popup policy
+ const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
+ for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
+ {
+ const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
+ if (n != -1 && dir == *last_dir) // Already tried this direction?
+ continue;
+ float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
+ float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
+ if (avail_w < size.x || avail_h < size.y)
+ continue;
+ ImVec2 pos;
+ pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
+ pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
+ *last_dir = dir;
+ return pos;
+ }
+
+ // Fallback, try to keep within display
+ *last_dir = ImGuiDir_None;
+ ImVec2 pos = ref_pos;
+ pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
+ pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
+ return pos;
+}
+
+ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+
+ ImRect r_outer = GetWindowAllowedExtentRect(window);
+ if (window->Flags & ImGuiWindowFlags_ChildMenu)
+ {
+ // Child menus typically request _any_ position within the parent menu item, and then our FindBestWindowPosForPopup() function will move the new menu outside the parent bounds.
+ // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu.
+ IM_ASSERT(g.CurrentWindow == window);
+ ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2];
+ float horizontal_overlap = g.Style.ItemSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x).
+ ImRect r_avoid;
+ if (parent_window->DC.MenuBarAppending)
+ r_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight());
+ else
+ r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);
+ return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
+ }
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ {
+ ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1);
+ return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
+ }
+ if (window->Flags & ImGuiWindowFlags_Tooltip)
+ {
+ // Position tooltip (always follows mouse)
+ float sc = g.Style.MouseCursorScale;
+ ImVec2 ref_pos = NavCalcPreferredRefPos();
+ ImRect r_avoid;
+ if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
+ r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
+ else
+ r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
+ ImVec2 pos = FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
+ if (window->AutoPosLastDirection == ImGuiDir_None)
+ pos = ref_pos + ImVec2(2, 2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.
+ return pos;
+ }
+ IM_ASSERT(0);
+ return window->Pos;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] VIEWPORTS, PLATFORM WINDOWS
+//-----------------------------------------------------------------------------
+
+// (this section is filled in the 'viewport' and 'docking' branches)
+
+//-----------------------------------------------------------------------------
+// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
+//-----------------------------------------------------------------------------
+
+ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
+{
+ if (ImFabs(dx) > ImFabs(dy))
+ return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
+ return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
+}
+
+static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
+{
+ if (a1 < b0)
+ return a1 - b0;
+ if (b1 < a0)
+ return a0 - b1;
+ return 0.0f;
+}
+
+static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect)
+{
+ if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
+ {
+ r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y);
+ r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y);
+ }
+ else
+ {
+ r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x);
+ r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x);
+ }
+}
+
+// Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057
+static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.NavLayer != window->DC.NavLayerCurrent)
+ return false;
+
+ const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
+ g.NavScoringCount++;
+
+ // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
+ if (window->ParentWindow == g.NavWindow)
+ {
+ IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened);
+ if (!window->ClipRect.Contains(cand))
+ return false;
+ cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window
+ }
+
+ // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
+ // For example, this ensure that items in one column are not reached when moving vertically from items in another column.
+ NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect);
+
+ // Compute distance between boxes
+ // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
+ float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
+ float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items
+ if (dby != 0.0f && dbx != 0.0f)
+ dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
+ float dist_box = ImFabs(dbx) + ImFabs(dby);
+
+ // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter)
+ float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
+ float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
+ float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee)
+
+ // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
+ ImGuiDir quadrant;
+ float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
+ if (dbx != 0.0f || dby != 0.0f)
+ {
+ // For non-overlapping boxes, use distance between boxes
+ dax = dbx;
+ day = dby;
+ dist_axial = dist_box;
+ quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
+ }
+ else if (dcx != 0.0f || dcy != 0.0f)
+ {
+ // For overlapping boxes with different centers, use distance between centers
+ dax = dcx;
+ day = dcy;
+ dist_axial = dist_center;
+ quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
+ }
+ else
+ {
+ // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)
+ quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
+ }
+
+#if IMGUI_DEBUG_NAV_SCORING
+ char buf[128];
+ if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max))
+ {
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]);
+ ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
+ draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100));
+ draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200));
+ draw_list->AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150));
+ draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf);
+ }
+ else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
+ {
+ if (ImGui::IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; }
+ if (quadrant == g.NavMoveDir)
+ {
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
+ ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
+ draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200));
+ draw_list->AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf);
+ }
+ }
+ #endif
+
+ // Is it in the quadrant we're interesting in moving to?
+ bool new_best = false;
+ if (quadrant == g.NavMoveDir)
+ {
+ // Does it beat the current best candidate?
+ if (dist_box < result->DistBox)
+ {
+ result->DistBox = dist_box;
+ result->DistCenter = dist_center;
+ return true;
+ }
+ if (dist_box == result->DistBox)
+ {
+ // Try using distance between center points to break ties
+ if (dist_center < result->DistCenter)
+ {
+ result->DistCenter = dist_center;
+ new_best = true;
+ }
+ else if (dist_center == result->DistCenter)
+ {
+ // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
+ // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
+ // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
+ if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
+ new_best = true;
+ }
+ }
+ }
+
+ // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches
+ // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
+ // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too.
+ // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward.
+ // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
+ if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match
+ if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
+ if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f))
+ {
+ result->DistAxial = dist_axial;
+ new_best = true;
+ }
+
+ return new_best;
+}
+
+// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
+static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
+ // return;
+
+ const ImGuiItemFlags item_flags = window->DC.ItemFlags;
+ const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
+
+ // Process Init Request
+ if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
+ {
+ // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback
+ if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0)
+ {
+ g.NavInitResultId = id;
+ g.NavInitResultRectRel = nav_bb_rel;
+ }
+ if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus))
+ {
+ g.NavInitRequest = false; // Found a match, clear request
+ NavUpdateAnyRequestFlag();
+ }
+ }
+
+ // Process Move Request (scoring for navigation)
+ // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
+ if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & ImGuiItemFlags_NoNav))
+ {
+ ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
+#if IMGUI_DEBUG_NAV_SCORING
+ // [DEBUG] Score all items in NavWindow at all times
+ if (!g.NavMoveRequest)
+ g.NavMoveDir = g.NavMoveDirLast;
+ bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest;
+#else
+ bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb);
+#endif
+ if (new_best)
+ {
+ result->ID = id;
+ result->Window = window;
+ result->RectRel = nav_bb_rel;
+ }
+
+ const float VISIBLE_RATIO = 0.70f;
+ if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
+ if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
+ if (NavScoreItem(&g.NavMoveResultLocalVisibleSet, nav_bb))
+ {
+ result = &g.NavMoveResultLocalVisibleSet;
+ result->ID = id;
+ result->Window = window;
+ result->RectRel = nav_bb_rel;
+ }
+ }
+
+ // Update window-relative bounding box of navigated item
+ if (g.NavId == id)
+ {
+ g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
+ g.NavLayer = window->DC.NavLayerCurrent;
+ g.NavIdIsAlive = true;
+ g.NavIdTabCounter = window->FocusIdxTabCounter;
+ window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
+ }
+}
+
+bool ImGui::NavMoveRequestButNoResultYet()
+{
+ ImGuiContext& g = *GImGui;
+ return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
+}
+
+void ImGui::NavMoveRequestCancel()
+{
+ ImGuiContext& g = *GImGui;
+ g.NavMoveRequest = false;
+ NavUpdateAnyRequestFlag();
+}
+
+void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None);
+ ImGui::NavMoveRequestCancel();
+ g.NavMoveDir = move_dir;
+ g.NavMoveClipDir = clip_dir;
+ g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
+ g.NavMoveRequestFlags = move_flags;
+ g.NavWindow->NavRectRel[g.NavLayer] = bb_rel;
+}
+
+void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != 0)
+ return;
+ IM_ASSERT(move_flags != 0); // No points calling this with no wrapping
+ ImRect bb_rel = window->NavRectRel[0];
+
+ ImGuiDir clip_dir = g.NavMoveDir;
+ if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
+ {
+ bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x;
+ if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
+ NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
+ }
+ if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
+ {
+ bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
+ if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); clip_dir = ImGuiDir_Down; }
+ NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
+ }
+ if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
+ {
+ bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y;
+ if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
+ NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
+ }
+ if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
+ {
+ bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
+ if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); clip_dir = ImGuiDir_Right; }
+ NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
+ }
+}
+
+static void ImGui::NavSaveLastChildNavWindow(ImGuiWindow* nav_window)
+{
+ ImGuiWindow* parent_window = nav_window;
+ while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
+ parent_window = parent_window->ParentWindow;
+ if (parent_window && parent_window != nav_window)
+ parent_window->NavLastChildNavWindow = nav_window;
+}
+
+// Call when we are expected to land on Layer 0 after FocusWindow()
+static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
+{
+ return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
+}
+
+static void NavRestoreLayer(ImGuiNavLayer layer)
+{
+ ImGuiContext& g = *GImGui;
+ g.NavLayer = layer;
+ if (layer == 0)
+ g.NavWindow = ImGui::NavRestoreLastChildNavWindow(g.NavWindow);
+ if (layer == 0 && g.NavWindow->NavLastIds[0] != 0)
+ ImGui::SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]);
+ else
+ ImGui::NavInitWindow(g.NavWindow, true);
+}
+
+static inline void ImGui::NavUpdateAnyRequestFlag()
+{
+ ImGuiContext& g = *GImGui;
+ g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
+ if (g.NavAnyRequest)
+ IM_ASSERT(g.NavWindow != NULL);
+}
+
+// This needs to be called before we submit any widget (aka in or before Begin)
+void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(window == g.NavWindow);
+ bool init_for_nav = false;
+ if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
+ if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
+ init_for_nav = true;
+ if (init_for_nav)
+ {
+ SetNavID(0, g.NavLayer);
+ g.NavInitRequest = true;
+ g.NavInitRequestFromMove = false;
+ g.NavInitResultId = 0;
+ g.NavInitResultRectRel = ImRect();
+ NavUpdateAnyRequestFlag();
+ }
+ else
+ {
+ g.NavId = window->NavLastIds[0];
+ }
+}
+
+static ImVec2 ImGui::NavCalcPreferredRefPos()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
+ {
+ // Mouse (we need a fallback in case the mouse becomes invalid after being used)
+ if (IsMousePosValid(&g.IO.MousePos))
+ return g.IO.MousePos;
+ return g.LastValidMousePos;
+ }
+ else
+ {
+ // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item.
+ const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
+ ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
+ ImRect visible_rect = GetViewportRect();
+ return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta.
+ }
+}
+
+float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
+{
+ ImGuiContext& g = *GImGui;
+ if (mode == ImGuiInputReadMode_Down)
+ return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user)
+
+ const float t = g.IO.NavInputsDownDuration[n];
+ if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input.
+ return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
+ if (t < 0.0f)
+ return 0.0f;
+ if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input.
+ return (t == 0.0f) ? 1.0f : 0.0f;
+ if (mode == ImGuiInputReadMode_Repeat)
+ return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f);
+ if (mode == ImGuiInputReadMode_RepeatSlow)
+ return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f);
+ if (mode == ImGuiInputReadMode_RepeatFast)
+ return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f);
+ return 0.0f;
+}
+
+ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor)
+{
+ ImVec2 delta(0.0f, 0.0f);
+ if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
+ delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode));
+ if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
+ delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode));
+ if (dir_sources & ImGuiNavDirSourceFlags_PadLStick)
+ delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode));
+ if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow))
+ delta *= slow_factor;
+ if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast))
+ delta *= fast_factor;
+ return delta;
+}
+
+// Scroll to keep newly navigated item fully into view
+// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated.
+static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect)
+{
+ ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1));
+ //GetOverlayDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
+ if (window_rect.Contains(item_rect))
+ return;
+
+ ImGuiContext& g = *GImGui;
+ if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x)
+ {
+ window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x;
+ window->ScrollTargetCenterRatio.x = 0.0f;
+ }
+ else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x)
+ {
+ window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x;
+ window->ScrollTargetCenterRatio.x = 1.0f;
+ }
+ if (item_rect.Min.y < window_rect.Min.y)
+ {
+ window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y;
+ window->ScrollTargetCenterRatio.y = 0.0f;
+ }
+ else if (item_rect.Max.y >= window_rect.Max.y)
+ {
+ window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y;
+ window->ScrollTargetCenterRatio.y = 1.0f;
+ }
+}
+
+static void ImGui::NavUpdate()
+{
+ ImGuiContext& g = *GImGui;
+ g.IO.WantSetMousePos = false;
+#if 0
+ if (g.NavScoringCount > 0) IMGUI_DEBUG_LOG("NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
+#endif
+
+ // Set input source as Gamepad when buttons are pressed before we map Keyboard (some features differs when used with Gamepad vs Keyboard)
+ bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
+ bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
+ if (nav_gamepad_active)
+ if (g.IO.NavInputs[ImGuiNavInput_Activate] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Input] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Cancel] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Menu] > 0.0f)
+ g.NavInputSource = ImGuiInputSource_NavGamepad;
+
+ // Update Keyboard->Nav inputs mapping
+ if (nav_keyboard_active)
+ {
+ #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; }
+ NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate );
+ NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input );
+ NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel );
+ NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ );
+ NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
+ NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
+ NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
+ if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
+ if (g.IO.KeyShift) g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
+ if (g.IO.KeyAlt) g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
+ #undef NAV_MAP_KEY
+ }
+ memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration));
+ for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++)
+ g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f;
+
+ // Process navigation init request (select first/default focus)
+ if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove))
+ {
+ // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
+ IM_ASSERT(g.NavWindow);
+ if (g.NavInitRequestFromMove)
+ SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel);
+ else
+ SetNavID(g.NavInitResultId, g.NavLayer);
+ g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel;
+ }
+ g.NavInitRequest = false;
+ g.NavInitRequestFromMove = false;
+ g.NavInitResultId = 0;
+ g.NavJustMovedToId = 0;
+
+ // Process navigation move request
+ if (g.NavMoveRequest)
+ NavUpdateMoveResult();
+
+ // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame
+ if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive)
+ {
+ IM_ASSERT(g.NavMoveRequest);
+ if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0)
+ g.NavDisableHighlight = false;
+ g.NavMoveRequestForward = ImGuiNavForward_None;
+ }
+
+ // Apply application mouse position movement, after we had a chance to process move request result.
+ if (g.NavMousePosDirty && g.NavIdIsAlive)
+ {
+ // Set mouse position given our knowledge of the navigated item position from last frame
+ if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
+ {
+ if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
+ {
+ g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos();
+ g.IO.WantSetMousePos = true;
+ }
+ }
+ g.NavMousePosDirty = false;
+ }
+ g.NavIdIsAlive = false;
+ g.NavJustTabbedId = 0;
+ IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1);
+
+ // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0
+ if (g.NavWindow)
+ NavSaveLastChildNavWindow(g.NavWindow);
+ if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0)
+ g.NavWindow->NavLastChildNavWindow = NULL;
+
+ // Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.)
+ NavUpdateWindowing();
+
+ // Set output flags for user application
+ g.IO.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
+ g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest;
+
+ // Process NavCancel input (to close a popup, get back to parent, clear focus)
+ if (IsNavInputPressed(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed))
+ {
+ if (g.ActiveId != 0)
+ {
+ ClearActiveID();
+ }
+ else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
+ {
+ // Exit child window
+ ImGuiWindow* child_window = g.NavWindow;
+ ImGuiWindow* parent_window = g.NavWindow->ParentWindow;
+ IM_ASSERT(child_window->ChildId != 0);
+ FocusWindow(parent_window);
+ SetNavID(child_window->ChildId, 0);
+ g.NavIdIsAlive = false;
+ if (g.NavDisableMouseHover)
+ g.NavMousePosDirty = true;
+ }
+ else if (g.OpenPopupStack.Size > 0)
+ {
+ // Close open popup/menu
+ if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
+ ClosePopupToLevel(g.OpenPopupStack.Size - 1, true);
+ }
+ else if (g.NavLayer != 0)
+ {
+ // Leave the "menu" layer
+ NavRestoreLayer(ImGuiNavLayer_Main);
+ }
+ else
+ {
+ // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
+ if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
+ g.NavWindow->NavLastIds[0] = 0;
+ g.NavId = 0;
+ }
+ }
+
+ // Process manual activation request
+ g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0;
+ if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+ {
+ bool activate_down = IsNavInputDown(ImGuiNavInput_Activate);
+ bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed);
+ if (g.ActiveId == 0 && activate_pressed)
+ g.NavActivateId = g.NavId;
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down)
+ g.NavActivateDownId = g.NavId;
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed)
+ g.NavActivatePressedId = g.NavId;
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed))
+ g.NavInputId = g.NavId;
+ }
+ if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+ g.NavDisableHighlight = true;
+ if (g.NavActivateId != 0)
+ IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
+ g.NavMoveRequest = false;
+
+ // Process programmatic activation request
+ if (g.NavNextActivateId != 0)
+ g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId;
+ g.NavNextActivateId = 0;
+
+ // Initiate directional inputs request
+ const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags;
+ if (g.NavMoveRequestForward == ImGuiNavForward_None)
+ {
+ g.NavMoveDir = ImGuiDir_None;
+ g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
+ if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+ {
+ if ((allowed_dir_flags & (1<<ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Left;
+ if ((allowed_dir_flags & (1<<ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Right;
+ if ((allowed_dir_flags & (1<<ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Up;
+ if ((allowed_dir_flags & (1<<ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Down;
+ }
+ g.NavMoveClipDir = g.NavMoveDir;
+ }
+ else
+ {
+ // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
+ // (Preserve g.NavMoveRequestFlags, g.NavMoveClipDir which were set by the NavMoveRequestForward() function)
+ IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
+ IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_ForwardQueued);
+ g.NavMoveRequestForward = ImGuiNavForward_ForwardActive;
+ }
+
+ // Update PageUp/PageDown scroll
+ float nav_scoring_rect_offset_y = 0.0f;
+ if (nav_keyboard_active)
+ nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
+
+ // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match
+ if (g.NavMoveDir != ImGuiDir_None)
+ {
+ g.NavMoveRequest = true;
+ g.NavMoveDirLast = g.NavMoveDir;
+ }
+ if (g.NavMoveRequest && g.NavId == 0)
+ {
+ g.NavInitRequest = g.NavInitRequestFromMove = true;
+ g.NavInitResultId = 0;
+ g.NavDisableHighlight = false;
+ }
+ NavUpdateAnyRequestFlag();
+
+ // Scrolling
+ if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget)
+ {
+ // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
+ ImGuiWindow* window = g.NavWindow;
+ const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
+ if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
+ {
+ if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
+ SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
+ if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)
+ SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
+ }
+
+ // *Normal* Manual scroll with NavScrollXXX keys
+ // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
+ ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f);
+ if (scroll_dir.x != 0.0f && window->ScrollbarX)
+ {
+ SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
+ g.NavMoveFromClampedRefRect = true;
+ }
+ if (scroll_dir.y != 0.0f)
+ {
+ SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
+ g.NavMoveFromClampedRefRect = true;
+ }
+ }
+
+ // Reset search results
+ g.NavMoveResultLocal.Clear();
+ g.NavMoveResultLocalVisibleSet.Clear();
+ g.NavMoveResultOther.Clear();
+
+ // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items
+ if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0)
+ {
+ ImGuiWindow* window = g.NavWindow;
+ ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1));
+ if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
+ {
+ float pad = window->CalcFontSize() * 0.5f;
+ window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
+ window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel);
+ g.NavId = 0;
+ }
+ g.NavMoveFromClampedRefRect = false;
+ }
+
+ // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
+ ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0);
+ g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect();
+ g.NavScoringRectScreen.TranslateY(nav_scoring_rect_offset_y);
+ g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x);
+ g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x;
+ IM_ASSERT(!g.NavScoringRectScreen.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
+ //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG]
+ g.NavScoringCount = 0;
+#if IMGUI_DEBUG_NAV_RECTS
+ if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) GetOverlayDrawList(g.NavWindow)->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG]
+ if (g.NavWindow) { ImU32 col = (!g.NavWindow->Hidden) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); GetOverlayDrawList(g.NavWindow)->AddCircleFilled(p, 3.0f, col); GetOverlayDrawList(g.NavWindow)->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
+#endif
+}
+
+// Apply result from previous frame navigation directional move request
+static void ImGui::NavUpdateMoveResult()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0)
+ {
+ // In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result)
+ if (g.NavId != 0)
+ {
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = true;
+ }
+ return;
+ }
+
+ // Select which result to use
+ ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
+
+ // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
+ if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
+ if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId)
+ result = &g.NavMoveResultLocalVisibleSet;
+
+ // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
+ if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
+ if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
+ result = &g.NavMoveResultOther;
+ IM_ASSERT(g.NavWindow && result->Window);
+
+ // Scroll to keep newly navigated item fully into view.
+ if (g.NavLayer == 0)
+ {
+ ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
+ NavScrollToBringItemIntoView(result->Window, rect_abs);
+
+ // Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate()
+ ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false);
+ ImVec2 delta_scroll = result->Window->Scroll - next_scroll;
+ result->RectRel.Translate(delta_scroll);
+
+ // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy).
+ if (result->Window->Flags & ImGuiWindowFlags_ChildWindow)
+ NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll));
+ }
+
+ ClearActiveID();
+ g.NavWindow = result->Window;
+ SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel);
+ g.NavJustMovedToId = result->ID;
+ g.NavMoveFromClampedRefRect = false;
+}
+
+static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.NavMoveDir == ImGuiDir_None && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0)
+ {
+ ImGuiWindow* window = g.NavWindow;
+ bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
+ bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
+ if ((page_up_held && !page_down_held) || (page_down_held && !page_up_held))
+ {
+ if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
+ {
+ // Fallback manual-scroll when window has no navigable item
+ if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
+ SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight());
+ else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
+ SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight());
+ }
+ else
+ {
+ const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
+ const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
+ float nav_scoring_rect_offset_y = 0.0f;
+ if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
+ {
+ nav_scoring_rect_offset_y = -page_offset_y;
+ g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
+ g.NavMoveClipDir = ImGuiDir_Up;
+ g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
+ }
+ else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
+ {
+ nav_scoring_rect_offset_y = +page_offset_y;
+ g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
+ g.NavMoveClipDir = ImGuiDir_Down;
+ g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
+ }
+ return nav_scoring_rect_offset_y;
+ }
+ }
+ }
+ return 0.0f;
+}
+
+static int FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
+{
+ ImGuiContext& g = *GImGui;
+ for (int i = g.WindowsFocusOrder.Size-1; i >= 0; i--)
+ if (g.WindowsFocusOrder[i] == window)
+ return i;
+ return -1;
+}
+
+static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
+{
+ ImGuiContext& g = *GImGui;
+ for (int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir)
+ if (ImGui::IsWindowNavFocusable(g.WindowsFocusOrder[i]))
+ return g.WindowsFocusOrder[i];
+ return NULL;
+}
+
+static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindowingTarget);
+ if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
+ return;
+
+ const int i_current = FindWindowFocusIndex(g.NavWindowingTarget);
+ ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
+ if (!window_target)
+ window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
+ if (window_target) // Don't reset windowing target if there's a single window in the list
+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target;
+ g.NavWindowingToggleLayer = false;
+}
+
+// Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer)
+static void ImGui::NavUpdateWindowing()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* apply_focus_window = NULL;
+ bool apply_toggle_layer = false;
+
+ ImGuiWindow* modal_window = GetFrontMostPopupModal();
+ if (modal_window != NULL)
+ {
+ g.NavWindowingTarget = NULL;
+ return;
+ }
+
+ // Fade out
+ if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL)
+ {
+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - g.IO.DeltaTime * 10.0f, 0.0f);
+ if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f)
+ g.NavWindowingTargetAnim = NULL;
+ }
+
+ // Start CTRL-TAB or Square+L/R window selection
+ bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
+ bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard);
+ if (start_windowing_with_gamepad || start_windowing_with_keyboard)
+ if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
+ {
+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window;
+ g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
+ g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true;
+ g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad;
+ }
+
+ // Gamepad update
+ g.NavWindowingTimer += g.IO.DeltaTime;
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad)
+ {
+ // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise
+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
+
+ // Select window to focus
+ const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow);
+ if (focus_change_dir != 0)
+ {
+ NavUpdateWindowingHighlightWindow(focus_change_dir);
+ g.NavWindowingHighlightAlpha = 1.0f;
+ }
+
+ // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most)
+ if (!IsNavInputDown(ImGuiNavInput_Menu))
+ {
+ g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore.
+ if (g.NavWindowingToggleLayer && g.NavWindow)
+ apply_toggle_layer = true;
+ else if (!g.NavWindowingToggleLayer)
+ apply_focus_window = g.NavWindowingTarget;
+ g.NavWindowingTarget = NULL;
+ }
+ }
+
+ // Keyboard: Focus
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard)
+ {
+ // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
+ if (IsKeyPressedMap(ImGuiKey_Tab, true))
+ NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1);
+ if (!g.IO.KeyCtrl)
+ apply_focus_window = g.NavWindowingTarget;
+ }
+
+ // Keyboard: Press and Release ALT to toggle menu layer
+ // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB
+ if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released))
+ if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev))
+ apply_toggle_layer = true;
+
+ // Move window
+ if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
+ {
+ ImVec2 move_delta;
+ if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift)
+ move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down);
+ if (g.NavInputSource == ImGuiInputSource_NavGamepad)
+ move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down);
+ if (move_delta.x != 0.0f || move_delta.y != 0.0f)
+ {
+ const float NAV_MOVE_SPEED = 800.0f;
+ const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't code variable framerate very well
+ g.NavWindowingTarget->RootWindow->Pos += move_delta * move_speed;
+ g.NavDisableMouseHover = true;
+ MarkIniSettingsDirty(g.NavWindowingTarget);
+ }
+ }
+
+ // Apply final focus
+ if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
+ {
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = true;
+ apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
+ ClosePopupsOverWindow(apply_focus_window);
+ FocusWindow(apply_focus_window);
+ if (apply_focus_window->NavLastIds[0] == 0)
+ NavInitWindow(apply_focus_window, false);
+
+ // If the window only has a menu layer, select it directly
+ if (apply_focus_window->DC.NavLayerActiveMask == (1 << ImGuiNavLayer_Menu))
+ g.NavLayer = ImGuiNavLayer_Menu;
+ }
+ if (apply_focus_window)
+ g.NavWindowingTarget = NULL;
+
+ // Apply menu/layer toggle
+ if (apply_toggle_layer && g.NavWindow)
+ {
+ // Move to parent menu if necessary
+ ImGuiWindow* new_nav_window = g.NavWindow;
+ while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0
+ && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
+ && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
+ new_nav_window = new_nav_window->ParentWindow;
+ if (new_nav_window != g.NavWindow)
+ {
+ ImGuiWindow* old_nav_window = g.NavWindow;
+ FocusWindow(new_nav_window);
+ new_nav_window->NavLastChildNavWindow = old_nav_window;
+ }
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = true;
+ NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main);
+ }
+}
+
+// Window has already passed the IsWindowNavFocusable()
+static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
+{
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ return "(Popup)";
+ if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0)
+ return "(Main menu bar)";
+ return "(Untitled)";
+}
+
+// Overlay displayed when using CTRL+TAB. Called by EndFrame().
+void ImGui::NavUpdateWindowingList()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindowingTarget != NULL);
+
+ if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
+ return;
+
+ if (g.NavWindowingList == NULL)
+ g.NavWindowingList = FindWindowByName("###NavWindowingList");
+ SetNextWindowSizeConstraints(ImVec2(g.IO.DisplaySize.x * 0.20f, g.IO.DisplaySize.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
+ SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
+ PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f);
+ Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
+ for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
+ {
+ ImGuiWindow* window = g.WindowsFocusOrder[n];
+ if (!IsWindowNavFocusable(window))
+ continue;
+ const char* label = window->Name;
+ if (label == FindRenderedTextEnd(label))
+ label = GetFallbackWindowNameForWindowingList(window);
+ Selectable(label, g.NavWindowingTarget == window);
+ }
+ End();
+ PopStyleVar();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] COLUMNS
+// In the current version, Columns are very weak. Needs to be replaced with a more full-featured system.
+//-----------------------------------------------------------------------------
+
+void ImGui::NextColumn()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems || window->DC.ColumnsSet == NULL)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ PopItemWidth();
+ PopClipRect();
+
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
+ if (++columns->Current < columns->Count)
+ {
+ // Columns 1+ cancel out IndentX
+ window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x;
+ window->DrawList->ChannelsSetCurrent(columns->Current);
+ }
+ else
+ {
+ window->DC.ColumnsOffset.x = 0.0f;
+ window->DrawList->ChannelsSetCurrent(0);
+ columns->Current = 0;
+ columns->LineMinY = columns->LineMaxY;
+ }
+ window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+ window->DC.CursorPos.y = columns->LineMinY;
+ window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
+ window->DC.CurrentLineTextBaseOffset = 0.0f;
+
+ PushColumnClipRect();
+ PushItemWidth(GetColumnWidth() * 0.65f); // FIXME: Move on columns setup
+}
+
+int ImGui::GetColumnIndex()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0;
+}
+
+int ImGui::GetColumnsCount()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1;
+}
+
+static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm)
+{
+ return offset_norm * (columns->MaxX - columns->MinX);
+}
+
+static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset)
+{
+ return offset / (columns->MaxX - columns->MinX);
+}
+
+static inline float GetColumnsRectHalfWidth() { return 4.0f; }
+
+static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index)
+{
+ // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing
+ // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
+ IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
+
+ float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x;
+ x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
+ if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths))
+ x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
+
+ return x;
+}
+
+float ImGui::GetColumnOffset(int column_index)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ IM_ASSERT(columns != NULL);
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ IM_ASSERT(column_index < columns->Columns.Size);
+
+ const float t = columns->Columns[column_index].OffsetNorm;
+ const float x_offset = ImLerp(columns->MinX, columns->MaxX, t);
+ return x_offset;
+}
+
+static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false)
+{
+ if (column_index < 0)
+ column_index = columns->Current;
+
+ float offset_norm;
+ if (before_resize)
+ offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize;
+ else
+ offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm;
+ return OffsetNormToPixels(columns, offset_norm);
+}
+
+float ImGui::GetColumnWidth(int column_index)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ IM_ASSERT(columns != NULL);
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm);
+}
+
+void ImGui::SetColumnOffset(int column_index, float offset)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ IM_ASSERT(columns != NULL);
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ IM_ASSERT(column_index < columns->Columns.Size);
+
+ const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1);
+ const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
+
+ if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
+ offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
+ columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->MinX);
+
+ if (preserve_width)
+ SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
+}
+
+void ImGui::SetColumnWidth(int column_index, float width)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ IM_ASSERT(columns != NULL);
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width);
+}
+
+void ImGui::PushColumnClipRect(int column_index)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ if (column_index < 0)
+ column_index = columns->Current;
+
+ PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false);
+}
+
+static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id)
+{
+ for (int n = 0; n < window->ColumnsStorage.Size; n++)
+ if (window->ColumnsStorage[n].ID == id)
+ return &window->ColumnsStorage[n];
+
+ window->ColumnsStorage.push_back(ImGuiColumnsSet());
+ ImGuiColumnsSet* columns = &window->ColumnsStorage.back();
+ columns->ID = id;
+ return columns;
+}
+
+void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ IM_ASSERT(columns_count > 1);
+ IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported
+
+ // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget.
+ // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer.
+ PushID(0x11223347 + (str_id ? 0 : columns_count));
+ ImGuiID id = window->GetID(str_id ? str_id : "columns");
+ PopID();
+
+ // Acquire storage for the columns set
+ ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id);
+ IM_ASSERT(columns->ID == id);
+ columns->Current = 0;
+ columns->Count = columns_count;
+ columns->Flags = flags;
+ window->DC.ColumnsSet = columns;
+
+ // Set state for first column
+ const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x);
+ columns->MinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
+ columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f);
+ columns->StartPosY = window->DC.CursorPos.y;
+ columns->StartMaxPosX = window->DC.CursorMaxPos.x;
+ columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
+ window->DC.ColumnsOffset.x = 0.0f;
+ window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+
+ // Clear data if columns count changed
+ if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1)
+ columns->Columns.resize(0);
+
+ // Initialize defaults
+ columns->IsFirstFrame = (columns->Columns.Size == 0);
+ if (columns->Columns.Size == 0)
+ {
+ columns->Columns.reserve(columns_count + 1);
+ for (int n = 0; n < columns_count + 1; n++)
+ {
+ ImGuiColumnData column;
+ column.OffsetNorm = n / (float)columns_count;
+ columns->Columns.push_back(column);
+ }
+ }
+
+ for (int n = 0; n < columns_count; n++)
+ {
+ // Compute clipping rectangle
+ ImGuiColumnData* column = &columns->Columns[n];
+ float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f);
+ float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
+ column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);
+ column->ClipRect.ClipWith(window->ClipRect);
+ }
+
+ window->DrawList->ChannelsSplit(columns->Count);
+ PushColumnClipRect();
+ PushItemWidth(GetColumnWidth() * 0.65f);
+}
+
+void ImGui::EndColumns()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ ImGuiColumnsSet* columns = window->DC.ColumnsSet;
+ IM_ASSERT(columns != NULL);
+
+ PopItemWidth();
+ PopClipRect();
+ window->DrawList->ChannelsMerge();
+
+ columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
+ window->DC.CursorPos.y = columns->LineMaxY;
+ if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize))
+ window->DC.CursorMaxPos.x = columns->StartMaxPosX; // Restore cursor max pos, as columns don't grow parent
+
+ // Draw columns borders and handle resize
+ bool is_being_resized = false;
+ if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
+ {
+ const float y1 = columns->StartPosY;
+ const float y2 = window->DC.CursorPos.y;
+ int dragging_column = -1;
+ for (int n = 1; n < columns->Count; n++)
+ {
+ float x = window->Pos.x + GetColumnOffset(n);
+ const ImGuiID column_id = columns->ID + ImGuiID(n);
+ const float column_hw = GetColumnsRectHalfWidth(); // Half-width for interaction
+ const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2));
+ KeepAliveID(column_id);
+ if (IsClippedEx(column_rect, column_id, false))
+ continue;
+
+ bool hovered = false, held = false;
+ if (!(columns->Flags & ImGuiColumnsFlags_NoResize))
+ {
+ ButtonBehavior(column_rect, column_id, &hovered, &held);
+ if (hovered || held)
+ g.MouseCursor = ImGuiMouseCursor_ResizeEW;
+ if (held && !(columns->Columns[n].Flags & ImGuiColumnsFlags_NoResize))
+ dragging_column = n;
+ }
+
+ // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.)
+ const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
+ const float xi = (float)(int)x;
+ window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col);
+ }
+
+ // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
+ if (dragging_column != -1)
+ {
+ if (!columns->IsBeingResized)
+ for (int n = 0; n < columns->Count + 1; n++)
+ columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm;
+ columns->IsBeingResized = is_being_resized = true;
+ float x = GetDraggedColumnOffset(columns, dragging_column);
+ SetColumnOffset(dragging_column, x);
+ }
+ }
+ columns->IsBeingResized = is_being_resized;
+
+ window->DC.ColumnsSet = NULL;
+ window->DC.ColumnsOffset.x = 0.0f;
+ window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+}
+
+// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing]
+void ImGui::Columns(int columns_count, const char* id, bool border)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ IM_ASSERT(columns_count >= 1);
+
+ ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder);
+ //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior
+ if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags)
+ return;
+
+ if (window->DC.ColumnsSet != NULL)
+ EndColumns();
+
+ if (columns_count != 1)
+ BeginColumns(id, columns_count, flags);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] DRAG AND DROP
+//-----------------------------------------------------------------------------
+
+void ImGui::ClearDragDrop()
+{
+ ImGuiContext& g = *GImGui;
+ g.DragDropActive = false;
+ g.DragDropPayload.Clear();
+ g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
+ g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0;
+ g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
+ g.DragDropAcceptFrameCount = -1;
+
+ g.DragDropPayloadBufHeap.clear();
+ memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
+}
+
+// Call when current ID is active.
+// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource()
+bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ bool source_drag_active = false;
+ ImGuiID source_id = 0;
+ ImGuiID source_parent_id = 0;
+ int mouse_button = 0;
+ if (!(flags & ImGuiDragDropFlags_SourceExtern))
+ {
+ source_id = window->DC.LastItemId;
+ if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case
+ return false;
+ if (g.IO.MouseDown[mouse_button] == false)
+ return false;
+
+ if (source_id == 0)
+ {
+ // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
+ // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
+ if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
+ {
+ IM_ASSERT(0);
+ return false;
+ }
+
+ // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image()
+ // We build a throwaway ID based on current ID stack + relative AABB of items in window.
+ // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
+ // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
+ bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0;
+ if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
+ return false;
+ source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
+ if (is_hovered)
+ SetHoveredID(source_id);
+ if (is_hovered && g.IO.MouseClicked[mouse_button])
+ {
+ SetActiveID(source_id, window);
+ FocusWindow(window);
+ }
+ if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
+ g.ActiveIdAllowOverlap = is_hovered;
+ }
+ else
+ {
+ g.ActiveIdAllowOverlap = false;
+ }
+ if (g.ActiveId != source_id)
+ return false;
+ source_parent_id = window->IDStack.back();
+ source_drag_active = IsMouseDragging(mouse_button);
+ }
+ else
+ {
+ window = NULL;
+ source_id = ImHash("#SourceExtern", 0);
+ source_drag_active = true;
+ }
+
+ if (source_drag_active)
+ {
+ if (!g.DragDropActive)
+ {
+ IM_ASSERT(source_id != 0);
+ ClearDragDrop();
+ ImGuiPayload& payload = g.DragDropPayload;
+ payload.SourceId = source_id;
+ payload.SourceParentId = source_parent_id;
+ g.DragDropActive = true;
+ g.DragDropSourceFlags = flags;
+ g.DragDropMouseButton = mouse_button;
+ }
+ g.DragDropSourceFrameCount = g.FrameCount;
+ g.DragDropWithinSourceOrTarget = true;
+
+ if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+ {
+ // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
+ // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
+ BeginTooltip();
+ if (g.DragDropActive && g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
+ {
+ ImGuiWindow* tooltip_window = g.CurrentWindow;
+ tooltip_window->SkipItems = true;
+ tooltip_window->HiddenFramesRegular = 1;
+ }
+ }
+
+ if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
+ window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
+
+ return true;
+ }
+ return false;
+}
+
+void ImGui::EndDragDropSource()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.DragDropActive);
+ IM_ASSERT(g.DragDropWithinSourceOrTarget && "Not after a BeginDragDropSource()?");
+
+ if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+ EndTooltip();
+
+ // Discard the drag if have not called SetDragDropPayload()
+ if (g.DragDropPayload.DataFrameCount == -1)
+ ClearDragDrop();
+ g.DragDropWithinSourceOrTarget = false;
+}
+
+// Use 'cond' to choose to submit payload on drag start or every frame
+bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiPayload& payload = g.DragDropPayload;
+ if (cond == 0)
+ cond = ImGuiCond_Always;
+
+ IM_ASSERT(type != NULL);
+ IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
+ IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
+ IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
+ IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
+
+ if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
+ {
+ // Copy payload
+ ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
+ g.DragDropPayloadBufHeap.resize(0);
+ if (data_size > sizeof(g.DragDropPayloadBufLocal))
+ {
+ // Store in heap
+ g.DragDropPayloadBufHeap.resize((int)data_size);
+ payload.Data = g.DragDropPayloadBufHeap.Data;
+ memcpy(payload.Data, data, data_size);
+ }
+ else if (data_size > 0)
+ {
+ // Store locally
+ memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
+ payload.Data = g.DragDropPayloadBufLocal;
+ memcpy(payload.Data, data, data_size);
+ }
+ else
+ {
+ payload.Data = NULL;
+ }
+ payload.DataSize = (int)data_size;
+ }
+ payload.DataFrameCount = g.FrameCount;
+
+ return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1);
+}
+
+bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.DragDropActive)
+ return false;
+
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
+ return false;
+ IM_ASSERT(id != 0);
+ if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
+ return false;
+ if (window->SkipItems)
+ return false;
+
+ IM_ASSERT(g.DragDropWithinSourceOrTarget == false);
+ g.DragDropTargetRect = bb;
+ g.DragDropTargetId = id;
+ g.DragDropWithinSourceOrTarget = true;
+ return true;
+}
+
+// We don't use BeginDragDropTargetCustom() and duplicate its code because:
+// 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them.
+// 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can.
+// Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case)
+bool ImGui::BeginDragDropTarget()
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.DragDropActive)
+ return false;
+
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
+ return false;
+ if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
+ return false;
+
+ const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
+ ImGuiID id = window->DC.LastItemId;
+ if (id == 0)
+ id = window->GetIDFromRectangle(display_rect);
+ if (g.DragDropPayload.SourceId == id)
+ return false;
+
+ IM_ASSERT(g.DragDropWithinSourceOrTarget == false);
+ g.DragDropTargetRect = display_rect;
+ g.DragDropTargetId = id;
+ g.DragDropWithinSourceOrTarget = true;
+ return true;
+}
+
+bool ImGui::IsDragDropPayloadBeingAccepted()
+{
+ ImGuiContext& g = *GImGui;
+ return g.DragDropActive && g.DragDropAcceptIdPrev != 0;
+}
+
+const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiPayload& payload = g.DragDropPayload;
+ IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ?
+ IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ?
+ if (type != NULL && !payload.IsDataType(type))
+ return NULL;
+
+ // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints.
+ // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function!
+ const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId);
+ ImRect r = g.DragDropTargetRect;
+ float r_surface = r.GetWidth() * r.GetHeight();
+ if (r_surface < g.DragDropAcceptIdCurrRectSurface)
+ {
+ g.DragDropAcceptFlags = flags;
+ g.DragDropAcceptIdCurr = g.DragDropTargetId;
+ g.DragDropAcceptIdCurrRectSurface = r_surface;
+ }
+
+ // Render default drop visuals
+ payload.Preview = was_accepted_previously;
+ flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
+ if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
+ {
+ // FIXME-DRAG: Settle on a proper default visuals for drop target.
+ r.Expand(3.5f);
+ bool push_clip_rect = !window->ClipRect.Contains(r);
+ if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1));
+ window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
+ if (push_clip_rect) window->DrawList->PopClipRect();
+ }
+
+ g.DragDropAcceptFrameCount = g.FrameCount;
+ payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()
+ if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
+ return NULL;
+
+ return &payload;
+}
+
+const ImGuiPayload* ImGui::GetDragDropPayload()
+{
+ ImGuiContext& g = *GImGui;
+ return g.DragDropActive ? &g.DragDropPayload : NULL;
+}
+
+// We don't really use/need this now, but added it for the sake of consistency and because we might need it later.
+void ImGui::EndDragDropTarget()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.DragDropActive);
+ IM_ASSERT(g.DragDropWithinSourceOrTarget);
+ g.DragDropWithinSourceOrTarget = false;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] DOCKING
+//-----------------------------------------------------------------------------
+
+// (this section is filled in the 'docking' branch)
+
+//-----------------------------------------------------------------------------
+// [SECTION] LOGGING/CAPTURING
+//-----------------------------------------------------------------------------
+
+// Pass text data straight to log (without being displayed)
+void ImGui::LogText(const char* fmt, ...)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ va_list args;
+ va_start(args, fmt);
+ if (g.LogFile)
+ vfprintf(g.LogFile, fmt, args);
+ else
+ g.LogClipboard.appendfv(fmt, args);
+ va_end(args);
+}
+
+// Internal version that takes a position to decide on newline placement and pad items according to their depth.
+// We split text into individual lines to add current tree level padding
+void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (!text_end)
+ text_end = FindRenderedTextEnd(text, text_end);
+
+ const bool log_new_line = ref_pos && (ref_pos->y > window->DC.LogLinePosY + 1);
+ if (ref_pos)
+ window->DC.LogLinePosY = ref_pos->y;
+
+ const char* text_remaining = text;
+ if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
+ g.LogStartDepth = window->DC.TreeDepth;
+ const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
+ for (;;)
+ {
+ // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
+ const char* line_start = text_remaining;
+ const char* line_end = ImStreolRange(line_start, text_end);
+ const bool is_first_line = (line_start == text);
+ const bool is_last_line = (line_end == text_end);
+ if (!is_last_line || (line_start != line_end))
+ {
+ const int char_count = (int)(line_end - line_start);
+ if (log_new_line || !is_first_line)
+ LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, line_start);
+ else
+ LogText(" %.*s", char_count, line_start);
+ }
+
+ if (is_last_line)
+ break;
+ text_remaining = line_end + 1;
+ }
+}
+
+// Start logging ImGui output to TTY
+void ImGui::LogToTTY(int max_depth)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ IM_ASSERT(g.LogFile == NULL);
+ g.LogFile = stdout;
+ g.LogEnabled = true;
+ g.LogStartDepth = window->DC.TreeDepth;
+ if (max_depth >= 0)
+ g.LogAutoExpandMaxDepth = max_depth;
+}
+
+// Start logging ImGui output to given file
+void ImGui::LogToFile(int max_depth, const char* filename)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (!filename)
+ {
+ filename = g.IO.LogFilename;
+ if (!filename)
+ return;
+ }
+
+ IM_ASSERT(g.LogFile == NULL);
+ g.LogFile = ImFileOpen(filename, "ab");
+ if (!g.LogFile)
+ {
+ IM_ASSERT(g.LogFile != NULL); // Consider this an error
+ return;
+ }
+ g.LogEnabled = true;
+ g.LogStartDepth = window->DC.TreeDepth;
+ if (max_depth >= 0)
+ g.LogAutoExpandMaxDepth = max_depth;
+}
+
+// Start logging ImGui output to clipboard
+void ImGui::LogToClipboard(int max_depth)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ IM_ASSERT(g.LogFile == NULL);
+ g.LogFile = NULL;
+ g.LogEnabled = true;
+ g.LogStartDepth = window->DC.TreeDepth;
+ if (max_depth >= 0)
+ g.LogAutoExpandMaxDepth = max_depth;
+}
+
+void ImGui::LogFinish()
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ LogText(IM_NEWLINE);
+ if (g.LogFile != NULL)
+ {
+ if (g.LogFile == stdout)
+ fflush(g.LogFile);
+ else
+ fclose(g.LogFile);
+ g.LogFile = NULL;
+ }
+ if (g.LogClipboard.size() > 1)
+ {
+ SetClipboardText(g.LogClipboard.begin());
+ g.LogClipboard.clear();
+ }
+ g.LogEnabled = false;
+}
+
+// Helper to display logging buttons
+void ImGui::LogButtons()
+{
+ ImGuiContext& g = *GImGui;
+
+ PushID("LogButtons");
+ const bool log_to_tty = Button("Log To TTY"); SameLine();
+ const bool log_to_file = Button("Log To File"); SameLine();
+ const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
+ PushItemWidth(80.0f);
+ PushAllowKeyboardFocus(false);
+ SliderInt("Depth", &g.LogAutoExpandMaxDepth, 0, 9, NULL);
+ PopAllowKeyboardFocus();
+ PopItemWidth();
+ PopID();
+
+ // Start logging at the end of the function so that the buttons don't appear in the log
+ if (log_to_tty)
+ LogToTTY(g.LogAutoExpandMaxDepth);
+ if (log_to_file)
+ LogToFile(g.LogAutoExpandMaxDepth, g.IO.LogFilename);
+ if (log_to_clipboard)
+ LogToClipboard(g.LogAutoExpandMaxDepth);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] SETTINGS
+//-----------------------------------------------------------------------------
+
+void ImGui::MarkIniSettingsDirty()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.SettingsDirtyTimer <= 0.0f)
+ g.SettingsDirtyTimer = g.IO.IniSavingRate;
+}
+
+void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
+ if (g.SettingsDirtyTimer <= 0.0f)
+ g.SettingsDirtyTimer = g.IO.IniSavingRate;
+}
+
+ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
+{
+ ImGuiContext& g = *GImGui;
+ g.SettingsWindows.push_back(ImGuiWindowSettings());
+ ImGuiWindowSettings* settings = &g.SettingsWindows.back();
+ settings->Name = ImStrdup(name);
+ settings->ID = ImHash(name, 0);
+ return settings;
+}
+
+ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ for (int i = 0; i != g.SettingsWindows.Size; i++)
+ if (g.SettingsWindows[i].ID == id)
+ return &g.SettingsWindows[i];
+ return NULL;
+}
+
+void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
+{
+ size_t file_data_size = 0;
+ char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size);
+ if (!file_data)
+ return;
+ LoadIniSettingsFromMemory(file_data, (size_t)file_data_size);
+ ImGui::MemFree(file_data);
+}
+
+ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiID type_hash = ImHash(type_name, 0, 0);
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
+ return &g.SettingsHandlers[handler_n];
+ return NULL;
+}
+
+// Zero-tolerance, no error reporting, cheap .ini parsing
+void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Initialized);
+ IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0);
+
+ // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
+ // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
+ if (ini_size == 0)
+ ini_size = strlen(ini_data);
+ char* buf = (char*)ImGui::MemAlloc(ini_size + 1);
+ char* buf_end = buf + ini_size;
+ memcpy(buf, ini_data, ini_size);
+ buf[ini_size] = 0;
+
+ void* entry_data = NULL;
+ ImGuiSettingsHandler* entry_handler = NULL;
+
+ char* line_end = NULL;
+ for (char* line = buf; line < buf_end; line = line_end + 1)
+ {
+ // Skip new lines markers, then find end of the line
+ while (*line == '\n' || *line == '\r')
+ line++;
+ line_end = line;
+ while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
+ line_end++;
+ line_end[0] = 0;
+ if (line[0] == ';')
+ continue;
+ if (line[0] == '[' && line_end > line && line_end[-1] == ']')
+ {
+ // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
+ line_end[-1] = 0;
+ const char* name_end = line_end - 1;
+ const char* type_start = line + 1;
+ char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']');
+ const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL;
+ if (!type_end || !name_start)
+ {
+ name_start = type_start; // Import legacy entries that have no type
+ type_start = "Window";
+ }
+ else
+ {
+ *type_end = 0; // Overwrite first ']'
+ name_start++; // Skip second '['
+ }
+ entry_handler = FindSettingsHandler(type_start);
+ entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL;
+ }
+ else if (entry_handler != NULL && entry_data != NULL)
+ {
+ // Let type handler parse the line
+ entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
+ }
+ }
+ ImGui::MemFree(buf);
+ g.SettingsLoaded = true;
+}
+
+void ImGui::SaveIniSettingsToDisk(const char* ini_filename)
+{
+ ImGuiContext& g = *GImGui;
+ g.SettingsDirtyTimer = 0.0f;
+ if (!ini_filename)
+ return;
+
+ size_t ini_data_size = 0;
+ const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
+ FILE* f = ImFileOpen(ini_filename, "wt");
+ if (!f)
+ return;
+ fwrite(ini_data, sizeof(char), ini_data_size, f);
+ fclose(f);
+}
+
+// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer
+const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
+{
+ ImGuiContext& g = *GImGui;
+ g.SettingsDirtyTimer = 0.0f;
+ g.SettingsIniData.Buf.resize(0);
+ g.SettingsIniData.Buf.push_back(0);
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ {
+ ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n];
+ handler->WriteAllFn(&g, handler, &g.SettingsIniData);
+ }
+ if (out_size)
+ *out_size = (size_t)g.SettingsIniData.size();
+ return g.SettingsIniData.c_str();
+}
+
+static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
+{
+ ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHash(name, 0));
+ if (!settings)
+ settings = ImGui::CreateNewWindowSettings(name);
+ return (void*)settings;
+}
+
+static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line)
+{
+ ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
+ float x, y;
+ int i;
+ if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) settings->Pos = ImVec2(x, y);
+ else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize);
+ else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0);
+}
+
+static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
+{
+ // Gather data from windows that were active during this session
+ // (if a window wasn't opened in this session we preserve its settings)
+ ImGuiContext& g = *imgui_ctx;
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
+ continue;
+
+ ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID);
+ if (!settings)
+ {
+ settings = ImGui::CreateNewWindowSettings(window->Name);
+ window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
+ }
+ IM_ASSERT(settings->ID == window->ID);
+ settings->Pos = window->Pos;
+ settings->Size = window->SizeFull;
+ settings->Collapsed = window->Collapsed;
+ }
+
+ // Write to text buffer
+ buf->reserve(buf->size() + g.SettingsWindows.Size * 96); // ballpark reserve
+ for (int i = 0; i != g.SettingsWindows.Size; i++)
+ {
+ const ImGuiWindowSettings* settings = &g.SettingsWindows[i];
+ if (settings->Pos.x == FLT_MAX)
+ continue;
+ const char* name = settings->Name;
+ if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
+ name = p;
+ buf->appendf("[%s][%s]\n", handler->TypeName, name);
+ buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
+ buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
+ buf->appendf("Collapsed=%d\n", settings->Collapsed);
+ buf->appendf("\n");
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] PLATFORM DEPENDENT HELPERS
+//-----------------------------------------------------------------------------
+
+#if defined(_WIN32) && !defined(_WINDOWS_) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS))
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef __MINGW32__
+#include <Windows.h>
+#else
+#include <windows.h>
+#endif
+#endif
+
+// Win32 API clipboard implementation
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
+
+#ifdef _MSC_VER
+#pragma comment(lib, "user32")
+#endif
+
+static const char* GetClipboardTextFn_DefaultImpl(void*)
+{
+ static ImVector<char> buf_local;
+ buf_local.clear();
+ if (!::OpenClipboard(NULL))
+ return NULL;
+ HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
+ if (wbuf_handle == NULL)
+ {
+ ::CloseClipboard();
+ return NULL;
+ }
+ if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle))
+ {
+ int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
+ buf_local.resize(buf_len);
+ ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL);
+ }
+ ::GlobalUnlock(wbuf_handle);
+ ::CloseClipboard();
+ return buf_local.Data;
+}
+
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
+{
+ if (!::OpenClipboard(NULL))
+ return;
+ const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
+ HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
+ if (wbuf_handle == NULL)
+ {
+ ::CloseClipboard();
+ return;
+ }
+ ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle);
+ ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
+ ::GlobalUnlock(wbuf_handle);
+ ::EmptyClipboard();
+ if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
+ ::GlobalFree(wbuf_handle);
+ ::CloseClipboard();
+}
+
+#else
+
+// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
+static const char* GetClipboardTextFn_DefaultImpl(void*)
+{
+ ImGuiContext& g = *GImGui;
+ return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin();
+}
+
+// Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
+{
+ ImGuiContext& g = *GImGui;
+ g.PrivateClipboard.clear();
+ const char* text_end = text + strlen(text);
+ g.PrivateClipboard.resize((int)(text_end - text) + 1);
+ memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text));
+ g.PrivateClipboard[(int)(text_end - text)] = 0;
+}
+
+#endif
+
+// Win32 API IME support (for Asian languages, etc.)
+#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
+
+#include <imm.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "imm32")
+#endif
+
+static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
+{
+ // Notify OS Input Method Editor of text input position
+ if (HWND hwnd = (HWND)GImGui->IO.ImeWindowHandle)
+ if (HIMC himc = ::ImmGetContext(hwnd))
+ {
+ COMPOSITIONFORM cf;
+ cf.ptCurrentPos.x = x;
+ cf.ptCurrentPos.y = y;
+ cf.dwStyle = CFS_FORCE_POSITION;
+ ::ImmSetCompositionWindow(himc, &cf);
+ ::ImmReleaseContext(hwnd, himc);
+ }
+}
+
+#else
+
+static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] METRICS/DEBUG WINDOW
+//-----------------------------------------------------------------------------
+
+void ImGui::ShowMetricsWindow(bool* p_open)
+{
+ if (!ImGui::Begin("ImGui Metrics", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ static bool show_draw_cmd_clip_rects = true;
+ static bool show_window_begin_order = false;
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+ ImGui::Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
+ ImGui::Text("%d active windows (%d visible)", io.MetricsActiveWindows, io.MetricsRenderWindows);
+ ImGui::Text("%d allocations", io.MetricsActiveAllocations);
+ ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_draw_cmd_clip_rects);
+ ImGui::Checkbox("Ctrl shows window begin order", &show_window_begin_order);
+ ImGui::Separator();
+
+ struct Funcs
+ {
+ static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label)
+ {
+ bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size);
+ if (draw_list == ImGui::GetWindowDrawList())
+ {
+ ImGui::SameLine();
+ ImGui::TextColored(ImColor(255,100,100), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
+ if (node_open) ImGui::TreePop();
+ return;
+ }
+
+ ImDrawList* overlay_draw_list = GetOverlayDrawList(window); // Render additional visuals into the top-most draw list
+ if (window && IsItemHovered())
+ overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
+ if (!node_open)
+ return;
+
+ int elem_offset = 0;
+ for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++)
+ {
+ if (pcmd->UserCallback == NULL && pcmd->ElemCount == 0)
+ continue;
+ if (pcmd->UserCallback)
+ {
+ ImGui::BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
+ continue;
+ }
+ ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
+ bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
+ if (show_draw_cmd_clip_rects && ImGui::IsItemHovered())
+ {
+ ImRect clip_rect = pcmd->ClipRect;
+ ImRect vtxs_rect;
+ for (int i = elem_offset; i < elem_offset + (int)pcmd->ElemCount; i++)
+ vtxs_rect.Add(draw_list->VtxBuffer[idx_buffer ? idx_buffer[i] : i].pos);
+ clip_rect.Floor(); overlay_draw_list->AddRect(clip_rect.Min, clip_rect.Max, IM_COL32(255,255,0,255));
+ vtxs_rect.Floor(); overlay_draw_list->AddRect(vtxs_rect.Min, vtxs_rect.Max, IM_COL32(255,0,255,255));
+ }
+ if (!pcmd_node_open)
+ continue;
+
+ // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
+ ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
+ while (clipper.Step())
+ for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++)
+ {
+ char buf[300];
+ char *buf_p = buf, *buf_end = buf + IM_ARRAYSIZE(buf);
+ ImVec2 triangles_pos[3];
+ for (int n = 0; n < 3; n++, vtx_i++)
+ {
+ ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i];
+ triangles_pos[n] = v.pos;
+ buf_p += ImFormatString(buf_p, (int)(buf_end - buf_p), "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
+ }
+ ImGui::Selectable(buf, false);
+ if (ImGui::IsItemHovered())
+ {
+ ImDrawListFlags backup_flags = overlay_draw_list->Flags;
+ overlay_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines at is more readable for very large and thin triangles.
+ overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f);
+ overlay_draw_list->Flags = backup_flags;
+ }
+ }
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ static void NodeWindows(ImVector<ImGuiWindow*>& windows, const char* label)
+ {
+ if (!ImGui::TreeNode(label, "%s (%d)", label, windows.Size))
+ return;
+ for (int i = 0; i < windows.Size; i++)
+ Funcs::NodeWindow(windows[i], "Window");
+ ImGui::TreePop();
+ }
+
+ static void NodeWindow(ImGuiWindow* window, const char* label)
+ {
+ if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window))
+ return;
+ ImGuiWindowFlags flags = window->Flags;
+ NodeDrawList(window, window->DrawList, "DrawList");
+ ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y);
+ ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
+ (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "",
+ (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "",
+ (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : "");
+ ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetWindowScrollMaxX(window), window->Scroll.y, GetWindowScrollMaxY(window));
+ ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
+ ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems);
+ ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask);
+ ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
+ if (!window->NavRectRel[0].IsInverted())
+ ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y);
+ else
+ ImGui::BulletText("NavRectRel[0]: <None>");
+ if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
+ if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow");
+ if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
+ if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
+ {
+ for (int n = 0; n < window->ColumnsStorage.Size; n++)
+ {
+ const ImGuiColumnsSet* columns = &window->ColumnsStorage[n];
+ if (ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
+ {
+ ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX);
+ for (int column_n = 0; column_n < columns->Columns.Size; column_n++)
+ ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm));
+ ImGui::TreePop();
+ }
+ }
+ ImGui::TreePop();
+ }
+ ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));
+ ImGui::TreePop();
+ }
+
+ static void NodeTabBar(ImGuiTabBar* tab_bar)
+ {
+ // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernable strings.
+ char buf[256];
+ char* p = buf;
+ const char* buf_end = buf + IM_ARRAYSIZE(buf);
+ p += ImFormatString(p, buf_end - p, "TabBar (%d tabs)%s",
+ tab_bar->Tabs.Size, (tab_bar->PrevFrameVisible < ImGui::GetFrameCount() - 2) ? " *Inactive*" : "");
+ if (ImGui::TreeNode(tab_bar, "%s", buf))
+ {
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ ImGui::PushID(tab);
+ if (ImGui::SmallButton("<")) { TabBarQueueChangeTabOrder(tab_bar, tab, -1); } ImGui::SameLine(0, 2);
+ if (ImGui::SmallButton(">")) { TabBarQueueChangeTabOrder(tab_bar, tab, +1); } ImGui::SameLine();
+ ImGui::Text("%02d%c Tab 0x%08X", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID);
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+ }
+ };
+
+ // Access private state, we are going to display the draw lists from last frame
+ ImGuiContext& g = *GImGui;
+ Funcs::NodeWindows(g.Windows, "Windows");
+ if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size))
+ {
+ for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++)
+ Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList");
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))
+ {
+ for (int i = 0; i < g.OpenPopupStack.Size; i++)
+ {
+ ImGuiWindow* window = g.OpenPopupStack[i].Window;
+ ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : "");
+ }
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.Data.Size))
+ {
+ for (int n = 0; n < g.TabBars.Data.Size; n++)
+ Funcs::NodeTabBar(g.TabBars.GetByIndex(n));
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("Internal state"))
+ {
+ const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
+ ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
+ ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
+ ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
+ ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]);
+ ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
+ ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
+ ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL");
+ ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
+ ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
+ ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
+ ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId);
+ ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
+ ImGui::Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL");
+ ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
+ ImGui::TreePop();
+ }
+
+
+ if (g.IO.KeyCtrl && show_window_begin_order)
+ {
+ for (int n = 0; n < g.Windows.Size; n++)
+ {
+ ImGuiWindow* window = g.Windows[n];
+ if ((window->Flags & ImGuiWindowFlags_ChildWindow) || !window->WasActive)
+ continue;
+ char buf[32];
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
+ float font_size = ImGui::GetFontSize() * 2;
+ ImDrawList* overlay_draw_list = GetOverlayDrawList(window);
+ overlay_draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
+ overlay_draw_list->AddText(NULL, font_size, window->Pos, IM_COL32(255, 255, 255, 255), buf);
+ }
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+
+// Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed.
+// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github.
+#ifdef IMGUI_INCLUDE_IMGUI_USER_INL
+#include "imgui_user.inl"
+#endif
+
+//-----------------------------------------------------------------------------
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imgui.h b/Client/ThirdParty/Box2D/extern/imgui/imgui.h
new file mode 100644
index 0000000..3ac1f0e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imgui.h
@@ -0,0 +1,2130 @@
+// dear imgui, v1.67 WIP
+// (headers)
+
+// See imgui.cpp file for documentation.
+// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code.
+// Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
+// Get latest version at https://github.com/ocornut/imgui
+
+/*
+
+Index of this file:
+// Header mess
+// Forward declarations and basic types
+// ImGui API (Dear ImGui end-user API)
+// Flags & Enumerations
+// ImVector<>
+// ImGuiStyle
+// ImGuiIO
+// Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload)
+// Obsolete functions
+// Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
+// Draw List API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListFlags, ImDrawList, ImDrawData)
+// Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
+
+*/
+
+#pragma once
+
+// Configuration file (edit imconfig.h or define IMGUI_USER_CONFIG to your own filename)
+#ifdef IMGUI_USER_CONFIG
+#include IMGUI_USER_CONFIG
+#endif
+#if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H)
+#include "imconfig.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Header mess
+//-----------------------------------------------------------------------------
+
+#include <float.h> // FLT_MAX
+#include <stdarg.h> // va_list
+#include <stddef.h> // ptrdiff_t, NULL
+#include <string.h> // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
+
+// Version
+// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY00 then bounced up to XYY01 when release tagging happens)
+#define IMGUI_VERSION "1.67 WIP"
+#define IMGUI_VERSION_NUM 16602
+#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert))
+
+// Define attributes of all API symbols declarations (e.g. for DLL under Windows)
+// IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default bindings files (imgui_impl_xxx.h)
+#ifndef IMGUI_API
+#define IMGUI_API
+#endif
+#ifndef IMGUI_IMPL_API
+#define IMGUI_IMPL_API IMGUI_API
+#endif
+
+// Helper Macros
+#ifndef IM_ASSERT
+#include <assert.h>
+#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h
+#endif
+#if defined(__clang__) || defined(__GNUC__)
+#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to user functions.
+#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))
+#else
+#define IM_FMTARGS(FMT)
+#define IM_FMTLIST(FMT)
+#endif
+#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers!
+#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in modern C++.
+
+// Warnings
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+#elif defined(__GNUC__) && __GNUC__ >= 8
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations and basic types
+//-----------------------------------------------------------------------------
+
+struct ImDrawChannel; // Temporary storage for ImDrawList ot output draw commands out of order, used by ImDrawList::ChannelsSplit()
+struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback)
+struct ImDrawData; // All draw command lists required to render the frame + pos/size coordinates to use for the projection matrix.
+struct ImDrawList; // A single draw command list (generally one per window, conceptually you may see this as a dynamic "mesh" builder)
+struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself)
+struct ImDrawVert; // A single vertex (pos + uv + col = 20 bytes by default. Override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT)
+struct ImFont; // Runtime data for a single font within a parent ImFontAtlas
+struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader
+struct ImFontConfig; // Configuration data when adding a font or merging fonts
+struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset)
+struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data
+struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using)
+struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h)
+struct ImGuiIO; // Main configuration and I/O between your application and ImGui
+struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
+struct ImGuiListClipper; // Helper to manually clip large list of items
+struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro
+struct ImGuiPayload; // User data payload for drag and drop operations
+struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
+struct ImGuiStorage; // Helper for key->value storage
+struct ImGuiStyle; // Runtime data for styling/colors
+struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder)
+struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbb][,ccccc]")
+
+// Typedefs and Enums/Flags (declared as int for compatibility with old C++, to allow using as flags and to not pollute the top of this file)
+// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
+#ifndef ImTextureID
+typedef void* ImTextureID; // User data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp)
+#endif
+typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string)
+typedef unsigned short ImWchar; // A single U16 character for keyboard input/display. We encode them as multi bytes UTF-8 when used in strings.
+typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
+typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for Set*()
+typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
+typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction
+typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier (ImGui-side enum)
+typedef int ImGuiNavInput; // -> enum ImGuiNavInput_ // Enum: An input identifier for navigation
+typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor identifier
+typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling
+typedef int ImDrawCornerFlags; // -> enum ImDrawCornerFlags_ // Flags: for ImDrawList::AddRect*() etc.
+typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList
+typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas
+typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags
+typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit*(), ColorPicker*()
+typedef int ImGuiColumnsFlags; // -> enum ImGuiColumnsFlags_ // Flags: for Columns(), BeginColumns()
+typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags
+typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo()
+typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for *DragDrop*()
+typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused()
+typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
+typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText*()
+typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
+typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
+typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem()
+typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode*(),CollapsingHeader()
+typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin*()
+typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data);
+typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data);
+
+// Scalar data types
+typedef signed int ImS32; // 32-bit signed integer == int
+typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
+#if defined(_MSC_VER) && !defined(__clang__)
+typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio)
+typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio)
+#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
+#include <stdint.h>
+typedef int64_t ImS64; // 64-bit signed integer (pre C++11)
+typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11)
+#else
+typedef signed long long ImS64; // 64-bit signed integer (post C++11)
+typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11)
+#endif
+
+// 2D vector (often used to store positions, sizes, etc.)
+struct ImVec2
+{
+ float x, y;
+ ImVec2() { x = y = 0.0f; }
+ ImVec2(float _x, float _y) { x = _x; y = _y; }
+ float operator[] (size_t i) const { IM_ASSERT(i <= 1); return (&x)[i]; } // We very rarely use this [] operator, the assert overhead is fine.
+#ifdef IM_VEC2_CLASS_EXTRA
+ IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2.
+#endif
+};
+
+// 4D vector (often used to store floating-point colors)
+struct ImVec4
+{
+ float x, y, z, w;
+ ImVec4() { x = y = z = w = 0.0f; }
+ ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
+#ifdef IM_VEC4_CLASS_EXTRA
+ IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4.
+#endif
+};
+
+//-----------------------------------------------------------------------------
+// ImGui: Dear ImGui end-user API
+// (Inside a namespace so you can add extra functions in your own separate file. Please don't modify imgui.cpp/.h!)
+//-----------------------------------------------------------------------------
+
+namespace ImGui
+{
+ // Context creation and access
+ // Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between imgui contexts.
+ // All those functions are not reliant on the current context.
+ IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL);
+ IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context
+ IMGUI_API ImGuiContext* GetCurrentContext();
+ IMGUI_API void SetCurrentContext(ImGuiContext* ctx);
+ IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert);
+
+ // Main
+ IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags)
+ IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame.
+ IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame().
+ IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), you likely don't need to call that yourself directly. If you don't need to render data (skipping rendering) you may call EndFrame() but you'll have wasted CPU already! If you don't need to render, better to not create any imgui windows and not call NewFrame() at all!
+ IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data. (Obsolete: optionally call io.RenderDrawListsFn if set. Nowadays, prefer calling your render function yourself.)
+ IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.)
+
+ // Demo, Debug, Information
+ IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
+ IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create about window. display Dear ImGui version, credits and build/system information.
+ IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display Dear ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc.
+ IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style)
+ IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles.
+ IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts.
+ IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls).
+ IMGUI_API const char* GetVersion(); // get the compiled version string e.g. "1.23"
+
+ // Styles
+ IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style (default)
+ IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // classic imgui style
+ IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font
+
+ // Windows
+ // - Begin() = push window to the stack and start appending to it. End() = pop window from the stack.
+ // - You may append multiple times to the same window during the same frame.
+ // - Passing 'bool* p_open != NULL' shows a window-closing widget in the upper-right corner of the window,
+ // which clicking will set the boolean to false when clicked.
+ // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting
+ // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value!
+ // [this is due to legacy reason and is inconsistent with most other functions such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc.
+ // where the EndXXX call should only be called if the corresponding BeginXXX function returned true.]
+ // - Note that the bottom of window stack always contains a window called "Debug".
+ IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);
+ IMGUI_API void End();
+
+ // Child Windows
+ // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child.
+ // - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400).
+ // - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window.
+ // Always call a matching EndChild() for each BeginChild() call, regardless of its return value [this is due to legacy reason and is inconsistent with most other functions such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function returned true.]
+ IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0);
+ IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0);
+ IMGUI_API void EndChild();
+
+ // Windows Utilities
+ // - "current window" = the window we are appending into while inside a Begin()/End() block. "next window" = next window we will Begin() into.
+ IMGUI_API bool IsWindowAppearing();
+ IMGUI_API bool IsWindowCollapsed();
+ IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options.
+ IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ!
+ IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the window, to append your own drawing primitives
+ IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList API)
+ IMGUI_API ImVec2 GetWindowSize(); // get current window size
+ IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x)
+ IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y)
+ IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates
+ IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos()
+ IMGUI_API float GetContentRegionAvailWidth(); //
+ IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates
+ IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates
+ IMGUI_API float GetWindowContentRegionWidth(); //
+
+ IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
+ IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()
+ IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints.
+ IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin()
+ IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin()
+ IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin()
+ IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground.
+ IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects.
+ IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects.
+ IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed().
+ IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus().
+ IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows
+ IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position.
+ IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis.
+ IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state
+ IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus.
+
+ // Windows Scrolling
+ IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()]
+ IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()]
+ IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X
+ IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y
+ IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()]
+ IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()]
+ IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead.
+ IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions.
+
+ // Parameters stacks (shared)
+ IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font
+ IMGUI_API void PopFont();
+ IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col);
+ IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col);
+ IMGUI_API void PopStyleColor(int count = 1);
+ IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val);
+ IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val);
+ IMGUI_API void PopStyleVar(int count = 1);
+ IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in.
+ IMGUI_API ImFont* GetFont(); // get current font
+ IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied
+ IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API
+ IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier
+ IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied
+ IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied
+
+ // Parameters stacks (current window)
+ IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side)
+ IMGUI_API void PopItemWidth();
+ IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position
+ IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space
+ IMGUI_API void PopTextWrapPos();
+ IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
+ IMGUI_API void PopAllowKeyboardFocus();
+ IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
+ IMGUI_API void PopButtonRepeat();
+
+ // Cursor / Layout
+ // - By "cursor" we mean the current output position.
+ // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down.
+ IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator.
+ IMGUI_API void SameLine(float local_pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates.
+ IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in an horizontal-layout context.
+ IMGUI_API void Spacing(); // add vertical spacing.
+ IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size. unlike InvisibleButton(), Dummy() won't take the mouse click or be navigable into.
+ IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if != 0
+ IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if != 0
+ IMGUI_API void BeginGroup(); // lock horizontal starting position
+ IMGUI_API void EndGroup(); // unlock horizontal starting position + capture the whole group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
+ IMGUI_API ImVec2 GetCursorPos(); // cursor position in window coordinates (relative to window position)
+ IMGUI_API float GetCursorPosX(); // (some functions are using window-relative coordinates, such as: GetCursorPos, GetCursorStartPos, GetContentRegionMax, GetWindowContentRegion* etc.
+ IMGUI_API float GetCursorPosY(); // other functions such as GetCursorScreenPos or everything in ImDrawList::
+ IMGUI_API void SetCursorPos(const ImVec2& local_pos); // are using the main, absolute coordinate system.
+ IMGUI_API void SetCursorPosX(float local_x); // GetWindowPos() + GetCursorPos() == GetCursorScreenPos() etc.)
+ IMGUI_API void SetCursorPosY(float local_y); //
+ IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position in window coordinates
+ IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API)
+ IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize]
+ IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item)
+ IMGUI_API float GetTextLineHeight(); // ~ FontSize
+ IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text)
+ IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2
+ IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets)
+
+ // ID stack/scopes
+ // - Read the FAQ for more details about how ID are handled in dear imgui. If you are creating widgets in a loop you most
+ // likely want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them.
+ // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others.
+ // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed and used as an ID,
+ // whereas "str_id" denote a string that is only used as an ID and not normally displayed.
+ IMGUI_API void PushID(const char* str_id); // push string identifier into the ID stack. IDs == hash of the entire stack!
+ IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end);
+ IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack.
+ IMGUI_API void PushID(int int_id); // push integer into the ID stack.
+ IMGUI_API void PopID(); // pop from the ID stack.
+ IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself
+ IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end);
+ IMGUI_API ImGuiID GetID(const void* ptr_id);
+
+ // Widgets: Text
+ IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text.
+ IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // simple formatted text
+ IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1);
+ IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
+ IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor();
+ IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1);
+ IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize().
+ IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1);
+ IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets
+ IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text()
+ IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1);
+
+ // Widgets: Main
+ // - Most widgets return true when the value has been changed or when pressed/selected
+ IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button
+ IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text
+ IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.)
+ IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape
+ IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
+ IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding
+ IMGUI_API bool Checkbox(const char* label, bool* v);
+ IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
+ IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; }
+ IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer
+ IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL);
+ IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses
+
+ // Widgets: Combo Box
+ // - The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.
+ // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose.
+ IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
+ IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true!
+ IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1);
+ IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0"
+ IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1);
+
+ // Widgets: Drags
+ // - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped and can go off-bounds.
+ // - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x
+ // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
+ // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
+ IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound
+ IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, float power = 1.0f);
+ IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d"); // If v_min >= v_max we have no bound
+ IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d");
+ IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d");
+ IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d");
+ IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL);
+ IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f);
+ IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min = NULL, const void* v_max = NULL, const char* format = NULL, float power = 1.0f);
+
+ // Widgets: Sliders
+ // - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds.
+ // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
+ IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for power curve sliders
+ IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "%.0f deg");
+ IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d");
+ IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d");
+ IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d");
+ IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d");
+ IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f);
+ IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f);
+ IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f);
+ IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d");
+ IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format = NULL, float power = 1.0f);
+
+ // Widgets: Input with Keyboard
+ // - If you want to use InputText() with a dynamic string type such as std::string or your own, see misc/cpp/imgui_stdlib.h
+ // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc.
+ IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* format = "%.6f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* v, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step = NULL, const void* step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
+
+ // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.)
+ // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can the pass the address of a first float element out of a contiguous structure, e.g. &myvector.x
+ IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
+ IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0);
+ IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
+ IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);
+ IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0)); // display a colored square/button, hover for details, return true when pressed.
+ IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.
+
+ // Widgets: Trees
+ // - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents.
+ IMGUI_API bool TreeNode(const char* label);
+ IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to completely decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet().
+ IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // "
+ IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0);
+ IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);
+ IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);
+ IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);
+ IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);
+ IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired.
+ IMGUI_API void TreePush(const void* ptr_id = NULL); // "
+ IMGUI_API void TreePop(); // ~ Unindent()+PopId()
+ IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing()
+ IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode
+ IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
+ IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop().
+ IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header
+
+ // Widgets: Selectables
+ // - A selectable highlights when hovered, and can display another color when selected.
+ // - Neighbors selectable extend their highlight bounds in order to leave no gap between them.
+ IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
+ IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
+
+ // Widgets: List Boxes
+ // - FIXME: To be consistent with all the newer API, ListBoxHeader/ListBoxFooter should in reality be called BeginListBox/EndListBox. Will rename them.
+ IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
+ IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);
+ IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. if the function return true, you can output elements then call ListBoxFooter() afterwards.
+ IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // "
+ IMGUI_API void ListBoxFooter(); // terminate the scrolling region. only call ListBoxFooter() if ListBoxHeader() returned true!
+
+ // Widgets: Data Plotting
+ IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
+ IMGUI_API void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0));
+ IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
+ IMGUI_API void PlotHistogram(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0));
+
+ // Widgets: Value() Helpers.
+ // - Those are merely shortcut to calling Text() with a format string. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace)
+ IMGUI_API void Value(const char* prefix, bool b);
+ IMGUI_API void Value(const char* prefix, int v);
+ IMGUI_API void Value(const char* prefix, unsigned int v);
+ IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL);
+
+ // Widgets: Menus
+ IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar.
+ IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true!
+ IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window).
+ IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true!
+ IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true!
+ IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true!
+ IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment
+ IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL
+
+ // Tooltips
+ IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items).
+ IMGUI_API void EndTooltip();
+ IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). overidde any previous call to SetTooltip().
+ IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
+
+ // Popups, Modals
+ // The properties of popups windows are:
+ // - They block normal mouse hovering detection outside them. (*)
+ // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
+ // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls.
+ // User can manipulate the visibility state by calling OpenPopup().
+ // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
+ // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time.
+ IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
+ IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true!
+ IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
+ IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window.
+ IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows).
+ IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside)
+ IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
+ IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors). return true when just opened.
+ IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open at the current begin-ed level of the popup stack.
+ IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup.
+
+ // Columns
+ // - You can also use SameLine(pos_x) to mimic simplified columns.
+ // - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!)
+ IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true);
+ IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished
+ IMGUI_API int GetColumnIndex(); // get current column index
+ IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column
+ IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column
+ IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f
+ IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column
+ IMGUI_API int GetColumnsCount();
+
+ // Tab Bars, Tabs
+ // [BETA API] API may evolve!
+ IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar
+ IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true!
+ IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0);// create a Tab. Returns true if the Tab is selected.
+ IMGUI_API void EndTabItem(); // only call EndTabItem() if BeginTabItem() returns true!
+ IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name.
+
+ // Logging/Capture
+ // - All text output from the interface can be captured into tty/file/clipboard. By default, tree nodes are automatically opened during logging.
+ IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty (stdout)
+ IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file
+ IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard
+ IMGUI_API void LogFinish(); // stop logging (close file, etc.)
+ IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard
+ IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed)
+
+ // Drag and Drop
+ // [BETA API] API may evolve!
+ IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource()
+ IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui.
+ IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true!
+ IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget()
+ IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released.
+ IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true!
+ IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. may return NULL. use ImGuiPayload::IsDataType() to test for the payload type.
+
+ // Clipping
+ IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect);
+ IMGUI_API void PopClipRect();
+
+ // Focus, Activation
+ // - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item"
+ IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window.
+ IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
+
+ // Item/Widgets Utilities
+ // - Most of the functions are referring to the last/previous item we submitted.
+ // - See Demo Window under "Widgets->Querying Status" for an interactive visualization of most of those functions.
+ IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options.
+ IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false)
+ IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation?
+ IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered()
+ IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling)
+ IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets.
+ IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing.
+ IMGUI_API bool IsItemDeactivatedAfterEdit(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item).
+ IMGUI_API bool IsAnyItemHovered();
+ IMGUI_API bool IsAnyItemActive();
+ IMGUI_API bool IsAnyItemFocused();
+ IMGUI_API ImVec2 GetItemRectMin(); // get upper-left bounding rectangle of the last item (screen space)
+ IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space)
+ IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
+ IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.
+
+ // Miscellaneous Utilities
+ IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped.
+ IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side.
+ IMGUI_API double GetTime(); // get global imgui time. incremented by io.DeltaTime every frame.
+ IMGUI_API int GetFrameCount(); // get global imgui frame count. incremented by 1 every frame.
+ IMGUI_API ImDrawList* GetOverlayDrawList(); // this draw list will be the last rendered one, useful to quickly draw overlays shapes/text
+ IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); // you may use this when creating your own ImDrawList instances
+ IMGUI_API const char* GetStyleColorName(ImGuiCol idx);
+ IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it)
+ IMGUI_API ImGuiStorage* GetStateStorage();
+ IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
+ IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.
+ IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame
+ IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window)
+
+ // Color Utilities
+ IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in);
+ IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in);
+ IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);
+ IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
+
+ // Inputs Utilities
+ IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key]
+ IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index]. note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]!
+ IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down). if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate
+ IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down)..
+ IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate
+ IMGUI_API bool IsMouseDown(int button); // is mouse button held (0=left, 1=right, 2=middle)
+ IMGUI_API bool IsAnyMouseDown(); // is any mouse button held
+ IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) (0=left, 1=right, 2=middle)
+ IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime.
+ IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down)
+ IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold
+ IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
+ IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); //
+ IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
+ IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse position at the time of opening popup we have BeginPopup() into
+ IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position. This is locked and return 0.0f until the mouse moves past a distance threshold at least once. If lock_threshold < -1.0f uses io.MouseDraggingThreshold
+ IMGUI_API void ResetMouseDragDelta(int button = 0); //
+ IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
+ IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type
+ IMGUI_API void CaptureKeyboardFromApp(bool want_capture_keyboard_value = true); // attention: misleading name! manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard_value"; after the next NewFrame() call.
+ IMGUI_API void CaptureMouseFromApp(bool want_capture_mouse_value = true); // attention: misleading name! manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse_value;" after the next NewFrame() call.
+
+ // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard)
+ IMGUI_API const char* GetClipboardText();
+ IMGUI_API void SetClipboardText(const char* text);
+
+ // Settings/.Ini Utilities
+ // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini").
+ // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually.
+ IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename).
+ IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source.
+ IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename);
+ IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
+
+ // Memory Utilities
+ // - All those functions are not reliant on the current context.
+ // - If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again.
+ IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data = NULL);
+ IMGUI_API void* MemAlloc(size_t size);
+ IMGUI_API void MemFree(void* ptr);
+
+} // namespace ImGui
+
+//-----------------------------------------------------------------------------
+// Flags & Enumerations
+//-----------------------------------------------------------------------------
+
+// Flags for ImGui::Begin()
+enum ImGuiWindowFlags_
+{
+ ImGuiWindowFlags_None = 0,
+ ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar
+ ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip
+ ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window
+ ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically)
+ ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set.
+ ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it
+ ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame
+ ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f).
+ ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file
+ ImGuiWindowFlags_NoMouseInputs = 1 << 9, // Disable catching mouse, hovering test with pass through.
+ ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar
+ ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section.
+ ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state
+ ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus)
+ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y)
+ ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
+ ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)
+ ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window
+ ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB)
+ ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. When used in a tab/docking context, tab is selected on closure and closure is deferred by one frame to allow code to cancel the closure (with a confirmation popup, etc.) without flicker.
+ ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
+ ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse,
+ ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
+
+ // [Internal]
+ ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!)
+ ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild()
+ ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip()
+ ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup()
+ ImGuiWindowFlags_Modal = 1 << 27, // Don't use! For internal use by BeginPopupModal()
+ ImGuiWindowFlags_ChildMenu = 1 << 28 // Don't use! For internal use by BeginMenu()
+
+ // [Obsolete]
+ //ImGuiWindowFlags_ShowBorders = 1 << 7, // --> Set style.FrameBorderSize=1.0f / style.WindowBorderSize=1.0f to enable borders around windows and items
+ //ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // --> Set io.ConfigWindowsResizeFromEdges and make sure mouse cursors are supported by back-end (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)
+};
+
+// Flags for ImGui::InputText()
+enum ImGuiInputTextFlags_
+{
+ ImGuiInputTextFlags_None = 0,
+ ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/
+ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef
+ ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z
+ ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs
+ ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus
+ ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to when the value was modified)
+ ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Callback on pressing TAB (for completion handling)
+ ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling)
+ ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer.
+ ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+ ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field
+ ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter).
+ ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally
+ ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode
+ ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode
+ ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*'
+ ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
+ ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
+ ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
+ // [Internal]
+ ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline()
+};
+
+// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*()
+enum ImGuiTreeNodeFlags_
+{
+ ImGuiTreeNodeFlags_None = 0,
+ ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
+ ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader)
+ ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one
+ ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
+ ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
+ ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
+ ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node
+ ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open.
+ ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
+ ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow
+ ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
+ //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed
+ //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
+ ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
+ ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap
+#endif
+};
+
+// Flags for ImGui::Selectable()
+enum ImGuiSelectableFlags_
+{
+ ImGuiSelectableFlags_None = 0,
+ ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window
+ ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column)
+ ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
+ ImGuiSelectableFlags_Disabled = 1 << 3 // Cannot be selected, display greyed out text
+};
+
+// Flags for ImGui::BeginCombo()
+enum ImGuiComboFlags_
+{
+ ImGuiComboFlags_None = 0,
+ ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default
+ ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo()
+ ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default)
+ ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible
+ ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible
+ ImGuiComboFlags_NoArrowButton = 1 << 5, // Display on the preview box without the square arrow button
+ ImGuiComboFlags_NoPreview = 1 << 6, // Display only a square arrow button
+ ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest
+};
+
+// Flags for ImGui::BeginTabBar()
+enum ImGuiTabBarFlags_
+{
+ ImGuiTabBarFlags_None = 0,
+ ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list
+ ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear
+ ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
+ ImGuiTabBarFlags_NoTabListPopupButton = 1 << 3,
+ ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4,
+ ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab
+ ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit
+ ImGuiTabBarFlags_FittingPolicyScroll = 1 << 7, // Add scroll buttons when tabs don't fit
+ ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll,
+ ImGuiTabBarFlags_FittingPolicyDefault_ = ImGuiTabBarFlags_FittingPolicyResizeDown
+};
+
+// Flags for ImGui::BeginTabItem()
+enum ImGuiTabItemFlags_
+{
+ ImGuiTabItemFlags_None = 0,
+ ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it without flicker.
+ ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programatically make the tab selected when calling BeginTabItem()
+ ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
+ ImGuiTabItemFlags_NoPushId = 1 << 3 // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
+};
+
+// Flags for ImGui::IsWindowFocused()
+enum ImGuiFocusedFlags_
+{
+ ImGuiFocusedFlags_None = 0,
+ ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused
+ ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy)
+ ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use ImGui::GetIO().WantCaptureMouse instead.
+ ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows
+};
+
+// Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered()
+// Note: if you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that. Please read the FAQ!
+// Note: windows with the ImGuiWindowFlags_NoInputs flag are ignored by IsWindowHovered() calls.
+enum ImGuiHoveredFlags_
+{
+ ImGuiHoveredFlags_None = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
+ ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered
+ ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy)
+ ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered
+ ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, // Return true even if a popup window is normally blocking access to this item/window
+ //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet.
+ ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
+ ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is overlapped by another window
+ ImGuiHoveredFlags_AllowWhenDisabled = 1 << 7, // Return true even if the item is disabled
+ ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
+ ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows
+};
+
+// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload()
+enum ImGuiDragDropFlags_
+{
+ ImGuiDragDropFlags_None = 0,
+ // BeginDragDropSource() flags
+ ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior.
+ ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return false, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item.
+ ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item.
+ ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit.
+ ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously.
+ ImGuiDragDropFlags_SourceAutoExpirePayload = 1 << 5, // Automatically expire the payload if the source cease to be submitted (otherwise payloads are persisting while being dragged)
+ // AcceptDragDropPayload() flags
+ ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered.
+ ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target.
+ ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site.
+ ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery.
+};
+
+// Standard Drag and Drop payload types. You can define you own payload types using short strings. Types starting with '_' are defined by Dear ImGui.
+#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type.
+#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type.
+
+// A primary data type
+enum ImGuiDataType_
+{
+ ImGuiDataType_S32, // int
+ ImGuiDataType_U32, // unsigned int
+ ImGuiDataType_S64, // long long, __int64
+ ImGuiDataType_U64, // unsigned long long, unsigned __int64
+ ImGuiDataType_Float, // float
+ ImGuiDataType_Double, // double
+ ImGuiDataType_COUNT
+};
+
+// A cardinal direction
+enum ImGuiDir_
+{
+ ImGuiDir_None = -1,
+ ImGuiDir_Left = 0,
+ ImGuiDir_Right = 1,
+ ImGuiDir_Up = 2,
+ ImGuiDir_Down = 3,
+ ImGuiDir_COUNT
+};
+
+// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array
+enum ImGuiKey_
+{
+ ImGuiKey_Tab,
+ ImGuiKey_LeftArrow,
+ ImGuiKey_RightArrow,
+ ImGuiKey_UpArrow,
+ ImGuiKey_DownArrow,
+ ImGuiKey_PageUp,
+ ImGuiKey_PageDown,
+ ImGuiKey_Home,
+ ImGuiKey_End,
+ ImGuiKey_Insert,
+ ImGuiKey_Delete,
+ ImGuiKey_Backspace,
+ ImGuiKey_Space,
+ ImGuiKey_Enter,
+ ImGuiKey_Escape,
+ ImGuiKey_A, // for text edit CTRL+A: select all
+ ImGuiKey_C, // for text edit CTRL+C: copy
+ ImGuiKey_V, // for text edit CTRL+V: paste
+ ImGuiKey_X, // for text edit CTRL+X: cut
+ ImGuiKey_Y, // for text edit CTRL+Y: redo
+ ImGuiKey_Z, // for text edit CTRL+Z: undo
+ ImGuiKey_COUNT
+};
+
+// Gamepad/Keyboard directional navigation
+// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
+// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Back-end: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame().
+// Read instructions in imgui.cpp for more details. Download PNG/PSD at http://goo.gl/9LgVZW.
+enum ImGuiNavInput_
+{
+ // Gamepad Mapping
+ ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Cross (PS4), A (Xbox), A (Switch), Space (Keyboard)
+ ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Circle (PS4), B (Xbox), B (Switch), Escape (Keyboard)
+ ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard)
+ ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard)
+ ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard)
+ ImGuiNavInput_DpadRight, //
+ ImGuiNavInput_DpadUp, //
+ ImGuiNavInput_DpadDown, //
+ ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down
+ ImGuiNavInput_LStickRight, //
+ ImGuiNavInput_LStickUp, //
+ ImGuiNavInput_LStickDown, //
+ ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch)
+ ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch)
+ ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch)
+ ImGuiNavInput_TweakFast, // faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch)
+
+ // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them.
+ // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].
+ ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt
+ ImGuiNavInput_KeyLeft_, // move left // = Arrow keys
+ ImGuiNavInput_KeyRight_, // move right
+ ImGuiNavInput_KeyUp_, // move up
+ ImGuiNavInput_KeyDown_, // move down
+ ImGuiNavInput_COUNT,
+ ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_
+};
+
+// Configuration flags stored in io.ConfigFlags. Set by user/application.
+enum ImGuiConfigFlags_
+{
+ ImGuiConfigFlags_None = 0,
+ ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[].
+ ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad.
+ ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth.
+ ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set.
+ ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information set by the back-end.
+ ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. Use if the back-end cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
+
+ // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui)
+ ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware.
+ ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse.
+};
+
+// Back-end capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom back-end.
+enum ImGuiBackendFlags_
+{
+ ImGuiBackendFlags_None = 0,
+ ImGuiBackendFlags_HasGamepad = 1 << 0, // Back-end supports gamepad and currently has one connected.
+ ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Back-end supports honoring GetMouseCursor() value to change the OS cursor shape.
+ ImGuiBackendFlags_HasSetMousePos = 1 << 2 // Back-end supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set).
+};
+
+// Enumeration for PushStyleColor() / PopStyleColor()
+enum ImGuiCol_
+{
+ ImGuiCol_Text,
+ ImGuiCol_TextDisabled,
+ ImGuiCol_WindowBg, // Background of normal windows
+ ImGuiCol_ChildBg, // Background of child windows
+ ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows
+ ImGuiCol_Border,
+ ImGuiCol_BorderShadow,
+ ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input
+ ImGuiCol_FrameBgHovered,
+ ImGuiCol_FrameBgActive,
+ ImGuiCol_TitleBg,
+ ImGuiCol_TitleBgActive,
+ ImGuiCol_TitleBgCollapsed,
+ ImGuiCol_MenuBarBg,
+ ImGuiCol_ScrollbarBg,
+ ImGuiCol_ScrollbarGrab,
+ ImGuiCol_ScrollbarGrabHovered,
+ ImGuiCol_ScrollbarGrabActive,
+ ImGuiCol_CheckMark,
+ ImGuiCol_SliderGrab,
+ ImGuiCol_SliderGrabActive,
+ ImGuiCol_Button,
+ ImGuiCol_ButtonHovered,
+ ImGuiCol_ButtonActive,
+ ImGuiCol_Header,
+ ImGuiCol_HeaderHovered,
+ ImGuiCol_HeaderActive,
+ ImGuiCol_Separator,
+ ImGuiCol_SeparatorHovered,
+ ImGuiCol_SeparatorActive,
+ ImGuiCol_ResizeGrip,
+ ImGuiCol_ResizeGripHovered,
+ ImGuiCol_ResizeGripActive,
+ ImGuiCol_Tab,
+ ImGuiCol_TabHovered,
+ ImGuiCol_TabActive,
+ ImGuiCol_TabUnfocused,
+ ImGuiCol_TabUnfocusedActive,
+ ImGuiCol_PlotLines,
+ ImGuiCol_PlotLinesHovered,
+ ImGuiCol_PlotHistogram,
+ ImGuiCol_PlotHistogramHovered,
+ ImGuiCol_TextSelectedBg,
+ ImGuiCol_DragDropTarget,
+ ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item
+ ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
+ ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active
+ ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active
+ ImGuiCol_COUNT
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiCol_ModalWindowDarkening = ImGuiCol_ModalWindowDimBg // [renamed in 1.63]
+ , ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg // [renamed in 1.53]
+ , ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive // [renamed in 1.51]
+ //ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered, // [unused since 1.60+] the close button now uses regular button colors.
+ //ImGuiCol_ComboBg, // [unused since 1.53+] ComboBg has been merged with PopupBg, so a redirect isn't accurate.
+#endif
+};
+
+// Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure.
+// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly.
+// NB: if changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.
+enum ImGuiStyleVar_
+{
+ // Enum name ......................// Member in ImGuiStyle structure (see ImGuiStyle for descriptions)
+ ImGuiStyleVar_Alpha, // float Alpha
+ ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding
+ ImGuiStyleVar_WindowRounding, // float WindowRounding
+ ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize
+ ImGuiStyleVar_WindowMinSize, // ImVec2 WindowMinSize
+ ImGuiStyleVar_WindowTitleAlign, // ImVec2 WindowTitleAlign
+ ImGuiStyleVar_ChildRounding, // float ChildRounding
+ ImGuiStyleVar_ChildBorderSize, // float ChildBorderSize
+ ImGuiStyleVar_PopupRounding, // float PopupRounding
+ ImGuiStyleVar_PopupBorderSize, // float PopupBorderSize
+ ImGuiStyleVar_FramePadding, // ImVec2 FramePadding
+ ImGuiStyleVar_FrameRounding, // float FrameRounding
+ ImGuiStyleVar_FrameBorderSize, // float FrameBorderSize
+ ImGuiStyleVar_ItemSpacing, // ImVec2 ItemSpacing
+ ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ItemInnerSpacing
+ ImGuiStyleVar_IndentSpacing, // float IndentSpacing
+ ImGuiStyleVar_ScrollbarSize, // float ScrollbarSize
+ ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding
+ ImGuiStyleVar_GrabMinSize, // float GrabMinSize
+ ImGuiStyleVar_GrabRounding, // float GrabRounding
+ ImGuiStyleVar_TabRounding, // float TabRounding
+ ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
+ ImGuiStyleVar_COUNT
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT, ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding
+#endif
+};
+
+// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
+enum ImGuiColorEditFlags_
+{
+ ImGuiColorEditFlags_None = 0,
+ ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (read 3 components from the input pointer).
+ ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on colored square.
+ ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview.
+ ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable colored square preview next to the inputs. (e.g. to show only the inputs)
+ ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview colored square).
+ ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview.
+ ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker).
+ ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small colored square preview instead.
+ ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source.
+
+ // User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions(). The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorEditOptions() during startup.
+ ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
+ ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque.
+ ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque.
+ ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
+ ImGuiColorEditFlags_RGB = 1 << 20, // [Inputs] // ColorEdit: choose one among RGB/HSV/HEX. ColorPicker: choose any combination using RGB/HSV/HEX.
+ ImGuiColorEditFlags_HSV = 1 << 21, // [Inputs] // "
+ ImGuiColorEditFlags_HEX = 1 << 22, // [Inputs] // "
+ ImGuiColorEditFlags_Uint8 = 1 << 23, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255.
+ ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
+ ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [PickerMode] // ColorPicker: bar for Hue, rectangle for Sat/Value.
+ ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [PickerMode] // ColorPicker: wheel for Hue, triangle for Sat/Value.
+
+ // [Internal] Masks
+ ImGuiColorEditFlags__InputsMask = ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_HSV|ImGuiColorEditFlags_HEX,
+ ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_Float,
+ ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel|ImGuiColorEditFlags_PickerHueBar,
+ ImGuiColorEditFlags__OptionsDefault = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_PickerHueBar // Change application default using SetColorEditOptions()
+};
+
+// Enumeration for GetMouseCursor()
+// User code may request binding to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here
+enum ImGuiMouseCursor_
+{
+ ImGuiMouseCursor_None = -1,
+ ImGuiMouseCursor_Arrow = 0,
+ ImGuiMouseCursor_TextInput, // When hovering over InputText, etc.
+ ImGuiMouseCursor_ResizeAll, // (Unused by imgui functions)
+ ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border
+ ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column
+ ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window
+ ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window
+ ImGuiMouseCursor_Hand, // (Unused by imgui functions. Use for e.g. hyperlinks)
+ ImGuiMouseCursor_COUNT
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiMouseCursor_Count_ = ImGuiMouseCursor_COUNT
+#endif
+};
+
+// Enumateration for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions
+// Represent a condition.
+// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
+enum ImGuiCond_
+{
+ ImGuiCond_Always = 1 << 0, // Set the variable
+ ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call with succeed)
+ ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file)
+ ImGuiCond_Appearing = 1 << 3 // Set the variable if the object/window is appearing after being hidden/inactive (or the first time)
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiSetCond_Always = ImGuiCond_Always, ImGuiSetCond_Once = ImGuiCond_Once, ImGuiSetCond_FirstUseEver = ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing = ImGuiCond_Appearing
+#endif
+};
+
+//-----------------------------------------------------------------------------
+// Helper: ImVector<>
+// Lightweight std::vector<>-like class to avoid dragging dependencies (also, some implementations of STL with debug enabled are absurdly slow, we bypass it so our code runs fast in debug).
+// You generally do NOT need to care or use this ever. But we need to make it available in imgui.h because some of our data structures are relying on it.
+// Important: clear() frees memory, resize(0) keep the allocated buffer. We use resize(0) a lot to intentionally recycle allocated buffers across frames and amortize our costs.
+// Important: our implementation does NOT call C++ constructors/destructors, we treat everything as raw data! This is intentional but be extra mindful of that,
+// do NOT use this class as a std::vector replacement in your own code! Many of the structures used by dear imgui can be safely initialized by a zero-memset.
+//-----------------------------------------------------------------------------
+
+template<typename T>
+struct ImVector
+{
+ int Size;
+ int Capacity;
+ T* Data;
+
+ // Provide standard typedefs but we don't use them ourselves.
+ typedef T value_type;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+
+ // Constructors, destructor
+ inline ImVector() { Size = Capacity = 0; Data = NULL; }
+ inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); }
+ inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
+ inline ~ImVector() { if (Data) ImGui::MemFree(Data); }
+
+ inline bool empty() const { return Size == 0; }
+ inline int size() const { return Size; }
+ inline int capacity() const { return Capacity; }
+ inline T& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; }
+ inline const T& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; }
+
+ inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
+ inline T* begin() { return Data; }
+ inline const T* begin() const { return Data; }
+ inline T* end() { return Data + Size; }
+ inline const T* end() const { return Data + Size; }
+ inline T& front() { IM_ASSERT(Size > 0); return Data[0]; }
+ inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; }
+ inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; }
+ inline const T& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; }
+ inline void swap(ImVector<T>& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; T* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
+
+ inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; }
+ inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }
+ inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; }
+ inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)ImGui::MemAlloc((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); ImGui::MemFree(Data); } Data = new_data; Capacity = new_capacity; }
+
+ // NB: It is illegal to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden.
+ inline void push_back(const T& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; }
+ inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
+ inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); }
+ inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
+ inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data+Size && it_last > it && it_last <= Data+Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; }
+ inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; if (it < Data+Size-1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
+ inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
+ inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; }
+ inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; return (int)off; }
+};
+
+//-----------------------------------------------------------------------------
+// ImGuiStyle
+// You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame().
+// During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values,
+// and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors.
+//-----------------------------------------------------------------------------
+
+struct ImGuiStyle
+{
+ float Alpha; // Global alpha applies to everything in ImGui.
+ ImVec2 WindowPadding; // Padding within a window.
+ float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows.
+ float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints().
+ ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
+ float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows.
+ float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding)
+ float PopupBorderSize; // Thickness of border around popup/tooltip windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets).
+ float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets).
+ float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines.
+ ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label).
+ ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
+ float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
+ float ColumnsMinSpacing; // Minimum horizontal spacing between two columns.
+ float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar.
+ float ScrollbarRounding; // Radius of grab corners for scrollbar.
+ float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.
+ float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
+ float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
+ float TabBorderSize; // Thickness of border around tabs.
+ ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered.
+ ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows.
+ ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly!
+ float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
+ bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU.
+ bool AntiAliasedFill; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
+ float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
+ ImVec4 Colors[ImGuiCol_COUNT];
+
+ IMGUI_API ImGuiStyle();
+ IMGUI_API void ScaleAllSizes(float scale_factor);
+};
+
+//-----------------------------------------------------------------------------
+// ImGuiIO
+// Communicate most settings and inputs/outputs to Dear ImGui using this structure.
+// Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage.
+//-----------------------------------------------------------------------------
+
+struct ImGuiIO
+{
+ //------------------------------------------------------------------
+ // Configuration (fill once) // Default value
+ //------------------------------------------------------------------
+
+ ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
+ ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by back-end (imgui_impl_xxx files or custom back-end) to communicate features supported by the back-end.
+ ImVec2 DisplaySize; // <unset> // Main display size, in pixels. For clamping windows positions.
+ float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
+ float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
+ const char* IniFilename; // = "imgui.ini" // Path to .ini file. Set NULL to disable automatic .ini loading/saving, if e.g. you want to manually load/save from memory.
+ const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
+ float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
+ float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
+ float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
+ int KeyMap[ImGuiKey_COUNT]; // <unset> // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state.
+ float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
+ float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
+ void* UserData; // = NULL // Store your own data for retrieval by callbacks.
+
+ ImFontAtlas*Fonts; // <auto> // Load, rasterize and pack one or more fonts into a single texture.
+ float FontGlobalScale; // = 1.0f // Global scale all fonts
+ bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel.
+ ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
+ ImVec2 DisplayFramebufferScale; // = (1.0f,1.0f) // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
+ ImVec2 DisplayVisibleMin; // <unset> // [OBSOLETE] If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.
+ ImVec2 DisplayVisibleMax; // <unset> // [OBSOLETE] Just use io.DisplaySize! If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize
+
+ // Miscellaneous configuration options
+ bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by back-end implementations.
+ bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl (was called io.OptMacOSXBehaviors prior to 1.63)
+ bool ConfigInputTextCursorBlink; // = true // Set to false to disable blinking cursor, for users who consider it distracting. (was called: io.OptCursorBlink prior to 1.63)
+ bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be the a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
+ bool ConfigWindowsMoveFromTitleBarOnly;// = false // [BETA] Set to true to only allow moving windows when clicked+dragged from the title bar. Windows without a title bar are not affected.
+
+ //------------------------------------------------------------------
+ // Platform Functions
+ // (the imgui_impl_xxxx back-end files are setting those up for you)
+ //------------------------------------------------------------------
+
+ // Optional: Platform/Renderer back-end name (informational only! will be displayed in About Window) + User data for back-end/wrappers to store their own stuff.
+ const char* BackendPlatformName; // = NULL
+ const char* BackendRendererName; // = NULL
+ void* BackendPlatformUserData; // = NULL
+ void* BackendRendererUserData; // = NULL
+ void* BackendLanguageUserData; // = NULL
+
+ // Optional: Access OS clipboard
+ // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
+ const char* (*GetClipboardTextFn)(void* user_data);
+ void (*SetClipboardTextFn)(void* user_data, const char* text);
+ void* ClipboardUserData;
+
+ // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows)
+ // (default to use native imm32 api on Windows)
+ void (*ImeSetInputScreenPosFn)(int x, int y);
+ void* ImeWindowHandle; // = NULL // (Windows) Set this to your HWND to get automatic IME cursor positioning.
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ // [OBSOLETE since 1.60+] Rendering function, will be automatically called in Render(). Please call your rendering function yourself now!
+ // You can obtain the ImDrawData* by calling ImGui::GetDrawData() after Render(). See example applications if you are unsure of how to implement this.
+ void (*RenderDrawListsFn)(ImDrawData* data);
+#else
+ // This is only here to keep ImGuiIO the same size/layout, so that IMGUI_DISABLE_OBSOLETE_FUNCTIONS can exceptionally be used outside of imconfig.h.
+ void* RenderDrawListsFnUnused;
+#endif
+
+ //------------------------------------------------------------------
+ // Input - Fill before calling NewFrame()
+ //------------------------------------------------------------------
+
+ ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.)
+ bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
+ float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
+ float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends.
+ bool KeyCtrl; // Keyboard modifier pressed: Control
+ bool KeyShift; // Keyboard modifier pressed: Shift
+ bool KeyAlt; // Keyboard modifier pressed: Alt
+ bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows
+ bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys).
+ float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame().
+
+ // Functions
+ IMGUI_API void AddInputCharacter(ImWchar c); // Queue new character input
+ IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string
+ IMGUI_API void ClearInputCharacters(); // Clear the text input buffer manually
+
+ //------------------------------------------------------------------
+ // Output - Retrieve after calling NewFrame()
+ //------------------------------------------------------------------
+
+ bool WantCaptureMouse; // When io.WantCaptureMouse is true, imgui will use the mouse inputs, do not dispatch them to your main game/application (in both cases, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.).
+ bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, imgui will use the keyboard inputs, do not dispatch them to your main game/application (in both cases, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.).
+ bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active).
+ bool WantSetMousePos; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled.
+ bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. IMPORTANT: You need to clear io.WantSaveIniSettings yourself.
+ bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
+ bool NavVisible; // Directional navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
+ float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames
+ int MetricsRenderVertices; // Vertices output during last call to Render()
+ int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3
+ int MetricsRenderWindows; // Number of visible windows
+ int MetricsActiveWindows; // Number of active windows
+ int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts.
+ ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
+
+ //------------------------------------------------------------------
+ // [Internal] ImGui will maintain those fields. Forward compatibility not guaranteed!
+ //------------------------------------------------------------------
+
+ ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
+ ImVec2 MouseClickedPos[5]; // Position at time of clicking
+ double MouseClickedTime[5]; // Time of last click (used to figure out double-click)
+ bool MouseClicked[5]; // Mouse button went from !Down to Down
+ bool MouseDoubleClicked[5]; // Has mouse button been double-clicked?
+ bool MouseReleased[5]; // Mouse button went from Down to !Down
+ bool MouseDownOwned[5]; // Track if button was clicked inside a window. We don't request mouse capture from the application if click started outside ImGui bounds.
+ float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
+ float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
+ ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point
+ float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point
+ float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed)
+ float KeysDownDurationPrev[512]; // Previous duration the key has been down
+ float NavInputsDownDuration[ImGuiNavInput_COUNT];
+ float NavInputsDownDurationPrev[ImGuiNavInput_COUNT];
+ ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform back-end). Fill using AddInputCharacter() helper.
+
+ IMGUI_API ImGuiIO();
+};
+
+//-----------------------------------------------------------------------------
+// Misc data structures
+//-----------------------------------------------------------------------------
+
+// Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used.
+// The callback function should return 0 by default.
+// Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details)
+// - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB
+// - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows
+// - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration
+// - ImGuiInputTextFlags_CallbackCharFilter: Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+// - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow.
+struct ImGuiInputTextCallbackData
+{
+ ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
+ ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
+ void* UserData; // What user passed to InputText() // Read-only
+
+ // Arguments for the different callback events
+ // - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary.
+ // - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state.
+ ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0;
+ ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History]
+ char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
+ int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length()
+ int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1
+ bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always]
+ int CursorPos; // // Read-write // [Completion,History,Always]
+ int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection)
+ int SelectionEnd; // // Read-write // [Completion,History,Always]
+
+ // Helper functions for text manipulation.
+ // Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection.
+ IMGUI_API ImGuiInputTextCallbackData();
+ IMGUI_API void DeleteChars(int pos, int bytes_count);
+ IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL);
+ bool HasSelection() const { return SelectionStart != SelectionEnd; }
+};
+
+// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin().
+// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough.
+struct ImGuiSizeCallbackData
+{
+ void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints()
+ ImVec2 Pos; // Read-only. Window position, for reference.
+ ImVec2 CurrentSize; // Read-only. Current window size.
+ ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing.
+};
+
+// Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload()
+struct ImGuiPayload
+{
+ // Members
+ void* Data; // Data (copied and owned by dear imgui)
+ int DataSize; // Data size
+
+ // [Internal]
+ ImGuiID SourceId; // Source item id
+ ImGuiID SourceParentId; // Source parent id (if available)
+ int DataFrameCount; // Data timestamp
+ char DataType[32+1]; // Data type tag (short user-supplied string, 32 characters max)
+ bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets)
+ bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item.
+
+ ImGuiPayload() { Clear(); }
+ void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; }
+ bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; }
+ bool IsPreview() const { return Preview; }
+ bool IsDelivery() const { return Delivery; }
+};
+
+//-----------------------------------------------------------------------------
+// Obsolete functions (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details)
+// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead.
+//-----------------------------------------------------------------------------
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+namespace ImGui
+{
+ // OBSOLETED in 1.66 (from Sep 2018)
+ static inline void SetScrollHere(float center_ratio=0.5f){ SetScrollHereY(center_ratio); }
+ // OBSOLETED in 1.63 (between Aug 2018 and Sept 2018)
+ static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); }
+ // OBSOLETED in 1.61 (between Apr 2018 and Aug 2018)
+ IMGUI_API bool InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags flags = 0); // Use the 'const char* format' version instead of 'decimal_precision'!
+ IMGUI_API bool InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags = 0);
+ // OBSOLETED in 1.60 (between Dec 2017 and Apr 2018)
+ static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); }
+ static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); }
+ static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { (void)on_edge; (void)outward; IM_ASSERT(0); return pos; }
+ // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
+ static inline void ShowTestWindow() { return ShowDemoWindow(); }
+ static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); }
+ static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); }
+ static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); }
+ static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); }
+ // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017)
+ IMGUI_API bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead.
+ static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); }
+ static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); }
+ static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); }
+ // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017)
+ static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); }
+ static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // This was misleading and partly broken. You probably want to use the ImGui::GetIO().WantCaptureMouse flag instead.
+ static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); }
+ static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); }
+}
+typedef ImGuiInputTextCallback ImGuiTextEditCallback; // OBSOLETE in 1.63 (from Aug 2018): made the names consistent
+typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData;
+#endif
+
+//-----------------------------------------------------------------------------
+// Helpers
+//-----------------------------------------------------------------------------
+
+// Helper: IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() macros to call MemAlloc + Placement New, Placement Delete + MemFree
+// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
+// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
+struct ImNewDummy {};
+inline void* operator new(size_t, ImNewDummy, void* ptr) { return ptr; }
+inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symetrical new()
+#define IM_PLACEMENT_NEW(_PTR) new(ImNewDummy(), _PTR)
+#define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE
+template<typename T> void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } }
+
+// Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame.
+// Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame");
+struct ImGuiOnceUponAFrame
+{
+ ImGuiOnceUponAFrame() { RefFrame = -1; }
+ mutable int RefFrame;
+ operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; }
+};
+
+// Helper: Macro for ImGuiOnceUponAFrame. Attention: The macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces.
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+#define IMGUI_ONCE_UPON_A_FRAME static ImGuiOnceUponAFrame imgui_oaf; if (imgui_oaf) // OBSOLETED in 1.51, will remove!
+#endif
+
+// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
+struct ImGuiTextFilter
+{
+ IMGUI_API ImGuiTextFilter(const char* default_filter = "");
+ IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
+ IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const;
+ IMGUI_API void Build();
+ void Clear() { InputBuf[0] = 0; Build(); }
+ bool IsActive() const { return !Filters.empty(); }
+
+ // [Internal]
+ struct TextRange
+ {
+ const char* b;
+ const char* e;
+
+ TextRange() { b = e = NULL; }
+ TextRange(const char* _b, const char* _e) { b = _b; e = _e; }
+ const char* begin() const { return b; }
+ const char* end () const { return e; }
+ bool empty() const { return b == e; }
+ IMGUI_API void split(char separator, ImVector<TextRange>* out) const;
+ };
+ char InputBuf[256];
+ ImVector<TextRange> Filters;
+ int CountGrep;
+};
+
+// Helper: Growable text buffer for logging/accumulating text
+// (this could be called 'ImGuiTextBuilder' / 'ImGuiStringBuilder')
+struct ImGuiTextBuffer
+{
+ ImVector<char> Buf;
+ static char EmptyString[1];
+
+ ImGuiTextBuffer() { }
+ inline char operator[](int i) { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; }
+ const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; }
+ const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator
+ int size() const { return Buf.Data ? Buf.Size - 1 : 0; }
+ bool empty() { return Buf.Size <= 1; }
+ void clear() { Buf.clear(); }
+ void reserve(int capacity) { Buf.reserve(capacity); }
+ const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; }
+ IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2);
+ IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2);
+};
+
+// Helper: Key->Value storage
+// Typically you don't have to worry about this since a storage is held within each Window.
+// We use it to e.g. store collapse state for a tree (Int 0/1)
+// This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame)
+// You can use it as custom user storage for temporary values. Declare your own storage if, for example:
+// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state).
+// - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient)
+// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types.
+struct ImGuiStorage
+{
+ struct Pair
+ {
+ ImGuiID key;
+ union { int val_i; float val_f; void* val_p; };
+ Pair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; }
+ Pair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; }
+ Pair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; }
+ };
+ ImVector<Pair> Data;
+
+ // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)
+ // - Set***() functions find pair, insertion on demand if missing.
+ // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair.
+ void Clear() { Data.clear(); }
+ IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const;
+ IMGUI_API void SetInt(ImGuiID key, int val);
+ IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const;
+ IMGUI_API void SetBool(ImGuiID key, bool val);
+ IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const;
+ IMGUI_API void SetFloat(ImGuiID key, float val);
+ IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL
+ IMGUI_API void SetVoidPtr(ImGuiID key, void* val);
+
+ // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set.
+ // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
+ // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct)
+ // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar;
+ IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0);
+ IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false);
+ IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f);
+ IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL);
+
+ // Use on your own storage if you know only integer are being stored (open/close all tree nodes)
+ IMGUI_API void SetAllInt(int val);
+
+ // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
+ IMGUI_API void BuildSortByKey();
+};
+
+// Helper: Manually clip large list of items.
+// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse clipping based on visibility to save yourself from processing those items at all.
+// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.
+// ImGui already clip items based on their bounds but it needs to measure text size to do so. Coarse clipping before submission makes this cost and your own data fetching/submission cost null.
+// Usage:
+// ImGuiListClipper clipper(1000); // we have 1000 elements, evenly spaced.
+// while (clipper.Step())
+// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+// ImGui::Text("line number %d", i);
+// - Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height (step skipped if we passed a known height as second arg to constructor).
+// - Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
+// - (Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user call Step(). Does nothing and switch to Step 3.)
+// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
+struct ImGuiListClipper
+{
+ float StartPosY;
+ float ItemsHeight;
+ int ItemsCount, StepNo, DisplayStart, DisplayEnd;
+
+ // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).
+ // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
+ // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step().
+ ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want).
+ ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false.
+
+ IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
+ IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1.
+ IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
+};
+
+// Helpers macros to generate 32-bits encoded colors
+#ifdef IMGUI_USE_BGRA_PACKED_COLOR
+#define IM_COL32_R_SHIFT 16
+#define IM_COL32_G_SHIFT 8
+#define IM_COL32_B_SHIFT 0
+#define IM_COL32_A_SHIFT 24
+#define IM_COL32_A_MASK 0xFF000000
+#else
+#define IM_COL32_R_SHIFT 0
+#define IM_COL32_G_SHIFT 8
+#define IM_COL32_B_SHIFT 16
+#define IM_COL32_A_SHIFT 24
+#define IM_COL32_A_MASK 0xFF000000
+#endif
+#define IM_COL32(R,G,B,A) (((ImU32)(A)<<IM_COL32_A_SHIFT) | ((ImU32)(B)<<IM_COL32_B_SHIFT) | ((ImU32)(G)<<IM_COL32_G_SHIFT) | ((ImU32)(R)<<IM_COL32_R_SHIFT))
+#define IM_COL32_WHITE IM_COL32(255,255,255,255) // Opaque white = 0xFFFFFFFF
+#define IM_COL32_BLACK IM_COL32(0,0,0,255) // Opaque black
+#define IM_COL32_BLACK_TRANS IM_COL32(0,0,0,0) // Transparent black = 0x00000000
+
+// Helper: ImColor() implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
+// Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API.
+// **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. MAY OBSOLETE.
+// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed.
+struct ImColor
+{
+ ImVec4 Value;
+
+ ImColor() { Value.x = Value.y = Value.z = Value.w = 0.0f; }
+ ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f/255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }
+ ImColor(ImU32 rgba) { float sc = 1.0f/255.0f; Value.x = (float)((rgba>>IM_COL32_R_SHIFT)&0xFF) * sc; Value.y = (float)((rgba>>IM_COL32_G_SHIFT)&0xFF) * sc; Value.z = (float)((rgba>>IM_COL32_B_SHIFT)&0xFF) * sc; Value.w = (float)((rgba>>IM_COL32_A_SHIFT)&0xFF) * sc; }
+ ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; }
+ ImColor(const ImVec4& col) { Value = col; }
+ inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); }
+ inline operator ImVec4() const { return Value; }
+
+ // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers.
+ inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; }
+ static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r,g,b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r,g,b,a); }
+};
+
+//-----------------------------------------------------------------------------
+// Draw List API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListFlags, ImDrawList, ImDrawData)
+// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList.
+//-----------------------------------------------------------------------------
+
+// Draw callbacks for advanced uses.
+// NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering,
+// you can poke into the draw list for that! Draw callback may be useful for example to: A) Change your GPU render state,
+// B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc.
+// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }'
+typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);
+
+// Typically, 1 command = 1 GPU draw call (unless command is a callback)
+struct ImDrawCmd
+{
+ unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
+ ImVec4 ClipRect; // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
+ ImTextureID TextureId; // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
+ ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
+ void* UserCallbackData; // The draw callback code can access this.
+
+ ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = ClipRect.z = ClipRect.w = 0.0f; TextureId = (ImTextureID)NULL; UserCallback = NULL; UserCallbackData = NULL; }
+};
+
+// Vertex index (override with '#define ImDrawIdx unsigned int' in imconfig.h)
+#ifndef ImDrawIdx
+typedef unsigned short ImDrawIdx;
+#endif
+
+// Vertex layout
+#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT
+struct ImDrawVert
+{
+ ImVec2 pos;
+ ImVec2 uv;
+ ImU32 col;
+};
+#else
+// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h
+// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine.
+// The type has to be described within the macro (you can either declare the struct or use a typedef)
+// NOTE: IMGUI DOESN'T CLEAR THE STRUCTURE AND DOESN'T CALL A CONSTRUCTOR SO ANY CUSTOM FIELD WILL BE UNINITIALIZED. IF YOU ADD EXTRA FIELDS (SUCH AS A 'Z' COORDINATES) YOU WILL NEED TO CLEAR THEM DURING RENDER OR TO IGNORE THEM.
+IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;
+#endif
+
+// Draw channels are used by the Columns API to "split" the render list into different channels while building, so items of each column can be batched together.
+// You can also use them to simulate drawing layers and submit primitives in a different order than how they will be rendered.
+struct ImDrawChannel
+{
+ ImVector<ImDrawCmd> CmdBuffer;
+ ImVector<ImDrawIdx> IdxBuffer;
+};
+
+enum ImDrawCornerFlags_
+{
+ ImDrawCornerFlags_TopLeft = 1 << 0, // 0x1
+ ImDrawCornerFlags_TopRight = 1 << 1, // 0x2
+ ImDrawCornerFlags_BotLeft = 1 << 2, // 0x4
+ ImDrawCornerFlags_BotRight = 1 << 3, // 0x8
+ ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight, // 0x3
+ ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight, // 0xC
+ ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft, // 0x5
+ ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight, // 0xA
+ ImDrawCornerFlags_All = 0xF // In your function calls you may use ~0 (= all bits sets) instead of ImDrawCornerFlags_All, as a convenience
+};
+
+enum ImDrawListFlags_
+{
+ ImDrawListFlags_None = 0,
+ ImDrawListFlags_AntiAliasedLines = 1 << 0, // Lines are anti-aliased (*2 the number of triangles for 1.0f wide line, otherwise *3 the number of triangles)
+ ImDrawListFlags_AntiAliasedFill = 1 << 1 // Filled shapes have anti-aliased edges (*2 the number of vertices)
+};
+
+// Draw command list
+// This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering.
+// Each ImGui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to access the current window draw list and draw custom primitives.
+// You can interleave normal ImGui:: calls and adding primitives to the current draw list.
+// All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), but you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well)
+// Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects.
+struct ImDrawList
+{
+ // This is what you have to render
+ ImVector<ImDrawCmd> CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback.
+ ImVector<ImDrawIdx> IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those
+ ImVector<ImDrawVert> VtxBuffer; // Vertex buffer.
+ ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
+
+ // [Internal, used while building lists]
+ const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context)
+ const char* _OwnerName; // Pointer to owner window's name for debugging
+ unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size
+ ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
+ ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
+ ImVector<ImVec4> _ClipRectStack; // [Internal]
+ ImVector<ImTextureID> _TextureIdStack; // [Internal]
+ ImVector<ImVec2> _Path; // [Internal] current path building
+ int _ChannelsCurrent; // [Internal] current channel number (0)
+ int _ChannelsCount; // [Internal] number of active channels (1+)
+ ImVector<ImDrawChannel> _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size)
+
+ // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui)
+ ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); }
+ ~ImDrawList() { ClearFreeMemory(); }
+ IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
+ IMGUI_API void PushClipRectFullScreen();
+ IMGUI_API void PopClipRect();
+ IMGUI_API void PushTextureID(ImTextureID texture_id);
+ IMGUI_API void PopTextureID();
+ inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); }
+ inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); }
+
+ // Primitives
+ IMGUI_API void AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness = 1.0f);
+ IMGUI_API void AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All, float thickness = 1.0f); // a: upper-left, b: lower-right, rounding_corners_flags: 4-bits corresponding to which corner to round
+ IMGUI_API void AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All); // a: upper-left, b: lower-right
+ IMGUI_API void AddRectFilledMultiColor(const ImVec2& a, const ImVec2& b, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
+ IMGUI_API void AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness = 1.0f);
+ IMGUI_API void AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col);
+ IMGUI_API void AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness = 1.0f);
+ IMGUI_API void AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col);
+ IMGUI_API void AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12, float thickness = 1.0f);
+ IMGUI_API void AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments = 12);
+ IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
+ IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
+ IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = 0xFFFFFFFF);
+ IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = 0xFFFFFFFF);
+ IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners = ImDrawCornerFlags_All);
+ IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness);
+ IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order.
+ IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0);
+
+ // Stateful path API, add points then finish with PathFillConvex() or PathStroke()
+ inline void PathClear() { _Path.Size = 0; }
+ inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
+ inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); }
+ inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } // Note: Anti-aliased filling requires points to be in clockwise order.
+ inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness); _Path.Size = 0; }
+ IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10);
+ IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
+ IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0);
+ IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, int rounding_corners_flags = ImDrawCornerFlags_All);
+
+ // Channels
+ // - Use to simulate layers. By switching channels to can render out-of-order (e.g. submit foreground primitives before background primitives)
+ // - Use to minimize draw calls (e.g. if going back-and-forth between multiple non-overlapping clipping rectangles, prefer to append into separate channels then merge at the end)
+ IMGUI_API void ChannelsSplit(int channels_count);
+ IMGUI_API void ChannelsMerge();
+ IMGUI_API void ChannelsSetCurrent(int channel_index);
+
+ // Advanced
+ IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.
+ IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
+ IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer.
+
+ // Internal helpers
+ // NB: all primitives needs to be reserved via PrimReserve() beforehand!
+ IMGUI_API void Clear();
+ IMGUI_API void ClearFreeMemory();
+ IMGUI_API void PrimReserve(int idx_count, int vtx_count);
+ IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles)
+ IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col);
+ IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col);
+ inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col){ _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; }
+ inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; }
+ inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); }
+ IMGUI_API void UpdateClipRect();
+ IMGUI_API void UpdateTextureID();
+};
+
+// All draw data to render an ImGui frame
+// (NB: the style and the naming convention here is a little inconsistent but we preserve them for backward compatibility purpose)
+struct ImDrawData
+{
+ bool Valid; // Only valid after Render() is called and before the next NewFrame() is called.
+ ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here.
+ int CmdListsCount; // Number of ImDrawList* to render
+ int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size
+ int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size
+ ImVec2 DisplayPos; // Upper-left position of the viewport to render (== upper-left of the orthogonal projection matrix to use)
+ ImVec2 DisplaySize; // Size of the viewport to render (== io.DisplaySize for the main viewport) (DisplayPos + DisplaySize == lower-right of the orthogonal projection matrix to use)
+
+ // Functions
+ ImDrawData() { Valid = false; Clear(); }
+ ~ImDrawData() { Clear(); }
+ void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; DisplayPos = DisplaySize = ImVec2(0.f, 0.f); } // The ImDrawList are owned by ImGuiContext!
+ IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
+ IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
+};
+
+//-----------------------------------------------------------------------------
+// Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont)
+//-----------------------------------------------------------------------------
+
+struct ImFontConfig
+{
+ void* FontData; // // TTF/OTF data
+ int FontDataSize; // // TTF/OTF data size
+ bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
+ int FontNo; // 0 // Index of font within TTF/OTF file
+ float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height).
+ int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis.
+ int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis.
+ bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
+ ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
+ ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input.
+ const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
+ float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
+ float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs
+ bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
+ unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one.
+ float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
+
+ // [Internal]
+ char Name[40]; // Name (strictly to ease debugging)
+ ImFont* DstFont;
+
+ IMGUI_API ImFontConfig();
+};
+
+struct ImFontGlyph
+{
+ ImWchar Codepoint; // 0x0000..0xFFFF
+ float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in)
+ float X0, Y0, X1, Y1; // Glyph corners
+ float U0, V0, U1, V1; // Texture coordinates
+};
+
+// Helper to build glyph ranges from text/string data. Feed your application strings/characters to it then call BuildRanges().
+// This is essentially a tightly packed of vector of 64k booleans = 8KB storage.
+struct ImFontGlyphRangesBuilder
+{
+ ImVector<int> UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used)
+
+ ImFontGlyphRangesBuilder() { UsedChars.resize(0x10000 / 32); memset(UsedChars.Data, 0, 0x10000 / 32); }
+ bool GetBit(int n) const { int off = (n >> 5); int mask = 1 << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array
+ void SetBit(int n) { int off = (n >> 5); int mask = 1 << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array
+ void AddChar(ImWchar c) { SetBit(c); } // Add character
+ IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added)
+ IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext
+ IMGUI_API void BuildRanges(ImVector<ImWchar>* out_ranges); // Output new ranges
+};
+
+enum ImFontAtlasFlags_
+{
+ ImFontAtlasFlags_None = 0,
+ ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two
+ ImFontAtlasFlags_NoMouseCursors = 1 << 1 // Don't build software mouse cursors into the atlas
+};
+
+// Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding:
+// - One or more fonts.
+// - Custom graphics data needed to render the shapes needed by Dear ImGui.
+// - Mouse cursor shapes for software cursor rendering (unless setting 'Flags |= ImFontAtlasFlags_NoMouseCursors' in the font atlas).
+// It is the user-code responsibility to setup/build the atlas, then upload the pixel data into a texture accessible by your graphics api.
+// - Optionally, call any of the AddFont*** functions. If you don't call any, the default font embedded in the code will be loaded for you.
+// - Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
+// - Upload the pixels data into a texture within your graphics system (see imgui_impl_xxxx.cpp examples)
+// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
+// This value will be passed back to you during rendering to identify the texture. Read FAQ entry about ImTextureID for more details.
+// Common pitfalls:
+// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the
+// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
+// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
+// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
+// - Even though many functions are suffixed with "TTF", OTF data is supported just as well.
+// - This is an old API and it is currently awkward for those and and various other reasons! We will address them in the future!
+struct ImFontAtlas
+{
+ IMGUI_API ImFontAtlas();
+ IMGUI_API ~ImFontAtlas();
+ IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg);
+ IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL);
+ IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL);
+ IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
+ IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
+ IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
+ IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
+ IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory.
+ IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates).
+ IMGUI_API void Clear(); // Clear all input and output.
+
+ // Build atlas, retrieve pixel data.
+ // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
+ // The pitch is always = Width * BytesPerPixels (1 or 4)
+ // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into
+ // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste.
+ IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions.
+ IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
+ IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
+ bool IsBuilt() { return Fonts.Size > 0 && (TexPixelsAlpha8 != NULL || TexPixelsRGBA32 != NULL); }
+ void SetTexID(ImTextureID id) { TexID = id; }
+
+ //-------------------------------------------
+ // Glyph Ranges
+ //-------------------------------------------
+
+ // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list)
+ // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details.
+ // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data.
+ IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
+ IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters
+ IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
+ IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
+ IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
+ IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters
+ IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters
+
+ //-------------------------------------------
+ // Custom Rectangles/Glyphs API
+ //-------------------------------------------
+
+ // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. After calling Build(), you can query the rectangle position and render your pixels.
+ // You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), so you can render e.g. custom colorful icons and use them as regular glyphs.
+ struct CustomRect
+ {
+ unsigned int ID; // Input // User ID. Use <0x10000 to map into a font glyph, >=0x10000 for other/internal/custom texture data.
+ unsigned short Width, Height; // Input // Desired rectangle dimension
+ unsigned short X, Y; // Output // Packed position in Atlas
+ float GlyphAdvanceX; // Input // For custom font glyphs only (ID<0x10000): glyph xadvance
+ ImVec2 GlyphOffset; // Input // For custom font glyphs only (ID<0x10000): glyph display offset
+ ImFont* Font; // Input // For custom font glyphs only (ID<0x10000): target font
+ CustomRect() { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0,0); Font = NULL; }
+ bool IsPacked() const { return X != 0xFFFF; }
+ };
+
+ IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList
+ IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font.
+ const CustomRect* GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; }
+
+ // [Internal]
+ IMGUI_API void CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max);
+ IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]);
+
+ //-------------------------------------------
+ // Members
+ //-------------------------------------------
+
+ bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
+ ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_)
+ ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
+ int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
+ int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1.
+
+ // [Internal]
+ // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you.
+ unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight
+ unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4
+ int TexWidth; // Texture width calculated during Build().
+ int TexHeight; // Texture height calculated during Build().
+ ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight)
+ ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel
+ ImVector<ImFont*> Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font.
+ ImVector<CustomRect> CustomRects; // Rectangles for packing custom texture data into the atlas.
+ ImVector<ImFontConfig> ConfigData; // Internal data
+ int CustomRectIds[1]; // Identifiers of custom texture rectangle used by ImFontAtlas/ImDrawList
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETE 1.67+
+#endif
+};
+
+// Font runtime data and rendering
+// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32().
+struct ImFont
+{
+ // Members: Hot ~62/78 bytes
+ float FontSize; // <user set> // Height of characters, set during loading (don't change after loading)
+ float Scale; // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
+ ImVec2 DisplayOffset; // = (0.f,0.f) // Offset font rendering by xx pixels
+ ImVector<ImFontGlyph> Glyphs; // // All glyphs.
+ ImVector<float> IndexAdvanceX; // // Sparse. Glyphs->AdvanceX in a directly indexable way (more cache-friendly, for CalcTextSize functions which are often bottleneck in large UI).
+ ImVector<ImWchar> IndexLookup; // // Sparse. Index glyphs by Unicode code-point.
+ const ImFontGlyph* FallbackGlyph; // == FindGlyph(FontFallbackChar)
+ float FallbackAdvanceX; // == FallbackGlyph->AdvanceX
+ ImWchar FallbackChar; // = '?' // Replacement glyph if one isn't found. Only set via SetFallbackChar()
+
+ // Members: Cold ~18/26 bytes
+ short ConfigDataCount; // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
+ ImFontConfig* ConfigData; // // Pointer within ContainerAtlas->ConfigData
+ ImFontAtlas* ContainerAtlas; // // What we has been loaded into
+ float Ascent, Descent; // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
+ bool DirtyLookupTables;
+ int MetricsTotalSurface;// // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
+
+ // Methods
+ IMGUI_API ImFont();
+ IMGUI_API ~ImFont();
+ IMGUI_API void ClearOutputData();
+ IMGUI_API void BuildLookupTable();
+ IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const;
+ IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c) const;
+ IMGUI_API void SetFallbackChar(ImWchar c);
+ float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; }
+ bool IsLoaded() const { return ContainerAtlas != NULL; }
+ const char* GetDebugName() const { return ConfigData ? ConfigData->Name : "<unknown>"; }
+
+ // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.
+ // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable.
+ IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8
+ IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const;
+ IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const;
+ IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const;
+
+ // [Internal]
+ IMGUI_API void GrowIndex(int new_size);
+ IMGUI_API void AddGlyph(ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x);
+ IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built.
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ typedef ImFontGlyph Glyph; // OBSOLETE 1.52+
+#endif
+};
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__) && __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+
+// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h)
+#ifdef IMGUI_INCLUDE_IMGUI_USER_H
+#include "imgui_user.h"
+#endif
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imgui_demo.cpp b/Client/ThirdParty/Box2D/extern/imgui/imgui_demo.cpp
new file mode 100644
index 0000000..cf1d4b3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imgui_demo.cpp
@@ -0,0 +1,4211 @@
+// dear imgui, v1.67 WIP
+// (demo code)
+
+// Message to the person tempted to delete this file when integrating Dear ImGui into their code base:
+// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other coders
+// will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of
+// your game/app! Removing this file from your project is hindering access to documentation for everyone in your team,
+// likely leading you to poorer usage of the library.
+// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
+// If you want to link core Dear ImGui in your shipped builds but want an easy guarantee that the demo will not be linked,
+// you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
+// In other situation, whenever you have Dear ImGui available you probably want this to be available for reference.
+// Thank you,
+// -Your beloved friend, imgui_demo.cpp (that you won't delete)
+
+// Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
+// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is
+// essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data
+// in the same place, to make the demo source code faster to read, faster to write, and smaller in size.
+// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant
+// or used in threads. This might be a pattern you will want to use in your code, but most of the real data you would be editing is
+// likely going to be stored outside your functions.
+
+/*
+
+Index of this file:
+
+// [SECTION] Forward Declarations, Helpers
+// [SECTION] Demo Window / ShowDemoWindow()
+// [SECTION] About Window / ShowAboutWindow()
+// [SECTION] Style Editor / ShowStyleEditor()
+// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
+// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
+// [SECTION] Example App: Debug Log / ShowExampleAppLog()
+// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
+// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
+// [SECTION] Example App: Long Text / ShowExampleAppLongText()
+// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
+// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
+// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
+// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
+// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
+// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#include <ctype.h> // toupper, isprint
+#include <limits.h> // INT_MIN, INT_MAX
+#include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
+#include <stdio.h> // vsnprintf, sscanf, printf
+#include <stdlib.h> // NULL, malloc, free, atoi
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#define vsnprintf _vsnprintf
+#endif
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
+#pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal
+#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
+#if __has_warning("-Wreserved-id-macro")
+#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
+#endif
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure)
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#if (__GNUC__ >= 6)
+#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
+#endif
+#endif
+
+// Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
+#ifdef _WIN32
+#define IM_NEWLINE "\r\n"
+#else
+#define IM_NEWLINE "\n"
+#endif
+
+#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B))
+
+//-----------------------------------------------------------------------------
+// [SECTION] Forward Declarations, Helpers
+//-----------------------------------------------------------------------------
+
+#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Obsolete name since 1.53, TEST->DEMO
+#define IMGUI_DISABLE_DEMO_WINDOWS
+#endif
+
+#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
+
+// Forward Declarations
+static void ShowExampleAppDocuments(bool* p_open);
+static void ShowExampleAppMainMenuBar();
+static void ShowExampleAppConsole(bool* p_open);
+static void ShowExampleAppLog(bool* p_open);
+static void ShowExampleAppLayout(bool* p_open);
+static void ShowExampleAppPropertyEditor(bool* p_open);
+static void ShowExampleAppLongText(bool* p_open);
+static void ShowExampleAppAutoResize(bool* p_open);
+static void ShowExampleAppConstrainedResize(bool* p_open);
+static void ShowExampleAppSimpleOverlay(bool* p_open);
+static void ShowExampleAppWindowTitles(bool* p_open);
+static void ShowExampleAppCustomRendering(bool* p_open);
+static void ShowExampleMenuFile();
+
+// Helper to display a little (?) mark which shows a tooltip when hovered.
+static void ShowHelpMarker(const char* desc)
+{
+ ImGui::TextDisabled("(?)");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
+ ImGui::TextUnformatted(desc);
+ ImGui::PopTextWrapPos();
+ ImGui::EndTooltip();
+ }
+}
+
+// Helper to display basic user controls.
+void ImGui::ShowUserGuide()
+{
+ ImGui::BulletText("Double-click on title bar to collapse window.");
+ ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
+ ImGui::BulletText("Click and drag on any empty space to move window.");
+ ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
+ ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
+ if (ImGui::GetIO().FontAllowUserScaling)
+ ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
+ ImGui::BulletText("Mouse Wheel to scroll.");
+ ImGui::BulletText("While editing text:\n");
+ ImGui::Indent();
+ ImGui::BulletText("Hold SHIFT or use mouse to select text.");
+ ImGui::BulletText("CTRL+Left/Right to word jump.");
+ ImGui::BulletText("CTRL+A or double-click to select all.");
+ ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
+ ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
+ ImGui::BulletText("ESCAPE to revert.");
+ ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
+ ImGui::Unindent();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Demo Window / ShowDemoWindow()
+//-----------------------------------------------------------------------------
+
+// We split the contents of the big ShowDemoWindow() function into smaller functions (because the link time of very large functions grow non-linearly)
+static void ShowDemoWindowWidgets();
+static void ShowDemoWindowLayout();
+static void ShowDemoWindowPopups();
+static void ShowDemoWindowColumns();
+static void ShowDemoWindowMisc();
+
+// Demonstrate most Dear ImGui features (this is big function!)
+// You may execute this function to experiment with the UI and understand what it does. You may then search for keywords in the code when you are interested by a specific feature.
+void ImGui::ShowDemoWindow(bool* p_open)
+{
+ // Examples Apps (accessible from the "Examples" menu)
+ static bool show_app_documents = false;
+ static bool show_app_main_menu_bar = false;
+ static bool show_app_console = false;
+ static bool show_app_log = false;
+ static bool show_app_layout = false;
+ static bool show_app_property_editor = false;
+ static bool show_app_long_text = false;
+ static bool show_app_auto_resize = false;
+ static bool show_app_constrained_resize = false;
+ static bool show_app_simple_overlay = false;
+ static bool show_app_window_titles = false;
+ static bool show_app_custom_rendering = false;
+
+ if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); // Process the Document app next, as it may also use a DockSpace()
+ if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
+ if (show_app_console) ShowExampleAppConsole(&show_app_console);
+ if (show_app_log) ShowExampleAppLog(&show_app_log);
+ if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
+ if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
+ if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
+ if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
+ if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
+ if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
+ if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles);
+ if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
+
+ // Dear ImGui Apps (accessible from the "Help" menu)
+ static bool show_app_metrics = false;
+ static bool show_app_style_editor = false;
+ static bool show_app_about = false;
+
+ if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); }
+ if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
+ if (show_app_about) { ImGui::ShowAboutWindow(&show_app_about); }
+
+ // Demonstrate the various window flags. Typically you would just use the default!
+ static bool no_titlebar = false;
+ static bool no_scrollbar = false;
+ static bool no_menu = false;
+ static bool no_move = false;
+ static bool no_resize = false;
+ static bool no_collapse = false;
+ static bool no_close = false;
+ static bool no_nav = false;
+ static bool no_background = false;
+ static bool no_bring_to_front = false;
+
+ ImGuiWindowFlags window_flags = 0;
+ if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
+ if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
+ if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
+ if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
+ if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
+ if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
+ if (no_nav) window_flags |= ImGuiWindowFlags_NoNav;
+ if (no_background) window_flags |= ImGuiWindowFlags_NoBackground;
+ if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
+ if (no_close) p_open = NULL; // Don't pass our bool* to Begin
+
+ // We specify a default position/size in case there's no data in the .ini file. Typically this isn't required! We only do it to make the Demo applications a little more welcoming.
+ ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
+
+ // Main body of the Demo window starts here.
+ if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
+ {
+ // Early out if the window is collapsed, as an optimization.
+ ImGui::End();
+ return;
+ }
+ ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
+
+ // Most "big" widgets share a common width settings by default.
+ //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // Use 2/3 of the space for widgets and 1/3 for labels (default)
+ ImGui::PushItemWidth(ImGui::GetFontSize() * -12); // Use fixed width for labels (by passing a negative value), the rest goes to widgets. We choose a width proportional to our font size.
+
+ // Menu
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("Menu"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Examples"))
+ {
+ ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
+ ImGui::MenuItem("Console", NULL, &show_app_console);
+ ImGui::MenuItem("Log", NULL, &show_app_log);
+ ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
+ ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
+ ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
+ ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
+ ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
+ ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
+ ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
+ ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
+ ImGui::MenuItem("Documents", NULL, &show_app_documents);
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Help"))
+ {
+ ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
+ ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
+ ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+
+ ImGui::Spacing();
+ if (ImGui::CollapsingHeader("Help"))
+ {
+ ImGui::Text("PROGRAMMER GUIDE:");
+ ImGui::BulletText("Please see the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
+ ImGui::BulletText("Please see the comments in imgui.cpp.");
+ ImGui::BulletText("Please see the examples/ in application.");
+ ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
+ ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
+ ImGui::Separator();
+
+ ImGui::Text("USER GUIDE:");
+ ImGui::ShowUserGuide();
+ }
+
+ if (ImGui::CollapsingHeader("Configuration"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+
+ if (ImGui::TreeNode("Configuration##2"))
+ {
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
+ ImGui::SameLine(); ShowHelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
+ ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
+ ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) // Create a way to restore this flag otherwise we could be stuck completely!
+ {
+ if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
+ {
+ ImGui::SameLine();
+ ImGui::Text("<<PRESS SPACE TO DISABLE>>");
+ }
+ if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
+ io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
+ }
+ ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
+ ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
+ ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
+ ImGui::SameLine(); ShowHelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
+ ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
+ ImGui::SameLine(); ShowHelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
+ ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
+ ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
+ ImGui::SameLine(); ShowHelpMarker("Instruct Dear ImGui to render a mouse cursor for you. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+
+ if (ImGui::TreeNode("Backend Flags"))
+ {
+ ImGuiBackendFlags backend_flags = io.BackendFlags; // Make a local copy to avoid modifying the back-end flags.
+ ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad);
+ ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
+ ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+
+ if (ImGui::TreeNode("Style"))
+ {
+ ImGui::ShowStyleEditor();
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+
+ if (ImGui::TreeNode("Capture/Logging"))
+ {
+ ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded.");
+ ShowHelpMarker("Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
+ ImGui::LogButtons();
+ ImGui::TextWrapped("You can also call ImGui::LogText() to output directly to the log without a visual output.");
+ if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
+ {
+ ImGui::LogToClipboard();
+ ImGui::LogText("Hello, world!");
+ ImGui::LogFinish();
+ }
+ ImGui::TreePop();
+ }
+ }
+
+ if (ImGui::CollapsingHeader("Window options"))
+ {
+ ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
+ ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
+ ImGui::Checkbox("No menu", &no_menu);
+ ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
+ ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
+ ImGui::Checkbox("No collapse", &no_collapse);
+ ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
+ ImGui::Checkbox("No nav", &no_nav); ImGui::SameLine(300);
+ ImGui::Checkbox("No background", &no_background);
+ ImGui::Checkbox("No bring to front", &no_bring_to_front);
+ }
+
+ // All demo contents
+ ShowDemoWindowWidgets();
+ ShowDemoWindowLayout();
+ ShowDemoWindowPopups();
+ ShowDemoWindowColumns();
+ ShowDemoWindowMisc();
+
+ // End of ShowDemoWindow()
+ ImGui::End();
+}
+
+static void ShowDemoWindowWidgets()
+{
+ if (!ImGui::CollapsingHeader("Widgets"))
+ return;
+
+ if (ImGui::TreeNode("Basic"))
+ {
+ static int clicked = 0;
+ if (ImGui::Button("Button"))
+ clicked++;
+ if (clicked & 1)
+ {
+ ImGui::SameLine();
+ ImGui::Text("Thanks for clicking me!");
+ }
+
+ static bool check = true;
+ ImGui::Checkbox("checkbox", &check);
+
+ static int e = 0;
+ ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
+ ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
+ ImGui::RadioButton("radio c", &e, 2);
+
+ // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
+ for (int i = 0; i < 7; i++)
+ {
+ if (i > 0)
+ ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
+ ImGui::Button("Click");
+ ImGui::PopStyleColor(3);
+ ImGui::PopID();
+ }
+
+ // Use AlignTextToFramePadding() to align text baseline to the baseline of framed elements (otherwise a Text+SameLine+Button sequence will have the text a little too high by default)
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("Hold to repeat:");
+ ImGui::SameLine();
+
+ // Arrow buttons with Repeater
+ static int counter = 0;
+ float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
+ ImGui::PushButtonRepeat(true);
+ if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
+ ImGui::SameLine(0.0f, spacing);
+ if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
+ ImGui::PopButtonRepeat();
+ ImGui::SameLine();
+ ImGui::Text("%d", counter);
+
+ ImGui::Text("Hover over me");
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("I am a tooltip");
+
+ ImGui::SameLine();
+ ImGui::Text("- or me");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::Text("I am a fancy tooltip");
+ static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
+ ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
+ ImGui::EndTooltip();
+ }
+
+ ImGui::Separator();
+
+ ImGui::LabelText("label", "Value");
+
+ {
+ // Using the _simplified_ one-liner Combo() api here
+ // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
+ static int item_current = 0;
+ ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
+ ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
+ }
+
+ {
+ static char str0[128] = "Hello, world!";
+ static int i0 = 123;
+ ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
+ ImGui::SameLine(); ShowHelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp).");
+
+ ImGui::InputInt("input int", &i0);
+ ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
+
+ static float f0 = 0.001f;
+ ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
+
+ static double d0 = 999999.00000001;
+ ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
+
+ static float f1 = 1.e10f;
+ ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
+ ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n");
+
+ static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
+ ImGui::InputFloat3("input float3", vec4a);
+ }
+
+ {
+ static int i1 = 50, i2 = 42;
+ ImGui::DragInt("drag int", &i1, 1);
+ ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
+
+ ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");
+
+ static float f1=1.00f, f2=0.0067f;
+ ImGui::DragFloat("drag float", &f1, 0.005f);
+ ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
+ }
+
+ {
+ static int i1=0;
+ ImGui::SliderInt("slider int", &i1, -1, 3);
+ ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
+
+ static float f1=0.123f, f2=0.0f;
+ ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
+ ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f);
+ static float angle = 0.0f;
+ ImGui::SliderAngle("slider angle", &angle);
+ }
+
+ {
+ static float col1[3] = { 1.0f,0.0f,0.2f };
+ static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
+ ImGui::ColorEdit3("color 1", col1);
+ ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
+
+ ImGui::ColorEdit4("color 2", col2);
+ }
+
+ {
+ // List box
+ const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
+ static int listbox_item_current = 1;
+ ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
+
+ //static int listbox_item_current2 = 2;
+ //ImGui::PushItemWidth(-1);
+ //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
+ //ImGui::PopItemWidth();
+ }
+
+ ImGui::TreePop();
+ }
+
+ // Testing ImGuiOnceUponAFrame helper.
+ //static ImGuiOnceUponAFrame once;
+ //for (int i = 0; i < 5; i++)
+ // if (once)
+ // ImGui::Text("This will be displayed only once.");
+
+ if (ImGui::TreeNode("Trees"))
+ {
+ if (ImGui::TreeNode("Basic trees"))
+ {
+ for (int i = 0; i < 5; i++)
+ if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
+ {
+ ImGui::Text("blah blah");
+ ImGui::SameLine();
+ if (ImGui::SmallButton("button")) { };
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Advanced, with Selectable nodes"))
+ {
+ ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
+ static bool align_label_with_current_x_position = false;
+ ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
+ ImGui::Text("Hello!");
+ if (align_label_with_current_x_position)
+ ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
+
+ static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
+ int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
+ ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
+ for (int i = 0; i < 6; i++)
+ {
+ // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
+ ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
+ if (i < 3)
+ {
+ // Node
+ bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
+ if (ImGui::IsItemClicked())
+ node_clicked = i;
+ if (node_open)
+ {
+ ImGui::Text("Blah blah\nBlah Blah");
+ ImGui::TreePop();
+ }
+ }
+ else
+ {
+ // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().
+ node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
+ ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
+ if (ImGui::IsItemClicked())
+ node_clicked = i;
+ }
+ }
+ if (node_clicked != -1)
+ {
+ // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
+ if (ImGui::GetIO().KeyCtrl)
+ selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
+ else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
+ selection_mask = (1 << node_clicked); // Click to single-select
+ }
+ ImGui::PopStyleVar();
+ if (align_label_with_current_x_position)
+ ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Collapsing Headers"))
+ {
+ static bool closable_group = true;
+ ImGui::Checkbox("Enable extra group", &closable_group);
+ if (ImGui::CollapsingHeader("Header"))
+ {
+ ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
+ for (int i = 0; i < 5; i++)
+ ImGui::Text("Some content %d", i);
+ }
+ if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
+ {
+ ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
+ for (int i = 0; i < 5; i++)
+ ImGui::Text("More content %d", i);
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Bullets"))
+ {
+ ImGui::BulletText("Bullet point 1");
+ ImGui::BulletText("Bullet point 2\nOn multiple lines");
+ ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
+ ImGui::Bullet(); ImGui::SmallButton("Button");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Text"))
+ {
+ if (ImGui::TreeNode("Colored Text"))
+ {
+ // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
+ ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
+ ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
+ ImGui::TextDisabled("Disabled");
+ ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Word Wrapping"))
+ {
+ // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
+ ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.");
+ ImGui::Spacing();
+
+ static float wrap_width = 200.0f;
+ ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
+
+ ImGui::Text("Test paragraph 1:");
+ ImVec2 pos = ImGui::GetCursorScreenPos();
+ ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
+ ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
+ ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
+ ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
+ ImGui::PopTextWrapPos();
+
+ ImGui::Text("Test paragraph 2:");
+ pos = ImGui::GetCursorScreenPos();
+ ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
+ ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
+ ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
+ ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
+ ImGui::PopTextWrapPos();
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("UTF-8 Text"))
+ {
+ // UTF-8 test with Japanese characters
+ // (Needs a suitable font, try Noto, or Arial Unicode, or M+ fonts. Read misc/fonts/README.txt for details.)
+ // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
+ // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature')
+ // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
+ // Instead we are encoding a few strings with hexadecimal constants. Don't do this in your application!
+ // Please use u8"text in any language" in your application!
+ // Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
+ ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->AddFontFromFileTTF() manually to load extra character ranges. Read misc/fonts/README.txt for details.");
+ ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
+ ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
+ static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
+ //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
+ ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Images"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!");
+
+ // Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
+ // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure.
+ // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID.
+ // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.)
+ // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc.
+ // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this.
+ // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
+ ImTextureID my_tex_id = io.Fonts->TexID;
+ float my_tex_w = (float)io.Fonts->TexWidth;
+ float my_tex_h = (float)io.Fonts->TexHeight;
+
+ ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
+ ImVec2 pos = ImGui::GetCursorScreenPos();
+ ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ float region_sz = 32.0f;
+ float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; if (region_x < 0.0f) region_x = 0.0f; else if (region_x > my_tex_w - region_sz) region_x = my_tex_w - region_sz;
+ float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; if (region_y < 0.0f) region_y = 0.0f; else if (region_y > my_tex_h - region_sz) region_y = my_tex_h - region_sz;
+ float zoom = 4.0f;
+ ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
+ ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
+ ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
+ ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
+ ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
+ ImGui::EndTooltip();
+ }
+ ImGui::TextWrapped("And now some textured buttons..");
+ static int pressed_count = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ ImGui::PushID(i);
+ int frame_padding = -1 + i; // -1 = uses default padding
+ if (ImGui::ImageButton(my_tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/my_tex_w,32/my_tex_h), frame_padding, ImColor(0,0,0,255)))
+ pressed_count += 1;
+ ImGui::PopID();
+ ImGui::SameLine();
+ }
+ ImGui::NewLine();
+ ImGui::Text("Pressed %d times.", pressed_count);
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Combo"))
+ {
+ // Expose flags as checkbox for the demo
+ static ImGuiComboFlags flags = 0;
+ ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
+ if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
+ flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both
+ if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
+ flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
+
+ // General BeginCombo() API, you have full control over your selection data and display type.
+ // (your selection data could be an index, a pointer to the object, an id for the object, a flag stored in the object itself, etc.)
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
+ static const char* item_current = items[0]; // Here our selection is a single pointer stored outside the object.
+ if (ImGui::BeginCombo("combo 1", item_current, flags)) // The second parameter is the label previewed before opening the combo.
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+ {
+ bool is_selected = (item_current == items[n]);
+ if (ImGui::Selectable(items[n], is_selected))
+ item_current = items[n];
+ if (is_selected)
+ ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
+ }
+ ImGui::EndCombo();
+ }
+
+ // Simplified one-liner Combo() API, using values packed in a single constant string
+ static int item_current_2 = 0;
+ ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
+
+ // Simplified one-liner Combo() using an array of const char*
+ static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
+ ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
+
+ // Simplified one-liner Combo() using an accessor function
+ struct FuncHolder { static bool ItemGetter(void* data, int idx, const char** out_str) { *out_str = ((const char**)data)[idx]; return true; } };
+ static int item_current_4 = 0;
+ ImGui::Combo("combo 4 (function)", &item_current_4, &FuncHolder::ItemGetter, items, IM_ARRAYSIZE(items));
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Selectables"))
+ {
+ // Selectable() has 2 overloads:
+ // - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly.
+ // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
+ // The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc).
+ if (ImGui::TreeNode("Basic"))
+ {
+ static bool selection[5] = { false, true, false, false, false };
+ ImGui::Selectable("1. I am selectable", &selection[0]);
+ ImGui::Selectable("2. I am selectable", &selection[1]);
+ ImGui::Text("3. I am not selectable");
+ ImGui::Selectable("4. I am selectable", &selection[3]);
+ if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
+ if (ImGui::IsMouseDoubleClicked(0))
+ selection[4] = !selection[4];
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("Selection State: Single Selection"))
+ {
+ static int selected = -1;
+ for (int n = 0; n < 5; n++)
+ {
+ char buf[32];
+ sprintf(buf, "Object %d", n);
+ if (ImGui::Selectable(buf, selected == n))
+ selected = n;
+ }
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("Selection State: Multiple Selection"))
+ {
+ ShowHelpMarker("Hold CTRL and click to select multiple items.");
+ static bool selection[5] = { false, false, false, false, false };
+ for (int n = 0; n < 5; n++)
+ {
+ char buf[32];
+ sprintf(buf, "Object %d", n);
+ if (ImGui::Selectable(buf, selection[n]))
+ {
+ if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
+ memset(selection, 0, sizeof(selection));
+ selection[n] ^= 1;
+ }
+ }
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("Rendering more text into the same line"))
+ {
+ // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically.
+ static bool selected[3] = { false, false, false };
+ ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
+ ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
+ ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("In columns"))
+ {
+ ImGui::Columns(3, NULL, false);
+ static bool selected[16] = { 0 };
+ for (int i = 0; i < 16; i++)
+ {
+ char label[32]; sprintf(label, "Item %d", i);
+ if (ImGui::Selectable(label, &selected[i])) {}
+ ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ ImGui::TreePop();
+ }
+ if (ImGui::TreeNode("Grid"))
+ {
+ static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
+ for (int i = 0; i < 16; i++)
+ {
+ ImGui::PushID(i);
+ if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
+ {
+ int x = i % 4, y = i / 4;
+ if (x > 0) selected[i - 1] ^= 1;
+ if (x < 3) selected[i + 1] ^= 1;
+ if (y > 0) selected[i - 4] ^= 1;
+ if (y < 3) selected[i + 4] ^= 1;
+ }
+ if ((i % 4) < 3) ImGui::SameLine();
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Filtered Text Input"))
+ {
+ static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
+ static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
+ static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
+ static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
+ static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
+ struct TextFilters { static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
+ static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
+
+ ImGui::Text("Password input");
+ static char bufpass[64] = "password123";
+ ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
+ ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
+ ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Multi-line Text Input"))
+ {
+ // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
+ // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
+ static bool read_only = false;
+ static char text[1024*16] =
+ "/*\n"
+ " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
+ " the hexadecimal encoding of one offending instruction,\n"
+ " more formally, the invalid operand with locked CMPXCHG8B\n"
+ " instruction bug, is a design flaw in the majority of\n"
+ " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
+ " processors (all in the P5 microarchitecture).\n"
+ "*/\n\n"
+ "label:\n"
+ "\tlock cmpxchg8b eax\n";
+
+ ShowHelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp)");
+ ImGui::Checkbox("Read-only", &read_only);
+ ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0);
+ ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), flags);
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Plots Widgets"))
+ {
+ static bool animate = true;
+ ImGui::Checkbox("Animate", &animate);
+
+ static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
+ ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
+
+ // Create a dummy array of contiguous float values to plot
+ // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.
+ static float values[90] = { 0 };
+ static int values_offset = 0;
+ static double refresh_time = 0.0;
+ if (!animate || refresh_time == 0.0f)
+ refresh_time = ImGui::GetTime();
+ while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo
+ {
+ static float phase = 0.0f;
+ values[values_offset] = cosf(phase);
+ values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
+ phase += 0.10f*values_offset;
+ refresh_time += 1.0f/60.0f;
+ }
+ ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
+ ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
+
+ // Use functions to generate output
+ // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.
+ struct Funcs
+ {
+ static float Sin(void*, int i) { return sinf(i * 0.1f); }
+ static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
+ };
+ static int func_type = 0, display_count = 70;
+ ImGui::Separator();
+ ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
+ ImGui::SameLine();
+ ImGui::SliderInt("Sample count", &display_count, 1, 400);
+ float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
+ ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
+ ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
+ ImGui::Separator();
+
+ // Animate a simple progress bar
+ static float progress = 0.0f, progress_dir = 1.0f;
+ if (animate)
+ {
+ progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
+ if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
+ if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
+ }
+
+ // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
+ ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
+ ImGui::Text("Progress Bar");
+
+ float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
+ char buf[32];
+ sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
+ ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Color/Picker Widgets"))
+ {
+ static ImVec4 color = ImColor(114, 144, 154, 200);
+
+ static bool alpha_preview = true;
+ static bool alpha_half_preview = false;
+ static bool drag_and_drop = true;
+ static bool options_menu = true;
+ static bool hdr = false;
+ ImGui::Checkbox("With Alpha Preview", &alpha_preview);
+ ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
+ ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
+ ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
+ ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
+ int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
+
+ ImGui::Text("Color widget:");
+ ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
+ ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
+
+ ImGui::Text("Color widget HSV with Alpha:");
+ ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
+
+ ImGui::Text("Color widget with Float Display:");
+ ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
+
+ ImGui::Text("Color button with Picker:");
+ ImGui::SameLine(); ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
+ ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
+
+ ImGui::Text("Color button with Custom Picker Popup:");
+
+ // Generate a dummy palette
+ static bool saved_palette_inited = false;
+ static ImVec4 saved_palette[32];
+ if (!saved_palette_inited)
+ for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
+ {
+ ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
+ saved_palette[n].w = 1.0f; // Alpha
+ }
+ saved_palette_inited = true;
+
+ static ImVec4 backup_color;
+ bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
+ ImGui::SameLine();
+ open_popup |= ImGui::Button("Palette");
+ if (open_popup)
+ {
+ ImGui::OpenPopup("mypicker");
+ backup_color = color;
+ }
+ if (ImGui::BeginPopup("mypicker"))
+ {
+ // FIXME: Adding a drag and drop example here would be perfect!
+ ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
+ ImGui::Separator();
+ ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
+ ImGui::SameLine();
+ ImGui::BeginGroup();
+ ImGui::Text("Current");
+ ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));
+ ImGui::Text("Previous");
+ if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))
+ color = backup_color;
+ ImGui::Separator();
+ ImGui::Text("Palette");
+ for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
+ {
+ ImGui::PushID(n);
+ if ((n % 8) != 0)
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
+ if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20)))
+ color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
+
+ if (ImGui::BeginDragDropTarget())
+ {
+ if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
+ memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
+ if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
+ memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
+ ImGui::EndDragDropTarget();
+ }
+
+ ImGui::PopID();
+ }
+ ImGui::EndGroup();
+ ImGui::EndPopup();
+ }
+
+ ImGui::Text("Color button only:");
+ ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
+
+ ImGui::Text("Color picker:");
+ static bool alpha = true;
+ static bool alpha_bar = true;
+ static bool side_preview = true;
+ static bool ref_color = false;
+ static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
+ static int inputs_mode = 2;
+ static int picker_mode = 0;
+ ImGui::Checkbox("With Alpha", &alpha);
+ ImGui::Checkbox("With Alpha Bar", &alpha_bar);
+ ImGui::Checkbox("With Side Preview", &side_preview);
+ if (side_preview)
+ {
+ ImGui::SameLine();
+ ImGui::Checkbox("With Ref Color", &ref_color);
+ if (ref_color)
+ {
+ ImGui::SameLine();
+ ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
+ }
+ }
+ ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
+ ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
+ ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
+ ImGuiColorEditFlags flags = misc_flags;
+ if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
+ if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
+ if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
+ if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
+ if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
+ if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
+ if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
+ if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
+ if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
+ ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
+
+ ImGui::Text("Programmatically set defaults:");
+ ImGui::SameLine(); ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
+ if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
+ ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV | ImGuiColorEditFlags_PickerHueBar);
+ if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
+ ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Range Widgets"))
+ {
+ static float begin = 10, end = 90;
+ static int begin_i = 100, end_i = 1000;
+ ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
+ ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Data Types"))
+ {
+ // The DragScalar/InputScalar/SliderScalar functions allow various data types: signed/unsigned int/long long and float/double
+ // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type,
+ // and passing all arguments by address.
+ // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
+ // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it
+ // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address
+ // to the generic function. For example:
+ // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
+ // {
+ // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
+ // }
+
+ // Limits (as helper variables that we can take the address of)
+ // Note that the SliderScalar function has a maximum usable range of half the natural type maximum, hence the /2 below.
+ #ifndef LLONG_MIN
+ ImS64 LLONG_MIN = -9223372036854775807LL - 1;
+ ImS64 LLONG_MAX = 9223372036854775807LL;
+ ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
+ #endif
+ const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2;
+ const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2;
+ const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2;
+ const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2;
+ const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
+ const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
+
+ // State
+ static ImS32 s32_v = -1;
+ static ImU32 u32_v = (ImU32)-1;
+ static ImS64 s64_v = -1;
+ static ImU64 u64_v = (ImU64)-1;
+ static float f32_v = 0.123f;
+ static double f64_v = 90000.01234567890123456789;
+
+ const float drag_speed = 0.2f;
+ static bool drag_clamp = false;
+ ImGui::Text("Drags:");
+ ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); ImGui::SameLine(); ShowHelpMarker("As with every widgets in dear imgui, we never modify values unless there is a user interaction.\nYou can override the clamping limits by using CTRL+Click to input a value.");
+ ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
+ ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
+ ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
+ ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
+ ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 1.0f);
+ ImGui::DragScalar("drag float ^2", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", 2.0f); ImGui::SameLine(); ShowHelpMarker("You can use the 'power' parameter to increase tweaking precision on one side of the range.");
+ ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams", 1.0f);
+ ImGui::DragScalar("drag double ^2", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", 2.0f);
+
+ ImGui::Text("Sliders");
+ ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d");
+ ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d");
+ ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d");
+ ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u");
+ ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u");
+ ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u");
+ ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%I64d");
+ ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
+ ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%I64d");
+ ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
+ ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
+ ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%I64u ms");
+ ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one);
+ ImGui::SliderScalar("slider float low^2", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", 2.0f);
+ ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e");
+ ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams", 1.0f);
+ ImGui::SliderScalar("slider double low^2",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", 2.0f);
+ ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams", 1.0f);
+
+ static bool inputs_step = true;
+ ImGui::Text("Inputs");
+ ImGui::Checkbox("Show step buttons", &inputs_step);
+ ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
+ ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
+ ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
+ ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
+ ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL);
+ ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL);
+ ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL);
+ ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Multi-component Widgets"))
+ {
+ static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
+ static int vec4i[4] = { 1, 5, 100, 255 };
+
+ ImGui::InputFloat2("input float2", vec4f);
+ ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
+ ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
+ ImGui::InputInt2("input int2", vec4i);
+ ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
+ ImGui::SliderInt2("slider int2", vec4i, 0, 255);
+ ImGui::Spacing();
+
+ ImGui::InputFloat3("input float3", vec4f);
+ ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
+ ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
+ ImGui::InputInt3("input int3", vec4i);
+ ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
+ ImGui::SliderInt3("slider int3", vec4i, 0, 255);
+ ImGui::Spacing();
+
+ ImGui::InputFloat4("input float4", vec4f);
+ ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
+ ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
+ ImGui::InputInt4("input int4", vec4i);
+ ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
+ ImGui::SliderInt4("slider int4", vec4i, 0, 255);
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Vertical Sliders"))
+ {
+ const float spacing = 4;
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
+
+ static int int_value = 0;
+ ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
+ ImGui::SameLine();
+
+ static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
+ ImGui::PushID("set1");
+ for (int i = 0; i < 7; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
+ ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
+ if (ImGui::IsItemActive() || ImGui::IsItemHovered())
+ ImGui::SetTooltip("%.3f", values[i]);
+ ImGui::PopStyleColor(4);
+ ImGui::PopID();
+ }
+ ImGui::PopID();
+
+ ImGui::SameLine();
+ ImGui::PushID("set2");
+ static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
+ const int rows = 3;
+ const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
+ for (int nx = 0; nx < 4; nx++)
+ {
+ if (nx > 0) ImGui::SameLine();
+ ImGui::BeginGroup();
+ for (int ny = 0; ny < rows; ny++)
+ {
+ ImGui::PushID(nx*rows+ny);
+ ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
+ if (ImGui::IsItemActive() || ImGui::IsItemHovered())
+ ImGui::SetTooltip("%.3f", values2[nx]);
+ ImGui::PopID();
+ }
+ ImGui::EndGroup();
+ }
+ ImGui::PopID();
+
+ ImGui::SameLine();
+ ImGui::PushID("set3");
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
+ ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
+ ImGui::PopStyleVar();
+ ImGui::PopID();
+ }
+ ImGui::PopID();
+ ImGui::PopStyleVar();
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Drag and Drop"))
+ {
+ {
+ // ColorEdit widgets automatically act as drag source and drag target.
+ // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets
+ // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo.
+ ImGui::BulletText("Drag and drop in standard widgets");
+ ImGui::Indent();
+ static float col1[3] = { 1.0f,0.0f,0.2f };
+ static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
+ ImGui::ColorEdit3("color 1", col1);
+ ImGui::ColorEdit4("color 2", col2);
+ ImGui::Unindent();
+ }
+
+ {
+ ImGui::BulletText("Drag and drop to copy/swap items");
+ ImGui::Indent();
+ enum Mode
+ {
+ Mode_Copy,
+ Mode_Move,
+ Mode_Swap
+ };
+ static int mode = 0;
+ if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
+ if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
+ if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
+ static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" };
+ for (int n = 0; n < IM_ARRAYSIZE(names); n++)
+ {
+ ImGui::PushID(n);
+ if ((n % 3) != 0)
+ ImGui::SameLine();
+ ImGui::Button(names[n], ImVec2(60,60));
+
+ // Our buttons are both drag sources and drag targets here!
+ if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
+ {
+ ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int)); // Set payload to carry the index of our item (could be anything)
+ if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); } // Display preview (could be anything, e.g. when dragging an image we could decide to display the filename and a small preview of the image, etc.)
+ if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
+ if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
+ ImGui::EndDragDropSource();
+ }
+ if (ImGui::BeginDragDropTarget())
+ {
+ if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
+ {
+ IM_ASSERT(payload->DataSize == sizeof(int));
+ int payload_n = *(const int*)payload->Data;
+ if (mode == Mode_Copy)
+ {
+ names[n] = names[payload_n];
+ }
+ if (mode == Mode_Move)
+ {
+ names[n] = names[payload_n];
+ names[payload_n] = "";
+ }
+ if (mode == Mode_Swap)
+ {
+ const char* tmp = names[n];
+ names[n] = names[payload_n];
+ names[payload_n] = tmp;
+ }
+ }
+ ImGui::EndDragDropTarget();
+ }
+ ImGui::PopID();
+ }
+ ImGui::Unindent();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)"))
+ {
+ // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined.
+ // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code).
+ static int item_type = 1;
+ static bool b = false;
+ static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
+ ImGui::RadioButton("Text", &item_type, 0);
+ ImGui::RadioButton("Button", &item_type, 1);
+ ImGui::RadioButton("CheckBox", &item_type, 2);
+ ImGui::RadioButton("SliderFloat", &item_type, 3);
+ ImGui::RadioButton("ColorEdit4", &item_type, 4);
+ ImGui::RadioButton("ListBox", &item_type, 5);
+ ImGui::Separator();
+ bool ret = false;
+ if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
+ if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button
+ if (item_type == 2) { ret = ImGui::Checkbox("ITEM: CheckBox", &b); } // Testing checkbox
+ if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item
+ if (item_type == 4) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
+ if (item_type == 5) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
+ ImGui::BulletText(
+ "Return value = %d\n"
+ "IsItemFocused() = %d\n"
+ "IsItemHovered() = %d\n"
+ "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
+ "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
+ "IsItemHovered(_AllowWhenOverlapped) = %d\n"
+ "IsItemHovered(_RectOnly) = %d\n"
+ "IsItemActive() = %d\n"
+ "IsItemEdited() = %d\n"
+ "IsItemDeactivated() = %d\n"
+ "IsItemDeactivatedEdit() = %d\n"
+ "IsItemVisible() = %d\n"
+ "GetItemRectMin() = (%.1f, %.1f)\n"
+ "GetItemRectMax() = (%.1f, %.1f)\n"
+ "GetItemRectSize() = (%.1f, %.1f)",
+ ret,
+ ImGui::IsItemFocused(),
+ ImGui::IsItemHovered(),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
+ ImGui::IsItemActive(),
+ ImGui::IsItemEdited(),
+ ImGui::IsItemDeactivated(),
+ ImGui::IsItemDeactivatedAfterEdit(),
+ ImGui::IsItemVisible(),
+ ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
+ ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
+ ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
+ );
+
+ static bool embed_all_inside_a_child_window = false;
+ ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
+ if (embed_all_inside_a_child_window)
+ ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true);
+
+ // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined.
+ ImGui::BulletText(
+ "IsWindowFocused() = %d\n"
+ "IsWindowFocused(_ChildWindows) = %d\n"
+ "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
+ "IsWindowFocused(_RootWindow) = %d\n"
+ "IsWindowFocused(_AnyWindow) = %d\n",
+ ImGui::IsWindowFocused(),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
+
+ // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined.
+ ImGui::BulletText(
+ "IsWindowHovered() = %d\n"
+ "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
+ "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
+ "IsWindowHovered(_ChildWindows) = %d\n"
+ "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
+ "IsWindowHovered(_RootWindow) = %d\n"
+ "IsWindowHovered(_AnyWindow) = %d\n",
+ ImGui::IsWindowHovered(),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
+
+ ImGui::BeginChild("child", ImVec2(0, 50), true);
+ ImGui::Text("This is another child window for testing the _ChildWindows flag.");
+ ImGui::EndChild();
+ if (embed_all_inside_a_child_window)
+ ImGui::EndChild();
+
+ // Calling IsItemHovered() after begin returns the hovered status of the title bar.
+ // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window.
+ static bool test_window = false;
+ ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
+ if (test_window)
+ {
+ ImGui::Begin("Title bar Hovered/Active tests", &test_window);
+ if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
+ {
+ if (ImGui::MenuItem("Close")) { test_window = false; }
+ ImGui::EndPopup();
+ }
+ ImGui::Text(
+ "IsItemHovered() after begin = %d (== is title bar hovered)\n"
+ "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
+ ImGui::IsItemHovered(), ImGui::IsItemActive());
+ ImGui::End();
+ }
+
+ ImGui::TreePop();
+ }
+}
+
+static void ShowDemoWindowLayout()
+{
+ if (!ImGui::CollapsingHeader("Layout"))
+ return;
+
+ if (ImGui::TreeNode("Child windows"))
+ {
+ ShowHelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
+ static bool disable_mouse_wheel = false;
+ static bool disable_menu = false;
+ ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
+ ImGui::Checkbox("Disable Menu", &disable_menu);
+
+ static int line = 50;
+ bool goto_line = ImGui::Button("Goto");
+ ImGui::SameLine();
+ ImGui::PushItemWidth(100);
+ goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
+ ImGui::PopItemWidth();
+
+ // Child 1: no border, enable horizontal scrollbar
+ {
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0);
+ ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags);
+ for (int i = 0; i < 100; i++)
+ {
+ ImGui::Text("%04d: scrollable region", i);
+ if (goto_line && line == i)
+ ImGui::SetScrollHereY();
+ }
+ if (goto_line && line >= 100)
+ ImGui::SetScrollHereY();
+ ImGui::EndChild();
+ }
+
+ ImGui::SameLine();
+
+ // Child 2: rounded border
+ {
+ ImGuiWindowFlags window_flags = (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar);
+ ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
+ ImGui::BeginChild("Child2", ImVec2(0, 260), true, window_flags);
+ if (!disable_menu && ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("Menu"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+ ImGui::Columns(2);
+ for (int i = 0; i < 100; i++)
+ {
+ char buf[32];
+ sprintf(buf, "%03d", i);
+ ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
+ ImGui::NextColumn();
+ }
+ ImGui::EndChild();
+ ImGui::PopStyleVar();
+ }
+
+ ImGui::Separator();
+
+ // Demonstrate a few extra things
+ // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
+ // - Using SetCursorPos() to position the child window (because the child window is an item from the POV of the parent window)
+ // You can also call SetNextWindowPos() to position the child window. The parent window will effectively layout from this position.
+ // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from the POV of the parent window)
+ // See "Widgets" -> "Querying Status (Active/Focused/Hovered etc.)" section for more details about this.
+ {
+ ImGui::SetCursorPosX(50);
+ ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
+ ImGui::BeginChild("blah", ImVec2(200, 100), true, ImGuiWindowFlags_None);
+ for (int n = 0; n < 50; n++)
+ ImGui::Text("Some test %d", n);
+ ImGui::EndChild();
+ ImVec2 child_rect_min = ImGui::GetItemRectMin();
+ ImVec2 child_rect_max = ImGui::GetItemRectMax();
+ ImGui::PopStyleColor();
+ ImGui::Text("Rect of child window is: (%.0f,%.0f) (%.0f,%.0f)", child_rect_min.x, child_rect_min.y, child_rect_max.x, child_rect_max.y);
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Widgets Width"))
+ {
+ static float f = 0.0f;
+ ImGui::Text("PushItemWidth(100)");
+ ImGui::SameLine(); ShowHelpMarker("Fixed width.");
+ ImGui::PushItemWidth(100);
+ ImGui::DragFloat("float##1", &f);
+ ImGui::PopItemWidth();
+
+ ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
+ ImGui::SameLine(); ShowHelpMarker("Half of window width.");
+ ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
+ ImGui::DragFloat("float##2", &f);
+ ImGui::PopItemWidth();
+
+ ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
+ ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
+ ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
+ ImGui::DragFloat("float##3", &f);
+ ImGui::PopItemWidth();
+
+ ImGui::Text("PushItemWidth(-100)");
+ ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
+ ImGui::PushItemWidth(-100);
+ ImGui::DragFloat("float##4", &f);
+ ImGui::PopItemWidth();
+
+ ImGui::Text("PushItemWidth(-1)");
+ ImGui::SameLine(); ShowHelpMarker("Align to right edge");
+ ImGui::PushItemWidth(-1);
+ ImGui::DragFloat("float##5", &f);
+ ImGui::PopItemWidth();
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Basic Horizontal Layout"))
+ {
+ ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
+
+ // Text
+ ImGui::Text("Two items: Hello"); ImGui::SameLine();
+ ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
+
+ // Adjust spacing
+ ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
+ ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
+
+ // Button
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("Normal buttons"); ImGui::SameLine();
+ ImGui::Button("Banana"); ImGui::SameLine();
+ ImGui::Button("Apple"); ImGui::SameLine();
+ ImGui::Button("Corniflower");
+
+ // Button
+ ImGui::Text("Small buttons"); ImGui::SameLine();
+ ImGui::SmallButton("Like this one"); ImGui::SameLine();
+ ImGui::Text("can fit within a text block.");
+
+ // Aligned to arbitrary position. Easy/cheap column.
+ ImGui::Text("Aligned");
+ ImGui::SameLine(150); ImGui::Text("x=150");
+ ImGui::SameLine(300); ImGui::Text("x=300");
+ ImGui::Text("Aligned");
+ ImGui::SameLine(150); ImGui::SmallButton("x=150");
+ ImGui::SameLine(300); ImGui::SmallButton("x=300");
+
+ // Checkbox
+ static bool c1 = false, c2 = false, c3 = false, c4 = false;
+ ImGui::Checkbox("My", &c1); ImGui::SameLine();
+ ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
+ ImGui::Checkbox("Is", &c3); ImGui::SameLine();
+ ImGui::Checkbox("Rich", &c4);
+
+ // Various
+ static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
+ ImGui::PushItemWidth(80);
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
+ static int item = -1;
+ ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
+ ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
+ ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
+ ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
+ ImGui::PopItemWidth();
+
+ ImGui::PushItemWidth(80);
+ ImGui::Text("Lists:");
+ static int selection[4] = { 0, 1, 2, 3 };
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
+ ImGui::PopID();
+ //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
+ }
+ ImGui::PopItemWidth();
+
+ // Dummy
+ ImVec2 button_sz(40, 40);
+ ImGui::Button("A", button_sz); ImGui::SameLine();
+ ImGui::Dummy(button_sz); ImGui::SameLine();
+ ImGui::Button("B", button_sz);
+
+ // Manually wrapping (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
+ ImGui::Text("Manually wrapping:");
+ ImGuiStyle& style = ImGui::GetStyle();
+ int buttons_count = 20;
+ float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
+ for (int n = 0; n < buttons_count; n++)
+ {
+ ImGui::PushID(n);
+ ImGui::Button("Box", button_sz);
+ float last_button_x2 = ImGui::GetItemRectMax().x;
+ float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
+ if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
+ ImGui::SameLine();
+ ImGui::PopID();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Tabs"))
+ {
+ if (ImGui::TreeNode("Basic"))
+ {
+ ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
+ if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
+ {
+ if (ImGui::BeginTabItem("Avocado"))
+ {
+ ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("Broccoli"))
+ {
+ ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("Cucumber"))
+ {
+ ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Advanced & Close Button"))
+ {
+ // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
+ static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_Reorderable);
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
+ if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
+ tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
+ if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
+ tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
+ if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
+ tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
+
+ // Tab Bar
+ const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
+ static bool opened[4] = { true, true, true, true }; // Persistent user state
+ for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
+ {
+ if (n > 0) { ImGui::SameLine(); }
+ ImGui::Checkbox(names[n], &opened[n]);
+ }
+
+ // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): the underlying bool will be set to false when the tab is closed.
+ if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
+ if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n]))
+ {
+ ImGui::Text("This is the %s tab!", names[n]);
+ if (n & 1)
+ ImGui::Text("I am an odd tab.");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Groups"))
+ {
+ ShowHelpMarker("Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.");
+ ImGui::BeginGroup();
+ {
+ ImGui::BeginGroup();
+ ImGui::Button("AAA");
+ ImGui::SameLine();
+ ImGui::Button("BBB");
+ ImGui::SameLine();
+ ImGui::BeginGroup();
+ ImGui::Button("CCC");
+ ImGui::Button("DDD");
+ ImGui::EndGroup();
+ ImGui::SameLine();
+ ImGui::Button("EEE");
+ ImGui::EndGroup();
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("First group hovered");
+ }
+ // Capture the group size and create widgets using the same size
+ ImVec2 size = ImGui::GetItemRectSize();
+ const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
+ ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
+
+ ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
+ ImGui::SameLine();
+ ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
+ ImGui::EndGroup();
+ ImGui::SameLine();
+
+ ImGui::Button("LEVERAGE\nBUZZWORD", size);
+ ImGui::SameLine();
+
+ if (ImGui::ListBoxHeader("List", size))
+ {
+ ImGui::Selectable("Selected", true);
+ ImGui::Selectable("Not Selected", false);
+ ImGui::ListBoxFooter();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Text Baseline Alignment"))
+ {
+ ShowHelpMarker("This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets.");
+
+ ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("Banana");
+
+ ImGui::Text("Banana"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("One\nTwo\nThree");
+
+ ImGui::Button("HOP##1"); ImGui::SameLine();
+ ImGui::Text("Banana"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("Banana");
+
+ ImGui::Button("HOP##2"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("Banana");
+
+ ImGui::Button("TEST##1"); ImGui::SameLine();
+ ImGui::Text("TEST"); ImGui::SameLine();
+ ImGui::SmallButton("TEST##2");
+
+ ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets.
+ ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
+ ImGui::Button("Widget##1"); ImGui::SameLine();
+ ImGui::Text("Widget"); ImGui::SameLine();
+ ImGui::SmallButton("Widget##2"); ImGui::SameLine();
+ ImGui::Button("Widget##3");
+
+ // Tree
+ const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
+ ImGui::Button("Button##1");
+ ImGui::SameLine(0.0f, spacing);
+ if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
+
+ ImGui::AlignTextToFramePadding(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
+ bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
+ ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
+ if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
+
+ // Bullet
+ ImGui::Button("Button##3");
+ ImGui::SameLine(0.0f, spacing);
+ ImGui::BulletText("Bullet text");
+
+ ImGui::AlignTextToFramePadding();
+ ImGui::BulletText("Node");
+ ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Scrolling"))
+ {
+ ShowHelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position.");
+
+ static bool track = true;
+ static int track_line = 50, scroll_to_px = 200;
+ ImGui::Checkbox("Track", &track);
+ ImGui::PushItemWidth(100);
+ ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d");
+ bool scroll_to = ImGui::Button("Scroll To Pos");
+ ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %d px");
+ ImGui::PopItemWidth();
+ if (scroll_to) track = false;
+
+ for (int i = 0; i < 5; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::BeginGroup();
+ ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
+ ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
+ if (scroll_to)
+ ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
+ for (int line = 0; line < 100; line++)
+ {
+ if (track && line == track_line)
+ {
+ ImGui::TextColored(ImVec4(1,1,0,1), "Line %d", line);
+ ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
+ }
+ else
+ {
+ ImGui::Text("Line %d", line);
+ }
+ }
+ float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
+ ImGui::EndChild();
+ ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
+ ImGui::EndGroup();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Horizontal Scrolling"))
+ {
+ ShowHelpMarker("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\nYou may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
+ static int lines = 7;
+ ImGui::SliderInt("Lines", &lines, 1, 15);
+ ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
+ ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
+ for (int line = 0; line < lines; line++)
+ {
+ // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off
+ // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API)
+ int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
+ for (int n = 0; n < num_buttons; n++)
+ {
+ if (n > 0) ImGui::SameLine();
+ ImGui::PushID(n + line * 1000);
+ char num_buf[16];
+ sprintf(num_buf, "%d", n);
+ const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf;
+ float hue = n*0.05f;
+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
+ ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
+ ImGui::PopStyleColor(3);
+ ImGui::PopID();
+ }
+ }
+ float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
+ ImGui::EndChild();
+ ImGui::PopStyleVar(2);
+ float scroll_x_delta = 0.0f;
+ ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
+ ImGui::Text("Scroll from code"); ImGui::SameLine();
+ ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
+ ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
+ if (scroll_x_delta != 0.0f)
+ {
+ ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window)
+ ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
+ ImGui::End();
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Clipping"))
+ {
+ static ImVec2 size(100, 100), offset(50, 20);
+ ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
+ ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
+ ImGui::TextWrapped("(Click and drag)");
+ ImVec2 pos = ImGui::GetCursorScreenPos();
+ ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
+ ImGui::InvisibleButton("##dummy", size);
+ if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
+ ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(90, 90, 120, 255));
+ ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x + offset.x, pos.y + offset.y), IM_COL32(255, 255, 255, 255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
+ ImGui::TreePop();
+ }
+}
+
+static void ShowDemoWindowPopups()
+{
+ if (!ImGui::CollapsingHeader("Popups & Modal windows"))
+ return;
+
+ // The properties of popups windows are:
+ // - They block normal mouse hovering detection outside them. (*)
+ // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
+ // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls.
+ // User can manipulate the visibility state by calling OpenPopup().
+ // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
+ // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time.
+
+ // Typical use for regular windows:
+ // bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End();
+ // Typical use for popups:
+ // if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
+
+ // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
+ // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
+
+ if (ImGui::TreeNode("Popups"))
+ {
+ ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
+
+ static int selected_fish = -1;
+ const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
+ static bool toggles[] = { true, false, false, false, false };
+
+ // Simple selection popup
+ // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
+ if (ImGui::Button("Select.."))
+ ImGui::OpenPopup("my_select_popup");
+ ImGui::SameLine();
+ ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
+ if (ImGui::BeginPopup("my_select_popup"))
+ {
+ ImGui::Text("Aquarium");
+ ImGui::Separator();
+ for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+ if (ImGui::Selectable(names[i]))
+ selected_fish = i;
+ ImGui::EndPopup();
+ }
+
+ // Showing a menu with toggles
+ if (ImGui::Button("Toggle.."))
+ ImGui::OpenPopup("my_toggle_popup");
+ if (ImGui::BeginPopup("my_toggle_popup"))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+ ImGui::MenuItem(names[i], "", &toggles[i]);
+ if (ImGui::BeginMenu("Sub-menu"))
+ {
+ ImGui::MenuItem("Click me");
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+ ImGui::Text("Tooltip here");
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("I am a tooltip over a popup");
+
+ if (ImGui::Button("Stacked Popup"))
+ ImGui::OpenPopup("another popup");
+ if (ImGui::BeginPopup("another popup"))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+ ImGui::MenuItem(names[i], "", &toggles[i]);
+ if (ImGui::BeginMenu("Sub-menu"))
+ {
+ ImGui::MenuItem("Click me");
+ ImGui::EndMenu();
+ }
+ ImGui::EndPopup();
+ }
+ ImGui::EndPopup();
+ }
+
+ // Call the more complete ShowExampleMenuFile which we use in various places of this demo
+ if (ImGui::Button("File Menu.."))
+ ImGui::OpenPopup("my_file_popup");
+ if (ImGui::BeginPopup("my_file_popup"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndPopup();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Context menus"))
+ {
+ // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
+ // if (IsItemHovered() && IsMouseReleased(0))
+ // OpenPopup(id);
+ // return BeginPopup(id);
+ // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
+ static float value = 0.5f;
+ ImGui::Text("Value = %.3f (<-- right-click here)", value);
+ if (ImGui::BeginPopupContextItem("item context menu"))
+ {
+ if (ImGui::Selectable("Set to zero")) value = 0.0f;
+ if (ImGui::Selectable("Set to PI")) value = 3.1415f;
+ ImGui::PushItemWidth(-1);
+ ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
+ ImGui::PopItemWidth();
+ ImGui::EndPopup();
+ }
+
+ // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
+ // So here we will make it that clicking on the text field with the right mouse button (1) will toggle the visibility of the popup above.
+ ImGui::Text("(You can also right-click me to the same popup as above.)");
+ ImGui::OpenPopupOnItemClick("item context menu", 1);
+
+ // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
+ // BeginPopupContextItem() will use the last item ID as the popup ID.
+ // In addition here, we want to include your editable label inside the button label. We use the ### operator to override the ID (read FAQ about ID for details)
+ static char name[32] = "Label1";
+ char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
+ ImGui::Button(buf);
+ if (ImGui::BeginPopupContextItem())
+ {
+ ImGui::Text("Edit name:");
+ ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+ ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Modals"))
+ {
+ ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
+
+ if (ImGui::Button("Delete.."))
+ ImGui::OpenPopup("Delete?");
+
+ if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
+ ImGui::Separator();
+
+ //static int dummy_i = 0;
+ //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
+
+ static bool dont_ask_me_next_time = false;
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
+ ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
+ ImGui::PopStyleVar();
+
+ if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
+ ImGui::SetItemDefaultFocus();
+ ImGui::SameLine();
+ if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
+ ImGui::EndPopup();
+ }
+
+ if (ImGui::Button("Stacked modals.."))
+ ImGui::OpenPopup("Stacked 1");
+ if (ImGui::BeginPopupModal("Stacked 1"))
+ {
+ ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
+ static int item = 1;
+ ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
+ static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
+ ImGui::ColorEdit4("color", color); // This is to test behavior of stacked regular popups over a modal
+
+ if (ImGui::Button("Add another modal.."))
+ ImGui::OpenPopup("Stacked 2");
+
+ // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which will close the popup.
+ // Note that the visibility state of popups is owned by imgui, so the input value of the bool actually doesn't matter here.
+ bool dummy_open = true;
+ if (ImGui::BeginPopupModal("Stacked 2", &dummy_open))
+ {
+ ImGui::Text("Hello from Stacked The Second!");
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Menus inside a regular window"))
+ {
+ ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
+ ImGui::Separator();
+ // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above.
+ // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here
+ // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus.
+ ImGui::PushID("foo");
+ ImGui::MenuItem("Menu item", "CTRL+M");
+ if (ImGui::BeginMenu("Menu inside a regular window"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::PopID();
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+}
+
+static void ShowDemoWindowColumns()
+{
+ if (!ImGui::CollapsingHeader("Columns"))
+ return;
+
+ ImGui::PushID("Columns");
+
+ // Basic columns
+ if (ImGui::TreeNode("Basic"))
+ {
+ ImGui::Text("Without border:");
+ ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border
+ ImGui::Separator();
+ for (int n = 0; n < 14; n++)
+ {
+ char label[32];
+ sprintf(label, "Item %d", n);
+ if (ImGui::Selectable(label)) {}
+ //if (ImGui::Button(label, ImVec2(-1,0))) {}
+ ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ ImGui::Separator();
+
+ ImGui::Text("With border:");
+ ImGui::Columns(4, "mycolumns"); // 4-ways, with border
+ ImGui::Separator();
+ ImGui::Text("ID"); ImGui::NextColumn();
+ ImGui::Text("Name"); ImGui::NextColumn();
+ ImGui::Text("Path"); ImGui::NextColumn();
+ ImGui::Text("Hovered"); ImGui::NextColumn();
+ ImGui::Separator();
+ const char* names[3] = { "One", "Two", "Three" };
+ const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
+ static int selected = -1;
+ for (int i = 0; i < 3; i++)
+ {
+ char label[32];
+ sprintf(label, "%04d", i);
+ if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
+ selected = i;
+ bool hovered = ImGui::IsItemHovered();
+ ImGui::NextColumn();
+ ImGui::Text(names[i]); ImGui::NextColumn();
+ ImGui::Text(paths[i]); ImGui::NextColumn();
+ ImGui::Text("%d", hovered); ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ // Create multiple items in a same cell before switching to next column
+ if (ImGui::TreeNode("Mixed items"))
+ {
+ ImGui::Columns(3, "mixed");
+ ImGui::Separator();
+
+ ImGui::Text("Hello");
+ ImGui::Button("Banana");
+ ImGui::NextColumn();
+
+ ImGui::Text("ImGui");
+ ImGui::Button("Apple");
+ static float foo = 1.0f;
+ ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
+ ImGui::Text("An extra line here.");
+ ImGui::NextColumn();
+
+ ImGui::Text("Sailor");
+ ImGui::Button("Corniflower");
+ static float bar = 1.0f;
+ ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
+ ImGui::NextColumn();
+
+ if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+ if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+ if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ // Word wrapping
+ if (ImGui::TreeNode("Word-wrapping"))
+ {
+ ImGui::Columns(2, "word-wrapping");
+ ImGui::Separator();
+ ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
+ ImGui::TextWrapped("Hello Left");
+ ImGui::NextColumn();
+ ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
+ ImGui::TextWrapped("Hello Right");
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Borders"))
+ {
+ // NB: Future columns API should allow automatic horizontal borders.
+ static bool h_borders = true;
+ static bool v_borders = true;
+ ImGui::Checkbox("horizontal", &h_borders);
+ ImGui::SameLine();
+ ImGui::Checkbox("vertical", &v_borders);
+ ImGui::Columns(4, NULL, v_borders);
+ for (int i = 0; i < 4*3; i++)
+ {
+ if (h_borders && ImGui::GetColumnIndex() == 0)
+ ImGui::Separator();
+ ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
+ ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
+ ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ if (h_borders)
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ // Scrolling columns
+ /*
+ if (ImGui::TreeNode("Vertical Scrolling"))
+ {
+ ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
+ ImGui::Columns(3);
+ ImGui::Text("ID"); ImGui::NextColumn();
+ ImGui::Text("Name"); ImGui::NextColumn();
+ ImGui::Text("Path"); ImGui::NextColumn();
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::EndChild();
+ ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
+ ImGui::Columns(3);
+ for (int i = 0; i < 10; i++)
+ {
+ ImGui::Text("%04d", i); ImGui::NextColumn();
+ ImGui::Text("Foobar"); ImGui::NextColumn();
+ ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ ImGui::EndChild();
+ ImGui::TreePop();
+ }
+ */
+
+ if (ImGui::TreeNode("Horizontal Scrolling"))
+ {
+ ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
+ ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
+ ImGui::Columns(10);
+ int ITEMS_COUNT = 2000;
+ ImGuiListClipper clipper(ITEMS_COUNT); // Also demonstrate using the clipper for large list
+ while (clipper.Step())
+ {
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ for (int j = 0; j < 10; j++)
+ {
+ ImGui::Text("Line %d Column %d...", i, j);
+ ImGui::NextColumn();
+ }
+ }
+ ImGui::Columns(1);
+ ImGui::EndChild();
+ ImGui::TreePop();
+ }
+
+ bool node_open = ImGui::TreeNode("Tree within single cell");
+ ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
+ if (node_open)
+ {
+ ImGui::Columns(2, "tree items");
+ ImGui::Separator();
+ if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
+ if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+}
+
+static void ShowDemoWindowMisc()
+{
+ if (ImGui::CollapsingHeader("Filtering"))
+ {
+ static ImGuiTextFilter filter;
+ ImGui::Text("Filter usage:\n"
+ " \"\" display all lines\n"
+ " \"xxx\" display lines containing \"xxx\"\n"
+ " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
+ " \"-xxx\" hide lines containing \"xxx\"");
+ filter.Draw();
+ const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
+ for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
+ if (filter.PassFilter(lines[i]))
+ ImGui::BulletText("%s", lines[i]);
+ }
+
+ if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
+ ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
+ ImGui::Text("WantTextInput: %d", io.WantTextInput);
+ ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
+ ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
+
+ if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
+ {
+ if (ImGui::IsMousePosValid())
+ ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
+ else
+ ImGui::Text("Mouse pos: <INVALID>");
+ ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
+ ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
+ ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
+
+ ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
+ ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
+ ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
+ ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
+
+ ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
+ ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
+ ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
+
+ ImGui::Button("Hovering me sets the\nkeyboard capture flag");
+ if (ImGui::IsItemHovered())
+ ImGui::CaptureKeyboardFromApp(true);
+ ImGui::SameLine();
+ ImGui::Button("Holding me clears the\nthe keyboard capture flag");
+ if (ImGui::IsItemActive())
+ ImGui::CaptureKeyboardFromApp(false);
+
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Tabbing"))
+ {
+ ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
+ static char buf[32] = "dummy";
+ ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
+ ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
+ ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
+ ImGui::PushAllowKeyboardFocus(false);
+ ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
+ //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
+ ImGui::PopAllowKeyboardFocus();
+ ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Focus from code"))
+ {
+ bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
+ bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
+ bool focus_3 = ImGui::Button("Focus on 3");
+ int has_focus = 0;
+ static char buf[128] = "click on a button to set focus";
+
+ if (focus_1) ImGui::SetKeyboardFocusHere();
+ ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
+ if (ImGui::IsItemActive()) has_focus = 1;
+
+ if (focus_2) ImGui::SetKeyboardFocusHere();
+ ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
+ if (ImGui::IsItemActive()) has_focus = 2;
+
+ ImGui::PushAllowKeyboardFocus(false);
+ if (focus_3) ImGui::SetKeyboardFocusHere();
+ ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
+ if (ImGui::IsItemActive()) has_focus = 3;
+ ImGui::PopAllowKeyboardFocus();
+
+ if (has_focus)
+ ImGui::Text("Item with focus: %d", has_focus);
+ else
+ ImGui::Text("Item with focus: <none>");
+
+ // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
+ static float f3[3] = { 0.0f, 0.0f, 0.0f };
+ int focus_ahead = -1;
+ if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine();
+ if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine();
+ if (ImGui::Button("Focus on Z")) focus_ahead = 2;
+ if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
+ ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
+
+ ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Dragging"))
+ {
+ ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
+ for (int button = 0; button < 3; button++)
+ ImGui::Text("IsMouseDragging(%d):\n w/ default threshold: %d,\n w/ zero threshold: %d\n w/ large threshold: %d",
+ button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
+ ImGui::Button("Drag Me");
+ if (ImGui::IsItemActive())
+ {
+ // Draw a line between the button and the mouse cursor
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+ draw_list->PushClipRectFullScreen();
+ draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f);
+ draw_list->PopClipRect();
+
+ // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
+ // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
+ ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
+ ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
+ ImVec2 mouse_delta = io.MouseDelta;
+ ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);
+ }
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Mouse cursors"))
+ {
+ const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" };
+ IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
+
+ ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
+ ImGui::Text("Hover to see mouse cursors:");
+ ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
+ for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
+ {
+ char label[32];
+ sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
+ ImGui::Bullet(); ImGui::Selectable(label, false);
+ if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
+ ImGui::SetMouseCursor(i);
+ }
+ ImGui::TreePop();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] About Window / ShowAboutWindow()
+// Access from ImGui Demo -> Help -> About
+//-----------------------------------------------------------------------------
+
+void ImGui::ShowAboutWindow(bool* p_open)
+{
+ if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::End();
+ return;
+ }
+ ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
+ ImGui::Separator();
+ ImGui::Text("By Omar Cornut and all dear imgui contributors.");
+ ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
+
+ static bool show_config_info = false;
+ ImGui::Checkbox("Config/Build Information", &show_config_info);
+ if (show_config_info)
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ ImGuiStyle& style = ImGui::GetStyle();
+
+ bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
+ ImGui::BeginChildFrame(ImGui::GetID("cfginfos"), ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18), ImGuiWindowFlags_NoMove);
+ if (copy_to_clipboard)
+ ImGui::LogToClipboard();
+
+ ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
+ ImGui::Separator();
+ ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
+ ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
+#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_MATH_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_MATH_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
+ ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
+#endif
+#ifdef IMGUI_USE_BGRA_PACKED_COLOR
+ ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
+#endif
+#ifdef _WIN32
+ ImGui::Text("define: _WIN32");
+#endif
+#ifdef _WIN64
+ ImGui::Text("define: _WIN64");
+#endif
+#ifdef __linux__
+ ImGui::Text("define: __linux__");
+#endif
+#ifdef __APPLE__
+ ImGui::Text("define: __APPLE__");
+#endif
+#ifdef _MSC_VER
+ ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
+#endif
+#ifdef __MINGW32__
+ ImGui::Text("define: __MINGW32__");
+#endif
+#ifdef __MINGW64__
+ ImGui::Text("define: __MINGW64__");
+#endif
+#ifdef __GNUC__
+ ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
+#endif
+#ifdef __clang_version__
+ ImGui::Text("define: __clang_version__=%s", __clang_version__);
+#endif
+ ImGui::Separator();
+ ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
+ ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
+ ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) ImGui::Text(" NavEnableKeyboard");
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) ImGui::Text(" NavEnableGamepad");
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) ImGui::Text(" NavEnableSetMousePos");
+ if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard) ImGui::Text(" NavNoCaptureKeyboard");
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) ImGui::Text(" NoMouse");
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) ImGui::Text(" NoMouseCursorChange");
+ if (io.MouseDrawCursor) ImGui::Text("io.MouseDrawCursor");
+ if (io.ConfigMacOSXBehaviors) ImGui::Text("io.ConfigMacOSXBehaviors");
+ if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink");
+ if (io.ConfigWindowsResizeFromEdges) ImGui::Text("io.ConfigWindowsResizeFromEdges");
+ if (io.ConfigWindowsMoveFromTitleBarOnly) ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
+ ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
+ if (io.BackendFlags & ImGuiBackendFlags_HasGamepad) ImGui::Text(" HasGamepad");
+ if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) ImGui::Text(" HasMouseCursors");
+ if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos) ImGui::Text(" HasSetMousePos");
+ ImGui::Separator();
+ ImGui::Text("io.Fonts: %d fonts, Flags: 0x%08X, TexSize: %d,%d", io.Fonts->Fonts.Size, io.Fonts->Flags, io.Fonts->TexWidth, io.Fonts->TexHeight);
+ ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
+ ImGui::Separator();
+ ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
+ ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
+ ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
+ ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
+ ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
+ ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
+ ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
+
+ if (copy_to_clipboard)
+ ImGui::LogFinish();
+ ImGui::EndChildFrame();
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Style Editor / ShowStyleEditor()
+//-----------------------------------------------------------------------------
+
+// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
+// Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally.
+bool ImGui::ShowStyleSelector(const char* label)
+{
+ static int style_idx = -1;
+ if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
+ {
+ switch (style_idx)
+ {
+ case 0: ImGui::StyleColorsClassic(); break;
+ case 1: ImGui::StyleColorsDark(); break;
+ case 2: ImGui::StyleColorsLight(); break;
+ }
+ return true;
+ }
+ return false;
+}
+
+// Demo helper function to select among loaded fonts.
+// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
+void ImGui::ShowFontSelector(const char* label)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImFont* font_current = ImGui::GetFont();
+ if (ImGui::BeginCombo(label, font_current->GetDebugName()))
+ {
+ for (int n = 0; n < io.Fonts->Fonts.Size; n++)
+ if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current))
+ io.FontDefault = io.Fonts->Fonts[n];
+ ImGui::EndCombo();
+ }
+ ImGui::SameLine();
+ ShowHelpMarker(
+ "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
+ "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
+ "- Read FAQ and documentation in misc/fonts/ for more details.\n"
+ "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
+}
+
+void ImGui::ShowStyleEditor(ImGuiStyle* ref)
+{
+ // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
+ ImGuiStyle& style = ImGui::GetStyle();
+ static ImGuiStyle ref_saved_style;
+
+ // Default to using internal storage as reference
+ static bool init = true;
+ if (init && ref == NULL)
+ ref_saved_style = style;
+ init = false;
+ if (ref == NULL)
+ ref = &ref_saved_style;
+
+ ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
+
+ if (ImGui::ShowStyleSelector("Colors##Selector"))
+ ref_saved_style = style;
+ ImGui::ShowFontSelector("Fonts##Selector");
+
+ // Simplified Settings
+ if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
+ style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
+ { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
+ ImGui::SameLine();
+ { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
+ ImGui::SameLine();
+ { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
+
+ // Save/Revert button
+ if (ImGui::Button("Save Ref"))
+ *ref = ref_saved_style = style;
+ ImGui::SameLine();
+ if (ImGui::Button("Revert Ref"))
+ style = *ref;
+ ImGui::SameLine();
+ ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
+
+ ImGui::Separator();
+
+ if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
+ {
+ if (ImGui::BeginTabItem("Sizes"))
+ {
+ ImGui::Text("Main");
+ ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
+ ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
+ ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
+ ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
+ ImGui::Text("Borders");
+ ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::Text("Rounding");
+ ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
+ ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
+ ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::Text("Alignment");
+ ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
+ ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
+ ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
+ ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Colors"))
+ {
+ static int output_dest = 0;
+ static bool output_only_modified = true;
+ if (ImGui::Button("Export Unsaved"))
+ {
+ if (output_dest == 0)
+ ImGui::LogToClipboard();
+ else
+ ImGui::LogToTTY();
+ ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const ImVec4& col = style.Colors[i];
+ const char* name = ImGui::GetStyleColorName(i);
+ if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
+ ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
+ }
+ ImGui::LogFinish();
+ }
+ ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
+ ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
+
+ static ImGuiTextFilter filter;
+ filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
+
+ static ImGuiColorEditFlags alpha_flags = 0;
+ ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
+ ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
+ ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); ImGui::SameLine();
+ ShowHelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu.");
+
+ ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
+ ImGui::PushItemWidth(-160);
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const char* name = ImGui::GetStyleColorName(i);
+ if (!filter.PassFilter(name))
+ continue;
+ ImGui::PushID(i);
+ ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
+ if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
+ {
+ // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
+ // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
+ }
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
+ ImGui::TextUnformatted(name);
+ ImGui::PopID();
+ }
+ ImGui::PopItemWidth();
+ ImGui::EndChild();
+
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Fonts"))
+ {
+ ImFontAtlas* atlas = ImGui::GetIO().Fonts;
+ ShowHelpMarker("Read FAQ and misc/fonts/README.txt for details on font loading.");
+ ImGui::PushItemWidth(120);
+ for (int i = 0; i < atlas->Fonts.Size; i++)
+ {
+ ImFont* font = atlas->Fonts[i];
+ ImGui::PushID(font);
+ bool font_details_opened = ImGui::TreeNode(font, "Font %d: \"%s\"\n%.2f px, %d glyphs, %d file(s)", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
+ ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
+ if (font_details_opened)
+ {
+ ImGui::PushFont(font);
+ ImGui::Text("The quick brown fox jumps over the lazy dog");
+ ImGui::PopFont();
+ ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font
+ ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
+ ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
+ ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
+ ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
+ ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
+ for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
+ if (ImFontConfig* cfg = &font->ConfigData[config_i])
+ ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
+ if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
+ {
+ // Display all glyphs of the fonts in separate pages of 256 characters
+ for (int base = 0; base < 0x10000; base += 256)
+ {
+ int count = 0;
+ for (int n = 0; n < 256; n++)
+ count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;
+ if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
+ {
+ float cell_size = font->FontSize * 1;
+ float cell_spacing = style.ItemSpacing.y;
+ ImVec2 base_pos = ImGui::GetCursorScreenPos();
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+ for (int n = 0; n < 256; n++)
+ {
+ ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
+ ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
+ const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
+ draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
+ if (glyph)
+ font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base + n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.
+ if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
+ {
+ ImGui::BeginTooltip();
+ ImGui::Text("Codepoint: U+%04X", base + n);
+ ImGui::Separator();
+ ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
+ ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
+ ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
+ ImGui::EndTooltip();
+ }
+ }
+ ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
+ ImGui::TreePop();
+ }
+ }
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+ }
+ if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
+ {
+ ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
+ ImGui::TreePop();
+ }
+
+ static float window_scale = 1.0f;
+ if (ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f")) // scale only this window
+ ImGui::SetWindowFontScale(window_scale);
+ ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything
+ ImGui::PopItemWidth();
+
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Rendering"))
+ {
+ ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
+ ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
+ ImGui::PushItemWidth(100);
+ ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f);
+ if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
+ ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
+ ImGui::PopItemWidth();
+
+ ImGui::EndTabItem();
+ }
+
+ ImGui::EndTabBar();
+ }
+
+ ImGui::PopItemWidth();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a fullscreen menu bar and populating it.
+static void ShowExampleAppMainMenuBar()
+{
+ if (ImGui::BeginMainMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Edit"))
+ {
+ if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
+ if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
+ ImGui::Separator();
+ if (ImGui::MenuItem("Cut", "CTRL+X")) {}
+ if (ImGui::MenuItem("Copy", "CTRL+C")) {}
+ if (ImGui::MenuItem("Paste", "CTRL+V")) {}
+ ImGui::EndMenu();
+ }
+ ImGui::EndMainMenuBar();
+ }
+}
+
+static void ShowExampleMenuFile()
+{
+ ImGui::MenuItem("(dummy menu)", NULL, false, false);
+ if (ImGui::MenuItem("New")) {}
+ if (ImGui::MenuItem("Open", "Ctrl+O")) {}
+ if (ImGui::BeginMenu("Open Recent"))
+ {
+ ImGui::MenuItem("fish_hat.c");
+ ImGui::MenuItem("fish_hat.inl");
+ ImGui::MenuItem("fish_hat.h");
+ if (ImGui::BeginMenu("More.."))
+ {
+ ImGui::MenuItem("Hello");
+ ImGui::MenuItem("Sailor");
+ if (ImGui::BeginMenu("Recurse.."))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenu();
+ }
+ if (ImGui::MenuItem("Save", "Ctrl+S")) {}
+ if (ImGui::MenuItem("Save As..")) {}
+ ImGui::Separator();
+ if (ImGui::BeginMenu("Options"))
+ {
+ static bool enabled = true;
+ ImGui::MenuItem("Enabled", "", &enabled);
+ ImGui::BeginChild("child", ImVec2(0, 60), true);
+ for (int i = 0; i < 10; i++)
+ ImGui::Text("Scrolling Text %d", i);
+ ImGui::EndChild();
+ static float f = 0.5f;
+ static int n = 0;
+ static bool b = true;
+ ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
+ ImGui::InputFloat("Input", &f, 0.1f);
+ ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
+ ImGui::Checkbox("Check", &b);
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Colors"))
+ {
+ float sz = ImGui::GetTextLineHeight();
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
+ ImVec2 p = ImGui::GetCursorScreenPos();
+ ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i));
+ ImGui::Dummy(ImVec2(sz, sz));
+ ImGui::SameLine();
+ ImGui::MenuItem(name);
+ }
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Disabled", false)) // Disabled
+ {
+ IM_ASSERT(0);
+ }
+ if (ImGui::MenuItem("Checked", NULL, true)) {}
+ if (ImGui::MenuItem("Quit", "Alt+F4")) {}
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
+// For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
+struct ExampleAppConsole
+{
+ char InputBuf[256];
+ ImVector<char*> Items;
+ bool ScrollToBottom;
+ ImVector<char*> History;
+ int HistoryPos; // -1: new line, 0..History.Size-1 browsing history.
+ ImVector<const char*> Commands;
+
+ ExampleAppConsole()
+ {
+ ClearLog();
+ memset(InputBuf, 0, sizeof(InputBuf));
+ HistoryPos = -1;
+ Commands.push_back("HELP");
+ Commands.push_back("HISTORY");
+ Commands.push_back("CLEAR");
+ Commands.push_back("CLASSIFY"); // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
+ AddLog("Welcome to Dear ImGui!");
+ }
+ ~ExampleAppConsole()
+ {
+ ClearLog();
+ for (int i = 0; i < History.Size; i++)
+ free(History[i]);
+ }
+
+ // Portable helpers
+ static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
+ static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }
+ static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
+ static void Strtrim(char* str) { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }
+
+ void ClearLog()
+ {
+ for (int i = 0; i < Items.Size; i++)
+ free(Items[i]);
+ Items.clear();
+ ScrollToBottom = true;
+ }
+
+ void AddLog(const char* fmt, ...) IM_FMTARGS(2)
+ {
+ // FIXME-OPT
+ char buf[1024];
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
+ buf[IM_ARRAYSIZE(buf)-1] = 0;
+ va_end(args);
+ Items.push_back(Strdup(buf));
+ ScrollToBottom = true;
+ }
+
+ void Draw(const char* title, bool* p_open)
+ {
+ ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin(title, p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
+ // Here we create a context menu only available from the title bar.
+ if (ImGui::BeginPopupContextItem())
+ {
+ if (ImGui::MenuItem("Close Console"))
+ *p_open = false;
+ ImGui::EndPopup();
+ }
+
+ ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
+ ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
+
+ // TODO: display items starting from the bottom
+
+ if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
+ if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
+ if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
+ bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
+ if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
+ //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
+
+ ImGui::Separator();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
+ static ImGuiTextFilter filter;
+ filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
+ ImGui::PopStyleVar();
+ ImGui::Separator();
+
+ const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
+ ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
+ if (ImGui::BeginPopupContextWindow())
+ {
+ if (ImGui::Selectable("Clear")) ClearLog();
+ ImGui::EndPopup();
+ }
+
+ // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
+ // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
+ // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.
+ // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
+ // ImGuiListClipper clipper(Items.Size);
+ // while (clipper.Step())
+ // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ // However, note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.
+ // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,
+ // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!
+ // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
+ if (copy_to_clipboard)
+ ImGui::LogToClipboard();
+ ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text);
+ for (int i = 0; i < Items.Size; i++)
+ {
+ const char* item = Items[i];
+ if (!filter.PassFilter(item))
+ continue;
+ ImVec4 col = col_default_text;
+ if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f);
+ else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);
+ ImGui::PushStyleColor(ImGuiCol_Text, col);
+ ImGui::TextUnformatted(item);
+ ImGui::PopStyleColor();
+ }
+ if (copy_to_clipboard)
+ ImGui::LogFinish();
+ if (ScrollToBottom)
+ ImGui::SetScrollHereY(1.0f);
+ ScrollToBottom = false;
+ ImGui::PopStyleVar();
+ ImGui::EndChild();
+ ImGui::Separator();
+
+ // Command-line
+ bool reclaim_focus = false;
+ if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
+ {
+ char* s = InputBuf;
+ Strtrim(s);
+ if (s[0])
+ ExecCommand(s);
+ strcpy(s, "");
+ reclaim_focus = true;
+ }
+
+ // Auto-focus on window apparition
+ ImGui::SetItemDefaultFocus();
+ if (reclaim_focus)
+ ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
+
+ ImGui::End();
+ }
+
+ void ExecCommand(const char* command_line)
+ {
+ AddLog("# %s\n", command_line);
+
+ // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
+ HistoryPos = -1;
+ for (int i = History.Size-1; i >= 0; i--)
+ if (Stricmp(History[i], command_line) == 0)
+ {
+ free(History[i]);
+ History.erase(History.begin() + i);
+ break;
+ }
+ History.push_back(Strdup(command_line));
+
+ // Process command
+ if (Stricmp(command_line, "CLEAR") == 0)
+ {
+ ClearLog();
+ }
+ else if (Stricmp(command_line, "HELP") == 0)
+ {
+ AddLog("Commands:");
+ for (int i = 0; i < Commands.Size; i++)
+ AddLog("- %s", Commands[i]);
+ }
+ else if (Stricmp(command_line, "HISTORY") == 0)
+ {
+ int first = History.Size - 10;
+ for (int i = first > 0 ? first : 0; i < History.Size; i++)
+ AddLog("%3d: %s\n", i, History[i]);
+ }
+ else
+ {
+ AddLog("Unknown command: '%s'\n", command_line);
+ }
+ }
+
+ static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
+ {
+ ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
+ return console->TextEditCallback(data);
+ }
+
+ int TextEditCallback(ImGuiInputTextCallbackData* data)
+ {
+ //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
+ switch (data->EventFlag)
+ {
+ case ImGuiInputTextFlags_CallbackCompletion:
+ {
+ // Example of TEXT COMPLETION
+
+ // Locate beginning of current word
+ const char* word_end = data->Buf + data->CursorPos;
+ const char* word_start = word_end;
+ while (word_start > data->Buf)
+ {
+ const char c = word_start[-1];
+ if (c == ' ' || c == '\t' || c == ',' || c == ';')
+ break;
+ word_start--;
+ }
+
+ // Build a list of candidates
+ ImVector<const char*> candidates;
+ for (int i = 0; i < Commands.Size; i++)
+ if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
+ candidates.push_back(Commands[i]);
+
+ if (candidates.Size == 0)
+ {
+ // No match
+ AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
+ }
+ else if (candidates.Size == 1)
+ {
+ // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
+ data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
+ data->InsertChars(data->CursorPos, candidates[0]);
+ data->InsertChars(data->CursorPos, " ");
+ }
+ else
+ {
+ // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
+ int match_len = (int)(word_end - word_start);
+ for (;;)
+ {
+ int c = 0;
+ bool all_candidates_matches = true;
+ for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
+ if (i == 0)
+ c = toupper(candidates[i][match_len]);
+ else if (c == 0 || c != toupper(candidates[i][match_len]))
+ all_candidates_matches = false;
+ if (!all_candidates_matches)
+ break;
+ match_len++;
+ }
+
+ if (match_len > 0)
+ {
+ data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
+ data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
+ }
+
+ // List matches
+ AddLog("Possible matches:\n");
+ for (int i = 0; i < candidates.Size; i++)
+ AddLog("- %s\n", candidates[i]);
+ }
+
+ break;
+ }
+ case ImGuiInputTextFlags_CallbackHistory:
+ {
+ // Example of HISTORY
+ const int prev_history_pos = HistoryPos;
+ if (data->EventKey == ImGuiKey_UpArrow)
+ {
+ if (HistoryPos == -1)
+ HistoryPos = History.Size - 1;
+ else if (HistoryPos > 0)
+ HistoryPos--;
+ }
+ else if (data->EventKey == ImGuiKey_DownArrow)
+ {
+ if (HistoryPos != -1)
+ if (++HistoryPos >= History.Size)
+ HistoryPos = -1;
+ }
+
+ // A better implementation would preserve the data on the current input line along with cursor position.
+ if (prev_history_pos != HistoryPos)
+ {
+ const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
+ data->DeleteChars(0, data->BufTextLen);
+ data->InsertChars(0, history_str);
+ }
+ }
+ }
+ return 0;
+ }
+};
+
+static void ShowExampleAppConsole(bool* p_open)
+{
+ static ExampleAppConsole console;
+ console.Draw("Example: Console", p_open);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Debug Log / ShowExampleAppLog()
+//-----------------------------------------------------------------------------
+
+// Usage:
+// static ExampleAppLog my_log;
+// my_log.AddLog("Hello %d world\n", 123);
+// my_log.Draw("title");
+struct ExampleAppLog
+{
+ ImGuiTextBuffer Buf;
+ ImGuiTextFilter Filter;
+ ImVector<int> LineOffsets; // Index to lines offset. We maintain this with AddLog() calls, allowing us to have a random access on lines
+ bool ScrollToBottom;
+
+ void Clear()
+ {
+ Buf.clear();
+ LineOffsets.clear();
+ LineOffsets.push_back(0);
+ }
+
+ void AddLog(const char* fmt, ...) IM_FMTARGS(2)
+ {
+ int old_size = Buf.size();
+ va_list args;
+ va_start(args, fmt);
+ Buf.appendfv(fmt, args);
+ va_end(args);
+ for (int new_size = Buf.size(); old_size < new_size; old_size++)
+ if (Buf[old_size] == '\n')
+ LineOffsets.push_back(old_size + 1);
+ ScrollToBottom = true;
+ }
+
+ void Draw(const char* title, bool* p_open = NULL)
+ {
+ if (!ImGui::Begin(title, p_open))
+ {
+ ImGui::End();
+ return;
+ }
+ if (ImGui::Button("Clear")) Clear();
+ ImGui::SameLine();
+ bool copy = ImGui::Button("Copy");
+ ImGui::SameLine();
+ Filter.Draw("Filter", -100.0f);
+ ImGui::Separator();
+ ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
+ if (copy)
+ ImGui::LogToClipboard();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ const char* buf = Buf.begin();
+ const char* buf_end = Buf.end();
+ if (Filter.IsActive())
+ {
+ for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
+ {
+ const char* line_start = buf + LineOffsets[line_no];
+ const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
+ if (Filter.PassFilter(line_start, line_end))
+ ImGui::TextUnformatted(line_start, line_end);
+ }
+ }
+ else
+ {
+ // The simplest and easy way to display the entire buffer:
+ // ImGui::TextUnformatted(buf_begin, buf_end);
+ // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward to skip non-visible lines.
+ // Here we instead demonstrate using the clipper to only process lines that are within the visible area.
+ // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them on your side is recommended.
+ // Using ImGuiListClipper requires A) random access into your data, and B) items all being the same height,
+ // both of which we can handle since we an array pointing to the beginning of each line of text.
+ // When using the filter (in the block of code above) we don't have random access into the data to display anymore, which is why we don't use the clipper.
+ // Storing or skimming through the search result would make it possible (and would be recommended if you want to search through tens of thousands of entries)
+ ImGuiListClipper clipper;
+ clipper.Begin(LineOffsets.Size);
+ while (clipper.Step())
+ {
+ for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
+ {
+ const char* line_start = buf + LineOffsets[line_no];
+ const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
+ ImGui::TextUnformatted(line_start, line_end);
+ }
+ }
+ clipper.End();
+ }
+ ImGui::PopStyleVar();
+
+ if (ScrollToBottom)
+ ImGui::SetScrollHereY(1.0f);
+ ScrollToBottom = false;
+ ImGui::EndChild();
+ ImGui::End();
+ }
+};
+
+// Demonstrate creating a simple log window with basic filtering.
+static void ShowExampleAppLog(bool* p_open)
+{
+ static ExampleAppLog log;
+
+ // For the demo: add a debug button before the normal log window contents
+ // We take advantage of the fact that multiple calls to Begin()/End() are appending to the same window.
+ ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Example: Log", p_open);
+ if (ImGui::SmallButton("Add 5 entries"))
+ {
+ static int counter = 0;
+ for (int n = 0; n < 5; n++)
+ {
+ const char* categories[3] = { "info", "warn", "error" };
+ const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
+ log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
+ ImGui::GetFrameCount(), categories[counter % IM_ARRAYSIZE(categories)], ImGui::GetTime(), words[counter % IM_ARRAYSIZE(words)]);
+ counter++;
+ }
+ }
+ ImGui::End();
+
+ log.Draw("Example: Log", p_open);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
+//-----------------------------------------------------------------------------
+
+// Demonstrate create a window with multiple child windows.
+static void ShowExampleAppLayout(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
+ if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
+ {
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ if (ImGui::MenuItem("Close")) *p_open = false;
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+
+ // left
+ static int selected = 0;
+ ImGui::BeginChild("left pane", ImVec2(150, 0), true);
+ for (int i = 0; i < 100; i++)
+ {
+ char label[128];
+ sprintf(label, "MyObject %d", i);
+ if (ImGui::Selectable(label, selected == i))
+ selected = i;
+ }
+ ImGui::EndChild();
+ ImGui::SameLine();
+
+ // right
+ ImGui::BeginGroup();
+ ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
+ ImGui::Text("MyObject: %d", selected);
+ ImGui::Separator();
+ if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
+ {
+ if (ImGui::BeginTabItem("Description"))
+ {
+ ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("Details"))
+ {
+ ImGui::Text("ID: 0123456789");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::EndChild();
+ if (ImGui::Button("Revert")) {}
+ ImGui::SameLine();
+ if (ImGui::Button("Save")) {}
+ ImGui::EndGroup();
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
+//-----------------------------------------------------------------------------
+
+// Demonstrate create a simple property editor.
+static void ShowExampleAppPropertyEditor(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin("Example: Property editor", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
+
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
+ ImGui::Columns(2);
+ ImGui::Separator();
+
+ struct funcs
+ {
+ static void ShowDummyObject(const char* prefix, int uid)
+ {
+ ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
+ ImGui::AlignTextToFramePadding(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
+ bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
+ ImGui::NextColumn();
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("my sailor is rich");
+ ImGui::NextColumn();
+ if (node_open)
+ {
+ static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
+ for (int i = 0; i < 8; i++)
+ {
+ ImGui::PushID(i); // Use field index as identifier.
+ if (i < 2)
+ {
+ ShowDummyObject("Child", 424242);
+ }
+ else
+ {
+ // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
+ ImGui::AlignTextToFramePadding();
+ ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i);
+ ImGui::NextColumn();
+ ImGui::PushItemWidth(-1);
+ if (i >= 5)
+ ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
+ else
+ ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
+ ImGui::PopItemWidth();
+ ImGui::NextColumn();
+ }
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+ }
+ };
+
+ // Iterate dummy objects with dummy members (all the same data)
+ for (int obj_i = 0; obj_i < 3; obj_i++)
+ funcs::ShowDummyObject("Object", obj_i);
+
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::PopStyleVar();
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Long Text / ShowExampleAppLongText()
+//-----------------------------------------------------------------------------
+
+// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
+static void ShowExampleAppLongText(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin("Example: Long text display", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ static int test_type = 0;
+ static ImGuiTextBuffer log;
+ static int lines = 0;
+ ImGui::Text("Printing unusually long amount of text.");
+ ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
+ ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
+ if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
+ ImGui::SameLine();
+ if (ImGui::Button("Add 1000 lines"))
+ {
+ for (int i = 0; i < 1000; i++)
+ log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
+ lines += 1000;
+ }
+ ImGui::BeginChild("Log");
+ switch (test_type)
+ {
+ case 0:
+ // Single call to TextUnformatted() with a big buffer
+ ImGui::TextUnformatted(log.begin(), log.end());
+ break;
+ case 1:
+ {
+ // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
+ ImGuiListClipper clipper(lines);
+ while (clipper.Step())
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
+ ImGui::PopStyleVar();
+ break;
+ }
+ case 2:
+ // Multiple calls to Text(), not clipped (slow)
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
+ for (int i = 0; i < lines; i++)
+ ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
+ ImGui::PopStyleVar();
+ break;
+ }
+ ImGui::EndChild();
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a window which gets auto-resized according to its content.
+static void ShowExampleAppAutoResize(bool* p_open)
+{
+ if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::End();
+ return;
+ }
+
+ static int lines = 10;
+ ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
+ ImGui::SliderInt("Number of lines", &lines, 1, 20);
+ for (int i = 0; i < lines; i++)
+ ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a window with custom resize constraints.
+static void ShowExampleAppConstrainedResize(bool* p_open)
+{
+ struct CustomConstraints // Helper functions to demonstrate programmatic constraints
+ {
+ static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
+ static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
+ };
+
+ static bool auto_resize = false;
+ static int type = 0;
+ static int display_lines = 10;
+ if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
+ if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
+ if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
+ if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500
+ if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500
+ if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
+ if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step
+
+ ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
+ if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
+ {
+ const char* desc[] =
+ {
+ "Resize vertical only",
+ "Resize horizontal only",
+ "Width > 100, Height > 100",
+ "Width 400-500",
+ "Height 400-500",
+ "Custom: Always Square",
+ "Custom: Fixed Steps (100)",
+ };
+ if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
+ if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
+ if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
+ ImGui::PushItemWidth(200);
+ ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
+ ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
+ ImGui::PopItemWidth();
+ ImGui::Checkbox("Auto-resize", &auto_resize);
+ for (int i = 0; i < display_lines; i++)
+ ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
+static void ShowExampleAppSimpleOverlay(bool* p_open)
+{
+ const float DISTANCE = 10.0f;
+ static int corner = 0;
+ ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
+ ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
+ if (corner != -1)
+ ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
+ ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background
+ if (ImGui::Begin("Example: Simple overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
+ {
+ ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
+ ImGui::Separator();
+ if (ImGui::IsMousePosValid())
+ ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
+ else
+ ImGui::Text("Mouse Position: <invalid>");
+ if (ImGui::BeginPopupContextWindow())
+ {
+ if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
+ if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
+ if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
+ if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
+ if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
+ if (p_open && ImGui::MenuItem("Close")) *p_open = false;
+ ImGui::EndPopup();
+ }
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
+//-----------------------------------------------------------------------------
+
+// Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
+// This apply to all regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details.
+static void ShowExampleAppWindowTitles(bool*)
+{
+ // By default, Windows are uniquely identified by their title.
+ // You can use the "##" and "###" markers to manipulate the display/ID.
+
+ // Using "##" to display same title but have unique identifier.
+ ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Same title as another window##1");
+ ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
+ ImGui::End();
+
+ ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Same title as another window##2");
+ ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
+ ImGui::End();
+
+ // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
+ char buf[128];
+ sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
+ ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
+ ImGui::Begin(buf);
+ ImGui::Text("This window has a changing title.");
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
+//-----------------------------------------------------------------------------
+
+// Demonstrate using the low-level ImDrawList to draw custom shapes.
+static void ShowExampleAppCustomRendering(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin("Example: Custom rendering", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
+ // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
+ // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
+ // In this example we are not using the maths operators!
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+
+ // Primitives
+ ImGui::Text("Primitives");
+ static float sz = 36.0f;
+ static float thickness = 4.0f;
+ static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
+ ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
+ ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
+ ImGui::ColorEdit3("Color", &col.x);
+ {
+ const ImVec2 p = ImGui::GetCursorScreenPos();
+ const ImU32 col32 = ImColor(col);
+ float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
+ for (int n = 0; n < 2; n++)
+ {
+ float curr_thickness = (n == 0) ? 1.0f : thickness;
+ draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, curr_thickness); x += sz+spacing;
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing;
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing;
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, curr_thickness); x += sz+spacing;
+ draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, curr_thickness); x += sz+spacing;
+ draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, curr_thickness); x += sz+spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
+ draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, curr_thickness); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
+ draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, curr_thickness); x += sz+spacing; // Diagonal line
+ draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, curr_thickness);
+ x = p.x + 4;
+ y += sz+spacing;
+ }
+ draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
+ draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+thickness), col32); x += sz+spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+thickness, y+sz), col32); x += spacing+spacing; // Vertical line (faster than AddLine, but only handle integer thickness)
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+1, y+1), col32); x += sz; // Pixel (faster than AddLine)
+ draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255));
+ ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
+ }
+ ImGui::Separator();
+ {
+ static ImVector<ImVec2> points;
+ static bool adding_line = false;
+ ImGui::Text("Canvas example");
+ if (ImGui::Button("Clear")) points.clear();
+ if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
+ ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
+
+ // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
+ // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
+ // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
+ ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
+ ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
+ if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
+ if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
+ draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255));
+ draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));
+
+ bool adding_preview = false;
+ ImGui::InvisibleButton("canvas", canvas_size);
+ ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
+ if (adding_line)
+ {
+ adding_preview = true;
+ points.push_back(mouse_pos_in_canvas);
+ if (!ImGui::IsMouseDown(0))
+ adding_line = adding_preview = false;
+ }
+ if (ImGui::IsItemHovered())
+ {
+ if (!adding_line && ImGui::IsMouseClicked(0))
+ {
+ points.push_back(mouse_pos_in_canvas);
+ adding_line = true;
+ }
+ if (ImGui::IsMouseClicked(1) && !points.empty())
+ {
+ adding_line = adding_preview = false;
+ points.pop_back();
+ points.pop_back();
+ }
+ }
+ draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), true); // clip lines within the canvas (if we resize it, etc.)
+ for (int i = 0; i < points.Size - 1; i += 2)
+ draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
+ draw_list->PopClipRect();
+ if (adding_preview)
+ points.pop_back();
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
+//-----------------------------------------------------------------------------
+
+// Simplified structure to mimic a Document model
+struct MyDocument
+{
+ const char* Name; // Document title
+ bool Open; // Set when the document is open (in this demo, we keep an array of all available documents to simplify the demo)
+ bool OpenPrev; // Copy of Open from last update.
+ bool Dirty; // Set when the document has been modified
+ bool WantClose; // Set when the document
+ ImVec4 Color; // An arbitrary variable associated to the document
+
+ MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f,1.0f,1.0f,1.0f))
+ {
+ Name = name;
+ Open = OpenPrev = open;
+ Dirty = false;
+ WantClose = false;
+ Color = color;
+ }
+ void DoOpen() { Open = true; }
+ void DoQueueClose() { WantClose = true; }
+ void DoForceClose() { Open = false; Dirty = false; }
+ void DoSave() { Dirty = false; }
+
+ // Display dummy contents for the Document
+ static void DisplayContents(MyDocument* doc)
+ {
+ ImGui::PushID(doc);
+ ImGui::Text("Document \"%s\"", doc->Name);
+ ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
+ ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+ ImGui::PopStyleColor();
+ if (ImGui::Button("Modify", ImVec2(100, 0)))
+ doc->Dirty = true;
+ ImGui::SameLine();
+ if (ImGui::Button("Save", ImVec2(100, 0)))
+ doc->DoSave();
+ ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
+ ImGui::PopID();
+ }
+
+ // Display context menu for the Document
+ static void DisplayContextMenu(MyDocument* doc)
+ {
+ if (!ImGui::BeginPopupContextItem())
+ return;
+
+ char buf[256];
+ sprintf(buf, "Save %s", doc->Name);
+ if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
+ doc->DoSave();
+ if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
+ doc->DoQueueClose();
+ ImGui::EndPopup();
+ }
+};
+
+struct ExampleAppDocuments
+{
+ ImVector<MyDocument> Documents;
+
+ ExampleAppDocuments()
+ {
+ Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
+ Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
+ Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
+ Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
+ Documents.push_back(MyDocument("A Rather Long Title", false));
+ Documents.push_back(MyDocument("Some Document", false));
+ }
+};
+
+// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
+// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, as opposed
+// to clicking on the regular tab closing button) and stops being submitted, it will take a frame for the tab bar to notice its absence.
+// During this frame there will be a gap in the tab bar, and if the tab that has disappeared was the selected one, the tab bar
+// will report no selected tab during the frame. This will effectively give the impression of a flicker for one frame.
+// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
+// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
+static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
+{
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (!doc->Open && doc->OpenPrev)
+ ImGui::SetTabItemClosed(doc->Name);
+ doc->OpenPrev = doc->Open;
+ }
+}
+
+void ShowExampleAppDocuments(bool* p_open)
+{
+ static ExampleAppDocuments app;
+
+ if (!ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar))
+ {
+ ImGui::End();
+ return;
+ }
+
+ // Options
+ static bool opt_reorderable = true;
+ static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
+
+ // Menu
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ int open_count = 0;
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ open_count += app.Documents[doc_n].Open ? 1 : 0;
+
+ if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
+ {
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (!doc->Open)
+ if (ImGui::MenuItem(doc->Name))
+ doc->DoOpen();
+ }
+ ImGui::EndMenu();
+ }
+ if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ app.Documents[doc_n].DoQueueClose();
+ if (ImGui::MenuItem("Exit", "Alt+F4")) {}
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+
+ // [Debug] List documents with one checkbox for each
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (doc_n > 0)
+ ImGui::SameLine();
+ ImGui::PushID(doc);
+ if (ImGui::Checkbox(doc->Name, &doc->Open))
+ if (!doc->Open)
+ doc->DoForceClose();
+ ImGui::PopID();
+ }
+
+ ImGui::Separator();
+
+ // Submit Tab Bar and Tabs
+ {
+ ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
+ if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
+ {
+ if (opt_reorderable)
+ NotifyOfDocumentsClosedElsewhere(app);
+
+ // [DEBUG] Stress tests
+ //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
+ //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
+
+ // Submit Tabs
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (!doc->Open)
+ continue;
+
+ ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
+ bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
+
+ // Cancel attempt to close when unsaved add to save queue so we can display a popup.
+ if (!doc->Open && doc->Dirty)
+ {
+ doc->Open = true;
+ doc->DoQueueClose();
+ }
+
+ MyDocument::DisplayContextMenu(doc);
+ if (visible)
+ {
+ MyDocument::DisplayContents(doc);
+ ImGui::EndTabItem();
+ }
+ }
+
+ ImGui::EndTabBar();
+ }
+ }
+
+ // Update closing queue
+ static ImVector<MyDocument*> close_queue;
+ if (close_queue.empty())
+ {
+ // Close queue is locked once we started a popup
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (doc->WantClose)
+ {
+ doc->WantClose = false;
+ close_queue.push_back(doc);
+ }
+ }
+ }
+
+ // Display closing confirmation UI
+ if (!close_queue.empty())
+ {
+ int close_queue_unsaved_documents = 0;
+ for (int n = 0; n < close_queue.Size; n++)
+ if (close_queue[n]->Dirty)
+ close_queue_unsaved_documents++;
+
+ if (close_queue_unsaved_documents == 0)
+ {
+ // Close documents when all are unsaved
+ for (int n = 0; n < close_queue.Size; n++)
+ close_queue[n]->DoForceClose();
+ close_queue.clear();
+ }
+ else
+ {
+ if (!ImGui::IsPopupOpen("Save?"))
+ ImGui::OpenPopup("Save?");
+ if (ImGui::BeginPopupModal("Save?"))
+ {
+ ImGui::Text("Save change to the following items?");
+ ImGui::PushItemWidth(-1.0f);
+ ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6);
+ for (int n = 0; n < close_queue.Size; n++)
+ if (close_queue[n]->Dirty)
+ ImGui::Text("%s", close_queue[n]->Name);
+ ImGui::ListBoxFooter();
+
+ if (ImGui::Button("Yes", ImVec2(80, 0)))
+ {
+ for (int n = 0; n < close_queue.Size; n++)
+ {
+ if (close_queue[n]->Dirty)
+ close_queue[n]->DoSave();
+ close_queue[n]->DoForceClose();
+ }
+ close_queue.clear();
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("No", ImVec2(80, 0)))
+ {
+ for (int n = 0; n < close_queue.Size; n++)
+ close_queue[n]->DoForceClose();
+ close_queue.clear();
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Cancel", ImVec2(80, 0)))
+ {
+ close_queue.clear();
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::EndPopup();
+ }
+ }
+ }
+
+ ImGui::End();
+}
+
+// End of Demo code
+#else
+
+void ImGui::ShowAboutWindow(bool*) {}
+void ImGui::ShowDemoWindow(bool*) {}
+void ImGui::ShowUserGuide() {}
+void ImGui::ShowStyleEditor(ImGuiStyle*) {}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imgui_draw.cpp b/Client/ThirdParty/Box2D/extern/imgui/imgui_draw.cpp
new file mode 100644
index 0000000..9833590
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imgui_draw.cpp
@@ -0,0 +1,3199 @@
+// dear imgui, v1.67 WIP
+// (drawing and font code)
+
+/*
+
+Index of this file:
+
+// [SECTION] STB libraries implementation
+// [SECTION] Style functions
+// [SECTION] ImDrawList
+// [SECTION] ImDrawData
+// [SECTION] Helpers ShadeVertsXXX functions
+// [SECTION] ImFontConfig
+// [SECTION] ImFontAtlas
+// [SECTION] ImFontAtlas glyph ranges helpers
+// [SECTION] ImFontGlyphRangesBuilder
+// [SECTION] ImFont
+// [SECTION] Internal Render Helpers
+// [SECTION] Decompression code
+// [SECTION] Default font data (ProggyClean.ttf)
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+#include <stdio.h> // vsnprintf, sscanf, printf
+#if !defined(alloca)
+#if defined(__GLIBC__) || defined(__sun) || defined(__CYGWIN__) || defined(__APPLE__)
+#include <alloca.h> // alloca (glibc uses <alloca.h>. Note that Cygwin may have _WIN32 defined, so the order matters here)
+#elif defined(_WIN32)
+#include <malloc.h> // alloca
+#if !defined(alloca)
+#define alloca _alloca // for clang with MS Codegen
+#endif
+#else
+#include <stdlib.h> // alloca
+#endif
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#endif
+
+// Clang/GCC warnings with -Weverything
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
+#pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
+#if __has_warning("-Wcomma")
+#pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here //
+#endif
+#if __has_warning("-Wreserved-id-macro")
+#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
+#endif
+#if __has_warning("-Wdouble-promotion")
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#endif
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#if __GNUC__ >= 8
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+#endif
+
+//-------------------------------------------------------------------------
+// [SECTION] STB libraries implementation
+//-------------------------------------------------------------------------
+
+// Compile time options:
+//#define IMGUI_STB_NAMESPACE ImGuiStb
+//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
+//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
+//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
+//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
+
+#ifdef IMGUI_STB_NAMESPACE
+namespace IMGUI_STB_NAMESPACE
+{
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxx *' drops const qualifier //
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits]
+#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
+#endif
+
+#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
+#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
+#define STBRP_STATIC
+#define STBRP_ASSERT(x) IM_ASSERT(x)
+#define STBRP_SORT ImQsort
+#define STB_RECT_PACK_IMPLEMENTATION
+#endif
+#ifdef IMGUI_STB_RECT_PACK_FILENAME
+#include IMGUI_STB_RECT_PACK_FILENAME
+#else
+#include "imstb_rectpack.h"
+#endif
+#endif
+
+#ifndef STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
+#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
+#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x))
+#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x))
+#define STBTT_assert(x) IM_ASSERT(x)
+#define STBTT_fmod(x,y) ImFmod(x,y)
+#define STBTT_sqrt(x) ImSqrt(x)
+#define STBTT_pow(x,y) ImPow(x,y)
+#define STBTT_fabs(x) ImFabs(x)
+#define STBTT_ifloor(x) ((int)ImFloorStd(x))
+#define STBTT_iceil(x) ((int)ImCeil(x))
+#define STBTT_STATIC
+#define STB_TRUETYPE_IMPLEMENTATION
+#else
+#define STBTT_DEF extern
+#endif
+#ifdef IMGUI_STB_TRUETYPE_FILENAME
+#include IMGUI_STB_TRUETYPE_FILENAME
+#else
+#include "imstb_truetype.h"
+#endif
+#endif
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+#ifdef IMGUI_STB_NAMESPACE
+} // namespace ImGuiStb
+using namespace IMGUI_STB_NAMESPACE;
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] Style functions
+//-----------------------------------------------------------------------------
+
+void ImGui::StyleColorsDark(ImGuiStyle* dst)
+{
+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+ ImVec4* colors = style->Colors;
+
+ colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+ colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
+ colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
+ colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
+ colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f);
+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f);
+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
+ colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
+ colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
+ colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];
+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
+ colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+ colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
+ colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
+ colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
+ colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
+ colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
+ colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
+ colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
+ colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
+ colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
+}
+
+void ImGui::StyleColorsClassic(ImGuiStyle* dst)
+{
+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+ ImVec4* colors = style->Colors;
+
+ colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
+ colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
+ colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
+ colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
+ colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);
+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f);
+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f);
+ colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);
+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);
+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);
+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);
+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
+ colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
+ colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
+ colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f);
+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.48f, 0.71f, 0.79f);
+ colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.54f, 0.80f, 1.00f);
+ colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
+ colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
+ colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
+ colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f);
+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
+ colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
+ colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
+ colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
+ colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
+ colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
+ colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
+ colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
+ colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
+ colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
+ colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
+}
+
+// Those light colors are better suited with a thicker font than the default one + FrameBorder
+void ImGui::StyleColorsLight(ImGuiStyle* dst)
+{
+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+ ImVec4* colors = style->Colors;
+
+ colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
+ colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
+ colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f);
+ colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f);
+ colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f);
+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f);
+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);
+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f);
+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f);
+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f);
+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
+ colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
+ colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
+ colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
+ colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f);
+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f);
+ colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f);
+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+ colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
+ colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
+ colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
+ colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
+ colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f);
+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
+ colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+ colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
+ colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
+ colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
+}
+
+//-----------------------------------------------------------------------------
+// ImDrawList
+//-----------------------------------------------------------------------------
+
+ImDrawListSharedData::ImDrawListSharedData()
+{
+ Font = NULL;
+ FontSize = 0.0f;
+ CurveTessellationTol = 0.0f;
+ ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f);
+
+ // Const data
+ for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++)
+ {
+ const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12);
+ CircleVtx12[i] = ImVec2(ImCos(a), ImSin(a));
+ }
+}
+
+void ImDrawList::Clear()
+{
+ CmdBuffer.resize(0);
+ IdxBuffer.resize(0);
+ VtxBuffer.resize(0);
+ Flags = ImDrawListFlags_AntiAliasedLines | ImDrawListFlags_AntiAliasedFill;
+ _VtxCurrentIdx = 0;
+ _VtxWritePtr = NULL;
+ _IdxWritePtr = NULL;
+ _ClipRectStack.resize(0);
+ _TextureIdStack.resize(0);
+ _Path.resize(0);
+ _ChannelsCurrent = 0;
+ _ChannelsCount = 1;
+ // NB: Do not clear channels so our allocations are re-used after the first frame.
+}
+
+void ImDrawList::ClearFreeMemory()
+{
+ CmdBuffer.clear();
+ IdxBuffer.clear();
+ VtxBuffer.clear();
+ _VtxCurrentIdx = 0;
+ _VtxWritePtr = NULL;
+ _IdxWritePtr = NULL;
+ _ClipRectStack.clear();
+ _TextureIdStack.clear();
+ _Path.clear();
+ _ChannelsCurrent = 0;
+ _ChannelsCount = 1;
+ for (int i = 0; i < _Channels.Size; i++)
+ {
+ if (i == 0) memset(&_Channels[0], 0, sizeof(_Channels[0])); // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again
+ _Channels[i].CmdBuffer.clear();
+ _Channels[i].IdxBuffer.clear();
+ }
+ _Channels.clear();
+}
+
+ImDrawList* ImDrawList::CloneOutput() const
+{
+ ImDrawList* dst = IM_NEW(ImDrawList(NULL));
+ dst->CmdBuffer = CmdBuffer;
+ dst->IdxBuffer = IdxBuffer;
+ dst->VtxBuffer = VtxBuffer;
+ dst->Flags = Flags;
+ return dst;
+}
+
+// Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds
+#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : _Data->ClipRectFullscreen)
+#define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL)
+
+void ImDrawList::AddDrawCmd()
+{
+ ImDrawCmd draw_cmd;
+ draw_cmd.ClipRect = GetCurrentClipRect();
+ draw_cmd.TextureId = GetCurrentTextureId();
+
+ IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
+ CmdBuffer.push_back(draw_cmd);
+}
+
+void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
+{
+ ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
+ if (!current_cmd || current_cmd->ElemCount != 0 || current_cmd->UserCallback != NULL)
+ {
+ AddDrawCmd();
+ current_cmd = &CmdBuffer.back();
+ }
+ current_cmd->UserCallback = callback;
+ current_cmd->UserCallbackData = callback_data;
+
+ AddDrawCmd(); // Force a new command after us (see comment below)
+}
+
+// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.
+// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.
+void ImDrawList::UpdateClipRect()
+{
+ // If current command is used with different settings we need to add a new command
+ const ImVec4 curr_clip_rect = GetCurrentClipRect();
+ ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size-1] : NULL;
+ if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL)
+ {
+ AddDrawCmd();
+ return;
+ }
+
+ // Try to merge with previous command if it matches, else use current command
+ ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
+ if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL)
+ CmdBuffer.pop_back();
+ else
+ curr_cmd->ClipRect = curr_clip_rect;
+}
+
+void ImDrawList::UpdateTextureID()
+{
+ // If current command is used with different settings we need to add a new command
+ const ImTextureID curr_texture_id = GetCurrentTextureId();
+ ImDrawCmd* curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
+ if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL)
+ {
+ AddDrawCmd();
+ return;
+ }
+
+ // Try to merge with previous command if it matches, else use current command
+ ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
+ if (curr_cmd->ElemCount == 0 && prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL)
+ CmdBuffer.pop_back();
+ else
+ curr_cmd->TextureId = curr_texture_id;
+}
+
+#undef GetCurrentClipRect
+#undef GetCurrentTextureId
+
+// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
+void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect)
+{
+ ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);
+ if (intersect_with_current_clip_rect && _ClipRectStack.Size)
+ {
+ ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size-1];
+ if (cr.x < current.x) cr.x = current.x;
+ if (cr.y < current.y) cr.y = current.y;
+ if (cr.z > current.z) cr.z = current.z;
+ if (cr.w > current.w) cr.w = current.w;
+ }
+ cr.z = ImMax(cr.x, cr.z);
+ cr.w = ImMax(cr.y, cr.w);
+
+ _ClipRectStack.push_back(cr);
+ UpdateClipRect();
+}
+
+void ImDrawList::PushClipRectFullScreen()
+{
+ PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w));
+}
+
+void ImDrawList::PopClipRect()
+{
+ IM_ASSERT(_ClipRectStack.Size > 0);
+ _ClipRectStack.pop_back();
+ UpdateClipRect();
+}
+
+void ImDrawList::PushTextureID(ImTextureID texture_id)
+{
+ _TextureIdStack.push_back(texture_id);
+ UpdateTextureID();
+}
+
+void ImDrawList::PopTextureID()
+{
+ IM_ASSERT(_TextureIdStack.Size > 0);
+ _TextureIdStack.pop_back();
+ UpdateTextureID();
+}
+
+void ImDrawList::ChannelsSplit(int channels_count)
+{
+ IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1);
+ int old_channels_count = _Channels.Size;
+ if (old_channels_count < channels_count)
+ _Channels.resize(channels_count);
+ _ChannelsCount = channels_count;
+
+ // _Channels[] (24/32 bytes each) hold storage that we'll swap with this->_CmdBuffer/_IdxBuffer
+ // The content of _Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to.
+ // When we switch to the next channel, we'll copy _CmdBuffer/_IdxBuffer into _Channels[0] and then _Channels[1] into _CmdBuffer/_IdxBuffer
+ memset(&_Channels[0], 0, sizeof(ImDrawChannel));
+ for (int i = 1; i < channels_count; i++)
+ {
+ if (i >= old_channels_count)
+ {
+ IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel();
+ }
+ else
+ {
+ _Channels[i].CmdBuffer.resize(0);
+ _Channels[i].IdxBuffer.resize(0);
+ }
+ if (_Channels[i].CmdBuffer.Size == 0)
+ {
+ ImDrawCmd draw_cmd;
+ draw_cmd.ClipRect = _ClipRectStack.back();
+ draw_cmd.TextureId = _TextureIdStack.back();
+ _Channels[i].CmdBuffer.push_back(draw_cmd);
+ }
+ }
+}
+
+void ImDrawList::ChannelsMerge()
+{
+ // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
+ if (_ChannelsCount <= 1)
+ return;
+
+ ChannelsSetCurrent(0);
+ if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0)
+ CmdBuffer.pop_back();
+
+ int new_cmd_buffer_count = 0, new_idx_buffer_count = 0;
+ for (int i = 1; i < _ChannelsCount; i++)
+ {
+ ImDrawChannel& ch = _Channels[i];
+ if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0)
+ ch.CmdBuffer.pop_back();
+ new_cmd_buffer_count += ch.CmdBuffer.Size;
+ new_idx_buffer_count += ch.IdxBuffer.Size;
+ }
+ CmdBuffer.resize(CmdBuffer.Size + new_cmd_buffer_count);
+ IdxBuffer.resize(IdxBuffer.Size + new_idx_buffer_count);
+
+ ImDrawCmd* cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count;
+ _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count;
+ for (int i = 1; i < _ChannelsCount; i++)
+ {
+ ImDrawChannel& ch = _Channels[i];
+ if (int sz = ch.CmdBuffer.Size) { memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; }
+ if (int sz = ch.IdxBuffer.Size) { memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx)); _IdxWritePtr += sz; }
+ }
+ UpdateClipRect(); // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call.
+ _ChannelsCount = 1;
+}
+
+void ImDrawList::ChannelsSetCurrent(int idx)
+{
+ IM_ASSERT(idx < _ChannelsCount);
+ if (_ChannelsCurrent == idx) return;
+ memcpy(&_Channels.Data[_ChannelsCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer)); // copy 12 bytes, four times
+ memcpy(&_Channels.Data[_ChannelsCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer));
+ _ChannelsCurrent = idx;
+ memcpy(&CmdBuffer, &_Channels.Data[_ChannelsCurrent].CmdBuffer, sizeof(CmdBuffer));
+ memcpy(&IdxBuffer, &_Channels.Data[_ChannelsCurrent].IdxBuffer, sizeof(IdxBuffer));
+ _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size;
+}
+
+// NB: this can be called with negative count for removing primitives (as long as the result does not underflow)
+void ImDrawList::PrimReserve(int idx_count, int vtx_count)
+{
+ ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size-1];
+ draw_cmd.ElemCount += idx_count;
+
+ int vtx_buffer_old_size = VtxBuffer.Size;
+ VtxBuffer.resize(vtx_buffer_old_size + vtx_count);
+ _VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size;
+
+ int idx_buffer_old_size = IdxBuffer.Size;
+ IdxBuffer.resize(idx_buffer_old_size + idx_count);
+ _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size;
+}
+
+// Fully unrolled with inline call to keep our debug builds decently fast.
+void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col)
+{
+ ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel);
+ ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
+ _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
+ _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
+ _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+ _VtxCurrentIdx += 4;
+ _IdxWritePtr += 6;
+}
+
+void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col)
+{
+ ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y);
+ ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
+ _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
+ _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
+ _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+ _VtxCurrentIdx += 4;
+ _IdxWritePtr += 6;
+}
+
+void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)
+{
+ ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
+ _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
+ _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
+ _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+ _VtxCurrentIdx += 4;
+ _IdxWritePtr += 6;
+}
+
+// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superflous function calls to optimize debug/non-inlined builds.
+// Those macros expects l-values.
+#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } }
+#define IM_NORMALIZE2F_OVER_EPSILON_CLAMP(VX,VY,EPS,INVLENMAX) { float d2 = VX*VX + VY*VY; if (d2 > EPS) { float inv_len = 1.0f / ImSqrt(d2); if (inv_len > INVLENMAX) inv_len = INVLENMAX; VX *= inv_len; VY *= inv_len; } }
+
+// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
+// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
+void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness)
+{
+ if (points_count < 2)
+ return;
+
+ const ImVec2 uv = _Data->TexUvWhitePixel;
+
+ int count = points_count;
+ if (!closed)
+ count = points_count-1;
+
+ const bool thick_line = thickness > 1.0f;
+ if (Flags & ImDrawListFlags_AntiAliasedLines)
+ {
+ // Anti-aliased stroke
+ const float AA_SIZE = 1.0f;
+ const ImU32 col_trans = col & ~IM_COL32_A_MASK;
+
+ const int idx_count = thick_line ? count*18 : count*12;
+ const int vtx_count = thick_line ? points_count*4 : points_count*3;
+ PrimReserve(idx_count, vtx_count);
+
+ // Temporary buffer
+ ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2));
+ ImVec2* temp_points = temp_normals + points_count;
+
+ for (int i1 = 0; i1 < count; i1++)
+ {
+ const int i2 = (i1+1) == points_count ? 0 : i1+1;
+ float dx = points[i2].x - points[i1].x;
+ float dy = points[i2].y - points[i1].y;
+ IM_NORMALIZE2F_OVER_ZERO(dx, dy);
+ temp_normals[i1].x = dy;
+ temp_normals[i1].y = -dx;
+ }
+ if (!closed)
+ temp_normals[points_count-1] = temp_normals[points_count-2];
+
+ if (!thick_line)
+ {
+ if (!closed)
+ {
+ temp_points[0] = points[0] + temp_normals[0] * AA_SIZE;
+ temp_points[1] = points[0] - temp_normals[0] * AA_SIZE;
+ temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * AA_SIZE;
+ temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE;
+ }
+
+ // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
+ unsigned int idx1 = _VtxCurrentIdx;
+ for (int i1 = 0; i1 < count; i1++)
+ {
+ const int i2 = (i1+1) == points_count ? 0 : i1+1;
+ unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+3;
+
+ // Average normals
+ float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
+ float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f;
+ IM_NORMALIZE2F_OVER_EPSILON_CLAMP(dm_x, dm_y, 0.000001f, 100.0f)
+ dm_x *= AA_SIZE;
+ dm_y *= AA_SIZE;
+
+ // Add temporary vertexes
+ ImVec2* out_vtx = &temp_points[i2*2];
+ out_vtx[0].x = points[i2].x + dm_x;
+ out_vtx[0].y = points[i2].y + dm_y;
+ out_vtx[1].x = points[i2].x - dm_x;
+ out_vtx[1].y = points[i2].y - dm_y;
+
+ // Add indexes
+ _IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2);
+ _IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0);
+ _IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0);
+ _IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10]= (ImDrawIdx)(idx2+0); _IdxWritePtr[11]= (ImDrawIdx)(idx2+1);
+ _IdxWritePtr += 12;
+
+ idx1 = idx2;
+ }
+
+ // Add vertexes
+ for (int i = 0; i < points_count; i++)
+ {
+ _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = temp_points[i*2+0]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans;
+ _VtxWritePtr[2].pos = temp_points[i*2+1]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col_trans;
+ _VtxWritePtr += 3;
+ }
+ }
+ else
+ {
+ const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
+ if (!closed)
+ {
+ temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE);
+ temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness);
+ temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness);
+ temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE);
+ temp_points[(points_count-1)*4+0] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE);
+ temp_points[(points_count-1)*4+1] = points[points_count-1] + temp_normals[points_count-1] * (half_inner_thickness);
+ temp_points[(points_count-1)*4+2] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness);
+ temp_points[(points_count-1)*4+3] = points[points_count-1] - temp_normals[points_count-1] * (half_inner_thickness + AA_SIZE);
+ }
+
+ // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
+ unsigned int idx1 = _VtxCurrentIdx;
+ for (int i1 = 0; i1 < count; i1++)
+ {
+ const int i2 = (i1+1) == points_count ? 0 : i1+1;
+ unsigned int idx2 = (i1+1) == points_count ? _VtxCurrentIdx : idx1+4;
+
+ // Average normals
+ float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
+ float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f;
+ IM_NORMALIZE2F_OVER_EPSILON_CLAMP(dm_x, dm_y, 0.000001f, 100.0f);
+ float dm_out_x = dm_x * (half_inner_thickness + AA_SIZE);
+ float dm_out_y = dm_y * (half_inner_thickness + AA_SIZE);
+ float dm_in_x = dm_x * half_inner_thickness;
+ float dm_in_y = dm_y * half_inner_thickness;
+
+ // Add temporary vertexes
+ ImVec2* out_vtx = &temp_points[i2*4];
+ out_vtx[0].x = points[i2].x + dm_out_x;
+ out_vtx[0].y = points[i2].y + dm_out_y;
+ out_vtx[1].x = points[i2].x + dm_in_x;
+ out_vtx[1].y = points[i2].y + dm_in_y;
+ out_vtx[2].x = points[i2].x - dm_in_x;
+ out_vtx[2].y = points[i2].y - dm_in_y;
+ out_vtx[3].x = points[i2].x - dm_out_x;
+ out_vtx[3].y = points[i2].y - dm_out_y;
+
+ // Add indexes
+ _IdxWritePtr[0] = (ImDrawIdx)(idx2+1); _IdxWritePtr[1] = (ImDrawIdx)(idx1+1); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2);
+ _IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+1);
+ _IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0);
+ _IdxWritePtr[9] = (ImDrawIdx)(idx1+0); _IdxWritePtr[10] = (ImDrawIdx)(idx2+0); _IdxWritePtr[11] = (ImDrawIdx)(idx2+1);
+ _IdxWritePtr[12] = (ImDrawIdx)(idx2+2); _IdxWritePtr[13] = (ImDrawIdx)(idx1+2); _IdxWritePtr[14] = (ImDrawIdx)(idx1+3);
+ _IdxWritePtr[15] = (ImDrawIdx)(idx1+3); _IdxWritePtr[16] = (ImDrawIdx)(idx2+3); _IdxWritePtr[17] = (ImDrawIdx)(idx2+2);
+ _IdxWritePtr += 18;
+
+ idx1 = idx2;
+ }
+
+ // Add vertexes
+ for (int i = 0; i < points_count; i++)
+ {
+ _VtxWritePtr[0].pos = temp_points[i*4+0]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col_trans;
+ _VtxWritePtr[1].pos = temp_points[i*4+1]; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = temp_points[i*4+2]; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = temp_points[i*4+3]; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col_trans;
+ _VtxWritePtr += 4;
+ }
+ }
+ _VtxCurrentIdx += (ImDrawIdx)vtx_count;
+ }
+ else
+ {
+ // Non Anti-aliased Stroke
+ const int idx_count = count*6;
+ const int vtx_count = count*4; // FIXME-OPT: Not sharing edges
+ PrimReserve(idx_count, vtx_count);
+
+ for (int i1 = 0; i1 < count; i1++)
+ {
+ const int i2 = (i1+1) == points_count ? 0 : i1+1;
+ const ImVec2& p1 = points[i1];
+ const ImVec2& p2 = points[i2];
+
+ float dx = p2.x - p1.x;
+ float dy = p2.y - p1.y;
+ IM_NORMALIZE2F_OVER_ZERO(dx, dy);
+ dx *= (thickness * 0.5f);
+ dy *= (thickness * 0.5f);
+
+ _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+
+ _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+2);
+ _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx+2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx+3);
+ _IdxWritePtr += 6;
+ _VtxCurrentIdx += 4;
+ }
+ }
+}
+
+// We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds.
+void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
+{
+ if (points_count < 3)
+ return;
+
+ const ImVec2 uv = _Data->TexUvWhitePixel;
+
+ if (Flags & ImDrawListFlags_AntiAliasedFill)
+ {
+ // Anti-aliased Fill
+ const float AA_SIZE = 1.0f;
+ const ImU32 col_trans = col & ~IM_COL32_A_MASK;
+ const int idx_count = (points_count-2)*3 + points_count*6;
+ const int vtx_count = (points_count*2);
+ PrimReserve(idx_count, vtx_count);
+
+ // Add indexes for fill
+ unsigned int vtx_inner_idx = _VtxCurrentIdx;
+ unsigned int vtx_outer_idx = _VtxCurrentIdx+1;
+ for (int i = 2; i < points_count; i++)
+ {
+ _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+((i-1)<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx+(i<<1));
+ _IdxWritePtr += 3;
+ }
+
+ // Compute normals
+ ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2));
+ for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)
+ {
+ const ImVec2& p0 = points[i0];
+ const ImVec2& p1 = points[i1];
+ float dx = p1.x - p0.x;
+ float dy = p1.y - p0.y;
+ IM_NORMALIZE2F_OVER_ZERO(dx, dy);
+ temp_normals[i0].x = dy;
+ temp_normals[i0].y = -dx;
+ }
+
+ for (int i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++)
+ {
+ // Average normals
+ const ImVec2& n0 = temp_normals[i0];
+ const ImVec2& n1 = temp_normals[i1];
+ float dm_x = (n0.x + n1.x) * 0.5f;
+ float dm_y = (n0.y + n1.y) * 0.5f;
+ IM_NORMALIZE2F_OVER_EPSILON_CLAMP(dm_x, dm_y, 0.000001f, 100.0f);
+ dm_x *= AA_SIZE * 0.5f;
+ dm_y *= AA_SIZE * 0.5f;
+
+ // Add vertices
+ _VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner
+ _VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer
+ _VtxWritePtr += 2;
+
+ // Add indexes for fringes
+ _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx+(i1<<1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx+(i0<<1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx+(i0<<1));
+ _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx+(i0<<1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx+(i1<<1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx+(i1<<1));
+ _IdxWritePtr += 6;
+ }
+ _VtxCurrentIdx += (ImDrawIdx)vtx_count;
+ }
+ else
+ {
+ // Non Anti-aliased Fill
+ const int idx_count = (points_count-2)*3;
+ const int vtx_count = points_count;
+ PrimReserve(idx_count, vtx_count);
+ for (int i = 0; i < vtx_count; i++)
+ {
+ _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr++;
+ }
+ for (int i = 2; i < points_count; i++)
+ {
+ _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx+i-1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx+i);
+ _IdxWritePtr += 3;
+ }
+ _VtxCurrentIdx += (ImDrawIdx)vtx_count;
+ }
+}
+
+void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12)
+{
+ if (radius == 0.0f || a_min_of_12 > a_max_of_12)
+ {
+ _Path.push_back(centre);
+ return;
+ }
+ _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1));
+ for (int a = a_min_of_12; a <= a_max_of_12; a++)
+ {
+ const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)];
+ _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius));
+ }
+}
+
+void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments)
+{
+ if (radius == 0.0f)
+ {
+ _Path.push_back(centre);
+ return;
+ }
+ _Path.reserve(_Path.Size + (num_segments + 1));
+ for (int i = 0; i <= num_segments; i++)
+ {
+ const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);
+ _Path.push_back(ImVec2(centre.x + ImCos(a) * radius, centre.y + ImSin(a) * radius));
+ }
+}
+
+static void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
+{
+ float dx = x4 - x1;
+ float dy = y4 - y1;
+ float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
+ float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
+ d2 = (d2 >= 0) ? d2 : -d2;
+ d3 = (d3 >= 0) ? d3 : -d3;
+ if ((d2+d3) * (d2+d3) < tess_tol * (dx*dx + dy*dy))
+ {
+ path->push_back(ImVec2(x4, y4));
+ }
+ else if (level < 10)
+ {
+ float x12 = (x1+x2)*0.5f, y12 = (y1+y2)*0.5f;
+ float x23 = (x2+x3)*0.5f, y23 = (y2+y3)*0.5f;
+ float x34 = (x3+x4)*0.5f, y34 = (y3+y4)*0.5f;
+ float x123 = (x12+x23)*0.5f, y123 = (y12+y23)*0.5f;
+ float x234 = (x23+x34)*0.5f, y234 = (y23+y34)*0.5f;
+ float x1234 = (x123+x234)*0.5f, y1234 = (y123+y234)*0.5f;
+
+ PathBezierToCasteljau(path, x1,y1, x12,y12, x123,y123, x1234,y1234, tess_tol, level+1);
+ PathBezierToCasteljau(path, x1234,y1234, x234,y234, x34,y34, x4,y4, tess_tol, level+1);
+ }
+}
+
+void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments)
+{
+ ImVec2 p1 = _Path.back();
+ if (num_segments == 0)
+ {
+ // Auto-tessellated
+ PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0);
+ }
+ else
+ {
+ float t_step = 1.0f / (float)num_segments;
+ for (int i_step = 1; i_step <= num_segments; i_step++)
+ {
+ float t = t_step * i_step;
+ float u = 1.0f - t;
+ float w1 = u*u*u;
+ float w2 = 3*u*u*t;
+ float w3 = 3*u*t*t;
+ float w4 = t*t*t;
+ _Path.push_back(ImVec2(w1*p1.x + w2*p2.x + w3*p3.x + w4*p4.x, w1*p1.y + w2*p2.y + w3*p3.y + w4*p4.y));
+ }
+ }
+}
+
+void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners)
+{
+ rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f ) - 1.0f);
+ rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f ) - 1.0f);
+
+ if (rounding <= 0.0f || rounding_corners == 0)
+ {
+ PathLineTo(a);
+ PathLineTo(ImVec2(b.x, a.y));
+ PathLineTo(b);
+ PathLineTo(ImVec2(a.x, b.y));
+ }
+ else
+ {
+ const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f;
+ const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f;
+ const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f;
+ const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f;
+ PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);
+ PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);
+ PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);
+ PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6);
+ }
+}
+
+void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+ PathLineTo(a + ImVec2(0.5f,0.5f));
+ PathLineTo(b + ImVec2(0.5f,0.5f));
+ PathStroke(col, false, thickness);
+}
+
+// a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly.
+void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+ if (Flags & ImDrawListFlags_AntiAliasedLines)
+ PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners_flags);
+ else
+ PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners_flags); // Better looking lower-right corner and rounded non-AA shapes.
+ PathStroke(col, true, thickness);
+}
+
+void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+ if (rounding > 0.0f)
+ {
+ PathRect(a, b, rounding, rounding_corners_flags);
+ PathFillConvex(col);
+ }
+ else
+ {
+ PrimReserve(6, 4);
+ PrimRect(a, b, col);
+ }
+}
+
+void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
+{
+ if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
+ return;
+
+ const ImVec2 uv = _Data->TexUvWhitePixel;
+ PrimReserve(6, 4);
+ PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2));
+ PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3));
+ PrimWriteVtx(a, uv, col_upr_left);
+ PrimWriteVtx(ImVec2(c.x, a.y), uv, col_upr_right);
+ PrimWriteVtx(c, uv, col_bot_right);
+ PrimWriteVtx(ImVec2(a.x, c.y), uv, col_bot_left);
+}
+
+void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(a);
+ PathLineTo(b);
+ PathLineTo(c);
+ PathLineTo(d);
+ PathStroke(col, true, thickness);
+}
+
+void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(a);
+ PathLineTo(b);
+ PathLineTo(c);
+ PathLineTo(d);
+ PathFillConvex(col);
+}
+
+void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(a);
+ PathLineTo(b);
+ PathLineTo(c);
+ PathStroke(col, true, thickness);
+}
+
+void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(a);
+ PathLineTo(b);
+ PathLineTo(c);
+ PathFillConvex(col);
+}
+
+void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
+ PathArcTo(centre, radius-0.5f, 0.0f, a_max, num_segments);
+ PathStroke(col, true, thickness);
+}
+
+void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ const float a_max = IM_PI*2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
+ PathArcTo(centre, radius, 0.0f, a_max, num_segments);
+ PathFillConvex(col);
+}
+
+void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(pos0);
+ PathBezierCurveTo(cp0, cp1, pos1, num_segments);
+ PathStroke(col, false, thickness);
+}
+
+void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ if (text_end == NULL)
+ text_end = text_begin + strlen(text_begin);
+ if (text_begin == text_end)
+ return;
+
+ // Pull default font/size from the shared ImDrawListSharedData instance
+ if (font == NULL)
+ font = _Data->Font;
+ if (font_size == 0.0f)
+ font_size = _Data->FontSize;
+
+ IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
+
+ ImVec4 clip_rect = _ClipRectStack.back();
+ if (cpu_fine_clip_rect)
+ {
+ clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x);
+ clip_rect.y = ImMax(clip_rect.y, cpu_fine_clip_rect->y);
+ clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z);
+ clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);
+ }
+ font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);
+}
+
+void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)
+{
+ AddText(NULL, 0.0f, pos, col, text_begin, text_end);
+}
+
+void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
+ if (push_texture_id)
+ PushTextureID(user_texture_id);
+
+ PrimReserve(6, 4);
+ PrimRectUV(a, b, uv_a, uv_b, col);
+
+ if (push_texture_id)
+ PopTextureID();
+}
+
+void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
+ if (push_texture_id)
+ PushTextureID(user_texture_id);
+
+ PrimReserve(6, 4);
+ PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col);
+
+ if (push_texture_id)
+ PopTextureID();
+}
+
+void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0)
+ {
+ AddImage(user_texture_id, a, b, uv_a, uv_b, col);
+ return;
+ }
+
+ const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
+ if (push_texture_id)
+ PushTextureID(user_texture_id);
+
+ int vert_start_idx = VtxBuffer.Size;
+ PathRect(a, b, rounding, rounding_corners);
+ PathFillConvex(col);
+ int vert_end_idx = VtxBuffer.Size;
+ ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, a, b, uv_a, uv_b, true);
+
+ if (push_texture_id)
+ PopTextureID();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImDrawData
+//-----------------------------------------------------------------------------
+
+// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
+void ImDrawData::DeIndexAllBuffers()
+{
+ ImVector<ImDrawVert> new_vtx_buffer;
+ TotalVtxCount = TotalIdxCount = 0;
+ for (int i = 0; i < CmdListsCount; i++)
+ {
+ ImDrawList* cmd_list = CmdLists[i];
+ if (cmd_list->IdxBuffer.empty())
+ continue;
+ new_vtx_buffer.resize(cmd_list->IdxBuffer.Size);
+ for (int j = 0; j < cmd_list->IdxBuffer.Size; j++)
+ new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]];
+ cmd_list->VtxBuffer.swap(new_vtx_buffer);
+ cmd_list->IdxBuffer.resize(0);
+ TotalVtxCount += cmd_list->VtxBuffer.Size;
+ }
+}
+
+// Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
+void ImDrawData::ScaleClipRects(const ImVec2& scale)
+{
+ for (int i = 0; i < CmdListsCount; i++)
+ {
+ ImDrawList* cmd_list = CmdLists[i];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i];
+ cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, cmd->ClipRect.w * scale.y);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Helpers ShadeVertsXXX functions
+//-----------------------------------------------------------------------------
+
+// Generic linear color gradient, write to RGB fields, leave A untouched.
+void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)
+{
+ ImVec2 gradient_extent = gradient_p1 - gradient_p0;
+ float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent);
+ ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx;
+ ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx;
+ for (ImDrawVert* vert = vert_start; vert < vert_end; vert++)
+ {
+ float d = ImDot(vert->pos - gradient_p0, gradient_extent);
+ float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
+ int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t);
+ int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t);
+ int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t);
+ vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK);
+ }
+}
+
+// Distribute UV over (a, b) rectangle
+void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp)
+{
+ const ImVec2 size = b - a;
+ const ImVec2 uv_size = uv_b - uv_a;
+ const ImVec2 scale = ImVec2(
+ size.x != 0.0f ? (uv_size.x / size.x) : 0.0f,
+ size.y != 0.0f ? (uv_size.y / size.y) : 0.0f);
+
+ ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx;
+ ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx;
+ if (clamp)
+ {
+ const ImVec2 min = ImMin(uv_a, uv_b);
+ const ImVec2 max = ImMax(uv_a, uv_b);
+ for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
+ vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max);
+ }
+ else
+ {
+ for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
+ vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontConfig
+//-----------------------------------------------------------------------------
+
+ImFontConfig::ImFontConfig()
+{
+ FontData = NULL;
+ FontDataSize = 0;
+ FontDataOwnedByAtlas = true;
+ FontNo = 0;
+ SizePixels = 0.0f;
+ OversampleH = 3;
+ OversampleV = 1;
+ PixelSnapH = false;
+ GlyphExtraSpacing = ImVec2(0.0f, 0.0f);
+ GlyphOffset = ImVec2(0.0f, 0.0f);
+ GlyphRanges = NULL;
+ GlyphMinAdvanceX = 0.0f;
+ GlyphMaxAdvanceX = FLT_MAX;
+ MergeMode = false;
+ RasterizerFlags = 0x00;
+ RasterizerMultiply = 1.0f;
+ memset(Name, 0, sizeof(Name));
+ DstFont = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontAtlas
+//-----------------------------------------------------------------------------
+
+// A work of art lies ahead! (. = white layer, X = black layer, others are blank)
+// The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes.
+const int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 108;
+const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27;
+const unsigned int FONT_ATLAS_DEFAULT_TEX_DATA_ID = 0x80000000;
+static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] =
+{
+ "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX "
+ "..- -X.....X- X.X - X.X -X.....X - X.....X- X..X "
+ "--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X "
+ "X - X.X - X.....X - X.....X -X...X - X...X- X..X "
+ "XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X "
+ "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX "
+ "X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX "
+ "X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX "
+ "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X "
+ "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X"
+ "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X"
+ "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X"
+ "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X"
+ "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X"
+ "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X"
+ "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X"
+ "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X "
+ "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X "
+ "X.X X..X - -X.......X- X.......X - XX XX - - X..........X "
+ "XX X..X - - X.....X - X.....X - X.X X.X - - X........X "
+ " X..X - X...X - X...X - X..X X..X - - X........X "
+ " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX "
+ "------------ - X - X -X.....................X- ------------------"
+ " ----------------------------------- X...XXXXXXXXXXXXX...X - "
+ " - X..X X..X - "
+ " - X.X X.X - "
+ " - XX XX - "
+};
+
+static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] =
+{
+ // Pos ........ Size ......... Offset ......
+ { ImVec2( 0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow
+ { ImVec2(13,0), ImVec2( 7,16), ImVec2( 1, 8) }, // ImGuiMouseCursor_TextInput
+ { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll
+ { ImVec2(21,0), ImVec2( 9,23), ImVec2( 4,11) }, // ImGuiMouseCursor_ResizeNS
+ { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 4) }, // ImGuiMouseCursor_ResizeEW
+ { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW
+ { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE
+ { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand
+};
+
+ImFontAtlas::ImFontAtlas()
+{
+ Locked = false;
+ Flags = ImFontAtlasFlags_None;
+ TexID = (ImTextureID)NULL;
+ TexDesiredWidth = 0;
+ TexGlyphPadding = 1;
+
+ TexPixelsAlpha8 = NULL;
+ TexPixelsRGBA32 = NULL;
+ TexWidth = TexHeight = 0;
+ TexUvScale = ImVec2(0.0f, 0.0f);
+ TexUvWhitePixel = ImVec2(0.0f, 0.0f);
+ for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++)
+ CustomRectIds[n] = -1;
+}
+
+ImFontAtlas::~ImFontAtlas()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ Clear();
+}
+
+void ImFontAtlas::ClearInputData()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ for (int i = 0; i < ConfigData.Size; i++)
+ if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas)
+ {
+ ImGui::MemFree(ConfigData[i].FontData);
+ ConfigData[i].FontData = NULL;
+ }
+
+ // When clearing this we lose access to the font name and other information used to build the font.
+ for (int i = 0; i < Fonts.Size; i++)
+ if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size)
+ {
+ Fonts[i]->ConfigData = NULL;
+ Fonts[i]->ConfigDataCount = 0;
+ }
+ ConfigData.clear();
+ CustomRects.clear();
+ for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++)
+ CustomRectIds[n] = -1;
+}
+
+void ImFontAtlas::ClearTexData()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ if (TexPixelsAlpha8)
+ ImGui::MemFree(TexPixelsAlpha8);
+ if (TexPixelsRGBA32)
+ ImGui::MemFree(TexPixelsRGBA32);
+ TexPixelsAlpha8 = NULL;
+ TexPixelsRGBA32 = NULL;
+}
+
+void ImFontAtlas::ClearFonts()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ for (int i = 0; i < Fonts.Size; i++)
+ IM_DELETE(Fonts[i]);
+ Fonts.clear();
+}
+
+void ImFontAtlas::Clear()
+{
+ ClearInputData();
+ ClearTexData();
+ ClearFonts();
+}
+
+void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
+{
+ // Build atlas on demand
+ if (TexPixelsAlpha8 == NULL)
+ {
+ if (ConfigData.empty())
+ AddFontDefault();
+ Build();
+ }
+
+ *out_pixels = TexPixelsAlpha8;
+ if (out_width) *out_width = TexWidth;
+ if (out_height) *out_height = TexHeight;
+ if (out_bytes_per_pixel) *out_bytes_per_pixel = 1;
+}
+
+void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
+{
+ // Convert to RGBA32 format on demand
+ // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp
+ if (!TexPixelsRGBA32)
+ {
+ unsigned char* pixels = NULL;
+ GetTexDataAsAlpha8(&pixels, NULL, NULL);
+ if (pixels)
+ {
+ TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4));
+ const unsigned char* src = pixels;
+ unsigned int* dst = TexPixelsRGBA32;
+ for (int n = TexWidth * TexHeight; n > 0; n--)
+ *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));
+ }
+ }
+
+ *out_pixels = (unsigned char*)TexPixelsRGBA32;
+ if (out_width) *out_width = TexWidth;
+ if (out_height) *out_height = TexHeight;
+ if (out_bytes_per_pixel) *out_bytes_per_pixel = 4;
+}
+
+ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);
+ IM_ASSERT(font_cfg->SizePixels > 0.0f);
+
+ // Create new font
+ if (!font_cfg->MergeMode)
+ Fonts.push_back(IM_NEW(ImFont));
+ else
+ IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
+
+ ConfigData.push_back(*font_cfg);
+ ImFontConfig& new_font_cfg = ConfigData.back();
+ if (!new_font_cfg.DstFont)
+ new_font_cfg.DstFont = Fonts.back();
+ if (!new_font_cfg.FontDataOwnedByAtlas)
+ {
+ new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize);
+ new_font_cfg.FontDataOwnedByAtlas = true;
+ memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);
+ }
+
+ // Invalidate texture
+ ClearTexData();
+ return new_font_cfg.DstFont;
+}
+
+// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
+static unsigned int stb_decompress_length(const unsigned char *input);
+static unsigned int stb_decompress(unsigned char *output, const unsigned char *input, unsigned int length);
+static const char* GetDefaultCompressedFontDataTTFBase85();
+static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; }
+static void Decode85(const unsigned char* src, unsigned char* dst)
+{
+ while (*src)
+ {
+ unsigned int tmp = Decode85Byte(src[0]) + 85*(Decode85Byte(src[1]) + 85*(Decode85Byte(src[2]) + 85*(Decode85Byte(src[3]) + 85*Decode85Byte(src[4]))));
+ dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness.
+ src += 5;
+ dst += 4;
+ }
+}
+
+// Load embedded ProggyClean.ttf at size 13, disable oversampling
+ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
+{
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ if (!font_cfg_template)
+ {
+ font_cfg.OversampleH = font_cfg.OversampleV = 1;
+ font_cfg.PixelSnapH = true;
+ }
+ if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "ProggyClean.ttf, 13px");
+ if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f;
+
+ const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
+ const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault();
+ ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges);
+ font->DisplayOffset.y = 1.0f;
+ return font;
+}
+
+ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ size_t data_size = 0;
+ void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0);
+ if (!data)
+ {
+ IM_ASSERT(0); // Could not load file.
+ return NULL;
+ }
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ if (font_cfg.Name[0] == '\0')
+ {
+ // Store a short copy of filename into into the font name for convenience
+ const char* p;
+ for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
+ ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels);
+ }
+ return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
+}
+
+// NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
+ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ IM_ASSERT(font_cfg.FontData == NULL);
+ font_cfg.FontData = ttf_data;
+ font_cfg.FontDataSize = ttf_size;
+ font_cfg.SizePixels = size_pixels;
+ if (glyph_ranges)
+ font_cfg.GlyphRanges = glyph_ranges;
+ return AddFont(&font_cfg);
+}
+
+ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
+{
+ const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data);
+ unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size);
+ stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);
+
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ IM_ASSERT(font_cfg.FontData == NULL);
+ font_cfg.FontDataOwnedByAtlas = true;
+ return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges);
+}
+
+ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)
+{
+ int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
+ void* compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size);
+ Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
+ ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
+ ImGui::MemFree(compressed_ttf);
+ return font;
+}
+
+int ImFontAtlas::AddCustomRectRegular(unsigned int id, int width, int height)
+{
+ IM_ASSERT(id >= 0x10000);
+ IM_ASSERT(width > 0 && width <= 0xFFFF);
+ IM_ASSERT(height > 0 && height <= 0xFFFF);
+ CustomRect r;
+ r.ID = id;
+ r.Width = (unsigned short)width;
+ r.Height = (unsigned short)height;
+ CustomRects.push_back(r);
+ return CustomRects.Size - 1; // Return index
+}
+
+int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset)
+{
+ IM_ASSERT(font != NULL);
+ IM_ASSERT(width > 0 && width <= 0xFFFF);
+ IM_ASSERT(height > 0 && height <= 0xFFFF);
+ CustomRect r;
+ r.ID = id;
+ r.Width = (unsigned short)width;
+ r.Height = (unsigned short)height;
+ r.GlyphAdvanceX = advance_x;
+ r.GlyphOffset = offset;
+ r.Font = font;
+ CustomRects.push_back(r);
+ return CustomRects.Size - 1; // Return index
+}
+
+void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max)
+{
+ IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates
+ IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed
+ *out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y);
+ *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y);
+}
+
+bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2])
+{
+ if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT)
+ return false;
+ if (Flags & ImFontAtlasFlags_NoMouseCursors)
+ return false;
+
+ IM_ASSERT(CustomRectIds[0] != -1);
+ ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]];
+ IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID);
+ ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y);
+ ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1];
+ *out_size = size;
+ *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2];
+ out_uv_border[0] = (pos) * TexUvScale;
+ out_uv_border[1] = (pos + size) * TexUvScale;
+ pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;
+ out_uv_fill[0] = (pos) * TexUvScale;
+ out_uv_fill[1] = (pos + size) * TexUvScale;
+ return true;
+}
+
+bool ImFontAtlas::Build()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ return ImFontAtlasBuildWithStbTruetype(this);
+}
+
+void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor)
+{
+ for (unsigned int i = 0; i < 256; i++)
+ {
+ unsigned int value = (unsigned int)(i * in_brighten_factor);
+ out_table[i] = value > 255 ? 255 : (value & 0xFF);
+ }
+}
+
+void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride)
+{
+ unsigned char* data = pixels + x + y * stride;
+ for (int j = h; j > 0; j--, data += stride)
+ for (int i = 0; i < w; i++)
+ data[i] = table[data[i]];
+}
+
+bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
+{
+ IM_ASSERT(atlas->ConfigData.Size > 0);
+
+ ImFontAtlasBuildRegisterDefaultCustomRects(atlas);
+
+ atlas->TexID = (ImTextureID)NULL;
+ atlas->TexWidth = atlas->TexHeight = 0;
+ atlas->TexUvScale = ImVec2(0.0f, 0.0f);
+ atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
+ atlas->ClearTexData();
+
+ // Count glyphs/ranges
+ int total_glyphs_count = 0;
+ int total_ranges_count = 0;
+ for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
+ {
+ ImFontConfig& cfg = atlas->ConfigData[input_i];
+ if (!cfg.GlyphRanges)
+ cfg.GlyphRanges = atlas->GetGlyphRangesDefault();
+ for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, total_ranges_count++)
+ total_glyphs_count += (in_range[1] - in_range[0]) + 1;
+ }
+
+ // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish.
+ // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
+ atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512;
+ atlas->TexHeight = 0;
+
+ // Start packing
+ const int max_tex_height = 1024*32;
+ stbtt_pack_context spc = {};
+ if (!stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL))
+ return false;
+ stbtt_PackSetOversampling(&spc, 1, 1);
+
+ // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
+ ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info);
+
+ // Initialize font information (so we can error without any cleanup)
+ struct ImFontTempBuildData
+ {
+ stbtt_fontinfo FontInfo;
+ stbrp_rect* Rects;
+ int RectsCount;
+ stbtt_pack_range* Ranges;
+ int RangesCount;
+ };
+ ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)atlas->ConfigData.Size * sizeof(ImFontTempBuildData));
+ for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
+ {
+ ImFontConfig& cfg = atlas->ConfigData[input_i];
+ ImFontTempBuildData& tmp = tmp_array[input_i];
+ IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));
+
+ const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo);
+ IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found.");
+ if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset))
+ {
+ atlas->TexWidth = atlas->TexHeight = 0; // Reset output on failure
+ ImGui::MemFree(tmp_array);
+ return false;
+ }
+ }
+
+ // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
+ int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0;
+ stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbtt_packedchar));
+ stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbrp_rect));
+ stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_ranges_count * sizeof(stbtt_pack_range));
+ memset(buf_packedchars, 0, total_glyphs_count * sizeof(stbtt_packedchar));
+ memset(buf_rects, 0, total_glyphs_count * sizeof(stbrp_rect)); // Unnecessary but let's clear this for the sake of sanity.
+ memset(buf_ranges, 0, total_ranges_count * sizeof(stbtt_pack_range));
+
+ // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point)
+ for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
+ {
+ ImFontConfig& cfg = atlas->ConfigData[input_i];
+ ImFontTempBuildData& tmp = tmp_array[input_i];
+
+ // Setup ranges
+ int font_glyphs_count = 0;
+ int font_ranges_count = 0;
+ for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, font_ranges_count++)
+ font_glyphs_count += (in_range[1] - in_range[0]) + 1;
+ tmp.Ranges = buf_ranges + buf_ranges_n;
+ tmp.RangesCount = font_ranges_count;
+ buf_ranges_n += font_ranges_count;
+ for (int i = 0; i < font_ranges_count; i++)
+ {
+ const ImWchar* in_range = &cfg.GlyphRanges[i * 2];
+ stbtt_pack_range& range = tmp.Ranges[i];
+ range.font_size = cfg.SizePixels;
+ range.first_unicode_codepoint_in_range = in_range[0];
+ range.num_chars = (in_range[1] - in_range[0]) + 1;
+ range.chardata_for_range = buf_packedchars + buf_packedchars_n;
+ buf_packedchars_n += range.num_chars;
+ }
+
+ // Gather the sizes of all rectangle we need
+ tmp.Rects = buf_rects + buf_rects_n;
+ tmp.RectsCount = font_glyphs_count;
+ buf_rects_n += font_glyphs_count;
+ stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV);
+ int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects);
+ IM_ASSERT(n == font_glyphs_count);
+
+ // Detect missing glyphs and replace them with a zero-sized box instead of relying on the default glyphs
+ // This allows us merging overlapping icon fonts more easily.
+ int rect_i = 0;
+ for (int range_i = 0; range_i < tmp.RangesCount; range_i++)
+ for (int char_i = 0; char_i < tmp.Ranges[range_i].num_chars; char_i++, rect_i++)
+ if (stbtt_FindGlyphIndex(&tmp.FontInfo, tmp.Ranges[range_i].first_unicode_codepoint_in_range + char_i) == 0)
+ tmp.Rects[rect_i].w = tmp.Rects[rect_i].h = 0;
+
+ // Pack
+ stbrp_pack_rects((stbrp_context*)spc.pack_info, tmp.Rects, n);
+
+ // Extend texture height
+ // Also mark missing glyphs as non-packed so we don't attempt to render into them
+ for (int i = 0; i < n; i++)
+ {
+ if (tmp.Rects[i].w == 0 && tmp.Rects[i].h == 0)
+ tmp.Rects[i].was_packed = 0;
+ if (tmp.Rects[i].was_packed)
+ atlas->TexHeight = ImMax(atlas->TexHeight, tmp.Rects[i].y + tmp.Rects[i].h);
+ }
+ }
+ IM_ASSERT(buf_rects_n == total_glyphs_count);
+ IM_ASSERT(buf_packedchars_n == total_glyphs_count);
+ IM_ASSERT(buf_ranges_n == total_ranges_count);
+
+ // Create texture
+ atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
+ atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
+ atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight);
+ memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
+ spc.pixels = atlas->TexPixelsAlpha8;
+ spc.height = atlas->TexHeight;
+
+ // Second pass: render font characters
+ for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
+ {
+ ImFontConfig& cfg = atlas->ConfigData[input_i];
+ ImFontTempBuildData& tmp = tmp_array[input_i];
+ stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV);
+ stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects);
+ if (cfg.RasterizerMultiply != 1.0f)
+ {
+ unsigned char multiply_table[256];
+ ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply);
+ for (const stbrp_rect* r = tmp.Rects; r != tmp.Rects + tmp.RectsCount; r++)
+ if (r->was_packed)
+ ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, spc.pixels, r->x, r->y, r->w, r->h, spc.stride_in_bytes);
+ }
+ tmp.Rects = NULL;
+ }
+
+ // End packing
+ stbtt_PackEnd(&spc);
+ ImGui::MemFree(buf_rects);
+ buf_rects = NULL;
+
+ // Third pass: setup ImFont and glyphs for runtime
+ for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
+ {
+ ImFontConfig& cfg = atlas->ConfigData[input_i];
+ ImFontTempBuildData& tmp = tmp_array[input_i];
+ ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true)
+ if (cfg.MergeMode)
+ dst_font->BuildLookupTable();
+
+ const float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels);
+ int unscaled_ascent, unscaled_descent, unscaled_line_gap;
+ stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap);
+
+ const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1));
+ const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1));
+ ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
+ const float font_off_x = cfg.GlyphOffset.x;
+ const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f);
+
+ for (int i = 0; i < tmp.RangesCount; i++)
+ {
+ stbtt_pack_range& range = tmp.Ranges[i];
+ for (int char_idx = 0; char_idx < range.num_chars; char_idx += 1)
+ {
+ const stbtt_packedchar& pc = range.chardata_for_range[char_idx];
+ if (!pc.x0 && !pc.x1 && !pc.y0 && !pc.y1)
+ continue;
+
+ const int codepoint = range.first_unicode_codepoint_in_range + char_idx;
+ if (cfg.MergeMode && dst_font->FindGlyphNoFallback((ImWchar)codepoint))
+ continue;
+
+ float char_advance_x_org = pc.xadvance;
+ float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
+ float char_off_x = font_off_x;
+ if (char_advance_x_org != char_advance_x_mod)
+ char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
+
+ stbtt_aligned_quad q;
+ float dummy_x = 0.0f, dummy_y = 0.0f;
+ stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0);
+ dst_font->AddGlyph((ImWchar)codepoint, q.x0 + char_off_x, q.y0 + font_off_y, q.x1 + char_off_x, q.y1 + font_off_y, q.s0, q.t0, q.s1, q.t1, char_advance_x_mod);
+ }
+ }
+ }
+
+ // Cleanup temporaries
+ ImGui::MemFree(buf_packedchars);
+ ImGui::MemFree(buf_ranges);
+ ImGui::MemFree(tmp_array);
+
+ ImFontAtlasBuildFinish(atlas);
+
+ return true;
+}
+
+void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas)
+{
+ if (atlas->CustomRectIds[0] >= 0)
+ return;
+ if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
+ atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
+ else
+ atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, 2, 2);
+}
+
+void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent)
+{
+ if (!font_config->MergeMode)
+ {
+ font->ClearOutputData();
+ font->FontSize = font_config->SizePixels;
+ font->ConfigData = font_config;
+ font->ContainerAtlas = atlas;
+ font->Ascent = ascent;
+ font->Descent = descent;
+ }
+ font->ConfigDataCount++;
+}
+
+void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaque)
+{
+ stbrp_context* pack_context = (stbrp_context*)pack_context_opaque;
+
+ ImVector<ImFontAtlas::CustomRect>& user_rects = atlas->CustomRects;
+ IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong.
+
+ ImVector<stbrp_rect> pack_rects;
+ pack_rects.resize(user_rects.Size);
+ memset(pack_rects.Data, 0, sizeof(stbrp_rect) * user_rects.Size);
+ for (int i = 0; i < user_rects.Size; i++)
+ {
+ pack_rects[i].w = user_rects[i].Width;
+ pack_rects[i].h = user_rects[i].Height;
+ }
+ stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size);
+ for (int i = 0; i < pack_rects.Size; i++)
+ if (pack_rects[i].was_packed)
+ {
+ user_rects[i].X = pack_rects[i].x;
+ user_rects[i].Y = pack_rects[i].y;
+ IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);
+ atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);
+ }
+}
+
+static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
+{
+ IM_ASSERT(atlas->CustomRectIds[0] >= 0);
+ IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);
+ ImFontAtlas::CustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]];
+ IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID);
+ IM_ASSERT(r.IsPacked());
+
+ const int w = atlas->TexWidth;
+ if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
+ {
+ // Render/copy pixels
+ IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
+ for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++)
+ for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++)
+ {
+ const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * w;
+ const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;
+ atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00;
+ atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00;
+ }
+ }
+ else
+ {
+ IM_ASSERT(r.Width == 2 && r.Height == 2);
+ const int offset = (int)(r.X) + (int)(r.Y) * w;
+ atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
+ }
+ atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y);
+}
+
+void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
+{
+ // Render into our custom data block
+ ImFontAtlasBuildRenderDefaultTexData(atlas);
+
+ // Register custom rectangle glyphs
+ for (int i = 0; i < atlas->CustomRects.Size; i++)
+ {
+ const ImFontAtlas::CustomRect& r = atlas->CustomRects[i];
+ if (r.Font == NULL || r.ID > 0x10000)
+ continue;
+
+ IM_ASSERT(r.Font->ContainerAtlas == atlas);
+ ImVec2 uv0, uv1;
+ atlas->CalcCustomRectUV(&r, &uv0, &uv1);
+ r.Font->AddGlyph((ImWchar)r.ID, r.GlyphOffset.x, r.GlyphOffset.y, r.GlyphOffset.x + r.Width, r.GlyphOffset.y + r.Height, uv0.x, uv0.y, uv1.x, uv1.y, r.GlyphAdvanceX);
+ }
+
+ // Build all fonts lookup tables
+ for (int i = 0; i < atlas->Fonts.Size; i++)
+ if (atlas->Fonts[i]->DirtyLookupTables)
+ atlas->Fonts[i]->BuildLookupTable();
+}
+
+// Retrieve list of range (2 int per range, values are inclusive)
+const ImWchar* ImFontAtlas::GetGlyphRangesDefault()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesKorean()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3131, 0x3163, // Korean alphabets
+ 0xAC00, 0xD79D, // Korean characters
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
+ 0x31F0, 0x31FF, // Katakana Phonetic Extensions
+ 0xFF00, 0xFFEF, // Half-width characters
+ 0x4e00, 0x9FAF, // CJK Ideograms
+ 0,
+ };
+ return &ranges[0];
+}
+
+static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short* accumulative_offsets, int accumulative_offsets_count, ImWchar* out_ranges)
+{
+ for (int n = 0; n < accumulative_offsets_count; n++, out_ranges += 2)
+ {
+ out_ranges[0] = out_ranges[1] = (ImWchar)(base_codepoint + accumulative_offsets[n]);
+ base_codepoint += accumulative_offsets[n];
+ }
+ out_ranges[0] = 0;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] ImFontAtlas glyph ranges helpers
+//-------------------------------------------------------------------------
+
+const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
+{
+ // Store 2500 regularly used characters for Simplified Chinese.
+ // Sourced from https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E7%8E%B0%E4%BB%A3%E6%B1%89%E8%AF%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E8%A1%A8
+ // This table covers 97.97% of all characters used during the month in July, 1987.
+ // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
+ // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.)
+ static const short accumulative_offsets_from_0x4E00[] =
+ {
+ 0,1,2,4,1,1,1,1,2,1,3,2,1,2,2,1,1,1,1,1,5,2,1,2,3,3,3,2,2,4,1,1,1,2,1,5,2,3,1,2,1,2,1,1,2,1,1,2,2,1,4,1,1,1,1,5,10,1,2,19,2,1,2,1,2,1,2,1,2,
+ 1,5,1,6,3,2,1,2,2,1,1,1,4,8,5,1,1,4,1,1,3,1,2,1,5,1,2,1,1,1,10,1,1,5,2,4,6,1,4,2,2,2,12,2,1,1,6,1,1,1,4,1,1,4,6,5,1,4,2,2,4,10,7,1,1,4,2,4,
+ 2,1,4,3,6,10,12,5,7,2,14,2,9,1,1,6,7,10,4,7,13,1,5,4,8,4,1,1,2,28,5,6,1,1,5,2,5,20,2,2,9,8,11,2,9,17,1,8,6,8,27,4,6,9,20,11,27,6,68,2,2,1,1,
+ 1,2,1,2,2,7,6,11,3,3,1,1,3,1,2,1,1,1,1,1,3,1,1,8,3,4,1,5,7,2,1,4,4,8,4,2,1,2,1,1,4,5,6,3,6,2,12,3,1,3,9,2,4,3,4,1,5,3,3,1,3,7,1,5,1,1,1,1,2,
+ 3,4,5,2,3,2,6,1,1,2,1,7,1,7,3,4,5,15,2,2,1,5,3,22,19,2,1,1,1,1,2,5,1,1,1,6,1,1,12,8,2,9,18,22,4,1,1,5,1,16,1,2,7,10,15,1,1,6,2,4,1,2,4,1,6,
+ 1,1,3,2,4,1,6,4,5,1,2,1,1,2,1,10,3,1,3,2,1,9,3,2,5,7,2,19,4,3,6,1,1,1,1,1,4,3,2,1,1,1,2,5,3,1,1,1,2,2,1,1,2,1,1,2,1,3,1,1,1,3,7,1,4,1,1,2,1,
+ 1,2,1,2,4,4,3,8,1,1,1,2,1,3,5,1,3,1,3,4,6,2,2,14,4,6,6,11,9,1,15,3,1,28,5,2,5,5,3,1,3,4,5,4,6,14,3,2,3,5,21,2,7,20,10,1,2,19,2,4,28,28,2,3,
+ 2,1,14,4,1,26,28,42,12,40,3,52,79,5,14,17,3,2,2,11,3,4,6,3,1,8,2,23,4,5,8,10,4,2,7,3,5,1,1,6,3,1,2,2,2,5,28,1,1,7,7,20,5,3,29,3,17,26,1,8,4,
+ 27,3,6,11,23,5,3,4,6,13,24,16,6,5,10,25,35,7,3,2,3,3,14,3,6,2,6,1,4,2,3,8,2,1,1,3,3,3,4,1,1,13,2,2,4,5,2,1,14,14,1,2,2,1,4,5,2,3,1,14,3,12,
+ 3,17,2,16,5,1,2,1,8,9,3,19,4,2,2,4,17,25,21,20,28,75,1,10,29,103,4,1,2,1,1,4,2,4,1,2,3,24,2,2,2,1,1,2,1,3,8,1,1,1,2,1,1,3,1,1,1,6,1,5,3,1,1,
+ 1,3,4,1,1,5,2,1,5,6,13,9,16,1,1,1,1,3,2,3,2,4,5,2,5,2,2,3,7,13,7,2,2,1,1,1,1,2,3,3,2,1,6,4,9,2,1,14,2,14,2,1,18,3,4,14,4,11,41,15,23,15,23,
+ 176,1,3,4,1,1,1,1,5,3,1,2,3,7,3,1,1,2,1,2,4,4,6,2,4,1,9,7,1,10,5,8,16,29,1,1,2,2,3,1,3,5,2,4,5,4,1,1,2,2,3,3,7,1,6,10,1,17,1,44,4,6,2,1,1,6,
+ 5,4,2,10,1,6,9,2,8,1,24,1,2,13,7,8,8,2,1,4,1,3,1,3,3,5,2,5,10,9,4,9,12,2,1,6,1,10,1,1,7,7,4,10,8,3,1,13,4,3,1,6,1,3,5,2,1,2,17,16,5,2,16,6,
+ 1,4,2,1,3,3,6,8,5,11,11,1,3,3,2,4,6,10,9,5,7,4,7,4,7,1,1,4,2,1,3,6,8,7,1,6,11,5,5,3,24,9,4,2,7,13,5,1,8,82,16,61,1,1,1,4,2,2,16,10,3,8,1,1,
+ 6,4,2,1,3,1,1,1,4,3,8,4,2,2,1,1,1,1,1,6,3,5,1,1,4,6,9,2,1,1,1,2,1,7,2,1,6,1,5,4,4,3,1,8,1,3,3,1,3,2,2,2,2,3,1,6,1,2,1,2,1,3,7,1,8,2,1,2,1,5,
+ 2,5,3,5,10,1,2,1,1,3,2,5,11,3,9,3,5,1,1,5,9,1,2,1,5,7,9,9,8,1,3,3,3,6,8,2,3,2,1,1,32,6,1,2,15,9,3,7,13,1,3,10,13,2,14,1,13,10,2,1,3,10,4,15,
+ 2,15,15,10,1,3,9,6,9,32,25,26,47,7,3,2,3,1,6,3,4,3,2,8,5,4,1,9,4,2,2,19,10,6,2,3,8,1,2,2,4,2,1,9,4,4,4,6,4,8,9,2,3,1,1,1,1,3,5,5,1,3,8,4,6,
+ 2,1,4,12,1,5,3,7,13,2,5,8,1,6,1,2,5,14,6,1,5,2,4,8,15,5,1,23,6,62,2,10,1,1,8,1,2,2,10,4,2,2,9,2,1,1,3,2,3,1,5,3,3,2,1,3,8,1,1,1,11,3,1,1,4,
+ 3,7,1,14,1,2,3,12,5,2,5,1,6,7,5,7,14,11,1,3,1,8,9,12,2,1,11,8,4,4,2,6,10,9,13,1,1,3,1,5,1,3,2,4,4,1,18,2,3,14,11,4,29,4,2,7,1,3,13,9,2,2,5,
+ 3,5,20,7,16,8,5,72,34,6,4,22,12,12,28,45,36,9,7,39,9,191,1,1,1,4,11,8,4,9,2,3,22,1,1,1,1,4,17,1,7,7,1,11,31,10,2,4,8,2,3,2,1,4,2,16,4,32,2,
+ 3,19,13,4,9,1,5,2,14,8,1,1,3,6,19,6,5,1,16,6,2,10,8,5,1,2,3,1,5,5,1,11,6,6,1,3,3,2,6,3,8,1,1,4,10,7,5,7,7,5,8,9,2,1,3,4,1,1,3,1,3,3,2,6,16,
+ 1,4,6,3,1,10,6,1,3,15,2,9,2,10,25,13,9,16,6,2,2,10,11,4,3,9,1,2,6,6,5,4,30,40,1,10,7,12,14,33,6,3,6,7,3,1,3,1,11,14,4,9,5,12,11,49,18,51,31,
+ 140,31,2,2,1,5,1,8,1,10,1,4,4,3,24,1,10,1,3,6,6,16,3,4,5,2,1,4,2,57,10,6,22,2,22,3,7,22,6,10,11,36,18,16,33,36,2,5,5,1,1,1,4,10,1,4,13,2,7,
+ 5,2,9,3,4,1,7,43,3,7,3,9,14,7,9,1,11,1,1,3,7,4,18,13,1,14,1,3,6,10,73,2,2,30,6,1,11,18,19,13,22,3,46,42,37,89,7,3,16,34,2,2,3,9,1,7,1,1,1,2,
+ 2,4,10,7,3,10,3,9,5,28,9,2,6,13,7,3,1,3,10,2,7,2,11,3,6,21,54,85,2,1,4,2,2,1,39,3,21,2,2,5,1,1,1,4,1,1,3,4,15,1,3,2,4,4,2,3,8,2,20,1,8,7,13,
+ 4,1,26,6,2,9,34,4,21,52,10,4,4,1,5,12,2,11,1,7,2,30,12,44,2,30,1,1,3,6,16,9,17,39,82,2,2,24,7,1,7,3,16,9,14,44,2,1,2,1,2,3,5,2,4,1,6,7,5,3,
+ 2,6,1,11,5,11,2,1,18,19,8,1,3,24,29,2,1,3,5,2,2,1,13,6,5,1,46,11,3,5,1,1,5,8,2,10,6,12,6,3,7,11,2,4,16,13,2,5,1,1,2,2,5,2,28,5,2,23,10,8,4,
+ 4,22,39,95,38,8,14,9,5,1,13,5,4,3,13,12,11,1,9,1,27,37,2,5,4,4,63,211,95,2,2,2,1,3,5,2,1,1,2,2,1,1,1,3,2,4,1,2,1,1,5,2,2,1,1,2,3,1,3,1,1,1,
+ 3,1,4,2,1,3,6,1,1,3,7,15,5,3,2,5,3,9,11,4,2,22,1,6,3,8,7,1,4,28,4,16,3,3,25,4,4,27,27,1,4,1,2,2,7,1,3,5,2,28,8,2,14,1,8,6,16,25,3,3,3,14,3,
+ 3,1,1,2,1,4,6,3,8,4,1,1,1,2,3,6,10,6,2,3,18,3,2,5,5,4,3,1,5,2,5,4,23,7,6,12,6,4,17,11,9,5,1,1,10,5,12,1,1,11,26,33,7,3,6,1,17,7,1,5,12,1,11,
+ 2,4,1,8,14,17,23,1,2,1,7,8,16,11,9,6,5,2,6,4,16,2,8,14,1,11,8,9,1,1,1,9,25,4,11,19,7,2,15,2,12,8,52,7,5,19,2,16,4,36,8,1,16,8,24,26,4,6,2,9,
+ 5,4,36,3,28,12,25,15,37,27,17,12,59,38,5,32,127,1,2,9,17,14,4,1,2,1,1,8,11,50,4,14,2,19,16,4,17,5,4,5,26,12,45,2,23,45,104,30,12,8,3,10,2,2,
+ 3,3,1,4,20,7,2,9,6,15,2,20,1,3,16,4,11,15,6,134,2,5,59,1,2,2,2,1,9,17,3,26,137,10,211,59,1,2,4,1,4,1,1,1,2,6,2,3,1,1,2,3,2,3,1,3,4,4,2,3,3,
+ 1,4,3,1,7,2,2,3,1,2,1,3,3,3,2,2,3,2,1,3,14,6,1,3,2,9,6,15,27,9,34,145,1,1,2,1,1,1,1,2,1,1,1,1,2,2,2,3,1,2,1,1,1,2,3,5,8,3,5,2,4,1,3,2,2,2,12,
+ 4,1,1,1,10,4,5,1,20,4,16,1,15,9,5,12,2,9,2,5,4,2,26,19,7,1,26,4,30,12,15,42,1,6,8,172,1,1,4,2,1,1,11,2,2,4,2,1,2,1,10,8,1,2,1,4,5,1,2,5,1,8,
+ 4,1,3,4,2,1,6,2,1,3,4,1,2,1,1,1,1,12,5,7,2,4,3,1,1,1,3,3,6,1,2,2,3,3,3,2,1,2,12,14,11,6,6,4,12,2,8,1,7,10,1,35,7,4,13,15,4,3,23,21,28,52,5,
+ 26,5,6,1,7,10,2,7,53,3,2,1,1,1,2,163,532,1,10,11,1,3,3,4,8,2,8,6,2,2,23,22,4,2,2,4,2,1,3,1,3,3,5,9,8,2,1,2,8,1,10,2,12,21,20,15,105,2,3,1,1,
+ 3,2,3,1,1,2,5,1,4,15,11,19,1,1,1,1,5,4,5,1,1,2,5,3,5,12,1,2,5,1,11,1,1,15,9,1,4,5,3,26,8,2,1,3,1,1,15,19,2,12,1,2,5,2,7,2,19,2,20,6,26,7,5,
+ 2,2,7,34,21,13,70,2,128,1,1,2,1,1,2,1,1,3,2,2,2,15,1,4,1,3,4,42,10,6,1,49,85,8,1,2,1,1,4,4,2,3,6,1,5,7,4,3,211,4,1,2,1,2,5,1,2,4,2,2,6,5,6,
+ 10,3,4,48,100,6,2,16,296,5,27,387,2,2,3,7,16,8,5,38,15,39,21,9,10,3,7,59,13,27,21,47,5,21,6
+ };
+ static ImWchar base_ranges[] = // not zero-terminated
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
+ 0x31F0, 0x31FF, // Katakana Phonetic Extensions
+ 0xFF00, 0xFFEF, // Half-width characters
+ };
+ static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 };
+ if (!full_ranges[0])
+ {
+ memcpy(full_ranges, base_ranges, sizeof(base_ranges));
+ UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
+ }
+ return &full_ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
+{
+ // 1946 common ideograms code points for Japanese
+ // Sourced from http://theinstructionlimit.com/common-kanji-character-ranges-for-xna-spritefont-rendering
+ // FIXME: Source a list of the revised 2136 Joyo Kanji list from 2010 and rebuild this.
+ // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
+ // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.)
+ static const short accumulative_offsets_from_0x4E00[] =
+ {
+ 0,1,2,4,1,1,1,1,2,1,6,2,2,1,8,5,7,11,1,2,10,10,8,2,4,20,2,11,8,2,1,2,1,6,2,1,7,5,3,7,1,1,13,7,9,1,4,6,1,2,1,10,1,1,9,2,2,4,5,6,14,1,1,9,3,18,
+ 5,4,2,2,10,7,1,1,1,3,2,4,3,23,2,10,12,2,14,2,4,13,1,6,10,3,1,7,13,6,4,13,5,2,3,17,2,2,5,7,6,4,1,7,14,16,6,13,9,15,1,1,7,16,4,7,1,19,9,2,7,15,
+ 2,6,5,13,25,4,14,13,11,25,1,1,1,2,1,2,2,3,10,11,3,3,1,1,4,4,2,1,4,9,1,4,3,5,5,2,7,12,11,15,7,16,4,5,16,2,1,1,6,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1,
+ 2,1,12,3,3,9,5,8,1,11,1,2,3,18,20,4,1,3,6,1,7,3,5,5,7,2,2,12,3,1,4,2,3,2,3,11,8,7,4,17,1,9,25,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,6,16,1,2,1,1,3,12,
+ 20,2,5,20,8,7,6,2,1,1,1,1,6,2,1,2,10,1,1,6,1,3,1,2,1,4,1,12,4,1,3,1,1,1,1,1,10,4,7,5,13,1,15,1,1,30,11,9,1,15,38,14,1,32,17,20,1,9,31,2,21,9,
+ 4,49,22,2,1,13,1,11,45,35,43,55,12,19,83,1,3,2,3,13,2,1,7,3,18,3,13,8,1,8,18,5,3,7,25,24,9,24,40,3,17,24,2,1,6,2,3,16,15,6,7,3,12,1,9,7,3,3,
+ 3,15,21,5,16,4,5,12,11,11,3,6,3,2,31,3,2,1,1,23,6,6,1,4,2,6,5,2,1,1,3,3,22,2,6,2,3,17,3,2,4,5,1,9,5,1,1,6,15,12,3,17,2,14,2,8,1,23,16,4,2,23,
+ 8,15,23,20,12,25,19,47,11,21,65,46,4,3,1,5,6,1,2,5,26,2,1,1,3,11,1,1,1,2,1,2,3,1,1,10,2,3,1,1,1,3,6,3,2,2,6,6,9,2,2,2,6,2,5,10,2,4,1,2,1,2,2,
+ 3,1,1,3,1,2,9,23,9,2,1,1,1,1,5,3,2,1,10,9,6,1,10,2,31,25,3,7,5,40,1,15,6,17,7,27,180,1,3,2,2,1,1,1,6,3,10,7,1,3,6,17,8,6,2,2,1,3,5,5,8,16,14,
+ 15,1,1,4,1,2,1,1,1,3,2,7,5,6,2,5,10,1,4,2,9,1,1,11,6,1,44,1,3,7,9,5,1,3,1,1,10,7,1,10,4,2,7,21,15,7,2,5,1,8,3,4,1,3,1,6,1,4,2,1,4,10,8,1,4,5,
+ 1,5,10,2,7,1,10,1,1,3,4,11,10,29,4,7,3,5,2,3,33,5,2,19,3,1,4,2,6,31,11,1,3,3,3,1,8,10,9,12,11,12,8,3,14,8,6,11,1,4,41,3,1,2,7,13,1,5,6,2,6,12,
+ 12,22,5,9,4,8,9,9,34,6,24,1,1,20,9,9,3,4,1,7,2,2,2,6,2,28,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,8,8,3,2,1,5,1,2,2,3,1,11,11,7,3,6,10,8,6,16,16,
+ 22,7,12,6,21,5,4,6,6,3,6,1,3,2,1,2,8,29,1,10,1,6,13,6,6,19,31,1,13,4,4,22,17,26,33,10,4,15,12,25,6,67,10,2,3,1,6,10,2,6,2,9,1,9,4,4,1,2,16,2,
+ 5,9,2,3,8,1,8,3,9,4,8,6,4,8,11,3,2,1,1,3,26,1,7,5,1,11,1,5,3,5,2,13,6,39,5,1,5,2,11,6,10,5,1,15,5,3,6,19,21,22,2,4,1,6,1,8,1,4,8,2,4,2,2,9,2,
+ 1,1,1,4,3,6,3,12,7,1,14,2,4,10,2,13,1,17,7,3,2,1,3,2,13,7,14,12,3,1,29,2,8,9,15,14,9,14,1,3,1,6,5,9,11,3,38,43,20,7,7,8,5,15,12,19,15,81,8,7,
+ 1,5,73,13,37,28,8,8,1,15,18,20,165,28,1,6,11,8,4,14,7,15,1,3,3,6,4,1,7,14,1,1,11,30,1,5,1,4,14,1,4,2,7,52,2,6,29,3,1,9,1,21,3,5,1,26,3,11,14,
+ 11,1,17,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,7,7,5,17,3,3,3,1,23,10,4,4,6,3,1,16,17,22,3,10,21,16,16,6,4,10,2,1,1,2,8,8,6,5,3,3,3,39,25,
+ 15,1,1,16,6,7,25,15,6,6,12,1,22,13,1,4,9,5,12,2,9,1,12,28,8,3,5,10,22,60,1,2,40,4,61,63,4,1,13,12,1,4,31,12,1,14,89,5,16,6,29,14,2,5,49,18,18,
+ 5,29,33,47,1,17,1,19,12,2,9,7,39,12,3,7,12,39,3,1,46,4,12,3,8,9,5,31,15,18,3,2,2,66,19,13,17,5,3,46,124,13,57,34,2,5,4,5,8,1,1,1,4,3,1,17,5,
+ 3,5,3,1,8,5,6,3,27,3,26,7,12,7,2,17,3,7,18,78,16,4,36,1,2,1,6,2,1,39,17,7,4,13,4,4,4,1,10,4,2,4,6,3,10,1,19,1,26,2,4,33,2,73,47,7,3,8,2,4,15,
+ 18,1,29,2,41,14,1,21,16,41,7,39,25,13,44,2,2,10,1,13,7,1,7,3,5,20,4,8,2,49,1,10,6,1,6,7,10,7,11,16,3,12,20,4,10,3,1,2,11,2,28,9,2,4,7,2,15,1,
+ 27,1,28,17,4,5,10,7,3,24,10,11,6,26,3,2,7,2,2,49,16,10,16,15,4,5,27,61,30,14,38,22,2,7,5,1,3,12,23,24,17,17,3,3,2,4,1,6,2,7,5,1,1,5,1,1,9,4,
+ 1,3,6,1,8,2,8,4,14,3,5,11,4,1,3,32,1,19,4,1,13,11,5,2,1,8,6,8,1,6,5,13,3,23,11,5,3,16,3,9,10,1,24,3,198,52,4,2,2,5,14,5,4,22,5,20,4,11,6,41,
+ 1,5,2,2,11,5,2,28,35,8,22,3,18,3,10,7,5,3,4,1,5,3,8,9,3,6,2,16,22,4,5,5,3,3,18,23,2,6,23,5,27,8,1,33,2,12,43,16,5,2,3,6,1,20,4,2,9,7,1,11,2,
+ 10,3,14,31,9,3,25,18,20,2,5,5,26,14,1,11,17,12,40,19,9,6,31,83,2,7,9,19,78,12,14,21,76,12,113,79,34,4,1,1,61,18,85,10,2,2,13,31,11,50,6,33,159,
+ 179,6,6,7,4,4,2,4,2,5,8,7,20,32,22,1,3,10,6,7,28,5,10,9,2,77,19,13,2,5,1,4,4,7,4,13,3,9,31,17,3,26,2,6,6,5,4,1,7,11,3,4,2,1,6,2,20,4,1,9,2,6,
+ 3,7,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,5,13,8,4,11,23,1,10,6,2,1,3,21,2,2,4,24,31,4,10,10,2,5,192,15,4,16,7,9,51,1,2,1,1,5,1,1,2,1,3,5,3,1,3,4,1,
+ 3,1,3,3,9,8,1,2,2,2,4,4,18,12,92,2,10,4,3,14,5,25,16,42,4,14,4,2,21,5,126,30,31,2,1,5,13,3,22,5,6,6,20,12,1,14,12,87,3,19,1,8,2,9,9,3,3,23,2,
+ 3,7,6,3,1,2,3,9,1,3,1,6,3,2,1,3,11,3,1,6,10,3,2,3,1,2,1,5,1,1,11,3,6,4,1,7,2,1,2,5,5,34,4,14,18,4,19,7,5,8,2,6,79,1,5,2,14,8,2,9,2,1,36,28,16,
+ 4,1,1,1,2,12,6,42,39,16,23,7,15,15,3,2,12,7,21,64,6,9,28,8,12,3,3,41,59,24,51,55,57,294,9,9,2,6,2,15,1,2,13,38,90,9,9,9,3,11,7,1,1,1,5,6,3,2,
+ 1,2,2,3,8,1,4,4,1,5,7,1,4,3,20,4,9,1,1,1,5,5,17,1,5,2,6,2,4,1,4,5,7,3,18,11,11,32,7,5,4,7,11,127,8,4,3,3,1,10,1,1,6,21,14,1,16,1,7,1,3,6,9,65,
+ 51,4,3,13,3,10,1,1,12,9,21,110,3,19,24,1,1,10,62,4,1,29,42,78,28,20,18,82,6,3,15,6,84,58,253,15,155,264,15,21,9,14,7,58,40,39,
+ };
+ static ImWchar base_ranges[] = // not zero-terminated
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3000, 0x30FF, // Punctuations, Hiragana, Katakana
+ 0x31F0, 0x31FF, // Katakana Phonetic Extensions
+ 0xFF00, 0xFFEF, // Half-width characters
+ };
+ static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
+ if (!full_ranges[0])
+ {
+ memcpy(full_ranges, base_ranges, sizeof(base_ranges));
+ UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
+ }
+ return &full_ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement
+ 0x2DE0, 0x2DFF, // Cyrillic Extended-A
+ 0xA640, 0xA69F, // Cyrillic Extended-B
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesThai()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin
+ 0x2010, 0x205E, // Punctuations
+ 0x0E00, 0x0E7F, // Thai
+ 0,
+ };
+ return &ranges[0];
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontGlyphRangesBuilder
+//-----------------------------------------------------------------------------
+
+void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
+{
+ while (text_end ? (text < text_end) : *text)
+ {
+ unsigned int c = 0;
+ int c_len = ImTextCharFromUtf8(&c, text, text_end);
+ text += c_len;
+ if (c_len == 0)
+ break;
+ if (c < 0x10000)
+ AddChar((ImWchar)c);
+ }
+}
+
+void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges)
+{
+ for (; ranges[0]; ranges += 2)
+ for (ImWchar c = ranges[0]; c <= ranges[1]; c++)
+ AddChar(c);
+}
+
+void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
+{
+ for (int n = 0; n < 0x10000; n++)
+ if (GetBit(n))
+ {
+ out_ranges->push_back((ImWchar)n);
+ while (n < 0x10000 && GetBit(n + 1))
+ n++;
+ out_ranges->push_back((ImWchar)n);
+ }
+ out_ranges->push_back(0);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFont
+//-----------------------------------------------------------------------------
+
+ImFont::ImFont()
+{
+ Scale = 1.0f;
+ FallbackChar = (ImWchar)'?';
+ DisplayOffset = ImVec2(0.0f, 0.0f);
+ ClearOutputData();
+}
+
+ImFont::~ImFont()
+{
+ // Invalidate active font so that the user gets a clear crash instead of a dangling pointer.
+ // If you want to delete fonts you need to do it between Render() and NewFrame().
+ // FIXME-CLEANUP
+ /*
+ ImGuiContext& g = *GImGui;
+ if (g.Font == this)
+ g.Font = NULL;
+ */
+ ClearOutputData();
+}
+
+void ImFont::ClearOutputData()
+{
+ FontSize = 0.0f;
+ Glyphs.clear();
+ IndexAdvanceX.clear();
+ IndexLookup.clear();
+ FallbackGlyph = NULL;
+ FallbackAdvanceX = 0.0f;
+ ConfigDataCount = 0;
+ ConfigData = NULL;
+ ContainerAtlas = NULL;
+ Ascent = Descent = 0.0f;
+ DirtyLookupTables = true;
+ MetricsTotalSurface = 0;
+}
+
+void ImFont::BuildLookupTable()
+{
+ int max_codepoint = 0;
+ for (int i = 0; i != Glyphs.Size; i++)
+ max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint);
+
+ IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved
+ IndexAdvanceX.clear();
+ IndexLookup.clear();
+ DirtyLookupTables = false;
+ GrowIndex(max_codepoint + 1);
+ for (int i = 0; i < Glyphs.Size; i++)
+ {
+ int codepoint = (int)Glyphs[i].Codepoint;
+ IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX;
+ IndexLookup[codepoint] = (ImWchar)i;
+ }
+
+ // Create a glyph to handle TAB
+ // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?)
+ if (FindGlyph((ImWchar)' '))
+ {
+ if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times
+ Glyphs.resize(Glyphs.Size + 1);
+ ImFontGlyph& tab_glyph = Glyphs.back();
+ tab_glyph = *FindGlyph((ImWchar)' ');
+ tab_glyph.Codepoint = '\t';
+ tab_glyph.AdvanceX *= 4;
+ IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX;
+ IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size-1);
+ }
+
+ FallbackGlyph = FindGlyphNoFallback(FallbackChar);
+ FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f;
+ for (int i = 0; i < max_codepoint + 1; i++)
+ if (IndexAdvanceX[i] < 0.0f)
+ IndexAdvanceX[i] = FallbackAdvanceX;
+}
+
+void ImFont::SetFallbackChar(ImWchar c)
+{
+ FallbackChar = c;
+ BuildLookupTable();
+}
+
+void ImFont::GrowIndex(int new_size)
+{
+ IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size);
+ if (new_size <= IndexLookup.Size)
+ return;
+ IndexAdvanceX.resize(new_size, -1.0f);
+ IndexLookup.resize(new_size, (ImWchar)-1);
+}
+
+// x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero.
+// Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis).
+void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x)
+{
+ Glyphs.resize(Glyphs.Size + 1);
+ ImFontGlyph& glyph = Glyphs.back();
+ glyph.Codepoint = (ImWchar)codepoint;
+ glyph.X0 = x0;
+ glyph.Y0 = y0;
+ glyph.X1 = x1;
+ glyph.Y1 = y1;
+ glyph.U0 = u0;
+ glyph.V0 = v0;
+ glyph.U1 = u1;
+ glyph.V1 = v1;
+ glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x; // Bake spacing into AdvanceX
+
+ if (ConfigData->PixelSnapH)
+ glyph.AdvanceX = (float)(int)(glyph.AdvanceX + 0.5f);
+
+ // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round)
+ DirtyLookupTables = true;
+ MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + 1.99f);
+}
+
+void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
+{
+ IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function.
+ int index_size = IndexLookup.Size;
+
+ if (dst < index_size && IndexLookup.Data[dst] == (ImWchar)-1 && !overwrite_dst) // 'dst' already exists
+ return;
+ if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op
+ return;
+
+ GrowIndex(dst + 1);
+ IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (ImWchar)-1;
+ IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f;
+}
+
+const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
+{
+ if (c >= IndexLookup.Size)
+ return FallbackGlyph;
+ const ImWchar i = IndexLookup.Data[c];
+ if (i == (ImWchar)-1)
+ return FallbackGlyph;
+ return &Glyphs.Data[i];
+}
+
+const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const
+{
+ if (c >= IndexLookup.Size)
+ return NULL;
+ const ImWchar i = IndexLookup.Data[c];
+ if (i == (ImWchar)-1)
+ return NULL;
+ return &Glyphs.Data[i];
+}
+
+const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
+{
+ // Simple word-wrapping for English, not full-featured. Please submit failing cases!
+ // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
+
+ // For references, possible wrap point marked with ^
+ // "aaa bbb, ccc,ddd. eee fff. ggg!"
+ // ^ ^ ^ ^ ^__ ^ ^
+
+ // List of hardcoded separators: .,;!?'"
+
+ // Skip extra blanks after a line returns (that includes not counting them in width computation)
+ // e.g. "Hello world" --> "Hello" "World"
+
+ // Cut words that cannot possibly fit within one line.
+ // e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish"
+
+ float line_width = 0.0f;
+ float word_width = 0.0f;
+ float blank_width = 0.0f;
+ wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters
+
+ const char* word_end = text;
+ const char* prev_word_end = NULL;
+ bool inside_word = true;
+
+ const char* s = text;
+ while (s < text_end)
+ {
+ unsigned int c = (unsigned int)*s;
+ const char* next_s;
+ if (c < 0x80)
+ next_s = s + 1;
+ else
+ next_s = s + ImTextCharFromUtf8(&c, s, text_end);
+ if (c == 0)
+ break;
+
+ if (c < 32)
+ {
+ if (c == '\n')
+ {
+ line_width = word_width = blank_width = 0.0f;
+ inside_word = true;
+ s = next_s;
+ continue;
+ }
+ if (c == '\r')
+ {
+ s = next_s;
+ continue;
+ }
+ }
+
+ const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX);
+ if (ImCharIsBlankW(c))
+ {
+ if (inside_word)
+ {
+ line_width += blank_width;
+ blank_width = 0.0f;
+ word_end = s;
+ }
+ blank_width += char_width;
+ inside_word = false;
+ }
+ else
+ {
+ word_width += char_width;
+ if (inside_word)
+ {
+ word_end = next_s;
+ }
+ else
+ {
+ prev_word_end = word_end;
+ line_width += word_width + blank_width;
+ word_width = blank_width = 0.0f;
+ }
+
+ // Allow wrapping after punctuation.
+ inside_word = !(c == '.' || c == ',' || c == ';' || c == '!' || c == '?' || c == '\"');
+ }
+
+ // We ignore blank width at the end of the line (they can be skipped)
+ if (line_width + word_width >= wrap_width)
+ {
+ // Words that cannot possibly fit within an entire line will be cut anywhere.
+ if (word_width < wrap_width)
+ s = prev_word_end ? prev_word_end : word_end;
+ break;
+ }
+
+ s = next_s;
+ }
+
+ return s;
+}
+
+ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const
+{
+ if (!text_end)
+ text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this.
+
+ const float line_height = size;
+ const float scale = size / FontSize;
+
+ ImVec2 text_size = ImVec2(0,0);
+ float line_width = 0.0f;
+
+ const bool word_wrap_enabled = (wrap_width > 0.0f);
+ const char* word_wrap_eol = NULL;
+
+ const char* s = text_begin;
+ while (s < text_end)
+ {
+ if (word_wrap_enabled)
+ {
+ // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
+ if (!word_wrap_eol)
+ {
+ word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width);
+ if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
+ word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
+ }
+
+ if (s >= word_wrap_eol)
+ {
+ if (text_size.x < line_width)
+ text_size.x = line_width;
+ text_size.y += line_height;
+ line_width = 0.0f;
+ word_wrap_eol = NULL;
+
+ // Wrapping skips upcoming blanks
+ while (s < text_end)
+ {
+ const char c = *s;
+ if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
+ }
+ continue;
+ }
+ }
+
+ // Decode and advance source
+ const char* prev_s = s;
+ unsigned int c = (unsigned int)*s;
+ if (c < 0x80)
+ {
+ s += 1;
+ }
+ else
+ {
+ s += ImTextCharFromUtf8(&c, s, text_end);
+ if (c == 0) // Malformed UTF-8?
+ break;
+ }
+
+ if (c < 32)
+ {
+ if (c == '\n')
+ {
+ text_size.x = ImMax(text_size.x, line_width);
+ text_size.y += line_height;
+ line_width = 0.0f;
+ continue;
+ }
+ if (c == '\r')
+ continue;
+ }
+
+ const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * scale;
+ if (line_width + char_width >= max_width)
+ {
+ s = prev_s;
+ break;
+ }
+
+ line_width += char_width;
+ }
+
+ if (text_size.x < line_width)
+ text_size.x = line_width;
+
+ if (line_width > 0 || text_size.y == 0.0f)
+ text_size.y += line_height;
+
+ if (remaining)
+ *remaining = s;
+
+ return text_size;
+}
+
+void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const
+{
+ if (c == ' ' || c == '\t' || c == '\n' || c == '\r') // Match behavior of RenderText(), those 4 codepoints are hard-coded.
+ return;
+ if (const ImFontGlyph* glyph = FindGlyph(c))
+ {
+ float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
+ pos.x = (float)(int)pos.x + DisplayOffset.x;
+ pos.y = (float)(int)pos.y + DisplayOffset.y;
+ draw_list->PrimReserve(6, 4);
+ draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
+ }
+}
+
+void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
+{
+ if (!text_end)
+ text_end = text_begin + strlen(text_begin); // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls.
+
+ // Align to be pixel perfect
+ pos.x = (float)(int)pos.x + DisplayOffset.x;
+ pos.y = (float)(int)pos.y + DisplayOffset.y;
+ float x = pos.x;
+ float y = pos.y;
+ if (y > clip_rect.w)
+ return;
+
+ const float scale = size / FontSize;
+ const float line_height = FontSize * scale;
+ const bool word_wrap_enabled = (wrap_width > 0.0f);
+ const char* word_wrap_eol = NULL;
+
+ // Fast-forward to first visible line
+ const char* s = text_begin;
+ if (y + line_height < clip_rect.y && !word_wrap_enabled)
+ while (y + line_height < clip_rect.y && s < text_end)
+ {
+ s = (const char*)memchr(s, '\n', text_end - s);
+ s = s ? s + 1 : text_end;
+ y += line_height;
+ }
+
+ // For large text, scan for the last visible line in order to avoid over-reserving in the call to PrimReserve()
+ // Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer without a newline will likely crash atm)
+ if (text_end - s > 10000 && !word_wrap_enabled)
+ {
+ const char* s_end = s;
+ float y_end = y;
+ while (y_end < clip_rect.w && s_end < text_end)
+ {
+ s_end = (const char*)memchr(s_end, '\n', text_end - s_end);
+ s_end = s_end ? s_end + 1 : text_end;
+ y_end += line_height;
+ }
+ text_end = s_end;
+ }
+ if (s == text_end)
+ return;
+
+ // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)
+ const int vtx_count_max = (int)(text_end - s) * 4;
+ const int idx_count_max = (int)(text_end - s) * 6;
+ const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;
+ draw_list->PrimReserve(idx_count_max, vtx_count_max);
+
+ ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
+ ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
+ unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
+
+ while (s < text_end)
+ {
+ if (word_wrap_enabled)
+ {
+ // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
+ if (!word_wrap_eol)
+ {
+ word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x));
+ if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
+ word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
+ }
+
+ if (s >= word_wrap_eol)
+ {
+ x = pos.x;
+ y += line_height;
+ word_wrap_eol = NULL;
+
+ // Wrapping skips upcoming blanks
+ while (s < text_end)
+ {
+ const char c = *s;
+ if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
+ }
+ continue;
+ }
+ }
+
+ // Decode and advance source
+ unsigned int c = (unsigned int)*s;
+ if (c < 0x80)
+ {
+ s += 1;
+ }
+ else
+ {
+ s += ImTextCharFromUtf8(&c, s, text_end);
+ if (c == 0) // Malformed UTF-8?
+ break;
+ }
+
+ if (c < 32)
+ {
+ if (c == '\n')
+ {
+ x = pos.x;
+ y += line_height;
+ if (y > clip_rect.w)
+ break; // break out of main loop
+ continue;
+ }
+ if (c == '\r')
+ continue;
+ }
+
+ float char_width = 0.0f;
+ if (const ImFontGlyph* glyph = FindGlyph((ImWchar)c))
+ {
+ char_width = glyph->AdvanceX * scale;
+
+ // Arbitrarily assume that both space and tabs are empty glyphs as an optimization
+ if (c != ' ' && c != '\t')
+ {
+ // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w
+ float x1 = x + glyph->X0 * scale;
+ float x2 = x + glyph->X1 * scale;
+ float y1 = y + glyph->Y0 * scale;
+ float y2 = y + glyph->Y1 * scale;
+ if (x1 <= clip_rect.z && x2 >= clip_rect.x)
+ {
+ // Render a character
+ float u1 = glyph->U0;
+ float v1 = glyph->V0;
+ float u2 = glyph->U1;
+ float v2 = glyph->V1;
+
+ // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.
+ if (cpu_fine_clip)
+ {
+ if (x1 < clip_rect.x)
+ {
+ u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1);
+ x1 = clip_rect.x;
+ }
+ if (y1 < clip_rect.y)
+ {
+ v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1);
+ y1 = clip_rect.y;
+ }
+ if (x2 > clip_rect.z)
+ {
+ u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1);
+ x2 = clip_rect.z;
+ }
+ if (y2 > clip_rect.w)
+ {
+ v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1);
+ y2 = clip_rect.w;
+ }
+ if (y1 >= y2)
+ {
+ x += char_width;
+ continue;
+ }
+ }
+
+ // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:
+ {
+ idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2);
+ idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3);
+ vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1;
+ vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1;
+ vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2;
+ vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2;
+ vtx_write += 4;
+ vtx_current_idx += 4;
+ idx_write += 6;
+ }
+ }
+ }
+ }
+
+ x += char_width;
+ }
+
+ // Give back unused vertices
+ draw_list->VtxBuffer.resize((int)(vtx_write - draw_list->VtxBuffer.Data));
+ draw_list->IdxBuffer.resize((int)(idx_write - draw_list->IdxBuffer.Data));
+ draw_list->CmdBuffer[draw_list->CmdBuffer.Size-1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
+ draw_list->_VtxWritePtr = vtx_write;
+ draw_list->_IdxWritePtr = idx_write;
+ draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Internal Render Helpers
+// (progressively moved from imgui.cpp to here when they are redesigned to stop accessing ImGui global state)
+//-----------------------------------------------------------------------------
+// - RenderMouseCursor()
+// - RenderArrowPointingAt()
+// - RenderRectFilledRangeH()
+// - RenderPixelEllipsis()
+//-----------------------------------------------------------------------------
+
+void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor)
+{
+ if (mouse_cursor == ImGuiMouseCursor_None)
+ return;
+ IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
+
+ const ImU32 col_shadow = IM_COL32(0, 0, 0, 48);
+ const ImU32 col_border = IM_COL32(0, 0, 0, 255); // Black
+ const ImU32 col_fill = IM_COL32(255, 255, 255, 255); // White
+
+ ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas;
+ ImVec2 offset, size, uv[4];
+ if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
+ {
+ pos -= offset;
+ const ImTextureID tex_id = font_atlas->TexID;
+ draw_list->PushTextureID(tex_id);
+ draw_list->AddImage(tex_id, pos + ImVec2(1,0)*scale, pos + ImVec2(1,0)*scale + size*scale, uv[2], uv[3], col_shadow);
+ draw_list->AddImage(tex_id, pos + ImVec2(2,0)*scale, pos + ImVec2(2,0)*scale + size*scale, uv[2], uv[3], col_shadow);
+ draw_list->AddImage(tex_id, pos, pos + size*scale, uv[2], uv[3], col_border);
+ draw_list->AddImage(tex_id, pos, pos + size*scale, uv[0], uv[1], col_fill);
+ draw_list->PopTextureID();
+ }
+}
+
+// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.
+void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col)
+{
+ switch (direction)
+ {
+ case ImGuiDir_Left: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return;
+ case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return;
+ case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return;
+ case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return;
+ case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings
+ }
+}
+
+static inline float ImAcos01(float x)
+{
+ if (x <= 0.0f) return IM_PI * 0.5f;
+ if (x >= 1.0f) return 0.0f;
+ return ImAcos(x);
+ //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do.
+}
+
+// FIXME: Cleanup and move code to ImDrawList.
+void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding)
+{
+ if (x_end_norm == x_start_norm)
+ return;
+ if (x_start_norm > x_end_norm)
+ ImSwap(x_start_norm, x_end_norm);
+
+ ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y);
+ ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y);
+ if (rounding == 0.0f)
+ {
+ draw_list->AddRectFilled(p0, p1, col, 0.0f);
+ return;
+ }
+
+ rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding);
+ const float inv_rounding = 1.0f / rounding;
+ const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding);
+ const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding);
+ const float x0 = ImMax(p0.x, rect.Min.x + rounding);
+ if (arc0_b == arc0_e)
+ {
+ draw_list->PathLineTo(ImVec2(x0, p1.y));
+ draw_list->PathLineTo(ImVec2(x0, p0.y));
+ }
+ else if (arc0_b == 0.0f && arc0_e == IM_PI*0.5f)
+ {
+ draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL
+ draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR
+ }
+ else
+ {
+ draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL
+ draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR
+ }
+ if (p1.x > rect.Min.x + rounding)
+ {
+ const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding);
+ const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding);
+ const float x1 = ImMin(p1.x, rect.Max.x - rounding);
+ if (arc1_b == arc1_e)
+ {
+ draw_list->PathLineTo(ImVec2(x1, p0.y));
+ draw_list->PathLineTo(ImVec2(x1, p1.y));
+ }
+ else if (arc1_b == 0.0f && arc1_e == IM_PI*0.5f)
+ {
+ draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR
+ draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3); // BR
+ }
+ else
+ {
+ draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR
+ draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR
+ }
+ }
+ draw_list->PathFillConvex(col);
+}
+
+// FIXME: Rendering an ellipsis "..." is a surprisingly tricky problem for us... we cannot rely on font glyph having it,
+// and regular dot are typically too wide. If we render a dot/shape ourselves it comes with the risk that it wouldn't match
+// the boldness or positioning of what the font uses...
+void ImGui::RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, int count, ImU32 col)
+{
+ ImFont* font = draw_list->_Data->Font;
+ pos.y += (float)(int)(font->DisplayOffset.y + font->Ascent + 0.5f - 1.0f);
+ for (int dot_n = 0; dot_n < count; dot_n++)
+ draw_list->AddRectFilled(ImVec2(pos.x + dot_n * 2.0f, pos.y), ImVec2(pos.x + dot_n * 2.0f + 1.0f, pos.y + 1.0f), col);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Decompression code
+//-----------------------------------------------------------------------------
+// Compressed with stb_compress() then converted to a C array and encoded as base85.
+// Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file.
+// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
+// Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h
+//-----------------------------------------------------------------------------
+
+static unsigned int stb_decompress_length(const unsigned char *input)
+{
+ return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
+}
+
+static unsigned char *stb__barrier_out_e, *stb__barrier_out_b;
+static const unsigned char *stb__barrier_in_b;
+static unsigned char *stb__dout;
+static void stb__match(const unsigned char *data, unsigned int length)
+{
+ // INVERSE of memmove... write each byte before copying the next...
+ IM_ASSERT(stb__dout + length <= stb__barrier_out_e);
+ if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; }
+ if (data < stb__barrier_out_b) { stb__dout = stb__barrier_out_e+1; return; }
+ while (length--) *stb__dout++ = *data++;
+}
+
+static void stb__lit(const unsigned char *data, unsigned int length)
+{
+ IM_ASSERT(stb__dout + length <= stb__barrier_out_e);
+ if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; }
+ if (data < stb__barrier_in_b) { stb__dout = stb__barrier_out_e+1; return; }
+ memcpy(stb__dout, data, length);
+ stb__dout += length;
+}
+
+#define stb__in2(x) ((i[x] << 8) + i[(x)+1])
+#define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
+#define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
+
+static const unsigned char *stb_decompress_token(const unsigned char *i)
+{
+ if (*i >= 0x20) { // use fewer if's for cases that expand small
+ if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
+ else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
+ else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
+ } else { // more ifs for cases that expand large, since overhead is amortized
+ if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
+ else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
+ else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
+ else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
+ else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
+ else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
+ }
+ return i;
+}
+
+static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
+{
+ const unsigned long ADLER_MOD = 65521;
+ unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
+ unsigned long blocklen, i;
+
+ blocklen = buflen % 5552;
+ while (buflen) {
+ for (i=0; i + 7 < blocklen; i += 8) {
+ s1 += buffer[0], s2 += s1;
+ s1 += buffer[1], s2 += s1;
+ s1 += buffer[2], s2 += s1;
+ s1 += buffer[3], s2 += s1;
+ s1 += buffer[4], s2 += s1;
+ s1 += buffer[5], s2 += s1;
+ s1 += buffer[6], s2 += s1;
+ s1 += buffer[7], s2 += s1;
+
+ buffer += 8;
+ }
+
+ for (; i < blocklen; ++i)
+ s1 += *buffer++, s2 += s1;
+
+ s1 %= ADLER_MOD, s2 %= ADLER_MOD;
+ buflen -= blocklen;
+ blocklen = 5552;
+ }
+ return (unsigned int)(s2 << 16) + (unsigned int)s1;
+}
+
+static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/)
+{
+ unsigned int olen;
+ if (stb__in4(0) != 0x57bC0000) return 0;
+ if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
+ olen = stb_decompress_length(i);
+ stb__barrier_in_b = i;
+ stb__barrier_out_e = output + olen;
+ stb__barrier_out_b = output;
+ i += 16;
+
+ stb__dout = output;
+ for (;;) {
+ const unsigned char *old_i = i;
+ i = stb_decompress_token(i);
+ if (i == old_i) {
+ if (*i == 0x05 && i[1] == 0xfa) {
+ IM_ASSERT(stb__dout == output + olen);
+ if (stb__dout != output + olen) return 0;
+ if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2))
+ return 0;
+ return olen;
+ } else {
+ IM_ASSERT(0); /* NOTREACHED */
+ return 0;
+ }
+ }
+ IM_ASSERT(stb__dout <= output + olen);
+ if (stb__dout > output + olen)
+ return 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Default font data (ProggyClean.ttf)
+//-----------------------------------------------------------------------------
+// ProggyClean.ttf
+// Copyright (c) 2004, 2005 Tristan Grimmer
+// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
+// Download and more information at http://upperbounds.net
+//-----------------------------------------------------------------------------
+// File: 'ProggyClean.ttf' (41208 bytes)
+// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).
+// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
+//-----------------------------------------------------------------------------
+static const char proggy_clean_ttf_compressed_data_base85[11980+1] =
+ "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
+ "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
+ "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
+ "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
+ "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
+ "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
+ "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
+ "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
+ "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
+ "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
+ "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
+ "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
+ "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
+ "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
+ "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
+ "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
+ "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
+ "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
+ "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
+ "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
+ "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
+ "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
+ "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
+ "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
+ "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
+ "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
+ "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
+ "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
+ "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
+ "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
+ ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
+ "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
+ "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
+ "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
+ "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
+ "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
+ "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
+ ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
+ "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
+ "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
+ "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
+ "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
+ "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
+ "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
+ "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
+ "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
+ ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
+ "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
+ "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
+ ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
+ "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
+ "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
+ "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
+ ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
+ "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
+ "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
+ "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
+ "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
+ "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
+ "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
+ "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
+ "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
+ "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
+ "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
+ "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
+ "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
+ "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
+ "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
+ ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
+ "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
+ "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
+ "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
+ "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
+ "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
+ "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
+ "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
+ "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
+ ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
+ "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
+ "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
+ "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
+ "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
+ "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
+ "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
+ "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
+ "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
+
+static const char* GetDefaultCompressedFontDataTTFBase85()
+{
+ return proggy_clean_ttf_compressed_data_base85;
+}
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imgui_internal.h b/Client/ThirdParty/Box2D/extern/imgui/imgui_internal.h
new file mode 100644
index 0000000..51f3a3f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imgui_internal.h
@@ -0,0 +1,1466 @@
+// dear imgui, v1.67 WIP
+// (internal structures/api)
+
+// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
+// Set:
+// #define IMGUI_DEFINE_MATH_OPERATORS
+// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)
+
+/*
+
+Index of this file:
+// Header mess
+// Forward declarations
+// STB libraries includes
+// Context pointer
+// Generic helpers
+// Misc data structures
+// Main imgui context
+// Tab bar, tab item
+// Internal API
+
+*/
+
+#pragma once
+
+//-----------------------------------------------------------------------------
+// Header mess
+//-----------------------------------------------------------------------------
+
+#ifndef IMGUI_VERSION
+#error Must include imgui.h before imgui_internal.h
+#endif
+
+#include <stdio.h> // FILE*
+#include <stdlib.h> // NULL, malloc, free, qsort, atoi, atof
+#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
+#include <limits.h> // INT_MIN, INT_MAX
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
+#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
+#pragma clang diagnostic ignored "-Wold-style-cast"
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+
+struct ImRect; // An axis-aligned rectangle (2 points)
+struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
+struct ImDrawListSharedData; // Data shared between all ImDrawList instances
+struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
+struct ImGuiColumnData; // Storage data for a single column
+struct ImGuiColumnsSet; // Storage data for a columns set
+struct ImGuiContext; // Main imgui context
+struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
+struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
+struct ImGuiItemHoveredDataBackup; // Backup and restore IsItemHovered() internal data
+struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
+struct ImGuiNavMoveResult; // Result of a directional navigation move query result
+struct ImGuiNextWindowData; // Storage for SetNexWindow** functions
+struct ImGuiPopupRef; // Storage for current popup stack
+struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file
+struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it
+struct ImGuiTabBar; // Storage for a tab bar
+struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
+struct ImGuiWindow; // Storage for one window
+struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame)
+struct ImGuiWindowSettings; // Storage for window settings stored in .ini file (we keep one of those even if the actual window wasn't instanced during this session)
+
+// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
+typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
+typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for ButtonEx(), ButtonBehavior()
+typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
+typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
+typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
+typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: for GetNavInputAmount2d()
+typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
+typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for Separator() - internal
+typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for SliderBehavior()
+typedef int ImGuiDragFlags; // -> enum ImGuiDragFlags_ // Flags: for DragBehavior()
+
+//-------------------------------------------------------------------------
+// STB libraries includes
+//-------------------------------------------------------------------------
+
+namespace ImGuiStb
+{
+
+#undef STB_TEXTEDIT_STRING
+#undef STB_TEXTEDIT_CHARTYPE
+#define STB_TEXTEDIT_STRING ImGuiInputTextState
+#define STB_TEXTEDIT_CHARTYPE ImWchar
+#define STB_TEXTEDIT_GETWIDTH_NEWLINE -1.0f
+#include "imstb_textedit.h"
+
+} // namespace ImGuiStb
+
+//-----------------------------------------------------------------------------
+// Context pointer
+//-----------------------------------------------------------------------------
+
+#ifndef GImGui
+extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointer
+#endif
+
+//-----------------------------------------------------------------------------
+// Generic helpers
+//-----------------------------------------------------------------------------
+
+#define IM_PI 3.14159265358979323846f
+#ifdef _WIN32
+#define IM_NEWLINE "\r\n" // Play it nice with Windows users (2018/05 news: Microsoft announced that Notepad will finally display Unix-style carriage returns!)
+#else
+#define IM_NEWLINE "\n"
+#endif
+#define IMGUI_DEBUG_LOG(_FMT,...) printf("[%05d] " _FMT, GImGui->FrameCount, __VA_ARGS__)
+#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1]
+#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
+#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
+
+// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
+#ifdef _MSC_VER
+#define IMGUI_CDECL __cdecl
+#else
+#define IMGUI_CDECL
+#endif
+
+// Helpers: UTF-8 <> wchar
+IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
+IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count
+IMGUI_API int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
+IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
+IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
+IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
+
+// Helpers: Misc
+IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings
+IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size = NULL, int padding_bytes = 0);
+IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode);
+static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
+static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
+static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
+static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
+#define ImQsort qsort
+
+// Helpers: Geometry
+IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
+IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
+IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
+IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
+IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy);
+
+// Helpers: String
+IMGUI_API int ImStricmp(const char* str1, const char* str2);
+IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count);
+IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count);
+IMGUI_API char* ImStrdup(const char* str);
+IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str);
+IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c);
+IMGUI_API int ImStrlenW(const ImWchar* str);
+IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line
+IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
+IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
+IMGUI_API void ImStrTrimBlanks(char* str);
+IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3);
+IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3);
+IMGUI_API const char* ImParseFormatFindStart(const char* format);
+IMGUI_API const char* ImParseFormatFindEnd(const char* format);
+IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, int buf_size);
+IMGUI_API int ImParseFormatPrecision(const char* format, int default_value);
+
+// Helpers: ImVec2/ImVec4 operators
+// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)
+// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself.
+#ifdef IMGUI_DEFINE_MATH_OPERATORS
+static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x*rhs, lhs.y*rhs); }
+static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x/rhs, lhs.y/rhs); }
+static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x+rhs.x, lhs.y+rhs.y); }
+static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x-rhs.x, lhs.y-rhs.y); }
+static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x*rhs.x, lhs.y*rhs.y); }
+static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x/rhs.x, lhs.y/rhs.y); }
+static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
+static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
+static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
+static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
+static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w); }
+static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w); }
+static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x*rhs.x, lhs.y*rhs.y, lhs.z*rhs.z, lhs.w*rhs.w); }
+#endif
+
+// Helpers: Maths
+// - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy)
+#ifndef IMGUI_DISABLE_MATH_FUNCTIONS
+static inline float ImFabs(float x) { return fabsf(x); }
+static inline float ImSqrt(float x) { return sqrtf(x); }
+static inline float ImPow(float x, float y) { return powf(x, y); }
+static inline double ImPow(double x, double y) { return pow(x, y); }
+static inline float ImFmod(float x, float y) { return fmodf(x, y); }
+static inline double ImFmod(double x, double y) { return fmod(x, y); }
+static inline float ImCos(float x) { return cosf(x); }
+static inline float ImSin(float x) { return sinf(x); }
+static inline float ImAcos(float x) { return acosf(x); }
+static inline float ImAtan2(float y, float x) { return atan2f(y, x); }
+static inline double ImAtof(const char* s) { return atof(s); }
+static inline float ImFloorStd(float x) { return floorf(x); } // we already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by stb_truetype)
+static inline float ImCeil(float x) { return ceilf(x); }
+#endif
+// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support for variety of types: signed/unsigned int/long long float/double, using templates here but we could also redefine them 6 times
+template<typename T> static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
+template<typename T> static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
+template<typename T> static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
+template<typename T> static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); }
+template<typename T> static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
+// - Misc maths helpers
+static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); }
+static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); }
+static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); }
+static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); }
+static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
+static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); }
+static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
+static inline float ImLengthSqr(const ImVec2& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y; }
+static inline float ImLengthSqr(const ImVec4& lhs) { return lhs.x*lhs.x + lhs.y*lhs.y + lhs.z*lhs.z + lhs.w*lhs.w; }
+static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = lhs.x*lhs.x + lhs.y*lhs.y; if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
+static inline float ImFloor(float f) { return (float)(int)f; }
+static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)v.x, (float)(int)v.y); }
+static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
+static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
+static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
+static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
+
+// Helper: ImPool<>. Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer,
+// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
+typedef int ImPoolIdx;
+template<typename T>
+struct IMGUI_API ImPool
+{
+ ImVector<T> Data; // Contiguous data
+ ImGuiStorage Map; // ID->Index
+ ImPoolIdx FreeIdx; // Next free idx to use
+
+ ImPool() { FreeIdx = 0; }
+ ~ImPool() { Clear(); }
+ T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Data[idx] : NULL; }
+ T* GetByIndex(ImPoolIdx n) { return &Data[n]; }
+ ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Data.Data && p < Data.Data + Data.Size); return (ImPoolIdx)(p - Data.Data); }
+ T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Data[*p_idx]; *p_idx = FreeIdx; return Add(); }
+ void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Data[idx].~T(); } Map.Clear(); Data.clear(); FreeIdx = 0; }
+ T* Add() { int idx = FreeIdx; if (idx == Data.Size) { Data.resize(Data.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Data[idx]; } IM_PLACEMENT_NEW(&Data[idx]) T(); return &Data[idx]; }
+ void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); }
+ void Remove(ImGuiID key, ImPoolIdx idx) { Data[idx].~T(); *(int*)&Data[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); }
+ void Reserve(int capacity) { Data.reserve(capacity); Map.Data.reserve(capacity); }
+ int GetSize() const { return Data.Size; }
+};
+
+//-----------------------------------------------------------------------------
+// Misc data structures
+//-----------------------------------------------------------------------------
+
+// 1D vector (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches)
+struct ImVec1
+{
+ float x;
+ ImVec1() { x = 0.0f; }
+ ImVec1(float _x) { x = _x; }
+};
+
+enum ImGuiButtonFlags_
+{
+ ImGuiButtonFlags_None = 0,
+ ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat
+ ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // return true on click + release on same item [DEFAULT if no PressedOn* flag is set]
+ ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release)
+ ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release)
+ ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release)
+ ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping
+ ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap()
+ ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED]
+ ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions
+ ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
+ ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held
+ ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
+ ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12, // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
+ ImGuiButtonFlags_NoNavFocus = 1 << 13 // don't override navigation focus when activated
+};
+
+enum ImGuiSliderFlags_
+{
+ ImGuiSliderFlags_None = 0,
+ ImGuiSliderFlags_Vertical = 1 << 0
+};
+
+enum ImGuiDragFlags_
+{
+ ImGuiDragFlags_None = 0,
+ ImGuiDragFlags_Vertical = 1 << 0
+};
+
+enum ImGuiColumnsFlags_
+{
+ // Default: 0
+ ImGuiColumnsFlags_None = 0,
+ ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers
+ ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
+ ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
+ ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window
+ ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove.
+};
+
+enum ImGuiSelectableFlagsPrivate_
+{
+ // NB: need to be in sync with last value of ImGuiSelectableFlags_
+ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 10,
+ ImGuiSelectableFlags_PressedOnClick = 1 << 11,
+ ImGuiSelectableFlags_PressedOnRelease = 1 << 12,
+ ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 13
+};
+
+enum ImGuiSeparatorFlags_
+{
+ ImGuiSeparatorFlags_None = 0,
+ ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
+ ImGuiSeparatorFlags_Vertical = 1 << 1
+};
+
+// Storage for LastItem data
+enum ImGuiItemStatusFlags_
+{
+ ImGuiItemStatusFlags_None = 0,
+ ImGuiItemStatusFlags_HoveredRect = 1 << 0,
+ ImGuiItemStatusFlags_HasDisplayRect = 1 << 1,
+ ImGuiItemStatusFlags_Edited = 1 << 2 // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ , // [imgui-test only]
+ ImGuiItemStatusFlags_Openable = 1 << 10, //
+ ImGuiItemStatusFlags_Opened = 1 << 11, //
+ ImGuiItemStatusFlags_Checkable = 1 << 12, //
+ ImGuiItemStatusFlags_Checked = 1 << 13 //
+#endif
+};
+
+// FIXME: this is in development, not exposed/functional as a generic feature yet.
+enum ImGuiLayoutType_
+{
+ ImGuiLayoutType_Vertical = 0,
+ ImGuiLayoutType_Horizontal = 1
+};
+
+enum ImGuiAxis
+{
+ ImGuiAxis_None = -1,
+ ImGuiAxis_X = 0,
+ ImGuiAxis_Y = 1
+};
+
+enum ImGuiPlotType
+{
+ ImGuiPlotType_Lines,
+ ImGuiPlotType_Histogram
+};
+
+enum ImGuiInputSource
+{
+ ImGuiInputSource_None = 0,
+ ImGuiInputSource_Mouse,
+ ImGuiInputSource_Nav,
+ ImGuiInputSource_NavKeyboard, // Only used occasionally for storage, not tested/handled by most code
+ ImGuiInputSource_NavGamepad, // "
+ ImGuiInputSource_COUNT
+};
+
+// FIXME-NAV: Clarify/expose various repeat delay/rate
+enum ImGuiInputReadMode
+{
+ ImGuiInputReadMode_Down,
+ ImGuiInputReadMode_Pressed,
+ ImGuiInputReadMode_Released,
+ ImGuiInputReadMode_Repeat,
+ ImGuiInputReadMode_RepeatSlow,
+ ImGuiInputReadMode_RepeatFast
+};
+
+enum ImGuiNavHighlightFlags_
+{
+ ImGuiNavHighlightFlags_None = 0,
+ ImGuiNavHighlightFlags_TypeDefault = 1 << 0,
+ ImGuiNavHighlightFlags_TypeThin = 1 << 1,
+ ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2,
+ ImGuiNavHighlightFlags_NoRounding = 1 << 3
+};
+
+enum ImGuiNavDirSourceFlags_
+{
+ ImGuiNavDirSourceFlags_None = 0,
+ ImGuiNavDirSourceFlags_Keyboard = 1 << 0,
+ ImGuiNavDirSourceFlags_PadDPad = 1 << 1,
+ ImGuiNavDirSourceFlags_PadLStick = 1 << 2
+};
+
+enum ImGuiNavMoveFlags_
+{
+ ImGuiNavMoveFlags_None = 0,
+ ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side
+ ImGuiNavMoveFlags_LoopY = 1 << 1,
+ ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
+ ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful for provided for completeness
+ ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
+ ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5 // Store alternate result in NavMoveResultLocalVisibleSet that only comprise elements that are already fully visible.
+};
+
+enum ImGuiNavForward
+{
+ ImGuiNavForward_None,
+ ImGuiNavForward_ForwardQueued,
+ ImGuiNavForward_ForwardActive
+};
+
+enum ImGuiNavLayer
+{
+ ImGuiNavLayer_Main = 0, // Main scrolling layer
+ ImGuiNavLayer_Menu = 1, // Menu layer (access with Alt/ImGuiNavInput_Menu)
+ ImGuiNavLayer_COUNT
+};
+
+enum ImGuiPopupPositionPolicy
+{
+ ImGuiPopupPositionPolicy_Default,
+ ImGuiPopupPositionPolicy_ComboBox
+};
+
+// 2D axis aligned bounding-box
+// NB: we can't rely on ImVec2 math operators being available here
+struct IMGUI_API ImRect
+{
+ ImVec2 Min; // Upper-left
+ ImVec2 Max; // Lower-right
+
+ ImRect() : Min(FLT_MAX,FLT_MAX), Max(-FLT_MAX,-FLT_MAX) {}
+ ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
+ ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
+ ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
+
+ ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); }
+ ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
+ float GetWidth() const { return Max.x - Min.x; }
+ float GetHeight() const { return Max.y - Min.y; }
+ ImVec2 GetTL() const { return Min; } // Top-left
+ ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
+ ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
+ ImVec2 GetBR() const { return Max; } // Bottom-right
+ bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
+ bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; }
+ bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
+ void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; }
+ void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; }
+ void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
+ void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
+ void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; }
+ void TranslateX(float dx) { Min.x += dx; Max.x += dx; }
+ void TranslateY(float dy) { Min.y += dy; Max.y += dy; }
+ void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display.
+ void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
+ void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; }
+ bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
+};
+
+// Stacked color modifier, backup of modified data so we can restore it
+struct ImGuiColorMod
+{
+ ImGuiCol Col;
+ ImVec4 BackupValue;
+};
+
+// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
+struct ImGuiStyleMod
+{
+ ImGuiStyleVar VarIdx;
+ union { int BackupInt[2]; float BackupFloat[2]; };
+ ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; }
+ ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; }
+ ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
+};
+
+// Stacked storage data for BeginGroup()/EndGroup()
+struct ImGuiGroupData
+{
+ ImVec2 BackupCursorPos;
+ ImVec2 BackupCursorMaxPos;
+ ImVec1 BackupIndent;
+ ImVec1 BackupGroupOffset;
+ ImVec2 BackupCurrentLineSize;
+ float BackupCurrentLineTextBaseOffset;
+ float BackupLogLinePosY;
+ ImGuiID BackupActiveIdIsAlive;
+ bool BackupActiveIdPreviousFrameIsAlive;
+ bool AdvanceCursor;
+};
+
+// Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper.
+struct IMGUI_API ImGuiMenuColumns
+{
+ int Count;
+ float Spacing;
+ float Width, NextWidth;
+ float Pos[4], NextWidths[4];
+
+ ImGuiMenuColumns();
+ void Update(int count, float spacing, bool clear);
+ float DeclColumns(float w0, float w1, float w2);
+ float CalcExtraSpace(float avail_w);
+};
+
+// Internal state of the currently focused/edited text input box
+struct IMGUI_API ImGuiInputTextState
+{
+ ImGuiID ID; // widget id owning the text state
+ ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
+ ImVector<char> InitialText; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
+ ImVector<char> TempBuffer; // temporary buffer for callback and other other operations. size=capacity.
+ int CurLenA, CurLenW; // we need to maintain our buffer length in both UTF-8 and wchar format.
+ int BufCapacityA; // end-user buffer capacity
+ float ScrollX;
+ ImGuiStb::STB_TexteditState StbState;
+ float CursorAnim;
+ bool CursorFollow;
+ bool SelectedAllMouseLock;
+
+ // Temporarily set when active
+ ImGuiInputTextFlags UserFlags;
+ ImGuiInputTextCallback UserCallback;
+ void* UserCallbackData;
+
+ ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
+ void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
+ void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); }
+ bool HasSelection() const { return StbState.select_start != StbState.select_end; }
+ void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; }
+ void SelectAll() { StbState.select_start = 0; StbState.cursor = StbState.select_end = CurLenW; StbState.has_preferred_x = false; }
+ void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
+};
+
+// Windows data saved in imgui.ini file
+struct ImGuiWindowSettings
+{
+ char* Name;
+ ImGuiID ID;
+ ImVec2 Pos;
+ ImVec2 Size;
+ bool Collapsed;
+
+ ImGuiWindowSettings() { Name = NULL; ID = 0; Pos = Size = ImVec2(0,0); Collapsed = false; }
+};
+
+struct ImGuiSettingsHandler
+{
+ const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
+ ImGuiID TypeHash; // == ImHash(TypeName, 0, 0)
+ void* (*ReadOpenFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); // Read: Called when entering into a new ini entry e.g. "[Window][Name]"
+ void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry
+ void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf'
+ void* UserData;
+
+ ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); }
+};
+
+// Storage for current popup stack
+struct ImGuiPopupRef
+{
+ ImGuiID PopupId; // Set on OpenPopup()
+ ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
+ ImGuiWindow* ParentWindow; // Set on OpenPopup()
+ int OpenFrameCount; // Set on OpenPopup()
+ ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
+ ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
+ ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
+};
+
+struct ImGuiColumnData
+{
+ float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
+ float OffsetNormBeforeResize;
+ ImGuiColumnsFlags Flags; // Not exposed
+ ImRect ClipRect;
+
+ ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; Flags = 0; }
+};
+
+struct ImGuiColumnsSet
+{
+ ImGuiID ID;
+ ImGuiColumnsFlags Flags;
+ bool IsFirstFrame;
+ bool IsBeingResized;
+ int Current;
+ int Count;
+ float MinX, MaxX;
+ float LineMinY, LineMaxY;
+ float StartPosY; // Copy of CursorPos
+ float StartMaxPosX; // Copy of CursorMaxPos
+ ImVector<ImGuiColumnData> Columns;
+
+ ImGuiColumnsSet() { Clear(); }
+ void Clear()
+ {
+ ID = 0;
+ Flags = 0;
+ IsFirstFrame = false;
+ IsBeingResized = false;
+ Current = 0;
+ Count = 1;
+ MinX = MaxX = 0.0f;
+ LineMinY = LineMaxY = 0.0f;
+ StartPosY = 0.0f;
+ StartMaxPosX = 0.0f;
+ Columns.clear();
+ }
+};
+
+// Data shared between all ImDrawList instances
+struct IMGUI_API ImDrawListSharedData
+{
+ ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
+ ImFont* Font; // Current/default font (optional, for simplified AddText overload)
+ float FontSize; // Current/default font size (optional, for simplified AddText overload)
+ float CurveTessellationTol;
+ ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
+
+ // Const data
+ // FIXME: Bake rounded corners fill/borders in atlas
+ ImVec2 CircleVtx12[12];
+
+ ImDrawListSharedData();
+};
+
+struct ImDrawDataBuilder
+{
+ ImVector<ImDrawList*> Layers[2]; // Global layers for: regular, tooltip
+
+ void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); }
+ void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); }
+ IMGUI_API void FlattenIntoSingleLayer();
+};
+
+struct ImGuiNavMoveResult
+{
+ ImGuiID ID; // Best candidate
+ ImGuiWindow* Window; // Best candidate window
+ float DistBox; // Best candidate box distance to current NavId
+ float DistCenter; // Best candidate center distance to current NavId
+ float DistAxial;
+ ImRect RectRel; // Best candidate bounding box in window relative space
+
+ ImGuiNavMoveResult() { Clear(); }
+ void Clear() { ID = 0; Window = NULL; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); }
+};
+
+// Storage for SetNexWindow** functions
+struct ImGuiNextWindowData
+{
+ ImGuiCond PosCond;
+ ImGuiCond SizeCond;
+ ImGuiCond ContentSizeCond;
+ ImGuiCond CollapsedCond;
+ ImGuiCond SizeConstraintCond;
+ ImGuiCond FocusCond;
+ ImGuiCond BgAlphaCond;
+ ImVec2 PosVal;
+ ImVec2 PosPivotVal;
+ ImVec2 SizeVal;
+ ImVec2 ContentSizeVal;
+ bool CollapsedVal;
+ ImRect SizeConstraintRect;
+ ImGuiSizeCallback SizeCallback;
+ void* SizeCallbackUserData;
+ float BgAlphaVal;
+ ImVec2 MenuBarOffsetMinVal; // This is not exposed publicly, so we don't clear it.
+
+ ImGuiNextWindowData()
+ {
+ PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = 0;
+ PosVal = PosPivotVal = SizeVal = ImVec2(0.0f, 0.0f);
+ ContentSizeVal = ImVec2(0.0f, 0.0f);
+ CollapsedVal = false;
+ SizeConstraintRect = ImRect();
+ SizeCallback = NULL;
+ SizeCallbackUserData = NULL;
+ BgAlphaVal = FLT_MAX;
+ MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
+ }
+
+ void Clear()
+ {
+ PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = 0;
+ }
+};
+
+struct ImGuiTabBarSortItem
+{
+ int Index;
+ float Width;
+};
+
+//-----------------------------------------------------------------------------
+// Main imgui context
+//-----------------------------------------------------------------------------
+
+struct ImGuiContext
+{
+ bool Initialized;
+ bool FrameScopeActive; // Set by NewFrame(), cleared by EndFrame()
+ bool FrameScopePushedImplicitWindow; // Set by NewFrame(), cleared by EndFrame()
+ bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
+ ImGuiIO IO;
+ ImGuiStyle Style;
+ ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
+ float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
+ float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
+ ImDrawListSharedData DrawListSharedData;
+
+ double Time;
+ int FrameCount;
+ int FrameCountEnded;
+ int FrameCountRendered;
+ ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
+ ImVector<ImGuiWindow*> WindowsFocusOrder; // Windows, sorted in focus order, back to front
+ ImVector<ImGuiWindow*> WindowsSortBuffer;
+ ImVector<ImGuiWindow*> CurrentWindowStack;
+ ImGuiStorage WindowsById;
+ int WindowsActiveCount;
+ ImGuiWindow* CurrentWindow; // Being drawn into
+ ImGuiWindow* HoveredWindow; // Will catch mouse inputs
+ ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
+ ImGuiID HoveredId; // Hovered widget
+ bool HoveredIdAllowOverlap;
+ ImGuiID HoveredIdPreviousFrame;
+ float HoveredIdTimer; // Measure contiguous hovering time
+ float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
+ ImGuiID ActiveId; // Active widget
+ ImGuiID ActiveIdPreviousFrame;
+ ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
+ float ActiveIdTimer;
+ bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
+ bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
+ bool ActiveIdHasBeenEdited; // Was the value associated to the widget Edited over the course of the Active state.
+ bool ActiveIdPreviousFrameIsAlive;
+ bool ActiveIdPreviousFrameHasBeenEdited;
+ int ActiveIdAllowNavDirFlags; // Active widget allows using directional navigation (e.g. can activate a button and move away from it)
+ ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
+ ImGuiWindow* ActiveIdWindow;
+ ImGuiWindow* ActiveIdPreviousFrameWindow;
+ ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
+ ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
+ float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
+ ImVec2 LastValidMousePos;
+ ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
+ ImVector<ImGuiColorMod> ColorModifiers; // Stack for PushStyleColor()/PopStyleColor()
+ ImVector<ImGuiStyleMod> StyleModifiers; // Stack for PushStyleVar()/PopStyleVar()
+ ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont()
+ ImVector<ImGuiPopupRef> OpenPopupStack; // Which popups are open (persistent)
+ ImVector<ImGuiPopupRef> BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
+ ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
+ bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions
+ ImGuiCond NextTreeNodeOpenCond;
+
+ // Navigation data (for gamepad/keyboard)
+ ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow'
+ ImGuiID NavId; // Focused item for navigation
+ ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem()
+ ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0
+ ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0
+ ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0
+ ImGuiID NavJustTabbedId; // Just tabbed to this id.
+ ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest)
+ ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame
+ ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
+ ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring.
+ int NavScoringCount; // Metrics for debugging
+ ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most.
+ ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f
+ ImGuiWindow* NavWindowingList;
+ float NavWindowingTimer;
+ float NavWindowingHighlightAlpha;
+ bool NavWindowingToggleLayer;
+ ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
+ int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
+ bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid
+ bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
+ bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
+ bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
+ bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest
+ bool NavInitRequest; // Init request for appearing window to select first item
+ bool NavInitRequestFromMove;
+ ImGuiID NavInitResultId;
+ ImRect NavInitResultRectRel;
+ bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items
+ bool NavMoveRequest; // Move request for this frame
+ ImGuiNavMoveFlags NavMoveRequestFlags;
+ ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu)
+ ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request
+ ImGuiDir NavMoveClipDir;
+ ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow
+ ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
+ ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
+
+ // Render
+ ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user
+ ImDrawDataBuilder DrawDataBuilder;
+ float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
+ ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays
+ ImGuiMouseCursor MouseCursor;
+
+ // Drag and Drop
+ bool DragDropActive;
+ bool DragDropWithinSourceOrTarget;
+ ImGuiDragDropFlags DragDropSourceFlags;
+ int DragDropSourceFrameCount;
+ int DragDropMouseButton;
+ ImGuiPayload DragDropPayload;
+ ImRect DragDropTargetRect;
+ ImGuiID DragDropTargetId;
+ ImGuiDragDropFlags DragDropAcceptFlags;
+ float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface)
+ ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload)
+ ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets)
+ int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source
+ ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly
+ unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads
+
+ // Tab bars
+ ImPool<ImGuiTabBar> TabBars;
+ ImVector<ImGuiTabBar*> CurrentTabBar;
+ ImVector<ImGuiTabBarSortItem> TabSortByWidthBuffer;
+
+ // Widget state
+ ImGuiInputTextState InputTextState;
+ ImFont InputTextPasswordFont;
+ ImGuiID ScalarAsInputTextId; // Temporary text input when CTRL+clicking on a slider, etc.
+ ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
+ ImVec4 ColorPickerRef;
+ bool DragCurrentAccumDirty;
+ float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
+ float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
+ ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
+ int TooltipOverrideCount;
+ ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
+
+ // Platform support
+ ImVec2 PlatformImePos, PlatformImeLastPos; // Cursor position request & last passed to the OS Input Method Editor
+
+ // Settings
+ bool SettingsLoaded;
+ float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero
+ ImGuiTextBuffer SettingsIniData; // In memory .ini settings
+ ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
+ ImVector<ImGuiWindowSettings> SettingsWindows; // ImGuiWindow .ini settings entries (parsed from the last loaded .ini file and maintained on saving)
+
+ // Logging
+ bool LogEnabled;
+ FILE* LogFile; // If != NULL log to stdout/ file
+ ImGuiTextBuffer LogClipboard; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
+ int LogStartDepth;
+ int LogAutoExpandMaxDepth;
+
+ // Misc
+ float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds.
+ int FramerateSecPerFrameIdx;
+ float FramerateSecPerFrameAccum;
+ int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags
+ int WantCaptureKeyboardNextFrame;
+ int WantTextInputNextFrame;
+ char TempBuffer[1024*3+1]; // Temporary text buffer
+
+ ImGuiContext(ImFontAtlas* shared_font_atlas) : OverlayDrawList(NULL)
+ {
+ Initialized = false;
+ FrameScopeActive = FrameScopePushedImplicitWindow = false;
+ Font = NULL;
+ FontSize = FontBaseSize = 0.0f;
+ FontAtlasOwnedByContext = shared_font_atlas ? false : true;
+ IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
+
+ Time = 0.0f;
+ FrameCount = 0;
+ FrameCountEnded = FrameCountRendered = -1;
+ WindowsActiveCount = 0;
+ CurrentWindow = NULL;
+ HoveredWindow = NULL;
+ HoveredRootWindow = NULL;
+ HoveredId = 0;
+ HoveredIdAllowOverlap = false;
+ HoveredIdPreviousFrame = 0;
+ HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
+ ActiveId = 0;
+ ActiveIdPreviousFrame = 0;
+ ActiveIdIsAlive = 0;
+ ActiveIdTimer = 0.0f;
+ ActiveIdIsJustActivated = false;
+ ActiveIdAllowOverlap = false;
+ ActiveIdHasBeenEdited = false;
+ ActiveIdPreviousFrameIsAlive = false;
+ ActiveIdPreviousFrameHasBeenEdited = false;
+ ActiveIdAllowNavDirFlags = 0;
+ ActiveIdClickOffset = ImVec2(-1,-1);
+ ActiveIdWindow = ActiveIdPreviousFrameWindow = NULL;
+ ActiveIdSource = ImGuiInputSource_None;
+ LastActiveId = 0;
+ LastActiveIdTimer = 0.0f;
+ LastValidMousePos = ImVec2(0.0f, 0.0f);
+ MovingWindow = NULL;
+ NextTreeNodeOpenVal = false;
+ NextTreeNodeOpenCond = 0;
+
+ NavWindow = NULL;
+ NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0;
+ NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0;
+ NavInputSource = ImGuiInputSource_None;
+ NavScoringRectScreen = ImRect();
+ NavScoringCount = 0;
+ NavWindowingTarget = NavWindowingTargetAnim = NavWindowingList = NULL;
+ NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
+ NavWindowingToggleLayer = false;
+ NavLayer = ImGuiNavLayer_Main;
+ NavIdTabCounter = INT_MAX;
+ NavIdIsAlive = false;
+ NavMousePosDirty = false;
+ NavDisableHighlight = true;
+ NavDisableMouseHover = false;
+ NavAnyRequest = false;
+ NavInitRequest = false;
+ NavInitRequestFromMove = false;
+ NavInitResultId = 0;
+ NavMoveFromClampedRefRect = false;
+ NavMoveRequest = false;
+ NavMoveRequestFlags = 0;
+ NavMoveRequestForward = ImGuiNavForward_None;
+ NavMoveDir = NavMoveDirLast = NavMoveClipDir = ImGuiDir_None;
+
+ DimBgRatio = 0.0f;
+ OverlayDrawList._Data = &DrawListSharedData;
+ OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging
+ MouseCursor = ImGuiMouseCursor_Arrow;
+
+ DragDropActive = DragDropWithinSourceOrTarget = false;
+ DragDropSourceFlags = 0;
+ DragDropSourceFrameCount = -1;
+ DragDropMouseButton = -1;
+ DragDropTargetId = 0;
+ DragDropAcceptFlags = 0;
+ DragDropAcceptIdCurrRectSurface = 0.0f;
+ DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
+ DragDropAcceptFrameCount = -1;
+ memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
+
+ ScalarAsInputTextId = 0;
+ ColorEditOptions = ImGuiColorEditFlags__OptionsDefault;
+ DragCurrentAccumDirty = false;
+ DragCurrentAccum = 0.0f;
+ DragSpeedDefaultRatio = 1.0f / 100.0f;
+ ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
+ TooltipOverrideCount = 0;
+ PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX);
+
+ SettingsLoaded = false;
+ SettingsDirtyTimer = 0.0f;
+
+ LogEnabled = false;
+ LogFile = NULL;
+ LogStartDepth = 0;
+ LogAutoExpandMaxDepth = 2;
+
+ memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
+ FramerateSecPerFrameIdx = 0;
+ FramerateSecPerFrameAccum = 0.0f;
+ WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
+ memset(TempBuffer, 0, sizeof(TempBuffer));
+ }
+};
+
+// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().
+// This is going to be exposed in imgui.h when stabilized enough.
+enum ImGuiItemFlags_
+{
+ ImGuiItemFlags_NoTabStop = 1 << 0, // false
+ ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
+ ImGuiItemFlags_Disabled = 1 << 2, // false // [BETA] Disable interactions but doesn't affect visuals yet. See github.com/ocornut/imgui/issues/211
+ ImGuiItemFlags_NoNav = 1 << 3, // false
+ ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false
+ ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window
+ ImGuiItemFlags_Default_ = 0
+};
+
+// Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow.
+// FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered.
+struct IMGUI_API ImGuiWindowTempData
+{
+ ImVec2 CursorPos;
+ ImVec2 CursorPosPrevLine;
+ ImVec2 CursorStartPos; // Initial position in client area with padding
+ ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Turned into window->SizeContents at the beginning of next frame
+ ImVec2 CurrentLineSize;
+ float CurrentLineTextBaseOffset;
+ ImVec2 PrevLineSize;
+ float PrevLineTextBaseOffset;
+ float LogLinePosY;
+ int TreeDepth;
+ ImU32 TreeDepthMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31
+ ImGuiID LastItemId;
+ ImGuiItemStatusFlags LastItemStatusFlags;
+ ImRect LastItemRect; // Interaction rect
+ ImRect LastItemDisplayRect; // End-user display rect (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect)
+ ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
+ int NavLayerCurrentMask; // = (1 << NavLayerCurrent) used by ItemAdd prior to clipping.
+ int NavLayerActiveMask; // Which layer have been written to (result from previous frame)
+ int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame)
+ bool NavHideHighlightOneFrame;
+ bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f)
+ bool MenuBarAppending; // FIXME: Remove this
+ ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
+ ImVector<ImGuiWindow*> ChildWindows;
+ ImGuiStorage* StateStorage;
+ ImGuiLayoutType LayoutType;
+ ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
+
+ // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
+ ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default]
+ float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window
+ float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f]
+ ImVector<ImGuiItemFlags>ItemFlagsStack;
+ ImVector<float> ItemWidthStack;
+ ImVector<float> TextWrapPosStack;
+ ImVector<ImGuiGroupData>GroupStack;
+ short StackSizesBackup[6]; // Store size of various stacks for asserting
+
+ ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
+ ImVec1 GroupOffset;
+ ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
+ ImGuiColumnsSet* ColumnsSet; // Current columns set
+
+ ImGuiWindowTempData()
+ {
+ CursorPos = CursorPosPrevLine = CursorStartPos = CursorMaxPos = ImVec2(0.0f, 0.0f);
+ CurrentLineSize = PrevLineSize = ImVec2(0.0f, 0.0f);
+ CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f;
+ LogLinePosY = -1.0f;
+ TreeDepth = 0;
+ TreeDepthMayJumpToParentOnPop = 0x00;
+ LastItemId = 0;
+ LastItemStatusFlags = 0;
+ LastItemRect = LastItemDisplayRect = ImRect();
+ NavLayerActiveMask = NavLayerActiveMaskNext = 0x00;
+ NavLayerCurrent = ImGuiNavLayer_Main;
+ NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
+ NavHideHighlightOneFrame = false;
+ NavHasScroll = false;
+ MenuBarAppending = false;
+ MenuBarOffset = ImVec2(0.0f, 0.0f);
+ StateStorage = NULL;
+ LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical;
+ ItemWidth = 0.0f;
+ ItemFlags = ImGuiItemFlags_Default_;
+ TextWrapPos = -1.0f;
+ memset(StackSizesBackup, 0, sizeof(StackSizesBackup));
+
+ Indent = ImVec1(0.0f);
+ GroupOffset = ImVec1(0.0f);
+ ColumnsOffset = ImVec1(0.0f);
+ ColumnsSet = NULL;
+ }
+};
+
+// Storage for one window
+struct IMGUI_API ImGuiWindow
+{
+ char* Name;
+ ImGuiID ID; // == ImHash(Name)
+ ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
+ ImVec2 Pos; // Position (always rounded-up to nearest pixel)
+ ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
+ ImVec2 SizeFull; // Size when non collapsed
+ ImVec2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars.
+ ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. Include decoration, window title, border, menu, etc.
+ ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize()
+ ImVec2 WindowPadding; // Window padding at the time of begin.
+ float WindowRounding; // Window rounding at the time of begin.
+ float WindowBorderSize; // Window border size at the time of begin.
+ int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)!
+ ImGuiID MoveId; // == window->GetID("#MOVE")
+ ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window)
+ ImVec2 Scroll;
+ ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
+ ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
+ ImVec2 ScrollbarSizes; // Size taken by scrollbars on each axis
+ bool ScrollbarX, ScrollbarY;
+ bool Active; // Set to true on Begin(), unless Collapsed
+ bool WasActive;
+ bool WriteAccessed; // Set to true when any widget access the current window
+ bool Collapsed; // Set when collapsing window to become only title-bar
+ bool WantCollapseToggle;
+ bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
+ bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
+ bool Hidden; // Do not display (== (HiddenFramesForResize > 0) ||
+ bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
+ short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
+ short BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0.
+ short BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues.
+ ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
+ int AutoFitFramesX, AutoFitFramesY;
+ bool AutoFitOnlyGrows;
+ int AutoFitChildAxises;
+ ImGuiDir AutoPosLastDirection;
+ int HiddenFramesRegular; // Hide the window for N frames
+ int HiddenFramesForResize; // Hide the window for N frames while allowing items to be submitted so we can measure their size
+ ImGuiCond SetWindowPosAllowFlags; // store acceptable condition flags for SetNextWindowPos() use.
+ ImGuiCond SetWindowSizeAllowFlags; // store acceptable condition flags for SetNextWindowSize() use.
+ ImGuiCond SetWindowCollapsedAllowFlags; // store acceptable condition flags for SetNextWindowCollapsed() use.
+ ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
+ ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right.
+
+ ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
+ ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
+ ImRect ClipRect; // Current clipping rectangle. = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
+ ImRect OuterRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window.
+ ImRect InnerMainRect, InnerClipRect;
+ ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
+ int LastFrameActive; // Last frame number the window was Active.
+ float ItemWidthDefault;
+ ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items
+ ImGuiStorage StateStorage;
+ ImVector<ImGuiColumnsSet> ColumnsStorage;
+ float FontWindowScale; // User scale multiplier per-window
+ int SettingsIdx; // Index into SettingsWindow[] (indices are always valid as we only grow the array from the back)
+
+ ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer)
+ ImDrawList DrawListInst;
+ ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL.
+ ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window.
+ ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
+ ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag.
+
+ ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
+ ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
+ ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
+
+ // Navigation / Focus
+ // FIXME-NAV: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext
+ int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister()
+ int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through)
+ int FocusIdxAllRequestCurrent; // Item being requested for focus
+ int FocusIdxTabRequestCurrent; // Tab-able item being requested for focus
+ int FocusIdxAllRequestNext; // Item being requested for focus, for next update (relies on layout to be stable between the frame pressing TAB and the next frame)
+ int FocusIdxTabRequestNext; // "
+
+public:
+ ImGuiWindow(ImGuiContext* context, const char* name);
+ ~ImGuiWindow();
+
+ ImGuiID GetID(const char* str, const char* str_end = NULL);
+ ImGuiID GetID(const void* ptr);
+ ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
+ ImGuiID GetIDNoKeepAlive(const void* ptr);
+ ImGuiID GetIDFromRectangle(const ImRect& r_abs);
+
+ // We don't use g.FontSize because the window may be != g.CurrentWidow.
+ ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); }
+ float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; }
+ float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; }
+ ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
+ float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; }
+ ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
+};
+
+// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data.
+struct ImGuiItemHoveredDataBackup
+{
+ ImGuiID LastItemId;
+ ImGuiItemStatusFlags LastItemStatusFlags;
+ ImRect LastItemRect;
+ ImRect LastItemDisplayRect;
+
+ ImGuiItemHoveredDataBackup() { Backup(); }
+ void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; }
+ void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; }
+};
+
+//-----------------------------------------------------------------------------
+// Tab bar, tab item
+//-----------------------------------------------------------------------------
+
+enum ImGuiTabBarFlagsPrivate_
+{
+ ImGuiTabBarFlags_DockNode = 1 << 20, // [Docking: Unused in Master Branch] Part of a dock node
+ ImGuiTabBarFlags_DockNodeIsDockSpace = 1 << 21, // [Docking: Unused in Master Branch] Part of an explicit dockspace node node
+ ImGuiTabBarFlags_IsFocused = 1 << 22,
+ ImGuiTabBarFlags_SaveSettings = 1 << 23 // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs
+};
+
+// Storage for one active tab item (sizeof() 26~32 bytes)
+struct ImGuiTabItem
+{
+ ImGuiID ID;
+ ImGuiTabItemFlags Flags;
+ int LastFrameVisible;
+ int LastFrameSelected; // This allows us to infer an ordered list of the last activated tabs with little maintenance
+ float Offset; // Position relative to beginning of tab
+ float Width; // Width currently displayed
+ float WidthContents; // Width of actual contents, stored during BeginTabItem() call
+
+ ImGuiTabItem() { ID = Flags = 0; LastFrameVisible = LastFrameSelected = -1; Offset = Width = WidthContents = 0.0f; }
+};
+
+// Storage for a tab bar (sizeof() 92~96 bytes)
+struct ImGuiTabBar
+{
+ ImVector<ImGuiTabItem> Tabs;
+ ImGuiID ID; // Zero for tab-bars used by docking
+ ImGuiID SelectedTabId; // Selected tab
+ ImGuiID NextSelectedTabId;
+ ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview)
+ int CurrFrameVisible;
+ int PrevFrameVisible;
+ ImRect BarRect;
+ float ContentsHeight;
+ float OffsetMax; // Distance from BarRect.Min.x, locked during layout
+ float OffsetNextTab; // Distance from BarRect.Min.x, incremented with each BeginTabItem() call, not used if ImGuiTabBarFlags_Reorderable if set.
+ float ScrollingAnim;
+ float ScrollingTarget;
+ ImGuiTabBarFlags Flags;
+ ImGuiID ReorderRequestTabId;
+ int ReorderRequestDir;
+ bool WantLayout;
+ bool VisibleTabWasSubmitted;
+ short LastTabItemIdx; // For BeginTabItem()/EndTabItem()
+
+ ImGuiTabBar();
+ int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); }
+};
+
+//-----------------------------------------------------------------------------
+// Internal API
+// No guarantee of forward compatibility here.
+//-----------------------------------------------------------------------------
+
+namespace ImGui
+{
+ // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
+ // If this ever crash because g.CurrentWindow is NULL it means that either
+ // - ImGui::NewFrame() has never been called, which is illegal.
+ // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
+ inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
+ inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
+ IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
+ IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
+ IMGUI_API void FocusWindow(ImGuiWindow* window);
+ IMGUI_API void FocusPreviousWindowIgnoringOne(ImGuiWindow* ignore_window);
+ IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
+ IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
+ IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
+ IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
+ IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window);
+ IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
+ IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
+ IMGUI_API void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x);
+ IMGUI_API void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
+ IMGUI_API float GetWindowScrollMaxX(ImGuiWindow* window);
+ IMGUI_API float GetWindowScrollMaxY(ImGuiWindow* window);
+ IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window);
+
+ IMGUI_API void SetCurrentFont(ImFont* font);
+ inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
+
+ // Init
+ IMGUI_API void Initialize(ImGuiContext* context);
+ IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
+
+ // NewFrame
+ IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
+ IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
+ IMGUI_API void UpdateMouseMovingWindowNewFrame();
+ IMGUI_API void UpdateMouseMovingWindowEndFrame();
+
+ // Settings
+ IMGUI_API void MarkIniSettingsDirty();
+ IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
+ IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name);
+ IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);
+ IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
+
+ // Basic Accessors
+ inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemId; }
+ inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
+ inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
+ IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
+ IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
+ IMGUI_API void ClearActiveID();
+ IMGUI_API ImGuiID GetHoveredID();
+ IMGUI_API void SetHoveredID(ImGuiID id);
+ IMGUI_API void KeepAliveID(ImGuiID id);
+ IMGUI_API void MarkItemEdited(ImGuiID id);
+
+ // Basic Helpers for widget code
+ IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f);
+ IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f);
+ IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL);
+ IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
+ IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
+ IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested
+ IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
+ IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);
+ IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
+ IMGUI_API void PushMultiItemsWidths(int components, float width_full = 0.0f);
+ IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
+ IMGUI_API void PopItemFlag();
+
+ // Popups, Modals, Tooltips
+ IMGUI_API void OpenPopupEx(ImGuiID id);
+ IMGUI_API void ClosePopupToLevel(int remaining, bool apply_focus_to_window_under);
+ IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window);
+ IMGUI_API bool IsPopupOpen(ImGuiID id); // Test for id within current popup stack level (currently begin-ed into); this doesn't scan the whole popup stack!
+ IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
+ IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true);
+ IMGUI_API ImGuiWindow* GetFrontMostPopupModal();
+ IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
+ IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy = ImGuiPopupPositionPolicy_Default);
+
+ // Navigation
+ IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
+ IMGUI_API bool NavMoveRequestButNoResultYet();
+ IMGUI_API void NavMoveRequestCancel();
+ IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const ImRect& bb_rel, ImGuiNavMoveFlags move_flags);
+ IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
+ IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode);
+ IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
+ IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate);
+ IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
+ IMGUI_API void SetNavID(ImGuiID id, int nav_layer);
+ IMGUI_API void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel);
+
+ // Inputs
+ inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { const int key_index = GImGui->IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; }
+ inline bool IsNavInputDown(ImGuiNavInput n) { return GImGui->IO.NavInputs[n] > 0.0f; }
+ inline bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) { return GetNavInputAmount(n, mode) > 0.0f; }
+ inline bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiInputReadMode mode) { return (GetNavInputAmount(n1, mode) + GetNavInputAmount(n2, mode)) > 0.0f; }
+
+ // Drag and Drop
+ IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);
+ IMGUI_API void ClearDragDrop();
+ IMGUI_API bool IsDragDropPayloadBeingAccepted();
+
+ // New Columns API (FIXME-WIP)
+ IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
+ IMGUI_API void EndColumns(); // close columns
+ IMGUI_API void PushColumnClipRect(int column_index = -1);
+
+ // Tab Bars
+ IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
+ IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
+ IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
+ IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
+ IMGUI_API void TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir);
+ IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags);
+ IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button);
+ IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col);
+ IMGUI_API bool TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, const char* label, ImGuiID tab_id, ImGuiID close_button_id);
+
+ // Render helpers
+ // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.
+ // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally)
+ IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
+ IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
+ IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
+ IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
+ IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
+ IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
+ IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0);
+ IMGUI_API void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale = 1.0f);
+ IMGUI_API void RenderBullet(ImVec2 pos);
+ IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz);
+ IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight
+ IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
+ IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL);
+
+ // Render helpers (those functions don't access any ImGui state!)
+ IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow);
+ IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
+ IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
+ IMGUI_API void RenderPixelEllipsis(ImDrawList* draw_list, ImVec2 pos, int count, ImU32 col);
+
+ // Widgets
+ IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
+ IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius);
+ IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos);
+ IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags);
+ IMGUI_API void Scrollbar(ImGuiLayoutType direction);
+ IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
+
+ // Widgets low-level behaviors
+ IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
+ IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags);
+ IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb);
+ IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f);
+ IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
+ IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextTreeNodeOpened() data, if any. May return true when logging
+ IMGUI_API void TreePushRawID(ImGuiID id);
+
+ // Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
+ // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
+ // e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); "
+ template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, const T v_min, const T v_max, const char* format, float power, ImGuiDragFlags flags);
+ template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, const T v_min, const T v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb);
+ template<typename T, typename FLOAT_T> IMGUI_API float SliderCalcRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, float power, float linear_zero_pos);
+ template<typename T, typename SIGNED_T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
+
+ // InputText
+ IMGUI_API bool InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format);
+
+ // Color
+ IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
+ IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags);
+ IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags);
+
+ // Plot
+ IMGUI_API void PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size);
+
+ // Shade functions (write over already created vertices)
+ IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
+ IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp);
+
+} // namespace ImGui
+
+// ImFontAtlas internals
+IMGUI_API bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas);
+IMGUI_API void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas);
+IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent);
+IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* spc);
+IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
+IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
+IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
+
+// Test engine hooks (imgui-test)
+//#define IMGUI_ENABLE_TEST_ENGINE
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+extern void ImGuiTestEngineHook_PreNewFrame(ImGuiContext* ctx);
+extern void ImGuiTestEngineHook_PostNewFrame(ImGuiContext* ctx);
+extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
+extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, int flags);
+#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register status flags
+#else
+#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID, _LABEL, _FLAGS) do { } while (0)
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imgui_widgets.cpp b/Client/ThirdParty/Box2D/extern/imgui/imgui_widgets.cpp
new file mode 100644
index 0000000..d65a420
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imgui_widgets.cpp
@@ -0,0 +1,6557 @@
+// dear imgui, v1.67 WIP
+// (widgets code)
+
+/*
+
+Index of this file:
+
+// [SECTION] Forward Declarations
+// [SECTION] Widgets: Text, etc.
+// [SECTION] Widgets: Main (Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.)
+// [SECTION] Widgets: Low-level Layout helpers (Spacing, Dummy, NewLine, Separator, etc.)
+// [SECTION] Widgets: ComboBox
+// [SECTION] Data Type and Data Formatting Helpers
+// [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
+// [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
+// [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
+// [SECTION] Widgets: InputText, InputTextMultiline
+// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
+// [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
+// [SECTION] Widgets: Selectable
+// [SECTION] Widgets: ListBox
+// [SECTION] Widgets: PlotLines, PlotHistogram
+// [SECTION] Widgets: Value helpers
+// [SECTION] Widgets: MenuItem, BeginMenu, EndMenu, etc.
+// [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
+// [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+#include <ctype.h> // toupper, isprint
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#endif
+
+// Clang/GCC warnings with -Weverything
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning : format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness //
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
+#if __GNUC__ >= 8
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+#endif
+
+//-------------------------------------------------------------------------
+// Data
+//-------------------------------------------------------------------------
+
+// Those MIN/MAX values are not define because we need to point to them
+static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000);
+static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF)
+static const ImU32 IM_U32_MIN = 0;
+static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF)
+#ifdef LLONG_MIN
+static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll);
+static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll);
+#else
+static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1;
+static const ImS64 IM_S64_MAX = 9223372036854775807LL;
+#endif
+static const ImU64 IM_U64_MIN = 0;
+#ifdef ULLONG_MAX
+static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull);
+#else
+static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
+#endif
+
+//-------------------------------------------------------------------------
+// [SECTION] Forward Declarations
+//-------------------------------------------------------------------------
+
+// Data Type helpers
+static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format);
+static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2);
+static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format);
+
+// For InputTextEx()
+static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
+static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
+static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Text, etc.
+//-------------------------------------------------------------------------
+// - TextUnformatted()
+// - Text()
+// - TextV()
+// - TextColored()
+// - TextColoredV()
+// - TextDisabled()
+// - TextDisabledV()
+// - TextWrapped()
+// - TextWrappedV()
+// - LabelText()
+// - LabelTextV()
+// - BulletText()
+// - BulletTextV()
+//-------------------------------------------------------------------------
+
+void ImGui::TextUnformatted(const char* text, const char* text_end)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(text != NULL);
+ const char* text_begin = text;
+ if (text_end == NULL)
+ text_end = text + strlen(text); // FIXME-OPT
+
+ const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
+ const float wrap_pos_x = window->DC.TextWrapPos;
+ const bool wrap_enabled = wrap_pos_x >= 0.0f;
+ if (text_end - text > 2000 && !wrap_enabled)
+ {
+ // Long text!
+ // Perform manual coarse clipping to optimize for long multi-line text
+ // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
+ // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
+ // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
+ const char* line = text;
+ const float line_height = GetTextLineHeight();
+ const ImRect clip_rect = window->ClipRect;
+ ImVec2 text_size(0,0);
+
+ if (text_pos.y <= clip_rect.Max.y)
+ {
+ ImVec2 pos = text_pos;
+
+ // Lines to skip (can't skip when logging text)
+ if (!g.LogEnabled)
+ {
+ int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
+ if (lines_skippable > 0)
+ {
+ int lines_skipped = 0;
+ while (line < text_end && lines_skipped < lines_skippable)
+ {
+ const char* line_end = (const char*)memchr(line, '\n', text_end - line);
+ if (!line_end)
+ line_end = text_end;
+ line = line_end + 1;
+ lines_skipped++;
+ }
+ pos.y += lines_skipped * line_height;
+ }
+ }
+
+ // Lines to render
+ if (line < text_end)
+ {
+ ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
+ while (line < text_end)
+ {
+ if (IsClippedEx(line_rect, 0, false))
+ break;
+
+ const char* line_end = (const char*)memchr(line, '\n', text_end - line);
+ if (!line_end)
+ line_end = text_end;
+ const ImVec2 line_size = CalcTextSize(line, line_end, false);
+ text_size.x = ImMax(text_size.x, line_size.x);
+ RenderText(pos, line, line_end, false);
+ line = line_end + 1;
+ line_rect.Min.y += line_height;
+ line_rect.Max.y += line_height;
+ pos.y += line_height;
+ }
+
+ // Count remaining lines
+ int lines_skipped = 0;
+ while (line < text_end)
+ {
+ const char* line_end = (const char*)memchr(line, '\n', text_end - line);
+ if (!line_end)
+ line_end = text_end;
+ line = line_end + 1;
+ lines_skipped++;
+ }
+ pos.y += lines_skipped * line_height;
+ }
+
+ text_size.y += (pos - text_pos).y;
+ }
+
+ ImRect bb(text_pos, text_pos + text_size);
+ ItemSize(text_size);
+ ItemAdd(bb, 0);
+ }
+ else
+ {
+ const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
+ const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
+
+ // Account of baseline offset
+ ImRect bb(text_pos, text_pos + text_size);
+ ItemSize(text_size);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Render (we don't hide text after ## in this end-user function)
+ RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
+ }
+}
+
+void ImGui::Text(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextV(fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextV(const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ TextUnformatted(g.TempBuffer, text_end);
+}
+
+void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextColoredV(col, fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
+{
+ PushStyleColor(ImGuiCol_Text, col);
+ TextV(fmt, args);
+ PopStyleColor();
+}
+
+void ImGui::TextDisabled(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextDisabledV(fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextDisabledV(const char* fmt, va_list args)
+{
+ PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]);
+ TextV(fmt, args);
+ PopStyleColor();
+}
+
+void ImGui::TextWrapped(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextWrappedV(fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextWrappedV(const char* fmt, va_list args)
+{
+ bool need_backup = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
+ if (need_backup)
+ PushTextWrapPos(0.0f);
+ TextV(fmt, args);
+ if (need_backup)
+ PopTextWrapPos();
+}
+
+void ImGui::LabelText(const char* label, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ LabelTextV(label, fmt, args);
+ va_end(args);
+}
+
+// Add a label+text combo aligned to other label+value widgets
+void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
+ const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, 0))
+ return;
+
+ // Render
+ const char* value_text_begin = &g.TempBuffer[0];
+ const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
+}
+
+void ImGui::BulletText(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ BulletTextV(fmt, args);
+ va_end(args);
+}
+
+// Text with a little bullet aligned to the typical tree node.
+void ImGui::BulletTextV(const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ const char* text_begin = g.TempBuffer;
+ const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
+ const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
+ const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding
+ ItemSize(bb);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Render
+ RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
+ RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Main
+//-------------------------------------------------------------------------
+// - ButtonBehavior() [Internal]
+// - Button()
+// - SmallButton()
+// - InvisibleButton()
+// - ArrowButton()
+// - CloseButton() [Internal]
+// - CollapseButton() [Internal]
+// - Scrollbar() [Internal]
+// - Image()
+// - ImageButton()
+// - Checkbox()
+// - CheckboxFlags()
+// - RadioButton()
+// - ProgressBar()
+// - Bullet()
+//-------------------------------------------------------------------------
+
+bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ if (flags & ImGuiButtonFlags_Disabled)
+ {
+ if (out_hovered) *out_hovered = false;
+ if (out_held) *out_held = false;
+ if (g.ActiveId == id) ClearActiveID();
+ return false;
+ }
+
+ // Default behavior requires click+release on same spot
+ if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0)
+ flags |= ImGuiButtonFlags_PressedOnClickRelease;
+
+ ImGuiWindow* backup_hovered_window = g.HoveredWindow;
+ if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window)
+ g.HoveredWindow = window;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ if (id != 0 && window->DC.LastItemId != id)
+ ImGuiTestEngineHook_ItemAdd(&g, bb, id);
+#endif
+
+ bool pressed = false;
+ bool hovered = ItemHoverable(bb, id);
+
+ // Drag source doesn't report as hovered
+ if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
+ hovered = false;
+
+ // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button
+ if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
+ if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ {
+ hovered = true;
+ SetHoveredID(id);
+ if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy
+ {
+ pressed = true;
+ FocusWindow(window);
+ }
+ }
+
+ if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window)
+ g.HoveredWindow = backup_hovered_window;
+
+ // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.
+ if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
+ hovered = false;
+
+ // Mouse
+ if (hovered)
+ {
+ if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
+ {
+ // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat
+ // PressedOnClickRelease | <on release>* | <on repeat> <on repeat> .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds
+ // PressedOnClick | <on click> | <on click> <on repeat> <on repeat> ..
+ // PressedOnRelease | <on release> | <on repeat> <on repeat> .. (NOT on release)
+ // PressedOnDoubleClick | <on dclick> | <on dclick> <on repeat> <on repeat> ..
+ // FIXME-NAV: We don't honor those different behaviors.
+ if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0])
+ {
+ SetActiveID(id, window);
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ SetFocusID(id, window);
+ FocusWindow(window);
+ }
+ if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]))
+ {
+ pressed = true;
+ if (flags & ImGuiButtonFlags_NoHoldingActiveID)
+ ClearActiveID();
+ else
+ SetActiveID(id, window); // Hold on ID
+ FocusWindow(window);
+ }
+ if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0])
+ {
+ if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps <on release>
+ pressed = true;
+ ClearActiveID();
+ }
+
+ // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above).
+ // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings.
+ if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true))
+ pressed = true;
+ }
+
+ if (pressed)
+ g.NavDisableHighlight = true;
+ }
+
+ // Gamepad/Keyboard navigation
+ // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse.
+ if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId))
+ hovered = true;
+
+ if (g.NavActivateDownId == id)
+ {
+ bool nav_activated_by_code = (g.NavActivateId == id);
+ bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed);
+ if (nav_activated_by_code || nav_activated_by_inputs)
+ pressed = true;
+ if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id)
+ {
+ // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
+ g.NavActivateId = id; // This is so SetActiveId assign a Nav source
+ SetActiveID(id, window);
+ if ((nav_activated_by_code || nav_activated_by_inputs) && !(flags & ImGuiButtonFlags_NoNavFocus))
+ SetFocusID(id, window);
+ g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+ }
+ }
+
+ bool held = false;
+ if (g.ActiveId == id)
+ {
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse)
+ {
+ if (g.ActiveIdIsJustActivated)
+ g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
+ if (g.IO.MouseDown[0])
+ {
+ held = true;
+ }
+ else
+ {
+ if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease))
+ if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps <on release>
+ if (!g.DragDropActive)
+ pressed = true;
+ ClearActiveID();
+ }
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ g.NavDisableHighlight = true;
+ }
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ {
+ if (g.NavActivateDownId != id)
+ ClearActiveID();
+ }
+ }
+
+ if (out_hovered) *out_hovered = hovered;
+ if (out_held) *out_held = held;
+
+ return pressed;
+}
+
+bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ ImVec2 pos = window->DC.CursorPos;
+ if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrentLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
+ pos.y += window->DC.CurrentLineTextBaseOffset - style.FramePadding.y;
+ ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
+
+ const ImRect bb(pos, pos + size);
+ ItemSize(size, style.FramePadding.y);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat)
+ flags |= ImGuiButtonFlags_Repeat;
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
+ if (pressed)
+ MarkItemEdited(id);
+
+ // Render
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ RenderNavHighlight(bb, id);
+ RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
+ RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
+
+ // Automatically close popups
+ //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
+ // CloseCurrentPopup();
+
+ return pressed;
+}
+
+bool ImGui::Button(const char* label, const ImVec2& size_arg)
+{
+ return ButtonEx(label, size_arg, 0);
+}
+
+// Small buttons fits within text without additional vertical spacing.
+bool ImGui::SmallButton(const char* label)
+{
+ ImGuiContext& g = *GImGui;
+ float backup_padding_y = g.Style.FramePadding.y;
+ g.Style.FramePadding.y = 0.0f;
+ bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine);
+ g.Style.FramePadding.y = backup_padding_y;
+ return pressed;
+}
+
+// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.
+// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id)
+bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size.
+ IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
+
+ const ImGuiID id = window->GetID(str_id);
+ ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(size);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+
+ return pressed;
+}
+
+bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiID id = window->GetID(str_id);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ const float default_size = GetFrameHeight();
+ ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat)
+ flags |= ImGuiButtonFlags_Repeat;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
+
+ // Render
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ RenderNavHighlight(bb, id);
+ RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding);
+ RenderArrow(bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), dir);
+
+ return pressed;
+}
+
+bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
+{
+ float sz = GetFrameHeight();
+ return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), 0);
+}
+
+// Button to close a window
+bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
+ // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
+ const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius));
+ bool is_clipped = !ItemAdd(bb, id);
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+ if (is_clipped)
+ return pressed;
+
+ // Render
+ ImVec2 center = bb.GetCenter();
+ if (hovered)
+ window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), 9);
+
+ float cross_extent = (radius * 0.7071f) - 1.0f;
+ ImU32 cross_col = GetColorU32(ImGuiCol_Text);
+ center -= ImVec2(0.5f, 0.5f);
+ window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f);
+ window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f);
+
+ return pressed;
+}
+
+bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
+ ItemAdd(bb, id);
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
+
+ ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ if (hovered || held)
+ window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, col, 9);
+ RenderArrow(bb.Min + g.Style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
+
+ // Switch to moving the window after mouse is moved beyond the initial drag threshold
+ if (IsItemActive() && IsMouseDragging())
+ StartMouseMovingWindow(window);
+
+ return pressed;
+}
+
+// Vertical/Horizontal scrollbar
+// The entire piece of code below is rather confusing because:
+// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
+// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
+// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
+void ImGui::Scrollbar(ImGuiLayoutType direction)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const bool horizontal = (direction == ImGuiLayoutType_Horizontal);
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY");
+
+ // Render background
+ bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
+ float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
+ const ImRect window_rect = window->Rect();
+ const float border_size = window->WindowBorderSize;
+ ImRect bb = horizontal
+ ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size)
+ : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size);
+ if (!horizontal)
+ bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f);
+ if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f)
+ return;
+
+ int window_rounding_corners;
+ if (horizontal)
+ window_rounding_corners = ImDrawCornerFlags_BotLeft | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight);
+ else
+ window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0) | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight);
+ window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, window_rounding_corners);
+ bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f)));
+
+ // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
+ float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
+ float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y;
+ float win_size_avail_v = (horizontal ? window->SizeFull.x : window->SizeFull.y) - other_scrollbar_size_w;
+ float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y;
+
+ // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
+ // But we maintain a minimum size in pixel to allow for the user to still aim inside.
+ IM_ASSERT(ImMax(win_size_contents_v, win_size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
+ const float win_size_v = ImMax(ImMax(win_size_contents_v, win_size_avail_v), 1.0f);
+ const float grab_h_pixels = ImClamp(scrollbar_size_v * (win_size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
+ const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
+
+ // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
+ bool held = false;
+ bool hovered = false;
+ const bool previously_held = (g.ActiveId == id);
+ ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
+
+ float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v);
+ float scroll_ratio = ImSaturate(scroll_v / scroll_max);
+ float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
+ if (held && grab_h_norm < 1.0f)
+ {
+ float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y;
+ float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;
+ float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y;
+
+ // Click position in scrollbar normalized space (0.0f->1.0f)
+ const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
+ SetHoveredID(id);
+
+ bool seek_absolute = false;
+ if (!previously_held)
+ {
+ // On initial click calculate the distance between mouse and the center of the grab
+ if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm)
+ {
+ *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
+ }
+ else
+ {
+ seek_absolute = true;
+ *click_delta_to_grab_center_v = 0.0f;
+ }
+ }
+
+ // Apply scroll
+ // It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position
+ const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm));
+ scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
+ if (horizontal)
+ window->Scroll.x = scroll_v;
+ else
+ window->Scroll.y = scroll_v;
+
+ // Update values for rendering
+ scroll_ratio = ImSaturate(scroll_v / scroll_max);
+ grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
+
+ // Update distance to grab now that we have seeked and saturated
+ if (seek_absolute)
+ *click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
+ }
+
+ // Render
+ const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab);
+ ImRect grab_rect;
+ if (horizontal)
+ grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, window_rect.Max.x), bb.Max.y);
+ else
+ grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImMin(ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels, window_rect.Max.y));
+ window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
+}
+
+void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ if (border_col.w > 0.0f)
+ bb.Max += ImVec2(2, 2);
+ ItemSize(bb);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ if (border_col.w > 0.0f)
+ {
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f);
+ window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col));
+ }
+ else
+ {
+ window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));
+ }
+}
+
+// frame_padding < 0: uses FramePadding from style (default)
+// frame_padding = 0: no framing
+// frame_padding > 0: set framing size
+// The color used are the button colors.
+bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ // Default to using texture ID as ID. User can still push string/integer prefixes.
+ // We could hash the size/uv to create a unique ID but that would prevent the user from animating UV.
+ PushID((void*)(intptr_t)user_texture_id);
+ const ImGuiID id = window->GetID("#image");
+ PopID();
+
+ const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : style.FramePadding;
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
+ const ImRect image_bb(window->DC.CursorPos + padding, window->DC.CursorPos + padding + size);
+ ItemSize(bb);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+
+ // Render
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ RenderNavHighlight(bb, id);
+ RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding));
+ if (bg_col.w > 0.0f)
+ window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col));
+ window->DrawList->AddImage(user_texture_id, image_bb.Min, image_bb.Max, uv0, uv1, GetColorU32(tint_col));
+
+ return pressed;
+}
+
+bool ImGui::Checkbox(const char* label, bool* v)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2, label_size.y + style.FramePadding.y*2)); // We want a square shape to we use Y twice
+ ItemSize(check_bb, style.FramePadding.y);
+
+ ImRect total_bb = check_bb;
+ if (label_size.x > 0)
+ SameLine(0, style.ItemInnerSpacing.x);
+ const ImRect text_bb(window->DC.CursorPos + ImVec2(0,style.FramePadding.y), window->DC.CursorPos + ImVec2(0,style.FramePadding.y) + label_size);
+ if (label_size.x > 0)
+ {
+ ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);
+ total_bb = ImRect(ImMin(check_bb.Min, text_bb.Min), ImMax(check_bb.Max, text_bb.Max));
+ }
+
+ if (!ItemAdd(total_bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
+ if (pressed)
+ {
+ *v = !(*v);
+ MarkItemEdited(id);
+ }
+
+ RenderNavHighlight(total_bb, id);
+ RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
+ if (*v)
+ {
+ const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
+ const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f));
+ RenderCheckMark(check_bb.Min + ImVec2(pad,pad), GetColorU32(ImGuiCol_CheckMark), check_bb.GetWidth() - pad*2.0f);
+ }
+
+ if (g.LogEnabled)
+ LogRenderedText(&text_bb.Min, *v ? "[x]" : "[ ]");
+ if (label_size.x > 0.0f)
+ RenderText(text_bb.Min, label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
+ return pressed;
+}
+
+bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
+{
+ bool v = ((*flags & flags_value) == flags_value);
+ bool pressed = Checkbox(label, &v);
+ if (pressed)
+ {
+ if (v)
+ *flags |= flags_value;
+ else
+ *flags &= ~flags_value;
+ }
+
+ return pressed;
+}
+
+bool ImGui::RadioButton(const char* label, bool active)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ const ImRect check_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(label_size.y + style.FramePadding.y*2-1, label_size.y + style.FramePadding.y*2-1));
+ ItemSize(check_bb, style.FramePadding.y);
+
+ ImRect total_bb = check_bb;
+ if (label_size.x > 0)
+ SameLine(0, style.ItemInnerSpacing.x);
+ const ImRect text_bb(window->DC.CursorPos + ImVec2(0, style.FramePadding.y), window->DC.CursorPos + ImVec2(0, style.FramePadding.y) + label_size);
+ if (label_size.x > 0)
+ {
+ ItemSize(ImVec2(text_bb.GetWidth(), check_bb.GetHeight()), style.FramePadding.y);
+ total_bb.Add(text_bb);
+ }
+
+ if (!ItemAdd(total_bb, id))
+ return false;
+
+ ImVec2 center = check_bb.GetCenter();
+ center.x = (float)(int)center.x + 0.5f;
+ center.y = (float)(int)center.y + 0.5f;
+ const float radius = check_bb.GetHeight() * 0.5f;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
+ if (pressed)
+ MarkItemEdited(id);
+
+ RenderNavHighlight(total_bb, id);
+ window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
+ if (active)
+ {
+ const float check_sz = ImMin(check_bb.GetWidth(), check_bb.GetHeight());
+ const float pad = ImMax(1.0f, (float)(int)(check_sz / 6.0f));
+ window->DrawList->AddCircleFilled(center, radius-pad, GetColorU32(ImGuiCol_CheckMark), 16);
+ }
+
+ if (style.FrameBorderSize > 0.0f)
+ {
+ window->DrawList->AddCircle(center+ImVec2(1,1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
+ window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
+ }
+
+ if (g.LogEnabled)
+ LogRenderedText(&text_bb.Min, active ? "(x)" : "( )");
+ if (label_size.x > 0.0f)
+ RenderText(text_bb.Min, label);
+
+ return pressed;
+}
+
+bool ImGui::RadioButton(const char* label, int* v, int v_button)
+{
+ const bool pressed = RadioButton(label, *v == v_button);
+ if (pressed)
+ *v = v_button;
+ return pressed;
+}
+
+// size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size
+void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ ImVec2 pos = window->DC.CursorPos;
+ ImRect bb(pos, pos + CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y*2.0f));
+ ItemSize(bb, style.FramePadding.y);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Render
+ fraction = ImSaturate(fraction);
+ RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
+ bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
+ const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);
+ RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
+
+ // Default displaying the fraction as percentage string, but user can override it
+ char overlay_buf[32];
+ if (!overlay)
+ {
+ ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction*100+0.01f);
+ overlay = overlay_buf;
+ }
+
+ ImVec2 overlay_size = CalcTextSize(overlay, NULL);
+ if (overlay_size.x > 0.0f)
+ RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f,0.5f), &bb);
+}
+
+void ImGui::Bullet()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
+ ItemSize(bb);
+ if (!ItemAdd(bb, 0))
+ {
+ SameLine(0, style.FramePadding.x*2);
+ return;
+ }
+
+ // Render and stay on same line
+ RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
+ SameLine(0, style.FramePadding.x*2);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Low-level Layout helpers
+//-------------------------------------------------------------------------
+// - Spacing()
+// - Dummy()
+// - NewLine()
+// - AlignTextToFramePadding()
+// - Separator()
+// - VerticalSeparator() [Internal]
+// - SplitterBehavior() [Internal]
+//-------------------------------------------------------------------------
+
+void ImGui::Spacing()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ItemSize(ImVec2(0,0));
+}
+
+void ImGui::Dummy(const ImVec2& size)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(bb);
+ ItemAdd(bb, 0);
+}
+
+void ImGui::NewLine()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
+ window->DC.LayoutType = ImGuiLayoutType_Vertical;
+ if (window->DC.CurrentLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
+ ItemSize(ImVec2(0,0));
+ else
+ ItemSize(ImVec2(0.0f, g.FontSize));
+ window->DC.LayoutType = backup_layout_type;
+}
+
+void ImGui::AlignTextToFramePadding()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ window->DC.CurrentLineSize.y = ImMax(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
+ window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
+}
+
+// Horizontal/vertical separating line
+void ImGui::Separator()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ImGuiContext& g = *GImGui;
+
+ // Those flags should eventually be overridable by the user
+ ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
+ IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected
+ if (flags & ImGuiSeparatorFlags_Vertical)
+ {
+ VerticalSeparator();
+ return;
+ }
+
+ // Horizontal Separator
+ if (window->DC.ColumnsSet)
+ PopClipRect();
+
+ float x1 = window->Pos.x;
+ float x2 = window->Pos.x + window->Size.x;
+ if (!window->DC.GroupStack.empty())
+ x1 += window->DC.Indent.x;
+
+ const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));
+ ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout.
+ if (!ItemAdd(bb, 0))
+ {
+ if (window->DC.ColumnsSet)
+ PushColumnClipRect();
+ return;
+ }
+
+ window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator));
+
+ if (g.LogEnabled)
+ LogRenderedText(&bb.Min, "--------------------------------");
+
+ if (window->DC.ColumnsSet)
+ {
+ PushColumnClipRect();
+ window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y;
+ }
+}
+
+void ImGui::VerticalSeparator()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ImGuiContext& g = *GImGui;
+
+ float y1 = window->DC.CursorPos.y;
+ float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y;
+ const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + 1.0f, y2));
+ ItemSize(ImVec2(bb.GetWidth(), 0.0f));
+ if (!ItemAdd(bb, 0))
+ return;
+
+ window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
+ if (g.LogEnabled)
+ LogText(" |");
+}
+
+// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
+bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
+ window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
+ bool item_add = ItemAdd(bb, id);
+ window->DC.ItemFlags = item_flags_backup;
+ if (!item_add)
+ return false;
+
+ bool hovered, held;
+ ImRect bb_interact = bb;
+ bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
+ ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);
+ if (g.ActiveId != id)
+ SetItemAllowOverlap();
+
+ if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
+ SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW);
+
+ ImRect bb_render = bb;
+ if (held)
+ {
+ ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
+ float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
+
+ // Minimum pane size
+ float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
+ float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2);
+ if (mouse_delta < -size_1_maximum_delta)
+ mouse_delta = -size_1_maximum_delta;
+ if (mouse_delta > size_2_maximum_delta)
+ mouse_delta = size_2_maximum_delta;
+
+ // Apply resize
+ if (mouse_delta != 0.0f)
+ {
+ if (mouse_delta < 0.0f)
+ IM_ASSERT(*size1 + mouse_delta >= min_size1);
+ if (mouse_delta > 0.0f)
+ IM_ASSERT(*size2 - mouse_delta >= min_size2);
+ *size1 += mouse_delta;
+ *size2 -= mouse_delta;
+ bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
+ MarkItemEdited(id);
+ }
+ }
+
+ // Render
+ const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
+ window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, g.Style.FrameRounding);
+
+ return held;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: ComboBox
+//-------------------------------------------------------------------------
+// - BeginCombo()
+// - EndCombo()
+// - Combo()
+//-------------------------------------------------------------------------
+
+static float CalcMaxPopupHeightFromItemCount(int items_count)
+{
+ ImGuiContext& g = *GImGui;
+ if (items_count <= 0)
+ return FLT_MAX;
+ return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
+}
+
+bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
+{
+ // Always consume the SetNextWindowSizeConstraint() call in our early return paths
+ ImGuiContext& g = *GImGui;
+ ImGuiCond backup_next_window_size_constraint = g.NextWindowData.SizeConstraintCond;
+ g.NextWindowData.SizeConstraintCond = 0;
+
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
+
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+
+ const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth();
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id, &frame_bb))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
+ bool popup_open = IsPopupOpen(id);
+
+ const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
+ const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ if (!(flags & ImGuiComboFlags_NoPreview))
+ window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), frame_col, style.FrameRounding, ImDrawCornerFlags_Left);
+ if (!(flags & ImGuiComboFlags_NoArrowButton))
+ {
+ window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
+ RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down);
+ }
+ RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
+ if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
+ RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
+ if (label_size.x > 0)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ if ((pressed || g.NavActivateId == id) && !popup_open)
+ {
+ if (window->DC.NavLayerCurrent == 0)
+ window->NavLastIds[0] = id;
+ OpenPopupEx(id);
+ popup_open = true;
+ }
+
+ if (!popup_open)
+ return false;
+
+ if (backup_next_window_size_constraint)
+ {
+ g.NextWindowData.SizeConstraintCond = backup_next_window_size_constraint;
+ g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
+ }
+ else
+ {
+ if ((flags & ImGuiComboFlags_HeightMask_) == 0)
+ flags |= ImGuiComboFlags_HeightRegular;
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one
+ int popup_max_height_in_items = -1;
+ if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
+ else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
+ else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
+ SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
+ }
+
+ char name[16];
+ ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
+
+ // Peak into expected window size so we can position it
+ if (ImGuiWindow* popup_window = FindWindowByName(name))
+ if (popup_window->WasActive)
+ {
+ ImVec2 size_expected = CalcWindowExpectedSize(popup_window);
+ if (flags & ImGuiComboFlags_PopupAlignLeft)
+ popup_window->AutoPosLastDirection = ImGuiDir_Left;
+ ImRect r_outer = GetWindowAllowedExtentRect(popup_window);
+ ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
+ SetNextWindowPos(pos);
+ }
+
+ // Horizontally align ourselves with the framed text
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
+ PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y));
+ bool ret = Begin(name, NULL, window_flags);
+ PopStyleVar();
+ if (!ret)
+ {
+ EndPopup();
+ IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
+ return false;
+ }
+ return true;
+}
+
+void ImGui::EndCombo()
+{
+ EndPopup();
+}
+
+// Getter for the old Combo() API: const char*[]
+static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
+{
+ const char* const* items = (const char* const*)data;
+ if (out_text)
+ *out_text = items[idx];
+ return true;
+}
+
+// Getter for the old Combo() API: "item1\0item2\0item3\0"
+static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
+{
+ // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
+ const char* items_separated_by_zeros = (const char*)data;
+ int items_count = 0;
+ const char* p = items_separated_by_zeros;
+ while (*p)
+ {
+ if (idx == items_count)
+ break;
+ p += strlen(p) + 1;
+ items_count++;
+ }
+ if (!*p)
+ return false;
+ if (out_text)
+ *out_text = p;
+ return true;
+}
+
+// Old API, prefer using BeginCombo() nowadays if you can.
+bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Call the getter to obtain the preview string which is a parameter to BeginCombo()
+ const char* preview_value = NULL;
+ if (*current_item >= 0 && *current_item < items_count)
+ items_getter(data, *current_item, &preview_value);
+
+ // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
+ if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond)
+ SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
+
+ if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
+ return false;
+
+ // Display items
+ // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
+ bool value_changed = false;
+ for (int i = 0; i < items_count; i++)
+ {
+ PushID((void*)(intptr_t)i);
+ const bool item_selected = (i == *current_item);
+ const char* item_text;
+ if (!items_getter(data, i, &item_text))
+ item_text = "*Unknown item*";
+ if (Selectable(item_text, item_selected))
+ {
+ value_changed = true;
+ *current_item = i;
+ }
+ if (item_selected)
+ SetItemDefaultFocus();
+ PopID();
+ }
+
+ EndCombo();
+ return value_changed;
+}
+
+// Combo box helper allowing to pass an array of strings.
+bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
+{
+ const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);
+ return value_changed;
+}
+
+// Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0"
+bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
+{
+ int items_count = 0;
+ const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open
+ while (*p)
+ {
+ p += strlen(p) + 1;
+ items_count++;
+ }
+ bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Data Type and Data Formatting Helpers [Internal]
+//-------------------------------------------------------------------------
+// - PatchFormatStringFloatToInt()
+// - DataTypeFormatString()
+// - DataTypeApplyOp()
+// - DataTypeApplyOpFromText()
+// - GetMinimumStepAtDecimalPrecision
+// - RoundScalarWithFormat<>()
+//-------------------------------------------------------------------------
+
+struct ImGuiDataTypeInfo
+{
+ size_t Size;
+ const char* PrintFmt; // Unused
+ const char* ScanFmt;
+};
+
+static const ImGuiDataTypeInfo GDataTypeInfo[] =
+{
+ { sizeof(int), "%d", "%d" },
+ { sizeof(unsigned int), "%u", "%u" },
+#ifdef _MSC_VER
+ { sizeof(ImS64), "%I64d","%I64d" },
+ { sizeof(ImU64), "%I64u","%I64u" },
+#else
+ { sizeof(ImS64), "%lld", "%lld" },
+ { sizeof(ImU64), "%llu", "%llu" },
+#endif
+ { sizeof(float), "%f", "%f" }, // float are promoted to double in va_arg
+ { sizeof(double), "%f", "%lf" },
+};
+IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
+
+// FIXME-LEGACY: Prior to 1.61 our DragInt() function internally used floats and because of this the compile-time default value for format was "%.0f".
+// Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls.
+// To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?!
+static const char* PatchFormatStringFloatToInt(const char* fmt)
+{
+ if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0) // Fast legacy path for "%.0f" which is expected to be the most common case.
+ return "%d";
+ const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%)
+ const char* fmt_end = ImParseFormatFindEnd(fmt_start); // Find end of format specifier, which itself is an exercise of confidence/recklessness (because snprintf is dependent on libc or user).
+ if (fmt_end > fmt_start && fmt_end[-1] == 'f')
+ {
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ if (fmt_start == fmt && fmt_end[0] == 0)
+ return "%d";
+ ImGuiContext& g = *GImGui;
+ ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end); // Honor leading and trailing decorations, but lose alignment/precision.
+ return g.TempBuffer;
+#else
+ IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d"
+#endif
+ }
+ return fmt;
+}
+
+static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format)
+{
+ if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) // Signedness doesn't matter when pushing the argument
+ return ImFormatString(buf, buf_size, format, *(const ImU32*)data_ptr);
+ if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) // Signedness doesn't matter when pushing the argument
+ return ImFormatString(buf, buf_size, format, *(const ImU64*)data_ptr);
+ if (data_type == ImGuiDataType_Float)
+ return ImFormatString(buf, buf_size, format, *(const float*)data_ptr);
+ if (data_type == ImGuiDataType_Double)
+ return ImFormatString(buf, buf_size, format, *(const double*)data_ptr);
+ IM_ASSERT(0);
+ return 0;
+}
+
+// FIXME: Adding support for clamping on boundaries of the data type would be nice.
+static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2)
+{
+ IM_ASSERT(op == '+' || op == '-');
+ switch (data_type)
+ {
+ case ImGuiDataType_S32:
+ if (op == '+') *(int*)output = *(const int*)arg1 + *(const int*)arg2;
+ else if (op == '-') *(int*)output = *(const int*)arg1 - *(const int*)arg2;
+ return;
+ case ImGuiDataType_U32:
+ if (op == '+') *(unsigned int*)output = *(const unsigned int*)arg1 + *(const ImU32*)arg2;
+ else if (op == '-') *(unsigned int*)output = *(const unsigned int*)arg1 - *(const ImU32*)arg2;
+ return;
+ case ImGuiDataType_S64:
+ if (op == '+') *(ImS64*)output = *(const ImS64*)arg1 + *(const ImS64*)arg2;
+ else if (op == '-') *(ImS64*)output = *(const ImS64*)arg1 - *(const ImS64*)arg2;
+ return;
+ case ImGuiDataType_U64:
+ if (op == '+') *(ImU64*)output = *(const ImU64*)arg1 + *(const ImU64*)arg2;
+ else if (op == '-') *(ImU64*)output = *(const ImU64*)arg1 - *(const ImU64*)arg2;
+ return;
+ case ImGuiDataType_Float:
+ if (op == '+') *(float*)output = *(const float*)arg1 + *(const float*)arg2;
+ else if (op == '-') *(float*)output = *(const float*)arg1 - *(const float*)arg2;
+ return;
+ case ImGuiDataType_Double:
+ if (op == '+') *(double*)output = *(const double*)arg1 + *(const double*)arg2;
+ else if (op == '-') *(double*)output = *(const double*)arg1 - *(const double*)arg2;
+ return;
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+}
+
+// User can input math operators (e.g. +100) to edit a numerical values.
+// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
+static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* format)
+{
+ while (ImCharIsBlankA(*buf))
+ buf++;
+
+ // We don't support '-' op because it would conflict with inputing negative value.
+ // Instead you can use +-100 to subtract from an existing value
+ char op = buf[0];
+ if (op == '+' || op == '*' || op == '/')
+ {
+ buf++;
+ while (ImCharIsBlankA(*buf))
+ buf++;
+ }
+ else
+ {
+ op = 0;
+ }
+ if (!buf[0])
+ return false;
+
+ // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
+ IM_ASSERT(data_type < ImGuiDataType_COUNT);
+ int data_backup[2];
+ IM_ASSERT(GDataTypeInfo[data_type].Size <= sizeof(data_backup));
+ memcpy(data_backup, data_ptr, GDataTypeInfo[data_type].Size);
+
+ if (format == NULL)
+ format = GDataTypeInfo[data_type].ScanFmt;
+
+ int arg1i = 0;
+ if (data_type == ImGuiDataType_S32)
+ {
+ int* v = (int*)data_ptr;
+ int arg0i = *v;
+ float arg1f = 0.0f;
+ if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
+ return false;
+ // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
+ if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract)
+ else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply
+ else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide
+ else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant
+ }
+ else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
+ {
+ // Assign constant
+ // FIXME: We don't bother handling support for legacy operators since they are a little too crappy. Instead we may implement a proper expression evaluator in the future.
+ sscanf(buf, format, data_ptr);
+ }
+ else if (data_type == ImGuiDataType_Float)
+ {
+ // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
+ format = "%f";
+ float* v = (float*)data_ptr;
+ float arg0f = *v, arg1f = 0.0f;
+ if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
+ return false;
+ if (sscanf(buf, format, &arg1f) < 1)
+ return false;
+ if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
+ else if (op == '*') { *v = arg0f * arg1f; } // Multiply
+ else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
+ else { *v = arg1f; } // Assign constant
+ }
+ else if (data_type == ImGuiDataType_Double)
+ {
+ format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
+ double* v = (double*)data_ptr;
+ double arg0f = *v, arg1f = 0.0;
+ if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
+ return false;
+ if (sscanf(buf, format, &arg1f) < 1)
+ return false;
+ if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
+ else if (op == '*') { *v = arg0f * arg1f; } // Multiply
+ else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
+ else { *v = arg1f; } // Assign constant
+ }
+ return memcmp(data_backup, data_ptr, GDataTypeInfo[data_type].Size) != 0;
+}
+
+static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
+{
+ static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
+ if (decimal_precision < 0)
+ return FLT_MIN;
+ return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
+}
+
+template<typename TYPE>
+static const char* ImAtoi(const char* src, TYPE* output)
+{
+ int negative = 0;
+ if (*src == '-') { negative = 1; src++; }
+ if (*src == '+') { src++; }
+ TYPE v = 0;
+ while (*src >= '0' && *src <= '9')
+ v = (v * 10) + (*src++ - '0');
+ *output = negative ? -v : v;
+ return src;
+}
+
+template<typename TYPE, typename SIGNEDTYPE>
+TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v)
+{
+ const char* fmt_start = ImParseFormatFindStart(format);
+ if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string
+ return v;
+ char v_str[64];
+ ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
+ const char* p = v_str;
+ while (*p == ' ')
+ p++;
+ if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
+ v = (TYPE)ImAtof(p);
+ else
+ ImAtoi(p, (SIGNEDTYPE*)&v);
+ return v;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
+//-------------------------------------------------------------------------
+// - DragBehaviorT<>() [Internal]
+// - DragBehavior() [Internal]
+// - DragScalar()
+// - DragScalarN()
+// - DragFloat()
+// - DragFloat2()
+// - DragFloat3()
+// - DragFloat4()
+// - DragFloatRange2()
+// - DragInt()
+// - DragInt2()
+// - DragInt3()
+// - DragInt4()
+// - DragIntRange2()
+//-------------------------------------------------------------------------
+
+// This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls)
+template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
+bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiDragFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiAxis axis = (flags & ImGuiDragFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
+ const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
+ const bool has_min_max = (v_min != v_max);
+
+ // Default tweak speed
+ if (v_speed == 0.0f && has_min_max && (v_max - v_min < FLT_MAX))
+ v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio);
+
+ // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
+ float adjust_delta = 0.0f;
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && g.IO.MouseDragMaxDistanceSqr[0] > 1.0f*1.0f)
+ {
+ adjust_delta = g.IO.MouseDelta[axis];
+ if (g.IO.KeyAlt)
+ adjust_delta *= 1.0f / 100.0f;
+ if (g.IO.KeyShift)
+ adjust_delta *= 10.0f;
+ }
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ {
+ int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
+ adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis];
+ v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
+ }
+ adjust_delta *= v_speed;
+
+ // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter.
+ if (axis == ImGuiAxis_Y)
+ adjust_delta = -adjust_delta;
+
+ // Clear current value on activation
+ // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300.
+ bool is_just_activated = g.ActiveIdIsJustActivated;
+ bool is_already_past_limits_and_pushing_outward = has_min_max && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
+ if (is_just_activated || is_already_past_limits_and_pushing_outward)
+ {
+ g.DragCurrentAccum = 0.0f;
+ g.DragCurrentAccumDirty = false;
+ }
+ else if (adjust_delta != 0.0f)
+ {
+ g.DragCurrentAccum += adjust_delta;
+ g.DragCurrentAccumDirty = true;
+ }
+
+ if (!g.DragCurrentAccumDirty)
+ return false;
+
+ TYPE v_cur = *v;
+ FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f;
+
+ const bool is_power = (power != 1.0f && is_decimal && has_min_max && (v_max - v_min < FLT_MAX));
+ if (is_power)
+ {
+ // Offset + round to user desired precision, with a curve on the v_min..v_max range to get more precision on one side of the range
+ FLOATTYPE v_old_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
+ FLOATTYPE v_new_norm_curved = v_old_norm_curved + (g.DragCurrentAccum / (v_max - v_min));
+ v_cur = v_min + (TYPE)ImPow(ImSaturate((float)v_new_norm_curved), power) * (v_max - v_min);
+ v_old_ref_for_accum_remainder = v_old_norm_curved;
+ }
+ else
+ {
+ v_cur += (TYPE)g.DragCurrentAccum;
+ }
+
+ // Round to user desired precision based on format string
+ v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_cur);
+
+ // Preserve remainder after rounding has been applied. This also allow slow tweaking of values.
+ g.DragCurrentAccumDirty = false;
+ if (is_power)
+ {
+ FLOATTYPE v_cur_norm_curved = ImPow((FLOATTYPE)(v_cur - v_min) / (FLOATTYPE)(v_max - v_min), (FLOATTYPE)1.0f / power);
+ g.DragCurrentAccum -= (float)(v_cur_norm_curved - v_old_ref_for_accum_remainder);
+ }
+ else
+ {
+ g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v);
+ }
+
+ // Lose zero sign for float/double
+ if (v_cur == (TYPE)-0)
+ v_cur = (TYPE)0;
+
+ // Clamp values (+ handle overflow/wrap-around for integer types)
+ if (*v != v_cur && has_min_max)
+ {
+ if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
+ v_cur = v_min;
+ if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal))
+ v_cur = v_max;
+ }
+
+ // Apply result
+ if (*v == v_cur)
+ return false;
+ *v = v_cur;
+ return true;
+}
+
+bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power, ImGuiDragFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId == id)
+ {
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
+ ClearActiveID();
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
+ ClearActiveID();
+ }
+ if (g.ActiveId != id)
+ return false;
+
+ switch (data_type)
+ {
+ case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)v, v_speed, v_min ? *(const ImS32* )v_min : IM_S32_MIN, v_max ? *(const ImS32* )v_max : IM_S32_MAX, format, power, flags);
+ case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)v, v_speed, v_min ? *(const ImU32* )v_min : IM_U32_MIN, v_max ? *(const ImU32* )v_max : IM_U32_MAX, format, power, flags);
+ case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)v, v_speed, v_min ? *(const ImS64* )v_min : IM_S64_MIN, v_max ? *(const ImS64* )v_max : IM_S64_MAX, format, power, flags);
+ case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)v, v_speed, v_min ? *(const ImU64* )v_min : IM_U64_MIN, v_max ? *(const ImU64* )v_max : IM_U64_MAX, format, power, flags);
+ case ImGuiDataType_Float: return DragBehaviorT<float, float, float >(data_type, (float*)v, v_speed, v_min ? *(const float* )v_min : -FLT_MAX, v_max ? *(const float* )v_max : FLT_MAX, format, power, flags);
+ case ImGuiDataType_Double: return DragBehaviorT<double,double,double>(data_type, (double*)v, v_speed, v_min ? *(const double*)v_min : -DBL_MAX, v_max ? *(const double*)v_max : DBL_MAX, format, power, flags);
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+ return false;
+}
+
+bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, float v_speed, const void* v_min, const void* v_max, const char* format, float power)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ if (power != 1.0f)
+ IM_ASSERT(v_min != NULL && v_max != NULL); // When using a power curve the drag needs to have known bounds
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
+ const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ // NB- we don't call ItemSize() yet because we may turn into a text edit box below
+ if (!ItemAdd(total_bb, id, &frame_bb))
+ {
+ ItemSize(total_bb, style.FramePadding.y);
+ return false;
+ }
+ const bool hovered = ItemHoverable(frame_bb, id);
+
+ // Default format string when passing NULL
+ // Patch old "%.0f" format string to use "%d", read function comments for more details.
+ IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
+ if (format == NULL)
+ format = GDataTypeInfo[data_type].PrintFmt;
+ else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
+ format = PatchFormatStringFloatToInt(format);
+
+ // Tabbing or CTRL-clicking on Drag turns it into an input box
+ bool start_text_input = false;
+ const bool tab_focus_requested = FocusableItemRegister(window, id);
+ if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
+ {
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+ if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id)
+ {
+ start_text_input = true;
+ g.ScalarAsInputTextId = 0;
+ }
+ }
+ if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
+ {
+ FocusableItemUnregister(window);
+ return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
+ }
+
+ // Actual drag behavior
+ ItemSize(total_bb, style.FramePadding.y);
+ const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power, ImGuiDragFlags_None);
+ if (value_changed)
+ MarkItemEdited(id);
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
+
+ return value_changed;
+}
+
+bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int components, float v_speed, const void* v_min, const void* v_max, const char* format, float power)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ PushMultiItemsWidths(components);
+ size_t type_size = GDataTypeInfo[data_type].Size;
+ for (int i = 0; i < components; i++)
+ {
+ PushID(i);
+ value_changed |= DragScalar("##v", data_type, v, v_speed, v_min, v_max, format, power);
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ PopID();
+ PopItemWidth();
+ v = (void*)((char*)v + type_size);
+ }
+ PopID();
+
+ TextUnformatted(label, FindRenderedTextEnd(label));
+ EndGroup();
+ return value_changed;
+}
+
+bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power)
+{
+ return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power);
+}
+
+bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power)
+{
+ return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power);
+}
+
+bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power)
+{
+ return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power);
+}
+
+bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power)
+{
+ return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power);
+}
+
+bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, float power)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ PushID(label);
+ BeginGroup();
+ PushMultiItemsWidths(2);
+
+ bool value_changed = DragFloat("##min", v_current_min, v_speed, (v_min >= v_max) ? -FLT_MAX : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format, power);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ value_changed |= DragFloat("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? FLT_MAX : v_max, format_max ? format_max : format, power);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+
+ TextUnformatted(label, FindRenderedTextEnd(label));
+ EndGroup();
+ PopID();
+ return value_changed;
+}
+
+// NB: v_speed is float to allow adjusting the drag speed with more precision
+bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format)
+{
+ return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format);
+}
+
+bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format)
+{
+ return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format);
+}
+
+bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format)
+{
+ return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format);
+}
+
+bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format)
+{
+ return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format);
+}
+
+bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ PushID(label);
+ BeginGroup();
+ PushMultiItemsWidths(2);
+
+ bool value_changed = DragInt("##min", v_current_min, v_speed, (v_min >= v_max) ? INT_MIN : v_min, (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max), format);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ value_changed |= DragInt("##max", v_current_max, v_speed, (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min), (v_min >= v_max) ? INT_MAX : v_max, format_max ? format_max : format);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+
+ TextUnformatted(label, FindRenderedTextEnd(label));
+ EndGroup();
+ PopID();
+
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
+//-------------------------------------------------------------------------
+// - SliderBehaviorT<>() [Internal]
+// - SliderBehavior() [Internal]
+// - SliderScalar()
+// - SliderScalarN()
+// - SliderFloat()
+// - SliderFloat2()
+// - SliderFloat3()
+// - SliderFloat4()
+// - SliderAngle()
+// - SliderInt()
+// - SliderInt2()
+// - SliderInt3()
+// - SliderInt4()
+// - VSliderScalar()
+// - VSliderFloat()
+// - VSliderInt()
+//-------------------------------------------------------------------------
+
+template<typename TYPE, typename FLOATTYPE>
+float ImGui::SliderCalcRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, float power, float linear_zero_pos)
+{
+ if (v_min == v_max)
+ return 0.0f;
+
+ const bool is_power = (power != 1.0f) && (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double);
+ const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
+ if (is_power)
+ {
+ if (v_clamped < 0.0f)
+ {
+ const float f = 1.0f - (float)((v_clamped - v_min) / (ImMin((TYPE)0, v_max) - v_min));
+ return (1.0f - ImPow(f, 1.0f/power)) * linear_zero_pos;
+ }
+ else
+ {
+ const float f = (float)((v_clamped - ImMax((TYPE)0, v_min)) / (v_max - ImMax((TYPE)0, v_min)));
+ return linear_zero_pos + ImPow(f, 1.0f/power) * (1.0f - linear_zero_pos);
+ }
+ }
+
+ // Linear slider
+ return (float)((FLOATTYPE)(v_clamped - v_min) / (FLOATTYPE)(v_max - v_min));
+}
+
+// FIXME: Move some of the code into SliderBehavior(). Current responsability is larger than what the equivalent DragBehaviorT<> does, we also do some rendering, etc.
+template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
+bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
+ const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
+ const bool is_power = (power != 1.0f) && is_decimal;
+
+ const float grab_padding = 2.0f;
+ const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
+ float grab_sz = style.GrabMinSize;
+ SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
+ if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows
+ grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit
+ grab_sz = ImMin(grab_sz, slider_sz);
+ const float slider_usable_sz = slider_sz - grab_sz;
+ const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz*0.5f;
+ const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz*0.5f;
+
+ // For power curve sliders that cross over sign boundary we want the curve to be symmetric around 0.0f
+ float linear_zero_pos; // 0.0->1.0f
+ if (is_power && v_min * v_max < 0.0f)
+ {
+ // Different sign
+ const FLOATTYPE linear_dist_min_to_0 = ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0f/power);
+ const FLOATTYPE linear_dist_max_to_0 = ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0f/power);
+ linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0));
+ }
+ else
+ {
+ // Same sign
+ linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
+ }
+
+ // Process interacting with the slider
+ bool value_changed = false;
+ if (g.ActiveId == id)
+ {
+ bool set_new_value = false;
+ float clicked_t = 0.0f;
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse)
+ {
+ if (!g.IO.MouseDown[0])
+ {
+ ClearActiveID();
+ }
+ else
+ {
+ const float mouse_abs_pos = g.IO.MousePos[axis];
+ clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f;
+ if (axis == ImGuiAxis_Y)
+ clicked_t = 1.0f - clicked_t;
+ set_new_value = true;
+ }
+ }
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ {
+ const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f);
+ float delta = (axis == ImGuiAxis_X) ? delta2.x : -delta2.y;
+ if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
+ {
+ ClearActiveID();
+ }
+ else if (delta != 0.0f)
+ {
+ clicked_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
+ const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
+ if ((decimal_precision > 0) || is_power)
+ {
+ delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
+ if (IsNavInputDown(ImGuiNavInput_TweakSlow))
+ delta /= 10.0f;
+ }
+ else
+ {
+ if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow))
+ delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range; // Gamepad/keyboard tweak speeds in integer steps
+ else
+ delta /= 100.0f;
+ }
+ if (IsNavInputDown(ImGuiNavInput_TweakFast))
+ delta *= 10.0f;
+ set_new_value = true;
+ if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits
+ set_new_value = false;
+ else
+ clicked_t = ImSaturate(clicked_t + delta);
+ }
+ }
+
+ if (set_new_value)
+ {
+ TYPE v_new;
+ if (is_power)
+ {
+ // Account for power curve scale on both sides of the zero
+ if (clicked_t < linear_zero_pos)
+ {
+ // Negative: rescale to the negative range before powering
+ float a = 1.0f - (clicked_t / linear_zero_pos);
+ a = ImPow(a, power);
+ v_new = ImLerp(ImMin(v_max, (TYPE)0), v_min, a);
+ }
+ else
+ {
+ // Positive: rescale to the positive range before powering
+ float a;
+ if (ImFabs(linear_zero_pos - 1.0f) > 1.e-6f)
+ a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos);
+ else
+ a = clicked_t;
+ a = ImPow(a, power);
+ v_new = ImLerp(ImMax(v_min, (TYPE)0), v_max, a);
+ }
+ }
+ else
+ {
+ // Linear slider
+ if (is_decimal)
+ {
+ v_new = ImLerp(v_min, v_max, clicked_t);
+ }
+ else
+ {
+ // For integer values we want the clicking position to match the grab box so we round above
+ // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
+ FLOATTYPE v_new_off_f = (v_max - v_min) * clicked_t;
+ TYPE v_new_off_floor = (TYPE)(v_new_off_f);
+ TYPE v_new_off_round = (TYPE)(v_new_off_f + (FLOATTYPE)0.5);
+ if (!is_decimal && v_new_off_floor < v_new_off_round)
+ v_new = v_min + v_new_off_round;
+ else
+ v_new = v_min + v_new_off_floor;
+ }
+ }
+
+ // Round to user desired precision based on format string
+ v_new = RoundScalarWithFormatT<TYPE,SIGNEDTYPE>(format, data_type, v_new);
+
+ // Apply result
+ if (*v != v_new)
+ {
+ *v = v_new;
+ value_changed = true;
+ }
+ }
+ }
+
+ // Output grab position so it can be displayed by the caller
+ float grab_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
+ if (axis == ImGuiAxis_Y)
+ grab_t = 1.0f - grab_t;
+ const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
+ if (axis == ImGuiAxis_X)
+ *out_grab_bb = ImRect(grab_pos - grab_sz*0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz*0.5f, bb.Max.y - grab_padding);
+ else
+ *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f);
+
+ return value_changed;
+}
+
+// For 32-bits and larger types, slider bounds are limited to half the natural type range.
+// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok.
+// It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders.
+bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power, ImGuiSliderFlags flags, ImRect* out_grab_bb)
+{
+ switch (data_type)
+ {
+ case ImGuiDataType_S32:
+ IM_ASSERT(*(const ImS32*)v_min >= IM_S32_MIN/2 && *(const ImS32*)v_max <= IM_S32_MAX/2);
+ return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)v, *(const ImS32*)v_min, *(const ImS32*)v_max, format, power, flags, out_grab_bb);
+ case ImGuiDataType_U32:
+ IM_ASSERT(*(const ImU32*)v_min <= IM_U32_MAX/2);
+ return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)v, *(const ImU32*)v_min, *(const ImU32*)v_max, format, power, flags, out_grab_bb);
+ case ImGuiDataType_S64:
+ IM_ASSERT(*(const ImS64*)v_min >= IM_S64_MIN/2 && *(const ImS64*)v_max <= IM_S64_MAX/2);
+ return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)v, *(const ImS64*)v_min, *(const ImS64*)v_max, format, power, flags, out_grab_bb);
+ case ImGuiDataType_U64:
+ IM_ASSERT(*(const ImU64*)v_min <= IM_U64_MAX/2);
+ return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)v, *(const ImU64*)v_min, *(const ImU64*)v_max, format, power, flags, out_grab_bb);
+ case ImGuiDataType_Float:
+ IM_ASSERT(*(const float*)v_min >= -FLT_MAX/2.0f && *(const float*)v_max <= FLT_MAX/2.0f);
+ return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)v, *(const float*)v_min, *(const float*)v_max, format, power, flags, out_grab_bb);
+ case ImGuiDataType_Double:
+ IM_ASSERT(*(const double*)v_min >= -DBL_MAX/2.0f && *(const double*)v_max <= DBL_MAX/2.0f);
+ return SliderBehaviorT<double,double,double>(bb, id, data_type, (double*)v, *(const double*)v_min, *(const double*)v_max, format, power, flags, out_grab_bb);
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+ return false;
+}
+
+bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f));
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ // NB- we don't call ItemSize() yet because we may turn into a text edit box below
+ if (!ItemAdd(total_bb, id, &frame_bb))
+ {
+ ItemSize(total_bb, style.FramePadding.y);
+ return false;
+ }
+
+ // Default format string when passing NULL
+ // Patch old "%.0f" format string to use "%d", read function comments for more details.
+ IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
+ if (format == NULL)
+ format = GDataTypeInfo[data_type].PrintFmt;
+ else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
+ format = PatchFormatStringFloatToInt(format);
+
+ // Tabbing or CTRL-clicking on Slider turns it into an input box
+ bool start_text_input = false;
+ const bool tab_focus_requested = FocusableItemRegister(window, id);
+ const bool hovered = ItemHoverable(frame_bb, id);
+ if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id))
+ {
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+ if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id)
+ {
+ start_text_input = true;
+ g.ScalarAsInputTextId = 0;
+ }
+ }
+ if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
+ {
+ FocusableItemUnregister(window);
+ return InputScalarAsWidgetReplacement(frame_bb, id, label, data_type, v, format);
+ }
+
+ ItemSize(total_bb, style.FramePadding.y);
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
+
+ // Slider behavior
+ ImRect grab_bb;
+ const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_None, &grab_bb);
+ if (value_changed)
+ MarkItemEdited(id);
+
+ // Render grab
+ window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.5f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ return value_changed;
+}
+
+// Add multiple sliders on 1 line for compact edition of multiple components
+bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ PushMultiItemsWidths(components);
+ size_t type_size = GDataTypeInfo[data_type].Size;
+ for (int i = 0; i < components; i++)
+ {
+ PushID(i);
+ value_changed |= SliderScalar("##v", data_type, v, v_min, v_max, format, power);
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ PopID();
+ PopItemWidth();
+ v = (void*)((char*)v + type_size);
+ }
+ PopID();
+
+ TextUnformatted(label, FindRenderedTextEnd(label));
+ EndGroup();
+ return value_changed;
+}
+
+bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power)
+{
+ return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
+}
+
+bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power)
+{
+ return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power);
+}
+
+bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power)
+{
+ return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power);
+}
+
+bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power)
+{
+ return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power);
+}
+
+bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format)
+{
+ if (format == NULL)
+ format = "%.0f deg";
+ float v_deg = (*v_rad) * 360.0f / (2*IM_PI);
+ bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, 1.0f);
+ *v_rad = v_deg * (2*IM_PI) / 360.0f;
+ return value_changed;
+}
+
+bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format)
+{
+ return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format);
+}
+
+bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format)
+{
+ return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format);
+}
+
+bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format)
+{
+ return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format);
+}
+
+bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format)
+{
+ return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format);
+}
+
+bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* v, const void* v_min, const void* v_max, const char* format, float power)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ ItemSize(bb, style.FramePadding.y);
+ if (!ItemAdd(frame_bb, id))
+ return false;
+
+ // Default format string when passing NULL
+ // Patch old "%.0f" format string to use "%d", read function comments for more details.
+ IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
+ if (format == NULL)
+ format = GDataTypeInfo[data_type].PrintFmt;
+ else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0)
+ format = PatchFormatStringFloatToInt(format);
+
+ const bool hovered = ItemHoverable(frame_bb, id);
+ if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id)
+ {
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ }
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
+
+ // Slider behavior
+ ImRect grab_bb;
+ const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical, &grab_bb);
+ if (value_changed)
+ MarkItemEdited(id);
+
+ // Render grab
+ window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ // For the vertical slider we allow centered text to overlap the frame padding
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, v, format);
+ RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f,0.0f));
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ return value_changed;
+}
+
+bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, float power)
+{
+ return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, power);
+}
+
+bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format)
+{
+ return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
+//-------------------------------------------------------------------------
+// - ImParseFormatFindStart() [Internal]
+// - ImParseFormatFindEnd() [Internal]
+// - ImParseFormatTrimDecorations() [Internal]
+// - ImParseFormatPrecision() [Internal]
+// - InputScalarAsWidgetReplacement() [Internal]
+// - InputScalar()
+// - InputScalarN()
+// - InputFloat()
+// - InputFloat2()
+// - InputFloat3()
+// - InputFloat4()
+// - InputInt()
+// - InputInt2()
+// - InputInt3()
+// - InputInt4()
+// - InputDouble()
+//-------------------------------------------------------------------------
+
+// We don't use strchr() because our strings are usually very short and often start with '%'
+const char* ImParseFormatFindStart(const char* fmt)
+{
+ while (char c = fmt[0])
+ {
+ if (c == '%' && fmt[1] != '%')
+ return fmt;
+ else if (c == '%')
+ fmt++;
+ fmt++;
+ }
+ return fmt;
+}
+
+const char* ImParseFormatFindEnd(const char* fmt)
+{
+ // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format.
+ if (fmt[0] != '%')
+ return fmt;
+ const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A'));
+ const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a'));
+ for (char c; (c = *fmt) != 0; fmt++)
+ {
+ if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0)
+ return fmt + 1;
+ if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0)
+ return fmt + 1;
+ }
+ return fmt;
+}
+
+// Extract the format out of a format string with leading or trailing decorations
+// fmt = "blah blah" -> return fmt
+// fmt = "%.3f" -> return fmt
+// fmt = "hello %.3f" -> return fmt + 6
+// fmt = "%.3f hello" -> return buf written with "%.3f"
+const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, int buf_size)
+{
+ const char* fmt_start = ImParseFormatFindStart(fmt);
+ if (fmt_start[0] != '%')
+ return fmt;
+ const char* fmt_end = ImParseFormatFindEnd(fmt_start);
+ if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
+ return fmt_start;
+ ImStrncpy(buf, fmt_start, ImMin((int)(fmt_end + 1 - fmt_start), buf_size));
+ return buf;
+}
+
+// Parse display precision back from the display format string
+// FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed.
+int ImParseFormatPrecision(const char* fmt, int default_precision)
+{
+ fmt = ImParseFormatFindStart(fmt);
+ if (fmt[0] != '%')
+ return default_precision;
+ fmt++;
+ while (*fmt >= '0' && *fmt <= '9')
+ fmt++;
+ int precision = INT_MAX;
+ if (*fmt == '.')
+ {
+ fmt = ImAtoi<int>(fmt + 1, &precision);
+ if (precision < 0 || precision > 99)
+ precision = default_precision;
+ }
+ if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation
+ precision = -1;
+ if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX)
+ precision = -1;
+ return (precision == INT_MAX) ? default_precision : precision;
+}
+
+// Create text input in place of an active drag/slider (used when doing a CTRL+Click on drag/slider widgets)
+// FIXME: Logic is awkward and confusing. This should be reworked to facilitate using in other situations.
+bool ImGui::InputScalarAsWidgetReplacement(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* data_ptr, const char* format)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen)
+ // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id
+ SetActiveID(g.ScalarAsInputTextId, window);
+ SetHoveredID(0);
+ g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+
+ char fmt_buf[32];
+ char data_buf[32];
+ format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
+ DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, data_ptr, format);
+ ImStrTrimBlanks(data_buf);
+ ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
+ bool value_changed = InputTextEx(label, data_buf, IM_ARRAYSIZE(data_buf), bb.GetSize(), flags);
+ if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget
+ {
+ IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID
+ g.ScalarAsInputTextId = g.ActiveId;
+ SetHoveredID(id);
+ }
+ if (value_changed)
+ return DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialText.Data, data_type, data_ptr, NULL);
+ return false;
+}
+
+bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_ptr, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
+ if (format == NULL)
+ format = GDataTypeInfo[data_type].PrintFmt;
+
+ char buf[64];
+ DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, data_ptr, format);
+
+ bool value_changed = false;
+ if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
+ flags |= ImGuiInputTextFlags_CharsDecimal;
+ flags |= ImGuiInputTextFlags_AutoSelectAll;
+
+ if (step != NULL)
+ {
+ const float button_size = GetFrameHeight();
+
+ BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
+ PushID(label);
+ PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
+ if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
+ value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format);
+ PopItemWidth();
+
+ // Step buttons
+ ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups;
+ if (flags & ImGuiInputTextFlags_ReadOnly)
+ button_flags |= ImGuiButtonFlags_Disabled;
+ SameLine(0, style.ItemInnerSpacing.x);
+ if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
+ {
+ DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step);
+ value_changed = true;
+ }
+ SameLine(0, style.ItemInnerSpacing.x);
+ if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
+ {
+ DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step);
+ value_changed = true;
+ }
+ SameLine(0, style.ItemInnerSpacing.x);
+ TextUnformatted(label, FindRenderedTextEnd(label));
+
+ PopID();
+ EndGroup();
+ }
+ else
+ {
+ if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
+ value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialText.Data, data_type, data_ptr, format);
+ }
+
+ return value_changed;
+}
+
+bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* step, const void* step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ PushMultiItemsWidths(components);
+ size_t type_size = GDataTypeInfo[data_type].Size;
+ for (int i = 0; i < components; i++)
+ {
+ PushID(i);
+ value_changed |= InputScalar("##v", data_type, v, step, step_fast, format, flags);
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ PopID();
+ PopItemWidth();
+ v = (void*)((char*)v + type_size);
+ }
+ PopID();
+
+ TextUnformatted(label, FindRenderedTextEnd(label));
+ EndGroup();
+ return value_changed;
+}
+
+bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ flags |= ImGuiInputTextFlags_CharsScientific;
+ return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), format, flags);
+}
+
+bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags);
+}
+
+// Prefer using "const char* format" directly, which is more flexible and consistent with other API.
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags flags)
+{
+ char format[16] = "%f";
+ if (decimal_precision >= 0)
+ ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
+ return InputFloat(label, v, step, step_fast, format, flags);
+}
+
+bool ImGui::InputFloat2(const char* label, float v[2], int decimal_precision, ImGuiInputTextFlags flags)
+{
+ char format[16] = "%f";
+ if (decimal_precision >= 0)
+ ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
+ return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputFloat3(const char* label, float v[3], int decimal_precision, ImGuiInputTextFlags flags)
+{
+ char format[16] = "%f";
+ if (decimal_precision >= 0)
+ ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
+ return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputFloat4(const char* label, float v[4], int decimal_precision, ImGuiInputTextFlags flags)
+{
+ char format[16] = "%f";
+ if (decimal_precision >= 0)
+ ImFormatString(format, IM_ARRAYSIZE(format), "%%.%df", decimal_precision);
+ return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags);
+}
+#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags)
+{
+ // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes.
+ const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
+ return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), format, flags);
+}
+
+bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags);
+}
+
+bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags);
+}
+
+bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags);
+}
+
+bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ flags |= ImGuiInputTextFlags_CharsScientific;
+ return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), format, flags);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: InputText, InputTextMultiline
+//-------------------------------------------------------------------------
+// - InputText()
+// - InputTextMultiline()
+// - InputTextEx() [Internal]
+//-------------------------------------------------------------------------
+
+bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
+ return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
+}
+
+bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
+}
+
+static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
+{
+ int line_count = 0;
+ const char* s = text_begin;
+ while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding
+ if (c == '\n')
+ line_count++;
+ s--;
+ if (s[0] != '\n' && s[0] != '\r')
+ line_count++;
+ *out_text_end = s;
+ return line_count;
+}
+
+static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)
+{
+ ImFont* font = GImGui->Font;
+ const float line_height = GImGui->FontSize;
+ const float scale = line_height / font->FontSize;
+
+ ImVec2 text_size = ImVec2(0,0);
+ float line_width = 0.0f;
+
+ const ImWchar* s = text_begin;
+ while (s < text_end)
+ {
+ unsigned int c = (unsigned int)(*s++);
+ if (c == '\n')
+ {
+ text_size.x = ImMax(text_size.x, line_width);
+ text_size.y += line_height;
+ line_width = 0.0f;
+ if (stop_on_new_line)
+ break;
+ continue;
+ }
+ if (c == '\r')
+ continue;
+
+ const float char_width = font->GetCharAdvance((ImWchar)c) * scale;
+ line_width += char_width;
+ }
+
+ if (text_size.x < line_width)
+ text_size.x = line_width;
+
+ if (out_offset)
+ *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n
+
+ if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n
+ text_size.y += line_height;
+
+ if (remaining)
+ *remaining = s;
+
+ return text_size;
+}
+
+// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar)
+namespace ImGuiStb
+{
+
+static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; }
+static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; }
+static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx+char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; return GImGui->Font->GetCharAdvance(c) * (GImGui->FontSize / GImGui->Font->FontSize); }
+static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x10000 ? 0 : key; }
+static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
+static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
+{
+ const ImWchar* text = obj->TextW.Data;
+ const ImWchar* text_remaining = NULL;
+ const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);
+ r->x0 = 0.0f;
+ r->x1 = size.x;
+ r->baseline_y_delta = size.y;
+ r->ymin = 0.0f;
+ r->ymax = size.y;
+ r->num_chars = (int)(text_remaining - (text + line_start_idx));
+}
+
+static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
+static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->TextW[idx-1] ) && !is_separator( obj->TextW[idx] ) ) : 1; }
+static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
+#ifdef __APPLE__ // FIXME: Move setting to IO structure
+static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->TextW[idx-1] ) && is_separator( obj->TextW[idx] ) ) : 1; }
+static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
+#else
+static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
+#endif
+#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
+#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
+
+static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
+{
+ ImWchar* dst = obj->TextW.Data + pos;
+
+ // We maintain our buffer length in both UTF-8 and wchar formats
+ obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
+ obj->CurLenW -= n;
+
+ // Offset remaining text (FIXME-OPT: Use memmove)
+ const ImWchar* src = obj->TextW.Data + pos + n;
+ while (ImWchar c = *src++)
+ *dst++ = c;
+ *dst = '\0';
+}
+
+static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
+{
+ const bool is_resizable = (obj->UserFlags & ImGuiInputTextFlags_CallbackResize) != 0;
+ const int text_len = obj->CurLenW;
+ IM_ASSERT(pos <= text_len);
+
+ const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
+ if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
+ return false;
+
+ // Grow internal buffer if needed
+ if (new_text_len + text_len + 1 > obj->TextW.Size)
+ {
+ if (!is_resizable)
+ return false;
+ IM_ASSERT(text_len < obj->TextW.Size);
+ obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1);
+ }
+
+ ImWchar* text = obj->TextW.Data;
+ if (pos != text_len)
+ memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar));
+ memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
+
+ obj->CurLenW += new_text_len;
+ obj->CurLenA += new_text_len_utf8;
+ obj->TextW[obj->CurLenW] = '\0';
+
+ return true;
+}
+
+// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
+#define STB_TEXTEDIT_K_LEFT 0x10000 // keyboard input to move cursor left
+#define STB_TEXTEDIT_K_RIGHT 0x10001 // keyboard input to move cursor right
+#define STB_TEXTEDIT_K_UP 0x10002 // keyboard input to move cursor up
+#define STB_TEXTEDIT_K_DOWN 0x10003 // keyboard input to move cursor down
+#define STB_TEXTEDIT_K_LINESTART 0x10004 // keyboard input to move cursor to start of line
+#define STB_TEXTEDIT_K_LINEEND 0x10005 // keyboard input to move cursor to end of line
+#define STB_TEXTEDIT_K_TEXTSTART 0x10006 // keyboard input to move cursor to start of text
+#define STB_TEXTEDIT_K_TEXTEND 0x10007 // keyboard input to move cursor to end of text
+#define STB_TEXTEDIT_K_DELETE 0x10008 // keyboard input to delete selection or character under cursor
+#define STB_TEXTEDIT_K_BACKSPACE 0x10009 // keyboard input to delete selection or character left of cursor
+#define STB_TEXTEDIT_K_UNDO 0x1000A // keyboard input to perform undo
+#define STB_TEXTEDIT_K_REDO 0x1000B // keyboard input to perform redo
+#define STB_TEXTEDIT_K_WORDLEFT 0x1000C // keyboard input to move cursor left one word
+#define STB_TEXTEDIT_K_WORDRIGHT 0x1000D // keyboard input to move cursor right one word
+#define STB_TEXTEDIT_K_SHIFT 0x20000
+
+#define STB_TEXTEDIT_IMPLEMENTATION
+#include "imstb_textedit.h"
+
+}
+
+void ImGuiInputTextState::OnKeyPressed(int key)
+{
+ stb_textedit_key(this, &StbState, key);
+ CursorFollow = true;
+ CursorAnimReset();
+}
+
+ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
+{
+ memset(this, 0, sizeof(*this));
+}
+
+// Public API to manipulate UTF-8 text
+// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
+// FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
+void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
+{
+ IM_ASSERT(pos + bytes_count <= BufTextLen);
+ char* dst = Buf + pos;
+ const char* src = Buf + pos + bytes_count;
+ while (char c = *src++)
+ *dst++ = c;
+ *dst = '\0';
+
+ if (CursorPos + bytes_count >= pos)
+ CursorPos -= bytes_count;
+ else if (CursorPos >= pos)
+ CursorPos = pos;
+ SelectionStart = SelectionEnd = CursorPos;
+ BufDirty = true;
+ BufTextLen -= bytes_count;
+}
+
+void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
+{
+ const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
+ const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
+ if (new_text_len + BufTextLen >= BufSize)
+ {
+ if (!is_resizable)
+ return;
+
+ // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the midly similar code (until we remove the U16 buffer alltogether!)
+ ImGuiContext& g = *GImGui;
+ ImGuiInputTextState* edit_state = &g.InputTextState;
+ IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
+ IM_ASSERT(Buf == edit_state->TempBuffer.Data);
+ int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
+ edit_state->TempBuffer.reserve(new_buf_size + 1);
+ Buf = edit_state->TempBuffer.Data;
+ BufSize = edit_state->BufCapacityA = new_buf_size;
+ }
+
+ if (BufTextLen != pos)
+ memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));
+ memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
+ Buf[BufTextLen + new_text_len] = '\0';
+
+ if (CursorPos >= pos)
+ CursorPos += new_text_len;
+ SelectionStart = SelectionEnd = CursorPos;
+ BufDirty = true;
+ BufTextLen += new_text_len;
+}
+
+// Return false to discard a character.
+static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ unsigned int c = *p_char;
+
+ if (c < 128 && c != ' ' && !isprint((int)(c & 0xFF)))
+ {
+ bool pass = false;
+ pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline));
+ pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput));
+ if (!pass)
+ return false;
+ }
+
+ if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys.
+ return false;
+
+ if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))
+ {
+ if (flags & ImGuiInputTextFlags_CharsDecimal)
+ if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
+ return false;
+
+ if (flags & ImGuiInputTextFlags_CharsScientific)
+ if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
+ return false;
+
+ if (flags & ImGuiInputTextFlags_CharsHexadecimal)
+ if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
+ return false;
+
+ if (flags & ImGuiInputTextFlags_CharsUppercase)
+ if (c >= 'a' && c <= 'z')
+ *p_char = (c += (unsigned int)('A'-'a'));
+
+ if (flags & ImGuiInputTextFlags_CharsNoBlank)
+ if (ImCharIsBlankW(c))
+ return false;
+ }
+
+ if (flags & ImGuiInputTextFlags_CallbackCharFilter)
+ {
+ ImGuiInputTextCallbackData callback_data;
+ memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
+ callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
+ callback_data.EventChar = (ImWchar)c;
+ callback_data.Flags = flags;
+ callback_data.UserData = user_data;
+ if (callback(&callback_data) != 0)
+ return false;
+ *p_char = callback_data.EventChar;
+ if (!callback_data.EventChar)
+ return false;
+ }
+
+ return true;
+}
+
+// Edit a string of text
+// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
+// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
+// Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator.
+// - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect.
+// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h
+// (FIXME: Rather messy function partly because we are doing UTF8 > u16 > UTF8 conversions on the go to more easily handle stb_textedit calls. Ideally we should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
+bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys)
+ IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)
+
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+ const ImGuiStyle& style = g.Style;
+
+ const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
+ const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0;
+ const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
+ const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
+ const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
+ if (is_resizable)
+ IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
+
+ if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
+ BeginGroup();
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? GetTextLineHeight() * 8.0f : label_size.y) + style.FramePadding.y*2.0f); // Arbitrary default of 8 lines high for multi-line
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? (style.ItemInnerSpacing.x + label_size.x) : 0.0f, 0.0f));
+
+ ImGuiWindow* draw_window = window;
+ if (is_multiline)
+ {
+ ItemAdd(total_bb, id, &frame_bb);
+ if (!BeginChildFrame(id, frame_bb.GetSize()))
+ {
+ EndChildFrame();
+ EndGroup();
+ return false;
+ }
+ draw_window = GetCurrentWindow();
+ draw_window->DC.NavLayerActiveMaskNext |= draw_window->DC.NavLayerCurrentMask; // This is to ensure that EndChild() will display a navigation highlight
+ size.x -= draw_window->ScrollbarSizes.x;
+ }
+ else
+ {
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id, &frame_bb))
+ return false;
+ }
+ const bool hovered = ItemHoverable(frame_bb, id);
+ if (hovered)
+ g.MouseCursor = ImGuiMouseCursor_TextInput;
+
+ // Password pushes a temporary font with only a fallback glyph
+ if (is_password)
+ {
+ const ImFontGlyph* glyph = g.Font->FindGlyph('*');
+ ImFont* password_font = &g.InputTextPasswordFont;
+ password_font->FontSize = g.Font->FontSize;
+ password_font->Scale = g.Font->Scale;
+ password_font->DisplayOffset = g.Font->DisplayOffset;
+ password_font->Ascent = g.Font->Ascent;
+ password_font->Descent = g.Font->Descent;
+ password_font->ContainerAtlas = g.Font->ContainerAtlas;
+ password_font->FallbackGlyph = glyph;
+ password_font->FallbackAdvanceX = glyph->AdvanceX;
+ IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
+ PushFont(password_font);
+ }
+
+ // NB: we are only allowed to access 'edit_state' if we are the active widget.
+ ImGuiInputTextState& edit_state = g.InputTextState;
+
+ const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing
+ const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
+ const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
+
+ const bool user_clicked = hovered && io.MouseClicked[0];
+ const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.ID == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY");
+ const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_NavKeyboard));
+
+ bool clear_active_id = false;
+
+ bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline);
+ if (focus_requested || user_clicked || user_scrolled || user_nav_input_start)
+ {
+ if (g.ActiveId != id)
+ {
+ // Start edition
+ // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
+ // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
+ const int prev_len_w = edit_state.CurLenW;
+ const int init_buf_len = (int)strlen(buf);
+ edit_state.TextW.resize(buf_size+1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
+ edit_state.InitialText.resize(init_buf_len + 1); // UTF-8. we use +1 to make sure that .Data isn't NULL so it doesn't crash.
+ memcpy(edit_state.InitialText.Data, buf, init_buf_len + 1);
+ const char* buf_end = NULL;
+ edit_state.CurLenW = ImTextStrFromUtf8(edit_state.TextW.Data, buf_size, buf, NULL, &buf_end);
+ edit_state.CurLenA = (int)(buf_end - buf); // We can't get the result from ImStrncpy() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
+ edit_state.CursorAnimReset();
+
+ // Preserve cursor position and undo/redo stack if we come back to same widget
+ // FIXME: We should probably compare the whole buffer to be on the safety side. Comparing buf (utf8) and edit_state.Text (wchar).
+ const bool recycle_state = (edit_state.ID == id) && (prev_len_w == edit_state.CurLenW);
+ if (recycle_state)
+ {
+ // Recycle existing cursor/selection/undo stack but clamp position
+ // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
+ edit_state.CursorClamp();
+ }
+ else
+ {
+ edit_state.ID = id;
+ edit_state.ScrollX = 0.0f;
+ stb_textedit_initialize_state(&edit_state.StbState, !is_multiline);
+ if (!is_multiline && focus_requested_by_code)
+ select_all = true;
+ }
+ if (flags & ImGuiInputTextFlags_AlwaysInsertMode)
+ edit_state.StbState.insert_mode = true;
+ if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
+ select_all = true;
+ }
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory))
+ g.ActiveIdAllowNavDirFlags |= ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down));
+ }
+ else if (io.MouseClicked[0])
+ {
+ // Release focus when we click outside
+ clear_active_id = true;
+ }
+
+ bool value_changed = false;
+ bool enter_pressed = false;
+ int backup_current_text_length = 0;
+
+ if (g.ActiveId == id)
+ {
+ if (!is_editable && !g.ActiveIdIsJustActivated)
+ {
+ // When read-only we always use the live data passed to the function
+ edit_state.TextW.resize(buf_size+1);
+ const char* buf_end = NULL;
+ edit_state.CurLenW = ImTextStrFromUtf8(edit_state.TextW.Data, edit_state.TextW.Size, buf, NULL, &buf_end);
+ edit_state.CurLenA = (int)(buf_end - buf);
+ edit_state.CursorClamp();
+ }
+
+ backup_current_text_length = edit_state.CurLenA;
+ edit_state.BufCapacityA = buf_size;
+ edit_state.UserFlags = flags;
+ edit_state.UserCallback = callback;
+ edit_state.UserCallbackData = callback_user_data;
+
+ // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
+ // Down the line we should have a cleaner library-wide concept of Selected vs Active.
+ g.ActiveIdAllowOverlap = !io.MouseDown[0];
+ g.WantTextInputNextFrame = 1;
+
+ // Edit in progress
+ const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
+ const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));
+
+ const bool is_osx = io.ConfigMacOSXBehaviors;
+ if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
+ {
+ edit_state.SelectAll();
+ edit_state.SelectedAllMouseLock = true;
+ }
+ else if (hovered && is_osx && io.MouseDoubleClicked[0])
+ {
+ // Double-click select a word only, OS X style (by simulating keystrokes)
+ edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
+ edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
+ }
+ else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock)
+ {
+ if (hovered)
+ {
+ stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
+ edit_state.CursorAnimReset();
+ }
+ }
+ else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
+ {
+ stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
+ edit_state.CursorAnimReset();
+ edit_state.CursorFollow = true;
+ }
+ if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
+ edit_state.SelectedAllMouseLock = false;
+
+ if (io.InputQueueCharacters.Size > 0)
+ {
+ // Process text input (before we check for Return because using some IME will effectively send a Return?)
+ // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
+ bool ignore_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
+ if (!ignore_inputs && is_editable && !user_nav_input_start)
+ for (int n = 0; n < io.InputQueueCharacters.Size; n++)
+ {
+ // Insert character if they pass filtering
+ unsigned int c = (unsigned int)io.InputQueueCharacters[n];
+ if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
+ edit_state.OnKeyPressed((int)c);
+ }
+
+ // Consume characters
+ io.InputQueueCharacters.resize(0);
+ }
+ }
+
+ bool cancel_edit = false;
+ if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id)
+ {
+ // Handle key-presses
+ const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
+ const bool is_osx = io.ConfigMacOSXBehaviors;
+ const bool is_shortcut_key = (is_osx ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl
+ const bool is_osx_shift_shortcut = is_osx && io.KeySuper && io.KeyShift && !io.KeyCtrl && !io.KeyAlt;
+ const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
+ const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
+ const bool is_ctrl_key_only = io.KeyCtrl && !io.KeyShift && !io.KeyAlt && !io.KeySuper;
+ const bool is_shift_key_only = io.KeyShift && !io.KeyCtrl && !io.KeyAlt && !io.KeySuper;
+
+ const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && is_editable && !is_password && (!is_multiline || edit_state.HasSelection());
+ const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || edit_state.HasSelection());
+ const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && is_editable;
+ const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && is_editable && is_undoable);
+ const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && is_editable && is_undoable;
+
+ if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_End)) { edit_state.OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_Delete) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_Backspace) && is_editable)
+ {
+ if (!edit_state.HasSelection())
+ {
+ if (is_wordmove_key_down) edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT|STB_TEXTEDIT_K_SHIFT);
+ else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) edit_state.OnKeyPressed(STB_TEXTEDIT_K_LINESTART|STB_TEXTEDIT_K_SHIFT);
+ }
+ edit_state.OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
+ }
+ else if (IsKeyPressedMap(ImGuiKey_Enter))
+ {
+ bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
+ if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
+ {
+ enter_pressed = clear_active_id = true;
+ }
+ else if (is_editable)
+ {
+ unsigned int c = '\n'; // Insert new line
+ if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
+ edit_state.OnKeyPressed((int)c);
+ }
+ }
+ else if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !io.KeyCtrl && !io.KeyShift && !io.KeyAlt && is_editable)
+ {
+ unsigned int c = '\t'; // Insert TAB
+ if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
+ edit_state.OnKeyPressed((int)c);
+ }
+ else if (IsKeyPressedMap(ImGuiKey_Escape))
+ {
+ clear_active_id = cancel_edit = true;
+ }
+ else if (is_undo || is_redo)
+ {
+ edit_state.OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO);
+ edit_state.ClearSelection();
+ }
+ else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A))
+ {
+ edit_state.SelectAll();
+ edit_state.CursorFollow = true;
+ }
+ else if (is_cut || is_copy)
+ {
+ // Cut, Copy
+ if (io.SetClipboardTextFn)
+ {
+ const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0;
+ const int ie = edit_state.HasSelection() ? ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end) : edit_state.CurLenW;
+ edit_state.TempBuffer.resize((ie-ib) * 4 + 1);
+ ImTextStrToUtf8(edit_state.TempBuffer.Data, edit_state.TempBuffer.Size, edit_state.TextW.Data+ib, edit_state.TextW.Data+ie);
+ SetClipboardText(edit_state.TempBuffer.Data);
+ }
+ if (is_cut)
+ {
+ if (!edit_state.HasSelection())
+ edit_state.SelectAll();
+ edit_state.CursorFollow = true;
+ stb_textedit_cut(&edit_state, &edit_state.StbState);
+ }
+ }
+ else if (is_paste)
+ {
+ if (const char* clipboard = GetClipboardText())
+ {
+ // Filter pasted buffer
+ const int clipboard_len = (int)strlen(clipboard);
+ ImWchar* clipboard_filtered = (ImWchar*)MemAlloc((clipboard_len+1) * sizeof(ImWchar));
+ int clipboard_filtered_len = 0;
+ for (const char* s = clipboard; *s; )
+ {
+ unsigned int c;
+ s += ImTextCharFromUtf8(&c, s, NULL);
+ if (c == 0)
+ break;
+ if (c >= 0x10000 || !InputTextFilterCharacter(&c, flags, callback, callback_user_data))
+ continue;
+ clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
+ }
+ clipboard_filtered[clipboard_filtered_len] = 0;
+ if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
+ {
+ stb_textedit_paste(&edit_state, &edit_state.StbState, clipboard_filtered, clipboard_filtered_len);
+ edit_state.CursorFollow = true;
+ }
+ MemFree(clipboard_filtered);
+ }
+ }
+ }
+
+ if (g.ActiveId == id)
+ {
+ const char* apply_new_text = NULL;
+ int apply_new_text_length = 0;
+ if (cancel_edit)
+ {
+ // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
+ if (is_editable && strcmp(buf, edit_state.InitialText.Data) != 0)
+ {
+ apply_new_text = edit_state.InitialText.Data;
+ apply_new_text_length = edit_state.InitialText.Size - 1;
+ }
+ }
+
+ // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.
+ // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage.
+ bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
+ if (apply_edit_back_to_user_buffer)
+ {
+ // Apply new value immediately - copy modified buffer back
+ // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
+ // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
+ // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
+ if (is_editable)
+ {
+ edit_state.TempBuffer.resize(edit_state.TextW.Size * 4 + 1);
+ ImTextStrToUtf8(edit_state.TempBuffer.Data, edit_state.TempBuffer.Size, edit_state.TextW.Data, NULL);
+ }
+
+ // User callback
+ if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways)) != 0)
+ {
+ IM_ASSERT(callback != NULL);
+
+ // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
+ ImGuiInputTextFlags event_flag = 0;
+ ImGuiKey event_key = ImGuiKey_COUNT;
+ if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab))
+ {
+ event_flag = ImGuiInputTextFlags_CallbackCompletion;
+ event_key = ImGuiKey_Tab;
+ }
+ else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow))
+ {
+ event_flag = ImGuiInputTextFlags_CallbackHistory;
+ event_key = ImGuiKey_UpArrow;
+ }
+ else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow))
+ {
+ event_flag = ImGuiInputTextFlags_CallbackHistory;
+ event_key = ImGuiKey_DownArrow;
+ }
+ else if (flags & ImGuiInputTextFlags_CallbackAlways)
+ event_flag = ImGuiInputTextFlags_CallbackAlways;
+
+ if (event_flag)
+ {
+ ImGuiInputTextCallbackData callback_data;
+ memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
+ callback_data.EventFlag = event_flag;
+ callback_data.Flags = flags;
+ callback_data.UserData = callback_user_data;
+
+ callback_data.EventKey = event_key;
+ callback_data.Buf = edit_state.TempBuffer.Data;
+ callback_data.BufTextLen = edit_state.CurLenA;
+ callback_data.BufSize = edit_state.BufCapacityA;
+ callback_data.BufDirty = false;
+
+ // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
+ ImWchar* text = edit_state.TextW.Data;
+ const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.cursor);
+ const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_start);
+ const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + edit_state.StbState.select_end);
+
+ // Call user code
+ callback(&callback_data);
+
+ // Read back what user may have modified
+ IM_ASSERT(callback_data.Buf == edit_state.TempBuffer.Data); // Invalid to modify those fields
+ IM_ASSERT(callback_data.BufSize == edit_state.BufCapacityA);
+ IM_ASSERT(callback_data.Flags == flags);
+ if (callback_data.CursorPos != utf8_cursor_pos) { edit_state.StbState.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); edit_state.CursorFollow = true; }
+ if (callback_data.SelectionStart != utf8_selection_start) { edit_state.StbState.select_start = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
+ if (callback_data.SelectionEnd != utf8_selection_end) { edit_state.StbState.select_end = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
+ if (callback_data.BufDirty)
+ {
+ IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
+ if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
+ edit_state.TextW.resize(edit_state.TextW.Size + (callback_data.BufTextLen - backup_current_text_length));
+ edit_state.CurLenW = ImTextStrFromUtf8(edit_state.TextW.Data, edit_state.TextW.Size, callback_data.Buf, NULL);
+ edit_state.CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
+ edit_state.CursorAnimReset();
+ }
+ }
+ }
+
+ // Will copy result string if modified
+ if (is_editable && strcmp(edit_state.TempBuffer.Data, buf) != 0)
+ {
+ apply_new_text = edit_state.TempBuffer.Data;
+ apply_new_text_length = edit_state.CurLenA;
+ }
+ }
+
+ // Copy result to user buffer
+ if (apply_new_text)
+ {
+ IM_ASSERT(apply_new_text_length >= 0);
+ if (backup_current_text_length != apply_new_text_length && is_resizable)
+ {
+ ImGuiInputTextCallbackData callback_data;
+ callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
+ callback_data.Flags = flags;
+ callback_data.Buf = buf;
+ callback_data.BufTextLen = apply_new_text_length;
+ callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
+ callback_data.UserData = callback_user_data;
+ callback(&callback_data);
+ buf = callback_data.Buf;
+ buf_size = callback_data.BufSize;
+ apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
+ IM_ASSERT(apply_new_text_length <= buf_size);
+ }
+
+ // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
+ ImStrncpy(buf, edit_state.TempBuffer.Data, ImMin(apply_new_text_length + 1, buf_size));
+ value_changed = true;
+ }
+
+ // Clear temporary user storage
+ edit_state.UserFlags = 0;
+ edit_state.UserCallback = NULL;
+ edit_state.UserCallbackData = NULL;
+ }
+
+ // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
+ if (clear_active_id && g.ActiveId == id)
+ ClearActiveID();
+
+ // Render
+ // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on.
+ const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempBuffer.Data : buf; buf = NULL;
+
+ // Set upper limit of single-line InputTextEx() at 2 million characters strings. The current pathological worst case is a long line
+ // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
+ // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
+ const int buf_display_max_length = 2 * 1024 * 1024;
+
+ if (!is_multiline)
+ {
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
+ }
+
+ const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + size.x, frame_bb.Min.y + size.y); // Not using frame_bb.Max because we have adjusted size
+ ImVec2 render_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;
+ ImVec2 text_size(0.f, 0.f);
+ const bool is_currently_scrolling = (edit_state.ID == id && is_multiline && g.ActiveId == draw_window->GetIDNoKeepAlive("#SCROLLY"));
+ if (g.ActiveId == id || is_currently_scrolling)
+ {
+ edit_state.CursorAnim += io.DeltaTime;
+
+ // This is going to be messy. We need to:
+ // - Display the text (this alone can be more easily clipped)
+ // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)
+ // - Measure text height (for scrollbar)
+ // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
+ // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
+ const ImWchar* text_begin = edit_state.TextW.Data;
+ ImVec2 cursor_offset, select_start_offset;
+
+ {
+ // Count lines + find lines numbers straddling 'cursor' and 'select_start' position.
+ const ImWchar* searches_input_ptr[2];
+ searches_input_ptr[0] = text_begin + edit_state.StbState.cursor;
+ searches_input_ptr[1] = NULL;
+ int searches_remaining = 1;
+ int searches_result_line_number[2] = { -1, -999 };
+ if (edit_state.StbState.select_start != edit_state.StbState.select_end)
+ {
+ searches_input_ptr[1] = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);
+ searches_result_line_number[1] = -1;
+ searches_remaining++;
+ }
+
+ // Iterate all lines to find our line numbers
+ // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
+ searches_remaining += is_multiline ? 1 : 0;
+ int line_count = 0;
+ //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) // FIXME-OPT: Could use this when wchar_t are 16-bits
+ for (const ImWchar* s = text_begin; *s != 0; s++)
+ if (*s == '\n')
+ {
+ line_count++;
+ if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; }
+ if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; }
+ }
+ line_count++;
+ if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count;
+ if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count;
+
+ // Calculate 2d position by finding the beginning of the line and measuring distance
+ cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
+ cursor_offset.y = searches_result_line_number[0] * g.FontSize;
+ if (searches_result_line_number[1] >= 0)
+ {
+ select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
+ select_start_offset.y = searches_result_line_number[1] * g.FontSize;
+ }
+
+ // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)
+ if (is_multiline)
+ text_size = ImVec2(size.x, line_count * g.FontSize);
+ }
+
+ // Scroll
+ if (edit_state.CursorFollow)
+ {
+ // Horizontal scroll in chunks of quarter width
+ if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll))
+ {
+ const float scroll_increment_x = size.x * 0.25f;
+ if (cursor_offset.x < edit_state.ScrollX)
+ edit_state.ScrollX = (float)(int)ImMax(0.0f, cursor_offset.x - scroll_increment_x);
+ else if (cursor_offset.x - size.x >= edit_state.ScrollX)
+ edit_state.ScrollX = (float)(int)(cursor_offset.x - size.x + scroll_increment_x);
+ }
+ else
+ {
+ edit_state.ScrollX = 0.0f;
+ }
+
+ // Vertical scroll
+ if (is_multiline)
+ {
+ float scroll_y = draw_window->Scroll.y;
+ if (cursor_offset.y - g.FontSize < scroll_y)
+ scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
+ else if (cursor_offset.y - size.y >= scroll_y)
+ scroll_y = cursor_offset.y - size.y;
+ draw_window->DC.CursorPos.y += (draw_window->Scroll.y - scroll_y); // To avoid a frame of lag
+ draw_window->Scroll.y = scroll_y;
+ render_pos.y = draw_window->DC.CursorPos.y;
+ }
+ }
+ edit_state.CursorFollow = false;
+ const ImVec2 render_scroll = ImVec2(edit_state.ScrollX, 0.0f);
+
+ // Draw selection
+ if (edit_state.StbState.select_start != edit_state.StbState.select_end)
+ {
+ const ImWchar* text_selected_begin = text_begin + ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end);
+ const ImWchar* text_selected_end = text_begin + ImMax(edit_state.StbState.select_start, edit_state.StbState.select_end);
+
+ float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
+ float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
+ ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg);
+ ImVec2 rect_pos = render_pos + select_start_offset - render_scroll;
+ for (const ImWchar* p = text_selected_begin; p < text_selected_end; )
+ {
+ if (rect_pos.y > clip_rect.w + g.FontSize)
+ break;
+ if (rect_pos.y < clip_rect.y)
+ {
+ //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bits
+ //p = p ? p + 1 : text_selected_end;
+ while (p < text_selected_end)
+ if (*p++ == '\n')
+ break;
+ }
+ else
+ {
+ ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
+ if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
+ ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn));
+ rect.ClipWith(clip_rect);
+ if (rect.Overlaps(clip_rect))
+ draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
+ }
+ rect_pos.x = render_pos.x - render_scroll.x;
+ rect_pos.y += g.FontSize;
+ }
+ }
+
+ const int buf_display_len = edit_state.CurLenA;
+ if (is_multiline || buf_display_len < buf_display_max_length)
+ draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos - render_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display + buf_display_len, 0.0f, is_multiline ? NULL : &clip_rect);
+
+ // Draw blinking cursor
+ bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (g.InputTextState.CursorAnim <= 0.0f) || ImFmod(g.InputTextState.CursorAnim, 1.20f) <= 0.80f;
+ ImVec2 cursor_screen_pos = render_pos + cursor_offset - render_scroll;
+ ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y-g.FontSize+0.5f, cursor_screen_pos.x+1.0f, cursor_screen_pos.y-1.5f);
+ if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
+ draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
+
+ // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
+ if (is_editable)
+ g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
+ }
+ else
+ {
+ // Render text only
+ const char* buf_end = NULL;
+ if (is_multiline)
+ text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_end) * g.FontSize); // We don't need width
+ else
+ buf_end = buf_display + strlen(buf_display);
+ if (is_multiline || (buf_end - buf_display) < buf_display_max_length)
+ draw_window->DrawList->AddText(g.Font, g.FontSize, render_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_end, 0.0f, is_multiline ? NULL : &clip_rect);
+ }
+
+ if (is_multiline)
+ {
+ Dummy(text_size + ImVec2(0.0f, g.FontSize)); // Always add room to scroll an extra line
+ EndChildFrame();
+ EndGroup();
+ }
+
+ if (is_password)
+ PopFont();
+
+ // Log as text
+ if (g.LogEnabled && !is_password)
+ LogRenderedText(&render_pos, buf_display, NULL);
+
+ if (label_size.x > 0)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ if (value_changed)
+ MarkItemEdited(id);
+
+ if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
+ return enter_pressed;
+ else
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
+//-------------------------------------------------------------------------
+// - ColorEdit3()
+// - ColorEdit4()
+// - ColorPicker3()
+// - RenderColorRectWithAlphaCheckerboard() [Internal]
+// - ColorPicker4()
+// - ColorButton()
+// - SetColorEditOptions()
+// - ColorTooltip() [Internal]
+// - ColorEditOptionsPopup() [Internal]
+// - ColorPickerOptionsPopup() [Internal]
+//-------------------------------------------------------------------------
+
+bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)
+{
+ return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);
+}
+
+// Edit colors components (each component in 0.0f..1.0f range).
+// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
+// With typical options: Left-click on colored square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item.
+bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const float square_sz = GetFrameHeight();
+ const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
+ const float w_items_all = CalcItemWidth() - w_extra;
+ const char* label_display_end = FindRenderedTextEnd(label);
+
+ BeginGroup();
+ PushID(label);
+
+ // If we're not showing any slider there's no point in doing any HSV conversions
+ const ImGuiColorEditFlags flags_untouched = flags;
+ if (flags & ImGuiColorEditFlags_NoInputs)
+ flags = (flags & (~ImGuiColorEditFlags__InputsMask)) | ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_NoOptions;
+
+ // Context menu: display and modify options (before defaults are applied)
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ ColorEditOptionsPopup(col, flags);
+
+ // Read stored options
+ if (!(flags & ImGuiColorEditFlags__InputsMask))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags__InputsMask);
+ if (!(flags & ImGuiColorEditFlags__DataTypeMask))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags__DataTypeMask);
+ if (!(flags & ImGuiColorEditFlags__PickerMask))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags__PickerMask);
+ flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask));
+
+ const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;
+ const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;
+ const int components = alpha ? 4 : 3;
+
+ // Convert to the formats we need
+ float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
+ if (flags & ImGuiColorEditFlags_HSV)
+ ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
+ int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) };
+
+ bool value_changed = false;
+ bool value_changed_as_float = false;
+
+ if ((flags & (ImGuiColorEditFlags_RGB | ImGuiColorEditFlags_HSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
+ {
+ // RGB/HSV 0..255 Sliders
+ const float w_item_one = ImMax(1.0f, (float)(int)((w_items_all - (style.ItemInnerSpacing.x) * (components-1)) / (float)components));
+ const float w_item_last = ImMax(1.0f, (float)(int)(w_items_all - (w_item_one + style.ItemInnerSpacing.x) * (components-1)));
+
+ const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
+ const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
+ const char* fmt_table_int[3][4] =
+ {
+ { "%3d", "%3d", "%3d", "%3d" }, // Short display
+ { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA
+ { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA
+ };
+ const char* fmt_table_float[3][4] =
+ {
+ { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display
+ { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA
+ { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA
+ };
+ const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_HSV) ? 2 : 1;
+
+ PushItemWidth(w_item_one);
+ for (int n = 0; n < components; n++)
+ {
+ if (n > 0)
+ SameLine(0, style.ItemInnerSpacing.x);
+ if (n + 1 == components)
+ PushItemWidth(w_item_last);
+ if (flags & ImGuiColorEditFlags_Float)
+ value_changed = value_changed_as_float = value_changed | DragFloat(ids[n], &f[n], 1.0f/255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
+ else
+ value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+ }
+ PopItemWidth();
+ PopItemWidth();
+ }
+ else if ((flags & ImGuiColorEditFlags_HEX) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
+ {
+ // RGB Hexadecimal Input
+ char buf[64];
+ if (alpha)
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255), ImClamp(i[3],0,255));
+ else
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0],0,255), ImClamp(i[1],0,255), ImClamp(i[2],0,255));
+ PushItemWidth(w_items_all);
+ if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))
+ {
+ value_changed = true;
+ char* p = buf;
+ while (*p == '#' || ImCharIsBlankA(*p))
+ p++;
+ i[0] = i[1] = i[2] = i[3] = 0;
+ if (alpha)
+ sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
+ else
+ sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+ PopItemWidth();
+ }
+
+ ImGuiWindow* picker_active_window = NULL;
+ if (!(flags & ImGuiColorEditFlags_NoSmallPreview))
+ {
+ if (!(flags & ImGuiColorEditFlags_NoInputs))
+ SameLine(0, style.ItemInnerSpacing.x);
+
+ const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f);
+ if (ColorButton("##ColorButton", col_v4, flags))
+ {
+ if (!(flags & ImGuiColorEditFlags_NoPicker))
+ {
+ // Store current color and open a picker
+ g.ColorPickerRef = col_v4;
+ OpenPopup("picker");
+ SetNextWindowPos(window->DC.LastItemRect.GetBL() + ImVec2(-1,style.ItemSpacing.y));
+ }
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+
+ if (BeginPopup("picker"))
+ {
+ picker_active_window = g.CurrentWindow;
+ if (label != label_display_end)
+ {
+ TextUnformatted(label, label_display_end);
+ Spacing();
+ }
+ ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
+ ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__InputsMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
+ PushItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
+ value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
+ PopItemWidth();
+ EndPopup();
+ }
+ }
+
+ if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
+ {
+ SameLine(0, style.ItemInnerSpacing.x);
+ TextUnformatted(label, label_display_end);
+ }
+
+ // Convert back
+ if (picker_active_window == NULL)
+ {
+ if (!value_changed_as_float)
+ for (int n = 0; n < 4; n++)
+ f[n] = i[n] / 255.0f;
+ if (flags & ImGuiColorEditFlags_HSV)
+ ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
+ if (value_changed)
+ {
+ col[0] = f[0];
+ col[1] = f[1];
+ col[2] = f[2];
+ if (alpha)
+ col[3] = f[3];
+ }
+ }
+
+ PopID();
+ EndGroup();
+
+ // Drag and Drop Target
+ // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
+ if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
+ {
+ if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
+ {
+ memcpy((float*)col, payload->Data, sizeof(float) * 3);
+ value_changed = true;
+ }
+ if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
+ {
+ memcpy((float*)col, payload->Data, sizeof(float) * components);
+ value_changed = true;
+ }
+ EndDragDropTarget();
+ }
+
+ // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4().
+ if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)
+ window->DC.LastItemId = g.ActiveId;
+
+ if (value_changed)
+ MarkItemEdited(window->DC.LastItemId);
+
+ return value_changed;
+}
+
+bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)
+{
+ float col4[4] = { col[0], col[1], col[2], 1.0f };
+ if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha))
+ return false;
+ col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
+ return true;
+}
+
+static inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b)
+{
+ float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
+ int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t);
+ int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t);
+ int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t);
+ return IM_COL32(r, g, b, 0xFF);
+}
+
+// Helper for ColorPicker4()
+// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
+// I spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding alltogether.
+void ImGui::RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, int rounding_corners_flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
+ {
+ ImU32 col_bg1 = GetColorU32(ImAlphaBlendColor(IM_COL32(204,204,204,255), col));
+ ImU32 col_bg2 = GetColorU32(ImAlphaBlendColor(IM_COL32(128,128,128,255), col));
+ window->DrawList->AddRectFilled(p_min, p_max, col_bg1, rounding, rounding_corners_flags);
+
+ int yi = 0;
+ for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)
+ {
+ float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);
+ if (y2 <= y1)
+ continue;
+ for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
+ {
+ float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
+ if (x2 <= x1)
+ continue;
+ int rounding_corners_flags_cell = 0;
+ if (y1 <= p_min.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_TopRight; }
+ if (y2 >= p_max.y) { if (x1 <= p_min.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotLeft; if (x2 >= p_max.x) rounding_corners_flags_cell |= ImDrawCornerFlags_BotRight; }
+ rounding_corners_flags_cell &= rounding_corners_flags;
+ window->DrawList->AddRectFilled(ImVec2(x1,y1), ImVec2(x2,y2), col_bg2, rounding_corners_flags_cell ? rounding : 0.0f, rounding_corners_flags_cell);
+ }
+ }
+ }
+ else
+ {
+ window->DrawList->AddRectFilled(p_min, p_max, col, rounding, rounding_corners_flags);
+ }
+}
+
+// Helper for ColorPicker4()
+static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w)
+{
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32_BLACK);
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32_WHITE);
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32_BLACK);
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32_WHITE);
+}
+
+// Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
+// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
+bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ ImDrawList* draw_list = window->DrawList;
+
+ ImGuiStyle& style = g.Style;
+ ImGuiIO& io = g.IO;
+
+ PushID(label);
+ BeginGroup();
+
+ if (!(flags & ImGuiColorEditFlags_NoSidePreview))
+ flags |= ImGuiColorEditFlags_NoSmallPreview;
+
+ // Context menu: display and store options.
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ ColorPickerOptionsPopup(col, flags);
+
+ // Read stored options
+ if (!(flags & ImGuiColorEditFlags__PickerMask))
+ flags |= ((g.ColorEditOptions & ImGuiColorEditFlags__PickerMask) ? g.ColorEditOptions : ImGuiColorEditFlags__OptionsDefault) & ImGuiColorEditFlags__PickerMask;
+ IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check that only 1 is selected
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
+
+ // Setup
+ int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
+ bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);
+ ImVec2 picker_pos = window->DC.CursorPos;
+ float square_sz = GetFrameHeight();
+ float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
+ float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
+ float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
+ float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
+ float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f);
+
+ float backup_initial_col[4];
+ memcpy(backup_initial_col, col, components * sizeof(float));
+
+ float wheel_thickness = sv_picker_size * 0.08f;
+ float wheel_r_outer = sv_picker_size * 0.50f;
+ float wheel_r_inner = wheel_r_outer - wheel_thickness;
+ ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size*0.5f);
+
+ // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
+ float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
+ ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
+ ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
+ ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
+
+ float H,S,V;
+ ColorConvertRGBtoHSV(col[0], col[1], col[2], H, S, V);
+
+ bool value_changed = false, value_changed_h = false, value_changed_sv = false;
+
+ PushItemFlag(ImGuiItemFlags_NoNav, true);
+ if (flags & ImGuiColorEditFlags_PickerHueWheel)
+ {
+ // Hue wheel + SV triangle logic
+ InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
+ if (IsItemActive())
+ {
+ ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
+ ImVec2 current_off = g.IO.MousePos - wheel_center;
+ float initial_dist2 = ImLengthSqr(initial_off);
+ if (initial_dist2 >= (wheel_r_inner-1)*(wheel_r_inner-1) && initial_dist2 <= (wheel_r_outer+1)*(wheel_r_outer+1))
+ {
+ // Interactive with Hue wheel
+ H = ImAtan2(current_off.y, current_off.x) / IM_PI*0.5f;
+ if (H < 0.0f)
+ H += 1.0f;
+ value_changed = value_changed_h = true;
+ }
+ float cos_hue_angle = ImCos(-H * 2.0f * IM_PI);
+ float sin_hue_angle = ImSin(-H * 2.0f * IM_PI);
+ if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
+ {
+ // Interacting with SV triangle
+ ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
+ if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
+ current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
+ float uu, vv, ww;
+ ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
+ V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
+ S = ImClamp(uu / V, 0.0001f, 1.0f);
+ value_changed = value_changed_sv = true;
+ }
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+ }
+ else if (flags & ImGuiColorEditFlags_PickerHueBar)
+ {
+ // SV rectangle logic
+ InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
+ if (IsItemActive())
+ {
+ S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size-1));
+ V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
+ value_changed = value_changed_sv = true;
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+
+ // Hue bar logic
+ SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
+ InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
+ if (IsItemActive())
+ {
+ H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
+ value_changed = value_changed_h = true;
+ }
+ }
+
+ // Alpha bar logic
+ if (alpha_bar)
+ {
+ SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
+ InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
+ if (IsItemActive())
+ {
+ col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size-1));
+ value_changed = true;
+ }
+ }
+ PopItemFlag(); // ImGuiItemFlags_NoNav
+
+ if (!(flags & ImGuiColorEditFlags_NoSidePreview))
+ {
+ SameLine(0, style.ItemInnerSpacing.x);
+ BeginGroup();
+ }
+
+ if (!(flags & ImGuiColorEditFlags_NoLabel))
+ {
+ const char* label_display_end = FindRenderedTextEnd(label);
+ if (label != label_display_end)
+ {
+ if ((flags & ImGuiColorEditFlags_NoSidePreview))
+ SameLine(0, style.ItemInnerSpacing.x);
+ TextUnformatted(label, label_display_end);
+ }
+ }
+
+ if (!(flags & ImGuiColorEditFlags_NoSidePreview))
+ {
+ PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
+ ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
+ if ((flags & ImGuiColorEditFlags_NoLabel))
+ Text("Current");
+ ColorButton("##current", col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2));
+ if (ref_col != NULL)
+ {
+ Text("Original");
+ ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
+ if (ColorButton("##original", ref_col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2)))
+ {
+ memcpy(col, ref_col, components * sizeof(float));
+ value_changed = true;
+ }
+ }
+ PopItemFlag();
+ EndGroup();
+ }
+
+ // Convert back color to RGB
+ if (value_changed_h || value_changed_sv)
+ ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10*1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]);
+
+ // R,G,B and H,S,V slider color editor
+ bool value_changed_fix_hue_wrap = false;
+ if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
+ {
+ PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
+ ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;
+ ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
+ if (flags & ImGuiColorEditFlags_RGB || (flags & ImGuiColorEditFlags__InputsMask) == 0)
+ if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_RGB))
+ {
+ // FIXME: Hackily differenciating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget.
+ // For the later we don't want to run the hue-wrap canceling code. If you are well versed in HSV picker please provide your input! (See #2050)
+ value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap);
+ value_changed = true;
+ }
+ if (flags & ImGuiColorEditFlags_HSV || (flags & ImGuiColorEditFlags__InputsMask) == 0)
+ value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_HSV);
+ if (flags & ImGuiColorEditFlags_HEX || (flags & ImGuiColorEditFlags__InputsMask) == 0)
+ value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_HEX);
+ PopItemWidth();
+ }
+
+ // Try to cancel hue wrap (after ColorEdit4 call), if any
+ if (value_changed_fix_hue_wrap)
+ {
+ float new_H, new_S, new_V;
+ ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
+ if (new_H <= 0 && H > 0)
+ {
+ if (new_V <= 0 && V != new_V)
+ ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
+ else if (new_S <= 0)
+ ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
+ }
+ }
+
+ ImVec4 hue_color_f(1, 1, 1, 1); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
+ ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
+ ImU32 col32_no_alpha = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 1.0f));
+
+ const ImU32 hue_colors[6+1] = { IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255), IM_COL32(0,255,255,255), IM_COL32(0,0,255,255), IM_COL32(255,0,255,255), IM_COL32(255,0,0,255) };
+ ImVec2 sv_cursor_pos;
+
+ if (flags & ImGuiColorEditFlags_PickerHueWheel)
+ {
+ // Render Hue Wheel
+ const float aeps = 1.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
+ const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
+ for (int n = 0; n < 6; n++)
+ {
+ const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps;
+ const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
+ const int vert_start_idx = draw_list->VtxBuffer.Size;
+ draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
+ draw_list->PathStroke(IM_COL32_WHITE, false, wheel_thickness);
+ const int vert_end_idx = draw_list->VtxBuffer.Size;
+
+ // Paint colors over existing vertices
+ ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
+ ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
+ ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, hue_colors[n], hue_colors[n+1]);
+ }
+
+ // Render Cursor + preview on Hue Wheel
+ float cos_hue_angle = ImCos(H * 2.0f * IM_PI);
+ float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
+ ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner+wheel_r_outer)*0.5f);
+ float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
+ int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
+ draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
+ draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad+1, IM_COL32(128,128,128,255), hue_cursor_segments);
+ draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, IM_COL32_WHITE, hue_cursor_segments);
+
+ // Render SV triangle (rotated according to hue)
+ ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
+ ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
+ ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
+ ImVec2 uv_white = GetFontTexUvWhitePixel();
+ draw_list->PrimReserve(6, 6);
+ draw_list->PrimVtx(tra, uv_white, hue_color32);
+ draw_list->PrimVtx(trb, uv_white, hue_color32);
+ draw_list->PrimVtx(trc, uv_white, IM_COL32_WHITE);
+ draw_list->PrimVtx(tra, uv_white, IM_COL32_BLACK_TRANS);
+ draw_list->PrimVtx(trb, uv_white, IM_COL32_BLACK);
+ draw_list->PrimVtx(trc, uv_white, IM_COL32_BLACK_TRANS);
+ draw_list->AddTriangle(tra, trb, trc, IM_COL32(128,128,128,255), 1.5f);
+ sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
+ }
+ else if (flags & ImGuiColorEditFlags_PickerHueBar)
+ {
+ // Render SV Square
+ draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_WHITE, hue_color32, hue_color32, IM_COL32_WHITE);
+ draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), IM_COL32_BLACK_TRANS, IM_COL32_BLACK_TRANS, IM_COL32_BLACK, IM_COL32_BLACK);
+ RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size,sv_picker_size), 0.0f);
+ sv_cursor_pos.x = ImClamp((float)(int)(picker_pos.x + ImSaturate(S) * sv_picker_size + 0.5f), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
+ sv_cursor_pos.y = ImClamp((float)(int)(picker_pos.y + ImSaturate(1 - V) * sv_picker_size + 0.5f), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
+
+ // Render Hue Bar
+ for (int i = 0; i < 6; ++i)
+ draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), hue_colors[i], hue_colors[i], hue_colors[i + 1], hue_colors[i + 1]);
+ float bar0_line_y = (float)(int)(picker_pos.y + H * sv_picker_size + 0.5f);
+ RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
+ RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
+ }
+
+ // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
+ float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
+ draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, col32_no_alpha, 12);
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad+1, IM_COL32(128,128,128,255), 12);
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, IM_COL32_WHITE, 12);
+
+ // Render alpha bar
+ if (alpha_bar)
+ {
+ float alpha = ImSaturate(col[3]);
+ ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
+ RenderColorRectWithAlphaCheckerboard(bar1_bb.Min, bar1_bb.Max, IM_COL32(0,0,0,0), bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
+ draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, col32_no_alpha, col32_no_alpha, col32_no_alpha & ~IM_COL32_A_MASK, col32_no_alpha & ~IM_COL32_A_MASK);
+ float bar1_line_y = (float)(int)(picker_pos.y + (1.0f - alpha) * sv_picker_size + 0.5f);
+ RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
+ RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f);
+ }
+
+ EndGroup();
+
+ if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0)
+ value_changed = false;
+ if (value_changed)
+ MarkItemEdited(window->DC.LastItemId);
+
+ PopID();
+
+ return value_changed;
+}
+
+// A little colored square. Return true when clicked.
+// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip.
+// 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip.
+bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiID id = window->GetID(desc_id);
+ float default_size = GetFrameHeight();
+ if (size.x == 0.0f)
+ size.x = default_size;
+ if (size.y == 0.0f)
+ size.y = default_size;
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf);
+
+ ImVec4 col_without_alpha(col.x, col.y, col.z, 1.0f);
+ float grid_step = ImMin(size.x, size.y) / 2.99f;
+ float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
+ ImRect bb_inner = bb;
+ float off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts.
+ bb_inner.Expand(off);
+ if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col.w < 1.0f)
+ {
+ float mid_x = (float)(int)((bb_inner.Min.x + bb_inner.Max.x) * 0.5f + 0.5f);
+ RenderColorRectWithAlphaCheckerboard(ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawCornerFlags_TopRight| ImDrawCornerFlags_BotRight);
+ window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_without_alpha), rounding, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotLeft);
+ }
+ else
+ {
+ // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha
+ ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col : col_without_alpha;
+ if (col_source.w < 1.0f)
+ RenderColorRectWithAlphaCheckerboard(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
+ else
+ window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding, ImDrawCornerFlags_All);
+ }
+ RenderNavHighlight(bb, id);
+ if (g.Style.FrameBorderSize > 0.0f)
+ RenderFrameBorder(bb.Min, bb.Max, rounding);
+ else
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
+
+ // Drag and Drop Source
+ // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test.
+ if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource())
+ {
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col, sizeof(float) * 3, ImGuiCond_Once);
+ else
+ SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col, sizeof(float) * 4, ImGuiCond_Once);
+ ColorButton(desc_id, col, flags);
+ SameLine();
+ TextUnformatted("Color");
+ EndDragDropSource();
+ }
+
+ // Tooltip
+ if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
+ ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
+
+ if (pressed)
+ MarkItemEdited(id);
+
+ return pressed;
+}
+
+void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if ((flags & ImGuiColorEditFlags__InputsMask) == 0)
+ flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__InputsMask;
+ if ((flags & ImGuiColorEditFlags__DataTypeMask) == 0)
+ flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__DataTypeMask;
+ if ((flags & ImGuiColorEditFlags__PickerMask) == 0)
+ flags |= ImGuiColorEditFlags__OptionsDefault & ImGuiColorEditFlags__PickerMask;
+ IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__InputsMask))); // Check only 1 option is selected
+ IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__DataTypeMask))); // Check only 1 option is selected
+ IM_ASSERT(ImIsPowerOfTwo((int)(flags & ImGuiColorEditFlags__PickerMask))); // Check only 1 option is selected
+ g.ColorEditOptions = flags;
+}
+
+// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
+void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+
+ int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
+ BeginTooltipEx(0, true);
+
+ const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
+ if (text_end > text)
+ {
+ TextUnformatted(text, text_end);
+ Separator();
+ }
+
+ ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2);
+ ColorButton("##preview", ImVec4(col[0], col[1], col[2], col[3]), (flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz);
+ SameLine();
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);
+ else
+ Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]);
+ EndTooltip();
+}
+
+void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
+{
+ bool allow_opt_inputs = !(flags & ImGuiColorEditFlags__InputsMask);
+ bool allow_opt_datatype = !(flags & ImGuiColorEditFlags__DataTypeMask);
+ if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
+ return;
+ ImGuiContext& g = *GImGui;
+ ImGuiColorEditFlags opts = g.ColorEditOptions;
+ if (allow_opt_inputs)
+ {
+ if (RadioButton("RGB", (opts & ImGuiColorEditFlags_RGB) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_RGB;
+ if (RadioButton("HSV", (opts & ImGuiColorEditFlags_HSV) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HSV;
+ if (RadioButton("HEX", (opts & ImGuiColorEditFlags_HEX) != 0)) opts = (opts & ~ImGuiColorEditFlags__InputsMask) | ImGuiColorEditFlags_HEX;
+ }
+ if (allow_opt_datatype)
+ {
+ if (allow_opt_inputs) Separator();
+ if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Uint8;
+ if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags__DataTypeMask) | ImGuiColorEditFlags_Float;
+ }
+
+ if (allow_opt_inputs || allow_opt_datatype)
+ Separator();
+ if (Button("Copy as..", ImVec2(-1,0)))
+ OpenPopup("Copy");
+ if (BeginPopup("Copy"))
+ {
+ int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
+ char buf[64];
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X", cr, cg, cb);
+ else
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "0x%02X%02X%02X%02X", cr, cg, cb, ca);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ EndPopup();
+ }
+
+ g.ColorEditOptions = opts;
+ EndPopup();
+}
+
+void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
+{
+ bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask);
+ bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
+ if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
+ return;
+ ImGuiContext& g = *GImGui;
+ if (allow_opt_picker)
+ {
+ ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
+ PushItemWidth(picker_size.x);
+ for (int picker_type = 0; picker_type < 2; picker_type++)
+ {
+ // Draw small/thumbnail version of each picker type (over an invisible button for selection)
+ if (picker_type > 0) Separator();
+ PushID(picker_type);
+ ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoOptions|ImGuiColorEditFlags_NoLabel|ImGuiColorEditFlags_NoSidePreview|(flags & ImGuiColorEditFlags_NoAlpha);
+ if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;
+ if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
+ ImVec2 backup_pos = GetCursorScreenPos();
+ if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
+ g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags__PickerMask) | (picker_flags & ImGuiColorEditFlags__PickerMask);
+ SetCursorScreenPos(backup_pos);
+ ImVec4 dummy_ref_col;
+ memcpy(&dummy_ref_col.x, ref_col, sizeof(float) * (picker_flags & ImGuiColorEditFlags_NoAlpha ? 3 : 4));
+ ColorPicker4("##dummypicker", &dummy_ref_col.x, picker_flags);
+ PopID();
+ }
+ PopItemWidth();
+ }
+ if (allow_opt_alpha_bar)
+ {
+ if (allow_opt_picker) Separator();
+ CheckboxFlags("Alpha Bar", (unsigned int*)&g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
+ }
+ EndPopup();
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
+//-------------------------------------------------------------------------
+// - TreeNode()
+// - TreeNodeV()
+// - TreeNodeEx()
+// - TreeNodeExV()
+// - TreeNodeBehavior() [Internal]
+// - TreePush()
+// - TreePop()
+// - TreeAdvanceToLabelPos()
+// - GetTreeNodeToLabelSpacing()
+// - SetNextTreeNodeOpen()
+// - CollapsingHeader()
+//-------------------------------------------------------------------------
+
+bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(str_id, 0, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(ptr_id, 0, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNode(const char* label)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+ return TreeNodeBehavior(window->GetID(label), 0, label, NULL);
+}
+
+bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
+{
+ return TreeNodeExV(str_id, 0, fmt, args);
+}
+
+bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
+{
+ return TreeNodeExV(ptr_id, 0, fmt, args);
+}
+
+bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ return TreeNodeBehavior(window->GetID(label), flags, label, NULL);
+}
+
+bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(str_id, flags, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(ptr_id, flags, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);
+}
+
+bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);
+}
+
+bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
+{
+ if (flags & ImGuiTreeNodeFlags_Leaf)
+ return true;
+
+ // We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions)
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiStorage* storage = window->DC.StateStorage;
+
+ bool is_open;
+ if (g.NextTreeNodeOpenCond != 0)
+ {
+ if (g.NextTreeNodeOpenCond & ImGuiCond_Always)
+ {
+ is_open = g.NextTreeNodeOpenVal;
+ storage->SetInt(id, is_open);
+ }
+ else
+ {
+ // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently.
+ const int stored_value = storage->GetInt(id, -1);
+ if (stored_value == -1)
+ {
+ is_open = g.NextTreeNodeOpenVal;
+ storage->SetInt(id, is_open);
+ }
+ else
+ {
+ is_open = stored_value != 0;
+ }
+ }
+ g.NextTreeNodeOpenCond = 0;
+ }
+ else
+ {
+ is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;
+ }
+
+ // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
+ // NB- If we are above max depth we still allow manually opened nodes to be logged.
+ if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && window->DC.TreeDepth < g.LogAutoExpandMaxDepth)
+ is_open = true;
+
+ return is_open;
+}
+
+bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
+ const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
+
+ if (!label_end)
+ label_end = FindRenderedTextEnd(label);
+ const ImVec2 label_size = CalcTextSize(label, label_end, false);
+
+ // We vertically grow up to current line height up the typical widget height.
+ const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
+ const float frame_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
+ ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height));
+ if (display_frame)
+ {
+ // Framed header expand a little outside the default padding
+ frame_bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
+ frame_bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
+ }
+
+ const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing
+ const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
+ ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
+
+ // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
+ // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not)
+ const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y);
+ bool is_open = TreeNodeBehaviorIsOpen(id, flags);
+ bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
+
+ // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
+ // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
+ // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
+ if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
+ window->DC.TreeDepthMayJumpToParentOnPop |= (1 << window->DC.TreeDepth);
+
+ bool item_add = ItemAdd(interact_bb, id);
+ window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
+ window->DC.LastItemDisplayRect = frame_bb;
+
+ if (!item_add)
+ {
+ if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
+ TreePushRawID(id);
+ IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
+ return is_open;
+ }
+
+ // Flags that affects opening behavior:
+ // - 0(default) ..................... single-click anywhere to open
+ // - OpenOnDoubleClick .............. double-click anywhere to open
+ // - OpenOnArrow .................... single-click on arrow to open
+ // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open
+ ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowItemOverlap) ? ImGuiButtonFlags_AllowItemOverlap : 0);
+ if (!is_leaf)
+ button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
+ if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
+ button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0);
+
+ bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
+ if (!is_leaf)
+ {
+ bool toggled = false;
+ if (pressed)
+ {
+ toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) || (g.NavActivateId == id);
+ if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
+ toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover);
+ if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
+ toggled |= g.IO.MouseDoubleClicked[0];
+ if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again.
+ toggled = false;
+ }
+
+ if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open)
+ {
+ toggled = true;
+ NavMoveRequestCancel();
+ }
+ if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
+ {
+ toggled = true;
+ NavMoveRequestCancel();
+ }
+
+ if (toggled)
+ {
+ is_open = !is_open;
+ window->DC.StateStorage->SetInt(id, is_open);
+ }
+ }
+ if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
+ SetItemAllowOverlap();
+
+ // Render
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+ const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y);
+ if (display_frame)
+ {
+ // Framed type
+ RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding);
+ RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin);
+ RenderArrow(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
+ if (g.LogEnabled)
+ {
+ // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
+ const char log_prefix[] = "\n##";
+ const char log_suffix[] = "##";
+ LogRenderedText(&text_pos, log_prefix, log_prefix+3);
+ RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
+ LogRenderedText(&text_pos, log_suffix+1, log_suffix+3);
+ }
+ else
+ {
+ RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
+ }
+ }
+ else
+ {
+ // Unframed typed for tree nodes
+ if (hovered || (flags & ImGuiTreeNodeFlags_Selected))
+ {
+ RenderFrame(frame_bb.Min, frame_bb.Max, col, false);
+ RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin);
+ }
+
+ if (flags & ImGuiTreeNodeFlags_Bullet)
+ RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y));
+ else if (!is_leaf)
+ RenderArrow(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
+ if (g.LogEnabled)
+ LogRenderedText(&text_pos, ">");
+ RenderText(text_pos, label, label_end, false);
+ }
+
+ if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
+ TreePushRawID(id);
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
+ return is_open;
+}
+
+void ImGui::TreePush(const char* str_id)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ Indent();
+ window->DC.TreeDepth++;
+ PushID(str_id ? str_id : "#TreePush");
+}
+
+void ImGui::TreePush(const void* ptr_id)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ Indent();
+ window->DC.TreeDepth++;
+ PushID(ptr_id ? ptr_id : (const void*)"#TreePush");
+}
+
+void ImGui::TreePushRawID(ImGuiID id)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ Indent();
+ window->DC.TreeDepth++;
+ window->IDStack.push_back(id);
+}
+
+void ImGui::TreePop()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ Unindent();
+
+ window->DC.TreeDepth--;
+ if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
+ if (g.NavIdIsAlive && (window->DC.TreeDepthMayJumpToParentOnPop & (1 << window->DC.TreeDepth)))
+ {
+ SetNavID(window->IDStack.back(), g.NavLayer);
+ NavMoveRequestCancel();
+ }
+ window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1;
+
+ IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
+ PopID();
+}
+
+void ImGui::TreeAdvanceToLabelPos()
+{
+ ImGuiContext& g = *GImGui;
+ g.CurrentWindow->DC.CursorPos.x += GetTreeNodeToLabelSpacing();
+}
+
+// Horizontal distance preceding label when using TreeNode() or Bullet()
+float ImGui::GetTreeNodeToLabelSpacing()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + (g.Style.FramePadding.x * 2.0f);
+}
+
+void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.CurrentWindow->SkipItems)
+ return;
+ g.NextTreeNodeOpenVal = is_open;
+ g.NextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always;
+}
+
+// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).
+// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode().
+bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label);
+}
+
+bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ if (p_open && !*p_open)
+ return false;
+
+ ImGuiID id = window->GetID(label);
+ bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label);
+ if (p_open)
+ {
+ // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
+ ImGuiContext& g = *GImGui;
+ ImGuiItemHoveredDataBackup last_item_backup;
+ float button_radius = g.FontSize * 0.5f;
+ ImVec2 button_center = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_radius, window->DC.LastItemRect.GetCenter().y);
+ if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), button_center, button_radius))
+ *p_open = false;
+ last_item_backup.Restore();
+ }
+
+ return is_open;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Selectable
+//-------------------------------------------------------------------------
+// - Selectable()
+//-------------------------------------------------------------------------
+
+// Tip: pass a non-visible label (e.g. "##dummy") then you can use the space to draw other text or image.
+// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
+bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped.
+ PopClipRect();
+
+ ImGuiID id = window->GetID(label);
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+ ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
+ ImVec2 pos = window->DC.CursorPos;
+ pos.y += window->DC.CurrentLineTextBaseOffset;
+ ImRect bb_inner(pos, pos + size);
+ ItemSize(bb_inner);
+
+ // Fill horizontal space.
+ ImVec2 window_padding = window->WindowPadding;
+ float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x;
+ float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - window->DC.CursorPos.x);
+ ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y);
+ ImRect bb(pos, pos + size_draw);
+ if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth))
+ bb.Max.x += window_padding.x;
+
+ // Selectables are tightly packed together, we extend the box to cover spacing between selectable.
+ float spacing_L = (float)(int)(style.ItemSpacing.x * 0.5f);
+ float spacing_U = (float)(int)(style.ItemSpacing.y * 0.5f);
+ float spacing_R = style.ItemSpacing.x - spacing_L;
+ float spacing_D = style.ItemSpacing.y - spacing_U;
+ bb.Min.x -= spacing_L;
+ bb.Min.y -= spacing_U;
+ bb.Max.x += spacing_R;
+ bb.Max.y += spacing_D;
+ if (!ItemAdd(bb, id))
+ {
+ if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet)
+ PushColumnClipRect();
+ return false;
+ }
+
+ // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
+ ImGuiButtonFlags button_flags = 0;
+ if (flags & ImGuiSelectableFlags_NoHoldingActiveID) button_flags |= ImGuiButtonFlags_NoHoldingActiveID;
+ if (flags & ImGuiSelectableFlags_PressedOnClick) button_flags |= ImGuiButtonFlags_PressedOnClick;
+ if (flags & ImGuiSelectableFlags_PressedOnRelease) button_flags |= ImGuiButtonFlags_PressedOnRelease;
+ if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled;
+ if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
+ if (flags & ImGuiSelectableFlags_Disabled)
+ selected = false;
+
+ // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets)
+ if (pressed || hovered)
+ if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
+ {
+ g.NavDisableHighlight = true;
+ SetNavID(id, window->DC.NavLayerCurrent);
+ }
+ if (pressed)
+ MarkItemEdited(id);
+
+ // Render
+ if (hovered || selected)
+ {
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+ RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
+ RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
+ }
+
+ if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet)
+ {
+ PushColumnClipRect();
+ bb.Max.x -= (GetContentRegionMax().x - max_x);
+ }
+
+ if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
+ RenderTextClipped(bb_inner.Min, bb.Max, label, NULL, &label_size, ImVec2(0.0f,0.0f));
+ if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
+
+ // Automatically close popups
+ if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
+ CloseCurrentPopup();
+ return pressed;
+}
+
+bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
+{
+ if (Selectable(label, *p_selected, flags, size_arg))
+ {
+ *p_selected = !*p_selected;
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: ListBox
+//-------------------------------------------------------------------------
+// - ListBox()
+// - ListBoxHeader()
+// - ListBoxFooter()
+//-------------------------------------------------------------------------
+
+// FIXME: In principle this function should be called BeginListBox(). We should rename it after re-evaluating if we want to keep the same signature.
+// Helper to calculate the size of a listbox and display a label on the right.
+// Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an non-visible label e.g. "##empty"
+bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ const ImGuiStyle& style = GetStyle();
+ const ImGuiID id = GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
+ ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y);
+ ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
+ ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
+ ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+ window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy.
+
+ BeginGroup();
+ if (label_size.x > 0)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ BeginChildFrame(id, frame_bb.GetSize());
+ return true;
+}
+
+// FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
+bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
+{
+ // Size default to hold ~7.25 items.
+ // We add +25% worth of item height to allow the user to see at a glance if there are more items up/down, without looking at the scrollbar.
+ // We don't add this extra bit if items_count <= height_in_items. It is slightly dodgy, because it means a dynamic list of items will make the widget resize occasionally when it crosses that size.
+ // I am expecting that someone will come and complain about this behavior in a remote future, then we can advise on a better solution.
+ if (height_in_items < 0)
+ height_in_items = ImMin(items_count, 7);
+ const ImGuiStyle& style = GetStyle();
+ float height_in_items_f = (height_in_items < items_count) ? (height_in_items + 0.25f) : (height_in_items + 0.00f);
+
+ // We include ItemSpacing.y so that a list sized for the exact number of items doesn't make a scrollbar appears. We could also enforce that by passing a flag to BeginChild().
+ ImVec2 size;
+ size.x = 0.0f;
+ size.y = GetTextLineHeightWithSpacing() * height_in_items_f + style.FramePadding.y * 2.0f;
+ return ListBoxHeader(label, size);
+}
+
+// FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
+void ImGui::ListBoxFooter()
+{
+ ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow;
+ const ImRect bb = parent_window->DC.LastItemRect;
+ const ImGuiStyle& style = GetStyle();
+
+ EndChildFrame();
+
+ // Redeclare item size so that it includes the label (we have stored the full size in LastItemRect)
+ // We call SameLine() to restore DC.CurrentLine* data
+ SameLine();
+ parent_window->DC.CursorPos = bb.Min;
+ ItemSize(bb, style.FramePadding.y);
+ EndGroup();
+}
+
+bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items)
+{
+ const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);
+ return value_changed;
+}
+
+bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
+{
+ if (!ListBoxHeader(label, items_count, height_in_items))
+ return false;
+
+ // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper.
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
+ while (clipper.Step())
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ {
+ const bool item_selected = (i == *current_item);
+ const char* item_text;
+ if (!items_getter(data, i, &item_text))
+ item_text = "*Unknown item*";
+
+ PushID(i);
+ if (Selectable(item_text, item_selected))
+ {
+ *current_item = i;
+ value_changed = true;
+ }
+ if (item_selected)
+ SetItemDefaultFocus();
+ PopID();
+ }
+ ListBoxFooter();
+ if (value_changed)
+ MarkItemEdited(g.CurrentWindow->DC.LastItemId);
+
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: PlotLines, PlotHistogram
+//-------------------------------------------------------------------------
+// - PlotEx() [Internal]
+// - PlotLines()
+// - PlotHistogram()
+//-------------------------------------------------------------------------
+
+void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ if (graph_size.x == 0.0f)
+ graph_size.x = CalcItemWidth();
+ if (graph_size.y == 0.0f)
+ graph_size.y = label_size.y + (style.FramePadding.y * 2);
+
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(graph_size.x, graph_size.y));
+ const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, 0, &frame_bb))
+ return;
+ const bool hovered = ItemHoverable(inner_bb, 0);
+
+ // Determine scale from values if not specified
+ if (scale_min == FLT_MAX || scale_max == FLT_MAX)
+ {
+ float v_min = FLT_MAX;
+ float v_max = -FLT_MAX;
+ for (int i = 0; i < values_count; i++)
+ {
+ const float v = values_getter(data, i);
+ v_min = ImMin(v_min, v);
+ v_max = ImMax(v_max, v);
+ }
+ if (scale_min == FLT_MAX)
+ scale_min = v_min;
+ if (scale_max == FLT_MAX)
+ scale_max = v_max;
+ }
+
+ RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
+
+ if (values_count > 0)
+ {
+ int res_w = ImMin((int)graph_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
+ int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
+
+ // Tooltip on hover
+ int v_hovered = -1;
+ if (hovered)
+ {
+ const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
+ const int v_idx = (int)(t * item_count);
+ IM_ASSERT(v_idx >= 0 && v_idx < values_count);
+
+ const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
+ const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
+ if (plot_type == ImGuiPlotType_Lines)
+ SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx+1, v1);
+ else if (plot_type == ImGuiPlotType_Histogram)
+ SetTooltip("%d: %8.4g", v_idx, v0);
+ v_hovered = v_idx;
+ }
+
+ const float t_step = 1.0f / (float)res_w;
+ const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min));
+
+ float v0 = values_getter(data, (0 + values_offset) % values_count);
+ float t0 = 0.0f;
+ ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle
+ float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
+
+ const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
+ const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
+
+ for (int n = 0; n < res_w; n++)
+ {
+ const float t1 = t0 + t_step;
+ const int v1_idx = (int)(t0 * item_count + 0.5f);
+ IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
+ const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
+ const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) );
+
+ // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
+ ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
+ ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
+ if (plot_type == ImGuiPlotType_Lines)
+ {
+ window->DrawList->AddLine(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
+ }
+ else if (plot_type == ImGuiPlotType_Histogram)
+ {
+ if (pos1.x >= pos0.x + 2.0f)
+ pos1.x -= 1.0f;
+ window->DrawList->AddRectFilled(pos0, pos1, v_hovered == v1_idx ? col_hovered : col_base);
+ }
+
+ t0 = t1;
+ tp0 = tp1;
+ }
+ }
+
+ // Text overlay
+ if (overlay_text)
+ RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f,0.0f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
+}
+
+struct ImGuiPlotArrayGetterData
+{
+ const float* Values;
+ int Stride;
+
+ ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; }
+};
+
+static float Plot_ArrayGetter(void* data, int idx)
+{
+ ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data;
+ const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
+ return v;
+}
+
+void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
+{
+ ImGuiPlotArrayGetterData data(values, stride);
+ PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
+{
+ PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
+{
+ ImGuiPlotArrayGetterData data(values, stride);
+ PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
+{
+ PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Value helpers
+// Those is not very useful, legacy API.
+//-------------------------------------------------------------------------
+// - Value()
+//-------------------------------------------------------------------------
+
+void ImGui::Value(const char* prefix, bool b)
+{
+ Text("%s: %s", prefix, (b ? "true" : "false"));
+}
+
+void ImGui::Value(const char* prefix, int v)
+{
+ Text("%s: %d", prefix, v);
+}
+
+void ImGui::Value(const char* prefix, unsigned int v)
+{
+ Text("%s: %d", prefix, v);
+}
+
+void ImGui::Value(const char* prefix, float v, const char* float_format)
+{
+ if (float_format)
+ {
+ char fmt[64];
+ ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format);
+ Text(fmt, prefix, v);
+ }
+ else
+ {
+ Text("%s: %.3f", prefix, v);
+ }
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] MenuItem, BeginMenu, EndMenu, etc.
+//-------------------------------------------------------------------------
+// - ImGuiMenuColumns [Internal]
+// - BeginMainMenuBar()
+// - EndMainMenuBar()
+// - BeginMenuBar()
+// - EndMenuBar()
+// - BeginMenu()
+// - EndMenu()
+// - MenuItem()
+//-------------------------------------------------------------------------
+
+// Helpers for internal use
+ImGuiMenuColumns::ImGuiMenuColumns()
+{
+ Count = 0;
+ Spacing = Width = NextWidth = 0.0f;
+ memset(Pos, 0, sizeof(Pos));
+ memset(NextWidths, 0, sizeof(NextWidths));
+}
+
+void ImGuiMenuColumns::Update(int count, float spacing, bool clear)
+{
+ IM_ASSERT(Count <= IM_ARRAYSIZE(Pos));
+ Count = count;
+ Width = NextWidth = 0.0f;
+ Spacing = spacing;
+ if (clear) memset(NextWidths, 0, sizeof(NextWidths));
+ for (int i = 0; i < Count; i++)
+ {
+ if (i > 0 && NextWidths[i] > 0.0f)
+ Width += Spacing;
+ Pos[i] = (float)(int)Width;
+ Width += NextWidths[i];
+ NextWidths[i] = 0.0f;
+ }
+}
+
+float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double
+{
+ NextWidth = 0.0f;
+ NextWidths[0] = ImMax(NextWidths[0], w0);
+ NextWidths[1] = ImMax(NextWidths[1], w1);
+ NextWidths[2] = ImMax(NextWidths[2], w2);
+ for (int i = 0; i < 3; i++)
+ NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);
+ return ImMax(Width, NextWidth);
+}
+
+float ImGuiMenuColumns::CalcExtraSpace(float avail_w)
+{
+ return ImMax(0.0f, avail_w - Width);
+}
+
+// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
+bool ImGui::BeginMainMenuBar()
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
+ SetNextWindowPos(ImVec2(0.0f, 0.0f));
+ SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y));
+ PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+ PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0));
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
+ bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar();
+ PopStyleVar(2);
+ g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
+ if (!is_open)
+ {
+ End();
+ return false;
+ }
+ return true;
+}
+
+void ImGui::EndMainMenuBar()
+{
+ EndMenuBar();
+
+ // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window
+ ImGuiContext& g = *GImGui;
+ if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0)
+ FocusPreviousWindowIgnoringOne(g.NavWindow);
+
+ End();
+}
+
+bool ImGui::BeginMenuBar()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+ if (!(window->Flags & ImGuiWindowFlags_MenuBar))
+ return false;
+
+ IM_ASSERT(!window->DC.MenuBarAppending);
+ BeginGroup(); // Backup position on layer 0
+ PushID("##menubar");
+
+ // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
+ // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy.
+ ImRect bar_rect = window->MenuBarRect();
+ ImRect clip_rect(ImFloor(bar_rect.Min.x + 0.5f), ImFloor(bar_rect.Min.y + window->WindowBorderSize + 0.5f), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding) + 0.5f), ImFloor(bar_rect.Max.y + 0.5f));
+ clip_rect.ClipWith(window->OuterRectClipped);
+ PushClipRect(clip_rect.Min, clip_rect.Max, false);
+
+ window->DC.CursorPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y);
+ window->DC.LayoutType = ImGuiLayoutType_Horizontal;
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
+ window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
+ window->DC.MenuBarAppending = true;
+ AlignTextToFramePadding();
+ return true;
+}
+
+void ImGui::EndMenuBar()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ImGuiContext& g = *GImGui;
+
+ // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
+ if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
+ {
+ ImGuiWindow* nav_earliest_child = g.NavWindow;
+ while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
+ nav_earliest_child = nav_earliest_child->ParentWindow;
+ if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None)
+ {
+ // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
+ // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
+ IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check
+ FocusWindow(window);
+ SetNavIDWithRectRel(window->NavLastIds[1], 1, window->NavRectRel[1]);
+ g.NavLayer = ImGuiNavLayer_Menu;
+ g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
+ g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
+ NavMoveRequestCancel();
+ }
+ }
+
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar);
+ IM_ASSERT(window->DC.MenuBarAppending);
+ PopClipRect();
+ PopID();
+ window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
+ window->DC.GroupStack.back().AdvanceCursor = false;
+ EndGroup(); // Restore position on layer 0
+ window->DC.LayoutType = ImGuiLayoutType_Vertical;
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+ window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
+ window->DC.MenuBarAppending = false;
+}
+
+bool ImGui::BeginMenu(const char* label, bool enabled)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ bool pressed;
+ bool menu_is_open = IsPopupOpen(id);
+ bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
+ ImGuiWindow* backed_nav_window = g.NavWindow;
+ if (menuset_is_open)
+ g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
+
+ // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu (using FindBestWindowPosForPopup).
+ ImVec2 popup_pos, pos = window->DC.CursorPos;
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
+ {
+ // Menu inside an horizontal menu bar
+ // Selectable extend their highlight by half ItemSpacing in each direction.
+ // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
+ popup_pos = ImVec2(pos.x - 1.0f - (float)(int)(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
+ window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f);
+ float w = label_size.x;
+ pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
+ PopStyleVar();
+ window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
+ }
+ else
+ {
+ // Menu inside a menu
+ popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
+ float w = window->MenuColumns.DeclColumns(label_size.x, 0.0f, (float)(int)(g.FontSize * 1.20f)); // Feedback to next frame
+ float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
+ pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_PressedOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
+ if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
+ RenderArrow(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right);
+ if (!enabled) PopStyleColor();
+ }
+
+ const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id);
+ if (menuset_is_open)
+ g.NavWindow = backed_nav_window;
+
+ bool want_open = false, want_close = false;
+ if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
+ {
+ // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
+ bool moving_within_opened_triangle = false;
+ if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].ParentWindow == window && !(window->Flags & ImGuiWindowFlags_MenuBar))
+ {
+ if (ImGuiWindow* next_window = g.OpenPopupStack[g.BeginPopupStack.Size].Window)
+ {
+ ImRect next_window_rect = next_window->Rect();
+ ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
+ ImVec2 tb = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
+ ImVec2 tc = (window->Pos.x < next_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
+ float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack.
+ ta.x += (window->Pos.x < next_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues
+ tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
+ tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);
+ moving_within_opened_triangle = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
+ //window->DrawList->PushClipRectFullScreen(); window->DrawList->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); window->DrawList->PopClipRect(); // Debug
+ }
+ }
+
+ want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle);
+ want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed);
+
+ if (g.NavActivateId == id)
+ {
+ want_close = menu_is_open;
+ want_open = !menu_is_open;
+ }
+ if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
+ {
+ want_open = true;
+ NavMoveRequestCancel();
+ }
+ }
+ else
+ {
+ // Menu bar
+ if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it
+ {
+ want_close = true;
+ want_open = menu_is_open = false;
+ }
+ else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others
+ {
+ want_open = true;
+ }
+ else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
+ {
+ want_open = true;
+ NavMoveRequestCancel();
+ }
+ }
+
+ if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
+ want_close = true;
+ if (want_close && IsPopupOpen(id))
+ ClosePopupToLevel(g.BeginPopupStack.Size, true);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
+
+ if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
+ {
+ // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
+ OpenPopup(label);
+ return false;
+ }
+
+ menu_is_open |= want_open;
+ if (want_open)
+ OpenPopup(label);
+
+ if (menu_is_open)
+ {
+ // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
+ SetNextWindowPos(popup_pos, ImGuiCond_Always);
+ ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
+ if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
+ flags |= ImGuiWindowFlags_ChildWindow;
+ menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
+ }
+
+ return menu_is_open;
+}
+
+void ImGui::EndMenu()
+{
+ // Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
+ // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs.
+ // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction.
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
+ {
+ ClosePopupToLevel(g.BeginPopupStack.Size, true);
+ NavMoveRequestCancel();
+ }
+
+ EndPopup();
+}
+
+bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ ImVec2 pos = window->DC.CursorPos;
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ ImGuiSelectableFlags flags = ImGuiSelectableFlags_PressedOnRelease | (enabled ? 0 : ImGuiSelectableFlags_Disabled);
+ bool pressed;
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
+ {
+ // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
+ // Note that in this situation we render neither the shortcut neither the selected tick mark
+ float w = label_size.x;
+ window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * 0.5f);
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, style.ItemSpacing * 2.0f);
+ pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
+ PopStyleVar();
+ window->DC.CursorPos.x += (float)(int)(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
+ }
+ else
+ {
+ ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f);
+ float w = window->MenuColumns.DeclColumns(label_size.x, shortcut_size.x, (float)(int)(g.FontSize * 1.20f)); // Feedback for next frame
+ float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
+ pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f));
+ if (shortcut_size.x > 0.0f)
+ {
+ PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
+ RenderText(pos + ImVec2(window->MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);
+ PopStyleColor();
+ }
+ if (selected)
+ RenderCheckMark(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
+ }
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
+ return pressed;
+}
+
+bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled)
+{
+ if (MenuItem(label, shortcut, p_selected ? *p_selected : false, enabled))
+ {
+ if (p_selected)
+ *p_selected = !*p_selected;
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
+//-------------------------------------------------------------------------
+// [BETA API] API may evolve! This code has been extracted out of the Docking branch,
+// and some of the construct which are not used in Master may be left here to facilitate merging.
+//-------------------------------------------------------------------------
+// - BeginTabBar()
+// - BeginTabBarEx() [Internal]
+// - EndTabBar()
+// - TabBarLayout() [Internal]
+// - TabBarCalcTabID() [Internal]
+// - TabBarCalcMaxTabWidth() [Internal]
+// - TabBarFindTabById() [Internal]
+// - TabBarRemoveTab() [Internal]
+// - TabBarCloseTab() [Internal]
+// - TabBarScrollClamp()v
+// - TabBarScrollToTab() [Internal]
+// - TabBarQueueChangeTabOrder() [Internal]
+// - TabBarScrollingButtons() [Internal]
+//-------------------------------------------------------------------------
+
+namespace ImGui
+{
+ static void TabBarLayout(ImGuiTabBar* tab_bar);
+ static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label);
+ static float TabBarCalcMaxTabWidth();
+ static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
+ static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
+ static ImGuiTabItem* TabBarScrollingButtons(ImGuiTabBar* tab_bar);
+}
+
+ImGuiTabBar::ImGuiTabBar()
+{
+ ID = 0;
+ SelectedTabId = NextSelectedTabId = VisibleTabId = 0;
+ CurrFrameVisible = PrevFrameVisible = -1;
+ OffsetMax = OffsetNextTab = 0.0f;
+ ScrollingAnim = ScrollingTarget = 0.0f;
+ Flags = ImGuiTabBarFlags_None;
+ ReorderRequestTabId = 0;
+ ReorderRequestDir = 0;
+ WantLayout = VisibleTabWasSubmitted = false;
+ LastTabItemIdx = -1;
+}
+
+static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const void* rhs)
+{
+ const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
+ const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
+ return (int)(a->Offset - b->Offset);
+}
+
+static int IMGUI_CDECL TabBarSortItemComparer(const void* lhs, const void* rhs)
+{
+ const ImGuiTabBarSortItem* a = (const ImGuiTabBarSortItem*)lhs;
+ const ImGuiTabBarSortItem* b = (const ImGuiTabBarSortItem*)rhs;
+ if (int d = (int)(b->Width - a->Width))
+ return d;
+ return (b->Index - a->Index);
+}
+
+bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ ImGuiID id = window->GetID(str_id);
+ ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id);
+ ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->InnerClipRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2);
+ tab_bar->ID = id;
+ return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused);
+}
+
+bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImGuiTabBarFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ if ((flags & ImGuiTabBarFlags_DockNode) == 0)
+ window->IDStack.push_back(tab_bar->ID);
+
+ g.CurrentTabBar.push_back(tab_bar);
+ if (tab_bar->CurrFrameVisible == g.FrameCount)
+ {
+ //IMGUI_DEBUG_LOG("BeginTabBarEx already called this frame\n", g.FrameCount);
+ IM_ASSERT(0);
+ return true;
+ }
+
+ // When toggling back from ordered to manually-reorderable, shuffle tabs to enforce the last visible order.
+ // Otherwise, the most recently inserted tabs would move at the end of visible list which can be a little too confusing or magic for the user.
+ if ((flags & ImGuiTabBarFlags_Reorderable) && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1 && tab_bar->PrevFrameVisible != -1)
+ ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByVisibleOffset);
+
+ // Flags
+ if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
+ flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
+
+ tab_bar->Flags = flags;
+ tab_bar->BarRect = tab_bar_bb;
+ tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab()
+ tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
+ tab_bar->CurrFrameVisible = g.FrameCount;
+
+ // Layout
+ ItemSize(ImVec2(tab_bar->OffsetMax, tab_bar->BarRect.GetHeight()));
+ window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
+
+ // Draw separator
+ const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_Tab);
+ const float y = tab_bar->BarRect.Max.y - 1.0f;
+ {
+ const float separator_min_x = tab_bar->BarRect.Min.x - ((flags & ImGuiTabBarFlags_DockNodeIsDockSpace) ? 0.0f : window->WindowPadding.x);
+ const float separator_max_x = tab_bar->BarRect.Max.x + ((flags & ImGuiTabBarFlags_DockNodeIsDockSpace) ? 0.0f : window->WindowPadding.x);
+ window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
+ }
+ return true;
+}
+
+void ImGui::EndTabBar()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ IM_ASSERT(!g.CurrentTabBar.empty()); // Mismatched BeginTabBar/EndTabBar
+ ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
+ if (tab_bar->WantLayout)
+ TabBarLayout(tab_bar);
+
+ // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed().
+ const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
+ if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing)
+ tab_bar->ContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f);
+ else
+ window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->ContentsHeight;
+
+ if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
+ PopID();
+ g.CurrentTabBar.pop_back();
+}
+
+// This is called only once a frame before by the first call to ItemTab()
+// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
+static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
+{
+ ImGuiContext& g = *GImGui;
+ tab_bar->WantLayout = false;
+
+ // Garbage collect
+ int tab_dst_n = 0;
+ for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n];
+ if (tab->LastFrameVisible < tab_bar->PrevFrameVisible)
+ {
+ if (tab->ID == tab_bar->SelectedTabId)
+ tab_bar->SelectedTabId = 0;
+ continue;
+ }
+ if (tab_dst_n != tab_src_n)
+ tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n];
+ tab_dst_n++;
+ }
+ if (tab_bar->Tabs.Size != tab_dst_n)
+ tab_bar->Tabs.resize(tab_dst_n);
+
+ // Setup next selected tab
+ ImGuiID scroll_track_selected_tab_id = 0;
+ if (tab_bar->NextSelectedTabId)
+ {
+ tab_bar->SelectedTabId = tab_bar->NextSelectedTabId;
+ tab_bar->NextSelectedTabId = 0;
+ scroll_track_selected_tab_id = tab_bar->SelectedTabId;
+ }
+
+ // Process order change request (we could probably process it when requested but it's just saner to do it in a single spot).
+ if (tab_bar->ReorderRequestTabId != 0)
+ {
+ if (ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId))
+ {
+ //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
+ int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
+ if (tab2_order >= 0 && tab2_order < tab_bar->Tabs.Size)
+ {
+ ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
+ ImGuiTabItem item_tmp = *tab1;
+ *tab1 = *tab2;
+ *tab2 = item_tmp;
+ if (tab2->ID == tab_bar->SelectedTabId)
+ scroll_track_selected_tab_id = tab2->ID;
+ tab1 = tab2 = NULL;
+ }
+ if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
+ MarkIniSettingsDirty();
+ }
+ tab_bar->ReorderRequestTabId = 0;
+ }
+
+ ImVector<ImGuiTabBarSortItem>& width_sort_buffer = g.TabSortByWidthBuffer;
+ width_sort_buffer.resize(tab_bar->Tabs.Size);
+
+ // Compute ideal widths
+ float width_total_contents = 0.0f;
+ ImGuiTabItem* most_recently_selected_tab = NULL;
+ bool found_selected_tab_id = false;
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible);
+
+ if (most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected)
+ most_recently_selected_tab = tab;
+ if (tab->ID == tab_bar->SelectedTabId)
+ found_selected_tab_id = true;
+
+ // Refresh tab width immediately if we can (for manual tab bar, WidthContent will lag by one frame which is mostly noticeable when changing style.FramePadding.x)
+ // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
+ // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
+ width_total_contents += (tab_n > 0 ? g.Style.ItemInnerSpacing.x : 0.0f) + tab->WidthContents;
+
+ // Store data so we can build an array sorted by width if we need to shrink tabs down
+ width_sort_buffer[tab_n].Index = tab_n;
+ width_sort_buffer[tab_n].Width = tab->WidthContents;
+ }
+
+ // Compute width
+ const float width_avail = tab_bar->BarRect.GetWidth();
+ float width_excess = (width_avail < width_total_contents) ? (width_total_contents - width_avail) : 0.0f;
+ if (width_excess > 0.0f && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown))
+ {
+ // If we don't have enough room, resize down the largest tabs first
+ if (tab_bar->Tabs.Size > 1)
+ ImQsort(width_sort_buffer.Data, (size_t)width_sort_buffer.Size, sizeof(ImGuiTabBarSortItem), TabBarSortItemComparer);
+ int tab_count_same_width = 1;
+ while (width_excess > 0.0f && tab_count_same_width < tab_bar->Tabs.Size)
+ {
+ while (tab_count_same_width < tab_bar->Tabs.Size && width_sort_buffer[0].Width == width_sort_buffer[tab_count_same_width].Width)
+ tab_count_same_width++;
+ float width_to_remove_per_tab_max = (tab_count_same_width < tab_bar->Tabs.Size) ? (width_sort_buffer[0].Width - width_sort_buffer[tab_count_same_width].Width) : (width_sort_buffer[0].Width - 1.0f);
+ float width_to_remove_per_tab = ImMin(width_excess / tab_count_same_width, width_to_remove_per_tab_max);
+ for (int tab_n = 0; tab_n < tab_count_same_width; tab_n++)
+ width_sort_buffer[tab_n].Width -= width_to_remove_per_tab;
+ width_excess -= width_to_remove_per_tab * tab_count_same_width;
+ }
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ tab_bar->Tabs[width_sort_buffer[tab_n].Index].Width = (float)(int)width_sort_buffer[tab_n].Width;
+ }
+ else
+ {
+ const float tab_max_width = TabBarCalcMaxTabWidth();
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ tab->Width = ImMin(tab->WidthContents, tab_max_width);
+ }
+ }
+
+ // Layout all active tabs
+ float offset_x = 0.0f;
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ tab->Offset = offset_x;
+ if (scroll_track_selected_tab_id == 0 && g.NavJustMovedToId == tab->ID)
+ scroll_track_selected_tab_id = tab->ID;
+ offset_x += tab->Width + g.Style.ItemInnerSpacing.x;
+ }
+ tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
+ tab_bar->OffsetNextTab = 0.0f;
+
+ // Horizontal scrolling buttons
+ const bool scrolling_buttons = (tab_bar->OffsetMax > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll);
+ if (scrolling_buttons)
+ if (ImGuiTabItem* tab_to_select = TabBarScrollingButtons(tab_bar)) // NB: Will alter BarRect.Max.x!
+ scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
+
+ // If we have lost the selected tab, select the next most recently active one
+ if (found_selected_tab_id == false)
+ tab_bar->SelectedTabId = 0;
+ if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
+ scroll_track_selected_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
+
+ // Lock in visible tab
+ tab_bar->VisibleTabId = tab_bar->SelectedTabId;
+ tab_bar->VisibleTabWasSubmitted = false;
+
+ // Update scrolling
+ if (scroll_track_selected_tab_id)
+ if (ImGuiTabItem* scroll_track_selected_tab = TabBarFindTabByID(tab_bar, scroll_track_selected_tab_id))
+ TabBarScrollToTab(tab_bar, scroll_track_selected_tab);
+ tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
+ tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
+ const float scrolling_speed = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) ? FLT_MAX : (g.IO.DeltaTime * g.FontSize * 70.0f);
+ if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
+ tab_bar->ScrollingAnim = ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, scrolling_speed);
+}
+
+// Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.
+static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
+{
+ if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
+ {
+ ImGuiID id = ImHash(label, 0);
+ KeepAliveID(id);
+ return id;
+ }
+ else
+ {
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->GetID(label);
+ }
+}
+
+static float ImGui::TabBarCalcMaxTabWidth()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize * 20.0f;
+}
+
+ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
+{
+ if (tab_id != 0)
+ for (int n = 0; n < tab_bar->Tabs.Size; n++)
+ if (tab_bar->Tabs[n].ID == tab_id)
+ return &tab_bar->Tabs[n];
+ return NULL;
+}
+
+// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
+void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
+{
+ if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
+ tab_bar->Tabs.erase(tab);
+ if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; }
+ if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; }
+ if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; }
+}
+
+// Called on manual closure attempt
+void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
+{
+ if ((tab_bar->VisibleTabId == tab->ID) && !(tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
+ {
+ // This will remove a frame of lag for selecting another tab on closure.
+ // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure
+ tab->LastFrameVisible = -1;
+ tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0;
+ }
+ else if ((tab_bar->VisibleTabId != tab->ID) && (tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
+ {
+ // Actually select before expecting closure
+ tab_bar->NextSelectedTabId = tab->ID;
+ }
+}
+
+static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
+{
+ scrolling = ImMin(scrolling, tab_bar->OffsetMax - tab_bar->BarRect.GetWidth());
+ return ImMax(scrolling, 0.0f);
+}
+
+static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
+{
+ ImGuiContext& g = *GImGui;
+ float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
+ int order = tab_bar->GetTabOrder(tab);
+ float tab_x1 = tab->Offset + (order > 0 ? -margin : 0.0f);
+ float tab_x2 = tab->Offset + tab->Width + (order + 1 < tab_bar->Tabs.Size ? margin : 1.0f);
+ if (tab_bar->ScrollingTarget > tab_x1)
+ tab_bar->ScrollingTarget = tab_x1;
+ if (tab_bar->ScrollingTarget + tab_bar->BarRect.GetWidth() < tab_x2)
+ tab_bar->ScrollingTarget = tab_x2 - tab_bar->BarRect.GetWidth();
+}
+
+void ImGui::TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
+{
+ IM_ASSERT(dir == -1 || dir == +1);
+ IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
+ tab_bar->ReorderRequestTabId = tab->ID;
+ tab_bar->ReorderRequestDir = dir;
+}
+
+static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f);
+ const float scrolling_buttons_width = arrow_button_size.x * 2.0f;
+
+ const ImVec2 backup_cursor_pos = window->DC.CursorPos;
+ //window->DrawList->AddRect(ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y), ImVec2(tab_bar->BarRect.Max.x, tab_bar->BarRect.Max.y), IM_COL32(255,0,0,255));
+
+ const ImRect avail_bar_rect = tab_bar->BarRect;
+ bool want_clip_rect = !avail_bar_rect.Contains(ImRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(scrolling_buttons_width, 0.0f)));
+ if (want_clip_rect)
+ PushClipRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max + ImVec2(g.Style.ItemInnerSpacing.x, 0.0f), true);
+
+ ImGuiTabItem* tab_to_select = NULL;
+
+ int select_dir = 0;
+ ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
+ arrow_col.w *= 0.5f;
+
+ PushStyleColor(ImGuiCol_Text, arrow_col);
+ PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
+ const float backup_repeat_delay = g.IO.KeyRepeatDelay;
+ const float backup_repeat_rate = g.IO.KeyRepeatRate;
+ g.IO.KeyRepeatDelay = 0.250f;
+ g.IO.KeyRepeatRate = 0.200f;
+ window->DC.CursorPos = ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y);
+ if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
+ select_dir = -1;
+ window->DC.CursorPos = ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width + arrow_button_size.x, tab_bar->BarRect.Min.y);
+ if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
+ select_dir = +1;
+ PopStyleColor(2);
+ g.IO.KeyRepeatRate = backup_repeat_rate;
+ g.IO.KeyRepeatDelay = backup_repeat_delay;
+
+ if (want_clip_rect)
+ PopClipRect();
+
+ if (select_dir != 0)
+ if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
+ {
+ int selected_order = tab_bar->GetTabOrder(tab_item);
+ int target_order = selected_order + select_dir;
+ tab_to_select = &tab_bar->Tabs[(target_order >= 0 && target_order < tab_bar->Tabs.Size) ? target_order : selected_order]; // If we are at the end of the list, still scroll to make our tab visible
+ }
+ window->DC.CursorPos = backup_cursor_pos;
+ tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f;
+
+ return tab_to_select;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
+//-------------------------------------------------------------------------
+// [BETA API] API may evolve! This code has been extracted out of the Docking branch,
+// and some of the construct which are not used in Master may be left here to facilitate merging.
+//-------------------------------------------------------------------------
+// - BeginTabItem()
+// - EndTabItem()
+// - TabItemEx() [Internal]
+// - SetTabItemClosed()
+// - TabItemCalcSize() [Internal]
+// - TabItemRenderBackground() [Internal]
+// - TabItemLabelAndCloseButton() [Internal]
+//-------------------------------------------------------------------------
+
+bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.CurrentWindow->SkipItems)
+ return false;
+
+ IM_ASSERT(g.CurrentTabBar.Size > 0 && "Needs to be called between BeginTabBar() and EndTabBar()!");
+ ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
+ bool ret = TabItemEx(tab_bar, label, p_open, flags);
+ if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
+ g.CurrentWindow->IDStack.push_back(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
+ }
+ return ret;
+}
+
+void ImGui::EndTabItem()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.CurrentWindow->SkipItems)
+ return;
+
+ IM_ASSERT(g.CurrentTabBar.Size > 0 && "Needs to be called between BeginTabBar() and EndTabBar()!");
+ ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
+ IM_ASSERT(tab_bar->LastTabItemIdx >= 0 && "Needs to be called between BeginTabItem() and EndTabItem()");
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
+ if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
+ g.CurrentWindow->IDStack.pop_back();
+}
+
+bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)
+{
+ // Layout whole tab bar if not already done
+ if (tab_bar->WantLayout)
+ TabBarLayout(tab_bar);
+
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = TabBarCalcTabID(tab_bar, label);
+
+ // If the user called us with *p_open == false, we early out and don't render. We make a dummy call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID.
+ if (p_open && !*p_open)
+ {
+ PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true);
+ ItemAdd(ImRect(), id);
+ PopItemFlag();
+ return false;
+ }
+
+ // Calculate tab contents size
+ ImVec2 size = TabItemCalcSize(label, p_open != NULL);
+
+ // Acquire tab data
+ ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id);
+ bool tab_is_new = false;
+ if (tab == NULL)
+ {
+ tab_bar->Tabs.push_back(ImGuiTabItem());
+ tab = &tab_bar->Tabs.back();
+ tab->ID = id;
+ tab->Width = size.x;
+ tab_is_new = true;
+ }
+ tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab);
+ tab->WidthContents = size.x;
+
+ const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
+ const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;
+ const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount);
+ tab->LastFrameVisible = g.FrameCount;
+ tab->Flags = flags;
+
+ // If we are not reorderable, always reset offset based on submission order.
+ // (We already handled layout and sizing using the previous known order, but sizing is not affected by order!)
+ if (!tab_appearing && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
+ {
+ tab->Offset = tab_bar->OffsetNextTab;
+ tab_bar->OffsetNextTab += tab->Width + g.Style.ItemInnerSpacing.x;
+ }
+
+ // Update selected tab
+ if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
+ if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
+ tab_bar->NextSelectedTabId = id; // New tabs gets activated
+
+ // Lock visibility
+ bool tab_contents_visible = (tab_bar->VisibleTabId == id);
+ if (tab_contents_visible)
+ tab_bar->VisibleTabWasSubmitted = true;
+
+ // On the very first frame of a tab bar we let first tab contents be visible to minimize appearing glitches
+ if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing)
+ if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs))
+ tab_contents_visible = true;
+
+ if (tab_appearing && !(tab_bar_appearing && !tab_is_new))
+ {
+ PushItemFlag(ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus, true);
+ ItemAdd(ImRect(), id);
+ PopItemFlag();
+ return tab_contents_visible;
+ }
+
+ if (tab_bar->SelectedTabId == id)
+ tab->LastFrameSelected = g.FrameCount;
+
+ // Backup current layout position
+ const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
+
+ // Layout
+ size.x = tab->Width;
+ window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2((float)(int)tab->Offset - tab_bar->ScrollingAnim, 0.0f);
+ ImVec2 pos = window->DC.CursorPos;
+ ImRect bb(pos, pos + size);
+
+ // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
+ bool want_clip_rect = (bb.Min.x < tab_bar->BarRect.Min.x) || (bb.Max.x >= tab_bar->BarRect.Max.x);
+ if (want_clip_rect)
+ PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true);
+
+ ItemSize(bb, style.FramePadding.y);
+ if (!ItemAdd(bb, id))
+ {
+ if (want_clip_rect)
+ PopClipRect();
+ window->DC.CursorPos = backup_main_cursor_pos;
+ return tab_contents_visible;
+ }
+
+ // Click to Select a tab
+ ImGuiButtonFlags button_flags = (ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_AllowItemOverlap);
+ if (g.DragDropActive)
+ button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
+ hovered |= (g.HoveredId == id);
+ if (pressed || ((flags & ImGuiTabItemFlags_SetSelected) && !tab_contents_visible)) // SetSelected can only be passed on explicit tab bar
+ tab_bar->NextSelectedTabId = id;
+
+ // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
+ if (!held)
+ SetItemAllowOverlap();
+
+ // Drag and drop: re-order tabs
+ if (held && !tab_appearing && IsMouseDragging(0))
+ {
+ if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
+ {
+ // While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x
+ if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
+ {
+ if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
+ TabBarQueueChangeTabOrder(tab_bar, tab, -1);
+ }
+ else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
+ {
+ if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
+ TabBarQueueChangeTabOrder(tab_bar, tab, +1);
+ }
+ }
+ }
+
+#if 0
+ if (hovered && g.HoveredIdNotActiveTimer > 0.50f && bb.GetWidth() < tab->WidthContents)
+ {
+ // Enlarge tab display when hovering
+ bb.Max.x = bb.Min.x + (float)(int)ImLerp(bb.GetWidth(), tab->WidthContents, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f));
+ display_draw_list = GetOverlayDrawList(window);
+ TabItemRenderBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive));
+ }
+#endif
+
+ // Render tab shape
+ ImDrawList* display_draw_list = window->DrawList;
+ const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabUnfocused));
+ TabItemBackground(display_draw_list, bb, flags, tab_col);
+ RenderNavHighlight(bb, id);
+
+ // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
+ const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
+ if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
+ tab_bar->NextSelectedTabId = id;
+
+ if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
+ flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
+
+ // Render tab label, process close button
+ const ImGuiID close_button_id = p_open ? window->GetID((void*)(intptr_t)(id + 1)) : 0;
+ bool just_closed = TabItemLabelAndCloseButton(display_draw_list, bb, flags, label, id, close_button_id);
+ if (just_closed)
+ {
+ *p_open = false;
+ TabBarCloseTab(tab_bar, tab);
+ }
+
+ // Restore main window position so user can draw there
+ if (want_clip_rect)
+ PopClipRect();
+ window->DC.CursorPos = backup_main_cursor_pos;
+
+ // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer)
+ if (g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > 0.50f)
+ if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip))
+ SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
+
+ return tab_contents_visible;
+}
+
+// [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed.
+// To use it to need to call the function SetTabItemClosed() after BeginTabBar() and before any call to BeginTabItem()
+void ImGui::SetTabItemClosed(const char* label)
+{
+ ImGuiContext& g = *GImGui;
+ bool is_within_manual_tab_bar = (g.CurrentTabBar.Size > 0) && !(g.CurrentTabBar.back()->Flags & ImGuiTabBarFlags_DockNode);
+ if (is_within_manual_tab_bar)
+ {
+ ImGuiTabBar* tab_bar = g.CurrentTabBar.back();
+ IM_ASSERT(tab_bar->WantLayout); // Needs to be called AFTER BeginTabBar() and BEFORE the first call to BeginTabItem()
+ ImGuiID tab_id = TabBarCalcTabID(tab_bar, label);
+ TabBarRemoveTab(tab_bar, tab_id);
+ }
+}
+
+ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+ ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f);
+ if (has_close_button)
+ size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle.
+ else
+ size.x += g.Style.FramePadding.x + 1.0f;
+ return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y);
+}
+
+void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col)
+{
+ // While rendering tabs, we trim 1 pixel off the top of our bounding box so they can fit within a regular frame height while looking "detached" from it.
+ (void)flags;
+ ImGuiContext& g = *GImGui;
+ const float width = bb.GetWidth();
+ IM_ASSERT(width > 0.0f);
+ const float rounding = ImMax(0.0f, ImMin(g.Style.TabRounding, width * 0.5f - 1.0f));
+ float y1 = bb.Min.y + 1.0f;
+ float y2 = bb.Max.y - 1.0f;
+ draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
+ draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
+ draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
+ draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
+ draw_list->AddConvexPolyFilled(draw_list->_Path.Data, draw_list->_Path.Size, col);
+ if (g.Style.TabBorderSize > 0.0f)
+ draw_list->AddPolyline(draw_list->_Path.Data, draw_list->_Path.Size, GetColorU32(ImGuiCol_Border), false, g.Style.TabBorderSize);
+ draw_list->PathClear();
+}
+
+// Render text label (with custom clipping) + Unsaved Document marker + Close Button logic
+bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, const char* label, ImGuiID tab_id, ImGuiID close_button_id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+ if (bb.GetWidth() <= 1.0f)
+ return false;
+
+ // Render text label (with clipping + alpha gradient) + unsaved marker
+ const char* TAB_UNSAVED_MARKER = "*";
+ ImRect text_pixel_clip_bb(bb.Min.x + style.FramePadding.x, bb.Min.y + style.FramePadding.y, bb.Max.x - style.FramePadding.x, bb.Max.y);
+ if (flags & ImGuiTabItemFlags_UnsavedDocument)
+ {
+ text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x;
+ ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + style.FramePadding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + style.FramePadding.y + (float)(int)(-g.FontSize * 0.25f));
+ RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - style.FramePadding, TAB_UNSAVED_MARKER, NULL, NULL);
+ }
+ ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
+
+ // Close Button
+ // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap()
+ // 'hovered' will be true when hovering the Tab but NOT when hovering the close button
+ // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button
+ // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false
+ bool close_button_pressed = false;
+ bool close_button_visible = false;
+ if (close_button_id != 0)
+ if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == close_button_id)
+ close_button_visible = true;
+ if (close_button_visible)
+ {
+ ImGuiItemHoveredDataBackup last_item_backup;
+ const float close_button_sz = g.FontSize * 0.5f;
+ if (CloseButton(close_button_id, ImVec2(bb.Max.x - style.FramePadding.x - close_button_sz, bb.Min.y + style.FramePadding.y + close_button_sz), close_button_sz))
+ close_button_pressed = true;
+ last_item_backup.Restore();
+
+ // Close with middle mouse button
+ if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2))
+ close_button_pressed = true;
+
+ text_pixel_clip_bb.Max.x -= close_button_sz * 2.0f;
+ }
+
+ // Label with ellipsis
+ // FIXME: This should be extracted into a helper but the use of text_pixel_clip_bb and !close_button_visible makes it tricky to abstract at the moment
+ const char* label_display_end = FindRenderedTextEnd(label);
+ if (label_size.x > text_ellipsis_clip_bb.GetWidth())
+ {
+ const int ellipsis_dot_count = 3;
+ const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f;
+ const char* label_end = NULL;
+ float label_size_clipped_x = g.Font->CalcTextSizeA(g.FontSize, text_ellipsis_clip_bb.GetWidth() - ellipsis_width + 1.0f, 0.0f, label, label_display_end, &label_end).x;
+ if (label_end == label && label_end < label_display_end) // Always display at least 1 character if there's no room for character + ellipsis
+ {
+ label_end = label + ImTextCountUtf8BytesFromChar(label, label_display_end);
+ label_size_clipped_x = g.Font->CalcTextSizeA(g.FontSize, FLT_MAX, 0.0f, label, label_end).x;
+ }
+ while (label_end > label && ImCharIsBlankA(label_end[-1])) // Trim trailing space
+ {
+ label_end--;
+ label_size_clipped_x -= g.Font->CalcTextSizeA(g.FontSize, FLT_MAX, 0.0f, label_end, label_end + 1).x; // Ascii blanks are always 1 byte
+ }
+ RenderTextClippedEx(draw_list, text_pixel_clip_bb.Min, text_pixel_clip_bb.Max, label, label_end, &label_size, ImVec2(0.0f, 0.0f));
+
+ const float ellipsis_x = text_pixel_clip_bb.Min.x + label_size_clipped_x + 1.0f;
+ if (!close_button_visible && ellipsis_x + ellipsis_width <= bb.Max.x)
+ RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, text_pixel_clip_bb.Min.y), ellipsis_dot_count, GetColorU32(ImGuiCol_Text));
+ }
+ else
+ {
+ RenderTextClippedEx(draw_list, text_pixel_clip_bb.Min, text_pixel_clip_bb.Max, label, label_display_end, &label_size, ImVec2(0.0f, 0.0f));
+ }
+
+ return close_button_pressed;
+}
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imstb_rectpack.h b/Client/ThirdParty/Box2D/extern/imgui/imstb_rectpack.h
new file mode 100644
index 0000000..2b07dcc
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imstb_rectpack.h
@@ -0,0 +1,623 @@
+// stb_rect_pack.h - v0.11 - public domain - rectangle packing
+// Sean Barrett 2014
+//
+// Useful for e.g. packing rectangular textures into an atlas.
+// Does not do rotation.
+//
+// Not necessarily the awesomest packing method, but better than
+// the totally naive one in stb_truetype (which is primarily what
+// this is meant to replace).
+//
+// Has only had a few tests run, may have issues.
+//
+// More docs to come.
+//
+// No memory allocations; uses qsort() and assert() from stdlib.
+// Can override those by defining STBRP_SORT and STBRP_ASSERT.
+//
+// This library currently uses the Skyline Bottom-Left algorithm.
+//
+// Please note: better rectangle packers are welcome! Please
+// implement them to the same API, but with a different init
+// function.
+//
+// Credits
+//
+// Library
+// Sean Barrett
+// Minor features
+// Martins Mozeiko
+// github:IntellectualKitty
+//
+// Bugfixes / warning fixes
+// Jeremy Jaussaud
+//
+// Version history:
+//
+// 0.11 (2017-03-03) return packing success/fail result
+// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
+// 0.09 (2016-08-27) fix compiler warnings
+// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
+// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
+// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
+// 0.05: added STBRP_ASSERT to allow replacing assert
+// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
+// 0.01: initial release
+//
+// LICENSE
+//
+// See end of file for license information.
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// INCLUDE SECTION
+//
+
+#ifndef STB_INCLUDE_STB_RECT_PACK_H
+#define STB_INCLUDE_STB_RECT_PACK_H
+
+#define STB_RECT_PACK_VERSION 1
+
+#ifdef STBRP_STATIC
+#define STBRP_DEF static
+#else
+#define STBRP_DEF extern
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct stbrp_context stbrp_context;
+typedef struct stbrp_node stbrp_node;
+typedef struct stbrp_rect stbrp_rect;
+
+#ifdef STBRP_LARGE_RECTS
+typedef int stbrp_coord;
+#else
+typedef unsigned short stbrp_coord;
+#endif
+
+STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
+// Assign packed locations to rectangles. The rectangles are of type
+// 'stbrp_rect' defined below, stored in the array 'rects', and there
+// are 'num_rects' many of them.
+//
+// Rectangles which are successfully packed have the 'was_packed' flag
+// set to a non-zero value and 'x' and 'y' store the minimum location
+// on each axis (i.e. bottom-left in cartesian coordinates, top-left
+// if you imagine y increasing downwards). Rectangles which do not fit
+// have the 'was_packed' flag set to 0.
+//
+// You should not try to access the 'rects' array from another thread
+// while this function is running, as the function temporarily reorders
+// the array while it executes.
+//
+// To pack into another rectangle, you need to call stbrp_init_target
+// again. To continue packing into the same rectangle, you can call
+// this function again. Calling this multiple times with multiple rect
+// arrays will probably produce worse packing results than calling it
+// a single time with the full rectangle array, but the option is
+// available.
+//
+// The function returns 1 if all of the rectangles were successfully
+// packed and 0 otherwise.
+
+struct stbrp_rect
+{
+ // reserved for your use:
+ int id;
+
+ // input:
+ stbrp_coord w, h;
+
+ // output:
+ stbrp_coord x, y;
+ int was_packed; // non-zero if valid packing
+
+}; // 16 bytes, nominally
+
+
+STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
+// Initialize a rectangle packer to:
+// pack a rectangle that is 'width' by 'height' in dimensions
+// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
+//
+// You must call this function every time you start packing into a new target.
+//
+// There is no "shutdown" function. The 'nodes' memory must stay valid for
+// the following stbrp_pack_rects() call (or calls), but can be freed after
+// the call (or calls) finish.
+//
+// Note: to guarantee best results, either:
+// 1. make sure 'num_nodes' >= 'width'
+// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
+//
+// If you don't do either of the above things, widths will be quantized to multiples
+// of small integers to guarantee the algorithm doesn't run out of temporary storage.
+//
+// If you do #2, then the non-quantized algorithm will be used, but the algorithm
+// may run out of temporary storage and be unable to pack some rectangles.
+
+STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
+// Optionally call this function after init but before doing any packing to
+// change the handling of the out-of-temp-memory scenario, described above.
+// If you call init again, this will be reset to the default (false).
+
+
+STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
+// Optionally select which packing heuristic the library should use. Different
+// heuristics will produce better/worse results for different data sets.
+// If you call init again, this will be reset to the default.
+
+enum
+{
+ STBRP_HEURISTIC_Skyline_default=0,
+ STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
+ STBRP_HEURISTIC_Skyline_BF_sortHeight
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// the details of the following structures don't matter to you, but they must
+// be visible so you can handle the memory allocations for them
+
+struct stbrp_node
+{
+ stbrp_coord x,y;
+ stbrp_node *next;
+};
+
+struct stbrp_context
+{
+ int width;
+ int height;
+ int align;
+ int init_mode;
+ int heuristic;
+ int num_nodes;
+ stbrp_node *active_head;
+ stbrp_node *free_head;
+ stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// IMPLEMENTATION SECTION
+//
+
+#ifdef STB_RECT_PACK_IMPLEMENTATION
+#ifndef STBRP_SORT
+#include <stdlib.h>
+#define STBRP_SORT qsort
+#endif
+
+#ifndef STBRP_ASSERT
+#include <assert.h>
+#define STBRP_ASSERT assert
+#endif
+
+#ifdef _MSC_VER
+#define STBRP__NOTUSED(v) (void)(v)
+#define STBRP__CDECL __cdecl
+#else
+#define STBRP__NOTUSED(v) (void)sizeof(v)
+#define STBRP__CDECL
+#endif
+
+enum
+{
+ STBRP__INIT_skyline = 1
+};
+
+STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
+{
+ switch (context->init_mode) {
+ case STBRP__INIT_skyline:
+ STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
+ context->heuristic = heuristic;
+ break;
+ default:
+ STBRP_ASSERT(0);
+ }
+}
+
+STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
+{
+ if (allow_out_of_mem)
+ // if it's ok to run out of memory, then don't bother aligning them;
+ // this gives better packing, but may fail due to OOM (even though
+ // the rectangles easily fit). @TODO a smarter approach would be to only
+ // quantize once we've hit OOM, then we could get rid of this parameter.
+ context->align = 1;
+ else {
+ // if it's not ok to run out of memory, then quantize the widths
+ // so that num_nodes is always enough nodes.
+ //
+ // I.e. num_nodes * align >= width
+ // align >= width / num_nodes
+ // align = ceil(width/num_nodes)
+
+ context->align = (context->width + context->num_nodes-1) / context->num_nodes;
+ }
+}
+
+STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
+{
+ int i;
+#ifndef STBRP_LARGE_RECTS
+ STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
+#endif
+
+ for (i=0; i < num_nodes-1; ++i)
+ nodes[i].next = &nodes[i+1];
+ nodes[i].next = NULL;
+ context->init_mode = STBRP__INIT_skyline;
+ context->heuristic = STBRP_HEURISTIC_Skyline_default;
+ context->free_head = &nodes[0];
+ context->active_head = &context->extra[0];
+ context->width = width;
+ context->height = height;
+ context->num_nodes = num_nodes;
+ stbrp_setup_allow_out_of_mem(context, 0);
+
+ // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
+ context->extra[0].x = 0;
+ context->extra[0].y = 0;
+ context->extra[0].next = &context->extra[1];
+ context->extra[1].x = (stbrp_coord) width;
+#ifdef STBRP_LARGE_RECTS
+ context->extra[1].y = (1<<30);
+#else
+ context->extra[1].y = 65535;
+#endif
+ context->extra[1].next = NULL;
+}
+
+// find minimum y position if it starts at x1
+static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
+{
+ stbrp_node *node = first;
+ int x1 = x0 + width;
+ int min_y, visited_width, waste_area;
+
+ STBRP__NOTUSED(c);
+
+ STBRP_ASSERT(first->x <= x0);
+
+ #if 0
+ // skip in case we're past the node
+ while (node->next->x <= x0)
+ ++node;
+ #else
+ STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
+ #endif
+
+ STBRP_ASSERT(node->x <= x0);
+
+ min_y = 0;
+ waste_area = 0;
+ visited_width = 0;
+ while (node->x < x1) {
+ if (node->y > min_y) {
+ // raise min_y higher.
+ // we've accounted for all waste up to min_y,
+ // but we'll now add more waste for everything we've visted
+ waste_area += visited_width * (node->y - min_y);
+ min_y = node->y;
+ // the first time through, visited_width might be reduced
+ if (node->x < x0)
+ visited_width += node->next->x - x0;
+ else
+ visited_width += node->next->x - node->x;
+ } else {
+ // add waste area
+ int under_width = node->next->x - node->x;
+ if (under_width + visited_width > width)
+ under_width = width - visited_width;
+ waste_area += under_width * (min_y - node->y);
+ visited_width += under_width;
+ }
+ node = node->next;
+ }
+
+ *pwaste = waste_area;
+ return min_y;
+}
+
+typedef struct
+{
+ int x,y;
+ stbrp_node **prev_link;
+} stbrp__findresult;
+
+static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
+{
+ int best_waste = (1<<30), best_x, best_y = (1 << 30);
+ stbrp__findresult fr;
+ stbrp_node **prev, *node, *tail, **best = NULL;
+
+ // align to multiple of c->align
+ width = (width + c->align - 1);
+ width -= width % c->align;
+ STBRP_ASSERT(width % c->align == 0);
+
+ node = c->active_head;
+ prev = &c->active_head;
+ while (node->x + width <= c->width) {
+ int y,waste;
+ y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
+ if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
+ // bottom left
+ if (y < best_y) {
+ best_y = y;
+ best = prev;
+ }
+ } else {
+ // best-fit
+ if (y + height <= c->height) {
+ // can only use it if it first vertically
+ if (y < best_y || (y == best_y && waste < best_waste)) {
+ best_y = y;
+ best_waste = waste;
+ best = prev;
+ }
+ }
+ }
+ prev = &node->next;
+ node = node->next;
+ }
+
+ best_x = (best == NULL) ? 0 : (*best)->x;
+
+ // if doing best-fit (BF), we also have to try aligning right edge to each node position
+ //
+ // e.g, if fitting
+ //
+ // ____________________
+ // |____________________|
+ //
+ // into
+ //
+ // | |
+ // | ____________|
+ // |____________|
+ //
+ // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
+ //
+ // This makes BF take about 2x the time
+
+ if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
+ tail = c->active_head;
+ node = c->active_head;
+ prev = &c->active_head;
+ // find first node that's admissible
+ while (tail->x < width)
+ tail = tail->next;
+ while (tail) {
+ int xpos = tail->x - width;
+ int y,waste;
+ STBRP_ASSERT(xpos >= 0);
+ // find the left position that matches this
+ while (node->next->x <= xpos) {
+ prev = &node->next;
+ node = node->next;
+ }
+ STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
+ y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
+ if (y + height < c->height) {
+ if (y <= best_y) {
+ if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
+ best_x = xpos;
+ STBRP_ASSERT(y <= best_y);
+ best_y = y;
+ best_waste = waste;
+ best = prev;
+ }
+ }
+ }
+ tail = tail->next;
+ }
+ }
+
+ fr.prev_link = best;
+ fr.x = best_x;
+ fr.y = best_y;
+ return fr;
+}
+
+static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
+{
+ // find best position according to heuristic
+ stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
+ stbrp_node *node, *cur;
+
+ // bail if:
+ // 1. it failed
+ // 2. the best node doesn't fit (we don't always check this)
+ // 3. we're out of memory
+ if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
+ res.prev_link = NULL;
+ return res;
+ }
+
+ // on success, create new node
+ node = context->free_head;
+ node->x = (stbrp_coord) res.x;
+ node->y = (stbrp_coord) (res.y + height);
+
+ context->free_head = node->next;
+
+ // insert the new node into the right starting point, and
+ // let 'cur' point to the remaining nodes needing to be
+ // stiched back in
+
+ cur = *res.prev_link;
+ if (cur->x < res.x) {
+ // preserve the existing one, so start testing with the next one
+ stbrp_node *next = cur->next;
+ cur->next = node;
+ cur = next;
+ } else {
+ *res.prev_link = node;
+ }
+
+ // from here, traverse cur and free the nodes, until we get to one
+ // that shouldn't be freed
+ while (cur->next && cur->next->x <= res.x + width) {
+ stbrp_node *next = cur->next;
+ // move the current node to the free list
+ cur->next = context->free_head;
+ context->free_head = cur;
+ cur = next;
+ }
+
+ // stitch the list back in
+ node->next = cur;
+
+ if (cur->x < res.x + width)
+ cur->x = (stbrp_coord) (res.x + width);
+
+#ifdef _DEBUG
+ cur = context->active_head;
+ while (cur->x < context->width) {
+ STBRP_ASSERT(cur->x < cur->next->x);
+ cur = cur->next;
+ }
+ STBRP_ASSERT(cur->next == NULL);
+
+ {
+ int count=0;
+ cur = context->active_head;
+ while (cur) {
+ cur = cur->next;
+ ++count;
+ }
+ cur = context->free_head;
+ while (cur) {
+ cur = cur->next;
+ ++count;
+ }
+ STBRP_ASSERT(count == context->num_nodes+2);
+ }
+#endif
+
+ return res;
+}
+
+static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
+{
+ const stbrp_rect *p = (const stbrp_rect *) a;
+ const stbrp_rect *q = (const stbrp_rect *) b;
+ if (p->h > q->h)
+ return -1;
+ if (p->h < q->h)
+ return 1;
+ return (p->w > q->w) ? -1 : (p->w < q->w);
+}
+
+static int STBRP__CDECL rect_original_order(const void *a, const void *b)
+{
+ const stbrp_rect *p = (const stbrp_rect *) a;
+ const stbrp_rect *q = (const stbrp_rect *) b;
+ return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
+}
+
+#ifdef STBRP_LARGE_RECTS
+#define STBRP__MAXVAL 0xffffffff
+#else
+#define STBRP__MAXVAL 0xffff
+#endif
+
+STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
+{
+ int i, all_rects_packed = 1;
+
+ // we use the 'was_packed' field internally to allow sorting/unsorting
+ for (i=0; i < num_rects; ++i) {
+ rects[i].was_packed = i;
+ #ifndef STBRP_LARGE_RECTS
+ STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
+ #endif
+ }
+
+ // sort according to heuristic
+ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
+
+ for (i=0; i < num_rects; ++i) {
+ if (rects[i].w == 0 || rects[i].h == 0) {
+ rects[i].x = rects[i].y = 0; // empty rect needs no space
+ } else {
+ stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
+ if (fr.prev_link) {
+ rects[i].x = (stbrp_coord) fr.x;
+ rects[i].y = (stbrp_coord) fr.y;
+ } else {
+ rects[i].x = rects[i].y = STBRP__MAXVAL;
+ }
+ }
+ }
+
+ // unsort
+ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
+
+ // set was_packed flags and all_rects_packed status
+ for (i=0; i < num_rects; ++i) {
+ rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
+ if (!rects[i].was_packed)
+ all_rects_packed = 0;
+ }
+
+ // return the all_rects_packed status
+ return all_rects_packed;
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imstb_textedit.h b/Client/ThirdParty/Box2D/extern/imgui/imstb_textedit.h
new file mode 100644
index 0000000..9e12469
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imstb_textedit.h
@@ -0,0 +1,1409 @@
+// [ImGui] this is a slightly modified version of stb_textedit.h 1.12. Those changes would need to be pushed into nothings/stb
+// [ImGui] - 2018-06: fixed undo/redo after pasting large amount of text (over 32 kb). Redo will still fail when undo buffers are exhausted, but text won't be corrupted (see nothings/stb issue #620)
+// [ImGui] - 2018-06: fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
+// [ImGui] - fixed some minor warnings
+
+// stb_textedit.h - v1.12 - public domain - Sean Barrett
+// Development of this library was sponsored by RAD Game Tools
+//
+// This C header file implements the guts of a multi-line text-editing
+// widget; you implement display, word-wrapping, and low-level string
+// insertion/deletion, and stb_textedit will map user inputs into
+// insertions & deletions, plus updates to the cursor position,
+// selection state, and undo state.
+//
+// It is intended for use in games and other systems that need to build
+// their own custom widgets and which do not have heavy text-editing
+// requirements (this library is not recommended for use for editing large
+// texts, as its performance does not scale and it has limited undo).
+//
+// Non-trivial behaviors are modelled after Windows text controls.
+//
+//
+// LICENSE
+//
+// See end of file for license information.
+//
+//
+// DEPENDENCIES
+//
+// Uses the C runtime function 'memmove', which you can override
+// by defining STB_TEXTEDIT_memmove before the implementation.
+// Uses no other functions. Performs no runtime allocations.
+//
+//
+// VERSION HISTORY
+//
+// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
+// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
+// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
+// 1.9 (2016-08-27) customizable move-by-word
+// 1.8 (2016-04-02) better keyboard handling when mouse button is down
+// 1.7 (2015-09-13) change y range handling in case baseline is non-0
+// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
+// 1.5 (2014-09-10) add support for secondary keys for OS X
+// 1.4 (2014-08-17) fix signed/unsigned warnings
+// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
+// 1.2 (2014-05-27) fix some RAD types that had crept into the new code
+// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE )
+// 1.0 (2012-07-26) improve documentation, initial public release
+// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode
+// 0.2 (2011-11-28) fixes to undo/redo
+// 0.1 (2010-07-08) initial version
+//
+// ADDITIONAL CONTRIBUTORS
+//
+// Ulf Winklemann: move-by-word in 1.1
+// Fabian Giesen: secondary key inputs in 1.5
+// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
+//
+// Bugfixes:
+// Scott Graham
+// Daniel Keller
+// Omar Cornut
+// Dan Thompson
+//
+// USAGE
+//
+// This file behaves differently depending on what symbols you define
+// before including it.
+//
+//
+// Header-file mode:
+//
+// If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this,
+// it will operate in "header file" mode. In this mode, it declares a
+// single public symbol, STB_TexteditState, which encapsulates the current
+// state of a text widget (except for the string, which you will store
+// separately).
+//
+// To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a
+// primitive type that defines a single character (e.g. char, wchar_t, etc).
+//
+// To save space or increase undo-ability, you can optionally define the
+// following things that are used by the undo system:
+//
+// STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position
+// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
+// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
+//
+// If you don't define these, they are set to permissive types and
+// moderate sizes. The undo system does no memory allocations, so
+// it grows STB_TexteditState by the worst-case storage which is (in bytes):
+//
+// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
+// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
+//
+//
+// Implementation mode:
+//
+// If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it
+// will compile the implementation of the text edit widget, depending
+// on a large number of symbols which must be defined before the include.
+//
+// The implementation is defined only as static functions. You will then
+// need to provide your own APIs in the same file which will access the
+// static functions.
+//
+// The basic concept is that you provide a "string" object which
+// behaves like an array of characters. stb_textedit uses indices to
+// refer to positions in the string, implicitly representing positions
+// in the displayed textedit. This is true for both plain text and
+// rich text; even with rich text stb_truetype interacts with your
+// code as if there was an array of all the displayed characters.
+//
+// Symbols that must be the same in header-file and implementation mode:
+//
+// STB_TEXTEDIT_CHARTYPE the character type
+// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position
+// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
+// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
+//
+// Symbols you must define for implementation mode:
+//
+// STB_TEXTEDIT_STRING the type of object representing a string being edited,
+// typically this is a wrapper object with other data you need
+//
+// STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1))
+// STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters
+// starting from character #n (see discussion below)
+// STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character
+// to the xpos of the i+1'th char for a line of characters
+// starting at character #n (i.e. accounts for kerning
+// with previous char)
+// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
+// (return type is int, -1 means not valid to insert)
+// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
+// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
+// as manually wordwrapping for end-of-line positioning
+//
+// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
+// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
+//
+// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
+//
+// STB_TEXTEDIT_K_LEFT keyboard input to move cursor left
+// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
+// STB_TEXTEDIT_K_UP keyboard input to move cursor up
+// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
+// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
+// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
+// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
+// STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END
+// STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor
+// STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor
+// STB_TEXTEDIT_K_UNDO keyboard input to perform undo
+// STB_TEXTEDIT_K_REDO keyboard input to perform redo
+//
+// Optional:
+// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode
+// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'),
+// required for default WORDLEFT/WORDRIGHT handlers
+// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to
+// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to
+// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT
+// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT
+// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line
+// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line
+// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
+// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
+//
+// Todo:
+// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
+// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
+//
+// Keyboard input must be encoded as a single integer value; e.g. a character code
+// and some bitflags that represent shift states. to simplify the interface, SHIFT must
+// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
+// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
+//
+// You can encode other things, such as CONTROL or ALT, in additional bits, and
+// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
+// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN
+// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit,
+// and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the
+// API below. The control keys will only match WM_KEYDOWN events because of the
+// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN
+// bit so it only decodes WM_CHAR events.
+//
+// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed
+// row of characters assuming they start on the i'th character--the width and
+// the height and the number of characters consumed. This allows this library
+// to traverse the entire layout incrementally. You need to compute word-wrapping
+// here.
+//
+// Each textfield keeps its own insert mode state, which is not how normal
+// applications work. To keep an app-wide insert mode, update/copy the
+// "insert_mode" field of STB_TexteditState before/after calling API functions.
+//
+// API
+//
+// void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
+//
+// void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
+// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
+//
+// Each of these functions potentially updates the string and updates the
+// state.
+//
+// initialize_state:
+// set the textedit state to a known good default state when initially
+// constructing the textedit.
+//
+// click:
+// call this with the mouse x,y on a mouse down; it will update the cursor
+// and reset the selection start/end to the cursor point. the x,y must
+// be relative to the text widget, with (0,0) being the top left.
+//
+// drag:
+// call this with the mouse x,y on a mouse drag/up; it will update the
+// cursor and the selection end point
+//
+// cut:
+// call this to delete the current selection; returns true if there was
+// one. you should FIRST copy the current selection to the system paste buffer.
+// (To copy, just copy the current selection out of the string yourself.)
+//
+// paste:
+// call this to paste text at the current cursor point or over the current
+// selection if there is one.
+//
+// key:
+// call this for keyboard inputs sent to the textfield. you can use it
+// for "key down" events or for "translated" key events. if you need to
+// do both (as in Win32), or distinguish Unicode characters from control
+// inputs, set a high bit to distinguish the two; then you can define the
+// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
+// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
+// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
+// anything other type you wante before including.
+//
+//
+// When rendering, you can read the cursor position and selection state from
+// the STB_TexteditState.
+//
+//
+// Notes:
+//
+// This is designed to be usable in IMGUI, so it allows for the possibility of
+// running in an IMGUI that has NOT cached the multi-line layout. For this
+// reason, it provides an interface that is compatible with computing the
+// layout incrementally--we try to make sure we make as few passes through
+// as possible. (For example, to locate the mouse pointer in the text, we
+// could define functions that return the X and Y positions of characters
+// and binary search Y and then X, but if we're doing dynamic layout this
+// will run the layout algorithm many times, so instead we manually search
+// forward in one pass. Similar logic applies to e.g. up-arrow and
+// down-arrow movement.)
+//
+// If it's run in a widget that *has* cached the layout, then this is less
+// efficient, but it's not horrible on modern computers. But you wouldn't
+// want to edit million-line files with it.
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////
+//// Header-file mode
+////
+////
+
+#ifndef INCLUDE_STB_TEXTEDIT_H
+#define INCLUDE_STB_TEXTEDIT_H
+
+////////////////////////////////////////////////////////////////////////
+//
+// STB_TexteditState
+//
+// Definition of STB_TexteditState which you should store
+// per-textfield; it includes cursor position, selection state,
+// and undo state.
+//
+
+#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
+#define STB_TEXTEDIT_UNDOSTATECOUNT 99
+#endif
+#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
+#define STB_TEXTEDIT_UNDOCHARCOUNT 999
+#endif
+#ifndef STB_TEXTEDIT_CHARTYPE
+#define STB_TEXTEDIT_CHARTYPE int
+#endif
+#ifndef STB_TEXTEDIT_POSITIONTYPE
+#define STB_TEXTEDIT_POSITIONTYPE int
+#endif
+
+typedef struct
+{
+ // private data
+ STB_TEXTEDIT_POSITIONTYPE where;
+ STB_TEXTEDIT_POSITIONTYPE insert_length;
+ STB_TEXTEDIT_POSITIONTYPE delete_length;
+ int char_storage;
+} StbUndoRecord;
+
+typedef struct
+{
+ // private data
+ StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
+ STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
+ short undo_point, redo_point;
+ int undo_char_point, redo_char_point;
+} StbUndoState;
+
+typedef struct
+{
+ /////////////////////
+ //
+ // public data
+ //
+
+ int cursor;
+ // position of the text cursor within the string
+
+ int select_start; // selection start point
+ int select_end;
+ // selection start and end point in characters; if equal, no selection.
+ // note that start may be less than or greater than end (e.g. when
+ // dragging the mouse, start is where the initial click was, and you
+ // can drag in either direction)
+
+ unsigned char insert_mode;
+ // each textfield keeps its own insert mode state. to keep an app-wide
+ // insert mode, copy this value in/out of the app state
+
+ /////////////////////
+ //
+ // private data
+ //
+ unsigned char cursor_at_end_of_line; // not implemented yet
+ unsigned char initialized;
+ unsigned char has_preferred_x;
+ unsigned char single_line;
+ unsigned char padding1, padding2, padding3;
+ float preferred_x; // this determines where the cursor up/down tries to seek to along x
+ StbUndoState undostate;
+} STB_TexteditState;
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// StbTexteditRow
+//
+// Result of layout query, used by stb_textedit to determine where
+// the text in each row is.
+
+// result of layout query
+typedef struct
+{
+ float x0,x1; // starting x location, end x location (allows for align=right, etc)
+ float baseline_y_delta; // position of baseline relative to previous row's baseline
+ float ymin,ymax; // height of row above and below baseline
+ int num_chars;
+} StbTexteditRow;
+#endif //INCLUDE_STB_TEXTEDIT_H
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////
+//// Implementation mode
+////
+////
+
+
+// implementation isn't include-guarded, since it might have indirectly
+// included just the "header" portion
+#ifdef STB_TEXTEDIT_IMPLEMENTATION
+
+#ifndef STB_TEXTEDIT_memmove
+#include <string.h>
+#define STB_TEXTEDIT_memmove memmove
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Mouse input handling
+//
+
+// traverse the layout to locate the nearest character to a display position
+static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
+{
+ StbTexteditRow r;
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ float base_y = 0, prev_x;
+ int i=0, k;
+
+ r.x0 = r.x1 = 0;
+ r.ymin = r.ymax = 0;
+ r.num_chars = 0;
+
+ // search rows to find one that straddles 'y'
+ while (i < n) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, i);
+ if (r.num_chars <= 0)
+ return n;
+
+ if (i==0 && y < base_y + r.ymin)
+ return 0;
+
+ if (y < base_y + r.ymax)
+ break;
+
+ i += r.num_chars;
+ base_y += r.baseline_y_delta;
+ }
+
+ // below all text, return 'after' last character
+ if (i >= n)
+ return n;
+
+ // check if it's before the beginning of the line
+ if (x < r.x0)
+ return i;
+
+ // check if it's before the end of the line
+ if (x < r.x1) {
+ // search characters in row for one that straddles 'x'
+ prev_x = r.x0;
+ for (k=0; k < r.num_chars; ++k) {
+ float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
+ if (x < prev_x+w) {
+ if (x < prev_x+w/2)
+ return k+i;
+ else
+ return k+i+1;
+ }
+ prev_x += w;
+ }
+ // shouldn't happen, but if it does, fall through to end-of-line case
+ }
+
+ // if the last character is a newline, return that. otherwise return 'after' the last character
+ if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE)
+ return i+r.num_chars-1;
+ else
+ return i+r.num_chars;
+}
+
+// API click: on mouse down, move the cursor to the clicked location, and reset the selection
+static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+{
+ // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
+ // goes off the top or bottom of the text
+ if( state->single_line )
+ {
+ StbTexteditRow r;
+ STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
+ y = r.ymin;
+ }
+
+ state->cursor = stb_text_locate_coord(str, x, y);
+ state->select_start = state->cursor;
+ state->select_end = state->cursor;
+ state->has_preferred_x = 0;
+}
+
+// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
+static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+{
+ int p = 0;
+
+ // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
+ // goes off the top or bottom of the text
+ if( state->single_line )
+ {
+ StbTexteditRow r;
+ STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
+ y = r.ymin;
+ }
+
+ if (state->select_start == state->select_end)
+ state->select_start = state->cursor;
+
+ p = stb_text_locate_coord(str, x, y);
+ state->cursor = state->select_end = p;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Keyboard input handling
+//
+
+// forward declarations
+static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
+static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
+static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
+static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
+static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
+
+typedef struct
+{
+ float x,y; // position of n'th character
+ float height; // height of line
+ int first_char, length; // first char of row, and length
+ int prev_first; // first char of previous row
+} StbFindState;
+
+// find the x/y location of a character, and remember info about the previous row in
+// case we get a move-up event (for page up, we'll have to rescan)
+static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
+{
+ StbTexteditRow r;
+ int prev_start = 0;
+ int z = STB_TEXTEDIT_STRINGLEN(str);
+ int i=0, first;
+
+ if (n == z) {
+ // if it's at the end, then find the last line -- simpler than trying to
+ // explicitly handle this case in the regular code
+ if (single_line) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
+ find->y = 0;
+ find->first_char = 0;
+ find->length = z;
+ find->height = r.ymax - r.ymin;
+ find->x = r.x1;
+ } else {
+ find->y = 0;
+ find->x = 0;
+ find->height = 1;
+ while (i < z) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, i);
+ prev_start = i;
+ i += r.num_chars;
+ }
+ find->first_char = i;
+ find->length = 0;
+ find->prev_first = prev_start;
+ }
+ return;
+ }
+
+ // search rows to find the one that straddles character n
+ find->y = 0;
+
+ for(;;) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, i);
+ if (n < i + r.num_chars)
+ break;
+ prev_start = i;
+ i += r.num_chars;
+ find->y += r.baseline_y_delta;
+ }
+
+ find->first_char = first = i;
+ find->length = r.num_chars;
+ find->height = r.ymax - r.ymin;
+ find->prev_first = prev_start;
+
+ // now scan to find xpos
+ find->x = r.x0;
+ i = 0;
+ for (i=0; first+i < n; ++i)
+ find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
+}
+
+#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
+
+// make the selection/cursor state valid if client altered the string
+static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ if (state->select_start > n) state->select_start = n;
+ if (state->select_end > n) state->select_end = n;
+ // if clamping forced them to be equal, move the cursor to match
+ if (state->select_start == state->select_end)
+ state->cursor = state->select_start;
+ }
+ if (state->cursor > n) state->cursor = n;
+}
+
+// delete characters while updating undo
+static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
+{
+ stb_text_makeundo_delete(str, state, where, len);
+ STB_TEXTEDIT_DELETECHARS(str, where, len);
+ state->has_preferred_x = 0;
+}
+
+// delete the section
+static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ stb_textedit_clamp(str, state);
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ if (state->select_start < state->select_end) {
+ stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start);
+ state->select_end = state->cursor = state->select_start;
+ } else {
+ stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end);
+ state->select_start = state->cursor = state->select_end;
+ }
+ state->has_preferred_x = 0;
+ }
+}
+
+// canoncialize the selection so start <= end
+static void stb_textedit_sortselection(STB_TexteditState *state)
+{
+ if (state->select_end < state->select_start) {
+ int temp = state->select_end;
+ state->select_end = state->select_start;
+ state->select_start = temp;
+ }
+}
+
+// move cursor to first character of selection
+static void stb_textedit_move_to_first(STB_TexteditState *state)
+{
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ stb_textedit_sortselection(state);
+ state->cursor = state->select_start;
+ state->select_end = state->select_start;
+ state->has_preferred_x = 0;
+ }
+}
+
+// move cursor to last character of selection
+static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ stb_textedit_sortselection(state);
+ stb_textedit_clamp(str, state);
+ state->cursor = state->select_end;
+ state->select_start = state->select_end;
+ state->has_preferred_x = 0;
+ }
+}
+
+#ifdef STB_TEXTEDIT_IS_SPACE
+static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
+{
+ return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
+}
+
+#ifndef STB_TEXTEDIT_MOVEWORDLEFT
+static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
+{
+ --c; // always move at least one character
+ while( c >= 0 && !is_word_boundary( str, c ) )
+ --c;
+
+ if( c < 0 )
+ c = 0;
+
+ return c;
+}
+#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
+#endif
+
+#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
+static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
+{
+ const int len = STB_TEXTEDIT_STRINGLEN(str);
+ ++c; // always move at least one character
+ while( c < len && !is_word_boundary( str, c ) )
+ ++c;
+
+ if( c > len )
+ c = len;
+
+ return c;
+}
+#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
+#endif
+
+#endif
+
+// update selection and cursor to match each other
+static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
+{
+ if (!STB_TEXT_HAS_SELECTION(state))
+ state->select_start = state->select_end = state->cursor;
+ else
+ state->cursor = state->select_end;
+}
+
+// API cut: delete selection
+static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ stb_textedit_delete_selection(str,state); // implicity clamps
+ state->has_preferred_x = 0;
+ return 1;
+ }
+ return 0;
+}
+
+// API paste: replace existing selection with passed-in text
+static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
+{
+ // if there's a selection, the paste should delete it
+ stb_textedit_clamp(str, state);
+ stb_textedit_delete_selection(str,state);
+ // try to insert the characters
+ if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
+ stb_text_makeundo_insert(state, state->cursor, len);
+ state->cursor += len;
+ state->has_preferred_x = 0;
+ return 1;
+ }
+ // remove the undo since we didn't actually insert the characters
+ if (state->undostate.undo_point)
+ --state->undostate.undo_point;
+ return 0;
+}
+
+#ifndef STB_TEXTEDIT_KEYTYPE
+#define STB_TEXTEDIT_KEYTYPE int
+#endif
+
+// API key: process a keyboard input
+static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
+{
+retry:
+ switch (key) {
+ default: {
+ int c = STB_TEXTEDIT_KEYTOTEXT(key);
+ if (c > 0) {
+ STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
+
+ // can't add newline in single-line mode
+ if (c == '\n' && state->single_line)
+ break;
+
+ if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
+ stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
+ STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
+ if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
+ ++state->cursor;
+ state->has_preferred_x = 0;
+ }
+ } else {
+ stb_textedit_delete_selection(str,state); // implicity clamps
+ if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
+ stb_text_makeundo_insert(state, state->cursor, 1);
+ ++state->cursor;
+ state->has_preferred_x = 0;
+ }
+ }
+ }
+ break;
+ }
+
+#ifdef STB_TEXTEDIT_K_INSERT
+ case STB_TEXTEDIT_K_INSERT:
+ state->insert_mode = !state->insert_mode;
+ break;
+#endif
+
+ case STB_TEXTEDIT_K_UNDO:
+ stb_text_undo(str, state);
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_REDO:
+ stb_text_redo(str, state);
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_LEFT:
+ // if currently there's a selection, move cursor to start of selection
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_first(state);
+ else
+ if (state->cursor > 0)
+ --state->cursor;
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_RIGHT:
+ // if currently there's a selection, move cursor to end of selection
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_last(str, state);
+ else
+ ++state->cursor;
+ stb_textedit_clamp(str, state);
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_clamp(str, state);
+ stb_textedit_prep_selection_at_cursor(state);
+ // move selection left
+ if (state->select_end > 0)
+ --state->select_end;
+ state->cursor = state->select_end;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_MOVEWORDLEFT
+ case STB_TEXTEDIT_K_WORDLEFT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_first(state);
+ else {
+ state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
+ stb_textedit_clamp( str, state );
+ }
+ break;
+
+ case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT:
+ if( !STB_TEXT_HAS_SELECTION( state ) )
+ stb_textedit_prep_selection_at_cursor(state);
+
+ state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
+ state->select_end = state->cursor;
+
+ stb_textedit_clamp( str, state );
+ break;
+#endif
+
+#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
+ case STB_TEXTEDIT_K_WORDRIGHT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_last(str, state);
+ else {
+ state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
+ stb_textedit_clamp( str, state );
+ }
+ break;
+
+ case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT:
+ if( !STB_TEXT_HAS_SELECTION( state ) )
+ stb_textedit_prep_selection_at_cursor(state);
+
+ state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
+ state->select_end = state->cursor;
+
+ stb_textedit_clamp( str, state );
+ break;
+#endif
+
+ case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_prep_selection_at_cursor(state);
+ // move selection right
+ ++state->select_end;
+ stb_textedit_clamp(str, state);
+ state->cursor = state->select_end;
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_DOWN:
+ case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
+ StbFindState find;
+ StbTexteditRow row;
+ int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
+
+ if (state->single_line) {
+ // on windows, up&down in single-line behave like left&right
+ key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
+ goto retry;
+ }
+
+ if (sel)
+ stb_textedit_prep_selection_at_cursor(state);
+ else if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_last(str,state);
+
+ // compute current position of cursor point
+ stb_textedit_clamp(str, state);
+ stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
+
+ // now find character position down a row
+ if (find.length) {
+ float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
+ float x;
+ int start = find.first_char + find.length;
+ state->cursor = start;
+ STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
+ x = row.x0;
+ for (i=0; i < row.num_chars; ++i) {
+ float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
+ #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
+ if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
+ break;
+ #endif
+ x += dx;
+ if (x > goal_x)
+ break;
+ ++state->cursor;
+ }
+ stb_textedit_clamp(str, state);
+
+ state->has_preferred_x = 1;
+ state->preferred_x = goal_x;
+
+ if (sel)
+ state->select_end = state->cursor;
+ }
+ break;
+ }
+
+ case STB_TEXTEDIT_K_UP:
+ case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
+ StbFindState find;
+ StbTexteditRow row;
+ int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
+
+ if (state->single_line) {
+ // on windows, up&down become left&right
+ key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
+ goto retry;
+ }
+
+ if (sel)
+ stb_textedit_prep_selection_at_cursor(state);
+ else if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_first(state);
+
+ // compute current position of cursor point
+ stb_textedit_clamp(str, state);
+ stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
+
+ // can only go up if there's a previous row
+ if (find.prev_first != find.first_char) {
+ // now find character position up a row
+ float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
+ float x;
+ state->cursor = find.prev_first;
+ STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
+ x = row.x0;
+ for (i=0; i < row.num_chars; ++i) {
+ float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
+ #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
+ if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
+ break;
+ #endif
+ x += dx;
+ if (x > goal_x)
+ break;
+ ++state->cursor;
+ }
+ stb_textedit_clamp(str, state);
+
+ state->has_preferred_x = 1;
+ state->preferred_x = goal_x;
+
+ if (sel)
+ state->select_end = state->cursor;
+ }
+ break;
+ }
+
+ case STB_TEXTEDIT_K_DELETE:
+ case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_delete_selection(str, state);
+ else {
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ if (state->cursor < n)
+ stb_textedit_delete(str, state, state->cursor, 1);
+ }
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_BACKSPACE:
+ case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_delete_selection(str, state);
+ else {
+ stb_textedit_clamp(str, state);
+ if (state->cursor > 0) {
+ stb_textedit_delete(str, state, state->cursor-1, 1);
+ --state->cursor;
+ }
+ }
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTSTART2
+ case STB_TEXTEDIT_K_TEXTSTART2:
+#endif
+ case STB_TEXTEDIT_K_TEXTSTART:
+ state->cursor = state->select_start = state->select_end = 0;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTEND2
+ case STB_TEXTEDIT_K_TEXTEND2:
+#endif
+ case STB_TEXTEDIT_K_TEXTEND:
+ state->cursor = STB_TEXTEDIT_STRINGLEN(str);
+ state->select_start = state->select_end = 0;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTSTART2
+ case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_prep_selection_at_cursor(state);
+ state->cursor = state->select_end = 0;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTEND2
+ case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_prep_selection_at_cursor(state);
+ state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
+ state->has_preferred_x = 0;
+ break;
+
+
+#ifdef STB_TEXTEDIT_K_LINESTART2
+ case STB_TEXTEDIT_K_LINESTART2:
+#endif
+ case STB_TEXTEDIT_K_LINESTART:
+ stb_textedit_clamp(str, state);
+ stb_textedit_move_to_first(state);
+ if (state->single_line)
+ state->cursor = 0;
+ else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
+ --state->cursor;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_LINEEND2
+ case STB_TEXTEDIT_K_LINEEND2:
+#endif
+ case STB_TEXTEDIT_K_LINEEND: {
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ stb_textedit_clamp(str, state);
+ stb_textedit_move_to_first(state);
+ if (state->single_line)
+ state->cursor = n;
+ else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
+ ++state->cursor;
+ state->has_preferred_x = 0;
+ break;
+ }
+
+#ifdef STB_TEXTEDIT_K_LINESTART2
+ case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_clamp(str, state);
+ stb_textedit_prep_selection_at_cursor(state);
+ if (state->single_line)
+ state->cursor = 0;
+ else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
+ --state->cursor;
+ state->select_end = state->cursor;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_LINEEND2
+ case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ stb_textedit_clamp(str, state);
+ stb_textedit_prep_selection_at_cursor(state);
+ if (state->single_line)
+ state->cursor = n;
+ else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
+ ++state->cursor;
+ state->select_end = state->cursor;
+ state->has_preferred_x = 0;
+ break;
+ }
+
+// @TODO:
+// STB_TEXTEDIT_K_PGUP - move cursor up a page
+// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Undo processing
+//
+// @OPTIMIZE: the undo/redo buffer should be circular
+
+static void stb_textedit_flush_redo(StbUndoState *state)
+{
+ state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
+ state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
+}
+
+// discard the oldest entry in the undo list
+static void stb_textedit_discard_undo(StbUndoState *state)
+{
+ if (state->undo_point > 0) {
+ // if the 0th undo state has characters, clean those up
+ if (state->undo_rec[0].char_storage >= 0) {
+ int n = state->undo_rec[0].insert_length, i;
+ // delete n characters from all other records
+ state->undo_char_point -= n;
+ STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
+ for (i=0; i < state->undo_point; ++i)
+ if (state->undo_rec[i].char_storage >= 0)
+ state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
+ }
+ --state->undo_point;
+ STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
+ }
+}
+
+// discard the oldest entry in the redo list--it's bad if this
+// ever happens, but because undo & redo have to store the actual
+// characters in different cases, the redo character buffer can
+// fill up even though the undo buffer didn't
+static void stb_textedit_discard_redo(StbUndoState *state)
+{
+ int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
+
+ if (state->redo_point <= k) {
+ // if the k'th undo state has characters, clean those up
+ if (state->undo_rec[k].char_storage >= 0) {
+ int n = state->undo_rec[k].insert_length, i;
+ // move the remaining redo character data to the end of the buffer
+ state->redo_char_point += n;
+ STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
+ // adjust the position of all the other records to account for above memmove
+ for (i=state->redo_point; i < k; ++i)
+ if (state->undo_rec[i].char_storage >= 0)
+ state->undo_rec[i].char_storage += n;
+ }
+ // now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
+ STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
+ // now move redo_point to point to the new one
+ ++state->redo_point;
+ }
+}
+
+static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)
+{
+ // any time we create a new undo record, we discard redo
+ stb_textedit_flush_redo(state);
+
+ // if we have no free records, we have to make room, by sliding the
+ // existing records down
+ if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
+ stb_textedit_discard_undo(state);
+
+ // if the characters to store won't possibly fit in the buffer, we can't undo
+ if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
+ state->undo_point = 0;
+ state->undo_char_point = 0;
+ return NULL;
+ }
+
+ // if we don't have enough free characters in the buffer, we have to make room
+ while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
+ stb_textedit_discard_undo(state);
+
+ return &state->undo_rec[state->undo_point++];
+}
+
+static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
+{
+ StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
+ if (r == NULL)
+ return NULL;
+
+ r->where = pos;
+ r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
+ r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
+
+ if (insert_len == 0) {
+ r->char_storage = -1;
+ return NULL;
+ } else {
+ r->char_storage = state->undo_char_point;
+ state->undo_char_point += insert_len;
+ return &state->undo_char[r->char_storage];
+ }
+}
+
+static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ StbUndoState *s = &state->undostate;
+ StbUndoRecord u, *r;
+ if (s->undo_point == 0)
+ return;
+
+ // we need to do two things: apply the undo record, and create a redo record
+ u = s->undo_rec[s->undo_point-1];
+ r = &s->undo_rec[s->redo_point-1];
+ r->char_storage = -1;
+
+ r->insert_length = u.delete_length;
+ r->delete_length = u.insert_length;
+ r->where = u.where;
+
+ if (u.delete_length) {
+ // if the undo record says to delete characters, then the redo record will
+ // need to re-insert the characters that get deleted, so we need to store
+ // them.
+
+ // there are three cases:
+ // there's enough room to store the characters
+ // characters stored for *redoing* don't leave room for redo
+ // characters stored for *undoing* don't leave room for redo
+ // if the last is true, we have to bail
+
+ if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
+ // the undo records take up too much character space; there's no space to store the redo characters
+ r->insert_length = 0;
+ } else {
+ int i;
+
+ // there's definitely room to store the characters eventually
+ while (s->undo_char_point + u.delete_length > s->redo_char_point) {
+ // should never happen:
+ if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
+ return;
+ // there's currently not enough room, so discard a redo record
+ stb_textedit_discard_redo(s);
+ }
+ r = &s->undo_rec[s->redo_point-1];
+
+ r->char_storage = s->redo_char_point - u.delete_length;
+ s->redo_char_point = s->redo_char_point - u.delete_length;
+
+ // now save the characters
+ for (i=0; i < u.delete_length; ++i)
+ s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);
+ }
+
+ // now we can carry out the deletion
+ STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
+ }
+
+ // check type of recorded action:
+ if (u.insert_length) {
+ // easy case: was a deletion, so we need to insert n characters
+ STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
+ s->undo_char_point -= u.insert_length;
+ }
+
+ state->cursor = u.where + u.insert_length;
+
+ s->undo_point--;
+ s->redo_point--;
+}
+
+static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ StbUndoState *s = &state->undostate;
+ StbUndoRecord *u, r;
+ if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
+ return;
+
+ // we need to do two things: apply the redo record, and create an undo record
+ u = &s->undo_rec[s->undo_point];
+ r = s->undo_rec[s->redo_point];
+
+ // we KNOW there must be room for the undo record, because the redo record
+ // was derived from an undo record
+
+ u->delete_length = r.insert_length;
+ u->insert_length = r.delete_length;
+ u->where = r.where;
+ u->char_storage = -1;
+
+ if (r.delete_length) {
+ // the redo record requires us to delete characters, so the undo record
+ // needs to store the characters
+
+ if (s->undo_char_point + u->insert_length > s->redo_char_point) {
+ u->insert_length = 0;
+ u->delete_length = 0;
+ } else {
+ int i;
+ u->char_storage = s->undo_char_point;
+ s->undo_char_point = s->undo_char_point + u->insert_length;
+
+ // now save the characters
+ for (i=0; i < u->insert_length; ++i)
+ s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i);
+ }
+
+ STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);
+ }
+
+ if (r.insert_length) {
+ // easy case: need to insert n characters
+ STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
+ s->redo_char_point += r.insert_length;
+ }
+
+ state->cursor = r.where + r.insert_length;
+
+ s->undo_point++;
+ s->redo_point++;
+}
+
+static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
+{
+ stb_text_createundo(&state->undostate, where, 0, length);
+}
+
+static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
+{
+ int i;
+ STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
+ if (p) {
+ for (i=0; i < length; ++i)
+ p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
+ }
+}
+
+static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
+{
+ int i;
+ STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
+ if (p) {
+ for (i=0; i < old_length; ++i)
+ p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
+ }
+}
+
+// reset the state to default
+static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)
+{
+ state->undostate.undo_point = 0;
+ state->undostate.undo_char_point = 0;
+ state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
+ state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
+ state->select_end = state->select_start = 0;
+ state->cursor = 0;
+ state->has_preferred_x = 0;
+ state->preferred_x = 0;
+ state->cursor_at_end_of_line = 0;
+ state->initialized = 1;
+ state->single_line = (unsigned char) is_single_line;
+ state->insert_mode = 0;
+}
+
+// API initialize
+static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
+{
+ stb_textedit_clear_state(state, is_single_line);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+
+static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
+{
+ return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif//STB_TEXTEDIT_IMPLEMENTATION
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/Client/ThirdParty/Box2D/extern/imgui/imstb_truetype.h b/Client/ThirdParty/Box2D/extern/imgui/imstb_truetype.h
new file mode 100644
index 0000000..f65deb5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/imgui/imstb_truetype.h
@@ -0,0 +1,4854 @@
+// stb_truetype.h - v1.19 - public domain
+// authored from 2009-2016 by Sean Barrett / RAD Game Tools
+//
+// This library processes TrueType files:
+// parse files
+// extract glyph metrics
+// extract glyph shapes
+// render glyphs to one-channel bitmaps with antialiasing (box filter)
+// render glyphs to one-channel SDF bitmaps (signed-distance field/function)
+//
+// Todo:
+// non-MS cmaps
+// crashproof on bad data
+// hinting? (no longer patented)
+// cleartype-style AA?
+// optimize: use simple memory allocator for intermediates
+// optimize: build edge-list directly from curves
+// optimize: rasterize directly from curves?
+//
+// ADDITIONAL CONTRIBUTORS
+//
+// Mikko Mononen: compound shape support, more cmap formats
+// Tor Andersson: kerning, subpixel rendering
+// Dougall Johnson: OpenType / Type 2 font handling
+// Daniel Ribeiro Maciel: basic GPOS-based kerning
+//
+// Misc other:
+// Ryan Gordon
+// Simon Glass
+// github:IntellectualKitty
+// Imanol Celaya
+// Daniel Ribeiro Maciel
+//
+// Bug/warning reports/fixes:
+// "Zer" on mollyrocket Fabian "ryg" Giesen
+// Cass Everitt Martins Mozeiko
+// stoiko (Haemimont Games) Cap Petschulat
+// Brian Hook Omar Cornut
+// Walter van Niftrik github:aloucks
+// David Gow Peter LaValle
+// David Given Sergey Popov
+// Ivan-Assen Ivanov Giumo X. Clanjor
+// Anthony Pesch Higor Euripedes
+// Johan Duparc Thomas Fields
+// Hou Qiming Derek Vinyard
+// Rob Loach Cort Stratton
+// Kenney Phillis Jr. github:oyvindjam
+// Brian Costabile github:vassvik
+//
+// VERSION HISTORY
+//
+// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
+// 1.18 (2018-01-29) add missing function
+// 1.17 (2017-07-23) make more arguments const; doc fix
+// 1.16 (2017-07-12) SDF support
+// 1.15 (2017-03-03) make more arguments const
+// 1.14 (2017-01-16) num-fonts-in-TTC function
+// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
+// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
+// 1.11 (2016-04-02) fix unused-variable warning
+// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
+// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
+// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
+// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
+// variant PackFontRanges to pack and render in separate phases;
+// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
+// fixed an assert() bug in the new rasterizer
+// replace assert() with STBTT_assert() in new rasterizer
+//
+// Full history can be found at the end of this file.
+//
+// LICENSE
+//
+// See end of file for license information.
+//
+// USAGE
+//
+// Include this file in whatever places neeed to refer to it. In ONE C/C++
+// file, write:
+// #define STB_TRUETYPE_IMPLEMENTATION
+// before the #include of this file. This expands out the actual
+// implementation into that C/C++ file.
+//
+// To make the implementation private to the file that generates the implementation,
+// #define STBTT_STATIC
+//
+// Simple 3D API (don't ship this, but it's fine for tools and quick start)
+// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
+// stbtt_GetBakedQuad() -- compute quad to draw for a given char
+//
+// Improved 3D API (more shippable):
+// #include "stb_rect_pack.h" -- optional, but you really want it
+// stbtt_PackBegin()
+// stbtt_PackSetOversampling() -- for improved quality on small fonts
+// stbtt_PackFontRanges() -- pack and renders
+// stbtt_PackEnd()
+// stbtt_GetPackedQuad()
+//
+// "Load" a font file from a memory buffer (you have to keep the buffer loaded)
+// stbtt_InitFont()
+// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
+// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
+//
+// Render a unicode codepoint to a bitmap
+// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
+// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
+// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
+//
+// Character advance/positioning
+// stbtt_GetCodepointHMetrics()
+// stbtt_GetFontVMetrics()
+// stbtt_GetFontVMetricsOS2()
+// stbtt_GetCodepointKernAdvance()
+//
+// Starting with version 1.06, the rasterizer was replaced with a new,
+// faster and generally-more-precise rasterizer. The new rasterizer more
+// accurately measures pixel coverage for anti-aliasing, except in the case
+// where multiple shapes overlap, in which case it overestimates the AA pixel
+// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
+// this turns out to be a problem, you can re-enable the old rasterizer with
+// #define STBTT_RASTERIZER_VERSION 1
+// which will incur about a 15% speed hit.
+//
+// ADDITIONAL DOCUMENTATION
+//
+// Immediately after this block comment are a series of sample programs.
+//
+// After the sample programs is the "header file" section. This section
+// includes documentation for each API function.
+//
+// Some important concepts to understand to use this library:
+//
+// Codepoint
+// Characters are defined by unicode codepoints, e.g. 65 is
+// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
+// the hiragana for "ma".
+//
+// Glyph
+// A visual character shape (every codepoint is rendered as
+// some glyph)
+//
+// Glyph index
+// A font-specific integer ID representing a glyph
+//
+// Baseline
+// Glyph shapes are defined relative to a baseline, which is the
+// bottom of uppercase characters. Characters extend both above
+// and below the baseline.
+//
+// Current Point
+// As you draw text to the screen, you keep track of a "current point"
+// which is the origin of each character. The current point's vertical
+// position is the baseline. Even "baked fonts" use this model.
+//
+// Vertical Font Metrics
+// The vertical qualities of the font, used to vertically position
+// and space the characters. See docs for stbtt_GetFontVMetrics.
+//
+// Font Size in Pixels or Points
+// The preferred interface for specifying font sizes in stb_truetype
+// is to specify how tall the font's vertical extent should be in pixels.
+// If that sounds good enough, skip the next paragraph.
+//
+// Most font APIs instead use "points", which are a common typographic
+// measurement for describing font size, defined as 72 points per inch.
+// stb_truetype provides a point API for compatibility. However, true
+// "per inch" conventions don't make much sense on computer displays
+// since different monitors have different number of pixels per
+// inch. For example, Windows traditionally uses a convention that
+// there are 96 pixels per inch, thus making 'inch' measurements have
+// nothing to do with inches, and thus effectively defining a point to
+// be 1.333 pixels. Additionally, the TrueType font data provides
+// an explicit scale factor to scale a given font's glyphs to points,
+// but the author has observed that this scale factor is often wrong
+// for non-commercial fonts, thus making fonts scaled in points
+// according to the TrueType spec incoherently sized in practice.
+//
+// DETAILED USAGE:
+//
+// Scale:
+// Select how high you want the font to be, in points or pixels.
+// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
+// a scale factor SF that will be used by all other functions.
+//
+// Baseline:
+// You need to select a y-coordinate that is the baseline of where
+// your text will appear. Call GetFontBoundingBox to get the baseline-relative
+// bounding box for all characters. SF*-y0 will be the distance in pixels
+// that the worst-case character could extend above the baseline, so if
+// you want the top edge of characters to appear at the top of the
+// screen where y=0, then you would set the baseline to SF*-y0.
+//
+// Current point:
+// Set the current point where the first character will appear. The
+// first character could extend left of the current point; this is font
+// dependent. You can either choose a current point that is the leftmost
+// point and hope, or add some padding, or check the bounding box or
+// left-side-bearing of the first character to be displayed and set
+// the current point based on that.
+//
+// Displaying a character:
+// Compute the bounding box of the character. It will contain signed values
+// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
+// then the character should be displayed in the rectangle from
+// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
+//
+// Advancing for the next character:
+// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
+//
+//
+// ADVANCED USAGE
+//
+// Quality:
+//
+// - Use the functions with Subpixel at the end to allow your characters
+// to have subpixel positioning. Since the font is anti-aliased, not
+// hinted, this is very import for quality. (This is not possible with
+// baked fonts.)
+//
+// - Kerning is now supported, and if you're supporting subpixel rendering
+// then kerning is worth using to give your text a polished look.
+//
+// Performance:
+//
+// - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
+// if you don't do this, stb_truetype is forced to do the conversion on
+// every call.
+//
+// - There are a lot of memory allocations. We should modify it to take
+// a temp buffer and allocate from the temp buffer (without freeing),
+// should help performance a lot.
+//
+// NOTES
+//
+// The system uses the raw data found in the .ttf file without changing it
+// and without building auxiliary data structures. This is a bit inefficient
+// on little-endian systems (the data is big-endian), but assuming you're
+// caching the bitmaps or glyph shapes this shouldn't be a big deal.
+//
+// It appears to be very hard to programmatically determine what font a
+// given file is in a general way. I provide an API for this, but I don't
+// recommend it.
+//
+//
+// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
+//
+// Documentation & header file 520 LOC \___ 660 LOC documentation
+// Sample code 140 LOC /
+// Truetype parsing 620 LOC ---- 620 LOC TrueType
+// Software rasterization 240 LOC \ .
+// Curve tesselation 120 LOC \__ 550 LOC Bitmap creation
+// Bitmap management 100 LOC /
+// Baked bitmap interface 70 LOC /
+// Font name matching & access 150 LOC ---- 150
+// C runtime library abstraction 60 LOC ---- 60
+//
+//
+// PERFORMANCE MEASUREMENTS FOR 1.06:
+//
+// 32-bit 64-bit
+// Previous release: 8.83 s 7.68 s
+// Pool allocations: 7.72 s 6.34 s
+// Inline sort : 6.54 s 5.65 s
+// New rasterizer : 5.63 s 5.00 s
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+////
+//// SAMPLE PROGRAMS
+////
+//
+// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
+//
+#if 0
+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
+#include "stb_truetype.h"
+
+unsigned char ttf_buffer[1<<20];
+unsigned char temp_bitmap[512*512];
+
+stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
+GLuint ftex;
+
+void my_stbtt_initfont(void)
+{
+ fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
+ stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
+ // can free ttf_buffer at this point
+ glGenTextures(1, &ftex);
+ glBindTexture(GL_TEXTURE_2D, ftex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
+ // can free temp_bitmap at this point
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+}
+
+void my_stbtt_print(float x, float y, char *text)
+{
+ // assume orthographic projection with units = screen pixels, origin at top left
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, ftex);
+ glBegin(GL_QUADS);
+ while (*text) {
+ if (*text >= 32 && *text < 128) {
+ stbtt_aligned_quad q;
+ stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
+ glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
+ glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
+ glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
+ glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
+ }
+ ++text;
+ }
+ glEnd();
+}
+#endif
+//
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Complete program (this compiles): get a single bitmap, print as ASCII art
+//
+#if 0
+#include <stdio.h>
+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
+#include "stb_truetype.h"
+
+char ttf_buffer[1<<25];
+
+int main(int argc, char **argv)
+{
+ stbtt_fontinfo font;
+ unsigned char *bitmap;
+ int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
+
+ fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
+
+ stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
+ bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
+
+ for (j=0; j < h; ++j) {
+ for (i=0; i < w; ++i)
+ putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
+ putchar('\n');
+ }
+ return 0;
+}
+#endif
+//
+// Output:
+//
+// .ii.
+// @@@@@@.
+// V@Mio@@o
+// :i. V@V
+// :oM@@M
+// :@@@MM@M
+// @@o o@M
+// :@@. M@M
+// @@@o@@@@
+// :M@@V:@@.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Complete program: print "Hello World!" banner, with bugs
+//
+#if 0
+char buffer[24<<20];
+unsigned char screen[20][79];
+
+int main(int arg, char **argv)
+{
+ stbtt_fontinfo font;
+ int i,j,ascent,baseline,ch=0;
+ float scale, xpos=2; // leave a little padding in case the character extends left
+ char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
+
+ fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
+ stbtt_InitFont(&font, buffer, 0);
+
+ scale = stbtt_ScaleForPixelHeight(&font, 15);
+ stbtt_GetFontVMetrics(&font, &ascent,0,0);
+ baseline = (int) (ascent*scale);
+
+ while (text[ch]) {
+ int advance,lsb,x0,y0,x1,y1;
+ float x_shift = xpos - (float) floor(xpos);
+ stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
+ stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
+ stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
+ // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
+ // because this API is really for baking character bitmaps into textures. if you want to render
+ // a sequence of characters, you really need to render each bitmap to a temp buffer, then
+ // "alpha blend" that into the working buffer
+ xpos += (advance * scale);
+ if (text[ch+1])
+ xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
+ ++ch;
+ }
+
+ for (j=0; j < 20; ++j) {
+ for (i=0; i < 78; ++i)
+ putchar(" .:ioVM@"[screen[j][i]>>5]);
+ putchar('\n');
+ }
+
+ return 0;
+}
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+////
+//// INTEGRATION WITH YOUR CODEBASE
+////
+//// The following sections allow you to supply alternate definitions
+//// of C library functions used by stb_truetype, e.g. if you don't
+//// link with the C runtime library.
+
+#ifdef STB_TRUETYPE_IMPLEMENTATION
+ // #define your own (u)stbtt_int8/16/32 before including to override this
+ #ifndef stbtt_uint8
+ typedef unsigned char stbtt_uint8;
+ typedef signed char stbtt_int8;
+ typedef unsigned short stbtt_uint16;
+ typedef signed short stbtt_int16;
+ typedef unsigned int stbtt_uint32;
+ typedef signed int stbtt_int32;
+ #endif
+
+ typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
+ typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
+
+ // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
+ #ifndef STBTT_ifloor
+ #include <math.h>
+ #define STBTT_ifloor(x) ((int) floor(x))
+ #define STBTT_iceil(x) ((int) ceil(x))
+ #endif
+
+ #ifndef STBTT_sqrt
+ #include <math.h>
+ #define STBTT_sqrt(x) sqrt(x)
+ #define STBTT_pow(x,y) pow(x,y)
+ #endif
+
+ #ifndef STBTT_fmod
+ #include <math.h>
+ #define STBTT_fmod(x,y) fmod(x,y)
+ #endif
+
+ #ifndef STBTT_cos
+ #include <math.h>
+ #define STBTT_cos(x) cos(x)
+ #define STBTT_acos(x) acos(x)
+ #endif
+
+ #ifndef STBTT_fabs
+ #include <math.h>
+ #define STBTT_fabs(x) fabs(x)
+ #endif
+
+ // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
+ #ifndef STBTT_malloc
+ #include <stdlib.h>
+ #define STBTT_malloc(x,u) ((void)(u),malloc(x))
+ #define STBTT_free(x,u) ((void)(u),free(x))
+ #endif
+
+ #ifndef STBTT_assert
+ #include <assert.h>
+ #define STBTT_assert(x) assert(x)
+ #endif
+
+ #ifndef STBTT_strlen
+ #include <string.h>
+ #define STBTT_strlen(x) strlen(x)
+ #endif
+
+ #ifndef STBTT_memcpy
+ #include <string.h>
+ #define STBTT_memcpy memcpy
+ #define STBTT_memset memset
+ #endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+////
+//// INTERFACE
+////
+////
+
+#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
+#define __STB_INCLUDE_STB_TRUETYPE_H__
+
+#ifdef STBTT_STATIC
+#define STBTT_DEF static
+#else
+#define STBTT_DEF extern
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// private structure
+typedef struct
+{
+ unsigned char *data;
+ int cursor;
+ int size;
+} stbtt__buf;
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTURE BAKING API
+//
+// If you use this API, you only have to call two functions ever.
+//
+
+typedef struct
+{
+ unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
+ float xoff,yoff,xadvance;
+} stbtt_bakedchar;
+
+STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
+ float pixel_height, // height of font in pixels
+ unsigned char *pixels, int pw, int ph, // bitmap to be filled in
+ int first_char, int num_chars, // characters to bake
+ stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
+// if return is positive, the first unused row of the bitmap
+// if return is negative, returns the negative of the number of characters that fit
+// if return is 0, no characters fit and no rows were used
+// This uses a very crappy packing.
+
+typedef struct
+{
+ float x0,y0,s0,t0; // top-left
+ float x1,y1,s1,t1; // bottom-right
+} stbtt_aligned_quad;
+
+STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above
+ int char_index, // character to display
+ float *xpos, float *ypos, // pointers to current position in screen pixel space
+ stbtt_aligned_quad *q, // output: quad to draw
+ int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
+// Call GetBakedQuad with char_index = 'character - first_char', and it
+// creates the quad you need to draw and advances the current position.
+//
+// The coordinate system used assumes y increases downwards.
+//
+// Characters will extend both above and below the current position;
+// see discussion of "BASELINE" above.
+//
+// It's inefficient; you might want to c&p it and optimize it.
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// NEW TEXTURE BAKING API
+//
+// This provides options for packing multiple fonts into one atlas, not
+// perfectly but better than nothing.
+
+typedef struct
+{
+ unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
+ float xoff,yoff,xadvance;
+ float xoff2,yoff2;
+} stbtt_packedchar;
+
+typedef struct stbtt_pack_context stbtt_pack_context;
+typedef struct stbtt_fontinfo stbtt_fontinfo;
+#ifndef STB_RECT_PACK_VERSION
+typedef struct stbrp_rect stbrp_rect;
+#endif
+
+STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
+// Initializes a packing context stored in the passed-in stbtt_pack_context.
+// Future calls using this context will pack characters into the bitmap passed
+// in here: a 1-channel bitmap that is width * height. stride_in_bytes is
+// the distance from one row to the next (or 0 to mean they are packed tightly
+// together). "padding" is the amount of padding to leave between each
+// character (normally you want '1' for bitmaps you'll use as textures with
+// bilinear filtering).
+//
+// Returns 0 on failure, 1 on success.
+
+STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
+// Cleans up the packing context and frees all memory.
+
+#define STBTT_POINT_SIZE(x) (-(x))
+
+STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
+ int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
+// Creates character bitmaps from the font_index'th font found in fontdata (use
+// font_index=0 if you don't know what that is). It creates num_chars_in_range
+// bitmaps for characters with unicode values starting at first_unicode_char_in_range
+// and increasing. Data for how to render them is stored in chardata_for_range;
+// pass these to stbtt_GetPackedQuad to get back renderable quads.
+//
+// font_size is the full height of the character from ascender to descender,
+// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
+// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
+// and pass that result as 'font_size':
+// ..., 20 , ... // font max minus min y is 20 pixels tall
+// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
+
+typedef struct
+{
+ float font_size;
+ int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint
+ int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
+ int num_chars;
+ stbtt_packedchar *chardata_for_range; // output
+ unsigned char h_oversample, v_oversample; // don't set these, they're used internally
+} stbtt_pack_range;
+
+STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
+// Creates character bitmaps from multiple ranges of characters stored in
+// ranges. This will usually create a better-packed bitmap than multiple
+// calls to stbtt_PackFontRange. Note that you can call this multiple
+// times within a single PackBegin/PackEnd.
+
+STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
+// Oversampling a font increases the quality by allowing higher-quality subpixel
+// positioning, and is especially valuable at smaller text sizes.
+//
+// This function sets the amount of oversampling for all following calls to
+// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
+// pack context. The default (no oversampling) is achieved by h_oversample=1
+// and v_oversample=1. The total number of pixels required is
+// h_oversample*v_oversample larger than the default; for example, 2x2
+// oversampling requires 4x the storage of 1x1. For best results, render
+// oversampled textures with bilinear filtering. Look at the readme in
+// stb/tests/oversample for information about oversampled fonts
+//
+// To use with PackFontRangesGather etc., you must set it before calls
+// call to PackFontRangesGatherRects.
+
+STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
+ int char_index, // character to display
+ float *xpos, float *ypos, // pointers to current position in screen pixel space
+ stbtt_aligned_quad *q, // output: quad to draw
+ int align_to_integer);
+
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
+STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
+// Calling these functions in sequence is roughly equivalent to calling
+// stbtt_PackFontRanges(). If you more control over the packing of multiple
+// fonts, or if you want to pack custom data into a font texture, take a look
+// at the source to of stbtt_PackFontRanges() and create a custom version
+// using these functions, e.g. call GatherRects multiple times,
+// building up a single array of rects, then call PackRects once,
+// then call RenderIntoRects repeatedly. This may result in a
+// better packing than calling PackFontRanges multiple times
+// (or it may not).
+
+// this is an opaque structure that you shouldn't mess with which holds
+// all the context needed from PackBegin to PackEnd.
+struct stbtt_pack_context {
+ void *user_allocator_context;
+ void *pack_info;
+ int width;
+ int height;
+ int stride_in_bytes;
+ int padding;
+ unsigned int h_oversample, v_oversample;
+ unsigned char *pixels;
+ void *nodes;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// FONT LOADING
+//
+//
+
+STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
+// This function will determine the number of fonts in a font file. TrueType
+// collection (.ttc) files may contain multiple fonts, while TrueType font
+// (.ttf) files only contain one font. The number of fonts can be used for
+// indexing with the previous function where the index is between zero and one
+// less than the total fonts. If an error occurs, -1 is returned.
+
+STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
+// Each .ttf/.ttc file may have more than one font. Each font has a sequential
+// index number starting from 0. Call this function to get the font offset for
+// a given index; it returns -1 if the index is out of range. A regular .ttf
+// file will only define one font and it always be at offset 0, so it will
+// return '0' for index 0, and -1 for all other indices.
+
+// The following structure is defined publically so you can declare one on
+// the stack or as a global or etc, but you should treat it as opaque.
+struct stbtt_fontinfo
+{
+ void * userdata;
+ unsigned char * data; // pointer to .ttf file
+ int fontstart; // offset of start of font
+
+ int numGlyphs; // number of glyphs, needed for range checking
+
+ int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
+ int index_map; // a cmap mapping for our chosen character encoding
+ int indexToLocFormat; // format needed to map from glyph index to glyph
+
+ stbtt__buf cff; // cff font data
+ stbtt__buf charstrings; // the charstring index
+ stbtt__buf gsubrs; // global charstring subroutines index
+ stbtt__buf subrs; // private charstring subroutines index
+ stbtt__buf fontdicts; // array of font dicts
+ stbtt__buf fdselect; // map from glyph to fontdict
+};
+
+STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
+// Given an offset into the file that defines a font, this function builds
+// the necessary cached info for the rest of the system. You must allocate
+// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
+// need to do anything special to free it, because the contents are pure
+// value data with no additional data structures. Returns 0 on failure.
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// CHARACTER TO GLYPH-INDEX CONVERSIOn
+
+STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
+// If you're going to perform multiple operations on the same character
+// and you want a speed-up, call this function with the character you're
+// going to process, then use glyph-based functions instead of the
+// codepoint-based functions.
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// CHARACTER PROPERTIES
+//
+
+STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
+// computes a scale factor to produce a font whose "height" is 'pixels' tall.
+// Height is measured as the distance from the highest ascender to the lowest
+// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
+// and computing:
+// scale = pixels / (ascent - descent)
+// so if you prefer to measure height by the ascent only, use a similar calculation.
+
+STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
+// computes a scale factor to produce a font whose EM size is mapped to
+// 'pixels' tall. This is probably what traditional APIs compute, but
+// I'm not positive.
+
+STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
+// ascent is the coordinate above the baseline the font extends; descent
+// is the coordinate below the baseline the font extends (i.e. it is typically negative)
+// lineGap is the spacing between one row's descent and the next row's ascent...
+// so you should advance the vertical position by "*ascent - *descent + *lineGap"
+// these are expressed in unscaled coordinates, so you must multiply by
+// the scale factor for a given size
+
+STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
+// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
+// table (specific to MS/Windows TTF files).
+//
+// Returns 1 on success (table present), 0 on failure.
+
+STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
+// the bounding box around all possible characters
+
+STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
+// leftSideBearing is the offset from the current horizontal position to the left edge of the character
+// advanceWidth is the offset from the current horizontal position to the next horizontal position
+// these are expressed in unscaled coordinates
+
+STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
+// an additional amount to add to the 'advance' value between ch1 and ch2
+
+STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
+// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
+
+STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
+STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
+STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
+// as above, but takes one or more glyph indices for greater efficiency
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// GLYPH SHAPES (you probably don't need these, but they have to go before
+// the bitmaps for C declaration-order reasons)
+//
+
+#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
+ enum {
+ STBTT_vmove=1,
+ STBTT_vline,
+ STBTT_vcurve,
+ STBTT_vcubic
+ };
+#endif
+
+#ifndef stbtt_vertex // you can predefine this to use different values
+ // (we share this with other code at RAD)
+ #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
+ typedef struct
+ {
+ stbtt_vertex_type x,y,cx,cy,cx1,cy1;
+ unsigned char type,padding;
+ } stbtt_vertex;
+#endif
+
+STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
+// returns non-zero if nothing is drawn for this glyph
+
+STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
+STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
+// returns # of vertices and fills *vertices with the pointer to them
+// these are expressed in "unscaled" coordinates
+//
+// The shape is a series of countours. Each one starts with
+// a STBTT_moveto, then consists of a series of mixed
+// STBTT_lineto and STBTT_curveto segments. A lineto
+// draws a line from previous endpoint to its x,y; a curveto
+// draws a quadratic bezier from previous endpoint to
+// its x,y, using cx,cy as the bezier control point.
+
+STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
+// frees the data allocated above
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// BITMAP RENDERING
+//
+
+STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
+// frees the bitmap allocated below
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
+// allocates a large-enough single-channel 8bpp bitmap and renders the
+// specified character/glyph at the specified scale into it, with
+// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
+// *width & *height are filled out with the width & height of the bitmap,
+// which is stored left-to-right, top-to-bottom.
+//
+// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
+// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
+// shift for the character
+
+STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
+// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
+// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
+// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
+// width and height and positioning info for it first.
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
+// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
+// shift for the character
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
+// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
+// is performed (see stbtt_PackSetOversampling)
+
+STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
+// get the bbox of the bitmap centered around the glyph origin; so the
+// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
+// the bitmap top left is (leftSideBearing*scale,iy0).
+// (Note that the bitmap uses y-increases-down, but the shape uses
+// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
+
+STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
+// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
+// shift for the character
+
+// the following functions are equivalent to the above functions, but operate
+// on glyph indices instead of Unicode codepoints (for efficiency)
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
+STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
+STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
+
+
+// @TODO: don't expose this structure
+typedef struct
+{
+ int w,h,stride;
+ unsigned char *pixels;
+} stbtt__bitmap;
+
+// rasterize a shape with quadratic beziers into a bitmap
+STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
+ float flatness_in_pixels, // allowable error of curve in pixels
+ stbtt_vertex *vertices, // array of vertices defining shape
+ int num_verts, // number of vertices in above array
+ float scale_x, float scale_y, // scale applied to input vertices
+ float shift_x, float shift_y, // translation applied to input vertices
+ int x_off, int y_off, // another translation applied to input
+ int invert, // if non-zero, vertically flip shape
+ void *userdata); // context for to STBTT_MALLOC
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Signed Distance Function (or Field) rendering
+
+STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
+// frees the SDF bitmap allocated below
+
+STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
+// These functions compute a discretized SDF field for a single character, suitable for storing
+// in a single-channel texture, sampling with bilinear filtering, and testing against
+// larger than some threshhold to produce scalable fonts.
+// info -- the font
+// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
+// glyph/codepoint -- the character to generate the SDF for
+// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
+// which allows effects like bit outlines
+// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
+// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
+// if positive, > onedge_value is inside; if negative, < onedge_value is inside
+// width,height -- output height & width of the SDF bitmap (including padding)
+// xoff,yoff -- output origin of the character
+// return value -- a 2D array of bytes 0..255, width*height in size
+//
+// pixel_dist_scale & onedge_value are a scale & bias that allows you to make
+// optimal use of the limited 0..255 for your application, trading off precision
+// and special effects. SDF values outside the range 0..255 are clamped to 0..255.
+//
+// Example:
+// scale = stbtt_ScaleForPixelHeight(22)
+// padding = 5
+// onedge_value = 180
+// pixel_dist_scale = 180/5.0 = 36.0
+//
+// This will create an SDF bitmap in which the character is about 22 pixels
+// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
+// shape, sample the SDF at each pixel and fill the pixel if the SDF value
+// is greater than or equal to 180/255. (You'll actually want to antialias,
+// which is beyond the scope of this example.) Additionally, you can compute
+// offset outlines (e.g. to stroke the character border inside & outside,
+// or only outside). For example, to fill outside the character up to 3 SDF
+// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
+// choice of variables maps a range from 5 pixels outside the shape to
+// 2 pixels inside the shape to 0..255; this is intended primarily for apply
+// outside effects only (the interior range is needed to allow proper
+// antialiasing of the font at *smaller* sizes)
+//
+// The function computes the SDF analytically at each SDF pixel, not by e.g.
+// building a higher-res bitmap and approximating it. In theory the quality
+// should be as high as possible for an SDF of this size & representation, but
+// unclear if this is true in practice (perhaps building a higher-res bitmap
+// and computing from that can allow drop-out prevention).
+//
+// The algorithm has not been optimized at all, so expect it to be slow
+// if computing lots of characters or very large sizes.
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Finding the right font...
+//
+// You should really just solve this offline, keep your own tables
+// of what font is what, and don't try to get it out of the .ttf file.
+// That's because getting it out of the .ttf file is really hard, because
+// the names in the file can appear in many possible encodings, in many
+// possible languages, and e.g. if you need a case-insensitive comparison,
+// the details of that depend on the encoding & language in a complex way
+// (actually underspecified in truetype, but also gigantic).
+//
+// But you can use the provided functions in two possible ways:
+// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
+// unicode-encoded names to try to find the font you want;
+// you can run this before calling stbtt_InitFont()
+//
+// stbtt_GetFontNameString() lets you get any of the various strings
+// from the file yourself and do your own comparisons on them.
+// You have to have called stbtt_InitFont() first.
+
+
+STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
+// returns the offset (not index) of the font that matches, or -1 if none
+// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
+// if you use any other flag, use a font name like "Arial"; this checks
+// the 'macStyle' header field; i don't know if fonts set this consistently
+#define STBTT_MACSTYLE_DONTCARE 0
+#define STBTT_MACSTYLE_BOLD 1
+#define STBTT_MACSTYLE_ITALIC 2
+#define STBTT_MACSTYLE_UNDERSCORE 4
+#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
+
+STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
+// returns 1/0 whether the first string interpreted as utf8 is identical to
+// the second string interpreted as big-endian utf16... useful for strings from next func
+
+STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
+// returns the string (which may be big-endian double byte, e.g. for unicode)
+// and puts the length in bytes in *length.
+//
+// some of the values for the IDs are below; for more see the truetype spec:
+// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
+// http://www.microsoft.com/typography/otspec/name.htm
+
+enum { // platformID
+ STBTT_PLATFORM_ID_UNICODE =0,
+ STBTT_PLATFORM_ID_MAC =1,
+ STBTT_PLATFORM_ID_ISO =2,
+ STBTT_PLATFORM_ID_MICROSOFT =3
+};
+
+enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
+ STBTT_UNICODE_EID_UNICODE_1_0 =0,
+ STBTT_UNICODE_EID_UNICODE_1_1 =1,
+ STBTT_UNICODE_EID_ISO_10646 =2,
+ STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
+ STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
+};
+
+enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
+ STBTT_MS_EID_SYMBOL =0,
+ STBTT_MS_EID_UNICODE_BMP =1,
+ STBTT_MS_EID_SHIFTJIS =2,
+ STBTT_MS_EID_UNICODE_FULL =10
+};
+
+enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
+ STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
+ STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
+ STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
+ STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
+};
+
+enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
+ // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
+ STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
+ STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
+ STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
+ STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
+ STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
+ STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
+};
+
+enum { // languageID for STBTT_PLATFORM_ID_MAC
+ STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
+ STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
+ STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
+ STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
+ STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
+ STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
+ STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __STB_INCLUDE_STB_TRUETYPE_H__
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+////
+//// IMPLEMENTATION
+////
+////
+
+#ifdef STB_TRUETYPE_IMPLEMENTATION
+
+#ifndef STBTT_MAX_OVERSAMPLE
+#define STBTT_MAX_OVERSAMPLE 8
+#endif
+
+#if STBTT_MAX_OVERSAMPLE > 255
+#error "STBTT_MAX_OVERSAMPLE cannot be > 255"
+#endif
+
+typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
+
+#ifndef STBTT_RASTERIZER_VERSION
+#define STBTT_RASTERIZER_VERSION 2
+#endif
+
+#ifdef _MSC_VER
+#define STBTT__NOTUSED(v) (void)(v)
+#else
+#define STBTT__NOTUSED(v) (void)sizeof(v)
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//
+// stbtt__buf helpers to parse data from file
+//
+
+static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
+{
+ if (b->cursor >= b->size)
+ return 0;
+ return b->data[b->cursor++];
+}
+
+static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
+{
+ if (b->cursor >= b->size)
+ return 0;
+ return b->data[b->cursor];
+}
+
+static void stbtt__buf_seek(stbtt__buf *b, int o)
+{
+ STBTT_assert(!(o > b->size || o < 0));
+ b->cursor = (o > b->size || o < 0) ? b->size : o;
+}
+
+static void stbtt__buf_skip(stbtt__buf *b, int o)
+{
+ stbtt__buf_seek(b, b->cursor + o);
+}
+
+static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
+{
+ stbtt_uint32 v = 0;
+ int i;
+ STBTT_assert(n >= 1 && n <= 4);
+ for (i = 0; i < n; i++)
+ v = (v << 8) | stbtt__buf_get8(b);
+ return v;
+}
+
+static stbtt__buf stbtt__new_buf(const void *p, size_t size)
+{
+ stbtt__buf r;
+ STBTT_assert(size < 0x40000000);
+ r.data = (stbtt_uint8*) p;
+ r.size = (int) size;
+ r.cursor = 0;
+ return r;
+}
+
+#define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
+#define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
+
+static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
+{
+ stbtt__buf r = stbtt__new_buf(NULL, 0);
+ if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
+ r.data = b->data + o;
+ r.size = s;
+ return r;
+}
+
+static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
+{
+ int count, start, offsize;
+ start = b->cursor;
+ count = stbtt__buf_get16(b);
+ if (count) {
+ offsize = stbtt__buf_get8(b);
+ STBTT_assert(offsize >= 1 && offsize <= 4);
+ stbtt__buf_skip(b, offsize * count);
+ stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
+ }
+ return stbtt__buf_range(b, start, b->cursor - start);
+}
+
+static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
+{
+ int b0 = stbtt__buf_get8(b);
+ if (b0 >= 32 && b0 <= 246) return b0 - 139;
+ else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
+ else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
+ else if (b0 == 28) return stbtt__buf_get16(b);
+ else if (b0 == 29) return stbtt__buf_get32(b);
+ STBTT_assert(0);
+ return 0;
+}
+
+static void stbtt__cff_skip_operand(stbtt__buf *b) {
+ int v, b0 = stbtt__buf_peek8(b);
+ STBTT_assert(b0 >= 28);
+ if (b0 == 30) {
+ stbtt__buf_skip(b, 1);
+ while (b->cursor < b->size) {
+ v = stbtt__buf_get8(b);
+ if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
+ break;
+ }
+ } else {
+ stbtt__cff_int(b);
+ }
+}
+
+static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
+{
+ stbtt__buf_seek(b, 0);
+ while (b->cursor < b->size) {
+ int start = b->cursor, end, op;
+ while (stbtt__buf_peek8(b) >= 28)
+ stbtt__cff_skip_operand(b);
+ end = b->cursor;
+ op = stbtt__buf_get8(b);
+ if (op == 12) op = stbtt__buf_get8(b) | 0x100;
+ if (op == key) return stbtt__buf_range(b, start, end-start);
+ }
+ return stbtt__buf_range(b, 0, 0);
+}
+
+static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
+{
+ int i;
+ stbtt__buf operands = stbtt__dict_get(b, key);
+ for (i = 0; i < outcount && operands.cursor < operands.size; i++)
+ out[i] = stbtt__cff_int(&operands);
+}
+
+static int stbtt__cff_index_count(stbtt__buf *b)
+{
+ stbtt__buf_seek(b, 0);
+ return stbtt__buf_get16(b);
+}
+
+static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
+{
+ int count, offsize, start, end;
+ stbtt__buf_seek(&b, 0);
+ count = stbtt__buf_get16(&b);
+ offsize = stbtt__buf_get8(&b);
+ STBTT_assert(i >= 0 && i < count);
+ STBTT_assert(offsize >= 1 && offsize <= 4);
+ stbtt__buf_skip(&b, i*offsize);
+ start = stbtt__buf_get(&b, offsize);
+ end = stbtt__buf_get(&b, offsize);
+ return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// accessors to parse data from file
+//
+
+// on platforms that don't allow misaligned reads, if we want to allow
+// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
+
+#define ttBYTE(p) (* (stbtt_uint8 *) (p))
+#define ttCHAR(p) (* (stbtt_int8 *) (p))
+#define ttFixed(p) ttLONG(p)
+
+static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
+static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
+static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
+static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
+
+#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
+#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
+
+static int stbtt__isfont(stbtt_uint8 *font)
+{
+ // check the version number
+ if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
+ if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
+ if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
+ if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
+ if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
+ return 0;
+}
+
+// @OPTIMIZE: binary search
+static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
+{
+ stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
+ stbtt_uint32 tabledir = fontstart + 12;
+ stbtt_int32 i;
+ for (i=0; i < num_tables; ++i) {
+ stbtt_uint32 loc = tabledir + 16*i;
+ if (stbtt_tag(data+loc+0, tag))
+ return ttULONG(data+loc+8);
+ }
+ return 0;
+}
+
+static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
+{
+ // if it's just a font, there's only one valid index
+ if (stbtt__isfont(font_collection))
+ return index == 0 ? 0 : -1;
+
+ // check if it's a TTC
+ if (stbtt_tag(font_collection, "ttcf")) {
+ // version 1?
+ if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
+ stbtt_int32 n = ttLONG(font_collection+8);
+ if (index >= n)
+ return -1;
+ return ttULONG(font_collection+12+index*4);
+ }
+ }
+ return -1;
+}
+
+static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
+{
+ // if it's just a font, there's only one valid font
+ if (stbtt__isfont(font_collection))
+ return 1;
+
+ // check if it's a TTC
+ if (stbtt_tag(font_collection, "ttcf")) {
+ // version 1?
+ if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
+ return ttLONG(font_collection+8);
+ }
+ }
+ return 0;
+}
+
+static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
+{
+ stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
+ stbtt__buf pdict;
+ stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
+ if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
+ pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
+ stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
+ if (!subrsoff) return stbtt__new_buf(NULL, 0);
+ stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
+ return stbtt__cff_get_index(&cff);
+}
+
+static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
+{
+ stbtt_uint32 cmap, t;
+ stbtt_int32 i,numTables;
+
+ info->data = data;
+ info->fontstart = fontstart;
+ info->cff = stbtt__new_buf(NULL, 0);
+
+ cmap = stbtt__find_table(data, fontstart, "cmap"); // required
+ info->loca = stbtt__find_table(data, fontstart, "loca"); // required
+ info->head = stbtt__find_table(data, fontstart, "head"); // required
+ info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
+ info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
+ info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
+ info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
+ info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
+
+ if (!cmap || !info->head || !info->hhea || !info->hmtx)
+ return 0;
+ if (info->glyf) {
+ // required for truetype
+ if (!info->loca) return 0;
+ } else {
+ // initialization for CFF / Type2 fonts (OTF)
+ stbtt__buf b, topdict, topdictidx;
+ stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
+ stbtt_uint32 cff;
+
+ cff = stbtt__find_table(data, fontstart, "CFF ");
+ if (!cff) return 0;
+
+ info->fontdicts = stbtt__new_buf(NULL, 0);
+ info->fdselect = stbtt__new_buf(NULL, 0);
+
+ // @TODO this should use size from table (not 512MB)
+ info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
+ b = info->cff;
+
+ // read the header
+ stbtt__buf_skip(&b, 2);
+ stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
+
+ // @TODO the name INDEX could list multiple fonts,
+ // but we just use the first one.
+ stbtt__cff_get_index(&b); // name INDEX
+ topdictidx = stbtt__cff_get_index(&b);
+ topdict = stbtt__cff_index_get(topdictidx, 0);
+ stbtt__cff_get_index(&b); // string INDEX
+ info->gsubrs = stbtt__cff_get_index(&b);
+
+ stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
+ stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
+ stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
+ stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
+ info->subrs = stbtt__get_subrs(b, topdict);
+
+ // we only support Type 2 charstrings
+ if (cstype != 2) return 0;
+ if (charstrings == 0) return 0;
+
+ if (fdarrayoff) {
+ // looks like a CID font
+ if (!fdselectoff) return 0;
+ stbtt__buf_seek(&b, fdarrayoff);
+ info->fontdicts = stbtt__cff_get_index(&b);
+ info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
+ }
+
+ stbtt__buf_seek(&b, charstrings);
+ info->charstrings = stbtt__cff_get_index(&b);
+ }
+
+ t = stbtt__find_table(data, fontstart, "maxp");
+ if (t)
+ info->numGlyphs = ttUSHORT(data+t+4);
+ else
+ info->numGlyphs = 0xffff;
+
+ // find a cmap encoding table we understand *now* to avoid searching
+ // later. (todo: could make this installable)
+ // the same regardless of glyph.
+ numTables = ttUSHORT(data + cmap + 2);
+ info->index_map = 0;
+ for (i=0; i < numTables; ++i) {
+ stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
+ // find an encoding we understand:
+ switch(ttUSHORT(data+encoding_record)) {
+ case STBTT_PLATFORM_ID_MICROSOFT:
+ switch (ttUSHORT(data+encoding_record+2)) {
+ case STBTT_MS_EID_UNICODE_BMP:
+ case STBTT_MS_EID_UNICODE_FULL:
+ // MS/Unicode
+ info->index_map = cmap + ttULONG(data+encoding_record+4);
+ break;
+ }
+ break;
+ case STBTT_PLATFORM_ID_UNICODE:
+ // Mac/iOS has these
+ // all the encodingIDs are unicode, so we don't bother to check it
+ info->index_map = cmap + ttULONG(data+encoding_record+4);
+ break;
+ }
+ }
+ if (info->index_map == 0)
+ return 0;
+
+ info->indexToLocFormat = ttUSHORT(data+info->head + 50);
+ return 1;
+}
+
+STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
+{
+ stbtt_uint8 *data = info->data;
+ stbtt_uint32 index_map = info->index_map;
+
+ stbtt_uint16 format = ttUSHORT(data + index_map + 0);
+ if (format == 0) { // apple byte encoding
+ stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
+ if (unicode_codepoint < bytes-6)
+ return ttBYTE(data + index_map + 6 + unicode_codepoint);
+ return 0;
+ } else if (format == 6) {
+ stbtt_uint32 first = ttUSHORT(data + index_map + 6);
+ stbtt_uint32 count = ttUSHORT(data + index_map + 8);
+ if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
+ return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
+ return 0;
+ } else if (format == 2) {
+ STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
+ return 0;
+ } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
+ stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
+ stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
+ stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
+ stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
+
+ // do a binary search of the segments
+ stbtt_uint32 endCount = index_map + 14;
+ stbtt_uint32 search = endCount;
+
+ if (unicode_codepoint > 0xffff)
+ return 0;
+
+ // they lie from endCount .. endCount + segCount
+ // but searchRange is the nearest power of two, so...
+ if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
+ search += rangeShift*2;
+
+ // now decrement to bias correctly to find smallest
+ search -= 2;
+ while (entrySelector) {
+ stbtt_uint16 end;
+ searchRange >>= 1;
+ end = ttUSHORT(data + search + searchRange*2);
+ if (unicode_codepoint > end)
+ search += searchRange*2;
+ --entrySelector;
+ }
+ search += 2;
+
+ {
+ stbtt_uint16 offset, start;
+ stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
+
+ STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
+ start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
+ if (unicode_codepoint < start)
+ return 0;
+
+ offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
+ if (offset == 0)
+ return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
+
+ return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
+ }
+ } else if (format == 12 || format == 13) {
+ stbtt_uint32 ngroups = ttULONG(data+index_map+12);
+ stbtt_int32 low,high;
+ low = 0; high = (stbtt_int32)ngroups;
+ // Binary search the right group.
+ while (low < high) {
+ stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
+ stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
+ stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
+ if ((stbtt_uint32) unicode_codepoint < start_char)
+ high = mid;
+ else if ((stbtt_uint32) unicode_codepoint > end_char)
+ low = mid+1;
+ else {
+ stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
+ if (format == 12)
+ return start_glyph + unicode_codepoint-start_char;
+ else // format == 13
+ return start_glyph;
+ }
+ }
+ return 0; // not found
+ }
+ // @TODO
+ STBTT_assert(0);
+ return 0;
+}
+
+STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
+{
+ return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
+}
+
+static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
+{
+ v->type = type;
+ v->x = (stbtt_int16) x;
+ v->y = (stbtt_int16) y;
+ v->cx = (stbtt_int16) cx;
+ v->cy = (stbtt_int16) cy;
+}
+
+static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
+{
+ int g1,g2;
+
+ STBTT_assert(!info->cff.size);
+
+ if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
+ if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
+
+ if (info->indexToLocFormat == 0) {
+ g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
+ g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
+ } else {
+ g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
+ g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
+ }
+
+ return g1==g2 ? -1 : g1; // if length is 0, return -1
+}
+
+static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
+
+STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
+{
+ if (info->cff.size) {
+ stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
+ } else {
+ int g = stbtt__GetGlyfOffset(info, glyph_index);
+ if (g < 0) return 0;
+
+ if (x0) *x0 = ttSHORT(info->data + g + 2);
+ if (y0) *y0 = ttSHORT(info->data + g + 4);
+ if (x1) *x1 = ttSHORT(info->data + g + 6);
+ if (y1) *y1 = ttSHORT(info->data + g + 8);
+ }
+ return 1;
+}
+
+STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
+{
+ return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
+}
+
+STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
+{
+ stbtt_int16 numberOfContours;
+ int g;
+ if (info->cff.size)
+ return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
+ g = stbtt__GetGlyfOffset(info, glyph_index);
+ if (g < 0) return 1;
+ numberOfContours = ttSHORT(info->data + g);
+ return numberOfContours == 0;
+}
+
+static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
+ stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
+{
+ if (start_off) {
+ if (was_off)
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
+ } else {
+ if (was_off)
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
+ else
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
+ }
+ return num_vertices;
+}
+
+static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
+{
+ stbtt_int16 numberOfContours;
+ stbtt_uint8 *endPtsOfContours;
+ stbtt_uint8 *data = info->data;
+ stbtt_vertex *vertices=0;
+ int num_vertices=0;
+ int g = stbtt__GetGlyfOffset(info, glyph_index);
+
+ *pvertices = NULL;
+
+ if (g < 0) return 0;
+
+ numberOfContours = ttSHORT(data + g);
+
+ if (numberOfContours > 0) {
+ stbtt_uint8 flags=0,flagcount;
+ stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
+ stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
+ stbtt_uint8 *points;
+ endPtsOfContours = (data + g + 10);
+ ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
+ points = data + g + 10 + numberOfContours * 2 + 2 + ins;
+
+ n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
+
+ m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
+ vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
+ if (vertices == 0)
+ return 0;
+
+ next_move = 0;
+ flagcount=0;
+
+ // in first pass, we load uninterpreted data into the allocated array
+ // above, shifted to the end of the array so we won't overwrite it when
+ // we create our final data starting from the front
+
+ off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
+
+ // first load flags
+
+ for (i=0; i < n; ++i) {
+ if (flagcount == 0) {
+ flags = *points++;
+ if (flags & 8)
+ flagcount = *points++;
+ } else
+ --flagcount;
+ vertices[off+i].type = flags;
+ }
+
+ // now load x coordinates
+ x=0;
+ for (i=0; i < n; ++i) {
+ flags = vertices[off+i].type;
+ if (flags & 2) {
+ stbtt_int16 dx = *points++;
+ x += (flags & 16) ? dx : -dx; // ???
+ } else {
+ if (!(flags & 16)) {
+ x = x + (stbtt_int16) (points[0]*256 + points[1]);
+ points += 2;
+ }
+ }
+ vertices[off+i].x = (stbtt_int16) x;
+ }
+
+ // now load y coordinates
+ y=0;
+ for (i=0; i < n; ++i) {
+ flags = vertices[off+i].type;
+ if (flags & 4) {
+ stbtt_int16 dy = *points++;
+ y += (flags & 32) ? dy : -dy; // ???
+ } else {
+ if (!(flags & 32)) {
+ y = y + (stbtt_int16) (points[0]*256 + points[1]);
+ points += 2;
+ }
+ }
+ vertices[off+i].y = (stbtt_int16) y;
+ }
+
+ // now convert them to our format
+ num_vertices=0;
+ sx = sy = cx = cy = scx = scy = 0;
+ for (i=0; i < n; ++i) {
+ flags = vertices[off+i].type;
+ x = (stbtt_int16) vertices[off+i].x;
+ y = (stbtt_int16) vertices[off+i].y;
+
+ if (next_move == i) {
+ if (i != 0)
+ num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
+
+ // now start the new one
+ start_off = !(flags & 1);
+ if (start_off) {
+ // if we start off with an off-curve point, then when we need to find a point on the curve
+ // where we can start, and we need to save some state for when we wraparound.
+ scx = x;
+ scy = y;
+ if (!(vertices[off+i+1].type & 1)) {
+ // next point is also a curve point, so interpolate an on-point curve
+ sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
+ sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
+ } else {
+ // otherwise just use the next point as our start point
+ sx = (stbtt_int32) vertices[off+i+1].x;
+ sy = (stbtt_int32) vertices[off+i+1].y;
+ ++i; // we're using point i+1 as the starting point, so skip it
+ }
+ } else {
+ sx = x;
+ sy = y;
+ }
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
+ was_off = 0;
+ next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
+ ++j;
+ } else {
+ if (!(flags & 1)) { // if it's a curve
+ if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
+ cx = x;
+ cy = y;
+ was_off = 1;
+ } else {
+ if (was_off)
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
+ else
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
+ was_off = 0;
+ }
+ }
+ }
+ num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
+ } else if (numberOfContours == -1) {
+ // Compound shapes.
+ int more = 1;
+ stbtt_uint8 *comp = data + g + 10;
+ num_vertices = 0;
+ vertices = 0;
+ while (more) {
+ stbtt_uint16 flags, gidx;
+ int comp_num_verts = 0, i;
+ stbtt_vertex *comp_verts = 0, *tmp = 0;
+ float mtx[6] = {1,0,0,1,0,0}, m, n;
+
+ flags = ttSHORT(comp); comp+=2;
+ gidx = ttSHORT(comp); comp+=2;
+
+ if (flags & 2) { // XY values
+ if (flags & 1) { // shorts
+ mtx[4] = ttSHORT(comp); comp+=2;
+ mtx[5] = ttSHORT(comp); comp+=2;
+ } else {
+ mtx[4] = ttCHAR(comp); comp+=1;
+ mtx[5] = ttCHAR(comp); comp+=1;
+ }
+ }
+ else {
+ // @TODO handle matching point
+ STBTT_assert(0);
+ }
+ if (flags & (1<<3)) { // WE_HAVE_A_SCALE
+ mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[1] = mtx[2] = 0;
+ } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
+ mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[1] = mtx[2] = 0;
+ mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
+ } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
+ mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
+ }
+
+ // Find transformation scales.
+ m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
+ n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
+
+ // Get indexed glyph.
+ comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
+ if (comp_num_verts > 0) {
+ // Transform vertices.
+ for (i = 0; i < comp_num_verts; ++i) {
+ stbtt_vertex* v = &comp_verts[i];
+ stbtt_vertex_type x,y;
+ x=v->x; y=v->y;
+ v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
+ v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
+ x=v->cx; y=v->cy;
+ v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
+ v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
+ }
+ // Append vertices.
+ tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
+ if (!tmp) {
+ if (vertices) STBTT_free(vertices, info->userdata);
+ if (comp_verts) STBTT_free(comp_verts, info->userdata);
+ return 0;
+ }
+ if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex));
+ STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
+ if (vertices) STBTT_free(vertices, info->userdata);
+ vertices = tmp;
+ STBTT_free(comp_verts, info->userdata);
+ num_vertices += comp_num_verts;
+ }
+ // More components ?
+ more = flags & (1<<5);
+ }
+ } else if (numberOfContours < 0) {
+ // @TODO other compound variations?
+ STBTT_assert(0);
+ } else {
+ // numberOfCounters == 0, do nothing
+ }
+
+ *pvertices = vertices;
+ return num_vertices;
+}
+
+typedef struct
+{
+ int bounds;
+ int started;
+ float first_x, first_y;
+ float x, y;
+ stbtt_int32 min_x, max_x, min_y, max_y;
+
+ stbtt_vertex *pvertices;
+ int num_vertices;
+} stbtt__csctx;
+
+#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
+
+static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
+{
+ if (x > c->max_x || !c->started) c->max_x = x;
+ if (y > c->max_y || !c->started) c->max_y = y;
+ if (x < c->min_x || !c->started) c->min_x = x;
+ if (y < c->min_y || !c->started) c->min_y = y;
+ c->started = 1;
+}
+
+static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
+{
+ if (c->bounds) {
+ stbtt__track_vertex(c, x, y);
+ if (type == STBTT_vcubic) {
+ stbtt__track_vertex(c, cx, cy);
+ stbtt__track_vertex(c, cx1, cy1);
+ }
+ } else {
+ stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
+ c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
+ c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
+ }
+ c->num_vertices++;
+}
+
+static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
+{
+ if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
+ stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
+}
+
+static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
+{
+ stbtt__csctx_close_shape(ctx);
+ ctx->first_x = ctx->x = ctx->x + dx;
+ ctx->first_y = ctx->y = ctx->y + dy;
+ stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
+}
+
+static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
+{
+ ctx->x += dx;
+ ctx->y += dy;
+ stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
+}
+
+static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
+{
+ float cx1 = ctx->x + dx1;
+ float cy1 = ctx->y + dy1;
+ float cx2 = cx1 + dx2;
+ float cy2 = cy1 + dy2;
+ ctx->x = cx2 + dx3;
+ ctx->y = cy2 + dy3;
+ stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
+}
+
+static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
+{
+ int count = stbtt__cff_index_count(&idx);
+ int bias = 107;
+ if (count >= 33900)
+ bias = 32768;
+ else if (count >= 1240)
+ bias = 1131;
+ n += bias;
+ if (n < 0 || n >= count)
+ return stbtt__new_buf(NULL, 0);
+ return stbtt__cff_index_get(idx, n);
+}
+
+static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
+{
+ stbtt__buf fdselect = info->fdselect;
+ int nranges, start, end, v, fmt, fdselector = -1, i;
+
+ stbtt__buf_seek(&fdselect, 0);
+ fmt = stbtt__buf_get8(&fdselect);
+ if (fmt == 0) {
+ // untested
+ stbtt__buf_skip(&fdselect, glyph_index);
+ fdselector = stbtt__buf_get8(&fdselect);
+ } else if (fmt == 3) {
+ nranges = stbtt__buf_get16(&fdselect);
+ start = stbtt__buf_get16(&fdselect);
+ for (i = 0; i < nranges; i++) {
+ v = stbtt__buf_get8(&fdselect);
+ end = stbtt__buf_get16(&fdselect);
+ if (glyph_index >= start && glyph_index < end) {
+ fdselector = v;
+ break;
+ }
+ start = end;
+ }
+ }
+ if (fdselector == -1) stbtt__new_buf(NULL, 0);
+ return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
+}
+
+static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
+{
+ int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
+ int has_subrs = 0, clear_stack;
+ float s[48];
+ stbtt__buf subr_stack[10], subrs = info->subrs, b;
+ float f;
+
+#define STBTT__CSERR(s) (0)
+
+ // this currently ignores the initial width value, which isn't needed if we have hmtx
+ b = stbtt__cff_index_get(info->charstrings, glyph_index);
+ while (b.cursor < b.size) {
+ i = 0;
+ clear_stack = 1;
+ b0 = stbtt__buf_get8(&b);
+ switch (b0) {
+ // @TODO implement hinting
+ case 0x13: // hintmask
+ case 0x14: // cntrmask
+ if (in_header)
+ maskbits += (sp / 2); // implicit "vstem"
+ in_header = 0;
+ stbtt__buf_skip(&b, (maskbits + 7) / 8);
+ break;
+
+ case 0x01: // hstem
+ case 0x03: // vstem
+ case 0x12: // hstemhm
+ case 0x17: // vstemhm
+ maskbits += (sp / 2);
+ break;
+
+ case 0x15: // rmoveto
+ in_header = 0;
+ if (sp < 2) return STBTT__CSERR("rmoveto stack");
+ stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
+ break;
+ case 0x04: // vmoveto
+ in_header = 0;
+ if (sp < 1) return STBTT__CSERR("vmoveto stack");
+ stbtt__csctx_rmove_to(c, 0, s[sp-1]);
+ break;
+ case 0x16: // hmoveto
+ in_header = 0;
+ if (sp < 1) return STBTT__CSERR("hmoveto stack");
+ stbtt__csctx_rmove_to(c, s[sp-1], 0);
+ break;
+
+ case 0x05: // rlineto
+ if (sp < 2) return STBTT__CSERR("rlineto stack");
+ for (; i + 1 < sp; i += 2)
+ stbtt__csctx_rline_to(c, s[i], s[i+1]);
+ break;
+
+ // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
+ // starting from a different place.
+
+ case 0x07: // vlineto
+ if (sp < 1) return STBTT__CSERR("vlineto stack");
+ goto vlineto;
+ case 0x06: // hlineto
+ if (sp < 1) return STBTT__CSERR("hlineto stack");
+ for (;;) {
+ if (i >= sp) break;
+ stbtt__csctx_rline_to(c, s[i], 0);
+ i++;
+ vlineto:
+ if (i >= sp) break;
+ stbtt__csctx_rline_to(c, 0, s[i]);
+ i++;
+ }
+ break;
+
+ case 0x1F: // hvcurveto
+ if (sp < 4) return STBTT__CSERR("hvcurveto stack");
+ goto hvcurveto;
+ case 0x1E: // vhcurveto
+ if (sp < 4) return STBTT__CSERR("vhcurveto stack");
+ for (;;) {
+ if (i + 3 >= sp) break;
+ stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
+ i += 4;
+ hvcurveto:
+ if (i + 3 >= sp) break;
+ stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
+ i += 4;
+ }
+ break;
+
+ case 0x08: // rrcurveto
+ if (sp < 6) return STBTT__CSERR("rcurveline stack");
+ for (; i + 5 < sp; i += 6)
+ stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
+ break;
+
+ case 0x18: // rcurveline
+ if (sp < 8) return STBTT__CSERR("rcurveline stack");
+ for (; i + 5 < sp - 2; i += 6)
+ stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
+ if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
+ stbtt__csctx_rline_to(c, s[i], s[i+1]);
+ break;
+
+ case 0x19: // rlinecurve
+ if (sp < 8) return STBTT__CSERR("rlinecurve stack");
+ for (; i + 1 < sp - 6; i += 2)
+ stbtt__csctx_rline_to(c, s[i], s[i+1]);
+ if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
+ stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
+ break;
+
+ case 0x1A: // vvcurveto
+ case 0x1B: // hhcurveto
+ if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
+ f = 0.0;
+ if (sp & 1) { f = s[i]; i++; }
+ for (; i + 3 < sp; i += 4) {
+ if (b0 == 0x1B)
+ stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
+ else
+ stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
+ f = 0.0;
+ }
+ break;
+
+ case 0x0A: // callsubr
+ if (!has_subrs) {
+ if (info->fdselect.size)
+ subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
+ has_subrs = 1;
+ }
+ // fallthrough
+ case 0x1D: // callgsubr
+ if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
+ v = (int) s[--sp];
+ if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
+ subr_stack[subr_stack_height++] = b;
+ b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
+ if (b.size == 0) return STBTT__CSERR("subr not found");
+ b.cursor = 0;
+ clear_stack = 0;
+ break;
+
+ case 0x0B: // return
+ if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
+ b = subr_stack[--subr_stack_height];
+ clear_stack = 0;
+ break;
+
+ case 0x0E: // endchar
+ stbtt__csctx_close_shape(c);
+ return 1;
+
+ case 0x0C: { // two-byte escape
+ float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
+ float dx, dy;
+ int b1 = stbtt__buf_get8(&b);
+ switch (b1) {
+ // @TODO These "flex" implementations ignore the flex-depth and resolution,
+ // and always draw beziers.
+ case 0x22: // hflex
+ if (sp < 7) return STBTT__CSERR("hflex stack");
+ dx1 = s[0];
+ dx2 = s[1];
+ dy2 = s[2];
+ dx3 = s[3];
+ dx4 = s[4];
+ dx5 = s[5];
+ dx6 = s[6];
+ stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
+ stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
+ break;
+
+ case 0x23: // flex
+ if (sp < 13) return STBTT__CSERR("flex stack");
+ dx1 = s[0];
+ dy1 = s[1];
+ dx2 = s[2];
+ dy2 = s[3];
+ dx3 = s[4];
+ dy3 = s[5];
+ dx4 = s[6];
+ dy4 = s[7];
+ dx5 = s[8];
+ dy5 = s[9];
+ dx6 = s[10];
+ dy6 = s[11];
+ //fd is s[12]
+ stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
+ stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
+ break;
+
+ case 0x24: // hflex1
+ if (sp < 9) return STBTT__CSERR("hflex1 stack");
+ dx1 = s[0];
+ dy1 = s[1];
+ dx2 = s[2];
+ dy2 = s[3];
+ dx3 = s[4];
+ dx4 = s[5];
+ dx5 = s[6];
+ dy5 = s[7];
+ dx6 = s[8];
+ stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
+ stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
+ break;
+
+ case 0x25: // flex1
+ if (sp < 11) return STBTT__CSERR("flex1 stack");
+ dx1 = s[0];
+ dy1 = s[1];
+ dx2 = s[2];
+ dy2 = s[3];
+ dx3 = s[4];
+ dy3 = s[5];
+ dx4 = s[6];
+ dy4 = s[7];
+ dx5 = s[8];
+ dy5 = s[9];
+ dx6 = dy6 = s[10];
+ dx = dx1+dx2+dx3+dx4+dx5;
+ dy = dy1+dy2+dy3+dy4+dy5;
+ if (STBTT_fabs(dx) > STBTT_fabs(dy))
+ dy6 = -dy;
+ else
+ dx6 = -dx;
+ stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
+ stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
+ break;
+
+ default:
+ return STBTT__CSERR("unimplemented");
+ }
+ } break;
+
+ default:
+ if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254))
+ return STBTT__CSERR("reserved operator");
+
+ // push immediate
+ if (b0 == 255) {
+ f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
+ } else {
+ stbtt__buf_skip(&b, -1);
+ f = (float)(stbtt_int16)stbtt__cff_int(&b);
+ }
+ if (sp >= 48) return STBTT__CSERR("push stack overflow");
+ s[sp++] = f;
+ clear_stack = 0;
+ break;
+ }
+ if (clear_stack) sp = 0;
+ }
+ return STBTT__CSERR("no endchar");
+
+#undef STBTT__CSERR
+}
+
+static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
+{
+ // runs the charstring twice, once to count and once to output (to avoid realloc)
+ stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
+ stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
+ if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
+ *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
+ output_ctx.pvertices = *pvertices;
+ if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
+ STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
+ return output_ctx.num_vertices;
+ }
+ }
+ *pvertices = NULL;
+ return 0;
+}
+
+static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
+{
+ stbtt__csctx c = STBTT__CSCTX_INIT(1);
+ int r = stbtt__run_charstring(info, glyph_index, &c);
+ if (x0) *x0 = r ? c.min_x : 0;
+ if (y0) *y0 = r ? c.min_y : 0;
+ if (x1) *x1 = r ? c.max_x : 0;
+ if (y1) *y1 = r ? c.max_y : 0;
+ return r ? c.num_vertices : 0;
+}
+
+STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
+{
+ if (!info->cff.size)
+ return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
+ else
+ return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
+}
+
+STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
+{
+ stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
+ if (glyph_index < numOfLongHorMetrics) {
+ if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
+ if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
+ } else {
+ if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
+ if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
+ }
+}
+
+static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
+{
+ stbtt_uint8 *data = info->data + info->kern;
+ stbtt_uint32 needle, straw;
+ int l, r, m;
+
+ // we only look at the first table. it must be 'horizontal' and format 0.
+ if (!info->kern)
+ return 0;
+ if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
+ return 0;
+ if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
+ return 0;
+
+ l = 0;
+ r = ttUSHORT(data+10) - 1;
+ needle = glyph1 << 16 | glyph2;
+ while (l <= r) {
+ m = (l + r) >> 1;
+ straw = ttULONG(data+18+(m*6)); // note: unaligned read
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else
+ return ttSHORT(data+22+(m*6));
+ }
+ return 0;
+}
+
+static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
+{
+ stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
+ switch(coverageFormat) {
+ case 1: {
+ stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
+
+ // Binary search.
+ stbtt_int32 l=0, r=glyphCount-1, m;
+ int straw, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *glyphArray = coverageTable + 4;
+ stbtt_uint16 glyphID;
+ m = (l + r) >> 1;
+ glyphID = ttUSHORT(glyphArray + 2 * m);
+ straw = glyphID;
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else {
+ return m;
+ }
+ }
+ } break;
+
+ case 2: {
+ stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
+ stbtt_uint8 *rangeArray = coverageTable + 4;
+
+ // Binary search.
+ stbtt_int32 l=0, r=rangeCount-1, m;
+ int strawStart, strawEnd, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *rangeRecord;
+ m = (l + r) >> 1;
+ rangeRecord = rangeArray + 6 * m;
+ strawStart = ttUSHORT(rangeRecord);
+ strawEnd = ttUSHORT(rangeRecord + 2);
+ if (needle < strawStart)
+ r = m - 1;
+ else if (needle > strawEnd)
+ l = m + 1;
+ else {
+ stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
+ return startCoverageIndex + glyph - strawStart;
+ }
+ }
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ } break;
+ }
+
+ return -1;
+}
+
+static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
+{
+ stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
+ switch(classDefFormat)
+ {
+ case 1: {
+ stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
+ stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
+ stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
+
+ if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
+ return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
+
+ classDefTable = classDef1ValueArray + 2 * glyphCount;
+ } break;
+
+ case 2: {
+ stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
+ stbtt_uint8 *classRangeRecords = classDefTable + 4;
+
+ // Binary search.
+ stbtt_int32 l=0, r=classRangeCount-1, m;
+ int strawStart, strawEnd, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *classRangeRecord;
+ m = (l + r) >> 1;
+ classRangeRecord = classRangeRecords + 6 * m;
+ strawStart = ttUSHORT(classRangeRecord);
+ strawEnd = ttUSHORT(classRangeRecord + 2);
+ if (needle < strawStart)
+ r = m - 1;
+ else if (needle > strawEnd)
+ l = m + 1;
+ else
+ return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
+ }
+
+ classDefTable = classRangeRecords + 6 * classRangeCount;
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ } break;
+ }
+
+ return -1;
+}
+
+// Define to STBTT_assert(x) if you want to break on unimplemented formats.
+#define STBTT_GPOS_TODO_assert(x)
+
+static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
+{
+ stbtt_uint16 lookupListOffset;
+ stbtt_uint8 *lookupList;
+ stbtt_uint16 lookupCount;
+ stbtt_uint8 *data;
+ stbtt_int32 i;
+
+ if (!info->gpos) return 0;
+
+ data = info->data + info->gpos;
+
+ if (ttUSHORT(data+0) != 1) return 0; // Major version 1
+ if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
+
+ lookupListOffset = ttUSHORT(data+8);
+ lookupList = data + lookupListOffset;
+ lookupCount = ttUSHORT(lookupList);
+
+ for (i=0; i<lookupCount; ++i) {
+ stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
+ stbtt_uint8 *lookupTable = lookupList + lookupOffset;
+
+ stbtt_uint16 lookupType = ttUSHORT(lookupTable);
+ stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
+ stbtt_uint8 *subTableOffsets = lookupTable + 6;
+ switch(lookupType) {
+ case 2: { // Pair Adjustment Positioning Subtable
+ stbtt_int32 sti;
+ for (sti=0; sti<subTableCount; sti++) {
+ stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
+ stbtt_uint8 *table = lookupTable + subtableOffset;
+ stbtt_uint16 posFormat = ttUSHORT(table);
+ stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
+ stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
+ if (coverageIndex == -1) continue;
+
+ switch (posFormat) {
+ case 1: {
+ stbtt_int32 l, r, m;
+ int straw, needle;
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+ stbtt_int32 valueRecordPairSizeInBytes = 2;
+ stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
+ stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
+ stbtt_uint8 *pairValueTable = table + pairPosOffset;
+ stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
+ stbtt_uint8 *pairValueArray = pairValueTable + 2;
+ // TODO: Support more formats.
+ STBTT_GPOS_TODO_assert(valueFormat1 == 4);
+ if (valueFormat1 != 4) return 0;
+ STBTT_GPOS_TODO_assert(valueFormat2 == 0);
+ if (valueFormat2 != 0) return 0;
+
+ STBTT_assert(coverageIndex < pairSetCount);
+ STBTT__NOTUSED(pairSetCount);
+
+ needle=glyph2;
+ r=pairValueCount-1;
+ l=0;
+
+ // Binary search.
+ while (l <= r) {
+ stbtt_uint16 secondGlyph;
+ stbtt_uint8 *pairValue;
+ m = (l + r) >> 1;
+ pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
+ secondGlyph = ttUSHORT(pairValue);
+ straw = secondGlyph;
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else {
+ stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
+ return xAdvance;
+ }
+ }
+ } break;
+
+ case 2: {
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+
+ stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
+ stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
+ int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
+ int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
+
+ stbtt_uint16 class1Count = ttUSHORT(table + 12);
+ stbtt_uint16 class2Count = ttUSHORT(table + 14);
+ STBTT_assert(glyph1class < class1Count);
+ STBTT_assert(glyph2class < class2Count);
+
+ // TODO: Support more formats.
+ STBTT_GPOS_TODO_assert(valueFormat1 == 4);
+ if (valueFormat1 != 4) return 0;
+ STBTT_GPOS_TODO_assert(valueFormat2 == 0);
+ if (valueFormat2 != 0) return 0;
+
+ if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
+ stbtt_uint8 *class1Records = table + 16;
+ stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
+ stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
+ return xAdvance;
+ }
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ break;
+ };
+ }
+ }
+ break;
+ };
+
+ default:
+ // TODO: Implement other stuff.
+ break;
+ }
+ }
+
+ return 0;
+}
+
+STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
+{
+ int xAdvance = 0;
+
+ if (info->gpos)
+ xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
+
+ if (info->kern)
+ xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
+
+ return xAdvance;
+}
+
+STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
+{
+ if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
+ return 0;
+ return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
+}
+
+STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
+{
+ stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
+}
+
+STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
+{
+ if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
+ if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
+ if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
+}
+
+STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
+{
+ int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
+ if (!tab)
+ return 0;
+ if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
+ if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
+ if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
+ return 1;
+}
+
+STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
+{
+ *x0 = ttSHORT(info->data + info->head + 36);
+ *y0 = ttSHORT(info->data + info->head + 38);
+ *x1 = ttSHORT(info->data + info->head + 40);
+ *y1 = ttSHORT(info->data + info->head + 42);
+}
+
+STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
+{
+ int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
+ return (float) height / fheight;
+}
+
+STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
+{
+ int unitsPerEm = ttUSHORT(info->data + info->head + 18);
+ return pixels / unitsPerEm;
+}
+
+STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
+{
+ STBTT_free(v, info->userdata);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// antialiasing software rasterizer
+//
+
+STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
+ if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
+ // e.g. space character
+ if (ix0) *ix0 = 0;
+ if (iy0) *iy0 = 0;
+ if (ix1) *ix1 = 0;
+ if (iy1) *iy1 = 0;
+ } else {
+ // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
+ if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
+ if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
+ if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
+ if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
+ }
+}
+
+STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
+}
+
+STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
+}
+
+STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Rasterizer
+
+typedef struct stbtt__hheap_chunk
+{
+ struct stbtt__hheap_chunk *next;
+} stbtt__hheap_chunk;
+
+typedef struct stbtt__hheap
+{
+ struct stbtt__hheap_chunk *head;
+ void *first_free;
+ int num_remaining_in_head_chunk;
+} stbtt__hheap;
+
+static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
+{
+ if (hh->first_free) {
+ void *p = hh->first_free;
+ hh->first_free = * (void **) p;
+ return p;
+ } else {
+ if (hh->num_remaining_in_head_chunk == 0) {
+ int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
+ stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
+ if (c == NULL)
+ return NULL;
+ c->next = hh->head;
+ hh->head = c;
+ hh->num_remaining_in_head_chunk = count;
+ }
+ --hh->num_remaining_in_head_chunk;
+ return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
+ }
+}
+
+static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
+{
+ *(void **) p = hh->first_free;
+ hh->first_free = p;
+}
+
+static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
+{
+ stbtt__hheap_chunk *c = hh->head;
+ while (c) {
+ stbtt__hheap_chunk *n = c->next;
+ STBTT_free(c, userdata);
+ c = n;
+ }
+}
+
+typedef struct stbtt__edge {
+ float x0,y0, x1,y1;
+ int invert;
+} stbtt__edge;
+
+
+typedef struct stbtt__active_edge
+{
+ struct stbtt__active_edge *next;
+ #if STBTT_RASTERIZER_VERSION==1
+ int x,dx;
+ float ey;
+ int direction;
+ #elif STBTT_RASTERIZER_VERSION==2
+ float fx,fdx,fdy;
+ float direction;
+ float sy;
+ float ey;
+ #else
+ #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+ #endif
+} stbtt__active_edge;
+
+#if STBTT_RASTERIZER_VERSION == 1
+#define STBTT_FIXSHIFT 10
+#define STBTT_FIX (1 << STBTT_FIXSHIFT)
+#define STBTT_FIXMASK (STBTT_FIX-1)
+
+static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
+{
+ stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
+ float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
+ STBTT_assert(z != NULL);
+ if (!z) return z;
+
+ // round dx down to avoid overshooting
+ if (dxdy < 0)
+ z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
+ else
+ z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
+
+ z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
+ z->x -= off_x * STBTT_FIX;
+
+ z->ey = e->y1;
+ z->next = 0;
+ z->direction = e->invert ? 1 : -1;
+ return z;
+}
+#elif STBTT_RASTERIZER_VERSION == 2
+static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
+{
+ stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
+ float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
+ STBTT_assert(z != NULL);
+ //STBTT_assert(e->y0 <= start_point);
+ if (!z) return z;
+ z->fdx = dxdy;
+ z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
+ z->fx = e->x0 + dxdy * (start_point - e->y0);
+ z->fx -= off_x;
+ z->direction = e->invert ? 1.0f : -1.0f;
+ z->sy = e->y0;
+ z->ey = e->y1;
+ z->next = 0;
+ return z;
+}
+#else
+#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#endif
+
+#if STBTT_RASTERIZER_VERSION == 1
+// note: this routine clips fills that extend off the edges... ideally this
+// wouldn't happen, but it could happen if the truetype glyph bounding boxes
+// are wrong, or if the user supplies a too-small bitmap
+static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
+{
+ // non-zero winding fill
+ int x0=0, w=0;
+
+ while (e) {
+ if (w == 0) {
+ // if we're currently at zero, we need to record the edge start point
+ x0 = e->x; w += e->direction;
+ } else {
+ int x1 = e->x; w += e->direction;
+ // if we went to zero, we need to draw
+ if (w == 0) {
+ int i = x0 >> STBTT_FIXSHIFT;
+ int j = x1 >> STBTT_FIXSHIFT;
+
+ if (i < len && j >= 0) {
+ if (i == j) {
+ // x0,x1 are the same pixel, so compute combined coverage
+ scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
+ } else {
+ if (i >= 0) // add antialiasing for x0
+ scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
+ else
+ i = -1; // clip
+
+ if (j < len) // add antialiasing for x1
+ scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
+ else
+ j = len; // clip
+
+ for (++i; i < j; ++i) // fill pixels between x0 and x1
+ scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
+ }
+ }
+ }
+ }
+
+ e = e->next;
+ }
+}
+
+static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
+{
+ stbtt__hheap hh = { 0, 0, 0 };
+ stbtt__active_edge *active = NULL;
+ int y,j=0;
+ int max_weight = (255 / vsubsample); // weight per vertical scanline
+ int s; // vertical subsample index
+ unsigned char scanline_data[512], *scanline;
+
+ if (result->w > 512)
+ scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
+ else
+ scanline = scanline_data;
+
+ y = off_y * vsubsample;
+ e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
+
+ while (j < result->h) {
+ STBTT_memset(scanline, 0, result->w);
+ for (s=0; s < vsubsample; ++s) {
+ // find center of pixel for this scanline
+ float scan_y = y + 0.5f;
+ stbtt__active_edge **step = &active;
+
+ // update all active edges;
+ // remove all active edges that terminate before the center of this scanline
+ while (*step) {
+ stbtt__active_edge * z = *step;
+ if (z->ey <= scan_y) {
+ *step = z->next; // delete from list
+ STBTT_assert(z->direction);
+ z->direction = 0;
+ stbtt__hheap_free(&hh, z);
+ } else {
+ z->x += z->dx; // advance to position for current scanline
+ step = &((*step)->next); // advance through list
+ }
+ }
+
+ // resort the list if needed
+ for(;;) {
+ int changed=0;
+ step = &active;
+ while (*step && (*step)->next) {
+ if ((*step)->x > (*step)->next->x) {
+ stbtt__active_edge *t = *step;
+ stbtt__active_edge *q = t->next;
+
+ t->next = q->next;
+ q->next = t;
+ *step = q;
+ changed = 1;
+ }
+ step = &(*step)->next;
+ }
+ if (!changed) break;
+ }
+
+ // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
+ while (e->y0 <= scan_y) {
+ if (e->y1 > scan_y) {
+ stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
+ if (z != NULL) {
+ // find insertion point
+ if (active == NULL)
+ active = z;
+ else if (z->x < active->x) {
+ // insert at front
+ z->next = active;
+ active = z;
+ } else {
+ // find thing to insert AFTER
+ stbtt__active_edge *p = active;
+ while (p->next && p->next->x < z->x)
+ p = p->next;
+ // at this point, p->next->x is NOT < z->x
+ z->next = p->next;
+ p->next = z;
+ }
+ }
+ }
+ ++e;
+ }
+
+ // now process all active edges in XOR fashion
+ if (active)
+ stbtt__fill_active_edges(scanline, result->w, active, max_weight);
+
+ ++y;
+ }
+ STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
+ ++j;
+ }
+
+ stbtt__hheap_cleanup(&hh, userdata);
+
+ if (scanline != scanline_data)
+ STBTT_free(scanline, userdata);
+}
+
+#elif STBTT_RASTERIZER_VERSION == 2
+
+// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
+// (i.e. it has already been clipped to those)
+static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
+{
+ if (y0 == y1) return;
+ STBTT_assert(y0 < y1);
+ STBTT_assert(e->sy <= e->ey);
+ if (y0 > e->ey) return;
+ if (y1 < e->sy) return;
+ if (y0 < e->sy) {
+ x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
+ y0 = e->sy;
+ }
+ if (y1 > e->ey) {
+ x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
+ y1 = e->ey;
+ }
+
+ if (x0 == x)
+ STBTT_assert(x1 <= x+1);
+ else if (x0 == x+1)
+ STBTT_assert(x1 >= x);
+ else if (x0 <= x)
+ STBTT_assert(x1 <= x);
+ else if (x0 >= x+1)
+ STBTT_assert(x1 >= x+1);
+ else
+ STBTT_assert(x1 >= x && x1 <= x+1);
+
+ if (x0 <= x && x1 <= x)
+ scanline[x] += e->direction * (y1-y0);
+ else if (x0 >= x+1 && x1 >= x+1)
+ ;
+ else {
+ STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
+ scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
+ }
+}
+
+static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
+{
+ float y_bottom = y_top+1;
+
+ while (e) {
+ // brute force every pixel
+
+ // compute intersection points with top & bottom
+ STBTT_assert(e->ey >= y_top);
+
+ if (e->fdx == 0) {
+ float x0 = e->fx;
+ if (x0 < len) {
+ if (x0 >= 0) {
+ stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
+ stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
+ } else {
+ stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
+ }
+ }
+ } else {
+ float x0 = e->fx;
+ float dx = e->fdx;
+ float xb = x0 + dx;
+ float x_top, x_bottom;
+ float sy0,sy1;
+ float dy = e->fdy;
+ STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
+
+ // compute endpoints of line segment clipped to this scanline (if the
+ // line segment starts on this scanline. x0 is the intersection of the
+ // line with y_top, but that may be off the line segment.
+ if (e->sy > y_top) {
+ x_top = x0 + dx * (e->sy - y_top);
+ sy0 = e->sy;
+ } else {
+ x_top = x0;
+ sy0 = y_top;
+ }
+ if (e->ey < y_bottom) {
+ x_bottom = x0 + dx * (e->ey - y_top);
+ sy1 = e->ey;
+ } else {
+ x_bottom = xb;
+ sy1 = y_bottom;
+ }
+
+ if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
+ // from here on, we don't have to range check x values
+
+ if ((int) x_top == (int) x_bottom) {
+ float height;
+ // simple case, only spans one pixel
+ int x = (int) x_top;
+ height = sy1 - sy0;
+ STBTT_assert(x >= 0 && x < len);
+ scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
+ scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
+ } else {
+ int x,x1,x2;
+ float y_crossing, step, sign, area;
+ // covers 2+ pixels
+ if (x_top > x_bottom) {
+ // flip scanline vertically; signed area is the same
+ float t;
+ sy0 = y_bottom - (sy0 - y_top);
+ sy1 = y_bottom - (sy1 - y_top);
+ t = sy0, sy0 = sy1, sy1 = t;
+ t = x_bottom, x_bottom = x_top, x_top = t;
+ dx = -dx;
+ dy = -dy;
+ t = x0, x0 = xb, xb = t;
+ }
+
+ x1 = (int) x_top;
+ x2 = (int) x_bottom;
+ // compute intersection with y axis at x1+1
+ y_crossing = (x1+1 - x0) * dy + y_top;
+
+ sign = e->direction;
+ // area of the rectangle covered from y0..y_crossing
+ area = sign * (y_crossing-sy0);
+ // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
+ scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
+
+ step = sign * dy;
+ for (x = x1+1; x < x2; ++x) {
+ scanline[x] += area + step/2;
+ area += step;
+ }
+ y_crossing += dy * (x2 - (x1+1));
+
+ STBTT_assert(STBTT_fabs(area) <= 1.01f);
+
+ scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
+
+ scanline_fill[x2] += sign * (sy1-sy0);
+ }
+ } else {
+ // if edge goes outside of box we're drawing, we require
+ // clipping logic. since this does not match the intended use
+ // of this library, we use a different, very slow brute
+ // force implementation
+ int x;
+ for (x=0; x < len; ++x) {
+ // cases:
+ //
+ // there can be up to two intersections with the pixel. any intersection
+ // with left or right edges can be handled by splitting into two (or three)
+ // regions. intersections with top & bottom do not necessitate case-wise logic.
+ //
+ // the old way of doing this found the intersections with the left & right edges,
+ // then used some simple logic to produce up to three segments in sorted order
+ // from top-to-bottom. however, this had a problem: if an x edge was epsilon
+ // across the x border, then the corresponding y position might not be distinct
+ // from the other y segment, and it might ignored as an empty segment. to avoid
+ // that, we need to explicitly produce segments based on x positions.
+
+ // rename variables to clearly-defined pairs
+ float y0 = y_top;
+ float x1 = (float) (x);
+ float x2 = (float) (x+1);
+ float x3 = xb;
+ float y3 = y_bottom;
+
+ // x = e->x + e->dx * (y-y_top)
+ // (y-y_top) = (x - e->x) / e->dx
+ // y = (x - e->x) / e->dx + y_top
+ float y1 = (x - x0) / dx + y_top;
+ float y2 = (x+1 - x0) / dx + y_top;
+
+ if (x0 < x1 && x3 > x2) { // three segments descending down-right
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
+ } else if (x3 < x1 && x0 > x2) { // three segments descending down-left
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
+ } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
+ } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
+ } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
+ } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
+ } else { // one segment
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
+ }
+ }
+ }
+ }
+ e = e->next;
+ }
+}
+
+// directly AA rasterize edges w/o supersampling
+static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
+{
+ stbtt__hheap hh = { 0, 0, 0 };
+ stbtt__active_edge *active = NULL;
+ int y,j=0, i;
+ float scanline_data[129], *scanline, *scanline2;
+
+ STBTT__NOTUSED(vsubsample);
+
+ if (result->w > 64)
+ scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
+ else
+ scanline = scanline_data;
+
+ scanline2 = scanline + result->w;
+
+ y = off_y;
+ e[n].y0 = (float) (off_y + result->h) + 1;
+
+ while (j < result->h) {
+ // find center of pixel for this scanline
+ float scan_y_top = y + 0.0f;
+ float scan_y_bottom = y + 1.0f;
+ stbtt__active_edge **step = &active;
+
+ STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
+ STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
+
+ // update all active edges;
+ // remove all active edges that terminate before the top of this scanline
+ while (*step) {
+ stbtt__active_edge * z = *step;
+ if (z->ey <= scan_y_top) {
+ *step = z->next; // delete from list
+ STBTT_assert(z->direction);
+ z->direction = 0;
+ stbtt__hheap_free(&hh, z);
+ } else {
+ step = &((*step)->next); // advance through list
+ }
+ }
+
+ // insert all edges that start before the bottom of this scanline
+ while (e->y0 <= scan_y_bottom) {
+ if (e->y0 != e->y1) {
+ stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
+ if (z != NULL) {
+ STBTT_assert(z->ey >= scan_y_top);
+ // insert at front
+ z->next = active;
+ active = z;
+ }
+ }
+ ++e;
+ }
+
+ // now process all active edges
+ if (active)
+ stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
+
+ {
+ float sum = 0;
+ for (i=0; i < result->w; ++i) {
+ float k;
+ int m;
+ sum += scanline2[i];
+ k = scanline[i] + sum;
+ k = (float) STBTT_fabs(k)*255 + 0.5f;
+ m = (int) k;
+ if (m > 255) m = 255;
+ result->pixels[j*result->stride + i] = (unsigned char) m;
+ }
+ }
+ // advance all the edges
+ step = &active;
+ while (*step) {
+ stbtt__active_edge *z = *step;
+ z->fx += z->fdx; // advance to position for current scanline
+ step = &((*step)->next); // advance through list
+ }
+
+ ++y;
+ ++j;
+ }
+
+ stbtt__hheap_cleanup(&hh, userdata);
+
+ if (scanline != scanline_data)
+ STBTT_free(scanline, userdata);
+}
+#else
+#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#endif
+
+#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
+
+static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
+{
+ int i,j;
+ for (i=1; i < n; ++i) {
+ stbtt__edge t = p[i], *a = &t;
+ j = i;
+ while (j > 0) {
+ stbtt__edge *b = &p[j-1];
+ int c = STBTT__COMPARE(a,b);
+ if (!c) break;
+ p[j] = p[j-1];
+ --j;
+ }
+ if (i != j)
+ p[j] = t;
+ }
+}
+
+static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
+{
+ /* threshhold for transitioning to insertion sort */
+ while (n > 12) {
+ stbtt__edge t;
+ int c01,c12,c,m,i,j;
+
+ /* compute median of three */
+ m = n >> 1;
+ c01 = STBTT__COMPARE(&p[0],&p[m]);
+ c12 = STBTT__COMPARE(&p[m],&p[n-1]);
+ /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
+ if (c01 != c12) {
+ /* otherwise, we'll need to swap something else to middle */
+ int z;
+ c = STBTT__COMPARE(&p[0],&p[n-1]);
+ /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
+ /* 0<mid && mid>n: 0>n => 0; 0<n => n */
+ z = (c == c12) ? 0 : n-1;
+ t = p[z];
+ p[z] = p[m];
+ p[m] = t;
+ }
+ /* now p[m] is the median-of-three */
+ /* swap it to the beginning so it won't move around */
+ t = p[0];
+ p[0] = p[m];
+ p[m] = t;
+
+ /* partition loop */
+ i=1;
+ j=n-1;
+ for(;;) {
+ /* handling of equality is crucial here */
+ /* for sentinels & efficiency with duplicates */
+ for (;;++i) {
+ if (!STBTT__COMPARE(&p[i], &p[0])) break;
+ }
+ for (;;--j) {
+ if (!STBTT__COMPARE(&p[0], &p[j])) break;
+ }
+ /* make sure we haven't crossed */
+ if (i >= j) break;
+ t = p[i];
+ p[i] = p[j];
+ p[j] = t;
+
+ ++i;
+ --j;
+ }
+ /* recurse on smaller side, iterate on larger */
+ if (j < (n-i)) {
+ stbtt__sort_edges_quicksort(p,j);
+ p = p+i;
+ n = n-i;
+ } else {
+ stbtt__sort_edges_quicksort(p+i, n-i);
+ n = j;
+ }
+ }
+}
+
+static void stbtt__sort_edges(stbtt__edge *p, int n)
+{
+ stbtt__sort_edges_quicksort(p, n);
+ stbtt__sort_edges_ins_sort(p, n);
+}
+
+typedef struct
+{
+ float x,y;
+} stbtt__point;
+
+static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
+{
+ float y_scale_inv = invert ? -scale_y : scale_y;
+ stbtt__edge *e;
+ int n,i,j,k,m;
+#if STBTT_RASTERIZER_VERSION == 1
+ int vsubsample = result->h < 8 ? 15 : 5;
+#elif STBTT_RASTERIZER_VERSION == 2
+ int vsubsample = 1;
+#else
+ #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#endif
+ // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
+
+ // now we have to blow out the windings into explicit edge lists
+ n = 0;
+ for (i=0; i < windings; ++i)
+ n += wcount[i];
+
+ e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
+ if (e == 0) return;
+ n = 0;
+
+ m=0;
+ for (i=0; i < windings; ++i) {
+ stbtt__point *p = pts + m;
+ m += wcount[i];
+ j = wcount[i]-1;
+ for (k=0; k < wcount[i]; j=k++) {
+ int a=k,b=j;
+ // skip the edge if horizontal
+ if (p[j].y == p[k].y)
+ continue;
+ // add edge from j to k to the list
+ e[n].invert = 0;
+ if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
+ e[n].invert = 1;
+ a=j,b=k;
+ }
+ e[n].x0 = p[a].x * scale_x + shift_x;
+ e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
+ e[n].x1 = p[b].x * scale_x + shift_x;
+ e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
+ ++n;
+ }
+ }
+
+ // now sort the edges by their highest point (should snap to integer, and then by x)
+ //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
+ stbtt__sort_edges(e, n);
+
+ // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
+ stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
+
+ STBTT_free(e, userdata);
+}
+
+static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
+{
+ if (!points) return; // during first pass, it's unallocated
+ points[n].x = x;
+ points[n].y = y;
+}
+
+// tesselate until threshhold p is happy... @TODO warped to compensate for non-linear stretching
+static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
+{
+ // midpoint
+ float mx = (x0 + 2*x1 + x2)/4;
+ float my = (y0 + 2*y1 + y2)/4;
+ // versus directly drawn line
+ float dx = (x0+x2)/2 - mx;
+ float dy = (y0+y2)/2 - my;
+ if (n > 16) // 65536 segments on one curve better be enough!
+ return 1;
+ if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
+ stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
+ stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
+ } else {
+ stbtt__add_point(points, *num_points,x2,y2);
+ *num_points = *num_points+1;
+ }
+ return 1;
+}
+
+static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
+{
+ // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
+ float dx0 = x1-x0;
+ float dy0 = y1-y0;
+ float dx1 = x2-x1;
+ float dy1 = y2-y1;
+ float dx2 = x3-x2;
+ float dy2 = y3-y2;
+ float dx = x3-x0;
+ float dy = y3-y0;
+ float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
+ float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
+ float flatness_squared = longlen*longlen-shortlen*shortlen;
+
+ if (n > 16) // 65536 segments on one curve better be enough!
+ return;
+
+ if (flatness_squared > objspace_flatness_squared) {
+ float x01 = (x0+x1)/2;
+ float y01 = (y0+y1)/2;
+ float x12 = (x1+x2)/2;
+ float y12 = (y1+y2)/2;
+ float x23 = (x2+x3)/2;
+ float y23 = (y2+y3)/2;
+
+ float xa = (x01+x12)/2;
+ float ya = (y01+y12)/2;
+ float xb = (x12+x23)/2;
+ float yb = (y12+y23)/2;
+
+ float mx = (xa+xb)/2;
+ float my = (ya+yb)/2;
+
+ stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
+ stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
+ } else {
+ stbtt__add_point(points, *num_points,x3,y3);
+ *num_points = *num_points+1;
+ }
+}
+
+// returns number of contours
+static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
+{
+ stbtt__point *points=0;
+ int num_points=0;
+
+ float objspace_flatness_squared = objspace_flatness * objspace_flatness;
+ int i,n=0,start=0, pass;
+
+ // count how many "moves" there are to get the contour count
+ for (i=0; i < num_verts; ++i)
+ if (vertices[i].type == STBTT_vmove)
+ ++n;
+
+ *num_contours = n;
+ if (n == 0) return 0;
+
+ *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
+
+ if (*contour_lengths == 0) {
+ *num_contours = 0;
+ return 0;
+ }
+
+ // make two passes through the points so we don't need to realloc
+ for (pass=0; pass < 2; ++pass) {
+ float x=0,y=0;
+ if (pass == 1) {
+ points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
+ if (points == NULL) goto error;
+ }
+ num_points = 0;
+ n= -1;
+ for (i=0; i < num_verts; ++i) {
+ switch (vertices[i].type) {
+ case STBTT_vmove:
+ // start the next contour
+ if (n >= 0)
+ (*contour_lengths)[n] = num_points - start;
+ ++n;
+ start = num_points;
+
+ x = vertices[i].x, y = vertices[i].y;
+ stbtt__add_point(points, num_points++, x,y);
+ break;
+ case STBTT_vline:
+ x = vertices[i].x, y = vertices[i].y;
+ stbtt__add_point(points, num_points++, x, y);
+ break;
+ case STBTT_vcurve:
+ stbtt__tesselate_curve(points, &num_points, x,y,
+ vertices[i].cx, vertices[i].cy,
+ vertices[i].x, vertices[i].y,
+ objspace_flatness_squared, 0);
+ x = vertices[i].x, y = vertices[i].y;
+ break;
+ case STBTT_vcubic:
+ stbtt__tesselate_cubic(points, &num_points, x,y,
+ vertices[i].cx, vertices[i].cy,
+ vertices[i].cx1, vertices[i].cy1,
+ vertices[i].x, vertices[i].y,
+ objspace_flatness_squared, 0);
+ x = vertices[i].x, y = vertices[i].y;
+ break;
+ }
+ }
+ (*contour_lengths)[n] = num_points - start;
+ }
+
+ return points;
+error:
+ STBTT_free(points, userdata);
+ STBTT_free(*contour_lengths, userdata);
+ *contour_lengths = 0;
+ *num_contours = 0;
+ return NULL;
+}
+
+STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
+{
+ float scale = scale_x > scale_y ? scale_y : scale_x;
+ int winding_count = 0;
+ int *winding_lengths = NULL;
+ stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
+ if (windings) {
+ stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
+ STBTT_free(winding_lengths, userdata);
+ STBTT_free(windings, userdata);
+ }
+}
+
+STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
+{
+ STBTT_free(bitmap, userdata);
+}
+
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
+{
+ int ix0,iy0,ix1,iy1;
+ stbtt__bitmap gbm;
+ stbtt_vertex *vertices;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
+
+ if (scale_x == 0) scale_x = scale_y;
+ if (scale_y == 0) {
+ if (scale_x == 0) {
+ STBTT_free(vertices, info->userdata);
+ return NULL;
+ }
+ scale_y = scale_x;
+ }
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
+
+ // now we get the size
+ gbm.w = (ix1 - ix0);
+ gbm.h = (iy1 - iy0);
+ gbm.pixels = NULL; // in case we error
+
+ if (width ) *width = gbm.w;
+ if (height) *height = gbm.h;
+ if (xoff ) *xoff = ix0;
+ if (yoff ) *yoff = iy0;
+
+ if (gbm.w && gbm.h) {
+ gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
+ if (gbm.pixels) {
+ gbm.stride = gbm.w;
+
+ stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
+ }
+ }
+ STBTT_free(vertices, info->userdata);
+ return gbm.pixels;
+}
+
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
+}
+
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
+{
+ int ix0,iy0;
+ stbtt_vertex *vertices;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
+ stbtt__bitmap gbm;
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
+ gbm.pixels = output;
+ gbm.w = out_w;
+ gbm.h = out_h;
+ gbm.stride = out_stride;
+
+ if (gbm.w && gbm.h)
+ stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
+
+ STBTT_free(vertices, info->userdata);
+}
+
+STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
+{
+ stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
+}
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
+{
+ stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
+{
+ stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
+}
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
+{
+ stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// bitmap baking
+//
+// This is SUPER-CRAPPY packing to keep source code small
+
+static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
+ float pixel_height, // height of font in pixels
+ unsigned char *pixels, int pw, int ph, // bitmap to be filled in
+ int first_char, int num_chars, // characters to bake
+ stbtt_bakedchar *chardata)
+{
+ float scale;
+ int x,y,bottom_y, i;
+ stbtt_fontinfo f;
+ f.userdata = NULL;
+ if (!stbtt_InitFont(&f, data, offset))
+ return -1;
+ STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
+ x=y=1;
+ bottom_y = 1;
+
+ scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
+
+ for (i=0; i < num_chars; ++i) {
+ int advance, lsb, x0,y0,x1,y1,gw,gh;
+ int g = stbtt_FindGlyphIndex(&f, first_char + i);
+ stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
+ stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
+ gw = x1-x0;
+ gh = y1-y0;
+ if (x + gw + 1 >= pw)
+ y = bottom_y, x = 1; // advance to next row
+ if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
+ return -i;
+ STBTT_assert(x+gw < pw);
+ STBTT_assert(y+gh < ph);
+ stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
+ chardata[i].x0 = (stbtt_int16) x;
+ chardata[i].y0 = (stbtt_int16) y;
+ chardata[i].x1 = (stbtt_int16) (x + gw);
+ chardata[i].y1 = (stbtt_int16) (y + gh);
+ chardata[i].xadvance = scale * advance;
+ chardata[i].xoff = (float) x0;
+ chardata[i].yoff = (float) y0;
+ x = x + gw + 1;
+ if (y+gh+1 > bottom_y)
+ bottom_y = y+gh+1;
+ }
+ return bottom_y;
+}
+
+STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
+{
+ float d3d_bias = opengl_fillrule ? 0 : -0.5f;
+ float ipw = 1.0f / pw, iph = 1.0f / ph;
+ const stbtt_bakedchar *b = chardata + char_index;
+ int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
+ int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
+
+ q->x0 = round_x + d3d_bias;
+ q->y0 = round_y + d3d_bias;
+ q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
+ q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
+
+ q->s0 = b->x0 * ipw;
+ q->t0 = b->y0 * iph;
+ q->s1 = b->x1 * ipw;
+ q->t1 = b->y1 * iph;
+
+ *xpos += b->xadvance;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// rectangle packing replacement routines if you don't have stb_rect_pack.h
+//
+
+#ifndef STB_RECT_PACK_VERSION
+
+typedef int stbrp_coord;
+
+////////////////////////////////////////////////////////////////////////////////////
+// //
+// //
+// COMPILER WARNING ?!?!? //
+// //
+// //
+// if you get a compile warning due to these symbols being defined more than //
+// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
+// //
+////////////////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+ int width,height;
+ int x,y,bottom_y;
+} stbrp_context;
+
+typedef struct
+{
+ unsigned char x;
+} stbrp_node;
+
+struct stbrp_rect
+{
+ stbrp_coord x,y;
+ int id,w,h,was_packed;
+};
+
+static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
+{
+ con->width = pw;
+ con->height = ph;
+ con->x = 0;
+ con->y = 0;
+ con->bottom_y = 0;
+ STBTT__NOTUSED(nodes);
+ STBTT__NOTUSED(num_nodes);
+}
+
+static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
+{
+ int i;
+ for (i=0; i < num_rects; ++i) {
+ if (con->x + rects[i].w > con->width) {
+ con->x = 0;
+ con->y = con->bottom_y;
+ }
+ if (con->y + rects[i].h > con->height)
+ break;
+ rects[i].x = con->x;
+ rects[i].y = con->y;
+ rects[i].was_packed = 1;
+ con->x += rects[i].w;
+ if (con->y + rects[i].h > con->bottom_y)
+ con->bottom_y = con->y + rects[i].h;
+ }
+ for ( ; i < num_rects; ++i)
+ rects[i].was_packed = 0;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// bitmap baking
+//
+// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
+// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
+
+STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
+{
+ stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
+ int num_nodes = pw - padding;
+ stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
+
+ if (context == NULL || nodes == NULL) {
+ if (context != NULL) STBTT_free(context, alloc_context);
+ if (nodes != NULL) STBTT_free(nodes , alloc_context);
+ return 0;
+ }
+
+ spc->user_allocator_context = alloc_context;
+ spc->width = pw;
+ spc->height = ph;
+ spc->pixels = pixels;
+ spc->pack_info = context;
+ spc->nodes = nodes;
+ spc->padding = padding;
+ spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
+ spc->h_oversample = 1;
+ spc->v_oversample = 1;
+
+ stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
+
+ if (pixels)
+ STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
+
+ return 1;
+}
+
+STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
+{
+ STBTT_free(spc->nodes , spc->user_allocator_context);
+ STBTT_free(spc->pack_info, spc->user_allocator_context);
+}
+
+STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
+{
+ STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
+ STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
+ if (h_oversample <= STBTT_MAX_OVERSAMPLE)
+ spc->h_oversample = h_oversample;
+ if (v_oversample <= STBTT_MAX_OVERSAMPLE)
+ spc->v_oversample = v_oversample;
+}
+
+#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
+
+static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
+{
+ unsigned char buffer[STBTT_MAX_OVERSAMPLE];
+ int safe_w = w - kernel_width;
+ int j;
+ STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
+ for (j=0; j < h; ++j) {
+ int i;
+ unsigned int total;
+ STBTT_memset(buffer, 0, kernel_width);
+
+ total = 0;
+
+ // make kernel_width a constant in common cases so compiler can optimize out the divide
+ switch (kernel_width) {
+ case 2:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 2);
+ }
+ break;
+ case 3:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 3);
+ }
+ break;
+ case 4:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 4);
+ }
+ break;
+ case 5:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 5);
+ }
+ break;
+ default:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / kernel_width);
+ }
+ break;
+ }
+
+ for (; i < w; ++i) {
+ STBTT_assert(pixels[i] == 0);
+ total -= buffer[i & STBTT__OVER_MASK];
+ pixels[i] = (unsigned char) (total / kernel_width);
+ }
+
+ pixels += stride_in_bytes;
+ }
+}
+
+static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
+{
+ unsigned char buffer[STBTT_MAX_OVERSAMPLE];
+ int safe_h = h - kernel_width;
+ int j;
+ STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
+ for (j=0; j < w; ++j) {
+ int i;
+ unsigned int total;
+ STBTT_memset(buffer, 0, kernel_width);
+
+ total = 0;
+
+ // make kernel_width a constant in common cases so compiler can optimize out the divide
+ switch (kernel_width) {
+ case 2:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
+ }
+ break;
+ case 3:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
+ }
+ break;
+ case 4:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
+ }
+ break;
+ case 5:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
+ }
+ break;
+ default:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
+ }
+ break;
+ }
+
+ for (; i < h; ++i) {
+ STBTT_assert(pixels[i*stride_in_bytes] == 0);
+ total -= buffer[i & STBTT__OVER_MASK];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
+ }
+
+ pixels += 1;
+ }
+}
+
+static float stbtt__oversample_shift(int oversample)
+{
+ if (!oversample)
+ return 0.0f;
+
+ // The prefilter is a box filter of width "oversample",
+ // which shifts phase by (oversample - 1)/2 pixels in
+ // oversampled space. We want to shift in the opposite
+ // direction to counter this.
+ return (float)-(oversample - 1) / (2.0f * (float)oversample);
+}
+
+// rects array must be big enough to accommodate all characters in the given ranges
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
+{
+ int i,j,k;
+
+ k=0;
+ for (i=0; i < num_ranges; ++i) {
+ float fh = ranges[i].font_size;
+ float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
+ ranges[i].h_oversample = (unsigned char) spc->h_oversample;
+ ranges[i].v_oversample = (unsigned char) spc->v_oversample;
+ for (j=0; j < ranges[i].num_chars; ++j) {
+ int x0,y0,x1,y1;
+ int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
+ int glyph = stbtt_FindGlyphIndex(info, codepoint);
+ stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ 0,0,
+ &x0,&y0,&x1,&y1);
+ rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
+ rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
+ ++k;
+ }
+ }
+
+ return k;
+}
+
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
+{
+ stbtt_MakeGlyphBitmapSubpixel(info,
+ output,
+ out_w - (prefilter_x - 1),
+ out_h - (prefilter_y - 1),
+ out_stride,
+ scale_x,
+ scale_y,
+ shift_x,
+ shift_y,
+ glyph);
+
+ if (prefilter_x > 1)
+ stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
+
+ if (prefilter_y > 1)
+ stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
+
+ *sub_x = stbtt__oversample_shift(prefilter_x);
+ *sub_y = stbtt__oversample_shift(prefilter_y);
+}
+
+// rects array must be big enough to accommodate all characters in the given ranges
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
+{
+ int i,j,k, return_value = 1;
+
+ // save current values
+ int old_h_over = spc->h_oversample;
+ int old_v_over = spc->v_oversample;
+
+ k = 0;
+ for (i=0; i < num_ranges; ++i) {
+ float fh = ranges[i].font_size;
+ float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
+ float recip_h,recip_v,sub_x,sub_y;
+ spc->h_oversample = ranges[i].h_oversample;
+ spc->v_oversample = ranges[i].v_oversample;
+ recip_h = 1.0f / spc->h_oversample;
+ recip_v = 1.0f / spc->v_oversample;
+ sub_x = stbtt__oversample_shift(spc->h_oversample);
+ sub_y = stbtt__oversample_shift(spc->v_oversample);
+ for (j=0; j < ranges[i].num_chars; ++j) {
+ stbrp_rect *r = &rects[k];
+ if (r->was_packed) {
+ stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
+ int advance, lsb, x0,y0,x1,y1;
+ int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
+ int glyph = stbtt_FindGlyphIndex(info, codepoint);
+ stbrp_coord pad = (stbrp_coord) spc->padding;
+
+ // pad on left and top
+ r->x += pad;
+ r->y += pad;
+ r->w -= pad;
+ r->h -= pad;
+ stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
+ stbtt_GetGlyphBitmapBox(info, glyph,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ &x0,&y0,&x1,&y1);
+ stbtt_MakeGlyphBitmapSubpixel(info,
+ spc->pixels + r->x + r->y*spc->stride_in_bytes,
+ r->w - spc->h_oversample+1,
+ r->h - spc->v_oversample+1,
+ spc->stride_in_bytes,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ 0,0,
+ glyph);
+
+ if (spc->h_oversample > 1)
+ stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
+ r->w, r->h, spc->stride_in_bytes,
+ spc->h_oversample);
+
+ if (spc->v_oversample > 1)
+ stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
+ r->w, r->h, spc->stride_in_bytes,
+ spc->v_oversample);
+
+ bc->x0 = (stbtt_int16) r->x;
+ bc->y0 = (stbtt_int16) r->y;
+ bc->x1 = (stbtt_int16) (r->x + r->w);
+ bc->y1 = (stbtt_int16) (r->y + r->h);
+ bc->xadvance = scale * advance;
+ bc->xoff = (float) x0 * recip_h + sub_x;
+ bc->yoff = (float) y0 * recip_v + sub_y;
+ bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
+ bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
+ } else {
+ return_value = 0; // if any fail, report failure
+ }
+
+ ++k;
+ }
+ }
+
+ // restore original values
+ spc->h_oversample = old_h_over;
+ spc->v_oversample = old_v_over;
+
+ return return_value;
+}
+
+STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
+{
+ stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
+}
+
+STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
+{
+ stbtt_fontinfo info;
+ int i,j,n, return_value = 1;
+ //stbrp_context *context = (stbrp_context *) spc->pack_info;
+ stbrp_rect *rects;
+
+ // flag all characters as NOT packed
+ for (i=0; i < num_ranges; ++i)
+ for (j=0; j < ranges[i].num_chars; ++j)
+ ranges[i].chardata_for_range[j].x0 =
+ ranges[i].chardata_for_range[j].y0 =
+ ranges[i].chardata_for_range[j].x1 =
+ ranges[i].chardata_for_range[j].y1 = 0;
+
+ n = 0;
+ for (i=0; i < num_ranges; ++i)
+ n += ranges[i].num_chars;
+
+ rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
+ if (rects == NULL)
+ return 0;
+
+ info.userdata = spc->user_allocator_context;
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
+
+ n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
+
+ stbtt_PackFontRangesPackRects(spc, rects, n);
+
+ return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
+
+ STBTT_free(rects, spc->user_allocator_context);
+ return return_value;
+}
+
+STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
+ int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
+{
+ stbtt_pack_range range;
+ range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
+ range.array_of_unicode_codepoints = NULL;
+ range.num_chars = num_chars_in_range;
+ range.chardata_for_range = chardata_for_range;
+ range.font_size = font_size;
+ return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
+}
+
+STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
+{
+ float ipw = 1.0f / pw, iph = 1.0f / ph;
+ const stbtt_packedchar *b = chardata + char_index;
+
+ if (align_to_integer) {
+ float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
+ float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
+ q->x0 = x;
+ q->y0 = y;
+ q->x1 = x + b->xoff2 - b->xoff;
+ q->y1 = y + b->yoff2 - b->yoff;
+ } else {
+ q->x0 = *xpos + b->xoff;
+ q->y0 = *ypos + b->yoff;
+ q->x1 = *xpos + b->xoff2;
+ q->y1 = *ypos + b->yoff2;
+ }
+
+ q->s0 = b->x0 * ipw;
+ q->t0 = b->y0 * iph;
+ q->s1 = b->x1 * ipw;
+ q->t1 = b->y1 * iph;
+
+ *xpos += b->xadvance;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// sdf computation
+//
+
+#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
+#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
+
+static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
+{
+ float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
+ float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
+ float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
+ float roperp = orig[1]*ray[0] - orig[0]*ray[1];
+
+ float a = q0perp - 2*q1perp + q2perp;
+ float b = q1perp - q0perp;
+ float c = q0perp - roperp;
+
+ float s0 = 0., s1 = 0.;
+ int num_s = 0;
+
+ if (a != 0.0) {
+ float discr = b*b - a*c;
+ if (discr > 0.0) {
+ float rcpna = -1 / a;
+ float d = (float) STBTT_sqrt(discr);
+ s0 = (b+d) * rcpna;
+ s1 = (b-d) * rcpna;
+ if (s0 >= 0.0 && s0 <= 1.0)
+ num_s = 1;
+ if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
+ if (num_s == 0) s0 = s1;
+ ++num_s;
+ }
+ }
+ } else {
+ // 2*b*s + c = 0
+ // s = -c / (2*b)
+ s0 = c / (-2 * b);
+ if (s0 >= 0.0 && s0 <= 1.0)
+ num_s = 1;
+ }
+
+ if (num_s == 0)
+ return 0;
+ else {
+ float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
+ float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
+
+ float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
+ float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
+ float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
+ float rod = orig[0]*rayn_x + orig[1]*rayn_y;
+
+ float q10d = q1d - q0d;
+ float q20d = q2d - q0d;
+ float q0rd = q0d - rod;
+
+ hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
+ hits[0][1] = a*s0+b;
+
+ if (num_s > 1) {
+ hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
+ hits[1][1] = a*s1+b;
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+}
+
+static int equal(float *a, float *b)
+{
+ return (a[0] == b[0] && a[1] == b[1]);
+}
+
+static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
+{
+ int i;
+ float orig[2], ray[2] = { 1, 0 };
+ float y_frac;
+ int winding = 0;
+
+ orig[0] = x;
+ orig[1] = y;
+
+ // make sure y never passes through a vertex of the shape
+ y_frac = (float) STBTT_fmod(y, 1.0f);
+ if (y_frac < 0.01f)
+ y += 0.01f;
+ else if (y_frac > 0.99f)
+ y -= 0.01f;
+ orig[1] = y;
+
+ // test a ray from (-infinity,y) to (x,y)
+ for (i=0; i < nverts; ++i) {
+ if (verts[i].type == STBTT_vline) {
+ int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
+ int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
+ if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
+ float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
+ if (x_inter < x)
+ winding += (y0 < y1) ? 1 : -1;
+ }
+ }
+ if (verts[i].type == STBTT_vcurve) {
+ int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
+ int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
+ int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
+ int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
+ int by = STBTT_max(y0,STBTT_max(y1,y2));
+ if (y > ay && y < by && x > ax) {
+ float q0[2],q1[2],q2[2];
+ float hits[2][2];
+ q0[0] = (float)x0;
+ q0[1] = (float)y0;
+ q1[0] = (float)x1;
+ q1[1] = (float)y1;
+ q2[0] = (float)x2;
+ q2[1] = (float)y2;
+ if (equal(q0,q1) || equal(q1,q2)) {
+ x0 = (int)verts[i-1].x;
+ y0 = (int)verts[i-1].y;
+ x1 = (int)verts[i ].x;
+ y1 = (int)verts[i ].y;
+ if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
+ float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
+ if (x_inter < x)
+ winding += (y0 < y1) ? 1 : -1;
+ }
+ } else {
+ int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
+ if (num_hits >= 1)
+ if (hits[0][0] < 0)
+ winding += (hits[0][1] < 0 ? -1 : 1);
+ if (num_hits >= 2)
+ if (hits[1][0] < 0)
+ winding += (hits[1][1] < 0 ? -1 : 1);
+ }
+ }
+ }
+ }
+ return winding;
+}
+
+static float stbtt__cuberoot( float x )
+{
+ if (x<0)
+ return -(float) STBTT_pow(-x,1.0f/3.0f);
+ else
+ return (float) STBTT_pow( x,1.0f/3.0f);
+}
+
+// x^3 + c*x^2 + b*x + a = 0
+static int stbtt__solve_cubic(float a, float b, float c, float* r)
+{
+ float s = -a / 3;
+ float p = b - a*a / 3;
+ float q = a * (2*a*a - 9*b) / 27 + c;
+ float p3 = p*p*p;
+ float d = q*q + 4*p3 / 27;
+ if (d >= 0) {
+ float z = (float) STBTT_sqrt(d);
+ float u = (-q + z) / 2;
+ float v = (-q - z) / 2;
+ u = stbtt__cuberoot(u);
+ v = stbtt__cuberoot(v);
+ r[0] = s + u + v;
+ return 1;
+ } else {
+ float u = (float) STBTT_sqrt(-p/3);
+ float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
+ float m = (float) STBTT_cos(v);
+ float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
+ r[0] = s + u * 2 * m;
+ r[1] = s - u * (m + n);
+ r[2] = s - u * (m - n);
+
+ //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
+ //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
+ //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
+ return 3;
+ }
+}
+
+STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
+{
+ float scale_x = scale, scale_y = scale;
+ int ix0,iy0,ix1,iy1;
+ int w,h;
+ unsigned char *data;
+
+ // if one scale is 0, use same scale for both
+ if (scale_x == 0) scale_x = scale_y;
+ if (scale_y == 0) {
+ if (scale_x == 0) return NULL; // if both scales are 0, return NULL
+ scale_y = scale_x;
+ }
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
+
+ // if empty, return NULL
+ if (ix0 == ix1 || iy0 == iy1)
+ return NULL;
+
+ ix0 -= padding;
+ iy0 -= padding;
+ ix1 += padding;
+ iy1 += padding;
+
+ w = (ix1 - ix0);
+ h = (iy1 - iy0);
+
+ if (width ) *width = w;
+ if (height) *height = h;
+ if (xoff ) *xoff = ix0;
+ if (yoff ) *yoff = iy0;
+
+ // invert for y-downwards bitmaps
+ scale_y = -scale_y;
+
+ {
+ int x,y,i,j;
+ float *precompute;
+ stbtt_vertex *verts;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
+ data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
+ precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
+
+ for (i=0,j=num_verts-1; i < num_verts; j=i++) {
+ if (verts[i].type == STBTT_vline) {
+ float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
+ float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
+ float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
+ precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
+ } else if (verts[i].type == STBTT_vcurve) {
+ float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
+ float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
+ float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
+ float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
+ float len2 = bx*bx + by*by;
+ if (len2 != 0.0f)
+ precompute[i] = 1.0f / (bx*bx + by*by);
+ else
+ precompute[i] = 0.0f;
+ } else
+ precompute[i] = 0.0f;
+ }
+
+ for (y=iy0; y < iy1; ++y) {
+ for (x=ix0; x < ix1; ++x) {
+ float val;
+ float min_dist = 999999.0f;
+ float sx = (float) x + 0.5f;
+ float sy = (float) y + 0.5f;
+ float x_gspace = (sx / scale_x);
+ float y_gspace = (sy / scale_y);
+
+ int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
+
+ for (i=0; i < num_verts; ++i) {
+ float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
+
+ // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
+ float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
+ if (dist2 < min_dist*min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+
+ if (verts[i].type == STBTT_vline) {
+ float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
+
+ // coarse culling against bbox
+ //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
+ // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
+ float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
+ STBTT_assert(i != 0);
+ if (dist < min_dist) {
+ // check position along line
+ // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
+ // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
+ float dx = x1-x0, dy = y1-y0;
+ float px = x0-sx, py = y0-sy;
+ // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
+ // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
+ float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
+ if (t >= 0.0f && t <= 1.0f)
+ min_dist = dist;
+ }
+ } else if (verts[i].type == STBTT_vcurve) {
+ float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
+ float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
+ float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
+ float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
+ float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
+ float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
+ // coarse culling against bbox to avoid computing cubic unnecessarily
+ if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
+ int num=0;
+ float ax = x1-x0, ay = y1-y0;
+ float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
+ float mx = x0 - sx, my = y0 - sy;
+ float res[3],px,py,t,it;
+ float a_inv = precompute[i];
+ if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
+ float a = 3*(ax*bx + ay*by);
+ float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
+ float c = mx*ax+my*ay;
+ if (a == 0.0) { // if a is 0, it's linear
+ if (b != 0.0) {
+ res[num++] = -c/b;
+ }
+ } else {
+ float discriminant = b*b - 4*a*c;
+ if (discriminant < 0)
+ num = 0;
+ else {
+ float root = (float) STBTT_sqrt(discriminant);
+ res[0] = (-b - root)/(2*a);
+ res[1] = (-b + root)/(2*a);
+ num = 2; // don't bother distinguishing 1-solution case, as code below will still work
+ }
+ }
+ } else {
+ float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
+ float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
+ float d = (mx*ax+my*ay) * a_inv;
+ num = stbtt__solve_cubic(b, c, d, res);
+ }
+ if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
+ t = res[0], it = 1.0f - t;
+ px = it*it*x0 + 2*t*it*x1 + t*t*x2;
+ py = it*it*y0 + 2*t*it*y1 + t*t*y2;
+ dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+ }
+ if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
+ t = res[1], it = 1.0f - t;
+ px = it*it*x0 + 2*t*it*x1 + t*t*x2;
+ py = it*it*y0 + 2*t*it*y1 + t*t*y2;
+ dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+ }
+ if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
+ t = res[2], it = 1.0f - t;
+ px = it*it*x0 + 2*t*it*x1 + t*t*x2;
+ py = it*it*y0 + 2*t*it*y1 + t*t*y2;
+ dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+ }
+ }
+ }
+ }
+ if (winding == 0)
+ min_dist = -min_dist; // if outside the shape, value is negative
+ val = onedge_value + pixel_dist_scale * min_dist;
+ if (val < 0)
+ val = 0;
+ else if (val > 255)
+ val = 255;
+ data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
+ }
+ }
+ STBTT_free(precompute, info->userdata);
+ STBTT_free(verts, info->userdata);
+ }
+ return data;
+}
+
+STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
+}
+
+STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
+{
+ STBTT_free(bitmap, userdata);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// font name matching -- recommended not to use this
+//
+
+// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
+static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
+{
+ stbtt_int32 i=0;
+
+ // convert utf16 to utf8 and compare the results while converting
+ while (len2) {
+ stbtt_uint16 ch = s2[0]*256 + s2[1];
+ if (ch < 0x80) {
+ if (i >= len1) return -1;
+ if (s1[i++] != ch) return -1;
+ } else if (ch < 0x800) {
+ if (i+1 >= len1) return -1;
+ if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
+ if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
+ } else if (ch >= 0xd800 && ch < 0xdc00) {
+ stbtt_uint32 c;
+ stbtt_uint16 ch2 = s2[2]*256 + s2[3];
+ if (i+3 >= len1) return -1;
+ c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
+ if (s1[i++] != 0xf0 + (c >> 18)) return -1;
+ if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
+ if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
+ if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
+ s2 += 2; // plus another 2 below
+ len2 -= 2;
+ } else if (ch >= 0xdc00 && ch < 0xe000) {
+ return -1;
+ } else {
+ if (i+2 >= len1) return -1;
+ if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
+ if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
+ if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
+ }
+ s2 += 2;
+ len2 -= 2;
+ }
+ return i;
+}
+
+static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
+{
+ return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
+}
+
+// returns results in whatever encoding you request... but note that 2-byte encodings
+// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
+STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
+{
+ stbtt_int32 i,count,stringOffset;
+ stbtt_uint8 *fc = font->data;
+ stbtt_uint32 offset = font->fontstart;
+ stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
+ if (!nm) return NULL;
+
+ count = ttUSHORT(fc+nm+2);
+ stringOffset = nm + ttUSHORT(fc+nm+4);
+ for (i=0; i < count; ++i) {
+ stbtt_uint32 loc = nm + 6 + 12 * i;
+ if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
+ && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
+ *length = ttUSHORT(fc+loc+8);
+ return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
+ }
+ }
+ return NULL;
+}
+
+static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
+{
+ stbtt_int32 i;
+ stbtt_int32 count = ttUSHORT(fc+nm+2);
+ stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
+
+ for (i=0; i < count; ++i) {
+ stbtt_uint32 loc = nm + 6 + 12 * i;
+ stbtt_int32 id = ttUSHORT(fc+loc+6);
+ if (id == target_id) {
+ // find the encoding
+ stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
+
+ // is this a Unicode encoding?
+ if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
+ stbtt_int32 slen = ttUSHORT(fc+loc+8);
+ stbtt_int32 off = ttUSHORT(fc+loc+10);
+
+ // check if there's a prefix match
+ stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
+ if (matchlen >= 0) {
+ // check for target_id+1 immediately following, with same encoding & language
+ if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
+ slen = ttUSHORT(fc+loc+12+8);
+ off = ttUSHORT(fc+loc+12+10);
+ if (slen == 0) {
+ if (matchlen == nlen)
+ return 1;
+ } else if (matchlen < nlen && name[matchlen] == ' ') {
+ ++matchlen;
+ if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
+ return 1;
+ }
+ } else {
+ // if nothing immediately following
+ if (matchlen == nlen)
+ return 1;
+ }
+ }
+ }
+
+ // @TODO handle other encodings
+ }
+ }
+ return 0;
+}
+
+static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
+{
+ stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
+ stbtt_uint32 nm,hd;
+ if (!stbtt__isfont(fc+offset)) return 0;
+
+ // check italics/bold/underline flags in macStyle...
+ if (flags) {
+ hd = stbtt__find_table(fc, offset, "head");
+ if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
+ }
+
+ nm = stbtt__find_table(fc, offset, "name");
+ if (!nm) return 0;
+
+ if (flags) {
+ // if we checked the macStyle flags, then just check the family and ignore the subfamily
+ if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
+ } else {
+ if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
+ }
+
+ return 0;
+}
+
+static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
+{
+ stbtt_int32 i;
+ for (i=0;;++i) {
+ stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
+ if (off < 0) return off;
+ if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
+ return off;
+ }
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+
+STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
+ float pixel_height, unsigned char *pixels, int pw, int ph,
+ int first_char, int num_chars, stbtt_bakedchar *chardata)
+{
+ return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
+}
+
+STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
+{
+ return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
+}
+
+STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
+{
+ return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
+}
+
+STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
+{
+ return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
+}
+
+STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
+{
+ return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
+}
+
+STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
+{
+ return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif // STB_TRUETYPE_IMPLEMENTATION
+
+
+// FULL VERSION HISTORY
+//
+// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
+// 1.18 (2018-01-29) add missing function
+// 1.17 (2017-07-23) make more arguments const; doc fix
+// 1.16 (2017-07-12) SDF support
+// 1.15 (2017-03-03) make more arguments const
+// 1.14 (2017-01-16) num-fonts-in-TTC function
+// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
+// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
+// 1.11 (2016-04-02) fix unused-variable warning
+// 1.10 (2016-04-02) allow user-defined fabs() replacement
+// fix memory leak if fontsize=0.0
+// fix warning from duplicate typedef
+// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
+// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
+// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
+// allow PackFontRanges to pack and render in separate phases;
+// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
+// fixed an assert() bug in the new rasterizer
+// replace assert() with STBTT_assert() in new rasterizer
+// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
+// also more precise AA rasterizer, except if shapes overlap
+// remove need for STBTT_sort
+// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
+// 1.04 (2015-04-15) typo in example
+// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
+// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
+// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
+// non-oversampled; STBTT_POINT_SIZE for packed case only
+// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
+// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
+// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
+// 0.8b (2014-07-07) fix a warning
+// 0.8 (2014-05-25) fix a few more warnings
+// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
+// 0.6c (2012-07-24) improve documentation
+// 0.6b (2012-07-20) fix a few more warnings
+// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
+// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
+// 0.5 (2011-12-09) bugfixes:
+// subpixel glyph renderer computed wrong bounding box
+// first vertex of shape can be off-curve (FreeSans)
+// 0.4b (2011-12-03) fixed an error in the font baking example
+// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
+// bugfixes for:
+// codepoint-to-glyph conversion using table fmt=12
+// codepoint-to-glyph conversion using table fmt=4
+// stbtt_GetBakedQuad with non-square texture (Zer)
+// updated Hello World! sample to use kerning and subpixel
+// fixed some warnings
+// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
+// userdata, malloc-from-userdata, non-zero fill (stb)
+// 0.2 (2009-03-11) Fix unsigned/signed char warnings
+// 0.1 (2009-03-09) First public release
+//
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt b/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt
new file mode 100644
index 0000000..cc23e58
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_library(sajson STATIC sajson.cpp sajson.h)
+target_include_directories(sajson PUBLIC ..)
+
+set_target_properties(sajson PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO
+)
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES sajson.cpp sajson.h)
diff --git a/Client/ThirdParty/Box2D/extern/sajson/sajson.cpp b/Client/ThirdParty/Box2D/extern/sajson/sajson.cpp
new file mode 100644
index 0000000..0a60a35
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/sajson/sajson.cpp
@@ -0,0 +1,2 @@
+// This cpp is here to force cmake to make a project file for sajson.
+int sajson_dummy;
diff --git a/Client/ThirdParty/Box2D/extern/sajson/sajson.h b/Client/ThirdParty/Box2D/extern/sajson/sajson.h
new file mode 100644
index 0000000..b7a816b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/extern/sajson/sajson.h
@@ -0,0 +1,2493 @@
+/*
+ * Copyright (c) 2012-2017 Chad Austin
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include <assert.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+#include <algorithm>
+#include <cstdio>
+#include <limits>
+
+#ifndef SAJSON_NO_STD_STRING
+#include <string> // for convenient access to error messages and string values.
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+#define SAJSON_LIKELY(x) __builtin_expect(!!(x), 1)
+#define SAJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#define SAJSON_ALWAYS_INLINE __attribute__((always_inline))
+#define SAJSON_UNREACHABLE() __builtin_unreachable()
+#define SAJSON_snprintf snprintf
+#elif defined(_MSC_VER)
+#define SAJSON_LIKELY(x) x
+#define SAJSON_UNLIKELY(x) x
+#define SAJSON_ALWAYS_INLINE __forceinline
+#define SAJSON_UNREACHABLE() __assume(0)
+#if (_MSC_VER <= 1800)
+#define SAJSON_snprintf _snprintf
+#else
+#define SAJSON_snprintf snprintf
+#endif
+#else
+#define SAJSON_LIKELY(x) x
+#define SAJSON_UNLIKELY(x) x
+#define SAJSON_ALWAYS_INLINE inline
+#define SAJSON_UNREACHABLE() assert(!"unreachable")
+#define SAJSON_snprintf snprintf
+#endif
+
+/**
+ * sajson Public API
+ */
+namespace sajson {
+
+ /// Tag indicating a JSON value's type.
+ enum type: uint8_t {
+ TYPE_INTEGER = 0,
+ TYPE_DOUBLE = 1,
+ TYPE_NULL = 2,
+ TYPE_FALSE = 3,
+ TYPE_TRUE = 4,
+ TYPE_STRING = 5,
+ TYPE_ARRAY = 6,
+ TYPE_OBJECT = 7,
+ };
+
+ namespace internal {
+ static const size_t TYPE_BITS = 3;
+ static const size_t TYPE_MASK = (1 << TYPE_BITS) - 1;
+ static const size_t VALUE_MASK = size_t(-1) >> TYPE_BITS;
+
+ static const size_t ROOT_MARKER = VALUE_MASK;
+
+ inline type get_element_type(size_t s) {
+ return static_cast<type>(s & TYPE_MASK);
+ }
+
+ inline size_t get_element_value(size_t s) {
+ return s >> TYPE_BITS;
+ }
+
+ inline size_t make_element(type t, size_t value) {
+ //assert((value & ~VALUE_MASK) == 0);
+ //value &= VALUE_MASK;
+ return static_cast<size_t>(t) | (value << TYPE_BITS);
+ }
+
+ // This template utilizes the One Definition Rule to create global arrays in a header.
+ // This trick courtesy of Rich Geldreich's Purple JSON parser.
+ template<typename unused=void>
+ struct globals_struct {
+ static const unsigned char parse_flags[256];
+ };
+ typedef globals_struct<> globals;
+
+ // bit 0 (1) - set if: plain ASCII string character
+ // bit 1 (2) - set if: whitespace
+ // bit 4 (0x10) - set if: 0-9 e E .
+ template<typename unused>
+ const uint8_t globals_struct<unused>::parse_flags[256] = {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ 3, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x11,1, // 2
+ 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, 0x11,0x11,1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 0x11,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 0x11,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+
+ // 128-255
+ 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, 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, 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, 0,0,0,0,0,0,0,0
+ };
+
+ inline bool is_plain_string_character(char c) {
+ //return c >= 0x20 && c <= 0x7f && c != 0x22 && c != 0x5c;
+ return (globals::parse_flags[static_cast<unsigned char>(c)] & 1) != 0;
+ }
+
+ inline bool is_whitespace(char c) {
+ //return c == '\r' || c == '\n' || c == '\t' || c == ' ';
+ return (globals::parse_flags[static_cast<unsigned char>(c)] & 2) != 0;
+ }
+
+ class allocated_buffer {
+ public:
+ allocated_buffer()
+ : memory(0)
+ {}
+
+ explicit allocated_buffer(size_t length) {
+ // throws std::bad_alloc upon allocation failure
+ void* buffer = operator new(sizeof(size_t) + length);
+ memory = static_cast<layout*>(buffer);
+ memory->refcount = 1;
+ }
+
+ allocated_buffer(const allocated_buffer& that)
+ : memory(that.memory)
+ {
+ incref();
+ }
+
+ allocated_buffer(allocated_buffer&& that)
+ : memory(that.memory)
+ {
+ that.memory = 0;
+ }
+
+ ~allocated_buffer() {
+ decref();
+ }
+
+ allocated_buffer& operator=(const allocated_buffer& that) {
+ if (this != &that) {
+ decref();
+ memory = that.memory;
+ incref();
+ }
+ return *this;
+ }
+
+ allocated_buffer& operator=(allocated_buffer&& that) {
+ if (this != &that) {
+ decref();
+ memory = that.memory;
+ that.memory = 0;
+ }
+ return *this;
+ }
+
+ char* get_data() const {
+ return memory ? memory->data : 0;
+ }
+
+ private:
+ void incref() const {
+ if (memory) {
+ ++(memory->refcount);
+ }
+ }
+
+ void decref() const {
+ if (memory && --(memory->refcount) == 0) {
+ operator delete(memory);
+ }
+ }
+
+ struct layout {
+ size_t refcount;
+ char data[1];
+ };
+
+ layout* memory;
+ };
+ }
+
+ /// A simple type encoding a pointer to some memory and a length (in bytes).
+ /// Does not maintain any memory.
+ class string {
+ public:
+ string(const char* text_, size_t length)
+ : text(text_)
+ , _length(length)
+ {}
+
+ const char* data() const {
+ return text;
+ }
+
+ size_t length() const {
+ return _length;
+ }
+
+#ifndef SAJSON_NO_STD_STRING
+ std::string as_string() const {
+ return std::string(text, text + _length);
+ }
+#endif
+
+ private:
+ const char* const text;
+ const size_t _length;
+
+ string(); /*=delete*/
+ };
+
+ /// A convenient way to parse JSON from a string literal. The string ends
+ /// at its first NUL character.
+ class literal : public string {
+ public:
+ template <size_t sz>
+ explicit literal(const char (&text_)[sz])
+ : string(text_, sz - 1)
+ {
+ static_assert(sz > 0, "!");
+ }
+ };
+
+ /// A pointer to a mutable buffer, its size in bytes, and strong ownership of any
+ /// copied memory.
+ class mutable_string_view {
+ public:
+ /// Creates an empty, zero-sized view.
+ mutable_string_view()
+ : length_(0)
+ , data(0)
+ , buffer()
+ {}
+
+ /// Given a length in bytes and a pointer, constructs a view
+ /// that does not allocate a copy of the data or maintain its life.
+ /// The given pointer must stay valid for the duration of the parse and the
+ /// resulting \ref document's life.
+ mutable_string_view(size_t length, char* data_)
+ : length_(length)
+ , data(data_)
+ , buffer()
+ {}
+
+ /// Allocates a copy of the given \ref literal string and exposes a
+ /// mutable view into it. Throws std::bad_alloc if allocation fails.
+ mutable_string_view(const literal& s)
+ : length_(s.length())
+ , buffer(length_)
+ {
+ data = buffer.get_data();
+ memcpy(data, s.data(), length_);
+ }
+
+ /// Allocates a copy of the given \ref string and exposes a mutable view
+ /// into it. Throws std::bad_alloc if allocation fails.
+ mutable_string_view(const string& s)
+ : length_(s.length())
+ , buffer(length_)
+ {
+ data = buffer.get_data();
+ memcpy(data, s.data(), length_);
+ }
+
+ /// Copies a mutable_string_view. If any backing memory has been
+ /// allocated, its refcount is incremented - both views can safely
+ /// use the memory.
+ mutable_string_view(const mutable_string_view& that)
+ : length_(that.length_)
+ , data(that.data)
+ , buffer(that.buffer)
+ {}
+
+ /// Move constructor - neuters the old mutable_string_view.
+ mutable_string_view(mutable_string_view&& that)
+ : length_(that.length_)
+ , data(that.data)
+ , buffer(std::move(that.buffer))
+ {
+ that.length_ = 0;
+ that.data = 0;
+ }
+
+ mutable_string_view& operator=(mutable_string_view&& that) {
+ if (this != &that) {
+ length_ = that.length_;
+ data = that.data;
+ buffer = std::move(that.buffer);
+ that.length_ = 0;
+ that.data = 0;
+ }
+ return *this;
+ }
+
+ mutable_string_view& operator=(const mutable_string_view& that) {
+ if (this != &that) {
+ length_ = that.length_;
+ data = that.data;
+ buffer = that.buffer;
+ }
+ return *this;
+ }
+
+ size_t length() const {
+ return length_;
+ }
+
+ char* get_data() const {
+ return data;
+ }
+
+ private:
+ size_t length_;
+ char* data;
+ internal::allocated_buffer buffer; // may not be allocated
+ };
+
+ namespace internal {
+ struct object_key_record {
+ size_t key_start;
+ size_t key_end;
+ size_t value;
+ };
+
+ struct object_key_comparator {
+ object_key_comparator(const char* object_data)
+ : data(object_data)
+ {}
+
+ bool operator()(const object_key_record& lhs, const string& rhs) const {
+ const size_t lhs_length = lhs.key_end - lhs.key_start;
+ const size_t rhs_length = rhs.length();
+ if (lhs_length < rhs_length) {
+ return true;
+ } else if (lhs_length > rhs_length) {
+ return false;
+ }
+ return memcmp(data + lhs.key_start, rhs.data(), lhs_length) < 0;
+ }
+
+ bool operator()(const string& lhs, const object_key_record& rhs) const {
+ return !(*this)(rhs, lhs);
+ }
+
+ bool operator()(
+ const object_key_record& lhs,
+ const object_key_record& rhs
+ ) {
+ const size_t lhs_length = lhs.key_end - lhs.key_start;
+ const size_t rhs_length = rhs.key_end - rhs.key_start;
+ if (lhs_length < rhs_length) {
+ return true;
+ } else if (lhs_length > rhs_length) {
+ return false;
+ }
+ return memcmp(
+ data + lhs.key_start,
+ data + rhs.key_start,
+ lhs_length
+ ) < 0;
+ }
+
+ const char* data;
+ };
+ }
+
+ namespace integer_storage {
+ enum {
+ word_length = 1
+ };
+
+ inline int load(const size_t* location) {
+ int value;
+ memcpy(&value, location, sizeof(value));
+ return value;
+ }
+
+ inline void store(size_t* location, int value) {
+ // NOTE: Most modern compilers optimize away this constant-size
+ // memcpy into a single instruction. If any don't, and treat
+ // punning through a union as legal, they can be special-cased.
+ static_assert(
+ sizeof(value) <= sizeof(*location),
+ "size_t must not be smaller than int");
+ memcpy(location, &value, sizeof(value));
+ }
+ }
+
+ namespace double_storage {
+ enum {
+ word_length = sizeof(double) / sizeof(size_t)
+ };
+
+ inline double load(const size_t* location) {
+ double value;
+ memcpy(&value, location, sizeof(double));
+ return value;
+ }
+
+ inline void store(size_t* location, double value) {
+ // NOTE: Most modern compilers optimize away this constant-size
+ // memcpy into a single instruction. If any don't, and treat
+ // punning through a union as legal, they can be special-cased.
+ memcpy(location, &value, sizeof(double));
+ }
+ }
+
+ /// Represents a JSON value. First, call get_type() to check its type,
+ /// which determines which methods are available.
+ ///
+ /// Note that \ref value does not maintain any backing memory, only the
+ /// corresponding \ref document does. It is illegal to access a \ref value
+ /// after its \ref document has been destroyed.
+ class value {
+ public:
+ /// Returns the JSON value's \ref type.
+ type get_type() const {
+ return value_type;
+ }
+
+ /// Returns the length of the object or array.
+ /// Only legal if get_type() is TYPE_ARRAY or TYPE_OBJECT.
+ size_t get_length() const {
+ assert_type_2(TYPE_ARRAY, TYPE_OBJECT);
+ return payload[0];
+ }
+
+ /// Returns the nth element of an array. Calling with an out-of-bound
+ /// index is undefined behavior.
+ /// Only legal if get_type() is TYPE_ARRAY.
+ value get_array_element(size_t index) const {
+ using namespace internal;
+ assert_type(TYPE_ARRAY);
+ size_t element = payload[1 + index];
+ return value(get_element_type(element), payload + get_element_value(element), text);
+ }
+
+ /// Returns the nth key of an object. Calling with an out-of-bound
+ /// index is undefined behavior.
+ /// Only legal if get_type() is TYPE_OBJECT.
+ string get_object_key(size_t index) const {
+ assert_type(TYPE_OBJECT);
+ const size_t* s = payload + 1 + index * 3;
+ return string(text + s[0], s[1] - s[0]);
+ }
+
+ /// Returns the nth value of an object. Calling with an out-of-bound
+ /// index is undefined behavior. Only legal if get_type() is TYPE_OBJECT.
+ value get_object_value(size_t index) const {
+ using namespace internal;
+ assert_type(TYPE_OBJECT);
+ size_t element = payload[3 + index * 3];
+ return value(get_element_type(element), payload + get_element_value(element), text);
+ }
+
+ /// Given a string key, returns the value with that key or a null value
+ /// if the key is not found. Running time is O(lg N).
+ /// Only legal if get_type() is TYPE_OBJECT.
+ value get_value_of_key(const string& key) const {
+ assert_type(TYPE_OBJECT);
+ size_t i = find_object_key(key);
+ if (i < get_length()) {
+ return get_object_value(i);
+ } else {
+ return value(TYPE_NULL, 0, 0);
+ }
+ }
+
+ /// Given a string key, returns the index of the associated value if
+ /// one exists. Returns get_length() if there is no such key.
+ /// Note: sajson sorts object keys, so the running time is O(lg N).
+ /// Only legal if get_type() is TYPE_OBJECT
+ size_t find_object_key(const string& key) const {
+ using namespace internal;
+ assert_type(TYPE_OBJECT);
+ const object_key_record* start = reinterpret_cast<const object_key_record*>(payload + 1);
+ const object_key_record* end = start + get_length();
+#ifdef SAJSON_UNSORTED_OBJECT_KEYS
+ for (const object_key_record* i = start; i != end; ++i)
+#else
+ const object_key_record* i = std::lower_bound(start, end, key, object_key_comparator(text));
+#endif
+ if (i != end
+ && (i->key_end - i->key_start) == key.length()
+ && memcmp(key.data(), text + i->key_start, key.length()) == 0) {
+ return i - start;
+ }
+ return get_length();
+ }
+
+ /// If a numeric value was parsed as a 32-bit integer, returns it.
+ /// Only legal if get_type() is TYPE_INTEGER.
+ int get_integer_value() const {
+ assert_type(TYPE_INTEGER);
+ return integer_storage::load(payload);
+ }
+
+ /// If a numeric value was parsed as a double, returns it.
+ /// Only legal if get_type() is TYPE_DOUBLE.
+ double get_double_value() const {
+ assert_type(TYPE_DOUBLE);
+ return double_storage::load(payload);
+ }
+
+ /// Returns a numeric value as a double-precision float.
+ /// Only legal if get_type() is TYPE_INTEGER or TYPE_DOUBLE.
+ double get_number_value() const {
+ assert_type_2(TYPE_INTEGER, TYPE_DOUBLE);
+ if (get_type() == TYPE_INTEGER) {
+ return get_integer_value();
+ } else {
+ return get_double_value();
+ }
+ }
+
+ /// Returns true and writes to the output argument if the numeric value
+ /// fits in a 53-bit integer. This is useful for timestamps and other
+ /// situations where integral values with greater than 32-bit precision
+ /// are used, as 64-bit values are not understood by all JSON
+ /// implementations or languages.
+ /// Returns false if the value is not an integer or not in range.
+ /// Only legal if get_type() is TYPE_INTEGER or TYPE_DOUBLE.
+ bool get_int53_value(int64_t* out) const {
+ // Make sure the output variable is always defined to avoid any
+ // possible situation like
+ // https://gist.github.com/chadaustin/2c249cb850619ddec05b23ca42cf7a18
+ *out = 0;
+
+ assert_type_2(TYPE_INTEGER, TYPE_DOUBLE);
+ if (get_type() == TYPE_INTEGER) {
+ *out = get_integer_value();
+ return true;
+ } else if (get_type() == TYPE_DOUBLE) {
+ double v = get_double_value();
+ if (v < -(1LL << 53) || v > (1LL << 53)) {
+ return false;
+ }
+ int64_t as_int = static_cast<int64_t>(v);
+ if (as_int != v) {
+ return false;
+ }
+ *out = as_int;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /// Returns the length of the string.
+ /// Only legal if get_type() is TYPE_STRING.
+ size_t get_string_length() const {
+ assert_type(TYPE_STRING);
+ return payload[1] - payload[0];
+ }
+
+ /// Returns a pointer to the beginning of a string value's data.
+ /// WARNING: Calling this function and using the return value as a
+ /// C-style string (that is, without also using get_string_length())
+ /// will cause the string to appear truncated if the string has
+ /// embedded NULs.
+ /// Only legal if get_type() is TYPE_STRING.
+ const char* as_cstring() const {
+ assert_type(TYPE_STRING);
+ return text + payload[0];
+ }
+
+#ifndef SAJSON_NO_STD_STRING
+ /// Returns a string's value as a std::string.
+ /// Only legal if get_type() is TYPE_STRING.
+ std::string as_string() const {
+ assert_type(TYPE_STRING);
+ return std::string(text + payload[0], text + payload[1]);
+ }
+#endif
+
+ /// \cond INTERNAL
+ const size_t* _internal_get_payload() const {
+ return payload;
+ }
+ /// \endcond
+
+ private:
+ explicit value(type value_type_, const size_t* payload_, const char* text_)
+ : value_type(value_type_)
+ , payload(payload_)
+ , text(text_)
+ {}
+
+ void assert_type(type expected) const {
+ assert(expected == get_type());
+ }
+
+ void assert_type_2(type e1, type e2) const {
+ assert(e1 == get_type() || e2 == get_type());
+ }
+
+ void assert_in_bounds(size_t i) const {
+ assert(i < get_length());
+ }
+
+ const type value_type;
+ const size_t* const payload;
+ const char* const text;
+
+ friend class document;
+ };
+
+ /// Error code indicating why parse failed.
+ enum error {
+ ERROR_NO_ERROR,
+ ERROR_OUT_OF_MEMORY,
+ ERROR_UNEXPECTED_END,
+ ERROR_MISSING_ROOT_ELEMENT,
+ ERROR_BAD_ROOT,
+ ERROR_EXPECTED_COMMA,
+ ERROR_MISSING_OBJECT_KEY,
+ ERROR_EXPECTED_COLON,
+ ERROR_EXPECTED_END_OF_INPUT,
+ ERROR_UNEXPECTED_COMMA,
+ ERROR_EXPECTED_VALUE,
+ ERROR_EXPECTED_NULL,
+ ERROR_EXPECTED_FALSE,
+ ERROR_EXPECTED_TRUE,
+ ERROR_INVALID_NUMBER,
+ ERROR_MISSING_EXPONENT,
+ ERROR_ILLEGAL_CODEPOINT,
+ ERROR_INVALID_UNICODE_ESCAPE,
+ ERROR_UNEXPECTED_END_OF_UTF16,
+ ERROR_EXPECTED_U,
+ ERROR_INVALID_UTF16_TRAIL_SURROGATE,
+ ERROR_UNKNOWN_ESCAPE,
+ ERROR_INVALID_UTF8,
+ };
+
+ namespace internal {
+ class ownership {
+ public:
+ ownership() = delete;
+ ownership(const ownership&) = delete;
+ void operator=(const ownership&) = delete;
+
+ explicit ownership(size_t* p_)
+ : p(p_)
+ {}
+
+ ownership(ownership&& p_)
+ : p(p_.p) {
+ p_.p = 0;
+ }
+
+ ~ownership() {
+ delete[] p;
+ }
+
+ bool is_valid() const {
+ return !!p;
+ }
+
+ private:
+ size_t* p;
+ };
+
+ inline const char* get_error_text(error error_code) {
+ switch (error_code) {
+ case ERROR_NO_ERROR: return "no error";
+ case ERROR_OUT_OF_MEMORY: return "out of memory";
+ case ERROR_UNEXPECTED_END: return "unexpected end of input";
+ case ERROR_MISSING_ROOT_ELEMENT: return "missing root element";
+ case ERROR_BAD_ROOT: return "document root must be object or array";
+ case ERROR_EXPECTED_COMMA: return "expected ,";
+ case ERROR_MISSING_OBJECT_KEY: return "missing object key";
+ case ERROR_EXPECTED_COLON: return "expected :";
+ case ERROR_EXPECTED_END_OF_INPUT: return "expected end of input";
+ case ERROR_UNEXPECTED_COMMA: return "unexpected comma";
+ case ERROR_EXPECTED_VALUE: return "expected value";
+ case ERROR_EXPECTED_NULL: return "expected 'null'";
+ case ERROR_EXPECTED_FALSE: return "expected 'false'";
+ case ERROR_EXPECTED_TRUE: return "expected 'true'";
+ case ERROR_INVALID_NUMBER: return "invalid number";
+ case ERROR_MISSING_EXPONENT: return "missing exponent";
+ case ERROR_ILLEGAL_CODEPOINT: return "illegal unprintable codepoint in string";
+ case ERROR_INVALID_UNICODE_ESCAPE: return "invalid character in unicode escape";
+ case ERROR_UNEXPECTED_END_OF_UTF16: return "unexpected end of input during UTF-16 surrogate pair";
+ case ERROR_EXPECTED_U: return "expected \\u";
+ case ERROR_INVALID_UTF16_TRAIL_SURROGATE: return "invalid UTF-16 trail surrogate";
+ case ERROR_UNKNOWN_ESCAPE: return "unknown escape";
+ case ERROR_INVALID_UTF8: return "invalid UTF-8";
+ }
+
+ SAJSON_UNREACHABLE();
+ }
+ }
+
+ /**
+ * Represents the result of a JSON parse: either is_valid() and the document
+ * contains a root value or parse error information is available.
+ *
+ * Note that the document holds a strong reference to any memory allocated:
+ * any mutable copy of the input text and any memory allocated for the
+ * AST data structure. Thus, the document must not be deallocated while any
+ * \ref value is in use.
+ */
+ class document {
+ public:
+ document(document&& rhs)
+ : input(rhs.input)
+ , structure(std::move(rhs.structure))
+ , root_type(rhs.root_type)
+ , root(rhs.root)
+ , error_line(rhs.error_line)
+ , error_column(rhs.error_column)
+ , error_code(rhs.error_code)
+ , error_arg(rhs.error_arg)
+ {
+ // Yikes... but strcpy is okay here because formatted_error is
+ // guaranteed to be null-terminated.
+ strcpy(formatted_error_message, rhs.formatted_error_message);
+ // should rhs's fields be zeroed too?
+ }
+
+ /**
+ * Returns true if the document was parsed successfully.
+ * If true, call get_root() to access the document's root value.
+ * If false, call get_error_line(), get_error_column(), and
+ * get_error_message_as_cstring() to see why the parse failed.
+ */
+ bool is_valid() const {
+ return root_type == TYPE_ARRAY || root_type == TYPE_OBJECT;
+ }
+
+ /// If is_valid(), returns the document's root \ref value.
+ value get_root() const {
+ return value(root_type, root, input.get_data());
+ }
+
+ /// If not is_valid(), returns the one-based line number where the parse failed.
+ size_t get_error_line() const {
+ return error_line;
+ }
+
+ /// If not is_valid(), returns the one-based column number where the parse failed.
+ size_t get_error_column() const {
+ return error_column;
+ }
+
+#ifndef SAJSON_NO_STD_STRING
+ /// If not is_valid(), returns a std::string indicating why the parse failed.
+ std::string get_error_message_as_string() const {
+ return formatted_error_message;
+ }
+#endif
+
+ /// If not is_valid(), returns a null-terminated C string indicating why the parse failed.
+ const char* get_error_message_as_cstring() const {
+ return formatted_error_message;
+ }
+
+ /// \cond INTERNAL
+
+ // WARNING: Internal function which is subject to change
+ error _internal_get_error_code() const {
+ return error_code;
+ }
+
+ // WARNING: Internal function which is subject to change
+ int _internal_get_error_argument() const {
+ return error_arg;
+ }
+
+ // WARNING: Internal function which is subject to change
+ const char* _internal_get_error_text() const {
+ return internal::get_error_text(error_code);
+ }
+
+ // WARNING: Internal function exposed only for high-performance language bindings.
+ type _internal_get_root_type() const {
+ return root_type;
+ }
+
+ // WARNING: Internal function exposed only for high-performance language bindings.
+ const size_t* _internal_get_root() const {
+ return root;
+ }
+
+ // WARNING: Internal function exposed only for high-performance language bindings.
+ const mutable_string_view& _internal_get_input() const {
+ return input;
+ }
+
+ /// \endcond
+
+ private:
+ document(const document&) = delete;
+ void operator=(const document&) = delete;
+
+ explicit document(const mutable_string_view& input_, internal::ownership&& structure_, type root_type_, const size_t* root_)
+ : input(input_)
+ , structure(std::move(structure_))
+ , root_type(root_type_)
+ , root(root_)
+ , error_line(0)
+ , error_column(0)
+ , error_code(ERROR_NO_ERROR)
+ , error_arg(0)
+ {
+ formatted_error_message[0] = 0;
+ }
+
+ explicit document(const mutable_string_view& input_, size_t error_line_, size_t error_column_, const error error_code_, int error_arg_)
+ : input(input_)
+ , structure(0)
+ , root_type(TYPE_NULL)
+ , root(0)
+ , error_line(error_line_)
+ , error_column(error_column_)
+ , error_code(error_code_)
+ , error_arg(error_arg_)
+ {
+ formatted_error_message[ERROR_BUFFER_LENGTH - 1] = 0;
+ int written = has_significant_error_arg()
+ ? SAJSON_snprintf(formatted_error_message, ERROR_BUFFER_LENGTH - 1, "%s: %d", _internal_get_error_text(), error_arg)
+ : SAJSON_snprintf(formatted_error_message, ERROR_BUFFER_LENGTH - 1, "%s", _internal_get_error_text());
+ (void)written;
+ assert(written >= 0 && written < ERROR_BUFFER_LENGTH);
+ }
+
+ bool has_significant_error_arg() const {
+ return error_code == ERROR_ILLEGAL_CODEPOINT;
+ }
+
+ mutable_string_view input;
+ internal::ownership structure;
+ const type root_type;
+ const size_t* const root;
+ const size_t error_line;
+ const size_t error_column;
+ const error error_code;
+ const int error_arg;
+
+ enum { ERROR_BUFFER_LENGTH = 128 };
+ char formatted_error_message[ERROR_BUFFER_LENGTH];
+
+ template<typename AllocationStrategy, typename StringType>
+ friend document parse(const AllocationStrategy& strategy, const StringType& string);
+ template<typename Allocator>
+ friend class parser;
+ };
+
+ /// Allocation policy that allocates one large buffer guaranteed to hold the
+ /// resulting AST. This allocation policy is the fastest since it requires
+ /// no conditionals to see if more memory must be allocated.
+ class single_allocation {
+ public:
+ /// \cond INTERNAL
+
+ class stack_head {
+ public:
+ stack_head(stack_head&& other)
+ : stack_bottom(other.stack_bottom)
+ , stack_top(other.stack_top)
+ {}
+
+ bool push(size_t element) {
+ *stack_top++ = element;
+ return true;
+ }
+
+ size_t* reserve(size_t amount, bool* success) {
+ size_t* rv = stack_top;
+ stack_top += amount;
+ *success = true;
+ return rv;
+ }
+
+ // The compiler does not see the stack_head (stored in a local)
+ // and the allocator (stored as a field) have the same stack_bottom
+ // values, so it does a bit of redundant work.
+ // So there's a microoptimization available here: introduce a type
+ // "stack_mark" and make it polymorphic on the allocator. For
+ // single_allocation, it merely needs to be a single pointer.
+
+ void reset(size_t new_top) {
+ stack_top = stack_bottom + new_top;
+ }
+
+ size_t get_size() {
+ return stack_top - stack_bottom;
+ }
+
+ size_t* get_top() {
+ return stack_top;
+ }
+
+ size_t* get_pointer_from_offset(size_t offset) {
+ return stack_bottom + offset;
+ }
+
+ private:
+ stack_head() = delete;
+ stack_head(const stack_head&) = delete;
+ void operator=(const stack_head&) = delete;
+
+ explicit stack_head(size_t* base)
+ : stack_bottom(base)
+ , stack_top(base)
+ {}
+
+ size_t* const stack_bottom;
+ size_t* stack_top;
+
+ friend class single_allocation;
+ };
+
+ class allocator {
+ public:
+ allocator() = delete;
+ allocator(const allocator&) = delete;
+ void operator=(const allocator&) = delete;
+
+ explicit allocator(size_t* buffer, size_t input_size, bool should_deallocate_)
+ : structure(buffer)
+ , structure_end(buffer ? buffer + input_size : 0)
+ , write_cursor(structure_end)
+ , should_deallocate(should_deallocate_)
+ {}
+
+ explicit allocator(std::nullptr_t)
+ : structure(0)
+ , structure_end(0)
+ , write_cursor(0)
+ , should_deallocate(false)
+ {}
+
+ allocator(allocator&& other)
+ : structure(other.structure)
+ , structure_end(other.structure_end)
+ , write_cursor(other.write_cursor)
+ , should_deallocate(other.should_deallocate)
+ {
+ other.structure = 0;
+ other.structure_end = 0;
+ other.write_cursor = 0;
+ other.should_deallocate = false;
+ }
+
+ ~allocator() {
+ if (should_deallocate) {
+ delete[] structure;
+ }
+ }
+
+ stack_head get_stack_head(bool* success) {
+ *success = true;
+ return stack_head(structure);
+ }
+
+ size_t get_write_offset() {
+ return structure_end - write_cursor;
+ }
+
+ size_t* get_write_pointer_of(size_t v) {
+ return structure_end - v;
+ }
+
+ size_t* reserve(size_t size, bool* success) {
+ *success = true;
+ write_cursor -= size;
+ return write_cursor;
+ }
+
+ size_t* get_ast_root() {
+ return write_cursor;
+ }
+
+ internal::ownership transfer_ownership() {
+ auto p = structure;
+ structure = 0;
+ structure_end = 0;
+ write_cursor = 0;
+ if (should_deallocate) {
+ return internal::ownership(p);
+ } else {
+ return internal::ownership(0);
+ }
+ }
+
+ private:
+ size_t* structure;
+ size_t* structure_end;
+ size_t* write_cursor;
+ bool should_deallocate;
+ };
+
+ /// \endcond
+
+ /// Allocate a single worst-case AST buffer with one word per byte in
+ /// the input document.
+ single_allocation()
+ : has_existing_buffer(false)
+ , existing_buffer(0)
+ , existing_buffer_size(0)
+ {}
+
+ /// Write the AST into an existing buffer. Will fail with an out of
+ /// memory error if the buffer is not guaranteed to be big enough for
+ /// the document. The caller must guarantee the memory is valid for
+ /// the duration of the parse and the AST traversal.
+ single_allocation(size_t* existing_buffer_, size_t size_in_words)
+ : has_existing_buffer(true)
+ , existing_buffer(existing_buffer_)
+ , existing_buffer_size(size_in_words)
+ {}
+
+ /// Convenience wrapper for single_allocation(size_t*, size_t) that
+ /// automatically infers the length of a given array.
+ template<size_t N>
+ explicit single_allocation(size_t (&existing_buffer_)[N])
+ : single_allocation(existing_buffer_, N)
+ {}
+
+ /// \cond INTERNAL
+
+ allocator make_allocator(size_t input_document_size_in_bytes, bool* succeeded) const {
+ if (has_existing_buffer) {
+ if (existing_buffer_size < input_document_size_in_bytes) {
+ *succeeded = false;
+ return allocator(nullptr);
+ }
+ *succeeded = true;
+ return allocator(existing_buffer, input_document_size_in_bytes, false);
+ } else {
+ size_t* buffer = new(std::nothrow) size_t[input_document_size_in_bytes];
+ if (!buffer) {
+ *succeeded = false;
+ return allocator(nullptr);
+ }
+ *succeeded = true;
+ return allocator(buffer, input_document_size_in_bytes, true);
+ }
+ }
+
+ /// \endcond
+
+ private:
+ bool has_existing_buffer;
+ size_t* existing_buffer;
+ size_t existing_buffer_size;
+ };
+
+ /// Allocation policy that uses dynamically-growing buffers for both the
+ /// parse stack and the AST. This allocation policy minimizes peak memory
+ /// usage at the cost of some allocation and copying churn.
+ class dynamic_allocation {
+ public:
+ /// \cond INTERNAL
+
+ class stack_head {
+ public:
+ stack_head(stack_head&& other)
+ : stack_top(other.stack_top)
+ , stack_bottom(other.stack_bottom)
+ , stack_limit(other.stack_limit)
+ {
+ other.stack_top = 0;
+ other.stack_bottom = 0;
+ other.stack_limit = 0;
+ }
+
+ ~stack_head() {
+ delete[] stack_bottom;
+ }
+
+ bool push(size_t element) {
+ if (can_grow(1)) {
+ *stack_top++ = element;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ size_t* reserve(size_t amount, bool* success) {
+ if (can_grow(amount)) {
+ size_t* rv = stack_top;
+ stack_top += amount;
+ *success = true;
+ return rv;
+ } else {
+ *success = false;
+ return 0;
+ }
+ }
+
+ void reset(size_t new_top) {
+ stack_top = stack_bottom + new_top;
+ }
+
+ size_t get_size() {
+ return stack_top - stack_bottom;
+ }
+
+ size_t* get_top() {
+ return stack_top;
+ }
+
+ size_t* get_pointer_from_offset(size_t offset) {
+ return stack_bottom + offset;
+ }
+
+ private:
+ stack_head(const stack_head&) = delete;
+ void operator=(const stack_head&) = delete;
+
+ explicit stack_head(size_t initial_capacity, bool* success) {
+ assert(initial_capacity);
+ stack_bottom = new(std::nothrow) size_t[initial_capacity];
+ stack_top = stack_bottom;
+ if (stack_bottom) {
+ stack_limit = stack_bottom + initial_capacity;
+ } else {
+ stack_limit = 0;
+ }
+ *success = !!stack_bottom;
+ }
+
+ bool can_grow(size_t amount) {
+ if (SAJSON_LIKELY(amount <= static_cast<size_t>(stack_limit - stack_top))) {
+ return true;
+ }
+
+ size_t current_size = stack_top - stack_bottom;
+ size_t old_capacity = stack_limit - stack_bottom;
+ size_t new_capacity = old_capacity * 2;
+ while (new_capacity < amount + current_size) {
+ new_capacity *= 2;
+ }
+ size_t* new_stack = new(std::nothrow) size_t[new_capacity];
+ if (!new_stack) {
+ stack_top = 0;
+ stack_bottom = 0;
+ stack_limit = 0;
+ return false;
+ }
+
+ memcpy(new_stack, stack_bottom, current_size * sizeof(size_t));
+ delete[] stack_bottom;
+ stack_top = new_stack + current_size;
+ stack_bottom = new_stack;
+ stack_limit = stack_bottom + new_capacity;
+ return true;
+ }
+
+ size_t* stack_top; // stack grows up: stack_top >= stack_bottom
+ size_t* stack_bottom;
+ size_t* stack_limit;
+
+ friend class dynamic_allocation;
+ };
+
+ class allocator {
+ public:
+ allocator() = delete;
+ allocator(const allocator&) = delete;
+ void operator=(const allocator&) = delete;
+
+ explicit allocator(size_t* buffer_, size_t current_capacity, size_t initial_stack_capacity_)
+ : ast_buffer_bottom(buffer_)
+ , ast_buffer_top(buffer_ + current_capacity)
+ , ast_write_head(ast_buffer_top)
+ , initial_stack_capacity(initial_stack_capacity_)
+ {}
+
+ explicit allocator(std::nullptr_t)
+ : ast_buffer_bottom(0)
+ , ast_buffer_top(0)
+ , ast_write_head(0)
+ , initial_stack_capacity(0)
+ {}
+
+ allocator(allocator&& other)
+ : ast_buffer_bottom(other.ast_buffer_bottom)
+ , ast_buffer_top(other.ast_buffer_top)
+ , ast_write_head(other.ast_write_head)
+ , initial_stack_capacity(other.initial_stack_capacity)
+ {
+ other.ast_buffer_bottom = 0;
+ other.ast_buffer_top = 0;
+ other.ast_write_head = 0;
+ }
+
+ ~allocator() {
+ delete[] ast_buffer_bottom;
+ }
+
+ stack_head get_stack_head(bool* success) {
+ return stack_head(initial_stack_capacity, success);
+ }
+
+ size_t get_write_offset() {
+ return ast_buffer_top - ast_write_head;
+ }
+
+ size_t* get_write_pointer_of(size_t v) {
+ return ast_buffer_top - v;
+ }
+
+ size_t* reserve(size_t size, bool* success) {
+ if (can_grow(size)) {
+ ast_write_head -= size;
+ *success = true;
+ return ast_write_head;
+ } else {
+ *success = false;
+ return 0;
+ }
+ }
+
+ size_t* get_ast_root() {
+ return ast_write_head;
+ }
+
+ internal::ownership transfer_ownership() {
+ auto p = ast_buffer_bottom;
+ ast_buffer_bottom = 0;
+ ast_buffer_top = 0;
+ ast_write_head = 0;
+ return internal::ownership(p);
+ }
+
+ private:
+ bool can_grow(size_t amount) {
+ if (SAJSON_LIKELY(amount <= static_cast<size_t>(ast_write_head - ast_buffer_bottom))) {
+ return true;
+ }
+ size_t current_capacity = ast_buffer_top - ast_buffer_bottom;
+
+ size_t current_size = ast_buffer_top - ast_write_head;
+ size_t new_capacity = current_capacity * 2;
+ while (new_capacity < amount + current_size) {
+ new_capacity *= 2;
+ }
+
+ size_t* old_buffer = ast_buffer_bottom;
+ size_t* new_buffer = new(std::nothrow) size_t[new_capacity];
+ if (!new_buffer) {
+ ast_buffer_bottom = 0;
+ ast_buffer_top = 0;
+ ast_write_head = 0;
+ return false;
+ }
+
+ size_t* old_write_head = ast_write_head;
+ ast_buffer_bottom = new_buffer;
+ ast_buffer_top = new_buffer + new_capacity;
+ ast_write_head = ast_buffer_top - current_size;
+ memcpy(ast_write_head, old_write_head, current_size * sizeof(size_t));
+ delete[] old_buffer;
+
+ return true;
+ }
+
+ size_t* ast_buffer_bottom; // base address of the ast buffer - it grows down
+ size_t* ast_buffer_top;
+ size_t* ast_write_head;
+ size_t initial_stack_capacity;
+ };
+
+ /// \endcond
+
+ /// Creates a dynamic_allocation policy with the given initial AST
+ /// and stack buffer sizes.
+ dynamic_allocation(size_t initial_ast_capacity_ = 0, size_t initial_stack_capacity_ = 0)
+ : initial_ast_capacity(initial_ast_capacity_)
+ , initial_stack_capacity(initial_stack_capacity_)
+ {}
+
+ /// \cond INTERNAL
+
+ allocator make_allocator(size_t, bool* succeeded) const {
+ size_t capacity = initial_ast_capacity;
+ if (!capacity) {
+ // TODO: guess based on input document size
+ capacity = 1024;
+ }
+
+ size_t* buffer = new(std::nothrow) size_t[capacity];
+ if (!buffer) {
+ *succeeded = false;
+ return allocator(nullptr);
+ }
+
+ size_t stack_capacity = initial_stack_capacity;
+ if (!stack_capacity) {
+ stack_capacity = 256;
+ }
+
+ *succeeded = true;
+ return allocator(buffer, capacity, stack_capacity);
+ }
+
+ /// \endcond
+
+ private:
+ size_t initial_ast_capacity;
+ size_t initial_stack_capacity;
+ };
+
+ /// Allocation policy that attempts to fit the parsed AST into an existing
+ /// memory buffer. This allocation policy is useful when using sajson in
+ /// a zero-allocation context or when there are constraints on the amount
+ // of memory that can be used.
+ class bounded_allocation {
+ public:
+ /// \cond INTERNAL
+
+ class allocator;
+
+ class stack_head {
+ public:
+ stack_head(stack_head&& other)
+ : source_allocator(other.source_allocator)
+ {
+ other.source_allocator = 0;
+ }
+
+ bool push(size_t element) {
+ if (SAJSON_LIKELY(source_allocator->can_grow(1))) {
+ *(source_allocator->stack_top)++ = element;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ size_t* reserve(size_t amount, bool* success) {
+ if (SAJSON_LIKELY(source_allocator->can_grow(amount))) {
+ size_t* rv = source_allocator->stack_top;
+ source_allocator->stack_top += amount;
+ *success = true;
+ return rv;
+ } else {
+ *success = false;
+ return 0;
+ }
+ }
+
+ void reset(size_t new_top) {
+ source_allocator->stack_top = source_allocator->structure + new_top;
+ }
+
+ size_t get_size() {
+ return source_allocator->stack_top - source_allocator->structure;
+ }
+
+ size_t* get_top() {
+ return source_allocator->stack_top;
+ }
+
+ size_t* get_pointer_from_offset(size_t offset) {
+ return source_allocator->structure + offset;
+ }
+
+ private:
+ stack_head(const stack_head&) = delete;
+ void operator=(const stack_head&) = delete;
+
+ explicit stack_head(allocator* source_allocator_)
+ : source_allocator(source_allocator_)
+ {}
+
+ allocator* source_allocator;
+
+ friend class bounded_allocation;
+ };
+
+ class allocator {
+ public:
+ allocator() = delete;
+ allocator(const allocator&) = delete;
+ void operator=(const allocator&) = delete;
+
+ explicit allocator(size_t* existing_buffer, size_t existing_buffer_size)
+ : structure(existing_buffer)
+ , structure_end(existing_buffer + existing_buffer_size)
+ , write_cursor(structure_end)
+ , stack_top(structure)
+ {}
+
+ allocator(allocator&& other)
+ : structure(other.structure)
+ , structure_end(other.structure_end)
+ , write_cursor(other.write_cursor)
+ , stack_top(other.stack_top)
+ {
+ other.structure = 0;
+ other.structure_end = 0;
+ other.write_cursor = 0;
+ other.stack_top = 0;
+ }
+
+ stack_head get_stack_head(bool* success) {
+ *success = true;
+ return stack_head(this);
+ }
+
+ size_t get_write_offset() {
+ return structure_end - write_cursor;
+ }
+
+ size_t* get_write_pointer_of(size_t v) {
+ return structure_end - v;
+ }
+
+ size_t* reserve(size_t size, bool* success) {
+ if (can_grow(size)) {
+ write_cursor -= size;
+ *success = true;
+ return write_cursor;
+ } else {
+ *success = false;
+ return 0;
+ }
+ }
+
+ size_t* get_ast_root() {
+ return write_cursor;
+ }
+
+ internal::ownership transfer_ownership() {
+ structure = 0;
+ structure_end = 0;
+ write_cursor = 0;
+ return internal::ownership(0);
+ }
+
+ private:
+ bool can_grow(size_t amount) {
+ // invariant: stack_top <= write_cursor
+ // thus: write_cursor - stack_top is positive
+ return static_cast<size_t>(write_cursor - stack_top) >= amount;
+ }
+
+ size_t* structure;
+ size_t* structure_end;
+ size_t* write_cursor;
+ size_t* stack_top;
+
+ friend class bounded_allocation;
+ };
+
+ /// \endcond
+
+ /// Uses an existing buffer to hold the parsed AST, if it fits. The
+ /// specified buffer must not be deallocated until after the document
+ /// is parsed and the AST traversed.
+ bounded_allocation(size_t* existing_buffer_, size_t size_in_words)
+ : existing_buffer(existing_buffer_)
+ , existing_buffer_size(size_in_words)
+ {}
+
+ /// Convenience wrapper for bounded_allocation(size_t*, size) that
+ /// automatically infers the size of the given array.
+ template<size_t N>
+ explicit bounded_allocation(size_t (&existing_buffer_)[N])
+ : bounded_allocation(existing_buffer_, N)
+ {}
+
+ /// \cond INTERNAL
+
+ allocator make_allocator(size_t, bool* succeeded) const {
+ *succeeded = true;
+ return allocator(existing_buffer, existing_buffer_size);
+ }
+
+ /// \endcond
+
+ private:
+ size_t* existing_buffer;
+ size_t existing_buffer_size;
+ };
+
+ // I thought about putting parser in the internal namespace but I don't
+ // want to indent it further...
+ /// \cond INTERNAL
+ template<typename Allocator>
+ class parser {
+ public:
+ parser(const mutable_string_view& msv, Allocator&& allocator_)
+ : input(msv)
+ , input_end(input.get_data() + input.length())
+ , allocator(std::move(allocator_))
+ , root_type(TYPE_NULL)
+ , error_line(0)
+ , error_column(0)
+ {}
+
+ document get_document() {
+ if (parse()) {
+ size_t* ast_root = allocator.get_ast_root();
+ return document(input, allocator.transfer_ownership(), root_type, ast_root);
+ } else {
+ return document(input, error_line, error_column, error_code, error_arg);
+ }
+ }
+
+ private:
+ struct error_result {
+ operator bool() const {
+ return false;
+ }
+ operator char*() const {
+ return 0;
+ }
+ };
+
+ bool at_eof(const char* p) {
+ return p == input_end;
+ }
+
+ char* skip_whitespace(char* p) {
+ // There is an opportunity to make better use of superscalar
+ // hardware here* but if someone cares about JSON parsing
+ // performance the first thing they do is minify, so prefer
+ // to optimize for code size here.
+ // * https://github.com/chadaustin/Web-Benchmarks/blob/master/json/third-party/pjson/pjson.h#L1873
+ for (;;) {
+ if (SAJSON_UNLIKELY(p == input_end)) {
+ return 0;
+ } else if (internal::is_whitespace(*p)) {
+ ++p;
+ } else {
+ return p;
+ }
+ }
+ }
+
+ error_result oom(char* p) {
+ return make_error(p, ERROR_OUT_OF_MEMORY);
+ }
+
+ error_result unexpected_end() {
+ return make_error(0, ERROR_UNEXPECTED_END);
+ }
+
+ error_result unexpected_end(char* p) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+
+ error_result make_error(char* p, error code, int arg = 0) {
+ if (!p) {
+ p = input_end;
+ }
+
+ error_line = 1;
+ error_column = 1;
+
+ char* c = input.get_data();
+ while (c < p) {
+ if (*c == '\r') {
+ if (c + 1 < p && c[1] == '\n') {
+ ++error_line;
+ error_column = 1;
+ ++c;
+ } else {
+ ++error_line;
+ error_column = 1;
+ }
+ } else if (*c == '\n') {
+ ++error_line;
+ error_column = 1;
+ } else {
+ // TODO: count UTF-8 characters
+ ++error_column;
+ }
+ ++c;
+ }
+
+ error_code = code;
+ error_arg = arg;
+ return error_result();
+ }
+
+ bool parse() {
+ using namespace internal;
+
+ // p points to the character currently being parsed
+ char* p = input.get_data();
+
+ bool success;
+ auto stack = allocator.get_stack_head(&success);
+ if (SAJSON_UNLIKELY(!success)) {
+ return oom(p);
+ }
+
+ p = skip_whitespace(p);
+ if (SAJSON_UNLIKELY(!p)) {
+ return make_error(p, ERROR_MISSING_ROOT_ELEMENT);
+ }
+
+ // current_base is an offset to the first element of the current structure (object or array)
+ size_t current_base = stack.get_size();
+ type current_structure_type;
+ if (*p == '[') {
+ current_structure_type = TYPE_ARRAY;
+ bool s = stack.push(make_element(current_structure_type, ROOT_MARKER));
+ if (SAJSON_UNLIKELY(!s)) {
+ return oom(p);
+ }
+ goto array_close_or_element;
+ } else if (*p == '{') {
+ current_structure_type = TYPE_OBJECT;
+ bool s = stack.push(make_element(current_structure_type, ROOT_MARKER));
+ if (SAJSON_UNLIKELY(!s)) {
+ return oom(p);
+ }
+ goto object_close_or_element;
+ } else {
+ return make_error(p, ERROR_BAD_ROOT);
+ }
+
+ // BEGIN STATE MACHINE
+
+ size_t pop_element; // used as an argument into the `pop` routine
+
+ if (0) { // purely for structure
+
+ // ASSUMES: byte at p SHOULD be skipped
+ array_close_or_element:
+ p = skip_whitespace(p + 1);
+ if (SAJSON_UNLIKELY(!p)) {
+ return unexpected_end();
+ }
+ if (*p == ']') {
+ goto pop_array;
+ } else {
+ goto next_element;
+ }
+ SAJSON_UNREACHABLE();
+
+ // ASSUMES: byte at p SHOULD be skipped
+ object_close_or_element:
+ p = skip_whitespace(p + 1);
+ if (SAJSON_UNLIKELY(!p)) {
+ return unexpected_end();
+ }
+ if (*p == '}') {
+ goto pop_object;
+ } else {
+ goto object_key;
+ }
+ SAJSON_UNREACHABLE();
+
+ // ASSUMES: byte at p SHOULD NOT be skipped
+ structure_close_or_comma:
+ p = skip_whitespace(p);
+ if (SAJSON_UNLIKELY(!p)) {
+ return unexpected_end();
+ }
+
+ if (current_structure_type == TYPE_ARRAY) {
+ if (*p == ']') {
+ goto pop_array;
+ } else {
+ if (SAJSON_UNLIKELY(*p != ',')) {
+ return make_error(p, ERROR_EXPECTED_COMMA);
+ }
+ ++p;
+ goto next_element;
+ }
+ } else {
+ assert(current_structure_type == TYPE_OBJECT);
+ if (*p == '}') {
+ goto pop_object;
+ } else {
+ if (SAJSON_UNLIKELY(*p != ',')) {
+ return make_error(p, ERROR_EXPECTED_COMMA);
+ }
+ ++p;
+ goto object_key;
+ }
+ }
+ SAJSON_UNREACHABLE();
+
+ // ASSUMES: *p == '}'
+ pop_object: {
+ ++p;
+ size_t* base_ptr = stack.get_pointer_from_offset(current_base);
+ pop_element = *base_ptr;
+ if (SAJSON_UNLIKELY(!install_object(base_ptr + 1, stack.get_top()))) {
+ return oom(p);
+ }
+ goto pop;
+ }
+
+ // ASSUMES: *p == ']'
+ pop_array: {
+ ++p;
+ size_t* base_ptr = stack.get_pointer_from_offset(current_base);
+ pop_element = *base_ptr;
+ if (SAJSON_UNLIKELY(!install_array(base_ptr + 1, stack.get_top()))) {
+ return oom(p);
+ }
+ goto pop;
+ }
+
+ // ASSUMES: byte at p SHOULD NOT be skipped
+ object_key: {
+ p = skip_whitespace(p);
+ if (SAJSON_UNLIKELY(!p)) {
+ return unexpected_end();
+ }
+ if (SAJSON_UNLIKELY(*p != '"')) {
+ return make_error(p, ERROR_MISSING_OBJECT_KEY);
+ }
+ bool success_;
+ size_t* out = stack.reserve(2, &success_);
+ if (SAJSON_UNLIKELY(!success_)) {
+ return oom(p);
+ }
+ p = parse_string(p, out);
+ if (SAJSON_UNLIKELY(!p)) {
+ return false;
+ }
+ p = skip_whitespace(p);
+ if (SAJSON_UNLIKELY(!p || *p != ':')) {
+ return make_error(p, ERROR_EXPECTED_COLON);
+ }
+ ++p;
+ goto next_element;
+ }
+
+ // ASSUMES: byte at p SHOULD NOT be skipped
+ next_element:
+ p = skip_whitespace(p);
+ if (SAJSON_UNLIKELY(!p)) {
+ return unexpected_end();
+ }
+
+ type value_type_result;
+ switch (*p) {
+ case 0:
+ return unexpected_end(p);
+ case 'n':
+ p = parse_null(p);
+ if (!p) {
+ return false;
+ }
+ value_type_result = TYPE_NULL;
+ break;
+ case 'f':
+ p = parse_false(p);
+ if (!p) {
+ return false;
+ }
+ value_type_result = TYPE_FALSE;
+ break;
+ case 't':
+ p = parse_true(p);
+ if (!p) {
+ return false;
+ }
+ value_type_result = TYPE_TRUE;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-': {
+ auto result = parse_number(p);
+ p = result.first;
+ if (!p) {
+ return false;
+ }
+ value_type_result = result.second;
+ break;
+ }
+ case '"': {
+ bool success_;
+ size_t* string_tag = allocator.reserve(2, &success_);
+ if (SAJSON_UNLIKELY(!success_)) {
+ return oom(p);
+ }
+ p = parse_string(p, string_tag);
+ if (!p) {
+ return false;
+ }
+ value_type_result = TYPE_STRING;
+ break;
+ }
+
+ case '[': {
+ size_t previous_base = current_base;
+ current_base = stack.get_size();
+ bool s = stack.push(make_element(current_structure_type, previous_base));
+ if (SAJSON_UNLIKELY(!s)) {
+ return oom(p);
+ }
+ current_structure_type = TYPE_ARRAY;
+ goto array_close_or_element;
+ }
+ case '{': {
+ size_t previous_base = current_base;
+ current_base = stack.get_size();
+ bool s = stack.push(make_element(current_structure_type, previous_base));
+ if (SAJSON_UNLIKELY(!s)) {
+ return oom(p);
+ }
+ current_structure_type = TYPE_OBJECT;
+ goto object_close_or_element;
+ }
+ pop: {
+ size_t parent = get_element_value(pop_element);
+ if (parent == ROOT_MARKER) {
+ root_type = current_structure_type;
+ p = skip_whitespace(p);
+ if (SAJSON_UNLIKELY(p)) {
+ return make_error(p, ERROR_EXPECTED_END_OF_INPUT);
+ }
+ return true;
+ }
+ stack.reset(current_base);
+ current_base = parent;
+ value_type_result = current_structure_type;
+ current_structure_type = get_element_type(pop_element);
+ break;
+ }
+
+ case ',':
+ return make_error(p, ERROR_UNEXPECTED_COMMA);
+ default:
+ return make_error(p, ERROR_EXPECTED_VALUE);
+ }
+
+ bool s = stack.push(make_element(
+ value_type_result,
+ allocator.get_write_offset()));
+ if (SAJSON_UNLIKELY(!s)) {
+ return oom(p);
+ }
+
+ goto structure_close_or_comma;
+ }
+
+ SAJSON_UNREACHABLE();
+ }
+
+ bool has_remaining_characters(char* p, ptrdiff_t remaining) {
+ return input_end - p >= remaining;
+ }
+
+ char* parse_null(char* p) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 4))) {
+ make_error(p, ERROR_UNEXPECTED_END);
+ return 0;
+ }
+ char p1 = p[1];
+ char p2 = p[2];
+ char p3 = p[3];
+ if (SAJSON_UNLIKELY(p1 != 'u' || p2 != 'l' || p3 != 'l')) {
+ make_error(p, ERROR_EXPECTED_NULL);
+ return 0;
+ }
+ return p + 4;
+ }
+
+ char* parse_false(char* p) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 5))) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+ char p1 = p[1];
+ char p2 = p[2];
+ char p3 = p[3];
+ char p4 = p[4];
+ if (SAJSON_UNLIKELY(p1 != 'a' || p2 != 'l' || p3 != 's' || p4 != 'e')) {
+ return make_error(p, ERROR_EXPECTED_FALSE);
+ }
+ return p + 5;
+ }
+
+ char* parse_true(char* p) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 4))) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+ char p1 = p[1];
+ char p2 = p[2];
+ char p3 = p[3];
+ if (SAJSON_UNLIKELY(p1 != 'r' || p2 != 'u' || p3 != 'e')) {
+ return make_error(p, ERROR_EXPECTED_TRUE);
+ }
+ return p + 4;
+ }
+
+ static double pow10(int64_t exponent) {
+ if (SAJSON_UNLIKELY(exponent > 308)) {
+ return std::numeric_limits<double>::infinity();
+ } else if (SAJSON_UNLIKELY(exponent < -323)) {
+ return 0.0;
+ }
+ static const double constants[] = {
+ 1e-323,1e-322,1e-321,1e-320,1e-319,1e-318,1e-317,1e-316,1e-315,1e-314,
+ 1e-313,1e-312,1e-311,1e-310,1e-309,1e-308,1e-307,1e-306,1e-305,1e-304,
+ 1e-303,1e-302,1e-301,1e-300,1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,
+ 1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,
+ 1e-283,1e-282,1e-281,1e-280,1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,
+ 1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,
+ 1e-263,1e-262,1e-261,1e-260,1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,
+ 1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,
+ 1e-243,1e-242,1e-241,1e-240,1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,
+ 1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,
+ 1e-223,1e-222,1e-221,1e-220,1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,
+ 1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,
+ 1e-203,1e-202,1e-201,1e-200,1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,
+ 1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,
+ 1e-183,1e-182,1e-181,1e-180,1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,
+ 1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,
+ 1e-163,1e-162,1e-161,1e-160,1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,
+ 1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,
+ 1e-143,1e-142,1e-141,1e-140,1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,
+ 1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,
+ 1e-123,1e-122,1e-121,1e-120,1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,
+ 1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,
+ 1e-103,1e-102,1e-101,1e-100,1e-99,1e-98,1e-97,1e-96,1e-95,1e-94,1e-93,
+ 1e-92,1e-91,1e-90,1e-89,1e-88,1e-87,1e-86,1e-85,1e-84,1e-83,1e-82,1e-81,
+ 1e-80,1e-79,1e-78,1e-77,1e-76,1e-75,1e-74,1e-73,1e-72,1e-71,1e-70,1e-69,
+ 1e-68,1e-67,1e-66,1e-65,1e-64,1e-63,1e-62,1e-61,1e-60,1e-59,1e-58,1e-57,
+ 1e-56,1e-55,1e-54,1e-53,1e-52,1e-51,1e-50,1e-49,1e-48,1e-47,1e-46,1e-45,
+ 1e-44,1e-43,1e-42,1e-41,1e-40,1e-39,1e-38,1e-37,1e-36,1e-35,1e-34,1e-33,
+ 1e-32,1e-31,1e-30,1e-29,1e-28,1e-27,1e-26,1e-25,1e-24,1e-23,1e-22,1e-21,
+ 1e-20,1e-19,1e-18,1e-17,1e-16,1e-15,1e-14,1e-13,1e-12,1e-11,1e-10,1e-9,
+ 1e-8,1e-7,1e-6,1e-5,1e-4,1e-3,1e-2,1e-1,1e0,1e1,1e2,1e3,1e4,1e5,1e6,1e7,
+ 1e8,1e9,1e10,1e11,1e12,1e13,1e14,1e15,1e16,1e17,1e18,1e19,1e20,1e21,
+ 1e22,1e23,1e24,1e25,1e26,1e27,1e28,1e29,1e30,1e31,1e32,1e33,1e34,1e35,
+ 1e36,1e37,1e38,1e39,1e40,1e41,1e42,1e43,1e44,1e45,1e46,1e47,1e48,1e49,
+ 1e50,1e51,1e52,1e53,1e54,1e55,1e56,1e57,1e58,1e59,1e60,1e61,1e62,1e63,
+ 1e64,1e65,1e66,1e67,1e68,1e69,1e70,1e71,1e72,1e73,1e74,1e75,1e76,1e77,
+ 1e78,1e79,1e80,1e81,1e82,1e83,1e84,1e85,1e86,1e87,1e88,1e89,1e90,1e91,
+ 1e92,1e93,1e94,1e95,1e96,1e97,1e98,1e99,1e100,1e101,1e102,1e103,1e104,
+ 1e105,1e106,1e107,1e108,1e109,1e110,1e111,1e112,1e113,1e114,1e115,1e116,
+ 1e117,1e118,1e119,1e120,1e121,1e122,1e123,1e124,1e125,1e126,1e127,1e128,
+ 1e129,1e130,1e131,1e132,1e133,1e134,1e135,1e136,1e137,1e138,1e139,1e140,
+ 1e141,1e142,1e143,1e144,1e145,1e146,1e147,1e148,1e149,1e150,1e151,1e152,
+ 1e153,1e154,1e155,1e156,1e157,1e158,1e159,1e160,1e161,1e162,1e163,1e164,
+ 1e165,1e166,1e167,1e168,1e169,1e170,1e171,1e172,1e173,1e174,1e175,1e176,
+ 1e177,1e178,1e179,1e180,1e181,1e182,1e183,1e184,1e185,1e186,1e187,1e188,
+ 1e189,1e190,1e191,1e192,1e193,1e194,1e195,1e196,1e197,1e198,1e199,1e200,
+ 1e201,1e202,1e203,1e204,1e205,1e206,1e207,1e208,1e209,1e210,1e211,1e212,
+ 1e213,1e214,1e215,1e216,1e217,1e218,1e219,1e220,1e221,1e222,1e223,1e224,
+ 1e225,1e226,1e227,1e228,1e229,1e230,1e231,1e232,1e233,1e234,1e235,1e236,
+ 1e237,1e238,1e239,1e240,1e241,1e242,1e243,1e244,1e245,1e246,1e247,1e248,
+ 1e249,1e250,1e251,1e252,1e253,1e254,1e255,1e256,1e257,1e258,1e259,1e260,
+ 1e261,1e262,1e263,1e264,1e265,1e266,1e267,1e268,1e269,1e270,1e271,1e272,
+ 1e273,1e274,1e275,1e276,1e277,1e278,1e279,1e280,1e281,1e282,1e283,1e284,
+ 1e285,1e286,1e287,1e288,1e289,1e290,1e291,1e292,1e293,1e294,1e295,1e296,
+ 1e297,1e298,1e299,1e300,1e301,1e302,1e303,1e304,1e305,1e306,1e307,1e308
+ };
+ return constants[exponent + 323];
+ }
+
+ std::pair<char*, type> parse_number(char* p) {
+ bool negative = false;
+ if ('-' == *p) {
+ ++p;
+ negative = true;
+
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+ }
+
+ bool try_double = false;
+
+ int i = 0;
+ double d = 0.0; // gcc complains that d might be used uninitialized which isn't true. appease the warning anyway.
+ if (*p == '0') {
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+ } else {
+ unsigned char c = *p;
+ if (c < '0' || c > '9') {
+ return std::make_pair(make_error(p, ERROR_INVALID_NUMBER), TYPE_NULL);
+ }
+
+ do {
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+
+ unsigned char digit = c - '0';
+
+ if (SAJSON_UNLIKELY(!try_double && i > INT_MAX / 10 - 9)) {
+ // TODO: could split this into two loops
+ try_double = true;
+ d = i;
+ }
+ if (SAJSON_UNLIKELY(try_double)) {
+ d = 10.0 * d + digit;
+ } else {
+ i = 10 * i + digit;
+ }
+
+ c = *p;
+ } while (c >= '0' && c <= '9');
+ }
+
+ int64_t exponent = 0;
+
+ if ('.' == *p) {
+ if (!try_double) {
+ try_double = true;
+ d = i;
+ }
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+ char c = *p;
+ if (c < '0' || c > '9') {
+ return std::make_pair(make_error(p, ERROR_INVALID_NUMBER), TYPE_NULL);
+ }
+
+ do {
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+ d = d * 10 + (c - '0');
+ // One option to avoid underflow would be to clamp
+ // to INT_MIN, but int64 subtraction is cheap and
+ // in the absurd case of parsing 2 GB of digits
+ // with an extremely high exponent, this will
+ // produce accurate results. Instead, we just
+ // leave exponent as int64_t and it will never
+ // underflow.
+ --exponent;
+
+ c = *p;
+ } while (c >= '0' && c <= '9');
+ }
+
+ char e = *p;
+ if ('e' == e || 'E' == e) {
+ if (!try_double) {
+ try_double = true;
+ d = i;
+ }
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+
+ bool negativeExponent = false;
+ if ('-' == *p) {
+ negativeExponent = true;
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+ } else if ('+' == *p) {
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+ }
+
+ int exp = 0;
+
+ char c = *p;
+ if (SAJSON_UNLIKELY(c < '0' || c > '9')) {
+ return std::make_pair(make_error(p, ERROR_MISSING_EXPONENT), TYPE_NULL);
+ }
+ for (;;) {
+ // c guaranteed to be between '0' and '9', inclusive
+ unsigned char digit = c - '0';
+ if (exp > (INT_MAX - digit) / 10) {
+ // The exponent overflowed. Keep parsing, but
+ // it will definitely be out of range when
+ // pow10 is called.
+ exp = INT_MAX;
+ } else {
+ exp = 10 * exp + digit;
+ }
+
+ ++p;
+ if (SAJSON_UNLIKELY(at_eof(p))) {
+ return std::make_pair(make_error(p, ERROR_UNEXPECTED_END), TYPE_NULL);
+ }
+
+ c = *p;
+ if (c < '0' || c > '9') {
+ break;
+ }
+ }
+ static_assert(-INT_MAX >= INT_MIN, "exp can be negated without loss or UB");
+ exponent += (negativeExponent ? -exp : exp);
+ }
+
+ if (exponent) {
+ assert(try_double);
+ // If d is zero but the exponent is huge, don't
+ // multiply zero by inf which gives nan.
+ if (d != 0.0) {
+ d *= pow10(exponent);
+ }
+ }
+
+ if (negative) {
+ if (try_double) {
+ d = -d;
+ } else {
+ i = -i;
+ }
+ }
+ if (try_double) {
+ bool success;
+ size_t* out = allocator.reserve(double_storage::word_length, &success);
+ if (SAJSON_UNLIKELY(!success)) {
+ return std::make_pair(oom(p), TYPE_NULL);
+ }
+ double_storage::store(out, d);
+ return std::make_pair(p, TYPE_DOUBLE);
+ } else {
+ bool success;
+ size_t* out = allocator.reserve(integer_storage::word_length, &success);
+ if (SAJSON_UNLIKELY(!success)) {
+ return std::make_pair(oom(p), TYPE_NULL);
+ }
+ integer_storage::store(out, i);
+ return std::make_pair(p, TYPE_INTEGER);
+ }
+ }
+
+ bool install_array(size_t* array_base, size_t* array_end) {
+ using namespace sajson::internal;
+
+ const size_t length = array_end - array_base;
+ bool success;
+ size_t* const new_base = allocator.reserve(length + 1, &success);
+ if (SAJSON_UNLIKELY(!success)) {
+ return false;
+ }
+ size_t* out = new_base + length + 1;
+ size_t* const structure_end = allocator.get_write_pointer_of(0);
+
+ while (array_end > array_base) {
+ size_t element = *--array_end;
+ type element_type = get_element_type(element);
+ size_t element_value = get_element_value(element);
+ size_t* element_ptr = structure_end - element_value;
+ *--out = make_element(element_type, element_ptr - new_base);
+ }
+ *--out = length;
+ return true;
+ }
+
+ bool install_object(size_t* object_base, size_t* object_end) {
+ using namespace internal;
+
+ assert((object_end - object_base) % 3 == 0);
+ const size_t length_times_3 = object_end - object_base;
+#ifndef SAJSON_UNSORTED_OBJECT_KEYS
+ std::sort(
+ reinterpret_cast<object_key_record*>(object_base),
+ reinterpret_cast<object_key_record*>(object_end),
+ object_key_comparator(input.get_data()));
+#endif
+
+ bool success;
+ size_t* const new_base = allocator.reserve(length_times_3 + 1, &success);
+ if (SAJSON_UNLIKELY(!success)) {
+ return false;
+ }
+ size_t* out = new_base + length_times_3 + 1;
+ size_t* const structure_end = allocator.get_write_pointer_of(0);
+
+ while (object_end > object_base) {
+ size_t element = *--object_end;
+ type element_type = get_element_type(element);
+ size_t element_value = get_element_value(element);
+ size_t* element_ptr = structure_end - element_value;
+
+ *--out = make_element(element_type, element_ptr - new_base);
+ *--out = *--object_end;
+ *--out = *--object_end;
+ }
+ *--out = length_times_3 / 3;
+ return true;
+ }
+
+ char* parse_string(char* p, size_t* tag) {
+ using namespace internal;
+
+ ++p; // "
+ size_t start = p - input.get_data();
+ char* input_end_local = input_end;
+ while (input_end_local - p >= 4) {
+ if (!is_plain_string_character(p[0])) { goto found; }
+ if (!is_plain_string_character(p[1])) { p += 1; goto found; }
+ if (!is_plain_string_character(p[2])) { p += 2; goto found; }
+ if (!is_plain_string_character(p[3])) { p += 3; goto found; }
+ p += 4;
+ }
+ for (;;) {
+ if (SAJSON_UNLIKELY(p >= input_end_local)) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+
+ if (!is_plain_string_character(*p)) {
+ break;
+ }
+
+ ++p;
+ }
+ found:
+ if (SAJSON_LIKELY(*p == '"')) {
+ tag[0] = start;
+ tag[1] = p - input.get_data();
+ *p = '\0';
+ return p + 1;
+ }
+
+ if (*p >= 0 && *p < 0x20) {
+ return make_error(p, ERROR_ILLEGAL_CODEPOINT, static_cast<int>(*p));
+ } else {
+ // backslash or >0x7f
+ return parse_string_slow(p, tag, start);
+ }
+ }
+
+ char* read_hex(char* p, unsigned& u) {
+ unsigned v = 0;
+ int i = 4;
+ while (i--) {
+ unsigned char c = *p++;
+ if (c >= '0' && c <= '9') {
+ c -= '0';
+ } else if (c >= 'a' && c <= 'f') {
+ c = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ c = c - 'A' + 10;
+ } else {
+ return make_error(p, ERROR_INVALID_UNICODE_ESCAPE);
+ }
+ v = (v << 4) + c;
+ }
+
+ u = v;
+ return p;
+ }
+
+ void write_utf8(unsigned codepoint, char*& end) {
+ if (codepoint < 0x80) {
+ *end++ = char(codepoint);
+ } else if (codepoint < 0x800) {
+ *end++ = 0xC0 | char(codepoint >> 6);
+ *end++ = 0x80 | char(codepoint & 0x3F);
+ } else if (codepoint < 0x10000) {
+ *end++ = 0xE0 | char(codepoint >> 12);
+ *end++ = 0x80 | char((codepoint >> 6) & 0x3F);
+ *end++ = 0x80 | char(codepoint & 0x3F);
+ } else {
+ assert(codepoint < 0x200000);
+ *end++ = 0xF0 | char(codepoint >> 18);
+ *end++ = 0x80 | char((codepoint >> 12) & 0x3F);
+ *end++ = 0x80 | char((codepoint >> 6) & 0x3F);
+ *end++ = 0x80 | char(codepoint & 0x3F);
+ }
+ }
+
+ char* parse_string_slow(char* p, size_t* tag, size_t start) {
+ char* end = p;
+ char* input_end_local = input_end;
+
+ for (;;) {
+ if (SAJSON_UNLIKELY(p >= input_end_local)) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+
+ if (SAJSON_UNLIKELY(*p >= 0 && *p < 0x20)) {
+ return make_error(p, ERROR_ILLEGAL_CODEPOINT, static_cast<int>(*p));
+ }
+
+ switch (*p) {
+ case '"':
+ tag[0] = start;
+ tag[1] = end - input.get_data();
+ *end = '\0';
+ return p + 1;
+
+ case '\\':
+ ++p;
+ if (SAJSON_UNLIKELY(p >= input_end_local)) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+
+ char replacement;
+ switch (*p) {
+ case '"': replacement = '"'; goto replace;
+ case '\\': replacement = '\\'; goto replace;
+ case '/': replacement = '/'; goto replace;
+ case 'b': replacement = '\b'; goto replace;
+ case 'f': replacement = '\f'; goto replace;
+ case 'n': replacement = '\n'; goto replace;
+ case 'r': replacement = '\r'; goto replace;
+ case 't': replacement = '\t'; goto replace;
+ replace:
+ *end++ = replacement;
+ ++p;
+ break;
+ case 'u': {
+ ++p;
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 4))) {
+ return make_error(p, ERROR_UNEXPECTED_END);
+ }
+ unsigned u = 0; // gcc's complaining that this could be used uninitialized. wrong.
+ p = read_hex(p, u);
+ if (!p) {
+ return 0;
+ }
+ if (u >= 0xD800 && u <= 0xDBFF) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 6))) {
+ return make_error(p, ERROR_UNEXPECTED_END_OF_UTF16);
+ }
+ char p0 = p[0];
+ char p1 = p[1];
+ if (p0 != '\\' || p1 != 'u') {
+ return make_error(p, ERROR_EXPECTED_U);
+ }
+ p += 2;
+ unsigned v = 0; // gcc's complaining that this could be used uninitialized. wrong.
+ p = read_hex(p, v);
+ if (!p) {
+ return p;
+ }
+
+ if (v < 0xDC00 || v > 0xDFFF) {
+ return make_error(p, ERROR_INVALID_UTF16_TRAIL_SURROGATE);
+ }
+ u = 0x10000 + (((u - 0xD800) << 10) | (v - 0xDC00));
+ }
+ write_utf8(u, end);
+ break;
+ }
+ default:
+ return make_error(p, ERROR_UNKNOWN_ESCAPE);
+ }
+ break;
+
+ default:
+ // validate UTF-8
+ unsigned char c0 = p[0];
+ if (c0 < 128) {
+ *end++ = *p++;
+ } else if (c0 < 224) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 2))) {
+ return unexpected_end(p);
+ }
+ unsigned char c1 = p[1];
+ if (c1 < 128 || c1 >= 192) {
+ return make_error(p + 1, ERROR_INVALID_UTF8);
+ }
+ end[0] = c0;
+ end[1] = c1;
+ end += 2;
+ p += 2;
+ } else if (c0 < 240) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 3))) {
+ return unexpected_end(p);
+ }
+ unsigned char c1 = p[1];
+ if (c1 < 128 || c1 >= 192) {
+ return make_error(p + 1, ERROR_INVALID_UTF8);
+ }
+ unsigned char c2 = p[2];
+ if (c2 < 128 || c2 >= 192) {
+ return make_error(p + 2, ERROR_INVALID_UTF8);
+ }
+ end[0] = c0;
+ end[1] = c1;
+ end[2] = c2;
+ end += 3;
+ p += 3;
+ } else if (c0 < 248) {
+ if (SAJSON_UNLIKELY(!has_remaining_characters(p, 4))) {
+ return unexpected_end(p);
+ }
+ unsigned char c1 = p[1];
+ if (c1 < 128 || c1 >= 192) {
+ return make_error(p + 1, ERROR_INVALID_UTF8);
+ }
+ unsigned char c2 = p[2];
+ if (c2 < 128 || c2 >= 192) {
+ return make_error(p + 2, ERROR_INVALID_UTF8);
+ }
+ unsigned char c3 = p[3];
+ if (c3 < 128 || c3 >= 192) {
+ return make_error(p + 3, ERROR_INVALID_UTF8);
+ }
+ end[0] = c0;
+ end[1] = c1;
+ end[2] = c2;
+ end[3] = c3;
+ end += 4;
+ p += 4;
+ } else {
+ return make_error(p, ERROR_INVALID_UTF8);
+ }
+ break;
+ }
+ }
+ }
+
+ mutable_string_view input;
+ char* const input_end;
+ Allocator allocator;
+
+ type root_type;
+ size_t error_line;
+ size_t error_column;
+ error error_code;
+ int error_arg; // optional argument for the error
+ };
+ /// \endcond
+
+ /**
+ * Parses a string of JSON bytes into a \ref document, given an allocation
+ * strategy instance. Any kind of string type is valid as long as a
+ * mutable_string_view can be constructed from it.
+ *
+ * Valid allocation strategies are \ref single_allocation,
+ * \ref dynamic_allocation, and \ref bounded_allocation.
+ *
+ * A \ref document is returned whether or not the parse succeeds: success
+ * state is available by calling document::is_valid().
+ */
+ template<typename AllocationStrategy, typename StringType>
+ document parse(const AllocationStrategy& strategy, const StringType& string) {
+ mutable_string_view input(string);
+
+ bool success;
+ auto allocator = strategy.make_allocator(input.length(), &success);
+ if (!success) {
+ return document(input, 1, 1, ERROR_OUT_OF_MEMORY, 0);
+ }
+
+ return parser<typename AllocationStrategy::allocator>(
+ input,
+ std::move(allocator)
+ ).get_document();
+ }
+}
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_api.h b/Client/ThirdParty/Box2D/include/box2d/b2_api.h
new file mode 100644
index 0000000..6730203
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_api.h
@@ -0,0 +1,52 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_API_H
+#define B2_API_H
+
+#ifdef B2_SHARED
+ #if defined _WIN32 || defined __CYGWIN__
+ #ifdef box2d_EXPORTS
+ #ifdef __GNUC__
+ #define B2_API __attribute__ ((dllexport))
+ #else
+ #define B2_API __declspec(dllexport)
+ #endif
+ #else
+ #ifdef __GNUC__
+ #define B2_API __attribute__ ((dllimport))
+ #else
+ #define B2_API __declspec(dllimport)
+ #endif
+ #endif
+ #else
+ #if __GNUC__ >= 4
+ #define B2_API __attribute__ ((visibility ("default")))
+ #else
+ #define B2_API
+ #endif
+ #endif
+#else
+ #define B2_API
+#endif
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_block_allocator.h b/Client/ThirdParty/Box2D/include/box2d/b2_block_allocator.h
new file mode 100644
index 0000000..95c12de
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_block_allocator.h
@@ -0,0 +1,60 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_BLOCK_ALLOCATOR_H
+#define B2_BLOCK_ALLOCATOR_H
+
+#include "b2_api.h"
+#include "b2_settings.h"
+
+const int32 b2_blockSizeCount = 14;
+
+struct b2Block;
+struct b2Chunk;
+
+/// This is a small object allocator used for allocating small
+/// objects that persist for more than one time step.
+/// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp
+class B2_API b2BlockAllocator
+{
+public:
+ b2BlockAllocator();
+ ~b2BlockAllocator();
+
+ /// Allocate memory. This will use b2Alloc if the size is larger than b2_maxBlockSize.
+ void* Allocate(int32 size);
+
+ /// Free memory. This will use b2Free if the size is larger than b2_maxBlockSize.
+ void Free(void* p, int32 size);
+
+ void Clear();
+
+private:
+
+ b2Chunk* m_chunks;
+ int32 m_chunkCount;
+ int32 m_chunkSpace;
+
+ b2Block* m_freeLists[b2_blockSizeCount];
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_body.h b/Client/ThirdParty/Box2D/include/box2d/b2_body.h
new file mode 100644
index 0000000..ff4adec
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_body.h
@@ -0,0 +1,878 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_BODY_H
+#define B2_BODY_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+#include "b2_shape.h"
+
+class b2Fixture;
+class b2Joint;
+class b2Contact;
+class b2Controller;
+class b2World;
+struct b2FixtureDef;
+struct b2JointEdge;
+struct b2ContactEdge;
+
+/// The body type.
+/// static: zero mass, zero velocity, may be manually moved
+/// kinematic: zero mass, non-zero velocity set by user, moved by solver
+/// dynamic: positive mass, non-zero velocity determined by forces, moved by solver
+enum b2BodyType
+{
+ b2_staticBody = 0,
+ b2_kinematicBody,
+ b2_dynamicBody
+};
+
+/// A body definition holds all the data needed to construct a rigid body.
+/// You can safely re-use body definitions. Shapes are added to a body after construction.
+struct B2_API b2BodyDef
+{
+ /// This constructor sets the body definition default values.
+ b2BodyDef()
+ {
+ position.Set(0.0f, 0.0f);
+ angle = 0.0f;
+ linearVelocity.Set(0.0f, 0.0f);
+ angularVelocity = 0.0f;
+ linearDamping = 0.0f;
+ angularDamping = 0.0f;
+ allowSleep = true;
+ awake = true;
+ fixedRotation = false;
+ bullet = false;
+ type = b2_staticBody;
+ enabled = true;
+ gravityScale = 1.0f;
+ }
+
+ /// The body type: static, kinematic, or dynamic.
+ /// Note: if a dynamic body would have zero mass, the mass is set to one.
+ b2BodyType type;
+
+ /// The world position of the body. Avoid creating bodies at the origin
+ /// since this can lead to many overlapping shapes.
+ b2Vec2 position;
+
+ /// The world angle of the body in radians.
+ float angle;
+
+ /// The linear velocity of the body's origin in world co-ordinates.
+ b2Vec2 linearVelocity;
+
+ /// The angular velocity of the body.
+ float angularVelocity;
+
+ /// Linear damping is use to reduce the linear velocity. The damping parameter
+ /// can be larger than 1.0f but the damping effect becomes sensitive to the
+ /// time step when the damping parameter is large.
+ /// Units are 1/time
+ float linearDamping;
+
+ /// Angular damping is use to reduce the angular velocity. The damping parameter
+ /// can be larger than 1.0f but the damping effect becomes sensitive to the
+ /// time step when the damping parameter is large.
+ /// Units are 1/time
+ float angularDamping;
+
+ /// Set this flag to false if this body should never fall asleep. Note that
+ /// this increases CPU usage.
+ bool allowSleep;
+
+ /// Is this body initially awake or sleeping?
+ bool awake;
+
+ /// Should this body be prevented from rotating? Useful for characters.
+ bool fixedRotation;
+
+ /// Is this a fast moving body that should be prevented from tunneling through
+ /// other moving bodies? Note that all bodies are prevented from tunneling through
+ /// kinematic and static bodies. This setting is only considered on dynamic bodies.
+ /// @warning You should use this flag sparingly since it increases processing time.
+ bool bullet;
+
+ /// Does this body start out enabled?
+ bool enabled;
+
+ /// Use this to store application specific body data.
+ b2BodyUserData userData;
+
+ /// Scale the gravity applied to this body.
+ float gravityScale;
+};
+
+/// A rigid body. These are created via b2World::CreateBody.
+class B2_API b2Body
+{
+public:
+ /// Creates a fixture and attach it to this body. Use this function if you need
+ /// to set some fixture parameters, like friction. Otherwise you can create the
+ /// fixture directly from a shape.
+ /// If the density is non-zero, this function automatically updates the mass of the body.
+ /// Contacts are not created until the next time step.
+ /// @param def the fixture definition.
+ /// @warning This function is locked during callbacks.
+ b2Fixture* CreateFixture(const b2FixtureDef* def);
+
+ /// Creates a fixture from a shape and attach it to this body.
+ /// This is a convenience function. Use b2FixtureDef if you need to set parameters
+ /// like friction, restitution, user data, or filtering.
+ /// If the density is non-zero, this function automatically updates the mass of the body.
+ /// @param shape the shape to be cloned.
+ /// @param density the shape density (set to zero for static bodies).
+ /// @warning This function is locked during callbacks.
+ b2Fixture* CreateFixture(const b2Shape* shape, float density);
+
+ /// Destroy a fixture. This removes the fixture from the broad-phase and
+ /// destroys all contacts associated with this fixture. This will
+ /// automatically adjust the mass of the body if the body is dynamic and the
+ /// fixture has positive density.
+ /// All fixtures attached to a body are implicitly destroyed when the body is destroyed.
+ /// @param fixture the fixture to be removed.
+ /// @warning This function is locked during callbacks.
+ void DestroyFixture(b2Fixture* fixture);
+
+ /// Set the position of the body's origin and rotation.
+ /// Manipulating a body's transform may cause non-physical behavior.
+ /// Note: contacts are updated on the next call to b2World::Step.
+ /// @param position the world position of the body's local origin.
+ /// @param angle the world rotation in radians.
+ void SetTransform(const b2Vec2& position, float angle);
+
+ /// Get the body transform for the body's origin.
+ /// @return the world transform of the body's origin.
+ const b2Transform& GetTransform() const;
+
+ /// Get the world body origin position.
+ /// @return the world position of the body's origin.
+ const b2Vec2& GetPosition() const;
+
+ /// Get the angle in radians.
+ /// @return the current world rotation angle in radians.
+ float GetAngle() const;
+
+ /// Get the world position of the center of mass.
+ const b2Vec2& GetWorldCenter() const;
+
+ /// Get the local position of the center of mass.
+ const b2Vec2& GetLocalCenter() const;
+
+ /// Set the linear velocity of the center of mass.
+ /// @param v the new linear velocity of the center of mass.
+ void SetLinearVelocity(const b2Vec2& v);
+
+ /// Get the linear velocity of the center of mass.
+ /// @return the linear velocity of the center of mass.
+ const b2Vec2& GetLinearVelocity() const;
+
+ /// Set the angular velocity.
+ /// @param omega the new angular velocity in radians/second.
+ void SetAngularVelocity(float omega);
+
+ /// Get the angular velocity.
+ /// @return the angular velocity in radians/second.
+ float GetAngularVelocity() const;
+
+ /// Apply a force at a world point. If the force is not
+ /// applied at the center of mass, it will generate a torque and
+ /// affect the angular velocity. This wakes up the body.
+ /// @param force the world force vector, usually in Newtons (N).
+ /// @param point the world position of the point of application.
+ /// @param wake also wake up the body
+ void ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake);
+
+ /// Apply a force to the center of mass. This wakes up the body.
+ /// @param force the world force vector, usually in Newtons (N).
+ /// @param wake also wake up the body
+ void ApplyForceToCenter(const b2Vec2& force, bool wake);
+
+ /// Apply a torque. This affects the angular velocity
+ /// without affecting the linear velocity of the center of mass.
+ /// @param torque about the z-axis (out of the screen), usually in N-m.
+ /// @param wake also wake up the body
+ void ApplyTorque(float torque, bool wake);
+
+ /// Apply an impulse at a point. This immediately modifies the velocity.
+ /// It also modifies the angular velocity if the point of application
+ /// is not at the center of mass. This wakes up the body.
+ /// @param impulse the world impulse vector, usually in N-seconds or kg-m/s.
+ /// @param point the world position of the point of application.
+ /// @param wake also wake up the body
+ void ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point, bool wake);
+
+ /// Apply an impulse to the center of mass. This immediately modifies the velocity.
+ /// @param impulse the world impulse vector, usually in N-seconds or kg-m/s.
+ /// @param wake also wake up the body
+ void ApplyLinearImpulseToCenter(const b2Vec2& impulse, bool wake);
+
+ /// Apply an angular impulse.
+ /// @param impulse the angular impulse in units of kg*m*m/s
+ /// @param wake also wake up the body
+ void ApplyAngularImpulse(float impulse, bool wake);
+
+ /// Get the total mass of the body.
+ /// @return the mass, usually in kilograms (kg).
+ float GetMass() const;
+
+ /// Get the rotational inertia of the body about the local origin.
+ /// @return the rotational inertia, usually in kg-m^2.
+ float GetInertia() const;
+
+ /// Get the mass data of the body.
+ /// @return a struct containing the mass, inertia and center of the body.
+ void GetMassData(b2MassData* data) const;
+
+ /// Set the mass properties to override the mass properties of the fixtures.
+ /// Note that this changes the center of mass position.
+ /// Note that creating or destroying fixtures can also alter the mass.
+ /// This function has no effect if the body isn't dynamic.
+ /// @param data the mass properties.
+ void SetMassData(const b2MassData* data);
+
+ /// This resets the mass properties to the sum of the mass properties of the fixtures.
+ /// This normally does not need to be called unless you called SetMassData to override
+ /// the mass and you later want to reset the mass.
+ void ResetMassData();
+
+ /// Get the world coordinates of a point given the local coordinates.
+ /// @param localPoint a point on the body measured relative the the body's origin.
+ /// @return the same point expressed in world coordinates.
+ b2Vec2 GetWorldPoint(const b2Vec2& localPoint) const;
+
+ /// Get the world coordinates of a vector given the local coordinates.
+ /// @param localVector a vector fixed in the body.
+ /// @return the same vector expressed in world coordinates.
+ b2Vec2 GetWorldVector(const b2Vec2& localVector) const;
+
+ /// Gets a local point relative to the body's origin given a world point.
+ /// @param worldPoint a point in world coordinates.
+ /// @return the corresponding local point relative to the body's origin.
+ b2Vec2 GetLocalPoint(const b2Vec2& worldPoint) const;
+
+ /// Gets a local vector given a world vector.
+ /// @param worldVector a vector in world coordinates.
+ /// @return the corresponding local vector.
+ b2Vec2 GetLocalVector(const b2Vec2& worldVector) const;
+
+ /// Get the world linear velocity of a world point attached to this body.
+ /// @param worldPoint a point in world coordinates.
+ /// @return the world velocity of a point.
+ b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const;
+
+ /// Get the world velocity of a local point.
+ /// @param localPoint a point in local coordinates.
+ /// @return the world velocity of a point.
+ b2Vec2 GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const;
+
+ /// Get the linear damping of the body.
+ float GetLinearDamping() const;
+
+ /// Set the linear damping of the body.
+ void SetLinearDamping(float linearDamping);
+
+ /// Get the angular damping of the body.
+ float GetAngularDamping() const;
+
+ /// Set the angular damping of the body.
+ void SetAngularDamping(float angularDamping);
+
+ /// Get the gravity scale of the body.
+ float GetGravityScale() const;
+
+ /// Set the gravity scale of the body.
+ void SetGravityScale(float scale);
+
+ /// Set the type of this body. This may alter the mass and velocity.
+ void SetType(b2BodyType type);
+
+ /// Get the type of this body.
+ b2BodyType GetType() const;
+
+ /// Should this body be treated like a bullet for continuous collision detection?
+ void SetBullet(bool flag);
+
+ /// Is this body treated like a bullet for continuous collision detection?
+ bool IsBullet() const;
+
+ /// You can disable sleeping on this body. If you disable sleeping, the
+ /// body will be woken.
+ void SetSleepingAllowed(bool flag);
+
+ /// Is this body allowed to sleep
+ bool IsSleepingAllowed() const;
+
+ /// Set the sleep state of the body. A sleeping body has very
+ /// low CPU cost.
+ /// @param flag set to true to wake the body, false to put it to sleep.
+ void SetAwake(bool flag);
+
+ /// Get the sleeping state of this body.
+ /// @return true if the body is awake.
+ bool IsAwake() const;
+
+ /// Allow a body to be disabled. A disabled body is not simulated and cannot
+ /// be collided with or woken up.
+ /// If you pass a flag of true, all fixtures will be added to the broad-phase.
+ /// If you pass a flag of false, all fixtures will be removed from the
+ /// broad-phase and all contacts will be destroyed.
+ /// Fixtures and joints are otherwise unaffected. You may continue
+ /// to create/destroy fixtures and joints on disabled bodies.
+ /// Fixtures on a disabled body are implicitly disabled and will
+ /// not participate in collisions, ray-casts, or queries.
+ /// Joints connected to a disabled body are implicitly disabled.
+ /// An diabled body is still owned by a b2World object and remains
+ /// in the body list.
+ void SetEnabled(bool flag);
+
+ /// Get the active state of the body.
+ bool IsEnabled() const;
+
+ /// Set this body to have fixed rotation. This causes the mass
+ /// to be reset.
+ void SetFixedRotation(bool flag);
+
+ /// Does this body have fixed rotation?
+ bool IsFixedRotation() const;
+
+ /// Get the list of all fixtures attached to this body.
+ b2Fixture* GetFixtureList();
+ const b2Fixture* GetFixtureList() const;
+
+ /// Get the list of all joints attached to this body.
+ b2JointEdge* GetJointList();
+ const b2JointEdge* GetJointList() const;
+
+ /// Get the list of all contacts attached to this body.
+ /// @warning this list changes during the time step and you may
+ /// miss some collisions if you don't use b2ContactListener.
+ b2ContactEdge* GetContactList();
+ const b2ContactEdge* GetContactList() const;
+
+ /// Get the next body in the world's body list.
+ b2Body* GetNext();
+ const b2Body* GetNext() const;
+
+ /// Get the user data pointer that was provided in the body definition.
+ b2BodyUserData& GetUserData();
+
+ /// Get the parent world of this body.
+ b2World* GetWorld();
+ const b2World* GetWorld() const;
+
+ /// Dump this body to a file
+ void Dump();
+
+private:
+
+ friend class b2World;
+ friend class b2Island;
+ friend class b2ContactManager;
+ friend class b2ContactSolver;
+ friend class b2Contact;
+
+ friend class b2DistanceJoint;
+ friend class b2FrictionJoint;
+ friend class b2GearJoint;
+ friend class b2MotorJoint;
+ friend class b2MouseJoint;
+ friend class b2PrismaticJoint;
+ friend class b2PulleyJoint;
+ friend class b2RevoluteJoint;
+ friend class b2RopeJoint;
+ friend class b2WeldJoint;
+ friend class b2WheelJoint;
+
+ // m_flags
+ enum
+ {
+ e_islandFlag = 0x0001,
+ e_awakeFlag = 0x0002,
+ e_autoSleepFlag = 0x0004,
+ e_bulletFlag = 0x0008,
+ e_fixedRotationFlag = 0x0010,
+ e_enabledFlag = 0x0020,
+ e_toiFlag = 0x0040
+ };
+
+ b2Body(const b2BodyDef* bd, b2World* world);
+ ~b2Body();
+
+ void SynchronizeFixtures();
+ void SynchronizeTransform();
+
+ // This is used to prevent connected bodies from colliding.
+ // It may lie, depending on the collideConnected flag.
+ bool ShouldCollide(const b2Body* other) const;
+
+ void Advance(float t);
+
+ b2BodyType m_type;
+
+ uint16 m_flags;
+
+ int32 m_islandIndex;
+
+ b2Transform m_xf; // the body origin transform
+ b2Sweep m_sweep; // the swept motion for CCD
+
+ b2Vec2 m_linearVelocity;
+ float m_angularVelocity;
+
+ b2Vec2 m_force;
+ float m_torque;
+
+ b2World* m_world;
+ b2Body* m_prev;
+ b2Body* m_next;
+
+ b2Fixture* m_fixtureList;
+ int32 m_fixtureCount;
+
+ b2JointEdge* m_jointList;
+ b2ContactEdge* m_contactList;
+
+ float m_mass, m_invMass;
+
+ // Rotational inertia about the center of mass.
+ float m_I, m_invI;
+
+ float m_linearDamping;
+ float m_angularDamping;
+ float m_gravityScale;
+
+ float m_sleepTime;
+
+ b2BodyUserData m_userData;
+};
+
+inline b2BodyType b2Body::GetType() const
+{
+ return m_type;
+}
+
+inline const b2Transform& b2Body::GetTransform() const
+{
+ return m_xf;
+}
+
+inline const b2Vec2& b2Body::GetPosition() const
+{
+ return m_xf.p;
+}
+
+inline float b2Body::GetAngle() const
+{
+ return m_sweep.a;
+}
+
+inline const b2Vec2& b2Body::GetWorldCenter() const
+{
+ return m_sweep.c;
+}
+
+inline const b2Vec2& b2Body::GetLocalCenter() const
+{
+ return m_sweep.localCenter;
+}
+
+inline void b2Body::SetLinearVelocity(const b2Vec2& v)
+{
+ if (m_type == b2_staticBody)
+ {
+ return;
+ }
+
+ if (b2Dot(v,v) > 0.0f)
+ {
+ SetAwake(true);
+ }
+
+ m_linearVelocity = v;
+}
+
+inline const b2Vec2& b2Body::GetLinearVelocity() const
+{
+ return m_linearVelocity;
+}
+
+inline void b2Body::SetAngularVelocity(float w)
+{
+ if (m_type == b2_staticBody)
+ {
+ return;
+ }
+
+ if (w * w > 0.0f)
+ {
+ SetAwake(true);
+ }
+
+ m_angularVelocity = w;
+}
+
+inline float b2Body::GetAngularVelocity() const
+{
+ return m_angularVelocity;
+}
+
+inline float b2Body::GetMass() const
+{
+ return m_mass;
+}
+
+inline float b2Body::GetInertia() const
+{
+ return m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter);
+}
+
+inline void b2Body::GetMassData(b2MassData* data) const
+{
+ data->mass = m_mass;
+ data->I = m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter);
+ data->center = m_sweep.localCenter;
+}
+
+inline b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint) const
+{
+ return b2Mul(m_xf, localPoint);
+}
+
+inline b2Vec2 b2Body::GetWorldVector(const b2Vec2& localVector) const
+{
+ return b2Mul(m_xf.q, localVector);
+}
+
+inline b2Vec2 b2Body::GetLocalPoint(const b2Vec2& worldPoint) const
+{
+ return b2MulT(m_xf, worldPoint);
+}
+
+inline b2Vec2 b2Body::GetLocalVector(const b2Vec2& worldVector) const
+{
+ return b2MulT(m_xf.q, worldVector);
+}
+
+inline b2Vec2 b2Body::GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const
+{
+ return m_linearVelocity + b2Cross(m_angularVelocity, worldPoint - m_sweep.c);
+}
+
+inline b2Vec2 b2Body::GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const
+{
+ return GetLinearVelocityFromWorldPoint(GetWorldPoint(localPoint));
+}
+
+inline float b2Body::GetLinearDamping() const
+{
+ return m_linearDamping;
+}
+
+inline void b2Body::SetLinearDamping(float linearDamping)
+{
+ m_linearDamping = linearDamping;
+}
+
+inline float b2Body::GetAngularDamping() const
+{
+ return m_angularDamping;
+}
+
+inline void b2Body::SetAngularDamping(float angularDamping)
+{
+ m_angularDamping = angularDamping;
+}
+
+inline float b2Body::GetGravityScale() const
+{
+ return m_gravityScale;
+}
+
+inline void b2Body::SetGravityScale(float scale)
+{
+ m_gravityScale = scale;
+}
+
+inline void b2Body::SetBullet(bool flag)
+{
+ if (flag)
+ {
+ m_flags |= e_bulletFlag;
+ }
+ else
+ {
+ m_flags &= ~e_bulletFlag;
+ }
+}
+
+inline bool b2Body::IsBullet() const
+{
+ return (m_flags & e_bulletFlag) == e_bulletFlag;
+}
+
+inline void b2Body::SetAwake(bool flag)
+{
+ if (m_type == b2_staticBody)
+ {
+ return;
+ }
+
+ if (flag)
+ {
+ m_flags |= e_awakeFlag;
+ m_sleepTime = 0.0f;
+ }
+ else
+ {
+ m_flags &= ~e_awakeFlag;
+ m_sleepTime = 0.0f;
+ m_linearVelocity.SetZero();
+ m_angularVelocity = 0.0f;
+ m_force.SetZero();
+ m_torque = 0.0f;
+ }
+}
+
+inline bool b2Body::IsAwake() const
+{
+ return (m_flags & e_awakeFlag) == e_awakeFlag;
+}
+
+inline bool b2Body::IsEnabled() const
+{
+ return (m_flags & e_enabledFlag) == e_enabledFlag;
+}
+
+inline bool b2Body::IsFixedRotation() const
+{
+ return (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag;
+}
+
+inline void b2Body::SetSleepingAllowed(bool flag)
+{
+ if (flag)
+ {
+ m_flags |= e_autoSleepFlag;
+ }
+ else
+ {
+ m_flags &= ~e_autoSleepFlag;
+ SetAwake(true);
+ }
+}
+
+inline bool b2Body::IsSleepingAllowed() const
+{
+ return (m_flags & e_autoSleepFlag) == e_autoSleepFlag;
+}
+
+inline b2Fixture* b2Body::GetFixtureList()
+{
+ return m_fixtureList;
+}
+
+inline const b2Fixture* b2Body::GetFixtureList() const
+{
+ return m_fixtureList;
+}
+
+inline b2JointEdge* b2Body::GetJointList()
+{
+ return m_jointList;
+}
+
+inline const b2JointEdge* b2Body::GetJointList() const
+{
+ return m_jointList;
+}
+
+inline b2ContactEdge* b2Body::GetContactList()
+{
+ return m_contactList;
+}
+
+inline const b2ContactEdge* b2Body::GetContactList() const
+{
+ return m_contactList;
+}
+
+inline b2Body* b2Body::GetNext()
+{
+ return m_next;
+}
+
+inline const b2Body* b2Body::GetNext() const
+{
+ return m_next;
+}
+
+inline b2BodyUserData& b2Body::GetUserData()
+{
+ return m_userData;
+}
+
+inline void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake)
+{
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ if (wake && (m_flags & e_awakeFlag) == 0)
+ {
+ SetAwake(true);
+ }
+
+ // Don't accumulate a force if the body is sleeping.
+ if (m_flags & e_awakeFlag)
+ {
+ m_force += force;
+ m_torque += b2Cross(point - m_sweep.c, force);
+ }
+}
+
+inline void b2Body::ApplyForceToCenter(const b2Vec2& force, bool wake)
+{
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ if (wake && (m_flags & e_awakeFlag) == 0)
+ {
+ SetAwake(true);
+ }
+
+ // Don't accumulate a force if the body is sleeping
+ if (m_flags & e_awakeFlag)
+ {
+ m_force += force;
+ }
+}
+
+inline void b2Body::ApplyTorque(float torque, bool wake)
+{
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ if (wake && (m_flags & e_awakeFlag) == 0)
+ {
+ SetAwake(true);
+ }
+
+ // Don't accumulate a force if the body is sleeping
+ if (m_flags & e_awakeFlag)
+ {
+ m_torque += torque;
+ }
+}
+
+inline void b2Body::ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point, bool wake)
+{
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ if (wake && (m_flags & e_awakeFlag) == 0)
+ {
+ SetAwake(true);
+ }
+
+ // Don't accumulate velocity if the body is sleeping
+ if (m_flags & e_awakeFlag)
+ {
+ m_linearVelocity += m_invMass * impulse;
+ m_angularVelocity += m_invI * b2Cross(point - m_sweep.c, impulse);
+ }
+}
+
+inline void b2Body::ApplyLinearImpulseToCenter(const b2Vec2& impulse, bool wake)
+{
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ if (wake && (m_flags & e_awakeFlag) == 0)
+ {
+ SetAwake(true);
+ }
+
+ // Don't accumulate velocity if the body is sleeping
+ if (m_flags & e_awakeFlag)
+ {
+ m_linearVelocity += m_invMass * impulse;
+ }
+}
+
+inline void b2Body::ApplyAngularImpulse(float impulse, bool wake)
+{
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ if (wake && (m_flags & e_awakeFlag) == 0)
+ {
+ SetAwake(true);
+ }
+
+ // Don't accumulate velocity if the body is sleeping
+ if (m_flags & e_awakeFlag)
+ {
+ m_angularVelocity += m_invI * impulse;
+ }
+}
+
+inline void b2Body::SynchronizeTransform()
+{
+ m_xf.q.Set(m_sweep.a);
+ m_xf.p = m_sweep.c - b2Mul(m_xf.q, m_sweep.localCenter);
+}
+
+inline void b2Body::Advance(float alpha)
+{
+ // Advance to the new safe time. This doesn't sync the broad-phase.
+ m_sweep.Advance(alpha);
+ m_sweep.c = m_sweep.c0;
+ m_sweep.a = m_sweep.a0;
+ m_xf.q.Set(m_sweep.a);
+ m_xf.p = m_sweep.c - b2Mul(m_xf.q, m_sweep.localCenter);
+}
+
+inline b2World* b2Body::GetWorld()
+{
+ return m_world;
+}
+
+inline const b2World* b2Body::GetWorld() const
+{
+ return m_world;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_broad_phase.h b/Client/ThirdParty/Box2D/include/box2d/b2_broad_phase.h
new file mode 100644
index 0000000..cc882ab
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_broad_phase.h
@@ -0,0 +1,238 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_BROAD_PHASE_H
+#define B2_BROAD_PHASE_H
+
+#include "b2_api.h"
+#include "b2_settings.h"
+#include "b2_collision.h"
+#include "b2_dynamic_tree.h"
+
+struct B2_API b2Pair
+{
+ int32 proxyIdA;
+ int32 proxyIdB;
+};
+
+/// The broad-phase is used for computing pairs and performing volume queries and ray casts.
+/// This broad-phase does not persist pairs. Instead, this reports potentially new pairs.
+/// It is up to the client to consume the new pairs and to track subsequent overlap.
+class B2_API b2BroadPhase
+{
+public:
+
+ enum
+ {
+ e_nullProxy = -1
+ };
+
+ b2BroadPhase();
+ ~b2BroadPhase();
+
+ /// Create a proxy with an initial AABB. Pairs are not reported until
+ /// UpdatePairs is called.
+ int32 CreateProxy(const b2AABB& aabb, void* userData);
+
+ /// Destroy a proxy. It is up to the client to remove any pairs.
+ void DestroyProxy(int32 proxyId);
+
+ /// Call MoveProxy as many times as you like, then when you are done
+ /// call UpdatePairs to finalized the proxy pairs (for your time step).
+ void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement);
+
+ /// Call to trigger a re-processing of it's pairs on the next call to UpdatePairs.
+ void TouchProxy(int32 proxyId);
+
+ /// Get the fat AABB for a proxy.
+ const b2AABB& GetFatAABB(int32 proxyId) const;
+
+ /// Get user data from a proxy. Returns nullptr if the id is invalid.
+ void* GetUserData(int32 proxyId) const;
+
+ /// Test overlap of fat AABBs.
+ bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const;
+
+ /// Get the number of proxies.
+ int32 GetProxyCount() const;
+
+ /// Update the pairs. This results in pair callbacks. This can only add pairs.
+ template <typename T>
+ void UpdatePairs(T* callback);
+
+ /// Query an AABB for overlapping proxies. The callback class
+ /// is called for each proxy that overlaps the supplied AABB.
+ template <typename T>
+ void Query(T* callback, const b2AABB& aabb) const;
+
+ /// Ray-cast against the proxies in the tree. This relies on the callback
+ /// to perform a exact ray-cast in the case were the proxy contains a shape.
+ /// The callback also performs the any collision filtering. This has performance
+ /// roughly equal to k * log(n), where k is the number of collisions and n is the
+ /// number of proxies in the tree.
+ /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
+ /// @param callback a callback class that is called for each proxy that is hit by the ray.
+ template <typename T>
+ void RayCast(T* callback, const b2RayCastInput& input) const;
+
+ /// Get the height of the embedded tree.
+ int32 GetTreeHeight() const;
+
+ /// Get the balance of the embedded tree.
+ int32 GetTreeBalance() const;
+
+ /// Get the quality metric of the embedded tree.
+ float GetTreeQuality() const;
+
+ /// Shift the world origin. Useful for large worlds.
+ /// The shift formula is: position -= newOrigin
+ /// @param newOrigin the new origin with respect to the old origin
+ void ShiftOrigin(const b2Vec2& newOrigin);
+
+private:
+
+ friend class b2DynamicTree;
+
+ void BufferMove(int32 proxyId);
+ void UnBufferMove(int32 proxyId);
+
+ bool QueryCallback(int32 proxyId);
+
+ b2DynamicTree m_tree;
+
+ int32 m_proxyCount;
+
+ int32* m_moveBuffer;
+ int32 m_moveCapacity;
+ int32 m_moveCount;
+
+ b2Pair* m_pairBuffer;
+ int32 m_pairCapacity;
+ int32 m_pairCount;
+
+ int32 m_queryProxyId;
+};
+
+inline void* b2BroadPhase::GetUserData(int32 proxyId) const
+{
+ return m_tree.GetUserData(proxyId);
+}
+
+inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const
+{
+ const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA);
+ const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB);
+ return b2TestOverlap(aabbA, aabbB);
+}
+
+inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const
+{
+ return m_tree.GetFatAABB(proxyId);
+}
+
+inline int32 b2BroadPhase::GetProxyCount() const
+{
+ return m_proxyCount;
+}
+
+inline int32 b2BroadPhase::GetTreeHeight() const
+{
+ return m_tree.GetHeight();
+}
+
+inline int32 b2BroadPhase::GetTreeBalance() const
+{
+ return m_tree.GetMaxBalance();
+}
+
+inline float b2BroadPhase::GetTreeQuality() const
+{
+ return m_tree.GetAreaRatio();
+}
+
+template <typename T>
+void b2BroadPhase::UpdatePairs(T* callback)
+{
+ // Reset pair buffer
+ m_pairCount = 0;
+
+ // Perform tree queries for all moving proxies.
+ for (int32 i = 0; i < m_moveCount; ++i)
+ {
+ m_queryProxyId = m_moveBuffer[i];
+ if (m_queryProxyId == e_nullProxy)
+ {
+ continue;
+ }
+
+ // We have to query the tree with the fat AABB so that
+ // we don't fail to create a pair that may touch later.
+ const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId);
+
+ // Query tree, create pairs and add them pair buffer.
+ m_tree.Query(this, fatAABB);
+ }
+
+ // Send pairs to caller
+ for (int32 i = 0; i < m_pairCount; ++i)
+ {
+ b2Pair* primaryPair = m_pairBuffer + i;
+ void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA);
+ void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB);
+
+ callback->AddPair(userDataA, userDataB);
+ }
+
+ // Clear move flags
+ for (int32 i = 0; i < m_moveCount; ++i)
+ {
+ int32 proxyId = m_moveBuffer[i];
+ if (proxyId == e_nullProxy)
+ {
+ continue;
+ }
+
+ m_tree.ClearMoved(proxyId);
+ }
+
+ // Reset move buffer
+ m_moveCount = 0;
+}
+
+template <typename T>
+inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const
+{
+ m_tree.Query(callback, aabb);
+}
+
+template <typename T>
+inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const
+{
+ m_tree.RayCast(callback, input);
+}
+
+inline void b2BroadPhase::ShiftOrigin(const b2Vec2& newOrigin)
+{
+ m_tree.ShiftOrigin(newOrigin);
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_chain_shape.h b/Client/ThirdParty/Box2D/include/box2d/b2_chain_shape.h
new file mode 100644
index 0000000..da2605d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_chain_shape.h
@@ -0,0 +1,101 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CHAIN_SHAPE_H
+#define B2_CHAIN_SHAPE_H
+
+#include "b2_api.h"
+#include "b2_shape.h"
+
+class b2EdgeShape;
+
+/// A chain shape is a free form sequence of line segments.
+/// The chain has one-sided collision, with the surface normal pointing to the right of the edge.
+/// This provides a counter-clockwise winding like the polygon shape.
+/// Connectivity information is used to create smooth collisions.
+/// @warning the chain will not collide properly if there are self-intersections.
+class B2_API b2ChainShape : public b2Shape
+{
+public:
+ b2ChainShape();
+
+ /// The destructor frees the vertices using b2Free.
+ ~b2ChainShape();
+
+ /// Clear all data.
+ void Clear();
+
+ /// Create a loop. This automatically adjusts connectivity.
+ /// @param vertices an array of vertices, these are copied
+ /// @param count the vertex count
+ void CreateLoop(const b2Vec2* vertices, int32 count);
+
+ /// Create a chain with ghost vertices to connect multiple chains together.
+ /// @param vertices an array of vertices, these are copied
+ /// @param count the vertex count
+ /// @param prevVertex previous vertex from chain that connects to the start
+ /// @param nextVertex next vertex from chain that connects to the end
+ void CreateChain(const b2Vec2* vertices, int32 count,
+ const b2Vec2& prevVertex, const b2Vec2& nextVertex);
+
+ /// Implement b2Shape. Vertices are cloned using b2Alloc.
+ b2Shape* Clone(b2BlockAllocator* allocator) const override;
+
+ /// @see b2Shape::GetChildCount
+ int32 GetChildCount() const override;
+
+ /// Get a child edge.
+ void GetChildEdge(b2EdgeShape* edge, int32 index) const;
+
+ /// This always return false.
+ /// @see b2Shape::TestPoint
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override;
+
+ /// Implement b2Shape.
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeAABB
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override;
+
+ /// Chains have zero mass.
+ /// @see b2Shape::ComputeMass
+ void ComputeMass(b2MassData* massData, float density) const override;
+
+ /// The vertices. Owned by this class.
+ b2Vec2* m_vertices;
+
+ /// The vertex count.
+ int32 m_count;
+
+ b2Vec2 m_prevVertex, m_nextVertex;
+};
+
+inline b2ChainShape::b2ChainShape()
+{
+ m_type = e_chain;
+ m_radius = b2_polygonRadius;
+ m_vertices = nullptr;
+ m_count = 0;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_circle_shape.h b/Client/ThirdParty/Box2D/include/box2d/b2_circle_shape.h
new file mode 100644
index 0000000..5e330f5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_circle_shape.h
@@ -0,0 +1,67 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CIRCLE_SHAPE_H
+#define B2_CIRCLE_SHAPE_H
+
+#include "b2_api.h"
+#include "b2_shape.h"
+
+/// A solid circle shape
+class B2_API b2CircleShape : public b2Shape
+{
+public:
+ b2CircleShape();
+
+ /// Implement b2Shape.
+ b2Shape* Clone(b2BlockAllocator* allocator) const override;
+
+ /// @see b2Shape::GetChildCount
+ int32 GetChildCount() const override;
+
+ /// Implement b2Shape.
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override;
+
+ /// Implement b2Shape.
+ /// @note because the circle is solid, rays that start inside do not hit because the normal is
+ /// not defined.
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeAABB
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeMass
+ void ComputeMass(b2MassData* massData, float density) const override;
+
+ /// Position
+ b2Vec2 m_p;
+};
+
+inline b2CircleShape::b2CircleShape()
+{
+ m_type = e_circle;
+ m_radius = 0.0f;
+ m_p.SetZero();
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_collision.h b/Client/ThirdParty/Box2D/include/box2d/b2_collision.h
new file mode 100644
index 0000000..4c45920
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_collision.h
@@ -0,0 +1,283 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_COLLISION_H
+#define B2_COLLISION_H
+
+#include <limits.h>
+
+#include "b2_api.h"
+#include "b2_math.h"
+
+/// @file
+/// Structures and functions used for computing contact points, distance
+/// queries, and TOI queries.
+
+class b2Shape;
+class b2CircleShape;
+class b2EdgeShape;
+class b2PolygonShape;
+
+const uint8 b2_nullFeature = UCHAR_MAX;
+
+/// The features that intersect to form the contact point
+/// This must be 4 bytes or less.
+struct B2_API b2ContactFeature
+{
+ enum Type
+ {
+ e_vertex = 0,
+ e_face = 1
+ };
+
+ uint8 indexA; ///< Feature index on shapeA
+ uint8 indexB; ///< Feature index on shapeB
+ uint8 typeA; ///< The feature type on shapeA
+ uint8 typeB; ///< The feature type on shapeB
+};
+
+/// Contact ids to facilitate warm starting.
+union B2_API b2ContactID
+{
+ b2ContactFeature cf;
+ uint32 key; ///< Used to quickly compare contact ids.
+};
+
+/// A manifold point is a contact point belonging to a contact
+/// manifold. It holds details related to the geometry and dynamics
+/// of the contact points.
+/// The local point usage depends on the manifold type:
+/// -e_circles: the local center of circleB
+/// -e_faceA: the local center of cirlceB or the clip point of polygonB
+/// -e_faceB: the clip point of polygonA
+/// This structure is stored across time steps, so we keep it small.
+/// Note: the impulses are used for internal caching and may not
+/// provide reliable contact forces, especially for high speed collisions.
+struct B2_API b2ManifoldPoint
+{
+ b2Vec2 localPoint; ///< usage depends on manifold type
+ float normalImpulse; ///< the non-penetration impulse
+ float tangentImpulse; ///< the friction impulse
+ b2ContactID id; ///< uniquely identifies a contact point between two shapes
+};
+
+/// A manifold for two touching convex shapes.
+/// Box2D supports multiple types of contact:
+/// - clip point versus plane with radius
+/// - point versus point with radius (circles)
+/// The local point usage depends on the manifold type:
+/// -e_circles: the local center of circleA
+/// -e_faceA: the center of faceA
+/// -e_faceB: the center of faceB
+/// Similarly the local normal usage:
+/// -e_circles: not used
+/// -e_faceA: the normal on polygonA
+/// -e_faceB: the normal on polygonB
+/// We store contacts in this way so that position correction can
+/// account for movement, which is critical for continuous physics.
+/// All contact scenarios must be expressed in one of these types.
+/// This structure is stored across time steps, so we keep it small.
+struct B2_API b2Manifold
+{
+ enum Type
+ {
+ e_circles,
+ e_faceA,
+ e_faceB
+ };
+
+ b2ManifoldPoint points[b2_maxManifoldPoints]; ///< the points of contact
+ b2Vec2 localNormal; ///< not use for Type::e_points
+ b2Vec2 localPoint; ///< usage depends on manifold type
+ Type type;
+ int32 pointCount; ///< the number of manifold points
+};
+
+/// This is used to compute the current state of a contact manifold.
+struct B2_API b2WorldManifold
+{
+ /// Evaluate the manifold with supplied transforms. This assumes
+ /// modest motion from the original state. This does not change the
+ /// point count, impulses, etc. The radii must come from the shapes
+ /// that generated the manifold.
+ void Initialize(const b2Manifold* manifold,
+ const b2Transform& xfA, float radiusA,
+ const b2Transform& xfB, float radiusB);
+
+ b2Vec2 normal; ///< world vector pointing from A to B
+ b2Vec2 points[b2_maxManifoldPoints]; ///< world contact point (point of intersection)
+ float separations[b2_maxManifoldPoints]; ///< a negative value indicates overlap, in meters
+};
+
+/// This is used for determining the state of contact points.
+enum b2PointState
+{
+ b2_nullState, ///< point does not exist
+ b2_addState, ///< point was added in the update
+ b2_persistState, ///< point persisted across the update
+ b2_removeState ///< point was removed in the update
+};
+
+/// Compute the point states given two manifolds. The states pertain to the transition from manifold1
+/// to manifold2. So state1 is either persist or remove while state2 is either add or persist.
+B2_API void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],
+ const b2Manifold* manifold1, const b2Manifold* manifold2);
+
+/// Used for computing contact manifolds.
+struct B2_API b2ClipVertex
+{
+ b2Vec2 v;
+ b2ContactID id;
+};
+
+/// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
+struct B2_API b2RayCastInput
+{
+ b2Vec2 p1, p2;
+ float maxFraction;
+};
+
+/// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2
+/// come from b2RayCastInput.
+struct B2_API b2RayCastOutput
+{
+ b2Vec2 normal;
+ float fraction;
+};
+
+/// An axis aligned bounding box.
+struct B2_API b2AABB
+{
+ /// Verify that the bounds are sorted.
+ bool IsValid() const;
+
+ /// Get the center of the AABB.
+ b2Vec2 GetCenter() const
+ {
+ return 0.5f * (lowerBound + upperBound);
+ }
+
+ /// Get the extents of the AABB (half-widths).
+ b2Vec2 GetExtents() const
+ {
+ return 0.5f * (upperBound - lowerBound);
+ }
+
+ /// Get the perimeter length
+ float GetPerimeter() const
+ {
+ float wx = upperBound.x - lowerBound.x;
+ float wy = upperBound.y - lowerBound.y;
+ return 2.0f * (wx + wy);
+ }
+
+ /// Combine an AABB into this one.
+ void Combine(const b2AABB& aabb)
+ {
+ lowerBound = b2Min(lowerBound, aabb.lowerBound);
+ upperBound = b2Max(upperBound, aabb.upperBound);
+ }
+
+ /// Combine two AABBs into this one.
+ void Combine(const b2AABB& aabb1, const b2AABB& aabb2)
+ {
+ lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound);
+ upperBound = b2Max(aabb1.upperBound, aabb2.upperBound);
+ }
+
+ /// Does this aabb contain the provided AABB.
+ bool Contains(const b2AABB& aabb) const
+ {
+ bool result = true;
+ result = result && lowerBound.x <= aabb.lowerBound.x;
+ result = result && lowerBound.y <= aabb.lowerBound.y;
+ result = result && aabb.upperBound.x <= upperBound.x;
+ result = result && aabb.upperBound.y <= upperBound.y;
+ return result;
+ }
+
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const;
+
+ b2Vec2 lowerBound; ///< the lower vertex
+ b2Vec2 upperBound; ///< the upper vertex
+};
+
+/// Compute the collision manifold between two circles.
+B2_API void b2CollideCircles(b2Manifold* manifold,
+ const b2CircleShape* circleA, const b2Transform& xfA,
+ const b2CircleShape* circleB, const b2Transform& xfB);
+
+/// Compute the collision manifold between a polygon and a circle.
+B2_API void b2CollidePolygonAndCircle(b2Manifold* manifold,
+ const b2PolygonShape* polygonA, const b2Transform& xfA,
+ const b2CircleShape* circleB, const b2Transform& xfB);
+
+/// Compute the collision manifold between two polygons.
+B2_API void b2CollidePolygons(b2Manifold* manifold,
+ const b2PolygonShape* polygonA, const b2Transform& xfA,
+ const b2PolygonShape* polygonB, const b2Transform& xfB);
+
+/// Compute the collision manifold between an edge and a circle.
+B2_API void b2CollideEdgeAndCircle(b2Manifold* manifold,
+ const b2EdgeShape* polygonA, const b2Transform& xfA,
+ const b2CircleShape* circleB, const b2Transform& xfB);
+
+/// Compute the collision manifold between an edge and a polygon.
+B2_API void b2CollideEdgeAndPolygon(b2Manifold* manifold,
+ const b2EdgeShape* edgeA, const b2Transform& xfA,
+ const b2PolygonShape* circleB, const b2Transform& xfB);
+
+/// Clipping for contact manifolds.
+B2_API int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],
+ const b2Vec2& normal, float offset, int32 vertexIndexA);
+
+/// Determine if two generic shapes overlap.
+B2_API bool b2TestOverlap( const b2Shape* shapeA, int32 indexA,
+ const b2Shape* shapeB, int32 indexB,
+ const b2Transform& xfA, const b2Transform& xfB);
+
+// ---------------- Inline Functions ------------------------------------------
+
+inline bool b2AABB::IsValid() const
+{
+ b2Vec2 d = upperBound - lowerBound;
+ bool valid = d.x >= 0.0f && d.y >= 0.0f;
+ valid = valid && lowerBound.IsValid() && upperBound.IsValid();
+ return valid;
+}
+
+inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b)
+{
+ b2Vec2 d1, d2;
+ d1 = b.lowerBound - a.upperBound;
+ d2 = a.lowerBound - b.upperBound;
+
+ if (d1.x > 0.0f || d1.y > 0.0f)
+ return false;
+
+ if (d2.x > 0.0f || d2.y > 0.0f)
+ return false;
+
+ return true;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_common.h b/Client/ThirdParty/Box2D/include/box2d/b2_common.h
new file mode 100644
index 0000000..dfca8af
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_common.h
@@ -0,0 +1,138 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_COMMON_H
+#define B2_COMMON_H
+
+#include "b2_settings.h"
+
+#include <stddef.h>
+#include <assert.h>
+#include <float.h>
+
+#if !defined(NDEBUG)
+ #define b2DEBUG
+#endif
+
+#define B2_NOT_USED(x) ((void)(x))
+#define b2Assert(A) assert(A)
+
+#define b2_maxFloat FLT_MAX
+#define b2_epsilon FLT_EPSILON
+#define b2_pi 3.14159265359f
+
+/// @file
+/// Global tuning constants based on meters-kilograms-seconds (MKS) units.
+///
+
+// Collision
+
+/// The maximum number of contact points between two convex shapes. Do
+/// not change this value.
+#define b2_maxManifoldPoints 2
+
+/// This is used to fatten AABBs in the dynamic tree. This allows proxies
+/// to move by a small amount without triggering a tree adjustment.
+/// This is in meters.
+#define b2_aabbExtension (0.1f * b2_lengthUnitsPerMeter)
+
+/// This is used to fatten AABBs in the dynamic tree. This is used to predict
+/// the future position based on the current displacement.
+/// This is a dimensionless multiplier.
+#define b2_aabbMultiplier 4.0f
+
+/// A small length used as a collision and constraint tolerance. Usually it is
+/// chosen to be numerically significant, but visually insignificant. In meters.
+#define b2_linearSlop (0.005f * b2_lengthUnitsPerMeter)
+
+/// A small angle used as a collision and constraint tolerance. Usually it is
+/// chosen to be numerically significant, but visually insignificant.
+#define b2_angularSlop (2.0f / 180.0f * b2_pi)
+
+/// The radius of the polygon/edge shape skin. This should not be modified. Making
+/// this smaller means polygons will have an insufficient buffer for continuous collision.
+/// Making it larger may create artifacts for vertex collision.
+#define b2_polygonRadius (2.0f * b2_linearSlop)
+
+/// Maximum number of sub-steps per contact in continuous physics simulation.
+#define b2_maxSubSteps 8
+
+
+// Dynamics
+
+/// Maximum number of contacts to be handled to solve a TOI impact.
+#define b2_maxTOIContacts 32
+
+/// The maximum linear position correction used when solving constraints. This helps to
+/// prevent overshoot. Meters.
+#define b2_maxLinearCorrection (0.2f * b2_lengthUnitsPerMeter)
+
+/// The maximum angular position correction used when solving constraints. This helps to
+/// prevent overshoot.
+#define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi)
+
+/// The maximum linear translation of a body per step. This limit is very large and is used
+/// to prevent numerical problems. You shouldn't need to adjust this. Meters.
+#define b2_maxTranslation (2.0f * b2_lengthUnitsPerMeter)
+#define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation)
+
+/// The maximum angular velocity of a body. This limit is very large and is used
+/// to prevent numerical problems. You shouldn't need to adjust this.
+#define b2_maxRotation (0.5f * b2_pi)
+#define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation)
+
+/// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so
+/// that overlap is removed in one time step. However using values close to 1 often lead
+/// to overshoot.
+#define b2_baumgarte 0.2f
+#define b2_toiBaumgarte 0.75f
+
+
+// Sleep
+
+/// The time that a body must be still before it will go to sleep.
+#define b2_timeToSleep 0.5f
+
+/// A body cannot sleep if its linear velocity is above this tolerance.
+#define b2_linearSleepTolerance (0.01f * b2_lengthUnitsPerMeter)
+
+/// A body cannot sleep if its angular velocity is above this tolerance.
+#define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi)
+
+/// Dump to a file. Only one dump file allowed at a time.
+void b2OpenDump(const char* fileName);
+void b2Dump(const char* string, ...);
+void b2CloseDump();
+
+/// Version numbering scheme.
+/// See http://en.wikipedia.org/wiki/Software_versioning
+struct b2Version
+{
+ int32 major; ///< significant changes
+ int32 minor; ///< incremental changes
+ int32 revision; ///< bug fixes
+};
+
+/// Current version.
+extern B2_API b2Version b2_version;
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_contact.h b/Client/ThirdParty/Box2D/include/box2d/b2_contact.h
new file mode 100644
index 0000000..de7541f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_contact.h
@@ -0,0 +1,386 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CONTACT_H
+#define B2_CONTACT_H
+
+#include "b2_api.h"
+#include "b2_collision.h"
+#include "b2_fixture.h"
+#include "b2_math.h"
+#include "b2_shape.h"
+
+class b2Body;
+class b2Contact;
+class b2Fixture;
+class b2World;
+class b2BlockAllocator;
+class b2StackAllocator;
+class b2ContactListener;
+
+/// Friction mixing law. The idea is to allow either fixture to drive the friction to zero.
+/// For example, anything slides on ice.
+inline float b2MixFriction(float friction1, float friction2)
+{
+ return b2Sqrt(friction1 * friction2);
+}
+
+/// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
+/// For example, a superball bounces on anything.
+inline float b2MixRestitution(float restitution1, float restitution2)
+{
+ return restitution1 > restitution2 ? restitution1 : restitution2;
+}
+
+/// Restitution mixing law. This picks the lowest value.
+inline float b2MixRestitutionThreshold(float threshold1, float threshold2)
+{
+ return threshold1 < threshold2 ? threshold1 : threshold2;
+}
+
+typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB,
+ b2BlockAllocator* allocator);
+typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
+
+struct B2_API b2ContactRegister
+{
+ b2ContactCreateFcn* createFcn;
+ b2ContactDestroyFcn* destroyFcn;
+ bool primary;
+};
+
+/// A contact edge is used to connect bodies and contacts together
+/// in a contact graph where each body is a node and each contact
+/// is an edge. A contact edge belongs to a doubly linked list
+/// maintained in each attached body. Each contact has two contact
+/// nodes, one for each attached body.
+struct B2_API b2ContactEdge
+{
+ b2Body* other; ///< provides quick access to the other body attached.
+ b2Contact* contact; ///< the contact
+ b2ContactEdge* prev; ///< the previous contact edge in the body's contact list
+ b2ContactEdge* next; ///< the next contact edge in the body's contact list
+};
+
+/// The class manages contact between two shapes. A contact exists for each overlapping
+/// AABB in the broad-phase (except if filtered). Therefore a contact object may exist
+/// that has no contact points.
+class B2_API b2Contact
+{
+public:
+
+ /// Get the contact manifold. Do not modify the manifold unless you understand the
+ /// internals of Box2D.
+ b2Manifold* GetManifold();
+ const b2Manifold* GetManifold() const;
+
+ /// Get the world manifold.
+ void GetWorldManifold(b2WorldManifold* worldManifold) const;
+
+ /// Is this contact touching?
+ bool IsTouching() const;
+
+ /// Enable/disable this contact. This can be used inside the pre-solve
+ /// contact listener. The contact is only disabled for the current
+ /// time step (or sub-step in continuous collisions).
+ void SetEnabled(bool flag);
+
+ /// Has this contact been disabled?
+ bool IsEnabled() const;
+
+ /// Get the next contact in the world's contact list.
+ b2Contact* GetNext();
+ const b2Contact* GetNext() const;
+
+ /// Get fixture A in this contact.
+ b2Fixture* GetFixtureA();
+ const b2Fixture* GetFixtureA() const;
+
+ /// Get the child primitive index for fixture A.
+ int32 GetChildIndexA() const;
+
+ /// Get fixture B in this contact.
+ b2Fixture* GetFixtureB();
+ const b2Fixture* GetFixtureB() const;
+
+ /// Get the child primitive index for fixture B.
+ int32 GetChildIndexB() const;
+
+ /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve.
+ /// This value persists until set or reset.
+ void SetFriction(float friction);
+
+ /// Get the friction.
+ float GetFriction() const;
+
+ /// Reset the friction mixture to the default value.
+ void ResetFriction();
+
+ /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve.
+ /// The value persists until you set or reset.
+ void SetRestitution(float restitution);
+
+ /// Get the restitution.
+ float GetRestitution() const;
+
+ /// Reset the restitution to the default value.
+ void ResetRestitution();
+
+ /// Override the default restitution velocity threshold mixture. You can call this in b2ContactListener::PreSolve.
+ /// The value persists until you set or reset.
+ void SetRestitutionThreshold(float threshold);
+
+ /// Get the restitution threshold.
+ float GetRestitutionThreshold() const;
+
+ /// Reset the restitution threshold to the default value.
+ void ResetRestitutionThreshold();
+
+ /// Set the desired tangent speed for a conveyor belt behavior. In meters per second.
+ void SetTangentSpeed(float speed);
+
+ /// Get the desired tangent speed. In meters per second.
+ float GetTangentSpeed() const;
+
+ /// Evaluate this contact with your own manifold and transforms.
+ virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0;
+
+protected:
+ friend class b2ContactManager;
+ friend class b2World;
+ friend class b2ContactSolver;
+ friend class b2Body;
+ friend class b2Fixture;
+
+ // Flags stored in m_flags
+ enum
+ {
+ // Used when crawling contact graph when forming islands.
+ e_islandFlag = 0x0001,
+
+ // Set when the shapes are touching.
+ e_touchingFlag = 0x0002,
+
+ // This contact can be disabled (by user)
+ e_enabledFlag = 0x0004,
+
+ // This contact needs filtering because a fixture filter was changed.
+ e_filterFlag = 0x0008,
+
+ // This bullet contact had a TOI event
+ e_bulletHitFlag = 0x0010,
+
+ // This contact has a valid TOI in m_toi
+ e_toiFlag = 0x0020
+ };
+
+ /// Flag this contact for filtering. Filtering will occur the next time step.
+ void FlagForFiltering();
+
+ static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn,
+ b2Shape::Type typeA, b2Shape::Type typeB);
+ static void InitializeRegisters();
+ static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2Contact() : m_fixtureA(nullptr), m_fixtureB(nullptr) {}
+ b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
+ virtual ~b2Contact() {}
+
+ void Update(b2ContactListener* listener);
+
+ static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];
+ static bool s_initialized;
+
+ uint32 m_flags;
+
+ // World pool and list pointers.
+ b2Contact* m_prev;
+ b2Contact* m_next;
+
+ // Nodes for connecting bodies.
+ b2ContactEdge m_nodeA;
+ b2ContactEdge m_nodeB;
+
+ b2Fixture* m_fixtureA;
+ b2Fixture* m_fixtureB;
+
+ int32 m_indexA;
+ int32 m_indexB;
+
+ b2Manifold m_manifold;
+
+ int32 m_toiCount;
+ float m_toi;
+
+ float m_friction;
+ float m_restitution;
+ float m_restitutionThreshold;
+
+ float m_tangentSpeed;
+};
+
+inline b2Manifold* b2Contact::GetManifold()
+{
+ return &m_manifold;
+}
+
+inline const b2Manifold* b2Contact::GetManifold() const
+{
+ return &m_manifold;
+}
+
+inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const
+{
+ const b2Body* bodyA = m_fixtureA->GetBody();
+ const b2Body* bodyB = m_fixtureB->GetBody();
+ const b2Shape* shapeA = m_fixtureA->GetShape();
+ const b2Shape* shapeB = m_fixtureB->GetShape();
+
+ worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius);
+}
+
+inline void b2Contact::SetEnabled(bool flag)
+{
+ if (flag)
+ {
+ m_flags |= e_enabledFlag;
+ }
+ else
+ {
+ m_flags &= ~e_enabledFlag;
+ }
+}
+
+inline bool b2Contact::IsEnabled() const
+{
+ return (m_flags & e_enabledFlag) == e_enabledFlag;
+}
+
+inline bool b2Contact::IsTouching() const
+{
+ return (m_flags & e_touchingFlag) == e_touchingFlag;
+}
+
+inline b2Contact* b2Contact::GetNext()
+{
+ return m_next;
+}
+
+inline const b2Contact* b2Contact::GetNext() const
+{
+ return m_next;
+}
+
+inline b2Fixture* b2Contact::GetFixtureA()
+{
+ return m_fixtureA;
+}
+
+inline const b2Fixture* b2Contact::GetFixtureA() const
+{
+ return m_fixtureA;
+}
+
+inline b2Fixture* b2Contact::GetFixtureB()
+{
+ return m_fixtureB;
+}
+
+inline int32 b2Contact::GetChildIndexA() const
+{
+ return m_indexA;
+}
+
+inline const b2Fixture* b2Contact::GetFixtureB() const
+{
+ return m_fixtureB;
+}
+
+inline int32 b2Contact::GetChildIndexB() const
+{
+ return m_indexB;
+}
+
+inline void b2Contact::FlagForFiltering()
+{
+ m_flags |= e_filterFlag;
+}
+
+inline void b2Contact::SetFriction(float friction)
+{
+ m_friction = friction;
+}
+
+inline float b2Contact::GetFriction() const
+{
+ return m_friction;
+}
+
+inline void b2Contact::ResetFriction()
+{
+ m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
+}
+
+inline void b2Contact::SetRestitution(float restitution)
+{
+ m_restitution = restitution;
+}
+
+inline float b2Contact::GetRestitution() const
+{
+ return m_restitution;
+}
+
+inline void b2Contact::ResetRestitution()
+{
+ m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
+}
+
+inline void b2Contact::SetRestitutionThreshold(float threshold)
+{
+ m_restitutionThreshold = threshold;
+}
+
+inline float b2Contact::GetRestitutionThreshold() const
+{
+ return m_restitutionThreshold;
+}
+
+inline void b2Contact::ResetRestitutionThreshold()
+{
+ m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold);
+}
+
+inline void b2Contact::SetTangentSpeed(float speed)
+{
+ m_tangentSpeed = speed;
+}
+
+inline float b2Contact::GetTangentSpeed() const
+{
+ return m_tangentSpeed;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_contact_manager.h b/Client/ThirdParty/Box2D/include/box2d/b2_contact_manager.h
new file mode 100644
index 0000000..fbd3b4d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_contact_manager.h
@@ -0,0 +1,57 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CONTACT_MANAGER_H
+#define B2_CONTACT_MANAGER_H
+
+#include "b2_api.h"
+#include "b2_broad_phase.h"
+
+class b2Contact;
+class b2ContactFilter;
+class b2ContactListener;
+class b2BlockAllocator;
+
+// Delegate of b2World.
+class B2_API b2ContactManager
+{
+public:
+ b2ContactManager();
+
+ // Broad-phase callback.
+ void AddPair(void* proxyUserDataA, void* proxyUserDataB);
+
+ void FindNewContacts();
+
+ void Destroy(b2Contact* c);
+
+ void Collide();
+
+ b2BroadPhase m_broadPhase;
+ b2Contact* m_contactList;
+ int32 m_contactCount;
+ b2ContactFilter* m_contactFilter;
+ b2ContactListener* m_contactListener;
+ b2BlockAllocator* m_allocator;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_distance.h b/Client/ThirdParty/Box2D/include/box2d/b2_distance.h
new file mode 100644
index 0000000..3e05773
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_distance.h
@@ -0,0 +1,171 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_DISTANCE_H
+#define B2_DISTANCE_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+
+class b2Shape;
+
+/// A distance proxy is used by the GJK algorithm.
+/// It encapsulates any shape.
+struct B2_API b2DistanceProxy
+{
+ b2DistanceProxy() : m_vertices(nullptr), m_count(0), m_radius(0.0f) {}
+
+ /// Initialize the proxy using the given shape. The shape
+ /// must remain in scope while the proxy is in use.
+ void Set(const b2Shape* shape, int32 index);
+
+ /// Initialize the proxy using a vertex cloud and radius. The vertices
+ /// must remain in scope while the proxy is in use.
+ void Set(const b2Vec2* vertices, int32 count, float radius);
+
+ /// Get the supporting vertex index in the given direction.
+ int32 GetSupport(const b2Vec2& d) const;
+
+ /// Get the supporting vertex in the given direction.
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;
+
+ /// Get the vertex count.
+ int32 GetVertexCount() const;
+
+ /// Get a vertex by index. Used by b2Distance.
+ const b2Vec2& GetVertex(int32 index) const;
+
+ b2Vec2 m_buffer[2];
+ const b2Vec2* m_vertices;
+ int32 m_count;
+ float m_radius;
+};
+
+/// Used to warm start b2Distance.
+/// Set count to zero on first call.
+struct B2_API b2SimplexCache
+{
+ float metric; ///< length or area
+ uint16 count;
+ uint8 indexA[3]; ///< vertices on shape A
+ uint8 indexB[3]; ///< vertices on shape B
+};
+
+/// Input for b2Distance.
+/// You have to option to use the shape radii
+/// in the computation. Even
+struct B2_API b2DistanceInput
+{
+ b2DistanceProxy proxyA;
+ b2DistanceProxy proxyB;
+ b2Transform transformA;
+ b2Transform transformB;
+ bool useRadii;
+};
+
+/// Output for b2Distance.
+struct B2_API b2DistanceOutput
+{
+ b2Vec2 pointA; ///< closest point on shapeA
+ b2Vec2 pointB; ///< closest point on shapeB
+ float distance;
+ int32 iterations; ///< number of GJK iterations used
+};
+
+/// Compute the closest points between two shapes. Supports any combination of:
+/// b2CircleShape, b2PolygonShape, b2EdgeShape. The simplex cache is input/output.
+/// On the first call set b2SimplexCache.count to zero.
+B2_API void b2Distance(b2DistanceOutput* output,
+ b2SimplexCache* cache,
+ const b2DistanceInput* input);
+
+/// Input parameters for b2ShapeCast
+struct B2_API b2ShapeCastInput
+{
+ b2DistanceProxy proxyA;
+ b2DistanceProxy proxyB;
+ b2Transform transformA;
+ b2Transform transformB;
+ b2Vec2 translationB;
+};
+
+/// Output results for b2ShapeCast
+struct B2_API b2ShapeCastOutput
+{
+ b2Vec2 point;
+ b2Vec2 normal;
+ float lambda;
+ int32 iterations;
+};
+
+/// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction.
+/// @returns true if hit, false if there is no hit or an initial overlap
+B2_API bool b2ShapeCast(b2ShapeCastOutput* output, const b2ShapeCastInput* input);
+
+//////////////////////////////////////////////////////////////////////////
+
+inline int32 b2DistanceProxy::GetVertexCount() const
+{
+ return m_count;
+}
+
+inline const b2Vec2& b2DistanceProxy::GetVertex(int32 index) const
+{
+ b2Assert(0 <= index && index < m_count);
+ return m_vertices[index];
+}
+
+inline int32 b2DistanceProxy::GetSupport(const b2Vec2& d) const
+{
+ int32 bestIndex = 0;
+ float bestValue = b2Dot(m_vertices[0], d);
+ for (int32 i = 1; i < m_count; ++i)
+ {
+ float value = b2Dot(m_vertices[i], d);
+ if (value > bestValue)
+ {
+ bestIndex = i;
+ bestValue = value;
+ }
+ }
+
+ return bestIndex;
+}
+
+inline const b2Vec2& b2DistanceProxy::GetSupportVertex(const b2Vec2& d) const
+{
+ int32 bestIndex = 0;
+ float bestValue = b2Dot(m_vertices[0], d);
+ for (int32 i = 1; i < m_count; ++i)
+ {
+ float value = b2Dot(m_vertices[i], d);
+ if (value > bestValue)
+ {
+ bestIndex = i;
+ bestValue = value;
+ }
+ }
+
+ return m_vertices[bestIndex];
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_distance_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_distance_joint.h
new file mode 100644
index 0000000..cfc75fe
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_distance_joint.h
@@ -0,0 +1,176 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_DISTANCE_JOINT_H
+#define B2_DISTANCE_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Distance joint definition. This requires defining an anchor point on both
+/// bodies and the non-zero distance of the distance joint. The definition uses
+/// local anchor points so that the initial configuration can violate the
+/// constraint slightly. This helps when saving and loading a game.
+struct B2_API b2DistanceJointDef : public b2JointDef
+{
+ b2DistanceJointDef()
+ {
+ type = e_distanceJoint;
+ localAnchorA.Set(0.0f, 0.0f);
+ localAnchorB.Set(0.0f, 0.0f);
+ length = 1.0f;
+ minLength = 0.0f;
+ maxLength = FLT_MAX;
+ stiffness = 0.0f;
+ damping = 0.0f;
+ }
+
+ /// Initialize the bodies, anchors, and rest length using world space anchors.
+ /// The minimum and maximum lengths are set to the rest length.
+ void Initialize(b2Body* bodyA, b2Body* bodyB,
+ const b2Vec2& anchorA, const b2Vec2& anchorB);
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The rest length of this joint. Clamped to a stable minimum value.
+ float length;
+
+ /// Minimum length. Clamped to a stable minimum value.
+ float minLength;
+
+ /// Maximum length. Must be greater than or equal to the minimum length.
+ float maxLength;
+
+ /// The linear stiffness in N/m.
+ float stiffness;
+
+ /// The linear damping in N*s/m.
+ float damping;
+};
+
+/// A distance joint constrains two points on two bodies to remain at a fixed
+/// distance from each other. You can view this as a massless, rigid rod.
+class B2_API b2DistanceJoint : public b2Joint
+{
+public:
+
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ /// Get the reaction force given the inverse time step.
+ /// Unit is N.
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+
+ /// Get the reaction torque given the inverse time step.
+ /// Unit is N*m. This is always zero for a distance joint.
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// The local anchor point relative to bodyA's origin.
+ const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; }
+
+ /// The local anchor point relative to bodyB's origin.
+ const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; }
+
+ /// Get the rest length
+ float GetLength() const { return m_length; }
+
+ /// Set the rest length
+ /// @returns clamped rest length
+ float SetLength(float length);
+
+ /// Get the minimum length
+ float GetMinLength() const { return m_minLength; }
+
+ /// Set the minimum length
+ /// @returns the clamped minimum length
+ float SetMinLength(float minLength);
+
+ /// Get the maximum length
+ float GetMaxLength() const { return m_maxLength; }
+
+ /// Set the maximum length
+ /// @returns the clamped maximum length
+ float SetMaxLength(float maxLength);
+
+ /// Get the current length
+ float GetCurrentLength() const;
+
+ /// Set/get the linear stiffness in N/m
+ void SetStiffness(float stiffness) { m_stiffness = stiffness; }
+ float GetStiffness() const { return m_stiffness; }
+
+ /// Set/get linear damping in N*s/m
+ void SetDamping(float damping) { m_damping = damping; }
+ float GetDamping() const { return m_damping; }
+
+ /// Dump joint to dmLog
+ void Dump() override;
+
+ ///
+ void Draw(b2Draw* draw) const override;
+
+protected:
+
+ friend class b2Joint;
+ b2DistanceJoint(const b2DistanceJointDef* data);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ float m_stiffness;
+ float m_damping;
+ float m_bias;
+ float m_length;
+ float m_minLength;
+ float m_maxLength;
+
+ // Solver shared
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ float m_gamma;
+ float m_impulse;
+ float m_lowerImpulse;
+ float m_upperImpulse;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_u;
+ b2Vec2 m_rA;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_currentLength;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ float m_softMass;
+ float m_mass;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_draw.h b/Client/ThirdParty/Box2D/include/box2d/b2_draw.h
new file mode 100644
index 0000000..a4d1711
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_draw.h
@@ -0,0 +1,102 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_DRAW_H
+#define B2_DRAW_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+
+/// Color for debug drawing. Each value has the range [0,1].
+struct B2_API b2Color
+{
+ b2Color() {}
+ b2Color(float rIn, float gIn, float bIn, float aIn = 1.0f)
+ {
+ r = rIn; g = gIn; b = bIn; a = aIn;
+ }
+
+ void Set(float rIn, float gIn, float bIn, float aIn = 1.0f)
+ {
+ r = rIn; g = gIn; b = bIn; a = aIn;
+ }
+
+ float r, g, b, a;
+};
+
+/// Implement and register this class with a b2World to provide debug drawing of physics
+/// entities in your game.
+class B2_API b2Draw
+{
+public:
+ b2Draw();
+
+ virtual ~b2Draw() {}
+
+ enum
+ {
+ e_shapeBit = 0x0001, ///< draw shapes
+ e_jointBit = 0x0002, ///< draw joint connections
+ e_aabbBit = 0x0004, ///< draw axis aligned bounding boxes
+ e_pairBit = 0x0008, ///< draw broad-phase pairs
+ e_centerOfMassBit = 0x0010 ///< draw center of mass frame
+ };
+
+ /// Set the drawing flags.
+ void SetFlags(uint32 flags);
+
+ /// Get the drawing flags.
+ uint32 GetFlags() const;
+
+ /// Append flags to the current flags.
+ void AppendFlags(uint32 flags);
+
+ /// Clear flags from the current flags.
+ void ClearFlags(uint32 flags);
+
+ /// Draw a closed polygon provided in CCW order.
+ virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0;
+
+ /// Draw a solid closed polygon provided in CCW order.
+ virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0;
+
+ /// Draw a circle.
+ virtual void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) = 0;
+
+ /// Draw a solid circle.
+ virtual void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) = 0;
+
+ /// Draw a line segment.
+ virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0;
+
+ /// Draw a transform. Choose your own length scale.
+ /// @param xf a transform.
+ virtual void DrawTransform(const b2Transform& xf) = 0;
+
+ /// Draw a point.
+ virtual void DrawPoint(const b2Vec2& p, float size, const b2Color& color) = 0;
+
+protected:
+ uint32 m_drawFlags;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_dynamic_tree.h b/Client/ThirdParty/Box2D/include/box2d/b2_dynamic_tree.h
new file mode 100644
index 0000000..b854919
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_dynamic_tree.h
@@ -0,0 +1,308 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_DYNAMIC_TREE_H
+#define B2_DYNAMIC_TREE_H
+
+#include "b2_api.h"
+#include "b2_collision.h"
+#include "b2_growable_stack.h"
+
+#define b2_nullNode (-1)
+
+/// A node in the dynamic tree. The client does not interact with this directly.
+struct B2_API b2TreeNode
+{
+ bool IsLeaf() const
+ {
+ return child1 == b2_nullNode;
+ }
+
+ /// Enlarged AABB
+ b2AABB aabb;
+
+ void* userData;
+
+ union
+ {
+ int32 parent;
+ int32 next;
+ };
+
+ int32 child1;
+ int32 child2;
+
+ // leaf = 0, free node = -1
+ int32 height;
+
+ bool moved;
+};
+
+/// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
+/// A dynamic tree arranges data in a binary tree to accelerate
+/// queries such as volume queries and ray casts. Leafs are proxies
+/// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor
+/// so that the proxy AABB is bigger than the client object. This allows the client
+/// object to move by small amounts without triggering a tree update.
+///
+/// Nodes are pooled and relocatable, so we use node indices rather than pointers.
+class B2_API b2DynamicTree
+{
+public:
+ /// Constructing the tree initializes the node pool.
+ b2DynamicTree();
+
+ /// Destroy the tree, freeing the node pool.
+ ~b2DynamicTree();
+
+ /// Create a proxy. Provide a tight fitting AABB and a userData pointer.
+ int32 CreateProxy(const b2AABB& aabb, void* userData);
+
+ /// Destroy a proxy. This asserts if the id is invalid.
+ void DestroyProxy(int32 proxyId);
+
+ /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB,
+ /// then the proxy is removed from the tree and re-inserted. Otherwise
+ /// the function returns immediately.
+ /// @return true if the proxy was re-inserted.
+ bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);
+
+ /// Get proxy user data.
+ /// @return the proxy user data or 0 if the id is invalid.
+ void* GetUserData(int32 proxyId) const;
+
+ bool WasMoved(int32 proxyId) const;
+ void ClearMoved(int32 proxyId);
+
+ /// Get the fat AABB for a proxy.
+ const b2AABB& GetFatAABB(int32 proxyId) const;
+
+ /// Query an AABB for overlapping proxies. The callback class
+ /// is called for each proxy that overlaps the supplied AABB.
+ template <typename T>
+ void Query(T* callback, const b2AABB& aabb) const;
+
+ /// Ray-cast against the proxies in the tree. This relies on the callback
+ /// to perform a exact ray-cast in the case were the proxy contains a shape.
+ /// The callback also performs the any collision filtering. This has performance
+ /// roughly equal to k * log(n), where k is the number of collisions and n is the
+ /// number of proxies in the tree.
+ /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
+ /// @param callback a callback class that is called for each proxy that is hit by the ray.
+ template <typename T>
+ void RayCast(T* callback, const b2RayCastInput& input) const;
+
+ /// Validate this tree. For testing.
+ void Validate() const;
+
+ /// Compute the height of the binary tree in O(N) time. Should not be
+ /// called often.
+ int32 GetHeight() const;
+
+ /// Get the maximum balance of an node in the tree. The balance is the difference
+ /// in height of the two children of a node.
+ int32 GetMaxBalance() const;
+
+ /// Get the ratio of the sum of the node areas to the root area.
+ float GetAreaRatio() const;
+
+ /// Build an optimal tree. Very expensive. For testing.
+ void RebuildBottomUp();
+
+ /// Shift the world origin. Useful for large worlds.
+ /// The shift formula is: position -= newOrigin
+ /// @param newOrigin the new origin with respect to the old origin
+ void ShiftOrigin(const b2Vec2& newOrigin);
+
+private:
+
+ int32 AllocateNode();
+ void FreeNode(int32 node);
+
+ void InsertLeaf(int32 node);
+ void RemoveLeaf(int32 node);
+
+ int32 Balance(int32 index);
+
+ int32 ComputeHeight() const;
+ int32 ComputeHeight(int32 nodeId) const;
+
+ void ValidateStructure(int32 index) const;
+ void ValidateMetrics(int32 index) const;
+
+ int32 m_root;
+
+ b2TreeNode* m_nodes;
+ int32 m_nodeCount;
+ int32 m_nodeCapacity;
+
+ int32 m_freeList;
+
+ int32 m_insertionCount;
+};
+
+inline void* b2DynamicTree::GetUserData(int32 proxyId) const
+{
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
+ return m_nodes[proxyId].userData;
+}
+
+inline bool b2DynamicTree::WasMoved(int32 proxyId) const
+{
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
+ return m_nodes[proxyId].moved;
+}
+
+inline void b2DynamicTree::ClearMoved(int32 proxyId)
+{
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
+ m_nodes[proxyId].moved = false;
+}
+
+inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const
+{
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
+ return m_nodes[proxyId].aabb;
+}
+
+template <typename T>
+inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
+{
+ b2GrowableStack<int32, 256> stack;
+ stack.Push(m_root);
+
+ while (stack.GetCount() > 0)
+ {
+ int32 nodeId = stack.Pop();
+ if (nodeId == b2_nullNode)
+ {
+ continue;
+ }
+
+ const b2TreeNode* node = m_nodes + nodeId;
+
+ if (b2TestOverlap(node->aabb, aabb))
+ {
+ if (node->IsLeaf())
+ {
+ bool proceed = callback->QueryCallback(nodeId);
+ if (proceed == false)
+ {
+ return;
+ }
+ }
+ else
+ {
+ stack.Push(node->child1);
+ stack.Push(node->child2);
+ }
+ }
+ }
+}
+
+template <typename T>
+inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
+{
+ b2Vec2 p1 = input.p1;
+ b2Vec2 p2 = input.p2;
+ b2Vec2 r = p2 - p1;
+ b2Assert(r.LengthSquared() > 0.0f);
+ r.Normalize();
+
+ // v is perpendicular to the segment.
+ b2Vec2 v = b2Cross(1.0f, r);
+ b2Vec2 abs_v = b2Abs(v);
+
+ // Separating axis for segment (Gino, p80).
+ // |dot(v, p1 - c)| > dot(|v|, h)
+
+ float maxFraction = input.maxFraction;
+
+ // Build a bounding box for the segment.
+ b2AABB segmentAABB;
+ {
+ b2Vec2 t = p1 + maxFraction * (p2 - p1);
+ segmentAABB.lowerBound = b2Min(p1, t);
+ segmentAABB.upperBound = b2Max(p1, t);
+ }
+
+ b2GrowableStack<int32, 256> stack;
+ stack.Push(m_root);
+
+ while (stack.GetCount() > 0)
+ {
+ int32 nodeId = stack.Pop();
+ if (nodeId == b2_nullNode)
+ {
+ continue;
+ }
+
+ const b2TreeNode* node = m_nodes + nodeId;
+
+ if (b2TestOverlap(node->aabb, segmentAABB) == false)
+ {
+ continue;
+ }
+
+ // Separating axis for segment (Gino, p80).
+ // |dot(v, p1 - c)| > dot(|v|, h)
+ b2Vec2 c = node->aabb.GetCenter();
+ b2Vec2 h = node->aabb.GetExtents();
+ float separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
+ if (separation > 0.0f)
+ {
+ continue;
+ }
+
+ if (node->IsLeaf())
+ {
+ b2RayCastInput subInput;
+ subInput.p1 = input.p1;
+ subInput.p2 = input.p2;
+ subInput.maxFraction = maxFraction;
+
+ float value = callback->RayCastCallback(subInput, nodeId);
+
+ if (value == 0.0f)
+ {
+ // The client has terminated the ray cast.
+ return;
+ }
+
+ if (value > 0.0f)
+ {
+ // Update segment bounding box.
+ maxFraction = value;
+ b2Vec2 t = p1 + maxFraction * (p2 - p1);
+ segmentAABB.lowerBound = b2Min(p1, t);
+ segmentAABB.upperBound = b2Max(p1, t);
+ }
+ }
+ else
+ {
+ stack.Push(node->child1);
+ stack.Push(node->child2);
+ }
+ }
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_edge_shape.h b/Client/ThirdParty/Box2D/include/box2d/b2_edge_shape.h
new file mode 100644
index 0000000..b930ee8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_edge_shape.h
@@ -0,0 +1,86 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_EDGE_SHAPE_H
+#define B2_EDGE_SHAPE_H
+
+#include "b2_api.h"
+#include "b2_shape.h"
+
+/// A line segment (edge) shape. These can be connected in chains or loops
+/// to other edge shapes. Edges created independently are two-sided and do
+/// no provide smooth movement across junctions.
+class B2_API b2EdgeShape : public b2Shape
+{
+public:
+ b2EdgeShape();
+
+ /// Set this as a part of a sequence. Vertex v0 precedes the edge and vertex v3
+ /// follows. These extra vertices are used to provide smooth movement
+ /// across junctions. This also makes the collision one-sided. The edge
+ /// normal points to the right looking from v1 to v2.
+ void SetOneSided(const b2Vec2& v0, const b2Vec2& v1,const b2Vec2& v2, const b2Vec2& v3);
+
+ /// Set this as an isolated edge. Collision is two-sided.
+ void SetTwoSided(const b2Vec2& v1, const b2Vec2& v2);
+
+ /// Implement b2Shape.
+ b2Shape* Clone(b2BlockAllocator* allocator) const override;
+
+ /// @see b2Shape::GetChildCount
+ int32 GetChildCount() const override;
+
+ /// @see b2Shape::TestPoint
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override;
+
+ /// Implement b2Shape.
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeAABB
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeMass
+ void ComputeMass(b2MassData* massData, float density) const override;
+
+ /// These are the edge vertices
+ b2Vec2 m_vertex1, m_vertex2;
+
+ /// Optional adjacent vertices. These are used for smooth collision.
+ b2Vec2 m_vertex0, m_vertex3;
+
+ /// Uses m_vertex0 and m_vertex3 to create smooth collision.
+ bool m_oneSided;
+};
+
+inline b2EdgeShape::b2EdgeShape()
+{
+ m_type = e_edge;
+ m_radius = b2_polygonRadius;
+ m_vertex0.x = 0.0f;
+ m_vertex0.y = 0.0f;
+ m_vertex3.x = 0.0f;
+ m_vertex3.y = 0.0f;
+ m_oneSided = false;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_fixture.h b/Client/ThirdParty/Box2D/include/box2d/b2_fixture.h
new file mode 100644
index 0000000..f12789b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_fixture.h
@@ -0,0 +1,365 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_FIXTURE_H
+#define B2_FIXTURE_H
+
+#include "b2_api.h"
+#include "b2_body.h"
+#include "b2_collision.h"
+#include "b2_shape.h"
+
+class b2BlockAllocator;
+class b2Body;
+class b2BroadPhase;
+class b2Fixture;
+
+/// This holds contact filtering data.
+struct B2_API b2Filter
+{
+ b2Filter()
+ {
+ categoryBits = 0x0001;
+ maskBits = 0xFFFF;
+ groupIndex = 0;
+ }
+
+ /// The collision category bits. Normally you would just set one bit.
+ uint16 categoryBits;
+
+ /// The collision mask bits. This states the categories that this
+ /// shape would accept for collision.
+ uint16 maskBits;
+
+ /// Collision groups allow a certain group of objects to never collide (negative)
+ /// or always collide (positive). Zero means no collision group. Non-zero group
+ /// filtering always wins against the mask bits.
+ int16 groupIndex;
+};
+
+/// A fixture definition is used to create a fixture. This class defines an
+/// abstract fixture definition. You can reuse fixture definitions safely.
+struct B2_API b2FixtureDef
+{
+ /// The constructor sets the default fixture definition values.
+ b2FixtureDef()
+ {
+ shape = nullptr;
+ friction = 0.2f;
+ restitution = 0.0f;
+ restitutionThreshold = 1.0f * b2_lengthUnitsPerMeter;
+ density = 0.0f;
+ isSensor = false;
+ }
+
+ /// The shape, this must be set. The shape will be cloned, so you
+ /// can create the shape on the stack.
+ const b2Shape* shape;
+
+ /// Use this to store application specific fixture data.
+ b2FixtureUserData userData;
+
+ /// The friction coefficient, usually in the range [0,1].
+ float friction;
+
+ /// The restitution (elasticity) usually in the range [0,1].
+ float restitution;
+
+ /// Restitution velocity threshold, usually in m/s. Collisions above this
+ /// speed have restitution applied (will bounce).
+ float restitutionThreshold;
+
+ /// The density, usually in kg/m^2.
+ float density;
+
+ /// A sensor shape collects contact information but never generates a collision
+ /// response.
+ bool isSensor;
+
+ /// Contact filtering data.
+ b2Filter filter;
+};
+
+/// This proxy is used internally to connect fixtures to the broad-phase.
+struct B2_API b2FixtureProxy
+{
+ b2AABB aabb;
+ b2Fixture* fixture;
+ int32 childIndex;
+ int32 proxyId;
+};
+
+/// A fixture is used to attach a shape to a body for collision detection. A fixture
+/// inherits its transform from its parent. Fixtures hold additional non-geometric data
+/// such as friction, collision filters, etc.
+/// Fixtures are created via b2Body::CreateFixture.
+/// @warning you cannot reuse fixtures.
+class B2_API b2Fixture
+{
+public:
+ /// Get the type of the child shape. You can use this to down cast to the concrete shape.
+ /// @return the shape type.
+ b2Shape::Type GetType() const;
+
+ /// Get the child shape. You can modify the child shape, however you should not change the
+ /// number of vertices because this will crash some collision caching mechanisms.
+ /// Manipulating the shape may lead to non-physical behavior.
+ b2Shape* GetShape();
+ const b2Shape* GetShape() const;
+
+ /// Set if this fixture is a sensor.
+ void SetSensor(bool sensor);
+
+ /// Is this fixture a sensor (non-solid)?
+ /// @return the true if the shape is a sensor.
+ bool IsSensor() const;
+
+ /// Set the contact filtering data. This will not update contacts until the next time
+ /// step when either parent body is active and awake.
+ /// This automatically calls Refilter.
+ void SetFilterData(const b2Filter& filter);
+
+ /// Get the contact filtering data.
+ const b2Filter& GetFilterData() const;
+
+ /// Call this if you want to establish collision that was previously disabled by b2ContactFilter::ShouldCollide.
+ void Refilter();
+
+ /// Get the parent body of this fixture. This is nullptr if the fixture is not attached.
+ /// @return the parent body.
+ b2Body* GetBody();
+ const b2Body* GetBody() const;
+
+ /// Get the next fixture in the parent body's fixture list.
+ /// @return the next shape.
+ b2Fixture* GetNext();
+ const b2Fixture* GetNext() const;
+
+ /// Get the user data that was assigned in the fixture definition. Use this to
+ /// store your application specific data.
+ b2FixtureUserData& GetUserData();
+
+ /// Test a point for containment in this fixture.
+ /// @param p a point in world coordinates.
+ bool TestPoint(const b2Vec2& p) const;
+
+ /// Cast a ray against this shape.
+ /// @param output the ray-cast results.
+ /// @param input the ray-cast input parameters.
+ /// @param childIndex the child shape index (e.g. edge index)
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const;
+
+ /// Get the mass data for this fixture. The mass data is based on the density and
+ /// the shape. The rotational inertia is about the shape's origin. This operation
+ /// may be expensive.
+ void GetMassData(b2MassData* massData) const;
+
+ /// Set the density of this fixture. This will _not_ automatically adjust the mass
+ /// of the body. You must call b2Body::ResetMassData to update the body's mass.
+ void SetDensity(float density);
+
+ /// Get the density of this fixture.
+ float GetDensity() const;
+
+ /// Get the coefficient of friction.
+ float GetFriction() const;
+
+ /// Set the coefficient of friction. This will _not_ change the friction of
+ /// existing contacts.
+ void SetFriction(float friction);
+
+ /// Get the coefficient of restitution.
+ float GetRestitution() const;
+
+ /// Set the coefficient of restitution. This will _not_ change the restitution of
+ /// existing contacts.
+ void SetRestitution(float restitution);
+
+ /// Get the restitution velocity threshold.
+ float GetRestitutionThreshold() const;
+
+ /// Set the restitution threshold. This will _not_ change the restitution threshold of
+ /// existing contacts.
+ void SetRestitutionThreshold(float threshold);
+
+ /// Get the fixture's AABB. This AABB may be enlarge and/or stale.
+ /// If you need a more accurate AABB, compute it using the shape and
+ /// the body transform.
+ const b2AABB& GetAABB(int32 childIndex) const;
+
+ /// Dump this fixture to the log file.
+ void Dump(int32 bodyIndex);
+
+protected:
+
+ friend class b2Body;
+ friend class b2World;
+ friend class b2Contact;
+ friend class b2ContactManager;
+
+ b2Fixture();
+
+ // We need separation create/destroy functions from the constructor/destructor because
+ // the destructor cannot access the allocator (no destructor arguments allowed by C++).
+ void Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def);
+ void Destroy(b2BlockAllocator* allocator);
+
+ // These support body activation/deactivation.
+ void CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf);
+ void DestroyProxies(b2BroadPhase* broadPhase);
+
+ void Synchronize(b2BroadPhase* broadPhase, const b2Transform& xf1, const b2Transform& xf2);
+
+ float m_density;
+
+ b2Fixture* m_next;
+ b2Body* m_body;
+
+ b2Shape* m_shape;
+
+ float m_friction;
+ float m_restitution;
+ float m_restitutionThreshold;
+
+ b2FixtureProxy* m_proxies;
+ int32 m_proxyCount;
+
+ b2Filter m_filter;
+
+ bool m_isSensor;
+
+ b2FixtureUserData m_userData;
+};
+
+inline b2Shape::Type b2Fixture::GetType() const
+{
+ return m_shape->GetType();
+}
+
+inline b2Shape* b2Fixture::GetShape()
+{
+ return m_shape;
+}
+
+inline const b2Shape* b2Fixture::GetShape() const
+{
+ return m_shape;
+}
+
+inline bool b2Fixture::IsSensor() const
+{
+ return m_isSensor;
+}
+
+inline const b2Filter& b2Fixture::GetFilterData() const
+{
+ return m_filter;
+}
+
+inline b2FixtureUserData& b2Fixture::GetUserData()
+{
+ return m_userData;
+}
+
+inline b2Body* b2Fixture::GetBody()
+{
+ return m_body;
+}
+
+inline const b2Body* b2Fixture::GetBody() const
+{
+ return m_body;
+}
+
+inline b2Fixture* b2Fixture::GetNext()
+{
+ return m_next;
+}
+
+inline const b2Fixture* b2Fixture::GetNext() const
+{
+ return m_next;
+}
+
+inline void b2Fixture::SetDensity(float density)
+{
+ b2Assert(b2IsValid(density) && density >= 0.0f);
+ m_density = density;
+}
+
+inline float b2Fixture::GetDensity() const
+{
+ return m_density;
+}
+
+inline float b2Fixture::GetFriction() const
+{
+ return m_friction;
+}
+
+inline void b2Fixture::SetFriction(float friction)
+{
+ m_friction = friction;
+}
+
+inline float b2Fixture::GetRestitution() const
+{
+ return m_restitution;
+}
+
+inline void b2Fixture::SetRestitution(float restitution)
+{
+ m_restitution = restitution;
+}
+
+inline float b2Fixture::GetRestitutionThreshold() const
+{
+ return m_restitutionThreshold;
+}
+
+inline void b2Fixture::SetRestitutionThreshold(float threshold)
+{
+ m_restitutionThreshold = threshold;
+}
+
+inline bool b2Fixture::TestPoint(const b2Vec2& p) const
+{
+ return m_shape->TestPoint(m_body->GetTransform(), p);
+}
+
+inline bool b2Fixture::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const
+{
+ return m_shape->RayCast(output, input, m_body->GetTransform(), childIndex);
+}
+
+inline void b2Fixture::GetMassData(b2MassData* massData) const
+{
+ m_shape->ComputeMass(massData, m_density);
+}
+
+inline const b2AABB& b2Fixture::GetAABB(int32 childIndex) const
+{
+ b2Assert(0 <= childIndex && childIndex < m_proxyCount);
+ return m_proxies[childIndex].aabb;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_friction_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_friction_joint.h
new file mode 100644
index 0000000..99922c3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_friction_joint.h
@@ -0,0 +1,124 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_FRICTION_JOINT_H
+#define B2_FRICTION_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Friction joint definition.
+struct B2_API b2FrictionJointDef : public b2JointDef
+{
+ b2FrictionJointDef()
+ {
+ type = e_frictionJoint;
+ localAnchorA.SetZero();
+ localAnchorB.SetZero();
+ maxForce = 0.0f;
+ maxTorque = 0.0f;
+ }
+
+ /// Initialize the bodies, anchors, axis, and reference angle using the world
+ /// anchor and world axis.
+ void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor);
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The maximum friction force in N.
+ float maxForce;
+
+ /// The maximum friction torque in N-m.
+ float maxTorque;
+};
+
+/// Friction joint. This is used for top-down friction.
+/// It provides 2D translational friction and angular friction.
+class B2_API b2FrictionJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// The local anchor point relative to bodyA's origin.
+ const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; }
+
+ /// The local anchor point relative to bodyB's origin.
+ const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; }
+
+ /// Set the maximum friction force in N.
+ void SetMaxForce(float force);
+
+ /// Get the maximum friction force in N.
+ float GetMaxForce() const;
+
+ /// Set the maximum friction torque in N*m.
+ void SetMaxTorque(float torque);
+
+ /// Get the maximum friction torque in N*m.
+ float GetMaxTorque() const;
+
+ /// Dump joint to dmLog
+ void Dump() override;
+
+protected:
+
+ friend class b2Joint;
+
+ b2FrictionJoint(const b2FrictionJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+
+ // Solver shared
+ b2Vec2 m_linearImpulse;
+ float m_angularImpulse;
+ float m_maxForce;
+ float m_maxTorque;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_rA;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ b2Mat22 m_linearMass;
+ float m_angularMass;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_gear_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_gear_joint.h
new file mode 100644
index 0000000..1c40687
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_gear_joint.h
@@ -0,0 +1,130 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_GEAR_JOINT_H
+#define B2_GEAR_JOINT_H
+
+#include "b2_joint.h"
+
+/// Gear joint definition. This definition requires two existing
+/// revolute or prismatic joints (any combination will work).
+/// @warning bodyB on the input joints must both be dynamic
+struct B2_API b2GearJointDef : public b2JointDef
+{
+ b2GearJointDef()
+ {
+ type = e_gearJoint;
+ joint1 = nullptr;
+ joint2 = nullptr;
+ ratio = 1.0f;
+ }
+
+ /// The first revolute/prismatic joint attached to the gear joint.
+ b2Joint* joint1;
+
+ /// The second revolute/prismatic joint attached to the gear joint.
+ b2Joint* joint2;
+
+ /// The gear ratio.
+ /// @see b2GearJoint for explanation.
+ float ratio;
+};
+
+/// A gear joint is used to connect two joints together. Either joint
+/// can be a revolute or prismatic joint. You specify a gear ratio
+/// to bind the motions together:
+/// coordinate1 + ratio * coordinate2 = constant
+/// The ratio can be negative or positive. If one joint is a revolute joint
+/// and the other joint is a prismatic joint, then the ratio will have units
+/// of length or units of 1/length.
+/// @warning You have to manually destroy the gear joint if joint1 or joint2
+/// is destroyed.
+class B2_API b2GearJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// Get the first joint.
+ b2Joint* GetJoint1() { return m_joint1; }
+
+ /// Get the second joint.
+ b2Joint* GetJoint2() { return m_joint2; }
+
+ /// Set/Get the gear ratio.
+ void SetRatio(float ratio);
+ float GetRatio() const;
+
+ /// Dump joint to dmLog
+ void Dump() override;
+
+protected:
+
+ friend class b2Joint;
+ b2GearJoint(const b2GearJointDef* data);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ b2Joint* m_joint1;
+ b2Joint* m_joint2;
+
+ b2JointType m_typeA;
+ b2JointType m_typeB;
+
+ // Body A is connected to body C
+ // Body B is connected to body D
+ b2Body* m_bodyC;
+ b2Body* m_bodyD;
+
+ // Solver shared
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ b2Vec2 m_localAnchorC;
+ b2Vec2 m_localAnchorD;
+
+ b2Vec2 m_localAxisC;
+ b2Vec2 m_localAxisD;
+
+ float m_referenceAngleA;
+ float m_referenceAngleB;
+
+ float m_constant;
+ float m_ratio;
+
+ float m_impulse;
+
+ // Solver temp
+ int32 m_indexA, m_indexB, m_indexC, m_indexD;
+ b2Vec2 m_lcA, m_lcB, m_lcC, m_lcD;
+ float m_mA, m_mB, m_mC, m_mD;
+ float m_iA, m_iB, m_iC, m_iD;
+ b2Vec2 m_JvAC, m_JvBD;
+ float m_JwA, m_JwB, m_JwC, m_JwD;
+ float m_mass;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_growable_stack.h b/Client/ThirdParty/Box2D/include/box2d/b2_growable_stack.h
new file mode 100644
index 0000000..ec42e5e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_growable_stack.h
@@ -0,0 +1,91 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_GROWABLE_STACK_H
+#define B2_GROWABLE_STACK_H
+
+#include <string.h>
+
+#include "b2_settings.h"
+
+/// This is a growable LIFO stack with an initial capacity of N.
+/// If the stack size exceeds the initial capacity, the heap is used
+/// to increase the size of the stack.
+template <typename T, int32 N>
+class b2GrowableStack
+{
+public:
+ b2GrowableStack()
+ {
+ m_stack = m_array;
+ m_count = 0;
+ m_capacity = N;
+ }
+
+ ~b2GrowableStack()
+ {
+ if (m_stack != m_array)
+ {
+ b2Free(m_stack);
+ m_stack = nullptr;
+ }
+ }
+
+ void Push(const T& element)
+ {
+ if (m_count == m_capacity)
+ {
+ T* old = m_stack;
+ m_capacity *= 2;
+ m_stack = (T*)b2Alloc(m_capacity * sizeof(T));
+ memcpy(m_stack, old, m_count * sizeof(T));
+ if (old != m_array)
+ {
+ b2Free(old);
+ }
+ }
+
+ m_stack[m_count] = element;
+ ++m_count;
+ }
+
+ T Pop()
+ {
+ b2Assert(m_count > 0);
+ --m_count;
+ return m_stack[m_count];
+ }
+
+ int32 GetCount()
+ {
+ return m_count;
+ }
+
+private:
+ T* m_stack;
+ T m_array[N];
+ int32 m_count;
+ int32 m_capacity;
+};
+
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_joint.h
new file mode 100644
index 0000000..2b4d586
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_joint.h
@@ -0,0 +1,228 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_JOINT_H
+#define B2_JOINT_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+
+class b2Body;
+class b2Draw;
+class b2Joint;
+struct b2SolverData;
+class b2BlockAllocator;
+
+enum b2JointType
+{
+ e_unknownJoint,
+ e_revoluteJoint,
+ e_prismaticJoint,
+ e_distanceJoint,
+ e_pulleyJoint,
+ e_mouseJoint,
+ e_gearJoint,
+ e_wheelJoint,
+ e_weldJoint,
+ e_frictionJoint,
+ e_ropeJoint,
+ e_motorJoint
+};
+
+struct B2_API b2Jacobian
+{
+ b2Vec2 linear;
+ float angularA;
+ float angularB;
+};
+
+/// A joint edge is used to connect bodies and joints together
+/// in a joint graph where each body is a node and each joint
+/// is an edge. A joint edge belongs to a doubly linked list
+/// maintained in each attached body. Each joint has two joint
+/// nodes, one for each attached body.
+struct B2_API b2JointEdge
+{
+ b2Body* other; ///< provides quick access to the other body attached.
+ b2Joint* joint; ///< the joint
+ b2JointEdge* prev; ///< the previous joint edge in the body's joint list
+ b2JointEdge* next; ///< the next joint edge in the body's joint list
+};
+
+/// Joint definitions are used to construct joints.
+struct B2_API b2JointDef
+{
+ b2JointDef()
+ {
+ type = e_unknownJoint;
+ bodyA = nullptr;
+ bodyB = nullptr;
+ collideConnected = false;
+ }
+
+ /// The joint type is set automatically for concrete joint types.
+ b2JointType type;
+
+ /// Use this to attach application specific data to your joints.
+ b2JointUserData userData;
+
+ /// The first attached body.
+ b2Body* bodyA;
+
+ /// The second attached body.
+ b2Body* bodyB;
+
+ /// Set this flag to true if the attached bodies should collide.
+ bool collideConnected;
+};
+
+/// Utility to compute linear stiffness values from frequency and damping ratio
+B2_API void b2LinearStiffness(float& stiffness, float& damping,
+ float frequencyHertz, float dampingRatio,
+ const b2Body* bodyA, const b2Body* bodyB);
+
+/// Utility to compute rotational stiffness values frequency and damping ratio
+B2_API void b2AngularStiffness(float& stiffness, float& damping,
+ float frequencyHertz, float dampingRatio,
+ const b2Body* bodyA, const b2Body* bodyB);
+
+/// The base joint class. Joints are used to constraint two bodies together in
+/// various fashions. Some joints also feature limits and motors.
+class B2_API b2Joint
+{
+public:
+
+ /// Get the type of the concrete joint.
+ b2JointType GetType() const;
+
+ /// Get the first body attached to this joint.
+ b2Body* GetBodyA();
+
+ /// Get the second body attached to this joint.
+ b2Body* GetBodyB();
+
+ /// Get the anchor point on bodyA in world coordinates.
+ virtual b2Vec2 GetAnchorA() const = 0;
+
+ /// Get the anchor point on bodyB in world coordinates.
+ virtual b2Vec2 GetAnchorB() const = 0;
+
+ /// Get the reaction force on bodyB at the joint anchor in Newtons.
+ virtual b2Vec2 GetReactionForce(float inv_dt) const = 0;
+
+ /// Get the reaction torque on bodyB in N*m.
+ virtual float GetReactionTorque(float inv_dt) const = 0;
+
+ /// Get the next joint the world joint list.
+ b2Joint* GetNext();
+ const b2Joint* GetNext() const;
+
+ /// Get the user data pointer.
+ b2JointUserData& GetUserData();
+
+ /// Short-cut function to determine if either body is enabled.
+ bool IsEnabled() const;
+
+ /// Get collide connected.
+ /// Note: modifying the collide connect flag won't work correctly because
+ /// the flag is only checked when fixture AABBs begin to overlap.
+ bool GetCollideConnected() const;
+
+ /// Dump this joint to the log file.
+ virtual void Dump() { b2Dump("// Dump is not supported for this joint type.\n"); }
+
+ /// Shift the origin for any points stored in world coordinates.
+ virtual void ShiftOrigin(const b2Vec2& newOrigin) { B2_NOT_USED(newOrigin); }
+
+ /// Debug draw this joint
+ virtual void Draw(b2Draw* draw) const;
+
+protected:
+ friend class b2World;
+ friend class b2Body;
+ friend class b2Island;
+ friend class b2GearJoint;
+
+ static b2Joint* Create(const b2JointDef* def, b2BlockAllocator* allocator);
+ static void Destroy(b2Joint* joint, b2BlockAllocator* allocator);
+
+ b2Joint(const b2JointDef* def);
+ virtual ~b2Joint() {}
+
+ virtual void InitVelocityConstraints(const b2SolverData& data) = 0;
+ virtual void SolveVelocityConstraints(const b2SolverData& data) = 0;
+
+ // This returns true if the position errors are within tolerance.
+ virtual bool SolvePositionConstraints(const b2SolverData& data) = 0;
+
+ b2JointType m_type;
+ b2Joint* m_prev;
+ b2Joint* m_next;
+ b2JointEdge m_edgeA;
+ b2JointEdge m_edgeB;
+ b2Body* m_bodyA;
+ b2Body* m_bodyB;
+
+ int32 m_index;
+
+ bool m_islandFlag;
+ bool m_collideConnected;
+
+ b2JointUserData m_userData;
+};
+
+inline b2JointType b2Joint::GetType() const
+{
+ return m_type;
+}
+
+inline b2Body* b2Joint::GetBodyA()
+{
+ return m_bodyA;
+}
+
+inline b2Body* b2Joint::GetBodyB()
+{
+ return m_bodyB;
+}
+
+inline b2Joint* b2Joint::GetNext()
+{
+ return m_next;
+}
+
+inline const b2Joint* b2Joint::GetNext() const
+{
+ return m_next;
+}
+
+inline b2JointUserData& b2Joint::GetUserData()
+{
+ return m_userData;
+}
+
+inline bool b2Joint::GetCollideConnected() const
+{
+ return m_collideConnected;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_math.h b/Client/ThirdParty/Box2D/include/box2d/b2_math.h
new file mode 100644
index 0000000..479e667
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_math.h
@@ -0,0 +1,715 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_MATH_H
+#define B2_MATH_H
+
+#include <math.h>
+
+#include "b2_api.h"
+#include "b2_settings.h"
+
+/// This function is used to ensure that a floating point number is not a NaN or infinity.
+inline bool b2IsValid(float x)
+{
+ return isfinite(x);
+}
+
+#define b2Sqrt(x) sqrtf(x)
+#define b2Atan2(y, x) atan2f(y, x)
+
+/// A 2D column vector.
+struct B2_API b2Vec2
+{
+ /// Default constructor does nothing (for performance).
+ b2Vec2() {}
+
+ /// Construct using coordinates.
+ b2Vec2(float xIn, float yIn) : x(xIn), y(yIn) {}
+
+ /// Set this vector to all zeros.
+ void SetZero() { x = 0.0f; y = 0.0f; }
+
+ /// Set this vector to some specified coordinates.
+ void Set(float x_, float y_) { x = x_; y = y_; }
+
+ /// Negate this vector.
+ b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; }
+
+ /// Read from and indexed element.
+ float operator () (int32 i) const
+ {
+ return (&x)[i];
+ }
+
+ /// Write to an indexed element.
+ float& operator () (int32 i)
+ {
+ return (&x)[i];
+ }
+
+ /// Add a vector to this vector.
+ void operator += (const b2Vec2& v)
+ {
+ x += v.x; y += v.y;
+ }
+
+ /// Subtract a vector from this vector.
+ void operator -= (const b2Vec2& v)
+ {
+ x -= v.x; y -= v.y;
+ }
+
+ /// Multiply this vector by a scalar.
+ void operator *= (float a)
+ {
+ x *= a; y *= a;
+ }
+
+ /// Get the length of this vector (the norm).
+ float Length() const
+ {
+ return b2Sqrt(x * x + y * y);
+ }
+
+ /// Get the length squared. For performance, use this instead of
+ /// b2Vec2::Length (if possible).
+ float LengthSquared() const
+ {
+ return x * x + y * y;
+ }
+
+ /// Convert this vector into a unit vector. Returns the length.
+ float Normalize()
+ {
+ float length = Length();
+ if (length < b2_epsilon)
+ {
+ return 0.0f;
+ }
+ float invLength = 1.0f / length;
+ x *= invLength;
+ y *= invLength;
+
+ return length;
+ }
+
+ /// Does this vector contain finite coordinates?
+ bool IsValid() const
+ {
+ return b2IsValid(x) && b2IsValid(y);
+ }
+
+ /// Get the skew vector such that dot(skew_vec, other) == cross(vec, other)
+ b2Vec2 Skew() const
+ {
+ return b2Vec2(-y, x);
+ }
+
+ float x, y;
+};
+
+/// A 2D column vector with 3 elements.
+struct B2_API b2Vec3
+{
+ /// Default constructor does nothing (for performance).
+ b2Vec3() {}
+
+ /// Construct using coordinates.
+ b2Vec3(float xIn, float yIn, float zIn) : x(xIn), y(yIn), z(zIn) {}
+
+ /// Set this vector to all zeros.
+ void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; }
+
+ /// Set this vector to some specified coordinates.
+ void Set(float x_, float y_, float z_) { x = x_; y = y_; z = z_; }
+
+ /// Negate this vector.
+ b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; }
+
+ /// Add a vector to this vector.
+ void operator += (const b2Vec3& v)
+ {
+ x += v.x; y += v.y; z += v.z;
+ }
+
+ /// Subtract a vector from this vector.
+ void operator -= (const b2Vec3& v)
+ {
+ x -= v.x; y -= v.y; z -= v.z;
+ }
+
+ /// Multiply this vector by a scalar.
+ void operator *= (float s)
+ {
+ x *= s; y *= s; z *= s;
+ }
+
+ float x, y, z;
+};
+
+/// A 2-by-2 matrix. Stored in column-major order.
+struct B2_API b2Mat22
+{
+ /// The default constructor does nothing (for performance).
+ b2Mat22() {}
+
+ /// Construct this matrix using columns.
+ b2Mat22(const b2Vec2& c1, const b2Vec2& c2)
+ {
+ ex = c1;
+ ey = c2;
+ }
+
+ /// Construct this matrix using scalars.
+ b2Mat22(float a11, float a12, float a21, float a22)
+ {
+ ex.x = a11; ex.y = a21;
+ ey.x = a12; ey.y = a22;
+ }
+
+ /// Initialize this matrix using columns.
+ void Set(const b2Vec2& c1, const b2Vec2& c2)
+ {
+ ex = c1;
+ ey = c2;
+ }
+
+ /// Set this to the identity matrix.
+ void SetIdentity()
+ {
+ ex.x = 1.0f; ey.x = 0.0f;
+ ex.y = 0.0f; ey.y = 1.0f;
+ }
+
+ /// Set this matrix to all zeros.
+ void SetZero()
+ {
+ ex.x = 0.0f; ey.x = 0.0f;
+ ex.y = 0.0f; ey.y = 0.0f;
+ }
+
+ b2Mat22 GetInverse() const
+ {
+ float a = ex.x, b = ey.x, c = ex.y, d = ey.y;
+ b2Mat22 B;
+ float det = a * d - b * c;
+ if (det != 0.0f)
+ {
+ det = 1.0f / det;
+ }
+ B.ex.x = det * d; B.ey.x = -det * b;
+ B.ex.y = -det * c; B.ey.y = det * a;
+ return B;
+ }
+
+ /// Solve A * x = b, where b is a column vector. This is more efficient
+ /// than computing the inverse in one-shot cases.
+ b2Vec2 Solve(const b2Vec2& b) const
+ {
+ float a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y;
+ float det = a11 * a22 - a12 * a21;
+ if (det != 0.0f)
+ {
+ det = 1.0f / det;
+ }
+ b2Vec2 x;
+ x.x = det * (a22 * b.x - a12 * b.y);
+ x.y = det * (a11 * b.y - a21 * b.x);
+ return x;
+ }
+
+ b2Vec2 ex, ey;
+};
+
+/// A 3-by-3 matrix. Stored in column-major order.
+struct B2_API b2Mat33
+{
+ /// The default constructor does nothing (for performance).
+ b2Mat33() {}
+
+ /// Construct this matrix using columns.
+ b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3)
+ {
+ ex = c1;
+ ey = c2;
+ ez = c3;
+ }
+
+ /// Set this matrix to all zeros.
+ void SetZero()
+ {
+ ex.SetZero();
+ ey.SetZero();
+ ez.SetZero();
+ }
+
+ /// Solve A * x = b, where b is a column vector. This is more efficient
+ /// than computing the inverse in one-shot cases.
+ b2Vec3 Solve33(const b2Vec3& b) const;
+
+ /// Solve A * x = b, where b is a column vector. This is more efficient
+ /// than computing the inverse in one-shot cases. Solve only the upper
+ /// 2-by-2 matrix equation.
+ b2Vec2 Solve22(const b2Vec2& b) const;
+
+ /// Get the inverse of this matrix as a 2-by-2.
+ /// Returns the zero matrix if singular.
+ void GetInverse22(b2Mat33* M) const;
+
+ /// Get the symmetric inverse of this matrix as a 3-by-3.
+ /// Returns the zero matrix if singular.
+ void GetSymInverse33(b2Mat33* M) const;
+
+ b2Vec3 ex, ey, ez;
+};
+
+/// Rotation
+struct B2_API b2Rot
+{
+ b2Rot() {}
+
+ /// Initialize from an angle in radians
+ explicit b2Rot(float angle)
+ {
+ /// TODO_ERIN optimize
+ s = sinf(angle);
+ c = cosf(angle);
+ }
+
+ /// Set using an angle in radians.
+ void Set(float angle)
+ {
+ /// TODO_ERIN optimize
+ s = sinf(angle);
+ c = cosf(angle);
+ }
+
+ /// Set to the identity rotation
+ void SetIdentity()
+ {
+ s = 0.0f;
+ c = 1.0f;
+ }
+
+ /// Get the angle in radians
+ float GetAngle() const
+ {
+ return b2Atan2(s, c);
+ }
+
+ /// Get the x-axis
+ b2Vec2 GetXAxis() const
+ {
+ return b2Vec2(c, s);
+ }
+
+ /// Get the u-axis
+ b2Vec2 GetYAxis() const
+ {
+ return b2Vec2(-s, c);
+ }
+
+ /// Sine and cosine
+ float s, c;
+};
+
+/// A transform contains translation and rotation. It is used to represent
+/// the position and orientation of rigid frames.
+struct B2_API b2Transform
+{
+ /// The default constructor does nothing.
+ b2Transform() {}
+
+ /// Initialize using a position vector and a rotation.
+ b2Transform(const b2Vec2& position, const b2Rot& rotation) : p(position), q(rotation) {}
+
+ /// Set this to the identity transform.
+ void SetIdentity()
+ {
+ p.SetZero();
+ q.SetIdentity();
+ }
+
+ /// Set this based on the position and angle.
+ void Set(const b2Vec2& position, float angle)
+ {
+ p = position;
+ q.Set(angle);
+ }
+
+ b2Vec2 p;
+ b2Rot q;
+};
+
+/// This describes the motion of a body/shape for TOI computation.
+/// Shapes are defined with respect to the body origin, which may
+/// no coincide with the center of mass. However, to support dynamics
+/// we must interpolate the center of mass position.
+struct B2_API b2Sweep
+{
+ /// Get the interpolated transform at a specific time.
+ /// @param transform the output transform
+ /// @param beta is a factor in [0,1], where 0 indicates alpha0.
+ void GetTransform(b2Transform* transform, float beta) const;
+
+ /// Advance the sweep forward, yielding a new initial state.
+ /// @param alpha the new initial time.
+ void Advance(float alpha);
+
+ /// Normalize the angles.
+ void Normalize();
+
+ b2Vec2 localCenter; ///< local center of mass position
+ b2Vec2 c0, c; ///< center world positions
+ float a0, a; ///< world angles
+
+ /// Fraction of the current time step in the range [0,1]
+ /// c0 and a0 are the positions at alpha0.
+ float alpha0;
+};
+
+/// Useful constant
+extern B2_API const b2Vec2 b2Vec2_zero;
+
+/// Perform the dot product on two vectors.
+inline float b2Dot(const b2Vec2& a, const b2Vec2& b)
+{
+ return a.x * b.x + a.y * b.y;
+}
+
+/// Perform the cross product on two vectors. In 2D this produces a scalar.
+inline float b2Cross(const b2Vec2& a, const b2Vec2& b)
+{
+ return a.x * b.y - a.y * b.x;
+}
+
+/// Perform the cross product on a vector and a scalar. In 2D this produces
+/// a vector.
+inline b2Vec2 b2Cross(const b2Vec2& a, float s)
+{
+ return b2Vec2(s * a.y, -s * a.x);
+}
+
+/// Perform the cross product on a scalar and a vector. In 2D this produces
+/// a vector.
+inline b2Vec2 b2Cross(float s, const b2Vec2& a)
+{
+ return b2Vec2(-s * a.y, s * a.x);
+}
+
+/// Multiply a matrix times a vector. If a rotation matrix is provided,
+/// then this transforms the vector from one frame to another.
+inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v)
+{
+ return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y);
+}
+
+/// Multiply a matrix transpose times a vector. If a rotation matrix is provided,
+/// then this transforms the vector from one frame to another (inverse transform).
+inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v)
+{
+ return b2Vec2(b2Dot(v, A.ex), b2Dot(v, A.ey));
+}
+
+/// Add two vectors component-wise.
+inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b)
+{
+ return b2Vec2(a.x + b.x, a.y + b.y);
+}
+
+/// Subtract two vectors component-wise.
+inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b)
+{
+ return b2Vec2(a.x - b.x, a.y - b.y);
+}
+
+inline b2Vec2 operator * (float s, const b2Vec2& a)
+{
+ return b2Vec2(s * a.x, s * a.y);
+}
+
+inline bool operator == (const b2Vec2& a, const b2Vec2& b)
+{
+ return a.x == b.x && a.y == b.y;
+}
+
+inline bool operator != (const b2Vec2& a, const b2Vec2& b)
+{
+ return a.x != b.x || a.y != b.y;
+}
+
+inline float b2Distance(const b2Vec2& a, const b2Vec2& b)
+{
+ b2Vec2 c = a - b;
+ return c.Length();
+}
+
+inline float b2DistanceSquared(const b2Vec2& a, const b2Vec2& b)
+{
+ b2Vec2 c = a - b;
+ return b2Dot(c, c);
+}
+
+inline b2Vec3 operator * (float s, const b2Vec3& a)
+{
+ return b2Vec3(s * a.x, s * a.y, s * a.z);
+}
+
+/// Add two vectors component-wise.
+inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b)
+{
+ return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+/// Subtract two vectors component-wise.
+inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b)
+{
+ return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+/// Perform the dot product on two vectors.
+inline float b2Dot(const b2Vec3& a, const b2Vec3& b)
+{
+ return a.x * b.x + a.y * b.y + a.z * b.z;
+}
+
+/// Perform the cross product on two vectors.
+inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b)
+{
+ return b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
+}
+
+inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B)
+{
+ return b2Mat22(A.ex + B.ex, A.ey + B.ey);
+}
+
+// A * B
+inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B)
+{
+ return b2Mat22(b2Mul(A, B.ex), b2Mul(A, B.ey));
+}
+
+// A^T * B
+inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B)
+{
+ b2Vec2 c1(b2Dot(A.ex, B.ex), b2Dot(A.ey, B.ex));
+ b2Vec2 c2(b2Dot(A.ex, B.ey), b2Dot(A.ey, B.ey));
+ return b2Mat22(c1, c2);
+}
+
+/// Multiply a matrix times a vector.
+inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v)
+{
+ return v.x * A.ex + v.y * A.ey + v.z * A.ez;
+}
+
+/// Multiply a matrix times a vector.
+inline b2Vec2 b2Mul22(const b2Mat33& A, const b2Vec2& v)
+{
+ return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y);
+}
+
+/// Multiply two rotations: q * r
+inline b2Rot b2Mul(const b2Rot& q, const b2Rot& r)
+{
+ // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
+ // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
+ // s = qs * rc + qc * rs
+ // c = qc * rc - qs * rs
+ b2Rot qr;
+ qr.s = q.s * r.c + q.c * r.s;
+ qr.c = q.c * r.c - q.s * r.s;
+ return qr;
+}
+
+/// Transpose multiply two rotations: qT * r
+inline b2Rot b2MulT(const b2Rot& q, const b2Rot& r)
+{
+ // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
+ // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
+ // s = qc * rs - qs * rc
+ // c = qc * rc + qs * rs
+ b2Rot qr;
+ qr.s = q.c * r.s - q.s * r.c;
+ qr.c = q.c * r.c + q.s * r.s;
+ return qr;
+}
+
+/// Rotate a vector
+inline b2Vec2 b2Mul(const b2Rot& q, const b2Vec2& v)
+{
+ return b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y);
+}
+
+/// Inverse rotate a vector
+inline b2Vec2 b2MulT(const b2Rot& q, const b2Vec2& v)
+{
+ return b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y);
+}
+
+inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v)
+{
+ float x = (T.q.c * v.x - T.q.s * v.y) + T.p.x;
+ float y = (T.q.s * v.x + T.q.c * v.y) + T.p.y;
+
+ return b2Vec2(x, y);
+}
+
+inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v)
+{
+ float px = v.x - T.p.x;
+ float py = v.y - T.p.y;
+ float x = (T.q.c * px + T.q.s * py);
+ float y = (-T.q.s * px + T.q.c * py);
+
+ return b2Vec2(x, y);
+}
+
+// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
+// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
+inline b2Transform b2Mul(const b2Transform& A, const b2Transform& B)
+{
+ b2Transform C;
+ C.q = b2Mul(A.q, B.q);
+ C.p = b2Mul(A.q, B.p) + A.p;
+ return C;
+}
+
+// v2 = A.q' * (B.q * v1 + B.p - A.p)
+// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
+inline b2Transform b2MulT(const b2Transform& A, const b2Transform& B)
+{
+ b2Transform C;
+ C.q = b2MulT(A.q, B.q);
+ C.p = b2MulT(A.q, B.p - A.p);
+ return C;
+}
+
+template <typename T>
+inline T b2Abs(T a)
+{
+ return a > T(0) ? a : -a;
+}
+
+inline b2Vec2 b2Abs(const b2Vec2& a)
+{
+ return b2Vec2(b2Abs(a.x), b2Abs(a.y));
+}
+
+inline b2Mat22 b2Abs(const b2Mat22& A)
+{
+ return b2Mat22(b2Abs(A.ex), b2Abs(A.ey));
+}
+
+template <typename T>
+inline T b2Min(T a, T b)
+{
+ return a < b ? a : b;
+}
+
+inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b)
+{
+ return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y));
+}
+
+template <typename T>
+inline T b2Max(T a, T b)
+{
+ return a > b ? a : b;
+}
+
+inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b)
+{
+ return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y));
+}
+
+template <typename T>
+inline T b2Clamp(T a, T low, T high)
+{
+ return b2Max(low, b2Min(a, high));
+}
+
+inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high)
+{
+ return b2Max(low, b2Min(a, high));
+}
+
+template<typename T> inline void b2Swap(T& a, T& b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+/// "Next Largest Power of 2
+/// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
+/// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
+/// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
+/// largest power of 2. For a 32-bit value:"
+inline uint32 b2NextPowerOfTwo(uint32 x)
+{
+ x |= (x >> 1);
+ x |= (x >> 2);
+ x |= (x >> 4);
+ x |= (x >> 8);
+ x |= (x >> 16);
+ return x + 1;
+}
+
+inline bool b2IsPowerOfTwo(uint32 x)
+{
+ bool result = x > 0 && (x & (x - 1)) == 0;
+ return result;
+}
+
+// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
+inline void b2Sweep::GetTransform(b2Transform* xf, float beta) const
+{
+ xf->p = (1.0f - beta) * c0 + beta * c;
+ float angle = (1.0f - beta) * a0 + beta * a;
+ xf->q.Set(angle);
+
+ // Shift to origin
+ xf->p -= b2Mul(xf->q, localCenter);
+}
+
+inline void b2Sweep::Advance(float alpha)
+{
+ b2Assert(alpha0 < 1.0f);
+ float beta = (alpha - alpha0) / (1.0f - alpha0);
+ c0 += beta * (c - c0);
+ a0 += beta * (a - a0);
+ alpha0 = alpha;
+}
+
+/// Normalize an angle in radians to be between -pi and pi
+inline void b2Sweep::Normalize()
+{
+ float twoPi = 2.0f * b2_pi;
+ float d = twoPi * floorf(a0 / twoPi);
+ a0 -= d;
+ a -= d;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_motor_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_motor_joint.h
new file mode 100644
index 0000000..c88115f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_motor_joint.h
@@ -0,0 +1,138 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_MOTOR_JOINT_H
+#define B2_MOTOR_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Motor joint definition.
+struct B2_API b2MotorJointDef : public b2JointDef
+{
+ b2MotorJointDef()
+ {
+ type = e_motorJoint;
+ linearOffset.SetZero();
+ angularOffset = 0.0f;
+ maxForce = 1.0f;
+ maxTorque = 1.0f;
+ correctionFactor = 0.3f;
+ }
+
+ /// Initialize the bodies and offsets using the current transforms.
+ void Initialize(b2Body* bodyA, b2Body* bodyB);
+
+ /// Position of bodyB minus the position of bodyA, in bodyA's frame, in meters.
+ b2Vec2 linearOffset;
+
+ /// The bodyB angle minus bodyA angle in radians.
+ float angularOffset;
+
+ /// The maximum motor force in N.
+ float maxForce;
+
+ /// The maximum motor torque in N-m.
+ float maxTorque;
+
+ /// Position correction factor in the range [0,1].
+ float correctionFactor;
+};
+
+/// A motor joint is used to control the relative motion
+/// between two bodies. A typical usage is to control the movement
+/// of a dynamic body with respect to the ground.
+class B2_API b2MotorJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// Set/get the target linear offset, in frame A, in meters.
+ void SetLinearOffset(const b2Vec2& linearOffset);
+ const b2Vec2& GetLinearOffset() const;
+
+ /// Set/get the target angular offset, in radians.
+ void SetAngularOffset(float angularOffset);
+ float GetAngularOffset() const;
+
+ /// Set the maximum friction force in N.
+ void SetMaxForce(float force);
+
+ /// Get the maximum friction force in N.
+ float GetMaxForce() const;
+
+ /// Set the maximum friction torque in N*m.
+ void SetMaxTorque(float torque);
+
+ /// Get the maximum friction torque in N*m.
+ float GetMaxTorque() const;
+
+ /// Set the position correction factor in the range [0,1].
+ void SetCorrectionFactor(float factor);
+
+ /// Get the position correction factor in the range [0,1].
+ float GetCorrectionFactor() const;
+
+ /// Dump to b2Log
+ void Dump() override;
+
+protected:
+
+ friend class b2Joint;
+
+ b2MotorJoint(const b2MotorJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ // Solver shared
+ b2Vec2 m_linearOffset;
+ float m_angularOffset;
+ b2Vec2 m_linearImpulse;
+ float m_angularImpulse;
+ float m_maxForce;
+ float m_maxTorque;
+ float m_correctionFactor;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_rA;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ b2Vec2 m_linearError;
+ float m_angularError;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ b2Mat22 m_linearMass;
+ float m_angularMass;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_mouse_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_mouse_joint.h
new file mode 100644
index 0000000..fcbc56a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_mouse_joint.h
@@ -0,0 +1,134 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_MOUSE_JOINT_H
+#define B2_MOUSE_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Mouse joint definition. This requires a world target point,
+/// tuning parameters, and the time step.
+struct B2_API b2MouseJointDef : public b2JointDef
+{
+ b2MouseJointDef()
+ {
+ type = e_mouseJoint;
+ target.Set(0.0f, 0.0f);
+ maxForce = 0.0f;
+ stiffness = 0.0f;
+ damping = 0.0f;
+ }
+
+ /// The initial world target point. This is assumed
+ /// to coincide with the body anchor initially.
+ b2Vec2 target;
+
+ /// The maximum constraint force that can be exerted
+ /// to move the candidate body. Usually you will express
+ /// as some multiple of the weight (multiplier * mass * gravity).
+ float maxForce;
+
+ /// The linear stiffness in N/m
+ float stiffness;
+
+ /// The linear damping in N*s/m
+ float damping;
+};
+
+/// A mouse joint is used to make a point on a body track a
+/// specified world point. This a soft constraint with a maximum
+/// force. This allows the constraint to stretch and without
+/// applying huge forces.
+/// NOTE: this joint is not documented in the manual because it was
+/// developed to be used in the testbed. If you want to learn how to
+/// use the mouse joint, look at the testbed.
+class B2_API b2MouseJoint : public b2Joint
+{
+public:
+
+ /// Implements b2Joint.
+ b2Vec2 GetAnchorA() const override;
+
+ /// Implements b2Joint.
+ b2Vec2 GetAnchorB() const override;
+
+ /// Implements b2Joint.
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+
+ /// Implements b2Joint.
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// Use this to update the target point.
+ void SetTarget(const b2Vec2& target);
+ const b2Vec2& GetTarget() const;
+
+ /// Set/get the maximum force in Newtons.
+ void SetMaxForce(float force);
+ float GetMaxForce() const;
+
+ /// Set/get the linear stiffness in N/m
+ void SetStiffness(float stiffness) { m_stiffness = stiffness; }
+ float GetStiffness() const { return m_stiffness; }
+
+ /// Set/get linear damping in N*s/m
+ void SetDamping(float damping) { m_damping = damping; }
+ float GetDamping() const { return m_damping; }
+
+ /// The mouse joint does not support dumping.
+ void Dump() override { b2Log("Mouse joint dumping is not supported.\n"); }
+
+ /// Implement b2Joint::ShiftOrigin
+ void ShiftOrigin(const b2Vec2& newOrigin) override;
+
+protected:
+ friend class b2Joint;
+
+ b2MouseJoint(const b2MouseJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ b2Vec2 m_localAnchorB;
+ b2Vec2 m_targetA;
+ float m_stiffness;
+ float m_damping;
+ float m_beta;
+
+ // Solver shared
+ b2Vec2 m_impulse;
+ float m_maxForce;
+ float m_gamma;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterB;
+ float m_invMassB;
+ float m_invIB;
+ b2Mat22 m_mass;
+ b2Vec2 m_C;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_polygon_shape.h b/Client/ThirdParty/Box2D/include/box2d/b2_polygon_shape.h
new file mode 100644
index 0000000..5a4e563
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_polygon_shape.h
@@ -0,0 +1,95 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+#ifndef B2_POLYGON_SHAPE_H
+#define B2_POLYGON_SHAPE_H
+
+#include "b2_api.h"
+#include "b2_shape.h"
+
+/// A solid convex polygon. It is assumed that the interior of the polygon is to
+/// the left of each edge.
+/// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices.
+/// In most cases you should not need many vertices for a convex polygon.
+class B2_API b2PolygonShape : public b2Shape
+{
+public:
+ b2PolygonShape();
+
+ /// Implement b2Shape.
+ b2Shape* Clone(b2BlockAllocator* allocator) const override;
+
+ /// @see b2Shape::GetChildCount
+ int32 GetChildCount() const override;
+
+ /// Create a convex hull from the given array of local points.
+ /// The count must be in the range [3, b2_maxPolygonVertices].
+ /// @warning the points may be re-ordered, even if they form a convex polygon
+ /// @warning collinear points are handled but not removed. Collinear points
+ /// may lead to poor stacking behavior.
+ void Set(const b2Vec2* points, int32 count);
+
+ /// Build vertices to represent an axis-aligned box centered on the local origin.
+ /// @param hx the half-width.
+ /// @param hy the half-height.
+ void SetAsBox(float hx, float hy);
+
+ /// Build vertices to represent an oriented box.
+ /// @param hx the half-width.
+ /// @param hy the half-height.
+ /// @param center the center of the box in local coordinates.
+ /// @param angle the rotation of the box in local coordinates.
+ void SetAsBox(float hx, float hy, const b2Vec2& center, float angle);
+
+ /// @see b2Shape::TestPoint
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override;
+
+ /// Implement b2Shape.
+ /// @note because the polygon is solid, rays that start inside do not hit because the normal is
+ /// not defined.
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeAABB
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override;
+
+ /// @see b2Shape::ComputeMass
+ void ComputeMass(b2MassData* massData, float density) const override;
+
+ /// Validate convexity. This is a very time consuming operation.
+ /// @returns true if valid
+ bool Validate() const;
+
+ b2Vec2 m_centroid;
+ b2Vec2 m_vertices[b2_maxPolygonVertices];
+ b2Vec2 m_normals[b2_maxPolygonVertices];
+ int32 m_count;
+};
+
+inline b2PolygonShape::b2PolygonShape()
+{
+ m_type = e_polygon;
+ m_radius = b2_polygonRadius;
+ m_count = 0;
+ m_centroid.SetZero();
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_prismatic_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_prismatic_joint.h
new file mode 100644
index 0000000..9d12d21
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_prismatic_joint.h
@@ -0,0 +1,205 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_PRISMATIC_JOINT_H
+#define B2_PRISMATIC_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Prismatic joint definition. This requires defining a line of
+/// motion using an axis and an anchor point. The definition uses local
+/// anchor points and a local axis so that the initial configuration
+/// can violate the constraint slightly. The joint translation is zero
+/// when the local anchor points coincide in world space. Using local
+/// anchors and a local axis helps when saving and loading a game.
+struct B2_API b2PrismaticJointDef : public b2JointDef
+{
+ b2PrismaticJointDef()
+ {
+ type = e_prismaticJoint;
+ localAnchorA.SetZero();
+ localAnchorB.SetZero();
+ localAxisA.Set(1.0f, 0.0f);
+ referenceAngle = 0.0f;
+ enableLimit = false;
+ lowerTranslation = 0.0f;
+ upperTranslation = 0.0f;
+ enableMotor = false;
+ maxMotorForce = 0.0f;
+ motorSpeed = 0.0f;
+ }
+
+ /// Initialize the bodies, anchors, axis, and reference angle using the world
+ /// anchor and unit world axis.
+ void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor, const b2Vec2& axis);
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The local translation unit axis in bodyA.
+ b2Vec2 localAxisA;
+
+ /// The constrained angle between the bodies: bodyB_angle - bodyA_angle.
+ float referenceAngle;
+
+ /// Enable/disable the joint limit.
+ bool enableLimit;
+
+ /// The lower translation limit, usually in meters.
+ float lowerTranslation;
+
+ /// The upper translation limit, usually in meters.
+ float upperTranslation;
+
+ /// Enable/disable the joint motor.
+ bool enableMotor;
+
+ /// The maximum motor torque, usually in N-m.
+ float maxMotorForce;
+
+ /// The desired motor speed in radians per second.
+ float motorSpeed;
+};
+
+/// A prismatic joint. This joint provides one degree of freedom: translation
+/// along an axis fixed in bodyA. Relative rotation is prevented. You can
+/// use a joint limit to restrict the range of motion and a joint motor to
+/// drive the motion or to model joint friction.
+class B2_API b2PrismaticJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// The local anchor point relative to bodyA's origin.
+ const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; }
+
+ /// The local anchor point relative to bodyB's origin.
+ const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; }
+
+ /// The local joint axis relative to bodyA.
+ const b2Vec2& GetLocalAxisA() const { return m_localXAxisA; }
+
+ /// Get the reference angle.
+ float GetReferenceAngle() const { return m_referenceAngle; }
+
+ /// Get the current joint translation, usually in meters.
+ float GetJointTranslation() const;
+
+ /// Get the current joint translation speed, usually in meters per second.
+ float GetJointSpeed() const;
+
+ /// Is the joint limit enabled?
+ bool IsLimitEnabled() const;
+
+ /// Enable/disable the joint limit.
+ void EnableLimit(bool flag);
+
+ /// Get the lower joint limit, usually in meters.
+ float GetLowerLimit() const;
+
+ /// Get the upper joint limit, usually in meters.
+ float GetUpperLimit() const;
+
+ /// Set the joint limits, usually in meters.
+ void SetLimits(float lower, float upper);
+
+ /// Is the joint motor enabled?
+ bool IsMotorEnabled() const;
+
+ /// Enable/disable the joint motor.
+ void EnableMotor(bool flag);
+
+ /// Set the motor speed, usually in meters per second.
+ void SetMotorSpeed(float speed);
+
+ /// Get the motor speed, usually in meters per second.
+ float GetMotorSpeed() const;
+
+ /// Set the maximum motor force, usually in N.
+ void SetMaxMotorForce(float force);
+ float GetMaxMotorForce() const { return m_maxMotorForce; }
+
+ /// Get the current motor force given the inverse time step, usually in N.
+ float GetMotorForce(float inv_dt) const;
+
+ /// Dump to b2Log
+ void Dump() override;
+
+ ///
+ void Draw(b2Draw* draw) const override;
+
+protected:
+ friend class b2Joint;
+ friend class b2GearJoint;
+ b2PrismaticJoint(const b2PrismaticJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ b2Vec2 m_localXAxisA;
+ b2Vec2 m_localYAxisA;
+ float m_referenceAngle;
+ b2Vec2 m_impulse;
+ float m_motorImpulse;
+ float m_lowerImpulse;
+ float m_upperImpulse;
+ float m_lowerTranslation;
+ float m_upperTranslation;
+ float m_maxMotorForce;
+ float m_motorSpeed;
+ bool m_enableLimit;
+ bool m_enableMotor;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ b2Vec2 m_axis, m_perp;
+ float m_s1, m_s2;
+ float m_a1, m_a2;
+ b2Mat22 m_K;
+ float m_translation;
+ float m_axialMass;
+};
+
+inline float b2PrismaticJoint::GetMotorSpeed() const
+{
+ return m_motorSpeed;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_pulley_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_pulley_joint.h
new file mode 100644
index 0000000..6b14456
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_pulley_joint.h
@@ -0,0 +1,157 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_PULLEY_JOINT_H
+#define B2_PULLEY_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+const float b2_minPulleyLength = 2.0f;
+
+/// Pulley joint definition. This requires two ground anchors,
+/// two dynamic body anchor points, and a pulley ratio.
+struct B2_API b2PulleyJointDef : public b2JointDef
+{
+ b2PulleyJointDef()
+ {
+ type = e_pulleyJoint;
+ groundAnchorA.Set(-1.0f, 1.0f);
+ groundAnchorB.Set(1.0f, 1.0f);
+ localAnchorA.Set(-1.0f, 0.0f);
+ localAnchorB.Set(1.0f, 0.0f);
+ lengthA = 0.0f;
+ lengthB = 0.0f;
+ ratio = 1.0f;
+ collideConnected = true;
+ }
+
+ /// Initialize the bodies, anchors, lengths, max lengths, and ratio using the world anchors.
+ void Initialize(b2Body* bodyA, b2Body* bodyB,
+ const b2Vec2& groundAnchorA, const b2Vec2& groundAnchorB,
+ const b2Vec2& anchorA, const b2Vec2& anchorB,
+ float ratio);
+
+ /// The first ground anchor in world coordinates. This point never moves.
+ b2Vec2 groundAnchorA;
+
+ /// The second ground anchor in world coordinates. This point never moves.
+ b2Vec2 groundAnchorB;
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The a reference length for the segment attached to bodyA.
+ float lengthA;
+
+ /// The a reference length for the segment attached to bodyB.
+ float lengthB;
+
+ /// The pulley ratio, used to simulate a block-and-tackle.
+ float ratio;
+};
+
+/// The pulley joint is connected to two bodies and two fixed ground points.
+/// The pulley supports a ratio such that:
+/// length1 + ratio * length2 <= constant
+/// Yes, the force transmitted is scaled by the ratio.
+/// Warning: the pulley joint can get a bit squirrelly by itself. They often
+/// work better when combined with prismatic joints. You should also cover the
+/// the anchor points with static shapes to prevent one side from going to
+/// zero length.
+class B2_API b2PulleyJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// Get the first ground anchor.
+ b2Vec2 GetGroundAnchorA() const;
+
+ /// Get the second ground anchor.
+ b2Vec2 GetGroundAnchorB() const;
+
+ /// Get the current length of the segment attached to bodyA.
+ float GetLengthA() const;
+
+ /// Get the current length of the segment attached to bodyB.
+ float GetLengthB() const;
+
+ /// Get the pulley ratio.
+ float GetRatio() const;
+
+ /// Get the current length of the segment attached to bodyA.
+ float GetCurrentLengthA() const;
+
+ /// Get the current length of the segment attached to bodyB.
+ float GetCurrentLengthB() const;
+
+ /// Dump joint to dmLog
+ void Dump() override;
+
+ /// Implement b2Joint::ShiftOrigin
+ void ShiftOrigin(const b2Vec2& newOrigin) override;
+
+protected:
+
+ friend class b2Joint;
+ b2PulleyJoint(const b2PulleyJointDef* data);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ b2Vec2 m_groundAnchorA;
+ b2Vec2 m_groundAnchorB;
+ float m_lengthA;
+ float m_lengthB;
+
+ // Solver shared
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ float m_constant;
+ float m_ratio;
+ float m_impulse;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_uA;
+ b2Vec2 m_uB;
+ b2Vec2 m_rA;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ float m_mass;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_revolute_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_revolute_joint.h
new file mode 100644
index 0000000..36ad531
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_revolute_joint.h
@@ -0,0 +1,211 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_REVOLUTE_JOINT_H
+#define B2_REVOLUTE_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Revolute joint definition. This requires defining an anchor point where the
+/// bodies are joined. The definition uses local anchor points so that the
+/// initial configuration can violate the constraint slightly. You also need to
+/// specify the initial relative angle for joint limits. This helps when saving
+/// and loading a game.
+/// The local anchor points are measured from the body's origin
+/// rather than the center of mass because:
+/// 1. you might not know where the center of mass will be.
+/// 2. if you add/remove shapes from a body and recompute the mass,
+/// the joints will be broken.
+struct B2_API b2RevoluteJointDef : public b2JointDef
+{
+ b2RevoluteJointDef()
+ {
+ type = e_revoluteJoint;
+ localAnchorA.Set(0.0f, 0.0f);
+ localAnchorB.Set(0.0f, 0.0f);
+ referenceAngle = 0.0f;
+ lowerAngle = 0.0f;
+ upperAngle = 0.0f;
+ maxMotorTorque = 0.0f;
+ motorSpeed = 0.0f;
+ enableLimit = false;
+ enableMotor = false;
+ }
+
+ /// Initialize the bodies, anchors, and reference angle using a world
+ /// anchor point.
+ void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor);
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The bodyB angle minus bodyA angle in the reference state (radians).
+ float referenceAngle;
+
+ /// A flag to enable joint limits.
+ bool enableLimit;
+
+ /// The lower angle for the joint limit (radians).
+ float lowerAngle;
+
+ /// The upper angle for the joint limit (radians).
+ float upperAngle;
+
+ /// A flag to enable the joint motor.
+ bool enableMotor;
+
+ /// The desired motor speed. Usually in radians per second.
+ float motorSpeed;
+
+ /// The maximum motor torque used to achieve the desired motor speed.
+ /// Usually in N-m.
+ float maxMotorTorque;
+};
+
+/// A revolute joint constrains two bodies to share a common point while they
+/// are free to rotate about the point. The relative rotation about the shared
+/// point is the joint angle. You can limit the relative rotation with
+/// a joint limit that specifies a lower and upper angle. You can use a motor
+/// to drive the relative rotation about the shared point. A maximum motor torque
+/// is provided so that infinite forces are not generated.
+class B2_API b2RevoluteJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ /// The local anchor point relative to bodyA's origin.
+ const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; }
+
+ /// The local anchor point relative to bodyB's origin.
+ const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; }
+
+ /// Get the reference angle.
+ float GetReferenceAngle() const { return m_referenceAngle; }
+
+ /// Get the current joint angle in radians.
+ float GetJointAngle() const;
+
+ /// Get the current joint angle speed in radians per second.
+ float GetJointSpeed() const;
+
+ /// Is the joint limit enabled?
+ bool IsLimitEnabled() const;
+
+ /// Enable/disable the joint limit.
+ void EnableLimit(bool flag);
+
+ /// Get the lower joint limit in radians.
+ float GetLowerLimit() const;
+
+ /// Get the upper joint limit in radians.
+ float GetUpperLimit() const;
+
+ /// Set the joint limits in radians.
+ void SetLimits(float lower, float upper);
+
+ /// Is the joint motor enabled?
+ bool IsMotorEnabled() const;
+
+ /// Enable/disable the joint motor.
+ void EnableMotor(bool flag);
+
+ /// Set the motor speed in radians per second.
+ void SetMotorSpeed(float speed);
+
+ /// Get the motor speed in radians per second.
+ float GetMotorSpeed() const;
+
+ /// Set the maximum motor torque, usually in N-m.
+ void SetMaxMotorTorque(float torque);
+ float GetMaxMotorTorque() const { return m_maxMotorTorque; }
+
+ /// Get the reaction force given the inverse time step.
+ /// Unit is N.
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+
+ /// Get the reaction torque due to the joint limit given the inverse time step.
+ /// Unit is N*m.
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// Get the current motor torque given the inverse time step.
+ /// Unit is N*m.
+ float GetMotorTorque(float inv_dt) const;
+
+ /// Dump to b2Log.
+ void Dump() override;
+
+ ///
+ void Draw(b2Draw* draw) const override;
+
+protected:
+
+ friend class b2Joint;
+ friend class b2GearJoint;
+
+ b2RevoluteJoint(const b2RevoluteJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ // Solver shared
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ b2Vec2 m_impulse;
+ float m_motorImpulse;
+ float m_lowerImpulse;
+ float m_upperImpulse;
+ bool m_enableMotor;
+ float m_maxMotorTorque;
+ float m_motorSpeed;
+ bool m_enableLimit;
+ float m_referenceAngle;
+ float m_lowerAngle;
+ float m_upperAngle;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_rA;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ b2Mat22 m_K;
+ float m_angle;
+ float m_axialMass;
+};
+
+inline float b2RevoluteJoint::GetMotorSpeed() const
+{
+ return m_motorSpeed;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_rope.h b/Client/ThirdParty/Box2D/include/box2d/b2_rope.h
new file mode 100644
index 0000000..47f5fc4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_rope.h
@@ -0,0 +1,153 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_ROPE_H
+#define B2_ROPE_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+
+class b2Draw;
+struct b2RopeStretch;
+struct b2RopeBend;
+
+enum b2StretchingModel
+{
+ b2_pbdStretchingModel,
+ b2_xpbdStretchingModel
+};
+
+enum b2BendingModel
+{
+ b2_springAngleBendingModel = 0,
+ b2_pbdAngleBendingModel,
+ b2_xpbdAngleBendingModel,
+ b2_pbdDistanceBendingModel,
+ b2_pbdHeightBendingModel,
+ b2_pbdTriangleBendingModel
+};
+
+///
+struct B2_API b2RopeTuning
+{
+ b2RopeTuning()
+ {
+ stretchingModel = b2_pbdStretchingModel;
+ bendingModel = b2_pbdAngleBendingModel;
+ damping = 0.0f;
+ stretchStiffness = 1.0f;
+ bendStiffness = 0.5f;
+ bendHertz = 1.0f;
+ bendDamping = 0.0f;
+ isometric = false;
+ fixedEffectiveMass = false;
+ warmStart = false;
+ }
+
+ b2StretchingModel stretchingModel;
+ b2BendingModel bendingModel;
+ float damping;
+ float stretchStiffness;
+ float stretchHertz;
+ float stretchDamping;
+ float bendStiffness;
+ float bendHertz;
+ float bendDamping;
+ bool isometric;
+ bool fixedEffectiveMass;
+ bool warmStart;
+};
+
+///
+struct B2_API b2RopeDef
+{
+ b2RopeDef()
+ {
+ position.SetZero();
+ vertices = nullptr;
+ count = 0;
+ masses = nullptr;
+ gravity.SetZero();
+ }
+
+ b2Vec2 position;
+ b2Vec2* vertices;
+ int32 count;
+ float* masses;
+ b2Vec2 gravity;
+ b2RopeTuning tuning;
+};
+
+///
+class B2_API b2Rope
+{
+public:
+ b2Rope();
+ ~b2Rope();
+
+ ///
+ void Create(const b2RopeDef& def);
+
+ ///
+ void SetTuning(const b2RopeTuning& tuning);
+
+ ///
+ void Step(float timeStep, int32 iterations, const b2Vec2& position);
+
+ ///
+ void Reset(const b2Vec2& position);
+
+ ///
+ void Draw(b2Draw* draw) const;
+
+private:
+
+ void SolveStretch_PBD();
+ void SolveStretch_XPBD(float dt);
+ void SolveBend_PBD_Angle();
+ void SolveBend_XPBD_Angle(float dt);
+ void SolveBend_PBD_Distance();
+ void SolveBend_PBD_Height();
+ void SolveBend_PBD_Triangle();
+ void ApplyBendForces(float dt);
+
+ b2Vec2 m_position;
+
+ int32 m_count;
+ int32 m_stretchCount;
+ int32 m_bendCount;
+
+ b2RopeStretch* m_stretchConstraints;
+ b2RopeBend* m_bendConstraints;
+
+ b2Vec2* m_bindPositions;
+ b2Vec2* m_ps;
+ b2Vec2* m_p0s;
+ b2Vec2* m_vs;
+
+ float* m_invMasses;
+ b2Vec2 m_gravity;
+
+ b2RopeTuning m_tuning;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_settings.h b/Client/ThirdParty/Box2D/include/box2d/b2_settings.h
new file mode 100644
index 0000000..48cd95d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_settings.h
@@ -0,0 +1,127 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_SETTINGS_H
+#define B2_SETTINGS_H
+
+#include "b2_types.h"
+#include "b2_api.h"
+
+/// @file
+/// Settings that can be overriden for your application
+///
+
+/// Define this macro in your build if you want to override settings
+#ifdef B2_USER_SETTINGS
+
+/// This is a user file that includes custom definitions of the macros, structs, and functions
+/// defined below.
+#include "b2_user_settings.h"
+
+#else
+
+#include <stdarg.h>
+#include <stdint.h>
+
+// Tunable Constants
+
+/// You can use this to change the length scale used by your game.
+/// For example for inches you could use 39.4.
+#define b2_lengthUnitsPerMeter 1.0f
+
+/// The maximum number of vertices on a convex polygon. You cannot increase
+/// this too much because b2BlockAllocator has a maximum object size.
+#define b2_maxPolygonVertices 8
+
+// User data
+
+/// You can define this to inject whatever data you want in b2Body
+struct B2_API b2BodyUserData
+{
+ b2BodyUserData()
+ {
+ pointer = 0;
+ }
+
+ /// For legacy compatibility
+ uintptr_t pointer;
+};
+
+/// You can define this to inject whatever data you want in b2Fixture
+struct B2_API b2FixtureUserData
+{
+ b2FixtureUserData()
+ {
+ pointer = 0;
+ }
+
+ /// For legacy compatibility
+ uintptr_t pointer;
+};
+
+/// You can define this to inject whatever data you want in b2Joint
+struct B2_API b2JointUserData
+{
+ b2JointUserData()
+ {
+ pointer = 0;
+ }
+
+ /// For legacy compatibility
+ uintptr_t pointer;
+};
+
+// Memory Allocation
+
+/// Default allocation functions
+B2_API void* b2Alloc_Default(int32 size);
+B2_API void b2Free_Default(void* mem);
+
+/// Implement this function to use your own memory allocator.
+inline void* b2Alloc(int32 size)
+{
+ return b2Alloc_Default(size);
+}
+
+/// If you implement b2Alloc, you should also implement this function.
+inline void b2Free(void* mem)
+{
+ b2Free_Default(mem);
+}
+
+/// Default logging function
+B2_API void b2Log_Default(const char* string, va_list args);
+
+/// Implement this to use your own logging.
+inline void b2Log(const char* string, ...)
+{
+ va_list args;
+ va_start(args, string);
+ b2Log_Default(string, args);
+ va_end(args);
+}
+
+#endif // B2_USER_SETTINGS
+
+#include "b2_common.h"
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_shape.h b/Client/ThirdParty/Box2D/include/box2d/b2_shape.h
new file mode 100644
index 0000000..cbed2b8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_shape.h
@@ -0,0 +1,110 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_SHAPE_H
+#define B2_SHAPE_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+#include "b2_collision.h"
+
+class b2BlockAllocator;
+
+/// This holds the mass data computed for a shape.
+struct B2_API b2MassData
+{
+ /// The mass of the shape, usually in kilograms.
+ float mass;
+
+ /// The position of the shape's centroid relative to the shape's origin.
+ b2Vec2 center;
+
+ /// The rotational inertia of the shape about the local origin.
+ float I;
+};
+
+/// A shape is used for collision detection. You can create a shape however you like.
+/// Shapes used for simulation in b2World are created automatically when a b2Fixture
+/// is created. Shapes may encapsulate a one or more child shapes.
+class B2_API b2Shape
+{
+public:
+
+ enum Type
+ {
+ e_circle = 0,
+ e_edge = 1,
+ e_polygon = 2,
+ e_chain = 3,
+ e_typeCount = 4
+ };
+
+ virtual ~b2Shape() {}
+
+ /// Clone the concrete shape using the provided allocator.
+ virtual b2Shape* Clone(b2BlockAllocator* allocator) const = 0;
+
+ /// Get the type of this shape. You can use this to down cast to the concrete shape.
+ /// @return the shape type.
+ Type GetType() const;
+
+ /// Get the number of child primitives.
+ virtual int32 GetChildCount() const = 0;
+
+ /// Test a point for containment in this shape. This only works for convex shapes.
+ /// @param xf the shape world transform.
+ /// @param p a point in world coordinates.
+ virtual bool TestPoint(const b2Transform& xf, const b2Vec2& p) const = 0;
+
+ /// Cast a ray against a child shape.
+ /// @param output the ray-cast results.
+ /// @param input the ray-cast input parameters.
+ /// @param transform the transform to be applied to the shape.
+ /// @param childIndex the child shape index
+ virtual bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& transform, int32 childIndex) const = 0;
+
+ /// Given a transform, compute the associated axis aligned bounding box for a child shape.
+ /// @param aabb returns the axis aligned box.
+ /// @param xf the world transform of the shape.
+ /// @param childIndex the child shape
+ virtual void ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const = 0;
+
+ /// Compute the mass properties of this shape using its dimensions and density.
+ /// The inertia tensor is computed about the local origin.
+ /// @param massData returns the mass data for this shape.
+ /// @param density the density in kilograms per meter squared.
+ virtual void ComputeMass(b2MassData* massData, float density) const = 0;
+
+ Type m_type;
+
+ /// Radius of a shape. For polygonal shapes this must be b2_polygonRadius. There is no support for
+ /// making rounded polygons.
+ float m_radius;
+};
+
+inline b2Shape::Type b2Shape::GetType() const
+{
+ return m_type;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_stack_allocator.h b/Client/ThirdParty/Box2D/include/box2d/b2_stack_allocator.h
new file mode 100644
index 0000000..1db2af5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_stack_allocator.h
@@ -0,0 +1,65 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_STACK_ALLOCATOR_H
+#define B2_STACK_ALLOCATOR_H
+
+#include "b2_api.h"
+#include "b2_settings.h"
+
+const int32 b2_stackSize = 100 * 1024; // 100k
+const int32 b2_maxStackEntries = 32;
+
+struct B2_API b2StackEntry
+{
+ char* data;
+ int32 size;
+ bool usedMalloc;
+};
+
+// This is a stack allocator used for fast per step allocations.
+// You must nest allocate/free pairs. The code will assert
+// if you try to interleave multiple allocate/free pairs.
+class B2_API b2StackAllocator
+{
+public:
+ b2StackAllocator();
+ ~b2StackAllocator();
+
+ void* Allocate(int32 size);
+ void Free(void* p);
+
+ int32 GetMaxAllocation() const;
+
+private:
+
+ char m_data[b2_stackSize];
+ int32 m_index;
+
+ int32 m_allocation;
+ int32 m_maxAllocation;
+
+ b2StackEntry m_entries[b2_maxStackEntries];
+ int32 m_entryCount;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_time_of_impact.h b/Client/ThirdParty/Box2D/include/box2d/b2_time_of_impact.h
new file mode 100644
index 0000000..04d4626
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_time_of_impact.h
@@ -0,0 +1,63 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_TIME_OF_IMPACT_H
+#define B2_TIME_OF_IMPACT_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+#include "b2_distance.h"
+
+/// Input parameters for b2TimeOfImpact
+struct B2_API b2TOIInput
+{
+ b2DistanceProxy proxyA;
+ b2DistanceProxy proxyB;
+ b2Sweep sweepA;
+ b2Sweep sweepB;
+ float tMax; // defines sweep interval [0, tMax]
+};
+
+/// Output parameters for b2TimeOfImpact.
+struct B2_API b2TOIOutput
+{
+ enum State
+ {
+ e_unknown,
+ e_failed,
+ e_overlapped,
+ e_touching,
+ e_separated
+ };
+
+ State state;
+ float t;
+};
+
+/// Compute the upper bound on time before two shapes penetrate. Time is represented as
+/// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate,
+/// non-tunneling collisions. If you change the time interval, you should call this function
+/// again.
+/// Note: use b2Distance to compute the contact point and normal at the time of impact.
+B2_API void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input);
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_time_step.h b/Client/ThirdParty/Box2D/include/box2d/b2_time_step.h
new file mode 100644
index 0000000..13d6292
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_time_step.h
@@ -0,0 +1,74 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+#ifndef B2_TIME_STEP_H
+#define B2_TIME_STEP_H
+
+#include "b2_api.h"
+#include "b2_math.h"
+
+/// Profiling data. Times are in milliseconds.
+struct B2_API b2Profile
+{
+ float step;
+ float collide;
+ float solve;
+ float solveInit;
+ float solveVelocity;
+ float solvePosition;
+ float broadphase;
+ float solveTOI;
+};
+
+/// This is an internal structure.
+struct B2_API b2TimeStep
+{
+ float dt; // time step
+ float inv_dt; // inverse time step (0 if dt == 0).
+ float dtRatio; // dt * inv_dt0
+ int32 velocityIterations;
+ int32 positionIterations;
+ bool warmStarting;
+};
+
+/// This is an internal structure.
+struct B2_API b2Position
+{
+ b2Vec2 c;
+ float a;
+};
+
+/// This is an internal structure.
+struct B2_API b2Velocity
+{
+ b2Vec2 v;
+ float w;
+};
+
+/// Solver Data
+struct B2_API b2SolverData
+{
+ b2TimeStep step;
+ b2Position* positions;
+ b2Velocity* velocities;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_timer.h b/Client/ThirdParty/Box2D/include/box2d/b2_timer.h
new file mode 100644
index 0000000..7893c32
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_timer.h
@@ -0,0 +1,55 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_TIMER_H
+#define B2_TIMER_H
+
+#include "b2_api.h"
+#include "b2_settings.h"
+
+/// Timer for profiling. This has platform specific code and may
+/// not work on every platform.
+class B2_API b2Timer
+{
+public:
+
+ /// Constructor
+ b2Timer();
+
+ /// Reset the timer.
+ void Reset();
+
+ /// Get the time since construction or the last reset.
+ float GetMilliseconds() const;
+
+private:
+
+#if defined(_WIN32)
+ double m_start;
+ static double s_invFrequency;
+#elif defined(__linux__) || defined (__APPLE__)
+ unsigned long long m_start_sec;
+ unsigned long long m_start_usec;
+#endif
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_types.h b/Client/ThirdParty/Box2D/include/box2d/b2_types.h
new file mode 100644
index 0000000..e0d4377
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_types.h
@@ -0,0 +1,33 @@
+// MIT License
+
+// Copyright (c) 2020 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_TYPES_H
+#define B2_TYPES_H
+
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_weld_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_weld_joint.h
new file mode 100644
index 0000000..f226c8a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_weld_joint.h
@@ -0,0 +1,133 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_WELD_JOINT_H
+#define B2_WELD_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Weld joint definition. You need to specify local anchor points
+/// where they are attached and the relative body angle. The position
+/// of the anchor points is important for computing the reaction torque.
+struct B2_API b2WeldJointDef : public b2JointDef
+{
+ b2WeldJointDef()
+ {
+ type = e_weldJoint;
+ localAnchorA.Set(0.0f, 0.0f);
+ localAnchorB.Set(0.0f, 0.0f);
+ referenceAngle = 0.0f;
+ stiffness = 0.0f;
+ damping = 0.0f;
+ }
+
+ /// Initialize the bodies, anchors, reference angle, stiffness, and damping.
+ /// @param bodyA the first body connected by this joint
+ /// @param bodyB the second body connected by this joint
+ /// @param anchor the point of connection in world coordinates
+ void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor);
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The bodyB angle minus bodyA angle in the reference state (radians).
+ float referenceAngle;
+
+ /// The rotational stiffness in N*m
+ /// Disable softness with a value of 0
+ float stiffness;
+
+ /// The rotational damping in N*m*s
+ float damping;
+};
+
+/// A weld joint essentially glues two bodies together. A weld joint may
+/// distort somewhat because the island constraint solver is approximate.
+class B2_API b2WeldJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// The local anchor point relative to bodyA's origin.
+ const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; }
+
+ /// The local anchor point relative to bodyB's origin.
+ const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; }
+
+ /// Get the reference angle.
+ float GetReferenceAngle() const { return m_referenceAngle; }
+
+ /// Set/get stiffness in N*m
+ void SetStiffness(float hz) { m_stiffness = hz; }
+ float GetStiffness() const { return m_stiffness; }
+
+ /// Set/get damping in N*m*s
+ void SetDamping(float damping) { m_damping = damping; }
+ float GetDamping() const { return m_damping; }
+
+ /// Dump to b2Log
+ void Dump() override;
+
+protected:
+
+ friend class b2Joint;
+
+ b2WeldJoint(const b2WeldJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ float m_stiffness;
+ float m_damping;
+ float m_bias;
+
+ // Solver shared
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ float m_referenceAngle;
+ float m_gamma;
+ b2Vec3 m_impulse;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_rA;
+ b2Vec2 m_rB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+ b2Mat33 m_mass;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_wheel_joint.h b/Client/ThirdParty/Box2D/include/box2d/b2_wheel_joint.h
new file mode 100644
index 0000000..8576adb
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_wheel_joint.h
@@ -0,0 +1,240 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_WHEEL_JOINT_H
+#define B2_WHEEL_JOINT_H
+
+#include "b2_api.h"
+#include "b2_joint.h"
+
+/// Wheel joint definition. This requires defining a line of
+/// motion using an axis and an anchor point. The definition uses local
+/// anchor points and a local axis so that the initial configuration
+/// can violate the constraint slightly. The joint translation is zero
+/// when the local anchor points coincide in world space. Using local
+/// anchors and a local axis helps when saving and loading a game.
+struct B2_API b2WheelJointDef : public b2JointDef
+{
+ b2WheelJointDef()
+ {
+ type = e_wheelJoint;
+ localAnchorA.SetZero();
+ localAnchorB.SetZero();
+ localAxisA.Set(1.0f, 0.0f);
+ enableLimit = false;
+ lowerTranslation = 0.0f;
+ upperTranslation = 0.0f;
+ enableMotor = false;
+ maxMotorTorque = 0.0f;
+ motorSpeed = 0.0f;
+ stiffness = 0.0f;
+ damping = 0.0f;
+ }
+
+ /// Initialize the bodies, anchors, axis, and reference angle using the world
+ /// anchor and world axis.
+ void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor, const b2Vec2& axis);
+
+ /// The local anchor point relative to bodyA's origin.
+ b2Vec2 localAnchorA;
+
+ /// The local anchor point relative to bodyB's origin.
+ b2Vec2 localAnchorB;
+
+ /// The local translation axis in bodyA.
+ b2Vec2 localAxisA;
+
+ /// Enable/disable the joint limit.
+ bool enableLimit;
+
+ /// The lower translation limit, usually in meters.
+ float lowerTranslation;
+
+ /// The upper translation limit, usually in meters.
+ float upperTranslation;
+
+ /// Enable/disable the joint motor.
+ bool enableMotor;
+
+ /// The maximum motor torque, usually in N-m.
+ float maxMotorTorque;
+
+ /// The desired motor speed in radians per second.
+ float motorSpeed;
+
+ /// Suspension stiffness. Typically in units N/m.
+ float stiffness;
+
+ /// Suspension damping. Typically in units of N*s/m.
+ float damping;
+};
+
+/// A wheel joint. This joint provides two degrees of freedom: translation
+/// along an axis fixed in bodyA and rotation in the plane. In other words, it is a point to
+/// line constraint with a rotational motor and a linear spring/damper. The spring/damper is
+/// initialized upon creation. This joint is designed for vehicle suspensions.
+class B2_API b2WheelJoint : public b2Joint
+{
+public:
+ b2Vec2 GetAnchorA() const override;
+ b2Vec2 GetAnchorB() const override;
+
+ b2Vec2 GetReactionForce(float inv_dt) const override;
+ float GetReactionTorque(float inv_dt) const override;
+
+ /// The local anchor point relative to bodyA's origin.
+ const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; }
+
+ /// The local anchor point relative to bodyB's origin.
+ const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; }
+
+ /// The local joint axis relative to bodyA.
+ const b2Vec2& GetLocalAxisA() const { return m_localXAxisA; }
+
+ /// Get the current joint translation, usually in meters.
+ float GetJointTranslation() const;
+
+ /// Get the current joint linear speed, usually in meters per second.
+ float GetJointLinearSpeed() const;
+
+ /// Get the current joint angle in radians.
+ float GetJointAngle() const;
+
+ /// Get the current joint angular speed in radians per second.
+ float GetJointAngularSpeed() const;
+
+ /// Is the joint limit enabled?
+ bool IsLimitEnabled() const;
+
+ /// Enable/disable the joint translation limit.
+ void EnableLimit(bool flag);
+
+ /// Get the lower joint translation limit, usually in meters.
+ float GetLowerLimit() const;
+
+ /// Get the upper joint translation limit, usually in meters.
+ float GetUpperLimit() const;
+
+ /// Set the joint translation limits, usually in meters.
+ void SetLimits(float lower, float upper);
+
+ /// Is the joint motor enabled?
+ bool IsMotorEnabled() const;
+
+ /// Enable/disable the joint motor.
+ void EnableMotor(bool flag);
+
+ /// Set the motor speed, usually in radians per second.
+ void SetMotorSpeed(float speed);
+
+ /// Get the motor speed, usually in radians per second.
+ float GetMotorSpeed() const;
+
+ /// Set/Get the maximum motor force, usually in N-m.
+ void SetMaxMotorTorque(float torque);
+ float GetMaxMotorTorque() const;
+
+ /// Get the current motor torque given the inverse time step, usually in N-m.
+ float GetMotorTorque(float inv_dt) const;
+
+ /// Access spring stiffness
+ void SetStiffness(float stiffness);
+ float GetStiffness() const;
+
+ /// Access damping
+ void SetDamping(float damping);
+ float GetDamping() const;
+
+ /// Dump to b2Log
+ void Dump() override;
+
+ ///
+ void Draw(b2Draw* draw) const override;
+
+protected:
+
+ friend class b2Joint;
+ b2WheelJoint(const b2WheelJointDef* def);
+
+ void InitVelocityConstraints(const b2SolverData& data) override;
+ void SolveVelocityConstraints(const b2SolverData& data) override;
+ bool SolvePositionConstraints(const b2SolverData& data) override;
+
+ b2Vec2 m_localAnchorA;
+ b2Vec2 m_localAnchorB;
+ b2Vec2 m_localXAxisA;
+ b2Vec2 m_localYAxisA;
+
+ float m_impulse;
+ float m_motorImpulse;
+ float m_springImpulse;
+
+ float m_lowerImpulse;
+ float m_upperImpulse;
+ float m_translation;
+ float m_lowerTranslation;
+ float m_upperTranslation;
+
+ float m_maxMotorTorque;
+ float m_motorSpeed;
+
+ bool m_enableLimit;
+ bool m_enableMotor;
+
+ float m_stiffness;
+ float m_damping;
+
+ // Solver temp
+ int32 m_indexA;
+ int32 m_indexB;
+ b2Vec2 m_localCenterA;
+ b2Vec2 m_localCenterB;
+ float m_invMassA;
+ float m_invMassB;
+ float m_invIA;
+ float m_invIB;
+
+ b2Vec2 m_ax, m_ay;
+ float m_sAx, m_sBx;
+ float m_sAy, m_sBy;
+
+ float m_mass;
+ float m_motorMass;
+ float m_axialMass;
+ float m_springMass;
+
+ float m_bias;
+ float m_gamma;
+
+};
+
+inline float b2WheelJoint::GetMotorSpeed() const
+{
+ return m_motorSpeed;
+}
+
+inline float b2WheelJoint::GetMaxMotorTorque() const
+{
+ return m_maxMotorTorque;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_world.h b/Client/ThirdParty/Box2D/include/box2d/b2_world.h
new file mode 100644
index 0000000..57d3709
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_world.h
@@ -0,0 +1,345 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_WORLD_H
+#define B2_WORLD_H
+
+#include "b2_api.h"
+#include "b2_block_allocator.h"
+#include "b2_contact_manager.h"
+#include "b2_math.h"
+#include "b2_stack_allocator.h"
+#include "b2_time_step.h"
+#include "b2_world_callbacks.h"
+
+struct b2AABB;
+struct b2BodyDef;
+struct b2Color;
+struct b2JointDef;
+class b2Body;
+class b2Draw;
+class b2Fixture;
+class b2Joint;
+
+/// The world class manages all physics entities, dynamic simulation,
+/// and asynchronous queries. The world also contains efficient memory
+/// management facilities.
+class B2_API b2World
+{
+public:
+ /// Construct a world object.
+ /// @param gravity the world gravity vector.
+ b2World(const b2Vec2& gravity);
+
+ /// Destruct the world. All physics entities are destroyed and all heap memory is released.
+ ~b2World();
+
+ /// Register a destruction listener. The listener is owned by you and must
+ /// remain in scope.
+ void SetDestructionListener(b2DestructionListener* listener);
+
+ /// Register a contact filter to provide specific control over collision.
+ /// Otherwise the default filter is used (b2_defaultFilter). The listener is
+ /// owned by you and must remain in scope.
+ void SetContactFilter(b2ContactFilter* filter);
+
+ /// Register a contact event listener. The listener is owned by you and must
+ /// remain in scope.
+ void SetContactListener(b2ContactListener* listener);
+
+ /// Register a routine for debug drawing. The debug draw functions are called
+ /// inside with b2World::DebugDraw method. The debug draw object is owned
+ /// by you and must remain in scope.
+ void SetDebugDraw(b2Draw* debugDraw);
+
+ /// Create a rigid body given a definition. No reference to the definition
+ /// is retained.
+ /// @warning This function is locked during callbacks.
+ b2Body* CreateBody(const b2BodyDef* def);
+
+ /// Destroy a rigid body given a definition. No reference to the definition
+ /// is retained. This function is locked during callbacks.
+ /// @warning This automatically deletes all associated shapes and joints.
+ /// @warning This function is locked during callbacks.
+ void DestroyBody(b2Body* body);
+
+ /// Create a joint to constrain bodies together. No reference to the definition
+ /// is retained. This may cause the connected bodies to cease colliding.
+ /// @warning This function is locked during callbacks.
+ b2Joint* CreateJoint(const b2JointDef* def);
+
+ /// Destroy a joint. This may cause the connected bodies to begin colliding.
+ /// @warning This function is locked during callbacks.
+ void DestroyJoint(b2Joint* joint);
+
+ /// Take a time step. This performs collision detection, integration,
+ /// and constraint solution.
+ /// @param timeStep the amount of time to simulate, this should not vary.
+ /// @param velocityIterations for the velocity constraint solver.
+ /// @param positionIterations for the position constraint solver.
+ void Step( float timeStep,
+ int32 velocityIterations,
+ int32 positionIterations);
+
+ /// Manually clear the force buffer on all bodies. By default, forces are cleared automatically
+ /// after each call to Step. The default behavior is modified by calling SetAutoClearForces.
+ /// The purpose of this function is to support sub-stepping. Sub-stepping is often used to maintain
+ /// a fixed sized time step under a variable frame-rate.
+ /// When you perform sub-stepping you will disable auto clearing of forces and instead call
+ /// ClearForces after all sub-steps are complete in one pass of your game loop.
+ /// @see SetAutoClearForces
+ void ClearForces();
+
+ /// Call this to draw shapes and other debug draw data. This is intentionally non-const.
+ void DebugDraw();
+
+ /// Query the world for all fixtures that potentially overlap the
+ /// provided AABB.
+ /// @param callback a user implemented callback class.
+ /// @param aabb the query box.
+ void QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const;
+
+ /// Ray-cast the world for all fixtures in the path of the ray. Your callback
+ /// controls whether you get the closest point, any point, or n-points.
+ /// The ray-cast ignores shapes that contain the starting point.
+ /// @param callback a user implemented callback class.
+ /// @param point1 the ray starting point
+ /// @param point2 the ray ending point
+ void RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const;
+
+ /// Get the world body list. With the returned body, use b2Body::GetNext to get
+ /// the next body in the world list. A nullptr body indicates the end of the list.
+ /// @return the head of the world body list.
+ b2Body* GetBodyList();
+ const b2Body* GetBodyList() const;
+
+ /// Get the world joint list. With the returned joint, use b2Joint::GetNext to get
+ /// the next joint in the world list. A nullptr joint indicates the end of the list.
+ /// @return the head of the world joint list.
+ b2Joint* GetJointList();
+ const b2Joint* GetJointList() const;
+
+ /// Get the world contact list. With the returned contact, use b2Contact::GetNext to get
+ /// the next contact in the world list. A nullptr contact indicates the end of the list.
+ /// @return the head of the world contact list.
+ /// @warning contacts are created and destroyed in the middle of a time step.
+ /// Use b2ContactListener to avoid missing contacts.
+ b2Contact* GetContactList();
+ const b2Contact* GetContactList() const;
+
+ /// Enable/disable sleep.
+ void SetAllowSleeping(bool flag);
+ bool GetAllowSleeping() const { return m_allowSleep; }
+
+ /// Enable/disable warm starting. For testing.
+ void SetWarmStarting(bool flag) { m_warmStarting = flag; }
+ bool GetWarmStarting() const { return m_warmStarting; }
+
+ /// Enable/disable continuous physics. For testing.
+ void SetContinuousPhysics(bool flag) { m_continuousPhysics = flag; }
+ bool GetContinuousPhysics() const { return m_continuousPhysics; }
+
+ /// Enable/disable single stepped continuous physics. For testing.
+ void SetSubStepping(bool flag) { m_subStepping = flag; }
+ bool GetSubStepping() const { return m_subStepping; }
+
+ /// Get the number of broad-phase proxies.
+ int32 GetProxyCount() const;
+
+ /// Get the number of bodies.
+ int32 GetBodyCount() const;
+
+ /// Get the number of joints.
+ int32 GetJointCount() const;
+
+ /// Get the number of contacts (each may have 0 or more contact points).
+ int32 GetContactCount() const;
+
+ /// Get the height of the dynamic tree.
+ int32 GetTreeHeight() const;
+
+ /// Get the balance of the dynamic tree.
+ int32 GetTreeBalance() const;
+
+ /// Get the quality metric of the dynamic tree. The smaller the better.
+ /// The minimum is 1.
+ float GetTreeQuality() const;
+
+ /// Change the global gravity vector.
+ void SetGravity(const b2Vec2& gravity);
+
+ /// Get the global gravity vector.
+ b2Vec2 GetGravity() const;
+
+ /// Is the world locked (in the middle of a time step).
+ bool IsLocked() const;
+
+ /// Set flag to control automatic clearing of forces after each time step.
+ void SetAutoClearForces(bool flag);
+
+ /// Get the flag that controls automatic clearing of forces after each time step.
+ bool GetAutoClearForces() const;
+
+ /// Shift the world origin. Useful for large worlds.
+ /// The body shift formula is: position -= newOrigin
+ /// @param newOrigin the new origin with respect to the old origin
+ void ShiftOrigin(const b2Vec2& newOrigin);
+
+ /// Get the contact manager for testing.
+ const b2ContactManager& GetContactManager() const;
+
+ /// Get the current profile.
+ const b2Profile& GetProfile() const;
+
+ /// Dump the world into the log file.
+ /// @warning this should be called outside of a time step.
+ void Dump();
+
+private:
+
+ friend class b2Body;
+ friend class b2Fixture;
+ friend class b2ContactManager;
+ friend class b2Controller;
+
+ void Solve(const b2TimeStep& step);
+ void SolveTOI(const b2TimeStep& step);
+
+ void DrawShape(b2Fixture* shape, const b2Transform& xf, const b2Color& color);
+
+ b2BlockAllocator m_blockAllocator;
+ b2StackAllocator m_stackAllocator;
+
+ b2ContactManager m_contactManager;
+
+ b2Body* m_bodyList;
+ b2Joint* m_jointList;
+
+ int32 m_bodyCount;
+ int32 m_jointCount;
+
+ b2Vec2 m_gravity;
+ bool m_allowSleep;
+
+ b2DestructionListener* m_destructionListener;
+ b2Draw* m_debugDraw;
+
+ // This is used to compute the time step ratio to
+ // support a variable time step.
+ float m_inv_dt0;
+
+ bool m_newContacts;
+ bool m_locked;
+ bool m_clearForces;
+
+ // These are for debugging the solver.
+ bool m_warmStarting;
+ bool m_continuousPhysics;
+ bool m_subStepping;
+
+ bool m_stepComplete;
+
+ b2Profile m_profile;
+};
+
+inline b2Body* b2World::GetBodyList()
+{
+ return m_bodyList;
+}
+
+inline const b2Body* b2World::GetBodyList() const
+{
+ return m_bodyList;
+}
+
+inline b2Joint* b2World::GetJointList()
+{
+ return m_jointList;
+}
+
+inline const b2Joint* b2World::GetJointList() const
+{
+ return m_jointList;
+}
+
+inline b2Contact* b2World::GetContactList()
+{
+ return m_contactManager.m_contactList;
+}
+
+inline const b2Contact* b2World::GetContactList() const
+{
+ return m_contactManager.m_contactList;
+}
+
+inline int32 b2World::GetBodyCount() const
+{
+ return m_bodyCount;
+}
+
+inline int32 b2World::GetJointCount() const
+{
+ return m_jointCount;
+}
+
+inline int32 b2World::GetContactCount() const
+{
+ return m_contactManager.m_contactCount;
+}
+
+inline void b2World::SetGravity(const b2Vec2& gravity)
+{
+ m_gravity = gravity;
+}
+
+inline b2Vec2 b2World::GetGravity() const
+{
+ return m_gravity;
+}
+
+inline bool b2World::IsLocked() const
+{
+ return m_locked;
+}
+
+inline void b2World::SetAutoClearForces(bool flag)
+{
+ m_clearForces = flag;
+}
+
+/// Get the flag that controls automatic clearing of forces after each time step.
+inline bool b2World::GetAutoClearForces() const
+{
+ return m_clearForces;
+}
+
+inline const b2ContactManager& b2World::GetContactManager() const
+{
+ return m_contactManager;
+}
+
+inline const b2Profile& b2World::GetProfile() const
+{
+ return m_profile;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/b2_world_callbacks.h b/Client/ThirdParty/Box2D/include/box2d/b2_world_callbacks.h
new file mode 100644
index 0000000..da45640
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/b2_world_callbacks.h
@@ -0,0 +1,161 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_WORLD_CALLBACKS_H
+#define B2_WORLD_CALLBACKS_H
+
+#include "b2_api.h"
+#include "b2_settings.h"
+
+struct b2Vec2;
+struct b2Transform;
+class b2Fixture;
+class b2Body;
+class b2Joint;
+class b2Contact;
+struct b2ContactResult;
+struct b2Manifold;
+
+/// Joints and fixtures are destroyed when their associated
+/// body is destroyed. Implement this listener so that you
+/// may nullify references to these joints and shapes.
+class B2_API b2DestructionListener
+{
+public:
+ virtual ~b2DestructionListener() {}
+
+ /// Called when any joint is about to be destroyed due
+ /// to the destruction of one of its attached bodies.
+ virtual void SayGoodbye(b2Joint* joint) = 0;
+
+ /// Called when any fixture is about to be destroyed due
+ /// to the destruction of its parent body.
+ virtual void SayGoodbye(b2Fixture* fixture) = 0;
+};
+
+/// Implement this class to provide collision filtering. In other words, you can implement
+/// this class if you want finer control over contact creation.
+class B2_API b2ContactFilter
+{
+public:
+ virtual ~b2ContactFilter() {}
+
+ /// Return true if contact calculations should be performed between these two shapes.
+ /// @warning for performance reasons this is only called when the AABBs begin to overlap.
+ virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB);
+};
+
+/// Contact impulses for reporting. Impulses are used instead of forces because
+/// sub-step forces may approach infinity for rigid body collisions. These
+/// match up one-to-one with the contact points in b2Manifold.
+struct B2_API b2ContactImpulse
+{
+ float normalImpulses[b2_maxManifoldPoints];
+ float tangentImpulses[b2_maxManifoldPoints];
+ int32 count;
+};
+
+/// Implement this class to get contact information. You can use these results for
+/// things like sounds and game logic. You can also get contact results by
+/// traversing the contact lists after the time step. However, you might miss
+/// some contacts because continuous physics leads to sub-stepping.
+/// Additionally you may receive multiple callbacks for the same contact in a
+/// single time step.
+/// You should strive to make your callbacks efficient because there may be
+/// many callbacks per time step.
+/// @warning You cannot create/destroy Box2D entities inside these callbacks.
+class B2_API b2ContactListener
+{
+public:
+ virtual ~b2ContactListener() {}
+
+ /// Called when two fixtures begin to touch.
+ virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }
+
+ /// Called when two fixtures cease to touch.
+ virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }
+
+ /// This is called after a contact is updated. This allows you to inspect a
+ /// contact before it goes to the solver. If you are careful, you can modify the
+ /// contact manifold (e.g. disable contact).
+ /// A copy of the old manifold is provided so that you can detect changes.
+ /// Note: this is called only for awake bodies.
+ /// Note: this is called even when the number of contact points is zero.
+ /// Note: this is not called for sensors.
+ /// Note: if you set the number of contact points to zero, you will not
+ /// get an EndContact callback. However, you may get a BeginContact callback
+ /// the next step.
+ virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+ {
+ B2_NOT_USED(contact);
+ B2_NOT_USED(oldManifold);
+ }
+
+ /// This lets you inspect a contact after the solver is finished. This is useful
+ /// for inspecting impulses.
+ /// Note: the contact manifold does not include time of impact impulses, which can be
+ /// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly
+ /// in a separate data structure.
+ /// Note: this is only called for contacts that are touching, solid, and awake.
+ virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
+ {
+ B2_NOT_USED(contact);
+ B2_NOT_USED(impulse);
+ }
+};
+
+/// Callback class for AABB queries.
+/// See b2World::Query
+class B2_API b2QueryCallback
+{
+public:
+ virtual ~b2QueryCallback() {}
+
+ /// Called for each fixture found in the query AABB.
+ /// @return false to terminate the query.
+ virtual bool ReportFixture(b2Fixture* fixture) = 0;
+};
+
+/// Callback class for ray casts.
+/// See b2World::RayCast
+class B2_API b2RayCastCallback
+{
+public:
+ virtual ~b2RayCastCallback() {}
+
+ /// Called for each fixture found in the query. You control how the ray cast
+ /// proceeds by returning a float:
+ /// return -1: ignore this fixture and continue
+ /// return 0: terminate the ray cast
+ /// return fraction: clip the ray to this point
+ /// return 1: don't clip the ray and continue
+ /// @param fixture the fixture hit by the ray
+ /// @param point the point of initial intersection
+ /// @param normal the normal vector at the point of intersection
+ /// @param fraction the fraction along the ray at the point of intersection
+ /// @return -1 to filter, 0 to terminate, fraction to clip the ray for
+ /// closest hit, 1 to continue
+ virtual float ReportFixture( b2Fixture* fixture, const b2Vec2& point,
+ const b2Vec2& normal, float fraction) = 0;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/include/box2d/box2d.h b/Client/ThirdParty/Box2D/include/box2d/box2d.h
new file mode 100644
index 0000000..55c6958
--- /dev/null
+++ b/Client/ThirdParty/Box2D/include/box2d/box2d.h
@@ -0,0 +1,58 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef BOX2D_H
+#define BOX2D_H
+
+// These include files constitute the main Box2D API
+
+#include "b2_settings.h"
+#include "b2_draw.h"
+#include "b2_timer.h"
+
+#include "b2_chain_shape.h"
+#include "b2_circle_shape.h"
+#include "b2_edge_shape.h"
+#include "b2_polygon_shape.h"
+
+#include "b2_broad_phase.h"
+#include "b2_dynamic_tree.h"
+
+#include "b2_body.h"
+#include "b2_contact.h"
+#include "b2_fixture.h"
+#include "b2_time_step.h"
+#include "b2_world.h"
+#include "b2_world_callbacks.h"
+
+#include "b2_distance_joint.h"
+#include "b2_friction_joint.h"
+#include "b2_gear_joint.h"
+#include "b2_motor_joint.h"
+#include "b2_mouse_joint.h"
+#include "b2_prismatic_joint.h"
+#include "b2_pulley_joint.h"
+#include "b2_revolute_joint.h"
+#include "b2_weld_joint.h"
+#include "b2_wheel_joint.h"
+
+#endif
diff --git a/Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj b/Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj
new file mode 100644
index 0000000..d8a2af6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>ALL_BUILD</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\box2d.vcxproj">
+ <Project>{4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}</Project>
+ <Name>box2d</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\glad.vcxproj">
+ <Project>{29408AB9-D01F-3745-93F3-94160B037370}</Project>
+ <Name>glad</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\glfw.vcxproj">
+ <Project>{7F32E689-3D5C-3885-9B34-0860DAE8BE92}</Project>
+ <Name>glfw</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\imgui.vcxproj">
+ <Project>{B288C97F-F14F-33EA-9CAC-B55922D1FDC7}</Project>
+ <Name>imgui</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\sajson.vcxproj">
+ <Project>{EE68EE8F-E321-3CD7-A04C-C0A66C401380}</Project>
+ <Name>sajson</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\testbed.vcxproj">
+ <Project>{A168F045-AE5A-3724-B305-AA2A8C4749BA}</Project>
+ <Name>testbed</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\unit_test.vcxproj">
+ <Project>{7ED467E4-0B19-329B-B677-9C4C01A3EC52}</Project>
+ <Name>unit_test</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj.filters b/Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj.filters
new file mode 100644
index 0000000..9443b67
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/ALL_BUILD.vcxproj.filters
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/CMakeCache.txt b/Client/ThirdParty/Box2D/proj/CMakeCache.txt
new file mode 100644
index 0000000..545df5f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeCache.txt
@@ -0,0 +1,441 @@
+# This is the CMakeCache file.
+# For build in directory: d:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj
+# It was generated by CMake: C:/Program Files/CMake/bin/cmake.exe
+# You can edit this file to change values found and used by cmake.
+# If you do not want to change any of the values, simply exit the editor.
+# If you do want to change a value, simply edit, save, and exit the editor.
+# The syntax for the file is as follows:
+# KEY:TYPE=VALUE
+# KEY is the name of a variable in the cache.
+# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
+# VALUE is the current value for the KEY.
+
+########################
+# EXTERNAL cache entries
+########################
+
+//Build the Box2D documentation
+BOX2D_BUILD_DOCS:BOOL=OFF
+
+//Build the Box2D testbed
+BOX2D_BUILD_TESTBED:BOOL=ON
+
+//Build the Box2D unit tests
+BOX2D_BUILD_UNIT_TESTS:BOOL=ON
+
+//Override Box2D settings with b2UserSettings.h
+BOX2D_USER_SETTINGS:BOOL=OFF
+
+//Build Box2D as a shared library
+BUILD_SHARED_LIBS:BOOL=OFF
+
+//Path to a program.
+CMAKE_AR:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/lib.exe
+
+//Semicolon separated list of supported configuration types, only
+// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything
+// else will be ignored.
+CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo
+
+//Flags used by the CXX compiler during all build types.
+CMAKE_CXX_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 /GR /EHsc
+
+//Flags used by the CXX compiler during DEBUG builds.
+CMAKE_CXX_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1
+
+//Flags used by the CXX compiler during MINSIZEREL builds.
+CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG
+
+//Flags used by the CXX compiler during RELEASE builds.
+CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG
+
+//Flags used by the CXX compiler during RELWITHDEBINFO builds.
+CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG
+
+//Libraries linked by default with all C++ applications.
+CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
+
+//Flags used by the C compiler during all build types.
+CMAKE_C_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3
+
+//Flags used by the C compiler during DEBUG builds.
+CMAKE_C_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1
+
+//Flags used by the C compiler during MINSIZEREL builds.
+CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG
+
+//Flags used by the C compiler during RELEASE builds.
+CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG
+
+//Flags used by the C compiler during RELWITHDEBINFO builds.
+CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG
+
+//Libraries linked by default with all C applications.
+CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
+
+//Flags used by the linker during all build types.
+CMAKE_EXE_LINKER_FLAGS:STRING=/machine:X86
+
+//Flags used by the linker during DEBUG builds.
+CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
+
+//Flags used by the linker during MINSIZEREL builds.
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
+
+//Flags used by the linker during RELEASE builds.
+CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
+
+//Flags used by the linker during RELWITHDEBINFO builds.
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
+
+//User executables (bin)
+CMAKE_INSTALL_BINDIR:PATH=bin
+
+//Read-only architecture-independent data (DATAROOTDIR)
+CMAKE_INSTALL_DATADIR:PATH=
+
+//Read-only architecture-independent data root (share)
+CMAKE_INSTALL_DATAROOTDIR:PATH=share
+
+//Documentation root (DATAROOTDIR/doc/PROJECT_NAME)
+CMAKE_INSTALL_DOCDIR:PATH=
+
+//C header files (include)
+CMAKE_INSTALL_INCLUDEDIR:PATH=include
+
+//Info documentation (DATAROOTDIR/info)
+CMAKE_INSTALL_INFODIR:PATH=
+
+//Object code libraries (lib)
+CMAKE_INSTALL_LIBDIR:PATH=lib
+
+//Program executables (libexec)
+CMAKE_INSTALL_LIBEXECDIR:PATH=libexec
+
+//Locale-dependent data (DATAROOTDIR/locale)
+CMAKE_INSTALL_LOCALEDIR:PATH=
+
+//Modifiable single-machine data (var)
+CMAKE_INSTALL_LOCALSTATEDIR:PATH=var
+
+//Man documentation (DATAROOTDIR/man)
+CMAKE_INSTALL_MANDIR:PATH=
+
+//C header files for non-gcc (/usr/include)
+CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include
+
+//Install path prefix, prepended onto install directories.
+CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/box2d
+
+//Run-time variable data (LOCALSTATEDIR/run)
+CMAKE_INSTALL_RUNSTATEDIR:PATH=
+
+//System admin executables (sbin)
+CMAKE_INSTALL_SBINDIR:PATH=sbin
+
+//Modifiable architecture-independent data (com)
+CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com
+
+//Read-only single-machine data (etc)
+CMAKE_INSTALL_SYSCONFDIR:PATH=etc
+
+//Path to a program.
+CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/link.exe
+
+//Flags used by the linker during the creation of modules during
+// all build types.
+CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:X86
+
+//Flags used by the linker during the creation of modules during
+// DEBUG builds.
+CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
+
+//Flags used by the linker during the creation of modules during
+// MINSIZEREL builds.
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
+
+//Flags used by the linker during the creation of modules during
+// RELEASE builds.
+CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
+
+//Flags used by the linker during the creation of modules during
+// RELWITHDEBINFO builds.
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
+
+//Path to a program.
+CMAKE_MT:FILEPATH=CMAKE_MT-NOTFOUND
+
+//Value Computed by CMake
+CMAKE_PROJECT_DESCRIPTION:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
+
+//Value Computed by CMake
+CMAKE_PROJECT_NAME:STATIC=box2d
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION:STATIC=2.4.1
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_MAJOR:STATIC=2
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_MINOR:STATIC=4
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_PATCH:STATIC=1
+
+//Value Computed by CMake
+CMAKE_PROJECT_VERSION_TWEAK:STATIC=
+
+//RC compiler
+CMAKE_RC_COMPILER:FILEPATH=rc
+
+//Flags for Windows Resource Compiler during all build types.
+CMAKE_RC_FLAGS:STRING=-DWIN32
+
+//Flags for Windows Resource Compiler during DEBUG builds.
+CMAKE_RC_FLAGS_DEBUG:STRING=-D_DEBUG
+
+//Flags for Windows Resource Compiler during MINSIZEREL builds.
+CMAKE_RC_FLAGS_MINSIZEREL:STRING=
+
+//Flags for Windows Resource Compiler during RELEASE builds.
+CMAKE_RC_FLAGS_RELEASE:STRING=
+
+//Flags for Windows Resource Compiler during RELWITHDEBINFO builds.
+CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING=
+
+//Flags used by the linker during the creation of shared libraries
+// during all build types.
+CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:X86
+
+//Flags used by the linker during the creation of shared libraries
+// during DEBUG builds.
+CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
+
+//Flags used by the linker during the creation of shared libraries
+// during MINSIZEREL builds.
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
+
+//Flags used by the linker during the creation of shared libraries
+// during RELEASE builds.
+CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
+
+//Flags used by the linker during the creation of shared libraries
+// during RELWITHDEBINFO builds.
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
+
+//If set, runtime paths are not added when installing shared libraries,
+// but are added when building.
+CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
+
+//If set, runtime paths are not added when using shared libraries.
+CMAKE_SKIP_RPATH:BOOL=NO
+
+//Flags used by the linker during the creation of static libraries
+// during all build types.
+CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:X86
+
+//Flags used by the linker during the creation of static libraries
+// during DEBUG builds.
+CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during MINSIZEREL builds.
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELEASE builds.
+CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
+
+//Flags used by the linker during the creation of static libraries
+// during RELWITHDEBINFO builds.
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
+
+//If this value is on, makefiles will be generated without the
+// .SILENT directive, and all commands will be echoed to the console
+// during the make. This is useful for debugging only. With Visual
+// Studio IDE projects all commands are done without /nologo.
+CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
+
+//Value Computed by CMake
+box2d_BINARY_DIR:STATIC=D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj
+
+//Value Computed by CMake
+box2d_IS_TOP_LEVEL:STATIC=ON
+
+//Value Computed by CMake
+box2d_SOURCE_DIR:STATIC=D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D
+
+
+########################
+# INTERNAL cache entries
+########################
+
+//ADVANCED property for variable: CMAKE_AR
+CMAKE_AR-ADVANCED:INTERNAL=1
+//This is the directory where this CMakeCache.txt was created
+CMAKE_CACHEFILE_DIR:INTERNAL=d:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj
+//Major version of cmake used to create the current loaded cache
+CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
+//Minor version of cmake used to create the current loaded cache
+CMAKE_CACHE_MINOR_VERSION:INTERNAL=22
+//Patch version of cmake used to create the current loaded cache
+CMAKE_CACHE_PATCH_VERSION:INTERNAL=0
+//Path to CMake executable.
+CMAKE_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cmake.exe
+//Path to cpack program executable.
+CMAKE_CPACK_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cpack.exe
+//Path to ctest program executable.
+CMAKE_CTEST_COMMAND:INTERNAL=C:/Program Files/CMake/bin/ctest.exe
+//ADVANCED property for variable: CMAKE_CXX_FLAGS
+CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
+CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
+CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
+CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
+CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES
+CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS
+CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
+CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
+CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
+CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
+CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES
+CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
+//Executable file format
+CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
+CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
+CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
+CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
+CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//Name of external makefile project generator.
+CMAKE_EXTRA_GENERATOR:INTERNAL=
+//Name of generator.
+CMAKE_GENERATOR:INTERNAL=Visual Studio 15 2017
+//Generator instance identifier.
+CMAKE_GENERATOR_INSTANCE:INTERNAL=C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise
+//Name of generator platform.
+CMAKE_GENERATOR_PLATFORM:INTERNAL=
+//Name of generator toolset.
+CMAKE_GENERATOR_TOOLSET:INTERNAL=
+//Have include pthread.h
+CMAKE_HAVE_PTHREAD_H:INTERNAL=
+//Source directory with the top level CMakeLists.txt file for this
+// project
+CMAKE_HOME_DIRECTORY:INTERNAL=D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D
+//ADVANCED property for variable: CMAKE_INSTALL_BINDIR
+CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DATADIR
+CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR
+CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR
+CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR
+CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_INFODIR
+CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR
+CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR
+CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR
+CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR
+CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_MANDIR
+CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR
+CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR
+CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR
+CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR
+CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR
+CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_LINKER
+CMAKE_LINKER-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
+CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
+CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
+CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
+CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_MT
+CMAKE_MT-ADVANCED:INTERNAL=1
+//number of local generators
+CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=8
+//Platform information initialized
+CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
+//noop for ranlib
+CMAKE_RANLIB:INTERNAL=:
+//ADVANCED property for variable: CMAKE_RC_COMPILER
+CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1
+CMAKE_RC_COMPILER_WORKS:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RC_FLAGS
+CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RC_FLAGS_DEBUG
+CMAKE_RC_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RC_FLAGS_MINSIZEREL
+CMAKE_RC_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RC_FLAGS_RELEASE
+CMAKE_RC_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_RC_FLAGS_RELWITHDEBINFO
+CMAKE_RC_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//Path to CMake installation.
+CMAKE_ROOT:INTERNAL=C:/Program Files/CMake/share/cmake-3.22
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
+CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
+CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
+CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
+CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
+CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_SKIP_RPATH
+CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
+CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
+CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
+CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
+CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
+CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
+//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
+CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
+//Details about finding Threads
+FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()]
+//CMAKE_INSTALL_PREFIX during last run
+_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=C:/Program Files (x86)/box2d
+
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/049e1eb7380682ec4cf9a2c62dad57db/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/049e1eb7380682ec4cf9a2c62dad57db/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/049e1eb7380682ec4cf9a2c62dad57db/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/14f8a92cc8883d19b638672092016c39/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/14f8a92cc8883d19b638672092016c39/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/14f8a92cc8883d19b638672092016c39/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCCompiler.cmake b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCCompiler.cmake
new file mode 100644
index 0000000..08969aa
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCCompiler.cmake
@@ -0,0 +1,72 @@
+set(CMAKE_C_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe")
+set(CMAKE_C_COMPILER_ARG1 "")
+set(CMAKE_C_COMPILER_ID "MSVC")
+set(CMAKE_C_COMPILER_VERSION "19.16.27045.0")
+set(CMAKE_C_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_C_COMPILER_WRAPPER "")
+set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "90")
+set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "OFF")
+set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_std_99;c_std_11;c_function_prototypes;c_variadic_macros")
+set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes")
+set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_variadic_macros")
+set(CMAKE_C11_COMPILE_FEATURES "c_std_11")
+set(CMAKE_C17_COMPILE_FEATURES "")
+set(CMAKE_C23_COMPILE_FEATURES "")
+
+set(CMAKE_C_PLATFORM_ID "Windows")
+set(CMAKE_C_SIMULATE_ID "")
+set(CMAKE_C_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_C_SIMULATE_VERSION "")
+set(CMAKE_C_COMPILER_ARCHITECTURE_ID X86)
+
+set(MSVC_C_ARCHITECTURE_ID X86)
+
+set(CMAKE_AR "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/lib.exe")
+set(CMAKE_C_COMPILER_AR "")
+set(CMAKE_RANLIB ":")
+set(CMAKE_C_COMPILER_RANLIB "")
+set(CMAKE_LINKER "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/link.exe")
+set(CMAKE_MT "CMAKE_MT-NOTFOUND")
+set(CMAKE_COMPILER_IS_GNUCC )
+set(CMAKE_C_COMPILER_LOADED 1)
+set(CMAKE_C_COMPILER_WORKS TRUE)
+set(CMAKE_C_ABI_COMPILED TRUE)
+
+set(CMAKE_C_COMPILER_ENV_VAR "CC")
+
+set(CMAKE_C_COMPILER_ID_RUN 1)
+set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
+set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
+set(CMAKE_C_LINKER_PREFERENCE 10)
+
+# Save compiler ABI information.
+set(CMAKE_C_SIZEOF_DATA_PTR "4")
+set(CMAKE_C_COMPILER_ABI "")
+set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN")
+set(CMAKE_C_LIBRARY_ARCHITECTURE "")
+
+if(CMAKE_C_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_C_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}")
+endif()
+
+if(CMAKE_C_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "")
+endif()
+
+set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_C_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "")
+set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "")
+set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "")
+set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCXXCompiler.cmake b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCXXCompiler.cmake
new file mode 100644
index 0000000..e905aa1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCXXCompiler.cmake
@@ -0,0 +1,83 @@
+set(CMAKE_CXX_COMPILER "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/cl.exe")
+set(CMAKE_CXX_COMPILER_ARG1 "")
+set(CMAKE_CXX_COMPILER_ID "MSVC")
+set(CMAKE_CXX_COMPILER_VERSION "19.16.27045.0")
+set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "")
+set(CMAKE_CXX_COMPILER_WRAPPER "")
+set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14")
+set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "OFF")
+set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20")
+set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters")
+set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates")
+set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates")
+set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17")
+set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20")
+set(CMAKE_CXX23_COMPILE_FEATURES "")
+
+set(CMAKE_CXX_PLATFORM_ID "Windows")
+set(CMAKE_CXX_SIMULATE_ID "")
+set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "")
+set(CMAKE_CXX_SIMULATE_VERSION "")
+set(CMAKE_CXX_COMPILER_ARCHITECTURE_ID X86)
+
+set(MSVC_CXX_ARCHITECTURE_ID X86)
+
+set(CMAKE_AR "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/lib.exe")
+set(CMAKE_CXX_COMPILER_AR "")
+set(CMAKE_RANLIB ":")
+set(CMAKE_CXX_COMPILER_RANLIB "")
+set(CMAKE_LINKER "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC/Tools/MSVC/14.16.27023/bin/Hostx86/x86/link.exe")
+set(CMAKE_MT "CMAKE_MT-NOTFOUND")
+set(CMAKE_COMPILER_IS_GNUCXX )
+set(CMAKE_CXX_COMPILER_LOADED 1)
+set(CMAKE_CXX_COMPILER_WORKS TRUE)
+set(CMAKE_CXX_ABI_COMPILED TRUE)
+
+set(CMAKE_CXX_COMPILER_ENV_VAR "CXX")
+
+set(CMAKE_CXX_COMPILER_ID_RUN 1)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm)
+set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
+
+foreach (lang C OBJC OBJCXX)
+ if (CMAKE_${lang}_COMPILER_ID_RUN)
+ foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
+ list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
+ endforeach()
+ endif()
+endforeach()
+
+set(CMAKE_CXX_LINKER_PREFERENCE 30)
+set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
+
+# Save compiler ABI information.
+set(CMAKE_CXX_SIZEOF_DATA_PTR "4")
+set(CMAKE_CXX_COMPILER_ABI "")
+set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN")
+set(CMAKE_CXX_LIBRARY_ARCHITECTURE "")
+
+if(CMAKE_CXX_SIZEOF_DATA_PTR)
+ set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_CXX_COMPILER_ABI)
+ set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}")
+endif()
+
+if(CMAKE_CXX_LIBRARY_ARCHITECTURE)
+ set(CMAKE_LIBRARY_ARCHITECTURE "")
+endif()
+
+set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "")
+if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX)
+ set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}")
+endif()
+
+
+
+
+
+set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "")
+set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
+set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
+set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "")
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_C.bin b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_C.bin
new file mode 100644
index 0000000..1f16555
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_C.bin
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_CXX.bin b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_CXX.bin
new file mode 100644
index 0000000..54e380e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeDetermineCompilerABI_CXX.bin
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeRCCompiler.cmake b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeRCCompiler.cmake
new file mode 100644
index 0000000..0f61961
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeRCCompiler.cmake
@@ -0,0 +1,6 @@
+set(CMAKE_RC_COMPILER "rc")
+set(CMAKE_RC_COMPILER_ARG1 "")
+set(CMAKE_RC_COMPILER_LOADED 1)
+set(CMAKE_RC_SOURCE_FILE_EXTENSIONS rc;RC)
+set(CMAKE_RC_OUTPUT_EXTENSION .res)
+set(CMAKE_RC_COMPILER_ENV_VAR "RC")
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeSystem.cmake b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeSystem.cmake
new file mode 100644
index 0000000..013b053
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeSystem.cmake
@@ -0,0 +1,15 @@
+set(CMAKE_HOST_SYSTEM "Windows-10.0.19042")
+set(CMAKE_HOST_SYSTEM_NAME "Windows")
+set(CMAKE_HOST_SYSTEM_VERSION "10.0.19042")
+set(CMAKE_HOST_SYSTEM_PROCESSOR "AMD64")
+
+
+
+set(CMAKE_SYSTEM "Windows-10.0.19042")
+set(CMAKE_SYSTEM_NAME "Windows")
+set(CMAKE_SYSTEM_VERSION "10.0.19042")
+set(CMAKE_SYSTEM_PROCESSOR "AMD64")
+
+set(CMAKE_CROSSCOMPILING "FALSE")
+
+set(CMAKE_SYSTEM_LOADED 1)
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CMakeCCompilerId.c b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CMakeCCompilerId.c
new file mode 100644
index 0000000..55753d5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CMakeCCompilerId.c
@@ -0,0 +1,803 @@
+#ifdef __cplusplus
+# error "A C++ compiler has been selected for C."
+#endif
+
+#if defined(__18CXX)
+# define ID_VOID_MAIN
+#endif
+#if defined(__CLASSIC_C__)
+/* cv-qualifiers did not exist in K&R C */
+# define const
+# define volatile
+#endif
+
+#if !defined(__has_include)
+/* If the compiler does not have __has_include, pretend the answer is
+ always no. */
+# define __has_include(x) 0
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
+ except that a few beta releases use the old format with V=2021. */
+# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# else
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
+ /* The third version component from --version is an update index,
+ but no macro is provided for it. */
+# define COMPILER_VERSION_PATCH DEC(0)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
+# define COMPILER_ID "IntelLLVM"
+#if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+#endif
+#if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+#endif
+/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
+ * later. Look for 6 digit vs. 8 digit version number to decide encoding.
+ * VVVV is no smaller than the current year when a version is released.
+ */
+#if __INTEL_LLVM_COMPILER < 1000000L
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
+#else
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
+#endif
+#if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+#endif
+#if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+#elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+#endif
+#if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+#endif
+#if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+#endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_C)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_C >= 0x5100
+ /* __SUNPRO_C = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF)
+# endif
+
+#elif defined(__HP_cc)
+# define COMPILER_ID "HP"
+ /* __HP_cc = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100)
+
+#elif defined(__DECC)
+# define COMPILER_ID "Compaq"
+ /* __DECC_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000)
+
+#elif defined(__IBMC__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMC__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10)
+
+#elif defined(__NVCOMPILER)
+# define COMPILER_ID "NVHPC"
+# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
+# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
+# if defined(__NVCOMPILER_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
+# endif
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__CLANG_FUJITSU)
+# define COMPILER_ID "FujitsuClang"
+# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+# define COMPILER_VERSION_INTERNAL_STR __clang_version__
+
+
+#elif defined(__FUJITSU)
+# define COMPILER_ID "Fujitsu"
+# if defined(__FCC_version__)
+# define COMPILER_VERSION __FCC_version__
+# elif defined(__FCC_major__)
+# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+# endif
+# if defined(__fcc_version)
+# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
+# elif defined(__FCC_VERSION)
+# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
+# endif
+
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__TINYC__)
+# define COMPILER_ID "TinyCC"
+
+#elif defined(__BCC__)
+# define COMPILER_ID "Bruce"
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__)
+# define COMPILER_ID "GNU"
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC)
+# define COMPILER_ID "SDCC"
+# if defined(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR)
+# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH)
+# else
+ /* SDCC = VRP */
+# define COMPILER_VERSION_MAJOR DEC(SDCC/100)
+# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(SDCC % 10)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__MSYS__)
+# define PLATFORM_ID "MSYS"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# elif defined(__VXWORKS__)
+# define PLATFORM_ID "VxWorks"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_ARM64EC)
+# define ARCHITECTURE_ID "ARM64EC"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# elif defined(__ICCSTM8__)
+# define ARCHITECTURE_ID "STM8"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__TI_COMPILER_VERSION__)
+# if defined(__TI_ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__MSP430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__TMS320C28XX__)
+# define ARCHITECTURE_ID "TMS320C28x"
+
+# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
+# define ARCHITECTURE_ID "TMS320C6x"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number. */
+#ifdef COMPILER_VERSION
+char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
+
+/* Construct a string literal encoding the version number components. */
+#elif defined(COMPILER_VERSION_MAJOR)
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#elif defined(COMPILER_VERSION_INTERNAL_STR)
+char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+#if !defined(__STDC__) && !defined(__clang__)
+# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__)
+# define C_VERSION "90"
+# else
+# define C_VERSION
+# endif
+#elif __STDC_VERSION__ > 201710L
+# define C_VERSION "23"
+#elif __STDC_VERSION__ >= 201710L
+# define C_VERSION "17"
+#elif __STDC_VERSION__ >= 201000L
+# define C_VERSION "11"
+#elif __STDC_VERSION__ >= 199901L
+# define C_VERSION "99"
+#else
+# define C_VERSION "90"
+#endif
+const char* info_language_standard_default =
+ "INFO" ":" "standard_default[" C_VERSION "]";
+
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode.
+#if (defined(__clang__) || defined(__GNUC__) || \
+ defined(__TI_COMPILER_VERSION__)) && \
+ !defined(__STRICT_ANSI__) && !defined(_MSC_VER)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+#ifdef ID_VOID_MAIN
+void main() {}
+#else
+# if defined(__CLASSIC_C__)
+int main(argc, argv) int argc; char *argv[];
+# else
+int main(int argc, char* argv[])
+# endif
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+ require += info_arch[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+ require += info_cray[argc];
+#endif
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
+ (void)argv;
+ return require;
+}
+#endif
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.exe b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.exe
new file mode 100644
index 0000000..3d8110a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.exe
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.vcxproj b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.vcxproj
new file mode 100644
index 0000000..a96ed0a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.vcxproj
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CAE07175-D007-4FC3-BFE8-47B392814159}</ProjectGuid>
+ <RootNamespace>CompilerIdC</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+
+
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+
+
+
+
+ </PropertyGroup>
+
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup>
+
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+
+ </ImportGroup>
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>TurnOffAllWarnings</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+
+ <Link>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+
+ </Link>
+ <PostBuildEvent>
+ <Command>for %%i in (cl.exe) do %40echo CMAKE_C_COMPILER=%%~$PATH:i</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="CMakeCCompilerId.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+
+ </ImportGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CMakeCCompilerId.obj b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CMakeCCompilerId.obj
new file mode 100644
index 0000000..c0c9d27
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CMakeCCompilerId.obj
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.command.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.command.1.tlog
new file mode 100644
index 0000000..1f3c250
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.command.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.read.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.read.1.tlog
new file mode 100644
index 0000000..ee0a19b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.read.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.write.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.write.1.tlog
new file mode 100644
index 0000000..b0bc733
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CL.write.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CompilerIdC.lastbuildstate b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CompilerIdC.lastbuildstate
new file mode 100644
index 0000000..3773964
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/CompilerIdC.lastbuildstate
@@ -0,0 +1,2 @@
+#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
+Debug|Win32|D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdC\|
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.command.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.command.1.tlog
new file mode 100644
index 0000000..d89b4b2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.command.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.read.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.read.1.tlog
new file mode 100644
index 0000000..022717c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.read.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.write.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.write.1.tlog
new file mode 100644
index 0000000..958b952
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/Debug/CompilerIdC.tlog/link.write.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CMakeCXXCompilerId.cpp b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CMakeCXXCompilerId.cpp
new file mode 100644
index 0000000..adc0bb8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CMakeCXXCompilerId.cpp
@@ -0,0 +1,791 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+ recognize the extension without flags. Borland does not know .cxx for
+ example. */
+#ifndef __cplusplus
+# error "A C compiler has been selected for C++."
+#endif
+
+#if !defined(__has_include)
+/* If the compiler does not have __has_include, pretend the answer is
+ always no. */
+# define __has_include(x) 0
+#endif
+
+
+/* Version number components: V=Version, R=Revision, P=Patch
+ Version date components: YYYY=Year, MM=Month, DD=Day */
+
+#if defined(__COMO__)
+# define COMPILER_ID "Comeau"
+ /* __COMO_VERSION__ = VRR */
+# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
+# define COMPILER_ID "Intel"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+# endif
+ /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
+ except that a few beta releases use the old format with V=2021. */
+# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+# if defined(__INTEL_COMPILER_UPDATE)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+# else
+# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+# endif
+# else
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
+ /* The third version component from --version is an update index,
+ but no macro is provided for it. */
+# define COMPILER_VERSION_PATCH DEC(0)
+# endif
+# if defined(__INTEL_COMPILER_BUILD_DATE)
+ /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+# endif
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+# elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
+# define COMPILER_ID "IntelLLVM"
+#if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+#endif
+#if defined(__GNUC__)
+# define SIMULATE_ID "GNU"
+#endif
+/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
+ * later. Look for 6 digit vs. 8 digit version number to decide encoding.
+ * VVVV is no smaller than the current year when a version is released.
+ */
+#if __INTEL_LLVM_COMPILER < 1000000L
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
+#else
+# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
+# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
+#endif
+#if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+#endif
+#if defined(__GNUC__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+#elif defined(__GNUG__)
+# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+#endif
+#if defined(__GNUC_MINOR__)
+# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+#endif
+#if defined(__GNUC_PATCHLEVEL__)
+# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+#endif
+
+#elif defined(__PATHCC__)
+# define COMPILER_ID "PathScale"
+# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+# if defined(__PATHCC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+# endif
+
+#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+# define COMPILER_ID "Embarcadero"
+# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
+#elif defined(__BORLANDC__)
+# define COMPILER_ID "Borland"
+ /* __BORLANDC__ = 0xVRR */
+# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
+#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+# define COMPILER_ID "Watcom"
+ /* __WATCOMC__ = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__WATCOMC__)
+# define COMPILER_ID "OpenWatcom"
+ /* __WATCOMC__ = VVRP + 1100 */
+# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+# if (__WATCOMC__ % 10) > 0
+# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+# endif
+
+#elif defined(__SUNPRO_CC)
+# define COMPILER_ID "SunPro"
+# if __SUNPRO_CC >= 0x5100
+ /* __SUNPRO_CC = 0xVRRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# else
+ /* __SUNPRO_CC = 0xVRP */
+# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+# endif
+
+#elif defined(__HP_aCC)
+# define COMPILER_ID "HP"
+ /* __HP_aCC = VVRRPP */
+# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
+
+#elif defined(__DECCXX)
+# define COMPILER_ID "Compaq"
+ /* __DECCXX_VER = VVRRTPPPP */
+# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
+# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
+
+#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
+# define COMPILER_ID "zOS"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__ibmxl__) && defined(__clang__)
+# define COMPILER_ID "XLClang"
+# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
+# define COMPILER_ID "XL"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
+# define COMPILER_ID "VisualAge"
+ /* __IBMCPP__ = VRP */
+# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
+#elif defined(__NVCOMPILER)
+# define COMPILER_ID "NVHPC"
+# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
+# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
+# if defined(__NVCOMPILER_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
+# endif
+
+#elif defined(__PGI)
+# define COMPILER_ID "PGI"
+# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+# if defined(__PGIC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+# endif
+
+#elif defined(_CRAYC)
+# define COMPILER_ID "Cray"
+# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
+#elif defined(__TI_COMPILER_VERSION__)
+# define COMPILER_ID "TI"
+ /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
+#elif defined(__CLANG_FUJITSU)
+# define COMPILER_ID "FujitsuClang"
+# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+# define COMPILER_VERSION_INTERNAL_STR __clang_version__
+
+
+#elif defined(__FUJITSU)
+# define COMPILER_ID "Fujitsu"
+# if defined(__FCC_version__)
+# define COMPILER_VERSION __FCC_version__
+# elif defined(__FCC_major__)
+# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+# endif
+# if defined(__fcc_version)
+# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
+# elif defined(__FCC_VERSION)
+# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
+# endif
+
+
+#elif defined(__ghs__)
+# define COMPILER_ID "GHS"
+/* __GHS_VERSION_NUMBER = VVVVRP */
+# ifdef __GHS_VERSION_NUMBER
+# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+# endif
+
+#elif defined(__SCO_VERSION__)
+# define COMPILER_ID "SCO"
+
+#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+# define COMPILER_ID "ARMCC"
+#if __ARMCC_VERSION >= 1000000
+ /* __ARMCC_VERSION = VRRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#else
+ /* __ARMCC_VERSION = VRPPPP */
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+#endif
+
+
+#elif defined(__clang__) && defined(__apple_build_version__)
+# define COMPILER_ID "AppleClang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
+#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+# define COMPILER_ID "ARMClang"
+ # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+ # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+ # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000)
+# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
+#elif defined(__clang__)
+# define COMPILER_ID "Clang"
+# if defined(_MSC_VER)
+# define SIMULATE_ID "MSVC"
+# endif
+# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+# if defined(_MSC_VER)
+ /* _MSC_VER = VVRR */
+# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+# endif
+
+#elif defined(__GNUC__) || defined(__GNUG__)
+# define COMPILER_ID "GNU"
+# if defined(__GNUC__)
+# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+# else
+# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
+# endif
+# if defined(__GNUC_MINOR__)
+# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+# endif
+# if defined(__GNUC_PATCHLEVEL__)
+# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+# endif
+
+#elif defined(_MSC_VER)
+# define COMPILER_ID "MSVC"
+ /* _MSC_VER = VVRR */
+# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+# if defined(_MSC_FULL_VER)
+# if _MSC_VER >= 1400
+ /* _MSC_FULL_VER = VVRRPPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+# else
+ /* _MSC_FULL_VER = VVRRPPPP */
+# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+# endif
+# endif
+# if defined(_MSC_BUILD)
+# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+# endif
+
+#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__)
+# define COMPILER_ID "ADSP"
+#if defined(__VISUALDSPVERSION__)
+ /* __VISUALDSPVERSION__ = 0xVVRRPP00 */
+# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24)
+# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF)
+# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF)
+#endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# define COMPILER_ID "IAR"
+# if defined(__VER__) && defined(__ICCARM__)
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
+# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+# endif
+
+
+/* These compilers are either not known or too old to define an
+ identification macro. Try to identify the platform and guess that
+ it is the native compiler. */
+#elif defined(__hpux) || defined(__hpua)
+# define COMPILER_ID "HP"
+
+#else /* unknown compiler */
+# define COMPILER_ID ""
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+#endif
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+/* Identify known platforms by name. */
+#if defined(__linux) || defined(__linux__) || defined(linux)
+# define PLATFORM_ID "Linux"
+
+#elif defined(__MSYS__)
+# define PLATFORM_ID "MSYS"
+
+#elif defined(__CYGWIN__)
+# define PLATFORM_ID "Cygwin"
+
+#elif defined(__MINGW32__)
+# define PLATFORM_ID "MinGW"
+
+#elif defined(__APPLE__)
+# define PLATFORM_ID "Darwin"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+# define PLATFORM_ID "Windows"
+
+#elif defined(__FreeBSD__) || defined(__FreeBSD)
+# define PLATFORM_ID "FreeBSD"
+
+#elif defined(__NetBSD__) || defined(__NetBSD)
+# define PLATFORM_ID "NetBSD"
+
+#elif defined(__OpenBSD__) || defined(__OPENBSD)
+# define PLATFORM_ID "OpenBSD"
+
+#elif defined(__sun) || defined(sun)
+# define PLATFORM_ID "SunOS"
+
+#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+# define PLATFORM_ID "AIX"
+
+#elif defined(__hpux) || defined(__hpux__)
+# define PLATFORM_ID "HP-UX"
+
+#elif defined(__HAIKU__)
+# define PLATFORM_ID "Haiku"
+
+#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+# define PLATFORM_ID "BeOS"
+
+#elif defined(__QNX__) || defined(__QNXNTO__)
+# define PLATFORM_ID "QNX"
+
+#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+# define PLATFORM_ID "Tru64"
+
+#elif defined(__riscos) || defined(__riscos__)
+# define PLATFORM_ID "RISCos"
+
+#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+# define PLATFORM_ID "SINIX"
+
+#elif defined(__UNIX_SV__)
+# define PLATFORM_ID "UNIX_SV"
+
+#elif defined(__bsdos__)
+# define PLATFORM_ID "BSDOS"
+
+#elif defined(_MPRAS) || defined(MPRAS)
+# define PLATFORM_ID "MP-RAS"
+
+#elif defined(__osf) || defined(__osf__)
+# define PLATFORM_ID "OSF1"
+
+#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+# define PLATFORM_ID "SCO_SV"
+
+#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+# define PLATFORM_ID "ULTRIX"
+
+#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+# define PLATFORM_ID "Xenix"
+
+#elif defined(__WATCOMC__)
+# if defined(__LINUX__)
+# define PLATFORM_ID "Linux"
+
+# elif defined(__DOS__)
+# define PLATFORM_ID "DOS"
+
+# elif defined(__OS2__)
+# define PLATFORM_ID "OS2"
+
+# elif defined(__WINDOWS__)
+# define PLATFORM_ID "Windows3x"
+
+# elif defined(__VXWORKS__)
+# define PLATFORM_ID "VxWorks"
+
+# else /* unknown platform */
+# define PLATFORM_ID
+# endif
+
+#elif defined(__INTEGRITY)
+# if defined(INT_178B)
+# define PLATFORM_ID "Integrity178"
+
+# else /* regular Integrity */
+# define PLATFORM_ID "Integrity"
+# endif
+
+#else /* unknown platform */
+# define PLATFORM_ID
+
+#endif
+
+/* For windows compilers MSVC and Intel we can determine
+ the architecture of the compiler being used. This is because
+ the compilers do not have flags that can change the architecture,
+ but rather depend on which compiler is being used
+*/
+#if defined(_WIN32) && defined(_MSC_VER)
+# if defined(_M_IA64)
+# define ARCHITECTURE_ID "IA64"
+
+# elif defined(_M_ARM64EC)
+# define ARCHITECTURE_ID "ARM64EC"
+
+# elif defined(_M_X64) || defined(_M_AMD64)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# elif defined(_M_ARM64)
+# define ARCHITECTURE_ID "ARM64"
+
+# elif defined(_M_ARM)
+# if _M_ARM == 4
+# define ARCHITECTURE_ID "ARMV4I"
+# elif _M_ARM == 5
+# define ARCHITECTURE_ID "ARMV5I"
+# else
+# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+# endif
+
+# elif defined(_M_MIPS)
+# define ARCHITECTURE_ID "MIPS"
+
+# elif defined(_M_SH)
+# define ARCHITECTURE_ID "SHx"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__WATCOMC__)
+# if defined(_M_I86)
+# define ARCHITECTURE_ID "I86"
+
+# elif defined(_M_IX86)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+# if defined(__ICCARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__ICCRX__)
+# define ARCHITECTURE_ID "RX"
+
+# elif defined(__ICCRH850__)
+# define ARCHITECTURE_ID "RH850"
+
+# elif defined(__ICCRL78__)
+# define ARCHITECTURE_ID "RL78"
+
+# elif defined(__ICCRISCV__)
+# define ARCHITECTURE_ID "RISCV"
+
+# elif defined(__ICCAVR__)
+# define ARCHITECTURE_ID "AVR"
+
+# elif defined(__ICC430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__ICCV850__)
+# define ARCHITECTURE_ID "V850"
+
+# elif defined(__ICC8051__)
+# define ARCHITECTURE_ID "8051"
+
+# elif defined(__ICCSTM8__)
+# define ARCHITECTURE_ID "STM8"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__ghs__)
+# if defined(__PPC64__)
+# define ARCHITECTURE_ID "PPC64"
+
+# elif defined(__ppc__)
+# define ARCHITECTURE_ID "PPC"
+
+# elif defined(__ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__x86_64__)
+# define ARCHITECTURE_ID "x64"
+
+# elif defined(__i386__)
+# define ARCHITECTURE_ID "X86"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#elif defined(__TI_COMPILER_VERSION__)
+# if defined(__TI_ARM__)
+# define ARCHITECTURE_ID "ARM"
+
+# elif defined(__MSP430__)
+# define ARCHITECTURE_ID "MSP430"
+
+# elif defined(__TMS320C28XX__)
+# define ARCHITECTURE_ID "TMS320C28x"
+
+# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
+# define ARCHITECTURE_ID "TMS320C6x"
+
+# else /* unknown architecture */
+# define ARCHITECTURE_ID ""
+# endif
+
+#else
+# define ARCHITECTURE_ID
+#endif
+
+/* Convert integer to decimal digit literals. */
+#define DEC(n) \
+ ('0' + (((n) / 10000000)%10)), \
+ ('0' + (((n) / 1000000)%10)), \
+ ('0' + (((n) / 100000)%10)), \
+ ('0' + (((n) / 10000)%10)), \
+ ('0' + (((n) / 1000)%10)), \
+ ('0' + (((n) / 100)%10)), \
+ ('0' + (((n) / 10)%10)), \
+ ('0' + ((n) % 10))
+
+/* Convert integer to hex digit literals. */
+#define HEX(n) \
+ ('0' + ((n)>>28 & 0xF)), \
+ ('0' + ((n)>>24 & 0xF)), \
+ ('0' + ((n)>>20 & 0xF)), \
+ ('0' + ((n)>>16 & 0xF)), \
+ ('0' + ((n)>>12 & 0xF)), \
+ ('0' + ((n)>>8 & 0xF)), \
+ ('0' + ((n)>>4 & 0xF)), \
+ ('0' + ((n) & 0xF))
+
+/* Construct a string literal encoding the version number. */
+#ifdef COMPILER_VERSION
+char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
+
+/* Construct a string literal encoding the version number components. */
+#elif defined(COMPILER_VERSION_MAJOR)
+char const info_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+ COMPILER_VERSION_MAJOR,
+# ifdef COMPILER_VERSION_MINOR
+ '.', COMPILER_VERSION_MINOR,
+# ifdef COMPILER_VERSION_PATCH
+ '.', COMPILER_VERSION_PATCH,
+# ifdef COMPILER_VERSION_TWEAK
+ '.', COMPILER_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct a string literal encoding the internal version number. */
+#ifdef COMPILER_VERSION_INTERNAL
+char const info_version_internal[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+ 'i','n','t','e','r','n','a','l','[',
+ COMPILER_VERSION_INTERNAL,']','\0'};
+#elif defined(COMPILER_VERSION_INTERNAL_STR)
+char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
+#endif
+
+/* Construct a string literal encoding the version number components. */
+#ifdef SIMULATE_VERSION_MAJOR
+char const info_simulate_version[] = {
+ 'I', 'N', 'F', 'O', ':',
+ 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+ SIMULATE_VERSION_MAJOR,
+# ifdef SIMULATE_VERSION_MINOR
+ '.', SIMULATE_VERSION_MINOR,
+# ifdef SIMULATE_VERSION_PATCH
+ '.', SIMULATE_VERSION_PATCH,
+# ifdef SIMULATE_VERSION_TWEAK
+ '.', SIMULATE_VERSION_TWEAK,
+# endif
+# endif
+# endif
+ ']','\0'};
+#endif
+
+/* Construct the string literal in pieces to prevent the source from
+ getting matched. Store it in a pointer rather than an array
+ because some compilers will just produce instructions to fill the
+ array rather than assigning a pointer to a static array. */
+char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
+
+
+#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
+# if defined(__INTEL_CXX11_MODE__)
+# if defined(__cpp_aggregate_nsdmi)
+# define CXX_STD 201402L
+# else
+# define CXX_STD 201103L
+# endif
+# else
+# define CXX_STD 199711L
+# endif
+#elif defined(_MSC_VER) && defined(_MSVC_LANG)
+# define CXX_STD _MSVC_LANG
+#else
+# define CXX_STD __cplusplus
+#endif
+
+const char* info_language_standard_default = "INFO" ":" "standard_default["
+#if CXX_STD > 202002L
+ "23"
+#elif CXX_STD > 201703L
+ "20"
+#elif CXX_STD >= 201703L
+ "17"
+#elif CXX_STD >= 201402L
+ "14"
+#elif CXX_STD >= 201103L
+ "11"
+#else
+ "98"
+#endif
+"]";
+
+const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+// !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode.
+#if (defined(__clang__) || defined(__GNUC__) || \
+ defined(__TI_COMPILER_VERSION__)) && \
+ !defined(__STRICT_ANSI__) && !defined(_MSC_VER)
+ "ON"
+#else
+ "OFF"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+ int require = 0;
+ require += info_compiler[argc];
+ require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+ require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+ require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+ require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+ require += info_simulate_version[argc];
+#endif
+#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+ require += info_cray[argc];
+#endif
+ require += info_language_standard_default[argc];
+ require += info_language_extensions_default[argc];
+ (void)argv;
+ return require;
+}
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.exe b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.exe
new file mode 100644
index 0000000..d241921
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.exe
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.vcxproj b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.vcxproj
new file mode 100644
index 0000000..2bf082a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.vcxproj
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CAE07175-D007-4FC3-BFE8-47B392814159}</ProjectGuid>
+ <RootNamespace>CompilerIdCXX</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+
+
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+
+
+
+
+ </PropertyGroup>
+
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup>
+
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v141</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+
+ </ImportGroup>
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>TurnOffAllWarnings</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+
+ <Link>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+
+ </Link>
+ <PostBuildEvent>
+ <Command>for %%i in (cl.exe) do %40echo CMAKE_CXX_COMPILER=%%~$PATH:i</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="CMakeCXXCompilerId.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+
+ </ImportGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj
new file mode 100644
index 0000000..f963658
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlog
new file mode 100644
index 0000000..8c79403
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlog
new file mode 100644
index 0000000..ebb0c38
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlog
new file mode 100644
index 0000000..5a23772
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate
new file mode 100644
index 0000000..17c7430
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate
@@ -0,0 +1,2 @@
+#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
+Debug|Win32|D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdCXX\|
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlog
new file mode 100644
index 0000000..e4d58e8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlog
new file mode 100644
index 0000000..270e397
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlog b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlog
new file mode 100644
index 0000000..864cc81
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlog
Binary files differ
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate
new file mode 100644
index 0000000..9bf662b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate
@@ -0,0 +1,2 @@
+#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0
+Debug|Win32|D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\|
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.txt b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.txt
new file mode 100644
index 0000000..80259da
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.txt
@@ -0,0 +1 @@
+C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/Common7/IDE/VC/VCTargets
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.vcxproj b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.vcxproj
new file mode 100644
index 0000000..84ac03b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/VCTargetsPath.vcxproj
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F3FC6D86-508D-3FB1-96D2-995F08B142EC}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
+ <PropertyGroup Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
+ <ItemDefinitionGroup>
+ <PostBuildEvent>
+ <Command>echo VCTargetsPath=$(VCTargetsPath)</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/generate.stamp.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/generate.stamp.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/3f042071a51acdc6d8fcb5e7be7244c8/generate.stamp.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/455517aeb2285a20077dbce51065d1ef/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/455517aeb2285a20077dbce51065d1ef/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/455517aeb2285a20077dbce51065d1ef/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/5db6461968e3a28c7176c305697cc35c/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/5db6461968e3a28c7176c305697cc35c/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/5db6461968e3a28c7176c305697cc35c/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/6ddefecedef78174b7ed9b2bc8a1e035/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/6ddefecedef78174b7ed9b2bc8a1e035/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/6ddefecedef78174b7ed9b2bc8a1e035/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/9ab13db7d2176474a16e440b6b1b97a8/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/9ab13db7d2176474a16e440b6b1b97a8/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/9ab13db7d2176474a16e440b6b1b97a8/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeError.log b/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeError.log
new file mode 100644
index 0000000..e554191
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeError.log
@@ -0,0 +1,16 @@
+Determining if the include file pthread.h exists failed with the following output:
+Change Dir: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeTmp
+
+Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/MSBuild/15.0/Bin/MSBuild.exe cmTC_ba595.vcxproj /p:Configuration=Debug /p:Platform=Win32 /p:VisualStudioVersion=15.0 /v:m && 用于 .NET Framework 的 Microsoft (R) 生成引擎版本 15.9.21+g9802d43bc3
+版权所有(C) Microsoft Corporation。保留所有权利。
+
+ 用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.16.27045 版
+ 版权所有(C) Microsoft Corporation。保留所有权利。
+
+ cl /c /Zi /W3 /WX- /diagnostics:classic /Od /Ob0 /Oy- /D _MBCS /D WIN32 /D _WINDOWS /D "CMAKE_INTDIR=\"Debug\"" /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_ba595.dir\Debug\\" /Fd"cmTC_ba595.dir\Debug\vc141.pdb" /Gd /TC /analyze- /errorReport:queue D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\CMakeTmp\CheckIncludeFile.c
+ CheckIncludeFile.c
+
+D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\CMakeTmp\CheckIncludeFile.c(1): fatal error C1083: 无法打开包括文件: “pthread.h”: No such file or directory [D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\CMakeTmp\cmTC_ba595.vcxproj]
+
+
+
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeOutput.log b/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeOutput.log
new file mode 100644
index 0000000..56666a2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeOutput.log
@@ -0,0 +1,123 @@
+The system is: Windows - 10.0.19042 - AMD64
+Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded.
+Compiler:
+Build flags:
+Id flags:
+
+The output was:
+0
+用于 .NET Framework 的 Microsoft (R) 生成引擎版本 15.9.21+g9802d43bc3
+版权所有(C) Microsoft Corporation。保留所有权利。
+
+生成启动时间为 2021/12/10 0:31:45。
+节点 1 上的项目“D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdC\CompilerIdC.vcxproj”(默认目标)。
+PrepareForBuild:
+ 正在创建目录“Debug\”。
+ 正在创建目录“Debug\CompilerIdC.tlog\”。
+InitializeBuildStatus:
+ 正在创建“Debug\CompilerIdC.tlog\unsuccessfulbuild”,因为已指定“AlwaysCreate”。
+ClCompile:
+ C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86\CL.exe /c /nologo /W0 /WX- /diagnostics:classic /Od /Oy- /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"Debug\\" /Fd"Debug\vc141.pdb" /Gd /TC /analyze- /FC /errorReport:queue CMakeCCompilerId.c
+ CMakeCCompilerId.c
+Link:
+ C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86\link.exe /ERRORREPORT:QUEUE /OUT:".\CompilerIdC.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdC.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdC.lib" /MACHINE:X86 /SAFESEH Debug\CMakeCCompilerId.obj
+ CompilerIdC.vcxproj -> D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdC\.\CompilerIdC.exe
+PostBuildEvent:
+ for %%i in (cl.exe) do @echo CMAKE_C_COMPILER=%%~$PATH:i
+ :VCEnd
+ CMAKE_C_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\Hostx86\x86\cl.exe
+FinalizeBuildStatus:
+ 正在删除文件“Debug\CompilerIdC.tlog\unsuccessfulbuild”。
+ 正在对“Debug\CompilerIdC.tlog\CompilerIdC.lastbuildstate”执行 Touch 任务。
+已完成生成项目“D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdC\CompilerIdC.vcxproj”(默认目标)的操作。
+
+已成功生成。
+ 0 个警告
+ 0 个错误
+
+已用时间 00:00:02.03
+
+
+Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CompilerIdC.exe"
+
+Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CompilerIdC.vcxproj"
+
+The C compiler identification is MSVC, found in "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdC/CompilerIdC.exe"
+
+Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded.
+Compiler:
+Build flags:
+Id flags:
+
+The output was:
+0
+用于 .NET Framework 的 Microsoft (R) 生成引擎版本 15.9.21+g9802d43bc3
+版权所有(C) Microsoft Corporation。保留所有权利。
+
+生成启动时间为 2021/12/10 0:31:48。
+节点 1 上的项目“D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdCXX\CompilerIdCXX.vcxproj”(默认目标)。
+PrepareForBuild:
+ 正在创建目录“Debug\”。
+ 正在创建目录“Debug\CompilerIdCXX.tlog\”。
+InitializeBuildStatus:
+ 正在创建“Debug\CompilerIdCXX.tlog\unsuccessfulbuild”,因为已指定“AlwaysCreate”。
+ClCompile:
+ C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86\CL.exe /c /nologo /W0 /WX- /diagnostics:classic /Od /Oy- /D _MBCS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"Debug\\" /Fd"Debug\vc141.pdb" /Gd /TP /analyze- /FC /errorReport:queue CMakeCXXCompilerId.cpp
+ CMakeCXXCompilerId.cpp
+Link:
+ C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\HostX86\x86\link.exe /ERRORREPORT:QUEUE /OUT:".\CompilerIdCXX.exe" /INCREMENTAL:NO /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /PDB:".\CompilerIdCXX.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\CompilerIdCXX.lib" /MACHINE:X86 /SAFESEH Debug\CMakeCXXCompilerId.obj
+ CompilerIdCXX.vcxproj -> D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdCXX\.\CompilerIdCXX.exe
+PostBuildEvent:
+ for %%i in (cl.exe) do @echo CMAKE_CXX_COMPILER=%%~$PATH:i
+ :VCEnd
+ CMAKE_CXX_COMPILER=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\bin\Hostx86\x86\cl.exe
+FinalizeBuildStatus:
+ 正在删除文件“Debug\CompilerIdCXX.tlog\unsuccessfulbuild”。
+ 正在对“Debug\CompilerIdCXX.tlog\CompilerIdCXX.lastbuildstate”执行 Touch 任务。
+已完成生成项目“D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CompilerIdCXX\CompilerIdCXX.vcxproj”(默认目标)的操作。
+
+已成功生成。
+ 0 个警告
+ 0 个错误
+
+已用时间 00:00:01.06
+
+
+Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.exe"
+
+Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CompilerIdCXX.vcxproj"
+
+The CXX compiler identification is MSVC, found in "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CompilerIdCXX/CompilerIdCXX.exe"
+
+Detecting C compiler ABI info compiled with the following output:
+Change Dir: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeTmp
+
+Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/MSBuild/15.0/Bin/MSBuild.exe cmTC_33301.vcxproj /p:Configuration=Debug /p:Platform=Win32 /p:VisualStudioVersion=15.0 /v:m && 用于 .NET Framework 的 Microsoft (R) 生成引擎版本 15.9.21+g9802d43bc3
+版权所有(C) Microsoft Corporation。保留所有权利。
+
+ 用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.16.27045 版
+ 版权所有(C) Microsoft Corporation。保留所有权利。
+
+ cl /c /Zi /W3 /WX- /diagnostics:classic /Od /Ob0 /Oy- /D _MBCS /D WIN32 /D _WINDOWS /D "CMAKE_INTDIR=\"Debug\"" /Gm- /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"cmTC_33301.dir\Debug\\" /Fd"cmTC_33301.dir\Debug\vc141.pdb" /Gd /TC /analyze- /errorReport:queue "C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c"
+ CMakeCCompilerABI.c
+
+ cmTC_33301.vcxproj -> D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\CMakeTmp\Debug\cmTC_33301.exe
+
+
+
+Detecting CXX compiler ABI info compiled with the following output:
+Change Dir: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/CMakeTmp
+
+Run Build Command(s):C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/MSBuild/15.0/Bin/MSBuild.exe cmTC_3f802.vcxproj /p:Configuration=Debug /p:Platform=Win32 /p:VisualStudioVersion=15.0 /v:m && 用于 .NET Framework 的 Microsoft (R) 生成引擎版本 15.9.21+g9802d43bc3
+版权所有(C) Microsoft Corporation。保留所有权利。
+
+ 用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.16.27045 版
+ 版权所有(C) Microsoft Corporation。保留所有权利。
+
+ cl /c /Zi /W3 /WX- /diagnostics:classic /Od /Ob0 /Oy- /D _MBCS /D WIN32 /D _WINDOWS /D "CMAKE_INTDIR=\"Debug\"" /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /GR /Fo"cmTC_3f802.dir\Debug\\" /Fd"cmTC_3f802.dir\Debug\vc141.pdb" /Gd /TP /analyze- /errorReport:queue "C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp"
+ CMakeCXXCompilerABI.cpp
+
+ cmTC_3f802.vcxproj -> D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\CMakeTmp\Debug\cmTC_3f802.exe
+
+
+
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/TargetDirectories.txt b/Client/ThirdParty/Box2D/proj/CMakeFiles/TargetDirectories.txt
new file mode 100644
index 0000000..312a8c9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/TargetDirectories.txt
@@ -0,0 +1,17 @@
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/ALL_BUILD.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/ZERO_CHECK.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/box2d.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/unit_test.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/glad.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/glfw.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/imgui.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/sajson.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/INSTALL.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/testbed.dir
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/INSTALL.dir
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/bfe9de955132cd9d067c24acf7d98bef/INSTALL_force.rule b/Client/ThirdParty/Box2D/proj/CMakeFiles/bfe9de955132cd9d067c24acf7d98bef/INSTALL_force.rule
new file mode 100644
index 0000000..2d3998c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/bfe9de955132cd9d067c24acf7d98bef/INSTALL_force.rule
@@ -0,0 +1 @@
+# generated from CMake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/cmake.check_cache b/Client/ThirdParty/Box2D/proj/CMakeFiles/cmake.check_cache
new file mode 100644
index 0000000..3dccd73
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/cmake.check_cache
@@ -0,0 +1 @@
+# This file is generated by cmake for dependency checking of the CMakeCache.txt file
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..ac4d405
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,96 @@
+# CMake generation dependency list for this directory.
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCCompilerABI.c
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCInformation.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCXXCompiler.cmake.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCXXCompilerABI.cpp
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCXXInformation.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineCXXCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineRCCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeGenericSystem.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeRCCompiler.cmake.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeRCInformation.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeSystem.cmake.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeTestCXXCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakeTestRCCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Comeau-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/HP-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/MSVC-C.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/MSVC-CXX.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/XL-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CompilerId/VS-10.vcxproj.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/GNUInstallDirs.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Platform/Windows-Determine-CXX.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Platform/Windows-MSVC-C.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Platform/Windows-MSVC-CXX.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Platform/Windows-MSVC.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Platform/Windows.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Platform/WindowsPaths.cmake
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/CMakeLists.txt
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCCompiler.cmake
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeCXXCompiler.cmake
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeRCCompiler.cmake
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/3.22.0-rc2/CMakeSystem.cmake
diff --git a/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.list b/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.list
new file mode 100644
index 0000000..9ff9311
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp.list
@@ -0,0 +1,8 @@
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
diff --git a/Client/ThirdParty/Box2D/proj/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/INSTALL.vcxproj
new file mode 100644
index 0000000..53a7ff2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3f042071a51acdc6d8fcb5e7be7244c8\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..8aed76c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3f042071a51acdc6d8fcb5e7be7244c8\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj b/Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj
new file mode 100644
index 0000000..afb370d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>ZERO_CHECK</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3f042071a51acdc6d8fcb5e7be7244c8\generate.stamp.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Checking Build System</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/box2d.sln
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Checking Build System</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/box2d.sln
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Checking Build System</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/box2d.sln
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Checking Build System</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-list CMakeFiles/generate.stamp.list --vs-solution-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/box2d.sln
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCCompilerABI.c;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXCompilerABI.cpp;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCXXInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCommonLanguageInclude.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompileFeatures.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerABI.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeDetermineSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeFindBinUtils.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeLanguageInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitIncludeInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseImplicitLinkInfo.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeParseLibraryArchitecture.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeRCInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystem.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCXXCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakeTestRCCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ADSP-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMCC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\ARMClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\AppleClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Borland-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Bruce-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\CMakeCommonCompilerMacros.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Clang-DetermineCompilerInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Comeau-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Compaq-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Cray-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Embarcadero-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Fujitsu-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\FujitsuClang-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GHS-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\GNU-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\HP-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IAR-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-C-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IBMCPP-CXX-DetermineVersionInternal.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Intel-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\IntelLLVM-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\MSVC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVHPC-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\NVIDIA-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\OpenWatcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PGI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\PathScale-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SCO-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SDCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\SunPro-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TI-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\TinyCC-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\VisualAge-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\Watcom-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XL-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\XLClang-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-C-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Compiler\zOS-CXX-DetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CompilerId\VS-10.vcxproj.in;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\GNUInstallDirs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\FeatureTesting.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-Determine-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-C.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC-CXX.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows-MSVC.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Platform\WindowsPaths.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeCXXCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeRCCompiler.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3.22.0-rc2\CMakeSystem.cmake;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\CMakeLists.txt;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj.filters b/Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj.filters
new file mode 100644
index 0000000..9347418
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/ZERO_CHECK.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\3f042071a51acdc6d8fcb5e7be7244c8\generate.stamp.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/box2d.sln b/Client/ThirdParty/Box2D/proj/box2d.sln
new file mode 100644
index 0000000..e4d5968
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/box2d.sln
@@ -0,0 +1,164 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CMakePredefinedTargets", "CMakePredefinedTargets", "{71FC76BE-FD8A-37AA-B070-4AD8DFF9C5B9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testbed", "testbed\testbed.vcxproj", "{A168F045-AE5A-3724-B305-AA2A8C4749BA}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E} = {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}
+ {29408AB9-D01F-3745-93F3-94160B037370} = {29408AB9-D01F-3745-93F3-94160B037370}
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92} = {7F32E689-3D5C-3885-9B34-0860DAE8BE92}
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7} = {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380} = {EE68EE8F-E321-3CD7-A04C-C0A66C401380}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{2BA85667-24FF-36F3-825F-79CEC5AB3361}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E} = {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}
+ {29408AB9-D01F-3745-93F3-94160B037370} = {29408AB9-D01F-3745-93F3-94160B037370}
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92} = {7F32E689-3D5C-3885-9B34-0860DAE8BE92}
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7} = {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380} = {EE68EE8F-E321-3CD7-A04C-C0A66C401380}
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA} = {A168F045-AE5A-3724-B305-AA2A8C4749BA}
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52} = {7ED467E4-0B19-329B-B677-9C4C01A3EC52}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INSTALL", "INSTALL.vcxproj", "{9AC23237-8AB3-35CD-9010-F378760CC445}"
+ ProjectSection(ProjectDependencies) = postProject
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361} = {2BA85667-24FF-36F3-825F-79CEC5AB3361}
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "box2d", "src\box2d.vcxproj", "{4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glad", "extern\glad\glad.vcxproj", "{29408AB9-D01F-3745-93F3-94160B037370}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glfw", "extern\glfw\glfw.vcxproj", "{7F32E689-3D5C-3885-9B34-0860DAE8BE92}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "extern\imgui\imgui.vcxproj", "{B288C97F-F14F-33EA-9CAC-B55922D1FDC7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sajson", "extern\sajson\sajson.vcxproj", "{EE68EE8F-E321-3CD7-A04C-C0A66C401380}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unit_test", "unit-test\unit_test.vcxproj", "{7ED467E4-0B19-329B-B677-9C4C01A3EC52}"
+ ProjectSection(ProjectDependencies) = postProject
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E} = {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ MinSizeRel|Win32 = MinSizeRel|Win32
+ RelWithDebInfo|Win32 = RelWithDebInfo|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.Debug|Win32.Build.0 = Debug|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.Release|Win32.ActiveCfg = Release|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.Release|Win32.Build.0 = Release|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {A168F045-AE5A-3724-B305-AA2A8C4749BA}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.Debug|Win32.Build.0 = Debug|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.Release|Win32.ActiveCfg = Release|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.Release|Win32.Build.0 = Release|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {9AC23237-8AB3-35CD-9010-F378760CC445}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9AC23237-8AB3-35CD-9010-F378760CC445}.Release|Win32.ActiveCfg = Release|Win32
+ {9AC23237-8AB3-35CD-9010-F378760CC445}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {9AC23237-8AB3-35CD-9010-F378760CC445}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.Debug|Win32.Build.0 = Debug|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.Release|Win32.ActiveCfg = Release|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.Release|Win32.Build.0 = Release|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.Debug|Win32.Build.0 = Debug|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.Release|Win32.ActiveCfg = Release|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.Release|Win32.Build.0 = Release|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.Debug|Win32.ActiveCfg = Debug|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.Debug|Win32.Build.0 = Debug|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.Release|Win32.ActiveCfg = Release|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.Release|Win32.Build.0 = Release|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {29408AB9-D01F-3745-93F3-94160B037370}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.Debug|Win32.Build.0 = Debug|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.Release|Win32.ActiveCfg = Release|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.Release|Win32.Build.0 = Release|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {7F32E689-3D5C-3885-9B34-0860DAE8BE92}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.Debug|Win32.Build.0 = Debug|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.Release|Win32.ActiveCfg = Release|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.Release|Win32.Build.0 = Release|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {B288C97F-F14F-33EA-9CAC-B55922D1FDC7}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.Debug|Win32.ActiveCfg = Debug|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.Debug|Win32.Build.0 = Debug|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.Release|Win32.ActiveCfg = Release|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.Release|Win32.Build.0 = Release|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {EE68EE8F-E321-3CD7-A04C-C0A66C401380}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.Debug|Win32.Build.0 = Debug|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.Release|Win32.ActiveCfg = Release|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.Release|Win32.Build.0 = Release|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
+ {7ED467E4-0B19-329B-B677-9C4C01A3EC52}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {2BA85667-24FF-36F3-825F-79CEC5AB3361} = {71FC76BE-FD8A-37AA-B070-4AD8DFF9C5B9}
+ {9AC23237-8AB3-35CD-9010-F378760CC445} = {71FC76BE-FD8A-37AA-B070-4AD8DFF9C5B9}
+ {BE3FCA9C-E0F7-3263-BFDC-D625CD827C80} = {71FC76BE-FD8A-37AA-B070-4AD8DFF9C5B9}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {97ED1C2D-8C4A-3AB8-B57A-98BCD6D53BC0}
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Client/ThirdParty/Box2D/proj/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/cmake_install.cmake
new file mode 100644
index 0000000..c934970
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/cmake_install.cmake
@@ -0,0 +1,60 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
+if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/include" TYPE DIRECTORY FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/include/box2d")
+endif()
+
+if(NOT CMAKE_INSTALL_LOCAL_ONLY)
+ # Include the install script for each subdirectory.
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/cmake_install.cmake")
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/cmake_install.cmake")
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/cmake_install.cmake")
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/cmake_install.cmake")
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/cmake_install.cmake")
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/cmake_install.cmake")
+ include("D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/cmake_install.cmake")
+
+endif()
+
+if(CMAKE_INSTALL_COMPONENT)
+ set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
+else()
+ set(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
+endif()
+
+string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
+ "${CMAKE_INSTALL_MANIFEST_FILES}")
+file(WRITE "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/${CMAKE_INSTALL_MANIFEST}"
+ "${CMAKE_INSTALL_MANIFEST_CONTENT}")
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..360d398
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,2 @@
+# CMake generation dependency list for this directory.
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj
new file mode 100644
index 0000000..190e04c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\14f8a92cc8883d19b638672092016c39\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..73b4ed6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\14f8a92cc8883d19b638672092016c39\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/extern/glad/cmake_install.cmake
new file mode 100644
index 0000000..1fb9427
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/cmake_install.cmake
@@ -0,0 +1,34 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glad
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj b/Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj
new file mode 100644
index 0000000..586e8c1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj
@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{29408AB9-D01F-3745-93F3-94160B037370}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>glad</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">glad.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">glad</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">glad.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">glad</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">glad.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">glad</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">glad.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">glad</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.lib</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glad/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glad/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\src\gl.c" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include\glad\gl.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include\KHR\khrplatform.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj.filters
new file mode 100644
index 0000000..e492470
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glad/glad.vcxproj.filters
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\src\gl.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include\glad\gl.h">
+ <Filter>include\glad</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include\KHR\khrplatform.h">
+ <Filter>include\KHR</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="include">
+ <UniqueIdentifier>{2B754068-BECE-3CED-9144-9AA210967EB9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\KHR">
+ <UniqueIdentifier>{247E20A5-3102-3368-AEA3-7C6A2608F1DA}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\glad">
+ <UniqueIdentifier>{6C0DE5BF-9EF7-3060-890B-9D628058E4B7}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src">
+ <UniqueIdentifier>{A24BD43B-5C67-30C5-8AF1-02F4AF819691}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..ee5692b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,10 @@
+# CMake generation dependency list for this directory.
+C:/Program Files/CMake/share/cmake-3.22/Modules/CheckCSourceCompiles.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CheckIncludeFile.c.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/CheckIncludeFile.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/CheckLibraryExists.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/FindPackageMessage.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/FindThreads.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/Internal/CheckSourceCompiles.cmake
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj
new file mode 100644
index 0000000..c925fa4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\455517aeb2285a20077dbce51065d1ef\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..774c4c0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\455517aeb2285a20077dbce51065d1ef\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/extern/glfw/cmake_install.cmake
new file mode 100644
index 0000000..3e26128
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/cmake_install.cmake
@@ -0,0 +1,34 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glfw
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj b/Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj
new file mode 100644
index 0000000..8709b95
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7F32E689-3D5C-3885-9B34-0860DAE8BE92}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>glfw</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">glfw.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">glfw</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">glfw.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">glfw</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">glfw.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">glfw</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">glfw.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">glfw</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.lib</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/glfw/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/glfw/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\CheckCSourceCompiles.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.c.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckIncludeFile.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\CheckLibraryExists.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageHandleStandardArgs.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindPackageMessage.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\FindThreads.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\Internal\CheckSourceCompiles.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\context.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\init.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\input.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\monitor.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\vulkan.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\window.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_init.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_joystick.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_monitor.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_time.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_thread.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_window.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\wgl_context.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\egl_context.c" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\osmesa_context.c" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\internal.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\mappings.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include\GLFW\glfw3.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include\GLFW\glfw3native.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_platform.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_joystick.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\wgl_context.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\egl_context.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\osmesa_context.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj.filters
new file mode 100644
index 0000000..ec923bf
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/glfw/glfw.vcxproj.filters
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\context.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\init.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\input.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\monitor.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\vulkan.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\window.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_init.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_joystick.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_monitor.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_time.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_thread.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_window.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\wgl_context.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\egl_context.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\osmesa_context.c">
+ <Filter>src</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\internal.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\mappings.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include\GLFW\glfw3.h">
+ <Filter>include\GLFW</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include\GLFW\glfw3native.h">
+ <Filter>include\GLFW</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_platform.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\win32_joystick.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\wgl_context.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\egl_context.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\src\osmesa_context.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="include">
+ <UniqueIdentifier>{2B754068-BECE-3CED-9144-9AA210967EB9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\GLFW">
+ <UniqueIdentifier>{8046E0DF-0536-3330-8D73-CADA49EA10AD}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src">
+ <UniqueIdentifier>{A24BD43B-5C67-30C5-8AF1-02F4AF819691}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..0fee0f9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,2 @@
+# CMake generation dependency list for this directory.
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj
new file mode 100644
index 0000000..ad0fed8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\9ab13db7d2176474a16e440b6b1b97a8\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..3cf65ec
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\9ab13db7d2176474a16e440b6b1b97a8\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/extern/imgui/cmake_install.cmake
new file mode 100644
index 0000000..78732f0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/cmake_install.cmake
@@ -0,0 +1,34 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/imgui
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj b/Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj
new file mode 100644
index 0000000..449cae4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{B288C97F-F14F-33EA-9CAC-B55922D1FDC7}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>imgui</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">imgui.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">imgui</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">imgui.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">imgui</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">imgui.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">imgui</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">imgui.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">imgui</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.lib</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/imgui/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/imgui/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_demo.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_draw.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_widgets.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imconfig.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_internal.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imstb_rectpack.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imstb_textedit.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imstb_truetype.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj.filters
new file mode 100644
index 0000000..513764a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/imgui/imgui.vcxproj.filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_demo.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_draw.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_widgets.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imconfig.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imgui_internal.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imstb_rectpack.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imstb_textedit.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\imstb_truetype.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..6358b51
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,2 @@
+# CMake generation dependency list for this directory.
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj
new file mode 100644
index 0000000..3966786
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\049e1eb7380682ec4cf9a2c62dad57db\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..068dfc2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\049e1eb7380682ec4cf9a2c62dad57db\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/extern/sajson/cmake_install.cmake
new file mode 100644
index 0000000..9de7c41
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/cmake_install.cmake
@@ -0,0 +1,34 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/sajson
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj b/Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj
new file mode 100644
index 0000000..0a2534b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{EE68EE8F-E321-3CD7-A04C-C0A66C401380}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>sajson</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">sajson.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">sajson</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">sajson.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">sajson</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">sajson.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">sajson</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">sajson.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">sajson</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.lib</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/extern/sajson/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/extern/sajson/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\sajson.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\sajson.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj.filters b/Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj.filters
new file mode 100644
index 0000000..cfcef01
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/extern/sajson/sajson.vcxproj.filters
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\sajson.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\sajson.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-debug.cmake b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-debug.cmake
new file mode 100644
index 0000000..786d951
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-debug.cmake
@@ -0,0 +1,19 @@
+#----------------------------------------------------------------
+# Generated CMake target import file for configuration "Debug".
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Import target "box2d::box2d" for configuration "Debug"
+set_property(TARGET box2d::box2d APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+set_target_properties(box2d::box2d PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
+ IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/box2d.lib"
+ )
+
+list(APPEND _IMPORT_CHECK_TARGETS box2d::box2d )
+list(APPEND _IMPORT_CHECK_FILES_FOR_box2d::box2d "${_IMPORT_PREFIX}/lib/box2d.lib" )
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-minsizerel.cmake b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-minsizerel.cmake
new file mode 100644
index 0000000..330120c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-minsizerel.cmake
@@ -0,0 +1,19 @@
+#----------------------------------------------------------------
+# Generated CMake target import file for configuration "MinSizeRel".
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Import target "box2d::box2d" for configuration "MinSizeRel"
+set_property(TARGET box2d::box2d APPEND PROPERTY IMPORTED_CONFIGURATIONS MINSIZEREL)
+set_target_properties(box2d::box2d PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_MINSIZEREL "CXX"
+ IMPORTED_LOCATION_MINSIZEREL "${_IMPORT_PREFIX}/lib/box2d.lib"
+ )
+
+list(APPEND _IMPORT_CHECK_TARGETS box2d::box2d )
+list(APPEND _IMPORT_CHECK_FILES_FOR_box2d::box2d "${_IMPORT_PREFIX}/lib/box2d.lib" )
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-release.cmake b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-release.cmake
new file mode 100644
index 0000000..e29ee82
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-release.cmake
@@ -0,0 +1,19 @@
+#----------------------------------------------------------------
+# Generated CMake target import file for configuration "Release".
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Import target "box2d::box2d" for configuration "Release"
+set_property(TARGET box2d::box2d APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+set_target_properties(box2d::box2d PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
+ IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/box2d.lib"
+ )
+
+list(APPEND _IMPORT_CHECK_TARGETS box2d::box2d )
+list(APPEND _IMPORT_CHECK_FILES_FOR_box2d::box2d "${_IMPORT_PREFIX}/lib/box2d.lib" )
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-relwithdebinfo.cmake b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-relwithdebinfo.cmake
new file mode 100644
index 0000000..a41bfce
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-relwithdebinfo.cmake
@@ -0,0 +1,19 @@
+#----------------------------------------------------------------
+# Generated CMake target import file for configuration "RelWithDebInfo".
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Import target "box2d::box2d" for configuration "RelWithDebInfo"
+set_property(TARGET box2d::box2d APPEND PROPERTY IMPORTED_CONFIGURATIONS RELWITHDEBINFO)
+set_target_properties(box2d::box2d PROPERTIES
+ IMPORTED_LINK_INTERFACE_LANGUAGES_RELWITHDEBINFO "CXX"
+ IMPORTED_LOCATION_RELWITHDEBINFO "${_IMPORT_PREFIX}/lib/box2d.lib"
+ )
+
+list(APPEND _IMPORT_CHECK_TARGETS box2d::box2d )
+list(APPEND _IMPORT_CHECK_FILES_FOR_box2d::box2d "${_IMPORT_PREFIX}/lib/box2d.lib" )
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig.cmake b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig.cmake
new file mode 100644
index 0000000..5a32fdc
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig.cmake
@@ -0,0 +1,94 @@
+# Generated by CMake
+
+if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.6)
+ message(FATAL_ERROR "CMake >= 2.6.0 required")
+endif()
+cmake_policy(PUSH)
+cmake_policy(VERSION 2.6...3.20)
+#----------------------------------------------------------------
+# Generated CMake target import file.
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Protect against multiple inclusion, which would fail when already imported targets are added once more.
+set(_targetsDefined)
+set(_targetsNotDefined)
+set(_expectedTargets)
+foreach(_expectedTarget box2d::box2d)
+ list(APPEND _expectedTargets ${_expectedTarget})
+ if(NOT TARGET ${_expectedTarget})
+ list(APPEND _targetsNotDefined ${_expectedTarget})
+ endif()
+ if(TARGET ${_expectedTarget})
+ list(APPEND _targetsDefined ${_expectedTarget})
+ endif()
+endforeach()
+if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
+ unset(_targetsDefined)
+ unset(_targetsNotDefined)
+ unset(_expectedTargets)
+ set(CMAKE_IMPORT_FILE_VERSION)
+ cmake_policy(POP)
+ return()
+endif()
+if(NOT "${_targetsDefined}" STREQUAL "")
+ message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
+endif()
+unset(_targetsDefined)
+unset(_targetsNotDefined)
+unset(_expectedTargets)
+
+
+# Compute the installation prefix relative to this file.
+get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+if(_IMPORT_PREFIX STREQUAL "/")
+ set(_IMPORT_PREFIX "")
+endif()
+
+# Create imported target box2d::box2d
+add_library(box2d::box2d STATIC IMPORTED)
+
+set_target_properties(box2d::box2d PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
+)
+
+# Load information for each installed configuration.
+get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+file(GLOB CONFIG_FILES "${_DIR}/box2dConfig-*.cmake")
+foreach(f ${CONFIG_FILES})
+ include(${f})
+endforeach()
+
+# Cleanup temporary variables.
+set(_IMPORT_PREFIX)
+
+# Loop over all imported files and verify that they actually exist
+foreach(target ${_IMPORT_CHECK_TARGETS} )
+ foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
+ if(NOT EXISTS "${file}" )
+ message(FATAL_ERROR "The imported target \"${target}\" references the file
+ \"${file}\"
+but this file does not exist. Possible reasons include:
+* The file was deleted, renamed, or moved to another location.
+* An install or uninstall procedure did not complete successfully.
+* The installation package was faulty and contained
+ \"${CMAKE_CURRENT_LIST_FILE}\"
+but not all the files it references.
+")
+ endif()
+ endforeach()
+ unset(_IMPORT_CHECK_FILES_FOR_${target})
+endforeach()
+unset(_IMPORT_CHECK_TARGETS)
+
+# This file does not depend on other imported targets which have
+# been exported from the same project but in a separate export set.
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
+cmake_policy(POP)
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..36bdce4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,5 @@
+# CMake generation dependency list for this directory.
+C:/Program Files/CMake/share/cmake-3.22/Modules/BasicConfigVersion-SameMajorVersion.cmake.in
+C:/Program Files/CMake/share/cmake-3.22/Modules/CMakePackageConfigHelpers.cmake
+C:/Program Files/CMake/share/cmake-3.22/Modules/WriteBasicConfigVersionFile.cmake
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/src/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj
new file mode 100644
index 0000000..c715096
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\5db6461968e3a28c7176c305697cc35c\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..d373820
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\5db6461968e3a28c7176c305697cc35c\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/src/box2d.vcxproj b/Client/ThirdParty/Box2D/proj/src/box2d.vcxproj
new file mode 100644
index 0000000..4c28ee3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/box2d.vcxproj
@@ -0,0 +1,374 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>box2d</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">box2d.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">box2d</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">box2d.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">box2d</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">box2d.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">box2d</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.lib</TargetExt>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">box2d.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">box2d</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.lib</TargetExt>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\Debug\box2d.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <ProgramDataBaseFileName>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\Release\box2d.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <ProgramDataBaseFileName>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\MinSizeRel\box2d.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\RelWithDebInfo\box2d.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Lib>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/src/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/src/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/src/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/src/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">C:\Program Files\CMake\share\cmake-3.22\Modules\BasicConfigVersion-SameMajorVersion.cmake.in;C:\Program Files\CMake\share\cmake-3.22\Modules\CMakePackageConfigHelpers.cmake;C:\Program Files\CMake\share\cmake-3.22\Modules\WriteBasicConfigVersionFile.cmake;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_broad_phase.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_chain_shape.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_circle_shape.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collide_circle.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collide_edge.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collide_polygon.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collision.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_distance.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_dynamic_tree.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_edge_shape.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_polygon_shape.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_time_of_impact.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_block_allocator.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_draw.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_math.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_settings.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_stack_allocator.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_timer.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_body.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_circle_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_circle_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_polygon_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_polygon_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_circle_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_circle_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact_manager.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact_solver.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact_solver.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_distance_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_circle_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_circle_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_polygon_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_polygon_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_fixture.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_friction_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_gear_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_island.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_island.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_motor_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_mouse_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_circle_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_circle_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_contact.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_contact.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_prismatic_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_pulley_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_revolute_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_weld_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_wheel_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_world.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_world_callbacks.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\rope\b2_rope.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_api.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_block_allocator.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_body.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_broad_phase.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_chain_shape.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_circle_shape.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_collision.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_common.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_contact.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_contact_manager.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_distance.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_distance_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_draw.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_dynamic_tree.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_edge_shape.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_fixture.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_friction_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_gear_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_growable_stack.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_math.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_motor_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_mouse_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_polygon_shape.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_prismatic_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_pulley_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_revolute_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_rope.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_settings.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_shape.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_stack_allocator.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_time_of_impact.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_timer.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_time_step.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_types.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_weld_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_wheel_joint.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_world.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_world_callbacks.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\box2d.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/src/box2d.vcxproj.filters b/Client/ThirdParty/Box2D/proj/src/box2d.vcxproj.filters
new file mode 100644
index 0000000..6a9ca63
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/box2d.vcxproj.filters
@@ -0,0 +1,315 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_broad_phase.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_chain_shape.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_circle_shape.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collide_circle.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collide_edge.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collide_polygon.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_collision.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_distance.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_dynamic_tree.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_edge_shape.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_polygon_shape.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\collision\b2_time_of_impact.cpp">
+ <Filter>src\collision</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_block_allocator.cpp">
+ <Filter>src\common</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_draw.cpp">
+ <Filter>src\common</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_math.cpp">
+ <Filter>src\common</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_settings.cpp">
+ <Filter>src\common</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_stack_allocator.cpp">
+ <Filter>src\common</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\common\b2_timer.cpp">
+ <Filter>src\common</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_body.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_circle_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_polygon_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_circle_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact_manager.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact_solver.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_distance_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_circle_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_polygon_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_fixture.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_friction_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_gear_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_island.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_motor_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_mouse_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_circle_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_contact.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_prismatic_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_pulley_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_revolute_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_weld_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_wheel_joint.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_world.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_world_callbacks.cpp">
+ <Filter>src\dynamics</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\rope\b2_rope.cpp">
+ <Filter>src\rope</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_circle_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_chain_polygon_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_circle_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_contact_solver.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_circle_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_edge_polygon_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_island.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_circle_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\dynamics\b2_polygon_contact.h">
+ <Filter>src\dynamics</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_api.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_block_allocator.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_body.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_broad_phase.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_chain_shape.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_circle_shape.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_collision.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_common.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_contact.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_contact_manager.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_distance.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_distance_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_draw.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_dynamic_tree.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_edge_shape.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_fixture.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_friction_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_gear_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_growable_stack.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_math.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_motor_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_mouse_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_polygon_shape.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_prismatic_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_pulley_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_revolute_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_rope.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_settings.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_shape.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_stack_allocator.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_time_of_impact.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_timer.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_time_step.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_types.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_weld_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_wheel_joint.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_world.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\b2_world_callbacks.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\include\box2d\box2d.h">
+ <Filter>include\box2d</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="include">
+ <UniqueIdentifier>{2B754068-BECE-3CED-9144-9AA210967EB9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\box2d">
+ <UniqueIdentifier>{44BE8560-7149-31D1-86F4-77906E2C0964}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src">
+ <UniqueIdentifier>{A24BD43B-5C67-30C5-8AF1-02F4AF819691}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\collision">
+ <UniqueIdentifier>{44A461AD-15F1-3F81-9DD3-2F84788CC206}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\common">
+ <UniqueIdentifier>{E64D37AD-9345-3075-89E6-11CF67457044}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\dynamics">
+ <UniqueIdentifier>{322B13ED-462E-37F0-920F-C4B6752E7654}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\rope">
+ <UniqueIdentifier>{BC484391-F853-356A-BCD3-79E86AF80865}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/src/box2dConfigVersion.cmake b/Client/ThirdParty/Box2D/proj/src/box2dConfigVersion.cmake
new file mode 100644
index 0000000..e1421d4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/box2dConfigVersion.cmake
@@ -0,0 +1,70 @@
+# This is a basic version file for the Config-mode of find_package().
+# It is used by write_basic_package_version_file() as input file for configure_file()
+# to create a version-file which can be installed along a config.cmake file.
+#
+# The created file sets PACKAGE_VERSION_EXACT if the current version string and
+# the requested version string are exactly the same and it sets
+# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version,
+# but only if the requested major version is the same as the current one.
+# The variable CVF_VERSION must be set before calling configure_file().
+
+
+set(PACKAGE_VERSION "2.4.1")
+
+if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+
+ if("2.4.1" MATCHES "^([0-9]+)\\.")
+ set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
+ string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
+ endif()
+ else()
+ set(CVF_VERSION_MAJOR "2.4.1")
+ endif()
+
+ if(PACKAGE_FIND_VERSION_RANGE)
+ # both endpoints of the range must have the expected major version
+ math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1")
+ if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR
+ OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR)
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT)))
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+ elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR
+ AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX)
+ OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX)))
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ else()
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+ endif()
+ else()
+ if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR)
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ else()
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+ endif()
+
+ if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif()
+ endif()
+endif()
+
+
+# if the installed project requested no architecture check, don't perform the check
+if("FALSE")
+ return()
+endif()
+
+# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
+if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "4" STREQUAL "")
+ return()
+endif()
+
+# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
+if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "4")
+ math(EXPR installedBits "4 * 8")
+ set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
+endif()
diff --git a/Client/ThirdParty/Box2D/proj/src/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/src/cmake_install.cmake
new file mode 100644
index 0000000..eaa7515
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/src/cmake_install.cmake
@@ -0,0 +1,90 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/src
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
+if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
+ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE FILE OPTIONAL FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/Debug/box2d.pdb")
+ elseif("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE FILE OPTIONAL FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/Release/box2d.pdb")
+ elseif("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Mm][Ii][Nn][Ss][Ii][Zz][Ee][Rr][Ee][Ll])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE FILE OPTIONAL FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/MinSizeRel/box2d.pdb")
+ elseif("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE FILE OPTIONAL FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/RelWithDebInfo/box2d.pdb")
+ endif()
+endif()
+
+if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
+ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Debug/box2d.lib")
+ elseif("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Release/box2d.lib")
+ elseif("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Mm][Ii][Nn][Ss][Ii][Zz][Ee][Rr][Ee][Ll])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/MinSizeRel/box2d.lib")
+ elseif("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/RelWithDebInfo/box2d.lib")
+ endif()
+endif()
+
+if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
+ if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d/box2dConfig.cmake")
+ file(DIFFERENT EXPORT_FILE_CHANGED FILES
+ "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d/box2dConfig.cmake"
+ "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig.cmake")
+ if(EXPORT_FILE_CHANGED)
+ file(GLOB OLD_CONFIG_FILES "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d/box2dConfig-*.cmake")
+ if(OLD_CONFIG_FILES)
+ message(STATUS "Old export file \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d/box2dConfig.cmake\" will be replaced. Removing files [${OLD_CONFIG_FILES}].")
+ file(REMOVE ${OLD_CONFIG_FILES})
+ endif()
+ endif()
+ endif()
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d" TYPE FILE FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig.cmake")
+ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d" TYPE FILE FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-debug.cmake")
+ endif()
+ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Mm][Ii][Nn][Ss][Ii][Zz][Ee][Rr][Ee][Ll])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d" TYPE FILE FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-minsizerel.cmake")
+ endif()
+ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ww][Ii][Tt][Hh][Dd][Ee][Bb][Ii][Nn][Ff][Oo])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d" TYPE FILE FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-relwithdebinfo.cmake")
+ endif()
+ if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$")
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d" TYPE FILE FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/CMakeFiles/Export/lib/cmake/box2d/box2dConfig-release.cmake")
+ endif()
+endif()
+
+if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
+ file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/box2d" TYPE FILE FILES "D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/src/box2dConfigVersion.cmake")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..d9dafb9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,2 @@
+# CMake generation dependency list for this directory.
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj
new file mode 100644
index 0000000..c4594d2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\bfe9de955132cd9d067c24acf7d98bef\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..53254e6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\bfe9de955132cd9d067c24acf7d98bef\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/testbed/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/testbed/cmake_install.cmake
new file mode 100644
index 0000000..56b763e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/cmake_install.cmake
@@ -0,0 +1,34 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj b/Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj
new file mode 100644
index 0000000..6bd4fe2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj
@@ -0,0 +1,465 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A168F045-AE5A-3724-B305-AA2A8C4749BA}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>testbed</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <LocalDebuggerWorkingDirectory Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed</LocalDebuggerWorkingDirectory>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">testbed.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">testbed</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <LocalDebuggerWorkingDirectory Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed</LocalDebuggerWorkingDirectory>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">testbed.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">testbed</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <LocalDebuggerWorkingDirectory Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed</LocalDebuggerWorkingDirectory>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">testbed.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">testbed</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">true</GenerateManifest>
+ <LocalDebuggerWorkingDirectory Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed</LocalDebuggerWorkingDirectory>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">testbed.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">testbed</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -E copy_directory D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/data/ D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/data/
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ <Link>
+ <AdditionalDependencies>..\bin\Debug\box2d.lib;..\bin\Debug\glfw.lib;..\bin\Debug\imgui.lib;..\bin\Debug\sajson.lib;..\bin\Debug\glad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Debug/testbed.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Debug/testbed.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -E copy_directory D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/data/ D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/data/
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ <Link>
+ <AdditionalDependencies>..\bin\Release\box2d.lib;..\bin\Release\glfw.lib;..\bin\Release\imgui.lib;..\bin\Release\sajson.lib;..\bin\Release\glad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Release/testbed.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Release/testbed.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -E copy_directory D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/data/ D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/data/
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ <Link>
+ <AdditionalDependencies>..\bin\MinSizeRel\box2d.lib;..\bin\MinSizeRel\glfw.lib;..\bin\MinSizeRel\imgui.lib;..\bin\MinSizeRel\sajson.lib;..\bin\MinSizeRel\glad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/MinSizeRel/testbed.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/MinSizeRel/testbed.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glfw\include;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\imgui\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\sajson\..;D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\extern\glad\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -E copy_directory D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/data/ D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/data/
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ <Link>
+ <AdditionalDependencies>..\bin\RelWithDebInfo\box2d.lib;..\bin\RelWithDebInfo\glfw.lib;..\bin\RelWithDebInfo\imgui.lib;..\bin\RelWithDebInfo\sajson.lib;..\bin\RelWithDebInfo\glad.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/RelWithDebInfo/testbed.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/RelWithDebInfo/testbed.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/testbed/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/testbed/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\testbed\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\draw.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\draw.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_glfw.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_glfw.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_opengl3.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_opengl3.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\main.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\settings.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\settings.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\test.cpp" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\test.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\add_pair.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\apply_force.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\body_types.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\box_stack.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\breakable.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\bridge.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\bullet_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\cantilever.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\car.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\chain.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\chain_problem.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\character_collision.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\circle_stack.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\collision_filtering.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\collision_processing.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\compound_shapes.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\confined.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\continuous_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\convex_hull.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\conveyor_belt.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\distance_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\distance_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\dominos.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\dump_loader.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\dynamic_tree.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\edge_shapes.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\edge_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\friction.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\gear_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\heavy1.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\heavy2.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\mobile_balanced.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\mobile_unbalanced.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\motor_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\pinball.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\platformer.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\polygon_collision.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\polygon_shapes.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\prismatic_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\pulley_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\pyramid.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\ray_cast.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\restitution.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\revolute_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\rope.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\sensor.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\shape_cast.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\shape_editing.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\skier.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\slider_crank_1.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\slider_crank_2.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\theo_jansen.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\tiles.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\time_of_impact.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\tumbler.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\web.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\wheel_joint.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\wrecking_ball.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\box2d.vcxproj">
+ <Project>{4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}</Project>
+ <Name>box2d</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glad\glad.vcxproj">
+ <Project>{29408AB9-D01F-3745-93F3-94160B037370}</Project>
+ <Name>glad</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\glfw\glfw.vcxproj">
+ <Project>{7F32E689-3D5C-3885-9B34-0860DAE8BE92}</Project>
+ <Name>glfw</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\imgui\imgui.vcxproj">
+ <Project>{B288C97F-F14F-33EA-9CAC-B55922D1FDC7}</Project>
+ <Name>imgui</Name>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\extern\sajson\sajson.vcxproj">
+ <Project>{EE68EE8F-E321-3CD7-A04C-C0A66C401380}</Project>
+ <Name>sajson</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj.filters b/Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj.filters
new file mode 100644
index 0000000..2781f18
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/testbed/testbed.vcxproj.filters
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\draw.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_glfw.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_opengl3.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\main.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\settings.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\add_pair.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\apply_force.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\body_types.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\box_stack.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\breakable.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\bridge.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\bullet_test.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\cantilever.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\car.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\chain.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\chain_problem.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\character_collision.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\circle_stack.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\collision_filtering.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\collision_processing.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\compound_shapes.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\confined.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\continuous_test.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\convex_hull.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\conveyor_belt.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\distance_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\distance_test.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\dominos.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\dump_loader.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\dynamic_tree.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\edge_shapes.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\edge_test.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\friction.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\gear_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\heavy1.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\heavy2.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\mobile_balanced.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\mobile_unbalanced.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\motor_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\pinball.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\platformer.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\polygon_collision.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\polygon_shapes.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\prismatic_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\pulley_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\pyramid.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\ray_cast.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\restitution.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\revolute_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\rope.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\sensor.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\shape_cast.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\shape_editing.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\skier.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\slider_crank_1.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\slider_crank_2.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\theo_jansen.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\tiles.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\time_of_impact.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\tumbler.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\web.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\wheel_joint.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\tests\wrecking_ball.cpp">
+ <Filter>tests</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\draw.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_glfw.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\imgui_impl_opengl3.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\settings.h" />
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\test.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\testbed\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="tests">
+ <UniqueIdentifier>{E24537DA-4173-36D5-9B2A-0CFE337F0649}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp b/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
new file mode 100644
index 0000000..9b5f49f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
@@ -0,0 +1 @@
+# CMake generation timestamp file for this directory.
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp.depend b/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp.depend
new file mode 100644
index 0000000..e940e58
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp.depend
@@ -0,0 +1,2 @@
+# CMake generation dependency list for this directory.
+D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj b/Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj
new file mode 100644
index 0000000..42b9eb6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9AC23237-8AB3-35CD-9010-F378760CC445}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Utility</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\6ddefecedef78174b7ed9b2bc8a1e035\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\INSTALL_force</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ALL_BUILD.vcxproj">
+ <Project>{2BA85667-24FF-36F3-825F-79CEC5AB3361}</Project>
+ <Name>ALL_BUILD</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj.filters b/Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..82a060e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/INSTALL.vcxproj.filters
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\CMakeFiles\6ddefecedef78174b7ed9b2bc8a1e035\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{403DEAA2-503F-3ECB-A013-6CDC0F5B48FC}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/cmake_install.cmake b/Client/ThirdParty/Box2D/proj/unit-test/cmake_install.cmake
new file mode 100644
index 0000000..e76260f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/cmake_install.cmake
@@ -0,0 +1,34 @@
+# Install script for directory: D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/unit-test
+
+# Set the install prefix
+if(NOT DEFINED CMAKE_INSTALL_PREFIX)
+ set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/box2d")
+endif()
+string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
+
+# Set the install configuration name.
+if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
+ if(BUILD_TYPE)
+ string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
+ CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
+ else()
+ set(CMAKE_INSTALL_CONFIG_NAME "Release")
+ endif()
+ message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
+endif()
+
+# Set the component getting installed.
+if(NOT CMAKE_INSTALL_COMPONENT)
+ if(COMPONENT)
+ message(STATUS "Install component: \"${COMPONENT}\"")
+ set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
+ else()
+ set(CMAKE_INSTALL_COMPONENT)
+ endif()
+endif()
+
+# Is this installation the result of a crosscompile?
+if(NOT DEFINED CMAKE_CROSSCOMPILING)
+ set(CMAKE_CROSSCOMPILING "FALSE")
+endif()
+
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj b/Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj
new file mode 100644
index 0000000..38beb60
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj
@@ -0,0 +1,334 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7ED467E4-0B19-329B-B677-9C4C01A3EC52}</ProjectGuid>
+ <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>unit_test</ProjectName>
+ <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v141</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">unit_test.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">unit_test</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">unit_test.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">unit_test</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">unit_test.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">unit_test</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">unit_test.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">unit_test</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;CMAKE_INTDIR="Debug"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_DEBUG;_WINDOWS;CMAKE_INTDIR=\"Debug\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>..\bin\Debug\box2d.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Debug/unit_test.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Debug/unit_test.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="Release"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"Release\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>..\bin\Release\box2d.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Release/unit_test.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/Release/unit_test.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MinSpace</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="MinSizeRel"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"MinSizeRel\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>..\bin\MinSizeRel\box2d.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/MinSizeRel/unit_test.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/MinSizeRel/unit_test.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <Optimization>MaxSpeed</Optimization>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <UseFullPaths>false</UseFullPaths>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR="RelWithDebInfo"</PreprocessorDefinitions>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);WIN32;_WINDOWS;NDEBUG;CMAKE_INTDIR=\"RelWithDebInfo\"</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\src\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>..\bin\RelWithDebInfo\box2d.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalOptions>%(AdditionalOptions) /machine:X86</AdditionalOptions>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ImportLibrary>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/RelWithDebInfo/unit_test.lib</ImportLibrary>
+ <ProgramDataBaseFile>D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/bin/RelWithDebInfo/unit_test.pdb</ProgramDataBaseFile>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkObjects>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files\CMake\bin\cmake.exe" -SD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D -BD:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj --check-stamp-file D:/Documents/VisualStudio2017/Projects/Ragdolls/Client/ThirdParty/Box2D/proj/unit-test/CMakeFiles/generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\unit-test\CMakeFiles\generate.stamp</Outputs>
+ <LinkObjects Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">false</LinkObjects>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\doctest.h" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\hello_world.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\collision_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\joint_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\math_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\world_test.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\ZERO_CHECK.vcxproj">
+ <Project>{BE3FCA9C-E0F7-3263-BFDC-D625CD827C80}</Project>
+ <Name>ZERO_CHECK</Name>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <CopyToOutputDirectory>Never</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\proj\src\box2d.vcxproj">
+ <Project>{4C709A21-ABF6-3B27-8C03-FCEBEB527A6E}</Project>
+ <Name>box2d</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj.filters b/Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj.filters
new file mode 100644
index 0000000..993ecd0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/proj/unit-test/unit_test.vcxproj.filters
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\hello_world.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\collision_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\joint_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\math_test.cpp" />
+ <ClCompile Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\world_test.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\doctest.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="D:\Documents\VisualStudio2017\Projects\Ragdolls\Client\ThirdParty\Box2D\unit-test\CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/Box2D/src/CMakeLists.txt b/Client/ThirdParty/Box2D/src/CMakeLists.txt
new file mode 100644
index 0000000..7b76c78
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/CMakeLists.txt
@@ -0,0 +1,163 @@
+set(BOX2D_SOURCE_FILES
+ collision/b2_broad_phase.cpp
+ collision/b2_chain_shape.cpp
+ collision/b2_circle_shape.cpp
+ collision/b2_collide_circle.cpp
+ collision/b2_collide_edge.cpp
+ collision/b2_collide_polygon.cpp
+ collision/b2_collision.cpp
+ collision/b2_distance.cpp
+ collision/b2_dynamic_tree.cpp
+ collision/b2_edge_shape.cpp
+ collision/b2_polygon_shape.cpp
+ collision/b2_time_of_impact.cpp
+ common/b2_block_allocator.cpp
+ common/b2_draw.cpp
+ common/b2_math.cpp
+ common/b2_settings.cpp
+ common/b2_stack_allocator.cpp
+ common/b2_timer.cpp
+ dynamics/b2_body.cpp
+ dynamics/b2_chain_circle_contact.cpp
+ dynamics/b2_chain_circle_contact.h
+ dynamics/b2_chain_polygon_contact.cpp
+ dynamics/b2_chain_polygon_contact.h
+ dynamics/b2_circle_contact.cpp
+ dynamics/b2_circle_contact.h
+ dynamics/b2_contact.cpp
+ dynamics/b2_contact_manager.cpp
+ dynamics/b2_contact_solver.cpp
+ dynamics/b2_contact_solver.h
+ dynamics/b2_distance_joint.cpp
+ dynamics/b2_edge_circle_contact.cpp
+ dynamics/b2_edge_circle_contact.h
+ dynamics/b2_edge_polygon_contact.cpp
+ dynamics/b2_edge_polygon_contact.h
+ dynamics/b2_fixture.cpp
+ dynamics/b2_friction_joint.cpp
+ dynamics/b2_gear_joint.cpp
+ dynamics/b2_island.cpp
+ dynamics/b2_island.h
+ dynamics/b2_joint.cpp
+ dynamics/b2_motor_joint.cpp
+ dynamics/b2_mouse_joint.cpp
+ dynamics/b2_polygon_circle_contact.cpp
+ dynamics/b2_polygon_circle_contact.h
+ dynamics/b2_polygon_contact.cpp
+ dynamics/b2_polygon_contact.h
+ dynamics/b2_prismatic_joint.cpp
+ dynamics/b2_pulley_joint.cpp
+ dynamics/b2_revolute_joint.cpp
+ dynamics/b2_weld_joint.cpp
+ dynamics/b2_wheel_joint.cpp
+ dynamics/b2_world.cpp
+ dynamics/b2_world_callbacks.cpp
+ rope/b2_rope.cpp)
+
+set(BOX2D_HEADER_FILES
+ ../include/box2d/b2_api.h
+ ../include/box2d/b2_block_allocator.h
+ ../include/box2d/b2_body.h
+ ../include/box2d/b2_broad_phase.h
+ ../include/box2d/b2_chain_shape.h
+ ../include/box2d/b2_circle_shape.h
+ ../include/box2d/b2_collision.h
+ ../include/box2d/b2_common.h
+ ../include/box2d/b2_contact.h
+ ../include/box2d/b2_contact_manager.h
+ ../include/box2d/b2_distance.h
+ ../include/box2d/b2_distance_joint.h
+ ../include/box2d/b2_draw.h
+ ../include/box2d/b2_dynamic_tree.h
+ ../include/box2d/b2_edge_shape.h
+ ../include/box2d/b2_fixture.h
+ ../include/box2d/b2_friction_joint.h
+ ../include/box2d/b2_gear_joint.h
+ ../include/box2d/b2_growable_stack.h
+ ../include/box2d/b2_joint.h
+ ../include/box2d/b2_math.h
+ ../include/box2d/b2_motor_joint.h
+ ../include/box2d/b2_mouse_joint.h
+ ../include/box2d/b2_polygon_shape.h
+ ../include/box2d/b2_prismatic_joint.h
+ ../include/box2d/b2_pulley_joint.h
+ ../include/box2d/b2_revolute_joint.h
+ ../include/box2d/b2_rope.h
+ ../include/box2d/b2_settings.h
+ ../include/box2d/b2_shape.h
+ ../include/box2d/b2_stack_allocator.h
+ ../include/box2d/b2_time_of_impact.h
+ ../include/box2d/b2_timer.h
+ ../include/box2d/b2_time_step.h
+ ../include/box2d/b2_types.h
+ ../include/box2d/b2_weld_joint.h
+ ../include/box2d/b2_wheel_joint.h
+ ../include/box2d/b2_world.h
+ ../include/box2d/b2_world_callbacks.h
+ ../include/box2d/box2d.h)
+
+add_library(box2d ${BOX2D_SOURCE_FILES} ${BOX2D_HEADER_FILES})
+target_include_directories(box2d
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+set_target_properties(box2d PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO
+ VERSION ${PROJECT_VERSION}
+ SOVERSION ${PROJECT_VERSION_MAJOR}
+)
+
+if(MSVC)
+ set_target_properties(box2d PROPERTIES
+ COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ COMPILE_PDB_NAME box2d
+ )
+
+ install(
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/box2d.pdb"
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ OPTIONAL
+ )
+endif()
+
+if (BUILD_SHARED_LIBS)
+ target_compile_definitions(box2d
+ PUBLIC
+ B2_SHARED
+ )
+endif()
+
+source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "src" FILES ${BOX2D_SOURCE_FILES})
+source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" PREFIX "include" FILES ${BOX2D_HEADER_FILES})
+
+install(
+ TARGETS box2d
+ EXPORT box2dConfig
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+install(
+ EXPORT box2dConfig
+ NAMESPACE box2d::
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d"
+)
+
+include(CMakePackageConfigHelpers)
+
+write_basic_package_version_file(
+ "${CMAKE_CURRENT_BINARY_DIR}/box2dConfigVersion.cmake"
+ COMPATIBILITY SameMajorVersion
+)
+
+install(
+ FILES "${CMAKE_CURRENT_BINARY_DIR}/box2dConfigVersion.cmake"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d"
+)
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_broad_phase.cpp b/Client/ThirdParty/Box2D/src/collision/b2_broad_phase.cpp
new file mode 100644
index 0000000..d063a3a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_broad_phase.cpp
@@ -0,0 +1,131 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_broad_phase.h"
+#include <string.h>
+
+b2BroadPhase::b2BroadPhase()
+{
+ m_proxyCount = 0;
+
+ m_pairCapacity = 16;
+ m_pairCount = 0;
+ m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair));
+
+ m_moveCapacity = 16;
+ m_moveCount = 0;
+ m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32));
+}
+
+b2BroadPhase::~b2BroadPhase()
+{
+ b2Free(m_moveBuffer);
+ b2Free(m_pairBuffer);
+}
+
+int32 b2BroadPhase::CreateProxy(const b2AABB& aabb, void* userData)
+{
+ int32 proxyId = m_tree.CreateProxy(aabb, userData);
+ ++m_proxyCount;
+ BufferMove(proxyId);
+ return proxyId;
+}
+
+void b2BroadPhase::DestroyProxy(int32 proxyId)
+{
+ UnBufferMove(proxyId);
+ --m_proxyCount;
+ m_tree.DestroyProxy(proxyId);
+}
+
+void b2BroadPhase::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement)
+{
+ bool buffer = m_tree.MoveProxy(proxyId, aabb, displacement);
+ if (buffer)
+ {
+ BufferMove(proxyId);
+ }
+}
+
+void b2BroadPhase::TouchProxy(int32 proxyId)
+{
+ BufferMove(proxyId);
+}
+
+void b2BroadPhase::BufferMove(int32 proxyId)
+{
+ if (m_moveCount == m_moveCapacity)
+ {
+ int32* oldBuffer = m_moveBuffer;
+ m_moveCapacity *= 2;
+ m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32));
+ memcpy(m_moveBuffer, oldBuffer, m_moveCount * sizeof(int32));
+ b2Free(oldBuffer);
+ }
+
+ m_moveBuffer[m_moveCount] = proxyId;
+ ++m_moveCount;
+}
+
+void b2BroadPhase::UnBufferMove(int32 proxyId)
+{
+ for (int32 i = 0; i < m_moveCount; ++i)
+ {
+ if (m_moveBuffer[i] == proxyId)
+ {
+ m_moveBuffer[i] = e_nullProxy;
+ }
+ }
+}
+
+// This is called from b2DynamicTree::Query when we are gathering pairs.
+bool b2BroadPhase::QueryCallback(int32 proxyId)
+{
+ // A proxy cannot form a pair with itself.
+ if (proxyId == m_queryProxyId)
+ {
+ return true;
+ }
+
+ const bool moved = m_tree.WasMoved(proxyId);
+ if (moved && proxyId > m_queryProxyId)
+ {
+ // Both proxies are moving. Avoid duplicate pairs.
+ return true;
+ }
+
+ // Grow the pair buffer as needed.
+ if (m_pairCount == m_pairCapacity)
+ {
+ b2Pair* oldBuffer = m_pairBuffer;
+ m_pairCapacity = m_pairCapacity + (m_pairCapacity >> 1);
+ m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair));
+ memcpy(m_pairBuffer, oldBuffer, m_pairCount * sizeof(b2Pair));
+ b2Free(oldBuffer);
+ }
+
+ m_pairBuffer[m_pairCount].proxyIdA = b2Min(proxyId, m_queryProxyId);
+ m_pairBuffer[m_pairCount].proxyIdB = b2Max(proxyId, m_queryProxyId);
+ ++m_pairCount;
+
+ return true;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_chain_shape.cpp b/Client/ThirdParty/Box2D/src/collision/b2_chain_shape.cpp
new file mode 100644
index 0000000..b964a43
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_chain_shape.cpp
@@ -0,0 +1,185 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_chain_shape.h"
+#include "box2d/b2_edge_shape.h"
+
+#include "box2d/b2_block_allocator.h"
+
+#include <new>
+#include <string.h>
+
+b2ChainShape::~b2ChainShape()
+{
+ Clear();
+}
+
+void b2ChainShape::Clear()
+{
+ b2Free(m_vertices);
+ m_vertices = nullptr;
+ m_count = 0;
+}
+
+void b2ChainShape::CreateLoop(const b2Vec2* vertices, int32 count)
+{
+ b2Assert(m_vertices == nullptr && m_count == 0);
+ b2Assert(count >= 3);
+ if (count < 3)
+ {
+ return;
+ }
+
+ for (int32 i = 1; i < count; ++i)
+ {
+ b2Vec2 v1 = vertices[i-1];
+ b2Vec2 v2 = vertices[i];
+ // If the code crashes here, it means your vertices are too close together.
+ b2Assert(b2DistanceSquared(v1, v2) > b2_linearSlop * b2_linearSlop);
+ }
+
+ m_count = count + 1;
+ m_vertices = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
+ memcpy(m_vertices, vertices, count * sizeof(b2Vec2));
+ m_vertices[count] = m_vertices[0];
+ m_prevVertex = m_vertices[m_count - 2];
+ m_nextVertex = m_vertices[1];
+}
+
+void b2ChainShape::CreateChain(const b2Vec2* vertices, int32 count, const b2Vec2& prevVertex, const b2Vec2& nextVertex)
+{
+ b2Assert(m_vertices == nullptr && m_count == 0);
+ b2Assert(count >= 2);
+ for (int32 i = 1; i < count; ++i)
+ {
+ // If the code crashes here, it means your vertices are too close together.
+ b2Assert(b2DistanceSquared(vertices[i-1], vertices[i]) > b2_linearSlop * b2_linearSlop);
+ }
+
+ m_count = count;
+ m_vertices = (b2Vec2*)b2Alloc(count * sizeof(b2Vec2));
+ memcpy(m_vertices, vertices, m_count * sizeof(b2Vec2));
+
+ m_prevVertex = prevVertex;
+ m_nextVertex = nextVertex;
+}
+
+b2Shape* b2ChainShape::Clone(b2BlockAllocator* allocator) const
+{
+ void* mem = allocator->Allocate(sizeof(b2ChainShape));
+ b2ChainShape* clone = new (mem) b2ChainShape;
+ clone->CreateChain(m_vertices, m_count, m_prevVertex, m_nextVertex);
+ return clone;
+}
+
+int32 b2ChainShape::GetChildCount() const
+{
+ // edge count = vertex count - 1
+ return m_count - 1;
+}
+
+void b2ChainShape::GetChildEdge(b2EdgeShape* edge, int32 index) const
+{
+ b2Assert(0 <= index && index < m_count - 1);
+ edge->m_type = b2Shape::e_edge;
+ edge->m_radius = m_radius;
+
+ edge->m_vertex1 = m_vertices[index + 0];
+ edge->m_vertex2 = m_vertices[index + 1];
+ edge->m_oneSided = true;
+
+ if (index > 0)
+ {
+ edge->m_vertex0 = m_vertices[index - 1];
+ }
+ else
+ {
+ edge->m_vertex0 = m_prevVertex;
+ }
+
+ if (index < m_count - 2)
+ {
+ edge->m_vertex3 = m_vertices[index + 2];
+ }
+ else
+ {
+ edge->m_vertex3 = m_nextVertex;
+ }
+}
+
+bool b2ChainShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const
+{
+ B2_NOT_USED(xf);
+ B2_NOT_USED(p);
+ return false;
+}
+
+bool b2ChainShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& xf, int32 childIndex) const
+{
+ b2Assert(childIndex < m_count);
+
+ b2EdgeShape edgeShape;
+
+ int32 i1 = childIndex;
+ int32 i2 = childIndex + 1;
+ if (i2 == m_count)
+ {
+ i2 = 0;
+ }
+
+ edgeShape.m_vertex1 = m_vertices[i1];
+ edgeShape.m_vertex2 = m_vertices[i2];
+
+ return edgeShape.RayCast(output, input, xf, 0);
+}
+
+void b2ChainShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const
+{
+ b2Assert(childIndex < m_count);
+
+ int32 i1 = childIndex;
+ int32 i2 = childIndex + 1;
+ if (i2 == m_count)
+ {
+ i2 = 0;
+ }
+
+ b2Vec2 v1 = b2Mul(xf, m_vertices[i1]);
+ b2Vec2 v2 = b2Mul(xf, m_vertices[i2]);
+
+ b2Vec2 lower = b2Min(v1, v2);
+ b2Vec2 upper = b2Max(v1, v2);
+
+ b2Vec2 r(m_radius, m_radius);
+ aabb->lowerBound = lower - r;
+ aabb->upperBound = upper + r;
+}
+
+void b2ChainShape::ComputeMass(b2MassData* massData, float density) const
+{
+ B2_NOT_USED(density);
+
+ massData->mass = 0.0f;
+ massData->center.SetZero();
+ massData->I = 0.0f;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_circle_shape.cpp b/Client/ThirdParty/Box2D/src/collision/b2_circle_shape.cpp
new file mode 100644
index 0000000..ecc6929
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_circle_shape.cpp
@@ -0,0 +1,105 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_block_allocator.h"
+
+#include <new>
+
+b2Shape* b2CircleShape::Clone(b2BlockAllocator* allocator) const
+{
+ void* mem = allocator->Allocate(sizeof(b2CircleShape));
+ b2CircleShape* clone = new (mem) b2CircleShape;
+ *clone = *this;
+ return clone;
+}
+
+int32 b2CircleShape::GetChildCount() const
+{
+ return 1;
+}
+
+bool b2CircleShape::TestPoint(const b2Transform& transform, const b2Vec2& p) const
+{
+ b2Vec2 center = transform.p + b2Mul(transform.q, m_p);
+ b2Vec2 d = p - center;
+ return b2Dot(d, d) <= m_radius * m_radius;
+}
+
+// Collision Detection in Interactive 3D Environments by Gino van den Bergen
+// From Section 3.1.2
+// x = s + a * r
+// norm(x) = radius
+bool b2CircleShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& transform, int32 childIndex) const
+{
+ B2_NOT_USED(childIndex);
+
+ b2Vec2 position = transform.p + b2Mul(transform.q, m_p);
+ b2Vec2 s = input.p1 - position;
+ float b = b2Dot(s, s) - m_radius * m_radius;
+
+ // Solve quadratic equation.
+ b2Vec2 r = input.p2 - input.p1;
+ float c = b2Dot(s, r);
+ float rr = b2Dot(r, r);
+ float sigma = c * c - rr * b;
+
+ // Check for negative discriminant and short segment.
+ if (sigma < 0.0f || rr < b2_epsilon)
+ {
+ return false;
+ }
+
+ // Find the point of intersection of the line with the circle.
+ float a = -(c + b2Sqrt(sigma));
+
+ // Is the intersection point on the segment?
+ if (0.0f <= a && a <= input.maxFraction * rr)
+ {
+ a /= rr;
+ output->fraction = a;
+ output->normal = s + a * r;
+ output->normal.Normalize();
+ return true;
+ }
+
+ return false;
+}
+
+void b2CircleShape::ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const
+{
+ B2_NOT_USED(childIndex);
+
+ b2Vec2 p = transform.p + b2Mul(transform.q, m_p);
+ aabb->lowerBound.Set(p.x - m_radius, p.y - m_radius);
+ aabb->upperBound.Set(p.x + m_radius, p.y + m_radius);
+}
+
+void b2CircleShape::ComputeMass(b2MassData* massData, float density) const
+{
+ massData->mass = density * b2_pi * m_radius * m_radius;
+ massData->center = m_p;
+
+ // inertia about the local origin
+ massData->I = massData->mass * (0.5f * m_radius * m_radius + b2Dot(m_p, m_p));
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_collide_circle.cpp b/Client/ThirdParty/Box2D/src/collision/b2_collide_circle.cpp
new file mode 100644
index 0000000..469da55
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_collide_circle.cpp
@@ -0,0 +1,158 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_collision.h"
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_polygon_shape.h"
+
+void b2CollideCircles(
+ b2Manifold* manifold,
+ const b2CircleShape* circleA, const b2Transform& xfA,
+ const b2CircleShape* circleB, const b2Transform& xfB)
+{
+ manifold->pointCount = 0;
+
+ b2Vec2 pA = b2Mul(xfA, circleA->m_p);
+ b2Vec2 pB = b2Mul(xfB, circleB->m_p);
+
+ b2Vec2 d = pB - pA;
+ float distSqr = b2Dot(d, d);
+ float rA = circleA->m_radius, rB = circleB->m_radius;
+ float radius = rA + rB;
+ if (distSqr > radius * radius)
+ {
+ return;
+ }
+
+ manifold->type = b2Manifold::e_circles;
+ manifold->localPoint = circleA->m_p;
+ manifold->localNormal.SetZero();
+ manifold->pointCount = 1;
+
+ manifold->points[0].localPoint = circleB->m_p;
+ manifold->points[0].id.key = 0;
+}
+
+void b2CollidePolygonAndCircle(
+ b2Manifold* manifold,
+ const b2PolygonShape* polygonA, const b2Transform& xfA,
+ const b2CircleShape* circleB, const b2Transform& xfB)
+{
+ manifold->pointCount = 0;
+
+ // Compute circle position in the frame of the polygon.
+ b2Vec2 c = b2Mul(xfB, circleB->m_p);
+ b2Vec2 cLocal = b2MulT(xfA, c);
+
+ // Find the min separating edge.
+ int32 normalIndex = 0;
+ float separation = -b2_maxFloat;
+ float radius = polygonA->m_radius + circleB->m_radius;
+ int32 vertexCount = polygonA->m_count;
+ const b2Vec2* vertices = polygonA->m_vertices;
+ const b2Vec2* normals = polygonA->m_normals;
+
+ for (int32 i = 0; i < vertexCount; ++i)
+ {
+ float s = b2Dot(normals[i], cLocal - vertices[i]);
+
+ if (s > radius)
+ {
+ // Early out.
+ return;
+ }
+
+ if (s > separation)
+ {
+ separation = s;
+ normalIndex = i;
+ }
+ }
+
+ // Vertices that subtend the incident face.
+ int32 vertIndex1 = normalIndex;
+ int32 vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
+ b2Vec2 v1 = vertices[vertIndex1];
+ b2Vec2 v2 = vertices[vertIndex2];
+
+ // If the center is inside the polygon ...
+ if (separation < b2_epsilon)
+ {
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_faceA;
+ manifold->localNormal = normals[normalIndex];
+ manifold->localPoint = 0.5f * (v1 + v2);
+ manifold->points[0].localPoint = circleB->m_p;
+ manifold->points[0].id.key = 0;
+ return;
+ }
+
+ // Compute barycentric coordinates
+ float u1 = b2Dot(cLocal - v1, v2 - v1);
+ float u2 = b2Dot(cLocal - v2, v1 - v2);
+ if (u1 <= 0.0f)
+ {
+ if (b2DistanceSquared(cLocal, v1) > radius * radius)
+ {
+ return;
+ }
+
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_faceA;
+ manifold->localNormal = cLocal - v1;
+ manifold->localNormal.Normalize();
+ manifold->localPoint = v1;
+ manifold->points[0].localPoint = circleB->m_p;
+ manifold->points[0].id.key = 0;
+ }
+ else if (u2 <= 0.0f)
+ {
+ if (b2DistanceSquared(cLocal, v2) > radius * radius)
+ {
+ return;
+ }
+
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_faceA;
+ manifold->localNormal = cLocal - v2;
+ manifold->localNormal.Normalize();
+ manifold->localPoint = v2;
+ manifold->points[0].localPoint = circleB->m_p;
+ manifold->points[0].id.key = 0;
+ }
+ else
+ {
+ b2Vec2 faceCenter = 0.5f * (v1 + v2);
+ float s = b2Dot(cLocal - faceCenter, normals[vertIndex1]);
+ if (s > radius)
+ {
+ return;
+ }
+
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_faceA;
+ manifold->localNormal = normals[vertIndex1];
+ manifold->localPoint = faceCenter;
+ manifold->points[0].localPoint = circleB->m_p;
+ manifold->points[0].id.key = 0;
+ }
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_collide_edge.cpp b/Client/ThirdParty/Box2D/src/collision/b2_collide_edge.cpp
new file mode 100644
index 0000000..e06b900
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_collide_edge.cpp
@@ -0,0 +1,524 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_collision.h"
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_edge_shape.h"
+#include "box2d/b2_polygon_shape.h"
+
+
+// Compute contact points for edge versus circle.
+// This accounts for edge connectivity.
+void b2CollideEdgeAndCircle(b2Manifold* manifold,
+ const b2EdgeShape* edgeA, const b2Transform& xfA,
+ const b2CircleShape* circleB, const b2Transform& xfB)
+{
+ manifold->pointCount = 0;
+
+ // Compute circle in frame of edge
+ b2Vec2 Q = b2MulT(xfA, b2Mul(xfB, circleB->m_p));
+
+ b2Vec2 A = edgeA->m_vertex1, B = edgeA->m_vertex2;
+ b2Vec2 e = B - A;
+
+ // Normal points to the right for a CCW winding
+ b2Vec2 n(e.y, -e.x);
+ float offset = b2Dot(n, Q - A);
+
+ bool oneSided = edgeA->m_oneSided;
+ if (oneSided && offset < 0.0f)
+ {
+ return;
+ }
+
+ // Barycentric coordinates
+ float u = b2Dot(e, B - Q);
+ float v = b2Dot(e, Q - A);
+
+ float radius = edgeA->m_radius + circleB->m_radius;
+
+ b2ContactFeature cf;
+ cf.indexB = 0;
+ cf.typeB = b2ContactFeature::e_vertex;
+
+ // Region A
+ if (v <= 0.0f)
+ {
+ b2Vec2 P = A;
+ b2Vec2 d = Q - P;
+ float dd = b2Dot(d, d);
+ if (dd > radius * radius)
+ {
+ return;
+ }
+
+ // Is there an edge connected to A?
+ if (edgeA->m_oneSided)
+ {
+ b2Vec2 A1 = edgeA->m_vertex0;
+ b2Vec2 B1 = A;
+ b2Vec2 e1 = B1 - A1;
+ float u1 = b2Dot(e1, B1 - Q);
+
+ // Is the circle in Region AB of the previous edge?
+ if (u1 > 0.0f)
+ {
+ return;
+ }
+ }
+
+ cf.indexA = 0;
+ cf.typeA = b2ContactFeature::e_vertex;
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_circles;
+ manifold->localNormal.SetZero();
+ manifold->localPoint = P;
+ manifold->points[0].id.key = 0;
+ manifold->points[0].id.cf = cf;
+ manifold->points[0].localPoint = circleB->m_p;
+ return;
+ }
+
+ // Region B
+ if (u <= 0.0f)
+ {
+ b2Vec2 P = B;
+ b2Vec2 d = Q - P;
+ float dd = b2Dot(d, d);
+ if (dd > radius * radius)
+ {
+ return;
+ }
+
+ // Is there an edge connected to B?
+ if (edgeA->m_oneSided)
+ {
+ b2Vec2 B2 = edgeA->m_vertex3;
+ b2Vec2 A2 = B;
+ b2Vec2 e2 = B2 - A2;
+ float v2 = b2Dot(e2, Q - A2);
+
+ // Is the circle in Region AB of the next edge?
+ if (v2 > 0.0f)
+ {
+ return;
+ }
+ }
+
+ cf.indexA = 1;
+ cf.typeA = b2ContactFeature::e_vertex;
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_circles;
+ manifold->localNormal.SetZero();
+ manifold->localPoint = P;
+ manifold->points[0].id.key = 0;
+ manifold->points[0].id.cf = cf;
+ manifold->points[0].localPoint = circleB->m_p;
+ return;
+ }
+
+ // Region AB
+ float den = b2Dot(e, e);
+ b2Assert(den > 0.0f);
+ b2Vec2 P = (1.0f / den) * (u * A + v * B);
+ b2Vec2 d = Q - P;
+ float dd = b2Dot(d, d);
+ if (dd > radius * radius)
+ {
+ return;
+ }
+
+ if (offset < 0.0f)
+ {
+ n.Set(-n.x, -n.y);
+ }
+ n.Normalize();
+
+ cf.indexA = 0;
+ cf.typeA = b2ContactFeature::e_face;
+ manifold->pointCount = 1;
+ manifold->type = b2Manifold::e_faceA;
+ manifold->localNormal = n;
+ manifold->localPoint = A;
+ manifold->points[0].id.key = 0;
+ manifold->points[0].id.cf = cf;
+ manifold->points[0].localPoint = circleB->m_p;
+}
+
+// This structure is used to keep track of the best separating axis.
+struct b2EPAxis
+{
+ enum Type
+ {
+ e_unknown,
+ e_edgeA,
+ e_edgeB
+ };
+
+ b2Vec2 normal;
+ Type type;
+ int32 index;
+ float separation;
+};
+
+// This holds polygon B expressed in frame A.
+struct b2TempPolygon
+{
+ b2Vec2 vertices[b2_maxPolygonVertices];
+ b2Vec2 normals[b2_maxPolygonVertices];
+ int32 count;
+};
+
+// Reference face used for clipping
+struct b2ReferenceFace
+{
+ int32 i1, i2;
+ b2Vec2 v1, v2;
+ b2Vec2 normal;
+
+ b2Vec2 sideNormal1;
+ float sideOffset1;
+
+ b2Vec2 sideNormal2;
+ float sideOffset2;
+};
+
+static b2EPAxis b2ComputeEdgeSeparation(const b2TempPolygon& polygonB, const b2Vec2& v1, const b2Vec2& normal1)
+{
+ b2EPAxis axis;
+ axis.type = b2EPAxis::e_edgeA;
+ axis.index = -1;
+ axis.separation = -FLT_MAX;
+ axis.normal.SetZero();
+
+ b2Vec2 axes[2] = { normal1, -normal1 };
+
+ // Find axis with least overlap (min-max problem)
+ for (int32 j = 0; j < 2; ++j)
+ {
+ float sj = FLT_MAX;
+
+ // Find deepest polygon vertex along axis j
+ for (int32 i = 0; i < polygonB.count; ++i)
+ {
+ float si = b2Dot(axes[j], polygonB.vertices[i] - v1);
+ if (si < sj)
+ {
+ sj = si;
+ }
+ }
+
+ if (sj > axis.separation)
+ {
+ axis.index = j;
+ axis.separation = sj;
+ axis.normal = axes[j];
+ }
+ }
+
+ return axis;
+}
+
+static b2EPAxis b2ComputePolygonSeparation(const b2TempPolygon& polygonB, const b2Vec2& v1, const b2Vec2& v2)
+{
+ b2EPAxis axis;
+ axis.type = b2EPAxis::e_unknown;
+ axis.index = -1;
+ axis.separation = -FLT_MAX;
+ axis.normal.SetZero();
+
+ for (int32 i = 0; i < polygonB.count; ++i)
+ {
+ b2Vec2 n = -polygonB.normals[i];
+
+ float s1 = b2Dot(n, polygonB.vertices[i] - v1);
+ float s2 = b2Dot(n, polygonB.vertices[i] - v2);
+ float s = b2Min(s1, s2);
+
+ if (s > axis.separation)
+ {
+ axis.type = b2EPAxis::e_edgeB;
+ axis.index = i;
+ axis.separation = s;
+ axis.normal = n;
+ }
+ }
+
+ return axis;
+}
+
+void b2CollideEdgeAndPolygon(b2Manifold* manifold,
+ const b2EdgeShape* edgeA, const b2Transform& xfA,
+ const b2PolygonShape* polygonB, const b2Transform& xfB)
+{
+ manifold->pointCount = 0;
+
+ b2Transform xf = b2MulT(xfA, xfB);
+
+ b2Vec2 centroidB = b2Mul(xf, polygonB->m_centroid);
+
+ b2Vec2 v1 = edgeA->m_vertex1;
+ b2Vec2 v2 = edgeA->m_vertex2;
+
+ b2Vec2 edge1 = v2 - v1;
+ edge1.Normalize();
+
+ // Normal points to the right for a CCW winding
+ b2Vec2 normal1(edge1.y, -edge1.x);
+ float offset1 = b2Dot(normal1, centroidB - v1);
+
+ bool oneSided = edgeA->m_oneSided;
+ if (oneSided && offset1 < 0.0f)
+ {
+ return;
+ }
+
+ // Get polygonB in frameA
+ b2TempPolygon tempPolygonB;
+ tempPolygonB.count = polygonB->m_count;
+ for (int32 i = 0; i < polygonB->m_count; ++i)
+ {
+ tempPolygonB.vertices[i] = b2Mul(xf, polygonB->m_vertices[i]);
+ tempPolygonB.normals[i] = b2Mul(xf.q, polygonB->m_normals[i]);
+ }
+
+ float radius = polygonB->m_radius + edgeA->m_radius;
+
+ b2EPAxis edgeAxis = b2ComputeEdgeSeparation(tempPolygonB, v1, normal1);
+ if (edgeAxis.separation > radius)
+ {
+ return;
+ }
+
+ b2EPAxis polygonAxis = b2ComputePolygonSeparation(tempPolygonB, v1, v2);
+ if (polygonAxis.separation > radius)
+ {
+ return;
+ }
+
+ // Use hysteresis for jitter reduction.
+ const float k_relativeTol = 0.98f;
+ const float k_absoluteTol = 0.001f;
+
+ b2EPAxis primaryAxis;
+ if (polygonAxis.separation - radius > k_relativeTol * (edgeAxis.separation - radius) + k_absoluteTol)
+ {
+ primaryAxis = polygonAxis;
+ }
+ else
+ {
+ primaryAxis = edgeAxis;
+ }
+
+ if (oneSided)
+ {
+ // Smooth collision
+ // See https://box2d.org/posts/2020/06/ghost-collisions/
+
+ b2Vec2 edge0 = v1 - edgeA->m_vertex0;
+ edge0.Normalize();
+ b2Vec2 normal0(edge0.y, -edge0.x);
+ bool convex1 = b2Cross(edge0, edge1) >= 0.0f;
+
+ b2Vec2 edge2 = edgeA->m_vertex3 - v2;
+ edge2.Normalize();
+ b2Vec2 normal2(edge2.y, -edge2.x);
+ bool convex2 = b2Cross(edge1, edge2) >= 0.0f;
+
+ const float sinTol = 0.1f;
+ bool side1 = b2Dot(primaryAxis.normal, edge1) <= 0.0f;
+
+ // Check Gauss Map
+ if (side1)
+ {
+ if (convex1)
+ {
+ if (b2Cross(primaryAxis.normal, normal0) > sinTol)
+ {
+ // Skip region
+ return;
+ }
+
+ // Admit region
+ }
+ else
+ {
+ // Snap region
+ primaryAxis = edgeAxis;
+ }
+ }
+ else
+ {
+ if (convex2)
+ {
+ if (b2Cross(normal2, primaryAxis.normal) > sinTol)
+ {
+ // Skip region
+ return;
+ }
+
+ // Admit region
+ }
+ else
+ {
+ // Snap region
+ primaryAxis = edgeAxis;
+ }
+ }
+ }
+
+ b2ClipVertex clipPoints[2];
+ b2ReferenceFace ref;
+ if (primaryAxis.type == b2EPAxis::e_edgeA)
+ {
+ manifold->type = b2Manifold::e_faceA;
+
+ // Search for the polygon normal that is most anti-parallel to the edge normal.
+ int32 bestIndex = 0;
+ float bestValue = b2Dot(primaryAxis.normal, tempPolygonB.normals[0]);
+ for (int32 i = 1; i < tempPolygonB.count; ++i)
+ {
+ float value = b2Dot(primaryAxis.normal, tempPolygonB.normals[i]);
+ if (value < bestValue)
+ {
+ bestValue = value;
+ bestIndex = i;
+ }
+ }
+
+ int32 i1 = bestIndex;
+ int32 i2 = i1 + 1 < tempPolygonB.count ? i1 + 1 : 0;
+
+ clipPoints[0].v = tempPolygonB.vertices[i1];
+ clipPoints[0].id.cf.indexA = 0;
+ clipPoints[0].id.cf.indexB = static_cast<uint8>(i1);
+ clipPoints[0].id.cf.typeA = b2ContactFeature::e_face;
+ clipPoints[0].id.cf.typeB = b2ContactFeature::e_vertex;
+
+ clipPoints[1].v = tempPolygonB.vertices[i2];
+ clipPoints[1].id.cf.indexA = 0;
+ clipPoints[1].id.cf.indexB = static_cast<uint8>(i2);
+ clipPoints[1].id.cf.typeA = b2ContactFeature::e_face;
+ clipPoints[1].id.cf.typeB = b2ContactFeature::e_vertex;
+
+ ref.i1 = 0;
+ ref.i2 = 1;
+ ref.v1 = v1;
+ ref.v2 = v2;
+ ref.normal = primaryAxis.normal;
+ ref.sideNormal1 = -edge1;
+ ref.sideNormal2 = edge1;
+ }
+ else
+ {
+ manifold->type = b2Manifold::e_faceB;
+
+ clipPoints[0].v = v2;
+ clipPoints[0].id.cf.indexA = 1;
+ clipPoints[0].id.cf.indexB = static_cast<uint8>(primaryAxis.index);
+ clipPoints[0].id.cf.typeA = b2ContactFeature::e_vertex;
+ clipPoints[0].id.cf.typeB = b2ContactFeature::e_face;
+
+ clipPoints[1].v = v1;
+ clipPoints[1].id.cf.indexA = 0;
+ clipPoints[1].id.cf.indexB = static_cast<uint8>(primaryAxis.index);
+ clipPoints[1].id.cf.typeA = b2ContactFeature::e_vertex;
+ clipPoints[1].id.cf.typeB = b2ContactFeature::e_face;
+
+ ref.i1 = primaryAxis.index;
+ ref.i2 = ref.i1 + 1 < tempPolygonB.count ? ref.i1 + 1 : 0;
+ ref.v1 = tempPolygonB.vertices[ref.i1];
+ ref.v2 = tempPolygonB.vertices[ref.i2];
+ ref.normal = tempPolygonB.normals[ref.i1];
+
+ // CCW winding
+ ref.sideNormal1.Set(ref.normal.y, -ref.normal.x);
+ ref.sideNormal2 = -ref.sideNormal1;
+ }
+
+ ref.sideOffset1 = b2Dot(ref.sideNormal1, ref.v1);
+ ref.sideOffset2 = b2Dot(ref.sideNormal2, ref.v2);
+
+ // Clip incident edge against reference face side planes
+ b2ClipVertex clipPoints1[2];
+ b2ClipVertex clipPoints2[2];
+ int32 np;
+
+ // Clip to side 1
+ np = b2ClipSegmentToLine(clipPoints1, clipPoints, ref.sideNormal1, ref.sideOffset1, ref.i1);
+
+ if (np < b2_maxManifoldPoints)
+ {
+ return;
+ }
+
+ // Clip to side 2
+ np = b2ClipSegmentToLine(clipPoints2, clipPoints1, ref.sideNormal2, ref.sideOffset2, ref.i2);
+
+ if (np < b2_maxManifoldPoints)
+ {
+ return;
+ }
+
+ // Now clipPoints2 contains the clipped points.
+ if (primaryAxis.type == b2EPAxis::e_edgeA)
+ {
+ manifold->localNormal = ref.normal;
+ manifold->localPoint = ref.v1;
+ }
+ else
+ {
+ manifold->localNormal = polygonB->m_normals[ref.i1];
+ manifold->localPoint = polygonB->m_vertices[ref.i1];
+ }
+
+ int32 pointCount = 0;
+ for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
+ {
+ float separation;
+
+ separation = b2Dot(ref.normal, clipPoints2[i].v - ref.v1);
+
+ if (separation <= radius)
+ {
+ b2ManifoldPoint* cp = manifold->points + pointCount;
+
+ if (primaryAxis.type == b2EPAxis::e_edgeA)
+ {
+ cp->localPoint = b2MulT(xf, clipPoints2[i].v);
+ cp->id = clipPoints2[i].id;
+ }
+ else
+ {
+ cp->localPoint = clipPoints2[i].v;
+ cp->id.cf.typeA = clipPoints2[i].id.cf.typeB;
+ cp->id.cf.typeB = clipPoints2[i].id.cf.typeA;
+ cp->id.cf.indexA = clipPoints2[i].id.cf.indexB;
+ cp->id.cf.indexB = clipPoints2[i].id.cf.indexA;
+ }
+
+ ++pointCount;
+ }
+ }
+
+ manifold->pointCount = pointCount;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_collide_polygon.cpp b/Client/ThirdParty/Box2D/src/collision/b2_collide_polygon.cpp
new file mode 100644
index 0000000..f3fa850
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_collide_polygon.cpp
@@ -0,0 +1,243 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_collision.h"
+#include "box2d/b2_polygon_shape.h"
+
+// Find the max separation between poly1 and poly2 using edge normals from poly1.
+static float b2FindMaxSeparation(int32* edgeIndex,
+ const b2PolygonShape* poly1, const b2Transform& xf1,
+ const b2PolygonShape* poly2, const b2Transform& xf2)
+{
+ int32 count1 = poly1->m_count;
+ int32 count2 = poly2->m_count;
+ const b2Vec2* n1s = poly1->m_normals;
+ const b2Vec2* v1s = poly1->m_vertices;
+ const b2Vec2* v2s = poly2->m_vertices;
+ b2Transform xf = b2MulT(xf2, xf1);
+
+ int32 bestIndex = 0;
+ float maxSeparation = -b2_maxFloat;
+ for (int32 i = 0; i < count1; ++i)
+ {
+ // Get poly1 normal in frame2.
+ b2Vec2 n = b2Mul(xf.q, n1s[i]);
+ b2Vec2 v1 = b2Mul(xf, v1s[i]);
+
+ // Find deepest point for normal i.
+ float si = b2_maxFloat;
+ for (int32 j = 0; j < count2; ++j)
+ {
+ float sij = b2Dot(n, v2s[j] - v1);
+ if (sij < si)
+ {
+ si = sij;
+ }
+ }
+
+ if (si > maxSeparation)
+ {
+ maxSeparation = si;
+ bestIndex = i;
+ }
+ }
+
+ *edgeIndex = bestIndex;
+ return maxSeparation;
+}
+
+static void b2FindIncidentEdge(b2ClipVertex c[2],
+ const b2PolygonShape* poly1, const b2Transform& xf1, int32 edge1,
+ const b2PolygonShape* poly2, const b2Transform& xf2)
+{
+ const b2Vec2* normals1 = poly1->m_normals;
+
+ int32 count2 = poly2->m_count;
+ const b2Vec2* vertices2 = poly2->m_vertices;
+ const b2Vec2* normals2 = poly2->m_normals;
+
+ b2Assert(0 <= edge1 && edge1 < poly1->m_count);
+
+ // Get the normal of the reference edge in poly2's frame.
+ b2Vec2 normal1 = b2MulT(xf2.q, b2Mul(xf1.q, normals1[edge1]));
+
+ // Find the incident edge on poly2.
+ int32 index = 0;
+ float minDot = b2_maxFloat;
+ for (int32 i = 0; i < count2; ++i)
+ {
+ float dot = b2Dot(normal1, normals2[i]);
+ if (dot < minDot)
+ {
+ minDot = dot;
+ index = i;
+ }
+ }
+
+ // Build the clip vertices for the incident edge.
+ int32 i1 = index;
+ int32 i2 = i1 + 1 < count2 ? i1 + 1 : 0;
+
+ c[0].v = b2Mul(xf2, vertices2[i1]);
+ c[0].id.cf.indexA = (uint8)edge1;
+ c[0].id.cf.indexB = (uint8)i1;
+ c[0].id.cf.typeA = b2ContactFeature::e_face;
+ c[0].id.cf.typeB = b2ContactFeature::e_vertex;
+
+ c[1].v = b2Mul(xf2, vertices2[i2]);
+ c[1].id.cf.indexA = (uint8)edge1;
+ c[1].id.cf.indexB = (uint8)i2;
+ c[1].id.cf.typeA = b2ContactFeature::e_face;
+ c[1].id.cf.typeB = b2ContactFeature::e_vertex;
+}
+
+// Find edge normal of max separation on A - return if separating axis is found
+// Find edge normal of max separation on B - return if separation axis is found
+// Choose reference edge as min(minA, minB)
+// Find incident edge
+// Clip
+
+// The normal points from 1 to 2
+void b2CollidePolygons(b2Manifold* manifold,
+ const b2PolygonShape* polyA, const b2Transform& xfA,
+ const b2PolygonShape* polyB, const b2Transform& xfB)
+{
+ manifold->pointCount = 0;
+ float totalRadius = polyA->m_radius + polyB->m_radius;
+
+ int32 edgeA = 0;
+ float separationA = b2FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
+ if (separationA > totalRadius)
+ return;
+
+ int32 edgeB = 0;
+ float separationB = b2FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);
+ if (separationB > totalRadius)
+ return;
+
+ const b2PolygonShape* poly1; // reference polygon
+ const b2PolygonShape* poly2; // incident polygon
+ b2Transform xf1, xf2;
+ int32 edge1; // reference edge
+ uint8 flip;
+ const float k_tol = 0.1f * b2_linearSlop;
+
+ if (separationB > separationA + k_tol)
+ {
+ poly1 = polyB;
+ poly2 = polyA;
+ xf1 = xfB;
+ xf2 = xfA;
+ edge1 = edgeB;
+ manifold->type = b2Manifold::e_faceB;
+ flip = 1;
+ }
+ else
+ {
+ poly1 = polyA;
+ poly2 = polyB;
+ xf1 = xfA;
+ xf2 = xfB;
+ edge1 = edgeA;
+ manifold->type = b2Manifold::e_faceA;
+ flip = 0;
+ }
+
+ b2ClipVertex incidentEdge[2];
+ b2FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
+
+ int32 count1 = poly1->m_count;
+ const b2Vec2* vertices1 = poly1->m_vertices;
+
+ int32 iv1 = edge1;
+ int32 iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0;
+
+ b2Vec2 v11 = vertices1[iv1];
+ b2Vec2 v12 = vertices1[iv2];
+
+ b2Vec2 localTangent = v12 - v11;
+ localTangent.Normalize();
+
+ b2Vec2 localNormal = b2Cross(localTangent, 1.0f);
+ b2Vec2 planePoint = 0.5f * (v11 + v12);
+
+ b2Vec2 tangent = b2Mul(xf1.q, localTangent);
+ b2Vec2 normal = b2Cross(tangent, 1.0f);
+
+ v11 = b2Mul(xf1, v11);
+ v12 = b2Mul(xf1, v12);
+
+ // Face offset.
+ float frontOffset = b2Dot(normal, v11);
+
+ // Side offsets, extended by polytope skin thickness.
+ float sideOffset1 = -b2Dot(tangent, v11) + totalRadius;
+ float sideOffset2 = b2Dot(tangent, v12) + totalRadius;
+
+ // Clip incident edge against extruded edge1 side edges.
+ b2ClipVertex clipPoints1[2];
+ b2ClipVertex clipPoints2[2];
+ int np;
+
+ // Clip to box side 1
+ np = b2ClipSegmentToLine(clipPoints1, incidentEdge, -tangent, sideOffset1, iv1);
+
+ if (np < 2)
+ return;
+
+ // Clip to negative box side 1
+ np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2);
+
+ if (np < 2)
+ {
+ return;
+ }
+
+ // Now clipPoints2 contains the clipped points.
+ manifold->localNormal = localNormal;
+ manifold->localPoint = planePoint;
+
+ int32 pointCount = 0;
+ for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
+ {
+ float separation = b2Dot(normal, clipPoints2[i].v) - frontOffset;
+
+ if (separation <= totalRadius)
+ {
+ b2ManifoldPoint* cp = manifold->points + pointCount;
+ cp->localPoint = b2MulT(xf2, clipPoints2[i].v);
+ cp->id = clipPoints2[i].id;
+ if (flip)
+ {
+ // Swap features
+ b2ContactFeature cf = cp->id.cf;
+ cp->id.cf.indexA = cf.indexB;
+ cp->id.cf.indexB = cf.indexA;
+ cp->id.cf.typeA = cf.typeB;
+ cp->id.cf.typeB = cf.typeA;
+ }
+ ++pointCount;
+ }
+ }
+
+ manifold->pointCount = pointCount;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_collision.cpp b/Client/ThirdParty/Box2D/src/collision/b2_collision.cpp
new file mode 100644
index 0000000..8a0501b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_collision.cpp
@@ -0,0 +1,258 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_collision.h"
+#include "box2d/b2_distance.h"
+
+void b2WorldManifold::Initialize(const b2Manifold* manifold,
+ const b2Transform& xfA, float radiusA,
+ const b2Transform& xfB, float radiusB)
+{
+ if (manifold->pointCount == 0)
+ {
+ return;
+ }
+
+ switch (manifold->type)
+ {
+ case b2Manifold::e_circles:
+ {
+ normal.Set(1.0f, 0.0f);
+ b2Vec2 pointA = b2Mul(xfA, manifold->localPoint);
+ b2Vec2 pointB = b2Mul(xfB, manifold->points[0].localPoint);
+ if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon)
+ {
+ normal = pointB - pointA;
+ normal.Normalize();
+ }
+
+ b2Vec2 cA = pointA + radiusA * normal;
+ b2Vec2 cB = pointB - radiusB * normal;
+ points[0] = 0.5f * (cA + cB);
+ separations[0] = b2Dot(cB - cA, normal);
+ }
+ break;
+
+ case b2Manifold::e_faceA:
+ {
+ normal = b2Mul(xfA.q, manifold->localNormal);
+ b2Vec2 planePoint = b2Mul(xfA, manifold->localPoint);
+
+ for (int32 i = 0; i < manifold->pointCount; ++i)
+ {
+ b2Vec2 clipPoint = b2Mul(xfB, manifold->points[i].localPoint);
+ b2Vec2 cA = clipPoint + (radiusA - b2Dot(clipPoint - planePoint, normal)) * normal;
+ b2Vec2 cB = clipPoint - radiusB * normal;
+ points[i] = 0.5f * (cA + cB);
+ separations[i] = b2Dot(cB - cA, normal);
+ }
+ }
+ break;
+
+ case b2Manifold::e_faceB:
+ {
+ normal = b2Mul(xfB.q, manifold->localNormal);
+ b2Vec2 planePoint = b2Mul(xfB, manifold->localPoint);
+
+ for (int32 i = 0; i < manifold->pointCount; ++i)
+ {
+ b2Vec2 clipPoint = b2Mul(xfA, manifold->points[i].localPoint);
+ b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal;
+ b2Vec2 cA = clipPoint - radiusA * normal;
+ points[i] = 0.5f * (cA + cB);
+ separations[i] = b2Dot(cA - cB, normal);
+ }
+
+ // Ensure normal points from A to B.
+ normal = -normal;
+ }
+ break;
+ }
+}
+
+void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],
+ const b2Manifold* manifold1, const b2Manifold* manifold2)
+{
+ for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
+ {
+ state1[i] = b2_nullState;
+ state2[i] = b2_nullState;
+ }
+
+ // Detect persists and removes.
+ for (int32 i = 0; i < manifold1->pointCount; ++i)
+ {
+ b2ContactID id = manifold1->points[i].id;
+
+ state1[i] = b2_removeState;
+
+ for (int32 j = 0; j < manifold2->pointCount; ++j)
+ {
+ if (manifold2->points[j].id.key == id.key)
+ {
+ state1[i] = b2_persistState;
+ break;
+ }
+ }
+ }
+
+ // Detect persists and adds.
+ for (int32 i = 0; i < manifold2->pointCount; ++i)
+ {
+ b2ContactID id = manifold2->points[i].id;
+
+ state2[i] = b2_addState;
+
+ for (int32 j = 0; j < manifold1->pointCount; ++j)
+ {
+ if (manifold1->points[j].id.key == id.key)
+ {
+ state2[i] = b2_persistState;
+ break;
+ }
+ }
+ }
+}
+
+// From Real-time Collision Detection, p179.
+bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const
+{
+ float tmin = -b2_maxFloat;
+ float tmax = b2_maxFloat;
+
+ b2Vec2 p = input.p1;
+ b2Vec2 d = input.p2 - input.p1;
+ b2Vec2 absD = b2Abs(d);
+
+ b2Vec2 normal;
+
+ for (int32 i = 0; i < 2; ++i)
+ {
+ if (absD(i) < b2_epsilon)
+ {
+ // Parallel.
+ if (p(i) < lowerBound(i) || upperBound(i) < p(i))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ float inv_d = 1.0f / d(i);
+ float t1 = (lowerBound(i) - p(i)) * inv_d;
+ float t2 = (upperBound(i) - p(i)) * inv_d;
+
+ // Sign of the normal vector.
+ float s = -1.0f;
+
+ if (t1 > t2)
+ {
+ b2Swap(t1, t2);
+ s = 1.0f;
+ }
+
+ // Push the min up
+ if (t1 > tmin)
+ {
+ normal.SetZero();
+ normal(i) = s;
+ tmin = t1;
+ }
+
+ // Pull the max down
+ tmax = b2Min(tmax, t2);
+
+ if (tmin > tmax)
+ {
+ return false;
+ }
+ }
+ }
+
+ // Does the ray start inside the box?
+ // Does the ray intersect beyond the max fraction?
+ if (tmin < 0.0f || input.maxFraction < tmin)
+ {
+ return false;
+ }
+
+ // Intersection.
+ output->fraction = tmin;
+ output->normal = normal;
+ return true;
+}
+
+// Sutherland-Hodgman clipping.
+int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],
+ const b2Vec2& normal, float offset, int32 vertexIndexA)
+{
+ // Start with no output points
+ int32 count = 0;
+
+ // Calculate the distance of end points to the line
+ float distance0 = b2Dot(normal, vIn[0].v) - offset;
+ float distance1 = b2Dot(normal, vIn[1].v) - offset;
+
+ // If the points are behind the plane
+ if (distance0 <= 0.0f) vOut[count++] = vIn[0];
+ if (distance1 <= 0.0f) vOut[count++] = vIn[1];
+
+ // If the points are on different sides of the plane
+ if (distance0 * distance1 < 0.0f)
+ {
+ // Find intersection point of edge and plane
+ float interp = distance0 / (distance0 - distance1);
+ vOut[count].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
+
+ // VertexA is hitting edgeB.
+ vOut[count].id.cf.indexA = static_cast<uint8>(vertexIndexA);
+ vOut[count].id.cf.indexB = vIn[0].id.cf.indexB;
+ vOut[count].id.cf.typeA = b2ContactFeature::e_vertex;
+ vOut[count].id.cf.typeB = b2ContactFeature::e_face;
+ ++count;
+
+ b2Assert(count == 2);
+ }
+
+ return count;
+}
+
+bool b2TestOverlap( const b2Shape* shapeA, int32 indexA,
+ const b2Shape* shapeB, int32 indexB,
+ const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2DistanceInput input;
+ input.proxyA.Set(shapeA, indexA);
+ input.proxyB.Set(shapeB, indexB);
+ input.transformA = xfA;
+ input.transformB = xfB;
+ input.useRadii = true;
+
+ b2SimplexCache cache;
+ cache.count = 0;
+
+ b2DistanceOutput output;
+
+ b2Distance(&output, &cache, &input);
+
+ return output.distance < 10.0f * b2_epsilon;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_distance.cpp b/Client/ThirdParty/Box2D/src/collision/b2_distance.cpp
new file mode 100644
index 0000000..2441324
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_distance.cpp
@@ -0,0 +1,746 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_distance.h"
+#include "box2d/b2_edge_shape.h"
+#include "box2d/b2_chain_shape.h"
+#include "box2d/b2_polygon_shape.h"
+
+// GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates.
+B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
+
+void b2DistanceProxy::Set(const b2Shape* shape, int32 index)
+{
+ switch (shape->GetType())
+ {
+ case b2Shape::e_circle:
+ {
+ const b2CircleShape* circle = static_cast<const b2CircleShape*>(shape);
+ m_vertices = &circle->m_p;
+ m_count = 1;
+ m_radius = circle->m_radius;
+ }
+ break;
+
+ case b2Shape::e_polygon:
+ {
+ const b2PolygonShape* polygon = static_cast<const b2PolygonShape*>(shape);
+ m_vertices = polygon->m_vertices;
+ m_count = polygon->m_count;
+ m_radius = polygon->m_radius;
+ }
+ break;
+
+ case b2Shape::e_chain:
+ {
+ const b2ChainShape* chain = static_cast<const b2ChainShape*>(shape);
+ b2Assert(0 <= index && index < chain->m_count);
+
+ m_buffer[0] = chain->m_vertices[index];
+ if (index + 1 < chain->m_count)
+ {
+ m_buffer[1] = chain->m_vertices[index + 1];
+ }
+ else
+ {
+ m_buffer[1] = chain->m_vertices[0];
+ }
+
+ m_vertices = m_buffer;
+ m_count = 2;
+ m_radius = chain->m_radius;
+ }
+ break;
+
+ case b2Shape::e_edge:
+ {
+ const b2EdgeShape* edge = static_cast<const b2EdgeShape*>(shape);
+ m_vertices = &edge->m_vertex1;
+ m_count = 2;
+ m_radius = edge->m_radius;
+ }
+ break;
+
+ default:
+ b2Assert(false);
+ }
+}
+
+void b2DistanceProxy::Set(const b2Vec2* vertices, int32 count, float radius)
+{
+ m_vertices = vertices;
+ m_count = count;
+ m_radius = radius;
+}
+
+struct b2SimplexVertex
+{
+ b2Vec2 wA; // support point in proxyA
+ b2Vec2 wB; // support point in proxyB
+ b2Vec2 w; // wB - wA
+ float a; // barycentric coordinate for closest point
+ int32 indexA; // wA index
+ int32 indexB; // wB index
+};
+
+struct b2Simplex
+{
+ void ReadCache( const b2SimplexCache* cache,
+ const b2DistanceProxy* proxyA, const b2Transform& transformA,
+ const b2DistanceProxy* proxyB, const b2Transform& transformB)
+ {
+ b2Assert(cache->count <= 3);
+
+ // Copy data from cache.
+ m_count = cache->count;
+ b2SimplexVertex* vertices = &m_v1;
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2SimplexVertex* v = vertices + i;
+ v->indexA = cache->indexA[i];
+ v->indexB = cache->indexB[i];
+ b2Vec2 wALocal = proxyA->GetVertex(v->indexA);
+ b2Vec2 wBLocal = proxyB->GetVertex(v->indexB);
+ v->wA = b2Mul(transformA, wALocal);
+ v->wB = b2Mul(transformB, wBLocal);
+ v->w = v->wB - v->wA;
+ v->a = 0.0f;
+ }
+
+ // Compute the new simplex metric, if it is substantially different than
+ // old metric then flush the simplex.
+ if (m_count > 1)
+ {
+ float metric1 = cache->metric;
+ float metric2 = GetMetric();
+ if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon)
+ {
+ // Reset the simplex.
+ m_count = 0;
+ }
+ }
+
+ // If the cache is empty or invalid ...
+ if (m_count == 0)
+ {
+ b2SimplexVertex* v = vertices + 0;
+ v->indexA = 0;
+ v->indexB = 0;
+ b2Vec2 wALocal = proxyA->GetVertex(0);
+ b2Vec2 wBLocal = proxyB->GetVertex(0);
+ v->wA = b2Mul(transformA, wALocal);
+ v->wB = b2Mul(transformB, wBLocal);
+ v->w = v->wB - v->wA;
+ v->a = 1.0f;
+ m_count = 1;
+ }
+ }
+
+ void WriteCache(b2SimplexCache* cache) const
+ {
+ cache->metric = GetMetric();
+ cache->count = uint16(m_count);
+ const b2SimplexVertex* vertices = &m_v1;
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ cache->indexA[i] = uint8(vertices[i].indexA);
+ cache->indexB[i] = uint8(vertices[i].indexB);
+ }
+ }
+
+ b2Vec2 GetSearchDirection() const
+ {
+ switch (m_count)
+ {
+ case 1:
+ return -m_v1.w;
+
+ case 2:
+ {
+ b2Vec2 e12 = m_v2.w - m_v1.w;
+ float sgn = b2Cross(e12, -m_v1.w);
+ if (sgn > 0.0f)
+ {
+ // Origin is left of e12.
+ return b2Cross(1.0f, e12);
+ }
+ else
+ {
+ // Origin is right of e12.
+ return b2Cross(e12, 1.0f);
+ }
+ }
+
+ default:
+ b2Assert(false);
+ return b2Vec2_zero;
+ }
+ }
+
+ b2Vec2 GetClosestPoint() const
+ {
+ switch (m_count)
+ {
+ case 0:
+ b2Assert(false);
+ return b2Vec2_zero;
+
+ case 1:
+ return m_v1.w;
+
+ case 2:
+ return m_v1.a * m_v1.w + m_v2.a * m_v2.w;
+
+ case 3:
+ return b2Vec2_zero;
+
+ default:
+ b2Assert(false);
+ return b2Vec2_zero;
+ }
+ }
+
+ void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const
+ {
+ switch (m_count)
+ {
+ case 0:
+ b2Assert(false);
+ break;
+
+ case 1:
+ *pA = m_v1.wA;
+ *pB = m_v1.wB;
+ break;
+
+ case 2:
+ *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA;
+ *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB;
+ break;
+
+ case 3:
+ *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA;
+ *pB = *pA;
+ break;
+
+ default:
+ b2Assert(false);
+ break;
+ }
+ }
+
+ float GetMetric() const
+ {
+ switch (m_count)
+ {
+ case 0:
+ b2Assert(false);
+ return 0.0f;
+
+ case 1:
+ return 0.0f;
+
+ case 2:
+ return b2Distance(m_v1.w, m_v2.w);
+
+ case 3:
+ return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w);
+
+ default:
+ b2Assert(false);
+ return 0.0f;
+ }
+ }
+
+ void Solve2();
+ void Solve3();
+
+ b2SimplexVertex m_v1, m_v2, m_v3;
+ int32 m_count;
+};
+
+
+// Solve a line segment using barycentric coordinates.
+//
+// p = a1 * w1 + a2 * w2
+// a1 + a2 = 1
+//
+// The vector from the origin to the closest point on the line is
+// perpendicular to the line.
+// e12 = w2 - w1
+// dot(p, e) = 0
+// a1 * dot(w1, e) + a2 * dot(w2, e) = 0
+//
+// 2-by-2 linear system
+// [1 1 ][a1] = [1]
+// [w1.e12 w2.e12][a2] = [0]
+//
+// Define
+// d12_1 = dot(w2, e12)
+// d12_2 = -dot(w1, e12)
+// d12 = d12_1 + d12_2
+//
+// Solution
+// a1 = d12_1 / d12
+// a2 = d12_2 / d12
+void b2Simplex::Solve2()
+{
+ b2Vec2 w1 = m_v1.w;
+ b2Vec2 w2 = m_v2.w;
+ b2Vec2 e12 = w2 - w1;
+
+ // w1 region
+ float d12_2 = -b2Dot(w1, e12);
+ if (d12_2 <= 0.0f)
+ {
+ // a2 <= 0, so we clamp it to 0
+ m_v1.a = 1.0f;
+ m_count = 1;
+ return;
+ }
+
+ // w2 region
+ float d12_1 = b2Dot(w2, e12);
+ if (d12_1 <= 0.0f)
+ {
+ // a1 <= 0, so we clamp it to 0
+ m_v2.a = 1.0f;
+ m_count = 1;
+ m_v1 = m_v2;
+ return;
+ }
+
+ // Must be in e12 region.
+ float inv_d12 = 1.0f / (d12_1 + d12_2);
+ m_v1.a = d12_1 * inv_d12;
+ m_v2.a = d12_2 * inv_d12;
+ m_count = 2;
+}
+
+// Possible regions:
+// - points[2]
+// - edge points[0]-points[2]
+// - edge points[1]-points[2]
+// - inside the triangle
+void b2Simplex::Solve3()
+{
+ b2Vec2 w1 = m_v1.w;
+ b2Vec2 w2 = m_v2.w;
+ b2Vec2 w3 = m_v3.w;
+
+ // Edge12
+ // [1 1 ][a1] = [1]
+ // [w1.e12 w2.e12][a2] = [0]
+ // a3 = 0
+ b2Vec2 e12 = w2 - w1;
+ float w1e12 = b2Dot(w1, e12);
+ float w2e12 = b2Dot(w2, e12);
+ float d12_1 = w2e12;
+ float d12_2 = -w1e12;
+
+ // Edge13
+ // [1 1 ][a1] = [1]
+ // [w1.e13 w3.e13][a3] = [0]
+ // a2 = 0
+ b2Vec2 e13 = w3 - w1;
+ float w1e13 = b2Dot(w1, e13);
+ float w3e13 = b2Dot(w3, e13);
+ float d13_1 = w3e13;
+ float d13_2 = -w1e13;
+
+ // Edge23
+ // [1 1 ][a2] = [1]
+ // [w2.e23 w3.e23][a3] = [0]
+ // a1 = 0
+ b2Vec2 e23 = w3 - w2;
+ float w2e23 = b2Dot(w2, e23);
+ float w3e23 = b2Dot(w3, e23);
+ float d23_1 = w3e23;
+ float d23_2 = -w2e23;
+
+ // Triangle123
+ float n123 = b2Cross(e12, e13);
+
+ float d123_1 = n123 * b2Cross(w2, w3);
+ float d123_2 = n123 * b2Cross(w3, w1);
+ float d123_3 = n123 * b2Cross(w1, w2);
+
+ // w1 region
+ if (d12_2 <= 0.0f && d13_2 <= 0.0f)
+ {
+ m_v1.a = 1.0f;
+ m_count = 1;
+ return;
+ }
+
+ // e12
+ if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f)
+ {
+ float inv_d12 = 1.0f / (d12_1 + d12_2);
+ m_v1.a = d12_1 * inv_d12;
+ m_v2.a = d12_2 * inv_d12;
+ m_count = 2;
+ return;
+ }
+
+ // e13
+ if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f)
+ {
+ float inv_d13 = 1.0f / (d13_1 + d13_2);
+ m_v1.a = d13_1 * inv_d13;
+ m_v3.a = d13_2 * inv_d13;
+ m_count = 2;
+ m_v2 = m_v3;
+ return;
+ }
+
+ // w2 region
+ if (d12_1 <= 0.0f && d23_2 <= 0.0f)
+ {
+ m_v2.a = 1.0f;
+ m_count = 1;
+ m_v1 = m_v2;
+ return;
+ }
+
+ // w3 region
+ if (d13_1 <= 0.0f && d23_1 <= 0.0f)
+ {
+ m_v3.a = 1.0f;
+ m_count = 1;
+ m_v1 = m_v3;
+ return;
+ }
+
+ // e23
+ if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f)
+ {
+ float inv_d23 = 1.0f / (d23_1 + d23_2);
+ m_v2.a = d23_1 * inv_d23;
+ m_v3.a = d23_2 * inv_d23;
+ m_count = 2;
+ m_v1 = m_v3;
+ return;
+ }
+
+ // Must be in triangle123
+ float inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3);
+ m_v1.a = d123_1 * inv_d123;
+ m_v2.a = d123_2 * inv_d123;
+ m_v3.a = d123_3 * inv_d123;
+ m_count = 3;
+}
+
+void b2Distance(b2DistanceOutput* output,
+ b2SimplexCache* cache,
+ const b2DistanceInput* input)
+{
+ ++b2_gjkCalls;
+
+ const b2DistanceProxy* proxyA = &input->proxyA;
+ const b2DistanceProxy* proxyB = &input->proxyB;
+
+ b2Transform transformA = input->transformA;
+ b2Transform transformB = input->transformB;
+
+ // Initialize the simplex.
+ b2Simplex simplex;
+ simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB);
+
+ // Get simplex vertices as an array.
+ b2SimplexVertex* vertices = &simplex.m_v1;
+ const int32 k_maxIters = 20;
+
+ // These store the vertices of the last simplex so that we
+ // can check for duplicates and prevent cycling.
+ int32 saveA[3], saveB[3];
+ int32 saveCount = 0;
+
+ // Main iteration loop.
+ int32 iter = 0;
+ while (iter < k_maxIters)
+ {
+ // Copy simplex so we can identify duplicates.
+ saveCount = simplex.m_count;
+ for (int32 i = 0; i < saveCount; ++i)
+ {
+ saveA[i] = vertices[i].indexA;
+ saveB[i] = vertices[i].indexB;
+ }
+
+ switch (simplex.m_count)
+ {
+ case 1:
+ break;
+
+ case 2:
+ simplex.Solve2();
+ break;
+
+ case 3:
+ simplex.Solve3();
+ break;
+
+ default:
+ b2Assert(false);
+ }
+
+ // If we have 3 points, then the origin is in the corresponding triangle.
+ if (simplex.m_count == 3)
+ {
+ break;
+ }
+
+ // Get search direction.
+ b2Vec2 d = simplex.GetSearchDirection();
+
+ // Ensure the search direction is numerically fit.
+ if (d.LengthSquared() < b2_epsilon * b2_epsilon)
+ {
+ // The origin is probably contained by a line segment
+ // or triangle. Thus the shapes are overlapped.
+
+ // We can't return zero here even though there may be overlap.
+ // In case the simplex is a point, segment, or triangle it is difficult
+ // to determine if the origin is contained in the CSO or very close to it.
+ break;
+ }
+
+ // Compute a tentative new simplex vertex using support points.
+ b2SimplexVertex* vertex = vertices + simplex.m_count;
+ vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d));
+ vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA));
+ vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d));
+ vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB));
+ vertex->w = vertex->wB - vertex->wA;
+
+ // Iteration count is equated to the number of support point calls.
+ ++iter;
+ ++b2_gjkIters;
+
+ // Check for duplicate support points. This is the main termination criteria.
+ bool duplicate = false;
+ for (int32 i = 0; i < saveCount; ++i)
+ {
+ if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i])
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ // If we found a duplicate support point we must exit to avoid cycling.
+ if (duplicate)
+ {
+ break;
+ }
+
+ // New vertex is ok and needed.
+ ++simplex.m_count;
+ }
+
+ b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter);
+
+ // Prepare output.
+ simplex.GetWitnessPoints(&output->pointA, &output->pointB);
+ output->distance = b2Distance(output->pointA, output->pointB);
+ output->iterations = iter;
+
+ // Cache the simplex.
+ simplex.WriteCache(cache);
+
+ // Apply radii if requested.
+ if (input->useRadii)
+ {
+ float rA = proxyA->m_radius;
+ float rB = proxyB->m_radius;
+
+ if (output->distance > rA + rB && output->distance > b2_epsilon)
+ {
+ // Shapes are still no overlapped.
+ // Move the witness points to the outer surface.
+ output->distance -= rA + rB;
+ b2Vec2 normal = output->pointB - output->pointA;
+ normal.Normalize();
+ output->pointA += rA * normal;
+ output->pointB -= rB * normal;
+ }
+ else
+ {
+ // Shapes are overlapped when radii are considered.
+ // Move the witness points to the middle.
+ b2Vec2 p = 0.5f * (output->pointA + output->pointB);
+ output->pointA = p;
+ output->pointB = p;
+ output->distance = 0.0f;
+ }
+ }
+}
+
+// GJK-raycast
+// Algorithm by Gino van den Bergen.
+// "Smooth Mesh Contacts with GJK" in Game Physics Pearls. 2010
+bool b2ShapeCast(b2ShapeCastOutput * output, const b2ShapeCastInput * input)
+{
+ output->iterations = 0;
+ output->lambda = 1.0f;
+ output->normal.SetZero();
+ output->point.SetZero();
+
+ const b2DistanceProxy* proxyA = &input->proxyA;
+ const b2DistanceProxy* proxyB = &input->proxyB;
+
+ float radiusA = b2Max(proxyA->m_radius, b2_polygonRadius);
+ float radiusB = b2Max(proxyB->m_radius, b2_polygonRadius);
+ float radius = radiusA + radiusB;
+
+ b2Transform xfA = input->transformA;
+ b2Transform xfB = input->transformB;
+
+ b2Vec2 r = input->translationB;
+ b2Vec2 n(0.0f, 0.0f);
+ float lambda = 0.0f;
+
+ // Initial simplex
+ b2Simplex simplex;
+ simplex.m_count = 0;
+
+ // Get simplex vertices as an array.
+ b2SimplexVertex* vertices = &simplex.m_v1;
+
+ // Get support point in -r direction
+ int32 indexA = proxyA->GetSupport(b2MulT(xfA.q, -r));
+ b2Vec2 wA = b2Mul(xfA, proxyA->GetVertex(indexA));
+ int32 indexB = proxyB->GetSupport(b2MulT(xfB.q, r));
+ b2Vec2 wB = b2Mul(xfB, proxyB->GetVertex(indexB));
+ b2Vec2 v = wA - wB;
+
+ // Sigma is the target distance between polygons
+ float sigma = b2Max(b2_polygonRadius, radius - b2_polygonRadius);
+ const float tolerance = 0.5f * b2_linearSlop;
+
+ // Main iteration loop.
+ const int32 k_maxIters = 20;
+ int32 iter = 0;
+ while (iter < k_maxIters && v.Length() - sigma > tolerance)
+ {
+ b2Assert(simplex.m_count < 3);
+
+ output->iterations += 1;
+
+ // Support in direction -v (A - B)
+ indexA = proxyA->GetSupport(b2MulT(xfA.q, -v));
+ wA = b2Mul(xfA, proxyA->GetVertex(indexA));
+ indexB = proxyB->GetSupport(b2MulT(xfB.q, v));
+ wB = b2Mul(xfB, proxyB->GetVertex(indexB));
+ b2Vec2 p = wA - wB;
+
+ // -v is a normal at p
+ v.Normalize();
+
+ // Intersect ray with plane
+ float vp = b2Dot(v, p);
+ float vr = b2Dot(v, r);
+ if (vp - sigma > lambda * vr)
+ {
+ if (vr <= 0.0f)
+ {
+ return false;
+ }
+
+ lambda = (vp - sigma) / vr;
+ if (lambda > 1.0f)
+ {
+ return false;
+ }
+
+ n = -v;
+ simplex.m_count = 0;
+ }
+
+ // Reverse simplex since it works with B - A.
+ // Shift by lambda * r because we want the closest point to the current clip point.
+ // Note that the support point p is not shifted because we want the plane equation
+ // to be formed in unshifted space.
+ b2SimplexVertex* vertex = vertices + simplex.m_count;
+ vertex->indexA = indexB;
+ vertex->wA = wB + lambda * r;
+ vertex->indexB = indexA;
+ vertex->wB = wA;
+ vertex->w = vertex->wB - vertex->wA;
+ vertex->a = 1.0f;
+ simplex.m_count += 1;
+
+ switch (simplex.m_count)
+ {
+ case 1:
+ break;
+
+ case 2:
+ simplex.Solve2();
+ break;
+
+ case 3:
+ simplex.Solve3();
+ break;
+
+ default:
+ b2Assert(false);
+ }
+
+ // If we have 3 points, then the origin is in the corresponding triangle.
+ if (simplex.m_count == 3)
+ {
+ // Overlap
+ return false;
+ }
+
+ // Get search direction.
+ v = simplex.GetClosestPoint();
+
+ // Iteration count is equated to the number of support point calls.
+ ++iter;
+ }
+
+ if (iter == 0)
+ {
+ // Initial overlap
+ return false;
+ }
+
+ // Prepare output.
+ b2Vec2 pointA, pointB;
+ simplex.GetWitnessPoints(&pointB, &pointA);
+
+ if (v.LengthSquared() > 0.0f)
+ {
+ n = -v;
+ n.Normalize();
+ }
+
+ output->point = pointA + radiusA * n;
+ output->normal = n;
+ output->lambda = lambda;
+ output->iterations = iter;
+ return true;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_dynamic_tree.cpp b/Client/ThirdParty/Box2D/src/collision/b2_dynamic_tree.cpp
new file mode 100644
index 0000000..55a9d32
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_dynamic_tree.cpp
@@ -0,0 +1,801 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+#include "box2d/b2_dynamic_tree.h"
+#include <string.h>
+
+b2DynamicTree::b2DynamicTree()
+{
+ m_root = b2_nullNode;
+
+ m_nodeCapacity = 16;
+ m_nodeCount = 0;
+ m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode));
+ memset(m_nodes, 0, m_nodeCapacity * sizeof(b2TreeNode));
+
+ // Build a linked list for the free list.
+ for (int32 i = 0; i < m_nodeCapacity - 1; ++i)
+ {
+ m_nodes[i].next = i + 1;
+ m_nodes[i].height = -1;
+ }
+ m_nodes[m_nodeCapacity-1].next = b2_nullNode;
+ m_nodes[m_nodeCapacity-1].height = -1;
+ m_freeList = 0;
+
+ m_insertionCount = 0;
+}
+
+b2DynamicTree::~b2DynamicTree()
+{
+ // This frees the entire tree in one shot.
+ b2Free(m_nodes);
+}
+
+// Allocate a node from the pool. Grow the pool if necessary.
+int32 b2DynamicTree::AllocateNode()
+{
+ // Expand the node pool as needed.
+ if (m_freeList == b2_nullNode)
+ {
+ b2Assert(m_nodeCount == m_nodeCapacity);
+
+ // The free list is empty. Rebuild a bigger pool.
+ b2TreeNode* oldNodes = m_nodes;
+ m_nodeCapacity *= 2;
+ m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode));
+ memcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2TreeNode));
+ b2Free(oldNodes);
+
+ // Build a linked list for the free list. The parent
+ // pointer becomes the "next" pointer.
+ for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i)
+ {
+ m_nodes[i].next = i + 1;
+ m_nodes[i].height = -1;
+ }
+ m_nodes[m_nodeCapacity-1].next = b2_nullNode;
+ m_nodes[m_nodeCapacity-1].height = -1;
+ m_freeList = m_nodeCount;
+ }
+
+ // Peel a node off the free list.
+ int32 nodeId = m_freeList;
+ m_freeList = m_nodes[nodeId].next;
+ m_nodes[nodeId].parent = b2_nullNode;
+ m_nodes[nodeId].child1 = b2_nullNode;
+ m_nodes[nodeId].child2 = b2_nullNode;
+ m_nodes[nodeId].height = 0;
+ m_nodes[nodeId].userData = nullptr;
+ m_nodes[nodeId].moved = false;
+ ++m_nodeCount;
+ return nodeId;
+}
+
+// Return a node to the pool.
+void b2DynamicTree::FreeNode(int32 nodeId)
+{
+ b2Assert(0 <= nodeId && nodeId < m_nodeCapacity);
+ b2Assert(0 < m_nodeCount);
+ m_nodes[nodeId].next = m_freeList;
+ m_nodes[nodeId].height = -1;
+ m_freeList = nodeId;
+ --m_nodeCount;
+}
+
+// Create a proxy in the tree as a leaf node. We return the index
+// of the node instead of a pointer so that we can grow
+// the node pool.
+int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData)
+{
+ int32 proxyId = AllocateNode();
+
+ // Fatten the aabb.
+ b2Vec2 r(b2_aabbExtension, b2_aabbExtension);
+ m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r;
+ m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r;
+ m_nodes[proxyId].userData = userData;
+ m_nodes[proxyId].height = 0;
+ m_nodes[proxyId].moved = true;
+
+ InsertLeaf(proxyId);
+
+ return proxyId;
+}
+
+void b2DynamicTree::DestroyProxy(int32 proxyId)
+{
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
+ b2Assert(m_nodes[proxyId].IsLeaf());
+
+ RemoveLeaf(proxyId);
+ FreeNode(proxyId);
+}
+
+bool b2DynamicTree::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement)
+{
+ b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
+
+ b2Assert(m_nodes[proxyId].IsLeaf());
+
+ // Extend AABB
+ b2AABB fatAABB;
+ b2Vec2 r(b2_aabbExtension, b2_aabbExtension);
+ fatAABB.lowerBound = aabb.lowerBound - r;
+ fatAABB.upperBound = aabb.upperBound + r;
+
+ // Predict AABB movement
+ b2Vec2 d = b2_aabbMultiplier * displacement;
+
+ if (d.x < 0.0f)
+ {
+ fatAABB.lowerBound.x += d.x;
+ }
+ else
+ {
+ fatAABB.upperBound.x += d.x;
+ }
+
+ if (d.y < 0.0f)
+ {
+ fatAABB.lowerBound.y += d.y;
+ }
+ else
+ {
+ fatAABB.upperBound.y += d.y;
+ }
+
+ const b2AABB& treeAABB = m_nodes[proxyId].aabb;
+ if (treeAABB.Contains(aabb))
+ {
+ // The tree AABB still contains the object, but it might be too large.
+ // Perhaps the object was moving fast but has since gone to sleep.
+ // The huge AABB is larger than the new fat AABB.
+ b2AABB hugeAABB;
+ hugeAABB.lowerBound = fatAABB.lowerBound - 4.0f * r;
+ hugeAABB.upperBound = fatAABB.upperBound + 4.0f * r;
+
+ if (hugeAABB.Contains(treeAABB))
+ {
+ // The tree AABB contains the object AABB and the tree AABB is
+ // not too large. No tree update needed.
+ return false;
+ }
+
+ // Otherwise the tree AABB is huge and needs to be shrunk
+ }
+
+ RemoveLeaf(proxyId);
+
+ m_nodes[proxyId].aabb = fatAABB;
+
+ InsertLeaf(proxyId);
+
+ m_nodes[proxyId].moved = true;
+
+ return true;
+}
+
+void b2DynamicTree::InsertLeaf(int32 leaf)
+{
+ ++m_insertionCount;
+
+ if (m_root == b2_nullNode)
+ {
+ m_root = leaf;
+ m_nodes[m_root].parent = b2_nullNode;
+ return;
+ }
+
+ // Find the best sibling for this node
+ b2AABB leafAABB = m_nodes[leaf].aabb;
+ int32 index = m_root;
+ while (m_nodes[index].IsLeaf() == false)
+ {
+ int32 child1 = m_nodes[index].child1;
+ int32 child2 = m_nodes[index].child2;
+
+ float area = m_nodes[index].aabb.GetPerimeter();
+
+ b2AABB combinedAABB;
+ combinedAABB.Combine(m_nodes[index].aabb, leafAABB);
+ float combinedArea = combinedAABB.GetPerimeter();
+
+ // Cost of creating a new parent for this node and the new leaf
+ float cost = 2.0f * combinedArea;
+
+ // Minimum cost of pushing the leaf further down the tree
+ float inheritanceCost = 2.0f * (combinedArea - area);
+
+ // Cost of descending into child1
+ float cost1;
+ if (m_nodes[child1].IsLeaf())
+ {
+ b2AABB aabb;
+ aabb.Combine(leafAABB, m_nodes[child1].aabb);
+ cost1 = aabb.GetPerimeter() + inheritanceCost;
+ }
+ else
+ {
+ b2AABB aabb;
+ aabb.Combine(leafAABB, m_nodes[child1].aabb);
+ float oldArea = m_nodes[child1].aabb.GetPerimeter();
+ float newArea = aabb.GetPerimeter();
+ cost1 = (newArea - oldArea) + inheritanceCost;
+ }
+
+ // Cost of descending into child2
+ float cost2;
+ if (m_nodes[child2].IsLeaf())
+ {
+ b2AABB aabb;
+ aabb.Combine(leafAABB, m_nodes[child2].aabb);
+ cost2 = aabb.GetPerimeter() + inheritanceCost;
+ }
+ else
+ {
+ b2AABB aabb;
+ aabb.Combine(leafAABB, m_nodes[child2].aabb);
+ float oldArea = m_nodes[child2].aabb.GetPerimeter();
+ float newArea = aabb.GetPerimeter();
+ cost2 = newArea - oldArea + inheritanceCost;
+ }
+
+ // Descend according to the minimum cost.
+ if (cost < cost1 && cost < cost2)
+ {
+ break;
+ }
+
+ // Descend
+ if (cost1 < cost2)
+ {
+ index = child1;
+ }
+ else
+ {
+ index = child2;
+ }
+ }
+
+ int32 sibling = index;
+
+ // Create a new parent.
+ int32 oldParent = m_nodes[sibling].parent;
+ int32 newParent = AllocateNode();
+ m_nodes[newParent].parent = oldParent;
+ m_nodes[newParent].userData = nullptr;
+ m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb);
+ m_nodes[newParent].height = m_nodes[sibling].height + 1;
+
+ if (oldParent != b2_nullNode)
+ {
+ // The sibling was not the root.
+ if (m_nodes[oldParent].child1 == sibling)
+ {
+ m_nodes[oldParent].child1 = newParent;
+ }
+ else
+ {
+ m_nodes[oldParent].child2 = newParent;
+ }
+
+ m_nodes[newParent].child1 = sibling;
+ m_nodes[newParent].child2 = leaf;
+ m_nodes[sibling].parent = newParent;
+ m_nodes[leaf].parent = newParent;
+ }
+ else
+ {
+ // The sibling was the root.
+ m_nodes[newParent].child1 = sibling;
+ m_nodes[newParent].child2 = leaf;
+ m_nodes[sibling].parent = newParent;
+ m_nodes[leaf].parent = newParent;
+ m_root = newParent;
+ }
+
+ // Walk back up the tree fixing heights and AABBs
+ index = m_nodes[leaf].parent;
+ while (index != b2_nullNode)
+ {
+ index = Balance(index);
+
+ int32 child1 = m_nodes[index].child1;
+ int32 child2 = m_nodes[index].child2;
+
+ b2Assert(child1 != b2_nullNode);
+ b2Assert(child2 != b2_nullNode);
+
+ m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height);
+ m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);
+
+ index = m_nodes[index].parent;
+ }
+
+ //Validate();
+}
+
+void b2DynamicTree::RemoveLeaf(int32 leaf)
+{
+ if (leaf == m_root)
+ {
+ m_root = b2_nullNode;
+ return;
+ }
+
+ int32 parent = m_nodes[leaf].parent;
+ int32 grandParent = m_nodes[parent].parent;
+ int32 sibling;
+ if (m_nodes[parent].child1 == leaf)
+ {
+ sibling = m_nodes[parent].child2;
+ }
+ else
+ {
+ sibling = m_nodes[parent].child1;
+ }
+
+ if (grandParent != b2_nullNode)
+ {
+ // Destroy parent and connect sibling to grandParent.
+ if (m_nodes[grandParent].child1 == parent)
+ {
+ m_nodes[grandParent].child1 = sibling;
+ }
+ else
+ {
+ m_nodes[grandParent].child2 = sibling;
+ }
+ m_nodes[sibling].parent = grandParent;
+ FreeNode(parent);
+
+ // Adjust ancestor bounds.
+ int32 index = grandParent;
+ while (index != b2_nullNode)
+ {
+ index = Balance(index);
+
+ int32 child1 = m_nodes[index].child1;
+ int32 child2 = m_nodes[index].child2;
+
+ m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);
+ m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height);
+
+ index = m_nodes[index].parent;
+ }
+ }
+ else
+ {
+ m_root = sibling;
+ m_nodes[sibling].parent = b2_nullNode;
+ FreeNode(parent);
+ }
+
+ //Validate();
+}
+
+// Perform a left or right rotation if node A is imbalanced.
+// Returns the new root index.
+int32 b2DynamicTree::Balance(int32 iA)
+{
+ b2Assert(iA != b2_nullNode);
+
+ b2TreeNode* A = m_nodes + iA;
+ if (A->IsLeaf() || A->height < 2)
+ {
+ return iA;
+ }
+
+ int32 iB = A->child1;
+ int32 iC = A->child2;
+ b2Assert(0 <= iB && iB < m_nodeCapacity);
+ b2Assert(0 <= iC && iC < m_nodeCapacity);
+
+ b2TreeNode* B = m_nodes + iB;
+ b2TreeNode* C = m_nodes + iC;
+
+ int32 balance = C->height - B->height;
+
+ // Rotate C up
+ if (balance > 1)
+ {
+ int32 iF = C->child1;
+ int32 iG = C->child2;
+ b2TreeNode* F = m_nodes + iF;
+ b2TreeNode* G = m_nodes + iG;
+ b2Assert(0 <= iF && iF < m_nodeCapacity);
+ b2Assert(0 <= iG && iG < m_nodeCapacity);
+
+ // Swap A and C
+ C->child1 = iA;
+ C->parent = A->parent;
+ A->parent = iC;
+
+ // A's old parent should point to C
+ if (C->parent != b2_nullNode)
+ {
+ if (m_nodes[C->parent].child1 == iA)
+ {
+ m_nodes[C->parent].child1 = iC;
+ }
+ else
+ {
+ b2Assert(m_nodes[C->parent].child2 == iA);
+ m_nodes[C->parent].child2 = iC;
+ }
+ }
+ else
+ {
+ m_root = iC;
+ }
+
+ // Rotate
+ if (F->height > G->height)
+ {
+ C->child2 = iF;
+ A->child2 = iG;
+ G->parent = iA;
+ A->aabb.Combine(B->aabb, G->aabb);
+ C->aabb.Combine(A->aabb, F->aabb);
+
+ A->height = 1 + b2Max(B->height, G->height);
+ C->height = 1 + b2Max(A->height, F->height);
+ }
+ else
+ {
+ C->child2 = iG;
+ A->child2 = iF;
+ F->parent = iA;
+ A->aabb.Combine(B->aabb, F->aabb);
+ C->aabb.Combine(A->aabb, G->aabb);
+
+ A->height = 1 + b2Max(B->height, F->height);
+ C->height = 1 + b2Max(A->height, G->height);
+ }
+
+ return iC;
+ }
+
+ // Rotate B up
+ if (balance < -1)
+ {
+ int32 iD = B->child1;
+ int32 iE = B->child2;
+ b2TreeNode* D = m_nodes + iD;
+ b2TreeNode* E = m_nodes + iE;
+ b2Assert(0 <= iD && iD < m_nodeCapacity);
+ b2Assert(0 <= iE && iE < m_nodeCapacity);
+
+ // Swap A and B
+ B->child1 = iA;
+ B->parent = A->parent;
+ A->parent = iB;
+
+ // A's old parent should point to B
+ if (B->parent != b2_nullNode)
+ {
+ if (m_nodes[B->parent].child1 == iA)
+ {
+ m_nodes[B->parent].child1 = iB;
+ }
+ else
+ {
+ b2Assert(m_nodes[B->parent].child2 == iA);
+ m_nodes[B->parent].child2 = iB;
+ }
+ }
+ else
+ {
+ m_root = iB;
+ }
+
+ // Rotate
+ if (D->height > E->height)
+ {
+ B->child2 = iD;
+ A->child1 = iE;
+ E->parent = iA;
+ A->aabb.Combine(C->aabb, E->aabb);
+ B->aabb.Combine(A->aabb, D->aabb);
+
+ A->height = 1 + b2Max(C->height, E->height);
+ B->height = 1 + b2Max(A->height, D->height);
+ }
+ else
+ {
+ B->child2 = iE;
+ A->child1 = iD;
+ D->parent = iA;
+ A->aabb.Combine(C->aabb, D->aabb);
+ B->aabb.Combine(A->aabb, E->aabb);
+
+ A->height = 1 + b2Max(C->height, D->height);
+ B->height = 1 + b2Max(A->height, E->height);
+ }
+
+ return iB;
+ }
+
+ return iA;
+}
+
+int32 b2DynamicTree::GetHeight() const
+{
+ if (m_root == b2_nullNode)
+ {
+ return 0;
+ }
+
+ return m_nodes[m_root].height;
+}
+
+//
+float b2DynamicTree::GetAreaRatio() const
+{
+ if (m_root == b2_nullNode)
+ {
+ return 0.0f;
+ }
+
+ const b2TreeNode* root = m_nodes + m_root;
+ float rootArea = root->aabb.GetPerimeter();
+
+ float totalArea = 0.0f;
+ for (int32 i = 0; i < m_nodeCapacity; ++i)
+ {
+ const b2TreeNode* node = m_nodes + i;
+ if (node->height < 0)
+ {
+ // Free node in pool
+ continue;
+ }
+
+ totalArea += node->aabb.GetPerimeter();
+ }
+
+ return totalArea / rootArea;
+}
+
+// Compute the height of a sub-tree.
+int32 b2DynamicTree::ComputeHeight(int32 nodeId) const
+{
+ b2Assert(0 <= nodeId && nodeId < m_nodeCapacity);
+ b2TreeNode* node = m_nodes + nodeId;
+
+ if (node->IsLeaf())
+ {
+ return 0;
+ }
+
+ int32 height1 = ComputeHeight(node->child1);
+ int32 height2 = ComputeHeight(node->child2);
+ return 1 + b2Max(height1, height2);
+}
+
+int32 b2DynamicTree::ComputeHeight() const
+{
+ int32 height = ComputeHeight(m_root);
+ return height;
+}
+
+void b2DynamicTree::ValidateStructure(int32 index) const
+{
+ if (index == b2_nullNode)
+ {
+ return;
+ }
+
+ if (index == m_root)
+ {
+ b2Assert(m_nodes[index].parent == b2_nullNode);
+ }
+
+ const b2TreeNode* node = m_nodes + index;
+
+ int32 child1 = node->child1;
+ int32 child2 = node->child2;
+
+ if (node->IsLeaf())
+ {
+ b2Assert(child1 == b2_nullNode);
+ b2Assert(child2 == b2_nullNode);
+ b2Assert(node->height == 0);
+ return;
+ }
+
+ b2Assert(0 <= child1 && child1 < m_nodeCapacity);
+ b2Assert(0 <= child2 && child2 < m_nodeCapacity);
+
+ b2Assert(m_nodes[child1].parent == index);
+ b2Assert(m_nodes[child2].parent == index);
+
+ ValidateStructure(child1);
+ ValidateStructure(child2);
+}
+
+void b2DynamicTree::ValidateMetrics(int32 index) const
+{
+ if (index == b2_nullNode)
+ {
+ return;
+ }
+
+ const b2TreeNode* node = m_nodes + index;
+
+ int32 child1 = node->child1;
+ int32 child2 = node->child2;
+
+ if (node->IsLeaf())
+ {
+ b2Assert(child1 == b2_nullNode);
+ b2Assert(child2 == b2_nullNode);
+ b2Assert(node->height == 0);
+ return;
+ }
+
+ b2Assert(0 <= child1 && child1 < m_nodeCapacity);
+ b2Assert(0 <= child2 && child2 < m_nodeCapacity);
+
+ int32 height1 = m_nodes[child1].height;
+ int32 height2 = m_nodes[child2].height;
+ int32 height;
+ height = 1 + b2Max(height1, height2);
+ b2Assert(node->height == height);
+
+ b2AABB aabb;
+ aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb);
+
+ b2Assert(aabb.lowerBound == node->aabb.lowerBound);
+ b2Assert(aabb.upperBound == node->aabb.upperBound);
+
+ ValidateMetrics(child1);
+ ValidateMetrics(child2);
+}
+
+void b2DynamicTree::Validate() const
+{
+#if defined(b2DEBUG)
+ ValidateStructure(m_root);
+ ValidateMetrics(m_root);
+
+ int32 freeCount = 0;
+ int32 freeIndex = m_freeList;
+ while (freeIndex != b2_nullNode)
+ {
+ b2Assert(0 <= freeIndex && freeIndex < m_nodeCapacity);
+ freeIndex = m_nodes[freeIndex].next;
+ ++freeCount;
+ }
+
+ b2Assert(GetHeight() == ComputeHeight());
+
+ b2Assert(m_nodeCount + freeCount == m_nodeCapacity);
+#endif
+}
+
+int32 b2DynamicTree::GetMaxBalance() const
+{
+ int32 maxBalance = 0;
+ for (int32 i = 0; i < m_nodeCapacity; ++i)
+ {
+ const b2TreeNode* node = m_nodes + i;
+ if (node->height <= 1)
+ {
+ continue;
+ }
+
+ b2Assert(node->IsLeaf() == false);
+
+ int32 child1 = node->child1;
+ int32 child2 = node->child2;
+ int32 balance = b2Abs(m_nodes[child2].height - m_nodes[child1].height);
+ maxBalance = b2Max(maxBalance, balance);
+ }
+
+ return maxBalance;
+}
+
+void b2DynamicTree::RebuildBottomUp()
+{
+ int32* nodes = (int32*)b2Alloc(m_nodeCount * sizeof(int32));
+ int32 count = 0;
+
+ // Build array of leaves. Free the rest.
+ for (int32 i = 0; i < m_nodeCapacity; ++i)
+ {
+ if (m_nodes[i].height < 0)
+ {
+ // free node in pool
+ continue;
+ }
+
+ if (m_nodes[i].IsLeaf())
+ {
+ m_nodes[i].parent = b2_nullNode;
+ nodes[count] = i;
+ ++count;
+ }
+ else
+ {
+ FreeNode(i);
+ }
+ }
+
+ while (count > 1)
+ {
+ float minCost = b2_maxFloat;
+ int32 iMin = -1, jMin = -1;
+ for (int32 i = 0; i < count; ++i)
+ {
+ b2AABB aabbi = m_nodes[nodes[i]].aabb;
+
+ for (int32 j = i + 1; j < count; ++j)
+ {
+ b2AABB aabbj = m_nodes[nodes[j]].aabb;
+ b2AABB b;
+ b.Combine(aabbi, aabbj);
+ float cost = b.GetPerimeter();
+ if (cost < minCost)
+ {
+ iMin = i;
+ jMin = j;
+ minCost = cost;
+ }
+ }
+ }
+
+ int32 index1 = nodes[iMin];
+ int32 index2 = nodes[jMin];
+ b2TreeNode* child1 = m_nodes + index1;
+ b2TreeNode* child2 = m_nodes + index2;
+
+ int32 parentIndex = AllocateNode();
+ b2TreeNode* parent = m_nodes + parentIndex;
+ parent->child1 = index1;
+ parent->child2 = index2;
+ parent->height = 1 + b2Max(child1->height, child2->height);
+ parent->aabb.Combine(child1->aabb, child2->aabb);
+ parent->parent = b2_nullNode;
+
+ child1->parent = parentIndex;
+ child2->parent = parentIndex;
+
+ nodes[jMin] = nodes[count-1];
+ nodes[iMin] = parentIndex;
+ --count;
+ }
+
+ m_root = nodes[0];
+ b2Free(nodes);
+
+ Validate();
+}
+
+void b2DynamicTree::ShiftOrigin(const b2Vec2& newOrigin)
+{
+ // Build array of leaves. Free the rest.
+ for (int32 i = 0; i < m_nodeCapacity; ++i)
+ {
+ m_nodes[i].aabb.lowerBound -= newOrigin;
+ m_nodes[i].aabb.upperBound -= newOrigin;
+ }
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_edge_shape.cpp b/Client/ThirdParty/Box2D/src/collision/b2_edge_shape.cpp
new file mode 100644
index 0000000..65f0606
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_edge_shape.cpp
@@ -0,0 +1,158 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_edge_shape.h"
+#include "box2d/b2_block_allocator.h"
+#include <new>
+
+void b2EdgeShape::SetOneSided(const b2Vec2& v0, const b2Vec2& v1, const b2Vec2& v2, const b2Vec2& v3)
+{
+ m_vertex0 = v0;
+ m_vertex1 = v1;
+ m_vertex2 = v2;
+ m_vertex3 = v3;
+ m_oneSided = true;
+}
+
+void b2EdgeShape::SetTwoSided(const b2Vec2& v1, const b2Vec2& v2)
+{
+ m_vertex1 = v1;
+ m_vertex2 = v2;
+ m_oneSided = false;
+}
+
+b2Shape* b2EdgeShape::Clone(b2BlockAllocator* allocator) const
+{
+ void* mem = allocator->Allocate(sizeof(b2EdgeShape));
+ b2EdgeShape* clone = new (mem) b2EdgeShape;
+ *clone = *this;
+ return clone;
+}
+
+int32 b2EdgeShape::GetChildCount() const
+{
+ return 1;
+}
+
+bool b2EdgeShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const
+{
+ B2_NOT_USED(xf);
+ B2_NOT_USED(p);
+ return false;
+}
+
+// p = p1 + t * d
+// v = v1 + s * e
+// p1 + t * d = v1 + s * e
+// s * e - t * d = p1 - v1
+bool b2EdgeShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& xf, int32 childIndex) const
+{
+ B2_NOT_USED(childIndex);
+
+ // Put the ray into the edge's frame of reference.
+ b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p);
+ b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p);
+ b2Vec2 d = p2 - p1;
+
+ b2Vec2 v1 = m_vertex1;
+ b2Vec2 v2 = m_vertex2;
+ b2Vec2 e = v2 - v1;
+
+ // Normal points to the right, looking from v1 at v2
+ b2Vec2 normal(e.y, -e.x);
+ normal.Normalize();
+
+ // q = p1 + t * d
+ // dot(normal, q - v1) = 0
+ // dot(normal, p1 - v1) + t * dot(normal, d) = 0
+ float numerator = b2Dot(normal, v1 - p1);
+ if (m_oneSided && numerator > 0.0f)
+ {
+ return false;
+ }
+
+ float denominator = b2Dot(normal, d);
+
+ if (denominator == 0.0f)
+ {
+ return false;
+ }
+
+ float t = numerator / denominator;
+ if (t < 0.0f || input.maxFraction < t)
+ {
+ return false;
+ }
+
+ b2Vec2 q = p1 + t * d;
+
+ // q = v1 + s * r
+ // s = dot(q - v1, r) / dot(r, r)
+ b2Vec2 r = v2 - v1;
+ float rr = b2Dot(r, r);
+ if (rr == 0.0f)
+ {
+ return false;
+ }
+
+ float s = b2Dot(q - v1, r) / rr;
+ if (s < 0.0f || 1.0f < s)
+ {
+ return false;
+ }
+
+ output->fraction = t;
+ if (numerator > 0.0f)
+ {
+ output->normal = -b2Mul(xf.q, normal);
+ }
+ else
+ {
+ output->normal = b2Mul(xf.q, normal);
+ }
+ return true;
+}
+
+void b2EdgeShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const
+{
+ B2_NOT_USED(childIndex);
+
+ b2Vec2 v1 = b2Mul(xf, m_vertex1);
+ b2Vec2 v2 = b2Mul(xf, m_vertex2);
+
+ b2Vec2 lower = b2Min(v1, v2);
+ b2Vec2 upper = b2Max(v1, v2);
+
+ b2Vec2 r(m_radius, m_radius);
+ aabb->lowerBound = lower - r;
+ aabb->upperBound = upper + r;
+}
+
+void b2EdgeShape::ComputeMass(b2MassData* massData, float density) const
+{
+ B2_NOT_USED(density);
+
+ massData->mass = 0.0f;
+ massData->center = 0.5f * (m_vertex1 + m_vertex2);
+ massData->I = 0.0f;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_polygon_shape.cpp b/Client/ThirdParty/Box2D/src/collision/b2_polygon_shape.cpp
new file mode 100644
index 0000000..368fb80
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_polygon_shape.cpp
@@ -0,0 +1,459 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_polygon_shape.h"
+#include "box2d/b2_block_allocator.h"
+
+#include <new>
+
+b2Shape* b2PolygonShape::Clone(b2BlockAllocator* allocator) const
+{
+ void* mem = allocator->Allocate(sizeof(b2PolygonShape));
+ b2PolygonShape* clone = new (mem) b2PolygonShape;
+ *clone = *this;
+ return clone;
+}
+
+void b2PolygonShape::SetAsBox(float hx, float hy)
+{
+ m_count = 4;
+ m_vertices[0].Set(-hx, -hy);
+ m_vertices[1].Set( hx, -hy);
+ m_vertices[2].Set( hx, hy);
+ m_vertices[3].Set(-hx, hy);
+ m_normals[0].Set(0.0f, -1.0f);
+ m_normals[1].Set(1.0f, 0.0f);
+ m_normals[2].Set(0.0f, 1.0f);
+ m_normals[3].Set(-1.0f, 0.0f);
+ m_centroid.SetZero();
+}
+
+void b2PolygonShape::SetAsBox(float hx, float hy, const b2Vec2& center, float angle)
+{
+ m_count = 4;
+ m_vertices[0].Set(-hx, -hy);
+ m_vertices[1].Set( hx, -hy);
+ m_vertices[2].Set( hx, hy);
+ m_vertices[3].Set(-hx, hy);
+ m_normals[0].Set(0.0f, -1.0f);
+ m_normals[1].Set(1.0f, 0.0f);
+ m_normals[2].Set(0.0f, 1.0f);
+ m_normals[3].Set(-1.0f, 0.0f);
+ m_centroid = center;
+
+ b2Transform xf;
+ xf.p = center;
+ xf.q.Set(angle);
+
+ // Transform vertices and normals.
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ m_vertices[i] = b2Mul(xf, m_vertices[i]);
+ m_normals[i] = b2Mul(xf.q, m_normals[i]);
+ }
+}
+
+int32 b2PolygonShape::GetChildCount() const
+{
+ return 1;
+}
+
+static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count)
+{
+ b2Assert(count >= 3);
+
+ b2Vec2 c(0.0f, 0.0f);
+ float area = 0.0f;
+
+ // Get a reference point for forming triangles.
+ // Use the first vertex to reduce round-off errors.
+ b2Vec2 s = vs[0];
+
+ const float inv3 = 1.0f / 3.0f;
+
+ for (int32 i = 0; i < count; ++i)
+ {
+ // Triangle vertices.
+ b2Vec2 p1 = vs[0] - s;
+ b2Vec2 p2 = vs[i] - s;
+ b2Vec2 p3 = i + 1 < count ? vs[i+1] - s : vs[0] - s;
+
+ b2Vec2 e1 = p2 - p1;
+ b2Vec2 e2 = p3 - p1;
+
+ float D = b2Cross(e1, e2);
+
+ float triangleArea = 0.5f * D;
+ area += triangleArea;
+
+ // Area weighted centroid
+ c += triangleArea * inv3 * (p1 + p2 + p3);
+ }
+
+ // Centroid
+ b2Assert(area > b2_epsilon);
+ c = (1.0f / area) * c + s;
+ return c;
+}
+
+void b2PolygonShape::Set(const b2Vec2* vertices, int32 count)
+{
+ b2Assert(3 <= count && count <= b2_maxPolygonVertices);
+ if (count < 3)
+ {
+ SetAsBox(1.0f, 1.0f);
+ return;
+ }
+
+ int32 n = b2Min(count, b2_maxPolygonVertices);
+
+ // Perform welding and copy vertices into local buffer.
+ b2Vec2 ps[b2_maxPolygonVertices];
+ int32 tempCount = 0;
+ for (int32 i = 0; i < n; ++i)
+ {
+ b2Vec2 v = vertices[i];
+
+ bool unique = true;
+ for (int32 j = 0; j < tempCount; ++j)
+ {
+ if (b2DistanceSquared(v, ps[j]) < ((0.5f * b2_linearSlop) * (0.5f * b2_linearSlop)))
+ {
+ unique = false;
+ break;
+ }
+ }
+
+ if (unique)
+ {
+ ps[tempCount++] = v;
+ }
+ }
+
+ n = tempCount;
+ if (n < 3)
+ {
+ // Polygon is degenerate.
+ b2Assert(false);
+ SetAsBox(1.0f, 1.0f);
+ return;
+ }
+
+ // Create the convex hull using the Gift wrapping algorithm
+ // http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
+
+ // Find the right most point on the hull
+ int32 i0 = 0;
+ float x0 = ps[0].x;
+ for (int32 i = 1; i < n; ++i)
+ {
+ float x = ps[i].x;
+ if (x > x0 || (x == x0 && ps[i].y < ps[i0].y))
+ {
+ i0 = i;
+ x0 = x;
+ }
+ }
+
+ int32 hull[b2_maxPolygonVertices];
+ int32 m = 0;
+ int32 ih = i0;
+
+ for (;;)
+ {
+ b2Assert(m < b2_maxPolygonVertices);
+ hull[m] = ih;
+
+ int32 ie = 0;
+ for (int32 j = 1; j < n; ++j)
+ {
+ if (ie == ih)
+ {
+ ie = j;
+ continue;
+ }
+
+ b2Vec2 r = ps[ie] - ps[hull[m]];
+ b2Vec2 v = ps[j] - ps[hull[m]];
+ float c = b2Cross(r, v);
+ if (c < 0.0f)
+ {
+ ie = j;
+ }
+
+ // Collinearity check
+ if (c == 0.0f && v.LengthSquared() > r.LengthSquared())
+ {
+ ie = j;
+ }
+ }
+
+ ++m;
+ ih = ie;
+
+ if (ie == i0)
+ {
+ break;
+ }
+ }
+
+ if (m < 3)
+ {
+ // Polygon is degenerate.
+ b2Assert(false);
+ SetAsBox(1.0f, 1.0f);
+ return;
+ }
+
+ m_count = m;
+
+ // Copy vertices.
+ for (int32 i = 0; i < m; ++i)
+ {
+ m_vertices[i] = ps[hull[i]];
+ }
+
+ // Compute normals. Ensure the edges have non-zero length.
+ for (int32 i = 0; i < m; ++i)
+ {
+ int32 i1 = i;
+ int32 i2 = i + 1 < m ? i + 1 : 0;
+ b2Vec2 edge = m_vertices[i2] - m_vertices[i1];
+ b2Assert(edge.LengthSquared() > b2_epsilon * b2_epsilon);
+ m_normals[i] = b2Cross(edge, 1.0f);
+ m_normals[i].Normalize();
+ }
+
+ // Compute the polygon centroid.
+ m_centroid = ComputeCentroid(m_vertices, m);
+}
+
+bool b2PolygonShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const
+{
+ b2Vec2 pLocal = b2MulT(xf.q, p - xf.p);
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ float dot = b2Dot(m_normals[i], pLocal - m_vertices[i]);
+ if (dot > 0.0f)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool b2PolygonShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input,
+ const b2Transform& xf, int32 childIndex) const
+{
+ B2_NOT_USED(childIndex);
+
+ // Put the ray into the polygon's frame of reference.
+ b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p);
+ b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p);
+ b2Vec2 d = p2 - p1;
+
+ float lower = 0.0f, upper = input.maxFraction;
+
+ int32 index = -1;
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ // p = p1 + a * d
+ // dot(normal, p - v) = 0
+ // dot(normal, p1 - v) + a * dot(normal, d) = 0
+ float numerator = b2Dot(m_normals[i], m_vertices[i] - p1);
+ float denominator = b2Dot(m_normals[i], d);
+
+ if (denominator == 0.0f)
+ {
+ if (numerator < 0.0f)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Note: we want this predicate without division:
+ // lower < numerator / denominator, where denominator < 0
+ // Since denominator < 0, we have to flip the inequality:
+ // lower < numerator / denominator <==> denominator * lower > numerator.
+ if (denominator < 0.0f && numerator < lower * denominator)
+ {
+ // Increase lower.
+ // The segment enters this half-space.
+ lower = numerator / denominator;
+ index = i;
+ }
+ else if (denominator > 0.0f && numerator < upper * denominator)
+ {
+ // Decrease upper.
+ // The segment exits this half-space.
+ upper = numerator / denominator;
+ }
+ }
+
+ // The use of epsilon here causes the assert on lower to trip
+ // in some cases. Apparently the use of epsilon was to make edge
+ // shapes work, but now those are handled separately.
+ //if (upper < lower - b2_epsilon)
+ if (upper < lower)
+ {
+ return false;
+ }
+ }
+
+ b2Assert(0.0f <= lower && lower <= input.maxFraction);
+
+ if (index >= 0)
+ {
+ output->fraction = lower;
+ output->normal = b2Mul(xf.q, m_normals[index]);
+ return true;
+ }
+
+ return false;
+}
+
+void b2PolygonShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const
+{
+ B2_NOT_USED(childIndex);
+
+ b2Vec2 lower = b2Mul(xf, m_vertices[0]);
+ b2Vec2 upper = lower;
+
+ for (int32 i = 1; i < m_count; ++i)
+ {
+ b2Vec2 v = b2Mul(xf, m_vertices[i]);
+ lower = b2Min(lower, v);
+ upper = b2Max(upper, v);
+ }
+
+ b2Vec2 r(m_radius, m_radius);
+ aabb->lowerBound = lower - r;
+ aabb->upperBound = upper + r;
+}
+
+void b2PolygonShape::ComputeMass(b2MassData* massData, float density) const
+{
+ // Polygon mass, centroid, and inertia.
+ // Let rho be the polygon density in mass per unit area.
+ // Then:
+ // mass = rho * int(dA)
+ // centroid.x = (1/mass) * rho * int(x * dA)
+ // centroid.y = (1/mass) * rho * int(y * dA)
+ // I = rho * int((x*x + y*y) * dA)
+ //
+ // We can compute these integrals by summing all the integrals
+ // for each triangle of the polygon. To evaluate the integral
+ // for a single triangle, we make a change of variables to
+ // the (u,v) coordinates of the triangle:
+ // x = x0 + e1x * u + e2x * v
+ // y = y0 + e1y * u + e2y * v
+ // where 0 <= u && 0 <= v && u + v <= 1.
+ //
+ // We integrate u from [0,1-v] and then v from [0,1].
+ // We also need to use the Jacobian of the transformation:
+ // D = cross(e1, e2)
+ //
+ // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
+ //
+ // The rest of the derivation is handled by computer algebra.
+
+ b2Assert(m_count >= 3);
+
+ b2Vec2 center(0.0f, 0.0f);
+ float area = 0.0f;
+ float I = 0.0f;
+
+ // Get a reference point for forming triangles.
+ // Use the first vertex to reduce round-off errors.
+ b2Vec2 s = m_vertices[0];
+
+ const float k_inv3 = 1.0f / 3.0f;
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ // Triangle vertices.
+ b2Vec2 e1 = m_vertices[i] - s;
+ b2Vec2 e2 = i + 1 < m_count ? m_vertices[i+1] - s : m_vertices[0] - s;
+
+ float D = b2Cross(e1, e2);
+
+ float triangleArea = 0.5f * D;
+ area += triangleArea;
+
+ // Area weighted centroid
+ center += triangleArea * k_inv3 * (e1 + e2);
+
+ float ex1 = e1.x, ey1 = e1.y;
+ float ex2 = e2.x, ey2 = e2.y;
+
+ float intx2 = ex1*ex1 + ex2*ex1 + ex2*ex2;
+ float inty2 = ey1*ey1 + ey2*ey1 + ey2*ey2;
+
+ I += (0.25f * k_inv3 * D) * (intx2 + inty2);
+ }
+
+ // Total mass
+ massData->mass = density * area;
+
+ // Center of mass
+ b2Assert(area > b2_epsilon);
+ center *= 1.0f / area;
+ massData->center = center + s;
+
+ // Inertia tensor relative to the local origin (point s).
+ massData->I = density * I;
+
+ // Shift to center of mass then to original body origin.
+ massData->I += massData->mass * (b2Dot(massData->center, massData->center) - b2Dot(center, center));
+}
+
+bool b2PolygonShape::Validate() const
+{
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ int32 i1 = i;
+ int32 i2 = i < m_count - 1 ? i1 + 1 : 0;
+ b2Vec2 p = m_vertices[i1];
+ b2Vec2 e = m_vertices[i2] - p;
+
+ for (int32 j = 0; j < m_count; ++j)
+ {
+ if (j == i1 || j == i2)
+ {
+ continue;
+ }
+
+ b2Vec2 v = m_vertices[j] - p;
+ float c = b2Cross(e, v);
+ if (c < 0.0f)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/Client/ThirdParty/Box2D/src/collision/b2_time_of_impact.cpp b/Client/ThirdParty/Box2D/src/collision/b2_time_of_impact.cpp
new file mode 100644
index 0000000..7a1011b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/collision/b2_time_of_impact.cpp
@@ -0,0 +1,490 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_collision.h"
+#include "box2d/b2_distance.h"
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_polygon_shape.h"
+#include "box2d/b2_time_of_impact.h"
+#include "box2d/b2_timer.h"
+
+#include <stdio.h>
+
+B2_API float b2_toiTime, b2_toiMaxTime;
+B2_API int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters;
+B2_API int32 b2_toiRootIters, b2_toiMaxRootIters;
+
+//
+struct b2SeparationFunction
+{
+ enum Type
+ {
+ e_points,
+ e_faceA,
+ e_faceB
+ };
+
+ // TODO_ERIN might not need to return the separation
+
+ float Initialize(const b2SimplexCache* cache,
+ const b2DistanceProxy* proxyA, const b2Sweep& sweepA,
+ const b2DistanceProxy* proxyB, const b2Sweep& sweepB,
+ float t1)
+ {
+ m_proxyA = proxyA;
+ m_proxyB = proxyB;
+ int32 count = cache->count;
+ b2Assert(0 < count && count < 3);
+
+ m_sweepA = sweepA;
+ m_sweepB = sweepB;
+
+ b2Transform xfA, xfB;
+ m_sweepA.GetTransform(&xfA, t1);
+ m_sweepB.GetTransform(&xfB, t1);
+
+ if (count == 1)
+ {
+ m_type = e_points;
+ b2Vec2 localPointA = m_proxyA->GetVertex(cache->indexA[0]);
+ b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]);
+ b2Vec2 pointA = b2Mul(xfA, localPointA);
+ b2Vec2 pointB = b2Mul(xfB, localPointB);
+ m_axis = pointB - pointA;
+ float s = m_axis.Normalize();
+ return s;
+ }
+ else if (cache->indexA[0] == cache->indexA[1])
+ {
+ // Two points on B and one on A.
+ m_type = e_faceB;
+ b2Vec2 localPointB1 = proxyB->GetVertex(cache->indexB[0]);
+ b2Vec2 localPointB2 = proxyB->GetVertex(cache->indexB[1]);
+
+ m_axis = b2Cross(localPointB2 - localPointB1, 1.0f);
+ m_axis.Normalize();
+ b2Vec2 normal = b2Mul(xfB.q, m_axis);
+
+ m_localPoint = 0.5f * (localPointB1 + localPointB2);
+ b2Vec2 pointB = b2Mul(xfB, m_localPoint);
+
+ b2Vec2 localPointA = proxyA->GetVertex(cache->indexA[0]);
+ b2Vec2 pointA = b2Mul(xfA, localPointA);
+
+ float s = b2Dot(pointA - pointB, normal);
+ if (s < 0.0f)
+ {
+ m_axis = -m_axis;
+ s = -s;
+ }
+ return s;
+ }
+ else
+ {
+ // Two points on A and one or two points on B.
+ m_type = e_faceA;
+ b2Vec2 localPointA1 = m_proxyA->GetVertex(cache->indexA[0]);
+ b2Vec2 localPointA2 = m_proxyA->GetVertex(cache->indexA[1]);
+
+ m_axis = b2Cross(localPointA2 - localPointA1, 1.0f);
+ m_axis.Normalize();
+ b2Vec2 normal = b2Mul(xfA.q, m_axis);
+
+ m_localPoint = 0.5f * (localPointA1 + localPointA2);
+ b2Vec2 pointA = b2Mul(xfA, m_localPoint);
+
+ b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]);
+ b2Vec2 pointB = b2Mul(xfB, localPointB);
+
+ float s = b2Dot(pointB - pointA, normal);
+ if (s < 0.0f)
+ {
+ m_axis = -m_axis;
+ s = -s;
+ }
+ return s;
+ }
+ }
+
+ //
+ float FindMinSeparation(int32* indexA, int32* indexB, float t) const
+ {
+ b2Transform xfA, xfB;
+ m_sweepA.GetTransform(&xfA, t);
+ m_sweepB.GetTransform(&xfB, t);
+
+ switch (m_type)
+ {
+ case e_points:
+ {
+ b2Vec2 axisA = b2MulT(xfA.q, m_axis);
+ b2Vec2 axisB = b2MulT(xfB.q, -m_axis);
+
+ *indexA = m_proxyA->GetSupport(axisA);
+ *indexB = m_proxyB->GetSupport(axisB);
+
+ b2Vec2 localPointA = m_proxyA->GetVertex(*indexA);
+ b2Vec2 localPointB = m_proxyB->GetVertex(*indexB);
+
+ b2Vec2 pointA = b2Mul(xfA, localPointA);
+ b2Vec2 pointB = b2Mul(xfB, localPointB);
+
+ float separation = b2Dot(pointB - pointA, m_axis);
+ return separation;
+ }
+
+ case e_faceA:
+ {
+ b2Vec2 normal = b2Mul(xfA.q, m_axis);
+ b2Vec2 pointA = b2Mul(xfA, m_localPoint);
+
+ b2Vec2 axisB = b2MulT(xfB.q, -normal);
+
+ *indexA = -1;
+ *indexB = m_proxyB->GetSupport(axisB);
+
+ b2Vec2 localPointB = m_proxyB->GetVertex(*indexB);
+ b2Vec2 pointB = b2Mul(xfB, localPointB);
+
+ float separation = b2Dot(pointB - pointA, normal);
+ return separation;
+ }
+
+ case e_faceB:
+ {
+ b2Vec2 normal = b2Mul(xfB.q, m_axis);
+ b2Vec2 pointB = b2Mul(xfB, m_localPoint);
+
+ b2Vec2 axisA = b2MulT(xfA.q, -normal);
+
+ *indexB = -1;
+ *indexA = m_proxyA->GetSupport(axisA);
+
+ b2Vec2 localPointA = m_proxyA->GetVertex(*indexA);
+ b2Vec2 pointA = b2Mul(xfA, localPointA);
+
+ float separation = b2Dot(pointA - pointB, normal);
+ return separation;
+ }
+
+ default:
+ b2Assert(false);
+ *indexA = -1;
+ *indexB = -1;
+ return 0.0f;
+ }
+ }
+
+ //
+ float Evaluate(int32 indexA, int32 indexB, float t) const
+ {
+ b2Transform xfA, xfB;
+ m_sweepA.GetTransform(&xfA, t);
+ m_sweepB.GetTransform(&xfB, t);
+
+ switch (m_type)
+ {
+ case e_points:
+ {
+ b2Vec2 localPointA = m_proxyA->GetVertex(indexA);
+ b2Vec2 localPointB = m_proxyB->GetVertex(indexB);
+
+ b2Vec2 pointA = b2Mul(xfA, localPointA);
+ b2Vec2 pointB = b2Mul(xfB, localPointB);
+ float separation = b2Dot(pointB - pointA, m_axis);
+
+ return separation;
+ }
+
+ case e_faceA:
+ {
+ b2Vec2 normal = b2Mul(xfA.q, m_axis);
+ b2Vec2 pointA = b2Mul(xfA, m_localPoint);
+
+ b2Vec2 localPointB = m_proxyB->GetVertex(indexB);
+ b2Vec2 pointB = b2Mul(xfB, localPointB);
+
+ float separation = b2Dot(pointB - pointA, normal);
+ return separation;
+ }
+
+ case e_faceB:
+ {
+ b2Vec2 normal = b2Mul(xfB.q, m_axis);
+ b2Vec2 pointB = b2Mul(xfB, m_localPoint);
+
+ b2Vec2 localPointA = m_proxyA->GetVertex(indexA);
+ b2Vec2 pointA = b2Mul(xfA, localPointA);
+
+ float separation = b2Dot(pointA - pointB, normal);
+ return separation;
+ }
+
+ default:
+ b2Assert(false);
+ return 0.0f;
+ }
+ }
+
+ const b2DistanceProxy* m_proxyA;
+ const b2DistanceProxy* m_proxyB;
+ b2Sweep m_sweepA, m_sweepB;
+ Type m_type;
+ b2Vec2 m_localPoint;
+ b2Vec2 m_axis;
+};
+
+// CCD via the local separating axis method. This seeks progression
+// by computing the largest time at which separation is maintained.
+void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input)
+{
+ b2Timer timer;
+
+ ++b2_toiCalls;
+
+ output->state = b2TOIOutput::e_unknown;
+ output->t = input->tMax;
+
+ const b2DistanceProxy* proxyA = &input->proxyA;
+ const b2DistanceProxy* proxyB = &input->proxyB;
+
+ b2Sweep sweepA = input->sweepA;
+ b2Sweep sweepB = input->sweepB;
+
+ // Large rotations can make the root finder fail, so we normalize the
+ // sweep angles.
+ sweepA.Normalize();
+ sweepB.Normalize();
+
+ float tMax = input->tMax;
+
+ float totalRadius = proxyA->m_radius + proxyB->m_radius;
+ float target = b2Max(b2_linearSlop, totalRadius - 3.0f * b2_linearSlop);
+ float tolerance = 0.25f * b2_linearSlop;
+ b2Assert(target > tolerance);
+
+ float t1 = 0.0f;
+ const int32 k_maxIterations = 20; // TODO_ERIN b2Settings
+ int32 iter = 0;
+
+ // Prepare input for distance query.
+ b2SimplexCache cache;
+ cache.count = 0;
+ b2DistanceInput distanceInput;
+ distanceInput.proxyA = input->proxyA;
+ distanceInput.proxyB = input->proxyB;
+ distanceInput.useRadii = false;
+
+ // The outer loop progressively attempts to compute new separating axes.
+ // This loop terminates when an axis is repeated (no progress is made).
+ for(;;)
+ {
+ b2Transform xfA, xfB;
+ sweepA.GetTransform(&xfA, t1);
+ sweepB.GetTransform(&xfB, t1);
+
+ // Get the distance between shapes. We can also use the results
+ // to get a separating axis.
+ distanceInput.transformA = xfA;
+ distanceInput.transformB = xfB;
+ b2DistanceOutput distanceOutput;
+ b2Distance(&distanceOutput, &cache, &distanceInput);
+
+ // If the shapes are overlapped, we give up on continuous collision.
+ if (distanceOutput.distance <= 0.0f)
+ {
+ // Failure!
+ output->state = b2TOIOutput::e_overlapped;
+ output->t = 0.0f;
+ break;
+ }
+
+ if (distanceOutput.distance < target + tolerance)
+ {
+ // Victory!
+ output->state = b2TOIOutput::e_touching;
+ output->t = t1;
+ break;
+ }
+
+ // Initialize the separating axis.
+ b2SeparationFunction fcn;
+ fcn.Initialize(&cache, proxyA, sweepA, proxyB, sweepB, t1);
+#if 0
+ // Dump the curve seen by the root finder
+ {
+ const int32 N = 100;
+ float dx = 1.0f / N;
+ float xs[N+1];
+ float fs[N+1];
+
+ float x = 0.0f;
+
+ for (int32 i = 0; i <= N; ++i)
+ {
+ sweepA.GetTransform(&xfA, x);
+ sweepB.GetTransform(&xfB, x);
+ float f = fcn.Evaluate(xfA, xfB) - target;
+
+ printf("%g %g\n", x, f);
+
+ xs[i] = x;
+ fs[i] = f;
+
+ x += dx;
+ }
+ }
+#endif
+
+ // Compute the TOI on the separating axis. We do this by successively
+ // resolving the deepest point. This loop is bounded by the number of vertices.
+ bool done = false;
+ float t2 = tMax;
+ int32 pushBackIter = 0;
+ for (;;)
+ {
+ // Find the deepest point at t2. Store the witness point indices.
+ int32 indexA, indexB;
+ float s2 = fcn.FindMinSeparation(&indexA, &indexB, t2);
+
+ // Is the final configuration separated?
+ if (s2 > target + tolerance)
+ {
+ // Victory!
+ output->state = b2TOIOutput::e_separated;
+ output->t = tMax;
+ done = true;
+ break;
+ }
+
+ // Has the separation reached tolerance?
+ if (s2 > target - tolerance)
+ {
+ // Advance the sweeps
+ t1 = t2;
+ break;
+ }
+
+ // Compute the initial separation of the witness points.
+ float s1 = fcn.Evaluate(indexA, indexB, t1);
+
+ // Check for initial overlap. This might happen if the root finder
+ // runs out of iterations.
+ if (s1 < target - tolerance)
+ {
+ output->state = b2TOIOutput::e_failed;
+ output->t = t1;
+ done = true;
+ break;
+ }
+
+ // Check for touching
+ if (s1 <= target + tolerance)
+ {
+ // Victory! t1 should hold the TOI (could be 0.0).
+ output->state = b2TOIOutput::e_touching;
+ output->t = t1;
+ done = true;
+ break;
+ }
+
+ // Compute 1D root of: f(x) - target = 0
+ int32 rootIterCount = 0;
+ float a1 = t1, a2 = t2;
+ for (;;)
+ {
+ // Use a mix of the secant rule and bisection.
+ float t;
+ if (rootIterCount & 1)
+ {
+ // Secant rule to improve convergence.
+ t = a1 + (target - s1) * (a2 - a1) / (s2 - s1);
+ }
+ else
+ {
+ // Bisection to guarantee progress.
+ t = 0.5f * (a1 + a2);
+ }
+
+ ++rootIterCount;
+ ++b2_toiRootIters;
+
+ float s = fcn.Evaluate(indexA, indexB, t);
+
+ if (b2Abs(s - target) < tolerance)
+ {
+ // t2 holds a tentative value for t1
+ t2 = t;
+ break;
+ }
+
+ // Ensure we continue to bracket the root.
+ if (s > target)
+ {
+ a1 = t;
+ s1 = s;
+ }
+ else
+ {
+ a2 = t;
+ s2 = s;
+ }
+
+ if (rootIterCount == 50)
+ {
+ break;
+ }
+ }
+
+ b2_toiMaxRootIters = b2Max(b2_toiMaxRootIters, rootIterCount);
+
+ ++pushBackIter;
+
+ if (pushBackIter == b2_maxPolygonVertices)
+ {
+ break;
+ }
+ }
+
+ ++iter;
+ ++b2_toiIters;
+
+ if (done)
+ {
+ break;
+ }
+
+ if (iter == k_maxIterations)
+ {
+ // Root finder got stuck. Semi-victory.
+ output->state = b2TOIOutput::e_failed;
+ output->t = t1;
+ break;
+ }
+ }
+
+ b2_toiMaxIters = b2Max(b2_toiMaxIters, iter);
+
+ float time = timer.GetMilliseconds();
+ b2_toiMaxTime = b2Max(b2_toiMaxTime, time);
+ b2_toiTime += time;
+}
diff --git a/Client/ThirdParty/Box2D/src/common/b2_block_allocator.cpp b/Client/ThirdParty/Box2D/src/common/b2_block_allocator.cpp
new file mode 100644
index 0000000..595f2ad
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/common/b2_block_allocator.cpp
@@ -0,0 +1,230 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_block_allocator.h"
+#include <limits.h>
+#include <string.h>
+#include <stddef.h>
+
+static const int32 b2_chunkSize = 16 * 1024;
+static const int32 b2_maxBlockSize = 640;
+static const int32 b2_chunkArrayIncrement = 128;
+
+// These are the supported object sizes. Actual allocations are rounded up the next size.
+static const int32 b2_blockSizes[b2_blockSizeCount] =
+{
+ 16, // 0
+ 32, // 1
+ 64, // 2
+ 96, // 3
+ 128, // 4
+ 160, // 5
+ 192, // 6
+ 224, // 7
+ 256, // 8
+ 320, // 9
+ 384, // 10
+ 448, // 11
+ 512, // 12
+ 640, // 13
+};
+
+// This maps an arbitrary allocation size to a suitable slot in b2_blockSizes.
+struct b2SizeMap
+{
+ b2SizeMap()
+ {
+ int32 j = 0;
+ values[0] = 0;
+ for (int32 i = 1; i <= b2_maxBlockSize; ++i)
+ {
+ b2Assert(j < b2_blockSizeCount);
+ if (i <= b2_blockSizes[j])
+ {
+ values[i] = (uint8)j;
+ }
+ else
+ {
+ ++j;
+ values[i] = (uint8)j;
+ }
+ }
+ }
+
+ uint8 values[b2_maxBlockSize + 1];
+};
+
+static const b2SizeMap b2_sizeMap;
+
+struct b2Chunk
+{
+ int32 blockSize;
+ b2Block* blocks;
+};
+
+struct b2Block
+{
+ b2Block* next;
+};
+
+b2BlockAllocator::b2BlockAllocator()
+{
+ b2Assert(b2_blockSizeCount < UCHAR_MAX);
+
+ m_chunkSpace = b2_chunkArrayIncrement;
+ m_chunkCount = 0;
+ m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
+
+ memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
+ memset(m_freeLists, 0, sizeof(m_freeLists));
+}
+
+b2BlockAllocator::~b2BlockAllocator()
+{
+ for (int32 i = 0; i < m_chunkCount; ++i)
+ {
+ b2Free(m_chunks[i].blocks);
+ }
+
+ b2Free(m_chunks);
+}
+
+void* b2BlockAllocator::Allocate(int32 size)
+{
+ if (size == 0)
+ {
+ return nullptr;
+ }
+
+ b2Assert(0 < size);
+
+ if (size > b2_maxBlockSize)
+ {
+ return b2Alloc(size);
+ }
+
+ int32 index = b2_sizeMap.values[size];
+ b2Assert(0 <= index && index < b2_blockSizeCount);
+
+ if (m_freeLists[index])
+ {
+ b2Block* block = m_freeLists[index];
+ m_freeLists[index] = block->next;
+ return block;
+ }
+ else
+ {
+ if (m_chunkCount == m_chunkSpace)
+ {
+ b2Chunk* oldChunks = m_chunks;
+ m_chunkSpace += b2_chunkArrayIncrement;
+ m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
+ memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk));
+ memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk));
+ b2Free(oldChunks);
+ }
+
+ b2Chunk* chunk = m_chunks + m_chunkCount;
+ chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize);
+#if defined(_DEBUG)
+ memset(chunk->blocks, 0xcd, b2_chunkSize);
+#endif
+ int32 blockSize = b2_blockSizes[index];
+ chunk->blockSize = blockSize;
+ int32 blockCount = b2_chunkSize / blockSize;
+ b2Assert(blockCount * blockSize <= b2_chunkSize);
+ for (int32 i = 0; i < blockCount - 1; ++i)
+ {
+ b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i);
+ b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1));
+ block->next = next;
+ }
+ b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1));
+ last->next = nullptr;
+
+ m_freeLists[index] = chunk->blocks->next;
+ ++m_chunkCount;
+
+ return chunk->blocks;
+ }
+}
+
+void b2BlockAllocator::Free(void* p, int32 size)
+{
+ if (size == 0)
+ {
+ return;
+ }
+
+ b2Assert(0 < size);
+
+ if (size > b2_maxBlockSize)
+ {
+ b2Free(p);
+ return;
+ }
+
+ int32 index = b2_sizeMap.values[size];
+ b2Assert(0 <= index && index < b2_blockSizeCount);
+
+#if defined(_DEBUG)
+ // Verify the memory address and size is valid.
+ int32 blockSize = b2_blockSizes[index];
+ bool found = false;
+ for (int32 i = 0; i < m_chunkCount; ++i)
+ {
+ b2Chunk* chunk = m_chunks + i;
+ if (chunk->blockSize != blockSize)
+ {
+ b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks ||
+ (int8*)chunk->blocks + b2_chunkSize <= (int8*)p);
+ }
+ else
+ {
+ if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize)
+ {
+ found = true;
+ }
+ }
+ }
+
+ b2Assert(found);
+
+ memset(p, 0xfd, blockSize);
+#endif
+
+ b2Block* block = (b2Block*)p;
+ block->next = m_freeLists[index];
+ m_freeLists[index] = block;
+}
+
+void b2BlockAllocator::Clear()
+{
+ for (int32 i = 0; i < m_chunkCount; ++i)
+ {
+ b2Free(m_chunks[i].blocks);
+ }
+
+ m_chunkCount = 0;
+ memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
+ memset(m_freeLists, 0, sizeof(m_freeLists));
+}
diff --git a/Client/ThirdParty/Box2D/src/common/b2_draw.cpp b/Client/ThirdParty/Box2D/src/common/b2_draw.cpp
new file mode 100644
index 0000000..1ec11e5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/common/b2_draw.cpp
@@ -0,0 +1,47 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+#include "box2d/b2_draw.h"
+
+b2Draw::b2Draw()
+{
+ m_drawFlags = 0;
+}
+
+void b2Draw::SetFlags(uint32 flags)
+{
+ m_drawFlags = flags;
+}
+
+uint32 b2Draw::GetFlags() const
+{
+ return m_drawFlags;
+}
+
+void b2Draw::AppendFlags(uint32 flags)
+{
+ m_drawFlags |= flags;
+}
+
+void b2Draw::ClearFlags(uint32 flags)
+{
+ m_drawFlags &= ~flags;
+}
diff --git a/Client/ThirdParty/Box2D/src/common/b2_math.cpp b/Client/ThirdParty/Box2D/src/common/b2_math.cpp
new file mode 100644
index 0000000..a14460c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/common/b2_math.cpp
@@ -0,0 +1,98 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_math.h"
+
+const b2Vec2 b2Vec2_zero(0.0f, 0.0f);
+
+/// Solve A * x = b, where b is a column vector. This is more efficient
+/// than computing the inverse in one-shot cases.
+b2Vec3 b2Mat33::Solve33(const b2Vec3& b) const
+{
+ float det = b2Dot(ex, b2Cross(ey, ez));
+ if (det != 0.0f)
+ {
+ det = 1.0f / det;
+ }
+ b2Vec3 x;
+ x.x = det * b2Dot(b, b2Cross(ey, ez));
+ x.y = det * b2Dot(ex, b2Cross(b, ez));
+ x.z = det * b2Dot(ex, b2Cross(ey, b));
+ return x;
+}
+
+/// Solve A * x = b, where b is a column vector. This is more efficient
+/// than computing the inverse in one-shot cases.
+b2Vec2 b2Mat33::Solve22(const b2Vec2& b) const
+{
+ float a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y;
+ float det = a11 * a22 - a12 * a21;
+ if (det != 0.0f)
+ {
+ det = 1.0f / det;
+ }
+ b2Vec2 x;
+ x.x = det * (a22 * b.x - a12 * b.y);
+ x.y = det * (a11 * b.y - a21 * b.x);
+ return x;
+}
+
+///
+void b2Mat33::GetInverse22(b2Mat33* M) const
+{
+ float a = ex.x, b = ey.x, c = ex.y, d = ey.y;
+ float det = a * d - b * c;
+ if (det != 0.0f)
+ {
+ det = 1.0f / det;
+ }
+
+ M->ex.x = det * d; M->ey.x = -det * b; M->ex.z = 0.0f;
+ M->ex.y = -det * c; M->ey.y = det * a; M->ey.z = 0.0f;
+ M->ez.x = 0.0f; M->ez.y = 0.0f; M->ez.z = 0.0f;
+}
+
+/// Returns the zero matrix if singular.
+void b2Mat33::GetSymInverse33(b2Mat33* M) const
+{
+ float det = b2Dot(ex, b2Cross(ey, ez));
+ if (det != 0.0f)
+ {
+ det = 1.0f / det;
+ }
+
+ float a11 = ex.x, a12 = ey.x, a13 = ez.x;
+ float a22 = ey.y, a23 = ez.y;
+ float a33 = ez.z;
+
+ M->ex.x = det * (a22 * a33 - a23 * a23);
+ M->ex.y = det * (a13 * a23 - a12 * a33);
+ M->ex.z = det * (a12 * a23 - a13 * a22);
+
+ M->ey.x = M->ex.y;
+ M->ey.y = det * (a11 * a33 - a13 * a13);
+ M->ey.z = det * (a13 * a12 - a11 * a23);
+
+ M->ez.x = M->ex.z;
+ M->ez.y = M->ey.z;
+ M->ez.z = det * (a11 * a22 - a12 * a12);
+}
diff --git a/Client/ThirdParty/Box2D/src/common/b2_settings.cpp b/Client/ThirdParty/Box2D/src/common/b2_settings.cpp
new file mode 100644
index 0000000..9b66769
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/common/b2_settings.cpp
@@ -0,0 +1,74 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#define _CRT_SECURE_NO_WARNINGS
+
+#include "box2d/b2_settings.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+b2Version b2_version = {2, 4, 0};
+
+// Memory allocators. Modify these to use your own allocator.
+void* b2Alloc_Default(int32 size)
+{
+ return malloc(size);
+}
+
+void b2Free_Default(void* mem)
+{
+ free(mem);
+}
+
+// You can modify this to use your logging facility.
+void b2Log_Default(const char* string, va_list args)
+{
+ vprintf(string, args);
+}
+
+FILE* b2_dumpFile = nullptr;
+
+void b2OpenDump(const char* fileName)
+{
+ b2Assert(b2_dumpFile == nullptr);
+ b2_dumpFile = fopen(fileName, "w");
+}
+
+void b2Dump(const char* string, ...)
+{
+ if (b2_dumpFile == nullptr)
+ {
+ return;
+ }
+
+ va_list args;
+ va_start(args, string);
+ vfprintf(b2_dumpFile, string, args);
+ va_end(args);
+}
+
+void b2CloseDump()
+{
+ fclose(b2_dumpFile);
+ b2_dumpFile = nullptr;
+}
diff --git a/Client/ThirdParty/Box2D/src/common/b2_stack_allocator.cpp b/Client/ThirdParty/Box2D/src/common/b2_stack_allocator.cpp
new file mode 100644
index 0000000..602db1a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/common/b2_stack_allocator.cpp
@@ -0,0 +1,87 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_stack_allocator.h"
+#include "box2d/b2_math.h"
+
+b2StackAllocator::b2StackAllocator()
+{
+ m_index = 0;
+ m_allocation = 0;
+ m_maxAllocation = 0;
+ m_entryCount = 0;
+}
+
+b2StackAllocator::~b2StackAllocator()
+{
+ b2Assert(m_index == 0);
+ b2Assert(m_entryCount == 0);
+}
+
+void* b2StackAllocator::Allocate(int32 size)
+{
+ b2Assert(m_entryCount < b2_maxStackEntries);
+
+ b2StackEntry* entry = m_entries + m_entryCount;
+ entry->size = size;
+ if (m_index + size > b2_stackSize)
+ {
+ entry->data = (char*)b2Alloc(size);
+ entry->usedMalloc = true;
+ }
+ else
+ {
+ entry->data = m_data + m_index;
+ entry->usedMalloc = false;
+ m_index += size;
+ }
+
+ m_allocation += size;
+ m_maxAllocation = b2Max(m_maxAllocation, m_allocation);
+ ++m_entryCount;
+
+ return entry->data;
+}
+
+void b2StackAllocator::Free(void* p)
+{
+ b2Assert(m_entryCount > 0);
+ b2StackEntry* entry = m_entries + m_entryCount - 1;
+ b2Assert(p == entry->data);
+ if (entry->usedMalloc)
+ {
+ b2Free(p);
+ }
+ else
+ {
+ m_index -= entry->size;
+ }
+ m_allocation -= entry->size;
+ --m_entryCount;
+
+ p = nullptr;
+}
+
+int32 b2StackAllocator::GetMaxAllocation() const
+{
+ return m_maxAllocation;
+}
diff --git a/Client/ThirdParty/Box2D/src/common/b2_timer.cpp b/Client/ThirdParty/Box2D/src/common/b2_timer.cpp
new file mode 100644
index 0000000..dd7cde7
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/common/b2_timer.cpp
@@ -0,0 +1,125 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_timer.h"
+
+#if defined(_WIN32)
+
+double b2Timer::s_invFrequency = 0.0;
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+b2Timer::b2Timer()
+{
+ LARGE_INTEGER largeInteger;
+
+ if (s_invFrequency == 0.0)
+ {
+ QueryPerformanceFrequency(&largeInteger);
+ s_invFrequency = double(largeInteger.QuadPart);
+ if (s_invFrequency > 0.0)
+ {
+ s_invFrequency = 1000.0 / s_invFrequency;
+ }
+ }
+
+ QueryPerformanceCounter(&largeInteger);
+ m_start = double(largeInteger.QuadPart);
+}
+
+void b2Timer::Reset()
+{
+ LARGE_INTEGER largeInteger;
+ QueryPerformanceCounter(&largeInteger);
+ m_start = double(largeInteger.QuadPart);
+}
+
+float b2Timer::GetMilliseconds() const
+{
+ LARGE_INTEGER largeInteger;
+ QueryPerformanceCounter(&largeInteger);
+ double count = double(largeInteger.QuadPart);
+ float ms = float(s_invFrequency * (count - m_start));
+ return ms;
+}
+
+#elif defined(__linux__) || defined (__APPLE__)
+
+#include <sys/time.h>
+
+b2Timer::b2Timer()
+{
+ Reset();
+}
+
+void b2Timer::Reset()
+{
+ timeval t;
+ gettimeofday(&t, 0);
+ m_start_sec = t.tv_sec;
+ m_start_usec = t.tv_usec;
+}
+
+float b2Timer::GetMilliseconds() const
+{
+ timeval t;
+ gettimeofday(&t, 0);
+ time_t start_sec = m_start_sec;
+ suseconds_t start_usec = m_start_usec;
+
+ // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
+ if (t.tv_usec < start_usec)
+ {
+ int nsec = (start_usec - t.tv_usec) / 1000000 + 1;
+ start_usec -= 1000000 * nsec;
+ start_sec += nsec;
+ }
+
+ if (t.tv_usec - start_usec > 1000000)
+ {
+ int nsec = (t.tv_usec - start_usec) / 1000000;
+ start_usec += 1000000 * nsec;
+ start_sec -= nsec;
+ }
+ return 1000.0f * (t.tv_sec - start_sec) + 0.001f * (t.tv_usec - start_usec);
+}
+
+#else
+
+b2Timer::b2Timer()
+{
+}
+
+void b2Timer::Reset()
+{
+}
+
+float b2Timer::GetMilliseconds() const
+{
+ return 0.0f;
+}
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_body.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_body.cpp
new file mode 100644
index 0000000..5746664
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_body.cpp
@@ -0,0 +1,565 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_contact.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_joint.h"
+#include "box2d/b2_world.h"
+
+#include <new>
+
+b2Body::b2Body(const b2BodyDef* bd, b2World* world)
+{
+ b2Assert(bd->position.IsValid());
+ b2Assert(bd->linearVelocity.IsValid());
+ b2Assert(b2IsValid(bd->angle));
+ b2Assert(b2IsValid(bd->angularVelocity));
+ b2Assert(b2IsValid(bd->angularDamping) && bd->angularDamping >= 0.0f);
+ b2Assert(b2IsValid(bd->linearDamping) && bd->linearDamping >= 0.0f);
+
+ m_flags = 0;
+
+ if (bd->bullet)
+ {
+ m_flags |= e_bulletFlag;
+ }
+ if (bd->fixedRotation)
+ {
+ m_flags |= e_fixedRotationFlag;
+ }
+ if (bd->allowSleep)
+ {
+ m_flags |= e_autoSleepFlag;
+ }
+ if (bd->awake && bd->type != b2_staticBody)
+ {
+ m_flags |= e_awakeFlag;
+ }
+ if (bd->enabled)
+ {
+ m_flags |= e_enabledFlag;
+ }
+
+ m_world = world;
+
+ m_xf.p = bd->position;
+ m_xf.q.Set(bd->angle);
+
+ m_sweep.localCenter.SetZero();
+ m_sweep.c0 = m_xf.p;
+ m_sweep.c = m_xf.p;
+ m_sweep.a0 = bd->angle;
+ m_sweep.a = bd->angle;
+ m_sweep.alpha0 = 0.0f;
+
+ m_jointList = nullptr;
+ m_contactList = nullptr;
+ m_prev = nullptr;
+ m_next = nullptr;
+
+ m_linearVelocity = bd->linearVelocity;
+ m_angularVelocity = bd->angularVelocity;
+
+ m_linearDamping = bd->linearDamping;
+ m_angularDamping = bd->angularDamping;
+ m_gravityScale = bd->gravityScale;
+
+ m_force.SetZero();
+ m_torque = 0.0f;
+
+ m_sleepTime = 0.0f;
+
+ m_type = bd->type;
+
+ m_mass = 0.0f;
+ m_invMass = 0.0f;
+
+ m_I = 0.0f;
+ m_invI = 0.0f;
+
+ m_userData = bd->userData;
+
+ m_fixtureList = nullptr;
+ m_fixtureCount = 0;
+}
+
+b2Body::~b2Body()
+{
+ // shapes and joints are destroyed in b2World::Destroy
+}
+
+void b2Body::SetType(b2BodyType type)
+{
+ b2Assert(m_world->IsLocked() == false);
+ if (m_world->IsLocked() == true)
+ {
+ return;
+ }
+
+ if (m_type == type)
+ {
+ return;
+ }
+
+ m_type = type;
+
+ ResetMassData();
+
+ if (m_type == b2_staticBody)
+ {
+ m_linearVelocity.SetZero();
+ m_angularVelocity = 0.0f;
+ m_sweep.a0 = m_sweep.a;
+ m_sweep.c0 = m_sweep.c;
+ m_flags &= ~e_awakeFlag;
+ SynchronizeFixtures();
+ }
+
+ SetAwake(true);
+
+ m_force.SetZero();
+ m_torque = 0.0f;
+
+ // Delete the attached contacts.
+ b2ContactEdge* ce = m_contactList;
+ while (ce)
+ {
+ b2ContactEdge* ce0 = ce;
+ ce = ce->next;
+ m_world->m_contactManager.Destroy(ce0->contact);
+ }
+ m_contactList = nullptr;
+
+ // Touch the proxies so that new contacts will be created (when appropriate)
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ int32 proxyCount = f->m_proxyCount;
+ for (int32 i = 0; i < proxyCount; ++i)
+ {
+ broadPhase->TouchProxy(f->m_proxies[i].proxyId);
+ }
+ }
+}
+
+b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)
+{
+ b2Assert(m_world->IsLocked() == false);
+ if (m_world->IsLocked() == true)
+ {
+ return nullptr;
+ }
+
+ b2BlockAllocator* allocator = &m_world->m_blockAllocator;
+
+ void* memory = allocator->Allocate(sizeof(b2Fixture));
+ b2Fixture* fixture = new (memory) b2Fixture;
+ fixture->Create(allocator, this, def);
+
+ if (m_flags & e_enabledFlag)
+ {
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+ fixture->CreateProxies(broadPhase, m_xf);
+ }
+
+ fixture->m_next = m_fixtureList;
+ m_fixtureList = fixture;
+ ++m_fixtureCount;
+
+ fixture->m_body = this;
+
+ // Adjust mass properties if needed.
+ if (fixture->m_density > 0.0f)
+ {
+ ResetMassData();
+ }
+
+ // Let the world know we have a new fixture. This will cause new contacts
+ // to be created at the beginning of the next time step.
+ m_world->m_newContacts = true;
+
+ return fixture;
+}
+
+b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float density)
+{
+ b2FixtureDef def;
+ def.shape = shape;
+ def.density = density;
+
+ return CreateFixture(&def);
+}
+
+void b2Body::DestroyFixture(b2Fixture* fixture)
+{
+ if (fixture == NULL)
+ {
+ return;
+ }
+
+ b2Assert(m_world->IsLocked() == false);
+ if (m_world->IsLocked() == true)
+ {
+ return;
+ }
+
+ b2Assert(fixture->m_body == this);
+
+ // Remove the fixture from this body's singly linked list.
+ b2Assert(m_fixtureCount > 0);
+ b2Fixture** node = &m_fixtureList;
+ bool found = false;
+ while (*node != nullptr)
+ {
+ if (*node == fixture)
+ {
+ *node = fixture->m_next;
+ found = true;
+ break;
+ }
+
+ node = &(*node)->m_next;
+ }
+
+ // You tried to remove a shape that is not attached to this body.
+ b2Assert(found);
+
+ // Destroy any contacts associated with the fixture.
+ b2ContactEdge* edge = m_contactList;
+ while (edge)
+ {
+ b2Contact* c = edge->contact;
+ edge = edge->next;
+
+ b2Fixture* fixtureA = c->GetFixtureA();
+ b2Fixture* fixtureB = c->GetFixtureB();
+
+ if (fixture == fixtureA || fixture == fixtureB)
+ {
+ // This destroys the contact and removes it from
+ // this body's contact list.
+ m_world->m_contactManager.Destroy(c);
+ }
+ }
+
+ b2BlockAllocator* allocator = &m_world->m_blockAllocator;
+
+ if (m_flags & e_enabledFlag)
+ {
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+ fixture->DestroyProxies(broadPhase);
+ }
+
+ fixture->m_body = nullptr;
+ fixture->m_next = nullptr;
+ fixture->Destroy(allocator);
+ fixture->~b2Fixture();
+ allocator->Free(fixture, sizeof(b2Fixture));
+
+ --m_fixtureCount;
+
+ // Reset the mass data.
+ ResetMassData();
+}
+
+void b2Body::ResetMassData()
+{
+ // Compute mass data from shapes. Each shape has its own density.
+ m_mass = 0.0f;
+ m_invMass = 0.0f;
+ m_I = 0.0f;
+ m_invI = 0.0f;
+ m_sweep.localCenter.SetZero();
+
+ // Static and kinematic bodies have zero mass.
+ if (m_type == b2_staticBody || m_type == b2_kinematicBody)
+ {
+ m_sweep.c0 = m_xf.p;
+ m_sweep.c = m_xf.p;
+ m_sweep.a0 = m_sweep.a;
+ return;
+ }
+
+ b2Assert(m_type == b2_dynamicBody);
+
+ // Accumulate mass over all fixtures.
+ b2Vec2 localCenter = b2Vec2_zero;
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ if (f->m_density == 0.0f)
+ {
+ continue;
+ }
+
+ b2MassData massData;
+ f->GetMassData(&massData);
+ m_mass += massData.mass;
+ localCenter += massData.mass * massData.center;
+ m_I += massData.I;
+ }
+
+ // Compute center of mass.
+ if (m_mass > 0.0f)
+ {
+ m_invMass = 1.0f / m_mass;
+ localCenter *= m_invMass;
+ }
+
+ if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0)
+ {
+ // Center the inertia about the center of mass.
+ m_I -= m_mass * b2Dot(localCenter, localCenter);
+ b2Assert(m_I > 0.0f);
+ m_invI = 1.0f / m_I;
+
+ }
+ else
+ {
+ m_I = 0.0f;
+ m_invI = 0.0f;
+ }
+
+ // Move center of mass.
+ b2Vec2 oldCenter = m_sweep.c;
+ m_sweep.localCenter = localCenter;
+ m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
+
+ // Update center of mass velocity.
+ m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter);
+}
+
+void b2Body::SetMassData(const b2MassData* massData)
+{
+ b2Assert(m_world->IsLocked() == false);
+ if (m_world->IsLocked() == true)
+ {
+ return;
+ }
+
+ if (m_type != b2_dynamicBody)
+ {
+ return;
+ }
+
+ m_invMass = 0.0f;
+ m_I = 0.0f;
+ m_invI = 0.0f;
+
+ m_mass = massData->mass;
+ if (m_mass <= 0.0f)
+ {
+ m_mass = 1.0f;
+ }
+
+ m_invMass = 1.0f / m_mass;
+
+ if (massData->I > 0.0f && (m_flags & b2Body::e_fixedRotationFlag) == 0)
+ {
+ m_I = massData->I - m_mass * b2Dot(massData->center, massData->center);
+ b2Assert(m_I > 0.0f);
+ m_invI = 1.0f / m_I;
+ }
+
+ // Move center of mass.
+ b2Vec2 oldCenter = m_sweep.c;
+ m_sweep.localCenter = massData->center;
+ m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
+
+ // Update center of mass velocity.
+ m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter);
+}
+
+bool b2Body::ShouldCollide(const b2Body* other) const
+{
+ // At least one body should be dynamic.
+ if (m_type != b2_dynamicBody && other->m_type != b2_dynamicBody)
+ {
+ return false;
+ }
+
+ // Does a joint prevent collision?
+ for (b2JointEdge* jn = m_jointList; jn; jn = jn->next)
+ {
+ if (jn->other == other)
+ {
+ if (jn->joint->m_collideConnected == false)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void b2Body::SetTransform(const b2Vec2& position, float angle)
+{
+ b2Assert(m_world->IsLocked() == false);
+ if (m_world->IsLocked() == true)
+ {
+ return;
+ }
+
+ m_xf.q.Set(angle);
+ m_xf.p = position;
+
+ m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
+ m_sweep.a = angle;
+
+ m_sweep.c0 = m_sweep.c;
+ m_sweep.a0 = angle;
+
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ f->Synchronize(broadPhase, m_xf, m_xf);
+ }
+
+ // Check for new contacts the next step
+ m_world->m_newContacts = true;
+}
+
+void b2Body::SynchronizeFixtures()
+{
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+
+ if (m_flags & b2Body::e_awakeFlag)
+ {
+ b2Transform xf1;
+ xf1.q.Set(m_sweep.a0);
+ xf1.p = m_sweep.c0 - b2Mul(xf1.q, m_sweep.localCenter);
+
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ f->Synchronize(broadPhase, xf1, m_xf);
+ }
+ }
+ else
+ {
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ f->Synchronize(broadPhase, m_xf, m_xf);
+ }
+ }
+}
+
+void b2Body::SetEnabled(bool flag)
+{
+ b2Assert(m_world->IsLocked() == false);
+
+ if (flag == IsEnabled())
+ {
+ return;
+ }
+
+ if (flag)
+ {
+ m_flags |= e_enabledFlag;
+
+ // Create all proxies.
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ f->CreateProxies(broadPhase, m_xf);
+ }
+
+ // Contacts are created at the beginning of the next
+ m_world->m_newContacts = true;
+ }
+ else
+ {
+ m_flags &= ~e_enabledFlag;
+
+ // Destroy all proxies.
+ b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ f->DestroyProxies(broadPhase);
+ }
+
+ // Destroy the attached contacts.
+ b2ContactEdge* ce = m_contactList;
+ while (ce)
+ {
+ b2ContactEdge* ce0 = ce;
+ ce = ce->next;
+ m_world->m_contactManager.Destroy(ce0->contact);
+ }
+ m_contactList = nullptr;
+ }
+}
+
+void b2Body::SetFixedRotation(bool flag)
+{
+ bool status = (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag;
+ if (status == flag)
+ {
+ return;
+ }
+
+ if (flag)
+ {
+ m_flags |= e_fixedRotationFlag;
+ }
+ else
+ {
+ m_flags &= ~e_fixedRotationFlag;
+ }
+
+ m_angularVelocity = 0.0f;
+
+ ResetMassData();
+}
+
+void b2Body::Dump()
+{
+ int32 bodyIndex = m_islandIndex;
+
+ // %.9g is sufficient to save and load the same value using text
+ // FLT_DECIMAL_DIG == 9
+
+ b2Dump("{\n");
+ b2Dump(" b2BodyDef bd;\n");
+ b2Dump(" bd.type = b2BodyType(%d);\n", m_type);
+ b2Dump(" bd.position.Set(%.9g, %.9g);\n", m_xf.p.x, m_xf.p.y);
+ b2Dump(" bd.angle = %.9g;\n", m_sweep.a);
+ b2Dump(" bd.linearVelocity.Set(%.9g, %.9g);\n", m_linearVelocity.x, m_linearVelocity.y);
+ b2Dump(" bd.angularVelocity = %.9g;\n", m_angularVelocity);
+ b2Dump(" bd.linearDamping = %.9g;\n", m_linearDamping);
+ b2Dump(" bd.angularDamping = %.9g;\n", m_angularDamping);
+ b2Dump(" bd.allowSleep = bool(%d);\n", m_flags & e_autoSleepFlag);
+ b2Dump(" bd.awake = bool(%d);\n", m_flags & e_awakeFlag);
+ b2Dump(" bd.fixedRotation = bool(%d);\n", m_flags & e_fixedRotationFlag);
+ b2Dump(" bd.bullet = bool(%d);\n", m_flags & e_bulletFlag);
+ b2Dump(" bd.enabled = bool(%d);\n", m_flags & e_enabledFlag);
+ b2Dump(" bd.gravityScale = %.9g;\n", m_gravityScale);
+ b2Dump(" bodies[%d] = m_world->CreateBody(&bd);\n", m_islandIndex);
+ b2Dump("\n");
+ for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
+ {
+ b2Dump(" {\n");
+ f->Dump(bodyIndex);
+ b2Dump(" }\n");
+ }
+ b2Dump("}\n");
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.cpp
new file mode 100644
index 0000000..8464fe8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.cpp
@@ -0,0 +1,57 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_chain_circle_contact.h"
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_chain_shape.h"
+#include "box2d/b2_edge_shape.h"
+
+#include <new>
+
+b2Contact* b2ChainAndCircleContact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2ChainAndCircleContact));
+ return new (mem) b2ChainAndCircleContact(fixtureA, indexA, fixtureB, indexB);
+}
+
+void b2ChainAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2ChainAndCircleContact*)contact)->~b2ChainAndCircleContact();
+ allocator->Free(contact, sizeof(b2ChainAndCircleContact));
+}
+
+b2ChainAndCircleContact::b2ChainAndCircleContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB)
+: b2Contact(fixtureA, indexA, fixtureB, indexB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_chain);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);
+}
+
+void b2ChainAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2ChainShape* chain = (b2ChainShape*)m_fixtureA->GetShape();
+ b2EdgeShape edge;
+ chain->GetChildEdge(&edge, m_indexA);
+ b2CollideEdgeAndCircle( manifold, &edge, xfA,
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.h
new file mode 100644
index 0000000..33ced64
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_circle_contact.h
@@ -0,0 +1,43 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CHAIN_AND_CIRCLE_CONTACT_H
+#define B2_CHAIN_AND_CIRCLE_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2ChainAndCircleContact : public b2Contact
+{
+public:
+ static b2Contact* Create( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2ChainAndCircleContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
+ ~b2ChainAndCircleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.cpp
new file mode 100644
index 0000000..b8257aa
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.cpp
@@ -0,0 +1,57 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_chain_polygon_contact.h"
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_chain_shape.h"
+#include "box2d/b2_edge_shape.h"
+
+#include <new>
+
+b2Contact* b2ChainAndPolygonContact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2ChainAndPolygonContact));
+ return new (mem) b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB);
+}
+
+void b2ChainAndPolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2ChainAndPolygonContact*)contact)->~b2ChainAndPolygonContact();
+ allocator->Free(contact, sizeof(b2ChainAndPolygonContact));
+}
+
+b2ChainAndPolygonContact::b2ChainAndPolygonContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB)
+: b2Contact(fixtureA, indexA, fixtureB, indexB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_chain);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon);
+}
+
+void b2ChainAndPolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2ChainShape* chain = (b2ChainShape*)m_fixtureA->GetShape();
+ b2EdgeShape edge;
+ chain->GetChildEdge(&edge, m_indexA);
+ b2CollideEdgeAndPolygon( manifold, &edge, xfA,
+ (b2PolygonShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.h
new file mode 100644
index 0000000..058154f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_chain_polygon_contact.h
@@ -0,0 +1,43 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CHAIN_AND_POLYGON_CONTACT_H
+#define B2_CHAIN_AND_POLYGON_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2ChainAndPolygonContact : public b2Contact
+{
+public:
+ static b2Contact* Create( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2ChainAndPolygonContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
+ ~b2ChainAndPolygonContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.cpp
new file mode 100644
index 0000000..738aa84
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.cpp
@@ -0,0 +1,56 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_circle_contact.h"
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_body.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_time_of_impact.h"
+#include "box2d/b2_world_callbacks.h"
+
+#include <new>
+
+b2Contact* b2CircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2CircleContact));
+ return new (mem) b2CircleContact(fixtureA, fixtureB);
+}
+
+void b2CircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2CircleContact*)contact)->~b2CircleContact();
+ allocator->Free(contact, sizeof(b2CircleContact));
+}
+
+b2CircleContact::b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, 0, fixtureB, 0)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_circle);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);
+}
+
+void b2CircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2CollideCircles(manifold,
+ (b2CircleShape*)m_fixtureA->GetShape(), xfA,
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.h
new file mode 100644
index 0000000..98e09ea
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_circle_contact.h
@@ -0,0 +1,43 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CIRCLE_CONTACT_H
+#define B2_CIRCLE_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2CircleContact : public b2Contact
+{
+public:
+ static b2Contact* Create( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2CircleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_contact.cpp
new file mode 100644
index 0000000..1c65bc8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_contact.cpp
@@ -0,0 +1,252 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_chain_circle_contact.h"
+#include "b2_chain_polygon_contact.h"
+#include "b2_circle_contact.h"
+#include "b2_contact_solver.h"
+#include "b2_edge_circle_contact.h"
+#include "b2_edge_polygon_contact.h"
+#include "b2_polygon_circle_contact.h"
+#include "b2_polygon_contact.h"
+
+#include "box2d/b2_contact.h"
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_body.h"
+#include "box2d/b2_collision.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_shape.h"
+#include "box2d/b2_time_of_impact.h"
+#include "box2d/b2_world.h"
+
+b2ContactRegister b2Contact::s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];
+bool b2Contact::s_initialized = false;
+
+void b2Contact::InitializeRegisters()
+{
+ AddType(b2CircleContact::Create, b2CircleContact::Destroy, b2Shape::e_circle, b2Shape::e_circle);
+ AddType(b2PolygonAndCircleContact::Create, b2PolygonAndCircleContact::Destroy, b2Shape::e_polygon, b2Shape::e_circle);
+ AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, b2Shape::e_polygon, b2Shape::e_polygon);
+ AddType(b2EdgeAndCircleContact::Create, b2EdgeAndCircleContact::Destroy, b2Shape::e_edge, b2Shape::e_circle);
+ AddType(b2EdgeAndPolygonContact::Create, b2EdgeAndPolygonContact::Destroy, b2Shape::e_edge, b2Shape::e_polygon);
+ AddType(b2ChainAndCircleContact::Create, b2ChainAndCircleContact::Destroy, b2Shape::e_chain, b2Shape::e_circle);
+ AddType(b2ChainAndPolygonContact::Create, b2ChainAndPolygonContact::Destroy, b2Shape::e_chain, b2Shape::e_polygon);
+}
+
+void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn,
+ b2Shape::Type type1, b2Shape::Type type2)
+{
+ b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount);
+ b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount);
+
+ s_registers[type1][type2].createFcn = createFcn;
+ s_registers[type1][type2].destroyFcn = destoryFcn;
+ s_registers[type1][type2].primary = true;
+
+ if (type1 != type2)
+ {
+ s_registers[type2][type1].createFcn = createFcn;
+ s_registers[type2][type1].destroyFcn = destoryFcn;
+ s_registers[type2][type1].primary = false;
+ }
+}
+
+b2Contact* b2Contact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator)
+{
+ if (s_initialized == false)
+ {
+ InitializeRegisters();
+ s_initialized = true;
+ }
+
+ b2Shape::Type type1 = fixtureA->GetType();
+ b2Shape::Type type2 = fixtureB->GetType();
+
+ b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount);
+ b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount);
+
+ b2ContactCreateFcn* createFcn = s_registers[type1][type2].createFcn;
+ if (createFcn)
+ {
+ if (s_registers[type1][type2].primary)
+ {
+ return createFcn(fixtureA, indexA, fixtureB, indexB, allocator);
+ }
+ else
+ {
+ return createFcn(fixtureB, indexB, fixtureA, indexA, allocator);
+ }
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+void b2Contact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ b2Assert(s_initialized == true);
+
+ b2Fixture* fixtureA = contact->m_fixtureA;
+ b2Fixture* fixtureB = contact->m_fixtureB;
+
+ if (contact->m_manifold.pointCount > 0 &&
+ fixtureA->IsSensor() == false &&
+ fixtureB->IsSensor() == false)
+ {
+ fixtureA->GetBody()->SetAwake(true);
+ fixtureB->GetBody()->SetAwake(true);
+ }
+
+ b2Shape::Type typeA = fixtureA->GetType();
+ b2Shape::Type typeB = fixtureB->GetType();
+
+ b2Assert(0 <= typeA && typeA < b2Shape::e_typeCount);
+ b2Assert(0 <= typeB && typeB < b2Shape::e_typeCount);
+
+ b2ContactDestroyFcn* destroyFcn = s_registers[typeA][typeB].destroyFcn;
+ destroyFcn(contact, allocator);
+}
+
+b2Contact::b2Contact(b2Fixture* fA, int32 indexA, b2Fixture* fB, int32 indexB)
+{
+ m_flags = e_enabledFlag;
+
+ m_fixtureA = fA;
+ m_fixtureB = fB;
+
+ m_indexA = indexA;
+ m_indexB = indexB;
+
+ m_manifold.pointCount = 0;
+
+ m_prev = nullptr;
+ m_next = nullptr;
+
+ m_nodeA.contact = nullptr;
+ m_nodeA.prev = nullptr;
+ m_nodeA.next = nullptr;
+ m_nodeA.other = nullptr;
+
+ m_nodeB.contact = nullptr;
+ m_nodeB.prev = nullptr;
+ m_nodeB.next = nullptr;
+ m_nodeB.other = nullptr;
+
+ m_toiCount = 0;
+
+ m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
+ m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
+ m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold);
+
+ m_tangentSpeed = 0.0f;
+}
+
+// Update the contact manifold and touching status.
+// Note: do not assume the fixture AABBs are overlapping or are valid.
+void b2Contact::Update(b2ContactListener* listener)
+{
+ b2Manifold oldManifold = m_manifold;
+
+ // Re-enable this contact.
+ m_flags |= e_enabledFlag;
+
+ bool touching = false;
+ bool wasTouching = (m_flags & e_touchingFlag) == e_touchingFlag;
+
+ bool sensorA = m_fixtureA->IsSensor();
+ bool sensorB = m_fixtureB->IsSensor();
+ bool sensor = sensorA || sensorB;
+
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+ const b2Transform& xfA = bodyA->GetTransform();
+ const b2Transform& xfB = bodyB->GetTransform();
+
+ // Is this contact a sensor?
+ if (sensor)
+ {
+ const b2Shape* shapeA = m_fixtureA->GetShape();
+ const b2Shape* shapeB = m_fixtureB->GetShape();
+ touching = b2TestOverlap(shapeA, m_indexA, shapeB, m_indexB, xfA, xfB);
+
+ // Sensors don't generate manifolds.
+ m_manifold.pointCount = 0;
+ }
+ else
+ {
+ Evaluate(&m_manifold, xfA, xfB);
+ touching = m_manifold.pointCount > 0;
+
+ // Match old contact ids to new contact ids and copy the
+ // stored impulses to warm start the solver.
+ for (int32 i = 0; i < m_manifold.pointCount; ++i)
+ {
+ b2ManifoldPoint* mp2 = m_manifold.points + i;
+ mp2->normalImpulse = 0.0f;
+ mp2->tangentImpulse = 0.0f;
+ b2ContactID id2 = mp2->id;
+
+ for (int32 j = 0; j < oldManifold.pointCount; ++j)
+ {
+ b2ManifoldPoint* mp1 = oldManifold.points + j;
+
+ if (mp1->id.key == id2.key)
+ {
+ mp2->normalImpulse = mp1->normalImpulse;
+ mp2->tangentImpulse = mp1->tangentImpulse;
+ break;
+ }
+ }
+ }
+
+ if (touching != wasTouching)
+ {
+ bodyA->SetAwake(true);
+ bodyB->SetAwake(true);
+ }
+ }
+
+ if (touching)
+ {
+ m_flags |= e_touchingFlag;
+ }
+ else
+ {
+ m_flags &= ~e_touchingFlag;
+ }
+
+ if (wasTouching == false && touching == true && listener)
+ {
+ listener->BeginContact(this);
+ }
+
+ if (wasTouching == true && touching == false && listener)
+ {
+ listener->EndContact(this);
+ }
+
+ if (sensor == false && touching && listener)
+ {
+ listener->PreSolve(this, &oldManifold);
+ }
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_contact_manager.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_contact_manager.cpp
new file mode 100644
index 0000000..5666608
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_contact_manager.cpp
@@ -0,0 +1,293 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_contact.h"
+#include "box2d/b2_contact_manager.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_world_callbacks.h"
+
+b2ContactFilter b2_defaultFilter;
+b2ContactListener b2_defaultListener;
+
+b2ContactManager::b2ContactManager()
+{
+ m_contactList = nullptr;
+ m_contactCount = 0;
+ m_contactFilter = &b2_defaultFilter;
+ m_contactListener = &b2_defaultListener;
+ m_allocator = nullptr;
+}
+
+void b2ContactManager::Destroy(b2Contact* c)
+{
+ b2Fixture* fixtureA = c->GetFixtureA();
+ b2Fixture* fixtureB = c->GetFixtureB();
+ b2Body* bodyA = fixtureA->GetBody();
+ b2Body* bodyB = fixtureB->GetBody();
+
+ if (m_contactListener && c->IsTouching())
+ {
+ m_contactListener->EndContact(c);
+ }
+
+ // Remove from the world.
+ if (c->m_prev)
+ {
+ c->m_prev->m_next = c->m_next;
+ }
+
+ if (c->m_next)
+ {
+ c->m_next->m_prev = c->m_prev;
+ }
+
+ if (c == m_contactList)
+ {
+ m_contactList = c->m_next;
+ }
+
+ // Remove from body 1
+ if (c->m_nodeA.prev)
+ {
+ c->m_nodeA.prev->next = c->m_nodeA.next;
+ }
+
+ if (c->m_nodeA.next)
+ {
+ c->m_nodeA.next->prev = c->m_nodeA.prev;
+ }
+
+ if (&c->m_nodeA == bodyA->m_contactList)
+ {
+ bodyA->m_contactList = c->m_nodeA.next;
+ }
+
+ // Remove from body 2
+ if (c->m_nodeB.prev)
+ {
+ c->m_nodeB.prev->next = c->m_nodeB.next;
+ }
+
+ if (c->m_nodeB.next)
+ {
+ c->m_nodeB.next->prev = c->m_nodeB.prev;
+ }
+
+ if (&c->m_nodeB == bodyB->m_contactList)
+ {
+ bodyB->m_contactList = c->m_nodeB.next;
+ }
+
+ // Call the factory.
+ b2Contact::Destroy(c, m_allocator);
+ --m_contactCount;
+}
+
+// This is the top level collision call for the time step. Here
+// all the narrow phase collision is processed for the world
+// contact list.
+void b2ContactManager::Collide()
+{
+ // Update awake contacts.
+ b2Contact* c = m_contactList;
+ while (c)
+ {
+ b2Fixture* fixtureA = c->GetFixtureA();
+ b2Fixture* fixtureB = c->GetFixtureB();
+ int32 indexA = c->GetChildIndexA();
+ int32 indexB = c->GetChildIndexB();
+ b2Body* bodyA = fixtureA->GetBody();
+ b2Body* bodyB = fixtureB->GetBody();
+
+ // Is this contact flagged for filtering?
+ if (c->m_flags & b2Contact::e_filterFlag)
+ {
+ // Should these bodies collide?
+ if (bodyB->ShouldCollide(bodyA) == false)
+ {
+ b2Contact* cNuke = c;
+ c = cNuke->GetNext();
+ Destroy(cNuke);
+ continue;
+ }
+
+ // Check user filtering.
+ if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
+ {
+ b2Contact* cNuke = c;
+ c = cNuke->GetNext();
+ Destroy(cNuke);
+ continue;
+ }
+
+ // Clear the filtering flag.
+ c->m_flags &= ~b2Contact::e_filterFlag;
+ }
+
+ bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody;
+ bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody;
+
+ // At least one body must be awake and it must be dynamic or kinematic.
+ if (activeA == false && activeB == false)
+ {
+ c = c->GetNext();
+ continue;
+ }
+
+ int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId;
+ int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId;
+ bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB);
+
+ // Here we destroy contacts that cease to overlap in the broad-phase.
+ if (overlap == false)
+ {
+ b2Contact* cNuke = c;
+ c = cNuke->GetNext();
+ Destroy(cNuke);
+ continue;
+ }
+
+ // The contact persists.
+ c->Update(m_contactListener);
+ c = c->GetNext();
+ }
+}
+
+void b2ContactManager::FindNewContacts()
+{
+ m_broadPhase.UpdatePairs(this);
+}
+
+void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB)
+{
+ b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA;
+ b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB;
+
+ b2Fixture* fixtureA = proxyA->fixture;
+ b2Fixture* fixtureB = proxyB->fixture;
+
+ int32 indexA = proxyA->childIndex;
+ int32 indexB = proxyB->childIndex;
+
+ b2Body* bodyA = fixtureA->GetBody();
+ b2Body* bodyB = fixtureB->GetBody();
+
+ // Are the fixtures on the same body?
+ if (bodyA == bodyB)
+ {
+ return;
+ }
+
+ // TODO_ERIN use a hash table to remove a potential bottleneck when both
+ // bodies have a lot of contacts.
+ // Does a contact already exist?
+ b2ContactEdge* edge = bodyB->GetContactList();
+ while (edge)
+ {
+ if (edge->other == bodyA)
+ {
+ b2Fixture* fA = edge->contact->GetFixtureA();
+ b2Fixture* fB = edge->contact->GetFixtureB();
+ int32 iA = edge->contact->GetChildIndexA();
+ int32 iB = edge->contact->GetChildIndexB();
+
+ if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB)
+ {
+ // A contact already exists.
+ return;
+ }
+
+ if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA)
+ {
+ // A contact already exists.
+ return;
+ }
+ }
+
+ edge = edge->next;
+ }
+
+ // Does a joint override collision? Is at least one body dynamic?
+ if (bodyB->ShouldCollide(bodyA) == false)
+ {
+ return;
+ }
+
+ // Check user filtering.
+ if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
+ {
+ return;
+ }
+
+ // Call the factory.
+ b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator);
+ if (c == nullptr)
+ {
+ return;
+ }
+
+ // Contact creation may swap fixtures.
+ fixtureA = c->GetFixtureA();
+ fixtureB = c->GetFixtureB();
+ indexA = c->GetChildIndexA();
+ indexB = c->GetChildIndexB();
+ bodyA = fixtureA->GetBody();
+ bodyB = fixtureB->GetBody();
+
+ // Insert into the world.
+ c->m_prev = nullptr;
+ c->m_next = m_contactList;
+ if (m_contactList != nullptr)
+ {
+ m_contactList->m_prev = c;
+ }
+ m_contactList = c;
+
+ // Connect to island graph.
+
+ // Connect to body A
+ c->m_nodeA.contact = c;
+ c->m_nodeA.other = bodyB;
+
+ c->m_nodeA.prev = nullptr;
+ c->m_nodeA.next = bodyA->m_contactList;
+ if (bodyA->m_contactList != nullptr)
+ {
+ bodyA->m_contactList->prev = &c->m_nodeA;
+ }
+ bodyA->m_contactList = &c->m_nodeA;
+
+ // Connect to body B
+ c->m_nodeB.contact = c;
+ c->m_nodeB.other = bodyA;
+
+ c->m_nodeB.prev = nullptr;
+ c->m_nodeB.next = bodyB->m_contactList;
+ if (bodyB->m_contactList != nullptr)
+ {
+ bodyB->m_contactList->prev = &c->m_nodeB;
+ }
+ bodyB->m_contactList = &c->m_nodeB;
+
+ ++m_contactCount;
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.cpp
new file mode 100644
index 0000000..e6f432a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.cpp
@@ -0,0 +1,843 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_contact_solver.h"
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_contact.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_stack_allocator.h"
+#include "box2d/b2_world.h"
+
+// Solver debugging is normally disabled because the block solver sometimes has to deal with a poorly conditioned effective mass matrix.
+#define B2_DEBUG_SOLVER 0
+
+B2_API bool g_blockSolve = true;
+
+struct b2ContactPositionConstraint
+{
+ b2Vec2 localPoints[b2_maxManifoldPoints];
+ b2Vec2 localNormal;
+ b2Vec2 localPoint;
+ int32 indexA;
+ int32 indexB;
+ float invMassA, invMassB;
+ b2Vec2 localCenterA, localCenterB;
+ float invIA, invIB;
+ b2Manifold::Type type;
+ float radiusA, radiusB;
+ int32 pointCount;
+};
+
+b2ContactSolver::b2ContactSolver(b2ContactSolverDef* def)
+{
+ m_step = def->step;
+ m_allocator = def->allocator;
+ m_count = def->count;
+ m_positionConstraints = (b2ContactPositionConstraint*)m_allocator->Allocate(m_count * sizeof(b2ContactPositionConstraint));
+ m_velocityConstraints = (b2ContactVelocityConstraint*)m_allocator->Allocate(m_count * sizeof(b2ContactVelocityConstraint));
+ m_positions = def->positions;
+ m_velocities = def->velocities;
+ m_contacts = def->contacts;
+
+ // Initialize position independent portions of the constraints.
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2Contact* contact = m_contacts[i];
+
+ b2Fixture* fixtureA = contact->m_fixtureA;
+ b2Fixture* fixtureB = contact->m_fixtureB;
+ b2Shape* shapeA = fixtureA->GetShape();
+ b2Shape* shapeB = fixtureB->GetShape();
+ float radiusA = shapeA->m_radius;
+ float radiusB = shapeB->m_radius;
+ b2Body* bodyA = fixtureA->GetBody();
+ b2Body* bodyB = fixtureB->GetBody();
+ b2Manifold* manifold = contact->GetManifold();
+
+ int32 pointCount = manifold->pointCount;
+ b2Assert(pointCount > 0);
+
+ b2ContactVelocityConstraint* vc = m_velocityConstraints + i;
+ vc->friction = contact->m_friction;
+ vc->restitution = contact->m_restitution;
+ vc->threshold = contact->m_restitutionThreshold;
+ vc->tangentSpeed = contact->m_tangentSpeed;
+ vc->indexA = bodyA->m_islandIndex;
+ vc->indexB = bodyB->m_islandIndex;
+ vc->invMassA = bodyA->m_invMass;
+ vc->invMassB = bodyB->m_invMass;
+ vc->invIA = bodyA->m_invI;
+ vc->invIB = bodyB->m_invI;
+ vc->contactIndex = i;
+ vc->pointCount = pointCount;
+ vc->K.SetZero();
+ vc->normalMass.SetZero();
+
+ b2ContactPositionConstraint* pc = m_positionConstraints + i;
+ pc->indexA = bodyA->m_islandIndex;
+ pc->indexB = bodyB->m_islandIndex;
+ pc->invMassA = bodyA->m_invMass;
+ pc->invMassB = bodyB->m_invMass;
+ pc->localCenterA = bodyA->m_sweep.localCenter;
+ pc->localCenterB = bodyB->m_sweep.localCenter;
+ pc->invIA = bodyA->m_invI;
+ pc->invIB = bodyB->m_invI;
+ pc->localNormal = manifold->localNormal;
+ pc->localPoint = manifold->localPoint;
+ pc->pointCount = pointCount;
+ pc->radiusA = radiusA;
+ pc->radiusB = radiusB;
+ pc->type = manifold->type;
+
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2ManifoldPoint* cp = manifold->points + j;
+ b2VelocityConstraintPoint* vcp = vc->points + j;
+
+ if (m_step.warmStarting)
+ {
+ vcp->normalImpulse = m_step.dtRatio * cp->normalImpulse;
+ vcp->tangentImpulse = m_step.dtRatio * cp->tangentImpulse;
+ }
+ else
+ {
+ vcp->normalImpulse = 0.0f;
+ vcp->tangentImpulse = 0.0f;
+ }
+
+ vcp->rA.SetZero();
+ vcp->rB.SetZero();
+ vcp->normalMass = 0.0f;
+ vcp->tangentMass = 0.0f;
+ vcp->velocityBias = 0.0f;
+
+ pc->localPoints[j] = cp->localPoint;
+ }
+ }
+}
+
+b2ContactSolver::~b2ContactSolver()
+{
+ m_allocator->Free(m_velocityConstraints);
+ m_allocator->Free(m_positionConstraints);
+}
+
+// Initialize position dependent portions of the velocity constraints.
+void b2ContactSolver::InitializeVelocityConstraints()
+{
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2ContactVelocityConstraint* vc = m_velocityConstraints + i;
+ b2ContactPositionConstraint* pc = m_positionConstraints + i;
+
+ float radiusA = pc->radiusA;
+ float radiusB = pc->radiusB;
+ b2Manifold* manifold = m_contacts[vc->contactIndex]->GetManifold();
+
+ int32 indexA = vc->indexA;
+ int32 indexB = vc->indexB;
+
+ float mA = vc->invMassA;
+ float mB = vc->invMassB;
+ float iA = vc->invIA;
+ float iB = vc->invIB;
+ b2Vec2 localCenterA = pc->localCenterA;
+ b2Vec2 localCenterB = pc->localCenterB;
+
+ b2Vec2 cA = m_positions[indexA].c;
+ float aA = m_positions[indexA].a;
+ b2Vec2 vA = m_velocities[indexA].v;
+ float wA = m_velocities[indexA].w;
+
+ b2Vec2 cB = m_positions[indexB].c;
+ float aB = m_positions[indexB].a;
+ b2Vec2 vB = m_velocities[indexB].v;
+ float wB = m_velocities[indexB].w;
+
+ b2Assert(manifold->pointCount > 0);
+
+ b2Transform xfA, xfB;
+ xfA.q.Set(aA);
+ xfB.q.Set(aB);
+ xfA.p = cA - b2Mul(xfA.q, localCenterA);
+ xfB.p = cB - b2Mul(xfB.q, localCenterB);
+
+ b2WorldManifold worldManifold;
+ worldManifold.Initialize(manifold, xfA, radiusA, xfB, radiusB);
+
+ vc->normal = worldManifold.normal;
+
+ int32 pointCount = vc->pointCount;
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2VelocityConstraintPoint* vcp = vc->points + j;
+
+ vcp->rA = worldManifold.points[j] - cA;
+ vcp->rB = worldManifold.points[j] - cB;
+
+ float rnA = b2Cross(vcp->rA, vc->normal);
+ float rnB = b2Cross(vcp->rB, vc->normal);
+
+ float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
+
+ vcp->normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f;
+
+ b2Vec2 tangent = b2Cross(vc->normal, 1.0f);
+
+ float rtA = b2Cross(vcp->rA, tangent);
+ float rtB = b2Cross(vcp->rB, tangent);
+
+ float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB;
+
+ vcp->tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f;
+
+ // Setup a velocity bias for restitution.
+ vcp->velocityBias = 0.0f;
+ float vRel = b2Dot(vc->normal, vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA));
+ if (vRel < -vc->threshold)
+ {
+ vcp->velocityBias = -vc->restitution * vRel;
+ }
+ }
+
+ // If we have two points, then prepare the block solver.
+ if (vc->pointCount == 2 && g_blockSolve)
+ {
+ b2VelocityConstraintPoint* vcp1 = vc->points + 0;
+ b2VelocityConstraintPoint* vcp2 = vc->points + 1;
+
+ float rn1A = b2Cross(vcp1->rA, vc->normal);
+ float rn1B = b2Cross(vcp1->rB, vc->normal);
+ float rn2A = b2Cross(vcp2->rA, vc->normal);
+ float rn2B = b2Cross(vcp2->rB, vc->normal);
+
+ float k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B;
+ float k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B;
+ float k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B;
+
+ // Ensure a reasonable condition number.
+ const float k_maxConditionNumber = 1000.0f;
+ if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12))
+ {
+ // K is safe to invert.
+ vc->K.ex.Set(k11, k12);
+ vc->K.ey.Set(k12, k22);
+ vc->normalMass = vc->K.GetInverse();
+ }
+ else
+ {
+ // The constraints are redundant, just use one.
+ // TODO_ERIN use deepest?
+ vc->pointCount = 1;
+ }
+ }
+ }
+}
+
+void b2ContactSolver::WarmStart()
+{
+ // Warm start.
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2ContactVelocityConstraint* vc = m_velocityConstraints + i;
+
+ int32 indexA = vc->indexA;
+ int32 indexB = vc->indexB;
+ float mA = vc->invMassA;
+ float iA = vc->invIA;
+ float mB = vc->invMassB;
+ float iB = vc->invIB;
+ int32 pointCount = vc->pointCount;
+
+ b2Vec2 vA = m_velocities[indexA].v;
+ float wA = m_velocities[indexA].w;
+ b2Vec2 vB = m_velocities[indexB].v;
+ float wB = m_velocities[indexB].w;
+
+ b2Vec2 normal = vc->normal;
+ b2Vec2 tangent = b2Cross(normal, 1.0f);
+
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2VelocityConstraintPoint* vcp = vc->points + j;
+ b2Vec2 P = vcp->normalImpulse * normal + vcp->tangentImpulse * tangent;
+ wA -= iA * b2Cross(vcp->rA, P);
+ vA -= mA * P;
+ wB += iB * b2Cross(vcp->rB, P);
+ vB += mB * P;
+ }
+
+ m_velocities[indexA].v = vA;
+ m_velocities[indexA].w = wA;
+ m_velocities[indexB].v = vB;
+ m_velocities[indexB].w = wB;
+ }
+}
+
+void b2ContactSolver::SolveVelocityConstraints()
+{
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2ContactVelocityConstraint* vc = m_velocityConstraints + i;
+
+ int32 indexA = vc->indexA;
+ int32 indexB = vc->indexB;
+ float mA = vc->invMassA;
+ float iA = vc->invIA;
+ float mB = vc->invMassB;
+ float iB = vc->invIB;
+ int32 pointCount = vc->pointCount;
+
+ b2Vec2 vA = m_velocities[indexA].v;
+ float wA = m_velocities[indexA].w;
+ b2Vec2 vB = m_velocities[indexB].v;
+ float wB = m_velocities[indexB].w;
+
+ b2Vec2 normal = vc->normal;
+ b2Vec2 tangent = b2Cross(normal, 1.0f);
+ float friction = vc->friction;
+
+ b2Assert(pointCount == 1 || pointCount == 2);
+
+ // Solve tangent constraints first because non-penetration is more important
+ // than friction.
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2VelocityConstraintPoint* vcp = vc->points + j;
+
+ // Relative velocity at contact
+ b2Vec2 dv = vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA);
+
+ // Compute tangent force
+ float vt = b2Dot(dv, tangent) - vc->tangentSpeed;
+ float lambda = vcp->tangentMass * (-vt);
+
+ // b2Clamp the accumulated force
+ float maxFriction = friction * vcp->normalImpulse;
+ float newImpulse = b2Clamp(vcp->tangentImpulse + lambda, -maxFriction, maxFriction);
+ lambda = newImpulse - vcp->tangentImpulse;
+ vcp->tangentImpulse = newImpulse;
+
+ // Apply contact impulse
+ b2Vec2 P = lambda * tangent;
+
+ vA -= mA * P;
+ wA -= iA * b2Cross(vcp->rA, P);
+
+ vB += mB * P;
+ wB += iB * b2Cross(vcp->rB, P);
+ }
+
+ // Solve normal constraints
+ if (pointCount == 1 || g_blockSolve == false)
+ {
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2VelocityConstraintPoint* vcp = vc->points + j;
+
+ // Relative velocity at contact
+ b2Vec2 dv = vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA);
+
+ // Compute normal impulse
+ float vn = b2Dot(dv, normal);
+ float lambda = -vcp->normalMass * (vn - vcp->velocityBias);
+
+ // b2Clamp the accumulated impulse
+ float newImpulse = b2Max(vcp->normalImpulse + lambda, 0.0f);
+ lambda = newImpulse - vcp->normalImpulse;
+ vcp->normalImpulse = newImpulse;
+
+ // Apply contact impulse
+ b2Vec2 P = lambda * normal;
+ vA -= mA * P;
+ wA -= iA * b2Cross(vcp->rA, P);
+
+ vB += mB * P;
+ wB += iB * b2Cross(vcp->rB, P);
+ }
+ }
+ else
+ {
+ // Block solver developed in collaboration with Dirk Gregorius (back in 01/07 on Box2D_Lite).
+ // Build the mini LCP for this contact patch
+ //
+ // vn = A * x + b, vn >= 0, x >= 0 and vn_i * x_i = 0 with i = 1..2
+ //
+ // A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n )
+ // b = vn0 - velocityBias
+ //
+ // The system is solved using the "Total enumeration method" (s. Murty). The complementary constraint vn_i * x_i
+ // implies that we must have in any solution either vn_i = 0 or x_i = 0. So for the 2D contact problem the cases
+ // vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and vn1 = 0 need to be tested. The first valid
+ // solution that satisfies the problem is chosen.
+ //
+ // In order to account of the accumulated impulse 'a' (because of the iterative nature of the solver which only requires
+ // that the accumulated impulse is clamped and not the incremental impulse) we change the impulse variable (x_i).
+ //
+ // Substitute:
+ //
+ // x = a + d
+ //
+ // a := old total impulse
+ // x := new total impulse
+ // d := incremental impulse
+ //
+ // For the current iteration we extend the formula for the incremental impulse
+ // to compute the new total impulse:
+ //
+ // vn = A * d + b
+ // = A * (x - a) + b
+ // = A * x + b - A * a
+ // = A * x + b'
+ // b' = b - A * a;
+
+ b2VelocityConstraintPoint* cp1 = vc->points + 0;
+ b2VelocityConstraintPoint* cp2 = vc->points + 1;
+
+ b2Vec2 a(cp1->normalImpulse, cp2->normalImpulse);
+ b2Assert(a.x >= 0.0f && a.y >= 0.0f);
+
+ // Relative velocity at contact
+ b2Vec2 dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA);
+ b2Vec2 dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA);
+
+ // Compute normal velocity
+ float vn1 = b2Dot(dv1, normal);
+ float vn2 = b2Dot(dv2, normal);
+
+ b2Vec2 b;
+ b.x = vn1 - cp1->velocityBias;
+ b.y = vn2 - cp2->velocityBias;
+
+ // Compute b'
+ b -= b2Mul(vc->K, a);
+
+ const float k_errorTol = 1e-3f;
+ B2_NOT_USED(k_errorTol);
+
+ for (;;)
+ {
+ //
+ // Case 1: vn = 0
+ //
+ // 0 = A * x + b'
+ //
+ // Solve for x:
+ //
+ // x = - inv(A) * b'
+ //
+ b2Vec2 x = - b2Mul(vc->normalMass, b);
+
+ if (x.x >= 0.0f && x.y >= 0.0f)
+ {
+ // Get the incremental impulse
+ b2Vec2 d = x - a;
+
+ // Apply incremental impulse
+ b2Vec2 P1 = d.x * normal;
+ b2Vec2 P2 = d.y * normal;
+ vA -= mA * (P1 + P2);
+ wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));
+
+ vB += mB * (P1 + P2);
+ wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));
+
+ // Accumulate
+ cp1->normalImpulse = x.x;
+ cp2->normalImpulse = x.y;
+
+#if B2_DEBUG_SOLVER == 1
+ // Postconditions
+ dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA);
+ dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA);
+
+ // Compute normal velocity
+ vn1 = b2Dot(dv1, normal);
+ vn2 = b2Dot(dv2, normal);
+
+ b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol);
+ b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol);
+#endif
+ break;
+ }
+
+ //
+ // Case 2: vn1 = 0 and x2 = 0
+ //
+ // 0 = a11 * x1 + a12 * 0 + b1'
+ // vn2 = a21 * x1 + a22 * 0 + b2'
+ //
+ x.x = - cp1->normalMass * b.x;
+ x.y = 0.0f;
+ vn1 = 0.0f;
+ vn2 = vc->K.ex.y * x.x + b.y;
+ if (x.x >= 0.0f && vn2 >= 0.0f)
+ {
+ // Get the incremental impulse
+ b2Vec2 d = x - a;
+
+ // Apply incremental impulse
+ b2Vec2 P1 = d.x * normal;
+ b2Vec2 P2 = d.y * normal;
+ vA -= mA * (P1 + P2);
+ wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));
+
+ vB += mB * (P1 + P2);
+ wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));
+
+ // Accumulate
+ cp1->normalImpulse = x.x;
+ cp2->normalImpulse = x.y;
+
+#if B2_DEBUG_SOLVER == 1
+ // Postconditions
+ dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA);
+
+ // Compute normal velocity
+ vn1 = b2Dot(dv1, normal);
+
+ b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol);
+#endif
+ break;
+ }
+
+
+ //
+ // Case 3: vn2 = 0 and x1 = 0
+ //
+ // vn1 = a11 * 0 + a12 * x2 + b1'
+ // 0 = a21 * 0 + a22 * x2 + b2'
+ //
+ x.x = 0.0f;
+ x.y = - cp2->normalMass * b.y;
+ vn1 = vc->K.ey.x * x.y + b.x;
+ vn2 = 0.0f;
+
+ if (x.y >= 0.0f && vn1 >= 0.0f)
+ {
+ // Resubstitute for the incremental impulse
+ b2Vec2 d = x - a;
+
+ // Apply incremental impulse
+ b2Vec2 P1 = d.x * normal;
+ b2Vec2 P2 = d.y * normal;
+ vA -= mA * (P1 + P2);
+ wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));
+
+ vB += mB * (P1 + P2);
+ wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));
+
+ // Accumulate
+ cp1->normalImpulse = x.x;
+ cp2->normalImpulse = x.y;
+
+#if B2_DEBUG_SOLVER == 1
+ // Postconditions
+ dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA);
+
+ // Compute normal velocity
+ vn2 = b2Dot(dv2, normal);
+
+ b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol);
+#endif
+ break;
+ }
+
+ //
+ // Case 4: x1 = 0 and x2 = 0
+ //
+ // vn1 = b1
+ // vn2 = b2;
+ x.x = 0.0f;
+ x.y = 0.0f;
+ vn1 = b.x;
+ vn2 = b.y;
+
+ if (vn1 >= 0.0f && vn2 >= 0.0f )
+ {
+ // Resubstitute for the incremental impulse
+ b2Vec2 d = x - a;
+
+ // Apply incremental impulse
+ b2Vec2 P1 = d.x * normal;
+ b2Vec2 P2 = d.y * normal;
+ vA -= mA * (P1 + P2);
+ wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2));
+
+ vB += mB * (P1 + P2);
+ wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2));
+
+ // Accumulate
+ cp1->normalImpulse = x.x;
+ cp2->normalImpulse = x.y;
+
+ break;
+ }
+
+ // No solution, give up. This is hit sometimes, but it doesn't seem to matter.
+ break;
+ }
+ }
+
+ m_velocities[indexA].v = vA;
+ m_velocities[indexA].w = wA;
+ m_velocities[indexB].v = vB;
+ m_velocities[indexB].w = wB;
+ }
+}
+
+void b2ContactSolver::StoreImpulses()
+{
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2ContactVelocityConstraint* vc = m_velocityConstraints + i;
+ b2Manifold* manifold = m_contacts[vc->contactIndex]->GetManifold();
+
+ for (int32 j = 0; j < vc->pointCount; ++j)
+ {
+ manifold->points[j].normalImpulse = vc->points[j].normalImpulse;
+ manifold->points[j].tangentImpulse = vc->points[j].tangentImpulse;
+ }
+ }
+}
+
+struct b2PositionSolverManifold
+{
+ void Initialize(b2ContactPositionConstraint* pc, const b2Transform& xfA, const b2Transform& xfB, int32 index)
+ {
+ b2Assert(pc->pointCount > 0);
+
+ switch (pc->type)
+ {
+ case b2Manifold::e_circles:
+ {
+ b2Vec2 pointA = b2Mul(xfA, pc->localPoint);
+ b2Vec2 pointB = b2Mul(xfB, pc->localPoints[0]);
+ normal = pointB - pointA;
+ normal.Normalize();
+ point = 0.5f * (pointA + pointB);
+ separation = b2Dot(pointB - pointA, normal) - pc->radiusA - pc->radiusB;
+ }
+ break;
+
+ case b2Manifold::e_faceA:
+ {
+ normal = b2Mul(xfA.q, pc->localNormal);
+ b2Vec2 planePoint = b2Mul(xfA, pc->localPoint);
+
+ b2Vec2 clipPoint = b2Mul(xfB, pc->localPoints[index]);
+ separation = b2Dot(clipPoint - planePoint, normal) - pc->radiusA - pc->radiusB;
+ point = clipPoint;
+ }
+ break;
+
+ case b2Manifold::e_faceB:
+ {
+ normal = b2Mul(xfB.q, pc->localNormal);
+ b2Vec2 planePoint = b2Mul(xfB, pc->localPoint);
+
+ b2Vec2 clipPoint = b2Mul(xfA, pc->localPoints[index]);
+ separation = b2Dot(clipPoint - planePoint, normal) - pc->radiusA - pc->radiusB;
+ point = clipPoint;
+
+ // Ensure normal points from A to B
+ normal = -normal;
+ }
+ break;
+ }
+ }
+
+ b2Vec2 normal;
+ b2Vec2 point;
+ float separation;
+};
+
+// Sequential solver.
+bool b2ContactSolver::SolvePositionConstraints()
+{
+ float minSeparation = 0.0f;
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2ContactPositionConstraint* pc = m_positionConstraints + i;
+
+ int32 indexA = pc->indexA;
+ int32 indexB = pc->indexB;
+ b2Vec2 localCenterA = pc->localCenterA;
+ float mA = pc->invMassA;
+ float iA = pc->invIA;
+ b2Vec2 localCenterB = pc->localCenterB;
+ float mB = pc->invMassB;
+ float iB = pc->invIB;
+ int32 pointCount = pc->pointCount;
+
+ b2Vec2 cA = m_positions[indexA].c;
+ float aA = m_positions[indexA].a;
+
+ b2Vec2 cB = m_positions[indexB].c;
+ float aB = m_positions[indexB].a;
+
+ // Solve normal constraints
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2Transform xfA, xfB;
+ xfA.q.Set(aA);
+ xfB.q.Set(aB);
+ xfA.p = cA - b2Mul(xfA.q, localCenterA);
+ xfB.p = cB - b2Mul(xfB.q, localCenterB);
+
+ b2PositionSolverManifold psm;
+ psm.Initialize(pc, xfA, xfB, j);
+ b2Vec2 normal = psm.normal;
+
+ b2Vec2 point = psm.point;
+ float separation = psm.separation;
+
+ b2Vec2 rA = point - cA;
+ b2Vec2 rB = point - cB;
+
+ // Track max constraint error.
+ minSeparation = b2Min(minSeparation, separation);
+
+ // Prevent large corrections and allow slop.
+ float C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f);
+
+ // Compute the effective mass.
+ float rnA = b2Cross(rA, normal);
+ float rnB = b2Cross(rB, normal);
+ float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
+
+ // Compute normal impulse
+ float impulse = K > 0.0f ? - C / K : 0.0f;
+
+ b2Vec2 P = impulse * normal;
+
+ cA -= mA * P;
+ aA -= iA * b2Cross(rA, P);
+
+ cB += mB * P;
+ aB += iB * b2Cross(rB, P);
+ }
+
+ m_positions[indexA].c = cA;
+ m_positions[indexA].a = aA;
+
+ m_positions[indexB].c = cB;
+ m_positions[indexB].a = aB;
+ }
+
+ // We can't expect minSpeparation >= -b2_linearSlop because we don't
+ // push the separation above -b2_linearSlop.
+ return minSeparation >= -3.0f * b2_linearSlop;
+}
+
+// Sequential position solver for position constraints.
+bool b2ContactSolver::SolveTOIPositionConstraints(int32 toiIndexA, int32 toiIndexB)
+{
+ float minSeparation = 0.0f;
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ b2ContactPositionConstraint* pc = m_positionConstraints + i;
+
+ int32 indexA = pc->indexA;
+ int32 indexB = pc->indexB;
+ b2Vec2 localCenterA = pc->localCenterA;
+ b2Vec2 localCenterB = pc->localCenterB;
+ int32 pointCount = pc->pointCount;
+
+ float mA = 0.0f;
+ float iA = 0.0f;
+ if (indexA == toiIndexA || indexA == toiIndexB)
+ {
+ mA = pc->invMassA;
+ iA = pc->invIA;
+ }
+
+ float mB = 0.0f;
+ float iB = 0.;
+ if (indexB == toiIndexA || indexB == toiIndexB)
+ {
+ mB = pc->invMassB;
+ iB = pc->invIB;
+ }
+
+ b2Vec2 cA = m_positions[indexA].c;
+ float aA = m_positions[indexA].a;
+
+ b2Vec2 cB = m_positions[indexB].c;
+ float aB = m_positions[indexB].a;
+
+ // Solve normal constraints
+ for (int32 j = 0; j < pointCount; ++j)
+ {
+ b2Transform xfA, xfB;
+ xfA.q.Set(aA);
+ xfB.q.Set(aB);
+ xfA.p = cA - b2Mul(xfA.q, localCenterA);
+ xfB.p = cB - b2Mul(xfB.q, localCenterB);
+
+ b2PositionSolverManifold psm;
+ psm.Initialize(pc, xfA, xfB, j);
+ b2Vec2 normal = psm.normal;
+
+ b2Vec2 point = psm.point;
+ float separation = psm.separation;
+
+ b2Vec2 rA = point - cA;
+ b2Vec2 rB = point - cB;
+
+ // Track max constraint error.
+ minSeparation = b2Min(minSeparation, separation);
+
+ // Prevent large corrections and allow slop.
+ float C = b2Clamp(b2_toiBaumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f);
+
+ // Compute the effective mass.
+ float rnA = b2Cross(rA, normal);
+ float rnB = b2Cross(rB, normal);
+ float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB;
+
+ // Compute normal impulse
+ float impulse = K > 0.0f ? - C / K : 0.0f;
+
+ b2Vec2 P = impulse * normal;
+
+ cA -= mA * P;
+ aA -= iA * b2Cross(rA, P);
+
+ cB += mB * P;
+ aB += iB * b2Cross(rB, P);
+ }
+
+ m_positions[indexA].c = cA;
+ m_positions[indexA].a = aA;
+
+ m_positions[indexB].c = cB;
+ m_positions[indexB].a = aB;
+ }
+
+ // We can't expect minSpeparation >= -b2_linearSlop because we don't
+ // push the separation above -b2_linearSlop.
+ return minSeparation >= -1.5f * b2_linearSlop;
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.h b/Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.h
new file mode 100644
index 0000000..1064738
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_contact_solver.h
@@ -0,0 +1,100 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_CONTACT_SOLVER_H
+#define B2_CONTACT_SOLVER_H
+
+#include "box2d/b2_collision.h"
+#include "box2d/b2_math.h"
+#include "box2d/b2_time_step.h"
+
+class b2Contact;
+class b2Body;
+class b2StackAllocator;
+struct b2ContactPositionConstraint;
+
+struct b2VelocityConstraintPoint
+{
+ b2Vec2 rA;
+ b2Vec2 rB;
+ float normalImpulse;
+ float tangentImpulse;
+ float normalMass;
+ float tangentMass;
+ float velocityBias;
+};
+
+struct b2ContactVelocityConstraint
+{
+ b2VelocityConstraintPoint points[b2_maxManifoldPoints];
+ b2Vec2 normal;
+ b2Mat22 normalMass;
+ b2Mat22 K;
+ int32 indexA;
+ int32 indexB;
+ float invMassA, invMassB;
+ float invIA, invIB;
+ float friction;
+ float restitution;
+ float threshold;
+ float tangentSpeed;
+ int32 pointCount;
+ int32 contactIndex;
+};
+
+struct b2ContactSolverDef
+{
+ b2TimeStep step;
+ b2Contact** contacts;
+ int32 count;
+ b2Position* positions;
+ b2Velocity* velocities;
+ b2StackAllocator* allocator;
+};
+
+class b2ContactSolver
+{
+public:
+ b2ContactSolver(b2ContactSolverDef* def);
+ ~b2ContactSolver();
+
+ void InitializeVelocityConstraints();
+
+ void WarmStart();
+ void SolveVelocityConstraints();
+ void StoreImpulses();
+
+ bool SolvePositionConstraints();
+ bool SolveTOIPositionConstraints(int32 toiIndexA, int32 toiIndexB);
+
+ b2TimeStep m_step;
+ b2Position* m_positions;
+ b2Velocity* m_velocities;
+ b2StackAllocator* m_allocator;
+ b2ContactPositionConstraint* m_positionConstraints;
+ b2ContactVelocityConstraint* m_velocityConstraints;
+ b2Contact** m_contacts;
+ int m_count;
+};
+
+#endif
+
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_distance_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_distance_joint.cpp
new file mode 100644
index 0000000..e54dbaf
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_distance_joint.cpp
@@ -0,0 +1,421 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_draw.h"
+#include "box2d/b2_distance_joint.h"
+#include "box2d/b2_time_step.h"
+
+// 1-D constrained system
+// m (v2 - v1) = lambda
+// v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass.
+// x2 = x1 + h * v2
+
+// 1-D mass-damper-spring system
+// m (v2 - v1) + h * d * v2 + h * k *
+
+// C = norm(p2 - p1) - L
+// u = (p2 - p1) / norm(p2 - p1)
+// Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
+// J = [-u -cross(r1, u) u cross(r2, u)]
+// K = J * invM * JT
+// = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
+
+
+void b2DistanceJointDef::Initialize(b2Body* b1, b2Body* b2,
+ const b2Vec2& anchor1, const b2Vec2& anchor2)
+{
+ bodyA = b1;
+ bodyB = b2;
+ localAnchorA = bodyA->GetLocalPoint(anchor1);
+ localAnchorB = bodyB->GetLocalPoint(anchor2);
+ b2Vec2 d = anchor2 - anchor1;
+ length = b2Max(d.Length(), b2_linearSlop);
+ minLength = length;
+ maxLength = length;
+}
+
+b2DistanceJoint::b2DistanceJoint(const b2DistanceJointDef* def)
+: b2Joint(def)
+{
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+ m_length = b2Max(def->length, b2_linearSlop);
+ m_minLength = b2Max(def->minLength, b2_linearSlop);
+ m_maxLength = b2Max(def->maxLength, m_minLength);
+ m_stiffness = def->stiffness;
+ m_damping = def->damping;
+
+ m_gamma = 0.0f;
+ m_bias = 0.0f;
+ m_impulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ m_currentLength = 0.0f;
+}
+
+void b2DistanceJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ m_u = cB + m_rB - cA - m_rA;
+
+ // Handle singularity.
+ m_currentLength = m_u.Length();
+ if (m_currentLength > b2_linearSlop)
+ {
+ m_u *= 1.0f / m_currentLength;
+ }
+ else
+ {
+ m_u.Set(0.0f, 0.0f);
+ m_mass = 0.0f;
+ m_impulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ float crAu = b2Cross(m_rA, m_u);
+ float crBu = b2Cross(m_rB, m_u);
+ float invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu;
+ m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;
+
+ if (m_stiffness > 0.0f && m_minLength < m_maxLength)
+ {
+ // soft
+ float C = m_currentLength - m_length;
+
+ float d = m_damping;
+ float k = m_stiffness;
+
+ // magic formulas
+ float h = data.step.dt;
+
+ // gamma = 1 / (h * (d + h * k))
+ // the extra factor of h in the denominator is since the lambda is an impulse, not a force
+ m_gamma = h * (d + h * k);
+ m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f;
+ m_bias = C * h * k * m_gamma;
+
+ invMass += m_gamma;
+ m_softMass = invMass != 0.0f ? 1.0f / invMass : 0.0f;
+ }
+ else
+ {
+ // rigid
+ m_gamma = 0.0f;
+ m_bias = 0.0f;
+ m_softMass = m_mass;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Scale the impulse to support a variable time step.
+ m_impulse *= data.step.dtRatio;
+ m_lowerImpulse *= data.step.dtRatio;
+ m_upperImpulse *= data.step.dtRatio;
+
+ b2Vec2 P = (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u;
+ vA -= m_invMassA * P;
+ wA -= m_invIA * b2Cross(m_rA, P);
+ vB += m_invMassB * P;
+ wB += m_invIB * b2Cross(m_rB, P);
+ }
+ else
+ {
+ m_impulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2DistanceJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ if (m_minLength < m_maxLength)
+ {
+ if (m_stiffness > 0.0f)
+ {
+ // Cdot = dot(u, v + cross(w, r))
+ b2Vec2 vpA = vA + b2Cross(wA, m_rA);
+ b2Vec2 vpB = vB + b2Cross(wB, m_rB);
+ float Cdot = b2Dot(m_u, vpB - vpA);
+
+ float impulse = -m_softMass * (Cdot + m_bias + m_gamma * m_impulse);
+ m_impulse += impulse;
+
+ b2Vec2 P = impulse * m_u;
+ vA -= m_invMassA * P;
+ wA -= m_invIA * b2Cross(m_rA, P);
+ vB += m_invMassB * P;
+ wB += m_invIB * b2Cross(m_rB, P);
+ }
+
+ // lower
+ {
+ float C = m_currentLength - m_minLength;
+ float bias = b2Max(0.0f, C) * data.step.inv_dt;
+
+ b2Vec2 vpA = vA + b2Cross(wA, m_rA);
+ b2Vec2 vpB = vB + b2Cross(wB, m_rB);
+ float Cdot = b2Dot(m_u, vpB - vpA);
+
+ float impulse = -m_mass * (Cdot + bias);
+ float oldImpulse = m_lowerImpulse;
+ m_lowerImpulse = b2Max(0.0f, m_lowerImpulse + impulse);
+ impulse = m_lowerImpulse - oldImpulse;
+ b2Vec2 P = impulse * m_u;
+
+ vA -= m_invMassA * P;
+ wA -= m_invIA * b2Cross(m_rA, P);
+ vB += m_invMassB * P;
+ wB += m_invIB * b2Cross(m_rB, P);
+ }
+
+ // upper
+ {
+ float C = m_maxLength - m_currentLength;
+ float bias = b2Max(0.0f, C) * data.step.inv_dt;
+
+ b2Vec2 vpA = vA + b2Cross(wA, m_rA);
+ b2Vec2 vpB = vB + b2Cross(wB, m_rB);
+ float Cdot = b2Dot(m_u, vpA - vpB);
+
+ float impulse = -m_mass * (Cdot + bias);
+ float oldImpulse = m_upperImpulse;
+ m_upperImpulse = b2Max(0.0f, m_upperImpulse + impulse);
+ impulse = m_upperImpulse - oldImpulse;
+ b2Vec2 P = -impulse * m_u;
+
+ vA -= m_invMassA * P;
+ wA -= m_invIA * b2Cross(m_rA, P);
+ vB += m_invMassB * P;
+ wB += m_invIB * b2Cross(m_rB, P);
+ }
+ }
+ else
+ {
+ // Equal limits
+
+ // Cdot = dot(u, v + cross(w, r))
+ b2Vec2 vpA = vA + b2Cross(wA, m_rA);
+ b2Vec2 vpB = vB + b2Cross(wB, m_rB);
+ float Cdot = b2Dot(m_u, vpB - vpA);
+
+ float impulse = -m_mass * Cdot;
+ m_impulse += impulse;
+
+ b2Vec2 P = impulse * m_u;
+ vA -= m_invMassA * P;
+ wA -= m_invIA * b2Cross(m_rA, P);
+ vB += m_invMassB * P;
+ wB += m_invIB * b2Cross(m_rB, P);
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2DistanceJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+
+ b2Rot qA(aA), qB(aB);
+
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ b2Vec2 u = cB + rB - cA - rA;
+
+ float length = u.Normalize();
+ float C;
+ if (m_minLength == m_maxLength)
+ {
+ C = length - m_minLength;
+ }
+ else if (length < m_minLength)
+ {
+ C = length - m_minLength;
+ }
+ else if (m_maxLength < length)
+ {
+ C = length - m_maxLength;
+ }
+ else
+ {
+ return true;
+ }
+
+ float impulse = -m_mass * C;
+ b2Vec2 P = impulse * u;
+
+ cA -= m_invMassA * P;
+ aA -= m_invIA * b2Cross(rA, P);
+ cB += m_invMassB * P;
+ aB += m_invIB * b2Cross(rB, P);
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+
+ return b2Abs(C) < b2_linearSlop;
+}
+
+b2Vec2 b2DistanceJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2DistanceJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2DistanceJoint::GetReactionForce(float inv_dt) const
+{
+ b2Vec2 F = inv_dt * (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u;
+ return F;
+}
+
+float b2DistanceJoint::GetReactionTorque(float inv_dt) const
+{
+ B2_NOT_USED(inv_dt);
+ return 0.0f;
+}
+
+float b2DistanceJoint::SetLength(float length)
+{
+ m_impulse = 0.0f;
+ m_length = b2Max(b2_linearSlop, length);
+ return m_length;
+}
+
+float b2DistanceJoint::SetMinLength(float minLength)
+{
+ m_lowerImpulse = 0.0f;
+ m_minLength = b2Clamp(minLength, b2_linearSlop, m_maxLength);
+ return m_minLength;
+}
+
+float b2DistanceJoint::SetMaxLength(float maxLength)
+{
+ m_upperImpulse = 0.0f;
+ m_maxLength = b2Max(maxLength, m_minLength);
+ return m_maxLength;
+}
+
+float b2DistanceJoint::GetCurrentLength() const
+{
+ b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA);
+ b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB);
+ b2Vec2 d = pB - pA;
+ float length = d.Length();
+ return length;
+}
+
+void b2DistanceJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2DistanceJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.length = %.9g;\n", m_length);
+ b2Dump(" jd.minLength = %.9g;\n", m_minLength);
+ b2Dump(" jd.maxLength = %.9g;\n", m_maxLength);
+ b2Dump(" jd.stiffness = %.9g;\n", m_stiffness);
+ b2Dump(" jd.damping = %.9g;\n", m_damping);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
+
+void b2DistanceJoint::Draw(b2Draw* draw) const
+{
+ const b2Transform& xfA = m_bodyA->GetTransform();
+ const b2Transform& xfB = m_bodyB->GetTransform();
+ b2Vec2 pA = b2Mul(xfA, m_localAnchorA);
+ b2Vec2 pB = b2Mul(xfB, m_localAnchorB);
+
+ b2Vec2 axis = pB - pA;
+ float length = axis.Normalize();
+
+ b2Color c1(0.7f, 0.7f, 0.7f);
+ b2Color c2(0.3f, 0.9f, 0.3f);
+ b2Color c3(0.9f, 0.3f, 0.3f);
+ b2Color c4(0.4f, 0.4f, 0.4f);
+
+ draw->DrawSegment(pA, pB, c4);
+
+ b2Vec2 pRest = pA + m_length * axis;
+ draw->DrawPoint(pRest, 8.0f, c1);
+
+ if (m_minLength != m_maxLength)
+ {
+ if (m_minLength > b2_linearSlop)
+ {
+ b2Vec2 pMin = pA + m_minLength * axis;
+ draw->DrawPoint(pMin, 4.0f, c2);
+ }
+
+ if (m_maxLength < FLT_MAX)
+ {
+ b2Vec2 pMax = pA + m_maxLength * axis;
+ draw->DrawPoint(pMax, 4.0f, c3);
+ }
+ }
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.cpp
new file mode 100644
index 0000000..8a126de
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.cpp
@@ -0,0 +1,54 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_edge_circle_contact.h"
+
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_fixture.h"
+
+#include <new>
+
+b2Contact* b2EdgeAndCircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2EdgeAndCircleContact));
+ return new (mem) b2EdgeAndCircleContact(fixtureA, fixtureB);
+}
+
+void b2EdgeAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2EdgeAndCircleContact*)contact)->~b2EdgeAndCircleContact();
+ allocator->Free(contact, sizeof(b2EdgeAndCircleContact));
+}
+
+b2EdgeAndCircleContact::b2EdgeAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+: b2Contact(fixtureA, 0, fixtureB, 0)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_edge);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);
+}
+
+void b2EdgeAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2CollideEdgeAndCircle( manifold,
+ (b2EdgeShape*)m_fixtureA->GetShape(), xfA,
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.h
new file mode 100644
index 0000000..3efc88e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_circle_contact.h
@@ -0,0 +1,43 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_EDGE_AND_CIRCLE_CONTACT_H
+#define B2_EDGE_AND_CIRCLE_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2EdgeAndCircleContact : public b2Contact
+{
+public:
+ static b2Contact* Create( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2EdgeAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2EdgeAndCircleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.cpp
new file mode 100644
index 0000000..e617e35
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.cpp
@@ -0,0 +1,54 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_edge_polygon_contact.h"
+
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_fixture.h"
+
+#include <new>
+
+b2Contact* b2EdgeAndPolygonContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2EdgeAndPolygonContact));
+ return new (mem) b2EdgeAndPolygonContact(fixtureA, fixtureB);
+}
+
+void b2EdgeAndPolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2EdgeAndPolygonContact*)contact)->~b2EdgeAndPolygonContact();
+ allocator->Free(contact, sizeof(b2EdgeAndPolygonContact));
+}
+
+b2EdgeAndPolygonContact::b2EdgeAndPolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+: b2Contact(fixtureA, 0, fixtureB, 0)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_edge);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon);
+}
+
+void b2EdgeAndPolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2CollideEdgeAndPolygon( manifold,
+ (b2EdgeShape*)m_fixtureA->GetShape(), xfA,
+ (b2PolygonShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.h
new file mode 100644
index 0000000..e6616b5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_edge_polygon_contact.h
@@ -0,0 +1,43 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_EDGE_AND_POLYGON_CONTACT_H
+#define B2_EDGE_AND_POLYGON_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2EdgeAndPolygonContact : public b2Contact
+{
+public:
+ static b2Contact* Create( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2EdgeAndPolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2EdgeAndPolygonContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_fixture.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_fixture.cpp
new file mode 100644
index 0000000..9fd700a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_fixture.cpp
@@ -0,0 +1,305 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_broad_phase.h"
+#include "box2d/b2_chain_shape.h"
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_collision.h"
+#include "box2d/b2_contact.h"
+#include "box2d/b2_edge_shape.h"
+#include "box2d/b2_polygon_shape.h"
+#include "box2d/b2_world.h"
+
+b2Fixture::b2Fixture()
+{
+ m_body = nullptr;
+ m_next = nullptr;
+ m_proxies = nullptr;
+ m_proxyCount = 0;
+ m_shape = nullptr;
+ m_density = 0.0f;
+}
+
+void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def)
+{
+ m_userData = def->userData;
+ m_friction = def->friction;
+ m_restitution = def->restitution;
+ m_restitutionThreshold = def->restitutionThreshold;
+
+ m_body = body;
+ m_next = nullptr;
+
+ m_filter = def->filter;
+
+ m_isSensor = def->isSensor;
+
+ m_shape = def->shape->Clone(allocator);
+
+ // Reserve proxy space
+ int32 childCount = m_shape->GetChildCount();
+ m_proxies = (b2FixtureProxy*)allocator->Allocate(childCount * sizeof(b2FixtureProxy));
+ for (int32 i = 0; i < childCount; ++i)
+ {
+ m_proxies[i].fixture = nullptr;
+ m_proxies[i].proxyId = b2BroadPhase::e_nullProxy;
+ }
+ m_proxyCount = 0;
+
+ m_density = def->density;
+}
+
+void b2Fixture::Destroy(b2BlockAllocator* allocator)
+{
+ // The proxies must be destroyed before calling this.
+ b2Assert(m_proxyCount == 0);
+
+ // Free the proxy array.
+ int32 childCount = m_shape->GetChildCount();
+ allocator->Free(m_proxies, childCount * sizeof(b2FixtureProxy));
+ m_proxies = nullptr;
+
+ // Free the child shape.
+ switch (m_shape->m_type)
+ {
+ case b2Shape::e_circle:
+ {
+ b2CircleShape* s = (b2CircleShape*)m_shape;
+ s->~b2CircleShape();
+ allocator->Free(s, sizeof(b2CircleShape));
+ }
+ break;
+
+ case b2Shape::e_edge:
+ {
+ b2EdgeShape* s = (b2EdgeShape*)m_shape;
+ s->~b2EdgeShape();
+ allocator->Free(s, sizeof(b2EdgeShape));
+ }
+ break;
+
+ case b2Shape::e_polygon:
+ {
+ b2PolygonShape* s = (b2PolygonShape*)m_shape;
+ s->~b2PolygonShape();
+ allocator->Free(s, sizeof(b2PolygonShape));
+ }
+ break;
+
+ case b2Shape::e_chain:
+ {
+ b2ChainShape* s = (b2ChainShape*)m_shape;
+ s->~b2ChainShape();
+ allocator->Free(s, sizeof(b2ChainShape));
+ }
+ break;
+
+ default:
+ b2Assert(false);
+ break;
+ }
+
+ m_shape = nullptr;
+}
+
+void b2Fixture::CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf)
+{
+ b2Assert(m_proxyCount == 0);
+
+ // Create proxies in the broad-phase.
+ m_proxyCount = m_shape->GetChildCount();
+
+ for (int32 i = 0; i < m_proxyCount; ++i)
+ {
+ b2FixtureProxy* proxy = m_proxies + i;
+ m_shape->ComputeAABB(&proxy->aabb, xf, i);
+ proxy->proxyId = broadPhase->CreateProxy(proxy->aabb, proxy);
+ proxy->fixture = this;
+ proxy->childIndex = i;
+ }
+}
+
+void b2Fixture::DestroyProxies(b2BroadPhase* broadPhase)
+{
+ // Destroy proxies in the broad-phase.
+ for (int32 i = 0; i < m_proxyCount; ++i)
+ {
+ b2FixtureProxy* proxy = m_proxies + i;
+ broadPhase->DestroyProxy(proxy->proxyId);
+ proxy->proxyId = b2BroadPhase::e_nullProxy;
+ }
+
+ m_proxyCount = 0;
+}
+
+void b2Fixture::Synchronize(b2BroadPhase* broadPhase, const b2Transform& transform1, const b2Transform& transform2)
+{
+ if (m_proxyCount == 0)
+ {
+ return;
+ }
+
+ for (int32 i = 0; i < m_proxyCount; ++i)
+ {
+ b2FixtureProxy* proxy = m_proxies + i;
+
+ // Compute an AABB that covers the swept shape (may miss some rotation effect).
+ b2AABB aabb1, aabb2;
+ m_shape->ComputeAABB(&aabb1, transform1, proxy->childIndex);
+ m_shape->ComputeAABB(&aabb2, transform2, proxy->childIndex);
+
+ proxy->aabb.Combine(aabb1, aabb2);
+
+ b2Vec2 displacement = aabb2.GetCenter() - aabb1.GetCenter();
+
+ broadPhase->MoveProxy(proxy->proxyId, proxy->aabb, displacement);
+ }
+}
+
+void b2Fixture::SetFilterData(const b2Filter& filter)
+{
+ m_filter = filter;
+
+ Refilter();
+}
+
+void b2Fixture::Refilter()
+{
+ if (m_body == nullptr)
+ {
+ return;
+ }
+
+ // Flag associated contacts for filtering.
+ b2ContactEdge* edge = m_body->GetContactList();
+ while (edge)
+ {
+ b2Contact* contact = edge->contact;
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+ if (fixtureA == this || fixtureB == this)
+ {
+ contact->FlagForFiltering();
+ }
+
+ edge = edge->next;
+ }
+
+ b2World* world = m_body->GetWorld();
+
+ if (world == nullptr)
+ {
+ return;
+ }
+
+ // Touch each proxy so that new pairs may be created
+ b2BroadPhase* broadPhase = &world->m_contactManager.m_broadPhase;
+ for (int32 i = 0; i < m_proxyCount; ++i)
+ {
+ broadPhase->TouchProxy(m_proxies[i].proxyId);
+ }
+}
+
+void b2Fixture::SetSensor(bool sensor)
+{
+ if (sensor != m_isSensor)
+ {
+ m_body->SetAwake(true);
+ m_isSensor = sensor;
+ }
+}
+
+void b2Fixture::Dump(int32 bodyIndex)
+{
+ b2Dump(" b2FixtureDef fd;\n");
+ b2Dump(" fd.friction = %.9g;\n", m_friction);
+ b2Dump(" fd.restitution = %.9g;\n", m_restitution);
+ b2Dump(" fd.restitutionThreshold = %.9g;\n", m_restitutionThreshold);
+ b2Dump(" fd.density = %.9g;\n", m_density);
+ b2Dump(" fd.isSensor = bool(%d);\n", m_isSensor);
+ b2Dump(" fd.filter.categoryBits = uint16(%d);\n", m_filter.categoryBits);
+ b2Dump(" fd.filter.maskBits = uint16(%d);\n", m_filter.maskBits);
+ b2Dump(" fd.filter.groupIndex = int16(%d);\n", m_filter.groupIndex);
+
+ switch (m_shape->m_type)
+ {
+ case b2Shape::e_circle:
+ {
+ b2CircleShape* s = (b2CircleShape*)m_shape;
+ b2Dump(" b2CircleShape shape;\n");
+ b2Dump(" shape.m_radius = %.9g;\n", s->m_radius);
+ b2Dump(" shape.m_p.Set(%.9g, %.9g);\n", s->m_p.x, s->m_p.y);
+ }
+ break;
+
+ case b2Shape::e_edge:
+ {
+ b2EdgeShape* s = (b2EdgeShape*)m_shape;
+ b2Dump(" b2EdgeShape shape;\n");
+ b2Dump(" shape.m_radius = %.9g;\n", s->m_radius);
+ b2Dump(" shape.m_vertex0.Set(%.9g, %.9g);\n", s->m_vertex0.x, s->m_vertex0.y);
+ b2Dump(" shape.m_vertex1.Set(%.9g, %.9g);\n", s->m_vertex1.x, s->m_vertex1.y);
+ b2Dump(" shape.m_vertex2.Set(%.9g, %.9g);\n", s->m_vertex2.x, s->m_vertex2.y);
+ b2Dump(" shape.m_vertex3.Set(%.9g, %.9g);\n", s->m_vertex3.x, s->m_vertex3.y);
+ b2Dump(" shape.m_oneSided = bool(%d);\n", s->m_oneSided);
+ }
+ break;
+
+ case b2Shape::e_polygon:
+ {
+ b2PolygonShape* s = (b2PolygonShape*)m_shape;
+ b2Dump(" b2PolygonShape shape;\n");
+ b2Dump(" b2Vec2 vs[%d];\n", b2_maxPolygonVertices);
+ for (int32 i = 0; i < s->m_count; ++i)
+ {
+ b2Dump(" vs[%d].Set(%.9g, %.9g);\n", i, s->m_vertices[i].x, s->m_vertices[i].y);
+ }
+ b2Dump(" shape.Set(vs, %d);\n", s->m_count);
+ }
+ break;
+
+ case b2Shape::e_chain:
+ {
+ b2ChainShape* s = (b2ChainShape*)m_shape;
+ b2Dump(" b2ChainShape shape;\n");
+ b2Dump(" b2Vec2 vs[%d];\n", s->m_count);
+ for (int32 i = 0; i < s->m_count; ++i)
+ {
+ b2Dump(" vs[%d].Set(%.9g, %.9g);\n", i, s->m_vertices[i].x, s->m_vertices[i].y);
+ }
+ b2Dump(" shape.CreateChain(vs, %d);\n", s->m_count);
+ b2Dump(" shape.m_prevVertex.Set(%.9g, %.9g);\n", s->m_prevVertex.x, s->m_prevVertex.y);
+ b2Dump(" shape.m_nextVertex.Set(%.9g, %.9g);\n", s->m_nextVertex.x, s->m_nextVertex.y);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ b2Dump("\n");
+ b2Dump(" fd.shape = &shape;\n");
+ b2Dump("\n");
+ b2Dump(" bodies[%d]->CreateFixture(&fd);\n", bodyIndex);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_friction_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_friction_joint.cpp
new file mode 100644
index 0000000..d9d893a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_friction_joint.cpp
@@ -0,0 +1,255 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_friction_joint.h"
+#include "box2d/b2_body.h"
+#include "box2d/b2_time_step.h"
+
+// Point-to-point constraint
+// Cdot = v2 - v1
+// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
+// J = [-I -r1_skew I r2_skew ]
+// Identity used:
+// w k % (rx i + ry j) = w * (-ry i + rx j)
+
+// Angle constraint
+// Cdot = w2 - w1
+// J = [0 0 -1 0 0 1]
+// K = invI1 + invI2
+
+void b2FrictionJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor)
+{
+ bodyA = bA;
+ bodyB = bB;
+ localAnchorA = bodyA->GetLocalPoint(anchor);
+ localAnchorB = bodyB->GetLocalPoint(anchor);
+}
+
+b2FrictionJoint::b2FrictionJoint(const b2FrictionJointDef* def)
+: b2Joint(def)
+{
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+
+ m_linearImpulse.SetZero();
+ m_angularImpulse = 0.0f;
+
+ m_maxForce = def->maxForce;
+ m_maxTorque = def->maxTorque;
+}
+
+void b2FrictionJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ // Compute the effective mass matrix.
+ m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ // J = [-I -r1_skew I r2_skew]
+ // [ 0 -1 0 1]
+ // r_skew = [-ry; rx]
+
+ // Matlab
+ // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
+ // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
+ // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ b2Mat22 K;
+ K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y;
+ K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y;
+ K.ey.x = K.ex.y;
+ K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x;
+
+ m_linearMass = K.GetInverse();
+
+ m_angularMass = iA + iB;
+ if (m_angularMass > 0.0f)
+ {
+ m_angularMass = 1.0f / m_angularMass;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Scale impulses to support a variable time step.
+ m_linearImpulse *= data.step.dtRatio;
+ m_angularImpulse *= data.step.dtRatio;
+
+ b2Vec2 P(m_linearImpulse.x, m_linearImpulse.y);
+ vA -= mA * P;
+ wA -= iA * (b2Cross(m_rA, P) + m_angularImpulse);
+ vB += mB * P;
+ wB += iB * (b2Cross(m_rB, P) + m_angularImpulse);
+ }
+ else
+ {
+ m_linearImpulse.SetZero();
+ m_angularImpulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2FrictionJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ float h = data.step.dt;
+
+ // Solve angular friction
+ {
+ float Cdot = wB - wA;
+ float impulse = -m_angularMass * Cdot;
+
+ float oldImpulse = m_angularImpulse;
+ float maxImpulse = h * m_maxTorque;
+ m_angularImpulse = b2Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse);
+ impulse = m_angularImpulse - oldImpulse;
+
+ wA -= iA * impulse;
+ wB += iB * impulse;
+ }
+
+ // Solve linear friction
+ {
+ b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA);
+
+ b2Vec2 impulse = -b2Mul(m_linearMass, Cdot);
+ b2Vec2 oldImpulse = m_linearImpulse;
+ m_linearImpulse += impulse;
+
+ float maxImpulse = h * m_maxForce;
+
+ if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse)
+ {
+ m_linearImpulse.Normalize();
+ m_linearImpulse *= maxImpulse;
+ }
+
+ impulse = m_linearImpulse - oldImpulse;
+
+ vA -= mA * impulse;
+ wA -= iA * b2Cross(m_rA, impulse);
+
+ vB += mB * impulse;
+ wB += iB * b2Cross(m_rB, impulse);
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2FrictionJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ B2_NOT_USED(data);
+
+ return true;
+}
+
+b2Vec2 b2FrictionJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2FrictionJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2FrictionJoint::GetReactionForce(float inv_dt) const
+{
+ return inv_dt * m_linearImpulse;
+}
+
+float b2FrictionJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * m_angularImpulse;
+}
+
+void b2FrictionJoint::SetMaxForce(float force)
+{
+ b2Assert(b2IsValid(force) && force >= 0.0f);
+ m_maxForce = force;
+}
+
+float b2FrictionJoint::GetMaxForce() const
+{
+ return m_maxForce;
+}
+
+void b2FrictionJoint::SetMaxTorque(float torque)
+{
+ b2Assert(b2IsValid(torque) && torque >= 0.0f);
+ m_maxTorque = torque;
+}
+
+float b2FrictionJoint::GetMaxTorque() const
+{
+ return m_maxTorque;
+}
+
+void b2FrictionJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2FrictionJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.maxForce = %.9g;\n", m_maxForce);
+ b2Dump(" jd.maxTorque = %.9g;\n", m_maxTorque);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_gear_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_gear_joint.cpp
new file mode 100644
index 0000000..ff36d3e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_gear_joint.cpp
@@ -0,0 +1,429 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_gear_joint.h"
+#include "box2d/b2_revolute_joint.h"
+#include "box2d/b2_prismatic_joint.h"
+#include "box2d/b2_body.h"
+#include "box2d/b2_time_step.h"
+
+// Gear Joint:
+// C0 = (coordinate1 + ratio * coordinate2)_initial
+// C = (coordinate1 + ratio * coordinate2) - C0 = 0
+// J = [J1 ratio * J2]
+// K = J * invM * JT
+// = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T
+//
+// Revolute:
+// coordinate = rotation
+// Cdot = angularVelocity
+// J = [0 0 1]
+// K = J * invM * JT = invI
+//
+// Prismatic:
+// coordinate = dot(p - pg, ug)
+// Cdot = dot(v + cross(w, r), ug)
+// J = [ug cross(r, ug)]
+// K = J * invM * JT = invMass + invI * cross(r, ug)^2
+
+b2GearJoint::b2GearJoint(const b2GearJointDef* def)
+: b2Joint(def)
+{
+ m_joint1 = def->joint1;
+ m_joint2 = def->joint2;
+
+ m_typeA = m_joint1->GetType();
+ m_typeB = m_joint2->GetType();
+
+ b2Assert(m_typeA == e_revoluteJoint || m_typeA == e_prismaticJoint);
+ b2Assert(m_typeB == e_revoluteJoint || m_typeB == e_prismaticJoint);
+
+ float coordinateA, coordinateB;
+
+ // TODO_ERIN there might be some problem with the joint edges in b2Joint.
+
+ m_bodyC = m_joint1->GetBodyA();
+ m_bodyA = m_joint1->GetBodyB();
+
+ // Body B on joint1 must be dynamic
+ b2Assert(m_bodyA->m_type == b2_dynamicBody);
+
+ // Get geometry of joint1
+ b2Transform xfA = m_bodyA->m_xf;
+ float aA = m_bodyA->m_sweep.a;
+ b2Transform xfC = m_bodyC->m_xf;
+ float aC = m_bodyC->m_sweep.a;
+
+ if (m_typeA == e_revoluteJoint)
+ {
+ b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint1;
+ m_localAnchorC = revolute->m_localAnchorA;
+ m_localAnchorA = revolute->m_localAnchorB;
+ m_referenceAngleA = revolute->m_referenceAngle;
+ m_localAxisC.SetZero();
+
+ coordinateA = aA - aC - m_referenceAngleA;
+ }
+ else
+ {
+ b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint1;
+ m_localAnchorC = prismatic->m_localAnchorA;
+ m_localAnchorA = prismatic->m_localAnchorB;
+ m_referenceAngleA = prismatic->m_referenceAngle;
+ m_localAxisC = prismatic->m_localXAxisA;
+
+ b2Vec2 pC = m_localAnchorC;
+ b2Vec2 pA = b2MulT(xfC.q, b2Mul(xfA.q, m_localAnchorA) + (xfA.p - xfC.p));
+ coordinateA = b2Dot(pA - pC, m_localAxisC);
+ }
+
+ m_bodyD = m_joint2->GetBodyA();
+ m_bodyB = m_joint2->GetBodyB();
+
+ // Body B on joint2 must be dynamic
+ b2Assert(m_bodyB->m_type == b2_dynamicBody);
+
+ // Get geometry of joint2
+ b2Transform xfB = m_bodyB->m_xf;
+ float aB = m_bodyB->m_sweep.a;
+ b2Transform xfD = m_bodyD->m_xf;
+ float aD = m_bodyD->m_sweep.a;
+
+ if (m_typeB == e_revoluteJoint)
+ {
+ b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint2;
+ m_localAnchorD = revolute->m_localAnchorA;
+ m_localAnchorB = revolute->m_localAnchorB;
+ m_referenceAngleB = revolute->m_referenceAngle;
+ m_localAxisD.SetZero();
+
+ coordinateB = aB - aD - m_referenceAngleB;
+ }
+ else
+ {
+ b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint2;
+ m_localAnchorD = prismatic->m_localAnchorA;
+ m_localAnchorB = prismatic->m_localAnchorB;
+ m_referenceAngleB = prismatic->m_referenceAngle;
+ m_localAxisD = prismatic->m_localXAxisA;
+
+ b2Vec2 pD = m_localAnchorD;
+ b2Vec2 pB = b2MulT(xfD.q, b2Mul(xfB.q, m_localAnchorB) + (xfB.p - xfD.p));
+ coordinateB = b2Dot(pB - pD, m_localAxisD);
+ }
+
+ m_ratio = def->ratio;
+
+ m_constant = coordinateA + m_ratio * coordinateB;
+
+ m_impulse = 0.0f;
+}
+
+void b2GearJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_indexC = m_bodyC->m_islandIndex;
+ m_indexD = m_bodyD->m_islandIndex;
+ m_lcA = m_bodyA->m_sweep.localCenter;
+ m_lcB = m_bodyB->m_sweep.localCenter;
+ m_lcC = m_bodyC->m_sweep.localCenter;
+ m_lcD = m_bodyD->m_sweep.localCenter;
+ m_mA = m_bodyA->m_invMass;
+ m_mB = m_bodyB->m_invMass;
+ m_mC = m_bodyC->m_invMass;
+ m_mD = m_bodyD->m_invMass;
+ m_iA = m_bodyA->m_invI;
+ m_iB = m_bodyB->m_invI;
+ m_iC = m_bodyC->m_invI;
+ m_iD = m_bodyD->m_invI;
+
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ float aC = data.positions[m_indexC].a;
+ b2Vec2 vC = data.velocities[m_indexC].v;
+ float wC = data.velocities[m_indexC].w;
+
+ float aD = data.positions[m_indexD].a;
+ b2Vec2 vD = data.velocities[m_indexD].v;
+ float wD = data.velocities[m_indexD].w;
+
+ b2Rot qA(aA), qB(aB), qC(aC), qD(aD);
+
+ m_mass = 0.0f;
+
+ if (m_typeA == e_revoluteJoint)
+ {
+ m_JvAC.SetZero();
+ m_JwA = 1.0f;
+ m_JwC = 1.0f;
+ m_mass += m_iA + m_iC;
+ }
+ else
+ {
+ b2Vec2 u = b2Mul(qC, m_localAxisC);
+ b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC);
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA);
+ m_JvAC = u;
+ m_JwC = b2Cross(rC, u);
+ m_JwA = b2Cross(rA, u);
+ m_mass += m_mC + m_mA + m_iC * m_JwC * m_JwC + m_iA * m_JwA * m_JwA;
+ }
+
+ if (m_typeB == e_revoluteJoint)
+ {
+ m_JvBD.SetZero();
+ m_JwB = m_ratio;
+ m_JwD = m_ratio;
+ m_mass += m_ratio * m_ratio * (m_iB + m_iD);
+ }
+ else
+ {
+ b2Vec2 u = b2Mul(qD, m_localAxisD);
+ b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB);
+ m_JvBD = m_ratio * u;
+ m_JwD = m_ratio * b2Cross(rD, u);
+ m_JwB = m_ratio * b2Cross(rB, u);
+ m_mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * m_JwD * m_JwD + m_iB * m_JwB * m_JwB;
+ }
+
+ // Compute effective mass.
+ m_mass = m_mass > 0.0f ? 1.0f / m_mass : 0.0f;
+
+ if (data.step.warmStarting)
+ {
+ vA += (m_mA * m_impulse) * m_JvAC;
+ wA += m_iA * m_impulse * m_JwA;
+ vB += (m_mB * m_impulse) * m_JvBD;
+ wB += m_iB * m_impulse * m_JwB;
+ vC -= (m_mC * m_impulse) * m_JvAC;
+ wC -= m_iC * m_impulse * m_JwC;
+ vD -= (m_mD * m_impulse) * m_JvBD;
+ wD -= m_iD * m_impulse * m_JwD;
+ }
+ else
+ {
+ m_impulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+ data.velocities[m_indexC].v = vC;
+ data.velocities[m_indexC].w = wC;
+ data.velocities[m_indexD].v = vD;
+ data.velocities[m_indexD].w = wD;
+}
+
+void b2GearJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+ b2Vec2 vC = data.velocities[m_indexC].v;
+ float wC = data.velocities[m_indexC].w;
+ b2Vec2 vD = data.velocities[m_indexD].v;
+ float wD = data.velocities[m_indexD].w;
+
+ float Cdot = b2Dot(m_JvAC, vA - vC) + b2Dot(m_JvBD, vB - vD);
+ Cdot += (m_JwA * wA - m_JwC * wC) + (m_JwB * wB - m_JwD * wD);
+
+ float impulse = -m_mass * Cdot;
+ m_impulse += impulse;
+
+ vA += (m_mA * impulse) * m_JvAC;
+ wA += m_iA * impulse * m_JwA;
+ vB += (m_mB * impulse) * m_JvBD;
+ wB += m_iB * impulse * m_JwB;
+ vC -= (m_mC * impulse) * m_JvAC;
+ wC -= m_iC * impulse * m_JwC;
+ vD -= (m_mD * impulse) * m_JvBD;
+ wD -= m_iD * impulse * m_JwD;
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+ data.velocities[m_indexC].v = vC;
+ data.velocities[m_indexC].w = wC;
+ data.velocities[m_indexD].v = vD;
+ data.velocities[m_indexD].w = wD;
+}
+
+bool b2GearJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 cC = data.positions[m_indexC].c;
+ float aC = data.positions[m_indexC].a;
+ b2Vec2 cD = data.positions[m_indexD].c;
+ float aD = data.positions[m_indexD].a;
+
+ b2Rot qA(aA), qB(aB), qC(aC), qD(aD);
+
+ float linearError = 0.0f;
+
+ float coordinateA, coordinateB;
+
+ b2Vec2 JvAC, JvBD;
+ float JwA, JwB, JwC, JwD;
+ float mass = 0.0f;
+
+ if (m_typeA == e_revoluteJoint)
+ {
+ JvAC.SetZero();
+ JwA = 1.0f;
+ JwC = 1.0f;
+ mass += m_iA + m_iC;
+
+ coordinateA = aA - aC - m_referenceAngleA;
+ }
+ else
+ {
+ b2Vec2 u = b2Mul(qC, m_localAxisC);
+ b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC);
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA);
+ JvAC = u;
+ JwC = b2Cross(rC, u);
+ JwA = b2Cross(rA, u);
+ mass += m_mC + m_mA + m_iC * JwC * JwC + m_iA * JwA * JwA;
+
+ b2Vec2 pC = m_localAnchorC - m_lcC;
+ b2Vec2 pA = b2MulT(qC, rA + (cA - cC));
+ coordinateA = b2Dot(pA - pC, m_localAxisC);
+ }
+
+ if (m_typeB == e_revoluteJoint)
+ {
+ JvBD.SetZero();
+ JwB = m_ratio;
+ JwD = m_ratio;
+ mass += m_ratio * m_ratio * (m_iB + m_iD);
+
+ coordinateB = aB - aD - m_referenceAngleB;
+ }
+ else
+ {
+ b2Vec2 u = b2Mul(qD, m_localAxisD);
+ b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB);
+ JvBD = m_ratio * u;
+ JwD = m_ratio * b2Cross(rD, u);
+ JwB = m_ratio * b2Cross(rB, u);
+ mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * JwD * JwD + m_iB * JwB * JwB;
+
+ b2Vec2 pD = m_localAnchorD - m_lcD;
+ b2Vec2 pB = b2MulT(qD, rB + (cB - cD));
+ coordinateB = b2Dot(pB - pD, m_localAxisD);
+ }
+
+ float C = (coordinateA + m_ratio * coordinateB) - m_constant;
+
+ float impulse = 0.0f;
+ if (mass > 0.0f)
+ {
+ impulse = -C / mass;
+ }
+
+ cA += m_mA * impulse * JvAC;
+ aA += m_iA * impulse * JwA;
+ cB += m_mB * impulse * JvBD;
+ aB += m_iB * impulse * JwB;
+ cC -= m_mC * impulse * JvAC;
+ aC -= m_iC * impulse * JwC;
+ cD -= m_mD * impulse * JvBD;
+ aD -= m_iD * impulse * JwD;
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+ data.positions[m_indexC].c = cC;
+ data.positions[m_indexC].a = aC;
+ data.positions[m_indexD].c = cD;
+ data.positions[m_indexD].a = aD;
+
+ // TODO_ERIN not implemented
+ return linearError < b2_linearSlop;
+}
+
+b2Vec2 b2GearJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2GearJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2GearJoint::GetReactionForce(float inv_dt) const
+{
+ b2Vec2 P = m_impulse * m_JvAC;
+ return inv_dt * P;
+}
+
+float b2GearJoint::GetReactionTorque(float inv_dt) const
+{
+ float L = m_impulse * m_JwA;
+ return inv_dt * L;
+}
+
+void b2GearJoint::SetRatio(float ratio)
+{
+ b2Assert(b2IsValid(ratio));
+ m_ratio = ratio;
+}
+
+float b2GearJoint::GetRatio() const
+{
+ return m_ratio;
+}
+
+void b2GearJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ int32 index1 = m_joint1->m_index;
+ int32 index2 = m_joint2->m_index;
+
+ b2Dump(" b2GearJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.joint1 = joints[%d];\n", index1);
+ b2Dump(" jd.joint2 = joints[%d];\n", index2);
+ b2Dump(" jd.ratio = %.9g;\n", m_ratio);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_island.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_island.cpp
new file mode 100644
index 0000000..48d89a8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_island.cpp
@@ -0,0 +1,544 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_contact.h"
+#include "box2d/b2_distance.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_joint.h"
+#include "box2d/b2_stack_allocator.h"
+#include "box2d/b2_timer.h"
+#include "box2d/b2_world.h"
+
+#include "b2_island.h"
+#include "dynamics/b2_contact_solver.h"
+
+/*
+Position Correction Notes
+=========================
+I tried the several algorithms for position correction of the 2D revolute joint.
+I looked at these systems:
+- simple pendulum (1m diameter sphere on massless 5m stick) with initial angular velocity of 100 rad/s.
+- suspension bridge with 30 1m long planks of length 1m.
+- multi-link chain with 30 1m long links.
+
+Here are the algorithms:
+
+Baumgarte - A fraction of the position error is added to the velocity error. There is no
+separate position solver.
+
+Pseudo Velocities - After the velocity solver and position integration,
+the position error, Jacobian, and effective mass are recomputed. Then
+the velocity constraints are solved with pseudo velocities and a fraction
+of the position error is added to the pseudo velocity error. The pseudo
+velocities are initialized to zero and there is no warm-starting. After
+the position solver, the pseudo velocities are added to the positions.
+This is also called the First Order World method or the Position LCP method.
+
+Modified Nonlinear Gauss-Seidel (NGS) - Like Pseudo Velocities except the
+position error is re-computed for each constraint and the positions are updated
+after the constraint is solved. The radius vectors (aka Jacobians) are
+re-computed too (otherwise the algorithm has horrible instability). The pseudo
+velocity states are not needed because they are effectively zero at the beginning
+of each iteration. Since we have the current position error, we allow the
+iterations to terminate early if the error becomes smaller than b2_linearSlop.
+
+Full NGS or just NGS - Like Modified NGS except the effective mass are re-computed
+each time a constraint is solved.
+
+Here are the results:
+Baumgarte - this is the cheapest algorithm but it has some stability problems,
+especially with the bridge. The chain links separate easily close to the root
+and they jitter as they struggle to pull together. This is one of the most common
+methods in the field. The big drawback is that the position correction artificially
+affects the momentum, thus leading to instabilities and false bounce. I used a
+bias factor of 0.2. A larger bias factor makes the bridge less stable, a smaller
+factor makes joints and contacts more spongy.
+
+Pseudo Velocities - the is more stable than the Baumgarte method. The bridge is
+stable. However, joints still separate with large angular velocities. Drag the
+simple pendulum in a circle quickly and the joint will separate. The chain separates
+easily and does not recover. I used a bias factor of 0.2. A larger value lead to
+the bridge collapsing when a heavy cube drops on it.
+
+Modified NGS - this algorithm is better in some ways than Baumgarte and Pseudo
+Velocities, but in other ways it is worse. The bridge and chain are much more
+stable, but the simple pendulum goes unstable at high angular velocities.
+
+Full NGS - stable in all tests. The joints display good stiffness. The bridge
+still sags, but this is better than infinite forces.
+
+Recommendations
+Pseudo Velocities are not really worthwhile because the bridge and chain cannot
+recover from joint separation. In other cases the benefit over Baumgarte is small.
+
+Modified NGS is not a robust method for the revolute joint due to the violent
+instability seen in the simple pendulum. Perhaps it is viable with other constraint
+types, especially scalar constraints where the effective mass is a scalar.
+
+This leaves Baumgarte and Full NGS. Baumgarte has small, but manageable instabilities
+and is very fast. I don't think we can escape Baumgarte, especially in highly
+demanding cases where high constraint fidelity is not needed.
+
+Full NGS is robust and easy on the eyes. I recommend this as an option for
+higher fidelity simulation and certainly for suspension bridges and long chains.
+Full NGS might be a good choice for ragdolls, especially motorized ragdolls where
+joint separation can be problematic. The number of NGS iterations can be reduced
+for better performance without harming robustness much.
+
+Each joint in a can be handled differently in the position solver. So I recommend
+a system where the user can select the algorithm on a per joint basis. I would
+probably default to the slower Full NGS and let the user select the faster
+Baumgarte method in performance critical scenarios.
+*/
+
+/*
+Cache Performance
+
+The Box2D solvers are dominated by cache misses. Data structures are designed
+to increase the number of cache hits. Much of misses are due to random access
+to body data. The constraint structures are iterated over linearly, which leads
+to few cache misses.
+
+The bodies are not accessed during iteration. Instead read only data, such as
+the mass values are stored with the constraints. The mutable data are the constraint
+impulses and the bodies velocities/positions. The impulses are held inside the
+constraint structures. The body velocities/positions are held in compact, temporary
+arrays to increase the number of cache hits. Linear and angular velocity are
+stored in a single array since multiple arrays lead to multiple misses.
+*/
+
+/*
+2D Rotation
+
+R = [cos(theta) -sin(theta)]
+ [sin(theta) cos(theta) ]
+
+thetaDot = omega
+
+Let q1 = cos(theta), q2 = sin(theta).
+R = [q1 -q2]
+ [q2 q1]
+
+q1Dot = -thetaDot * q2
+q2Dot = thetaDot * q1
+
+q1_new = q1_old - dt * w * q2
+q2_new = q2_old + dt * w * q1
+then normalize.
+
+This might be faster than computing sin+cos.
+However, we can compute sin+cos of the same angle fast.
+*/
+
+b2Island::b2Island(
+ int32 bodyCapacity,
+ int32 contactCapacity,
+ int32 jointCapacity,
+ b2StackAllocator* allocator,
+ b2ContactListener* listener)
+{
+ m_bodyCapacity = bodyCapacity;
+ m_contactCapacity = contactCapacity;
+ m_jointCapacity = jointCapacity;
+ m_bodyCount = 0;
+ m_contactCount = 0;
+ m_jointCount = 0;
+
+ m_allocator = allocator;
+ m_listener = listener;
+
+ m_bodies = (b2Body**)m_allocator->Allocate(bodyCapacity * sizeof(b2Body*));
+ m_contacts = (b2Contact**)m_allocator->Allocate(contactCapacity * sizeof(b2Contact*));
+ m_joints = (b2Joint**)m_allocator->Allocate(jointCapacity * sizeof(b2Joint*));
+
+ m_velocities = (b2Velocity*)m_allocator->Allocate(m_bodyCapacity * sizeof(b2Velocity));
+ m_positions = (b2Position*)m_allocator->Allocate(m_bodyCapacity * sizeof(b2Position));
+}
+
+b2Island::~b2Island()
+{
+ // Warning: the order should reverse the constructor order.
+ m_allocator->Free(m_positions);
+ m_allocator->Free(m_velocities);
+ m_allocator->Free(m_joints);
+ m_allocator->Free(m_contacts);
+ m_allocator->Free(m_bodies);
+}
+
+void b2Island::Solve(b2Profile* profile, const b2TimeStep& step, const b2Vec2& gravity, bool allowSleep)
+{
+ b2Timer timer;
+
+ float h = step.dt;
+
+ // Integrate velocities and apply damping. Initialize the body state.
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Body* b = m_bodies[i];
+
+ b2Vec2 c = b->m_sweep.c;
+ float a = b->m_sweep.a;
+ b2Vec2 v = b->m_linearVelocity;
+ float w = b->m_angularVelocity;
+
+ // Store positions for continuous collision.
+ b->m_sweep.c0 = b->m_sweep.c;
+ b->m_sweep.a0 = b->m_sweep.a;
+
+ if (b->m_type == b2_dynamicBody)
+ {
+ // Integrate velocities.
+ v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravity + b->m_force);
+ w += h * b->m_invI * b->m_torque;
+
+ // Apply damping.
+ // ODE: dv/dt + c * v = 0
+ // Solution: v(t) = v0 * exp(-c * t)
+ // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt)
+ // v2 = exp(-c * dt) * v1
+ // Pade approximation:
+ // v2 = v1 * 1 / (1 + c * dt)
+ v *= 1.0f / (1.0f + h * b->m_linearDamping);
+ w *= 1.0f / (1.0f + h * b->m_angularDamping);
+ }
+
+ m_positions[i].c = c;
+ m_positions[i].a = a;
+ m_velocities[i].v = v;
+ m_velocities[i].w = w;
+ }
+
+ timer.Reset();
+
+ // Solver data
+ b2SolverData solverData;
+ solverData.step = step;
+ solverData.positions = m_positions;
+ solverData.velocities = m_velocities;
+
+ // Initialize velocity constraints.
+ b2ContactSolverDef contactSolverDef;
+ contactSolverDef.step = step;
+ contactSolverDef.contacts = m_contacts;
+ contactSolverDef.count = m_contactCount;
+ contactSolverDef.positions = m_positions;
+ contactSolverDef.velocities = m_velocities;
+ contactSolverDef.allocator = m_allocator;
+
+ b2ContactSolver contactSolver(&contactSolverDef);
+ contactSolver.InitializeVelocityConstraints();
+
+ if (step.warmStarting)
+ {
+ contactSolver.WarmStart();
+ }
+
+ for (int32 i = 0; i < m_jointCount; ++i)
+ {
+ m_joints[i]->InitVelocityConstraints(solverData);
+ }
+
+ profile->solveInit = timer.GetMilliseconds();
+
+ // Solve velocity constraints
+ timer.Reset();
+ for (int32 i = 0; i < step.velocityIterations; ++i)
+ {
+ for (int32 j = 0; j < m_jointCount; ++j)
+ {
+ m_joints[j]->SolveVelocityConstraints(solverData);
+ }
+
+ contactSolver.SolveVelocityConstraints();
+ }
+
+ // Store impulses for warm starting
+ contactSolver.StoreImpulses();
+ profile->solveVelocity = timer.GetMilliseconds();
+
+ // Integrate positions
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Vec2 c = m_positions[i].c;
+ float a = m_positions[i].a;
+ b2Vec2 v = m_velocities[i].v;
+ float w = m_velocities[i].w;
+
+ // Check for large velocities
+ b2Vec2 translation = h * v;
+ if (b2Dot(translation, translation) > b2_maxTranslationSquared)
+ {
+ float ratio = b2_maxTranslation / translation.Length();
+ v *= ratio;
+ }
+
+ float rotation = h * w;
+ if (rotation * rotation > b2_maxRotationSquared)
+ {
+ float ratio = b2_maxRotation / b2Abs(rotation);
+ w *= ratio;
+ }
+
+ // Integrate
+ c += h * v;
+ a += h * w;
+
+ m_positions[i].c = c;
+ m_positions[i].a = a;
+ m_velocities[i].v = v;
+ m_velocities[i].w = w;
+ }
+
+ // Solve position constraints
+ timer.Reset();
+ bool positionSolved = false;
+ for (int32 i = 0; i < step.positionIterations; ++i)
+ {
+ bool contactsOkay = contactSolver.SolvePositionConstraints();
+
+ bool jointsOkay = true;
+ for (int32 j = 0; j < m_jointCount; ++j)
+ {
+ bool jointOkay = m_joints[j]->SolvePositionConstraints(solverData);
+ jointsOkay = jointsOkay && jointOkay;
+ }
+
+ if (contactsOkay && jointsOkay)
+ {
+ // Exit early if the position errors are small.
+ positionSolved = true;
+ break;
+ }
+ }
+
+ // Copy state buffers back to the bodies
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Body* body = m_bodies[i];
+ body->m_sweep.c = m_positions[i].c;
+ body->m_sweep.a = m_positions[i].a;
+ body->m_linearVelocity = m_velocities[i].v;
+ body->m_angularVelocity = m_velocities[i].w;
+ body->SynchronizeTransform();
+ }
+
+ profile->solvePosition = timer.GetMilliseconds();
+
+ Report(contactSolver.m_velocityConstraints);
+
+ if (allowSleep)
+ {
+ float minSleepTime = b2_maxFloat;
+
+ const float linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance;
+ const float angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance;
+
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Body* b = m_bodies[i];
+ if (b->GetType() == b2_staticBody)
+ {
+ continue;
+ }
+
+ if ((b->m_flags & b2Body::e_autoSleepFlag) == 0 ||
+ b->m_angularVelocity * b->m_angularVelocity > angTolSqr ||
+ b2Dot(b->m_linearVelocity, b->m_linearVelocity) > linTolSqr)
+ {
+ b->m_sleepTime = 0.0f;
+ minSleepTime = 0.0f;
+ }
+ else
+ {
+ b->m_sleepTime += h;
+ minSleepTime = b2Min(minSleepTime, b->m_sleepTime);
+ }
+ }
+
+ if (minSleepTime >= b2_timeToSleep && positionSolved)
+ {
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Body* b = m_bodies[i];
+ b->SetAwake(false);
+ }
+ }
+ }
+}
+
+void b2Island::SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB)
+{
+ b2Assert(toiIndexA < m_bodyCount);
+ b2Assert(toiIndexB < m_bodyCount);
+
+ // Initialize the body state.
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Body* b = m_bodies[i];
+ m_positions[i].c = b->m_sweep.c;
+ m_positions[i].a = b->m_sweep.a;
+ m_velocities[i].v = b->m_linearVelocity;
+ m_velocities[i].w = b->m_angularVelocity;
+ }
+
+ b2ContactSolverDef contactSolverDef;
+ contactSolverDef.contacts = m_contacts;
+ contactSolverDef.count = m_contactCount;
+ contactSolverDef.allocator = m_allocator;
+ contactSolverDef.step = subStep;
+ contactSolverDef.positions = m_positions;
+ contactSolverDef.velocities = m_velocities;
+ b2ContactSolver contactSolver(&contactSolverDef);
+
+ // Solve position constraints.
+ for (int32 i = 0; i < subStep.positionIterations; ++i)
+ {
+ bool contactsOkay = contactSolver.SolveTOIPositionConstraints(toiIndexA, toiIndexB);
+ if (contactsOkay)
+ {
+ break;
+ }
+ }
+
+#if 0
+ // Is the new position really safe?
+ for (int32 i = 0; i < m_contactCount; ++i)
+ {
+ b2Contact* c = m_contacts[i];
+ b2Fixture* fA = c->GetFixtureA();
+ b2Fixture* fB = c->GetFixtureB();
+
+ b2Body* bA = fA->GetBody();
+ b2Body* bB = fB->GetBody();
+
+ int32 indexA = c->GetChildIndexA();
+ int32 indexB = c->GetChildIndexB();
+
+ b2DistanceInput input;
+ input.proxyA.Set(fA->GetShape(), indexA);
+ input.proxyB.Set(fB->GetShape(), indexB);
+ input.transformA = bA->GetTransform();
+ input.transformB = bB->GetTransform();
+ input.useRadii = false;
+
+ b2DistanceOutput output;
+ b2SimplexCache cache;
+ cache.count = 0;
+ b2Distance(&output, &cache, &input);
+
+ if (output.distance == 0 || cache.count == 3)
+ {
+ cache.count += 0;
+ }
+ }
+#endif
+
+ // Leap of faith to new safe state.
+ m_bodies[toiIndexA]->m_sweep.c0 = m_positions[toiIndexA].c;
+ m_bodies[toiIndexA]->m_sweep.a0 = m_positions[toiIndexA].a;
+ m_bodies[toiIndexB]->m_sweep.c0 = m_positions[toiIndexB].c;
+ m_bodies[toiIndexB]->m_sweep.a0 = m_positions[toiIndexB].a;
+
+ // No warm starting is needed for TOI events because warm
+ // starting impulses were applied in the discrete solver.
+ contactSolver.InitializeVelocityConstraints();
+
+ // Solve velocity constraints.
+ for (int32 i = 0; i < subStep.velocityIterations; ++i)
+ {
+ contactSolver.SolveVelocityConstraints();
+ }
+
+ // Don't store the TOI contact forces for warm starting
+ // because they can be quite large.
+
+ float h = subStep.dt;
+
+ // Integrate positions
+ for (int32 i = 0; i < m_bodyCount; ++i)
+ {
+ b2Vec2 c = m_positions[i].c;
+ float a = m_positions[i].a;
+ b2Vec2 v = m_velocities[i].v;
+ float w = m_velocities[i].w;
+
+ // Check for large velocities
+ b2Vec2 translation = h * v;
+ if (b2Dot(translation, translation) > b2_maxTranslationSquared)
+ {
+ float ratio = b2_maxTranslation / translation.Length();
+ v *= ratio;
+ }
+
+ float rotation = h * w;
+ if (rotation * rotation > b2_maxRotationSquared)
+ {
+ float ratio = b2_maxRotation / b2Abs(rotation);
+ w *= ratio;
+ }
+
+ // Integrate
+ c += h * v;
+ a += h * w;
+
+ m_positions[i].c = c;
+ m_positions[i].a = a;
+ m_velocities[i].v = v;
+ m_velocities[i].w = w;
+
+ // Sync bodies
+ b2Body* body = m_bodies[i];
+ body->m_sweep.c = c;
+ body->m_sweep.a = a;
+ body->m_linearVelocity = v;
+ body->m_angularVelocity = w;
+ body->SynchronizeTransform();
+ }
+
+ Report(contactSolver.m_velocityConstraints);
+}
+
+void b2Island::Report(const b2ContactVelocityConstraint* constraints)
+{
+ if (m_listener == nullptr)
+ {
+ return;
+ }
+
+ for (int32 i = 0; i < m_contactCount; ++i)
+ {
+ b2Contact* c = m_contacts[i];
+
+ const b2ContactVelocityConstraint* vc = constraints + i;
+
+ b2ContactImpulse impulse;
+ impulse.count = vc->pointCount;
+ for (int32 j = 0; j < vc->pointCount; ++j)
+ {
+ impulse.normalImpulses[j] = vc->points[j].normalImpulse;
+ impulse.tangentImpulses[j] = vc->points[j].tangentImpulse;
+ }
+
+ m_listener->PostSolve(c, &impulse);
+ }
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_island.h b/Client/ThirdParty/Box2D/src/dynamics/b2_island.h
new file mode 100644
index 0000000..2e28a35
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_island.h
@@ -0,0 +1,97 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_ISLAND_H
+#define B2_ISLAND_H
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_math.h"
+#include "box2d/b2_time_step.h"
+
+class b2Contact;
+class b2Joint;
+class b2StackAllocator;
+class b2ContactListener;
+struct b2ContactVelocityConstraint;
+struct b2Profile;
+
+/// This is an internal class.
+class b2Island
+{
+public:
+ b2Island(int32 bodyCapacity, int32 contactCapacity, int32 jointCapacity,
+ b2StackAllocator* allocator, b2ContactListener* listener);
+ ~b2Island();
+
+ void Clear()
+ {
+ m_bodyCount = 0;
+ m_contactCount = 0;
+ m_jointCount = 0;
+ }
+
+ void Solve(b2Profile* profile, const b2TimeStep& step, const b2Vec2& gravity, bool allowSleep);
+
+ void SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB);
+
+ void Add(b2Body* body)
+ {
+ b2Assert(m_bodyCount < m_bodyCapacity);
+ body->m_islandIndex = m_bodyCount;
+ m_bodies[m_bodyCount] = body;
+ ++m_bodyCount;
+ }
+
+ void Add(b2Contact* contact)
+ {
+ b2Assert(m_contactCount < m_contactCapacity);
+ m_contacts[m_contactCount++] = contact;
+ }
+
+ void Add(b2Joint* joint)
+ {
+ b2Assert(m_jointCount < m_jointCapacity);
+ m_joints[m_jointCount++] = joint;
+ }
+
+ void Report(const b2ContactVelocityConstraint* constraints);
+
+ b2StackAllocator* m_allocator;
+ b2ContactListener* m_listener;
+
+ b2Body** m_bodies;
+ b2Contact** m_contacts;
+ b2Joint** m_joints;
+
+ b2Position* m_positions;
+ b2Velocity* m_velocities;
+
+ int32 m_bodyCount;
+ int32 m_jointCount;
+ int32 m_contactCount;
+
+ int32 m_bodyCapacity;
+ int32 m_contactCapacity;
+ int32 m_jointCapacity;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_joint.cpp
new file mode 100644
index 0000000..41addbb
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_joint.cpp
@@ -0,0 +1,301 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_body.h"
+#include "box2d/b2_distance_joint.h"
+#include "box2d/b2_draw.h"
+#include "box2d/b2_friction_joint.h"
+#include "box2d/b2_gear_joint.h"
+#include "box2d/b2_motor_joint.h"
+#include "box2d/b2_mouse_joint.h"
+#include "box2d/b2_prismatic_joint.h"
+#include "box2d/b2_pulley_joint.h"
+#include "box2d/b2_revolute_joint.h"
+#include "box2d/b2_weld_joint.h"
+#include "box2d/b2_wheel_joint.h"
+#include "box2d/b2_world.h"
+
+#include <new>
+
+void b2LinearStiffness(float& stiffness, float& damping,
+ float frequencyHertz, float dampingRatio,
+ const b2Body* bodyA, const b2Body* bodyB)
+{
+ float massA = bodyA->GetMass();
+ float massB = bodyB->GetMass();
+ float mass;
+ if (massA > 0.0f && massB > 0.0f)
+ {
+ mass = massA * massB / (massA + massB);
+ }
+ else if (massA > 0.0f)
+ {
+ mass = massA;
+ }
+ else
+ {
+ mass = massB;
+ }
+
+ float omega = 2.0f * b2_pi * frequencyHertz;
+ stiffness = mass * omega * omega;
+ damping = 2.0f * mass * dampingRatio * omega;
+}
+
+void b2AngularStiffness(float& stiffness, float& damping,
+ float frequencyHertz, float dampingRatio,
+ const b2Body* bodyA, const b2Body* bodyB)
+{
+ float IA = bodyA->GetInertia();
+ float IB = bodyB->GetInertia();
+ float I;
+ if (IA > 0.0f && IB > 0.0f)
+ {
+ I = IA * IB / (IA + IB);
+ }
+ else if (IA > 0.0f)
+ {
+ I = IA;
+ }
+ else
+ {
+ I = IB;
+ }
+
+ float omega = 2.0f * b2_pi * frequencyHertz;
+ stiffness = I * omega * omega;
+ damping = 2.0f * I * dampingRatio * omega;
+}
+
+b2Joint* b2Joint::Create(const b2JointDef* def, b2BlockAllocator* allocator)
+{
+ b2Joint* joint = nullptr;
+
+ switch (def->type)
+ {
+ case e_distanceJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2DistanceJoint));
+ joint = new (mem) b2DistanceJoint(static_cast<const b2DistanceJointDef*>(def));
+ }
+ break;
+
+ case e_mouseJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2MouseJoint));
+ joint = new (mem) b2MouseJoint(static_cast<const b2MouseJointDef*>(def));
+ }
+ break;
+
+ case e_prismaticJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2PrismaticJoint));
+ joint = new (mem) b2PrismaticJoint(static_cast<const b2PrismaticJointDef*>(def));
+ }
+ break;
+
+ case e_revoluteJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2RevoluteJoint));
+ joint = new (mem) b2RevoluteJoint(static_cast<const b2RevoluteJointDef*>(def));
+ }
+ break;
+
+ case e_pulleyJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2PulleyJoint));
+ joint = new (mem) b2PulleyJoint(static_cast<const b2PulleyJointDef*>(def));
+ }
+ break;
+
+ case e_gearJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2GearJoint));
+ joint = new (mem) b2GearJoint(static_cast<const b2GearJointDef*>(def));
+ }
+ break;
+
+ case e_wheelJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2WheelJoint));
+ joint = new (mem) b2WheelJoint(static_cast<const b2WheelJointDef*>(def));
+ }
+ break;
+
+ case e_weldJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2WeldJoint));
+ joint = new (mem) b2WeldJoint(static_cast<const b2WeldJointDef*>(def));
+ }
+ break;
+
+ case e_frictionJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2FrictionJoint));
+ joint = new (mem) b2FrictionJoint(static_cast<const b2FrictionJointDef*>(def));
+ }
+ break;
+
+ case e_motorJoint:
+ {
+ void* mem = allocator->Allocate(sizeof(b2MotorJoint));
+ joint = new (mem) b2MotorJoint(static_cast<const b2MotorJointDef*>(def));
+ }
+ break;
+
+ default:
+ b2Assert(false);
+ break;
+ }
+
+ return joint;
+}
+
+void b2Joint::Destroy(b2Joint* joint, b2BlockAllocator* allocator)
+{
+ joint->~b2Joint();
+ switch (joint->m_type)
+ {
+ case e_distanceJoint:
+ allocator->Free(joint, sizeof(b2DistanceJoint));
+ break;
+
+ case e_mouseJoint:
+ allocator->Free(joint, sizeof(b2MouseJoint));
+ break;
+
+ case e_prismaticJoint:
+ allocator->Free(joint, sizeof(b2PrismaticJoint));
+ break;
+
+ case e_revoluteJoint:
+ allocator->Free(joint, sizeof(b2RevoluteJoint));
+ break;
+
+ case e_pulleyJoint:
+ allocator->Free(joint, sizeof(b2PulleyJoint));
+ break;
+
+ case e_gearJoint:
+ allocator->Free(joint, sizeof(b2GearJoint));
+ break;
+
+ case e_wheelJoint:
+ allocator->Free(joint, sizeof(b2WheelJoint));
+ break;
+
+ case e_weldJoint:
+ allocator->Free(joint, sizeof(b2WeldJoint));
+ break;
+
+ case e_frictionJoint:
+ allocator->Free(joint, sizeof(b2FrictionJoint));
+ break;
+
+ case e_motorJoint:
+ allocator->Free(joint, sizeof(b2MotorJoint));
+ break;
+
+ default:
+ b2Assert(false);
+ break;
+ }
+}
+
+b2Joint::b2Joint(const b2JointDef* def)
+{
+ b2Assert(def->bodyA != def->bodyB);
+
+ m_type = def->type;
+ m_prev = nullptr;
+ m_next = nullptr;
+ m_bodyA = def->bodyA;
+ m_bodyB = def->bodyB;
+ m_index = 0;
+ m_collideConnected = def->collideConnected;
+ m_islandFlag = false;
+ m_userData = def->userData;
+
+ m_edgeA.joint = nullptr;
+ m_edgeA.other = nullptr;
+ m_edgeA.prev = nullptr;
+ m_edgeA.next = nullptr;
+
+ m_edgeB.joint = nullptr;
+ m_edgeB.other = nullptr;
+ m_edgeB.prev = nullptr;
+ m_edgeB.next = nullptr;
+}
+
+bool b2Joint::IsEnabled() const
+{
+ return m_bodyA->IsEnabled() && m_bodyB->IsEnabled();
+}
+
+void b2Joint::Draw(b2Draw* draw) const
+{
+ const b2Transform& xf1 = m_bodyA->GetTransform();
+ const b2Transform& xf2 = m_bodyB->GetTransform();
+ b2Vec2 x1 = xf1.p;
+ b2Vec2 x2 = xf2.p;
+ b2Vec2 p1 = GetAnchorA();
+ b2Vec2 p2 = GetAnchorB();
+
+ b2Color color(0.5f, 0.8f, 0.8f);
+
+ switch (m_type)
+ {
+ case e_distanceJoint:
+ draw->DrawSegment(p1, p2, color);
+ break;
+
+ case e_pulleyJoint:
+ {
+ b2PulleyJoint* pulley = (b2PulleyJoint*)this;
+ b2Vec2 s1 = pulley->GetGroundAnchorA();
+ b2Vec2 s2 = pulley->GetGroundAnchorB();
+ draw->DrawSegment(s1, p1, color);
+ draw->DrawSegment(s2, p2, color);
+ draw->DrawSegment(s1, s2, color);
+ }
+ break;
+
+ case e_mouseJoint:
+ {
+ b2Color c;
+ c.Set(0.0f, 1.0f, 0.0f);
+ draw->DrawPoint(p1, 4.0f, c);
+ draw->DrawPoint(p2, 4.0f, c);
+
+ c.Set(0.8f, 0.8f, 0.8f);
+ draw->DrawSegment(p1, p2, c);
+
+ }
+ break;
+
+ default:
+ draw->DrawSegment(x1, p1, color);
+ draw->DrawSegment(p1, p2, color);
+ draw->DrawSegment(x2, p2, color);
+ }
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_motor_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_motor_joint.cpp
new file mode 100644
index 0000000..6e0b075
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_motor_joint.cpp
@@ -0,0 +1,311 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_motor_joint.h"
+#include "box2d/b2_time_step.h"
+
+// Point-to-point constraint
+// Cdot = v2 - v1
+// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
+// J = [-I -r1_skew I r2_skew ]
+// Identity used:
+// w k % (rx i + ry j) = w * (-ry i + rx j)
+//
+// r1 = offset - c1
+// r2 = -c2
+
+// Angle constraint
+// Cdot = w2 - w1
+// J = [0 0 -1 0 0 1]
+// K = invI1 + invI2
+
+void b2MotorJointDef::Initialize(b2Body* bA, b2Body* bB)
+{
+ bodyA = bA;
+ bodyB = bB;
+ b2Vec2 xB = bodyB->GetPosition();
+ linearOffset = bodyA->GetLocalPoint(xB);
+
+ float angleA = bodyA->GetAngle();
+ float angleB = bodyB->GetAngle();
+ angularOffset = angleB - angleA;
+}
+
+b2MotorJoint::b2MotorJoint(const b2MotorJointDef* def)
+: b2Joint(def)
+{
+ m_linearOffset = def->linearOffset;
+ m_angularOffset = def->angularOffset;
+
+ m_linearImpulse.SetZero();
+ m_angularImpulse = 0.0f;
+
+ m_maxForce = def->maxForce;
+ m_maxTorque = def->maxTorque;
+ m_correctionFactor = def->correctionFactor;
+}
+
+void b2MotorJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ // Compute the effective mass matrix.
+ m_rA = b2Mul(qA, m_linearOffset - m_localCenterA);
+ m_rB = b2Mul(qB, -m_localCenterB);
+
+ // J = [-I -r1_skew I r2_skew]
+ // r_skew = [-ry; rx]
+
+ // Matlab
+ // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
+ // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
+ // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ // Upper 2 by 2 of K for point to point
+ b2Mat22 K;
+ K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y;
+ K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y;
+ K.ey.x = K.ex.y;
+ K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x;
+
+ m_linearMass = K.GetInverse();
+
+ m_angularMass = iA + iB;
+ if (m_angularMass > 0.0f)
+ {
+ m_angularMass = 1.0f / m_angularMass;
+ }
+
+ m_linearError = cB + m_rB - cA - m_rA;
+ m_angularError = aB - aA - m_angularOffset;
+
+ if (data.step.warmStarting)
+ {
+ // Scale impulses to support a variable time step.
+ m_linearImpulse *= data.step.dtRatio;
+ m_angularImpulse *= data.step.dtRatio;
+
+ b2Vec2 P(m_linearImpulse.x, m_linearImpulse.y);
+ vA -= mA * P;
+ wA -= iA * (b2Cross(m_rA, P) + m_angularImpulse);
+ vB += mB * P;
+ wB += iB * (b2Cross(m_rB, P) + m_angularImpulse);
+ }
+ else
+ {
+ m_linearImpulse.SetZero();
+ m_angularImpulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2MotorJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ float h = data.step.dt;
+ float inv_h = data.step.inv_dt;
+
+ // Solve angular friction
+ {
+ float Cdot = wB - wA + inv_h * m_correctionFactor * m_angularError;
+ float impulse = -m_angularMass * Cdot;
+
+ float oldImpulse = m_angularImpulse;
+ float maxImpulse = h * m_maxTorque;
+ m_angularImpulse = b2Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse);
+ impulse = m_angularImpulse - oldImpulse;
+
+ wA -= iA * impulse;
+ wB += iB * impulse;
+ }
+
+ // Solve linear friction
+ {
+ b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA) + inv_h * m_correctionFactor * m_linearError;
+
+ b2Vec2 impulse = -b2Mul(m_linearMass, Cdot);
+ b2Vec2 oldImpulse = m_linearImpulse;
+ m_linearImpulse += impulse;
+
+ float maxImpulse = h * m_maxForce;
+
+ if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse)
+ {
+ m_linearImpulse.Normalize();
+ m_linearImpulse *= maxImpulse;
+ }
+
+ impulse = m_linearImpulse - oldImpulse;
+
+ vA -= mA * impulse;
+ wA -= iA * b2Cross(m_rA, impulse);
+
+ vB += mB * impulse;
+ wB += iB * b2Cross(m_rB, impulse);
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2MotorJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ B2_NOT_USED(data);
+
+ return true;
+}
+
+b2Vec2 b2MotorJoint::GetAnchorA() const
+{
+ return m_bodyA->GetPosition();
+}
+
+b2Vec2 b2MotorJoint::GetAnchorB() const
+{
+ return m_bodyB->GetPosition();
+}
+
+b2Vec2 b2MotorJoint::GetReactionForce(float inv_dt) const
+{
+ return inv_dt * m_linearImpulse;
+}
+
+float b2MotorJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * m_angularImpulse;
+}
+
+void b2MotorJoint::SetMaxForce(float force)
+{
+ b2Assert(b2IsValid(force) && force >= 0.0f);
+ m_maxForce = force;
+}
+
+float b2MotorJoint::GetMaxForce() const
+{
+ return m_maxForce;
+}
+
+void b2MotorJoint::SetMaxTorque(float torque)
+{
+ b2Assert(b2IsValid(torque) && torque >= 0.0f);
+ m_maxTorque = torque;
+}
+
+float b2MotorJoint::GetMaxTorque() const
+{
+ return m_maxTorque;
+}
+
+void b2MotorJoint::SetCorrectionFactor(float factor)
+{
+ b2Assert(b2IsValid(factor) && 0.0f <= factor && factor <= 1.0f);
+ m_correctionFactor = factor;
+}
+
+float b2MotorJoint::GetCorrectionFactor() const
+{
+ return m_correctionFactor;
+}
+
+void b2MotorJoint::SetLinearOffset(const b2Vec2& linearOffset)
+{
+ if (linearOffset.x != m_linearOffset.x || linearOffset.y != m_linearOffset.y)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_linearOffset = linearOffset;
+ }
+}
+
+const b2Vec2& b2MotorJoint::GetLinearOffset() const
+{
+ return m_linearOffset;
+}
+
+void b2MotorJoint::SetAngularOffset(float angularOffset)
+{
+ if (angularOffset != m_angularOffset)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_angularOffset = angularOffset;
+ }
+}
+
+float b2MotorJoint::GetAngularOffset() const
+{
+ return m_angularOffset;
+}
+
+void b2MotorJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2MotorJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.linearOffset.Set(%.9g, %.9g);\n", m_linearOffset.x, m_linearOffset.y);
+ b2Dump(" jd.angularOffset = %.9g;\n", m_angularOffset);
+ b2Dump(" jd.maxForce = %.9g;\n", m_maxForce);
+ b2Dump(" jd.maxTorque = %.9g;\n", m_maxTorque);
+ b2Dump(" jd.correctionFactor = %.9g;\n", m_correctionFactor);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_mouse_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_mouse_joint.cpp
new file mode 100644
index 0000000..1ea6dd4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_mouse_joint.cpp
@@ -0,0 +1,192 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_mouse_joint.h"
+#include "box2d/b2_time_step.h"
+
+// p = attached point, m = mouse point
+// C = p - m
+// Cdot = v
+// = v + cross(w, r)
+// J = [I r_skew]
+// Identity used:
+// w k % (rx i + ry j) = w * (-ry i + rx j)
+
+b2MouseJoint::b2MouseJoint(const b2MouseJointDef* def)
+: b2Joint(def)
+{
+ m_targetA = def->target;
+ m_localAnchorB = b2MulT(m_bodyB->GetTransform(), m_targetA);
+ m_maxForce = def->maxForce;
+ m_stiffness = def->stiffness;
+ m_damping = def->damping;
+
+ m_impulse.SetZero();
+ m_beta = 0.0f;
+ m_gamma = 0.0f;
+}
+
+void b2MouseJoint::SetTarget(const b2Vec2& target)
+{
+ if (target != m_targetA)
+ {
+ m_bodyB->SetAwake(true);
+ m_targetA = target;
+ }
+}
+
+const b2Vec2& b2MouseJoint::GetTarget() const
+{
+ return m_targetA;
+}
+
+void b2MouseJoint::SetMaxForce(float force)
+{
+ m_maxForce = force;
+}
+
+float b2MouseJoint::GetMaxForce() const
+{
+ return m_maxForce;
+}
+
+void b2MouseJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIB = m_bodyB->m_invI;
+
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qB(aB);
+
+ float mass = m_bodyB->GetMass();
+
+ float d = m_damping;
+ float k = m_stiffness;
+
+ // magic formulas
+ // gamma has units of inverse mass.
+ // beta has units of inverse time.
+ float h = data.step.dt;
+ m_gamma = h * (d + h * k);
+ if (m_gamma != 0.0f)
+ {
+ m_gamma = 1.0f / m_gamma;
+ }
+ m_beta = h * k * m_gamma;
+
+ // Compute the effective mass matrix.
+ m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
+ // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
+ // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
+ b2Mat22 K;
+ K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma;
+ K.ex.y = -m_invIB * m_rB.x * m_rB.y;
+ K.ey.x = K.ex.y;
+ K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma;
+
+ m_mass = K.GetInverse();
+
+ m_C = cB + m_rB - m_targetA;
+ m_C *= m_beta;
+
+ // Cheat with some damping
+ wB *= 0.98f;
+
+ if (data.step.warmStarting)
+ {
+ m_impulse *= data.step.dtRatio;
+ vB += m_invMassB * m_impulse;
+ wB += m_invIB * b2Cross(m_rB, m_impulse);
+ }
+ else
+ {
+ m_impulse.SetZero();
+ }
+
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2MouseJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ // Cdot = v + cross(w, r)
+ b2Vec2 Cdot = vB + b2Cross(wB, m_rB);
+ b2Vec2 impulse = b2Mul(m_mass, -(Cdot + m_C + m_gamma * m_impulse));
+
+ b2Vec2 oldImpulse = m_impulse;
+ m_impulse += impulse;
+ float maxImpulse = data.step.dt * m_maxForce;
+ if (m_impulse.LengthSquared() > maxImpulse * maxImpulse)
+ {
+ m_impulse *= maxImpulse / m_impulse.Length();
+ }
+ impulse = m_impulse - oldImpulse;
+
+ vB += m_invMassB * impulse;
+ wB += m_invIB * b2Cross(m_rB, impulse);
+
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2MouseJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ B2_NOT_USED(data);
+ return true;
+}
+
+b2Vec2 b2MouseJoint::GetAnchorA() const
+{
+ return m_targetA;
+}
+
+b2Vec2 b2MouseJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2MouseJoint::GetReactionForce(float inv_dt) const
+{
+ return inv_dt * m_impulse;
+}
+
+float b2MouseJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * 0.0f;
+}
+
+void b2MouseJoint::ShiftOrigin(const b2Vec2& newOrigin)
+{
+ m_targetA -= newOrigin;
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.cpp
new file mode 100644
index 0000000..e4f34f5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.cpp
@@ -0,0 +1,54 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_polygon_circle_contact.h"
+
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_fixture.h"
+
+#include <new>
+
+b2Contact* b2PolygonAndCircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2PolygonAndCircleContact));
+ return new (mem) b2PolygonAndCircleContact(fixtureA, fixtureB);
+}
+
+void b2PolygonAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2PolygonAndCircleContact*)contact)->~b2PolygonAndCircleContact();
+ allocator->Free(contact, sizeof(b2PolygonAndCircleContact));
+}
+
+b2PolygonAndCircleContact::b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+: b2Contact(fixtureA, 0, fixtureB, 0)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);
+}
+
+void b2PolygonAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2CollidePolygonAndCircle( manifold,
+ (b2PolygonShape*)m_fixtureA->GetShape(), xfA,
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.h
new file mode 100644
index 0000000..6ae5425
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_circle_contact.h
@@ -0,0 +1,42 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_POLYGON_AND_CIRCLE_CONTACT_H
+#define B2_POLYGON_AND_CIRCLE_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2PolygonAndCircleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2PolygonAndCircleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.cpp
new file mode 100644
index 0000000..e92a9e8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.cpp
@@ -0,0 +1,57 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_polygon_contact.h"
+
+#include "box2d/b2_block_allocator.h"
+#include "box2d/b2_body.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_time_of_impact.h"
+#include "box2d/b2_world_callbacks.h"
+
+#include <new>
+
+b2Contact* b2PolygonContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2PolygonContact));
+ return new (mem) b2PolygonContact(fixtureA, fixtureB);
+}
+
+void b2PolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2PolygonContact*)contact)->~b2PolygonContact();
+ allocator->Free(contact, sizeof(b2PolygonContact));
+}
+
+b2PolygonContact::b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, 0, fixtureB, 0)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon);
+}
+
+void b2PolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2CollidePolygons( manifold,
+ (b2PolygonShape*)m_fixtureA->GetShape(), xfA,
+ (b2PolygonShape*)m_fixtureB->GetShape(), xfB);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.h b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.h
new file mode 100644
index 0000000..0516cb0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_polygon_contact.h
@@ -0,0 +1,43 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef B2_POLYGON_CONTACT_H
+#define B2_POLYGON_CONTACT_H
+
+#include "box2d/b2_contact.h"
+
+class b2BlockAllocator;
+
+class b2PolygonContact : public b2Contact
+{
+public:
+ static b2Contact* Create( b2Fixture* fixtureA, int32 indexA,
+ b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2PolygonContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override;
+};
+
+#endif
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_prismatic_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_prismatic_joint.cpp
new file mode 100644
index 0000000..00e7769
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_prismatic_joint.cpp
@@ -0,0 +1,643 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_draw.h"
+#include "box2d/b2_prismatic_joint.h"
+#include "box2d/b2_time_step.h"
+
+// Linear constraint (point-to-line)
+// d = p2 - p1 = x2 + r2 - x1 - r1
+// C = dot(perp, d)
+// Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1))
+// = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2)
+// J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)]
+//
+// Angular constraint
+// C = a2 - a1 + a_initial
+// Cdot = w2 - w1
+// J = [0 0 -1 0 0 1]
+//
+// K = J * invM * JT
+//
+// J = [-a -s1 a s2]
+// [0 -1 0 1]
+// a = perp
+// s1 = cross(d + r1, a) = cross(p2 - x1, a)
+// s2 = cross(r2, a) = cross(p2 - x2, a)
+
+// Motor/Limit linear constraint
+// C = dot(ax1, d)
+// Cdot = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2)
+// J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)]
+
+// Predictive limit is applied even when the limit is not active.
+// Prevents a constraint speed that can lead to a constraint error in one time step.
+// Want C2 = C1 + h * Cdot >= 0
+// Or:
+// Cdot + C1/h >= 0
+// I do not apply a negative constraint error because that is handled in position correction.
+// So:
+// Cdot + max(C1, 0)/h >= 0
+
+// Block Solver
+// We develop a block solver that includes the angular and linear constraints. This makes the limit stiffer.
+//
+// The Jacobian has 2 rows:
+// J = [-uT -s1 uT s2] // linear
+// [0 -1 0 1] // angular
+//
+// u = perp
+// s1 = cross(d + r1, u), s2 = cross(r2, u)
+// a1 = cross(d + r1, v), a2 = cross(r2, v)
+
+void b2PrismaticJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis)
+{
+ bodyA = bA;
+ bodyB = bB;
+ localAnchorA = bodyA->GetLocalPoint(anchor);
+ localAnchorB = bodyB->GetLocalPoint(anchor);
+ localAxisA = bodyA->GetLocalVector(axis);
+ referenceAngle = bodyB->GetAngle() - bodyA->GetAngle();
+}
+
+b2PrismaticJoint::b2PrismaticJoint(const b2PrismaticJointDef* def)
+: b2Joint(def)
+{
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+ m_localXAxisA = def->localAxisA;
+ m_localXAxisA.Normalize();
+ m_localYAxisA = b2Cross(1.0f, m_localXAxisA);
+ m_referenceAngle = def->referenceAngle;
+
+ m_impulse.SetZero();
+ m_axialMass = 0.0f;
+ m_motorImpulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+
+ m_lowerTranslation = def->lowerTranslation;
+ m_upperTranslation = def->upperTranslation;
+
+ b2Assert(m_lowerTranslation <= m_upperTranslation);
+
+ m_maxMotorForce = def->maxMotorForce;
+ m_motorSpeed = def->motorSpeed;
+ m_enableLimit = def->enableLimit;
+ m_enableMotor = def->enableMotor;
+
+ m_translation = 0.0f;
+ m_axis.SetZero();
+ m_perp.SetZero();
+}
+
+void b2PrismaticJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ // Compute the effective masses.
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ b2Vec2 d = (cB - cA) + rB - rA;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ // Compute motor Jacobian and effective mass.
+ {
+ m_axis = b2Mul(qA, m_localXAxisA);
+ m_a1 = b2Cross(d + rA, m_axis);
+ m_a2 = b2Cross(rB, m_axis);
+
+ m_axialMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2;
+ if (m_axialMass > 0.0f)
+ {
+ m_axialMass = 1.0f / m_axialMass;
+ }
+ }
+
+ // Prismatic constraint.
+ {
+ m_perp = b2Mul(qA, m_localYAxisA);
+
+ m_s1 = b2Cross(d + rA, m_perp);
+ m_s2 = b2Cross(rB, m_perp);
+
+ float k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2;
+ float k12 = iA * m_s1 + iB * m_s2;
+ float k22 = iA + iB;
+ if (k22 == 0.0f)
+ {
+ // For bodies with fixed rotation.
+ k22 = 1.0f;
+ }
+
+ m_K.ex.Set(k11, k12);
+ m_K.ey.Set(k12, k22);
+ }
+
+ if (m_enableLimit)
+ {
+ m_translation = b2Dot(m_axis, d);
+ }
+ else
+ {
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ if (m_enableMotor == false)
+ {
+ m_motorImpulse = 0.0f;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Account for variable time step.
+ m_impulse *= data.step.dtRatio;
+ m_motorImpulse *= data.step.dtRatio;
+ m_lowerImpulse *= data.step.dtRatio;
+ m_upperImpulse *= data.step.dtRatio;
+
+ float axialImpulse = m_motorImpulse + m_lowerImpulse - m_upperImpulse;
+ b2Vec2 P = m_impulse.x * m_perp + axialImpulse * m_axis;
+ float LA = m_impulse.x * m_s1 + m_impulse.y + axialImpulse * m_a1;
+ float LB = m_impulse.x * m_s2 + m_impulse.y + axialImpulse * m_a2;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+
+ vB += mB * P;
+ wB += iB * LB;
+ }
+ else
+ {
+ m_impulse.SetZero();
+ m_motorImpulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2PrismaticJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ // Solve linear motor constraint
+ if (m_enableMotor)
+ {
+ float Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
+ float impulse = m_axialMass * (m_motorSpeed - Cdot);
+ float oldImpulse = m_motorImpulse;
+ float maxImpulse = data.step.dt * m_maxMotorForce;
+ m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
+ impulse = m_motorImpulse - oldImpulse;
+
+ b2Vec2 P = impulse * m_axis;
+ float LA = impulse * m_a1;
+ float LB = impulse * m_a2;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+ vB += mB * P;
+ wB += iB * LB;
+ }
+
+ if (m_enableLimit)
+ {
+ // Lower limit
+ {
+ float C = m_translation - m_lowerTranslation;
+ float Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA;
+ float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt);
+ float oldImpulse = m_lowerImpulse;
+ m_lowerImpulse = b2Max(m_lowerImpulse + impulse, 0.0f);
+ impulse = m_lowerImpulse - oldImpulse;
+
+ b2Vec2 P = impulse * m_axis;
+ float LA = impulse * m_a1;
+ float LB = impulse * m_a2;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+ vB += mB * P;
+ wB += iB * LB;
+ }
+
+ // Upper limit
+ // Note: signs are flipped to keep C positive when the constraint is satisfied.
+ // This also keeps the impulse positive when the limit is active.
+ {
+ float C = m_upperTranslation - m_translation;
+ float Cdot = b2Dot(m_axis, vA - vB) + m_a1 * wA - m_a2 * wB;
+ float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt);
+ float oldImpulse = m_upperImpulse;
+ m_upperImpulse = b2Max(m_upperImpulse + impulse, 0.0f);
+ impulse = m_upperImpulse - oldImpulse;
+
+ b2Vec2 P = impulse * m_axis;
+ float LA = impulse * m_a1;
+ float LB = impulse * m_a2;
+
+ vA += mA * P;
+ wA += iA * LA;
+ vB -= mB * P;
+ wB -= iB * LB;
+ }
+ }
+
+ // Solve the prismatic constraint in block form.
+ {
+ b2Vec2 Cdot;
+ Cdot.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA;
+ Cdot.y = wB - wA;
+
+ b2Vec2 df = m_K.Solve(-Cdot);
+ m_impulse += df;
+
+ b2Vec2 P = df.x * m_perp;
+ float LA = df.x * m_s1 + df.y;
+ float LB = df.x * m_s2 + df.y;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+
+ vB += mB * P;
+ wB += iB * LB;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+// A velocity based solver computes reaction forces(impulses) using the velocity constraint solver.Under this context,
+// the position solver is not there to resolve forces.It is only there to cope with integration error.
+//
+// Therefore, the pseudo impulses in the position solver do not have any physical meaning.Thus it is okay if they suck.
+//
+// We could take the active state from the velocity solver.However, the joint might push past the limit when the velocity
+// solver indicates the limit is inactive.
+bool b2PrismaticJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+
+ b2Rot qA(aA), qB(aB);
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ // Compute fresh Jacobians
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ b2Vec2 d = cB + rB - cA - rA;
+
+ b2Vec2 axis = b2Mul(qA, m_localXAxisA);
+ float a1 = b2Cross(d + rA, axis);
+ float a2 = b2Cross(rB, axis);
+ b2Vec2 perp = b2Mul(qA, m_localYAxisA);
+
+ float s1 = b2Cross(d + rA, perp);
+ float s2 = b2Cross(rB, perp);
+
+ b2Vec3 impulse;
+ b2Vec2 C1;
+ C1.x = b2Dot(perp, d);
+ C1.y = aB - aA - m_referenceAngle;
+
+ float linearError = b2Abs(C1.x);
+ float angularError = b2Abs(C1.y);
+
+ bool active = false;
+ float C2 = 0.0f;
+ if (m_enableLimit)
+ {
+ float translation = b2Dot(axis, d);
+ if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop)
+ {
+ C2 = translation;
+ linearError = b2Max(linearError, b2Abs(translation));
+ active = true;
+ }
+ else if (translation <= m_lowerTranslation)
+ {
+ C2 = b2Min(translation - m_lowerTranslation, 0.0f);
+ linearError = b2Max(linearError, m_lowerTranslation - translation);
+ active = true;
+ }
+ else if (translation >= m_upperTranslation)
+ {
+ C2 = b2Max(translation - m_upperTranslation, 0.0f);
+ linearError = b2Max(linearError, translation - m_upperTranslation);
+ active = true;
+ }
+ }
+
+ if (active)
+ {
+ float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
+ float k12 = iA * s1 + iB * s2;
+ float k13 = iA * s1 * a1 + iB * s2 * a2;
+ float k22 = iA + iB;
+ if (k22 == 0.0f)
+ {
+ // For fixed rotation
+ k22 = 1.0f;
+ }
+ float k23 = iA * a1 + iB * a2;
+ float k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2;
+
+ b2Mat33 K;
+ K.ex.Set(k11, k12, k13);
+ K.ey.Set(k12, k22, k23);
+ K.ez.Set(k13, k23, k33);
+
+ b2Vec3 C;
+ C.x = C1.x;
+ C.y = C1.y;
+ C.z = C2;
+
+ impulse = K.Solve33(-C);
+ }
+ else
+ {
+ float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2;
+ float k12 = iA * s1 + iB * s2;
+ float k22 = iA + iB;
+ if (k22 == 0.0f)
+ {
+ k22 = 1.0f;
+ }
+
+ b2Mat22 K;
+ K.ex.Set(k11, k12);
+ K.ey.Set(k12, k22);
+
+ b2Vec2 impulse1 = K.Solve(-C1);
+ impulse.x = impulse1.x;
+ impulse.y = impulse1.y;
+ impulse.z = 0.0f;
+ }
+
+ b2Vec2 P = impulse.x * perp + impulse.z * axis;
+ float LA = impulse.x * s1 + impulse.y + impulse.z * a1;
+ float LB = impulse.x * s2 + impulse.y + impulse.z * a2;
+
+ cA -= mA * P;
+ aA -= iA * LA;
+ cB += mB * P;
+ aB += iB * LB;
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+
+ return linearError <= b2_linearSlop && angularError <= b2_angularSlop;
+}
+
+b2Vec2 b2PrismaticJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2PrismaticJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2PrismaticJoint::GetReactionForce(float inv_dt) const
+{
+ return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_lowerImpulse - m_upperImpulse) * m_axis);
+}
+
+float b2PrismaticJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * m_impulse.y;
+}
+
+float b2PrismaticJoint::GetJointTranslation() const
+{
+ b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA);
+ b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB);
+ b2Vec2 d = pB - pA;
+ b2Vec2 axis = m_bodyA->GetWorldVector(m_localXAxisA);
+
+ float translation = b2Dot(d, axis);
+ return translation;
+}
+
+float b2PrismaticJoint::GetJointSpeed() const
+{
+ b2Body* bA = m_bodyA;
+ b2Body* bB = m_bodyB;
+
+ b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter);
+ b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter);
+ b2Vec2 p1 = bA->m_sweep.c + rA;
+ b2Vec2 p2 = bB->m_sweep.c + rB;
+ b2Vec2 d = p2 - p1;
+ b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA);
+
+ b2Vec2 vA = bA->m_linearVelocity;
+ b2Vec2 vB = bB->m_linearVelocity;
+ float wA = bA->m_angularVelocity;
+ float wB = bB->m_angularVelocity;
+
+ float speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA));
+ return speed;
+}
+
+bool b2PrismaticJoint::IsLimitEnabled() const
+{
+ return m_enableLimit;
+}
+
+void b2PrismaticJoint::EnableLimit(bool flag)
+{
+ if (flag != m_enableLimit)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_enableLimit = flag;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+}
+
+float b2PrismaticJoint::GetLowerLimit() const
+{
+ return m_lowerTranslation;
+}
+
+float b2PrismaticJoint::GetUpperLimit() const
+{
+ return m_upperTranslation;
+}
+
+void b2PrismaticJoint::SetLimits(float lower, float upper)
+{
+ b2Assert(lower <= upper);
+ if (lower != m_lowerTranslation || upper != m_upperTranslation)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_lowerTranslation = lower;
+ m_upperTranslation = upper;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+}
+
+bool b2PrismaticJoint::IsMotorEnabled() const
+{
+ return m_enableMotor;
+}
+
+void b2PrismaticJoint::EnableMotor(bool flag)
+{
+ if (flag != m_enableMotor)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_enableMotor = flag;
+ }
+}
+
+void b2PrismaticJoint::SetMotorSpeed(float speed)
+{
+ if (speed != m_motorSpeed)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_motorSpeed = speed;
+ }
+}
+
+void b2PrismaticJoint::SetMaxMotorForce(float force)
+{
+ if (force != m_maxMotorForce)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_maxMotorForce = force;
+ }
+}
+
+float b2PrismaticJoint::GetMotorForce(float inv_dt) const
+{
+ return inv_dt * m_motorImpulse;
+}
+
+void b2PrismaticJoint::Dump()
+{
+ // FLT_DECIMAL_DIG == 9
+
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2PrismaticJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.localAxisA.Set(%.9g, %.9g);\n", m_localXAxisA.x, m_localXAxisA.y);
+ b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle);
+ b2Dump(" jd.enableLimit = bool(%d);\n", m_enableLimit);
+ b2Dump(" jd.lowerTranslation = %.9g;\n", m_lowerTranslation);
+ b2Dump(" jd.upperTranslation = %.9g;\n", m_upperTranslation);
+ b2Dump(" jd.enableMotor = bool(%d);\n", m_enableMotor);
+ b2Dump(" jd.motorSpeed = %.9g;\n", m_motorSpeed);
+ b2Dump(" jd.maxMotorForce = %.9g;\n", m_maxMotorForce);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
+
+void b2PrismaticJoint::Draw(b2Draw* draw) const
+{
+ const b2Transform& xfA = m_bodyA->GetTransform();
+ const b2Transform& xfB = m_bodyB->GetTransform();
+ b2Vec2 pA = b2Mul(xfA, m_localAnchorA);
+ b2Vec2 pB = b2Mul(xfB, m_localAnchorB);
+
+ b2Vec2 axis = b2Mul(xfA.q, m_localXAxisA);
+
+ b2Color c1(0.7f, 0.7f, 0.7f);
+ b2Color c2(0.3f, 0.9f, 0.3f);
+ b2Color c3(0.9f, 0.3f, 0.3f);
+ b2Color c4(0.3f, 0.3f, 0.9f);
+ b2Color c5(0.4f, 0.4f, 0.4f);
+
+ draw->DrawSegment(pA, pB, c5);
+
+ if (m_enableLimit)
+ {
+ b2Vec2 lower = pA + m_lowerTranslation * axis;
+ b2Vec2 upper = pA + m_upperTranslation * axis;
+ b2Vec2 perp = b2Mul(xfA.q, m_localYAxisA);
+ draw->DrawSegment(lower, upper, c1);
+ draw->DrawSegment(lower - 0.5f * perp, lower + 0.5f * perp, c2);
+ draw->DrawSegment(upper - 0.5f * perp, upper + 0.5f * perp, c3);
+ }
+ else
+ {
+ draw->DrawSegment(pA - 1.0f * axis, pA + 1.0f * axis, c1);
+ }
+
+ draw->DrawPoint(pA, 5.0f, c1);
+ draw->DrawPoint(pB, 5.0f, c4);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_pulley_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_pulley_joint.cpp
new file mode 100644
index 0000000..099e57e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_pulley_joint.cpp
@@ -0,0 +1,352 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_pulley_joint.h"
+#include "box2d/b2_time_step.h"
+
+// Pulley:
+// length1 = norm(p1 - s1)
+// length2 = norm(p2 - s2)
+// C0 = (length1 + ratio * length2)_initial
+// C = C0 - (length1 + ratio * length2)
+// u1 = (p1 - s1) / norm(p1 - s1)
+// u2 = (p2 - s2) / norm(p2 - s2)
+// Cdot = -dot(u1, v1 + cross(w1, r1)) - ratio * dot(u2, v2 + cross(w2, r2))
+// J = -[u1 cross(r1, u1) ratio * u2 ratio * cross(r2, u2)]
+// K = J * invM * JT
+// = invMass1 + invI1 * cross(r1, u1)^2 + ratio^2 * (invMass2 + invI2 * cross(r2, u2)^2)
+
+void b2PulleyJointDef::Initialize(b2Body* bA, b2Body* bB,
+ const b2Vec2& groundA, const b2Vec2& groundB,
+ const b2Vec2& anchorA, const b2Vec2& anchorB,
+ float r)
+{
+ bodyA = bA;
+ bodyB = bB;
+ groundAnchorA = groundA;
+ groundAnchorB = groundB;
+ localAnchorA = bodyA->GetLocalPoint(anchorA);
+ localAnchorB = bodyB->GetLocalPoint(anchorB);
+ b2Vec2 dA = anchorA - groundA;
+ lengthA = dA.Length();
+ b2Vec2 dB = anchorB - groundB;
+ lengthB = dB.Length();
+ ratio = r;
+ b2Assert(ratio > b2_epsilon);
+}
+
+b2PulleyJoint::b2PulleyJoint(const b2PulleyJointDef* def)
+: b2Joint(def)
+{
+ m_groundAnchorA = def->groundAnchorA;
+ m_groundAnchorB = def->groundAnchorB;
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+
+ m_lengthA = def->lengthA;
+ m_lengthB = def->lengthB;
+
+ b2Assert(def->ratio != 0.0f);
+ m_ratio = def->ratio;
+
+ m_constant = def->lengthA + m_ratio * def->lengthB;
+
+ m_impulse = 0.0f;
+}
+
+void b2PulleyJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ // Get the pulley axes.
+ m_uA = cA + m_rA - m_groundAnchorA;
+ m_uB = cB + m_rB - m_groundAnchorB;
+
+ float lengthA = m_uA.Length();
+ float lengthB = m_uB.Length();
+
+ if (lengthA > 10.0f * b2_linearSlop)
+ {
+ m_uA *= 1.0f / lengthA;
+ }
+ else
+ {
+ m_uA.SetZero();
+ }
+
+ if (lengthB > 10.0f * b2_linearSlop)
+ {
+ m_uB *= 1.0f / lengthB;
+ }
+ else
+ {
+ m_uB.SetZero();
+ }
+
+ // Compute effective mass.
+ float ruA = b2Cross(m_rA, m_uA);
+ float ruB = b2Cross(m_rB, m_uB);
+
+ float mA = m_invMassA + m_invIA * ruA * ruA;
+ float mB = m_invMassB + m_invIB * ruB * ruB;
+
+ m_mass = mA + m_ratio * m_ratio * mB;
+
+ if (m_mass > 0.0f)
+ {
+ m_mass = 1.0f / m_mass;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Scale impulses to support variable time steps.
+ m_impulse *= data.step.dtRatio;
+
+ // Warm starting.
+ b2Vec2 PA = -(m_impulse) * m_uA;
+ b2Vec2 PB = (-m_ratio * m_impulse) * m_uB;
+
+ vA += m_invMassA * PA;
+ wA += m_invIA * b2Cross(m_rA, PA);
+ vB += m_invMassB * PB;
+ wB += m_invIB * b2Cross(m_rB, PB);
+ }
+ else
+ {
+ m_impulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2PulleyJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Vec2 vpA = vA + b2Cross(wA, m_rA);
+ b2Vec2 vpB = vB + b2Cross(wB, m_rB);
+
+ float Cdot = -b2Dot(m_uA, vpA) - m_ratio * b2Dot(m_uB, vpB);
+ float impulse = -m_mass * Cdot;
+ m_impulse += impulse;
+
+ b2Vec2 PA = -impulse * m_uA;
+ b2Vec2 PB = -m_ratio * impulse * m_uB;
+ vA += m_invMassA * PA;
+ wA += m_invIA * b2Cross(m_rA, PA);
+ vB += m_invMassB * PB;
+ wB += m_invIB * b2Cross(m_rB, PB);
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2PulleyJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+
+ b2Rot qA(aA), qB(aB);
+
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ // Get the pulley axes.
+ b2Vec2 uA = cA + rA - m_groundAnchorA;
+ b2Vec2 uB = cB + rB - m_groundAnchorB;
+
+ float lengthA = uA.Length();
+ float lengthB = uB.Length();
+
+ if (lengthA > 10.0f * b2_linearSlop)
+ {
+ uA *= 1.0f / lengthA;
+ }
+ else
+ {
+ uA.SetZero();
+ }
+
+ if (lengthB > 10.0f * b2_linearSlop)
+ {
+ uB *= 1.0f / lengthB;
+ }
+ else
+ {
+ uB.SetZero();
+ }
+
+ // Compute effective mass.
+ float ruA = b2Cross(rA, uA);
+ float ruB = b2Cross(rB, uB);
+
+ float mA = m_invMassA + m_invIA * ruA * ruA;
+ float mB = m_invMassB + m_invIB * ruB * ruB;
+
+ float mass = mA + m_ratio * m_ratio * mB;
+
+ if (mass > 0.0f)
+ {
+ mass = 1.0f / mass;
+ }
+
+ float C = m_constant - lengthA - m_ratio * lengthB;
+ float linearError = b2Abs(C);
+
+ float impulse = -mass * C;
+
+ b2Vec2 PA = -impulse * uA;
+ b2Vec2 PB = -m_ratio * impulse * uB;
+
+ cA += m_invMassA * PA;
+ aA += m_invIA * b2Cross(rA, PA);
+ cB += m_invMassB * PB;
+ aB += m_invIB * b2Cross(rB, PB);
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+
+ return linearError < b2_linearSlop;
+}
+
+b2Vec2 b2PulleyJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2PulleyJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2PulleyJoint::GetReactionForce(float inv_dt) const
+{
+ b2Vec2 P = m_impulse * m_uB;
+ return inv_dt * P;
+}
+
+float b2PulleyJoint::GetReactionTorque(float inv_dt) const
+{
+ B2_NOT_USED(inv_dt);
+ return 0.0f;
+}
+
+b2Vec2 b2PulleyJoint::GetGroundAnchorA() const
+{
+ return m_groundAnchorA;
+}
+
+b2Vec2 b2PulleyJoint::GetGroundAnchorB() const
+{
+ return m_groundAnchorB;
+}
+
+float b2PulleyJoint::GetLengthA() const
+{
+ return m_lengthA;
+}
+
+float b2PulleyJoint::GetLengthB() const
+{
+ return m_lengthB;
+}
+
+float b2PulleyJoint::GetRatio() const
+{
+ return m_ratio;
+}
+
+float b2PulleyJoint::GetCurrentLengthA() const
+{
+ b2Vec2 p = m_bodyA->GetWorldPoint(m_localAnchorA);
+ b2Vec2 s = m_groundAnchorA;
+ b2Vec2 d = p - s;
+ return d.Length();
+}
+
+float b2PulleyJoint::GetCurrentLengthB() const
+{
+ b2Vec2 p = m_bodyB->GetWorldPoint(m_localAnchorB);
+ b2Vec2 s = m_groundAnchorB;
+ b2Vec2 d = p - s;
+ return d.Length();
+}
+
+void b2PulleyJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2PulleyJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.groundAnchorA.Set(%.9g, %.9g);\n", m_groundAnchorA.x, m_groundAnchorA.y);
+ b2Dump(" jd.groundAnchorB.Set(%.9g, %.9g);\n", m_groundAnchorB.x, m_groundAnchorB.y);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.lengthA = %.9g;\n", m_lengthA);
+ b2Dump(" jd.lengthB = %.9g;\n", m_lengthB);
+ b2Dump(" jd.ratio = %.9g;\n", m_ratio);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
+
+void b2PulleyJoint::ShiftOrigin(const b2Vec2& newOrigin)
+{
+ m_groundAnchorA -= newOrigin;
+ m_groundAnchorB -= newOrigin;
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_revolute_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_revolute_joint.cpp
new file mode 100644
index 0000000..f7cc4cc
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_revolute_joint.cpp
@@ -0,0 +1,501 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_draw.h"
+#include "box2d/b2_revolute_joint.h"
+#include "box2d/b2_time_step.h"
+
+// Point-to-point constraint
+// C = p2 - p1
+// Cdot = v2 - v1
+// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
+// J = [-I -r1_skew I r2_skew ]
+// Identity used:
+// w k % (rx i + ry j) = w * (-ry i + rx j)
+
+// Motor constraint
+// Cdot = w2 - w1
+// J = [0 0 -1 0 0 1]
+// K = invI1 + invI2
+
+void b2RevoluteJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor)
+{
+ bodyA = bA;
+ bodyB = bB;
+ localAnchorA = bodyA->GetLocalPoint(anchor);
+ localAnchorB = bodyB->GetLocalPoint(anchor);
+ referenceAngle = bodyB->GetAngle() - bodyA->GetAngle();
+}
+
+b2RevoluteJoint::b2RevoluteJoint(const b2RevoluteJointDef* def)
+: b2Joint(def)
+{
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+ m_referenceAngle = def->referenceAngle;
+
+ m_impulse.SetZero();
+ m_axialMass = 0.0f;
+ m_motorImpulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+
+ m_lowerAngle = def->lowerAngle;
+ m_upperAngle = def->upperAngle;
+ m_maxMotorTorque = def->maxMotorTorque;
+ m_motorSpeed = def->motorSpeed;
+ m_enableLimit = def->enableLimit;
+ m_enableMotor = def->enableMotor;
+
+ m_angle = 0.0f;
+}
+
+void b2RevoluteJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ // J = [-I -r1_skew I r2_skew]
+ // r_skew = [-ry; rx]
+
+ // Matlab
+ // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x]
+ // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB]
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ m_K.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB;
+ m_K.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB;
+ m_K.ex.y = m_K.ey.x;
+ m_K.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB;
+
+ m_axialMass = iA + iB;
+ bool fixedRotation;
+ if (m_axialMass > 0.0f)
+ {
+ m_axialMass = 1.0f / m_axialMass;
+ fixedRotation = false;
+ }
+ else
+ {
+ fixedRotation = true;
+ }
+
+ m_angle = aB - aA - m_referenceAngle;
+ if (m_enableLimit == false || fixedRotation)
+ {
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ if (m_enableMotor == false || fixedRotation)
+ {
+ m_motorImpulse = 0.0f;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Scale impulses to support a variable time step.
+ m_impulse *= data.step.dtRatio;
+ m_motorImpulse *= data.step.dtRatio;
+ m_lowerImpulse *= data.step.dtRatio;
+ m_upperImpulse *= data.step.dtRatio;
+
+ float axialImpulse = m_motorImpulse + m_lowerImpulse - m_upperImpulse;
+ b2Vec2 P(m_impulse.x, m_impulse.y);
+
+ vA -= mA * P;
+ wA -= iA * (b2Cross(m_rA, P) + axialImpulse);
+
+ vB += mB * P;
+ wB += iB * (b2Cross(m_rB, P) + axialImpulse);
+ }
+ else
+ {
+ m_impulse.SetZero();
+ m_motorImpulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2RevoluteJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ bool fixedRotation = (iA + iB == 0.0f);
+
+ // Solve motor constraint.
+ if (m_enableMotor && fixedRotation == false)
+ {
+ float Cdot = wB - wA - m_motorSpeed;
+ float impulse = -m_axialMass * Cdot;
+ float oldImpulse = m_motorImpulse;
+ float maxImpulse = data.step.dt * m_maxMotorTorque;
+ m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
+ impulse = m_motorImpulse - oldImpulse;
+
+ wA -= iA * impulse;
+ wB += iB * impulse;
+ }
+
+ if (m_enableLimit && fixedRotation == false)
+ {
+ // Lower limit
+ {
+ float C = m_angle - m_lowerAngle;
+ float Cdot = wB - wA;
+ float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt);
+ float oldImpulse = m_lowerImpulse;
+ m_lowerImpulse = b2Max(m_lowerImpulse + impulse, 0.0f);
+ impulse = m_lowerImpulse - oldImpulse;
+
+ wA -= iA * impulse;
+ wB += iB * impulse;
+ }
+
+ // Upper limit
+ // Note: signs are flipped to keep C positive when the constraint is satisfied.
+ // This also keeps the impulse positive when the limit is active.
+ {
+ float C = m_upperAngle - m_angle;
+ float Cdot = wA - wB;
+ float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt);
+ float oldImpulse = m_upperImpulse;
+ m_upperImpulse = b2Max(m_upperImpulse + impulse, 0.0f);
+ impulse = m_upperImpulse - oldImpulse;
+
+ wA += iA * impulse;
+ wB -= iB * impulse;
+ }
+ }
+
+ // Solve point-to-point constraint
+ {
+ b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA);
+ b2Vec2 impulse = m_K.Solve(-Cdot);
+
+ m_impulse.x += impulse.x;
+ m_impulse.y += impulse.y;
+
+ vA -= mA * impulse;
+ wA -= iA * b2Cross(m_rA, impulse);
+
+ vB += mB * impulse;
+ wB += iB * b2Cross(m_rB, impulse);
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2RevoluteJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+
+ b2Rot qA(aA), qB(aB);
+
+ float angularError = 0.0f;
+ float positionError = 0.0f;
+
+ bool fixedRotation = (m_invIA + m_invIB == 0.0f);
+
+ // Solve angular limit constraint
+ if (m_enableLimit && fixedRotation == false)
+ {
+ float angle = aB - aA - m_referenceAngle;
+ float C = 0.0f;
+
+ if (b2Abs(m_upperAngle - m_lowerAngle) < 2.0f * b2_angularSlop)
+ {
+ // Prevent large angular corrections
+ C = b2Clamp(angle - m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection);
+ }
+ else if (angle <= m_lowerAngle)
+ {
+ // Prevent large angular corrections and allow some slop.
+ C = b2Clamp(angle - m_lowerAngle + b2_angularSlop, -b2_maxAngularCorrection, 0.0f);
+ }
+ else if (angle >= m_upperAngle)
+ {
+ // Prevent large angular corrections and allow some slop.
+ C = b2Clamp(angle - m_upperAngle - b2_angularSlop, 0.0f, b2_maxAngularCorrection);
+ }
+
+ float limitImpulse = -m_axialMass * C;
+ aA -= m_invIA * limitImpulse;
+ aB += m_invIB * limitImpulse;
+ angularError = b2Abs(C);
+ }
+
+ // Solve point-to-point constraint.
+ {
+ qA.Set(aA);
+ qB.Set(aB);
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ b2Vec2 C = cB + rB - cA - rA;
+ positionError = C.Length();
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ b2Mat22 K;
+ K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y;
+ K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y;
+ K.ey.x = K.ex.y;
+ K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x;
+
+ b2Vec2 impulse = -K.Solve(C);
+
+ cA -= mA * impulse;
+ aA -= iA * b2Cross(rA, impulse);
+
+ cB += mB * impulse;
+ aB += iB * b2Cross(rB, impulse);
+ }
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+
+ return positionError <= b2_linearSlop && angularError <= b2_angularSlop;
+}
+
+b2Vec2 b2RevoluteJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2RevoluteJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2RevoluteJoint::GetReactionForce(float inv_dt) const
+{
+ b2Vec2 P(m_impulse.x, m_impulse.y);
+ return inv_dt * P;
+}
+
+float b2RevoluteJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * (m_motorImpulse + m_lowerImpulse - m_upperImpulse);
+}
+
+float b2RevoluteJoint::GetJointAngle() const
+{
+ b2Body* bA = m_bodyA;
+ b2Body* bB = m_bodyB;
+ return bB->m_sweep.a - bA->m_sweep.a - m_referenceAngle;
+}
+
+float b2RevoluteJoint::GetJointSpeed() const
+{
+ b2Body* bA = m_bodyA;
+ b2Body* bB = m_bodyB;
+ return bB->m_angularVelocity - bA->m_angularVelocity;
+}
+
+bool b2RevoluteJoint::IsMotorEnabled() const
+{
+ return m_enableMotor;
+}
+
+void b2RevoluteJoint::EnableMotor(bool flag)
+{
+ if (flag != m_enableMotor)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_enableMotor = flag;
+ }
+}
+
+float b2RevoluteJoint::GetMotorTorque(float inv_dt) const
+{
+ return inv_dt * m_motorImpulse;
+}
+
+void b2RevoluteJoint::SetMotorSpeed(float speed)
+{
+ if (speed != m_motorSpeed)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_motorSpeed = speed;
+ }
+}
+
+void b2RevoluteJoint::SetMaxMotorTorque(float torque)
+{
+ if (torque != m_maxMotorTorque)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_maxMotorTorque = torque;
+ }
+}
+
+bool b2RevoluteJoint::IsLimitEnabled() const
+{
+ return m_enableLimit;
+}
+
+void b2RevoluteJoint::EnableLimit(bool flag)
+{
+ if (flag != m_enableLimit)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_enableLimit = flag;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+}
+
+float b2RevoluteJoint::GetLowerLimit() const
+{
+ return m_lowerAngle;
+}
+
+float b2RevoluteJoint::GetUpperLimit() const
+{
+ return m_upperAngle;
+}
+
+void b2RevoluteJoint::SetLimits(float lower, float upper)
+{
+ b2Assert(lower <= upper);
+
+ if (lower != m_lowerAngle || upper != m_upperAngle)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ m_lowerAngle = lower;
+ m_upperAngle = upper;
+ }
+}
+
+void b2RevoluteJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2RevoluteJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle);
+ b2Dump(" jd.enableLimit = bool(%d);\n", m_enableLimit);
+ b2Dump(" jd.lowerAngle = %.9g;\n", m_lowerAngle);
+ b2Dump(" jd.upperAngle = %.9g;\n", m_upperAngle);
+ b2Dump(" jd.enableMotor = bool(%d);\n", m_enableMotor);
+ b2Dump(" jd.motorSpeed = %.9g;\n", m_motorSpeed);
+ b2Dump(" jd.maxMotorTorque = %.9g;\n", m_maxMotorTorque);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
+
+///
+void b2RevoluteJoint::Draw(b2Draw* draw) const
+{
+ const b2Transform& xfA = m_bodyA->GetTransform();
+ const b2Transform& xfB = m_bodyB->GetTransform();
+ b2Vec2 pA = b2Mul(xfA, m_localAnchorA);
+ b2Vec2 pB = b2Mul(xfB, m_localAnchorB);
+
+ b2Color c1(0.7f, 0.7f, 0.7f);
+ b2Color c2(0.3f, 0.9f, 0.3f);
+ b2Color c3(0.9f, 0.3f, 0.3f);
+ b2Color c4(0.3f, 0.3f, 0.9f);
+ b2Color c5(0.4f, 0.4f, 0.4f);
+
+ draw->DrawPoint(pA, 5.0f, c4);
+ draw->DrawPoint(pB, 5.0f, c5);
+
+ float aA = m_bodyA->GetAngle();
+ float aB = m_bodyB->GetAngle();
+ float angle = aB - aA - m_referenceAngle;
+
+ const float L = 0.5f;
+
+ b2Vec2 r = L * b2Vec2(cosf(angle), sinf(angle));
+ draw->DrawSegment(pB, pB + r, c1);
+ draw->DrawCircle(pB, L, c1);
+
+ if (m_enableLimit)
+ {
+ b2Vec2 rlo = L * b2Vec2(cosf(m_lowerAngle), sinf(m_lowerAngle));
+ b2Vec2 rhi = L * b2Vec2(cosf(m_upperAngle), sinf(m_upperAngle));
+
+ draw->DrawSegment(pB, pB + rlo, c2);
+ draw->DrawSegment(pB, pB + rhi, c3);
+ }
+
+ b2Color color(0.5f, 0.8f, 0.8f);
+ draw->DrawSegment(xfA.p, pA, color);
+ draw->DrawSegment(pA, pB, color);
+ draw->DrawSegment(xfB.p, pB, color);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_weld_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_weld_joint.cpp
new file mode 100644
index 0000000..df3ee0a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_weld_joint.cpp
@@ -0,0 +1,344 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_time_step.h"
+#include "box2d/b2_weld_joint.h"
+
+// Point-to-point constraint
+// C = p2 - p1
+// Cdot = v2 - v1
+// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
+// J = [-I -r1_skew I r2_skew ]
+// Identity used:
+// w k % (rx i + ry j) = w * (-ry i + rx j)
+
+// Angle constraint
+// C = angle2 - angle1 - referenceAngle
+// Cdot = w2 - w1
+// J = [0 0 -1 0 0 1]
+// K = invI1 + invI2
+
+void b2WeldJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor)
+{
+ bodyA = bA;
+ bodyB = bB;
+ localAnchorA = bodyA->GetLocalPoint(anchor);
+ localAnchorB = bodyB->GetLocalPoint(anchor);
+ referenceAngle = bodyB->GetAngle() - bodyA->GetAngle();
+}
+
+b2WeldJoint::b2WeldJoint(const b2WeldJointDef* def)
+: b2Joint(def)
+{
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+ m_referenceAngle = def->referenceAngle;
+ m_stiffness = def->stiffness;
+ m_damping = def->damping;
+
+ m_impulse.SetZero();
+}
+
+void b2WeldJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ // J = [-I -r1_skew I r2_skew]
+ // [ 0 -1 0 1]
+ // r_skew = [-ry; rx]
+
+ // Matlab
+ // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB]
+ // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB]
+ // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB]
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ b2Mat33 K;
+ K.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB;
+ K.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB;
+ K.ez.x = -m_rA.y * iA - m_rB.y * iB;
+ K.ex.y = K.ey.x;
+ K.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB;
+ K.ez.y = m_rA.x * iA + m_rB.x * iB;
+ K.ex.z = K.ez.x;
+ K.ey.z = K.ez.y;
+ K.ez.z = iA + iB;
+
+ if (m_stiffness > 0.0f)
+ {
+ K.GetInverse22(&m_mass);
+
+ float invM = iA + iB;
+
+ float C = aB - aA - m_referenceAngle;
+
+ // Damping coefficient
+ float d = m_damping;
+
+ // Spring stiffness
+ float k = m_stiffness;
+
+ // magic formulas
+ float h = data.step.dt;
+ m_gamma = h * (d + h * k);
+ m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f;
+ m_bias = C * h * k * m_gamma;
+
+ invM += m_gamma;
+ m_mass.ez.z = invM != 0.0f ? 1.0f / invM : 0.0f;
+ }
+ else if (K.ez.z == 0.0f)
+ {
+ K.GetInverse22(&m_mass);
+ m_gamma = 0.0f;
+ m_bias = 0.0f;
+ }
+ else
+ {
+ K.GetSymInverse33(&m_mass);
+ m_gamma = 0.0f;
+ m_bias = 0.0f;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Scale impulses to support a variable time step.
+ m_impulse *= data.step.dtRatio;
+
+ b2Vec2 P(m_impulse.x, m_impulse.y);
+
+ vA -= mA * P;
+ wA -= iA * (b2Cross(m_rA, P) + m_impulse.z);
+
+ vB += mB * P;
+ wB += iB * (b2Cross(m_rB, P) + m_impulse.z);
+ }
+ else
+ {
+ m_impulse.SetZero();
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2WeldJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ if (m_stiffness > 0.0f)
+ {
+ float Cdot2 = wB - wA;
+
+ float impulse2 = -m_mass.ez.z * (Cdot2 + m_bias + m_gamma * m_impulse.z);
+ m_impulse.z += impulse2;
+
+ wA -= iA * impulse2;
+ wB += iB * impulse2;
+
+ b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA);
+
+ b2Vec2 impulse1 = -b2Mul22(m_mass, Cdot1);
+ m_impulse.x += impulse1.x;
+ m_impulse.y += impulse1.y;
+
+ b2Vec2 P = impulse1;
+
+ vA -= mA * P;
+ wA -= iA * b2Cross(m_rA, P);
+
+ vB += mB * P;
+ wB += iB * b2Cross(m_rB, P);
+ }
+ else
+ {
+ b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA);
+ float Cdot2 = wB - wA;
+ b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2);
+
+ b2Vec3 impulse = -b2Mul(m_mass, Cdot);
+ m_impulse += impulse;
+
+ b2Vec2 P(impulse.x, impulse.y);
+
+ vA -= mA * P;
+ wA -= iA * (b2Cross(m_rA, P) + impulse.z);
+
+ vB += mB * P;
+ wB += iB * (b2Cross(m_rB, P) + impulse.z);
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2WeldJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+
+ b2Rot qA(aA), qB(aB);
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+
+ float positionError, angularError;
+
+ b2Mat33 K;
+ K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB;
+ K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB;
+ K.ez.x = -rA.y * iA - rB.y * iB;
+ K.ex.y = K.ey.x;
+ K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB;
+ K.ez.y = rA.x * iA + rB.x * iB;
+ K.ex.z = K.ez.x;
+ K.ey.z = K.ez.y;
+ K.ez.z = iA + iB;
+
+ if (m_stiffness > 0.0f)
+ {
+ b2Vec2 C1 = cB + rB - cA - rA;
+
+ positionError = C1.Length();
+ angularError = 0.0f;
+
+ b2Vec2 P = -K.Solve22(C1);
+
+ cA -= mA * P;
+ aA -= iA * b2Cross(rA, P);
+
+ cB += mB * P;
+ aB += iB * b2Cross(rB, P);
+ }
+ else
+ {
+ b2Vec2 C1 = cB + rB - cA - rA;
+ float C2 = aB - aA - m_referenceAngle;
+
+ positionError = C1.Length();
+ angularError = b2Abs(C2);
+
+ b2Vec3 C(C1.x, C1.y, C2);
+
+ b2Vec3 impulse;
+ if (K.ez.z > 0.0f)
+ {
+ impulse = -K.Solve33(C);
+ }
+ else
+ {
+ b2Vec2 impulse2 = -K.Solve22(C1);
+ impulse.Set(impulse2.x, impulse2.y, 0.0f);
+ }
+
+ b2Vec2 P(impulse.x, impulse.y);
+
+ cA -= mA * P;
+ aA -= iA * (b2Cross(rA, P) + impulse.z);
+
+ cB += mB * P;
+ aB += iB * (b2Cross(rB, P) + impulse.z);
+ }
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+
+ return positionError <= b2_linearSlop && angularError <= b2_angularSlop;
+}
+
+b2Vec2 b2WeldJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2WeldJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2WeldJoint::GetReactionForce(float inv_dt) const
+{
+ b2Vec2 P(m_impulse.x, m_impulse.y);
+ return inv_dt * P;
+}
+
+float b2WeldJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * m_impulse.z;
+}
+
+void b2WeldJoint::Dump()
+{
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2WeldJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle);
+ b2Dump(" jd.stiffness = %.9g;\n", m_stiffness);
+ b2Dump(" jd.damping = %.9g;\n", m_damping);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_wheel_joint.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_wheel_joint.cpp
new file mode 100644
index 0000000..c23b984
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_wheel_joint.cpp
@@ -0,0 +1,672 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_draw.h"
+#include "box2d/b2_wheel_joint.h"
+#include "box2d/b2_time_step.h"
+
+// Linear constraint (point-to-line)
+// d = pB - pA = xB + rB - xA - rA
+// C = dot(ay, d)
+// Cdot = dot(d, cross(wA, ay)) + dot(ay, vB + cross(wB, rB) - vA - cross(wA, rA))
+// = -dot(ay, vA) - dot(cross(d + rA, ay), wA) + dot(ay, vB) + dot(cross(rB, ay), vB)
+// J = [-ay, -cross(d + rA, ay), ay, cross(rB, ay)]
+
+// Spring linear constraint
+// C = dot(ax, d)
+// Cdot = = -dot(ax, vA) - dot(cross(d + rA, ax), wA) + dot(ax, vB) + dot(cross(rB, ax), vB)
+// J = [-ax -cross(d+rA, ax) ax cross(rB, ax)]
+
+// Motor rotational constraint
+// Cdot = wB - wA
+// J = [0 0 -1 0 0 1]
+
+void b2WheelJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis)
+{
+ bodyA = bA;
+ bodyB = bB;
+ localAnchorA = bodyA->GetLocalPoint(anchor);
+ localAnchorB = bodyB->GetLocalPoint(anchor);
+ localAxisA = bodyA->GetLocalVector(axis);
+}
+
+b2WheelJoint::b2WheelJoint(const b2WheelJointDef* def)
+: b2Joint(def)
+{
+ m_localAnchorA = def->localAnchorA;
+ m_localAnchorB = def->localAnchorB;
+ m_localXAxisA = def->localAxisA;
+ m_localYAxisA = b2Cross(1.0f, m_localXAxisA);
+
+ m_mass = 0.0f;
+ m_impulse = 0.0f;
+ m_motorMass = 0.0f;
+ m_motorImpulse = 0.0f;
+ m_springMass = 0.0f;
+ m_springImpulse = 0.0f;
+
+ m_axialMass = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ m_lowerTranslation = def->lowerTranslation;
+ m_upperTranslation = def->upperTranslation;
+ m_enableLimit = def->enableLimit;
+
+ m_maxMotorTorque = def->maxMotorTorque;
+ m_motorSpeed = def->motorSpeed;
+ m_enableMotor = def->enableMotor;
+
+ m_bias = 0.0f;
+ m_gamma = 0.0f;
+
+ m_ax.SetZero();
+ m_ay.SetZero();
+
+ m_stiffness = def->stiffness;
+ m_damping = def->damping;
+}
+
+void b2WheelJoint::InitVelocityConstraints(const b2SolverData& data)
+{
+ m_indexA = m_bodyA->m_islandIndex;
+ m_indexB = m_bodyB->m_islandIndex;
+ m_localCenterA = m_bodyA->m_sweep.localCenter;
+ m_localCenterB = m_bodyB->m_sweep.localCenter;
+ m_invMassA = m_bodyA->m_invMass;
+ m_invMassB = m_bodyB->m_invMass;
+ m_invIA = m_bodyA->m_invI;
+ m_invIB = m_bodyB->m_invI;
+
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ b2Rot qA(aA), qB(aB);
+
+ // Compute the effective masses.
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ b2Vec2 d = cB + rB - cA - rA;
+
+ // Point to line constraint
+ {
+ m_ay = b2Mul(qA, m_localYAxisA);
+ m_sAy = b2Cross(d + rA, m_ay);
+ m_sBy = b2Cross(rB, m_ay);
+
+ m_mass = mA + mB + iA * m_sAy * m_sAy + iB * m_sBy * m_sBy;
+
+ if (m_mass > 0.0f)
+ {
+ m_mass = 1.0f / m_mass;
+ }
+ }
+
+ // Spring constraint
+ m_ax = b2Mul(qA, m_localXAxisA);
+ m_sAx = b2Cross(d + rA, m_ax);
+ m_sBx = b2Cross(rB, m_ax);
+
+ const float invMass = mA + mB + iA * m_sAx * m_sAx + iB * m_sBx * m_sBx;
+ if (invMass > 0.0f)
+ {
+ m_axialMass = 1.0f / invMass;
+ }
+ else
+ {
+ m_axialMass = 0.0f;
+ }
+
+ m_springMass = 0.0f;
+ m_bias = 0.0f;
+ m_gamma = 0.0f;
+
+ if (m_stiffness > 0.0f && invMass > 0.0f)
+ {
+ m_springMass = 1.0f / invMass;
+
+ float C = b2Dot(d, m_ax);
+
+ // magic formulas
+ float h = data.step.dt;
+ m_gamma = h * (m_damping + h * m_stiffness);
+ if (m_gamma > 0.0f)
+ {
+ m_gamma = 1.0f / m_gamma;
+ }
+
+ m_bias = C * h * m_stiffness * m_gamma;
+
+ m_springMass = invMass + m_gamma;
+ if (m_springMass > 0.0f)
+ {
+ m_springMass = 1.0f / m_springMass;
+ }
+ }
+ else
+ {
+ m_springImpulse = 0.0f;
+ }
+
+ if (m_enableLimit)
+ {
+ m_translation = b2Dot(m_ax, d);
+ }
+ else
+ {
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ if (m_enableMotor)
+ {
+ m_motorMass = iA + iB;
+ if (m_motorMass > 0.0f)
+ {
+ m_motorMass = 1.0f / m_motorMass;
+ }
+ }
+ else
+ {
+ m_motorMass = 0.0f;
+ m_motorImpulse = 0.0f;
+ }
+
+ if (data.step.warmStarting)
+ {
+ // Account for variable time step.
+ m_impulse *= data.step.dtRatio;
+ m_springImpulse *= data.step.dtRatio;
+ m_motorImpulse *= data.step.dtRatio;
+
+ float axialImpulse = m_springImpulse + m_lowerImpulse - m_upperImpulse;
+ b2Vec2 P = m_impulse * m_ay + axialImpulse * m_ax;
+ float LA = m_impulse * m_sAy + axialImpulse * m_sAx + m_motorImpulse;
+ float LB = m_impulse * m_sBy + axialImpulse * m_sBx + m_motorImpulse;
+
+ vA -= m_invMassA * P;
+ wA -= m_invIA * LA;
+
+ vB += m_invMassB * P;
+ wB += m_invIB * LB;
+ }
+ else
+ {
+ m_impulse = 0.0f;
+ m_springImpulse = 0.0f;
+ m_motorImpulse = 0.0f;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+void b2WheelJoint::SolveVelocityConstraints(const b2SolverData& data)
+{
+ float mA = m_invMassA, mB = m_invMassB;
+ float iA = m_invIA, iB = m_invIB;
+
+ b2Vec2 vA = data.velocities[m_indexA].v;
+ float wA = data.velocities[m_indexA].w;
+ b2Vec2 vB = data.velocities[m_indexB].v;
+ float wB = data.velocities[m_indexB].w;
+
+ // Solve spring constraint
+ {
+ float Cdot = b2Dot(m_ax, vB - vA) + m_sBx * wB - m_sAx * wA;
+ float impulse = -m_springMass * (Cdot + m_bias + m_gamma * m_springImpulse);
+ m_springImpulse += impulse;
+
+ b2Vec2 P = impulse * m_ax;
+ float LA = impulse * m_sAx;
+ float LB = impulse * m_sBx;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+
+ vB += mB * P;
+ wB += iB * LB;
+ }
+
+ // Solve rotational motor constraint
+ {
+ float Cdot = wB - wA - m_motorSpeed;
+ float impulse = -m_motorMass * Cdot;
+
+ float oldImpulse = m_motorImpulse;
+ float maxImpulse = data.step.dt * m_maxMotorTorque;
+ m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse);
+ impulse = m_motorImpulse - oldImpulse;
+
+ wA -= iA * impulse;
+ wB += iB * impulse;
+ }
+
+ if (m_enableLimit)
+ {
+ // Lower limit
+ {
+ float C = m_translation - m_lowerTranslation;
+ float Cdot = b2Dot(m_ax, vB - vA) + m_sBx * wB - m_sAx * wA;
+ float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt);
+ float oldImpulse = m_lowerImpulse;
+ m_lowerImpulse = b2Max(m_lowerImpulse + impulse, 0.0f);
+ impulse = m_lowerImpulse - oldImpulse;
+
+ b2Vec2 P = impulse * m_ax;
+ float LA = impulse * m_sAx;
+ float LB = impulse * m_sBx;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+ vB += mB * P;
+ wB += iB * LB;
+ }
+
+ // Upper limit
+ // Note: signs are flipped to keep C positive when the constraint is satisfied.
+ // This also keeps the impulse positive when the limit is active.
+ {
+ float C = m_upperTranslation - m_translation;
+ float Cdot = b2Dot(m_ax, vA - vB) + m_sAx * wA - m_sBx * wB;
+ float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt);
+ float oldImpulse = m_upperImpulse;
+ m_upperImpulse = b2Max(m_upperImpulse + impulse, 0.0f);
+ impulse = m_upperImpulse - oldImpulse;
+
+ b2Vec2 P = impulse * m_ax;
+ float LA = impulse * m_sAx;
+ float LB = impulse * m_sBx;
+
+ vA += mA * P;
+ wA += iA * LA;
+ vB -= mB * P;
+ wB -= iB * LB;
+ }
+ }
+
+ // Solve point to line constraint
+ {
+ float Cdot = b2Dot(m_ay, vB - vA) + m_sBy * wB - m_sAy * wA;
+ float impulse = -m_mass * Cdot;
+ m_impulse += impulse;
+
+ b2Vec2 P = impulse * m_ay;
+ float LA = impulse * m_sAy;
+ float LB = impulse * m_sBy;
+
+ vA -= mA * P;
+ wA -= iA * LA;
+
+ vB += mB * P;
+ wB += iB * LB;
+ }
+
+ data.velocities[m_indexA].v = vA;
+ data.velocities[m_indexA].w = wA;
+ data.velocities[m_indexB].v = vB;
+ data.velocities[m_indexB].w = wB;
+}
+
+bool b2WheelJoint::SolvePositionConstraints(const b2SolverData& data)
+{
+ b2Vec2 cA = data.positions[m_indexA].c;
+ float aA = data.positions[m_indexA].a;
+ b2Vec2 cB = data.positions[m_indexB].c;
+ float aB = data.positions[m_indexB].a;
+
+ float linearError = 0.0f;
+
+ if (m_enableLimit)
+ {
+ b2Rot qA(aA), qB(aB);
+
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ b2Vec2 d = (cB - cA) + rB - rA;
+
+ b2Vec2 ax = b2Mul(qA, m_localXAxisA);
+ float sAx = b2Cross(d + rA, m_ax);
+ float sBx = b2Cross(rB, m_ax);
+
+ float C = 0.0f;
+ float translation = b2Dot(ax, d);
+ if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop)
+ {
+ C = translation;
+ }
+ else if (translation <= m_lowerTranslation)
+ {
+ C = b2Min(translation - m_lowerTranslation, 0.0f);
+ }
+ else if (translation >= m_upperTranslation)
+ {
+ C = b2Max(translation - m_upperTranslation, 0.0f);
+ }
+
+ if (C != 0.0f)
+ {
+
+ float invMass = m_invMassA + m_invMassB + m_invIA * sAx * sAx + m_invIB * sBx * sBx;
+ float impulse = 0.0f;
+ if (invMass != 0.0f)
+ {
+ impulse = -C / invMass;
+ }
+
+ b2Vec2 P = impulse * ax;
+ float LA = impulse * sAx;
+ float LB = impulse * sBx;
+
+ cA -= m_invMassA * P;
+ aA -= m_invIA * LA;
+ cB += m_invMassB * P;
+ aB += m_invIB * LB;
+
+ linearError = b2Abs(C);
+ }
+ }
+
+ // Solve perpendicular constraint
+ {
+ b2Rot qA(aA), qB(aB);
+
+ b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
+ b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+ b2Vec2 d = (cB - cA) + rB - rA;
+
+ b2Vec2 ay = b2Mul(qA, m_localYAxisA);
+
+ float sAy = b2Cross(d + rA, ay);
+ float sBy = b2Cross(rB, ay);
+
+ float C = b2Dot(d, ay);
+
+ float invMass = m_invMassA + m_invMassB + m_invIA * m_sAy * m_sAy + m_invIB * m_sBy * m_sBy;
+
+ float impulse = 0.0f;
+ if (invMass != 0.0f)
+ {
+ impulse = - C / invMass;
+ }
+
+ b2Vec2 P = impulse * ay;
+ float LA = impulse * sAy;
+ float LB = impulse * sBy;
+
+ cA -= m_invMassA * P;
+ aA -= m_invIA * LA;
+ cB += m_invMassB * P;
+ aB += m_invIB * LB;
+
+ linearError = b2Max(linearError, b2Abs(C));
+ }
+
+ data.positions[m_indexA].c = cA;
+ data.positions[m_indexA].a = aA;
+ data.positions[m_indexB].c = cB;
+ data.positions[m_indexB].a = aB;
+
+ return linearError <= b2_linearSlop;
+}
+
+b2Vec2 b2WheelJoint::GetAnchorA() const
+{
+ return m_bodyA->GetWorldPoint(m_localAnchorA);
+}
+
+b2Vec2 b2WheelJoint::GetAnchorB() const
+{
+ return m_bodyB->GetWorldPoint(m_localAnchorB);
+}
+
+b2Vec2 b2WheelJoint::GetReactionForce(float inv_dt) const
+{
+ return inv_dt * (m_impulse * m_ay + (m_springImpulse + m_lowerImpulse - m_upperImpulse) * m_ax);
+}
+
+float b2WheelJoint::GetReactionTorque(float inv_dt) const
+{
+ return inv_dt * m_motorImpulse;
+}
+
+float b2WheelJoint::GetJointTranslation() const
+{
+ b2Body* bA = m_bodyA;
+ b2Body* bB = m_bodyB;
+
+ b2Vec2 pA = bA->GetWorldPoint(m_localAnchorA);
+ b2Vec2 pB = bB->GetWorldPoint(m_localAnchorB);
+ b2Vec2 d = pB - pA;
+ b2Vec2 axis = bA->GetWorldVector(m_localXAxisA);
+
+ float translation = b2Dot(d, axis);
+ return translation;
+}
+
+float b2WheelJoint::GetJointLinearSpeed() const
+{
+ b2Body* bA = m_bodyA;
+ b2Body* bB = m_bodyB;
+
+ b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter);
+ b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter);
+ b2Vec2 p1 = bA->m_sweep.c + rA;
+ b2Vec2 p2 = bB->m_sweep.c + rB;
+ b2Vec2 d = p2 - p1;
+ b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA);
+
+ b2Vec2 vA = bA->m_linearVelocity;
+ b2Vec2 vB = bB->m_linearVelocity;
+ float wA = bA->m_angularVelocity;
+ float wB = bB->m_angularVelocity;
+
+ float speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA));
+ return speed;
+}
+
+float b2WheelJoint::GetJointAngle() const
+{
+ b2Body* bA = m_bodyA;
+ b2Body* bB = m_bodyB;
+ return bB->m_sweep.a - bA->m_sweep.a;
+}
+
+float b2WheelJoint::GetJointAngularSpeed() const
+{
+ float wA = m_bodyA->m_angularVelocity;
+ float wB = m_bodyB->m_angularVelocity;
+ return wB - wA;
+}
+
+bool b2WheelJoint::IsLimitEnabled() const
+{
+ return m_enableLimit;
+}
+
+void b2WheelJoint::EnableLimit(bool flag)
+{
+ if (flag != m_enableLimit)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_enableLimit = flag;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+}
+
+float b2WheelJoint::GetLowerLimit() const
+{
+ return m_lowerTranslation;
+}
+
+float b2WheelJoint::GetUpperLimit() const
+{
+ return m_upperTranslation;
+}
+
+void b2WheelJoint::SetLimits(float lower, float upper)
+{
+ b2Assert(lower <= upper);
+ if (lower != m_lowerTranslation || upper != m_upperTranslation)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_lowerTranslation = lower;
+ m_upperTranslation = upper;
+ m_lowerImpulse = 0.0f;
+ m_upperImpulse = 0.0f;
+ }
+}
+
+bool b2WheelJoint::IsMotorEnabled() const
+{
+ return m_enableMotor;
+}
+
+void b2WheelJoint::EnableMotor(bool flag)
+{
+ if (flag != m_enableMotor)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_enableMotor = flag;
+ }
+}
+
+void b2WheelJoint::SetMotorSpeed(float speed)
+{
+ if (speed != m_motorSpeed)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_motorSpeed = speed;
+ }
+}
+
+void b2WheelJoint::SetMaxMotorTorque(float torque)
+{
+ if (torque != m_maxMotorTorque)
+ {
+ m_bodyA->SetAwake(true);
+ m_bodyB->SetAwake(true);
+ m_maxMotorTorque = torque;
+ }
+}
+
+float b2WheelJoint::GetMotorTorque(float inv_dt) const
+{
+ return inv_dt * m_motorImpulse;
+}
+
+void b2WheelJoint::SetStiffness(float stiffness)
+{
+ m_stiffness = stiffness;
+}
+
+float b2WheelJoint::GetStiffness() const
+{
+ return m_stiffness;
+}
+
+void b2WheelJoint::SetDamping(float damping)
+{
+ m_damping = damping;
+}
+
+float b2WheelJoint::GetDamping() const
+{
+ return m_damping;
+}
+
+void b2WheelJoint::Dump()
+{
+ // FLT_DECIMAL_DIG == 9
+
+ int32 indexA = m_bodyA->m_islandIndex;
+ int32 indexB = m_bodyB->m_islandIndex;
+
+ b2Dump(" b2WheelJointDef jd;\n");
+ b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
+ b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
+ b2Dump(" jd.localAxisA.Set(%.9g, %.9g);\n", m_localXAxisA.x, m_localXAxisA.y);
+ b2Dump(" jd.enableMotor = bool(%d);\n", m_enableMotor);
+ b2Dump(" jd.motorSpeed = %.9g;\n", m_motorSpeed);
+ b2Dump(" jd.maxMotorTorque = %.9g;\n", m_maxMotorTorque);
+ b2Dump(" jd.stiffness = %.9g;\n", m_stiffness);
+ b2Dump(" jd.damping = %.9g;\n", m_damping);
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
+}
+
+///
+void b2WheelJoint::Draw(b2Draw* draw) const
+{
+ const b2Transform& xfA = m_bodyA->GetTransform();
+ const b2Transform& xfB = m_bodyB->GetTransform();
+ b2Vec2 pA = b2Mul(xfA, m_localAnchorA);
+ b2Vec2 pB = b2Mul(xfB, m_localAnchorB);
+
+ b2Vec2 axis = b2Mul(xfA.q, m_localXAxisA);
+
+ b2Color c1(0.7f, 0.7f, 0.7f);
+ b2Color c2(0.3f, 0.9f, 0.3f);
+ b2Color c3(0.9f, 0.3f, 0.3f);
+ b2Color c4(0.3f, 0.3f, 0.9f);
+ b2Color c5(0.4f, 0.4f, 0.4f);
+
+ draw->DrawSegment(pA, pB, c5);
+
+ if (m_enableLimit)
+ {
+ b2Vec2 lower = pA + m_lowerTranslation * axis;
+ b2Vec2 upper = pA + m_upperTranslation * axis;
+ b2Vec2 perp = b2Mul(xfA.q, m_localYAxisA);
+ draw->DrawSegment(lower, upper, c1);
+ draw->DrawSegment(lower - 0.5f * perp, lower + 0.5f * perp, c2);
+ draw->DrawSegment(upper - 0.5f * perp, upper + 0.5f * perp, c3);
+ }
+ else
+ {
+ draw->DrawSegment(pA - 1.0f * axis, pA + 1.0f * axis, c1);
+ }
+
+ draw->DrawPoint(pA, 5.0f, c1);
+ draw->DrawPoint(pB, 5.0f, c4);
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_world.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_world.cpp
new file mode 100644
index 0000000..78ec084
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_world.cpp
@@ -0,0 +1,1322 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "b2_contact_solver.h"
+#include "b2_island.h"
+
+#include "box2d/b2_body.h"
+#include "box2d/b2_broad_phase.h"
+#include "box2d/b2_chain_shape.h"
+#include "box2d/b2_circle_shape.h"
+#include "box2d/b2_collision.h"
+#include "box2d/b2_contact.h"
+#include "box2d/b2_draw.h"
+#include "box2d/b2_edge_shape.h"
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_polygon_shape.h"
+#include "box2d/b2_pulley_joint.h"
+#include "box2d/b2_time_of_impact.h"
+#include "box2d/b2_timer.h"
+#include "box2d/b2_world.h"
+
+#include <new>
+
+b2World::b2World(const b2Vec2& gravity)
+{
+ m_destructionListener = nullptr;
+ m_debugDraw = nullptr;
+
+ m_bodyList = nullptr;
+ m_jointList = nullptr;
+
+ m_bodyCount = 0;
+ m_jointCount = 0;
+
+ m_warmStarting = true;
+ m_continuousPhysics = true;
+ m_subStepping = false;
+
+ m_stepComplete = true;
+
+ m_allowSleep = true;
+ m_gravity = gravity;
+
+ m_newContacts = false;
+ m_locked = false;
+ m_clearForces = true;
+
+ m_inv_dt0 = 0.0f;
+
+ m_contactManager.m_allocator = &m_blockAllocator;
+
+ memset(&m_profile, 0, sizeof(b2Profile));
+}
+
+b2World::~b2World()
+{
+ // Some shapes allocate using b2Alloc.
+ b2Body* b = m_bodyList;
+ while (b)
+ {
+ b2Body* bNext = b->m_next;
+
+ b2Fixture* f = b->m_fixtureList;
+ while (f)
+ {
+ b2Fixture* fNext = f->m_next;
+ f->m_proxyCount = 0;
+ f->Destroy(&m_blockAllocator);
+ f = fNext;
+ }
+
+ b = bNext;
+ }
+}
+
+void b2World::SetDestructionListener(b2DestructionListener* listener)
+{
+ m_destructionListener = listener;
+}
+
+void b2World::SetContactFilter(b2ContactFilter* filter)
+{
+ m_contactManager.m_contactFilter = filter;
+}
+
+void b2World::SetContactListener(b2ContactListener* listener)
+{
+ m_contactManager.m_contactListener = listener;
+}
+
+void b2World::SetDebugDraw(b2Draw* debugDraw)
+{
+ m_debugDraw = debugDraw;
+}
+
+b2Body* b2World::CreateBody(const b2BodyDef* def)
+{
+ b2Assert(IsLocked() == false);
+ if (IsLocked())
+ {
+ return nullptr;
+ }
+
+ void* mem = m_blockAllocator.Allocate(sizeof(b2Body));
+ b2Body* b = new (mem) b2Body(def, this);
+
+ // Add to world doubly linked list.
+ b->m_prev = nullptr;
+ b->m_next = m_bodyList;
+ if (m_bodyList)
+ {
+ m_bodyList->m_prev = b;
+ }
+ m_bodyList = b;
+ ++m_bodyCount;
+
+ return b;
+}
+
+void b2World::DestroyBody(b2Body* b)
+{
+ b2Assert(m_bodyCount > 0);
+ b2Assert(IsLocked() == false);
+ if (IsLocked())
+ {
+ return;
+ }
+
+ // Delete the attached joints.
+ b2JointEdge* je = b->m_jointList;
+ while (je)
+ {
+ b2JointEdge* je0 = je;
+ je = je->next;
+
+ if (m_destructionListener)
+ {
+ m_destructionListener->SayGoodbye(je0->joint);
+ }
+
+ DestroyJoint(je0->joint);
+
+ b->m_jointList = je;
+ }
+ b->m_jointList = nullptr;
+
+ // Delete the attached contacts.
+ b2ContactEdge* ce = b->m_contactList;
+ while (ce)
+ {
+ b2ContactEdge* ce0 = ce;
+ ce = ce->next;
+ m_contactManager.Destroy(ce0->contact);
+ }
+ b->m_contactList = nullptr;
+
+ // Delete the attached fixtures. This destroys broad-phase proxies.
+ b2Fixture* f = b->m_fixtureList;
+ while (f)
+ {
+ b2Fixture* f0 = f;
+ f = f->m_next;
+
+ if (m_destructionListener)
+ {
+ m_destructionListener->SayGoodbye(f0);
+ }
+
+ f0->DestroyProxies(&m_contactManager.m_broadPhase);
+ f0->Destroy(&m_blockAllocator);
+ f0->~b2Fixture();
+ m_blockAllocator.Free(f0, sizeof(b2Fixture));
+
+ b->m_fixtureList = f;
+ b->m_fixtureCount -= 1;
+ }
+ b->m_fixtureList = nullptr;
+ b->m_fixtureCount = 0;
+
+ // Remove world body list.
+ if (b->m_prev)
+ {
+ b->m_prev->m_next = b->m_next;
+ }
+
+ if (b->m_next)
+ {
+ b->m_next->m_prev = b->m_prev;
+ }
+
+ if (b == m_bodyList)
+ {
+ m_bodyList = b->m_next;
+ }
+
+ --m_bodyCount;
+ b->~b2Body();
+ m_blockAllocator.Free(b, sizeof(b2Body));
+}
+
+b2Joint* b2World::CreateJoint(const b2JointDef* def)
+{
+ b2Assert(IsLocked() == false);
+ if (IsLocked())
+ {
+ return nullptr;
+ }
+
+ b2Joint* j = b2Joint::Create(def, &m_blockAllocator);
+
+ // Connect to the world list.
+ j->m_prev = nullptr;
+ j->m_next = m_jointList;
+ if (m_jointList)
+ {
+ m_jointList->m_prev = j;
+ }
+ m_jointList = j;
+ ++m_jointCount;
+
+ // Connect to the bodies' doubly linked lists.
+ j->m_edgeA.joint = j;
+ j->m_edgeA.other = j->m_bodyB;
+ j->m_edgeA.prev = nullptr;
+ j->m_edgeA.next = j->m_bodyA->m_jointList;
+ if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA;
+ j->m_bodyA->m_jointList = &j->m_edgeA;
+
+ j->m_edgeB.joint = j;
+ j->m_edgeB.other = j->m_bodyA;
+ j->m_edgeB.prev = nullptr;
+ j->m_edgeB.next = j->m_bodyB->m_jointList;
+ if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB;
+ j->m_bodyB->m_jointList = &j->m_edgeB;
+
+ b2Body* bodyA = def->bodyA;
+ b2Body* bodyB = def->bodyB;
+
+ // If the joint prevents collisions, then flag any contacts for filtering.
+ if (def->collideConnected == false)
+ {
+ b2ContactEdge* edge = bodyB->GetContactList();
+ while (edge)
+ {
+ if (edge->other == bodyA)
+ {
+ // Flag the contact for filtering at the next time step (where either
+ // body is awake).
+ edge->contact->FlagForFiltering();
+ }
+
+ edge = edge->next;
+ }
+ }
+
+ // Note: creating a joint doesn't wake the bodies.
+
+ return j;
+}
+
+void b2World::DestroyJoint(b2Joint* j)
+{
+ b2Assert(IsLocked() == false);
+ if (IsLocked())
+ {
+ return;
+ }
+
+ bool collideConnected = j->m_collideConnected;
+
+ // Remove from the doubly linked list.
+ if (j->m_prev)
+ {
+ j->m_prev->m_next = j->m_next;
+ }
+
+ if (j->m_next)
+ {
+ j->m_next->m_prev = j->m_prev;
+ }
+
+ if (j == m_jointList)
+ {
+ m_jointList = j->m_next;
+ }
+
+ // Disconnect from island graph.
+ b2Body* bodyA = j->m_bodyA;
+ b2Body* bodyB = j->m_bodyB;
+
+ // Wake up connected bodies.
+ bodyA->SetAwake(true);
+ bodyB->SetAwake(true);
+
+ // Remove from body 1.
+ if (j->m_edgeA.prev)
+ {
+ j->m_edgeA.prev->next = j->m_edgeA.next;
+ }
+
+ if (j->m_edgeA.next)
+ {
+ j->m_edgeA.next->prev = j->m_edgeA.prev;
+ }
+
+ if (&j->m_edgeA == bodyA->m_jointList)
+ {
+ bodyA->m_jointList = j->m_edgeA.next;
+ }
+
+ j->m_edgeA.prev = nullptr;
+ j->m_edgeA.next = nullptr;
+
+ // Remove from body 2
+ if (j->m_edgeB.prev)
+ {
+ j->m_edgeB.prev->next = j->m_edgeB.next;
+ }
+
+ if (j->m_edgeB.next)
+ {
+ j->m_edgeB.next->prev = j->m_edgeB.prev;
+ }
+
+ if (&j->m_edgeB == bodyB->m_jointList)
+ {
+ bodyB->m_jointList = j->m_edgeB.next;
+ }
+
+ j->m_edgeB.prev = nullptr;
+ j->m_edgeB.next = nullptr;
+
+ b2Joint::Destroy(j, &m_blockAllocator);
+
+ b2Assert(m_jointCount > 0);
+ --m_jointCount;
+
+ // If the joint prevents collisions, then flag any contacts for filtering.
+ if (collideConnected == false)
+ {
+ b2ContactEdge* edge = bodyB->GetContactList();
+ while (edge)
+ {
+ if (edge->other == bodyA)
+ {
+ // Flag the contact for filtering at the next time step (where either
+ // body is awake).
+ edge->contact->FlagForFiltering();
+ }
+
+ edge = edge->next;
+ }
+ }
+}
+
+//
+void b2World::SetAllowSleeping(bool flag)
+{
+ if (flag == m_allowSleep)
+ {
+ return;
+ }
+
+ m_allowSleep = flag;
+ if (m_allowSleep == false)
+ {
+ for (b2Body* b = m_bodyList; b; b = b->m_next)
+ {
+ b->SetAwake(true);
+ }
+ }
+}
+
+// Find islands, integrate and solve constraints, solve position constraints
+void b2World::Solve(const b2TimeStep& step)
+{
+ m_profile.solveInit = 0.0f;
+ m_profile.solveVelocity = 0.0f;
+ m_profile.solvePosition = 0.0f;
+
+ // Size the island for the worst case.
+ b2Island island(m_bodyCount,
+ m_contactManager.m_contactCount,
+ m_jointCount,
+ &m_stackAllocator,
+ m_contactManager.m_contactListener);
+
+ // Clear all the island flags.
+ for (b2Body* b = m_bodyList; b; b = b->m_next)
+ {
+ b->m_flags &= ~b2Body::e_islandFlag;
+ }
+ for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
+ {
+ c->m_flags &= ~b2Contact::e_islandFlag;
+ }
+ for (b2Joint* j = m_jointList; j; j = j->m_next)
+ {
+ j->m_islandFlag = false;
+ }
+
+ // Build and simulate all awake islands.
+ int32 stackSize = m_bodyCount;
+ b2Body** stack = (b2Body**)m_stackAllocator.Allocate(stackSize * sizeof(b2Body*));
+ for (b2Body* seed = m_bodyList; seed; seed = seed->m_next)
+ {
+ if (seed->m_flags & b2Body::e_islandFlag)
+ {
+ continue;
+ }
+
+ if (seed->IsAwake() == false || seed->IsEnabled() == false)
+ {
+ continue;
+ }
+
+ // The seed can be dynamic or kinematic.
+ if (seed->GetType() == b2_staticBody)
+ {
+ continue;
+ }
+
+ // Reset island and stack.
+ island.Clear();
+ int32 stackCount = 0;
+ stack[stackCount++] = seed;
+ seed->m_flags |= b2Body::e_islandFlag;
+
+ // Perform a depth first search (DFS) on the constraint graph.
+ while (stackCount > 0)
+ {
+ // Grab the next body off the stack and add it to the island.
+ b2Body* b = stack[--stackCount];
+ b2Assert(b->IsEnabled() == true);
+ island.Add(b);
+
+ // To keep islands as small as possible, we don't
+ // propagate islands across static bodies.
+ if (b->GetType() == b2_staticBody)
+ {
+ continue;
+ }
+
+ // Make sure the body is awake (without resetting sleep timer).
+ b->m_flags |= b2Body::e_awakeFlag;
+
+ // Search all contacts connected to this body.
+ for (b2ContactEdge* ce = b->m_contactList; ce; ce = ce->next)
+ {
+ b2Contact* contact = ce->contact;
+
+ // Has this contact already been added to an island?
+ if (contact->m_flags & b2Contact::e_islandFlag)
+ {
+ continue;
+ }
+
+ // Is this contact solid and touching?
+ if (contact->IsEnabled() == false ||
+ contact->IsTouching() == false)
+ {
+ continue;
+ }
+
+ // Skip sensors.
+ bool sensorA = contact->m_fixtureA->m_isSensor;
+ bool sensorB = contact->m_fixtureB->m_isSensor;
+ if (sensorA || sensorB)
+ {
+ continue;
+ }
+
+ island.Add(contact);
+ contact->m_flags |= b2Contact::e_islandFlag;
+
+ b2Body* other = ce->other;
+
+ // Was the other body already added to this island?
+ if (other->m_flags & b2Body::e_islandFlag)
+ {
+ continue;
+ }
+
+ b2Assert(stackCount < stackSize);
+ stack[stackCount++] = other;
+ other->m_flags |= b2Body::e_islandFlag;
+ }
+
+ // Search all joints connect to this body.
+ for (b2JointEdge* je = b->m_jointList; je; je = je->next)
+ {
+ if (je->joint->m_islandFlag == true)
+ {
+ continue;
+ }
+
+ b2Body* other = je->other;
+
+ // Don't simulate joints connected to disabled bodies.
+ if (other->IsEnabled() == false)
+ {
+ continue;
+ }
+
+ island.Add(je->joint);
+ je->joint->m_islandFlag = true;
+
+ if (other->m_flags & b2Body::e_islandFlag)
+ {
+ continue;
+ }
+
+ b2Assert(stackCount < stackSize);
+ stack[stackCount++] = other;
+ other->m_flags |= b2Body::e_islandFlag;
+ }
+ }
+
+ b2Profile profile;
+ island.Solve(&profile, step, m_gravity, m_allowSleep);
+ m_profile.solveInit += profile.solveInit;
+ m_profile.solveVelocity += profile.solveVelocity;
+ m_profile.solvePosition += profile.solvePosition;
+
+ // Post solve cleanup.
+ for (int32 i = 0; i < island.m_bodyCount; ++i)
+ {
+ // Allow static bodies to participate in other islands.
+ b2Body* b = island.m_bodies[i];
+ if (b->GetType() == b2_staticBody)
+ {
+ b->m_flags &= ~b2Body::e_islandFlag;
+ }
+ }
+ }
+
+ m_stackAllocator.Free(stack);
+
+ {
+ b2Timer timer;
+ // Synchronize fixtures, check for out of range bodies.
+ for (b2Body* b = m_bodyList; b; b = b->GetNext())
+ {
+ // If a body was not in an island then it did not move.
+ if ((b->m_flags & b2Body::e_islandFlag) == 0)
+ {
+ continue;
+ }
+
+ if (b->GetType() == b2_staticBody)
+ {
+ continue;
+ }
+
+ // Update fixtures (for broad-phase).
+ b->SynchronizeFixtures();
+ }
+
+ // Look for new contacts.
+ m_contactManager.FindNewContacts();
+ m_profile.broadphase = timer.GetMilliseconds();
+ }
+}
+
+// Find TOI contacts and solve them.
+void b2World::SolveTOI(const b2TimeStep& step)
+{
+ b2Island island(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, &m_stackAllocator, m_contactManager.m_contactListener);
+
+ if (m_stepComplete)
+ {
+ for (b2Body* b = m_bodyList; b; b = b->m_next)
+ {
+ b->m_flags &= ~b2Body::e_islandFlag;
+ b->m_sweep.alpha0 = 0.0f;
+ }
+
+ for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
+ {
+ // Invalidate TOI
+ c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag);
+ c->m_toiCount = 0;
+ c->m_toi = 1.0f;
+ }
+ }
+
+ // Find TOI events and solve them.
+ for (;;)
+ {
+ // Find the first TOI.
+ b2Contact* minContact = nullptr;
+ float minAlpha = 1.0f;
+
+ for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
+ {
+ // Is this contact disabled?
+ if (c->IsEnabled() == false)
+ {
+ continue;
+ }
+
+ // Prevent excessive sub-stepping.
+ if (c->m_toiCount > b2_maxSubSteps)
+ {
+ continue;
+ }
+
+ float alpha = 1.0f;
+ if (c->m_flags & b2Contact::e_toiFlag)
+ {
+ // This contact has a valid cached TOI.
+ alpha = c->m_toi;
+ }
+ else
+ {
+ b2Fixture* fA = c->GetFixtureA();
+ b2Fixture* fB = c->GetFixtureB();
+
+ // Is there a sensor?
+ if (fA->IsSensor() || fB->IsSensor())
+ {
+ continue;
+ }
+
+ b2Body* bA = fA->GetBody();
+ b2Body* bB = fB->GetBody();
+
+ b2BodyType typeA = bA->m_type;
+ b2BodyType typeB = bB->m_type;
+ b2Assert(typeA == b2_dynamicBody || typeB == b2_dynamicBody);
+
+ bool activeA = bA->IsAwake() && typeA != b2_staticBody;
+ bool activeB = bB->IsAwake() && typeB != b2_staticBody;
+
+ // Is at least one body active (awake and dynamic or kinematic)?
+ if (activeA == false && activeB == false)
+ {
+ continue;
+ }
+
+ bool collideA = bA->IsBullet() || typeA != b2_dynamicBody;
+ bool collideB = bB->IsBullet() || typeB != b2_dynamicBody;
+
+ // Are these two non-bullet dynamic bodies?
+ if (collideA == false && collideB == false)
+ {
+ continue;
+ }
+
+ // Compute the TOI for this contact.
+ // Put the sweeps onto the same time interval.
+ float alpha0 = bA->m_sweep.alpha0;
+
+ if (bA->m_sweep.alpha0 < bB->m_sweep.alpha0)
+ {
+ alpha0 = bB->m_sweep.alpha0;
+ bA->m_sweep.Advance(alpha0);
+ }
+ else if (bB->m_sweep.alpha0 < bA->m_sweep.alpha0)
+ {
+ alpha0 = bA->m_sweep.alpha0;
+ bB->m_sweep.Advance(alpha0);
+ }
+
+ b2Assert(alpha0 < 1.0f);
+
+ int32 indexA = c->GetChildIndexA();
+ int32 indexB = c->GetChildIndexB();
+
+ // Compute the time of impact in interval [0, minTOI]
+ b2TOIInput input;
+ input.proxyA.Set(fA->GetShape(), indexA);
+ input.proxyB.Set(fB->GetShape(), indexB);
+ input.sweepA = bA->m_sweep;
+ input.sweepB = bB->m_sweep;
+ input.tMax = 1.0f;
+
+ b2TOIOutput output;
+ b2TimeOfImpact(&output, &input);
+
+ // Beta is the fraction of the remaining portion of the .
+ float beta = output.t;
+ if (output.state == b2TOIOutput::e_touching)
+ {
+ alpha = b2Min(alpha0 + (1.0f - alpha0) * beta, 1.0f);
+ }
+ else
+ {
+ alpha = 1.0f;
+ }
+
+ c->m_toi = alpha;
+ c->m_flags |= b2Contact::e_toiFlag;
+ }
+
+ if (alpha < minAlpha)
+ {
+ // This is the minimum TOI found so far.
+ minContact = c;
+ minAlpha = alpha;
+ }
+ }
+
+ if (minContact == nullptr || 1.0f - 10.0f * b2_epsilon < minAlpha)
+ {
+ // No more TOI events. Done!
+ m_stepComplete = true;
+ break;
+ }
+
+ // Advance the bodies to the TOI.
+ b2Fixture* fA = minContact->GetFixtureA();
+ b2Fixture* fB = minContact->GetFixtureB();
+ b2Body* bA = fA->GetBody();
+ b2Body* bB = fB->GetBody();
+
+ b2Sweep backup1 = bA->m_sweep;
+ b2Sweep backup2 = bB->m_sweep;
+
+ bA->Advance(minAlpha);
+ bB->Advance(minAlpha);
+
+ // The TOI contact likely has some new contact points.
+ minContact->Update(m_contactManager.m_contactListener);
+ minContact->m_flags &= ~b2Contact::e_toiFlag;
+ ++minContact->m_toiCount;
+
+ // Is the contact solid?
+ if (minContact->IsEnabled() == false || minContact->IsTouching() == false)
+ {
+ // Restore the sweeps.
+ minContact->SetEnabled(false);
+ bA->m_sweep = backup1;
+ bB->m_sweep = backup2;
+ bA->SynchronizeTransform();
+ bB->SynchronizeTransform();
+ continue;
+ }
+
+ bA->SetAwake(true);
+ bB->SetAwake(true);
+
+ // Build the island
+ island.Clear();
+ island.Add(bA);
+ island.Add(bB);
+ island.Add(minContact);
+
+ bA->m_flags |= b2Body::e_islandFlag;
+ bB->m_flags |= b2Body::e_islandFlag;
+ minContact->m_flags |= b2Contact::e_islandFlag;
+
+ // Get contacts on bodyA and bodyB.
+ b2Body* bodies[2] = {bA, bB};
+ for (int32 i = 0; i < 2; ++i)
+ {
+ b2Body* body = bodies[i];
+ if (body->m_type == b2_dynamicBody)
+ {
+ for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next)
+ {
+ if (island.m_bodyCount == island.m_bodyCapacity)
+ {
+ break;
+ }
+
+ if (island.m_contactCount == island.m_contactCapacity)
+ {
+ break;
+ }
+
+ b2Contact* contact = ce->contact;
+
+ // Has this contact already been added to the island?
+ if (contact->m_flags & b2Contact::e_islandFlag)
+ {
+ continue;
+ }
+
+ // Only add static, kinematic, or bullet bodies.
+ b2Body* other = ce->other;
+ if (other->m_type == b2_dynamicBody &&
+ body->IsBullet() == false && other->IsBullet() == false)
+ {
+ continue;
+ }
+
+ // Skip sensors.
+ bool sensorA = contact->m_fixtureA->m_isSensor;
+ bool sensorB = contact->m_fixtureB->m_isSensor;
+ if (sensorA || sensorB)
+ {
+ continue;
+ }
+
+ // Tentatively advance the body to the TOI.
+ b2Sweep backup = other->m_sweep;
+ if ((other->m_flags & b2Body::e_islandFlag) == 0)
+ {
+ other->Advance(minAlpha);
+ }
+
+ // Update the contact points
+ contact->Update(m_contactManager.m_contactListener);
+
+ // Was the contact disabled by the user?
+ if (contact->IsEnabled() == false)
+ {
+ other->m_sweep = backup;
+ other->SynchronizeTransform();
+ continue;
+ }
+
+ // Are there contact points?
+ if (contact->IsTouching() == false)
+ {
+ other->m_sweep = backup;
+ other->SynchronizeTransform();
+ continue;
+ }
+
+ // Add the contact to the island
+ contact->m_flags |= b2Contact::e_islandFlag;
+ island.Add(contact);
+
+ // Has the other body already been added to the island?
+ if (other->m_flags & b2Body::e_islandFlag)
+ {
+ continue;
+ }
+
+ // Add the other body to the island.
+ other->m_flags |= b2Body::e_islandFlag;
+
+ if (other->m_type != b2_staticBody)
+ {
+ other->SetAwake(true);
+ }
+
+ island.Add(other);
+ }
+ }
+ }
+
+ b2TimeStep subStep;
+ subStep.dt = (1.0f - minAlpha) * step.dt;
+ subStep.inv_dt = 1.0f / subStep.dt;
+ subStep.dtRatio = 1.0f;
+ subStep.positionIterations = 20;
+ subStep.velocityIterations = step.velocityIterations;
+ subStep.warmStarting = false;
+ island.SolveTOI(subStep, bA->m_islandIndex, bB->m_islandIndex);
+
+ // Reset island flags and synchronize broad-phase proxies.
+ for (int32 i = 0; i < island.m_bodyCount; ++i)
+ {
+ b2Body* body = island.m_bodies[i];
+ body->m_flags &= ~b2Body::e_islandFlag;
+
+ if (body->m_type != b2_dynamicBody)
+ {
+ continue;
+ }
+
+ body->SynchronizeFixtures();
+
+ // Invalidate all contact TOIs on this displaced body.
+ for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next)
+ {
+ ce->contact->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag);
+ }
+ }
+
+ // Commit fixture proxy movements to the broad-phase so that new contacts are created.
+ // Also, some contacts can be destroyed.
+ m_contactManager.FindNewContacts();
+
+ if (m_subStepping)
+ {
+ m_stepComplete = false;
+ break;
+ }
+ }
+}
+
+void b2World::Step(float dt, int32 velocityIterations, int32 positionIterations)
+{
+ b2Timer stepTimer;
+
+ // If new fixtures were added, we need to find the new contacts.
+ if (m_newContacts)
+ {
+ m_contactManager.FindNewContacts();
+ m_newContacts = false;
+ }
+
+ m_locked = true;
+
+ b2TimeStep step;
+ step.dt = dt;
+ step.velocityIterations = velocityIterations;
+ step.positionIterations = positionIterations;
+ if (dt > 0.0f)
+ {
+ step.inv_dt = 1.0f / dt;
+ }
+ else
+ {
+ step.inv_dt = 0.0f;
+ }
+
+ step.dtRatio = m_inv_dt0 * dt;
+
+ step.warmStarting = m_warmStarting;
+
+ // Update contacts. This is where some contacts are destroyed.
+ {
+ b2Timer timer;
+ m_contactManager.Collide();
+ m_profile.collide = timer.GetMilliseconds();
+ }
+
+ // Integrate velocities, solve velocity constraints, and integrate positions.
+ if (m_stepComplete && step.dt > 0.0f)
+ {
+ b2Timer timer;
+ Solve(step);
+ m_profile.solve = timer.GetMilliseconds();
+ }
+
+ // Handle TOI events.
+ if (m_continuousPhysics && step.dt > 0.0f)
+ {
+ b2Timer timer;
+ SolveTOI(step);
+ m_profile.solveTOI = timer.GetMilliseconds();
+ }
+
+ if (step.dt > 0.0f)
+ {
+ m_inv_dt0 = step.inv_dt;
+ }
+
+ if (m_clearForces)
+ {
+ ClearForces();
+ }
+
+ m_locked = false;
+
+ m_profile.step = stepTimer.GetMilliseconds();
+}
+
+void b2World::ClearForces()
+{
+ for (b2Body* body = m_bodyList; body; body = body->GetNext())
+ {
+ body->m_force.SetZero();
+ body->m_torque = 0.0f;
+ }
+}
+
+struct b2WorldQueryWrapper
+{
+ bool QueryCallback(int32 proxyId)
+ {
+ b2FixtureProxy* proxy = (b2FixtureProxy*)broadPhase->GetUserData(proxyId);
+ return callback->ReportFixture(proxy->fixture);
+ }
+
+ const b2BroadPhase* broadPhase;
+ b2QueryCallback* callback;
+};
+
+void b2World::QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const
+{
+ b2WorldQueryWrapper wrapper;
+ wrapper.broadPhase = &m_contactManager.m_broadPhase;
+ wrapper.callback = callback;
+ m_contactManager.m_broadPhase.Query(&wrapper, aabb);
+}
+
+struct b2WorldRayCastWrapper
+{
+ float RayCastCallback(const b2RayCastInput& input, int32 proxyId)
+ {
+ void* userData = broadPhase->GetUserData(proxyId);
+ b2FixtureProxy* proxy = (b2FixtureProxy*)userData;
+ b2Fixture* fixture = proxy->fixture;
+ int32 index = proxy->childIndex;
+ b2RayCastOutput output;
+ bool hit = fixture->RayCast(&output, input, index);
+
+ if (hit)
+ {
+ float fraction = output.fraction;
+ b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
+ return callback->ReportFixture(fixture, point, output.normal, fraction);
+ }
+
+ return input.maxFraction;
+ }
+
+ const b2BroadPhase* broadPhase;
+ b2RayCastCallback* callback;
+};
+
+void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const
+{
+ b2WorldRayCastWrapper wrapper;
+ wrapper.broadPhase = &m_contactManager.m_broadPhase;
+ wrapper.callback = callback;
+ b2RayCastInput input;
+ input.maxFraction = 1.0f;
+ input.p1 = point1;
+ input.p2 = point2;
+ m_contactManager.m_broadPhase.RayCast(&wrapper, input);
+}
+
+void b2World::DrawShape(b2Fixture* fixture, const b2Transform& xf, const b2Color& color)
+{
+ switch (fixture->GetType())
+ {
+ case b2Shape::e_circle:
+ {
+ b2CircleShape* circle = (b2CircleShape*)fixture->GetShape();
+
+ b2Vec2 center = b2Mul(xf, circle->m_p);
+ float radius = circle->m_radius;
+ b2Vec2 axis = b2Mul(xf.q, b2Vec2(1.0f, 0.0f));
+
+ m_debugDraw->DrawSolidCircle(center, radius, axis, color);
+ }
+ break;
+
+ case b2Shape::e_edge:
+ {
+ b2EdgeShape* edge = (b2EdgeShape*)fixture->GetShape();
+ b2Vec2 v1 = b2Mul(xf, edge->m_vertex1);
+ b2Vec2 v2 = b2Mul(xf, edge->m_vertex2);
+ m_debugDraw->DrawSegment(v1, v2, color);
+
+ if (edge->m_oneSided == false)
+ {
+ m_debugDraw->DrawPoint(v1, 4.0f, color);
+ m_debugDraw->DrawPoint(v2, 4.0f, color);
+ }
+ }
+ break;
+
+ case b2Shape::e_chain:
+ {
+ b2ChainShape* chain = (b2ChainShape*)fixture->GetShape();
+ int32 count = chain->m_count;
+ const b2Vec2* vertices = chain->m_vertices;
+
+ b2Vec2 v1 = b2Mul(xf, vertices[0]);
+ for (int32 i = 1; i < count; ++i)
+ {
+ b2Vec2 v2 = b2Mul(xf, vertices[i]);
+ m_debugDraw->DrawSegment(v1, v2, color);
+ v1 = v2;
+ }
+ }
+ break;
+
+ case b2Shape::e_polygon:
+ {
+ b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape();
+ int32 vertexCount = poly->m_count;
+ b2Assert(vertexCount <= b2_maxPolygonVertices);
+ b2Vec2 vertices[b2_maxPolygonVertices];
+
+ for (int32 i = 0; i < vertexCount; ++i)
+ {
+ vertices[i] = b2Mul(xf, poly->m_vertices[i]);
+ }
+
+ m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void b2World::DebugDraw()
+{
+ if (m_debugDraw == nullptr)
+ {
+ return;
+ }
+
+ uint32 flags = m_debugDraw->GetFlags();
+
+ if (flags & b2Draw::e_shapeBit)
+ {
+ for (b2Body* b = m_bodyList; b; b = b->GetNext())
+ {
+ const b2Transform& xf = b->GetTransform();
+ for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext())
+ {
+ if (b->GetType() == b2_dynamicBody && b->m_mass == 0.0f)
+ {
+ // Bad body
+ DrawShape(f, xf, b2Color(1.0f, 0.0f, 0.0f));
+ }
+ else if (b->IsEnabled() == false)
+ {
+ DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.3f));
+ }
+ else if (b->GetType() == b2_staticBody)
+ {
+ DrawShape(f, xf, b2Color(0.5f, 0.9f, 0.5f));
+ }
+ else if (b->GetType() == b2_kinematicBody)
+ {
+ DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.9f));
+ }
+ else if (b->IsAwake() == false)
+ {
+ DrawShape(f, xf, b2Color(0.6f, 0.6f, 0.6f));
+ }
+ else
+ {
+ DrawShape(f, xf, b2Color(0.9f, 0.7f, 0.7f));
+ }
+ }
+ }
+ }
+
+ if (flags & b2Draw::e_jointBit)
+ {
+ for (b2Joint* j = m_jointList; j; j = j->GetNext())
+ {
+ j->Draw(m_debugDraw);
+ }
+ }
+
+ if (flags & b2Draw::e_pairBit)
+ {
+ b2Color color(0.3f, 0.9f, 0.9f);
+ for (b2Contact* c = m_contactManager.m_contactList; c; c = c->GetNext())
+ {
+ b2Fixture* fixtureA = c->GetFixtureA();
+ b2Fixture* fixtureB = c->GetFixtureB();
+ int32 indexA = c->GetChildIndexA();
+ int32 indexB = c->GetChildIndexB();
+ b2Vec2 cA = fixtureA->GetAABB(indexA).GetCenter();
+ b2Vec2 cB = fixtureB->GetAABB(indexB).GetCenter();
+
+ m_debugDraw->DrawSegment(cA, cB, color);
+ }
+ }
+
+ if (flags & b2Draw::e_aabbBit)
+ {
+ b2Color color(0.9f, 0.3f, 0.9f);
+ b2BroadPhase* bp = &m_contactManager.m_broadPhase;
+
+ for (b2Body* b = m_bodyList; b; b = b->GetNext())
+ {
+ if (b->IsEnabled() == false)
+ {
+ continue;
+ }
+
+ for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext())
+ {
+ for (int32 i = 0; i < f->m_proxyCount; ++i)
+ {
+ b2FixtureProxy* proxy = f->m_proxies + i;
+ b2AABB aabb = bp->GetFatAABB(proxy->proxyId);
+ b2Vec2 vs[4];
+ vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y);
+ vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y);
+ vs[2].Set(aabb.upperBound.x, aabb.upperBound.y);
+ vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y);
+
+ m_debugDraw->DrawPolygon(vs, 4, color);
+ }
+ }
+ }
+ }
+
+ if (flags & b2Draw::e_centerOfMassBit)
+ {
+ for (b2Body* b = m_bodyList; b; b = b->GetNext())
+ {
+ b2Transform xf = b->GetTransform();
+ xf.p = b->GetWorldCenter();
+ m_debugDraw->DrawTransform(xf);
+ }
+ }
+}
+
+int32 b2World::GetProxyCount() const
+{
+ return m_contactManager.m_broadPhase.GetProxyCount();
+}
+
+int32 b2World::GetTreeHeight() const
+{
+ return m_contactManager.m_broadPhase.GetTreeHeight();
+}
+
+int32 b2World::GetTreeBalance() const
+{
+ return m_contactManager.m_broadPhase.GetTreeBalance();
+}
+
+float b2World::GetTreeQuality() const
+{
+ return m_contactManager.m_broadPhase.GetTreeQuality();
+}
+
+void b2World::ShiftOrigin(const b2Vec2& newOrigin)
+{
+ b2Assert(m_locked == false);
+ if (m_locked)
+ {
+ return;
+ }
+
+ for (b2Body* b = m_bodyList; b; b = b->m_next)
+ {
+ b->m_xf.p -= newOrigin;
+ b->m_sweep.c0 -= newOrigin;
+ b->m_sweep.c -= newOrigin;
+ }
+
+ for (b2Joint* j = m_jointList; j; j = j->m_next)
+ {
+ j->ShiftOrigin(newOrigin);
+ }
+
+ m_contactManager.m_broadPhase.ShiftOrigin(newOrigin);
+}
+
+void b2World::Dump()
+{
+ if (m_locked)
+ {
+ return;
+ }
+
+ b2OpenDump("box2d_dump.inl");
+
+ b2Dump("b2Vec2 g(%.9g, %.9g);\n", m_gravity.x, m_gravity.y);
+ b2Dump("m_world->SetGravity(g);\n");
+
+ b2Dump("b2Body** bodies = (b2Body**)b2Alloc(%d * sizeof(b2Body*));\n", m_bodyCount);
+ b2Dump("b2Joint** joints = (b2Joint**)b2Alloc(%d * sizeof(b2Joint*));\n", m_jointCount);
+
+ int32 i = 0;
+ for (b2Body* b = m_bodyList; b; b = b->m_next)
+ {
+ b->m_islandIndex = i;
+ b->Dump();
+ ++i;
+ }
+
+ i = 0;
+ for (b2Joint* j = m_jointList; j; j = j->m_next)
+ {
+ j->m_index = i;
+ ++i;
+ }
+
+ // First pass on joints, skip gear joints.
+ for (b2Joint* j = m_jointList; j; j = j->m_next)
+ {
+ if (j->m_type == e_gearJoint)
+ {
+ continue;
+ }
+
+ b2Dump("{\n");
+ j->Dump();
+ b2Dump("}\n");
+ }
+
+ // Second pass on joints, only gear joints.
+ for (b2Joint* j = m_jointList; j; j = j->m_next)
+ {
+ if (j->m_type != e_gearJoint)
+ {
+ continue;
+ }
+
+ b2Dump("{\n");
+ j->Dump();
+ b2Dump("}\n");
+ }
+
+ b2Dump("b2Free(joints);\n");
+ b2Dump("b2Free(bodies);\n");
+ b2Dump("joints = nullptr;\n");
+ b2Dump("bodies = nullptr;\n");
+
+ b2CloseDump();
+}
diff --git a/Client/ThirdParty/Box2D/src/dynamics/b2_world_callbacks.cpp b/Client/ThirdParty/Box2D/src/dynamics/b2_world_callbacks.cpp
new file mode 100644
index 0000000..e1583e2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/dynamics/b2_world_callbacks.cpp
@@ -0,0 +1,40 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_fixture.h"
+#include "box2d/b2_world_callbacks.h"
+
+// Return true if contact calculations should be performed between these two shapes.
+// If you implement your own collision filter you may want to build from this implementation.
+bool b2ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
+{
+ const b2Filter& filterA = fixtureA->GetFilterData();
+ const b2Filter& filterB = fixtureB->GetFilterData();
+
+ if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0)
+ {
+ return filterA.groupIndex > 0;
+ }
+
+ bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0;
+ return collide;
+}
diff --git a/Client/ThirdParty/Box2D/src/rope/b2_rope.cpp b/Client/ThirdParty/Box2D/src/rope/b2_rope.cpp
new file mode 100644
index 0000000..d2425a2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/src/rope/b2_rope.cpp
@@ -0,0 +1,809 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/b2_draw.h"
+#include "box2d/b2_rope.h"
+
+#include <stdio.h>
+
+struct b2RopeStretch
+{
+ int32 i1, i2;
+ float invMass1, invMass2;
+ float L;
+ float lambda;
+ float spring;
+ float damper;
+};
+
+struct b2RopeBend
+{
+ int32 i1, i2, i3;
+ float invMass1, invMass2, invMass3;
+ float invEffectiveMass;
+ float lambda;
+ float L1, L2;
+ float alpha1, alpha2;
+ float spring;
+ float damper;
+};
+
+b2Rope::b2Rope()
+{
+ m_position.SetZero();
+ m_count = 0;
+ m_stretchCount = 0;
+ m_bendCount = 0;
+ m_stretchConstraints = nullptr;
+ m_bendConstraints = nullptr;
+ m_bindPositions = nullptr;
+ m_ps = nullptr;
+ m_p0s = nullptr;
+ m_vs = nullptr;
+ m_invMasses = nullptr;
+ m_gravity.SetZero();
+}
+
+b2Rope::~b2Rope()
+{
+ b2Free(m_stretchConstraints);
+ b2Free(m_bendConstraints);
+ b2Free(m_bindPositions);
+ b2Free(m_ps);
+ b2Free(m_p0s);
+ b2Free(m_vs);
+ b2Free(m_invMasses);
+}
+
+void b2Rope::Create(const b2RopeDef& def)
+{
+ b2Assert(def.count >= 3);
+ m_position = def.position;
+ m_count = def.count;
+ m_bindPositions = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
+ m_ps = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
+ m_p0s = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
+ m_vs = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
+ m_invMasses = (float*)b2Alloc(m_count * sizeof(float));
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ m_bindPositions[i] = def.vertices[i];
+ m_ps[i] = def.vertices[i] + m_position;
+ m_p0s[i] = def.vertices[i] + m_position;
+ m_vs[i].SetZero();
+
+ float m = def.masses[i];
+ if (m > 0.0f)
+ {
+ m_invMasses[i] = 1.0f / m;
+ }
+ else
+ {
+ m_invMasses[i] = 0.0f;
+ }
+ }
+
+ m_stretchCount = m_count - 1;
+ m_bendCount = m_count - 2;
+
+ m_stretchConstraints = (b2RopeStretch*)b2Alloc(m_stretchCount * sizeof(b2RopeStretch));
+ m_bendConstraints = (b2RopeBend*)b2Alloc(m_bendCount * sizeof(b2RopeBend));
+
+ for (int32 i = 0; i < m_stretchCount; ++i)
+ {
+ b2RopeStretch& c = m_stretchConstraints[i];
+
+ b2Vec2 p1 = m_ps[i];
+ b2Vec2 p2 = m_ps[i+1];
+
+ c.i1 = i;
+ c.i2 = i + 1;
+ c.L = b2Distance(p1, p2);
+ c.invMass1 = m_invMasses[i];
+ c.invMass2 = m_invMasses[i + 1];
+ c.lambda = 0.0f;
+ c.damper = 0.0f;
+ c.spring = 0.0f;
+ }
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ b2RopeBend& c = m_bendConstraints[i];
+
+ b2Vec2 p1 = m_ps[i];
+ b2Vec2 p2 = m_ps[i + 1];
+ b2Vec2 p3 = m_ps[i + 2];
+
+ c.i1 = i;
+ c.i2 = i + 1;
+ c.i3 = i + 2;
+ c.invMass1 = m_invMasses[i];
+ c.invMass2 = m_invMasses[i + 1];
+ c.invMass3 = m_invMasses[i + 2];
+ c.invEffectiveMass = 0.0f;
+ c.L1 = b2Distance(p1, p2);
+ c.L2 = b2Distance(p2, p3);
+ c.lambda = 0.0f;
+
+ // Pre-compute effective mass (TODO use flattened config)
+ b2Vec2 e1 = p2 - p1;
+ b2Vec2 e2 = p3 - p2;
+ float L1sqr = e1.LengthSquared();
+ float L2sqr = e2.LengthSquared();
+
+ if (L1sqr * L2sqr == 0.0f)
+ {
+ continue;
+ }
+
+ b2Vec2 Jd1 = (-1.0f / L1sqr) * e1.Skew();
+ b2Vec2 Jd2 = (1.0f / L2sqr) * e2.Skew();
+
+ b2Vec2 J1 = -Jd1;
+ b2Vec2 J2 = Jd1 - Jd2;
+ b2Vec2 J3 = Jd2;
+
+ c.invEffectiveMass = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
+
+ b2Vec2 r = p3 - p1;
+
+ float rr = r.LengthSquared();
+ if (rr == 0.0f)
+ {
+ continue;
+ }
+
+ // a1 = h2 / (h1 + h2)
+ // a2 = h1 / (h1 + h2)
+ c.alpha1 = b2Dot(e2, r) / rr;
+ c.alpha2 = b2Dot(e1, r) / rr;
+ }
+
+ m_gravity = def.gravity;
+
+ SetTuning(def.tuning);
+}
+
+void b2Rope::SetTuning(const b2RopeTuning& tuning)
+{
+ m_tuning = tuning;
+
+ // Pre-compute spring and damper values based on tuning
+
+ const float bendOmega = 2.0f * b2_pi * m_tuning.bendHertz;
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ b2RopeBend& c = m_bendConstraints[i];
+
+ float L1sqr = c.L1 * c.L1;
+ float L2sqr = c.L2 * c.L2;
+
+ if (L1sqr * L2sqr == 0.0f)
+ {
+ c.spring = 0.0f;
+ c.damper = 0.0f;
+ continue;
+ }
+
+ // Flatten the triangle formed by the two edges
+ float J2 = 1.0f / c.L1 + 1.0f / c.L2;
+ float sum = c.invMass1 / L1sqr + c.invMass2 * J2 * J2 + c.invMass3 / L2sqr;
+ if (sum == 0.0f)
+ {
+ c.spring = 0.0f;
+ c.damper = 0.0f;
+ continue;
+ }
+
+ float mass = 1.0f / sum;
+
+ c.spring = mass * bendOmega * bendOmega;
+ c.damper = 2.0f * mass * m_tuning.bendDamping * bendOmega;
+ }
+
+ const float stretchOmega = 2.0f * b2_pi * m_tuning.stretchHertz;
+
+ for (int32 i = 0; i < m_stretchCount; ++i)
+ {
+ b2RopeStretch& c = m_stretchConstraints[i];
+
+ float sum = c.invMass1 + c.invMass2;
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ float mass = 1.0f / sum;
+
+ c.spring = mass * stretchOmega * stretchOmega;
+ c.damper = 2.0f * mass * m_tuning.stretchDamping * stretchOmega;
+ }
+}
+
+void b2Rope::Step(float dt, int32 iterations, const b2Vec2& position)
+{
+ if (dt == 0.0)
+ {
+ return;
+ }
+
+ const float inv_dt = 1.0f / dt;
+ float d = expf(- dt * m_tuning.damping);
+
+ // Apply gravity and damping
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ if (m_invMasses[i] > 0.0f)
+ {
+ m_vs[i] *= d;
+ m_vs[i] += dt * m_gravity;
+ }
+ else
+ {
+ m_vs[i] = inv_dt * (m_bindPositions[i] + position - m_p0s[i]);
+ }
+ }
+
+ // Apply bending spring
+ if (m_tuning.bendingModel == b2_springAngleBendingModel)
+ {
+ ApplyBendForces(dt);
+ }
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ m_bendConstraints[i].lambda = 0.0f;
+ }
+
+ for (int32 i = 0; i < m_stretchCount; ++i)
+ {
+ m_stretchConstraints[i].lambda = 0.0f;
+ }
+
+ // Update position
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ m_ps[i] += dt * m_vs[i];
+ }
+
+ // Solve constraints
+ for (int32 i = 0; i < iterations; ++i)
+ {
+ if (m_tuning.bendingModel == b2_pbdAngleBendingModel)
+ {
+ SolveBend_PBD_Angle();
+ }
+ else if (m_tuning.bendingModel == b2_xpbdAngleBendingModel)
+ {
+ SolveBend_XPBD_Angle(dt);
+ }
+ else if (m_tuning.bendingModel == b2_pbdDistanceBendingModel)
+ {
+ SolveBend_PBD_Distance();
+ }
+ else if (m_tuning.bendingModel == b2_pbdHeightBendingModel)
+ {
+ SolveBend_PBD_Height();
+ }
+ else if (m_tuning.bendingModel == b2_pbdTriangleBendingModel)
+ {
+ SolveBend_PBD_Triangle();
+ }
+
+ if (m_tuning.stretchingModel == b2_pbdStretchingModel)
+ {
+ SolveStretch_PBD();
+ }
+ else if (m_tuning.stretchingModel == b2_xpbdStretchingModel)
+ {
+ SolveStretch_XPBD(dt);
+ }
+ }
+
+ // Constrain velocity
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ m_vs[i] = inv_dt * (m_ps[i] - m_p0s[i]);
+ m_p0s[i] = m_ps[i];
+ }
+}
+
+void b2Rope::Reset(const b2Vec2& position)
+{
+ m_position = position;
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ m_ps[i] = m_bindPositions[i] + m_position;
+ m_p0s[i] = m_bindPositions[i] + m_position;
+ m_vs[i].SetZero();
+ }
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ m_bendConstraints[i].lambda = 0.0f;
+ }
+
+ for (int32 i = 0; i < m_stretchCount; ++i)
+ {
+ m_stretchConstraints[i].lambda = 0.0f;
+ }
+}
+
+void b2Rope::SolveStretch_PBD()
+{
+ const float stiffness = m_tuning.stretchStiffness;
+
+ for (int32 i = 0; i < m_stretchCount; ++i)
+ {
+ const b2RopeStretch& c = m_stretchConstraints[i];
+
+ b2Vec2 p1 = m_ps[c.i1];
+ b2Vec2 p2 = m_ps[c.i2];
+
+ b2Vec2 d = p2 - p1;
+ float L = d.Normalize();
+
+ float sum = c.invMass1 + c.invMass2;
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ float s1 = c.invMass1 / sum;
+ float s2 = c.invMass2 / sum;
+
+ p1 -= stiffness * s1 * (c.L - L) * d;
+ p2 += stiffness * s2 * (c.L - L) * d;
+
+ m_ps[c.i1] = p1;
+ m_ps[c.i2] = p2;
+ }
+}
+
+void b2Rope::SolveStretch_XPBD(float dt)
+{
+ b2Assert(dt > 0.0f);
+
+ for (int32 i = 0; i < m_stretchCount; ++i)
+ {
+ b2RopeStretch& c = m_stretchConstraints[i];
+
+ b2Vec2 p1 = m_ps[c.i1];
+ b2Vec2 p2 = m_ps[c.i2];
+
+ b2Vec2 dp1 = p1 - m_p0s[c.i1];
+ b2Vec2 dp2 = p2 - m_p0s[c.i2];
+
+ b2Vec2 u = p2 - p1;
+ float L = u.Normalize();
+
+ b2Vec2 J1 = -u;
+ b2Vec2 J2 = u;
+
+ float sum = c.invMass1 + c.invMass2;
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ const float alpha = 1.0f / (c.spring * dt * dt); // 1 / kg
+ const float beta = dt * dt * c.damper; // kg * s
+ const float sigma = alpha * beta / dt; // non-dimensional
+ float C = L - c.L;
+
+ // This is using the initial velocities
+ float Cdot = b2Dot(J1, dp1) + b2Dot(J2, dp2);
+
+ float B = C + alpha * c.lambda + sigma * Cdot;
+ float sum2 = (1.0f + sigma) * sum + alpha;
+
+ float impulse = -B / sum2;
+
+ p1 += (c.invMass1 * impulse) * J1;
+ p2 += (c.invMass2 * impulse) * J2;
+
+ m_ps[c.i1] = p1;
+ m_ps[c.i2] = p2;
+ c.lambda += impulse;
+ }
+}
+
+void b2Rope::SolveBend_PBD_Angle()
+{
+ const float stiffness = m_tuning.bendStiffness;
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ const b2RopeBend& c = m_bendConstraints[i];
+
+ b2Vec2 p1 = m_ps[c.i1];
+ b2Vec2 p2 = m_ps[c.i2];
+ b2Vec2 p3 = m_ps[c.i3];
+
+ b2Vec2 d1 = p2 - p1;
+ b2Vec2 d2 = p3 - p2;
+ float a = b2Cross(d1, d2);
+ float b = b2Dot(d1, d2);
+
+ float angle = b2Atan2(a, b);
+
+ float L1sqr, L2sqr;
+
+ if (m_tuning.isometric)
+ {
+ L1sqr = c.L1 * c.L1;
+ L2sqr = c.L2 * c.L2;
+ }
+ else
+ {
+ L1sqr = d1.LengthSquared();
+ L2sqr = d2.LengthSquared();
+ }
+
+ if (L1sqr * L2sqr == 0.0f)
+ {
+ continue;
+ }
+
+ b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
+ b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
+
+ b2Vec2 J1 = -Jd1;
+ b2Vec2 J2 = Jd1 - Jd2;
+ b2Vec2 J3 = Jd2;
+
+ float sum;
+ if (m_tuning.fixedEffectiveMass)
+ {
+ sum = c.invEffectiveMass;
+ }
+ else
+ {
+ sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
+ }
+
+ if (sum == 0.0f)
+ {
+ sum = c.invEffectiveMass;
+ }
+
+ float impulse = -stiffness * angle / sum;
+
+ p1 += (c.invMass1 * impulse) * J1;
+ p2 += (c.invMass2 * impulse) * J2;
+ p3 += (c.invMass3 * impulse) * J3;
+
+ m_ps[c.i1] = p1;
+ m_ps[c.i2] = p2;
+ m_ps[c.i3] = p3;
+ }
+}
+
+void b2Rope::SolveBend_XPBD_Angle(float dt)
+{
+ b2Assert(dt > 0.0f);
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ b2RopeBend& c = m_bendConstraints[i];
+
+ b2Vec2 p1 = m_ps[c.i1];
+ b2Vec2 p2 = m_ps[c.i2];
+ b2Vec2 p3 = m_ps[c.i3];
+
+ b2Vec2 dp1 = p1 - m_p0s[c.i1];
+ b2Vec2 dp2 = p2 - m_p0s[c.i2];
+ b2Vec2 dp3 = p3 - m_p0s[c.i3];
+
+ b2Vec2 d1 = p2 - p1;
+ b2Vec2 d2 = p3 - p2;
+
+ float L1sqr, L2sqr;
+
+ if (m_tuning.isometric)
+ {
+ L1sqr = c.L1 * c.L1;
+ L2sqr = c.L2 * c.L2;
+ }
+ else
+ {
+ L1sqr = d1.LengthSquared();
+ L2sqr = d2.LengthSquared();
+ }
+
+ if (L1sqr * L2sqr == 0.0f)
+ {
+ continue;
+ }
+
+ float a = b2Cross(d1, d2);
+ float b = b2Dot(d1, d2);
+
+ float angle = b2Atan2(a, b);
+
+ b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
+ b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
+
+ b2Vec2 J1 = -Jd1;
+ b2Vec2 J2 = Jd1 - Jd2;
+ b2Vec2 J3 = Jd2;
+
+ float sum;
+ if (m_tuning.fixedEffectiveMass)
+ {
+ sum = c.invEffectiveMass;
+ }
+ else
+ {
+ sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
+ }
+
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ const float alpha = 1.0f / (c.spring * dt * dt);
+ const float beta = dt * dt * c.damper;
+ const float sigma = alpha * beta / dt;
+ float C = angle;
+
+ // This is using the initial velocities
+ float Cdot = b2Dot(J1, dp1) + b2Dot(J2, dp2) + b2Dot(J3, dp3);
+
+ float B = C + alpha * c.lambda + sigma * Cdot;
+ float sum2 = (1.0f + sigma) * sum + alpha;
+
+ float impulse = -B / sum2;
+
+ p1 += (c.invMass1 * impulse) * J1;
+ p2 += (c.invMass2 * impulse) * J2;
+ p3 += (c.invMass3 * impulse) * J3;
+
+ m_ps[c.i1] = p1;
+ m_ps[c.i2] = p2;
+ m_ps[c.i3] = p3;
+ c.lambda += impulse;
+ }
+}
+
+void b2Rope::ApplyBendForces(float dt)
+{
+ // omega = 2 * pi * hz
+ const float omega = 2.0f * b2_pi * m_tuning.bendHertz;
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ const b2RopeBend& c = m_bendConstraints[i];
+
+ b2Vec2 p1 = m_ps[c.i1];
+ b2Vec2 p2 = m_ps[c.i2];
+ b2Vec2 p3 = m_ps[c.i3];
+
+ b2Vec2 v1 = m_vs[c.i1];
+ b2Vec2 v2 = m_vs[c.i2];
+ b2Vec2 v3 = m_vs[c.i3];
+
+ b2Vec2 d1 = p2 - p1;
+ b2Vec2 d2 = p3 - p2;
+
+ float L1sqr, L2sqr;
+
+ if (m_tuning.isometric)
+ {
+ L1sqr = c.L1 * c.L1;
+ L2sqr = c.L2 * c.L2;
+ }
+ else
+ {
+ L1sqr = d1.LengthSquared();
+ L2sqr = d2.LengthSquared();
+ }
+
+ if (L1sqr * L2sqr == 0.0f)
+ {
+ continue;
+ }
+
+ float a = b2Cross(d1, d2);
+ float b = b2Dot(d1, d2);
+
+ float angle = b2Atan2(a, b);
+
+ b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
+ b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
+
+ b2Vec2 J1 = -Jd1;
+ b2Vec2 J2 = Jd1 - Jd2;
+ b2Vec2 J3 = Jd2;
+
+ float sum;
+ if (m_tuning.fixedEffectiveMass)
+ {
+ sum = c.invEffectiveMass;
+ }
+ else
+ {
+ sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3);
+ }
+
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ float mass = 1.0f / sum;
+
+ const float spring = mass * omega * omega;
+ const float damper = 2.0f * mass * m_tuning.bendDamping * omega;
+
+ float C = angle;
+ float Cdot = b2Dot(J1, v1) + b2Dot(J2, v2) + b2Dot(J3, v3);
+
+ float impulse = -dt * (spring * C + damper * Cdot);
+
+ m_vs[c.i1] += (c.invMass1 * impulse) * J1;
+ m_vs[c.i2] += (c.invMass2 * impulse) * J2;
+ m_vs[c.i3] += (c.invMass3 * impulse) * J3;
+ }
+}
+
+void b2Rope::SolveBend_PBD_Distance()
+{
+ const float stiffness = m_tuning.bendStiffness;
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ const b2RopeBend& c = m_bendConstraints[i];
+
+ int32 i1 = c.i1;
+ int32 i2 = c.i3;
+
+ b2Vec2 p1 = m_ps[i1];
+ b2Vec2 p2 = m_ps[i2];
+
+ b2Vec2 d = p2 - p1;
+ float L = d.Normalize();
+
+ float sum = c.invMass1 + c.invMass3;
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ float s1 = c.invMass1 / sum;
+ float s2 = c.invMass3 / sum;
+
+ p1 -= stiffness * s1 * (c.L1 + c.L2 - L) * d;
+ p2 += stiffness * s2 * (c.L1 + c.L2 - L) * d;
+
+ m_ps[i1] = p1;
+ m_ps[i2] = p2;
+ }
+}
+
+// Constraint based implementation of:
+// P. Volino: Simple Linear Bending Stiffness in Particle Systems
+void b2Rope::SolveBend_PBD_Height()
+{
+ const float stiffness = m_tuning.bendStiffness;
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ const b2RopeBend& c = m_bendConstraints[i];
+
+ b2Vec2 p1 = m_ps[c.i1];
+ b2Vec2 p2 = m_ps[c.i2];
+ b2Vec2 p3 = m_ps[c.i3];
+
+ // Barycentric coordinates are held constant
+ b2Vec2 d = c.alpha1 * p1 + c.alpha2 * p3 - p2;
+ float dLen = d.Length();
+
+ if (dLen == 0.0f)
+ {
+ continue;
+ }
+
+ b2Vec2 dHat = (1.0f / dLen) * d;
+
+ b2Vec2 J1 = c.alpha1 * dHat;
+ b2Vec2 J2 = -dHat;
+ b2Vec2 J3 = c.alpha2 * dHat;
+
+ float sum = c.invMass1 * c.alpha1 * c.alpha1 + c.invMass2 + c.invMass3 * c.alpha2 * c.alpha2;
+
+ if (sum == 0.0f)
+ {
+ continue;
+ }
+
+ float C = dLen;
+ float mass = 1.0f / sum;
+ float impulse = -stiffness * mass * C;
+
+ p1 += (c.invMass1 * impulse) * J1;
+ p2 += (c.invMass2 * impulse) * J2;
+ p3 += (c.invMass3 * impulse) * J3;
+
+ m_ps[c.i1] = p1;
+ m_ps[c.i2] = p2;
+ m_ps[c.i3] = p3;
+ }
+}
+
+// M. Kelager: A Triangle Bending Constraint Model for PBD
+void b2Rope::SolveBend_PBD_Triangle()
+{
+ const float stiffness = m_tuning.bendStiffness;
+
+ for (int32 i = 0; i < m_bendCount; ++i)
+ {
+ const b2RopeBend& c = m_bendConstraints[i];
+
+ b2Vec2 b0 = m_ps[c.i1];
+ b2Vec2 v = m_ps[c.i2];
+ b2Vec2 b1 = m_ps[c.i3];
+
+ float wb0 = c.invMass1;
+ float wv = c.invMass2;
+ float wb1 = c.invMass3;
+
+ float W = wb0 + wb1 + 2.0f * wv;
+ float invW = stiffness / W;
+
+ b2Vec2 d = v - (1.0f / 3.0f) * (b0 + v + b1);
+
+ b2Vec2 db0 = 2.0f * wb0 * invW * d;
+ b2Vec2 dv = -4.0f * wv * invW * d;
+ b2Vec2 db1 = 2.0f * wb1 * invW * d;
+
+ b0 += db0;
+ v += dv;
+ b1 += db1;
+
+ m_ps[c.i1] = b0;
+ m_ps[c.i2] = v;
+ m_ps[c.i3] = b1;
+ }
+}
+
+void b2Rope::Draw(b2Draw* draw) const
+{
+ b2Color c(0.4f, 0.5f, 0.7f);
+ b2Color pg(0.1f, 0.8f, 0.1f);
+ b2Color pd(0.7f, 0.2f, 0.4f);
+
+ for (int32 i = 0; i < m_count - 1; ++i)
+ {
+ draw->DrawSegment(m_ps[i], m_ps[i+1], c);
+
+ const b2Color& pc = m_invMasses[i] > 0.0f ? pd : pg;
+ draw->DrawPoint(m_ps[i], 5.0f, pc);
+ }
+
+ const b2Color& pc = m_invMasses[m_count - 1] > 0.0f ? pd : pg;
+ draw->DrawPoint(m_ps[m_count - 1], 5.0f, pc);
+}
diff --git a/Client/ThirdParty/Box2D/testbed/CMakeLists.txt b/Client/ThirdParty/Box2D/testbed/CMakeLists.txt
new file mode 100644
index 0000000..5ef305e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/CMakeLists.txt
@@ -0,0 +1,92 @@
+set (TESTBED_SOURCE_FILES
+ draw.cpp
+ draw.h
+ imgui_impl_glfw.cpp
+ imgui_impl_glfw.h
+ imgui_impl_opengl3.cpp
+ imgui_impl_opengl3.h
+ main.cpp
+ settings.h
+ settings.cpp
+ test.cpp
+ test.h
+ tests/add_pair.cpp
+ tests/apply_force.cpp
+ tests/body_types.cpp
+ tests/box_stack.cpp
+ tests/breakable.cpp
+ tests/bridge.cpp
+ tests/bullet_test.cpp
+ tests/cantilever.cpp
+ tests/car.cpp
+ tests/chain.cpp
+ tests/chain_problem.cpp
+ tests/character_collision.cpp
+ tests/circle_stack.cpp
+ tests/collision_filtering.cpp
+ tests/collision_processing.cpp
+ tests/compound_shapes.cpp
+ tests/confined.cpp
+ tests/continuous_test.cpp
+ tests/convex_hull.cpp
+ tests/conveyor_belt.cpp
+ tests/distance_joint.cpp
+ tests/distance_test.cpp
+ tests/dominos.cpp
+ tests/dump_loader.cpp
+ tests/dynamic_tree.cpp
+ tests/edge_shapes.cpp
+ tests/edge_test.cpp
+ tests/friction.cpp
+ tests/gear_joint.cpp
+ tests/heavy1.cpp
+ tests/heavy2.cpp
+ tests/mobile_balanced.cpp
+ tests/mobile_unbalanced.cpp
+ tests/motor_joint.cpp
+ tests/pinball.cpp
+ tests/platformer.cpp
+ tests/polygon_collision.cpp
+ tests/polygon_shapes.cpp
+ tests/prismatic_joint.cpp
+ tests/pulley_joint.cpp
+ tests/pyramid.cpp
+ tests/ray_cast.cpp
+ tests/restitution.cpp
+ tests/revolute_joint.cpp
+ tests/rope.cpp
+ tests/sensor.cpp
+ tests/shape_cast.cpp
+ tests/shape_editing.cpp
+ tests/skier.cpp
+ tests/slider_crank_1.cpp
+ tests/slider_crank_2.cpp
+ tests/theo_jansen.cpp
+ tests/tiles.cpp
+ tests/time_of_impact.cpp
+ tests/tumbler.cpp
+ tests/web.cpp
+ tests/wheel_joint.cpp
+ tests/wrecking_ball.cpp
+)
+
+add_executable(testbed ${TESTBED_SOURCE_FILES})
+target_include_directories(testbed PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(testbed PUBLIC box2d glfw imgui sajson glad)
+set_target_properties(testbed PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO
+)
+
+# message(STATUS "runtime = ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
+# message(STATUS "binary = ${CMAKE_CURRENT_BINARY_DIR}")
+
+# Copy font files, etc
+add_custom_command(
+ TARGET testbed POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ${CMAKE_CURRENT_SOURCE_DIR}/data/
+ ${CMAKE_CURRENT_BINARY_DIR}/data/)
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${TESTBED_SOURCE_FILES})
diff --git a/Client/ThirdParty/Box2D/testbed/MacOSXBundleInfo.plist.in b/Client/ThirdParty/Box2D/testbed/MacOSXBundleInfo.plist.in
new file mode 100644
index 0000000..8bdb5cd
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/MacOSXBundleInfo.plist.in
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleGetInfoString</key>
+ <string>${MACOSX_BUNDLE_INFO_STRING}</string>
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleLongVersionString</key>
+ <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>LSRequiresCarbon</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+ <key>NSSupportsAutomaticGraphicsSwitching</key>
+ <true/>
+ <key>NSHighResolutionCapable</key>
+ <true/>
+</dict>
+</plist>
+
diff --git a/Client/ThirdParty/Box2D/testbed/data/droid_sans.ttf b/Client/ThirdParty/Box2D/testbed/data/droid_sans.ttf
new file mode 100644
index 0000000..767c63a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/data/droid_sans.ttf
Binary files differ
diff --git a/Client/ThirdParty/Box2D/testbed/draw.cpp b/Client/ThirdParty/Box2D/testbed/draw.cpp
new file mode 100644
index 0000000..03ab6af
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/draw.cpp
@@ -0,0 +1,829 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "draw.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "imgui/imgui.h"
+
+#define BUFFER_OFFSET(x) ((const void*) (x))
+
+DebugDraw g_debugDraw;
+Camera g_camera;
+
+//
+b2Vec2 Camera::ConvertScreenToWorld(const b2Vec2& ps)
+{
+ float w = float(m_width);
+ float h = float(m_height);
+ float u = ps.x / w;
+ float v = (h - ps.y) / h;
+
+ float ratio = w / h;
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= m_zoom;
+
+ b2Vec2 lower = m_center - extents;
+ b2Vec2 upper = m_center + extents;
+
+ b2Vec2 pw;
+ pw.x = (1.0f - u) * lower.x + u * upper.x;
+ pw.y = (1.0f - v) * lower.y + v * upper.y;
+ return pw;
+}
+
+//
+b2Vec2 Camera::ConvertWorldToScreen(const b2Vec2& pw)
+{
+ float w = float(m_width);
+ float h = float(m_height);
+ float ratio = w / h;
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= m_zoom;
+
+ b2Vec2 lower = m_center - extents;
+ b2Vec2 upper = m_center + extents;
+
+ float u = (pw.x - lower.x) / (upper.x - lower.x);
+ float v = (pw.y - lower.y) / (upper.y - lower.y);
+
+ b2Vec2 ps;
+ ps.x = u * w;
+ ps.y = (1.0f - v) * h;
+ return ps;
+}
+
+// Convert from world coordinates to normalized device coordinates.
+// http://www.songho.ca/opengl/gl_projectionmatrix.html
+void Camera::BuildProjectionMatrix(float* m, float zBias)
+{
+ float w = float(m_width);
+ float h = float(m_height);
+ float ratio = w / h;
+ b2Vec2 extents(ratio * 25.0f, 25.0f);
+ extents *= m_zoom;
+
+ b2Vec2 lower = m_center - extents;
+ b2Vec2 upper = m_center + extents;
+
+ m[0] = 2.0f / (upper.x - lower.x);
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = 2.0f / (upper.y - lower.y);
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = 1.0f;
+ m[11] = 0.0f;
+
+ m[12] = -(upper.x + lower.x) / (upper.x - lower.x);
+ m[13] = -(upper.y + lower.y) / (upper.y - lower.y);
+ m[14] = zBias;
+ m[15] = 1.0f;
+}
+
+//
+static void sCheckGLError()
+{
+ GLenum errCode = glGetError();
+ if (errCode != GL_NO_ERROR)
+ {
+ fprintf(stderr, "OpenGL error = %d\n", errCode);
+ assert(false);
+ }
+}
+
+// Prints shader compilation errors
+static void sPrintLog(GLuint object)
+{
+ GLint log_length = 0;
+ if (glIsShader(object))
+ glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
+ else if (glIsProgram(object))
+ glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
+ else
+ {
+ fprintf(stderr, "printlog: Not a shader or a program\n");
+ return;
+ }
+
+ char* log = (char*)malloc(log_length);
+
+ if (glIsShader(object))
+ glGetShaderInfoLog(object, log_length, NULL, log);
+ else if (glIsProgram(object))
+ glGetProgramInfoLog(object, log_length, NULL, log);
+
+ fprintf(stderr, "%s", log);
+ free(log);
+}
+
+
+//
+static GLuint sCreateShaderFromString(const char* source, GLenum type)
+{
+ GLuint res = glCreateShader(type);
+ const char* sources[] = { source };
+ glShaderSource(res, 1, sources, NULL);
+ glCompileShader(res);
+ GLint compile_ok = GL_FALSE;
+ glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
+ if (compile_ok == GL_FALSE)
+ {
+ fprintf(stderr, "Error compiling shader of type %d!\n", type);
+ sPrintLog(res);
+ glDeleteShader(res);
+ return 0;
+ }
+
+ return res;
+}
+
+//
+static GLuint sCreateShaderProgram(const char* vs, const char* fs)
+{
+ GLuint vsId = sCreateShaderFromString(vs, GL_VERTEX_SHADER);
+ GLuint fsId = sCreateShaderFromString(fs, GL_FRAGMENT_SHADER);
+ assert(vsId != 0 && fsId != 0);
+
+ GLuint programId = glCreateProgram();
+ glAttachShader(programId, vsId);
+ glAttachShader(programId, fsId);
+ glBindFragDataLocation(programId, 0, "color");
+ glLinkProgram(programId);
+
+ glDeleteShader(vsId);
+ glDeleteShader(fsId);
+
+ GLint status = GL_FALSE;
+ glGetProgramiv(programId, GL_LINK_STATUS, &status);
+ assert(status != GL_FALSE);
+
+ return programId;
+}
+
+//
+struct GLRenderPoints
+{
+ void Create()
+ {
+ const char* vs = \
+ "#version 330\n"
+ "uniform mat4 projectionMatrix;\n"
+ "layout(location = 0) in vec2 v_position;\n"
+ "layout(location = 1) in vec4 v_color;\n"
+ "layout(location = 2) in float v_size;\n"
+ "out vec4 f_color;\n"
+ "void main(void)\n"
+ "{\n"
+ " f_color = v_color;\n"
+ " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
+ " gl_PointSize = v_size;\n"
+ "}\n";
+
+ const char* fs = \
+ "#version 330\n"
+ "in vec4 f_color;\n"
+ "out vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = f_color;\n"
+ "}\n";
+
+ m_programId = sCreateShaderProgram(vs, fs);
+ m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
+ m_vertexAttribute = 0;
+ m_colorAttribute = 1;
+ m_sizeAttribute = 2;
+
+ // Generate
+ glGenVertexArrays(1, &m_vaoId);
+ glGenBuffers(3, m_vboIds);
+
+ glBindVertexArray(m_vaoId);
+ glEnableVertexAttribArray(m_vertexAttribute);
+ glEnableVertexAttribArray(m_colorAttribute);
+ glEnableVertexAttribArray(m_sizeAttribute);
+
+ // Vertex buffer
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
+ glVertexAttribPointer(m_sizeAttribute, 1, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_sizes), m_sizes, GL_DYNAMIC_DRAW);
+
+ sCheckGLError();
+
+ // Cleanup
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ m_count = 0;
+ }
+
+ void Destroy()
+ {
+ if (m_vaoId)
+ {
+ glDeleteVertexArrays(1, &m_vaoId);
+ glDeleteBuffers(3, m_vboIds);
+ m_vaoId = 0;
+ }
+
+ if (m_programId)
+ {
+ glDeleteProgram(m_programId);
+ m_programId = 0;
+ }
+ }
+
+ void Vertex(const b2Vec2& v, const b2Color& c, float size)
+ {
+ if (m_count == e_maxVertices)
+ Flush();
+
+ m_vertices[m_count] = v;
+ m_colors[m_count] = c;
+ m_sizes[m_count] = size;
+ ++m_count;
+ }
+
+ void Flush()
+ {
+ if (m_count == 0)
+ return;
+
+ glUseProgram(m_programId);
+
+ float proj[16] = { 0.0f };
+ g_camera.BuildProjectionMatrix(proj, 0.0f);
+
+ glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
+
+ glBindVertexArray(m_vaoId);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[2]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(float), m_sizes);
+
+ glEnable(GL_PROGRAM_POINT_SIZE);
+ glDrawArrays(GL_POINTS, 0, m_count);
+ glDisable(GL_PROGRAM_POINT_SIZE);
+
+ sCheckGLError();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ m_count = 0;
+ }
+
+ enum { e_maxVertices = 512 };
+ b2Vec2 m_vertices[e_maxVertices];
+ b2Color m_colors[e_maxVertices];
+ float m_sizes[e_maxVertices];
+
+ int32 m_count;
+
+ GLuint m_vaoId;
+ GLuint m_vboIds[3];
+ GLuint m_programId;
+ GLint m_projectionUniform;
+ GLint m_vertexAttribute;
+ GLint m_colorAttribute;
+ GLint m_sizeAttribute;
+};
+
+//
+struct GLRenderLines
+{
+ void Create()
+ {
+ const char* vs = \
+ "#version 330\n"
+ "uniform mat4 projectionMatrix;\n"
+ "layout(location = 0) in vec2 v_position;\n"
+ "layout(location = 1) in vec4 v_color;\n"
+ "out vec4 f_color;\n"
+ "void main(void)\n"
+ "{\n"
+ " f_color = v_color;\n"
+ " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
+ "}\n";
+
+ const char* fs = \
+ "#version 330\n"
+ "in vec4 f_color;\n"
+ "out vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = f_color;\n"
+ "}\n";
+
+ m_programId = sCreateShaderProgram(vs, fs);
+ m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
+ m_vertexAttribute = 0;
+ m_colorAttribute = 1;
+
+ // Generate
+ glGenVertexArrays(1, &m_vaoId);
+ glGenBuffers(2, m_vboIds);
+
+ glBindVertexArray(m_vaoId);
+ glEnableVertexAttribArray(m_vertexAttribute);
+ glEnableVertexAttribArray(m_colorAttribute);
+
+ // Vertex buffer
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
+
+ sCheckGLError();
+
+ // Cleanup
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ m_count = 0;
+ }
+
+ void Destroy()
+ {
+ if (m_vaoId)
+ {
+ glDeleteVertexArrays(1, &m_vaoId);
+ glDeleteBuffers(2, m_vboIds);
+ m_vaoId = 0;
+ }
+
+ if (m_programId)
+ {
+ glDeleteProgram(m_programId);
+ m_programId = 0;
+ }
+ }
+
+ void Vertex(const b2Vec2& v, const b2Color& c)
+ {
+ if (m_count == e_maxVertices)
+ Flush();
+
+ m_vertices[m_count] = v;
+ m_colors[m_count] = c;
+ ++m_count;
+ }
+
+ void Flush()
+ {
+ if (m_count == 0)
+ return;
+
+ glUseProgram(m_programId);
+
+ float proj[16] = { 0.0f };
+ g_camera.BuildProjectionMatrix(proj, 0.1f);
+
+ glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
+
+ glBindVertexArray(m_vaoId);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
+
+ glDrawArrays(GL_LINES, 0, m_count);
+
+ sCheckGLError();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ m_count = 0;
+ }
+
+ enum { e_maxVertices = 2 * 512 };
+ b2Vec2 m_vertices[e_maxVertices];
+ b2Color m_colors[e_maxVertices];
+
+ int32 m_count;
+
+ GLuint m_vaoId;
+ GLuint m_vboIds[2];
+ GLuint m_programId;
+ GLint m_projectionUniform;
+ GLint m_vertexAttribute;
+ GLint m_colorAttribute;
+};
+
+//
+struct GLRenderTriangles
+{
+ void Create()
+ {
+ const char* vs = \
+ "#version 330\n"
+ "uniform mat4 projectionMatrix;\n"
+ "layout(location = 0) in vec2 v_position;\n"
+ "layout(location = 1) in vec4 v_color;\n"
+ "out vec4 f_color;\n"
+ "void main(void)\n"
+ "{\n"
+ " f_color = v_color;\n"
+ " gl_Position = projectionMatrix * vec4(v_position, 0.0f, 1.0f);\n"
+ "}\n";
+
+ const char* fs = \
+ "#version 330\n"
+ "in vec4 f_color;\n"
+ "out vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = f_color;\n"
+ "}\n";
+
+ m_programId = sCreateShaderProgram(vs, fs);
+ m_projectionUniform = glGetUniformLocation(m_programId, "projectionMatrix");
+ m_vertexAttribute = 0;
+ m_colorAttribute = 1;
+
+ // Generate
+ glGenVertexArrays(1, &m_vaoId);
+ glGenBuffers(2, m_vboIds);
+
+ glBindVertexArray(m_vaoId);
+ glEnableVertexAttribArray(m_vertexAttribute);
+ glEnableVertexAttribArray(m_colorAttribute);
+
+ // Vertex buffer
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glVertexAttribPointer(m_vertexAttribute, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertices), m_vertices, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glVertexAttribPointer(m_colorAttribute, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
+ glBufferData(GL_ARRAY_BUFFER, sizeof(m_colors), m_colors, GL_DYNAMIC_DRAW);
+
+ sCheckGLError();
+
+ // Cleanup
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+
+ m_count = 0;
+ }
+
+ void Destroy()
+ {
+ if (m_vaoId)
+ {
+ glDeleteVertexArrays(1, &m_vaoId);
+ glDeleteBuffers(2, m_vboIds);
+ m_vaoId = 0;
+ }
+
+ if (m_programId)
+ {
+ glDeleteProgram(m_programId);
+ m_programId = 0;
+ }
+ }
+
+ void Vertex(const b2Vec2& v, const b2Color& c)
+ {
+ if (m_count == e_maxVertices)
+ Flush();
+
+ m_vertices[m_count] = v;
+ m_colors[m_count] = c;
+ ++m_count;
+ }
+
+ void Flush()
+ {
+ if (m_count == 0)
+ return;
+
+ glUseProgram(m_programId);
+
+ float proj[16] = { 0.0f };
+ g_camera.BuildProjectionMatrix(proj, 0.2f);
+
+ glUniformMatrix4fv(m_projectionUniform, 1, GL_FALSE, proj);
+
+ glBindVertexArray(m_vaoId);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Vec2), m_vertices);
+
+ glBindBuffer(GL_ARRAY_BUFFER, m_vboIds[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, m_count * sizeof(b2Color), m_colors);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDrawArrays(GL_TRIANGLES, 0, m_count);
+ glDisable(GL_BLEND);
+
+ sCheckGLError();
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindVertexArray(0);
+ glUseProgram(0);
+
+ m_count = 0;
+ }
+
+ enum { e_maxVertices = 3 * 512 };
+ b2Vec2 m_vertices[e_maxVertices];
+ b2Color m_colors[e_maxVertices];
+
+ int32 m_count;
+
+ GLuint m_vaoId;
+ GLuint m_vboIds[2];
+ GLuint m_programId;
+ GLint m_projectionUniform;
+ GLint m_vertexAttribute;
+ GLint m_colorAttribute;
+};
+
+//
+DebugDraw::DebugDraw()
+{
+ m_showUI = true;
+ m_points = NULL;
+ m_lines = NULL;
+ m_triangles = NULL;
+}
+
+//
+DebugDraw::~DebugDraw()
+{
+ b2Assert(m_points == NULL);
+ b2Assert(m_lines == NULL);
+ b2Assert(m_triangles == NULL);
+}
+
+//
+void DebugDraw::Create()
+{
+ m_points = new GLRenderPoints;
+ m_points->Create();
+ m_lines = new GLRenderLines;
+ m_lines->Create();
+ m_triangles = new GLRenderTriangles;
+ m_triangles->Create();
+}
+
+//
+void DebugDraw::Destroy()
+{
+ m_points->Destroy();
+ delete m_points;
+ m_points = NULL;
+
+ m_lines->Destroy();
+ delete m_lines;
+ m_lines = NULL;
+
+ m_triangles->Destroy();
+ delete m_triangles;
+ m_triangles = NULL;
+}
+
+//
+void DebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
+{
+ b2Vec2 p1 = vertices[vertexCount - 1];
+ for (int32 i = 0; i < vertexCount; ++i)
+ {
+ b2Vec2 p2 = vertices[i];
+ m_lines->Vertex(p1, color);
+ m_lines->Vertex(p2, color);
+ p1 = p2;
+ }
+}
+
+//
+void DebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
+{
+ b2Color fillColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
+
+ for (int32 i = 1; i < vertexCount - 1; ++i)
+ {
+ m_triangles->Vertex(vertices[0], fillColor);
+ m_triangles->Vertex(vertices[i], fillColor);
+ m_triangles->Vertex(vertices[i + 1], fillColor);
+ }
+
+ b2Vec2 p1 = vertices[vertexCount - 1];
+ for (int32 i = 0; i < vertexCount; ++i)
+ {
+ b2Vec2 p2 = vertices[i];
+ m_lines->Vertex(p1, color);
+ m_lines->Vertex(p2, color);
+ p1 = p2;
+ }
+}
+
+//
+void DebugDraw::DrawCircle(const b2Vec2& center, float radius, const b2Color& color)
+{
+ const float k_segments = 16.0f;
+ const float k_increment = 2.0f * b2_pi / k_segments;
+ float sinInc = sinf(k_increment);
+ float cosInc = cosf(k_increment);
+ b2Vec2 r1(1.0f, 0.0f);
+ b2Vec2 v1 = center + radius * r1;
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ // Perform rotation to avoid additional trigonometry.
+ b2Vec2 r2;
+ r2.x = cosInc * r1.x - sinInc * r1.y;
+ r2.y = sinInc * r1.x + cosInc * r1.y;
+ b2Vec2 v2 = center + radius * r2;
+ m_lines->Vertex(v1, color);
+ m_lines->Vertex(v2, color);
+ r1 = r2;
+ v1 = v2;
+ }
+}
+
+//
+void DebugDraw::DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color)
+{
+ const float k_segments = 16.0f;
+ const float k_increment = 2.0f * b2_pi / k_segments;
+ float sinInc = sinf(k_increment);
+ float cosInc = cosf(k_increment);
+ b2Vec2 v0 = center;
+ b2Vec2 r1(cosInc, sinInc);
+ b2Vec2 v1 = center + radius * r1;
+ b2Color fillColor(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ // Perform rotation to avoid additional trigonometry.
+ b2Vec2 r2;
+ r2.x = cosInc * r1.x - sinInc * r1.y;
+ r2.y = sinInc * r1.x + cosInc * r1.y;
+ b2Vec2 v2 = center + radius * r2;
+ m_triangles->Vertex(v0, fillColor);
+ m_triangles->Vertex(v1, fillColor);
+ m_triangles->Vertex(v2, fillColor);
+ r1 = r2;
+ v1 = v2;
+ }
+
+ r1.Set(1.0f, 0.0f);
+ v1 = center + radius * r1;
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 r2;
+ r2.x = cosInc * r1.x - sinInc * r1.y;
+ r2.y = sinInc * r1.x + cosInc * r1.y;
+ b2Vec2 v2 = center + radius * r2;
+ m_lines->Vertex(v1, color);
+ m_lines->Vertex(v2, color);
+ r1 = r2;
+ v1 = v2;
+ }
+
+ // Draw a line fixed in the circle to animate rotation.
+ b2Vec2 p = center + radius * axis;
+ m_lines->Vertex(center, color);
+ m_lines->Vertex(p, color);
+}
+
+//
+void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
+{
+ m_lines->Vertex(p1, color);
+ m_lines->Vertex(p2, color);
+}
+
+//
+void DebugDraw::DrawTransform(const b2Transform& xf)
+{
+ const float k_axisScale = 0.4f;
+ b2Color red(1.0f, 0.0f, 0.0f);
+ b2Color green(0.0f, 1.0f, 0.0f);
+ b2Vec2 p1 = xf.p, p2;
+
+ m_lines->Vertex(p1, red);
+ p2 = p1 + k_axisScale * xf.q.GetXAxis();
+ m_lines->Vertex(p2, red);
+
+ m_lines->Vertex(p1, green);
+ p2 = p1 + k_axisScale * xf.q.GetYAxis();
+ m_lines->Vertex(p2, green);
+}
+
+//
+void DebugDraw::DrawPoint(const b2Vec2& p, float size, const b2Color& color)
+{
+ m_points->Vertex(p, color, size);
+}
+
+//
+void DebugDraw::DrawString(int x, int y, const char* string, ...)
+{
+ if (m_showUI == false)
+ {
+ return;
+ }
+
+ va_list arg;
+ va_start(arg, string);
+ ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
+ ImGui::SetCursorPos(ImVec2(float(x), float(y)));
+ ImGui::TextColoredV(ImColor(230, 153, 153, 255), string, arg);
+ ImGui::End();
+ va_end(arg);
+}
+
+//
+void DebugDraw::DrawString(const b2Vec2& pw, const char* string, ...)
+{
+ b2Vec2 ps = g_camera.ConvertWorldToScreen(pw);
+
+ va_list arg;
+ va_start(arg, string);
+ ImGui::Begin("Overlay", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
+ ImGui::SetCursorPos(ImVec2(ps.x, ps.y));
+ ImGui::TextColoredV(ImColor(230, 153, 153, 255), string, arg);
+ ImGui::End();
+ va_end(arg);
+}
+
+//
+void DebugDraw::DrawAABB(b2AABB* aabb, const b2Color& c)
+{
+ b2Vec2 p1 = aabb->lowerBound;
+ b2Vec2 p2 = b2Vec2(aabb->upperBound.x, aabb->lowerBound.y);
+ b2Vec2 p3 = aabb->upperBound;
+ b2Vec2 p4 = b2Vec2(aabb->lowerBound.x, aabb->upperBound.y);
+
+ m_lines->Vertex(p1, c);
+ m_lines->Vertex(p2, c);
+
+ m_lines->Vertex(p2, c);
+ m_lines->Vertex(p3, c);
+
+ m_lines->Vertex(p3, c);
+ m_lines->Vertex(p4, c);
+
+ m_lines->Vertex(p4, c);
+ m_lines->Vertex(p1, c);
+}
+
+//
+void DebugDraw::Flush()
+{
+ m_triangles->Flush();
+ m_lines->Flush();
+ m_points->Flush();
+}
diff --git a/Client/ThirdParty/Box2D/testbed/draw.h b/Client/ThirdParty/Box2D/testbed/draw.h
new file mode 100644
index 0000000..45ef234
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/draw.h
@@ -0,0 +1,102 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef DRAW_H
+#define DRAW_H
+
+#define GLFW_INCLUDE_NONE
+#include "glad/gl.h"
+#include "GLFW/glfw3.h"
+
+#include "box2d/box2d.h"
+
+struct b2AABB;
+struct GLRenderPoints;
+struct GLRenderLines;
+struct GLRenderTriangles;
+struct GLFWwindow;
+
+//
+struct Camera
+{
+ Camera()
+ {
+ m_center.Set(0.0f, 20.0f);
+ m_zoom = 1.0f;
+ m_width = 1280;
+ m_height = 800;
+ }
+
+ b2Vec2 ConvertScreenToWorld(const b2Vec2& screenPoint);
+ b2Vec2 ConvertWorldToScreen(const b2Vec2& worldPoint);
+ void BuildProjectionMatrix(float* m, float zBias);
+
+ b2Vec2 m_center;
+ float m_zoom;
+ int32 m_width;
+ int32 m_height;
+};
+
+// This class implements debug drawing callbacks that are invoked
+// inside b2World::Step.
+class DebugDraw : public b2Draw
+{
+public:
+ DebugDraw();
+ ~DebugDraw();
+
+ void Create();
+ void Destroy();
+
+ void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override;
+
+ void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) override;
+
+ void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override;
+
+ void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override;
+
+ void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override;
+
+ void DrawTransform(const b2Transform& xf) override;
+
+ void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override;
+
+ void DrawString(int x, int y, const char* string, ...);
+
+ void DrawString(const b2Vec2& p, const char* string, ...);
+
+ void DrawAABB(b2AABB* aabb, const b2Color& color);
+
+ void Flush();
+
+ bool m_showUI;
+ GLRenderPoints* m_points;
+ GLRenderLines* m_lines;
+ GLRenderTriangles* m_triangles;
+};
+
+extern DebugDraw g_debugDraw;
+extern Camera g_camera;
+extern GLFWwindow* g_mainWindow;
+
+#endif
diff --git a/Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.cpp b/Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.cpp
new file mode 100644
index 0000000..359eece
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.cpp
@@ -0,0 +1,324 @@
+// dear imgui: Platform Binding for GLFW
+// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
+// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
+// (Requires: GLFW 3.1+)
+
+// Implemented features:
+// [X] Platform: Clipboard support.
+// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW.
+// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
+
+// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
+// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
+// https://github.com/ocornut/imgui
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
+// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
+// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
+// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
+// 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.
+// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
+// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
+// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
+// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
+// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
+// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
+// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
+
+#include "imgui/imgui.h"
+#include "imgui_impl_glfw.h"
+
+// GLFW
+#define GLFW_INCLUDE_NONE
+#include "glad/gl.h"
+#include "GLFW/glfw3.h"
+#ifdef _WIN32
+#undef APIENTRY
+#define GLFW_EXPOSE_NATIVE_WIN32
+#include "GLFW/glfw3native.h" // for glfwGetWin32Window
+#endif
+#define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING
+#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED
+#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity
+#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale
+#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface
+
+// Data
+enum GlfwClientApi
+{
+ GlfwClientApi_Unknown,
+ GlfwClientApi_OpenGL,
+ GlfwClientApi_Vulkan
+};
+static GLFWwindow* g_Window = NULL;
+static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
+static double g_Time = 0.0;
+static bool g_MouseJustPressed[5] = { false, false, false, false, false };
+static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 };
+
+// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
+static GLFWmousebuttonfun g_PrevUserCallbackMousebutton = NULL;
+static GLFWscrollfun g_PrevUserCallbackScroll = NULL;
+static GLFWkeyfun g_PrevUserCallbackKey = NULL;
+static GLFWcharfun g_PrevUserCallbackChar = NULL;
+
+static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
+{
+ return glfwGetClipboardString((GLFWwindow*)user_data);
+}
+
+static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
+{
+ glfwSetClipboardString((GLFWwindow*)user_data, text);
+}
+
+void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
+{
+ if (g_PrevUserCallbackMousebutton != NULL)
+ g_PrevUserCallbackMousebutton(window, button, action, mods);
+
+ if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(g_MouseJustPressed))
+ g_MouseJustPressed[button] = true;
+}
+
+void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
+{
+ if (g_PrevUserCallbackScroll != NULL)
+ g_PrevUserCallbackScroll(window, xoffset, yoffset);
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseWheelH += (float)xoffset;
+ io.MouseWheel += (float)yoffset;
+}
+
+void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+ if (g_PrevUserCallbackKey != NULL)
+ g_PrevUserCallbackKey(window, key, scancode, action, mods);
+
+ ImGuiIO& io = ImGui::GetIO();
+ if (action == GLFW_PRESS)
+ io.KeysDown[key] = true;
+ if (action == GLFW_RELEASE)
+ io.KeysDown[key] = false;
+
+ // Modifiers are not reliable across systems
+ io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
+ io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
+ io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
+ io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
+}
+
+void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
+{
+ if (g_PrevUserCallbackChar != NULL)
+ g_PrevUserCallbackChar(window, c);
+
+ ImGuiIO& io = ImGui::GetIO();
+ if (c > 0 && c < 0x10000)
+ io.AddInputCharacter((unsigned short)c);
+}
+
+static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
+{
+ g_Window = window;
+ g_Time = 0.0;
+
+ // Setup back-end capabilities flags
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+ io.BackendPlatformName = "imgui_impl_glfw";
+
+ // Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
+ io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
+ io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
+ io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
+ io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
+ io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
+ io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
+ io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
+ io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
+ io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
+ io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
+ io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
+ io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
+ io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
+ io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
+ io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
+
+ io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
+ io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
+ io.ClipboardUserData = g_Window;
+#if defined(_WIN32)
+ io.ImeWindowHandle = (void*)glfwGetWin32Window(g_Window);
+#endif
+
+ g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+ g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
+ g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
+ g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
+ g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
+ g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
+ g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); // FIXME: GLFW doesn't have this.
+ g_MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
+
+ // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
+ g_PrevUserCallbackMousebutton = NULL;
+ g_PrevUserCallbackScroll = NULL;
+ g_PrevUserCallbackKey = NULL;
+ g_PrevUserCallbackChar = NULL;
+ if (install_callbacks)
+ {
+ g_PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
+ g_PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
+ g_PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
+ g_PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
+ }
+
+ g_ClientApi = client_api;
+ return true;
+}
+
+bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks)
+{
+ return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL);
+}
+
+bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks)
+{
+ return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan);
+}
+
+void ImGui_ImplGlfw_Shutdown()
+{
+ for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
+ {
+ glfwDestroyCursor(g_MouseCursors[cursor_n]);
+ g_MouseCursors[cursor_n] = NULL;
+ }
+ g_ClientApi = GlfwClientApi_Unknown;
+}
+
+static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
+{
+ // Update buttons
+ ImGuiIO& io = ImGui::GetIO();
+ for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
+ {
+ // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
+ io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0;
+ g_MouseJustPressed[i] = false;
+ }
+
+ // Update mouse position
+ const ImVec2 mouse_pos_backup = io.MousePos;
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+#ifdef __EMSCRIPTEN__
+ const bool focused = true; // Emscripten
+#else
+ const bool focused = glfwGetWindowAttrib(g_Window, GLFW_FOCUSED) != 0;
+#endif
+ if (focused)
+ {
+ if (io.WantSetMousePos)
+ {
+ glfwSetCursorPos(g_Window, (double)mouse_pos_backup.x, (double)mouse_pos_backup.y);
+ }
+ else
+ {
+ double mouse_x, mouse_y;
+ glfwGetCursorPos(g_Window, &mouse_x, &mouse_y);
+ io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
+ }
+ }
+}
+
+static void ImGui_ImplGlfw_UpdateMouseCursor()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(g_Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
+ return;
+
+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
+ if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
+ {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+ }
+ else
+ {
+ // Show OS mouse cursor
+ // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
+ glfwSetCursor(g_Window, g_MouseCursors[imgui_cursor] ? g_MouseCursors[imgui_cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]);
+ glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ }
+}
+
+void ImGui_ImplGlfw_NewFrame()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.Fonts->IsBuilt() && "Font atlas not built! It is generally built by the renderer back-end. Missing call to renderer _NewFrame() function? e.g. ImGui_ImplOpenGL3_NewFrame().");
+
+ // Setup display size (every frame to accommodate for window resizing)
+ int w, h;
+ int display_w, display_h;
+ glfwGetWindowSize(g_Window, &w, &h);
+ glfwGetFramebufferSize(g_Window, &display_w, &display_h);
+ io.DisplaySize = ImVec2((float)w, (float)h);
+ io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
+
+ // Setup time step
+ double current_time = glfwGetTime();
+ io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f);
+ g_Time = current_time;
+
+ ImGui_ImplGlfw_UpdateMousePosAndButtons();
+ ImGui_ImplGlfw_UpdateMouseCursor();
+
+ // Gamepad navigation mapping [BETA]
+ memset(io.NavInputs, 0, sizeof(io.NavInputs));
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)
+ {
+ // Update gamepad inputs
+ #define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
+ #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
+ int axes_count = 0, buttons_count = 0;
+ const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);
+ const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);
+ MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A
+ MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B
+ MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X
+ MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y
+ MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left
+ MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right
+ MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up
+ MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down
+ MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB
+ MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB
+ MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f);
+ MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f);
+ MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f);
+ MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f);
+ #undef MAP_BUTTON
+ #undef MAP_ANALOG
+ if (axes_count > 0 && buttons_count > 0)
+ io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
+ else
+ io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
+ }
+}
diff --git a/Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.h b/Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.h
new file mode 100644
index 0000000..ccbe840
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/imgui_impl_glfw.h
@@ -0,0 +1,33 @@
+// dear imgui: Platform Binding for GLFW
+// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan..)
+// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
+
+// Implemented features:
+// [X] Platform: Clipboard support.
+// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW.
+// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
+
+// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
+// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
+// https://github.com/ocornut/imgui
+
+// About GLSL version:
+// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
+// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure!
+
+#pragma once
+
+struct GLFWwindow;
+
+IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
+IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
+IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
+
+// InitXXX function with 'install_callbacks=true': install GLFW callbacks. They will call user's previously installed callbacks, if any.
+// InitXXX function with 'install_callbacks=false': do not install GLFW callbacks. You will need to call them yourself from your own GLFW callbacks.
+IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
+IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
+IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
+IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
diff --git a/Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.cpp b/Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.cpp
new file mode 100644
index 0000000..6e49ad4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.cpp
@@ -0,0 +1,556 @@
+// dear imgui: Renderer for OpenGL3 / OpenGL ES2 / OpenGL ES3 (modern OpenGL with shaders / programmatic pipeline)
+// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
+// (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
+
+// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
+// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
+// https://github.com/ocornut/imgui
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT).
+// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
+// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
+// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
+// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.
+// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
+// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
+// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
+// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".
+// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
+// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
+// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
+// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
+// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
+// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
+
+//----------------------------------------
+// OpenGL GLSL GLSL
+// version version string
+//----------------------------------------
+// 2.0 110 "#version 110"
+// 2.1 120
+// 3.0 130
+// 3.1 140
+// 3.2 150 "#version 150"
+// 3.3 330
+// 4.0 400
+// 4.1 410 "#version 410 core"
+// 4.2 420
+// 4.3 430
+// ES 2.0 100 "#version 100"
+// ES 3.0 300 "#version 300 es"
+//----------------------------------------
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+// MOD_ERIN
+#include "imgui/imgui.h"
+#include "imgui_impl_opengl3.h"
+#include <stdio.h>
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+#if defined(__APPLE__)
+#include "TargetConditionals.h"
+#endif
+
+// iOS, Android and Emscripten can use GL ES 3
+// Call ImGui_ImplOpenGL3_Init() with "#version 300 es"
+#if (defined(__APPLE__) && TARGET_OS_IOS) || (defined(__ANDROID__)) || (defined(__EMSCRIPTEN__))
+#define USE_GL_ES3
+#endif
+
+#ifdef USE_GL_ES3
+// OpenGL ES 3
+#include <GLES3/gl3.h> // Use GL ES 3
+#else
+// Regular OpenGL
+// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually.
+// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad.
+// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
+#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
+#include <GL/gl3w.h>
+#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
+#include <GL/glew.h>
+#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
+// MOD_ERIN
+#include "glad/gl.h"
+#else
+#include IMGUI_IMPL_OPENGL_LOADER_CUSTOM
+#endif
+#endif
+
+// OpenGL Data
+static char g_GlslVersionString[32] = "";
+static GLuint g_FontTexture = 0;
+static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
+static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
+static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
+static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
+
+// Functions
+bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendRendererName = "imgui_impl_opengl3";
+
+ // Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
+#ifdef USE_GL_ES3
+ if (glsl_version == NULL)
+ glsl_version = "#version 300 es";
+#else
+ if (glsl_version == NULL)
+ glsl_version = "#version 130";
+#endif
+ IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString));
+ strcpy(g_GlslVersionString, glsl_version);
+ strcat(g_GlslVersionString, "\n");
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_Shutdown()
+{
+ ImGui_ImplOpenGL3_DestroyDeviceObjects();
+}
+
+void ImGui_ImplOpenGL3_NewFrame()
+{
+ if (!g_FontTexture)
+ ImGui_ImplOpenGL3_CreateDeviceObjects();
+}
+
+// OpenGL3 Render function.
+// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
+// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
+void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ ImGuiIO& io = ImGui::GetIO();
+ int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);
+ int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);
+ if (fb_width <= 0 || fb_height <= 0)
+ return;
+ draw_data->ScaleClipRects(io.DisplayFramebufferScale);
+
+ // Backup GL state
+ GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
+ glActiveTexture(GL_TEXTURE0);
+ GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
+ GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+#ifdef GL_SAMPLER_BINDING
+ GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);
+#endif
+ GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
+ GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
+#ifdef GL_POLYGON_MODE
+ GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
+#endif
+ GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
+ GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
+ GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
+ GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
+ GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
+ GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
+ GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
+ GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
+ GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
+ GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
+ GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+ bool clip_origin_lower_left = true;
+#ifdef GL_CLIP_ORIGIN
+ GLenum last_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
+ if (last_clip_origin == GL_UPPER_LEFT)
+ clip_origin_lower_left = false;
+#endif
+
+ // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
+ glEnable(GL_BLEND);
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_SCISSOR_TEST);
+#ifdef GL_POLYGON_MODE
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+#endif
+
+ // Setup viewport, orthographic projection matrix
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
+ glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ const float ortho_projection[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, -1.0f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
+ };
+ glUseProgram(g_ShaderHandle);
+ glUniform1i(g_AttribLocationTex, 0);
+ glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
+#ifdef GL_SAMPLER_BINDING
+ glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
+#endif
+ // Recreate the VAO every time
+ // (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)
+ GLuint vao_handle = 0;
+ glGenVertexArrays(1, &vao_handle);
+ glBindVertexArray(vao_handle);
+ glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
+ glEnableVertexAttribArray(g_AttribLocationPosition);
+ glEnableVertexAttribArray(g_AttribLocationUV);
+ glEnableVertexAttribArray(g_AttribLocationColor);
+ glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
+ glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
+ glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
+
+ // Draw
+ ImVec2 pos = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawIdx* idx_buffer_offset = 0;
+
+ glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);
+ glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ // User callback (registered via ImDrawList::AddCallback)
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
+ if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
+ {
+ // Apply scissor/clipping rectangle
+ if (clip_origin_lower_left)
+ glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
+ else
+ glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT)
+
+ // Bind texture, Draw
+ glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
+ glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
+ }
+ }
+ idx_buffer_offset += pcmd->ElemCount;
+ }
+ }
+ glDeleteVertexArrays(1, &vao_handle);
+
+ // Restore modified GL state
+ glUseProgram(last_program);
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+#ifdef GL_SAMPLER_BINDING
+ glBindSampler(0, last_sampler);
+#endif
+ glActiveTexture(last_active_texture);
+ glBindVertexArray(last_vertex_array);
+ glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
+ glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
+ glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
+ if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
+ if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
+ if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
+ if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
+#ifdef GL_POLYGON_MODE
+ glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
+#endif
+ glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
+ glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
+}
+
+bool ImGui_ImplOpenGL3_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
+
+ // Upload texture to graphics system
+ GLint last_texture;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+ glGenTextures(1, &g_FontTexture);
+ glBindTexture(GL_TEXTURE_2D, g_FontTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ // Store our identifier
+ io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture;
+
+ // Restore state
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_DestroyFontsTexture()
+{
+ if (g_FontTexture)
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ glDeleteTextures(1, &g_FontTexture);
+ io.Fonts->TexID = 0;
+ g_FontTexture = 0;
+ }
+}
+
+// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
+static bool CheckShader(GLuint handle, const char* desc)
+{
+ GLint status = 0, log_length = 0;
+ glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
+ glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
+ if ((GLboolean)status == GL_FALSE)
+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);
+ if (log_length > 0)
+ {
+ ImVector<char> buf;
+ buf.resize((int)(log_length + 1));
+ glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
+ fprintf(stderr, "%s\n", buf.begin());
+ }
+ return (GLboolean)status == GL_TRUE;
+}
+
+// If you get an error please report on GitHub. You may try different GL context version or GLSL version.
+static bool CheckProgram(GLuint handle, const char* desc)
+{
+ GLint status = 0, log_length = 0;
+ glGetProgramiv(handle, GL_LINK_STATUS, &status);
+ glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
+ if ((GLboolean)status == GL_FALSE)
+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! (with GLSL '%s')\n", desc, g_GlslVersionString);
+ if (log_length > 0)
+ {
+ ImVector<char> buf;
+ buf.resize((int)(log_length + 1));
+ glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
+ fprintf(stderr, "%s\n", buf.begin());
+ }
+ return (GLboolean)status == GL_TRUE;
+}
+
+bool ImGui_ImplOpenGL3_CreateDeviceObjects()
+{
+ // Backup GL state
+ GLint last_texture, last_array_buffer, last_vertex_array;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
+
+ // Parse GLSL version string
+ int glsl_version = 130;
+ sscanf(g_GlslVersionString, "#version %d", &glsl_version);
+
+ const GLchar* vertex_shader_glsl_120 =
+ "uniform mat4 ProjMtx;\n"
+ "attribute vec2 Position;\n"
+ "attribute vec2 UV;\n"
+ "attribute vec4 Color;\n"
+ "varying vec2 Frag_UV;\n"
+ "varying vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_130 =
+ "uniform mat4 ProjMtx;\n"
+ "in vec2 Position;\n"
+ "in vec2 UV;\n"
+ "in vec4 Color;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_300_es =
+ "precision mediump float;\n"
+ "layout (location = 0) in vec2 Position;\n"
+ "layout (location = 1) in vec2 UV;\n"
+ "layout (location = 2) in vec4 Color;\n"
+ "uniform mat4 ProjMtx;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_410_core =
+ "layout (location = 0) in vec2 Position;\n"
+ "layout (location = 1) in vec2 UV;\n"
+ "layout (location = 2) in vec4 Color;\n"
+ "uniform mat4 ProjMtx;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_120 =
+ "#ifdef GL_ES\n"
+ " precision mediump float;\n"
+ "#endif\n"
+ "uniform sampler2D Texture;\n"
+ "varying vec2 Frag_UV;\n"
+ "varying vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_130 =
+ "uniform sampler2D Texture;\n"
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_300_es =
+ "precision mediump float;\n"
+ "uniform sampler2D Texture;\n"
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "layout (location = 0) out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_410_core =
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "uniform sampler2D Texture;\n"
+ "layout (location = 0) out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ // Select shaders matching our GLSL versions
+ const GLchar* vertex_shader = NULL;
+ const GLchar* fragment_shader = NULL;
+ if (glsl_version < 130)
+ {
+ vertex_shader = vertex_shader_glsl_120;
+ fragment_shader = fragment_shader_glsl_120;
+ }
+ else if (glsl_version >= 410)
+ {
+ vertex_shader = vertex_shader_glsl_410_core;
+ fragment_shader = fragment_shader_glsl_410_core;
+ }
+ else if (glsl_version == 300)
+ {
+ vertex_shader = vertex_shader_glsl_300_es;
+ fragment_shader = fragment_shader_glsl_300_es;
+ }
+ else
+ {
+ vertex_shader = vertex_shader_glsl_130;
+ fragment_shader = fragment_shader_glsl_130;
+ }
+
+ // Create shaders
+ const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader };
+ g_VertHandle = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);
+ glCompileShader(g_VertHandle);
+ CheckShader(g_VertHandle, "vertex shader");
+
+ const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader };
+ g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);
+ glCompileShader(g_FragHandle);
+ CheckShader(g_FragHandle, "fragment shader");
+
+ g_ShaderHandle = glCreateProgram();
+ glAttachShader(g_ShaderHandle, g_VertHandle);
+ glAttachShader(g_ShaderHandle, g_FragHandle);
+ glLinkProgram(g_ShaderHandle);
+ CheckProgram(g_ShaderHandle, "shader program");
+
+ g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");
+ g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");
+ g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");
+ g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");
+ g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");
+
+ // Create buffers
+ glGenBuffers(1, &g_VboHandle);
+ glGenBuffers(1, &g_ElementsHandle);
+
+ ImGui_ImplOpenGL3_CreateFontsTexture();
+
+ // Restore modified GL state
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+ glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
+ glBindVertexArray(last_vertex_array);
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_DestroyDeviceObjects()
+{
+ if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);
+ if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);
+ g_VboHandle = g_ElementsHandle = 0;
+
+ if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);
+ if (g_VertHandle) glDeleteShader(g_VertHandle);
+ g_VertHandle = 0;
+
+ if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);
+ if (g_FragHandle) glDeleteShader(g_FragHandle);
+ g_FragHandle = 0;
+
+ if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);
+ g_ShaderHandle = 0;
+
+ ImGui_ImplOpenGL3_DestroyFontsTexture();
+}
diff --git a/Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.h b/Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.h
new file mode 100644
index 0000000..1683b6e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/imgui_impl_opengl3.h
@@ -0,0 +1,44 @@
+// dear imgui: Renderer for OpenGL3 / OpenGL ES2 / OpenGL ES3 (modern OpenGL with shaders / programmatic pipeline)
+// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)
+// (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.
+
+// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.
+// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.
+// https://github.com/ocornut/imgui
+
+// About OpenGL function loaders:
+// About OpenGL function loaders: modern OpenGL doesn't have a standard header file and requires individual function pointers to be loaded manually.
+// Helper libraries are often used for this purpose! Here we are supporting a few common ones: gl3w, glew, glad.
+// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
+
+// About GLSL version:
+// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string.
+// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
+// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
+
+#pragma once
+
+// MOD_ERIN
+#define IMGUI_IMPL_OPENGL_LOADER_GLAD
+
+// Set default OpenGL loader to be gl3w
+#if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W) \
+ && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW) \
+ && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD) \
+ && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
+#define IMGUI_IMPL_OPENGL_LOADER_GL3W
+#endif
+
+IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
+
+// Called by Init/NewFrame/Shutdown
+IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
+IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
diff --git a/Client/ThirdParty/Box2D/testbed/main.cpp b/Client/ThirdParty/Box2D/testbed/main.cpp
new file mode 100644
index 0000000..c5969e3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/main.cpp
@@ -0,0 +1,651 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#define _CRT_SECURE_NO_WARNINGS
+#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 1
+
+#include "imgui/imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_opengl3.h"
+#include "draw.h"
+#include "settings.h"
+#include "test.h"
+
+#include <algorithm>
+#include <stdio.h>
+#include <thread>
+#include <chrono>
+
+#if defined(_WIN32)
+#include <crtdbg.h>
+#endif
+
+GLFWwindow* g_mainWindow = nullptr;
+static int32 s_testSelection = 0;
+static Test* s_test = nullptr;
+static Settings s_settings;
+static bool s_rightMouseDown = false;
+static b2Vec2 s_clickPointWS = b2Vec2_zero;
+
+void glfwErrorCallback(int error, const char* description)
+{
+ fprintf(stderr, "GLFW error occured. Code: %d. Description: %s\n", error, description);
+}
+
+static inline bool CompareTests(const TestEntry& a, const TestEntry& b)
+{
+ int result = strcmp(a.category, b.category);
+ if (result == 0)
+ {
+ result = strcmp(a.name, b.name);
+ }
+
+ return result < 0;
+}
+
+static void SortTests()
+{
+ std::sort(g_testEntries, g_testEntries + g_testCount, CompareTests);
+}
+
+static void CreateUI(GLFWwindow* window, const char* glslVersion = NULL)
+{
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+
+ bool success;
+ success = ImGui_ImplGlfw_InitForOpenGL(window, false);
+ if (success == false)
+ {
+ printf("ImGui_ImplGlfw_InitForOpenGL failed\n");
+ assert(false);
+ }
+
+ success = ImGui_ImplOpenGL3_Init(glslVersion);
+ if (success == false)
+ {
+ printf("ImGui_ImplOpenGL3_Init failed\n");
+ assert(false);
+ }
+
+ // Search for font file
+ const char* fontPath1 = "data/droid_sans.ttf";
+ const char* fontPath2 = "../data/droid_sans.ttf";
+ const char* fontPath = nullptr;
+ FILE* file1 = fopen(fontPath1, "rb");
+ FILE* file2 = fopen(fontPath2, "rb");
+ if (file1)
+ {
+ fontPath = fontPath1;
+ fclose(file1);
+ }
+
+ if (file2)
+ {
+ fontPath = fontPath2;
+ fclose(file2);
+ }
+
+ if (fontPath)
+ {
+ ImGui::GetIO().Fonts->AddFontFromFileTTF(fontPath, 13.0f);
+ }
+}
+
+static void ResizeWindowCallback(GLFWwindow*, int width, int height)
+{
+ g_camera.m_width = width;
+ g_camera.m_height = height;
+ s_settings.m_windowWidth = width;
+ s_settings.m_windowHeight = height;
+}
+
+static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+ ImGui_ImplGlfw_KeyCallback(window, key, scancode, action, mods);
+ if (ImGui::GetIO().WantCaptureKeyboard)
+ {
+ return;
+ }
+
+ if (action == GLFW_PRESS)
+ {
+ switch (key)
+ {
+ case GLFW_KEY_ESCAPE:
+ // Quit
+ glfwSetWindowShouldClose(g_mainWindow, GL_TRUE);
+ break;
+
+ case GLFW_KEY_LEFT:
+ // Pan left
+ if (mods == GLFW_MOD_CONTROL)
+ {
+ b2Vec2 newOrigin(2.0f, 0.0f);
+ s_test->ShiftOrigin(newOrigin);
+ }
+ else
+ {
+ g_camera.m_center.x -= 0.5f;
+ }
+ break;
+
+ case GLFW_KEY_RIGHT:
+ // Pan right
+ if (mods == GLFW_MOD_CONTROL)
+ {
+ b2Vec2 newOrigin(-2.0f, 0.0f);
+ s_test->ShiftOrigin(newOrigin);
+ }
+ else
+ {
+ g_camera.m_center.x += 0.5f;
+ }
+ break;
+
+ case GLFW_KEY_DOWN:
+ // Pan down
+ if (mods == GLFW_MOD_CONTROL)
+ {
+ b2Vec2 newOrigin(0.0f, 2.0f);
+ s_test->ShiftOrigin(newOrigin);
+ }
+ else
+ {
+ g_camera.m_center.y -= 0.5f;
+ }
+ break;
+
+ case GLFW_KEY_UP:
+ // Pan up
+ if (mods == GLFW_MOD_CONTROL)
+ {
+ b2Vec2 newOrigin(0.0f, -2.0f);
+ s_test->ShiftOrigin(newOrigin);
+ }
+ else
+ {
+ g_camera.m_center.y += 0.5f;
+ }
+ break;
+
+ case GLFW_KEY_HOME:
+ // Reset view
+ g_camera.m_zoom = 1.0f;
+ g_camera.m_center.Set(0.0f, 20.0f);
+ break;
+
+ case GLFW_KEY_Z:
+ // Zoom out
+ g_camera.m_zoom = b2Min(1.1f * g_camera.m_zoom, 20.0f);
+ break;
+
+ case GLFW_KEY_X:
+ // Zoom in
+ g_camera.m_zoom = b2Max(0.9f * g_camera.m_zoom, 0.02f);
+ break;
+
+ case GLFW_KEY_R:
+ // Reset test
+ delete s_test;
+ s_test = g_testEntries[s_settings.m_testIndex].createFcn();
+ break;
+
+ case GLFW_KEY_SPACE:
+ // Launch a bomb.
+ if (s_test)
+ {
+ s_test->LaunchBomb();
+ }
+ break;
+
+ case GLFW_KEY_O:
+ s_settings.m_singleStep = true;
+ break;
+
+ case GLFW_KEY_P:
+ s_settings.m_pause = !s_settings.m_pause;
+ break;
+
+ case GLFW_KEY_LEFT_BRACKET:
+ // Switch to previous test
+ --s_testSelection;
+ if (s_testSelection < 0)
+ {
+ s_testSelection = g_testCount - 1;
+ }
+ break;
+
+ case GLFW_KEY_RIGHT_BRACKET:
+ // Switch to next test
+ ++s_testSelection;
+ if (s_testSelection == g_testCount)
+ {
+ s_testSelection = 0;
+ }
+ break;
+
+ case GLFW_KEY_TAB:
+ g_debugDraw.m_showUI = !g_debugDraw.m_showUI;
+
+ default:
+ if (s_test)
+ {
+ s_test->Keyboard(key);
+ }
+ }
+ }
+ else if (action == GLFW_RELEASE)
+ {
+ s_test->KeyboardUp(key);
+ }
+ // else GLFW_REPEAT
+}
+
+static void CharCallback(GLFWwindow* window, unsigned int c)
+{
+ ImGui_ImplGlfw_CharCallback(window, c);
+}
+
+static void MouseButtonCallback(GLFWwindow* window, int32 button, int32 action, int32 mods)
+{
+ ImGui_ImplGlfw_MouseButtonCallback(window, button, action, mods);
+
+ double xd, yd;
+ glfwGetCursorPos(g_mainWindow, &xd, &yd);
+ b2Vec2 ps((float)xd, (float)yd);
+
+ // Use the mouse to move things around.
+ if (button == GLFW_MOUSE_BUTTON_1)
+ {
+ //<##>
+ //ps.Set(0, 0);
+ b2Vec2 pw = g_camera.ConvertScreenToWorld(ps);
+ if (action == GLFW_PRESS)
+ {
+ if (mods == GLFW_MOD_SHIFT)
+ {
+ s_test->ShiftMouseDown(pw);
+ }
+ else
+ {
+ s_test->MouseDown(pw);
+ }
+ }
+
+ if (action == GLFW_RELEASE)
+ {
+ s_test->MouseUp(pw);
+ }
+ }
+ else if (button == GLFW_MOUSE_BUTTON_2)
+ {
+ if (action == GLFW_PRESS)
+ {
+ s_clickPointWS = g_camera.ConvertScreenToWorld(ps);
+ s_rightMouseDown = true;
+ }
+
+ if (action == GLFW_RELEASE)
+ {
+ s_rightMouseDown = false;
+ }
+ }
+}
+
+static void MouseMotionCallback(GLFWwindow*, double xd, double yd)
+{
+ b2Vec2 ps((float)xd, (float)yd);
+
+ b2Vec2 pw = g_camera.ConvertScreenToWorld(ps);
+ s_test->MouseMove(pw);
+
+ if (s_rightMouseDown)
+ {
+ b2Vec2 diff = pw - s_clickPointWS;
+ g_camera.m_center.x -= diff.x;
+ g_camera.m_center.y -= diff.y;
+ s_clickPointWS = g_camera.ConvertScreenToWorld(ps);
+ }
+}
+
+static void ScrollCallback(GLFWwindow* window, double dx, double dy)
+{
+ ImGui_ImplGlfw_ScrollCallback(window, dx, dy);
+ if (ImGui::GetIO().WantCaptureMouse)
+ {
+ return;
+ }
+
+ if (dy > 0)
+ {
+ g_camera.m_zoom /= 1.1f;
+ }
+ else
+ {
+ g_camera.m_zoom *= 1.1f;
+ }
+}
+
+static void RestartTest()
+{
+ delete s_test;
+ s_test = g_testEntries[s_settings.m_testIndex].createFcn();
+}
+
+static void UpdateUI()
+{
+ int menuWidth = 180;
+ if (g_debugDraw.m_showUI)
+ {
+ ImGui::SetNextWindowPos(ImVec2((float)g_camera.m_width - menuWidth - 10, 10));
+ ImGui::SetNextWindowSize(ImVec2((float)menuWidth, (float)g_camera.m_height - 20));
+
+ ImGui::Begin("Tools", &g_debugDraw.m_showUI, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
+
+ if (ImGui::BeginTabBar("ControlTabs", ImGuiTabBarFlags_None))
+ {
+ if (ImGui::BeginTabItem("Controls"))
+ {
+ ImGui::SliderInt("Vel Iters", &s_settings.m_velocityIterations, 0, 50);
+ ImGui::SliderInt("Pos Iters", &s_settings.m_positionIterations, 0, 50);
+ ImGui::SliderFloat("Hertz", &s_settings.m_hertz, 5.0f, 120.0f, "%.0f hz");
+
+ ImGui::Separator();
+
+ ImGui::Checkbox("Sleep", &s_settings.m_enableSleep);
+ ImGui::Checkbox("Warm Starting", &s_settings.m_enableWarmStarting);
+ ImGui::Checkbox("Time of Impact", &s_settings.m_enableContinuous);
+ ImGui::Checkbox("Sub-Stepping", &s_settings.m_enableSubStepping);
+
+ ImGui::Separator();
+
+ ImGui::Checkbox("Shapes", &s_settings.m_drawShapes);
+ ImGui::Checkbox("Joints", &s_settings.m_drawJoints);
+ ImGui::Checkbox("AABBs", &s_settings.m_drawAABBs);
+ ImGui::Checkbox("Contact Points", &s_settings.m_drawContactPoints);
+ ImGui::Checkbox("Contact Normals", &s_settings.m_drawContactNormals);
+ ImGui::Checkbox("Contact Impulses", &s_settings.m_drawContactImpulse);
+ ImGui::Checkbox("Friction Impulses", &s_settings.m_drawFrictionImpulse);
+ ImGui::Checkbox("Center of Masses", &s_settings.m_drawCOMs);
+ ImGui::Checkbox("Statistics", &s_settings.m_drawStats);
+ ImGui::Checkbox("Profile", &s_settings.m_drawProfile);
+
+ ImVec2 button_sz = ImVec2(-1, 0);
+ if (ImGui::Button("Pause (P)", button_sz))
+ {
+ s_settings.m_pause = !s_settings.m_pause;
+ }
+
+ if (ImGui::Button("Single Step (O)", button_sz))
+ {
+ s_settings.m_singleStep = !s_settings.m_singleStep;
+ }
+
+ if (ImGui::Button("Restart (R)", button_sz))
+ {
+ RestartTest();
+ }
+
+ if (ImGui::Button("Quit", button_sz))
+ {
+ glfwSetWindowShouldClose(g_mainWindow, GL_TRUE);
+ }
+
+ ImGui::EndTabItem();
+ }
+
+ ImGuiTreeNodeFlags leafNodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
+ leafNodeFlags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;
+
+ ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
+
+ if (ImGui::BeginTabItem("Tests"))
+ {
+ int categoryIndex = 0;
+ const char* category = g_testEntries[categoryIndex].category;
+ int i = 0;
+ while (i < g_testCount)
+ {
+ bool categorySelected = strcmp(category, g_testEntries[s_settings.m_testIndex].category) == 0;
+ ImGuiTreeNodeFlags nodeSelectionFlags = categorySelected ? ImGuiTreeNodeFlags_Selected : 0;
+ bool nodeOpen = ImGui::TreeNodeEx(category, nodeFlags | nodeSelectionFlags);
+
+ if (nodeOpen)
+ {
+ while (i < g_testCount && strcmp(category, g_testEntries[i].category) == 0)
+ {
+ ImGuiTreeNodeFlags selectionFlags = 0;
+ if (s_settings.m_testIndex == i)
+ {
+ selectionFlags = ImGuiTreeNodeFlags_Selected;
+ }
+ ImGui::TreeNodeEx((void*)(intptr_t)i, leafNodeFlags | selectionFlags, "%s", g_testEntries[i].name);
+ if (ImGui::IsItemClicked())
+ {
+ delete s_test;
+ s_settings.m_testIndex = i;
+ s_test = g_testEntries[i].createFcn();
+ s_testSelection = i;
+ }
+ ++i;
+ }
+ ImGui::TreePop();
+ }
+ else
+ {
+ while (i < g_testCount && strcmp(category, g_testEntries[i].category) == 0)
+ {
+ ++i;
+ }
+ }
+
+ if (i < g_testCount)
+ {
+ category = g_testEntries[i].category;
+ categoryIndex = i;
+ }
+ }
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+
+ ImGui::End();
+
+ s_test->UpdateUI();
+ }
+}
+
+//
+int main(int, char**)
+{
+#if defined(_WIN32)
+ // Enable memory-leak reports
+ _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
+#endif
+
+ char buffer[128];
+
+ s_settings.Load();
+ SortTests();
+
+ glfwSetErrorCallback(glfwErrorCallback);
+
+ g_camera.m_width = s_settings.m_windowWidth;
+ g_camera.m_height = s_settings.m_windowHeight;
+
+ if (glfwInit() == 0)
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ return -1;
+ }
+
+#if __APPLE__
+ const char* glslVersion = "#version 150";
+#else
+ const char* glslVersion = NULL;
+#endif
+
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+
+ sprintf(buffer, "Box2D Testbed Version %d.%d.%d", b2_version.major, b2_version.minor, b2_version.revision);
+
+ bool fullscreen = false;
+ if (fullscreen)
+ {
+ g_mainWindow = glfwCreateWindow(1920, 1080, buffer, glfwGetPrimaryMonitor(), NULL);
+ }
+ else
+ {
+ g_mainWindow = glfwCreateWindow(g_camera.m_width, g_camera.m_height, buffer, NULL, NULL);
+ }
+
+ if (g_mainWindow == NULL)
+ {
+ fprintf(stderr, "Failed to open GLFW g_mainWindow.\n");
+ glfwTerminate();
+ return -1;
+ }
+
+ glfwMakeContextCurrent(g_mainWindow);
+
+ // Load OpenGL functions using glad
+ int version = gladLoadGL(glfwGetProcAddress);
+ printf("GL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
+ printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));
+
+ glfwSetScrollCallback(g_mainWindow, ScrollCallback);
+ glfwSetWindowSizeCallback(g_mainWindow, ResizeWindowCallback);
+ glfwSetKeyCallback(g_mainWindow, KeyCallback);
+ glfwSetCharCallback(g_mainWindow, CharCallback);
+ glfwSetMouseButtonCallback(g_mainWindow, MouseButtonCallback);
+ glfwSetCursorPosCallback(g_mainWindow, MouseMotionCallback);
+ glfwSetScrollCallback(g_mainWindow, ScrollCallback);
+
+ g_debugDraw.Create();
+
+ CreateUI(g_mainWindow, glslVersion);
+
+ s_settings.m_testIndex = b2Clamp(s_settings.m_testIndex, 0, g_testCount - 1);
+ s_testSelection = s_settings.m_testIndex;
+ s_test = g_testEntries[s_settings.m_testIndex].createFcn();
+
+ // Control the frame rate. One draw per monitor refresh.
+ //glfwSwapInterval(1);
+
+ glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
+
+ std::chrono::duration<double> frameTime(0.0);
+ std::chrono::duration<double> sleepAdjust(0.0);
+
+ while (!glfwWindowShouldClose(g_mainWindow))
+ {
+ std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
+
+ glfwGetWindowSize(g_mainWindow, &g_camera.m_width, &g_camera.m_height);
+
+ int bufferWidth, bufferHeight;
+ glfwGetFramebufferSize(g_mainWindow, &bufferWidth, &bufferHeight);
+ glViewport(0, 0, bufferWidth, bufferHeight);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+
+ ImGui::NewFrame();
+
+ if (g_debugDraw.m_showUI)
+ {
+ ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
+ ImGui::SetNextWindowSize(ImVec2(float(g_camera.m_width), float(g_camera.m_height)));
+ ImGui::SetNextWindowBgAlpha(0.0f);
+ ImGui::Begin("Overlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar);
+ ImGui::End();
+
+ const TestEntry& entry = g_testEntries[s_settings.m_testIndex];
+ sprintf(buffer, "%s : %s", entry.category, entry.name);
+ s_test->DrawTitle(buffer);
+ }
+
+ s_test->Step(s_settings);
+
+ UpdateUI();
+
+ // ImGui::ShowDemoWindow();
+
+ if (g_debugDraw.m_showUI)
+ {
+ sprintf(buffer, "%.1f ms", 1000.0 * frameTime.count());
+ g_debugDraw.DrawString(5, g_camera.m_height - 20, buffer);
+ }
+
+ ImGui::Render();
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+ glfwSwapBuffers(g_mainWindow);
+
+ if (s_testSelection != s_settings.m_testIndex)
+ {
+ s_settings.m_testIndex = s_testSelection;
+ delete s_test;
+ s_test = g_testEntries[s_settings.m_testIndex].createFcn();
+ g_camera.m_zoom = 1.0f;
+ g_camera.m_center.Set(0.0f, 20.0f);
+ }
+
+ glfwPollEvents();
+
+ // Throttle to cap at 60Hz. This adaptive using a sleep adjustment. This could be improved by
+ // using mm_pause or equivalent for the last millisecond.
+ std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
+ std::chrono::duration<double> target(1.0 / 60.0);
+ std::chrono::duration<double> timeUsed = t2 - t1;
+ std::chrono::duration<double> sleepTime = target - timeUsed + sleepAdjust;
+ if (sleepTime > std::chrono::duration<double>(0))
+ {
+ std::this_thread::sleep_for(sleepTime);
+ }
+
+ std::chrono::steady_clock::time_point t3 = std::chrono::steady_clock::now();
+ frameTime = t3 - t1;
+
+ // Compute the sleep adjustment using a low pass filter
+ sleepAdjust = 0.9 * sleepAdjust + 0.1 * (target - frameTime);
+ }
+
+ delete s_test;
+ s_test = nullptr;
+
+ g_debugDraw.Destroy();
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ glfwTerminate();
+
+ s_settings.Save();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/Box2D/testbed/settings.cpp b/Client/ThirdParty/Box2D/testbed/settings.cpp
new file mode 100644
index 0000000..fbdf9c0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/settings.cpp
@@ -0,0 +1,176 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#define _CRT_SECURE_NO_WARNINGS
+#include "settings.h"
+#include "sajson/sajson.h"
+#include <stdio.h>
+
+static const char* fileName = "settings.ini";
+
+// Load a file. You must free the character array.
+static bool sReadFile(char*& data, int& size, const char* filename)
+{
+ FILE* file = fopen(filename, "rb");
+ if (file == nullptr)
+ {
+ return false;
+ }
+
+ fseek(file, 0, SEEK_END);
+ size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ if (size == 0)
+ {
+ return false;
+ }
+
+ data = (char*)malloc(size + 1);
+ fread(data, size, 1, file);
+ fclose(file);
+ data[size] = 0;
+
+ return true;
+}
+
+void Settings::Save()
+{
+ FILE* file = fopen(fileName, "w");
+ fprintf(file, "{\n");
+ fprintf(file, " \"testIndex\": %d,\n", m_testIndex);
+ fprintf(file, " \"windowWidth\": %d,\n", m_windowWidth);
+ fprintf(file, " \"windowHeight\": %d,\n", m_windowHeight);
+ fprintf(file, " \"hertz\": %.9g,\n", m_hertz);
+ fprintf(file, " \"velocityIterations\": %d,\n", m_velocityIterations);
+ fprintf(file, " \"positionIterations\": %d,\n", m_positionIterations);
+ fprintf(file, " \"drawShapes\": %s,\n", m_drawShapes ? "true" : "false");
+ fprintf(file, " \"drawJoints\": %s,\n", m_drawJoints ? "true" : "false");
+ fprintf(file, " \"drawAABBs\": %s,\n", m_drawAABBs ? "true" : "false");
+ fprintf(file, " \"drawContactPoints\": %s,\n", m_drawContactPoints ? "true" : "false");
+ fprintf(file, " \"drawContactNormals\": %s,\n", m_drawContactNormals ? "true" : "false");
+ fprintf(file, " \"drawContactImpulse\": %s,\n", m_drawContactImpulse ? "true" : "false");
+ fprintf(file, " \"drawFrictionImpulse\": %s,\n", m_drawFrictionImpulse ? "true" : "false");
+ fprintf(file, " \"drawCOMs\": %s,\n", m_drawCOMs ? "true" : "false");
+ fprintf(file, " \"drawStats\": %s,\n", m_drawStats ? "true" : "false");
+ fprintf(file, " \"drawProfile\": %s,\n", m_drawProfile ? "true" : "false");
+ fprintf(file, " \"enableWarmStarting\": %s,\n", m_enableWarmStarting ? "true" : "false");
+ fprintf(file, " \"enableContinuous\": %s,\n", m_enableContinuous ? "true" : "false");
+ fprintf(file, " \"enableSubStepping\": %s,\n", m_enableSubStepping ? "true" : "false");
+ fprintf(file, " \"enableSleep\": %s\n", m_enableSleep ? "true" : "false");
+ fprintf(file, "}\n");
+ fclose(file);
+}
+
+void Settings::Load()
+{
+ char* data = nullptr;
+ int size = 0;
+ bool found = sReadFile(data, size, fileName);
+ if (found == false)
+ {
+ return;
+ }
+
+ const sajson::document& document = sajson::parse(sajson::dynamic_allocation(), sajson::mutable_string_view(size, data));
+ if (document.is_valid() == false)
+ {
+ return;
+ }
+
+ sajson::value root = document.get_root();
+ int fieldCount = int(root.get_length());
+ for (int i = 0; i < fieldCount; ++i)
+ {
+ sajson::string fieldName = root.get_object_key(i);
+ sajson::value fieldValue = root.get_object_value(i);
+
+ if (strncmp(fieldName.data(), "testIndex", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_INTEGER)
+ {
+ m_testIndex = fieldValue.get_integer_value();
+ }
+ continue;
+ }
+
+ if (strncmp(fieldName.data(), "windowWidth", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_INTEGER)
+ {
+ m_windowWidth = fieldValue.get_integer_value();
+ }
+ continue;
+ }
+
+ if (strncmp(fieldName.data(), "windowHeight", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_INTEGER)
+ {
+ m_windowHeight = fieldValue.get_integer_value();
+ }
+ continue;
+ }
+
+ if (strncmp(fieldName.data(), "hertz", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_DOUBLE || fieldValue.get_type() == sajson::TYPE_INTEGER)
+ {
+ m_hertz = float(fieldValue.get_number_value());
+ }
+ continue;
+ }
+
+ if (strncmp(fieldName.data(), "velocityIterations", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_INTEGER)
+ {
+ m_velocityIterations = fieldValue.get_integer_value();
+ }
+ continue;
+ }
+
+ if (strncmp(fieldName.data(), "positionIterations", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_INTEGER)
+ {
+ m_positionIterations = fieldValue.get_integer_value();
+ }
+ continue;
+ }
+
+ if (strncmp(fieldName.data(), "drawShapes", fieldName.length()) == 0)
+ {
+ if (fieldValue.get_type() == sajson::TYPE_FALSE)
+ {
+ m_drawShapes = false;
+ }
+ else if (fieldValue.get_type() == sajson::TYPE_TRUE)
+ {
+ m_drawShapes = true;
+ }
+ continue;
+ }
+ }
+
+ free(data);
+}
diff --git a/Client/ThirdParty/Box2D/testbed/settings.h b/Client/ThirdParty/Box2D/testbed/settings.h
new file mode 100644
index 0000000..dcb8426
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/settings.h
@@ -0,0 +1,83 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#pragma once
+
+struct Settings
+{
+ Settings()
+ {
+ Reset();
+ }
+
+ void Reset()
+ {
+ m_testIndex = 0;
+ m_windowWidth = 1600;
+ m_windowHeight = 900;
+ m_hertz = 60.0f;
+ m_velocityIterations = 8;
+ m_positionIterations = 3;
+ m_drawShapes = true;
+ m_drawJoints = true;
+ m_drawAABBs = false;
+ m_drawContactPoints = false;
+ m_drawContactNormals = false;
+ m_drawContactImpulse = false;
+ m_drawFrictionImpulse = false;
+ m_drawCOMs = false;
+ m_drawStats = false;
+ m_drawProfile = false;
+ m_enableWarmStarting = true;
+ m_enableContinuous = true;
+ m_enableSubStepping = false;
+ m_enableSleep = true;
+ m_pause = false;
+ m_singleStep = false;
+ }
+
+ void Save();
+ void Load();
+
+ int m_testIndex;
+ int m_windowWidth;
+ int m_windowHeight;
+ float m_hertz;
+ int m_velocityIterations;
+ int m_positionIterations;
+ bool m_drawShapes;
+ bool m_drawJoints;
+ bool m_drawAABBs;
+ bool m_drawContactPoints;
+ bool m_drawContactNormals;
+ bool m_drawContactImpulse;
+ bool m_drawFrictionImpulse;
+ bool m_drawCOMs;
+ bool m_drawStats;
+ bool m_drawProfile;
+ bool m_enableWarmStarting;
+ bool m_enableContinuous;
+ bool m_enableSubStepping;
+ bool m_enableSleep;
+ bool m_pause;
+ bool m_singleStep;
+};
diff --git a/Client/ThirdParty/Box2D/testbed/test.cpp b/Client/ThirdParty/Box2D/testbed/test.cpp
new file mode 100644
index 0000000..b871fa0
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/test.cpp
@@ -0,0 +1,469 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "settings.h"
+#include <stdio.h>
+
+void DestructionListener::SayGoodbye(b2Joint* joint)
+{
+ if (test->m_mouseJoint == joint)
+ {
+ test->m_mouseJoint = NULL;
+ }
+ else
+ {
+ test->JointDestroyed(joint);
+ }
+}
+
+Test::Test()
+{
+ b2Vec2 gravity;
+ gravity.Set(0.0f, -10.0f);
+ m_world = new b2World(gravity);
+ m_bomb = NULL;
+ m_textLine = 30;
+ m_textIncrement = 13;
+ m_mouseJoint = NULL;
+ m_pointCount = 0;
+
+ m_destructionListener.test = this;
+ m_world->SetDestructionListener(&m_destructionListener);
+ m_world->SetContactListener(this);
+ m_world->SetDebugDraw(&g_debugDraw);
+
+ m_bombSpawning = false;
+
+ m_stepCount = 0;
+
+ b2BodyDef bodyDef;
+ m_groundBody = m_world->CreateBody(&bodyDef);
+
+ memset(&m_maxProfile, 0, sizeof(b2Profile));
+ memset(&m_totalProfile, 0, sizeof(b2Profile));
+}
+
+Test::~Test()
+{
+ // By deleting the world, we delete the bomb, mouse joint, etc.
+ delete m_world;
+ m_world = NULL;
+}
+
+void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
+{
+ const b2Manifold* manifold = contact->GetManifold();
+
+ if (manifold->pointCount == 0)
+ {
+ return;
+ }
+
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+
+ b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];
+ b2GetPointStates(state1, state2, oldManifold, manifold);
+
+ b2WorldManifold worldManifold;
+ contact->GetWorldManifold(&worldManifold);
+
+ for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i)
+ {
+ ContactPoint* cp = m_points + m_pointCount;
+ cp->fixtureA = fixtureA;
+ cp->fixtureB = fixtureB;
+ cp->position = worldManifold.points[i];
+ cp->normal = worldManifold.normal;
+ cp->state = state2[i];
+ cp->normalImpulse = manifold->points[i].normalImpulse;
+ cp->tangentImpulse = manifold->points[i].tangentImpulse;
+ cp->separation = worldManifold.separations[i];
+ ++m_pointCount;
+ }
+}
+
+void Test::DrawTitle(const char *string)
+{
+ g_debugDraw.DrawString(5, 5, string);
+ m_textLine = int32(26.0f);
+}
+
+class QueryCallback : public b2QueryCallback
+{
+public:
+ QueryCallback(const b2Vec2& point)
+ {
+ m_point = point;
+ m_fixture = NULL;
+ }
+
+ bool ReportFixture(b2Fixture* fixture) override
+ {
+ b2Body* body = fixture->GetBody();
+ if (body->GetType() == b2_dynamicBody)
+ {
+ bool inside = fixture->TestPoint(m_point);
+ if (inside)
+ {
+ m_fixture = fixture;
+
+ // We are done, terminate the query.
+ return false;
+ }
+ }
+
+ // Continue the query.
+ return true;
+ }
+
+ b2Vec2 m_point;
+ b2Fixture* m_fixture;
+};
+
+void Test::MouseDown(const b2Vec2& p)
+{
+ m_mouseWorld = p;
+
+ if (m_mouseJoint != NULL)
+ {
+ return;
+ }
+
+ // Make a small box.
+ b2AABB aabb;
+ b2Vec2 d;
+ d.Set(0.001f, 0.001f);
+ aabb.lowerBound = p - d;
+ aabb.upperBound = p + d;
+
+ // Query the world for overlapping shapes.
+ QueryCallback callback(p);
+ m_world->QueryAABB(&callback, aabb);
+
+ if (callback.m_fixture)
+ {
+ float frequencyHz = 5.0f;
+ float dampingRatio = 0.7f;
+
+ b2Body* body = callback.m_fixture->GetBody();
+ b2MouseJointDef jd;
+ jd.bodyA = m_groundBody;
+ jd.bodyB = body;
+ jd.target = p;
+ jd.maxForce = 1000.0f * body->GetMass();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+
+ m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&jd);
+ body->SetAwake(true);
+ }
+}
+
+void Test::SpawnBomb(const b2Vec2& worldPt)
+{
+ m_bombSpawnPoint = worldPt;
+ m_bombSpawning = true;
+}
+
+void Test::CompleteBombSpawn(const b2Vec2& p)
+{
+ if (m_bombSpawning == false)
+ {
+ return;
+ }
+
+ const float multiplier = 30.0f;
+ b2Vec2 vel = m_bombSpawnPoint - p;
+ vel *= multiplier;
+ LaunchBomb(m_bombSpawnPoint,vel);
+ m_bombSpawning = false;
+}
+
+void Test::ShiftMouseDown(const b2Vec2& p)
+{
+ m_mouseWorld = p;
+
+ if (m_mouseJoint != NULL)
+ {
+ return;
+ }
+
+ SpawnBomb(p);
+}
+
+void Test::MouseUp(const b2Vec2& p)
+{
+ if (m_mouseJoint)
+ {
+ m_world->DestroyJoint(m_mouseJoint);
+ m_mouseJoint = NULL;
+ }
+
+ if (m_bombSpawning)
+ {
+ CompleteBombSpawn(p);
+ }
+}
+
+void Test::MouseMove(const b2Vec2& p)
+{
+ m_mouseWorld = p;
+
+ if (m_mouseJoint)
+ {
+ m_mouseJoint->SetTarget(p);
+ }
+}
+
+void Test::LaunchBomb()
+{
+ b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f);
+ b2Vec2 v = -5.0f * p;
+ LaunchBomb(p, v);
+}
+
+void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
+{
+ if (m_bomb)
+ {
+ m_world->DestroyBody(m_bomb);
+ m_bomb = NULL;
+ }
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = position;
+ bd.bullet = true;
+ m_bomb = m_world->CreateBody(&bd);
+ m_bomb->SetLinearVelocity(velocity);
+
+ b2CircleShape circle;
+ circle.m_radius = 0.3f;
+
+ b2FixtureDef fd;
+ fd.shape = &circle;
+ fd.density = 20.0f;
+ fd.restitution = 0.0f;
+
+ b2Vec2 minV = position - b2Vec2(0.3f,0.3f);
+ b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);
+
+ b2AABB aabb;
+ aabb.lowerBound = minV;
+ aabb.upperBound = maxV;
+
+ m_bomb->CreateFixture(&fd);
+}
+
+void Test::Step(Settings& settings)
+{
+ float timeStep = settings.m_hertz > 0.0f ? 1.0f / settings.m_hertz : float(0.0f);
+
+ if (settings.m_pause)
+ {
+ if (settings.m_singleStep)
+ {
+ settings.m_singleStep = 0;
+ }
+ else
+ {
+ timeStep = 0.0f;
+ }
+
+ g_debugDraw.DrawString(5, m_textLine, "****PAUSED****");
+ m_textLine += m_textIncrement;
+ }
+
+ uint32 flags = 0;
+ flags += settings.m_drawShapes * b2Draw::e_shapeBit;
+ flags += settings.m_drawJoints * b2Draw::e_jointBit;
+ flags += settings.m_drawAABBs * b2Draw::e_aabbBit;
+ flags += settings.m_drawCOMs * b2Draw::e_centerOfMassBit;
+ g_debugDraw.SetFlags(flags);
+
+ m_world->SetAllowSleeping(settings.m_enableSleep);
+ m_world->SetWarmStarting(settings.m_enableWarmStarting);
+ m_world->SetContinuousPhysics(settings.m_enableContinuous);
+ m_world->SetSubStepping(settings.m_enableSubStepping);
+
+ m_pointCount = 0;
+
+ m_world->Step(timeStep, settings.m_velocityIterations, settings.m_positionIterations);
+
+ m_world->DebugDraw();
+ g_debugDraw.Flush();
+
+ if (timeStep > 0.0f)
+ {
+ ++m_stepCount;
+ }
+
+ if (settings.m_drawStats)
+ {
+ int32 bodyCount = m_world->GetBodyCount();
+ int32 contactCount = m_world->GetContactCount();
+ int32 jointCount = m_world->GetJointCount();
+ g_debugDraw.DrawString(5, m_textLine, "bodies/contacts/joints = %d/%d/%d", bodyCount, contactCount, jointCount);
+ m_textLine += m_textIncrement;
+
+ int32 proxyCount = m_world->GetProxyCount();
+ int32 height = m_world->GetTreeHeight();
+ int32 balance = m_world->GetTreeBalance();
+ float quality = m_world->GetTreeQuality();
+ g_debugDraw.DrawString(5, m_textLine, "proxies/height/balance/quality = %d/%d/%d/%g", proxyCount, height, balance, quality);
+ m_textLine += m_textIncrement;
+ }
+
+ // Track maximum profile times
+ {
+ const b2Profile& p = m_world->GetProfile();
+ m_maxProfile.step = b2Max(m_maxProfile.step, p.step);
+ m_maxProfile.collide = b2Max(m_maxProfile.collide, p.collide);
+ m_maxProfile.solve = b2Max(m_maxProfile.solve, p.solve);
+ m_maxProfile.solveInit = b2Max(m_maxProfile.solveInit, p.solveInit);
+ m_maxProfile.solveVelocity = b2Max(m_maxProfile.solveVelocity, p.solveVelocity);
+ m_maxProfile.solvePosition = b2Max(m_maxProfile.solvePosition, p.solvePosition);
+ m_maxProfile.solveTOI = b2Max(m_maxProfile.solveTOI, p.solveTOI);
+ m_maxProfile.broadphase = b2Max(m_maxProfile.broadphase, p.broadphase);
+
+ m_totalProfile.step += p.step;
+ m_totalProfile.collide += p.collide;
+ m_totalProfile.solve += p.solve;
+ m_totalProfile.solveInit += p.solveInit;
+ m_totalProfile.solveVelocity += p.solveVelocity;
+ m_totalProfile.solvePosition += p.solvePosition;
+ m_totalProfile.solveTOI += p.solveTOI;
+ m_totalProfile.broadphase += p.broadphase;
+ }
+
+ if (settings.m_drawProfile)
+ {
+ const b2Profile& p = m_world->GetProfile();
+
+ b2Profile aveProfile;
+ memset(&aveProfile, 0, sizeof(b2Profile));
+ if (m_stepCount > 0)
+ {
+ float scale = 1.0f / m_stepCount;
+ aveProfile.step = scale * m_totalProfile.step;
+ aveProfile.collide = scale * m_totalProfile.collide;
+ aveProfile.solve = scale * m_totalProfile.solve;
+ aveProfile.solveInit = scale * m_totalProfile.solveInit;
+ aveProfile.solveVelocity = scale * m_totalProfile.solveVelocity;
+ aveProfile.solvePosition = scale * m_totalProfile.solvePosition;
+ aveProfile.solveTOI = scale * m_totalProfile.solveTOI;
+ aveProfile.broadphase = scale * m_totalProfile.broadphase;
+ }
+
+ g_debugDraw.DrawString(5, m_textLine, "step [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.step, aveProfile.step, m_maxProfile.step);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "collide [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.collide, aveProfile.collide, m_maxProfile.collide);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "solve [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solve, aveProfile.solve, m_maxProfile.solve);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "solve init [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveInit, aveProfile.solveInit, m_maxProfile.solveInit);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "solve velocity [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveVelocity, aveProfile.solveVelocity, m_maxProfile.solveVelocity);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "solve position [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solvePosition, aveProfile.solvePosition, m_maxProfile.solvePosition);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "solveTOI [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveTOI, aveProfile.solveTOI, m_maxProfile.solveTOI);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "broad-phase [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.broadphase, aveProfile.broadphase, m_maxProfile.broadphase);
+ m_textLine += m_textIncrement;
+ }
+
+ if (m_bombSpawning)
+ {
+ b2Color c;
+ c.Set(0.0f, 0.0f, 1.0f);
+ g_debugDraw.DrawPoint(m_bombSpawnPoint, 4.0f, c);
+
+ c.Set(0.8f, 0.8f, 0.8f);
+ g_debugDraw.DrawSegment(m_mouseWorld, m_bombSpawnPoint, c);
+ }
+
+ if (settings.m_drawContactPoints)
+ {
+ const float k_impulseScale = 0.1f;
+ const float k_axisScale = 0.3f;
+
+ for (int32 i = 0; i < m_pointCount; ++i)
+ {
+ ContactPoint* point = m_points + i;
+
+ if (point->state == b2_addState)
+ {
+ // Add
+ g_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f));
+ }
+ else if (point->state == b2_persistState)
+ {
+ // Persist
+ g_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
+ }
+
+ if (settings.m_drawContactNormals == 1)
+ {
+ b2Vec2 p1 = point->position;
+ b2Vec2 p2 = p1 + k_axisScale * point->normal;
+ g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.9f));
+ }
+ else if (settings.m_drawContactImpulse == 1)
+ {
+ b2Vec2 p1 = point->position;
+ b2Vec2 p2 = p1 + k_impulseScale * point->normalImpulse * point->normal;
+ g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
+ }
+
+ if (settings.m_drawFrictionImpulse == 1)
+ {
+ b2Vec2 tangent = b2Cross(point->normal, 1.0f);
+ b2Vec2 p1 = point->position;
+ b2Vec2 p2 = p1 + k_impulseScale * point->tangentImpulse * tangent;
+ g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
+ }
+ }
+ }
+}
+
+void Test::ShiftOrigin(const b2Vec2& newOrigin)
+{
+ m_world->ShiftOrigin(newOrigin);
+}
+
+TestEntry g_testEntries[MAX_TESTS] = { {nullptr} };
+int g_testCount = 0;
+
+int RegisterTest(const char* category, const char* name, TestCreateFcn* fcn)
+{
+ int index = g_testCount;
+ if (index < MAX_TESTS)
+ {
+ g_testEntries[index] = { category, name, fcn };
+ ++g_testCount;
+ return index;
+ }
+
+ return -1;
+}
diff --git a/Client/ThirdParty/Box2D/testbed/test.h b/Client/ThirdParty/Box2D/testbed/test.h
new file mode 100644
index 0000000..d4f36c7
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/test.h
@@ -0,0 +1,156 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef TEST_H
+#define TEST_H
+
+#include "box2d/box2d.h"
+#include "draw.h"
+
+#include <stdlib.h>
+
+struct Settings;
+class Test;
+
+#define RAND_LIMIT 32767
+
+/// Random number in range [-1,1]
+inline float RandomFloat()
+{
+ float r = (float)(rand() & (RAND_LIMIT));
+ r /= RAND_LIMIT;
+ r = 2.0f * r - 1.0f;
+ return r;
+}
+
+/// Random floating point number in range [lo, hi]
+inline float RandomFloat(float lo, float hi)
+{
+ float r = (float)(rand() & (RAND_LIMIT));
+ r /= RAND_LIMIT;
+ r = (hi - lo) * r + lo;
+ return r;
+}
+
+// This is called when a joint in the world is implicitly destroyed
+// because an attached body is destroyed. This gives us a chance to
+// nullify the mouse joint.
+class DestructionListener : public b2DestructionListener
+{
+public:
+ void SayGoodbye(b2Fixture* fixture) override { B2_NOT_USED(fixture); }
+ void SayGoodbye(b2Joint* joint) override;
+
+ Test* test;
+};
+
+const int32 k_maxContactPoints = 2048;
+
+struct ContactPoint
+{
+ b2Fixture* fixtureA;
+ b2Fixture* fixtureB;
+ b2Vec2 normal;
+ b2Vec2 position;
+ b2PointState state;
+ float normalImpulse;
+ float tangentImpulse;
+ float separation;
+};
+
+class Test : public b2ContactListener
+{
+public:
+
+ Test();
+ virtual ~Test();
+
+ void DrawTitle(const char* string);
+ virtual void Step(Settings& settings);
+ virtual void UpdateUI() {}
+ virtual void Keyboard(int key) { B2_NOT_USED(key); }
+ virtual void KeyboardUp(int key) { B2_NOT_USED(key); }
+ void ShiftMouseDown(const b2Vec2& p);
+ virtual void MouseDown(const b2Vec2& p);
+ virtual void MouseUp(const b2Vec2& p);
+ virtual void MouseMove(const b2Vec2& p);
+ void LaunchBomb();
+ void LaunchBomb(const b2Vec2& position, const b2Vec2& velocity);
+
+ void SpawnBomb(const b2Vec2& worldPt);
+ void CompleteBombSpawn(const b2Vec2& p);
+
+ // Let derived tests know that a joint was destroyed.
+ virtual void JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); }
+
+ // Callbacks for derived classes.
+ virtual void BeginContact(b2Contact* contact) override { B2_NOT_USED(contact); }
+ virtual void EndContact(b2Contact* contact) override { B2_NOT_USED(contact); }
+ virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override;
+ virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override
+ {
+ B2_NOT_USED(contact);
+ B2_NOT_USED(impulse);
+ }
+
+ void ShiftOrigin(const b2Vec2& newOrigin);
+
+protected:
+ friend class DestructionListener;
+ friend class BoundaryListener;
+ friend class ContactListener;
+
+ b2Body* m_groundBody;
+ b2AABB m_worldAABB;
+ ContactPoint m_points[k_maxContactPoints];
+ int32 m_pointCount;
+ DestructionListener m_destructionListener;
+ int32 m_textLine;
+ b2World* m_world;
+ b2Body* m_bomb;
+ b2MouseJoint* m_mouseJoint;
+ b2Vec2 m_bombSpawnPoint;
+ bool m_bombSpawning;
+ b2Vec2 m_mouseWorld;
+ int32 m_stepCount;
+ int32 m_textIncrement;
+ b2Profile m_maxProfile;
+ b2Profile m_totalProfile;
+};
+
+typedef Test* TestCreateFcn();
+
+int RegisterTest(const char* category, const char* name, TestCreateFcn* fcn);
+
+//
+struct TestEntry
+{
+ const char* category;
+ const char* name;
+ TestCreateFcn* createFcn;
+};
+
+#define MAX_TESTS 256
+extern TestEntry g_testEntries[MAX_TESTS];
+extern int g_testCount;
+
+#endif
diff --git a/Client/ThirdParty/Box2D/testbed/tests/add_pair.cpp b/Client/ThirdParty/Box2D/testbed/tests/add_pair.cpp
new file mode 100644
index 0000000..ceccbf8
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/add_pair.cpp
@@ -0,0 +1,71 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class AddPair : public Test
+{
+public:
+
+ AddPair()
+ {
+ m_world->SetGravity(b2Vec2(0.0f,0.0f));
+ {
+ b2CircleShape shape;
+ shape.m_p.SetZero();
+ shape.m_radius = 0.1f;
+
+ float minX = -6.0f;
+ float maxX = 0.0f;
+ float minY = 4.0f;
+ float maxY = 6.0f;
+
+ for (int32 i = 0; i < 400; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = b2Vec2(RandomFloat(minX,maxX),RandomFloat(minY,maxY));
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 0.01f);
+ }
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(1.5f, 1.5f);
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-40.0f,5.0f);
+ bd.bullet = true;
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 1.0f);
+ body->SetLinearVelocity(b2Vec2(10.0f, 0.0f));
+ }
+ }
+
+ static Test* Create()
+ {
+ return new AddPair;
+ }
+};
+
+static int testIndex = RegisterTest("Benchmark", "Add Pair", AddPair::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/apply_force.cpp b/Client/ThirdParty/Box2D/testbed/tests/apply_force.cpp
new file mode 100644
index 0000000..65d8094
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/apply_force.cpp
@@ -0,0 +1,203 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// This test shows how to apply forces and torques to a body.
+// It also shows how to use the friction joint that can be useful
+// for overhead games.
+class ApplyForce : public Test
+{
+public:
+ ApplyForce()
+ {
+ m_world->SetGravity(b2Vec2(0.0f, 0.0f));
+
+ const float k_restitution = 0.4f;
+
+ b2Body* ground;
+ {
+ b2BodyDef bd;
+ bd.position.Set(0.0f, 20.0f);
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+
+ b2FixtureDef sd;
+ sd.shape = &shape;
+ sd.density = 0.0f;
+ sd.restitution = k_restitution;
+
+ // Left vertical
+ shape.SetTwoSided(b2Vec2(-20.0f, -20.0f), b2Vec2(-20.0f, 20.0f));
+ ground->CreateFixture(&sd);
+
+ // Right vertical
+ shape.SetTwoSided(b2Vec2(20.0f, -20.0f), b2Vec2(20.0f, 20.0f));
+ ground->CreateFixture(&sd);
+
+ // Top horizontal
+ shape.SetTwoSided(b2Vec2(-20.0f, 20.0f), b2Vec2(20.0f, 20.0f));
+ ground->CreateFixture(&sd);
+
+ // Bottom horizontal
+ shape.SetTwoSided(b2Vec2(-20.0f, -20.0f), b2Vec2(20.0f, -20.0f));
+ ground->CreateFixture(&sd);
+ }
+
+ {
+ b2Transform xf1;
+ xf1.q.Set(0.3524f * b2_pi);
+ xf1.p = xf1.q.GetXAxis();
+
+ b2Vec2 vertices[3];
+ vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f));
+ vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f));
+ vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f));
+
+ b2PolygonShape poly1;
+ poly1.Set(vertices, 3);
+
+ b2FixtureDef sd1;
+ sd1.shape = &poly1;
+ sd1.density = 2.0f;
+
+ b2Transform xf2;
+ xf2.q.Set(-0.3524f * b2_pi);
+ xf2.p = -xf2.q.GetXAxis();
+
+ vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f));
+ vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f));
+ vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f));
+
+ b2PolygonShape poly2;
+ poly2.Set(vertices, 3);
+
+ b2FixtureDef sd2;
+ sd2.shape = &poly2;
+ sd2.density = 2.0f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ bd.position.Set(0.0f, 3.0);
+ bd.angle = b2_pi;
+ bd.allowSleep = false;
+ m_body = m_world->CreateBody(&bd);
+ m_body->CreateFixture(&sd1);
+ m_body->CreateFixture(&sd2);
+
+ float gravity = 10.0f;
+ float I = m_body->GetInertia();
+ float mass = m_body->GetMass();
+
+ // Compute an effective radius that can be used to
+ // set the max torque for a friction joint
+ // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m)
+ float radius = b2Sqrt(2.0f * I / mass);
+
+ b2FrictionJointDef jd;
+ jd.bodyA = ground;
+ jd.bodyB = m_body;
+ jd.localAnchorA.SetZero();
+ jd.localAnchorB = m_body->GetLocalCenter();
+ jd.collideConnected = true;
+ jd.maxForce = 0.5f * mass * gravity;
+ jd.maxTorque = 0.2f * mass * radius * gravity;
+
+ m_world->CreateJoint(&jd);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+ fd.friction = 0.3f;
+
+ for (int i = 0; i < 10; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ bd.position.Set(0.0f, 7.0f + 1.54f * i);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ body->CreateFixture(&fd);
+
+ float gravity = 10.0f;
+ float I = body->GetInertia();
+ float mass = body->GetMass();
+
+ // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m)
+ float radius = b2Sqrt(2.0f * I / mass);
+
+ b2FrictionJointDef jd;
+ jd.localAnchorA.SetZero();
+ jd.localAnchorB.SetZero();
+ jd.bodyA = ground;
+ jd.bodyB = body;
+ jd.collideConnected = true;
+ jd.maxForce = mass * gravity;
+ jd.maxTorque = 0.1f * mass * radius * gravity;
+
+ m_world->CreateJoint(&jd);
+ }
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ g_debugDraw.DrawString(5, m_textLine, "Forward (W), Turn (A) and (D)");
+ m_textLine += m_textIncrement;
+
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_W) == GLFW_PRESS)
+ {
+ b2Vec2 f = m_body->GetWorldVector(b2Vec2(0.0f, -50.0f));
+ b2Vec2 p = m_body->GetWorldPoint(b2Vec2(0.0f, 3.0f));
+ m_body->ApplyForce(f, p, true);
+ }
+
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_A) == GLFW_PRESS)
+ {
+ m_body->ApplyTorque(10.0f, true);
+ }
+
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_D) == GLFW_PRESS)
+ {
+ m_body->ApplyTorque(-10.0f, true);
+ }
+
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new ApplyForce;
+ }
+
+ b2Body* m_body;
+};
+
+static int testIndex = RegisterTest("Forces", "Apply Force", ApplyForce::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/body_types.cpp b/Client/ThirdParty/Box2D/testbed/tests/body_types.cpp
new file mode 100644
index 0000000..279ae39
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/body_types.cpp
@@ -0,0 +1,163 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class BodyTypes : public Test
+{
+public:
+ BodyTypes()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+
+ ground->CreateFixture(&fd);
+ }
+
+ // Define attachment
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 3.0f);
+ m_attachment = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 2.0f);
+ m_attachment->CreateFixture(&shape, 2.0f);
+ }
+
+ // Define platform
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-4.0f, 5.0f);
+ m_platform = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 4.0f, b2Vec2(4.0f, 0.0f), 0.5f * b2_pi);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.friction = 0.6f;
+ fd.density = 2.0f;
+ m_platform->CreateFixture(&fd);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(m_attachment, m_platform, b2Vec2(0.0f, 5.0f));
+ rjd.maxMotorTorque = 50.0f;
+ rjd.enableMotor = true;
+ m_world->CreateJoint(&rjd);
+
+ b2PrismaticJointDef pjd;
+ pjd.Initialize(ground, m_platform, b2Vec2(0.0f, 5.0f), b2Vec2(1.0f, 0.0f));
+
+ pjd.maxMotorForce = 1000.0f;
+ pjd.enableMotor = true;
+ pjd.lowerTranslation = -10.0f;
+ pjd.upperTranslation = 10.0f;
+ pjd.enableLimit = true;
+
+ m_world->CreateJoint(&pjd);
+
+ m_speed = 3.0f;
+ }
+
+ // Create a payload
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 8.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.75f, 0.75f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.friction = 0.6f;
+ fd.density = 2.0f;
+
+ body->CreateFixture(&fd);
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_D:
+ m_platform->SetType(b2_dynamicBody);
+ break;
+
+ case GLFW_KEY_S:
+ m_platform->SetType(b2_staticBody);
+ break;
+
+ case GLFW_KEY_K:
+ m_platform->SetType(b2_kinematicBody);
+ m_platform->SetLinearVelocity(b2Vec2(-m_speed, 0.0f));
+ m_platform->SetAngularVelocity(0.0f);
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ // Drive the kinematic body.
+ if (m_platform->GetType() == b2_kinematicBody)
+ {
+ b2Vec2 p = m_platform->GetTransform().p;
+ b2Vec2 v = m_platform->GetLinearVelocity();
+
+ if ((p.x < -10.0f && v.x < 0.0f) ||
+ (p.x > 10.0f && v.x > 0.0f))
+ {
+ v.x = -v.x;
+ m_platform->SetLinearVelocity(v);
+ }
+ }
+
+ Test::Step(settings);
+
+ g_debugDraw.DrawString(5, m_textLine, "Keys: (d) dynamic, (s) static, (k) kinematic");
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new BodyTypes;
+ }
+
+ b2Body* m_attachment;
+ b2Body* m_platform;
+ float m_speed;
+};
+
+static int testIndex = RegisterTest("Examples", "Body Types", BodyTypes::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/box_stack.cpp b/Client/ThirdParty/Box2D/testbed/tests/box_stack.cpp
new file mode 100644
index 0000000..db9fec5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/box_stack.cpp
@@ -0,0 +1,174 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+extern B2_API bool g_blockSolve;
+
+class BoxStack : public Test
+{
+public:
+
+ enum
+ {
+ e_columnCount = 1,
+ e_rowCount = 15
+ //e_columnCount = 1,
+ //e_rowCount = 1
+ };
+
+ BoxStack()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(b2Vec2(20.0f, 0.0f), b2Vec2(20.0f, 20.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ float xs[5] = {0.0f, -10.0f, -5.0f, 5.0f, 10.0f};
+
+ for (int32 j = 0; j < e_columnCount; ++j)
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+ fd.friction = 0.3f;
+
+ for (int i = 0; i < e_rowCount; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ int32 n = j * e_rowCount + i;
+ b2Assert(n < e_rowCount * e_columnCount);
+ m_indices[n] = n;
+ bd.userData.pointer = n;
+
+ float x = 0.0f;
+ //float x = RandomFloat(-0.02f, 0.02f);
+ //float x = i % 2 == 0 ? -0.01f : 0.01f;
+ bd.position.Set(xs[j] + x, 0.55f + 1.1f * i);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ m_bodies[n] = body;
+
+ body->CreateFixture(&fd);
+ }
+ }
+
+ m_bullet = NULL;
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_COMMA:
+ if (m_bullet != NULL)
+ {
+ m_world->DestroyBody(m_bullet);
+ m_bullet = NULL;
+ }
+
+ {
+ b2CircleShape shape;
+ shape.m_radius = 0.25f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ fd.restitution = 0.05f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.bullet = true;
+ bd.position.Set(-31.0f, 5.0f);
+
+ m_bullet = m_world->CreateBody(&bd);
+ m_bullet->CreateFixture(&fd);
+
+ m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f));
+ }
+ break;
+
+ case GLFW_KEY_B:
+ g_blockSolve = !g_blockSolve;
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "Press: (,) to launch a bullet.");
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "Blocksolve = %d", g_blockSolve);
+ //if (m_stepCount == 300)
+ //{
+ // if (m_bullet != NULL)
+ // {
+ // m_world->DestroyBody(m_bullet);
+ // m_bullet = NULL;
+ // }
+
+ // {
+ // b2CircleShape shape;
+ // shape.m_radius = 0.25f;
+
+ // b2FixtureDef fd;
+ // fd.shape = &shape;
+ // fd.density = 20.0f;
+ // fd.restitution = 0.05f;
+
+ // b2BodyDef bd;
+ // bd.type = b2_dynamicBody;
+ // bd.bullet = true;
+ // bd.position.Set(-31.0f, 5.0f);
+
+ // m_bullet = m_world->CreateBody(&bd);
+ // m_bullet->CreateFixture(&fd);
+
+ // m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f));
+ // }
+ //}
+ }
+
+ static Test* Create()
+ {
+ return new BoxStack;
+ }
+
+ b2Body* m_bullet;
+ b2Body* m_bodies[e_rowCount * e_columnCount];
+ int32 m_indices[e_rowCount * e_columnCount];
+};
+
+static int testIndex = RegisterTest("Stacking", "Boxes", BoxStack::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/breakable.cpp b/Client/ThirdParty/Box2D/testbed/tests/breakable.cpp
new file mode 100644
index 0000000..136244a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/breakable.cpp
@@ -0,0 +1,158 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// This is used to test sensor shapes.
+class Breakable : public Test
+{
+public:
+
+ enum
+ {
+ e_count = 7
+ };
+
+ Breakable()
+ {
+ // Ground body
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Breakable dynamic body
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 40.0f);
+ bd.angle = 0.25f * b2_pi;
+ m_body1 = m_world->CreateBody(&bd);
+
+ m_shape1.SetAsBox(0.5f, 0.5f, b2Vec2(-0.5f, 0.0f), 0.0f);
+ m_piece1 = m_body1->CreateFixture(&m_shape1, 1.0f);
+
+ m_shape2.SetAsBox(0.5f, 0.5f, b2Vec2(0.5f, 0.0f), 0.0f);
+ m_piece2 = m_body1->CreateFixture(&m_shape2, 1.0f);
+ }
+
+ m_break = false;
+ m_broke = false;
+ }
+
+ void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override
+ {
+ if (m_broke)
+ {
+ // The body already broke.
+ return;
+ }
+
+ // Should the body break?
+ int32 count = contact->GetManifold()->pointCount;
+
+ float maxImpulse = 0.0f;
+ for (int32 i = 0; i < count; ++i)
+ {
+ maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]);
+ }
+
+ if (maxImpulse > 40.0f)
+ {
+ // Flag the body for breaking.
+ m_break = true;
+ }
+ }
+
+ void Break()
+ {
+ // Create two bodies from one.
+ b2Body* body1 = m_piece1->GetBody();
+ b2Vec2 center = body1->GetWorldCenter();
+
+ body1->DestroyFixture(m_piece2);
+ m_piece2 = NULL;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = body1->GetPosition();
+ bd.angle = body1->GetAngle();
+
+ b2Body* body2 = m_world->CreateBody(&bd);
+ m_piece2 = body2->CreateFixture(&m_shape2, 1.0f);
+
+ // Compute consistent velocities for new bodies based on
+ // cached velocity.
+ b2Vec2 center1 = body1->GetWorldCenter();
+ b2Vec2 center2 = body2->GetWorldCenter();
+
+ b2Vec2 velocity1 = m_velocity + b2Cross(m_angularVelocity, center1 - center);
+ b2Vec2 velocity2 = m_velocity + b2Cross(m_angularVelocity, center2 - center);
+
+ body1->SetAngularVelocity(m_angularVelocity);
+ body1->SetLinearVelocity(velocity1);
+
+ body2->SetAngularVelocity(m_angularVelocity);
+ body2->SetLinearVelocity(velocity2);
+ }
+
+ void Step(Settings& settings) override
+ {
+ if (m_break)
+ {
+ Break();
+ m_broke = true;
+ m_break = false;
+ }
+
+ // Cache velocities to improve movement on breakage.
+ if (m_broke == false)
+ {
+ m_velocity = m_body1->GetLinearVelocity();
+ m_angularVelocity = m_body1->GetAngularVelocity();
+ }
+
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new Breakable;
+ }
+
+ b2Body* m_body1;
+ b2Vec2 m_velocity;
+ float m_angularVelocity;
+ b2PolygonShape m_shape1;
+ b2PolygonShape m_shape2;
+ b2Fixture* m_piece1;
+ b2Fixture* m_piece2;
+
+ bool m_broke;
+ bool m_break;
+};
+
+static int testIndex = RegisterTest("Examples", "Breakable", Breakable::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/bridge.cpp b/Client/ThirdParty/Box2D/testbed/tests/bridge.cpp
new file mode 100644
index 0000000..d397a60
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/bridge.cpp
@@ -0,0 +1,128 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Bridge : public Test
+{
+public:
+
+ enum
+ {
+ e_count = 30
+ };
+
+ Bridge()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ fd.friction = 0.2f;
+
+ b2RevoluteJointDef jd;
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-14.5f + 1.0f * i, 5.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+
+ b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f);
+ jd.Initialize(prevBody, body, anchor);
+ m_world->CreateJoint(&jd);
+
+ if (i == (e_count >> 1))
+ {
+ m_middle = body;
+ }
+ prevBody = body;
+ }
+
+ b2Vec2 anchor(-15.0f + 1.0f * e_count, 5.0f);
+ jd.Initialize(prevBody, ground, anchor);
+ m_world->CreateJoint(&jd);
+ }
+
+ for (int32 i = 0; i < 2; ++i)
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.5f, 0.0f);
+ vertices[1].Set(0.5f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+
+ b2PolygonShape shape;
+ shape.Set(vertices, 3);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-8.0f + 8.0f * i, 12.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+ }
+
+ for (int32 i = 0; i < 3; ++i)
+ {
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-6.0f + 6.0f * i, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Bridge;
+ }
+
+ b2Body* m_middle;
+};
+
+static int testIndex = RegisterTest("Joints", "Bridge", Bridge::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/bullet_test.cpp b/Client/ThirdParty/Box2D/testbed/tests/bullet_test.cpp
new file mode 100644
index 0000000..9ddd733
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/bullet_test.cpp
@@ -0,0 +1,139 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class BulletTest : public Test
+{
+public:
+
+ BulletTest()
+ {
+ {
+ b2BodyDef bd;
+ bd.position.Set(0.0f, 0.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2EdgeShape edge;
+
+ edge.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f));
+ body->CreateFixture(&edge, 0.0f);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f);
+ body->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 4.0f);
+
+ b2PolygonShape box;
+ box.SetAsBox(2.0f, 0.1f);
+
+ m_body = m_world->CreateBody(&bd);
+ m_body->CreateFixture(&box, 1.0f);
+
+ box.SetAsBox(0.25f, 0.25f);
+
+ //m_x = RandomFloat(-1.0f, 1.0f);
+ m_x = 0.20352793f;
+ bd.position.Set(m_x, 10.0f);
+ bd.bullet = true;
+
+ m_bullet = m_world->CreateBody(&bd);
+ m_bullet->CreateFixture(&box, 100.0f);
+
+ m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f));
+ }
+ }
+
+ void Launch()
+ {
+ m_body->SetTransform(b2Vec2(0.0f, 4.0f), 0.0f);
+ m_body->SetLinearVelocity(b2Vec2_zero);
+ m_body->SetAngularVelocity(0.0f);
+
+ m_x = RandomFloat(-1.0f, 1.0f);
+ m_bullet->SetTransform(b2Vec2(m_x, 10.0f), 0.0f);
+ m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f));
+ m_bullet->SetAngularVelocity(0.0f);
+
+ extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
+ extern B2_API int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters;
+ extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters;
+
+ b2_gjkCalls = 0;
+ b2_gjkIters = 0;
+ b2_gjkMaxIters = 0;
+
+ b2_toiCalls = 0;
+ b2_toiIters = 0;
+ b2_toiMaxIters = 0;
+ b2_toiRootIters = 0;
+ b2_toiMaxRootIters = 0;
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
+ extern B2_API int32 b2_toiCalls, b2_toiIters;
+ extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters;
+
+ if (b2_gjkCalls > 0)
+ {
+ g_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d",
+ b2_gjkCalls, b2_gjkIters / float(b2_gjkCalls), b2_gjkMaxIters);
+ m_textLine += m_textIncrement;
+ }
+
+ if (b2_toiCalls > 0)
+ {
+ g_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d",
+ b2_toiCalls, b2_toiIters / float(b2_toiCalls), b2_toiMaxRootIters);
+ m_textLine += m_textIncrement;
+
+ g_debugDraw.DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d",
+ b2_toiRootIters / float(b2_toiCalls), b2_toiMaxRootIters);
+ m_textLine += m_textIncrement;
+ }
+
+ if (m_stepCount % 60 == 0)
+ {
+ Launch();
+ }
+ }
+
+ static Test* Create()
+ {
+ return new BulletTest;
+ }
+
+ b2Body* m_body;
+ b2Body* m_bullet;
+ float m_x;
+};
+
+static int testIndex = RegisterTest("Continuous", "Bullet Test", BulletTest::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/cantilever.cpp b/Client/ThirdParty/Box2D/testbed/tests/cantilever.cpp
new file mode 100644
index 0000000..e54717b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/cantilever.cpp
@@ -0,0 +1,218 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// It is difficult to make a cantilever made of links completely rigid with weld joints.
+// You will have to use a high number of iterations to make them stiff.
+// So why not go ahead and use soft weld joints? They behave like a revolute
+// joint with a rotational spring.
+class Cantilever : public Test
+{
+public:
+
+ enum
+ {
+ e_count = 8
+ };
+
+ Cantilever()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+
+ b2WeldJointDef jd;
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-14.5f + 1.0f * i, 5.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+
+ b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f);
+ jd.Initialize(prevBody, body, anchor);
+ m_world->CreateJoint(&jd);
+
+ prevBody = body;
+ }
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(1.0f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+
+ b2WeldJointDef jd;
+ float frequencyHz = 5.0f;
+ float dampingRatio = 0.7f;
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < 3; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-14.0f + 2.0f * i, 15.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+
+ b2Vec2 anchor(-15.0f + 2.0f * i, 15.0f);
+ jd.Initialize(prevBody, body, anchor);
+ b2AngularStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_world->CreateJoint(&jd);
+
+ prevBody = body;
+ }
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+
+ b2WeldJointDef jd;
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-4.5f + 1.0f * i, 5.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+
+ if (i > 0)
+ {
+ b2Vec2 anchor(-5.0f + 1.0f * i, 5.0f);
+ jd.Initialize(prevBody, body, anchor);
+ m_world->CreateJoint(&jd);
+ }
+
+ prevBody = body;
+ }
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+
+ b2WeldJointDef jd;
+ float frequencyHz = 8.0f;
+ float dampingRatio = 0.7f;
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(5.5f + 1.0f * i, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+
+ if (i > 0)
+ {
+ b2Vec2 anchor(5.0f + 1.0f * i, 10.0f);
+ jd.Initialize(prevBody, body, anchor);
+
+ b2AngularStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, prevBody, body);
+
+ m_world->CreateJoint(&jd);
+ }
+
+ prevBody = body;
+ }
+ }
+
+ for (int32 i = 0; i < 2; ++i)
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.5f, 0.0f);
+ vertices[1].Set(0.5f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+
+ b2PolygonShape shape;
+ shape.Set(vertices, 3);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-8.0f + 8.0f * i, 12.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+ }
+
+ for (int32 i = 0; i < 2; ++i)
+ {
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-6.0f + 6.0f * i, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Cantilever;
+ }
+
+ b2Body* m_middle;
+};
+
+static int testIndex = RegisterTest("Joints", "Cantilever", Cantilever::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/car.cpp b/Client/ThirdParty/Box2D/testbed/tests/car.cpp
new file mode 100644
index 0000000..06a9b65
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/car.cpp
@@ -0,0 +1,284 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// This is a fun demo that shows off the wheel joint
+class Car : public Test
+{
+public:
+ Car()
+ {
+ m_speed = 50.0f;
+
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 0.0f;
+ fd.friction = 0.6f;
+
+ shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));
+ ground->CreateFixture(&fd);
+
+ float hs[10] = {0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f};
+
+ float x = 20.0f, y1 = 0.0f, dx = 5.0f;
+
+ for (int32 i = 0; i < 10; ++i)
+ {
+ float y2 = hs[i];
+ shape.SetTwoSided(b2Vec2(x, y1), b2Vec2(x + dx, y2));
+ ground->CreateFixture(&fd);
+ y1 = y2;
+ x += dx;
+ }
+
+ for (int32 i = 0; i < 10; ++i)
+ {
+ float y2 = hs[i];
+ shape.SetTwoSided(b2Vec2(x, y1), b2Vec2(x + dx, y2));
+ ground->CreateFixture(&fd);
+ y1 = y2;
+ x += dx;
+ }
+
+ shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f));
+ ground->CreateFixture(&fd);
+
+ x += 80.0f;
+ shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f));
+ ground->CreateFixture(&fd);
+
+ x += 40.0f;
+ shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 10.0f, 5.0f));
+ ground->CreateFixture(&fd);
+
+ x += 20.0f;
+ shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f));
+ ground->CreateFixture(&fd);
+
+ x += 40.0f;
+ shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x, 20.0f));
+ ground->CreateFixture(&fd);
+ }
+
+ // Teeter
+ {
+ b2BodyDef bd;
+ bd.position.Set(140.0f, 1.0f);
+ bd.type = b2_dynamicBody;
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape box;
+ box.SetAsBox(10.0f, 0.25f);
+ body->CreateFixture(&box, 1.0f);
+
+ b2RevoluteJointDef jd;
+ jd.Initialize(ground, body, body->GetPosition());
+ jd.lowerAngle = -8.0f * b2_pi / 180.0f;
+ jd.upperAngle = 8.0f * b2_pi / 180.0f;
+ jd.enableLimit = true;
+ m_world->CreateJoint(&jd);
+
+ body->ApplyAngularImpulse(100.0f, true);
+ }
+
+ // Bridge
+ {
+ int32 N = 20;
+ b2PolygonShape shape;
+ shape.SetAsBox(1.0f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+ fd.friction = 0.6f;
+
+ b2RevoluteJointDef jd;
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < N; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(161.0f + 2.0f * i, -0.125f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+
+ b2Vec2 anchor(160.0f + 2.0f * i, -0.125f);
+ jd.Initialize(prevBody, body, anchor);
+ m_world->CreateJoint(&jd);
+
+ prevBody = body;
+ }
+
+ b2Vec2 anchor(160.0f + 2.0f * N, -0.125f);
+ jd.Initialize(prevBody, ground, anchor);
+ m_world->CreateJoint(&jd);
+ }
+
+ // Boxes
+ {
+ b2PolygonShape box;
+ box.SetAsBox(0.5f, 0.5f);
+
+ b2Body* body = NULL;
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ bd.position.Set(230.0f, 0.5f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&box, 0.5f);
+
+ bd.position.Set(230.0f, 1.5f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&box, 0.5f);
+
+ bd.position.Set(230.0f, 2.5f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&box, 0.5f);
+
+ bd.position.Set(230.0f, 3.5f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&box, 0.5f);
+
+ bd.position.Set(230.0f, 4.5f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&box, 0.5f);
+ }
+
+ // Car
+ {
+ b2PolygonShape chassis;
+ b2Vec2 vertices[8];
+ vertices[0].Set(-1.5f, -0.5f);
+ vertices[1].Set(1.5f, -0.5f);
+ vertices[2].Set(1.5f, 0.0f);
+ vertices[3].Set(0.0f, 0.9f);
+ vertices[4].Set(-1.15f, 0.9f);
+ vertices[5].Set(-1.5f, 0.2f);
+ chassis.Set(vertices, 6);
+
+ b2CircleShape circle;
+ circle.m_radius = 0.4f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 1.0f);
+ m_car = m_world->CreateBody(&bd);
+ m_car->CreateFixture(&chassis, 1.0f);
+
+ b2FixtureDef fd;
+ fd.shape = &circle;
+ fd.density = 1.0f;
+ fd.friction = 0.9f;
+
+ bd.position.Set(-1.0f, 0.35f);
+ m_wheel1 = m_world->CreateBody(&bd);
+ m_wheel1->CreateFixture(&fd);
+
+ bd.position.Set(1.0f, 0.4f);
+ m_wheel2 = m_world->CreateBody(&bd);
+ m_wheel2->CreateFixture(&fd);
+
+ b2WheelJointDef jd;
+ b2Vec2 axis(0.0f, 1.0f);
+
+ float mass1 = m_wheel1->GetMass();
+ float mass2 = m_wheel2->GetMass();
+
+ float hertz = 4.0f;
+ float dampingRatio = 0.7f;
+ float omega = 2.0f * b2_pi * hertz;
+
+ jd.Initialize(m_car, m_wheel1, m_wheel1->GetPosition(), axis);
+ jd.motorSpeed = 0.0f;
+ jd.maxMotorTorque = 20.0f;
+ jd.enableMotor = true;
+ jd.stiffness = mass1 * omega * omega;
+ jd.damping = 2.0f * mass1 * dampingRatio * omega;
+ jd.lowerTranslation = -0.25f;
+ jd.upperTranslation = 0.25f;
+ jd.enableLimit = true;
+ m_spring1 = (b2WheelJoint*)m_world->CreateJoint(&jd);
+
+ jd.Initialize(m_car, m_wheel2, m_wheel2->GetPosition(), axis);
+ jd.motorSpeed = 0.0f;
+ jd.maxMotorTorque = 10.0f;
+ jd.enableMotor = false;
+ jd.stiffness = mass2 * omega * omega;
+ jd.damping = 2.0f * mass2 * dampingRatio * omega;
+ jd.lowerTranslation = -0.25f;
+ jd.upperTranslation = 0.25f;
+ jd.enableLimit = true;
+ m_spring2 = (b2WheelJoint*)m_world->CreateJoint(&jd);
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_spring1->SetMotorSpeed(m_speed);
+ break;
+
+ case GLFW_KEY_S:
+ m_spring1->SetMotorSpeed(0.0f);
+ break;
+
+ case GLFW_KEY_D:
+ m_spring1->SetMotorSpeed(-m_speed);
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ g_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, hz down = q, hz up = e");
+ m_textLine += m_textIncrement;
+
+ g_camera.m_center.x = m_car->GetPosition().x;
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new Car;
+ }
+
+ b2Body* m_car;
+ b2Body* m_wheel1;
+ b2Body* m_wheel2;
+
+ float m_speed;
+ b2WheelJoint* m_spring1;
+ b2WheelJoint* m_spring2;
+};
+
+static int testIndex = RegisterTest("Examples", "Car", Car::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/chain.cpp b/Client/ThirdParty/Box2D/testbed/tests/chain.cpp
new file mode 100644
index 0000000..e158035
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/chain.cpp
@@ -0,0 +1,92 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+#define TEST_BAD_BODY 0
+
+class Chain : public Test
+{
+public:
+ Chain()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.6f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ fd.friction = 0.2f;
+
+ b2RevoluteJointDef jd;
+ jd.collideConnected = false;
+
+ const float y = 25.0f;
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < 30; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.5f + i, y);
+ b2Body* body = m_world->CreateBody(&bd);
+
+#if TEST_BAD_BODY == 1
+ if (i == 10)
+ {
+ // Test zero density dynamic body
+ fd.density = 0.0f;
+ }
+ else
+ {
+ fd.density = 20.0f;
+ }
+#endif
+
+ body->CreateFixture(&fd);
+
+ b2Vec2 anchor(float(i), y);
+ jd.Initialize(prevBody, body, anchor);
+ m_world->CreateJoint(&jd);
+
+ prevBody = body;
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Chain;
+ }
+};
+
+static int testIndex = RegisterTest("Joints", "Chain", Chain::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/chain_problem.cpp b/Client/ThirdParty/Box2D/testbed/tests/chain_problem.cpp
new file mode 100644
index 0000000..4b2ab38
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/chain_problem.cpp
@@ -0,0 +1,94 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class ChainProblem : public Test
+{
+public:
+
+ ChainProblem()
+ {
+ {
+ b2Vec2 g(0.0f, -10.0f);
+ m_world->SetGravity(g);
+ b2Body** bodies = (b2Body**)b2Alloc(2 * sizeof(b2Body*));
+ b2Joint** joints = (b2Joint**)b2Alloc(0 * sizeof(b2Joint*));
+ {
+ b2BodyDef bd;
+ bd.type = b2BodyType(0);
+ bodies[0] = m_world->CreateBody(&bd);
+
+ {
+ b2FixtureDef fd;
+
+ b2Vec2 v1(0.0f, 1.0f);
+ b2Vec2 v2(0.0f, 0.0f);
+ b2Vec2 v3(4.0f, 0.0f);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(v1, v2);
+ bodies[0]->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v2, v3);
+ bodies[0]->CreateFixture(&shape, 0.0f);
+ }
+ }
+ {
+ b2BodyDef bd;
+ bd.type = b2BodyType(2);
+ //bd.position.Set(6.033980250358582e-01f, 3.028350114822388e+00f);
+ bd.position.Set(1.0f, 3.0f);
+ bodies[1] = m_world->CreateBody(&bd);
+
+ {
+ b2FixtureDef fd;
+ fd.friction = 0.2f;
+ fd.density = 10.0f;
+ b2PolygonShape shape;
+ b2Vec2 vs[8];
+ vs[0].Set(0.5f, -3.0f);
+ vs[1].Set(0.5f, 3.0f);
+ vs[2].Set(-0.5f, 3.0f);
+ vs[3].Set(-0.5f, -3.0f);
+ shape.Set(vs, 4);
+
+ fd.shape = &shape;
+
+ bodies[1]->CreateFixture(&fd);
+ }
+ }
+ b2Free(joints);
+ b2Free(bodies);
+ joints = NULL;
+ bodies = NULL;
+ }
+ }
+
+ static Test* Create()
+ {
+ return new ChainProblem;
+ }
+
+};
+
+static int testIndex = RegisterTest("Bugs", "Chain Problem", ChainProblem::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/character_collision.cpp b/Client/ThirdParty/Box2D/testbed/tests/character_collision.cpp
new file mode 100644
index 0000000..3eab4a7
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/character_collision.cpp
@@ -0,0 +1,256 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+/// This is a test of typical character collision scenarios. This does not
+/// show how you should implement a character in your application.
+/// Instead this is used to test smooth collision on edge chains.
+class CharacterCollision : public Test
+{
+public:
+ CharacterCollision()
+ {
+ // Ground body
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Collinear edges with no adjacency information.
+ // This shows the problematic case where a box shape can hit
+ // an internal vertex.
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-8.0f, 1.0f), b2Vec2(-6.0f, 1.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ shape.SetTwoSided(b2Vec2(-6.0f, 1.0f), b2Vec2(-4.0f, 1.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ shape.SetTwoSided(b2Vec2(-4.0f, 1.0f), b2Vec2(-2.0f, 1.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Chain shape
+ {
+ b2BodyDef bd;
+ bd.angle = 0.25f * b2_pi;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2Vec2 vs[4];
+ vs[0].Set(5.0f, 7.0f);
+ vs[1].Set(6.0f, 8.0f);
+ vs[2].Set(7.0f, 8.0f);
+ vs[3].Set(8.0f, 7.0f);
+ b2ChainShape shape;
+ shape.CreateLoop(vs, 4);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Square tiles. This shows that adjacency shapes may
+ // have non-smooth collision. There is no solution
+ // to this problem.
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(1.0f, 1.0f, b2Vec2(4.0f, 3.0f), 0.0f);
+ ground->CreateFixture(&shape, 0.0f);
+ shape.SetAsBox(1.0f, 1.0f, b2Vec2(6.0f, 3.0f), 0.0f);
+ ground->CreateFixture(&shape, 0.0f);
+ shape.SetAsBox(1.0f, 1.0f, b2Vec2(8.0f, 3.0f), 0.0f);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Square made from an edge loop. Collision should be smooth.
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2Vec2 vs[4];
+ vs[0].Set(-1.0f, 3.0f);
+ vs[1].Set(1.0f, 3.0f);
+ vs[2].Set(1.0f, 5.0f);
+ vs[3].Set(-1.0f, 5.0f);
+ b2ChainShape shape;
+ shape.CreateLoop(vs, 4);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Edge loop. Collision should be smooth.
+ {
+ b2BodyDef bd;
+ bd.position.Set(-10.0f, 4.0f);
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2Vec2 vs[10];
+ vs[0].Set(0.0f, 0.0f);
+ vs[1].Set(6.0f, 0.0f);
+ vs[2].Set(6.0f, 2.0f);
+ vs[3].Set(4.0f, 1.0f);
+ vs[4].Set(2.0f, 2.0f);
+ vs[5].Set(0.0f, 2.0f);
+ vs[6].Set(-2.0f, 2.0f);
+ vs[7].Set(-4.0f, 3.0f);
+ vs[8].Set(-6.0f, 2.0f);
+ vs[9].Set(-6.0f, 0.0f);
+ b2ChainShape shape;
+ shape.CreateLoop(vs, 10);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Square character 1
+ {
+ b2BodyDef bd;
+ bd.position.Set(-3.0f, 8.0f);
+ bd.type = b2_dynamicBody;
+ bd.fixedRotation = true;
+ bd.allowSleep = false;
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ body->CreateFixture(&fd);
+ }
+
+ // Square character 2
+ {
+ b2BodyDef bd;
+ bd.position.Set(-5.0f, 5.0f);
+ bd.type = b2_dynamicBody;
+ bd.fixedRotation = true;
+ bd.allowSleep = false;
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f, 0.25f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ body->CreateFixture(&fd);
+ }
+
+ // Hexagon character
+ {
+ b2BodyDef bd;
+ bd.position.Set(-5.0f, 8.0f);
+ bd.type = b2_dynamicBody;
+ bd.fixedRotation = true;
+ bd.allowSleep = false;
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ float angle = 0.0f;
+ float delta = b2_pi / 3.0f;
+ b2Vec2 vertices[6];
+ for (int32 i = 0; i < 6; ++i)
+ {
+ vertices[i].Set(0.5f * cosf(angle), 0.5f * sinf(angle));
+ angle += delta;
+ }
+
+ b2PolygonShape shape;
+ shape.Set(vertices, 6);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ body->CreateFixture(&fd);
+ }
+
+ // Circle character
+ {
+ b2BodyDef bd;
+ bd.position.Set(3.0f, 5.0f);
+ bd.type = b2_dynamicBody;
+ bd.fixedRotation = true;
+ bd.allowSleep = false;
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ body->CreateFixture(&fd);
+ }
+
+ // Circle character
+ {
+ b2BodyDef bd;
+ bd.position.Set(-7.0f, 6.0f);
+ bd.type = b2_dynamicBody;
+ bd.allowSleep = false;
+
+ m_character = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.25f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ fd.friction = 1.0f;
+ m_character->CreateFixture(&fd);
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ b2Vec2 v = m_character->GetLinearVelocity();
+ v.x = -5.0f;
+ m_character->SetLinearVelocity(v);
+
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "This tests various character collision shapes.");
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "Limitation: square and hexagon can snag on aligned boxes.");
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "Feature: edge chains have smooth collision inside and out.");
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new CharacterCollision;
+ }
+
+ b2Body* m_character;
+};
+
+static int testIndex = RegisterTest("Examples", "Character Collision", CharacterCollision::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/circle_stack.cpp b/Client/ThirdParty/Box2D/testbed/tests/circle_stack.cpp
new file mode 100644
index 0000000..62d19ea
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/circle_stack.cpp
@@ -0,0 +1,89 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class CircleStack : public Test
+{
+public:
+
+ enum
+ {
+ e_count = 10
+ };
+
+ CircleStack()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2CircleShape shape;
+ shape.m_radius = 1.0f;
+
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0, 4.0f + 3.0f * i);
+
+ m_bodies[i] = m_world->CreateBody(&bd);
+
+ m_bodies[i]->CreateFixture(&shape, 1.0f);
+
+ m_bodies[i]->SetLinearVelocity(b2Vec2(0.0f, -50.0f));
+ }
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ //for (int32 i = 0; i < e_count; ++i)
+ //{
+ // printf("%g ", m_bodies[i]->GetWorldCenter().y);
+ //}
+
+ //for (int32 i = 0; i < e_count; ++i)
+ //{
+ // printf("%g ", m_bodies[i]->GetLinearVelocity().y);
+ //}
+
+ //printf("\n");
+ }
+
+ static Test* Create()
+ {
+ return new CircleStack;
+ }
+
+ b2Body* m_bodies[e_count];
+};
+
+static int testIndex = RegisterTest("Stacking", "Circles", CircleStack::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/collision_filtering.cpp b/Client/ThirdParty/Box2D/testbed/tests/collision_filtering.cpp
new file mode 100644
index 0000000..4903da5
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/collision_filtering.cpp
@@ -0,0 +1,179 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// This is a test of collision filtering.
+// There is a triangle, a box, and a circle.
+// There are 6 shapes. 3 large and 3 small.
+// The 3 small ones always collide.
+// The 3 large ones never collide.
+// The boxes don't collide with triangles (except if both are small).
+const int16 k_smallGroup = 1;
+const int16 k_largeGroup = -1;
+
+const uint16 k_triangleCategory = 0x0002;
+const uint16 k_boxCategory = 0x0004;
+const uint16 k_circleCategory = 0x0008;
+
+const uint16 k_triangleMask = 0xFFFF;
+const uint16 k_boxMask = 0xFFFF ^ k_triangleCategory;
+const uint16 k_circleMask = 0xFFFF;
+
+class CollisionFiltering : public Test
+{
+public:
+ CollisionFiltering()
+ {
+ // Ground body
+ {
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+
+ b2FixtureDef sd;
+ sd.shape = &shape;
+ sd.friction = 0.3f;
+
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&sd);
+ }
+
+ // Small triangle
+ b2Vec2 vertices[3];
+ vertices[0].Set(-1.0f, 0.0f);
+ vertices[1].Set(1.0f, 0.0f);
+ vertices[2].Set(0.0f, 2.0f);
+ b2PolygonShape polygon;
+ polygon.Set(vertices, 3);
+
+ b2FixtureDef triangleShapeDef;
+ triangleShapeDef.shape = &polygon;
+ triangleShapeDef.density = 1.0f;
+
+ triangleShapeDef.filter.groupIndex = k_smallGroup;
+ triangleShapeDef.filter.categoryBits = k_triangleCategory;
+ triangleShapeDef.filter.maskBits = k_triangleMask;
+
+ b2BodyDef triangleBodyDef;
+ triangleBodyDef.type = b2_dynamicBody;
+ triangleBodyDef.position.Set(-5.0f, 2.0f);
+
+ b2Body* body1 = m_world->CreateBody(&triangleBodyDef);
+ body1->CreateFixture(&triangleShapeDef);
+
+ // Large triangle (recycle definitions)
+ vertices[0] *= 2.0f;
+ vertices[1] *= 2.0f;
+ vertices[2] *= 2.0f;
+ polygon.Set(vertices, 3);
+ triangleShapeDef.filter.groupIndex = k_largeGroup;
+ triangleBodyDef.position.Set(-5.0f, 6.0f);
+ triangleBodyDef.fixedRotation = true; // look at me!
+
+ b2Body* body2 = m_world->CreateBody(&triangleBodyDef);
+ body2->CreateFixture(&triangleShapeDef);
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-5.0f, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape p;
+ p.SetAsBox(0.5f, 1.0f);
+ body->CreateFixture(&p, 1.0f);
+
+ b2PrismaticJointDef jd;
+ jd.bodyA = body2;
+ jd.bodyB = body;
+ jd.enableLimit = true;
+ jd.localAnchorA.Set(0.0f, 4.0f);
+ jd.localAnchorB.SetZero();
+ jd.localAxisA.Set(0.0f, 1.0f);
+ jd.lowerTranslation = -1.0f;
+ jd.upperTranslation = 1.0f;
+
+ m_world->CreateJoint(&jd);
+ }
+
+ // Small box
+ polygon.SetAsBox(1.0f, 0.5f);
+ b2FixtureDef boxShapeDef;
+ boxShapeDef.shape = &polygon;
+ boxShapeDef.density = 1.0f;
+ boxShapeDef.restitution = 0.1f;
+
+ boxShapeDef.filter.groupIndex = k_smallGroup;
+ boxShapeDef.filter.categoryBits = k_boxCategory;
+ boxShapeDef.filter.maskBits = k_boxMask;
+
+ b2BodyDef boxBodyDef;
+ boxBodyDef.type = b2_dynamicBody;
+ boxBodyDef.position.Set(0.0f, 2.0f);
+
+ b2Body* body3 = m_world->CreateBody(&boxBodyDef);
+ body3->CreateFixture(&boxShapeDef);
+
+ // Large box (recycle definitions)
+ polygon.SetAsBox(2.0f, 1.0f);
+ boxShapeDef.filter.groupIndex = k_largeGroup;
+ boxBodyDef.position.Set(0.0f, 6.0f);
+
+ b2Body* body4 = m_world->CreateBody(&boxBodyDef);
+ body4->CreateFixture(&boxShapeDef);
+
+ // Small circle
+ b2CircleShape circle;
+ circle.m_radius = 1.0f;
+
+ b2FixtureDef circleShapeDef;
+ circleShapeDef.shape = &circle;
+ circleShapeDef.density = 1.0f;
+
+ circleShapeDef.filter.groupIndex = k_smallGroup;
+ circleShapeDef.filter.categoryBits = k_circleCategory;
+ circleShapeDef.filter.maskBits = k_circleMask;
+
+ b2BodyDef circleBodyDef;
+ circleBodyDef.type = b2_dynamicBody;
+ circleBodyDef.position.Set(5.0f, 2.0f);
+
+ b2Body* body5 = m_world->CreateBody(&circleBodyDef);
+ body5->CreateFixture(&circleShapeDef);
+
+ // Large circle
+ circle.m_radius *= 2.0f;
+ circleShapeDef.filter.groupIndex = k_largeGroup;
+ circleBodyDef.position.Set(5.0f, 6.0f);
+
+ b2Body* body6 = m_world->CreateBody(&circleBodyDef);
+ body6->CreateFixture(&circleShapeDef);
+ }
+
+ static Test* Create()
+ {
+ return new CollisionFiltering;
+ }
+};
+
+static int testIndex = RegisterTest("Examples", "Collision Filtering", CollisionFiltering::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/collision_processing.cpp b/Client/ThirdParty/Box2D/testbed/tests/collision_processing.cpp
new file mode 100644
index 0000000..1c684bd
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/collision_processing.cpp
@@ -0,0 +1,191 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+#include <algorithm>
+
+// This test shows collision processing and tests
+// deferred body destruction.
+class CollisionProcessing : public Test
+{
+public:
+ CollisionProcessing()
+ {
+ // Ground body
+ {
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f));
+
+ b2FixtureDef sd;
+ sd.shape = &shape;;
+
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&sd);
+ }
+
+ float xLo = -5.0f, xHi = 5.0f;
+ float yLo = 2.0f, yHi = 35.0f;
+
+ // Small triangle
+ b2Vec2 vertices[3];
+ vertices[0].Set(-1.0f, 0.0f);
+ vertices[1].Set(1.0f, 0.0f);
+ vertices[2].Set(0.0f, 2.0f);
+
+ b2PolygonShape polygon;
+ polygon.Set(vertices, 3);
+
+ b2FixtureDef triangleShapeDef;
+ triangleShapeDef.shape = &polygon;
+ triangleShapeDef.density = 1.0f;
+
+ b2BodyDef triangleBodyDef;
+ triangleBodyDef.type = b2_dynamicBody;
+ triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
+
+ b2Body* body1 = m_world->CreateBody(&triangleBodyDef);
+ body1->CreateFixture(&triangleShapeDef);
+
+ // Large triangle (recycle definitions)
+ vertices[0] *= 2.0f;
+ vertices[1] *= 2.0f;
+ vertices[2] *= 2.0f;
+ polygon.Set(vertices, 3);
+
+ triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
+
+ b2Body* body2 = m_world->CreateBody(&triangleBodyDef);
+ body2->CreateFixture(&triangleShapeDef);
+
+ // Small box
+ polygon.SetAsBox(1.0f, 0.5f);
+
+ b2FixtureDef boxShapeDef;
+ boxShapeDef.shape = &polygon;
+ boxShapeDef.density = 1.0f;
+
+ b2BodyDef boxBodyDef;
+ boxBodyDef.type = b2_dynamicBody;
+ boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
+
+ b2Body* body3 = m_world->CreateBody(&boxBodyDef);
+ body3->CreateFixture(&boxShapeDef);
+
+ // Large box (recycle definitions)
+ polygon.SetAsBox(2.0f, 1.0f);
+ boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
+
+ b2Body* body4 = m_world->CreateBody(&boxBodyDef);
+ body4->CreateFixture(&boxShapeDef);
+
+ // Small circle
+ b2CircleShape circle;
+ circle.m_radius = 1.0f;
+
+ b2FixtureDef circleShapeDef;
+ circleShapeDef.shape = &circle;
+ circleShapeDef.density = 1.0f;
+
+ b2BodyDef circleBodyDef;
+ circleBodyDef.type = b2_dynamicBody;
+ circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
+
+ b2Body* body5 = m_world->CreateBody(&circleBodyDef);
+ body5->CreateFixture(&circleShapeDef);
+
+ // Large circle
+ circle.m_radius *= 2.0f;
+ circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
+
+ b2Body* body6 = m_world->CreateBody(&circleBodyDef);
+ body6->CreateFixture(&circleShapeDef);
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ // We are going to destroy some bodies according to contact
+ // points. We must buffer the bodies that should be destroyed
+ // because they may belong to multiple contact points.
+ const int32 k_maxNuke = 6;
+ b2Body* nuke[k_maxNuke];
+ int32 nukeCount = 0;
+
+ // Traverse the contact results. Destroy bodies that
+ // are touching heavier bodies.
+ for (int32 i = 0; i < m_pointCount; ++i)
+ {
+ ContactPoint* point = m_points + i;
+
+ b2Body* body1 = point->fixtureA->GetBody();
+ b2Body* body2 = point->fixtureB->GetBody();
+ float mass1 = body1->GetMass();
+ float mass2 = body2->GetMass();
+
+ if (mass1 > 0.0f && mass2 > 0.0f)
+ {
+ if (mass2 > mass1)
+ {
+ nuke[nukeCount++] = body1;
+ }
+ else
+ {
+ nuke[nukeCount++] = body2;
+ }
+
+ if (nukeCount == k_maxNuke)
+ {
+ break;
+ }
+ }
+ }
+
+ // Sort the nuke array to group duplicates.
+ std::sort(nuke, nuke + nukeCount);
+
+ // Destroy the bodies, skipping duplicates.
+ int32 i = 0;
+ while (i < nukeCount)
+ {
+ b2Body* b = nuke[i++];
+ while (i < nukeCount && nuke[i] == b)
+ {
+ ++i;
+ }
+
+ if (b != m_bomb)
+ {
+ m_world->DestroyBody(b);
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new CollisionProcessing;
+ }
+};
+
+static int testIndex = RegisterTest("Examples", "Collision Processing", CollisionProcessing::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/compound_shapes.cpp b/Client/ThirdParty/Box2D/testbed/tests/compound_shapes.cpp
new file mode 100644
index 0000000..5862e8e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/compound_shapes.cpp
@@ -0,0 +1,227 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "imgui/imgui.h"
+
+class CompoundShapes : public Test
+{
+public:
+ CompoundShapes()
+ {
+ {
+ b2BodyDef bd;
+ bd.position.Set(0.0f, 0.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f));
+
+ body->CreateFixture(&shape, 0.0f);
+ }
+
+ // Table 1
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-15.0f, 1.0f);
+ m_table1 = m_world->CreateBody(&bd);
+
+ b2PolygonShape top;
+ top.SetAsBox(3.0f, 0.5f, b2Vec2(0.0f, 3.5f), 0.0f);
+
+ b2PolygonShape leftLeg;
+ leftLeg.SetAsBox(0.5f, 1.5f, b2Vec2(-2.5f, 1.5f), 0.0f);
+
+ b2PolygonShape rightLeg;
+ rightLeg.SetAsBox(0.5f, 1.5f, b2Vec2(2.5f, 1.5f), 0.0f);
+
+ m_table1->CreateFixture(&top, 2.0f);
+ m_table1->CreateFixture(&leftLeg, 2.0f);
+ m_table1->CreateFixture(&rightLeg, 2.0f);
+ }
+
+ // Table 2
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-5.0f, 1.0f);
+ m_table2 = m_world->CreateBody(&bd);
+
+ b2PolygonShape top;
+ top.SetAsBox(3.0f, 0.5f, b2Vec2(0.0f, 3.5f), 0.0f);
+
+ b2PolygonShape leftLeg;
+ leftLeg.SetAsBox(0.5f, 2.0f, b2Vec2(-2.5f, 2.0f), 0.0f);
+
+ b2PolygonShape rightLeg;
+ rightLeg.SetAsBox(0.5f, 2.0f, b2Vec2(2.5f, 2.0f), 0.0f);
+
+ m_table2->CreateFixture(&top, 2.0f);
+ m_table2->CreateFixture(&leftLeg, 2.0f);
+ m_table2->CreateFixture(&rightLeg, 2.0f);
+ }
+
+ // Spaceship 1
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(5.0f, 1.0f);
+ m_ship1 = m_world->CreateBody(&bd);
+
+ b2Vec2 vertices[3];
+
+ b2PolygonShape left;
+ vertices[0].Set(-2.0f, 0.0f);
+ vertices[1].Set(0.0f, 4.0f / 3.0f);
+ vertices[2].Set(0.0f, 4.0f);
+ left.Set(vertices, 3);
+
+ b2PolygonShape right;
+ vertices[0].Set(2.0f, 0.0f);
+ vertices[1].Set(0.0f, 4.0f / 3.0f);
+ vertices[2].Set(0.0f, 4.0f);
+ right.Set(vertices, 3);
+
+ m_ship1->CreateFixture(&left, 2.0f);
+ m_ship1->CreateFixture(&right, 2.0f);
+ }
+
+ // Spaceship 2
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(15.0f, 1.0f);
+ m_ship2 = m_world->CreateBody(&bd);
+
+ b2Vec2 vertices[3];
+
+ b2PolygonShape left;
+ vertices[0].Set(-2.0f, 0.0f);
+ vertices[1].Set(1.0f, 2.0f);
+ vertices[2].Set(0.0f, 4.0f);
+ left.Set(vertices, 3);
+
+ b2PolygonShape right;
+ vertices[0].Set(2.0f, 0.0f);
+ vertices[1].Set(-1.0f, 2.0f);
+ vertices[2].Set(0.0f, 4.0f);
+ right.Set(vertices, 3);
+
+ m_ship2->CreateFixture(&left, 2.0f);
+ m_ship2->CreateFixture(&right, 2.0f);
+ }
+ }
+
+ void Spawn()
+ {
+ // Table 1 obstruction
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = m_table1->GetPosition();
+ bd.angle = m_table1->GetAngle();
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape box;
+ box.SetAsBox(4.0f, 0.1f, b2Vec2(0.0f, 3.0f), 0.0f);
+
+ body->CreateFixture(&box, 2.0f);
+ }
+
+ // Table 2 obstruction
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = m_table2->GetPosition();
+ bd.angle = m_table2->GetAngle();
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape box;
+ box.SetAsBox(4.0f, 0.1f, b2Vec2(0.0f, 3.0f), 0.0f);
+
+ body->CreateFixture(&box, 2.0f);
+ }
+
+ // Ship 1 obstruction
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = m_ship1->GetPosition();
+ bd.angle = m_ship1->GetAngle();
+ bd.gravityScale = 0.0f;
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2CircleShape circle;
+ circle.m_radius = 0.5f;
+ circle.m_p.Set(0.0f, 2.0f);
+
+ body->CreateFixture(&circle, 2.0f);
+ }
+
+ // Ship 2 obstruction
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = m_ship2->GetPosition();
+ bd.angle = m_ship2->GetAngle();
+ bd.gravityScale = 0.0f;
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2CircleShape circle;
+ circle.m_radius = 0.5f;
+ circle.m_p.Set(0.0f, 2.0f);
+
+ body->CreateFixture(&circle, 2.0f);
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f));
+ ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::Button("Spawn"))
+ {
+ Spawn();
+ }
+
+ ImGui::End();
+ }
+
+ static Test* Create()
+ {
+ return new CompoundShapes;
+ }
+
+ b2Body* m_table1;
+ b2Body* m_table2;
+ b2Body* m_ship1;
+ b2Body* m_ship2;
+};
+
+static int testIndex = RegisterTest("Examples", "Compound Shapes", CompoundShapes::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/confined.cpp b/Client/ThirdParty/Box2D/testbed/tests/confined.cpp
new file mode 100644
index 0000000..3ac9bd6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/confined.cpp
@@ -0,0 +1,170 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Confined : public Test
+{
+public:
+
+ enum
+ {
+ e_columnCount = 0,
+ e_rowCount = 0
+ };
+
+ Confined()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+
+ // Floor
+ shape.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+
+ // Left wall
+ shape.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(-10.0f, 20.0f));
+ ground->CreateFixture(&shape, 0.0f);
+
+ // Right wall
+ shape.SetTwoSided(b2Vec2(10.0f, 0.0f), b2Vec2(10.0f, 20.0f));
+ ground->CreateFixture(&shape, 0.0f);
+
+ // Roof
+ shape.SetTwoSided(b2Vec2(-10.0f, 20.0f), b2Vec2(10.0f, 20.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ float radius = 0.5f;
+ b2CircleShape shape;
+ shape.m_p.SetZero();
+ shape.m_radius = radius;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+ fd.friction = 0.1f;
+
+ for (int32 j = 0; j < e_columnCount; ++j)
+ {
+ for (int i = 0; i < e_rowCount; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-10.0f + (2.1f * j + 1.0f + 0.01f * i) * radius, (2.0f * i + 1.0f) * radius);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ body->CreateFixture(&fd);
+ }
+ }
+
+ m_world->SetGravity(b2Vec2(0.0f, 0.0f));
+ }
+
+ void CreateCircle()
+ {
+ float radius = 2.0f;
+ b2CircleShape shape;
+ shape.m_p.SetZero();
+ shape.m_radius = radius;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+ fd.friction = 0.0f;
+
+ b2Vec2 p(RandomFloat(), 3.0f + RandomFloat());
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = p;
+ //bd.allowSleep = false;
+ b2Body* body = m_world->CreateBody(&bd);
+
+ body->CreateFixture(&fd);
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_C:
+ CreateCircle();
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ bool sleeping = true;
+ for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
+ {
+ if (b->GetType() != b2_dynamicBody)
+ {
+ continue;
+ }
+
+ if (b->IsAwake())
+ {
+ sleeping = false;
+ }
+ }
+
+ if (m_stepCount == 180)
+ {
+ m_stepCount += 0;
+ }
+
+ //if (sleeping)
+ //{
+ // CreateCircle();
+ //}
+
+ Test::Step(settings);
+
+ for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
+ {
+ if (b->GetType() != b2_dynamicBody)
+ {
+ continue;
+ }
+
+ b2Vec2 p = b->GetPosition();
+ if (p.x <= -10.0f || 10.0f <= p.x || p.y <= 0.0f || 20.0f <= p.y)
+ {
+ p.x += 0.0f;
+ }
+ }
+
+ g_debugDraw.DrawString(5, m_textLine, "Press 'c' to create a circle.");
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new Confined;
+ }
+};
+
+static int testIndex = RegisterTest("Solver", "Confined", Confined::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/continuous_test.cpp b/Client/ThirdParty/Box2D/testbed/tests/continuous_test.cpp
new file mode 100644
index 0000000..1166c71
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/continuous_test.cpp
@@ -0,0 +1,160 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class ContinuousTest : public Test
+{
+public:
+
+ ContinuousTest()
+ {
+ {
+ b2BodyDef bd;
+ bd.position.Set(0.0f, 0.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2EdgeShape edge;
+
+ edge.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f));
+ body->CreateFixture(&edge, 0.0f);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f);
+ body->CreateFixture(&shape, 0.0f);
+ }
+
+#if 1
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 20.0f);
+ //bd.angle = 0.1f;
+
+ b2PolygonShape shape;
+ shape.SetAsBox(2.0f, 0.1f);
+
+ m_body = m_world->CreateBody(&bd);
+ m_body->CreateFixture(&shape, 1.0f);
+
+ m_angularVelocity = RandomFloat(-50.0f, 50.0f);
+ //m_angularVelocity = 46.661274f;
+ m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f));
+ m_body->SetAngularVelocity(m_angularVelocity);
+ }
+#else
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 2.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_p.SetZero();
+ shape.m_radius = 0.5f;
+ body->CreateFixture(&shape, 1.0f);
+
+ bd.bullet = true;
+ bd.position.Set(0.0f, 10.0f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 1.0f);
+ body->SetLinearVelocity(b2Vec2(0.0f, -100.0f));
+ }
+#endif
+
+ extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
+ extern B2_API int32 b2_toiCalls, b2_toiIters;
+ extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters;
+ extern B2_API float b2_toiTime, b2_toiMaxTime;
+
+ b2_gjkCalls = 0; b2_gjkIters = 0; b2_gjkMaxIters = 0;
+ b2_toiCalls = 0; b2_toiIters = 0;
+ b2_toiRootIters = 0; b2_toiMaxRootIters = 0;
+ b2_toiTime = 0.0f; b2_toiMaxTime = 0.0f;
+ }
+
+ void Launch()
+ {
+ extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
+ extern B2_API int32 b2_toiCalls, b2_toiIters;
+ extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters;
+ extern B2_API float b2_toiTime, b2_toiMaxTime;
+
+ b2_gjkCalls = 0; b2_gjkIters = 0; b2_gjkMaxIters = 0;
+ b2_toiCalls = 0; b2_toiIters = 0;
+ b2_toiRootIters = 0; b2_toiMaxRootIters = 0;
+ b2_toiTime = 0.0f; b2_toiMaxTime = 0.0f;
+
+ m_body->SetTransform(b2Vec2(0.0f, 20.0f), 0.0f);
+ m_angularVelocity = RandomFloat(-50.0f, 50.0f);
+ m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f));
+ m_body->SetAngularVelocity(m_angularVelocity);
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
+
+ if (b2_gjkCalls > 0)
+ {
+ g_debugDraw.DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d",
+ b2_gjkCalls, b2_gjkIters / float(b2_gjkCalls), b2_gjkMaxIters);
+ m_textLine += m_textIncrement;
+ }
+
+ extern B2_API int32 b2_toiCalls, b2_toiIters;
+ extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters;
+ extern B2_API float b2_toiTime, b2_toiMaxTime;
+
+ if (b2_toiCalls > 0)
+ {
+ g_debugDraw.DrawString(5, m_textLine, "toi calls = %d, ave [max] toi iters = %3.1f [%d]",
+ b2_toiCalls, b2_toiIters / float(b2_toiCalls), b2_toiMaxRootIters);
+ m_textLine += m_textIncrement;
+
+ g_debugDraw.DrawString(5, m_textLine, "ave [max] toi root iters = %3.1f [%d]",
+ b2_toiRootIters / float(b2_toiCalls), b2_toiMaxRootIters);
+ m_textLine += m_textIncrement;
+
+ g_debugDraw.DrawString(5, m_textLine, "ave [max] toi time = %.1f [%.1f] (microseconds)",
+ 1000.0f * b2_toiTime / float(b2_toiCalls), 1000.0f * b2_toiMaxTime);
+ m_textLine += m_textIncrement;
+ }
+
+ if (m_stepCount % 60 == 0)
+ {
+ //Launch();
+ }
+ }
+
+ static Test* Create()
+ {
+ return new ContinuousTest;
+ }
+
+ b2Body* m_body;
+ float m_angularVelocity;
+};
+
+static int testIndex = RegisterTest("Continuous", "Continuous Test", ContinuousTest::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/convex_hull.cpp b/Client/ThirdParty/Box2D/testbed/tests/convex_hull.cpp
new file mode 100644
index 0000000..ab56e91
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/convex_hull.cpp
@@ -0,0 +1,112 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class ConvexHull : public Test
+{
+public:
+ enum
+ {
+ e_count = b2_maxPolygonVertices
+ };
+
+ ConvexHull()
+ {
+ Generate();
+ m_auto = false;
+ }
+
+ void Generate()
+ {
+ b2Vec2 lowerBound(-8.0f, -8.0f);
+ b2Vec2 upperBound(8.0f, 8.0f);
+
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ float x = 10.0f * RandomFloat();
+ float y = 10.0f * RandomFloat();
+
+ // Clamp onto a square to help create collinearities.
+ // This will stress the convex hull algorithm.
+ b2Vec2 v(x, y);
+ v = b2Clamp(v, lowerBound, upperBound);
+ m_points[i] = v;
+ }
+
+ m_count = e_count;
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_auto = !m_auto;
+ break;
+
+ case GLFW_KEY_G:
+ Generate();
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ b2PolygonShape shape;
+ shape.Set(m_points, m_count);
+
+ g_debugDraw.DrawString(5, m_textLine, "Press g to generate a new random convex hull");
+ m_textLine += m_textIncrement;
+
+ g_debugDraw.DrawPolygon(shape.m_vertices, shape.m_count, b2Color(0.9f, 0.9f, 0.9f));
+
+ for (int32 i = 0; i < m_count; ++i)
+ {
+ g_debugDraw.DrawPoint(m_points[i], 3.0f, b2Color(0.3f, 0.9f, 0.3f));
+ g_debugDraw.DrawString(m_points[i] + b2Vec2(0.05f, 0.05f), "%d", i);
+ }
+
+ if (shape.Validate() == false)
+ {
+ m_textLine += 0;
+ }
+
+ if (m_auto)
+ {
+ Generate();
+ }
+ }
+
+ static Test* Create()
+ {
+ return new ConvexHull;
+ }
+
+ b2Vec2 m_points[b2_maxPolygonVertices];
+ int32 m_count;
+ bool m_auto;
+};
+
+static int testIndex = RegisterTest("Geometry", "Convex Hull", ConvexHull::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/conveyor_belt.cpp b/Client/ThirdParty/Box2D/testbed/tests/conveyor_belt.cpp
new file mode 100644
index 0000000..41d4f2c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/conveyor_belt.cpp
@@ -0,0 +1,101 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class ConveyorBelt : public Test
+{
+public:
+
+ ConveyorBelt()
+ {
+ // Ground
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Platform
+ {
+ b2BodyDef bd;
+ bd.position.Set(-5.0f, 5.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(10.0f, 0.5f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.friction = 0.8f;
+ m_platform = body->CreateFixture(&fd);
+ }
+
+ // Boxes
+ for (int32 i = 0; i < 5; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-10.0f + 2.0f * i, 7.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+ body->CreateFixture(&shape, 20.0f);
+ }
+ }
+
+ void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override
+ {
+ Test::PreSolve(contact, oldManifold);
+
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+
+ if (fixtureA == m_platform)
+ {
+ contact->SetTangentSpeed(5.0f);
+ }
+
+ if (fixtureB == m_platform)
+ {
+ contact->SetTangentSpeed(-5.0f);
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new ConveyorBelt;
+ }
+
+ b2Fixture* m_platform;
+};
+
+static int testIndex = RegisterTest("Examples", "Conveyor Belt", ConveyorBelt::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/distance_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/distance_joint.cpp
new file mode 100644
index 0000000..389f403
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/distance_joint.cpp
@@ -0,0 +1,123 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "imgui/imgui.h"
+
+// This tests distance joints, body destruction, and joint destruction.
+class DistanceJoint : public Test
+{
+public:
+ DistanceJoint()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.angularDamping = 0.1f;
+
+ bd.position.Set(0.0f, 5.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+ body->CreateFixture(&shape, 5.0f);
+
+ m_hertz = 1.0f;
+ m_dampingRatio = 0.7f;
+
+ b2DistanceJointDef jd;
+ jd.Initialize(ground, body, b2Vec2(0.0f, 15.0f), bd.position);
+ jd.collideConnected = true;
+ m_length = jd.length;
+ m_minLength = m_length;
+ m_maxLength = m_length;
+ b2LinearStiffness(jd.stiffness, jd.damping, m_hertz, m_dampingRatio, jd.bodyA, jd.bodyB);
+ m_joint = (b2DistanceJoint*)m_world->CreateJoint(&jd);
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(260.0f, 150.0f));
+ ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::SliderFloat("Length", &m_length, 0.0f, 20.0f, "%.0f"))
+ {
+ m_length = m_joint->SetLength(m_length);
+ }
+
+ if (ImGui::SliderFloat("Min Length", &m_minLength, 0.0f, 20.0f, "%.0f"))
+ {
+ m_minLength = m_joint->SetMinLength(m_minLength);
+ }
+
+ if (ImGui::SliderFloat("Max Length", &m_maxLength, 0.0f, 20.0f, "%.0f"))
+ {
+ m_maxLength = m_joint->SetMaxLength(m_maxLength);
+ }
+
+ if (ImGui::SliderFloat("Hertz", &m_hertz, 0.0f, 10.0f, "%.1f"))
+ {
+ float stiffness;
+ float damping;
+ b2LinearStiffness(stiffness, damping, m_hertz, m_dampingRatio, m_joint->GetBodyA(), m_joint->GetBodyB());
+ m_joint->SetStiffness(stiffness);
+ m_joint->SetDamping(damping);
+ }
+
+ if (ImGui::SliderFloat("Damping Ratio", &m_dampingRatio, 0.0f, 2.0f, "%.1f"))
+ {
+ float stiffness;
+ float damping;
+ b2LinearStiffness(stiffness, damping, m_hertz, m_dampingRatio, m_joint->GetBodyA(), m_joint->GetBodyB());
+ m_joint->SetStiffness(stiffness);
+ m_joint->SetDamping(damping);
+ }
+
+ ImGui::End();
+ }
+
+ static Test* Create()
+ {
+ return new DistanceJoint;
+ }
+
+ b2DistanceJoint* m_joint;
+ float m_length;
+ float m_minLength;
+ float m_maxLength;
+ float m_hertz;
+ float m_dampingRatio;
+};
+
+static int testIndex = RegisterTest("Joints", "Distance Joint", DistanceJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/distance_test.cpp b/Client/ThirdParty/Box2D/testbed/tests/distance_test.cpp
new file mode 100644
index 0000000..90496ad
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/distance_test.cpp
@@ -0,0 +1,139 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "box2d/b2_distance.h"
+
+class DistanceTest : public Test
+{
+public:
+ DistanceTest()
+ {
+ {
+ m_transformA.SetIdentity();
+ m_transformA.p.Set(0.0f, -0.2f);
+ m_polygonA.SetAsBox(10.0f, 0.2f);
+ }
+
+ {
+ m_positionB.Set(12.017401f, 0.13678508f);
+ m_angleB = -0.0109265f;
+ m_transformB.Set(m_positionB, m_angleB);
+
+ m_polygonB.SetAsBox(2.0f, 0.1f);
+ }
+ }
+
+ static Test* Create()
+ {
+ return new DistanceTest;
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ b2DistanceInput input;
+ input.proxyA.Set(&m_polygonA, 0);
+ input.proxyB.Set(&m_polygonB, 0);
+ input.transformA = m_transformA;
+ input.transformB = m_transformB;
+ input.useRadii = true;
+ b2SimplexCache cache;
+ cache.count = 0;
+ b2DistanceOutput output;
+ b2Distance(&output, &cache, &input);
+
+ g_debugDraw.DrawString(5, m_textLine, "distance = %g", output.distance);
+ m_textLine += m_textIncrement;
+
+ g_debugDraw.DrawString(5, m_textLine, "iterations = %d", output.iterations);
+ m_textLine += m_textIncrement;
+
+ {
+ b2Color color(0.9f, 0.9f, 0.9f);
+ b2Vec2 v[b2_maxPolygonVertices];
+ for (int32 i = 0; i < m_polygonA.m_count; ++i)
+ {
+ v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(v, m_polygonA.m_count, color);
+
+ for (int32 i = 0; i < m_polygonB.m_count; ++i)
+ {
+ v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(v, m_polygonB.m_count, color);
+ }
+
+ b2Vec2 x1 = output.pointA;
+ b2Vec2 x2 = output.pointB;
+
+ b2Color c1(1.0f, 0.0f, 0.0f);
+ g_debugDraw.DrawPoint(x1, 4.0f, c1);
+
+ b2Color c2(1.0f, 1.0f, 0.0f);
+ g_debugDraw.DrawPoint(x2, 4.0f, c2);
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_positionB.x -= 0.1f;
+ break;
+
+ case GLFW_KEY_D:
+ m_positionB.x += 0.1f;
+ break;
+
+ case GLFW_KEY_S:
+ m_positionB.y -= 0.1f;
+ break;
+
+ case GLFW_KEY_W:
+ m_positionB.y += 0.1f;
+ break;
+
+ case GLFW_KEY_Q:
+ m_angleB += 0.1f * b2_pi;
+ break;
+
+ case GLFW_KEY_E:
+ m_angleB -= 0.1f * b2_pi;
+ break;
+ }
+
+ m_transformB.Set(m_positionB, m_angleB);
+ }
+
+ b2Vec2 m_positionB;
+ float m_angleB;
+
+ b2Transform m_transformA;
+ b2Transform m_transformB;
+ b2PolygonShape m_polygonA;
+ b2PolygonShape m_polygonB;
+};
+
+static int testIndex = RegisterTest("Geometry", "Distance Test", DistanceTest::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/dominos.cpp b/Client/ThirdParty/Box2D/testbed/tests/dominos.cpp
new file mode 100644
index 0000000..739876b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/dominos.cpp
@@ -0,0 +1,220 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Dominos : public Test
+{
+public:
+
+ Dominos()
+ {
+ b2Body* b1;
+ {
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+
+ b2BodyDef bd;
+ b1 = m_world->CreateBody(&bd);
+ b1->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(6.0f, 0.25f);
+
+ b2BodyDef bd;
+ bd.position.Set(-1.5f, 10.0f);
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.1f, 1.0f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ fd.friction = 0.1f;
+
+ for (int i = 0; i < 10; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-6.0f + 1.0f * i, 11.25f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&fd);
+ }
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(7.0f, 0.25f, b2Vec2_zero, 0.3f);
+
+ b2BodyDef bd;
+ bd.position.Set(1.0f, 6.0f);
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ b2Body* b2;
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f, 1.5f);
+
+ b2BodyDef bd;
+ bd.position.Set(-7.0f, 4.0f);
+ b2 = m_world->CreateBody(&bd);
+ b2->CreateFixture(&shape, 0.0f);
+ }
+
+ b2Body* b3;
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(6.0f, 0.125f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-0.9f, 1.0f);
+ bd.angle = -0.15f;
+
+ b3 = m_world->CreateBody(&bd);
+ b3->CreateFixture(&shape, 10.0f);
+ }
+
+ b2RevoluteJointDef jd;
+ b2Vec2 anchor;
+
+ anchor.Set(-2.0f, 1.0f);
+ jd.Initialize(b1, b3, anchor);
+ jd.collideConnected = true;
+ m_world->CreateJoint(&jd);
+
+ b2Body* b4;
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f, 0.25f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-10.0f, 15.0f);
+ b4 = m_world->CreateBody(&bd);
+ b4->CreateFixture(&shape, 10.0f);
+ }
+
+ anchor.Set(-7.0f, 15.0f);
+ jd.Initialize(b2, b4, anchor);
+ m_world->CreateJoint(&jd);
+
+ b2Body* b5;
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(6.5f, 3.0f);
+ b5 = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ b2FixtureDef fd;
+
+ fd.shape = &shape;
+ fd.density = 10.0f;
+ fd.friction = 0.1f;
+
+ shape.SetAsBox(1.0f, 0.1f, b2Vec2(0.0f, -0.9f), 0.0f);
+ b5->CreateFixture(&fd);
+
+ shape.SetAsBox(0.1f, 1.0f, b2Vec2(-0.9f, 0.0f), 0.0f);
+ b5->CreateFixture(&fd);
+
+ shape.SetAsBox(0.1f, 1.0f, b2Vec2(0.9f, 0.0f), 0.0f);
+ b5->CreateFixture(&fd);
+ }
+
+ anchor.Set(6.0f, 2.0f);
+ jd.Initialize(b1, b5, anchor);
+ m_world->CreateJoint(&jd);
+
+ b2Body* b6;
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(1.0f, 0.1f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(6.5f, 4.1f);
+ b6 = m_world->CreateBody(&bd);
+ b6->CreateFixture(&shape, 30.0f);
+ }
+
+ anchor.Set(7.5f, 4.0f);
+ jd.Initialize(b5, b6, anchor);
+ m_world->CreateJoint(&jd);
+
+ b2Body* b7;
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.1f, 1.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(7.4f, 1.0f);
+
+ b7 = m_world->CreateBody(&bd);
+ b7->CreateFixture(&shape, 10.0f);
+ }
+
+ b2DistanceJointDef djd;
+ djd.bodyA = b3;
+ djd.bodyB = b7;
+ djd.localAnchorA.Set(6.0f, 0.0f);
+ djd.localAnchorB.Set(0.0f, -1.0f);
+ b2Vec2 d = djd.bodyB->GetWorldPoint(djd.localAnchorB) - djd.bodyA->GetWorldPoint(djd.localAnchorA);
+ djd.length = d.Length();
+
+ b2LinearStiffness(djd.stiffness, djd.damping, 1.0f, 1.0f, djd.bodyA, djd.bodyB);
+ m_world->CreateJoint(&djd);
+
+ {
+ float radius = 0.2f;
+
+ b2CircleShape shape;
+ shape.m_radius = radius;
+
+ for (int32 i = 0; i < 4; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(5.9f + 2.0f * radius * i, 2.4f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 10.0f);
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Dominos;
+ }
+};
+
+static int testIndex = RegisterTest("Examples", "Dominos", Dominos::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/dump_loader.cpp b/Client/ThirdParty/Box2D/testbed/tests/dump_loader.cpp
new file mode 100644
index 0000000..882f59b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/dump_loader.cpp
@@ -0,0 +1,88 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// This test holds worlds dumped using b2World::Dump.
+class DumpLoader : public Test
+{
+public:
+
+ DumpLoader()
+ {
+ b2ChainShape chainShape;
+ b2Vec2 vertices[] = {b2Vec2(-5,0), b2Vec2(5,0), b2Vec2(5,5), b2Vec2(4,1), b2Vec2(-4,1), b2Vec2(-5,5)};
+ chainShape.CreateLoop(vertices, 6);
+
+ b2FixtureDef groundFixtureDef;
+ groundFixtureDef.density = 0;
+ groundFixtureDef.shape = &chainShape;
+
+ b2BodyDef groundBodyDef;
+ groundBodyDef.type = b2_staticBody;
+
+ b2Body *groundBody = m_world->CreateBody(&groundBodyDef);
+ b2Fixture *groundBodyFixture = groundBody->CreateFixture(&groundFixtureDef);
+
+ b2CircleShape ballShape;
+ ballShape.m_radius = 1;
+
+ b2FixtureDef ballFixtureDef;
+ ballFixtureDef.restitution = 0.75f;
+ ballFixtureDef.density = 1;
+ ballFixtureDef.shape = &ballShape;
+
+ b2BodyDef ballBodyDef;
+ ballBodyDef.type = b2BodyType::b2_dynamicBody;
+ ballBodyDef.position = b2Vec2(0, 10);
+ // ballBodyDef.angularDamping = 0.2f;
+
+ m_ball = m_world->CreateBody(&ballBodyDef);
+ b2Fixture *ballFixture = m_ball->CreateFixture(&ballFixtureDef);
+ m_ball->ApplyForceToCenter(b2Vec2(-1000, -400), true);
+ }
+
+ void Step(Settings& settings) override
+ {
+ b2Vec2 v = m_ball->GetLinearVelocity();
+ float omega = m_ball->GetAngularVelocity();
+
+ b2MassData massData;
+ m_ball->GetMassData(&massData);
+
+ float ke = 0.5f * massData.mass * b2Dot(v, v) + 0.5f * massData.I * omega * omega;
+
+ g_debugDraw.DrawString(5, m_textLine, "kinetic energy = %.6f", ke);
+ m_textLine += m_textIncrement;
+
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new DumpLoader;
+ }
+
+ b2Body* m_ball;
+};
+
+static int testIndex = RegisterTest("Bugs", "Dump Loader", DumpLoader::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/dynamic_tree.cpp b/Client/ThirdParty/Box2D/testbed/tests/dynamic_tree.cpp
new file mode 100644
index 0000000..7772d5c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/dynamic_tree.cpp
@@ -0,0 +1,360 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class DynamicTree : public Test
+{
+public:
+
+ enum
+ {
+ e_actorCount = 128
+ };
+
+ DynamicTree()
+ {
+ m_worldExtent = 15.0f;
+ m_proxyExtent = 0.5f;
+
+ srand(888);
+
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ Actor* actor = m_actors + i;
+ GetRandomAABB(&actor->aabb);
+ actor->proxyId = m_tree.CreateProxy(actor->aabb, actor);
+ }
+
+ m_stepCount = 0;
+
+ float h = m_worldExtent;
+ m_queryAABB.lowerBound.Set(-3.0f, -4.0f + h);
+ m_queryAABB.upperBound.Set(5.0f, 6.0f + h);
+
+ m_rayCastInput.p1.Set(-5.0, 5.0f + h);
+ m_rayCastInput.p2.Set(7.0f, -4.0f + h);
+ //m_rayCastInput.p1.Set(0.0f, 2.0f + h);
+ //m_rayCastInput.p2.Set(0.0f, -2.0f + h);
+ m_rayCastInput.maxFraction = 1.0f;
+
+ m_automated = false;
+ }
+
+ static Test* Create()
+ {
+ return new DynamicTree;
+ }
+
+ void Step(Settings& settings) override
+ {
+ B2_NOT_USED(settings);
+
+ m_rayActor = NULL;
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ m_actors[i].fraction = 1.0f;
+ m_actors[i].overlap = false;
+ }
+
+ if (m_automated == true)
+ {
+ int32 actionCount = b2Max(1, e_actorCount >> 2);
+
+ for (int32 i = 0; i < actionCount; ++i)
+ {
+ Action();
+ }
+ }
+
+ Query();
+ RayCast();
+
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ Actor* actor = m_actors + i;
+ if (actor->proxyId == b2_nullNode)
+ continue;
+
+ b2Color c(0.9f, 0.9f, 0.9f);
+ if (actor == m_rayActor && actor->overlap)
+ {
+ c.Set(0.9f, 0.6f, 0.6f);
+ }
+ else if (actor == m_rayActor)
+ {
+ c.Set(0.6f, 0.9f, 0.6f);
+ }
+ else if (actor->overlap)
+ {
+ c.Set(0.6f, 0.6f, 0.9f);
+ }
+
+ g_debugDraw.DrawAABB(&actor->aabb, c);
+ }
+
+ b2Color c(0.7f, 0.7f, 0.7f);
+ g_debugDraw.DrawAABB(&m_queryAABB, c);
+
+ g_debugDraw.DrawSegment(m_rayCastInput.p1, m_rayCastInput.p2, c);
+
+ b2Color c1(0.2f, 0.9f, 0.2f);
+ b2Color c2(0.9f, 0.2f, 0.2f);
+ g_debugDraw.DrawPoint(m_rayCastInput.p1, 6.0f, c1);
+ g_debugDraw.DrawPoint(m_rayCastInput.p2, 6.0f, c2);
+
+ if (m_rayActor)
+ {
+ b2Color cr(0.2f, 0.2f, 0.9f);
+ b2Vec2 p = m_rayCastInput.p1 + m_rayActor->fraction * (m_rayCastInput.p2 - m_rayCastInput.p1);
+ g_debugDraw.DrawPoint(p, 6.0f, cr);
+ }
+
+ {
+ int32 height = m_tree.GetHeight();
+ g_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d", height);
+ m_textLine += m_textIncrement;
+ }
+
+ ++m_stepCount;
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_automated = !m_automated;
+ break;
+
+ case GLFW_KEY_C:
+ CreateProxy();
+ break;
+
+ case GLFW_KEY_D:
+ DestroyProxy();
+ break;
+
+ case GLFW_KEY_M:
+ MoveProxy();
+ break;
+ }
+ }
+
+ bool QueryCallback(int32 proxyId)
+ {
+ Actor* actor = (Actor*)m_tree.GetUserData(proxyId);
+ actor->overlap = b2TestOverlap(m_queryAABB, actor->aabb);
+ return true;
+ }
+
+ float RayCastCallback(const b2RayCastInput& input, int32 proxyId)
+ {
+ Actor* actor = (Actor*)m_tree.GetUserData(proxyId);
+
+ b2RayCastOutput output;
+ bool hit = actor->aabb.RayCast(&output, input);
+
+ if (hit)
+ {
+ m_rayCastOutput = output;
+ m_rayActor = actor;
+ m_rayActor->fraction = output.fraction;
+ return output.fraction;
+ }
+
+ return input.maxFraction;
+ }
+
+private:
+
+ struct Actor
+ {
+ b2AABB aabb;
+ float fraction;
+ bool overlap;
+ int32 proxyId;
+ };
+
+ void GetRandomAABB(b2AABB* aabb)
+ {
+ b2Vec2 w; w.Set(2.0f * m_proxyExtent, 2.0f * m_proxyExtent);
+ //aabb->lowerBound.x = -m_proxyExtent;
+ //aabb->lowerBound.y = -m_proxyExtent + m_worldExtent;
+ aabb->lowerBound.x = RandomFloat(-m_worldExtent, m_worldExtent);
+ aabb->lowerBound.y = RandomFloat(0.0f, 2.0f * m_worldExtent);
+ aabb->upperBound = aabb->lowerBound + w;
+ }
+
+ void MoveAABB(b2AABB* aabb)
+ {
+ b2Vec2 d;
+ d.x = RandomFloat(-0.5f, 0.5f);
+ d.y = RandomFloat(-0.5f, 0.5f);
+ //d.x = 2.0f;
+ //d.y = 0.0f;
+ aabb->lowerBound += d;
+ aabb->upperBound += d;
+
+ b2Vec2 c0 = 0.5f * (aabb->lowerBound + aabb->upperBound);
+ b2Vec2 min; min.Set(-m_worldExtent, 0.0f);
+ b2Vec2 max; max.Set(m_worldExtent, 2.0f * m_worldExtent);
+ b2Vec2 c = b2Clamp(c0, min, max);
+
+ aabb->lowerBound += c - c0;
+ aabb->upperBound += c - c0;
+ }
+
+ void CreateProxy()
+ {
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ int32 j = rand() % e_actorCount;
+ Actor* actor = m_actors + j;
+ if (actor->proxyId == b2_nullNode)
+ {
+ GetRandomAABB(&actor->aabb);
+ actor->proxyId = m_tree.CreateProxy(actor->aabb, actor);
+ return;
+ }
+ }
+ }
+
+ void DestroyProxy()
+ {
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ int32 j = rand() % e_actorCount;
+ Actor* actor = m_actors + j;
+ if (actor->proxyId != b2_nullNode)
+ {
+ m_tree.DestroyProxy(actor->proxyId);
+ actor->proxyId = b2_nullNode;
+ return;
+ }
+ }
+ }
+
+ void MoveProxy()
+ {
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ int32 j = rand() % e_actorCount;
+ Actor* actor = m_actors + j;
+ if (actor->proxyId == b2_nullNode)
+ {
+ continue;
+ }
+
+ b2AABB aabb0 = actor->aabb;
+ MoveAABB(&actor->aabb);
+ b2Vec2 displacement = actor->aabb.GetCenter() - aabb0.GetCenter();
+ m_tree.MoveProxy(actor->proxyId, actor->aabb, displacement);
+ return;
+ }
+ }
+
+ void Action()
+ {
+ int32 choice = rand() % 20;
+
+ switch (choice)
+ {
+ case 0:
+ CreateProxy();
+ break;
+
+ case 1:
+ DestroyProxy();
+ break;
+
+ default:
+ MoveProxy();
+ }
+ }
+
+ void Query()
+ {
+ m_tree.Query(this, m_queryAABB);
+
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ if (m_actors[i].proxyId == b2_nullNode)
+ {
+ continue;
+ }
+
+ bool overlap = b2TestOverlap(m_queryAABB, m_actors[i].aabb);
+ B2_NOT_USED(overlap);
+ b2Assert(overlap == m_actors[i].overlap);
+ }
+ }
+
+ void RayCast()
+ {
+ m_rayActor = NULL;
+
+ b2RayCastInput input = m_rayCastInput;
+
+ // Ray cast against the dynamic tree.
+ m_tree.RayCast(this, input);
+
+ // Brute force ray cast.
+ Actor* bruteActor = NULL;
+ b2RayCastOutput bruteOutput;
+ for (int32 i = 0; i < e_actorCount; ++i)
+ {
+ if (m_actors[i].proxyId == b2_nullNode)
+ {
+ continue;
+ }
+
+ b2RayCastOutput output;
+ bool hit = m_actors[i].aabb.RayCast(&output, input);
+ if (hit)
+ {
+ bruteActor = m_actors + i;
+ bruteOutput = output;
+ input.maxFraction = output.fraction;
+ }
+ }
+
+ if (bruteActor != NULL)
+ {
+ b2Assert(bruteOutput.fraction == m_rayCastOutput.fraction);
+ }
+ }
+
+ float m_worldExtent;
+ float m_proxyExtent;
+
+ b2DynamicTree m_tree;
+ b2AABB m_queryAABB;
+ b2RayCastInput m_rayCastInput;
+ b2RayCastOutput m_rayCastOutput;
+ Actor* m_rayActor;
+ Actor m_actors[e_actorCount];
+ int32 m_stepCount;
+ bool m_automated;
+};
+
+static int testIndex = RegisterTest("Collision", "Dynamic Tree", DynamicTree::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/edge_shapes.cpp b/Client/ThirdParty/Box2D/testbed/tests/edge_shapes.cpp
new file mode 100644
index 0000000..6648c3c
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/edge_shapes.cpp
@@ -0,0 +1,253 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+
+class EdgeShapesCallback : public b2RayCastCallback
+{
+public:
+ EdgeShapesCallback()
+ {
+ m_fixture = NULL;
+ }
+
+ float ReportFixture(b2Fixture* fixture, const b2Vec2& point,
+ const b2Vec2& normal, float fraction) override
+ {
+ m_fixture = fixture;
+ m_point = point;
+ m_normal = normal;
+
+ return fraction;
+ }
+
+ b2Fixture* m_fixture;
+ b2Vec2 m_point;
+ b2Vec2 m_normal;
+};
+
+class EdgeShapes : public Test
+{
+public:
+
+ enum
+ {
+ e_maxBodies = 256
+ };
+
+ EdgeShapes()
+ {
+ // Ground body
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ float x1 = -20.0f;
+ float y1 = 2.0f * cosf(x1 / 10.0f * b2_pi);
+ for (int32 i = 0; i < 80; ++i)
+ {
+ float x2 = x1 + 0.5f;
+ float y2 = 2.0f * cosf(x2 / 10.0f * b2_pi);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(x1, y1), b2Vec2(x2, y2));
+ ground->CreateFixture(&shape, 0.0f);
+
+ x1 = x2;
+ y1 = y2;
+ }
+ }
+
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.5f, 0.0f);
+ vertices[1].Set(0.5f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+ m_polygons[0].Set(vertices, 3);
+ }
+
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.1f, 0.0f);
+ vertices[1].Set(0.1f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+ m_polygons[1].Set(vertices, 3);
+ }
+
+ {
+ float w = 1.0f;
+ float b = w / (2.0f + b2Sqrt(2.0f));
+ float s = b2Sqrt(2.0f) * b;
+
+ b2Vec2 vertices[8];
+ vertices[0].Set(0.5f * s, 0.0f);
+ vertices[1].Set(0.5f * w, b);
+ vertices[2].Set(0.5f * w, b + s);
+ vertices[3].Set(0.5f * s, w);
+ vertices[4].Set(-0.5f * s, w);
+ vertices[5].Set(-0.5f * w, b + s);
+ vertices[6].Set(-0.5f * w, b);
+ vertices[7].Set(-0.5f * s, 0.0f);
+
+ m_polygons[2].Set(vertices, 8);
+ }
+
+ {
+ m_polygons[3].SetAsBox(0.5f, 0.5f);
+ }
+
+ {
+ m_circle.m_radius = 0.5f;
+ }
+
+ m_bodyIndex = 0;
+ memset(m_bodies, 0, sizeof(m_bodies));
+
+ m_angle = 0.0f;
+ }
+
+ void Create(int32 index)
+ {
+ if (m_bodies[m_bodyIndex] != NULL)
+ {
+ m_world->DestroyBody(m_bodies[m_bodyIndex]);
+ m_bodies[m_bodyIndex] = NULL;
+ }
+
+ b2BodyDef bd;
+
+ float x = RandomFloat(-10.0f, 10.0f);
+ float y = RandomFloat(10.0f, 20.0f);
+ bd.position.Set(x, y);
+ bd.angle = RandomFloat(-b2_pi, b2_pi);
+ bd.type = b2_dynamicBody;
+
+ if (index == 4)
+ {
+ bd.angularDamping = 0.02f;
+ }
+
+ m_bodies[m_bodyIndex] = m_world->CreateBody(&bd);
+
+ if (index < 4)
+ {
+ b2FixtureDef fd;
+ fd.shape = m_polygons + index;
+ fd.friction = 0.3f;
+ fd.density = 20.0f;
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = &m_circle;
+ fd.friction = 0.3f;
+ fd.density = 20.0f;
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+
+ m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies;
+ }
+
+ void DestroyBody()
+ {
+ for (int32 i = 0; i < e_maxBodies; ++i)
+ {
+ if (m_bodies[i] != NULL)
+ {
+ m_world->DestroyBody(m_bodies[i]);
+ m_bodies[i] = NULL;
+ return;
+ }
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_1:
+ case GLFW_KEY_2:
+ case GLFW_KEY_3:
+ case GLFW_KEY_4:
+ case GLFW_KEY_5:
+ Create(key - GLFW_KEY_1);
+ break;
+
+ case GLFW_KEY_D:
+ DestroyBody();
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ bool advanceRay = settings.m_pause == 0 || settings.m_singleStep;
+
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff");
+ m_textLine += m_textIncrement;
+
+ float L = 25.0f;
+ b2Vec2 point1(0.0f, 10.0f);
+ b2Vec2 d(L * cosf(m_angle), -L * b2Abs(sinf(m_angle)));
+ b2Vec2 point2 = point1 + d;
+
+ EdgeShapesCallback callback;
+
+ m_world->RayCast(&callback, point1, point2);
+
+ if (callback.m_fixture)
+ {
+ g_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f));
+
+ g_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f));
+
+ b2Vec2 head = callback.m_point + 0.5f * callback.m_normal;
+ g_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f));
+ }
+ else
+ {
+ g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f));
+ }
+
+ if (advanceRay)
+ {
+ m_angle += 0.25f * b2_pi / 180.0f;
+ }
+ }
+
+ static Test* Create()
+ {
+ return new EdgeShapes;
+ }
+
+ int32 m_bodyIndex;
+ b2Body* m_bodies[e_maxBodies];
+ b2PolygonShape m_polygons[4];
+ b2CircleShape m_circle;
+
+ float m_angle;
+};
+
+static int testIndex = RegisterTest("Geometry", "Edge Shapes", EdgeShapes::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/edge_test.cpp b/Client/ThirdParty/Box2D/testbed/tests/edge_test.cpp
new file mode 100644
index 0000000..335e9fe
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/edge_test.cpp
@@ -0,0 +1,282 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "imgui/imgui.h"
+
+class EdgeTest : public Test
+{
+public:
+
+ EdgeTest()
+ {
+ b2Vec2 vertices[10] =
+ {
+ {10.0f, -4.0f},
+ {10.0f, 0.0f},
+ {6.0f, 0.0f},
+ {4.0f, 2.0f},
+ {2.0f, 0.0f},
+ {-2.0f, 0.0f},
+ {-6.0f, 0.0f},
+ {-8.0f, -3.0f},
+ {-10.0f, 0.0f},
+ {-10.0f, -4.0f}
+ };
+
+ m_offset1.Set(0.0f, 8.0f);
+ m_offset2.Set(0.0f, 16.0f);
+
+ {
+ b2Vec2 v1 = vertices[0] + m_offset1;
+ b2Vec2 v2 = vertices[1] + m_offset1;
+ b2Vec2 v3 = vertices[2] + m_offset1;
+ b2Vec2 v4 = vertices[3] + m_offset1;
+ b2Vec2 v5 = vertices[4] + m_offset1;
+ b2Vec2 v6 = vertices[5] + m_offset1;
+ b2Vec2 v7 = vertices[6] + m_offset1;
+ b2Vec2 v8 = vertices[7] + m_offset1;
+ b2Vec2 v9 = vertices[8] + m_offset1;
+ b2Vec2 v10 = vertices[9] + m_offset1;
+
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+
+ shape.SetOneSided(v10, v1, v2, v3);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v1, v2, v3, v4);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v2, v3, v4, v5);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v3, v4, v5, v6);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v4, v5, v6, v7);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v5, v6, v7, v8);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v6, v7, v8, v9);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v7, v8, v9, v10);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v8, v9, v10, v1);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetOneSided(v9, v10, v1, v2);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2Vec2 v1 = vertices[0] + m_offset2;
+ b2Vec2 v2 = vertices[1] + m_offset2;
+ b2Vec2 v3 = vertices[2] + m_offset2;
+ b2Vec2 v4 = vertices[3] + m_offset2;
+ b2Vec2 v5 = vertices[4] + m_offset2;
+ b2Vec2 v6 = vertices[5] + m_offset2;
+ b2Vec2 v7 = vertices[6] + m_offset2;
+ b2Vec2 v8 = vertices[7] + m_offset2;
+ b2Vec2 v9 = vertices[8] + m_offset2;
+ b2Vec2 v10 = vertices[9] + m_offset2;
+
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+
+ shape.SetTwoSided(v1, v2);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v2, v3);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v3, v4);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v4, v5);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v5, v6);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v6, v7);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v7, v8);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v8, v9);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v9, v10);
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(v10, v1);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ m_body1 = nullptr;
+ m_body2 = nullptr;
+ CreateBoxes();
+ m_boxes = true;
+ }
+
+ void CreateBoxes()
+ {
+ if (m_body1)
+ {
+ m_world->DestroyBody(m_body1);
+ m_body1 = nullptr;
+ }
+
+ if (m_body2)
+ {
+ m_world->DestroyBody(m_body2);
+ m_body2 = nullptr;
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = b2Vec2(8.0f, 2.6f) + m_offset1;
+ bd.allowSleep = false;
+ m_body1 = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 1.0f);
+
+ m_body1->CreateFixture(&shape, 1.0f);
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = b2Vec2(8.0f, 2.6f) + m_offset2;
+ bd.allowSleep = false;
+ m_body2 = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 1.0f);
+
+ m_body2->CreateFixture(&shape, 1.0f);
+ }
+ }
+
+ void CreateCircles()
+ {
+ if (m_body1)
+ {
+ m_world->DestroyBody(m_body1);
+ m_body1 = nullptr;
+ }
+
+ if (m_body2)
+ {
+ m_world->DestroyBody(m_body2);
+ m_body2 = nullptr;
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = b2Vec2(-0.5f, 0.6f) + m_offset1;
+ bd.allowSleep = false;
+ m_body1 = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+
+ m_body1->CreateFixture(&shape, 1.0f);
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = b2Vec2(-0.5f, 0.6f) + m_offset2;
+ bd.allowSleep = false;
+ m_body2 = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+
+ m_body2->CreateFixture(&shape, 1.0f);
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f));
+ ImGui::Begin("Custom Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::RadioButton("Boxes", m_boxes == true))
+ {
+ CreateBoxes();
+ m_boxes = true;
+ }
+
+ if (ImGui::RadioButton("Circles", m_boxes == false))
+ {
+ CreateCircles();
+ m_boxes = false;
+ }
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_A) == GLFW_PRESS)
+ {
+ m_body1->ApplyForceToCenter(b2Vec2(-10.0f, 0.0f), true);
+ m_body2->ApplyForceToCenter(b2Vec2(-10.0f, 0.0f), true);
+ }
+
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_D) == GLFW_PRESS)
+ {
+ m_body1->ApplyForceToCenter(b2Vec2(10.0f, 0.0f), true);
+ m_body2->ApplyForceToCenter(b2Vec2(10.0f, 0.0f), true);
+ }
+
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new EdgeTest;
+ }
+
+ b2Vec2 m_offset1, m_offset2;
+ b2Body* m_body1;
+ b2Body* m_body2;
+ bool m_boxes;
+};
+
+static int testIndex = RegisterTest("Geometry", "Edge Test", EdgeTest::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/friction.cpp b/Client/ThirdParty/Box2D/testbed/tests/friction.cpp
new file mode 100644
index 0000000..9f1c06e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/friction.cpp
@@ -0,0 +1,127 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Friction : public Test
+{
+public:
+
+ Friction()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(13.0f, 0.25f);
+
+ b2BodyDef bd;
+ bd.position.Set(-4.0f, 22.0f);
+ bd.angle = -0.25f;
+
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f, 1.0f);
+
+ b2BodyDef bd;
+ bd.position.Set(10.5f, 19.0f);
+
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(13.0f, 0.25f);
+
+ b2BodyDef bd;
+ bd.position.Set(4.0f, 14.0f);
+ bd.angle = 0.25f;
+
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f, 1.0f);
+
+ b2BodyDef bd;
+ bd.position.Set(-10.5f, 11.0f);
+
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(13.0f, 0.25f);
+
+ b2BodyDef bd;
+ bd.position.Set(-4.0f, 6.0f);
+ bd.angle = -0.25f;
+
+ b2Body* ground = m_world->CreateBody(&bd);
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 25.0f;
+
+ float friction[5] = {0.75f, 0.5f, 0.35f, 0.1f, 0.0f};
+
+ for (int i = 0; i < 5; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-15.0f + 4.0f * i, 28.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ fd.friction = friction[i];
+ body->CreateFixture(&fd);
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Friction;
+ }
+};
+
+static int testIndex = RegisterTest("Forces", "Friction", Friction::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/gear_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/gear_joint.cpp
new file mode 100644
index 0000000..6f31283
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/gear_joint.cpp
@@ -0,0 +1,180 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class GearJoint : public Test
+{
+public:
+ GearJoint()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2CircleShape circle1;
+ circle1.m_radius = 1.0f;
+
+ b2PolygonShape box;
+ box.SetAsBox(0.5f, 5.0f);
+
+ b2CircleShape circle2;
+ circle2.m_radius = 2.0f;
+
+ b2BodyDef bd1;
+ bd1.type = b2_staticBody;
+ bd1.position.Set(10.0f, 9.0f);
+ b2Body* body1 = m_world->CreateBody(&bd1);
+ body1->CreateFixture(&circle1, 5.0f);
+
+ b2BodyDef bd2;
+ bd2.type = b2_dynamicBody;
+ bd2.position.Set(10.0f, 8.0f);
+ b2Body* body2 = m_world->CreateBody(&bd2);
+ body2->CreateFixture(&box, 5.0f);
+
+ b2BodyDef bd3;
+ bd3.type = b2_dynamicBody;
+ bd3.position.Set(10.0f, 6.0f);
+ b2Body* body3 = m_world->CreateBody(&bd3);
+ body3->CreateFixture(&circle2, 5.0f);
+
+ b2RevoluteJointDef jd1;
+ jd1.Initialize(body1, body2, bd1.position);
+ b2Joint* joint1 = m_world->CreateJoint(&jd1);
+
+ b2RevoluteJointDef jd2;
+ jd2.Initialize(body2, body3, bd3.position);
+ b2Joint* joint2 = m_world->CreateJoint(&jd2);
+
+ b2GearJointDef jd4;
+ jd4.bodyA = body1;
+ jd4.bodyB = body3;
+ jd4.joint1 = joint1;
+ jd4.joint2 = joint2;
+ jd4.ratio = circle2.m_radius / circle1.m_radius;
+ m_world->CreateJoint(&jd4);
+ }
+
+ {
+ b2CircleShape circle1;
+ circle1.m_radius = 1.0f;
+
+ b2CircleShape circle2;
+ circle2.m_radius = 2.0f;
+
+ b2PolygonShape box;
+ box.SetAsBox(0.5f, 5.0f);
+
+ b2BodyDef bd1;
+ bd1.type = b2_dynamicBody;
+ bd1.position.Set(-3.0f, 12.0f);
+ b2Body* body1 = m_world->CreateBody(&bd1);
+ body1->CreateFixture(&circle1, 5.0f);
+
+ b2RevoluteJointDef jd1;
+ jd1.bodyA = ground;
+ jd1.bodyB = body1;
+ jd1.localAnchorA = ground->GetLocalPoint(bd1.position);
+ jd1.localAnchorB = body1->GetLocalPoint(bd1.position);
+ jd1.referenceAngle = body1->GetAngle() - ground->GetAngle();
+ m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd1);
+
+ b2BodyDef bd2;
+ bd2.type = b2_dynamicBody;
+ bd2.position.Set(0.0f, 12.0f);
+ b2Body* body2 = m_world->CreateBody(&bd2);
+ body2->CreateFixture(&circle2, 5.0f);
+
+ b2RevoluteJointDef jd2;
+ jd2.Initialize(ground, body2, bd2.position);
+ m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd2);
+
+ b2BodyDef bd3;
+ bd3.type = b2_dynamicBody;
+ bd3.position.Set(2.5f, 12.0f);
+ b2Body* body3 = m_world->CreateBody(&bd3);
+ body3->CreateFixture(&box, 5.0f);
+
+ b2PrismaticJointDef jd3;
+ jd3.Initialize(ground, body3, bd3.position, b2Vec2(0.0f, 1.0f));
+ jd3.lowerTranslation = -5.0f;
+ jd3.upperTranslation = 5.0f;
+ jd3.enableLimit = true;
+
+ m_joint3 = (b2PrismaticJoint*)m_world->CreateJoint(&jd3);
+
+ b2GearJointDef jd4;
+ jd4.bodyA = body1;
+ jd4.bodyB = body2;
+ jd4.joint1 = m_joint1;
+ jd4.joint2 = m_joint2;
+ jd4.ratio = circle2.m_radius / circle1.m_radius;
+ m_joint4 = (b2GearJoint*)m_world->CreateJoint(&jd4);
+
+ b2GearJointDef jd5;
+ jd5.bodyA = body2;
+ jd5.bodyB = body3;
+ jd5.joint1 = m_joint2;
+ jd5.joint2 = m_joint3;
+ jd5.ratio = -1.0f / circle2.m_radius;
+ m_joint5 = (b2GearJoint*)m_world->CreateJoint(&jd5);
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ float ratio, value;
+
+ ratio = m_joint4->GetRatio();
+ value = m_joint1->GetJointAngle() + ratio * m_joint2->GetJointAngle();
+ g_debugDraw.DrawString(5, m_textLine, "theta1 + %4.2f * theta2 = %4.2f", (float) ratio, (float) value);
+ m_textLine += m_textIncrement;
+
+ ratio = m_joint5->GetRatio();
+ value = m_joint2->GetJointAngle() + ratio * m_joint3->GetJointTranslation();
+ g_debugDraw.DrawString(5, m_textLine, "theta2 + %4.2f * delta = %4.2f", (float) ratio, (float) value);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new GearJoint;
+ }
+
+ b2RevoluteJoint* m_joint1;
+ b2RevoluteJoint* m_joint2;
+ b2PrismaticJoint* m_joint3;
+ b2GearJoint* m_joint4;
+ b2GearJoint* m_joint5;
+};
+
+static int testIndex = RegisterTest("Joints", "Gear", GearJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/heavy1.cpp b/Client/ThirdParty/Box2D/testbed/tests/heavy1.cpp
new file mode 100644
index 0000000..d302808
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/heavy1.cpp
@@ -0,0 +1,61 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Heavy1 : public Test
+{
+public:
+
+ Heavy1()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 0.5f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+ body->CreateFixture(&shape, 10.0f);
+
+ bd.position.Set(0.0f, 6.0f);
+ body = m_world->CreateBody(&bd);
+ shape.m_radius = 5.0f;
+ body->CreateFixture(&shape, 10.0f);
+ }
+
+ static Test* Create()
+ {
+ return new Heavy1;
+ }
+};
+
+static int testIndex = RegisterTest("Solver", "Heavy 1", Heavy1::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/heavy2.cpp b/Client/ThirdParty/Box2D/testbed/tests/heavy2.cpp
new file mode 100644
index 0000000..271c089
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/heavy2.cpp
@@ -0,0 +1,94 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Heavy2 : public Test
+{
+public:
+
+ Heavy2()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 2.5f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.5f;
+ body->CreateFixture(&shape, 10.0f);
+
+ bd.position.Set(0.0f, 3.5f);
+ body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 10.0f);
+
+ m_heavy = NULL;
+ }
+
+ void ToggleHeavy()
+ {
+ if (m_heavy)
+ {
+ m_world->DestroyBody(m_heavy);
+ m_heavy = NULL;
+ }
+ else
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 9.0f);
+ m_heavy = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 5.0f;
+ m_heavy->CreateFixture(&shape, 10.0f);
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_H:
+ ToggleHeavy();
+ break;
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Heavy2;
+ }
+
+ b2Body* m_heavy;
+};
+
+static int testIndex = RegisterTest("Solver", "Heavy 2", Heavy2::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/mobile_balanced.cpp b/Client/ThirdParty/Box2D/testbed/tests/mobile_balanced.cpp
new file mode 100644
index 0000000..ee5af37
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/mobile_balanced.cpp
@@ -0,0 +1,108 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class MobileBalanced : public Test
+{
+public:
+
+ enum
+ {
+ e_depth = 4
+ };
+
+ MobileBalanced()
+ {
+ b2Body* ground;
+
+ // Create ground body.
+ {
+ b2BodyDef bodyDef;
+ bodyDef.position.Set(0.0f, 20.0f);
+ ground = m_world->CreateBody(&bodyDef);
+ }
+
+ float a = 0.5f;
+ b2Vec2 h(0.0f, a);
+
+ b2Body* root = AddNode(ground, b2Vec2_zero, 0, 3.0f, a);
+
+ b2RevoluteJointDef jointDef;
+ jointDef.bodyA = ground;
+ jointDef.bodyB = root;
+ jointDef.localAnchorA.SetZero();
+ jointDef.localAnchorB = h;
+ m_world->CreateJoint(&jointDef);
+ }
+
+ b2Body* AddNode(b2Body* parent, const b2Vec2& localAnchor, int32 depth, float offset, float a)
+ {
+ float density = 20.0f;
+ b2Vec2 h(0.0f, a);
+
+ b2Vec2 p = parent->GetPosition() + localAnchor - h;
+
+ b2BodyDef bodyDef;
+ bodyDef.type = b2_dynamicBody;
+ bodyDef.position = p;
+ b2Body* body = m_world->CreateBody(&bodyDef);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f * a, a);
+ body->CreateFixture(&shape, density);
+
+ if (depth == e_depth)
+ {
+ return body;
+ }
+
+ shape.SetAsBox(offset, 0.25f * a, b2Vec2(0, -a), 0.0f);
+ body->CreateFixture(&shape, density);
+
+ b2Vec2 a1 = b2Vec2(offset, -a);
+ b2Vec2 a2 = b2Vec2(-offset, -a);
+ b2Body* body1 = AddNode(body, a1, depth + 1, 0.5f * offset, a);
+ b2Body* body2 = AddNode(body, a2, depth + 1, 0.5f * offset, a);
+
+ b2RevoluteJointDef jointDef;
+ jointDef.bodyA = body;
+ jointDef.localAnchorB = h;
+
+ jointDef.localAnchorA = a1;
+ jointDef.bodyB = body1;
+ m_world->CreateJoint(&jointDef);
+
+ jointDef.localAnchorA = a2;
+ jointDef.bodyB = body2;
+ m_world->CreateJoint(&jointDef);
+
+ return body;
+ }
+
+ static Test* Create()
+ {
+ return new MobileBalanced;
+ }
+};
+
+static int testIndex = RegisterTest("Solver", "Mobile Balanced", MobileBalanced::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/mobile_unbalanced.cpp b/Client/ThirdParty/Box2D/testbed/tests/mobile_unbalanced.cpp
new file mode 100644
index 0000000..5f62fb6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/mobile_unbalanced.cpp
@@ -0,0 +1,105 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class MobileUnbalanced : public Test
+{
+public:
+
+ enum
+ {
+ e_depth = 4
+ };
+
+ MobileUnbalanced()
+ {
+ b2Body* ground;
+
+ // Create ground body.
+ {
+ b2BodyDef bodyDef;
+ bodyDef.position.Set(0.0f, 20.0f);
+ ground = m_world->CreateBody(&bodyDef);
+ }
+
+ float a = 0.5f;
+ b2Vec2 h(0.0f, a);
+
+ b2Body* root = AddNode(ground, b2Vec2_zero, 0, 3.0f, a);
+
+ b2RevoluteJointDef jointDef;
+ jointDef.bodyA = ground;
+ jointDef.bodyB = root;
+ jointDef.localAnchorA.SetZero();
+ jointDef.localAnchorB = h;
+ m_world->CreateJoint(&jointDef);
+ }
+
+ b2Body* AddNode(b2Body* parent, const b2Vec2& localAnchor, int32 depth, float offset, float a)
+ {
+ float density = 20.0f;
+ b2Vec2 h(0.0f, a);
+
+ b2Vec2 p = parent->GetPosition() + localAnchor - h;
+
+ b2BodyDef bodyDef;
+ bodyDef.type = b2_dynamicBody;
+ bodyDef.position = p;
+ b2Body* body = m_world->CreateBody(&bodyDef);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f * a, a);
+ body->CreateFixture(&shape, density);
+
+ if (depth == e_depth)
+ {
+ return body;
+ }
+
+ b2Vec2 a1 = b2Vec2(offset, -a);
+ b2Vec2 a2 = b2Vec2(-offset, -a);
+ b2Body* body1 = AddNode(body, a1, depth + 1, 0.5f * offset, a);
+ b2Body* body2 = AddNode(body, a2, depth + 1, 0.5f * offset, a);
+
+ b2RevoluteJointDef jointDef;
+ jointDef.bodyA = body;
+ jointDef.localAnchorB = h;
+
+ jointDef.localAnchorA = a1;
+ jointDef.bodyB = body1;
+ m_world->CreateJoint(&jointDef);
+
+ jointDef.localAnchorA = a2;
+ jointDef.bodyB = body2;
+ m_world->CreateJoint(&jointDef);
+
+ return body;
+ }
+
+ static Test* Create()
+ {
+ return new MobileUnbalanced;
+ }
+};
+
+static int testIndex = RegisterTest("Solver", "Mobile Unbalanced", MobileUnbalanced::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/motor_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/motor_joint.cpp
new file mode 100644
index 0000000..dcda76f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/motor_joint.cpp
@@ -0,0 +1,118 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+
+/// This test shows how to use a motor joint. A motor joint
+/// can be used to animate a dynamic body. With finite motor forces
+/// the body can be blocked by collision with other bodies.
+class MotorJoint : public Test
+{
+public:
+ MotorJoint()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+
+ ground->CreateFixture(&fd);
+ }
+
+ // Define motorized body
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 8.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(2.0f, 0.5f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.friction = 0.6f;
+ fd.density = 2.0f;
+ body->CreateFixture(&fd);
+
+ b2MotorJointDef mjd;
+ mjd.Initialize(ground, body);
+ mjd.maxForce = 1000.0f;
+ mjd.maxTorque = 1000.0f;
+ m_joint = (b2MotorJoint*)m_world->CreateJoint(&mjd);
+ }
+
+ m_go = false;
+ m_time = 0.0f;
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_S:
+ m_go = !m_go;
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ if (m_go && settings.m_hertz > 0.0f)
+ {
+ m_time += 1.0f / settings.m_hertz;
+ }
+
+ b2Vec2 linearOffset;
+ linearOffset.x = 6.0f * sinf(2.0f * m_time);
+ linearOffset.y = 8.0f + 4.0f * sinf(1.0f * m_time);
+
+ float angularOffset = 4.0f * m_time;
+
+ m_joint->SetLinearOffset(linearOffset);
+ m_joint->SetAngularOffset(angularOffset);
+
+ g_debugDraw.DrawPoint(linearOffset, 4.0f, b2Color(0.9f, 0.9f, 0.9f));
+
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "Keys: (s) pause");
+ m_textLine += 15;
+ }
+
+ static Test* Create()
+ {
+ return new MotorJoint;
+ }
+
+ b2MotorJoint* m_joint;
+ float m_time;
+ bool m_go;
+};
+
+static int testIndex = RegisterTest("Joints", "Motor Joint", MotorJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/pinball.cpp b/Client/ThirdParty/Box2D/testbed/tests/pinball.cpp
new file mode 100644
index 0000000..9a9826d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/pinball.cpp
@@ -0,0 +1,170 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+/// This tests bullet collision and provides an example of a gameplay scenario.
+/// This also uses a loop shape.
+class Pinball : public Test
+{
+public:
+ Pinball()
+ {
+ // Ground body
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2Vec2 vs[5];
+ vs[0].Set(-8.0f, 6.0f);
+ vs[1].Set(-8.0f, 20.0f);
+ vs[2].Set(8.0f, 20.0f);
+ vs[3].Set(8.0f, 6.0f);
+ vs[4].Set(0.0f, -2.0f);
+
+ b2ChainShape loop;
+ loop.CreateLoop(vs, 5);
+ b2FixtureDef fd;
+ fd.shape = &loop;
+ fd.density = 0.0f;
+ ground->CreateFixture(&fd);
+ }
+
+ // Flippers
+ {
+ b2Vec2 p1(-2.0f, 0.0f), p2(2.0f, 0.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ bd.position = p1;
+ b2Body* leftFlipper = m_world->CreateBody(&bd);
+
+ bd.position = p2;
+ b2Body* rightFlipper = m_world->CreateBody(&bd);
+
+ b2PolygonShape box;
+ box.SetAsBox(1.75f, 0.1f);
+
+ b2FixtureDef fd;
+ fd.shape = &box;
+ fd.density = 1.0f;
+
+ leftFlipper->CreateFixture(&fd);
+ rightFlipper->CreateFixture(&fd);
+
+ b2RevoluteJointDef jd;
+ jd.bodyA = ground;
+ jd.localAnchorB.SetZero();
+ jd.enableMotor = true;
+ jd.maxMotorTorque = 1000.0f;
+ jd.enableLimit = true;
+
+ jd.motorSpeed = 0.0f;
+ jd.localAnchorA = p1;
+ jd.bodyB = leftFlipper;
+ jd.lowerAngle = -30.0f * b2_pi / 180.0f;
+ jd.upperAngle = 5.0f * b2_pi / 180.0f;
+ m_leftJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
+
+ jd.motorSpeed = 0.0f;
+ jd.localAnchorA = p2;
+ jd.bodyB = rightFlipper;
+ jd.lowerAngle = -5.0f * b2_pi / 180.0f;
+ jd.upperAngle = 30.0f * b2_pi / 180.0f;
+ m_rightJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
+ }
+
+ // Circle character
+ {
+ b2BodyDef bd;
+ bd.position.Set(1.0f, 15.0f);
+ bd.type = b2_dynamicBody;
+ bd.bullet = true;
+
+ m_ball = m_world->CreateBody(&bd);
+
+ b2CircleShape shape;
+ shape.m_radius = 0.2f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+ m_ball->CreateFixture(&fd);
+ }
+
+ m_button = false;
+ }
+
+ void Step(Settings& settings) override
+ {
+ if (m_button)
+ {
+ m_leftJoint->SetMotorSpeed(20.0f);
+ m_rightJoint->SetMotorSpeed(-20.0f);
+ }
+ else
+ {
+ m_leftJoint->SetMotorSpeed(-10.0f);
+ m_rightJoint->SetMotorSpeed(10.0f);
+ }
+
+ Test::Step(settings);
+
+ g_debugDraw.DrawString(5, m_textLine, "Press 'a' to control the flippers");
+ m_textLine += m_textIncrement;
+
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_button = true;
+ break;
+ }
+ }
+
+ void KeyboardUp(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_button = false;
+ break;
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Pinball;
+ }
+
+ b2RevoluteJoint* m_leftJoint;
+ b2RevoluteJoint* m_rightJoint;
+ b2Body* m_ball;
+ bool m_button;
+};
+
+static int testIndex = RegisterTest("Examples", "Pinball", Pinball::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/platformer.cpp b/Client/ThirdParty/Box2D/testbed/tests/platformer.cpp
new file mode 100644
index 0000000..388892f
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/platformer.cpp
@@ -0,0 +1,133 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Platformer : public Test
+{
+public:
+
+ enum State
+ {
+ e_unknown,
+ e_above,
+ e_below
+ };
+
+ Platformer()
+ {
+ // Ground
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Platform
+ {
+ b2BodyDef bd;
+ bd.position.Set(0.0f, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(3.0f, 0.5f);
+ m_platform = body->CreateFixture(&shape, 0.0f);
+
+ m_bottom = 10.0f - 0.5f;
+ m_top = 10.0f + 0.5f;
+ }
+
+ // Actor
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 12.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ m_radius = 0.5f;
+ b2CircleShape shape;
+ shape.m_radius = m_radius;
+ m_character = body->CreateFixture(&shape, 20.0f);
+
+ body->SetLinearVelocity(b2Vec2(0.0f, -50.0f));
+
+ m_state = e_unknown;
+ }
+ }
+
+ void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override
+ {
+ Test::PreSolve(contact, oldManifold);
+
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+
+ if (fixtureA != m_platform && fixtureA != m_character)
+ {
+ return;
+ }
+
+ if (fixtureB != m_platform && fixtureB != m_character)
+ {
+ return;
+ }
+
+#if 1
+ b2Vec2 position = m_character->GetBody()->GetPosition();
+
+ if (position.y < m_top + m_radius - 3.0f * b2_linearSlop)
+ {
+ contact->SetEnabled(false);
+ }
+#else
+ b2Vec2 v = m_character->GetBody()->GetLinearVelocity();
+ if (v.y > 0.0f)
+ {
+ contact->SetEnabled(false);
+ }
+#endif
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ b2Vec2 v = m_character->GetBody()->GetLinearVelocity();
+ g_debugDraw.DrawString(5, m_textLine, "Character Linear Velocity: %f", v.y);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new Platformer;
+ }
+
+ float m_radius, m_top, m_bottom;
+ State m_state;
+ b2Fixture* m_platform;
+ b2Fixture* m_character;
+};
+
+static int testIndex = RegisterTest("Examples", "Platformer", Platformer::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/polygon_collision.cpp b/Client/ThirdParty/Box2D/testbed/tests/polygon_collision.cpp
new file mode 100644
index 0000000..e55f133
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/polygon_collision.cpp
@@ -0,0 +1,127 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class PolygonCollision : public Test
+{
+public:
+ PolygonCollision()
+ {
+ {
+ m_polygonA.SetAsBox(0.2f, 0.4f);
+ m_transformA.Set(b2Vec2(0.0f, 0.0f), 0.0f);
+ }
+
+ {
+ m_polygonB.SetAsBox(0.5f, 0.5f);
+ m_positionB.Set(19.345284f, 1.5632932f);
+ m_angleB = 1.9160721f;
+ m_transformB.Set(m_positionB, m_angleB);
+ }
+ }
+
+ static Test* Create()
+ {
+ return new PolygonCollision;
+ }
+
+ void Step(Settings& settings) override
+ {
+ B2_NOT_USED(settings);
+
+ b2Manifold manifold;
+ b2CollidePolygons(&manifold, &m_polygonA, m_transformA, &m_polygonB, m_transformB);
+
+ b2WorldManifold worldManifold;
+ worldManifold.Initialize(&manifold, m_transformA, m_polygonA.m_radius, m_transformB, m_polygonB.m_radius);
+
+ g_debugDraw.DrawString(5, m_textLine, "point count = %d", manifold.pointCount);
+ m_textLine += m_textIncrement;
+
+ {
+ b2Color color(0.9f, 0.9f, 0.9f);
+ b2Vec2 v[b2_maxPolygonVertices];
+ for (int32 i = 0; i < m_polygonA.m_count; ++i)
+ {
+ v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(v, m_polygonA.m_count, color);
+
+ for (int32 i = 0; i < m_polygonB.m_count; ++i)
+ {
+ v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(v, m_polygonB.m_count, color);
+ }
+
+ for (int32 i = 0; i < manifold.pointCount; ++i)
+ {
+ g_debugDraw.DrawPoint(worldManifold.points[i], 4.0f, b2Color(0.9f, 0.3f, 0.3f));
+ }
+
+ Test::Step(settings);
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_positionB.x -= 0.1f;
+ break;
+
+ case GLFW_KEY_D:
+ m_positionB.x += 0.1f;
+ break;
+
+ case GLFW_KEY_S:
+ m_positionB.y -= 0.1f;
+ break;
+
+ case GLFW_KEY_W:
+ m_positionB.y += 0.1f;
+ break;
+
+ case GLFW_KEY_Q:
+ m_angleB += 0.1f * b2_pi;
+ break;
+
+ case GLFW_KEY_E:
+ m_angleB -= 0.1f * b2_pi;
+ break;
+ }
+
+ m_transformB.Set(m_positionB, m_angleB);
+ }
+
+ b2PolygonShape m_polygonA;
+ b2PolygonShape m_polygonB;
+
+ b2Transform m_transformA;
+ b2Transform m_transformB;
+
+ b2Vec2 m_positionB;
+ float m_angleB;
+};
+
+static int testIndex = RegisterTest("Geometry", "Polygon Collision", PolygonCollision::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/polygon_shapes.cpp b/Client/ThirdParty/Box2D/testbed/tests/polygon_shapes.cpp
new file mode 100644
index 0000000..e12875b
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/polygon_shapes.cpp
@@ -0,0 +1,265 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+/// This tests stacking. It also shows how to use b2World::Query
+/// and b2TestOverlap.
+
+/// This callback is called by b2World::QueryAABB. We find all the fixtures
+/// that overlap an AABB. Of those, we use b2TestOverlap to determine which fixtures
+/// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border.
+class PolygonShapesCallback : public b2QueryCallback
+{
+public:
+
+ enum
+ {
+ e_maxCount = 4
+ };
+
+ PolygonShapesCallback()
+ {
+ m_count = 0;
+ }
+
+ /// Called for each fixture found in the query AABB.
+ /// @return false to terminate the query.
+ bool ReportFixture(b2Fixture* fixture) override
+ {
+ if (m_count == e_maxCount)
+ {
+ return false;
+ }
+
+ b2Body* body = fixture->GetBody();
+ b2Shape* shape = fixture->GetShape();
+
+ bool overlap = b2TestOverlap(shape, 0, &m_circle, 0, body->GetTransform(), m_transform);
+
+ if (overlap)
+ {
+ b2Color color(0.95f, 0.95f, 0.6f);
+ b2Vec2 center = body->GetWorldCenter();
+ g_debugDraw->DrawPoint(center, 5.0f, color);
+ ++m_count;
+ }
+
+ return true;
+ }
+
+ b2CircleShape m_circle;
+ b2Transform m_transform;
+ b2Draw* g_debugDraw;
+ int32 m_count;
+};
+
+class PolygonShapes : public Test
+{
+public:
+
+ enum
+ {
+ e_maxBodies = 256
+ };
+
+ PolygonShapes()
+ {
+ // Ground body
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.5f, 0.0f);
+ vertices[1].Set(0.5f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+ m_polygons[0].Set(vertices, 3);
+ }
+
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.1f, 0.0f);
+ vertices[1].Set(0.1f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+ m_polygons[1].Set(vertices, 3);
+ }
+
+ {
+ float w = 1.0f;
+ float b = w / (2.0f + b2Sqrt(2.0f));
+ float s = b2Sqrt(2.0f) * b;
+
+ b2Vec2 vertices[8];
+ vertices[0].Set(0.5f * s, 0.0f);
+ vertices[1].Set(0.5f * w, b);
+ vertices[2].Set(0.5f * w, b + s);
+ vertices[3].Set(0.5f * s, w);
+ vertices[4].Set(-0.5f * s, w);
+ vertices[5].Set(-0.5f * w, b + s);
+ vertices[6].Set(-0.5f * w, b);
+ vertices[7].Set(-0.5f * s, 0.0f);
+
+ m_polygons[2].Set(vertices, 8);
+ }
+
+ {
+ m_polygons[3].SetAsBox(0.5f, 0.5f);
+ }
+
+ {
+ m_circle.m_radius = 0.5f;
+ }
+
+ m_bodyIndex = 0;
+ memset(m_bodies, 0, sizeof(m_bodies));
+ }
+
+ void Create(int32 index)
+ {
+ if (m_bodies[m_bodyIndex] != NULL)
+ {
+ m_world->DestroyBody(m_bodies[m_bodyIndex]);
+ m_bodies[m_bodyIndex] = NULL;
+ }
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ float x = RandomFloat(-2.0f, 2.0f);
+ bd.position.Set(x, 10.0f);
+ bd.angle = RandomFloat(-b2_pi, b2_pi);
+
+ if (index == 4)
+ {
+ bd.angularDamping = 0.02f;
+ }
+
+ m_bodies[m_bodyIndex] = m_world->CreateBody(&bd);
+
+ if (index < 4)
+ {
+ b2FixtureDef fd;
+ fd.shape = m_polygons + index;
+ fd.density = 1.0f;
+ fd.friction = 0.3f;
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = &m_circle;
+ fd.density = 1.0f;
+ fd.friction = 0.3f;
+
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+
+ m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies;
+ }
+
+ void DestroyBody()
+ {
+ for (int32 i = 0; i < e_maxBodies; ++i)
+ {
+ if (m_bodies[i] != NULL)
+ {
+ m_world->DestroyBody(m_bodies[i]);
+ m_bodies[i] = NULL;
+ return;
+ }
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_1:
+ case GLFW_KEY_2:
+ case GLFW_KEY_3:
+ case GLFW_KEY_4:
+ case GLFW_KEY_5:
+ Create(key - GLFW_KEY_1);
+ break;
+
+ case GLFW_KEY_A:
+ for (int32 i = 0; i < e_maxBodies; i += 2)
+ {
+ if (m_bodies[i])
+ {
+ bool enabled = m_bodies[i]->IsEnabled();
+ m_bodies[i]->SetEnabled(!enabled);
+ }
+ }
+ break;
+
+ case GLFW_KEY_D:
+ DestroyBody();
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ PolygonShapesCallback callback;
+ callback.m_circle.m_radius = 2.0f;
+ callback.m_circle.m_p.Set(0.0f, 1.1f);
+ callback.m_transform.SetIdentity();
+ callback.g_debugDraw = &g_debugDraw;
+
+ b2AABB aabb;
+ callback.m_circle.ComputeAABB(&aabb, callback.m_transform, 0);
+
+ m_world->QueryAABB(&callback, aabb);
+
+ b2Color color(0.4f, 0.7f, 0.8f);
+ g_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color);
+
+ g_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff, maximum of %d overlaps detected", PolygonShapesCallback::e_maxCount);
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "Press 'a' to enable/disable some bodies");
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "Press 'd' to destroy a body");
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new PolygonShapes;
+ }
+
+ int32 m_bodyIndex;
+ b2Body* m_bodies[e_maxBodies];
+ b2PolygonShape m_polygons[4];
+ b2CircleShape m_circle;
+};
+
+static int testIndex = RegisterTest("Geometry", "Polygon Shapes", PolygonShapes::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/prismatic_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/prismatic_joint.cpp
new file mode 100644
index 0000000..a3788cc
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/prismatic_joint.cpp
@@ -0,0 +1,118 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+#include "imgui/imgui.h"
+
+// Test the prismatic joint with limits and motor options.
+class PrismaticJoint : public Test
+{
+public:
+ PrismaticJoint()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ m_enableLimit = true;
+ m_enableMotor = false;
+ m_motorSpeed = 10.0f;
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(1.0f, 1.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 10.0f);
+ bd.angle = 0.5f * b2_pi;
+ bd.allowSleep = false;
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 5.0f);
+
+ b2PrismaticJointDef pjd;
+
+ // Horizontal
+ pjd.Initialize(ground, body, bd.position, b2Vec2(1.0f, 0.0f));
+
+ pjd.motorSpeed = m_motorSpeed;
+ pjd.maxMotorForce = 10000.0f;
+ pjd.enableMotor = m_enableMotor;
+ pjd.lowerTranslation = -10.0f;
+ pjd.upperTranslation = 10.0f;
+ pjd.enableLimit = m_enableLimit;
+
+ m_joint = (b2PrismaticJoint*)m_world->CreateJoint(&pjd);
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f));
+ ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::Checkbox("Limit", &m_enableLimit))
+ {
+ m_joint->EnableLimit(m_enableLimit);
+ }
+
+ if (ImGui::Checkbox("Motor", &m_enableMotor))
+ {
+ m_joint->EnableMotor(m_enableMotor);
+ }
+
+ if (ImGui::SliderFloat("Speed", &m_motorSpeed, -100.0f, 100.0f, "%.0f"))
+ {
+ m_joint->SetMotorSpeed(m_motorSpeed);
+ }
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+ float force = m_joint->GetMotorForce(settings.m_hertz);
+ g_debugDraw.DrawString(5, m_textLine, "Motor Force = %4.0f", force);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new PrismaticJoint;
+ }
+
+ b2PrismaticJoint* m_joint;
+ float m_motorSpeed;
+ bool m_enableMotor;
+ bool m_enableLimit;
+};
+
+static int testIndex = RegisterTest("Joints", "Prismatic", PrismaticJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/pulley_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/pulley_joint.cpp
new file mode 100644
index 0000000..c2ff683
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/pulley_joint.cpp
@@ -0,0 +1,96 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class PulleyJoint : public Test
+{
+public:
+ PulleyJoint()
+ {
+ float y = 16.0f;
+ float L = 12.0f;
+ float a = 1.0f;
+ float b = 2.0f;
+
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2CircleShape circle;
+ circle.m_radius = 2.0f;
+
+ circle.m_p.Set(-10.0f, y + b + L);
+ ground->CreateFixture(&circle, 0.0f);
+
+ circle.m_p.Set(10.0f, y + b + L);
+ ground->CreateFixture(&circle, 0.0f);
+ }
+
+ {
+
+ b2PolygonShape shape;
+ shape.SetAsBox(a, b);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ //bd.fixedRotation = true;
+ bd.position.Set(-10.0f, y);
+ b2Body* body1 = m_world->CreateBody(&bd);
+ body1->CreateFixture(&shape, 5.0f);
+
+ bd.position.Set(10.0f, y);
+ b2Body* body2 = m_world->CreateBody(&bd);
+ body2->CreateFixture(&shape, 5.0f);
+
+ b2PulleyJointDef pulleyDef;
+ b2Vec2 anchor1(-10.0f, y + b);
+ b2Vec2 anchor2(10.0f, y + b);
+ b2Vec2 groundAnchor1(-10.0f, y + b + L);
+ b2Vec2 groundAnchor2(10.0f, y + b + L);
+ pulleyDef.Initialize(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, 1.5f);
+
+ m_joint1 = (b2PulleyJoint*)m_world->CreateJoint(&pulleyDef);
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ float ratio = m_joint1->GetRatio();
+ float L = m_joint1->GetCurrentLengthA() + ratio * m_joint1->GetCurrentLengthB();
+ g_debugDraw.DrawString(5, m_textLine, "L1 + %4.2f * L2 = %4.2f", (float) ratio, (float) L);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new PulleyJoint;
+ }
+
+ b2PulleyJoint* m_joint1;
+};
+
+static int testIndex = RegisterTest("Joints", "Pulley", PulleyJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/pyramid.cpp b/Client/ThirdParty/Box2D/testbed/tests/pyramid.cpp
new file mode 100644
index 0000000..ee90d5d
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/pyramid.cpp
@@ -0,0 +1,92 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Pyramid : public Test
+{
+public:
+ enum
+ {
+ e_count = 20
+ };
+
+ Pyramid()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ float a = 0.5f;
+ b2PolygonShape shape;
+ shape.SetAsBox(a, a);
+
+ b2Vec2 x(-7.0f, 0.75f);
+ b2Vec2 y;
+ b2Vec2 deltaX(0.5625f, 1.25f);
+ b2Vec2 deltaY(1.125f, 0.0f);
+
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ y = x;
+
+ for (int32 j = i; j < e_count; ++j)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = y;
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 5.0f);
+
+ y += deltaY;
+ }
+
+ x += deltaX;
+ }
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree;
+
+ //if (m_stepCount == 400)
+ //{
+ // tree->RebuildBottomUp();
+ //}
+ }
+
+ static Test* Create()
+ {
+ return new Pyramid;
+ }
+};
+
+static int testIndex = RegisterTest("Stacking", "Pyramid", Pyramid::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/ray_cast.cpp b/Client/ThirdParty/Box2D/testbed/tests/ray_cast.cpp
new file mode 100644
index 0000000..c3c648e
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/ray_cast.cpp
@@ -0,0 +1,479 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+#include "imgui/imgui.h"
+
+enum
+{
+ e_maxBodies = 256
+};
+
+// This test demonstrates how to use the world ray-cast feature.
+// NOTE: we are intentionally filtering one of the polygons, therefore
+// the ray will always miss one type of polygon.
+
+// This callback finds the closest hit. Polygon 0 is filtered.
+class RayCastClosestCallback : public b2RayCastCallback
+{
+public:
+ RayCastClosestCallback()
+ {
+ m_hit = false;
+ }
+
+ float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override
+ {
+ uintptr_t index = fixture->GetUserData().pointer;
+ if (index == 1)
+ {
+ // By returning -1, we instruct the calling code to ignore this fixture and
+ // continue the ray-cast to the next fixture.
+ return -1.0f;
+ }
+
+ m_hit = true;
+ m_point = point;
+ m_normal = normal;
+
+ // By returning the current fraction, we instruct the calling code to clip the ray and
+ // continue the ray-cast to the next fixture. WARNING: do not assume that fixtures
+ // are reported in order. However, by clipping, we can always get the closest fixture.
+ return fraction;
+ }
+
+ bool m_hit;
+ b2Vec2 m_point;
+ b2Vec2 m_normal;
+};
+
+// This callback finds any hit. Polygon 0 is filtered. For this type of query we are usually
+// just checking for obstruction, so the actual fixture and hit point are irrelevant.
+class RayCastAnyCallback : public b2RayCastCallback
+{
+public:
+ RayCastAnyCallback()
+ {
+ m_hit = false;
+ }
+
+ float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float) override
+ {
+ uintptr_t index = fixture->GetUserData().pointer;
+ if (index == 1)
+ {
+ // By returning -1, we instruct the calling code to ignore this fixture and
+ // continue the ray-cast to the next fixture.
+ return -1.0f;
+ }
+
+ m_hit = true;
+ m_point = point;
+ m_normal = normal;
+
+ // At this point we have a hit, so we know the ray is obstructed.
+ // By returning 0, we instruct the calling code to terminate the ray-cast.
+ return 0.0f;
+ }
+
+ bool m_hit;
+ b2Vec2 m_point;
+ b2Vec2 m_normal;
+};
+
+// This ray cast collects multiple hits along the ray. Polygon 0 is filtered.
+// The fixtures are not necessary reported in order, so we might not capture
+// the closest fixture.
+class RayCastMultipleCallback : public b2RayCastCallback
+{
+public:
+ enum
+ {
+ e_maxCount = 3
+ };
+
+ RayCastMultipleCallback()
+ {
+ m_count = 0;
+ }
+
+ float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float) override
+ {
+ uintptr_t index = fixture->GetUserData().pointer;
+ if (index == 1)
+ {
+ // By returning -1, we instruct the calling code to ignore this fixture and
+ // continue the ray-cast to the next fixture.
+ return -1.0f;
+ }
+
+ b2Assert(m_count < e_maxCount);
+
+ m_points[m_count] = point;
+ m_normals[m_count] = normal;
+ ++m_count;
+
+ if (m_count == e_maxCount)
+ {
+ // At this point the buffer is full.
+ // By returning 0, we instruct the calling code to terminate the ray-cast.
+ return 0.0f;
+ }
+
+ // By returning 1, we instruct the caller to continue without clipping the ray.
+ return 1.0f;
+ }
+
+ b2Vec2 m_points[e_maxCount];
+ b2Vec2 m_normals[e_maxCount];
+ int32 m_count;
+};
+
+
+class RayCast : public Test
+{
+public:
+
+ enum Mode
+ {
+ e_any = 0,
+ e_closest = 1,
+ e_multiple = 2
+ };
+
+ RayCast()
+ {
+ // Ground body
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.5f, 0.0f);
+ vertices[1].Set(0.5f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+ m_polygons[0].Set(vertices, 3);
+ }
+
+ {
+ b2Vec2 vertices[3];
+ vertices[0].Set(-0.1f, 0.0f);
+ vertices[1].Set(0.1f, 0.0f);
+ vertices[2].Set(0.0f, 1.5f);
+ m_polygons[1].Set(vertices, 3);
+ }
+
+ {
+ float w = 1.0f;
+ float b = w / (2.0f + b2Sqrt(2.0f));
+ float s = b2Sqrt(2.0f) * b;
+
+ b2Vec2 vertices[8];
+ vertices[0].Set(0.5f * s, 0.0f);
+ vertices[1].Set(0.5f * w, b);
+ vertices[2].Set(0.5f * w, b + s);
+ vertices[3].Set(0.5f * s, w);
+ vertices[4].Set(-0.5f * s, w);
+ vertices[5].Set(-0.5f * w, b + s);
+ vertices[6].Set(-0.5f * w, b);
+ vertices[7].Set(-0.5f * s, 0.0f);
+
+ m_polygons[2].Set(vertices, 8);
+ }
+
+ {
+ m_polygons[3].SetAsBox(0.5f, 0.5f);
+ }
+
+ {
+ m_circle.m_radius = 0.5f;
+ }
+
+ {
+ m_edge.SetTwoSided(b2Vec2(-1.0f, 0.0f), b2Vec2(1.0f, 0.0f));
+ }
+
+ m_bodyIndex = 0;
+ memset(m_bodies, 0, sizeof(m_bodies));
+
+ m_degrees = 0.0f;
+
+ m_mode = e_closest;
+ }
+
+ void Create(int32 index)
+ {
+ if (m_bodies[m_bodyIndex] != NULL)
+ {
+ m_world->DestroyBody(m_bodies[m_bodyIndex]);
+ m_bodies[m_bodyIndex] = NULL;
+ }
+
+ b2BodyDef bd;
+
+ float x = RandomFloat(-10.0f, 10.0f);
+ float y = RandomFloat(0.0f, 20.0f);
+ bd.position.Set(x, y);
+ bd.angle = RandomFloat(-b2_pi, b2_pi);
+
+ if (index == 4)
+ {
+ bd.angularDamping = 0.02f;
+ }
+
+ m_bodies[m_bodyIndex] = m_world->CreateBody(&bd);
+
+ if (index < 4)
+ {
+ b2FixtureDef fd;
+ fd.shape = m_polygons + index;
+ fd.friction = 0.3f;
+ fd.userData.pointer = index + 1;
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+ else if (index < 5)
+ {
+ b2FixtureDef fd;
+ fd.shape = &m_circle;
+ fd.friction = 0.3f;
+ fd.userData.pointer = index + 1;
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = &m_edge;
+ fd.friction = 0.3f;
+ fd.userData.pointer = index + 1;
+
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
+
+ m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies;
+ }
+
+ void DestroyBody()
+ {
+ for (int32 i = 0; i < e_maxBodies; ++i)
+ {
+ if (m_bodies[i] != NULL)
+ {
+ m_world->DestroyBody(m_bodies[i]);
+ m_bodies[i] = NULL;
+ return;
+ }
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(210.0f, 285.0f));
+ ImGui::Begin("Ray-cast Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::Button("Shape 1"))
+ {
+ Create(0);
+ }
+
+ if (ImGui::Button("Shape 2"))
+ {
+ Create(1);
+ }
+
+ if (ImGui::Button("Shape 3"))
+ {
+ Create(2);
+ }
+
+ if (ImGui::Button("Shape 4"))
+ {
+ Create(3);
+ }
+
+ if (ImGui::Button("Shape 5"))
+ {
+ Create(4);
+ }
+
+ if (ImGui::Button("Shape 6"))
+ {
+ Create(5);
+ }
+
+ if (ImGui::Button("Destroy Shape"))
+ {
+ DestroyBody();
+ }
+
+ ImGui::RadioButton("Any", &m_mode, e_any);
+ ImGui::RadioButton("Closest", &m_mode, e_closest);
+ ImGui::RadioButton("Multiple", &m_mode, e_multiple);
+
+ ImGui::SliderFloat("Angle", &m_degrees, 0.0f, 360.0f, "%.0f");
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ g_debugDraw.DrawString(5, m_textLine, "Shape 1 is intentionally ignored by the ray");
+ m_textLine += m_textIncrement;
+ switch (m_mode)
+ {
+ case e_closest:
+ g_debugDraw.DrawString(5, m_textLine, "Ray-cast mode: closest - find closest fixture along the ray");
+ break;
+
+ case e_any:
+ g_debugDraw.DrawString(5, m_textLine, "Ray-cast mode: any - check for obstruction");
+ break;
+
+ case e_multiple:
+ g_debugDraw.DrawString(5, m_textLine, "Ray-cast mode: multiple - gather multiple fixtures");
+ break;
+ }
+
+ m_textLine += m_textIncrement;
+
+ float angle = b2_pi * m_degrees / 180.0f;
+ float L = 11.0f;
+ b2Vec2 point1(0.0f, 10.0f);
+ b2Vec2 d(L * cosf(angle), L * sinf(angle));
+ b2Vec2 point2 = point1 + d;
+
+ if (m_mode == e_closest)
+ {
+ RayCastClosestCallback callback;
+ m_world->RayCast(&callback, point1, point2);
+
+ if (callback.m_hit)
+ {
+ g_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f));
+ g_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f));
+ b2Vec2 head = callback.m_point + 0.5f * callback.m_normal;
+ g_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f));
+ }
+ else
+ {
+ g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f));
+ }
+ }
+ else if (m_mode == e_any)
+ {
+ RayCastAnyCallback callback;
+ m_world->RayCast(&callback, point1, point2);
+
+ if (callback.m_hit)
+ {
+ g_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f));
+ g_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f));
+ b2Vec2 head = callback.m_point + 0.5f * callback.m_normal;
+ g_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f));
+ }
+ else
+ {
+ g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f));
+ }
+ }
+ else if (m_mode == e_multiple)
+ {
+ RayCastMultipleCallback callback;
+ m_world->RayCast(&callback, point1, point2);
+ g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f));
+
+ for (int32 i = 0; i < callback.m_count; ++i)
+ {
+ b2Vec2 p = callback.m_points[i];
+ b2Vec2 n = callback.m_normals[i];
+ g_debugDraw.DrawPoint(p, 5.0f, b2Color(0.4f, 0.9f, 0.4f));
+ g_debugDraw.DrawSegment(point1, p, b2Color(0.8f, 0.8f, 0.8f));
+ b2Vec2 head = p + 0.5f * n;
+ g_debugDraw.DrawSegment(p, head, b2Color(0.9f, 0.9f, 0.4f));
+ }
+ }
+
+#if 0
+ // This case was failing.
+ {
+ b2Vec2 vertices[4];
+ //vertices[0].Set(-22.875f, -3.0f);
+ //vertices[1].Set(22.875f, -3.0f);
+ //vertices[2].Set(22.875f, 3.0f);
+ //vertices[3].Set(-22.875f, 3.0f);
+
+ b2PolygonShape shape;
+ //shape.Set(vertices, 4);
+ shape.SetAsBox(22.875f, 3.0f);
+
+ b2RayCastInput input;
+ input.p1.Set(10.2725f,1.71372f);
+ input.p2.Set(10.2353f,2.21807f);
+ //input.maxFraction = 0.567623f;
+ input.maxFraction = 0.56762173f;
+
+ b2Transform xf;
+ xf.SetIdentity();
+ xf.position.Set(23.0f, 5.0f);
+
+ b2RayCastOutput output;
+ bool hit;
+ hit = shape.RayCast(&output, input, xf);
+ hit = false;
+
+ b2Color color(1.0f, 1.0f, 1.0f);
+ b2Vec2 vs[4];
+ for (int32 i = 0; i < 4; ++i)
+ {
+ vs[i] = b2Mul(xf, shape.m_vertices[i]);
+ }
+
+ g_debugDraw.DrawPolygon(vs, 4, color);
+ g_debugDraw.DrawSegment(input.p1, input.p2, color);
+ }
+#endif
+ }
+
+ static Test* Create()
+ {
+ return new RayCast;
+ }
+
+ int32 m_bodyIndex;
+ b2Body* m_bodies[e_maxBodies];
+ b2PolygonShape m_polygons[4];
+ b2CircleShape m_circle;
+ b2EdgeShape m_edge;
+ float m_degrees;
+ int32 m_mode;
+};
+
+static int testIndex = RegisterTest("Collision", "Ray Cast", RayCast::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/restitution.cpp b/Client/ThirdParty/Box2D/testbed/tests/restitution.cpp
new file mode 100644
index 0000000..7772c62
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/restitution.cpp
@@ -0,0 +1,79 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// Note: even with a restitution of 1.0, there is some energy change
+// due to position correction.
+class Restitution : public Test
+{
+public:
+
+ Restitution()
+ {
+ const float threshold = 10.0f;
+
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.restitutionThreshold = threshold;
+ ground->CreateFixture(&fd);
+ }
+
+ {
+ b2CircleShape shape;
+ shape.m_radius = 1.0f;
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 1.0f;
+
+ float restitution[7] = { 0.0f, 0.1f, 0.3f, 0.5f, 0.75f, 0.9f, 1.0f };
+
+ for (int32 i = 0; i < 7; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-10.0f + 3.0f * i, 20.0f);
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ fd.restitution = restitution[i];
+ fd.restitutionThreshold = threshold;
+ body->CreateFixture(&fd);
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Restitution;
+ }
+};
+
+static int testIndex = RegisterTest("Forces", "Restitution", Restitution::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/revolute_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/revolute_joint.cpp
new file mode 100644
index 0000000..a67fea6
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/revolute_joint.cpp
@@ -0,0 +1,162 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+#include "imgui/imgui.h"
+
+class RevoluteJoint : public Test
+{
+public:
+ RevoluteJoint()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ //fd.filter.categoryBits = 2;
+
+ ground->CreateFixture(&fd);
+ }
+
+ m_enableLimit = true;
+ m_enableMotor = false;
+ m_motorSpeed = 1.0f;
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.25f, 3.0f, b2Vec2(0.0f, 3.0f), 0.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-10.0f, 20.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 5.0f);
+
+ b2RevoluteJointDef jd;
+ jd.Initialize(ground, body, b2Vec2(-10.0f, 20.5f));
+ jd.motorSpeed = m_motorSpeed;
+ jd.maxMotorTorque = 10000.0f;
+ jd.enableMotor = m_enableMotor;
+ jd.lowerAngle = -0.25f * b2_pi;
+ jd.upperAngle = 0.5f * b2_pi;
+ jd.enableLimit = m_enableLimit;
+
+ m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
+ }
+
+ {
+ b2CircleShape circle_shape;
+ circle_shape.m_radius = 2.0f;
+
+ b2BodyDef circle_bd;
+ circle_bd.type = b2_dynamicBody;
+ circle_bd.position.Set(5.0f, 30.0f);
+
+ b2FixtureDef fd;
+ fd.density = 5.0f;
+ fd.filter.maskBits = 1;
+ fd.shape = &circle_shape;
+
+ m_ball = m_world->CreateBody(&circle_bd);
+ m_ball->CreateFixture(&fd);
+
+ b2PolygonShape polygon_shape;
+ polygon_shape.SetAsBox(10.0f, 0.5f, b2Vec2 (-10.0f, 0.0f), 0.0f);
+
+ b2BodyDef polygon_bd;
+ polygon_bd.position.Set(20.0f, 10.0f);
+ polygon_bd.type = b2_dynamicBody;
+ polygon_bd.bullet = true;
+ b2Body* polygon_body = m_world->CreateBody(&polygon_bd);
+ polygon_body->CreateFixture(&polygon_shape, 2.0f);
+
+ b2RevoluteJointDef jd;
+ jd.Initialize(ground, polygon_body, b2Vec2(19.0f, 10.0f));
+ jd.lowerAngle = -0.25f * b2_pi;
+ jd.upperAngle = 0.0f * b2_pi;
+ jd.enableLimit = true;
+ jd.enableMotor = true;
+ jd.motorSpeed = 0.0f;
+ jd.maxMotorTorque = 10000.0f;
+
+ m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f));
+ ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::Checkbox("Limit", &m_enableLimit))
+ {
+ m_joint1->EnableLimit(m_enableLimit);
+ }
+
+ if (ImGui::Checkbox("Motor", &m_enableMotor))
+ {
+ m_joint1->EnableMotor(m_enableMotor);
+ }
+
+ if (ImGui::SliderFloat("Speed", &m_motorSpeed, -20.0f, 20.0f, "%.0f"))
+ {
+ m_joint1->SetMotorSpeed(m_motorSpeed);
+ }
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ float torque1 = m_joint1->GetMotorTorque(settings.m_hertz);
+ g_debugDraw.DrawString(5, m_textLine, "Motor Torque 1= %4.0f", torque1);
+ m_textLine += m_textIncrement;
+
+ float torque2 = m_joint2->GetMotorTorque(settings.m_hertz);
+ g_debugDraw.DrawString(5, m_textLine, "Motor Torque 2= %4.0f", torque2);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new RevoluteJoint;
+ }
+
+ b2Body* m_ball;
+ b2RevoluteJoint* m_joint1;
+ b2RevoluteJoint* m_joint2;
+ float m_motorSpeed;
+ bool m_enableMotor;
+ bool m_enableLimit;
+};
+
+static int testIndex = RegisterTest("Joints", "Revolute", RevoluteJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/rope.cpp b/Client/ThirdParty/Box2D/testbed/tests/rope.cpp
new file mode 100644
index 0000000..e4bf5d2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/rope.cpp
@@ -0,0 +1,286 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+#include "box2d/b2_rope.h"
+#include "imgui/imgui.h"
+
+///
+class Rope : public Test
+{
+public:
+ Rope()
+ {
+ const int32 N = 20;
+ const float L = 0.5f;
+ b2Vec2 vertices[N];
+ float masses[N];
+
+ for (int32 i = 0; i < N; ++i)
+ {
+ vertices[i].Set(0.0f, L * (N - i));
+ masses[i] = 1.0f;
+ }
+ masses[0] = 0.0f;
+ masses[1] = 0.0f;
+
+ m_tuning1.bendHertz = 30.0f;
+ m_tuning1.bendDamping = 4.0f;
+ m_tuning1.bendStiffness = 1.0f;
+ m_tuning1.bendingModel = b2_pbdTriangleBendingModel;
+ m_tuning1.isometric = true;
+
+ m_tuning1.stretchHertz = 30.0f;
+ m_tuning1.stretchDamping = 4.0f;
+ m_tuning1.stretchStiffness = 1.0f;
+ m_tuning1.stretchingModel = b2_pbdStretchingModel;
+
+ m_tuning2.bendHertz = 30.0f;
+ m_tuning2.bendDamping = 0.7f;
+ m_tuning2.bendStiffness = 1.0f;
+ m_tuning2.bendingModel = b2_pbdHeightBendingModel;
+ m_tuning2.isometric = true;
+
+ m_tuning2.stretchHertz = 30.0f;
+ m_tuning2.stretchDamping = 1.0f;
+ m_tuning2.stretchStiffness = 1.0f;
+ m_tuning2.stretchingModel = b2_pbdStretchingModel;
+
+ m_position1.Set(-5.0f, 15.0f);
+ m_position2.Set(5.0f, 15.0f);
+
+ b2RopeDef def;
+ def.vertices = vertices;
+ def.count = N;
+ def.gravity.Set(0.0f, -10.0f);
+ def.masses = masses;
+
+ def.position = m_position1;
+ def.tuning = m_tuning1;
+ m_rope1.Create(def);
+
+ def.position = m_position2;
+ def.tuning = m_tuning2;
+ m_rope2.Create(def);
+
+ m_iterations1 = 8;
+ m_iterations2 = 8;
+
+ m_speed = 10.0f;
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 700.0f));
+ ImGui::Begin("Tuning", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ ImGui::Separator();
+
+ ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
+
+ const ImGuiComboFlags comboFlags = 0;
+ const char* bendModels[] = { "Spring", "PBD Ang", "XPBD Ang", "PBD Dist", "PBD Height", "PBD Triangle" };
+ const char* stretchModels[] = { "PBD", "XPBD" };
+
+ ImGui::Text("Rope 1");
+ static int bendModel1 = m_tuning1.bendingModel;
+ if (ImGui::BeginCombo("Bend Model##1", bendModels[bendModel1], comboFlags))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(bendModels); ++i)
+ {
+ bool isSelected = (bendModel1 == i);
+ if (ImGui::Selectable(bendModels[i], isSelected))
+ {
+ bendModel1 = i;
+ m_tuning1.bendingModel = b2BendingModel(i);
+ }
+
+ if (isSelected)
+ {
+ ImGui::SetItemDefaultFocus();
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ ImGui::SliderFloat("Damping##B1", &m_tuning1.bendDamping, 0.0f, 4.0f, "%.1f");
+ ImGui::SliderFloat("Hertz##B1", &m_tuning1.bendHertz, 0.0f, 60.0f, "%.0f");
+ ImGui::SliderFloat("Stiffness##B1", &m_tuning1.bendStiffness, 0.0f, 1.0f, "%.1f");
+
+ ImGui::Checkbox("Isometric##1", &m_tuning1.isometric);
+ ImGui::Checkbox("Fixed Mass##1", &m_tuning1.fixedEffectiveMass);
+ ImGui::Checkbox("Warm Start##1", &m_tuning1.warmStart);
+
+ static int stretchModel1 = m_tuning1.stretchingModel;
+ if (ImGui::BeginCombo("Stretch Model##1", stretchModels[stretchModel1], comboFlags))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(stretchModels); ++i)
+ {
+ bool isSelected = (stretchModel1 == i);
+ if (ImGui::Selectable(stretchModels[i], isSelected))
+ {
+ stretchModel1 = i;
+ m_tuning1.stretchingModel = b2StretchingModel(i);
+ }
+
+ if (isSelected)
+ {
+ ImGui::SetItemDefaultFocus();
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ ImGui::SliderFloat("Damping##S1", &m_tuning1.stretchDamping, 0.0f, 4.0f, "%.1f");
+ ImGui::SliderFloat("Hertz##S1", &m_tuning1.stretchHertz, 0.0f, 60.0f, "%.0f");
+ ImGui::SliderFloat("Stiffness##S1", &m_tuning1.stretchStiffness, 0.0f, 1.0f, "%.1f");
+
+ ImGui::SliderInt("Iterations##1", &m_iterations1, 1, 100, "%d");
+
+ ImGui::Separator();
+
+ ImGui::Text("Rope 2");
+ static int bendModel2 = m_tuning2.bendingModel;
+ if (ImGui::BeginCombo("Bend Model##2", bendModels[bendModel2], comboFlags))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(bendModels); ++i)
+ {
+ bool isSelected = (bendModel2 == i);
+ if (ImGui::Selectable(bendModels[i], isSelected))
+ {
+ bendModel2 = i;
+ m_tuning2.bendingModel = b2BendingModel(i);
+ }
+
+ if (isSelected)
+ {
+ ImGui::SetItemDefaultFocus();
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ ImGui::SliderFloat("Damping##B2", &m_tuning2.bendDamping, 0.0f, 4.0f, "%.1f");
+ ImGui::SliderFloat("Hertz##B2", &m_tuning2.bendHertz, 0.0f, 60.0f, "%.0f");
+ ImGui::SliderFloat("Stiffness##B2", &m_tuning2.bendStiffness, 0.0f, 1.0f, "%.1f");
+
+ ImGui::Checkbox("Isometric##2", &m_tuning2.isometric);
+ ImGui::Checkbox("Fixed Mass##2", &m_tuning2.fixedEffectiveMass);
+ ImGui::Checkbox("Warm Start##2", &m_tuning2.warmStart);
+
+ static int stretchModel2 = m_tuning2.stretchingModel;
+ if (ImGui::BeginCombo("Stretch Model##2", stretchModels[stretchModel2], comboFlags))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(stretchModels); ++i)
+ {
+ bool isSelected = (stretchModel2 == i);
+ if (ImGui::Selectable(stretchModels[i], isSelected))
+ {
+ stretchModel2 = i;
+ m_tuning2.stretchingModel = b2StretchingModel(i);
+ }
+
+ if (isSelected)
+ {
+ ImGui::SetItemDefaultFocus();
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ ImGui::SliderFloat("Damping##S2", &m_tuning2.stretchDamping, 0.0f, 4.0f, "%.1f");
+ ImGui::SliderFloat("Hertz##S2", &m_tuning2.stretchHertz, 0.0f, 60.0f, "%.0f");
+ ImGui::SliderFloat("Stiffness##S2", &m_tuning2.stretchStiffness, 0.0f, 1.0f, "%.1f");
+
+ ImGui::SliderInt("Iterations##2", &m_iterations2, 1, 100, "%d");
+
+ ImGui::Separator();
+
+ ImGui::SliderFloat("Speed", &m_speed, 10.0f, 100.0f, "%.0f");
+
+ if (ImGui::Button("Reset"))
+ {
+ m_position1.Set(-5.0f, 15.0f);
+ m_position2.Set(5.0f, 15.0f);
+ m_rope1.Reset(m_position1);
+ m_rope2.Reset(m_position2);
+ }
+
+ ImGui::PopItemWidth();
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ float dt = settings.m_hertz > 0.0f ? 1.0f / settings.m_hertz : 0.0f;
+
+ if (settings.m_pause == 1 && settings.m_singleStep == 0)
+ {
+ dt = 0.0f;
+ }
+
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_COMMA) == GLFW_PRESS)
+ {
+ m_position1.x -= m_speed * dt;
+ m_position2.x -= m_speed * dt;
+ }
+
+ if (glfwGetKey(g_mainWindow, GLFW_KEY_PERIOD) == GLFW_PRESS)
+ {
+ m_position1.x += m_speed * dt;
+ m_position2.x += m_speed * dt;
+ }
+
+ m_rope1.SetTuning(m_tuning1);
+ m_rope2.SetTuning(m_tuning2);
+ m_rope1.Step(dt, m_iterations1, m_position1);
+ m_rope2.Step(dt, m_iterations2, m_position2);
+
+ Test::Step(settings);
+
+ m_rope1.Draw(&g_debugDraw);
+ m_rope2.Draw(&g_debugDraw);
+
+ g_debugDraw.DrawString(5, m_textLine, "Press comma and period to move left and right");
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new Rope;
+ }
+
+ b2Rope m_rope1;
+ b2Rope m_rope2;
+ b2RopeTuning m_tuning1;
+ b2RopeTuning m_tuning2;
+ int32 m_iterations1;
+ int32 m_iterations2;
+ b2Vec2 m_position1;
+ b2Vec2 m_position2;
+ float m_speed;
+};
+
+static int testIndex = RegisterTest("Rope", "Bending", Rope::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/sensor.cpp b/Client/ThirdParty/Box2D/testbed/tests/sensor.cpp
new file mode 100644
index 0000000..613a0e9
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/sensor.cpp
@@ -0,0 +1,195 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "imgui/imgui.h"
+
+// This shows how to use sensor shapes. Sensors don't have collision, but report overlap events.
+class Sensors : public Test
+{
+public:
+
+ enum
+ {
+ e_count = 7
+ };
+
+ Sensors()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ {
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+#if 0
+ {
+ b2FixtureDef sd;
+ sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f);
+ sd.isSensor = true;
+ m_sensor = ground->CreateFixture(&sd);
+ }
+#else
+ {
+ b2CircleShape shape;
+ shape.m_radius = 5.0f;
+ shape.m_p.Set(0.0f, 10.0f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.isSensor = true;
+ m_sensor = ground->CreateFixture(&fd);
+ }
+#endif
+ }
+
+ {
+ b2CircleShape shape;
+ shape.m_radius = 1.0f;
+
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-10.0f + 3.0f * i, 20.0f);
+ bd.userData.pointer = i;
+
+ m_touching[i] = false;
+ m_bodies[i] = m_world->CreateBody(&bd);
+
+ m_bodies[i]->CreateFixture(&shape, 1.0f);
+ }
+ }
+
+ m_force = 100.0f;
+ }
+
+ // Implement contact listener.
+ void BeginContact(b2Contact* contact) override
+ {
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+
+ if (fixtureA == m_sensor)
+ {
+ uintptr_t index = fixtureB->GetBody()->GetUserData().pointer;
+ if (index < e_count)
+ {
+ m_touching[index] = true;
+ }
+ }
+
+ if (fixtureB == m_sensor)
+ {
+ uintptr_t index = fixtureA->GetBody()->GetUserData().pointer;
+ if (index < e_count)
+ {
+ m_touching[index] = true;
+ }
+ }
+ }
+
+ // Implement contact listener.
+ void EndContact(b2Contact* contact) override
+ {
+ b2Fixture* fixtureA = contact->GetFixtureA();
+ b2Fixture* fixtureB = contact->GetFixtureB();
+
+ if (fixtureA == m_sensor)
+ {
+ uintptr_t index = fixtureB->GetBody()->GetUserData().pointer;
+ if (index < e_count)
+ {
+ m_touching[index] = false;
+ }
+ }
+
+ if (fixtureB == m_sensor)
+ {
+ uintptr_t index = fixtureA->GetBody()->GetUserData().pointer;
+ if (index < e_count)
+ {
+ m_touching[index] = false;
+ }
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 60.0f));
+ ImGui::Begin("Sensor Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ ImGui::SliderFloat("Force", &m_force, 0.0f, 2000.0f, "%.0f");
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ // Traverse the contact results. Apply a force on shapes
+ // that overlap the sensor.
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ if (m_touching[i] == false)
+ {
+ continue;
+ }
+
+ b2Body* body = m_bodies[i];
+ b2Body* ground = m_sensor->GetBody();
+
+ b2CircleShape* circle = (b2CircleShape*)m_sensor->GetShape();
+ b2Vec2 center = ground->GetWorldPoint(circle->m_p);
+
+ b2Vec2 position = body->GetPosition();
+
+ b2Vec2 d = center - position;
+ if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON)
+ {
+ continue;
+ }
+
+ d.Normalize();
+ b2Vec2 F = m_force * d;
+ body->ApplyForce(F, position, false);
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Sensors;
+ }
+
+ b2Fixture* m_sensor;
+ b2Body* m_bodies[e_count];
+ float m_force;
+ bool m_touching[e_count];
+};
+
+static int testIndex = RegisterTest("Collision", "Sensors", Sensors::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/shape_cast.cpp b/Client/ThirdParty/Box2D/testbed/tests/shape_cast.cpp
new file mode 100644
index 0000000..85ce422
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/shape_cast.cpp
@@ -0,0 +1,193 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "box2d/b2_distance.h"
+
+class ShapeCast : public Test
+{
+public:
+ enum
+ {
+ e_vertexCount = 8
+ };
+
+ ShapeCast()
+ {
+#if 1
+ m_vAs[0].Set(-0.5f, 1.0f);
+ m_vAs[1].Set(0.5f, 1.0f);
+ m_vAs[2].Set(0.0f, 0.0f);
+ m_countA = 3;
+ m_radiusA = b2_polygonRadius;
+
+ m_vBs[0].Set(-0.5f, -0.5f);
+ m_vBs[1].Set(0.5f, -0.5f);
+ m_vBs[2].Set(0.5f, 0.5f);
+ m_vBs[3].Set(-0.5f, 0.5f);
+ m_countB = 4;
+ m_radiusB = b2_polygonRadius;
+
+ m_transformA.p.Set(0.0f, 0.25f);
+ m_transformA.q.SetIdentity();
+ m_transformB.p.Set(-4.0f, 0.0f);
+ m_transformB.q.SetIdentity();
+ m_translationB.Set(8.0f, 0.0f);
+#elif 0
+ m_vAs[0].Set(0.0f, 0.0f);
+ m_countA = 1;
+ m_radiusA = 0.5f;
+
+ m_vBs[0].Set(0.0f, 0.0f);
+ m_countB = 1;
+ m_radiusB = 0.5f;
+
+ m_transformA.p.Set(0.0f, 0.25f);
+ m_transformA.q.SetIdentity();
+ m_transformB.p.Set(-4.0f, 0.0f);
+ m_transformB.q.SetIdentity();
+ m_translationB.Set(8.0f, 0.0f);
+#else
+ m_vAs[0].Set(0.0f, 0.0f);
+ m_vAs[1].Set(2.0f, 0.0f);
+ m_countA = 2;
+ m_radiusA = b2_polygonRadius;
+
+ m_vBs[0].Set(0.0f, 0.0f);
+ m_countB = 1;
+ m_radiusB = 0.25f;
+
+ // Initial overlap
+ m_transformA.p.Set(0.0f, 0.0f);
+ m_transformA.q.SetIdentity();
+ m_transformB.p.Set(-0.244360745f, 0.05999358f);
+ m_transformB.q.SetIdentity();
+ m_translationB.Set(0.0f, 0.0399999991f);
+#endif
+ }
+
+ static Test* Create()
+ {
+ return new ShapeCast;
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ b2ShapeCastInput input;
+ input.proxyA.Set(m_vAs, m_countA, m_radiusA);
+ input.proxyB.Set(m_vBs, m_countB, m_radiusB);
+ input.transformA = m_transformA;
+ input.transformB = m_transformB;
+ input.translationB = m_translationB;
+
+ b2ShapeCastOutput output;
+ bool hit = b2ShapeCast(&output, &input);
+
+ b2Transform transformB2;
+ transformB2.q = m_transformB.q;
+ transformB2.p = m_transformB.p + output.lambda * input.translationB;
+
+ b2DistanceInput distanceInput;
+ distanceInput.proxyA.Set(m_vAs, m_countA, m_radiusA);
+ distanceInput.proxyB.Set(m_vBs, m_countB, m_radiusB);
+ distanceInput.transformA = m_transformA;
+ distanceInput.transformB = transformB2;
+ distanceInput.useRadii = false;
+ b2SimplexCache simplexCache;
+ simplexCache.count = 0;
+ b2DistanceOutput distanceOutput;
+
+ b2Distance(&distanceOutput, &simplexCache, &distanceInput);
+
+ g_debugDraw.DrawString(5, m_textLine, "hit = %s, iters = %d, lambda = %g, distance = %g",
+ hit ? "true" : "false", output.iterations, output.lambda, distanceOutput.distance);
+ m_textLine += m_textIncrement;
+
+ b2Vec2 vertices[b2_maxPolygonVertices];
+
+ for (int32 i = 0; i < m_countA; ++i)
+ {
+ vertices[i] = b2Mul(m_transformA, m_vAs[i]);
+ }
+
+ if (m_countA == 1)
+ {
+ g_debugDraw.DrawCircle(vertices[0], m_radiusA, b2Color(0.9f, 0.9f, 0.9f));
+ }
+ else
+ {
+ g_debugDraw.DrawPolygon(vertices, m_countA, b2Color(0.9f, 0.9f, 0.9f));
+ }
+
+ for (int32 i = 0; i < m_countB; ++i)
+ {
+ vertices[i] = b2Mul(m_transformB, m_vBs[i]);
+ }
+
+ if (m_countB == 1)
+ {
+ g_debugDraw.DrawCircle(vertices[0], m_radiusB, b2Color(0.5f, 0.9f, 0.5f));
+ }
+ else
+ {
+ g_debugDraw.DrawPolygon(vertices, m_countB, b2Color(0.5f, 0.9f, 0.5f));
+ }
+
+ for (int32 i = 0; i < m_countB; ++i)
+ {
+ vertices[i] = b2Mul(transformB2, m_vBs[i]);
+ }
+
+ if (m_countB == 1)
+ {
+ g_debugDraw.DrawCircle(vertices[0], m_radiusB, b2Color(0.5f, 0.7f, 0.9f));
+ }
+ else
+ {
+ g_debugDraw.DrawPolygon(vertices, m_countB, b2Color(0.5f, 0.7f, 0.9f));
+ }
+
+ if (hit)
+ {
+ b2Vec2 p1 = output.point;
+ g_debugDraw.DrawPoint(p1, 10.0f, b2Color(0.9f, 0.3f, 0.3f));
+ b2Vec2 p2 = p1 + output.normal;
+ g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.3f, 0.3f));
+ }
+ }
+
+ b2Vec2 m_vAs[b2_maxPolygonVertices];
+ int32 m_countA;
+ float m_radiusA;
+
+ b2Vec2 m_vBs[b2_maxPolygonVertices];
+ int32 m_countB;
+ float m_radiusB;
+
+ b2Transform m_transformA;
+ b2Transform m_transformB;
+ b2Vec2 m_translationB;
+};
+
+static int testIndex = RegisterTest("Collision", "Shape Cast", ShapeCast::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/shape_editing.cpp b/Client/ThirdParty/Box2D/testbed/tests/shape_editing.cpp
new file mode 100644
index 0000000..307f295
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/shape_editing.cpp
@@ -0,0 +1,108 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class ShapeEditing : public Test
+{
+public:
+
+ ShapeEditing()
+ {
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 10.0f);
+ m_body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(4.0f, 4.0f, b2Vec2(0.0f, 0.0f), 0.0f);
+ m_fixture1 = m_body->CreateFixture(&shape, 10.0f);
+
+ m_fixture2 = NULL;
+
+ m_sensor = false;
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_C:
+ if (m_fixture2 == NULL)
+ {
+ b2CircleShape shape;
+ shape.m_radius = 3.0f;
+ shape.m_p.Set(0.5f, -4.0f);
+ m_fixture2 = m_body->CreateFixture(&shape, 10.0f);
+ m_body->SetAwake(true);
+ }
+ break;
+
+ case GLFW_KEY_D:
+ if (m_fixture2 != NULL)
+ {
+ m_body->DestroyFixture(m_fixture2);
+ m_fixture2 = NULL;
+ m_body->SetAwake(true);
+ }
+ break;
+
+ case GLFW_KEY_S:
+ if (m_fixture2 != NULL)
+ {
+ m_sensor = !m_sensor;
+ m_fixture2->SetSensor(m_sensor);
+ }
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape.");
+ m_textLine += m_textIncrement;
+ g_debugDraw.DrawString(5, m_textLine, "sensor = %d", m_sensor);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new ShapeEditing;
+ }
+
+ b2Body* m_body;
+ b2Fixture* m_fixture1;
+ b2Fixture* m_fixture2;
+ bool m_sensor;
+};
+
+static int testIndex = RegisterTest("Examples", "Shape Editing", ShapeEditing::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/skier.cpp b/Client/ThirdParty/Box2D/testbed/tests/skier.cpp
new file mode 100644
index 0000000..8604363
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/skier.cpp
@@ -0,0 +1,150 @@
+/*
+Test case for collision/jerking issue.
+*/
+
+#include "test.h"
+
+#include <vector>
+#include <iostream>
+
+class Skier : public Test
+{
+public:
+ Skier()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ float const PlatformWidth = 8.0f;
+
+ /*
+ First angle is from the horizontal and should be negative for a downward slope.
+ Second angle is relative to the preceding slope, and should be positive, creating a kind of
+ loose 'Z'-shape from the 3 edges.
+ If A1 = -10, then A2 <= ~1.5 will result in the collision glitch.
+ If A1 = -30, then A2 <= ~10.0 will result in the glitch.
+ */
+ float const Angle1Degrees = -30.0f;
+ float const Angle2Degrees = 10.0f;
+
+ /*
+ The larger the value of SlopeLength, the less likely the glitch will show up.
+ */
+ float const SlopeLength = 2.0f;
+
+ float const SurfaceFriction = 0.2f;
+
+ // Convert to radians
+ float const Slope1Incline = -Angle1Degrees * b2_pi / 180.0f;
+ float const Slope2Incline = Slope1Incline - Angle2Degrees * b2_pi / 180.0f;
+ //
+
+ m_platform_width = PlatformWidth;
+
+ // Horizontal platform
+ b2Vec2 v1(-PlatformWidth, 0.0f);
+ b2Vec2 v2(0.0f, 0.0f);
+ b2Vec2 v3(SlopeLength * cosf(Slope1Incline), -SlopeLength * sinf(Slope1Incline));
+ b2Vec2 v4(v3.x + SlopeLength * cosf(Slope2Incline), v3.y - SlopeLength * sinf(Slope2Incline));
+ b2Vec2 v5(v4.x, v4.y - 1.0f);
+
+ b2Vec2 vertices[5] = { v5, v4, v3, v2, v1 };
+
+ b2ChainShape shape;
+ shape.CreateLoop(vertices, 5);
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 0.0f;
+ fd.friction = SurfaceFriction;
+
+ ground->CreateFixture(&fd);
+ }
+
+ {
+ float const BodyWidth = 1.0f;
+ float const BodyHeight = 2.5f;
+ float const SkiLength = 3.0f;
+
+ /*
+ Larger values for this seem to alleviate the issue to some extent.
+ */
+ float const SkiThickness = 0.3f;
+
+ float const SkiFriction = 0.0f;
+ float const SkiRestitution = 0.15f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ float initial_y = BodyHeight / 2 + SkiThickness;
+ bd.position.Set(-m_platform_width / 2, initial_y);
+
+ b2Body* skier = m_world->CreateBody(&bd);
+
+ b2PolygonShape ski;
+ b2Vec2 verts[4];
+ verts[0].Set(-SkiLength / 2 - SkiThickness, -BodyHeight / 2);
+ verts[1].Set(-SkiLength / 2, -BodyHeight / 2 - SkiThickness);
+ verts[2].Set(SkiLength / 2, -BodyHeight / 2 - SkiThickness);
+ verts[3].Set(SkiLength / 2 + SkiThickness, -BodyHeight / 2);
+ ski.Set(verts, 4);
+
+ b2FixtureDef fd;
+ fd.density = 1.0f;
+
+ fd.friction = SkiFriction;
+ fd.restitution = SkiRestitution;
+
+ fd.shape = &ski;
+ skier->CreateFixture(&fd);
+
+ skier->SetLinearVelocity(b2Vec2(0.5f, 0.0f));
+
+ m_skier = skier;
+ }
+
+ g_camera.m_center = b2Vec2(m_platform_width / 2.0f, 0.0f);
+ g_camera.m_zoom = 0.4f;
+ m_fixed_camera = true;
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_C:
+ m_fixed_camera = !m_fixed_camera;
+ if(m_fixed_camera)
+ {
+ g_camera.m_center = b2Vec2(m_platform_width / 2.0f, 0.0f);
+ }
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ g_debugDraw.DrawString(5, m_textLine, "Keys: c = Camera fixed/tracking");
+ m_textLine += m_textIncrement;
+
+ if(!m_fixed_camera)
+ {
+ g_camera.m_center = m_skier->GetPosition();
+ }
+
+ Test::Step(settings);
+ }
+
+ static Test* Create()
+ {
+ return new Skier;
+ }
+
+ b2Body* m_skier;
+ float m_platform_width;
+ bool m_fixed_camera;
+};
+
+static int testIndex = RegisterTest("Bugs", "Skier", Skier::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/slider_crank_1.cpp b/Client/ThirdParty/Box2D/testbed/tests/slider_crank_1.cpp
new file mode 100644
index 0000000..395b939
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/slider_crank_1.cpp
@@ -0,0 +1,106 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// A basic slider crank created for GDC tutorial: Understanding Constraints
+class SliderCrank1 : public Test
+{
+public:
+ SliderCrank1()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ bd.position.Set(0.0f, 17.0f);
+ ground = m_world->CreateBody(&bd);
+ }
+
+ {
+ b2Body* prevBody = ground;
+
+ // Define crank.
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(4.0f, 1.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-8.0f, 20.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(prevBody, body, b2Vec2(-12.0f, 20.0f));
+ m_world->CreateJoint(&rjd);
+
+ prevBody = body;
+ }
+
+ // Define connecting rod
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(8.0f, 1.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(4.0f, 20.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(prevBody, body, b2Vec2(-4.0f, 20.0f));
+ m_world->CreateJoint(&rjd);
+
+ prevBody = body;
+ }
+
+ // Define piston
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(3.0f, 3.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.fixedRotation = true;
+ bd.position.Set(12.0f, 20.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(prevBody, body, b2Vec2(12.0f, 20.0f));
+ m_world->CreateJoint(&rjd);
+
+ b2PrismaticJointDef pjd;
+ pjd.Initialize(ground, body, b2Vec2(12.0f, 17.0f), b2Vec2(1.0f, 0.0f));
+ m_world->CreateJoint(&pjd);
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new SliderCrank1;
+ }
+};
+
+static int testIndex = RegisterTest("Examples", "Slider Crank 1", SliderCrank1::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/slider_crank_2.cpp b/Client/ThirdParty/Box2D/testbed/tests/slider_crank_2.cpp
new file mode 100644
index 0000000..546d6a1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/slider_crank_2.cpp
@@ -0,0 +1,160 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+
+// A motor driven slider crank with joint friction.
+
+class SliderCrank2 : public Test
+{
+public:
+ SliderCrank2()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2Body* prevBody = ground;
+
+ // Define crank.
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 2.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 7.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(prevBody, body, b2Vec2(0.0f, 5.0f));
+ rjd.motorSpeed = 1.0f * b2_pi;
+ rjd.maxMotorTorque = 10000.0f;
+ rjd.enableMotor = true;
+ m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&rjd);
+
+ prevBody = body;
+ }
+
+ // Define follower.
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 4.0f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 13.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(prevBody, body, b2Vec2(0.0f, 9.0f));
+ rjd.enableMotor = false;
+ m_world->CreateJoint(&rjd);
+
+ prevBody = body;
+ }
+
+ // Define piston
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(1.5f, 1.5f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.fixedRotation = true;
+ bd.position.Set(0.0f, 17.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+
+ b2RevoluteJointDef rjd;
+ rjd.Initialize(prevBody, body, b2Vec2(0.0f, 17.0f));
+ m_world->CreateJoint(&rjd);
+
+ b2PrismaticJointDef pjd;
+ pjd.Initialize(ground, body, b2Vec2(0.0f, 17.0f), b2Vec2(0.0f, 1.0f));
+
+ pjd.maxMotorForce = 1000.0f;
+ pjd.enableMotor = true;
+
+ m_joint2 = (b2PrismaticJoint*)m_world->CreateJoint(&pjd);
+ }
+
+ // Create a payload
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(1.5f, 1.5f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 23.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 2.0f);
+ }
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_F:
+ m_joint2->EnableMotor(!m_joint2->IsMotorEnabled());
+ m_joint2->GetBodyB()->SetAwake(true);
+ break;
+
+ case GLFW_KEY_M:
+ m_joint1->EnableMotor(!m_joint1->IsMotorEnabled());
+ m_joint1->GetBodyB()->SetAwake(true);
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "Keys: (f) toggle friction, (m) toggle motor");
+ m_textLine += m_textIncrement;
+ float torque = m_joint1->GetMotorTorque(settings.m_hertz);
+ g_debugDraw.DrawString(5, m_textLine, "Motor Torque = %5.0f", (float) torque);
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new SliderCrank2;
+ }
+
+ b2RevoluteJoint* m_joint1;
+ b2PrismaticJoint* m_joint2;
+};
+
+static int testIndex = RegisterTest("Examples", "Slider Crank 2", SliderCrank2::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/theo_jansen.cpp b/Client/ThirdParty/Box2D/testbed/tests/theo_jansen.cpp
new file mode 100644
index 0000000..a3155ac
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/theo_jansen.cpp
@@ -0,0 +1,266 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// Inspired by a contribution from roman_m
+// Dimensions scooped from APE (http://www.cove.org/ape/index.htm)
+
+#include "test.h"
+
+class TheoJansen : public Test
+{
+public:
+
+ void CreateLeg(float s, const b2Vec2& wheelAnchor)
+ {
+ b2Vec2 p1(5.4f * s, -6.1f);
+ b2Vec2 p2(7.2f * s, -1.2f);
+ b2Vec2 p3(4.3f * s, -1.9f);
+ b2Vec2 p4(3.1f * s, 0.8f);
+ b2Vec2 p5(6.0f * s, 1.5f);
+ b2Vec2 p6(2.5f * s, 3.7f);
+
+ b2FixtureDef fd1, fd2;
+ fd1.filter.groupIndex = -1;
+ fd2.filter.groupIndex = -1;
+ fd1.density = 1.0f;
+ fd2.density = 1.0f;
+
+ b2PolygonShape poly1, poly2;
+
+ if (s > 0.0f)
+ {
+ b2Vec2 vertices[3];
+
+ vertices[0] = p1;
+ vertices[1] = p2;
+ vertices[2] = p3;
+ poly1.Set(vertices, 3);
+
+ vertices[0] = b2Vec2_zero;
+ vertices[1] = p5 - p4;
+ vertices[2] = p6 - p4;
+ poly2.Set(vertices, 3);
+ }
+ else
+ {
+ b2Vec2 vertices[3];
+
+ vertices[0] = p1;
+ vertices[1] = p3;
+ vertices[2] = p2;
+ poly1.Set(vertices, 3);
+
+ vertices[0] = b2Vec2_zero;
+ vertices[1] = p6 - p4;
+ vertices[2] = p5 - p4;
+ poly2.Set(vertices, 3);
+ }
+
+ fd1.shape = &poly1;
+ fd2.shape = &poly2;
+
+ b2BodyDef bd1, bd2;
+ bd1.type = b2_dynamicBody;
+ bd2.type = b2_dynamicBody;
+ bd1.position = m_offset;
+ bd2.position = p4 + m_offset;
+
+ bd1.angularDamping = 10.0f;
+ bd2.angularDamping = 10.0f;
+
+ b2Body* body1 = m_world->CreateBody(&bd1);
+ b2Body* body2 = m_world->CreateBody(&bd2);
+
+ body1->CreateFixture(&fd1);
+ body2->CreateFixture(&fd2);
+
+ {
+ b2DistanceJointDef jd;
+
+ // Using a soft distance constraint can reduce some jitter.
+ // It also makes the structure seem a bit more fluid by
+ // acting like a suspension system.
+ float dampingRatio = 0.5f;
+ float frequencyHz = 10.0f;
+
+ jd.Initialize(body1, body2, p2 + m_offset, p5 + m_offset);
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_world->CreateJoint(&jd);
+
+ jd.Initialize(body1, body2, p3 + m_offset, p4 + m_offset);
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_world->CreateJoint(&jd);
+
+ jd.Initialize(body1, m_wheel, p3 + m_offset, wheelAnchor + m_offset);
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_world->CreateJoint(&jd);
+
+ jd.Initialize(body2, m_wheel, p6 + m_offset, wheelAnchor + m_offset);
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_world->CreateJoint(&jd);
+ }
+
+ {
+ b2RevoluteJointDef jd;
+ jd.Initialize(body2, m_chassis, p4 + m_offset);
+ m_world->CreateJoint(&jd);
+ }
+ }
+
+ TheoJansen()
+ {
+ m_offset.Set(0.0f, 8.0f);
+ m_motorSpeed = 2.0f;
+ m_motorOn = true;
+ b2Vec2 pivot(0.0f, 0.8f);
+
+ // Ground
+ {
+ b2BodyDef bd;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(-50.0f, 10.0f));
+ ground->CreateFixture(&shape, 0.0f);
+
+ shape.SetTwoSided(b2Vec2(50.0f, 0.0f), b2Vec2(50.0f, 10.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ // Balls
+ for (int32 i = 0; i < 40; ++i)
+ {
+ b2CircleShape shape;
+ shape.m_radius = 0.25f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(-40.0f + 2.0f * i, 0.5f);
+
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 1.0f);
+ }
+
+ // Chassis
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(2.5f, 1.0f);
+
+ b2FixtureDef sd;
+ sd.density = 1.0f;
+ sd.shape = &shape;
+ sd.filter.groupIndex = -1;
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = pivot + m_offset;
+ m_chassis = m_world->CreateBody(&bd);
+ m_chassis->CreateFixture(&sd);
+ }
+
+ {
+ b2CircleShape shape;
+ shape.m_radius = 1.6f;
+
+ b2FixtureDef sd;
+ sd.density = 1.0f;
+ sd.shape = &shape;
+ sd.filter.groupIndex = -1;
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = pivot + m_offset;
+ m_wheel = m_world->CreateBody(&bd);
+ m_wheel->CreateFixture(&sd);
+ }
+
+ {
+ b2RevoluteJointDef jd;
+ jd.Initialize(m_wheel, m_chassis, pivot + m_offset);
+ jd.collideConnected = false;
+ jd.motorSpeed = m_motorSpeed;
+ jd.maxMotorTorque = 400.0f;
+ jd.enableMotor = m_motorOn;
+ m_motorJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
+ }
+
+ b2Vec2 wheelAnchor;
+
+ wheelAnchor = pivot + b2Vec2(0.0f, -0.8f);
+
+ CreateLeg(-1.0f, wheelAnchor);
+ CreateLeg(1.0f, wheelAnchor);
+
+ m_wheel->SetTransform(m_wheel->GetPosition(), 120.0f * b2_pi / 180.0f);
+ CreateLeg(-1.0f, wheelAnchor);
+ CreateLeg(1.0f, wheelAnchor);
+
+ m_wheel->SetTransform(m_wheel->GetPosition(), -120.0f * b2_pi / 180.0f);
+ CreateLeg(-1.0f, wheelAnchor);
+ CreateLeg(1.0f, wheelAnchor);
+ }
+
+ void Step(Settings& settings) override
+ {
+ g_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, toggle motor = m");
+ m_textLine += m_textIncrement;
+
+ Test::Step(settings);
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_A:
+ m_motorJoint->SetMotorSpeed(-m_motorSpeed);
+ break;
+
+ case GLFW_KEY_S:
+ m_motorJoint->SetMotorSpeed(0.0f);
+ break;
+
+ case GLFW_KEY_D:
+ m_motorJoint->SetMotorSpeed(m_motorSpeed);
+ break;
+
+ case GLFW_KEY_M:
+ m_motorJoint->EnableMotor(!m_motorJoint->IsMotorEnabled());
+ break;
+ }
+ }
+
+ static Test* Create()
+ {
+ return new TheoJansen;
+ }
+
+ b2Vec2 m_offset;
+ b2Body* m_chassis;
+ b2Body* m_wheel;
+ b2RevoluteJoint* m_motorJoint;
+ bool m_motorOn;
+ float m_motorSpeed;
+};
+
+static int testIndex = RegisterTest("Examples", "Theo Jansen", TheoJansen::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/tiles.cpp b/Client/ThirdParty/Box2D/testbed/tests/tiles.cpp
new file mode 100644
index 0000000..e6a4e56
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/tiles.cpp
@@ -0,0 +1,159 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+/// This stress tests the dynamic tree broad-phase. This also shows that tile
+/// based collision is _not_ smooth due to Box2D not knowing about adjacency.
+class Tiles : public Test
+{
+public:
+ enum
+ {
+ e_count = 20
+ };
+
+ Tiles()
+ {
+ m_fixtureCount = 0;
+ b2Timer timer;
+
+ {
+ float a = 0.5f;
+ b2BodyDef bd;
+ bd.position.y = -a;
+ b2Body* ground = m_world->CreateBody(&bd);
+
+#if 1
+ int32 N = 200;
+ int32 M = 10;
+ b2Vec2 position;
+ position.y = 0.0f;
+ for (int32 j = 0; j < M; ++j)
+ {
+ position.x = -N * a;
+ for (int32 i = 0; i < N; ++i)
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(a, a, position, 0.0f);
+ ground->CreateFixture(&shape, 0.0f);
+ ++m_fixtureCount;
+ position.x += 2.0f * a;
+ }
+ position.y -= 2.0f * a;
+ }
+#else
+ int32 N = 200;
+ int32 M = 10;
+ b2Vec2 position;
+ position.x = -N * a;
+ for (int32 i = 0; i < N; ++i)
+ {
+ position.y = 0.0f;
+ for (int32 j = 0; j < M; ++j)
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(a, a, position, 0.0f);
+ ground->CreateFixture(&shape, 0.0f);
+ position.y -= 2.0f * a;
+ }
+ position.x += 2.0f * a;
+ }
+#endif
+ }
+
+ {
+ float a = 0.5f;
+ b2PolygonShape shape;
+ shape.SetAsBox(a, a);
+
+ b2Vec2 x(-7.0f, 0.75f);
+ b2Vec2 y;
+ b2Vec2 deltaX(0.5625f, 1.25f);
+ b2Vec2 deltaY(1.125f, 0.0f);
+
+ for (int32 i = 0; i < e_count; ++i)
+ {
+ y = x;
+
+ for (int32 j = i; j < e_count; ++j)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position = y;
+
+ //if (i == 0 && j == 0)
+ //{
+ // bd.allowSleep = false;
+ //}
+ //else
+ //{
+ // bd.allowSleep = true;
+ //}
+
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 5.0f);
+ ++m_fixtureCount;
+ y += deltaY;
+ }
+
+ x += deltaX;
+ }
+ }
+
+ m_createTime = timer.GetMilliseconds();
+ }
+
+ void Step(Settings& settings) override
+ {
+ const b2ContactManager& cm = m_world->GetContactManager();
+ int32 height = cm.m_broadPhase.GetTreeHeight();
+ int32 leafCount = cm.m_broadPhase.GetProxyCount();
+ int32 minimumNodeCount = 2 * leafCount - 1;
+ float minimumHeight = ceilf(logf(float(minimumNodeCount)) / logf(2.0f));
+ g_debugDraw.DrawString(5, m_textLine, "dynamic tree height = %d, min = %d", height, int32(minimumHeight));
+ m_textLine += m_textIncrement;
+
+ Test::Step(settings);
+
+ g_debugDraw.DrawString(5, m_textLine, "create time = %6.2f ms, fixture count = %d",
+ m_createTime, m_fixtureCount);
+ m_textLine += m_textIncrement;
+
+ //b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree;
+
+ //if (m_stepCount == 400)
+ //{
+ // tree->RebuildBottomUp();
+ //}
+ }
+
+ static Test* Create()
+ {
+ return new Tiles;
+ }
+
+ int32 m_fixtureCount;
+ float m_createTime;
+};
+
+static int testIndex = RegisterTest("Benchmark", "Tiles", Tiles::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/time_of_impact.cpp b/Client/ThirdParty/Box2D/testbed/tests/time_of_impact.cpp
new file mode 100644
index 0000000..a081ff3
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/time_of_impact.cpp
@@ -0,0 +1,131 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "box2d/b2_time_of_impact.h"
+
+class TimeOfImpact : public Test
+{
+public:
+ TimeOfImpact()
+ {
+ m_shapeA.SetAsBox(25.0f, 5.0f);
+ m_shapeB.SetAsBox(2.5f, 2.5f);
+ }
+
+ static Test* Create()
+ {
+ return new TimeOfImpact;
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ b2Sweep sweepA;
+ sweepA.c0.Set(24.0f, -60.0f);
+ sweepA.a0 = 2.95f;
+ sweepA.c = sweepA.c0;
+ sweepA.a = sweepA.a0;
+ sweepA.localCenter.SetZero();
+
+ b2Sweep sweepB;
+ sweepB.c0.Set(53.474274f, -50.252514f);
+ sweepB.a0 = 513.36676f; // - 162.0f * b2_pi;
+ sweepB.c.Set(54.595478f, -51.083473f);
+ sweepB.a = 513.62781f; // - 162.0f * b2_pi;
+ sweepB.localCenter.SetZero();
+
+ //sweepB.a0 -= 300.0f * b2_pi;
+ //sweepB.a -= 300.0f * b2_pi;
+
+ b2TOIInput input;
+ input.proxyA.Set(&m_shapeA, 0);
+ input.proxyB.Set(&m_shapeB, 0);
+ input.sweepA = sweepA;
+ input.sweepB = sweepB;
+ input.tMax = 1.0f;
+
+ b2TOIOutput output;
+
+ b2TimeOfImpact(&output, &input);
+
+ g_debugDraw.DrawString(5, m_textLine, "toi = %g", output.t);
+ m_textLine += m_textIncrement;
+
+ extern B2_API int32 b2_toiMaxIters, b2_toiMaxRootIters;
+ g_debugDraw.DrawString(5, m_textLine, "max toi iters = %d, max root iters = %d", b2_toiMaxIters, b2_toiMaxRootIters);
+ m_textLine += m_textIncrement;
+
+ b2Vec2 vertices[b2_maxPolygonVertices];
+
+ b2Transform transformA;
+ sweepA.GetTransform(&transformA, 0.0f);
+ for (int32 i = 0; i < m_shapeA.m_count; ++i)
+ {
+ vertices[i] = b2Mul(transformA, m_shapeA.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(vertices, m_shapeA.m_count, b2Color(0.9f, 0.9f, 0.9f));
+
+ b2Transform transformB;
+ sweepB.GetTransform(&transformB, 0.0f);
+
+ //b2Vec2 localPoint(2.0f, -0.1f);
+
+ for (int32 i = 0; i < m_shapeB.m_count; ++i)
+ {
+ vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.5f, 0.9f, 0.5f));
+
+ sweepB.GetTransform(&transformB, output.t);
+ for (int32 i = 0; i < m_shapeB.m_count; ++i)
+ {
+ vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.5f, 0.7f, 0.9f));
+
+ sweepB.GetTransform(&transformB, 1.0f);
+ for (int32 i = 0; i < m_shapeB.m_count; ++i)
+ {
+ vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.9f, 0.5f, 0.5f));
+
+#if 0
+ for (float t = 0.0f; t < 1.0f; t += 0.1f)
+ {
+ sweepB.GetTransform(&transformB, t);
+ for (int32 i = 0; i < m_shapeB.m_count; ++i)
+ {
+ vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]);
+ }
+ g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.9f, 0.5f, 0.5f));
+ }
+#endif
+ }
+
+ b2PolygonShape m_shapeA;
+ b2PolygonShape m_shapeB;
+};
+
+static int testIndex = RegisterTest("Collision", "Time of Impact", TimeOfImpact::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/tumbler.cpp b/Client/ThirdParty/Box2D/testbed/tests/tumbler.cpp
new file mode 100644
index 0000000..f7972bc
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/tumbler.cpp
@@ -0,0 +1,102 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+class Tumbler : public Test
+{
+public:
+
+ enum
+ {
+ e_count = 800
+ };
+
+ Tumbler()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+ }
+
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.allowSleep = false;
+ bd.position.Set(0.0f, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 10.0f, b2Vec2( 10.0f, 0.0f), 0.0);
+ body->CreateFixture(&shape, 5.0f);
+ shape.SetAsBox(0.5f, 10.0f, b2Vec2(-10.0f, 0.0f), 0.0);
+ body->CreateFixture(&shape, 5.0f);
+ shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, 10.0f), 0.0);
+ body->CreateFixture(&shape, 5.0f);
+ shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, -10.0f), 0.0);
+ body->CreateFixture(&shape, 5.0f);
+
+ b2RevoluteJointDef jd;
+ jd.bodyA = ground;
+ jd.bodyB = body;
+ jd.localAnchorA.Set(0.0f, 10.0f);
+ jd.localAnchorB.Set(0.0f, 0.0f);
+ jd.referenceAngle = 0.0f;
+ jd.motorSpeed = 0.05f * b2_pi;
+ jd.maxMotorTorque = 1e8f;
+ jd.enableMotor = true;
+ m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
+ }
+
+ m_count = 0;
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ if (m_count < e_count)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 10.0f);
+ b2Body* body = m_world->CreateBody(&bd);
+
+ b2PolygonShape shape;
+ shape.SetAsBox(0.125f, 0.125f);
+ body->CreateFixture(&shape, 1.0f);
+
+ ++m_count;
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Tumbler;
+ }
+
+ b2RevoluteJoint* m_joint;
+ int32 m_count;
+};
+
+static int testIndex = RegisterTest("Benchmark", "Tumbler", Tumbler::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/web.cpp b/Client/ThirdParty/Box2D/testbed/tests/web.cpp
new file mode 100644
index 0000000..aefa46a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/web.cpp
@@ -0,0 +1,218 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+
+// Test distance joints, body destruction, and joint destruction.
+class Web : public Test
+{
+public:
+ Web()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.5f);
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+
+ bd.position.Set(-5.0f, 5.0f);
+ m_bodies[0] = m_world->CreateBody(&bd);
+ m_bodies[0]->CreateFixture(&shape, 5.0f);
+
+ bd.position.Set(5.0f, 5.0f);
+ m_bodies[1] = m_world->CreateBody(&bd);
+ m_bodies[1]->CreateFixture(&shape, 5.0f);
+
+ bd.position.Set(5.0f, 15.0f);
+ m_bodies[2] = m_world->CreateBody(&bd);
+ m_bodies[2]->CreateFixture(&shape, 5.0f);
+
+ bd.position.Set(-5.0f, 15.0f);
+ m_bodies[3] = m_world->CreateBody(&bd);
+ m_bodies[3]->CreateFixture(&shape, 5.0f);
+
+ b2DistanceJointDef jd;
+ b2Vec2 p1, p2, d;
+
+ float frequencyHz = 2.0f;
+ float dampingRatio = 0.0f;
+
+ jd.bodyA = ground;
+ jd.bodyB = m_bodies[0];
+ jd.localAnchorA.Set(-10.0f, 0.0f);
+ jd.localAnchorB.Set(-0.5f, -0.5f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[0] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = ground;
+ jd.bodyB = m_bodies[1];
+ jd.localAnchorA.Set(10.0f, 0.0f);
+ jd.localAnchorB.Set(0.5f, -0.5f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[1] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = ground;
+ jd.bodyB = m_bodies[2];
+ jd.localAnchorA.Set(10.0f, 20.0f);
+ jd.localAnchorB.Set(0.5f, 0.5f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[2] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = ground;
+ jd.bodyB = m_bodies[3];
+ jd.localAnchorA.Set(-10.0f, 20.0f);
+ jd.localAnchorB.Set(-0.5f, 0.5f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[3] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = m_bodies[0];
+ jd.bodyB = m_bodies[1];
+ jd.localAnchorA.Set(0.5f, 0.0f);
+ jd.localAnchorB.Set(-0.5f, 0.0f);;
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[4] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = m_bodies[1];
+ jd.bodyB = m_bodies[2];
+ jd.localAnchorA.Set(0.0f, 0.5f);
+ jd.localAnchorB.Set(0.0f, -0.5f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[5] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = m_bodies[2];
+ jd.bodyB = m_bodies[3];
+ jd.localAnchorA.Set(-0.5f, 0.0f);
+ jd.localAnchorB.Set(0.5f, 0.0f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[6] = m_world->CreateJoint(&jd);
+
+ jd.bodyA = m_bodies[3];
+ jd.bodyB = m_bodies[0];
+ jd.localAnchorA.Set(0.0f, -0.5f);
+ jd.localAnchorB.Set(0.0f, 0.5f);
+ p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA);
+ p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB);
+ d = p2 - p1;
+ jd.length = d.Length();
+ b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB);
+ m_joints[7] = m_world->CreateJoint(&jd);
+ }
+ }
+
+ void Keyboard(int key) override
+ {
+ switch (key)
+ {
+ case GLFW_KEY_B:
+ for (int32 i = 0; i < 4; ++i)
+ {
+ if (m_bodies[i])
+ {
+ m_world->DestroyBody(m_bodies[i]);
+ m_bodies[i] = NULL;
+ break;
+ }
+ }
+ break;
+
+ case GLFW_KEY_J:
+ for (int32 i = 0; i < 8; ++i)
+ {
+ if (m_joints[i])
+ {
+ m_world->DestroyJoint(m_joints[i]);
+ m_joints[i] = NULL;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+ g_debugDraw.DrawString(5, m_textLine, "Press: (b) to delete a body, (j) to delete a joint");
+ m_textLine += m_textIncrement;
+ }
+
+ void JointDestroyed(b2Joint* joint) override
+ {
+ for (int32 i = 0; i < 8; ++i)
+ {
+ if (m_joints[i] == joint)
+ {
+ m_joints[i] = NULL;
+ break;
+ }
+ }
+ }
+
+ static Test* Create()
+ {
+ return new Web;
+ }
+
+ b2Body* m_bodies[4];
+ b2Joint* m_joints[8];
+};
+
+static int testIndex = RegisterTest("Examples", "Web", Web::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/wheel_joint.cpp b/Client/ThirdParty/Box2D/testbed/tests/wheel_joint.cpp
new file mode 100644
index 0000000..153cac1
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/wheel_joint.cpp
@@ -0,0 +1,126 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "settings.h"
+#include "test.h"
+#include "imgui/imgui.h"
+
+// Test the wheel joint with motor, spring, and limit options.
+class WheelJoint : public Test
+{
+public:
+ WheelJoint()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ m_enableLimit = true;
+ m_enableMotor = false;
+ m_motorSpeed = 10.0f;
+
+ {
+ b2CircleShape shape;
+ shape.m_radius = 2.0f;
+
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.0f, 10.0f);
+ bd.allowSleep = false;
+ b2Body* body = m_world->CreateBody(&bd);
+ body->CreateFixture(&shape, 5.0f);
+
+ b2WheelJointDef jd;
+
+ // Horizontal
+ jd.Initialize(ground, body, bd.position, b2Vec2(0.0f, 1.0f));
+
+ jd.motorSpeed = m_motorSpeed;
+ jd.maxMotorTorque = 10000.0f;
+ jd.enableMotor = m_enableMotor;
+ jd.lowerTranslation = -3.0f;
+ jd.upperTranslation = 3.0f;
+ jd.enableLimit = m_enableLimit;
+
+ float hertz = 1.0f;
+ float dampingRatio = 0.7f;
+ b2LinearStiffness(jd.stiffness, jd.damping, hertz, dampingRatio, ground, body);
+
+ m_joint = (b2WheelJoint*)m_world->CreateJoint(&jd);
+ }
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ float torque = m_joint->GetMotorTorque(settings.m_hertz);
+ g_debugDraw.DrawString(5, m_textLine, "Motor Torque = %4.0f", torque);
+ m_textLine += m_textIncrement;
+
+ b2Vec2 F = m_joint->GetReactionForce(settings.m_hertz);
+ g_debugDraw.DrawString(5, m_textLine, "Reaction Force = (%4.1f, %4.1f)", F.x, F.y);
+ m_textLine += m_textIncrement;
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f));
+ ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::Checkbox("Limit", &m_enableLimit))
+ {
+ m_joint->EnableLimit(m_enableLimit);
+ }
+
+ if (ImGui::Checkbox("Motor", &m_enableMotor))
+ {
+ m_joint->EnableMotor(m_enableMotor);
+ }
+
+ if (ImGui::SliderFloat("Speed", &m_motorSpeed, -100.0f, 100.0f, "%.0f"))
+ {
+ m_joint->SetMotorSpeed(m_motorSpeed);
+ }
+
+ ImGui::End();
+ }
+
+ static Test* Create()
+ {
+ return new WheelJoint;
+ }
+
+ b2WheelJoint* m_joint;
+ float m_motorSpeed;
+ bool m_enableMotor;
+ bool m_enableLimit;
+};
+
+static int testIndex = RegisterTest("Joints", "Wheel", WheelJoint::Create);
diff --git a/Client/ThirdParty/Box2D/testbed/tests/wrecking_ball.cpp b/Client/ThirdParty/Box2D/testbed/tests/wrecking_ball.cpp
new file mode 100644
index 0000000..74a61b4
--- /dev/null
+++ b/Client/ThirdParty/Box2D/testbed/tests/wrecking_ball.cpp
@@ -0,0 +1,165 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "test.h"
+#include "imgui/imgui.h"
+
+/// This test shows how a distance joint can be used to stabilize a chain of
+/// bodies with a heavy payload. Notice that the distance joint just prevents
+/// excessive stretching and has no other effect.
+/// By disabling the distance joint you can see that the Box2D solver has trouble
+/// supporting heavy bodies with light bodies. Try playing around with the
+/// densities, time step, and iterations to see how they affect stability.
+/// This test also shows how to use contact filtering. Filtering is configured
+/// so that the payload does not collide with the chain.
+class WreckingBall : public Test
+{
+public:
+ WreckingBall()
+ {
+ b2Body* ground = NULL;
+ {
+ b2BodyDef bd;
+ ground = m_world->CreateBody(&bd);
+
+ b2EdgeShape shape;
+ shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f));
+ ground->CreateFixture(&shape, 0.0f);
+ }
+
+ {
+ b2PolygonShape shape;
+ shape.SetAsBox(0.5f, 0.125f);
+
+ b2FixtureDef fd;
+ fd.shape = &shape;
+ fd.density = 20.0f;
+ fd.friction = 0.2f;
+ fd.filter.categoryBits = 0x0001;
+ fd.filter.maskBits = 0xFFFF & ~0x0002;
+
+ b2RevoluteJointDef jd;
+ jd.collideConnected = false;
+
+ const int32 N = 10;
+ const float y = 15.0f;
+ m_distanceJointDef.localAnchorA.Set(0.0f, y);
+
+ b2Body* prevBody = ground;
+ for (int32 i = 0; i < N; ++i)
+ {
+ b2BodyDef bd;
+ bd.type = b2_dynamicBody;
+ bd.position.Set(0.5f + 1.0f * i, y);
+ if (i == N - 1)
+ {
+ bd.position.Set(1.0f * i, y);
+ bd.angularDamping = 0.4f;
+ }
+
+ b2Body* body = m_world->CreateBody(&bd);
+
+ if (i == N - 1)
+ {
+ b2CircleShape circleShape;
+ circleShape.m_radius = 1.5f;
+ b2FixtureDef sfd;
+ sfd.shape = &circleShape;
+ sfd.density = 100.0f;
+ sfd.filter.categoryBits = 0x0002;
+ body->CreateFixture(&sfd);
+ }
+ else
+ {
+ body->CreateFixture(&fd);
+ }
+
+ b2Vec2 anchor(float(i), y);
+ jd.Initialize(prevBody, body, anchor);
+ m_world->CreateJoint(&jd);
+
+ prevBody = body;
+ }
+
+ m_distanceJointDef.localAnchorB.SetZero();
+
+ float extraLength = 0.01f;
+ m_distanceJointDef.minLength = 0.0f;
+ m_distanceJointDef.maxLength = N - 1.0f + extraLength;
+ m_distanceJointDef.bodyB = prevBody;
+ }
+
+ {
+ m_distanceJointDef.bodyA = ground;
+ m_distanceJoint = m_world->CreateJoint(&m_distanceJointDef);
+ m_stabilize = true;
+ }
+ }
+
+ void UpdateUI() override
+ {
+ ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f));
+ ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f));
+ ImGui::Begin("Wrecking Ball Controls", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
+
+ if (ImGui::Checkbox("Stabilize", &m_stabilize))
+ {
+ if (m_stabilize == true && m_distanceJoint == nullptr)
+ {
+ m_distanceJoint = m_world->CreateJoint(&m_distanceJointDef);
+ }
+ else if (m_stabilize == false && m_distanceJoint != nullptr)
+ {
+ m_world->DestroyJoint(m_distanceJoint);
+ m_distanceJoint = nullptr;
+ }
+ }
+
+ ImGui::End();
+ }
+
+ void Step(Settings& settings) override
+ {
+ Test::Step(settings);
+
+ if (m_distanceJoint)
+ {
+ g_debugDraw.DrawString(5, m_textLine, "Distance Joint ON");
+ }
+ else
+ {
+ g_debugDraw.DrawString(5, m_textLine, "Distance Joint OFF");
+ }
+ m_textLine += m_textIncrement;
+ }
+
+ static Test* Create()
+ {
+ return new WreckingBall;
+ }
+
+ b2DistanceJointDef m_distanceJointDef;
+ b2Joint* m_distanceJoint;
+ bool m_stabilize;
+};
+
+static int testIndex = RegisterTest("Examples", "Wrecking Ball", WreckingBall::Create);
diff --git a/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt b/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt
new file mode 100644
index 0000000..d941579
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_executable(unit_test
+ doctest.h
+ hello_world.cpp
+ collision_test.cpp
+ joint_test.cpp
+ math_test.cpp
+ world_test.cpp
+)
+
+set_target_properties(unit_test PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO
+)
+target_link_libraries(unit_test PUBLIC box2d)
+
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES doctest.h
+ hello_world.cpp collision_test.cpp joint_test.cpp math_test.cpp world_test.cpp )
diff --git a/Client/ThirdParty/Box2D/unit-test/collision_test.cpp b/Client/ThirdParty/Box2D/unit-test/collision_test.cpp
new file mode 100644
index 0000000..2e24b20
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/collision_test.cpp
@@ -0,0 +1,81 @@
+// MIT License
+
+// Copyright (c) 2020 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/box2d.h"
+#include "doctest.h"
+#include <stdio.h>
+
+// Unit tests for collision algorithms
+DOCTEST_TEST_CASE("collision test")
+{
+ SUBCASE("polygon mass data")
+ {
+ const b2Vec2 center(100.0f, -50.0f);
+ const float hx = 0.5f, hy = 1.5f;
+ const float angle1 = 0.25f;
+
+ // Data from issue #422. Not used because the data exceeds accuracy limits.
+ //const b2Vec2 center(-15000.0f, -15000.0f);
+ //const float hx = 0.72f, hy = 0.72f;
+ //const float angle1 = 0.0f;
+
+ b2PolygonShape polygon1;
+ polygon1.SetAsBox(hx, hy, center, angle1);
+
+ const float absTol = 2.0f * b2_epsilon;
+ const float relTol = 2.0f * b2_epsilon;
+
+ CHECK(b2Abs(polygon1.m_centroid.x - center.x) < absTol + relTol * b2Abs(center.x));
+ CHECK(b2Abs(polygon1.m_centroid.y - center.y) < absTol + relTol * b2Abs(center.y));
+
+ b2Vec2 vertices[4];
+ vertices[0].Set(center.x - hx, center.y - hy);
+ vertices[1].Set(center.x + hx, center.y - hy);
+ vertices[2].Set(center.x - hx, center.y + hy);
+ vertices[3].Set(center.x + hx, center.y + hy);
+
+ b2PolygonShape polygon2;
+ polygon2.Set(vertices, 4);
+
+ CHECK(b2Abs(polygon2.m_centroid.x - center.x) < absTol + relTol * b2Abs(center.x));
+ CHECK(b2Abs(polygon2.m_centroid.y - center.y) < absTol + relTol * b2Abs(center.y));
+
+ const float mass = 4.0f * hx * hy;
+ const float inertia = (mass / 3.0f) * (hx * hx + hy * hy) + mass * b2Dot(center, center);
+
+ b2MassData massData1;
+ polygon1.ComputeMass(&massData1, 1.0f);
+
+ CHECK(b2Abs(massData1.center.x - center.x) < absTol + relTol * b2Abs(center.x));
+ CHECK(b2Abs(massData1.center.y - center.y) < absTol + relTol * b2Abs(center.y));
+ CHECK(b2Abs(massData1.mass - mass) < 20.0f * (absTol + relTol * mass));
+ CHECK(b2Abs(massData1.I - inertia) < 40.0f * (absTol + relTol * inertia));
+
+ b2MassData massData2;
+ polygon2.ComputeMass(&massData2, 1.0f);
+
+ CHECK(b2Abs(massData2.center.x - center.x) < absTol + relTol * b2Abs(center.x));
+ CHECK(b2Abs(massData2.center.y - center.y) < absTol + relTol * b2Abs(center.y));
+ CHECK(b2Abs(massData2.mass - mass) < 20.0f * (absTol + relTol * mass));
+ CHECK(b2Abs(massData2.I - inertia) < 40.0f * (absTol + relTol * inertia));
+ }
+}
diff --git a/Client/ThirdParty/Box2D/unit-test/doctest.h b/Client/ThirdParty/Box2D/unit-test/doctest.h
new file mode 100644
index 0000000..42eb039
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/doctest.h
@@ -0,0 +1,6580 @@
+// ====================================================================== lgtm [cpp/missing-header-guard]
+// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
+// ======================================================================
+//
+// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
+//
+// Copyright (c) 2016-2021 Viktor Kirilov
+//
+// Distributed under the MIT Software License
+// See accompanying file LICENSE.txt or copy at
+// https://opensource.org/licenses/MIT
+//
+// The documentation can be found at the library's page:
+// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+//
+// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt
+//
+// The concept of subcases (sections in Catch) and expression decomposition are from there.
+// Some parts of the code are taken directly:
+// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
+// - the Approx() helper class for floating point comparison
+// - colors in the console
+// - breaking into a debugger
+// - signal / SEH handling
+// - timer
+// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste)
+//
+// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
+// which uses the Boost Software License - Version 1.0
+// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt
+//
+// =================================================================================================
+// =================================================================================================
+// =================================================================================================
+
+#ifndef DOCTEST_LIBRARY_INCLUDED
+#define DOCTEST_LIBRARY_INCLUDED
+
+// =================================================================================================
+// == VERSION ======================================================================================
+// =================================================================================================
+
+#define DOCTEST_VERSION_MAJOR 2
+#define DOCTEST_VERSION_MINOR 4
+#define DOCTEST_VERSION_PATCH 6
+#define DOCTEST_VERSION_STR "2.4.6"
+
+#define DOCTEST_VERSION \
+ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
+
+// =================================================================================================
+// == COMPILER VERSION =============================================================================
+// =================================================================================================
+
+// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
+
+#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
+
+// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
+#if defined(_MSC_VER) && defined(_MSC_FULL_VER)
+#if _MSC_VER == _MSC_FULL_VER / 10000
+#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
+#else // MSVC
+#define DOCTEST_MSVC \
+ DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
+#endif // MSVC
+#endif // MSVC
+#if defined(__clang__) && defined(__clang_minor__)
+#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
+#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
+ !defined(__INTEL_COMPILER)
+#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#endif // GCC
+
+#ifndef DOCTEST_MSVC
+#define DOCTEST_MSVC 0
+#endif // DOCTEST_MSVC
+#ifndef DOCTEST_CLANG
+#define DOCTEST_CLANG 0
+#endif // DOCTEST_CLANG
+#ifndef DOCTEST_GCC
+#define DOCTEST_GCC 0
+#endif // DOCTEST_GCC
+
+// =================================================================================================
+// == COMPILER WARNINGS HELPERS ====================================================================
+// =================================================================================================
+
+#if DOCTEST_CLANG
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#else // DOCTEST_CLANG
+#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+#define DOCTEST_CLANG_SUPPRESS_WARNING(w)
+#define DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_CLANG
+
+#if DOCTEST_GCC
+#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
+#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w)
+#else // DOCTEST_GCC
+#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_GCC_SUPPRESS_WARNING(w)
+#define DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_GCC
+
+#if DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#else // DOCTEST_MSVC
+#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+#define DOCTEST_MSVC_SUPPRESS_WARNING(w)
+#define DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
+#endif // DOCTEST_MSVC
+
+// =================================================================================================
+// == COMPILER WARNINGS ============================================================================
+// =================================================================================================
+
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
+
+DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")
+DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
+
+DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning
+DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning
+DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration
+DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression
+DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated
+DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant
+DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding
+DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe
+// static analysis
+DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept'
+DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable
+DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ...
+DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtr...
+DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
+
+// 4548 - expression before comma has no effect; expected expression with side - effect
+// 4265 - class has virtual functions, but destructor is not virtual
+// 4986 - exception specification does not match previous declaration
+// 4350 - behavior change: 'member1' called instead of 'member2'
+// 4668 - 'x' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+// 4365 - conversion from 'int' to 'unsigned long', signed/unsigned mismatch
+// 4774 - format string expected in argument 'x' is not a string literal
+// 4820 - padding in structs
+
+// only 4 should be disabled globally:
+// - 4514 # unreferenced inline function has been removed
+// - 4571 # SEH related
+// - 4710 # function not inlined
+// - 4711 # function 'x' selected for automatic inline expansion
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4548) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4265) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4986) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4350) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4668) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4365) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4774) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4623) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5039) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5105)
+
+#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+// =================================================================================================
+// == FEATURE DETECTION ============================================================================
+// =================================================================================================
+
+// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support
+// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx
+// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
+// MSVC version table:
+// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
+// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
+// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
+// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
+// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
+// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
+// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
+// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
+// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
+
+#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#define DOCTEST_CONFIG_WINDOWS_SEH
+#endif // MSVC
+#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH)
+#undef DOCTEST_CONFIG_WINDOWS_SEH
+#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
+
+#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \
+ !defined(__EMSCRIPTEN__)
+#define DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // _WIN32
+#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
+#undef DOCTEST_CONFIG_POSIX_SIGNALS
+#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND)
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // no exceptions
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+#define DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
+#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
+#define DOCTEST_CONFIG_IMPLEMENT
+#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#if DOCTEST_MSVC
+#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport)
+#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport)
+#else // MSVC
+#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport))
+#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport))
+#endif // MSVC
+#else // _WIN32
+#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default")))
+#define DOCTEST_SYMBOL_IMPORT
+#endif // _WIN32
+
+#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#ifdef DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT
+#else // DOCTEST_CONFIG_IMPLEMENT
+#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT
+#endif // DOCTEST_CONFIG_IMPLEMENT
+#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+#define DOCTEST_INTERFACE
+#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+
+#define DOCTEST_EMPTY
+
+#if DOCTEST_MSVC
+#define DOCTEST_NOINLINE __declspec(noinline)
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
+#define DOCTEST_NOINLINE
+#define DOCTEST_UNUSED
+#define DOCTEST_ALIGNMENT(x)
+#else
+#define DOCTEST_NOINLINE __attribute__((noinline))
+#define DOCTEST_UNUSED __attribute__((unused))
+#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
+#endif
+
+#ifndef DOCTEST_NORETURN
+#define DOCTEST_NORETURN [[noreturn]]
+#endif // DOCTEST_NORETURN
+
+#ifndef DOCTEST_NOEXCEPT
+#define DOCTEST_NOEXCEPT noexcept
+#endif // DOCTEST_NOEXCEPT
+
+// =================================================================================================
+// == FEATURE DETECTION END ========================================================================
+// =================================================================================================
+
+// internal macros for string concatenation and anonymous variable name generation
+#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
+#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
+#ifdef __COUNTER__ // not standard and may be missing for some compilers
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
+#else // __COUNTER__
+#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
+#endif // __COUNTER__
+
+#define DOCTEST_TOSTR(x) #x
+
+#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x&
+#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+#define DOCTEST_REF_WRAP(x) x
+#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
+
+// not using __APPLE__ because... this is how Catch does it
+#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
+#define DOCTEST_PLATFORM_MAC
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+#define DOCTEST_PLATFORM_IPHONE
+#elif defined(_WIN32)
+#define DOCTEST_PLATFORM_WINDOWS
+#else // DOCTEST_PLATFORM
+#define DOCTEST_PLATFORM_LINUX
+#endif // DOCTEST_PLATFORM
+
+#define DOCTEST_GLOBAL_NO_WARNINGS(var) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \
+ static const int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp)
+#define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#ifndef DOCTEST_BREAK_INTO_DEBUGGER
+// should probably take a look at https://github.com/scottt/debugbreak
+#ifdef DOCTEST_PLATFORM_LINUX
+#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+// Break at the location of the failing check if possible
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
+#else
+#include <signal.h>
+#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
+#endif
+#elif defined(DOCTEST_PLATFORM_MAC)
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
+#else
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT (hicpp-no-assembler)
+#endif
+#elif DOCTEST_MSVC
+#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
+#elif defined(__MINGW32__)
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
+extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
+#else // linux
+#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast<void>(0))
+#endif // linux
+#endif // DOCTEST_BREAK_INTO_DEBUGGER
+
+// this is kept here for backwards compatibility since the config option was changed
+#ifdef DOCTEST_CONFIG_USE_IOSFWD
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif // DOCTEST_CONFIG_USE_IOSFWD
+
+#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
+#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#include <iosfwd>
+#include <cstddef>
+#include <ostream>
+#else // DOCTEST_CONFIG_USE_STD_HEADERS
+
+#if DOCTEST_CLANG
+// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier)
+#include <ciso646>
+#endif // clang
+
+#ifdef _LIBCPP_VERSION
+#define DOCTEST_STD_NAMESPACE_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
+#define DOCTEST_STD_NAMESPACE_END _LIBCPP_END_NAMESPACE_STD
+#else // _LIBCPP_VERSION
+#define DOCTEST_STD_NAMESPACE_BEGIN namespace std {
+#define DOCTEST_STD_NAMESPACE_END }
+#endif // _LIBCPP_VERSION
+
+// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
+
+DOCTEST_STD_NAMESPACE_BEGIN // NOLINT (cert-dcl58-cpp)
+typedef decltype(nullptr) nullptr_t;
+template <class charT>
+struct char_traits;
+template <>
+struct char_traits<char>;
+template <class charT, class traits>
+class basic_ostream;
+typedef basic_ostream<char, char_traits<char>> ostream;
+template <class... Types>
+class tuple;
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+template <class _Ty>
+class allocator;
+template <class _Elem, class _Traits, class _Alloc>
+class basic_string;
+using string = basic_string<char, char_traits<char>, allocator<char>>;
+#endif // VS 2019
+DOCTEST_STD_NAMESPACE_END
+
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_USE_STD_HEADERS
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#include <type_traits>
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+namespace doctest {
+
+DOCTEST_INTERFACE extern bool is_running_in_test;
+
+// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
+// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
+// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
+// - if small - capacity left before going on the heap - using the lowest 5 bits
+// - if small - 2 bits are left unused - the second and third highest ones
+// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator)
+// and the "is small" bit remains "0" ("as well as the capacity left") so its OK
+// Idea taken from this lecture about the string implementation of facebook/folly - fbstring
+// https://www.youtube.com/watch?v=kPR8h4-qZdk
+// TODO:
+// - optimizations - like not deleting memory unnecessarily in operator= and etc.
+// - resize/reserve/clear
+// - substr
+// - replace
+// - back/front
+// - iterator stuff
+// - find & friends
+// - push_back/pop_back
+// - assign/insert/erase
+// - relational operators as free functions - taking const char* as one of the params
+class DOCTEST_INTERFACE String
+{
+ static const unsigned len = 24; //!OCLINT avoid private static members
+ static const unsigned last = len - 1; //!OCLINT avoid private static members
+
+ struct view // len should be more than sizeof(view) - because of the final byte for flags
+ {
+ char* ptr;
+ unsigned size;
+ unsigned capacity;
+ };
+
+ union
+ {
+ char buf[len];
+ view data;
+ };
+
+ bool isOnStack() const { return (buf[last] & 128) == 0; }
+ void setOnHeap();
+ void setLast(unsigned in = last);
+
+ void copy(const String& other);
+
+public:
+ String();
+ ~String();
+
+ // cppcheck-suppress noExplicitConstructor
+ String(const char* in);
+ String(const char* in, unsigned in_size);
+
+ String(const String& other);
+ String& operator=(const String& other);
+
+ String& operator+=(const String& other);
+ String operator+(const String& other) const;
+
+ String(String&& other);
+ String& operator=(String&& other);
+
+ char operator[](unsigned i) const;
+ char& operator[](unsigned i);
+
+ // the only functions I'm willing to leave in the interface - available for inlining
+ const char* c_str() const { return const_cast<String*>(this)->c_str(); } // NOLINT
+ char* c_str() {
+ if(isOnStack())
+ return reinterpret_cast<char*>(buf);
+ return data.ptr;
+ }
+
+ unsigned size() const;
+ unsigned capacity() const;
+
+ int compare(const char* other, bool no_case = false) const;
+ int compare(const String& other, bool no_case = false) const;
+};
+
+DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
+
+DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
+
+namespace Color {
+ enum Enum
+ {
+ None = 0,
+ White,
+ Red,
+ Green,
+ Blue,
+ Cyan,
+ Yellow,
+ Grey,
+
+ Bright = 0x10,
+
+ BrightRed = Bright | Red,
+ BrightGreen = Bright | Green,
+ LightGrey = Bright | Grey,
+ BrightWhite = Bright | White
+ };
+
+ DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code);
+} // namespace Color
+
+namespace assertType {
+ enum Enum
+ {
+ // macro traits
+
+ is_warn = 1,
+ is_check = 2 * is_warn,
+ is_require = 2 * is_check,
+
+ is_normal = 2 * is_require,
+ is_throws = 2 * is_normal,
+ is_throws_as = 2 * is_throws,
+ is_throws_with = 2 * is_throws_as,
+ is_nothrow = 2 * is_throws_with,
+
+ is_false = 2 * is_nothrow,
+ is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types
+
+ is_eq = 2 * is_unary,
+ is_ne = 2 * is_eq,
+
+ is_lt = 2 * is_ne,
+ is_gt = 2 * is_lt,
+
+ is_ge = 2 * is_gt,
+ is_le = 2 * is_ge,
+
+ // macro types
+
+ DT_WARN = is_normal | is_warn,
+ DT_CHECK = is_normal | is_check,
+ DT_REQUIRE = is_normal | is_require,
+
+ DT_WARN_FALSE = is_normal | is_false | is_warn,
+ DT_CHECK_FALSE = is_normal | is_false | is_check,
+ DT_REQUIRE_FALSE = is_normal | is_false | is_require,
+
+ DT_WARN_THROWS = is_throws | is_warn,
+ DT_CHECK_THROWS = is_throws | is_check,
+ DT_REQUIRE_THROWS = is_throws | is_require,
+
+ DT_WARN_THROWS_AS = is_throws_as | is_warn,
+ DT_CHECK_THROWS_AS = is_throws_as | is_check,
+ DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
+
+ DT_WARN_THROWS_WITH = is_throws_with | is_warn,
+ DT_CHECK_THROWS_WITH = is_throws_with | is_check,
+ DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
+
+ DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
+ DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
+ DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
+
+ DT_WARN_NOTHROW = is_nothrow | is_warn,
+ DT_CHECK_NOTHROW = is_nothrow | is_check,
+ DT_REQUIRE_NOTHROW = is_nothrow | is_require,
+
+ DT_WARN_EQ = is_normal | is_eq | is_warn,
+ DT_CHECK_EQ = is_normal | is_eq | is_check,
+ DT_REQUIRE_EQ = is_normal | is_eq | is_require,
+
+ DT_WARN_NE = is_normal | is_ne | is_warn,
+ DT_CHECK_NE = is_normal | is_ne | is_check,
+ DT_REQUIRE_NE = is_normal | is_ne | is_require,
+
+ DT_WARN_GT = is_normal | is_gt | is_warn,
+ DT_CHECK_GT = is_normal | is_gt | is_check,
+ DT_REQUIRE_GT = is_normal | is_gt | is_require,
+
+ DT_WARN_LT = is_normal | is_lt | is_warn,
+ DT_CHECK_LT = is_normal | is_lt | is_check,
+ DT_REQUIRE_LT = is_normal | is_lt | is_require,
+
+ DT_WARN_GE = is_normal | is_ge | is_warn,
+ DT_CHECK_GE = is_normal | is_ge | is_check,
+ DT_REQUIRE_GE = is_normal | is_ge | is_require,
+
+ DT_WARN_LE = is_normal | is_le | is_warn,
+ DT_CHECK_LE = is_normal | is_le | is_check,
+ DT_REQUIRE_LE = is_normal | is_le | is_require,
+
+ DT_WARN_UNARY = is_normal | is_unary | is_warn,
+ DT_CHECK_UNARY = is_normal | is_unary | is_check,
+ DT_REQUIRE_UNARY = is_normal | is_unary | is_require,
+
+ DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn,
+ DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check,
+ DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require,
+ };
+} // namespace assertType
+
+DOCTEST_INTERFACE const char* assertString(assertType::Enum at);
+DOCTEST_INTERFACE const char* failureString(assertType::Enum at);
+DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
+
+struct DOCTEST_INTERFACE TestCaseData
+{
+ String m_file; // the file in which the test was registered (using String - see #350)
+ unsigned m_line; // the line where the test was registered
+ const char* m_name; // name of the test case
+ const char* m_test_suite; // the test suite in which the test was added
+ const char* m_description;
+ bool m_skip;
+ bool m_no_breaks;
+ bool m_no_output;
+ bool m_may_fail;
+ bool m_should_fail;
+ int m_expected_failures;
+ double m_timeout;
+};
+
+struct DOCTEST_INTERFACE AssertData
+{
+ // common - for all asserts
+ const TestCaseData* m_test_case;
+ assertType::Enum m_at;
+ const char* m_file;
+ int m_line;
+ const char* m_expr;
+ bool m_failed;
+
+ // exception-related - for all asserts
+ bool m_threw;
+ String m_exception;
+
+ // for normal asserts
+ String m_decomp;
+
+ // for specific exception-related asserts
+ bool m_threw_as;
+ const char* m_exception_type;
+ const char* m_exception_string;
+};
+
+struct DOCTEST_INTERFACE MessageData
+{
+ String m_string;
+ const char* m_file;
+ int m_line;
+ assertType::Enum m_severity;
+};
+
+struct DOCTEST_INTERFACE SubcaseSignature
+{
+ String m_name;
+ const char* m_file;
+ int m_line;
+
+ bool operator<(const SubcaseSignature& other) const;
+};
+
+struct DOCTEST_INTERFACE IContextScope
+{
+ IContextScope();
+ virtual ~IContextScope();
+ virtual void stringify(std::ostream*) const = 0;
+};
+
+namespace detail {
+ struct DOCTEST_INTERFACE TestCase;
+} // namespace detail
+
+struct ContextOptions //!OCLINT too many fields
+{
+ std::ostream* cout; // stdout stream - std::cout by default
+ std::ostream* cerr; // stderr stream - std::cerr by default
+ String binary_name; // the test binary name
+
+ const detail::TestCase* currentTest = nullptr;
+
+ // == parameters from the command line
+ String out; // output filename
+ String order_by; // how tests should be ordered
+ unsigned rand_seed; // the seed for rand ordering
+
+ unsigned first; // the first (matching) test to be executed
+ unsigned last; // the last (matching) test to be executed
+
+ int abort_after; // stop tests after this many failed assertions
+ int subcase_filter_levels; // apply the subcase filters for the first N levels
+
+ bool success; // include successful assertions in output
+ bool case_sensitive; // if filtering should be case sensitive
+ bool exit; // if the program should be exited after the tests are ran/whatever
+ bool duration; // print the time duration of each test case
+ bool no_throw; // to skip exceptions-related assertion macros
+ bool no_exitcode; // if the framework should return 0 as the exitcode
+ bool no_run; // to not run the tests at all (can be done with an "*" exclude)
+ bool no_version; // to not print the version of the framework
+ bool no_colors; // if output to the console should be colorized
+ bool force_colors; // forces the use of colors even when a tty cannot be detected
+ bool no_breaks; // to not break into the debugger
+ bool no_skip; // don't skip test cases which are marked to be skipped
+ bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x):
+ bool no_path_in_filenames; // if the path to files should be removed from the output
+ bool no_line_numbers; // if source code line numbers should be omitted from the output
+ bool no_debug_output; // no output in the debug console when a debugger is attached
+ bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
+ bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!!
+
+ bool help; // to print the help
+ bool version; // to print the version
+ bool count; // if only the count of matching tests is to be retrieved
+ bool list_test_cases; // to list all tests matching the filters
+ bool list_test_suites; // to list all suites matching the filters
+ bool list_reporters; // lists all registered reporters
+};
+
+namespace detail {
+ template <bool CONDITION, typename TYPE = void>
+ struct enable_if
+ {};
+
+ template <typename TYPE>
+ struct enable_if<true, TYPE>
+ { typedef TYPE type; };
+
+ // clang-format off
+ template<class T> struct remove_reference { typedef T type; };
+ template<class T> struct remove_reference<T&> { typedef T type; };
+ template<class T> struct remove_reference<T&&> { typedef T type; };
+
+ template<typename T, typename U = T&&> U declval(int);
+
+ template<typename T> T declval(long);
+
+ template<typename T> auto declval() DOCTEST_NOEXCEPT -> decltype(declval<T>(0)) ;
+
+ template<class T> struct is_lvalue_reference { const static bool value=false; };
+ template<class T> struct is_lvalue_reference<T&> { const static bool value=true; };
+
+ template <class T>
+ inline T&& forward(typename remove_reference<T>::type& t) DOCTEST_NOEXCEPT
+ {
+ return static_cast<T&&>(t);
+ }
+
+ template <class T>
+ inline T&& forward(typename remove_reference<T>::type&& t) DOCTEST_NOEXCEPT
+ {
+ static_assert(!is_lvalue_reference<T>::value,
+ "Can not forward an rvalue as an lvalue.");
+ return static_cast<T&&>(t);
+ }
+
+ template<class T> struct remove_const { typedef T type; };
+ template<class T> struct remove_const<const T> { typedef T type; };
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template<class T> struct is_enum : public std::is_enum<T> {};
+ template<class T> struct underlying_type : public std::underlying_type<T> {};
+#else
+ // Use compiler intrinsics
+ template<class T> struct is_enum { constexpr static bool value = __is_enum(T); };
+ template<class T> struct underlying_type { typedef __underlying_type(T) type; };
+#endif
+ // clang-format on
+
+ template <typename T>
+ struct deferred_false
+ // cppcheck-suppress unusedStructMember
+ { static const bool value = false; };
+
+ namespace has_insertion_operator_impl {
+ std::ostream &os();
+ template<class T>
+ DOCTEST_REF_WRAP(T) val();
+
+ template<class, class = void>
+ struct check {
+ static constexpr bool value = false;
+ };
+
+ template<class T>
+ struct check<T, decltype(os() << val<T>(), void())> {
+ static constexpr bool value = true;
+ };
+ } // namespace has_insertion_operator_impl
+
+ template<class T>
+ using has_insertion_operator = has_insertion_operator_impl::check<const T>;
+
+ DOCTEST_INTERFACE void my_memcpy(void* dest, const void* src, unsigned num);
+
+ DOCTEST_INTERFACE std::ostream* getTlsOss(); // returns a thread-local ostringstream
+ DOCTEST_INTERFACE String getTlsOssResult();
+
+ template <bool C>
+ struct StringMakerBase
+ {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T)) {
+ return "{?}";
+ }
+ };
+
+ template <>
+ struct StringMakerBase<true>
+ {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T) in) {
+ *getTlsOss() << in;
+ return getTlsOssResult();
+ }
+ };
+
+ DOCTEST_INTERFACE String rawMemoryToString(const void* object, unsigned size);
+
+ template <typename T>
+ String rawMemoryToString(const DOCTEST_REF_WRAP(T) object) {
+ return rawMemoryToString(&object, sizeof(object));
+ }
+
+ template <typename T>
+ const char* type_to_string() {
+ return "<>";
+ }
+} // namespace detail
+
+template <typename T>
+struct StringMaker : public detail::StringMakerBase<detail::has_insertion_operator<T>::value>
+{};
+
+template <typename T>
+struct StringMaker<T*>
+{
+ template <typename U>
+ static String convert(U* p) {
+ if(p)
+ return detail::rawMemoryToString(p);
+ return "NULL";
+ }
+};
+
+template <typename R, typename C>
+struct StringMaker<R C::*>
+{
+ static String convert(R C::*p) {
+ if(p)
+ return detail::rawMemoryToString(p);
+ return "NULL";
+ }
+};
+
+template <typename T, typename detail::enable_if<!detail::is_enum<T>::value, bool>::type = true>
+String toString(const DOCTEST_REF_WRAP(T) value) {
+ return StringMaker<T>::convert(value);
+}
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+DOCTEST_INTERFACE String toString(char* in);
+DOCTEST_INTERFACE String toString(const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+DOCTEST_INTERFACE String toString(bool in);
+DOCTEST_INTERFACE String toString(float in);
+DOCTEST_INTERFACE String toString(double in);
+DOCTEST_INTERFACE String toString(double long in);
+
+DOCTEST_INTERFACE String toString(char in);
+DOCTEST_INTERFACE String toString(char signed in);
+DOCTEST_INTERFACE String toString(char unsigned in);
+DOCTEST_INTERFACE String toString(int short in);
+DOCTEST_INTERFACE String toString(int short unsigned in);
+DOCTEST_INTERFACE String toString(int in);
+DOCTEST_INTERFACE String toString(int unsigned in);
+DOCTEST_INTERFACE String toString(int long in);
+DOCTEST_INTERFACE String toString(int long unsigned in);
+DOCTEST_INTERFACE String toString(int long long in);
+DOCTEST_INTERFACE String toString(int long long unsigned in);
+DOCTEST_INTERFACE String toString(std::nullptr_t in);
+
+template <typename T, typename detail::enable_if<detail::is_enum<T>::value, bool>::type = true>
+String toString(const DOCTEST_REF_WRAP(T) value) {
+ typedef typename detail::underlying_type<T>::type UT;
+ return toString(static_cast<UT>(value));
+}
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
+class DOCTEST_INTERFACE Approx
+{
+public:
+ explicit Approx(double value);
+
+ Approx operator()(double value) const;
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template <typename T>
+ explicit Approx(const T& value,
+ typename detail::enable_if<std::is_constructible<double, T>::value>::type* =
+ static_cast<T*>(nullptr)) {
+ *this = Approx(static_cast<double>(value));
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& epsilon(double newEpsilon);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template <typename T>
+ typename detail::enable_if<std::is_constructible<double, T>::value, Approx&>::type epsilon(
+ const T& newEpsilon) {
+ m_epsilon = static_cast<double>(newEpsilon);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ Approx& scale(double newScale);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ template <typename T>
+ typename detail::enable_if<std::is_constructible<double, T>::value, Approx&>::type scale(
+ const T& newScale) {
+ m_scale = static_cast<double>(newScale);
+ return *this;
+ }
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format off
+ DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs);
+ DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs);
+ DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs);
+
+ DOCTEST_INTERFACE friend String toString(const Approx& in);
+
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+#define DOCTEST_APPROX_PREFIX \
+ template <typename T> friend typename detail::enable_if<std::is_constructible<double, T>::value, bool>::type
+
+ DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(double(lhs), rhs); }
+ DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
+ DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
+ DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return double(lhs) < rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < double(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return double(lhs) > rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > double(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return double(lhs) < rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < double(rhs) && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return double(lhs) > rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > double(rhs) && lhs != rhs; }
+#undef DOCTEST_APPROX_PREFIX
+#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+
+ // clang-format on
+
+private:
+ double m_epsilon;
+ double m_scale;
+ double m_value;
+};
+
+DOCTEST_INTERFACE String toString(const Approx& in);
+
+DOCTEST_INTERFACE const ContextOptions* getContextOptions();
+
+#if !defined(DOCTEST_CONFIG_DISABLE)
+
+namespace detail {
+ // clang-format off
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ template<class T> struct decay_array { typedef T type; };
+ template<class T, unsigned N> struct decay_array<T[N]> { typedef T* type; };
+ template<class T> struct decay_array<T[]> { typedef T* type; };
+
+ template<class T> struct not_char_pointer { enum { value = 1 }; };
+ template<> struct not_char_pointer<char*> { enum { value = 0 }; };
+ template<> struct not_char_pointer<const char*> { enum { value = 0 }; };
+
+ template<class T> struct can_use_op : public not_char_pointer<typename decay_array<T>::type> {};
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+ struct DOCTEST_INTERFACE TestFailureException
+ {
+ };
+
+ DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_NORETURN
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_INTERFACE void throwException();
+
+ struct DOCTEST_INTERFACE Subcase
+ {
+ SubcaseSignature m_signature;
+ bool m_entered = false;
+
+ Subcase(const String& name, const char* file, int line);
+ ~Subcase();
+
+ operator bool() const;
+ };
+
+ template <typename L, typename R>
+ String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ return toString(lhs) + op + toString(rhs);
+ }
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
+#endif
+
+// This will check if there is any way it could find a operator like member or friend and uses it.
+// If not it doesn't find the operator or if the operator at global scope is defined after
+// this template, the template won't be instantiated due to SFINAE. Once the template is not
+// instantiated it can look for global operator using normal conversions.
+#define SFINAE_OP(ret,op) decltype(doctest::detail::declval<L>() op doctest::detail::declval<R>(),static_cast<ret>(0))
+
+#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
+ template <typename R> \
+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
+ bool res = op_macro(doctest::detail::forward<L>(lhs), doctest::detail::forward<R>(rhs)); \
+ if(m_at & assertType::is_false) \
+ res = !res; \
+ if(!res || doctest::getContextOptions()->success) \
+ return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \
+ return Result(res); \
+ }
+
+ // more checks could be added - like in Catch:
+ // https://github.com/catchorg/Catch2/pull/1480/files
+ // https://github.com/catchorg/Catch2/pull/1481/files
+#define DOCTEST_FORBIT_EXPRESSION(rt, op) \
+ template <typename R> \
+ rt& operator op(const R&) { \
+ static_assert(deferred_false<R>::value, \
+ "Expression Too Complex Please Rewrite As Binary Comparison!"); \
+ return *this; \
+ }
+
+ struct DOCTEST_INTERFACE Result
+ {
+ bool m_passed;
+ String m_decomp;
+
+ Result(bool passed, const String& decomposition = String());
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Result, &)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^)
+ DOCTEST_FORBIT_EXPRESSION(Result, |)
+ DOCTEST_FORBIT_EXPRESSION(Result, &&)
+ DOCTEST_FORBIT_EXPRESSION(Result, ||)
+ DOCTEST_FORBIT_EXPRESSION(Result, ==)
+ DOCTEST_FORBIT_EXPRESSION(Result, !=)
+ DOCTEST_FORBIT_EXPRESSION(Result, <)
+ DOCTEST_FORBIT_EXPRESSION(Result, >)
+ DOCTEST_FORBIT_EXPRESSION(Result, <=)
+ DOCTEST_FORBIT_EXPRESSION(Result, >=)
+ DOCTEST_FORBIT_EXPRESSION(Result, =)
+ DOCTEST_FORBIT_EXPRESSION(Result, +=)
+ DOCTEST_FORBIT_EXPRESSION(Result, -=)
+ DOCTEST_FORBIT_EXPRESSION(Result, *=)
+ DOCTEST_FORBIT_EXPRESSION(Result, /=)
+ DOCTEST_FORBIT_EXPRESSION(Result, %=)
+ DOCTEST_FORBIT_EXPRESSION(Result, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Result, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Result, &=)
+ DOCTEST_FORBIT_EXPRESSION(Result, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Result, |=)
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
+ //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+ // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
+ DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
+ DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
+ //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ // clang-format off
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE bool
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
+ inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
+ inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
+ inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
+ inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
+ inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ // clang-format on
+
+#define DOCTEST_RELATIONAL_OP(name, op) \
+ template <typename L, typename R> \
+ DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \
+ const DOCTEST_REF_WRAP(R) rhs) { \
+ return lhs op rhs; \
+ }
+
+ DOCTEST_RELATIONAL_OP(eq, ==)
+ DOCTEST_RELATIONAL_OP(ne, !=)
+ DOCTEST_RELATIONAL_OP(lt, <)
+ DOCTEST_RELATIONAL_OP(gt, >)
+ DOCTEST_RELATIONAL_OP(le, <=)
+ DOCTEST_RELATIONAL_OP(ge, >=)
+
+#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) l == r
+#define DOCTEST_CMP_NE(l, r) l != r
+#define DOCTEST_CMP_GT(l, r) l > r
+#define DOCTEST_CMP_LT(l, r) l < r
+#define DOCTEST_CMP_GE(l, r) l >= r
+#define DOCTEST_CMP_LE(l, r) l <= r
+#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+#define DOCTEST_CMP_EQ(l, r) eq(l, r)
+#define DOCTEST_CMP_NE(l, r) ne(l, r)
+#define DOCTEST_CMP_GT(l, r) gt(l, r)
+#define DOCTEST_CMP_LT(l, r) lt(l, r)
+#define DOCTEST_CMP_GE(l, r) ge(l, r)
+#define DOCTEST_CMP_LE(l, r) le(l, r)
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+ template <typename L>
+ // cppcheck-suppress copyCtorAndEqOperator
+ struct Expression_lhs
+ {
+ L lhs;
+ assertType::Enum m_at;
+
+ explicit Expression_lhs(L&& in, assertType::Enum at)
+ : lhs(doctest::detail::forward<L>(in))
+ , m_at(at) {}
+
+ DOCTEST_NOINLINE operator Result() {
+// this is needed only foc MSVC 2015:
+// https://ci.appveyor.com/project/onqtam/doctest/builds/38181202
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
+ bool res = static_cast<bool>(lhs);
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ res = !res;
+
+ if(!res || getContextOptions()->success)
+ return Result(res, toString(lhs));
+ return Result(res);
+ }
+
+ /* This is required for user-defined conversions from Expression_lhs to L */
+ //operator L() const { return lhs; }
+ operator L() const { return lhs; }
+
+ // clang-format off
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
+ DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
+ // clang-format on
+
+ // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=)
+ // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
+ // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<)
+ DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>)
+ };
+
+#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
+
+#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#endif
+
+ struct DOCTEST_INTERFACE ExpressionDecomposer
+ {
+ assertType::Enum m_at;
+
+ ExpressionDecomposer(assertType::Enum at);
+
+ // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
+ // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
+ // https://github.com/catchorg/Catch2/issues/870
+ // https://github.com/catchorg/Catch2/issues/565
+ template <typename L>
+ Expression_lhs<L> operator<<(L &&operand) {
+ return Expression_lhs<L>(doctest::detail::forward<L>(operand), m_at);
+ }
+ };
+
+ struct DOCTEST_INTERFACE TestSuite
+ {
+ const char* m_test_suite;
+ const char* m_description;
+ bool m_skip;
+ bool m_no_breaks;
+ bool m_no_output;
+ bool m_may_fail;
+ bool m_should_fail;
+ int m_expected_failures;
+ double m_timeout;
+
+ TestSuite& operator*(const char* in);
+
+ template <typename T>
+ TestSuite& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+ };
+
+ typedef void (*funcType)();
+
+ struct DOCTEST_INTERFACE TestCase : public TestCaseData
+ {
+ funcType m_test; // a function pointer to the test case
+
+ const char* m_type; // for templated test cases - gets appended to the real name
+ int m_template_id; // an ID used to distinguish between the different versions of a templated test case
+ String m_full_name; // contains the name (only for templated test cases!) + the template type
+
+ TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
+ const char* type = "", int template_id = -1);
+
+ TestCase(const TestCase& other);
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
+ TestCase& operator=(const TestCase& other);
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ TestCase& operator*(const char* in);
+
+ template <typename T>
+ TestCase& operator*(const T& in) {
+ in.fill(*this);
+ return *this;
+ }
+
+ bool operator<(const TestCase& other) const;
+ };
+
+ // forward declarations of functions used by the macros
+ DOCTEST_INTERFACE int regTest(const TestCase& tc);
+ DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
+ DOCTEST_INTERFACE bool isDebuggerActive();
+
+ template<typename T>
+ int instantiationHelper(const T&) { return 0; }
+
+ namespace binaryAssertComparison {
+ enum Enum
+ {
+ eq = 0,
+ ne,
+ gt,
+ lt,
+ ge,
+ le
+ };
+ } // namespace binaryAssertComparison
+
+ // clang-format off
+ template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
+
+#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
+ template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
+ // clang-format on
+
+ DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
+ DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
+ DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
+ DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
+ DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
+ DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
+
+ struct DOCTEST_INTERFACE ResultBuilder : public AssertData
+ {
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type = "", const char* exception_string = "");
+
+ void setResult(const Result& res);
+
+ template <int comparison, typename L, typename R>
+ DOCTEST_NOINLINE void binary_assert(const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ m_failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
+ if(m_failed || getContextOptions()->success)
+ m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
+ }
+
+ template <typename L>
+ DOCTEST_NOINLINE void unary_assert(const DOCTEST_REF_WRAP(L) val) {
+ m_failed = !val;
+
+ if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ m_failed = !m_failed;
+
+ if(m_failed || getContextOptions()->success)
+ m_decomp = toString(val);
+ }
+
+ void translateException();
+
+ bool log();
+ void react() const;
+ };
+
+ namespace assertAction {
+ enum Enum
+ {
+ nothing = 0,
+ dbgbreak = 1,
+ shouldthrow = 2
+ };
+ } // namespace assertAction
+
+ DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
+
+ DOCTEST_INTERFACE void decomp_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, Result result);
+
+#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \
+ do { \
+ if(!is_running_in_test) { \
+ if(failed) { \
+ ResultBuilder rb(at, file, line, expr); \
+ rb.m_failed = failed; \
+ rb.m_decomp = decomp; \
+ failed_out_of_a_testing_context(rb); \
+ if(isDebuggerActive() && !getContextOptions()->no_breaks) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ if(checkIfShouldThrow(at)) \
+ throwException(); \
+ } \
+ return; \
+ } \
+ } while(false)
+
+#define DOCTEST_ASSERT_IN_TESTS(decomp) \
+ ResultBuilder rb(at, file, line, expr); \
+ rb.m_failed = failed; \
+ if(rb.m_failed || getContextOptions()->success) \
+ rb.m_decomp = decomp; \
+ if(rb.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ if(rb.m_failed && checkIfShouldThrow(at)) \
+ throwException()
+
+ template <int comparison, typename L, typename R>
+ DOCTEST_NOINLINE void binary_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const DOCTEST_REF_WRAP(L) lhs,
+ const DOCTEST_REF_WRAP(R) rhs) {
+ bool failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ }
+
+ template <typename L>
+ DOCTEST_NOINLINE void unary_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const DOCTEST_REF_WRAP(L) val) {
+ bool failed = !val;
+
+ if(at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ failed = !failed;
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS(toString(val));
+ DOCTEST_ASSERT_IN_TESTS(toString(val));
+ }
+
+ struct DOCTEST_INTERFACE IExceptionTranslator
+ {
+ IExceptionTranslator();
+ virtual ~IExceptionTranslator();
+ virtual bool translate(String&) const = 0;
+ };
+
+ template <typename T>
+ class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class
+ {
+ public:
+ explicit ExceptionTranslator(String (*translateFunction)(T))
+ : m_translateFunction(translateFunction) {}
+
+ bool translate(String& res) const override {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ try {
+ throw; // lgtm [cpp/rethrow-no-exception]
+ // cppcheck-suppress catchExceptionByValue
+ } catch(T ex) { // NOLINT
+ res = m_translateFunction(ex); //!OCLINT parameter reassignment
+ return true;
+ } catch(...) {} //!OCLINT - empty catch statement
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ static_cast<void>(res); // to silence -Wunused-parameter
+ return false;
+ }
+
+ private:
+ String (*m_translateFunction)(T);
+ };
+
+ DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
+
+ template <bool C>
+ struct StringStreamBase
+ {
+ template <typename T>
+ static void convert(std::ostream* s, const T& in) {
+ *s << toString(in);
+ }
+
+ // always treat char* as a string in this context - no matter
+ // if DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING is defined
+ static void convert(std::ostream* s, const char* in) { *s << String(in); }
+ };
+
+ template <>
+ struct StringStreamBase<true>
+ {
+ template <typename T>
+ static void convert(std::ostream* s, const T& in) {
+ *s << in;
+ }
+ };
+
+ template <typename T>
+ struct StringStream : public StringStreamBase<has_insertion_operator<T>::value>
+ {};
+
+ template <typename T>
+ void toStream(std::ostream* s, const T& value) {
+ StringStream<T>::convert(s, value);
+ }
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char* in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, const char* in);
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ DOCTEST_INTERFACE void toStream(std::ostream* s, bool in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, float in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, double in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, double long in);
+
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char signed in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, char unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int short in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int short unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long unsigned in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
+ DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
+
+ // ContextScope base class used to allow implementing methods of ContextScope
+ // that don't depend on the template parameter in doctest.cpp.
+ class DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
+ protected:
+ ContextScopeBase();
+
+ void destroy();
+ };
+
+ template <typename L> class ContextScope : public ContextScopeBase
+ {
+ const L lambda_;
+
+ public:
+ explicit ContextScope(const L &lambda) : lambda_(lambda) {}
+
+ ContextScope(ContextScope &&other) : lambda_(other.lambda_) {}
+
+ void stringify(std::ostream* s) const override { lambda_(s); }
+
+ ~ContextScope() override { destroy(); }
+ };
+
+ struct DOCTEST_INTERFACE MessageBuilder : public MessageData
+ {
+ std::ostream* m_stream;
+
+ MessageBuilder(const char* file, int line, assertType::Enum severity);
+ MessageBuilder() = delete;
+ ~MessageBuilder();
+
+ // the preferred way of chaining parameters for stringification
+ template <typename T>
+ MessageBuilder& operator,(const T& in) {
+ toStream(m_stream, in);
+ return *this;
+ }
+
+ // kept here just for backwards-compatibility - the comma operator should be preferred now
+ template <typename T>
+ MessageBuilder& operator<<(const T& in) { return this->operator,(in); }
+
+ // the `,` operator has the lowest operator precedence - if `<<` is used by the user then
+ // the `,` operator will be called last which is not what we want and thus the `*` operator
+ // is used first (has higher operator precedence compared to `<<`) so that we guarantee that
+ // an operator of the MessageBuilder class is called first before the rest of the parameters
+ template <typename T>
+ MessageBuilder& operator*(const T& in) { return this->operator,(in); }
+
+ bool log();
+ void react();
+ };
+
+ template <typename L>
+ ContextScope<L> MakeContextScope(const L &lambda) {
+ return ContextScope<L>(lambda);
+ }
+} // namespace detail
+
+#define DOCTEST_DEFINE_DECORATOR(name, type, def) \
+ struct name \
+ { \
+ type data; \
+ name(type in = def) \
+ : data(in) {} \
+ void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \
+ void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \
+ }
+
+DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
+DOCTEST_DEFINE_DECORATOR(description, const char*, "");
+DOCTEST_DEFINE_DECORATOR(skip, bool, true);
+DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
+DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
+DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
+DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
+DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
+DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0);
+
+template <typename T>
+int registerExceptionTranslator(String (*translateFunction)(T)) {
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors")
+ static detail::ExceptionTranslator<T> exceptionTranslator(translateFunction);
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ detail::registerExceptionTranslatorImpl(&exceptionTranslator);
+ return 0;
+}
+
+} // namespace doctest
+
+// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro
+// introduces an anonymous namespace in which getCurrentTestSuite gets overridden
+namespace doctest_detail_test_suite_ns {
+DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite();
+} // namespace doctest_detail_test_suite_ns
+
+namespace doctest {
+#else // DOCTEST_CONFIG_DISABLE
+template <typename T>
+int registerExceptionTranslator(String (*)(T)) {
+ return 0;
+}
+#endif // DOCTEST_CONFIG_DISABLE
+
+namespace detail {
+ typedef void (*assert_handler)(const AssertData&);
+ struct ContextState;
+} // namespace detail
+
+class DOCTEST_INTERFACE Context
+{
+ detail::ContextState* p;
+
+ void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
+
+public:
+ explicit Context(int argc = 0, const char* const* argv = nullptr);
+
+ ~Context();
+
+ void applyCommandLine(int argc, const char* const* argv);
+
+ void addFilter(const char* filter, const char* value);
+ void clearFilters();
+ void setOption(const char* option, int value);
+ void setOption(const char* option, const char* value);
+
+ bool shouldExit();
+
+ void setAsDefaultForAssertsOutOfTestCases();
+
+ void setAssertHandler(detail::assert_handler ah);
+
+ int run();
+};
+
+namespace TestCaseFailureReason {
+ enum Enum
+ {
+ None = 0,
+ AssertFailure = 1, // an assertion has failed in the test case
+ Exception = 2, // test case threw an exception
+ Crash = 4, // a crash...
+ TooManyFailedAsserts = 8, // the abort-after option
+ Timeout = 16, // see the timeout decorator
+ ShouldHaveFailedButDidnt = 32, // see the should_fail decorator
+ ShouldHaveFailedAndDid = 64, // see the should_fail decorator
+ DidntFailExactlyNumTimes = 128, // see the expected_failures decorator
+ FailedExactlyNumTimes = 256, // see the expected_failures decorator
+ CouldHaveFailedAndDid = 512 // see the may_fail decorator
+ };
+} // namespace TestCaseFailureReason
+
+struct DOCTEST_INTERFACE CurrentTestCaseStats
+{
+ int numAssertsCurrentTest;
+ int numAssertsFailedCurrentTest;
+ double seconds;
+ int failure_flags; // use TestCaseFailureReason::Enum
+};
+
+struct DOCTEST_INTERFACE TestCaseException
+{
+ String error_string;
+ bool is_crash;
+};
+
+struct DOCTEST_INTERFACE TestRunStats
+{
+ unsigned numTestCases;
+ unsigned numTestCasesPassingFilters;
+ unsigned numTestSuitesPassingFilters;
+ unsigned numTestCasesFailed;
+ int numAsserts;
+ int numAssertsFailed;
+};
+
+struct QueryData
+{
+ const TestRunStats* run_stats = nullptr;
+ const TestCaseData** data = nullptr;
+ unsigned num_data = 0;
+};
+
+struct DOCTEST_INTERFACE IReporter
+{
+ // The constructor has to accept "const ContextOptions&" as a single argument
+ // which has most of the options for the run + a pointer to the stdout stream
+ // Reporter(const ContextOptions& in)
+
+ // called when a query should be reported (listing test cases, printing the version, etc.)
+ virtual void report_query(const QueryData&) = 0;
+
+ // called when the whole test run starts
+ virtual void test_run_start() = 0;
+ // called when the whole test run ends (caching a pointer to the input doesn't make sense here)
+ virtual void test_run_end(const TestRunStats&) = 0;
+
+ // called when a test case is started (safe to cache a pointer to the input)
+ virtual void test_case_start(const TestCaseData&) = 0;
+ // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
+ virtual void test_case_reenter(const TestCaseData&) = 0;
+ // called when a test case has ended
+ virtual void test_case_end(const CurrentTestCaseStats&) = 0;
+
+ // called when an exception is thrown from the test case (or it crashes)
+ virtual void test_case_exception(const TestCaseException&) = 0;
+
+ // called whenever a subcase is entered (don't cache pointers to the input)
+ virtual void subcase_start(const SubcaseSignature&) = 0;
+ // called whenever a subcase is exited (don't cache pointers to the input)
+ virtual void subcase_end() = 0;
+
+ // called for each assert (don't cache pointers to the input)
+ virtual void log_assert(const AssertData&) = 0;
+ // called for each message (don't cache pointers to the input)
+ virtual void log_message(const MessageData&) = 0;
+
+ // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator
+ // or isn't in the execution range (between first and last) (safe to cache a pointer to the input)
+ virtual void test_case_skipped(const TestCaseData&) = 0;
+
+ // doctest will not be managing the lifetimes of reporters given to it but this would still be nice to have
+ virtual ~IReporter();
+
+ // can obtain all currently active contexts and stringify them if one wishes to do so
+ static int get_num_active_contexts();
+ static const IContextScope* const* get_active_contexts();
+
+ // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown
+ static int get_num_stringified_contexts();
+ static const String* get_stringified_contexts();
+};
+
+namespace detail {
+ typedef IReporter* (*reporterCreatorFunc)(const ContextOptions&);
+
+ DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
+
+ template <typename Reporter>
+ IReporter* reporterCreator(const ContextOptions& o) {
+ return new Reporter(o);
+ }
+} // namespace detail
+
+template <typename Reporter>
+int registerReporter(const char* name, int priority, bool isReporter) {
+ detail::registerReporterImpl(name, priority, detail::reporterCreator<Reporter>, isReporter);
+ return 0;
+}
+} // namespace doctest
+
+// if registering is not disabled
+#if !defined(DOCTEST_CONFIG_DISABLE)
+
+// common code in asserts - for convenience
+#define DOCTEST_ASSERT_LOG_AND_REACT(b) \
+ if(b.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ b.react()
+
+#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#define DOCTEST_WRAP_IN_TRY(x) x;
+#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#define DOCTEST_WRAP_IN_TRY(x) \
+ try { \
+ x; \
+ } catch(...) { _DOCTEST_RB.translateException(); }
+#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+
+#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
+#define DOCTEST_CAST_TO_VOID(...) \
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \
+ static_cast<void>(__VA_ARGS__); \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
+#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__;
+#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
+
+// registers the test by initializing a dummy var with a function
+#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \
+ global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
+ doctest::detail::regTest( \
+ doctest::detail::TestCase( \
+ f, __FILE__, __LINE__, \
+ doctest_detail_test_suite_ns::getCurrentTestSuite()) * \
+ decorators); \
+ DOCTEST_GLOBAL_NO_WARNINGS_END()
+
+#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \
+ namespace { \
+ struct der : public base \
+ { \
+ void f(); \
+ }; \
+ static void func() { \
+ der v; \
+ v.f(); \
+ } \
+ DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \
+ } \
+ inline DOCTEST_NOINLINE void der::f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \
+ static void f(); \
+ DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \
+ static void f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \
+ static doctest::detail::funcType proxy() { return f; } \
+ DOCTEST_REGISTER_FUNCTION(inline const, proxy(), decorators) \
+ static void f()
+
+// for registering tests
+#define DOCTEST_TEST_CASE(decorators) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators)
+
+// for registering tests in classes - requires C++17 for inline variables!
+#if __cplusplus >= 201703L || (DOCTEST_MSVC >= DOCTEST_COMPILER(19, 12, 0) && _MSVC_LANG >= 201703L)
+#define DOCTEST_TEST_CASE_CLASS(decorators) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_PROXY_), \
+ decorators)
+#else // DOCTEST_TEST_CASE_CLASS
+#define DOCTEST_TEST_CASE_CLASS(...) \
+ TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER
+#endif // DOCTEST_TEST_CASE_CLASS
+
+// for registering tests with a fixture
+#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators)
+
+// for converting types to strings without the <typeinfo> header and demangling
+#define DOCTEST_TYPE_TO_STRING_IMPL(...) \
+ template <> \
+ inline const char* type_to_string<__VA_ARGS__>() { \
+ return "<" #__VA_ARGS__ ">"; \
+ }
+#define DOCTEST_TYPE_TO_STRING(...) \
+ namespace doctest { namespace detail { \
+ DOCTEST_TYPE_TO_STRING_IMPL(__VA_ARGS__) \
+ } \
+ } \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
+ template <typename T> \
+ static void func(); \
+ namespace { \
+ template <typename Tuple> \
+ struct iter; \
+ template <typename Type, typename... Rest> \
+ struct iter<std::tuple<Type, Rest...>> \
+ { \
+ iter(const char* file, unsigned line, int index) { \
+ doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
+ doctest_detail_test_suite_ns::getCurrentTestSuite(), \
+ doctest::detail::type_to_string<Type>(), \
+ int(line) * 1000 + index) \
+ * dec); \
+ iter<std::tuple<Rest...>>(file, line, index + 1); \
+ } \
+ }; \
+ template <> \
+ struct iter<std::tuple<>> \
+ { \
+ iter(const char*, unsigned, int) {} \
+ }; \
+ } \
+ template <typename T> \
+ static void func()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \
+ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_))
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \
+ doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\
+ DOCTEST_GLOBAL_NO_WARNINGS_END()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \
+ template <typename T> \
+ static void anon()
+
+#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \
+ DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__)
+
+// for subcases
+#define DOCTEST_SUBCASE(name) \
+ if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
+ doctest::detail::Subcase(name, __FILE__, __LINE__))
+
+// for grouping tests in test suites by using code blocks
+#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \
+ namespace ns_name { namespace doctest_detail_test_suite_ns { \
+ static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \
+ static doctest::detail::TestSuite data{}; \
+ static bool inited = false; \
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
+ if(!inited) { \
+ data* decorators; \
+ inited = true; \
+ } \
+ return data; \
+ } \
+ } \
+ } \
+ namespace ns_name
+
+#define DOCTEST_TEST_SUITE(decorators) \
+ DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUITE_))
+
+// for starting a testsuite block
+#define DOCTEST_TEST_SUITE_BEGIN(decorators) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators); \
+ DOCTEST_GLOBAL_NO_WARNINGS_END() \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for ending a testsuite block
+#define DOCTEST_TEST_SUITE_END \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * ""); \
+ DOCTEST_GLOBAL_NO_WARNINGS_END() \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for registering exception translators
+#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \
+ inline doctest::String translatorName(signature); \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)) = \
+ doctest::registerExceptionTranslator(translatorName); \
+ DOCTEST_GLOBAL_NO_WARNINGS_END() \
+ doctest::String translatorName(signature)
+
+#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
+ DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \
+ signature)
+
+// for registering reporters
+#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
+ doctest::registerReporter<reporter>(name, priority, true); \
+ DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for registering listeners
+#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
+ doctest::registerReporter<reporter>(name, priority, false); \
+ DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for logging
+#define DOCTEST_INFO(...) \
+ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \
+ __VA_ARGS__)
+
+#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \
+ auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
+ [&](std::ostream* s_name) { \
+ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
+ mb_name.m_stream = s_name; \
+ mb_name * __VA_ARGS__; \
+ })
+
+#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
+
+#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \
+ do { \
+ doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \
+ mb * __VA_ARGS__; \
+ DOCTEST_ASSERT_LOG_AND_REACT(mb); \
+ } while(false)
+
+// clang-format off
+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__)
+// clang-format on
+
+#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__)
+#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__)
+#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__)
+
+#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility.
+
+#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.setResult( \
+ doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
+ << __VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
+ do { \
+ DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \
+ } while(false)
+
+#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+// necessary for <ASSERT>_MESSAGE
+#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1
+
+#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
+ doctest::detail::decomp_assert( \
+ doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \
+ doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
+ << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__)
+#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__)
+#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__)
+#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__)
+#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__)
+#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__)
+
+// clang-format off
+#define DOCTEST_WARN_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while(false)
+#define DOCTEST_CHECK_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while(false)
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while(false)
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while(false)
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while(false)
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while(false)
+// clang-format on
+
+#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \
+ do { \
+ if(!doctest::getContextOptions()->no_throw) { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #expr, #__VA_ARGS__, message); \
+ try { \
+ DOCTEST_CAST_TO_VOID(expr) \
+ } catch(const typename doctest::detail::remove_const< \
+ typename doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \
+ _DOCTEST_RB.translateException(); \
+ _DOCTEST_RB.m_threw_as = true; \
+ } catch(...) { _DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } \
+ } while(false)
+
+#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \
+ do { \
+ if(!doctest::getContextOptions()->no_throw) { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, expr_str, "", __VA_ARGS__); \
+ try { \
+ DOCTEST_CAST_TO_VOID(expr) \
+ } catch(...) { _DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } \
+ } while(false)
+
+#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \
+ do { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ try { \
+ DOCTEST_CAST_TO_VOID(__VA_ARGS__) \
+ } catch(...) { _DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } while(false)
+
+// clang-format off
+#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "")
+#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "")
+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "")
+
+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__)
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__)
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__)
+
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
+
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__)
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__)
+
+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__)
+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__)
+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__)
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } while(false)
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } while(false)
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } while(false)
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } while(false)
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } while(false)
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while(false)
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } while(false)
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } while(false)
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while(false)
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while(false)
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while(false)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while(false)
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } while(false)
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } while(false)
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } while(false)
+// clang-format on
+
+#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \
+ do { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY( \
+ _DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
+ __VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } while(false)
+
+#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
+ do { \
+ doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(__VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } while(false)
+
+#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \
+ doctest::detail::binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
+ doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__)
+
+#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
+ doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \
+ #__VA_ARGS__, __VA_ARGS__)
+
+#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
+
+#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__)
+#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__)
+#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__)
+#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__)
+#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__)
+#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__)
+#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__)
+#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__)
+#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__)
+#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__)
+#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__)
+#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__)
+#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__)
+#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__)
+#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__)
+#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__)
+#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__)
+#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__)
+
+#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__)
+#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__)
+#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__)
+#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__)
+#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__)
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__)
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#undef DOCTEST_WARN_THROWS
+#undef DOCTEST_CHECK_THROWS
+#undef DOCTEST_REQUIRE_THROWS
+#undef DOCTEST_WARN_THROWS_AS
+#undef DOCTEST_CHECK_THROWS_AS
+#undef DOCTEST_REQUIRE_THROWS_AS
+#undef DOCTEST_WARN_THROWS_WITH
+#undef DOCTEST_CHECK_THROWS_WITH
+#undef DOCTEST_REQUIRE_THROWS_WITH
+#undef DOCTEST_WARN_THROWS_WITH_AS
+#undef DOCTEST_CHECK_THROWS_WITH_AS
+#undef DOCTEST_REQUIRE_THROWS_WITH_AS
+#undef DOCTEST_WARN_NOTHROW
+#undef DOCTEST_CHECK_NOTHROW
+#undef DOCTEST_REQUIRE_NOTHROW
+
+#undef DOCTEST_WARN_THROWS_MESSAGE
+#undef DOCTEST_CHECK_THROWS_MESSAGE
+#undef DOCTEST_REQUIRE_THROWS_MESSAGE
+#undef DOCTEST_WARN_THROWS_AS_MESSAGE
+#undef DOCTEST_CHECK_THROWS_AS_MESSAGE
+#undef DOCTEST_REQUIRE_THROWS_AS_MESSAGE
+#undef DOCTEST_WARN_THROWS_WITH_MESSAGE
+#undef DOCTEST_CHECK_THROWS_WITH_MESSAGE
+#undef DOCTEST_REQUIRE_THROWS_WITH_MESSAGE
+#undef DOCTEST_WARN_THROWS_WITH_AS_MESSAGE
+#undef DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE
+#undef DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE
+#undef DOCTEST_WARN_NOTHROW_MESSAGE
+#undef DOCTEST_CHECK_NOTHROW_MESSAGE
+#undef DOCTEST_REQUIRE_NOTHROW_MESSAGE
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#define DOCTEST_WARN_THROWS(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS(...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_AS(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_NOTHROW(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_NOTHROW(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_NOTHROW(...) (static_cast<void>(0))
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
+
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#undef DOCTEST_REQUIRE
+#undef DOCTEST_REQUIRE_FALSE
+#undef DOCTEST_REQUIRE_MESSAGE
+#undef DOCTEST_REQUIRE_FALSE_MESSAGE
+#undef DOCTEST_REQUIRE_EQ
+#undef DOCTEST_REQUIRE_NE
+#undef DOCTEST_REQUIRE_GT
+#undef DOCTEST_REQUIRE_LT
+#undef DOCTEST_REQUIRE_GE
+#undef DOCTEST_REQUIRE_LE
+#undef DOCTEST_REQUIRE_UNARY
+#undef DOCTEST_REQUIRE_UNARY_FALSE
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+// =================================================================================================
+// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! ==
+// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! ==
+// =================================================================================================
+#else // DOCTEST_CONFIG_DISABLE
+
+#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
+ namespace { \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ struct der : public base \
+ { void f(); }; \
+ } \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ inline void der<DOCTEST_UNUSED_TEMPLATE_TYPE>::f()
+
+#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ static inline void f()
+
+// for registering tests
+#define DOCTEST_TEST_CASE(name) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for registering tests in classes
+#define DOCTEST_TEST_CASE_CLASS(name) \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for registering tests with a fixture
+#define DOCTEST_TEST_CASE_FIXTURE(x, name) \
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \
+ DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+
+// for converting types to strings without the <typeinfo> header and demangling
+#define DOCTEST_TYPE_TO_STRING(...) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#define DOCTEST_TYPE_TO_STRING_IMPL(...)
+
+// for typed tests
+#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \
+ template <typename type> \
+ inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \
+ template <typename type> \
+ inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)()
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
+ typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for subcases
+#define DOCTEST_SUBCASE(name)
+
+// for a testsuite block
+#define DOCTEST_TEST_SUITE(name) namespace
+
+// for starting a testsuite block
+#define DOCTEST_TEST_SUITE_BEGIN(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+// for ending a testsuite block
+#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+
+#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
+ template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
+ static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature)
+
+#define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
+#define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
+
+#define DOCTEST_INFO(...) (static_cast<void>(0))
+#define DOCTEST_CAPTURE(x) (static_cast<void>(0))
+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast<void>(0))
+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast<void>(0))
+#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast<void>(0))
+#define DOCTEST_MESSAGE(...) (static_cast<void>(0))
+#define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0))
+#define DOCTEST_FAIL(...) (static_cast<void>(0))
+
+#define DOCTEST_WARN(...) (static_cast<void>(0))
+#define DOCTEST_CHECK(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE(...) (static_cast<void>(0))
+#define DOCTEST_WARN_FALSE(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_FALSE(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_FALSE(...) (static_cast<void>(0))
+
+#define DOCTEST_WARN_MESSAGE(cond, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_MESSAGE(cond, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) (static_cast<void>(0))
+
+#define DOCTEST_WARN_THROWS(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS(...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_AS(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_NOTHROW(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_NOTHROW(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_NOTHROW(...) (static_cast<void>(0))
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
+
+#define DOCTEST_WARN_EQ(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_EQ(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_EQ(...) (static_cast<void>(0))
+#define DOCTEST_WARN_NE(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_NE(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_NE(...) (static_cast<void>(0))
+#define DOCTEST_WARN_GT(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_GT(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_GT(...) (static_cast<void>(0))
+#define DOCTEST_WARN_LT(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_LT(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_LT(...) (static_cast<void>(0))
+#define DOCTEST_WARN_GE(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_GE(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_GE(...) (static_cast<void>(0))
+#define DOCTEST_WARN_LE(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_LE(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_LE(...) (static_cast<void>(0))
+
+#define DOCTEST_WARN_UNARY(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_UNARY(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_UNARY(...) (static_cast<void>(0))
+#define DOCTEST_WARN_UNARY_FALSE(...) (static_cast<void>(0))
+#define DOCTEST_CHECK_UNARY_FALSE(...) (static_cast<void>(0))
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) (static_cast<void>(0))
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+// clang-format off
+// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS
+#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ
+#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ
+#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ
+#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE
+#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE
+#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE
+#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT
+#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT
+#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT
+#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT
+#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT
+#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT
+#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE
+#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE
+#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE
+#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE
+#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE
+#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE
+
+#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY
+#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY
+#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
+#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
+#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
+#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
+
+#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__)
+// clang-format on
+
+// BDD style macros
+// clang-format off
+#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name)
+#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name)
+#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__)
+#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id)
+
+#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name)
+#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name)
+#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name)
+#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name)
+#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name)
+// clang-format on
+
+// == SHORT VERSIONS OF THE MACROS
+#if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
+
+#define TEST_CASE(name) DOCTEST_TEST_CASE(name)
+#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
+#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
+#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
+#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
+#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
+#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__)
+#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__)
+#define SUBCASE(name) DOCTEST_SUBCASE(name)
+#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators)
+#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name)
+#define TEST_SUITE_END DOCTEST_TEST_SUITE_END
+#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)
+#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter)
+#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter)
+#define INFO(...) DOCTEST_INFO(__VA_ARGS__)
+#define CAPTURE(x) DOCTEST_CAPTURE(x)
+#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__)
+#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__)
+#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__)
+#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__)
+#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__)
+#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__)
+#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__)
+
+#define WARN(...) DOCTEST_WARN(__VA_ARGS__)
+#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__)
+#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__)
+#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__)
+#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__)
+#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__)
+#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__)
+#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
+#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__)
+#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__)
+#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__)
+#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__)
+#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__)
+#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__)
+#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__)
+#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__)
+#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__)
+#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__)
+#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__)
+
+#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__)
+#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)
+#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__)
+#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
+#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
+#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
+#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__)
+#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__)
+#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
+#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__)
+#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
+#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
+#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
+#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__)
+#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__)
+#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
+#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__)
+#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
+#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
+#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__)
+
+#define SCENARIO(name) DOCTEST_SCENARIO(name)
+#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name)
+#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__)
+#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id)
+#define GIVEN(name) DOCTEST_GIVEN(name)
+#define WHEN(name) DOCTEST_WHEN(name)
+#define AND_WHEN(name) DOCTEST_AND_WHEN(name)
+#define THEN(name) DOCTEST_THEN(name)
+#define AND_THEN(name) DOCTEST_AND_THEN(name)
+
+#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__)
+#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__)
+#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__)
+#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__)
+#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__)
+#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__)
+#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__)
+#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__)
+#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__)
+#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__)
+#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__)
+#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__)
+#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__)
+#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__)
+#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__)
+#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__)
+#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__)
+#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__)
+#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__)
+#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__)
+#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__)
+#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__)
+#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__)
+#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
+
+// KEPT FOR BACKWARDS COMPATIBILITY
+#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__)
+#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__)
+#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__)
+#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__)
+#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__)
+#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__)
+#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__)
+#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__)
+#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__)
+#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__)
+#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__)
+#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__)
+#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__)
+#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__)
+#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__)
+#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__)
+#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__)
+#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__)
+
+#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__)
+#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__)
+#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__)
+#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__)
+#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__)
+#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
+
+#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__)
+
+#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
+
+#if !defined(DOCTEST_CONFIG_DISABLE)
+
+// this is here to clear the 'current test suite' for the current translation unit - at the top
+DOCTEST_TEST_SUITE_END();
+
+// add stringification for primitive/fundamental types
+namespace doctest { namespace detail {
+ DOCTEST_TYPE_TO_STRING_IMPL(bool)
+ DOCTEST_TYPE_TO_STRING_IMPL(float)
+ DOCTEST_TYPE_TO_STRING_IMPL(double)
+ DOCTEST_TYPE_TO_STRING_IMPL(long double)
+ DOCTEST_TYPE_TO_STRING_IMPL(char)
+ DOCTEST_TYPE_TO_STRING_IMPL(signed char)
+ DOCTEST_TYPE_TO_STRING_IMPL(unsigned char)
+#if !DOCTEST_MSVC || defined(_NATIVE_WCHAR_T_DEFINED)
+ DOCTEST_TYPE_TO_STRING_IMPL(wchar_t)
+#endif // not MSVC or wchar_t support enabled
+ DOCTEST_TYPE_TO_STRING_IMPL(short int)
+ DOCTEST_TYPE_TO_STRING_IMPL(unsigned short int)
+ DOCTEST_TYPE_TO_STRING_IMPL(int)
+ DOCTEST_TYPE_TO_STRING_IMPL(unsigned int)
+ DOCTEST_TYPE_TO_STRING_IMPL(long int)
+ DOCTEST_TYPE_TO_STRING_IMPL(unsigned long int)
+ DOCTEST_TYPE_TO_STRING_IMPL(long long int)
+ DOCTEST_TYPE_TO_STRING_IMPL(unsigned long long int)
+}} // namespace doctest::detail
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_LIBRARY_INCLUDED
+
+#ifndef DOCTEST_SINGLE_HEADER
+#define DOCTEST_SINGLE_HEADER
+#endif // DOCTEST_SINGLE_HEADER
+
+#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER)
+
+#ifndef DOCTEST_SINGLE_HEADER
+#include "doctest_fwd.h"
+#endif // DOCTEST_SINGLE_HEADER
+
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros")
+
+#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
+#define DOCTEST_LIBRARY_IMPLEMENTATION
+
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
+DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
+
+DOCTEST_GCC_SUPPRESS_WARNING_PUSH
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
+DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
+DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute")
+
+DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
+DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning
+DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning
+DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration
+DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data
+DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression
+DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated
+DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant
+DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled
+DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified
+DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal
+DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch
+DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding in structs
+DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe
+DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C
+DOCTEST_MSVC_SUPPRESS_WARNING(5045) // Spectre mitigation stuff
+DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted
+DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning)
+// static analysis
+DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept'
+DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable
+DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ...
+DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtor...
+DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
+
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
+
+// required includes - will go only in one translation unit!
+#include <ctime>
+#include <cmath>
+#include <climits>
+// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37
+#ifdef __BORLANDC__
+#include <math.h>
+#endif // __BORLANDC__
+#include <new>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+#include <utility>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <algorithm>
+#include <iomanip>
+#include <vector>
+#include <atomic>
+#include <mutex>
+#include <set>
+#include <map>
+#include <exception>
+#include <stdexcept>
+#include <csignal>
+#include <cfloat>
+#include <cctype>
+#include <cstdint>
+
+#ifdef DOCTEST_PLATFORM_MAC
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/sysctl.h>
+#endif // DOCTEST_PLATFORM_MAC
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+
+// defines for a leaner windows.h
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif // WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif // NOMINMAX
+
+// not sure what AfxWin.h is for - here I do what Catch does
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+#include <io.h>
+
+#else // DOCTEST_PLATFORM_WINDOWS
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+// this is a fix for https://github.com/onqtam/doctest/issues/348
+// https://mail.gnome.org/archives/xml/2012-January/msg00000.html
+#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO)
+#define STDOUT_FILENO fileno(stdout)
+#endif // HAVE_UNISTD_H
+
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
+
+// counts the number of elements in a C array
+#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
+
+#ifdef DOCTEST_CONFIG_DISABLE
+#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled
+#else // DOCTEST_CONFIG_DISABLE
+#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled
+#endif // DOCTEST_CONFIG_DISABLE
+
+#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX
+#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-"
+#endif
+
+#ifndef DOCTEST_THREAD_LOCAL
+#define DOCTEST_THREAD_LOCAL thread_local
+#endif
+
+#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
+#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
+#endif
+
+#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE
+#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64
+#endif
+
+#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX
+#else
+#define DOCTEST_OPTIONS_PREFIX_DISPLAY ""
+#endif
+
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+#endif
+
+namespace doctest {
+
+bool is_running_in_test = false;
+
+namespace {
+ using namespace detail;
+ // case insensitive strcmp
+ int stricmp(const char* a, const char* b) {
+ for(;; a++, b++) {
+ const int d = tolower(*a) - tolower(*b);
+ if(d != 0 || !*a)
+ return d;
+ }
+ }
+
+ template <typename T>
+ String fpToString(T value, int precision) {
+ std::ostringstream oss;
+ oss << std::setprecision(precision) << std::fixed << value;
+ std::string d = oss.str();
+ size_t i = d.find_last_not_of('0');
+ if(i != std::string::npos && i != d.size() - 1) {
+ if(d[i] == '.')
+ i++;
+ d = d.substr(0, i + 1);
+ }
+ return d.c_str();
+ }
+
+ struct Endianness
+ {
+ enum Arch
+ {
+ Big,
+ Little
+ };
+
+ static Arch which() {
+ int x = 1;
+ // casting any data pointer to char* is allowed
+ auto ptr = reinterpret_cast<char*>(&x);
+ if(*ptr)
+ return Little;
+ return Big;
+ }
+ };
+} // namespace
+
+namespace detail {
+ void my_memcpy(void* dest, const void* src, unsigned num) { memcpy(dest, src, num); }
+
+ String rawMemoryToString(const void* object, unsigned size) {
+ // Reverse order for little endian architectures
+ int i = 0, end = static_cast<int>(size), inc = 1;
+ if(Endianness::which() == Endianness::Little) {
+ i = end - 1;
+ end = inc = -1;
+ }
+
+ unsigned const char* bytes = static_cast<unsigned const char*>(object);
+ std::ostringstream oss;
+ oss << "0x" << std::setfill('0') << std::hex;
+ for(; i != end; i += inc)
+ oss << std::setw(2) << static_cast<unsigned>(bytes[i]);
+ return oss.str().c_str();
+ }
+
+ DOCTEST_THREAD_LOCAL std::ostringstream g_oss; // NOLINT(cert-err58-cpp)
+
+ std::ostream* getTlsOss() {
+ g_oss.clear(); // there shouldn't be anything worth clearing in the flags
+ g_oss.str(""); // the slow way of resetting a string stream
+ //g_oss.seekp(0); // optimal reset - as seen here: https://stackoverflow.com/a/624291/3162383
+ return &g_oss;
+ }
+
+ String getTlsOssResult() {
+ //g_oss << std::ends; // needed - as shown here: https://stackoverflow.com/a/624291/3162383
+ return g_oss.str().c_str();
+ }
+
+#ifndef DOCTEST_CONFIG_DISABLE
+
+namespace timer_large_integer
+{
+
+#if defined(DOCTEST_PLATFORM_WINDOWS)
+ typedef ULONGLONG type;
+#else // DOCTEST_PLATFORM_WINDOWS
+ using namespace std;
+ typedef uint64_t type;
+#endif // DOCTEST_PLATFORM_WINDOWS
+}
+
+typedef timer_large_integer::type ticks_t;
+
+#ifdef DOCTEST_CONFIG_GETCURRENTTICKS
+ ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
+#elif defined(DOCTEST_PLATFORM_WINDOWS)
+ ticks_t getCurrentTicks() {
+ static LARGE_INTEGER hz = {0}, hzo = {0};
+ if(!hz.QuadPart) {
+ QueryPerformanceFrequency(&hz);
+ QueryPerformanceCounter(&hzo);
+ }
+ LARGE_INTEGER t;
+ QueryPerformanceCounter(&t);
+ return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart;
+ }
+#else // DOCTEST_PLATFORM_WINDOWS
+ ticks_t getCurrentTicks() {
+ timeval t;
+ gettimeofday(&t, nullptr);
+ return static_cast<ticks_t>(t.tv_sec) * 1000000 + static_cast<ticks_t>(t.tv_usec);
+ }
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ struct Timer
+ {
+ void start() { m_ticks = getCurrentTicks(); }
+ unsigned int getElapsedMicroseconds() const {
+ return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
+ }
+ //unsigned int getElapsedMilliseconds() const {
+ // return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
+ //}
+ double getElapsedSeconds() const { return static_cast<double>(getCurrentTicks() - m_ticks) / 1000000.0; }
+
+ private:
+ ticks_t m_ticks = 0;
+ };
+
+#ifdef DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+ template <typename T>
+ using AtomicOrMultiLaneAtomic = std::atomic<T>;
+#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+ // Provides a multilane implementation of an atomic variable that supports add, sub, load,
+ // store. Instead of using a single atomic variable, this splits up into multiple ones,
+ // each sitting on a separate cache line. The goal is to provide a speedup when most
+ // operations are modifying. It achieves this with two properties:
+ //
+ // * Multiple atomics are used, so chance of congestion from the same atomic is reduced.
+ // * Each atomic sits on a separate cache line, so false sharing is reduced.
+ //
+ // The disadvantage is that there is a small overhead due to the use of TLS, and load/store
+ // is slower because all atomics have to be accessed.
+ template <typename T>
+ class MultiLaneAtomic
+ {
+ struct CacheLineAlignedAtomic
+ {
+ std::atomic<T> atomic{};
+ char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(std::atomic<T>)];
+ };
+ CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
+
+ static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE,
+ "guarantee one atomic takes exactly one cache line");
+
+ public:
+ T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; }
+
+ T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); }
+
+ T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
+ return myAtomic().fetch_add(arg, order);
+ }
+
+ T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
+ return myAtomic().fetch_sub(arg, order);
+ }
+
+ operator T() const DOCTEST_NOEXCEPT { return load(); }
+
+ T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT {
+ auto result = T();
+ for(auto const& c : m_atomics) {
+ result += c.atomic.load(order);
+ }
+ return result;
+ }
+
+ T operator=(T desired) DOCTEST_NOEXCEPT {
+ store(desired);
+ return desired;
+ }
+
+ void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
+ // first value becomes desired", all others become 0.
+ for(auto& c : m_atomics) {
+ c.atomic.store(desired, order);
+ desired = {};
+ }
+ }
+
+ private:
+ // Each thread has a different atomic that it operates on. If more than NumLanes threads
+ // use this, some will use the same atomic. So performance will degrate a bit, but still
+ // everything will work.
+ //
+ // The logic here is a bit tricky. The call should be as fast as possible, so that there
+ // is minimal to no overhead in determining the correct atomic for the current thread.
+ //
+ // 1. A global static counter laneCounter counts continuously up.
+ // 2. Each successive thread will use modulo operation of that counter so it gets an atomic
+ // assigned in a round-robin fashion.
+ // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
+ // little overhead.
+ std::atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
+ static std::atomic<size_t> laneCounter;
+ DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
+ laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
+
+ return m_atomics[tlsLaneIdx].atomic;
+ }
+ };
+
+ template <typename T>
+ using AtomicOrMultiLaneAtomic = MultiLaneAtomic<T>;
+#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+
+ // this holds both parameters from the command line and runtime data for tests
+ struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
+ {
+ AtomicOrMultiLaneAtomic<int> numAssertsCurrentTest_atomic;
+ AtomicOrMultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
+
+ std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
+
+ std::vector<IReporter*> reporters_currently_used;
+
+ assert_handler ah = nullptr;
+
+ Timer timer;
+
+ std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
+
+ // stuff for subcases
+ std::vector<SubcaseSignature> subcasesStack;
+ std::set<decltype(subcasesStack)> subcasesPassed;
+ int subcasesCurrentMaxLevel;
+ bool should_reenter;
+ std::atomic<bool> shouldLogCurrentException;
+
+ void resetRunData() {
+ numTestCases = 0;
+ numTestCasesPassingFilters = 0;
+ numTestSuitesPassingFilters = 0;
+ numTestCasesFailed = 0;
+ numAsserts = 0;
+ numAssertsFailed = 0;
+ numAssertsCurrentTest = 0;
+ numAssertsFailedCurrentTest = 0;
+ }
+
+ void finalizeTestCaseData() {
+ seconds = timer.getElapsedSeconds();
+
+ // update the non-atomic counters
+ numAsserts += numAssertsCurrentTest_atomic;
+ numAssertsFailed += numAssertsFailedCurrentTest_atomic;
+ numAssertsCurrentTest = numAssertsCurrentTest_atomic;
+ numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic;
+
+ if(numAssertsFailedCurrentTest)
+ failure_flags |= TestCaseFailureReason::AssertFailure;
+
+ if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 &&
+ Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout)
+ failure_flags |= TestCaseFailureReason::Timeout;
+
+ if(currentTest->m_should_fail) {
+ if(failure_flags) {
+ failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid;
+ } else {
+ failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt;
+ }
+ } else if(failure_flags && currentTest->m_may_fail) {
+ failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid;
+ } else if(currentTest->m_expected_failures > 0) {
+ if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) {
+ failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes;
+ } else {
+ failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes;
+ }
+ }
+
+ bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) ||
+ (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) ||
+ (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags);
+
+ // if any subcase has failed - the whole test case has failed
+ if(failure_flags && !ok_to_fail)
+ numTestCasesFailed++;
+ }
+ };
+
+ ContextState* g_cs = nullptr;
+
+ // used to avoid locks for the debug output
+ // TODO: figure out if this is indeed necessary/correct - seems like either there still
+ // could be a race or that there wouldn't be a race even if using the context directly
+ DOCTEST_THREAD_LOCAL bool g_no_colors;
+
+#endif // DOCTEST_CONFIG_DISABLE
+} // namespace detail
+
+void String::setOnHeap() { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
+void String::setLast(unsigned in) { buf[last] = char(in); }
+
+void String::copy(const String& other) {
+ using namespace std;
+ if(other.isOnStack()) {
+ memcpy(buf, other.buf, len);
+ } else {
+ setOnHeap();
+ data.size = other.data.size;
+ data.capacity = data.size + 1;
+ data.ptr = new char[data.capacity];
+ memcpy(data.ptr, other.data.ptr, data.size + 1);
+ }
+}
+
+String::String() {
+ buf[0] = '\0';
+ setLast();
+}
+
+String::~String() {
+ if(!isOnStack())
+ delete[] data.ptr;
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+}
+
+String::String(const char* in)
+ : String(in, strlen(in)) {}
+
+String::String(const char* in, unsigned in_size) {
+ using namespace std;
+ if(in_size <= last) {
+ memcpy(buf, in, in_size);
+ buf[in_size] = '\0';
+ setLast(last - in_size);
+ } else {
+ setOnHeap();
+ data.size = in_size;
+ data.capacity = data.size + 1;
+ data.ptr = new char[data.capacity];
+ memcpy(data.ptr, in, in_size);
+ data.ptr[in_size] = '\0';
+ }
+}
+
+String::String(const String& other) { copy(other); }
+
+String& String::operator=(const String& other) {
+ if(this != &other) {
+ if(!isOnStack())
+ delete[] data.ptr;
+
+ copy(other);
+ }
+
+ return *this;
+}
+
+String& String::operator+=(const String& other) {
+ const unsigned my_old_size = size();
+ const unsigned other_size = other.size();
+ const unsigned total_size = my_old_size + other_size;
+ using namespace std;
+ if(isOnStack()) {
+ if(total_size < len) {
+ // append to the current stack space
+ memcpy(buf + my_old_size, other.c_str(), other_size + 1);
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ setLast(last - total_size);
+ } else {
+ // alloc new chunk
+ char* temp = new char[total_size + 1];
+ // copy current data to new location before writing in the union
+ memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed
+ // update data in union
+ setOnHeap();
+ data.size = total_size;
+ data.capacity = data.size + 1;
+ data.ptr = temp;
+ // transfer the rest of the data
+ memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
+ }
+ } else {
+ if(data.capacity > total_size) {
+ // append to the current heap block
+ data.size = total_size;
+ memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
+ } else {
+ // resize
+ data.capacity *= 2;
+ if(data.capacity <= total_size)
+ data.capacity = total_size + 1;
+ // alloc new chunk
+ char* temp = new char[data.capacity];
+ // copy current data to new location before releasing it
+ memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed
+ // release old chunk
+ delete[] data.ptr;
+ // update the rest of the union members
+ data.size = total_size;
+ data.ptr = temp;
+ // transfer the rest of the data
+ memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
+ }
+ }
+
+ return *this;
+}
+
+// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+String String::operator+(const String& other) const { return String(*this) += other; }
+
+String::String(String&& other) {
+ using namespace std;
+ memcpy(buf, other.buf, len);
+ other.buf[0] = '\0';
+ other.setLast();
+}
+
+String& String::operator=(String&& other) {
+ using namespace std;
+ if(this != &other) {
+ if(!isOnStack())
+ delete[] data.ptr;
+ memcpy(buf, other.buf, len);
+ other.buf[0] = '\0';
+ other.setLast();
+ }
+ return *this;
+}
+
+char String::operator[](unsigned i) const {
+ return const_cast<String*>(this)->operator[](i); // NOLINT
+}
+
+char& String::operator[](unsigned i) {
+ if(isOnStack())
+ return reinterpret_cast<char*>(buf)[i];
+ return data.ptr[i];
+}
+
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized")
+unsigned String::size() const {
+ if(isOnStack())
+ return last - (unsigned(buf[last]) & 31); // using "last" would work only if "len" is 32
+ return data.size;
+}
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+unsigned String::capacity() const {
+ if(isOnStack())
+ return len;
+ return data.capacity;
+}
+
+int String::compare(const char* other, bool no_case) const {
+ if(no_case)
+ return doctest::stricmp(c_str(), other);
+ return std::strcmp(c_str(), other);
+}
+
+int String::compare(const String& other, bool no_case) const {
+ return compare(other.c_str(), no_case);
+}
+
+// clang-format off
+bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
+bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
+bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
+bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
+bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
+bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
+// clang-format on
+
+std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); }
+
+namespace {
+ void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;)
+} // namespace
+
+namespace Color {
+ std::ostream& operator<<(std::ostream& s, Color::Enum code) {
+ color_to_stream(s, code);
+ return s;
+ }
+} // namespace Color
+
+// clang-format off
+const char* assertString(assertType::Enum at) {
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4062) // enum 'x' in switch of enum 'y' is not handled
+ switch(at) { //!OCLINT missing default in switch statements
+ case assertType::DT_WARN : return "WARN";
+ case assertType::DT_CHECK : return "CHECK";
+ case assertType::DT_REQUIRE : return "REQUIRE";
+
+ case assertType::DT_WARN_FALSE : return "WARN_FALSE";
+ case assertType::DT_CHECK_FALSE : return "CHECK_FALSE";
+ case assertType::DT_REQUIRE_FALSE : return "REQUIRE_FALSE";
+
+ case assertType::DT_WARN_THROWS : return "WARN_THROWS";
+ case assertType::DT_CHECK_THROWS : return "CHECK_THROWS";
+ case assertType::DT_REQUIRE_THROWS : return "REQUIRE_THROWS";
+
+ case assertType::DT_WARN_THROWS_AS : return "WARN_THROWS_AS";
+ case assertType::DT_CHECK_THROWS_AS : return "CHECK_THROWS_AS";
+ case assertType::DT_REQUIRE_THROWS_AS : return "REQUIRE_THROWS_AS";
+
+ case assertType::DT_WARN_THROWS_WITH : return "WARN_THROWS_WITH";
+ case assertType::DT_CHECK_THROWS_WITH : return "CHECK_THROWS_WITH";
+ case assertType::DT_REQUIRE_THROWS_WITH : return "REQUIRE_THROWS_WITH";
+
+ case assertType::DT_WARN_THROWS_WITH_AS : return "WARN_THROWS_WITH_AS";
+ case assertType::DT_CHECK_THROWS_WITH_AS : return "CHECK_THROWS_WITH_AS";
+ case assertType::DT_REQUIRE_THROWS_WITH_AS : return "REQUIRE_THROWS_WITH_AS";
+
+ case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW";
+ case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW";
+ case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW";
+
+ case assertType::DT_WARN_EQ : return "WARN_EQ";
+ case assertType::DT_CHECK_EQ : return "CHECK_EQ";
+ case assertType::DT_REQUIRE_EQ : return "REQUIRE_EQ";
+ case assertType::DT_WARN_NE : return "WARN_NE";
+ case assertType::DT_CHECK_NE : return "CHECK_NE";
+ case assertType::DT_REQUIRE_NE : return "REQUIRE_NE";
+ case assertType::DT_WARN_GT : return "WARN_GT";
+ case assertType::DT_CHECK_GT : return "CHECK_GT";
+ case assertType::DT_REQUIRE_GT : return "REQUIRE_GT";
+ case assertType::DT_WARN_LT : return "WARN_LT";
+ case assertType::DT_CHECK_LT : return "CHECK_LT";
+ case assertType::DT_REQUIRE_LT : return "REQUIRE_LT";
+ case assertType::DT_WARN_GE : return "WARN_GE";
+ case assertType::DT_CHECK_GE : return "CHECK_GE";
+ case assertType::DT_REQUIRE_GE : return "REQUIRE_GE";
+ case assertType::DT_WARN_LE : return "WARN_LE";
+ case assertType::DT_CHECK_LE : return "CHECK_LE";
+ case assertType::DT_REQUIRE_LE : return "REQUIRE_LE";
+
+ case assertType::DT_WARN_UNARY : return "WARN_UNARY";
+ case assertType::DT_CHECK_UNARY : return "CHECK_UNARY";
+ case assertType::DT_REQUIRE_UNARY : return "REQUIRE_UNARY";
+ case assertType::DT_WARN_UNARY_FALSE : return "WARN_UNARY_FALSE";
+ case assertType::DT_CHECK_UNARY_FALSE : return "CHECK_UNARY_FALSE";
+ case assertType::DT_REQUIRE_UNARY_FALSE : return "REQUIRE_UNARY_FALSE";
+ }
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ return "";
+}
+// clang-format on
+
+const char* failureString(assertType::Enum at) {
+ if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional
+ return "WARNING";
+ if(at & assertType::is_check) //!OCLINT bitwise operator in conditional
+ return "ERROR";
+ if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
+ return "FATAL ERROR";
+ return "";
+}
+
+DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
+DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
+// depending on the current options this will remove the path of filenames
+const char* skipPathFromFilename(const char* file) {
+#ifndef DOCTEST_CONFIG_DISABLE
+ if(getContextOptions()->no_path_in_filenames) {
+ auto back = std::strrchr(file, '\\');
+ auto forward = std::strrchr(file, '/');
+ if(back || forward) {
+ if(back > forward)
+ forward = back;
+ return forward + 1;
+ }
+ }
+#endif // DOCTEST_CONFIG_DISABLE
+ return file;
+}
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
+ if(m_line != other.m_line)
+ return m_line < other.m_line;
+ if(std::strcmp(m_file, other.m_file) != 0)
+ return std::strcmp(m_file, other.m_file) < 0;
+ return m_name.compare(other.m_name) < 0;
+}
+
+IContextScope::IContextScope() = default;
+IContextScope::~IContextScope() = default;
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(char* in) { return toString(static_cast<const char*>(in)); }
+// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(bool in) { return in ? "true" : "false"; }
+String toString(float in) { return fpToString(in, 5) + "f"; }
+String toString(double in) { return fpToString(in, 10); }
+String toString(double long in) { return fpToString(in, 15); }
+
+#define DOCTEST_TO_STRING_OVERLOAD(type, fmt) \
+ String toString(type in) { \
+ char buf[64]; \
+ std::sprintf(buf, fmt, in); \
+ return buf; \
+ }
+
+DOCTEST_TO_STRING_OVERLOAD(char, "%d")
+DOCTEST_TO_STRING_OVERLOAD(char signed, "%d")
+DOCTEST_TO_STRING_OVERLOAD(char unsigned, "%u")
+DOCTEST_TO_STRING_OVERLOAD(int short, "%d")
+DOCTEST_TO_STRING_OVERLOAD(int short unsigned, "%u")
+DOCTEST_TO_STRING_OVERLOAD(int, "%d")
+DOCTEST_TO_STRING_OVERLOAD(unsigned, "%u")
+DOCTEST_TO_STRING_OVERLOAD(int long, "%ld")
+DOCTEST_TO_STRING_OVERLOAD(int long unsigned, "%lu")
+DOCTEST_TO_STRING_OVERLOAD(int long long, "%lld")
+DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu")
+
+String toString(std::nullptr_t) { return "NULL"; }
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+String toString(const std::string& in) { return in.c_str(); }
+#endif // VS 2019
+
+Approx::Approx(double value)
+ : m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
+ , m_scale(1.0)
+ , m_value(value) {}
+
+Approx Approx::operator()(double value) const {
+ Approx approx(value);
+ approx.epsilon(m_epsilon);
+ approx.scale(m_scale);
+ return approx;
+}
+
+Approx& Approx::epsilon(double newEpsilon) {
+ m_epsilon = newEpsilon;
+ return *this;
+}
+Approx& Approx::scale(double newScale) {
+ m_scale = newScale;
+ return *this;
+}
+
+bool operator==(double lhs, const Approx& rhs) {
+ // Thanks to Richard Harris for his help refining this formula
+ return std::fabs(lhs - rhs.m_value) <
+ rhs.m_epsilon * (rhs.m_scale + std::max<double>(std::fabs(lhs), std::fabs(rhs.m_value)));
+}
+bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); }
+bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
+bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); }
+bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; }
+bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; }
+bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; }
+bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; }
+bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; }
+bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; }
+bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; }
+bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; }
+
+String toString(const Approx& in) {
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ return String("Approx( ") + doctest::toString(in.m_value) + " )";
+}
+const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); }
+
+} // namespace doctest
+
+#ifdef DOCTEST_CONFIG_DISABLE
+namespace doctest {
+Context::Context(int, const char* const*) {}
+Context::~Context() = default;
+void Context::applyCommandLine(int, const char* const*) {}
+void Context::addFilter(const char*, const char*) {}
+void Context::clearFilters() {}
+void Context::setOption(const char*, int) {}
+void Context::setOption(const char*, const char*) {}
+bool Context::shouldExit() { return false; }
+void Context::setAsDefaultForAssertsOutOfTestCases() {}
+void Context::setAssertHandler(detail::assert_handler) {}
+int Context::run() { return 0; }
+
+IReporter::~IReporter() = default;
+
+int IReporter::get_num_active_contexts() { return 0; }
+const IContextScope* const* IReporter::get_active_contexts() { return nullptr; }
+int IReporter::get_num_stringified_contexts() { return 0; }
+const String* IReporter::get_stringified_contexts() { return nullptr; }
+
+int registerReporter(const char*, int, IReporter*) { return 0; }
+
+} // namespace doctest
+#else // DOCTEST_CONFIG_DISABLE
+
+#if !defined(DOCTEST_CONFIG_COLORS_NONE)
+#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
+#ifdef DOCTEST_PLATFORM_WINDOWS
+#define DOCTEST_CONFIG_COLORS_WINDOWS
+#else // linux
+#define DOCTEST_CONFIG_COLORS_ANSI
+#endif // platform
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
+#endif // DOCTEST_CONFIG_COLORS_NONE
+
+namespace doctest_detail_test_suite_ns {
+// holds the current test suite
+doctest::detail::TestSuite& getCurrentTestSuite() {
+ static doctest::detail::TestSuite data{};
+ return data;
+}
+} // namespace doctest_detail_test_suite_ns
+
+namespace doctest {
+namespace {
+ // the int (priority) is part of the key for automatic sorting - sadly one can register a
+ // reporter with a duplicate name and a different priority but hopefully that won't happen often :|
+ typedef std::map<std::pair<int, String>, reporterCreatorFunc> reporterMap;
+
+ reporterMap& getReporters() {
+ static reporterMap data;
+ return data;
+ }
+ reporterMap& getListeners() {
+ static reporterMap data;
+ return data;
+ }
+} // namespace
+namespace detail {
+#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \
+ for(auto& curr_rep : g_cs->reporters_currently_used) \
+ curr_rep->function(__VA_ARGS__)
+
+ bool checkIfShouldThrow(assertType::Enum at) {
+ if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
+ return true;
+
+ if((at & assertType::is_check) //!OCLINT bitwise operator in conditional
+ && getContextOptions()->abort_after > 0 &&
+ (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >=
+ getContextOptions()->abort_after)
+ return true;
+
+ return false;
+ }
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ DOCTEST_NORETURN void throwException() {
+ g_cs->shouldLogCurrentException = false;
+ throw TestFailureException();
+ } // NOLINT(cert-err60-cpp)
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+ void throwException() {}
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+} // namespace detail
+
+namespace {
+ using namespace detail;
+ // matching of a string against a wildcard mask (case sensitivity configurable) taken from
+ // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
+ int wildcmp(const char* str, const char* wild, bool caseSensitive) {
+ const char* cp = str;
+ const char* mp = wild;
+
+ while((*str) && (*wild != '*')) {
+ if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
+ (*wild != '?')) {
+ return 0;
+ }
+ wild++;
+ str++;
+ }
+
+ while(*str) {
+ if(*wild == '*') {
+ if(!*++wild) {
+ return 1;
+ }
+ mp = wild;
+ cp = str + 1;
+ } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
+ (*wild == '?')) {
+ wild++;
+ str++;
+ } else {
+ wild = mp; //!OCLINT parameter reassignment
+ str = cp++; //!OCLINT parameter reassignment
+ }
+ }
+
+ while(*wild == '*') {
+ wild++;
+ }
+ return !*wild;
+ }
+
+ //// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
+ //unsigned hashStr(unsigned const char* str) {
+ // unsigned long hash = 5381;
+ // char c;
+ // while((c = *str++))
+ // hash = ((hash << 5) + hash) + c; // hash * 33 + c
+ // return hash;
+ //}
+
+ // checks if the name matches any of the filters (and can be configured what to do when empty)
+ bool matchesAny(const char* name, const std::vector<String>& filters, bool matchEmpty,
+ bool caseSensitive) {
+ if(filters.empty() && matchEmpty)
+ return true;
+ for(auto& curr : filters)
+ if(wildcmp(name, curr.c_str(), caseSensitive))
+ return true;
+ return false;
+ }
+} // namespace
+namespace detail {
+
+ Subcase::Subcase(const String& name, const char* file, int line)
+ : m_signature({name, file, line}) {
+ auto* s = g_cs;
+
+ // check subcase filters
+ if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) {
+ if(!matchesAny(m_signature.m_name.c_str(), s->filters[6], true, s->case_sensitive))
+ return;
+ if(matchesAny(m_signature.m_name.c_str(), s->filters[7], false, s->case_sensitive))
+ return;
+ }
+
+ // if a Subcase on the same level has already been entered
+ if(s->subcasesStack.size() < size_t(s->subcasesCurrentMaxLevel)) {
+ s->should_reenter = true;
+ return;
+ }
+
+ // push the current signature to the stack so we can check if the
+ // current stack + the current new subcase have been traversed
+ s->subcasesStack.push_back(m_signature);
+ if(s->subcasesPassed.count(s->subcasesStack) != 0) {
+ // pop - revert to previous stack since we've already passed this
+ s->subcasesStack.pop_back();
+ return;
+ }
+
+ s->subcasesCurrentMaxLevel = s->subcasesStack.size();
+ m_entered = true;
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+
+ Subcase::~Subcase() {
+ if(m_entered) {
+ // only mark the subcase stack as passed if no subcases have been skipped
+ if(g_cs->should_reenter == false)
+ g_cs->subcasesPassed.insert(g_cs->subcasesStack);
+ g_cs->subcasesStack.pop_back();
+
+#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
+ if(std::uncaught_exceptions() > 0
+#else
+ if(std::uncaught_exception()
+#endif
+ && g_cs->shouldLogCurrentException) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(
+ test_case_exception, {"exception thrown in subcase - will translate later "
+ "when the whole test case has been exited (cannot "
+ "translate while there is an active exception)",
+ false});
+ g_cs->shouldLogCurrentException = false;
+ }
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
+ }
+ }
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ Subcase::operator bool() const { return m_entered; }
+
+ Result::Result(bool passed, const String& decomposition)
+ : m_passed(passed)
+ , m_decomp(decomposition) {}
+
+ ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at)
+ : m_at(at) {}
+
+ TestSuite& TestSuite::operator*(const char* in) {
+ m_test_suite = in;
+ // clear state
+ m_description = nullptr;
+ m_skip = false;
+ m_no_breaks = false;
+ m_no_output = false;
+ m_may_fail = false;
+ m_should_fail = false;
+ m_expected_failures = 0;
+ m_timeout = 0;
+ return *this;
+ }
+
+ TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
+ const char* type, int template_id) {
+ m_file = file;
+ m_line = line;
+ m_name = nullptr; // will be later overridden in operator*
+ m_test_suite = test_suite.m_test_suite;
+ m_description = test_suite.m_description;
+ m_skip = test_suite.m_skip;
+ m_no_breaks = test_suite.m_no_breaks;
+ m_no_output = test_suite.m_no_output;
+ m_may_fail = test_suite.m_may_fail;
+ m_should_fail = test_suite.m_should_fail;
+ m_expected_failures = test_suite.m_expected_failures;
+ m_timeout = test_suite.m_timeout;
+
+ m_test = test;
+ m_type = type;
+ m_template_id = template_id;
+ }
+
+ TestCase::TestCase(const TestCase& other)
+ : TestCaseData() {
+ *this = other;
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
+ DOCTEST_MSVC_SUPPRESS_WARNING(26437) // Do not slice
+ TestCase& TestCase::operator=(const TestCase& other) {
+ static_cast<TestCaseData&>(*this) = static_cast<const TestCaseData&>(other);
+
+ m_test = other.m_test;
+ m_type = other.m_type;
+ m_template_id = other.m_template_id;
+ m_full_name = other.m_full_name;
+
+ if(m_template_id != -1)
+ m_name = m_full_name.c_str();
+ return *this;
+ }
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ TestCase& TestCase::operator*(const char* in) {
+ m_name = in;
+ // make a new name with an appended type for templated test case
+ if(m_template_id != -1) {
+ m_full_name = String(m_name) + m_type;
+ // redirect the name to point to the newly constructed full name
+ m_name = m_full_name.c_str();
+ }
+ return *this;
+ }
+
+ bool TestCase::operator<(const TestCase& other) const {
+ // this will be used only to differentiate between test cases - not relevant for sorting
+ if(m_line != other.m_line)
+ return m_line < other.m_line;
+ const int name_cmp = strcmp(m_name, other.m_name);
+ if(name_cmp != 0)
+ return name_cmp < 0;
+ const int file_cmp = m_file.compare(other.m_file);
+ if(file_cmp != 0)
+ return file_cmp < 0;
+ return m_template_id < other.m_template_id;
+ }
+
+ // all the registered tests
+ std::set<TestCase>& getRegisteredTests() {
+ static std::set<TestCase> data;
+ return data;
+ }
+} // namespace detail
+namespace {
+ using namespace detail;
+ // for sorting tests by file/line
+ bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) {
+ // this is needed because MSVC gives different case for drive letters
+ // for __FILE__ when evaluated in a header and a source file
+ const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC));
+ if(res != 0)
+ return res < 0;
+ if(lhs->m_line != rhs->m_line)
+ return lhs->m_line < rhs->m_line;
+ return lhs->m_template_id < rhs->m_template_id;
+ }
+
+ // for sorting tests by suite/file/line
+ bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) {
+ const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite);
+ if(res != 0)
+ return res < 0;
+ return fileOrderComparator(lhs, rhs);
+ }
+
+ // for sorting tests by name/suite/file/line
+ bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) {
+ const int res = std::strcmp(lhs->m_name, rhs->m_name);
+ if(res != 0)
+ return res < 0;
+ return suiteOrderComparator(lhs, rhs);
+ }
+
+#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
+ HANDLE g_stdoutHandle;
+ WORD g_origFgAttrs;
+ WORD g_origBgAttrs;
+ bool g_attrsInitted = false;
+
+ int colors_init() {
+ if(!g_attrsInitted) {
+ g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ g_attrsInitted = true;
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ GetConsoleScreenBufferInfo(g_stdoutHandle, &csbiInfo);
+ g_origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
+ BACKGROUND_BLUE | BACKGROUND_INTENSITY);
+ g_origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ }
+ return 0;
+ }
+
+ int dumy_init_console_colors = colors_init();
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ void color_to_stream(std::ostream& s, Color::Enum code) {
+ static_cast<void>(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
+ static_cast<void>(code); // for DOCTEST_CONFIG_COLORS_NONE
+#ifdef DOCTEST_CONFIG_COLORS_ANSI
+ if(g_no_colors ||
+ (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false))
+ return;
+
+ auto col = "";
+ // clang-format off
+ switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement
+ case Color::Red: col = "[0;31m"; break;
+ case Color::Green: col = "[0;32m"; break;
+ case Color::Blue: col = "[0;34m"; break;
+ case Color::Cyan: col = "[0;36m"; break;
+ case Color::Yellow: col = "[0;33m"; break;
+ case Color::Grey: col = "[1;30m"; break;
+ case Color::LightGrey: col = "[0;37m"; break;
+ case Color::BrightRed: col = "[1;31m"; break;
+ case Color::BrightGreen: col = "[1;32m"; break;
+ case Color::BrightWhite: col = "[1;37m"; break;
+ case Color::Bright: // invalid
+ case Color::None:
+ case Color::White:
+ default: col = "[0m";
+ }
+ // clang-format on
+ s << "\033" << col;
+#endif // DOCTEST_CONFIG_COLORS_ANSI
+
+#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
+ if(g_no_colors ||
+ (isatty(fileno(stdout)) == false && getContextOptions()->force_colors == false))
+ return;
+
+#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(g_stdoutHandle, x | g_origBgAttrs)
+
+ // clang-format off
+ switch (code) {
+ case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
+ case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break;
+ case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break;
+ case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break;
+ case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break;
+ case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break;
+ case Color::Grey: DOCTEST_SET_ATTR(0); break;
+ case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break;
+ case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break;
+ case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break;
+ case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
+ case Color::None:
+ case Color::Bright: // invalid
+ default: DOCTEST_SET_ATTR(g_origFgAttrs);
+ }
+ // clang-format on
+#endif // DOCTEST_CONFIG_COLORS_WINDOWS
+ }
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+
+ std::vector<const IExceptionTranslator*>& getExceptionTranslators() {
+ static std::vector<const IExceptionTranslator*> data;
+ return data;
+ }
+
+ String translateActiveException() {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ String res;
+ auto& translators = getExceptionTranslators();
+ for(auto& curr : translators)
+ if(curr->translate(res))
+ return res;
+ // clang-format off
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value")
+ try {
+ throw;
+ } catch(std::exception& ex) {
+ return ex.what();
+ } catch(std::string& msg) {
+ return msg.c_str();
+ } catch(const char* msg) {
+ return msg;
+ } catch(...) {
+ return "unknown exception";
+ }
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+// clang-format on
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+ return "";
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ }
+} // namespace
+
+namespace detail {
+ // used by the macros for registering tests
+ int regTest(const TestCase& tc) {
+ getRegisteredTests().insert(tc);
+ return 0;
+ }
+
+ // sets the current test suite
+ int setTestSuite(const TestSuite& ts) {
+ doctest_detail_test_suite_ns::getCurrentTestSuite() = ts;
+ return 0;
+ }
+
+#ifdef DOCTEST_IS_DEBUGGER_ACTIVE
+ bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); }
+#else // DOCTEST_IS_DEBUGGER_ACTIVE
+#ifdef DOCTEST_PLATFORM_LINUX
+ class ErrnoGuard {
+ public:
+ ErrnoGuard() : m_oldErrno(errno) {}
+ ~ErrnoGuard() { errno = m_oldErrno; }
+ private:
+ int m_oldErrno;
+ };
+ // See the comments in Catch2 for the reasoning behind this implementation:
+ // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102
+ bool isDebuggerActive() {
+ ErrnoGuard guard;
+ std::ifstream in("/proc/self/status");
+ for(std::string line; std::getline(in, line);) {
+ static const int PREFIX_LEN = 11;
+ if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) {
+ return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
+ }
+ }
+ return false;
+ }
+#elif defined(DOCTEST_PLATFORM_MAC)
+ // The following function is taken directly from the following technical note:
+ // https://developer.apple.com/library/archive/qa/qa1361/_index.html
+ // Returns true if the current process is being debugged (either
+ // running under the debugger or has a debugger attached post facto).
+ bool isDebuggerActive() {
+ int mib[4];
+ kinfo_proc info;
+ size_t size;
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+ info.kp_proc.p_flag = 0;
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+ // Call sysctl.
+ size = sizeof(info);
+ if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) {
+ std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n";
+ return false;
+ }
+ // We're being debugged if the P_TRACED flag is set.
+ return ((info.kp_proc.p_flag & P_TRACED) != 0);
+ }
+#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__)
+ bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
+#else
+ bool isDebuggerActive() { return false; }
+#endif // Platform
+#endif // DOCTEST_IS_DEBUGGER_ACTIVE
+
+ void registerExceptionTranslatorImpl(const IExceptionTranslator* et) {
+ if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) ==
+ getExceptionTranslators().end())
+ getExceptionTranslators().push_back(et);
+ }
+
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ void toStream(std::ostream* s, char* in) { *s << in; }
+ void toStream(std::ostream* s, const char* in) { *s << in; }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+ void toStream(std::ostream* s, bool in) { *s << std::boolalpha << in << std::noboolalpha; }
+ void toStream(std::ostream* s, float in) { *s << in; }
+ void toStream(std::ostream* s, double in) { *s << in; }
+ void toStream(std::ostream* s, double long in) { *s << in; }
+
+ void toStream(std::ostream* s, char in) { *s << in; }
+ void toStream(std::ostream* s, char signed in) { *s << in; }
+ void toStream(std::ostream* s, char unsigned in) { *s << in; }
+ void toStream(std::ostream* s, int short in) { *s << in; }
+ void toStream(std::ostream* s, int short unsigned in) { *s << in; }
+ void toStream(std::ostream* s, int in) { *s << in; }
+ void toStream(std::ostream* s, int unsigned in) { *s << in; }
+ void toStream(std::ostream* s, int long in) { *s << in; }
+ void toStream(std::ostream* s, int long unsigned in) { *s << in; }
+ void toStream(std::ostream* s, int long long in) { *s << in; }
+ void toStream(std::ostream* s, int long long unsigned in) { *s << in; }
+
+ DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO()
+
+ ContextScopeBase::ContextScopeBase() {
+ g_infoContexts.push_back(this);
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+
+ // destroy cannot be inlined into the destructor because that would mean calling stringify after
+ // ContextScope has been destroyed (base class destructors run after derived class destructors).
+ // Instead, ContextScope calls this method directly from its destructor.
+ void ContextScopeBase::destroy() {
+#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
+ if(std::uncaught_exceptions() > 0) {
+#else
+ if(std::uncaught_exception()) {
+#endif
+ std::ostringstream s;
+ this->stringify(&s);
+ g_cs->stringifiedContexts.push_back(s.str().c_str());
+ }
+ g_infoContexts.pop_back();
+ }
+
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+} // namespace detail
+namespace {
+ using namespace detail;
+
+#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
+ struct FatalConditionHandler
+ {
+ static void reset() {}
+ static void allocateAltStackMem() {}
+ static void freeAltStackMem() {}
+ };
+#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
+
+ void reportFatal(const std::string&);
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+
+ struct SignalDefs
+ {
+ DWORD id;
+ const char* name;
+ };
+ // There is no 1-1 mapping between signals and windows exceptions.
+ // Windows can easily distinguish between SO and SigSegV,
+ // but SigInt, SigTerm, etc are handled differently.
+ SignalDefs signalDefs[] = {
+ {static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),
+ "SIGILL - Illegal instruction signal"},
+ {static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"},
+ {static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION),
+ "SIGSEGV - Segmentation violation signal"},
+ {static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"},
+ };
+
+ struct FatalConditionHandler
+ {
+ static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) {
+ // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the
+ // console just once no matter how many threads have crashed.
+ static std::mutex mutex;
+ static bool execute = true;
+ {
+ std::lock_guard<std::mutex> lock(mutex);
+ if(execute) {
+ bool reported = false;
+ for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
+ reportFatal(signalDefs[i].name);
+ reported = true;
+ break;
+ }
+ }
+ if(reported == false)
+ reportFatal("Unhandled SEH exception caught");
+ if(isDebuggerActive() && !g_cs->no_breaks)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ }
+ execute = false;
+ }
+ std::exit(EXIT_FAILURE);
+ }
+
+ static void allocateAltStackMem() {}
+ static void freeAltStackMem() {}
+
+ FatalConditionHandler() {
+ isSet = true;
+ // 32k seems enough for doctest to handle stack overflow,
+ // but the value was found experimentally, so there is no strong guarantee
+ guaranteeSize = 32 * 1024;
+ // Register an unhandled exception filter
+ previousTop = SetUnhandledExceptionFilter(handleException);
+ // Pass in guarantee size to be filled
+ SetThreadStackGuarantee(&guaranteeSize);
+
+ // On Windows uncaught exceptions from another thread, exceptions from
+ // destructors, or calls to std::terminate are not a SEH exception
+
+ // The terminal handler gets called when:
+ // - std::terminate is called FROM THE TEST RUNNER THREAD
+ // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD
+ original_terminate_handler = std::get_terminate();
+ std::set_terminate([]() DOCTEST_NOEXCEPT {
+ reportFatal("Terminate handler called");
+ if(isDebuggerActive() && !g_cs->no_breaks)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well
+ });
+
+ // SIGABRT is raised when:
+ // - std::terminate is called FROM A DIFFERENT THREAD
+ // - an exception is thrown from a destructor FROM A DIFFERENT THREAD
+ // - an uncaught exception is thrown FROM A DIFFERENT THREAD
+ prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT {
+ if(signal == SIGABRT) {
+ reportFatal("SIGABRT - Abort (abnormal termination) signal");
+ if(isDebuggerActive() && !g_cs->no_breaks)
+ DOCTEST_BREAK_INTO_DEBUGGER();
+ std::exit(EXIT_FAILURE);
+ }
+ });
+
+ // The following settings are taken from google test, and more
+ // specifically from UnitTest::Run() inside of gtest.cc
+
+ // the user does not want to see pop-up dialogs about crashes
+ prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+ SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+ // This forces the abort message to go to stderr in all circumstances.
+ prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR);
+ // In the debug version, Visual Studio pops up a separate dialog
+ // offering a choice to debug the aborted program - we want to disable that.
+ prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
+ // In debug mode, the Windows CRT can crash with an assertion over invalid
+ // input (e.g. passing an invalid file descriptor). The default handling
+ // for these assertions is to pop up a dialog and wait for user input.
+ // Instead ask the CRT to dump such assertions to stderr non-interactively.
+ prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+ }
+
+ static void reset() {
+ if(isSet) {
+ // Unregister handler and restore the old guarantee
+ SetUnhandledExceptionFilter(previousTop);
+ SetThreadStackGuarantee(&guaranteeSize);
+ std::set_terminate(original_terminate_handler);
+ std::signal(SIGABRT, prev_sigabrt_handler);
+ SetErrorMode(prev_error_mode_1);
+ _set_error_mode(prev_error_mode_2);
+ _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
+ static_cast<void>(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode));
+ static_cast<void>(_CrtSetReportFile(_CRT_ASSERT, prev_report_file));
+ isSet = false;
+ }
+ }
+
+ ~FatalConditionHandler() { reset(); }
+
+ private:
+ static UINT prev_error_mode_1;
+ static int prev_error_mode_2;
+ static unsigned int prev_abort_behavior;
+ static int prev_report_mode;
+ static _HFILE prev_report_file;
+ static void (*prev_sigabrt_handler)(int);
+ static std::terminate_handler original_terminate_handler;
+ static bool isSet;
+ static ULONG guaranteeSize;
+ static LPTOP_LEVEL_EXCEPTION_FILTER previousTop;
+ };
+
+ UINT FatalConditionHandler::prev_error_mode_1;
+ int FatalConditionHandler::prev_error_mode_2;
+ unsigned int FatalConditionHandler::prev_abort_behavior;
+ int FatalConditionHandler::prev_report_mode;
+ _HFILE FatalConditionHandler::prev_report_file;
+ void (*FatalConditionHandler::prev_sigabrt_handler)(int);
+ std::terminate_handler FatalConditionHandler::original_terminate_handler;
+ bool FatalConditionHandler::isSet = false;
+ ULONG FatalConditionHandler::guaranteeSize = 0;
+ LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr;
+
+#else // DOCTEST_PLATFORM_WINDOWS
+
+ struct SignalDefs
+ {
+ int id;
+ const char* name;
+ };
+ SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"},
+ {SIGILL, "SIGILL - Illegal instruction signal"},
+ {SIGFPE, "SIGFPE - Floating point error signal"},
+ {SIGSEGV, "SIGSEGV - Segmentation violation signal"},
+ {SIGTERM, "SIGTERM - Termination request signal"},
+ {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}};
+
+ struct FatalConditionHandler
+ {
+ static bool isSet;
+ static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)];
+ static stack_t oldSigStack;
+ static size_t altStackSize;
+ static char* altStackMem;
+
+ static void handleSignal(int sig) {
+ const char* name = "<unknown signal>";
+ for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ SignalDefs& def = signalDefs[i];
+ if(sig == def.id) {
+ name = def.name;
+ break;
+ }
+ }
+ reset();
+ reportFatal(name);
+ raise(sig);
+ }
+
+ static void allocateAltStackMem() {
+ altStackMem = new char[altStackSize];
+ }
+
+ static void freeAltStackMem() {
+ delete[] altStackMem;
+ }
+
+ FatalConditionHandler() {
+ isSet = true;
+ stack_t sigStack;
+ sigStack.ss_sp = altStackMem;
+ sigStack.ss_size = altStackSize;
+ sigStack.ss_flags = 0;
+ sigaltstack(&sigStack, &oldSigStack);
+ struct sigaction sa = {};
+ sa.sa_handler = handleSignal; // NOLINT
+ sa.sa_flags = SA_ONSTACK;
+ for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
+ }
+ }
+
+ ~FatalConditionHandler() { reset(); }
+ static void reset() {
+ if(isSet) {
+ // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+ for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
+ sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
+ }
+ // Return the old stack
+ sigaltstack(&oldSigStack, nullptr);
+ isSet = false;
+ }
+ }
+ };
+
+ bool FatalConditionHandler::isSet = false;
+ struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {};
+ stack_t FatalConditionHandler::oldSigStack = {};
+ size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ;
+ char* FatalConditionHandler::altStackMem = nullptr;
+
+#endif // DOCTEST_PLATFORM_WINDOWS
+#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
+
+} // namespace
+
+namespace {
+ using namespace detail;
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text)
+#else
+ // TODO: integration with XCode and other IDEs
+#define DOCTEST_OUTPUT_DEBUG_STRING(text) // NOLINT(clang-diagnostic-unused-macros)
+#endif // Platform
+
+ void addAssert(assertType::Enum at) {
+ if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
+ g_cs->numAssertsCurrentTest_atomic++;
+ }
+
+ void addFailedAssert(assertType::Enum at) {
+ if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
+ g_cs->numAssertsFailedCurrentTest_atomic++;
+ }
+
+#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH)
+ void reportFatal(const std::string& message) {
+ g_cs->failure_flags |= TestCaseFailureReason::Crash;
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
+
+ while(g_cs->subcasesStack.size()) {
+ g_cs->subcasesStack.pop_back();
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
+ }
+
+ g_cs->finalizeTestCaseData();
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
+ }
+#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
+} // namespace
+namespace detail {
+
+ ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const char* exception_string) {
+ m_test_case = g_cs->currentTest;
+ m_at = at;
+ m_file = file;
+ m_line = line;
+ m_expr = expr;
+ m_failed = true;
+ m_threw = false;
+ m_threw_as = false;
+ m_exception_type = exception_type;
+ m_exception_string = exception_string;
+#if DOCTEST_MSVC
+ if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
+ ++m_expr;
+#endif // MSVC
+ }
+
+ void ResultBuilder::setResult(const Result& res) {
+ m_decomp = res.m_decomp;
+ m_failed = !res.m_passed;
+ }
+
+ void ResultBuilder::translateException() {
+ m_threw = true;
+ m_exception = translateActiveException();
+ }
+
+ bool ResultBuilder::log() {
+ if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_threw;
+ } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
+ m_failed = !m_threw_as || (m_exception != m_exception_string);
+ } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
+ m_failed = !m_threw_as;
+ } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
+ m_failed = m_exception != m_exception_string;
+ } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
+ m_failed = m_threw;
+ }
+
+ if(m_exception.size())
+ m_exception = String("\"") + m_exception + "\"";
+
+ if(is_running_in_test) {
+ addAssert(m_at);
+ DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this);
+
+ if(m_failed)
+ addFailedAssert(m_at);
+ } else if(m_failed) {
+ failed_out_of_a_testing_context(*this);
+ }
+
+ return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks &&
+ (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
+ }
+
+ void ResultBuilder::react() const {
+ if(m_failed && checkIfShouldThrow(m_at))
+ throwException();
+ }
+
+ void failed_out_of_a_testing_context(const AssertData& ad) {
+ if(g_cs->ah)
+ g_cs->ah(ad);
+ else
+ std::abort();
+ }
+
+ void decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
+ Result result) {
+ bool failed = !result.m_passed;
+
+ // ###################################################################################
+ // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
+ // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
+ // ###################################################################################
+ DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp);
+ DOCTEST_ASSERT_IN_TESTS(result.m_decomp);
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ }
+
+ MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) {
+ m_stream = getTlsOss();
+ m_file = file;
+ m_line = line;
+ m_severity = severity;
+ }
+
+ IExceptionTranslator::IExceptionTranslator() = default;
+ IExceptionTranslator::~IExceptionTranslator() = default;
+
+ bool MessageBuilder::log() {
+ m_string = getTlsOssResult();
+ DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
+
+ const bool isWarn = m_severity & assertType::is_warn;
+
+ // warn is just a message in this context so we don't treat it as an assert
+ if(!isWarn) {
+ addAssert(m_severity);
+ addFailedAssert(m_severity);
+ }
+
+ return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn &&
+ (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
+ }
+
+ void MessageBuilder::react() {
+ if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional
+ throwException();
+ }
+
+ MessageBuilder::~MessageBuilder() = default;
+} // namespace detail
+namespace {
+ using namespace detail;
+
+ template <typename Ex>
+ DOCTEST_NORETURN void throw_exception(Ex const& e) {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ throw e;
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+ std::cerr << "doctest will terminate because it needed to throw an exception.\n"
+ << "The message was: " << e.what() << '\n';
+ std::terminate();
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ }
+
+#ifndef DOCTEST_INTERNAL_ERROR
+#define DOCTEST_INTERNAL_ERROR(msg) \
+ throw_exception(std::logic_error( \
+ __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
+#endif // DOCTEST_INTERNAL_ERROR
+
+ // clang-format off
+
+// =================================================================================================
+// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
+// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
+// =================================================================================================
+
+ class XmlEncode {
+ public:
+ enum ForWhat { ForTextNodes, ForAttributes };
+
+ XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
+
+ void encodeTo( std::ostream& os ) const;
+
+ friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
+
+ private:
+ std::string m_str;
+ ForWhat m_forWhat;
+ };
+
+ class XmlWriter {
+ public:
+
+ class ScopedElement {
+ public:
+ ScopedElement( XmlWriter* writer );
+
+ ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT;
+ ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT;
+
+ ~ScopedElement();
+
+ ScopedElement& writeText( std::string const& text, bool indent = true );
+
+ template<typename T>
+ ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
+ m_writer->writeAttribute( name, attribute );
+ return *this;
+ }
+
+ private:
+ mutable XmlWriter* m_writer = nullptr;
+ };
+
+ XmlWriter( std::ostream& os = std::cout );
+ ~XmlWriter();
+
+ XmlWriter( XmlWriter const& ) = delete;
+ XmlWriter& operator=( XmlWriter const& ) = delete;
+
+ XmlWriter& startElement( std::string const& name );
+
+ ScopedElement scopedElement( std::string const& name );
+
+ XmlWriter& endElement();
+
+ XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
+
+ XmlWriter& writeAttribute( std::string const& name, const char* attribute );
+
+ XmlWriter& writeAttribute( std::string const& name, bool attribute );
+
+ template<typename T>
+ XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
+ std::stringstream rss;
+ rss << attribute;
+ return writeAttribute( name, rss.str() );
+ }
+
+ XmlWriter& writeText( std::string const& text, bool indent = true );
+
+ //XmlWriter& writeComment( std::string const& text );
+
+ //void writeStylesheetRef( std::string const& url );
+
+ //XmlWriter& writeBlankLine();
+
+ void ensureTagClosed();
+
+ private:
+
+ void writeDeclaration();
+
+ void newlineIfNecessary();
+
+ bool m_tagIsOpen = false;
+ bool m_needsNewline = false;
+ std::vector<std::string> m_tags;
+ std::string m_indent;
+ std::ostream& m_os;
+ };
+
+// =================================================================================================
+// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
+// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
+// =================================================================================================
+
+using uchar = unsigned char;
+
+namespace {
+
+ size_t trailingBytes(unsigned char c) {
+ if ((c & 0xE0) == 0xC0) {
+ return 2;
+ }
+ if ((c & 0xF0) == 0xE0) {
+ return 3;
+ }
+ if ((c & 0xF8) == 0xF0) {
+ return 4;
+ }
+ DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+ }
+
+ uint32_t headerValue(unsigned char c) {
+ if ((c & 0xE0) == 0xC0) {
+ return c & 0x1F;
+ }
+ if ((c & 0xF0) == 0xE0) {
+ return c & 0x0F;
+ }
+ if ((c & 0xF8) == 0xF0) {
+ return c & 0x07;
+ }
+ DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
+ }
+
+ void hexEscapeChar(std::ostream& os, unsigned char c) {
+ std::ios_base::fmtflags f(os.flags());
+ os << "\\x"
+ << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+ << static_cast<int>(c);
+ os.flags(f);
+ }
+
+} // anonymous namespace
+
+ XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
+ : m_str( str ),
+ m_forWhat( forWhat )
+ {}
+
+ void XmlEncode::encodeTo( std::ostream& os ) const {
+ // Apostrophe escaping not necessary if we always use " to write attributes
+ // (see: https://www.w3.org/TR/xml/#syntax)
+
+ for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
+ uchar c = m_str[idx];
+ switch (c) {
+ case '<': os << "&lt;"; break;
+ case '&': os << "&amp;"; break;
+
+ case '>':
+ // See: https://www.w3.org/TR/xml/#syntax
+ if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
+ os << "&gt;";
+ else
+ os << c;
+ break;
+
+ case '\"':
+ if (m_forWhat == ForAttributes)
+ os << "&quot;";
+ else
+ os << c;
+ break;
+
+ default:
+ // Check for control characters and invalid utf-8
+
+ // Escape control characters in standard ascii
+ // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
+ if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
+ hexEscapeChar(os, c);
+ break;
+ }
+
+ // Plain ASCII: Write it to stream
+ if (c < 0x7F) {
+ os << c;
+ break;
+ }
+
+ // UTF-8 territory
+ // Check if the encoding is valid and if it is not, hex escape bytes.
+ // Important: We do not check the exact decoded values for validity, only the encoding format
+ // First check that this bytes is a valid lead byte:
+ // This means that it is not encoded as 1111 1XXX
+ // Or as 10XX XXXX
+ if (c < 0xC0 ||
+ c >= 0xF8) {
+ hexEscapeChar(os, c);
+ break;
+ }
+
+ auto encBytes = trailingBytes(c);
+ // Are there enough bytes left to avoid accessing out-of-bounds memory?
+ if (idx + encBytes - 1 >= m_str.size()) {
+ hexEscapeChar(os, c);
+ break;
+ }
+ // The header is valid, check data
+ // The next encBytes bytes must together be a valid utf-8
+ // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
+ bool valid = true;
+ uint32_t value = headerValue(c);
+ for (std::size_t n = 1; n < encBytes; ++n) {
+ uchar nc = m_str[idx + n];
+ valid &= ((nc & 0xC0) == 0x80);
+ value = (value << 6) | (nc & 0x3F);
+ }
+
+ if (
+ // Wrong bit pattern of following bytes
+ (!valid) ||
+ // Overlong encodings
+ (value < 0x80) ||
+ ( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant
+ (0x800 < value && value < 0x10000 && encBytes > 3) ||
+ // Encoded value out of range
+ (value >= 0x110000)
+ ) {
+ hexEscapeChar(os, c);
+ break;
+ }
+
+ // If we got here, this is in fact a valid(ish) utf-8 sequence
+ for (std::size_t n = 0; n < encBytes; ++n) {
+ os << m_str[idx + n];
+ }
+ idx += encBytes - 1;
+ break;
+ }
+ }
+ }
+
+ std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
+ xmlEncode.encodeTo( os );
+ return os;
+ }
+
+ XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
+ : m_writer( writer )
+ {}
+
+ XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT
+ : m_writer( other.m_writer ){
+ other.m_writer = nullptr;
+ }
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT {
+ if ( m_writer ) {
+ m_writer->endElement();
+ }
+ m_writer = other.m_writer;
+ other.m_writer = nullptr;
+ return *this;
+ }
+
+
+ XmlWriter::ScopedElement::~ScopedElement() {
+ if( m_writer )
+ m_writer->endElement();
+ }
+
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
+ m_writer->writeText( text, indent );
+ return *this;
+ }
+
+ XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
+ {
+ writeDeclaration();
+ }
+
+ XmlWriter::~XmlWriter() {
+ while( !m_tags.empty() )
+ endElement();
+ }
+
+ XmlWriter& XmlWriter::startElement( std::string const& name ) {
+ ensureTagClosed();
+ newlineIfNecessary();
+ m_os << m_indent << '<' << name;
+ m_tags.push_back( name );
+ m_indent += " ";
+ m_tagIsOpen = true;
+ return *this;
+ }
+
+ XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
+ ScopedElement scoped( this );
+ startElement( name );
+ return scoped;
+ }
+
+ XmlWriter& XmlWriter::endElement() {
+ newlineIfNecessary();
+ m_indent = m_indent.substr( 0, m_indent.size()-2 );
+ if( m_tagIsOpen ) {
+ m_os << "/>";
+ m_tagIsOpen = false;
+ }
+ else {
+ m_os << m_indent << "</" << m_tags.back() << ">";
+ }
+ m_os << std::endl;
+ m_tags.pop_back();
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
+ if( !name.empty() && !attribute.empty() )
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) {
+ if( !name.empty() && attribute && attribute[0] != '\0' )
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
+ m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
+ return *this;
+ }
+
+ XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
+ if( !text.empty() ){
+ bool tagWasOpen = m_tagIsOpen;
+ ensureTagClosed();
+ if( tagWasOpen && indent )
+ m_os << m_indent;
+ m_os << XmlEncode( text );
+ m_needsNewline = true;
+ }
+ return *this;
+ }
+
+ //XmlWriter& XmlWriter::writeComment( std::string const& text ) {
+ // ensureTagClosed();
+ // m_os << m_indent << "<!--" << text << "-->";
+ // m_needsNewline = true;
+ // return *this;
+ //}
+
+ //void XmlWriter::writeStylesheetRef( std::string const& url ) {
+ // m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
+ //}
+
+ //XmlWriter& XmlWriter::writeBlankLine() {
+ // ensureTagClosed();
+ // m_os << '\n';
+ // return *this;
+ //}
+
+ void XmlWriter::ensureTagClosed() {
+ if( m_tagIsOpen ) {
+ m_os << ">" << std::endl;
+ m_tagIsOpen = false;
+ }
+ }
+
+ void XmlWriter::writeDeclaration() {
+ m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ }
+
+ void XmlWriter::newlineIfNecessary() {
+ if( m_needsNewline ) {
+ m_os << std::endl;
+ m_needsNewline = false;
+ }
+ }
+
+// =================================================================================================
+// End of copy-pasted code from Catch
+// =================================================================================================
+
+ // clang-format on
+
+ struct XmlReporter : public IReporter
+ {
+ XmlWriter xml;
+ std::mutex mutex;
+
+ // caching pointers/references to objects of these types - safe to do
+ const ContextOptions& opt;
+ const TestCaseData* tc = nullptr;
+
+ XmlReporter(const ContextOptions& co)
+ : xml(*co.cout)
+ , opt(co) {}
+
+ void log_contexts() {
+ int num_contexts = get_num_active_contexts();
+ if(num_contexts) {
+ auto contexts = get_active_contexts();
+ std::stringstream ss;
+ for(int i = 0; i < num_contexts; ++i) {
+ contexts[i]->stringify(&ss);
+ xml.scopedElement("Info").writeText(ss.str());
+ ss.str("");
+ }
+ }
+ }
+
+ unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
+
+ void test_case_start_impl(const TestCaseData& in) {
+ bool open_ts_tag = false;
+ if(tc != nullptr) { // we have already opened a test suite
+ if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) {
+ xml.endElement();
+ open_ts_tag = true;
+ }
+ }
+ else {
+ open_ts_tag = true; // first test case ==> first test suite
+ }
+
+ if(open_ts_tag) {
+ xml.startElement("TestSuite");
+ xml.writeAttribute("name", in.m_test_suite);
+ }
+
+ tc = &in;
+ xml.startElement("TestCase")
+ .writeAttribute("name", in.m_name)
+ .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str()))
+ .writeAttribute("line", line(in.m_line))
+ .writeAttribute("description", in.m_description);
+
+ if(Approx(in.m_timeout) != 0)
+ xml.writeAttribute("timeout", in.m_timeout);
+ if(in.m_may_fail)
+ xml.writeAttribute("may_fail", true);
+ if(in.m_should_fail)
+ xml.writeAttribute("should_fail", true);
+ }
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
+ // =========================================================================================
+
+ void report_query(const QueryData& in) override {
+ test_run_start();
+ if(opt.list_reporters) {
+ for(auto& curr : getListeners())
+ xml.scopedElement("Listener")
+ .writeAttribute("priority", curr.first.first)
+ .writeAttribute("name", curr.first.second);
+ for(auto& curr : getReporters())
+ xml.scopedElement("Reporter")
+ .writeAttribute("priority", curr.first.first)
+ .writeAttribute("name", curr.first.second);
+ } else if(opt.count || opt.list_test_cases) {
+ for(unsigned i = 0; i < in.num_data; ++i) {
+ xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name)
+ .writeAttribute("testsuite", in.data[i]->m_test_suite)
+ .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str()))
+ .writeAttribute("line", line(in.data[i]->m_line));
+ }
+ xml.scopedElement("OverallResultsTestCases")
+ .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
+ } else if(opt.list_test_suites) {
+ for(unsigned i = 0; i < in.num_data; ++i)
+ xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite);
+ xml.scopedElement("OverallResultsTestCases")
+ .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
+ xml.scopedElement("OverallResultsTestSuites")
+ .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters);
+ }
+ xml.endElement();
+ }
+
+ void test_run_start() override {
+ // remove .exe extension - mainly to have the same output on UNIX and Windows
+ std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ if(binary_name.rfind(".exe") != std::string::npos)
+ binary_name = binary_name.substr(0, binary_name.length() - 4);
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ xml.startElement("doctest").writeAttribute("binary", binary_name);
+ if(opt.no_version == false)
+ xml.writeAttribute("version", DOCTEST_VERSION_STR);
+
+ // only the consequential ones (TODO: filters)
+ xml.scopedElement("Options")
+ .writeAttribute("order_by", opt.order_by.c_str())
+ .writeAttribute("rand_seed", opt.rand_seed)
+ .writeAttribute("first", opt.first)
+ .writeAttribute("last", opt.last)
+ .writeAttribute("abort_after", opt.abort_after)
+ .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels)
+ .writeAttribute("case_sensitive", opt.case_sensitive)
+ .writeAttribute("no_throw", opt.no_throw)
+ .writeAttribute("no_skip", opt.no_skip);
+ }
+
+ void test_run_end(const TestRunStats& p) override {
+ if(tc) // the TestSuite tag - only if there has been at least 1 test case
+ xml.endElement();
+
+ xml.scopedElement("OverallResultsAsserts")
+ .writeAttribute("successes", p.numAsserts - p.numAssertsFailed)
+ .writeAttribute("failures", p.numAssertsFailed);
+
+ xml.startElement("OverallResultsTestCases")
+ .writeAttribute("successes",
+ p.numTestCasesPassingFilters - p.numTestCasesFailed)
+ .writeAttribute("failures", p.numTestCasesFailed);
+ if(opt.no_skipped_summary == false)
+ xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters);
+ xml.endElement();
+
+ xml.endElement();
+ }
+
+ void test_case_start(const TestCaseData& in) override {
+ test_case_start_impl(in);
+ xml.ensureTagClosed();
+ }
+
+ void test_case_reenter(const TestCaseData&) override {}
+
+ void test_case_end(const CurrentTestCaseStats& st) override {
+ xml.startElement("OverallResultsAsserts")
+ .writeAttribute("successes",
+ st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest)
+ .writeAttribute("failures", st.numAssertsFailedCurrentTest);
+ if(opt.duration)
+ xml.writeAttribute("duration", st.seconds);
+ if(tc->m_expected_failures)
+ xml.writeAttribute("expected_failures", tc->m_expected_failures);
+ xml.endElement();
+
+ xml.endElement();
+ }
+
+ void test_case_exception(const TestCaseException& e) override {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ xml.scopedElement("Exception")
+ .writeAttribute("crash", e.is_crash)
+ .writeText(e.error_string.c_str());
+ }
+
+ void subcase_start(const SubcaseSignature& in) override {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ xml.startElement("SubCase")
+ .writeAttribute("name", in.m_name)
+ .writeAttribute("filename", skipPathFromFilename(in.m_file))
+ .writeAttribute("line", line(in.m_line));
+ xml.ensureTagClosed();
+ }
+
+ void subcase_end() override { xml.endElement(); }
+
+ void log_assert(const AssertData& rb) override {
+ if(!rb.m_failed && !opt.success)
+ return;
+
+ std::lock_guard<std::mutex> lock(mutex);
+
+ xml.startElement("Expression")
+ .writeAttribute("success", !rb.m_failed)
+ .writeAttribute("type", assertString(rb.m_at))
+ .writeAttribute("filename", skipPathFromFilename(rb.m_file))
+ .writeAttribute("line", line(rb.m_line));
+
+ xml.scopedElement("Original").writeText(rb.m_expr);
+
+ if(rb.m_threw)
+ xml.scopedElement("Exception").writeText(rb.m_exception.c_str());
+
+ if(rb.m_at & assertType::is_throws_as)
+ xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
+ if(rb.m_at & assertType::is_throws_with)
+ xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string);
+ if((rb.m_at & assertType::is_normal) && !rb.m_threw)
+ xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
+
+ log_contexts();
+
+ xml.endElement();
+ }
+
+ void log_message(const MessageData& mb) override {
+ std::lock_guard<std::mutex> lock(mutex);
+
+ xml.startElement("Message")
+ .writeAttribute("type", failureString(mb.m_severity))
+ .writeAttribute("filename", skipPathFromFilename(mb.m_file))
+ .writeAttribute("line", line(mb.m_line));
+
+ xml.scopedElement("Text").writeText(mb.m_string.c_str());
+
+ log_contexts();
+
+ xml.endElement();
+ }
+
+ void test_case_skipped(const TestCaseData& in) override {
+ if(opt.no_skipped_summary == false) {
+ test_case_start_impl(in);
+ xml.writeAttribute("skipped", "true");
+ xml.endElement();
+ }
+ }
+ };
+
+ DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter);
+
+ void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) {
+ if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) ==
+ 0) //!OCLINT bitwise operator in conditional
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) "
+ << Color::None;
+
+ if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
+ s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
+ } else if((rb.m_at & assertType::is_throws_as) &&
+ (rb.m_at & assertType::is_throws_with)) { //!OCLINT
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
+ << rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None;
+ if(rb.m_threw) {
+ if(!rb.m_failed) {
+ s << "threw as expected!\n";
+ } else {
+ s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n";
+ }
+ } else {
+ s << "did NOT throw at all!\n";
+ }
+ } else if(rb.m_at &
+ assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
+ << rb.m_exception_type << " ) " << Color::None
+ << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" :
+ "threw a DIFFERENT exception: ") :
+ "did NOT throw at all!")
+ << Color::Cyan << rb.m_exception << "\n";
+ } else if(rb.m_at &
+ assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
+ s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
+ << rb.m_exception_string << "\" ) " << Color::None
+ << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
+ "threw a DIFFERENT exception: ") :
+ "did NOT throw at all!")
+ << Color::Cyan << rb.m_exception << "\n";
+ } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
+ s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan
+ << rb.m_exception << "\n";
+ } else {
+ s << (rb.m_threw ? "THREW exception: " :
+ (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n"));
+ if(rb.m_threw)
+ s << rb.m_exception << "\n";
+ else
+ s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n";
+ }
+ }
+
+ // TODO:
+ // - log_message()
+ // - respond to queries
+ // - honor remaining options
+ // - more attributes in tags
+ struct JUnitReporter : public IReporter
+ {
+ XmlWriter xml;
+ std::mutex mutex;
+ Timer timer;
+ std::vector<String> deepestSubcaseStackNames;
+
+ struct JUnitTestCaseData
+ {
+ static std::string getCurrentTimestamp() {
+ // Beware, this is not reentrant because of backward compatibility issues
+ // Also, UTC only, again because of backward compatibility (%z is C++11)
+ time_t rawtime;
+ std::time(&rawtime);
+ auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
+
+ std::tm timeInfo;
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ gmtime_s(&timeInfo, &rawtime);
+#else // DOCTEST_PLATFORM_WINDOWS
+ gmtime_r(&rawtime, &timeInfo);
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ char timeStamp[timeStampSize];
+ const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+ std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+ return std::string(timeStamp);
+ }
+
+ struct JUnitTestMessage
+ {
+ JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details)
+ : message(_message), type(_type), details(_details) {}
+
+ JUnitTestMessage(const std::string& _message, const std::string& _details)
+ : message(_message), type(), details(_details) {}
+
+ std::string message, type, details;
+ };
+
+ struct JUnitTestCase
+ {
+ JUnitTestCase(const std::string& _classname, const std::string& _name)
+ : classname(_classname), name(_name), time(0), failures() {}
+
+ std::string classname, name;
+ double time;
+ std::vector<JUnitTestMessage> failures, errors;
+ };
+
+ void add(const std::string& classname, const std::string& name) {
+ testcases.emplace_back(classname, name);
+ }
+
+ void appendSubcaseNamesToLastTestcase(std::vector<String> nameStack) {
+ for(auto& curr: nameStack)
+ if(curr.size())
+ testcases.back().name += std::string("/") + curr.c_str();
+ }
+
+ void addTime(double time) {
+ if(time < 1e-4)
+ time = 0;
+ testcases.back().time = time;
+ totalSeconds += time;
+ }
+
+ void addFailure(const std::string& message, const std::string& type, const std::string& details) {
+ testcases.back().failures.emplace_back(message, type, details);
+ ++totalFailures;
+ }
+
+ void addError(const std::string& message, const std::string& details) {
+ testcases.back().errors.emplace_back(message, details);
+ ++totalErrors;
+ }
+
+ std::vector<JUnitTestCase> testcases;
+ double totalSeconds = 0;
+ int totalErrors = 0, totalFailures = 0;
+ };
+
+ JUnitTestCaseData testCaseData;
+
+ // caching pointers/references to objects of these types - safe to do
+ const ContextOptions& opt;
+ const TestCaseData* tc = nullptr;
+
+ JUnitReporter(const ContextOptions& co)
+ : xml(*co.cout)
+ , opt(co) {}
+
+ unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
+ // =========================================================================================
+
+ void report_query(const QueryData&) override {}
+
+ void test_run_start() override {}
+
+ void test_run_end(const TestRunStats& p) override {
+ // remove .exe extension - mainly to have the same output on UNIX and Windows
+ std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ if(binary_name.rfind(".exe") != std::string::npos)
+ binary_name = binary_name.substr(0, binary_name.length() - 4);
+#endif // DOCTEST_PLATFORM_WINDOWS
+ xml.startElement("testsuites");
+ xml.startElement("testsuite").writeAttribute("name", binary_name)
+ .writeAttribute("errors", testCaseData.totalErrors)
+ .writeAttribute("failures", testCaseData.totalFailures)
+ .writeAttribute("tests", p.numAsserts);
+ if(opt.no_time_in_output == false) {
+ xml.writeAttribute("time", testCaseData.totalSeconds);
+ xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp());
+ }
+ if(opt.no_version == false)
+ xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR);
+
+ for(const auto& testCase : testCaseData.testcases) {
+ xml.startElement("testcase")
+ .writeAttribute("classname", testCase.classname)
+ .writeAttribute("name", testCase.name);
+ if(opt.no_time_in_output == false)
+ xml.writeAttribute("time", testCase.time);
+ // This is not ideal, but it should be enough to mimic gtest's junit output.
+ xml.writeAttribute("status", "run");
+
+ for(const auto& failure : testCase.failures) {
+ xml.scopedElement("failure")
+ .writeAttribute("message", failure.message)
+ .writeAttribute("type", failure.type)
+ .writeText(failure.details, false);
+ }
+
+ for(const auto& error : testCase.errors) {
+ xml.scopedElement("error")
+ .writeAttribute("message", error.message)
+ .writeText(error.details);
+ }
+
+ xml.endElement();
+ }
+ xml.endElement();
+ xml.endElement();
+ }
+
+ void test_case_start(const TestCaseData& in) override {
+ testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
+ timer.start();
+ }
+
+ void test_case_reenter(const TestCaseData& in) override {
+ testCaseData.addTime(timer.getElapsedSeconds());
+ testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
+ deepestSubcaseStackNames.clear();
+
+ timer.start();
+ testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
+ }
+
+ void test_case_end(const CurrentTestCaseStats&) override {
+ testCaseData.addTime(timer.getElapsedSeconds());
+ testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
+ deepestSubcaseStackNames.clear();
+ }
+
+ void test_case_exception(const TestCaseException& e) override {
+ std::lock_guard<std::mutex> lock(mutex);
+ testCaseData.addError("exception", e.error_string.c_str());
+ }
+
+ void subcase_start(const SubcaseSignature& in) override {
+ std::lock_guard<std::mutex> lock(mutex);
+ deepestSubcaseStackNames.push_back(in.m_name);
+ }
+
+ void subcase_end() override {}
+
+ void log_assert(const AssertData& rb) override {
+ if(!rb.m_failed) // report only failures & ignore the `success` option
+ return;
+
+ std::lock_guard<std::mutex> lock(mutex);
+
+ std::ostringstream os;
+ os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(")
+ << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
+
+ fulltext_log_assert_to_stream(os, rb);
+ log_contexts(os);
+ testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str());
+ }
+
+ void log_message(const MessageData&) override {}
+
+ void test_case_skipped(const TestCaseData&) override {}
+
+ void log_contexts(std::ostringstream& s) {
+ int num_contexts = get_num_active_contexts();
+ if(num_contexts) {
+ auto contexts = get_active_contexts();
+
+ s << " logged: ";
+ for(int i = 0; i < num_contexts; ++i) {
+ s << (i == 0 ? "" : " ");
+ contexts[i]->stringify(&s);
+ s << std::endl;
+ }
+ }
+ }
+ };
+
+ DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter);
+
+ struct Whitespace
+ {
+ int nrSpaces;
+ explicit Whitespace(int nr)
+ : nrSpaces(nr) {}
+ };
+
+ std::ostream& operator<<(std::ostream& out, const Whitespace& ws) {
+ if(ws.nrSpaces != 0)
+ out << std::setw(ws.nrSpaces) << ' ';
+ return out;
+ }
+
+ struct ConsoleReporter : public IReporter
+ {
+ std::ostream& s;
+ bool hasLoggedCurrentTestStart;
+ std::vector<SubcaseSignature> subcasesStack;
+ size_t currentSubcaseLevel;
+ std::mutex mutex;
+
+ // caching pointers/references to objects of these types - safe to do
+ const ContextOptions& opt;
+ const TestCaseData* tc;
+
+ ConsoleReporter(const ContextOptions& co)
+ : s(*co.cout)
+ , opt(co) {}
+
+ ConsoleReporter(const ContextOptions& co, std::ostream& ostr)
+ : s(ostr)
+ , opt(co) {}
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE
+ // =========================================================================================
+
+ void separator_to_stream() {
+ s << Color::Yellow
+ << "==============================================================================="
+ "\n";
+ }
+
+ const char* getSuccessOrFailString(bool success, assertType::Enum at,
+ const char* success_str) {
+ if(success)
+ return success_str;
+ return failureString(at);
+ }
+
+ Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) {
+ return success ? Color::BrightGreen :
+ (at & assertType::is_warn) ? Color::Yellow : Color::Red;
+ }
+
+ void successOrFailColoredStringToStream(bool success, assertType::Enum at,
+ const char* success_str = "SUCCESS") {
+ s << getSuccessOrFailColor(success, at)
+ << getSuccessOrFailString(success, at, success_str) << ": ";
+ }
+
+ void log_contexts() {
+ int num_contexts = get_num_active_contexts();
+ if(num_contexts) {
+ auto contexts = get_active_contexts();
+
+ s << Color::None << " logged: ";
+ for(int i = 0; i < num_contexts; ++i) {
+ s << (i == 0 ? "" : " ");
+ contexts[i]->stringify(&s);
+ s << "\n";
+ }
+ }
+
+ s << "\n";
+ }
+
+ // this was requested to be made virtual so users could override it
+ virtual void file_line_to_stream(const char* file, int line,
+ const char* tail = "") {
+ s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(")
+ << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option
+ << (opt.gnu_file_line ? ":" : "):") << tail;
+ }
+
+ void logTestStart() {
+ if(hasLoggedCurrentTestStart)
+ return;
+
+ separator_to_stream();
+ file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n");
+ if(tc->m_description)
+ s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n";
+ if(tc->m_test_suite && tc->m_test_suite[0] != '\0')
+ s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n";
+ if(strncmp(tc->m_name, " Scenario:", 11) != 0)
+ s << Color::Yellow << "TEST CASE: ";
+ s << Color::None << tc->m_name << "\n";
+
+ for(size_t i = 0; i < currentSubcaseLevel; ++i) {
+ if(subcasesStack[i].m_name[0] != '\0')
+ s << " " << subcasesStack[i].m_name << "\n";
+ }
+
+ if(currentSubcaseLevel != subcasesStack.size()) {
+ s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None;
+ for(size_t i = 0; i < subcasesStack.size(); ++i) {
+ if(subcasesStack[i].m_name[0] != '\0')
+ s << " " << subcasesStack[i].m_name << "\n";
+ }
+ }
+
+ s << "\n";
+
+ hasLoggedCurrentTestStart = true;
+ }
+
+ void printVersion() {
+ if(opt.no_version == false)
+ s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \""
+ << DOCTEST_VERSION_STR << "\"\n";
+ }
+
+ void printIntro() {
+ printVersion();
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
+ }
+
+ void printHelp() {
+ int sizePrefixDisplay = static_cast<int>(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY));
+ printVersion();
+ // clang-format off
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n";
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "filter values: \"str1,str2,str3\" (comma separated strings)\n";
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "filters use wildcards for matching strings\n";
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "something passes a filter if any of the strings in a filter matches\n";
+#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n";
+#endif
+ s << Color::Cyan << "[doctest]\n" << Color::None;
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "Query flags - the program quits after them. Available:\n\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h "
+ << Whitespace(sizePrefixDisplay*0) << "prints this message\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version "
+ << Whitespace(sizePrefixDisplay*1) << "prints the version\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count "
+ << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases "
+ << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites "
+ << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters "
+ << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n";
+ // ================================================================================== << 79
+ s << Color::Cyan << "[doctest] " << Color::None;
+ s << "The available <int>/<string> options/filters are:\n\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters=<filters> "
+ << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out=<string> "
+ << Whitespace(sizePrefixDisplay*1) << "output filename\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string> "
+ << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n";
+ s << Whitespace(sizePrefixDisplay*3) << " <string> - [file/suite/name/rand/none]\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n";
+ s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n";
+ s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "stop after <int> failed assertions\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels=<int> "
+ << Whitespace(sizePrefixDisplay*1) << "apply filters for the first <int> levels\n";
+ s << Color::Cyan << "\n[doctest] " << Color::None;
+ s << "Bool options - can be used like flags and true is assumed. Available:\n\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n";
+ // ================================================================================== << 79
+ // clang-format on
+
+ s << Color::Cyan << "\n[doctest] " << Color::None;
+ s << "for more information visit the project documentation\n\n";
+ }
+
+ void printRegisteredReporters() {
+ printVersion();
+ auto printReporters = [this] (const reporterMap& reporters, const char* type) {
+ if(reporters.size()) {
+ s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n";
+ for(auto& curr : reporters)
+ s << "priority: " << std::setw(5) << curr.first.first
+ << " name: " << curr.first.second << "\n";
+ }
+ };
+ printReporters(getListeners(), "listeners");
+ printReporters(getReporters(), "reporters");
+ }
+
+ void list_query_results() {
+ separator_to_stream();
+ if(opt.count || opt.list_test_cases) {
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "unskipped test cases passing the current filters: "
+ << g_cs->numTestCasesPassingFilters << "\n";
+ } else if(opt.list_test_suites) {
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "unskipped test cases passing the current filters: "
+ << g_cs->numTestCasesPassingFilters << "\n";
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "test suites with unskipped test cases passing the current filters: "
+ << g_cs->numTestSuitesPassingFilters << "\n";
+ }
+ }
+
+ // =========================================================================================
+ // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
+ // =========================================================================================
+
+ void report_query(const QueryData& in) override {
+ if(opt.version) {
+ printVersion();
+ } else if(opt.help) {
+ printHelp();
+ } else if(opt.list_reporters) {
+ printRegisteredReporters();
+ } else if(opt.count || opt.list_test_cases) {
+ if(opt.list_test_cases) {
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "listing all test case names\n";
+ separator_to_stream();
+ }
+
+ for(unsigned i = 0; i < in.num_data; ++i)
+ s << Color::None << in.data[i]->m_name << "\n";
+
+ separator_to_stream();
+
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "unskipped test cases passing the current filters: "
+ << g_cs->numTestCasesPassingFilters << "\n";
+
+ } else if(opt.list_test_suites) {
+ s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n";
+ separator_to_stream();
+
+ for(unsigned i = 0; i < in.num_data; ++i)
+ s << Color::None << in.data[i]->m_test_suite << "\n";
+
+ separator_to_stream();
+
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "unskipped test cases passing the current filters: "
+ << g_cs->numTestCasesPassingFilters << "\n";
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "test suites with unskipped test cases passing the current filters: "
+ << g_cs->numTestSuitesPassingFilters << "\n";
+ }
+ }
+
+ void test_run_start() override { printIntro(); }
+
+ void test_run_end(const TestRunStats& p) override {
+ separator_to_stream();
+ s << std::dec;
+
+ auto totwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
+ auto passwidth = int(std::ceil(log10((std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
+ auto failwidth = int(std::ceil(log10((std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
+ const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
+ s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth)
+ << p.numTestCasesPassingFilters << " | "
+ << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None :
+ Color::Green)
+ << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed"
+ << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None)
+ << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |";
+ if(opt.no_skipped_summary == false) {
+ const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters;
+ s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped
+ << " skipped" << Color::None;
+ }
+ s << "\n";
+ s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth)
+ << p.numAsserts << " | "
+ << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green)
+ << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None
+ << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth)
+ << p.numAssertsFailed << " failed" << Color::None << " |\n";
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green)
+ << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl;
+ }
+
+ void test_case_start(const TestCaseData& in) override {
+ hasLoggedCurrentTestStart = false;
+ tc = &in;
+ subcasesStack.clear();
+ currentSubcaseLevel = 0;
+ }
+
+ void test_case_reenter(const TestCaseData&) override {
+ subcasesStack.clear();
+ }
+
+ void test_case_end(const CurrentTestCaseStats& st) override {
+ if(tc->m_no_output)
+ return;
+
+ // log the preamble of the test case only if there is something
+ // else to print - something other than that an assert has failed
+ if(opt.duration ||
+ (st.failure_flags && st.failure_flags != TestCaseFailureReason::AssertFailure))
+ logTestStart();
+
+ if(opt.duration)
+ s << Color::None << std::setprecision(6) << std::fixed << st.seconds
+ << " s: " << tc->m_name << "\n";
+
+ if(st.failure_flags & TestCaseFailureReason::Timeout)
+ s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6)
+ << std::fixed << tc->m_timeout << "!\n";
+
+ if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) {
+ s << Color::Red << "Should have failed but didn't! Marking it as failed!\n";
+ } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) {
+ s << Color::Yellow << "Failed as expected so marking it as not failed\n";
+ } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) {
+ s << Color::Yellow << "Allowed to fail so marking it as not failed\n";
+ } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) {
+ s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures
+ << " times so marking it as failed!\n";
+ } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) {
+ s << Color::Yellow << "Failed exactly " << tc->m_expected_failures
+ << " times as expected so marking it as not failed!\n";
+ }
+ if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) {
+ s << Color::Red << "Aborting - too many failed asserts!\n";
+ }
+ s << Color::None; // lgtm [cpp/useless-expression]
+ }
+
+ void test_case_exception(const TestCaseException& e) override {
+ if(tc->m_no_output)
+ return;
+
+ logTestStart();
+
+ file_line_to_stream(tc->m_file.c_str(), tc->m_line, " ");
+ successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require :
+ assertType::is_check);
+ s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ")
+ << Color::Cyan << e.error_string << "\n";
+
+ int num_stringified_contexts = get_num_stringified_contexts();
+ if(num_stringified_contexts) {
+ auto stringified_contexts = get_stringified_contexts();
+ s << Color::None << " logged: ";
+ for(int i = num_stringified_contexts; i > 0; --i) {
+ s << (i == num_stringified_contexts ? "" : " ")
+ << stringified_contexts[i - 1] << "\n";
+ }
+ }
+ s << "\n" << Color::None;
+ }
+
+ void subcase_start(const SubcaseSignature& subc) override {
+ std::lock_guard<std::mutex> lock(mutex);
+ subcasesStack.push_back(subc);
+ ++currentSubcaseLevel;
+ hasLoggedCurrentTestStart = false;
+ }
+
+ void subcase_end() override {
+ std::lock_guard<std::mutex> lock(mutex);
+ --currentSubcaseLevel;
+ hasLoggedCurrentTestStart = false;
+ }
+
+ void log_assert(const AssertData& rb) override {
+ if((!rb.m_failed && !opt.success) || tc->m_no_output)
+ return;
+
+ std::lock_guard<std::mutex> lock(mutex);
+
+ logTestStart();
+
+ file_line_to_stream(rb.m_file, rb.m_line, " ");
+ successOrFailColoredStringToStream(!rb.m_failed, rb.m_at);
+
+ fulltext_log_assert_to_stream(s, rb);
+
+ log_contexts();
+ }
+
+ void log_message(const MessageData& mb) override {
+ if(tc->m_no_output)
+ return;
+
+ std::lock_guard<std::mutex> lock(mutex);
+
+ logTestStart();
+
+ file_line_to_stream(mb.m_file, mb.m_line, " ");
+ s << getSuccessOrFailColor(false, mb.m_severity)
+ << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity,
+ "MESSAGE") << ": ";
+ s << Color::None << mb.m_string << "\n";
+ log_contexts();
+ }
+
+ void test_case_skipped(const TestCaseData&) override {}
+ };
+
+ DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter);
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ struct DebugOutputWindowReporter : public ConsoleReporter
+ {
+ DOCTEST_THREAD_LOCAL static std::ostringstream oss;
+
+ DebugOutputWindowReporter(const ContextOptions& co)
+ : ConsoleReporter(co, oss) {}
+
+#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \
+ void func(type arg) override { \
+ bool with_col = g_no_colors; \
+ g_no_colors = false; \
+ ConsoleReporter::func(arg); \
+ if(oss.tellp() != std::streampos{}) { \
+ DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \
+ oss.str(""); \
+ } \
+ g_no_colors = with_col; \
+ }
+
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in)
+ DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in)
+ };
+
+ DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ // the implementation of parseOption()
+ bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
+ // going from the end to the beginning and stopping on the first occurrence from the end
+ for(int i = argc; i > 0; --i) {
+ auto index = i - 1;
+ auto temp = std::strstr(argv[index], pattern);
+ if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
+ // eliminate matches in which the chars before the option are not '-'
+ bool noBadCharsFound = true;
+ auto curr = argv[index];
+ while(curr != temp) {
+ if(*curr++ != '-') {
+ noBadCharsFound = false;
+ break;
+ }
+ }
+ if(noBadCharsFound && argv[index][0] == '-') {
+ if(value) {
+ // parsing the value of an option
+ temp += strlen(pattern);
+ const unsigned len = strlen(temp);
+ if(len) {
+ *value = temp;
+ return true;
+ }
+ } else {
+ // just a flag - no value
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ // parses an option and returns the string after the '=' character
+ bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
+ const String& defaultVal = String()) {
+ if(value)
+ *value = defaultVal;
+#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ // offset (normally 3 for "dt-") to skip prefix
+ if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
+ return true;
+#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
+ return parseOptionImpl(argc, argv, pattern, value);
+ }
+
+ // locates a flag on the command line
+ bool parseFlag(int argc, const char* const* argv, const char* pattern) {
+ return parseOption(argc, argv, pattern);
+ }
+
+ // parses a comma separated list of words after a pattern in one of the arguments in argv
+ bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
+ std::vector<String>& res) {
+ String filtersString;
+ if(parseOption(argc, argv, pattern, &filtersString)) {
+ // tokenize with "," as a separator
+ // cppcheck-suppress strtokCalled
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ auto pch = std::strtok(filtersString.c_str(), ","); // modifies the string
+ while(pch != nullptr) {
+ if(strlen(pch))
+ res.push_back(pch);
+ // uses the strtok() internal state to go to the next token
+ // cppcheck-suppress strtokCalled
+ pch = std::strtok(nullptr, ",");
+ }
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ return true;
+ }
+ return false;
+ }
+
+ enum optionType
+ {
+ option_bool,
+ option_int
+ };
+
+ // parses an int/bool option from the command line
+ bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
+ int& res) {
+ String parsedValue;
+ if(!parseOption(argc, argv, pattern, &parsedValue))
+ return false;
+
+ if(type == 0) {
+ // boolean
+ const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1
+ const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
+
+ // if the value matches any of the positive/negative possibilities
+ for(unsigned i = 0; i < 4; i++) {
+ if(parsedValue.compare(positive[i], true) == 0) {
+ res = 1; //!OCLINT parameter reassignment
+ return true;
+ }
+ if(parsedValue.compare(negative[i], true) == 0) {
+ res = 0; //!OCLINT parameter reassignment
+ return true;
+ }
+ }
+ } else {
+ // integer
+ // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
+ int theInt = std::atoi(parsedValue.c_str()); // NOLINT
+ if(theInt != 0) {
+ res = theInt; //!OCLINT parameter reassignment
+ return true;
+ }
+ }
+ return false;
+ }
+} // namespace
+
+Context::Context(int argc, const char* const* argv)
+ : p(new detail::ContextState) {
+ parseArgs(argc, argv, true);
+ if(argc)
+ p->binary_name = argv[0];
+}
+
+Context::~Context() {
+ if(g_cs == p)
+ g_cs = nullptr;
+ delete p;
+}
+
+void Context::applyCommandLine(int argc, const char* const* argv) {
+ parseArgs(argc, argv);
+ if(argc)
+ p->binary_name = argv[0];
+}
+
+// parses args
+void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
+ using namespace detail;
+
+ // clang-format off
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]);
+ parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]);
+ // clang-format on
+
+ int intRes = 0;
+ String strRes;
+
+#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
+ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \
+ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \
+ p->var = static_cast<bool>(intRes); \
+ else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \
+ p->var = true; \
+ else if(withDefaults) \
+ p->var = default
+
+#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \
+ if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \
+ parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \
+ p->var = intRes; \
+ else if(withDefaults) \
+ p->var = default
+
+#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
+ if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \
+ parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \
+ withDefaults) \
+ p->var = strRes
+
+ // clang-format off
+ DOCTEST_PARSE_STR_OPTION("out", "o", out, "");
+ DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file");
+ DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0);
+
+ DOCTEST_PARSE_INT_OPTION("first", "f", first, 0);
+ DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX);
+
+ DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0);
+ DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX);
+
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC));
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false);
+ // clang-format on
+
+ if(withDefaults) {
+ p->help = false;
+ p->version = false;
+ p->count = false;
+ p->list_test_cases = false;
+ p->list_test_suites = false;
+ p->list_reporters = false;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) {
+ p->help = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) {
+ p->version = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) {
+ p->count = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) {
+ p->list_test_cases = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) {
+ p->list_test_suites = true;
+ p->exit = true;
+ }
+ if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") ||
+ parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) {
+ p->list_reporters = true;
+ p->exit = true;
+ }
+}
+
+// allows the user to add procedurally to the filters from the command line
+void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
+
+// allows the user to clear all filters from the command line
+void Context::clearFilters() {
+ for(auto& curr : p->filters)
+ curr.clear();
+}
+
+// allows the user to override procedurally the int/bool options from the command line
+void Context::setOption(const char* option, int value) {
+ setOption(option, toString(value).c_str());
+ // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+}
+
+// allows the user to override procedurally the string options from the command line
+void Context::setOption(const char* option, const char* value) {
+ auto argv = String("-") + option + "=" + value;
+ auto lvalue = argv.c_str();
+ parseArgs(1, &lvalue);
+}
+
+// users should query this in their main() and exit the program if true
+bool Context::shouldExit() { return p->exit; }
+
+void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; }
+
+void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; }
+
+// the main function that does all the filtering and test running
+int Context::run() {
+ using namespace detail;
+
+ // save the old context state in case such was setup - for using asserts out of a testing context
+ auto old_cs = g_cs;
+ // this is the current contest
+ g_cs = p;
+ is_running_in_test = true;
+
+ g_no_colors = p->no_colors;
+ p->resetRunData();
+
+ // stdout by default
+ p->cout = &std::cout;
+ p->cerr = &std::cerr;
+
+ // or to a file if specified
+ std::fstream fstr;
+ if(p->out.size()) {
+ fstr.open(p->out.c_str(), std::fstream::out);
+ p->cout = &fstr;
+ }
+
+ FatalConditionHandler::allocateAltStackMem();
+
+ auto cleanup_and_return = [&]() {
+ FatalConditionHandler::freeAltStackMem();
+
+ if(fstr.is_open())
+ fstr.close();
+
+ // restore context
+ g_cs = old_cs;
+ is_running_in_test = false;
+
+ // we have to free the reporters which were allocated when the run started
+ for(auto& curr : p->reporters_currently_used)
+ delete curr;
+ p->reporters_currently_used.clear();
+
+ if(p->numTestCasesFailed && !p->no_exitcode)
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ };
+
+ // setup default reporter if none is given through the command line
+ if(p->filters[8].empty())
+ p->filters[8].push_back("console");
+
+ // check to see if any of the registered reporters has been selected
+ for(auto& curr : getReporters()) {
+ if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive))
+ p->reporters_currently_used.push_back(curr.second(*g_cs));
+ }
+
+ // TODO: check if there is nothing in reporters_currently_used
+
+ // prepend all listeners
+ for(auto& curr : getListeners())
+ p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs));
+
+#ifdef DOCTEST_PLATFORM_WINDOWS
+ if(isDebuggerActive() && p->no_debug_output == false)
+ p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs));
+#endif // DOCTEST_PLATFORM_WINDOWS
+
+ // handle version, help and no_run
+ if(p->no_run || p->version || p->help || p->list_reporters) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData());
+
+ return cleanup_and_return();
+ }
+
+ std::vector<const TestCase*> testArray;
+ for(auto& curr : getRegisteredTests())
+ testArray.push_back(&curr);
+ p->numTestCases = testArray.size();
+
+ // sort the collected records
+ if(!testArray.empty()) {
+ if(p->order_by.compare("file", true) == 0) {
+ std::sort(testArray.begin(), testArray.end(), fileOrderComparator);
+ } else if(p->order_by.compare("suite", true) == 0) {
+ std::sort(testArray.begin(), testArray.end(), suiteOrderComparator);
+ } else if(p->order_by.compare("name", true) == 0) {
+ std::sort(testArray.begin(), testArray.end(), nameOrderComparator);
+ } else if(p->order_by.compare("rand", true) == 0) {
+ std::srand(p->rand_seed);
+
+ // random_shuffle implementation
+ const auto first = &testArray[0];
+ for(size_t i = testArray.size() - 1; i > 0; --i) {
+ int idxToSwap = std::rand() % (i + 1); // NOLINT
+
+ const auto temp = first[i];
+
+ first[i] = first[idxToSwap];
+ first[idxToSwap] = temp;
+ }
+ } else if(p->order_by.compare("none", true) == 0) {
+ // means no sorting - beneficial for death tests which call into the executable
+ // with a specific test case in mind - we don't want to slow down the startup times
+ }
+ }
+
+ std::set<String> testSuitesPassingFilt;
+
+ bool query_mode = p->count || p->list_test_cases || p->list_test_suites;
+ std::vector<const TestCaseData*> queryResults;
+
+ if(!query_mode)
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY);
+
+ // invoke the registered functions if they match the filter criteria (or just count them)
+ for(auto& curr : testArray) {
+ const auto& tc = *curr;
+
+ bool skip_me = false;
+ if(tc.m_skip && !p->no_skip)
+ skip_me = true;
+
+ if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive))
+ skip_me = true;
+ if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive))
+ skip_me = true;
+ if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive))
+ skip_me = true;
+ if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive))
+ skip_me = true;
+ if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive))
+ skip_me = true;
+ if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive))
+ skip_me = true;
+
+ if(!skip_me)
+ p->numTestCasesPassingFilters++;
+
+ // skip the test if it is not in the execution range
+ if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) ||
+ (p->first > p->numTestCasesPassingFilters))
+ skip_me = true;
+
+ if(skip_me) {
+ if(!query_mode)
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc);
+ continue;
+ }
+
+ // do not execute the test if we are to only count the number of filter passing tests
+ if(p->count)
+ continue;
+
+ // print the name of the test and don't execute it
+ if(p->list_test_cases) {
+ queryResults.push_back(&tc);
+ continue;
+ }
+
+ // print the name of the test suite if not done already and don't execute it
+ if(p->list_test_suites) {
+ if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') {
+ queryResults.push_back(&tc);
+ testSuitesPassingFilt.insert(tc.m_test_suite);
+ p->numTestSuitesPassingFilters++;
+ }
+ continue;
+ }
+
+ // execute the test if it passes all the filtering
+ {
+ p->currentTest = &tc;
+
+ p->failure_flags = TestCaseFailureReason::None;
+ p->seconds = 0;
+
+ // reset atomic counters
+ p->numAssertsFailedCurrentTest_atomic = 0;
+ p->numAssertsCurrentTest_atomic = 0;
+
+ p->subcasesPassed.clear();
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
+
+ p->timer.start();
+
+ bool run_test = true;
+
+ do {
+ // reset some of the fields for subcases (except for the set of fully passed ones)
+ p->should_reenter = false;
+ p->subcasesCurrentMaxLevel = 0;
+ p->subcasesStack.clear();
+
+ p->shouldLogCurrentException = true;
+
+ // reset stuff for logging with INFO()
+ p->stringifiedContexts.clear();
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ try {
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method)
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable
+ FatalConditionHandler fatalConditionHandler; // Handle signals
+ // execute the test
+ tc.m_test();
+ fatalConditionHandler.reset();
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ } catch(const TestFailureException&) {
+ p->failure_flags |= TestCaseFailureReason::AssertFailure;
+ } catch(...) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception,
+ {translateActiveException(), false});
+ p->failure_flags |= TestCaseFailureReason::Exception;
+ }
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+ // exit this loop if enough assertions have failed - even if there are more subcases
+ if(p->abort_after > 0 &&
+ p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) {
+ run_test = false;
+ p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
+ }
+
+ if(p->should_reenter && run_test)
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
+ if(!p->should_reenter)
+ run_test = false;
+ } while(run_test);
+
+ p->finalizeTestCaseData();
+
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
+
+ p->currentTest = nullptr;
+
+ // stop executing tests if enough assertions have failed
+ if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after)
+ break;
+ }
+ }
+
+ if(!query_mode) {
+ DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
+ } else {
+ QueryData qdata;
+ qdata.run_stats = g_cs;
+ qdata.data = queryResults.data();
+ qdata.num_data = unsigned(queryResults.size());
+ DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
+ }
+
+ // see these issues on the reasoning for this:
+ // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
+ // - https://github.com/onqtam/doctest/issues/126
+ auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE
+ { std::cout << std::string(); };
+ DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
+
+ return cleanup_and_return();
+}
+
+IReporter::~IReporter() = default;
+
+int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
+const IContextScope* const* IReporter::get_active_contexts() {
+ return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr;
+}
+
+int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); }
+const String* IReporter::get_stringified_contexts() {
+ return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr;
+}
+
+namespace detail {
+ void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) {
+ if(isReporter)
+ getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
+ else
+ getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
+ }
+} // namespace detail
+
+} // namespace doctest
+
+#endif // DOCTEST_CONFIG_DISABLE
+
+#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182
+int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+
+DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+DOCTEST_GCC_SUPPRESS_WARNING_POP
+
+#endif // DOCTEST_LIBRARY_IMPLEMENTATION
+#endif // DOCTEST_CONFIG_IMPLEMENT
diff --git a/Client/ThirdParty/Box2D/unit-test/hello_world.cpp b/Client/ThirdParty/Box2D/unit-test/hello_world.cpp
new file mode 100644
index 0000000..eecc01a
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/hello_world.cpp
@@ -0,0 +1,112 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/box2d.h"
+#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
+#include "doctest.h"
+#include <stdio.h>
+
+// This is a simple example of building and running a simulation
+// using Box2D. Here we create a large ground box and a small dynamic
+// box.
+// There are no graphics for this example. Box2D is meant to be used
+// with your rendering engine in your game engine.
+DOCTEST_TEST_CASE("hello world")
+{
+ // Define the gravity vector.
+ b2Vec2 gravity(0.0f, -10.0f);
+
+ // Construct a world object, which will hold and simulate the rigid bodies.
+ b2World world(gravity);
+
+ // Define the ground body.
+ b2BodyDef groundBodyDef;
+ groundBodyDef.position.Set(0.0f, -10.0f);
+
+ // Call the body factory which allocates memory for the ground body
+ // from a pool and creates the ground box shape (also from a pool).
+ // The body is also added to the world.
+ b2Body* groundBody = world.CreateBody(&groundBodyDef);
+
+ // Define the ground box shape.
+ b2PolygonShape groundBox;
+
+ // The extents are the half-widths of the box.
+ groundBox.SetAsBox(50.0f, 10.0f);
+
+ // Add the ground fixture to the ground body.
+ groundBody->CreateFixture(&groundBox, 0.0f);
+
+ // Define the dynamic body. We set its position and call the body factory.
+ b2BodyDef bodyDef;
+ bodyDef.type = b2_dynamicBody;
+ bodyDef.position.Set(0.0f, 4.0f);
+ b2Body* body = world.CreateBody(&bodyDef);
+
+ // Define another box shape for our dynamic body.
+ b2PolygonShape dynamicBox;
+ dynamicBox.SetAsBox(1.0f, 1.0f);
+
+ // Define the dynamic body fixture.
+ b2FixtureDef fixtureDef;
+ fixtureDef.shape = &dynamicBox;
+
+ // Set the box density to be non-zero, so it will be dynamic.
+ fixtureDef.density = 1.0f;
+
+ // Override the default friction.
+ fixtureDef.friction = 0.3f;
+
+ // Add the shape to the body.
+ body->CreateFixture(&fixtureDef);
+
+ // Prepare for simulation. Typically we use a time step of 1/60 of a
+ // second (60Hz) and 10 iterations. This provides a high quality simulation
+ // in most game scenarios.
+ float timeStep = 1.0f / 60.0f;
+ int32 velocityIterations = 6;
+ int32 positionIterations = 2;
+
+ b2Vec2 position = body->GetPosition();
+ float angle = body->GetAngle();
+
+ // This is our little game loop.
+ for (int32 i = 0; i < 60; ++i)
+ {
+ // Instruct the world to perform a single step of simulation.
+ // It is generally best to keep the time step and iterations fixed.
+ world.Step(timeStep, velocityIterations, positionIterations);
+
+ // Now print the position and angle of the body.
+ position = body->GetPosition();
+ angle = body->GetAngle();
+
+ printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);
+ }
+
+ // When the world destructor is called, all bodies and joints are freed. This can
+ // create orphaned pointers, so be careful about your world management.
+
+ CHECK(b2Abs(position.x) < 0.01f);
+ CHECK(b2Abs(position.y - 1.01f) < 0.01f);
+ CHECK(b2Abs(angle) < 0.01f);
+}
diff --git a/Client/ThirdParty/Box2D/unit-test/joint_test.cpp b/Client/ThirdParty/Box2D/unit-test/joint_test.cpp
new file mode 100644
index 0000000..94a0880
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/joint_test.cpp
@@ -0,0 +1,106 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/box2d.h"
+#include "doctest.h"
+#include <stdio.h>
+
+DOCTEST_TEST_CASE("joint reactions")
+{
+ b2Vec2 gravity(0, -10.0f);
+ b2World world = b2World(gravity);
+
+ b2BodyDef bodyDef;
+ b2Body* ground = world.CreateBody(&bodyDef);
+
+ b2CircleShape circle;
+ circle.m_radius = 1.0f;
+
+ b2FixtureDef fixtureDef;
+
+ // Disable collision
+ fixtureDef.filter.maskBits = 0;
+ fixtureDef.density = 1.0f;
+ fixtureDef.shape = &circle;
+
+ bodyDef.type = b2_dynamicBody;
+ bodyDef.position.Set(-2.0f, 3.0f);
+
+ b2Body* bodyA = world.CreateBody(&bodyDef);
+ b2Body* bodyB = world.CreateBody(&bodyDef);
+ b2Body* bodyC = world.CreateBody(&bodyDef);
+
+ b2MassData massData;
+ circle.ComputeMass(&massData, fixtureDef.density);
+ const float mg = massData.mass * gravity.y;
+
+ bodyA->CreateFixture(&fixtureDef);
+ bodyB->CreateFixture(&fixtureDef);
+ bodyC->CreateFixture(&fixtureDef);
+
+ b2DistanceJointDef distanceJointDef;
+ distanceJointDef.Initialize(ground, bodyA, bodyDef.position + b2Vec2(0.0f, 4.0f), bodyDef.position);
+ distanceJointDef.minLength = distanceJointDef.length;
+ distanceJointDef.maxLength = distanceJointDef.length;
+
+ b2PrismaticJointDef prismaticJointDef;
+ prismaticJointDef.Initialize(ground, bodyB, bodyDef.position, b2Vec2(1.0f, 0.0f));
+
+ b2RevoluteJointDef revoluteJointDef;
+ revoluteJointDef.Initialize(ground, bodyC, bodyDef.position);
+
+ b2DistanceJoint* distanceJoint = (b2DistanceJoint*)world.CreateJoint(&distanceJointDef);
+ b2PrismaticJoint* prismaticJoint = (b2PrismaticJoint*)world.CreateJoint(&prismaticJointDef);
+ b2RevoluteJoint* revoluteJoint = (b2RevoluteJoint*)world.CreateJoint(&revoluteJointDef);
+
+ const float timeStep = 1.f / 60.f;
+ const float invTimeStep = 60.0f;
+ const int32 velocityIterations = 6;
+ const int32 positionIterations = 2;
+
+ world.Step(timeStep, velocityIterations, positionIterations);
+
+ const float tol = 1e-5f;
+ {
+ b2Vec2 F = distanceJoint->GetReactionForce(invTimeStep);
+ float T = distanceJoint->GetReactionTorque(invTimeStep);
+ CHECK(F.x == 0.0f);
+ CHECK(b2Abs(F.y + mg) < tol);
+ CHECK(T == 0.0f);
+ }
+
+ {
+ b2Vec2 F = prismaticJoint->GetReactionForce(invTimeStep);
+ float T = prismaticJoint->GetReactionTorque(invTimeStep);
+ CHECK(F.x == 0.0f);
+ CHECK(b2Abs(F.y + mg) < tol);
+ CHECK(T == 0.0f);
+ }
+
+ {
+ b2Vec2 F = revoluteJoint->GetReactionForce(invTimeStep);
+ float T = revoluteJoint->GetReactionTorque(invTimeStep);
+ CHECK(F.x == 0.0f);
+ CHECK(b2Abs(F.y + mg) < tol);
+ CHECK(T == 0.0f);
+ }
+}
diff --git a/Client/ThirdParty/Box2D/unit-test/math_test.cpp b/Client/ThirdParty/Box2D/unit-test/math_test.cpp
new file mode 100644
index 0000000..076ae58
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/math_test.cpp
@@ -0,0 +1,54 @@
+// MIT License
+
+// Copyright (c) 2020 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/box2d.h"
+#include "doctest.h"
+#include <stdio.h>
+
+DOCTEST_TEST_CASE("math test")
+{
+ SUBCASE("sweep")
+ {
+ // From issue #447
+ b2Sweep sweep;
+ sweep.localCenter.SetZero();
+ sweep.c0.Set(-2.0f, 4.0f);
+ sweep.c.Set(3.0f, 8.0f);
+ sweep.a0 = 0.5f;
+ sweep.a = 5.0f;
+ sweep.alpha0 = 0.0f;
+
+ b2Transform transform;
+
+ sweep.GetTransform(&transform, 0.0f);
+ DOCTEST_REQUIRE_EQ(transform.p.x, sweep.c0.x);
+ DOCTEST_REQUIRE_EQ(transform.p.y, sweep.c0.y);
+ DOCTEST_REQUIRE_EQ(transform.q.c, cosf(sweep.a0));
+ DOCTEST_REQUIRE_EQ(transform.q.s, sinf(sweep.a0));
+
+ sweep.GetTransform(&transform, 1.0f);
+ DOCTEST_REQUIRE_EQ(transform.p.x, sweep.c.x);
+ DOCTEST_REQUIRE_EQ(transform.p.y, sweep.c.y);
+ DOCTEST_REQUIRE_EQ(transform.q.c, cosf(sweep.a));
+ DOCTEST_REQUIRE_EQ(transform.q.s, sinf(sweep.a));
+ }
+}
diff --git a/Client/ThirdParty/Box2D/unit-test/world_test.cpp b/Client/ThirdParty/Box2D/unit-test/world_test.cpp
new file mode 100644
index 0000000..453f9f2
--- /dev/null
+++ b/Client/ThirdParty/Box2D/unit-test/world_test.cpp
@@ -0,0 +1,73 @@
+// MIT License
+
+// Copyright (c) 2019 Erin Catto
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "box2d/box2d.h"
+#include "doctest.h"
+#include <stdio.h>
+
+static bool begin_contact = false;
+
+class MyContactListener : public b2ContactListener
+{
+public:
+ void BeginContact(b2Contact* contact)
+ {
+ begin_contact = true;
+ }
+};
+
+DOCTEST_TEST_CASE("begin contact")
+{
+ b2World world = b2World(b2Vec2(0.0f, -10.0f));
+ MyContactListener listener;
+ world.SetContactListener(&listener);
+
+ b2CircleShape circle;
+ circle.m_radius = 5.f;
+
+ b2BodyDef bodyDef;
+ bodyDef.type = b2_dynamicBody;
+
+ b2Body* bodyA = world.CreateBody(&bodyDef);
+ b2Body* bodyB = world.CreateBody(&bodyDef);
+ bodyA->CreateFixture(&circle, 0.0f);
+ bodyB->CreateFixture(&circle, 0.0f);
+
+ bodyA->SetTransform(b2Vec2(0.f, 0.f), 0.f);
+ bodyB->SetTransform(b2Vec2(100.f, 0.f), 0.f);
+
+ const float timeStep = 1.f / 60.f;
+ const int32 velocityIterations = 6;
+ const int32 positionIterations = 2;
+
+ world.Step(timeStep, velocityIterations, positionIterations);
+
+ CHECK(world.GetContactList() == nullptr);
+ CHECK(begin_contact == false);
+
+ bodyB->SetTransform(b2Vec2(1.f, 0.f), 0.f);
+
+ world.Step(timeStep, velocityIterations, positionIterations);
+
+ CHECK(world.GetContactList() != nullptr);
+ CHECK(begin_contact == true);
+}
diff --git a/Client/ThirdParty/SDL2/BUGS.txt b/Client/ThirdParty/SDL2/BUGS.txt
new file mode 100644
index 0000000..b1463e7
--- /dev/null
+++ b/Client/ThirdParty/SDL2/BUGS.txt
@@ -0,0 +1,16 @@
+
+Bugs are now managed in the SDL issue tracker, here:
+
+ https://github.com/libsdl-org/SDL/issues
+
+You may report bugs there, and search to see if a given issue has already
+ been reported, discussed, and maybe even fixed.
+
+
+You may also find help at the SDL forums/mailing list:
+
+ https://discourse.libsdl.org/
+
+Bug reports are welcome here, but we really appreciate if you use the issue
+ tracker, as bugs discussed on the mailing list may be forgotten or missed.
+
diff --git a/Client/ThirdParty/SDL2/COPYING.txt b/Client/ThirdParty/SDL2/COPYING.txt
new file mode 100644
index 0000000..0e2bef3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/COPYING.txt
@@ -0,0 +1,20 @@
+
+Simple DirectMedia Layer
+Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
diff --git a/Client/ThirdParty/SDL2/README-SDL.txt b/Client/ThirdParty/SDL2/README-SDL.txt
new file mode 100644
index 0000000..8d92955
--- /dev/null
+++ b/Client/ThirdParty/SDL2/README-SDL.txt
@@ -0,0 +1,13 @@
+
+Please distribute this file with the SDL runtime environment:
+
+The Simple DirectMedia Layer (SDL for short) is a cross-platform library
+designed to make it easy to write multi-media software, such as games
+and emulators.
+
+The Simple DirectMedia Layer library source code is available from:
+https://www.libsdl.org/
+
+This library is distributed under the terms of the zlib license:
+http://www.zlib.net/zlib_license.html
+
diff --git a/Client/ThirdParty/SDL2/README.txt b/Client/ThirdParty/SDL2/README.txt
new file mode 100644
index 0000000..431ba0e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/README.txt
@@ -0,0 +1,21 @@
+
+ Simple DirectMedia Layer
+
+ (SDL)
+
+ Version 2.0
+
+---
+https://www.libsdl.org/
+
+Simple DirectMedia Layer is a cross-platform development library designed
+to provide low level access to audio, keyboard, mouse, joystick, and graphics
+hardware via OpenGL and Direct3D. It is used by video playback software,
+emulators, and popular games including Valve's award winning catalog
+and many Humble Bundle games.
+
+More extensive documentation is available in the docs directory, starting
+with README.md
+
+Enjoy!
+ Sam Lantinga (slouken@libsdl.org)
diff --git a/Client/ThirdParty/SDL2/SDL.h b/Client/ThirdParty/SDL2/SDL.h
new file mode 100644
index 0000000..222a8bd
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL.h
@@ -0,0 +1,221 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL.h
+ *
+ * Main include header for the SDL library
+ */
+
+
+#ifndef SDL_h_
+#define SDL_h_
+
+#include "SDL_main.h"
+#include "SDL_stdinc.h"
+#include "SDL_assert.h"
+#include "SDL_atomic.h"
+#include "SDL_audio.h"
+#include "SDL_clipboard.h"
+#include "SDL_cpuinfo.h"
+#include "SDL_endian.h"
+#include "SDL_error.h"
+#include "SDL_events.h"
+#include "SDL_filesystem.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_haptic.h"
+#include "SDL_hints.h"
+#include "SDL_joystick.h"
+#include "SDL_loadso.h"
+#include "SDL_log.h"
+#include "SDL_messagebox.h"
+#include "SDL_metal.h"
+#include "SDL_mutex.h"
+#include "SDL_power.h"
+#include "SDL_render.h"
+#include "SDL_rwops.h"
+#include "SDL_sensor.h"
+#include "SDL_shape.h"
+#include "SDL_system.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_version.h"
+#include "SDL_video.h"
+#include "SDL_locale.h"
+#include "SDL_misc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* As of version 0.5, SDL is loaded dynamically into the application */
+
+/**
+ * \name SDL_INIT_*
+ *
+ * These are the flags which may be passed to SDL_Init(). You should
+ * specify the subsystems which you will be using in your application.
+ */
+/* @{ */
+#define SDL_INIT_TIMER 0x00000001u
+#define SDL_INIT_AUDIO 0x00000010u
+#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK 0x00000200u /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
+#define SDL_INIT_HAPTIC 0x00001000u
+#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS 0x00004000u
+#define SDL_INIT_SENSOR 0x00008000u
+#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */
+#define SDL_INIT_EVERYTHING ( \
+ SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
+ SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \
+ )
+/* @} */
+
+/**
+ * Initialize the SDL library.
+ *
+ * SDL_Init() simply forwards to calling SDL_InitSubSystem(). Therefore, the
+ * two may be used interchangeably. Though for readability of your code
+ * SDL_InitSubSystem() might be preferred.
+ *
+ * The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread)
+ * subsystems are initialized by default. Message boxes
+ * (SDL_ShowSimpleMessageBox) also attempt to work without initializing the
+ * video subsystem, in hopes of being useful in showing an error dialog when
+ * SDL_Init fails. You must specifically initialize other subsystems if you
+ * use them in your application.
+ *
+ * Logging (such as SDL_Log) works without initialization, too.
+ *
+ * `flags` may be any of the following OR'd together:
+ *
+ * - `SDL_INIT_TIMER`: timer subsystem
+ * - `SDL_INIT_AUDIO`: audio subsystem
+ * - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events
+ * subsystem
+ * - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the
+ * events subsystem
+ * - `SDL_INIT_HAPTIC`: haptic (force feedback) subsystem
+ * - `SDL_INIT_GAMECONTROLLER`: controller subsystem; automatically
+ * initializes the joystick subsystem
+ * - `SDL_INIT_EVENTS`: events subsystem
+ * - `SDL_INIT_EVERYTHING`: all of the above subsystems
+ * - `SDL_INIT_NOPARACHUTE`: compatibility; this flag is ignored
+ *
+ * Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem()
+ * for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or
+ * call SDL_Quit() to force shutdown). If a subsystem is already loaded then
+ * this call will increase the ref-count and return.
+ *
+ * \param flags subsystem initialization flags
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_InitSubSystem
+ * \sa SDL_Quit
+ * \sa SDL_SetMainReady
+ * \sa SDL_WasInit
+ */
+extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
+
+/**
+ * Compatibility function to initialize the SDL library.
+ *
+ * In SDL2, this function and SDL_Init() are interchangeable.
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_Init
+ * \sa SDL_Quit
+ * \sa SDL_QuitSubSystem
+ */
+extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags);
+
+/**
+ * Shut down specific SDL subsystems.
+ *
+ * If you start a subsystem using a call to that subsystem's init function
+ * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
+ * SDL_QuitSubSystem() and SDL_WasInit() will not work. You will need to use
+ * that subsystem's quit function (SDL_VideoQuit()) directly instead. But
+ * generally, you should not be using those functions directly anyhow; use
+ * SDL_Init() instead.
+ *
+ * You still need to call SDL_Quit() even if you close all open subsystems
+ * with SDL_QuitSubSystem().
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ *
+ * \sa SDL_InitSubSystem
+ * \sa SDL_Quit
+ */
+extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags);
+
+/**
+ * Get a mask of the specified subsystems which are currently initialized.
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ * \returns a mask of all initialized subsystems if `flags` is 0, otherwise it
+ * returns the initialization status of the specified subsystems.
+ *
+ * The return value does not include SDL_INIT_NOPARACHUTE.
+ *
+ * \sa SDL_Init
+ * \sa SDL_InitSubSystem
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags);
+
+/**
+ * Clean up all initialized subsystems.
+ *
+ * You should call this function even if you have already shutdown each
+ * initialized subsystem with SDL_QuitSubSystem(). It is safe to call this
+ * function even in the case of errors in initialization.
+ *
+ * If you start a subsystem using a call to that subsystem's init function
+ * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
+ * then you must use that subsystem's quit function (SDL_VideoQuit()) to shut
+ * it down before calling SDL_Quit(). But generally, you should not be using
+ * those functions directly anyhow; use SDL_Init() instead.
+ *
+ * You can use this function with atexit() to ensure that it is run when your
+ * application is shutdown, but it is not wise to do this from a library or
+ * other dynamically loaded code.
+ *
+ * \sa SDL_Init
+ * \sa SDL_QuitSubSystem
+ */
+extern DECLSPEC void SDLCALL SDL_Quit(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_assert.h b/Client/ThirdParty/SDL2/SDL_assert.h
new file mode 100644
index 0000000..a627b17
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_assert.h
@@ -0,0 +1,318 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_assert_h_
+#define SDL_assert_h_
+
+#include "SDL_config.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SDL_ASSERT_LEVEL
+#ifdef SDL_DEFAULT_ASSERT_LEVEL
+#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
+#elif defined(_DEBUG) || defined(DEBUG) || \
+ (defined(__GNUC__) && !defined(__OPTIMIZE__))
+#define SDL_ASSERT_LEVEL 2
+#else
+#define SDL_ASSERT_LEVEL 1
+#endif
+#endif /* SDL_ASSERT_LEVEL */
+
+/*
+These are macros and not first class functions so that the debugger breaks
+on the assertion line and not in some random guts of SDL, and so each
+assert can have unique static variables associated with it.
+*/
+
+#if defined(_MSC_VER)
+/* Don't include intrin.h here because it contains C++ code */
+ extern void __cdecl __debugbreak(void);
+ #define SDL_TriggerBreakpoint() __debugbreak()
+#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
+#elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
+#elif defined(__APPLE__) && defined(__arm__)
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" )
+#elif defined(__386__) && defined(__WATCOMC__)
+ #define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
+#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
+ #include <signal.h>
+ #define SDL_TriggerBreakpoint() raise(SIGTRAP)
+#else
+ /* How do we trigger breakpoints on this platform? */
+ #define SDL_TriggerBreakpoint()
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
+# define SDL_FUNCTION __func__
+#elif ((__GNUC__ >= 2) || defined(_MSC_VER) || defined (__WATCOMC__))
+# define SDL_FUNCTION __FUNCTION__
+#else
+# define SDL_FUNCTION "???"
+#endif
+#define SDL_FILE __FILE__
+#define SDL_LINE __LINE__
+
+/*
+sizeof (x) makes the compiler still parse the expression even without
+assertions enabled, so the code is always checked at compile time, but
+doesn't actually generate code for it, so there are no side effects or
+expensive checks at run time, just the constant size of what x WOULD be,
+which presumably gets optimized out as unused.
+This also solves the problem of...
+
+ int somevalue = blah();
+ SDL_assert(somevalue == 1);
+
+...which would cause compiles to complain that somevalue is unused if we
+disable assertions.
+*/
+
+/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking
+ this condition isn't constant. And looks like an owl's face! */
+#ifdef _MSC_VER /* stupid /W4 warnings. */
+#define SDL_NULL_WHILE_LOOP_CONDITION (0,0)
+#else
+#define SDL_NULL_WHILE_LOOP_CONDITION (0)
+#endif
+
+#define SDL_disabled_assert(condition) \
+ do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+typedef enum
+{
+ SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */
+ SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */
+ SDL_ASSERTION_ABORT, /**< Terminate the program. */
+ SDL_ASSERTION_IGNORE, /**< Ignore the assert. */
+ SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */
+} SDL_AssertState;
+
+typedef struct SDL_AssertData
+{
+ int always_ignore;
+ unsigned int trigger_count;
+ const char *condition;
+ const char *filename;
+ int linenum;
+ const char *function;
+ const struct SDL_AssertData *next;
+} SDL_AssertData;
+
+#if (SDL_ASSERT_LEVEL > 0)
+
+/* Never call this directly. Use the SDL_assert* macros. */
+extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
+ const char *,
+ const char *, int)
+#if defined(__clang__)
+#if __has_feature(attribute_analyzer_noreturn)
+/* this tells Clang's static analysis that we're a custom assert function,
+ and that the analyzer should assume the condition was always true past this
+ SDL_assert test. */
+ __attribute__((analyzer_noreturn))
+#endif
+#endif
+;
+
+/* the do {} while(0) avoids dangling else problems:
+ if (x) SDL_assert(y); else blah();
+ ... without the do/while, the "else" could attach to this macro's "if".
+ We try to handle just the minimum we need here in a macro...the loop,
+ the static vars, and break points. The heavy lifting is handled in
+ SDL_ReportAssertion(), in SDL_assert.c.
+*/
+#define SDL_enabled_assert(condition) \
+ do { \
+ while ( !(condition) ) { \
+ static struct SDL_AssertData sdl_assert_data = { \
+ 0, 0, #condition, 0, 0, 0, 0 \
+ }; \
+ const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
+ if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
+ continue; /* go again. */ \
+ } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
+ SDL_TriggerBreakpoint(); \
+ } \
+ break; /* not retrying. */ \
+ } \
+ } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+#endif /* enabled assertions support code */
+
+/* Enable various levels of assertions. */
+#if SDL_ASSERT_LEVEL == 0 /* assertions disabled */
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_disabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 1 /* release settings. */
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 2 /* normal settings. */
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
+#else
+# error Unknown assertion level.
+#endif
+
+/* this assertion is never disabled at any level. */
+#define SDL_assert_always(condition) SDL_enabled_assert(condition)
+
+
+/**
+ * A callback that fires when an SDL assertion fails.
+ *
+ * \param data a pointer to the SDL_AssertData structure corresponding to the
+ * current assertion
+ * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler()
+ * \returns an SDL_AssertState value indicating how to handle the failure.
+ */
+typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
+ const SDL_AssertData* data, void* userdata);
+
+/**
+ * Set an application-defined assertion handler.
+ *
+ * This function allows an application to show its own assertion UI and/or
+ * force the response to an assertion failure. If the application doesn't
+ * provide this, SDL will try to do the right thing, popping up a
+ * system-specific GUI dialog, and probably minimizing any fullscreen windows.
+ *
+ * This callback may fire from any thread, but it runs wrapped in a mutex, so
+ * it will only fire from one thread at a time.
+ *
+ * This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
+ *
+ * \param handler the SDL_AssertionHandler function to call when an assertion
+ * fails or NULL for the default handler
+ * \param userdata a pointer that is passed to `handler`
+ *
+ * \sa SDL_GetAssertionHandler
+ */
+extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
+ SDL_AssertionHandler handler,
+ void *userdata);
+
+/**
+ * Get the default assertion handler.
+ *
+ * This returns the function pointer that is called by default when an
+ * assertion is triggered. This is an internal function provided by SDL, that
+ * is used for assertions when SDL_SetAssertionHandler() hasn't been used to
+ * provide a different function.
+ *
+ * \returns the default SDL_AssertionHandler that is called when an assert
+ * triggers.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GetAssertionHandler
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
+
+/**
+ * Get the current assertion handler.
+ *
+ * This returns the function pointer that is called when an assertion is
+ * triggered. This is either the value last passed to
+ * SDL_SetAssertionHandler(), or if no application-specified function is set,
+ * is equivalent to calling SDL_GetDefaultAssertionHandler().
+ *
+ * The parameter `puserdata` is a pointer to a void*, which will store the
+ * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value
+ * will always be NULL for the default handler. If you don't care about this
+ * data, it is safe to pass a NULL pointer to this function to ignore it.
+ *
+ * \param puserdata pointer which is filled with the "userdata" pointer that
+ * was passed to SDL_SetAssertionHandler()
+ * \returns the SDL_AssertionHandler that is called when an assert triggers.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_SetAssertionHandler
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
+
+/**
+ * Get a list of all assertion failures.
+ *
+ * This function gets all assertions triggered since the last call to
+ * SDL_ResetAssertionReport(), or the start of the program.
+ *
+ * The proper way to examine this data looks something like this:
+ *
+ * ```c
+ * const SDL_AssertData *item = SDL_GetAssertionReport();
+ * while (item) {
+ * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n",
+ * item->condition, item->function, item->filename,
+ * item->linenum, item->trigger_count,
+ * item->always_ignore ? "yes" : "no");
+ * item = item->next;
+ * }
+ * ```
+ *
+ * \returns a list of all failed assertions or NULL if the list is empty. This
+ * memory should not be modified or freed by the application.
+ *
+ * \sa SDL_ResetAssertionReport
+ */
+extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
+
+/**
+ * Clear the list of all assertion failures.
+ *
+ * This function will clear the list of all assertions triggered up to that
+ * point. Immediately following this call, SDL_GetAssertionReport will return
+ * no items. In addition, any previously-triggered assertions will be reset to
+ * a trigger_count of zero, and their always_ignore state will be false.
+ *
+ * \sa SDL_GetAssertionReport
+ */
+extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
+
+
+/* these had wrong naming conventions until 2.0.4. Please update your app! */
+#define SDL_assert_state SDL_AssertState
+#define SDL_assert_data SDL_AssertData
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_assert_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_atomic.h b/Client/ThirdParty/SDL2/SDL_atomic.h
new file mode 100644
index 0000000..5e1eae7
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_atomic.h
@@ -0,0 +1,379 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_atomic.h
+ *
+ * Atomic operations.
+ *
+ * IMPORTANT:
+ * If you are not an expert in concurrent lockless programming, you should
+ * only be using the atomic lock and reference counting functions in this
+ * file. In all other cases you should be protecting your data structures
+ * with full mutexes.
+ *
+ * The list of "safe" functions to use are:
+ * SDL_AtomicLock()
+ * SDL_AtomicUnlock()
+ * SDL_AtomicIncRef()
+ * SDL_AtomicDecRef()
+ *
+ * Seriously, here be dragons!
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * You can find out a little more about lockless programming and the
+ * subtle issues that can arise here:
+ * http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx
+ *
+ * There's also lots of good information here:
+ * http://www.1024cores.net/home/lock-free-algorithms
+ * http://preshing.com/
+ *
+ * These operations may or may not actually be implemented using
+ * processor specific atomic operations. When possible they are
+ * implemented as true processor specific atomic operations. When that
+ * is not possible the are implemented using locks that *do* use the
+ * available atomic operations.
+ *
+ * All of the atomic operations that modify memory are full memory barriers.
+ */
+
+#ifndef SDL_atomic_h_
+#define SDL_atomic_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_platform.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SDL AtomicLock
+ *
+ * The atomic locks are efficient spinlocks using CPU instructions,
+ * but are vulnerable to starvation and can spin forever if a thread
+ * holding a lock has been terminated. For this reason you should
+ * minimize the code executed inside an atomic lock and never do
+ * expensive things like API or system calls while holding them.
+ *
+ * The atomic locks are not safe to lock recursively.
+ *
+ * Porting Note:
+ * The spin lock functions and type are required and can not be
+ * emulated because they are used in the atomic emulation code.
+ */
+/* @{ */
+
+typedef int SDL_SpinLock;
+
+/**
+ * Try to lock a spin lock by setting it to a non-zero value.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ * \returns SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already
+ * held.
+ *
+ * \sa SDL_AtomicLock
+ * \sa SDL_AtomicUnlock
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
+
+/**
+ * Lock a spin lock by setting it to a non-zero value.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ *
+ * \sa SDL_AtomicTryLock
+ * \sa SDL_AtomicUnlock
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
+
+/**
+ * Unlock a spin lock by setting it to 0.
+ *
+ * Always returns immediately.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicLock
+ * \sa SDL_AtomicTryLock
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
+
+/* @} *//* SDL AtomicLock */
+
+
+/**
+ * The compiler barrier prevents the compiler from reordering
+ * reads and writes to globally visible variables across the call.
+ */
+#if defined(_MSC_VER) && (_MSC_VER > 1200) && !defined(__clang__)
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define SDL_CompilerBarrier() _ReadWriteBarrier()
+#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
+#define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
+#elif defined(__WATCOMC__)
+extern _inline void SDL_CompilerBarrier (void);
+#pragma aux SDL_CompilerBarrier = "" parm [] modify exact [];
+#else
+#define SDL_CompilerBarrier() \
+{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
+#endif
+
+/**
+ * Memory barriers are designed to prevent reads and writes from being
+ * reordered by the compiler and being seen out of order on multi-core CPUs.
+ *
+ * A typical pattern would be for thread A to write some data and a flag, and
+ * for thread B to read the flag and get the data. In this case you would
+ * insert a release barrier between writing the data and the flag,
+ * guaranteeing that the data write completes no later than the flag is
+ * written, and you would insert an acquire barrier between reading the flag
+ * and reading the data, to ensure that all the reads associated with the flag
+ * have completed.
+ *
+ * In this pattern you should always see a release barrier paired with an
+ * acquire barrier and you should gate the data reads/writes with a single
+ * flag variable.
+ *
+ * For more information on these semantics, take a look at the blog post:
+ * http://preshing.com/20120913/acquire-and-release-semantics
+ */
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierReleaseFunction(void);
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
+
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
+#elif defined(__GNUC__) && defined(__aarch64__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__GNUC__) && defined(__arm__)
+#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */
+/* Information from:
+ https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19
+
+ The Linux kernel provides a helper function which provides the right code for a memory barrier,
+ hard-coded at address 0xffff0fa0
+*/
+typedef void (*SDL_KernelMemoryBarrierFunc)();
+#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#elif 0 /* defined(__QNXNTO__) */
+#include <sys/cpuinline.h>
+
+#define SDL_MemoryBarrierRelease() __cpu_membarrier()
+#define SDL_MemoryBarrierAcquire() __cpu_membarrier()
+#else
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__)
+#ifdef __thumb__
+/* The mcr instruction isn't available in thumb mode, use real functions */
+#define SDL_MEMORY_BARRIER_USES_FUNCTION
+#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction()
+#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction()
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#endif /* __thumb__ */
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
+#endif /* __LINUX__ || __ANDROID__ */
+#endif /* __GNUC__ && __arm__ */
+#else
+#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
+#include <mbarrier.h>
+#define SDL_MemoryBarrierRelease() __machine_rel_barrier()
+#define SDL_MemoryBarrierAcquire() __machine_acq_barrier()
+#else
+/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
+#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
+#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
+#endif
+#endif
+
+/**
+ * \brief A type representing an atomic integer value. It is a struct
+ * so people don't accidentally use numeric operations on it.
+ */
+typedef struct { int value; } SDL_atomic_t;
+
+/**
+ * Set an atomic variable to a new value if it is currently an old value.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param oldval the old value
+ * \param newval the new value
+ * \returns SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicGet
+ * \sa SDL_AtomicSet
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
+
+/**
+ * Set an atomic variable to a value.
+ *
+ * This function also acts as a full memory barrier.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param v the desired value
+ * \returns the previous value of the atomic variable.
+ *
+ * \sa SDL_AtomicGet
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int v);
+
+/**
+ * Get the value of an atomic variable.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable
+ * \returns the current value of an atomic variable.
+ *
+ * \sa SDL_AtomicSet
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a);
+
+/**
+ * Add to an atomic variable.
+ *
+ * This function also acts as a full memory barrier.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param v the desired value to add
+ * \returns the previous value of the atomic variable.
+ *
+ * \sa SDL_AtomicDecRef
+ * \sa SDL_AtomicIncRef
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int v);
+
+/**
+ * \brief Increment an atomic variable used as a reference count.
+ */
+#ifndef SDL_AtomicIncRef
+#define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
+#endif
+
+/**
+ * \brief Decrement an atomic variable used as a reference count.
+ *
+ * \return SDL_TRUE if the variable reached zero after decrementing,
+ * SDL_FALSE otherwise
+ */
+#ifndef SDL_AtomicDecRef
+#define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
+#endif
+
+/**
+ * Set a pointer to a new value if it is currently an old value.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \param oldval the old pointer value
+ * \param newval the new pointer value
+ * \returns SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicCAS
+ * \sa SDL_AtomicGetPtr
+ * \sa SDL_AtomicSetPtr
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
+
+/**
+ * Set a pointer to a value atomically.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \param v the desired pointer value
+ * \returns the previous value of the pointer.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicGetPtr
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v);
+
+/**
+ * Get the value of a pointer atomically.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \returns the current value of a pointer.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicSetPtr
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#include "close_code.h"
+
+#endif /* SDL_atomic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_audio.h b/Client/ThirdParty/SDL2/SDL_audio.h
new file mode 100644
index 0000000..0aa0017
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_audio.h
@@ -0,0 +1,1185 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* !!! FIXME: several functions in here need Doxygen comments. */
+
+/**
+ * \file SDL_audio.h
+ *
+ * Access to the raw audio mixing buffer for the SDL library.
+ */
+
+#ifndef SDL_audio_h_
+#define SDL_audio_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_endian.h"
+#include "SDL_mutex.h"
+#include "SDL_thread.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Audio format flags.
+ *
+ * These are what the 16 bits in SDL_AudioFormat currently mean...
+ * (Unspecified bits are always zero).
+ *
+ * \verbatim
+ ++-----------------------sample is signed if set
+ ||
+ || ++-----------sample is bigendian if set
+ || ||
+ || || ++---sample is float if set
+ || || ||
+ || || || +---sample bit size---+
+ || || || | |
+ 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+ \endverbatim
+ *
+ * There are macros in SDL 2.0 and later to query these bits.
+ */
+typedef Uint16 SDL_AudioFormat;
+
+/**
+ * \name Audio flags
+ */
+/* @{ */
+
+#define SDL_AUDIO_MASK_BITSIZE (0xFF)
+#define SDL_AUDIO_MASK_DATATYPE (1<<8)
+#define SDL_AUDIO_MASK_ENDIAN (1<<12)
+#define SDL_AUDIO_MASK_SIGNED (1<<15)
+#define SDL_AUDIO_BITSIZE(x) (x & SDL_AUDIO_MASK_BITSIZE)
+#define SDL_AUDIO_ISFLOAT(x) (x & SDL_AUDIO_MASK_DATATYPE)
+#define SDL_AUDIO_ISBIGENDIAN(x) (x & SDL_AUDIO_MASK_ENDIAN)
+#define SDL_AUDIO_ISSIGNED(x) (x & SDL_AUDIO_MASK_SIGNED)
+#define SDL_AUDIO_ISINT(x) (!SDL_AUDIO_ISFLOAT(x))
+#define SDL_AUDIO_ISLITTLEENDIAN(x) (!SDL_AUDIO_ISBIGENDIAN(x))
+#define SDL_AUDIO_ISUNSIGNED(x) (!SDL_AUDIO_ISSIGNED(x))
+
+/**
+ * \name Audio format flags
+ *
+ * Defaults to LSB byte order.
+ */
+/* @{ */
+#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */
+#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */
+#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */
+#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */
+#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */
+#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */
+#define AUDIO_U16 AUDIO_U16LSB
+#define AUDIO_S16 AUDIO_S16LSB
+/* @} */
+
+/**
+ * \name int32 support
+ */
+/* @{ */
+#define AUDIO_S32LSB 0x8020 /**< 32-bit integer samples */
+#define AUDIO_S32MSB 0x9020 /**< As above, but big-endian byte order */
+#define AUDIO_S32 AUDIO_S32LSB
+/* @} */
+
+/**
+ * \name float32 support
+ */
+/* @{ */
+#define AUDIO_F32LSB 0x8120 /**< 32-bit floating point samples */
+#define AUDIO_F32MSB 0x9120 /**< As above, but big-endian byte order */
+#define AUDIO_F32 AUDIO_F32LSB
+/* @} */
+
+/**
+ * \name Native audio byte ordering
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define AUDIO_U16SYS AUDIO_U16LSB
+#define AUDIO_S16SYS AUDIO_S16LSB
+#define AUDIO_S32SYS AUDIO_S32LSB
+#define AUDIO_F32SYS AUDIO_F32LSB
+#else
+#define AUDIO_U16SYS AUDIO_U16MSB
+#define AUDIO_S16SYS AUDIO_S16MSB
+#define AUDIO_S32SYS AUDIO_S32MSB
+#define AUDIO_F32SYS AUDIO_F32MSB
+#endif
+/* @} */
+
+/**
+ * \name Allow change flags
+ *
+ * Which audio format changes are allowed when opening a device.
+ */
+/* @{ */
+#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
+#define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
+#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
+#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0x00000008
+#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)
+/* @} */
+
+/* @} *//* Audio flags */
+
+/**
+ * This function is called when the audio device needs more data.
+ *
+ * \param userdata An application-specific parameter saved in
+ * the SDL_AudioSpec structure
+ * \param stream A pointer to the audio data buffer.
+ * \param len The length of that buffer in bytes.
+ *
+ * Once the callback returns, the buffer will no longer be valid.
+ * Stereo samples are stored in a LRLRLR ordering.
+ *
+ * You can choose to avoid callbacks and use SDL_QueueAudio() instead, if
+ * you like. Just open your audio device with a NULL callback.
+ */
+typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
+ int len);
+
+/**
+ * The calculated values in this structure are calculated by SDL_OpenAudio().
+ *
+ * For multi-channel audio, the default SDL channel mapping is:
+ * 2: FL FR (stereo)
+ * 3: FL FR LFE (2.1 surround)
+ * 4: FL FR BL BR (quad)
+ * 5: FL FR FC BL BR (quad + center)
+ * 6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR)
+ * 7: FL FR FC LFE BC SL SR (6.1 surround)
+ * 8: FL FR FC LFE BL BR SL SR (7.1 surround)
+ */
+typedef struct SDL_AudioSpec
+{
+ int freq; /**< DSP frequency -- samples per second */
+ SDL_AudioFormat format; /**< Audio data format */
+ Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */
+ Uint8 silence; /**< Audio buffer silence value (calculated) */
+ Uint16 samples; /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
+ Uint16 padding; /**< Necessary for some compile environments */
+ Uint32 size; /**< Audio buffer size in bytes (calculated) */
+ SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
+ void *userdata; /**< Userdata passed to callback (ignored for NULL callbacks). */
+} SDL_AudioSpec;
+
+
+struct SDL_AudioCVT;
+typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
+ SDL_AudioFormat format);
+
+/**
+ * \brief Upper limit of filters in SDL_AudioCVT
+ *
+ * The maximum number of SDL_AudioFilter functions in SDL_AudioCVT is
+ * currently limited to 9. The SDL_AudioCVT.filters array has 10 pointers,
+ * one of which is the terminating NULL pointer.
+ */
+#define SDL_AUDIOCVT_MAX_FILTERS 9
+
+/**
+ * \struct SDL_AudioCVT
+ * \brief A structure to hold a set of audio conversion filters and buffers.
+ *
+ * Note that various parts of the conversion pipeline can take advantage
+ * of SIMD operations (like SSE2, for example). SDL_AudioCVT doesn't require
+ * you to pass it aligned data, but can possibly run much faster if you
+ * set both its (buf) field to a pointer that is aligned to 16 bytes, and its
+ * (len) field to something that's a multiple of 16, if possible.
+ */
+#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__)
+/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
+ pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+ This is not a concern on CHERI architectures, where pointers must be stored
+ at aligned locations otherwise they will become invalid, and thus structs
+ containing pointers cannot be packed without giving a warning or error.
+ vvv
+ The next time we rev the ABI, make sure to size the ints and add padding.
+*/
+#define SDL_AUDIOCVT_PACKED __attribute__((packed))
+#else
+#define SDL_AUDIOCVT_PACKED
+#endif
+/* */
+typedef struct SDL_AudioCVT
+{
+ int needed; /**< Set to 1 if conversion possible */
+ SDL_AudioFormat src_format; /**< Source audio format */
+ SDL_AudioFormat dst_format; /**< Target audio format */
+ double rate_incr; /**< Rate conversion increment */
+ Uint8 *buf; /**< Buffer to hold entire audio data */
+ int len; /**< Length of original audio buffer */
+ int len_cvt; /**< Length of converted audio buffer */
+ int len_mult; /**< buffer must be len*len_mult big */
+ double len_ratio; /**< Given len, final size is len*len_ratio */
+ SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */
+ int filter_index; /**< Current audio conversion function */
+} SDL_AUDIOCVT_PACKED SDL_AudioCVT;
+
+
+/* Function prototypes */
+
+/**
+ * \name Driver discovery functions
+ *
+ * These functions return the list of built in audio drivers, in the
+ * order that they are normally initialized by default.
+ */
+/* @{ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
+/* @} */
+
+/**
+ * \name Initialization and cleanup
+ *
+ * \internal These functions are used internally, and should not be used unless
+ * you have a specific need to specify the audio driver you want to
+ * use. You should normally use SDL_Init() or SDL_InitSubSystem().
+ */
+/* @{ */
+extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name);
+extern DECLSPEC void SDLCALL SDL_AudioQuit(void);
+/* @} */
+
+/**
+ * Get the name of the current audio driver.
+ *
+ * The returned string points to internal static memory and thus never becomes
+ * invalid, even if you quit the audio subsystem and initialize a new driver
+ * (although such a case would return a different static string from another
+ * call to this function, of course). As such, you should not modify or free
+ * the returned string.
+ *
+ * \returns the name of the current audio driver or NULL if no driver has been
+ * initialized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AudioInit
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
+
+/**
+ * This function is a legacy means of opening the audio device.
+ *
+ * This function remains for compatibility with SDL 1.2, but also because it's
+ * slightly easier to use than the new functions in SDL 2.0. The new, more
+ * powerful, and preferred way to do this is SDL_OpenAudioDevice().
+ *
+ * This function is roughly equivalent to:
+ *
+ * ```c++
+ * SDL_OpenAudioDevice(NULL, 0, desired, obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
+ * ```
+ *
+ * With two notable exceptions:
+ *
+ * - If `obtained` is NULL, we use `desired` (and allow no changes), which
+ * means desired will be modified to have the correct values for silence,
+ * etc, and SDL will convert any differences between your app's specific
+ * request and the hardware behind the scenes.
+ * - The return value is always success or failure, and not a device ID, which
+ * means you can only have one device open at a time with this function.
+ *
+ * \param desired an SDL_AudioSpec structure representing the desired output
+ * format. Please refer to the SDL_OpenAudioDevice
+ * documentation for details on how to prepare this structure.
+ * \param obtained an SDL_AudioSpec structure filled in with the actual
+ * parameters, or NULL.
+ * \returns 0 if successful, placing the actual hardware parameters in the
+ * structure pointed to by `obtained`.
+ *
+ * If `obtained` is NULL, the audio data passed to the callback
+ * function will be guaranteed to be in the requested format, and
+ * will be automatically converted to the actual hardware audio
+ * format if necessary. If `obtained` is NULL, `desired` will have
+ * fields modified.
+ *
+ * This function returns a negative error code on failure to open the
+ * audio device or failure to set up the audio thread; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CloseAudio
+ * \sa SDL_LockAudio
+ * \sa SDL_PauseAudio
+ * \sa SDL_UnlockAudio
+ */
+extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
+ SDL_AudioSpec * obtained);
+
+/**
+ * SDL Audio Device IDs.
+ *
+ * A successful call to SDL_OpenAudio() is always device id 1, and legacy
+ * SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls
+ * always returns devices >= 2 on success. The legacy calls are good both
+ * for backwards compatibility and when you don't care about multiple,
+ * specific, or capture devices.
+ */
+typedef Uint32 SDL_AudioDeviceID;
+
+/**
+ * Get the number of built-in audio devices.
+ *
+ * This function is only valid after successfully initializing the audio
+ * subsystem.
+ *
+ * Note that audio capture support is not implemented as of SDL 2.0.4, so the
+ * `iscapture` parameter is for future expansion and should always be zero for
+ * now.
+ *
+ * This function will return -1 if an explicit list of devices can't be
+ * determined. Returning -1 is not an error. For example, if SDL is set up to
+ * talk to a remote audio server, it can't list every one available on the
+ * Internet, but it will still allow a specific host to be specified in
+ * SDL_OpenAudioDevice().
+ *
+ * In many common cases, when this function returns a value <= 0, it can still
+ * successfully open the default device (NULL for first argument of
+ * SDL_OpenAudioDevice()).
+ *
+ * This function may trigger a complete redetect of available hardware. It
+ * should not be called for each iteration of a loop, but rather once at the
+ * start of a loop:
+ *
+ * ```c++
+ * // Don't do this:
+ * for (int i = 0; i < SDL_GetNumAudioDevices(0); i++)
+ *
+ * // do this instead:
+ * const int count = SDL_GetNumAudioDevices(0);
+ * for (int i = 0; i < count; ++i) { do_something_here(); }
+ * ```
+ *
+ * \param iscapture zero to request playback devices, non-zero to request
+ * recording devices
+ * \returns the number of available devices exposed by the current driver or
+ * -1 if an explicit list of devices can't be determined. A return
+ * value of -1 does not necessarily mean an error condition.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture);
+
+/**
+ * Get the human-readable name of a specific audio device.
+ *
+ * This function is only valid after successfully initializing the audio
+ * subsystem. The values returned by this function reflect the latest call to
+ * SDL_GetNumAudioDevices(); re-call that function to redetect available
+ * hardware.
+ *
+ * The string returned by this function is UTF-8 encoded, read-only, and
+ * managed internally. You are not to free it. If you need to keep the string
+ * for any length of time, you should make your own copy of it, as it will be
+ * invalid next time any of several other SDL functions are called.
+ *
+ * \param index the index of the audio device; valid values range from 0 to
+ * SDL_GetNumAudioDevices() - 1
+ * \param iscapture non-zero to query the list of recording devices, zero to
+ * query the list of output devices.
+ * \returns the name of the audio device at the requested index, or NULL on
+ * error.
+ *
+ * \sa SDL_GetNumAudioDevices
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index,
+ int iscapture);
+
+/**
+ * Get the preferred audio format of a specific audio device.
+ *
+ * This function is only valid after a successfully initializing the audio
+ * subsystem. The values returned by this function reflect the latest call to
+ * SDL_GetNumAudioDevices(); re-call that function to redetect available
+ * hardware.
+ *
+ * `spec` will be filled with the sample rate, sample format, and channel
+ * count. All other values in the structure are filled with 0. When the
+ * supported struct members are 0, SDL was unable to get the property from the
+ * backend.
+ *
+ * \param index the index of the audio device; valid values range from 0 to
+ * SDL_GetNumAudioDevices() - 1
+ * \param iscapture non-zero to query the list of recording devices, zero to
+ * query the list of output devices.
+ * \param spec The SDL_AudioSpec to be initialized by this function.
+ * \returns 0 on success, nonzero on error
+ *
+ * \sa SDL_GetNumAudioDevices
+ */
+extern DECLSPEC int SDLCALL SDL_GetAudioDeviceSpec(int index,
+ int iscapture,
+ SDL_AudioSpec *spec);
+
+
+/**
+ * Open a specific audio device.
+ *
+ * SDL_OpenAudio(), unlike this function, always acts on device ID 1. As such,
+ * this function will never return a 1 so as not to conflict with the legacy
+ * function.
+ *
+ * Please note that SDL 2.0 before 2.0.5 did not support recording; as such,
+ * this function would fail if `iscapture` was not zero. Starting with SDL
+ * 2.0.5, recording is implemented and this value can be non-zero.
+ *
+ * Passing in a `device` name of NULL requests the most reasonable default
+ * (and is equivalent to what SDL_OpenAudio() does to choose a device). The
+ * `device` name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but
+ * some drivers allow arbitrary and driver-specific strings, such as a
+ * hostname/IP address for a remote audio server, or a filename in the
+ * diskaudio driver.
+ *
+ * When filling in the desired audio spec structure:
+ *
+ * - `desired->freq` should be the frequency in sample-frames-per-second (Hz).
+ * - `desired->format` should be the audio format (`AUDIO_S16SYS`, etc).
+ * - `desired->samples` is the desired size of the audio buffer, in _sample
+ * frames_ (with stereo output, two samples--left and right--would make a
+ * single sample frame). This number should be a power of two, and may be
+ * adjusted by the audio driver to a value more suitable for the hardware.
+ * Good values seem to range between 512 and 8096 inclusive, depending on
+ * the application and CPU speed. Smaller values reduce latency, but can
+ * lead to underflow if the application is doing heavy processing and cannot
+ * fill the audio buffer in time. Note that the number of sample frames is
+ * directly related to time by the following formula: `ms =
+ * (sampleframes*1000)/freq`
+ * - `desired->size` is the size in _bytes_ of the audio buffer, and is
+ * calculated by SDL_OpenAudioDevice(). You don't initialize this.
+ * - `desired->silence` is the value used to set the buffer to silence, and is
+ * calculated by SDL_OpenAudioDevice(). You don't initialize this.
+ * - `desired->callback` should be set to a function that will be called when
+ * the audio device is ready for more data. It is passed a pointer to the
+ * audio buffer, and the length in bytes of the audio buffer. This function
+ * usually runs in a separate thread, and so you should protect data
+ * structures that it accesses by calling SDL_LockAudioDevice() and
+ * SDL_UnlockAudioDevice() in your code. Alternately, you may pass a NULL
+ * pointer here, and call SDL_QueueAudio() with some frequency, to queue
+ * more audio samples to be played (or for capture devices, call
+ * SDL_DequeueAudio() with some frequency, to obtain audio samples).
+ * - `desired->userdata` is passed as the first parameter to your callback
+ * function. If you passed a NULL callback, this value is ignored.
+ *
+ * `allowed_changes` can have the following flags OR'd together:
+ *
+ * - `SDL_AUDIO_ALLOW_FREQUENCY_CHANGE`
+ * - `SDL_AUDIO_ALLOW_FORMAT_CHANGE`
+ * - `SDL_AUDIO_ALLOW_CHANNELS_CHANGE`
+ * - `SDL_AUDIO_ALLOW_ANY_CHANGE`
+ *
+ * These flags specify how SDL should behave when a device cannot offer a
+ * specific feature. If the application requests a feature that the hardware
+ * doesn't offer, SDL will always try to get the closest equivalent.
+ *
+ * For example, if you ask for float32 audio format, but the sound card only
+ * supports int16, SDL will set the hardware to int16. If you had set
+ * SDL_AUDIO_ALLOW_FORMAT_CHANGE, SDL will change the format in the `obtained`
+ * structure. If that flag was *not* set, SDL will prepare to convert your
+ * callback's float32 audio to int16 before feeding it to the hardware and
+ * will keep the originally requested format in the `obtained` structure.
+ *
+ * If your application can only handle one specific data format, pass a zero
+ * for `allowed_changes` and let SDL transparently handle any differences.
+ *
+ * An opened audio device starts out paused, and should be enabled for playing
+ * by calling SDL_PauseAudioDevice(devid, 0) when you are ready for your audio
+ * callback function to be called. Since the audio driver may modify the
+ * requested size of the audio buffer, you should allocate any local mixing
+ * buffers after you open the audio device.
+ *
+ * The audio callback runs in a separate thread in most cases; you can prevent
+ * race conditions between your callback and other threads without fully
+ * pausing playback with SDL_LockAudioDevice(). For more information about the
+ * callback, see SDL_AudioSpec.
+ *
+ * \param device a UTF-8 string reported by SDL_GetAudioDeviceName() or a
+ * driver-specific name as appropriate. NULL requests the most
+ * reasonable default device.
+ * \param iscapture non-zero to specify a device should be opened for
+ * recording, not playback
+ * \param desired an SDL_AudioSpec structure representing the desired output
+ * format; see SDL_OpenAudio() for more information
+ * \param obtained an SDL_AudioSpec structure filled in with the actual output
+ * format; see SDL_OpenAudio() for more information
+ * \param allowed_changes 0, or one or more flags OR'd together
+ * \returns a valid device ID that is > 0 on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * For compatibility with SDL 1.2, this will never return 1, since
+ * SDL reserves that ID for the legacy SDL_OpenAudio() function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CloseAudioDevice
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_LockAudioDevice
+ * \sa SDL_OpenAudio
+ * \sa SDL_PauseAudioDevice
+ * \sa SDL_UnlockAudioDevice
+ */
+extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(
+ const char *device,
+ int iscapture,
+ const SDL_AudioSpec *desired,
+ SDL_AudioSpec *obtained,
+ int allowed_changes);
+
+
+
+/**
+ * \name Audio state
+ *
+ * Get the current audio state.
+ */
+/* @{ */
+typedef enum
+{
+ SDL_AUDIO_STOPPED = 0,
+ SDL_AUDIO_PLAYING,
+ SDL_AUDIO_PAUSED
+} SDL_AudioStatus;
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioStatus(void);
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
+/* @} *//* Audio State */
+
+/**
+ * \name Pause audio functions
+ *
+ * These functions pause and unpause the audio callback processing.
+ * They should be called with a parameter of 0 after opening the audio
+ * device to start playing sound. This is so you can safely initialize
+ * data for your callback function after opening the audio device.
+ * Silence will be written to the audio device during the pause.
+ */
+/* @{ */
+extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on);
+extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
+ int pause_on);
+/* @} *//* Pause audio functions */
+
+/**
+ * Load the audio data of a WAVE file into memory.
+ *
+ * Loading a WAVE file requires `src`, `spec`, `audio_buf` and `audio_len` to
+ * be valid pointers. The entire data portion of the file is then loaded into
+ * memory and decoded if necessary.
+ *
+ * If `freesrc` is non-zero, the data source gets automatically closed and
+ * freed before the function returns.
+ *
+ * Supported formats are RIFF WAVE files with the formats PCM (8, 16, 24, and
+ * 32 bits), IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and
+ * A-law and mu-law (8 bits). Other formats are currently unsupported and
+ * cause an error.
+ *
+ * If this function succeeds, the pointer returned by it is equal to `spec`
+ * and the pointer to the audio data allocated by the function is written to
+ * `audio_buf` and its length in bytes to `audio_len`. The SDL_AudioSpec
+ * members `freq`, `channels`, and `format` are set to the values of the audio
+ * data in the buffer. The `samples` member is set to a sane default and all
+ * others are set to zero.
+ *
+ * It's necessary to use SDL_FreeWAV() to free the audio data returned in
+ * `audio_buf` when it is no longer used.
+ *
+ * Because of the underspecification of the .WAV format, there are many
+ * problematic files in the wild that cause issues with strict decoders. To
+ * provide compatibility with these files, this decoder is lenient in regards
+ * to the truncation of the file, the fact chunk, and the size of the RIFF
+ * chunk. The hints `SDL_HINT_WAVE_RIFF_CHUNK_SIZE`,
+ * `SDL_HINT_WAVE_TRUNCATION`, and `SDL_HINT_WAVE_FACT_CHUNK` can be used to
+ * tune the behavior of the loading process.
+ *
+ * Any file that is invalid (due to truncation, corruption, or wrong values in
+ * the headers), too big, or unsupported causes an error. Additionally, any
+ * critical I/O error from the data source will terminate the loading process
+ * with an error. The function returns NULL on error and in all cases (with
+ * the exception of `src` being NULL), an appropriate error message will be
+ * set.
+ *
+ * It is required that the data source supports seeking.
+ *
+ * Example:
+ *
+ * ```c++
+ * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, &spec, &buf, &len);
+ * ```
+ *
+ * Note that the SDL_LoadWAV macro does this same thing for you, but in a less
+ * messy way:
+ *
+ * ```c++
+ * SDL_LoadWAV("sample.wav", &spec, &buf, &len);
+ * ```
+ *
+ * \param src The data source for the WAVE data
+ * \param freesrc If non-zero, SDL will _always_ free the data source
+ * \param spec An SDL_AudioSpec that will be filled in with the wave file's
+ * format details
+ * \param audio_buf A pointer filled with the audio data, allocated by the
+ * function.
+ * \param audio_len A pointer filled with the length of the audio data buffer
+ * in bytes
+ * \returns This function, if successfully called, returns `spec`, which will
+ * be filled with the audio data format of the wave source data.
+ * `audio_buf` will be filled with a pointer to an allocated buffer
+ * containing the audio data, and `audio_len` is filled with the
+ * length of that audio buffer in bytes.
+ *
+ * This function returns NULL if the .WAV file cannot be opened, uses
+ * an unknown data format, or is corrupt; call SDL_GetError() for
+ * more information.
+ *
+ * When the application is done with the data returned in
+ * `audio_buf`, it should call SDL_FreeWAV() to dispose of it.
+ *
+ * \sa SDL_FreeWAV
+ * \sa SDL_LoadWAV
+ */
+extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
+ int freesrc,
+ SDL_AudioSpec * spec,
+ Uint8 ** audio_buf,
+ Uint32 * audio_len);
+
+/**
+ * Loads a WAV from a file.
+ * Compatibility convenience function.
+ */
+#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
+ SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
+
+/**
+ * Free data previously allocated with SDL_LoadWAV() or SDL_LoadWAV_RW().
+ *
+ * After a WAVE file has been opened with SDL_LoadWAV() or SDL_LoadWAV_RW()
+ * its data can eventually be freed with SDL_FreeWAV(). It is safe to call
+ * this function with a NULL pointer.
+ *
+ * \param audio_buf a pointer to the buffer created by SDL_LoadWAV() or
+ * SDL_LoadWAV_RW()
+ *
+ * \sa SDL_LoadWAV
+ * \sa SDL_LoadWAV_RW
+ */
+extern DECLSPEC void SDLCALL SDL_FreeWAV(Uint8 * audio_buf);
+
+/**
+ * Initialize an SDL_AudioCVT structure for conversion.
+ *
+ * Before an SDL_AudioCVT structure can be used to convert audio data it must
+ * be initialized with source and destination information.
+ *
+ * This function will zero out every field of the SDL_AudioCVT, so it must be
+ * called before the application fills in the final buffer information.
+ *
+ * Once this function has returned successfully, and reported that a
+ * conversion is necessary, the application fills in the rest of the fields in
+ * SDL_AudioCVT, now that it knows how large a buffer it needs to allocate,
+ * and then can call SDL_ConvertAudio() to complete the conversion.
+ *
+ * \param cvt an SDL_AudioCVT structure filled in with audio conversion
+ * information
+ * \param src_format the source format of the audio data; for more info see
+ * SDL_AudioFormat
+ * \param src_channels the number of channels in the source
+ * \param src_rate the frequency (sample-frames-per-second) of the source
+ * \param dst_format the destination format of the audio data; for more info
+ * see SDL_AudioFormat
+ * \param dst_channels the number of channels in the destination
+ * \param dst_rate the frequency (sample-frames-per-second) of the destination
+ * \returns 1 if the audio filter is prepared, 0 if no conversion is needed,
+ * or a negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_ConvertAudio
+ */
+extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
+ SDL_AudioFormat src_format,
+ Uint8 src_channels,
+ int src_rate,
+ SDL_AudioFormat dst_format,
+ Uint8 dst_channels,
+ int dst_rate);
+
+/**
+ * Convert audio data to a desired audio format.
+ *
+ * This function does the actual audio data conversion, after the application
+ * has called SDL_BuildAudioCVT() to prepare the conversion information and
+ * then filled in the buffer details.
+ *
+ * Once the application has initialized the `cvt` structure using
+ * SDL_BuildAudioCVT(), allocated an audio buffer and filled it with audio
+ * data in the source format, this function will convert the buffer, in-place,
+ * to the desired format.
+ *
+ * The data conversion may go through several passes; any given pass may
+ * possibly temporarily increase the size of the data. For example, SDL might
+ * expand 16-bit data to 32 bits before resampling to a lower frequency,
+ * shrinking the data size after having grown it briefly. Since the supplied
+ * buffer will be both the source and destination, converting as necessary
+ * in-place, the application must allocate a buffer that will fully contain
+ * the data during its largest conversion pass. After SDL_BuildAudioCVT()
+ * returns, the application should set the `cvt->len` field to the size, in
+ * bytes, of the source data, and allocate a buffer that is `cvt->len *
+ * cvt->len_mult` bytes long for the `buf` field.
+ *
+ * The source data should be copied into this buffer before the call to
+ * SDL_ConvertAudio(). Upon successful return, this buffer will contain the
+ * converted audio, and `cvt->len_cvt` will be the size of the converted data,
+ * in bytes. Any bytes in the buffer past `cvt->len_cvt` are undefined once
+ * this function returns.
+ *
+ * \param cvt an SDL_AudioCVT structure that was previously set up by
+ * SDL_BuildAudioCVT().
+ * \returns 0 if the conversion was completed successfully or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_BuildAudioCVT
+ */
+extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt);
+
+/* SDL_AudioStream is a new audio conversion interface.
+ The benefits vs SDL_AudioCVT:
+ - it can handle resampling data in chunks without generating
+ artifacts, when it doesn't have the complete buffer available.
+ - it can handle incoming data in any variable size.
+ - You push data as you have it, and pull it when you need it
+ */
+/* this is opaque to the outside world. */
+struct _SDL_AudioStream;
+typedef struct _SDL_AudioStream SDL_AudioStream;
+
+/**
+ * Create a new audio stream.
+ *
+ * \param src_format The format of the source audio
+ * \param src_channels The number of channels of the source audio
+ * \param src_rate The sampling rate of the source audio
+ * \param dst_format The format of the desired audio output
+ * \param dst_channels The number of channels of the desired audio output
+ * \param dst_rate The sampling rate of the desired audio output
+ * \returns 0 on success, or -1 on error.
+ *
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC SDL_AudioStream * SDLCALL SDL_NewAudioStream(const SDL_AudioFormat src_format,
+ const Uint8 src_channels,
+ const int src_rate,
+ const SDL_AudioFormat dst_format,
+ const Uint8 dst_channels,
+ const int dst_rate);
+
+/**
+ * Add data to be converted/resampled to the stream.
+ *
+ * \param stream The stream the audio data is being added to
+ * \param buf A pointer to the audio data to add
+ * \param len The number of bytes to write to the stream
+ * \returns 0 on success, or -1 on error.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len);
+
+/**
+ * Get converted/resampled data from the stream
+ *
+ * \param stream The stream the audio is being requested from
+ * \param buf A buffer to fill with audio data
+ * \param len The maximum number of bytes to fill
+ * \returns the number of bytes read from the stream, or -1 on error
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len);
+
+/**
+ * Get the number of converted/resampled bytes available.
+ *
+ * The stream may be buffering data behind the scenes until it has enough to
+ * resample correctly, so this number might be lower than what you expect, or
+ * even be zero. Add more data or flush the stream if you need the data now.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamAvailable(SDL_AudioStream *stream);
+
+/**
+ * Tell the stream that you're done sending data, and anything being buffered
+ * should be converted/resampled and made available immediately.
+ *
+ * It is legal to add more data to a stream after flushing, but there will be
+ * audio gaps in the output. Generally this is intended to signal the end of
+ * input, so the complete output becomes available.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamFlush(SDL_AudioStream *stream);
+
+/**
+ * Clear any pending data in the stream without converting it
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC void SDLCALL SDL_AudioStreamClear(SDL_AudioStream *stream);
+
+/**
+ * Free an audio stream
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ */
+extern DECLSPEC void SDLCALL SDL_FreeAudioStream(SDL_AudioStream *stream);
+
+#define SDL_MIX_MAXVOLUME 128
+/**
+ * This function is a legacy means of mixing audio.
+ *
+ * This function is equivalent to calling
+ *
+ * ```c++
+ * SDL_MixAudioFormat(dst, src, format, len, volume);
+ * ```
+ *
+ * where `format` is the obtained format of the audio device from the legacy
+ * SDL_OpenAudio() function.
+ *
+ * \param dst the destination for the mixed audio
+ * \param src the source audio buffer to be mixed
+ * \param len the length of the audio buffer in bytes
+ * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+ * for full audio volume
+ *
+ * \sa SDL_MixAudioFormat
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src,
+ Uint32 len, int volume);
+
+/**
+ * Mix audio data in a specified format.
+ *
+ * This takes an audio buffer `src` of `len` bytes of `format` data and mixes
+ * it into `dst`, performing addition, volume adjustment, and overflow
+ * clipping. The buffer pointed to by `dst` must also be `len` bytes of
+ * `format` data.
+ *
+ * This is provided for convenience -- you can mix your own audio data.
+ *
+ * Do not use this function for mixing together more than two streams of
+ * sample data. The output from repeated application of this function may be
+ * distorted by clipping, because there is no accumulator with greater range
+ * than the input (not to mention this being an inefficient way of doing it).
+ *
+ * It is a common misconception that this function is required to write audio
+ * data to an output stream in an audio callback. While you can do that,
+ * SDL_MixAudioFormat() is really only needed when you're mixing a single
+ * audio stream with a volume adjustment.
+ *
+ * \param dst the destination for the mixed audio
+ * \param src the source audio buffer to be mixed
+ * \param format the SDL_AudioFormat structure representing the desired audio
+ * format
+ * \param len the length of the audio buffer in bytes
+ * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+ * for full audio volume
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
+ const Uint8 * src,
+ SDL_AudioFormat format,
+ Uint32 len, int volume);
+
+/**
+ * Queue more audio on non-callback devices.
+ *
+ * If you are looking to retrieve queued audio from a non-callback capture
+ * device, you want SDL_DequeueAudio() instead. SDL_QueueAudio() will return
+ * -1 to signify an error if you use it with capture devices.
+ *
+ * SDL offers two ways to feed audio to the device: you can either supply a
+ * callback that SDL triggers with some frequency to obtain more audio (pull
+ * method), or you can supply no callback, and then SDL will expect you to
+ * supply data at regular intervals (push method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Queued data will drain to the device as
+ * necessary without further intervention from you. If the device needs audio
+ * but there is not enough queued, it will play silence to make up the
+ * difference. This means you will have skips in your audio playback if you
+ * aren't routinely queueing sufficient data.
+ *
+ * This function copies the supplied data, so you are safe to free it when the
+ * function returns. This function is thread-safe, but queueing to the same
+ * device from two threads at once does not promise which buffer will be
+ * queued first.
+ *
+ * You may not queue audio on a device that is using an application-supplied
+ * callback; doing so returns an error. You have to use the audio callback or
+ * queue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before queueing; SDL
+ * handles locking internally for this function.
+ *
+ * Note that SDL2
+ * [https://discourse.libsdl.org/t/sdl2-support-for-planar-audio/31263/3 does
+ * not support planar audio]. You will need to resample from planar audio
+ * formats into a non-planar one (see SDL_AudioFormat) before queuing audio.
+ *
+ * \param dev the device ID to which we will queue audio
+ * \param data the data to queue to the device for later playback
+ * \param len the number of bytes (not samples!) to which `data` points
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
+
+/**
+ * Dequeue more audio on non-callback devices.
+ *
+ * If you are looking to queue audio for output on a non-callback playback
+ * device, you want SDL_QueueAudio() instead. SDL_DequeueAudio() will always
+ * return 0 if you use it with playback devices.
+ *
+ * SDL offers two ways to retrieve audio from a capture device: you can either
+ * supply a callback that SDL triggers with some frequency as the device
+ * records more audio data, (push method), or you can supply no callback, and
+ * then SDL will expect you to retrieve data at regular intervals (pull
+ * method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Data from the device will keep queuing as
+ * necessary without further intervention from you. This means you will
+ * eventually run out of memory if you aren't routinely dequeueing data.
+ *
+ * Capture devices will not queue data when paused; if you are expecting to
+ * not need captured audio for some length of time, use SDL_PauseAudioDevice()
+ * to stop the capture device from queueing more data. This can be useful
+ * during, say, level loading times. When unpaused, capture devices will start
+ * queueing data from that point, having flushed any capturable data available
+ * while paused.
+ *
+ * This function is thread-safe, but dequeueing from the same device from two
+ * threads at once does not promise which thread will dequeue data first.
+ *
+ * You may not dequeue audio from a device that is using an
+ * application-supplied callback; doing so returns an error. You have to use
+ * the audio callback, or dequeue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before dequeueing; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev the device ID from which we will dequeue audio
+ * \param data a pointer into where audio data should be copied
+ * \param len the number of bytes (not samples!) to which (data) points
+ * \returns the number of bytes dequeued, which could be less than requested;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_DequeueAudio(SDL_AudioDeviceID dev, void *data, Uint32 len);
+
+/**
+ * Get the number of bytes of still-queued audio.
+ *
+ * For playback devices: this is the number of bytes that have been queued for
+ * playback with SDL_QueueAudio(), but have not yet been sent to the hardware.
+ *
+ * Once we've sent it to the hardware, this function can not decide the exact
+ * byte boundary of what has been played. It's possible that we just gave the
+ * hardware several kilobytes right before you called this function, but it
+ * hasn't played any of it yet, or maybe half of it, etc.
+ *
+ * For capture devices, this is the number of bytes that have been captured by
+ * the device and are waiting for you to dequeue. This number may grow at any
+ * time, so this only informs of the lower-bound of available data.
+ *
+ * You may not queue or dequeue audio on a device that is using an
+ * application-supplied callback; calling this function on such a device
+ * always returns 0. You have to use the audio callback or queue audio, but
+ * not both.
+ *
+ * You should not call SDL_LockAudio() on the device before querying; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev the device ID of which we will query queued audio size
+ * \returns the number of bytes (not samples!) of queued audio.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_QueueAudio
+ * \sa SDL_DequeueAudio
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
+
+/**
+ * Drop any queued audio data waiting to be sent to the hardware.
+ *
+ * Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For
+ * output devices, the hardware will start playing silence if more audio isn't
+ * queued. For capture devices, the hardware will start filling the empty
+ * queue with new data if the capture device isn't paused.
+ *
+ * This will not prevent playback of queued audio that's already been sent to
+ * the hardware, as we can not undo that, so expect there to be some fraction
+ * of a second of audio that might still be heard. This can be useful if you
+ * want to, say, drop any pending music or any unprocessed microphone input
+ * during a level change in your game.
+ *
+ * You may not queue or dequeue audio on a device that is using an
+ * application-supplied callback; calling this function on such a device
+ * always returns 0. You have to use the audio callback or queue audio, but
+ * not both.
+ *
+ * You should not call SDL_LockAudio() on the device before clearing the
+ * queue; SDL handles locking internally for this function.
+ *
+ * This function always succeeds and thus returns void.
+ *
+ * \param dev the device ID of which to clear the audio queue
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetQueuedAudioSize
+ * \sa SDL_QueueAudio
+ * \sa SDL_DequeueAudio
+ */
+extern DECLSPEC void SDLCALL SDL_ClearQueuedAudio(SDL_AudioDeviceID dev);
+
+
+/**
+ * \name Audio lock functions
+ *
+ * The lock manipulated by these functions protects the callback function.
+ * During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that
+ * the callback function is not running. Do not call these from the callback
+ * function or you will cause deadlock.
+ */
+/* @{ */
+extern DECLSPEC void SDLCALL SDL_LockAudio(void);
+extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev);
+extern DECLSPEC void SDLCALL SDL_UnlockAudio(void);
+extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
+/* @} *//* Audio lock functions */
+
+/**
+ * This function is a legacy means of closing the audio device.
+ *
+ * This function is equivalent to calling
+ *
+ * ```c++
+ * SDL_CloseAudioDevice(1);
+ * ```
+ *
+ * and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \sa SDL_OpenAudio
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudio(void);
+
+/**
+ * Use this function to shut down audio processing and close the audio device.
+ *
+ * The application should close open audio devices once they are no longer
+ * needed. Calling this function will wait until the device's audio callback
+ * is not running, release the audio hardware and then clean up internal
+ * state. No further audio will play from this device once this function
+ * returns.
+ *
+ * This function may block briefly while pending audio data is played by the
+ * hardware, so that applications don't drop the last buffer of data they
+ * supplied.
+ *
+ * The device ID is invalid as soon as the device is closed, and is eligible
+ * for reuse in a new SDL_OpenAudioDevice() call immediately.
+ *
+ * \param dev an audio device previously opened with SDL_OpenAudioDevice()
+ *
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_audio_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_bits.h b/Client/ThirdParty/SDL2/SDL_bits.h
new file mode 100644
index 0000000..553b687
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_bits.h
@@ -0,0 +1,126 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_bits.h
+ *
+ * Functions for fiddling with bits and bitmasks.
+ */
+
+#ifndef SDL_bits_h_
+#define SDL_bits_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_bits.h
+ */
+
+/**
+ * Get the index of the most significant bit. Result is undefined when called
+ * with 0. This operation can also be stated as "count leading zeroes" and
+ * "log base 2".
+ *
+ * \return the index of the most significant bit, or -1 if the value is 0.
+ */
+#if defined(__WATCOMC__) && defined(__386__)
+extern _inline int _SDL_bsr_watcom (Uint32);
+#pragma aux _SDL_bsr_watcom = \
+ "bsr eax, eax" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+SDL_FORCE_INLINE int
+SDL_MostSignificantBitIndex32(Uint32 x)
+{
+#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+ /* Count Leading Zeroes builtin in GCC.
+ * http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
+ */
+ if (x == 0) {
+ return -1;
+ }
+ return 31 - __builtin_clz(x);
+#elif defined(__WATCOMC__) && defined(__386__)
+ if (x == 0) {
+ return -1;
+ }
+ return _SDL_bsr_watcom(x);
+#elif defined(_MSC_VER)
+ unsigned long index;
+ if (_BitScanReverse(&index, x)) {
+ return index;
+ }
+ return -1;
+#else
+ /* Based off of Bit Twiddling Hacks by Sean Eron Anderson
+ * <seander@cs.stanford.edu>, released in the public domain.
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
+ */
+ const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+ const int S[] = {1, 2, 4, 8, 16};
+
+ int msbIndex = 0;
+ int i;
+
+ if (x == 0) {
+ return -1;
+ }
+
+ for (i = 4; i >= 0; i--)
+ {
+ if (x & b[i])
+ {
+ x >>= S[i];
+ msbIndex |= S[i];
+ }
+ }
+
+ return msbIndex;
+#endif
+}
+
+SDL_FORCE_INLINE SDL_bool
+SDL_HasExactlyOneBitSet32(Uint32 x)
+{
+ if (x && !(x & (x - 1))) {
+ return SDL_TRUE;
+ }
+ return SDL_FALSE;
+}
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_bits_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_blendmode.h b/Client/ThirdParty/SDL2/SDL_blendmode.h
new file mode 100644
index 0000000..374f225
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_blendmode.h
@@ -0,0 +1,200 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_blendmode.h
+ *
+ * Header file declaring the SDL_BlendMode enumeration
+ */
+
+#ifndef SDL_blendmode_h_
+#define SDL_blendmode_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The blend mode used in SDL_RenderCopy() and drawing operations.
+ */
+typedef enum
+{
+ SDL_BLENDMODE_NONE = 0x00000000, /**< no blending
+ dstRGBA = srcRGBA */
+ SDL_BLENDMODE_BLEND = 0x00000001, /**< alpha blending
+ dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+ dstA = srcA + (dstA * (1-srcA)) */
+ SDL_BLENDMODE_ADD = 0x00000002, /**< additive blending
+ dstRGB = (srcRGB * srcA) + dstRGB
+ dstA = dstA */
+ SDL_BLENDMODE_MOD = 0x00000004, /**< color modulate
+ dstRGB = srcRGB * dstRGB
+ dstA = dstA */
+ SDL_BLENDMODE_MUL = 0x00000008, /**< color multiply
+ dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
+ dstA = (srcA * dstA) + (dstA * (1-srcA)) */
+ SDL_BLENDMODE_INVALID = 0x7FFFFFFF
+
+ /* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */
+
+} SDL_BlendMode;
+
+/**
+ * \brief The blend operation used when combining source and destination pixel components
+ */
+typedef enum
+{
+ SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
+ SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
+ SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D11 */
+ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D11 */
+
+} SDL_BlendOperation;
+
+/**
+ * \brief The normalized factor used to multiply pixel components
+ */
+typedef enum
+{
+ SDL_BLENDFACTOR_ZERO = 0x1, /**< 0, 0, 0, 0 */
+ SDL_BLENDFACTOR_ONE = 0x2, /**< 1, 1, 1, 1 */
+ SDL_BLENDFACTOR_SRC_COLOR = 0x3, /**< srcR, srcG, srcB, srcA */
+ SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4, /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
+ SDL_BLENDFACTOR_SRC_ALPHA = 0x5, /**< srcA, srcA, srcA, srcA */
+ SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6, /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
+ SDL_BLENDFACTOR_DST_COLOR = 0x7, /**< dstR, dstG, dstB, dstA */
+ SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
+ SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
+ SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
+
+} SDL_BlendFactor;
+
+/**
+ * Compose a custom blend mode for renderers.
+ *
+ * The functions SDL_SetRenderDrawBlendMode and SDL_SetTextureBlendMode accept
+ * the SDL_BlendMode returned by this function if the renderer supports it.
+ *
+ * A blend mode controls how the pixels from a drawing operation (source) get
+ * combined with the pixels from the render target (destination). First, the
+ * components of the source and destination pixels get multiplied with their
+ * blend factors. Then, the blend operation takes the two products and
+ * calculates the result that will get stored in the render target.
+ *
+ * Expressed in pseudocode, it would look like this:
+ *
+ * ```c
+ * dstRGB = colorOperation(srcRGB * srcColorFactor, dstRGB * dstColorFactor);
+ * dstA = alphaOperation(srcA * srcAlphaFactor, dstA * dstAlphaFactor);
+ * ```
+ *
+ * Where the functions `colorOperation(src, dst)` and `alphaOperation(src,
+ * dst)` can return one of the following:
+ *
+ * - `src + dst`
+ * - `src - dst`
+ * - `dst - src`
+ * - `min(src, dst)`
+ * - `max(src, dst)`
+ *
+ * The red, green, and blue components are always multiplied with the first,
+ * second, and third components of the SDL_BlendFactor, respectively. The
+ * fourth component is not used.
+ *
+ * The alpha component is always multiplied with the fourth component of the
+ * SDL_BlendFactor. The other components are not used in the alpha
+ * calculation.
+ *
+ * Support for these blend modes varies for each renderer. To check if a
+ * specific SDL_BlendMode is supported, create a renderer and pass it to
+ * either SDL_SetRenderDrawBlendMode or SDL_SetTextureBlendMode. They will
+ * return with an error if the blend mode is not supported.
+ *
+ * This list describes the support of custom blend modes for each renderer in
+ * SDL 2.0.6. All renderers support the four blend modes listed in the
+ * SDL_BlendMode enumeration.
+ *
+ * - **direct3d**: Supports `SDL_BLENDOPERATION_ADD` with all factors.
+ * - **direct3d11**: Supports all operations with all factors. However, some
+ * factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
+ * `SDL_BLENDOPERATION_MAXIMUM`.
+ * - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
+ * factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL
+ * 2.0.6.
+ * - **opengles**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
+ * factors. Color and alpha factors need to be the same. OpenGL ES 1
+ * implementation specific: May also support `SDL_BLENDOPERATION_SUBTRACT`
+ * and `SDL_BLENDOPERATION_REV_SUBTRACT`. May support color and alpha
+ * operations being different from each other. May support color and alpha
+ * factors being different from each other.
+ * - **opengles2**: Supports the `SDL_BLENDOPERATION_ADD`,
+ * `SDL_BLENDOPERATION_SUBTRACT`, `SDL_BLENDOPERATION_REV_SUBTRACT`
+ * operations with all factors.
+ * - **psp**: No custom blend mode support.
+ * - **software**: No custom blend mode support.
+ *
+ * Some renderers do not provide an alpha component for the default render
+ * target. The `SDL_BLENDFACTOR_DST_ALPHA` and
+ * `SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA` factors do not have an effect in this
+ * case.
+ *
+ * \param srcColorFactor the SDL_BlendFactor applied to the red, green, and
+ * blue components of the source pixels
+ * \param dstColorFactor the SDL_BlendFactor applied to the red, green, and
+ * blue components of the destination pixels
+ * \param colorOperation the SDL_BlendOperation used to combine the red,
+ * green, and blue components of the source and
+ * destination pixels
+ * \param srcAlphaFactor the SDL_BlendFactor applied to the alpha component of
+ * the source pixels
+ * \param dstAlphaFactor the SDL_BlendFactor applied to the alpha component of
+ * the destination pixels
+ * \param alphaOperation the SDL_BlendOperation used to combine the alpha
+ * component of the source and destination pixels
+ * \returns an SDL_BlendMode that represents the chosen factors and
+ * operations.
+ *
+ * \since This function is available in SDL 2.0.6.
+ *
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_GetRenderDrawBlendMode
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_GetTextureBlendMode
+ */
+extern DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor,
+ SDL_BlendFactor dstColorFactor,
+ SDL_BlendOperation colorOperation,
+ SDL_BlendFactor srcAlphaFactor,
+ SDL_BlendFactor dstAlphaFactor,
+ SDL_BlendOperation alphaOperation);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_blendmode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_clipboard.h b/Client/ThirdParty/SDL2/SDL_clipboard.h
new file mode 100644
index 0000000..79e4dcc
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_clipboard.h
@@ -0,0 +1,89 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_clipboard.h
+ *
+ * Include file for SDL clipboard handling
+ */
+
+#ifndef SDL_clipboard_h_
+#define SDL_clipboard_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+/**
+ * Put UTF-8 text into the clipboard.
+ *
+ * \param text the text to store in the clipboard
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetClipboardText
+ * \sa SDL_HasClipboardText
+ */
+extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text);
+
+/**
+ * Get UTF-8 text from the clipboard, which must be freed with SDL_free().
+ *
+ * This functions returns NULL if there was not enough memory left for a copy
+ * of the clipboard's content.
+ *
+ * \returns the clipboard text on success or NULL on failure; call
+ * SDL_GetError() for more information. Caller must call SDL_free()
+ * on the returned pointer when done with it.
+ *
+ * \sa SDL_HasClipboardText
+ * \sa SDL_SetClipboardText
+ */
+extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
+
+/**
+ * Query whether the clipboard exists and contains a non-empty text string.
+ *
+ * \returns SDL_TRUE if the clipboard has text, or SDL_FALSE if it does not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetClipboardText
+ * \sa SDL_SetClipboardText
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_clipboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_config.h b/Client/ThirdParty/SDL2/SDL_config.h
new file mode 100644
index 0000000..33436c4
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config.h
@@ -0,0 +1,299 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_windows_h_
+#define SDL_config_windows_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This is a set of defines to configure the SDL features */
+
+#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
+#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__) || defined(__clang__)
+#define HAVE_STDINT_H 1
+#elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#endif
+#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#endif
+#else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#endif
+typedef unsigned int uintptr_t;
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
+
+#define HAVE_DDRAW_H 1
+#define HAVE_DINPUT_H 1
+#define HAVE_DSOUND_H 1
+#define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
+#define HAVE_MMDEVICEAPI_H 1
+#define HAVE_AUDIOCLIENT_H 1
+#define HAVE_SENSORSAPI_H 1
+#if (defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)) && (defined(_MSC_VER) && _MSC_VER >= 1600)
+#define HAVE_IMMINTRIN_H 1
+#elif defined(__has_include) && (defined(__i386__) || defined(__x86_64))
+# if __has_include(<immintrin.h>)
+# define HAVE_IMMINTRIN_H 1
+# endif
+#endif
+
+/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
+#ifdef HAVE_LIBC
+/* Useful headers */
+#define STDC_HEADERS 1
+#define HAVE_CTYPE_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STRING_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE__STRREV 1
+/* These functions have security warnings, so we won't use them */
+/* #undef HAVE__STRUPR */
+/* #undef HAVE__STRLWR */
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+/* #undef HAVE_STRTOK_R */
+/* These functions have security warnings, so we won't use them */
+/* #undef HAVE__LTOA */
+/* #undef HAVE__ULTOA */
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE__STRICMP 1
+#define HAVE__STRNICMP 1
+#define HAVE__WCSICMP 1
+#define HAVE__WCSNICMP 1
+#define HAVE__WCSDUP 1
+#define HAVE_ACOS 1
+#define HAVE_ACOSF 1
+#define HAVE_ASIN 1
+#define HAVE_ASINF 1
+#define HAVE_ATAN 1
+#define HAVE_ATANF 1
+#define HAVE_ATAN2 1
+#define HAVE_ATAN2F 1
+#define HAVE_CEILF 1
+#define HAVE__COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_EXP 1
+#define HAVE_EXPF 1
+#define HAVE_FABS 1
+#define HAVE_FABSF 1
+#define HAVE_FLOOR 1
+#define HAVE_FLOORF 1
+#define HAVE_FMOD 1
+#define HAVE_FMODF 1
+#define HAVE_LOG 1
+#define HAVE_LOGF 1
+#define HAVE_LOG10 1
+#define HAVE_LOG10F 1
+#define HAVE_POW 1
+#define HAVE_POWF 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#if defined(_MSC_VER)
+/* These functions were added with the VC++ 2013 C runtime library */
+#if _MSC_VER >= 1800
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_VSSCANF 1
+#define HAVE_LROUND 1
+#define HAVE_LROUNDF 1
+#define HAVE_ROUND 1
+#define HAVE_ROUNDF 1
+#define HAVE_SCALBN 1
+#define HAVE_SCALBNF 1
+#define HAVE_TRUNC 1
+#define HAVE_TRUNCF 1
+#endif
+/* This function is available with at least the VC++ 2008 C runtime library */
+#if _MSC_VER >= 1400
+#define HAVE__FSEEKI64 1
+#endif
+#endif
+#if !defined(_MSC_VER) || defined(_USE_MATH_DEFINES)
+#define HAVE_M_PI 1
+#endif
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#endif
+
+/* Check to see if we have Windows 10 build environment */
+#if defined(_MSC_VER) && (_MSC_VER >= 1911) /* Visual Studio 15.3 */
+#include <sdkddkver.h>
+#if _WIN32_WINNT >= 0x0601 /* Windows 7 */
+#define SDL_WINDOWS7_SDK
+#endif
+#if _WIN32_WINNT >= 0x0602 /* Windows 8 */
+#define SDL_WINDOWS8_SDK
+#endif
+#if _WIN32_WINNT >= 0x0A00 /* Windows 10 */
+#define SDL_WINDOWS10_SDK
+#endif
+#endif /* _MSC_VER >= 1911 */
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_WASAPI 1
+#define SDL_AUDIO_DRIVER_DSOUND 1
+#define SDL_AUDIO_DRIVER_WINMM 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_DINPUT 1
+#define SDL_JOYSTICK_HIDAPI 1
+#ifndef __WINRT__
+#define SDL_JOYSTICK_RAWINPUT 1
+#endif
+#define SDL_JOYSTICK_VIRTUAL 1
+#ifdef SDL_WINDOWS10_SDK
+#define SDL_JOYSTICK_WGI 1
+#endif
+#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_DINPUT 1
+#define SDL_HAPTIC_XINPUT 1
+
+/* Enable the sensor driver */
+#define SDL_SENSOR_WINDOWS 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_WINDOWS 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_GENERIC_COND_SUFFIX 1
+#define SDL_THREAD_WINDOWS 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_WINDOWS 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_WINDOWS 1
+
+#ifndef SDL_VIDEO_RENDER_D3D
+#define SDL_VIDEO_RENDER_D3D 1
+#endif
+#ifdef SDL_WINDOWS7_SDK
+#define SDL_VIDEO_RENDER_D3D11 1
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_WGL
+#define SDL_VIDEO_OPENGL_WGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_OPENGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_EGL
+#define SDL_VIDEO_OPENGL_EGL 1
+#endif
+
+/* Enable Vulkan support */
+#define SDL_VIDEO_VULKAN 1
+
+/* Enable system power support */
+#define SDL_POWER_WINDOWS 1
+
+/* Enable filesystem support */
+#define SDL_FILESYSTEM_WINDOWS 1
+
+/* Enable assembly routines (Win64 doesn't have inline asm) */
+#ifndef _WIN64
+#define SDL_ASSEMBLY_ROUTINES 1
+#endif
+
+#endif /* SDL_config_windows_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_config.h.cmake b/Client/ThirdParty/SDL2/SDL_config.h.cmake
new file mode 100644
index 0000000..c57266c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config.h.cmake
@@ -0,0 +1,445 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_h_
+#define SDL_config_h_
+
+/**
+ * \file SDL_config.h.in
+ *
+ * This is a set of defines to configure the SDL features
+ */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+/* C language features */
+#cmakedefine const @HAVE_CONST@
+#cmakedefine inline @HAVE_INLINE@
+#cmakedefine volatile @HAVE_VOLATILE@
+
+/* C datatypes */
+/* Define SIZEOF_VOIDP for 64/32 architectures */
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#cmakedefine HAVE_GCC_ATOMICS @HAVE_GCC_ATOMICS@
+#cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET @HAVE_GCC_SYNC_LOCK_TEST_AND_SET@
+
+#cmakedefine HAVE_D3D_H @HAVE_D3D_H@
+#cmakedefine HAVE_D3D11_H @HAVE_D3D11_H@
+#cmakedefine HAVE_DDRAW_H @HAVE_DDRAW_H@
+#cmakedefine HAVE_DSOUND_H @HAVE_DSOUND_H@
+#cmakedefine HAVE_DINPUT_H @HAVE_DINPUT_H@
+#cmakedefine HAVE_XAUDIO2_H @HAVE_XAUDIO2_H@
+#cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@
+#cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@
+#cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@
+#cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@
+
+/* Comment this if you want to build without any C library requirements */
+#cmakedefine HAVE_LIBC 1
+#if HAVE_LIBC
+
+/* Useful headers */
+#cmakedefine HAVE_ALLOCA_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+#cmakedefine HAVE_STDIO_H 1
+#cmakedefine STDC_HEADERS 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STDARG_H 1
+#cmakedefine HAVE_MALLOC_H 1
+#cmakedefine HAVE_MEMORY_H 1
+#cmakedefine HAVE_STRING_H 1
+#cmakedefine HAVE_STRINGS_H 1
+#cmakedefine HAVE_WCHAR_H 1
+#cmakedefine HAVE_INTTYPES_H 1
+#cmakedefine HAVE_STDINT_H 1
+#cmakedefine HAVE_CTYPE_H 1
+#cmakedefine HAVE_MATH_H 1
+#cmakedefine HAVE_ICONV_H 1
+#cmakedefine HAVE_SIGNAL_H 1
+#cmakedefine HAVE_ALTIVEC_H 1
+#cmakedefine HAVE_PTHREAD_NP_H 1
+#cmakedefine HAVE_LIBUDEV_H 1
+#cmakedefine HAVE_DBUS_DBUS_H 1
+#cmakedefine HAVE_IBUS_IBUS_H 1
+#cmakedefine HAVE_FCITX_FRONTEND_H 1
+#cmakedefine HAVE_LIBSAMPLERATE_H 1
+
+/* C library functions */
+#cmakedefine HAVE_MALLOC 1
+#cmakedefine HAVE_CALLOC 1
+#cmakedefine HAVE_REALLOC 1
+#cmakedefine HAVE_FREE 1
+#cmakedefine HAVE_ALLOCA 1
+#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */
+#cmakedefine HAVE_GETENV 1
+#cmakedefine HAVE_SETENV 1
+#cmakedefine HAVE_PUTENV 1
+#cmakedefine HAVE_UNSETENV 1
+#endif
+#cmakedefine HAVE_QSORT 1
+#cmakedefine HAVE_ABS 1
+#cmakedefine HAVE_BCOPY 1
+#cmakedefine HAVE_MEMSET 1
+#cmakedefine HAVE_MEMCPY 1
+#cmakedefine HAVE_MEMMOVE 1
+#cmakedefine HAVE_MEMCMP 1
+#cmakedefine HAVE_WCSLEN 1
+#cmakedefine HAVE_WCSLCPY 1
+#cmakedefine HAVE_WCSLCAT 1
+#cmakedefine HAVE_WCSCMP 1
+#cmakedefine HAVE_STRLEN 1
+#cmakedefine HAVE_STRLCPY 1
+#cmakedefine HAVE_STRLCAT 1
+#cmakedefine HAVE_STRDUP 1
+#cmakedefine HAVE__STRREV 1
+#cmakedefine HAVE__STRUPR 1
+#cmakedefine HAVE__STRLWR 1
+#cmakedefine HAVE_INDEX 1
+#cmakedefine HAVE_RINDEX 1
+#cmakedefine HAVE_STRCHR 1
+#cmakedefine HAVE_STRRCHR 1
+#cmakedefine HAVE_STRSTR 1
+#cmakedefine HAVE_ITOA 1
+#cmakedefine HAVE__LTOA 1
+#cmakedefine HAVE__UITOA 1
+#cmakedefine HAVE__ULTOA 1
+#cmakedefine HAVE_STRTOL 1
+#cmakedefine HAVE_STRTOUL 1
+#cmakedefine HAVE__I64TOA 1
+#cmakedefine HAVE__UI64TOA 1
+#cmakedefine HAVE_STRTOLL 1
+#cmakedefine HAVE_STRTOULL 1
+#cmakedefine HAVE_STRTOD 1
+#cmakedefine HAVE_ATOI 1
+#cmakedefine HAVE_ATOF 1
+#cmakedefine HAVE_STRCMP 1
+#cmakedefine HAVE_STRNCMP 1
+#cmakedefine HAVE__STRICMP 1
+#cmakedefine HAVE_STRCASECMP 1
+#cmakedefine HAVE__STRNICMP 1
+#cmakedefine HAVE_STRNCASECMP 1
+#cmakedefine HAVE_VSSCANF 1
+#cmakedefine HAVE_VSNPRINTF 1
+#cmakedefine HAVE_M_PI 1
+#cmakedefine HAVE_ATAN 1
+#cmakedefine HAVE_ATAN2 1
+#cmakedefine HAVE_ACOS 1
+#cmakedefine HAVE_ASIN 1
+#cmakedefine HAVE_CEIL 1
+#cmakedefine HAVE_COPYSIGN 1
+#cmakedefine HAVE_COS 1
+#cmakedefine HAVE_COSF 1
+#cmakedefine HAVE_FABS 1
+#cmakedefine HAVE_FLOOR 1
+#cmakedefine HAVE_LOG 1
+#cmakedefine HAVE_POW 1
+#cmakedefine HAVE_SCALBN 1
+#cmakedefine HAVE_SIN 1
+#cmakedefine HAVE_SINF 1
+#cmakedefine HAVE_SQRT 1
+#cmakedefine HAVE_SQRTF 1
+#cmakedefine HAVE_TAN 1
+#cmakedefine HAVE_TANF 1
+#cmakedefine HAVE_FOPEN64 1
+#cmakedefine HAVE_FSEEKO 1
+#cmakedefine HAVE_FSEEKO64 1
+#cmakedefine HAVE_SIGACTION 1
+#cmakedefine HAVE_SA_SIGACTION 1
+#cmakedefine HAVE_SETJMP 1
+#cmakedefine HAVE_NANOSLEEP 1
+#cmakedefine HAVE_SYSCONF 1
+#cmakedefine HAVE_SYSCTLBYNAME 1
+#cmakedefine HAVE_CLOCK_GETTIME 1
+#cmakedefine HAVE_GETPAGESIZE 1
+#cmakedefine HAVE_MPROTECT 1
+#cmakedefine HAVE_ICONV 1
+#cmakedefine HAVE_PTHREAD_SETNAME_NP 1
+#cmakedefine HAVE_PTHREAD_SET_NAME_NP 1
+#cmakedefine HAVE_SEM_TIMEDWAIT 1
+#cmakedefine HAVE_GETAUXVAL 1
+#cmakedefine HAVE_POLL 1
+
+#elif __WIN32__
+#cmakedefine HAVE_STDARG_H 1
+#cmakedefine HAVE_STDDEF_H 1
+#else
+/* We may need some replacement for stdarg.h here */
+#include <stdarg.h>
+#endif /* HAVE_LIBC */
+
+/* SDL internal assertion support */
+#cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@
+
+/* Allow disabling of core subsystems */
+#cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@
+#cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@
+#cmakedefine SDL_CPUINFO_DISABLED @SDL_CPUINFO_DISABLED@
+#cmakedefine SDL_EVENTS_DISABLED @SDL_EVENTS_DISABLED@
+#cmakedefine SDL_FILE_DISABLED @SDL_FILE_DISABLED@
+#cmakedefine SDL_JOYSTICK_DISABLED @SDL_JOYSTICK_DISABLED@
+#cmakedefine SDL_HAPTIC_DISABLED @SDL_HAPTIC_DISABLED@
+#cmakedefine SDL_LOADSO_DISABLED @SDL_LOADSO_DISABLED@
+#cmakedefine SDL_RENDER_DISABLED @SDL_RENDER_DISABLED@
+#cmakedefine SDL_THREADS_DISABLED @SDL_THREADS_DISABLED@
+#cmakedefine SDL_TIMERS_DISABLED @SDL_TIMERS_DISABLED@
+#cmakedefine SDL_VIDEO_DISABLED @SDL_VIDEO_DISABLED@
+#cmakedefine SDL_POWER_DISABLED @SDL_POWER_DISABLED@
+#cmakedefine SDL_FILESYSTEM_DISABLED @SDL_FILESYSTEM_DISABLED@
+
+/* Enable various audio drivers */
+#cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@
+#cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@
+#cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@
+#cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_DISK @SDL_AUDIO_DRIVER_DISK@
+#cmakedefine SDL_AUDIO_DRIVER_DSOUND @SDL_AUDIO_DRIVER_DSOUND@
+#cmakedefine SDL_AUDIO_DRIVER_DUMMY @SDL_AUDIO_DRIVER_DUMMY@
+#cmakedefine SDL_AUDIO_DRIVER_EMSCRIPTEN @SDL_AUDIO_DRIVER_EMSCRIPTEN@
+#cmakedefine SDL_AUDIO_DRIVER_ESD @SDL_AUDIO_DRIVER_ESD@
+#cmakedefine SDL_AUDIO_DRIVER_ESD_DYNAMIC @SDL_AUDIO_DRIVER_ESD_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
+#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_HAIKU @SDL_AUDIO_DRIVER_HAIKU@
+#cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@
+#cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@
+#cmakedefine SDL_AUDIO_DRIVER_NAS_DYNAMIC @SDL_AUDIO_DRIVER_NAS_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_NETBSD @SDL_AUDIO_DRIVER_NETBSD@
+#cmakedefine SDL_AUDIO_DRIVER_OSS @SDL_AUDIO_DRIVER_OSS@
+#cmakedefine SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H @SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H@
+#cmakedefine SDL_AUDIO_DRIVER_PAUDIO @SDL_AUDIO_DRIVER_PAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_QSA @SDL_AUDIO_DRIVER_QSA@
+#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@
+#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_SUNAUDIO @SDL_AUDIO_DRIVER_SUNAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_WASAPI @SDL_AUDIO_DRIVER_WASAPI@
+#cmakedefine SDL_AUDIO_DRIVER_WINMM @SDL_AUDIO_DRIVER_WINMM@
+#cmakedefine SDL_AUDIO_DRIVER_XAUDIO2 @SDL_AUDIO_DRIVER_XAUDIO2@
+
+/* Enable various input drivers */
+#cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@
+#cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@
+#cmakedefine SDL_INPUT_TSLIB @SDL_INPUT_TSLIB@
+#cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@
+#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@
+#cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@
+#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@
+#cmakedefine SDL_JOYSTICK_DUMMY @SDL_JOYSTICK_DUMMY@
+#cmakedefine SDL_JOYSTICK_IOKIT @SDL_JOYSTICK_IOKIT@
+#cmakedefine SDL_JOYSTICK_MFI @SDL_JOYSTICK_MFI@
+#cmakedefine SDL_JOYSTICK_LINUX @SDL_JOYSTICK_LINUX@
+#cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@
+#cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@
+#cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
+#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
+#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
+#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
+#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
+#cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@
+#cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@
+#cmakedefine SDL_HAPTIC_ANDROID @SDL_HAPTIC_ANDROID@
+
+/* Enable various shared object loading systems */
+#cmakedefine SDL_LOADSO_DLOPEN @SDL_LOADSO_DLOPEN@
+#cmakedefine SDL_LOADSO_DUMMY @SDL_LOADSO_DUMMY@
+#cmakedefine SDL_LOADSO_LDG @SDL_LOADSO_LDG@
+#cmakedefine SDL_LOADSO_WINDOWS @SDL_LOADSO_WINDOWS@
+
+/* Enable various threading systems */
+#cmakedefine SDL_THREAD_PTHREAD @SDL_THREAD_PTHREAD@
+#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX@
+#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP@
+#cmakedefine SDL_THREAD_WINDOWS @SDL_THREAD_WINDOWS@
+
+/* Enable various timer systems */
+#cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@
+#cmakedefine SDL_TIMER_DUMMY @SDL_TIMER_DUMMY@
+#cmakedefine SDL_TIMER_UNIX @SDL_TIMER_UNIX@
+#cmakedefine SDL_TIMER_WINDOWS @SDL_TIMER_WINDOWS@
+#cmakedefine SDL_TIMER_WINCE @SDL_TIMER_WINCE@
+
+/* Enable various video drivers */
+#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
+#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
+#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
+#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
+#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
+#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
+#cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@
+#cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@
+#cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
+
+#cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@
+#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM@
+
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
+
+#cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
+#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON@
+#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
+#cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE @SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINERAMA @SDL_VIDEO_DRIVER_X11_XINERAMA@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 @SDL_VIDEO_DRIVER_X11_XINPUT2@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR @SDL_VIDEO_DRIVER_X11_XRANDR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER @SDL_VIDEO_DRIVER_X11_XSCRNSAVER@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XVIDMODE @SDL_VIDEO_DRIVER_X11_XVIDMODE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
+#cmakedefine SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY @SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY@
+#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@
+
+#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@
+#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@
+#cmakedefine SDL_VIDEO_RENDER_OGL @SDL_VIDEO_RENDER_OGL@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES @SDL_VIDEO_RENDER_OGL_ES@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES2 @SDL_VIDEO_RENDER_OGL_ES2@
+#cmakedefine SDL_VIDEO_RENDER_DIRECTFB @SDL_VIDEO_RENDER_DIRECTFB@
+
+/* Enable OpenGL support */
+#cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@
+#cmakedefine SDL_VIDEO_OPENGL_ES @SDL_VIDEO_OPENGL_ES@
+#cmakedefine SDL_VIDEO_OPENGL_ES2 @SDL_VIDEO_OPENGL_ES2@
+#cmakedefine SDL_VIDEO_OPENGL_BGL @SDL_VIDEO_OPENGL_BGL@
+#cmakedefine SDL_VIDEO_OPENGL_CGL @SDL_VIDEO_OPENGL_CGL@
+#cmakedefine SDL_VIDEO_OPENGL_GLX @SDL_VIDEO_OPENGL_GLX@
+#cmakedefine SDL_VIDEO_OPENGL_WGL @SDL_VIDEO_OPENGL_WGL@
+#cmakedefine SDL_VIDEO_OPENGL_EGL @SDL_VIDEO_OPENGL_EGL@
+#cmakedefine SDL_VIDEO_OPENGL_OSMESA @SDL_VIDEO_OPENGL_OSMESA@
+#cmakedefine SDL_VIDEO_OPENGL_OSMESA_DYNAMIC @SDL_VIDEO_OPENGL_OSMESA_DYNAMIC@
+
+/* Enable Vulkan support */
+#cmakedefine SDL_VIDEO_VULKAN @SDL_VIDEO_VULKAN@
+
+/* Enable system power support */
+#cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
+#cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@
+#cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@
+#cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@
+#cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@
+#cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@
+#cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
+
+/* Enable system filesystem support */
+#cmakedefine SDL_FILESYSTEM_ANDROID @SDL_FILESYSTEM_ANDROID@
+#cmakedefine SDL_FILESYSTEM_HAIKU @SDL_FILESYSTEM_HAIKU@
+#cmakedefine SDL_FILESYSTEM_COCOA @SDL_FILESYSTEM_COCOA@
+#cmakedefine SDL_FILESYSTEM_DUMMY @SDL_FILESYSTEM_DUMMY@
+#cmakedefine SDL_FILESYSTEM_UNIX @SDL_FILESYSTEM_UNIX@
+#cmakedefine SDL_FILESYSTEM_WINDOWS @SDL_FILESYSTEM_WINDOWS@
+#cmakedefine SDL_FILESYSTEM_EMSCRIPTEN @SDL_FILESYSTEM_EMSCRIPTEN@
+
+/* Enable assembly routines */
+#cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@
+#cmakedefine SDL_ALTIVEC_BLITTERS @SDL_ALTIVEC_BLITTERS@
+
+/* Enable dynamic libsamplerate support */
+#cmakedefine SDL_LIBSAMPLERATE_DYNAMIC @SDL_LIBSAMPLERATE_DYNAMIC@
+
+/* Platform specific definitions */
+#if !defined(__WIN32__)
+# if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
+typedef unsigned int size_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+# endif /* if (stdint.h isn't available) */
+#else /* __WIN32__ */
+# if !defined(_STDINT_H_) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
+# if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H 1
+# elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+# ifndef _UINTPTR_T_DEFINED
+# ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+# else
+typedef unsigned int uintptr_t;
+# endif
+#define _UINTPTR_T_DEFINED
+# endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+# if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+# endif
+# if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+# endif
+# else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+# ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+# endif
+typedef unsigned int uintptr_t;
+# endif /* __GNUC__ || _MSC_VER */
+# endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+#endif /* __WIN32__ */
+
+#endif /* SDL_config_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config.h.in b/Client/ThirdParty/SDL2/SDL_config.h.in
new file mode 100644
index 0000000..8b3d208
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config.h.in
@@ -0,0 +1,389 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_h_
+#define SDL_config_h_
+
+/**
+ * \file SDL_config.h.in
+ *
+ * This is a set of defines to configure the SDL features
+ */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+/* Make sure that this isn't included by Visual C++ */
+#ifdef _MSC_VER
+#error You should run hg revert SDL_config.h
+#endif
+
+/* C language features */
+#undef const
+#undef inline
+#undef volatile
+
+/* C datatypes */
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+#undef HAVE_GCC_ATOMICS
+#undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET
+
+#undef HAVE_DDRAW_H
+#undef HAVE_DINPUT_H
+#undef HAVE_DSOUND_H
+#undef HAVE_DXGI_H
+#undef HAVE_XINPUT_H
+#undef HAVE_XINPUT_GAMEPAD_EX
+#undef HAVE_XINPUT_STATE_EX
+
+/* Comment this if you want to build without any C library requirements */
+#undef HAVE_LIBC
+#if HAVE_LIBC
+
+/* Useful headers */
+#undef HAVE_ALLOCA_H
+#undef HAVE_SYS_TYPES_H
+#undef HAVE_STDIO_H
+#undef STDC_HEADERS
+#undef HAVE_STDLIB_H
+#undef HAVE_STDARG_H
+#undef HAVE_MALLOC_H
+#undef HAVE_MEMORY_H
+#undef HAVE_STRING_H
+#undef HAVE_STRINGS_H
+#undef HAVE_WCHAR_H
+#undef HAVE_INTTYPES_H
+#undef HAVE_STDINT_H
+#undef HAVE_CTYPE_H
+#undef HAVE_MATH_H
+#undef HAVE_ICONV_H
+#undef HAVE_SIGNAL_H
+#undef HAVE_ALTIVEC_H
+#undef HAVE_PTHREAD_NP_H
+#undef HAVE_LIBUDEV_H
+#undef HAVE_DBUS_DBUS_H
+#undef HAVE_IBUS_IBUS_H
+#undef HAVE_FCITX_FRONTEND_H
+#undef HAVE_LIBSAMPLERATE_H
+
+/* C library functions */
+#undef HAVE_MALLOC
+#undef HAVE_CALLOC
+#undef HAVE_REALLOC
+#undef HAVE_FREE
+#undef HAVE_ALLOCA
+#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */
+#undef HAVE_GETENV
+#undef HAVE_SETENV
+#undef HAVE_PUTENV
+#undef HAVE_UNSETENV
+#endif
+#undef HAVE_QSORT
+#undef HAVE_ABS
+#undef HAVE_BCOPY
+#undef HAVE_MEMSET
+#undef HAVE_MEMCPY
+#undef HAVE_MEMMOVE
+#undef HAVE_MEMCMP
+#undef HAVE_WCSLEN
+#undef HAVE_WCSLCPY
+#undef HAVE_WCSLCAT
+#undef HAVE_WCSCMP
+#undef HAVE_STRLEN
+#undef HAVE_STRLCPY
+#undef HAVE_STRLCAT
+#undef HAVE_STRDUP
+#undef HAVE__STRREV
+#undef HAVE__STRUPR
+#undef HAVE__STRLWR
+#undef HAVE_INDEX
+#undef HAVE_RINDEX
+#undef HAVE_STRCHR
+#undef HAVE_STRRCHR
+#undef HAVE_STRSTR
+#undef HAVE_ITOA
+#undef HAVE__LTOA
+#undef HAVE__UITOA
+#undef HAVE__ULTOA
+#undef HAVE_STRTOL
+#undef HAVE_STRTOUL
+#undef HAVE__I64TOA
+#undef HAVE__UI64TOA
+#undef HAVE_STRTOLL
+#undef HAVE_STRTOULL
+#undef HAVE_STRTOD
+#undef HAVE_ATOI
+#undef HAVE_ATOF
+#undef HAVE_STRCMP
+#undef HAVE_STRNCMP
+#undef HAVE__STRICMP
+#undef HAVE_STRCASECMP
+#undef HAVE__STRNICMP
+#undef HAVE_STRNCASECMP
+#undef HAVE_SSCANF
+#undef HAVE_VSSCANF
+#undef HAVE_SNPRINTF
+#undef HAVE_VSNPRINTF
+#undef HAVE_M_PI
+#undef HAVE_ATAN
+#undef HAVE_ATAN2
+#undef HAVE_ACOS
+#undef HAVE_ASIN
+#undef HAVE_CEIL
+#undef HAVE_COPYSIGN
+#undef HAVE_COS
+#undef HAVE_COSF
+#undef HAVE_FABS
+#undef HAVE_FLOOR
+#undef HAVE_LOG
+#undef HAVE_POW
+#undef HAVE_SCALBN
+#undef HAVE_SIN
+#undef HAVE_SINF
+#undef HAVE_SQRT
+#undef HAVE_SQRTF
+#undef HAVE_TAN
+#undef HAVE_TANF
+#undef HAVE_FOPEN64
+#undef HAVE_FSEEKO
+#undef HAVE_FSEEKO64
+#undef HAVE_SIGACTION
+#undef HAVE_SA_SIGACTION
+#undef HAVE_SETJMP
+#undef HAVE_NANOSLEEP
+#undef HAVE_SYSCONF
+#undef HAVE_SYSCTLBYNAME
+#undef HAVE_CLOCK_GETTIME
+#undef HAVE_GETPAGESIZE
+#undef HAVE_MPROTECT
+#undef HAVE_ICONV
+#undef HAVE_PTHREAD_SETNAME_NP
+#undef HAVE_PTHREAD_SET_NAME_NP
+#undef HAVE_SEM_TIMEDWAIT
+#undef HAVE_GETAUXVAL
+#undef HAVE_POLL
+
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
+#endif /* HAVE_LIBC */
+
+/* SDL internal assertion support */
+#undef SDL_DEFAULT_ASSERT_LEVEL
+
+/* Allow disabling of core subsystems */
+#undef SDL_ATOMIC_DISABLED
+#undef SDL_AUDIO_DISABLED
+#undef SDL_CPUINFO_DISABLED
+#undef SDL_EVENTS_DISABLED
+#undef SDL_FILE_DISABLED
+#undef SDL_JOYSTICK_DISABLED
+#undef SDL_HAPTIC_DISABLED
+#undef SDL_LOADSO_DISABLED
+#undef SDL_RENDER_DISABLED
+#undef SDL_THREADS_DISABLED
+#undef SDL_TIMERS_DISABLED
+#undef SDL_VIDEO_DISABLED
+#undef SDL_POWER_DISABLED
+#undef SDL_FILESYSTEM_DISABLED
+
+/* Enable various audio drivers */
+#undef SDL_AUDIO_DRIVER_ALSA
+#undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
+#undef SDL_AUDIO_DRIVER_ANDROID
+#undef SDL_AUDIO_DRIVER_ARTS
+#undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
+#undef SDL_AUDIO_DRIVER_COREAUDIO
+#undef SDL_AUDIO_DRIVER_DISK
+#undef SDL_AUDIO_DRIVER_DSOUND
+#undef SDL_AUDIO_DRIVER_DUMMY
+#undef SDL_AUDIO_DRIVER_EMSCRIPTEN
+#undef SDL_AUDIO_DRIVER_ESD
+#undef SDL_AUDIO_DRIVER_ESD_DYNAMIC
+#undef SDL_AUDIO_DRIVER_FUSIONSOUND
+#undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
+#undef SDL_AUDIO_DRIVER_HAIKU
+#undef SDL_AUDIO_DRIVER_JACK
+#undef SDL_AUDIO_DRIVER_JACK_DYNAMIC
+#undef SDL_AUDIO_DRIVER_NACL
+#undef SDL_AUDIO_DRIVER_NAS
+#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
+#undef SDL_AUDIO_DRIVER_NETBSD
+#undef SDL_AUDIO_DRIVER_OSS
+#undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
+#undef SDL_AUDIO_DRIVER_PAUDIO
+#undef SDL_AUDIO_DRIVER_PULSEAUDIO
+#undef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC
+#undef SDL_AUDIO_DRIVER_QSA
+#undef SDL_AUDIO_DRIVER_SNDIO
+#undef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
+#undef SDL_AUDIO_DRIVER_SUNAUDIO
+#undef SDL_AUDIO_DRIVER_WASAPI
+#undef SDL_AUDIO_DRIVER_WINMM
+#undef SDL_AUDIO_DRIVER_XAUDIO2
+
+/* Enable various input drivers */
+#undef SDL_INPUT_LINUXEV
+#undef SDL_INPUT_LINUXKD
+#undef SDL_INPUT_TSLIB
+#undef SDL_JOYSTICK_HAIKU
+#undef SDL_JOYSTICK_DINPUT
+#undef SDL_JOYSTICK_XINPUT
+#undef SDL_JOYSTICK_DUMMY
+#undef SDL_JOYSTICK_IOKIT
+#undef SDL_JOYSTICK_LINUX
+#undef SDL_JOYSTICK_ANDROID
+#undef SDL_JOYSTICK_WINMM
+#undef SDL_JOYSTICK_USBHID
+#undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
+#undef SDL_JOYSTICK_EMSCRIPTEN
+#undef SDL_HAPTIC_DUMMY
+#undef SDL_HAPTIC_LINUX
+#undef SDL_HAPTIC_IOKIT
+#undef SDL_HAPTIC_DINPUT
+#undef SDL_HAPTIC_XINPUT
+
+/* Enable various shared object loading systems */
+#undef SDL_LOADSO_DLOPEN
+#undef SDL_LOADSO_DUMMY
+#undef SDL_LOADSO_LDG
+#undef SDL_LOADSO_WINDOWS
+
+/* Enable various threading systems */
+#undef SDL_THREAD_PTHREAD
+#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
+#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
+#undef SDL_THREAD_WINDOWS
+
+/* Enable various timer systems */
+#undef SDL_TIMER_HAIKU
+#undef SDL_TIMER_DUMMY
+#undef SDL_TIMER_UNIX
+#undef SDL_TIMER_WINDOWS
+
+/* Enable various video drivers */
+#undef SDL_VIDEO_DRIVER_HAIKU
+#undef SDL_VIDEO_DRIVER_COCOA
+#undef SDL_VIDEO_DRIVER_DIRECTFB
+#undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC
+#undef SDL_VIDEO_DRIVER_DUMMY
+#undef SDL_VIDEO_DRIVER_WINDOWS
+#undef SDL_VIDEO_DRIVER_WAYLAND
+#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_MIR
+#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC
+#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_X11
+#undef SDL_VIDEO_DRIVER_RPI
+#undef SDL_VIDEO_DRIVER_KMSDRM
+#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
+#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM
+#undef SDL_VIDEO_DRIVER_ANDROID
+#undef SDL_VIDEO_DRIVER_EMSCRIPTEN
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE
+#undef SDL_VIDEO_DRIVER_X11_XCURSOR
+#undef SDL_VIDEO_DRIVER_X11_XDBE
+#undef SDL_VIDEO_DRIVER_X11_XINERAMA
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+#undef SDL_VIDEO_DRIVER_X11_XRANDR
+#undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+#undef SDL_VIDEO_DRIVER_X11_XSHAPE
+#undef SDL_VIDEO_DRIVER_X11_XVIDMODE
+#undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+#undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
+#undef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+#undef SDL_VIDEO_DRIVER_NACL
+#undef SDL_VIDEO_DRIVER_VIVANTE
+#undef SDL_VIDEO_DRIVER_VIVANTE_VDK
+#undef SDL_VIDEO_DRIVER_QNX
+
+#undef SDL_VIDEO_RENDER_D3D
+#undef SDL_VIDEO_RENDER_D3D11
+#undef SDL_VIDEO_RENDER_OGL
+#undef SDL_VIDEO_RENDER_OGL_ES
+#undef SDL_VIDEO_RENDER_OGL_ES2
+#undef SDL_VIDEO_RENDER_DIRECTFB
+
+/* Enable OpenGL support */
+#undef SDL_VIDEO_OPENGL
+#undef SDL_VIDEO_OPENGL_ES
+#undef SDL_VIDEO_OPENGL_ES2
+#undef SDL_VIDEO_OPENGL_BGL
+#undef SDL_VIDEO_OPENGL_CGL
+#undef SDL_VIDEO_OPENGL_EGL
+#undef SDL_VIDEO_OPENGL_GLX
+#undef SDL_VIDEO_OPENGL_WGL
+#undef SDL_VIDEO_OPENGL_OSMESA
+#undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC
+
+/* Enable Vulkan support */
+#undef SDL_VIDEO_VULKAN
+
+/* Enable system power support */
+#undef SDL_POWER_LINUX
+#undef SDL_POWER_WINDOWS
+#undef SDL_POWER_MACOSX
+#undef SDL_POWER_HAIKU
+#undef SDL_POWER_ANDROID
+#undef SDL_POWER_EMSCRIPTEN
+#undef SDL_POWER_HARDWIRED
+
+/* Enable system filesystem support */
+#undef SDL_FILESYSTEM_HAIKU
+#undef SDL_FILESYSTEM_COCOA
+#undef SDL_FILESYSTEM_DUMMY
+#undef SDL_FILESYSTEM_UNIX
+#undef SDL_FILESYSTEM_WINDOWS
+#undef SDL_FILESYSTEM_NACL
+#undef SDL_FILESYSTEM_ANDROID
+#undef SDL_FILESYSTEM_EMSCRIPTEN
+
+/* Enable assembly routines */
+#undef SDL_ASSEMBLY_ROUTINES
+#undef SDL_ALTIVEC_BLITTERS
+
+/* Enable ime support */
+#undef SDL_USE_IME
+
+/* Enable dynamic udev support */
+#undef SDL_UDEV_DYNAMIC
+
+/* Enable dynamic libsamplerate support */
+#undef SDL_LIBSAMPLERATE_DYNAMIC
+
+#endif /* SDL_config_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_android.h b/Client/ThirdParty/SDL2/SDL_config_android.h
new file mode 100644
index 0000000..361bad8
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_android.h
@@ -0,0 +1,157 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_android_h_
+#define SDL_config_android_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/**
+ * \file SDL_config_android.h
+ *
+ * This is a configuration that can be used to build SDL for Android
+ */
+
+#include <stdarg.h>
+
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_CLOCK_GETTIME 1
+
+#define SIZEOF_VOIDP 4
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_ANDROID 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_ANDROID 1
+#define SDL_HAPTIC_ANDROID 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_ANDROID 1
+
+/* Enable OpenGL ES */
+#define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_EGL 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+
+/* Enable Vulkan support */
+/* Android does not support Vulkan in native code using the "armeabi" ABI. */
+#if defined(__ARM_ARCH) && __ARM_ARCH < 7
+#define SDL_VIDEO_VULKAN 0
+#else
+#define SDL_VIDEO_VULKAN 1
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_ANDROID 1
+
+/* Enable the filesystem driver */
+#define SDL_FILESYSTEM_ANDROID 1
+
+#endif /* SDL_config_android_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_iphoneos.h b/Client/ThirdParty/SDL2/SDL_config_iphoneos.h
new file mode 100644
index 0000000..deea030
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_iphoneos.h
@@ -0,0 +1,166 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_iphoneos_h_
+#define SDL_config_iphoneos_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+
+/* enable iPhone version of Core Audio driver */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DUMMY 1
+
+/* Enable MFi joystick support */
+#define SDL_JOYSTICK_MFI 1
+
+/* Enable Unix style SO loading */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Supported video drivers */
+#define SDL_VIDEO_DRIVER_UIKIT 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+/* enable OpenGL ES */
+#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+
+/* Enable Vulkan support */
+#if !TARGET_OS_SIMULATOR && !TARGET_CPU_ARM // Only 64-bit devices have Metal
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_UIKIT 1
+
+/* enable iPhone keyboard support */
+#define SDL_IPHONE_KEYBOARD 1
+
+/* enable iOS extended launch screen */
+#define SDL_IPHONE_LAUNCHSCREEN 1
+
+/* Set max recognized G-force from accelerometer
+ See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
+ */
+#define SDL_IPHONE_MAX_GFORCE 5.0
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+#endif /* SDL_config_iphoneos_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_macosx.h b/Client/ThirdParty/SDL2/SDL_config_macosx.h
new file mode 100644
index 0000000..9b09899
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_macosx.h
@@ -0,0 +1,197 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_macosx_h_
+#define SDL_config_macosx_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
+#include <AvailabilityMacros.h>
+
+/* This is a set of defines to configure the SDL features */
+
+#ifdef __LP64__
+ #define SIZEOF_VOIDP 8
+#else
+ #define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_IOKIT 1
+#define SDL_HAPTIC_IOKIT 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_COCOA 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#undef SDL_VIDEO_DRIVER_X11
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_XDBE 1
+#define SDL_VIDEO_DRIVER_X11_XINERAMA 1
+#define SDL_VIDEO_DRIVER_X11_XRANDR 1
+#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
+#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
+#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1
+#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
+
+#ifdef MAC_OS_X_VERSION_10_8
+/*
+ * No matter the versions targeted, this is the 10.8 or later SDK, so you have
+ * to use the external Xquartz, which is a more modern Xlib. Previous SDKs
+ * used an older Xlib.
+ */
+#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1
+#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 1
+#endif
+
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_CGL
+#define SDL_VIDEO_OPENGL_CGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_GLX
+#define SDL_VIDEO_OPENGL_GLX 1
+#endif
+
+/* Enable Vulkan support */
+/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures with 10.11+ */
+#if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_MACOSX 1
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+/* Enable assembly routines */
+#define SDL_ASSEMBLY_ROUTINES 1
+#ifdef __ppc__
+#define SDL_ALTIVEC_BLITTERS 1
+#endif
+
+#endif /* SDL_config_macosx_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_macosx.h.orig b/Client/ThirdParty/SDL2/SDL_config_macosx.h.orig
new file mode 100644
index 0000000..f03f1ae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_macosx.h.orig
@@ -0,0 +1,197 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_macosx_h_
+#define SDL_config_macosx_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
+#include <AvailabilityMacros.h>
+
+/* This is a set of defines to configure the SDL features */
+
+#ifdef __LP64__
+ #define SIZEOF_VOIDP 8
+#else
+ #define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_IOKIT 1
+#define SDL_HAPTIC_IOKIT 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_COCOA 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#undef SDL_VIDEO_DRIVER_X11
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_XDBE 1
+#define SDL_VIDEO_DRIVER_X11_XINERAMA 1
+#define SDL_VIDEO_DRIVER_X11_XRANDR 1
+#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
+#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
+#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1
+#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
+
+#ifdef MAC_OS_X_VERSION_10_8
+/*
+ * No matter the versions targeted, this is the 10.8 or later SDK, so you have
+ * to use the external Xquartz, which is a more modern Xlib. Previous SDKs
+ * used an older Xlib.
+ */
+#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1
+#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 1
+#endif
+
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_CGL
+#define SDL_VIDEO_OPENGL_CGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_GLX
+#define SDL_VIDEO_OPENGL_GLX 1
+#endif
+
+/* Enable Vulkan support */
+/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures and 10.11+ */
+#if TARGET_CPU_X86_64
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_MACOSX 1
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+/* Enable assembly routines */
+#define SDL_ASSEMBLY_ROUTINES 1
+#ifdef __ppc__
+#define SDL_ALTIVEC_BLITTERS 1
+#endif
+
+#endif /* SDL_config_macosx_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_minimal.h b/Client/ThirdParty/SDL2/SDL_config_minimal.h
new file mode 100644
index 0000000..3112700
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_minimal.h
@@ -0,0 +1,82 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_minimal_h_
+#define SDL_config_minimal_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/**
+ * \file SDL_config_minimal.h
+ *
+ * This is the minimal configuration that can be used to build SDL.
+ */
+
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+
+/* Most everything except Visual Studio 2008 and earlier has stdint.h now */
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+/* Here are some reasonable defaults */
+typedef unsigned int size_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+#else
+#define HAVE_STDINT_H 1
+#endif /* Visual Studio 2008 */
+
+#ifdef __GNUC__
+#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1
+#endif
+
+/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable the stub joystick driver (src/joystick/dummy/\*.c) */
+#define SDL_JOYSTICK_DISABLED 1
+
+/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED 1
+
+/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */
+#define SDL_LOADSO_DISABLED 1
+
+/* Enable the stub thread support (src/thread/generic/\*.c) */
+#define SDL_THREADS_DISABLED 1
+
+/* Enable the stub timer support (src/timer/dummy/\*.c) */
+#define SDL_TIMERS_DISABLED 1
+
+/* Enable the dummy video driver (src/video/dummy/\*.c) */
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */
+#define SDL_FILESYSTEM_DUMMY 1
+
+#endif /* SDL_config_minimal_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_pandora.h b/Client/ThirdParty/SDL2/SDL_config_pandora.h
new file mode 100644
index 0000000..ea62fe5
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_pandora.h
@@ -0,0 +1,128 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_pandora_h_
+#define SDL_config_pandora_h_
+#define SDL_config_h_
+
+/* This is a set of defines to configure the SDL features */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#define SDL_BYTEORDER 1234
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_STRLEN 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+
+#define SDL_AUDIO_DRIVER_DUMMY 1
+#define SDL_AUDIO_DRIVER_OSS 1
+
+#define SDL_INPUT_LINUXEV 1
+#define SDL_INPUT_TSLIB 1
+#define SDL_JOYSTICK_LINUX 1
+#define SDL_HAPTIC_LINUX 1
+
+#define SDL_LOADSO_DLOPEN 1
+
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1
+
+#define SDL_TIMER_UNIX 1
+#define SDL_FILESYSTEM_UNIX 1
+
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_X11 1
+#define SDL_VIDEO_DRIVER_PANDORA 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_OPENGL_ES 1
+
+#endif /* SDL_config_pandora_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_psp.h b/Client/ThirdParty/SDL2/SDL_config_psp.h
new file mode 100644
index 0000000..28efb4c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_psp.h
@@ -0,0 +1,144 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_psp_h_
+#define SDL_config_psp_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+
+
+#ifdef __GNUC__
+#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1
+#endif
+
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+/* #define HAVE_SYSCONF 1 */
+/* #define HAVE_SIGACTION 1 */
+
+
+/* PSP isn't that sophisticated */
+#define LACKS_SYS_MMAN_H 1
+
+/* Enable the stub thread support (src/thread/psp/\*.c) */
+#define SDL_THREAD_PSP 1
+
+/* Enable the stub timer support (src/timer/psp/\*.c) */
+#define SDL_TIMERS_PSP 1
+
+/* Enable the stub joystick driver (src/joystick/psp/\*.c) */
+#define SDL_JOYSTICK_PSP 1
+
+/* Enable the stub audio driver (src/audio/psp/\*.c) */
+#define SDL_AUDIO_DRIVER_PSP 1
+
+/* PSP video dirver */
+#define SDL_VIDEO_DRIVER_PSP 1
+
+/* PSP render dirver */
+#define SDL_VIDEO_RENDER_PSP 1
+
+#define SDL_POWER_PSP 1
+
+/* !!! FIXME: what does PSP do for filesystem stuff? */
+#define SDL_FILESYSTEM_DUMMY 1
+
+/* PSP doesn't have haptic device (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED 1
+
+/* PSP can't load shared object (src/loadso/dummy/\*.c) */
+#define SDL_LOADSO_DISABLED 1
+
+
+#endif /* SDL_config_psp_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_windows.h b/Client/ThirdParty/SDL2/SDL_config_windows.h
new file mode 100644
index 0000000..2456c84
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_windows.h
@@ -0,0 +1,225 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_windows_h_
+#define SDL_config_windows_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This is a set of defines to configure the SDL features */
+
+#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
+#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H 1
+#elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#endif
+#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#endif
+#else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#endif
+typedef unsigned int uintptr_t;
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
+
+#define HAVE_DDRAW_H 1
+#define HAVE_DINPUT_H 1
+#define HAVE_DSOUND_H 1
+#define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
+
+/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
+#ifdef HAVE_LIBC
+/* Useful headers */
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE__STRREV 1
+#define HAVE__STRUPR 1
+#define HAVE__STRLWR 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE__LTOA 1
+#define HAVE__ULTOA 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE__STRICMP 1
+#define HAVE__STRNICMP 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#if _MSC_VER >= 1800
+#define HAVE_STRTOLL 1
+#define HAVE_VSSCANF 1
+#define HAVE_COPYSIGN 1
+#define HAVE_SCALBN 1
+#endif
+#if !defined(_MSC_VER) || defined(_USE_MATH_DEFINES)
+#define HAVE_M_PI 1
+#endif
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#endif
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_WASAPI 1
+#define SDL_AUDIO_DRIVER_DSOUND 1
+#define SDL_AUDIO_DRIVER_XAUDIO2 0
+#define SDL_AUDIO_DRIVER_WINMM 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_DINPUT 1
+#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_DINPUT 1
+#define SDL_HAPTIC_XINPUT 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_WINDOWS 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_WINDOWS 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_WINDOWS 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_WINDOWS 1
+
+#ifndef SDL_VIDEO_RENDER_D3D
+#define SDL_VIDEO_RENDER_D3D 1
+#endif
+#ifndef SDL_VIDEO_RENDER_D3D11
+#define SDL_VIDEO_RENDER_D3D11 0
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_WGL
+#define SDL_VIDEO_OPENGL_WGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_OPENGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_EGL
+#define SDL_VIDEO_OPENGL_EGL 1
+#endif
+
+/* Enable Vulkan support */
+#define SDL_VIDEO_VULKAN 1
+
+/* Enable system power support */
+#define SDL_POWER_WINDOWS 1
+
+/* Enable filesystem support */
+#define SDL_FILESYSTEM_WINDOWS 1
+
+/* Enable assembly routines (Win64 doesn't have inline asm) */
+#ifndef _WIN64
+#define SDL_ASSEMBLY_ROUTINES 1
+#endif
+
+#endif /* SDL_config_windows_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_winrt.h b/Client/ThirdParty/SDL2/SDL_config_winrt.h
new file mode 100644
index 0000000..24f9e17
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_winrt.h
@@ -0,0 +1,215 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_winrt_h_
+#define SDL_config_winrt_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* Make sure the Windows SDK's NTDDI_VERSION macro gets defined. This is used
+ by SDL to determine which version of the Windows SDK is being used.
+*/
+#include <sdkddkver.h>
+
+/* Define possibly-undefined NTDDI values (used when compiling SDL against
+ older versions of the Windows SDK.
+*/
+#ifndef NTDDI_WINBLUE
+#define NTDDI_WINBLUE 0x06030000
+#endif
+#ifndef NTDDI_WIN10
+#define NTDDI_WIN10 0x0A000000
+#endif
+
+/* This is a set of defines to configure the SDL features */
+
+#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
+#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H 1
+#elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#endif
+#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#endif
+#else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#endif
+typedef unsigned int uintptr_t;
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define HAVE_DXGI_H 1
+#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+#define HAVE_XINPUT_H 1
+#endif
+#define HAVE_LIBC 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE__STRREV 1
+#define HAVE__STRUPR 1
+//#define HAVE__STRLWR 1 // TODO, WinRT: consider using _strlwr_s instead
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+//#define HAVE_ITOA 1 // TODO, WinRT: consider using _itoa_s instead
+//#define HAVE__LTOA 1 // TODO, WinRT: consider using _ltoa_s instead
+//#define HAVE__ULTOA 1 // TODO, WinRT: consider using _ultoa_s instead
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+//#define HAVE_STRTOLL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE__STRICMP 1
+#define HAVE__STRNICMP 1
+#define HAVE_VSNPRINTF 1
+//#define HAVE_SSCANF 1 // TODO, WinRT: consider using sscanf_s instead
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_CEIL 1
+#define HAVE__COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+//#define HAVE_SCALBN 1
+#define HAVE__SCALB 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE__FSEEKI64 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_XAUDIO2 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+#define SDL_JOYSTICK_DISABLED 1
+#define SDL_HAPTIC_DISABLED 1
+#else
+#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_XINPUT 1
+#endif
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_WINDOWS 1
+
+/* Enable various threading systems */
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
+#define SDL_THREAD_WINDOWS 1
+#else
+/* WinRT on Windows 8.0 and Windows Phone 8.0 don't support CreateThread() */
+#define SDL_THREAD_STDCPP 1
+#endif
+
+/* Enable various timer systems */
+#define SDL_TIMER_WINDOWS 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_WINRT 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+/* Enable OpenGL ES 2.0 (via a modified ANGLE library) */
+#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_EGL 1
+
+/* Enable appropriate renderer(s) */
+#define SDL_VIDEO_RENDER_D3D11 1
+
+#if SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_WINRT 1
+
+/* Enable assembly routines (Win64 doesn't have inline asm) */
+#ifndef _WIN64
+#define SDL_ASSEMBLY_ROUTINES 1
+#endif
+
+#endif /* SDL_config_winrt_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_config_wiz.h b/Client/ThirdParty/SDL2/SDL_config_wiz.h
new file mode 100644
index 0000000..5bb845a
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_config_wiz.h
@@ -0,0 +1,121 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_wiz_h_
+#define SDL_config_wiz_h_
+#define SDL_config_h_
+
+/* This is a set of defines to configure the SDL features */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+#define SDL_BYTEORDER 1234
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_STRLEN 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_POW 1
+
+#define SDL_AUDIO_DRIVER_DUMMY 1
+#define SDL_AUDIO_DRIVER_OSS 1
+
+#define SDL_INPUT_LINUXEV 1
+#define SDL_INPUT_TSLIB 1
+#define SDL_JOYSTICK_LINUX 1
+#define SDL_HAPTIC_LINUX 1
+
+#define SDL_LOADSO_DLOPEN 1
+
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1
+
+#define SDL_TIMER_UNIX 1
+
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_PANDORA 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_OPENGL_ES 1
+
+#endif /* SDL_config_wiz_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_copying.h b/Client/ThirdParty/SDL2/SDL_copying.h
new file mode 100644
index 0000000..8f60af6
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_copying.h
@@ -0,0 +1,20 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
diff --git a/Client/ThirdParty/SDL2/SDL_cpuinfo.h b/Client/ThirdParty/SDL2/SDL_cpuinfo.h
new file mode 100644
index 0000000..4401c37
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_cpuinfo.h
@@ -0,0 +1,524 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_cpuinfo.h
+ *
+ * CPU feature detection for SDL.
+ */
+
+#ifndef SDL_cpuinfo_h_
+#define SDL_cpuinfo_h_
+
+#include "SDL_stdinc.h"
+
+/* Need to do this here because intrin.h has C++ code in it */
+/* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64))
+#ifdef __clang__
+/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
+ so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
+
+#ifndef __PRFCHWINTRIN_H
+#define __PRFCHWINTRIN_H
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+#endif /* __PRFCHWINTRIN_H */
+#endif /* __clang__ */
+#include <intrin.h>
+#ifndef _WIN64
+#ifndef __MMX__
+#define __MMX__
+#endif
+#ifndef __3dNOW__
+#define __3dNOW__
+#endif
+#endif
+#ifndef __SSE__
+#define __SSE__
+#endif
+#ifndef __SSE2__
+#define __SSE2__
+#endif
+#elif defined(__MINGW64_VERSION_MAJOR)
+#include <intrin.h>
+#if !defined(SDL_DISABLE_ARM_NEON_H) && defined(__ARM_NEON)
+# include <arm_neon.h>
+#endif
+#else
+/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */
+#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H)
+#include <altivec.h>
+#endif
+#if !defined(SDL_DISABLE_ARM_NEON_H)
+# if defined(__ARM_NEON)
+# include <arm_neon.h>
+# elif defined(__WINDOWS__) || defined(__WINRT__)
+/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */
+# if defined(_M_ARM)
+# include <armintr.h>
+# include <arm_neon.h>
+# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
+# endif
+# if defined (_M_ARM64)
+# include <arm64intr.h>
+# include <arm64_neon.h>
+# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
+# endif
+# endif
+#endif
+#endif /* compiler version */
+
+#if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
+#include <mm3dnow.h>
+#endif
+#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
+#include <immintrin.h>
+#else
+#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H)
+#include <mmintrin.h>
+#endif
+#if defined(__SSE__) && !defined(SDL_DISABLE_XMMINTRIN_H)
+#include <xmmintrin.h>
+#endif
+#if defined(__SSE2__) && !defined(SDL_DISABLE_EMMINTRIN_H)
+#include <emmintrin.h>
+#endif
+#if defined(__SSE3__) && !defined(SDL_DISABLE_PMMINTRIN_H)
+#include <pmmintrin.h>
+#endif
+#endif /* HAVE_IMMINTRIN_H */
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This is a guess for the cacheline size used for padding.
+ * Most x86 processors have a 64 byte cache line.
+ * The 64-bit PowerPC processors have a 128 byte cache line.
+ * We'll use the larger value to be generally safe.
+ */
+#define SDL_CACHELINE_SIZE 128
+
+/**
+ * Get the number of CPU cores available.
+ *
+ * \returns the total number of logical CPU cores. On CPUs that include
+ * technologies such as hyperthreading, the number of logical cores
+ * may be more than the number of physical cores.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GetCPUCount(void);
+
+/**
+ * Determine the L1 cache line size of the CPU.
+ *
+ * This is useful for determining multi-threaded structure padding or SIMD
+ * prefetch sizes.
+ *
+ * \returns the L1 cache line size of the CPU, in bytes.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GetCPUCacheLineSize(void);
+
+/**
+ * Determine whether the CPU has the RDTSC instruction.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has the RDTSC instruction or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(void);
+
+/**
+ * Determine whether the CPU has AltiVec features.
+ *
+ * This always returns false on CPUs that aren't using PowerPC instruction
+ * sets.
+ *
+ * \returns SDL_TRUE if the CPU has AltiVec features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void);
+
+/**
+ * Determine whether the CPU has MMX features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has MMX features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void);
+
+/**
+ * Determine whether the CPU has 3DNow! features.
+ *
+ * This always returns false on CPUs that aren't using AMD instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has 3DNow! features or SDL_FALSE if not.
+ *
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(void);
+
+/**
+ * Determine whether the CPU has SSE features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void);
+
+/**
+ * Determine whether the CPU has SSE2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE2 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void);
+
+/**
+ * Determine whether the CPU has SSE3 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE3 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE3(void);
+
+/**
+ * Determine whether the CPU has SSE4.1 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE4.1 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void);
+
+/**
+ * Determine whether the CPU has SSE4.2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE4.2 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void);
+
+/**
+ * Determine whether the CPU has AVX features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void);
+
+/**
+ * Determine whether the CPU has AVX2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX2 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
+
+/**
+ * Determine whether the CPU has AVX-512F (foundation) features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX-512F features or SDL_FALSE if not.
+ *
+ * \sa SDL_HasAVX
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
+
+/**
+ * Determine whether the CPU has ARM SIMD (ARMv6) features.
+ *
+ * This is different from ARM NEON, which is a different instruction set.
+ *
+ * This always returns false on CPUs that aren't using ARM instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has ARM SIMD features or SDL_FALSE if not.
+ *
+ * \sa SDL_HasNEON
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void);
+
+/**
+ * Determine whether the CPU has NEON (ARM SIMD) features.
+ *
+ * This always returns false on CPUs that aren't using ARM instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has ARM NEON features or SDL_FALSE if not.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
+
+/**
+ * Get the amount of RAM configured in the system.
+ *
+ * \returns the amount of RAM configured in the system in MB.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
+
+/**
+ * Report the alignment this system needs for SIMD allocations.
+ *
+ * This will return the minimum number of bytes to which a pointer must be
+ * aligned to be compatible with SIMD instructions on the current machine. For
+ * example, if the machine supports SSE only, it will return 16, but if it
+ * supports AVX-512F, it'll return 64 (etc). This only reports values for
+ * instruction sets SDL knows about, so if your SDL build doesn't have
+ * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and
+ * not 64 for the AVX-512 instructions that exist but SDL doesn't know about.
+ * Plan accordingly.
+ *
+ * \returns the alignment in bytes needed for available, known SIMD
+ * instructions.
+ */
+extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void);
+
+/**
+ * Allocate memory in a SIMD-friendly way.
+ *
+ * This will allocate a block of memory that is suitable for use with SIMD
+ * instructions. Specifically, it will be properly aligned and padded for the
+ * system's supported vector instructions.
+ *
+ * The memory returned will be padded such that it is safe to read or write an
+ * incomplete vector at the end of the memory block. This can be useful so you
+ * don't have to drop back to a scalar fallback at the end of your SIMD
+ * processing loop to deal with the final elements without overflowing the
+ * allocated buffer.
+ *
+ * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() or
+ * delete[], etc.
+ *
+ * Note that SDL will only deal with SIMD instruction sets it is aware of; for
+ * example, SDL 2.0.8 knows that SSE wants 16-byte vectors (SDL_HasSSE()), and
+ * AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't know that AVX-512 wants
+ * 64. To be clear: if you can't decide to use an instruction set with an
+ * SDL_Has*() function, don't use that instruction set with memory allocated
+ * through here.
+ *
+ * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't
+ * out of memory, but you are not allowed to dereference it (because you only
+ * own zero bytes of that buffer).
+ *
+ * \param len The length, in bytes, of the block to allocate. The actual
+ * allocated block might be larger due to padding, etc.
+ * \returns a pointer to thenewly-allocated block, NULL if out of memory.
+ *
+ * \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDRealloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
+
+/**
+ * Reallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
+ * SDL_malloc, memalign, new[], etc.
+ *
+ * \param mem The pointer obtained from SDL_SIMDAlloc. This function also
+ * accepts NULL, at which point this function is the same as
+ * calling SDL_SIMDAlloc with a NULL pointer.
+ * \param len The length, in bytes, of the block to allocated. The actual
+ * allocated block might be larger due to padding, etc. Passing 0
+ * will return a non-NULL pointer, assuming the system isn't out of
+ * memory.
+ * \returns a pointer to the newly-reallocated block, NULL if out of memory.
+ *
+ * \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, const size_t len);
+
+/**
+ * Deallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc() or SDL_SIMDRealloc(). It can't be used on pointers from
+ * malloc, realloc, SDL_malloc, memalign, new[], etc.
+ *
+ * However, SDL_SIMDFree(NULL) is a legal no-op.
+ *
+ * The memory pointed to by `ptr` is no longer valid for access upon return,
+ * and may be returned to the system or reused by a future allocation. The
+ * pointer passed to this function is no longer safe to dereference once this
+ * function returns, and should be discarded.
+ *
+ * \param ptr The pointer, returned from SDL_SIMDAlloc or SDL_SIMDRealloc, to
+ * deallocate. NULL is a legal no-op.
+ *
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDRealloc
+ */
+extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_cpuinfo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_egl.h b/Client/ThirdParty/SDL2/SDL_egl.h
new file mode 100644
index 0000000..223357e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_egl.h
@@ -0,0 +1,1676 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_egl.h
+ *
+ * This is a simple file to encapsulate the EGL API headers.
+ */
+#if !defined(_MSC_VER) && !defined(__ANDROID__)
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#else /* _MSC_VER */
+
+/* EGL headers for Visual Studio */
+
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+*
+* $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+*
+* Adopters may modify this file to suit their platform. Adopters are
+* encouraged to submit platform specific modifications to the Khronos
+* group so that they can be included in future versions of this file.
+* Please submit changes by sending them to the public Khronos Bugzilla
+* (http://khronos.org/bugzilla) by filing a bug against product
+* "Khronos (general)" component "Registry".
+*
+* A predefined template which fills in some of the bug fields can be
+* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+* must create a Bugzilla login first.
+*
+*
+* See the Implementer's Guidelines for information about where this file
+* should be located on your system and for more details of its use:
+* http://www.khronos.org/registry/implementers_guide.pdf
+*
+* This file should be included as
+* #include <KHR/khrplatform.h>
+* by Khronos client API header files that use its types and defines.
+*
+* The types in khrplatform.h should only be used to define API-specific types.
+*
+* Types defined in khrplatform.h:
+* khronos_int8_t signed 8 bit
+* khronos_uint8_t unsigned 8 bit
+* khronos_int16_t signed 16 bit
+* khronos_uint16_t unsigned 16 bit
+* khronos_int32_t signed 32 bit
+* khronos_uint32_t unsigned 32 bit
+* khronos_int64_t signed 64 bit
+* khronos_uint64_t unsigned 64 bit
+* khronos_intptr_t signed same number of bits as a pointer
+* khronos_uintptr_t unsigned same number of bits as a pointer
+* khronos_ssize_t signed size
+* khronos_usize_t unsigned size
+* khronos_float_t signed 32 bit floating point
+* khronos_time_ns_t unsigned 64 bit time in nanoseconds
+* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+* nanoseconds
+* khronos_stime_nanoseconds_t signed time interval in nanoseconds
+* khronos_boolean_enum_t enumerated boolean type. This should
+* only be used as a base type when a client API's boolean type is
+* an enum. Client APIs which use an integer or other type for
+* booleans cannot use this as the base type for their boolean.
+*
+* Tokens defined in khrplatform.h:
+*
+* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+*
+* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+*
+* Calling convention macros defined in this file:
+* KHRONOS_APICALL
+* KHRONOS_APIENTRY
+* KHRONOS_APIATTRIBUTES
+*
+* These may be used in function prototypes as:
+*
+* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+* int arg1,
+* int arg2) KHRONOS_APIATTRIBUTES;
+*/
+
+/*-------------------------------------------------------------------------
+* Definition of KHRONOS_APICALL
+*-------------------------------------------------------------------------
+* This precedes the return type of the function in the function prototype.
+*/
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(SDL_VIDEO_STATIC_ANGLE)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+* Definition of KHRONOS_APIENTRY
+*-------------------------------------------------------------------------
+* This follows the return type of the function and precedes the function
+* name in the function prototype.
+*/
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+/* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+* Definition of KHRONOS_APIATTRIBUTES
+*-------------------------------------------------------------------------
+* This follows the closing parenthesis of the function prototype arguments.
+*/
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+* basic type definitions
+*-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+* Using <stdint.h>
+*/
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+* Using <inttypes.h>
+*/
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+* Win32
+*/
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+* Sun or Digital
+*/
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+* Hypothetical platform with no float or int64 support
+*/
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+* Generic fallback
+*/
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+* Types that are (so far) the same on all platforms
+*/
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+* Types that differ between LLP64 and LP64 architectures - in LLP64,
+* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+* to be the only LLP64 architecture in current use.
+*/
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+* Float type
+*/
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+*
+* These types can be used to represent a time interval in nanoseconds or
+* an absolute Unadjusted System Time. Unadjusted System Time is the number
+* of nanoseconds since some arbitrary system event (e.g. since the last
+* time the system booted). The Unadjusted System Time is an unsigned
+* 64 bit value that wraps back to 0 every 584 years. Time intervals
+* may be either signed or unsigned.
+*/
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+* Dummy value used to pad enum types to 32 bits.
+*/
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+* Enumerated boolean type
+*
+* Values other than zero should be considered to be true. Therefore
+* comparisons should not be made against KHRONOS_TRUE.
+*/
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
+
+
+#ifndef __eglplatform_h_
+#define __eglplatform_h_
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+* $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+*
+* Adopters may modify khrplatform.h and this file to suit their platform.
+* You are encouraged to submit all modifications to the Khronos group so that
+* they can be included in future versions of this file. Please submit changes
+* by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+* by filing a bug against product "EGL" component "Registry".
+*/
+
+/*#include <KHR/khrplatform.h>*/
+
+/* Macros used in EGL function prototype declarations.
+*
+* EGL functions should be prototyped as:
+*
+* EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+* typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+*
+* KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+*/
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+* are aliases of window-system-dependent types, such as X Display * or
+* Windows Device Context. They must be defined in platform-specific
+* code below. The EGL-prefixed versions of Native*Type are the same
+* types, renamed in EGL 1.3 so all types in the API start with "EGL".
+*
+* Khronos STRONGLY RECOMMENDS that you use the default definitions
+* provided below, since these changes affect both binary and source
+* portability of applications using EGL running on different EGL
+* implementations.
+*/
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+
+#if __WINRT__
+#include <Unknwn.h>
+typedef IUnknown * EGLNativeWindowType;
+typedef IUnknown * EGLNativePixmapType;
+typedef IUnknown * EGLNativeDisplayType;
+#else
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND EGLNativeWindowType;
+#endif
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+
+typedef int EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(WL_EGL_PLATFORM)
+
+typedef struct wl_display *EGLNativeDisplayType;
+typedef struct wl_egl_pixmap *EGLNativePixmapType;
+typedef struct wl_egl_window *EGLNativeWindowType;
+
+#elif defined(__GBM__)
+
+typedef struct gbm_device *EGLNativeDisplayType;
+typedef struct gbm_bo *EGLNativePixmapType;
+typedef void *EGLNativeWindowType;
+
+#elif defined(__ANDROID__) /* Android */
+
+struct ANativeWindow;
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow *EGLNativeWindowType;
+typedef struct egl_native_pixmap_t *EGLNativePixmapType;
+typedef void *EGLNativeDisplayType;
+
+#elif defined(MIR_EGL_PLATFORM)
+
+#include <mir_toolkit/mir_client_library.h>
+typedef MirEGLNativeDisplayType EGLNativeDisplayType;
+typedef void *EGLNativePixmapType;
+typedef MirEGLNativeWindowType EGLNativeWindowType;
+
+#elif defined(__unix__)
+
+#ifdef MESA_EGL_NO_X11_HEADERS
+
+typedef void *EGLNativeDisplayType;
+typedef khronos_uintptr_t EGLNativePixmapType;
+typedef khronos_uintptr_t EGLNativeWindowType;
+
+#else
+
+/* X11 (tentative) */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+
+#endif /* MESA_EGL_NO_X11_HEADERS */
+
+#else
+#error "Platform not recognized"
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType NativePixmapType;
+typedef EGLNativeWindowType NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+* all legal attribute names and values passed into and out of EGL, whether
+* their type is boolean, bitmask, enumerant (symbolic constant), integer,
+* handle, or other. While in general a 32-bit integer will suffice, if
+* handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+* integer type.
+*/
+typedef khronos_int32_t EGLint;
+
+#endif /* __eglplatform_h */
+
+#ifndef __egl_h_
+#define __egl_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
+*/
+
+/*#include <EGL/eglplatform.h>*/
+
+/* Generated on date 20150623 */
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_VERSION_1_0
+#define EGL_VERSION_1_0 1
+typedef unsigned int EGLBoolean;
+typedef void *EGLDisplay;
+typedef void *EGLConfig;
+typedef void *EGLSurface;
+typedef void *EGLContext;
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300A
+#define EGL_BAD_NATIVE_WINDOW 0x300B
+#define EGL_BAD_PARAMETER 0x300C
+#define EGL_BAD_SURFACE 0x300D
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_BUFFER_SIZE 0x3020
+#define EGL_CONFIG_CAVEAT 0x3027
+#define EGL_CONFIG_ID 0x3028
+#define EGL_CORE_NATIVE_ENGINE 0x305B
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_DONT_CARE ((EGLint)-1)
+#define EGL_DRAW 0x3059
+#define EGL_EXTENSIONS 0x3055
+#define EGL_FALSE 0
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_HEIGHT 0x3056
+#define EGL_LARGEST_PBUFFER 0x3058
+#define EGL_LEVEL 0x3029
+#define EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define EGL_MAX_PBUFFER_PIXELS 0x302B
+#define EGL_MAX_PBUFFER_WIDTH 0x302C
+#define EGL_NATIVE_RENDERABLE 0x302D
+#define EGL_NATIVE_VISUAL_ID 0x302E
+#define EGL_NATIVE_VISUAL_TYPE 0x302F
+#define EGL_NONE 0x3038
+#define EGL_NON_CONFORMANT_CONFIG 0x3051
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_NO_CONTEXT ((EGLContext)0)
+#define EGL_NO_DISPLAY ((EGLDisplay)0)
+#define EGL_NO_SURFACE ((EGLSurface)0)
+#define EGL_PBUFFER_BIT 0x0001
+#define EGL_PIXMAP_BIT 0x0002
+#define EGL_READ 0x305A
+#define EGL_RED_SIZE 0x3024
+#define EGL_SAMPLES 0x3031
+#define EGL_SAMPLE_BUFFERS 0x3032
+#define EGL_SLOW_CONFIG 0x3050
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_SUCCESS 0x3000
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define EGL_TRANSPARENT_RED_VALUE 0x3037
+#define EGL_TRANSPARENT_RGB 0x3052
+#define EGL_TRANSPARENT_TYPE 0x3034
+#define EGL_TRUE 1
+#define EGL_VENDOR 0x3053
+#define EGL_VERSION 0x3054
+#define EGL_WIDTH 0x3057
+#define EGL_WINDOW_BIT 0x0004
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+#endif /* EGL_VERSION_1_0 */
+
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_1 1
+#define EGL_BACK_BUFFER 0x3084
+#define EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define EGL_CONTEXT_LOST 0x300E
+#define EGL_MIN_SWAP_INTERVAL 0x303B
+#define EGL_MAX_SWAP_INTERVAL 0x303C
+#define EGL_MIPMAP_TEXTURE 0x3082
+#define EGL_MIPMAP_LEVEL 0x3083
+#define EGL_NO_TEXTURE 0x305C
+#define EGL_TEXTURE_2D 0x305F
+#define EGL_TEXTURE_FORMAT 0x3080
+#define EGL_TEXTURE_RGB 0x305D
+#define EGL_TEXTURE_RGBA 0x305E
+#define EGL_TEXTURE_TARGET 0x3081
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
+#endif /* EGL_VERSION_1_1 */
+
+#ifndef EGL_VERSION_1_2
+#define EGL_VERSION_1_2 1
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+#define EGL_ALPHA_FORMAT 0x3088
+#define EGL_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_ALPHA_FORMAT_PRE 0x308C
+#define EGL_ALPHA_MASK_SIZE 0x303E
+#define EGL_BUFFER_PRESERVED 0x3094
+#define EGL_BUFFER_DESTROYED 0x3095
+#define EGL_CLIENT_APIS 0x308D
+#define EGL_COLORSPACE 0x3087
+#define EGL_COLORSPACE_sRGB 0x3089
+#define EGL_COLORSPACE_LINEAR 0x308A
+#define EGL_COLOR_BUFFER_TYPE 0x303F
+#define EGL_CONTEXT_CLIENT_TYPE 0x3097
+#define EGL_DISPLAY_SCALING 10000
+#define EGL_HORIZONTAL_RESOLUTION 0x3090
+#define EGL_LUMINANCE_BUFFER 0x308F
+#define EGL_LUMINANCE_SIZE 0x303D
+#define EGL_OPENGL_ES_BIT 0x0001
+#define EGL_OPENVG_BIT 0x0002
+#define EGL_OPENGL_ES_API 0x30A0
+#define EGL_OPENVG_API 0x30A1
+#define EGL_OPENVG_IMAGE 0x3096
+#define EGL_PIXEL_ASPECT_RATIO 0x3092
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_RENDER_BUFFER 0x3086
+#define EGL_RGB_BUFFER 0x308E
+#define EGL_SINGLE_BUFFER 0x3085
+#define EGL_SWAP_BEHAVIOR 0x3093
+#define EGL_UNKNOWN ((EGLint)-1)
+#define EGL_VERTICAL_RESOLUTION 0x3091
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
+#endif /* EGL_VERSION_1_2 */
+
+#ifndef EGL_VERSION_1_3
+#define EGL_VERSION_1_3 1
+#define EGL_CONFORMANT 0x3042
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+#define EGL_MATCH_NATIVE_PIXMAP 0x3041
+#define EGL_OPENGL_ES2_BIT 0x0004
+#define EGL_VG_ALPHA_FORMAT 0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
+#define EGL_VG_COLORSPACE 0x3087
+#define EGL_VG_COLORSPACE_sRGB 0x3089
+#define EGL_VG_COLORSPACE_LINEAR 0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
+#endif /* EGL_VERSION_1_3 */
+
+#ifndef EGL_VERSION_1_4
+#define EGL_VERSION_1_4 1
+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
+#define EGL_MULTISAMPLE_RESOLVE 0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
+#define EGL_OPENGL_API 0x30A2
+#define EGL_OPENGL_BIT 0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+#endif /* EGL_VERSION_1_4 */
+
+#ifndef EGL_VERSION_1_5
+#define EGL_VERSION_1_5 1
+typedef void *EGLSync;
+typedef intptr_t EGLAttrib;
+typedef khronos_utime_nanoseconds_t EGLTime;
+typedef void *EGLImage;
+#define EGL_CONTEXT_MAJOR_VERSION 0x3098
+#define EGL_CONTEXT_MINOR_VERSION 0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
+#define EGL_OPENGL_ES3_BIT 0x00000040
+#define EGL_CL_EVENT_HANDLE 0x309C
+#define EGL_SYNC_CL_EVENT 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
+#define EGL_SYNC_TYPE 0x30F7
+#define EGL_SYNC_STATUS 0x30F1
+#define EGL_SYNC_CONDITION 0x30F8
+#define EGL_SIGNALED 0x30F2
+#define EGL_UNSIGNALED 0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
+#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull
+#define EGL_TIMEOUT_EXPIRED 0x30F5
+#define EGL_CONDITION_SATISFIED 0x30F6
+#define EGL_NO_SYNC ((EGLSync)0)
+#define EGL_SYNC_FENCE 0x30F9
+#define EGL_GL_COLORSPACE 0x309D
+#define EGL_GL_COLORSPACE_SRGB 0x3089
+#define EGL_GL_COLORSPACE_LINEAR 0x308A
+#define EGL_GL_RENDERBUFFER 0x30B9
+#define EGL_GL_TEXTURE_2D 0x30B1
+#define EGL_GL_TEXTURE_LEVEL 0x30BC
+#define EGL_GL_TEXTURE_3D 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED 0x30D2
+#define EGL_NO_IMAGE ((EGLImage)0)
+EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags);
+#endif /* EGL_VERSION_1_5 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __egl_h_ */
+
+
+
+#ifndef __eglext_h_
+#define __eglext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
+*/
+
+/*#include <EGL/eglplatform.h>*/
+
+#define EGL_EGLEXT_VERSION 20150623
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: egl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_KHR_cl_event
+#define EGL_KHR_cl_event 1
+#define EGL_CL_EVENT_HANDLE_KHR 0x309C
+#define EGL_SYNC_CL_EVENT_KHR 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF
+#endif /* EGL_KHR_cl_event */
+
+#ifndef EGL_KHR_cl_event2
+#define EGL_KHR_cl_event2 1
+typedef void *EGLSyncKHR;
+typedef intptr_t EGLAttribKHR;
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#endif
+#endif /* EGL_KHR_cl_event2 */
+
+#ifndef EGL_KHR_client_get_all_proc_addresses
+#define EGL_KHR_client_get_all_proc_addresses 1
+#endif /* EGL_KHR_client_get_all_proc_addresses */
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR 0x3042
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
+#endif /* EGL_KHR_config_attribs */
+
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#define EGL_CONTEXT_FLAGS_KHR 0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
+#endif /* EGL_KHR_create_context */
+
+#ifndef EGL_KHR_create_context_no_error
+#define EGL_KHR_create_context_no_error 1
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
+#endif /* EGL_KHR_create_context_no_error */
+
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR 0x30F8
+#define EGL_SYNC_FENCE_KHR 0x30F9
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
+
+#ifndef EGL_KHR_get_all_proc_addresses
+#define EGL_KHR_get_all_proc_addresses 1
+#endif /* EGL_KHR_get_all_proc_addresses */
+
+#ifndef EGL_KHR_gl_colorspace
+#define EGL_KHR_gl_colorspace 1
+#define EGL_GL_COLORSPACE_KHR 0x309D
+#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
+#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
+#endif /* EGL_KHR_gl_colorspace */
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR 0x30B9
+#endif /* EGL_KHR_gl_renderbuffer_image */
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR 0x30B1
+#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
+#endif /* EGL_KHR_gl_texture_2D_image */
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
+#endif /* EGL_KHR_gl_texture_3D_image */
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+typedef void *EGLImageKHR;
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0
+#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif
+#endif /* EGL_KHR_image */
+
+#ifndef EGL_KHR_image_base
+#define EGL_KHR_image_base 1
+#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+#endif /* EGL_KHR_image_base */
+
+#ifndef EGL_KHR_image_pixmap
+#define EGL_KHR_image_pixmap 1
+#endif /* EGL_KHR_image_pixmap */
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR 0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR 0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR 0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
+#define EGL_MATCH_FORMAT_KHR 0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
+#define EGL_FORMAT_RGB_565_KHR 0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR 0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR 0x30C5
+#define EGL_BITMAP_POINTER_KHR 0x30C6
+#define EGL_BITMAP_PITCH_KHR 0x30C7
+#define EGL_BITMAP_ORIGIN_KHR 0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR 0x30CE
+#define EGL_UPPER_LEFT_KHR 0x30CF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
+#endif
+#endif /* EGL_KHR_lock_surface */
+
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifndef EGL_KHR_lock_surface3
+#define EGL_KHR_lock_surface3 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#endif
+#endif /* EGL_KHR_lock_surface3 */
+
+#ifndef EGL_KHR_partial_update
+#define EGL_KHR_partial_update 1
+#define EGL_BUFFER_AGE_KHR 0x313D
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_partial_update */
+
+#ifndef EGL_KHR_platform_android
+#define EGL_KHR_platform_android 1
+#define EGL_PLATFORM_ANDROID_KHR 0x3141
+#endif /* EGL_KHR_platform_android */
+
+#ifndef EGL_KHR_platform_gbm
+#define EGL_KHR_platform_gbm 1
+#define EGL_PLATFORM_GBM_KHR 0x31D7
+#endif /* EGL_KHR_platform_gbm */
+
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
+#endif /* EGL_KHR_platform_wayland */
+
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#define EGL_PLATFORM_X11_KHR 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6
+#endif /* EGL_KHR_platform_x11 */
+
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_STATUS_KHR 0x30F1
+#define EGL_SIGNALED_KHR 0x30F2
+#define EGL_UNSIGNALED_KHR 0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
+#define EGL_CONDITION_SATISFIED_KHR 0x30F6
+#define EGL_SYNC_TYPE_KHR 0x30F7
+#define EGL_SYNC_REUSABLE_KHR 0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
+#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_reusable_sync */
+
+#ifndef EGL_KHR_stream
+#define EGL_KHR_stream 1
+typedef void *EGLStreamKHR;
+typedef khronos_uint64_t EGLuint64KHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
+#define EGL_PRODUCER_FRAME_KHR 0x3212
+#define EGL_CONSUMER_FRAME_KHR 0x3213
+#define EGL_STREAM_STATE_KHR 0x3214
+#define EGL_STREAM_STATE_CREATED_KHR 0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR 0x321B
+#define EGL_BAD_STATE_KHR 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream */
+
+#ifndef EGL_KHR_stream_consumer_gltexture
+#define EGL_KHR_stream_consumer_gltexture 1
+#ifdef EGL_KHR_stream
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_consumer_gltexture */
+
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#ifdef EGL_KHR_stream
+#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1))
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_cross_process_fd */
+
+#ifndef EGL_KHR_stream_fifo
+#define EGL_KHR_stream_fifo 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
+#define EGL_STREAM_TIME_NOW_KHR 0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_fifo */
+
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#ifdef EGL_KHR_stream
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_BIT_KHR 0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_eglsurface */
+
+#ifndef EGL_KHR_surfaceless_context
+#define EGL_KHR_surfaceless_context 1
+#endif /* EGL_KHR_surfaceless_context */
+
+#ifndef EGL_KHR_swap_buffers_with_damage
+#define EGL_KHR_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_swap_buffers_with_damage */
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
+#endif /* EGL_KHR_vg_parent_image */
+
+#ifndef EGL_KHR_wait_sync
+#define EGL_KHR_wait_sync 1
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#endif
+#endif /* EGL_KHR_wait_sync */
+
+#ifndef EGL_ANDROID_blob_cache
+#define EGL_ANDROID_blob_cache 1
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#endif
+#endif /* EGL_ANDROID_blob_cache */
+
+#ifndef EGL_ANDROID_framebuffer_target
+#define EGL_ANDROID_framebuffer_target 1
+#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
+#endif /* EGL_ANDROID_framebuffer_target */
+
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_ANDROID 0x3140
+#endif /* EGL_ANDROID_image_native_buffer */
+
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_ANDROID_native_fence_sync 1
+#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
+#endif
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID 0x3142
+#endif /* EGL_ANDROID_recordable */
+
+#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifndef EGL_ANGLE_device_d3d
+#define EGL_ANGLE_device_d3d 1
+#define EGL_D3D9_DEVICE_ANGLE 0x33A0
+#define EGL_D3D11_DEVICE_ANGLE 0x33A1
+#endif /* EGL_ANGLE_device_d3d */
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE 0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
+#ifndef EGL_ARM_pixmap_multisample_discard
+#define EGL_ARM_pixmap_multisample_discard 1
+#define EGL_DISCARD_SAMPLES_ARM 0x3286
+#endif /* EGL_ARM_pixmap_multisample_discard */
+
+#ifndef EGL_EXT_buffer_age
+#define EGL_EXT_buffer_age 1
+#define EGL_BUFFER_AGE_EXT 0x313D
+#endif /* EGL_EXT_buffer_age */
+
+#ifndef EGL_EXT_client_extensions
+#define EGL_EXT_client_extensions 1
+#endif /* EGL_EXT_client_extensions */
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0))
+#define EGL_BAD_DEVICE_EXT 0x322B
+#define EGL_DEVICE_EXT 0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_EXT_device_drm
+#define EGL_EXT_device_drm 1
+#define EGL_DRM_DEVICE_FILE_EXT 0x3233
+#endif /* EGL_EXT_device_drm */
+
+#ifndef EGL_EXT_device_enumeration
+#define EGL_EXT_device_enumeration 1
+#endif /* EGL_EXT_device_enumeration */
+
+#ifndef EGL_EXT_device_openwf
+#define EGL_EXT_device_openwf 1
+#define EGL_OPENWF_DEVICE_ID_EXT 0x3237
+#endif /* EGL_EXT_device_openwf */
+
+#ifndef EGL_EXT_device_query
+#define EGL_EXT_device_query 1
+#endif /* EGL_EXT_device_query */
+
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_EXT_image_dma_buf_import 1
+#define EGL_LINUX_DMA_BUF_EXT 0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT 0x327F
+#define EGL_ITU_REC709_EXT 0x3280
+#define EGL_ITU_REC2020_EXT 0x3281
+#define EGL_YUV_FULL_RANGE_EXT 0x3282
+#define EGL_YUV_NARROW_RANGE_EXT 0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
+#endif /* EGL_EXT_image_dma_buf_import */
+
+#ifndef EGL_EXT_multiview_window
+#define EGL_EXT_multiview_window 1
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
+#endif /* EGL_EXT_multiview_window */
+
+#ifndef EGL_EXT_output_base
+#define EGL_EXT_output_base 1
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0)
+#define EGL_NO_OUTPUT_PORT_EXT ((EGLOutputPortEXT)0)
+#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D
+#define EGL_BAD_OUTPUT_PORT_EXT 0x322E
+#define EGL_SWAP_INTERVAL_EXT 0x322F
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#endif
+#endif /* EGL_EXT_output_base */
+
+#ifndef EGL_EXT_output_drm
+#define EGL_EXT_output_drm 1
+#define EGL_DRM_CRTC_EXT 0x3234
+#define EGL_DRM_PLANE_EXT 0x3235
+#define EGL_DRM_CONNECTOR_EXT 0x3236
+#endif /* EGL_EXT_output_drm */
+
+#ifndef EGL_EXT_output_openwf
+#define EGL_EXT_output_openwf 1
+#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238
+#define EGL_OPENWF_PORT_ID_EXT 0x3239
+#endif /* EGL_EXT_output_openwf */
+
+#ifndef EGL_EXT_platform_base
+#define EGL_EXT_platform_base 1
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#endif
+#endif /* EGL_EXT_platform_base */
+
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif /* EGL_EXT_platform_device */
+
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
+#endif /* EGL_EXT_platform_wayland */
+
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#define EGL_PLATFORM_X11_EXT 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
+#endif /* EGL_EXT_platform_x11 */
+
+#ifndef EGL_EXT_protected_surface
+#define EGL_EXT_protected_surface 1
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+#endif /* EGL_EXT_protected_surface */
+
+#ifndef EGL_EXT_stream_consumer_egloutput
+#define EGL_EXT_stream_consumer_egloutput 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#endif
+#endif /* EGL_EXT_stream_consumer_egloutput */
+
+#ifndef EGL_EXT_swap_buffers_with_damage
+#define EGL_EXT_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_EXT_swap_buffers_with_damage */
+
+#ifndef EGL_EXT_yuv_surface
+#define EGL_EXT_yuv_surface 1
+#define EGL_YUV_ORDER_EXT 0x3301
+#define EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311
+#define EGL_YUV_SUBSAMPLE_EXT 0x3312
+#define EGL_YUV_DEPTH_RANGE_EXT 0x3317
+#define EGL_YUV_CSC_STANDARD_EXT 0x330A
+#define EGL_YUV_PLANE_BPP_EXT 0x331A
+#define EGL_YUV_BUFFER_EXT 0x3300
+#define EGL_YUV_ORDER_YUV_EXT 0x3302
+#define EGL_YUV_ORDER_YVU_EXT 0x3303
+#define EGL_YUV_ORDER_YUYV_EXT 0x3304
+#define EGL_YUV_ORDER_UYVY_EXT 0x3305
+#define EGL_YUV_ORDER_YVYU_EXT 0x3306
+#define EGL_YUV_ORDER_VYUY_EXT 0x3307
+#define EGL_YUV_ORDER_AYUV_EXT 0x3308
+#define EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313
+#define EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314
+#define EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315
+#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318
+#define EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319
+#define EGL_YUV_CSC_STANDARD_601_EXT 0x330B
+#define EGL_YUV_CSC_STANDARD_709_EXT 0x330C
+#define EGL_YUV_CSC_STANDARD_2020_EXT 0x330D
+#define EGL_YUV_PLANE_BPP_0_EXT 0x331B
+#define EGL_YUV_PLANE_BPP_8_EXT 0x331C
+#define EGL_YUV_PLANE_BPP_10_EXT 0x331D
+#endif /* EGL_EXT_yuv_surface */
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+struct EGLClientPixmapHI {
+ void *pData;
+ EGLint iWidth;
+ EGLint iHeight;
+ EGLint iStride;
+};
+#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#endif
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+#define EGL_COLOR_FORMAT_HI 0x8F70
+#define EGL_COLOR_RGB_HI 0x8F71
+#define EGL_COLOR_RGBA_HI 0x8F72
+#define EGL_COLOR_ARGB_HI 0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
+#endif /* EGL_IMG_context_priority */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
+#define EGL_DRM_BUFFER_USE_MESA 0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA 0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+#endif /* EGL_MESA_drm_image */
+
+#ifndef EGL_MESA_image_dma_buf_export
+#define EGL_MESA_image_dma_buf_export 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#endif
+#endif /* EGL_MESA_image_dma_buf_export */
+
+#ifndef EGL_MESA_platform_gbm
+#define EGL_MESA_platform_gbm 1
+#define EGL_PLATFORM_GBM_MESA 0x31D7
+#endif /* EGL_MESA_platform_gbm */
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region */
+
+#ifndef EGL_NOK_swap_region2
+#define EGL_NOK_swap_region2 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region2 */
+
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+#define EGL_Y_INVERTED_NOK 0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+#ifndef EGL_NV_3dvision_surface
+#define EGL_NV_3dvision_surface 1
+#define EGL_AUTO_STEREO_NV 0x3136
+#endif /* EGL_NV_3dvision_surface */
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define EGL_COVERAGE_SAMPLES_NV 0x30E1
+#endif /* EGL_NV_coverage_sample */
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifndef EGL_NV_cuda_event
+#define EGL_NV_cuda_event 1
+#define EGL_CUDA_EVENT_HANDLE_NV 0x323B
+#define EGL_SYNC_CUDA_EVENT_NV 0x323C
+#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D
+#endif /* EGL_NV_cuda_event */
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV 0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+#endif /* EGL_NV_depth_nonlinear */
+
+#ifndef EGL_NV_device_cuda
+#define EGL_NV_device_cuda 1
+#define EGL_CUDA_DEVICE_NV 0x323A
+#endif /* EGL_NV_device_cuda */
+
+#ifndef EGL_NV_native_query
+#define EGL_NV_native_query 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#endif
+#endif /* EGL_NV_native_query */
+
+#ifndef EGL_NV_post_convert_rounding
+#define EGL_NV_post_convert_rounding 1
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifndef EGL_NV_stream_sync
+#define EGL_NV_stream_sync 1
+#define EGL_SYNC_NEW_FRAME_NV 0x321F
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#endif
+#endif /* EGL_NV_stream_sync */
+
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+typedef void *EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV 0x30E7
+#define EGL_SIGNALED_NV 0x30E8
+#define EGL_UNSIGNALED_NV 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
+#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV 0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
+#define EGL_CONDITION_SATISFIED_NV 0x30EC
+#define EGL_SYNC_TYPE_NV 0x30ED
+#define EGL_SYNC_CONDITION_NV 0x30EE
+#define EGL_SYNC_FENCE_NV 0x30EF
+#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_sync */
+
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_system_time */
+
+#ifndef EGL_TIZEN_image_native_buffer
+#define EGL_TIZEN_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_TIZEN 0x32A0
+#endif /* EGL_TIZEN_image_native_buffer */
+
+#ifndef EGL_TIZEN_image_native_surface
+#define EGL_TIZEN_image_native_surface 1
+#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
+#endif /* EGL_TIZEN_image_native_surface */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __eglext_h_ */
+
+
+#endif /* _MSC_VER */
diff --git a/Client/ThirdParty/SDL2/SDL_endian.h b/Client/ThirdParty/SDL2/SDL_endian.h
new file mode 100644
index 0000000..205b793
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_endian.h
@@ -0,0 +1,316 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_endian.h
+ *
+ * Functions for reading and writing endian-specific values
+ */
+
+#ifndef SDL_endian_h_
+#define SDL_endian_h_
+
+#include "SDL_stdinc.h"
+
+#ifdef _MSC_VER
+/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
+ so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
+
+#ifdef __clang__
+#ifndef __PRFCHWINTRIN_H
+#define __PRFCHWINTRIN_H
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+#endif /* __PRFCHWINTRIN_H */
+#endif /* __clang__ */
+
+#include <intrin.h>
+#endif
+
+/**
+ * \name The two types of endianness
+ */
+/* @{ */
+#define SDL_LIL_ENDIAN 1234
+#define SDL_BIG_ENDIAN 4321
+/* @} */
+
+#ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */
+#ifdef __linux__
+#include <endian.h>
+#define SDL_BYTEORDER __BYTE_ORDER
+#elif defined(__OpenBSD__)
+#include <endian.h>
+#define SDL_BYTEORDER BYTE_ORDER
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+#include <sys/endian.h>
+#define SDL_BYTEORDER BYTE_ORDER
+#else
+#if defined(__hppa__) || \
+ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
+ (defined(__MIPS__) && defined(__MIPSEB__)) || \
+ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
+ defined(__sparc__)
+#define SDL_BYTEORDER SDL_BIG_ENDIAN
+#else
+#define SDL_BYTEORDER SDL_LIL_ENDIAN
+#endif
+#endif /* __linux__ */
+#endif /* !SDL_BYTEORDER */
+
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_endian.h
+ */
+#if (defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) || \
+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
+#define SDL_Swap16(x) __builtin_bswap16(x)
+#elif defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ int result;
+
+ __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
+ return (Uint16)result;
+}
+#elif defined(__GNUC__) && defined(__aarch64__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("rev16 %w1, %w0" : "=r"(x) : "r"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#elif defined(_MSC_VER)
+#pragma intrinsic(_byteswap_ushort)
+#define SDL_Swap16(x) _byteswap_ushort(x)
+#elif defined(__WATCOMC__) && defined(__386__)
+extern _inline Uint16 SDL_Swap16(Uint16);
+#pragma aux SDL_Swap16 = \
+ "xchg al, ah" \
+ parm [ax] \
+ modify [ax];
+#else
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ return SDL_static_cast(Uint16, ((x << 8) | (x >> 8)));
+}
+#endif
+
+#if (defined(__clang__) && (__clang_major__ > 2 || (__clang_major__ == 2 && __clang_minor__ >= 6))) || \
+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+#define SDL_Swap32(x) __builtin_bswap32(x)
+#elif defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswap %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswapl %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ Uint32 result;
+
+ __asm__("rlwimi %0,%2,24,16,23": "=&r"(result): "0" (x>>24), "r"(x));
+ __asm__("rlwimi %0,%2,8,8,15" : "=&r"(result): "0" (result), "r"(x));
+ __asm__("rlwimi %0,%2,24,0,7" : "=&r"(result): "0" (result), "r"(x));
+ return result;
+}
+#elif defined(__GNUC__) && defined(__aarch64__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("rev %w1, %w0": "=r"(x):"r"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern _inline Uint32 SDL_Swap32(Uint32);
+#pragma aux SDL_Swap32 = \
+ "bswap eax" \
+ parm [eax] \
+ modify [eax];
+#elif defined(_MSC_VER)
+#pragma intrinsic(_byteswap_ulong)
+#define SDL_Swap32(x) _byteswap_ulong(x)
+#else
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) |
+ ((x >> 8) & 0x0000FF00) | (x >> 24)));
+}
+#endif
+
+#if (defined(__clang__) && (__clang_major__ > 2 || (__clang_major__ == 2 && __clang_minor__ >= 6))) || \
+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+#define SDL_Swap64(x) __builtin_bswap64(x)
+#elif defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ union {
+ struct {
+ Uint32 a, b;
+ } s;
+ Uint64 u;
+ } v;
+ v.u = x;
+ __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r"(v.s.a), "=r"(v.s.b)
+ : "0" (v.s.a), "1"(v.s.b));
+ return v.u;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ __asm__("bswapq %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern _inline Uint64 SDL_Swap64(Uint64);
+#pragma aux SDL_Swap64 = \
+ "bswap eax" \
+ "bswap edx" \
+ "xchg eax,edx" \
+ parm [eax edx] \
+ modify [eax edx];
+#elif defined(_MSC_VER)
+#pragma intrinsic(_byteswap_uint64)
+#define SDL_Swap64(x) _byteswap_uint64(x)
+#else
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ Uint32 hi, lo;
+
+ /* Separate into high and low 32-bit values and swap them */
+ lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x >>= 32;
+ hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x = SDL_Swap32(lo);
+ x <<= 32;
+ x |= SDL_Swap32(hi);
+ return (x);
+}
+#endif
+
+
+SDL_FORCE_INLINE float
+SDL_SwapFloat(float x)
+{
+ union {
+ float f;
+ Uint32 ui32;
+ } swapper;
+ swapper.f = x;
+ swapper.ui32 = SDL_Swap32(swapper.ui32);
+ return swapper.f;
+}
+
+
+/**
+ * \name Swap to native
+ * Byteswap item from the specified endianness to the native endianness.
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define SDL_SwapLE16(X) (X)
+#define SDL_SwapLE32(X) (X)
+#define SDL_SwapLE64(X) (X)
+#define SDL_SwapFloatLE(X) (X)
+#define SDL_SwapBE16(X) SDL_Swap16(X)
+#define SDL_SwapBE32(X) SDL_Swap32(X)
+#define SDL_SwapBE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatBE(X) SDL_SwapFloat(X)
+#else
+#define SDL_SwapLE16(X) SDL_Swap16(X)
+#define SDL_SwapLE32(X) SDL_Swap32(X)
+#define SDL_SwapLE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatLE(X) SDL_SwapFloat(X)
+#define SDL_SwapBE16(X) (X)
+#define SDL_SwapBE32(X) (X)
+#define SDL_SwapBE64(X) (X)
+#define SDL_SwapFloatBE(X) (X)
+#endif
+/* @} *//* Swap to native */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_endian_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_error.h b/Client/ThirdParty/SDL2/SDL_error.h
new file mode 100644
index 0000000..f61a200
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_error.h
@@ -0,0 +1,155 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_error.h
+ *
+ * Simple error message routines for SDL.
+ */
+
+#ifndef SDL_error_h_
+#define SDL_error_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public functions */
+
+
+/**
+ * Set the SDL error message for the current thread.
+ *
+ * Calling this function will replace any previous error message that was set.
+ *
+ * This function always returns -1, since SDL frequently uses -1 to signify an
+ * failing result, leading to this idiom:
+ *
+ * ```c
+ * if (error_code) {
+ * return SDL_SetError("This operation has failed: %d", error_code);
+ * }
+ * ```
+ *
+ * \param fmt a printf()-style message format string
+ * \param ... additional parameters matching % tokens in the `fmt` string, if
+ * any
+ * \returns always -1.
+ *
+ * \sa SDL_ClearError
+ * \sa SDL_GetError
+ */
+extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * Retrieve a message about the last error that occurred on the current
+ * thread.
+ *
+ * It is possible for multiple errors to occur before calling SDL_GetError().
+ * Only the last error is returned.
+ *
+ * The message is only applicable when an SDL function has signaled an error.
+ * You must check the return values of SDL function calls to determine when to
+ * appropriately call SDL_GetError(). You should _not_ use the results of
+ * SDL_GetError() to decide if an error has occurred! Sometimes SDL will set
+ * an error string even when reporting success.
+ *
+ * SDL will _not_ clear the error string for successful API calls. You _must_
+ * check return values for failure cases before you can assume the error
+ * string applies.
+ *
+ * Error strings are set per-thread, so an error set in a different thread
+ * will not interfere with the current thread's operation.
+ *
+ * The returned string is internally allocated and must not be freed by the
+ * application.
+ *
+ * \returns a message with information about the specific error that occurred,
+ * or an empty string if there hasn't been an error message set since
+ * the last call to SDL_ClearError(). The message is only applicable
+ * when an SDL function has signaled an error. You must check the
+ * return values of SDL function calls to determine when to
+ * appropriately call SDL_GetError().
+ *
+ * \sa SDL_ClearError
+ * \sa SDL_SetError
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetError(void);
+
+/**
+ * Get the last error message that was set for the current thread.
+ *
+ * This allows the caller to copy the error string into a provided buffer, but
+ * otherwise operates exactly the same as SDL_GetError().
+ *
+ * \param errstr A buffer to fill with the last error message that was set for
+ * the current thread
+ * \param maxlen The size of the buffer pointed to by the errstr parameter
+ * \returns the pointer passed in as the `errstr` parameter.
+ *
+ * \sa SDL_GetError
+ */
+extern DECLSPEC char * SDLCALL SDL_GetErrorMsg(char *errstr, int maxlen);
+
+/**
+ * Clear any previous error message for this thread.
+ *
+ * \sa SDL_GetError
+ * \sa SDL_SetError
+ */
+extern DECLSPEC void SDLCALL SDL_ClearError(void);
+
+/**
+ * \name Internal error functions
+ *
+ * \internal
+ * Private error reporting function - used internally.
+ */
+/* @{ */
+#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM)
+#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED)
+#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param))
+typedef enum
+{
+ SDL_ENOMEM,
+ SDL_EFREAD,
+ SDL_EFWRITE,
+ SDL_EFSEEK,
+ SDL_UNSUPPORTED,
+ SDL_LASTERROR
+} SDL_errorcode;
+/* SDL_Error() unconditionally returns -1. */
+extern DECLSPEC int SDLCALL SDL_Error(SDL_errorcode code);
+/* @} *//* Internal error functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_error_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_events.h b/Client/ThirdParty/SDL2/SDL_events.h
new file mode 100644
index 0000000..c3037b2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_events.h
@@ -0,0 +1,1098 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_events.h
+ *
+ * Include file for SDL event handling.
+ */
+
+#ifndef SDL_events_h_
+#define SDL_events_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_keyboard.h"
+#include "SDL_mouse.h"
+#include "SDL_joystick.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_quit.h"
+#include "SDL_gesture.h"
+#include "SDL_touch.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General keyboard/mouse state definitions */
+#define SDL_RELEASED 0
+#define SDL_PRESSED 1
+
+/**
+ * The types of events that can be delivered.
+ */
+typedef enum
+{
+ SDL_FIRSTEVENT = 0, /**< Unused (do not remove) */
+
+ /* Application events */
+ SDL_QUIT = 0x100, /**< User-requested quit */
+
+ /* These application events have special meaning on iOS, see README-ios.md for details */
+ SDL_APP_TERMINATING, /**< The application is being terminated by the OS
+ Called on iOS in applicationWillTerminate()
+ Called on Android in onDestroy()
+ */
+ SDL_APP_LOWMEMORY, /**< The application is low on memory, free memory if possible.
+ Called on iOS in applicationDidReceiveMemoryWarning()
+ Called on Android in onLowMemory()
+ */
+ SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
+ Called on iOS in applicationWillResignActive()
+ Called on Android in onPause()
+ */
+ SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
+ Called on iOS in applicationDidEnterBackground()
+ Called on Android in onPause()
+ */
+ SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
+ Called on iOS in applicationWillEnterForeground()
+ Called on Android in onResume()
+ */
+ SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive
+ Called on iOS in applicationDidBecomeActive()
+ Called on Android in onResume()
+ */
+
+ SDL_LOCALECHANGED, /**< The user's locale preferences have changed. */
+
+ /* Display events */
+ SDL_DISPLAYEVENT = 0x150, /**< Display state change */
+
+ /* Window events */
+ SDL_WINDOWEVENT = 0x200, /**< Window state change */
+ SDL_SYSWMEVENT, /**< System specific event */
+
+ /* Keyboard events */
+ SDL_KEYDOWN = 0x300, /**< Key pressed */
+ SDL_KEYUP, /**< Key released */
+ SDL_TEXTEDITING, /**< Keyboard text editing (composition) */
+ SDL_TEXTINPUT, /**< Keyboard text input */
+ SDL_KEYMAPCHANGED, /**< Keymap changed due to a system event such as an
+ input language or keyboard layout change.
+ */
+
+ /* Mouse events */
+ SDL_MOUSEMOTION = 0x400, /**< Mouse moved */
+ SDL_MOUSEBUTTONDOWN, /**< Mouse button pressed */
+ SDL_MOUSEBUTTONUP, /**< Mouse button released */
+ SDL_MOUSEWHEEL, /**< Mouse wheel motion */
+
+ /* Joystick events */
+ SDL_JOYAXISMOTION = 0x600, /**< Joystick axis motion */
+ SDL_JOYBALLMOTION, /**< Joystick trackball motion */
+ SDL_JOYHATMOTION, /**< Joystick hat position change */
+ SDL_JOYBUTTONDOWN, /**< Joystick button pressed */
+ SDL_JOYBUTTONUP, /**< Joystick button released */
+ SDL_JOYDEVICEADDED, /**< A new joystick has been inserted into the system */
+ SDL_JOYDEVICEREMOVED, /**< An opened joystick has been removed */
+
+ /* Game controller events */
+ SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */
+ SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */
+ SDL_CONTROLLERBUTTONUP, /**< Game controller button released */
+ SDL_CONTROLLERDEVICEADDED, /**< A new Game controller has been inserted into the system */
+ SDL_CONTROLLERDEVICEREMOVED, /**< An opened Game controller has been removed */
+ SDL_CONTROLLERDEVICEREMAPPED, /**< The controller mapping was updated */
+ SDL_CONTROLLERTOUCHPADDOWN, /**< Game controller touchpad was touched */
+ SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */
+ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */
+ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */
+
+ /* Touch events */
+ SDL_FINGERDOWN = 0x700,
+ SDL_FINGERUP,
+ SDL_FINGERMOTION,
+
+ /* Gesture events */
+ SDL_DOLLARGESTURE = 0x800,
+ SDL_DOLLARRECORD,
+ SDL_MULTIGESTURE,
+
+ /* Clipboard events */
+ SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard changed */
+
+ /* Drag and drop events */
+ SDL_DROPFILE = 0x1000, /**< The system requests a file open */
+ SDL_DROPTEXT, /**< text/plain drag-and-drop event */
+ SDL_DROPBEGIN, /**< A new set of drops is beginning (NULL filename) */
+ SDL_DROPCOMPLETE, /**< Current set of drops is now complete (NULL filename) */
+
+ /* Audio hotplug events */
+ SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
+ SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */
+
+ /* Sensor events */
+ SDL_SENSORUPDATE = 0x1200, /**< A sensor was updated */
+
+ /* Render events */
+ SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
+ SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
+
+ /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
+ * and should be allocated with SDL_RegisterEvents()
+ */
+ SDL_USEREVENT = 0x8000,
+
+ /**
+ * This last event is only for bounding internal arrays
+ */
+ SDL_LASTEVENT = 0xFFFF
+} SDL_EventType;
+
+/**
+ * \brief Fields shared by every event
+ */
+typedef struct SDL_CommonEvent
+{
+ Uint32 type;
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_CommonEvent;
+
+/**
+ * \brief Display state change event data (event.display.*)
+ */
+typedef struct SDL_DisplayEvent
+{
+ Uint32 type; /**< ::SDL_DISPLAYEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 display; /**< The associated display index */
+ Uint8 event; /**< ::SDL_DisplayEventID */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1; /**< event dependent data */
+} SDL_DisplayEvent;
+
+/**
+ * \brief Window state change event data (event.window.*)
+ */
+typedef struct SDL_WindowEvent
+{
+ Uint32 type; /**< ::SDL_WINDOWEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The associated window */
+ Uint8 event; /**< ::SDL_WindowEventID */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1; /**< event dependent data */
+ Sint32 data2; /**< event dependent data */
+} SDL_WindowEvent;
+
+/**
+ * \brief Keyboard button event structure (event.key.*)
+ */
+typedef struct SDL_KeyboardEvent
+{
+ Uint32 type; /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 repeat; /**< Non-zero if this is a key repeat */
+ Uint8 padding2;
+ Uint8 padding3;
+ SDL_Keysym keysym; /**< The key that was pressed or released */
+} SDL_KeyboardEvent;
+
+#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32)
+/**
+ * \brief Keyboard text editing event structure (event.edit.*)
+ */
+typedef struct SDL_TextEditingEvent
+{
+ Uint32 type; /**< ::SDL_TEXTEDITING */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */
+ Sint32 start; /**< The start cursor of selected editing text */
+ Sint32 length; /**< The length of selected editing text */
+} SDL_TextEditingEvent;
+
+
+#define SDL_TEXTINPUTEVENT_TEXT_SIZE (32)
+/**
+ * \brief Keyboard text input event structure (event.text.*)
+ */
+typedef struct SDL_TextInputEvent
+{
+ Uint32 type; /**< ::SDL_TEXTINPUT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */
+} SDL_TextInputEvent;
+
+/**
+ * \brief Mouse motion event structure (event.motion.*)
+ */
+typedef struct SDL_MouseMotionEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Uint32 state; /**< The current button state */
+ Sint32 x; /**< X coordinate, relative to window */
+ Sint32 y; /**< Y coordinate, relative to window */
+ Sint32 xrel; /**< The relative motion in the X direction */
+ Sint32 yrel; /**< The relative motion in the Y direction */
+} SDL_MouseMotionEvent;
+
+/**
+ * \brief Mouse button event structure (event.button.*)
+ */
+typedef struct SDL_MouseButtonEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Uint8 button; /**< The mouse button index */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
+ Uint8 padding1;
+ Sint32 x; /**< X coordinate, relative to window */
+ Sint32 y; /**< Y coordinate, relative to window */
+} SDL_MouseButtonEvent;
+
+/**
+ * \brief Mouse wheel event structure (event.wheel.*)
+ */
+typedef struct SDL_MouseWheelEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEWHEEL */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
+ Sint32 y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
+ Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
+} SDL_MouseWheelEvent;
+
+/**
+ * \brief Joystick axis motion event structure (event.jaxis.*)
+ */
+typedef struct SDL_JoyAxisEvent
+{
+ Uint32 type; /**< ::SDL_JOYAXISMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 axis; /**< The joystick axis index */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value; /**< The axis value (range: -32768 to 32767) */
+ Uint16 padding4;
+} SDL_JoyAxisEvent;
+
+/**
+ * \brief Joystick trackball motion event structure (event.jball.*)
+ */
+typedef struct SDL_JoyBallEvent
+{
+ Uint32 type; /**< ::SDL_JOYBALLMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 ball; /**< The joystick trackball index */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 xrel; /**< The relative motion in the X direction */
+ Sint16 yrel; /**< The relative motion in the Y direction */
+} SDL_JoyBallEvent;
+
+/**
+ * \brief Joystick hat position change event structure (event.jhat.*)
+ */
+typedef struct SDL_JoyHatEvent
+{
+ Uint32 type; /**< ::SDL_JOYHATMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 hat; /**< The joystick hat index */
+ Uint8 value; /**< The hat position value.
+ * \sa ::SDL_HAT_LEFTUP ::SDL_HAT_UP ::SDL_HAT_RIGHTUP
+ * \sa ::SDL_HAT_LEFT ::SDL_HAT_CENTERED ::SDL_HAT_RIGHT
+ * \sa ::SDL_HAT_LEFTDOWN ::SDL_HAT_DOWN ::SDL_HAT_RIGHTDOWN
+ *
+ * Note that zero means the POV is centered.
+ */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyHatEvent;
+
+/**
+ * \brief Joystick button event structure (event.jbutton.*)
+ */
+typedef struct SDL_JoyButtonEvent
+{
+ Uint32 type; /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 button; /**< The joystick button index */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyButtonEvent;
+
+/**
+ * \brief Joystick device event structure (event.jdevice.*)
+ */
+typedef struct SDL_JoyDeviceEvent
+{
+ Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
+} SDL_JoyDeviceEvent;
+
+
+/**
+ * \brief Game controller axis motion event structure (event.caxis.*)
+ */
+typedef struct SDL_ControllerAxisEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERAXISMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value; /**< The axis value (range: -32768 to 32767) */
+ Uint16 padding4;
+} SDL_ControllerAxisEvent;
+
+
+/**
+ * \brief Game controller button event structure (event.cbutton.*)
+ */
+typedef struct SDL_ControllerButtonEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 button; /**< The controller button (SDL_GameControllerButton) */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_ControllerButtonEvent;
+
+
+/**
+ * \brief Controller device event structure (event.cdevice.*)
+ */
+typedef struct SDL_ControllerDeviceEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
+} SDL_ControllerDeviceEvent;
+
+/**
+ * \brief Game controller touchpad event structure (event.ctouchpad.*)
+ */
+typedef struct SDL_ControllerTouchpadEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Sint32 touchpad; /**< The index of the touchpad */
+ Sint32 finger; /**< The index of the finger on the touchpad */
+ float x; /**< Normalized in the range 0...1 with 0 being on the left */
+ float y; /**< Normalized in the range 0...1 with 0 being at the top */
+ float pressure; /**< Normalized in the range 0...1 */
+} SDL_ControllerTouchpadEvent;
+
+/**
+ * \brief Game controller sensor event structure (event.csensor.*)
+ */
+typedef struct SDL_ControllerSensorEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */
+ float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
+} SDL_ControllerSensorEvent;
+
+/**
+ * \brief Audio device event structure (event.adevice.*)
+ */
+typedef struct SDL_AudioDeviceEvent
+{
+ Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
+ Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+} SDL_AudioDeviceEvent;
+
+
+/**
+ * \brief Touch finger event structure (event.tfinger.*)
+ */
+typedef struct SDL_TouchFingerEvent
+{
+ Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ SDL_FingerID fingerId;
+ float x; /**< Normalized in the range 0...1 */
+ float y; /**< Normalized in the range 0...1 */
+ float dx; /**< Normalized in the range -1...1 */
+ float dy; /**< Normalized in the range -1...1 */
+ float pressure; /**< Normalized in the range 0...1 */
+ Uint32 windowID; /**< The window underneath the finger, if any */
+} SDL_TouchFingerEvent;
+
+
+/**
+ * \brief Multiple Finger Gesture Event (event.mgesture.*)
+ */
+typedef struct SDL_MultiGestureEvent
+{
+ Uint32 type; /**< ::SDL_MULTIGESTURE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ float dTheta;
+ float dDist;
+ float x;
+ float y;
+ Uint16 numFingers;
+ Uint16 padding;
+} SDL_MultiGestureEvent;
+
+
+/**
+ * \brief Dollar Gesture Event (event.dgesture.*)
+ */
+typedef struct SDL_DollarGestureEvent
+{
+ Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ SDL_GestureID gestureId;
+ Uint32 numFingers;
+ float error;
+ float x; /**< Normalized center of gesture */
+ float y; /**< Normalized center of gesture */
+} SDL_DollarGestureEvent;
+
+
+/**
+ * \brief An event used to request a file open by the system (event.drop.*)
+ * This event is enabled by default, you can disable it with SDL_EventState().
+ * \note If this event is enabled, you must free the filename in the event.
+ */
+typedef struct SDL_DropEvent
+{
+ Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
+ Uint32 windowID; /**< The window that was dropped on, if any */
+} SDL_DropEvent;
+
+
+/**
+ * \brief Sensor event structure (event.sensor.*)
+ */
+typedef struct SDL_SensorEvent
+{
+ Uint32 type; /**< ::SDL_SENSORUPDATE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The instance ID of the sensor */
+ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
+} SDL_SensorEvent;
+
+/**
+ * \brief The "quit requested" event
+ */
+typedef struct SDL_QuitEvent
+{
+ Uint32 type; /**< ::SDL_QUIT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_QuitEvent;
+
+/**
+ * \brief OS Specific event
+ */
+typedef struct SDL_OSEvent
+{
+ Uint32 type; /**< ::SDL_QUIT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_OSEvent;
+
+/**
+ * \brief A user-defined event type (event.user.*)
+ */
+typedef struct SDL_UserEvent
+{
+ Uint32 type; /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The associated window if any */
+ Sint32 code; /**< User defined event code */
+ void *data1; /**< User defined data pointer */
+ void *data2; /**< User defined data pointer */
+} SDL_UserEvent;
+
+
+struct SDL_SysWMmsg;
+typedef struct SDL_SysWMmsg SDL_SysWMmsg;
+
+/**
+ * \brief A video driver dependent system event (event.syswm.*)
+ * This event is disabled by default, you can enable it with SDL_EventState()
+ *
+ * \note If you want to use this event, you should include SDL_syswm.h.
+ */
+typedef struct SDL_SysWMEvent
+{
+ Uint32 type; /**< ::SDL_SYSWMEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */
+} SDL_SysWMEvent;
+
+/**
+ * \brief General event structure
+ */
+typedef union SDL_Event
+{
+ Uint32 type; /**< Event type, shared with all events */
+ SDL_CommonEvent common; /**< Common event data */
+ SDL_DisplayEvent display; /**< Display event data */
+ SDL_WindowEvent window; /**< Window event data */
+ SDL_KeyboardEvent key; /**< Keyboard event data */
+ SDL_TextEditingEvent edit; /**< Text editing event data */
+ SDL_TextInputEvent text; /**< Text input event data */
+ SDL_MouseMotionEvent motion; /**< Mouse motion event data */
+ SDL_MouseButtonEvent button; /**< Mouse button event data */
+ SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */
+ SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */
+ SDL_JoyBallEvent jball; /**< Joystick ball event data */
+ SDL_JoyHatEvent jhat; /**< Joystick hat event data */
+ SDL_JoyButtonEvent jbutton; /**< Joystick button event data */
+ SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */
+ SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */
+ SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
+ SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
+ SDL_ControllerTouchpadEvent ctouchpad; /**< Game Controller touchpad event data */
+ SDL_ControllerSensorEvent csensor; /**< Game Controller sensor event data */
+ SDL_AudioDeviceEvent adevice; /**< Audio device event data */
+ SDL_SensorEvent sensor; /**< Sensor event data */
+ SDL_QuitEvent quit; /**< Quit request event data */
+ SDL_UserEvent user; /**< Custom event data */
+ SDL_SysWMEvent syswm; /**< System dependent window event data */
+ SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
+ SDL_MultiGestureEvent mgesture; /**< Gesture event data */
+ SDL_DollarGestureEvent dgesture; /**< Gesture event data */
+ SDL_DropEvent drop; /**< Drag and drop event data */
+
+ /* This is necessary for ABI compatibility between Visual C++ and GCC.
+ Visual C++ will respect the push pack pragma and use 52 bytes (size of
+ SDL_TextEditingEvent, the largest structure for 32-bit and 64-bit
+ architectures) for this union, and GCC will use the alignment of the
+ largest datatype within the union, which is 8 bytes on 64-bit
+ architectures.
+
+ So... we'll add padding to force the size to be 56 bytes for both.
+
+ On architectures where pointers are 16 bytes, this needs rounding up to
+ the next multiple of 16, 64, and on architectures where pointers are
+ even larger the size of SDL_UserEvent will dominate as being 3 pointers.
+ */
+ Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)];
+} SDL_Event;
+
+/* Make sure we haven't broken binary compatibility */
+SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding));
+
+
+/* Function prototypes */
+
+/**
+ * Pump the event loop, gathering events from the input devices.
+ *
+ * This function updates the event queue and internal input device state.
+ *
+ * **WARNING**: This should only be run in the thread that initialized the
+ * video subsystem, and for extra safety, you should consider only doing those
+ * things on the main thread in any case.
+ *
+ * SDL_PumpEvents() gathers all the pending input information from devices and
+ * places it in the event queue. Without calls to SDL_PumpEvents() no events
+ * would ever be placed on the queue. Often the need for calls to
+ * SDL_PumpEvents() is hidden from the user since SDL_PollEvent() and
+ * SDL_WaitEvent() implicitly call SDL_PumpEvents(). However, if you are not
+ * polling or waiting for events (e.g. you are filtering them), then you must
+ * call SDL_PumpEvents() to force an event queue update.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_WaitEvent
+ */
+extern DECLSPEC void SDLCALL SDL_PumpEvents(void);
+
+/* @{ */
+typedef enum
+{
+ SDL_ADDEVENT,
+ SDL_PEEKEVENT,
+ SDL_GETEVENT
+} SDL_eventaction;
+
+/**
+ * Check the event queue for messages and optionally return them.
+ *
+ * `action` may be any of the following:
+ *
+ * - `SDL_ADDEVENT`: up to `numevents` events will be added to the back of the
+ * event queue.
+ * - `SDL_PEEKEVENT`: `numevents` events at the front of the event queue,
+ * within the specified minimum and maximum type, will be returned to the
+ * caller and will _not_ be removed from the queue.
+ * - `SDL_GETEVENT`: up to `numevents` events at the front of the event queue,
+ * within the specified minimum and maximum type, will be returned to the
+ * caller and will be removed from the queue.
+ *
+ * You may have to call SDL_PumpEvents() before calling this function.
+ * Otherwise, the events may not be ready to be filtered when you call
+ * SDL_PeepEvents().
+ *
+ * This function is thread-safe.
+ *
+ * \param events destination buffer for the retrieved events
+ * \param numevents if action is SDL_ADDEVENT, the number of events to add
+ * back to the event queue; if action is SDL_PEEKEVENT or
+ * SDL_GETEVENT, the maximum number of events to retrieve
+ * \param action action to take; see [[#action|Remarks]] for details
+ * \param minType minimum value of the event type to be considered;
+ * SDL_FIRSTEVENT is a safe choice
+ * \param maxType maximum value of the event type to be considered;
+ * SDL_LASTEVENT is a safe choice
+ * \returns the number of events actually stored or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event * events, int numevents,
+ SDL_eventaction action,
+ Uint32 minType, Uint32 maxType);
+/* @} */
+
+/**
+ * Check for the existence of a certain event type in the event queue.
+ *
+ * If you need to check for a range of event types, use SDL_HasEvents()
+ * instead.
+ *
+ * \param type the type of event to be queried; see SDL_EventType for details
+ * \returns SDL_TRUE if events matching `type` are present, or SDL_FALSE if
+ * events matching `type` are not present.
+ *
+ * \sa SDL_HasEvents
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasEvent(Uint32 type);
+
+
+/**
+ * Check for the existence of certain event types in the event queue.
+ *
+ * If you need to check for a single event type, use SDL_HasEvent() instead.
+ *
+ * \param minType the low end of event type to be queried, inclusive; see
+ * SDL_EventType for details
+ * \param maxType the high end of event type to be queried, inclusive; see
+ * SDL_EventType for details
+ * \returns SDL_TRUE if events with type >= `minType` and <= `maxType` are
+ * present, or SDL_FALSE if not.
+ *
+ * \sa SDL_HasEvents
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasEvents(Uint32 minType, Uint32 maxType);
+
+/**
+ * Clear events of a specific type from the event queue.
+ *
+ * This will unconditionally remove any events from the queue that match
+ * `type`. If you need to remove a range of event types, use SDL_FlushEvents()
+ * instead.
+ *
+ * It's also normal to just ignore events you don't care about in your event
+ * loop without calling this function.
+ *
+ * This function only affects currently queued events. If you want to make
+ * sure that all pending OS events are flushed, you can call SDL_PumpEvents()
+ * on the main thread immediately before the flush call.
+ *
+ * \param type the type of event to be cleared; see SDL_EventType for details
+ *
+ * \sa SDL_FlushEvents
+ */
+extern DECLSPEC void SDLCALL SDL_FlushEvent(Uint32 type);
+
+/**
+ * Clear events of a range of types from the event queue.
+ *
+ * This will unconditionally remove any events from the queue that are in the
+ * range of `minType` to `maxType`, inclusive. If you need to remove a single
+ * event type, use SDL_FlushEvent() instead.
+ *
+ * It's also normal to just ignore events you don't care about in your event
+ * loop without calling this function.
+ *
+ * This function only affects currently queued events. If you want to make
+ * sure that all pending OS events are flushed, you can call SDL_PumpEvents()
+ * on the main thread immediately before the flush call.
+ *
+ * \param minType the low end of event type to be cleared, inclusive; see
+ * SDL_EventType for details
+ * \param maxType the high end of event type to be cleared, inclusive; see
+ * SDL_EventType for details
+ *
+ * \sa SDL_FlushEvent
+ */
+extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType);
+
+/**
+ * Poll for currently pending events.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`. The 1 returned refers to
+ * this event, immediately stored in the SDL Event structure -- not an event
+ * to follow.
+ *
+ * If `event` is NULL, it simply returns 1 if there is an event in the queue,
+ * but will not remove it from the queue.
+ *
+ * As this function implicitly calls SDL_PumpEvents(), you can only call this
+ * function in the thread that set the video mode.
+ *
+ * SDL_PollEvent() is the favored way of receiving system events since it can
+ * be done from the main loop and does not suspend the main loop while waiting
+ * on an event to be posted.
+ *
+ * The common practice is to fully process the event queue once every frame,
+ * usually as a first step before updating the game's state:
+ *
+ * ```c
+ * while (game_is_still_running) {
+ * SDL_Event event;
+ * while (SDL_PollEvent(&event)) { // poll until all events are handled!
+ * // decide what to do with this event.
+ * }
+ *
+ * // update game state, draw the current frame
+ * }
+ * ```
+ *
+ * \param event the SDL_Event structure to be filled with the next event from
+ * the queue, or NULL
+ * \returns 1 if there is a pending event or 0 if there are none available.
+ *
+ * \sa SDL_GetEventFilter
+ * \sa SDL_PeepEvents
+ * \sa SDL_PushEvent
+ * \sa SDL_SetEventFilter
+ * \sa SDL_WaitEvent
+ * \sa SDL_WaitEventTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event);
+
+/**
+ * Wait indefinitely for the next available event.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`.
+ *
+ * As this function implicitly calls SDL_PumpEvents(), you can only call this
+ * function in the thread that initialized the video subsystem.
+ *
+ * \param event the SDL_Event structure to be filled in with the next event
+ * from the queue, or NULL
+ * \returns 1 on success or 0 if there was an error while waiting for events;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_WaitEventTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event);
+
+/**
+ * Wait until the specified timeout (in milliseconds) for the next available
+ * event.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`.
+ *
+ * As this function implicitly calls SDL_PumpEvents(), you can only call this
+ * function in the thread that initialized the video subsystem.
+ *
+ * \param event the SDL_Event structure to be filled in with the next event
+ * from the queue, or NULL
+ * \param timeout the maximum number of milliseconds to wait for the next
+ * available event
+ * \returns 1 on success or 0 if there was an error while waiting for events;
+ * call SDL_GetError() for more information. This also returns 0 if
+ * the timeout elapsed without an event arriving.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_WaitEvent
+ */
+extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event * event,
+ int timeout);
+
+/**
+ * Add an event to the event queue.
+ *
+ * The event queue can actually be used as a two way communication channel.
+ * Not only can events be read from the queue, but the user can also push
+ * their own events onto it. `event` is a pointer to the event structure you
+ * wish to push onto the queue. The event is copied into the queue, and the
+ * caller may dispose of the memory pointed to after SDL_PushEvent() returns.
+ *
+ * Note: Pushing device input events onto the queue doesn't modify the state
+ * of the device within SDL.
+ *
+ * This function is thread-safe, and can be called from other threads safely.
+ *
+ * Note: Events pushed onto the queue with SDL_PushEvent() get passed through
+ * the event filter but events added with SDL_PeepEvents() do not.
+ *
+ * For pushing application-specific events, please use SDL_RegisterEvents() to
+ * get an event type that does not conflict with other code that also wants
+ * its own custom event types.
+ *
+ * \param event the SDL_Event to be added to the queue
+ * \returns 1 on success, 0 if the event was filtered, or a negative error
+ * code on failure; call SDL_GetError() for more information. A
+ * common reason for error is the event queue being full.
+ *
+ * \sa SDL_PeepEvents
+ * \sa SDL_PollEvent
+ * \sa SDL_RegisterEvents
+ */
+extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event);
+
+/**
+ * A function pointer used for callbacks that watch the event queue.
+ *
+ * \param userdata what was passed as `userdata` to SDL_SetEventFilter()
+ * or SDL_AddEventWatch, etc
+ * \param event the event that triggered the callback
+ * \returns 1 to permit event to be added to the queue, and 0 to disallow
+ * it. When used with SDL_AddEventWatch, the return value is ignored.
+ *
+ * \sa SDL_SetEventFilter
+ * \sa SDL_AddEventWatch
+ */
+typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event);
+
+/**
+ * Set up a filter to process all events before they change internal state and
+ * are posted to the internal event queue.
+ *
+ * If the filter function returns 1 when called, then the event will be added
+ * to the internal queue. If it returns 0, then the event will be dropped from
+ * the queue, but the internal state will still be updated. This allows
+ * selective filtering of dynamically arriving events.
+ *
+ * **WARNING**: Be very careful of what you do in the event filter function,
+ * as it may run in a different thread!
+ *
+ * On platforms that support it, if the quit event is generated by an
+ * interrupt signal (e.g. pressing Ctrl-C), it will be delivered to the
+ * application at the next event poll.
+ *
+ * There is one caveat when dealing with the ::SDL_QuitEvent event type. The
+ * event filter is only called when the window manager desires to close the
+ * application window. If the event filter returns 1, then the window will be
+ * closed, otherwise the window will remain open if possible.
+ *
+ * Note: Disabled events never make it to the event filter function; see
+ * SDL_EventState().
+ *
+ * Note: If you just want to inspect events without filtering, you should use
+ * SDL_AddEventWatch() instead.
+ *
+ * Note: Events pushed onto the queue with SDL_PushEvent() get passed through
+ * the event filter, but events pushed onto the queue with SDL_PeepEvents() do
+ * not.
+ *
+ * \param filter An SDL_EventFilter function to call when an event happens
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \sa SDL_AddEventWatch
+ * \sa SDL_EventState
+ * \sa SDL_GetEventFilter
+ * \sa SDL_PeepEvents
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Query the current event filter.
+ *
+ * This function can be used to "chain" filters, by saving the existing filter
+ * before replacing it with a function that will call that saved filter.
+ *
+ * \param filter the current callback function will be stored here
+ * \param userdata the pointer that is passed to the current event filter will
+ * be stored here
+ * \returns SDL_TRUE on success or SDL_FALSE if there is no event filter set.
+ *
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter * filter,
+ void **userdata);
+
+/**
+ * Add a callback to be triggered when an event is added to the event queue.
+ *
+ * `filter` will be called when an event happens, and its return value is
+ * ignored.
+ *
+ * **WARNING**: Be very careful of what you do in the event filter function,
+ * as it may run in a different thread!
+ *
+ * If the quit event is generated by a signal (e.g. SIGINT), it will bypass
+ * the internal queue and be delivered to the watch callback immediately, and
+ * arrive at the next event poll.
+ *
+ * Note: the callback is called for events posted by the user through
+ * SDL_PushEvent(), but not for disabled events, nor for events by a filter
+ * callback set with SDL_SetEventFilter(), nor for events posted by the user
+ * through SDL_PeepEvents().
+ *
+ * \param filter an SDL_EventFilter function to call when an event happens.
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \sa SDL_DelEventWatch
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC void SDLCALL SDL_AddEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Remove an event watch callback added with SDL_AddEventWatch().
+ *
+ * This function takes the same input as SDL_AddEventWatch() to identify and
+ * delete the corresponding callback.
+ *
+ * \param filter the function originally passed to SDL_AddEventWatch()
+ * \param userdata the pointer originally passed to SDL_AddEventWatch()
+ *
+ * \sa SDL_AddEventWatch
+ */
+extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Run a specific filter function on the current event queue, removing any
+ * events for which the filter returns 0.
+ *
+ * See SDL_SetEventFilter() for more information. Unlike SDL_SetEventFilter(),
+ * this function does not change the filter permanently, it only uses the
+ * supplied filter until this function returns.
+ *
+ * \param filter the SDL_EventFilter function to call when an event happens
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \sa SDL_GetEventFilter
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter,
+ void *userdata);
+
+/* @{ */
+#define SDL_QUERY -1
+#define SDL_IGNORE 0
+#define SDL_DISABLE 0
+#define SDL_ENABLE 1
+
+/**
+ * Set the state of processing events by type.
+ *
+ * `state` may be any of the following:
+ *
+ * - `SDL_QUERY`: returns the current processing state of the specified event
+ * - `SDL_IGNORE` (aka `SDL_DISABLE`): the event will automatically be dropped
+ * from the event queue and will not be filtered
+ * - `SDL_ENABLE`: the event will be processed normally
+ *
+ * \param type the type of event; see SDL_EventType for details
+ * \param state how to process the event
+ * \returns `SDL_DISABLE` or `SDL_ENABLE`, representing the processing state
+ * of the event before this function makes any changes to it.
+ *
+ * \sa SDL_GetEventState
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint32 type, int state);
+/* @} */
+#define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY)
+
+/**
+ * Allocate a set of user-defined events, and return the beginning event
+ * number for that set of events.
+ *
+ * Calling this function with `numevents` <= 0 is an error and will return
+ * (Uint32)-1.
+ *
+ * Note, (Uint32)-1 means the maximum unsigned 32-bit integer value (or
+ * 0xFFFFFFFF), but is clearer to write.
+ *
+ * \param numevents the number of events to be allocated
+ * \returns the beginning event number, or (Uint32)-1 if there are not enough
+ * user-defined events left.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_events_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_filesystem.h b/Client/ThirdParty/SDL2/SDL_filesystem.h
new file mode 100644
index 0000000..9dbd28f
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_filesystem.h
@@ -0,0 +1,145 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_filesystem.h
+ *
+ * \brief Include file for filesystem SDL API functions
+ */
+
+#ifndef SDL_filesystem_h_
+#define SDL_filesystem_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the directory where the application was run from.
+ *
+ * This is not necessarily a fast call, so you should call this once near
+ * startup and save the string if you need it.
+ *
+ * **Mac OS X and iOS Specific Functionality**: If the application is in a
+ * ".app" bundle, this function returns the Resource directory (e.g.
+ * MyApp.app/Contents/Resources/). This behaviour can be overridden by adding
+ * a property to the Info.plist file. Adding a string key with the name
+ * SDL_FILESYSTEM_BASE_DIR_TYPE with a supported value will change the
+ * behaviour.
+ *
+ * Supported values for the SDL_FILESYSTEM_BASE_DIR_TYPE property (Given an
+ * application in /Applications/SDLApp/MyApp.app):
+ *
+ * - `resource`: bundle resource directory (the default). For example:
+ * `/Applications/SDLApp/MyApp.app/Contents/Resources`
+ * - `bundle`: the Bundle directory. Fpr example:
+ * `/Applications/SDLApp/MyApp.app/`
+ * - `parent`: the containing directory of the bundle. For example:
+ * `/Applications/SDLApp/`
+ *
+ * The returned path is guaranteed to end with a path separator ('\' on
+ * Windows, '/' on most other platforms).
+ *
+ * The pointer returned is owned by the caller. Please call SDL_free() on the
+ * pointer when done with it.
+ *
+ * \returns an absolute path in UTF-8 encoding to the application data
+ * directory. NULL will be returned on error or when the platform
+ * doesn't implement this functionality, call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_GetPrefPath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetBasePath(void);
+
+/**
+ * Get the user-and-app-specific path where files can be written.
+ *
+ * Get the "pref dir". This is meant to be where users can write personal
+ * files (preferences and save games, etc) that are specific to your
+ * application. This directory is unique per user, per application.
+ *
+ * This function will decide the appropriate location in the native
+ * filesystem, create the directory if necessary, and return a string of the
+ * absolute path to the directory in UTF-8 encoding.
+ *
+ * On Windows, the string might look like:
+ *
+ * `C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\`
+ *
+ * On Linux, the string might look like"
+ *
+ * `/home/bob/.local/share/My Program Name/`
+ *
+ * On Mac OS X, the string might look like:
+ *
+ * `/Users/bob/Library/Application Support/My Program Name/`
+ *
+ * You should assume the path returned by this function is the only safe place
+ * to write files (and that SDL_GetBasePath(), while it might be writable, or
+ * even the parent of the returned path, isn't where you should be writing
+ * things).
+ *
+ * Both the org and app strings may become part of a directory name, so please
+ * follow these rules:
+ *
+ * - Try to use the same org string (_including case-sensitivity_) for all
+ * your applications that use this function.
+ * - Always use a unique app string for each one, and make sure it never
+ * changes for an app once you've decided on it.
+ * - Unicode characters are legal, as long as it's UTF-8 encoded, but...
+ * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
+ * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
+ *
+ * The returned path is guaranteed to end with a path separator ('\' on
+ * Windows, '/' on most other platforms).
+ *
+ * The pointer returned is owned by the caller. Please call SDL_free() on the
+ * pointer when done with it.
+ *
+ * \param org the name of your organization
+ * \param app the name of your application
+ * \returns a UTF-8 string of the user directory in platform-dependent
+ * notation. NULL if there's a problem (creating directory failed,
+ * etc.).
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_GetBasePath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_filesystem_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_gamecontroller.h b/Client/ThirdParty/SDL2/SDL_gamecontroller.h
new file mode 100644
index 0000000..cf1bd48
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_gamecontroller.h
@@ -0,0 +1,870 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gamecontroller.h
+ *
+ * Include file for SDL game controller event handling
+ */
+
+#ifndef SDL_gamecontroller_h_
+#define SDL_gamecontroller_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_rwops.h"
+#include "SDL_sensor.h"
+#include "SDL_joystick.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_gamecontroller.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_GAMECONTROLLER flag. This causes SDL to scan the system
+ * for game controllers, and load appropriate drivers.
+ *
+ * If you would like to receive controller updates while the application
+ * is in the background, you should set the following hint before calling
+ * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+ */
+
+/**
+ * The gamecontroller structure used to identify an SDL game controller
+ */
+struct _SDL_GameController;
+typedef struct _SDL_GameController SDL_GameController;
+
+typedef enum
+{
+ SDL_CONTROLLER_TYPE_UNKNOWN = 0,
+ SDL_CONTROLLER_TYPE_XBOX360,
+ SDL_CONTROLLER_TYPE_XBOXONE,
+ SDL_CONTROLLER_TYPE_PS3,
+ SDL_CONTROLLER_TYPE_PS4,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO,
+ SDL_CONTROLLER_TYPE_VIRTUAL,
+ SDL_CONTROLLER_TYPE_PS5,
+ SDL_CONTROLLER_TYPE_AMAZON_LUNA,
+ SDL_CONTROLLER_TYPE_GOOGLE_STADIA
+} SDL_GameControllerType;
+
+typedef enum
+{
+ SDL_CONTROLLER_BINDTYPE_NONE = 0,
+ SDL_CONTROLLER_BINDTYPE_BUTTON,
+ SDL_CONTROLLER_BINDTYPE_AXIS,
+ SDL_CONTROLLER_BINDTYPE_HAT
+} SDL_GameControllerBindType;
+
+/**
+ * Get the SDL joystick layer binding for this controller button/axis mapping
+ */
+typedef struct SDL_GameControllerButtonBind
+{
+ SDL_GameControllerBindType bindType;
+ union
+ {
+ int button;
+ int axis;
+ struct {
+ int hat;
+ int hat_mask;
+ } hat;
+ } value;
+
+} SDL_GameControllerButtonBind;
+
+
+/**
+ * To count the number of game controllers in the system for the following:
+ *
+ * ```c
+ * int nJoysticks = SDL_NumJoysticks();
+ * int nGameControllers = 0;
+ * for (int i = 0; i < nJoysticks; i++) {
+ * if (SDL_IsGameController(i)) {
+ * nGameControllers++;
+ * }
+ * }
+ * ```
+ *
+ * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping() you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
+ * guid,name,mappings
+ *
+ * Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
+ * Under Windows there is a reserved GUID of "xinput" that covers any XInput devices.
+ * The mapping format for joystick is:
+ * bX - a joystick button, index X
+ * hX.Y - hat X with value Y
+ * aX - axis X of the joystick
+ * Buttons can be used as a controller axis and vice versa.
+ *
+ * This string shows an example of a valid mapping for a controller
+ *
+ * ```c
+ * "03000000341a00003608000000000000,PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7",
+ * ```
+ */
+
+/**
+ * Load a set of Game Controller mappings from a seekable SDL data stream.
+ *
+ * You can call this function several times, if needed, to load different
+ * database files.
+ *
+ * If a new mapping is loaded for an already known controller GUID, the later
+ * version will overwrite the one currently loaded.
+ *
+ * Mappings not belonging to the current platform or with no platform field
+ * specified will be ignored (i.e. mappings for Linux will be ignored in
+ * Windows, etc).
+ *
+ * This function will load the text database entirely in memory before
+ * processing it, so take this into consideration if you are in a memory
+ * constrained environment.
+ *
+ * \param rw the data stream for the mappings to be added
+ * \param freerw non-zero to close the stream after being read
+ * \returns the number of mappings added or -1 on error; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GameControllerAddMapping
+ * \sa SDL_GameControllerAddMappingsFromFile
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMappingsFromRW(SDL_RWops * rw, int freerw);
+
+/**
+ * Load a set of mappings from a file, filtered by the current SDL_GetPlatform()
+ *
+ * Convenience macro.
+ */
+#define SDL_GameControllerAddMappingsFromFile(file) SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(file, "rb"), 1)
+
+/**
+ * Add support for controllers that SDL is unaware of or to cause an existing
+ * controller to have a different binding.
+ *
+ * The mapping string has the format "GUID,name,mapping", where GUID is the
+ * string value from SDL_JoystickGetGUIDString(), name is the human readable
+ * string for the device and mappings are controller mappings to joystick
+ * ones. Under Windows there is a reserved GUID of "xinput" that covers all
+ * XInput devices. The mapping format for joystick is: {| |bX |a joystick
+ * button, index X |- |hX.Y |hat X with value Y |- |aX |axis X of the joystick
+ * |} Buttons can be used as a controller axes and vice versa.
+ *
+ * This string shows an example of a valid mapping for a controller:
+ *
+ * ```c
+ * "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7"
+ * ```
+ *
+ * \param mappingString the mapping string
+ * \returns 1 if a new mapping is added, 0 if an existing mapping is updated,
+ * -1 on error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_GameControllerMapping
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping(const char* mappingString);
+
+/**
+ * Get the number of mappings installed.
+ *
+ * \returns the number of mappings.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerNumMappings(void);
+
+/**
+ * Get the mapping at a particular index.
+ *
+ * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
+ * the index is out of range.
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForIndex(int mapping_index);
+
+/**
+ * Get the game controller mapping string for a given GUID.
+ *
+ * The returned string must be freed with SDL_free().
+ *
+ * \param guid a structure containing the GUID for which a mapping is desired
+ * \returns a mapping string or NULL on error; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUID
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid);
+
+/**
+ * Get the current mapping of a Game Controller.
+ *
+ * The returned string must be freed with SDL_free().
+ *
+ * Details about mappings are discussed with SDL_GameControllerAddMapping().
+ *
+ * \param gamecontroller the game controller you want to get the current
+ * mapping for
+ * \returns a string that has the controller's mapping or NULL if no mapping
+ * is available; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerAddMapping
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMapping(SDL_GameController *gamecontroller);
+
+/**
+ * Check if the given joystick is supported by the game controller interface.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, up to
+ * SDL_NumJoysticks()
+ * \returns SDL_TRUE if the given joystick is supported by the game controller
+ * interface, SDL_FALSE if it isn't or it's an invalid index.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsGameController(int joystick_index);
+
+/**
+ * Get the implementation dependent name for the game controller.
+ *
+ * This function can be called before any controllers are opened.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the implementation-dependent name for the game controller, or NULL
+ * if there is no name or the index is invalid.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerName
+ * \sa SDL_GameControllerOpen
+ * \sa SDL_IsGameController
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index);
+
+/**
+ * Get the type of a game controller.
+ *
+ * This can be called before any controllers are opened.
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the controller type.
+ */
+extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerTypeForIndex(int joystick_index);
+
+/**
+ * Get the mapping of a game controller.
+ *
+ * This can be called before any controllers are opened.
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
+ * no mapping is available.
+ */
+extern DECLSPEC char *SDLCALL SDL_GameControllerMappingForDeviceIndex(int joystick_index);
+
+/**
+ * Open a game controller for use.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * The index passed as an argument refers to the N'th game controller on the
+ * system. This index is not the value which will identify this controller in
+ * future controller events. The joystick's instance id (SDL_JoystickID) will
+ * be used there instead.
+ *
+ * \param joystick_index the device_index of a device, up to
+ * SDL_NumJoysticks()
+ * \returns a gamecontroller identifier or NULL if an error occurred; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerClose
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_IsGameController
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_index);
+
+/**
+ * Get the SDL_GameController associated with an instance id.
+ *
+ * \param joyid the instance id to get the SDL_GameController for
+ * \returns an SDL_GameController on success or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid);
+
+/**
+ * Get the SDL_GameController associated with a player index.
+ *
+ * Please note that the player index is _not_ the device index, nor is it the
+ * instance id!
+ *
+ * \param player_index the player index, which is not the device index or the
+ * instance id!
+ * \returns the SDL_GameController associated with a player index.
+ *
+ * \sa SDL_GameControllerGetPlayerIndex
+ * \sa SDL_GameControllerSetPlayerIndex
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index);
+
+/**
+ * Get the implementation-dependent name for an opened game controller.
+ *
+ * This is the same name as returned by SDL_GameControllerNameForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns the implementation dependent name for the game controller, or NULL
+ * if there is no name or the identifier passed is invalid.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller);
+
+/**
+ * Get the type of this currently opened controller
+ *
+ * This is the same name as returned by SDL_GameControllerTypeForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the controller type.
+ */
+extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_GameController *gamecontroller);
+
+/**
+ * Get the player index of an opened game controller.
+ *
+ * For XInput controllers this returns the XInput user index.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the player index for controller, or -1 if it's not available.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller);
+
+/**
+ * Set the player index of an opened game controller.
+ *
+ * \param gamecontroller the game controller object to adjust.
+ * \param player_index Player index to assign to this controller.
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index);
+
+/**
+ * Get the USB vendor ID of an opened controller, if available.
+ *
+ * If the vendor ID isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB vendor ID, or zero if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetVendor(SDL_GameController *gamecontroller);
+
+/**
+ * Get the USB product ID of an opened controller, if available.
+ *
+ * If the product ID isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB product ID, or zero if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProduct(SDL_GameController *gamecontroller);
+
+/**
+ * Get the product version of an opened controller, if available.
+ *
+ * If the product version isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB product version, or zero if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller);
+
+/**
+ * Get the serial number of an opened controller, if available.
+ *
+ * Returns the serial number of the controller, or NULL if it is not
+ * available.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the serial number, or NULL if unavailable.
+ */
+extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
+
+/**
+ * Check if a controller has been opened and is currently connected.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns SDL_TRUE if the controller has been opened and is currently
+ * connected, or SDL_FALSE if not.
+ *
+ * \sa SDL_GameControllerClose
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerGetAttached(SDL_GameController *gamecontroller);
+
+/**
+ * Get the Joystick ID from a Game Controller.
+ *
+ * This function will give you a SDL_Joystick object, which allows you to use
+ * the SDL_Joystick functions with a SDL_GameController object. This would be
+ * useful for getting a joystick's position at any given time, even if it
+ * hasn't moved (moving it would produce an event, which would have the axis'
+ * value).
+ *
+ * The pointer returned is owned by the SDL_GameController. You should not
+ * call SDL_JoystickClose() on it, for example, since doing so will likely
+ * cause SDL to crash.
+ *
+ * \param gamecontroller the game controller object that you want to get a
+ * joystick from
+ * \returns a SDL_Joystick object; call SDL_GetError() for more information.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller);
+
+/**
+ * Query or change current state of Game Controller events.
+ *
+ * If controller events are disabled, you must call SDL_GameControllerUpdate()
+ * yourself and check the state of the controller when you want controller
+ * information.
+ *
+ * Any number can be passed to SDL_GameControllerEventState(), but only -1, 0,
+ * and 1 will have any effect. Other numbers will just be returned.
+ *
+ * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE`
+ * \returns the same value passed to the function, with exception to -1
+ * (SDL_QUERY), which will return the current state.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickEventState
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerEventState(int state);
+
+/**
+ * Manually pump game controller updates if not using the loop.
+ *
+ * This function is called automatically by the event loop if events are
+ * enabled. Under such circumstances, it will not be necessary to call this
+ * function.
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void);
+
+
+/**
+ * The list of axes available from a controller
+ *
+ * Thumbstick axis values range from SDL_JOYSTICK_AXIS_MIN to SDL_JOYSTICK_AXIS_MAX,
+ * and are centered within ~8000 of zero, though advanced UI will allow users to set
+ * or autodetect the dead zone, which varies between controllers.
+ *
+ * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX.
+ */
+typedef enum
+{
+ SDL_CONTROLLER_AXIS_INVALID = -1,
+ SDL_CONTROLLER_AXIS_LEFTX,
+ SDL_CONTROLLER_AXIS_LEFTY,
+ SDL_CONTROLLER_AXIS_RIGHTX,
+ SDL_CONTROLLER_AXIS_RIGHTY,
+ SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+ SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+ SDL_CONTROLLER_AXIS_MAX
+} SDL_GameControllerAxis;
+
+/**
+ * Convert a string into SDL_GameControllerAxis enum.
+ *
+ * This function is called internally to translate SDL_GameController mapping
+ * strings for the underlying joystick device into the consistent
+ * SDL_GameController mapping. You do not normally need to call this function
+ * unless you are parsing SDL_GameController mappings in your own code.
+ *
+ * Note specially that "righttrigger" and "lefttrigger" map to
+ * `SDL_CONTROLLER_AXIS_TRIGGERRIGHT` and `SDL_CONTROLLER_AXIS_TRIGGERLEFT`,
+ * respectively.
+ *
+ * \param str string representing a SDL_GameController axis
+ * \returns the SDL_GameControllerAxis enum corresponding to the input string,
+ * or `SDL_CONTROLLER_AXIS_INVALID` if no match was found.
+ *
+ * \sa SDL_GameControllerGetStringForAxis
+ */
+extern DECLSPEC SDL_GameControllerAxis SDLCALL SDL_GameControllerGetAxisFromString(const char *str);
+
+/**
+ * Convert from an SDL_GameControllerAxis enum to a string.
+ *
+ * The caller should not SDL_free() the returned string.
+ *
+ * \param axis an enum value for a given SDL_GameControllerAxis
+ * \returns a string for the given axis, or NULL if an invalid axis is
+ * specified. The string returned is of the format used by
+ * SDL_GameController mapping strings.
+ *
+ * \sa SDL_GameControllerGetAxisFromString
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis);
+
+/**
+ * Get the SDL joystick layer binding for a controller axis mapping.
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis enum value (one of the SDL_GameControllerAxis values)
+ * \returns a SDL_GameControllerButtonBind describing the bind. On failure
+ * (like the given Controller axis doesn't exist on the device), its
+ * `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetBindForButton
+ */
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller,
+ SDL_GameControllerAxis axis);
+
+/**
+ * Query whether a game controller has a given axis.
+ *
+ * This merely reports whether the controller's mapping defined this axis, as
+ * that is all the information SDL has about the physical device.
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis enum value (an SDL_GameControllerAxis value)
+ * \returns SDL_TRUE if the controller has this axis, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL
+SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+/**
+ * Get the current state of an axis control on a game controller.
+ *
+ * The axis indices start at index 0.
+ *
+ * The state is a value ranging from -32768 to 32767. Triggers, however, range
+ * from 0 to 32767 (they never return a negative value).
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis index (one of the SDL_GameControllerAxis values)
+ * \returns axis state (including 0) on success or 0 (also) on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetButton
+ */
+extern DECLSPEC Sint16 SDLCALL
+SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+/**
+ * The list of buttons available from a controller
+ */
+typedef enum
+{
+ SDL_CONTROLLER_BUTTON_INVALID = -1,
+ SDL_CONTROLLER_BUTTON_A,
+ SDL_CONTROLLER_BUTTON_B,
+ SDL_CONTROLLER_BUTTON_X,
+ SDL_CONTROLLER_BUTTON_Y,
+ SDL_CONTROLLER_BUTTON_BACK,
+ SDL_CONTROLLER_BUTTON_GUIDE,
+ SDL_CONTROLLER_BUTTON_START,
+ SDL_CONTROLLER_BUTTON_LEFTSTICK,
+ SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+ SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+ SDL_CONTROLLER_BUTTON_DPAD_UP,
+ SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+ SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+ SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+ SDL_CONTROLLER_BUTTON_MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
+ SDL_CONTROLLER_BUTTON_PADDLE1, /* Xbox Elite paddle P1 */
+ SDL_CONTROLLER_BUTTON_PADDLE2, /* Xbox Elite paddle P3 */
+ SDL_CONTROLLER_BUTTON_PADDLE3, /* Xbox Elite paddle P2 */
+ SDL_CONTROLLER_BUTTON_PADDLE4, /* Xbox Elite paddle P4 */
+ SDL_CONTROLLER_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */
+ SDL_CONTROLLER_BUTTON_MAX
+} SDL_GameControllerButton;
+
+/**
+ * Convert a string into an SDL_GameControllerButton enum.
+ *
+ * This function is called internally to translate SDL_GameController mapping
+ * strings for the underlying joystick device into the consistent
+ * SDL_GameController mapping. You do not normally need to call this function
+ * unless you are parsing SDL_GameController mappings in your own code.
+ *
+ * \param str string representing a SDL_GameController axis
+ * \returns the SDL_GameControllerButton enum corresponding to the input
+ * string, or `SDL_CONTROLLER_AXIS_INVALID` if no match was found.
+ */
+extern DECLSPEC SDL_GameControllerButton SDLCALL SDL_GameControllerGetButtonFromString(const char *str);
+
+/**
+ * Convert from an SDL_GameControllerButton enum to a string.
+ *
+ * The caller should not SDL_free() the returned string.
+ *
+ * \param button an enum value for a given SDL_GameControllerButton
+ * \returns a string for the given button, or NULL if an invalid axis is
+ * specified. The string returned is of the format used by
+ * SDL_GameController mapping strings.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetButtonFromString
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForButton(SDL_GameControllerButton button);
+
+/**
+ * Get the SDL joystick layer binding for a controller button mapping.
+ *
+ * \param gamecontroller a game controller
+ * \param button an button enum value (an SDL_GameControllerButton value)
+ * \returns a SDL_GameControllerButtonBind describing the bind. On failure
+ * (like the given Controller button doesn't exist on the device),
+ * its `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetBindForAxis
+ */
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Query whether a game controller has a given button.
+ *
+ * This merely reports whether the controller's mapping defined this button,
+ * as that is all the information SDL has about the physical device.
+ *
+ * \param gamecontroller a game controller
+ * \param button a button enum value (an SDL_GameControllerButton value)
+ * \returns SDL_TRUE if the controller has this button, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Get the current state of a button on a game controller.
+ *
+ * \param gamecontroller a game controller
+ * \param button a button index (one of the SDL_GameControllerButton values)
+ * \returns 1 for pressed state or 0 for not pressed state or error; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetAxis
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Get the number of touchpads on a game controller.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller);
+
+/**
+ * Get the number of supported simultaneous fingers on a touchpad on a game
+ * controller.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, int touchpad);
+
+/**
+ * Get the current state of a finger on a touchpad on a game controller.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure);
+
+/**
+ * Return whether a game controller has a particular sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \returns SDL_TRUE if the sensor exists, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Set whether data reporting for a game controller sensor is enabled.
+ *
+ * \param gamecontroller The controller to update
+ * \param type The type of sensor to enable/disable
+ * \param enabled Whether data reporting should be enabled
+ * \returns 0 or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled);
+
+/**
+ * Query whether sensor data reporting is enabled for a game controller.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \returns SDL_TRUE if the sensor is enabled, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Get the data rate (number of events per second) of a game controller
+ * sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \return the data rate, or 0.0f if the data rate is not available.
+ */
+extern DECLSPEC float SDLCALL SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Get the current state of a game controller sensor.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ * See SDL_sensor.h for the details for each type of sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \param data A pointer filled with the current sensor state
+ * \param num_values The number of values to write to data
+ * \return 0 or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values);
+
+/**
+ * Start a rumble effect on a game controller.
+ *
+ * Each call to this function cancels any previous rumble effect, and calling
+ * it with 0 intensity stops any rumbling.
+ *
+ * \param gamecontroller The controller to vibrate
+ * \param low_frequency_rumble The intensity of the low frequency (left)
+ * rumble motor, from 0 to 0xFFFF
+ * \param high_frequency_rumble The intensity of the high frequency (right)
+ * rumble motor, from 0 to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if rumble isn't supported on this controller
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
+
+/**
+ * Start a rumble effect in the game controller's triggers.
+ *
+ * Each call to this function cancels any previous trigger rumble effect, and
+ * calling it with 0 intensity stops any rumbling.
+ *
+ * Note that this is rumbling of the _triggers_ and not the game controller as
+ * a whole. The first controller to offer this feature was the PlayStation 5's
+ * DualShock 5.
+ *
+ * \param gamecontroller The controller to vibrate
+ * \param left_rumble The intensity of the left trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param right_rumble The intensity of the right trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if trigger rumble isn't supported on this controller
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms);
+
+/**
+ * Query whether a game controller has an LED.
+ *
+ * \param gamecontroller The controller to query
+ * \returns SDL_TRUE, or SDL_FALSE if this controller does not have a
+ * modifiable LED
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasLED(SDL_GameController *gamecontroller);
+
+/**
+ * Update a game controller's LED color.
+ *
+ * \param gamecontroller The controller to update
+ * \param red The intensity of the red LED
+ * \param green The intensity of the green LED
+ * \param blue The intensity of the blue LED
+ * \returns 0, or -1 if this controller does not have a modifiable LED
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue);
+
+/**
+ * Send a controller specific effect packet
+ *
+ * \param gamecontroller The controller to affect
+ * \param data The data to send to the controller
+ * \param size The size of the data to send to the controller
+ * \returns 0, or -1 if this controller or driver doesn't support effect
+ * packets
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSendEffect(SDL_GameController *gamecontroller, const void *data, int size);
+
+/**
+ * Close a game controller previously opened with SDL_GameControllerOpen().
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ *
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerClose(SDL_GameController *gamecontroller);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_gamecontroller_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_gesture.h b/Client/ThirdParty/SDL2/SDL_gesture.h
new file mode 100644
index 0000000..530b3d5
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_gesture.h
@@ -0,0 +1,117 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gesture.h
+ *
+ * Include file for SDL gesture event handling.
+ */
+
+#ifndef SDL_gesture_h_
+#define SDL_gesture_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "SDL_touch.h"
+
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_GestureID;
+
+/* Function prototypes */
+
+/**
+ * Begin recording a gesture on a specified touch device or all touch devices.
+ *
+ * If the parameter `touchId` is -1 (i.e., all devices), this function will
+ * always return 1, regardless of whether there actually are any devices.
+ *
+ * \param touchId the touch device id, or -1 for all touch devices
+ * \returns 1 on success or 0 if the specified device could not be found.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchDevice
+ */
+extern DECLSPEC int SDLCALL SDL_RecordGesture(SDL_TouchID touchId);
+
+
+/**
+ * Save all currently loaded Dollar Gesture templates.
+ *
+ * \param dst a SDL_RWops to save to
+ * \returns the number of saved templates on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadDollarTemplates
+ * \sa SDL_SaveDollarTemplate
+ */
+extern DECLSPEC int SDLCALL SDL_SaveAllDollarTemplates(SDL_RWops *dst);
+
+/**
+ * Save a currently loaded Dollar Gesture template.
+ *
+ * \param gestureId a gesture id
+ * \param dst a SDL_RWops to save to
+ * \returns 1 on success or 0 on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadDollarTemplates
+ * \sa SDL_SaveAllDollarTemplates
+ */
+extern DECLSPEC int SDLCALL SDL_SaveDollarTemplate(SDL_GestureID gestureId,SDL_RWops *dst);
+
+
+/**
+ * Load Dollar Gesture templates from a file.
+ *
+ * \param touchId a touch id
+ * \param src a SDL_RWops to load from
+ * \returns the number of loaded templates on success or a negative error code
+ * (or 0) on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SaveAllDollarTemplates
+ * \sa SDL_SaveDollarTemplate
+ */
+extern DECLSPEC int SDLCALL SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_gesture_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_haptic.h b/Client/ThirdParty/SDL2/SDL_haptic.h
new file mode 100644
index 0000000..bb53ed3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_haptic.h
@@ -0,0 +1,1320 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_haptic.h
+ *
+ * \brief The SDL haptic subsystem allows you to control haptic (force feedback)
+ * devices.
+ *
+ * The basic usage is as follows:
+ * - Initialize the subsystem (::SDL_INIT_HAPTIC).
+ * - Open a haptic device.
+ * - SDL_HapticOpen() to open from index.
+ * - SDL_HapticOpenFromJoystick() to open from an existing joystick.
+ * - Create an effect (::SDL_HapticEffect).
+ * - Upload the effect with SDL_HapticNewEffect().
+ * - Run the effect with SDL_HapticRunEffect().
+ * - (optional) Free the effect with SDL_HapticDestroyEffect().
+ * - Close the haptic device with SDL_HapticClose().
+ *
+ * \par Simple rumble example:
+ * \code
+ * SDL_Haptic *haptic;
+ *
+ * // Open the device
+ * haptic = SDL_HapticOpen( 0 );
+ * if (haptic == NULL)
+ * return -1;
+ *
+ * // Initialize simple rumble
+ * if (SDL_HapticRumbleInit( haptic ) != 0)
+ * return -1;
+ *
+ * // Play effect at 50% strength for 2 seconds
+ * if (SDL_HapticRumblePlay( haptic, 0.5, 2000 ) != 0)
+ * return -1;
+ * SDL_Delay( 2000 );
+ *
+ * // Clean up
+ * SDL_HapticClose( haptic );
+ * \endcode
+ *
+ * \par Complete example:
+ * \code
+ * int test_haptic( SDL_Joystick * joystick ) {
+ * SDL_Haptic *haptic;
+ * SDL_HapticEffect effect;
+ * int effect_id;
+ *
+ * // Open the device
+ * haptic = SDL_HapticOpenFromJoystick( joystick );
+ * if (haptic == NULL) return -1; // Most likely joystick isn't haptic
+ *
+ * // See if it can do sine waves
+ * if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_SINE)==0) {
+ * SDL_HapticClose(haptic); // No sine effect
+ * return -1;
+ * }
+ *
+ * // Create the effect
+ * memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default
+ * effect.type = SDL_HAPTIC_SINE;
+ * effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
+ * effect.periodic.direction.dir[0] = 18000; // Force comes from south
+ * effect.periodic.period = 1000; // 1000 ms
+ * effect.periodic.magnitude = 20000; // 20000/32767 strength
+ * effect.periodic.length = 5000; // 5 seconds long
+ * effect.periodic.attack_length = 1000; // Takes 1 second to get max strength
+ * effect.periodic.fade_length = 1000; // Takes 1 second to fade away
+ *
+ * // Upload the effect
+ * effect_id = SDL_HapticNewEffect( haptic, &effect );
+ *
+ * // Test the effect
+ * SDL_HapticRunEffect( haptic, effect_id, 1 );
+ * SDL_Delay( 5000); // Wait for the effect to finish
+ *
+ * // We destroy the effect, although closing the device also does this
+ * SDL_HapticDestroyEffect( haptic, effect_id );
+ *
+ * // Close the device
+ * SDL_HapticClose(haptic);
+ *
+ * return 0; // Success
+ * }
+ * \endcode
+ */
+
+#ifndef SDL_haptic_h_
+#define SDL_haptic_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_joystick.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* FIXME: For SDL 2.1, adjust all the magnitude variables to be Uint16 (0xFFFF).
+ *
+ * At the moment the magnitude variables are mixed between signed/unsigned, and
+ * it is also not made clear that ALL of those variables expect a max of 0x7FFF.
+ *
+ * Some platforms may have higher precision than that (Linux FF, Windows XInput)
+ * so we should fix the inconsistency in favor of higher possible precision,
+ * adjusting for platforms that use different scales.
+ * -flibit
+ */
+
+/**
+ * \typedef SDL_Haptic
+ *
+ * \brief The haptic structure used to identify an SDL haptic.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticOpenFromJoystick
+ * \sa SDL_HapticClose
+ */
+struct _SDL_Haptic;
+typedef struct _SDL_Haptic SDL_Haptic;
+
+
+/**
+ * \name Haptic features
+ *
+ * Different haptic features a device can have.
+ */
+/* @{ */
+
+/**
+ * \name Haptic effects
+ */
+/* @{ */
+
+/**
+ * \brief Constant effect supported.
+ *
+ * Constant haptic effect.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_CONSTANT (1u<<0)
+
+/**
+ * \brief Sine wave effect supported.
+ *
+ * Periodic haptic effect that simulates sine waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SINE (1u<<1)
+
+/**
+ * \brief Left/Right effect supported.
+ *
+ * Haptic effect for direct control over high/low frequency motors.
+ *
+ * \sa SDL_HapticLeftRight
+ * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
+ * we ran out of bits, and this is important for XInput devices.
+ */
+#define SDL_HAPTIC_LEFTRIGHT (1u<<2)
+
+/* !!! FIXME: put this back when we have more bits in 2.1 */
+/* #define SDL_HAPTIC_SQUARE (1<<2) */
+
+/**
+ * \brief Triangle wave effect supported.
+ *
+ * Periodic haptic effect that simulates triangular waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_TRIANGLE (1u<<3)
+
+/**
+ * \brief Sawtoothup wave effect supported.
+ *
+ * Periodic haptic effect that simulates saw tooth up waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SAWTOOTHUP (1u<<4)
+
+/**
+ * \brief Sawtoothdown wave effect supported.
+ *
+ * Periodic haptic effect that simulates saw tooth down waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5)
+
+/**
+ * \brief Ramp effect supported.
+ *
+ * Ramp haptic effect.
+ *
+ * \sa SDL_HapticRamp
+ */
+#define SDL_HAPTIC_RAMP (1u<<6)
+
+/**
+ * \brief Spring effect supported - uses axes position.
+ *
+ * Condition haptic effect that simulates a spring. Effect is based on the
+ * axes position.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_SPRING (1u<<7)
+
+/**
+ * \brief Damper effect supported - uses axes velocity.
+ *
+ * Condition haptic effect that simulates dampening. Effect is based on the
+ * axes velocity.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_DAMPER (1u<<8)
+
+/**
+ * \brief Inertia effect supported - uses axes acceleration.
+ *
+ * Condition haptic effect that simulates inertia. Effect is based on the axes
+ * acceleration.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_INERTIA (1u<<9)
+
+/**
+ * \brief Friction effect supported - uses axes movement.
+ *
+ * Condition haptic effect that simulates friction. Effect is based on the
+ * axes movement.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_FRICTION (1u<<10)
+
+/**
+ * \brief Custom effect is supported.
+ *
+ * User defined custom haptic effect.
+ */
+#define SDL_HAPTIC_CUSTOM (1u<<11)
+
+/* @} *//* Haptic effects */
+
+/* These last few are features the device has, not effects */
+
+/**
+ * \brief Device can set global gain.
+ *
+ * Device supports setting the global gain.
+ *
+ * \sa SDL_HapticSetGain
+ */
+#define SDL_HAPTIC_GAIN (1u<<12)
+
+/**
+ * \brief Device can set autocenter.
+ *
+ * Device supports setting autocenter.
+ *
+ * \sa SDL_HapticSetAutocenter
+ */
+#define SDL_HAPTIC_AUTOCENTER (1u<<13)
+
+/**
+ * \brief Device can be queried for effect status.
+ *
+ * Device supports querying effect status.
+ *
+ * \sa SDL_HapticGetEffectStatus
+ */
+#define SDL_HAPTIC_STATUS (1u<<14)
+
+/**
+ * \brief Device can be paused.
+ *
+ * Devices supports being paused.
+ *
+ * \sa SDL_HapticPause
+ * \sa SDL_HapticUnpause
+ */
+#define SDL_HAPTIC_PAUSE (1u<<15)
+
+
+/**
+ * \name Direction encodings
+ */
+/* @{ */
+
+/**
+ * \brief Uses polar coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_POLAR 0
+
+/**
+ * \brief Uses cartesian coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_CARTESIAN 1
+
+/**
+ * \brief Uses spherical coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_SPHERICAL 2
+
+/**
+ * \brief Use this value to play an effect on the steering wheel axis. This
+ * provides better compatibility across platforms and devices as SDL will guess
+ * the correct axis.
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_STEERING_AXIS 3
+
+/* @} *//* Direction encodings */
+
+/* @} *//* Haptic features */
+
+/*
+ * Misc defines.
+ */
+
+/**
+ * \brief Used to play a device an infinite number of times.
+ *
+ * \sa SDL_HapticRunEffect
+ */
+#define SDL_HAPTIC_INFINITY 4294967295U
+
+
+/**
+ * \brief Structure that represents a haptic direction.
+ *
+ * This is the direction where the force comes from,
+ * instead of the direction in which the force is exerted.
+ *
+ * Directions can be specified by:
+ * - ::SDL_HAPTIC_POLAR : Specified by polar coordinates.
+ * - ::SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates.
+ * - ::SDL_HAPTIC_SPHERICAL : Specified by spherical coordinates.
+ *
+ * Cardinal directions of the haptic device are relative to the positioning
+ * of the device. North is considered to be away from the user.
+ *
+ * The following diagram represents the cardinal directions:
+ * \verbatim
+ .--.
+ |__| .-------.
+ |=.| |.-----.|
+ |--| || ||
+ | | |'-----'|
+ |__|~')_____('
+ [ COMPUTER ]
+
+
+ North (0,-1)
+ ^
+ |
+ |
+ (-1,0) West <----[ HAPTIC ]----> East (1,0)
+ |
+ |
+ v
+ South (0,1)
+
+
+ [ USER ]
+ \|||/
+ (o o)
+ ---ooO-(_)-Ooo---
+ \endverbatim
+ *
+ * If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a
+ * degree starting north and turning clockwise. ::SDL_HAPTIC_POLAR only uses
+ * the first \c dir parameter. The cardinal directions would be:
+ * - North: 0 (0 degrees)
+ * - East: 9000 (90 degrees)
+ * - South: 18000 (180 degrees)
+ * - West: 27000 (270 degrees)
+ *
+ * If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions
+ * (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses
+ * the first three \c dir parameters. The cardinal directions would be:
+ * - North: 0,-1, 0
+ * - East: 1, 0, 0
+ * - South: 0, 1, 0
+ * - West: -1, 0, 0
+ *
+ * The Z axis represents the height of the effect if supported, otherwise
+ * it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you
+ * can use any multiple you want, only the direction matters.
+ *
+ * If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations.
+ * The first two \c dir parameters are used. The \c dir parameters are as
+ * follows (all values are in hundredths of degrees):
+ * - Degrees from (1, 0) rotated towards (0, 1).
+ * - Degrees towards (0, 0, 1) (device needs at least 3 axes).
+ *
+ *
+ * Example of force coming from the south with all encodings (force coming
+ * from the south means the user will have to pull the stick to counteract):
+ * \code
+ * SDL_HapticDirection direction;
+ *
+ * // Cartesian directions
+ * direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding.
+ * direction.dir[0] = 0; // X position
+ * direction.dir[1] = 1; // Y position
+ * // Assuming the device has 2 axes, we don't need to specify third parameter.
+ *
+ * // Polar directions
+ * direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding.
+ * direction.dir[0] = 18000; // Polar only uses first parameter
+ *
+ * // Spherical coordinates
+ * direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding
+ * direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters.
+ * \endcode
+ *
+ * \sa SDL_HAPTIC_POLAR
+ * \sa SDL_HAPTIC_CARTESIAN
+ * \sa SDL_HAPTIC_SPHERICAL
+ * \sa SDL_HAPTIC_STEERING_AXIS
+ * \sa SDL_HapticEffect
+ * \sa SDL_HapticNumAxes
+ */
+typedef struct SDL_HapticDirection
+{
+ Uint8 type; /**< The type of encoding. */
+ Sint32 dir[3]; /**< The encoded direction. */
+} SDL_HapticDirection;
+
+
+/**
+ * \brief A structure containing a template for a Constant effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_CONSTANT effect.
+ *
+ * A constant effect applies a constant force in the specified direction
+ * to the joystick.
+ *
+ * \sa SDL_HAPTIC_CONSTANT
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticConstant
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_CONSTANT */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Constant */
+ Sint16 level; /**< Strength of the constant effect. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticConstant;
+
+/**
+ * \brief A structure containing a template for a Periodic effect.
+ *
+ * The struct handles the following effects:
+ * - ::SDL_HAPTIC_SINE
+ * - ::SDL_HAPTIC_LEFTRIGHT
+ * - ::SDL_HAPTIC_TRIANGLE
+ * - ::SDL_HAPTIC_SAWTOOTHUP
+ * - ::SDL_HAPTIC_SAWTOOTHDOWN
+ *
+ * A periodic effect consists in a wave-shaped effect that repeats itself
+ * over time. The type determines the shape of the wave and the parameters
+ * determine the dimensions of the wave.
+ *
+ * Phase is given by hundredth of a degree meaning that giving the phase a value
+ * of 9000 will displace it 25% of its period. Here are sample values:
+ * - 0: No phase displacement.
+ * - 9000: Displaced 25% of its period.
+ * - 18000: Displaced 50% of its period.
+ * - 27000: Displaced 75% of its period.
+ * - 36000: Displaced 100% of its period, same as 0, but 0 is preferred.
+ *
+ * Examples:
+ * \verbatim
+ SDL_HAPTIC_SINE
+ __ __ __ __
+ / \ / \ / \ /
+ / \__/ \__/ \__/
+
+ SDL_HAPTIC_SQUARE
+ __ __ __ __ __
+ | | | | | | | | | |
+ | |__| |__| |__| |__| |
+
+ SDL_HAPTIC_TRIANGLE
+ /\ /\ /\ /\ /\
+ / \ / \ / \ / \ /
+ / \/ \/ \/ \/
+
+ SDL_HAPTIC_SAWTOOTHUP
+ /| /| /| /| /| /| /|
+ / | / | / | / | / | / | / |
+ / |/ |/ |/ |/ |/ |/ |
+
+ SDL_HAPTIC_SAWTOOTHDOWN
+ \ |\ |\ |\ |\ |\ |\ |
+ \ | \ | \ | \ | \ | \ | \ |
+ \| \| \| \| \| \| \|
+ \endverbatim
+ *
+ * \sa SDL_HAPTIC_SINE
+ * \sa SDL_HAPTIC_LEFTRIGHT
+ * \sa SDL_HAPTIC_TRIANGLE
+ * \sa SDL_HAPTIC_SAWTOOTHUP
+ * \sa SDL_HAPTIC_SAWTOOTHDOWN
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticPeriodic
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT,
+ ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or
+ ::SDL_HAPTIC_SAWTOOTHDOWN */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Periodic */
+ Uint16 period; /**< Period of the wave. */
+ Sint16 magnitude; /**< Peak value; if negative, equivalent to 180 degrees extra phase shift. */
+ Sint16 offset; /**< Mean value of the wave. */
+ Uint16 phase; /**< Positive phase shift given by hundredth of a degree. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticPeriodic;
+
+/**
+ * \brief A structure containing a template for a Condition effect.
+ *
+ * The struct handles the following effects:
+ * - ::SDL_HAPTIC_SPRING: Effect based on axes position.
+ * - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity.
+ * - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration.
+ * - ::SDL_HAPTIC_FRICTION: Effect based on axes movement.
+ *
+ * Direction is handled by condition internals instead of a direction member.
+ * The condition effect specific members have three parameters. The first
+ * refers to the X axis, the second refers to the Y axis and the third
+ * refers to the Z axis. The right terms refer to the positive side of the
+ * axis and the left terms refer to the negative side of the axis. Please
+ * refer to the ::SDL_HapticDirection diagram for which side is positive and
+ * which is negative.
+ *
+ * \sa SDL_HapticDirection
+ * \sa SDL_HAPTIC_SPRING
+ * \sa SDL_HAPTIC_DAMPER
+ * \sa SDL_HAPTIC_INERTIA
+ * \sa SDL_HAPTIC_FRICTION
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticCondition
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER,
+ ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION */
+ SDL_HapticDirection direction; /**< Direction of the effect - Not used ATM. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Condition */
+ Uint16 right_sat[3]; /**< Level when joystick is to the positive side; max 0xFFFF. */
+ Uint16 left_sat[3]; /**< Level when joystick is to the negative side; max 0xFFFF. */
+ Sint16 right_coeff[3]; /**< How fast to increase the force towards the positive side. */
+ Sint16 left_coeff[3]; /**< How fast to increase the force towards the negative side. */
+ Uint16 deadband[3]; /**< Size of the dead zone; max 0xFFFF: whole axis-range when 0-centered. */
+ Sint16 center[3]; /**< Position of the dead zone. */
+} SDL_HapticCondition;
+
+/**
+ * \brief A structure containing a template for a Ramp effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_RAMP effect.
+ *
+ * The ramp effect starts at start strength and ends at end strength.
+ * It augments in linear fashion. If you use attack and fade with a ramp
+ * the effects get added to the ramp effect making the effect become
+ * quadratic instead of linear.
+ *
+ * \sa SDL_HAPTIC_RAMP
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticRamp
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_RAMP */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Ramp */
+ Sint16 start; /**< Beginning strength level. */
+ Sint16 end; /**< Ending strength level. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticRamp;
+
+/**
+ * \brief A structure containing a template for a Left/Right effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
+ *
+ * The Left/Right effect is used to explicitly control the large and small
+ * motors, commonly found in modern game controllers. The small (right) motor
+ * is high frequency, and the large (left) motor is low frequency.
+ *
+ * \sa SDL_HAPTIC_LEFTRIGHT
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticLeftRight
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect in milliseconds. */
+
+ /* Rumble */
+ Uint16 large_magnitude; /**< Control of the large controller motor. */
+ Uint16 small_magnitude; /**< Control of the small controller motor. */
+} SDL_HapticLeftRight;
+
+/**
+ * \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_CUSTOM effect.
+ *
+ * A custom force feedback effect is much like a periodic effect, where the
+ * application can define its exact shape. You will have to allocate the
+ * data yourself. Data should consist of channels * samples Uint16 samples.
+ *
+ * If channels is one, the effect is rotated using the defined direction.
+ * Otherwise it uses the samples in data for the different axes.
+ *
+ * \sa SDL_HAPTIC_CUSTOM
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticCustom
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_CUSTOM */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Custom */
+ Uint8 channels; /**< Axes to use, minimum of one. */
+ Uint16 period; /**< Sample periods. */
+ Uint16 samples; /**< Amount of samples. */
+ Uint16 *data; /**< Should contain channels*samples items. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticCustom;
+
+/**
+ * \brief The generic template for any haptic effect.
+ *
+ * All values max at 32767 (0x7FFF). Signed values also can be negative.
+ * Time values unless specified otherwise are in milliseconds.
+ *
+ * You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767
+ * value. Neither delay, interval, attack_length nor fade_length support
+ * ::SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends.
+ *
+ * Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of
+ * ::SDL_HAPTIC_INFINITY.
+ *
+ * Button triggers may not be supported on all devices, it is advised to not
+ * use them if possible. Buttons start at index 1 instead of index 0 like
+ * the joystick.
+ *
+ * If both attack_length and fade_level are 0, the envelope is not used,
+ * otherwise both values are used.
+ *
+ * Common parts:
+ * \code
+ * // Replay - All effects have this
+ * Uint32 length; // Duration of effect (ms).
+ * Uint16 delay; // Delay before starting effect.
+ *
+ * // Trigger - All effects have this
+ * Uint16 button; // Button that triggers effect.
+ * Uint16 interval; // How soon before effect can be triggered again.
+ *
+ * // Envelope - All effects except condition effects have this
+ * Uint16 attack_length; // Duration of the attack (ms).
+ * Uint16 attack_level; // Level at the start of the attack.
+ * Uint16 fade_length; // Duration of the fade out (ms).
+ * Uint16 fade_level; // Level at the end of the fade.
+ * \endcode
+ *
+ *
+ * Here we have an example of a constant effect evolution in time:
+ * \verbatim
+ Strength
+ ^
+ |
+ | effect level --> _________________
+ | / \
+ | / \
+ | / \
+ | / \
+ | attack_level --> | \
+ | | | <--- fade_level
+ |
+ +--------------------------------------------------> Time
+ [--] [---]
+ attack_length fade_length
+
+ [------------------][-----------------------]
+ delay length
+ \endverbatim
+ *
+ * Note either the attack_level or the fade_level may be above the actual
+ * effect level.
+ *
+ * \sa SDL_HapticConstant
+ * \sa SDL_HapticPeriodic
+ * \sa SDL_HapticCondition
+ * \sa SDL_HapticRamp
+ * \sa SDL_HapticLeftRight
+ * \sa SDL_HapticCustom
+ */
+typedef union SDL_HapticEffect
+{
+ /* Common for all force feedback effects */
+ Uint16 type; /**< Effect type. */
+ SDL_HapticConstant constant; /**< Constant effect. */
+ SDL_HapticPeriodic periodic; /**< Periodic effect. */
+ SDL_HapticCondition condition; /**< Condition effect. */
+ SDL_HapticRamp ramp; /**< Ramp effect. */
+ SDL_HapticLeftRight leftright; /**< Left/Right effect. */
+ SDL_HapticCustom custom; /**< Custom effect. */
+} SDL_HapticEffect;
+
+
+/* Function prototypes */
+/**
+ * Count the number of haptic devices attached to the system.
+ *
+ * \returns the number of haptic devices detected on the system or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticName
+ */
+extern DECLSPEC int SDLCALL SDL_NumHaptics(void);
+
+/**
+ * Get the implementation dependent name of a haptic device.
+ *
+ * This can be called before any joysticks are opened. If no name can be
+ * found, this function returns NULL.
+ *
+ * \param device_index index of the device to query.
+ * \returns the name of the device or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_NumHaptics
+ */
+extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index);
+
+/**
+ * Open a haptic device for use.
+ *
+ * The index passed as an argument refers to the N'th haptic device on this
+ * system.
+ *
+ * When opening a haptic device, its gain will be set to maximum and
+ * autocenter will be disabled. To modify these values use SDL_HapticSetGain()
+ * and SDL_HapticSetAutocenter().
+ *
+ * \param device_index index of the device to open
+ * \returns the device identifier or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticClose
+ * \sa SDL_HapticIndex
+ * \sa SDL_HapticOpenFromJoystick
+ * \sa SDL_HapticOpenFromMouse
+ * \sa SDL_HapticPause
+ * \sa SDL_HapticSetAutocenter
+ * \sa SDL_HapticSetGain
+ * \sa SDL_HapticStopAll
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpen(int device_index);
+
+/**
+ * Check if the haptic device at the designated index has been opened.
+ *
+ * \param device_index the index of the device to query
+ * \returns 1 if it has been opened, 0 if it hasn't or on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticIndex
+ * \sa SDL_HapticOpen
+ */
+extern DECLSPEC int SDLCALL SDL_HapticOpened(int device_index);
+
+/**
+ * Get the index of a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the index of the specified haptic device or a negative error code
+ * on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticOpened
+ */
+extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic);
+
+/**
+ * Query whether or not the current mouse has haptic capabilities.
+ *
+ * \returns SDL_TRUE if the mouse is haptic or SDL_FALSE if it isn't.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpenFromMouse
+ */
+extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void);
+
+/**
+ * Try to open a haptic device from the current mouse.
+ *
+ * \returns the haptic device identifier or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_MouseIsHaptic
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromMouse(void);
+
+/**
+ * Query if a joystick has haptic features.
+ *
+ * \param joystick the SDL_Joystick to test for haptic capabilities
+ * \returns SDL_TRUE if the joystick is haptic, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpenFromJoystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick);
+
+/**
+ * Open a haptic device for use from a joystick device.
+ *
+ * You must still close the haptic device separately. It will not be closed
+ * with the joystick.
+ *
+ * When opened from a joystick you should first close the haptic device before
+ * closing the joystick device. If not, on some implementations the haptic
+ * device will also get unallocated and you'll be unable to use force feedback
+ * on that device.
+ *
+ * \param joystick the SDL_Joystick to create a haptic device from
+ * \returns a valid haptic device identifier on success or NULL on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticClose
+ * \sa SDL_HapticOpen
+ * \sa SDL_JoystickIsHaptic
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromJoystick(SDL_Joystick *
+ joystick);
+
+/**
+ * Close a haptic device previously opened with SDL_HapticOpen().
+ *
+ * \param haptic the SDL_Haptic device to close
+ *
+ * \sa SDL_HapticOpen
+ */
+extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic);
+
+/**
+ * Get the number of effects a haptic device can store.
+ *
+ * On some platforms this isn't fully supported, and therefore is an
+ * approximation. Always check to see if your created effect was actually
+ * created and do not rely solely on SDL_HapticNumEffects().
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the number of effects the haptic device can store or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNumEffectsPlaying
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic);
+
+/**
+ * Get the number of effects a haptic device can play at the same time.
+ *
+ * This is not supported on all platforms, but will always return a value.
+ *
+ * \param haptic the SDL_Haptic device to query maximum playing effects
+ * \returns the number of effects the haptic device can play at the same time
+ * or a negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNumEffects
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic);
+
+/**
+ * Get the haptic device's supported features in bitwise manner.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns a list of supported haptic features in bitwise manner (OR'd), or 0
+ * on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticEffectSupported
+ * \sa SDL_HapticNumEffects
+ */
+extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic);
+
+
+/**
+ * Get the number of haptic axes the device has.
+ *
+ * The number of haptic axes might be useful if working with the
+ * SDL_HapticDirection effect.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the number of axes on success or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumAxes(SDL_Haptic * haptic);
+
+/**
+ * Check to see if an effect is supported by a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \param effect the desired effect to query
+ * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNewEffect
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic,
+ SDL_HapticEffect *
+ effect);
+
+/**
+ * Create a new haptic effect on a specified device.
+ *
+ * \param haptic an SDL_Haptic device to create the effect on
+ * \param effect an SDL_HapticEffect structure containing the properties of
+ * the effect to create
+ * \returns the ID of the effect on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticRunEffect
+ * \sa SDL_HapticUpdateEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic,
+ SDL_HapticEffect * effect);
+
+/**
+ * Update the properties of an effect.
+ *
+ * Can be used dynamically, although behavior when dynamically changing
+ * direction may be strange. Specifically the effect may re-upload itself and
+ * start playing from the start. You also cannot change the type either when
+ * running SDL_HapticUpdateEffect().
+ *
+ * \param haptic the SDL_Haptic device that has the effect
+ * \param effect the identifier of the effect to update
+ * \param data an SDL_HapticEffect structure containing the new effect
+ * properties to use
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticNewEffect
+ * \sa SDL_HapticRunEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic,
+ int effect,
+ SDL_HapticEffect * data);
+
+/**
+ * Run the haptic effect on its associated haptic device.
+ *
+ * To repeat the effect over and over indefinitely, set `iterations` to
+ * `SDL_HAPTIC_INFINITY`. (Repeats the envelope - attack and fade.) To make
+ * one instance of the effect last indefinitely (so the effect does not fade),
+ * set the effect's `length` in its structure/union to `SDL_HAPTIC_INFINITY`
+ * instead.
+ *
+ * \param haptic the SDL_Haptic device to run the effect on
+ * \param effect the ID of the haptic effect to run
+ * \param iterations the number of iterations to run the effect; use
+ * `SDL_HAPTIC_INFINITY` to repeat forever
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticGetEffectStatus
+ * \sa SDL_HapticStopEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic,
+ int effect,
+ Uint32 iterations);
+
+/**
+ * Stop the haptic effect on its associated haptic device.
+ *
+ * *
+ *
+ * \param haptic the SDL_Haptic device to stop the effect on
+ * \param effect the ID of the haptic effect to stop
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticRunEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Destroy a haptic effect on the device.
+ *
+ * This will stop the effect if it's running. Effects are automatically
+ * destroyed when the device is closed.
+ *
+ * \param haptic the SDL_Haptic device to destroy the effect on
+ * \param effect the ID of the haptic effect to destroy
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNewEffect
+ */
+extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Get the status of the current effect on the specified haptic device.
+ *
+ * Device must support the SDL_HAPTIC_STATUS feature.
+ *
+ * \param haptic the SDL_Haptic device to query for the effect status on
+ * \param effect the ID of the haptic effect to query its status
+ * \returns 0 if it isn't playing, 1 if it is playing, or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticRunEffect
+ * \sa SDL_HapticStopEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Set the global gain of the specified haptic device.
+ *
+ * Device must support the SDL_HAPTIC_GAIN feature.
+ *
+ * The user may specify the maximum gain by setting the environment variable
+ * `SDL_HAPTIC_GAIN_MAX` which should be between 0 and 100. All calls to
+ * SDL_HapticSetGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the
+ * maximum.
+ *
+ * \param haptic the SDL_Haptic device to set the gain on
+ * \param gain value to set the gain to, should be between 0 and 100 (0 - 100)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain);
+
+/**
+ * Set the global autocenter of the device.
+ *
+ * Autocenter should be between 0 and 100. Setting it to 0 will disable
+ * autocentering.
+ *
+ * Device must support the SDL_HAPTIC_AUTOCENTER feature.
+ *
+ * \param haptic the SDL_Haptic device to set autocentering on
+ * \param autocenter value to set autocenter to (0-100)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic,
+ int autocenter);
+
+/**
+ * Pause a haptic device.
+ *
+ * Device must support the `SDL_HAPTIC_PAUSE` feature. Call
+ * SDL_HapticUnpause() to resume playback.
+ *
+ * Do not modify the effects nor add new ones while the device is paused. That
+ * can cause all sorts of weird errors.
+ *
+ * \param haptic the SDL_Haptic device to pause
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticUnpause
+ */
+extern DECLSPEC int SDLCALL SDL_HapticPause(SDL_Haptic * haptic);
+
+/**
+ * Unpause a haptic device.
+ *
+ * Call to unpause after SDL_HapticPause().
+ *
+ * \param haptic the SDL_Haptic device to unpause
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticPause
+ */
+extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic);
+
+/**
+ * Stop all the currently playing effects on a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to stop
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_HapticStopAll(SDL_Haptic * haptic);
+
+/**
+ * Check whether rumble is supported on a haptic device.
+ *
+ * \param haptic haptic device to check for rumble support
+ * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleStop
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic);
+
+/**
+ * Initialize a haptic device for simple rumble playback.
+ *
+ * \param haptic the haptic device to initialize for simple rumble playback
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleStop
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic);
+
+/**
+ * Run a simple rumble effect on a haptic device.
+ *
+ * \param haptic the haptic device to play the rumble effect on
+ * \param strength strength of the rumble to play as a 0-1 float value
+ * \param length length of the rumble to play in milliseconds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumbleStop
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length );
+
+/**
+ * Stop the simple rumble on a haptic device.
+ *
+ * \param haptic the haptic device to stop the rumble effect on
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_haptic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_hints.h b/Client/ThirdParty/SDL2/SDL_hints.h
new file mode 100644
index 0000000..c3ae80d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_hints.h
@@ -0,0 +1,1840 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_hints.h
+ *
+ * Official documentation for SDL configuration variables
+ *
+ * This file contains functions to set and get configuration hints,
+ * as well as listing each of them alphabetically.
+ *
+ * The convention for naming hints is SDL_HINT_X, where "SDL_X" is
+ * the environment variable that can be used to override the default.
+ *
+ * In general these hints are just that - they may or may not be
+ * supported or applicable on any given platform, but they provide
+ * a way for an application or user to give the library a hint as
+ * to how they would like the library to work.
+ */
+
+#ifndef SDL_hints_h_
+#define SDL_hints_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief A variable controlling whether the Android / iOS built-in
+ * accelerometer should be listed as a joystick device.
+ *
+ * This variable can be set to the following values:
+ * "0" - The accelerometer is not listed as a joystick
+ * "1" - The accelerometer is available as a 3 axis joystick (the default).
+ */
+#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK"
+
+/**
+ * \brief Specify the behavior of Alt+Tab while the keyboard is grabbed.
+ *
+ * By default, SDL emulates Alt+Tab functionality while the keyboard is grabbed
+ * and your window is full-screen. This prevents the user from getting stuck in
+ * your application if you've enabled keyboard grab.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will not handle Alt+Tab. Your application is responsible
+ for handling Alt+Tab while the keyboard is grabbed.
+ * "1" - SDL will minimize your window when Alt+Tab is pressed (default)
+*/
+#define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED"
+
+/**
+ * \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it.
+ * This is a debugging aid for developers and not expected to be used by end users. The default is "1"
+ *
+ * This variable can be set to the following values:
+ * "0" - don't allow topmost
+ * "1" - allow topmost
+ */
+#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"
+
+/**
+ * \brief Android APK expansion main file version. Should be a string number like "1", "2" etc.
+ *
+ * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION.
+ *
+ * If both hints were set then SDL_RWFromFile() will look into expansion files
+ * after a given relative path was not found in the internal storage and assets.
+ *
+ * By default this hint is not set and the APK expansion files are not searched.
+ */
+#define SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION"
+
+/**
+ * \brief Android APK expansion patch file version. Should be a string number like "1", "2" etc.
+ *
+ * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION.
+ *
+ * If both hints were set then SDL_RWFromFile() will look into expansion files
+ * after a given relative path was not found in the internal storage and assets.
+ *
+ * By default this hint is not set and the APK expansion files are not searched.
+ */
+#define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"
+
+/**
+ * \brief A variable to control whether the event loop will block itself when the app is paused.
+ *
+ * The variable can be set to the following values:
+ * "0" - Non blocking.
+ * "1" - Blocking. (default)
+ *
+ * The value should be set before SDL is initialized.
+ */
+#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE"
+
+/**
+ * \brief A variable to control whether SDL will pause audio in background
+ * (Requires SDL_ANDROID_BLOCK_ON_PAUSE as "Non blocking")
+ *
+ * The variable can be set to the following values:
+ * "0" - Non paused.
+ * "1" - Paused. (default)
+ *
+ * The value should be set before SDL is initialized.
+ */
+#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO"
+
+/**
+ * \brief A variable to control whether we trap the Android back button to handle it manually.
+ * This is necessary for the right mouse button to work on some Android devices, or
+ * to be able to trap the back button for use in your code reliably. If set to true,
+ * the back button will show up as an SDL_KEYDOWN / SDL_KEYUP pair with a keycode of
+ * SDL_SCANCODE_AC_BACK.
+ *
+ * The variable can be set to the following values:
+ * "0" - Back button will be handled as usual for system. (default)
+ * "1" - Back button will be trapped, allowing you to handle the key press
+ * manually. (This will also let right mouse click work on systems
+ * where the right mouse button functions as back.)
+ *
+ * The value of this hint is used at runtime, so it can be changed at any time.
+ */
+#define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON"
+
+/**
+ * \brief A variable controlling whether controllers used with the Apple TV
+ * generate UI events.
+ *
+ * When UI events are generated by controller input, the app will be
+ * backgrounded when the Apple TV remote's menu button is pressed, and when the
+ * pause or B buttons on gamepads are pressed.
+ *
+ * More information about properly making use of controllers for the Apple TV
+ * can be found here:
+ * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/
+ *
+ * This variable can be set to the following values:
+ * "0" - Controller input does not generate UI events (the default).
+ * "1" - Controller input generates UI events.
+ */
+#define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS"
+
+/**
+ * \brief A variable controlling whether the Apple TV remote's joystick axes
+ * will automatically match the rotation of the remote.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remote orientation does not affect joystick axes (the default).
+ * "1" - Joystick axes are based on the orientation of the remote.
+ */
+#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION"
+
+/**
+ * \brief A variable controlling the audio category on iOS and Mac OS X
+ *
+ * This variable can be set to the following values:
+ *
+ * "ambient" - Use the AVAudioSessionCategoryAmbient audio category, will be muted by the phone mute switch (default)
+ * "playback" - Use the AVAudioSessionCategoryPlayback category
+ *
+ * For more information, see Apple's documentation:
+ * https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html
+ */
+#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
+
+/**
+ * \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your program ("My Game 2: The Revenge")
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: probably the application's name or "SDL Application" if SDL
+ * doesn't have any better information.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME"
+
+/**
+ * \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing ("audio stream" is
+ * probably sufficient in many cases, but this could be useful for something
+ * like "team chat" if you have a headset playing VoIP audio separately).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "audio stream" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME"
+
+/**
+ * \brief Specify an application role for an audio device.
+ *
+ * Some audio backends (such as Pipewire) allow you to describe the role of
+ * your audio stream. Among other things, this description might show up in
+ * a system control panel or software for displaying and manipulating media
+ * playback/capture graphs.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing (Game, Music, Movie,
+ * etc...).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "Game" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE"
+
+/**
+ * \brief A variable controlling speed/quality tradeoff of audio resampling.
+ *
+ * If available, SDL can use libsamplerate ( http://www.mega-nerd.com/SRC/ )
+ * to handle audio resampling. There are different resampling modes available
+ * that produce different levels of quality, using more CPU.
+ *
+ * If this hint isn't specified to a valid setting, or libsamplerate isn't
+ * available, SDL will use the default, internal resampling algorithm.
+ *
+ * Note that this is currently only applicable to resampling audio that is
+ * being written to a device for playback or audio being read from a device
+ * for capture. SDL_AudioCVT always uses the default resampler (although this
+ * might change for SDL 2.1).
+ *
+ * This hint is currently only checked at audio subsystem initialization.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" or "default" - Use SDL's internal resampling (Default when not set - low quality, fast)
+ * "1" or "fast" - Use fast, slightly higher quality resampling, if available
+ * "2" or "medium" - Use medium quality resampling, if available
+ * "3" or "best" - Use high quality resampling, if available
+ */
+#define SDL_HINT_AUDIO_RESAMPLING_MODE "SDL_AUDIO_RESAMPLING_MODE"
+
+/**
+ * \brief A variable controlling whether SDL updates joystick state when getting input events
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - You'll call SDL_JoystickUpdate() manually
+ * "1" - SDL will automatically call SDL_JoystickUpdate() (default)
+ *
+ * This hint can be toggled on and off at runtime.
+ */
+#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS"
+
+/**
+ * \brief A variable controlling whether SDL updates sensor state when getting input events
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - You'll call SDL_SensorUpdate() manually
+ * "1" - SDL will automatically call SDL_SensorUpdate() (default)
+ *
+ * This hint can be toggled on and off at runtime.
+ */
+#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS"
+
+/**
+ * \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs.
+ *
+ * The bitmap header version 4 is required for proper alpha channel support and
+ * SDL will use it when required. Should this not be desired, this hint can
+ * force the use of the 40 byte header version which is supported everywhere.
+ *
+ * The variable can be set to the following values:
+ * "0" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file with an alpha mask. SDL will use the bitmap
+ * header version 4 and set the alpha mask accordingly.
+ * "1" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file without an alpha mask. The alpha channel data
+ * will be in the file, but applications are going to ignore it.
+ *
+ * The default value is "0".
+ */
+#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT"
+
+/**
+ * \brief Override for SDL_GetDisplayUsableBounds()
+ *
+ * If set, this hint will override the expected results for
+ * SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want
+ * to do this, but this allows an embedded system to request that some of the
+ * screen be reserved for other uses when paired with a well-behaved
+ * application.
+ *
+ * The contents of this hint must be 4 comma-separated integers, the first
+ * is the bounds x, then y, width and height, in that order.
+ */
+#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
+
+/**
+ * \brief Disable giving back control to the browser automatically
+ * when running with asyncify
+ *
+ * With -s ASYNCIFY, SDL2 calls emscripten_sleep during operations
+ * such as refreshing the screen or polling events.
+ *
+ * This hint only applies to the emscripten platform
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable emscripten_sleep calls (if you give back browser control manually or use asyncify for other purposes)
+ * "1" - Enable emscripten_sleep calls (the default)
+ */
+#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY"
+
+/**
+ * \brief override the binding element for keyboard inputs for Emscripten builds
+ *
+ * This hint only applies to the emscripten platform
+ *
+ * The variable can be one of
+ * "#window" - The javascript window object (this is the default)
+ * "#document" - The javascript document object
+ * "#screen" - the javascript window.screen object
+ * "#canvas" - the WebGL canvas element
+ * any other string without a leading # sign applies to the element on the page with that ID.
+ */
+#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
+
+/**
+ * \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
+ *
+ * The variable can be set to the following values:
+ * "0" - Do not scan for Steam Controllers
+ * "1" - Scan for Steam Controllers (the default)
+ *
+ * The default value is "1". This hint must be set before initializing the joystick subsystem.
+ */
+#define SDL_HINT_ENABLE_STEAM_CONTROLLERS "SDL_ENABLE_STEAM_CONTROLLERS"
+
+/**
+ * \brief A variable controlling whether SDL logs all events pushed onto its internal queue.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - Don't log any events (default)
+ * "1" - Log all events except mouse and finger motion, which are pretty spammy.
+ * "2" - Log all events.
+ *
+ * This is generally meant to be used to debug SDL itself, but can be useful
+ * for application developers that need better visibility into what is going
+ * on in the event queue. Logged events are sent through SDL_Log(), which
+ * means by default they appear on stdout on most platforms or maybe
+ * OutputDebugString() on Windows, and can be funneled by the app with
+ * SDL_LogSetOutputFunction(), etc.
+ *
+ * This hint can be toggled on and off at runtime, if you only need to log
+ * events for a small subset of program execution.
+ */
+#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING"
+
+/**
+ * \brief A variable controlling how 3D acceleration is used to accelerate the SDL screen surface.
+ *
+ * SDL can try to accelerate the SDL screen surface by using streaming
+ * textures with a 3D rendering engine. This variable controls whether and
+ * how this is done.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable 3D acceleration
+ * "1" - Enable 3D acceleration, using the default renderer.
+ * "X" - Enable 3D acceleration, using X where X is one of the valid rendering drivers. (e.g. "direct3d", "opengl", etc.)
+ *
+ * By default SDL tries to make a best guess for each platform whether
+ * to use acceleration or not.
+ */
+#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION"
+
+/**
+ * \brief A variable that lets you manually hint extra gamecontroller db entries.
+ *
+ * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping()
+ */
+#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG"
+
+/**
+ * \brief A variable that lets you provide a file with extra gamecontroller db entries.
+ *
+ * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping()
+ */
+#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE"
+
+/**
+ * \brief A variable that overrides the automatic controller type detection
+ *
+ * The variable should be comma separated entries, in the form: VID/PID=type
+ *
+ * The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd
+ *
+ * The type should be one of:
+ * Xbox360
+ * XboxOne
+ * PS3
+ * PS4
+ * PS5
+ * SwitchPro
+ *
+ * This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ */
+#define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE"
+
+/**
+ * \brief A variable containing a list of devices to skip when scanning for game controllers.
+ *
+ * The format of the string is a comma separated list of USB VID/PID pairs
+ * in hexadecimal form, e.g.
+ *
+ * 0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ * The variable can also take the form of @file, in which case the named
+ * file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES "SDL_GAMECONTROLLER_IGNORE_DEVICES"
+
+/**
+ * \brief If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable.
+ *
+ * The format of the string is a comma separated list of USB VID/PID pairs
+ * in hexadecimal form, e.g.
+ *
+ * 0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ * The variable can also take the form of @file, in which case the named
+ * file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
+
+/**
+ * \brief If set, game controller face buttons report their values according to their labels instead of their positional layout.
+ *
+ * For example, on Nintendo Switch controllers, normally you'd get:
+ *
+ * (Y)
+ * (X) (B)
+ * (A)
+ *
+ * but if this hint is set, you'll get:
+ *
+ * (X)
+ * (Y) (A)
+ * (B)
+ *
+ * The variable can be set to the following values:
+ * "0" - Report the face buttons by position, as though they were on an Xbox controller.
+ * "1" - Report the face buttons by label instead of position
+ *
+ * The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS"
+
+/**
+ * \brief A variable controlling whether grabbing input grabs the keyboard
+ *
+ * This variable can be set to the following values:
+ * "0" - Grab will affect only the mouse
+ * "1" - Grab will affect mouse and keyboard
+ *
+ * By default SDL will not grab the keyboard so system shortcuts still work.
+ */
+#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD"
+
+/**
+ * \brief A variable controlling whether the idle timer is disabled on iOS.
+ *
+ * When an iOS app does not receive touches for some time, the screen is
+ * dimmed automatically. For games where the accelerometer is the only input
+ * this is problematic. This functionality can be disabled by setting this
+ * hint.
+ *
+ * As of SDL 2.0.4, SDL_EnableScreenSaver() and SDL_DisableScreenSaver()
+ * accomplish the same thing on iOS. They should be preferred over this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Enable idle timer
+ * "1" - Disable idle timer
+ */
+#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED"
+
+/**
+ * \brief A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_TEXTEDITING events.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL_TEXTEDITING events are sent, and it is the application's
+ * responsibility to render the text from these events and
+ * differentiate it somehow from committed text. (default)
+ * "1" - If supported by the IME then SDL_TEXTEDITING events are not sent,
+ * and text that is being composed will be rendered in its own UI.
+ */
+#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
+
+/**
+ * \brief A variable controlling whether the home indicator bar on iPhone X
+ * should be hidden.
+ *
+ * This variable can be set to the following values:
+ * "0" - The indicator bar is not hidden (default for windowed applications)
+ * "1" - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications)
+ * "2" - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action (default for fullscreen applications)
+ */
+#define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR"
+
+/**
+ * \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable joystick & gamecontroller input events when the
+ * application is in the background.
+ * "1" - Enable joystick & gamecontroller input events when the
+ * application is in the background.
+ *
+ * The default value is "0". This hint may be set at any time.
+ */
+#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
+
+/**
+ * \brief A variable controlling whether the HIDAPI joystick drivers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI drivers are not used
+ * "1" - HIDAPI drivers are used (the default)
+ *
+ * This variable is the default for all drivers, but can be overridden by the hints for specific drivers below.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
+
+ /**
+ * \brief A variable controlling whether Switch Joy-Cons should be treated the same as Switch Pro Controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - basic Joy-Con support with no analog input (the default)
+ * "1" - Joy-Cons treated as half full Pro Controllers with analog inputs and sensors
+ *
+ * This does not combine Joy-Cons into a single controller. That's up to the user.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS"
+
+ /**
+ * \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_LUNA "SDL_JOYSTICK_HIDAPI_LUNA"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4"
+
+/**
+ * \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - extended reports are not enabled (the default)
+ * "1" - extended reports
+ *
+ * Extended input reports allow rumble on Bluetooth PS4 controllers, but
+ * break DirectInput handling for applications that don't use SDL.
+ *
+ * Once extended reports are enabled, they can not be disabled without
+ * power cycling the controller.
+ *
+ * For compatibility with applications written for versions of SDL prior
+ * to the introduction of PS5 controller support, this value will also
+ * control the state of extended reports on PS5 controllers when the
+ * SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE hint is not explicitly set.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS5 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5"
+
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller.
+ *
+ * This variable can be set to the following values:
+ * "0" - player LEDs are not enabled
+ * "1" - player LEDs are enabled (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED"
+
+/**
+ * \brief A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - extended reports are not enabled (the default)
+ * "1" - extended reports
+ *
+ * Extended input reports allow rumble on Bluetooth PS5 controllers, but
+ * break DirectInput handling for applications that don't use SDL.
+ *
+ * Once extended reports are enabled, they can not be disabled without
+ * power cycling the controller.
+ *
+ * For compatibility with applications written for versions of SDL prior
+ * to the introduction of PS5 controller support, this value defaults to
+ * the value of SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Steam Controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH"
+
+/**
+ * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch controller is opened
+ *
+ * This variable can be set to the following values:
+ * "0" - home button LED is left off
+ * "1" - home button LED is turned on (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
+
+ /**
+ * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices.
+ *
+ * This variable can be set to the following values:
+ * "0" - RAWINPUT drivers are not used
+ * "1" - RAWINPUT drivers are used (the default)
+ *
+ */
+#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT"
+
+ /**
+ * \brief A variable controlling whether the RAWINPUT driver should pull correlated data from XInput.
+ *
+ * This variable can be set to the following values:
+ * "0" - RAWINPUT driver will only use data from raw input APIs
+ * "1" - RAWINPUT driver will also pull data from XInput, providing
+ * better trigger axes, guide button presses, and rumble support
+ * for Xbox controllers
+ *
+ * The default is "1". This hint applies to any joysticks opened after setting the hint.
+ */
+#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT"
+
+ /**
+ * \brief A variable controlling whether a separate thread should be used
+ * for handling joystick detection and raw input messages on Windows
+ *
+ * This variable can be set to the following values:
+ * "0" - A separate thread is not used (the default)
+ * "1" - A separate thread is used for handling raw input messages
+ *
+ */
+#define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
+
+/**
+ * \brief Determines whether SDL enforces that DRM master is required in order
+ * to initialize the KMSDRM video backend.
+ *
+ * The DRM subsystem has a concept of a "DRM master" which is a DRM client that
+ * has the ability to set planes, set cursor, etc. When SDL is DRM master, it
+ * can draw to the screen using the SDL rendering APIs. Without DRM master, SDL
+ * is still able to process input and query attributes of attached displays,
+ * but it cannot change display state or draw to the screen directly.
+ *
+ * In some cases, it can be useful to have the KMSDRM backend even if it cannot
+ * be used for rendering. An app may want to use SDL for input processing while
+ * using another rendering API (such as an MMAL overlay on Raspberry Pi) or
+ * using its own code to render to DRM overlays that SDL doesn't support.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL will allow usage of the KMSDRM backend without DRM master
+ * "1" - SDL Will require DRM master to use the KMSDRM backend (default)
+ */
+#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER"
+
+ /**
+ * \brief A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values.
+ *
+ * This variable can be set to the following values:
+ * "0" - Return unfiltered joystick axis values (the default)
+ * "1" - Return axis values with deadzones taken into account
+ */
+#define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES"
+
+/**
+* \brief When set don't force the SDL app to become a foreground process
+*
+* This hint only applies to Mac OS X.
+*
+*/
+#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP"
+
+/**
+ * \brief A variable that determines whether ctrl+click should generate a right-click event on Mac
+ *
+ * If present, holding ctrl while left clicking will generate a right click
+ * event when on Mac.
+ */
+#define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK"
+
+/**
+ * \brief A variable setting the double click radius, in pixels.
+ */
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS"
+
+/**
+ * \brief A variable setting the double click time, in milliseconds.
+ */
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME"
+
+/**
+ * \brief Allow mouse click events when clicking to focus an SDL window
+ *
+ * This variable can be set to the following values:
+ * "0" - Ignore mouse clicks that activate a window
+ * "1" - Generate events for mouse clicks that activate a window
+ *
+ * By default SDL will ignore mouse clicks that activate a window
+ */
+#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH"
+
+/**
+ * \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode
+ */
+#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE"
+
+/**
+ * \brief A variable controlling whether relative mouse mode is implemented using mouse warping
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse mode uses raw input
+ * "1" - Relative mouse mode uses mouse warping
+ *
+ * By default SDL will use raw input for relative mouse mode
+ */
+#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP"
+
+/**
+ * \brief A variable controlling whether relative mouse motion is affected by renderer scaling
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative motion is unaffected by DPI or renderer's logical size
+ * "1" - Relative motion is scaled according to DPI scaling and logical size
+ *
+ * By default relative mouse deltas are affected by DPI and renderer scaling
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SCALING "SDL_MOUSE_RELATIVE_SCALING"
+
+/**
+ * \brief A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE"
+
+/**
+ * \brief A variable controlling whether mouse events should generate synthetic touch events
+ *
+ * This variable can be set to the following values:
+ * "0" - Mouse events will not generate touch events (default for desktop platforms)
+ * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS)
+ */
+#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS"
+
+/**
+ * \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
+ *
+ * This hint only applies to Unix-like platforms, and should set before
+ * any calls to SDL_Init()
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will install a SIGINT and SIGTERM handler, and when it
+ * catches a signal, convert it into an SDL_QUIT event.
+ * "1" - SDL will not install a signal handler at all.
+ */
+#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS"
+
+/**
+ * \brief A variable controlling what driver to use for OpenGL ES contexts.
+ *
+ * On some platforms, currently Windows and X11, OpenGL drivers may support
+ * creating contexts with an OpenGL ES profile. By default SDL uses these
+ * profiles, when available, otherwise it attempts to load an OpenGL ES
+ * library, e.g. that provided by the ANGLE project. This variable controls
+ * whether SDL follows this default behaviour or will always load an
+ * OpenGL ES library.
+ *
+ * Circumstances where this is useful include
+ * - Testing an app with a particular OpenGL ES implementation, e.g ANGLE,
+ * or emulator, e.g. those from ARM, Imagination or Qualcomm.
+ * - Resolving OpenGL ES function addresses at link time by linking with
+ * the OpenGL ES library instead of querying them at run time with
+ * SDL_GL_GetProcAddress().
+ *
+ * Caution: for an application to work with the default behaviour across
+ * different OpenGL drivers it must query the OpenGL ES function
+ * addresses at run time using SDL_GL_GetProcAddress().
+ *
+ * This variable is ignored on most platforms because OpenGL ES is native
+ * or not supported.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use ES profile of OpenGL, if available. (Default when not set.)
+ * "1" - Load OpenGL ES library using the default library names.
+ *
+ */
+#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER"
+
+/**
+ * \brief A variable controlling which orientations are allowed on iOS/Android.
+ *
+ * In some circumstances it is necessary to be able to explicitly control
+ * which UI orientations are allowed.
+ *
+ * This variable is a space delimited list of the following values:
+ * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
+ */
+#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
+
+/**
+ * \brief Override for SDL_GetPreferredLocales()
+ *
+ * If set, this will be favored over anything the OS might report for the
+ * user's preferred locales. Changing this hint at runtime will not generate
+ * a SDL_LOCALECHANGED event (but if you can change the hint, you can push
+ * your own event, if you want).
+ *
+ * The format of this hint is a comma-separated list of language and locale,
+ * combined with an underscore, as is a common format: "en_GB". Locale is
+ * optional: "en". So you might have a list like this: "en_GB,jp,es_PT"
+ */
+#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES"
+
+/**
+ * \brief A variable describing the content orientation on QtWayland-based platforms.
+ *
+ * On QtWayland platforms, windows are rotated client-side to allow for custom
+ * transitions. In order to correctly position overlays (e.g. volume bar) and
+ * gestures (e.g. events view, close/minimize gestures), the system needs to
+ * know in which orientation the application is currently drawing its contents.
+ *
+ * This does not cause the window to be rotated or resized, the application
+ * needs to take care of drawing the content in the right orientation (the
+ * framebuffer is always in portrait mode).
+ *
+ * This variable can be one of the following values:
+ * "primary" (default), "portrait", "landscape", "inverted-portrait", "inverted-landscape"
+ */
+#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION"
+
+/**
+ * \brief Flags to set on QtWayland windows to integrate with the native window manager.
+ *
+ * On QtWayland platforms, this hint controls the flags to set on the windows.
+ * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures.
+ *
+ * This variable is a space-separated list of the following values (empty = no flags):
+ * "OverridesSystemGestures", "StaysOnTop", "BypassWindowManager"
+ */
+#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS"
+
+/**
+ * \brief A variable controlling whether the 2D render API is compatible or efficient.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - Don't use batching to make rendering more efficient.
+ * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls.
+ *
+ * Up to SDL 2.0.9, the render API would draw immediately when requested. Now
+ * it batches up draw requests and sends them all to the GPU only when forced
+ * to (during SDL_RenderPresent, when changing render targets, by updating a
+ * texture that the batch needs, etc). This is significantly more efficient,
+ * but it can cause problems for apps that expect to render on top of the
+ * render API's output. As such, SDL will disable batching if a specific
+ * render backend is requested (since this might indicate that the app is
+ * planning to use the underlying graphics API directly). This hint can
+ * be used to explicitly request batching in this instance. It is a contract
+ * that you will either never use the underlying graphics API directly, or
+ * if you do, you will call SDL_RenderFlush() before you do so any current
+ * batch goes to the GPU before your work begins. Not following this contract
+ * will result in undefined behavior.
+ */
+#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING"
+
+/**
+ * \brief A variable controlling whether to enable Direct3D 11+'s Debug Layer.
+ *
+ * This variable does not have any effect on the Direct3D 9 based renderer.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable Debug Layer use
+ * "1" - Enable Debug Layer use
+ *
+ * By default, SDL does not use Direct3D Debug Layer.
+ */
+#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG"
+
+/**
+ * \brief A variable controlling whether the Direct3D device is initialized for thread-safe operations.
+ *
+ * This variable can be set to the following values:
+ * "0" - Thread-safety is not enabled (faster)
+ * "1" - Thread-safety is enabled
+ *
+ * By default the Direct3D device is created with thread-safety disabled.
+ */
+#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE"
+
+/**
+ * \brief A variable specifying which render driver to use.
+ *
+ * If the application doesn't pick a specific renderer to use, this variable
+ * specifies the name of the preferred renderer. If the preferred renderer
+ * can't be initialized, the normal default renderer is used.
+ *
+ * This variable is case insensitive and can be set to the following values:
+ * "direct3d"
+ * "opengl"
+ * "opengles2"
+ * "opengles"
+ * "metal"
+ * "software"
+ *
+ * The default varies by platform, but it's the first one in the list that
+ * is available on the current platform.
+ */
+#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER"
+
+/**
+ * \brief A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
+ *
+ * This variable can be set to the following values:
+ * "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen
+ * "1" or "overscan" - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
+ *
+ * By default letterbox is used
+ */
+#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE "SDL_RENDER_LOGICAL_SIZE_MODE"
+
+/**
+ * \brief A variable controlling whether the OpenGL render driver uses shaders if they are available.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable shaders
+ * "1" - Enable shaders
+ *
+ * By default shaders are used if OpenGL supports them.
+ */
+#define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS"
+
+/**
+ * \brief A variable controlling the scaling quality
+ *
+ * This variable can be set to the following values:
+ * "0" or "nearest" - Nearest pixel sampling
+ * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D)
+ * "2" or "best" - Currently this is the same as "linear"
+ *
+ * By default nearest pixel sampling is used
+ */
+#define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY"
+
+/**
+ * \brief A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable vsync
+ * "1" - Enable vsync
+ *
+ * By default SDL does not sync screen surface updates with vertical refresh.
+ */
+#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
+
+ /**
+ * \brief A variable to control whether the return key on the soft keyboard
+ * should hide the soft keyboard on Android and iOS.
+ *
+ * The variable can be set to the following values:
+ * "0" - The return key will be handled as a key event. This is the behaviour of SDL <= 2.0.3. (default)
+ * "1" - The return key will hide the keyboard.
+ *
+ * The value of this hint is used at runtime, so it can be changed at any time.
+ */
+#define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME"
+
+/**
+ * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI
+ *
+ * Also known as Z-order. The variable can take a negative or positive value.
+ * The default is 10000.
+ */
+#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER"
+
+/**
+ * \brief Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime.
+ *
+ * On some platforms, like Linux, a realtime priority thread may be subject to restrictions
+ * that require special handling by the application. This hint exists to let SDL know that
+ * the app is prepared to handle said restrictions.
+ *
+ * On Linux, SDL will apply the following configuration to any thread that becomes realtime:
+ * * The SCHED_RESET_ON_FORK bit will be set on the scheduling policy,
+ * * An RLIMIT_RTTIME budget will be configured to the rtkit specified limit.
+ * * Exceeding this limit will result in the kernel sending SIGKILL to the app,
+ * * Refer to the man pages for more information.
+ *
+ * This variable can be set to the following values:
+ * "0" - default platform specific behaviour
+ * "1" - Force SDL_THREAD_PRIORITY_TIME_CRITICAL to a realtime scheduling policy
+ */
+#define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL"
+
+/**
+* \brief A string specifying additional information to use with SDL_SetThreadPriority.
+*
+* By default SDL_SetThreadPriority will make appropriate system changes in order to
+* apply a thread priority. For example on systems using pthreads the scheduler policy
+* is changed automatically to a policy that works well with a given priority.
+* Code which has specific requirements can override SDL's default behavior with this hint.
+*
+* pthread hint values are "current", "other", "fifo" and "rr".
+* Currently no other platform hint values are defined but may be in the future.
+*
+* \note On Linux, the kernel may send SIGKILL to realtime tasks which exceed the distro
+* configured execution budget for rtkit. This budget can be queried through RLIMIT_RTTIME
+* after calling SDL_SetThreadPriority().
+*/
+#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY"
+
+/**
+* \brief A string specifying SDL's threads stack size in bytes or "0" for the backend's default size
+*
+* Use this hint in case you need to set SDL's threads stack size to other than the default.
+* This is specially useful if you build SDL against a non glibc libc library (such as musl) which
+* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
+* Support for this hint is currently available only in the pthread, Windows, and PSP backend.
+*
+* Instead of this hint, in 2.0.9 and later, you can use
+* SDL_CreateThreadWithStackSize(). This hint only works with the classic
+* SDL_CreateThread().
+*/
+#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE"
+
+/**
+ * \brief A variable that controls the timer resolution, in milliseconds.
+ *
+ * The higher resolution the timer, the more frequently the CPU services
+ * timer interrupts, and the more precise delays are, but this takes up
+ * power and CPU time. This hint is only used on Windows.
+ *
+ * See this blog post for more information:
+ * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
+ *
+ * If this variable is set to "0", the system timer resolution is not set.
+ *
+ * The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"
+
+/**
+ * \brief A variable controlling whether touch events should generate synthetic mouse events
+ *
+ * This variable can be set to the following values:
+ * "0" - Touch events will not generate mouse events
+ * "1" - Touch events will generate mouse events
+ *
+ * By default SDL will generate mouse events for touch events
+ */
+#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS"
+
+/**
+ * \brief A variable controlling whether the Android / tvOS remotes
+ * should be listed as joystick devices, instead of sending keyboard events.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remotes send enter/escape/arrow key events
+ * "1" - Remotes are available as 2 axis, 2 button joysticks (the default).
+ */
+#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK"
+
+/**
+ * \brief A variable controlling whether the screensaver is enabled.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable screensaver
+ * "1" - Enable screensaver
+ *
+ * By default SDL will disable the screensaver.
+ */
+#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER"
+
+/**
+ * \brief Tell the video driver that we only want a double buffer.
+ *
+ * By default, most lowlevel 2D APIs will use a triple buffer scheme that
+ * wastes no CPU time on waiting for vsync after issuing a flip, but
+ * introduces a frame of latency. On the other hand, using a double buffer
+ * scheme instead is recommended for cases where low latency is an important
+ * factor because we save a whole frame of latency.
+ * We do so by waiting for vsync immediately after issuing a flip, usually just
+ * after eglSwapBuffers call in the backend's *_SwapWindow function.
+ *
+ * Since it's driver-specific, it's only supported where possible and
+ * implemented. Currently supported the following drivers:
+ *
+ * - KMSDRM (kmsdrm)
+ * - Raspberry Pi (raspberrypi)
+ */
+#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER"
+
+/**
+ * \brief A variable controlling whether the graphics context is externally managed.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL will manage graphics contexts that are attached to windows.
+ * "1" - Disable graphics context management on windows.
+ *
+ * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the
+ * context will be automatically saved and restored when pausing the application. Additionally, some
+ * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this
+ * behavior, which is desireable when the application manages the graphics context, such as
+ * an externally managed OpenGL context or attaching a Vulkan surface to the window.
+ */
+#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT"
+
+/**
+ * \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS)
+ */
+#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
+
+/**
+ * \brief A variable that dictates policy for fullscreen Spaces on Mac OS X.
+ *
+ * This hint only applies to Mac OS X.
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable Spaces support (FULLSCREEN_DESKTOP won't use them and
+ * SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen"
+ * button on their titlebars).
+ * "1" - Enable Spaces support (FULLSCREEN_DESKTOP will use them and
+ * SDL_WINDOW_RESIZABLE windows will offer the "fullscreen"
+ * button on their titlebars).
+ *
+ * The default value is "1". Spaces are disabled regardless of this hint if
+ * the OS isn't at least Mac OS X Lion (10.7). This hint must be set before
+ * any windows are created.
+ */
+#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES"
+
+/**
+ * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false.
+ * \warning Before SDL 2.0.14, this defaulted to true! In 2.0.14, we're
+ * seeing if "true" causes more problems than it solves in modern times.
+ *
+ */
+#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
+
+/**
+ * \brief A variable controlling whether the libdecor Wayland backend is allowed to be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - libdecor use is disabled.
+ * "1" - libdecor use is enabled (default).
+ *
+ * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
+
+/**
+* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
+*
+* If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has
+* SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly
+* created SDL_Window:
+*
+* 1. Its pixel format will be set to the same pixel format as this SDL_Window. This is
+* needed for example when sharing an OpenGL context across multiple windows.
+*
+* 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for
+* OpenGL rendering.
+*
+* This variable can be set to the following values:
+* The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should
+* share a pixel format with.
+*/
+#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"
+
+/**
+* \brief A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries
+*
+* SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It
+* can use two different sets of binaries, those compiled by the user from source
+* or those provided by the Chrome browser. In the later case, these binaries require
+* that SDL loads a DLL providing the shader compiler.
+*
+* This variable can be set to the following values:
+* "d3dcompiler_46.dll" - default, best for Vista or later.
+* "d3dcompiler_43.dll" - for XP support.
+* "none" - do not load any library, useful if you compiled ANGLE from source and included the compiler in your binaries.
+*
+*/
+#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
+
+/**
+ * \brief A variable controlling whether X11 should use GLX or EGL by default
+ *
+ * This variable can be set to the following values:
+ * "0" - Use GLX
+ * "1" - Use EGL
+ *
+ * By default SDL will use GLX when both are present.
+ */
+#define SDL_HINT_VIDEO_X11_FORCE_EGL "SDL_VIDEO_X11_FORCE_EGL"
+
+/**
+ * \brief A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable _NET_WM_BYPASS_COMPOSITOR
+ * "1" - Enable _NET_WM_BYPASS_COMPOSITOR
+ *
+ * By default SDL will use _NET_WM_BYPASS_COMPOSITOR
+ *
+ */
+#define SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR"
+
+/**
+ * \brief A variable controlling whether the X11 _NET_WM_PING protocol should be supported.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable _NET_WM_PING
+ * "1" - Enable _NET_WM_PING
+ *
+ * By default SDL will use _NET_WM_PING, but for applications that know they
+ * will not always be able to respond to ping requests in a timely manner they can
+ * turn it off to avoid the window manager thinking the app is hung.
+ * The hint is checked in CreateWindow.
+ */
+#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING"
+
+/**
+ * \brief A variable forcing the visual ID chosen for new X11 windows
+ *
+ */
+#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID"
+
+/**
+ * \brief A variable controlling whether the X11 Xinerama extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable Xinerama
+ * "1" - Enable Xinerama
+ *
+ * By default SDL will use Xinerama if it is available.
+ */
+#define SDL_HINT_VIDEO_X11_XINERAMA "SDL_VIDEO_X11_XINERAMA"
+
+/**
+ * \brief A variable controlling whether the X11 XRandR extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable XRandR
+ * "1" - Enable XRandR
+ *
+ * By default SDL will not use XRandR because of window manager issues.
+ */
+#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR"
+
+/**
+ * \brief A variable controlling whether the X11 VidMode extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable XVidMode
+ * "1" - Enable XVidMode
+ *
+ * By default SDL will use XVidMode if it is available.
+ */
+#define SDL_HINT_VIDEO_X11_XVIDMODE "SDL_VIDEO_X11_XVIDMODE"
+
+/**
+ * \brief Controls how the fact chunk affects the loading of a WAVE file.
+ *
+ * The fact chunk stores information about the number of samples of a WAVE
+ * file. The Standards Update from Microsoft notes that this value can be used
+ * to 'determine the length of the data in seconds'. This is especially useful
+ * for compressed formats (for which this is a mandatory chunk) if they produce
+ * multiple sample frames per block and truncating the block is not allowed.
+ * The fact chunk can exactly specify how many sample frames there should be
+ * in this case.
+ *
+ * Unfortunately, most application seem to ignore the fact chunk and so SDL
+ * ignores it by default as well.
+ *
+ * This variable can be set to the following values:
+ *
+ * "truncate" - Use the number of samples to truncate the wave data if
+ * the fact chunk is present and valid
+ * "strict" - Like "truncate", but raise an error if the fact chunk
+ * is invalid, not present for non-PCM formats, or if the
+ * data chunk doesn't have that many samples
+ * "ignorezero" - Like "truncate", but ignore fact chunk if the number of
+ * samples is zero
+ * "ignore" - Ignore fact chunk entirely (default)
+ */
+#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK"
+
+/**
+ * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file.
+ *
+ * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE
+ * file) is not always reliable. In case the size is wrong, it's possible to
+ * just ignore it and step through the chunks until a fixed limit is reached.
+ *
+ * Note that files that have trailing data unrelated to the WAVE file or
+ * corrupt files may slow down the loading process without a reliable boundary.
+ * By default, SDL stops after 10000 chunks to prevent wasting time. Use the
+ * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value.
+ *
+ * This variable can be set to the following values:
+ *
+ * "force" - Always use the RIFF chunk size as a boundary for the chunk search
+ * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default)
+ * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB
+ * "maximum" - Search for chunks until the end of file (not recommended)
+ */
+#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE"
+
+/**
+ * \brief Controls how a truncated WAVE file is handled.
+ *
+ * A WAVE file is considered truncated if any of the chunks are incomplete or
+ * the data chunk size is not a multiple of the block size. By default, SDL
+ * decodes until the first incomplete block, as most applications seem to do.
+ *
+ * This variable can be set to the following values:
+ *
+ * "verystrict" - Raise an error if the file is truncated
+ * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored
+ * "dropframe" - Decode until the first incomplete sample frame
+ * "dropblock" - Decode until the first incomplete block (default)
+ */
+#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION"
+
+/**
+ * \brief Tell SDL not to name threads on Windows with the 0x406D1388 Exception.
+ * The 0x406D1388 Exception is a trick used to inform Visual Studio of a
+ * thread's name, but it tends to cause problems with other debuggers,
+ * and the .NET runtime. Note that SDL 2.0.6 and later will still use
+ * the (safer) SetThreadDescription API, introduced in the Windows 10
+ * Creators Update, if available.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will raise the 0x406D1388 Exception to name threads.
+ * This is the default behavior of SDL <= 2.0.4.
+ * "1" - SDL will not raise this exception, and threads will be unnamed. (default)
+ * This is necessary with .NET languages or debuggers that aren't Visual Studio.
+ */
+#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING"
+
+/**
+ * \brief A variable controlling whether the windows message loop is processed by SDL
+ *
+ * This variable can be set to the following values:
+ * "0" - The window message loop is not run
+ * "1" - The window message loop is processed in SDL_PumpEvents()
+ *
+ * By default SDL will process the windows message loop
+ */
+#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP"
+
+/**
+ * \brief Force SDL to use Critical Sections for mutexes on Windows.
+ * On Windows 7 and newer, Slim Reader/Writer Locks are available.
+ * They offer better performance, allocate no kernel ressources and
+ * use less memory. SDL will fall back to Critical Sections on older
+ * OS versions or if forced to by this hint.
+ * This also affects Condition Variables. When SRW mutexes are used,
+ * SDL will use Windows Condition Variables as well. Else, a generic
+ * SDL_cond implementation will be used that works with all mutexes.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use SRW Locks when available. If not, fall back to Critical Sections. (default)
+ * "1" - Force the use of Critical Sections in all cases.
+ *
+ */
+#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS"
+
+/**
+ * \brief Force SDL to use Kernel Semaphores on Windows.
+ * Kernel Semaphores are inter-process and require a context
+ * switch on every interaction. On Windows 8 and newer, the
+ * WaitOnAddress API is available. Using that and atomics to
+ * implement semaphores increases performance.
+ * SDL will fall back to Kernel Objects on older OS versions
+ * or if forced to by this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use Atomics and WaitOnAddress API when available. If not, fall back to Kernel Objects. (default)
+ * "1" - Force the use of Kernel Objects in all cases.
+ *
+ */
+#define SDL_HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL"
+
+/**
+ * \brief A variable to specify custom icon resource id from RC file on Windows platform
+ */
+#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON"
+#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL"
+
+/**
+ * \brief Tell SDL not to generate window-close events for Alt+F4 on Windows.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will generate a window-close event when it sees Alt+F4.
+ * "1" - SDL will only do normal key handling for Alt+F4.
+ */
+#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
+
+/**
+ * \brief Use the D3D9Ex API introduced in Windows Vista, instead of normal D3D9.
+ * Direct3D 9Ex contains changes to state management that can eliminate device
+ * loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may require
+ * some changes to your application to cope with the new behavior, so this
+ * is disabled by default.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * For more information on Direct3D 9Ex, see:
+ * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/graphics-apis-in-windows-vista#direct3d-9ex
+ * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/direct3d-9ex-improvements
+ *
+ * This variable can be set to the following values:
+ * "0" - Use the original Direct3D 9 API (default)
+ * "1" - Use the Direct3D 9Ex API on Vista and later (and fall back if D3D9Ex is unavailable)
+ *
+ */
+#define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX"
+
+/**
+ * \brief A variable controlling whether the window frame and title bar are interactive when the cursor is hidden
+ *
+ * This variable can be set to the following values:
+ * "0" - The window frame is not interactive when the cursor is hidden (no move, resize, etc)
+ * "1" - The window frame is interactive when the cursor is hidden
+ *
+ * By default SDL will allow interaction with the window frame when the cursor is hidden
+ */
+#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"
+
+/** \brief Allows back-button-press events on Windows Phone to be marked as handled
+ *
+ * Windows Phone devices typically feature a Back button. When pressed,
+ * the OS will emit back-button-press events, which apps are expected to
+ * handle in an appropriate manner. If apps do not explicitly mark these
+ * events as 'Handled', then the OS will invoke its default behavior for
+ * unhandled back-button-press events, which on Windows Phone 8 and 8.1 is to
+ * terminate the app (and attempt to switch to the previous app, or to the
+ * device's home screen).
+ *
+ * Setting the SDL_HINT_WINRT_HANDLE_BACK_BUTTON hint to "1" will cause SDL
+ * to mark back-button-press events as Handled, if and when one is sent to
+ * the app.
+ *
+ * Internally, Windows Phone sends back button events as parameters to
+ * special back-button-press callback functions. Apps that need to respond
+ * to back-button-press events are expected to register one or more
+ * callback functions for such, shortly after being launched (during the
+ * app's initialization phase). After the back button is pressed, the OS
+ * will invoke these callbacks. If the app's callback(s) do not explicitly
+ * mark the event as handled by the time they return, or if the app never
+ * registers one of these callback, the OS will consider the event
+ * un-handled, and it will apply its default back button behavior (terminate
+ * the app).
+ *
+ * SDL registers its own back-button-press callback with the Windows Phone
+ * OS. This callback will emit a pair of SDL key-press events (SDL_KEYDOWN
+ * and SDL_KEYUP), each with a scancode of SDL_SCANCODE_AC_BACK, after which
+ * it will check the contents of the hint, SDL_HINT_WINRT_HANDLE_BACK_BUTTON.
+ * If the hint's value is set to "1", the back button event's Handled
+ * property will get set to 'true'. If the hint's value is set to something
+ * else, or if it is unset, SDL will leave the event's Handled property
+ * alone. (By default, the OS sets this property to 'false', to note.)
+ *
+ * SDL apps can either set SDL_HINT_WINRT_HANDLE_BACK_BUTTON well before a
+ * back button is pressed, or can set it in direct-response to a back button
+ * being pressed.
+ *
+ * In order to get notified when a back button is pressed, SDL apps should
+ * register a callback function with SDL_AddEventWatch(), and have it listen
+ * for SDL_KEYDOWN events that have a scancode of SDL_SCANCODE_AC_BACK.
+ * (Alternatively, SDL_KEYUP events can be listened-for. Listening for
+ * either event type is suitable.) Any value of SDL_HINT_WINRT_HANDLE_BACK_BUTTON
+ * set by such a callback, will be applied to the OS' current
+ * back-button-press event.
+ *
+ * More details on back button behavior in Windows Phone apps can be found
+ * at the following page, on Microsoft's developer site:
+ * http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj247550(v=vs.105).aspx
+ */
+#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON"
+
+/** \brief Label text for a WinRT app's privacy policy link
+ *
+ * Network-enabled WinRT apps must include a privacy policy. On Windows 8, 8.1, and RT,
+ * Microsoft mandates that this policy be available via the Windows Settings charm.
+ * SDL provides code to add a link there, with its label text being set via the
+ * optional hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL.
+ *
+ * Please note that a privacy policy's contents are not set via this hint. A separate
+ * hint, SDL_HINT_WINRT_PRIVACY_POLICY_URL, is used to link to the actual text of the
+ * policy.
+ *
+ * The contents of this hint should be encoded as a UTF8 string.
+ *
+ * The default value is "Privacy Policy". This hint should only be set during app
+ * initialization, preferably before any calls to SDL_Init().
+ *
+ * For additional information on linking to a privacy policy, see the documentation for
+ * SDL_HINT_WINRT_PRIVACY_POLICY_URL.
+ */
+#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL"
+
+/**
+ * \brief A URL to a WinRT app's privacy policy
+ *
+ * All network-enabled WinRT apps must make a privacy policy available to its
+ * users. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be
+ * be available in the Windows Settings charm, as accessed from within the app.
+ * SDL provides code to add a URL-based link there, which can point to the app's
+ * privacy policy.
+ *
+ * To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL
+ * before calling any SDL_Init() functions. The contents of the hint should
+ * be a valid URL. For example, "http://www.example.com".
+ *
+ * The default value is "", which will prevent SDL from adding a privacy policy
+ * link to the Settings charm. This hint should only be set during app init.
+ *
+ * The label text of an app's "Privacy Policy" link may be customized via another
+ * hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL.
+ *
+ * Please note that on Windows Phone, Microsoft does not provide standard UI
+ * for displaying a privacy policy link, and as such, SDL_HINT_WINRT_PRIVACY_POLICY_URL
+ * will not get used on that platform. Network-enabled phone apps should display
+ * their privacy policy through some other, in-app means.
+ */
+#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL"
+
+/**
+ * \brief Mark X11 windows as override-redirect.
+ *
+ * If set, this _might_ increase framerate at the expense of the desktop
+ * not working as expected. Override-redirect windows aren't noticed by the
+ * window manager at all.
+ *
+ * You should probably only use this for fullscreen windows, and you probably
+ * shouldn't even use it for that. But it's here if you want to try!
+ */
+#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT"
+
+/**
+ * \brief A variable that lets you disable the detection and use of Xinput gamepad devices
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable XInput detection (only uses direct input)
+ * "1" - Enable XInput detection (the default)
+ */
+#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED"
+
+/**
+ * \brief A variable that causes SDL to use the old axis and button mapping for XInput devices.
+ *
+ * This hint is for backwards compatibility only and will be removed in SDL 2.1
+ *
+ * The default value is "0". This hint must be set before SDL_Init()
+ */
+#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING"
+
+/**
+ * \brief A variable that causes SDL to not ignore audio "monitors"
+ *
+ * This is currently only used for PulseAudio and ignored elsewhere.
+ *
+ * By default, SDL ignores audio devices that aren't associated with physical
+ * hardware. Changing this hint to "1" will expose anything SDL sees that
+ * appears to be an audio source or sink. This will add "devices" to the list
+ * that the user probably doesn't want or need, but it can be useful in
+ * scenarios where you want to hook up SDL to some sort of virtual device,
+ * etc.
+ *
+ * The default value is "0". This hint must be set before SDL_Init().
+ *
+ * This hint is available since SDL 2.0.16. Before then, virtual devices are
+ * always ignored.
+ */
+#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS"
+
+
+/**
+ * \brief An enumeration of hint priorities
+ */
+typedef enum
+{
+ SDL_HINT_DEFAULT,
+ SDL_HINT_NORMAL,
+ SDL_HINT_OVERRIDE
+} SDL_HintPriority;
+
+
+/**
+ * Set a hint with a specific priority.
+ *
+ * The priority controls the behavior when setting a hint that already has a
+ * value. Hints will replace existing hints of their priority and lower.
+ * Environment variables are considered to have override priority.
+ *
+ * \param name the hint to set
+ * \param value the value of the hint variable
+ * \param priority the SDL_HintPriority level for the hint
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name,
+ const char *value,
+ SDL_HintPriority priority);
+
+/**
+ * Set a hint with normal priority.
+ *
+ * Hints will not be set if there is an existing override hint or environment
+ * variable that takes precedence. You can use SDL_SetHintWithPriority() to
+ * set the hint with override priority instead.
+ *
+ * \param name the hint to set
+ * \param value the value of the hint variable
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHintWithPriority
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
+ const char *value);
+
+/**
+ * Get the value of a hint.
+ *
+ * \param name the hint to query
+ * \returns the string value of a hint or NULL if the hint isn't set.
+ *
+ * \sa SDL_SetHint
+ * \sa SDL_SetHintWithPriority
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
+
+/**
+ * Get the boolean value of a hint variable.
+ *
+ * \param name the name of the hint to get the boolean value from
+ * \param default_value the value to return if the hint does not exist
+ * \returns the boolean value of a hint or the provided default value if the
+ * hint does not exist.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value);
+
+/**
+ * Type definition of the hint callback function.
+ *
+ * \param userdata what was passed as `userdata` to SDL_AddHintCallback()
+ * \param name what was passed as `name` to SDL_AddHintCallback()
+ * \param oldValue the previous hint value
+ * \param newValue the new value hint is to be set to
+ */
+typedef void (SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
+
+/**
+ * Add a function to watch a particular hint.
+ *
+ * \param name the hint to watch
+ * \param callback An SDL_HintCallback function that will be called when the
+ * hint value changes
+ * \param userdata a pointer to pass to the callback function
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DelHintCallback
+ */
+extern DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+/**
+ * Remove a function watching a particular hint.
+ *
+ * \param name the hint being watched
+ * \param callback An SDL_HintCallback function that will be called when the
+ * hint value changes
+ * \param userdata a pointer being passed to the callback function
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AddHintCallback
+ */
+extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+/**
+ * Clear all hints.
+ *
+ * This function is automatically called during SDL_Quit().
+ */
+extern DECLSPEC void SDLCALL SDL_ClearHints(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_hints_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_joystick.h b/Client/ThirdParty/SDL2/SDL_joystick.h
new file mode 100644
index 0000000..8be4b73
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_joystick.h
@@ -0,0 +1,821 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_joystick.h
+ *
+ * Include file for SDL joystick event handling
+ *
+ * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks(), with the exact joystick
+ * behind a device_index changing as joysticks are plugged and unplugged.
+ *
+ * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
+ * then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in.
+ *
+ * The term "player_index" is the number assigned to a player on a specific
+ * controller. For XInput controllers this returns the XInput user index.
+ * Many joysticks will not be able to supply this information.
+ *
+ * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of
+ * the device (a X360 wired controller for example). This identifier is platform dependent.
+ */
+
+#ifndef SDL_joystick_h_
+#define SDL_joystick_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_joystick.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system
+ * for joysticks, and load appropriate drivers.
+ *
+ * If you would like to receive joystick updates while the application
+ * is in the background, you should set the following hint before calling
+ * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+ */
+
+/**
+ * The joystick structure used to identify an SDL joystick
+ */
+struct _SDL_Joystick;
+typedef struct _SDL_Joystick SDL_Joystick;
+
+/* A structure that encodes the stable unique id for a joystick device */
+typedef struct {
+ Uint8 data[16];
+} SDL_JoystickGUID;
+
+/**
+ * This is a unique ID for a joystick for the time it is connected to the system,
+ * and is never reused for the lifetime of the application. If the joystick is
+ * disconnected and reconnected, it will get a new ID.
+ *
+ * The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
+ */
+typedef Sint32 SDL_JoystickID;
+
+typedef enum
+{
+ SDL_JOYSTICK_TYPE_UNKNOWN,
+ SDL_JOYSTICK_TYPE_GAMECONTROLLER,
+ SDL_JOYSTICK_TYPE_WHEEL,
+ SDL_JOYSTICK_TYPE_ARCADE_STICK,
+ SDL_JOYSTICK_TYPE_FLIGHT_STICK,
+ SDL_JOYSTICK_TYPE_DANCE_PAD,
+ SDL_JOYSTICK_TYPE_GUITAR,
+ SDL_JOYSTICK_TYPE_DRUM_KIT,
+ SDL_JOYSTICK_TYPE_ARCADE_PAD,
+ SDL_JOYSTICK_TYPE_THROTTLE
+} SDL_JoystickType;
+
+typedef enum
+{
+ SDL_JOYSTICK_POWER_UNKNOWN = -1,
+ SDL_JOYSTICK_POWER_EMPTY, /* <= 5% */
+ SDL_JOYSTICK_POWER_LOW, /* <= 20% */
+ SDL_JOYSTICK_POWER_MEDIUM, /* <= 70% */
+ SDL_JOYSTICK_POWER_FULL, /* <= 100% */
+ SDL_JOYSTICK_POWER_WIRED,
+ SDL_JOYSTICK_POWER_MAX
+} SDL_JoystickPowerLevel;
+
+/* Set max recognized G-force from accelerometer
+ See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
+ */
+#define SDL_IPHONE_MAX_GFORCE 5.0
+
+
+/* Function prototypes */
+
+/**
+ * Locking for multi-threaded access to the joystick API
+ *
+ * If you are using the joystick API or handling events from multiple threads
+ * you should use these locking functions to protect access to the joysticks.
+ *
+ * In particular, you are guaranteed that the joystick list won't change, so
+ * the API functions that take a joystick index will be valid, and joystick
+ * and game controller events will not be delivered.
+ */
+extern DECLSPEC void SDLCALL SDL_LockJoysticks(void);
+
+
+/**
+ * Unlocking for multi-threaded access to the joystick API
+ *
+ * If you are using the joystick API or handling events from multiple threads
+ * you should use these locking functions to protect access to the joysticks.
+ *
+ * In particular, you are guaranteed that the joystick list won't change, so
+ * the API functions that take a joystick index will be valid, and joystick
+ * and game controller events will not be delivered.
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void);
+
+/**
+ * Count the number of joysticks attached to the system.
+ *
+ * \returns the number of attached joysticks on success or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickName
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_NumJoysticks(void);
+
+/**
+ * Get the implementation dependent name of a joystick.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system)
+ * \returns the name of the selected joystick. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickName
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index);
+
+/**
+ * Get the player index of a joystick, or -1 if it's not available This can be
+ * called before any joysticks are opened.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetDevicePlayerIndex(int device_index);
+
+/**
+ * Get the implementation-dependent GUID for the joystick at a given device
+ * index.
+ *
+ * This function can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the GUID of the selected joystick. If called on an invalid index,
+ * this function returns a zero GUID
+ *
+ * \sa SDL_JoystickGetGUID
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetDeviceGUID(int device_index);
+
+/**
+ * Get the USB vendor ID of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the vendor ID isn't
+ * available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the USB vendor ID of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceVendor(int device_index);
+
+/**
+ * Get the USB product ID of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the product ID isn't
+ * available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the USB product ID of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProduct(int device_index);
+
+/**
+ * Get the product version of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the product version
+ * isn't available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the product version of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProductVersion(int device_index);
+
+/**
+ * Get the type of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the SDL_JoystickType of the selected joystick. If called on an
+ * invalid index, this function returns `SDL_JOYSTICK_TYPE_UNKNOWN`
+ */
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetDeviceType(int device_index);
+
+/**
+ * Get the instance ID of a joystick.
+ *
+ * This can be called before any joysticks are opened. If the index is out of
+ * range, this function will return -1.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the instance id of the selected joystick. If called on an invalid
+ * index, this function returns zero
+ */
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickGetDeviceInstanceID(int device_index);
+
+/**
+ * Open a joystick for use.
+ *
+ * The `device_index` argument refers to the N'th joystick presently
+ * recognized by SDL on the system. It is **NOT** the same as the instance ID
+ * used to identify the joystick in future events. See
+ * SDL_JoystickInstanceID() for more details about instance IDs.
+ *
+ * The joystick subsystem must be initialized before a joystick can be opened
+ * for use.
+ *
+ * \param device_index the index of the joystick to query
+ * \returns a joystick identifier or NULL if an error occurred; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickClose
+ * \sa SDL_JoystickInstanceID
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index);
+
+/**
+ * Get the SDL_Joystick associated with an instance id.
+ *
+ * \param instance_id the instance id to get the SDL_Joystick for
+ * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id);
+
+/**
+ * Get the SDL_Joystick associated with a player index.
+ *
+ * \param player_index the player index to get the SDL_Joystick for
+ * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index);
+
+/**
+ * Attach a new virtual joystick.
+ *
+ * \returns the joystick's device index, or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type,
+ int naxes,
+ int nbuttons,
+ int nhats);
+
+/**
+ * Detach a virtual joystick.
+ *
+ * \param device_index a value previously returned from
+ * SDL_JoystickAttachVirtual()
+ * \returns 0 on success, or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
+
+/**
+ * Query whether or not the joystick at a given device index is virtual.
+ *
+ * \param device_index a joystick device index.
+ * \returns SDL_TRUE if the joystick is virtual, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
+
+/**
+ * Set values on an opened, virtual-joystick's axis.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param axis the specific axis on the virtual joystick to set.
+ * \param value the new value for the specified axis.
+ * \returns 0 on success, -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value);
+
+/**
+ * Set values on an opened, virtual-joystick's button.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param button the specific button on the virtual joystick to set.
+ * \param value the new value for the specified button.
+ * \returns 0 on success, -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value);
+
+/**
+ * Set values on an opened, virtual-joystick's hat.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param hat the specific hat on the virtual joystick to set.
+ * \param value the new value for the specified hat.
+ * \returns 0 on success, -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value);
+
+/**
+ * Get the implementation dependent name of a joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the name of the selected joystick. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNameForIndex
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick *joystick);
+
+/**
+ * Get the player index of an opened joystick.
+ *
+ * For XInput controllers this returns the XInput user index. Many joysticks
+ * will not be able to supply this information.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the player index, or -1 if it's not available.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick);
+
+/**
+ * Set the player index of an opened joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \param player_index the player index to set.
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index);
+
+/**
+ * Get the implementation-dependent GUID for the joystick.
+ *
+ * This function requires an open joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the GUID of the given joystick. If called on an invalid index,
+ * this function returns a zero GUID; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick *joystick);
+
+/**
+ * Get the USB vendor ID of an opened joystick, if available.
+ *
+ * If the vendor ID isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the USB vendor ID of the selected joystick, or 0 if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetVendor(SDL_Joystick *joystick);
+
+/**
+ * Get the USB product ID of an opened joystick, if available.
+ *
+ * If the product ID isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the USB product ID of the selected joystick, or 0 if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProduct(SDL_Joystick *joystick);
+
+/**
+ * Get the product version of an opened joystick, if available.
+ *
+ * If the product version isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the product version of the selected joystick, or 0 if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProductVersion(SDL_Joystick *joystick);
+
+/**
+ * Get the serial number of an opened joystick, if available.
+ *
+ * Returns the serial number of the joystick, or NULL if it is not available.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the serial number of the selected joystick, or NULL if
+ * unavailable.
+ */
+extern DECLSPEC const char * SDLCALL SDL_JoystickGetSerial(SDL_Joystick *joystick);
+
+/**
+ * Get the type of an opened joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the SDL_JoystickType of the selected joystick.
+ */
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetType(SDL_Joystick *joystick);
+
+/**
+ * Get an ASCII string representation for a given SDL_JoystickGUID.
+ *
+ * You should supply at least 33 bytes for pszGUID.
+ *
+ * \param guid the SDL_JoystickGUID you wish to convert to string
+ * \param pszGUID buffer in which to write the ASCII string
+ * \param cbGUID the size of pszGUID
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUID
+ * \sa SDL_JoystickGetGUIDFromString
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID);
+
+/**
+ * Convert a GUID string into a SDL_JoystickGUID structure.
+ *
+ * Performs no error checking. If this function is given a string containing
+ * an invalid GUID, the function will silently succeed, but the GUID generated
+ * will not be useful.
+ *
+ * \param pchGUID string containing an ASCII representation of a GUID
+ * \returns a SDL_JoystickGUID structure.
+ *
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUIDFromString(const char *pchGUID);
+
+/**
+ * Get the status of a specified joystick.
+ *
+ * \param joystick the joystick to query
+ * \returns SDL_TRUE if the joystick has been opened, SDL_FALSE if it has not;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickClose
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAttached(SDL_Joystick *joystick);
+
+/**
+ * Get the instance ID of an opened joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the instance ID of the specified joystick on success or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickInstanceID(SDL_Joystick *joystick);
+
+/**
+ * Get the number of general axis controls on a joystick.
+ *
+ * Often, the directional pad on a game controller will either look like 4
+ * separate buttons or a POV hat, and not axes, but all of this is up to the
+ * device and platform.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of axis controls/number of axes on success or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_JoystickGetAxis
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumAxes(SDL_Joystick *joystick);
+
+/**
+ * Get the number of trackballs on a joystick.
+ *
+ * Joystick trackballs have only relative motion events associated with them
+ * and their state cannot be polled.
+ *
+ * Most joysticks do not have trackballs.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of trackballs on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickGetBall
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumBalls(SDL_Joystick *joystick);
+
+/**
+ * Get the number of POV hats on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of POV hats on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickGetHat
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumHats(SDL_Joystick *joystick);
+
+/**
+ * Get the number of buttons on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of buttons on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickGetButton
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick *joystick);
+
+/**
+ * Update the current state of the open joysticks.
+ *
+ * This is called automatically by the event loop if any joystick events are
+ * enabled.
+ *
+ * \sa SDL_JoystickEventState
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickUpdate(void);
+
+/**
+ * Enable/disable joystick event polling.
+ *
+ * If joystick events are disabled, you must call SDL_JoystickUpdate()
+ * yourself and manually check the state of the joystick when you want
+ * joystick information.
+ *
+ * It is recommended that you leave joystick event handling enabled.
+ *
+ * **WARNING**: Calling this function may delete all events currently in SDL's
+ * event queue.
+ *
+ * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE`
+ * \returns 1 if enabled, 0 if disabled, or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ *
+ * If `state` is `SDL_QUERY` then the current state is returned,
+ * otherwise the new processing state is returned.
+ *
+ * \sa SDL_GameControllerEventState
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickEventState(int state);
+
+#define SDL_JOYSTICK_AXIS_MAX 32767
+#define SDL_JOYSTICK_AXIS_MIN -32768
+/**
+ * Get the current state of an axis control on a joystick.
+ *
+ * SDL makes no promises about what part of the joystick any given axis refers
+ * to. Your game should have some sort of configuration UI to let users
+ * specify what each axis should be bound to. Alternately, SDL's higher-level
+ * Game Controller API makes a great effort to apply order to this lower-level
+ * interface, so you know that a specific axis is the "left thumb stick," etc.
+ *
+ * The value returned by SDL_JoystickGetAxis() is a signed integer (-32768 to
+ * 32767) representing the current position of the axis. It may be necessary
+ * to impose certain tolerances on these values to account for jitter.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param axis the axis to query; the axis indices start at index 0
+ * \returns a 16-bit signed integer representing the current position of the
+ * axis or 0 on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickNumAxes
+ */
+extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick *joystick,
+ int axis);
+
+/**
+ * Get the initial state of an axis control on a joystick.
+ *
+ * The state is a value ranging from -32768 to 32767.
+ *
+ * The axis indices start at index 0.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param axis the axis to query; the axis indices start at index 0
+ * \param state Upon return, the initial value is supplied here.
+ * \return SDL_TRUE if this axis has any initial value, or SDL_FALSE if not.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick,
+ int axis, Sint16 *state);
+
+/**
+ * \name Hat positions
+ */
+/* @{ */
+#define SDL_HAT_CENTERED 0x00
+#define SDL_HAT_UP 0x01
+#define SDL_HAT_RIGHT 0x02
+#define SDL_HAT_DOWN 0x04
+#define SDL_HAT_LEFT 0x08
+#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP)
+#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN)
+#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP)
+#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN)
+/* @} */
+
+/**
+ * Get the current state of a POV hat on a joystick.
+ *
+ * The returned value will be one of the following positions:
+ *
+ * - `SDL_HAT_CENTERED`
+ * - `SDL_HAT_UP`
+ * - `SDL_HAT_RIGHT`
+ * - `SDL_HAT_DOWN`
+ * - `SDL_HAT_LEFT`
+ * - `SDL_HAT_RIGHTUP`
+ * - `SDL_HAT_RIGHTDOWN`
+ * - `SDL_HAT_LEFTUP`
+ * - `SDL_HAT_LEFTDOWN`
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param hat the hat index to get the state from; indices start at index 0
+ * \returns the current hat position.
+ *
+ * \sa SDL_JoystickNumHats
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetHat(SDL_Joystick *joystick,
+ int hat);
+
+/**
+ * Get the ball axis change since the last poll.
+ *
+ * Trackballs can only return relative motion since the last call to
+ * SDL_JoystickGetBall(), these motion deltas are placed into `dx` and `dy`.
+ *
+ * Most joysticks do not have trackballs.
+ *
+ * \param joystick the SDL_Joystick to query
+ * \param ball the ball index to query; ball indices start at index 0
+ * \param dx stores the difference in the x axis position since the last poll
+ * \param dy stores the difference in the y axis position since the last poll
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickNumBalls
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick *joystick,
+ int ball, int *dx, int *dy);
+
+/**
+ * Get the current state of a button on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param button the button index to get the state from; indices start at
+ * index 0
+ * \returns 1 if the specified button is pressed, 0 otherwise.
+ *
+ * \sa SDL_JoystickNumButtons
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick *joystick,
+ int button);
+
+/**
+ * Start a rumble effect.
+ *
+ * Each call to this function cancels any previous rumble effect, and calling
+ * it with 0 intensity stops any rumbling.
+ *
+ * \param joystick The joystick to vibrate
+ * \param low_frequency_rumble The intensity of the low frequency (left)
+ * rumble motor, from 0 to 0xFFFF
+ * \param high_frequency_rumble The intensity of the high frequency (right)
+ * rumble motor, from 0 to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if rumble isn't supported on this joystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
+
+/**
+ * Start a rumble effect in the joystick's triggers
+ *
+ * Each call to this function cancels any previous trigger rumble effect, and
+ * calling it with 0 intensity stops any rumbling.
+ *
+ * Note that this function is for _trigger_ rumble; the first joystick to
+ * support this was the PlayStation 5's DualShock 5 controller. If you want
+ * the (more common) whole-controller rumble, use SDL_JoystickRumble()
+ * instead.
+ *
+ * \param joystick The joystick to vibrate
+ * \param left_rumble The intensity of the left trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param right_rumble The intensity of the right trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if trigger rumble isn't supported on this joystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms);
+
+/**
+ * Query whether a joystick has an LED.
+ *
+ * An example of a joystick LED is the light on the back of a PlayStation 4's
+ * DualShock 4 controller.
+ *
+ * \param joystick The joystick to query
+ * \return SDL_TRUE if the joystick has a modifiable LED, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasLED(SDL_Joystick *joystick);
+
+/**
+ * Update a joystick's LED color.
+ *
+ * An example of a joystick LED is the light on the back of a PlayStation 4's
+ * DualShock 4 controller.
+ *
+ * \param joystick The joystick to update
+ * \param red The intensity of the red LED
+ * \param green The intensity of the green LED
+ * \param blue The intensity of the blue LED
+ * \returns 0 on success, -1 if this joystick does not have a modifiable LED
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
+
+/**
+ * Send a joystick specific effect packet
+ *
+ * \param joystick The joystick to affect
+ * \param data The data to send to the joystick
+ * \param size The size of the data to send to the joystick
+ * \returns 0, or -1 if this joystick or driver doesn't support effect packets
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size);
+
+/**
+ * Close a joystick previously opened with SDL_JoystickOpen().
+ *
+ * \param joystick The joystick device to close
+ *
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick *joystick);
+
+/**
+ * Get the battery level of a joystick as SDL_JoystickPowerLevel.
+ *
+ * \param joystick the SDL_Joystick to query
+ * \returns the current battery level as SDL_JoystickPowerLevel on success or
+ * `SDL_JOYSTICK_POWER_UNKNOWN` if it is unknown
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_JoystickPowerLevel SDLCALL SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_joystick_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_keyboard.h b/Client/ThirdParty/SDL2/SDL_keyboard.h
new file mode 100644
index 0000000..4260b5e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_keyboard.h
@@ -0,0 +1,294 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_keyboard.h
+ *
+ * Include file for SDL keyboard event handling
+ */
+
+#ifndef SDL_keyboard_h_
+#define SDL_keyboard_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_keycode.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The SDL keysym structure, used in key events.
+ *
+ * \note If you are looking for translated character input, see the ::SDL_TEXTINPUT event.
+ */
+typedef struct SDL_Keysym
+{
+ SDL_Scancode scancode; /**< SDL physical key code - see ::SDL_Scancode for details */
+ SDL_Keycode sym; /**< SDL virtual key code - see ::SDL_Keycode for details */
+ Uint16 mod; /**< current key modifiers */
+ Uint32 unused;
+} SDL_Keysym;
+
+/* Function prototypes */
+
+/**
+ * Query the window which currently has keyboard focus.
+ *
+ * \returns the window with keyboard focus.
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void);
+
+/**
+ * Get a snapshot of the current state of the keyboard.
+ *
+ * The pointer returned is a pointer to an internal SDL array. It will be
+ * valid for the whole lifetime of the application and should not be freed by
+ * the caller.
+ *
+ * A array element with a value of 1 means that the key is pressed and a value
+ * of 0 means that it is not. Indexes into this array are obtained by using
+ * SDL_Scancode values.
+ *
+ * Use SDL_PumpEvents() to update the state array.
+ *
+ * This function gives you the current state after all events have been
+ * processed, so if a key or button has been pressed and released before you
+ * process events, then the pressed state will never show up in the
+ * SDL_GetKeyboardState() calls.
+ *
+ * Note: This function doesn't take into account whether shift has been
+ * pressed or not.
+ *
+ * \param numkeys if non-NULL, receives the length of the returned array
+ * \returns a pointer to an array of key states.
+ *
+ * \sa SDL_PumpEvents
+ */
+extern DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys);
+
+/**
+ * Get the current key modifier state for the keyboard.
+ *
+ * \returns an OR'd combination of the modifier keys for the keyboard. See
+ * SDL_Keymod for details.
+ *
+ * \sa SDL_GetKeyboardState
+ * \sa SDL_SetModState
+ */
+extern DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void);
+
+/**
+ * Set the current key modifier state for the keyboard.
+ *
+ * The inverse of SDL_GetModState(), SDL_SetModState() allows you to impose
+ * modifier key states on your application. Simply pass your desired modifier
+ * states into `modstate`. This value may be a bitwise, OR'd combination of
+ * SDL_Keymod values.
+ *
+ * This does not change the keyboard state, only the key modifier flags that
+ * SDL reports.
+ *
+ * \param modstate the desired SDL_Keymod for the keyboard
+ *
+ * \sa SDL_GetModState
+ */
+extern DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate);
+
+/**
+ * Get the key code corresponding to the given scancode according to the
+ * current keyboard layout.
+ *
+ * See SDL_Keycode for details.
+ *
+ * \param scancode the desired SDL_Scancode to query
+ * \returns the SDL_Keycode that corresponds to the given SDL_Scancode.
+ *
+ * \sa SDL_GetKeyName
+ * \sa SDL_GetScancodeFromKey
+ */
+extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode);
+
+/**
+ * Get the scancode corresponding to the given key code according to the
+ * current keyboard layout.
+ *
+ * See SDL_Scancode for details.
+ *
+ * \param key the desired SDL_Keycode to query
+ * \returns the SDL_Scancode that corresponds to the given SDL_Keycode.
+ *
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetScancodeName
+ */
+extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key);
+
+/**
+ * Get a human-readable name for a scancode.
+ *
+ * See SDL_Scancode for details.
+ *
+ * **Warning**: The returned name is by design not stable across platforms,
+ * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left
+ * Windows" under Microsoft Windows, and some scancodes like
+ * `SDL_SCANCODE_NONUSBACKSLASH` don't have any name at all. There are even
+ * scancodes that share names, e.g. `SDL_SCANCODE_RETURN` and
+ * `SDL_SCANCODE_RETURN2` (both called "Return"). This function is therefore
+ * unsuitable for creating a stable cross-platform two-way mapping between
+ * strings and scancodes.
+ *
+ * \param scancode the desired SDL_Scancode to query
+ * \returns a pointer to the name for the scancode. If the scancode doesn't
+ * have a name this function returns an empty string ("").
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetScancodeFromKey
+ * \sa SDL_GetScancodeFromName
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetScancodeName(SDL_Scancode scancode);
+
+/**
+ * Get a scancode from a human-readable name.
+ *
+ * \param name the human-readable scancode name
+ * \returns the SDL_Scancode, or `SDL_SCANCODE_UNKNOWN` if the name wasn't
+ * recognized; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyFromName
+ * \sa SDL_GetScancodeFromKey
+ * \sa SDL_GetScancodeName
+ */
+extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name);
+
+/**
+ * Get a human-readable name for a key.
+ *
+ * See SDL_Scancode and SDL_Keycode for details.
+ *
+ * \param key the desired SDL_Keycode to query
+ * \returns a pointer to a UTF-8 string that stays valid at least until the
+ * next call to this function. If you need it around any longer, you
+ * must copy it. If the key doesn't have a name, this function
+ * returns an empty string ("").
+ *
+ * \sa SDL_GetKeyFromName
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetScancodeFromKey
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key);
+
+/**
+ * Get a key code from a human-readable name.
+ *
+ * \param name the human-readable key name
+ * \returns key code, or `SDLK_UNKNOWN` if the name wasn't recognized; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetKeyName
+ * \sa SDL_GetScancodeFromName
+ */
+extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name);
+
+/**
+ * Start accepting Unicode text input events.
+ *
+ * This function will start accepting Unicode text input events in the focused
+ * SDL window, and start emitting SDL_TextInputEvent (SDL_TEXTINPUT) and
+ * SDL_TextEditingEvent (SDL_TEXTEDITING) events. Please use this function in
+ * pair with SDL_StopTextInput().
+ *
+ * On some platforms using this function activates the screen keyboard.
+ *
+ * \sa SDL_SetTextInputRect
+ * \sa SDL_StopTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_StartTextInput(void);
+
+/**
+ * Check whether or not Unicode text input events are enabled.
+ *
+ * \returns SDL_TRUE if text input events are enabled else SDL_FALSE.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputActive(void);
+
+/**
+ * Stop receiving any text input events.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_StopTextInput(void);
+
+/**
+ * Set the rectangle used to type Unicode text inputs.
+ *
+ * \param rect the SDL_Rect structure representing the rectangle to receive
+ * text (ignored if NULL)
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_SetTextInputRect(SDL_Rect *rect);
+
+/**
+ * Check whether the platform has screen keyboard support.
+ *
+ * \returns SDL_TRUE if the platform has some screen keyboard support or
+ * SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ * \sa SDL_IsScreenKeyboardShown
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasScreenKeyboardSupport(void);
+
+/**
+ * Check whether the screen keyboard is shown for given window.
+ *
+ * \param window the window for which screen keyboard should be queried
+ * \returns SDL_TRUE if screen keyboard is shown or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasScreenKeyboardSupport
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenKeyboardShown(SDL_Window *window);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_keyboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_keycode.h b/Client/ThirdParty/SDL2/SDL_keycode.h
new file mode 100644
index 0000000..4fb0d39
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_keycode.h
@@ -0,0 +1,351 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_keycode.h
+ *
+ * Defines constants which identify keyboard keys and modifiers.
+ */
+
+#ifndef SDL_keycode_h_
+#define SDL_keycode_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_scancode.h"
+
+/**
+ * \brief The SDL virtual key representation.
+ *
+ * Values of this type are used to represent keyboard keys using the current
+ * layout of the keyboard. These values include Unicode values representing
+ * the unmodified character that would be generated by pressing the key, or
+ * an SDLK_* constant for those keys that do not generate characters.
+ *
+ * A special exception is the number keys at the top of the keyboard which
+ * always map to SDLK_0...SDLK_9, regardless of layout.
+ */
+typedef Sint32 SDL_Keycode;
+
+#define SDLK_SCANCODE_MASK (1<<30)
+#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK)
+
+typedef enum
+{
+ SDLK_UNKNOWN = 0,
+
+ SDLK_RETURN = '\r',
+ SDLK_ESCAPE = '\x1B',
+ SDLK_BACKSPACE = '\b',
+ SDLK_TAB = '\t',
+ SDLK_SPACE = ' ',
+ SDLK_EXCLAIM = '!',
+ SDLK_QUOTEDBL = '"',
+ SDLK_HASH = '#',
+ SDLK_PERCENT = '%',
+ SDLK_DOLLAR = '$',
+ SDLK_AMPERSAND = '&',
+ SDLK_QUOTE = '\'',
+ SDLK_LEFTPAREN = '(',
+ SDLK_RIGHTPAREN = ')',
+ SDLK_ASTERISK = '*',
+ SDLK_PLUS = '+',
+ SDLK_COMMA = ',',
+ SDLK_MINUS = '-',
+ SDLK_PERIOD = '.',
+ SDLK_SLASH = '/',
+ SDLK_0 = '0',
+ SDLK_1 = '1',
+ SDLK_2 = '2',
+ SDLK_3 = '3',
+ SDLK_4 = '4',
+ SDLK_5 = '5',
+ SDLK_6 = '6',
+ SDLK_7 = '7',
+ SDLK_8 = '8',
+ SDLK_9 = '9',
+ SDLK_COLON = ':',
+ SDLK_SEMICOLON = ';',
+ SDLK_LESS = '<',
+ SDLK_EQUALS = '=',
+ SDLK_GREATER = '>',
+ SDLK_QUESTION = '?',
+ SDLK_AT = '@',
+
+ /*
+ Skip uppercase letters
+ */
+
+ SDLK_LEFTBRACKET = '[',
+ SDLK_BACKSLASH = '\\',
+ SDLK_RIGHTBRACKET = ']',
+ SDLK_CARET = '^',
+ SDLK_UNDERSCORE = '_',
+ SDLK_BACKQUOTE = '`',
+ SDLK_a = 'a',
+ SDLK_b = 'b',
+ SDLK_c = 'c',
+ SDLK_d = 'd',
+ SDLK_e = 'e',
+ SDLK_f = 'f',
+ SDLK_g = 'g',
+ SDLK_h = 'h',
+ SDLK_i = 'i',
+ SDLK_j = 'j',
+ SDLK_k = 'k',
+ SDLK_l = 'l',
+ SDLK_m = 'm',
+ SDLK_n = 'n',
+ SDLK_o = 'o',
+ SDLK_p = 'p',
+ SDLK_q = 'q',
+ SDLK_r = 'r',
+ SDLK_s = 's',
+ SDLK_t = 't',
+ SDLK_u = 'u',
+ SDLK_v = 'v',
+ SDLK_w = 'w',
+ SDLK_x = 'x',
+ SDLK_y = 'y',
+ SDLK_z = 'z',
+
+ SDLK_CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK),
+
+ SDLK_F1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1),
+ SDLK_F2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2),
+ SDLK_F3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3),
+ SDLK_F4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4),
+ SDLK_F5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5),
+ SDLK_F6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6),
+ SDLK_F7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7),
+ SDLK_F8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8),
+ SDLK_F9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9),
+ SDLK_F10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10),
+ SDLK_F11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11),
+ SDLK_F12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12),
+
+ SDLK_PRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN),
+ SDLK_SCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK),
+ SDLK_PAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE),
+ SDLK_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT),
+ SDLK_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME),
+ SDLK_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP),
+ SDLK_DELETE = '\x7F',
+ SDLK_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END),
+ SDLK_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN),
+ SDLK_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT),
+ SDLK_LEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT),
+ SDLK_DOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN),
+ SDLK_UP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP),
+
+ SDLK_NUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR),
+ SDLK_KP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE),
+ SDLK_KP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY),
+ SDLK_KP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS),
+ SDLK_KP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS),
+ SDLK_KP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER),
+ SDLK_KP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1),
+ SDLK_KP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2),
+ SDLK_KP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3),
+ SDLK_KP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4),
+ SDLK_KP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5),
+ SDLK_KP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6),
+ SDLK_KP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7),
+ SDLK_KP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8),
+ SDLK_KP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9),
+ SDLK_KP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0),
+ SDLK_KP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD),
+
+ SDLK_APPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION),
+ SDLK_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER),
+ SDLK_KP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS),
+ SDLK_F13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13),
+ SDLK_F14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14),
+ SDLK_F15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15),
+ SDLK_F16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16),
+ SDLK_F17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17),
+ SDLK_F18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18),
+ SDLK_F19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19),
+ SDLK_F20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20),
+ SDLK_F21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21),
+ SDLK_F22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22),
+ SDLK_F23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23),
+ SDLK_F24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24),
+ SDLK_EXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE),
+ SDLK_HELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP),
+ SDLK_MENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU),
+ SDLK_SELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT),
+ SDLK_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP),
+ SDLK_AGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN),
+ SDLK_UNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO),
+ SDLK_CUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT),
+ SDLK_COPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY),
+ SDLK_PASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE),
+ SDLK_FIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND),
+ SDLK_MUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE),
+ SDLK_VOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP),
+ SDLK_VOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN),
+ SDLK_KP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA),
+ SDLK_KP_EQUALSAS400 =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400),
+
+ SDLK_ALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE),
+ SDLK_SYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ),
+ SDLK_CANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL),
+ SDLK_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR),
+ SDLK_PRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR),
+ SDLK_RETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2),
+ SDLK_SEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR),
+ SDLK_OUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT),
+ SDLK_OPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER),
+ SDLK_CLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN),
+ SDLK_CRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL),
+ SDLK_EXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL),
+
+ SDLK_KP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00),
+ SDLK_KP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000),
+ SDLK_THOUSANDSSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR),
+ SDLK_DECIMALSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR),
+ SDLK_CURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT),
+ SDLK_CURRENCYSUBUNIT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT),
+ SDLK_KP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN),
+ SDLK_KP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN),
+ SDLK_KP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE),
+ SDLK_KP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE),
+ SDLK_KP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB),
+ SDLK_KP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE),
+ SDLK_KP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A),
+ SDLK_KP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B),
+ SDLK_KP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C),
+ SDLK_KP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D),
+ SDLK_KP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E),
+ SDLK_KP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F),
+ SDLK_KP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR),
+ SDLK_KP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER),
+ SDLK_KP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT),
+ SDLK_KP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS),
+ SDLK_KP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER),
+ SDLK_KP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND),
+ SDLK_KP_DBLAMPERSAND =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND),
+ SDLK_KP_VERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR),
+ SDLK_KP_DBLVERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR),
+ SDLK_KP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON),
+ SDLK_KP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH),
+ SDLK_KP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE),
+ SDLK_KP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT),
+ SDLK_KP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM),
+ SDLK_KP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE),
+ SDLK_KP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL),
+ SDLK_KP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR),
+ SDLK_KP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD),
+ SDLK_KP_MEMSUBTRACT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT),
+ SDLK_KP_MEMMULTIPLY =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY),
+ SDLK_KP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE),
+ SDLK_KP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS),
+ SDLK_KP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR),
+ SDLK_KP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY),
+ SDLK_KP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY),
+ SDLK_KP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL),
+ SDLK_KP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL),
+ SDLK_KP_HEXADECIMAL =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL),
+
+ SDLK_LCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL),
+ SDLK_LSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT),
+ SDLK_LALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT),
+ SDLK_LGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI),
+ SDLK_RCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL),
+ SDLK_RSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT),
+ SDLK_RALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT),
+ SDLK_RGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI),
+
+ SDLK_MODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE),
+
+ SDLK_AUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT),
+ SDLK_AUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV),
+ SDLK_AUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP),
+ SDLK_AUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY),
+ SDLK_AUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE),
+ SDLK_MEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT),
+ SDLK_WWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW),
+ SDLK_MAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL),
+ SDLK_CALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR),
+ SDLK_COMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER),
+ SDLK_AC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH),
+ SDLK_AC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME),
+ SDLK_AC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK),
+ SDLK_AC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD),
+ SDLK_AC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP),
+ SDLK_AC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH),
+ SDLK_AC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS),
+
+ SDLK_BRIGHTNESSDOWN =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN),
+ SDLK_BRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP),
+ SDLK_DISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH),
+ SDLK_KBDILLUMTOGGLE =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE),
+ SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),
+ SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),
+ SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),
+ SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP),
+ SDLK_APP1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP1),
+ SDLK_APP2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP2),
+
+ SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND),
+ SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD)
+} SDL_KeyCode;
+
+/**
+ * \brief Enumeration of valid key mods (possibly OR'd together).
+ */
+typedef enum
+{
+ KMOD_NONE = 0x0000,
+ KMOD_LSHIFT = 0x0001,
+ KMOD_RSHIFT = 0x0002,
+ KMOD_LCTRL = 0x0040,
+ KMOD_RCTRL = 0x0080,
+ KMOD_LALT = 0x0100,
+ KMOD_RALT = 0x0200,
+ KMOD_LGUI = 0x0400,
+ KMOD_RGUI = 0x0800,
+ KMOD_NUM = 0x1000,
+ KMOD_CAPS = 0x2000,
+ KMOD_MODE = 0x4000,
+ KMOD_RESERVED = 0x8000,
+
+ KMOD_CTRL = KMOD_LCTRL | KMOD_RCTRL,
+ KMOD_SHIFT = KMOD_LSHIFT | KMOD_RSHIFT,
+ KMOD_ALT = KMOD_LALT | KMOD_RALT,
+ KMOD_GUI = KMOD_LGUI | KMOD_RGUI
+} SDL_Keymod;
+
+#endif /* SDL_keycode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_loadso.h b/Client/ThirdParty/SDL2/SDL_loadso.h
new file mode 100644
index 0000000..e6a33a0
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_loadso.h
@@ -0,0 +1,109 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_loadso.h
+ *
+ * System dependent library loading routines
+ *
+ * Some things to keep in mind:
+ * \li These functions only work on C function names. Other languages may
+ * have name mangling and intrinsic language support that varies from
+ * compiler to compiler.
+ * \li Make sure you declare your function pointers with the same calling
+ * convention as the actual library function. Your code will crash
+ * mysteriously if you do not do this.
+ * \li Avoid namespace collisions. If you load a symbol from the library,
+ * it is not defined whether or not it goes into the global symbol
+ * namespace for the application. If it does and it conflicts with
+ * symbols in your code or other shared libraries, you will not get
+ * the results you expect. :)
+ */
+
+#ifndef SDL_loadso_h_
+#define SDL_loadso_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Dynamically load a shared object.
+ *
+ * \param sofile a system-dependent name of the object file
+ * \returns an opaque pointer to the object handle or NULL if there was an
+ * error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_LoadFunction
+ * \sa SDL_UnloadObject
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile);
+
+/**
+ * Look up the address of the named function in a shared object.
+ *
+ * This function pointer is no longer valid after calling SDL_UnloadObject().
+ *
+ * This function can only look up C function names. Other languages may have
+ * name mangling and intrinsic language support that varies from compiler to
+ * compiler.
+ *
+ * Make sure you declare your function pointers with the same calling
+ * convention as the actual library function. Your code will crash
+ * mysteriously if you do not do this.
+ *
+ * If the requested function doesn't exist, NULL is returned.
+ *
+ * \param handle a valid shared object handle returned by SDL_LoadObject()
+ * \param name the name of the function to look up
+ * \returns a pointer to the function or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_LoadObject
+ * \sa SDL_UnloadObject
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle,
+ const char *name);
+
+/**
+ * Unload a shared object from memory.
+ *
+ * \param handle a valid shared object handle returned by SDL_LoadObject()
+ *
+ * \sa SDL_LoadFunction
+ * \sa SDL_LoadObject
+ */
+extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_loadso_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_locale.h b/Client/ThirdParty/SDL2/SDL_locale.h
new file mode 100644
index 0000000..cb4b043
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_locale.h
@@ -0,0 +1,101 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_locale.h
+ *
+ * Include file for SDL locale services
+ */
+
+#ifndef _SDL_locale_h
+#define _SDL_locale_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+
+typedef struct SDL_Locale
+{
+ const char *language; /**< A language name, like "en" for English. */
+ const char *country; /**< A country, like "US" for America. Can be NULL. */
+} SDL_Locale;
+
+/**
+ * Report the user's preferred locale.
+ *
+ * This returns an array of SDL_Locale structs, the final item zeroed out.
+ * When the caller is done with this array, it should call SDL_free() on the
+ * returned value; all the memory involved is allocated in a single block, so
+ * a single SDL_free() will suffice.
+ *
+ * Returned language strings are in the format xx, where 'xx' is an ISO-639
+ * language specifier (such as "en" for English, "de" for German, etc).
+ * Country strings are in the format YY, where "YY" is an ISO-3166 country
+ * code (such as "US" for the United States, "CA" for Canada, etc). Country
+ * might be NULL if there's no specific guidance on them (so you might get {
+ * "en", "US" } for American English, but { "en", NULL } means "English
+ * language, generically"). Language strings are never NULL, except to
+ * terminate the array.
+ *
+ * Please note that not all of these strings are 2 characters; some are three
+ * or more.
+ *
+ * The returned list of locales are in the order of the user's preference. For
+ * example, a German citizen that is fluent in US English and knows enough
+ * Japanese to navigate around Tokyo might have a list like: { "de", "en_US",
+ * "jp", NULL }. Someone from England might prefer British English (where
+ * "color" is spelled "colour", etc), but will settle for anything like it: {
+ * "en_GB", "en", NULL }.
+ *
+ * This function returns NULL on error, including when the platform does not
+ * supply this information at all.
+ *
+ * This might be a "slow" call that has to query the operating system. It's
+ * best to ask for this once and save the results. However, this list can
+ * change, usually because the user has changed a system preference outside of
+ * your program; SDL will send an SDL_LOCALECHANGED event in this case, if
+ * possible, and you can call this function again to get an updated copy of
+ * preferred locales.
+ *
+ * \return array of locales, terminated with a locale with a NULL language
+ * field. Will return NULL on error.
+ */
+extern DECLSPEC SDL_Locale * SDLCALL SDL_GetPreferredLocales(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_locale_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_log.h b/Client/ThirdParty/SDL2/SDL_log.h
new file mode 100644
index 0000000..e85961a
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_log.h
@@ -0,0 +1,376 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_log.h
+ *
+ * Simple log messages with categories and priorities.
+ *
+ * By default logs are quiet, but if you're debugging SDL you might want:
+ *
+ * SDL_LogSetAllPriority(SDL_LOG_PRIORITY_WARN);
+ *
+ * Here's where the messages go on different platforms:
+ * Windows: debug output stream
+ * Android: log output
+ * Others: standard error output (stderr)
+ */
+
+#ifndef SDL_log_h_
+#define SDL_log_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief The maximum size of a log message
+ *
+ * Messages longer than the maximum size will be truncated
+ */
+#define SDL_MAX_LOG_MESSAGE 4096
+
+/**
+ * \brief The predefined log categories
+ *
+ * By default the application category is enabled at the INFO level,
+ * the assert category is enabled at the WARN level, test is enabled
+ * at the VERBOSE level and all other categories are enabled at the
+ * CRITICAL level.
+ */
+typedef enum
+{
+ SDL_LOG_CATEGORY_APPLICATION,
+ SDL_LOG_CATEGORY_ERROR,
+ SDL_LOG_CATEGORY_ASSERT,
+ SDL_LOG_CATEGORY_SYSTEM,
+ SDL_LOG_CATEGORY_AUDIO,
+ SDL_LOG_CATEGORY_VIDEO,
+ SDL_LOG_CATEGORY_RENDER,
+ SDL_LOG_CATEGORY_INPUT,
+ SDL_LOG_CATEGORY_TEST,
+
+ /* Reserved for future SDL library use */
+ SDL_LOG_CATEGORY_RESERVED1,
+ SDL_LOG_CATEGORY_RESERVED2,
+ SDL_LOG_CATEGORY_RESERVED3,
+ SDL_LOG_CATEGORY_RESERVED4,
+ SDL_LOG_CATEGORY_RESERVED5,
+ SDL_LOG_CATEGORY_RESERVED6,
+ SDL_LOG_CATEGORY_RESERVED7,
+ SDL_LOG_CATEGORY_RESERVED8,
+ SDL_LOG_CATEGORY_RESERVED9,
+ SDL_LOG_CATEGORY_RESERVED10,
+
+ /* Beyond this point is reserved for application use, e.g.
+ enum {
+ MYAPP_CATEGORY_AWESOME1 = SDL_LOG_CATEGORY_CUSTOM,
+ MYAPP_CATEGORY_AWESOME2,
+ MYAPP_CATEGORY_AWESOME3,
+ ...
+ };
+ */
+ SDL_LOG_CATEGORY_CUSTOM
+} SDL_LogCategory;
+
+/**
+ * \brief The predefined log priorities
+ */
+typedef enum
+{
+ SDL_LOG_PRIORITY_VERBOSE = 1,
+ SDL_LOG_PRIORITY_DEBUG,
+ SDL_LOG_PRIORITY_INFO,
+ SDL_LOG_PRIORITY_WARN,
+ SDL_LOG_PRIORITY_ERROR,
+ SDL_LOG_PRIORITY_CRITICAL,
+ SDL_NUM_LOG_PRIORITIES
+} SDL_LogPriority;
+
+
+/**
+ * Set the priority of all log categories.
+ *
+ * \param priority the SDL_LogPriority to assign
+ *
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority);
+
+/**
+ * Set the priority of a particular log category.
+ *
+ * \param category the category to assign a priority to
+ * \param priority the SDL_LogPriority to assign
+ *
+ * \sa SDL_LogGetPriority
+ * \sa SDL_LogSetAllPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetPriority(int category,
+ SDL_LogPriority priority);
+
+/**
+ * Get the priority of a particular log category.
+ *
+ * \param category the category to query
+ * \returns the SDL_LogPriority for the requested category
+ *
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC SDL_LogPriority SDLCALL SDL_LogGetPriority(int category);
+
+/**
+ * Reset all priorities to default.
+ *
+ * This is called by SDL_Quit().
+ *
+ * \sa SDL_LogSetAllPriority
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogResetPriorities(void);
+
+/**
+ * Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO.
+ *
+ * = * \param fmt a printf() style message format string
+ *
+ * \param ... additional parameters matching % tokens in the `fmt` string, if
+ * any
+ *
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_VERBOSE.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_DEBUG.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_INFO.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_WARN.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ */
+extern DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_ERROR.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_CRITICAL.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with the specified category and priority.
+ *
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogMessage(int category,
+ SDL_LogPriority priority,
+ SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(3);
+
+/**
+ * Log a message with the specified category and priority.
+ *
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param fmt a printf() style message format string
+ * \param ap a variable argument list
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogMessageV(int category,
+ SDL_LogPriority priority,
+ const char *fmt, va_list ap);
+
+/**
+ * The prototype for the log output callback function.
+ *
+ * This function is called by SDL when there is new text to be logged.
+ *
+ * \param userdata what was passed as `userdata` to SDL_LogSetOutputFunction()
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param message the message being output
+ */
+typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message);
+
+/**
+ * Get the current log output function.
+ *
+ * \param callback an SDL_LogOutputFunction filled in with the current log
+ * callback
+ * \param userdata a pointer filled in with the pointer that is passed to
+ * `callback`
+ *
+ * \sa SDL_LogSetOutputFunction
+ */
+extern DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata);
+
+/**
+ * Replace the default log output function with one of your own.
+ *
+ * \param callback an SDL_LogOutputFunction to call instead of the default
+ * \param userdata a pointer that is passed to `callback`
+ *
+ * \sa SDL_LogGetOutputFunction
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_log_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_main.h b/Client/ThirdParty/SDL2/SDL_main.h
new file mode 100644
index 0000000..087193b
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_main.h
@@ -0,0 +1,186 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_main_h_
+#define SDL_main_h_
+
+#include "SDL_stdinc.h"
+
+/**
+ * \file SDL_main.h
+ *
+ * Redefine main() on some platforms so that it is called by SDL.
+ */
+
+#ifndef SDL_MAIN_HANDLED
+#if defined(__WIN32__)
+/* On Windows SDL provides WinMain(), which parses the command line and passes
+ the arguments to your main function.
+
+ If you provide your own WinMain(), you may define SDL_MAIN_HANDLED
+ */
+#define SDL_MAIN_AVAILABLE
+
+#elif defined(__WINRT__)
+/* On WinRT, SDL provides a main function that initializes CoreApplication,
+ creating an instance of IFrameworkView in the process.
+
+ Please note that #include'ing SDL_main.h is not enough to get a main()
+ function working. In non-XAML apps, the file,
+ src/main/winrt/SDL_WinRT_main_NonXAML.cpp, or a copy of it, must be compiled
+ into the app itself. In XAML apps, the function, SDL_WinRTRunApp must be
+ called, with a pointer to the Direct3D-hosted XAML control passed in.
+*/
+#define SDL_MAIN_NEEDED
+
+#elif defined(__IPHONEOS__)
+/* On iOS SDL provides a main function that creates an application delegate
+ and starts the iOS application run loop.
+
+ If you link with SDL dynamically on iOS, the main function can't be in a
+ shared library, so you need to link with libSDLmain.a, which includes a
+ stub main function that calls into the shared library to start execution.
+
+ See src/video/uikit/SDL_uikitappdelegate.m for more details.
+ */
+#define SDL_MAIN_NEEDED
+
+#elif defined(__ANDROID__)
+/* On Android SDL provides a Java class in SDLActivity.java that is the
+ main activity entry point.
+
+ See docs/README-android.md for more details on extending that class.
+ */
+#define SDL_MAIN_NEEDED
+
+/* We need to export SDL_main so it can be launched from Java */
+#define SDLMAIN_DECLSPEC DECLSPEC
+
+#elif defined(__NACL__)
+/* On NACL we use ppapi_simple to set up the application helper code,
+ then wait for the first PSE_INSTANCE_DIDCHANGEVIEW event before
+ starting the user main function.
+ All user code is run in a separate thread by ppapi_simple, thus
+ allowing for blocking io to take place via nacl_io
+*/
+#define SDL_MAIN_NEEDED
+
+#endif
+#endif /* SDL_MAIN_HANDLED */
+
+#ifndef SDLMAIN_DECLSPEC
+#define SDLMAIN_DECLSPEC
+#endif
+
+/**
+ * \file SDL_main.h
+ *
+ * The application's main() function must be called with C linkage,
+ * and should be declared like this:
+ * \code
+ * #ifdef __cplusplus
+ * extern "C"
+ * #endif
+ * int main(int argc, char *argv[])
+ * {
+ * }
+ * \endcode
+ */
+
+#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE)
+#define main SDL_main
+#endif
+
+#include "begin_code.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The prototype for the application's main() function
+ */
+typedef int (*SDL_main_func)(int argc, char *argv[]);
+extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]);
+
+
+/**
+ * Circumvent failure of SDL_Init() when not using SDL_main() as an entry
+ * point.
+ *
+ * This function is defined in SDL_main.h, along with the preprocessor rule to
+ * redefine main() as SDL_main(). Thus to ensure that your main() function
+ * will not be changed it is necessary to define SDL_MAIN_HANDLED before
+ * including SDL.h.
+ *
+ * \sa SDL_Init
+ */
+extern DECLSPEC void SDLCALL SDL_SetMainReady(void);
+
+#ifdef __WIN32__
+
+/**
+ * This can be called to set the application class at startup
+ */
+extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, void *hInst);
+extern DECLSPEC void SDLCALL SDL_UnregisterApp(void);
+
+#endif /* __WIN32__ */
+
+
+#ifdef __WINRT__
+
+/**
+ * Initialize and launch an SDL/WinRT application.
+ *
+ * \param mainFunction the SDL app's C-style main(), an SDL_main_func
+ * \param reserved reserved for future use; should be NULL
+ * \returns 0 on success or -1 on failure; call SDL_GetError() to retrieve
+ * more information on the failure.
+ *
+ * \since This function is available since SDL 2.0.3.
+ */
+extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved);
+
+#endif /* __WINRT__ */
+
+#if defined(__IPHONEOS__)
+
+/**
+ * Initializes and launches an SDL application.
+ *
+ * \param argc The argc parameter from the application's main() function
+ * \param argv The argv parameter from the application's main() function
+ * \param mainFunction The SDL app's C-style main(), an SDL_main_func
+ * \return the return value from mainFunction
+ */
+extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction);
+
+#endif /* __IPHONEOS__ */
+
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_main_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_messagebox.h b/Client/ThirdParty/SDL2/SDL_messagebox.h
new file mode 100644
index 0000000..c2aef70
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_messagebox.h
@@ -0,0 +1,191 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_messagebox_h_
+#define SDL_messagebox_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_video.h" /* For SDL_Window */
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * SDL_MessageBox flags. If supported will display warning icon, etc.
+ */
+typedef enum
+{
+ SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */
+ SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */
+ SDL_MESSAGEBOX_INFORMATION = 0x00000040, /**< informational dialog */
+ SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT = 0x00000080, /**< buttons placed left to right */
+ SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT = 0x00000100 /**< buttons placed right to left */
+} SDL_MessageBoxFlags;
+
+/**
+ * Flags for SDL_MessageBoxButtonData.
+ */
+typedef enum
+{
+ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001, /**< Marks the default button when return is hit */
+ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002 /**< Marks the default button when escape is hit */
+} SDL_MessageBoxButtonFlags;
+
+/**
+ * Individual button data.
+ */
+typedef struct
+{
+ Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */
+ int buttonid; /**< User defined button id (value returned via SDL_ShowMessageBox) */
+ const char * text; /**< The UTF-8 button text */
+} SDL_MessageBoxButtonData;
+
+/**
+ * RGB value used in a message box color scheme
+ */
+typedef struct
+{
+ Uint8 r, g, b;
+} SDL_MessageBoxColor;
+
+typedef enum
+{
+ SDL_MESSAGEBOX_COLOR_BACKGROUND,
+ SDL_MESSAGEBOX_COLOR_TEXT,
+ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
+ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
+ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
+ SDL_MESSAGEBOX_COLOR_MAX
+} SDL_MessageBoxColorType;
+
+/**
+ * A set of colors to use for message box dialogs
+ */
+typedef struct
+{
+ SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX];
+} SDL_MessageBoxColorScheme;
+
+/**
+ * MessageBox structure containing title, text, window, etc.
+ */
+typedef struct
+{
+ Uint32 flags; /**< ::SDL_MessageBoxFlags */
+ SDL_Window *window; /**< Parent window, can be NULL */
+ const char *title; /**< UTF-8 title */
+ const char *message; /**< UTF-8 message text */
+
+ int numbuttons;
+ const SDL_MessageBoxButtonData *buttons;
+
+ const SDL_MessageBoxColorScheme *colorScheme; /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */
+} SDL_MessageBoxData;
+
+/**
+ * Create a modal message box.
+ *
+ * If your needs aren't complex, it might be easier to use
+ * SDL_ShowSimpleMessageBox.
+ *
+ * This function should be called on the thread that created the parent
+ * window, or on the main thread if the messagebox has no parent. It will
+ * block execution of that thread until the user clicks a button or closes the
+ * messagebox.
+ *
+ * This function may be called at any time, even before SDL_Init(). This makes
+ * it useful for reporting errors like a failure to create a renderer or
+ * OpenGL context.
+ *
+ * On X11, SDL rolls its own dialog box with X11 primitives instead of a
+ * formal toolkit like GTK+ or Qt.
+ *
+ * Note that if SDL_Init() would fail because there isn't any available video
+ * target, this function is likely to fail for the same reasons. If this is a
+ * concern, check the return value from this function and fall back to writing
+ * to stderr if you can.
+ *
+ * \param messageboxdata the SDL_MessageBoxData structure with title, text and
+ * other options
+ * \param buttonid the pointer to which user id of hit button should be copied
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ShowSimpleMessageBox
+ */
+extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+/**
+ * Display a simple modal message box.
+ *
+ * If your needs aren't complex, this function is preferred over
+ * SDL_ShowMessageBox.
+ *
+ * `flags` may be any of the following:
+ *
+ * - `SDL_MESSAGEBOX_ERROR`: error dialog
+ * - `SDL_MESSAGEBOX_WARNING`: warning dialog
+ * - `SDL_MESSAGEBOX_INFORMATION`: informational dialog
+ *
+ * This function should be called on the thread that created the parent
+ * window, or on the main thread if the messagebox has no parent. It will
+ * block execution of that thread until the user clicks a button or closes the
+ * messagebox.
+ *
+ * This function may be called at any time, even before SDL_Init(). This makes
+ * it useful for reporting errors like a failure to create a renderer or
+ * OpenGL context.
+ *
+ * On X11, SDL rolls its own dialog box with X11 primitives instead of a
+ * formal toolkit like GTK+ or Qt.
+ *
+ * Note that if SDL_Init() would fail because there isn't any available video
+ * target, this function is likely to fail for the same reasons. If this is a
+ * concern, check the return value from this function and fall back to writing
+ * to stderr if you can.
+ *
+ * \param flags an SDL_MessageBoxFlags value
+ * \param title UTF-8 title text
+ * \param message UTF-8 message text
+ * \param window the parent window, or NULL for no parent
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_ShowMessageBox
+ */
+extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_messagebox_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_metal.h b/Client/ThirdParty/SDL2/SDL_metal.h
new file mode 100644
index 0000000..60bcb6e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_metal.h
@@ -0,0 +1,104 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_metal.h
+ *
+ * Header file for functions to creating Metal layers and views on SDL windows.
+ */
+
+#ifndef SDL_metal_h_
+#define SDL_metal_h_
+
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS).
+ *
+ * \note This can be cast directly to an NSView or UIView.
+ */
+typedef void *SDL_MetalView;
+
+/**
+ * \name Metal support functions
+ */
+/* @{ */
+
+/**
+ * Create a CAMetalLayer-backed NSView/UIView and attach it to the specified
+ * window.
+ *
+ * On macOS, this does *not* associate a MTLDevice with the CAMetalLayer on
+ * its own. It is up to user code to do that.
+ *
+ * The returned handle can be casted directly to a NSView or UIView. To access
+ * the backing CAMetalLayer, call SDL_Metal_GetLayer().
+ *
+ * \sa SDL_Metal_DestroyView
+ * \sa SDL_Metal_GetLayer
+ */
+extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window);
+
+/**
+ * Destroy an existing SDL_MetalView object.
+ *
+ * This should be called before SDL_DestroyWindow, if SDL_Metal_CreateView was
+ * called after SDL_CreateWindow.
+ *
+ * \sa SDL_Metal_CreateView
+ */
+extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view);
+
+/**
+ * Get a pointer to the backing CAMetalLayer for the given view.
+ *
+ * \sa SDL_MetalCreateView
+ */
+extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view);
+
+/**
+ * Get the size of a window's underlying drawable in pixels (for use with
+ * setting viewport, scissor & etc).
+ *
+ * \param window SDL_Window from which the drawable size should be queried
+ * \param w Pointer to variable for storing the width in pixels, may be NULL
+ *
+ * \sa SDL_GetWindowSize
+ * \sa SDL_CreateWindow
+ */
+extern DECLSPEC void SDLCALL SDL_Metal_GetDrawableSize(SDL_Window* window, int *w,
+ int *h);
+
+/* @} *//* Metal support functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_metal_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_misc.h b/Client/ThirdParty/SDL2/SDL_misc.h
new file mode 100644
index 0000000..7cd4d57
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_misc.h
@@ -0,0 +1,79 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_misc.h
+ *
+ * \brief Include file for SDL API functions that don't fit elsewhere.
+ */
+
+#ifndef SDL_misc_h_
+#define SDL_misc_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Open a URL/URI in the browser or other appropriate external application.
+ *
+ * Open a URL in a separate, system-provided application. How this works will
+ * vary wildly depending on the platform. This will likely launch what makes
+ * sense to handle a specific URL's protocol (a web browser for `http://`,
+ * etc), but it might also be able to launch file managers for directories and
+ * other things.
+ *
+ * What happens when you open a URL varies wildly as well: your game window
+ * may lose focus (and may or may not lose focus if your game was fullscreen
+ * or grabbing input at the time). On mobile devices, your app will likely
+ * move to the background or your process might be paused. Any given platform
+ * may or may not handle a given URL.
+ *
+ * If this is unimplemented (or simply unavailable) for a platform, this will
+ * fail with an error. A successful result does not mean the URL loaded, just
+ * that we launched _something_ to handle it (or at least believe we did).
+ *
+ * All this to say: this function can be useful, but you should definitely
+ * test it on every platform you target.
+ *
+ * \param url A valid URL/URI to open. Use `file:///full/path/to/file` for
+ * local files, if supported.
+ * \returns 0 on success, or -1 on error; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available in SDL 2.0.14 and newer
+ */
+extern DECLSPEC int SDLCALL SDL_OpenURL(const char *url);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_misc_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_mouse.h b/Client/ThirdParty/SDL2/SDL_mouse.h
new file mode 100644
index 0000000..8fbe38f
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_mouse.h
@@ -0,0 +1,432 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_mouse.h
+ *
+ * Include file for SDL mouse event handling.
+ */
+
+#ifndef SDL_mouse_h_
+#define SDL_mouse_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SDL_Cursor SDL_Cursor; /**< Implementation dependent */
+
+/**
+ * \brief Cursor types for SDL_CreateSystemCursor().
+ */
+typedef enum
+{
+ SDL_SYSTEM_CURSOR_ARROW, /**< Arrow */
+ SDL_SYSTEM_CURSOR_IBEAM, /**< I-beam */
+ SDL_SYSTEM_CURSOR_WAIT, /**< Wait */
+ SDL_SYSTEM_CURSOR_CROSSHAIR, /**< Crosshair */
+ SDL_SYSTEM_CURSOR_WAITARROW, /**< Small wait cursor (or Wait if not available) */
+ SDL_SYSTEM_CURSOR_SIZENWSE, /**< Double arrow pointing northwest and southeast */
+ SDL_SYSTEM_CURSOR_SIZENESW, /**< Double arrow pointing northeast and southwest */
+ SDL_SYSTEM_CURSOR_SIZEWE, /**< Double arrow pointing west and east */
+ SDL_SYSTEM_CURSOR_SIZENS, /**< Double arrow pointing north and south */
+ SDL_SYSTEM_CURSOR_SIZEALL, /**< Four pointed arrow pointing north, south, east, and west */
+ SDL_SYSTEM_CURSOR_NO, /**< Slashed circle or crossbones */
+ SDL_SYSTEM_CURSOR_HAND, /**< Hand */
+ SDL_NUM_SYSTEM_CURSORS
+} SDL_SystemCursor;
+
+/**
+ * \brief Scroll direction types for the Scroll event
+ */
+typedef enum
+{
+ SDL_MOUSEWHEEL_NORMAL, /**< The scroll direction is normal */
+ SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */
+} SDL_MouseWheelDirection;
+
+/* Function prototypes */
+
+/**
+ * Get the window which currently has mouse focus.
+ *
+ * \returns the window with mouse focus.
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void);
+
+/**
+ * Retrieve the current state of the mouse.
+ *
+ * The current button state is returned as a button bitmask, which can be
+ * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the
+ * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the
+ * mouse cursor position relative to the focus window. You can pass NULL for
+ * either `x` or `y`.
+ *
+ * \param x the x coordinate of the mouse cursor position relative to the
+ * focus window
+ * \param y the y coordinate of the mouse cursor position relative to the
+ * focus window
+ * \returns a 32-bit button bitmask of the current button state.
+ *
+ * \sa SDL_GetGlobalMouseState
+ * \sa SDL_GetRelativeMouseState
+ * \sa SDL_PumpEvents
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(int *x, int *y);
+
+/**
+ * Get the current state of the mouse in relation to the desktop.
+ *
+ * This works similarly to SDL_GetMouseState(), but the coordinates will be
+ * reported relative to the top-left of the desktop. This can be useful if you
+ * need to track the mouse outside of a specific window and SDL_CaptureMouse()
+ * doesn't fit your needs. For example, it could be useful if you need to
+ * track the mouse while dragging a window, where coordinates relative to a
+ * window might not be in sync at all times.
+ *
+ * Note: SDL_GetMouseState() returns the mouse position as SDL understands it
+ * from the last pump of the event queue. This function, however, queries the
+ * OS for the current mouse position, and as such, might be a slightly less
+ * efficient function. Unless you know what you're doing and have a good
+ * reason to use this function, you probably want SDL_GetMouseState() instead.
+ *
+ * \param x filled in with the current X coord relative to the desktop; can be
+ * NULL
+ * \param y filled in with the current Y coord relative to the desktop; can be
+ * NULL
+ * \returns the current button state as a bitmask which can be tested using
+ * the SDL_BUTTON(X) macros.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_CaptureMouse
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetGlobalMouseState(int *x, int *y);
+
+/**
+ * Retrieve the relative state of the mouse.
+ *
+ * The current button state is returned as a button bitmask, which can be
+ * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the
+ * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the
+ * mouse deltas since the last call to SDL_GetRelativeMouseState() or since
+ * event initialization. You can pass NULL for either `x` or `y`.
+ *
+ * \param x a pointer filled with the last recorded x coordinate of the mouse
+ * \param y a pointer filled with the last recorded y coordinate of the mouse
+ * \returns a 32-bit button bitmask of the relative button state.
+ *
+ * \sa SDL_GetMouseState
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(int *x, int *y);
+
+/**
+ * Move the mouse cursor to the given position within the window.
+ *
+ * This function generates a mouse motion event.
+ *
+ * Note that this function will appear to succeed, but not actually move the
+ * mouse when used over Microsoft Remote Desktop.
+ *
+ * \param window the window to move the mouse into, or NULL for the current
+ * mouse focus
+ * \param x the x coordinate within the window
+ * \param y the y coordinate within the window
+ *
+ * \sa SDL_WarpMouseGlobal
+ */
+extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window,
+ int x, int y);
+
+/**
+ * Move the mouse to the given position in global screen space.
+ *
+ * This function generates a mouse motion event.
+ *
+ * A failure of this function usually means that it is unsupported by a
+ * platform.
+ *
+ * Note that this function will appear to succeed, but not actually move the
+ * mouse when used over Microsoft Remote Desktop.
+ *
+ * \param x the x coordinate
+ * \param y the y coordinate
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_WarpMouseInWindow
+ */
+extern DECLSPEC int SDLCALL SDL_WarpMouseGlobal(int x, int y);
+
+/**
+ * Set relative mouse mode.
+ *
+ * While the mouse is in relative mode, the cursor is hidden, and the driver
+ * will try to report continuous motion in the current window. Only relative
+ * motion events will be delivered, the mouse position will not change.
+ *
+ * Note that this function will not be able to provide continuous relative
+ * motion when used over Microsoft Remote Desktop, instead motion is limited
+ * to the bounds of the screen.
+ *
+ * This function will flush any pending mouse motion.
+ *
+ * \param enabled SDL_TRUE to enable relative mode, SDL_FALSE to disable.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * If relative mode is not supported, this returns -1.
+ *
+ * \sa SDL_GetRelativeMouseMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled);
+
+/**
+ * Capture the mouse and to track input outside an SDL window.
+ *
+ * Capturing enables your app to obtain mouse events globally, instead of just
+ * within your window. Not all video targets support this function. When
+ * capturing is enabled, the current window will get all mouse events, but
+ * unlike relative mode, no change is made to the cursor and it is not
+ * restrained to your window.
+ *
+ * This function may also deny mouse input to other windows--both those in
+ * your application and others on the system--so you should use this function
+ * sparingly, and in small bursts. For example, you might want to track the
+ * mouse while the user is dragging something, until the user releases a mouse
+ * button. It is not recommended that you capture the mouse for long periods
+ * of time, such as the entire time your app is running. For that, you should
+ * probably use SDL_SetRelativeMouseMode() or SDL_SetWindowGrab(), depending
+ * on your goals.
+ *
+ * While captured, mouse events still report coordinates relative to the
+ * current (foreground) window, but those coordinates may be outside the
+ * bounds of the window (including negative values). Capturing is only allowed
+ * for the foreground window. If the window loses focus while capturing, the
+ * capture will be disabled automatically.
+ *
+ * While capturing is enabled, the current window will have the
+ * `SDL_WINDOW_MOUSE_CAPTURE` flag set.
+ *
+ * \param enabled SDL_TRUE to enable capturing, SDL_FALSE to disable.
+ * \returns 0 on success or -1 if not supported; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetGlobalMouseState
+ */
+extern DECLSPEC int SDLCALL SDL_CaptureMouse(SDL_bool enabled);
+
+/**
+ * Query whether relative mouse mode is enabled.
+ *
+ * \returns SDL_TRUE if relative mode is enabled or SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetRelativeMouseMode
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void);
+
+/**
+ * Create a cursor using the specified bitmap data and mask (in MSB format).
+ *
+ * `mask` has to be in MSB (Most Significant Bit) format.
+ *
+ * The cursor width (`w`) must be a multiple of 8 bits.
+ *
+ * The cursor is created in black and white according to the following:
+ *
+ * - data=0, mask=1: white
+ * - data=1, mask=1: black
+ * - data=0, mask=0: transparent
+ * - data=1, mask=0: inverted color if possible, black if not.
+ *
+ * Cursors created with this function must be freed with SDL_FreeCursor().
+ *
+ * If you want to have a color cursor, or create your cursor from an
+ * SDL_Surface, you should use SDL_CreateColorCursor(). Alternately, you can
+ * hide the cursor and draw your own as part of your game's rendering, but it
+ * will be bound to the framerate.
+ *
+ * Also, since SDL 2.0.0, SDL_CreateSystemCursor() is available, which
+ * provides twelve readily available system cursors to pick from.
+ *
+ * \param data the color value for each pixel of the cursor
+ * \param mask the mask value for each pixel of the cursor
+ * \param w the width of the cursor
+ * \param h the height of the cursor
+ * \param hot_x the X-axis location of the upper left corner of the cursor
+ * relative to the actual mouse position
+ * \param hot_y the Y-axis location of the upper left corner of the cursor
+ * relative to the actual mouse position
+ * \returns a new cursor with the specified parameters on success or NULL on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_FreeCursor
+ * \sa SDL_SetCursor
+ * \sa SDL_ShowCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data,
+ const Uint8 * mask,
+ int w, int h, int hot_x,
+ int hot_y);
+
+/**
+ * Create a color cursor.
+ *
+ * \param surface an SDL_Surface structure representing the cursor image
+ * \param hot_x the x position of the cursor hot spot
+ * \param hot_y the y position of the cursor hot spot
+ * \returns the new cursor on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateCursor
+ * \sa SDL_FreeCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface,
+ int hot_x,
+ int hot_y);
+
+/**
+ * Create a system cursor.
+ *
+ * \param id an SDL_SystemCursor enum value
+ * \returns a cursor on success or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_FreeCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id);
+
+/**
+ * Set the active cursor.
+ *
+ * This function sets the currently active cursor to the specified one. If the
+ * cursor is currently visible, the change will be immediately represented on
+ * the display. SDL_SetCursor(NULL) can be used to force cursor redraw, if
+ * this is desired for any reason.
+ *
+ * \param cursor a cursor to make active
+ *
+ * \sa SDL_CreateCursor
+ * \sa SDL_GetCursor
+ * \sa SDL_ShowCursor
+ */
+extern DECLSPEC void SDLCALL SDL_SetCursor(SDL_Cursor * cursor);
+
+/**
+ * Get the active cursor.
+ *
+ * This function returns a pointer to the current cursor which is owned by the
+ * library. It is not necessary to free the cursor with SDL_FreeCursor().
+ *
+ * \returns the active cursor or NULL if there is no mouse.
+ *
+ * \sa SDL_SetCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void);
+
+/**
+ * Get the default cursor.
+ *
+ * \returns the default cursor on success or NULL on failure.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateSystemCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void);
+
+/**
+ * Free a previously-created cursor.
+ *
+ * Use this function to free cursor resources created with SDL_CreateCursor(),
+ * SDL_CreateColorCursor() or SDL_CreateSystemCursor().
+ *
+ * \param cursor the cursor to free
+ *
+ * \sa SDL_CreateColorCursor
+ * \sa SDL_CreateCursor
+ * \sa SDL_CreateSystemCursor
+ */
+extern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor * cursor);
+
+/**
+ * Toggle whether or not the cursor is shown.
+ *
+ * The cursor starts off displayed but can be turned off. Passing `SDL_ENABLE`
+ * displays the cursor and passing `SDL_DISABLE` hides it.
+ *
+ * The current state of the mouse cursor can be queried by passing
+ * `SDL_QUERY`; either `SDL_DISABLE` or `SDL_ENABLE` will be returned.
+ *
+ * \param toggle `SDL_ENABLE` to show the cursor, `SDL_DISABLE` to hide it,
+ * `SDL_QUERY` to query the current state without changing it.
+ * \returns `SDL_ENABLE` if the cursor is shown, or `SDL_DISABLE` if the
+ * cursor is hidden, or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateCursor
+ * \sa SDL_SetCursor
+ */
+extern DECLSPEC int SDLCALL SDL_ShowCursor(int toggle);
+
+/**
+ * Used as a mask when testing buttons in buttonstate.
+ *
+ * - Button 1: Left mouse button
+ * - Button 2: Middle mouse button
+ * - Button 3: Right mouse button
+ */
+#define SDL_BUTTON(X) (1 << ((X)-1))
+#define SDL_BUTTON_LEFT 1
+#define SDL_BUTTON_MIDDLE 2
+#define SDL_BUTTON_RIGHT 3
+#define SDL_BUTTON_X1 4
+#define SDL_BUTTON_X2 5
+#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT)
+#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE)
+#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT)
+#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1)
+#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2)
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_mouse_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_mutex.h b/Client/ThirdParty/SDL2/SDL_mutex.h
new file mode 100644
index 0000000..2f27f19
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_mutex.h
@@ -0,0 +1,435 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_mutex_h_
+#define SDL_mutex_h_
+
+/**
+ * \file SDL_mutex.h
+ *
+ * Functions to provide thread synchronization primitives.
+ */
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Synchronization functions which can time out return this value
+ * if they time out.
+ */
+#define SDL_MUTEX_TIMEDOUT 1
+
+/**
+ * This is the timeout value which corresponds to never time out.
+ */
+#define SDL_MUTEX_MAXWAIT (~(Uint32)0)
+
+
+/**
+ * \name Mutex functions
+ */
+/* @{ */
+
+/* The SDL mutex structure, defined in SDL_sysmutex.c */
+struct SDL_mutex;
+typedef struct SDL_mutex SDL_mutex;
+
+/**
+ * Create a new mutex.
+ *
+ * All newly-created mutexes begin in the _unlocked_ state.
+ *
+ * Calls to SDL_LockMutex() will not return while the mutex is locked by
+ * another thread. See SDL_TryLockMutex() to attempt to lock without blocking.
+ *
+ * SDL mutexes are reentrant.
+ *
+ * \returns the initialized and unlocked mutex or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_DestroyMutex
+ * \sa SDL_LockMutex
+ * \sa SDL_TryLockMutex
+ * \sa SDL_UnlockMutex
+ */
+extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void);
+
+/**
+ * Lock the mutex.
+ *
+ * This will block until the mutex is available, which is to say it is in the
+ * unlocked state and the OS has chosen the caller as the next thread to lock
+ * it. Of all threads waiting to lock the mutex, only one may do so at a time.
+ *
+ * It is legal for the owning thread to lock an already-locked mutex. It must
+ * unlock it the same number of times before it is actually made available for
+ * other threads in the system (this is known as a "recursive mutex").
+ *
+ * \param mutex the mutex to lock
+ * \return 0, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex);
+#define SDL_mutexP(m) SDL_LockMutex(m)
+
+/**
+ * Try to lock a mutex without blocking.
+ *
+ * This works just like SDL_LockMutex(), but if the mutex is not available,
+ * this function returns `SDL_MUTEX_TIMEOUT` immediately.
+ *
+ * This technique is useful if you need exclusive access to a resource but
+ * don't want to wait for it, and will return to it to try again later.
+ *
+ * \param mutex the mutex to try to lock
+ * \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for
+ * more information.
+ *
+ * \sa SDL_CreateMutex
+ * \sa SDL_DestroyMutex
+ * \sa SDL_LockMutex
+ * \sa SDL_UnlockMutex
+ */
+extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex);
+
+/**
+ * Unlock the mutex.
+ *
+ * It is legal for the owning thread to lock an already-locked mutex. It must
+ * unlock it the same number of times before it is actually made available for
+ * other threads in the system (this is known as a "recursive mutex").
+ *
+ * It is an error to unlock a mutex that has not been locked by the current
+ * thread, and doing so results in undefined behavior.
+ *
+ * It is also an error to unlock a mutex that isn't locked at all.
+ *
+ * \param mutex the mutex to unlock.
+ * \returns 0, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex);
+#define SDL_mutexV(m) SDL_UnlockMutex(m)
+
+/**
+ * Destroy a mutex created with SDL_CreateMutex().
+ *
+ * This function must be called on any mutex that is no longer needed. Failure
+ * to destroy a mutex will result in a system memory or resource leak. While
+ * it is safe to destroy a mutex that is _unlocked_, it is not safe to attempt
+ * to destroy a locked mutex, and may result in undefined behavior depending
+ * on the platform.
+ *
+ * \param mutex the mutex to destroy
+ *
+ * \sa SDL_CreateMutex
+ * \sa SDL_LockMutex
+ * \sa SDL_TryLockMutex
+ * \sa SDL_UnlockMutex
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex);
+
+/* @} *//* Mutex functions */
+
+
+/**
+ * \name Semaphore functions
+ */
+/* @{ */
+
+/* The SDL semaphore structure, defined in SDL_syssem.c */
+struct SDL_semaphore;
+typedef struct SDL_semaphore SDL_sem;
+
+/**
+ * Create a semaphore.
+ *
+ * This function creates a new semaphore and initializes it with the value
+ * `initial_value`. Each wait operation on the semaphore will atomically
+ * decrement the semaphore value and potentially block if the semaphore value
+ * is 0. Each post operation will atomically increment the semaphore value and
+ * wake waiting threads and allow them to retry the wait operation.
+ *
+ * \param initial_value the starting value of the semaphore
+ * \returns a new semaphore or NULL on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
+
+/**
+ * Destroy a semaphore.
+ *
+ * It is not safe to destroy a semaphore if there are threads currently
+ * waiting on it.
+ *
+ * \param sem the semaphore to destroy
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem);
+
+/**
+ * Wait until a semaphore has a positive value and then decrements it.
+ *
+ * This function suspends the calling thread until either the semaphore
+ * pointed to by `sem` has a positive value or the call is interrupted by a
+ * signal or error. If the call is successful it will atomically decrement the
+ * semaphore value.
+ *
+ * This function is the equivalent of calling SDL_SemWaitTimeout() with a time
+ * length of `SDL_MUTEX_MAXWAIT`.
+ *
+ * \param sem the semaphore wait on
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem);
+
+/**
+ * See if a semaphore has a positive value and decrement it if it does.
+ *
+ * This function checks to see if the semaphore pointed to by `sem` has a
+ * positive value and atomically decrements the semaphore value if it does. If
+ * the semaphore doesn't have a positive value, the function immediately
+ * returns SDL_MUTEX_TIMEDOUT.
+ *
+ * \param sem the semaphore to wait on
+ * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait would
+ * block, or a negative error code on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem);
+
+/**
+ * Wait until a semaphore has a positive value and then decrements it.
+ *
+ * This function suspends the calling thread until either the semaphore
+ * pointed to by `sem` has a positive value, the call is interrupted by a
+ * signal or error, or the specified time has elapsed. If the call is
+ * successful it will atomically decrement the semaphore value.
+ *
+ * \param sem the semaphore to wait on
+ * \param ms the length of the timeout, in milliseconds
+ * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not
+ * succeed in the allotted time, or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ */
+extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem * sem, Uint32 ms);
+
+/**
+ * Atomically increment a semaphore's value and wake waiting threads.
+ *
+ * \param sem the semaphore to increment
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem);
+
+/**
+ * Get the current value of a semaphore.
+ *
+ * \param sem the semaphore to query
+ * \returns the current value of the semaphore.
+ *
+ * \sa SDL_CreateSemaphore
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem);
+
+/* @} *//* Semaphore functions */
+
+
+/**
+ * \name Condition variable functions
+ */
+/* @{ */
+
+/* The SDL condition variable structure, defined in SDL_syscond.c */
+struct SDL_cond;
+typedef struct SDL_cond SDL_cond;
+
+/**
+ * Create a condition variable.
+ *
+ * \returns a new condition variable or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
+
+/**
+ * Destroy a condition variable.
+ *
+ * \param cond the condition variable to destroy
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond);
+
+/**
+ * Restart one of the threads that are waiting on the condition variable.
+ *
+ * \param cond the condition variable to signal
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond);
+
+/**
+ * Restart all threads that are waiting on the condition variable.
+ *
+ * \param cond the condition variable to signal
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond);
+
+/**
+ * Wait until a condition variable is signaled.
+ *
+ * This function unlocks the specified `mutex` and waits for another thread to
+ * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
+ * `cond`. Once the condition variable is signaled, the mutex is re-locked and
+ * the function returns.
+ *
+ * The mutex must be locked before calling this function.
+ *
+ * This function is the equivalent of calling SDL_CondWaitTimeout() with a
+ * time length of `SDL_MUTEX_MAXWAIT`.
+ *
+ * \param cond the condition variable to wait on
+ * \param mutex the mutex used to coordinate thread access
+ * \returns 0 when it is signaled or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
+
+/**
+ * Wait until a condition variable is signaled or a certain time has passed.
+ *
+ * This function unlocks the specified `mutex` and waits for another thread to
+ * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
+ * `cond`, or for the specified time to elapse. Once the condition variable is
+ * signaled or the time elapsed, the mutex is re-locked and the function
+ * returns.
+ *
+ * The mutex must be locked before calling this function.
+ *
+ * \param cond the condition variable to wait on
+ * \param mutex the mutex used to coordinate thread access
+ * \param ms the maximum time to wait, in milliseconds, or `SDL_MUTEX_MAXWAIT`
+ * to wait indefinitely
+ * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if
+ * the condition is not signaled in the allotted time, or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond,
+ SDL_mutex * mutex, Uint32 ms);
+
+/* @} *//* Condition variable functions */
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_mutex_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_name.h b/Client/ThirdParty/SDL2/SDL_name.h
new file mode 100644
index 0000000..21e1b79
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_name.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDLname_h_
+#define SDLname_h_
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define NeedFunctionPrototypes 1
+#endif
+
+#define SDL_NAME(X) SDL_##X
+
+#endif /* SDLname_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_opengl.h b/Client/ThirdParty/SDL2/SDL_opengl.h
new file mode 100644
index 0000000..95b51ae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengl.h
@@ -0,0 +1,2183 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengl.h
+ *
+ * This is a simple file to encapsulate the OpenGL API headers.
+ */
+
+/**
+ * \def NO_SDL_GLEXT
+ *
+ * Define this if you have your own version of glext.h and want to disable the
+ * version included in SDL_opengl.h.
+ */
+
+#ifndef SDL_opengl_h_
+#define SDL_opengl_h_
+
+#include "SDL_config.h"
+
+#ifndef __IPHONEOS__ /* No OpenGL on iOS. */
+
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef __gl_h_
+#define __gl_h_
+
+#if defined(USE_MGL_NAMESPACE)
+#include "gl_mangle.h"
+#endif
+
+
+/**********************************************************************
+ * Begin system-specific stuff.
+ */
+
+#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__)
+#define __WIN32__
+#endif
+
+#if defined(__WIN32__) && !defined(__CYGWIN__)
+# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
+# define GLAPI __declspec(dllexport)
+# elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
+# define GLAPI __declspec(dllimport)
+# else /* for use with static link lib build of Win32 edition only */
+# define GLAPI extern
+# endif /* _STATIC_MESA support */
+# if defined(__MINGW32__) && defined(GL_NO_STDCALL) || defined(UNDER_CE) /* The generated DLLs by MingW with STDCALL are not compatible with the ones done by Microsoft's compilers */
+# define GLAPIENTRY
+# else
+# define GLAPIENTRY __stdcall
+# endif
+#elif defined(__CYGWIN__) && defined(USE_OPENGL32) /* use native windows opengl32 */
+# define GLAPI extern
+# define GLAPIENTRY __stdcall
+#elif defined(__OS2__) || defined(__EMX__) /* native os/2 opengl */
+# define GLAPI extern
+# define GLAPIENTRY _System
+# define APIENTRY _System
+# if defined(__GNUC__) && !defined(_System)
+# define _System
+# endif
+#elif (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+# define GLAPI __attribute__((visibility("default")))
+# define GLAPIENTRY
+#endif /* WIN32 && !CYGWIN */
+
+/*
+ * WINDOWS: Include windows.h here to define APIENTRY.
+ * It is also useful when applications include this file by
+ * including only glut.h, since glut.h depends on windows.h.
+ * Applications needing to include windows.h with parms other
+ * than "WIN32_LEAN_AND_MEAN" may include windows.h before
+ * glut.h or gl.h.
+ */
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY GLAPIENTRY
+#endif
+
+/* "P" suffix to be used for a pointer to a function */
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+
+#ifndef GLAPIENTRYP
+#define GLAPIENTRYP GLAPIENTRY *
+#endif
+
+#if defined(PRAGMA_EXPORT_SUPPORTED)
+#pragma export on
+#endif
+
+/*
+ * End system-specific stuff.
+ **********************************************************************/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define GL_VERSION_1_1 1
+#define GL_VERSION_1_2 1
+#define GL_VERSION_1_3 1
+#define GL_ARB_imaging 1
+
+
+/*
+ * Datatypes
+ */
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef signed char GLbyte; /* 1-byte signed */
+typedef short GLshort; /* 2-byte signed */
+typedef int GLint; /* 4-byte signed */
+typedef unsigned char GLubyte; /* 1-byte unsigned */
+typedef unsigned short GLushort; /* 2-byte unsigned */
+typedef unsigned int GLuint; /* 4-byte unsigned */
+typedef int GLsizei; /* 4-byte signed */
+typedef float GLfloat; /* single precision float */
+typedef float GLclampf; /* single precision float in [0,1] */
+typedef double GLdouble; /* double precision float */
+typedef double GLclampd; /* double precision float in [0,1] */
+
+
+
+/*
+ * Constants
+ */
+
+/* Boolean values */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* Data types */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_DOUBLE 0x140A
+
+/* Primitives */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON 0x0009
+
+/* Vertex Arrays */
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+
+/* Matrix Mode */
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+
+/* Points */
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_RANGE 0x0B12
+
+/* Lines */
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+
+/* Polygons */
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_FILL 0x8037
+
+/* Display Lists */
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_LIST_MODE 0x0B30
+
+/* Depth buffer */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_COMPONENT 0x1902
+
+/* Lighting */
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_SHININESS 0x1601
+#define GL_EMISSION 0x1600
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_SHADE_MODEL 0x0B54
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_NORMALIZE 0x0BA1
+
+/* User clipping planes */
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+
+/* Accumulation buffer */
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_ACCUM 0x0100
+#define GL_ADD 0x0104
+#define GL_LOAD 0x0101
+#define GL_MULT 0x0103
+#define GL_RETURN 0x0102
+
+/* Alpha testing */
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+
+/* Blending */
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_DST 0x0BE0
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+
+/* Render Mode */
+#define GL_FEEDBACK 0x1C01
+#define GL_RENDER 0x1C00
+#define GL_SELECT 0x1C02
+
+/* Feedback */
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+
+/* Selection */
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+
+/* Fog */
+#define GL_FOG 0x0B60
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_COLOR 0x0B66
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_LINEAR 0x2601
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+
+/* Logic Ops */
+#define GL_LOGIC_OP 0x0BF1
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_CLEAR 0x1500
+#define GL_SET 0x150F
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_NOOP 0x1505
+#define GL_INVERT 0x150A
+#define GL_AND 0x1501
+#define GL_NAND 0x150E
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_XOR 0x1506
+#define GL_EQUIV 0x1509
+#define GL_AND_REVERSE 0x1502
+#define GL_AND_INVERTED 0x1504
+#define GL_OR_REVERSE 0x150B
+#define GL_OR_INVERTED 0x150D
+
+/* Stencil */
+#define GL_STENCIL_BITS 0x0D57
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_INDEX 0x1901
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+
+/* Buffers, Pixel Drawing/Reading */
+#define GL_NONE 0
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+/*GL_FRONT 0x0404 */
+/*GL_BACK 0x0405 */
+/*GL_FRONT_AND_BACK 0x0408 */
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_COLOR_INDEX 0x1900
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_ALPHA_BITS 0x0D55
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_INDEX_BITS 0x0D51
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_READ_BUFFER 0x0C02
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_BITMAP 0x1A00
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_DITHER 0x0BD0
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+
+/* Implementation limits */
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+
+/* Gets */
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_MODE 0x0C30
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_RENDER_MODE 0x0C40
+#define GL_RGBA_MODE 0x0C31
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_VIEWPORT 0x0BA2
+
+/* Evaluators */
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+
+/* Hints */
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* Scissor box */
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+
+/* Pixel Mode / Transfer */
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+
+/* Texture mapping */
+#define GL_TEXTURE_ENV 0x2300
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_LINEAR 0x2400
+#define GL_EYE_PLANE 0x2502
+#define GL_SPHERE_MAP 0x2402
+#define GL_DECAL 0x2101
+#define GL_MODULATE 0x2100
+#define GL_NEAREST 0x2600
+#define GL_REPEAT 0x2901
+#define GL_CLAMP 0x2900
+#define GL_S 0x2000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+
+/* Utility */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* Errors */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* glPush/PopAttrib bits */
+#define GL_CURRENT_BIT 0x00000001
+#define GL_POINT_BIT 0x00000002
+#define GL_LINE_BIT 0x00000004
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_HINT_BIT 0x00008000
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0x000FFFFF
+
+
+/* OpenGL 1.1 */
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_ALL_CLIENT_ATTRIB_BITS 0xFFFFFFFF
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+
+
+
+/*
+ * Miscellaneous
+ */
+
+GLAPI void GLAPIENTRY glClearIndex( GLfloat c );
+
+GLAPI void GLAPIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha );
+
+GLAPI void GLAPIENTRY glClear( GLbitfield mask );
+
+GLAPI void GLAPIENTRY glIndexMask( GLuint mask );
+
+GLAPI void GLAPIENTRY glColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha );
+
+GLAPI void GLAPIENTRY glAlphaFunc( GLenum func, GLclampf ref );
+
+GLAPI void GLAPIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor );
+
+GLAPI void GLAPIENTRY glLogicOp( GLenum opcode );
+
+GLAPI void GLAPIENTRY glCullFace( GLenum mode );
+
+GLAPI void GLAPIENTRY glFrontFace( GLenum mode );
+
+GLAPI void GLAPIENTRY glPointSize( GLfloat size );
+
+GLAPI void GLAPIENTRY glLineWidth( GLfloat width );
+
+GLAPI void GLAPIENTRY glLineStipple( GLint factor, GLushort pattern );
+
+GLAPI void GLAPIENTRY glPolygonMode( GLenum face, GLenum mode );
+
+GLAPI void GLAPIENTRY glPolygonOffset( GLfloat factor, GLfloat units );
+
+GLAPI void GLAPIENTRY glPolygonStipple( const GLubyte *mask );
+
+GLAPI void GLAPIENTRY glGetPolygonStipple( GLubyte *mask );
+
+GLAPI void GLAPIENTRY glEdgeFlag( GLboolean flag );
+
+GLAPI void GLAPIENTRY glEdgeFlagv( const GLboolean *flag );
+
+GLAPI void GLAPIENTRY glScissor( GLint x, GLint y, GLsizei width, GLsizei height);
+
+GLAPI void GLAPIENTRY glClipPlane( GLenum plane, const GLdouble *equation );
+
+GLAPI void GLAPIENTRY glGetClipPlane( GLenum plane, GLdouble *equation );
+
+GLAPI void GLAPIENTRY glDrawBuffer( GLenum mode );
+
+GLAPI void GLAPIENTRY glReadBuffer( GLenum mode );
+
+GLAPI void GLAPIENTRY glEnable( GLenum cap );
+
+GLAPI void GLAPIENTRY glDisable( GLenum cap );
+
+GLAPI GLboolean GLAPIENTRY glIsEnabled( GLenum cap );
+
+
+GLAPI void GLAPIENTRY glEnableClientState( GLenum cap ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glDisableClientState( GLenum cap ); /* 1.1 */
+
+
+GLAPI void GLAPIENTRY glGetBooleanv( GLenum pname, GLboolean *params );
+
+GLAPI void GLAPIENTRY glGetDoublev( GLenum pname, GLdouble *params );
+
+GLAPI void GLAPIENTRY glGetFloatv( GLenum pname, GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetIntegerv( GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glPushAttrib( GLbitfield mask );
+
+GLAPI void GLAPIENTRY glPopAttrib( void );
+
+
+GLAPI void GLAPIENTRY glPushClientAttrib( GLbitfield mask ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glPopClientAttrib( void ); /* 1.1 */
+
+
+GLAPI GLint GLAPIENTRY glRenderMode( GLenum mode );
+
+GLAPI GLenum GLAPIENTRY glGetError( void );
+
+GLAPI const GLubyte * GLAPIENTRY glGetString( GLenum name );
+
+GLAPI void GLAPIENTRY glFinish( void );
+
+GLAPI void GLAPIENTRY glFlush( void );
+
+GLAPI void GLAPIENTRY glHint( GLenum target, GLenum mode );
+
+
+/*
+ * Depth Buffer
+ */
+
+GLAPI void GLAPIENTRY glClearDepth( GLclampd depth );
+
+GLAPI void GLAPIENTRY glDepthFunc( GLenum func );
+
+GLAPI void GLAPIENTRY glDepthMask( GLboolean flag );
+
+GLAPI void GLAPIENTRY glDepthRange( GLclampd near_val, GLclampd far_val );
+
+
+/*
+ * Accumulation Buffer
+ */
+
+GLAPI void GLAPIENTRY glClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha );
+
+GLAPI void GLAPIENTRY glAccum( GLenum op, GLfloat value );
+
+
+/*
+ * Transformation
+ */
+
+GLAPI void GLAPIENTRY glMatrixMode( GLenum mode );
+
+GLAPI void GLAPIENTRY glOrtho( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble near_val, GLdouble far_val );
+
+GLAPI void GLAPIENTRY glFrustum( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble near_val, GLdouble far_val );
+
+GLAPI void GLAPIENTRY glViewport( GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+GLAPI void GLAPIENTRY glPushMatrix( void );
+
+GLAPI void GLAPIENTRY glPopMatrix( void );
+
+GLAPI void GLAPIENTRY glLoadIdentity( void );
+
+GLAPI void GLAPIENTRY glLoadMatrixd( const GLdouble *m );
+GLAPI void GLAPIENTRY glLoadMatrixf( const GLfloat *m );
+
+GLAPI void GLAPIENTRY glMultMatrixd( const GLdouble *m );
+GLAPI void GLAPIENTRY glMultMatrixf( const GLfloat *m );
+
+GLAPI void GLAPIENTRY glRotated( GLdouble angle,
+ GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glRotatef( GLfloat angle,
+ GLfloat x, GLfloat y, GLfloat z );
+
+GLAPI void GLAPIENTRY glScaled( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glScalef( GLfloat x, GLfloat y, GLfloat z );
+
+GLAPI void GLAPIENTRY glTranslated( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glTranslatef( GLfloat x, GLfloat y, GLfloat z );
+
+
+/*
+ * Display Lists
+ */
+
+GLAPI GLboolean GLAPIENTRY glIsList( GLuint list );
+
+GLAPI void GLAPIENTRY glDeleteLists( GLuint list, GLsizei range );
+
+GLAPI GLuint GLAPIENTRY glGenLists( GLsizei range );
+
+GLAPI void GLAPIENTRY glNewList( GLuint list, GLenum mode );
+
+GLAPI void GLAPIENTRY glEndList( void );
+
+GLAPI void GLAPIENTRY glCallList( GLuint list );
+
+GLAPI void GLAPIENTRY glCallLists( GLsizei n, GLenum type,
+ const GLvoid *lists );
+
+GLAPI void GLAPIENTRY glListBase( GLuint base );
+
+
+/*
+ * Drawing Functions
+ */
+
+GLAPI void GLAPIENTRY glBegin( GLenum mode );
+
+GLAPI void GLAPIENTRY glEnd( void );
+
+
+GLAPI void GLAPIENTRY glVertex2d( GLdouble x, GLdouble y );
+GLAPI void GLAPIENTRY glVertex2f( GLfloat x, GLfloat y );
+GLAPI void GLAPIENTRY glVertex2i( GLint x, GLint y );
+GLAPI void GLAPIENTRY glVertex2s( GLshort x, GLshort y );
+
+GLAPI void GLAPIENTRY glVertex3d( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glVertex3f( GLfloat x, GLfloat y, GLfloat z );
+GLAPI void GLAPIENTRY glVertex3i( GLint x, GLint y, GLint z );
+GLAPI void GLAPIENTRY glVertex3s( GLshort x, GLshort y, GLshort z );
+
+GLAPI void GLAPIENTRY glVertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w );
+GLAPI void GLAPIENTRY glVertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+GLAPI void GLAPIENTRY glVertex4i( GLint x, GLint y, GLint z, GLint w );
+GLAPI void GLAPIENTRY glVertex4s( GLshort x, GLshort y, GLshort z, GLshort w );
+
+GLAPI void GLAPIENTRY glVertex2dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glVertex2fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glVertex2iv( const GLint *v );
+GLAPI void GLAPIENTRY glVertex2sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glVertex3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glVertex3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glVertex3iv( const GLint *v );
+GLAPI void GLAPIENTRY glVertex3sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glVertex4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glVertex4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glVertex4iv( const GLint *v );
+GLAPI void GLAPIENTRY glVertex4sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glNormal3b( GLbyte nx, GLbyte ny, GLbyte nz );
+GLAPI void GLAPIENTRY glNormal3d( GLdouble nx, GLdouble ny, GLdouble nz );
+GLAPI void GLAPIENTRY glNormal3f( GLfloat nx, GLfloat ny, GLfloat nz );
+GLAPI void GLAPIENTRY glNormal3i( GLint nx, GLint ny, GLint nz );
+GLAPI void GLAPIENTRY glNormal3s( GLshort nx, GLshort ny, GLshort nz );
+
+GLAPI void GLAPIENTRY glNormal3bv( const GLbyte *v );
+GLAPI void GLAPIENTRY glNormal3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glNormal3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glNormal3iv( const GLint *v );
+GLAPI void GLAPIENTRY glNormal3sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glIndexd( GLdouble c );
+GLAPI void GLAPIENTRY glIndexf( GLfloat c );
+GLAPI void GLAPIENTRY glIndexi( GLint c );
+GLAPI void GLAPIENTRY glIndexs( GLshort c );
+GLAPI void GLAPIENTRY glIndexub( GLubyte c ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glIndexdv( const GLdouble *c );
+GLAPI void GLAPIENTRY glIndexfv( const GLfloat *c );
+GLAPI void GLAPIENTRY glIndexiv( const GLint *c );
+GLAPI void GLAPIENTRY glIndexsv( const GLshort *c );
+GLAPI void GLAPIENTRY glIndexubv( const GLubyte *c ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glColor3b( GLbyte red, GLbyte green, GLbyte blue );
+GLAPI void GLAPIENTRY glColor3d( GLdouble red, GLdouble green, GLdouble blue );
+GLAPI void GLAPIENTRY glColor3f( GLfloat red, GLfloat green, GLfloat blue );
+GLAPI void GLAPIENTRY glColor3i( GLint red, GLint green, GLint blue );
+GLAPI void GLAPIENTRY glColor3s( GLshort red, GLshort green, GLshort blue );
+GLAPI void GLAPIENTRY glColor3ub( GLubyte red, GLubyte green, GLubyte blue );
+GLAPI void GLAPIENTRY glColor3ui( GLuint red, GLuint green, GLuint blue );
+GLAPI void GLAPIENTRY glColor3us( GLushort red, GLushort green, GLushort blue );
+
+GLAPI void GLAPIENTRY glColor4b( GLbyte red, GLbyte green,
+ GLbyte blue, GLbyte alpha );
+GLAPI void GLAPIENTRY glColor4d( GLdouble red, GLdouble green,
+ GLdouble blue, GLdouble alpha );
+GLAPI void GLAPIENTRY glColor4f( GLfloat red, GLfloat green,
+ GLfloat blue, GLfloat alpha );
+GLAPI void GLAPIENTRY glColor4i( GLint red, GLint green,
+ GLint blue, GLint alpha );
+GLAPI void GLAPIENTRY glColor4s( GLshort red, GLshort green,
+ GLshort blue, GLshort alpha );
+GLAPI void GLAPIENTRY glColor4ub( GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha );
+GLAPI void GLAPIENTRY glColor4ui( GLuint red, GLuint green,
+ GLuint blue, GLuint alpha );
+GLAPI void GLAPIENTRY glColor4us( GLushort red, GLushort green,
+ GLushort blue, GLushort alpha );
+
+
+GLAPI void GLAPIENTRY glColor3bv( const GLbyte *v );
+GLAPI void GLAPIENTRY glColor3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glColor3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glColor3iv( const GLint *v );
+GLAPI void GLAPIENTRY glColor3sv( const GLshort *v );
+GLAPI void GLAPIENTRY glColor3ubv( const GLubyte *v );
+GLAPI void GLAPIENTRY glColor3uiv( const GLuint *v );
+GLAPI void GLAPIENTRY glColor3usv( const GLushort *v );
+
+GLAPI void GLAPIENTRY glColor4bv( const GLbyte *v );
+GLAPI void GLAPIENTRY glColor4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glColor4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glColor4iv( const GLint *v );
+GLAPI void GLAPIENTRY glColor4sv( const GLshort *v );
+GLAPI void GLAPIENTRY glColor4ubv( const GLubyte *v );
+GLAPI void GLAPIENTRY glColor4uiv( const GLuint *v );
+GLAPI void GLAPIENTRY glColor4usv( const GLushort *v );
+
+
+GLAPI void GLAPIENTRY glTexCoord1d( GLdouble s );
+GLAPI void GLAPIENTRY glTexCoord1f( GLfloat s );
+GLAPI void GLAPIENTRY glTexCoord1i( GLint s );
+GLAPI void GLAPIENTRY glTexCoord1s( GLshort s );
+
+GLAPI void GLAPIENTRY glTexCoord2d( GLdouble s, GLdouble t );
+GLAPI void GLAPIENTRY glTexCoord2f( GLfloat s, GLfloat t );
+GLAPI void GLAPIENTRY glTexCoord2i( GLint s, GLint t );
+GLAPI void GLAPIENTRY glTexCoord2s( GLshort s, GLshort t );
+
+GLAPI void GLAPIENTRY glTexCoord3d( GLdouble s, GLdouble t, GLdouble r );
+GLAPI void GLAPIENTRY glTexCoord3f( GLfloat s, GLfloat t, GLfloat r );
+GLAPI void GLAPIENTRY glTexCoord3i( GLint s, GLint t, GLint r );
+GLAPI void GLAPIENTRY glTexCoord3s( GLshort s, GLshort t, GLshort r );
+
+GLAPI void GLAPIENTRY glTexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q );
+GLAPI void GLAPIENTRY glTexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q );
+GLAPI void GLAPIENTRY glTexCoord4i( GLint s, GLint t, GLint r, GLint q );
+GLAPI void GLAPIENTRY glTexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q );
+
+GLAPI void GLAPIENTRY glTexCoord1dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord1fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord1iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord1sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glTexCoord2dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord2fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord2iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord2sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glTexCoord3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord3iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord3sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glTexCoord4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord4iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord4sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glRasterPos2d( GLdouble x, GLdouble y );
+GLAPI void GLAPIENTRY glRasterPos2f( GLfloat x, GLfloat y );
+GLAPI void GLAPIENTRY glRasterPos2i( GLint x, GLint y );
+GLAPI void GLAPIENTRY glRasterPos2s( GLshort x, GLshort y );
+
+GLAPI void GLAPIENTRY glRasterPos3d( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glRasterPos3f( GLfloat x, GLfloat y, GLfloat z );
+GLAPI void GLAPIENTRY glRasterPos3i( GLint x, GLint y, GLint z );
+GLAPI void GLAPIENTRY glRasterPos3s( GLshort x, GLshort y, GLshort z );
+
+GLAPI void GLAPIENTRY glRasterPos4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w );
+GLAPI void GLAPIENTRY glRasterPos4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+GLAPI void GLAPIENTRY glRasterPos4i( GLint x, GLint y, GLint z, GLint w );
+GLAPI void GLAPIENTRY glRasterPos4s( GLshort x, GLshort y, GLshort z, GLshort w );
+
+GLAPI void GLAPIENTRY glRasterPos2dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glRasterPos2fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glRasterPos2iv( const GLint *v );
+GLAPI void GLAPIENTRY glRasterPos2sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glRasterPos3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glRasterPos3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glRasterPos3iv( const GLint *v );
+GLAPI void GLAPIENTRY glRasterPos3sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glRasterPos4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glRasterPos4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glRasterPos4iv( const GLint *v );
+GLAPI void GLAPIENTRY glRasterPos4sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glRectd( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 );
+GLAPI void GLAPIENTRY glRectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 );
+GLAPI void GLAPIENTRY glRecti( GLint x1, GLint y1, GLint x2, GLint y2 );
+GLAPI void GLAPIENTRY glRects( GLshort x1, GLshort y1, GLshort x2, GLshort y2 );
+
+
+GLAPI void GLAPIENTRY glRectdv( const GLdouble *v1, const GLdouble *v2 );
+GLAPI void GLAPIENTRY glRectfv( const GLfloat *v1, const GLfloat *v2 );
+GLAPI void GLAPIENTRY glRectiv( const GLint *v1, const GLint *v2 );
+GLAPI void GLAPIENTRY glRectsv( const GLshort *v1, const GLshort *v2 );
+
+
+/*
+ * Vertex Arrays (1.1)
+ */
+
+GLAPI void GLAPIENTRY glVertexPointer( GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glNormalPointer( GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glColorPointer( GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glIndexPointer( GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glTexCoordPointer( GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glEdgeFlagPointer( GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glGetPointerv( GLenum pname, GLvoid **params );
+
+GLAPI void GLAPIENTRY glArrayElement( GLint i );
+
+GLAPI void GLAPIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count );
+
+GLAPI void GLAPIENTRY glDrawElements( GLenum mode, GLsizei count,
+ GLenum type, const GLvoid *indices );
+
+GLAPI void GLAPIENTRY glInterleavedArrays( GLenum format, GLsizei stride,
+ const GLvoid *pointer );
+
+/*
+ * Lighting
+ */
+
+GLAPI void GLAPIENTRY glShadeModel( GLenum mode );
+
+GLAPI void GLAPIENTRY glLightf( GLenum light, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glLighti( GLenum light, GLenum pname, GLint param );
+GLAPI void GLAPIENTRY glLightfv( GLenum light, GLenum pname,
+ const GLfloat *params );
+GLAPI void GLAPIENTRY glLightiv( GLenum light, GLenum pname,
+ const GLint *params );
+
+GLAPI void GLAPIENTRY glGetLightfv( GLenum light, GLenum pname,
+ GLfloat *params );
+GLAPI void GLAPIENTRY glGetLightiv( GLenum light, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glLightModelf( GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glLightModeli( GLenum pname, GLint param );
+GLAPI void GLAPIENTRY glLightModelfv( GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glLightModeliv( GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glMaterialf( GLenum face, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glMateriali( GLenum face, GLenum pname, GLint param );
+GLAPI void GLAPIENTRY glMaterialfv( GLenum face, GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glMaterialiv( GLenum face, GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glGetMaterialfv( GLenum face, GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetMaterialiv( GLenum face, GLenum pname, GLint *params );
+
+GLAPI void GLAPIENTRY glColorMaterial( GLenum face, GLenum mode );
+
+
+/*
+ * Raster functions
+ */
+
+GLAPI void GLAPIENTRY glPixelZoom( GLfloat xfactor, GLfloat yfactor );
+
+GLAPI void GLAPIENTRY glPixelStoref( GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glPixelStorei( GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glPixelTransferf( GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glPixelTransferi( GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glPixelMapfv( GLenum map, GLsizei mapsize,
+ const GLfloat *values );
+GLAPI void GLAPIENTRY glPixelMapuiv( GLenum map, GLsizei mapsize,
+ const GLuint *values );
+GLAPI void GLAPIENTRY glPixelMapusv( GLenum map, GLsizei mapsize,
+ const GLushort *values );
+
+GLAPI void GLAPIENTRY glGetPixelMapfv( GLenum map, GLfloat *values );
+GLAPI void GLAPIENTRY glGetPixelMapuiv( GLenum map, GLuint *values );
+GLAPI void GLAPIENTRY glGetPixelMapusv( GLenum map, GLushort *values );
+
+GLAPI void GLAPIENTRY glBitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig,
+ GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap );
+
+GLAPI void GLAPIENTRY glReadPixels( GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glDrawPixels( GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glCopyPixels( GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type );
+
+/*
+ * Stenciling
+ */
+
+GLAPI void GLAPIENTRY glStencilFunc( GLenum func, GLint ref, GLuint mask );
+
+GLAPI void GLAPIENTRY glStencilMask( GLuint mask );
+
+GLAPI void GLAPIENTRY glStencilOp( GLenum fail, GLenum zfail, GLenum zpass );
+
+GLAPI void GLAPIENTRY glClearStencil( GLint s );
+
+
+
+/*
+ * Texture mapping
+ */
+
+GLAPI void GLAPIENTRY glTexGend( GLenum coord, GLenum pname, GLdouble param );
+GLAPI void GLAPIENTRY glTexGenf( GLenum coord, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glTexGeni( GLenum coord, GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glTexGendv( GLenum coord, GLenum pname, const GLdouble *params );
+GLAPI void GLAPIENTRY glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glTexGeniv( GLenum coord, GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexGendv( GLenum coord, GLenum pname, GLdouble *params );
+GLAPI void GLAPIENTRY glGetTexGenfv( GLenum coord, GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetTexGeniv( GLenum coord, GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glTexEnvf( GLenum target, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glTexEnvi( GLenum target, GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glTexEnvfv( GLenum target, GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glTexEnviv( GLenum target, GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetTexEnviv( GLenum target, GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glTexParameterf( GLenum target, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glTexParameterfv( GLenum target, GLenum pname,
+ const GLfloat *params );
+GLAPI void GLAPIENTRY glTexParameteriv( GLenum target, GLenum pname,
+ const GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexParameterfv( GLenum target,
+ GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexParameteriv( GLenum target,
+ GLenum pname, GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexLevelParameterfv( GLenum target, GLint level,
+ GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetTexLevelParameteriv( GLenum target, GLint level,
+ GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glTexImage1D( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glTexImage2D( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glGetTexImage( GLenum target, GLint level,
+ GLenum format, GLenum type,
+ GLvoid *pixels );
+
+
+/* 1.1 functions */
+
+GLAPI void GLAPIENTRY glGenTextures( GLsizei n, GLuint *textures );
+
+GLAPI void GLAPIENTRY glDeleteTextures( GLsizei n, const GLuint *textures);
+
+GLAPI void GLAPIENTRY glBindTexture( GLenum target, GLuint texture );
+
+GLAPI void GLAPIENTRY glPrioritizeTextures( GLsizei n,
+ const GLuint *textures,
+ const GLclampf *priorities );
+
+GLAPI GLboolean GLAPIENTRY glAreTexturesResident( GLsizei n,
+ const GLuint *textures,
+ GLboolean *residences );
+
+GLAPI GLboolean GLAPIENTRY glIsTexture( GLuint texture );
+
+
+GLAPI void GLAPIENTRY glTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset,
+ GLsizei width, GLenum format,
+ GLenum type, const GLvoid *pixels );
+
+
+GLAPI void GLAPIENTRY glTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+GLAPI void GLAPIENTRY glCopyTexImage1D( GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLint border );
+
+
+GLAPI void GLAPIENTRY glCopyTexImage2D( GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLint border );
+
+
+GLAPI void GLAPIENTRY glCopyTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y,
+ GLsizei width );
+
+
+GLAPI void GLAPIENTRY glCopyTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+
+/*
+ * Evaluators
+ */
+
+GLAPI void GLAPIENTRY glMap1d( GLenum target, GLdouble u1, GLdouble u2,
+ GLint stride,
+ GLint order, const GLdouble *points );
+GLAPI void GLAPIENTRY glMap1f( GLenum target, GLfloat u1, GLfloat u2,
+ GLint stride,
+ GLint order, const GLfloat *points );
+
+GLAPI void GLAPIENTRY glMap2d( GLenum target,
+ GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
+ GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
+ const GLdouble *points );
+GLAPI void GLAPIENTRY glMap2f( GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points );
+
+GLAPI void GLAPIENTRY glGetMapdv( GLenum target, GLenum query, GLdouble *v );
+GLAPI void GLAPIENTRY glGetMapfv( GLenum target, GLenum query, GLfloat *v );
+GLAPI void GLAPIENTRY glGetMapiv( GLenum target, GLenum query, GLint *v );
+
+GLAPI void GLAPIENTRY glEvalCoord1d( GLdouble u );
+GLAPI void GLAPIENTRY glEvalCoord1f( GLfloat u );
+
+GLAPI void GLAPIENTRY glEvalCoord1dv( const GLdouble *u );
+GLAPI void GLAPIENTRY glEvalCoord1fv( const GLfloat *u );
+
+GLAPI void GLAPIENTRY glEvalCoord2d( GLdouble u, GLdouble v );
+GLAPI void GLAPIENTRY glEvalCoord2f( GLfloat u, GLfloat v );
+
+GLAPI void GLAPIENTRY glEvalCoord2dv( const GLdouble *u );
+GLAPI void GLAPIENTRY glEvalCoord2fv( const GLfloat *u );
+
+GLAPI void GLAPIENTRY glMapGrid1d( GLint un, GLdouble u1, GLdouble u2 );
+GLAPI void GLAPIENTRY glMapGrid1f( GLint un, GLfloat u1, GLfloat u2 );
+
+GLAPI void GLAPIENTRY glMapGrid2d( GLint un, GLdouble u1, GLdouble u2,
+ GLint vn, GLdouble v1, GLdouble v2 );
+GLAPI void GLAPIENTRY glMapGrid2f( GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 );
+
+GLAPI void GLAPIENTRY glEvalPoint1( GLint i );
+
+GLAPI void GLAPIENTRY glEvalPoint2( GLint i, GLint j );
+
+GLAPI void GLAPIENTRY glEvalMesh1( GLenum mode, GLint i1, GLint i2 );
+
+GLAPI void GLAPIENTRY glEvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 );
+
+
+/*
+ * Fog
+ */
+
+GLAPI void GLAPIENTRY glFogf( GLenum pname, GLfloat param );
+
+GLAPI void GLAPIENTRY glFogi( GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glFogfv( GLenum pname, const GLfloat *params );
+
+GLAPI void GLAPIENTRY glFogiv( GLenum pname, const GLint *params );
+
+
+/*
+ * Selection and Feedback
+ */
+
+GLAPI void GLAPIENTRY glFeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer );
+
+GLAPI void GLAPIENTRY glPassThrough( GLfloat token );
+
+GLAPI void GLAPIENTRY glSelectBuffer( GLsizei size, GLuint *buffer );
+
+GLAPI void GLAPIENTRY glInitNames( void );
+
+GLAPI void GLAPIENTRY glLoadName( GLuint name );
+
+GLAPI void GLAPIENTRY glPushName( GLuint name );
+
+GLAPI void GLAPIENTRY glPopName( void );
+
+
+
+/*
+ * OpenGL 1.2
+ */
+
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_TEXTURE_BINDING_3D 0x806A
+
+GLAPI void GLAPIENTRY glDrawRangeElements( GLenum mode, GLuint start,
+ GLuint end, GLsizei count, GLenum type, const GLvoid *indices );
+
+GLAPI void GLAPIENTRY glTexImage3D( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth,
+ GLenum format,
+ GLenum type, const GLvoid *pixels);
+
+GLAPI void GLAPIENTRY glCopyTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint zoffset, GLint x,
+ GLint y, GLsizei width,
+ GLsizei height );
+
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+/*
+ * GL_ARB_imaging
+ */
+
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_BLEND_EQUATION 0x8009
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_COLOR 0x8005
+
+
+GLAPI void GLAPIENTRY glColorTable( GLenum target, GLenum internalformat,
+ GLsizei width, GLenum format,
+ GLenum type, const GLvoid *table );
+
+GLAPI void GLAPIENTRY glColorSubTable( GLenum target,
+ GLsizei start, GLsizei count,
+ GLenum format, GLenum type,
+ const GLvoid *data );
+
+GLAPI void GLAPIENTRY glColorTableParameteriv(GLenum target, GLenum pname,
+ const GLint *params);
+
+GLAPI void GLAPIENTRY glColorTableParameterfv(GLenum target, GLenum pname,
+ const GLfloat *params);
+
+GLAPI void GLAPIENTRY glCopyColorSubTable( GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width );
+
+GLAPI void GLAPIENTRY glCopyColorTable( GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width );
+
+GLAPI void GLAPIENTRY glGetColorTable( GLenum target, GLenum format,
+ GLenum type, GLvoid *table );
+
+GLAPI void GLAPIENTRY glGetColorTableParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetColorTableParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glBlendEquation( GLenum mode );
+
+GLAPI void GLAPIENTRY glBlendColor( GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha );
+
+GLAPI void GLAPIENTRY glHistogram( GLenum target, GLsizei width,
+ GLenum internalformat, GLboolean sink );
+
+GLAPI void GLAPIENTRY glResetHistogram( GLenum target );
+
+GLAPI void GLAPIENTRY glGetHistogram( GLenum target, GLboolean reset,
+ GLenum format, GLenum type,
+ GLvoid *values );
+
+GLAPI void GLAPIENTRY glGetHistogramParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetHistogramParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glMinmax( GLenum target, GLenum internalformat,
+ GLboolean sink );
+
+GLAPI void GLAPIENTRY glResetMinmax( GLenum target );
+
+GLAPI void GLAPIENTRY glGetMinmax( GLenum target, GLboolean reset,
+ GLenum format, GLenum types,
+ GLvoid *values );
+
+GLAPI void GLAPIENTRY glGetMinmaxParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetMinmaxParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glConvolutionFilter1D( GLenum target,
+ GLenum internalformat, GLsizei width, GLenum format, GLenum type,
+ const GLvoid *image );
+
+GLAPI void GLAPIENTRY glConvolutionFilter2D( GLenum target,
+ GLenum internalformat, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid *image );
+
+GLAPI void GLAPIENTRY glConvolutionParameterf( GLenum target, GLenum pname,
+ GLfloat params );
+
+GLAPI void GLAPIENTRY glConvolutionParameterfv( GLenum target, GLenum pname,
+ const GLfloat *params );
+
+GLAPI void GLAPIENTRY glConvolutionParameteri( GLenum target, GLenum pname,
+ GLint params );
+
+GLAPI void GLAPIENTRY glConvolutionParameteriv( GLenum target, GLenum pname,
+ const GLint *params );
+
+GLAPI void GLAPIENTRY glCopyConvolutionFilter1D( GLenum target,
+ GLenum internalformat, GLint x, GLint y, GLsizei width );
+
+GLAPI void GLAPIENTRY glCopyConvolutionFilter2D( GLenum target,
+ GLenum internalformat, GLint x, GLint y, GLsizei width,
+ GLsizei height);
+
+GLAPI void GLAPIENTRY glGetConvolutionFilter( GLenum target, GLenum format,
+ GLenum type, GLvoid *image );
+
+GLAPI void GLAPIENTRY glGetConvolutionParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetConvolutionParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glSeparableFilter2D( GLenum target,
+ GLenum internalformat, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid *row, const GLvoid *column );
+
+GLAPI void GLAPIENTRY glGetSeparableFilter( GLenum target, GLenum format,
+ GLenum type, GLvoid *row, GLvoid *column, GLvoid *span );
+
+
+
+
+/*
+ * OpenGL 1.3
+ */
+
+/* multitexture */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+/* texture_cube_map */
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+/* texture_compression */
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+/* multisample */
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_MULTISAMPLE_BIT 0x20000000
+/* transpose_matrix */
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+/* texture_env_combine */
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+/* texture_env_dot3 */
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+/* texture_border_clamp */
+#define GL_CLAMP_TO_BORDER 0x812D
+
+GLAPI void GLAPIENTRY glActiveTexture( GLenum texture );
+
+GLAPI void GLAPIENTRY glClientActiveTexture( GLenum texture );
+
+GLAPI void GLAPIENTRY glCompressedTexImage1D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexImage3D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glGetCompressedTexImage( GLenum target, GLint lod, GLvoid *img );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1d( GLenum target, GLdouble s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1f( GLenum target, GLfloat s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1i( GLenum target, GLint s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1s( GLenum target, GLshort s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1sv( GLenum target, const GLshort *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2d( GLenum target, GLdouble s, GLdouble t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2f( GLenum target, GLfloat s, GLfloat t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2i( GLenum target, GLint s, GLint t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2s( GLenum target, GLshort s, GLshort t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2sv( GLenum target, const GLshort *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3d( GLenum target, GLdouble s, GLdouble t, GLdouble r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, GLfloat r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3i( GLenum target, GLint s, GLint t, GLint r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3s( GLenum target, GLshort s, GLshort t, GLshort r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3sv( GLenum target, const GLshort *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4d( GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4i( GLenum target, GLint s, GLint t, GLint r, GLint q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4s( GLenum target, GLshort s, GLshort t, GLshort r, GLshort q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4sv( GLenum target, const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glLoadTransposeMatrixd( const GLdouble m[16] );
+
+GLAPI void GLAPIENTRY glLoadTransposeMatrixf( const GLfloat m[16] );
+
+GLAPI void GLAPIENTRY glMultTransposeMatrixd( const GLdouble m[16] );
+
+GLAPI void GLAPIENTRY glMultTransposeMatrixf( const GLfloat m[16] );
+
+GLAPI void GLAPIENTRY glSampleCoverage( GLclampf value, GLboolean invert );
+
+
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
+
+
+
+/*
+ * GL_ARB_multitexture (ARB extension 1 and OpenGL 1.2.1)
+ */
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+
+GLAPI void GLAPIENTRY glActiveTextureARB(GLenum texture);
+GLAPI void GLAPIENTRY glClientActiveTextureARB(GLenum texture);
+GLAPI void GLAPIENTRY glMultiTexCoord1dARB(GLenum target, GLdouble s);
+GLAPI void GLAPIENTRY glMultiTexCoord1dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord1fARB(GLenum target, GLfloat s);
+GLAPI void GLAPIENTRY glMultiTexCoord1fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord1iARB(GLenum target, GLint s);
+GLAPI void GLAPIENTRY glMultiTexCoord1ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord1sARB(GLenum target, GLshort s);
+GLAPI void GLAPIENTRY glMultiTexCoord1svARB(GLenum target, const GLshort *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t);
+GLAPI void GLAPIENTRY glMultiTexCoord2dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t);
+GLAPI void GLAPIENTRY glMultiTexCoord2fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2iARB(GLenum target, GLint s, GLint t);
+GLAPI void GLAPIENTRY glMultiTexCoord2ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2sARB(GLenum target, GLshort s, GLshort t);
+GLAPI void GLAPIENTRY glMultiTexCoord2svARB(GLenum target, const GLshort *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void GLAPIENTRY glMultiTexCoord3dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void GLAPIENTRY glMultiTexCoord3fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r);
+GLAPI void GLAPIENTRY glMultiTexCoord3ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void GLAPIENTRY glMultiTexCoord3svARB(GLenum target, const GLshort *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void GLAPIENTRY glMultiTexCoord4dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void GLAPIENTRY glMultiTexCoord4fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void GLAPIENTRY glMultiTexCoord4ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void GLAPIENTRY glMultiTexCoord4svARB(GLenum target, const GLshort *v);
+
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+
+#endif /* GL_ARB_multitexture */
+
+
+
+/*
+ * Define this token if you want "old-style" header file behaviour (extensions
+ * defined in gl.h). Otherwise, extensions will be included from glext.h.
+ */
+#if !defined(NO_SDL_GLEXT) && !defined(GL_GLEXT_LEGACY)
+#include "SDL_opengl_glext.h"
+#endif /* GL_GLEXT_LEGACY */
+
+
+
+/*
+ * ???. GL_MESA_packed_depth_stencil
+ * XXX obsolete
+ */
+#ifndef GL_MESA_packed_depth_stencil
+#define GL_MESA_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_MESA 0x8750
+#define GL_UNSIGNED_INT_24_8_MESA 0x8751
+#define GL_UNSIGNED_INT_8_24_REV_MESA 0x8752
+#define GL_UNSIGNED_SHORT_15_1_MESA 0x8753
+#define GL_UNSIGNED_SHORT_1_15_REV_MESA 0x8754
+
+#endif /* GL_MESA_packed_depth_stencil */
+
+
+#ifndef GL_ATI_blend_equation_separate
+#define GL_ATI_blend_equation_separate 1
+
+#define GL_ALPHA_BLEND_EQUATION_ATI 0x883D
+
+GLAPI void GLAPIENTRY glBlendEquationSeparateATI( GLenum modeRGB, GLenum modeA );
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEATIPROC) (GLenum modeRGB, GLenum modeA);
+
+#endif /* GL_ATI_blend_equation_separate */
+
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GLAPI void APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+
+/**
+ ** NOTE!!!!! If you add new functions to this file, or update
+ ** glext.h be sure to regenerate the gl_mangle.h file. See comments
+ ** in that file for details.
+ **/
+
+
+
+/**********************************************************************
+ * Begin system-specific stuff
+ */
+#if defined(PRAGMA_EXPORT_SUPPORTED)
+#pragma export off
+#endif
+
+/*
+ * End system-specific stuff
+ **********************************************************************/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl_h_ */
+
+#endif /* !__IPHONEOS__ */
+
+#endif /* SDL_opengl_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_opengl_glext.h b/Client/ThirdParty/SDL2/SDL_opengl_glext.h
new file mode 100644
index 0000000..6a402b1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengl_glext.h
@@ -0,0 +1,11180 @@
+#ifndef __glext_h_
+#define __glext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 26745 $ on $Date: 2014-05-21 03:12:26 -0700 (Wed, 21 May 2014) $
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#define GL_GLEXT_VERSION 20140521
+
+/* Generated C header for:
+ * API: gl
+ * Profile: compatibility
+ * Versions considered: .*
+ * Versions emitted: 1\.[2-9]|[234]\.[0-9]
+ * Default extensions included: gl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_VERSION_1_2 */
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, void *img);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum texture);
+GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, void *img);
+GLAPI void APIENTRY glClientActiveTexture (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1d (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1f (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1i (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1s (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2i (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2s (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m);
+#endif
+#endif /* GL_VERSION_1_3 */
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFogCoordf (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfv (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoordd (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddv (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointer (GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3i (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3iv (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3s (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3us (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glWindowPos2d (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2f (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2i (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos2s (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2sv (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3sv (const GLshort *v);
+GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void APIENTRY glBlendEquation (GLenum mode);
+#endif
+#endif /* GL_VERSION_1_4 */
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#include <stddef.h>
+#ifdef __MACOSX__
+typedef long GLsizeiptr;
+typedef long GLintptr;
+#else
+typedef ptrdiff_t GLsizeiptr;
+typedef ptrdiff_t GLintptr;
+#endif
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_COORD 0x8451
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC2_ALPHA 0x858A
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint id);
+GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQuery (GLenum target);
+GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer);
+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_VERSION_1_5 */
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+typedef char GLchar;
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_TEXTURE_COORDS 0x8871
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GLAPI void APIENTRY glCompileShader (GLuint shader);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum type);
+GLAPI void APIENTRY glDeleteProgram (GLuint program);
+GLAPI void APIENTRY glDeleteShader (GLuint shader);
+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
+GLAPI GLboolean APIENTRY glIsShader (GLuint shader);
+GLAPI void APIENTRY glLinkProgram (GLuint program);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GLAPI void APIENTRY glUseProgram (GLuint program);
+GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glValidateProgram (GLuint program);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_VERSION_2_0 */
+
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+#endif /* GL_VERSION_2_1 */
+
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_INDEX 0x8222
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_ALPHA_INTEGER 0x8D97
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glEnablei (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisablei (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedback (void);
+GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp);
+GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRender (void);
+GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
+GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmap (GLenum target);
+GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void *APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glBindVertexArray (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
+#endif
+#endif /* GL_VERSION_3_0 */
+
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index);
+GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif
+#endif /* GL_VERSION_3_1 */
+
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+typedef struct __GLsync *GLsync;
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glxext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GL_EXT_timer_query extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
+#endif
+#endif
+typedef uint64_t GLuint64;
+typedef int64_t GLint64;
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+GLAPI void APIENTRY glProvokingVertex (GLenum mode);
+GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GLAPI GLboolean APIENTRY glIsSync (GLsync sync);
+GLAPI void APIENTRY glDeleteSync (GLsync sync);
+GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+#endif
+#endif /* GL_VERSION_3_2 */
+
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_SRC1_COLOR 0x88F9
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+#define GL_INT_2_10_10_10_REV 0x8D9F
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler);
+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target);
+GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params);
+GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color);
+#endif
+#endif /* GL_VERSION_3_3 */
+
+#ifndef GL_VERSION_4_0
+#define GL_VERSION_4_0 1
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define GL_PATCHES 0x000E
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_ISOLINES 0x8E7A
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params);
+typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices);
+typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values);
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShading (GLfloat value);
+GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x);
+GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params);
+GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices);
+GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params);
+GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values);
+GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedback (void);
+GLAPI void APIENTRY glResumeTransformFeedback (void);
+GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id);
+GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream);
+GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id);
+GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif
+#endif /* GL_VERSION_4_0 */
+
+#ifndef GL_VERSION_4_1
+#define GL_VERSION_4_1 1
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_RGB565 0x8D62
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f);
+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReleaseShaderCompiler (void);
+GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GLAPI void APIENTRY glClearDepthf (GLfloat d);
+GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0);
+GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v);
+GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f);
+GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data);
+#endif
+#endif /* GL_VERSION_4_1 */
+
+#ifndef GL_VERSION_4_2
+#define GL_VERSION_4_2 1
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers);
+GLAPI void APIENTRY glTexStorage1D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount);
+GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#endif
+#endif /* GL_VERSION_4_2 */
+
+#ifndef GL_VERSION_4_3
+#define GL_VERSION_4_3 1
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_MAX_WIDTH 0x827E
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_MIPMAP 0x8293
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_COLOR_ENCODING 0x8296
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_FILTER 0x829A
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_DISPLAY_LIST 0x82E7
+typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level);
+GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer);
+GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GLAPI void APIENTRY glPopDebugGroup (void);
+GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_VERSION_4_3 */
+
+#ifndef GL_VERSION_4_4
+#define GL_VERSION_4_4 1
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define GL_MAP_PERSISTENT_BIT 0x0040
+#define GL_MAP_COHERENT_BIT 0x0080
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+#define GL_CLEAR_TEXTURE 0x9365
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferStorage (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glClearTexImage (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glBindBuffersBase (GLenum target, GLuint first, GLsizei count, const GLuint *buffers);
+GLAPI void APIENTRY glBindBuffersRange (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+GLAPI void APIENTRY glBindTextures (GLuint first, GLsizei count, const GLuint *textures);
+GLAPI void APIENTRY glBindSamplers (GLuint first, GLsizei count, const GLuint *samplers);
+GLAPI void APIENTRY glBindImageTextures (GLuint first, GLsizei count, const GLuint *textures);
+GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+#endif
+#endif /* GL_VERSION_4_4 */
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_ARB_ES2_compatibility 1
+#endif /* GL_ARB_ES2_compatibility */
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_ARB_ES3_compatibility 1
+#endif /* GL_ARB_ES3_compatibility */
+
+#ifndef GL_ARB_arrays_of_arrays
+#define GL_ARB_arrays_of_arrays 1
+#endif /* GL_ARB_arrays_of_arrays */
+
+#ifndef GL_ARB_base_instance
+#define GL_ARB_base_instance 1
+#endif /* GL_ARB_base_instance */
+
+#ifndef GL_ARB_bindless_texture
+#define GL_ARB_bindless_texture 1
+typedef uint64_t GLuint64EXT;
+#define GL_UNSIGNED_INT64_ARB 0x140F
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleARB (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleARB (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentARB (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleARB (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentARB (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64ARB (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64ARB (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentARB (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glVertexAttribL1ui64ARB (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL1ui64vARB (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLui64vARB (GLuint index, GLenum pname, GLuint64EXT *params);
+#endif
+#endif /* GL_ARB_bindless_texture */
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_ARB_blend_func_extended 1
+#endif /* GL_ARB_blend_func_extended */
+
+#ifndef GL_ARB_buffer_storage
+#define GL_ARB_buffer_storage 1
+#endif /* GL_ARB_buffer_storage */
+
+#ifndef GL_ARB_cl_event
+#define GL_ARB_cl_event 1
+struct _cl_context;
+struct _cl_event;
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context *context, struct _cl_event *event, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context *context, struct _cl_event *event, GLbitfield flags);
+#endif
+#endif /* GL_ARB_cl_event */
+
+#ifndef GL_ARB_clear_buffer_object
+#define GL_ARB_clear_buffer_object 1
+#endif /* GL_ARB_clear_buffer_object */
+
+#ifndef GL_ARB_clear_texture
+#define GL_ARB_clear_texture 1
+#endif /* GL_ARB_clear_texture */
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp);
+#endif
+#endif /* GL_ARB_color_buffer_float */
+
+#ifndef GL_ARB_compatibility
+#define GL_ARB_compatibility 1
+#endif /* GL_ARB_compatibility */
+
+#ifndef GL_ARB_compressed_texture_pixel_storage
+#define GL_ARB_compressed_texture_pixel_storage 1
+#endif /* GL_ARB_compressed_texture_pixel_storage */
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#endif /* GL_ARB_compute_shader */
+
+#ifndef GL_ARB_compute_variable_group_size
+#define GL_ARB_compute_variable_group_size 1
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344
+#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345
+#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDispatchComputeGroupSizeARB (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+#endif
+#endif /* GL_ARB_compute_variable_group_size */
+
+#ifndef GL_ARB_conservative_depth
+#define GL_ARB_conservative_depth 1
+#endif /* GL_ARB_conservative_depth */
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#endif /* GL_ARB_copy_buffer */
+
+#ifndef GL_ARB_copy_image
+#define GL_ARB_copy_image 1
+#endif /* GL_ARB_copy_image */
+
+#ifndef GL_ARB_debug_output
+#define GL_ARB_debug_output 1
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif
+#endif /* GL_ARB_debug_output */
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_ARB_depth_buffer_float 1
+#endif /* GL_ARB_depth_buffer_float */
+
+#ifndef GL_ARB_depth_clamp
+#define GL_ARB_depth_clamp 1
+#endif /* GL_ARB_depth_clamp */
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#endif /* GL_ARB_depth_texture */
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersARB (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_ARB_draw_buffers */
+
+#ifndef GL_ARB_draw_buffers_blend
+#define GL_ARB_draw_buffers_blend 1
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+#endif /* GL_ARB_draw_buffers_blend */
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#define GL_ARB_draw_elements_base_vertex 1
+#endif /* GL_ARB_draw_elements_base_vertex */
+
+#ifndef GL_ARB_draw_indirect
+#define GL_ARB_draw_indirect 1
+#endif /* GL_ARB_draw_indirect */
+
+#ifndef GL_ARB_draw_instanced
+#define GL_ARB_draw_instanced 1
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_ARB_draw_instanced */
+
+#ifndef GL_ARB_enhanced_layouts
+#define GL_ARB_enhanced_layouts 1
+#endif /* GL_ARB_enhanced_layouts */
+
+#ifndef GL_ARB_explicit_attrib_location
+#define GL_ARB_explicit_attrib_location 1
+#endif /* GL_ARB_explicit_attrib_location */
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_ARB_explicit_uniform_location 1
+#endif /* GL_ARB_explicit_uniform_location */
+
+#ifndef GL_ARB_fragment_coord_conventions
+#define GL_ARB_fragment_coord_conventions 1
+#endif /* GL_ARB_fragment_coord_conventions */
+
+#ifndef GL_ARB_fragment_layer_viewport
+#define GL_ARB_fragment_layer_viewport 1
+#endif /* GL_ARB_fragment_layer_viewport */
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string);
+typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramStringARB (GLenum target, GLenum format, GLsizei len, const void *string);
+GLAPI void APIENTRY glBindProgramARB (GLenum target, GLuint program);
+GLAPI void APIENTRY glDeleteProgramsARB (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glGenProgramsARB (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringARB (GLenum target, GLenum pname, void *string);
+GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
+#endif
+#endif /* GL_ARB_fragment_program */
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+#endif /* GL_ARB_fragment_program_shadow */
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif /* GL_ARB_fragment_shader */
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_ARB_framebuffer_no_attachments 1
+#endif /* GL_ARB_framebuffer_no_attachments */
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_ARB_framebuffer_object 1
+#endif /* GL_ARB_framebuffer_object */
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_ARB_framebuffer_sRGB 1
+#endif /* GL_ARB_framebuffer_sRGB */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+#endif /* GL_KHR_context_flush_control */
+
+#ifndef GL_ARB_geometry_shader4
+#define GL_ARB_geometry_shader4 1
+#define GL_LINES_ADJACENCY_ARB 0x000A
+#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
+#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+#endif /* GL_ARB_geometry_shader4 */
+
+#ifndef GL_ARB_get_program_binary
+#define GL_ARB_get_program_binary 1
+#endif /* GL_ARB_get_program_binary */
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_ARB_gpu_shader5 1
+#endif /* GL_ARB_gpu_shader5 */
+
+#ifndef GL_ARB_gpu_shader_fp64
+#define GL_ARB_gpu_shader_fp64 1
+#endif /* GL_ARB_gpu_shader_fp64 */
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+typedef unsigned short GLhalfARB;
+#define GL_HALF_FLOAT_ARB 0x140B
+#endif /* GL_ARB_half_float_pixel */
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_ARB_half_float_vertex 1
+#endif /* GL_ARB_half_float_vertex */
+
+#ifndef GL_ARB_imaging
+#define GL_ARB_imaging 1
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_EQUATION 0x8009
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, void *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTable (GLenum target, GLenum format, GLenum type, void *table);
+GLAPI void APIENTRY glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteri (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, void *image);
+GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilter (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+GLAPI void APIENTRY glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+GLAPI void APIENTRY glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmax (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogram (GLenum target);
+GLAPI void APIENTRY glResetMinmax (GLenum target);
+#endif
+#endif /* GL_ARB_imaging */
+
+#ifndef GL_ARB_indirect_parameters
+#define GL_ARB_indirect_parameters 1
+#define GL_PARAMETER_BUFFER_ARB 0x80EE
+#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#endif
+#endif /* GL_ARB_indirect_parameters */
+
+#ifndef GL_ARB_instanced_arrays
+#define GL_ARB_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_ARB_instanced_arrays */
+
+#ifndef GL_ARB_internalformat_query
+#define GL_ARB_internalformat_query 1
+#endif /* GL_ARB_internalformat_query */
+
+#ifndef GL_ARB_internalformat_query2
+#define GL_ARB_internalformat_query2 1
+#define GL_SRGB_DECODE_ARB 0x8299
+#endif /* GL_ARB_internalformat_query2 */
+
+#ifndef GL_ARB_invalidate_subdata
+#define GL_ARB_invalidate_subdata 1
+#endif /* GL_ARB_invalidate_subdata */
+
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_ARB_map_buffer_alignment 1
+#endif /* GL_ARB_map_buffer_alignment */
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+#endif /* GL_ARB_map_buffer_range */
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint index);
+GLAPI void APIENTRY glMatrixIndexubvARB (GLint size, const GLubyte *indices);
+GLAPI void APIENTRY glMatrixIndexusvARB (GLint size, const GLushort *indices);
+GLAPI void APIENTRY glMatrixIndexuivARB (GLint size, const GLuint *indices);
+GLAPI void APIENTRY glMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_ARB_matrix_palette */
+
+#ifndef GL_ARB_multi_bind
+#define GL_ARB_multi_bind 1
+#endif /* GL_ARB_multi_bind */
+
+#ifndef GL_ARB_multi_draw_indirect
+#define GL_ARB_multi_draw_indirect 1
+#endif /* GL_ARB_multi_draw_indirect */
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLfloat value, GLboolean invert);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleCoverageARB (GLfloat value, GLboolean invert);
+#endif
+#endif /* GL_ARB_multisample */
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glClientActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum target, const GLshort *v);
+#endif
+#endif /* GL_ARB_multitexture */
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueriesARB (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueriesARB (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQueryARB (GLuint id);
+GLAPI void APIENTRY glBeginQueryARB (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQueryARB (GLenum target);
+GLAPI void APIENTRY glGetQueryivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_ARB_occlusion_query */
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ARB_occlusion_query2 1
+#endif /* GL_ARB_occlusion_query2 */
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#endif /* GL_ARB_pixel_buffer_object */
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfARB (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_ARB_point_parameters */
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+#endif /* GL_ARB_point_sprite */
+
+#ifndef GL_ARB_program_interface_query
+#define GL_ARB_program_interface_query 1
+#endif /* GL_ARB_program_interface_query */
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_ARB_provoking_vertex 1
+#endif /* GL_ARB_provoking_vertex */
+
+#ifndef GL_ARB_query_buffer_object
+#define GL_ARB_query_buffer_object 1
+#endif /* GL_ARB_query_buffer_object */
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#define GL_ARB_robust_buffer_access_behavior 1
+#endif /* GL_ARB_robust_buffer_access_behavior */
+
+#ifndef GL_ARB_robustness
+#define GL_ARB_robustness 1
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img);
+typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void *img);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+typedef void (APIENTRYP PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values);
+typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern);
+typedef void (APIENTRYP PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+typedef void (APIENTRYP PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void);
+GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img);
+GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, void *img);
+GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+GLAPI void APIENTRY glGetnMapdvARB (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+GLAPI void APIENTRY glGetnMapfvARB (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+GLAPI void APIENTRY glGetnMapivARB (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+GLAPI void APIENTRY glGetnPixelMapfvARB (GLenum map, GLsizei bufSize, GLfloat *values);
+GLAPI void APIENTRY glGetnPixelMapuivARB (GLenum map, GLsizei bufSize, GLuint *values);
+GLAPI void APIENTRY glGetnPixelMapusvARB (GLenum map, GLsizei bufSize, GLushort *values);
+GLAPI void APIENTRY glGetnPolygonStippleARB (GLsizei bufSize, GLubyte *pattern);
+GLAPI void APIENTRY glGetnColorTableARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+GLAPI void APIENTRY glGetnConvolutionFilterARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+GLAPI void APIENTRY glGetnSeparableFilterARB (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+GLAPI void APIENTRY glGetnHistogramARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+#endif
+#endif /* GL_ARB_robustness */
+
+#ifndef GL_ARB_robustness_isolation
+#define GL_ARB_robustness_isolation 1
+#endif /* GL_ARB_robustness_isolation */
+
+#ifndef GL_ARB_sample_shading
+#define GL_ARB_sample_shading 1
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
+#endif
+#endif /* GL_ARB_sample_shading */
+
+#ifndef GL_ARB_sampler_objects
+#define GL_ARB_sampler_objects 1
+#endif /* GL_ARB_sampler_objects */
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_ARB_seamless_cube_map 1
+#endif /* GL_ARB_seamless_cube_map */
+
+#ifndef GL_ARB_seamless_cubemap_per_texture
+#define GL_ARB_seamless_cubemap_per_texture 1
+#endif /* GL_ARB_seamless_cubemap_per_texture */
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_ARB_separate_shader_objects 1
+#endif /* GL_ARB_separate_shader_objects */
+
+#ifndef GL_ARB_shader_atomic_counters
+#define GL_ARB_shader_atomic_counters 1
+#endif /* GL_ARB_shader_atomic_counters */
+
+#ifndef GL_ARB_shader_bit_encoding
+#define GL_ARB_shader_bit_encoding 1
+#endif /* GL_ARB_shader_bit_encoding */
+
+#ifndef GL_ARB_shader_draw_parameters
+#define GL_ARB_shader_draw_parameters 1
+#endif /* GL_ARB_shader_draw_parameters */
+
+#ifndef GL_ARB_shader_group_vote
+#define GL_ARB_shader_group_vote 1
+#endif /* GL_ARB_shader_group_vote */
+
+#ifndef GL_ARB_shader_image_load_store
+#define GL_ARB_shader_image_load_store 1
+#endif /* GL_ARB_shader_image_load_store */
+
+#ifndef GL_ARB_shader_image_size
+#define GL_ARB_shader_image_size 1
+#endif /* GL_ARB_shader_image_size */
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef char GLcharARB;
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB obj);
+GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum pname);
+GLAPI void APIENTRY glDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj);
+GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum shaderType);
+GLAPI void APIENTRY glShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length);
+GLAPI void APIENTRY glCompileShaderARB (GLhandleARB shaderObj);
+GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj);
+GLAPI void APIENTRY glLinkProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB programObj);
+GLAPI void APIENTRY glValidateProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUniform1fARB (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2fARB (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1iARB (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2iARB (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params);
+GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+#endif /* GL_ARB_shader_objects */
+
+#ifndef GL_ARB_shader_precision
+#define GL_ARB_shader_precision 1
+#endif /* GL_ARB_shader_precision */
+
+#ifndef GL_ARB_shader_stencil_export
+#define GL_ARB_shader_stencil_export 1
+#endif /* GL_ARB_shader_stencil_export */
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_ARB_shader_storage_buffer_object 1
+#endif /* GL_ARB_shader_storage_buffer_object */
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ARB_shader_subroutine 1
+#endif /* GL_ARB_shader_subroutine */
+
+#ifndef GL_ARB_shader_texture_lod
+#define GL_ARB_shader_texture_lod 1
+#endif /* GL_ARB_shader_texture_lod */
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#endif /* GL_ARB_shading_language_100 */
+
+#ifndef GL_ARB_shading_language_420pack
+#define GL_ARB_shading_language_420pack 1
+#endif /* GL_ARB_shading_language_420pack */
+
+#ifndef GL_ARB_shading_language_include
+#define GL_ARB_shading_language_include 1
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length);
+GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ARB_shading_language_include */
+
+#ifndef GL_ARB_shading_language_packing
+#define GL_ARB_shading_language_packing 1
+#endif /* GL_ARB_shading_language_packing */
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+#endif /* GL_ARB_shadow */
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#endif /* GL_ARB_shadow_ambient */
+
+#ifndef GL_ARB_sparse_texture
+#define GL_ARB_sparse_texture 1
+#define GL_TEXTURE_SPARSE_ARB 0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7
+#define GL_MIN_SPARSE_LEVEL_ARB 0x919B
+#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
+typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+#endif
+#endif /* GL_ARB_sparse_texture */
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_ARB_stencil_texturing 1
+#endif /* GL_ARB_stencil_texturing */
+
+#ifndef GL_ARB_sync
+#define GL_ARB_sync 1
+#endif /* GL_ARB_sync */
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_ARB_tessellation_shader 1
+#endif /* GL_ARB_tessellation_shader */
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+#endif /* GL_ARB_texture_border_clamp */
+
+#ifndef GL_ARB_texture_buffer_object
+#define GL_ARB_texture_buffer_object 1
+#define GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+#endif /* GL_ARB_texture_buffer_object */
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+#define GL_ARB_texture_buffer_object_rgb32 1
+#endif /* GL_ARB_texture_buffer_object_rgb32 */
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_ARB_texture_buffer_range 1
+#endif /* GL_ARB_texture_buffer_range */
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void *img);
+#endif
+#endif /* GL_ARB_texture_compression */
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_ARB_texture_compression_bptc 1
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+#endif /* GL_ARB_texture_compression_bptc */
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc 1
+#endif /* GL_ARB_texture_compression_rgtc */
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#endif /* GL_ARB_texture_cube_map */
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_ARB_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#endif /* GL_ARB_texture_cube_map_array */
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif /* GL_ARB_texture_env_add */
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#endif /* GL_ARB_texture_env_combine */
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+#endif /* GL_ARB_texture_env_crossbar */
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+#endif /* GL_ARB_texture_env_dot3 */
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#endif /* GL_ARB_texture_float */
+
+#ifndef GL_ARB_texture_gather
+#define GL_ARB_texture_gather 1
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+#endif /* GL_ARB_texture_gather */
+
+#ifndef GL_ARB_texture_mirror_clamp_to_edge
+#define GL_ARB_texture_mirror_clamp_to_edge 1
+#endif /* GL_ARB_texture_mirror_clamp_to_edge */
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+#ifndef GL_ARB_texture_multisample
+#define GL_ARB_texture_multisample 1
+#endif /* GL_ARB_texture_multisample */
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+#endif /* GL_ARB_texture_non_power_of_two */
+
+#ifndef GL_ARB_texture_query_levels
+#define GL_ARB_texture_query_levels 1
+#endif /* GL_ARB_texture_query_levels */
+
+#ifndef GL_ARB_texture_query_lod
+#define GL_ARB_texture_query_lod 1
+#endif /* GL_ARB_texture_query_lod */
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif /* GL_ARB_texture_rectangle */
+
+#ifndef GL_ARB_texture_rg
+#define GL_ARB_texture_rg 1
+#endif /* GL_ARB_texture_rg */
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_ARB_texture_rgb10_a2ui 1
+#endif /* GL_ARB_texture_rgb10_a2ui */
+
+#ifndef GL_ARB_texture_stencil8
+#define GL_ARB_texture_stencil8 1
+#endif /* GL_ARB_texture_stencil8 */
+
+#ifndef GL_ARB_texture_storage
+#define GL_ARB_texture_storage 1
+#endif /* GL_ARB_texture_storage */
+
+#ifndef GL_ARB_texture_storage_multisample
+#define GL_ARB_texture_storage_multisample 1
+#endif /* GL_ARB_texture_storage_multisample */
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_ARB_texture_swizzle 1
+#endif /* GL_ARB_texture_swizzle */
+
+#ifndef GL_ARB_texture_view
+#define GL_ARB_texture_view 1
+#endif /* GL_ARB_texture_view */
+
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+#endif /* GL_ARB_timer_query */
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_ARB_transform_feedback2 1
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#endif /* GL_ARB_transform_feedback2 */
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_ARB_transform_feedback3 1
+#endif /* GL_ARB_transform_feedback3 */
+
+#ifndef GL_ARB_transform_feedback_instanced
+#define GL_ARB_transform_feedback_instanced 1
+#endif /* GL_ARB_transform_feedback_instanced */
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m);
+#endif
+#endif /* GL_ARB_transpose_matrix */
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_ARB_uniform_buffer_object 1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#endif /* GL_ARB_uniform_buffer_object */
+
+#ifndef GL_ARB_vertex_array_bgra
+#define GL_ARB_vertex_array_bgra 1
+#endif /* GL_ARB_vertex_array_bgra */
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_ARB_vertex_array_object 1
+#endif /* GL_ARB_vertex_array_object */
+
+#ifndef GL_ARB_vertex_attrib_64bit
+#define GL_ARB_vertex_attrib_64bit 1
+#endif /* GL_ARB_vertex_attrib_64bit */
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_ARB_vertex_attrib_binding 1
+#endif /* GL_ARB_vertex_attrib_binding */
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWeightbvARB (GLint size, const GLbyte *weights);
+GLAPI void APIENTRY glWeightsvARB (GLint size, const GLshort *weights);
+GLAPI void APIENTRY glWeightivARB (GLint size, const GLint *weights);
+GLAPI void APIENTRY glWeightfvARB (GLint size, const GLfloat *weights);
+GLAPI void APIENTRY glWeightdvARB (GLint size, const GLdouble *weights);
+GLAPI void APIENTRY glWeightubvARB (GLint size, const GLubyte *weights);
+GLAPI void APIENTRY glWeightusvARB (GLint size, const GLushort *weights);
+GLAPI void APIENTRY glWeightuivARB (GLint size, const GLuint *weights);
+GLAPI void APIENTRY glWeightPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glVertexBlendARB (GLint count);
+#endif
+#endif /* GL_ARB_vertex_blend */
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+#ifdef __MACOSX__ /* The OS X headers haven't caught up with Khronos yet */
+typedef long GLsizeiptrARB;
+typedef long GLintptrARB;
+#else
+typedef ptrdiff_t GLsizeiptrARB;
+typedef ptrdiff_t GLintptrARB;
+#endif
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data);
+typedef void *(APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBufferARB (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffersARB (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffersARB (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBufferARB (GLuint buffer);
+GLAPI void APIENTRY glBufferDataARB (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data);
+GLAPI void APIENTRY glGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data);
+GLAPI void *APIENTRY glMapBufferARB (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum target);
+GLAPI void APIENTRY glGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointervARB (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_ARB_vertex_buffer_object */
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttrib1dARB (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fARB (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sARB (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sARB (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint index, GLenum pname, void **pointer);
+#endif
+#endif /* GL_ARB_vertex_program */
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name);
+#endif
+#endif /* GL_ARB_vertex_shader */
+
+#ifndef GL_ARB_vertex_type_10f_11f_11f_rev
+#define GL_ARB_vertex_type_10f_11f_11f_rev 1
+#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+#endif /* GL_ARB_vertex_type_2_10_10_10_rev */
+
+#ifndef GL_ARB_viewport_array
+#define GL_ARB_viewport_array 1
+#endif /* GL_ARB_viewport_array */
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dARB (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fARB (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iARB (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sARB (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svARB (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iARB (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sARB (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v);
+#endif
+#endif /* GL_ARB_window_pos */
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#endif /* GL_KHR_debug */
+
+#ifndef GL_KHR_texture_compression_astc_hdr
+#define GL_KHR_texture_compression_astc_hdr 1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif /* GL_KHR_texture_compression_astc_hdr */
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
+#ifndef GL_OES_byte_coordinates
+#define GL_OES_byte_coordinates 1
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2BOESPROC) (GLenum texture, GLbyte s, GLbyte t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD1BOESPROC) (GLbyte s);
+typedef void (APIENTRYP PFNGLTEXCOORD1BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD2BOESPROC) (GLbyte s, GLbyte t);
+typedef void (APIENTRYP PFNGLTEXCOORD2BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD3BOESPROC) (GLbyte s, GLbyte t, GLbyte r);
+typedef void (APIENTRYP PFNGLTEXCOORD3BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD4BOESPROC) (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+typedef void (APIENTRYP PFNGLTEXCOORD4BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX2BOESPROC) (GLbyte x);
+typedef void (APIENTRYP PFNGLVERTEX2BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX3BOESPROC) (GLbyte x, GLbyte y);
+typedef void (APIENTRYP PFNGLVERTEX3BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z);
+typedef void (APIENTRYP PFNGLVERTEX4BVOESPROC) (const GLbyte *coords);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiTexCoord1bOES (GLenum texture, GLbyte s);
+GLAPI void APIENTRY glMultiTexCoord1bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord2bOES (GLenum texture, GLbyte s, GLbyte t);
+GLAPI void APIENTRY glMultiTexCoord2bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord3bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r);
+GLAPI void APIENTRY glMultiTexCoord3bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord4bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+GLAPI void APIENTRY glMultiTexCoord4bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord1bOES (GLbyte s);
+GLAPI void APIENTRY glTexCoord1bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord2bOES (GLbyte s, GLbyte t);
+GLAPI void APIENTRY glTexCoord2bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord3bOES (GLbyte s, GLbyte t, GLbyte r);
+GLAPI void APIENTRY glTexCoord3bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord4bOES (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+GLAPI void APIENTRY glTexCoord4bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex2bOES (GLbyte x);
+GLAPI void APIENTRY glVertex2bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex3bOES (GLbyte x, GLbyte y);
+GLAPI void APIENTRY glVertex3bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex4bOES (GLbyte x, GLbyte y, GLbyte z);
+GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords);
+#endif
+#endif /* GL_OES_byte_coordinates */
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifndef GL_OES_fixed_point
+#define GL_OES_fixed_point 1
+typedef GLint GLfixed;
+#define GL_FIXED_OES 0x140C
+typedef void (APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref);
+typedef void (APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLfixed depth);
+typedef void (APIENTRYP PFNGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation);
+typedef void (APIENTRYP PFNGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLFOGXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum plane, GLfixed *equation);
+typedef void (APIENTRYP PFNGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLLINEWIDTHXOESPROC) (GLfixed width);
+typedef void (APIENTRYP PFNGLLOADMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLMULTMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (APIENTRYP PFNGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (APIENTRYP PFNGLORTHOXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size);
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units);
+typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLACCUMXOESPROC) (GLenum op, GLfixed value);
+typedef void (APIENTRYP PFNGLBITMAPXOESPROC) (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap);
+typedef void (APIENTRYP PFNGLBLENDCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCLEARACCUMXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCOLOR3XOESPROC) (GLfixed red, GLfixed green, GLfixed blue);
+typedef void (APIENTRYP PFNGLCOLOR3XVOESPROC) (const GLfixed *components);
+typedef void (APIENTRYP PFNGLCOLOR4XVOESPROC) (const GLfixed *components);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLEVALCOORD1XOESPROC) (GLfixed u);
+typedef void (APIENTRYP PFNGLEVALCOORD1XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLEVALCOORD2XOESPROC) (GLfixed u, GLfixed v);
+typedef void (APIENTRYP PFNGLEVALCOORD2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLFEEDBACKBUFFERXOESPROC) (GLsizei n, GLenum type, const GLfixed *buffer);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETMAPXVOESPROC) (GLenum target, GLenum query, GLfixed *v);
+typedef void (APIENTRYP PFNGLGETMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLGETPIXELMAPXVPROC) (GLenum map, GLint size, GLfixed *values);
+typedef void (APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERXVOESPROC) (GLenum target, GLint level, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLINDEXXOESPROC) (GLfixed component);
+typedef void (APIENTRYP PFNGLINDEXXVOESPROC) (const GLfixed *component);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMAP1XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+typedef void (APIENTRYP PFNGLMAP2XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+typedef void (APIENTRYP PFNGLMAPGRID1XOESPROC) (GLint n, GLfixed u1, GLfixed u2);
+typedef void (APIENTRYP PFNGLMAPGRID2XOESPROC) (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1XOESPROC) (GLenum texture, GLfixed s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2XOESPROC) (GLenum texture, GLfixed s, GLfixed t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLNORMAL3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLPASSTHROUGHXOESPROC) (GLfixed token);
+typedef void (APIENTRYP PFNGLPIXELMAPXPROC) (GLenum map, GLint size, const GLfixed *values);
+typedef void (APIENTRYP PFNGLPIXELSTOREXPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFERXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLPIXELZOOMXOESPROC) (GLfixed xfactor, GLfixed yfactor);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESXOESPROC) (GLsizei n, const GLuint *textures, const GLfixed *priorities);
+typedef void (APIENTRYP PFNGLRASTERPOS2XOESPROC) (GLfixed x, GLfixed y);
+typedef void (APIENTRYP PFNGLRASTERPOS2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRASTERPOS3XOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLRASTERPOS3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRASTERPOS4XOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+typedef void (APIENTRYP PFNGLRASTERPOS4XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRECTXOESPROC) (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+typedef void (APIENTRYP PFNGLRECTXVOESPROC) (const GLfixed *v1, const GLfixed *v2);
+typedef void (APIENTRYP PFNGLTEXCOORD1XOESPROC) (GLfixed s);
+typedef void (APIENTRYP PFNGLTEXCOORD1XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD2XOESPROC) (GLfixed s, GLfixed t);
+typedef void (APIENTRYP PFNGLTEXCOORD2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD3XOESPROC) (GLfixed s, GLfixed t, GLfixed r);
+typedef void (APIENTRYP PFNGLTEXCOORD3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD4XOESPROC) (GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (APIENTRYP PFNGLTEXCOORD4XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLVERTEX2XOESPROC) (GLfixed x);
+typedef void (APIENTRYP PFNGLVERTEX2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLVERTEX3XOESPROC) (GLfixed x, GLfixed y);
+typedef void (APIENTRYP PFNGLVERTEX3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLVERTEX4XOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLVERTEX4XVOESPROC) (const GLfixed *coords);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAlphaFuncxOES (GLenum func, GLfixed ref);
+GLAPI void APIENTRY glClearColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glClearDepthxOES (GLfixed depth);
+GLAPI void APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation);
+GLAPI void APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glDepthRangexOES (GLfixed n, GLfixed f);
+GLAPI void APIENTRY glFogxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glFogxvOES (GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glFrustumxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GLAPI void APIENTRY glGetClipPlanexOES (GLenum plane, GLfixed *equation);
+GLAPI void APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexEnvxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glLightModelxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glLineWidthxOES (GLfixed width);
+GLAPI void APIENTRY glLoadMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glMultMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMultiTexCoord4xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GLAPI void APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz);
+GLAPI void APIENTRY glOrthoxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glPointSizexOES (GLfixed size);
+GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
+GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert);
+GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glAccumxOES (GLenum op, GLfixed value);
+GLAPI void APIENTRY glBitmapxOES (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap);
+GLAPI void APIENTRY glBlendColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glClearAccumxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glColor3xOES (GLfixed red, GLfixed green, GLfixed blue);
+GLAPI void APIENTRY glColor3xvOES (const GLfixed *components);
+GLAPI void APIENTRY glColor4xvOES (const GLfixed *components);
+GLAPI void APIENTRY glConvolutionParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glConvolutionParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glEvalCoord1xOES (GLfixed u);
+GLAPI void APIENTRY glEvalCoord1xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glEvalCoord2xOES (GLfixed u, GLfixed v);
+GLAPI void APIENTRY glEvalCoord2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glFeedbackBufferxOES (GLsizei n, GLenum type, const GLfixed *buffer);
+GLAPI void APIENTRY glGetConvolutionParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetHistogramParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetLightxOES (GLenum light, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetMapxvOES (GLenum target, GLenum query, GLfixed *v);
+GLAPI void APIENTRY glGetMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glGetPixelMapxv (GLenum map, GLint size, GLfixed *values);
+GLAPI void APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexLevelParameterxvOES (GLenum target, GLint level, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glIndexxOES (GLfixed component);
+GLAPI void APIENTRY glIndexxvOES (const GLfixed *component);
+GLAPI void APIENTRY glLoadTransposeMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMap1xOES (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+GLAPI void APIENTRY glMap2xOES (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+GLAPI void APIENTRY glMapGrid1xOES (GLint n, GLfixed u1, GLfixed u2);
+GLAPI void APIENTRY glMapGrid2xOES (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+GLAPI void APIENTRY glMultTransposeMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMultiTexCoord1xOES (GLenum texture, GLfixed s);
+GLAPI void APIENTRY glMultiTexCoord1xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord2xOES (GLenum texture, GLfixed s, GLfixed t);
+GLAPI void APIENTRY glMultiTexCoord2xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord3xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+GLAPI void APIENTRY glMultiTexCoord3xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord4xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glNormal3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glPassThroughxOES (GLfixed token);
+GLAPI void APIENTRY glPixelMapx (GLenum map, GLint size, const GLfixed *values);
+GLAPI void APIENTRY glPixelStorex (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glPixelTransferxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glPixelZoomxOES (GLfixed xfactor, GLfixed yfactor);
+GLAPI void APIENTRY glPrioritizeTexturesxOES (GLsizei n, const GLuint *textures, const GLfixed *priorities);
+GLAPI void APIENTRY glRasterPos2xOES (GLfixed x, GLfixed y);
+GLAPI void APIENTRY glRasterPos2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRasterPos3xOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glRasterPos3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRasterPos4xOES (GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+GLAPI void APIENTRY glRasterPos4xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRectxOES (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+GLAPI void APIENTRY glRectxvOES (const GLfixed *v1, const GLfixed *v2);
+GLAPI void APIENTRY glTexCoord1xOES (GLfixed s);
+GLAPI void APIENTRY glTexCoord1xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord2xOES (GLfixed s, GLfixed t);
+GLAPI void APIENTRY glTexCoord2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord3xOES (GLfixed s, GLfixed t, GLfixed r);
+GLAPI void APIENTRY glTexCoord3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord4xOES (GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GLAPI void APIENTRY glTexCoord4xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glVertex2xOES (GLfixed x);
+GLAPI void APIENTRY glVertex2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glVertex3xOES (GLfixed x, GLfixed y);
+GLAPI void APIENTRY glVertex3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glVertex4xOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glVertex4xvOES (const GLfixed *coords);
+#endif
+#endif /* GL_OES_fixed_point */
+
+#ifndef GL_OES_query_matrix
+#define GL_OES_query_matrix 1
+typedef GLbitfield (APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed *mantissa, GLint *exponent);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLbitfield APIENTRY glQueryMatrixxOES (GLfixed *mantissa, GLint *exponent);
+#endif
+#endif /* GL_OES_query_matrix */
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif /* GL_OES_read_format */
+
+#ifndef GL_OES_single_precision
+#define GL_OES_single_precision 1
+typedef void (APIENTRYP PFNGLCLEARDEPTHFOESPROC) (GLclampf depth);
+typedef void (APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat *equation);
+typedef void (APIENTRYP PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearDepthfOES (GLclampf depth);
+GLAPI void APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation);
+GLAPI void APIENTRY glDepthRangefOES (GLclampf n, GLclampf f);
+GLAPI void APIENTRY glFrustumfOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+GLAPI void APIENTRY glGetClipPlanefOES (GLenum plane, GLfloat *equation);
+GLAPI void APIENTRY glOrthofOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#endif
+#endif /* GL_OES_single_precision */
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+#endif /* GL_3DFX_multisample */
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTbufferMask3DFX (GLuint mask);
+#endif
+#endif /* GL_3DFX_tbuffer */
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+#ifndef GL_AMD_blend_minmax_factor
+#define GL_AMD_blend_minmax_factor 1
+#define GL_FACTOR_MIN_AMD 0x901C
+#define GL_FACTOR_MAX_AMD 0x901D
+#endif /* GL_AMD_blend_minmax_factor */
+
+#ifndef GL_AMD_conservative_depth
+#define GL_AMD_conservative_depth 1
+#endif /* GL_AMD_conservative_depth */
+
+#ifndef GL_AMD_debug_output
+#define GL_AMD_debug_output 1
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#endif
+#endif /* GL_AMD_debug_output */
+
+#ifndef GL_AMD_depth_clamp_separate
+#define GL_AMD_depth_clamp_separate 1
+#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E
+#define GL_DEPTH_CLAMP_FAR_AMD 0x901F
+#endif /* GL_AMD_depth_clamp_separate */
+
+#ifndef GL_AMD_draw_buffers_blend
+#define GL_AMD_draw_buffers_blend 1
+typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#endif
+#endif /* GL_AMD_draw_buffers_blend */
+
+#ifndef GL_AMD_gcn_shader
+#define GL_AMD_gcn_shader 1
+#endif /* GL_AMD_gcn_shader */
+
+#ifndef GL_AMD_gpu_shader_int64
+#define GL_AMD_gpu_shader_int64 1
+typedef int64_t GLint64EXT;
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params);
+GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_AMD_gpu_shader_int64 */
+
+#ifndef GL_AMD_interleaved_elements
+#define GL_AMD_interleaved_elements 1
+#define GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4
+#define GL_VERTEX_ID_SWIZZLE_AMD 0x91A5
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribParameteriAMD (GLuint index, GLenum pname, GLint param);
+#endif
+#endif /* GL_AMD_interleaved_elements */
+
+#ifndef GL_AMD_multi_draw_indirect
+#define GL_AMD_multi_draw_indirect 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectAMD (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride);
+#endif
+#endif /* GL_AMD_multi_draw_indirect */
+
+#ifndef GL_AMD_name_gen_delete
+#define GL_AMD_name_gen_delete 1
+#define GL_DATA_BUFFER_AMD 0x9151
+#define GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define GL_QUERY_OBJECT_AMD 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define GL_SAMPLER_OBJECT_AMD 0x9155
+typedef void (APIENTRYP PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint *names);
+typedef void (APIENTRYP PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint *names);
+typedef GLboolean (APIENTRYP PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenNamesAMD (GLenum identifier, GLuint num, GLuint *names);
+GLAPI void APIENTRY glDeleteNamesAMD (GLenum identifier, GLuint num, const GLuint *names);
+GLAPI GLboolean APIENTRY glIsNameAMD (GLenum identifier, GLuint name);
+#endif
+#endif /* GL_AMD_name_gen_delete */
+
+#ifndef GL_AMD_occlusion_query_event
+#define GL_AMD_occlusion_query_event 1
+#define GL_OCCLUSION_QUERY_EVENT_MASK_AMD 0x874F
+#define GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD 0x00000001
+#define GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD 0x00000002
+#define GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD 0x00000004
+#define GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD 0x00000008
+#define GL_QUERY_ALL_EVENT_BITS_AMD 0xFFFFFFFF
+typedef void (APIENTRYP PFNGLQUERYOBJECTPARAMETERUIAMDPROC) (GLenum target, GLuint id, GLenum pname, GLuint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glQueryObjectParameteruiAMD (GLenum target, GLuint id, GLenum pname, GLuint param);
+#endif
+#endif /* GL_AMD_occlusion_query_event */
+
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+#endif /* GL_AMD_performance_monitor */
+
+#ifndef GL_AMD_pinned_memory
+#define GL_AMD_pinned_memory 1
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+#endif /* GL_AMD_pinned_memory */
+
+#ifndef GL_AMD_query_buffer_object
+#define GL_AMD_query_buffer_object 1
+#define GL_QUERY_BUFFER_AMD 0x9192
+#define GL_QUERY_BUFFER_BINDING_AMD 0x9193
+#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194
+#endif /* GL_AMD_query_buffer_object */
+
+#ifndef GL_AMD_sample_positions
+#define GL_AMD_sample_positions 1
+#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
+typedef void (APIENTRYP PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat *val);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLfloat *val);
+#endif
+#endif /* GL_AMD_sample_positions */
+
+#ifndef GL_AMD_seamless_cubemap_per_texture
+#define GL_AMD_seamless_cubemap_per_texture 1
+#endif /* GL_AMD_seamless_cubemap_per_texture */
+
+#ifndef GL_AMD_shader_atomic_counter_ops
+#define GL_AMD_shader_atomic_counter_ops 1
+#endif /* GL_AMD_shader_atomic_counter_ops */
+
+#ifndef GL_AMD_shader_stencil_export
+#define GL_AMD_shader_stencil_export 1
+#endif /* GL_AMD_shader_stencil_export */
+
+#ifndef GL_AMD_shader_trinary_minmax
+#define GL_AMD_shader_trinary_minmax 1
+#endif /* GL_AMD_shader_trinary_minmax */
+
+#ifndef GL_AMD_sparse_texture
+#define GL_AMD_sparse_texture 1
+#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
+#define GL_MIN_SPARSE_LEVEL_AMD 0x919B
+#define GL_MIN_LOD_WARNING_AMD 0x919C
+#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001
+typedef void (APIENTRYP PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexStorageSparseAMD (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+GLAPI void APIENTRY glTextureStorageSparseAMD (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+#endif
+#endif /* GL_AMD_sparse_texture */
+
+#ifndef GL_AMD_stencil_operation_extended
+#define GL_AMD_stencil_operation_extended 1
+#define GL_SET_AMD 0x874A
+#define GL_REPLACE_VALUE_AMD 0x874B
+#define GL_STENCIL_OP_VALUE_AMD 0x874C
+#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D
+typedef void (APIENTRYP PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value);
+#endif
+#endif /* GL_AMD_stencil_operation_extended */
+
+#ifndef GL_AMD_texture_texture4
+#define GL_AMD_texture_texture4 1
+#endif /* GL_AMD_texture_texture4 */
+
+#ifndef GL_AMD_transform_feedback3_lines_triangles
+#define GL_AMD_transform_feedback3_lines_triangles 1
+#endif /* GL_AMD_transform_feedback3_lines_triangles */
+
+#ifndef GL_AMD_transform_feedback4
+#define GL_AMD_transform_feedback4 1
+#define GL_STREAM_RASTERIZATION_AMD 0x91A0
+#endif /* GL_AMD_transform_feedback4 */
+
+#ifndef GL_AMD_vertex_shader_layer
+#define GL_AMD_vertex_shader_layer 1
+#endif /* GL_AMD_vertex_shader_layer */
+
+#ifndef GL_AMD_vertex_shader_tessellator
+#define GL_AMD_vertex_shader_tessellator 1
+#define GL_SAMPLER_BUFFER_AMD 0x9001
+#define GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define GL_TESSELLATION_MODE_AMD 0x9004
+#define GL_TESSELLATION_FACTOR_AMD 0x9005
+#define GL_DISCRETE_AMD 0x9006
+#define GL_CONTINUOUS_AMD 0x9007
+typedef void (APIENTRYP PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTessellationFactorAMD (GLfloat factor);
+GLAPI void APIENTRY glTessellationModeAMD (GLenum mode);
+#endif
+#endif /* GL_AMD_vertex_shader_tessellator */
+
+#ifndef GL_AMD_vertex_shader_viewport_index
+#define GL_AMD_vertex_shader_viewport_index 1
+#endif /* GL_AMD_vertex_shader_viewport_index */
+
+#ifndef GL_APPLE_aux_depth_stencil
+#define GL_APPLE_aux_depth_stencil 1
+#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+#endif /* GL_APPLE_aux_depth_stencil */
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+#endif /* GL_APPLE_client_storage */
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+#define GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerAPPLE (GLenum type, const void *pointer);
+GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+#endif /* GL_APPLE_element_array */
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);
+typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenFencesAPPLE (GLsizei n, GLuint *fences);
+GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glSetFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint fence);
+GLAPI void APIENTRY glFinishFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum object, GLuint name);
+GLAPI void APIENTRY glFinishObjectAPPLE (GLenum object, GLint name);
+#endif
+#endif /* GL_APPLE_fence */
+
+#ifndef GL_APPLE_float_pixels
+#define GL_APPLE_float_pixels 1
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+#endif /* GL_APPLE_float_pixels */
+
+#ifndef GL_APPLE_flush_buffer_range
+#define GL_APPLE_flush_buffer_range 1
+#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+typedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferParameteriAPPLE (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_APPLE_flush_buffer_range */
+
+#ifndef GL_APPLE_object_purgeable
+#define GL_APPLE_object_purgeable 1
+#define GL_BUFFER_OBJECT_APPLE 0x85B3
+#define GL_RELEASED_APPLE 0x8A19
+#define GL_VOLATILE_APPLE 0x8A1A
+#define GL_RETAINED_APPLE 0x8A1B
+#define GL_UNDEFINED_APPLE 0x8A1C
+#define GL_PURGEABLE_APPLE 0x8A1D
+typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#endif
+#endif /* GL_APPLE_object_purgeable */
+
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_RAW_422_APPLE 0x8A51
+#endif /* GL_APPLE_rgb_422 */
+
+#ifndef GL_APPLE_row_bytes
+#define GL_APPLE_row_bytes 1
+#define GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+#endif /* GL_APPLE_row_bytes */
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif /* GL_APPLE_specular_vector */
+
+#ifndef GL_APPLE_texture_range
+#define GL_APPLE_texture_range 1
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const void *pointer);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureRangeAPPLE (GLenum target, GLsizei length, const void *pointer);
+GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_APPLE_texture_range */
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+#endif /* GL_APPLE_transform_hint */
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint array);
+#endif
+#endif /* GL_APPLE_vertex_array_object */
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CLIENT_APPLE 0x85B4
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei length, void *pointer);
+GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei length, void *pointer);
+GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum pname, GLint param);
+#endif
+#endif /* GL_APPLE_vertex_array_range */
+
+#ifndef GL_APPLE_vertex_program_evaluators
+#define GL_APPLE_vertex_program_evaluators 1
+#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#endif
+#endif /* GL_APPLE_vertex_program_evaluators */
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+#define GL_YCBCR_422_APPLE 0x85B9
+#endif /* GL_APPLE_ycbcr_422 */
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersATI (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_ATI_draw_buffers */
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerATI (GLenum type, const void *pointer);
+GLAPI void APIENTRY glDrawElementArrayATI (GLenum mode, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+#endif /* GL_ATI_element_array */
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBumpParameterivATI (GLenum pname, const GLint *param);
+GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum pname, GLfloat *param);
+#endif
+#endif /* GL_ATI_envmap_bumpmap */
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_REG_6_ATI 0x8927
+#define GL_REG_7_ATI 0x8928
+#define GL_REG_8_ATI 0x8929
+#define GL_REG_9_ATI 0x892A
+#define GL_REG_10_ATI 0x892B
+#define GL_REG_11_ATI 0x892C
+#define GL_REG_12_ATI 0x892D
+#define GL_REG_13_ATI 0x892E
+#define GL_REG_14_ATI 0x892F
+#define GL_REG_15_ATI 0x8930
+#define GL_REG_16_ATI 0x8931
+#define GL_REG_17_ATI 0x8932
+#define GL_REG_18_ATI 0x8933
+#define GL_REG_19_ATI 0x8934
+#define GL_REG_20_ATI 0x8935
+#define GL_REG_21_ATI 0x8936
+#define GL_REG_22_ATI 0x8937
+#define GL_REG_23_ATI 0x8938
+#define GL_REG_24_ATI 0x8939
+#define GL_REG_25_ATI 0x893A
+#define GL_REG_26_ATI 0x893B
+#define GL_REG_27_ATI 0x893C
+#define GL_REG_28_ATI 0x893D
+#define GL_REG_29_ATI 0x893E
+#define GL_REG_30_ATI 0x893F
+#define GL_REG_31_ATI 0x8940
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_CON_8_ATI 0x8949
+#define GL_CON_9_ATI 0x894A
+#define GL_CON_10_ATI 0x894B
+#define GL_CON_11_ATI 0x894C
+#define GL_CON_12_ATI 0x894D
+#define GL_CON_13_ATI 0x894E
+#define GL_CON_14_ATI 0x894F
+#define GL_CON_15_ATI 0x8950
+#define GL_CON_16_ATI 0x8951
+#define GL_CON_17_ATI 0x8952
+#define GL_CON_18_ATI 0x8953
+#define GL_CON_19_ATI 0x8954
+#define GL_CON_20_ATI 0x8955
+#define GL_CON_21_ATI 0x8956
+#define GL_CON_22_ATI 0x8957
+#define GL_CON_23_ATI 0x8958
+#define GL_CON_24_ATI 0x8959
+#define GL_CON_25_ATI 0x895A
+#define GL_CON_26_ATI 0x895B
+#define GL_CON_27_ATI 0x895C
+#define GL_CON_28_ATI 0x895D
+#define GL_CON_29_ATI 0x895E
+#define GL_CON_30_ATI 0x895F
+#define GL_CON_31_ATI 0x8960
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint range);
+GLAPI void APIENTRY glBindFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glBeginFragmentShaderATI (void);
+GLAPI void APIENTRY glEndFragmentShaderATI (void);
+GLAPI void APIENTRY glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle);
+GLAPI void APIENTRY glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle);
+GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value);
+#endif
+#endif /* GL_ATI_fragment_shader */
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+typedef void *(APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void *APIENTRY glMapObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint buffer);
+#endif
+#endif /* GL_ATI_map_object_buffer */
+
+#ifndef GL_ATI_meminfo
+#define GL_ATI_meminfo 1
+#define GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+#endif /* GL_ATI_meminfo */
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_ATI_pixel_format_float 1
+#define GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#endif /* GL_ATI_pixel_format_float */
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPNTrianglesiATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glPNTrianglesfATI (GLenum pname, GLfloat param);
+#endif
+#endif /* GL_ATI_pn_triangles */
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+#endif /* GL_ATI_separate_stencil */
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+#endif /* GL_ATI_text_fragment_shader */
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+#endif /* GL_ATI_texture_env_combine3 */
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+#endif /* GL_ATI_texture_float */
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+#endif /* GL_ATI_texture_mirror_once */
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void *pointer, GLenum usage);
+typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei size, const void *pointer, GLenum usage);
+GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve);
+GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFreeObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params);
+GLAPI void APIENTRY glVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ATI_vertex_array_object */
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_STREAM0_ATI 0x876C
+#define GL_VERTEX_STREAM1_ATI 0x876D
+#define GL_VERTEX_STREAM2_ATI 0x876E
+#define GL_VERTEX_STREAM3_ATI 0x876F
+#define GL_VERTEX_STREAM4_ATI 0x8770
+#define GL_VERTEX_STREAM5_ATI 0x8771
+#define GL_VERTEX_STREAM6_ATI 0x8772
+#define GL_VERTEX_STREAM7_ATI 0x8773
+#define GL_VERTEX_SOURCE_ATI 0x8774
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexStream1sATI (GLenum stream, GLshort x);
+GLAPI void APIENTRY glVertexStream1svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream1iATI (GLenum stream, GLint x);
+GLAPI void APIENTRY glVertexStream1ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream1fATI (GLenum stream, GLfloat x);
+GLAPI void APIENTRY glVertexStream1fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream1dATI (GLenum stream, GLdouble x);
+GLAPI void APIENTRY glVertexStream1dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream2sATI (GLenum stream, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexStream2svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream2iATI (GLenum stream, GLint x, GLint y);
+GLAPI void APIENTRY glVertexStream2ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexStream2fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexStream2dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexStream4svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexStream4ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexStream4fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexStream4dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI void APIENTRY glNormalStream3bvATI (GLenum stream, const GLbyte *coords);
+GLAPI void APIENTRY glNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+GLAPI void APIENTRY glNormalStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz);
+GLAPI void APIENTRY glNormalStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void APIENTRY glNormalStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI void APIENTRY glNormalStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum stream);
+GLAPI void APIENTRY glVertexBlendEnviATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param);
+#endif
+#endif /* GL_ATI_vertex_streams */
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+#endif /* GL_EXT_422_pixels */
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#define GL_ABGR_EXT 0x8000
+#endif /* GL_EXT_abgr */
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+#endif /* GL_EXT_bgra */
+
+#ifndef GL_EXT_bindable_uniform
+#define GL_EXT_bindable_uniform 1
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+typedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer);
+GLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location);
+GLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint program, GLint location);
+#endif
+#endif /* GL_EXT_bindable_uniform */
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColorEXT (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#endif
+#endif /* GL_EXT_blend_color */
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha);
+#endif
+#endif /* GL_EXT_blend_equation_separate */
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+#endif /* GL_EXT_blend_func_separate */
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+#endif /* GL_EXT_blend_logic_op */
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_BLEND_EQUATION_EXT 0x8009
+typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_blend_minmax */
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+#endif /* GL_EXT_blend_subtract */
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+#endif /* GL_EXT_clip_volume_hint */
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+#endif /* GL_EXT_cmyka */
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+#endif /* GL_EXT_color_subtable */
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count);
+GLAPI void APIENTRY glUnlockArraysEXT (void);
+#endif
+#endif /* GL_EXT_compiled_vertex_array */
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, void *image);
+GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+#endif
+#endif /* GL_EXT_convolution */
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);
+typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);
+typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);
+typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);
+typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);
+typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);
+typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);
+typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);
+typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);
+typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);
+typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz);
+GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz);
+GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz);
+GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glTangent3iEXT (GLint tx, GLint ty, GLint tz);
+GLAPI void APIENTRY glTangent3ivEXT (const GLint *v);
+GLAPI void APIENTRY glTangent3sEXT (GLshort tx, GLshort ty, GLshort tz);
+GLAPI void APIENTRY glTangent3svEXT (const GLshort *v);
+GLAPI void APIENTRY glBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz);
+GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz);
+GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz);
+GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glBinormal3iEXT (GLint bx, GLint by, GLint bz);
+GLAPI void APIENTRY glBinormal3ivEXT (const GLint *v);
+GLAPI void APIENTRY glBinormal3sEXT (GLshort bx, GLshort by, GLshort bz);
+GLAPI void APIENTRY glBinormal3svEXT (const GLshort *v);
+GLAPI void APIENTRY glTangentPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glBinormalPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_coordinate_frame */
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_EXT_copy_texture */
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCullParameterdvEXT (GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glCullParameterfvEXT (GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_cull_vertex */
+
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+typedef void (APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_EXT_debug_label */
+
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+typedef void (APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GLAPI void APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GLAPI void APIENTRY glPopGroupMarkerEXT (void);
+#endif
+#endif /* GL_EXT_debug_marker */
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthBoundsEXT (GLclampd zmin, GLclampd zmax);
+#endif
+#endif /* GL_EXT_depth_bounds_test */
+
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+#define GL_PROGRAM_MATRIX_EXT 0x8E2D
+#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
+#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
+typedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+typedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data);
+typedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, void **data);
+typedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, void *img);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, void *img);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void *string);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);
+typedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, void **param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixPopEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixPushEXT (GLenum mode);
+GLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield mask);
+GLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield mask);
+GLAPI void APIENTRY glTextureParameterfEXT (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glTextureParameteriEXT (GLuint texture, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetTextureImageEXT (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+GLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glBindMultiTextureEXT (GLenum texunit, GLenum target, GLuint texture);
+GLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glMultiTexEnvfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexEnviEXT (GLenum texunit, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexGendEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+GLAPI void APIENTRY glMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
+GLAPI void APIENTRY glMultiTexGenfEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexGeniEXT (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, GLint *params);
+GLAPI void APIENTRY glMultiTexParameteriEXT (GLenum texunit, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexParameterfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+GLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum target, GLuint index, GLdouble *data);
+GLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum target, GLuint index, void **data);
+GLAPI void APIENTRY glEnableIndexedEXT (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisableIndexedEXT (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint texture, GLenum target, GLint lod, void *img);
+GLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target, GLint lod, void *img);
+GLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI void *APIENTRY glMapNamedBufferEXT (GLuint buffer, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint buffer);
+GLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint buffer, GLenum pname, void **params);
+GLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI void APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glTextureBufferEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glMultiTexBufferEXT (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint program, GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint program, GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint program, GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint program, GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glEnableClientStateiEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glDisableClientStateiEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glGetFloati_vEXT (GLenum pname, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetDoublei_vEXT (GLenum pname, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetPointeri_vEXT (GLenum pname, GLuint index, void **params);
+GLAPI void APIENTRY glNamedProgramStringEXT (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string);
+GLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint program, GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint program, GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint program, GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint program, GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetNamedProgramivEXT (GLuint program, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint program, GLenum target, GLenum pname, void *string);
+GLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint renderbuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint framebuffer, GLenum target);
+GLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint texture, GLenum target);
+GLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum texunit, GLenum target);
+GLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint framebuffer, GLenum mode);
+GLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint framebuffer, GLenum mode);
+GLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+GLAPI void APIENTRY glTextureRenderbufferEXT (GLuint texture, GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum texunit, GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glVertexArrayVertexOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayEdgeFlagOffsetEXT (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayIndexOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayNormalOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayMultiTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayFogCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArraySecondaryColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayVertexAttribOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayVertexAttribIOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glEnableVertexArrayEXT (GLuint vaobj, GLenum array);
+GLAPI void APIENTRY glDisableVertexArrayEXT (GLuint vaobj, GLenum array);
+GLAPI void APIENTRY glEnableVertexArrayAttribEXT (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glDisableVertexArrayAttribEXT (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glGetVertexArrayIntegervEXT (GLuint vaobj, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayPointervEXT (GLuint vaobj, GLenum pname, void **param);
+GLAPI void APIENTRY glGetVertexArrayIntegeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayPointeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, void **param);
+GLAPI void *APIENTRY glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glNamedBufferStorageEXT (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glNamedFramebufferParameteriEXT (GLuint framebuffer, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetNamedFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1dEXT (GLuint program, GLint location, GLdouble x);
+GLAPI void APIENTRY glProgramUniform2dEXT (GLuint program, GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glProgramUniform3dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glProgramUniform4dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramUniform1dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glTextureBufferRangeEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glTextureStorage2DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage3DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glVertexArrayBindVertexBufferEXT (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexArrayVertexAttribFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribIFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor);
+#endif
+#endif /* GL_EXT_direct_state_access */
+
+#ifndef GL_EXT_draw_buffers2
+#define GL_EXT_draw_buffers2 1
+typedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+#endif
+#endif /* GL_EXT_draw_buffers2 */
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_draw_instanced */
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+#endif
+#endif /* GL_EXT_draw_range_elements */
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordfEXT (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoorddEXT (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_fog_coord */
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* GL_EXT_framebuffer_blit */
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_EXT_framebuffer_multisample */
+
+#ifndef GL_EXT_framebuffer_multisample_blit_scaled
+#define GL_EXT_framebuffer_multisample_blit_scaled 1
+#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
+#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB
+#endif /* GL_EXT_framebuffer_multisample_blit_scaled */
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmapEXT (GLenum target);
+#endif
+#endif /* GL_EXT_framebuffer_object */
+
+#ifndef GL_EXT_framebuffer_sRGB
+#define GL_EXT_framebuffer_sRGB 1
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#endif /* GL_EXT_framebuffer_sRGB */
+
+#ifndef GL_EXT_geometry_shader4
+#define GL_EXT_geometry_shader4 1
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+#endif
+#endif /* GL_EXT_geometry_shader4 */
+
+#ifndef GL_EXT_gpu_program_parameters
+#define GL_EXT_gpu_program_parameters 1
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#endif
+#endif /* GL_EXT_gpu_program_parameters */
+
+#ifndef GL_EXT_gpu_shader4
+#define GL_EXT_gpu_shader4 1
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
+#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1uiEXT (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value);
+#endif
+#endif /* GL_EXT_gpu_shader4 */
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+#define GL_TABLE_TOO_LARGE_EXT 0x8031
+typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogramEXT (GLenum target);
+GLAPI void APIENTRY glResetMinmaxEXT (GLenum target);
+#endif
+#endif /* GL_EXT_histogram */
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+#define GL_IUI_V2F_EXT 0x81AD
+#define GL_IUI_V3F_EXT 0x81AE
+#define GL_IUI_N3F_V2F_EXT 0x81AF
+#define GL_IUI_N3F_V3F_EXT 0x81B0
+#define GL_T2F_IUI_V2F_EXT 0x81B1
+#define GL_T2F_IUI_V3F_EXT 0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4
+#endif /* GL_EXT_index_array_formats */
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+#define GL_INDEX_TEST_EXT 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT 0x81B6
+#define GL_INDEX_TEST_REF_EXT 0x81B7
+typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexFuncEXT (GLenum func, GLclampf ref);
+#endif
+#endif /* GL_EXT_index_func */
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+#define GL_INDEX_MATERIAL_EXT 0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA
+typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexMaterialEXT (GLenum face, GLenum mode);
+#endif
+#endif /* GL_EXT_index_material */
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+#endif /* GL_EXT_index_texture */
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyTextureEXT (GLenum mode);
+GLAPI void APIENTRY glTextureLightEXT (GLenum pname);
+GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode);
+#endif
+#endif /* GL_EXT_light_texture */
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+#endif /* GL_EXT_misc_attribute */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskEXT (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern);
+#endif
+#endif /* GL_EXT_multisample */
+
+#ifndef GL_EXT_packed_depth_stencil
+#define GL_EXT_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+#endif /* GL_EXT_packed_depth_stencil */
+
+#ifndef GL_EXT_packed_float
+#define GL_EXT_packed_float 1
+#define GL_R11F_G11F_B10F_EXT 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+#endif /* GL_EXT_packed_float */
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+#endif /* GL_EXT_packed_pixels */
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void *data);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glGetColorTableEXT (GLenum target, GLenum format, GLenum type, void *data);
+GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_paletted_texture */
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#endif /* GL_EXT_pixel_buffer_object */
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTransformParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTransformParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_pixel_transform */
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+#endif /* GL_EXT_pixel_transform_color_table */
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfEXT (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvEXT (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_EXT_point_parameters */
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias);
+#endif
+#endif /* GL_EXT_polygon_offset */
+
+#ifndef GL_EXT_provoking_vertex
+#define GL_EXT_provoking_vertex 1
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_PROVOKING_VERTEX_EXT 0x8E4F
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_provoking_vertex */
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#define GL_RESCALE_NORMAL_EXT 0x803A
+#endif /* GL_EXT_rescale_normal */
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3iEXT (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_secondary_color */
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
+typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program);
+GLAPI void APIENTRY glActiveProgramEXT (GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string);
+#endif
+#endif /* GL_EXT_separate_shader_objects */
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif /* GL_EXT_separate_specular_color */
+
+#ifndef GL_EXT_shader_image_load_formatted
+#define GL_EXT_shader_image_load_formatted 1
+#endif /* GL_EXT_shader_image_load_formatted */
+
+#ifndef GL_EXT_shader_image_load_store
+#define GL_EXT_shader_image_load_store 1
+#define GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define GL_IMAGE_1D_EXT 0x904C
+#define GL_IMAGE_2D_EXT 0x904D
+#define GL_IMAGE_3D_EXT 0x904E
+#define GL_IMAGE_2D_RECT_EXT 0x904F
+#define GL_IMAGE_CUBE_EXT 0x9050
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define GL_INT_IMAGE_1D_EXT 0x9057
+#define GL_INT_IMAGE_2D_EXT 0x9058
+#define GL_INT_IMAGE_3D_EXT 0x9059
+#define GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define GL_INT_IMAGE_CUBE_EXT 0x905B
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindImageTextureEXT (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers);
+#endif
+#endif /* GL_EXT_shader_image_load_store */
+
+#ifndef GL_EXT_shader_integer_mix
+#define GL_EXT_shader_integer_mix 1
+#endif /* GL_EXT_shader_integer_mix */
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif /* GL_EXT_shadow_funcs */
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+#endif /* GL_EXT_shared_texture_palette */
+
+#ifndef GL_EXT_stencil_clear_tag
+#define GL_EXT_stencil_clear_tag 1
+#define GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+typedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilClearTagEXT (GLsizei stencilTagBits, GLuint stencilClearTag);
+#endif
+#endif /* GL_EXT_stencil_clear_tag */
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum face);
+#endif
+#endif /* GL_EXT_stencil_two_side */
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+#endif /* GL_EXT_stencil_wrap */
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_EXT_subtexture */
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT 0x8065
+#endif /* GL_EXT_texture */
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_EXT_texture3D */
+
+#ifndef GL_EXT_texture_array
+#define GL_EXT_texture_array 1
+#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+#endif /* GL_EXT_texture_array */
+
+#ifndef GL_EXT_texture_buffer_object
+#define GL_EXT_texture_buffer_object 1
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+typedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+#endif /* GL_EXT_texture_buffer_object */
+
+#ifndef GL_EXT_texture_compression_latc
+#define GL_EXT_texture_compression_latc 1
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+#endif /* GL_EXT_texture_compression_latc */
+
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_EXT_texture_compression_rgtc 1
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#endif /* GL_EXT_texture_compression_rgtc */
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_EXT_texture_cube_map 1
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+#endif /* GL_EXT_texture_cube_map */
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif /* GL_EXT_texture_env_add */
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+#endif /* GL_EXT_texture_env_combine */
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+#endif /* GL_EXT_texture_env_dot3 */
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifndef GL_EXT_texture_integer
+#define GL_EXT_texture_integer 1
+#define GL_RGBA32UI_EXT 0x8D70
+#define GL_RGB32UI_EXT 0x8D71
+#define GL_ALPHA32UI_EXT 0x8D72
+#define GL_INTENSITY32UI_EXT 0x8D73
+#define GL_LUMINANCE32UI_EXT 0x8D74
+#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define GL_RGBA16UI_EXT 0x8D76
+#define GL_RGB16UI_EXT 0x8D77
+#define GL_ALPHA16UI_EXT 0x8D78
+#define GL_INTENSITY16UI_EXT 0x8D79
+#define GL_LUMINANCE16UI_EXT 0x8D7A
+#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define GL_RGBA8UI_EXT 0x8D7C
+#define GL_RGB8UI_EXT 0x8D7D
+#define GL_ALPHA8UI_EXT 0x8D7E
+#define GL_INTENSITY8UI_EXT 0x8D7F
+#define GL_LUMINANCE8UI_EXT 0x8D80
+#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define GL_RGBA32I_EXT 0x8D82
+#define GL_RGB32I_EXT 0x8D83
+#define GL_ALPHA32I_EXT 0x8D84
+#define GL_INTENSITY32I_EXT 0x8D85
+#define GL_LUMINANCE32I_EXT 0x8D86
+#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define GL_RGBA16I_EXT 0x8D88
+#define GL_RGB16I_EXT 0x8D89
+#define GL_ALPHA16I_EXT 0x8D8A
+#define GL_INTENSITY16I_EXT 0x8D8B
+#define GL_LUMINANCE16I_EXT 0x8D8C
+#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define GL_RGBA8I_EXT 0x8D8E
+#define GL_RGB8I_EXT 0x8D8F
+#define GL_ALPHA8I_EXT 0x8D90
+#define GL_INTENSITY8I_EXT 0x8D91
+#define GL_LUMINANCE8I_EXT 0x8D92
+#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define GL_RED_INTEGER_EXT 0x8D94
+#define GL_GREEN_INTEGER_EXT 0x8D95
+#define GL_BLUE_INTEGER_EXT 0x8D96
+#define GL_ALPHA_INTEGER_EXT 0x8D97
+#define GL_RGB_INTEGER_EXT 0x8D98
+#define GL_RGBA_INTEGER_EXT 0x8D99
+#define GL_BGR_INTEGER_EXT 0x8D9A
+#define GL_BGRA_INTEGER_EXT 0x8D9B
+#define GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI void APIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#endif
+#endif /* GL_EXT_texture_integer */
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#endif /* GL_EXT_texture_lod_bias */
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#endif /* GL_EXT_texture_mirror_clamp */
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI void APIENTRY glBindTextureEXT (GLenum target, GLuint texture);
+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures);
+GLAPI void APIENTRY glGenTexturesEXT (GLsizei n, GLuint *textures);
+GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint texture);
+GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+#endif /* GL_EXT_texture_object */
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_texture_perturb_normal */
+
+#ifndef GL_EXT_texture_sRGB
+#define GL_EXT_texture_sRGB 1
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB8_EXT 0x8C41
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define GL_SLUMINANCE_EXT 0x8C46
+#define GL_SLUMINANCE8_EXT 0x8C47
+#define GL_COMPRESSED_SRGB_EXT 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif /* GL_EXT_texture_sRGB */
+
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#endif /* GL_EXT_texture_sRGB_decode */
+
+#ifndef GL_EXT_texture_shared_exponent
+#define GL_EXT_texture_shared_exponent 1
+#define GL_RGB9_E5_EXT 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+#endif /* GL_EXT_texture_shared_exponent */
+
+#ifndef GL_EXT_texture_snorm
+#define GL_EXT_texture_snorm 1
+#define GL_ALPHA_SNORM 0x9010
+#define GL_LUMINANCE_SNORM 0x9011
+#define GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define GL_INTENSITY_SNORM 0x9013
+#define GL_ALPHA8_SNORM 0x9014
+#define GL_LUMINANCE8_SNORM 0x9015
+#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define GL_INTENSITY8_SNORM 0x9017
+#define GL_ALPHA16_SNORM 0x9018
+#define GL_LUMINANCE16_SNORM 0x9019
+#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define GL_INTENSITY16_SNORM 0x901B
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#endif /* GL_EXT_texture_snorm */
+
+#ifndef GL_EXT_texture_swizzle
+#define GL_EXT_texture_swizzle 1
+#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+#endif /* GL_EXT_texture_swizzle */
+
+#ifndef GL_EXT_timer_query
+#define GL_EXT_timer_query 1
+#define GL_TIME_ELAPSED_EXT 0x88BF
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+#endif /* GL_EXT_timer_query */
+
+#ifndef GL_EXT_transform_feedback
+#define GL_EXT_transform_feedback 1
+#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackEXT (void);
+GLAPI void APIENTRY glBindBufferRangeEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseEXT (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#endif
+#endif /* GL_EXT_transform_feedback */
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glArrayElementEXT (GLint i);
+GLAPI void APIENTRY glColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glDrawArraysEXT (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer);
+GLAPI void APIENTRY glGetPointervEXT (GLenum pname, void **params);
+GLAPI void APIENTRY glIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+#endif
+#endif /* GL_EXT_vertex_array */
+
+#ifndef GL_EXT_vertex_array_bgra
+#define GL_EXT_vertex_array_bgra 1
+#endif /* GL_EXT_vertex_array_bgra */
+
+#ifndef GL_EXT_vertex_attrib_64bit
+#define GL_EXT_vertex_attrib_64bit 1
+#define GL_DOUBLE_VEC2_EXT 0x8FFC
+#define GL_DOUBLE_VEC3_EXT 0x8FFD
+#define GL_DOUBLE_VEC4_EXT 0x8FFE
+#define GL_DOUBLE_MAT2_EXT 0x8F46
+#define GL_DOUBLE_MAT3_EXT 0x8F47
+#define GL_DOUBLE_MAT4_EXT 0x8F48
+#define GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define GL_DOUBLE_MAT4x3_EXT 0x8F4E
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1dEXT (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2dEXT (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdvEXT (GLuint index, GLenum pname, GLdouble *params);
+#endif
+#endif /* GL_EXT_vertex_attrib_64bit */
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const void *addr);
+typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const void *addr);
+typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);
+typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);
+typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);
+typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);
+typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);
+typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);
+typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const void *addr);
+typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, void **data);
+typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVertexShaderEXT (void);
+GLAPI void APIENTRY glEndVertexShaderEXT (void);
+GLAPI void APIENTRY glBindVertexShaderEXT (GLuint id);
+GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint range);
+GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint id);
+GLAPI void APIENTRY glShaderOp1EXT (GLenum op, GLuint res, GLuint arg1);
+GLAPI void APIENTRY glShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+GLAPI void APIENTRY glShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+GLAPI void APIENTRY glSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glInsertComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI void APIENTRY glExtractComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+GLAPI void APIENTRY glSetInvariantEXT (GLuint id, GLenum type, const void *addr);
+GLAPI void APIENTRY glSetLocalConstantEXT (GLuint id, GLenum type, const void *addr);
+GLAPI void APIENTRY glVariantbvEXT (GLuint id, const GLbyte *addr);
+GLAPI void APIENTRY glVariantsvEXT (GLuint id, const GLshort *addr);
+GLAPI void APIENTRY glVariantivEXT (GLuint id, const GLint *addr);
+GLAPI void APIENTRY glVariantfvEXT (GLuint id, const GLfloat *addr);
+GLAPI void APIENTRY glVariantdvEXT (GLuint id, const GLdouble *addr);
+GLAPI void APIENTRY glVariantubvEXT (GLuint id, const GLubyte *addr);
+GLAPI void APIENTRY glVariantusvEXT (GLuint id, const GLushort *addr);
+GLAPI void APIENTRY glVariantuivEXT (GLuint id, const GLuint *addr);
+GLAPI void APIENTRY glVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const void *addr);
+GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint id);
+GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint id);
+GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum light, GLenum value);
+GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum face, GLenum value);
+GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value);
+GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum unit, GLenum value);
+GLAPI GLuint APIENTRY glBindParameterEXT (GLenum value);
+GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint id, GLenum cap);
+GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetVariantPointervEXT (GLuint id, GLenum value, void **data);
+GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+#endif
+#endif /* GL_EXT_vertex_shader */
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW0_EXT 0x1700
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexWeightfEXT (GLfloat weight);
+GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *weight);
+GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_vertex_weighting */
+
+#ifndef GL_EXT_x11_sync_object
+#define GL_EXT_x11_sync_object 1
+#define GL_SYNC_X11_FENCE_EXT 0x90E1
+typedef GLsync (APIENTRYP PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glImportSyncEXT (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+#endif
+#endif /* GL_EXT_x11_sync_object */
+
+#ifndef GL_GREMEDY_frame_terminator
+#define GL_GREMEDY_frame_terminator 1
+typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameTerminatorGREMEDY (void);
+#endif
+#endif /* GL_GREMEDY_frame_terminator */
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void *string);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei len, const void *string);
+#endif
+#endif /* GL_GREMEDY_string_marker */
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+#define GL_IGNORE_BORDER_HP 0x8150
+#define GL_CONSTANT_BORDER_HP 0x8151
+#define GL_REPLICATE_BORDER_HP 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154
+#endif /* GL_HP_convolution_border_modes */
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+#define GL_IMAGE_SCALE_X_HP 0x8155
+#define GL_IMAGE_SCALE_Y_HP 0x8156
+#define GL_IMAGE_TRANSLATE_X_HP 0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP 0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B
+#define GL_IMAGE_MAG_FILTER_HP 0x815C
+#define GL_IMAGE_MIN_FILTER_HP 0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E
+#define GL_CUBIC_HP 0x815F
+#define GL_AVERAGE_HP 0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP 0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImageTransformParameteriHP (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_HP_image_transform */
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+#endif /* GL_HP_occlusion_test */
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP 0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169
+#endif /* GL_HP_texture_lighting */
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+#define GL_CULL_VERTEX_IBM 103050
+#endif /* GL_IBM_cull_vertex */
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride);
+#endif
+#endif /* GL_IBM_multimode_draw_arrays */
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262
+#endif /* GL_IBM_rasterpos_clip */
+
+#ifndef GL_IBM_static_data
+#define GL_IBM_static_data 1
+#define GL_ALL_STATIC_DATA_IBM 103060
+#define GL_STATIC_VERTEX_ARRAY_IBM 103061
+typedef void (APIENTRYP PFNGLFLUSHSTATICDATAIBMPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushStaticDataIBM (GLenum target);
+#endif
+#endif /* GL_IBM_static_data */
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_IBM_texture_mirrored_repeat 1
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint stride, const GLboolean **pointer, GLint ptrstride);
+GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glIndexPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glNormalPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glVertexPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+#endif
+#endif /* GL_IBM_vertex_array_lists */
+
+#ifndef GL_INGR_blend_func_separate
+#define GL_INGR_blend_func_separate 1
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+#endif /* GL_INGR_blend_func_separate */
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+#endif /* GL_INGR_color_clamp */
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+#define GL_INTERLACE_READ_INGR 0x8568
+#endif /* GL_INGR_interlace_read */
+
+#ifndef GL_INTEL_fragment_shader_ordering
+#define GL_INTEL_fragment_shader_ordering 1
+#endif /* GL_INTEL_fragment_shader_ordering */
+
+#ifndef GL_INTEL_map_texture
+#define GL_INTEL_map_texture 1
+#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
+#define GL_LAYOUT_DEFAULT_INTEL 0
+#define GL_LAYOUT_LINEAR_INTEL 1
+#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2
+typedef void (APIENTRYP PFNGLSYNCTEXTUREINTELPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level);
+typedef void *(APIENTRYP PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSyncTextureINTEL (GLuint texture);
+GLAPI void APIENTRY glUnmapTexture2DINTEL (GLuint texture, GLint level);
+GLAPI void *APIENTRY glMapTexture2DINTEL (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout);
+#endif
+#endif /* GL_INTEL_map_texture */
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexPointervINTEL (GLint size, GLenum type, const void **pointer);
+GLAPI void APIENTRY glNormalPointervINTEL (GLenum type, const void **pointer);
+GLAPI void APIENTRY glColorPointervINTEL (GLint size, GLenum type, const void **pointer);
+GLAPI void APIENTRY glTexCoordPointervINTEL (GLint size, GLenum type, const void **pointer);
+#endif
+#endif /* GL_INTEL_parallel_arrays */
+
+#ifndef GL_INTEL_performance_query
+#define GL_INTEL_performance_query 1
+#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
+#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001
+#define GL_PERFQUERY_WAIT_INTEL 0x83FB
+#define GL_PERFQUERY_FLUSH_INTEL 0x83FA
+#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9
+#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0
+#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1
+#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2
+#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3
+#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4
+#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5
+#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8
+#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9
+#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA
+#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB
+#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC
+#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD
+#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE
+#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF
+#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500
+typedef void (APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle);
+typedef void (APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
+typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
+typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
+typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle);
+GLAPI void APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
+GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
+GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
+GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#endif
+#endif /* GL_INTEL_performance_query */
+
+#ifndef GL_MESAX_texture_stack
+#define GL_MESAX_texture_stack 1
+#define GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+#endif /* GL_MESAX_texture_stack */
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+#define GL_PACK_INVERT_MESA 0x8758
+#endif /* GL_MESA_pack_invert */
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glResizeBuffersMESA (void);
+#endif
+#endif /* GL_MESA_resize_buffers */
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dMESA (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fMESA (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iMESA (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sMESA (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iMESA (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sMESA (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v);
+#endif
+#endif /* GL_MESA_window_pos */
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+#endif /* GL_MESA_ycbcr_texture */
+
+#ifndef GL_NVX_conditional_render
+#define GL_NVX_conditional_render 1
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNVX (GLuint id);
+GLAPI void APIENTRY glEndConditionalRenderNVX (void);
+#endif
+#endif /* GL_NVX_conditional_render */
+
+#ifndef GL_NVX_gpu_memory_info
+#define GL_NVX_gpu_memory_info 1
+#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+#endif /* GL_NVX_gpu_memory_info */
+
+#ifndef GL_NV_bindless_multi_draw_indirect
+#define GL_NV_bindless_multi_draw_indirect 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+#endif
+#endif /* GL_NV_bindless_multi_draw_indirect */
+
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleNV (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
+
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+#define GL_BLEND_OVERLAP_NV 0x9281
+#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define GL_BLUE_NV 0x1905
+#define GL_COLORBURN_NV 0x929A
+#define GL_COLORDODGE_NV 0x9299
+#define GL_CONJOINT_NV 0x9284
+#define GL_CONTRAST_NV 0x92A1
+#define GL_DARKEN_NV 0x9297
+#define GL_DIFFERENCE_NV 0x929E
+#define GL_DISJOINT_NV 0x9283
+#define GL_DST_ATOP_NV 0x928F
+#define GL_DST_IN_NV 0x928B
+#define GL_DST_NV 0x9287
+#define GL_DST_OUT_NV 0x928D
+#define GL_DST_OVER_NV 0x9289
+#define GL_EXCLUSION_NV 0x92A0
+#define GL_GREEN_NV 0x1904
+#define GL_HARDLIGHT_NV 0x929B
+#define GL_HARDMIX_NV 0x92A9
+#define GL_HSL_COLOR_NV 0x92AF
+#define GL_HSL_HUE_NV 0x92AD
+#define GL_HSL_LUMINOSITY_NV 0x92B0
+#define GL_HSL_SATURATION_NV 0x92AE
+#define GL_INVERT_OVG_NV 0x92B4
+#define GL_INVERT_RGB_NV 0x92A3
+#define GL_LIGHTEN_NV 0x9298
+#define GL_LINEARBURN_NV 0x92A5
+#define GL_LINEARDODGE_NV 0x92A4
+#define GL_LINEARLIGHT_NV 0x92A7
+#define GL_MINUS_CLAMPED_NV 0x92B3
+#define GL_MINUS_NV 0x929F
+#define GL_MULTIPLY_NV 0x9294
+#define GL_OVERLAY_NV 0x9296
+#define GL_PINLIGHT_NV 0x92A8
+#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define GL_PLUS_CLAMPED_NV 0x92B1
+#define GL_PLUS_DARKER_NV 0x9292
+#define GL_PLUS_NV 0x9291
+#define GL_RED_NV 0x1903
+#define GL_SCREEN_NV 0x9295
+#define GL_SOFTLIGHT_NV 0x929C
+#define GL_SRC_ATOP_NV 0x928E
+#define GL_SRC_IN_NV 0x928A
+#define GL_SRC_NV 0x9286
+#define GL_SRC_OUT_NV 0x928C
+#define GL_SRC_OVER_NV 0x9288
+#define GL_UNCORRELATED_NV 0x9282
+#define GL_VIVIDLIGHT_NV 0x92A6
+#define GL_XOR_NV 0x1506
+typedef void (APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLBLENDBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendParameteriNV (GLenum pname, GLint value);
+GLAPI void APIENTRY glBlendBarrierNV (void);
+#endif
+#endif /* GL_NV_blend_equation_advanced */
+
+#ifndef GL_NV_blend_equation_advanced_coherent
+#define GL_NV_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif /* GL_NV_blend_square */
+
+#ifndef GL_NV_compute_program5
+#define GL_NV_compute_program5 1
+#define GL_COMPUTE_PROGRAM_NV 0x90FB
+#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
+#endif /* GL_NV_compute_program5 */
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+#endif /* GL_NV_copy_depth_to_color */
+
+#ifndef GL_NV_copy_image
+#define GL_NV_copy_image 1
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyImageSubDataNV (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+#endif /* GL_NV_copy_image */
+
+#ifndef GL_NV_deep_texture3D
+#define GL_NV_deep_texture3D 1
+#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0
+#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1
+#endif /* GL_NV_deep_texture3D */
+
+#ifndef GL_NV_depth_buffer_float
+#define GL_NV_depth_buffer_float 1
+#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glClearDepthdNV (GLdouble depth);
+GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax);
+#endif
+#endif /* GL_NV_depth_buffer_float */
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#define GL_DEPTH_CLAMP_NV 0x864F
+#endif /* GL_NV_depth_clamp */
+
+#ifndef GL_NV_draw_texture
+#define GL_NV_draw_texture 1
+typedef void (APIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawTextureNV (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+#endif
+#endif /* GL_NV_draw_texture */
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points);
+typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points);
+GLAPI void APIENTRY glMapParameterivNV (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points);
+GLAPI void APIENTRY glGetMapParameterivNV (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glEvalMapsNV (GLenum target, GLenum mode);
+#endif
+#endif /* GL_NV_evaluators */
+
+#ifndef GL_NV_explicit_multisample
+#define GL_NV_explicit_multisample 1
+#define GL_SAMPLE_POSITION_NV 0x8E50
+#define GL_SAMPLE_MASK_NV 0x8E51
+#define GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);
+typedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetMultisamplefvNV (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaskIndexedNV (GLuint index, GLbitfield mask);
+GLAPI void APIENTRY glTexRenderbufferNV (GLenum target, GLuint renderbuffer);
+#endif
+#endif /* GL_NV_explicit_multisample */
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GLAPI GLboolean APIENTRY glIsFenceNV (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceNV (GLuint fence);
+GLAPI void APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFinishFenceNV (GLuint fence);
+GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+#endif /* GL_NV_fence */
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+#endif /* GL_NV_float_buffer */
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+#endif /* GL_NV_fog_distance */
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+#endif /* GL_NV_fragment_program */
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+#endif /* GL_NV_fragment_program2 */
+
+#ifndef GL_NV_fragment_program4
+#define GL_NV_fragment_program4 1
+#endif /* GL_NV_fragment_program4 */
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+#endif /* GL_NV_fragment_program_option */
+
+#ifndef GL_NV_framebuffer_multisample_coverage
+#define GL_NV_framebuffer_multisample_coverage 1
+#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+#ifndef GL_NV_geometry_program4
+#define GL_NV_geometry_program4 1
+#define GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit);
+GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+#endif /* GL_NV_geometry_program4 */
+
+#ifndef GL_NV_geometry_shader4
+#define GL_NV_geometry_shader4 1
+#endif /* GL_NV_geometry_shader4 */
+
+#ifndef GL_NV_gpu_program4
+#define GL_NV_gpu_program4 1
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+#endif
+#endif /* GL_NV_gpu_program4 */
+
+#ifndef GL_NV_gpu_program5
+#define GL_NV_gpu_program5 1
+#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F
+#define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
+#define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45
+typedef void (APIENTRYP PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC) (GLenum target, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC) (GLenum target, GLuint index, GLuint *param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramSubroutineParametersuivNV (GLenum target, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramSubroutineParameteruivNV (GLenum target, GLuint index, GLuint *param);
+#endif
+#endif /* GL_NV_gpu_program5 */
+
+#ifndef GL_NV_gpu_program5_mem_extended
+#define GL_NV_gpu_program5_mem_extended 1
+#endif /* GL_NV_gpu_program5_mem_extended */
+
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+#endif /* GL_NV_gpu_shader5 */
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+typedef unsigned short GLhalfNV;
+#define GL_HALF_FLOAT_NV 0x140B
+typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);
+typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
+typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV s);
+GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum target, GLhalfNV s);
+GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
+GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
+GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
+GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
+GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x);
+GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+#endif /* GL_NV_half_float */
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+#endif /* GL_NV_light_max_exponent */
+
+#ifndef GL_NV_multisample_coverage
+#define GL_NV_multisample_coverage 1
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#endif /* GL_NV_multisample_coverage */
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+#endif /* GL_NV_multisample_filter_hint */
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glEndOcclusionQueryNV (void);
+GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_NV_occlusion_query */
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+#endif /* GL_NV_packed_depth_stencil */
+
+#ifndef GL_NV_parameter_buffer_object
+#define GL_NV_parameter_buffer_object 1
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params);
+#endif
+#endif /* GL_NV_parameter_buffer_object */
+
+#ifndef GL_NV_parameter_buffer_object2
+#define GL_NV_parameter_buffer_object2 1
+#endif /* GL_NV_parameter_buffer_object2 */
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+typedef GLuint (APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode);
+typedef void (APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value);
+typedef GLboolean (APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenPathsNV (GLsizei range);
+GLAPI void APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GLAPI GLboolean APIENTRY glIsPathNV (GLuint path);
+GLAPI void APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GLAPI void APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GLAPI void APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GLAPI void APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GLAPI void APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GLAPI void APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GLAPI void APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GLAPI void APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GLAPI void APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GLAPI void APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GLAPI void APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GLAPI void APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GLAPI void APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathFogGenNV (GLenum genMode);
+GLAPI void APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GLAPI void APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GLAPI void APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GLAPI void APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GLAPI void APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GLAPI void APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GLAPI void APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GLAPI void APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GLAPI void APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value);
+GLAPI GLboolean APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GLAPI GLboolean APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GLAPI GLfloat APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GLAPI GLboolean APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, const void *pointer);
+typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, const void *pointer);
+GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target);
+#endif
+#endif /* GL_NV_pixel_data_range */
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameterivNV (GLenum pname, const GLint *params);
+#endif
+#endif /* GL_NV_point_sprite */
+
+#ifndef GL_NV_present_video
+#define GL_NV_present_video 1
+#define GL_FRAME_NV 0x8E26
+#define GL_FIELDS_NV 0x8E27
+#define GL_CURRENT_TIME_NV 0x8E28
+#define GL_NUM_FILL_STREAMS_NV 0x8E29
+#define GL_PRESENT_TIME_NV 0x8E2A
+#define GL_PRESENT_DURATION_NV 0x8E2B
+typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+GLAPI void APIENTRY glGetVideoivNV (GLuint video_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideouivNV (GLuint video_slot, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glGetVideoi64vNV (GLuint video_slot, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVideoui64vNV (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#endif
+#endif /* GL_NV_present_video */
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveRestartNV (void);
+GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index);
+#endif
+#endif /* GL_NV_primitive_restart */
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerParameterfvNV (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glCombinerParameterfNV (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glCombinerParameterivNV (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCombinerParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+GLAPI void APIENTRY glFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params);
+#endif
+#endif /* GL_NV_register_combiners */
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_NV_register_combiners2 */
+
+#ifndef GL_NV_shader_atomic_counters
+#define GL_NV_shader_atomic_counters 1
+#endif /* GL_NV_shader_atomic_counters */
+
+#ifndef GL_NV_shader_atomic_float
+#define GL_NV_shader_atomic_float 1
+#endif /* GL_NV_shader_atomic_float */
+
+#ifndef GL_NV_shader_buffer_load
+#define GL_NV_shader_buffer_load 1
+#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define GL_GPU_ADDRESS_NV 0x8F34
+#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result);
+typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access);
+GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target);
+GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target);
+GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access);
+GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer);
+GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer);
+GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result);
+GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_NV_shader_buffer_load */
+
+#ifndef GL_NV_shader_buffer_store
+#define GL_NV_shader_buffer_store 1
+#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010
+#endif /* GL_NV_shader_buffer_store */
+
+#ifndef GL_NV_shader_storage_buffer_object
+#define GL_NV_shader_storage_buffer_object 1
+#endif /* GL_NV_shader_storage_buffer_object */
+
+#ifndef GL_NV_shader_thread_group
+#define GL_NV_shader_thread_group 1
+#define GL_WARP_SIZE_NV 0x9339
+#define GL_WARPS_PER_SM_NV 0x933A
+#define GL_SM_COUNT_NV 0x933B
+#endif /* GL_NV_shader_thread_group */
+
+#ifndef GL_NV_shader_thread_shuffle
+#define GL_NV_shader_thread_shuffle 1
+#endif /* GL_NV_shader_thread_shuffle */
+
+#ifndef GL_NV_tessellation_program5
+#define GL_NV_tessellation_program5 1
+#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+#endif /* GL_NV_tessellation_program5 */
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+#endif /* GL_NV_texgen_emboss */
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+#endif /* GL_NV_texgen_reflection */
+
+#ifndef GL_NV_texture_barrier
+#define GL_NV_texture_barrier 1
+typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureBarrierNV (void);
+#endif
+#endif /* GL_NV_texture_barrier */
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif /* GL_NV_texture_compression_vtc */
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+#endif /* GL_NV_texture_env_combine4 */
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#endif /* GL_NV_texture_expand_normal */
+
+#ifndef GL_NV_texture_multisample
+#define GL_NV_texture_multisample 1
+#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045
+#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage2DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTexImage3DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage2DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage3DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage2DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+#endif
+#endif /* GL_NV_texture_multisample */
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+#endif /* GL_NV_texture_rectangle */
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+#endif /* GL_NV_texture_shader */
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#endif /* GL_NV_texture_shader2 */
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+#endif /* GL_NV_texture_shader3 */
+
+#ifndef GL_NV_transform_feedback
+#define GL_NV_transform_feedback 1
+#define GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define GL_TEXTURE_COORD_NV 0x8C79
+#define GL_CLIP_DISTANCE_NV 0x8C7A
+#define GL_VERTEX_ID_NV 0x8C7B
+#define GL_PRIMITIVE_ID_NV 0x8C7C
+#define GL_GENERIC_ATTRIB_NV 0x8C7D
+#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define GL_ACTIVE_VARYINGS_NV 0x8C81
+#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define GL_RASTERIZER_DISCARD_NV 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+#define GL_LAYER_NV 0x8DAA
+#define GL_NEXT_BUFFER_NV -2
+#define GL_SKIP_COMPONENTS4_NV -3
+#define GL_SKIP_COMPONENTS3_NV -4
+#define GL_SKIP_COMPONENTS2_NV -5
+#define GL_SKIP_COMPONENTS1_NV -6
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackNV (void);
+GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode);
+GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+GLAPI void APIENTRY glActiveVaryingNV (GLuint program, const GLchar *name);
+GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location);
+GLAPI void APIENTRY glTransformFeedbackStreamAttribsNV (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#endif
+#endif /* GL_NV_transform_feedback */
+
+#ifndef GL_NV_transform_feedback2
+#define GL_NV_transform_feedback2 1
+#define GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindTransformFeedbackNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedbackNV (void);
+GLAPI void APIENTRY glResumeTransformFeedbackNV (void);
+GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
+#endif
+#endif /* GL_NV_transform_feedback2 */
+
+#ifndef GL_NV_vdpau_interop
+#define GL_NV_vdpau_interop 1
+typedef GLintptr GLvdpauSurfaceNV;
+#define GL_SURFACE_STATE_NV 0x86EB
+#define GL_SURFACE_REGISTERED_NV 0x86FD
+#define GL_SURFACE_MAPPED_NV 0x8700
+#define GL_WRITE_DISCARD_NV 0x88BE
+typedef void (APIENTRYP PFNGLVDPAUINITNVPROC) (const void *vdpDevice, const void *getProcAddress);
+typedef void (APIENTRYP PFNGLVDPAUFININVPROC) (void);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLboolean (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
+typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVDPAUInitNV (const void *vdpDevice, const void *getProcAddress);
+GLAPI void APIENTRY glVDPAUFiniNV (void);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLboolean APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access);
+GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#endif
+#endif /* GL_NV_vdpau_interop */
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushVertexArrayRangeNV (void);
+GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei length, const void *pointer);
+#endif
+#endif /* GL_NV_vertex_array_range */
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif /* GL_NV_vertex_array_range2 */
+
+#ifndef GL_NV_vertex_attrib_integer_64bit
+#define GL_NV_vertex_attrib_integer_64bit 1
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+#endif
+#endif /* GL_NV_vertex_attrib_integer_64bit */
+
+#ifndef GL_NV_vertex_buffer_unified_memory
+#define GL_NV_vertex_buffer_unified_memory 1
+#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride);
+GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result);
+#endif
+#endif /* GL_NV_vertex_buffer_unified_memory */
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences);
+GLAPI void APIENTRY glBindProgramNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params);
+GLAPI void APIENTRY glGenProgramsNV (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program);
+GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint index, GLenum pname, void **pointer);
+GLAPI GLboolean APIENTRY glIsProgramNV (GLuint id);
+GLAPI void APIENTRY glLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+GLAPI void APIENTRY glProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glProgramParameters4dvNV (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameters4fvNV (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+GLAPI void APIENTRY glVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glVertexAttrib1dNV (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fNV (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sNV (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sNV (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+#endif /* GL_NV_vertex_program */
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif /* GL_NV_vertex_program1_1 */
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif /* GL_NV_vertex_program2 */
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+#endif /* GL_NV_vertex_program2_option */
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+#endif /* GL_NV_vertex_program3 */
+
+#ifndef GL_NV_vertex_program4
+#define GL_NV_vertex_program4 1
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_NV_vertex_program4 */
+
+#ifndef GL_NV_video_capture
+#define GL_NV_video_capture 1
+#define GL_VIDEO_BUFFER_NV 0x9020
+#define GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define GL_FIELD_UPPER_NV 0x9022
+#define GL_FIELD_LOWER_NV 0x9023
+#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define GL_PARTIAL_SUCCESS_NV 0x902E
+#define GL_SUCCESS_NV 0x902F
+#define GL_FAILURE_NV 0x9030
+#define GL_YCBYCR8_422_NV 0x9031
+#define GL_YCBAYCR8A_4224_NV 0x9032
+#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+typedef void (APIENTRYP PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+typedef GLenum (APIENTRYP PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glBindVideoCaptureStreamBufferNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+GLAPI void APIENTRY glBindVideoCaptureStreamTextureNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+GLAPI void APIENTRY glEndVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glGetVideoCaptureivNV (GLuint video_capture_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+GLAPI GLenum APIENTRY glVideoCaptureNV (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+GLAPI void APIENTRY glVideoCaptureStreamParameterivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#endif
+#endif /* GL_NV_video_capture */
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+#endif /* GL_OML_interlace */
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+#endif /* GL_OML_resample */
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+#endif /* GL_OML_subsample */
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI 0x1A219
+#define GL_CLIP_NEAR_HINT_PGI 0x1A220
+#define GL_CLIP_FAR_HINT_PGI 0x1A221
+#define GL_WIDE_LINE_HINT_PGI 0x1A222
+#define GL_BACK_NORMALS_HINT_PGI 0x1A223
+typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glHintPGI (GLenum target, GLint mode);
+#endif
+#endif /* GL_PGI_misc_hints */
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+#define GL_VERTEX_DATA_HINT_PGI 0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI 0x1A22D
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#endif /* GL_PGI_vertex_hints */
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+#endif /* GL_REND_screen_coordinates */
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#define GL_RGBA_DXT5_S3TC 0x83A4
+#define GL_RGBA4_DXT5_S3TC 0x83A5
+#endif /* GL_S3_s3tc */
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS 0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+#endif /* GL_SGIS_detail_texture */
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+#define GL_FOG_FUNC_SGIS 0x812A
+#define GL_FOG_FUNC_POINTS_SGIS 0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C
+typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogFuncSGIS (GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *points);
+#endif
+#endif /* GL_SGIS_fog_function */
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+#endif /* GL_SGIS_generate_mipmap */
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskSGIS (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternSGIS (GLenum pattern);
+#endif
+#endif /* GL_SGIS_multisample */
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+#define GL_PIXEL_TEXTURE_SGIS 0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_SGIS_pixel_texture */
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+#endif /* GL_SGIS_point_line_texgen */
+
+#ifndef GL_SGIS_point_parameters
+#define GL_SGIS_point_parameters 1
+#define GL_POINT_SIZE_MIN_SGIS 0x8126
+#define GL_POINT_SIZE_MAX_SGIS 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define GL_DISTANCE_ATTENUATION_SGIS 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvSGIS (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_SGIS_point_parameters */
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+#define GL_LINEAR_SHARPEN_SGIS 0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+#endif /* GL_SGIS_sharpen_texture */
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133
+#define GL_TEXTURE_4D_SGIS 0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS 0x8135
+#define GL_TEXTURE_4DSIZE_SGIS 0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS 0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS 0x814F
+typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_SGIS_texture4D */
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+#endif /* GL_SGIS_texture_border_clamp */
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_SGIS_texture_color_mask 1
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF
+typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+#endif /* GL_SGIS_texture_color_mask */
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+#endif /* GL_SGIS_texture_edge_clamp */
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+#define GL_FILTER4_SGIS 0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147
+typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);
+typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights);
+GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+#endif /* GL_SGIS_texture_filter4 */
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+#endif /* GL_SGIS_texture_lod */
+
+#ifndef GL_SGIS_texture_select
+#define GL_SGIS_texture_select 1
+#define GL_DUAL_ALPHA4_SGIS 0x8110
+#define GL_DUAL_ALPHA8_SGIS 0x8111
+#define GL_DUAL_ALPHA12_SGIS 0x8112
+#define GL_DUAL_ALPHA16_SGIS 0x8113
+#define GL_DUAL_LUMINANCE4_SGIS 0x8114
+#define GL_DUAL_LUMINANCE8_SGIS 0x8115
+#define GL_DUAL_LUMINANCE12_SGIS 0x8116
+#define GL_DUAL_LUMINANCE16_SGIS 0x8117
+#define GL_DUAL_INTENSITY4_SGIS 0x8118
+#define GL_DUAL_INTENSITY8_SGIS 0x8119
+#define GL_DUAL_INTENSITY12_SGIS 0x811A
+#define GL_DUAL_INTENSITY16_SGIS 0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D
+#define GL_QUAD_ALPHA4_SGIS 0x811E
+#define GL_QUAD_ALPHA8_SGIS 0x811F
+#define GL_QUAD_LUMINANCE4_SGIS 0x8120
+#define GL_QUAD_LUMINANCE8_SGIS 0x8121
+#define GL_QUAD_INTENSITY4_SGIS 0x8122
+#define GL_QUAD_INTENSITY8_SGIS 0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125
+#endif /* GL_SGIS_texture_select */
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+#define GL_ASYNC_MARKER_SGIX 0x8329
+typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);
+typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);
+typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint marker);
+GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *markerp);
+GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *markerp);
+GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei range);
+GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range);
+GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint marker);
+#endif
+#endif /* GL_SGIX_async */
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+#endif /* GL_SGIX_async_histogram */
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+#endif /* GL_SGIX_async_pixel */
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_SGIX_calligraphic_fragment 1
+#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183
+#endif /* GL_SGIX_calligraphic_fragment */
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F
+#endif /* GL_SGIX_clipmap */
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+#endif /* GL_SGIX_convolution_accuracy */
+
+#ifndef GL_SGIX_depth_pass_instrument
+#define GL_SGIX_depth_pass_instrument 1
+#endif /* GL_SGIX_depth_pass_instrument */
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+#endif /* GL_SGIX_depth_texture */
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushRasterSGIX (void);
+#endif
+#endif /* GL_SGIX_flush_raster */
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+#endif /* GL_SGIX_fog_offset */
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_SGIX_fragment_lighting 1
+#define GL_FRAGMENT_LIGHTING_SGIX 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405
+#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406
+#define GL_LIGHT_ENV_MODE_SGIX 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define GL_FRAGMENT_LIGHT0_SGIX 0x840C
+#define GL_FRAGMENT_LIGHT1_SGIX 0x840D
+#define GL_FRAGMENT_LIGHT2_SGIX 0x840E
+#define GL_FRAGMENT_LIGHT3_SGIX 0x840F
+#define GL_FRAGMENT_LIGHT4_SGIX 0x8410
+#define GL_FRAGMENT_LIGHT5_SGIX 0x8411
+#define GL_FRAGMENT_LIGHT6_SGIX 0x8412
+#define GL_FRAGMENT_LIGHT7_SGIX 0x8413
+typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum face, GLenum mode);
+GLAPI void APIENTRY glFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightiSGIX (GLenum light, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params);
+GLAPI void APIENTRY glLightEnviSGIX (GLenum pname, GLint param);
+#endif
+#endif /* GL_SGIX_fragment_lighting */
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+#define GL_FRAMEZOOM_SGIX 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D
+typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameZoomSGIX (GLint factor);
+#endif
+#endif /* GL_SGIX_framezoom */
+
+#ifndef GL_SGIX_igloo_interface
+#define GL_SGIX_igloo_interface 1
+typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const void *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum pname, const void *params);
+#endif
+#endif /* GL_SGIX_igloo_interface */
+
+#ifndef GL_SGIX_instruments
+#define GL_SGIX_instruments 1
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181
+typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);
+typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);
+typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetInstrumentsSGIX (void);
+GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei size, GLint *buffer);
+GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *marker_p);
+GLAPI void APIENTRY glReadInstrumentsSGIX (GLint marker);
+GLAPI void APIENTRY glStartInstrumentsSGIX (void);
+GLAPI void APIENTRY glStopInstrumentsSGIX (GLint marker);
+#endif
+#endif /* GL_SGIX_instruments */
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+#define GL_INTERLACE_SGIX 0x8094
+#endif /* GL_SGIX_interlace */
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+#define GL_IR_INSTRUMENT1_SGIX 0x817F
+#endif /* GL_SGIX_ir_instrument1 */
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+#define GL_LIST_PRIORITY_SGIX 0x8182
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params);
+GLAPI void APIENTRY glListParameterfSGIX (GLuint list, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glListParameteriSGIX (GLuint list, GLenum pname, GLint param);
+GLAPI void APIENTRY glListParameterivSGIX (GLuint list, GLenum pname, const GLint *params);
+#endif
+#endif /* GL_SGIX_list_priority */
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+#define GL_PIXEL_TEX_GEN_SGIX 0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B
+typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenSGIX (GLenum mode);
+#endif
+#endif /* GL_SGIX_pixel_texture */
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_SGIX_pixel_tiles 1
+#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140
+#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141
+#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142
+#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143
+#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144
+#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145
+#endif /* GL_SGIX_pixel_tiles */
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_SGIX_polynomial_ffd 1
+#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001
+#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002
+#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194
+#define GL_TEXTURE_DEFORMATION_SGIX 0x8195
+#define GL_DEFORMATIONS_MASK_SGIX 0x8196
+#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+GLAPI void APIENTRY glDeformSGIX (GLbitfield mask);
+GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield mask);
+#endif
+#endif /* GL_SGIX_polynomial_ffd */
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+#define GL_REFERENCE_PLANE_SGIX 0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E
+typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation);
+#endif
+#endif /* GL_SGIX_reference_plane */
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+#define GL_PACK_RESAMPLE_SGIX 0x842C
+#define GL_UNPACK_RESAMPLE_SGIX 0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX 0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#endif /* GL_SGIX_resample */
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SGIX_scalebias_hint 1
+#define GL_SCALEBIAS_HINT_SGIX 0x8322
+#endif /* GL_SGIX_scalebias_hint */
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+#endif /* GL_SGIX_shadow */
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+#endif /* GL_SGIX_shadow_ambient */
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+#define GL_SPRITE_SGIX 0x8148
+#define GL_SPRITE_MODE_SGIX 0x8149
+#define GL_SPRITE_AXIS_SGIX 0x814A
+#define GL_SPRITE_TRANSLATION_SGIX 0x814B
+#define GL_SPRITE_AXIAL_SGIX 0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum pname, const GLint *params);
+#endif
+#endif /* GL_SGIX_sprite */
+
+#ifndef GL_SGIX_subsample
+#define GL_SGIX_subsample 1
+#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0
+#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1
+#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2
+#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3
+#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4
+#endif /* GL_SGIX_subsample */
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTagSampleBufferSGIX (void);
+#endif
+#endif /* GL_SGIX_tag_sample_buffer */
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE
+#endif /* GL_SGIX_texture_add_env */
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190
+#endif /* GL_SGIX_texture_lod_bias */
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif /* GL_SGIX_texture_multi_buffer */
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif /* GL_SGIX_texture_scale_bias */
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+#endif /* GL_SGIX_vertex_preclip */
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+#define GL_YCRCB_422_SGIX 0x81BB
+#define GL_YCRCB_444_SGIX 0x81BC
+#endif /* GL_SGIX_ycrcb */
+
+#ifndef GL_SGIX_ycrcb_subsample
+#define GL_SGIX_ycrcb_subsample 1
+#endif /* GL_SGIX_ycrcb_subsample */
+
+#ifndef GL_SGIX_ycrcba
+#define GL_SGIX_ycrcba 1
+#define GL_YCRCB_SGIX 0x8318
+#define GL_YCRCBA_SGIX 0x8319
+#endif /* GL_SGIX_ycrcba */
+
+#ifndef GL_SGI_color_matrix
+#define GL_SGI_color_matrix 1
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif /* GL_SGI_color_matrix */
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTableSGI (GLenum target, GLenum format, GLenum type, void *table);
+GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params);
+#endif
+#endif /* GL_SGI_color_table */
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+#endif /* GL_SGI_texture_color_table */
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFinishTextureSUNX (void);
+#endif
+#endif /* GL_SUNX_constant_data */
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+#define GL_WRAP_BORDER_SUN 0x81D4
+#endif /* GL_SUN_convolution_border_modes */
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint factor);
+GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat factor);
+GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble factor);
+GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint factor);
+#endif
+#endif /* GL_SUN_global_alpha */
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+#endif /* GL_SUN_mesh_array */
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+#define GL_SLICE_ACCUM_SUN 0x85CC
+#endif /* GL_SUN_slice_accum */
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+#define GL_RESTART_SUN 0x0001
+#define GL_REPLACE_MIDDLE_SUN 0x0002
+#define GL_REPLACE_OLDEST_SUN 0x0003
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint code);
+GLAPI void APIENTRY glReplacementCodeusSUN (GLushort code);
+GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte code);
+GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *code);
+GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *code);
+GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *code);
+GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum type, GLsizei stride, const void **pointer);
+#endif
+#endif /* GL_SUN_triangle_list */
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+#endif /* GL_SUN_vertex */
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+#endif /* GL_WIN_phong_shading */
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+#endif /* GL_WIN_specular_fog */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Client/ThirdParty/SDL2/SDL_opengles.h b/Client/ThirdParty/SDL2/SDL_opengles.h
new file mode 100644
index 0000000..7ebf4cc
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengles.h
@@ -0,0 +1,39 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengles.h
+ *
+ * This is a simple file to encapsulate the OpenGL ES 1.X API headers.
+ */
+#include "SDL_config.h"
+
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+#else
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
diff --git a/Client/ThirdParty/SDL2/SDL_opengles2.h b/Client/ThirdParty/SDL2/SDL_opengles2.h
new file mode 100644
index 0000000..ce114ae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengles2.h
@@ -0,0 +1,52 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengles2.h
+ *
+ * This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
+ */
+#include "SDL_config.h"
+
+#ifndef _MSC_VER
+
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES2/gl.h>
+#include <OpenGLES/ES2/glext.h>
+#else
+#include <GLES2/gl2platform.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#endif
+
+#else /* _MSC_VER */
+
+/* OpenGL ES2 headers for Visual Studio */
+#include "SDL_opengles2_khrplatform.h"
+#include "SDL_opengles2_gl2platform.h"
+#include "SDL_opengles2_gl2.h"
+#include "SDL_opengles2_gl2ext.h"
+
+#endif /* _MSC_VER */
+
+#ifndef APIENTRY
+#define APIENTRY GL_APIENTRY
+#endif
diff --git a/Client/ThirdParty/SDL2/SDL_opengles2_gl2.h b/Client/ThirdParty/SDL2/SDL_opengles2_gl2.h
new file mode 100644
index 0000000..c62fb0a
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengles2_gl2.h
@@ -0,0 +1,621 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */
+
+/*#include <GLES2/gl2platform.h>*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+
+/* CullFaceMode */
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+/* GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+/* GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+
+/* GetTextureParameter */
+/* GL_TEXTURE_MAG_FILTER */
+/* GL_TEXTURE_MIN_FILTER */
+/* GL_TEXTURE_WRAP_S */
+/* GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelType */
+/* GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+/* TextureTarget */
+/* GL_TEXTURE_2D */
+#define GL_TEXTURE 0x1702
+
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+
+#define GL_NONE 0
+
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
+
diff --git a/Client/ThirdParty/SDL2/SDL_opengles2_gl2ext.h b/Client/ThirdParty/SDL2/SDL_opengles2_gl2ext.h
new file mode 100644
index 0000000..e8ca8b1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengles2_gl2ext.h
@@ -0,0 +1,2050 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 22801 $ on $Date:: 2013-08-21 03:20:48 -0700 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+# define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* New types shared by several extensions */
+
+#ifndef __gl3_h_
+/* These are defined with respect to <inttypes.h> in the
+ * Apple extension spec, but they are also used by non-APPLE
+ * extensions, and in the Khronos header we use the Khronos
+ * portable types in khrplatform.h, which must be defined.
+ */
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+#endif
+
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES 0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+/* GLeglImageOES defined in GL_OES_EGL_image already. */
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT 0x1405
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_ALPHA8_OES 0x803C
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+/* reuse GL_DEPTH_COMPONENT24_OES */
+/* reuse GL_DEPTH24_STENCIL8_OES */
+/* reuse GL_DEPTH_COMPONENT32_OES */
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGB565_OES 0x8D62
+/* reuse GL_RGB8_OES */
+/* reuse GL_RGBA8_OES */
+/* reuse GL_RGB10_EXT */
+/* reuse GL_RGB10_A2_EXT */
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA8_OES 0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_SAMPLER_3D_OES 0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#endif
+
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES 0x8D61
+#endif
+
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_INT_10_10_10_2_OES 0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension tokens
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+typedef void (GL_APIENTRYP GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define GL_DEBUG_SOURCE_API_KHR 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define GL_BUFFER_KHR 0x82E0
+#define GL_SHADER_KHR 0x82E1
+#define GL_PROGRAM_KHR 0x82E2
+#define GL_QUERY_KHR 0x82E3
+/* PROGRAM_PIPELINE only in GL */
+#define GL_SAMPLER_KHR 0x82E6
+/* DISPLAY_LIST only in GL */
+#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define GL_DEBUG_OUTPUT_KHR 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define GL_STACK_OVERFLOW_KHR 0x0503
+#define GL_STACK_UNDERFLOW_KHR 0x0504
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD 0x87F9
+#define GL_3DC_XY_AMD 0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD 0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD 0x8740
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_PROGRAM_BINARY_ANGLE 0x93A6
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+/* No new tokens introduced by this extension. */
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE 0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+
+#define GL_SYNC_OBJECT_APPLE 0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define GL_OBJECT_TYPE_APPLE 0x9112
+#define GL_SYNC_CONDITION_APPLE 0x9113
+#define GL_SYNC_STATUS_APPLE 0x9114
+#define GL_SYNC_FLAGS_APPLE 0x9115
+#define GL_SYNC_FENCE_APPLE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE 0x9118
+#define GL_SIGNALED_APPLE 0x9119
+#define GL_ALREADY_SIGNALED_APPLE 0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define GL_CONDITION_SATISFIED_APPLE 0x911C
+#define GL_WAIT_FAILED_APPLE 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_RG16F_EXT 0x822F
+#define GL_R16F_EXT 0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#endif
+
+/* GL_EXT_debug_marker */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+#endif
+
+#ifndef GL_EXT_disjoint_timer_query
+#define GL_QUERY_COUNTER_BITS_EXT 0x8864
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#define GL_TIMESTAMP_EXT 0x8E28
+#define GL_GPU_DISJOINT_EXT 0x8FBB
+#endif
+
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define GL_DRAW_BUFFER0_EXT 0x8825
+#define GL_DRAW_BUFFER1_EXT 0x8826
+#define GL_DRAW_BUFFER2_EXT 0x8827
+#define GL_DRAW_BUFFER3_EXT 0x8828
+#define GL_DRAW_BUFFER4_EXT 0x8829
+#define GL_DRAW_BUFFER5_EXT 0x882A
+#define GL_DRAW_BUFFER6_EXT 0x882B
+#define GL_DRAW_BUFFER7_EXT 0x882C
+#define GL_DRAW_BUFFER8_EXT 0x882D
+#define GL_DRAW_BUFFER9_EXT 0x882E
+#define GL_DRAW_BUFFER10_EXT 0x882F
+#define GL_DRAW_BUFFER11_EXT 0x8830
+#define GL_DRAW_BUFFER12_EXT 0x8831
+#define GL_DRAW_BUFFER13_EXT 0x8832
+#define GL_DRAW_BUFFER14_EXT 0x8833
+#define GL_DRAW_BUFFER15_EXT 0x8834
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#endif
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+/* reuse GL_NO_ERROR */
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#endif
+
+/* GL_EXT_shader_texture_lod */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#endif
+
+/* GL_EXT_sRGB_write_control */
+#ifndef GL_EXT_sRGB_write_control
+#define GL_EXT_sRGB_write_control 1
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_RED_EXT 0x1903
+#define GL_RG_EXT 0x8227
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#endif
+
+/* GL_EXT_texture_sRGB_decode */
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGB32F_EXT 0x8815
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+/* reuse GL_RGBA16F_EXT */
+/* reuse GL_RGB16F_EXT */
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGB10_EXT 0x8052
+#define GL_BGRA8_EXT 0x93A1
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#define GL_R32F_EXT 0x822E
+#define GL_RG32F_EXT 0x8230
+#define GL_R16F_EXT 0x822D
+#define GL_RG16F_EXT 0x822F
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_SHADER_BINARY_DMP 0x9250
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG 0x8C0A
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_SAMPLES_NV 0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV 0x00008000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define GL_DRAW_BUFFER0_NV 0x8825
+#define GL_DRAW_BUFFER1_NV 0x8826
+#define GL_DRAW_BUFFER2_NV 0x8827
+#define GL_DRAW_BUFFER3_NV 0x8828
+#define GL_DRAW_BUFFER4_NV 0x8829
+#define GL_DRAW_BUFFER5_NV 0x882A
+#define GL_DRAW_BUFFER6_NV 0x882B
+#define GL_DRAW_BUFFER7_NV 0x882C
+#define GL_DRAW_BUFFER8_NV 0x882D
+#define GL_DRAW_BUFFER9_NV 0x882E
+#define GL_DRAW_BUFFER10_NV 0x882F
+#define GL_DRAW_BUFFER11_NV 0x8830
+#define GL_DRAW_BUFFER12_NV 0x8831
+#define GL_DRAW_BUFFER13_NV 0x8832
+#define GL_DRAW_BUFFER14_NV 0x8833
+#define GL_DRAW_BUFFER15_NV 0x8834
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+#endif
+
+/* GL_NV_draw_instanced */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_NV 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56
+#define GL_MAX_SAMPLES_NV 0x8D57
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_READ_BUFFER_NV 0x0C02
+#endif
+
+/* GL_NV_read_buffer_front */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_SLUMINANCE_NV 0x8C46
+#define GL_SLUMINANCE_ALPHA_NV 0x8C44
+#define GL_SRGB8_NV 0x8C41
+#define GL_SLUMINANCE8_NV 0x8C47
+#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+#define GL_ETC1_SRGB8_NV 0x88EE
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_TEXTURE_BORDER_COLOR_NV 0x1004
+#define GL_CLAMP_TO_BORDER_NV 0x812D
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_npot_2D_mipmap */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_ALPHA_TEST_QCOM 0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM 0x0BC2
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+#endif
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_SHADER_BINARY_VIV 0x8FC4
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid **params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid **params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_OES_surfaceless_context 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension functions
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void);
+GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, GLvoid **params);
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif
+
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#endif
+
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+#ifndef GL_APPLE_copy_texture_levels
+#define GL_APPLE_copy_texture_levels 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+#define GL_APPLE_sync 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_ARM_mali_program_binary 1
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+/* GL_EXT_debug_marker */
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+#ifndef GL_EXT_disjoint_timer_query
+#define GL_EXT_disjoint_timer_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#endif /* GL_EXT_disjoint_timer_query */
+
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
+#endif /* GL_EXT_draw_buffers */
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_EXT_map_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_EXT_multiview_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index);
+GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+/* All entry points also exist in GL_EXT_disjoint_timer_query */
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#endif
+
+/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_IMG_texture_compression_pvrtc2 1
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_NV_draw_instanced */
+#ifndef GL_NV_draw_instanced
+#define GL_NV_draw_instanced 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_NV_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_NV_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+#ifndef GL_NV_generate_mipmap_sRGB
+#define GL_NV_generate_mipmap_sRGB 1
+#endif
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_NV_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#endif
+
+/* GL_NV_read_buffer_front */
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif
+
+/* GL_NV_read_depth */
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif
+
+/* GL_NV_read_depth_stencil */
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif
+
+/* GL_NV_read_stencil */
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_NV_shadow_samplers_array 1
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_NV_shadow_samplers_cube 1
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_NV_sRGB_formats 1
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_NV_texture_border_clamp 1
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif
+
+/* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_QCOM_binning_control 1
+#endif
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_opengles2_gl2platform.h b/Client/ThirdParty/SDL2/SDL_opengles2_gl2platform.h
new file mode 100644
index 0000000..c325686
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengles2_gl2platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+/*#include <KHR/khrplatform.h>*/
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_opengles2_khrplatform.h b/Client/ThirdParty/SDL2/SDL_opengles2_khrplatform.h
new file mode 100644
index 0000000..c9e6f17
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_opengles2_khrplatform.h
@@ -0,0 +1,282 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_pixels.h b/Client/ThirdParty/SDL2/SDL_pixels.h
new file mode 100644
index 0000000..a6d464c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_pixels.h
@@ -0,0 +1,613 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_pixels.h
+ *
+ * Header for the enumerated pixel format definitions.
+ */
+
+#ifndef SDL_pixels_h_
+#define SDL_pixels_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_endian.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Transparency definitions
+ *
+ * These define alpha as the opacity of a surface.
+ */
+/* @{ */
+#define SDL_ALPHA_OPAQUE 255
+#define SDL_ALPHA_TRANSPARENT 0
+/* @} */
+
+/** Pixel type. */
+typedef enum
+{
+ SDL_PIXELTYPE_UNKNOWN,
+ SDL_PIXELTYPE_INDEX1,
+ SDL_PIXELTYPE_INDEX4,
+ SDL_PIXELTYPE_INDEX8,
+ SDL_PIXELTYPE_PACKED8,
+ SDL_PIXELTYPE_PACKED16,
+ SDL_PIXELTYPE_PACKED32,
+ SDL_PIXELTYPE_ARRAYU8,
+ SDL_PIXELTYPE_ARRAYU16,
+ SDL_PIXELTYPE_ARRAYU32,
+ SDL_PIXELTYPE_ARRAYF16,
+ SDL_PIXELTYPE_ARRAYF32
+} SDL_PixelType;
+
+/** Bitmap pixel order, high bit -> low bit. */
+typedef enum
+{
+ SDL_BITMAPORDER_NONE,
+ SDL_BITMAPORDER_4321,
+ SDL_BITMAPORDER_1234
+} SDL_BitmapOrder;
+
+/** Packed component order, high bit -> low bit. */
+typedef enum
+{
+ SDL_PACKEDORDER_NONE,
+ SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDORDER_RGBX,
+ SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDORDER_BGRX,
+ SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDORDER_BGRA
+} SDL_PackedOrder;
+
+/** Array component order, low byte -> high byte. */
+/* !!! FIXME: in 2.1, make these not overlap differently with
+ !!! FIXME: SDL_PACKEDORDER_*, so we can simplify SDL_ISPIXELFORMAT_ALPHA */
+typedef enum
+{
+ SDL_ARRAYORDER_NONE,
+ SDL_ARRAYORDER_RGB,
+ SDL_ARRAYORDER_RGBA,
+ SDL_ARRAYORDER_ARGB,
+ SDL_ARRAYORDER_BGR,
+ SDL_ARRAYORDER_BGRA,
+ SDL_ARRAYORDER_ABGR
+} SDL_ArrayOrder;
+
+/** Packed component layout. */
+typedef enum
+{
+ SDL_PACKEDLAYOUT_NONE,
+ SDL_PACKEDLAYOUT_332,
+ SDL_PACKEDLAYOUT_4444,
+ SDL_PACKEDLAYOUT_1555,
+ SDL_PACKEDLAYOUT_5551,
+ SDL_PACKEDLAYOUT_565,
+ SDL_PACKEDLAYOUT_8888,
+ SDL_PACKEDLAYOUT_2101010,
+ SDL_PACKEDLAYOUT_1010102
+} SDL_PackedLayout;
+
+#define SDL_DEFINE_PIXELFOURCC(A, B, C, D) SDL_FOURCC(A, B, C, D)
+
+#define SDL_DEFINE_PIXELFORMAT(type, order, layout, bits, bytes) \
+ ((1 << 28) | ((type) << 24) | ((order) << 20) | ((layout) << 16) | \
+ ((bits) << 8) | ((bytes) << 0))
+
+#define SDL_PIXELFLAG(X) (((X) >> 28) & 0x0F)
+#define SDL_PIXELTYPE(X) (((X) >> 24) & 0x0F)
+#define SDL_PIXELORDER(X) (((X) >> 20) & 0x0F)
+#define SDL_PIXELLAYOUT(X) (((X) >> 16) & 0x0F)
+#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF)
+#define SDL_BYTESPERPIXEL(X) \
+ (SDL_ISPIXELFORMAT_FOURCC(X) ? \
+ ((((X) == SDL_PIXELFORMAT_YUY2) || \
+ ((X) == SDL_PIXELFORMAT_UYVY) || \
+ ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF))
+
+#define SDL_ISPIXELFORMAT_INDEXED(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
+
+#define SDL_ISPIXELFORMAT_PACKED(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED8) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED16) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32)))
+
+#define SDL_ISPIXELFORMAT_ARRAY(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU8) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU16) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU32) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF16) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF32)))
+
+#define SDL_ISPIXELFORMAT_ALPHA(format) \
+ ((SDL_ISPIXELFORMAT_PACKED(format) && \
+ ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA))) || \
+ (SDL_ISPIXELFORMAT_ARRAY(format) && \
+ ((SDL_PIXELORDER(format) == SDL_ARRAYORDER_ARGB) || \
+ (SDL_PIXELORDER(format) == SDL_ARRAYORDER_RGBA) || \
+ (SDL_PIXELORDER(format) == SDL_ARRAYORDER_ABGR) || \
+ (SDL_PIXELORDER(format) == SDL_ARRAYORDER_BGRA))))
+
+/* The flag is set to 1 because 0x1? is not in the printable ASCII range */
+#define SDL_ISPIXELFORMAT_FOURCC(format) \
+ ((format) && (SDL_PIXELFLAG(format) != 1))
+
+/* Note: If you modify this list, update SDL_GetPixelFormatName() */
+typedef enum
+{
+ SDL_PIXELFORMAT_UNKNOWN,
+ SDL_PIXELFORMAT_INDEX1LSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_4321, 0,
+ 1, 0),
+ SDL_PIXELFORMAT_INDEX1MSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,
+ 1, 0),
+ SDL_PIXELFORMAT_INDEX4LSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,
+ 4, 0),
+ SDL_PIXELFORMAT_INDEX4MSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_1234, 0,
+ 4, 0),
+ SDL_PIXELFORMAT_INDEX8 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0, 8, 1),
+ SDL_PIXELFORMAT_RGB332 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_332, 8, 1),
+ SDL_PIXELFORMAT_XRGB4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_4444, 12, 2),
+ SDL_PIXELFORMAT_RGB444 = SDL_PIXELFORMAT_XRGB4444,
+ SDL_PIXELFORMAT_XBGR4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_4444, 12, 2),
+ SDL_PIXELFORMAT_BGR444 = SDL_PIXELFORMAT_XBGR4444,
+ SDL_PIXELFORMAT_XRGB1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_1555, 15, 2),
+ SDL_PIXELFORMAT_RGB555 = SDL_PIXELFORMAT_XRGB1555,
+ SDL_PIXELFORMAT_XBGR1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_1555, 15, 2),
+ SDL_PIXELFORMAT_BGR555 = SDL_PIXELFORMAT_XBGR1555,
+ SDL_PIXELFORMAT_ARGB4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_RGBA4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_ABGR4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_BGRA4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_ARGB1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_1555, 16, 2),
+ SDL_PIXELFORMAT_RGBA5551 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_5551, 16, 2),
+ SDL_PIXELFORMAT_ABGR1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_1555, 16, 2),
+ SDL_PIXELFORMAT_BGRA5551 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_5551, 16, 2),
+ SDL_PIXELFORMAT_RGB565 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_565, 16, 2),
+ SDL_PIXELFORMAT_BGR565 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_565, 16, 2),
+ SDL_PIXELFORMAT_RGB24 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0,
+ 24, 3),
+ SDL_PIXELFORMAT_BGR24 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0,
+ 24, 3),
+ SDL_PIXELFORMAT_XRGB8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_RGB888 = SDL_PIXELFORMAT_XRGB8888,
+ SDL_PIXELFORMAT_RGBX8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_XBGR8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_BGR888 = SDL_PIXELFORMAT_XBGR8888,
+ SDL_PIXELFORMAT_BGRX8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_ARGB8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_RGBA8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_ABGR8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_BGRA8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_ARGB2101010 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_2101010, 32, 4),
+
+ /* Aliases for RGBA byte arrays of color data, for the current platform */
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888,
+ SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888,
+ SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888,
+#else
+ SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888,
+ SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888,
+ SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888,
+#endif
+
+ SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */
+ SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
+ SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */
+ SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),
+ SDL_PIXELFORMAT_YUY2 = /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
+ SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'),
+ SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
+ SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
+ SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
+ SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'),
+ SDL_PIXELFORMAT_NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */
+ SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'),
+ SDL_PIXELFORMAT_NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */
+ SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'),
+ SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */
+ SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ')
+} SDL_PixelFormatEnum;
+
+typedef struct SDL_Color
+{
+ Uint8 r;
+ Uint8 g;
+ Uint8 b;
+ Uint8 a;
+} SDL_Color;
+#define SDL_Colour SDL_Color
+
+typedef struct SDL_Palette
+{
+ int ncolors;
+ SDL_Color *colors;
+ Uint32 version;
+ int refcount;
+} SDL_Palette;
+
+/**
+ * \note Everything in the pixel format structure is read-only.
+ */
+typedef struct SDL_PixelFormat
+{
+ Uint32 format;
+ SDL_Palette *palette;
+ Uint8 BitsPerPixel;
+ Uint8 BytesPerPixel;
+ Uint8 padding[2];
+ Uint32 Rmask;
+ Uint32 Gmask;
+ Uint32 Bmask;
+ Uint32 Amask;
+ Uint8 Rloss;
+ Uint8 Gloss;
+ Uint8 Bloss;
+ Uint8 Aloss;
+ Uint8 Rshift;
+ Uint8 Gshift;
+ Uint8 Bshift;
+ Uint8 Ashift;
+ int refcount;
+ struct SDL_PixelFormat *next;
+} SDL_PixelFormat;
+
+/**
+ * Get the human readable name of a pixel format.
+ *
+ * \param format the pixel format to query
+ * \returns the human readable name of the specified pixel format or
+ * `SDL_PIXELFORMAT_UNKNOWN` if the format isn't recognized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(Uint32 format);
+
+/**
+ * Convert one of the enumerated pixel formats to a bpp value and RGBA masks.
+ *
+ * \param format one of the SDL_PixelFormatEnum values
+ * \param bpp a bits per pixel value; usually 15, 16, or 32
+ * \param Rmask a pointer filled in with the red mask for the format
+ * \param Gmask a pointer filled in with the green mask for the format
+ * \param Bmask a pointer filled in with the blue mask for the format
+ * \param Amask a pointer filled in with the alpha mask for the format
+ * \returns SDL_TRUE on success or SDL_FALSE if the conversion wasn't
+ * possible; call SDL_GetError() for more information.
+ *
+ * \sa SDL_MasksToPixelFormatEnum
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(Uint32 format,
+ int *bpp,
+ Uint32 * Rmask,
+ Uint32 * Gmask,
+ Uint32 * Bmask,
+ Uint32 * Amask);
+
+/**
+ * Convert a bpp value and RGBA masks to an enumerated pixel format.
+ *
+ * This will return `SDL_PIXELFORMAT_UNKNOWN` if the conversion wasn't
+ * possible.
+ *
+ * \param bpp a bits per pixel value; usually 15, 16, or 32
+ * \param Rmask the red mask for the format
+ * \param Gmask the green mask for the format
+ * \param Bmask the blue mask for the format
+ * \param Amask the alpha mask for the format
+ * \returns one of the SDL_PixelFormatEnum values
+ *
+ * \sa SDL_PixelFormatEnumToMasks
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp,
+ Uint32 Rmask,
+ Uint32 Gmask,
+ Uint32 Bmask,
+ Uint32 Amask);
+
+/**
+ * Create an SDL_PixelFormat structure corresponding to a pixel format.
+ *
+ * Returned structure may come from a shared global cache (i.e. not newly
+ * allocated), and hence should not be modified, especially the palette. Weird
+ * errors such as `Blit combination not supported` may occur.
+ *
+ * \param pixel_format one of the SDL_PixelFormatEnum values
+ * \returns the new SDL_PixelFormat structure or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_FreeFormat
+ */
+extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_AllocFormat(Uint32 pixel_format);
+
+/**
+ * Free an SDL_PixelFormat structure allocated by SDL_AllocFormat().
+ *
+ * \param format the SDL_PixelFormat structure to free
+ *
+ * \sa SDL_AllocFormat
+ */
+extern DECLSPEC void SDLCALL SDL_FreeFormat(SDL_PixelFormat *format);
+
+/**
+ * Create a palette structure with the specified number of color entries.
+ *
+ * The palette entries are initialized to white.
+ *
+ * \param ncolors represents the number of color entries in the color palette
+ * \returns a new SDL_Palette structure on success or NULL on failure (e.g. if
+ * there wasn't enough memory); call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_FreePalette
+ */
+extern DECLSPEC SDL_Palette *SDLCALL SDL_AllocPalette(int ncolors);
+
+/**
+ * Set the palette for a pixel format structure.
+ *
+ * \param format the SDL_PixelFormat structure that will use the palette
+ * \param palette the SDL_Palette structure that will be used
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocPalette
+ * \sa SDL_FreePalette
+ */
+extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format,
+ SDL_Palette *palette);
+
+/**
+ * Set a range of colors in a palette.
+ *
+ * \param palette the SDL_Palette structure to modify
+ * \param colors an array of SDL_Color structures to copy into the palette
+ * \param firstcolor the index of the first palette entry to modify
+ * \param ncolors the number of entries to modify
+ * \returns 0 on success or a negative error code if not all of the colors
+ * could be set; call SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocPalette
+ * \sa SDL_CreateRGBSurface
+ */
+extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette,
+ const SDL_Color * colors,
+ int firstcolor, int ncolors);
+
+/**
+ * Free a palette created with SDL_AllocPalette().
+ *
+ * \param palette the SDL_Palette structure to be freed
+ *
+ * \sa SDL_AllocPalette
+ */
+extern DECLSPEC void SDLCALL SDL_FreePalette(SDL_Palette * palette);
+
+/**
+ * Map an RGB triple to an opaque pixel value for a given pixel format.
+ *
+ * This function maps the RGB color value to the specified pixel format and
+ * returns the pixel value best approximating the given RGB color value for
+ * the given pixel format.
+ *
+ * If the format has a palette (8-bit) the index of the closest matching color
+ * in the palette will be returned.
+ *
+ * If the specified pixel format has an alpha component it will be returned as
+ * all 1 bits (fully opaque).
+ *
+ * If the pixel format bpp (color depth) is less than 32-bpp then the unused
+ * upper bits of the return value can safely be ignored (e.g., with a 16-bpp
+ * format the return value can be assigned to a Uint16, and similarly a Uint8
+ * for an 8-bpp format).
+ *
+ * \param format an SDL_PixelFormat structure describing the pixel format
+ * \param r the red component of the pixel in the range 0-255
+ * \param g the green component of the pixel in the range 0-255
+ * \param b the blue component of the pixel in the range 0-255
+ * \returns a pixel value
+ *
+ * \sa SDL_GetRGB
+ * \sa SDL_GetRGBA
+ * \sa SDL_MapRGBA
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format,
+ Uint8 r, Uint8 g, Uint8 b);
+
+/**
+ * Map an RGBA quadruple to a pixel value for a given pixel format.
+ *
+ * This function maps the RGBA color value to the specified pixel format and
+ * returns the pixel value best approximating the given RGBA color value for
+ * the given pixel format.
+ *
+ * If the specified pixel format has no alpha component the alpha value will
+ * be ignored (as it will be in formats with a palette).
+ *
+ * If the format has a palette (8-bit) the index of the closest matching color
+ * in the palette will be returned.
+ *
+ * If the pixel format bpp (color depth) is less than 32-bpp then the unused
+ * upper bits of the return value can safely be ignored (e.g., with a 16-bpp
+ * format the return value can be assigned to a Uint16, and similarly a Uint8
+ * for an 8-bpp format).
+ *
+ * \param format an SDL_PixelFormat structure describing the format of the
+ * pixel
+ * \param r the red component of the pixel in the range 0-255
+ * \param g the green component of the pixel in the range 0-255
+ * \param b the blue component of the pixel in the range 0-255
+ * \param a the alpha component of the pixel in the range 0-255
+ * \returns a pixel value
+ *
+ * \sa SDL_GetRGB
+ * \sa SDL_GetRGBA
+ * \sa SDL_MapRGB
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format,
+ Uint8 r, Uint8 g, Uint8 b,
+ Uint8 a);
+
+/**
+ * Get RGB values from a pixel in the specified format.
+ *
+ * This function uses the entire 8-bit [0..255] range when converting color
+ * components from pixel formats with less than 8-bits per RGB component
+ * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff,
+ * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]).
+ *
+ * \param pixel a pixel value
+ * \param format an SDL_PixelFormat structure describing the format of the
+ * pixel
+ * \param r a pointer filled in with the red component
+ * \param g a pointer filled in with the green component
+ * \param b a pointer filled in with the blue component
+ *
+ * \sa SDL_GetRGBA
+ * \sa SDL_MapRGB
+ * \sa SDL_MapRGBA
+ */
+extern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel,
+ const SDL_PixelFormat * format,
+ Uint8 * r, Uint8 * g, Uint8 * b);
+
+/**
+ * Get RGBA values from a pixel in the specified format.
+ *
+ * This function uses the entire 8-bit [0..255] range when converting color
+ * components from pixel formats with less than 8-bits per RGB component
+ * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff,
+ * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]).
+ *
+ * If the surface has no alpha component, the alpha will be returned as 0xff
+ * (100% opaque).
+ *
+ * \param pixel a pixel value
+ * \param format an SDL_PixelFormat structure describing the format of the
+ * pixel
+ * \param r a pointer filled in with the red component
+ * \param g a pointer filled in with the green component
+ * \param b a pointer filled in with the blue component
+ * \param a a pointer filled in with the alpha component
+ *
+ * \sa SDL_GetRGB
+ * \sa SDL_MapRGB
+ * \sa SDL_MapRGBA
+ */
+extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel,
+ const SDL_PixelFormat * format,
+ Uint8 * r, Uint8 * g, Uint8 * b,
+ Uint8 * a);
+
+/**
+ * Calculate a 256 entry gamma ramp for a gamma value.
+ *
+ * \param gamma a gamma value where 0.0 is black and 1.0 is identity
+ * \param ramp an array of 256 values filled in with the gamma ramp
+ *
+ * \sa SDL_SetWindowGammaRamp
+ */
+extern DECLSPEC void SDLCALL SDL_CalculateGammaRamp(float gamma, Uint16 * ramp);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_pixels_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_platform.h b/Client/ThirdParty/SDL2/SDL_platform.h
new file mode 100644
index 0000000..1516da3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_platform.h
@@ -0,0 +1,233 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_platform.h
+ *
+ * Try to get a standard set of platform defines.
+ */
+
+#ifndef SDL_platform_h_
+#define SDL_platform_h_
+
+#if defined(_AIX)
+#undef __AIX__
+#define __AIX__ 1
+#endif
+#if defined(__HAIKU__)
+#undef __HAIKU__
+#define __HAIKU__ 1
+#endif
+#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
+#undef __BSDI__
+#define __BSDI__ 1
+#endif
+#if defined(_arch_dreamcast)
+#undef __DREAMCAST__
+#define __DREAMCAST__ 1
+#endif
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#undef __FREEBSD__
+#define __FREEBSD__ 1
+#endif
+#if defined(hpux) || defined(__hpux) || defined(__hpux__)
+#undef __HPUX__
+#define __HPUX__ 1
+#endif
+#if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE)
+#undef __IRIX__
+#define __IRIX__ 1
+#endif
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+#undef __LINUX__
+#define __LINUX__ 1
+#endif
+#if defined(ANDROID) || defined(__ANDROID__)
+#undef __ANDROID__
+#undef __LINUX__ /* do we need to do this? */
+#define __ANDROID__ 1
+#endif
+
+#if defined(__APPLE__)
+/* lets us know what version of Mac OS X we're compiling on */
+#include "AvailabilityMacros.h"
+#include "TargetConditionals.h"
+
+/* Fix building with older SDKs that don't define these
+ See this for more information:
+ https://stackoverflow.com/questions/12132933/preprocessor-macro-for-os-x-targets
+*/
+#ifndef TARGET_OS_MACCATALYST
+#define TARGET_OS_MACCATALYST 0
+#endif
+#ifndef TARGET_OS_IOS
+#define TARGET_OS_IOS 0
+#endif
+#ifndef TARGET_OS_IPHONE
+#define TARGET_OS_IPHONE 0
+#endif
+#ifndef TARGET_OS_TV
+#define TARGET_OS_TV 0
+#endif
+#ifndef TARGET_OS_SIMULATOR
+#define TARGET_OS_SIMULATOR 0
+#endif
+
+#if TARGET_OS_TV
+#undef __TVOS__
+#define __TVOS__ 1
+#endif
+#if TARGET_OS_IPHONE
+/* if compiling for iOS */
+#undef __IPHONEOS__
+#define __IPHONEOS__ 1
+#undef __MACOSX__
+#else
+/* if not compiling for iOS */
+#undef __MACOSX__
+#define __MACOSX__ 1
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+# error SDL for Mac OS X only supports deploying on 10.6 and above.
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
+#endif /* TARGET_OS_IPHONE */
+#endif /* defined(__APPLE__) */
+
+#if defined(__NetBSD__)
+#undef __NETBSD__
+#define __NETBSD__ 1
+#endif
+#if defined(__OpenBSD__)
+#undef __OPENBSD__
+#define __OPENBSD__ 1
+#endif
+#if defined(__OS2__) || defined(__EMX__)
+#undef __OS2__
+#define __OS2__ 1
+#endif
+#if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE)
+#undef __OSF__
+#define __OSF__ 1
+#endif
+#if defined(__QNXNTO__)
+#undef __QNXNTO__
+#define __QNXNTO__ 1
+#endif
+#if defined(riscos) || defined(__riscos) || defined(__riscos__)
+#undef __RISCOS__
+#define __RISCOS__ 1
+#endif
+#if defined(__sun) && defined(__SVR4)
+#undef __SOLARIS__
+#define __SOLARIS__ 1
+#endif
+
+#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+/* Try to find out if we're compiling for WinRT or non-WinRT */
+#if defined(_MSC_VER) && defined(__has_include)
+#if __has_include(<winapifamily.h>)
+#define HAVE_WINAPIFAMILY_H 1
+#else
+#define HAVE_WINAPIFAMILY_H 0
+#endif
+
+/* If _USING_V110_SDK71_ is defined it means we are using the Windows XP toolset. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1700 && !_USING_V110_SDK71_) /* _MSC_VER == 1700 for Visual Studio 2012 */
+#define HAVE_WINAPIFAMILY_H 1
+#else
+#define HAVE_WINAPIFAMILY_H 0
+#endif
+
+#if HAVE_WINAPIFAMILY_H
+#include <winapifamily.h>
+#define WINAPI_FAMILY_WINRT (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP))
+#else
+#define WINAPI_FAMILY_WINRT 0
+#endif /* HAVE_WINAPIFAMILY_H */
+
+#if WINAPI_FAMILY_WINRT
+#undef __WINRT__
+#define __WINRT__ 1
+#else
+#undef __WINDOWS__
+#define __WINDOWS__ 1
+#endif
+#endif /* defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) */
+
+#if defined(__WINDOWS__)
+#undef __WIN32__
+#define __WIN32__ 1
+#endif
+#if defined(__PSP__)
+#undef __PSP__
+#define __PSP__ 1
+#endif
+
+/* The NACL compiler defines __native_client__ and __pnacl__
+ * Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi
+ */
+#if defined(__native_client__)
+#undef __LINUX__
+#undef __NACL__
+#define __NACL__ 1
+#endif
+#if defined(__pnacl__)
+#undef __LINUX__
+#undef __PNACL__
+#define __PNACL__ 1
+/* PNACL with newlib supports static linking only */
+#define __SDL_NOGETPROCADDR__
+#endif
+
+#if defined(__vita__)
+#define __VITA__ 1
+#endif
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the name of the platform.
+ *
+ * Here are the names returned for some (but not all) supported platforms:
+ *
+ * - "Windows"
+ * - "Mac OS X"
+ * - "Linux"
+ * - "iOS"
+ * - "Android"
+ *
+ * \returns the name of the platform. If the correct platform name is not
+ * available, returns a string beginning with the text "Unknown".
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetPlatform (void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_platform_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_power.h b/Client/ThirdParty/SDL2/SDL_power.h
new file mode 100644
index 0000000..872be18
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_power.h
@@ -0,0 +1,86 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_power_h_
+#define SDL_power_h_
+
+/**
+ * \file SDL_power.h
+ *
+ * Header for the SDL power management routines.
+ */
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The basic state for the system's power supply.
+ */
+typedef enum
+{
+ SDL_POWERSTATE_UNKNOWN, /**< cannot determine power status */
+ SDL_POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
+ SDL_POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
+ SDL_POWERSTATE_CHARGING, /**< Plugged in, charging battery */
+ SDL_POWERSTATE_CHARGED /**< Plugged in, battery charged */
+} SDL_PowerState;
+
+
+/**
+ * Get the current power supply details.
+ *
+ * You should never take a battery status as absolute truth. Batteries
+ * (especially failing batteries) are delicate hardware, and the values
+ * reported here are best estimates based on what that hardware reports. It's
+ * not uncommon for older batteries to lose stored power much faster than it
+ * reports, or completely drain when reporting it has 20 percent left, etc.
+ *
+ * Battery status can change at any time; if you are concerned with power
+ * state, you should call this function frequently, and perhaps ignore changes
+ * until they seem to be stable for a few seconds.
+ *
+ * It's possible a platform can only report battery percentage or time left
+ * but not both.
+ *
+ * \param secs seconds of battery life left, you can pass a NULL here if you
+ * don't care, will return -1 if we can't determine a value, or
+ * we're not running on a battery
+ * \param pct percentage of battery life left, between 0 and 100, you can pass
+ * a NULL here if you don't care, will return -1 if we can't
+ * determine a value, or we're not running on a battery
+ * \returns an SDL_PowerState enum representing the current battery state.
+ */
+extern DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *secs, int *pct);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_power_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_quit.h b/Client/ThirdParty/SDL2/SDL_quit.h
new file mode 100644
index 0000000..2825050
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_quit.h
@@ -0,0 +1,58 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_quit.h
+ *
+ * Include file for SDL quit event handling.
+ */
+
+#ifndef SDL_quit_h_
+#define SDL_quit_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+/**
+ * \file SDL_quit.h
+ *
+ * An ::SDL_QUIT event is generated when the user tries to close the application
+ * window. If it is ignored or filtered out, the window will remain open.
+ * If it is not ignored or filtered, it is queued normally and the window
+ * is allowed to close. When the window is closed, screen updates will
+ * complete, but have no effect.
+ *
+ * SDL_Init() installs signal handlers for SIGINT (keyboard interrupt)
+ * and SIGTERM (system termination request), if handlers do not already
+ * exist, that generate ::SDL_QUIT events as well. There is no way
+ * to determine the cause of an ::SDL_QUIT event, but setting a signal
+ * handler in your application will override the default generation of
+ * quit events for that signal.
+ *
+ * \sa SDL_Quit()
+ */
+
+/* There are no functions directly affecting the quit event */
+
+#define SDL_QuitRequested() \
+ (SDL_PumpEvents(), (SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUIT,SDL_QUIT) > 0))
+
+#endif /* SDL_quit_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_rect.h b/Client/ThirdParty/SDL2/SDL_rect.h
new file mode 100644
index 0000000..a17ea44
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_rect.h
@@ -0,0 +1,218 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_rect.h
+ *
+ * Header file for SDL_rect definition and management functions.
+ */
+
+#ifndef SDL_rect_h_
+#define SDL_rect_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_pixels.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The structure that defines a point (integer)
+ *
+ * \sa SDL_EnclosePoints
+ * \sa SDL_PointInRect
+ */
+typedef struct SDL_Point
+{
+ int x;
+ int y;
+} SDL_Point;
+
+/**
+ * The structure that defines a point (floating point)
+ *
+ * \sa SDL_EnclosePoints
+ * \sa SDL_PointInRect
+ */
+typedef struct SDL_FPoint
+{
+ float x;
+ float y;
+} SDL_FPoint;
+
+
+/**
+ * A rectangle, with the origin at the upper left (integer).
+ *
+ * \sa SDL_RectEmpty
+ * \sa SDL_RectEquals
+ * \sa SDL_HasIntersection
+ * \sa SDL_IntersectRect
+ * \sa SDL_UnionRect
+ * \sa SDL_EnclosePoints
+ */
+typedef struct SDL_Rect
+{
+ int x, y;
+ int w, h;
+} SDL_Rect;
+
+
+/**
+ * A rectangle, with the origin at the upper left (floating point).
+ */
+typedef struct SDL_FRect
+{
+ float x;
+ float y;
+ float w;
+ float h;
+} SDL_FRect;
+
+
+/**
+ * Returns true if point resides inside a rectangle.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r)
+{
+ return ( (p->x >= r->x) && (p->x < (r->x + r->w)) &&
+ (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Returns true if the rectangle has no area.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
+{
+ return ((!r) || (r->w <= 0) || (r->h <= 0)) ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Returns true if the two rectangles are equal.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_RectEquals(const SDL_Rect *a, const SDL_Rect *b)
+{
+ return (a && b && (a->x == b->x) && (a->y == b->y) &&
+ (a->w == b->w) && (a->h == b->h)) ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Determine whether two rectangles intersect.
+ *
+ * If either pointer is NULL the function will return SDL_FALSE.
+ *
+ * \param A an SDL_Rect structure representing the first rectangle
+ * \param B an SDL_Rect structure representing the second rectangle
+ * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_IntersectRect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasIntersection(const SDL_Rect * A,
+ const SDL_Rect * B);
+
+/**
+ * Calculate the intersection of two rectangles.
+ *
+ * If `result` is NULL then this function will return SDL_FALSE.
+ *
+ * \param A an SDL_Rect structure representing the first rectangle
+ * \param B an SDL_Rect structure representing the second rectangle
+ * \param result an SDL_Rect structure filled in with the intersection of
+ * rectangles `A` and `B`
+ * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasIntersection
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect * A,
+ const SDL_Rect * B,
+ SDL_Rect * result);
+
+/**
+ * Calculate the union of two rectangles.
+ *
+ * \param A an SDL_Rect structure representing the first rectangle
+ * \param B an SDL_Rect structure representing the second rectangle
+ * \param result an SDL_Rect structure filled in with the union of rectangles
+ * `A` and `B`
+ */
+extern DECLSPEC void SDLCALL SDL_UnionRect(const SDL_Rect * A,
+ const SDL_Rect * B,
+ SDL_Rect * result);
+
+/**
+ * Calculate a minimal rectangle enclosing a set of points.
+ *
+ * If `clip` is not NULL then only points inside of the clipping rectangle are
+ * considered.
+ *
+ * \param points an array of SDL_Point structures representing points to be
+ * enclosed
+ * \param count the number of structures in the `points` array
+ * \param clip an SDL_Rect used for clipping or NULL to enclose all points
+ * \param result an SDL_Rect structure filled in with the minimal enclosing
+ * rectangle
+ * \returns SDL_TRUE if any points were enclosed or SDL_FALSE if all the
+ * points were outside of the clipping rectangle.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_EnclosePoints(const SDL_Point * points,
+ int count,
+ const SDL_Rect * clip,
+ SDL_Rect * result);
+
+/**
+ * Calculate the intersection of a rectangle and line segment.
+ *
+ * This function is used to clip a line segment to a rectangle. A line segment
+ * contained entirely within the rectangle or that does not intersect will
+ * remain unchanged. A line segment that crosses the rectangle at either or
+ * both ends will be clipped to the boundary of the rectangle and the new
+ * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary.
+ *
+ * \param rect an SDL_Rect structure representing the rectangle to intersect
+ * \param X1 a pointer to the starting X-coordinate of the line
+ * \param Y1 a pointer to the starting Y-coordinate of the line
+ * \param X2 a pointer to the ending X-coordinate of the line
+ * \param Y2 a pointer to the ending Y-coordinate of the line
+ * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRectAndLine(const SDL_Rect *
+ rect, int *X1,
+ int *Y1, int *X2,
+ int *Y2);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_rect_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_render.h b/Client/ThirdParty/SDL2/SDL_render.h
new file mode 100644
index 0000000..d80f4d3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_render.h
@@ -0,0 +1,1625 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_render.h
+ *
+ * Header file for SDL 2D rendering functions.
+ *
+ * This API supports the following features:
+ * * single pixel points
+ * * single pixel lines
+ * * filled rectangles
+ * * texture images
+ *
+ * The primitives may be drawn in opaque, blended, or additive modes.
+ *
+ * The texture images may be drawn in opaque, blended, or additive modes.
+ * They can have an additional color tint or alpha modulation applied to
+ * them, and may also be stretched with linear interpolation.
+ *
+ * This API is designed to accelerate simple 2D operations. You may
+ * want more functionality such as polygons and particle effects and
+ * in that case you should use SDL's OpenGL/Direct3D support or one
+ * of the many good 3D engines.
+ *
+ * These functions must be called from the main thread.
+ * See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995
+ */
+
+#ifndef SDL_render_h_
+#define SDL_render_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_rect.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Flags used when creating a rendering context
+ */
+typedef enum
+{
+ SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */
+ SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware
+ acceleration */
+ SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronized
+ with the refresh rate */
+ SDL_RENDERER_TARGETTEXTURE = 0x00000008 /**< The renderer supports
+ rendering to texture */
+} SDL_RendererFlags;
+
+/**
+ * Information on the capabilities of a render driver or context.
+ */
+typedef struct SDL_RendererInfo
+{
+ const char *name; /**< The name of the renderer */
+ Uint32 flags; /**< Supported ::SDL_RendererFlags */
+ Uint32 num_texture_formats; /**< The number of available texture formats */
+ Uint32 texture_formats[16]; /**< The available texture formats */
+ int max_texture_width; /**< The maximum texture width */
+ int max_texture_height; /**< The maximum texture height */
+} SDL_RendererInfo;
+
+/**
+ * The scaling mode for a texture.
+ */
+typedef enum
+{
+ SDL_ScaleModeNearest, /**< nearest pixel sampling */
+ SDL_ScaleModeLinear, /**< linear filtering */
+ SDL_ScaleModeBest /**< anisotropic filtering */
+} SDL_ScaleMode;
+
+/**
+ * The access pattern allowed for a texture.
+ */
+typedef enum
+{
+ SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */
+ SDL_TEXTUREACCESS_STREAMING, /**< Changes frequently, lockable */
+ SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
+} SDL_TextureAccess;
+
+/**
+ * The texture channel modulation used in SDL_RenderCopy().
+ */
+typedef enum
+{
+ SDL_TEXTUREMODULATE_NONE = 0x00000000, /**< No modulation */
+ SDL_TEXTUREMODULATE_COLOR = 0x00000001, /**< srcC = srcC * color */
+ SDL_TEXTUREMODULATE_ALPHA = 0x00000002 /**< srcA = srcA * alpha */
+} SDL_TextureModulate;
+
+/**
+ * Flip constants for SDL_RenderCopyEx
+ */
+typedef enum
+{
+ SDL_FLIP_NONE = 0x00000000, /**< Do not flip */
+ SDL_FLIP_HORIZONTAL = 0x00000001, /**< flip horizontally */
+ SDL_FLIP_VERTICAL = 0x00000002 /**< flip vertically */
+} SDL_RendererFlip;
+
+/**
+ * A structure representing rendering state
+ */
+struct SDL_Renderer;
+typedef struct SDL_Renderer SDL_Renderer;
+
+/**
+ * An efficient driver-specific representation of pixel data
+ */
+struct SDL_Texture;
+typedef struct SDL_Texture SDL_Texture;
+
+
+/* Function prototypes */
+
+/**
+ * Get the number of 2D rendering drivers available for the current display.
+ *
+ * A render driver is a set of code that handles rendering and texture
+ * management on a particular display. Normally there is only one, but some
+ * drivers may have several available with different capabilities.
+ *
+ * There may be none if SDL was compiled without render support.
+ *
+ * \returns a number >= 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_GetRenderDriverInfo
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void);
+
+/**
+ * Get info about a specific 2D rendering driver for the current display.
+ *
+ * \param index the index of the driver to query information about
+ * \param info an SDL_RendererInfo structure to be filled with information on
+ * the rendering driver
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_GetNumRenderDrivers
+ */
+extern DECLSPEC int SDLCALL SDL_GetRenderDriverInfo(int index,
+ SDL_RendererInfo * info);
+
+/**
+ * Create a window and default renderer.
+ *
+ * \param width the width of the window
+ * \param height the height of the window
+ * \param window_flags the flags used to create the window (see
+ * SDL_CreateWindow())
+ * \param window a pointer filled with the window, or NULL on error
+ * \param renderer a pointer filled with the renderer, or NULL on error
+ * \returns 0 on success, or -1 on error; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_CreateWindow
+ */
+extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(
+ int width, int height, Uint32 window_flags,
+ SDL_Window **window, SDL_Renderer **renderer);
+
+
+/**
+ * Create a 2D rendering context for a window.
+ *
+ * \param window the window where rendering is displayed
+ * \param index the index of the rendering driver to initialize, or -1 to
+ * initialize the first one supporting the requested flags
+ * \param flags 0, or one or more SDL_RendererFlags OR'd together
+ * \returns a valid rendering context or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSoftwareRenderer
+ * \sa SDL_DestroyRenderer
+ * \sa SDL_GetNumRenderDrivers
+ * \sa SDL_GetRendererInfo
+ */
+extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,
+ int index, Uint32 flags);
+
+/**
+ * Create a 2D software rendering context for a surface.
+ *
+ * Two other API which can be used to create SDL_Renderer:
+ * SDL_CreateRenderer() and SDL_CreateWindowAndRenderer(). These can _also_
+ * create a software renderer, but they are intended to be used with an
+ * SDL_Window as the final destination and not an SDL_Surface.
+ *
+ * \param surface the SDL_Surface structure representing the surface where
+ * rendering is done
+ * \returns a valid rendering context or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_CreateWindowRenderer
+ * \sa SDL_DestroyRenderer
+ */
+extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface * surface);
+
+/**
+ * Get the renderer associated with a window.
+ *
+ * \param window the window to query
+ * \returns the rendering context on success or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ */
+extern DECLSPEC SDL_Renderer * SDLCALL SDL_GetRenderer(SDL_Window * window);
+
+/**
+ * Get information about a rendering context.
+ *
+ * \param renderer the rendering context
+ * \param info an SDL_RendererInfo structure filled with information about the
+ * current renderer
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ */
+extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer * renderer,
+ SDL_RendererInfo * info);
+
+/**
+ * Get the output size in pixels of a rendering context.
+ *
+ * Due to high-dpi displays, you might end up with a rendering context that
+ * has more pixels than the window that contains it, so use this instead of
+ * SDL_GetWindowSize() to decide how much drawing area you have.
+ *
+ * \param renderer the rendering context
+ * \param w an int filled with the width
+ * \param h an int filled with the height
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetRenderer
+ */
+extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer * renderer,
+ int *w, int *h);
+
+/**
+ * Create a texture for a rendering context.
+ *
+ * You can set the texture scaling method by setting
+ * `SDL_HINT_RENDER_SCALE_QUALITY` before creating the texture.
+ *
+ * \param renderer the rendering context
+ * \param format one of the enumerated values in SDL_PixelFormatEnum
+ * \param access one of the enumerated values in SDL_TextureAccess
+ * \param w the width of the texture in pixels
+ * \param h the height of the texture in pixels
+ * \returns a pointer to the created texture or NULL if no rendering context
+ * was active, the format was unsupported, or the width or height
+ * were out of range; call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateTextureFromSurface
+ * \sa SDL_DestroyTexture
+ * \sa SDL_QueryTexture
+ * \sa SDL_UpdateTexture
+ */
+extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,
+ Uint32 format,
+ int access, int w,
+ int h);
+
+/**
+ * Create a texture from an existing surface.
+ *
+ * The surface is not modified or freed by this function.
+ *
+ * The SDL_TextureAccess hint for the created texture is
+ * `SDL_TEXTUREACCESS_STATIC`.
+ *
+ * The pixel format of the created texture may be different from the pixel
+ * format of the surface. Use SDL_QueryTexture() to query the pixel format of
+ * the texture.
+ *
+ * \param renderer the rendering context
+ * \param surface the SDL_Surface structure containing pixel data used to fill
+ * the texture
+ * \returns the created texture or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_DestroyTexture
+ * \sa SDL_QueryTexture
+ */
+extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);
+
+/**
+ * Query the attributes of a texture.
+ *
+ * \param texture the texture to query
+ * \param format a pointer filled in with the raw format of the texture; the
+ * actual format may differ, but pixel transfers will use this
+ * format (one of the SDL_PixelFormatEnum values)
+ * \param access a pointer filled in with the actual access to the texture
+ * (one of the SDL_TextureAccess values)
+ * \param w a pointer filled in with the width of the texture in pixels
+ * \param h a pointer filled in with the height of the texture in pixels
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateTexture
+ */
+extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture * texture,
+ Uint32 * format, int *access,
+ int *w, int *h);
+
+/**
+ * Set an additional color value multiplied into render copy operations.
+ *
+ * When this texture is rendered, during the copy operation each source color
+ * channel is modulated by the appropriate color value according to the
+ * following formula:
+ *
+ * `srcC = srcC * (color / 255)`
+ *
+ * Color modulation is not always supported by the renderer; it will return -1
+ * if color modulation is not supported.
+ *
+ * \param texture the texture to update
+ * \param r the red color value multiplied into copy operations
+ * \param g the green color value multiplied into copy operations
+ * \param b the blue color value multiplied into copy operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureColorMod
+ * \sa SDL_SetTextureAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture * texture,
+ Uint8 r, Uint8 g, Uint8 b);
+
+
+/**
+ * Get the additional color value multiplied into render copy operations.
+ *
+ * \param texture the texture to query
+ * \param r a pointer filled in with the current red color value
+ * \param g a pointer filled in with the current green color value
+ * \param b a pointer filled in with the current blue color value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureAlphaMod
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureColorMod(SDL_Texture * texture,
+ Uint8 * r, Uint8 * g,
+ Uint8 * b);
+
+/**
+ * Set an additional alpha value multiplied into render copy operations.
+ *
+ * When this texture is rendered, during the copy operation the source alpha
+ * value is modulated by this alpha value according to the following formula:
+ *
+ * `srcA = srcA * (alpha / 255)`
+ *
+ * Alpha modulation is not always supported by the renderer; it will return -1
+ * if alpha modulation is not supported.
+ *
+ * \param texture the texture to update
+ * \param alpha the source alpha value multiplied into copy operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureAlphaMod
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture * texture,
+ Uint8 alpha);
+
+/**
+ * Get the additional alpha value multiplied into render copy operations.
+ *
+ * \param texture the texture to query
+ * \param alpha a pointer filled in with the current alpha value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureColorMod
+ * \sa SDL_SetTextureAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureAlphaMod(SDL_Texture * texture,
+ Uint8 * alpha);
+
+/**
+ * Set the blend mode for a texture, used by SDL_RenderCopy().
+ *
+ * If the blend mode is not supported, the closest supported mode is chosen
+ * and this function returns -1.
+ *
+ * \param texture the texture to update
+ * \param blendMode the SDL_BlendMode to use for texture blending
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureBlendMode
+ * \sa SDL_RenderCopy
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureBlendMode(SDL_Texture * texture,
+ SDL_BlendMode blendMode);
+
+/**
+ * Get the blend mode used for texture copy operations.
+ *
+ * \param texture the texture to query
+ * \param blendMode a pointer filled in with the current SDL_BlendMode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetTextureBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture * texture,
+ SDL_BlendMode *blendMode);
+
+/**
+ * Set the scale mode used for texture scale operations.
+ *
+ * If the scale mode is not supported, the closest supported mode is chosen.
+ *
+ * \param texture The texture to update.
+ * \param scaleMode the SDL_ScaleMode to use for texture scaling.
+ * \returns 0 on success, or -1 if the texture is not valid.
+ *
+ * \sa SDL_GetTextureScaleMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureScaleMode(SDL_Texture * texture,
+ SDL_ScaleMode scaleMode);
+
+/**
+ * Get the scale mode used for texture scale operations.
+ *
+ * \param texture the texture to query.
+ * \param scaleMode a pointer filled in with the current scale mode.
+ * \return 0 on success, or -1 if the texture is not valid.
+ *
+ * \sa SDL_SetTextureScaleMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture * texture,
+ SDL_ScaleMode *scaleMode);
+
+/**
+ * Update the given texture rectangle with new pixel data.
+ *
+ * The pixel data must be in the pixel format of the texture. Use
+ * SDL_QueryTexture() to query the pixel format of the texture.
+ *
+ * This is a fairly slow function, intended for use with static textures that
+ * do not change often.
+ *
+ * If the texture is intended to be updated often, it is preferred to create
+ * the texture as streaming and use the locking functions referenced below.
+ * While this function will work with streaming textures, for optimization
+ * reasons you may not get the pixels back if you lock the texture afterward.
+ *
+ * \param texture the texture to update
+ * \param rect an SDL_Rect structure representing the area to update, or NULL
+ * to update the entire texture
+ * \param pixels the raw pixel data in the format of the texture
+ * \param pitch the number of bytes in a row of pixel data, including padding
+ * between lines
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_LockTexture
+ * \sa SDL_UnlockTexture
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const void *pixels, int pitch);
+
+/**
+ * Update a rectangle within a planar YV12 or IYUV texture with new pixel
+ * data.
+ *
+ * You can use SDL_UpdateTexture() as long as your pixel data is a contiguous
+ * block of Y and U/V planes in the proper order, but this function is
+ * available if your pixel data is not contiguous.
+ *
+ * \param texture the texture to update
+ * \param rect a pointer to the rectangle of pixels to update, or NULL to
+ * update the entire texture
+ * \param Yplane the raw pixel data for the Y plane
+ * \param Ypitch the number of bytes between rows of pixel data for the Y
+ * plane
+ * \param Uplane the raw pixel data for the U plane
+ * \param Upitch the number of bytes between rows of pixel data for the U
+ * plane
+ * \param Vplane the raw pixel data for the V plane
+ * \param Vpitch the number of bytes between rows of pixel data for the V
+ * plane
+ * \returns 0 on success or -1 if the texture is not valid; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_UpdateTexture
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *Uplane, int Upitch,
+ const Uint8 *Vplane, int Vpitch);
+
+/**
+ * Update a rectangle within a planar NV12 or NV21 texture with new pixels.
+ *
+ * You can use SDL_UpdateTexture() as long as your pixel data is a contiguous
+ * block of NV12/21 planes in the proper order, but this function is available
+ * if your pixel data is not contiguous.
+ *
+ * \param texture the texture to update
+ * \param rect a pointer to the rectangle of pixels to update, or NULL to
+ * update the entire texture.
+ * \param Yplane the raw pixel data for the Y plane.
+ * \param Ypitch the number of bytes between rows of pixel data for the Y
+ * plane.
+ * \param UVplane the raw pixel data for the UV plane.
+ * \param UVpitch the number of bytes between rows of pixel data for the UV
+ * plane.
+ * \return 0 on success, or -1 if the texture is not valid.
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateNVTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *UVplane, int UVpitch);
+
+/**
+ * Lock a portion of the texture for **write-only** pixel access.
+ *
+ * As an optimization, the pixels made available for editing don't necessarily
+ * contain the old texture data. This is a write-only operation, and if you
+ * need to keep a copy of the texture data you should do that at the
+ * application level.
+ *
+ * You must use SDL_UnlockTexture() to unlock the pixels and apply any
+ * changes.
+ *
+ * \param texture the texture to lock for access, which was created with
+ * `SDL_TEXTUREACCESS_STREAMING`
+ * \param rect an SDL_Rect structure representing the area to lock for access;
+ * NULL to lock the entire texture
+ * \param pixels this is filled in with a pointer to the locked pixels,
+ * appropriately offset by the locked area
+ * \param pitch this is filled in with the pitch of the locked pixels; the
+ * pitch is the length of one row in bytes
+ * \returns 0 on success or a negative error code if the texture is not valid
+ * or was not created with `SDL_TEXTUREACCESS_STREAMING`; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_UnlockTexture
+ */
+extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ void **pixels, int *pitch);
+
+/**
+ * Lock a portion of the texture for **write-only** pixel access, and expose
+ * it as a SDL surface.
+ *
+ * Besides providing an SDL_Surface instead of raw pixel data, this function
+ * operates like SDL_LockTexture.
+ *
+ * As an optimization, the pixels made available for editing don't necessarily
+ * contain the old texture data. This is a write-only operation, and if you
+ * need to keep a copy of the texture data you should do that at the
+ * application level.
+ *
+ * You must use SDL_UnlockTexture() to unlock the pixels and apply any
+ * changes.
+ *
+ * The returned surface is freed internally after calling SDL_UnlockTexture()
+ * or SDL_DestroyTexture(). The caller should not free it.
+ *
+ * \param texture the texture to lock for access, which was created with
+ * `SDL_TEXTUREACCESS_STREAMING`
+ * \param rect a pointer to the rectangle to lock for access. If the rect is
+ * NULL, the entire texture will be locked
+ * \param surface this is filled in with an SDL surface representing the
+ * locked area
+ * \returns 0 on success, or -1 if the texture is not valid or was not created
+ * with `SDL_TEXTUREACCESS_STREAMING`
+ *
+ * \sa SDL_LockTexture
+ * \sa SDL_UnlockTexture
+ */
+extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture,
+ const SDL_Rect *rect,
+ SDL_Surface **surface);
+
+/**
+ * Unlock a texture, uploading the changes to video memory, if needed.
+ *
+ * **Warning**: Please note that SDL_LockTexture() is intended to be
+ * write-only; it will notguarantee the previous contents of the texture will
+ * be provided. You must fully initialize any area of a texture that you lock
+ * before unlocking it, as the pixels might otherwise be uninitialized memory.
+ *
+ * Which is to say: locking and immediately unlocking a texture can result in
+ * corrupted textures, depending on the renderer in use.
+ *
+ * \param texture a texture locked by SDL_LockTexture()
+ *
+ * \sa SDL_LockTexture
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture * texture);
+
+/**
+ * Determine whether a renderer supports the use of render targets.
+ *
+ * \param renderer the renderer that will be checked
+ * \returns SDL_TRUE if supported or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetRenderTarget
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderTargetSupported(SDL_Renderer *renderer);
+
+/**
+ * Set a texture as the current rendering target.
+ *
+ * Before using this function, you should check the
+ * `SDL_RENDERER_TARGETTEXTURE` bit in the flags of SDL_RendererInfo to see if
+ * render targets are supported.
+ *
+ * The default render target is the window for which the renderer was created.
+ * To stop rendering to a texture and render to the window again, call this
+ * function with a NULL `texture`.
+ *
+ * \param renderer the rendering context
+ * \param texture the targeted texture, which must be created with the
+ * `SDL_TEXTUREACCESS_TARGET` flag, or NULL to render to the
+ * window instead of a texture.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetRenderTarget
+ */
+extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
+ SDL_Texture *texture);
+
+/**
+ * Get the current render target.
+ *
+ * The default render target is the window for which the renderer was created,
+ * and is reported a NULL here.
+ *
+ * \param renderer the rendering context
+ * \returns the current render target or NULL for the default render target.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetRenderTarget
+ */
+extern DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer);
+
+/**
+ * Set a device independent resolution for rendering.
+ *
+ * This function uses the viewport and scaling functionality to allow a fixed
+ * logical resolution for rendering, regardless of the actual output
+ * resolution. If the actual output resolution doesn't have the same aspect
+ * ratio the output rendering will be centered within the output display.
+ *
+ * If the output display is a window, mouse and touch events in the window
+ * will be filtered and scaled so they seem to arrive within the logical
+ * resolution. The SDL_HINT_MOUSE_RELATIVE_SCALING hint controls whether
+ * relative motion events are also scaled.
+ *
+ * If this function results in scaling or subpixel drawing by the rendering
+ * backend, it will be handled using the appropriate quality hints.
+ *
+ * \param renderer the renderer for which resolution should be set
+ * \param w the width of the logical resolution
+ * \param h the height of the logical resolution
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderGetLogicalSize
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h);
+
+/**
+ * Get device independent resolution for rendering.
+ *
+ * This may return 0 for `w` and `h` if the SDL_Renderer has never had its
+ * logical size set by SDL_RenderSetLogicalSize() and never had a render
+ * target set.
+ *
+ * \param renderer a rendering context
+ * \param w an int to be filled with the width
+ * \param h an int to be filled with the height
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h);
+
+/**
+ * Set whether to force integer scales for resolution-independent rendering.
+ *
+ * This function restricts the logical viewport to integer values - that is,
+ * when a resolution is between two multiples of a logical size, the viewport
+ * size is rounded down to the lower multiple.
+ *
+ * \param renderer the renderer for which integer scaling should be set
+ * \param enable enable or disable the integer scaling for rendering
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_RenderGetIntegerScale
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetIntegerScale(SDL_Renderer * renderer,
+ SDL_bool enable);
+
+/**
+ * Get whether integer scales are forced for resolution-independent rendering.
+ *
+ * \param renderer the renderer from which integer scaling should be queried
+ * \returns SDL_TRUE if integer scales are forced or SDL_FALSE if not and on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_RenderSetIntegerScale
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer);
+
+/**
+ * Set the drawing area for rendering on the current target.
+ *
+ * When the window is resized, the viewport is reset to fill the entire new
+ * window size.
+ *
+ * \param renderer the rendering context
+ * \param rect the SDL_Rect structure representing the drawing area, or NULL
+ * to set the viewport to the entire target
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderGetViewport
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetViewport(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Get the drawing area for the current target.
+ *
+ * \param renderer the rendering context
+ * \param rect an SDL_Rect structure filled in with the current drawing area
+ *
+ * \sa SDL_RenderSetViewport
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer,
+ SDL_Rect * rect);
+
+/**
+ * Set the clip rectangle for rendering on the specified target.
+ *
+ * \param renderer the rendering context for which clip rectangle should be
+ * set
+ * \param rect an SDL_Rect structure representing the clip area, relative to
+ * the viewport, or NULL to disable clipping
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderGetClipRect
+ * \sa SDL_RenderIsClipEnabled
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetClipRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Get the clip rectangle for the current target.
+ *
+ * \param renderer the rendering context from which clip rectangle should be
+ * queried
+ * \param rect an SDL_Rect structure filled in with the current clipping area
+ * or an empty rectangle if clipping is disabled
+ *
+ * \sa SDL_RenderIsClipEnabled
+ * \sa SDL_RenderSetClipRect
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetClipRect(SDL_Renderer * renderer,
+ SDL_Rect * rect);
+
+/**
+ * Get whether clipping is enabled on the given renderer.
+ *
+ * \param renderer the renderer from which clip state should be queried
+ * \returns SDL_TRUE if clipping is enabled or SDL_FALSE if not; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_RenderGetClipRect
+ * \sa SDL_RenderSetClipRect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderIsClipEnabled(SDL_Renderer * renderer);
+
+
+/**
+ * Set the drawing scale for rendering on the current target.
+ *
+ * The drawing coordinates are scaled by the x/y scaling factors before they
+ * are used by the renderer. This allows resolution independent drawing with a
+ * single coordinate system.
+ *
+ * If this results in scaling or subpixel drawing by the rendering backend, it
+ * will be handled using the appropriate quality hints. For best results use
+ * integer scaling factors.
+ *
+ * \param renderer a rendering context
+ * \param scaleX the horizontal scaling factor
+ * \param scaleY the vertical scaling factor
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderGetScale
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetScale(SDL_Renderer * renderer,
+ float scaleX, float scaleY);
+
+/**
+ * Get the drawing scale for the current target.
+ *
+ * \param renderer the renderer from which drawing scale should be queried
+ * \param scaleX a pointer filled in with the horizontal scaling factor
+ * \param scaleY a pointer filled in with the vertical scaling factor
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderSetScale
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetScale(SDL_Renderer * renderer,
+ float *scaleX, float *scaleY);
+
+/**
+ * Set the color used for drawing operations (Rect, Line and Clear).
+ *
+ * Set the color for drawing or filling rectangles, lines, and points, and for
+ * SDL_RenderClear().
+ *
+ * \param renderer the rendering context
+ * \param r the red value used to draw on the rendering target
+ * \param g the green value used to draw on the rendering target
+ * \param b the blue value used to draw on the rendering target
+ * \param a the alpha value used to draw on the rendering target; usually
+ * `SDL_ALPHA_OPAQUE` (255). Use SDL_SetRenderDrawBlendMode to
+ * specify how the alpha channel is used
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetRenderDrawColor
+ * \sa SDL_RenderClear
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ */
+extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer * renderer,
+ Uint8 r, Uint8 g, Uint8 b,
+ Uint8 a);
+
+/**
+ * Get the color used for drawing operations (Rect, Line and Clear).
+ *
+ * \param renderer the rendering context
+ * \param r a pointer filled in with the red value used to draw on the
+ * rendering target
+ * \param g a pointer filled in with the green value used to draw on the
+ * rendering target
+ * \param b a pointer filled in with the blue value used to draw on the
+ * rendering target
+ * \param a a pointer filled in with the alpha value used to draw on the
+ * rendering target; usually `SDL_ALPHA_OPAQUE` (255)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_GetRenderDrawColor(SDL_Renderer * renderer,
+ Uint8 * r, Uint8 * g, Uint8 * b,
+ Uint8 * a);
+
+/**
+ * Set the blend mode used for drawing operations (Fill and Line).
+ *
+ * If the blend mode is not supported, the closest supported mode is chosen.
+ *
+ * \param renderer the rendering context
+ * \param blendMode the SDL_BlendMode to use for blending
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetRenderDrawBlendMode
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ */
+extern DECLSPEC int SDLCALL SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer,
+ SDL_BlendMode blendMode);
+
+/**
+ * Get the blend mode used for drawing operations.
+ *
+ * \param renderer the rendering context
+ * \param blendMode a pointer filled in with the current SDL_BlendMode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetRenderDrawBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer,
+ SDL_BlendMode *blendMode);
+
+/**
+ * Clear the current rendering target with the drawing color.
+ *
+ * This function clears the entire rendering target, ignoring the viewport and
+ * the clip rectangle.
+ *
+ * \param renderer the rendering context
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);
+
+/**
+ * Draw a point on the current rendering target.
+ *
+ * SDL_RenderDrawPoint() draws a single point. If you want to draw multiple,
+ * use SDL_RenderDrawPoints() instead.
+ *
+ * \param renderer the rendering context
+ * \param x the x coordinate of the point
+ * \param y the y coordinate of the point
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPoint(SDL_Renderer * renderer,
+ int x, int y);
+
+/**
+ * Draw multiple points on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param points an array of SDL_Point structures that represent the points to
+ * draw
+ * \param count the number of points to draw
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points,
+ int count);
+
+/**
+ * Draw a line on the current rendering target.
+ *
+ * SDL_RenderDrawLine() draws the line to include both end points. If you want
+ * to draw multiple, connecting lines use SDL_RenderDrawLines() instead.
+ *
+ * \param renderer the rendering context
+ * \param x1 the x coordinate of the start point
+ * \param y1 the y coordinate of the start point
+ * \param x2 the x coordinate of the end point
+ * \param y2 the y coordinate of the end point
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLine(SDL_Renderer * renderer,
+ int x1, int y1, int x2, int y2);
+
+/**
+ * Draw a series of connected lines on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param points an array of SDL_Point structures representing points along
+ * the lines
+ * \param count the number of points, drawing count-1 lines
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points,
+ int count);
+
+/**
+ * Draw a rectangle on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param rect an SDL_Rect structure representing the rectangle to draw, or
+ * NULL to outline the entire rendering target
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Draw some number of rectangles on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param rects an array of SDL_Rect structures representing the rectangles to
+ * be drawn
+ * \param count the number of rectangles
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRects(SDL_Renderer * renderer,
+ const SDL_Rect * rects,
+ int count);
+
+/**
+ * Fill a rectangle on the current rendering target with the drawing color.
+ *
+ * The current drawing color is set by SDL_SetRenderDrawColor(), and the
+ * color's alpha value is ignored unless blending is enabled with the
+ * appropriate call to SDL_SetRenderDrawBlendMode().
+ *
+ * \param renderer the rendering context
+ * \param rect the SDL_Rect structure representing the rectangle to fill, or
+ * NULL for the entire rendering target
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Fill some number of rectangles on the current rendering target with the
+ * drawing color.
+ *
+ * \param renderer the rendering context
+ * \param rects an array of SDL_Rect structures representing the rectangles to
+ * be filled
+ * \param count the number of rectangles
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderPresent
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect * rects,
+ int count);
+
+/**
+ * Copy a portion of the texture to the current rendering target.
+ *
+ * The texture is blended with the destination based on its blend mode set
+ * with SDL_SetTextureBlendMode().
+ *
+ * The texture color is affected based on its color modulation set by
+ * SDL_SetTextureColorMod().
+ *
+ * The texture alpha is affected based on its alpha modulation set by
+ * SDL_SetTextureAlphaMod().
+ *
+ * \param renderer the rendering context
+ * \param texture the source texture
+ * \param srcrect the source SDL_Rect structure or NULL for the entire texture
+ * \param dstrect the destination SDL_Rect structure or NULL for the entire
+ * rendering target; the texture will be stretched to fill the
+ * given rectangle
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderCopyEx
+ * \sa SDL_SetTextureAlphaMod
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect);
+
+/**
+ * Copy a portion of the texture to the current rendering, with optional
+ * rotation and flipping.
+ *
+ * Copy a portion of the texture to the current rendering target, optionally
+ * rotating it by angle around the given center and also flipping it
+ * top-bottom and/or left-right.
+ *
+ * The texture is blended with the destination based on its blend mode set
+ * with SDL_SetTextureBlendMode().
+ *
+ * The texture color is affected based on its color modulation set by
+ * SDL_SetTextureColorMod().
+ *
+ * The texture alpha is affected based on its alpha modulation set by
+ * SDL_SetTextureAlphaMod().
+ *
+ * \param renderer the rendering context
+ * \param texture the source texture
+ * \param srcrect the source SDL_Rect structure or NULL for the entire texture
+ * \param dstrect the destination SDL_Rect structure or NULL for the entire
+ * rendering target
+ * \param angle an angle in degrees that indicates the rotation that will be
+ * applied to dstrect, rotating it in a clockwise direction
+ * \param center a pointer to a point indicating the point around which
+ * dstrect will be rotated (if NULL, rotation will be done
+ * around `dstrect.w / 2`, `dstrect.h / 2`)
+ * \param flip a SDL_RendererFlip value stating which flipping actions should
+ * be performed on the texture
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderCopy
+ * \sa SDL_SetTextureAlphaMod
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect,
+ const double angle,
+ const SDL_Point *center,
+ const SDL_RendererFlip flip);
+
+
+/**
+ * Draw a point on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw a point.
+ * \param x The x coordinate of the point.
+ * \param y The y coordinate of the point.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer,
+ float x, float y);
+
+/**
+ * Draw multiple points on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw multiple points.
+ * \param points The points to draw
+ * \param count The number of points to draw
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer,
+ const SDL_FPoint * points,
+ int count);
+
+/**
+ * Draw a line on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw a line.
+ * \param x1 The x coordinate of the start point.
+ * \param y1 The y coordinate of the start point.
+ * \param x2 The x coordinate of the end point.
+ * \param y2 The y coordinate of the end point.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer,
+ float x1, float y1, float x2, float y2);
+
+/**
+ * Draw a series of connected lines on the current rendering target at
+ * subpixel precision.
+ *
+ * \param renderer The renderer which should draw multiple lines.
+ * \param points The points along the lines
+ * \param count The number of points, drawing count-1 lines
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer,
+ const SDL_FPoint * points,
+ int count);
+
+/**
+ * Draw a rectangle on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw a rectangle.
+ * \param rect A pointer to the destination rectangle, or NULL to outline the
+ * entire rendering target.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer,
+ const SDL_FRect * rect);
+
+/**
+ * Draw some number of rectangles on the current rendering target at subpixel
+ * precision.
+ *
+ * \param renderer The renderer which should draw multiple rectangles.
+ * \param rects A pointer to an array of destination rectangles.
+ * \param count The number of rectangles.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer,
+ const SDL_FRect * rects,
+ int count);
+
+/**
+ * Fill a rectangle on the current rendering target with the drawing color at
+ * subpixel precision.
+ *
+ * \param renderer The renderer which should fill a rectangle.
+ * \param rect A pointer to the destination rectangle, or NULL for the entire
+ * rendering target.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer,
+ const SDL_FRect * rect);
+
+/**
+ * Fill some number of rectangles on the current rendering target with the
+ * drawing color at subpixel precision.
+ *
+ * \param renderer The renderer which should fill multiple rectangles.
+ * \param rects A pointer to an array of destination rectangles.
+ * \param count The number of rectangles.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer,
+ const SDL_FRect * rects,
+ int count);
+
+/**
+ * Copy a portion of the texture to the current rendering target at subpixel
+ * precision.
+ *
+ * \param renderer The renderer which should copy parts of a texture.
+ * \param texture The source texture.
+ * \param srcrect A pointer to the source rectangle, or NULL for the entire
+ * texture.
+ * \param dstrect A pointer to the destination rectangle, or NULL for the
+ * entire rendering target.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_FRect * dstrect);
+
+/**
+ * Copy a portion of the source texture to the current rendering target, with
+ * rotation and flipping, at subpixel precision.
+ *
+ * \param renderer The renderer which should copy parts of a texture.
+ * \param texture The source texture.
+ * \param srcrect A pointer to the source rectangle, or NULL for the entire
+ * texture.
+ * \param dstrect A pointer to the destination rectangle, or NULL for the
+ * entire rendering target.
+ * \param angle An angle in degrees that indicates the rotation that will be
+ * applied to dstrect, rotating it in a clockwise direction
+ * \param center A pointer to a point indicating the point around which
+ * dstrect will be rotated (if NULL, rotation will be done
+ * around dstrect.w/2, dstrect.h/2).
+ * \param flip An SDL_RendererFlip value stating which flipping actions should
+ * be performed on the texture
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_FRect * dstrect,
+ const double angle,
+ const SDL_FPoint *center,
+ const SDL_RendererFlip flip);
+
+/**
+ * Read pixels from the current rendering target to an array of pixels.
+ *
+ * **WARNING**: This is a very slow operation, and should not be used
+ * frequently.
+ *
+ * `pitch` specifies the number of bytes between rows in the destination
+ * `pixels` data. This allows you to write to a subrectangle or have padded
+ * rows in the destination. Generally, `pitch` should equal the number of
+ * pixels per row in the `pixels` data times the number of bytes per pixel,
+ * but it might contain additional padding (for example, 24bit RGB Windows
+ * Bitmap data pads all rows to multiples of 4 bytes).
+ *
+ * \param renderer the rendering context
+ * \param rect an SDL_Rect structure representing the area to read, or NULL
+ * for the entire render target
+ * \param format an SDL_PixelFormatEnum value of the desired format of the
+ * pixel data, or 0 to use the format of the rendering target
+ * \param pixels a pointer to the pixel data to copy into
+ * \param pitch the pitch of the `pixels` parameter
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderReadPixels(SDL_Renderer * renderer,
+ const SDL_Rect * rect,
+ Uint32 format,
+ void *pixels, int pitch);
+
+/**
+ * Update the screen with any rendering performed since the previous call.
+ *
+ * SDL's rendering functions operate on a backbuffer; that is, calling a
+ * rendering function such as SDL_RenderDrawLine() does not directly put a
+ * line on the screen, but rather updates the backbuffer. As such, you compose
+ * your entire scene and *present* the composed backbuffer to the screen as a
+ * complete picture.
+ *
+ * Therefore, when using SDL's rendering API, one does all drawing intended
+ * for the frame, and then calls this function once per frame to present the
+ * final drawing to the user.
+ *
+ * The backbuffer should be considered invalidated after each present; do not
+ * assume that previous contents will exist between frames. You are strongly
+ * encouraged to call SDL_RenderClear() to initialize the backbuffer before
+ * starting each new frame's drawing, even if you plan to overwrite every
+ * pixel.
+ *
+ * \param renderer the rendering context
+ *
+ * \sa SDL_RenderClear
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
+
+/**
+ * Destroy the specified texture.
+ *
+ * Passing NULL or an otherwise invalid texture will set the SDL error message
+ * to "Invalid texture".
+ *
+ * \param texture the texture to destroy
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_CreateTextureFromSurface
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture);
+
+/**
+ * Destroy the rendering context for a window and free associated textures.
+ *
+ * \param renderer the rendering context
+ *
+ * \sa SDL_CreateRenderer
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer);
+
+/**
+ * Force the rendering context to flush any pending commands to the underlying
+ * rendering API.
+ *
+ * You do not need to (and in fact, shouldn't) call this function unless you
+ * are planning to call into OpenGL/Direct3D/Metal/whatever directly in
+ * addition to using an SDL_Renderer.
+ *
+ * This is for a very-specific case: if you are using SDL's render API, you
+ * asked for a specific renderer backend (OpenGL, Direct3D, etc), you set
+ * SDL_HINT_RENDER_BATCHING to "1", and you plan to make OpenGL/D3D/whatever
+ * calls in addition to SDL render API calls. If all of this applies, you
+ * should call SDL_RenderFlush() between calls to SDL's render API and the
+ * low-level API you're using in cooperation.
+ *
+ * In all other cases, you can ignore this function. This is only here to get
+ * maximum performance out of a specific situation. In all other cases, SDL
+ * will do the right thing, perhaps at a performance loss.
+ *
+ * This function is first available in SDL 2.0.10, and is not needed in 2.0.9
+ * and earlier, as earlier versions did not queue rendering commands at all,
+ * instead flushing them to the OS immediately.
+ *
+ * \param renderer the rendering context
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.10.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer);
+
+
+/**
+ * Bind an OpenGL/ES/ES2 texture to the current context.
+ *
+ * This is for use with OpenGL instructions when rendering OpenGL primitives
+ * directly.
+ *
+ * If not NULL, `texw` and `texh` will be filled with the width and height
+ * values suitable for the provided texture. In most cases, both will be 1.0,
+ * however, on systems that support the GL_ARB_texture_rectangle extension,
+ * these values will actually be the pixel width and height used to create the
+ * texture, so this factor needs to be taken into account when providing
+ * texture coordinates to OpenGL.
+ *
+ * You need a renderer to create an SDL_Texture, therefore you can only use
+ * this function with an implicit OpenGL context from SDL_CreateRenderer(),
+ * not with your own OpenGL context. If you need control over your OpenGL
+ * context, you need to write your own texture-loading methods.
+ *
+ * Also note that SDL may upload RGB textures as BGR (or vice-versa), and
+ * re-order the color channels in the shaders phase, so the uploaded texture
+ * may have swapped color channels.
+ *
+ * \param texture the texture to bind to the current OpenGL/ES/ES2 context
+ * \param texw a pointer to a float value which will be filled with the
+ * texture width or NULL if you don't need that value
+ * \param texh a pointer to a float value which will be filled with the
+ * texture height or NULL if you don't need that value
+ * \returns 0 on success, or -1 if the operation is not supported; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_MakeCurrent
+ * \sa SDL_GL_UnbindTexture
+ */
+extern DECLSPEC int SDLCALL SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh);
+
+/**
+ * Unbind an OpenGL/ES/ES2 texture from the current context.
+ *
+ * See SDL_GL_BindTexture() for examples on how to use these functions
+ *
+ * \param texture the texture to unbind from the current OpenGL/ES/ES2 context
+ * \returns 0 on success, or -1 if the operation is not supported
+ *
+ * \sa SDL_GL_BindTexture
+ * \sa SDL_GL_MakeCurrent
+ */
+extern DECLSPEC int SDLCALL SDL_GL_UnbindTexture(SDL_Texture *texture);
+
+/**
+ * Get the CAMetalLayer associated with the given Metal renderer.
+ *
+ * This function returns `void *`, so SDL doesn't have to include Metal's
+ * headers, but it can be safely cast to a `CAMetalLayer *`.
+ *
+ * \param renderer The renderer to query
+ * \returns a `CAMetalLayer *` on success, or NULL if the renderer isn't a
+ * Metal renderer
+ *
+ * \sa SDL_RenderGetMetalCommandEncoder
+ */
+extern DECLSPEC void *SDLCALL SDL_RenderGetMetalLayer(SDL_Renderer * renderer);
+
+/**
+ * Get the Metal command encoder for the current frame
+ *
+ * This function returns `void *`, so SDL doesn't have to include Metal's
+ * headers, but it can be safely cast to an `id<MTLRenderCommandEncoder>`.
+ *
+ * \param renderer The renderer to query
+ * \returns an `id<MTLRenderCommandEncoder>` on success, or NULL if the
+ * renderer isn't a Metal renderer.
+ *
+ * \sa SDL_RenderGetMetalLayer
+ */
+extern DECLSPEC void *SDLCALL SDL_RenderGetMetalCommandEncoder(SDL_Renderer * renderer);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_render_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_revision.h b/Client/ThirdParty/SDL2/SDL_revision.h
new file mode 100644
index 0000000..2376375
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_revision.h
@@ -0,0 +1,2 @@
+#define SDL_REVISION "https://github.com/libsdl-org/SDL.git@25f9ed87ff6947d9576fc9d79dee0784e638ac58"
+#define SDL_REVISION_NUMBER 0
diff --git a/Client/ThirdParty/SDL2/SDL_rwops.h b/Client/ThirdParty/SDL2/SDL_rwops.h
new file mode 100644
index 0000000..52b3a6c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_rwops.h
@@ -0,0 +1,412 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_rwops.h
+ *
+ * This file provides a general interface for SDL to read and write
+ * data streams. It can easily be extended to files, memory, etc.
+ */
+
+#ifndef SDL_rwops_h_
+#define SDL_rwops_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* RWops Types */
+#define SDL_RWOPS_UNKNOWN 0U /**< Unknown stream type */
+#define SDL_RWOPS_WINFILE 1U /**< Win32 file */
+#define SDL_RWOPS_STDFILE 2U /**< Stdio file */
+#define SDL_RWOPS_JNIFILE 3U /**< Android asset */
+#define SDL_RWOPS_MEMORY 4U /**< Memory stream */
+#define SDL_RWOPS_MEMORY_RO 5U /**< Read-Only memory stream */
+#if defined(__VITA__)
+#define SDL_RWOPS_VITAFILE 6U /**< Vita file */
+#endif
+
+/**
+ * This is the read/write operation structure -- very basic.
+ */
+typedef struct SDL_RWops
+{
+ /**
+ * Return the size of the file in this rwops, or -1 if unknown
+ */
+ Sint64 (SDLCALL * size) (struct SDL_RWops * context);
+
+ /**
+ * Seek to \c offset relative to \c whence, one of stdio's whence values:
+ * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END
+ *
+ * \return the final offset in the data stream, or -1 on error.
+ */
+ Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset,
+ int whence);
+
+ /**
+ * Read up to \c maxnum objects each of size \c size from the data
+ * stream to the area pointed at by \c ptr.
+ *
+ * \return the number of objects read, or 0 at error or end of file.
+ */
+ size_t (SDLCALL * read) (struct SDL_RWops * context, void *ptr,
+ size_t size, size_t maxnum);
+
+ /**
+ * Write exactly \c num objects each of size \c size from the area
+ * pointed at by \c ptr to data stream.
+ *
+ * \return the number of objects written, or 0 at error or end of file.
+ */
+ size_t (SDLCALL * write) (struct SDL_RWops * context, const void *ptr,
+ size_t size, size_t num);
+
+ /**
+ * Close and free an allocated SDL_RWops structure.
+ *
+ * \return 0 if successful or -1 on write error when flushing data.
+ */
+ int (SDLCALL * close) (struct SDL_RWops * context);
+
+ Uint32 type;
+ union
+ {
+#if defined(__ANDROID__)
+ struct
+ {
+ void *asset;
+ } androidio;
+#elif defined(__WIN32__)
+ struct
+ {
+ SDL_bool append;
+ void *h;
+ struct
+ {
+ void *data;
+ size_t size;
+ size_t left;
+ } buffer;
+ } windowsio;
+#elif defined(__VITA__)
+ struct
+ {
+ int h;
+ struct
+ {
+ void *data;
+ size_t size;
+ size_t left;
+ } buffer;
+ } vitaio;
+#endif
+
+#ifdef HAVE_STDIO_H
+ struct
+ {
+ SDL_bool autoclose;
+ FILE *fp;
+ } stdio;
+#endif
+ struct
+ {
+ Uint8 *base;
+ Uint8 *here;
+ Uint8 *stop;
+ } mem;
+ struct
+ {
+ void *data1;
+ void *data2;
+ } unknown;
+ } hidden;
+
+} SDL_RWops;
+
+
+/**
+ * \name RWFrom functions
+ *
+ * Functions to create SDL_RWops structures from various data streams.
+ */
+/* @{ */
+
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file,
+ const char *mode);
+
+#ifdef HAVE_STDIO_H
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(FILE * fp,
+ SDL_bool autoclose);
+#else
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(void * fp,
+ SDL_bool autoclose);
+#endif
+
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, int size);
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem,
+ int size);
+
+/* @} *//* RWFrom functions */
+
+
+extern DECLSPEC SDL_RWops *SDLCALL SDL_AllocRW(void);
+extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area);
+
+#define RW_SEEK_SET 0 /**< Seek from the beginning of data */
+#define RW_SEEK_CUR 1 /**< Seek relative to current read point */
+#define RW_SEEK_END 2 /**< Seek relative to the end of data */
+
+/**
+ * Use this macro to get the size of the data stream in an SDL_RWops.
+ *
+ * \param context the SDL_RWops to get the size of the data stream from
+ * \returns the size of the data stream in the SDL_RWops on success, -1 if
+ * unknown or a negative error code on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context);
+
+/**
+ * Seek within an SDL_RWops data stream.
+ *
+ * This function seeks to byte `offset`, relative to `whence`.
+ *
+ * `whence` may be any of the following values:
+ *
+ * - `RW_SEEK_SET`: seek from the beginning of data
+ * - `RW_SEEK_CUR`: seek relative to current read point
+ * - `RW_SEEK_END`: seek relative to the end of data
+ *
+ * If this stream can not seek, it will return -1.
+ *
+ * SDL_RWseek() is actually a wrapper function that calls the SDL_RWops's
+ * `seek` method appropriately, to simplify application development.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param offset an offset in bytes, relative to **whence** location; can be
+ * negative
+ * \param whence any of `RW_SEEK_SET`, `RW_SEEK_CUR`, `RW_SEEK_END`
+ * \returns the final offset in the data stream after the seek or -1 on error.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWtell
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context,
+ Sint64 offset, int whence);
+
+/**
+ * Determine the current read/write offset in an SDL_RWops data stream.
+ *
+ * SDL_RWtell is actually a wrapper function that calls the SDL_RWops's `seek`
+ * method, with an offset of 0 bytes from `RW_SEEK_CUR`, to simplify
+ * application development.
+ *
+ * \param context a SDL_RWops data stream object from which to get the current
+ * offset
+ * \returns the current offset in the stream, or -1 if the information can not
+ * be determined.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
+
+/**
+ * Read from a data source.
+ *
+ * This function reads up to `maxnum` objects each of size `size` from the
+ * data source to the area pointed at by `ptr`. This function may read less
+ * objects than requested. It will return zero when there has been an error or
+ * the data stream is completely read.
+ *
+ * SDL_RWread() is actually a function wrapper that calls the SDL_RWops's
+ * `read` method appropriately, to simplify application development.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param ptr a pointer to a buffer to read data into
+ * \param size the size of each object to read, in bytes
+ * \param maxnum the maximum number of objects to be read
+ * \returns the number of objects read, or 0 at error or end of file; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context,
+ void *ptr, size_t size,
+ size_t maxnum);
+
+/**
+ * Write to an SDL_RWops data stream.
+ *
+ * This function writes exactly `num` objects each of size `size` from the
+ * area pointed at by `ptr` to the stream. If this fails for any reason, it'll
+ * return less than `num` to demonstrate how far the write progressed. On
+ * success, it returns `num`.
+ *
+ * SDL_RWwrite is actually a function wrapper that calls the SDL_RWops's
+ * `write` method appropriately, to simplify application development.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param ptr a pointer to a buffer containing data to write
+ * \param size the size of an object to write, in bytes
+ * \param num the number of objects to write
+ * \returns the number of objects written, which will be less than **num** on
+ * error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context,
+ const void *ptr, size_t size,
+ size_t num);
+
+/**
+ * Close and free an allocated SDL_RWops structure.
+ *
+ * SDL_RWclose() closes and cleans up the SDL_RWops stream. It releases any
+ * resources used by the stream and frees the SDL_RWops itself with
+ * SDL_FreeRW(). This returns 0 on success, or -1 if the stream failed to
+ * flush to its output (e.g. to disk).
+ *
+ * Note that if this fails to flush the stream to disk, this function reports
+ * an error, but the SDL_RWops is still invalid once this function returns.
+ *
+ * SDL_RWclose() is actually a macro that calls the SDL_RWops's `close` method
+ * appropriately, to simplify application development.
+ *
+ * \param context SDL_RWops structure to close
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context);
+
+/**
+ * Load all the data from an SDL data stream.
+ *
+ * The data is allocated with a zero byte at the end (null terminated) for
+ * convenience. This extra byte is not included in the value reported via
+ * `datasize`.
+ *
+ * The data should be freed with SDL_free().
+ *
+ * \param src the SDL_RWops to read all available data from
+ * \param datasize if not NULL, will store the number of bytes read
+ * \param freesrc if non-zero, calls SDL_RWclose() on `src` before returning
+ * \returns the data, or NULL if there was an error.
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src,
+ size_t *datasize,
+ int freesrc);
+
+/**
+ * Load all the data from a file path.
+ *
+ * The data is allocated with a zero byte at the end (null terminated) for
+ * convenience. This extra byte is not included in the value reported via
+ * `datasize`.
+ *
+ * The data should be freed with SDL_free().
+ *
+ * \param file the path to read all available data from
+ * \param datasize if not NULL, will store the number of bytes read
+ * \returns the data, or NULL if there was an error.
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize);
+
+/**
+ * \name Read endian functions
+ *
+ * Read an item of the specified endianness and return in native format.
+ */
+/* @{ */
+extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src);
+extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src);
+extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src);
+extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src);
+extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src);
+extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src);
+extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src);
+/* @} *//* Read endian functions */
+
+/**
+ * \name Write endian functions
+ *
+ * Write an item of native format to the specified endianness.
+ */
+/* @{ */
+extern DECLSPEC size_t SDLCALL SDL_WriteU8(SDL_RWops * dst, Uint8 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteLE16(SDL_RWops * dst, Uint16 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteBE16(SDL_RWops * dst, Uint16 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteLE32(SDL_RWops * dst, Uint32 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteBE32(SDL_RWops * dst, Uint32 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteLE64(SDL_RWops * dst, Uint64 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteBE64(SDL_RWops * dst, Uint64 value);
+/* @} *//* Write endian functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_rwops_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_scancode.h b/Client/ThirdParty/SDL2/SDL_scancode.h
new file mode 100644
index 0000000..e54c1e0
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_scancode.h
@@ -0,0 +1,413 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_scancode.h
+ *
+ * Defines keyboard scancodes.
+ */
+
+#ifndef SDL_scancode_h_
+#define SDL_scancode_h_
+
+#include "SDL_stdinc.h"
+
+/**
+ * \brief The SDL keyboard scancode representation.
+ *
+ * Values of this type are used to represent keyboard keys, among other places
+ * in the \link SDL_Keysym::scancode key.keysym.scancode \endlink field of the
+ * SDL_Event structure.
+ *
+ * The values in this enumeration are based on the USB usage page standard:
+ * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
+ */
+typedef enum
+{
+ SDL_SCANCODE_UNKNOWN = 0,
+
+ /**
+ * \name Usage page 0x07
+ *
+ * These values are from usage page 0x07 (USB keyboard page).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_A = 4,
+ SDL_SCANCODE_B = 5,
+ SDL_SCANCODE_C = 6,
+ SDL_SCANCODE_D = 7,
+ SDL_SCANCODE_E = 8,
+ SDL_SCANCODE_F = 9,
+ SDL_SCANCODE_G = 10,
+ SDL_SCANCODE_H = 11,
+ SDL_SCANCODE_I = 12,
+ SDL_SCANCODE_J = 13,
+ SDL_SCANCODE_K = 14,
+ SDL_SCANCODE_L = 15,
+ SDL_SCANCODE_M = 16,
+ SDL_SCANCODE_N = 17,
+ SDL_SCANCODE_O = 18,
+ SDL_SCANCODE_P = 19,
+ SDL_SCANCODE_Q = 20,
+ SDL_SCANCODE_R = 21,
+ SDL_SCANCODE_S = 22,
+ SDL_SCANCODE_T = 23,
+ SDL_SCANCODE_U = 24,
+ SDL_SCANCODE_V = 25,
+ SDL_SCANCODE_W = 26,
+ SDL_SCANCODE_X = 27,
+ SDL_SCANCODE_Y = 28,
+ SDL_SCANCODE_Z = 29,
+
+ SDL_SCANCODE_1 = 30,
+ SDL_SCANCODE_2 = 31,
+ SDL_SCANCODE_3 = 32,
+ SDL_SCANCODE_4 = 33,
+ SDL_SCANCODE_5 = 34,
+ SDL_SCANCODE_6 = 35,
+ SDL_SCANCODE_7 = 36,
+ SDL_SCANCODE_8 = 37,
+ SDL_SCANCODE_9 = 38,
+ SDL_SCANCODE_0 = 39,
+
+ SDL_SCANCODE_RETURN = 40,
+ SDL_SCANCODE_ESCAPE = 41,
+ SDL_SCANCODE_BACKSPACE = 42,
+ SDL_SCANCODE_TAB = 43,
+ SDL_SCANCODE_SPACE = 44,
+
+ SDL_SCANCODE_MINUS = 45,
+ SDL_SCANCODE_EQUALS = 46,
+ SDL_SCANCODE_LEFTBRACKET = 47,
+ SDL_SCANCODE_RIGHTBRACKET = 48,
+ SDL_SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return
+ * key on ISO keyboards and at the right end
+ * of the QWERTY row on ANSI keyboards.
+ * Produces REVERSE SOLIDUS (backslash) and
+ * VERTICAL LINE in a US layout, REVERSE
+ * SOLIDUS and VERTICAL LINE in a UK Mac
+ * layout, NUMBER SIGN and TILDE in a UK
+ * Windows layout, DOLLAR SIGN and POUND SIGN
+ * in a Swiss German layout, NUMBER SIGN and
+ * APOSTROPHE in a German layout, GRAVE
+ * ACCENT and POUND SIGN in a French Mac
+ * layout, and ASTERISK and MICRO SIGN in a
+ * French Windows layout.
+ */
+ SDL_SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code
+ * instead of 49 for the same key, but all
+ * OSes I've seen treat the two codes
+ * identically. So, as an implementor, unless
+ * your keyboard generates both of those
+ * codes and your OS treats them differently,
+ * you should generate SDL_SCANCODE_BACKSLASH
+ * instead of this code. As a user, you
+ * should not rely on this code because SDL
+ * will never generate it with most (all?)
+ * keyboards.
+ */
+ SDL_SCANCODE_SEMICOLON = 51,
+ SDL_SCANCODE_APOSTROPHE = 52,
+ SDL_SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI
+ * and ISO keyboards). Produces GRAVE ACCENT and
+ * TILDE in a US Windows layout and in US and UK
+ * Mac layouts on ANSI keyboards, GRAVE ACCENT
+ * and NOT SIGN in a UK Windows layout, SECTION
+ * SIGN and PLUS-MINUS SIGN in US and UK Mac
+ * layouts on ISO keyboards, SECTION SIGN and
+ * DEGREE SIGN in a Swiss German layout (Mac:
+ * only on ISO keyboards), CIRCUMFLEX ACCENT and
+ * DEGREE SIGN in a German layout (Mac: only on
+ * ISO keyboards), SUPERSCRIPT TWO and TILDE in a
+ * French Windows layout, COMMERCIAL AT and
+ * NUMBER SIGN in a French Mac layout on ISO
+ * keyboards, and LESS-THAN SIGN and GREATER-THAN
+ * SIGN in a Swiss German, German, or French Mac
+ * layout on ANSI keyboards.
+ */
+ SDL_SCANCODE_COMMA = 54,
+ SDL_SCANCODE_PERIOD = 55,
+ SDL_SCANCODE_SLASH = 56,
+
+ SDL_SCANCODE_CAPSLOCK = 57,
+
+ SDL_SCANCODE_F1 = 58,
+ SDL_SCANCODE_F2 = 59,
+ SDL_SCANCODE_F3 = 60,
+ SDL_SCANCODE_F4 = 61,
+ SDL_SCANCODE_F5 = 62,
+ SDL_SCANCODE_F6 = 63,
+ SDL_SCANCODE_F7 = 64,
+ SDL_SCANCODE_F8 = 65,
+ SDL_SCANCODE_F9 = 66,
+ SDL_SCANCODE_F10 = 67,
+ SDL_SCANCODE_F11 = 68,
+ SDL_SCANCODE_F12 = 69,
+
+ SDL_SCANCODE_PRINTSCREEN = 70,
+ SDL_SCANCODE_SCROLLLOCK = 71,
+ SDL_SCANCODE_PAUSE = 72,
+ SDL_SCANCODE_INSERT = 73, /**< insert on PC, help on some Mac keyboards (but
+ does send code 73, not 117) */
+ SDL_SCANCODE_HOME = 74,
+ SDL_SCANCODE_PAGEUP = 75,
+ SDL_SCANCODE_DELETE = 76,
+ SDL_SCANCODE_END = 77,
+ SDL_SCANCODE_PAGEDOWN = 78,
+ SDL_SCANCODE_RIGHT = 79,
+ SDL_SCANCODE_LEFT = 80,
+ SDL_SCANCODE_DOWN = 81,
+ SDL_SCANCODE_UP = 82,
+
+ SDL_SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards
+ */
+ SDL_SCANCODE_KP_DIVIDE = 84,
+ SDL_SCANCODE_KP_MULTIPLY = 85,
+ SDL_SCANCODE_KP_MINUS = 86,
+ SDL_SCANCODE_KP_PLUS = 87,
+ SDL_SCANCODE_KP_ENTER = 88,
+ SDL_SCANCODE_KP_1 = 89,
+ SDL_SCANCODE_KP_2 = 90,
+ SDL_SCANCODE_KP_3 = 91,
+ SDL_SCANCODE_KP_4 = 92,
+ SDL_SCANCODE_KP_5 = 93,
+ SDL_SCANCODE_KP_6 = 94,
+ SDL_SCANCODE_KP_7 = 95,
+ SDL_SCANCODE_KP_8 = 96,
+ SDL_SCANCODE_KP_9 = 97,
+ SDL_SCANCODE_KP_0 = 98,
+ SDL_SCANCODE_KP_PERIOD = 99,
+
+ SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
+ * keyboards have over ANSI ones,
+ * located between left shift and Y.
+ * Produces GRAVE ACCENT and TILDE in a
+ * US or UK Mac layout, REVERSE SOLIDUS
+ * (backslash) and VERTICAL LINE in a
+ * US or UK Windows layout, and
+ * LESS-THAN SIGN and GREATER-THAN SIGN
+ * in a Swiss German, German, or French
+ * layout. */
+ SDL_SCANCODE_APPLICATION = 101, /**< windows contextual menu, compose */
+ SDL_SCANCODE_POWER = 102, /**< The USB document says this is a status flag,
+ * not a physical key - but some Mac keyboards
+ * do have a power key. */
+ SDL_SCANCODE_KP_EQUALS = 103,
+ SDL_SCANCODE_F13 = 104,
+ SDL_SCANCODE_F14 = 105,
+ SDL_SCANCODE_F15 = 106,
+ SDL_SCANCODE_F16 = 107,
+ SDL_SCANCODE_F17 = 108,
+ SDL_SCANCODE_F18 = 109,
+ SDL_SCANCODE_F19 = 110,
+ SDL_SCANCODE_F20 = 111,
+ SDL_SCANCODE_F21 = 112,
+ SDL_SCANCODE_F22 = 113,
+ SDL_SCANCODE_F23 = 114,
+ SDL_SCANCODE_F24 = 115,
+ SDL_SCANCODE_EXECUTE = 116,
+ SDL_SCANCODE_HELP = 117,
+ SDL_SCANCODE_MENU = 118,
+ SDL_SCANCODE_SELECT = 119,
+ SDL_SCANCODE_STOP = 120,
+ SDL_SCANCODE_AGAIN = 121, /**< redo */
+ SDL_SCANCODE_UNDO = 122,
+ SDL_SCANCODE_CUT = 123,
+ SDL_SCANCODE_COPY = 124,
+ SDL_SCANCODE_PASTE = 125,
+ SDL_SCANCODE_FIND = 126,
+ SDL_SCANCODE_MUTE = 127,
+ SDL_SCANCODE_VOLUMEUP = 128,
+ SDL_SCANCODE_VOLUMEDOWN = 129,
+/* not sure whether there's a reason to enable these */
+/* SDL_SCANCODE_LOCKINGCAPSLOCK = 130, */
+/* SDL_SCANCODE_LOCKINGNUMLOCK = 131, */
+/* SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */
+ SDL_SCANCODE_KP_COMMA = 133,
+ SDL_SCANCODE_KP_EQUALSAS400 = 134,
+
+ SDL_SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see
+ footnotes in USB doc */
+ SDL_SCANCODE_INTERNATIONAL2 = 136,
+ SDL_SCANCODE_INTERNATIONAL3 = 137, /**< Yen */
+ SDL_SCANCODE_INTERNATIONAL4 = 138,
+ SDL_SCANCODE_INTERNATIONAL5 = 139,
+ SDL_SCANCODE_INTERNATIONAL6 = 140,
+ SDL_SCANCODE_INTERNATIONAL7 = 141,
+ SDL_SCANCODE_INTERNATIONAL8 = 142,
+ SDL_SCANCODE_INTERNATIONAL9 = 143,
+ SDL_SCANCODE_LANG1 = 144, /**< Hangul/English toggle */
+ SDL_SCANCODE_LANG2 = 145, /**< Hanja conversion */
+ SDL_SCANCODE_LANG3 = 146, /**< Katakana */
+ SDL_SCANCODE_LANG4 = 147, /**< Hiragana */
+ SDL_SCANCODE_LANG5 = 148, /**< Zenkaku/Hankaku */
+ SDL_SCANCODE_LANG6 = 149, /**< reserved */
+ SDL_SCANCODE_LANG7 = 150, /**< reserved */
+ SDL_SCANCODE_LANG8 = 151, /**< reserved */
+ SDL_SCANCODE_LANG9 = 152, /**< reserved */
+
+ SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
+ SDL_SCANCODE_SYSREQ = 154,
+ SDL_SCANCODE_CANCEL = 155,
+ SDL_SCANCODE_CLEAR = 156,
+ SDL_SCANCODE_PRIOR = 157,
+ SDL_SCANCODE_RETURN2 = 158,
+ SDL_SCANCODE_SEPARATOR = 159,
+ SDL_SCANCODE_OUT = 160,
+ SDL_SCANCODE_OPER = 161,
+ SDL_SCANCODE_CLEARAGAIN = 162,
+ SDL_SCANCODE_CRSEL = 163,
+ SDL_SCANCODE_EXSEL = 164,
+
+ SDL_SCANCODE_KP_00 = 176,
+ SDL_SCANCODE_KP_000 = 177,
+ SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
+ SDL_SCANCODE_DECIMALSEPARATOR = 179,
+ SDL_SCANCODE_CURRENCYUNIT = 180,
+ SDL_SCANCODE_CURRENCYSUBUNIT = 181,
+ SDL_SCANCODE_KP_LEFTPAREN = 182,
+ SDL_SCANCODE_KP_RIGHTPAREN = 183,
+ SDL_SCANCODE_KP_LEFTBRACE = 184,
+ SDL_SCANCODE_KP_RIGHTBRACE = 185,
+ SDL_SCANCODE_KP_TAB = 186,
+ SDL_SCANCODE_KP_BACKSPACE = 187,
+ SDL_SCANCODE_KP_A = 188,
+ SDL_SCANCODE_KP_B = 189,
+ SDL_SCANCODE_KP_C = 190,
+ SDL_SCANCODE_KP_D = 191,
+ SDL_SCANCODE_KP_E = 192,
+ SDL_SCANCODE_KP_F = 193,
+ SDL_SCANCODE_KP_XOR = 194,
+ SDL_SCANCODE_KP_POWER = 195,
+ SDL_SCANCODE_KP_PERCENT = 196,
+ SDL_SCANCODE_KP_LESS = 197,
+ SDL_SCANCODE_KP_GREATER = 198,
+ SDL_SCANCODE_KP_AMPERSAND = 199,
+ SDL_SCANCODE_KP_DBLAMPERSAND = 200,
+ SDL_SCANCODE_KP_VERTICALBAR = 201,
+ SDL_SCANCODE_KP_DBLVERTICALBAR = 202,
+ SDL_SCANCODE_KP_COLON = 203,
+ SDL_SCANCODE_KP_HASH = 204,
+ SDL_SCANCODE_KP_SPACE = 205,
+ SDL_SCANCODE_KP_AT = 206,
+ SDL_SCANCODE_KP_EXCLAM = 207,
+ SDL_SCANCODE_KP_MEMSTORE = 208,
+ SDL_SCANCODE_KP_MEMRECALL = 209,
+ SDL_SCANCODE_KP_MEMCLEAR = 210,
+ SDL_SCANCODE_KP_MEMADD = 211,
+ SDL_SCANCODE_KP_MEMSUBTRACT = 212,
+ SDL_SCANCODE_KP_MEMMULTIPLY = 213,
+ SDL_SCANCODE_KP_MEMDIVIDE = 214,
+ SDL_SCANCODE_KP_PLUSMINUS = 215,
+ SDL_SCANCODE_KP_CLEAR = 216,
+ SDL_SCANCODE_KP_CLEARENTRY = 217,
+ SDL_SCANCODE_KP_BINARY = 218,
+ SDL_SCANCODE_KP_OCTAL = 219,
+ SDL_SCANCODE_KP_DECIMAL = 220,
+ SDL_SCANCODE_KP_HEXADECIMAL = 221,
+
+ SDL_SCANCODE_LCTRL = 224,
+ SDL_SCANCODE_LSHIFT = 225,
+ SDL_SCANCODE_LALT = 226, /**< alt, option */
+ SDL_SCANCODE_LGUI = 227, /**< windows, command (apple), meta */
+ SDL_SCANCODE_RCTRL = 228,
+ SDL_SCANCODE_RSHIFT = 229,
+ SDL_SCANCODE_RALT = 230, /**< alt gr, option */
+ SDL_SCANCODE_RGUI = 231, /**< windows, command (apple), meta */
+
+ SDL_SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered
+ * by any of the above, but since there's a
+ * special KMOD_MODE for it I'm adding it here
+ */
+
+ /* @} *//* Usage page 0x07 */
+
+ /**
+ * \name Usage page 0x0C
+ *
+ * These values are mapped from usage page 0x0C (USB consumer page).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_AUDIONEXT = 258,
+ SDL_SCANCODE_AUDIOPREV = 259,
+ SDL_SCANCODE_AUDIOSTOP = 260,
+ SDL_SCANCODE_AUDIOPLAY = 261,
+ SDL_SCANCODE_AUDIOMUTE = 262,
+ SDL_SCANCODE_MEDIASELECT = 263,
+ SDL_SCANCODE_WWW = 264,
+ SDL_SCANCODE_MAIL = 265,
+ SDL_SCANCODE_CALCULATOR = 266,
+ SDL_SCANCODE_COMPUTER = 267,
+ SDL_SCANCODE_AC_SEARCH = 268,
+ SDL_SCANCODE_AC_HOME = 269,
+ SDL_SCANCODE_AC_BACK = 270,
+ SDL_SCANCODE_AC_FORWARD = 271,
+ SDL_SCANCODE_AC_STOP = 272,
+ SDL_SCANCODE_AC_REFRESH = 273,
+ SDL_SCANCODE_AC_BOOKMARKS = 274,
+
+ /* @} *//* Usage page 0x0C */
+
+ /**
+ * \name Walther keys
+ *
+ * These are values that Christian Walther added (for mac keyboard?).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_BRIGHTNESSDOWN = 275,
+ SDL_SCANCODE_BRIGHTNESSUP = 276,
+ SDL_SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display
+ switch, video mode switch */
+ SDL_SCANCODE_KBDILLUMTOGGLE = 278,
+ SDL_SCANCODE_KBDILLUMDOWN = 279,
+ SDL_SCANCODE_KBDILLUMUP = 280,
+ SDL_SCANCODE_EJECT = 281,
+ SDL_SCANCODE_SLEEP = 282,
+
+ SDL_SCANCODE_APP1 = 283,
+ SDL_SCANCODE_APP2 = 284,
+
+ /* @} *//* Walther keys */
+
+ /**
+ * \name Usage page 0x0C (additional media keys)
+ *
+ * These values are mapped from usage page 0x0C (USB consumer page).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_AUDIOREWIND = 285,
+ SDL_SCANCODE_AUDIOFASTFORWARD = 286,
+
+ /* @} *//* Usage page 0x0C (additional media keys) */
+
+ /* Add any other keys here. */
+
+ SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes
+ for array bounds */
+} SDL_Scancode;
+
+#endif /* SDL_scancode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_sensor.h b/Client/ThirdParty/SDL2/SDL_sensor.h
new file mode 100644
index 0000000..3bab8a4
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_sensor.h
@@ -0,0 +1,271 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_sensor.h
+ *
+ * Include file for SDL sensor event handling
+ *
+ */
+
+#ifndef SDL_sensor_h_
+#define SDL_sensor_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/**
+ * \brief SDL_sensor.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_SENSOR flag. This causes SDL to scan the system
+ * for sensors, and load appropriate drivers.
+ */
+
+struct _SDL_Sensor;
+typedef struct _SDL_Sensor SDL_Sensor;
+
+/**
+ * This is a unique ID for a sensor for the time it is connected to the system,
+ * and is never reused for the lifetime of the application.
+ *
+ * The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
+ */
+typedef Sint32 SDL_SensorID;
+
+/* The different sensors defined by SDL
+ *
+ * Additional sensors may be available, using platform dependent semantics.
+ *
+ * Hare are the additional Android sensors:
+ * https://developer.android.com/reference/android/hardware/SensorEvent.html#values
+ */
+typedef enum
+{
+ SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */
+ SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */
+ SDL_SENSOR_ACCEL, /**< Accelerometer */
+ SDL_SENSOR_GYRO /**< Gyroscope */
+} SDL_SensorType;
+
+/**
+ * Accelerometer sensor
+ *
+ * The accelerometer returns the current acceleration in SI meters per
+ * second squared. This measurement includes the force of gravity, so
+ * a device at rest will have an value of SDL_STANDARD_GRAVITY away
+ * from the center of the earth.
+ *
+ * values[0]: Acceleration on the x axis
+ * values[1]: Acceleration on the y axis
+ * values[2]: Acceleration on the z axis
+ *
+ * For phones held in portrait mode and game controllers held in front of you,
+ * the axes are defined as follows:
+ * -X ... +X : left ... right
+ * -Y ... +Y : bottom ... top
+ * -Z ... +Z : farther ... closer
+ *
+ * The axis data is not changed when the phone is rotated.
+ *
+ * \sa SDL_GetDisplayOrientation()
+ */
+#define SDL_STANDARD_GRAVITY 9.80665f
+
+/**
+ * Gyroscope sensor
+ *
+ * The gyroscope returns the current rate of rotation in radians per second.
+ * The rotation is positive in the counter-clockwise direction. That is,
+ * an observer looking from a positive location on one of the axes would
+ * see positive rotation on that axis when it appeared to be rotating
+ * counter-clockwise.
+ *
+ * values[0]: Angular speed around the x axis (pitch)
+ * values[1]: Angular speed around the y axis (yaw)
+ * values[2]: Angular speed around the z axis (roll)
+ *
+ * For phones held in portrait mode and game controllers held in front of you,
+ * the axes are defined as follows:
+ * -X ... +X : left ... right
+ * -Y ... +Y : bottom ... top
+ * -Z ... +Z : farther ... closer
+ *
+ * The axis data is not changed when the phone or controller is rotated.
+ *
+ * \sa SDL_GetDisplayOrientation()
+ */
+
+/* Function prototypes */
+
+/**
+ * Locking for multi-threaded access to the sensor API
+ *
+ * If you are using the sensor API or handling events from multiple threads
+ * you should use these locking functions to protect access to the sensors.
+ *
+ * In particular, you are guaranteed that the sensor list won't change, so the
+ * API functions that take a sensor index will be valid, and sensor events
+ * will not be delivered.
+ */
+extern DECLSPEC void SDLCALL SDL_LockSensors(void);
+extern DECLSPEC void SDLCALL SDL_UnlockSensors(void);
+
+/**
+ * Count the number of sensors attached to the system right now.
+ *
+ * \returns the number of sensors detected.
+ */
+extern DECLSPEC int SDLCALL SDL_NumSensors(void);
+
+/**
+ * Get the implementation dependent name of a sensor.
+ *
+ * \param device_index The sensor to obtain name from
+ * \returns the sensor name, or NULL if `device_index` is out of range.
+ */
+extern DECLSPEC const char *SDLCALL SDL_SensorGetDeviceName(int device_index);
+
+/**
+ * Get the type of a sensor.
+ *
+ * \param device_index The sensor to get the type from
+ * \returns the SDL_SensorType, or `SDL_SENSOR_INVALID` if `device_index` is
+ * out of range.
+ */
+extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetDeviceType(int device_index);
+
+/**
+ * Get the platform dependent type of a sensor.
+ *
+ * \param device_index The sensor to check
+ * \returns the sensor platform dependent type, or -1 if `device_index` is out
+ * of range.
+ */
+extern DECLSPEC int SDLCALL SDL_SensorGetDeviceNonPortableType(int device_index);
+
+/**
+ * Get the instance ID of a sensor.
+ *
+ * \param device_index The sensor to get instance id from
+ * \returns the sensor instance ID, or -1 if `device_index` is out of range.
+ */
+extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetDeviceInstanceID(int device_index);
+
+/**
+ * Open a sensor for use.
+ *
+ * \param device_index The sensor to open
+ * \returns an SDL_Sensor sensor object, or NULL if an error occurred.
+ */
+extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorOpen(int device_index);
+
+/**
+ * Return the SDL_Sensor associated with an instance id.
+ *
+ * \param instance_id The sensor from instance id
+ * \returns an SDL_Sensor object.
+ */
+extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorFromInstanceID(SDL_SensorID instance_id);
+
+/**
+ * Get the implementation dependent name of a sensor
+ *
+ * \param sensor The SDL_Sensor object
+ * \returns the sensor name, or NULL if `sensor` is NULL.
+ */
+extern DECLSPEC const char *SDLCALL SDL_SensorGetName(SDL_Sensor *sensor);
+
+/**
+ * Get the type of a sensor.
+ *
+ * \param sensor The SDL_Sensor object to inspect
+ * \returns the SDL_SensorType type, or `SDL_SENSOR_INVALID` if `sensor` is
+ * NULL.
+ */
+extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetType(SDL_Sensor *sensor);
+
+/**
+ * Get the platform dependent type of a sensor.
+ *
+ * \param sensor The SDL_Sensor object to inspect
+ * \returns the sensor platform dependent type, or -1 if `sensor` is NULL.
+ */
+extern DECLSPEC int SDLCALL SDL_SensorGetNonPortableType(SDL_Sensor *sensor);
+
+/**
+ * Get the instance ID of a sensor.
+ *
+ * \param sensor The SDL_Sensor object to inspect
+ * \returns the sensor instance ID, or -1 if `sensor` is NULL.
+ */
+extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetInstanceID(SDL_Sensor *sensor);
+
+/**
+ * Get the current state of an opened sensor.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ *
+ * \param sensor The SDL_Sensor object to query
+ * \param data A pointer filled with the current sensor state
+ * \param num_values The number of values to write to data
+ * \returns 0 or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values);
+
+/**
+ * Close a sensor previously opened with SDL_SensorOpen().
+ *
+ * \param sensor The SDL_Sensor object to close
+ */
+extern DECLSPEC void SDLCALL SDL_SensorClose(SDL_Sensor * sensor);
+
+/**
+ * Update the current state of the open sensors.
+ *
+ * This is called automatically by the event loop if sensor events are
+ * enabled.
+ *
+ * This needs to be called from the thread that initialized the sensor
+ * subsystem.
+ */
+extern DECLSPEC void SDLCALL SDL_SensorUpdate(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#include "close_code.h"
+
+#endif /* SDL_sensor_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_shape.h b/Client/ThirdParty/SDL2/SDL_shape.h
new file mode 100644
index 0000000..8903e04
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_shape.h
@@ -0,0 +1,147 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_shape_h_
+#define SDL_shape_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_surface.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file SDL_shape.h
+ *
+ * Header file for the shaped window API.
+ */
+
+#define SDL_NONSHAPEABLE_WINDOW -1
+#define SDL_INVALID_SHAPE_ARGUMENT -2
+#define SDL_WINDOW_LACKS_SHAPE -3
+
+/**
+ * Create a window that can be shaped with the specified position, dimensions,
+ * and flags.
+ *
+ * \param title The title of the window, in UTF-8 encoding.
+ * \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or
+ * ::SDL_WINDOWPOS_UNDEFINED.
+ * \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or
+ * ::SDL_WINDOWPOS_UNDEFINED.
+ * \param w The width of the window.
+ * \param h The height of the window.
+ * \param flags The flags for the window, a mask of SDL_WINDOW_BORDERLESS with
+ * any of the following: ::SDL_WINDOW_OPENGL,
+ * ::SDL_WINDOW_INPUT_GRABBED, ::SDL_WINDOW_HIDDEN,
+ * ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED,
+ * ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_BORDERLESS is always set,
+ * and ::SDL_WINDOW_FULLSCREEN is always unset.
+ * \return the window created, or NULL if window creation failed.
+ *
+ * \sa SDL_DestroyWindow
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags);
+
+/**
+ * Return whether the given window is a shaped window.
+ *
+ * \param window The window to query for being shaped.
+ * \return SDL_TRUE if the window is a window that can be shaped, SDL_FALSE if
+ * the window is unshaped or NULL.
+ *
+ * \sa SDL_CreateShapedWindow
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsShapedWindow(const SDL_Window *window);
+
+/** \brief An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */
+typedef enum {
+ /** \brief The default mode, a binarized alpha cutoff of 1. */
+ ShapeModeDefault,
+ /** \brief A binarized alpha cutoff with a given integer value. */
+ ShapeModeBinarizeAlpha,
+ /** \brief A binarized alpha cutoff with a given integer value, but with the opposite comparison. */
+ ShapeModeReverseBinarizeAlpha,
+ /** \brief A color key is applied. */
+ ShapeModeColorKey
+} WindowShapeMode;
+
+#define SDL_SHAPEMODEALPHA(mode) (mode == ShapeModeDefault || mode == ShapeModeBinarizeAlpha || mode == ShapeModeReverseBinarizeAlpha)
+
+/** \brief A union containing parameters for shaped windows. */
+typedef union {
+ /** \brief A cutoff alpha value for binarization of the window shape's alpha channel. */
+ Uint8 binarizationCutoff;
+ SDL_Color colorKey;
+} SDL_WindowShapeParams;
+
+/** \brief A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */
+typedef struct SDL_WindowShapeMode {
+ /** \brief The mode of these window-shape parameters. */
+ WindowShapeMode mode;
+ /** \brief Window-shape parameters. */
+ SDL_WindowShapeParams parameters;
+} SDL_WindowShapeMode;
+
+/**
+ * Set the shape and parameters of a shaped window.
+ *
+ * \param window The shaped window whose parameters should be set.
+ * \param shape A surface encoding the desired shape for the window.
+ * \param shape_mode The parameters to set for the shaped window.
+ * \return 0 on success, SDL_INVALID_SHAPE_ARGUMENT on an invalid shape
+ * argument, or SDL_NONSHAPEABLE_WINDOW if the SDL_Window given does
+ * not reference a valid shaped window.
+ *
+ * \sa SDL_WindowShapeMode
+ * \sa SDL_GetShapedWindowMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode);
+
+/**
+ * Get the shape parameters of a shaped window.
+ *
+ * \param window The shaped window whose parameters should be retrieved.
+ * \param shape_mode An empty shape-mode structure to fill, or NULL to check
+ * whether the window has a shape.
+ * \return 0 if the window has a shape and, provided shape_mode was not NULL,
+ * shape_mode has been filled with the mode data,
+ * SDL_NONSHAPEABLE_WINDOW if the SDL_Window given is not a shaped
+ * window, or SDL_WINDOW_LACKS_SHAPE if the SDL_Window given is a
+ * shapeable window currently lacking a shape.
+ *
+ * \sa SDL_WindowShapeMode
+ * \sa SDL_SetWindowShape
+ */
+extern DECLSPEC int SDLCALL SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_shape_h_ */
diff --git a/Client/ThirdParty/SDL2/SDL_stdinc.h b/Client/ThirdParty/SDL2/SDL_stdinc.h
new file mode 100644
index 0000000..f64219d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_stdinc.h
@@ -0,0 +1,694 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_stdinc.h
+ *
+ * This is a general header that includes C language support.
+ */
+
+#ifndef SDL_stdinc_h_
+#define SDL_stdinc_h_
+
+#include "SDL_config.h"
+
+#ifdef __APPLE__
+#ifndef _DARWIN_C_SOURCE
+#define _DARWIN_C_SOURCE 1 /* for memset_pattern4() */
+#endif
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if defined(STDC_HEADERS)
+# include <stdlib.h>
+# include <stddef.h>
+# include <stdarg.h>
+#else
+# if defined(HAVE_STDLIB_H)
+# include <stdlib.h>
+# elif defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# endif
+# if defined(HAVE_STDDEF_H)
+# include <stddef.h>
+# endif
+# if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+#if defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+# include <stdint.h>
+#endif
+#ifdef HAVE_CTYPE_H
+# include <ctype.h>
+#endif
+#ifdef HAVE_MATH_H
+# if defined(__WINRT__)
+/* Defining _USE_MATH_DEFINES is required to get M_PI to be defined on
+ WinRT. See http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
+ for more information.
+*/
+# define _USE_MATH_DEFINES
+# endif
+# include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+#if defined(HAVE_ALLOCA) && !defined(alloca)
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# elif defined(__GNUC__)
+# define alloca __builtin_alloca
+# elif defined(_MSC_VER)
+# include <malloc.h>
+# define alloca _alloca
+# elif defined(__WATCOMC__)
+# include <malloc.h>
+# elif defined(__BORLANDC__)
+# include <malloc.h>
+# elif defined(__DMC__)
+# include <stdlib.h>
+# elif defined(__AIX__)
+#pragma alloca
+# elif defined(__MRC__)
+void *alloca(unsigned);
+# else
+char *alloca();
+# endif
+#endif
+
+/**
+ * The number of elements in an array.
+ */
+#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0]))
+#define SDL_TABLESIZE(table) SDL_arraysize(table)
+
+/**
+ * Macro useful for building other macros with strings in them
+ *
+ * e.g. #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n")
+ */
+#define SDL_STRINGIFY_ARG(arg) #arg
+
+/**
+ * \name Cast operators
+ *
+ * Use proper C++ casts when compiled as C++ to be compatible with the option
+ * -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above).
+ */
+/* @{ */
+#ifdef __cplusplus
+#define SDL_reinterpret_cast(type, expression) reinterpret_cast<type>(expression)
+#define SDL_static_cast(type, expression) static_cast<type>(expression)
+#define SDL_const_cast(type, expression) const_cast<type>(expression)
+#else
+#define SDL_reinterpret_cast(type, expression) ((type)(expression))
+#define SDL_static_cast(type, expression) ((type)(expression))
+#define SDL_const_cast(type, expression) ((type)(expression))
+#endif
+/* @} *//* Cast operators */
+
+/* Define a four character code as a Uint32 */
+#define SDL_FOURCC(A, B, C, D) \
+ ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24))
+
+/**
+ * \name Basic data types
+ */
+/* @{ */
+
+#ifdef __CC_ARM
+/* ARM's compiler throws warnings if we use an enum: like "SDL_bool x = a < b;" */
+#define SDL_FALSE 0
+#define SDL_TRUE 1
+typedef int SDL_bool;
+#else
+typedef enum
+{
+ SDL_FALSE = 0,
+ SDL_TRUE = 1
+} SDL_bool;
+#endif
+
+/**
+ * \brief A signed 8-bit integer type.
+ */
+#define SDL_MAX_SINT8 ((Sint8)0x7F) /* 127 */
+#define SDL_MIN_SINT8 ((Sint8)(~0x7F)) /* -128 */
+typedef int8_t Sint8;
+/**
+ * \brief An unsigned 8-bit integer type.
+ */
+#define SDL_MAX_UINT8 ((Uint8)0xFF) /* 255 */
+#define SDL_MIN_UINT8 ((Uint8)0x00) /* 0 */
+typedef uint8_t Uint8;
+/**
+ * \brief A signed 16-bit integer type.
+ */
+#define SDL_MAX_SINT16 ((Sint16)0x7FFF) /* 32767 */
+#define SDL_MIN_SINT16 ((Sint16)(~0x7FFF)) /* -32768 */
+typedef int16_t Sint16;
+/**
+ * \brief An unsigned 16-bit integer type.
+ */
+#define SDL_MAX_UINT16 ((Uint16)0xFFFF) /* 65535 */
+#define SDL_MIN_UINT16 ((Uint16)0x0000) /* 0 */
+typedef uint16_t Uint16;
+/**
+ * \brief A signed 32-bit integer type.
+ */
+#define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) /* 2147483647 */
+#define SDL_MIN_SINT32 ((Sint32)(~0x7FFFFFFF)) /* -2147483648 */
+typedef int32_t Sint32;
+/**
+ * \brief An unsigned 32-bit integer type.
+ */
+#define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu) /* 4294967295 */
+#define SDL_MIN_UINT32 ((Uint32)0x00000000) /* 0 */
+typedef uint32_t Uint32;
+
+/**
+ * \brief A signed 64-bit integer type.
+ */
+#define SDL_MAX_SINT64 ((Sint64)0x7FFFFFFFFFFFFFFFll) /* 9223372036854775807 */
+#define SDL_MIN_SINT64 ((Sint64)(~0x7FFFFFFFFFFFFFFFll)) /* -9223372036854775808 */
+typedef int64_t Sint64;
+/**
+ * \brief An unsigned 64-bit integer type.
+ */
+#define SDL_MAX_UINT64 ((Uint64)0xFFFFFFFFFFFFFFFFull) /* 18446744073709551615 */
+#define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */
+typedef uint64_t Uint64;
+
+/* @} *//* Basic data types */
+
+/* Make sure we have macros for printing width-based integers.
+ * <stdint.h> should define these but this is not true all platforms.
+ * (for example win32) */
+#ifndef SDL_PRIs64
+#ifdef PRIs64
+#define SDL_PRIs64 PRIs64
+#elif defined(__WIN32__)
+#define SDL_PRIs64 "I64d"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIs64 "ld"
+#else
+#define SDL_PRIs64 "lld"
+#endif
+#endif
+#ifndef SDL_PRIu64
+#ifdef PRIu64
+#define SDL_PRIu64 PRIu64
+#elif defined(__WIN32__)
+#define SDL_PRIu64 "I64u"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIu64 "lu"
+#else
+#define SDL_PRIu64 "llu"
+#endif
+#endif
+#ifndef SDL_PRIx64
+#ifdef PRIx64
+#define SDL_PRIx64 PRIx64
+#elif defined(__WIN32__)
+#define SDL_PRIx64 "I64x"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIx64 "lx"
+#else
+#define SDL_PRIx64 "llx"
+#endif
+#endif
+#ifndef SDL_PRIX64
+#ifdef PRIX64
+#define SDL_PRIX64 PRIX64
+#elif defined(__WIN32__)
+#define SDL_PRIX64 "I64X"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIX64 "lX"
+#else
+#define SDL_PRIX64 "llX"
+#endif
+#endif
+#ifndef SDL_PRIs32
+#ifdef PRId32
+#define SDL_PRIs32 PRId32
+#else
+#define SDL_PRIs32 "d"
+#endif
+#endif
+#ifndef SDL_PRIu32
+#ifdef PRIu32
+#define SDL_PRIu32 PRIu32
+#else
+#define SDL_PRIu32 "u"
+#endif
+#endif
+#ifndef SDL_PRIx32
+#ifdef PRIx32
+#define SDL_PRIx32 PRIx32
+#else
+#define SDL_PRIx32 "x"
+#endif
+#endif
+#ifndef SDL_PRIX32
+#ifdef PRIX32
+#define SDL_PRIX32 PRIX32
+#else
+#define SDL_PRIX32 "X"
+#endif
+#endif
+
+/* Annotations to help code analysis tools */
+#ifdef SDL_DISABLE_ANALYZE_MACROS
+#define SDL_IN_BYTECAP(x)
+#define SDL_INOUT_Z_CAP(x)
+#define SDL_OUT_Z_CAP(x)
+#define SDL_OUT_CAP(x)
+#define SDL_OUT_BYTECAP(x)
+#define SDL_OUT_Z_BYTECAP(x)
+#define SDL_PRINTF_FORMAT_STRING
+#define SDL_SCANF_FORMAT_STRING
+#define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#else
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
+#include <sal.h>
+
+#define SDL_IN_BYTECAP(x) _In_bytecount_(x)
+#define SDL_INOUT_Z_CAP(x) _Inout_z_cap_(x)
+#define SDL_OUT_Z_CAP(x) _Out_z_cap_(x)
+#define SDL_OUT_CAP(x) _Out_cap_(x)
+#define SDL_OUT_BYTECAP(x) _Out_bytecap_(x)
+#define SDL_OUT_Z_BYTECAP(x) _Out_z_bytecap_(x)
+
+#define SDL_PRINTF_FORMAT_STRING _Printf_format_string_
+#define SDL_SCANF_FORMAT_STRING _Scanf_format_string_impl_
+#else
+#define SDL_IN_BYTECAP(x)
+#define SDL_INOUT_Z_CAP(x)
+#define SDL_OUT_Z_CAP(x)
+#define SDL_OUT_CAP(x)
+#define SDL_OUT_BYTECAP(x)
+#define SDL_OUT_Z_BYTECAP(x)
+#define SDL_PRINTF_FORMAT_STRING
+#define SDL_SCANF_FORMAT_STRING
+#endif
+#if defined(__GNUC__)
+#define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 )))
+#define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 )))
+#else
+#define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#endif
+#endif /* SDL_DISABLE_ANALYZE_MACROS */
+
+#define SDL_COMPILE_TIME_ASSERT(name, x) \
+ typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1]
+/** \cond */
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1);
+SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1);
+SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2);
+SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2);
+SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4);
+SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4);
+SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8);
+SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
+#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
+/** \endcond */
+
+/* Check to make sure enums are the size of ints, for structure packing.
+ For both Watcom C/C++ and Borland C/C++ the compiler option that makes
+ enums having the size of an int must be enabled.
+ This is "-b" for Borland C/C++ and "-ei" for Watcom C/C++ (v11).
+*/
+
+/** \cond */
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+#if !defined(__ANDROID__) && !defined(__VITA__)
+ /* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */
+typedef enum
+{
+ DUMMY_ENUM_VALUE
+} SDL_DUMMY_ENUM;
+
+SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int));
+#endif
+#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
+/** \endcond */
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_ALLOCA
+#define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count))
+#define SDL_stack_free(data)
+#else
+#define SDL_stack_alloc(type, count) (type*)SDL_malloc(sizeof(type)*(count))
+#define SDL_stack_free(data) SDL_free(data)
+#endif
+
+extern DECLSPEC void *SDLCALL SDL_malloc(size_t size);
+extern DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size);
+extern DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size);
+extern DECLSPEC void SDLCALL SDL_free(void *mem);
+
+typedef void *(SDLCALL *SDL_malloc_func)(size_t size);
+typedef void *(SDLCALL *SDL_calloc_func)(size_t nmemb, size_t size);
+typedef void *(SDLCALL *SDL_realloc_func)(void *mem, size_t size);
+typedef void (SDLCALL *SDL_free_func)(void *mem);
+
+/**
+ * Get the current set of SDL memory functions
+ */
+extern DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func,
+ SDL_calloc_func *calloc_func,
+ SDL_realloc_func *realloc_func,
+ SDL_free_func *free_func);
+
+/**
+ * Replace SDL's memory allocation functions with a custom set
+ */
+extern DECLSPEC int SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func,
+ SDL_calloc_func calloc_func,
+ SDL_realloc_func realloc_func,
+ SDL_free_func free_func);
+
+/**
+ * Get the number of outstanding (unfreed) allocations
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAllocations(void);
+
+extern DECLSPEC char *SDLCALL SDL_getenv(const char *name);
+extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite);
+
+extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *));
+
+extern DECLSPEC int SDLCALL SDL_abs(int x);
+
+/* !!! FIXME: these have side effects. You probably shouldn't use them. */
+/* !!! FIXME: Maybe we do forceinline functions of SDL_mini, SDL_minf, etc? */
+#define SDL_min(x, y) (((x) < (y)) ? (x) : (y))
+#define SDL_max(x, y) (((x) > (y)) ? (x) : (y))
+
+extern DECLSPEC int SDLCALL SDL_isalpha(int x);
+extern DECLSPEC int SDLCALL SDL_isalnum(int x);
+extern DECLSPEC int SDLCALL SDL_isblank(int x);
+extern DECLSPEC int SDLCALL SDL_iscntrl(int x);
+extern DECLSPEC int SDLCALL SDL_isdigit(int x);
+extern DECLSPEC int SDLCALL SDL_isxdigit(int x);
+extern DECLSPEC int SDLCALL SDL_ispunct(int x);
+extern DECLSPEC int SDLCALL SDL_isspace(int x);
+extern DECLSPEC int SDLCALL SDL_isupper(int x);
+extern DECLSPEC int SDLCALL SDL_islower(int x);
+extern DECLSPEC int SDLCALL SDL_isprint(int x);
+extern DECLSPEC int SDLCALL SDL_isgraph(int x);
+extern DECLSPEC int SDLCALL SDL_toupper(int x);
+extern DECLSPEC int SDLCALL SDL_tolower(int x);
+
+extern DECLSPEC Uint32 SDLCALL SDL_crc32(Uint32 crc, const void *data, size_t len);
+
+extern DECLSPEC void *SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len);
+
+#define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
+#define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
+#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x)))
+
+/* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */
+SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
+{
+#ifdef __APPLE__
+ memset_pattern4(dst, &val, dwords * 4);
+#elif defined(__GNUC__) && defined(__i386__)
+ int u0, u1, u2;
+ __asm__ __volatile__ (
+ "cld \n\t"
+ "rep ; stosl \n\t"
+ : "=&D" (u0), "=&a" (u1), "=&c" (u2)
+ : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, dwords))
+ : "memory"
+ );
+#else
+ size_t _n = (dwords + 3) / 4;
+ Uint32 *_p = SDL_static_cast(Uint32 *, dst);
+ Uint32 _val = (val);
+ if (dwords == 0) {
+ return;
+ }
+
+ /* !!! FIXME: there are better ways to do this, but this is just to clean this up for now. */
+ #ifdef __clang__
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+ #endif
+
+ switch (dwords % 4) {
+ case 0: do { *_p++ = _val; /* fallthrough */
+ case 3: *_p++ = _val; /* fallthrough */
+ case 2: *_p++ = _val; /* fallthrough */
+ case 1: *_p++ = _val; /* fallthrough */
+ } while ( --_n );
+ }
+
+ #ifdef __clang__
+ #pragma clang diagnostic pop
+ #endif
+
+#endif
+}
+
+extern DECLSPEC void *SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len);
+
+extern DECLSPEC void *SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len);
+extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len);
+
+extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr);
+extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
+extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
+extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr);
+extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle);
+
+extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2);
+extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen);
+extern DECLSPEC int SDLCALL SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2);
+extern DECLSPEC int SDLCALL SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t len);
+
+extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str);
+extern DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen);
+extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes);
+extern DECLSPEC size_t SDLCALL SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen);
+extern DECLSPEC char *SDLCALL SDL_strdup(const char *str);
+extern DECLSPEC char *SDLCALL SDL_strrev(char *str);
+extern DECLSPEC char *SDLCALL SDL_strupr(char *str);
+extern DECLSPEC char *SDLCALL SDL_strlwr(char *str);
+extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c);
+extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c);
+extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle);
+extern DECLSPEC char *SDLCALL SDL_strtokr(char *s1, const char *s2, char **saveptr);
+extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str);
+
+extern DECLSPEC char *SDLCALL SDL_itoa(int value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_uitoa(unsigned int value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_lltoa(Sint64 value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ulltoa(Uint64 value, char *str, int radix);
+
+extern DECLSPEC int SDLCALL SDL_atoi(const char *str);
+extern DECLSPEC double SDLCALL SDL_atof(const char *str);
+extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base);
+extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base);
+extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *str, char **endp, int base);
+extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *str, char **endp, int base);
+extern DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp);
+
+extern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2);
+extern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen);
+extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2);
+extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len);
+
+extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2);
+extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3);
+extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap);
+
+#ifndef HAVE_M_PI
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327950288 /**< pi */
+#endif
+#endif
+
+extern DECLSPEC double SDLCALL SDL_acos(double x);
+extern DECLSPEC float SDLCALL SDL_acosf(float x);
+extern DECLSPEC double SDLCALL SDL_asin(double x);
+extern DECLSPEC float SDLCALL SDL_asinf(float x);
+extern DECLSPEC double SDLCALL SDL_atan(double x);
+extern DECLSPEC float SDLCALL SDL_atanf(float x);
+extern DECLSPEC double SDLCALL SDL_atan2(double x, double y);
+extern DECLSPEC float SDLCALL SDL_atan2f(float x, float y);
+extern DECLSPEC double SDLCALL SDL_ceil(double x);
+extern DECLSPEC float SDLCALL SDL_ceilf(float x);
+extern DECLSPEC double SDLCALL SDL_copysign(double x, double y);
+extern DECLSPEC float SDLCALL SDL_copysignf(float x, float y);
+extern DECLSPEC double SDLCALL SDL_cos(double x);
+extern DECLSPEC float SDLCALL SDL_cosf(float x);
+extern DECLSPEC double SDLCALL SDL_exp(double x);
+extern DECLSPEC float SDLCALL SDL_expf(float x);
+extern DECLSPEC double SDLCALL SDL_fabs(double x);
+extern DECLSPEC float SDLCALL SDL_fabsf(float x);
+extern DECLSPEC double SDLCALL SDL_floor(double x);
+extern DECLSPEC float SDLCALL SDL_floorf(float x);
+extern DECLSPEC double SDLCALL SDL_trunc(double x);
+extern DECLSPEC float SDLCALL SDL_truncf(float x);
+extern DECLSPEC double SDLCALL SDL_fmod(double x, double y);
+extern DECLSPEC float SDLCALL SDL_fmodf(float x, float y);
+extern DECLSPEC double SDLCALL SDL_log(double x);
+extern DECLSPEC float SDLCALL SDL_logf(float x);
+extern DECLSPEC double SDLCALL SDL_log10(double x);
+extern DECLSPEC float SDLCALL SDL_log10f(float x);
+extern DECLSPEC double SDLCALL SDL_pow(double x, double y);
+extern DECLSPEC float SDLCALL SDL_powf(float x, float y);
+extern DECLSPEC double SDLCALL SDL_round(double x);
+extern DECLSPEC float SDLCALL SDL_roundf(float x);
+extern DECLSPEC long SDLCALL SDL_lround(double x);
+extern DECLSPEC long SDLCALL SDL_lroundf(float x);
+extern DECLSPEC double SDLCALL SDL_scalbn(double x, int n);
+extern DECLSPEC float SDLCALL SDL_scalbnf(float x, int n);
+extern DECLSPEC double SDLCALL SDL_sin(double x);
+extern DECLSPEC float SDLCALL SDL_sinf(float x);
+extern DECLSPEC double SDLCALL SDL_sqrt(double x);
+extern DECLSPEC float SDLCALL SDL_sqrtf(float x);
+extern DECLSPEC double SDLCALL SDL_tan(double x);
+extern DECLSPEC float SDLCALL SDL_tanf(float x);
+
+/* The SDL implementation of iconv() returns these error codes */
+#define SDL_ICONV_ERROR (size_t)-1
+#define SDL_ICONV_E2BIG (size_t)-2
+#define SDL_ICONV_EILSEQ (size_t)-3
+#define SDL_ICONV_EINVAL (size_t)-4
+
+/* SDL_iconv_* are now always real symbols/types, not macros or inlined. */
+typedef struct _SDL_iconv_t *SDL_iconv_t;
+extern DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode,
+ const char *fromcode);
+extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);
+extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf,
+ size_t * inbytesleft, char **outbuf,
+ size_t * outbytesleft);
+/**
+ * This function converts a string between encodings in one pass, returning a
+ * string that must be freed with SDL_free() or NULL on error.
+ */
+extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode,
+ const char *fromcode,
+ const char *inbuf,
+ size_t inbytesleft);
+#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+
+/* force builds using Clang's static analysis tools to use literal C runtime
+ here, since there are possibly tests that are ineffective otherwise. */
+#if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS)
+
+/* The analyzer knows about strlcpy even when the system doesn't provide it */
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char* dst, const char* src, size_t size);
+#endif
+
+/* The analyzer knows about strlcat even when the system doesn't provide it */
+#ifndef HAVE_STRLCAT
+size_t strlcat(char* dst, const char* src, size_t size);
+#endif
+
+#define SDL_malloc malloc
+#define SDL_calloc calloc
+#define SDL_realloc realloc
+#define SDL_free free
+#define SDL_memset memset
+#define SDL_memcpy memcpy
+#define SDL_memmove memmove
+#define SDL_memcmp memcmp
+#define SDL_strlcpy strlcpy
+#define SDL_strlcat strlcat
+#define SDL_strlen strlen
+#define SDL_wcslen wcslen
+#define SDL_wcslcpy wcslcpy
+#define SDL_wcslcat wcslcat
+#define SDL_strdup strdup
+#define SDL_wcsdup wcsdup
+#define SDL_strchr strchr
+#define SDL_strrchr strrchr
+#define SDL_strstr strstr
+#define SDL_wcsstr wcsstr
+#define SDL_strtokr strtok_r
+#define SDL_strcmp strcmp
+#define SDL_wcscmp wcscmp
+#define SDL_strncmp strncmp
+#define SDL_wcsncmp wcsncmp
+#define SDL_strcasecmp strcasecmp
+#define SDL_strncasecmp strncasecmp
+#define SDL_sscanf sscanf
+#define SDL_vsscanf vsscanf
+#define SDL_snprintf snprintf
+#define SDL_vsnprintf vsnprintf
+#endif
+
+SDL_FORCE_INLINE void *SDL_memcpy4(SDL_OUT_BYTECAP(dwords*4) void *dst, SDL_IN_BYTECAP(dwords*4) const void *src, size_t dwords)
+{
+ return SDL_memcpy(dst, src, dwords * 4);
+}
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_stdinc_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_surface.h b/Client/ThirdParty/SDL2/SDL_surface.h
new file mode 100644
index 0000000..5325ed2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_surface.h
@@ -0,0 +1,887 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_surface.h
+ *
+ * Header file for ::SDL_Surface definition and management functions.
+ */
+
+#ifndef SDL_surface_h_
+#define SDL_surface_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_blendmode.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Surface flags
+ *
+ * These are the currently supported flags for the ::SDL_Surface.
+ *
+ * \internal
+ * Used internally (read-only).
+ */
+/* @{ */
+#define SDL_SWSURFACE 0 /**< Just here for compatibility */
+#define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */
+#define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */
+#define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */
+#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */
+/* @} *//* Surface flags */
+
+/**
+ * Evaluates to true if the surface needs to be locked before access.
+ */
+#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0)
+
+/**
+ * \brief A collection of pixels used in software blitting.
+ *
+ * \note This structure should be treated as read-only, except for \c pixels,
+ * which, if not NULL, contains the raw pixel data for the surface.
+ */
+typedef struct SDL_Surface
+{
+ Uint32 flags; /**< Read-only */
+ SDL_PixelFormat *format; /**< Read-only */
+ int w, h; /**< Read-only */
+ int pitch; /**< Read-only */
+ void *pixels; /**< Read-write */
+
+ /** Application data associated with the surface */
+ void *userdata; /**< Read-write */
+
+ /** information needed for surfaces requiring locks */
+ int locked; /**< Read-only */
+
+ /** list of BlitMap that hold a reference to this surface */
+ void *list_blitmap; /**< Private */
+
+ /** clipping information */
+ SDL_Rect clip_rect; /**< Read-only */
+
+ /** info for fast blit mapping to other surfaces */
+ struct SDL_BlitMap *map; /**< Private */
+
+ /** Reference count -- used when freeing surface */
+ int refcount; /**< Read-mostly */
+} SDL_Surface;
+
+/**
+ * \brief The type of function used for surface blitting functions.
+ */
+typedef int (SDLCALL *SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
+ struct SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * \brief The formula used for converting between YUV and RGB
+ */
+typedef enum
+{
+ SDL_YUV_CONVERSION_JPEG, /**< Full range JPEG */
+ SDL_YUV_CONVERSION_BT601, /**< BT.601 (the default) */
+ SDL_YUV_CONVERSION_BT709, /**< BT.709 */
+ SDL_YUV_CONVERSION_AUTOMATIC /**< BT.601 for SD content, BT.709 for HD content */
+} SDL_YUV_CONVERSION_MODE;
+
+/**
+ * Allocate a new RGB surface.
+ *
+ * If `depth` is 4 or 8 bits, an empty palette is allocated for the surface.
+ * If `depth` is greater than 8 bits, the pixel format is set using the
+ * [RGBA]mask parameters.
+ *
+ * The [RGBA]mask parameters are the bitmasks used to extract that color from
+ * a pixel. For instance, `Rmask` being 0xFF000000 means the red data is
+ * stored in the most significant byte. Using zeros for the RGB masks sets a
+ * default value, based on the depth. For example:
+ *
+ * ```c++
+ * SDL_CreateRGBSurface(0,w,h,32,0,0,0,0);
+ * ```
+ *
+ * However, using zero for the Amask results in an Amask of 0.
+ *
+ * By default surfaces with an alpha mask are set up for blending as with:
+ *
+ * ```c++
+ * SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND)
+ * ```
+ *
+ * You can change this by calling SDL_SetSurfaceBlendMode() and selecting a
+ * different `blendMode`.
+ *
+ * \param flags the flags are unused and should be set to 0
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param Rmask the red mask for the pixels
+ * \param Gmask the green mask for the pixels
+ * \param Bmask the blue mask for the pixels
+ * \param Amask the alpha mask for the pixels
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_CreateRGBSurfaceWithFormat
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface
+ (Uint32 flags, int width, int height, int depth,
+ Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
+
+
+/* !!! FIXME for 2.1: why does this ask for depth? Format provides that. */
+/**
+ * Allocate a new RGB surface with a specific pixel format.
+ *
+ * This function operates mostly like SDL_CreateRGBSurface(), except instead
+ * of providing pixel color masks, you provide it with a predefined format
+ * from SDL_PixelFormatEnum.
+ *
+ * \param flags the flags are unused and should be set to 0
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param format the SDL_PixelFormatEnum for the new surface's pixel format.
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurface
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormat
+ (Uint32 flags, int width, int height, int depth, Uint32 format);
+
+/**
+ * Allocate a new RGB surface with existing pixel data.
+ *
+ * This function operates mostly like SDL_CreateRGBSurface(), except it does
+ * not allocate memory for the pixel data, instead the caller provides an
+ * existing buffer of data for the surface to use.
+ *
+ * No copy is made of the pixel data. Pixel data is not managed automatically;
+ * you must free the surface before you free the pixel data.
+ *
+ * \param pixels a pointer to existing pixel data
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param pitch the pitch of the surface in bytes
+ * \param Rmask the red mask for the pixels
+ * \param Gmask the green mask for the pixels
+ * \param Bmask the blue mask for the pixels
+ * \param Amask the alpha mask for the pixels
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurface
+ * \sa SDL_CreateRGBSurfaceWithFormat
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
+ int width,
+ int height,
+ int depth,
+ int pitch,
+ Uint32 Rmask,
+ Uint32 Gmask,
+ Uint32 Bmask,
+ Uint32 Amask);
+
+/* !!! FIXME for 2.1: why does this ask for depth? Format provides that. */
+/**
+ * Allocate a new RGB surface with with a specific pixel format and existing
+ * pixel data.
+ *
+ * This function operates mostly like SDL_CreateRGBSurfaceFrom(), except
+ * instead of providing pixel color masks, you provide it with a predefined
+ * format from SDL_PixelFormatEnum.
+ *
+ * No copy is made of the pixel data. Pixel data is not managed automatically;
+ * you must free the surface before you free the pixel data.
+ *
+ * \param pixels a pointer to existing pixel data
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param pitch the pitch of the surface in bytes
+ * \param format the SDL_PixelFormatEnum for the new surface's pixel format.
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_CreateRGBSurfaceWithFormat
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormatFrom
+ (void *pixels, int width, int height, int depth, int pitch, Uint32 format);
+
+/**
+ * Free an RGB surface.
+ *
+ * It is safe to pass NULL to this function.
+ *
+ * \param surface the SDL_Surface to free.
+ *
+ * \sa SDL_CreateRGBSurface
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_LoadBMP
+ * \sa SDL_LoadBMP_RW
+ */
+extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface);
+
+/**
+ * Set the palette used by a surface.
+ *
+ * A single palette can be shared with many surfaces.
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param palette the SDL_Palette structure to use
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface * surface,
+ SDL_Palette * palette);
+
+/**
+ * Set up a surface for directly accessing the pixels.
+ *
+ * Between calls to SDL_LockSurface() / SDL_UnlockSurface(), you can write to
+ * and read from `surface->pixels`, using the pixel format stored in
+ * `surface->format`. Once you are done accessing the surface, you should use
+ * SDL_UnlockSurface() to release it.
+ *
+ * Not all surfaces require locking. If `SDL_MUSTLOCK(surface)` evaluates to
+ * 0, then you can read and write to the surface at any time, and the pixel
+ * format of the surface will not change.
+ *
+ * \param surface the SDL_Surface structure to be locked
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_MUSTLOCK
+ * \sa SDL_UnlockSurface
+ */
+extern DECLSPEC int SDLCALL SDL_LockSurface(SDL_Surface * surface);
+
+/**
+ * Release a surface after directly accessing the pixels.
+ *
+ * \param surface the SDL_Surface structure to be unlocked
+ *
+ * \sa SDL_LockSurface
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface * surface);
+
+/**
+ * Load a BMP image from a seekable SDL data stream.
+ *
+ * The new surface should be freed with SDL_FreeSurface().
+ *
+ * \param src the data stream for the surface
+ * \param freesrc non-zero to close the stream after being read
+ * \returns a pointer to a new SDL_Surface structure or NULL if there was an
+ * error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_FreeSurface
+ * \sa SDL_LoadBMP
+ * \sa SDL_SaveBMP_RW
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops * src,
+ int freesrc);
+
+/**
+ * Load a surface from a file.
+ *
+ * Convenience macro.
+ */
+#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
+
+/**
+ * Save a surface to a seekable SDL data stream in BMP format.
+ *
+ * Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
+ * BMP directly. Other RGB formats with 8-bit or higher get converted to a
+ * 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
+ * surface before they are saved. YUV and paletted 1-bit and 4-bit formats are
+ * not supported.
+ *
+ * \param surface the SDL_Surface structure containing the image to be saved
+ * \param dst a data stream to save to
+ * \param freedst non-zero to close the stream after being written
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_LoadBMP_RW
+ * \sa SDL_SaveBMP
+ */
+extern DECLSPEC int SDLCALL SDL_SaveBMP_RW
+ (SDL_Surface * surface, SDL_RWops * dst, int freedst);
+
+/**
+ * Save a surface to a file.
+ *
+ * Convenience macro.
+ */
+#define SDL_SaveBMP(surface, file) \
+ SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1)
+
+/**
+ * Set the RLE acceleration hint for a surface.
+ *
+ * If RLE is enabled, color key and alpha blending blits are much faster, but
+ * the surface must be locked before directly accessing the pixels.
+ *
+ * \param surface the SDL_Surface structure to optimize
+ * \param flag 0 to disable, non-zero to enable RLE acceleration
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_LockSurface
+ * \sa SDL_UnlockSurface
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface * surface,
+ int flag);
+
+/**
+ * Returns whether the surface is RLE enabled
+ *
+ * It is safe to pass a NULL `surface` here; it will return SDL_FALSE.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \returns SDL_TRUE if the surface is RLE enabled, SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetSurfaceRLE
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSurfaceRLE(SDL_Surface * surface);
+
+/**
+ * Set the color key (transparent pixel) in a surface.
+ *
+ * The color key defines a pixel value that will be treated as transparent in
+ * a blit. For example, one can use this to specify that cyan pixels should be
+ * considered transparent, and therefore not rendered.
+ *
+ * It is a pixel of the format used by the surface, as generated by
+ * SDL_MapRGB().
+ *
+ * RLE acceleration can substantially speed up blitting of images with large
+ * horizontal runs of transparent pixels. See SDL_SetSurfaceRLE() for details.
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param flag SDL_TRUE to enable color key, SDL_FALSE to disable color key
+ * \param key the transparent pixel
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_GetColorKey
+ */
+extern DECLSPEC int SDLCALL SDL_SetColorKey(SDL_Surface * surface,
+ int flag, Uint32 key);
+
+/**
+ * Returns whether the surface has a color key
+ *
+ * It is safe to pass a NULL `surface` here; it will return SDL_FALSE.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \return SDL_TRUE if the surface has a color key, SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetColorKey
+ * \sa SDL_GetColorKey
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasColorKey(SDL_Surface * surface);
+
+/**
+ * Get the color key (transparent pixel) for a surface.
+ *
+ * The color key is a pixel of the format used by the surface, as generated by
+ * SDL_MapRGB().
+ *
+ * If the surface doesn't have color key enabled this function returns -1.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param key a pointer filled in with the transparent pixel
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_SetColorKey
+ */
+extern DECLSPEC int SDLCALL SDL_GetColorKey(SDL_Surface * surface,
+ Uint32 * key);
+
+/**
+ * Set an additional color value multiplied into blit operations.
+ *
+ * When this surface is blitted, during the blit operation each source color
+ * channel is modulated by the appropriate color value according to the
+ * following formula:
+ *
+ * `srcC = srcC * (color / 255)`
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param r the red color value multiplied into blit operations
+ * \param g the green color value multiplied into blit operations
+ * \param b the blue color value multiplied into blit operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceColorMod
+ * \sa SDL_SetSurfaceAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface * surface,
+ Uint8 r, Uint8 g, Uint8 b);
+
+
+/**
+ * Get the additional color value multiplied into blit operations.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param r a pointer filled in with the current red color value
+ * \param g a pointer filled in with the current green color value
+ * \param b a pointer filled in with the current blue color value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceAlphaMod
+ * \sa SDL_SetSurfaceColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface * surface,
+ Uint8 * r, Uint8 * g,
+ Uint8 * b);
+
+/**
+ * Set an additional alpha value used in blit operations.
+ *
+ * When this surface is blitted, during the blit operation the source alpha
+ * value is modulated by this alpha value according to the following formula:
+ *
+ * `srcA = srcA * (alpha / 255)`
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param alpha the alpha value multiplied into blit operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceAlphaMod
+ * \sa SDL_SetSurfaceColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface * surface,
+ Uint8 alpha);
+
+/**
+ * Get the additional alpha value used in blit operations.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param alpha a pointer filled in with the current alpha value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceColorMod
+ * \sa SDL_SetSurfaceAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface * surface,
+ Uint8 * alpha);
+
+/**
+ * Set the blend mode used for blit operations.
+ *
+ * To copy a surface to another surface (or texture) without blending with the
+ * existing data, the blendmode of the SOURCE surface should be set to
+ * `SDL_BLENDMODE_NONE`.
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param blendMode the SDL_BlendMode to use for blit blending
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface * surface,
+ SDL_BlendMode blendMode);
+
+/**
+ * Get the blend mode used for blit operations.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param blendMode a pointer filled in with the current SDL_BlendMode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetSurfaceBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface * surface,
+ SDL_BlendMode *blendMode);
+
+/**
+ * Set the clipping rectangle for a surface.
+ *
+ * When `surface` is the destination of a blit, only the area within the clip
+ * rectangle is drawn into.
+ *
+ * Note that blits are automatically clipped to the edges of the source and
+ * destination surfaces.
+ *
+ * \param surface the SDL_Surface structure to be clipped
+ * \param rect the SDL_Rect structure representing the clipping rectangle, or
+ * NULL to disable clipping
+ * \returns SDL_TRUE if the rectangle intersects the surface, otherwise
+ * SDL_FALSE and blits will be completely clipped.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_GetClipRect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetClipRect(SDL_Surface * surface,
+ const SDL_Rect * rect);
+
+/**
+ * Get the clipping rectangle for a surface.
+ *
+ * When `surface` is the destination of a blit, only the area within the clip
+ * rectangle is drawn into.
+ *
+ * \param surface the SDL_Surface structure representing the surface to be
+ * clipped
+ * \param rect an SDL_Rect structure filled in with the clipping rectangle for
+ * the surface
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_SetClipRect
+ */
+extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface * surface,
+ SDL_Rect * rect);
+
+/*
+ * Creates a new surface identical to the existing surface.
+ *
+ * The returned surface should be freed with SDL_FreeSurface().
+ *
+ * \param surface the surface to duplicate.
+ * \returns a copy of the surface, or NULL on failure; call SDL_GetError() for
+ * more information.
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_DuplicateSurface(SDL_Surface * surface);
+
+/**
+ * Copy an existing surface to a new surface of the specified format.
+ *
+ * This function is used to optimize images for faster *repeat* blitting. This
+ * is accomplished by converting the original and storing the result as a new
+ * surface. The new, optimized surface can then be used as the source for
+ * future blits, making them faster.
+ *
+ * \param src the existing SDL_Surface structure to convert
+ * \param fmt the SDL_PixelFormat structure that the new surface is optimized
+ * for
+ * \param flags the flags are unused and should be set to 0; this is a
+ * leftover from SDL 1.2's API
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocFormat
+ * \sa SDL_ConvertSurfaceFormat
+ * \sa SDL_CreateRGBSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface
+ (SDL_Surface * src, const SDL_PixelFormat * fmt, Uint32 flags);
+
+/**
+ * Copy an existing surface to a new surface of the specified format enum.
+ *
+ * This function operates just like SDL_ConvertSurface(), but accepts an
+ * SDL_PixelFormatEnum value instead of an SDL_PixelFormat structure. As such,
+ * it might be easier to call but it doesn't have access to palette
+ * information for the destination surface, in case that would be important.
+ *
+ * \param src the existing SDL_Surface structure to convert
+ * \param pixel_format the SDL_PixelFormatEnum that the new surface is
+ * optimized for
+ * \param flags the flags are unused and should be set to 0; this is a
+ * leftover from SDL 1.2's API
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocFormat
+ * \sa SDL_ConvertSurfaceFormat
+ * \sa SDL_CreateRGBSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat
+ (SDL_Surface * src, Uint32 pixel_format, Uint32 flags);
+
+/**
+ * Copy a block of pixels of one format to another format.
+ *
+ * \param width the width of the block to copy, in pixels
+ * \param height the height of the block to copy, in pixels
+ * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format
+ * \param src a pointer to the source pixels
+ * \param src_pitch the pitch of the block to copy, in bytes
+ * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format
+ * \param dst a pointer to be filled in with new pixel data
+ * \param dst_pitch the pitch of the destination pixels, in bytes
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height,
+ Uint32 src_format,
+ const void * src, int src_pitch,
+ Uint32 dst_format,
+ void * dst, int dst_pitch);
+
+/**
+ * Perform a fast fill of a rectangle with a specific color.
+ *
+ * `color` should be a pixel of the format used by the surface, and can be
+ * generated by SDL_MapRGB() or SDL_MapRGBA(). If the color value contains an
+ * alpha component then the destination is simply filled with that alpha
+ * information, no blending takes place.
+ *
+ * If there is a clip rectangle set on the destination (set via
+ * SDL_SetClipRect()), then this function will fill based on the intersection
+ * of the clip rectangle and `rect`.
+ *
+ * \param dst the SDL_Surface structure that is the drawing target
+ * \param rect the SDL_Rect structure representing the rectangle to fill, or
+ * NULL to fill the entire surface
+ * \param color the color to fill with
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_FillRects
+ */
+extern DECLSPEC int SDLCALL SDL_FillRect
+ (SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
+
+/**
+ * Perform a fast fill of a set of rectangles with a specific color.
+ *
+ * `color` should be a pixel of the format used by the surface, and can be
+ * generated by SDL_MapRGB() or SDL_MapRGBA(). If the color value contains an
+ * alpha component then the destination is simply filled with that alpha
+ * information, no blending takes place.
+ *
+ * If there is a clip rectangle set on the destination (set via
+ * SDL_SetClipRect()), then this function will fill based on the intersection
+ * of the clip rectangle and `rect`.
+ *
+ * \param dst the SDL_Surface structure that is the drawing target
+ * \param rects an array of SDL_Rects representing the rectangles to fill.
+ * \param count the number of rectangles in the array
+ * \param color the color to fill with
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_FillRect
+ */
+extern DECLSPEC int SDLCALL SDL_FillRects
+ (SDL_Surface * dst, const SDL_Rect * rects, int count, Uint32 color);
+
+/* !!! FIXME: merge this documentation with the wiki */
+/**
+ * Performs a fast blit from the source surface to the destination surface.
+ *
+ * This assumes that the source and destination rectangles are
+ * the same size. If either \c srcrect or \c dstrect are NULL, the entire
+ * surface (\c src or \c dst) is copied. The final blit rectangles are saved
+ * in \c srcrect and \c dstrect after all clipping is performed.
+ *
+ * \returns 0 if the blit is successful, otherwise it returns -1.
+ *
+ * The blit function should not be called on a locked surface.
+ *
+ * The blit semantics for surfaces with and without blending and colorkey
+ * are defined as follows:
+ * \verbatim
+ RGBA->RGB:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source alpha-channel and per-surface alpha)
+ SDL_SRCCOLORKEY ignored.
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy RGB.
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ RGB values of the source color key, ignoring alpha in the
+ comparison.
+
+ RGB->RGBA:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source per-surface alpha)
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy RGB, set destination alpha to source per-surface alpha value.
+ both:
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ source color key.
+
+ RGBA->RGBA:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source alpha-channel and per-surface alpha)
+ SDL_SRCCOLORKEY ignored.
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy all of RGBA to the destination.
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ RGB values of the source color key, ignoring alpha in the
+ comparison.
+
+ RGB->RGB:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source per-surface alpha)
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy RGB.
+ both:
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ source color key.
+ \endverbatim
+ *
+ * You should call SDL_BlitSurface() unless you know exactly how SDL
+ * blitting works internally and how to use the other blit functions.
+ */
+#define SDL_BlitSurface SDL_UpperBlit
+
+/**
+ * Perform a fast blit from the source surface to the destination surface.
+ *
+ * SDL_UpperBlit() has been replaced by SDL_BlitSurface(), which is merely a
+ * macro for this function with a less confusing name.
+ *
+ * \sa SDL_BlitSurface
+ */
+extern DECLSPEC int SDLCALL SDL_UpperBlit
+ (SDL_Surface * src, const SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * Perform low-level surface blitting only.
+ *
+ * This is a semi-private blit function and it performs low-level surface
+ * blitting, assuming the input rectangles have already been clipped.
+ *
+ * Unless you know what you're doing, you should be using SDL_BlitSurface()
+ * instead.
+ *
+ * \param src the SDL_Surface structure to be copied from
+ * \param srcrect the SDL_Rect structure representing the rectangle to be
+ * copied, or NULL to copy the entire surface
+ * \param dst the SDL_Surface structure that is the blit target
+ * \param dstrect the SDL_Rect structure representing the rectangle that is
+ * copied into
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ */
+extern DECLSPEC int SDLCALL SDL_LowerBlit
+ (SDL_Surface * src, SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+
+ /**
+ * Perform a fast, low quality, stretch blit between two surfaces of the
+ * same format.
+ *
+ * Please use SDL_BlitScaled() instead.
+ */
+extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src,
+ const SDL_Rect * srcrect,
+ SDL_Surface * dst,
+ const SDL_Rect * dstrect);
+
+/**
+ * Perform bilinear scaling between two surfaces of the same format, 32BPP.
+ */
+extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface * src,
+ const SDL_Rect * srcrect,
+ SDL_Surface * dst,
+ const SDL_Rect * dstrect);
+
+
+#define SDL_BlitScaled SDL_UpperBlitScaled
+
+/**
+ * Perform a scaled surface copy to a destination surface.
+ *
+ * SDL_UpperBlitScaled() has been replaced by SDL_BlitScaled(), which is
+ * merely a macro for this function with a less confusing name.
+ *
+ * \sa SDL_BlitScaled
+ */
+extern DECLSPEC int SDLCALL SDL_UpperBlitScaled
+ (SDL_Surface * src, const SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * Perform low-level surface scaled blitting only.
+ *
+ * This is a semi-private function and it performs low-level surface blitting,
+ * assuming the input rectangles have already been clipped.
+ *
+ * \param src the SDL_Surface structure to be copied from
+ * \param srcrect the SDL_Rect structure representing the rectangle to be
+ * copied
+ * \param dst the SDL_Surface structure that is the blit target
+ * \param dstrect the SDL_Rect structure representing the rectangle that is
+ * copied into
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitScaled
+ */
+extern DECLSPEC int SDLCALL SDL_LowerBlitScaled
+ (SDL_Surface * src, SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * Set the YUV conversion mode
+ */
+extern DECLSPEC void SDLCALL SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode);
+
+/**
+ * Get the YUV conversion mode
+ */
+extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionMode(void);
+
+/**
+ * Get the YUV conversion mode, returning the correct mode for the resolution
+ * when the current conversion mode is SDL_YUV_CONVERSION_AUTOMATIC
+ */
+extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionModeForResolution(int width, int height);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_surface_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_system.h b/Client/ThirdParty/SDL2/SDL_system.h
new file mode 100644
index 0000000..5f12787
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_system.h
@@ -0,0 +1,475 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_system.h
+ *
+ * Include file for platform specific SDL API functions
+ */
+
+#ifndef SDL_system_h_
+#define SDL_system_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_keyboard.h"
+#include "SDL_render.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Platform specific functions for Windows */
+#ifdef __WIN32__
+
+typedef void (SDLCALL * SDL_WindowsMessageHook)(void *userdata, void *hWnd, unsigned int message, Uint64 wParam, Sint64 lParam);
+
+/**
+ * Set a callback for every Windows message, run before TranslateMessage().
+ *
+ * \param callback The SDL_WindowsMessageHook function to call.
+ * \param userdata a pointer to pass to every iteration of `callback`
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata);
+
+/**
+ * Get the D3D9 adapter index that matches the specified display index.
+ *
+ * The returned adapter index can be passed to `IDirect3D9::CreateDevice` and
+ * controls on which monitor a full screen application will appear.
+ *
+ * \param displayIndex the display index for which to get the D3D9 adapter
+ * index
+ * \returns the D3D9 adapter index on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex( int displayIndex );
+
+typedef struct IDirect3DDevice9 IDirect3DDevice9;
+
+/**
+ * Get the D3D9 device associated with a renderer.
+ *
+ * Once you are done using the device, you should release it to avoid a
+ * resource leak.
+ *
+ * \param renderer the renderer from which to get the associated D3D device
+ * \returns the D3D9 device associated with given renderer or NULL if it is
+ * not a D3D9 renderer; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer);
+
+typedef struct ID3D11Device ID3D11Device;
+
+/**
+ * Get the D3D11 device associated with a renderer.
+ *
+ * Once you are done using the device, you should release it to avoid a
+ * resource leak.
+ *
+ * \param renderer the renderer from which to get the associated D3D11 device
+ * \returns the D3D11 device associated with given renderer or NULL if it is
+ * not a D3D11 renderer; call SDL_GetError() for more information.
+ */
+extern DECLSPEC ID3D11Device* SDLCALL SDL_RenderGetD3D11Device(SDL_Renderer * renderer);
+
+/**
+ * Get the DXGI Adapter and Output indices for the specified display index.
+ *
+ * The DXGI Adapter and Output indices can be passed to `EnumAdapters` and
+ * `EnumOutputs` respectively to get the objects required to create a DX10 or
+ * DX11 device and swap chain.
+ *
+ * Before SDL 2.0.4 this function did not return a value. Since SDL 2.0.4 it
+ * returns an SDL_bool.
+ *
+ * \param displayIndex the display index for which to get both indices
+ * \param adapterIndex a pointer to be filled in with the adapter index
+ * \param outputIndex a pointer to be filled in with the output index
+ * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.2.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex );
+
+#endif /* __WIN32__ */
+
+
+/* Platform specific functions for Linux */
+#ifdef __LINUX__
+
+/**
+ * Sets the UNIX nice value for a thread.
+ *
+ * This uses setpriority() if possible, and RealtimeKit if available.
+ *
+ * \param threadID the Unix thread ID to change priority of.
+ * \param priority The new, Unix-specific, priority value.
+ * \returns 0 on success, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority);
+
+#endif /* __LINUX__ */
+
+/* Platform specific functions for iOS */
+#ifdef __IPHONEOS__
+
+#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam)
+extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
+
+#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled)
+extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
+
+#endif /* __IPHONEOS__ */
+
+
+/* Platform specific functions for Android */
+#ifdef __ANDROID__
+
+/**
+ * Get the Android Java Native Interface Environment of the current thread.
+ *
+ * This is the JNIEnv one needs to access the Java virtual machine from native
+ * code, and is needed for many Android APIs to be usable from C.
+ *
+ * The prototype of the function in SDL's code actually declare a void* return
+ * type, even if the implementation returns a pointer to a JNIEnv. The
+ * rationale being that the SDL headers can avoid including jni.h.
+ *
+ * \returns a pointer to Java native interface object (JNIEnv) to which the
+ * current thread is attached, or 0 on error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetActivity
+ */
+extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(void);
+
+/**
+ * Retrieve the Java instance of the Android activity class.
+ *
+ * The prototype of the function in SDL's code actually declares a void*
+ * return type, even if the implementation returns a jobject. The rationale
+ * being that the SDL headers can avoid including jni.h.
+ *
+ * The jobject returned by the function is a local reference and must be
+ * released by the caller. See the PushLocalFrame() and PopLocalFrame() or
+ * DeleteLocalRef() functions of the Java native interface:
+ *
+ * https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html
+ *
+ * \returns the jobject representing the instance of the Activity class of the
+ * Android application, or NULL on error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetJNIEnv
+ */
+extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void);
+
+/**
+ * Query Android API level of the current device.
+ *
+ * - API level 30: Android 11
+ * - API level 29: Android 10
+ * - API level 28: Android 9
+ * - API level 27: Android 8.1
+ * - API level 26: Android 8.0
+ * - API level 25: Android 7.1
+ * - API level 24: Android 7.0
+ * - API level 23: Android 6.0
+ * - API level 22: Android 5.1
+ * - API level 21: Android 5.0
+ * - API level 20: Android 4.4W
+ * - API level 19: Android 4.4
+ * - API level 18: Android 4.3
+ * - API level 17: Android 4.2
+ * - API level 16: Android 4.1
+ * - API level 15: Android 4.0.3
+ * - API level 14: Android 4.0
+ * - API level 13: Android 3.2
+ * - API level 12: Android 3.1
+ * - API level 11: Android 3.0
+ * - API level 10: Android 2.3.3
+ *
+ * \returns the Android API level.
+ */
+extern DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void);
+
+/**
+ * Query if the application is running on Android TV.
+ *
+ * \returns SDL_TRUE if this is Android TV, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void);
+
+/**
+ * Query if the application is running on a Chromebook.
+ *
+ * \returns SDL_TRUE if this is a Chromebook, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void);
+
+/**
+ * Query if the application is running on a Samsung DeX docking station.
+ *
+ * \returns SDL_TRUE if this is a DeX docking station, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void);
+
+/**
+ * Trigger the Android system back button behavior.
+ */
+extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void);
+
+/**
+ See the official Android developer guide for more information:
+ http://developer.android.com/guide/topics/data/data-storage.html
+*/
+#define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01
+#define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02
+
+/**
+ * Get the path used for internal storage for this application.
+ *
+ * This path is unique to your application and cannot be written to by other
+ * applications.
+ *
+ * Your internal storage path is typically:
+ * `/data/data/your.app.package/files`.
+ *
+ * \returns the path used for internal storage or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetExternalStorageState
+ */
+extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(void);
+
+/**
+ * Get the current state of external storage.
+ *
+ * The current state of external storage, a bitmask of these values:
+ * `SDL_ANDROID_EXTERNAL_STORAGE_READ`, `SDL_ANDROID_EXTERNAL_STORAGE_WRITE`.
+ *
+ * If external storage is currently unavailable, this will return 0.
+ *
+ * \returns the current state of external storage on success or 0 on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetExternalStoragePath
+ */
+extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(void);
+
+/**
+ * Get the path used for external storage for this application.
+ *
+ * This path is unique to your application, but is public and can be written
+ * to by other applications.
+ *
+ * Your external storage path is typically:
+ * `/storage/sdcard0/Android/data/your.app.package/files`.
+ *
+ * \returns the path used for external storage for this application on success
+ * or NULL on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetExternalStorageState
+ */
+extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void);
+
+/**
+ * Request permissions at runtime.
+ *
+ * This blocks the calling thread until the permission is granted or denied.
+ *
+ * \param permission The permission to request.
+ * \returns SDL_TRUE if the permission was granted, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission);
+
+/**
+ * Shows an Android toast notification.
+ *
+ * Toasts are a sort of lightweight notification that are unique to Android.
+ *
+ * https://developer.android.com/guide/topics/ui/notifiers/toasts
+ *
+ * Shows toast in UI thread.
+ *
+ * For the `gravity` parameter, choose a value from here, or -1 if you don't
+ * have a preference:
+ *
+ * https://developer.android.com/reference/android/view/Gravity
+ *
+ * \param message text message to be shown
+ * \param duration 0=short, 1=long
+ * \param gravity where the notification should appear on the screen.
+ * \param xoffset set this parameter only when gravity >=0
+ * \param yoffset set this parameter only when gravity >=0
+ * \returns 0 if success, -1 if any error occurs.
+ */
+extern DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset);
+
+#endif /* __ANDROID__ */
+
+/* Platform specific functions for WinRT */
+#ifdef __WINRT__
+
+/**
+ * \brief WinRT / Windows Phone path types
+ */
+typedef enum
+{
+ /** \brief The installed app's root directory.
+ Files here are likely to be read-only. */
+ SDL_WINRT_PATH_INSTALLED_LOCATION,
+
+ /** \brief The app's local data store. Files may be written here */
+ SDL_WINRT_PATH_LOCAL_FOLDER,
+
+ /** \brief The app's roaming data store. Unsupported on Windows Phone.
+ Files written here may be copied to other machines via a network
+ connection.
+ */
+ SDL_WINRT_PATH_ROAMING_FOLDER,
+
+ /** \brief The app's temporary data store. Unsupported on Windows Phone.
+ Files written here may be deleted at any time. */
+ SDL_WINRT_PATH_TEMP_FOLDER
+} SDL_WinRT_Path;
+
+
+/**
+ * \brief WinRT Device Family
+ */
+typedef enum
+{
+ /** \brief Unknown family */
+ SDL_WINRT_DEVICEFAMILY_UNKNOWN,
+
+ /** \brief Desktop family*/
+ SDL_WINRT_DEVICEFAMILY_DESKTOP,
+
+ /** \brief Mobile family (for example smartphone) */
+ SDL_WINRT_DEVICEFAMILY_MOBILE,
+
+ /** \brief XBox family */
+ SDL_WINRT_DEVICEFAMILY_XBOX,
+} SDL_WinRT_DeviceFamily;
+
+
+/**
+ * Retrieve a WinRT defined path on the local file system.
+ *
+ * Not all paths are available on all versions of Windows. This is especially
+ * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path
+ * for more information on which path types are supported where.
+ *
+ * Documentation on most app-specific path types on WinRT can be found on
+ * MSDN, at the URL:
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
+ *
+ * \param pathType the type of path to retrieve, one of SDL_WinRT_Path
+ * \returns a UCS-2 string (16-bit, wide-char) containing the path, or NULL if
+ * the path is not available for any reason; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.3.
+ *
+ * \sa SDL_WinRTGetFSPathUTF8
+ */
+extern DECLSPEC const wchar_t * SDLCALL SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType);
+
+/**
+ * Retrieve a WinRT defined path on the local file system.
+ *
+ * Not all paths are available on all versions of Windows. This is especially
+ * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path
+ * for more information on which path types are supported where.
+ *
+ * Documentation on most app-specific path types on WinRT can be found on
+ * MSDN, at the URL:
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
+ *
+ * \param pathType the type of path to retrieve, one of SDL_WinRT_Path
+ * \returns a UTF-8 string (8-bit, multi-byte) containing the path, or NULL if
+ * the path is not available for any reason; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.3.
+ *
+ * \sa SDL_WinRTGetFSPathUNICODE
+ */
+extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType);
+
+/**
+ * Detects the device family of WinRT plattform at runtime.
+ *
+ * \returns a value from the SDL_WinRT_DeviceFamily enum.
+ */
+extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily();
+
+#endif /* __WINRT__ */
+
+/**
+ * Query if the current device is a tablet.
+ *
+ * If SDL can't determine this, it will return SDL_FALSE.
+ *
+ * \returns SDL_TRUE if the device is a tablet, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsTablet(void);
+
+/* Functions used by iOS application delegates to notify SDL about state changes */
+extern DECLSPEC void SDLCALL SDL_OnApplicationWillTerminate(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidReceiveMemoryWarning(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationWillResignActive(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidEnterBackground(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationWillEnterForeground(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidBecomeActive(void);
+#ifdef __IPHONEOS__
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void);
+#endif
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_system_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_syswm.h b/Client/ThirdParty/SDL2/SDL_syswm.h
new file mode 100644
index 0000000..046a096
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_syswm.h
@@ -0,0 +1,378 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_syswm.h
+ *
+ * Include file for SDL custom system window manager hooks.
+ */
+
+#ifndef SDL_syswm_h_
+#define SDL_syswm_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_version.h"
+
+/**
+ * \brief SDL_syswm.h
+ *
+ * Your application has access to a special type of event ::SDL_SYSWMEVENT,
+ * which contains window-manager specific information and arrives whenever
+ * an unhandled window event occurs. This event is ignored by default, but
+ * you can enable it with SDL_EventState().
+ */
+struct SDL_SysWMinfo;
+
+#if !defined(SDL_PROTOTYPES_ONLY)
+
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_WINRT)
+#include <Inspectable.h>
+#endif
+
+/* This is the structure for custom window manager events */
+#if defined(SDL_VIDEO_DRIVER_X11)
+#if defined(__APPLE__) && defined(__MACH__)
+/* conflicts with Quickdraw.h */
+#define Cursor X11Cursor
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#if defined(__APPLE__) && defined(__MACH__)
+/* matches the re-define above */
+#undef Cursor
+#endif
+
+#endif /* defined(SDL_VIDEO_DRIVER_X11) */
+
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+#include <directfb.h>
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+#ifdef __OBJC__
+@class NSWindow;
+#else
+typedef struct _NSWindow NSWindow;
+#endif
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+#ifdef __OBJC__
+#include <UIKit/UIKit.h>
+#else
+typedef struct _UIWindow UIWindow;
+typedef struct _UIViewController UIViewController;
+#endif
+typedef Uint32 GLuint;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+typedef struct ANativeWindow ANativeWindow;
+typedef void *EGLSurface;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+#include "SDL_egl.h"
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_OS2)
+#define INCL_WIN
+#include <os2.h>
+#endif
+#endif /* SDL_PROTOTYPES_ONLY */
+
+#if defined(SDL_VIDEO_DRIVER_KMSDRM)
+struct gbm_device;
+#endif
+
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(SDL_PROTOTYPES_ONLY)
+/**
+ * These are the various supported windowing subsystems
+ */
+typedef enum
+{
+ SDL_SYSWM_UNKNOWN,
+ SDL_SYSWM_WINDOWS,
+ SDL_SYSWM_X11,
+ SDL_SYSWM_DIRECTFB,
+ SDL_SYSWM_COCOA,
+ SDL_SYSWM_UIKIT,
+ SDL_SYSWM_WAYLAND,
+ SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
+ SDL_SYSWM_WINRT,
+ SDL_SYSWM_ANDROID,
+ SDL_SYSWM_VIVANTE,
+ SDL_SYSWM_OS2,
+ SDL_SYSWM_HAIKU,
+ SDL_SYSWM_KMSDRM
+} SDL_SYSWM_TYPE;
+
+/**
+ * The custom event structure.
+ */
+struct SDL_SysWMmsg
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ struct {
+ HWND hwnd; /**< The window for the message */
+ UINT msg; /**< The type of message */
+ WPARAM wParam; /**< WORD message parameter */
+ LPARAM lParam; /**< LONG message parameter */
+ } win;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ struct {
+ XEvent event;
+ } x11;
+#endif
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ struct {
+ DFBEvent event;
+ } dfb;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ struct
+ {
+ /* Latest version of Xcode clang complains about empty structs in C v. C++:
+ error: empty struct has size 0 in C, size 1 in C++
+ */
+ int dummy;
+ /* No Cocoa window events yet */
+ } cocoa;
+#endif
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+ struct
+ {
+ int dummy;
+ /* No UIKit window events yet */
+ } uikit;
+#endif
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ struct
+ {
+ int dummy;
+ /* No Vivante window events yet */
+ } vivante;
+#endif
+#if defined(SDL_VIDEO_DRIVER_OS2)
+ struct
+ {
+ BOOL fFrame; /**< TRUE if hwnd is a frame window */
+ HWND hwnd; /**< The window receiving the message */
+ ULONG msg; /**< The message identifier */
+ MPARAM mp1; /**< The first first message parameter */
+ MPARAM mp2; /**< The second first message parameter */
+ } os2;
+#endif
+ /* Can't have an empty union */
+ int dummy;
+ } msg;
+};
+
+/**
+ * The custom window manager information structure.
+ *
+ * When this structure is returned, it holds information about which
+ * low level system it is using, and will be one of SDL_SYSWM_TYPE.
+ */
+struct SDL_SysWMinfo
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ struct
+ {
+ HWND window; /**< The window handle */
+ HDC hdc; /**< The window device context */
+ HINSTANCE hinstance; /**< The instance handle */
+ } win;
+#endif
+#if defined(SDL_VIDEO_DRIVER_WINRT)
+ struct
+ {
+ IInspectable * window; /**< The WinRT CoreWindow */
+ } winrt;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ struct
+ {
+ Display *display; /**< The X11 display */
+ Window window; /**< The X11 window */
+ } x11;
+#endif
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ struct
+ {
+ IDirectFB *dfb; /**< The directfb main interface */
+ IDirectFBWindow *window; /**< The directfb window handle */
+ IDirectFBSurface *surface; /**< The directfb client surface */
+ } dfb;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ struct
+ {
+#if defined(__OBJC__) && defined(__has_feature)
+ #if __has_feature(objc_arc)
+ NSWindow __unsafe_unretained *window; /**< The Cocoa window */
+ #else
+ NSWindow *window; /**< The Cocoa window */
+ #endif
+#else
+ NSWindow *window; /**< The Cocoa window */
+#endif
+ } cocoa;
+#endif
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+ struct
+ {
+#if defined(__OBJC__) && defined(__has_feature)
+ #if __has_feature(objc_arc)
+ UIWindow __unsafe_unretained *window; /**< The UIKit window */
+ #else
+ UIWindow *window; /**< The UIKit window */
+ #endif
+#else
+ UIWindow *window; /**< The UIKit window */
+#endif
+ GLuint framebuffer; /**< The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */
+ GLuint colorbuffer; /**< The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */
+ GLuint resolveFramebuffer; /**< The Framebuffer Object which holds the resolve color Renderbuffer, when MSAA is used. */
+ } uikit;
+#endif
+#if defined(SDL_VIDEO_DRIVER_WAYLAND)
+ struct
+ {
+ struct wl_display *display; /**< Wayland display */
+ struct wl_surface *surface; /**< Wayland surface */
+ void *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
+ struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */
+ struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */
+ } wl;
+#endif
+#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
+ struct
+ {
+ void *connection; /**< Mir display server connection */
+ void *surface; /**< Mir surface */
+ } mir;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+ struct
+ {
+ ANativeWindow *window;
+ EGLSurface surface;
+ } android;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_OS2)
+ struct
+ {
+ HWND hwnd; /**< The window handle */
+ HWND hwndFrame; /**< The frame window handle */
+ } os2;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ struct
+ {
+ EGLNativeDisplayType display;
+ EGLNativeWindowType window;
+ } vivante;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_KMSDRM)
+ struct
+ {
+ int dev_index; /**< Device index (ex: the X in /dev/dri/cardX) */
+ int drm_fd; /**< DRM FD (unavailable on Vulkan windows) */
+ struct gbm_device *gbm_dev; /**< GBM device (unavailable on Vulkan windows) */
+ } kmsdrm;
+#endif
+
+ /* Make sure this union is always 64 bytes (8 64-bit pointers). */
+ /* Be careful not to overflow this if you add a new target! */
+ Uint8 dummy[64];
+ } info;
+};
+
+#endif /* SDL_PROTOTYPES_ONLY */
+
+typedef struct SDL_SysWMinfo SDL_SysWMinfo;
+
+
+/**
+ * Get driver-specific information about a window.
+ *
+ * You must include SDL_syswm.h for the declaration of SDL_SysWMinfo.
+ *
+ * The caller must initialize the `info` structure's version by using
+ * `SDL_VERSION(&info.version)`, and then this function will fill in the rest
+ * of the structure with information about the given window.
+ *
+ * \param window the window about which information is being requested
+ * \param info an SDL_SysWMinfo structure filled in with window information
+ * \returns SDL_TRUE if the function is implemented and the `version` member
+ * of the `info` struct is valid, or SDL_FALSE if the information
+ * could not be retrieved; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowWMInfo(SDL_Window * window,
+ SDL_SysWMinfo * info);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_syswm_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test.h b/Client/ThirdParty/SDL2/SDL_test.h
new file mode 100644
index 0000000..66fde83
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test.h
@@ -0,0 +1,69 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_h_
+#define SDL_test_h_
+
+#include "SDL.h"
+#include "SDL_test_assert.h"
+#include "SDL_test_common.h"
+#include "SDL_test_compare.h"
+#include "SDL_test_crc32.h"
+#include "SDL_test_font.h"
+#include "SDL_test_fuzzer.h"
+#include "SDL_test_harness.h"
+#include "SDL_test_images.h"
+#include "SDL_test_log.h"
+#include "SDL_test_md5.h"
+#include "SDL_test_memory.h"
+#include "SDL_test_random.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global definitions */
+
+/*
+ * Note: Maximum size of SDLTest log message is less than SDL's limit
+ * to ensure we can fit additional information such as the timestamp.
+ */
+#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_assert.h b/Client/ThirdParty/SDL2/SDL_test_assert.h
new file mode 100644
index 0000000..d8e9d7d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_assert.h
@@ -0,0 +1,105 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_assert.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ *
+ * Assert API for test code and test cases
+ *
+ */
+
+#ifndef SDL_test_assert_h_
+#define SDL_test_assert_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Fails the assert.
+ */
+#define ASSERT_FAIL 0
+
+/**
+ * \brief Passes the assert.
+ */
+#define ASSERT_PASS 1
+
+/**
+ * \brief Assert that logs and break execution flow on failures.
+ *
+ * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0).
+ * \param assertDescription Message to log with the assert describing it.
+ */
+void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * \brief Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters.
+ *
+ * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0).
+ * \param assertDescription Message to log with the assert describing it.
+ *
+ * \returns the assertCondition so it can be used to externally to break execution flow if desired.
+ */
+int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * \brief Explicitly pass without checking an assertion condition. Updates assertion counter.
+ *
+ * \param assertDescription Message to log with the assert describing it.
+ */
+void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * \brief Resets the assert summary counters to zero.
+ */
+void SDLTest_ResetAssertSummary(void);
+
+/**
+ * \brief Logs summary of all assertions (total, pass, fail) since last reset as INFO or ERROR.
+ */
+void SDLTest_LogAssertSummary(void);
+
+
+/**
+ * \brief Converts the current assert summary state to a test result.
+ *
+ * \returns TEST_RESULT_PASSED, TEST_RESULT_FAILED, or TEST_RESULT_NO_ASSERT
+ */
+int SDLTest_AssertSummaryToTestResult(void);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_assert_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_common.h b/Client/ThirdParty/SDL2/SDL_test_common.h
new file mode 100644
index 0000000..97f036d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_common.h
@@ -0,0 +1,230 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_common.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/* Ported from original test\common.h file. */
+
+#ifndef SDL_test_common_h_
+#define SDL_test_common_h_
+
+#include "SDL.h"
+
+#if defined(__PSP__)
+#define DEFAULT_WINDOW_WIDTH 480
+#define DEFAULT_WINDOW_HEIGHT 272
+#elif defined(__VITA__)
+#define DEFAULT_WINDOW_WIDTH 960
+#define DEFAULT_WINDOW_HEIGHT 544
+#else
+#define DEFAULT_WINDOW_WIDTH 640
+#define DEFAULT_WINDOW_HEIGHT 480
+#endif
+
+#define VERBOSE_VIDEO 0x00000001
+#define VERBOSE_MODES 0x00000002
+#define VERBOSE_RENDER 0x00000004
+#define VERBOSE_EVENT 0x00000008
+#define VERBOSE_AUDIO 0x00000010
+
+typedef struct
+{
+ /* SDL init flags */
+ char **argv;
+ Uint32 flags;
+ Uint32 verbose;
+
+ /* Video info */
+ const char *videodriver;
+ int display;
+ const char *window_title;
+ const char *window_icon;
+ Uint32 window_flags;
+ SDL_bool flash_on_focus_loss;
+ int window_x;
+ int window_y;
+ int window_w;
+ int window_h;
+ int window_minW;
+ int window_minH;
+ int window_maxW;
+ int window_maxH;
+ int logical_w;
+ int logical_h;
+ float scale;
+ int depth;
+ int refresh_rate;
+ int num_windows;
+ SDL_Window **windows;
+
+ /* Renderer info */
+ const char *renderdriver;
+ Uint32 render_flags;
+ SDL_bool skip_renderer;
+ SDL_Renderer **renderers;
+ SDL_Texture **targets;
+
+ /* Audio info */
+ const char *audiodriver;
+ SDL_AudioSpec audiospec;
+
+ /* GL settings */
+ int gl_red_size;
+ int gl_green_size;
+ int gl_blue_size;
+ int gl_alpha_size;
+ int gl_buffer_size;
+ int gl_depth_size;
+ int gl_stencil_size;
+ int gl_double_buffer;
+ int gl_accum_red_size;
+ int gl_accum_green_size;
+ int gl_accum_blue_size;
+ int gl_accum_alpha_size;
+ int gl_stereo;
+ int gl_multisamplebuffers;
+ int gl_multisamplesamples;
+ int gl_retained_backing;
+ int gl_accelerated;
+ int gl_major_version;
+ int gl_minor_version;
+ int gl_debug;
+ int gl_profile_mask;
+} SDLTest_CommonState;
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+/**
+ * \brief Parse command line parameters and create common state.
+ *
+ * \param argv Array of command line parameters
+ * \param flags Flags indicating which subsystem to initialize (i.e. SDL_INIT_VIDEO | SDL_INIT_AUDIO)
+ *
+ * \returns a newly allocated common state object.
+ */
+SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags);
+
+/**
+ * \brief Process one common argument.
+ *
+ * \param state The common state describing the test window to create.
+ * \param index The index of the argument to process in argv[].
+ *
+ * \returns the number of arguments processed (i.e. 1 for --fullscreen, 2 for --video [videodriver], or -1 on error.
+ */
+int SDLTest_CommonArg(SDLTest_CommonState * state, int index);
+
+
+/**
+ * \brief Logs command line usage info.
+ *
+ * This logs the appropriate command line options for the subsystems in use
+ * plus other common options, and then any application-specific options.
+ * This uses the SDL_Log() function and splits up output to be friendly to
+ * 80-character-wide terminals.
+ *
+ * \param state The common state describing the test window for the app.
+ * \param argv0 argv[0], as passed to main/SDL_main.
+ * \param options an array of strings for application specific options. The last element of the array should be NULL.
+ */
+void SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options);
+
+/**
+ * \brief Returns common usage information
+ *
+ * You should (probably) be using SDLTest_CommonLogUsage() instead, but this
+ * function remains for binary compatibility. Strings returned from this
+ * function are valid until SDLTest_CommonQuit() is called, in which case
+ * those strings' memory is freed and can no longer be used.
+ *
+ * \param state The common state describing the test window to create.
+ * \returns a string with usage information
+ */
+const char *SDLTest_CommonUsage(SDLTest_CommonState * state);
+
+/**
+ * \brief Open test window.
+ *
+ * \param state The common state describing the test window to create.
+ *
+ * \returns SDL_TRUE if initialization succeeded, false otherwise
+ */
+SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state);
+
+/**
+ * \brief Easy argument handling when test app doesn't need any custom args.
+ *
+ * \param state The common state describing the test window to create.
+ * \param argc argc, as supplied to SDL_main
+ * \param argv argv, as supplied to SDL_main
+ *
+ * \returns SDL_FALSE if app should quit, true otherwise.
+ */
+SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState * state, const int argc, char **argv);
+
+/**
+ * \brief Common event handler for test windows.
+ *
+ * \param state The common state used to create test window.
+ * \param event The event to handle.
+ * \param done Flag indicating we are done.
+ *
+ */
+void SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done);
+
+/**
+ * \brief Close test window.
+ *
+ * \param state The common state used to create test window.
+ *
+ */
+void SDLTest_CommonQuit(SDLTest_CommonState * state);
+
+/**
+ * \brief Draws various window information (position, size, etc.) to the renderer.
+ *
+ * \param renderer The renderer to draw to.
+ * \param window The window whose information should be displayed.
+ *
+ */
+void SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_common_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_compare.h b/Client/ThirdParty/SDL2/SDL_test_compare.h
new file mode 100644
index 0000000..ee42c9d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_compare.h
@@ -0,0 +1,69 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_compare.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Defines comparison functions (i.e. for surfaces).
+
+*/
+
+#ifndef SDL_test_compare_h_
+#define SDL_test_compare_h_
+
+#include "SDL.h"
+
+#include "SDL_test_images.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Compares a surface and with reference image data for equality
+ *
+ * \param surface Surface used in comparison
+ * \param referenceSurface Test Surface used in comparison
+ * \param allowable_error Allowable difference (=sum of squared difference for each RGB component) in blending accuracy.
+ *
+ * \returns 0 if comparison succeeded, >0 (=number of pixels for which the comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ.
+ */
+int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_compare_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_crc32.h b/Client/ThirdParty/SDL2/SDL_test_crc32.h
new file mode 100644
index 0000000..f41e24e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_crc32.h
@@ -0,0 +1,124 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_crc32.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Implements CRC32 calculations (default output is Perl String::CRC32 compatible).
+
+*/
+
+#ifndef SDL_test_crc32_h_
+#define SDL_test_crc32_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ------------ Definitions --------- */
+
+/* Definition shared by all CRC routines */
+
+#ifndef CrcUint32
+ #define CrcUint32 unsigned int
+#endif
+#ifndef CrcUint8
+ #define CrcUint8 unsigned char
+#endif
+
+#ifdef ORIGINAL_METHOD
+ #define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+#else
+ #define CRC32_POLY 0xEDB88320 /* Perl String::CRC32 compatible */
+#endif
+
+/**
+ * Data structure for CRC32 (checksum) computation
+ */
+ typedef struct {
+ CrcUint32 crc32_table[256]; /* CRC table */
+ } SDLTest_Crc32Context;
+
+/* ---------- Function Prototypes ------------- */
+
+/**
+ * \brief Initialize the CRC context
+ *
+ * Note: The function initializes the crc table required for all crc calculations.
+ *
+ * \param crcContext pointer to context variable
+ *
+ * \returns 0 for OK, -1 on error
+ *
+ */
+ int SDLTest_Crc32Init(SDLTest_Crc32Context * crcContext);
+
+
+/**
+ * \brief calculate a crc32 from a data block
+ *
+ * \param crcContext pointer to context variable
+ * \param inBuf input buffer to checksum
+ * \param inLen length of input buffer
+ * \param crc32 pointer to Uint32 to store the final CRC into
+ *
+ * \returns 0 for OK, -1 on error
+ *
+ */
+int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+
+/* Same routine broken down into three steps */
+int SDLTest_Crc32CalcStart(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);
+int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);
+int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+
+
+/**
+ * \brief clean up CRC context
+ *
+ * \param crcContext pointer to context variable
+ *
+ * \returns 0 for OK, -1 on error
+ *
+*/
+
+int SDLTest_Crc32Done(SDLTest_Crc32Context * crcContext);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_crc32_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_font.h b/Client/ThirdParty/SDL2/SDL_test_font.h
new file mode 100644
index 0000000..daa6670
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_font.h
@@ -0,0 +1,81 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_font.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_font_h_
+#define SDL_test_font_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+#define FONT_CHARACTER_SIZE 8
+
+/**
+ * \brief Draw a string in the currently set font.
+ *
+ * \param renderer The renderer to draw on.
+ * \param x The X coordinate of the upper left corner of the character.
+ * \param y The Y coordinate of the upper left corner of the character.
+ * \param c The character to draw.
+ *
+ * \returns 0 on success, -1 on failure.
+ */
+int SDLTest_DrawCharacter(SDL_Renderer *renderer, int x, int y, char c);
+
+/**
+ * \brief Draw a string in the currently set font.
+ *
+ * \param renderer The renderer to draw on.
+ * \param x The X coordinate of the upper left corner of the string.
+ * \param y The Y coordinate of the upper left corner of the string.
+ * \param s The string to draw.
+ *
+ * \returns 0 on success, -1 on failure.
+ */
+int SDLTest_DrawString(SDL_Renderer *renderer, int x, int y, const char *s);
+
+
+/**
+ * \brief Cleanup textures used by font drawing functions.
+ */
+void SDLTest_CleanupTextDrawing(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_font_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_fuzzer.h b/Client/ThirdParty/SDL2/SDL_test_fuzzer.h
new file mode 100644
index 0000000..84278bf
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_fuzzer.h
@@ -0,0 +1,386 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_fuzzer.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Data generators for fuzzing test data in a reproducible way.
+
+*/
+
+#ifndef SDL_test_fuzzer_h_
+#define SDL_test_fuzzer_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ Based on GSOC code by Markus Kauppila <markus.kauppila@gmail.com>
+*/
+
+
+/**
+ * \file
+ * Note: The fuzzer implementation uses a static instance of random context
+ * internally which makes it thread-UNsafe.
+ */
+
+/**
+ * Initializes the fuzzer for a test
+ *
+ * \param execKey Execution "Key" that initializes the random number generator uniquely for the test.
+ *
+ */
+void SDLTest_FuzzerInit(Uint64 execKey);
+
+
+/**
+ * Returns a random Uint8
+ *
+ * \returns a generated integer
+ */
+Uint8 SDLTest_RandomUint8(void);
+
+/**
+ * Returns a random Sint8
+ *
+ * \returns a generated signed integer
+ */
+Sint8 SDLTest_RandomSint8(void);
+
+
+/**
+ * Returns a random Uint16
+ *
+ * \returns a generated integer
+ */
+Uint16 SDLTest_RandomUint16(void);
+
+/**
+ * Returns a random Sint16
+ *
+ * \returns a generated signed integer
+ */
+Sint16 SDLTest_RandomSint16(void);
+
+
+/**
+ * Returns a random integer
+ *
+ * \returns a generated integer
+ */
+Sint32 SDLTest_RandomSint32(void);
+
+
+/**
+ * Returns a random positive integer
+ *
+ * \returns a generated integer
+ */
+Uint32 SDLTest_RandomUint32(void);
+
+/**
+ * Returns random Uint64.
+ *
+ * \returns a generated integer
+ */
+Uint64 SDLTest_RandomUint64(void);
+
+
+/**
+ * Returns random Sint64.
+ *
+ * \returns a generated signed integer
+ */
+Sint64 SDLTest_RandomSint64(void);
+
+/**
+ * \returns a random float in range [0.0 - 1.0]
+ */
+float SDLTest_RandomUnitFloat(void);
+
+/**
+ * \returns a random double in range [0.0 - 1.0]
+ */
+double SDLTest_RandomUnitDouble(void);
+
+/**
+ * \returns a random float.
+ *
+ */
+float SDLTest_RandomFloat(void);
+
+/**
+ * \returns a random double.
+ *
+ */
+double SDLTest_RandomDouble(void);
+
+/**
+ * Returns a random boundary value for Uint8 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint8BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint8BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint8BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint8BoundaryValue(0, 255, SDL_FALSE) returns 0 (error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Uint16 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint16BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint16BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint16BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint16BoundaryValue(0, 0xFFFF, SDL_FALSE) returns 0 (error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Uint32 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint32BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint32BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint32BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint32BoundaryValue(0, 0xFFFFFFFF, SDL_FALSE) returns 0 (with error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Uint64 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint64BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint64BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint64BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint64BoundaryValue(0, 0xFFFFFFFFFFFFFFFF, SDL_FALSE) returns 0 (with error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Sint8 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint8BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint8BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint8BoundaryValue(SINT8_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint8BoundaryValue(SINT8_MIN, SINT8_MAX, SDL_FALSE) returns SINT8_MIN (== error value) with error set
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT8_MIN with error set
+ */
+Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain);
+
+
+/**
+ * Returns a random boundary value for Sint16 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint16BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint16BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint16BoundaryValue(SINT16_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint16BoundaryValue(SINT16_MIN, SINT16_MAX, SDL_FALSE) returns SINT16_MIN (== error value) with error set
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT16_MIN with error set
+ */
+Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Sint32 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint32BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint32BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint32BoundaryValue(SINT32_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint32BoundaryValue(SINT32_MIN, SINT32_MAX, SDL_FALSE) returns SINT32_MIN (== error value)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT32_MIN with error set
+ */
+Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Sint64 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint64BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint64BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint64BoundaryValue(SINT64_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint64BoundaryValue(SINT64_MIN, SINT64_MAX, SDL_FALSE) returns SINT64_MIN (== error value) and error set
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT64_MIN with error set
+ */
+Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain);
+
+
+/**
+ * Returns integer in range [min, max] (inclusive).
+ * Min and max values can be negative values.
+ * If Max in smaller than min, then the values are swapped.
+ * Min and max are the same value, that value will be returned.
+ *
+ * \param min Minimum inclusive value of returned random number
+ * \param max Maximum inclusive value of returned random number
+ *
+ * \returns a generated random integer in range
+ */
+Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max);
+
+
+/**
+ * Generates random null-terminated string. The minimum length for
+ * the string is 1 character, maximum length for the string is 255
+ * characters and it can contain ASCII characters from 32 to 126.
+ *
+ * Note: Returned string needs to be deallocated.
+ *
+ * \returns a newly allocated random string; or NULL if length was invalid or string could not be allocated.
+ */
+char * SDLTest_RandomAsciiString(void);
+
+
+/**
+ * Generates random null-terminated string. The maximum length for
+ * the string is defined by the maxLength parameter.
+ * String can contain ASCII characters from 32 to 126.
+ *
+ * Note: Returned string needs to be deallocated.
+ *
+ * \param maxLength The maximum length of the generated string.
+ *
+ * \returns a newly allocated random string; or NULL if maxLength was invalid or string could not be allocated.
+ */
+char * SDLTest_RandomAsciiStringWithMaximumLength(int maxLength);
+
+
+/**
+ * Generates random null-terminated string. The length for
+ * the string is defined by the size parameter.
+ * String can contain ASCII characters from 32 to 126.
+ *
+ * Note: Returned string needs to be deallocated.
+ *
+ * \param size The length of the generated string
+ *
+ * \returns a newly allocated random string; or NULL if size was invalid or string could not be allocated.
+ */
+char * SDLTest_RandomAsciiStringOfSize(int size);
+
+/**
+ * Get the invocation count for the fuzzer since last ...FuzzerInit.
+ *
+ * \returns the invocation count.
+ */
+int SDLTest_GetFuzzerInvocationCount(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_fuzzer_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_harness.h b/Client/ThirdParty/SDL2/SDL_test_harness.h
new file mode 100644
index 0000000..106464c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_harness.h
@@ -0,0 +1,134 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_harness.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ Defines types for test case definitions and the test execution harness API.
+
+ Based on original GSOC code by Markus Kauppila <markus.kauppila@gmail.com>
+*/
+
+#ifndef SDL_test_h_arness_h
+#define SDL_test_h_arness_h
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ! Definitions for test case structures */
+#define TEST_ENABLED 1
+#define TEST_DISABLED 0
+
+/* ! Definition of all the possible test return values of the test case method */
+#define TEST_ABORTED -1
+#define TEST_STARTED 0
+#define TEST_COMPLETED 1
+#define TEST_SKIPPED 2
+
+/* ! Definition of all the possible test results for the harness */
+#define TEST_RESULT_PASSED 0
+#define TEST_RESULT_FAILED 1
+#define TEST_RESULT_NO_ASSERT 2
+#define TEST_RESULT_SKIPPED 3
+#define TEST_RESULT_SETUP_FAILURE 4
+
+/* !< Function pointer to a test case setup function (run before every test) */
+typedef void (*SDLTest_TestCaseSetUpFp)(void *arg);
+
+/* !< Function pointer to a test case function */
+typedef int (*SDLTest_TestCaseFp)(void *arg);
+
+/* !< Function pointer to a test case teardown function (run after every test) */
+typedef void (*SDLTest_TestCaseTearDownFp)(void *arg);
+
+/**
+ * Holds information about a single test case.
+ */
+typedef struct SDLTest_TestCaseReference {
+ /* !< Func2Stress */
+ SDLTest_TestCaseFp testCase;
+ /* !< Short name (or function name) "Func2Stress" */
+ char *name;
+ /* !< Long name or full description "This test pushes func2() to the limit." */
+ char *description;
+ /* !< Set to TEST_ENABLED or TEST_DISABLED (test won't be run) */
+ int enabled;
+} SDLTest_TestCaseReference;
+
+/**
+ * Holds information about a test suite (multiple test cases).
+ */
+typedef struct SDLTest_TestSuiteReference {
+ /* !< "PlatformSuite" */
+ char *name;
+ /* !< The function that is run before each test. NULL skips. */
+ SDLTest_TestCaseSetUpFp testSetUp;
+ /* !< The test cases that are run as part of the suite. Last item should be NULL. */
+ const SDLTest_TestCaseReference **testCases;
+ /* !< The function that is run after each test. NULL skips. */
+ SDLTest_TestCaseTearDownFp testTearDown;
+} SDLTest_TestSuiteReference;
+
+
+/**
+ * \brief Generates a random run seed string for the harness. The generated seed will contain alphanumeric characters (0-9A-Z).
+ *
+ * Note: The returned string needs to be deallocated by the caller.
+ *
+ * \param length The length of the seed string to generate
+ *
+ * \returns the generated seed string
+ */
+char *SDLTest_GenerateRunSeed(const int length);
+
+/**
+ * \brief Execute a test suite using the given run seed and execution key.
+ *
+ * \param testSuites Suites containing the test case.
+ * \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one.
+ * \param userExecKey Custom execution key provided by user, or 0 to autogenerate one.
+ * \param filter Filter specification. NULL disables. Case sensitive.
+ * \param testIterations Number of iterations to run each test case.
+ *
+ * \returns the test run result: 0 when all tests passed, 1 if any tests failed.
+ */
+int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_h_arness_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_images.h b/Client/ThirdParty/SDL2/SDL_test_images.h
new file mode 100644
index 0000000..a379cf1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_images.h
@@ -0,0 +1,78 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_images.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Defines some images for tests.
+
+*/
+
+#ifndef SDL_test_images_h_
+#define SDL_test_images_h_
+
+#include "SDL.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *Type for test images.
+ */
+typedef struct SDLTest_SurfaceImage_s {
+ int width;
+ int height;
+ unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
+ const char *pixel_data;
+} SDLTest_SurfaceImage_t;
+
+/* Test images */
+SDL_Surface *SDLTest_ImageBlit(void);
+SDL_Surface *SDLTest_ImageBlitColor(void);
+SDL_Surface *SDLTest_ImageBlitAlpha(void);
+SDL_Surface *SDLTest_ImageBlitBlendAdd(void);
+SDL_Surface *SDLTest_ImageBlitBlend(void);
+SDL_Surface *SDLTest_ImageBlitBlendMod(void);
+SDL_Surface *SDLTest_ImageBlitBlendNone(void);
+SDL_Surface *SDLTest_ImageBlitBlendAll(void);
+SDL_Surface *SDLTest_ImageFace(void);
+SDL_Surface *SDLTest_ImagePrimitives(void);
+SDL_Surface *SDLTest_ImagePrimitivesBlend(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_images_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_log.h b/Client/ThirdParty/SDL2/SDL_test_log.h
new file mode 100644
index 0000000..0caddca
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_log.h
@@ -0,0 +1,67 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_log.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ *
+ * Wrapper to log in the TEST category
+ *
+ */
+
+#ifndef SDL_test_log_h_
+#define SDL_test_log_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Prints given message with a timestamp in the TEST category and INFO priority.
+ *
+ * \param fmt Message to be logged
+ */
+void SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * \brief Prints given message with a timestamp in the TEST category and the ERROR priority.
+ *
+ * \param fmt Message to be logged
+ */
+void SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_log_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_md5.h b/Client/ThirdParty/SDL2/SDL_test_md5.h
new file mode 100644
index 0000000..ca29757
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_md5.h
@@ -0,0 +1,129 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_md5.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ ***********************************************************************
+ ** Header file for implementation of MD5 **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ ** Revised (for MD5): RLR 4/27/91 **
+ ** -- G modified to have y&~z instead of y&z **
+ ** -- FF, GG, HH modified to add in last register done **
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
+ ** -- distinct additive constant for each step **
+ ** -- round 4 added, working mod 7 **
+ ***********************************************************************
+*/
+
+/*
+ ***********************************************************************
+ ** Message-digest routines: **
+ ** To form the message digest for a message M **
+ ** (1) Initialize a context buffer mdContext using MD5Init **
+ ** (2) Call MD5Update on mdContext and M **
+ ** (3) Call MD5Final on mdContext **
+ ** The message digest is now in mdContext->digest[0...15] **
+ ***********************************************************************
+*/
+
+#ifndef SDL_test_md5_h_
+#define SDL_test_md5_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------ Definitions --------- */
+
+/* typedef a 32-bit type */
+ typedef unsigned long int MD5UINT4;
+
+/* Data structure for MD5 (Message-Digest) computation */
+ typedef struct {
+ MD5UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ MD5UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after Md5Final call */
+ } SDLTest_Md5Context;
+
+/* ---------- Function Prototypes ------------- */
+
+/**
+ * \brief initialize the context
+ *
+ * \param mdContext pointer to context variable
+ *
+ * Note: The function initializes the message-digest context
+ * mdContext. Call before each new use of the context -
+ * all fields are set to zero.
+ */
+ void SDLTest_Md5Init(SDLTest_Md5Context * mdContext);
+
+
+/**
+ * \brief update digest from variable length data
+ *
+ * \param mdContext pointer to context variable
+ * \param inBuf pointer to data array/string
+ * \param inLen length of data array/string
+ *
+ * Note: The function updates the message-digest context to account
+ * for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+*/
+
+ void SDLTest_Md5Update(SDLTest_Md5Context * mdContext, unsigned char *inBuf,
+ unsigned int inLen);
+
+
+/**
+ * \brief complete digest computation
+ *
+ * \param mdContext pointer to context variable
+ *
+ * Note: The function terminates the message-digest computation and
+ * ends with the desired message digest in mdContext.digest[0..15].
+ * Always call before using the digest[] variable.
+*/
+
+ void SDLTest_Md5Final(SDLTest_Md5Context * mdContext);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_md5_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_memory.h b/Client/ThirdParty/SDL2/SDL_test_memory.h
new file mode 100644
index 0000000..4a19c1d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_memory.h
@@ -0,0 +1,63 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_memory.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_memory_h_
+#define SDL_test_memory_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief Start tracking SDL memory allocations
+ *
+ * \note This should be called before any other SDL functions for complete tracking coverage
+ */
+int SDLTest_TrackAllocations(void);
+
+/**
+ * \brief Print a log of any outstanding allocations
+ *
+ * \note This can be called after SDL_Quit()
+ */
+void SDLTest_LogAllocations(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_memory_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_test_random.h b/Client/ThirdParty/SDL2/SDL_test_random.h
new file mode 100644
index 0000000..8297f94
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_test_random.h
@@ -0,0 +1,115 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_random.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ A "32-bit Multiply with carry random number generator. Very fast.
+ Includes a list of recommended multipliers.
+
+ multiply-with-carry generator: x(n) = a*x(n-1) + carry mod 2^32.
+ period: (a*2^31)-1
+
+*/
+
+#ifndef SDL_test_random_h_
+#define SDL_test_random_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* --- Definitions */
+
+/*
+ * Macros that return a random number in a specific format.
+ */
+#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c))
+
+/*
+ * Context structure for the random number generator state.
+ */
+ typedef struct {
+ unsigned int a;
+ unsigned int x;
+ unsigned int c;
+ unsigned int ah;
+ unsigned int al;
+ } SDLTest_RandomContext;
+
+
+/* --- Function prototypes */
+
+/**
+ * \brief Initialize random number generator with two integers.
+ *
+ * Note: The random sequence of numbers returned by ...Random() is the
+ * same for the same two integers and has a period of 2^31.
+ *
+ * \param rndContext pointer to context structure
+ * \param xi integer that defines the random sequence
+ * \param ci integer that defines the random sequence
+ *
+ */
+ void SDLTest_RandomInit(SDLTest_RandomContext * rndContext, unsigned int xi,
+ unsigned int ci);
+
+/**
+ * \brief Initialize random number generator based on current system time.
+ *
+ * \param rndContext pointer to context structure
+ *
+ */
+ void SDLTest_RandomInitTime(SDLTest_RandomContext *rndContext);
+
+
+/**
+ * \brief Initialize random number generator based on current system time.
+ *
+ * Note: ...RandomInit() or ...RandomInitTime() must have been called
+ * before using this function.
+ *
+ * \param rndContext pointer to context structure
+ *
+ * \returns a random number (32bit unsigned integer)
+ *
+ */
+ unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_random_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_thread.h b/Client/ThirdParty/SDL2/SDL_thread.h
new file mode 100644
index 0000000..b344150
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_thread.h
@@ -0,0 +1,454 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_thread_h_
+#define SDL_thread_h_
+
+/**
+ * \file SDL_thread.h
+ *
+ * Header for the SDL thread management routines.
+ */
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+/* Thread synchronization primitives */
+#include "SDL_atomic.h"
+#include "SDL_mutex.h"
+
+#if defined(__WIN32__)
+#include <process.h> /* _beginthreadex() and _endthreadex() */
+#endif
+#if defined(__OS2__) /* for _beginthread() and _endthread() */
+#ifndef __EMX__
+#include <process.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The SDL thread structure, defined in SDL_thread.c */
+struct SDL_Thread;
+typedef struct SDL_Thread SDL_Thread;
+
+/* The SDL thread ID */
+typedef unsigned long SDL_threadID;
+
+/* Thread local storage ID, 0 is the invalid ID */
+typedef unsigned int SDL_TLSID;
+
+/**
+ * The SDL thread priority.
+ *
+ * SDL will make system changes as necessary in order to apply the thread priority.
+ * Code which attempts to control thread state related to priority should be aware
+ * that calling SDL_SetThreadPriority may alter such state.
+ * SDL_HINT_THREAD_PRIORITY_POLICY can be used to control aspects of this behavior.
+ *
+ * \note On many systems you require special privileges to set high or time critical priority.
+ */
+typedef enum {
+ SDL_THREAD_PRIORITY_LOW,
+ SDL_THREAD_PRIORITY_NORMAL,
+ SDL_THREAD_PRIORITY_HIGH,
+ SDL_THREAD_PRIORITY_TIME_CRITICAL
+} SDL_ThreadPriority;
+
+/**
+ * The function passed to SDL_CreateThread().
+ *
+ * \param data what was passed as `data` to SDL_CreateThread()
+ * \returns a value that can be reported through SDL_WaitThread().
+ */
+typedef int (SDLCALL * SDL_ThreadFunction) (void *data);
+
+
+#if defined(__WIN32__)
+/**
+ * \file SDL_thread.h
+ *
+ * We compile SDL into a DLL. This means, that it's the DLL which
+ * creates a new thread for the calling process with the SDL_CreateThread()
+ * API. There is a problem with this, that only the RTL of the SDL2.DLL will
+ * be initialized for those threads, and not the RTL of the calling
+ * application!
+ *
+ * To solve this, we make a little hack here.
+ *
+ * We'll always use the caller's _beginthread() and _endthread() APIs to
+ * start a new thread. This way, if it's the SDL2.DLL which uses this API,
+ * then the RTL of SDL2.DLL will be used to create the new thread, and if it's
+ * the application, then the RTL of the application will be used.
+ *
+ * So, in short:
+ * Always use the _beginthread() and _endthread() of the calling runtime
+ * library!
+ */
+#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
+
+typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread)
+ (void *, unsigned, unsigned (__stdcall *func)(void *),
+ void * /*arg*/, unsigned, unsigned * /* threadID */);
+typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
+
+#ifndef SDL_beginthread
+#define SDL_beginthread _beginthreadex
+#endif
+#ifndef SDL_endthread
+#define SDL_endthread _endthreadex
+#endif
+
+/**
+ * Create a thread.
+ */
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+ const char *name, const size_t stacksize, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+
+/**
+ * Create a thread.
+ */
+#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
+#undef SDL_CreateThread
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#undef SDL_CreateThreadWithStackSize
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#else
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)SDL_endthread)
+#endif
+
+#elif defined(__OS2__)
+/*
+ * just like the windows case above: We compile SDL2
+ * into a dll with Watcom's runtime statically linked.
+ */
+#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
+
+typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void * /*arg*/);
+typedef void (*pfnSDL_CurrentEndThread)(void);
+
+#ifndef SDL_beginthread
+#define SDL_beginthread _beginthread
+#endif
+#ifndef SDL_endthread
+#define SDL_endthread _endthread
+#endif
+
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
+#undef SDL_CreateThread
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#undef SDL_CreateThreadWithStackSize
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#else
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#endif
+
+#else
+
+/**
+ * Create a new thread with a default stack size.
+ *
+ * This is equivalent to calling:
+ *
+ * ```c
+ * SDL_CreateThreadWithStackSize(fn, name, 0, data);
+ * ```
+ *
+ * \param fn the SDL_ThreadFunction function to call in the new thread
+ * \param name the name of the thread
+ * \param data a pointer that is passed to `fn`
+ * \returns an opaque pointer to the new thread object on success, NULL if the
+ * new thread could not be created; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_CreateThreadWithStackSize
+ * \sa SDL_WaitThread
+ */
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
+
+/**
+ * Create a new thread with a specific stack size.
+ *
+ * SDL makes an attempt to report `name` to the system, so that debuggers can
+ * display it. Not all platforms support this.
+ *
+ * Thread naming is a little complicated: Most systems have very small limits
+ * for the string length (Haiku has 32 bytes, Linux currently has 16, Visual
+ * C++ 6.0 has _nine_!), and possibly other arbitrary rules. You'll have to
+ * see what happens with your system's debugger. The name should be UTF-8 (but
+ * using the naming limits of C identifiers is a better bet). There are no
+ * requirements for thread naming conventions, so long as the string is
+ * null-terminated UTF-8, but these guidelines are helpful in choosing a name:
+ *
+ * https://stackoverflow.com/questions/149932/naming-conventions-for-threads
+ *
+ * If a system imposes requirements, SDL will try to munge the string for it
+ * (truncate, etc), but the original string contents will be available from
+ * SDL_GetThreadName().
+ *
+ * The size (in bytes) of the new stack can be specified. Zero means "use the
+ * system default" which might be wildly different between platforms. x86
+ * Linux generally defaults to eight megabytes, an embedded device might be a
+ * few kilobytes instead. You generally need to specify a stack that is a
+ * multiple of the system's page size (in many cases, this is 4 kilobytes, but
+ * check your system documentation).
+ *
+ * In SDL 2.1, stack size will be folded into the original SDL_CreateThread
+ * function, but for backwards compatibility, this is currently a separate
+ * function.
+ *
+ * \param fn the SDL_ThreadFunction function to call in the new thread
+ * \param name the name of the thread
+ * \param stacksize the size, in bytes, to allocate for the new thread stack.
+ * \param data a pointer that is passed to `fn`
+ * \returns an opaque pointer to the new thread object on success, NULL if the
+ * new thread could not be created; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_WaitThread
+ */
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data);
+
+#endif
+
+/**
+ * Get the thread name as it was specified in SDL_CreateThread().
+ *
+ * This is internal memory, not to be freed by the caller, and remains valid
+ * until the specified thread is cleaned up by SDL_WaitThread().
+ *
+ * \param thread the thread to query
+ * \returns a pointer to a UTF-8 string that names the specified thread, or
+ * NULL if it doesn't have a name.
+ *
+ * \sa SDL_CreateThread
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread);
+
+/**
+ * Get the thread identifier for the current thread.
+ *
+ * This thread identifier is as reported by the underlying operating system.
+ * If SDL is running on a platform that does not support threads the return
+ * value will always be zero.
+ *
+ * This function also returns a valid thread ID when called from the main
+ * thread.
+ *
+ * \returns the ID of the current thread.
+ *
+ * \sa SDL_GetThreadID
+ */
+extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void);
+
+/**
+ * Get the thread identifier for the specified thread.
+ *
+ * This thread identifier is as reported by the underlying operating system.
+ * If SDL is running on a platform that does not support threads the return
+ * value will always be zero.
+ *
+ * \param thread the thread to query
+ * \returns the ID of the specified thread, or the ID of the current thread if
+ * `thread` is NULL.
+ *
+ * \sa SDL_ThreadID
+ */
+extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread);
+
+/**
+ * Set the priority for the current thread.
+ *
+ * Note that some platforms will not let you alter the priority (or at least,
+ * promote the thread to a higher priority) at all, and some require you to be
+ * an administrator account. Be prepared for this to fail.
+ *
+ * \param priority the SDL_ThreadPriority to set
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority);
+
+/**
+ * Wait for a thread to finish.
+ *
+ * Threads that haven't been detached will remain (as a "zombie") until this
+ * function cleans them up. Not doing so is a resource leak.
+ *
+ * Once a thread has been cleaned up through this function, the SDL_Thread
+ * that references it becomes invalid and should not be referenced again. As
+ * such, only one thread may call SDL_WaitThread() on another.
+ *
+ * The return code for the thread function is placed in the area pointed to by
+ * `status`, if `status` is not NULL.
+ *
+ * You may not wait on a thread that has been used in a call to
+ * SDL_DetachThread(). Use either that function or this one, but not both, or
+ * behavior is undefined.
+ *
+ * It is safe to pass a NULL thread to this function; it is a no-op.
+ *
+ * Note that the thread pointer is freed by this function and is not valid
+ * afterward.
+ *
+ * \param thread the SDL_Thread pointer that was returned from the
+ * SDL_CreateThread() call that started this thread
+ * \param status pointer to an integer that will receive the value returned
+ * from the thread function by its 'return', or NULL to not
+ * receive such value back.
+ *
+ * \sa SDL_CreateThread
+ * \sa SDL_DetachThread
+ */
+extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
+
+/**
+ * Let a thread clean up on exit without intervention.
+ *
+ * A thread may be "detached" to signify that it should not remain until
+ * another thread has called SDL_WaitThread() on it. Detaching a thread is
+ * useful for long-running threads that nothing needs to synchronize with or
+ * further manage. When a detached thread is done, it simply goes away.
+ *
+ * There is no way to recover the return code of a detached thread. If you
+ * need this, don't detach the thread and instead use SDL_WaitThread().
+ *
+ * Once a thread is detached, you should usually assume the SDL_Thread isn't
+ * safe to reference again, as it will become invalid immediately upon the
+ * detached thread's exit, instead of remaining until someone has called
+ * SDL_WaitThread() to finally clean it up. As such, don't detach the same
+ * thread more than once.
+ *
+ * If a thread has already exited when passed to SDL_DetachThread(), it will
+ * stop waiting for a call to SDL_WaitThread() and clean up immediately. It is
+ * not safe to detach a thread that might be used with SDL_WaitThread().
+ *
+ * You may not call SDL_WaitThread() on a thread that has been detached. Use
+ * either that function or this one, but not both, or behavior is undefined.
+ *
+ * It is safe to pass NULL to this function; it is a no-op.
+ *
+ * \param thread the SDL_Thread pointer that was returned from the
+ * SDL_CreateThread() call that started this thread
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_CreateThread
+ * \sa SDL_WaitThread
+ */
+extern DECLSPEC void SDLCALL SDL_DetachThread(SDL_Thread * thread);
+
+/**
+ * Create a piece of thread-local storage.
+ *
+ * This creates an identifier that is globally visible to all threads but
+ * refers to data that is thread-specific.
+ *
+ * \returns the newly created thread local storage identifier or 0 on error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_TLSGet
+ * \sa SDL_TLSSet
+ */
+extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate(void);
+
+/**
+ * Get the current thread's value associated with a thread local storage ID.
+ *
+ * \param id the thread local storage ID
+ * \returns the value associated with the ID for the current thread or NULL if
+ * no value has been set; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_TLSCreate
+ * \sa SDL_TLSSet
+ */
+extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id);
+
+/**
+ * Set the current thread's value associated with a thread local storage ID.
+ *
+ * The function prototype for `destructor` is:
+ *
+ * ```c
+ * void destructor(void *value)
+ * ```
+ *
+ * where its parameter `value` is what was passed as `value` to SDL_TLSSet().
+ *
+ * \param id the thread local storage ID
+ * \param value the value to associate with the ID for the current thread
+ * \param destructor a function called when the thread exits, to free the
+ * value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_TLSCreate
+ * \sa SDL_TLSGet
+ */
+extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void*));
+
+/**
+ * Cleanup all TLS data for this thread.
+ */
+extern DECLSPEC void SDLCALL SDL_TLSCleanup(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_thread_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_timer.h b/Client/ThirdParty/SDL2/SDL_timer.h
new file mode 100644
index 0000000..04696dc
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_timer.h
@@ -0,0 +1,172 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_timer_h_
+#define SDL_timer_h_
+
+/**
+ * \file SDL_timer.h
+ *
+ * Header for the SDL time management routines.
+ */
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the number of milliseconds since SDL library initialization.
+ *
+ * This value wraps if the program runs for more than ~49 days.
+ *
+ * \returns an unsigned 32-bit value representing the number of milliseconds
+ * since the SDL library initialized.
+ *
+ * \sa SDL_TICKS_PASSED
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void);
+
+/**
+ * Compare SDL ticks values, and return true if `A` has passed `B`.
+ *
+ * For example, if you want to wait 100 ms, you could do this:
+ *
+ * ```c++
+ * Uint32 timeout = SDL_GetTicks() + 100;
+ * while (!SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
+ * // ... do work until timeout has elapsed
+ * }
+ * ```
+ */
+#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0)
+
+/**
+ * Get the current value of the high resolution counter.
+ *
+ * This function is typically used for profiling.
+ *
+ * The counter values are only meaningful relative to each other. Differences
+ * between values can be converted to times by using
+ * SDL_GetPerformanceFrequency().
+ *
+ * \returns the current counter value.
+ *
+ * \sa SDL_GetPerformanceFrequency
+ */
+extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void);
+
+/**
+ * Get the count per second of the high resolution counter.
+ *
+ * \returns a platform-specific count per second.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetPerformanceCounter
+ */
+extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void);
+
+/**
+ * Wait a specified number of milliseconds before returning.
+ *
+ * This function waits a specified number of milliseconds before returning. It
+ * waits at least the specified time, but possibly longer due to OS
+ * scheduling.
+ *
+ * \param ms the number of milliseconds to delay
+ */
+extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);
+
+/**
+ * Function prototype for the timer callback function.
+ *
+ * The callback function is passed the current timer interval and returns
+ * the next timer interval. If the returned value is the same as the one
+ * passed in, the periodic alarm continues, otherwise a new alarm is
+ * scheduled. If the callback returns 0, the periodic alarm is cancelled.
+ */
+typedef Uint32 (SDLCALL * SDL_TimerCallback) (Uint32 interval, void *param);
+
+/**
+ * Definition of the timer ID type.
+ */
+typedef int SDL_TimerID;
+
+/**
+ * Call a callback function at a future time.
+ *
+ * If you use this function, you must pass `SDL_INIT_TIMER` to SDL_Init().
+ *
+ * The callback function is passed the current timer interval and the user
+ * supplied parameter from the SDL_AddTimer() call and should return the next
+ * timer interval. If the value returned from the callback is 0, the timer is
+ * canceled.
+ *
+ * The callback is run on a separate thread.
+ *
+ * Timers take into account the amount of time it took to execute the
+ * callback. For example, if the callback took 250 ms to execute and returned
+ * 1000 (ms), the timer would only wait another 750 ms before its next
+ * iteration.
+ *
+ * Timing may be inexact due to OS scheduling. Be sure to note the current
+ * time with SDL_GetTicks() or SDL_GetPerformanceCounter() in case your
+ * callback needs to adjust for variances.
+ *
+ * \param interval the timer delay, in milliseconds, passed to `callback`
+ * \param callback the SDL_TimerCallback function to call when the specified
+ * `interval` elapses
+ * \param param a pointer that is passed to `callback`
+ * \returns a timer ID or 0 if an error occurs; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_RemoveTimer
+ */
+extern DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval,
+ SDL_TimerCallback callback,
+ void *param);
+
+/**
+ * Remove a timer created with SDL_AddTimer().
+ *
+ * \param id the ID of the timer to remove
+ * \returns SDL_TRUE if the timer is removed or SDL_FALSE if the timer wasn't
+ * found.
+ *
+ * \sa SDL_AddTimer
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RemoveTimer(SDL_TimerID id);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_timer_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_touch.h b/Client/ThirdParty/SDL2/SDL_touch.h
new file mode 100644
index 0000000..f370a67
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_touch.h
@@ -0,0 +1,138 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_touch.h
+ *
+ * Include file for SDL touch event handling.
+ */
+
+#ifndef SDL_touch_h_
+#define SDL_touch_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_TouchID;
+typedef Sint64 SDL_FingerID;
+
+typedef enum
+{
+ SDL_TOUCH_DEVICE_INVALID = -1,
+ SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */
+ SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */
+ SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */
+} SDL_TouchDeviceType;
+
+typedef struct SDL_Finger
+{
+ SDL_FingerID id;
+ float x;
+ float y;
+ float pressure;
+} SDL_Finger;
+
+/* Used as the device ID for mouse events simulated with touch input */
+#define SDL_TOUCH_MOUSEID ((Uint32)-1)
+
+/* Used as the SDL_TouchID for touch events simulated with mouse input */
+#define SDL_MOUSE_TOUCHID ((Sint64)-1)
+
+
+/**
+ * Get the number of registered touch devices.
+ *
+ * On some platforms SDL first sees the touch device if it was actually used.
+ * Therefore SDL_GetNumTouchDevices() may return 0 although devices are
+ * available. After using all devices at least once the number will be
+ * correct.
+ *
+ * This was fixed for Android in SDL 2.0.1.
+ *
+ * \returns the number of registered touch devices.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchDevice
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void);
+
+/**
+ * Get the touch ID with the given index.
+ *
+ * \param index the touch device index
+ * \returns the touch ID with the given index on success or 0 if the index is
+ * invalid; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumTouchDevices
+ */
+extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index);
+
+/**
+ * Get the type of the given touch device.
+ */
+extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID);
+
+/**
+ * Get the number of active fingers for a given touch device.
+ *
+ * \param touchID the ID of a touch device
+ * \returns the number of active fingers for a given touch device on success
+ * or 0 on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchFinger
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID);
+
+/**
+ * Get the finger object for specified touch device ID and finger index.
+ *
+ * The returned resource is owned by SDL and should not be deallocated.
+ *
+ * \param touchID the ID of the requested touch device
+ * \param index the index of the requested finger
+ * \returns a pointer to the SDL_Finger object or NULL if no object at the
+ * given ID and index could be found.
+ *
+ * \sa SDL_RecordGesture
+ */
+extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_touch_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_types.h b/Client/ThirdParty/SDL2/SDL_types.h
new file mode 100644
index 0000000..4267f36
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_types.h
@@ -0,0 +1,29 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_types.h
+ *
+ * \deprecated
+ */
+
+/* DEPRECATED */
+#include "SDL_stdinc.h"
diff --git a/Client/ThirdParty/SDL2/SDL_version.h b/Client/ThirdParty/SDL2/SDL_version.h
new file mode 100644
index 0000000..f4f8be2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_version.h
@@ -0,0 +1,172 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_version.h
+ *
+ * This header defines the current SDL version.
+ */
+
+#ifndef SDL_version_h_
+#define SDL_version_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Information about the version of SDL in use.
+ *
+ * Represents the library's version as three levels: major revision
+ * (increments with massive changes, additions, and enhancements),
+ * minor revision (increments with backwards-compatible changes to the
+ * major revision), and patchlevel (increments with fixes to the minor
+ * revision).
+ *
+ * \sa SDL_VERSION
+ * \sa SDL_GetVersion
+ */
+typedef struct SDL_version
+{
+ Uint8 major; /**< major version */
+ Uint8 minor; /**< minor version */
+ Uint8 patch; /**< update version */
+} SDL_version;
+
+/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
+*/
+#define SDL_MAJOR_VERSION 2
+#define SDL_MINOR_VERSION 0
+#define SDL_PATCHLEVEL 16
+
+/**
+ * Macro to determine SDL version program was compiled against.
+ *
+ * This macro fills in a SDL_version structure with the version of the
+ * library you compiled against. This is determined by what header the
+ * compiler uses. Note that if you dynamically linked the library, you might
+ * have a slightly newer or older version at runtime. That version can be
+ * determined with SDL_GetVersion(), which, unlike SDL_VERSION(),
+ * is not a macro.
+ *
+ * \param x A pointer to a SDL_version struct to initialize.
+ *
+ * \sa SDL_version
+ * \sa SDL_GetVersion
+ */
+#define SDL_VERSION(x) \
+{ \
+ (x)->major = SDL_MAJOR_VERSION; \
+ (x)->minor = SDL_MINOR_VERSION; \
+ (x)->patch = SDL_PATCHLEVEL; \
+}
+
+/**
+ * This macro turns the version numbers into a numeric value:
+ * \verbatim
+ (1,2,3) -> (1203)
+ \endverbatim
+ *
+ * This assumes that there will never be more than 100 patchlevels.
+ */
+#define SDL_VERSIONNUM(X, Y, Z) \
+ ((X)*1000 + (Y)*100 + (Z))
+
+/**
+ * This is the version number macro for the current SDL version.
+ */
+#define SDL_COMPILEDVERSION \
+ SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL)
+
+/**
+ * This macro will evaluate to true if compiled with SDL at least X.Y.Z.
+ */
+#define SDL_VERSION_ATLEAST(X, Y, Z) \
+ (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
+
+/**
+ * Get the version of SDL that is linked against your program.
+ *
+ * If you are linking to SDL dynamically, then it is possible that the current
+ * version will be different than the version you compiled against. This
+ * function returns the current version, while SDL_VERSION() is a macro that
+ * tells you what version you compiled with.
+ *
+ * This function may be called safely at any time, even before SDL_Init().
+ *
+ * \param ver the SDL_version structure that contains the version information
+ *
+ * \sa SDL_GetRevision
+ */
+extern DECLSPEC void SDLCALL SDL_GetVersion(SDL_version * ver);
+
+/**
+ * Get the code revision of SDL that is linked against your program.
+ *
+ * This value is the revision of the code you are linked with and may be
+ * different from the code you are compiling with, which is found in the
+ * constant SDL_REVISION.
+ *
+ * The revision is arbitrary string (a hash value) uniquely identifying the
+ * exact revision of the SDL library in use, and is only useful in comparing
+ * against other revisions. It is NOT an incrementing number.
+ *
+ * If SDL wasn't built from a git repository with the appropriate tools, this
+ * will return an empty string.
+ *
+ * Prior to SDL 2.0.16, before development moved to GitHub, this returned a
+ * hash for a Mercurial repository.
+ *
+ * You shouldn't use this function for anything but logging it for debugging
+ * purposes. The string is not intended to be reliable in any way.
+ *
+ * \returns an arbitrary string, uniquely identifying the exact revision of
+ * the SDL library in use.
+ *
+ * \sa SDL_GetVersion
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetRevision(void);
+
+/**
+ * Obsolete function, do not use.
+ *
+ * When SDL was hosted in a Mercurial repository, and was built carefully,
+ * this would return the revision number that the build was created from.
+ * This number was not reliable for several reasons, but more importantly,
+ * SDL is now hosted in a git repository, which does not offer numbers at
+ * all, only hashes. This function only ever returns zero now. Don't use it.
+ */
+extern SDL_DEPRECATED DECLSPEC int SDLCALL SDL_GetRevisionNumber(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_version_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_video.h b/Client/ThirdParty/SDL2/SDL_video.h
new file mode 100644
index 0000000..b6eb255
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_video.h
@@ -0,0 +1,1901 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_video.h
+ *
+ * Header file for SDL video functions.
+ */
+
+#ifndef SDL_video_h_
+#define SDL_video_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_surface.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The structure that defines a display mode
+ *
+ * \sa SDL_GetNumDisplayModes()
+ * \sa SDL_GetDisplayMode()
+ * \sa SDL_GetDesktopDisplayMode()
+ * \sa SDL_GetCurrentDisplayMode()
+ * \sa SDL_GetClosestDisplayMode()
+ * \sa SDL_SetWindowDisplayMode()
+ * \sa SDL_GetWindowDisplayMode()
+ */
+typedef struct
+{
+ Uint32 format; /**< pixel format */
+ int w; /**< width, in screen coordinates */
+ int h; /**< height, in screen coordinates */
+ int refresh_rate; /**< refresh rate (or zero for unspecified) */
+ void *driverdata; /**< driver-specific data, initialize to 0 */
+} SDL_DisplayMode;
+
+/**
+ * \brief The type used to identify a window
+ *
+ * \sa SDL_CreateWindow()
+ * \sa SDL_CreateWindowFrom()
+ * \sa SDL_DestroyWindow()
+ * \sa SDL_FlashWindow()
+ * \sa SDL_GetWindowData()
+ * \sa SDL_GetWindowFlags()
+ * \sa SDL_GetWindowGrab()
+ * \sa SDL_GetWindowKeyboardGrab()
+ * \sa SDL_GetWindowMouseGrab()
+ * \sa SDL_GetWindowPosition()
+ * \sa SDL_GetWindowSize()
+ * \sa SDL_GetWindowTitle()
+ * \sa SDL_HideWindow()
+ * \sa SDL_MaximizeWindow()
+ * \sa SDL_MinimizeWindow()
+ * \sa SDL_RaiseWindow()
+ * \sa SDL_RestoreWindow()
+ * \sa SDL_SetWindowData()
+ * \sa SDL_SetWindowFullscreen()
+ * \sa SDL_SetWindowGrab()
+ * \sa SDL_SetWindowKeyboardGrab()
+ * \sa SDL_SetWindowMouseGrab()
+ * \sa SDL_SetWindowIcon()
+ * \sa SDL_SetWindowPosition()
+ * \sa SDL_SetWindowSize()
+ * \sa SDL_SetWindowBordered()
+ * \sa SDL_SetWindowResizable()
+ * \sa SDL_SetWindowTitle()
+ * \sa SDL_ShowWindow()
+ */
+typedef struct SDL_Window SDL_Window;
+
+/**
+ * \brief The flags on a window
+ *
+ * \sa SDL_GetWindowFlags()
+ */
+typedef enum
+{
+ SDL_WINDOW_FULLSCREEN = 0x00000001, /**< fullscreen window */
+ SDL_WINDOW_OPENGL = 0x00000002, /**< window usable with OpenGL context */
+ SDL_WINDOW_SHOWN = 0x00000004, /**< window is visible */
+ SDL_WINDOW_HIDDEN = 0x00000008, /**< window is not visible */
+ SDL_WINDOW_BORDERLESS = 0x00000010, /**< no window decoration */
+ SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */
+ SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */
+ SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */
+ SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */
+ SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */
+ SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */
+ SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
+ SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */
+ SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported.
+ On macOS NSHighResolutionCapable must be set true in the
+ application's Info.plist for this to have any effect. */
+ SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */
+ SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */
+ SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */
+ SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */
+ SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */
+ SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */
+ SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */
+ SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
+ SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */
+
+ SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
+} SDL_WindowFlags;
+
+/**
+ * \brief Used to indicate that you don't care what the window position is.
+ */
+#define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000u
+#define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X))
+#define SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED_DISPLAY(0)
+#define SDL_WINDOWPOS_ISUNDEFINED(X) \
+ (((X)&0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK)
+
+/**
+ * \brief Used to indicate that the window position should be centered.
+ */
+#define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000u
+#define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X))
+#define SDL_WINDOWPOS_CENTERED SDL_WINDOWPOS_CENTERED_DISPLAY(0)
+#define SDL_WINDOWPOS_ISCENTERED(X) \
+ (((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK)
+
+/**
+ * \brief Event subtype for window events
+ */
+typedef enum
+{
+ SDL_WINDOWEVENT_NONE, /**< Never used */
+ SDL_WINDOWEVENT_SHOWN, /**< Window has been shown */
+ SDL_WINDOWEVENT_HIDDEN, /**< Window has been hidden */
+ SDL_WINDOWEVENT_EXPOSED, /**< Window has been exposed and should be
+ redrawn */
+ SDL_WINDOWEVENT_MOVED, /**< Window has been moved to data1, data2
+ */
+ SDL_WINDOWEVENT_RESIZED, /**< Window has been resized to data1xdata2 */
+ SDL_WINDOWEVENT_SIZE_CHANGED, /**< The window size has changed, either as
+ a result of an API call or through the
+ system or user changing the window size. */
+ SDL_WINDOWEVENT_MINIMIZED, /**< Window has been minimized */
+ SDL_WINDOWEVENT_MAXIMIZED, /**< Window has been maximized */
+ SDL_WINDOWEVENT_RESTORED, /**< Window has been restored to normal size
+ and position */
+ SDL_WINDOWEVENT_ENTER, /**< Window has gained mouse focus */
+ SDL_WINDOWEVENT_LEAVE, /**< Window has lost mouse focus */
+ SDL_WINDOWEVENT_FOCUS_GAINED, /**< Window has gained keyboard focus */
+ SDL_WINDOWEVENT_FOCUS_LOST, /**< Window has lost keyboard focus */
+ SDL_WINDOWEVENT_CLOSE, /**< The window manager requests that the window be closed */
+ SDL_WINDOWEVENT_TAKE_FOCUS, /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */
+ SDL_WINDOWEVENT_HIT_TEST /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */
+} SDL_WindowEventID;
+
+/**
+ * \brief Event subtype for display events
+ */
+typedef enum
+{
+ SDL_DISPLAYEVENT_NONE, /**< Never used */
+ SDL_DISPLAYEVENT_ORIENTATION, /**< Display orientation has changed to data1 */
+ SDL_DISPLAYEVENT_CONNECTED, /**< Display has been added to the system */
+ SDL_DISPLAYEVENT_DISCONNECTED /**< Display has been removed from the system */
+} SDL_DisplayEventID;
+
+/**
+ * \brief Display orientation
+ */
+typedef enum
+{
+ SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */
+ SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */
+ SDL_ORIENTATION_LANDSCAPE_FLIPPED, /**< The display is in landscape mode, with the left side up, relative to portrait mode */
+ SDL_ORIENTATION_PORTRAIT, /**< The display is in portrait mode */
+ SDL_ORIENTATION_PORTRAIT_FLIPPED /**< The display is in portrait mode, upside down */
+} SDL_DisplayOrientation;
+
+/**
+ * \brief Window flash operation
+ */
+typedef enum
+{
+ SDL_FLASH_CANCEL, /**< Cancel any window flash state */
+ SDL_FLASH_BRIEFLY, /**< Flash the window briefly to get attention */
+ SDL_FLASH_UNTIL_FOCUSED, /**< Flash the window until it gets focus */
+} SDL_FlashOperation;
+
+/**
+ * \brief An opaque handle to an OpenGL context.
+ */
+typedef void *SDL_GLContext;
+
+/**
+ * \brief OpenGL configuration attributes
+ */
+typedef enum
+{
+ SDL_GL_RED_SIZE,
+ SDL_GL_GREEN_SIZE,
+ SDL_GL_BLUE_SIZE,
+ SDL_GL_ALPHA_SIZE,
+ SDL_GL_BUFFER_SIZE,
+ SDL_GL_DOUBLEBUFFER,
+ SDL_GL_DEPTH_SIZE,
+ SDL_GL_STENCIL_SIZE,
+ SDL_GL_ACCUM_RED_SIZE,
+ SDL_GL_ACCUM_GREEN_SIZE,
+ SDL_GL_ACCUM_BLUE_SIZE,
+ SDL_GL_ACCUM_ALPHA_SIZE,
+ SDL_GL_STEREO,
+ SDL_GL_MULTISAMPLEBUFFERS,
+ SDL_GL_MULTISAMPLESAMPLES,
+ SDL_GL_ACCELERATED_VISUAL,
+ SDL_GL_RETAINED_BACKING,
+ SDL_GL_CONTEXT_MAJOR_VERSION,
+ SDL_GL_CONTEXT_MINOR_VERSION,
+ SDL_GL_CONTEXT_EGL,
+ SDL_GL_CONTEXT_FLAGS,
+ SDL_GL_CONTEXT_PROFILE_MASK,
+ SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
+ SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
+ SDL_GL_CONTEXT_RELEASE_BEHAVIOR,
+ SDL_GL_CONTEXT_RESET_NOTIFICATION,
+ SDL_GL_CONTEXT_NO_ERROR
+} SDL_GLattr;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_PROFILE_CORE = 0x0001,
+ SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002,
+ SDL_GL_CONTEXT_PROFILE_ES = 0x0004 /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
+} SDL_GLprofile;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001,
+ SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
+ SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG = 0x0004,
+ SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008
+} SDL_GLcontextFlag;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000,
+ SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001
+} SDL_GLcontextReleaseFlag;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000,
+ SDL_GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001
+} SDL_GLContextResetNotification;
+
+/* Function prototypes */
+
+/**
+ * Get the number of video drivers compiled into SDL.
+ *
+ * \returns a number >= 1 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetVideoDriver
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void);
+
+/**
+ * Get the name of a built in video driver.
+ *
+ * The video drivers are presented in the order in which they are normally
+ * checked during initialization.
+ *
+ * \param index the index of a video driver
+ * \returns the name of the video driver with the given **index**.
+ *
+ * \sa SDL_GetNumVideoDrivers
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetVideoDriver(int index);
+
+/**
+ * Initialize the video subsystem, optionally specifying a video driver.
+ *
+ * This function initializes the video subsystem, setting up a connection to
+ * the window manager, etc, and determines the available display modes and
+ * pixel formats, but does not initialize a window or graphics mode.
+ *
+ * If you use this function and you haven't used the SDL_INIT_VIDEO flag with
+ * either SDL_Init() or SDL_InitSubSystem(), you should call SDL_VideoQuit()
+ * before calling SDL_Quit().
+ *
+ * It is safe to call this function multiple times. SDL_VideoInit() will call
+ * SDL_VideoQuit() itself if the video subsystem has already been initialized.
+ *
+ * You can use SDL_GetNumVideoDrivers() and SDL_GetVideoDriver() to find a
+ * specific `driver_name`.
+ *
+ * \param driver_name the name of a video driver to initialize, or NULL for
+ * the default driver
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetNumVideoDrivers
+ * \sa SDL_GetVideoDriver
+ * \sa SDL_InitSubSystem
+ * \sa SDL_VideoQuit
+ */
+extern DECLSPEC int SDLCALL SDL_VideoInit(const char *driver_name);
+
+/**
+ * Shut down the video subsystem, if initialized with SDL_VideoInit().
+ *
+ * This function closes all windows, and restores the original video mode.
+ *
+ * \sa SDL_VideoInit
+ */
+extern DECLSPEC void SDLCALL SDL_VideoQuit(void);
+
+/**
+ * Get the name of the currently initialized video driver.
+ *
+ * \returns the name of the current video driver or NULL if no driver has been
+ * initialized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumVideoDrivers
+ * \sa SDL_GetVideoDriver
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetCurrentVideoDriver(void);
+
+/**
+ * Get the number of available video displays.
+ *
+ * \returns a number >= 1 or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetDisplayBounds
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumVideoDisplays(void);
+
+/**
+ * Get the name of a display in UTF-8 encoding.
+ *
+ * \param displayIndex the index of display from which the name should be
+ * queried
+ * \returns the name of a display or NULL for an invalid display index or
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetDisplayName(int displayIndex);
+
+/**
+ * Get the desktop area represented by a display.
+ *
+ * The primary display (`displayIndex` zero) is always located at 0,0.
+ *
+ * \param displayIndex the index of the display to query
+ * \param rect the SDL_Rect structure filled in with the display bounds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect);
+
+/**
+ * Get the usable desktop area represented by a display.
+ *
+ * The primary display (`displayIndex` zero) is always located at 0,0.
+ *
+ * This is the same area as SDL_GetDisplayBounds() reports, but with portions
+ * reserved by the system removed. For example, on Apple's macOS, this
+ * subtracts the area occupied by the menu bar and dock.
+ *
+ * Setting a window to be fullscreen generally bypasses these unusable areas,
+ * so these are good guidelines for the maximum space available to a
+ * non-fullscreen window.
+ *
+ * The parameter `rect` is ignored if it is NULL.
+ *
+ * This function also returns -1 if the parameter `displayIndex` is out of
+ * range.
+ *
+ * \param displayIndex the index of the display to query the usable bounds
+ * from
+ * \param rect the SDL_Rect structure filled in with the display bounds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetDisplayBounds
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect);
+
+/**
+ * Get the dots/pixels-per-inch for a display.
+ *
+ * Diagonal, horizontal and vertical DPI can all be optionally returned if the
+ * appropriate parameter is non-NULL.
+ *
+ * A failure of this function usually means that either no DPI information is
+ * available or the `displayIndex` is out of range.
+ *
+ * \param displayIndex the index of the display from which DPI information
+ * should be queried
+ * \param ddpi a pointer filled in with the diagonal DPI of the display; may
+ * be NULL
+ * \param hdpi a pointer filled in with the horizontal DPI of the display; may
+ * be NULL
+ * \param vdpi a pointer filled in with the vertical DPI of the display; may
+ * be NULL
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
+
+/**
+ * Get the orientation of a display.
+ *
+ * \param displayIndex the index of the display to query
+ * \returns The SDL_DisplayOrientation enum value of the display, or
+ * `SDL_ORIENTATION_UNKNOWN` if it isn't available.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetDisplayOrientation(int displayIndex);
+
+/**
+ * Get the number of available display modes.
+ *
+ * The `displayIndex` needs to be in the range from 0 to
+ * SDL_GetNumVideoDisplays() - 1.
+ *
+ * \param displayIndex the index of the display to query
+ * \returns a number >= 1 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumDisplayModes(int displayIndex);
+
+/**
+ * Get information about a specific display mode.
+ *
+ * The display modes are sorted in this priority:
+ *
+ * - width -> largest to smallest
+ * - height -> largest to smallest
+ * - bits per pixel -> more colors to fewer colors
+ * - packed pixel layout -> largest to smallest
+ * - refresh rate -> highest to lowest
+ *
+ * \param displayIndex the index of the display to query
+ * \param modeIndex the index of the display mode to query
+ * \param mode an SDL_DisplayMode structure filled in with the mode at
+ * `modeIndex`
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetNumDisplayModes
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayMode(int displayIndex, int modeIndex,
+ SDL_DisplayMode * mode);
+
+/**
+ * Get information about the desktop's display mode.
+ *
+ * There's a difference between this function and SDL_GetCurrentDisplayMode()
+ * when SDL runs fullscreen and has changed the resolution. In that case this
+ * function will return the previous native display mode, and not the current
+ * display mode.
+ *
+ * \param displayIndex the index of the display to query
+ * \param mode an SDL_DisplayMode structure filled in with the current display
+ * mode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetCurrentDisplayMode
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode);
+
+/**
+ * Get information about the current display mode.
+ *
+ * There's a difference between this function and SDL_GetDesktopDisplayMode()
+ * when SDL runs fullscreen and has changed the resolution. In that case this
+ * function will return the current display mode, and not the previous native
+ * display mode.
+ *
+ * \param displayIndex the index of the display to query
+ * \param mode an SDL_DisplayMode structure filled in with the current display
+ * mode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetDesktopDisplayMode
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_GetNumVideoDisplays
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode);
+
+
+/**
+ * Get the closest match to the requested display mode.
+ *
+ * The available display modes are scanned and `closest` is filled in with the
+ * closest mode matching the requested mode and returned. The mode format and
+ * refresh rate default to the desktop mode if they are set to 0. The modes
+ * are scanned with size being first priority, format being second priority,
+ * and finally checking the refresh rate. If all the available modes are too
+ * small, then NULL is returned.
+ *
+ * \param displayIndex the index of the display to query
+ * \param mode an SDL_DisplayMode structure containing the desired display
+ * mode
+ * \param closest an SDL_DisplayMode structure filled in with the closest
+ * match of the available display modes
+ * \returns the passed in value `closest` or NULL if no matching video mode
+ * was available; call SDL_GetError() for more information.
+ *
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_GetNumDisplayModes
+ */
+extern DECLSPEC SDL_DisplayMode * SDLCALL SDL_GetClosestDisplayMode(int displayIndex, const SDL_DisplayMode * mode, SDL_DisplayMode * closest);
+
+/**
+ * Get the index of the display associated with a window.
+ *
+ * \param window the window to query
+ * \returns the index of the display containing the center of the window on
+ * success or a negative error code on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \sa SDL_GetDisplayBounds
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowDisplayIndex(SDL_Window * window);
+
+/**
+ * Set the display mode to use when a window is visible at fullscreen.
+ *
+ * This only affects the display mode used when the window is fullscreen. To
+ * change the window size when the window is not fullscreen, use
+ * SDL_SetWindowSize().
+ *
+ * \param window the window to affect
+ * \param mode the SDL_DisplayMode structure representing the mode to use, or
+ * NULL to use the window's dimensions and the desktop's format
+ * and refresh rate
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowDisplayMode
+ * \sa SDL_SetWindowFullscreen
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowDisplayMode(SDL_Window * window,
+ const SDL_DisplayMode * mode);
+
+/**
+ * Query the display mode to use when a window is visible at fullscreen.
+ *
+ * \param window the window to query
+ * \param mode an SDL_DisplayMode structure filled in with the fullscreen
+ * display mode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetWindowDisplayMode
+ * \sa SDL_SetWindowFullscreen
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowDisplayMode(SDL_Window * window,
+ SDL_DisplayMode * mode);
+
+/**
+ * Get the pixel format associated with the window.
+ *
+ * \param window the window to query
+ * \returns the pixel format of the window on success or
+ * SDL_PIXELFORMAT_UNKNOWN on failure; call SDL_GetError() for more
+ * information.
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
+
+/**
+ * Create a window with the specified position, dimensions, and flags.
+ *
+ * `flags` may be any of the following OR'd together:
+ *
+ * - `SDL_WINDOW_FULLSCREEN`: fullscreen window
+ * - `SDL_WINDOW_FULLSCREEN_DESKTOP`: fullscreen window at desktop resolution
+ * - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context
+ * - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance
+ * - `SDL_WINDOW_METAL`: window usable with a Metal instance
+ * - `SDL_WINDOW_HIDDEN`: window is not visible
+ * - `SDL_WINDOW_BORDERLESS`: no window decoration
+ * - `SDL_WINDOW_RESIZABLE`: window can be resized
+ * - `SDL_WINDOW_MINIMIZED`: window is minimized
+ * - `SDL_WINDOW_MAXIMIZED`: window is maximized
+ * - `SDL_WINDOW_INPUT_GRABBED`: window has grabbed input focus
+ * - `SDL_WINDOW_ALLOW_HIGHDPI`: window should be created in high-DPI mode if
+ * supported (>= SDL 2.0.1)
+ *
+ * `SDL_WINDOW_SHOWN` is ignored by SDL_CreateWindow(). The SDL_Window is
+ * implicitly shown if SDL_WINDOW_HIDDEN is not set. `SDL_WINDOW_SHOWN` may be
+ * queried later using SDL_GetWindowFlags().
+ *
+ * On Apple's macOS, you **must** set the NSHighResolutionCapable Info.plist
+ * property to YES, otherwise you will not receive a High-DPI OpenGL canvas.
+ *
+ * If the window is created with the `SDL_WINDOW_ALLOW_HIGHDPI` flag, its size
+ * in pixels may differ from its size in screen coordinates on platforms with
+ * high-DPI support (e.g. iOS and macOS). Use SDL_GetWindowSize() to query the
+ * client area's size in screen coordinates, and SDL_GL_GetDrawableSize() or
+ * SDL_GetRendererOutputSize() to query the drawable size in pixels.
+ *
+ * If the window is set fullscreen, the width and height parameters `w` and
+ * `h` will not be used. However, invalid size parameters (e.g. too large) may
+ * still fail. Window size is actually limited to 16384 x 16384 for all
+ * platforms at window creation.
+ *
+ * If the window is created with any of the SDL_WINDOW_OPENGL or
+ * SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function
+ * (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the
+ * corresponding UnloadLibrary function is called by SDL_DestroyWindow().
+ *
+ * If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver,
+ * SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail.
+ *
+ * If SDL_WINDOW_METAL is specified on an OS that does not support Metal,
+ * SDL_CreateWindow() will fail.
+ *
+ * On non-Apple devices, SDL requires you to either not link to the Vulkan
+ * loader or link to a dynamic library version. This limitation may be removed
+ * in a future version of SDL.
+ *
+ * \param title the title of the window, in UTF-8 encoding
+ * \param x the x position of the window, `SDL_WINDOWPOS_CENTERED`, or
+ * `SDL_WINDOWPOS_UNDEFINED`
+ * \param y the y position of the window, `SDL_WINDOWPOS_CENTERED`, or
+ * `SDL_WINDOWPOS_UNDEFINED`
+ * \param w the width of the window, in screen coordinates
+ * \param h the height of the window, in screen coordinates
+ * \param flags 0, or one or more SDL_WindowFlags OR'd together
+ * \returns the window that was created or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateWindowFrom
+ * \sa SDL_DestroyWindow
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title,
+ int x, int y, int w,
+ int h, Uint32 flags);
+
+/**
+ * Create an SDL window from an existing native window.
+ *
+ * In some cases (e.g. OpenGL) and on some platforms (e.g. Microsoft Windows)
+ * the hint `SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT` needs to be configured
+ * before using SDL_CreateWindowFrom().
+ *
+ * \param data a pointer to driver-dependent window creation data, typically
+ * your native window cast to a void*
+ * \returns the window that was created or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_DestroyWindow
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowFrom(const void *data);
+
+/**
+ * Get the numeric ID of a window.
+ *
+ * The numeric ID is what SDL_WindowEvent references, and is necessary to map
+ * these events to specific SDL_Window objects.
+ *
+ * \param window the window to query
+ * \returns the ID of the window on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetWindowFromID
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetWindowID(SDL_Window * window);
+
+/**
+ * Get a window from a stored ID.
+ *
+ * The numeric ID is what SDL_WindowEvent references, and is necessary to map
+ * these events to specific SDL_Window objects.
+ *
+ * \param id the ID of the window
+ * \returns the window associated with `id` or NULL if it doesn't exist; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowID
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromID(Uint32 id);
+
+/**
+ * Get the window flags.
+ *
+ * \param window the window to query
+ * \returns a mask of the SDL_WindowFlags associated with `window`
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_HideWindow
+ * \sa SDL_MaximizeWindow
+ * \sa SDL_MinimizeWindow
+ * \sa SDL_SetWindowFullscreen
+ * \sa SDL_SetWindowGrab
+ * \sa SDL_ShowWindow
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window * window);
+
+/**
+ * Set the title of a window.
+ *
+ * This string is expected to be in UTF-8 encoding.
+ *
+ * \param window the window to change
+ * \param title the desired window title in UTF-8 format
+ *
+ * \sa SDL_GetWindowTitle
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowTitle(SDL_Window * window,
+ const char *title);
+
+/**
+ * Get the title of a window.
+ *
+ * \param window the window to query
+ * \returns the title of the window in UTF-8 format or "" if there is no
+ * title.
+ *
+ * \sa SDL_SetWindowTitle
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window * window);
+
+/**
+ * Set the icon for a window.
+ *
+ * \param window the window to change
+ * \param icon an SDL_Surface structure containing the icon for the window
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowIcon(SDL_Window * window,
+ SDL_Surface * icon);
+
+/**
+ * Associate an arbitrary named pointer with a window.
+ *
+ * `name` is case-sensitive.
+ *
+ * \param window the window to associate with the pointer
+ * \param name the name of the pointer
+ * \param userdata the associated pointer
+ * \returns the previous value associated with `name`.
+ *
+ * \sa SDL_GetWindowData
+ */
+extern DECLSPEC void* SDLCALL SDL_SetWindowData(SDL_Window * window,
+ const char *name,
+ void *userdata);
+
+/**
+ * Retrieve the data pointer associated with a window.
+ *
+ * \param window the window to query
+ * \param name the name of the pointer
+ * \returns the value associated with `name`.
+ *
+ * \sa SDL_SetWindowData
+ */
+extern DECLSPEC void *SDLCALL SDL_GetWindowData(SDL_Window * window,
+ const char *name);
+
+/**
+ * Set the position of a window.
+ *
+ * The window coordinate origin is the upper left of the display.
+ *
+ * \param window the window to reposition
+ * \param x the x coordinate of the window in screen coordinates, or
+ * `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED`
+ * \param y the y coordinate of the window in screen coordinates, or
+ * `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED`
+ *
+ * \sa SDL_GetWindowPosition
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowPosition(SDL_Window * window,
+ int x, int y);
+
+/**
+ * Get the position of a window.
+ *
+ * If you do not need the value for one of the positions a NULL may be passed
+ * in the `x` or `y` parameter.
+ *
+ * \param window the window to query
+ * \param x a pointer filled in with the x position of the window, in screen
+ * coordinates, may be NULL
+ * \param y a pointer filled in with the y position of the window, in screen
+ * coordinates, may be NULL
+ *
+ * \sa SDL_SetWindowPosition
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowPosition(SDL_Window * window,
+ int *x, int *y);
+
+/**
+ * Set the size of a window's client area.
+ *
+ * The window size in screen coordinates may differ from the size in pixels,
+ * if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform
+ * with high-dpi support (e.g. iOS or macOS). Use SDL_GL_GetDrawableSize() or
+ * SDL_GetRendererOutputSize() to get the real client area size in pixels.
+ *
+ * Fullscreen windows automatically match the size of the display mode, and
+ * you should use SDL_SetWindowDisplayMode() to change their size.
+ *
+ * \param window the window to change
+ * \param w the width of the window in pixels, in screen coordinates, must be
+ * > 0
+ * \param h the height of the window in pixels, in screen coordinates, must be
+ * > 0
+ *
+ * \sa SDL_GetWindowSize
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window * window, int w,
+ int h);
+
+/**
+ * Get the size of a window's client area.
+ *
+ * NULL can safely be passed as the `w` or `h` parameter if the width or
+ * height value is not desired.
+ *
+ * The window size in screen coordinates may differ from the size in pixels,
+ * if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform
+ * with high-dpi support (e.g. iOS or macOS). Use SDL_GL_GetDrawableSize(),
+ * SDL_Vulkan_GetDrawableSize(), or SDL_GetRendererOutputSize() to get the
+ * real client area size in pixels.
+ *
+ * \param window the window to query the width and height from
+ * \param w a pointer filled in with the width of the window, in screen
+ * coordinates, may be NULL
+ * \param h a pointer filled in with the height of the window, in screen
+ * coordinates, may be NULL
+ *
+ * \sa SDL_GL_GetDrawableSize
+ * \sa SDL_Vulkan_GetDrawableSize
+ * \sa SDL_SetWindowSize
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window * window, int *w,
+ int *h);
+
+/**
+ * Get the size of a window's borders (decorations) around the client area.
+ *
+ * Note: If this function fails (returns -1), the size values will be
+ * initialized to 0, 0, 0, 0 (if a non-NULL pointer is provided), as if the
+ * window in question was borderless.
+ *
+ * Note: This function may fail on systems where the window has not yet been
+ * decorated by the display server (for example, immediately after calling
+ * SDL_CreateWindow). It is recommended that you wait at least until the
+ * window has been presented and composited, so that the window system has a
+ * chance to decorate the window and provide the border dimensions to SDL.
+ *
+ * This function also returns -1 if getting the information is not supported.
+ *
+ * \param window the window to query the size values of the border
+ * (decorations) from
+ * \param top pointer to variable for storing the size of the top border; NULL
+ * is permitted
+ * \param left pointer to variable for storing the size of the left border;
+ * NULL is permitted
+ * \param bottom pointer to variable for storing the size of the bottom
+ * border; NULL is permitted
+ * \param right pointer to variable for storing the size of the right border;
+ * NULL is permitted
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetWindowSize
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowBordersSize(SDL_Window * window,
+ int *top, int *left,
+ int *bottom, int *right);
+
+/**
+ * Set the minimum size of a window's client area.
+ *
+ * \param window the window to change
+ * \param min_w the minimum width of the window in pixels
+ * \param min_h the minimum height of the window in pixels
+ *
+ * \sa SDL_GetWindowMinimumSize
+ * \sa SDL_SetWindowMaximumSize
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowMinimumSize(SDL_Window * window,
+ int min_w, int min_h);
+
+/**
+ * Get the minimum size of a window's client area.
+ *
+ * \param window the window to query
+ * \param w a pointer filled in with the minimum width of the window, may be
+ * NULL
+ * \param h a pointer filled in with the minimum height of the window, may be
+ * NULL
+ *
+ * \sa SDL_GetWindowMaximumSize
+ * \sa SDL_SetWindowMinimumSize
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowMinimumSize(SDL_Window * window,
+ int *w, int *h);
+
+/**
+ * Set the maximum size of a window's client area.
+ *
+ * \param window the window to change
+ * \param max_w the maximum width of the window in pixels
+ * \param max_h the maximum height of the window in pixels
+ *
+ * \sa SDL_GetWindowMaximumSize
+ * \sa SDL_SetWindowMinimumSize
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowMaximumSize(SDL_Window * window,
+ int max_w, int max_h);
+
+/**
+ * Get the maximum size of a window's client area.
+ *
+ * \param window the window to query
+ * \param w a pointer filled in with the maximum width of the window, may be
+ * NULL
+ * \param h a pointer filled in with the maximum height of the window, may be
+ * NULL
+ *
+ * \sa SDL_GetWindowMinimumSize
+ * \sa SDL_SetWindowMaximumSize
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowMaximumSize(SDL_Window * window,
+ int *w, int *h);
+
+/**
+ * Set the border state of a window.
+ *
+ * This will add or remove the window's `SDL_WINDOW_BORDERLESS` flag and add
+ * or remove the border from the actual window. This is a no-op if the
+ * window's border already matches the requested state.
+ *
+ * You can't change the border state of a fullscreen window.
+ *
+ * \param window the window of which to change the border state
+ * \param bordered SDL_FALSE to remove border, SDL_TRUE to add border
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetWindowFlags
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowBordered(SDL_Window * window,
+ SDL_bool bordered);
+
+/**
+ * Set the user-resizable state of a window.
+ *
+ * This will add or remove the window's `SDL_WINDOW_RESIZABLE` flag and
+ * allow/disallow user resizing of the window. This is a no-op if the window's
+ * resizable state already matches the requested state.
+ *
+ * You can't change the resizable state of a fullscreen window.
+ *
+ * \param window the window of which to change the resizable state
+ * \param resizable SDL_TRUE to allow resizing, SDL_FALSE to disallow
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetWindowFlags
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowResizable(SDL_Window * window,
+ SDL_bool resizable);
+
+/**
+ * \brief Set the window to always be above the others.
+ *
+ * This will add or remove the window's `SDL_WINDOW_ALWAYS_ON_TOP`
+ * flag. This will bring the window to the front and keep the window above
+ * the rest.
+ *
+ * \param window The window of which to change the always on top state.
+ * \param on_top SDL_TRUE to set the window always on top, SDL_FALSE to disable.
+ *
+ * \sa SDL_SetWindowAlwaysOnTop
+ */
+
+extern DECLSPEC void SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window * window,
+ SDL_bool on_top);
+/**
+ * Show a window.
+ *
+ * \param window the window to show
+ *
+ * \sa SDL_HideWindow
+ * \sa SDL_RaiseWindow
+ */
+extern DECLSPEC void SDLCALL SDL_ShowWindow(SDL_Window * window);
+
+/**
+ * Hide a window.
+ *
+ * \param window the window to hide
+ *
+ * \sa SDL_ShowWindow
+ */
+extern DECLSPEC void SDLCALL SDL_HideWindow(SDL_Window * window);
+
+/**
+ * Raise a window above other windows and set the input focus.
+ *
+ * \param window the window to raise
+ */
+extern DECLSPEC void SDLCALL SDL_RaiseWindow(SDL_Window * window);
+
+/**
+ * Make a window as large as possible.
+ *
+ * \param window the window to maximize
+ *
+ * \sa SDL_MinimizeWindow
+ * \sa SDL_RestoreWindow
+ */
+extern DECLSPEC void SDLCALL SDL_MaximizeWindow(SDL_Window * window);
+
+/**
+ * Minimize a window to an iconic representation.
+ *
+ * \param window the window to minimize
+ *
+ * \sa SDL_MaximizeWindow
+ * \sa SDL_RestoreWindow
+ */
+extern DECLSPEC void SDLCALL SDL_MinimizeWindow(SDL_Window * window);
+
+/**
+ * Restore the size and position of a minimized or maximized window.
+ *
+ * \param window the window to restore
+ *
+ * \sa SDL_MaximizeWindow
+ * \sa SDL_MinimizeWindow
+ */
+extern DECLSPEC void SDLCALL SDL_RestoreWindow(SDL_Window * window);
+
+/**
+ * Set a window's fullscreen state.
+ *
+ * `flags` may be `SDL_WINDOW_FULLSCREEN`, for "real" fullscreen with a
+ * videomode change; `SDL_WINDOW_FULLSCREEN_DESKTOP` for "fake" fullscreen
+ * that takes the size of the desktop; and 0 for windowed mode.
+ *
+ * \param window the window to change
+ * \param flags `SDL_WINDOW_FULLSCREEN`, `SDL_WINDOW_FULLSCREEN_DESKTOP` or 0
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetWindowDisplayMode
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window,
+ Uint32 flags);
+
+/**
+ * Get the SDL surface associated with the window.
+ *
+ * A new surface will be created with the optimal format for the window, if
+ * necessary. This surface will be freed when the window is destroyed. Do not
+ * free this surface.
+ *
+ * This surface will be invalidated if the window is resized. After resizing a
+ * window this function must be called again to return a valid surface.
+ *
+ * You may not combine this with 3D or the rendering API on this window.
+ *
+ * This function is affected by `SDL_HINT_FRAMEBUFFER_ACCELERATION`.
+ *
+ * \param window the window to query
+ * \returns the surface associated with the window, or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_UpdateWindowSurface
+ * \sa SDL_UpdateWindowSurfaceRects
+ */
+extern DECLSPEC SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window * window);
+
+/**
+ * Copy the window surface to the screen.
+ *
+ * This is the function you use to reflect any changes to the surface on the
+ * screen.
+ *
+ * This function is equivalent to the SDL 1.2 API SDL_Flip().
+ *
+ * \param window the window to update
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowSurface
+ * \sa SDL_UpdateWindowSurfaceRects
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window);
+
+/**
+ * Copy areas of the window surface to the screen.
+ *
+ * This is the function you use to reflect changes to portions of the surface
+ * on the screen.
+ *
+ * This function is equivalent to the SDL 1.2 API SDL_UpdateRects().
+ *
+ * \param window the window to update
+ * \param rects an array of SDL_Rect structures representing areas of the
+ * surface to copy
+ * \param numrects the number of rectangles
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowSurface
+ * \sa SDL_UpdateWindowSurface
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
+ const SDL_Rect * rects,
+ int numrects);
+
+/**
+ * Set a window's input grab mode.
+ *
+ * When input is grabbed the mouse is confined to the window.
+ *
+ * If the caller enables a grab while another window is currently grabbed, the
+ * other window loses its grab in favor of the caller's window.
+ *
+ * \param window the window for which the input grab mode should be set
+ * \param grabbed SDL_TRUE to grab input or SDL_FALSE to release input
+ *
+ * \sa SDL_GetGrabbedWindow
+ * \sa SDL_GetWindowGrab
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+/**
+ * Set a window's keyboard grab mode.
+ *
+ * If the caller enables a grab while another window is currently grabbed, the
+ * other window loses its grab in favor of the caller's window.
+ *
+ * \param window The window for which the keyboard grab mode should be set.
+ * \param grabbed This is SDL_TRUE to grab keyboard, and SDL_FALSE to release.
+ *
+ * \sa SDL_GetWindowKeyboardGrab
+ * \sa SDL_SetWindowMouseGrab
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+/**
+ * Set a window's mouse grab mode.
+ *
+ * \param window The window for which the mouse grab mode should be set.
+ *
+ * \sa SDL_GetWindowMouseGrab
+ * \sa SDL_SetWindowKeyboardGrab
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowMouseGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+/**
+ * Get a window's input grab mode.
+ *
+ * \param window the window to query
+ * \returns SDL_TRUE if input is grabbed, SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
+
+/**
+ * Get a window's keyboard grab mode.
+ *
+ * \param window the window to query
+ * \returns SDL_TRUE if keyboard is grabbed, and SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetWindowKeyboardGrab
+ * \sa SDL_GetWindowGrab
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window * window);
+
+/**
+ * Get a window's mouse grab mode.
+ *
+ * \param window the window to query
+ * \returns SDL_TRUE if mouse is grabbed, and SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetWindowKeyboardGrab
+ * \sa SDL_GetWindowGrab
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window * window);
+
+/**
+ * Get the window that currently has an input grab enabled.
+ *
+ * \returns the window if input is grabbed or NULL otherwise.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetWindowGrab
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void);
+
+/**
+ * Set the brightness (gamma multiplier) for a given window's display.
+ *
+ * Despite the name and signature, this method sets the brightness of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().) The
+ * brightness set will not follow the window if it is moved to another
+ * display.
+ *
+ * Many platforms will refuse to set the display brightness in modern times.
+ * You are better off using a shader to adjust gamma during rendering, or
+ * something similar.
+ *
+ * \param window the window used to select the display whose brightness will
+ * be changed
+ * \param brightness the brightness (gamma multiplier) value to set where 0.0
+ * is completely dark and 1.0 is normal brightness
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowBrightness
+ * \sa SDL_SetWindowGammaRamp
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowBrightness(SDL_Window * window, float brightness);
+
+/**
+ * Get the brightness (gamma multiplier) for a given window's display.
+ *
+ * Despite the name and signature, this method retrieves the brightness of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().)
+ *
+ * \param window the window used to select the display whose brightness will
+ * be queried
+ * \returns the brightness for the display where 0.0 is completely dark and
+ * 1.0 is normal brightness.
+ *
+ * \sa SDL_SetWindowBrightness
+ */
+extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
+
+/**
+ * Set the opacity for a window.
+ *
+ * The parameter `opacity` will be clamped internally between 0.0f
+ * (transparent) and 1.0f (opaque).
+ *
+ * This function also returns -1 if setting the opacity isn't supported.
+ *
+ * \param window the window which will be made transparent or opaque
+ * \param opacity the opacity value (0.0f - transparent, 1.0f - opaque)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetWindowOpacity
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window * window, float opacity);
+
+/**
+ * Get the opacity of a window.
+ *
+ * If transparency isn't supported on this platform, opacity will be reported
+ * as 1.0f without error.
+ *
+ * The parameter `opacity` is ignored if it is NULL.
+ *
+ * This function also returns -1 if an invalid window was provided.
+ *
+ * \param window the window to get the current opacity value from
+ * \param out_opacity the float filled in (0.0f - transparent, 1.0f - opaque)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_SetWindowOpacity
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity);
+
+/**
+ * Set the window as a modal for another window.
+ *
+ * \param modal_window the window that should be set modal
+ * \param parent_window the parent window for the modal window
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window);
+
+/**
+ * Explicitly set input focus to the window.
+ *
+ * You almost certainly want SDL_RaiseWindow() instead of this function. Use
+ * this with caution, as you might give focus to a window that is completely
+ * obscured by other windows.
+ *
+ * \param window the window that should get the input focus
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_RaiseWindow
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowInputFocus(SDL_Window * window);
+
+/**
+ * Set the gamma ramp for the display that owns a given window.
+ *
+ * Set the gamma translation table for the red, green, and blue channels of
+ * the video hardware. Each table is an array of 256 16-bit quantities,
+ * representing a mapping between the input and output for that channel. The
+ * input is the index into the array, and the output is the 16-bit gamma value
+ * at that index, scaled to the output color precision.
+ *
+ * Despite the name and signature, this method sets the gamma ramp of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().) The gamma
+ * ramp set will not follow the window if it is moved to another display.
+ *
+ * \param window the window used to select the display whose gamma ramp will
+ * be changed
+ * \param red a 256 element array of 16-bit quantities representing the
+ * translation table for the red channel, or NULL
+ * \param green a 256 element array of 16-bit quantities representing the
+ * translation table for the green channel, or NULL
+ * \param blue a 256 element array of 16-bit quantities representing the
+ * translation table for the blue channel, or NULL
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowGammaRamp
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowGammaRamp(SDL_Window * window,
+ const Uint16 * red,
+ const Uint16 * green,
+ const Uint16 * blue);
+
+/**
+ * Get the gamma ramp for a given window's display.
+ *
+ * Despite the name and signature, this method retrieves the gamma ramp of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().)
+ *
+ * \param window the window used to select the display whose gamma ramp will
+ * be queried
+ * \param red a 256 element array of 16-bit quantities filled in with the
+ * translation table for the red channel, or NULL
+ * \param green a 256 element array of 16-bit quantities filled in with the
+ * translation table for the green channel, or NULL
+ * \param blue a 256 element array of 16-bit quantities filled in with the
+ * translation table for the blue channel, or NULL
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetWindowGammaRamp
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window,
+ Uint16 * red,
+ Uint16 * green,
+ Uint16 * blue);
+
+/**
+ * Possible return values from the SDL_HitTest callback.
+ *
+ * \sa SDL_HitTest
+ */
+typedef enum
+{
+ SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */
+ SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */
+ SDL_HITTEST_RESIZE_TOPLEFT,
+ SDL_HITTEST_RESIZE_TOP,
+ SDL_HITTEST_RESIZE_TOPRIGHT,
+ SDL_HITTEST_RESIZE_RIGHT,
+ SDL_HITTEST_RESIZE_BOTTOMRIGHT,
+ SDL_HITTEST_RESIZE_BOTTOM,
+ SDL_HITTEST_RESIZE_BOTTOMLEFT,
+ SDL_HITTEST_RESIZE_LEFT
+} SDL_HitTestResult;
+
+/**
+ * Callback used for hit-testing.
+ *
+ * \param win the SDL_Window where hit-testing was set on
+ * \param area an SDL_Point which should be hit-tested
+ * \param data what was passed as `callback_data` to SDL_SetWindowHitTest()
+ * \return an SDL_HitTestResult value.
+ *
+ * \sa SDL_SetWindowHitTest
+ */
+typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
+ const SDL_Point *area,
+ void *data);
+
+/**
+ * Provide a callback that decides if a window region has special properties.
+ *
+ * Normally windows are dragged and resized by decorations provided by the
+ * system window manager (a title bar, borders, etc), but for some apps, it
+ * makes sense to drag them from somewhere else inside the window itself; for
+ * example, one might have a borderless window that wants to be draggable from
+ * any part, or simulate its own title bar, etc.
+ *
+ * This function lets the app provide a callback that designates pieces of a
+ * given window as special. This callback is run during event processing if we
+ * need to tell the OS to treat a region of the window specially; the use of
+ * this callback is known as "hit testing."
+ *
+ * Mouse input may not be delivered to your application if it is within a
+ * special area; the OS will often apply that input to moving the window or
+ * resizing the window and not deliver it to the application.
+ *
+ * Specifying NULL for a callback disables hit-testing. Hit-testing is
+ * disabled by default.
+ *
+ * Platforms that don't support this functionality will return -1
+ * unconditionally, even if you're attempting to disable hit-testing.
+ *
+ * Your callback may fire at any time, and its firing does not indicate any
+ * specific behavior (for example, on Windows, this certainly might fire when
+ * the OS is deciding whether to drag your window, but it fires for lots of
+ * other reasons, too, some unrelated to anything you probably care about _and
+ * when the mouse isn't actually at the location it is testing_). Since this
+ * can fire at any time, you should try to keep your callback efficient,
+ * devoid of allocations, etc.
+ *
+ * \param window the window to set hit-testing on
+ * \param callback the function to call when doing a hit-test
+ * \param callback_data an app-defined void pointer passed to **callback**
+ * \returns 0 on success or -1 on error (including unsupported); call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window * window,
+ SDL_HitTest callback,
+ void *callback_data);
+
+/**
+ * Request a window to demand attention from the user.
+ *
+ * \param window the window to be flashed
+ * \param operation the flash operation
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window * window, SDL_FlashOperation operation);
+
+/**
+ * Destroy a window.
+ *
+ * If `window` is NULL, this function will return immediately after setting
+ * the SDL error message to "Invalid window". See SDL_GetError().
+ *
+ * \param window the window to destroy
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_CreateWindowFrom
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window * window);
+
+
+/**
+ * Check whether the screensaver is currently enabled.
+ *
+ * The screensaver is disabled by default since SDL 2.0.2. Before SDL 2.0.2
+ * the screensaver was enabled by default.
+ *
+ * The default can also be changed using `SDL_HINT_VIDEO_ALLOW_SCREENSAVER`.
+ *
+ * \returns SDL_TRUE if the screensaver is enabled, SDL_FALSE if it is
+ * disabled.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DisableScreenSaver
+ * \sa SDL_EnableScreenSaver
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenSaverEnabled(void);
+
+/**
+ * Allow the screen to be blanked by a screen saver.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DisableScreenSaver
+ * \sa SDL_IsScreenSaverEnabled
+ */
+extern DECLSPEC void SDLCALL SDL_EnableScreenSaver(void);
+
+/**
+ * Prevent the screen from being blanked by a screen saver.
+ *
+ * If you disable the screensaver, it is automatically re-enabled when SDL
+ * quits.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_EnableScreenSaver
+ * \sa SDL_IsScreenSaverEnabled
+ */
+extern DECLSPEC void SDLCALL SDL_DisableScreenSaver(void);
+
+
+/**
+ * \name OpenGL support functions
+ */
+/* @{ */
+
+/**
+ * Dynamically load an OpenGL library.
+ *
+ * This should be done after initializing the video driver, but before
+ * creating any OpenGL windows. If no OpenGL library is loaded, the default
+ * library will be loaded upon creation of the first OpenGL window.
+ *
+ * If you do this, you need to retrieve all of the GL functions used in your
+ * program from the dynamic library using SDL_GL_GetProcAddress().
+ *
+ * \param path the platform dependent OpenGL library name, or NULL to open the
+ * default OpenGL library
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_GetProcAddress
+ * \sa SDL_GL_UnloadLibrary
+ */
+extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path);
+
+/**
+ * Get an OpenGL function by name.
+ *
+ * If the GL library is loaded at runtime with SDL_GL_LoadLibrary(), then all
+ * GL functions must be retrieved this way. Usually this is used to retrieve
+ * function pointers to OpenGL extensions.
+ *
+ * There are some quirks to looking up OpenGL functions that require some
+ * extra care from the application. If you code carefully, you can handle
+ * these quirks without any platform-specific code, though:
+ *
+ * - On Windows, function pointers are specific to the current GL context;
+ * this means you need to have created a GL context and made it current
+ * before calling SDL_GL_GetProcAddress(). If you recreate your context or
+ * create a second context, you should assume that any existing function
+ * pointers aren't valid to use with it. This is (currently) a
+ * Windows-specific limitation, and in practice lots of drivers don't suffer
+ * this limitation, but it is still the way the wgl API is documented to
+ * work and you should expect crashes if you don't respect it. Store a copy
+ * of the function pointers that comes and goes with context lifespan.
+ * - On X11, function pointers returned by this function are valid for any
+ * context, and can even be looked up before a context is created at all.
+ * This means that, for at least some common OpenGL implementations, if you
+ * look up a function that doesn't exist, you'll get a non-NULL result that
+ * is _NOT_ safe to call. You must always make sure the function is actually
+ * available for a given GL context before calling it, by checking for the
+ * existence of the appropriate extension with SDL_GL_ExtensionSupported(),
+ * or verifying that the version of OpenGL you're using offers the function
+ * as core functionality.
+ * - Some OpenGL drivers, on all platforms, *will* return NULL if a function
+ * isn't supported, but you can't count on this behavior. Check for
+ * extensions you use, and if you get a NULL anyway, act as if that
+ * extension wasn't available. This is probably a bug in the driver, but you
+ * can code defensively for this scenario anyhow.
+ * - Just because you're on Linux/Unix, don't assume you'll be using X11.
+ * Next-gen display servers are waiting to replace it, and may or may not
+ * make the same promises about function pointers.
+ * - OpenGL function pointers must be declared `APIENTRY` as in the example
+ * code. This will ensure the proper calling convention is followed on
+ * platforms where this matters (Win32) thereby avoiding stack corruption.
+ *
+ * \param proc the name of an OpenGL function
+ * \returns a pointer to the named OpenGL function. The returned pointer
+ * should be cast to the appropriate function signature.
+ *
+ * \sa SDL_GL_ExtensionSupported
+ * \sa SDL_GL_LoadLibrary
+ * \sa SDL_GL_UnloadLibrary
+ */
+extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc);
+
+/**
+ * Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary().
+ *
+ * \sa SDL_GL_LoadLibrary
+ */
+extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void);
+
+/**
+ * Check if an OpenGL extension is supported for the current context.
+ *
+ * This function operates on the current GL context; you must have created a
+ * context and it must be current before calling this function. Do not assume
+ * that all contexts you create will have the same set of extensions
+ * available, or that recreating an existing context will offer the same
+ * extensions again.
+ *
+ * While it's probably not a massive overhead, this function is not an O(1)
+ * operation. Check the extensions you care about after creating the GL
+ * context and save that information somewhere instead of calling the function
+ * every time you need to know.
+ *
+ * \param extension the name of the extension to check
+ * \returns SDL_TRUE if the extension is supported, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char
+ *extension);
+
+/**
+ * Reset all previously set OpenGL context attributes to their default values.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GL_GetAttribute
+ * \sa SDL_GL_SetAttribute
+ */
+extern DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void);
+
+/**
+ * Set an OpenGL window attribute before window creation.
+ *
+ * This function sets the OpenGL attribute `attr` to `value`. The requested
+ * attributes should be set before creating an OpenGL window. You should use
+ * SDL_GL_GetAttribute() to check the values after creating the OpenGL
+ * context, since the values obtained can differ from the requested ones.
+ *
+ * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to set
+ * \param value the desired value for the attribute
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_GetAttribute
+ * \sa SDL_GL_ResetAttributes
+ */
+extern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);
+
+/**
+ * Get the actual value for an attribute from the current context.
+ *
+ * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to get
+ * \param value a pointer filled in with the current value of `attr`
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_ResetAttributes
+ * \sa SDL_GL_SetAttribute
+ */
+extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value);
+
+/**
+ * Create an OpenGL context for an OpenGL window, and make it current.
+ *
+ * Windows users new to OpenGL should note that, for historical reasons, GL
+ * functions added after OpenGL version 1.1 are not available by default.
+ * Those functions must be loaded at run-time, either with an OpenGL
+ * extension-handling library or with SDL_GL_GetProcAddress() and its related
+ * functions.
+ *
+ * SDL_GLContext is an alias for `void *`. It's opaque to the application.
+ *
+ * \param window the window to associate with the context
+ * \returns the OpenGL context associated with `window` or NULL on error; call
+ * SDL_GetError() for more details.
+ *
+ * \sa SDL_GL_DeleteContext
+ * \sa SDL_GL_MakeCurrent
+ */
+extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *
+ window);
+
+/**
+ * Set up an OpenGL context for rendering into an OpenGL window.
+ *
+ * The context must have been created with a compatible window.
+ *
+ * \param window the window to associate with the context
+ * \param context the OpenGL context to associate with the window
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_CreateContext
+ */
+extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window * window,
+ SDL_GLContext context);
+
+/**
+ * Get the currently active OpenGL window.
+ *
+ * \returns the currently active OpenGL window on success or NULL on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void);
+
+/**
+ * Get the currently active OpenGL context.
+ *
+ * \returns the currently active OpenGL context or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_MakeCurrent
+ */
+extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void);
+
+/**
+ * Get the size of a window's underlying drawable in pixels.
+ *
+ * This returns info useful for calling glViewport().
+ *
+ * This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI
+ * drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a
+ * platform with high-DPI support (Apple calls this "Retina"), and not
+ * disabled by the `SDL_HINT_VIDEO_HIGHDPI_DISABLED` hint.
+ *
+ * \param window the window from which the drawable size should be queried
+ * \param w a pointer to variable for storing the width in pixels, may be NULL
+ * \param h a pointer to variable for storing the height in pixels, may be
+ * NULL
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_GetWindowSize
+ */
+extern DECLSPEC void SDLCALL SDL_GL_GetDrawableSize(SDL_Window * window, int *w,
+ int *h);
+
+/**
+ * Set the swap interval for the current OpenGL context.
+ *
+ * Some systems allow specifying -1 for the interval, to enable adaptive
+ * vsync. Adaptive vsync works the same as vsync, but if you've already missed
+ * the vertical retrace for a given frame, it swaps buffers immediately, which
+ * might be less jarring for the user during occasional framerate drops. If an
+ * application requests adaptive vsync and the system does not support it,
+ * this function will fail and return -1. In such a case, you should probably
+ * retry the call with 1 for the interval.
+ *
+ * Adaptive vsync is implemented for some glX drivers with
+ * GLX_EXT_swap_control_tear:
+ *
+ * https://www.opengl.org/registry/specs/EXT/glx_swap_control_tear.txt
+ *
+ * and for some Windows drivers with WGL_EXT_swap_control_tear:
+ *
+ * https://www.opengl.org/registry/specs/EXT/wgl_swap_control_tear.txt
+ *
+ * Read more on the Khronos wiki:
+ * https://www.khronos.org/opengl/wiki/Swap_Interval#Adaptive_Vsync
+ *
+ * \param interval 0 for immediate updates, 1 for updates synchronized with
+ * the vertical retrace, -1 for adaptive vsync
+ * \returns 0 on success or -1 if setting the swap interval is not supported;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_GetSwapInterval
+ */
+extern DECLSPEC int SDLCALL SDL_GL_SetSwapInterval(int interval);
+
+/**
+ * Get the swap interval for the current OpenGL context.
+ *
+ * If the system can't determine the swap interval, or there isn't a valid
+ * current context, this function will return 0 as a safe default.
+ *
+ * \returns 0 if there is no vertical retrace synchronization, 1 if the buffer
+ * swap is synchronized with the vertical retrace, and -1 if late
+ * swaps happen immediately instead of waiting for the next retrace;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_SetSwapInterval
+ */
+extern DECLSPEC int SDLCALL SDL_GL_GetSwapInterval(void);
+
+/**
+ * Update a window with OpenGL rendering.
+ *
+ * This is used with double-buffered OpenGL contexts, which are the default.
+ *
+ * On macOS, make sure you bind 0 to the draw framebuffer before swapping the
+ * window, otherwise nothing will happen. If you aren't using
+ * glBindFramebuffer(), this is the default and you won't have to do anything
+ * extra.
+ *
+ * \param window the window to change
+ */
+extern DECLSPEC void SDLCALL SDL_GL_SwapWindow(SDL_Window * window);
+
+/**
+ * Delete an OpenGL context.
+ *
+ * \param context the OpenGL context to be deleted
+ *
+ * \sa SDL_GL_CreateContext
+ */
+extern DECLSPEC void SDLCALL SDL_GL_DeleteContext(SDL_GLContext context);
+
+/* @} *//* OpenGL support functions */
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_video_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/SDL_vulkan.h b/Client/ThirdParty/SDL2/SDL_vulkan.h
new file mode 100644
index 0000000..006c5aa
--- /dev/null
+++ b/Client/ThirdParty/SDL2/SDL_vulkan.h
@@ -0,0 +1,213 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 2017, Mark Callow
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_vulkan.h
+ *
+ * Header file for functions to creating Vulkan surfaces on SDL windows.
+ */
+
+#ifndef SDL_vulkan_h_
+#define SDL_vulkan_h_
+
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Avoid including vulkan.h, don't define VkInstance if it's already included */
+#ifdef VULKAN_H_
+#define NO_SDL_VULKAN_TYPEDEFS
+#endif
+#ifndef NO_SDL_VULKAN_TYPEDEFS
+#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+
+#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
+#else
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#endif
+
+VK_DEFINE_HANDLE(VkInstance)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
+
+#endif /* !NO_SDL_VULKAN_TYPEDEFS */
+
+typedef VkInstance SDL_vulkanInstance;
+typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */
+
+/**
+ * \name Vulkan support functions
+ *
+ * \note SDL_Vulkan_GetInstanceExtensions & SDL_Vulkan_CreateSurface API
+ * is compatable with Tizen's implementation of Vulkan in SDL.
+ */
+/* @{ */
+
+/**
+ * Dynamically load the Vulkan loader library.
+ *
+ * This should be called after initializing the video driver, but before
+ * creating any Vulkan windows. If no Vulkan loader library is loaded, the
+ * default library will be loaded upon creation of the first Vulkan window.
+ *
+ * It is fairly common for Vulkan applications to link with libvulkan instead
+ * of explicitly loading it at run time. This will work with SDL provided the
+ * application links to a dynamic library and both it and SDL use the same
+ * search path.
+ *
+ * If you specify a non-NULL `path`, an application should retrieve all of the
+ * Vulkan functions it uses from the dynamic library using
+ * SDL_Vulkan_GetVkGetInstanceProcAddr unless you can guarantee `path` points
+ * to the same vulkan loader library the application linked to.
+ *
+ * On Apple devices, if `path` is NULL, SDL will attempt to find the
+ * `vkGetInstanceProcAddr` address within all the Mach-O images of the current
+ * process. This is because it is fairly common for Vulkan applications to
+ * link with libvulkan (and historically MoltenVK was provided as a static
+ * library). If it is not found, on macOS, SDL will attempt to load
+ * `vulkan.framework/vulkan`, `libvulkan.1.dylib`,
+ * `MoltenVK.framework/MoltenVK`, and `libMoltenVK.dylib`, in that order. On
+ * iOS, SDL will attempt to load `libMoltenVK.dylib`. Applications using a
+ * dynamic framework or .dylib must ensure it is included in its application
+ * bundle.
+ *
+ * On non-Apple devices, application linking with a static libvulkan is not
+ * supported. Either do not link to the Vulkan loader or link to a dynamic
+ * library version.
+ *
+ * \param path The platform dependent Vulkan loader library name or NULL
+ * \returns 0 on success or -1 if the library couldn't be loaded; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_GetVkInstanceProcAddr
+ * \sa SDL_Vulkan_UnloadLibrary
+ */
+extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path);
+
+/**
+ * Get the address of the `vkGetInstanceProcAddr` function.
+ *
+ * This should be called after either calling SDL_Vulkan_LoadLibrary() or
+ * creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag.
+ *
+ * \returns the function pointer for `vkGetInstanceProcAddr` or NULL on error.
+ */
+extern DECLSPEC void *SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void);
+
+/**
+ * Unload the Vulkan library previously loaded by SDL_Vulkan_LoadLibrary()
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_LoadLibrary
+ */
+extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
+
+/**
+ * Get the names of the Vulkan instance extensions needed to create a surface
+ * with SDL_Vulkan_CreateSurface.
+ *
+ * If `pNames` is NULL, then the number of required Vulkan instance extensions
+ * is returned in `pCount`. Otherwise, `pCount` must point to a variable set
+ * to the number of elements in the `pNames` array, and on return the variable
+ * is overwritten with the number of names actually written to `pNames`. If
+ * `pCount` is less than the number of required extensions, at most `pCount`
+ * structures will be written. If `pCount` is smaller than the number of
+ * required extensions, SDL_FALSE will be returned instead of SDL_TRUE, to
+ * indicate that not all the required extensions were returned.
+ *
+ * The `window` parameter is currently needed to be valid as of SDL 2.0.8,
+ * however, this parameter will likely be removed in future releases
+ *
+ * \param window A window for which the required Vulkan instance extensions
+ * should be retrieved (will be deprecated in a future release)
+ * \param pCount A pointer to an unsigned int corresponding to the number of
+ * extensions to be returned
+ * \param pNames NULL or a pointer to an array to be filled with required
+ * Vulkan instance extensions
+ * \returns SDL_TRUE on success, SDL_FALSE on error.
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_CreateSurface
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_GetInstanceExtensions(SDL_Window *window,
+ unsigned int *pCount,
+ const char **pNames);
+
+/**
+ * Create a Vulkan rendering surface for a window.
+ *
+ * The `window` must have been created with the `SDL_WINDOW_VULKAN` flag and
+ * `instance` must have been created with extensions returned by
+ * SDL_Vulkan_GetInstanceExtensions() enabled.
+ *
+ * \param window The window to which to attach the Vulkan surface
+ * \param instance The Vulkan instance handle
+ * \param surface A pointer to a VkSurfaceKHR handle to output the newly
+ * created surface
+ * \returns SDL_TRUE on success, SDL_FALSE on error.
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_GetInstanceExtensions
+ * \sa SDL_Vulkan_GetDrawableSize
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR* surface);
+
+/**
+ * Get the size of the window's underlying drawable dimensions in pixels.
+ *
+ * This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI
+ * drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a
+ * platform with high-DPI support (Apple calls this "Retina"), and not
+ * disabled by the `SDL_HINT_VIDEO_HIGHDPI_DISABLED` hint.
+ *
+ * \param window an SDL_Window for which the size is to be queried
+ * \param w Pointer to the variable to write the width to or NULL
+ * \param h Pointer to the variable to write the height to or NULL
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_GetWindowSize
+ * \sa SDL_CreateWindow
+ * \sa SDL_Vulkan_CreateSurface
+ */
+extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window * window,
+ int *w, int *h);
+
+/* @} *//* Vulkan support functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_vulkan_h_ */
diff --git a/Client/ThirdParty/SDL2/WhatsNew.txt b/Client/ThirdParty/SDL2/WhatsNew.txt
new file mode 100644
index 0000000..257fb75
--- /dev/null
+++ b/Client/ThirdParty/SDL2/WhatsNew.txt
@@ -0,0 +1,643 @@
+
+This is a list of major changes in SDL's version history.
+
+---------------------------------------------------------------------------
+2.0.16:
+---------------------------------------------------------------------------
+General:
+* Added SDL_FlashWindow() to get a user's attention
+* Added SDL_GetAudioDeviceSpec() to get the preferred audio format of a device
+* Added SDL_SetWindowAlwaysOnTop() to dynamically change the SDL_WINDOW_ALWAYS_ON_TOP flag for a window
+* Added SDL_SetWindowKeyboardGrab() to support grabbing the keyboard independently of the mouse
+* Added SDL_SoftStretchLinear() to do bilinear scaling between 32-bit software surfaces
+* Added SDL_UpdateNVTexture() to update streaming NV12/21 textures
+* Added SDL_GameControllerSendEffect() and SDL_JoystickSendEffect() to allow sending custom trigger effects to the DualSense controller
+* Added SDL_GameControllerGetSensorDataRate() to get the sensor data rate for PlayStation and Nintendo Switch controllers
+* Added support for the Amazon Luna game controller
+* Added rumble support for the Google Stadia controller using the HIDAPI driver
+* Added SDL_GameControllerType constants for the Amazon Luna and Google Stadia controllers
+* Added analog rumble for Nintendo Switch Pro controllers using the HIDAPI driver
+* Reduced CPU usage when using SDL_WaitEvent() and SDL_WaitEventTimeout()
+
+Windows:
+* Added SDL_SetWindowsMessageHook() to set a function that is called for all Windows messages
+* Added SDL_RenderGetD3D11Device() to get the D3D11 device used by the SDL renderer
+
+Linux:
+* Greatly improved Wayland support
+* Added support for audio output and capture using Pipewire
+* Added the hint SDL_HINT_AUDIO_INCLUDE_MONITORS to control whether PulseAudio recording should include monitor devices
+* Added the hint SDL_HINT_AUDIO_DEVICE_STREAM_ROLE to describe the role of your application for audio control panels
+
+Android:
+* Added support for audio output and capture using AAudio
+* Added SDL_AndroidShowToast() to show a lightweight notification
+
+iOS:
+* Added support for mouse relative mode on iOS 14.1 and newer
+* Added support for the Xbox Series X controller
+
+tvOS:
+* Added support for the Xbox Series X controller
+
+
+---------------------------------------------------------------------------
+2.0.14:
+---------------------------------------------------------------------------
+General:
+* Added support for PS5 DualSense and Xbox Series X controllers to the HIDAPI controller driver
+* Added game controller button constants for paddles and new buttons
+* Added game controller functions to get additional information:
+ * SDL_GameControllerGetSerial()
+ * SDL_GameControllerHasAxis()
+ * SDL_GameControllerHasButton()
+ * SDL_GameControllerGetNumTouchpads()
+ * SDL_GameControllerGetNumTouchpadFingers()
+ * SDL_GameControllerGetTouchpadFinger()
+ * SDL_GameControllerHasSensor()
+ * SDL_GameControllerSetSensorEnabled()
+ * SDL_GameControllerIsSensorEnabled()
+ * SDL_GameControllerGetSensorData()
+ * SDL_GameControllerRumbleTriggers()
+ * SDL_GameControllerHasLED()
+ * SDL_GameControllerSetLED()
+* Added the hint SDL_HINT_JOYSTICK_HIDAPI_PS5 to control whether the HIDAPI driver for PS5 controllers should be used.
+* Added joystick functions to get additional information:
+ * SDL_JoystickGetSerial()
+ * SDL_JoystickRumbleTriggers()
+ * SDL_JoystickHasLED()
+ * SDL_JoystickSetLED()
+* Added an API to allow the application to create virtual joysticks:
+ * SDL_JoystickAttachVirtual()
+ * SDL_JoystickDetachVirtual()
+ * SDL_JoystickIsVirtual()
+ * SDL_JoystickSetVirtualAxis()
+ * SDL_JoystickSetVirtualButton()
+ * SDL_JoystickSetVirtualHat()
+* Added SDL_LockSensors() and SDL_UnlockSensors() to guarantee exclusive access to the sensor list
+* Added SDL_HAPTIC_STEERING_AXIS to play an effect on the steering wheel
+* Added the hint SDL_HINT_MOUSE_RELATIVE_SCALING to control whether relative motion is scaled by the screen DPI or renderer logical size
+* The default value for SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS is now false for better compatibility with modern window managers
+* Added SDL_GetPreferredLocales() to get the application's current locale setting
+* Added the hint SDL_HINT_PREFERRED_LOCALES to override your application's default locale setting
+* Added SDL_OpenURL() to open a URL in the system's default browser
+* Added SDL_HasSurfaceRLE() to tell whether a surface is currently using RLE encoding
+* Added SDL_SIMDRealloc() to reallocate memory obtained from SDL_SIMDAlloc()
+* Added SDL_GetErrorMsg() to get the last error in a thread-safe way
+* Added SDL_crc32(), SDL_wcscasecmp(), SDL_wcsncasecmp(), SDL_trunc(), SDL_truncf()
+* Added clearer names for RGB pixel formats, e.g. SDL_PIXELFORMAT_XRGB8888, SDL_PIXELFORMAT_XBGR8888, etc.
+
+Windows:
+* Added the RAWINPUT controller driver to support more than 4 Xbox controllers simultaneously
+* Added the hint SDL_HINT_JOYSTICK_RAWINPUT to control whether the RAWINPUT driver should be used
+* Added the hint SDL_HINT_JOYSTICK_HIDAPI_CORRELATE_XINPUT to control whether XInput and WGI should be used to for complete controller functionality with the RAWINPUT driver.
+
+macOS:
+* Added the SDL_WINDOW_METAL flag to specify that a window should be created with a Metal view
+* Added SDL_Metal_GetLayer() to get the CAMetalLayer backing a Metal view
+* Added SDL_Metal_GetDrawableSize() to get the size of a window's drawable, in pixels
+
+Linux:
+* Added the hint SDL_HINT_AUDIO_DEVICE_APP_NAME to specify the name that shows up in PulseAudio for your application
+* Added the hint SDL_HINT_AUDIO_DEVICE_STREAM_NAME to specify the name that shows up in PulseAudio associated with your audio stream
+* Added the hint SDL_HINT_LINUX_JOYSTICK_DEADZONES to control whether HID defined dead zones should be respected on Linux
+* Added the hint SDL_HINT_THREAD_PRIORITY_POLICY to specify the thread scheduler policy
+* Added the hint SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL to allow time critical threads to use a realtime scheduling policy
+
+Android:
+* Added SDL_AndroidRequestPermission() to request a specific system permission
+* Added the hint SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO to control whether audio will pause when the application goes intot he background
+
+OS/2:
+* Added support for OS/2, see docs/README-os2.md for details
+
+Emscripten (running in a web browser):
+* Added the hint SDL_HINT_EMSCRIPTEN_ASYNCIFY to control whether SDL should call emscripten_sleep internally
+
+
+---------------------------------------------------------------------------
+2.0.12:
+---------------------------------------------------------------------------
+
+General:
+* Added SDL_GetTextureScaleMode() and SDL_SetTextureScaleMode() to get and set the scaling mode used for a texture
+* Added SDL_LockTextureToSurface(), similar to SDL_LockTexture() but the locked area is exposed as a SDL surface.
+* Added new blend mode, SDL_BLENDMODE_MUL, which does a modulate and blend operation
+* Added the hint SDL_HINT_DISPLAY_USABLE_BOUNDS to override the results of SDL_GetDisplayUsableBounds() for display index 0.
+* Added the window underneath the finger to the SDL_TouchFingerEvent
+* Added SDL_GameControllerTypeForIndex(), SDL_GameControllerGetType() to return the type of a game controller (Xbox 360, Xbox One, PS3, PS4, or Nintendo Switch Pro)
+* Added the hint SDL_HINT_GAMECONTROLLERTYPE to override the automatic game controller type detection
+* Added SDL_JoystickFromPlayerIndex() and SDL_GameControllerFromPlayerIndex() to get the device associated with a player index
+* Added SDL_JoystickSetPlayerIndex() and SDL_GameControllerSetPlayerIndex() to set the player index associated with a device
+* Added the hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS to specify whether Nintendo Switch Pro controllers should use the buttons as labeled or swapped to match positional layout. The default is to use the buttons as labeled.
+* Added support for Nintendo GameCube controllers to the HIDAPI driver, and a hint SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE to control whether this is used.
+* Improved support for Xbox 360 and Xbox One controllers when using the HIDAPI driver
+* Added support for many game controllers, including:
+ * 8BitDo FC30 Pro
+ * 8BitDo M30 GamePad
+ * BDA PS4 Fightpad
+ * HORI Fighting Commander
+ * Hyperkin Duke
+ * Hyperkin X91
+ * MOGA XP5-A Plus
+ * NACON GC-400ES
+ * NVIDIA Controller v01.04
+ * PDP Versus Fighting Pad
+ * Razer Raion Fightpad for PS4
+ * Razer Serval
+ * Stadia Controller
+ * SteelSeries Stratus Duo
+ * Victrix Pro Fight Stick for PS4
+ * Xbox One Elite Series 2
+* Fixed blocking game controller rumble calls when using the HIDAPI driver
+* Added SDL_zeroa() macro to zero an array of elements
+* Added SDL_HasARMSIMD() which returns true if the CPU has ARM SIMD (ARMv6+) features
+
+Windows:
+* Fixed crash when using the release SDL DLL with applications built with gcc
+* Fixed performance regression in event handling introduced in 2.0.10
+* Added support for SDL_SetThreadPriority() for UWP applications
+
+Linux:
+* Added the hint SDL_HINT_VIDEO_X11_WINDOW_VISUALID to specify the visual chosen for new X11 windows
+* Added the hint SDL_HINT_VIDEO_X11_FORCE_EGL to specify whether X11 should use GLX or EGL by default
+
+iOS / tvOS / macOS:
+* Added SDL_Metal_CreateView() and SDL_Metal_DestroyView() to create CAMetalLayer-backed NSView/UIView and attach it to the specified window.
+
+iOS/ tvOS:
+* Added support for Bluetooth Steam Controllers as game controllers
+
+tvOS:
+* Fixed support for surround sound on Apple TV
+
+Android:
+* Added SDL_GetAndroidSDKVersion() to return the API level of the current device
+* Added support for audio capture using OpenSL-ES
+* Added support for Bluetooth Steam Controllers as game controllers
+* Fixed rare crashes when the app goes into the background or terminates
+
+
+---------------------------------------------------------------------------
+2.0.10:
+---------------------------------------------------------------------------
+
+General:
+* The SDL_RW* macros have been turned into functions that are available only in 2.0.10 and onward
+* Added SDL_SIMDGetAlignment(), SDL_SIMDAlloc(), and SDL_SIMDFree(), to allocate memory aligned for SIMD operations for the current CPU
+* Added SDL_RenderDrawPointF(), SDL_RenderDrawPointsF(), SDL_RenderDrawLineF(), SDL_RenderDrawLinesF(), SDL_RenderDrawRectF(), SDL_RenderDrawRectsF(), SDL_RenderFillRectF(), SDL_RenderFillRectsF(), SDL_RenderCopyF(), SDL_RenderCopyExF(), to allow floating point precision in the SDL rendering API.
+* Added SDL_GetTouchDeviceType() to get the type of a touch device, which can be a touch screen or a trackpad in relative or absolute coordinate mode.
+* The SDL rendering API now uses batched rendering by default, for improved performance
+* Added SDL_RenderFlush() to force batched render commands to execute, if you're going to mix SDL rendering with native rendering
+* Added the hint SDL_HINT_RENDER_BATCHING to control whether batching should be used for the rendering API. This defaults to "1" if you don't specify what rendering driver to use when creating the renderer.
+* Added the hint SDL_HINT_EVENT_LOGGING to enable logging of SDL events for debugging purposes
+* Added the hint SDL_HINT_GAMECONTROLLERCONFIG_FILE to specify a file that will be loaded at joystick initialization with game controller bindings
+* Added the hint SDL_HINT_MOUSE_TOUCH_EVENTS to control whether SDL will synthesize touch events from mouse events
+* Improved handling of malformed WAVE and BMP files, fixing potential security exploits
+
+Linux:
+* Removed the Mir video driver in favor of Wayland
+
+iOS / tvOS:
+* Added support for Xbox and PS4 wireless controllers in iOS 13 and tvOS 13
+* Added support for text input using Bluetooth keyboards
+
+Android:
+* Added low latency audio using OpenSL ES
+* Removed SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH (replaced by SDL_HINT_MOUSE_TOUCH_EVENTS and SDL_HINT_TOUCH_MOUSE_EVENTS)
+ SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=1, should be replaced by setting both previous hints to 0.
+ SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=0, should be replaced by setting both previous hints to 1.
+* Added the hint SDL_HINT_ANDROID_BLOCK_ON_PAUSE to set whether the event loop will block itself when the app is paused.
+
+
+---------------------------------------------------------------------------
+2.0.9:
+---------------------------------------------------------------------------
+
+General:
+* Added a new sensor API, initialized by passing SDL_INIT_SENSOR to SDL_Init(), and defined in SDL_sensor.h
+* Added an event SDL_SENSORUPDATE which is sent when a sensor is updated
+* Added SDL_GetDisplayOrientation() to return the current display orientation
+* Added an event SDL_DISPLAYEVENT which is sent when the display orientation changes
+* Added HIDAPI joystick drivers for more consistent support for Xbox, PS4 and Nintendo Switch Pro controller support across platforms. (Thanks to Valve for contributing the PS4 and Nintendo Switch Pro controller support)
+* Added support for many other popular game controllers
+* Added SDL_JoystickGetDevicePlayerIndex(), SDL_JoystickGetPlayerIndex(), and SDL_GameControllerGetPlayerIndex() to get the player index for a controller. For XInput controllers this returns the XInput index for the controller.
+* Added SDL_GameControllerRumble() and SDL_JoystickRumble() which allow simple rumble without using the haptics API
+* Added SDL_GameControllerMappingForDeviceIndex() to get the mapping for a controller before it's opened
+* Added the hint SDL_HINT_MOUSE_DOUBLE_CLICK_TIME to control the mouse double-click time
+* Added the hint SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS to control the mouse double-click radius, in pixels
+* Added SDL_HasColorKey() to return whether a surface has a colorkey active
+* Added SDL_HasAVX512F() to return whether the CPU has AVX-512F features
+* Added SDL_IsTablet() to return whether the application is running on a tablet
+* Added SDL_THREAD_PRIORITY_TIME_CRITICAL for threads that must run at the highest priority
+
+Mac OS X:
+* Fixed black screen at start on Mac OS X Mojave
+
+Linux:
+* Added SDL_LinuxSetThreadPriority() to allow adjusting the thread priority of native threads using RealtimeKit if available.
+
+iOS:
+* Fixed Asian IME input
+
+Android:
+* Updated required Android SDK to API 26, to match Google's new App Store requirements
+* Added support for wired USB Xbox, PS4, and Nintendo Switch Pro controllers
+* Added support for relative mouse mode on Android 7.0 and newer (except where it's broken, on Chromebooks and when in DeX mode with Samsung Experience 9.0)
+* Added support for custom mouse cursors on Android 7.0 and newer
+* Added the hint SDL_HINT_ANDROID_TRAP_BACK_BUTTON to control whether the back button will back out of the app (the default) or be passed to the application as SDL_SCANCODE_AC_BACK
+* Added SDL_AndroidBackButton() to trigger the Android system back button behavior when handling the back button in the application
+* Added SDL_IsChromebook() to return whether the app is running in the Chromebook Android runtime
+* Added SDL_IsDeXMode() to return whether the app is running while docked in the Samsung DeX
+
+
+---------------------------------------------------------------------------
+2.0.8:
+---------------------------------------------------------------------------
+
+General:
+* Added SDL_fmod() and SDL_log10()
+* Each of the SDL math functions now has the corresponding float version
+* Added SDL_SetYUVConversionMode() and SDL_GetYUVConversionMode() to control the formula used when converting to and from YUV colorspace. The options are JPEG, BT.601, and BT.709
+
+Windows:
+* Implemented WASAPI support on Windows UWP and removed the deprecated XAudio2 implementation
+* Added resampling support on WASAPI on Windows 7 and above
+
+Windows UWP:
+* Added SDL_WinRTGetDeviceFamily() to find out what type of device your application is running on
+
+Mac OS X:
+* Added support for the Vulkan SDK for Mac:
+ https://www.lunarg.com/lunarg-releases-vulkan-sdk-1-0-69-0-for-mac/
+* Added support for OpenGL ES using ANGLE when it's available
+
+Mac OS X / iOS / tvOS:
+* Added a Metal 2D render implementation
+* Added SDL_RenderGetMetalLayer() and SDL_RenderGetMetalCommandEncoder() to insert your own drawing into SDL rendering when using the Metal implementation
+
+iOS:
+* Added the hint SDL_HINT_IOS_HIDE_HOME_INDICATOR to control whether the home indicator bar on iPhone X should be hidden. This defaults to dimming the indicator for fullscreen applications and showing the indicator for windowed applications.
+
+iOS / Android:
+* Added the hint SDL_HINT_RETURN_KEY_HIDES_IME to control whether the return key on the software keyboard should hide the keyboard or send a key event (the default)
+
+Android:
+* SDL now supports building with Android Studio and Gradle by default, and the old Ant project is available in android-project-ant
+* SDL now requires the API 19 SDK to build, but can still target devices down to API 14 (Android 4.0.1)
+* Added SDL_IsAndroidTV() to tell whether the application is running on Android TV
+
+Android / tvOS:
+* Added the hint SDL_HINT_TV_REMOTE_AS_JOYSTICK to control whether TV remotes should be listed as joystick devices (the default) or send keyboard events.
+
+Linux:
+* Added the hint SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR to control whether the X server should skip the compositor for the SDL application. This defaults to "1"
+* Added the hint SDL_HINT_VIDEO_DOUBLE_BUFFER to control whether the Raspberry Pi and KMSDRM video drivers should use double or triple buffering (the default)
+
+
+---------------------------------------------------------------------------
+2.0.7:
+---------------------------------------------------------------------------
+
+General:
+* Added audio stream conversion functions:
+ SDL_NewAudioStream
+ SDL_AudioStreamPut
+ SDL_AudioStreamGet
+ SDL_AudioStreamAvailable
+ SDL_AudioStreamFlush
+ SDL_AudioStreamClear
+ SDL_FreeAudioStream
+* Added functions to query and set the SDL memory allocation functions:
+ SDL_GetMemoryFunctions()
+ SDL_SetMemoryFunctions()
+ SDL_GetNumAllocations()
+* Added locking functions for multi-threaded access to the joystick and game controller APIs:
+ SDL_LockJoysticks()
+ SDL_UnlockJoysticks()
+* The following functions are now thread-safe:
+ SDL_SetEventFilter()
+ SDL_GetEventFilter()
+ SDL_AddEventWatch()
+ SDL_DelEventWatch()
+
+
+General:
+---------------------------------------------------------------------------
+2.0.6:
+---------------------------------------------------------------------------
+
+General:
+* Added cross-platform Vulkan graphics support in SDL_vulkan.h
+ SDL_Vulkan_LoadLibrary()
+ SDL_Vulkan_GetVkGetInstanceProcAddr()
+ SDL_Vulkan_GetInstanceExtensions()
+ SDL_Vulkan_CreateSurface()
+ SDL_Vulkan_GetDrawableSize()
+ SDL_Vulkan_UnloadLibrary()
+ This is all the platform-specific code you need to bring up Vulkan on all SDL platforms. You can look at an example in test/testvulkan.c
+* Added SDL_ComposeCustomBlendMode() to create custom blend modes for 2D rendering
+* Added SDL_HasNEON() which returns whether the CPU has NEON instruction support
+* Added support for many game controllers, including the Nintendo Switch Pro Controller
+* Added support for inverted axes and separate axis directions in game controller mappings
+* Added functions to return information about a joystick before it's opened:
+ SDL_JoystickGetDeviceVendor()
+ SDL_JoystickGetDeviceProduct()
+ SDL_JoystickGetDeviceProductVersion()
+ SDL_JoystickGetDeviceType()
+ SDL_JoystickGetDeviceInstanceID()
+* Added functions to return information about an open joystick:
+ SDL_JoystickGetVendor()
+ SDL_JoystickGetProduct()
+ SDL_JoystickGetProductVersion()
+ SDL_JoystickGetType()
+ SDL_JoystickGetAxisInitialState()
+* Added functions to return information about an open game controller:
+ SDL_GameControllerGetVendor()
+ SDL_GameControllerGetProduct()
+ SDL_GameControllerGetProductVersion()
+* Added SDL_GameControllerNumMappings() and SDL_GameControllerMappingForIndex() to be able to enumerate the built-in game controller mappings
+* Added SDL_LoadFile() and SDL_LoadFile_RW() to load a file into memory
+* Added SDL_DuplicateSurface() to make a copy of a surface
+* Added an experimental JACK audio driver
+* Implemented non-power-of-two audio resampling, optionally using libsamplerate to perform the resampling
+* Added the hint SDL_HINT_AUDIO_RESAMPLING_MODE to control the quality of resampling
+* Added the hint SDL_HINT_RENDER_LOGICAL_SIZE_MODE to control the scaling policy for SDL_RenderSetLogicalSize():
+ "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen (the default)
+ "1" or "overscan" - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
+* Added the hints SDL_HINT_MOUSE_NORMAL_SPEED_SCALE and SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE to scale the mouse speed when being read from raw mouse input
+* Added the hint SDL_HINT_TOUCH_MOUSE_EVENTS to control whether SDL will synthesize mouse events from touch events
+
+Windows:
+* The new default audio driver on Windows is WASAPI and supports hot-plugging devices and changing the default audio device
+* The old XAudio2 audio driver is deprecated and will be removed in the next release
+* Added hints SDL_HINT_WINDOWS_INTRESOURCE_ICON and SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL to specify a custom icon resource ID for SDL windows
+* The hint SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING is now on by default for compatibility with .NET languages and various Windows debuggers
+* Updated the GUID format for game controller mappings, older mappings will be automatically converted on load
+* Implemented the SDL_WINDOW_ALWAYS_ON_TOP flag on Windows
+
+Linux:
+* Added an experimental KMS/DRM video driver for embedded development
+
+iOS:
+* Added a hint SDL_HINT_AUDIO_CATEGORY to control the audio category, determining whether the phone mute switch affects the audio
+
+---------------------------------------------------------------------------
+2.0.5:
+---------------------------------------------------------------------------
+
+General:
+* Implemented audio capture support for some platforms
+* Added SDL_DequeueAudio() to retrieve audio when buffer queuing is turned on for audio capture
+* Added events for dragging and dropping text
+* Added events for dragging and dropping multiple items
+* By default the click raising a window will not be delivered to the SDL application. You can set the hint SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH to "1" to allow that click through to the window.
+* Saving a surface with an alpha channel as a BMP will use a newer BMP format that supports alpha information. You can set the hint SDL_HINT_BMP_SAVE_LEGACY_FORMAT to "1" to use the old format.
+* Added SDL_GetHintBoolean() to get the boolean value of a hint
+* Added SDL_RenderSetIntegerScale() to set whether to smoothly scale or use integral multiples of the viewport size when scaling the rendering output
+* Added SDL_CreateRGBSurfaceWithFormat() and SDL_CreateRGBSurfaceWithFormatFrom() to create an SDL surface with a specific pixel format
+* Added SDL_GetDisplayUsableBounds() which returns the area usable for windows. For example, on Mac OS X, this subtracts the area occupied by the menu bar and dock.
+* Added SDL_GetWindowBordersSize() which returns the size of the window's borders around the client area
+* Added a window event SDL_WINDOWEVENT_HIT_TEST when a window had a hit test that wasn't SDL_HITTEST_NORMAL (e.g. in the title bar or window frame)
+* Added SDL_SetWindowResizable() to change whether a window is resizable
+* Added SDL_SetWindowOpacity() and SDL_GetWindowOpacity() to affect the window transparency
+* Added SDL_SetWindowModalFor() to set a window as modal for another window
+* Added support for AUDIO_U16LSB and AUDIO_U16MSB to SDL_MixAudioFormat()
+* Fixed flipped images when reading back from target textures when using the OpenGL renderer
+* Fixed texture color modulation with SDL_BLENDMODE_NONE when using the OpenGL renderer
+* Fixed bug where the alpha value of colorkeys was ignored when blitting in some cases
+
+Windows:
+* Added a hint SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING to prevent SDL from raising a debugger exception to name threads. This exception can cause problems with .NET applications when running under a debugger.
+* The hint SDL_HINT_THREAD_STACK_SIZE is now supported on Windows
+* Fixed XBox controller triggers automatically being pulled at startup
+* The first icon from the executable is used as the default window icon at runtime
+* Fixed SDL log messages being printed twice if SDL was built with C library support
+* Reset dead keys when the SDL window loses focus, so dead keys pressed in SDL applications don't affect text input into other applications.
+
+Mac OS X:
+* Fixed selecting the dummy video driver
+* The caps lock key now generates a pressed event when pressed and a released event when released, instead of a press/release event pair when pressed.
+* Fixed mouse wheel events on Mac OS X 10.12
+* The audio driver has been updated to use AVFoundation for better compatibility with newer versions of Mac OS X
+
+Linux:
+* Added support for the Fcitx IME
+* Added a window event SDL_WINDOWEVENT_TAKE_FOCUS when a window manager asks the SDL window whether it wants to take focus.
+* Refresh rates are now rounded instead of truncated, e.g. 59.94 Hz is rounded up to 60 Hz instead of 59.
+* Added initial support for touchscreens on Raspberry Pi
+
+OpenBSD:
+* SDL_GetBasePath() is now implemented on OpenBSD
+
+iOS:
+* Added support for dynamically loaded objects on iOS 8 and newer
+
+tvOS:
+* Added support for Apple TV
+* Added a hint SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION to control whether he Apple TV remote's joystick axes will automatically match the rotation of the remote.
+
+Android:
+* Fixed SDL not resizing window when Android screen resolution changes
+* Corrected the joystick Z axis reporting for the accelerometer
+
+Emscripten (running in a web browser):
+* Many bug fixes and improvements
+
+
+---------------------------------------------------------------------------
+2.0.4:
+---------------------------------------------------------------------------
+
+General:
+* Added support for web applications using Emscripten, see docs/README-emscripten.md for more information
+* Added support for web applications using Native Client (NaCl), see docs/README-nacl.md for more information
+* Added an API to queue audio instead of using the audio callback:
+ SDL_QueueAudio(), SDL_GetQueuedAudioSize(), SDL_ClearQueuedAudio()
+* Added events for audio device hot plug support:
+ SDL_AUDIODEVICEADDED, SDL_AUDIODEVICEREMOVED
+* Added SDL_PointInRect()
+* Added SDL_HasAVX2() to detect CPUs with AVX2 support
+* Added SDL_SetWindowHitTest() to let apps treat parts of their SDL window like traditional window decorations (drag areas, resize areas)
+* Added SDL_GetGrabbedWindow() to get the window that currently has input grab, if any
+* Added SDL_RenderIsClipEnabled() to tell whether clipping is currently enabled in a renderer
+* Added SDL_CaptureMouse() to capture the mouse to get events while the mouse is not in your window
+* Added SDL_WarpMouseGlobal() to warp the mouse cursor in global screen space
+* Added SDL_GetGlobalMouseState() to get the current mouse state outside of an SDL window
+* Added a direction field to mouse wheel events to tell whether they are flipped (natural) or not
+* Added GL_CONTEXT_RELEASE_BEHAVIOR GL attribute (maps to [WGL|GLX]_ARB_context_flush_control extension)
+* Added EGL_KHR_create_context support to allow OpenGL ES version selection on some platforms
+* Added NV12 and NV21 YUV texture support for OpenGL and OpenGL ES 2.0 renderers
+* Added a Vivante video driver that is used on various SoC platforms
+* Added an event SDL_RENDER_DEVICE_RESET that is sent from the D3D renderers when the D3D device is lost, and from Android's event loop when the GLES context had to be recreated
+* Added a hint SDL_HINT_NO_SIGNAL_HANDLERS to disable SDL's built in signal handling
+* Added a hint SDL_HINT_THREAD_STACK_SIZE to set the stack size of SDL's threads
+* Added SDL_sqrtf(), SDL_tan(), and SDL_tanf() to the stdlib routines
+* Improved support for WAV and BMP files with unusual chunks in them
+* Renamed SDL_assert_data to SDL_AssertData and SDL_assert_state to SDL_AssertState
+* Added a hint SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN to prevent window interaction while cursor is hidden
+* Added SDL_GetDisplayDPI() to get the DPI information for a display
+* Added SDL_JoystickCurrentPowerLevel() to get the battery level of a joystick
+* Added SDL_JoystickFromInstanceID(), as a helper function, to get the SDL_Joystick* that an event is referring to.
+* Added SDL_GameControllerFromInstanceID(), as a helper function, to get the SDL_GameController* that an event is referring to.
+
+Windows:
+* Added support for Windows Phone 8.1 and Windows 10/UWP (Universal Windows Platform)
+* Timer resolution is now 1 ms by default, adjustable with the SDL_HINT_TIMER_RESOLUTION hint
+* SDLmain no longer depends on the C runtime, so you can use the same .lib in both Debug and Release builds
+* Added SDL_SetWindowsMessageHook() to set a function to be called for every windows message before TranslateMessage()
+* Added a hint SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP to control whether SDL_PumpEvents() processes the Windows message loop
+* You can distinguish between real mouse and touch events by looking for SDL_TOUCH_MOUSEID in the mouse event "which" field
+* SDL_SysWMinfo now contains the window HDC
+* Added support for Unicode command line options
+* Prevent beeping when Alt-key combos are pressed
+* SDL_SetTextInputRect() re-positions the OS-rendered IME
+* Added a hint SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 to prevent generating SDL_WINDOWEVENT_CLOSE events when Alt-F4 is pressed
+* Added a hint SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING to use the old axis and button mapping for XInput devices (deprecated)
+
+Mac OS X:
+* Implemented drag-and-drop support
+* Improved joystick hot-plug detection
+* The SDL_WINDOWEVENT_EXPOSED window event is triggered in the appropriate situations
+* Fixed relative mouse mode when the application loses/regains focus
+* Fixed bugs related to transitioning to and from Spaces-aware fullscreen-desktop mode
+* Fixed the refresh rate of display modes
+* SDL_SysWMInfo is now ARC-compatible
+* Added a hint SDL_HINT_MAC_BACKGROUND_APP to prevent forcing the application to become a foreground process
+
+Linux:
+* Enabled building with Mir and Wayland support by default.
+* Added IBus IME support
+* Added a hint SDL_HINT_IME_INTERNAL_EDITING to control whether IBus should handle text editing internally instead of sending SDL_TEXTEDITING events
+* Added a hint SDL_HINT_VIDEO_X11_NET_WM_PING to allow disabling _NET_WM_PING protocol handling in SDL_CreateWindow()
+* Added support for multiple audio devices when using Pulseaudio
+* Fixed duplicate mouse events when using relative mouse motion
+
+iOS:
+* Added support for iOS 8
+* The SDL_WINDOW_ALLOW_HIGHDPI window flag now enables high-dpi support, and SDL_GL_GetDrawableSize() or SDL_GetRendererOutputSize() gets the window resolution in pixels
+* SDL_GetWindowSize() and display mode sizes are in the "DPI-independent points" / "screen coordinates" coordinate space rather than pixels (matches OS X behavior)
+* Added native resolution support for the iPhone 6 Plus
+* Added support for MFi game controllers
+* Added support for the hint SDL_HINT_ACCELEROMETER_AS_JOYSTICK
+* Added sRGB OpenGL ES context support on iOS 7+
+* Added support for SDL_DisableScreenSaver(), SDL_EnableScreenSaver() and the hint SDL_HINT_VIDEO_ALLOW_SCREENSAVER
+* SDL_SysWMinfo now contains the OpenGL ES framebuffer and color renderbuffer objects used by the window's active GLES view
+* Fixed various rotation and orientation issues
+* Fixed memory leaks
+
+Android:
+* Added a hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH to prevent mouse events from being registered as touch events
+* Added hints SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION and SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION
+* Added support for SDL_DisableScreenSaver(), SDL_EnableScreenSaver() and the hint SDL_HINT_VIDEO_ALLOW_SCREENSAVER
+* Added support for SDL_ShowMessageBox() and SDL_ShowSimpleMessageBox()
+
+Raspberry Pi:
+* Added support for the Raspberry Pi 2
+
+
+---------------------------------------------------------------------------
+2.0.3:
+---------------------------------------------------------------------------
+
+Mac OS X:
+* Fixed creating an OpenGL context by default on Mac OS X 10.6
+
+
+---------------------------------------------------------------------------
+2.0.2:
+---------------------------------------------------------------------------
+General:
+* Added SDL_GL_ResetAttributes() to reset OpenGL attributes to default values
+* Added an API to load a database of game controller mappings from a file:
+ SDL_GameControllerAddMappingsFromFile(), SDL_GameControllerAddMappingsFromRW()
+* Added game controller mappings for the PS4 and OUYA controllers
+* Added SDL_GetDefaultAssertionHandler() and SDL_GetAssertionHandler()
+* Added SDL_DetachThread()
+* Added SDL_HasAVX() to determine if the CPU has AVX features
+* Added SDL_vsscanf(), SDL_acos(), and SDL_asin() to the stdlib routines
+* EGL can now create/manage OpenGL and OpenGL ES 1.x/2.x contexts, and share
+ them using SDL_GL_SHARE_WITH_CURRENT_CONTEXT
+* Added a field "clicks" to the mouse button event which records whether the event is a single click, double click, etc.
+* The screensaver is now disabled by default, and there is a hint SDL_HINT_VIDEO_ALLOW_SCREENSAVER that can change that behavior.
+* Added a hint SDL_HINT_MOUSE_RELATIVE_MODE_WARP to specify whether mouse relative mode should be emulated using mouse warping.
+* testgl2 does not need to link with libGL anymore
+* Added testgles2 test program to demonstrate working with OpenGL ES 2.0
+* Added controllermap test program to visually map a game controller
+
+Windows:
+* Support for OpenGL ES 2.x contexts using either WGL or EGL (natively via
+ the driver or emulated through ANGLE)
+* Added a hint SDL_HINT_VIDEO_WIN_D3DCOMPILER to specify which D3D shader compiler to use for OpenGL ES 2 support through ANGLE
+* Added a hint SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT that is useful when creating multiple windows that should share the same OpenGL context.
+* Added an event SDL_RENDER_TARGETS_RESET that is sent when D3D9 render targets are reset after the device has been restored.
+
+Mac OS X:
+* Added a hint SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK to control whether Ctrl+click should be treated as a right click on Mac OS X. This is off by default.
+
+Linux:
+* Fixed fullscreen and focused behavior when receiving NotifyGrab events
+* Added experimental Wayland and Mir support, disabled by default
+
+Android:
+* Joystick support (minimum SDK version required to build SDL is now 12,
+ the required runtime version remains at 10, but on such devices joystick
+ support won't be available).
+* Hotplugging support for joysticks
+* Added a hint SDL_HINT_ACCELEROMETER_AS_JOYSTICK to control whether the accelerometer should be listed as a 3 axis joystick, which it will by default.
+
+
+---------------------------------------------------------------------------
+2.0.1:
+---------------------------------------------------------------------------
+
+General:
+* Added an API to get common filesystem paths in SDL_filesystem.h:
+ SDL_GetBasePath(), SDL_GetPrefPath()
+* Added an API to do optimized YV12 and IYUV texture updates:
+ SDL_UpdateYUVTexture()
+* Added an API to get the amount of RAM on the system:
+ SDL_GetSystemRAM()
+* Added a macro to perform timestamp comparisons with SDL_GetTicks():
+ SDL_TICKS_PASSED()
+* Dramatically improved OpenGL ES 2.0 rendering performance
+* Added OpenGL attribute SDL_GL_FRAMEBUFFER_SRGB_CAPABLE
+
+Windows:
+* Created a static library configuration for the Visual Studio 2010 project
+* Added a hint to create the Direct3D device with support for multi-threading:
+ SDL_HINT_RENDER_DIRECT3D_THREADSAFE
+* Added a function to get the D3D9 adapter index for a display:
+ SDL_Direct3D9GetAdapterIndex()
+* Added a function to get the D3D9 device for a D3D9 renderer:
+ SDL_RenderGetD3D9Device()
+* Fixed building SDL with the mingw32 toolchain (mingw-w64 is preferred)
+* Fixed crash when using two XInput controllers at the same time
+* Fixed detecting a mixture of XInput and DirectInput controllers
+* Fixed clearing a D3D render target larger than the window
+* Improved support for format specifiers in SDL_snprintf()
+
+Mac OS X:
+* Added support for retina displays:
+ Create your window with the SDL_WINDOW_ALLOW_HIGHDPI flag, and then use SDL_GL_GetDrawableSize() to find the actual drawable size. You are responsible for scaling mouse and drawing coordinates appropriately.
+* Fixed mouse warping in fullscreen mode
+* Right mouse click is emulated by holding the Ctrl key while left clicking
+
+Linux:
+* Fixed float audio support with the PulseAudio driver
+* Fixed missing line endpoints in the OpenGL renderer on some drivers
+* X11 symbols are no longer defined to avoid collisions when linking statically
+
+iOS:
+* Fixed status bar visibility on iOS 7
+* Flipped the accelerometer Y axis to match expected values
+
+Android:
+IMPORTANT: You MUST get the updated SDLActivity.java to match C code
+* Moved EGL initialization to native code
+* Fixed the accelerometer axis rotation relative to the device rotation
+* Fixed race conditions when handling the EGL context on pause/resume
+* Touch devices are available for enumeration immediately after init
+
+Raspberry Pi:
+* Added support for the Raspberry Pi, see README-raspberrypi.txt for details
diff --git a/Client/ThirdParty/SDL2/begin_code.h b/Client/ThirdParty/SDL2/begin_code.h
new file mode 100644
index 0000000..37bf975
--- /dev/null
+++ b/Client/ThirdParty/SDL2/begin_code.h
@@ -0,0 +1,166 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file begin_code.h
+ *
+ * This file sets things up for C dynamic library function definitions,
+ * static inlined functions, and structures aligned at 4-byte alignment.
+ * If you don't like ugly C preprocessor code, don't look at this file. :)
+ */
+
+/* This shouldn't be nested -- included it around code only. */
+#ifdef _begin_code_h
+#error Nested inclusion of begin_code.h
+#endif
+#define _begin_code_h
+
+#ifndef SDL_DEPRECATED
+# if (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */
+# define SDL_DEPRECATED __attribute__((deprecated))
+# else
+# define SDL_DEPRECATED
+# endif
+#endif
+
+#ifndef SDL_UNUSED
+# ifdef __GNUC__
+# define SDL_UNUSED __attribute__((unused))
+# else
+# define SDL_UNUSED
+# endif
+#endif
+
+/* Some compilers use a special export keyword */
+#ifndef DECLSPEC
+# if defined(__WIN32__) || defined(__WINRT__) || defined(__CYGWIN__)
+# ifdef DLL_EXPORT
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC
+# endif
+# elif defined(__OS2__)
+# ifdef BUILD_SDL
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC
+# endif
+# else
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define DECLSPEC __attribute__ ((visibility("default")))
+# else
+# define DECLSPEC
+# endif
+# endif
+#endif
+
+/* By default SDL uses the C calling convention */
+#ifndef SDLCALL
+#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__)
+#define SDLCALL __cdecl
+#elif defined(__OS2__) || defined(__EMX__)
+#define SDLCALL _System
+# if defined (__GNUC__) && !defined(_System)
+# define _System /* for old EMX/GCC compat. */
+# endif
+#else
+#define SDLCALL
+#endif
+#endif /* SDLCALL */
+
+/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */
+#ifdef __SYMBIAN32__
+#undef DECLSPEC
+#define DECLSPEC
+#endif /* __SYMBIAN32__ */
+
+/* Force structure packing at 4 byte alignment.
+ This is necessary if the header is included in code which has structure
+ packing set to an alternate value, say for loading structures from disk.
+ The packing is reset to the previous value in close_code.h
+ */
+#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
+#ifdef _MSC_VER
+#pragma warning(disable: 4103)
+#endif
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpragma-pack"
+#endif
+#ifdef __BORLANDC__
+#pragma nopackwarning
+#endif
+#ifdef _M_X64
+/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
+#pragma pack(push,8)
+#else
+#pragma pack(push,4)
+#endif
+#endif /* Compiler needs structure packing set */
+
+#ifndef SDL_INLINE
+#if defined(__GNUC__)
+#define SDL_INLINE __inline__
+#elif defined(_MSC_VER) || defined(__BORLANDC__) || \
+ defined(__DMC__) || defined(__SC__) || \
+ defined(__WATCOMC__) || defined(__LCC__) || \
+ defined(__DECC) || defined(__CC_ARM)
+#define SDL_INLINE __inline
+#ifndef __inline__
+#define __inline__ __inline
+#endif
+#else
+#define SDL_INLINE inline
+#ifndef __inline__
+#define __inline__ inline
+#endif
+#endif
+#endif /* SDL_INLINE not defined */
+
+#ifndef SDL_FORCE_INLINE
+#if defined(_MSC_VER)
+#define SDL_FORCE_INLINE __forceinline
+#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
+#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__
+#else
+#define SDL_FORCE_INLINE static SDL_INLINE
+#endif
+#endif /* SDL_FORCE_INLINE not defined */
+
+#ifndef SDL_NORETURN
+#if defined(__GNUC__)
+#define SDL_NORETURN __attribute__((noreturn))
+#elif defined(_MSC_VER)
+#define SDL_NORETURN __declspec(noreturn)
+#else
+#define SDL_NORETURN
+#endif
+#endif /* SDL_NORETURN not defined */
+
+/* Apparently this is needed by several Windows compilers */
+#if !defined(__MACH__)
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif /* NULL */
+#endif /* ! Mac OS X - breaks precompiled headers */
diff --git a/Client/ThirdParty/SDL2/close_code.h b/Client/ThirdParty/SDL2/close_code.h
new file mode 100644
index 0000000..c65a216
--- /dev/null
+++ b/Client/ThirdParty/SDL2/close_code.h
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file close_code.h
+ *
+ * This file reverses the effects of begin_code.h and should be included
+ * after you finish any function and structure declarations in your headers
+ */
+
+#ifndef _begin_code_h
+#error close_code.h included without matching begin_code.h
+#endif
+#undef _begin_code_h
+
+/* Reset structure packing at previous byte alignment */
+#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
+#ifdef __BORLANDC__
+#pragma nopackwarning
+#endif
+#pragma pack(pop)
+#endif /* Compiler needs structure packing set */
diff --git a/Client/ThirdParty/SDL2/docs/README-android.md b/Client/ThirdParty/SDL2/docs/README-android.md
new file mode 100644
index 0000000..fb835a5
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-android.md
@@ -0,0 +1,472 @@
+Android
+================================================================================
+
+Matt Styles wrote a tutorial on building SDL for Android with Visual Studio:
+http://trederia.blogspot.de/2017/03/building-sdl2-for-android-with-visual.html
+
+The rest of this README covers the Android gradle style build process.
+
+If you are using the older ant build process, it is no longer officially
+supported, but you can use the "android-project-ant" directory as a template.
+
+
+Requirements
+================================================================================
+
+Android SDK (version 26 or later)
+https://developer.android.com/sdk/index.html
+
+Android NDK r15c or later
+https://developer.android.com/tools/sdk/ndk/index.html
+
+Minimum API level supported by SDL: 16 (Android 4.1)
+
+
+How the port works
+================================================================================
+
+- Android applications are Java-based, optionally with parts written in C
+- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to
+ the SDL library
+- This means that your application C code must be placed inside an Android
+ Java project, along with some C support code that communicates with Java
+- This eventually produces a standard Android .apk package
+
+The Android Java code implements an "Activity" and can be found in:
+android-project/app/src/main/java/org/libsdl/app/SDLActivity.java
+
+The Java code loads your game code, the SDL shared library, and
+dispatches to native functions implemented in the SDL library:
+src/core/android/SDL_android.c
+
+
+Building an app
+================================================================================
+
+For simple projects you can use the script located at build-scripts/androidbuild.sh
+
+There's two ways of using it:
+
+ androidbuild.sh com.yourcompany.yourapp < sources.list
+ androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c
+
+sources.list should be a text file with a source file name in each line
+Filenames should be specified relative to the current directory, for example if
+you are in the build-scripts directory and want to create the testgles.c test, you'll
+run:
+
+ ./androidbuild.sh org.libsdl.testgles ../test/testgles.c
+
+One limitation of this script is that all sources provided will be aggregated into
+a single directory, thus all your source files should have a unique name.
+
+Once the project is complete the script will tell you where the debug APK is located.
+If you want to create a signed release APK, you can use the project created by this
+utility to generate it.
+
+Finally, a word of caution: re running androidbuild.sh wipes any changes you may have
+done in the build directory for the app!
+
+
+For more complex projects, follow these instructions:
+
+1. Copy the android-project directory wherever you want to keep your projects
+ and rename it to the name of your project.
+2. Move or symlink this SDL directory into the "<project>/app/jni" directory
+3. Edit "<project>/app/jni/src/Android.mk" to include your source files
+
+4a. If you want to use Android Studio, simply open your <project> directory and start building.
+
+4b. If you want to build manually, run './gradlew installDebug' in the project directory. This compiles the .java, creates an .apk with the native code embedded, and installs it on any connected Android device
+
+
+If you already have a project that uses CMake, the instructions change somewhat:
+
+1. Do points 1 and 2 from the instruction above.
+2. Edit "<project>/app/build.gradle" to comment out or remove sections containing ndk-build
+ and uncomment the cmake sections. Add arguments to the CMake invocation as needed.
+3. Edit "<project>/app/jni/CMakeLists.txt" to include your project (it defaults to
+ adding the "src" subdirectory). Note that you'll have SDL2, SDL2main and SDL2-static
+ as targets in your project, so you should have "target_link_libraries(yourgame SDL2 SDL2main)"
+ in your CMakeLists.txt file. Also be aware that you should use add_library() instead of
+ add_executable() for the target containing your "main" function.
+
+If you wish to use Android Studio, you can skip the last step.
+
+4. Run './gradlew installDebug' or './gradlew installRelease' in the project directory. It will build and install your .apk on any
+ connected Android device
+
+Here's an explanation of the files in the Android project, so you can customize them:
+
+ android-project/app
+ build.gradle - build info including the application version and SDK
+ src/main/AndroidManifest.xml - package manifest. Among others, it contains the class name of the main Activity and the package name of the application.
+ jni/ - directory holding native code
+ jni/Application.mk - Application JNI settings, including target platform and STL library
+ jni/Android.mk - Android makefile that can call recursively the Android.mk files in all subdirectories
+ jni/CMakeLists.txt - Top-level CMake project that adds SDL as a subproject
+ jni/SDL/ - (symlink to) directory holding the SDL library files
+ jni/SDL/Android.mk - Android makefile for creating the SDL shared library
+ jni/src/ - directory holding your C/C++ source
+ jni/src/Android.mk - Android makefile that you should customize to include your source code and any library references
+ jni/src/CMakeLists.txt - CMake file that you may customize to include your source code and any library references
+ src/main/assets/ - directory holding asset files for your application
+ src/main/res/ - directory holding resources for your application
+ src/main/res/mipmap-* - directories holding icons for different phone hardware
+ src/main/res/values/strings.xml - strings used in your application, including the application name
+ src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application.
+
+
+Customizing your application name
+================================================================================
+
+To customize your application name, edit AndroidManifest.xml and replace
+"org.libsdl.app" with an identifier for your product package.
+
+Then create a Java class extending SDLActivity and place it in a directory
+under src matching your package, e.g.
+
+ src/com/gamemaker/game/MyGame.java
+
+Here's an example of a minimal class file:
+
+ --- MyGame.java --------------------------
+ package com.gamemaker.game;
+
+ import org.libsdl.app.SDLActivity;
+
+ /**
+ * A sample wrapper class that just calls SDLActivity
+ */
+
+ public class MyGame extends SDLActivity { }
+
+ ------------------------------------------
+
+Then replace "SDLActivity" in AndroidManifest.xml with the name of your
+class, .e.g. "MyGame"
+
+
+Customizing your application icon
+================================================================================
+
+Conceptually changing your icon is just replacing the "ic_launcher.png" files in
+the drawable directories under the res directory. There are several directories
+for different screen sizes.
+
+
+Loading assets
+================================================================================
+
+Any files you put in the "app/src/main/assets" directory of your project
+directory will get bundled into the application package and you can load
+them using the standard functions in SDL_rwops.h.
+
+There are also a few Android specific functions that allow you to get other
+useful paths for saving and loading data:
+* SDL_AndroidGetInternalStoragePath()
+* SDL_AndroidGetExternalStorageState()
+* SDL_AndroidGetExternalStoragePath()
+
+See SDL_system.h for more details on these functions.
+
+The asset packaging system will, by default, compress certain file extensions.
+SDL includes two asset file access mechanisms, the preferred one is the so
+called "File Descriptor" method, which is faster and doesn't involve the Dalvik
+GC, but given this method does not work on compressed assets, there is also the
+"Input Stream" method, which is automatically used as a fall back by SDL. You
+may want to keep this fact in mind when building your APK, specially when large
+files are involved.
+For more information on which extensions get compressed by default and how to
+disable this behaviour, see for example:
+
+http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/
+
+
+Pause / Resume behaviour
+================================================================================
+
+If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default),
+the event loop will block itself when the app is paused (ie, when the user
+returns to the main Android dashboard). Blocking is better in terms of battery
+use, and it allows your app to spring back to life instantaneously after resume
+(versus polling for a resume message).
+
+Upon resume, SDL will attempt to restore the GL context automatically.
+In modern devices (Android 3.0 and up) this will most likely succeed and your
+app can continue to operate as it was.
+
+However, there's a chance (on older hardware, or on systems under heavy load),
+where the GL context can not be restored. In that case you have to listen for
+a specific message (SDL_RENDER_DEVICE_RESET) and restore your textures
+manually or quit the app.
+
+You should not use the SDL renderer API while the app going in background:
+- SDL_APP_WILLENTERBACKGROUND:
+ after you read this message, GL context gets backed-up and you should not
+ use the SDL renderer API.
+
+- SDL_APP_DIDENTERFOREGROUND:
+ GL context is restored, and the SDL renderer API is available (unless you
+ receive SDL_RENDER_DEVICE_RESET).
+
+Mouse / Touch events
+================================================================================
+
+In some case, SDL generates synthetic mouse (resp. touch) events for touch
+(resp. mouse) devices.
+To enable/disable this behavior, see SDL_hints.h:
+- SDL_HINT_TOUCH_MOUSE_EVENTS
+- SDL_HINT_MOUSE_TOUCH_EVENTS
+
+Misc
+================================================================================
+
+For some device, it appears to works better setting explicitly GL attributes
+before creating a window:
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+
+Threads and the Java VM
+================================================================================
+
+For a quick tour on how Linux native threads interoperate with the Java VM, take
+a look here: https://developer.android.com/guide/practices/jni.html
+
+If you want to use threads in your SDL app, it's strongly recommended that you
+do so by creating them using SDL functions. This way, the required attach/detach
+handling is managed by SDL automagically. If you have threads created by other
+means and they make calls to SDL functions, make sure that you call
+Android_JNI_SetupThread() before doing anything else otherwise SDL will attach
+your thread automatically anyway (when you make an SDL call), but it'll never
+detach it.
+
+
+If you ever want to use JNI in a native thread (created by "SDL_CreateThread()"),
+it won't be able to find your java class and method because of the java class loader
+which is different for native threads, than for java threads (eg your "main()").
+
+the work-around is to find class/method, in you "main()" thread, and to use them
+in your native thread.
+
+see:
+https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class
+
+Using STL
+================================================================================
+
+You can use STL in your project by creating an Application.mk file in the jni
+folder and adding the following line:
+
+ APP_STL := c++_shared
+
+For more information go here:
+ https://developer.android.com/ndk/guides/cpp-support
+
+
+Using the emulator
+================================================================================
+
+There are some good tips and tricks for getting the most out of the
+emulator here: https://developer.android.com/tools/devices/emulator.html
+
+Especially useful is the info on setting up OpenGL ES 2.0 emulation.
+
+Notice that this software emulator is incredibly slow and needs a lot of disk space.
+Using a real device works better.
+
+
+Troubleshooting
+================================================================================
+
+You can see if adb can see any devices with the following command:
+
+ adb devices
+
+You can see the output of log messages on the default device with:
+
+ adb logcat
+
+You can push files to the device with:
+
+ adb push local_file remote_path_and_file
+
+You can push files to the SD Card at /sdcard, for example:
+
+ adb push moose.dat /sdcard/moose.dat
+
+You can see the files on the SD card with a shell command:
+
+ adb shell ls /sdcard/
+
+You can start a command shell on the default device with:
+
+ adb shell
+
+You can remove the library files of your project (and not the SDL lib files) with:
+
+ ndk-build clean
+
+You can do a build with the following command:
+
+ ndk-build
+
+You can see the complete command line that ndk-build is using by passing V=1 on the command line:
+
+ ndk-build V=1
+
+If your application crashes in native code, you can use ndk-stack to get a symbolic stack trace:
+ https://developer.android.com/ndk/guides/ndk-stack
+
+If you want to go through the process manually, you can use addr2line to convert the
+addresses in the stack trace to lines in your code.
+
+For example, if your crash looks like this:
+
+ I/DEBUG ( 31): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 400085d0
+ I/DEBUG ( 31): r0 00000000 r1 00001000 r2 00000003 r3 400085d4
+ I/DEBUG ( 31): r4 400085d0 r5 40008000 r6 afd41504 r7 436c6a7c
+ I/DEBUG ( 31): r8 436c6b30 r9 435c6fb0 10 435c6f9c fp 4168d82c
+ I/DEBUG ( 31): ip 8346aff0 sp 436c6a60 lr afd1c8ff pc afd1c902 cpsr 60000030
+ I/DEBUG ( 31): #00 pc 0001c902 /system/lib/libc.so
+ I/DEBUG ( 31): #01 pc 0001ccf6 /system/lib/libc.so
+ I/DEBUG ( 31): #02 pc 000014bc /data/data/org.libsdl.app/lib/libmain.so
+ I/DEBUG ( 31): #03 pc 00001506 /data/data/org.libsdl.app/lib/libmain.so
+
+You can see that there's a crash in the C library being called from the main code.
+I run addr2line with the debug version of my code:
+
+ arm-eabi-addr2line -C -f -e obj/local/armeabi/libmain.so
+
+and then paste in the number after "pc" in the call stack, from the line that I care about:
+000014bc
+
+I get output from addr2line showing that it's in the quit function, in testspriteminimal.c, on line 23.
+
+You can add logging to your code to help show what's happening:
+
+ #include <android/log.h>
+
+ __android_log_print(ANDROID_LOG_INFO, "foo", "Something happened! x = %d", x);
+
+If you need to build without optimization turned on, you can create a file called
+"Application.mk" in the jni directory, with the following line in it:
+
+ APP_OPTIM := debug
+
+
+Memory debugging
+================================================================================
+
+The best (and slowest) way to debug memory issues on Android is valgrind.
+Valgrind has support for Android out of the box, just grab code using:
+
+ svn co svn://svn.valgrind.org/valgrind/trunk valgrind
+
+... and follow the instructions in the file README.android to build it.
+
+One thing I needed to do on Mac OS X was change the path to the toolchain,
+and add ranlib to the environment variables:
+export RANLIB=$NDKROOT/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-ranlib
+
+Once valgrind is built, you can create a wrapper script to launch your
+application with it, changing org.libsdl.app to your package identifier:
+
+ --- start_valgrind_app -------------------
+ #!/system/bin/sh
+ export TMPDIR=/data/data/org.libsdl.app
+ exec /data/local/Inst/bin/valgrind --log-file=/sdcard/valgrind.log --error-limit=no $*
+ ------------------------------------------
+
+Then push it to the device:
+
+ adb push start_valgrind_app /data/local
+
+and make it executable:
+
+ adb shell chmod 755 /data/local/start_valgrind_app
+
+and tell Android to use the script to launch your application:
+
+ adb shell setprop wrap.org.libsdl.app "logwrapper /data/local/start_valgrind_app"
+
+If the setprop command says "could not set property", it's likely that
+your package name is too long and you should make it shorter by changing
+AndroidManifest.xml and the path to your class file in android-project/src
+
+You can then launch your application normally and waaaaaaaiiittt for it.
+You can monitor the startup process with the logcat command above, and
+when it's done (or even while it's running) you can grab the valgrind
+output file:
+
+ adb pull /sdcard/valgrind.log
+
+When you're done instrumenting with valgrind, you can disable the wrapper:
+
+ adb shell setprop wrap.org.libsdl.app ""
+
+
+Graphics debugging
+================================================================================
+
+If you are developing on a compatible Tegra-based tablet, NVidia provides
+Tegra Graphics Debugger at their website. Because SDL2 dynamically loads EGL
+and GLES libraries, you must follow their instructions for installing the
+interposer library on a rooted device. The non-rooted instructions are not
+compatible with applications that use SDL2 for video.
+
+The Tegra Graphics Debugger is available from NVidia here:
+https://developer.nvidia.com/tegra-graphics-debugger
+
+
+Why is API level 16 the minimum required?
+================================================================================
+
+The latest NDK toolchain doesn't support targeting earlier than API level 16.
+As of this writing, according to https://developer.android.com/about/dashboards/index.html
+about 99% of the Android devices accessing Google Play support API level 16 or
+higher (January 2018).
+
+
+A note regarding the use of the "dirty rectangles" rendering technique
+================================================================================
+
+If your app uses a variation of the "dirty rectangles" rendering technique,
+where you only update a portion of the screen on each frame, you may notice a
+variety of visual glitches on Android, that are not present on other platforms.
+This is caused by SDL's use of EGL as the support system to handle OpenGL ES/ES2
+contexts, in particular the use of the eglSwapBuffers function. As stated in the
+documentation for the function "The contents of ancillary buffers are always
+undefined after calling eglSwapBuffers".
+Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED
+is not possible for SDL as it requires EGL 1.4, available only on the API level
+17+, so the only workaround available on this platform is to redraw the entire
+screen each frame.
+
+Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html
+
+
+Ending your application
+================================================================================
+
+Two legitimate ways:
+
+- return from your main() function. Java side will automatically terminate the
+Activity by calling Activity.finish().
+
+- Android OS can decide to terminate your application by calling onDestroy()
+(see Activity life cycle). Your application will receive a SDL_QUIT event you
+can handle to save things and quit.
+
+Don't call exit() as it stops the activity badly.
+
+NB: "Back button" can be handled as a SDL_KEYDOWN/UP events, with Keycode
+SDLK_AC_BACK, for any purpose.
+
+Known issues
+================================================================================
+
+- The number of buttons reported for each joystick is hardcoded to be 36, which
+is the current maximum number of buttons Android can report.
+
diff --git a/Client/ThirdParty/SDL2/docs/README-cmake.md b/Client/ThirdParty/SDL2/docs/README-cmake.md
new file mode 100644
index 0000000..0eeb6d7
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-cmake.md
@@ -0,0 +1,84 @@
+CMake
+================================================================================
+(www.cmake.org)
+
+SDL's build system was traditionally based on autotools. Over time, this
+approach has suffered from several issues across the different supported
+platforms.
+To solve these problems, a new build system based on CMake is under development.
+It works in parallel to the legacy system, so users can experiment with it
+without complication.
+While still experimental, the build system should be usable on the following
+platforms:
+
+* FreeBSD
+* Linux
+* VS.NET 2010
+* MinGW and Msys
+* macOS, iOS, and tvOS, with support for XCode
+
+
+================================================================================
+Usage
+================================================================================
+
+Assuming the source for SDL is located at ~/sdl
+
+ cd ~
+ mkdir build
+ cd build
+ cmake ../sdl
+
+This will build the static and dynamic versions of SDL in the ~/build directory.
+
+
+================================================================================
+Usage, iOS/tvOS
+================================================================================
+
+CMake 3.14+ natively includes support for iOS and tvOS. SDL binaries may be built
+using Xcode or Make, possibly among other build-systems.
+
+When using a recent version of CMake (3.14+), it should be possible to:
+
+- build SDL for iOS, both static and dynamic
+- build SDL test apps (as iOS/tvOS .app bundles)
+- generate a working SDL_config.h for iOS (using SDL_config.h.cmake as a basis)
+
+To use, set the following CMake variables when running CMake's configuration stage:
+
+- `CMAKE_SYSTEM_NAME=<OS>` (either `iOS` or `tvOS`)
+- `CMAKE_OSX_SYSROOT=<SDK>` (examples: `iphoneos`, `iphonesimulator`, `iphoneos12.4`, `/full/path/to/iPhoneOS.sdk`,
+ `appletvos`, `appletvsimulator`, `appletvos12.4`, `/full/path/to/AppleTVOS.sdk`, etc.)
+- `CMAKE_OSX_ARCHITECTURES=<semicolon-separated list of CPU architectures>` (example: "arm64;armv7s;x86_64")
+
+
+### Examples (for iOS/tvOS):
+
+- for iOS-Simulator, using the latest, installed SDK:
+
+ `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64`
+
+- for iOS-Device, using the latest, installed SDK, 64-bit only
+
+ `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES=arm64`
+
+- for iOS-Device, using the latest, installed SDK, mixed 32/64 bit
+
+ `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_ARCHITECTURES="arm64;armv7s"`
+
+- for iOS-Device, using a specific SDK revision (iOS 12.4, in this example):
+
+ `cmake ~/sdl -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos12.4 -DCMAKE_OSX_ARCHITECTURES=arm64`
+
+- for iOS-Simulator, using the latest, installed SDK, and building SDL test apps (as .app bundles):
+
+ `cmake ~/sdl -DSDL_TEST=1 -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_ARCHITECTURES=x86_64`
+
+- for tvOS-Simulator, using the latest, installed SDK:
+
+ `cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvsimulator -DCMAKE_OSX_ARCHITECTURES=x86_64`
+
+- for tvOS-Device, using the latest, installed SDK:
+
+ `cmake ~/sdl -DCMAKE_SYSTEM_NAME=tvOS -DCMAKE_OSX_SYSROOT=appletvos -DCMAKE_OSX_ARCHITECTURES=arm64`
diff --git a/Client/ThirdParty/SDL2/docs/README-directfb.md b/Client/ThirdParty/SDL2/docs/README-directfb.md
new file mode 100644
index 0000000..67b64fb
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-directfb.md
@@ -0,0 +1,107 @@
+DirectFB
+========
+
+Supports:
+
+- Hardware YUV overlays
+- OpenGL - software only
+- 2D/3D accelerations (depends on directfb driver)
+- multiple displays
+- windows
+
+What you need:
+
+* DirectFB 1.0.1, 1.2.x, 1.3.0
+* Kernel-Framebuffer support: required: vesafb, radeonfb ....
+* Mesa 7.0.x - optional for OpenGL
+
+/etc/directfbrc
+
+This file should contain the following lines to make
+your joystick work and avoid crashes:
+------------------------
+disable-module=joystick
+disable-module=cle266
+disable-module=cyber5k
+no-linux-input-grab
+------------------------
+
+To disable to use x11 backend when DISPLAY variable is found use
+
+export SDL_DIRECTFB_X11_CHECK=0
+
+To disable the use of linux input devices, i.e. multimice/multikeyboard support,
+use
+
+export SDL_DIRECTFB_LINUX_INPUT=0
+
+To use hardware accelerated YUV-overlays for YUV-textures, use:
+
+export SDL_DIRECTFB_YUV_DIRECT=1
+
+This is disabled by default. It will only support one
+YUV texture, namely the first. Every other YUV texture will be
+rendered in software.
+
+In addition, you may use (directfb-1.2.x)
+
+export SDL_DIRECTFB_YUV_UNDERLAY=1
+
+to make the YUV texture an underlay. This will make the cursor to
+be shown.
+
+Simple Window Manager
+=====================
+
+The driver has support for a very, very basic window manager you may
+want to use when running with "wm=default". Use
+
+export SDL_DIRECTFB_WM=1
+
+to enable basic window borders. In order to have the window title rendered,
+you need to have the following font installed:
+
+/usr/share/fonts/truetype/freefont/FreeSans.ttf
+
+OpenGL Support
+==============
+
+The following instructions will give you *software* OpenGL. However this
+works at least on all directfb supported platforms.
+
+As of this writing 20100802 you need to pull Mesa from git and do the following:
+
+------------------------
+git clone git://anongit.freedesktop.org/git/mesa/mesa
+cd mesa
+git checkout 2c9fdaf7292423c157fc79b5ce43f0f199dd753a
+------------------------
+
+Edit configs/linux-directfb so that the Directories-section looks like
+------------------------
+# Directories
+SRC_DIRS = mesa glu
+GLU_DIRS = sgi
+DRIVER_DIRS = directfb
+PROGRAM_DIRS =
+------------------------
+
+make linux-directfb
+make
+
+echo Installing - please enter sudo pw.
+
+sudo make install INSTALL_DIR=/usr/local/dfb_GL
+cd src/mesa/drivers/directfb
+make
+sudo make install INSTALL_DIR=/usr/local/dfb_GL
+------------------------
+
+To run the SDL - testprograms:
+
+export SDL_VIDEODRIVER=directfb
+export LD_LIBRARY_PATH=/usr/local/dfb_GL/lib
+export LD_PRELOAD=/usr/local/dfb_GL/libGL.so.7
+
+./testgl
+
diff --git a/Client/ThirdParty/SDL2/docs/README-dynapi.md b/Client/ThirdParty/SDL2/docs/README-dynapi.md
new file mode 100644
index 0000000..7827458
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-dynapi.md
@@ -0,0 +1,138 @@
+# Dynamic API
+
+Originally posted on Ryan's Google+ account.
+
+Background:
+
+- The Steam Runtime has (at least in theory) a really kick-ass build of SDL2,
+ but developers are shipping their own SDL2 with individual Steam games.
+ These games might stop getting updates, but a newer SDL2 might be needed later.
+ Certainly we'll always be fixing bugs in SDL, even if a new video target isn't
+ ever needed, and these fixes won't make it to a game shipping its own SDL.
+- Even if we replace the SDL2 in those games with a compatible one, that is to
+ say, edit a developer's Steam depot (yuck!), there are developers that are
+ statically linking SDL2 that we can't do this for. We can't even force the
+ dynamic loader to ignore their SDL2 in this case, of course.
+- If you don't ship an SDL2 with the game in some form, people that disabled the
+ Steam Runtime, or just tried to run the game from the command line instead of
+ Steam might find themselves unable to run the game, due to a missing dependency.
+- If you want to ship on non-Steam platforms like GOG or Humble Bundle, or target
+ generic Linux boxes that may or may not have SDL2 installed, you have to ship
+ the library or risk a total failure to launch. So now, you might have to have
+ a non-Steam build plus a Steam build (that is, one with and one without SDL2
+ included), which is inconvenient if you could have had one universal build
+ that works everywhere.
+- We like the zlib license, but the biggest complaint from the open source
+ community about the license change is the static linking. The LGPL forced this
+ as a legal, not technical issue, but zlib doesn't care. Even those that aren't
+ concerned about the GNU freedoms found themselves solving the same problems:
+ swapping in a newer SDL to an older game often times can save the day.
+ Static linking stops this dead.
+
+So here's what we did:
+
+SDL now has, internally, a table of function pointers. So, this is what SDL_Init
+now looks like:
+
+```c
+UInt32 SDL_Init(Uint32 flags)
+{
+ return jump_table.SDL_Init(flags);
+}
+```
+
+Except that is all done with a bunch of macro magic so we don't have to maintain
+every one of these.
+
+What is jump_table.SDL_init()? Eventually, that's a function pointer of the real
+SDL_Init() that you've been calling all this time. But at startup, it looks more
+like this:
+
+```c
+Uint32 SDL_Init_DEFAULT(Uint32 flags)
+{
+ SDL_InitDynamicAPI();
+ return jump_table.SDL_Init(flags);
+}
+```
+
+SDL_InitDynamicAPI() fills in jump_table with all the actual SDL function
+pointers, which means that this `_DEFAULT` function never gets called again.
+First call to any SDL function sets the whole thing up.
+
+So you might be asking, what was the value in that? Isn't this what the operating
+system's dynamic loader was supposed to do for us? Yes, but now we've got this
+level of indirection, we can do things like this:
+
+```bash
+export SDL_DYNAMIC_API=/my/actual/libSDL-2.0.so.0
+./MyGameThatIsStaticallyLinkedToSDL2
+```
+
+And now, this game that is statically linked to SDL, can still be overridden
+with a newer, or better, SDL. The statically linked one will only be used as
+far as calling into the jump table in this case. But in cases where no override
+is desired, the statically linked version will provide its own jump table,
+and everyone is happy.
+
+So now:
+- Developers can statically link SDL, and users can still replace it.
+ (We'd still rather you ship a shared library, though!)
+- Developers can ship an SDL with their game, Valve can override it for, say,
+ new features on SteamOS, or distros can override it for their own needs,
+ but it'll also just work in the default case.
+- Developers can ship the same package to everyone (Humble Bundle, GOG, etc),
+ and it'll do the right thing.
+- End users (and Valve) can update a game's SDL in almost any case,
+ to keep abandoned games running on newer platforms.
+- Everyone develops with SDL exactly as they have been doing all along.
+ Same headers, same ABI. Just get the latest version to enable this magic.
+
+
+A little more about SDL_InitDynamicAPI():
+
+Internally, InitAPI does some locking to make sure everything waits until a
+single thread initializes everything (although even SDL_CreateThread() goes
+through here before spinning a thread, too), and then decides if it should use
+an external SDL library. If not, it sets up the jump table using the current
+SDL's function pointers (which might be statically linked into a program, or in
+a shared library of its own). If so, it loads that library and looks for and
+calls a single function:
+
+```c
+SInt32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize);
+```
+
+That function takes a version number (more on that in a moment), the address of
+the jump table, and the size, in bytes, of the table.
+Now, we've got policy here: this table's layout never changes; new stuff gets
+added to the end. Therefore SDL_DYNAPI_entry() knows that it can provide all
+the needed functions if tablesize <= sizeof its own jump table. If tablesize is
+bigger (say, SDL 2.0.4 is trying to load SDL 2.0.3), then we know to abort, but
+if it's smaller, we know we can provide the entire API that the caller needs.
+
+The version variable is a failsafe switch.
+Right now it's always 1. This number changes when there are major API changes
+(so we know if the tablesize might be smaller, or entries in it have changed).
+Right now SDL_DYNAPI_entry gives up if the version doesn't match, but it's not
+inconceivable to have a small dispatch library that only supplies this one
+function and loads different, otherwise-incompatible SDL libraries and has the
+right one initialize the jump table based on the version. For something that
+must generically catch lots of different versions of SDL over time, like the
+Steam Client, this isn't a bad option.
+
+Finally, I'm sure some people are reading this and thinking,
+"I don't want that overhead in my project!"
+
+To which I would point out that the extra function call through the jump table
+probably wouldn't even show up in a profile, but lucky you: this can all be
+disabled. You can build SDL without this if you absolutely must, but we would
+encourage you not to do that. However, on heavily locked down platforms like
+iOS, or maybe when debugging, it makes sense to disable it. The way this is
+designed in SDL, you just have to change one #define, and the entire system
+vaporizes out, and SDL functions exactly like it always did. Most of it is
+macro magic, so the system is contained to one C file and a few headers.
+However, this is on by default and you have to edit a header file to turn it
+off. Our hopes is that if we make it easy to disable, but not too easy,
+everyone will ultimately be able to get what they want, but we've gently
+nudged everyone towards what we think is the best solution.
diff --git a/Client/ThirdParty/SDL2/docs/README-emscripten.md b/Client/ThirdParty/SDL2/docs/README-emscripten.md
new file mode 100644
index 0000000..9712084
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-emscripten.md
@@ -0,0 +1,35 @@
+Emscripten
+================================================================================
+
+Build:
+
+ $ mkdir build
+ $ cd build
+ $ emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --disable-cpuinfo CFLAGS="-O2"
+ $ emmake make
+
+Or with cmake:
+
+ $ mkdir build
+ $ cd build
+ $ emcmake cmake ..
+ $ emmake make
+
+To build one of the tests:
+
+ $ cd test/
+ $ emcc -O2 --js-opts 0 -g4 testdraw2.c -I../include ../build/.libs/libSDL2.a ../build/libSDL2_test.a -o a.html
+
+Uses GLES2 renderer or software
+
+Some other SDL2 libraries can be easily built (assuming SDL2 is installed somewhere):
+
+SDL_mixer (http://www.libsdl.org/projects/SDL_mixer/):
+
+ $ EMCONFIGURE_JS=1 emconfigure ../configure
+ build as usual...
+
+SDL_gfx (http://cms.ferzkopp.net/index.php/software/13-sdl-gfx):
+
+ $ EMCONFIGURE_JS=1 emconfigure ../configure --disable-mmx
+ build as usual...
diff --git a/Client/ThirdParty/SDL2/docs/README-gesture.md b/Client/ThirdParty/SDL2/docs/README-gesture.md
new file mode 100644
index 0000000..451afae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-gesture.md
@@ -0,0 +1,71 @@
+Dollar Gestures
+===========================================================================
+SDL provides an implementation of the $1 gesture recognition system. This allows for recording, saving, loading, and performing single stroke gestures.
+
+Gestures can be performed with any number of fingers (the centroid of the fingers must follow the path of the gesture), but the number of fingers must be constant (a finger cannot go down in the middle of a gesture). The path of a gesture is considered the path from the time when the final finger went down, to the first time any finger comes up.
+
+Dollar gestures are assigned an Id based on a hash function. This is guaranteed to remain constant for a given gesture. There is a (small) chance that two different gestures will be assigned the same ID. In this case, simply re-recording one of the gestures should result in a different ID.
+
+Recording:
+----------
+To begin recording on a touch device call:
+SDL_RecordGesture(SDL_TouchID touchId), where touchId is the id of the touch device you wish to record on, or -1 to record on all connected devices.
+
+Recording terminates as soon as a finger comes up. Recording is acknowledged by an SDL_DOLLARRECORD event.
+A SDL_DOLLARRECORD event is a dgesture with the following fields:
+
+* event.dgesture.touchId - the Id of the touch used to record the gesture.
+* event.dgesture.gestureId - the unique id of the recorded gesture.
+
+
+Performing:
+-----------
+As long as there is a dollar gesture assigned to a touch, every finger-up event will also cause an SDL_DOLLARGESTURE event with the following fields:
+
+* event.dgesture.touchId - the Id of the touch which performed the gesture.
+* event.dgesture.gestureId - the unique id of the closest gesture to the performed stroke.
+* event.dgesture.error - the difference between the gesture template and the actual performed gesture. Lower error is a better match.
+* event.dgesture.numFingers - the number of fingers used to draw the stroke.
+
+Most programs will want to define an appropriate error threshold and check to be sure that the error of a gesture is not abnormally high (an indicator that no gesture was performed).
+
+
+
+Saving:
+-------
+To save a template, call SDL_SaveDollarTemplate(gestureId, dst) where gestureId is the id of the gesture you want to save, and dst is an SDL_RWops pointer to the file where the gesture will be stored.
+
+To save all currently loaded templates, call SDL_SaveAllDollarTemplates(dst) where dst is an SDL_RWops pointer to the file where the gesture will be stored.
+
+Both functions return the number of gestures successfully saved.
+
+
+Loading:
+--------
+To load templates from a file, call SDL_LoadDollarTemplates(touchId,src) where touchId is the id of the touch to load to (or -1 to load to all touch devices), and src is an SDL_RWops pointer to a gesture save file.
+
+SDL_LoadDollarTemplates returns the number of templates successfully loaded.
+
+
+
+===========================================================================
+Multi Gestures
+===========================================================================
+SDL provides simple support for pinch/rotate/swipe gestures.
+Every time a finger is moved an SDL_MULTIGESTURE event is sent with the following fields:
+
+* event.mgesture.touchId - the Id of the touch on which the gesture was performed.
+* event.mgesture.x - the normalized x coordinate of the gesture. (0..1)
+* event.mgesture.y - the normalized y coordinate of the gesture. (0..1)
+* event.mgesture.dTheta - the amount that the fingers rotated during this motion.
+* event.mgesture.dDist - the amount that the fingers pinched during this motion.
+* event.mgesture.numFingers - the number of fingers used in the gesture.
+
+
+===========================================================================
+Notes
+===========================================================================
+For a complete example see test/testgesture.c
+
+Please direct questions/comments to:
+ jim.tla+sdl_touch@gmail.com
diff --git a/Client/ThirdParty/SDL2/docs/README-git.md b/Client/ThirdParty/SDL2/docs/README-git.md
new file mode 100644
index 0000000..3f03488
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-git.md
@@ -0,0 +1,19 @@
+git
+=========
+
+The latest development version of SDL is available via git.
+Git allows you to get up-to-the-minute fixes and enhancements;
+as a developer works on a source tree, you can use "git" to mirror that
+source tree instead of waiting for an official release. Please look
+at the Git website ( https://git-scm.com/ ) for more
+information on using git, where you can also download software for
+macOS, Windows, and Unix systems.
+
+ git clone https://github.com/libsdl-org/SDL
+
+If you are building SDL via configure, you will need to run autogen.sh
+before running configure.
+
+There is a web interface to the Git repository at:
+ http://github.com/libsdl-org/SDL/
+
diff --git a/Client/ThirdParty/SDL2/docs/README-hg.md b/Client/ThirdParty/SDL2/docs/README-hg.md
new file mode 100644
index 0000000..4e35683
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-hg.md
@@ -0,0 +1,4 @@
+We are no longer hosted in Mercurial. Please see README-git.md for details.
+
+Thanks!
+
diff --git a/Client/ThirdParty/SDL2/docs/README-ios.md b/Client/ThirdParty/SDL2/docs/README-ios.md
new file mode 100644
index 0000000..cab3af4
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-ios.md
@@ -0,0 +1,295 @@
+iOS
+======
+
+Building the Simple DirectMedia Layer for iOS 5.1+
+==============================================================================
+
+Requirements: Mac OS X 10.8 or later and the iOS 7+ SDK.
+
+Instructions:
+
+1. Open SDL.xcodeproj (located in Xcode/SDL) in Xcode.
+2. Select your desired target, and hit build.
+
+There are three build targets:
+- libSDL.a:
+ Build SDL as a statically linked library
+- testsdl:
+ Build a test program (there are known test failures which are fine)
+- Template:
+ Package a project template together with the SDL for iPhone static libraries and copies of the SDL headers. The template includes proper references to the SDL library and headers, skeleton code for a basic SDL program, and placeholder graphics for the application icon and startup screen.
+
+
+Build SDL for iOS from the command line
+==============================================================================
+
+1. cd (PATH WHERE THE SDL CODE IS)/build-scripts
+2. ./iosbuild.sh
+
+If everything goes fine, you should see a build/ios directory, inside there's
+two directories "lib" and "include".
+"include" contains a copy of the SDL headers that you'll need for your project,
+make sure to configure XCode to look for headers there.
+"lib" contains find two files, libSDL2.a and libSDL2main.a, you have to add both
+to your XCode project. These libraries contain three architectures in them,
+armv6 for legacy devices, armv7, and i386 (for the simulator).
+By default, iosbuild.sh will autodetect the SDK version you have installed using
+xcodebuild -showsdks, and build for iOS >= 3.0, you can override this behaviour
+by setting the MIN_OS_VERSION variable, ie:
+
+MIN_OS_VERSION=4.2 ./iosbuild.sh
+
+Using the Simple DirectMedia Layer for iOS
+==============================================================================
+
+FIXME: This needs to be updated for the latest methods
+
+Here is the easiest method:
+1. Build the SDL library (libSDL2.a) and the iPhone SDL Application template.
+2. Install the iPhone SDL Application template by copying it to one of Xcode's template directories. I recommend creating a directory called "SDL" in "/Developer/Platforms/iOS.platform/Developer/Library/Xcode/Project Templates/" and placing it there.
+3. Start a new project using the template. The project should be immediately ready for use with SDL.
+
+Here is a more manual method:
+1. Create a new iOS view based application.
+2. Build the SDL static library (libSDL2.a) for iOS and include them in your project. Xcode will ignore the library that is not currently of the correct architecture, hence your app will work both on iOS and in the iOS Simulator.
+3. Include the SDL header files in your project.
+4. Remove the ApplicationDelegate.h and ApplicationDelegate.m files -- SDL for iOS provides its own UIApplicationDelegate. Remove MainWindow.xib -- SDL for iOS produces its user interface programmatically.
+5. Delete the contents of main.m and program your app as a regular SDL program instead. You may replace main.m with your own main.c, but you must tell Xcode not to use the project prefix file, as it includes Objective-C code.
+
+
+Notes -- Retina / High-DPI and window sizes
+==============================================================================
+
+Window and display mode sizes in SDL are in "screen coordinates" (or "points",
+in Apple's terminology) rather than in pixels. On iOS this means that a window
+created on an iPhone 6 will have a size in screen coordinates of 375 x 667,
+rather than a size in pixels of 750 x 1334. All iOS apps are expected to
+size their content based on screen coordinates / points rather than pixels,
+as this allows different iOS devices to have different pixel densities
+(Retina versus non-Retina screens, etc.) without apps caring too much.
+
+By default SDL will not use the full pixel density of the screen on
+Retina/high-dpi capable devices. Use the SDL_WINDOW_ALLOW_HIGHDPI flag when
+creating your window to enable high-dpi support.
+
+When high-dpi support is enabled, SDL_GetWindowSize() and display mode sizes
+will still be in "screen coordinates" rather than pixels, but the window will
+have a much greater pixel density when the device supports it, and the
+SDL_GL_GetDrawableSize() or SDL_GetRendererOutputSize() functions (depending on
+whether raw OpenGL or the SDL_Render API is used) can be queried to determine
+the size in pixels of the drawable screen framebuffer.
+
+Some OpenGL ES functions such as glViewport expect sizes in pixels rather than
+sizes in screen coordinates. When doing 2D rendering with OpenGL ES, an
+orthographic projection matrix using the size in screen coordinates
+(SDL_GetWindowSize()) can be used in order to display content at the same scale
+no matter whether a Retina device is used or not.
+
+
+Notes -- Application events
+==============================================================================
+
+On iOS the application goes through a fixed life cycle and you will get
+notifications of state changes via application events. When these events
+are delivered you must handle them in an event callback because the OS may
+not give you any processing time after the events are delivered.
+
+e.g.
+
+ int HandleAppEvents(void *userdata, SDL_Event *event)
+ {
+ switch (event->type)
+ {
+ case SDL_APP_TERMINATING:
+ /* Terminate the app.
+ Shut everything down before returning from this function.
+ */
+ return 0;
+ case SDL_APP_LOWMEMORY:
+ /* You will get this when your app is paused and iOS wants more memory.
+ Release as much memory as possible.
+ */
+ return 0;
+ case SDL_APP_WILLENTERBACKGROUND:
+ /* Prepare your app to go into the background. Stop loops, etc.
+ This gets called when the user hits the home button, or gets a call.
+ */
+ return 0;
+ case SDL_APP_DIDENTERBACKGROUND:
+ /* This will get called if the user accepted whatever sent your app to the background.
+ If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops.
+ When you get this, you have 5 seconds to save all your state or the app will be terminated.
+ Your app is NOT active at this point.
+ */
+ return 0;
+ case SDL_APP_WILLENTERFOREGROUND:
+ /* This call happens when your app is coming back to the foreground.
+ Restore all your state here.
+ */
+ return 0;
+ case SDL_APP_DIDENTERFOREGROUND:
+ /* Restart your loops here.
+ Your app is interactive and getting CPU again.
+ */
+ return 0;
+ default:
+ /* No special processing, add it to the event queue */
+ return 1;
+ }
+ }
+
+ int main(int argc, char *argv[])
+ {
+ SDL_SetEventFilter(HandleAppEvents, NULL);
+
+ ... run your main loop
+
+ return 0;
+ }
+
+
+Notes -- Accelerometer as Joystick
+==============================================================================
+
+SDL for iPhone supports polling the built in accelerometer as a joystick device. For an example on how to do this, see the accelerometer.c in the demos directory.
+
+The main thing to note when using the accelerometer with SDL is that while the iPhone natively reports accelerometer as floating point values in units of g-force, SDL_JoystickGetAxis() reports joystick values as signed integers. Hence, in order to convert between the two, some clamping and scaling is necessary on the part of the iPhone SDL joystick driver. To convert SDL_JoystickGetAxis() reported values BACK to units of g-force, simply multiply the values by SDL_IPHONE_MAX_GFORCE / 0x7FFF.
+
+
+Notes -- OpenGL ES
+==============================================================================
+
+Your SDL application for iOS uses OpenGL ES for video by default.
+
+OpenGL ES for iOS supports several display pixel formats, such as RGBA8 and RGB565, which provide a 32 bit and 16 bit color buffer respectively. By default, the implementation uses RGB565, but you may use RGBA8 by setting each color component to 8 bits in SDL_GL_SetAttribute().
+
+If your application doesn't use OpenGL's depth buffer, you may find significant performance improvement by setting SDL_GL_DEPTH_SIZE to 0.
+
+Finally, if your application completely redraws the screen each frame, you may find significant performance improvement by setting the attribute SDL_GL_RETAINED_BACKING to 0.
+
+OpenGL ES on iOS doesn't use the traditional system-framebuffer setup provided in other operating systems. Special care must be taken because of this:
+
+- The drawable Renderbuffer must be bound to the GL_RENDERBUFFER binding point when SDL_GL_SwapWindow() is called.
+- The drawable Framebuffer Object must be bound while rendering to the screen and when SDL_GL_SwapWindow() is called.
+- If multisample antialiasing (MSAA) is used and glReadPixels is used on the screen, the drawable framebuffer must be resolved to the MSAA resolve framebuffer (via glBlitFramebuffer or glResolveMultisampleFramebufferAPPLE), and the MSAA resolve framebuffer must be bound to the GL_READ_FRAMEBUFFER binding point, before glReadPixels is called.
+
+The above objects can be obtained via SDL_GetWindowWMInfo() (in SDL_syswm.h).
+
+
+Notes -- Keyboard
+==============================================================================
+
+The SDL keyboard API has been extended to support on-screen keyboards:
+
+void SDL_StartTextInput()
+ -- enables text events and reveals the onscreen keyboard.
+
+void SDL_StopTextInput()
+ -- disables text events and hides the onscreen keyboard.
+
+SDL_bool SDL_IsTextInputActive()
+ -- returns whether or not text events are enabled (and the onscreen keyboard is visible)
+
+
+Notes -- Reading and Writing files
+==============================================================================
+
+Each application installed on iPhone resides in a sandbox which includes its own Application Home directory. Your application may not access files outside this directory.
+
+Once your application is installed its directory tree looks like:
+
+ MySDLApp Home/
+ MySDLApp.app
+ Documents/
+ Library/
+ Preferences/
+ tmp/
+
+When your SDL based iPhone application starts up, it sets the working directory to the main bundle (MySDLApp Home/MySDLApp.app), where your application resources are stored. You cannot write to this directory. Instead, I advise you to write document files to "../Documents/" and preferences to "../Library/Preferences".
+
+More information on this subject is available here:
+http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Introduction/Introduction.html
+
+
+Notes -- iPhone SDL limitations
+==============================================================================
+
+Windows:
+ Full-size, single window applications only. You cannot create multi-window SDL applications for iPhone OS. The application window will fill the display, though you have the option of turning on or off the menu-bar (pass SDL_CreateWindow() the flag SDL_WINDOW_BORDERLESS).
+
+Textures:
+ The optimal texture formats on iOS are SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_BGR888, and SDL_PIXELFORMAT_RGB24 pixel formats.
+
+Loading Shared Objects:
+ This is disabled by default since it seems to break the terms of the iOS SDK agreement for iOS versions prior to iOS 8. It can be re-enabled in SDL_config_iphoneos.h.
+
+
+Notes -- CoreBluetooth.framework
+==============================================================================
+
+SDL_JOYSTICK_HIDAPI is disabled by default. It can give you access to a lot
+more game controller devices, but it requires permission from the user before
+your app will be able to talk to the Bluetooth hardware. "Made For iOS"
+branded controllers do not need this as we don't have to speak to them
+directly with raw bluetooth, so many apps can live without this.
+
+You'll need to link with CoreBluetooth.framework and add something like this
+to your Info.plist:
+
+<key>NSBluetoothPeripheralUsageDescription</key>
+<string>MyApp would like to remain connected to nearby bluetooth Game Controllers and Game Pads even when you're not using the app.</string>
+
+
+Game Center
+==============================================================================
+
+Game Center integration might require that you break up your main loop in order to yield control back to the system. In other words, instead of running an endless main loop, you run each frame in a callback function, using:
+
+ int SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
+
+This will set up the given function to be called back on the animation callback, and then you have to return from main() to let the Cocoa event loop run.
+
+e.g.
+
+ extern "C"
+ void ShowFrame(void*)
+ {
+ ... do event handling, frame logic and rendering ...
+ }
+
+ int main(int argc, char *argv[])
+ {
+ ... initialize game ...
+
+ #if __IPHONEOS__
+ // Initialize the Game Center for scoring and matchmaking
+ InitGameCenter();
+
+ // Set up the game to run in the window animation callback on iOS
+ // so that Game Center and so forth works correctly.
+ SDL_iPhoneSetAnimationCallback(window, 1, ShowFrame, NULL);
+ #else
+ while ( running ) {
+ ShowFrame(0);
+ DelayFrame();
+ }
+ #endif
+ return 0;
+ }
+
+
+Deploying to older versions of iOS
+==============================================================================
+
+SDL supports deploying to older versions of iOS than are supported by the latest version of Xcode, all the way back to iOS 6.1
+
+In order to do that you need to download an older version of Xcode:
+https://developer.apple.com/download/more/?name=Xcode
+
+Open the package contents of the older Xcode and your newer version of Xcode and copy over the folders in Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
+
+Then open the file Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/SDKSettings.plist and add the versions of iOS you want to deploy to the key Root/DefaultProperties/DEPLOYMENT_TARGET_SUGGESTED_VALUES
+
+Open your project and set your deployment target to the desired version of iOS
+
+Finally, remove GameController from the list of frameworks linked by your application and edit the build settings for "Other Linker Flags" and add -weak_framework GameController
diff --git a/Client/ThirdParty/SDL2/docs/README-kmsbsd.md b/Client/ThirdParty/SDL2/docs/README-kmsbsd.md
new file mode 100644
index 0000000..01db5e8
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-kmsbsd.md
@@ -0,0 +1,27 @@
+KMSDRM on *BSD
+==================================================
+
+KMSDRM is supported on FreeBSD and OpenBSD. DragonFlyBSD works but requires being a root user. NetBSD isn't supported yet because the application will crash when creating the KMSDRM screen.
+
+WSCONS support has been brought back, but only as an input backend. It will not be brought back as a video backend to ease maintenance.
+
+OpenBSD note: Note that the video backend assumes that the user has read/write permissions to the /dev/drm* devices.
+
+
+SDL2 WSCONS input backend features
+===================================================
+1. It is keymap-aware; it will work properly with different keymaps.
+2. It has mouse support.
+3. Accent input is supported.
+4. Compose keys are supported.
+5. AltGr and Meta Shift keys work as intended.
+
+Partially working or no input on OpenBSD/NetBSD.
+==================================================
+
+The WSCONS input backend needs read/write access to the /dev/wskbd* devices, without which it will not work properly. /dev/wsmouse must also be read/write accessible, otherwise mouse input will not work.
+
+Partially working or no input on FreeBSD.
+==================================================
+
+The evdev devices are only accessible to the root user by default. Edit devfs rules to allow access to such devices. The /dev/kbd* devices are also only accessible to the root user by default. Edit devfs rules to allow access to such devices.
diff --git a/Client/ThirdParty/SDL2/docs/README-linux.md b/Client/ThirdParty/SDL2/docs/README-linux.md
new file mode 100644
index 0000000..9734941
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-linux.md
@@ -0,0 +1,83 @@
+Linux
+================================================================================
+
+By default SDL will only link against glibc, the rest of the features will be
+enabled dynamically at runtime depending on the available features on the target
+system. So, for example if you built SDL with Xinerama support and the target
+system does not have the Xinerama libraries installed, it will be disabled
+at runtime, and you won't get a missing library error, at least with the
+default configuration parameters.
+
+
+Build Dependencies
+--------------------------------------------------------------------------------
+
+Ubuntu 20.04, all available features enabled:
+
+ sudo apt-get install build-essential git make cmake autoconf automake \
+ libtool pkg-config libasound2-dev libpulse-dev libaudio-dev libjack-dev \
+ libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev \
+ libxinerama-dev libxxf86vm-dev libxss-dev libgl1-mesa-dev libdbus-1-dev \
+ libudev-dev libgles2-mesa-dev libegl1-mesa-dev libibus-1.0-dev \
+ fcitx-libs-dev libsamplerate0-dev libsndio-dev libwayland-dev \
+ libxkbcommon-dev libdrm-dev libgbm-dev
+
+NOTES:
+- This includes all the audio targets except arts and esd, because Ubuntu
+ (and/or Debian) pulled their packages, but in theory SDL still supports them.
+- libsamplerate0-dev lets SDL optionally link to libresamplerate at runtime
+ for higher-quality audio resampling. SDL will work without it if the library
+ is missing, so it's safe to build in support even if the end user doesn't
+ have this library installed.
+- DirectFB isn't included because the configure script (currently) fails to find
+ it at all. You can do "sudo apt-get install libdirectfb-dev" and fix the
+ configure script to include DirectFB support. Send patches. :)
+
+
+Joystick does not work
+--------------------------------------------------------------------------------
+
+If you compiled or are using a version of SDL with udev support (and you should!)
+there's a few issues that may cause SDL to fail to detect your joystick. To
+debug this, start by installing the evtest utility. On Ubuntu/Debian:
+
+ sudo apt-get install evtest
+
+Then run:
+
+ sudo evtest
+
+You'll hopefully see your joystick listed along with a name like "/dev/input/eventXX"
+Now run:
+
+ cat /dev/input/event/XX
+
+If you get a permission error, you need to set a udev rule to change the mode of
+your device (see below)
+
+Also, try:
+
+ sudo udevadm info --query=all --name=input/eventXX
+
+If you see a line stating ID_INPUT_JOYSTICK=1, great, if you don't see it,
+you need to set up an udev rule to force this variable.
+
+A combined rule for the Saitek Pro Flight Rudder Pedals to fix both issues looks
+like:
+
+ SUBSYSTEM=="input", ATTRS{idProduct}=="0763", ATTRS{idVendor}=="06a3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1"
+ SUBSYSTEM=="input", ATTRS{idProduct}=="0764", ATTRS{idVendor}=="06a3", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1"
+
+You can set up similar rules for your device by changing the values listed in
+idProduct and idVendor. To obtain these values, try:
+
+ sudo udevadm info -a --name=input/eventXX | grep idVendor
+ sudo udevadm info -a --name=input/eventXX | grep idProduct
+
+If multiple values come up for each of these, the one you want is the first one of each.
+
+On other systems which ship with an older udev (such as CentOS), you may need
+to set up a rule such as:
+
+ SUBSYSTEM=="input", ENV{ID_CLASS}=="joystick", ENV{ID_INPUT_JOYSTICK}="1"
+
diff --git a/Client/ThirdParty/SDL2/docs/README-macosx.md b/Client/ThirdParty/SDL2/docs/README-macosx.md
new file mode 100644
index 0000000..2cb8001
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-macosx.md
@@ -0,0 +1,240 @@
+Mac OS X
+==============================================================================
+
+These instructions are for people using Apple's Mac OS X (pronounced
+"ten").
+
+From the developer's point of view, OS X is a sort of hybrid Mac and
+Unix system, and you have the option of using either traditional
+command line tools or Apple's IDE Xcode.
+
+Command Line Build
+==================
+
+To build SDL using the command line, use the standard configure and make
+process:
+
+ ./configure
+ make
+ sudo make install
+
+You can also build SDL as a Universal library (a single binary for both
+32-bit and 64-bit Intel architectures), on Mac OS X 10.7 and newer, by using
+the gcc-fat.sh script in build-scripts:
+
+ mkdir mybuild
+ cd mybuild
+ CC=$PWD/../build-scripts/gcc-fat.sh CXX=$PWD/../build-scripts/g++-fat.sh ../configure
+ make
+ sudo make install
+
+This script builds SDL with 10.5 ABI compatibility on i386 and 10.6
+ABI compatibility on x86_64 architectures. For best compatibility you
+should compile your application the same way.
+
+Please note that building SDL requires at least Xcode 4.6 and the 10.7 SDK
+(even if you target back to 10.5 systems). PowerPC support for Mac OS X has
+been officially dropped as of SDL 2.0.2.
+
+To use the library once it's built, you essential have two possibilities:
+use the traditional autoconf/automake/make method, or use Xcode.
+
+==============================================================================
+Caveats for using SDL with Mac OS X
+==============================================================================
+
+Some things you have to be aware of when using SDL on Mac OS X:
+
+- If you register your own NSApplicationDelegate (using [NSApp setDelegate:]),
+ SDL will not register its own. This means that SDL will not terminate using
+ SDL_Quit if it receives a termination request, it will terminate like a
+ normal app, and it will not send a SDL_DROPFILE when you request to open a
+ file with the app. To solve these issues, put the following code in your
+ NSApplicationDelegate implementation:
+
+
+ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+ {
+ if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
+ SDL_Event event;
+ event.type = SDL_QUIT;
+ SDL_PushEvent(&event);
+ }
+
+ return NSTerminateCancel;
+ }
+
+ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
+ {
+ if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
+ SDL_Event event;
+ event.type = SDL_DROPFILE;
+ event.drop.file = SDL_strdup([filename UTF8String]);
+ return (SDL_PushEvent(&event) > 0);
+ }
+
+ return NO;
+ }
+
+==============================================================================
+Using the Simple DirectMedia Layer with a traditional Makefile
+==============================================================================
+
+An existing autoconf/automake build system for your SDL app has good chances
+to work almost unchanged on OS X. However, to produce a "real" Mac OS X binary
+that you can distribute to users, you need to put the generated binary into a
+so called "bundle", which basically is a fancy folder with a name like
+"MyCoolGame.app".
+
+To get this build automatically, add something like the following rule to
+your Makefile.am:
+
+ bundle_contents = APP_NAME.app/Contents
+ APP_NAME_bundle: EXE_NAME
+ mkdir -p $(bundle_contents)/MacOS
+ mkdir -p $(bundle_contents)/Resources
+ echo "APPL????" > $(bundle_contents)/PkgInfo
+ $(INSTALL_PROGRAM) $< $(bundle_contents)/MacOS/
+
+You should replace EXE_NAME with the name of the executable. APP_NAME is what
+will be visible to the user in the Finder. Usually it will be the same
+as EXE_NAME but capitalized. E.g. if EXE_NAME is "testgame" then APP_NAME
+usually is "TestGame". You might also want to use `@PACKAGE@` to use the package
+name as specified in your configure.ac file.
+
+If your project builds more than one application, you will have to do a bit
+more. For each of your target applications, you need a separate rule.
+
+If you want the created bundles to be installed, you may want to add this
+rule to your Makefile.am:
+
+ install-exec-hook: APP_NAME_bundle
+ rm -rf $(DESTDIR)$(prefix)/Applications/APP_NAME.app
+ mkdir -p $(DESTDIR)$(prefix)/Applications/
+ cp -r $< /$(DESTDIR)$(prefix)Applications/
+
+This rule takes the Bundle created by the rule from step 3 and installs them
+into "$(DESTDIR)$(prefix)/Applications/".
+
+Again, if you want to install multiple applications, you will have to augment
+the make rule accordingly.
+
+
+But beware! That is only part of the story! With the above, you end up with
+a bare bone .app bundle, which is double clickable from the Finder. But
+there are some more things you should do before shipping your product...
+
+1) The bundle right now probably is dynamically linked against SDL. That
+ means that when you copy it to another computer, *it will not run*,
+ unless you also install SDL on that other computer. A good solution
+ for this dilemma is to static link against SDL. On OS X, you can
+ achieve that by linking against the libraries listed by
+
+ sdl-config --static-libs
+
+ instead of those listed by
+
+ sdl-config --libs
+
+ Depending on how exactly SDL is integrated into your build systems, the
+ way to achieve that varies, so I won't describe it here in detail
+
+2) Add an 'Info.plist' to your application. That is a special XML file which
+ contains some meta-information about your application (like some copyright
+ information, the version of your app, the name of an optional icon file,
+ and other things). Part of that information is displayed by the Finder
+ when you click on the .app, or if you look at the "Get Info" window.
+ More information about Info.plist files can be found on Apple's homepage.
+
+
+As a final remark, let me add that I use some of the techniques (and some
+variations of them) in Exult and ScummVM; both are available in source on
+the net, so feel free to take a peek at them for inspiration!
+
+
+==============================================================================
+Using the Simple DirectMedia Layer with Xcode
+==============================================================================
+
+These instructions are for using Apple's Xcode IDE to build SDL applications.
+
+- First steps
+
+The first thing to do is to unpack the Xcode.tar.gz archive in the
+top level SDL directory (where the Xcode.tar.gz archive resides).
+Because Stuffit Expander will unpack the archive into a subdirectory,
+you should unpack the archive manually from the command line:
+
+ cd [path_to_SDL_source]
+ tar zxf Xcode.tar.gz
+
+This will create a new folder called Xcode, which you can browse
+normally from the Finder.
+
+- Building the Framework
+
+The SDL Library is packaged as a framework bundle, an organized
+relocatable folder hierarchy of executable code, interface headers,
+and additional resources. For practical purposes, you can think of a
+framework as a more user and system-friendly shared library, whose library
+file behaves more or less like a standard UNIX shared library.
+
+To build the framework, simply open the framework project and build it.
+By default, the framework bundle "SDL.framework" is installed in
+/Library/Frameworks. Therefore, the testers and project stationary expect
+it to be located there. However, it will function the same in any of the
+following locations:
+
+ ~/Library/Frameworks
+ /Local/Library/Frameworks
+ /System/Library/Frameworks
+
+- Build Options
+ There are two "Build Styles" (See the "Targets" tab) for SDL.
+ "Deployment" should be used if you aren't tweaking the SDL library.
+ "Development" should be used to debug SDL apps or the library itself.
+
+- Building the Testers
+ Open the SDLTest project and build away!
+
+- Using the Project Stationary
+ Copy the stationary to the indicated folders to access it from
+ the "New Project" and "Add target" menus. What could be easier?
+
+- Setting up a new project by hand
+ Some of you won't want to use the Stationary so I'll give some tips:
+ * Create a new "Cocoa Application"
+ * Add src/main/macosx/SDLMain.m , .h and .nib to your project
+ * Remove "main.c" from your project
+ * Remove "MainMenu.nib" from your project
+ * Add "$(HOME)/Library/Frameworks/SDL.framework/Headers" to include path
+ * Add "$(HOME)/Library/Frameworks" to the frameworks search path
+ * Add "-framework SDL -framework Foundation -framework AppKit" to "OTHER_LDFLAGS"
+ * Set the "Main Nib File" under "Application Settings" to "SDLMain.nib"
+ * Add your files
+ * Clean and build
+
+- Building from command line
+ Use pbxbuild in the same directory as your .pbproj file
+
+- Running your app
+ You can send command line args to your app by either invoking it from
+ the command line (in *.app/Contents/MacOS) or by entering them in the
+ "Executables" panel of the target settings.
+
+- Implementation Notes
+ Some things that may be of interest about how it all works...
+ * Working directory
+ As defined in the SDL_main.m file, the working directory of your SDL app
+ is by default set to its parent. You may wish to change this to better
+ suit your needs.
+ * You have a Cocoa App!
+ Your SDL app is essentially a Cocoa application. When your app
+ starts up and the libraries finish loading, a Cocoa procedure is called,
+ which sets up the working directory and calls your main() method.
+ You are free to modify your Cocoa app with generally no consequence
+ to SDL. You cannot, however, easily change the SDL window itself.
+ Functionality may be added in the future to help this.
+
+
+Known bugs are listed in the file "BUGS.txt".
diff --git a/Client/ThirdParty/SDL2/docs/README-nacl.md b/Client/ThirdParty/SDL2/docs/README-nacl.md
new file mode 100644
index 0000000..4c9432b
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-nacl.md
@@ -0,0 +1,103 @@
+Native Client
+================================================================================
+
+Requirements:
+
+* Native Client SDK (https://developer.chrome.com/native-client),
+ (tested with Pepper version 33 or higher).
+
+The SDL backend for Chrome's Native Client has been tested only with the PNaCl
+toolchain, which generates binaries designed to run on ARM and x86_32/64
+platforms. This does not mean it won't work with the other toolchains!
+
+================================================================================
+Building SDL for NaCl
+================================================================================
+
+Set up the right environment variables (see naclbuild.sh), then configure SDL with:
+
+ configure --host=pnacl --prefix some/install/destination
+
+Then "make".
+
+As an example of how to create a deployable app a Makefile project is provided
+in test/nacl/Makefile, which includes some monkey patching of the common.mk file
+provided by NaCl, without which linking properly to SDL won't work (the search
+path can't be modified externally, so the linker won't find SDL's binaries unless
+you dump them into the SDK path, which is inconvenient).
+Also provided in test/nacl is the required support file, such as index.html,
+manifest.json, etc.
+SDL apps for NaCl run on a worker thread using the ppapi_simple infrastructure.
+This allows for blocking calls on all the relevant systems (OpenGL ES, filesystem),
+hiding the asynchronous nature of the browser behind the scenes...which is not the
+same as making it disappear!
+
+
+================================================================================
+Running tests
+================================================================================
+
+Due to the nature of NaCl programs, building and running SDL tests is not as
+straightforward as one would hope. The script naclbuild.sh in build-scripts
+automates the process and should serve as a guide for users of SDL trying to build
+their own applications.
+
+Basic usage:
+
+ ./naclbuild.sh path/to/pepper/toolchain (i.e. ~/naclsdk/pepper_35)
+
+This will build testgles2.c by default.
+
+If you want to build a different test, for example testrendercopyex.c:
+
+ SOURCES=~/sdl/SDL/test/testrendercopyex.c ./naclbuild.sh ~/naclsdk/pepper_35
+
+Once the build finishes, you have to serve the contents with a web server (the
+script will give you instructions on how to do that with Python).
+
+================================================================================
+RWops and nacl_io
+================================================================================
+
+SDL_RWops work transparently with nacl_io. Two functions control the mount points:
+
+ int mount(const char* source, const char* target,
+ const char* filesystemtype,
+ unsigned long mountflags, const void *data);
+ int umount(const char *target);
+
+ For convenience, SDL will by default mount an httpfs tree at / before calling
+the app's main function. Such setting can be overridden by calling:
+
+ umount("/");
+
+And then mounting a different filesystem at /
+
+It's important to consider that the asynchronous nature of file operations on a
+browser is hidden from the application, effectively providing the developer with
+a set of blocking file operations just like you get in a regular desktop
+environment, which eases the job of porting to Native Client, but also introduces
+a set of challenges of its own, in particular when big file sizes and slow
+connections are involved.
+
+For more information on how nacl_io and mount points work, see:
+
+ https://developer.chrome.com/native-client/devguide/coding/nacl_io
+ https://src.chromium.org/chrome/trunk/src/native_client_sdk/src/libraries/nacl_io/nacl_io.h
+
+To be able to save into the directory "/save/" (like backup of game) :
+
+ mount("", "/save", "html5fs", 0, "type=PERSISTENT");
+
+And add to manifest.json :
+
+ "permissions": [
+ "unlimitedStorage"
+ ]
+
+================================================================================
+TODO - Known Issues
+================================================================================
+* Testing of all systems with a real application (something other than SDL's tests)
+* Key events don't seem to work properly
+
diff --git a/Client/ThirdParty/SDL2/docs/README-os2.md b/Client/ThirdParty/SDL2/docs/README-os2.md
new file mode 100644
index 0000000..2b7bb2b
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-os2.md
@@ -0,0 +1,54 @@
+Simple DirectMedia Layer 2 for OS/2 & eComStation
+================================================================================
+SDL port for OS/2, authored by Andrey Vasilkin <digi@os2.snc.ru>, 2016
+
+
+OpenGL, joystick and audio capture not supported by this port.
+
+Additional environment variables (optional) for OS/2 version:
+
+SDL_AUDIO_SHARE
+ Values: 0 or 1, default is 0
+ Initializes the device as shareable or exclusively acquired.
+
+SDL_VIDEODRIVER
+ Values: DIVE or VMAN, default is DIVE
+ Use video subsystem: Direct interface video extensions (DIVE) or
+ Video Manager (VMAN).
+
+You may significantly increase video output speed with OS4 kernel and patched
+files vman.dll and dive.dll or with latest versions of ACPI support and video
+driver Panorama.
+
+Latest versions of OS/4 kernel:
+ http://gus.biysk.ru/os4/
+ (Info: https://www.os2world.com/wiki/index.php/Phoenix_OS/4)
+
+Patched files vman.dll and dive.dll:
+ http://gus.biysk.ru/os4/test/pached_dll/PATCHED_DLL.RAR
+
+
+Compiling:
+----------
+
+Open Watcom 1.9 or newer is tested. For the new Open Watcom V2 fork, see:
+https://github.com/open-watcom/ and https://open-watcom.github.io
+WATCOM ervironment variable must to be set to the Open Watcom install
+directory. To compile, run: wmake -f Makefile.os2
+
+
+Installing:
+-----------
+
+- eComStation:
+
+ If you have previously installed SDL2, make a Backup copy of SDL2.dll
+ located in D:\ecs\dll (where D: is disk on which installed eComStation).
+ Stop all programs running with SDL2. Copy SDL2.dll to D:\ecs\dll
+
+- OS/2:
+
+ Copy SDL2.dll to any directory on your LIBPATH. If you have a previous
+ version installed, close all SDL2 applications before replacing the old
+ copy. Also make sure that any other older versions of DLLs are removed
+ from your system.
diff --git a/Client/ThirdParty/SDL2/docs/README-pandora.md b/Client/ThirdParty/SDL2/docs/README-pandora.md
new file mode 100644
index 0000000..511a054
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-pandora.md
@@ -0,0 +1,17 @@
+Pandora
+=====================================================================
+
+( http://openpandora.org/ )
+- A pandora specific video driver was written to allow SDL 2.0 with OpenGL ES
+support to work on the pandora under the framebuffer. This driver do not have
+input support for now, so if you use it you will have to add your own control code.
+The video driver name is "pandora" so if you have problem running it from
+the framebuffer, try to set the following variable before starting your application :
+"export SDL_VIDEODRIVER=pandora"
+
+- OpenGL ES support was added to the x11 driver, so it's working like the normal
+x11 driver one with OpenGLX support, with SDL input event's etc..
+
+
+David Carré (Cpasjuste)
+cpasjuste@gmail.com
diff --git a/Client/ThirdParty/SDL2/docs/README-platforms.md b/Client/ThirdParty/SDL2/docs/README-platforms.md
new file mode 100644
index 0000000..14454ec
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-platforms.md
@@ -0,0 +1,8 @@
+Platforms
+=========
+
+We maintain the list of supported platforms on our wiki now, and how to
+build and install SDL for those platforms:
+
+ https://wiki.libsdl.org/Installation
+
diff --git a/Client/ThirdParty/SDL2/docs/README-porting.md b/Client/ThirdParty/SDL2/docs/README-porting.md
new file mode 100644
index 0000000..82f35c6
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-porting.md
@@ -0,0 +1,68 @@
+Porting
+=======
+
+* Porting To A New Platform
+
+ The first thing you have to do when porting to a new platform, is look at
+include/SDL_platform.h and create an entry there for your operating system.
+The standard format is "__PLATFORM__", where PLATFORM is the name of the OS.
+Ideally SDL_platform.h will be able to auto-detect the system it's building
+on based on C preprocessor symbols.
+
+There are two basic ways of building SDL at the moment:
+
+1. The "UNIX" way: ./configure; make; make install
+
+ If you have a GNUish system, then you might try this. Edit configure.ac,
+ take a look at the large section labelled:
+
+ "Set up the configuration based on the host platform!"
+
+ Add a section for your platform, and then re-run autogen.sh and build!
+
+2. Using an IDE:
+
+ If you're using an IDE or other non-configure build system, you'll probably
+ want to create a custom SDL_config.h for your platform. Edit SDL_config.h,
+ add a section for your platform, and create a custom SDL_config_{platform}.h,
+ based on SDL_config_minimal.h and SDL_config.h.in
+
+ Add the top level include directory to the header search path, and then add
+ the following sources to the project:
+
+ src/*.c
+ src/atomic/*.c
+ src/audio/*.c
+ src/cpuinfo/*.c
+ src/events/*.c
+ src/file/*.c
+ src/haptic/*.c
+ src/joystick/*.c
+ src/power/*.c
+ src/render/*.c
+ src/render/software/*.c
+ src/stdlib/*.c
+ src/thread/*.c
+ src/timer/*.c
+ src/video/*.c
+ src/audio/disk/*.c
+ src/audio/dummy/*.c
+ src/filesystem/dummy/*.c
+ src/video/dummy/*.c
+ src/haptic/dummy/*.c
+ src/joystick/dummy/*.c
+ src/main/dummy/*.c
+ src/thread/generic/*.c
+ src/timer/dummy/*.c
+ src/loadso/dummy/*.c
+
+
+Once you have a working library without any drivers, you can go back to each
+of the major subsystems and start implementing drivers for your platform.
+
+If you have any questions, don't hesitate to ask on the SDL mailing list:
+ http://www.libsdl.org/mailing-list.php
+
+Enjoy!
+ Sam Lantinga (slouken@libsdl.org)
+
diff --git a/Client/ThirdParty/SDL2/docs/README-psp.md b/Client/ThirdParty/SDL2/docs/README-psp.md
new file mode 100644
index 0000000..0acc93d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-psp.md
@@ -0,0 +1,19 @@
+PSP
+======
+SDL port for the Sony PSP contributed by
+ Captian Lex
+
+Credit to
+ Marcus R.Brown,Jim Paris,Matthew H for the original SDL 1.2 for PSP
+ Geecko for his PSP GU lib "Glib2d"
+
+Building
+--------
+To build for the PSP, make sure psp-config is in the path and run:
+ make -f Makefile.psp
+
+
+
+To Do
+------
+PSP Screen Keyboard
diff --git a/Client/ThirdParty/SDL2/docs/README-raspberrypi.md b/Client/ThirdParty/SDL2/docs/README-raspberrypi.md
new file mode 100644
index 0000000..2c95e06
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-raspberrypi.md
@@ -0,0 +1,188 @@
+Raspberry Pi
+================================================================================
+
+Requirements:
+
+Raspbian (other Linux distros may work as well).
+
+================================================================================
+ Features
+================================================================================
+
+* Works without X11
+* Hardware accelerated OpenGL ES 2.x
+* Sound via ALSA
+* Input (mouse/keyboard/joystick) via EVDEV
+* Hotplugging of input devices via UDEV
+
+
+================================================================================
+ Raspbian Build Dependencies
+================================================================================
+
+sudo apt-get install libudev-dev libasound2-dev libdbus-1-dev
+
+You also need the VideoCore binary stuff that ships in /opt/vc for EGL and
+OpenGL ES 2.x, it usually comes pre-installed, but in any case:
+
+sudo apt-get install libraspberrypi0 libraspberrypi-bin libraspberrypi-dev
+
+
+================================================================================
+ NEON
+================================================================================
+
+If your Pi has NEON support, make sure you add -mfpu=neon to your CFLAGS so
+that SDL will select some otherwise-disabled highly-optimized code. The
+original Pi units don't have NEON, the Pi2 probably does, and the Pi3
+definitely does.
+
+================================================================================
+ Cross compiling from x86 Linux
+================================================================================
+
+To cross compile SDL for Raspbian from your desktop machine, you'll need a
+Raspbian system root and the cross compilation tools. We'll assume these tools
+will be placed in /opt/rpi-tools
+
+ sudo git clone --depth 1 https://github.com/raspberrypi/tools /opt/rpi-tools
+
+You'll also need a Raspbian binary image.
+Get it from: http://downloads.raspberrypi.org/raspbian_latest
+After unzipping, you'll get file with a name like: "<date>-wheezy-raspbian.img"
+Let's assume the sysroot will be built in /opt/rpi-sysroot.
+
+ export SYSROOT=/opt/rpi-sysroot
+ sudo kpartx -a -v <path_to_raspbian_image>.img
+ sudo mount -o loop /dev/mapper/loop0p2 /mnt
+ sudo cp -r /mnt $SYSROOT
+ sudo apt-get install qemu binfmt-support qemu-user-static
+ sudo cp /usr/bin/qemu-arm-static $SYSROOT/usr/bin
+ sudo mount --bind /dev $SYSROOT/dev
+ sudo mount --bind /proc $SYSROOT/proc
+ sudo mount --bind /sys $SYSROOT/sys
+
+Now, before chrooting into the ARM sysroot, you'll need to apply a workaround,
+edit $SYSROOT/etc/ld.so.preload and comment out all lines in it.
+
+ sudo chroot $SYSROOT
+ apt-get install libudev-dev libasound2-dev libdbus-1-dev libraspberrypi0 libraspberrypi-bin libraspberrypi-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev
+ exit
+ sudo umount $SYSROOT/dev
+ sudo umount $SYSROOT/proc
+ sudo umount $SYSROOT/sys
+ sudo umount /mnt
+
+There's one more fix required, as the libdl.so symlink uses an absolute path
+which doesn't quite work in our setup.
+
+ sudo rm -rf $SYSROOT/usr/lib/arm-linux-gnueabihf/libdl.so
+ sudo ln -s ../../../lib/arm-linux-gnueabihf/libdl.so.2 $SYSROOT/usr/lib/arm-linux-gnueabihf/libdl.so
+
+The final step is compiling SDL itself.
+
+ export CC="/opt/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc --sysroot=$SYSROOT -I$SYSROOT/opt/vc/include -I$SYSROOT/usr/include -I$SYSROOT/opt/vc/include/interface/vcos/pthreads -I$SYSROOT/opt/vc/include/interface/vmcs_host/linux"
+ cd <SDL SOURCE>
+ mkdir -p build;cd build
+ LDFLAGS="-L$SYSROOT/opt/vc/lib" ../configure --with-sysroot=$SYSROOT --host=arm-raspberry-linux-gnueabihf --prefix=$PWD/rpi-sdl2-installed --disable-pulseaudio --disable-esd
+ make
+ make install
+
+To be able to deploy this to /usr/local in the Raspbian system you need to fix up a few paths:
+
+ perl -w -pi -e "s#$PWD/rpi-sdl2-installed#/usr/local#g;" ./rpi-sdl2-installed/lib/libSDL2.la ./rpi-sdl2-installed/lib/pkgconfig/sdl2.pc ./rpi-sdl2-installed/bin/sdl2-config
+
+================================================================================
+ Apps don't work or poor video/audio performance
+================================================================================
+
+If you get sound problems, buffer underruns, etc, run "sudo rpi-update" to
+update the RPi's firmware. Note that doing so will fix these problems, but it
+will also render the CMA - Dynamic Memory Split functionality useless.
+
+Also, by default the Raspbian distro configures the GPU RAM at 64MB, this is too
+low in general, specially if a 1080p TV is hooked up.
+
+See here how to configure this setting: http://elinux.org/RPiconfig
+
+Using a fixed gpu_mem=128 is the best option (specially if you updated the
+firmware, using CMA probably won't work, at least it's the current case).
+
+================================================================================
+ No input
+================================================================================
+
+Make sure you belong to the "input" group.
+
+ sudo usermod -aG input `whoami`
+
+================================================================================
+ No HDMI Audio
+================================================================================
+
+If you notice that ALSA works but there's no audio over HDMI, try adding:
+
+ hdmi_drive=2
+
+to your config.txt file and reboot.
+
+Reference: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=5062
+
+================================================================================
+ Text Input API support
+================================================================================
+
+The Text Input API is supported, with translation of scan codes done via the
+kernel symbol tables. For this to work, SDL needs access to a valid console.
+If you notice there's no SDL_TEXTINPUT message being emitted, double check that
+your app has read access to one of the following:
+
+* /proc/self/fd/0
+* /dev/tty
+* /dev/tty[0...6]
+* /dev/vc/0
+* /dev/console
+
+This is usually not a problem if you run from the physical terminal (as opposed
+to running from a pseudo terminal, such as via SSH). If running from a PTS, a
+quick workaround is to run your app as root or add yourself to the tty group,
+then re-login to the system.
+
+ sudo usermod -aG tty `whoami`
+
+The keyboard layout used by SDL is the same as the one the kernel uses.
+To configure the layout on Raspbian:
+
+ sudo dpkg-reconfigure keyboard-configuration
+
+To configure the locale, which controls which keys are interpreted as letters,
+this determining the CAPS LOCK behavior:
+
+ sudo dpkg-reconfigure locales
+
+================================================================================
+ OpenGL problems
+================================================================================
+
+If you have desktop OpenGL headers installed at build time in your RPi or cross
+compilation environment, support for it will be built in. However, the chipset
+does not actually have support for it, which causes issues in certain SDL apps
+since the presence of OpenGL support supersedes the ES/ES2 variants.
+The workaround is to disable OpenGL at configuration time:
+
+ ./configure --disable-video-opengl
+
+Or if the application uses the Render functions, you can use the SDL_RENDER_DRIVER
+environment variable:
+
+ export SDL_RENDER_DRIVER=opengles2
+
+================================================================================
+ Notes
+================================================================================
+
+* When launching apps remotely (via SSH), SDL can prevent local keystrokes from
+ leaking into the console only if it has root privileges. Launching apps locally
+ does not suffer from this issue.
+
+
diff --git a/Client/ThirdParty/SDL2/docs/README-touch.md b/Client/ThirdParty/SDL2/docs/README-touch.md
new file mode 100644
index 0000000..b6745ac
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-touch.md
@@ -0,0 +1,86 @@
+Touch
+===========================================================================
+System Specific Notes
+===========================================================================
+Linux:
+The linux touch system is currently based off event streams, and proc/bus/devices. The active user must be given permissions to read /dev/input/TOUCHDEVICE, where TOUCHDEVICE is the event stream for your device. Currently only Wacom tablets are supported. If you have an unsupported tablet contact me at jim.tla+sdl_touch@gmail.com and I will help you get support for it.
+
+Mac:
+The Mac and iPhone APIs are pretty. If your touch device supports them then you'll be fine. If it doesn't, then there isn't much we can do.
+
+iPhone:
+Works out of box.
+
+Windows:
+Unfortunately there is no windows support as of yet. Support for Windows 7 is planned, but we currently have no way to test. If you have a Windows 7 WM_TOUCH supported device, and are willing to help test please contact me at jim.tla+sdl_touch@gmail.com
+
+===========================================================================
+Events
+===========================================================================
+SDL_FINGERDOWN:
+Sent when a finger (or stylus) is placed on a touch device.
+Fields:
+* event.tfinger.touchId - the Id of the touch device.
+* event.tfinger.fingerId - the Id of the finger which just went down.
+* event.tfinger.x - the x coordinate of the touch (0..1)
+* event.tfinger.y - the y coordinate of the touch (0..1)
+* event.tfinger.pressure - the pressure of the touch (0..1)
+
+SDL_FINGERMOTION:
+Sent when a finger (or stylus) is moved on the touch device.
+Fields:
+Same as SDL_FINGERDOWN but with additional:
+* event.tfinger.dx - change in x coordinate during this motion event.
+* event.tfinger.dy - change in y coordinate during this motion event.
+
+SDL_FINGERUP:
+Sent when a finger (or stylus) is lifted from the touch device.
+Fields:
+Same as SDL_FINGERDOWN.
+
+
+===========================================================================
+Functions
+===========================================================================
+SDL provides the ability to access the underlying SDL_Finger structures.
+These structures should _never_ be modified.
+
+The following functions are included from SDL_touch.h
+
+To get a SDL_TouchID call SDL_GetTouchDevice(int index).
+This returns a SDL_TouchID.
+IMPORTANT: If the touch has been removed, or there is no touch with the given index, SDL_GetTouchDevice() will return 0. Be sure to check for this!
+
+The number of touch devices can be queried with SDL_GetNumTouchDevices().
+
+A SDL_TouchID may be used to get pointers to SDL_Finger.
+
+SDL_GetNumTouchFingers(touchID) may be used to get the number of fingers currently down on the device.
+
+The most common reason to access SDL_Finger is to query the fingers outside the event. In most cases accessing the fingers is using the event. This would be accomplished by code like the following:
+
+ float x = event.tfinger.x;
+ float y = event.tfinger.y;
+
+
+
+To get a SDL_Finger, call SDL_GetTouchFinger(SDL_TouchID touchID, int index), where touchID is a SDL_TouchID, and index is the requested finger.
+This returns a SDL_Finger *, or NULL if the finger does not exist, or has been removed.
+A SDL_Finger is guaranteed to be persistent for the duration of a touch, but it will be de-allocated as soon as the finger is removed. This occurs when the SDL_FINGERUP event is _added_ to the event queue, and thus _before_ the SDL_FINGERUP event is polled.
+As a result, be very careful to check for NULL return values.
+
+A SDL_Finger has the following fields:
+* x, y:
+ The current coordinates of the touch.
+* pressure:
+ The pressure of the touch.
+
+
+===========================================================================
+Notes
+===========================================================================
+For a complete example see test/testgesture.c
+
+Please direct questions/comments to:
+ jim.tla+sdl_touch@gmail.com
+ (original author, API was changed since)
diff --git a/Client/ThirdParty/SDL2/docs/README-visualc.md b/Client/ThirdParty/SDL2/docs/README-visualc.md
new file mode 100644
index 0000000..ea2bc18
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-visualc.md
@@ -0,0 +1,114 @@
+Using SDL with Microsoft Visual C++
+===================================
+
+### by [Lion Kimbro](mailto:snowlion@sprynet.com) with additions by [James Turk](mailto:james@conceptofzero.net)
+
+You can either use the precompiled libraries from the [SDL](https://www.libsdl.org/download.php) web site, or you can build SDL
+yourself.
+
+### Building SDL
+
+0. To build SDL, your machine must, at a minimum, have the DirectX9.0c SDK installed. It may or may not be retrievable from
+the [Microsoft](https://www.microsoft.com) website, so you might need to locate it [online](https://duckduckgo.com/?q=directx9.0c+sdk+download&t=h_&ia=web).
+_Editor's note: I've been able to successfully build SDL using Visual Studio 2019 **without** the DX9.0c SDK_
+
+1. Open the Visual Studio solution file at `./VisualC/SDL.sln`.
+
+2. Your IDE will likely prompt you to upgrade this solution file to whatever later version of the IDE you're using. In the `Retarget Projects` dialog,
+all of the affected project files should be checked allowing you to use the latest `Windows SDK Version` you have installed, along with
+the `Platform Toolset`.
+
+If you choose *NOT* to upgrade to use the latest `Windows SDK Version` or `Platform Toolset`, then you'll need the `Visual Studio 2010 Platform Toolset`.
+
+3. Build the `.dll` and `.lib` files by right clicking on each project in turn (Projects are listed in the _Workspace_
+panel in the _FileView_ tab), and selecting `Build`.
+
+You may get a few warnings, but you should not get any errors.
+
+Later, we will refer to the following `.lib` and `.dll` files that have just been generated:
+
+- `./VisualC/Win32/Debug/SDL2.dll` or `./VisualC/Win32/Release/SDL2.dll`
+- `./VisualC/Win32/Debug/SDL2.lib` or `./VisualC/Win32/Release/SDL2.lib`
+- `./VisualC/Win32/Debug/SDL2main.lib` or `./VisualC/Win32/Release/SDL2main.lib`
+
+_Note for the `x64` versions, just replace `Win32` in the path with `x64`_
+
+### Creating a Project with SDL
+
+- Create a project as a `Win32 Application`.
+
+- Create a C++ file for your project.
+
+- Set the C runtime to `Multi-threaded DLL` in the menu:
+`Project|Settings|C/C++ tab|Code Generation|Runtime Library `.
+
+- Add the SDL `include` directory to your list of includes in the menu:
+`Project|Settings|C/C++ tab|Preprocessor|Additional include directories `
+
+*VC7 Specific: Instead of doing this, I find it easier to add the
+include and library directories to the list that VC7 keeps. Do this by
+selecting Tools|Options|Projects|VC++ Directories and under the "Show
+Directories For:" dropbox select "Include Files", and click the "New
+Directory Icon" and add the [SDLROOT]\\include directory (e.g. If you
+installed to c:\\SDL\\ add c:\\SDL\\include). Proceed to change the
+dropbox selection to "Library Files" and add [SDLROOT]\\lib.*
+
+The "include directory" I am referring to is the `./include` folder.
+
+Now we're going to use the files that we had created earlier in the *Build SDL* step.
+
+Copy the following file into your Project directory:
+
+- `SDL2.dll`
+
+Add the following files to your project (It is not necessary to copy them to your project directory):
+
+- `SDL2.lib`
+- `SDL2main.lib`
+
+To add them to your project, right click on your project, and select
+`Add files to project`.
+
+**Instead of adding the files to your project, it is more desirable to add them to the linker options: Project|Properties|Linker|Command Line
+and type the names of the libraries to link with in the "Additional Options:" box. Note: This must be done for each build configuration
+(e.g. Release,Debug).**
+
+### Hello SDL2
+
+Here's a sample SDL snippet to verify everything is setup in your IDE:
+
+```
+ #include "SDL.h"
+
+ int main( int argc, char* argv[] )
+ {
+ const int WIDTH = 640;
+ const int HEIGHT = 480;
+ SDL_Window* window = NULL;
+ SDL_Renderer* renderer = NULL;
+
+ SDL_Init(SDL_INIT_VIDEO);
+ window = SDL_CreateWindow("SDL2 Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+ return 0;
+ }
+ ```
+
+### That's it!
+
+I hope that this document has helped you get through the most difficult part of using the SDL: installing it.
+Suggestions for improvements should be posted to the [Github Issues](https://github.com/libsdl-org/SDL/issues).
+
+### Credits
+
+Thanks to [Paulus Esterhazy](mailto:pesterhazy@gmx.net), for the work on VC++ port.
+
+This document was originally called "VisualC.txt", and was written by [Sam Lantinga](mailto:slouken@libsdl.org).
+
+Later, it was converted to HTML and expanded into the document that you see today by [Lion Kimbro](mailto:snowlion@sprynet.com).
+
+Minor Fixes and Visual C++ 7 Information (In Green) was added by [James Turk](mailto:james@conceptofzero.net)
diff --git a/Client/ThirdParty/SDL2/docs/README-vita.md b/Client/ThirdParty/SDL2/docs/README-vita.md
new file mode 100644
index 0000000..4996e5c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-vita.md
@@ -0,0 +1,25 @@
+PS Vita
+=======
+SDL port for the Sony Playstation Vita and Sony Playstation TV
+
+Credit to
+* xerpi and rsn8887 for initial (vita2d) port
+* vitasdk/dolcesdk devs
+* CBPS discord (Namely Graphene and SonicMastr)
+
+Building
+--------
+To build for the PSVita, make sure you have vitasdk and cmake installed and run:
+```
+ cmake -S. -Bbuild -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release
+ cmake --build build
+ cmake --install build
+```
+
+
+Notes
+-----
+* gles2 support is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON`
+* By default SDL emits mouse events for touch events on every touchscreen.
+ Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead.
+* Support for L2/R2/R3/R3 buttons, haptic feedback and gamepad led only available on PSTV, or when using external ds4 gamepad on vita. \ No newline at end of file
diff --git a/Client/ThirdParty/SDL2/docs/README-wince.md b/Client/ThirdParty/SDL2/docs/README-wince.md
new file mode 100644
index 0000000..9fc6454
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-wince.md
@@ -0,0 +1,10 @@
+WinCE
+=====
+
+Windows CE is no longer supported by SDL.
+
+We have left the CE support in SDL 1.2 for those that must have it, and we
+have support for Windows Phone 8 and WinRT in SDL2, as of SDL 2.0.3.
+
+--ryan.
+
diff --git a/Client/ThirdParty/SDL2/docs/README-windows.md b/Client/ThirdParty/SDL2/docs/README-windows.md
new file mode 100644
index 0000000..71f968e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-windows.md
@@ -0,0 +1,45 @@
+Windows
+================================================================================
+
+================================================================================
+OpenGL ES 2.x support
+================================================================================
+
+SDL has support for OpenGL ES 2.x under Windows via two alternative
+implementations.
+The most straightforward method consists in running your app in a system with
+a graphic card paired with a relatively recent (as of November of 2013) driver
+which supports the WGL_EXT_create_context_es2_profile extension. Vendors known
+to ship said extension on Windows currently include nVidia and Intel.
+
+The other method involves using the ANGLE library (https://code.google.com/p/angleproject/)
+If an OpenGL ES 2.x context is requested and no WGL_EXT_create_context_es2_profile
+extension is found, SDL will try to load the libEGL.dll library provided by
+ANGLE.
+To obtain the ANGLE binaries, you can either compile from source from
+https://chromium.googlesource.com/angle/angle or copy the relevant binaries from
+a recent Chrome/Chromium install for Windows. The files you need are:
+
+ * libEGL.dll
+ * libGLESv2.dll
+ * d3dcompiler_46.dll (supports Windows Vista or later, better shader compiler)
+ or...
+ * d3dcompiler_43.dll (supports Windows XP or later)
+
+If you compile ANGLE from source, you can configure it so it does not need the
+d3dcompiler_* DLL at all (for details on this, see their documentation).
+However, by default SDL will try to preload the d3dcompiler_46.dll to
+comply with ANGLE's requirements. If you wish SDL to preload d3dcompiler_43.dll (to
+support Windows XP) or to skip this step at all, you can use the
+SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more details).
+
+Known Bugs:
+
+ * SDL_GL_SetSwapInterval is currently a no op when using ANGLE. It appears
+ that there's a bug in the library which prevents the window contents from
+ refreshing if this is set to anything other than the default value.
+
+Vulkan Surface Support
+==============
+
+Support for creating Vulkan surfaces is configured on by default. To disable it change the value of `SDL_VIDEO_VULKAN` to 0 in `SDL_config_windows.h`. You must install the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) in order to use Vulkan graphics in your application.
diff --git a/Client/ThirdParty/SDL2/docs/README-winrt.md b/Client/ThirdParty/SDL2/docs/README-winrt.md
new file mode 100644
index 0000000..87052ff
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README-winrt.md
@@ -0,0 +1,550 @@
+WinRT
+=====
+
+This port allows SDL applications to run on Microsoft's platforms that require
+use of "Windows Runtime", aka. "WinRT", APIs. Microsoft may, in some cases,
+refer to them as either "Windows Store", or for Windows 10, "UWP" apps.
+
+Some of the operating systems that include WinRT, are:
+
+* Windows 10, via its Universal Windows Platform (UWP) APIs
+* Windows 8.x
+* Windows RT 8.x (aka. Windows 8.x for ARM processors)
+* Windows Phone 8.x
+
+
+Requirements
+------------
+
+* Microsoft Visual C++ (aka Visual Studio), either 2017, 2015, 2013, or 2012
+ - Free, "Community" or "Express" editions may be used, so long as they
+ include support for either "Windows Store" or "Windows Phone" apps.
+ "Express" versions marked as supporting "Windows Desktop" development
+ typically do not include support for creating WinRT apps, to note.
+ (The "Community" editions of Visual C++ do, however, support both
+ desktop/Win32 and WinRT development).
+ - Visual Studio 2017 can be used, however it is recommended that you install
+ the Visual C++ 2015 build tools. These build tools can be installed
+ using VS 2017's installer. Be sure to also install the workload for
+ "Universal Windows Platform development", its optional component, the
+ "C++ Universal Windows Platform tools", and for UWP / Windows 10
+ development, the "Windows 10 SDK (10.0.10240.0)". Please note that
+ targeting UWP / Windows 10 apps from development machine(s) running
+ earlier versions of Windows, such as Windows 7, is not always supported
+ by Visual Studio, and you may get error(s) when attempting to do so.
+ - Visual C++ 2012 can only build apps that target versions 8.0 of Windows,
+ or Windows Phone. 8.0-targeted apps will run on devices running 8.1
+ editions of Windows, however they will not be able to take advantage of
+ 8.1-specific features.
+ - Visual C++ 2013 cannot create app projects that target Windows 8.0.
+ Visual C++ 2013 Update 4, can create app projects for Windows Phone 8.0,
+ Windows Phone 8.1, and Windows 8.1, but not Windows 8.0. An optional
+ Visual Studio add-in, "Tools for Maintaining Store apps for Windows 8",
+ allows Visual C++ 2013 to load and build Windows 8.0 projects that were
+ created with Visual C++ 2012, so long as Visual C++ 2012 is installed
+ on the same machine. More details on targeting different versions of
+ Windows can found at the following web pages:
+ - [Develop apps by using Visual Studio 2013](http://msdn.microsoft.com/en-us/library/windows/apps/br211384.aspx)
+ - [To add the Tools for Maintaining Store apps for Windows 8](http://msdn.microsoft.com/en-us/library/windows/apps/dn263114.aspx#AddMaintenanceTools)
+* A valid Microsoft account - This requirement is not imposed by SDL, but
+ rather by Microsoft's Visual C++ toolchain. This is required to launch or
+ debug apps.
+
+
+Status
+------
+
+Here is a rough list of what works, and what doesn't:
+
+* What works:
+ * compilation via Visual C++ 2012 through 2015
+ * compile-time platform detection for SDL programs. The C/C++ #define,
+ `__WINRT__`, will be set to 1 (by SDL) when compiling for WinRT.
+ * GPU-accelerated 2D rendering, via SDL_Renderer.
+ * OpenGL ES 2, via the ANGLE library (included separately from SDL)
+ * software rendering, via either SDL_Surface (optionally in conjunction with
+ SDL_GetWindowSurface() and SDL_UpdateWindowSurface()) or via the
+ SDL_Renderer APIs
+ * threads
+ * timers (via SDL_GetTicks(), SDL_AddTimer(), SDL_GetPerformanceCounter(),
+ SDL_GetPerformanceFrequency(), etc.)
+ * file I/O via SDL_RWops
+ * mouse input (unsupported on Windows Phone)
+ * audio, via SDL's WASAPI backend (if you want to record, your app must
+ have "Microphone" capabilities enabled in its manifest, and the user must
+ not have blocked access. Otherwise, capture devices will fail to work,
+ presenting as a device disconnect shortly after opening it.)
+ * .DLL file loading. Libraries *MUST* be packaged inside applications. Loading
+ anything outside of the app is not supported.
+ * system path retrieval via SDL's filesystem APIs
+ * game controllers. Support is provided via the SDL_Joystick and
+ SDL_GameController APIs, and is backed by Microsoft's XInput API. Please
+ note, however, that Windows limits game-controller support in UWP apps to,
+ "Xbox compatible controllers" (many controllers that work in Win32 apps,
+ do not work in UWP, due to restrictions in UWP itself.)
+ * multi-touch input
+ * app events. SDL_APP_WILLENTER* and SDL_APP_DIDENTER* events get sent out as
+ appropriate.
+ * window events
+ * using Direct3D 11.x APIs outside of SDL. Non-XAML / Direct3D-only apps can
+ choose to render content directly via Direct3D, using SDL to manage the
+ internal WinRT window, as well as input and audio. (Use
+ SDL_GetWindowWMInfo() to get the WinRT 'CoreWindow', and pass it into
+ IDXGIFactory2::CreateSwapChainForCoreWindow() as appropriate.)
+
+* What partially works:
+ * keyboard input. Most of WinRT's documented virtual keys are supported, as
+ well as many keys with documented hardware scancodes. Converting
+ SDL_Scancodes to or from SDL_Keycodes may not work, due to missing APIs
+ (MapVirtualKey()) in Microsoft's Windows Store / UWP APIs.
+ * SDLmain. WinRT uses a different signature for each app's main() function.
+ SDL-based apps that use this port must compile in SDL_winrt_main_NonXAML.cpp
+ (in `SDL\src\main\winrt\`) directly in order for their C-style main()
+ functions to be called.
+
+* What doesn't work:
+ * compilation with anything other than Visual C++
+ * programmatically-created custom cursors. These don't appear to be supported
+ by WinRT. Different OS-provided cursors can, however, be created via
+ SDL_CreateSystemCursor() (unsupported on Windows Phone)
+ * SDL_WarpMouseInWindow() or SDL_WarpMouseGlobal(). This are not currently
+ supported by WinRT itself.
+ * joysticks and game controllers that either are not supported by
+ Microsoft's XInput API, or are not supported within UWP apps (many
+ controllers that work in Win32, do not work in UWP, due to restrictions in
+ UWP itself).
+ * turning off VSync when rendering on Windows Phone. Attempts to turn VSync
+ off on Windows Phone result either in Direct3D not drawing anything, or it
+ forcing VSync back on. As such, SDL_RENDERER_PRESENTVSYNC will always get
+ turned-on on Windows Phone. This limitation is not present in non-Phone
+ WinRT (such as Windows 8.x), where turning off VSync appears to work.
+ * probably anything else that's not listed as supported
+
+
+
+Upgrade Notes
+-------------
+
+#### SDL_GetPrefPath() usage when upgrading WinRT apps from SDL 2.0.3
+
+SDL 2.0.4 fixes two bugs found in the WinRT version of SDL_GetPrefPath().
+The fixes may affect older, SDL 2.0.3-based apps' save data. Please note
+that these changes only apply to SDL-based WinRT apps, and not to apps for
+any other platform.
+
+1. SDL_GetPrefPath() would return an invalid path, one in which the path's
+ directory had not been created. Attempts to create files there
+ (via fopen(), for example), would fail, unless that directory was
+ explicitly created beforehand.
+
+2. SDL_GetPrefPath(), for non-WinPhone-based apps, would return a path inside
+ a WinRT 'Roaming' folder, the contents of which get automatically
+ synchronized across multiple devices. This process can occur while an
+ application runs, and can cause existing save-data to be overwritten
+ at unexpected times, with data from other devices. (Windows Phone apps
+ written with SDL 2.0.3 did not utilize a Roaming folder, due to API
+ restrictions in Windows Phone 8.0).
+
+
+SDL_GetPrefPath(), starting with SDL 2.0.4, addresses these by:
+
+1. making sure that SDL_GetPrefPath() returns a directory in which data
+ can be written to immediately, without first needing to create directories.
+
+2. basing SDL_GetPrefPath() off of a different, non-Roaming folder, the
+ contents of which do not automatically get synchronized across devices
+ (and which require less work to use safely, in terms of data integrity).
+
+Apps that wish to get their Roaming folder's path can do so either by using
+SDL_WinRTGetFSPathUTF8(), SDL_WinRTGetFSPathUNICODE() (which returns a
+UCS-2/wide-char string), or directly through the WinRT class,
+Windows.Storage.ApplicationData.
+
+
+
+Setup, High-Level Steps
+-----------------------
+
+The steps for setting up a project for an SDL/WinRT app looks like the
+following, at a high-level:
+
+1. create a new Visual C++ project using Microsoft's template for a,
+ "Direct3D App".
+2. remove most of the files from the project.
+3. make your app's project directly reference SDL/WinRT's own Visual C++
+ project file, via use of Visual C++'s "References" dialog. This will setup
+ the linker, and will copy SDL's .dll files to your app's final output.
+4. adjust your app's build settings, at minimum, telling it where to find SDL's
+ header files.
+5. add files that contains a WinRT-appropriate main function, along with some
+ data to make sure mouse-cursor-hiding (via SDL_ShowCursor(SDL_DISABLE) calls)
+ work properly.
+6. add SDL-specific app code.
+7. build and run your app.
+
+
+Setup, Detailed Steps
+---------------------
+
+### 1. Create a new project ###
+
+Create a new project using one of Visual C++'s templates for a plain, non-XAML,
+"Direct3D App" (XAML support for SDL/WinRT is not yet ready for use). If you
+don't see one of these templates, in Visual C++'s 'New Project' dialog, try
+using the textbox titled, 'Search Installed Templates' to look for one.
+
+
+### 2. Remove unneeded files from the project ###
+
+In the new project, delete any file that has one of the following extensions:
+
+- .cpp
+- .h
+- .hlsl
+
+When you are done, you should be left with a few files, each of which will be a
+necessary part of your app's project. These files will consist of:
+
+- an .appxmanifest file, which contains metadata on your WinRT app. This is
+ similar to an Info.plist file on iOS, or an AndroidManifest.xml on Android.
+- a few .png files, one of which is a splash screen (displayed when your app
+ launches), others are app icons.
+- a .pfx file, used for code signing purposes.
+
+
+### 3. Add references to SDL's project files ###
+
+SDL/WinRT can be built in multiple variations, spanning across three different
+CPU architectures (x86, x64, and ARM) and two different configurations
+(Debug and Release). WinRT and Visual C++ do not currently provide a means
+for combining multiple variations of one library into a single file.
+Furthermore, it does not provide an easy means for copying pre-built .dll files
+into your app's final output (via Post-Build steps, for example). It does,
+however, provide a system whereby an app can reference the MSVC projects of
+libraries such that, when the app is built:
+
+1. each library gets built for the appropriate CPU architecture(s) and WinRT
+ platform(s).
+2. each library's output, such as .dll files, get copied to the app's build
+ output.
+
+To set this up for SDL/WinRT, you'll need to run through the following steps:
+
+1. open up the Solution Explorer inside Visual C++ (under the "View" menu, then
+ "Solution Explorer")
+2. right click on your app's solution.
+3. navigate to "Add", then to "Existing Project..."
+4. find SDL/WinRT's Visual C++ project file and open it. Different project
+ files exist for different WinRT platforms. All of them are in SDL's
+ source distribution, in the following directories:
+ * `VisualC-WinRT/UWP_VS2015/` - for Windows 10 / UWP apps
+ * `VisualC-WinRT/WinPhone81_VS2013/` - for Windows Phone 8.1 apps
+ * `VisualC-WinRT/WinRT80_VS2012/` - for Windows 8.0 apps
+ * `VisualC-WinRT/WinRT81_VS2013/` - for Windows 8.1 apps
+5. once the project has been added, right-click on your app's project and
+ select, "References..."
+6. click on the button titled, "Add New Reference..."
+7. check the box next to SDL
+8. click OK to close the dialog
+9. SDL will now show up in the list of references. Click OK to close that
+ dialog.
+
+Your project is now linked to SDL's project, insofar that when the app is
+built, SDL will be built as well, with its build output getting included with
+your app.
+
+
+### 4. Adjust Your App's Build Settings ###
+
+Some build settings need to be changed in your app's project. This guide will
+outline the following:
+
+- making sure that the compiler knows where to find SDL's header files
+- **Optional for C++, but NECESSARY for compiling C code:** telling the
+ compiler not to use Microsoft's C++ extensions for WinRT development.
+- **Optional:** telling the compiler not generate errors due to missing
+ precompiled header files.
+
+To change these settings:
+
+1. right-click on the project
+2. choose "Properties"
+3. in the drop-down box next to "Configuration", choose, "All Configurations"
+4. in the drop-down box next to "Platform", choose, "All Platforms"
+5. in the left-hand list, expand the "C/C++" section
+6. select "General"
+7. edit the "Additional Include Directories" setting, and add a path to SDL's
+ "include" directory
+8. **Optional: to enable compilation of C code:** change the setting for
+ "Consume Windows Runtime Extension" from "Yes (/ZW)" to "No". If you're
+ working with a completely C++ based project, this step can usually be
+ omitted.
+9. **Optional: to disable precompiled headers (which can produce
+ 'stdafx.h'-related build errors, if setup incorrectly:** in the left-hand
+ list, select "Precompiled Headers", then change the setting for "Precompiled
+ Header" from "Use (/Yu)" to "Not Using Precompiled Headers".
+10. close the dialog, saving settings, by clicking the "OK" button
+
+
+### 5. Add a WinRT-appropriate main function, and a blank-cursor image, to the app. ###
+
+A few files should be included directly in your app's MSVC project, specifically:
+1. a WinRT-appropriate main function (which is different than main() functions on
+ other platforms)
+2. a Win32-style cursor resource, used by SDL_ShowCursor() to hide the mouse cursor
+ (if and when the app needs to do so). *If this cursor resource is not
+ included, mouse-position reporting may fail if and when the cursor is
+ hidden, due to possible bugs/design-oddities in Windows itself.*
+
+To include these files for C/C++ projects:
+
+1. right-click on your project (again, in Visual C++'s Solution Explorer),
+ navigate to "Add", then choose "Existing Item...".
+2. navigate to the directory containing SDL's source code, then into its
+ subdirectory, 'src/main/winrt/'. Select, then add, the following files:
+ - `SDL_winrt_main_NonXAML.cpp`
+ - `SDL2-WinRTResources.rc`
+ - `SDL2-WinRTResource_BlankCursor.cur`
+3. right-click on the file `SDL_winrt_main_NonXAML.cpp` (as listed in your
+ project), then click on "Properties...".
+4. in the drop-down box next to "Configuration", choose, "All Configurations"
+5. in the drop-down box next to "Platform", choose, "All Platforms"
+6. in the left-hand list, click on "C/C++"
+7. change the setting for "Consume Windows Runtime Extension" to "Yes (/ZW)".
+8. click the OK button. This will close the dialog.
+
+**NOTE: C++/CX compilation is currently required in at least one file of your
+app's project. This is to make sure that Visual C++'s linker builds a 'Windows
+Metadata' file (.winmd) for your app. Not doing so can lead to build errors.**
+
+For non-C++ projects, you will need to call SDL_WinRTRunApp from your language's
+main function, and generate SDL2-WinRTResources.res manually by using `rc` via
+the Developer Command Prompt and including it as a <Win32Resource> within the
+first <PropertyGroup> block in your Visual Studio project file.
+
+### 6. Add app code and assets ###
+
+At this point, you can add in SDL-specific source code. Be sure to include a
+C-style main function (ie: `int main(int argc, char *argv[])`). From there you
+should be able to create a single `SDL_Window` (WinRT apps can only have one
+window, at present), as well as an `SDL_Renderer`. Direct3D will be used to
+draw content. Events are received via SDL's usual event functions
+(`SDL_PollEvent`, etc.) If you have a set of existing source files and assets,
+you can start adding them to the project now. If not, or if you would like to
+make sure that you're setup correctly, some short and simple sample code is
+provided below.
+
+
+#### 6.A. ... when creating a new app ####
+
+If you are creating a new app (rather than porting an existing SDL-based app),
+or if you would just like a simple app to test SDL/WinRT with before trying to
+get existing code working, some working SDL/WinRT code is provided below. To
+set this up:
+
+1. right click on your app's project
+2. select Add, then New Item. An "Add New Item" dialog will show up.
+3. from the left-hand list, choose "Visual C++"
+4. from the middle/main list, choose "C++ File (.cpp)"
+5. near the bottom of the dialog, next to "Name:", type in a name for your
+source file, such as, "main.cpp".
+6. click on the Add button. This will close the dialog, add the new file to
+your project, and open the file in Visual C++'s text editor.
+7. Copy and paste the following code into the new file, then save it.
+
+```c
+#include <SDL.h>
+
+int main(int argc, char **argv)
+{
+ SDL_DisplayMode mode;
+ SDL_Window * window = NULL;
+ SDL_Renderer * renderer = NULL;
+ SDL_Event evt;
+ SDL_bool keep_going = SDL_TRUE;
+
+ if (SDL_Init(SDL_INIT_VIDEO) != 0) {
+ return 1;
+ } else if (SDL_GetCurrentDisplayMode(0, &mode) != 0) {
+ return 1;
+ } else if (SDL_CreateWindowAndRenderer(mode.w, mode.h, SDL_WINDOW_FULLSCREEN, &window, &renderer) != 0) {
+ return 1;
+ }
+
+ while (keep_going) {
+ while (SDL_PollEvent(&evt)) {
+ if ((evt.type == SDL_KEYDOWN) && (evt.key.keysym.sym == SDLK_ESCAPE)) {
+ keep_going = SDL_FALSE;
+ }
+ }
+
+ SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
+ SDL_RenderClear(renderer);
+ SDL_RenderPresent(renderer);
+ }
+
+ SDL_Quit();
+ return 0;
+}
+```
+
+#### 6.B. Adding code and assets ####
+
+If you have existing code and assets that you'd like to add, you should be able
+to add them now. The process for adding a set of files is as such.
+
+1. right click on the app's project
+2. select Add, then click on "New Item..."
+3. open any source, header, or asset files as appropriate. Support for C and
+C++ is available.
+
+Do note that WinRT only supports a subset of the APIs that are available to
+Win32-based apps. Many portions of the Win32 API and the C runtime are not
+available.
+
+A list of unsupported C APIs can be found at
+<http://msdn.microsoft.com/en-us/library/windows/apps/jj606124.aspx>
+
+General information on using the C runtime in WinRT can be found at
+<https://msdn.microsoft.com/en-us/library/hh972425.aspx>
+
+A list of supported Win32 APIs for WinRT apps can be found at
+<http://msdn.microsoft.com/en-us/library/windows/apps/br205757.aspx>. To note,
+the list of supported Win32 APIs for Windows Phone 8.0 is different.
+That list can be found at
+<http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662956(v=vs.105).aspx>
+
+
+### 7. Build and run your app ###
+
+Your app project should now be setup, and you should be ready to build your app.
+To run it on the local machine, open the Debug menu and choose "Start
+Debugging". This will build your app, then run your app full-screen. To switch
+out of your app, press the Windows key. Alternatively, you can choose to run
+your app in a window. To do this, before building and running your app, find
+the drop-down menu in Visual C++'s toolbar that says, "Local Machine". Expand
+this by clicking on the arrow on the right side of the list, then click on
+Simulator. Once you do that, any time you build and run the app, the app will
+launch in window, rather than full-screen.
+
+
+#### 7.A. Running apps on older, ARM-based, "Windows RT" devices ####
+
+**These instructions do not include Windows Phone, despite Windows Phone
+typically running on ARM processors.** They are specifically for devices
+that use the "Windows RT" operating system, which was a modified version of
+Windows 8.x that ran primarily on ARM-based tablet computers.
+
+To build and run the app on ARM-based, "Windows RT" devices, you'll need to:
+
+- install Microsoft's "Remote Debugger" on the device. Visual C++ installs and
+ debugs ARM-based apps via IP networks.
+- change a few options on the development machine, both to make sure it builds
+ for ARM (rather than x86 or x64), and to make sure it knows how to find the
+ Windows RT device (on the network).
+
+Microsoft's Remote Debugger can be found at
+<https://msdn.microsoft.com/en-us/library/hh441469.aspx>. Please note
+that separate versions of this debugger exist for different versions of Visual
+C++, one each for MSVC 2015, 2013, and 2012.
+
+To setup Visual C++ to launch your app on an ARM device:
+
+1. make sure the Remote Debugger is running on your ARM device, and that it's on
+ the same IP network as your development machine.
+2. from Visual C++'s toolbar, find a drop-down menu that says, "Win32". Click
+ it, then change the value to "ARM".
+3. make sure Visual C++ knows the hostname or IP address of the ARM device. To
+ do this:
+ 1. open the app project's properties
+ 2. select "Debugging"
+ 3. next to "Machine Name", enter the hostname or IP address of the ARM
+ device
+ 4. if, and only if, you've turned off authentication in the Remote Debugger,
+ then change the setting for "Require Authentication" to No
+ 5. click "OK"
+4. build and run the app (from Visual C++). The first time you do this, a
+ prompt will show up on the ARM device, asking for a Microsoft Account. You
+ do, unfortunately, need to log in here, and will need to follow the
+ subsequent registration steps in order to launch the app. After you do so,
+ if the app didn't already launch, try relaunching it again from within Visual
+ C++.
+
+
+Troubleshooting
+---------------
+
+#### Build fails with message, "error LNK2038: mismatch detected for 'vccorlib_lib_should_be_specified_before_msvcrt_lib_to_linker'"
+
+Try adding the following to your linker flags. In MSVC, this can be done by
+right-clicking on the app project, navigating to Configuration Properties ->
+Linker -> Command Line, then adding them to the Additional Options
+section.
+
+* For Release builds / MSVC-Configurations, add:
+
+ /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib
+
+* For Debug builds / MSVC-Configurations, add:
+
+ /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib
+
+
+#### Mouse-motion events fail to get sent, or SDL_GetMouseState() fails to return updated values
+
+This may be caused by a bug in Windows itself, whereby hiding the mouse
+cursor can cause mouse-position reporting to fail.
+
+SDL provides a workaround for this, but it requires that an app links to a
+set of Win32-style cursor image-resource files. A copy of suitable resource
+files can be found in `src/main/winrt/`. Adding them to an app's Visual C++
+project file should be sufficient to get the app to use them.
+
+
+#### SDL's Visual Studio project file fails to open, with message, "The system can't find the file specified."
+
+This can be caused for any one of a few reasons, which Visual Studio can
+report, but won't always do so in an up-front manner.
+
+To help determine why this error comes up:
+
+1. open a copy of Visual Studio without opening a project file. This can be
+ accomplished via Windows' Start Menu, among other means.
+2. show Visual Studio's Output window. This can be done by going to VS'
+ menu bar, then to View, and then to Output.
+3. try opening the SDL project file directly by going to VS' menu bar, then
+ to File, then to Open, then to Project/Solution. When a File-Open dialog
+ appears, open the SDL project (such as the one in SDL's source code, in its
+ directory, VisualC-WinRT/UWP_VS2015/).
+4. after attempting to open SDL's Visual Studio project file, additional error
+ information will be output to the Output window.
+
+If Visual Studio reports (via its Output window) that the project:
+
+"could not be loaded because it's missing install components. To fix this launch Visual Studio setup with the following selections:
+Microsoft.VisualStudio.ComponentGroup.UWP.VC"
+
+... then you will need to re-launch Visual Studio's installer, and make sure that
+the workflow for "Universal Windows Platform development" is checked, and that its
+optional component, "C++ Universal Windows Platform tools" is also checked. While
+you are there, if you are planning on targeting UWP / Windows 10, also make sure
+that you check the optional component, "Windows 10 SDK (10.0.10240.0)". After
+making sure these items are checked as-appropriate, install them.
+
+Once you install these components, try re-launching Visual Studio, and re-opening
+the SDL project file. If you still get the error dialog, try using the Output
+window, again, seeing what Visual Studio says about it.
+
+
+#### Game controllers / joysticks aren't working!
+
+Windows only permits certain game controllers and joysticks to work within
+WinRT / UWP apps. Even if a game controller or joystick works in a Win32
+app, that device is not guaranteed to work inside a WinRT / UWP app.
+
+According to Microsoft, "Xbox compatible controllers" should work inside
+UWP apps, potentially with more working in the future. This includes, but
+may not be limited to, Microsoft-made Xbox controllers and USB adapters.
+(Source: https://social.msdn.microsoft.com/Forums/en-US/9064838b-e8c3-4c18-8a83-19bf0dfe150d/xinput-fails-to-detect-game-controllers?forum=wpdevelop)
+
+
diff --git a/Client/ThirdParty/SDL2/docs/README.md b/Client/ThirdParty/SDL2/docs/README.md
new file mode 100644
index 0000000..4591fcf
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/README.md
@@ -0,0 +1,65 @@
+Simple DirectMedia Layer {#mainpage}
+========================
+
+ (SDL)
+
+ Version 2.0
+
+---
+http://www.libsdl.org/
+
+Simple DirectMedia Layer is a cross-platform development library designed
+to provide low level access to audio, keyboard, mouse, joystick, and graphics
+hardware via OpenGL and Direct3D. It is used by video playback software,
+emulators, and popular games including Valve's award winning catalog
+and many Humble Bundle games.
+
+SDL officially supports Windows, Mac OS X, Linux, iOS, and Android.
+Support for other platforms may be found in the source code.
+
+SDL is written in C, works natively with C++, and there are bindings
+available for several other languages, including C# and Python.
+
+This library is distributed under the zlib license, which can be found
+in the file "LICENSE.txt".
+
+The best way to learn how to use SDL is to check out the header files in
+the "include" subdirectory and the programs in the "test" subdirectory.
+The header files and test programs are well commented and always up to date.
+
+More documentation and FAQs are available online at [the wiki](http://wiki.libsdl.org/)
+
+- [Android](README-android.md)
+- [CMake](README-cmake.md)
+- [DirectFB](README-directfb.md)
+- [DynAPI](README-dynapi.md)
+- [Emscripten](README-emscripten.md)
+- [Gesture](README-gesture.md)
+- [Git](README-git.md)
+- [iOS](README-ios.md)
+- [Linux](README-linux.md)
+- [OS X](README-macosx.md)
+- [Native Client](README-nacl.md)
+- [Pandora](README-pandora.md)
+- [Supported Platforms](README-platforms.md)
+- [Porting information](README-porting.md)
+- [PSP](README-psp.md)
+- [Raspberry Pi](README-raspberrypi.md)
+- [Touch](README-touch.md)
+- [WinCE](README-wince.md)
+- [Windows](README-windows.md)
+- [WinRT](README-winrt.md)
+- [PSVita](README-vita.md)
+
+If you need help with the library, or just want to discuss SDL related
+issues, you can join the [SDL Discourse](https://discourse.libsdl.org/),
+which can be used as a web forum or a mailing list, at your preference.
+
+If you want to report bugs or contribute patches, please submit them to
+[our bug tracker](https://github.com/libsdl-org/SDL/issues)
+
+Enjoy!
+
+
+Sam Lantinga <mailto:slouken@libsdl.org>
+
diff --git a/Client/ThirdParty/SDL2/docs/doxyfile b/Client/ThirdParty/SDL2/docs/doxyfile
new file mode 100644
index 0000000..baf1c98
--- /dev/null
+++ b/Client/ThirdParty/SDL2/docs/doxyfile
@@ -0,0 +1,1560 @@
+# Doxyfile 1.5.9
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = SDL
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 2.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./output
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = YES
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES = "defined=\"\def\"" \
+ "discussion=\"\par Discussion:\n\""
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set
+# FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = YES
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page. This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE = ./doxygen_warn.txt
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = . ../include
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.vhd \
+ *.vhdl \
+ *.h.in \
+ *.h.default \
+ *.md
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = ../include/SDL_opengles2_gl2ext.h \
+ ../include/SDL_opengles2_gl2platform.h \
+ ../include/SDL_opengles2_khrplatform.h \
+ ../include/SDL_opengl_glext.h \
+ ../include/SDL_opengles2_gl2.h \
+ ../include/SDL_opengles2.h \
+ ../include/SDL_opengles.h \
+ ../include/SDL_opengl.h \
+ ../include/SDL_egl.h \
+
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX = SDL_ \
+ SDL
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "SDL 2.0 Doxygen"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.libsdl.sdl20
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE = ./sdl20.chm
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 1
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to FRAME, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature. Other possible values
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW = ALL
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN_SHOULD_IGNORE_THIS=1 \
+ DECLSPEC= \
+ SDLCALL= \
+ _WIN32=1
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = ./SDL.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = c:\Perl\bin\perl.exe
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 60
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Options related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/Client/ThirdParty/SDL2/include/SDL.h b/Client/ThirdParty/SDL2/include/SDL.h
new file mode 100644
index 0000000..222a8bd
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL.h
@@ -0,0 +1,221 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL.h
+ *
+ * Main include header for the SDL library
+ */
+
+
+#ifndef SDL_h_
+#define SDL_h_
+
+#include "SDL_main.h"
+#include "SDL_stdinc.h"
+#include "SDL_assert.h"
+#include "SDL_atomic.h"
+#include "SDL_audio.h"
+#include "SDL_clipboard.h"
+#include "SDL_cpuinfo.h"
+#include "SDL_endian.h"
+#include "SDL_error.h"
+#include "SDL_events.h"
+#include "SDL_filesystem.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_haptic.h"
+#include "SDL_hints.h"
+#include "SDL_joystick.h"
+#include "SDL_loadso.h"
+#include "SDL_log.h"
+#include "SDL_messagebox.h"
+#include "SDL_metal.h"
+#include "SDL_mutex.h"
+#include "SDL_power.h"
+#include "SDL_render.h"
+#include "SDL_rwops.h"
+#include "SDL_sensor.h"
+#include "SDL_shape.h"
+#include "SDL_system.h"
+#include "SDL_thread.h"
+#include "SDL_timer.h"
+#include "SDL_version.h"
+#include "SDL_video.h"
+#include "SDL_locale.h"
+#include "SDL_misc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* As of version 0.5, SDL is loaded dynamically into the application */
+
+/**
+ * \name SDL_INIT_*
+ *
+ * These are the flags which may be passed to SDL_Init(). You should
+ * specify the subsystems which you will be using in your application.
+ */
+/* @{ */
+#define SDL_INIT_TIMER 0x00000001u
+#define SDL_INIT_AUDIO 0x00000010u
+#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK 0x00000200u /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
+#define SDL_INIT_HAPTIC 0x00001000u
+#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS 0x00004000u
+#define SDL_INIT_SENSOR 0x00008000u
+#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */
+#define SDL_INIT_EVERYTHING ( \
+ SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
+ SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \
+ )
+/* @} */
+
+/**
+ * Initialize the SDL library.
+ *
+ * SDL_Init() simply forwards to calling SDL_InitSubSystem(). Therefore, the
+ * two may be used interchangeably. Though for readability of your code
+ * SDL_InitSubSystem() might be preferred.
+ *
+ * The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread)
+ * subsystems are initialized by default. Message boxes
+ * (SDL_ShowSimpleMessageBox) also attempt to work without initializing the
+ * video subsystem, in hopes of being useful in showing an error dialog when
+ * SDL_Init fails. You must specifically initialize other subsystems if you
+ * use them in your application.
+ *
+ * Logging (such as SDL_Log) works without initialization, too.
+ *
+ * `flags` may be any of the following OR'd together:
+ *
+ * - `SDL_INIT_TIMER`: timer subsystem
+ * - `SDL_INIT_AUDIO`: audio subsystem
+ * - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events
+ * subsystem
+ * - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the
+ * events subsystem
+ * - `SDL_INIT_HAPTIC`: haptic (force feedback) subsystem
+ * - `SDL_INIT_GAMECONTROLLER`: controller subsystem; automatically
+ * initializes the joystick subsystem
+ * - `SDL_INIT_EVENTS`: events subsystem
+ * - `SDL_INIT_EVERYTHING`: all of the above subsystems
+ * - `SDL_INIT_NOPARACHUTE`: compatibility; this flag is ignored
+ *
+ * Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem()
+ * for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or
+ * call SDL_Quit() to force shutdown). If a subsystem is already loaded then
+ * this call will increase the ref-count and return.
+ *
+ * \param flags subsystem initialization flags
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_InitSubSystem
+ * \sa SDL_Quit
+ * \sa SDL_SetMainReady
+ * \sa SDL_WasInit
+ */
+extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
+
+/**
+ * Compatibility function to initialize the SDL library.
+ *
+ * In SDL2, this function and SDL_Init() are interchangeable.
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_Init
+ * \sa SDL_Quit
+ * \sa SDL_QuitSubSystem
+ */
+extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags);
+
+/**
+ * Shut down specific SDL subsystems.
+ *
+ * If you start a subsystem using a call to that subsystem's init function
+ * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
+ * SDL_QuitSubSystem() and SDL_WasInit() will not work. You will need to use
+ * that subsystem's quit function (SDL_VideoQuit()) directly instead. But
+ * generally, you should not be using those functions directly anyhow; use
+ * SDL_Init() instead.
+ *
+ * You still need to call SDL_Quit() even if you close all open subsystems
+ * with SDL_QuitSubSystem().
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ *
+ * \sa SDL_InitSubSystem
+ * \sa SDL_Quit
+ */
+extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags);
+
+/**
+ * Get a mask of the specified subsystems which are currently initialized.
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ * \returns a mask of all initialized subsystems if `flags` is 0, otherwise it
+ * returns the initialization status of the specified subsystems.
+ *
+ * The return value does not include SDL_INIT_NOPARACHUTE.
+ *
+ * \sa SDL_Init
+ * \sa SDL_InitSubSystem
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags);
+
+/**
+ * Clean up all initialized subsystems.
+ *
+ * You should call this function even if you have already shutdown each
+ * initialized subsystem with SDL_QuitSubSystem(). It is safe to call this
+ * function even in the case of errors in initialization.
+ *
+ * If you start a subsystem using a call to that subsystem's init function
+ * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
+ * then you must use that subsystem's quit function (SDL_VideoQuit()) to shut
+ * it down before calling SDL_Quit(). But generally, you should not be using
+ * those functions directly anyhow; use SDL_Init() instead.
+ *
+ * You can use this function with atexit() to ensure that it is run when your
+ * application is shutdown, but it is not wise to do this from a library or
+ * other dynamically loaded code.
+ *
+ * \sa SDL_Init
+ * \sa SDL_QuitSubSystem
+ */
+extern DECLSPEC void SDLCALL SDL_Quit(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_assert.h b/Client/ThirdParty/SDL2/include/SDL_assert.h
new file mode 100644
index 0000000..a627b17
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_assert.h
@@ -0,0 +1,318 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_assert_h_
+#define SDL_assert_h_
+
+#include "SDL_config.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SDL_ASSERT_LEVEL
+#ifdef SDL_DEFAULT_ASSERT_LEVEL
+#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
+#elif defined(_DEBUG) || defined(DEBUG) || \
+ (defined(__GNUC__) && !defined(__OPTIMIZE__))
+#define SDL_ASSERT_LEVEL 2
+#else
+#define SDL_ASSERT_LEVEL 1
+#endif
+#endif /* SDL_ASSERT_LEVEL */
+
+/*
+These are macros and not first class functions so that the debugger breaks
+on the assertion line and not in some random guts of SDL, and so each
+assert can have unique static variables associated with it.
+*/
+
+#if defined(_MSC_VER)
+/* Don't include intrin.h here because it contains C++ code */
+ extern void __cdecl __debugbreak(void);
+ #define SDL_TriggerBreakpoint() __debugbreak()
+#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
+#elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
+#elif defined(__APPLE__) && defined(__arm__)
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" )
+#elif defined(__386__) && defined(__WATCOMC__)
+ #define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
+#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
+ #include <signal.h>
+ #define SDL_TriggerBreakpoint() raise(SIGTRAP)
+#else
+ /* How do we trigger breakpoints on this platform? */
+ #define SDL_TriggerBreakpoint()
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
+# define SDL_FUNCTION __func__
+#elif ((__GNUC__ >= 2) || defined(_MSC_VER) || defined (__WATCOMC__))
+# define SDL_FUNCTION __FUNCTION__
+#else
+# define SDL_FUNCTION "???"
+#endif
+#define SDL_FILE __FILE__
+#define SDL_LINE __LINE__
+
+/*
+sizeof (x) makes the compiler still parse the expression even without
+assertions enabled, so the code is always checked at compile time, but
+doesn't actually generate code for it, so there are no side effects or
+expensive checks at run time, just the constant size of what x WOULD be,
+which presumably gets optimized out as unused.
+This also solves the problem of...
+
+ int somevalue = blah();
+ SDL_assert(somevalue == 1);
+
+...which would cause compiles to complain that somevalue is unused if we
+disable assertions.
+*/
+
+/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking
+ this condition isn't constant. And looks like an owl's face! */
+#ifdef _MSC_VER /* stupid /W4 warnings. */
+#define SDL_NULL_WHILE_LOOP_CONDITION (0,0)
+#else
+#define SDL_NULL_WHILE_LOOP_CONDITION (0)
+#endif
+
+#define SDL_disabled_assert(condition) \
+ do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+typedef enum
+{
+ SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */
+ SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */
+ SDL_ASSERTION_ABORT, /**< Terminate the program. */
+ SDL_ASSERTION_IGNORE, /**< Ignore the assert. */
+ SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */
+} SDL_AssertState;
+
+typedef struct SDL_AssertData
+{
+ int always_ignore;
+ unsigned int trigger_count;
+ const char *condition;
+ const char *filename;
+ int linenum;
+ const char *function;
+ const struct SDL_AssertData *next;
+} SDL_AssertData;
+
+#if (SDL_ASSERT_LEVEL > 0)
+
+/* Never call this directly. Use the SDL_assert* macros. */
+extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
+ const char *,
+ const char *, int)
+#if defined(__clang__)
+#if __has_feature(attribute_analyzer_noreturn)
+/* this tells Clang's static analysis that we're a custom assert function,
+ and that the analyzer should assume the condition was always true past this
+ SDL_assert test. */
+ __attribute__((analyzer_noreturn))
+#endif
+#endif
+;
+
+/* the do {} while(0) avoids dangling else problems:
+ if (x) SDL_assert(y); else blah();
+ ... without the do/while, the "else" could attach to this macro's "if".
+ We try to handle just the minimum we need here in a macro...the loop,
+ the static vars, and break points. The heavy lifting is handled in
+ SDL_ReportAssertion(), in SDL_assert.c.
+*/
+#define SDL_enabled_assert(condition) \
+ do { \
+ while ( !(condition) ) { \
+ static struct SDL_AssertData sdl_assert_data = { \
+ 0, 0, #condition, 0, 0, 0, 0 \
+ }; \
+ const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
+ if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
+ continue; /* go again. */ \
+ } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
+ SDL_TriggerBreakpoint(); \
+ } \
+ break; /* not retrying. */ \
+ } \
+ } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+#endif /* enabled assertions support code */
+
+/* Enable various levels of assertions. */
+#if SDL_ASSERT_LEVEL == 0 /* assertions disabled */
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_disabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 1 /* release settings. */
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 2 /* normal settings. */
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
+#else
+# error Unknown assertion level.
+#endif
+
+/* this assertion is never disabled at any level. */
+#define SDL_assert_always(condition) SDL_enabled_assert(condition)
+
+
+/**
+ * A callback that fires when an SDL assertion fails.
+ *
+ * \param data a pointer to the SDL_AssertData structure corresponding to the
+ * current assertion
+ * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler()
+ * \returns an SDL_AssertState value indicating how to handle the failure.
+ */
+typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
+ const SDL_AssertData* data, void* userdata);
+
+/**
+ * Set an application-defined assertion handler.
+ *
+ * This function allows an application to show its own assertion UI and/or
+ * force the response to an assertion failure. If the application doesn't
+ * provide this, SDL will try to do the right thing, popping up a
+ * system-specific GUI dialog, and probably minimizing any fullscreen windows.
+ *
+ * This callback may fire from any thread, but it runs wrapped in a mutex, so
+ * it will only fire from one thread at a time.
+ *
+ * This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
+ *
+ * \param handler the SDL_AssertionHandler function to call when an assertion
+ * fails or NULL for the default handler
+ * \param userdata a pointer that is passed to `handler`
+ *
+ * \sa SDL_GetAssertionHandler
+ */
+extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
+ SDL_AssertionHandler handler,
+ void *userdata);
+
+/**
+ * Get the default assertion handler.
+ *
+ * This returns the function pointer that is called by default when an
+ * assertion is triggered. This is an internal function provided by SDL, that
+ * is used for assertions when SDL_SetAssertionHandler() hasn't been used to
+ * provide a different function.
+ *
+ * \returns the default SDL_AssertionHandler that is called when an assert
+ * triggers.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GetAssertionHandler
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
+
+/**
+ * Get the current assertion handler.
+ *
+ * This returns the function pointer that is called when an assertion is
+ * triggered. This is either the value last passed to
+ * SDL_SetAssertionHandler(), or if no application-specified function is set,
+ * is equivalent to calling SDL_GetDefaultAssertionHandler().
+ *
+ * The parameter `puserdata` is a pointer to a void*, which will store the
+ * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value
+ * will always be NULL for the default handler. If you don't care about this
+ * data, it is safe to pass a NULL pointer to this function to ignore it.
+ *
+ * \param puserdata pointer which is filled with the "userdata" pointer that
+ * was passed to SDL_SetAssertionHandler()
+ * \returns the SDL_AssertionHandler that is called when an assert triggers.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_SetAssertionHandler
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
+
+/**
+ * Get a list of all assertion failures.
+ *
+ * This function gets all assertions triggered since the last call to
+ * SDL_ResetAssertionReport(), or the start of the program.
+ *
+ * The proper way to examine this data looks something like this:
+ *
+ * ```c
+ * const SDL_AssertData *item = SDL_GetAssertionReport();
+ * while (item) {
+ * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n",
+ * item->condition, item->function, item->filename,
+ * item->linenum, item->trigger_count,
+ * item->always_ignore ? "yes" : "no");
+ * item = item->next;
+ * }
+ * ```
+ *
+ * \returns a list of all failed assertions or NULL if the list is empty. This
+ * memory should not be modified or freed by the application.
+ *
+ * \sa SDL_ResetAssertionReport
+ */
+extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
+
+/**
+ * Clear the list of all assertion failures.
+ *
+ * This function will clear the list of all assertions triggered up to that
+ * point. Immediately following this call, SDL_GetAssertionReport will return
+ * no items. In addition, any previously-triggered assertions will be reset to
+ * a trigger_count of zero, and their always_ignore state will be false.
+ *
+ * \sa SDL_GetAssertionReport
+ */
+extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
+
+
+/* these had wrong naming conventions until 2.0.4. Please update your app! */
+#define SDL_assert_state SDL_AssertState
+#define SDL_assert_data SDL_AssertData
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_assert_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_atomic.h b/Client/ThirdParty/SDL2/include/SDL_atomic.h
new file mode 100644
index 0000000..5e1eae7
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_atomic.h
@@ -0,0 +1,379 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_atomic.h
+ *
+ * Atomic operations.
+ *
+ * IMPORTANT:
+ * If you are not an expert in concurrent lockless programming, you should
+ * only be using the atomic lock and reference counting functions in this
+ * file. In all other cases you should be protecting your data structures
+ * with full mutexes.
+ *
+ * The list of "safe" functions to use are:
+ * SDL_AtomicLock()
+ * SDL_AtomicUnlock()
+ * SDL_AtomicIncRef()
+ * SDL_AtomicDecRef()
+ *
+ * Seriously, here be dragons!
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * You can find out a little more about lockless programming and the
+ * subtle issues that can arise here:
+ * http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx
+ *
+ * There's also lots of good information here:
+ * http://www.1024cores.net/home/lock-free-algorithms
+ * http://preshing.com/
+ *
+ * These operations may or may not actually be implemented using
+ * processor specific atomic operations. When possible they are
+ * implemented as true processor specific atomic operations. When that
+ * is not possible the are implemented using locks that *do* use the
+ * available atomic operations.
+ *
+ * All of the atomic operations that modify memory are full memory barriers.
+ */
+
+#ifndef SDL_atomic_h_
+#define SDL_atomic_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_platform.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SDL AtomicLock
+ *
+ * The atomic locks are efficient spinlocks using CPU instructions,
+ * but are vulnerable to starvation and can spin forever if a thread
+ * holding a lock has been terminated. For this reason you should
+ * minimize the code executed inside an atomic lock and never do
+ * expensive things like API or system calls while holding them.
+ *
+ * The atomic locks are not safe to lock recursively.
+ *
+ * Porting Note:
+ * The spin lock functions and type are required and can not be
+ * emulated because they are used in the atomic emulation code.
+ */
+/* @{ */
+
+typedef int SDL_SpinLock;
+
+/**
+ * Try to lock a spin lock by setting it to a non-zero value.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ * \returns SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already
+ * held.
+ *
+ * \sa SDL_AtomicLock
+ * \sa SDL_AtomicUnlock
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
+
+/**
+ * Lock a spin lock by setting it to a non-zero value.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ *
+ * \sa SDL_AtomicTryLock
+ * \sa SDL_AtomicUnlock
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
+
+/**
+ * Unlock a spin lock by setting it to 0.
+ *
+ * Always returns immediately.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicLock
+ * \sa SDL_AtomicTryLock
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
+
+/* @} *//* SDL AtomicLock */
+
+
+/**
+ * The compiler barrier prevents the compiler from reordering
+ * reads and writes to globally visible variables across the call.
+ */
+#if defined(_MSC_VER) && (_MSC_VER > 1200) && !defined(__clang__)
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define SDL_CompilerBarrier() _ReadWriteBarrier()
+#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
+#define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
+#elif defined(__WATCOMC__)
+extern _inline void SDL_CompilerBarrier (void);
+#pragma aux SDL_CompilerBarrier = "" parm [] modify exact [];
+#else
+#define SDL_CompilerBarrier() \
+{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
+#endif
+
+/**
+ * Memory barriers are designed to prevent reads and writes from being
+ * reordered by the compiler and being seen out of order on multi-core CPUs.
+ *
+ * A typical pattern would be for thread A to write some data and a flag, and
+ * for thread B to read the flag and get the data. In this case you would
+ * insert a release barrier between writing the data and the flag,
+ * guaranteeing that the data write completes no later than the flag is
+ * written, and you would insert an acquire barrier between reading the flag
+ * and reading the data, to ensure that all the reads associated with the flag
+ * have completed.
+ *
+ * In this pattern you should always see a release barrier paired with an
+ * acquire barrier and you should gate the data reads/writes with a single
+ * flag variable.
+ *
+ * For more information on these semantics, take a look at the blog post:
+ * http://preshing.com/20120913/acquire-and-release-semantics
+ */
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierReleaseFunction(void);
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
+
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
+#elif defined(__GNUC__) && defined(__aarch64__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__GNUC__) && defined(__arm__)
+#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */
+/* Information from:
+ https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19
+
+ The Linux kernel provides a helper function which provides the right code for a memory barrier,
+ hard-coded at address 0xffff0fa0
+*/
+typedef void (*SDL_KernelMemoryBarrierFunc)();
+#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#elif 0 /* defined(__QNXNTO__) */
+#include <sys/cpuinline.h>
+
+#define SDL_MemoryBarrierRelease() __cpu_membarrier()
+#define SDL_MemoryBarrierAcquire() __cpu_membarrier()
+#else
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__)
+#ifdef __thumb__
+/* The mcr instruction isn't available in thumb mode, use real functions */
+#define SDL_MEMORY_BARRIER_USES_FUNCTION
+#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction()
+#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction()
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#endif /* __thumb__ */
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
+#endif /* __LINUX__ || __ANDROID__ */
+#endif /* __GNUC__ && __arm__ */
+#else
+#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
+#include <mbarrier.h>
+#define SDL_MemoryBarrierRelease() __machine_rel_barrier()
+#define SDL_MemoryBarrierAcquire() __machine_acq_barrier()
+#else
+/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
+#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
+#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
+#endif
+#endif
+
+/**
+ * \brief A type representing an atomic integer value. It is a struct
+ * so people don't accidentally use numeric operations on it.
+ */
+typedef struct { int value; } SDL_atomic_t;
+
+/**
+ * Set an atomic variable to a new value if it is currently an old value.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param oldval the old value
+ * \param newval the new value
+ * \returns SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicGet
+ * \sa SDL_AtomicSet
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
+
+/**
+ * Set an atomic variable to a value.
+ *
+ * This function also acts as a full memory barrier.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param v the desired value
+ * \returns the previous value of the atomic variable.
+ *
+ * \sa SDL_AtomicGet
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int v);
+
+/**
+ * Get the value of an atomic variable.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable
+ * \returns the current value of an atomic variable.
+ *
+ * \sa SDL_AtomicSet
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a);
+
+/**
+ * Add to an atomic variable.
+ *
+ * This function also acts as a full memory barrier.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param v the desired value to add
+ * \returns the previous value of the atomic variable.
+ *
+ * \sa SDL_AtomicDecRef
+ * \sa SDL_AtomicIncRef
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int v);
+
+/**
+ * \brief Increment an atomic variable used as a reference count.
+ */
+#ifndef SDL_AtomicIncRef
+#define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
+#endif
+
+/**
+ * \brief Decrement an atomic variable used as a reference count.
+ *
+ * \return SDL_TRUE if the variable reached zero after decrementing,
+ * SDL_FALSE otherwise
+ */
+#ifndef SDL_AtomicDecRef
+#define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
+#endif
+
+/**
+ * Set a pointer to a new value if it is currently an old value.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \param oldval the old pointer value
+ * \param newval the new pointer value
+ * \returns SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicCAS
+ * \sa SDL_AtomicGetPtr
+ * \sa SDL_AtomicSetPtr
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
+
+/**
+ * Set a pointer to a value atomically.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \param v the desired pointer value
+ * \returns the previous value of the pointer.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicGetPtr
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v);
+
+/**
+ * Get the value of a pointer atomically.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \returns the current value of a pointer.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicSetPtr
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#include "close_code.h"
+
+#endif /* SDL_atomic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_audio.h b/Client/ThirdParty/SDL2/include/SDL_audio.h
new file mode 100644
index 0000000..0aa0017
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_audio.h
@@ -0,0 +1,1185 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* !!! FIXME: several functions in here need Doxygen comments. */
+
+/**
+ * \file SDL_audio.h
+ *
+ * Access to the raw audio mixing buffer for the SDL library.
+ */
+
+#ifndef SDL_audio_h_
+#define SDL_audio_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_endian.h"
+#include "SDL_mutex.h"
+#include "SDL_thread.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Audio format flags.
+ *
+ * These are what the 16 bits in SDL_AudioFormat currently mean...
+ * (Unspecified bits are always zero).
+ *
+ * \verbatim
+ ++-----------------------sample is signed if set
+ ||
+ || ++-----------sample is bigendian if set
+ || ||
+ || || ++---sample is float if set
+ || || ||
+ || || || +---sample bit size---+
+ || || || | |
+ 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+ \endverbatim
+ *
+ * There are macros in SDL 2.0 and later to query these bits.
+ */
+typedef Uint16 SDL_AudioFormat;
+
+/**
+ * \name Audio flags
+ */
+/* @{ */
+
+#define SDL_AUDIO_MASK_BITSIZE (0xFF)
+#define SDL_AUDIO_MASK_DATATYPE (1<<8)
+#define SDL_AUDIO_MASK_ENDIAN (1<<12)
+#define SDL_AUDIO_MASK_SIGNED (1<<15)
+#define SDL_AUDIO_BITSIZE(x) (x & SDL_AUDIO_MASK_BITSIZE)
+#define SDL_AUDIO_ISFLOAT(x) (x & SDL_AUDIO_MASK_DATATYPE)
+#define SDL_AUDIO_ISBIGENDIAN(x) (x & SDL_AUDIO_MASK_ENDIAN)
+#define SDL_AUDIO_ISSIGNED(x) (x & SDL_AUDIO_MASK_SIGNED)
+#define SDL_AUDIO_ISINT(x) (!SDL_AUDIO_ISFLOAT(x))
+#define SDL_AUDIO_ISLITTLEENDIAN(x) (!SDL_AUDIO_ISBIGENDIAN(x))
+#define SDL_AUDIO_ISUNSIGNED(x) (!SDL_AUDIO_ISSIGNED(x))
+
+/**
+ * \name Audio format flags
+ *
+ * Defaults to LSB byte order.
+ */
+/* @{ */
+#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */
+#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */
+#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */
+#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */
+#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */
+#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */
+#define AUDIO_U16 AUDIO_U16LSB
+#define AUDIO_S16 AUDIO_S16LSB
+/* @} */
+
+/**
+ * \name int32 support
+ */
+/* @{ */
+#define AUDIO_S32LSB 0x8020 /**< 32-bit integer samples */
+#define AUDIO_S32MSB 0x9020 /**< As above, but big-endian byte order */
+#define AUDIO_S32 AUDIO_S32LSB
+/* @} */
+
+/**
+ * \name float32 support
+ */
+/* @{ */
+#define AUDIO_F32LSB 0x8120 /**< 32-bit floating point samples */
+#define AUDIO_F32MSB 0x9120 /**< As above, but big-endian byte order */
+#define AUDIO_F32 AUDIO_F32LSB
+/* @} */
+
+/**
+ * \name Native audio byte ordering
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define AUDIO_U16SYS AUDIO_U16LSB
+#define AUDIO_S16SYS AUDIO_S16LSB
+#define AUDIO_S32SYS AUDIO_S32LSB
+#define AUDIO_F32SYS AUDIO_F32LSB
+#else
+#define AUDIO_U16SYS AUDIO_U16MSB
+#define AUDIO_S16SYS AUDIO_S16MSB
+#define AUDIO_S32SYS AUDIO_S32MSB
+#define AUDIO_F32SYS AUDIO_F32MSB
+#endif
+/* @} */
+
+/**
+ * \name Allow change flags
+ *
+ * Which audio format changes are allowed when opening a device.
+ */
+/* @{ */
+#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
+#define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
+#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
+#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0x00000008
+#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)
+/* @} */
+
+/* @} *//* Audio flags */
+
+/**
+ * This function is called when the audio device needs more data.
+ *
+ * \param userdata An application-specific parameter saved in
+ * the SDL_AudioSpec structure
+ * \param stream A pointer to the audio data buffer.
+ * \param len The length of that buffer in bytes.
+ *
+ * Once the callback returns, the buffer will no longer be valid.
+ * Stereo samples are stored in a LRLRLR ordering.
+ *
+ * You can choose to avoid callbacks and use SDL_QueueAudio() instead, if
+ * you like. Just open your audio device with a NULL callback.
+ */
+typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
+ int len);
+
+/**
+ * The calculated values in this structure are calculated by SDL_OpenAudio().
+ *
+ * For multi-channel audio, the default SDL channel mapping is:
+ * 2: FL FR (stereo)
+ * 3: FL FR LFE (2.1 surround)
+ * 4: FL FR BL BR (quad)
+ * 5: FL FR FC BL BR (quad + center)
+ * 6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR)
+ * 7: FL FR FC LFE BC SL SR (6.1 surround)
+ * 8: FL FR FC LFE BL BR SL SR (7.1 surround)
+ */
+typedef struct SDL_AudioSpec
+{
+ int freq; /**< DSP frequency -- samples per second */
+ SDL_AudioFormat format; /**< Audio data format */
+ Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */
+ Uint8 silence; /**< Audio buffer silence value (calculated) */
+ Uint16 samples; /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
+ Uint16 padding; /**< Necessary for some compile environments */
+ Uint32 size; /**< Audio buffer size in bytes (calculated) */
+ SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
+ void *userdata; /**< Userdata passed to callback (ignored for NULL callbacks). */
+} SDL_AudioSpec;
+
+
+struct SDL_AudioCVT;
+typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
+ SDL_AudioFormat format);
+
+/**
+ * \brief Upper limit of filters in SDL_AudioCVT
+ *
+ * The maximum number of SDL_AudioFilter functions in SDL_AudioCVT is
+ * currently limited to 9. The SDL_AudioCVT.filters array has 10 pointers,
+ * one of which is the terminating NULL pointer.
+ */
+#define SDL_AUDIOCVT_MAX_FILTERS 9
+
+/**
+ * \struct SDL_AudioCVT
+ * \brief A structure to hold a set of audio conversion filters and buffers.
+ *
+ * Note that various parts of the conversion pipeline can take advantage
+ * of SIMD operations (like SSE2, for example). SDL_AudioCVT doesn't require
+ * you to pass it aligned data, but can possibly run much faster if you
+ * set both its (buf) field to a pointer that is aligned to 16 bytes, and its
+ * (len) field to something that's a multiple of 16, if possible.
+ */
+#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__)
+/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
+ pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+ This is not a concern on CHERI architectures, where pointers must be stored
+ at aligned locations otherwise they will become invalid, and thus structs
+ containing pointers cannot be packed without giving a warning or error.
+ vvv
+ The next time we rev the ABI, make sure to size the ints and add padding.
+*/
+#define SDL_AUDIOCVT_PACKED __attribute__((packed))
+#else
+#define SDL_AUDIOCVT_PACKED
+#endif
+/* */
+typedef struct SDL_AudioCVT
+{
+ int needed; /**< Set to 1 if conversion possible */
+ SDL_AudioFormat src_format; /**< Source audio format */
+ SDL_AudioFormat dst_format; /**< Target audio format */
+ double rate_incr; /**< Rate conversion increment */
+ Uint8 *buf; /**< Buffer to hold entire audio data */
+ int len; /**< Length of original audio buffer */
+ int len_cvt; /**< Length of converted audio buffer */
+ int len_mult; /**< buffer must be len*len_mult big */
+ double len_ratio; /**< Given len, final size is len*len_ratio */
+ SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */
+ int filter_index; /**< Current audio conversion function */
+} SDL_AUDIOCVT_PACKED SDL_AudioCVT;
+
+
+/* Function prototypes */
+
+/**
+ * \name Driver discovery functions
+ *
+ * These functions return the list of built in audio drivers, in the
+ * order that they are normally initialized by default.
+ */
+/* @{ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
+/* @} */
+
+/**
+ * \name Initialization and cleanup
+ *
+ * \internal These functions are used internally, and should not be used unless
+ * you have a specific need to specify the audio driver you want to
+ * use. You should normally use SDL_Init() or SDL_InitSubSystem().
+ */
+/* @{ */
+extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name);
+extern DECLSPEC void SDLCALL SDL_AudioQuit(void);
+/* @} */
+
+/**
+ * Get the name of the current audio driver.
+ *
+ * The returned string points to internal static memory and thus never becomes
+ * invalid, even if you quit the audio subsystem and initialize a new driver
+ * (although such a case would return a different static string from another
+ * call to this function, of course). As such, you should not modify or free
+ * the returned string.
+ *
+ * \returns the name of the current audio driver or NULL if no driver has been
+ * initialized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AudioInit
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
+
+/**
+ * This function is a legacy means of opening the audio device.
+ *
+ * This function remains for compatibility with SDL 1.2, but also because it's
+ * slightly easier to use than the new functions in SDL 2.0. The new, more
+ * powerful, and preferred way to do this is SDL_OpenAudioDevice().
+ *
+ * This function is roughly equivalent to:
+ *
+ * ```c++
+ * SDL_OpenAudioDevice(NULL, 0, desired, obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
+ * ```
+ *
+ * With two notable exceptions:
+ *
+ * - If `obtained` is NULL, we use `desired` (and allow no changes), which
+ * means desired will be modified to have the correct values for silence,
+ * etc, and SDL will convert any differences between your app's specific
+ * request and the hardware behind the scenes.
+ * - The return value is always success or failure, and not a device ID, which
+ * means you can only have one device open at a time with this function.
+ *
+ * \param desired an SDL_AudioSpec structure representing the desired output
+ * format. Please refer to the SDL_OpenAudioDevice
+ * documentation for details on how to prepare this structure.
+ * \param obtained an SDL_AudioSpec structure filled in with the actual
+ * parameters, or NULL.
+ * \returns 0 if successful, placing the actual hardware parameters in the
+ * structure pointed to by `obtained`.
+ *
+ * If `obtained` is NULL, the audio data passed to the callback
+ * function will be guaranteed to be in the requested format, and
+ * will be automatically converted to the actual hardware audio
+ * format if necessary. If `obtained` is NULL, `desired` will have
+ * fields modified.
+ *
+ * This function returns a negative error code on failure to open the
+ * audio device or failure to set up the audio thread; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CloseAudio
+ * \sa SDL_LockAudio
+ * \sa SDL_PauseAudio
+ * \sa SDL_UnlockAudio
+ */
+extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
+ SDL_AudioSpec * obtained);
+
+/**
+ * SDL Audio Device IDs.
+ *
+ * A successful call to SDL_OpenAudio() is always device id 1, and legacy
+ * SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls
+ * always returns devices >= 2 on success. The legacy calls are good both
+ * for backwards compatibility and when you don't care about multiple,
+ * specific, or capture devices.
+ */
+typedef Uint32 SDL_AudioDeviceID;
+
+/**
+ * Get the number of built-in audio devices.
+ *
+ * This function is only valid after successfully initializing the audio
+ * subsystem.
+ *
+ * Note that audio capture support is not implemented as of SDL 2.0.4, so the
+ * `iscapture` parameter is for future expansion and should always be zero for
+ * now.
+ *
+ * This function will return -1 if an explicit list of devices can't be
+ * determined. Returning -1 is not an error. For example, if SDL is set up to
+ * talk to a remote audio server, it can't list every one available on the
+ * Internet, but it will still allow a specific host to be specified in
+ * SDL_OpenAudioDevice().
+ *
+ * In many common cases, when this function returns a value <= 0, it can still
+ * successfully open the default device (NULL for first argument of
+ * SDL_OpenAudioDevice()).
+ *
+ * This function may trigger a complete redetect of available hardware. It
+ * should not be called for each iteration of a loop, but rather once at the
+ * start of a loop:
+ *
+ * ```c++
+ * // Don't do this:
+ * for (int i = 0; i < SDL_GetNumAudioDevices(0); i++)
+ *
+ * // do this instead:
+ * const int count = SDL_GetNumAudioDevices(0);
+ * for (int i = 0; i < count; ++i) { do_something_here(); }
+ * ```
+ *
+ * \param iscapture zero to request playback devices, non-zero to request
+ * recording devices
+ * \returns the number of available devices exposed by the current driver or
+ * -1 if an explicit list of devices can't be determined. A return
+ * value of -1 does not necessarily mean an error condition.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture);
+
+/**
+ * Get the human-readable name of a specific audio device.
+ *
+ * This function is only valid after successfully initializing the audio
+ * subsystem. The values returned by this function reflect the latest call to
+ * SDL_GetNumAudioDevices(); re-call that function to redetect available
+ * hardware.
+ *
+ * The string returned by this function is UTF-8 encoded, read-only, and
+ * managed internally. You are not to free it. If you need to keep the string
+ * for any length of time, you should make your own copy of it, as it will be
+ * invalid next time any of several other SDL functions are called.
+ *
+ * \param index the index of the audio device; valid values range from 0 to
+ * SDL_GetNumAudioDevices() - 1
+ * \param iscapture non-zero to query the list of recording devices, zero to
+ * query the list of output devices.
+ * \returns the name of the audio device at the requested index, or NULL on
+ * error.
+ *
+ * \sa SDL_GetNumAudioDevices
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index,
+ int iscapture);
+
+/**
+ * Get the preferred audio format of a specific audio device.
+ *
+ * This function is only valid after a successfully initializing the audio
+ * subsystem. The values returned by this function reflect the latest call to
+ * SDL_GetNumAudioDevices(); re-call that function to redetect available
+ * hardware.
+ *
+ * `spec` will be filled with the sample rate, sample format, and channel
+ * count. All other values in the structure are filled with 0. When the
+ * supported struct members are 0, SDL was unable to get the property from the
+ * backend.
+ *
+ * \param index the index of the audio device; valid values range from 0 to
+ * SDL_GetNumAudioDevices() - 1
+ * \param iscapture non-zero to query the list of recording devices, zero to
+ * query the list of output devices.
+ * \param spec The SDL_AudioSpec to be initialized by this function.
+ * \returns 0 on success, nonzero on error
+ *
+ * \sa SDL_GetNumAudioDevices
+ */
+extern DECLSPEC int SDLCALL SDL_GetAudioDeviceSpec(int index,
+ int iscapture,
+ SDL_AudioSpec *spec);
+
+
+/**
+ * Open a specific audio device.
+ *
+ * SDL_OpenAudio(), unlike this function, always acts on device ID 1. As such,
+ * this function will never return a 1 so as not to conflict with the legacy
+ * function.
+ *
+ * Please note that SDL 2.0 before 2.0.5 did not support recording; as such,
+ * this function would fail if `iscapture` was not zero. Starting with SDL
+ * 2.0.5, recording is implemented and this value can be non-zero.
+ *
+ * Passing in a `device` name of NULL requests the most reasonable default
+ * (and is equivalent to what SDL_OpenAudio() does to choose a device). The
+ * `device` name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but
+ * some drivers allow arbitrary and driver-specific strings, such as a
+ * hostname/IP address for a remote audio server, or a filename in the
+ * diskaudio driver.
+ *
+ * When filling in the desired audio spec structure:
+ *
+ * - `desired->freq` should be the frequency in sample-frames-per-second (Hz).
+ * - `desired->format` should be the audio format (`AUDIO_S16SYS`, etc).
+ * - `desired->samples` is the desired size of the audio buffer, in _sample
+ * frames_ (with stereo output, two samples--left and right--would make a
+ * single sample frame). This number should be a power of two, and may be
+ * adjusted by the audio driver to a value more suitable for the hardware.
+ * Good values seem to range between 512 and 8096 inclusive, depending on
+ * the application and CPU speed. Smaller values reduce latency, but can
+ * lead to underflow if the application is doing heavy processing and cannot
+ * fill the audio buffer in time. Note that the number of sample frames is
+ * directly related to time by the following formula: `ms =
+ * (sampleframes*1000)/freq`
+ * - `desired->size` is the size in _bytes_ of the audio buffer, and is
+ * calculated by SDL_OpenAudioDevice(). You don't initialize this.
+ * - `desired->silence` is the value used to set the buffer to silence, and is
+ * calculated by SDL_OpenAudioDevice(). You don't initialize this.
+ * - `desired->callback` should be set to a function that will be called when
+ * the audio device is ready for more data. It is passed a pointer to the
+ * audio buffer, and the length in bytes of the audio buffer. This function
+ * usually runs in a separate thread, and so you should protect data
+ * structures that it accesses by calling SDL_LockAudioDevice() and
+ * SDL_UnlockAudioDevice() in your code. Alternately, you may pass a NULL
+ * pointer here, and call SDL_QueueAudio() with some frequency, to queue
+ * more audio samples to be played (or for capture devices, call
+ * SDL_DequeueAudio() with some frequency, to obtain audio samples).
+ * - `desired->userdata` is passed as the first parameter to your callback
+ * function. If you passed a NULL callback, this value is ignored.
+ *
+ * `allowed_changes` can have the following flags OR'd together:
+ *
+ * - `SDL_AUDIO_ALLOW_FREQUENCY_CHANGE`
+ * - `SDL_AUDIO_ALLOW_FORMAT_CHANGE`
+ * - `SDL_AUDIO_ALLOW_CHANNELS_CHANGE`
+ * - `SDL_AUDIO_ALLOW_ANY_CHANGE`
+ *
+ * These flags specify how SDL should behave when a device cannot offer a
+ * specific feature. If the application requests a feature that the hardware
+ * doesn't offer, SDL will always try to get the closest equivalent.
+ *
+ * For example, if you ask for float32 audio format, but the sound card only
+ * supports int16, SDL will set the hardware to int16. If you had set
+ * SDL_AUDIO_ALLOW_FORMAT_CHANGE, SDL will change the format in the `obtained`
+ * structure. If that flag was *not* set, SDL will prepare to convert your
+ * callback's float32 audio to int16 before feeding it to the hardware and
+ * will keep the originally requested format in the `obtained` structure.
+ *
+ * If your application can only handle one specific data format, pass a zero
+ * for `allowed_changes` and let SDL transparently handle any differences.
+ *
+ * An opened audio device starts out paused, and should be enabled for playing
+ * by calling SDL_PauseAudioDevice(devid, 0) when you are ready for your audio
+ * callback function to be called. Since the audio driver may modify the
+ * requested size of the audio buffer, you should allocate any local mixing
+ * buffers after you open the audio device.
+ *
+ * The audio callback runs in a separate thread in most cases; you can prevent
+ * race conditions between your callback and other threads without fully
+ * pausing playback with SDL_LockAudioDevice(). For more information about the
+ * callback, see SDL_AudioSpec.
+ *
+ * \param device a UTF-8 string reported by SDL_GetAudioDeviceName() or a
+ * driver-specific name as appropriate. NULL requests the most
+ * reasonable default device.
+ * \param iscapture non-zero to specify a device should be opened for
+ * recording, not playback
+ * \param desired an SDL_AudioSpec structure representing the desired output
+ * format; see SDL_OpenAudio() for more information
+ * \param obtained an SDL_AudioSpec structure filled in with the actual output
+ * format; see SDL_OpenAudio() for more information
+ * \param allowed_changes 0, or one or more flags OR'd together
+ * \returns a valid device ID that is > 0 on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * For compatibility with SDL 1.2, this will never return 1, since
+ * SDL reserves that ID for the legacy SDL_OpenAudio() function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CloseAudioDevice
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_LockAudioDevice
+ * \sa SDL_OpenAudio
+ * \sa SDL_PauseAudioDevice
+ * \sa SDL_UnlockAudioDevice
+ */
+extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(
+ const char *device,
+ int iscapture,
+ const SDL_AudioSpec *desired,
+ SDL_AudioSpec *obtained,
+ int allowed_changes);
+
+
+
+/**
+ * \name Audio state
+ *
+ * Get the current audio state.
+ */
+/* @{ */
+typedef enum
+{
+ SDL_AUDIO_STOPPED = 0,
+ SDL_AUDIO_PLAYING,
+ SDL_AUDIO_PAUSED
+} SDL_AudioStatus;
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioStatus(void);
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
+/* @} *//* Audio State */
+
+/**
+ * \name Pause audio functions
+ *
+ * These functions pause and unpause the audio callback processing.
+ * They should be called with a parameter of 0 after opening the audio
+ * device to start playing sound. This is so you can safely initialize
+ * data for your callback function after opening the audio device.
+ * Silence will be written to the audio device during the pause.
+ */
+/* @{ */
+extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on);
+extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
+ int pause_on);
+/* @} *//* Pause audio functions */
+
+/**
+ * Load the audio data of a WAVE file into memory.
+ *
+ * Loading a WAVE file requires `src`, `spec`, `audio_buf` and `audio_len` to
+ * be valid pointers. The entire data portion of the file is then loaded into
+ * memory and decoded if necessary.
+ *
+ * If `freesrc` is non-zero, the data source gets automatically closed and
+ * freed before the function returns.
+ *
+ * Supported formats are RIFF WAVE files with the formats PCM (8, 16, 24, and
+ * 32 bits), IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and
+ * A-law and mu-law (8 bits). Other formats are currently unsupported and
+ * cause an error.
+ *
+ * If this function succeeds, the pointer returned by it is equal to `spec`
+ * and the pointer to the audio data allocated by the function is written to
+ * `audio_buf` and its length in bytes to `audio_len`. The SDL_AudioSpec
+ * members `freq`, `channels`, and `format` are set to the values of the audio
+ * data in the buffer. The `samples` member is set to a sane default and all
+ * others are set to zero.
+ *
+ * It's necessary to use SDL_FreeWAV() to free the audio data returned in
+ * `audio_buf` when it is no longer used.
+ *
+ * Because of the underspecification of the .WAV format, there are many
+ * problematic files in the wild that cause issues with strict decoders. To
+ * provide compatibility with these files, this decoder is lenient in regards
+ * to the truncation of the file, the fact chunk, and the size of the RIFF
+ * chunk. The hints `SDL_HINT_WAVE_RIFF_CHUNK_SIZE`,
+ * `SDL_HINT_WAVE_TRUNCATION`, and `SDL_HINT_WAVE_FACT_CHUNK` can be used to
+ * tune the behavior of the loading process.
+ *
+ * Any file that is invalid (due to truncation, corruption, or wrong values in
+ * the headers), too big, or unsupported causes an error. Additionally, any
+ * critical I/O error from the data source will terminate the loading process
+ * with an error. The function returns NULL on error and in all cases (with
+ * the exception of `src` being NULL), an appropriate error message will be
+ * set.
+ *
+ * It is required that the data source supports seeking.
+ *
+ * Example:
+ *
+ * ```c++
+ * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, &spec, &buf, &len);
+ * ```
+ *
+ * Note that the SDL_LoadWAV macro does this same thing for you, but in a less
+ * messy way:
+ *
+ * ```c++
+ * SDL_LoadWAV("sample.wav", &spec, &buf, &len);
+ * ```
+ *
+ * \param src The data source for the WAVE data
+ * \param freesrc If non-zero, SDL will _always_ free the data source
+ * \param spec An SDL_AudioSpec that will be filled in with the wave file's
+ * format details
+ * \param audio_buf A pointer filled with the audio data, allocated by the
+ * function.
+ * \param audio_len A pointer filled with the length of the audio data buffer
+ * in bytes
+ * \returns This function, if successfully called, returns `spec`, which will
+ * be filled with the audio data format of the wave source data.
+ * `audio_buf` will be filled with a pointer to an allocated buffer
+ * containing the audio data, and `audio_len` is filled with the
+ * length of that audio buffer in bytes.
+ *
+ * This function returns NULL if the .WAV file cannot be opened, uses
+ * an unknown data format, or is corrupt; call SDL_GetError() for
+ * more information.
+ *
+ * When the application is done with the data returned in
+ * `audio_buf`, it should call SDL_FreeWAV() to dispose of it.
+ *
+ * \sa SDL_FreeWAV
+ * \sa SDL_LoadWAV
+ */
+extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
+ int freesrc,
+ SDL_AudioSpec * spec,
+ Uint8 ** audio_buf,
+ Uint32 * audio_len);
+
+/**
+ * Loads a WAV from a file.
+ * Compatibility convenience function.
+ */
+#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
+ SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
+
+/**
+ * Free data previously allocated with SDL_LoadWAV() or SDL_LoadWAV_RW().
+ *
+ * After a WAVE file has been opened with SDL_LoadWAV() or SDL_LoadWAV_RW()
+ * its data can eventually be freed with SDL_FreeWAV(). It is safe to call
+ * this function with a NULL pointer.
+ *
+ * \param audio_buf a pointer to the buffer created by SDL_LoadWAV() or
+ * SDL_LoadWAV_RW()
+ *
+ * \sa SDL_LoadWAV
+ * \sa SDL_LoadWAV_RW
+ */
+extern DECLSPEC void SDLCALL SDL_FreeWAV(Uint8 * audio_buf);
+
+/**
+ * Initialize an SDL_AudioCVT structure for conversion.
+ *
+ * Before an SDL_AudioCVT structure can be used to convert audio data it must
+ * be initialized with source and destination information.
+ *
+ * This function will zero out every field of the SDL_AudioCVT, so it must be
+ * called before the application fills in the final buffer information.
+ *
+ * Once this function has returned successfully, and reported that a
+ * conversion is necessary, the application fills in the rest of the fields in
+ * SDL_AudioCVT, now that it knows how large a buffer it needs to allocate,
+ * and then can call SDL_ConvertAudio() to complete the conversion.
+ *
+ * \param cvt an SDL_AudioCVT structure filled in with audio conversion
+ * information
+ * \param src_format the source format of the audio data; for more info see
+ * SDL_AudioFormat
+ * \param src_channels the number of channels in the source
+ * \param src_rate the frequency (sample-frames-per-second) of the source
+ * \param dst_format the destination format of the audio data; for more info
+ * see SDL_AudioFormat
+ * \param dst_channels the number of channels in the destination
+ * \param dst_rate the frequency (sample-frames-per-second) of the destination
+ * \returns 1 if the audio filter is prepared, 0 if no conversion is needed,
+ * or a negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_ConvertAudio
+ */
+extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
+ SDL_AudioFormat src_format,
+ Uint8 src_channels,
+ int src_rate,
+ SDL_AudioFormat dst_format,
+ Uint8 dst_channels,
+ int dst_rate);
+
+/**
+ * Convert audio data to a desired audio format.
+ *
+ * This function does the actual audio data conversion, after the application
+ * has called SDL_BuildAudioCVT() to prepare the conversion information and
+ * then filled in the buffer details.
+ *
+ * Once the application has initialized the `cvt` structure using
+ * SDL_BuildAudioCVT(), allocated an audio buffer and filled it with audio
+ * data in the source format, this function will convert the buffer, in-place,
+ * to the desired format.
+ *
+ * The data conversion may go through several passes; any given pass may
+ * possibly temporarily increase the size of the data. For example, SDL might
+ * expand 16-bit data to 32 bits before resampling to a lower frequency,
+ * shrinking the data size after having grown it briefly. Since the supplied
+ * buffer will be both the source and destination, converting as necessary
+ * in-place, the application must allocate a buffer that will fully contain
+ * the data during its largest conversion pass. After SDL_BuildAudioCVT()
+ * returns, the application should set the `cvt->len` field to the size, in
+ * bytes, of the source data, and allocate a buffer that is `cvt->len *
+ * cvt->len_mult` bytes long for the `buf` field.
+ *
+ * The source data should be copied into this buffer before the call to
+ * SDL_ConvertAudio(). Upon successful return, this buffer will contain the
+ * converted audio, and `cvt->len_cvt` will be the size of the converted data,
+ * in bytes. Any bytes in the buffer past `cvt->len_cvt` are undefined once
+ * this function returns.
+ *
+ * \param cvt an SDL_AudioCVT structure that was previously set up by
+ * SDL_BuildAudioCVT().
+ * \returns 0 if the conversion was completed successfully or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_BuildAudioCVT
+ */
+extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt);
+
+/* SDL_AudioStream is a new audio conversion interface.
+ The benefits vs SDL_AudioCVT:
+ - it can handle resampling data in chunks without generating
+ artifacts, when it doesn't have the complete buffer available.
+ - it can handle incoming data in any variable size.
+ - You push data as you have it, and pull it when you need it
+ */
+/* this is opaque to the outside world. */
+struct _SDL_AudioStream;
+typedef struct _SDL_AudioStream SDL_AudioStream;
+
+/**
+ * Create a new audio stream.
+ *
+ * \param src_format The format of the source audio
+ * \param src_channels The number of channels of the source audio
+ * \param src_rate The sampling rate of the source audio
+ * \param dst_format The format of the desired audio output
+ * \param dst_channels The number of channels of the desired audio output
+ * \param dst_rate The sampling rate of the desired audio output
+ * \returns 0 on success, or -1 on error.
+ *
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC SDL_AudioStream * SDLCALL SDL_NewAudioStream(const SDL_AudioFormat src_format,
+ const Uint8 src_channels,
+ const int src_rate,
+ const SDL_AudioFormat dst_format,
+ const Uint8 dst_channels,
+ const int dst_rate);
+
+/**
+ * Add data to be converted/resampled to the stream.
+ *
+ * \param stream The stream the audio data is being added to
+ * \param buf A pointer to the audio data to add
+ * \param len The number of bytes to write to the stream
+ * \returns 0 on success, or -1 on error.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len);
+
+/**
+ * Get converted/resampled data from the stream
+ *
+ * \param stream The stream the audio is being requested from
+ * \param buf A buffer to fill with audio data
+ * \param len The maximum number of bytes to fill
+ * \returns the number of bytes read from the stream, or -1 on error
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len);
+
+/**
+ * Get the number of converted/resampled bytes available.
+ *
+ * The stream may be buffering data behind the scenes until it has enough to
+ * resample correctly, so this number might be lower than what you expect, or
+ * even be zero. Add more data or flush the stream if you need the data now.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamAvailable(SDL_AudioStream *stream);
+
+/**
+ * Tell the stream that you're done sending data, and anything being buffered
+ * should be converted/resampled and made available immediately.
+ *
+ * It is legal to add more data to a stream after flushing, but there will be
+ * audio gaps in the output. Generally this is intended to signal the end of
+ * input, so the complete output becomes available.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamFlush(SDL_AudioStream *stream);
+
+/**
+ * Clear any pending data in the stream without converting it
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC void SDLCALL SDL_AudioStreamClear(SDL_AudioStream *stream);
+
+/**
+ * Free an audio stream
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ */
+extern DECLSPEC void SDLCALL SDL_FreeAudioStream(SDL_AudioStream *stream);
+
+#define SDL_MIX_MAXVOLUME 128
+/**
+ * This function is a legacy means of mixing audio.
+ *
+ * This function is equivalent to calling
+ *
+ * ```c++
+ * SDL_MixAudioFormat(dst, src, format, len, volume);
+ * ```
+ *
+ * where `format` is the obtained format of the audio device from the legacy
+ * SDL_OpenAudio() function.
+ *
+ * \param dst the destination for the mixed audio
+ * \param src the source audio buffer to be mixed
+ * \param len the length of the audio buffer in bytes
+ * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+ * for full audio volume
+ *
+ * \sa SDL_MixAudioFormat
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src,
+ Uint32 len, int volume);
+
+/**
+ * Mix audio data in a specified format.
+ *
+ * This takes an audio buffer `src` of `len` bytes of `format` data and mixes
+ * it into `dst`, performing addition, volume adjustment, and overflow
+ * clipping. The buffer pointed to by `dst` must also be `len` bytes of
+ * `format` data.
+ *
+ * This is provided for convenience -- you can mix your own audio data.
+ *
+ * Do not use this function for mixing together more than two streams of
+ * sample data. The output from repeated application of this function may be
+ * distorted by clipping, because there is no accumulator with greater range
+ * than the input (not to mention this being an inefficient way of doing it).
+ *
+ * It is a common misconception that this function is required to write audio
+ * data to an output stream in an audio callback. While you can do that,
+ * SDL_MixAudioFormat() is really only needed when you're mixing a single
+ * audio stream with a volume adjustment.
+ *
+ * \param dst the destination for the mixed audio
+ * \param src the source audio buffer to be mixed
+ * \param format the SDL_AudioFormat structure representing the desired audio
+ * format
+ * \param len the length of the audio buffer in bytes
+ * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+ * for full audio volume
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
+ const Uint8 * src,
+ SDL_AudioFormat format,
+ Uint32 len, int volume);
+
+/**
+ * Queue more audio on non-callback devices.
+ *
+ * If you are looking to retrieve queued audio from a non-callback capture
+ * device, you want SDL_DequeueAudio() instead. SDL_QueueAudio() will return
+ * -1 to signify an error if you use it with capture devices.
+ *
+ * SDL offers two ways to feed audio to the device: you can either supply a
+ * callback that SDL triggers with some frequency to obtain more audio (pull
+ * method), or you can supply no callback, and then SDL will expect you to
+ * supply data at regular intervals (push method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Queued data will drain to the device as
+ * necessary without further intervention from you. If the device needs audio
+ * but there is not enough queued, it will play silence to make up the
+ * difference. This means you will have skips in your audio playback if you
+ * aren't routinely queueing sufficient data.
+ *
+ * This function copies the supplied data, so you are safe to free it when the
+ * function returns. This function is thread-safe, but queueing to the same
+ * device from two threads at once does not promise which buffer will be
+ * queued first.
+ *
+ * You may not queue audio on a device that is using an application-supplied
+ * callback; doing so returns an error. You have to use the audio callback or
+ * queue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before queueing; SDL
+ * handles locking internally for this function.
+ *
+ * Note that SDL2
+ * [https://discourse.libsdl.org/t/sdl2-support-for-planar-audio/31263/3 does
+ * not support planar audio]. You will need to resample from planar audio
+ * formats into a non-planar one (see SDL_AudioFormat) before queuing audio.
+ *
+ * \param dev the device ID to which we will queue audio
+ * \param data the data to queue to the device for later playback
+ * \param len the number of bytes (not samples!) to which `data` points
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
+
+/**
+ * Dequeue more audio on non-callback devices.
+ *
+ * If you are looking to queue audio for output on a non-callback playback
+ * device, you want SDL_QueueAudio() instead. SDL_DequeueAudio() will always
+ * return 0 if you use it with playback devices.
+ *
+ * SDL offers two ways to retrieve audio from a capture device: you can either
+ * supply a callback that SDL triggers with some frequency as the device
+ * records more audio data, (push method), or you can supply no callback, and
+ * then SDL will expect you to retrieve data at regular intervals (pull
+ * method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Data from the device will keep queuing as
+ * necessary without further intervention from you. This means you will
+ * eventually run out of memory if you aren't routinely dequeueing data.
+ *
+ * Capture devices will not queue data when paused; if you are expecting to
+ * not need captured audio for some length of time, use SDL_PauseAudioDevice()
+ * to stop the capture device from queueing more data. This can be useful
+ * during, say, level loading times. When unpaused, capture devices will start
+ * queueing data from that point, having flushed any capturable data available
+ * while paused.
+ *
+ * This function is thread-safe, but dequeueing from the same device from two
+ * threads at once does not promise which thread will dequeue data first.
+ *
+ * You may not dequeue audio from a device that is using an
+ * application-supplied callback; doing so returns an error. You have to use
+ * the audio callback, or dequeue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before dequeueing; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev the device ID from which we will dequeue audio
+ * \param data a pointer into where audio data should be copied
+ * \param len the number of bytes (not samples!) to which (data) points
+ * \returns the number of bytes dequeued, which could be less than requested;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_DequeueAudio(SDL_AudioDeviceID dev, void *data, Uint32 len);
+
+/**
+ * Get the number of bytes of still-queued audio.
+ *
+ * For playback devices: this is the number of bytes that have been queued for
+ * playback with SDL_QueueAudio(), but have not yet been sent to the hardware.
+ *
+ * Once we've sent it to the hardware, this function can not decide the exact
+ * byte boundary of what has been played. It's possible that we just gave the
+ * hardware several kilobytes right before you called this function, but it
+ * hasn't played any of it yet, or maybe half of it, etc.
+ *
+ * For capture devices, this is the number of bytes that have been captured by
+ * the device and are waiting for you to dequeue. This number may grow at any
+ * time, so this only informs of the lower-bound of available data.
+ *
+ * You may not queue or dequeue audio on a device that is using an
+ * application-supplied callback; calling this function on such a device
+ * always returns 0. You have to use the audio callback or queue audio, but
+ * not both.
+ *
+ * You should not call SDL_LockAudio() on the device before querying; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev the device ID of which we will query queued audio size
+ * \returns the number of bytes (not samples!) of queued audio.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_QueueAudio
+ * \sa SDL_DequeueAudio
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
+
+/**
+ * Drop any queued audio data waiting to be sent to the hardware.
+ *
+ * Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For
+ * output devices, the hardware will start playing silence if more audio isn't
+ * queued. For capture devices, the hardware will start filling the empty
+ * queue with new data if the capture device isn't paused.
+ *
+ * This will not prevent playback of queued audio that's already been sent to
+ * the hardware, as we can not undo that, so expect there to be some fraction
+ * of a second of audio that might still be heard. This can be useful if you
+ * want to, say, drop any pending music or any unprocessed microphone input
+ * during a level change in your game.
+ *
+ * You may not queue or dequeue audio on a device that is using an
+ * application-supplied callback; calling this function on such a device
+ * always returns 0. You have to use the audio callback or queue audio, but
+ * not both.
+ *
+ * You should not call SDL_LockAudio() on the device before clearing the
+ * queue; SDL handles locking internally for this function.
+ *
+ * This function always succeeds and thus returns void.
+ *
+ * \param dev the device ID of which to clear the audio queue
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetQueuedAudioSize
+ * \sa SDL_QueueAudio
+ * \sa SDL_DequeueAudio
+ */
+extern DECLSPEC void SDLCALL SDL_ClearQueuedAudio(SDL_AudioDeviceID dev);
+
+
+/**
+ * \name Audio lock functions
+ *
+ * The lock manipulated by these functions protects the callback function.
+ * During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that
+ * the callback function is not running. Do not call these from the callback
+ * function or you will cause deadlock.
+ */
+/* @{ */
+extern DECLSPEC void SDLCALL SDL_LockAudio(void);
+extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev);
+extern DECLSPEC void SDLCALL SDL_UnlockAudio(void);
+extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
+/* @} *//* Audio lock functions */
+
+/**
+ * This function is a legacy means of closing the audio device.
+ *
+ * This function is equivalent to calling
+ *
+ * ```c++
+ * SDL_CloseAudioDevice(1);
+ * ```
+ *
+ * and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \sa SDL_OpenAudio
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudio(void);
+
+/**
+ * Use this function to shut down audio processing and close the audio device.
+ *
+ * The application should close open audio devices once they are no longer
+ * needed. Calling this function will wait until the device's audio callback
+ * is not running, release the audio hardware and then clean up internal
+ * state. No further audio will play from this device once this function
+ * returns.
+ *
+ * This function may block briefly while pending audio data is played by the
+ * hardware, so that applications don't drop the last buffer of data they
+ * supplied.
+ *
+ * The device ID is invalid as soon as the device is closed, and is eligible
+ * for reuse in a new SDL_OpenAudioDevice() call immediately.
+ *
+ * \param dev an audio device previously opened with SDL_OpenAudioDevice()
+ *
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_audio_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_bits.h b/Client/ThirdParty/SDL2/include/SDL_bits.h
new file mode 100644
index 0000000..553b687
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_bits.h
@@ -0,0 +1,126 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_bits.h
+ *
+ * Functions for fiddling with bits and bitmasks.
+ */
+
+#ifndef SDL_bits_h_
+#define SDL_bits_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_bits.h
+ */
+
+/**
+ * Get the index of the most significant bit. Result is undefined when called
+ * with 0. This operation can also be stated as "count leading zeroes" and
+ * "log base 2".
+ *
+ * \return the index of the most significant bit, or -1 if the value is 0.
+ */
+#if defined(__WATCOMC__) && defined(__386__)
+extern _inline int _SDL_bsr_watcom (Uint32);
+#pragma aux _SDL_bsr_watcom = \
+ "bsr eax, eax" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+SDL_FORCE_INLINE int
+SDL_MostSignificantBitIndex32(Uint32 x)
+{
+#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+ /* Count Leading Zeroes builtin in GCC.
+ * http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
+ */
+ if (x == 0) {
+ return -1;
+ }
+ return 31 - __builtin_clz(x);
+#elif defined(__WATCOMC__) && defined(__386__)
+ if (x == 0) {
+ return -1;
+ }
+ return _SDL_bsr_watcom(x);
+#elif defined(_MSC_VER)
+ unsigned long index;
+ if (_BitScanReverse(&index, x)) {
+ return index;
+ }
+ return -1;
+#else
+ /* Based off of Bit Twiddling Hacks by Sean Eron Anderson
+ * <seander@cs.stanford.edu>, released in the public domain.
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
+ */
+ const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+ const int S[] = {1, 2, 4, 8, 16};
+
+ int msbIndex = 0;
+ int i;
+
+ if (x == 0) {
+ return -1;
+ }
+
+ for (i = 4; i >= 0; i--)
+ {
+ if (x & b[i])
+ {
+ x >>= S[i];
+ msbIndex |= S[i];
+ }
+ }
+
+ return msbIndex;
+#endif
+}
+
+SDL_FORCE_INLINE SDL_bool
+SDL_HasExactlyOneBitSet32(Uint32 x)
+{
+ if (x && !(x & (x - 1))) {
+ return SDL_TRUE;
+ }
+ return SDL_FALSE;
+}
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_bits_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_blendmode.h b/Client/ThirdParty/SDL2/include/SDL_blendmode.h
new file mode 100644
index 0000000..374f225
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_blendmode.h
@@ -0,0 +1,200 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_blendmode.h
+ *
+ * Header file declaring the SDL_BlendMode enumeration
+ */
+
+#ifndef SDL_blendmode_h_
+#define SDL_blendmode_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The blend mode used in SDL_RenderCopy() and drawing operations.
+ */
+typedef enum
+{
+ SDL_BLENDMODE_NONE = 0x00000000, /**< no blending
+ dstRGBA = srcRGBA */
+ SDL_BLENDMODE_BLEND = 0x00000001, /**< alpha blending
+ dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+ dstA = srcA + (dstA * (1-srcA)) */
+ SDL_BLENDMODE_ADD = 0x00000002, /**< additive blending
+ dstRGB = (srcRGB * srcA) + dstRGB
+ dstA = dstA */
+ SDL_BLENDMODE_MOD = 0x00000004, /**< color modulate
+ dstRGB = srcRGB * dstRGB
+ dstA = dstA */
+ SDL_BLENDMODE_MUL = 0x00000008, /**< color multiply
+ dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
+ dstA = (srcA * dstA) + (dstA * (1-srcA)) */
+ SDL_BLENDMODE_INVALID = 0x7FFFFFFF
+
+ /* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */
+
+} SDL_BlendMode;
+
+/**
+ * \brief The blend operation used when combining source and destination pixel components
+ */
+typedef enum
+{
+ SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
+ SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
+ SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D11 */
+ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D11 */
+
+} SDL_BlendOperation;
+
+/**
+ * \brief The normalized factor used to multiply pixel components
+ */
+typedef enum
+{
+ SDL_BLENDFACTOR_ZERO = 0x1, /**< 0, 0, 0, 0 */
+ SDL_BLENDFACTOR_ONE = 0x2, /**< 1, 1, 1, 1 */
+ SDL_BLENDFACTOR_SRC_COLOR = 0x3, /**< srcR, srcG, srcB, srcA */
+ SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4, /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
+ SDL_BLENDFACTOR_SRC_ALPHA = 0x5, /**< srcA, srcA, srcA, srcA */
+ SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6, /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
+ SDL_BLENDFACTOR_DST_COLOR = 0x7, /**< dstR, dstG, dstB, dstA */
+ SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
+ SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
+ SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
+
+} SDL_BlendFactor;
+
+/**
+ * Compose a custom blend mode for renderers.
+ *
+ * The functions SDL_SetRenderDrawBlendMode and SDL_SetTextureBlendMode accept
+ * the SDL_BlendMode returned by this function if the renderer supports it.
+ *
+ * A blend mode controls how the pixels from a drawing operation (source) get
+ * combined with the pixels from the render target (destination). First, the
+ * components of the source and destination pixels get multiplied with their
+ * blend factors. Then, the blend operation takes the two products and
+ * calculates the result that will get stored in the render target.
+ *
+ * Expressed in pseudocode, it would look like this:
+ *
+ * ```c
+ * dstRGB = colorOperation(srcRGB * srcColorFactor, dstRGB * dstColorFactor);
+ * dstA = alphaOperation(srcA * srcAlphaFactor, dstA * dstAlphaFactor);
+ * ```
+ *
+ * Where the functions `colorOperation(src, dst)` and `alphaOperation(src,
+ * dst)` can return one of the following:
+ *
+ * - `src + dst`
+ * - `src - dst`
+ * - `dst - src`
+ * - `min(src, dst)`
+ * - `max(src, dst)`
+ *
+ * The red, green, and blue components are always multiplied with the first,
+ * second, and third components of the SDL_BlendFactor, respectively. The
+ * fourth component is not used.
+ *
+ * The alpha component is always multiplied with the fourth component of the
+ * SDL_BlendFactor. The other components are not used in the alpha
+ * calculation.
+ *
+ * Support for these blend modes varies for each renderer. To check if a
+ * specific SDL_BlendMode is supported, create a renderer and pass it to
+ * either SDL_SetRenderDrawBlendMode or SDL_SetTextureBlendMode. They will
+ * return with an error if the blend mode is not supported.
+ *
+ * This list describes the support of custom blend modes for each renderer in
+ * SDL 2.0.6. All renderers support the four blend modes listed in the
+ * SDL_BlendMode enumeration.
+ *
+ * - **direct3d**: Supports `SDL_BLENDOPERATION_ADD` with all factors.
+ * - **direct3d11**: Supports all operations with all factors. However, some
+ * factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
+ * `SDL_BLENDOPERATION_MAXIMUM`.
+ * - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
+ * factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL
+ * 2.0.6.
+ * - **opengles**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
+ * factors. Color and alpha factors need to be the same. OpenGL ES 1
+ * implementation specific: May also support `SDL_BLENDOPERATION_SUBTRACT`
+ * and `SDL_BLENDOPERATION_REV_SUBTRACT`. May support color and alpha
+ * operations being different from each other. May support color and alpha
+ * factors being different from each other.
+ * - **opengles2**: Supports the `SDL_BLENDOPERATION_ADD`,
+ * `SDL_BLENDOPERATION_SUBTRACT`, `SDL_BLENDOPERATION_REV_SUBTRACT`
+ * operations with all factors.
+ * - **psp**: No custom blend mode support.
+ * - **software**: No custom blend mode support.
+ *
+ * Some renderers do not provide an alpha component for the default render
+ * target. The `SDL_BLENDFACTOR_DST_ALPHA` and
+ * `SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA` factors do not have an effect in this
+ * case.
+ *
+ * \param srcColorFactor the SDL_BlendFactor applied to the red, green, and
+ * blue components of the source pixels
+ * \param dstColorFactor the SDL_BlendFactor applied to the red, green, and
+ * blue components of the destination pixels
+ * \param colorOperation the SDL_BlendOperation used to combine the red,
+ * green, and blue components of the source and
+ * destination pixels
+ * \param srcAlphaFactor the SDL_BlendFactor applied to the alpha component of
+ * the source pixels
+ * \param dstAlphaFactor the SDL_BlendFactor applied to the alpha component of
+ * the destination pixels
+ * \param alphaOperation the SDL_BlendOperation used to combine the alpha
+ * component of the source and destination pixels
+ * \returns an SDL_BlendMode that represents the chosen factors and
+ * operations.
+ *
+ * \since This function is available in SDL 2.0.6.
+ *
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_GetRenderDrawBlendMode
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_GetTextureBlendMode
+ */
+extern DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor,
+ SDL_BlendFactor dstColorFactor,
+ SDL_BlendOperation colorOperation,
+ SDL_BlendFactor srcAlphaFactor,
+ SDL_BlendFactor dstAlphaFactor,
+ SDL_BlendOperation alphaOperation);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_blendmode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_clipboard.h b/Client/ThirdParty/SDL2/include/SDL_clipboard.h
new file mode 100644
index 0000000..79e4dcc
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_clipboard.h
@@ -0,0 +1,89 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_clipboard.h
+ *
+ * Include file for SDL clipboard handling
+ */
+
+#ifndef SDL_clipboard_h_
+#define SDL_clipboard_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+/**
+ * Put UTF-8 text into the clipboard.
+ *
+ * \param text the text to store in the clipboard
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetClipboardText
+ * \sa SDL_HasClipboardText
+ */
+extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text);
+
+/**
+ * Get UTF-8 text from the clipboard, which must be freed with SDL_free().
+ *
+ * This functions returns NULL if there was not enough memory left for a copy
+ * of the clipboard's content.
+ *
+ * \returns the clipboard text on success or NULL on failure; call
+ * SDL_GetError() for more information. Caller must call SDL_free()
+ * on the returned pointer when done with it.
+ *
+ * \sa SDL_HasClipboardText
+ * \sa SDL_SetClipboardText
+ */
+extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
+
+/**
+ * Query whether the clipboard exists and contains a non-empty text string.
+ *
+ * \returns SDL_TRUE if the clipboard has text, or SDL_FALSE if it does not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetClipboardText
+ * \sa SDL_SetClipboardText
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_clipboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config.h b/Client/ThirdParty/SDL2/include/SDL_config.h
new file mode 100644
index 0000000..33436c4
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config.h
@@ -0,0 +1,299 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_windows_h_
+#define SDL_config_windows_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This is a set of defines to configure the SDL features */
+
+#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
+#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__) || defined(__clang__)
+#define HAVE_STDINT_H 1
+#elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#endif
+#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#endif
+#else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#endif
+typedef unsigned int uintptr_t;
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
+
+#define HAVE_DDRAW_H 1
+#define HAVE_DINPUT_H 1
+#define HAVE_DSOUND_H 1
+#define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
+#define HAVE_MMDEVICEAPI_H 1
+#define HAVE_AUDIOCLIENT_H 1
+#define HAVE_SENSORSAPI_H 1
+#if (defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)) && (defined(_MSC_VER) && _MSC_VER >= 1600)
+#define HAVE_IMMINTRIN_H 1
+#elif defined(__has_include) && (defined(__i386__) || defined(__x86_64))
+# if __has_include(<immintrin.h>)
+# define HAVE_IMMINTRIN_H 1
+# endif
+#endif
+
+/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
+#ifdef HAVE_LIBC
+/* Useful headers */
+#define STDC_HEADERS 1
+#define HAVE_CTYPE_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STRING_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE__STRREV 1
+/* These functions have security warnings, so we won't use them */
+/* #undef HAVE__STRUPR */
+/* #undef HAVE__STRLWR */
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+/* #undef HAVE_STRTOK_R */
+/* These functions have security warnings, so we won't use them */
+/* #undef HAVE__LTOA */
+/* #undef HAVE__ULTOA */
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE__STRICMP 1
+#define HAVE__STRNICMP 1
+#define HAVE__WCSICMP 1
+#define HAVE__WCSNICMP 1
+#define HAVE__WCSDUP 1
+#define HAVE_ACOS 1
+#define HAVE_ACOSF 1
+#define HAVE_ASIN 1
+#define HAVE_ASINF 1
+#define HAVE_ATAN 1
+#define HAVE_ATANF 1
+#define HAVE_ATAN2 1
+#define HAVE_ATAN2F 1
+#define HAVE_CEILF 1
+#define HAVE__COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_EXP 1
+#define HAVE_EXPF 1
+#define HAVE_FABS 1
+#define HAVE_FABSF 1
+#define HAVE_FLOOR 1
+#define HAVE_FLOORF 1
+#define HAVE_FMOD 1
+#define HAVE_FMODF 1
+#define HAVE_LOG 1
+#define HAVE_LOGF 1
+#define HAVE_LOG10 1
+#define HAVE_LOG10F 1
+#define HAVE_POW 1
+#define HAVE_POWF 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#if defined(_MSC_VER)
+/* These functions were added with the VC++ 2013 C runtime library */
+#if _MSC_VER >= 1800
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_VSSCANF 1
+#define HAVE_LROUND 1
+#define HAVE_LROUNDF 1
+#define HAVE_ROUND 1
+#define HAVE_ROUNDF 1
+#define HAVE_SCALBN 1
+#define HAVE_SCALBNF 1
+#define HAVE_TRUNC 1
+#define HAVE_TRUNCF 1
+#endif
+/* This function is available with at least the VC++ 2008 C runtime library */
+#if _MSC_VER >= 1400
+#define HAVE__FSEEKI64 1
+#endif
+#endif
+#if !defined(_MSC_VER) || defined(_USE_MATH_DEFINES)
+#define HAVE_M_PI 1
+#endif
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#endif
+
+/* Check to see if we have Windows 10 build environment */
+#if defined(_MSC_VER) && (_MSC_VER >= 1911) /* Visual Studio 15.3 */
+#include <sdkddkver.h>
+#if _WIN32_WINNT >= 0x0601 /* Windows 7 */
+#define SDL_WINDOWS7_SDK
+#endif
+#if _WIN32_WINNT >= 0x0602 /* Windows 8 */
+#define SDL_WINDOWS8_SDK
+#endif
+#if _WIN32_WINNT >= 0x0A00 /* Windows 10 */
+#define SDL_WINDOWS10_SDK
+#endif
+#endif /* _MSC_VER >= 1911 */
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_WASAPI 1
+#define SDL_AUDIO_DRIVER_DSOUND 1
+#define SDL_AUDIO_DRIVER_WINMM 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_DINPUT 1
+#define SDL_JOYSTICK_HIDAPI 1
+#ifndef __WINRT__
+#define SDL_JOYSTICK_RAWINPUT 1
+#endif
+#define SDL_JOYSTICK_VIRTUAL 1
+#ifdef SDL_WINDOWS10_SDK
+#define SDL_JOYSTICK_WGI 1
+#endif
+#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_DINPUT 1
+#define SDL_HAPTIC_XINPUT 1
+
+/* Enable the sensor driver */
+#define SDL_SENSOR_WINDOWS 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_WINDOWS 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_GENERIC_COND_SUFFIX 1
+#define SDL_THREAD_WINDOWS 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_WINDOWS 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_WINDOWS 1
+
+#ifndef SDL_VIDEO_RENDER_D3D
+#define SDL_VIDEO_RENDER_D3D 1
+#endif
+#ifdef SDL_WINDOWS7_SDK
+#define SDL_VIDEO_RENDER_D3D11 1
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_WGL
+#define SDL_VIDEO_OPENGL_WGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_OPENGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_EGL
+#define SDL_VIDEO_OPENGL_EGL 1
+#endif
+
+/* Enable Vulkan support */
+#define SDL_VIDEO_VULKAN 1
+
+/* Enable system power support */
+#define SDL_POWER_WINDOWS 1
+
+/* Enable filesystem support */
+#define SDL_FILESYSTEM_WINDOWS 1
+
+/* Enable assembly routines (Win64 doesn't have inline asm) */
+#ifndef _WIN64
+#define SDL_ASSEMBLY_ROUTINES 1
+#endif
+
+#endif /* SDL_config_windows_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config.h.cmake b/Client/ThirdParty/SDL2/include/SDL_config.h.cmake
new file mode 100644
index 0000000..c57266c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config.h.cmake
@@ -0,0 +1,445 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_h_
+#define SDL_config_h_
+
+/**
+ * \file SDL_config.h.in
+ *
+ * This is a set of defines to configure the SDL features
+ */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+/* C language features */
+#cmakedefine const @HAVE_CONST@
+#cmakedefine inline @HAVE_INLINE@
+#cmakedefine volatile @HAVE_VOLATILE@
+
+/* C datatypes */
+/* Define SIZEOF_VOIDP for 64/32 architectures */
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#cmakedefine HAVE_GCC_ATOMICS @HAVE_GCC_ATOMICS@
+#cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET @HAVE_GCC_SYNC_LOCK_TEST_AND_SET@
+
+#cmakedefine HAVE_D3D_H @HAVE_D3D_H@
+#cmakedefine HAVE_D3D11_H @HAVE_D3D11_H@
+#cmakedefine HAVE_DDRAW_H @HAVE_DDRAW_H@
+#cmakedefine HAVE_DSOUND_H @HAVE_DSOUND_H@
+#cmakedefine HAVE_DINPUT_H @HAVE_DINPUT_H@
+#cmakedefine HAVE_XAUDIO2_H @HAVE_XAUDIO2_H@
+#cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@
+#cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@
+#cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@
+#cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@
+
+/* Comment this if you want to build without any C library requirements */
+#cmakedefine HAVE_LIBC 1
+#if HAVE_LIBC
+
+/* Useful headers */
+#cmakedefine HAVE_ALLOCA_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+#cmakedefine HAVE_STDIO_H 1
+#cmakedefine STDC_HEADERS 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STDARG_H 1
+#cmakedefine HAVE_MALLOC_H 1
+#cmakedefine HAVE_MEMORY_H 1
+#cmakedefine HAVE_STRING_H 1
+#cmakedefine HAVE_STRINGS_H 1
+#cmakedefine HAVE_WCHAR_H 1
+#cmakedefine HAVE_INTTYPES_H 1
+#cmakedefine HAVE_STDINT_H 1
+#cmakedefine HAVE_CTYPE_H 1
+#cmakedefine HAVE_MATH_H 1
+#cmakedefine HAVE_ICONV_H 1
+#cmakedefine HAVE_SIGNAL_H 1
+#cmakedefine HAVE_ALTIVEC_H 1
+#cmakedefine HAVE_PTHREAD_NP_H 1
+#cmakedefine HAVE_LIBUDEV_H 1
+#cmakedefine HAVE_DBUS_DBUS_H 1
+#cmakedefine HAVE_IBUS_IBUS_H 1
+#cmakedefine HAVE_FCITX_FRONTEND_H 1
+#cmakedefine HAVE_LIBSAMPLERATE_H 1
+
+/* C library functions */
+#cmakedefine HAVE_MALLOC 1
+#cmakedefine HAVE_CALLOC 1
+#cmakedefine HAVE_REALLOC 1
+#cmakedefine HAVE_FREE 1
+#cmakedefine HAVE_ALLOCA 1
+#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */
+#cmakedefine HAVE_GETENV 1
+#cmakedefine HAVE_SETENV 1
+#cmakedefine HAVE_PUTENV 1
+#cmakedefine HAVE_UNSETENV 1
+#endif
+#cmakedefine HAVE_QSORT 1
+#cmakedefine HAVE_ABS 1
+#cmakedefine HAVE_BCOPY 1
+#cmakedefine HAVE_MEMSET 1
+#cmakedefine HAVE_MEMCPY 1
+#cmakedefine HAVE_MEMMOVE 1
+#cmakedefine HAVE_MEMCMP 1
+#cmakedefine HAVE_WCSLEN 1
+#cmakedefine HAVE_WCSLCPY 1
+#cmakedefine HAVE_WCSLCAT 1
+#cmakedefine HAVE_WCSCMP 1
+#cmakedefine HAVE_STRLEN 1
+#cmakedefine HAVE_STRLCPY 1
+#cmakedefine HAVE_STRLCAT 1
+#cmakedefine HAVE_STRDUP 1
+#cmakedefine HAVE__STRREV 1
+#cmakedefine HAVE__STRUPR 1
+#cmakedefine HAVE__STRLWR 1
+#cmakedefine HAVE_INDEX 1
+#cmakedefine HAVE_RINDEX 1
+#cmakedefine HAVE_STRCHR 1
+#cmakedefine HAVE_STRRCHR 1
+#cmakedefine HAVE_STRSTR 1
+#cmakedefine HAVE_ITOA 1
+#cmakedefine HAVE__LTOA 1
+#cmakedefine HAVE__UITOA 1
+#cmakedefine HAVE__ULTOA 1
+#cmakedefine HAVE_STRTOL 1
+#cmakedefine HAVE_STRTOUL 1
+#cmakedefine HAVE__I64TOA 1
+#cmakedefine HAVE__UI64TOA 1
+#cmakedefine HAVE_STRTOLL 1
+#cmakedefine HAVE_STRTOULL 1
+#cmakedefine HAVE_STRTOD 1
+#cmakedefine HAVE_ATOI 1
+#cmakedefine HAVE_ATOF 1
+#cmakedefine HAVE_STRCMP 1
+#cmakedefine HAVE_STRNCMP 1
+#cmakedefine HAVE__STRICMP 1
+#cmakedefine HAVE_STRCASECMP 1
+#cmakedefine HAVE__STRNICMP 1
+#cmakedefine HAVE_STRNCASECMP 1
+#cmakedefine HAVE_VSSCANF 1
+#cmakedefine HAVE_VSNPRINTF 1
+#cmakedefine HAVE_M_PI 1
+#cmakedefine HAVE_ATAN 1
+#cmakedefine HAVE_ATAN2 1
+#cmakedefine HAVE_ACOS 1
+#cmakedefine HAVE_ASIN 1
+#cmakedefine HAVE_CEIL 1
+#cmakedefine HAVE_COPYSIGN 1
+#cmakedefine HAVE_COS 1
+#cmakedefine HAVE_COSF 1
+#cmakedefine HAVE_FABS 1
+#cmakedefine HAVE_FLOOR 1
+#cmakedefine HAVE_LOG 1
+#cmakedefine HAVE_POW 1
+#cmakedefine HAVE_SCALBN 1
+#cmakedefine HAVE_SIN 1
+#cmakedefine HAVE_SINF 1
+#cmakedefine HAVE_SQRT 1
+#cmakedefine HAVE_SQRTF 1
+#cmakedefine HAVE_TAN 1
+#cmakedefine HAVE_TANF 1
+#cmakedefine HAVE_FOPEN64 1
+#cmakedefine HAVE_FSEEKO 1
+#cmakedefine HAVE_FSEEKO64 1
+#cmakedefine HAVE_SIGACTION 1
+#cmakedefine HAVE_SA_SIGACTION 1
+#cmakedefine HAVE_SETJMP 1
+#cmakedefine HAVE_NANOSLEEP 1
+#cmakedefine HAVE_SYSCONF 1
+#cmakedefine HAVE_SYSCTLBYNAME 1
+#cmakedefine HAVE_CLOCK_GETTIME 1
+#cmakedefine HAVE_GETPAGESIZE 1
+#cmakedefine HAVE_MPROTECT 1
+#cmakedefine HAVE_ICONV 1
+#cmakedefine HAVE_PTHREAD_SETNAME_NP 1
+#cmakedefine HAVE_PTHREAD_SET_NAME_NP 1
+#cmakedefine HAVE_SEM_TIMEDWAIT 1
+#cmakedefine HAVE_GETAUXVAL 1
+#cmakedefine HAVE_POLL 1
+
+#elif __WIN32__
+#cmakedefine HAVE_STDARG_H 1
+#cmakedefine HAVE_STDDEF_H 1
+#else
+/* We may need some replacement for stdarg.h here */
+#include <stdarg.h>
+#endif /* HAVE_LIBC */
+
+/* SDL internal assertion support */
+#cmakedefine SDL_DEFAULT_ASSERT_LEVEL @SDL_DEFAULT_ASSERT_LEVEL@
+
+/* Allow disabling of core subsystems */
+#cmakedefine SDL_ATOMIC_DISABLED @SDL_ATOMIC_DISABLED@
+#cmakedefine SDL_AUDIO_DISABLED @SDL_AUDIO_DISABLED@
+#cmakedefine SDL_CPUINFO_DISABLED @SDL_CPUINFO_DISABLED@
+#cmakedefine SDL_EVENTS_DISABLED @SDL_EVENTS_DISABLED@
+#cmakedefine SDL_FILE_DISABLED @SDL_FILE_DISABLED@
+#cmakedefine SDL_JOYSTICK_DISABLED @SDL_JOYSTICK_DISABLED@
+#cmakedefine SDL_HAPTIC_DISABLED @SDL_HAPTIC_DISABLED@
+#cmakedefine SDL_LOADSO_DISABLED @SDL_LOADSO_DISABLED@
+#cmakedefine SDL_RENDER_DISABLED @SDL_RENDER_DISABLED@
+#cmakedefine SDL_THREADS_DISABLED @SDL_THREADS_DISABLED@
+#cmakedefine SDL_TIMERS_DISABLED @SDL_TIMERS_DISABLED@
+#cmakedefine SDL_VIDEO_DISABLED @SDL_VIDEO_DISABLED@
+#cmakedefine SDL_POWER_DISABLED @SDL_POWER_DISABLED@
+#cmakedefine SDL_FILESYSTEM_DISABLED @SDL_FILESYSTEM_DISABLED@
+
+/* Enable various audio drivers */
+#cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@
+#cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@
+#cmakedefine SDL_AUDIO_DRIVER_ARTS @SDL_AUDIO_DRIVER_ARTS@
+#cmakedefine SDL_AUDIO_DRIVER_ARTS_DYNAMIC @SDL_AUDIO_DRIVER_ARTS_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_DISK @SDL_AUDIO_DRIVER_DISK@
+#cmakedefine SDL_AUDIO_DRIVER_DSOUND @SDL_AUDIO_DRIVER_DSOUND@
+#cmakedefine SDL_AUDIO_DRIVER_DUMMY @SDL_AUDIO_DRIVER_DUMMY@
+#cmakedefine SDL_AUDIO_DRIVER_EMSCRIPTEN @SDL_AUDIO_DRIVER_EMSCRIPTEN@
+#cmakedefine SDL_AUDIO_DRIVER_ESD @SDL_AUDIO_DRIVER_ESD@
+#cmakedefine SDL_AUDIO_DRIVER_ESD_DYNAMIC @SDL_AUDIO_DRIVER_ESD_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
+#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_HAIKU @SDL_AUDIO_DRIVER_HAIKU@
+#cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@
+#cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@
+#cmakedefine SDL_AUDIO_DRIVER_NAS_DYNAMIC @SDL_AUDIO_DRIVER_NAS_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_NETBSD @SDL_AUDIO_DRIVER_NETBSD@
+#cmakedefine SDL_AUDIO_DRIVER_OSS @SDL_AUDIO_DRIVER_OSS@
+#cmakedefine SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H @SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H@
+#cmakedefine SDL_AUDIO_DRIVER_PAUDIO @SDL_AUDIO_DRIVER_PAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO @SDL_AUDIO_DRIVER_PULSEAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_QSA @SDL_AUDIO_DRIVER_QSA@
+#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@
+#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@
+#cmakedefine SDL_AUDIO_DRIVER_SUNAUDIO @SDL_AUDIO_DRIVER_SUNAUDIO@
+#cmakedefine SDL_AUDIO_DRIVER_WASAPI @SDL_AUDIO_DRIVER_WASAPI@
+#cmakedefine SDL_AUDIO_DRIVER_WINMM @SDL_AUDIO_DRIVER_WINMM@
+#cmakedefine SDL_AUDIO_DRIVER_XAUDIO2 @SDL_AUDIO_DRIVER_XAUDIO2@
+
+/* Enable various input drivers */
+#cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@
+#cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@
+#cmakedefine SDL_INPUT_TSLIB @SDL_INPUT_TSLIB@
+#cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@
+#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@
+#cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@
+#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@
+#cmakedefine SDL_JOYSTICK_DUMMY @SDL_JOYSTICK_DUMMY@
+#cmakedefine SDL_JOYSTICK_IOKIT @SDL_JOYSTICK_IOKIT@
+#cmakedefine SDL_JOYSTICK_MFI @SDL_JOYSTICK_MFI@
+#cmakedefine SDL_JOYSTICK_LINUX @SDL_JOYSTICK_LINUX@
+#cmakedefine SDL_JOYSTICK_WINMM @SDL_JOYSTICK_WINMM@
+#cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@
+#cmakedefine SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H @SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H@
+#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@
+#cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@
+#cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@
+#cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@
+#cmakedefine SDL_HAPTIC_DINPUT @SDL_HAPTIC_DINPUT@
+#cmakedefine SDL_HAPTIC_XINPUT @SDL_HAPTIC_XINPUT@
+#cmakedefine SDL_HAPTIC_ANDROID @SDL_HAPTIC_ANDROID@
+
+/* Enable various shared object loading systems */
+#cmakedefine SDL_LOADSO_DLOPEN @SDL_LOADSO_DLOPEN@
+#cmakedefine SDL_LOADSO_DUMMY @SDL_LOADSO_DUMMY@
+#cmakedefine SDL_LOADSO_LDG @SDL_LOADSO_LDG@
+#cmakedefine SDL_LOADSO_WINDOWS @SDL_LOADSO_WINDOWS@
+
+/* Enable various threading systems */
+#cmakedefine SDL_THREAD_PTHREAD @SDL_THREAD_PTHREAD@
+#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX@
+#cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP@
+#cmakedefine SDL_THREAD_WINDOWS @SDL_THREAD_WINDOWS@
+
+/* Enable various timer systems */
+#cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@
+#cmakedefine SDL_TIMER_DUMMY @SDL_TIMER_DUMMY@
+#cmakedefine SDL_TIMER_UNIX @SDL_TIMER_UNIX@
+#cmakedefine SDL_TIMER_WINDOWS @SDL_TIMER_WINDOWS@
+#cmakedefine SDL_TIMER_WINCE @SDL_TIMER_WINCE@
+
+/* Enable various video drivers */
+#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
+#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
+#cmakedefine SDL_VIDEO_DRIVER_COCOA @SDL_VIDEO_DRIVER_COCOA@
+#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
+#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC @SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
+#cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
+#cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@
+#cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@
+#cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
+
+#cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@
+#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM@
+
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
+
+#cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
+#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON@
+#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
+#cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@
+#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE @SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINERAMA @SDL_VIDEO_DRIVER_X11_XINERAMA@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2 @SDL_VIDEO_DRIVER_X11_XINPUT2@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH @SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XRANDR @SDL_VIDEO_DRIVER_X11_XRANDR@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XSCRNSAVER @SDL_VIDEO_DRIVER_X11_XSCRNSAVER@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE @SDL_VIDEO_DRIVER_X11_XSHAPE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_XVIDMODE @SDL_VIDEO_DRIVER_X11_XVIDMODE@
+#cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@
+#cmakedefine SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY @SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY@
+#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@
+
+#cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@
+#cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@
+#cmakedefine SDL_VIDEO_RENDER_OGL @SDL_VIDEO_RENDER_OGL@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES @SDL_VIDEO_RENDER_OGL_ES@
+#cmakedefine SDL_VIDEO_RENDER_OGL_ES2 @SDL_VIDEO_RENDER_OGL_ES2@
+#cmakedefine SDL_VIDEO_RENDER_DIRECTFB @SDL_VIDEO_RENDER_DIRECTFB@
+
+/* Enable OpenGL support */
+#cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@
+#cmakedefine SDL_VIDEO_OPENGL_ES @SDL_VIDEO_OPENGL_ES@
+#cmakedefine SDL_VIDEO_OPENGL_ES2 @SDL_VIDEO_OPENGL_ES2@
+#cmakedefine SDL_VIDEO_OPENGL_BGL @SDL_VIDEO_OPENGL_BGL@
+#cmakedefine SDL_VIDEO_OPENGL_CGL @SDL_VIDEO_OPENGL_CGL@
+#cmakedefine SDL_VIDEO_OPENGL_GLX @SDL_VIDEO_OPENGL_GLX@
+#cmakedefine SDL_VIDEO_OPENGL_WGL @SDL_VIDEO_OPENGL_WGL@
+#cmakedefine SDL_VIDEO_OPENGL_EGL @SDL_VIDEO_OPENGL_EGL@
+#cmakedefine SDL_VIDEO_OPENGL_OSMESA @SDL_VIDEO_OPENGL_OSMESA@
+#cmakedefine SDL_VIDEO_OPENGL_OSMESA_DYNAMIC @SDL_VIDEO_OPENGL_OSMESA_DYNAMIC@
+
+/* Enable Vulkan support */
+#cmakedefine SDL_VIDEO_VULKAN @SDL_VIDEO_VULKAN@
+
+/* Enable system power support */
+#cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
+#cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@
+#cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@
+#cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@
+#cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@
+#cmakedefine SDL_POWER_EMSCRIPTEN @SDL_POWER_EMSCRIPTEN@
+#cmakedefine SDL_POWER_HARDWIRED @SDL_POWER_HARDWIRED@
+
+/* Enable system filesystem support */
+#cmakedefine SDL_FILESYSTEM_ANDROID @SDL_FILESYSTEM_ANDROID@
+#cmakedefine SDL_FILESYSTEM_HAIKU @SDL_FILESYSTEM_HAIKU@
+#cmakedefine SDL_FILESYSTEM_COCOA @SDL_FILESYSTEM_COCOA@
+#cmakedefine SDL_FILESYSTEM_DUMMY @SDL_FILESYSTEM_DUMMY@
+#cmakedefine SDL_FILESYSTEM_UNIX @SDL_FILESYSTEM_UNIX@
+#cmakedefine SDL_FILESYSTEM_WINDOWS @SDL_FILESYSTEM_WINDOWS@
+#cmakedefine SDL_FILESYSTEM_EMSCRIPTEN @SDL_FILESYSTEM_EMSCRIPTEN@
+
+/* Enable assembly routines */
+#cmakedefine SDL_ASSEMBLY_ROUTINES @SDL_ASSEMBLY_ROUTINES@
+#cmakedefine SDL_ALTIVEC_BLITTERS @SDL_ALTIVEC_BLITTERS@
+
+/* Enable dynamic libsamplerate support */
+#cmakedefine SDL_LIBSAMPLERATE_DYNAMIC @SDL_LIBSAMPLERATE_DYNAMIC@
+
+/* Platform specific definitions */
+#if !defined(__WIN32__)
+# if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
+typedef unsigned int size_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+# endif /* if (stdint.h isn't available) */
+#else /* __WIN32__ */
+# if !defined(_STDINT_H_) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
+# if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H 1
+# elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+# ifndef _UINTPTR_T_DEFINED
+# ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+# else
+typedef unsigned int uintptr_t;
+# endif
+#define _UINTPTR_T_DEFINED
+# endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+# if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+# endif
+# if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+# endif
+# else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+# ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+# endif
+typedef unsigned int uintptr_t;
+# endif /* __GNUC__ || _MSC_VER */
+# endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+#endif /* __WIN32__ */
+
+#endif /* SDL_config_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config.h.in b/Client/ThirdParty/SDL2/include/SDL_config.h.in
new file mode 100644
index 0000000..8b3d208
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config.h.in
@@ -0,0 +1,389 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_h_
+#define SDL_config_h_
+
+/**
+ * \file SDL_config.h.in
+ *
+ * This is a set of defines to configure the SDL features
+ */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+/* Make sure that this isn't included by Visual C++ */
+#ifdef _MSC_VER
+#error You should run hg revert SDL_config.h
+#endif
+
+/* C language features */
+#undef const
+#undef inline
+#undef volatile
+
+/* C datatypes */
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+#undef HAVE_GCC_ATOMICS
+#undef HAVE_GCC_SYNC_LOCK_TEST_AND_SET
+
+#undef HAVE_DDRAW_H
+#undef HAVE_DINPUT_H
+#undef HAVE_DSOUND_H
+#undef HAVE_DXGI_H
+#undef HAVE_XINPUT_H
+#undef HAVE_XINPUT_GAMEPAD_EX
+#undef HAVE_XINPUT_STATE_EX
+
+/* Comment this if you want to build without any C library requirements */
+#undef HAVE_LIBC
+#if HAVE_LIBC
+
+/* Useful headers */
+#undef HAVE_ALLOCA_H
+#undef HAVE_SYS_TYPES_H
+#undef HAVE_STDIO_H
+#undef STDC_HEADERS
+#undef HAVE_STDLIB_H
+#undef HAVE_STDARG_H
+#undef HAVE_MALLOC_H
+#undef HAVE_MEMORY_H
+#undef HAVE_STRING_H
+#undef HAVE_STRINGS_H
+#undef HAVE_WCHAR_H
+#undef HAVE_INTTYPES_H
+#undef HAVE_STDINT_H
+#undef HAVE_CTYPE_H
+#undef HAVE_MATH_H
+#undef HAVE_ICONV_H
+#undef HAVE_SIGNAL_H
+#undef HAVE_ALTIVEC_H
+#undef HAVE_PTHREAD_NP_H
+#undef HAVE_LIBUDEV_H
+#undef HAVE_DBUS_DBUS_H
+#undef HAVE_IBUS_IBUS_H
+#undef HAVE_FCITX_FRONTEND_H
+#undef HAVE_LIBSAMPLERATE_H
+
+/* C library functions */
+#undef HAVE_MALLOC
+#undef HAVE_CALLOC
+#undef HAVE_REALLOC
+#undef HAVE_FREE
+#undef HAVE_ALLOCA
+#ifndef __WIN32__ /* Don't use C runtime versions of these on Windows */
+#undef HAVE_GETENV
+#undef HAVE_SETENV
+#undef HAVE_PUTENV
+#undef HAVE_UNSETENV
+#endif
+#undef HAVE_QSORT
+#undef HAVE_ABS
+#undef HAVE_BCOPY
+#undef HAVE_MEMSET
+#undef HAVE_MEMCPY
+#undef HAVE_MEMMOVE
+#undef HAVE_MEMCMP
+#undef HAVE_WCSLEN
+#undef HAVE_WCSLCPY
+#undef HAVE_WCSLCAT
+#undef HAVE_WCSCMP
+#undef HAVE_STRLEN
+#undef HAVE_STRLCPY
+#undef HAVE_STRLCAT
+#undef HAVE_STRDUP
+#undef HAVE__STRREV
+#undef HAVE__STRUPR
+#undef HAVE__STRLWR
+#undef HAVE_INDEX
+#undef HAVE_RINDEX
+#undef HAVE_STRCHR
+#undef HAVE_STRRCHR
+#undef HAVE_STRSTR
+#undef HAVE_ITOA
+#undef HAVE__LTOA
+#undef HAVE__UITOA
+#undef HAVE__ULTOA
+#undef HAVE_STRTOL
+#undef HAVE_STRTOUL
+#undef HAVE__I64TOA
+#undef HAVE__UI64TOA
+#undef HAVE_STRTOLL
+#undef HAVE_STRTOULL
+#undef HAVE_STRTOD
+#undef HAVE_ATOI
+#undef HAVE_ATOF
+#undef HAVE_STRCMP
+#undef HAVE_STRNCMP
+#undef HAVE__STRICMP
+#undef HAVE_STRCASECMP
+#undef HAVE__STRNICMP
+#undef HAVE_STRNCASECMP
+#undef HAVE_SSCANF
+#undef HAVE_VSSCANF
+#undef HAVE_SNPRINTF
+#undef HAVE_VSNPRINTF
+#undef HAVE_M_PI
+#undef HAVE_ATAN
+#undef HAVE_ATAN2
+#undef HAVE_ACOS
+#undef HAVE_ASIN
+#undef HAVE_CEIL
+#undef HAVE_COPYSIGN
+#undef HAVE_COS
+#undef HAVE_COSF
+#undef HAVE_FABS
+#undef HAVE_FLOOR
+#undef HAVE_LOG
+#undef HAVE_POW
+#undef HAVE_SCALBN
+#undef HAVE_SIN
+#undef HAVE_SINF
+#undef HAVE_SQRT
+#undef HAVE_SQRTF
+#undef HAVE_TAN
+#undef HAVE_TANF
+#undef HAVE_FOPEN64
+#undef HAVE_FSEEKO
+#undef HAVE_FSEEKO64
+#undef HAVE_SIGACTION
+#undef HAVE_SA_SIGACTION
+#undef HAVE_SETJMP
+#undef HAVE_NANOSLEEP
+#undef HAVE_SYSCONF
+#undef HAVE_SYSCTLBYNAME
+#undef HAVE_CLOCK_GETTIME
+#undef HAVE_GETPAGESIZE
+#undef HAVE_MPROTECT
+#undef HAVE_ICONV
+#undef HAVE_PTHREAD_SETNAME_NP
+#undef HAVE_PTHREAD_SET_NAME_NP
+#undef HAVE_SEM_TIMEDWAIT
+#undef HAVE_GETAUXVAL
+#undef HAVE_POLL
+
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
+#endif /* HAVE_LIBC */
+
+/* SDL internal assertion support */
+#undef SDL_DEFAULT_ASSERT_LEVEL
+
+/* Allow disabling of core subsystems */
+#undef SDL_ATOMIC_DISABLED
+#undef SDL_AUDIO_DISABLED
+#undef SDL_CPUINFO_DISABLED
+#undef SDL_EVENTS_DISABLED
+#undef SDL_FILE_DISABLED
+#undef SDL_JOYSTICK_DISABLED
+#undef SDL_HAPTIC_DISABLED
+#undef SDL_LOADSO_DISABLED
+#undef SDL_RENDER_DISABLED
+#undef SDL_THREADS_DISABLED
+#undef SDL_TIMERS_DISABLED
+#undef SDL_VIDEO_DISABLED
+#undef SDL_POWER_DISABLED
+#undef SDL_FILESYSTEM_DISABLED
+
+/* Enable various audio drivers */
+#undef SDL_AUDIO_DRIVER_ALSA
+#undef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
+#undef SDL_AUDIO_DRIVER_ANDROID
+#undef SDL_AUDIO_DRIVER_ARTS
+#undef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
+#undef SDL_AUDIO_DRIVER_COREAUDIO
+#undef SDL_AUDIO_DRIVER_DISK
+#undef SDL_AUDIO_DRIVER_DSOUND
+#undef SDL_AUDIO_DRIVER_DUMMY
+#undef SDL_AUDIO_DRIVER_EMSCRIPTEN
+#undef SDL_AUDIO_DRIVER_ESD
+#undef SDL_AUDIO_DRIVER_ESD_DYNAMIC
+#undef SDL_AUDIO_DRIVER_FUSIONSOUND
+#undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
+#undef SDL_AUDIO_DRIVER_HAIKU
+#undef SDL_AUDIO_DRIVER_JACK
+#undef SDL_AUDIO_DRIVER_JACK_DYNAMIC
+#undef SDL_AUDIO_DRIVER_NACL
+#undef SDL_AUDIO_DRIVER_NAS
+#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
+#undef SDL_AUDIO_DRIVER_NETBSD
+#undef SDL_AUDIO_DRIVER_OSS
+#undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
+#undef SDL_AUDIO_DRIVER_PAUDIO
+#undef SDL_AUDIO_DRIVER_PULSEAUDIO
+#undef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC
+#undef SDL_AUDIO_DRIVER_QSA
+#undef SDL_AUDIO_DRIVER_SNDIO
+#undef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
+#undef SDL_AUDIO_DRIVER_SUNAUDIO
+#undef SDL_AUDIO_DRIVER_WASAPI
+#undef SDL_AUDIO_DRIVER_WINMM
+#undef SDL_AUDIO_DRIVER_XAUDIO2
+
+/* Enable various input drivers */
+#undef SDL_INPUT_LINUXEV
+#undef SDL_INPUT_LINUXKD
+#undef SDL_INPUT_TSLIB
+#undef SDL_JOYSTICK_HAIKU
+#undef SDL_JOYSTICK_DINPUT
+#undef SDL_JOYSTICK_XINPUT
+#undef SDL_JOYSTICK_DUMMY
+#undef SDL_JOYSTICK_IOKIT
+#undef SDL_JOYSTICK_LINUX
+#undef SDL_JOYSTICK_ANDROID
+#undef SDL_JOYSTICK_WINMM
+#undef SDL_JOYSTICK_USBHID
+#undef SDL_JOYSTICK_USBHID_MACHINE_JOYSTICK_H
+#undef SDL_JOYSTICK_EMSCRIPTEN
+#undef SDL_HAPTIC_DUMMY
+#undef SDL_HAPTIC_LINUX
+#undef SDL_HAPTIC_IOKIT
+#undef SDL_HAPTIC_DINPUT
+#undef SDL_HAPTIC_XINPUT
+
+/* Enable various shared object loading systems */
+#undef SDL_LOADSO_DLOPEN
+#undef SDL_LOADSO_DUMMY
+#undef SDL_LOADSO_LDG
+#undef SDL_LOADSO_WINDOWS
+
+/* Enable various threading systems */
+#undef SDL_THREAD_PTHREAD
+#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX
+#undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP
+#undef SDL_THREAD_WINDOWS
+
+/* Enable various timer systems */
+#undef SDL_TIMER_HAIKU
+#undef SDL_TIMER_DUMMY
+#undef SDL_TIMER_UNIX
+#undef SDL_TIMER_WINDOWS
+
+/* Enable various video drivers */
+#undef SDL_VIDEO_DRIVER_HAIKU
+#undef SDL_VIDEO_DRIVER_COCOA
+#undef SDL_VIDEO_DRIVER_DIRECTFB
+#undef SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC
+#undef SDL_VIDEO_DRIVER_DUMMY
+#undef SDL_VIDEO_DRIVER_WINDOWS
+#undef SDL_VIDEO_DRIVER_WAYLAND
+#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
+#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_MIR
+#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC
+#undef SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_X11
+#undef SDL_VIDEO_DRIVER_RPI
+#undef SDL_VIDEO_DRIVER_KMSDRM
+#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
+#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM
+#undef SDL_VIDEO_DRIVER_ANDROID
+#undef SDL_VIDEO_DRIVER_EMSCRIPTEN
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS
+#undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE
+#undef SDL_VIDEO_DRIVER_X11_XCURSOR
+#undef SDL_VIDEO_DRIVER_X11_XDBE
+#undef SDL_VIDEO_DRIVER_X11_XINERAMA
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2
+#undef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+#undef SDL_VIDEO_DRIVER_X11_XRANDR
+#undef SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+#undef SDL_VIDEO_DRIVER_X11_XSHAPE
+#undef SDL_VIDEO_DRIVER_X11_XVIDMODE
+#undef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+#undef SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
+#undef SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+#undef SDL_VIDEO_DRIVER_NACL
+#undef SDL_VIDEO_DRIVER_VIVANTE
+#undef SDL_VIDEO_DRIVER_VIVANTE_VDK
+#undef SDL_VIDEO_DRIVER_QNX
+
+#undef SDL_VIDEO_RENDER_D3D
+#undef SDL_VIDEO_RENDER_D3D11
+#undef SDL_VIDEO_RENDER_OGL
+#undef SDL_VIDEO_RENDER_OGL_ES
+#undef SDL_VIDEO_RENDER_OGL_ES2
+#undef SDL_VIDEO_RENDER_DIRECTFB
+
+/* Enable OpenGL support */
+#undef SDL_VIDEO_OPENGL
+#undef SDL_VIDEO_OPENGL_ES
+#undef SDL_VIDEO_OPENGL_ES2
+#undef SDL_VIDEO_OPENGL_BGL
+#undef SDL_VIDEO_OPENGL_CGL
+#undef SDL_VIDEO_OPENGL_EGL
+#undef SDL_VIDEO_OPENGL_GLX
+#undef SDL_VIDEO_OPENGL_WGL
+#undef SDL_VIDEO_OPENGL_OSMESA
+#undef SDL_VIDEO_OPENGL_OSMESA_DYNAMIC
+
+/* Enable Vulkan support */
+#undef SDL_VIDEO_VULKAN
+
+/* Enable system power support */
+#undef SDL_POWER_LINUX
+#undef SDL_POWER_WINDOWS
+#undef SDL_POWER_MACOSX
+#undef SDL_POWER_HAIKU
+#undef SDL_POWER_ANDROID
+#undef SDL_POWER_EMSCRIPTEN
+#undef SDL_POWER_HARDWIRED
+
+/* Enable system filesystem support */
+#undef SDL_FILESYSTEM_HAIKU
+#undef SDL_FILESYSTEM_COCOA
+#undef SDL_FILESYSTEM_DUMMY
+#undef SDL_FILESYSTEM_UNIX
+#undef SDL_FILESYSTEM_WINDOWS
+#undef SDL_FILESYSTEM_NACL
+#undef SDL_FILESYSTEM_ANDROID
+#undef SDL_FILESYSTEM_EMSCRIPTEN
+
+/* Enable assembly routines */
+#undef SDL_ASSEMBLY_ROUTINES
+#undef SDL_ALTIVEC_BLITTERS
+
+/* Enable ime support */
+#undef SDL_USE_IME
+
+/* Enable dynamic udev support */
+#undef SDL_UDEV_DYNAMIC
+
+/* Enable dynamic libsamplerate support */
+#undef SDL_LIBSAMPLERATE_DYNAMIC
+
+#endif /* SDL_config_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_android.h b/Client/ThirdParty/SDL2/include/SDL_config_android.h
new file mode 100644
index 0000000..361bad8
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_android.h
@@ -0,0 +1,157 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_android_h_
+#define SDL_config_android_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/**
+ * \file SDL_config_android.h
+ *
+ * This is a configuration that can be used to build SDL for Android
+ */
+
+#include <stdarg.h>
+
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_CLOCK_GETTIME 1
+
+#define SIZEOF_VOIDP 4
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_ANDROID 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_ANDROID 1
+#define SDL_HAPTIC_ANDROID 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_ANDROID 1
+
+/* Enable OpenGL ES */
+#define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_EGL 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+
+/* Enable Vulkan support */
+/* Android does not support Vulkan in native code using the "armeabi" ABI. */
+#if defined(__ARM_ARCH) && __ARM_ARCH < 7
+#define SDL_VIDEO_VULKAN 0
+#else
+#define SDL_VIDEO_VULKAN 1
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_ANDROID 1
+
+/* Enable the filesystem driver */
+#define SDL_FILESYSTEM_ANDROID 1
+
+#endif /* SDL_config_android_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_iphoneos.h b/Client/ThirdParty/SDL2/include/SDL_config_iphoneos.h
new file mode 100644
index 0000000..deea030
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_iphoneos.h
@@ -0,0 +1,166 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_iphoneos_h_
+#define SDL_config_iphoneos_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+
+/* enable iPhone version of Core Audio driver */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DUMMY 1
+
+/* Enable MFi joystick support */
+#define SDL_JOYSTICK_MFI 1
+
+/* Enable Unix style SO loading */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Supported video drivers */
+#define SDL_VIDEO_DRIVER_UIKIT 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+/* enable OpenGL ES */
+#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+
+/* Enable Vulkan support */
+#if !TARGET_OS_SIMULATOR && !TARGET_CPU_ARM // Only 64-bit devices have Metal
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_UIKIT 1
+
+/* enable iPhone keyboard support */
+#define SDL_IPHONE_KEYBOARD 1
+
+/* enable iOS extended launch screen */
+#define SDL_IPHONE_LAUNCHSCREEN 1
+
+/* Set max recognized G-force from accelerometer
+ See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
+ */
+#define SDL_IPHONE_MAX_GFORCE 5.0
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+#endif /* SDL_config_iphoneos_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_macosx.h b/Client/ThirdParty/SDL2/include/SDL_config_macosx.h
new file mode 100644
index 0000000..9b09899
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_macosx.h
@@ -0,0 +1,197 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_macosx_h_
+#define SDL_config_macosx_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
+#include <AvailabilityMacros.h>
+
+/* This is a set of defines to configure the SDL features */
+
+#ifdef __LP64__
+ #define SIZEOF_VOIDP 8
+#else
+ #define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_IOKIT 1
+#define SDL_HAPTIC_IOKIT 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_COCOA 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#undef SDL_VIDEO_DRIVER_X11
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_XDBE 1
+#define SDL_VIDEO_DRIVER_X11_XINERAMA 1
+#define SDL_VIDEO_DRIVER_X11_XRANDR 1
+#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
+#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
+#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1
+#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
+
+#ifdef MAC_OS_X_VERSION_10_8
+/*
+ * No matter the versions targeted, this is the 10.8 or later SDK, so you have
+ * to use the external Xquartz, which is a more modern Xlib. Previous SDKs
+ * used an older Xlib.
+ */
+#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1
+#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 1
+#endif
+
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_CGL
+#define SDL_VIDEO_OPENGL_CGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_GLX
+#define SDL_VIDEO_OPENGL_GLX 1
+#endif
+
+/* Enable Vulkan support */
+/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures with 10.11+ */
+#if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_MACOSX 1
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+/* Enable assembly routines */
+#define SDL_ASSEMBLY_ROUTINES 1
+#ifdef __ppc__
+#define SDL_ALTIVEC_BLITTERS 1
+#endif
+
+#endif /* SDL_config_macosx_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_macosx.h.orig b/Client/ThirdParty/SDL2/include/SDL_config_macosx.h.orig
new file mode 100644
index 0000000..f03f1ae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_macosx.h.orig
@@ -0,0 +1,197 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_macosx_h_
+#define SDL_config_macosx_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
+#include <AvailabilityMacros.h>
+
+/* This is a set of defines to configure the SDL features */
+
+#ifdef __LP64__
+ #define SIZEOF_VOIDP 8
+#else
+ #define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_IOKIT 1
+#define SDL_HAPTIC_IOKIT 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_COCOA 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#undef SDL_VIDEO_DRIVER_X11
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/usr/X11R6/lib/libX11.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/usr/X11R6/lib/libXext.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA "/usr/X11R6/lib/libXinerama.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/usr/X11R6/lib/libXi.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/usr/X11R6/lib/libXrandr.2.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/usr/X11R6/lib/libXss.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE "/usr/X11R6/lib/libXxf86vm.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_XDBE 1
+#define SDL_VIDEO_DRIVER_X11_XINERAMA 1
+#define SDL_VIDEO_DRIVER_X11_XRANDR 1
+#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
+#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
+#define SDL_VIDEO_DRIVER_X11_XVIDMODE 1
+#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
+
+#ifdef MAC_OS_X_VERSION_10_8
+/*
+ * No matter the versions targeted, this is the 10.8 or later SDK, so you have
+ * to use the external Xquartz, which is a more modern Xlib. Previous SDKs
+ * used an older Xlib.
+ */
+#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1
+#define SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY 1
+#endif
+
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_CGL
+#define SDL_VIDEO_OPENGL_CGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_GLX
+#define SDL_VIDEO_OPENGL_GLX 1
+#endif
+
+/* Enable Vulkan support */
+/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures and 10.11+ */
+#if TARGET_CPU_X86_64
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_MACOSX 1
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+/* Enable assembly routines */
+#define SDL_ASSEMBLY_ROUTINES 1
+#ifdef __ppc__
+#define SDL_ALTIVEC_BLITTERS 1
+#endif
+
+#endif /* SDL_config_macosx_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_minimal.h b/Client/ThirdParty/SDL2/include/SDL_config_minimal.h
new file mode 100644
index 0000000..3112700
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_minimal.h
@@ -0,0 +1,82 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_minimal_h_
+#define SDL_config_minimal_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/**
+ * \file SDL_config_minimal.h
+ *
+ * This is the minimal configuration that can be used to build SDL.
+ */
+
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+
+/* Most everything except Visual Studio 2008 and earlier has stdint.h now */
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+/* Here are some reasonable defaults */
+typedef unsigned int size_t;
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+typedef unsigned long uintptr_t;
+#else
+#define HAVE_STDINT_H 1
+#endif /* Visual Studio 2008 */
+
+#ifdef __GNUC__
+#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1
+#endif
+
+/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable the stub joystick driver (src/joystick/dummy/\*.c) */
+#define SDL_JOYSTICK_DISABLED 1
+
+/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED 1
+
+/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */
+#define SDL_LOADSO_DISABLED 1
+
+/* Enable the stub thread support (src/thread/generic/\*.c) */
+#define SDL_THREADS_DISABLED 1
+
+/* Enable the stub timer support (src/timer/dummy/\*.c) */
+#define SDL_TIMERS_DISABLED 1
+
+/* Enable the dummy video driver (src/video/dummy/\*.c) */
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */
+#define SDL_FILESYSTEM_DUMMY 1
+
+#endif /* SDL_config_minimal_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_pandora.h b/Client/ThirdParty/SDL2/include/SDL_config_pandora.h
new file mode 100644
index 0000000..ea62fe5
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_pandora.h
@@ -0,0 +1,128 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_pandora_h_
+#define SDL_config_pandora_h_
+#define SDL_config_h_
+
+/* This is a set of defines to configure the SDL features */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+#ifdef __LP64__
+#define SIZEOF_VOIDP 8
+#else
+#define SIZEOF_VOIDP 4
+#endif
+
+#define SDL_BYTEORDER 1234
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_STRLEN 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+
+#define SDL_AUDIO_DRIVER_DUMMY 1
+#define SDL_AUDIO_DRIVER_OSS 1
+
+#define SDL_INPUT_LINUXEV 1
+#define SDL_INPUT_TSLIB 1
+#define SDL_JOYSTICK_LINUX 1
+#define SDL_HAPTIC_LINUX 1
+
+#define SDL_LOADSO_DLOPEN 1
+
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1
+
+#define SDL_TIMER_UNIX 1
+#define SDL_FILESYSTEM_UNIX 1
+
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_X11 1
+#define SDL_VIDEO_DRIVER_PANDORA 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_OPENGL_ES 1
+
+#endif /* SDL_config_pandora_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_psp.h b/Client/ThirdParty/SDL2/include/SDL_config_psp.h
new file mode 100644
index 0000000..28efb4c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_psp.h
@@ -0,0 +1,144 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_psp_h_
+#define SDL_config_psp_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+
+
+#ifdef __GNUC__
+#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1
+#endif
+
+#define HAVE_GCC_ATOMICS 1
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_SETENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+/* #define HAVE_SYSCONF 1 */
+/* #define HAVE_SIGACTION 1 */
+
+
+/* PSP isn't that sophisticated */
+#define LACKS_SYS_MMAN_H 1
+
+/* Enable the stub thread support (src/thread/psp/\*.c) */
+#define SDL_THREAD_PSP 1
+
+/* Enable the stub timer support (src/timer/psp/\*.c) */
+#define SDL_TIMERS_PSP 1
+
+/* Enable the stub joystick driver (src/joystick/psp/\*.c) */
+#define SDL_JOYSTICK_PSP 1
+
+/* Enable the stub audio driver (src/audio/psp/\*.c) */
+#define SDL_AUDIO_DRIVER_PSP 1
+
+/* PSP video dirver */
+#define SDL_VIDEO_DRIVER_PSP 1
+
+/* PSP render dirver */
+#define SDL_VIDEO_RENDER_PSP 1
+
+#define SDL_POWER_PSP 1
+
+/* !!! FIXME: what does PSP do for filesystem stuff? */
+#define SDL_FILESYSTEM_DUMMY 1
+
+/* PSP doesn't have haptic device (src/haptic/dummy/\*.c) */
+#define SDL_HAPTIC_DISABLED 1
+
+/* PSP can't load shared object (src/loadso/dummy/\*.c) */
+#define SDL_LOADSO_DISABLED 1
+
+
+#endif /* SDL_config_psp_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_windows.h b/Client/ThirdParty/SDL2/include/SDL_config_windows.h
new file mode 100644
index 0000000..2456c84
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_windows.h
@@ -0,0 +1,225 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_windows_h_
+#define SDL_config_windows_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* This is a set of defines to configure the SDL features */
+
+#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
+#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H 1
+#elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#endif
+#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#endif
+#else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#endif
+typedef unsigned int uintptr_t;
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
+
+#define HAVE_DDRAW_H 1
+#define HAVE_DINPUT_H 1
+#define HAVE_DSOUND_H 1
+#define HAVE_DXGI_H 1
+#define HAVE_XINPUT_H 1
+
+/* This is disabled by default to avoid C runtime dependencies and manifest requirements */
+#ifdef HAVE_LIBC
+/* Useful headers */
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE__STRREV 1
+#define HAVE__STRUPR 1
+#define HAVE__STRLWR 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE__LTOA 1
+#define HAVE__ULTOA 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE__STRICMP 1
+#define HAVE__STRNICMP 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_ACOS 1
+#define HAVE_ASIN 1
+#define HAVE_CEIL 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#if _MSC_VER >= 1800
+#define HAVE_STRTOLL 1
+#define HAVE_VSSCANF 1
+#define HAVE_COPYSIGN 1
+#define HAVE_SCALBN 1
+#endif
+#if !defined(_MSC_VER) || defined(_USE_MATH_DEFINES)
+#define HAVE_M_PI 1
+#endif
+#else
+#define HAVE_STDARG_H 1
+#define HAVE_STDDEF_H 1
+#endif
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_WASAPI 1
+#define SDL_AUDIO_DRIVER_DSOUND 1
+#define SDL_AUDIO_DRIVER_XAUDIO2 0
+#define SDL_AUDIO_DRIVER_WINMM 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_DINPUT 1
+#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_DINPUT 1
+#define SDL_HAPTIC_XINPUT 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_WINDOWS 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_WINDOWS 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_WINDOWS 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_WINDOWS 1
+
+#ifndef SDL_VIDEO_RENDER_D3D
+#define SDL_VIDEO_RENDER_D3D 1
+#endif
+#ifndef SDL_VIDEO_RENDER_D3D11
+#define SDL_VIDEO_RENDER_D3D11 0
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_WGL
+#define SDL_VIDEO_OPENGL_WGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+#ifndef SDL_VIDEO_RENDER_OGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_OPENGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_EGL
+#define SDL_VIDEO_OPENGL_EGL 1
+#endif
+
+/* Enable Vulkan support */
+#define SDL_VIDEO_VULKAN 1
+
+/* Enable system power support */
+#define SDL_POWER_WINDOWS 1
+
+/* Enable filesystem support */
+#define SDL_FILESYSTEM_WINDOWS 1
+
+/* Enable assembly routines (Win64 doesn't have inline asm) */
+#ifndef _WIN64
+#define SDL_ASSEMBLY_ROUTINES 1
+#endif
+
+#endif /* SDL_config_windows_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_winrt.h b/Client/ThirdParty/SDL2/include/SDL_config_winrt.h
new file mode 100644
index 0000000..24f9e17
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_winrt.h
@@ -0,0 +1,215 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_winrt_h_
+#define SDL_config_winrt_h_
+#define SDL_config_h_
+
+#include "SDL_platform.h"
+
+/* Make sure the Windows SDK's NTDDI_VERSION macro gets defined. This is used
+ by SDL to determine which version of the Windows SDK is being used.
+*/
+#include <sdkddkver.h>
+
+/* Define possibly-undefined NTDDI values (used when compiling SDL against
+ older versions of the Windows SDK.
+*/
+#ifndef NTDDI_WINBLUE
+#define NTDDI_WINBLUE 0x06030000
+#endif
+#ifndef NTDDI_WIN10
+#define NTDDI_WIN10 0x0A000000
+#endif
+
+/* This is a set of defines to configure the SDL features */
+
+#if !defined(_STDINT_H_) && (!defined(HAVE_STDINT_H) || !_HAVE_STDINT_H)
+#if defined(__GNUC__) || defined(__DMC__) || defined(__WATCOMC__)
+#define HAVE_STDINT_H 1
+#elif defined(_MSC_VER)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+/* Older Visual C++ headers don't have the Win64-compatible typedefs... */
+#if ((_MSC_VER <= 1200) && (!defined(DWORD_PTR)))
+#define DWORD_PTR DWORD
+#endif
+#if ((_MSC_VER <= 1200) && (!defined(LONG_PTR)))
+#define LONG_PTR LONG
+#endif
+#else /* !__GNUC__ && !_MSC_VER */
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#ifndef _SIZE_T_DEFINED_
+#define _SIZE_T_DEFINED_
+typedef unsigned int size_t;
+#endif
+typedef unsigned int uintptr_t;
+#endif /* __GNUC__ || _MSC_VER */
+#endif /* !_STDINT_H_ && !HAVE_STDINT_H */
+
+#ifdef _WIN64
+# define SIZEOF_VOIDP 8
+#else
+# define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define HAVE_DXGI_H 1
+#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+#define HAVE_XINPUT_H 1
+#endif
+#define HAVE_LIBC 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STRING_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_SIGNAL_H 1
+
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE__STRREV 1
+#define HAVE__STRUPR 1
+//#define HAVE__STRLWR 1 // TODO, WinRT: consider using _strlwr_s instead
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+//#define HAVE_ITOA 1 // TODO, WinRT: consider using _itoa_s instead
+//#define HAVE__LTOA 1 // TODO, WinRT: consider using _ltoa_s instead
+//#define HAVE__ULTOA 1 // TODO, WinRT: consider using _ultoa_s instead
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+//#define HAVE_STRTOLL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE__STRICMP 1
+#define HAVE__STRNICMP 1
+#define HAVE_VSNPRINTF 1
+//#define HAVE_SSCANF 1 // TODO, WinRT: consider using sscanf_s instead
+#define HAVE_M_PI 1
+#define HAVE_ATAN 1
+#define HAVE_ATAN2 1
+#define HAVE_CEIL 1
+#define HAVE__COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_POW 1
+//#define HAVE_SCALBN 1
+#define HAVE__SCALB 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE__FSEEKI64 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_XAUDIO2 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+#define SDL_JOYSTICK_DISABLED 1
+#define SDL_HAPTIC_DISABLED 1
+#else
+#define SDL_JOYSTICK_XINPUT 1
+#define SDL_HAPTIC_XINPUT 1
+#endif
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_WINDOWS 1
+
+/* Enable various threading systems */
+#if (NTDDI_VERSION >= NTDDI_WINBLUE)
+#define SDL_THREAD_WINDOWS 1
+#else
+/* WinRT on Windows 8.0 and Windows Phone 8.0 don't support CreateThread() */
+#define SDL_THREAD_STDCPP 1
+#endif
+
+/* Enable various timer systems */
+#define SDL_TIMER_WINDOWS 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_WINRT 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+
+/* Enable OpenGL ES 2.0 (via a modified ANGLE library) */
+#define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_EGL 1
+
+/* Enable appropriate renderer(s) */
+#define SDL_VIDEO_RENDER_D3D11 1
+
+#if SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_WINRT 1
+
+/* Enable assembly routines (Win64 doesn't have inline asm) */
+#ifndef _WIN64
+#define SDL_ASSEMBLY_ROUTINES 1
+#endif
+
+#endif /* SDL_config_winrt_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_config_wiz.h b/Client/ThirdParty/SDL2/include/SDL_config_wiz.h
new file mode 100644
index 0000000..5bb845a
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_config_wiz.h
@@ -0,0 +1,121 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_wiz_h_
+#define SDL_config_wiz_h_
+#define SDL_config_h_
+
+/* This is a set of defines to configure the SDL features */
+
+/* General platform specific identifiers */
+#include "SDL_platform.h"
+
+#define SDL_BYTEORDER 1234
+
+#define HAVE_ALLOCA_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+#define HAVE_MALLOC_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_STRLEN 1
+#define HAVE_STRDUP 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_CEIL 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_FABS 1
+#define HAVE_FLOOR 1
+#define HAVE_LOG 1
+#define HAVE_SCALBN 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_POW 1
+
+#define SDL_AUDIO_DRIVER_DUMMY 1
+#define SDL_AUDIO_DRIVER_OSS 1
+
+#define SDL_INPUT_LINUXEV 1
+#define SDL_INPUT_TSLIB 1
+#define SDL_JOYSTICK_LINUX 1
+#define SDL_HAPTIC_LINUX 1
+
+#define SDL_LOADSO_DLOPEN 1
+
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1
+
+#define SDL_TIMER_UNIX 1
+
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#define SDL_VIDEO_DRIVER_PANDORA 1
+#define SDL_VIDEO_RENDER_OGL_ES 1
+#define SDL_VIDEO_OPENGL_ES 1
+
+#endif /* SDL_config_wiz_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_copying.h b/Client/ThirdParty/SDL2/include/SDL_copying.h
new file mode 100644
index 0000000..8f60af6
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_copying.h
@@ -0,0 +1,20 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
diff --git a/Client/ThirdParty/SDL2/include/SDL_cpuinfo.h b/Client/ThirdParty/SDL2/include/SDL_cpuinfo.h
new file mode 100644
index 0000000..4401c37
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_cpuinfo.h
@@ -0,0 +1,524 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_cpuinfo.h
+ *
+ * CPU feature detection for SDL.
+ */
+
+#ifndef SDL_cpuinfo_h_
+#define SDL_cpuinfo_h_
+
+#include "SDL_stdinc.h"
+
+/* Need to do this here because intrin.h has C++ code in it */
+/* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64))
+#ifdef __clang__
+/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
+ so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
+
+#ifndef __PRFCHWINTRIN_H
+#define __PRFCHWINTRIN_H
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+#endif /* __PRFCHWINTRIN_H */
+#endif /* __clang__ */
+#include <intrin.h>
+#ifndef _WIN64
+#ifndef __MMX__
+#define __MMX__
+#endif
+#ifndef __3dNOW__
+#define __3dNOW__
+#endif
+#endif
+#ifndef __SSE__
+#define __SSE__
+#endif
+#ifndef __SSE2__
+#define __SSE2__
+#endif
+#elif defined(__MINGW64_VERSION_MAJOR)
+#include <intrin.h>
+#if !defined(SDL_DISABLE_ARM_NEON_H) && defined(__ARM_NEON)
+# include <arm_neon.h>
+#endif
+#else
+/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */
+#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H)
+#include <altivec.h>
+#endif
+#if !defined(SDL_DISABLE_ARM_NEON_H)
+# if defined(__ARM_NEON)
+# include <arm_neon.h>
+# elif defined(__WINDOWS__) || defined(__WINRT__)
+/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */
+# if defined(_M_ARM)
+# include <armintr.h>
+# include <arm_neon.h>
+# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
+# endif
+# if defined (_M_ARM64)
+# include <arm64intr.h>
+# include <arm64_neon.h>
+# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
+# endif
+# endif
+#endif
+#endif /* compiler version */
+
+#if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
+#include <mm3dnow.h>
+#endif
+#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
+#include <immintrin.h>
+#else
+#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H)
+#include <mmintrin.h>
+#endif
+#if defined(__SSE__) && !defined(SDL_DISABLE_XMMINTRIN_H)
+#include <xmmintrin.h>
+#endif
+#if defined(__SSE2__) && !defined(SDL_DISABLE_EMMINTRIN_H)
+#include <emmintrin.h>
+#endif
+#if defined(__SSE3__) && !defined(SDL_DISABLE_PMMINTRIN_H)
+#include <pmmintrin.h>
+#endif
+#endif /* HAVE_IMMINTRIN_H */
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This is a guess for the cacheline size used for padding.
+ * Most x86 processors have a 64 byte cache line.
+ * The 64-bit PowerPC processors have a 128 byte cache line.
+ * We'll use the larger value to be generally safe.
+ */
+#define SDL_CACHELINE_SIZE 128
+
+/**
+ * Get the number of CPU cores available.
+ *
+ * \returns the total number of logical CPU cores. On CPUs that include
+ * technologies such as hyperthreading, the number of logical cores
+ * may be more than the number of physical cores.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GetCPUCount(void);
+
+/**
+ * Determine the L1 cache line size of the CPU.
+ *
+ * This is useful for determining multi-threaded structure padding or SIMD
+ * prefetch sizes.
+ *
+ * \returns the L1 cache line size of the CPU, in bytes.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GetCPUCacheLineSize(void);
+
+/**
+ * Determine whether the CPU has the RDTSC instruction.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has the RDTSC instruction or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(void);
+
+/**
+ * Determine whether the CPU has AltiVec features.
+ *
+ * This always returns false on CPUs that aren't using PowerPC instruction
+ * sets.
+ *
+ * \returns SDL_TRUE if the CPU has AltiVec features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void);
+
+/**
+ * Determine whether the CPU has MMX features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has MMX features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void);
+
+/**
+ * Determine whether the CPU has 3DNow! features.
+ *
+ * This always returns false on CPUs that aren't using AMD instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has 3DNow! features or SDL_FALSE if not.
+ *
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(void);
+
+/**
+ * Determine whether the CPU has SSE features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void);
+
+/**
+ * Determine whether the CPU has SSE2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE2 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void);
+
+/**
+ * Determine whether the CPU has SSE3 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE3 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE3(void);
+
+/**
+ * Determine whether the CPU has SSE4.1 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE4.1 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void);
+
+/**
+ * Determine whether the CPU has SSE4.2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE4.2 features or SDL_FALSE if not.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void);
+
+/**
+ * Determine whether the CPU has AVX features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void);
+
+/**
+ * Determine whether the CPU has AVX2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX2 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
+
+/**
+ * Determine whether the CPU has AVX-512F (foundation) features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX-512F features or SDL_FALSE if not.
+ *
+ * \sa SDL_HasAVX
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
+
+/**
+ * Determine whether the CPU has ARM SIMD (ARMv6) features.
+ *
+ * This is different from ARM NEON, which is a different instruction set.
+ *
+ * This always returns false on CPUs that aren't using ARM instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has ARM SIMD features or SDL_FALSE if not.
+ *
+ * \sa SDL_HasNEON
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void);
+
+/**
+ * Determine whether the CPU has NEON (ARM SIMD) features.
+ *
+ * This always returns false on CPUs that aren't using ARM instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has ARM NEON features or SDL_FALSE if not.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
+
+/**
+ * Get the amount of RAM configured in the system.
+ *
+ * \returns the amount of RAM configured in the system in MB.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
+
+/**
+ * Report the alignment this system needs for SIMD allocations.
+ *
+ * This will return the minimum number of bytes to which a pointer must be
+ * aligned to be compatible with SIMD instructions on the current machine. For
+ * example, if the machine supports SSE only, it will return 16, but if it
+ * supports AVX-512F, it'll return 64 (etc). This only reports values for
+ * instruction sets SDL knows about, so if your SDL build doesn't have
+ * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and
+ * not 64 for the AVX-512 instructions that exist but SDL doesn't know about.
+ * Plan accordingly.
+ *
+ * \returns the alignment in bytes needed for available, known SIMD
+ * instructions.
+ */
+extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void);
+
+/**
+ * Allocate memory in a SIMD-friendly way.
+ *
+ * This will allocate a block of memory that is suitable for use with SIMD
+ * instructions. Specifically, it will be properly aligned and padded for the
+ * system's supported vector instructions.
+ *
+ * The memory returned will be padded such that it is safe to read or write an
+ * incomplete vector at the end of the memory block. This can be useful so you
+ * don't have to drop back to a scalar fallback at the end of your SIMD
+ * processing loop to deal with the final elements without overflowing the
+ * allocated buffer.
+ *
+ * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() or
+ * delete[], etc.
+ *
+ * Note that SDL will only deal with SIMD instruction sets it is aware of; for
+ * example, SDL 2.0.8 knows that SSE wants 16-byte vectors (SDL_HasSSE()), and
+ * AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't know that AVX-512 wants
+ * 64. To be clear: if you can't decide to use an instruction set with an
+ * SDL_Has*() function, don't use that instruction set with memory allocated
+ * through here.
+ *
+ * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't
+ * out of memory, but you are not allowed to dereference it (because you only
+ * own zero bytes of that buffer).
+ *
+ * \param len The length, in bytes, of the block to allocate. The actual
+ * allocated block might be larger due to padding, etc.
+ * \returns a pointer to thenewly-allocated block, NULL if out of memory.
+ *
+ * \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDRealloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
+
+/**
+ * Reallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
+ * SDL_malloc, memalign, new[], etc.
+ *
+ * \param mem The pointer obtained from SDL_SIMDAlloc. This function also
+ * accepts NULL, at which point this function is the same as
+ * calling SDL_SIMDAlloc with a NULL pointer.
+ * \param len The length, in bytes, of the block to allocated. The actual
+ * allocated block might be larger due to padding, etc. Passing 0
+ * will return a non-NULL pointer, assuming the system isn't out of
+ * memory.
+ * \returns a pointer to the newly-reallocated block, NULL if out of memory.
+ *
+ * \sa SDL_SIMDAlignment
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, const size_t len);
+
+/**
+ * Deallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc() or SDL_SIMDRealloc(). It can't be used on pointers from
+ * malloc, realloc, SDL_malloc, memalign, new[], etc.
+ *
+ * However, SDL_SIMDFree(NULL) is a legal no-op.
+ *
+ * The memory pointed to by `ptr` is no longer valid for access upon return,
+ * and may be returned to the system or reused by a future allocation. The
+ * pointer passed to this function is no longer safe to dereference once this
+ * function returns, and should be discarded.
+ *
+ * \param ptr The pointer, returned from SDL_SIMDAlloc or SDL_SIMDRealloc, to
+ * deallocate. NULL is a legal no-op.
+ *
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDRealloc
+ */
+extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_cpuinfo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_egl.h b/Client/ThirdParty/SDL2/include/SDL_egl.h
new file mode 100644
index 0000000..223357e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_egl.h
@@ -0,0 +1,1676 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_egl.h
+ *
+ * This is a simple file to encapsulate the EGL API headers.
+ */
+#if !defined(_MSC_VER) && !defined(__ANDROID__)
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#else /* _MSC_VER */
+
+/* EGL headers for Visual Studio */
+
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+*
+* $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+*
+* Adopters may modify this file to suit their platform. Adopters are
+* encouraged to submit platform specific modifications to the Khronos
+* group so that they can be included in future versions of this file.
+* Please submit changes by sending them to the public Khronos Bugzilla
+* (http://khronos.org/bugzilla) by filing a bug against product
+* "Khronos (general)" component "Registry".
+*
+* A predefined template which fills in some of the bug fields can be
+* reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+* must create a Bugzilla login first.
+*
+*
+* See the Implementer's Guidelines for information about where this file
+* should be located on your system and for more details of its use:
+* http://www.khronos.org/registry/implementers_guide.pdf
+*
+* This file should be included as
+* #include <KHR/khrplatform.h>
+* by Khronos client API header files that use its types and defines.
+*
+* The types in khrplatform.h should only be used to define API-specific types.
+*
+* Types defined in khrplatform.h:
+* khronos_int8_t signed 8 bit
+* khronos_uint8_t unsigned 8 bit
+* khronos_int16_t signed 16 bit
+* khronos_uint16_t unsigned 16 bit
+* khronos_int32_t signed 32 bit
+* khronos_uint32_t unsigned 32 bit
+* khronos_int64_t signed 64 bit
+* khronos_uint64_t unsigned 64 bit
+* khronos_intptr_t signed same number of bits as a pointer
+* khronos_uintptr_t unsigned same number of bits as a pointer
+* khronos_ssize_t signed size
+* khronos_usize_t unsigned size
+* khronos_float_t signed 32 bit floating point
+* khronos_time_ns_t unsigned 64 bit time in nanoseconds
+* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+* nanoseconds
+* khronos_stime_nanoseconds_t signed time interval in nanoseconds
+* khronos_boolean_enum_t enumerated boolean type. This should
+* only be used as a base type when a client API's boolean type is
+* an enum. Client APIs which use an integer or other type for
+* booleans cannot use this as the base type for their boolean.
+*
+* Tokens defined in khrplatform.h:
+*
+* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+*
+* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+*
+* Calling convention macros defined in this file:
+* KHRONOS_APICALL
+* KHRONOS_APIENTRY
+* KHRONOS_APIATTRIBUTES
+*
+* These may be used in function prototypes as:
+*
+* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+* int arg1,
+* int arg2) KHRONOS_APIATTRIBUTES;
+*/
+
+/*-------------------------------------------------------------------------
+* Definition of KHRONOS_APICALL
+*-------------------------------------------------------------------------
+* This precedes the return type of the function in the function prototype.
+*/
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(SDL_VIDEO_STATIC_ANGLE)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+* Definition of KHRONOS_APIENTRY
+*-------------------------------------------------------------------------
+* This follows the return type of the function and precedes the function
+* name in the function prototype.
+*/
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+/* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+* Definition of KHRONOS_APIATTRIBUTES
+*-------------------------------------------------------------------------
+* This follows the closing parenthesis of the function prototype arguments.
+*/
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+* basic type definitions
+*-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+* Using <stdint.h>
+*/
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+* Using <inttypes.h>
+*/
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+* Win32
+*/
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+* Sun or Digital
+*/
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+* Hypothetical platform with no float or int64 support
+*/
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+* Generic fallback
+*/
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+* Types that are (so far) the same on all platforms
+*/
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+* Types that differ between LLP64 and LP64 architectures - in LLP64,
+* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+* to be the only LLP64 architecture in current use.
+*/
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+* Float type
+*/
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+*
+* These types can be used to represent a time interval in nanoseconds or
+* an absolute Unadjusted System Time. Unadjusted System Time is the number
+* of nanoseconds since some arbitrary system event (e.g. since the last
+* time the system booted). The Unadjusted System Time is an unsigned
+* 64 bit value that wraps back to 0 every 584 years. Time intervals
+* may be either signed or unsigned.
+*/
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+* Dummy value used to pad enum types to 32 bits.
+*/
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+* Enumerated boolean type
+*
+* Values other than zero should be considered to be true. Therefore
+* comparisons should not be made against KHRONOS_TRUE.
+*/
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
+
+
+#ifndef __eglplatform_h_
+#define __eglplatform_h_
+
+/*
+** Copyright (c) 2007-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Platform-specific types and definitions for egl.h
+* $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $
+*
+* Adopters may modify khrplatform.h and this file to suit their platform.
+* You are encouraged to submit all modifications to the Khronos group so that
+* they can be included in future versions of this file. Please submit changes
+* by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+* by filing a bug against product "EGL" component "Registry".
+*/
+
+/*#include <KHR/khrplatform.h>*/
+
+/* Macros used in EGL function prototype declarations.
+*
+* EGL functions should be prototyped as:
+*
+* EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
+* typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
+*
+* KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
+*/
+
+#ifndef EGLAPI
+#define EGLAPI KHRONOS_APICALL
+#endif
+
+#ifndef EGLAPIENTRY
+#define EGLAPIENTRY KHRONOS_APIENTRY
+#endif
+#define EGLAPIENTRYP EGLAPIENTRY*
+
+/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
+* are aliases of window-system-dependent types, such as X Display * or
+* Windows Device Context. They must be defined in platform-specific
+* code below. The EGL-prefixed versions of Native*Type are the same
+* types, renamed in EGL 1.3 so all types in the API start with "EGL".
+*
+* Khronos STRONGLY RECOMMENDS that you use the default definitions
+* provided below, since these changes affect both binary and source
+* portability of applications using EGL running on different EGL
+* implementations.
+*/
+
+#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+
+#if __WINRT__
+#include <Unknwn.h>
+typedef IUnknown * EGLNativeWindowType;
+typedef IUnknown * EGLNativePixmapType;
+typedef IUnknown * EGLNativeDisplayType;
+#else
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND EGLNativeWindowType;
+#endif
+
+#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
+
+typedef int EGLNativeDisplayType;
+typedef void *EGLNativeWindowType;
+typedef void *EGLNativePixmapType;
+
+#elif defined(WL_EGL_PLATFORM)
+
+typedef struct wl_display *EGLNativeDisplayType;
+typedef struct wl_egl_pixmap *EGLNativePixmapType;
+typedef struct wl_egl_window *EGLNativeWindowType;
+
+#elif defined(__GBM__)
+
+typedef struct gbm_device *EGLNativeDisplayType;
+typedef struct gbm_bo *EGLNativePixmapType;
+typedef void *EGLNativeWindowType;
+
+#elif defined(__ANDROID__) /* Android */
+
+struct ANativeWindow;
+struct egl_native_pixmap_t;
+
+typedef struct ANativeWindow *EGLNativeWindowType;
+typedef struct egl_native_pixmap_t *EGLNativePixmapType;
+typedef void *EGLNativeDisplayType;
+
+#elif defined(MIR_EGL_PLATFORM)
+
+#include <mir_toolkit/mir_client_library.h>
+typedef MirEGLNativeDisplayType EGLNativeDisplayType;
+typedef void *EGLNativePixmapType;
+typedef MirEGLNativeWindowType EGLNativeWindowType;
+
+#elif defined(__unix__)
+
+#ifdef MESA_EGL_NO_X11_HEADERS
+
+typedef void *EGLNativeDisplayType;
+typedef khronos_uintptr_t EGLNativePixmapType;
+typedef khronos_uintptr_t EGLNativeWindowType;
+
+#else
+
+/* X11 (tentative) */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+
+#endif /* MESA_EGL_NO_X11_HEADERS */
+
+#else
+#error "Platform not recognized"
+#endif
+
+/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
+typedef EGLNativeDisplayType NativeDisplayType;
+typedef EGLNativePixmapType NativePixmapType;
+typedef EGLNativeWindowType NativeWindowType;
+
+
+/* Define EGLint. This must be a signed integral type large enough to contain
+* all legal attribute names and values passed into and out of EGL, whether
+* their type is boolean, bitmask, enumerant (symbolic constant), integer,
+* handle, or other. While in general a 32-bit integer will suffice, if
+* handles are 64 bit types, then EGLint should be defined as a signed 64-bit
+* integer type.
+*/
+typedef khronos_int32_t EGLint;
+
+#endif /* __eglplatform_h */
+
+#ifndef __egl_h_
+#define __egl_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
+*/
+
+/*#include <EGL/eglplatform.h>*/
+
+/* Generated on date 20150623 */
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_VERSION_1_0
+#define EGL_VERSION_1_0 1
+typedef unsigned int EGLBoolean;
+typedef void *EGLDisplay;
+typedef void *EGLConfig;
+typedef void *EGLSurface;
+typedef void *EGLContext;
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+#define EGL_ALPHA_SIZE 0x3021
+#define EGL_BAD_ACCESS 0x3002
+#define EGL_BAD_ALLOC 0x3003
+#define EGL_BAD_ATTRIBUTE 0x3004
+#define EGL_BAD_CONFIG 0x3005
+#define EGL_BAD_CONTEXT 0x3006
+#define EGL_BAD_CURRENT_SURFACE 0x3007
+#define EGL_BAD_DISPLAY 0x3008
+#define EGL_BAD_MATCH 0x3009
+#define EGL_BAD_NATIVE_PIXMAP 0x300A
+#define EGL_BAD_NATIVE_WINDOW 0x300B
+#define EGL_BAD_PARAMETER 0x300C
+#define EGL_BAD_SURFACE 0x300D
+#define EGL_BLUE_SIZE 0x3022
+#define EGL_BUFFER_SIZE 0x3020
+#define EGL_CONFIG_CAVEAT 0x3027
+#define EGL_CONFIG_ID 0x3028
+#define EGL_CORE_NATIVE_ENGINE 0x305B
+#define EGL_DEPTH_SIZE 0x3025
+#define EGL_DONT_CARE ((EGLint)-1)
+#define EGL_DRAW 0x3059
+#define EGL_EXTENSIONS 0x3055
+#define EGL_FALSE 0
+#define EGL_GREEN_SIZE 0x3023
+#define EGL_HEIGHT 0x3056
+#define EGL_LARGEST_PBUFFER 0x3058
+#define EGL_LEVEL 0x3029
+#define EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define EGL_MAX_PBUFFER_PIXELS 0x302B
+#define EGL_MAX_PBUFFER_WIDTH 0x302C
+#define EGL_NATIVE_RENDERABLE 0x302D
+#define EGL_NATIVE_VISUAL_ID 0x302E
+#define EGL_NATIVE_VISUAL_TYPE 0x302F
+#define EGL_NONE 0x3038
+#define EGL_NON_CONFORMANT_CONFIG 0x3051
+#define EGL_NOT_INITIALIZED 0x3001
+#define EGL_NO_CONTEXT ((EGLContext)0)
+#define EGL_NO_DISPLAY ((EGLDisplay)0)
+#define EGL_NO_SURFACE ((EGLSurface)0)
+#define EGL_PBUFFER_BIT 0x0001
+#define EGL_PIXMAP_BIT 0x0002
+#define EGL_READ 0x305A
+#define EGL_RED_SIZE 0x3024
+#define EGL_SAMPLES 0x3031
+#define EGL_SAMPLE_BUFFERS 0x3032
+#define EGL_SLOW_CONFIG 0x3050
+#define EGL_STENCIL_SIZE 0x3026
+#define EGL_SUCCESS 0x3000
+#define EGL_SURFACE_TYPE 0x3033
+#define EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define EGL_TRANSPARENT_RED_VALUE 0x3037
+#define EGL_TRANSPARENT_RGB 0x3052
+#define EGL_TRANSPARENT_TYPE 0x3034
+#define EGL_TRUE 1
+#define EGL_VENDOR 0x3053
+#define EGL_VERSION 0x3054
+#define EGL_WIDTH 0x3057
+#define EGL_WINDOW_BIT 0x0004
+EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void);
+EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id);
+EGLAPI EGLint EGLAPIENTRY eglGetError (void);
+EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname);
+EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor);
+EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface);
+EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine);
+#endif /* EGL_VERSION_1_0 */
+
+#ifndef EGL_VERSION_1_1
+#define EGL_VERSION_1_1 1
+#define EGL_BACK_BUFFER 0x3084
+#define EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define EGL_CONTEXT_LOST 0x300E
+#define EGL_MIN_SWAP_INTERVAL 0x303B
+#define EGL_MAX_SWAP_INTERVAL 0x303C
+#define EGL_MIPMAP_TEXTURE 0x3082
+#define EGL_MIPMAP_LEVEL 0x3083
+#define EGL_NO_TEXTURE 0x305C
+#define EGL_TEXTURE_2D 0x305F
+#define EGL_TEXTURE_FORMAT 0x3080
+#define EGL_TEXTURE_RGB 0x305D
+#define EGL_TEXTURE_RGBA 0x305E
+#define EGL_TEXTURE_TARGET 0x3081
+EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval);
+#endif /* EGL_VERSION_1_1 */
+
+#ifndef EGL_VERSION_1_2
+#define EGL_VERSION_1_2 1
+typedef unsigned int EGLenum;
+typedef void *EGLClientBuffer;
+#define EGL_ALPHA_FORMAT 0x3088
+#define EGL_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_ALPHA_FORMAT_PRE 0x308C
+#define EGL_ALPHA_MASK_SIZE 0x303E
+#define EGL_BUFFER_PRESERVED 0x3094
+#define EGL_BUFFER_DESTROYED 0x3095
+#define EGL_CLIENT_APIS 0x308D
+#define EGL_COLORSPACE 0x3087
+#define EGL_COLORSPACE_sRGB 0x3089
+#define EGL_COLORSPACE_LINEAR 0x308A
+#define EGL_COLOR_BUFFER_TYPE 0x303F
+#define EGL_CONTEXT_CLIENT_TYPE 0x3097
+#define EGL_DISPLAY_SCALING 10000
+#define EGL_HORIZONTAL_RESOLUTION 0x3090
+#define EGL_LUMINANCE_BUFFER 0x308F
+#define EGL_LUMINANCE_SIZE 0x303D
+#define EGL_OPENGL_ES_BIT 0x0001
+#define EGL_OPENVG_BIT 0x0002
+#define EGL_OPENGL_ES_API 0x30A0
+#define EGL_OPENVG_API 0x30A1
+#define EGL_OPENVG_IMAGE 0x3096
+#define EGL_PIXEL_ASPECT_RATIO 0x3092
+#define EGL_RENDERABLE_TYPE 0x3040
+#define EGL_RENDER_BUFFER 0x3086
+#define EGL_RGB_BUFFER 0x308E
+#define EGL_SINGLE_BUFFER 0x3085
+#define EGL_SWAP_BEHAVIOR 0x3093
+#define EGL_UNKNOWN ((EGLint)-1)
+#define EGL_VERTICAL_RESOLUTION 0x3091
+EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api);
+EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void);
+#endif /* EGL_VERSION_1_2 */
+
+#ifndef EGL_VERSION_1_3
+#define EGL_VERSION_1_3 1
+#define EGL_CONFORMANT 0x3042
+#define EGL_CONTEXT_CLIENT_VERSION 0x3098
+#define EGL_MATCH_NATIVE_PIXMAP 0x3041
+#define EGL_OPENGL_ES2_BIT 0x0004
+#define EGL_VG_ALPHA_FORMAT 0x3088
+#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
+#define EGL_VG_ALPHA_FORMAT_PRE 0x308C
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
+#define EGL_VG_COLORSPACE 0x3087
+#define EGL_VG_COLORSPACE_sRGB 0x3089
+#define EGL_VG_COLORSPACE_LINEAR 0x308A
+#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
+#endif /* EGL_VERSION_1_3 */
+
+#ifndef EGL_VERSION_1_4
+#define EGL_VERSION_1_4 1
+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
+#define EGL_MULTISAMPLE_RESOLVE 0x3099
+#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
+#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
+#define EGL_OPENGL_API 0x30A2
+#define EGL_OPENGL_BIT 0x0008
+#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
+EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
+#endif /* EGL_VERSION_1_4 */
+
+#ifndef EGL_VERSION_1_5
+#define EGL_VERSION_1_5 1
+typedef void *EGLSync;
+typedef intptr_t EGLAttrib;
+typedef khronos_utime_nanoseconds_t EGLTime;
+typedef void *EGLImage;
+#define EGL_CONTEXT_MAJOR_VERSION 0x3098
+#define EGL_CONTEXT_MINOR_VERSION 0x30FB
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define EGL_NO_RESET_NOTIFICATION 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
+#define EGL_OPENGL_ES3_BIT 0x00000040
+#define EGL_CL_EVENT_HANDLE 0x309C
+#define EGL_SYNC_CL_EVENT 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
+#define EGL_SYNC_TYPE 0x30F7
+#define EGL_SYNC_STATUS 0x30F1
+#define EGL_SYNC_CONDITION 0x30F8
+#define EGL_SIGNALED 0x30F2
+#define EGL_UNSIGNALED 0x30F3
+#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
+#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull
+#define EGL_TIMEOUT_EXPIRED 0x30F5
+#define EGL_CONDITION_SATISFIED 0x30F6
+#define EGL_NO_SYNC ((EGLSync)0)
+#define EGL_SYNC_FENCE 0x30F9
+#define EGL_GL_COLORSPACE 0x309D
+#define EGL_GL_COLORSPACE_SRGB 0x3089
+#define EGL_GL_COLORSPACE_LINEAR 0x308A
+#define EGL_GL_RENDERBUFFER 0x30B9
+#define EGL_GL_TEXTURE_2D 0x30B1
+#define EGL_GL_TEXTURE_LEVEL 0x30BC
+#define EGL_GL_TEXTURE_3D 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET 0x30BD
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED 0x30D2
+#define EGL_NO_IMAGE ((EGLImage)0)
+EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags);
+#endif /* EGL_VERSION_1_5 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __egl_h_ */
+
+
+
+#ifndef __eglext_h_
+#define __eglext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 31566 $ on $Date: 2015-06-23 08:48:48 -0700 (Tue, 23 Jun 2015) $
+*/
+
+/*#include <EGL/eglplatform.h>*/
+
+#define EGL_EGLEXT_VERSION 20150623
+
+/* Generated C header for:
+ * API: egl
+ * Versions considered: .*
+ * Versions emitted: _nomatch_^
+ * Default extensions included: egl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef EGL_KHR_cl_event
+#define EGL_KHR_cl_event 1
+#define EGL_CL_EVENT_HANDLE_KHR 0x309C
+#define EGL_SYNC_CL_EVENT_KHR 0x30FE
+#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF
+#endif /* EGL_KHR_cl_event */
+
+#ifndef EGL_KHR_cl_event2
+#define EGL_KHR_cl_event2 1
+typedef void *EGLSyncKHR;
+typedef intptr_t EGLAttribKHR;
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
+#endif
+#endif /* EGL_KHR_cl_event2 */
+
+#ifndef EGL_KHR_client_get_all_proc_addresses
+#define EGL_KHR_client_get_all_proc_addresses 1
+#endif /* EGL_KHR_client_get_all_proc_addresses */
+
+#ifndef EGL_KHR_config_attribs
+#define EGL_KHR_config_attribs 1
+#define EGL_CONFORMANT_KHR 0x3042
+#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
+#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
+#endif /* EGL_KHR_config_attribs */
+
+#ifndef EGL_KHR_create_context
+#define EGL_KHR_create_context 1
+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#define EGL_CONTEXT_FLAGS_KHR 0x30FC
+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
+#endif /* EGL_KHR_create_context */
+
+#ifndef EGL_KHR_create_context_no_error
+#define EGL_KHR_create_context_no_error 1
+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
+#endif /* EGL_KHR_create_context_no_error */
+
+#ifndef EGL_KHR_fence_sync
+#define EGL_KHR_fence_sync 1
+typedef khronos_utime_nanoseconds_t EGLTimeKHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define EGL_SYNC_CONDITION_KHR 0x30F8
+#define EGL_SYNC_FENCE_KHR 0x30F9
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_fence_sync */
+
+#ifndef EGL_KHR_get_all_proc_addresses
+#define EGL_KHR_get_all_proc_addresses 1
+#endif /* EGL_KHR_get_all_proc_addresses */
+
+#ifndef EGL_KHR_gl_colorspace
+#define EGL_KHR_gl_colorspace 1
+#define EGL_GL_COLORSPACE_KHR 0x309D
+#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
+#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
+#endif /* EGL_KHR_gl_colorspace */
+
+#ifndef EGL_KHR_gl_renderbuffer_image
+#define EGL_KHR_gl_renderbuffer_image 1
+#define EGL_GL_RENDERBUFFER_KHR 0x30B9
+#endif /* EGL_KHR_gl_renderbuffer_image */
+
+#ifndef EGL_KHR_gl_texture_2D_image
+#define EGL_KHR_gl_texture_2D_image 1
+#define EGL_GL_TEXTURE_2D_KHR 0x30B1
+#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
+#endif /* EGL_KHR_gl_texture_2D_image */
+
+#ifndef EGL_KHR_gl_texture_3D_image
+#define EGL_KHR_gl_texture_3D_image 1
+#define EGL_GL_TEXTURE_3D_KHR 0x30B2
+#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
+#endif /* EGL_KHR_gl_texture_3D_image */
+
+#ifndef EGL_KHR_gl_texture_cubemap_image
+#define EGL_KHR_gl_texture_cubemap_image 1
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#endif /* EGL_KHR_gl_texture_cubemap_image */
+
+#ifndef EGL_KHR_image
+#define EGL_KHR_image 1
+typedef void *EGLImageKHR;
+#define EGL_NATIVE_PIXMAP_KHR 0x30B0
+#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image);
+#endif
+#endif /* EGL_KHR_image */
+
+#ifndef EGL_KHR_image_base
+#define EGL_KHR_image_base 1
+#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+#endif /* EGL_KHR_image_base */
+
+#ifndef EGL_KHR_image_pixmap
+#define EGL_KHR_image_pixmap 1
+#endif /* EGL_KHR_image_pixmap */
+
+#ifndef EGL_KHR_lock_surface
+#define EGL_KHR_lock_surface 1
+#define EGL_READ_SURFACE_BIT_KHR 0x0001
+#define EGL_WRITE_SURFACE_BIT_KHR 0x0002
+#define EGL_LOCK_SURFACE_BIT_KHR 0x0080
+#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
+#define EGL_MATCH_FORMAT_KHR 0x3043
+#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
+#define EGL_FORMAT_RGB_565_KHR 0x30C1
+#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
+#define EGL_FORMAT_RGBA_8888_KHR 0x30C3
+#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
+#define EGL_LOCK_USAGE_HINT_KHR 0x30C5
+#define EGL_BITMAP_POINTER_KHR 0x30C6
+#define EGL_BITMAP_PITCH_KHR 0x30C7
+#define EGL_BITMAP_ORIGIN_KHR 0x30C8
+#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
+#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
+#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define EGL_LOWER_LEFT_KHR 0x30CE
+#define EGL_UPPER_LEFT_KHR 0x30CF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface);
+#endif
+#endif /* EGL_KHR_lock_surface */
+
+#ifndef EGL_KHR_lock_surface2
+#define EGL_KHR_lock_surface2 1
+#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
+#endif /* EGL_KHR_lock_surface2 */
+
+#ifndef EGL_KHR_lock_surface3
+#define EGL_KHR_lock_surface3 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value);
+#endif
+#endif /* EGL_KHR_lock_surface3 */
+
+#ifndef EGL_KHR_partial_update
+#define EGL_KHR_partial_update 1
+#define EGL_BUFFER_AGE_KHR 0x313D
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_partial_update */
+
+#ifndef EGL_KHR_platform_android
+#define EGL_KHR_platform_android 1
+#define EGL_PLATFORM_ANDROID_KHR 0x3141
+#endif /* EGL_KHR_platform_android */
+
+#ifndef EGL_KHR_platform_gbm
+#define EGL_KHR_platform_gbm 1
+#define EGL_PLATFORM_GBM_KHR 0x31D7
+#endif /* EGL_KHR_platform_gbm */
+
+#ifndef EGL_KHR_platform_wayland
+#define EGL_KHR_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
+#endif /* EGL_KHR_platform_wayland */
+
+#ifndef EGL_KHR_platform_x11
+#define EGL_KHR_platform_x11 1
+#define EGL_PLATFORM_X11_KHR 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6
+#endif /* EGL_KHR_platform_x11 */
+
+#ifndef EGL_KHR_reusable_sync
+#define EGL_KHR_reusable_sync 1
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_STATUS_KHR 0x30F1
+#define EGL_SIGNALED_KHR 0x30F2
+#define EGL_UNSIGNALED_KHR 0x30F3
+#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5
+#define EGL_CONDITION_SATISFIED_KHR 0x30F6
+#define EGL_SYNC_TYPE_KHR 0x30F7
+#define EGL_SYNC_REUSABLE_KHR 0x30FA
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
+#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull
+#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0)
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_reusable_sync */
+
+#ifndef EGL_KHR_stream
+#define EGL_KHR_stream 1
+typedef void *EGLStreamKHR;
+typedef khronos_uint64_t EGLuint64KHR;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0)
+#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
+#define EGL_PRODUCER_FRAME_KHR 0x3212
+#define EGL_CONSUMER_FRAME_KHR 0x3213
+#define EGL_STREAM_STATE_KHR 0x3214
+#define EGL_STREAM_STATE_CREATED_KHR 0x3215
+#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216
+#define EGL_STREAM_STATE_EMPTY_KHR 0x3217
+#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define EGL_BAD_STREAM_KHR 0x321B
+#define EGL_BAD_STATE_KHR 0x321C
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_KHR_stream */
+
+#ifndef EGL_KHR_stream_consumer_gltexture
+#define EGL_KHR_stream_consumer_gltexture 1
+#ifdef EGL_KHR_stream
+#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_consumer_gltexture */
+
+#ifndef EGL_KHR_stream_cross_process_fd
+#define EGL_KHR_stream_cross_process_fd 1
+typedef int EGLNativeFileDescriptorKHR;
+#ifdef EGL_KHR_stream
+#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1))
+typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream);
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream);
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_cross_process_fd */
+
+#ifndef EGL_KHR_stream_fifo
+#define EGL_KHR_stream_fifo 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
+#define EGL_STREAM_TIME_NOW_KHR 0x31FD
+#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
+#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_fifo */
+
+#ifndef EGL_KHR_stream_producer_aldatalocator
+#define EGL_KHR_stream_producer_aldatalocator 1
+#ifdef EGL_KHR_stream
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_aldatalocator */
+
+#ifndef EGL_KHR_stream_producer_eglsurface
+#define EGL_KHR_stream_producer_eglsurface 1
+#ifdef EGL_KHR_stream
+#define EGL_STREAM_BIT_KHR 0x0800
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list);
+#endif
+#endif /* EGL_KHR_stream */
+#endif /* EGL_KHR_stream_producer_eglsurface */
+
+#ifndef EGL_KHR_surfaceless_context
+#define EGL_KHR_surfaceless_context 1
+#endif /* EGL_KHR_surfaceless_context */
+
+#ifndef EGL_KHR_swap_buffers_with_damage
+#define EGL_KHR_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_KHR_swap_buffers_with_damage */
+
+#ifndef EGL_KHR_vg_parent_image
+#define EGL_KHR_vg_parent_image 1
+#define EGL_VG_PARENT_IMAGE_KHR 0x30BA
+#endif /* EGL_KHR_vg_parent_image */
+
+#ifndef EGL_KHR_wait_sync
+#define EGL_KHR_wait_sync 1
+typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
+#endif
+#endif /* EGL_KHR_wait_sync */
+
+#ifndef EGL_ANDROID_blob_cache
+#define EGL_ANDROID_blob_cache 1
+typedef khronos_ssize_t EGLsizeiANDROID;
+typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize);
+typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize);
+typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+#endif
+#endif /* EGL_ANDROID_blob_cache */
+
+#ifndef EGL_ANDROID_framebuffer_target
+#define EGL_ANDROID_framebuffer_target 1
+#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
+#endif /* EGL_ANDROID_framebuffer_target */
+
+#ifndef EGL_ANDROID_image_native_buffer
+#define EGL_ANDROID_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_ANDROID 0x3140
+#endif /* EGL_ANDROID_image_native_buffer */
+
+#ifndef EGL_ANDROID_native_fence_sync
+#define EGL_ANDROID_native_fence_sync 1
+#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
+#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
+#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
+typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync);
+#endif
+#endif /* EGL_ANDROID_native_fence_sync */
+
+#ifndef EGL_ANDROID_recordable
+#define EGL_ANDROID_recordable 1
+#define EGL_RECORDABLE_ANDROID 0x3142
+#endif /* EGL_ANDROID_recordable */
+
+#ifndef EGL_ANGLE_d3d_share_handle_client_buffer
+#define EGL_ANGLE_d3d_share_handle_client_buffer 1
+#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */
+
+#ifndef EGL_ANGLE_device_d3d
+#define EGL_ANGLE_device_d3d 1
+#define EGL_D3D9_DEVICE_ANGLE 0x33A0
+#define EGL_D3D11_DEVICE_ANGLE 0x33A1
+#endif /* EGL_ANGLE_device_d3d */
+
+#ifndef EGL_ANGLE_query_surface_pointer
+#define EGL_ANGLE_query_surface_pointer 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+#endif
+#endif /* EGL_ANGLE_query_surface_pointer */
+
+#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle
+#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1
+#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */
+
+#ifndef EGL_ANGLE_window_fixed_size
+#define EGL_ANGLE_window_fixed_size 1
+#define EGL_FIXED_SIZE_ANGLE 0x3201
+#endif /* EGL_ANGLE_window_fixed_size */
+
+#ifndef EGL_ARM_pixmap_multisample_discard
+#define EGL_ARM_pixmap_multisample_discard 1
+#define EGL_DISCARD_SAMPLES_ARM 0x3286
+#endif /* EGL_ARM_pixmap_multisample_discard */
+
+#ifndef EGL_EXT_buffer_age
+#define EGL_EXT_buffer_age 1
+#define EGL_BUFFER_AGE_EXT 0x313D
+#endif /* EGL_EXT_buffer_age */
+
+#ifndef EGL_EXT_client_extensions
+#define EGL_EXT_client_extensions 1
+#endif /* EGL_EXT_client_extensions */
+
+#ifndef EGL_EXT_create_context_robustness
+#define EGL_EXT_create_context_robustness 1
+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
+#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
+#endif /* EGL_EXT_create_context_robustness */
+
+#ifndef EGL_EXT_device_base
+#define EGL_EXT_device_base 1
+typedef void *EGLDeviceEXT;
+#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0))
+#define EGL_BAD_DEVICE_EXT 0x322B
+#define EGL_DEVICE_EXT 0x322C
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
+#endif
+#endif /* EGL_EXT_device_base */
+
+#ifndef EGL_EXT_device_drm
+#define EGL_EXT_device_drm 1
+#define EGL_DRM_DEVICE_FILE_EXT 0x3233
+#endif /* EGL_EXT_device_drm */
+
+#ifndef EGL_EXT_device_enumeration
+#define EGL_EXT_device_enumeration 1
+#endif /* EGL_EXT_device_enumeration */
+
+#ifndef EGL_EXT_device_openwf
+#define EGL_EXT_device_openwf 1
+#define EGL_OPENWF_DEVICE_ID_EXT 0x3237
+#endif /* EGL_EXT_device_openwf */
+
+#ifndef EGL_EXT_device_query
+#define EGL_EXT_device_query 1
+#endif /* EGL_EXT_device_query */
+
+#ifndef EGL_EXT_image_dma_buf_import
+#define EGL_EXT_image_dma_buf_import 1
+#define EGL_LINUX_DMA_BUF_EXT 0x3270
+#define EGL_LINUX_DRM_FOURCC_EXT 0x3271
+#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
+#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
+#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
+#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
+#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
+#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
+#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
+#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
+#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
+#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
+#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C
+#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define EGL_ITU_REC601_EXT 0x327F
+#define EGL_ITU_REC709_EXT 0x3280
+#define EGL_ITU_REC2020_EXT 0x3281
+#define EGL_YUV_FULL_RANGE_EXT 0x3282
+#define EGL_YUV_NARROW_RANGE_EXT 0x3283
+#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284
+#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
+#endif /* EGL_EXT_image_dma_buf_import */
+
+#ifndef EGL_EXT_multiview_window
+#define EGL_EXT_multiview_window 1
+#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
+#endif /* EGL_EXT_multiview_window */
+
+#ifndef EGL_EXT_output_base
+#define EGL_EXT_output_base 1
+typedef void *EGLOutputLayerEXT;
+typedef void *EGLOutputPortEXT;
+#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0)
+#define EGL_NO_OUTPUT_PORT_EXT ((EGLOutputPortEXT)0)
+#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D
+#define EGL_BAD_OUTPUT_PORT_EXT 0x322E
+#define EGL_SWAP_INTERVAL_EXT 0x322F
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name);
+EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value);
+EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name);
+#endif
+#endif /* EGL_EXT_output_base */
+
+#ifndef EGL_EXT_output_drm
+#define EGL_EXT_output_drm 1
+#define EGL_DRM_CRTC_EXT 0x3234
+#define EGL_DRM_PLANE_EXT 0x3235
+#define EGL_DRM_CONNECTOR_EXT 0x3236
+#endif /* EGL_EXT_output_drm */
+
+#ifndef EGL_EXT_output_openwf
+#define EGL_EXT_output_openwf 1
+#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238
+#define EGL_OPENWF_PORT_ID_EXT 0x3239
+#endif /* EGL_EXT_output_openwf */
+
+#ifndef EGL_EXT_platform_base
+#define EGL_EXT_platform_base 1
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
+#endif
+#endif /* EGL_EXT_platform_base */
+
+#ifndef EGL_EXT_platform_device
+#define EGL_EXT_platform_device 1
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif /* EGL_EXT_platform_device */
+
+#ifndef EGL_EXT_platform_wayland
+#define EGL_EXT_platform_wayland 1
+#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
+#endif /* EGL_EXT_platform_wayland */
+
+#ifndef EGL_EXT_platform_x11
+#define EGL_EXT_platform_x11 1
+#define EGL_PLATFORM_X11_EXT 0x31D5
+#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
+#endif /* EGL_EXT_platform_x11 */
+
+#ifndef EGL_EXT_protected_surface
+#define EGL_EXT_protected_surface 1
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+#endif /* EGL_EXT_protected_surface */
+
+#ifndef EGL_EXT_stream_consumer_egloutput
+#define EGL_EXT_stream_consumer_egloutput 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer);
+#endif
+#endif /* EGL_EXT_stream_consumer_egloutput */
+
+#ifndef EGL_EXT_swap_buffers_with_damage
+#define EGL_EXT_swap_buffers_with_damage 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
+#endif
+#endif /* EGL_EXT_swap_buffers_with_damage */
+
+#ifndef EGL_EXT_yuv_surface
+#define EGL_EXT_yuv_surface 1
+#define EGL_YUV_ORDER_EXT 0x3301
+#define EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311
+#define EGL_YUV_SUBSAMPLE_EXT 0x3312
+#define EGL_YUV_DEPTH_RANGE_EXT 0x3317
+#define EGL_YUV_CSC_STANDARD_EXT 0x330A
+#define EGL_YUV_PLANE_BPP_EXT 0x331A
+#define EGL_YUV_BUFFER_EXT 0x3300
+#define EGL_YUV_ORDER_YUV_EXT 0x3302
+#define EGL_YUV_ORDER_YVU_EXT 0x3303
+#define EGL_YUV_ORDER_YUYV_EXT 0x3304
+#define EGL_YUV_ORDER_UYVY_EXT 0x3305
+#define EGL_YUV_ORDER_YVYU_EXT 0x3306
+#define EGL_YUV_ORDER_VYUY_EXT 0x3307
+#define EGL_YUV_ORDER_AYUV_EXT 0x3308
+#define EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313
+#define EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314
+#define EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315
+#define EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318
+#define EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319
+#define EGL_YUV_CSC_STANDARD_601_EXT 0x330B
+#define EGL_YUV_CSC_STANDARD_709_EXT 0x330C
+#define EGL_YUV_CSC_STANDARD_2020_EXT 0x330D
+#define EGL_YUV_PLANE_BPP_0_EXT 0x331B
+#define EGL_YUV_PLANE_BPP_8_EXT 0x331C
+#define EGL_YUV_PLANE_BPP_10_EXT 0x331D
+#endif /* EGL_EXT_yuv_surface */
+
+#ifndef EGL_HI_clientpixmap
+#define EGL_HI_clientpixmap 1
+struct EGLClientPixmapHI {
+ void *pData;
+ EGLint iWidth;
+ EGLint iHeight;
+ EGLint iStride;
+};
+#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap);
+#endif
+#endif /* EGL_HI_clientpixmap */
+
+#ifndef EGL_HI_colorformats
+#define EGL_HI_colorformats 1
+#define EGL_COLOR_FORMAT_HI 0x8F70
+#define EGL_COLOR_RGB_HI 0x8F71
+#define EGL_COLOR_RGBA_HI 0x8F72
+#define EGL_COLOR_ARGB_HI 0x8F73
+#endif /* EGL_HI_colorformats */
+
+#ifndef EGL_IMG_context_priority
+#define EGL_IMG_context_priority 1
+#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
+#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
+#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
+#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
+#endif /* EGL_IMG_context_priority */
+
+#ifndef EGL_MESA_drm_image
+#define EGL_MESA_drm_image 1
+#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
+#define EGL_DRM_BUFFER_USE_MESA 0x31D1
+#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define EGL_DRM_BUFFER_MESA 0x31D3
+#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
+#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001
+#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002
+typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride);
+#endif
+#endif /* EGL_MESA_drm_image */
+
+#ifndef EGL_MESA_image_dma_buf_export
+#define EGL_MESA_image_dma_buf_export 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDMABUFIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageQueryMESA (EGLDisplay dpy, EGLImageKHR image, int *fourcc, int *num_planes, EGLuint64KHR *modifiers);
+EGLAPI EGLBoolean EGLAPIENTRY eglExportDMABUFImageMESA (EGLDisplay dpy, EGLImageKHR image, int *fds, EGLint *strides, EGLint *offsets);
+#endif
+#endif /* EGL_MESA_image_dma_buf_export */
+
+#ifndef EGL_MESA_platform_gbm
+#define EGL_MESA_platform_gbm 1
+#define EGL_PLATFORM_GBM_MESA 0x31D7
+#endif /* EGL_MESA_platform_gbm */
+
+#ifndef EGL_NOK_swap_region
+#define EGL_NOK_swap_region 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region */
+
+#ifndef EGL_NOK_swap_region2
+#define EGL_NOK_swap_region2 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects);
+#endif
+#endif /* EGL_NOK_swap_region2 */
+
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+#define EGL_Y_INVERTED_NOK 0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+#ifndef EGL_NV_3dvision_surface
+#define EGL_NV_3dvision_surface 1
+#define EGL_AUTO_STEREO_NV 0x3136
+#endif /* EGL_NV_3dvision_surface */
+
+#ifndef EGL_NV_coverage_sample
+#define EGL_NV_coverage_sample 1
+#define EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define EGL_COVERAGE_SAMPLES_NV 0x30E1
+#endif /* EGL_NV_coverage_sample */
+
+#ifndef EGL_NV_coverage_sample_resolve
+#define EGL_NV_coverage_sample_resolve 1
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
+#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#endif /* EGL_NV_coverage_sample_resolve */
+
+#ifndef EGL_NV_cuda_event
+#define EGL_NV_cuda_event 1
+#define EGL_CUDA_EVENT_HANDLE_NV 0x323B
+#define EGL_SYNC_CUDA_EVENT_NV 0x323C
+#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D
+#endif /* EGL_NV_cuda_event */
+
+#ifndef EGL_NV_depth_nonlinear
+#define EGL_NV_depth_nonlinear 1
+#define EGL_DEPTH_ENCODING_NV 0x30E2
+#define EGL_DEPTH_ENCODING_NONE_NV 0
+#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+#endif /* EGL_NV_depth_nonlinear */
+
+#ifndef EGL_NV_device_cuda
+#define EGL_NV_device_cuda 1
+#define EGL_CUDA_DEVICE_NV 0x323A
+#endif /* EGL_NV_device_cuda */
+
+#ifndef EGL_NV_native_query
+#define EGL_NV_native_query 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap);
+#endif
+#endif /* EGL_NV_native_query */
+
+#ifndef EGL_NV_post_convert_rounding
+#define EGL_NV_post_convert_rounding 1
+#endif /* EGL_NV_post_convert_rounding */
+
+#ifndef EGL_NV_post_sub_buffer
+#define EGL_NV_post_sub_buffer 1
+#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+#endif
+#endif /* EGL_NV_post_sub_buffer */
+
+#ifndef EGL_NV_stream_sync
+#define EGL_NV_stream_sync 1
+#define EGL_SYNC_NEW_FRAME_NV 0x321F
+typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list);
+#endif
+#endif /* EGL_NV_stream_sync */
+
+#ifndef EGL_NV_sync
+#define EGL_NV_sync 1
+typedef void *EGLSyncNV;
+typedef khronos_utime_nanoseconds_t EGLTimeNV;
+#ifdef KHRONOS_SUPPORT_INT64
+#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define EGL_SYNC_STATUS_NV 0x30E7
+#define EGL_SIGNALED_NV 0x30E8
+#define EGL_UNSIGNALED_NV 0x30E9
+#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
+#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull
+#define EGL_ALREADY_SIGNALED_NV 0x30EA
+#define EGL_TIMEOUT_EXPIRED_NV 0x30EB
+#define EGL_CONDITION_SATISFIED_NV 0x30EC
+#define EGL_SYNC_TYPE_NV 0x30ED
+#define EGL_SYNC_CONDITION_NV 0x30EE
+#define EGL_SYNC_FENCE_NV 0x30EF
+#define EGL_NO_SYNC_NV ((EGLSyncNV)0)
+typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync);
+typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync);
+EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync);
+EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout);
+EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode);
+EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_sync */
+
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_utime_nanoseconds_t EGLuint64NV;
+#ifdef KHRONOS_SUPPORT_INT64
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void);
+#endif
+#endif /* KHRONOS_SUPPORT_INT64 */
+#endif /* EGL_NV_system_time */
+
+#ifndef EGL_TIZEN_image_native_buffer
+#define EGL_TIZEN_image_native_buffer 1
+#define EGL_NATIVE_BUFFER_TIZEN 0x32A0
+#endif /* EGL_TIZEN_image_native_buffer */
+
+#ifndef EGL_TIZEN_image_native_surface
+#define EGL_TIZEN_image_native_surface 1
+#define EGL_NATIVE_SURFACE_TIZEN 0x32A1
+#endif /* EGL_TIZEN_image_native_surface */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __eglext_h_ */
+
+
+#endif /* _MSC_VER */
diff --git a/Client/ThirdParty/SDL2/include/SDL_endian.h b/Client/ThirdParty/SDL2/include/SDL_endian.h
new file mode 100644
index 0000000..205b793
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_endian.h
@@ -0,0 +1,316 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_endian.h
+ *
+ * Functions for reading and writing endian-specific values
+ */
+
+#ifndef SDL_endian_h_
+#define SDL_endian_h_
+
+#include "SDL_stdinc.h"
+
+#ifdef _MSC_VER
+/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
+ so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
+
+#ifdef __clang__
+#ifndef __PRFCHWINTRIN_H
+#define __PRFCHWINTRIN_H
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+#endif /* __PRFCHWINTRIN_H */
+#endif /* __clang__ */
+
+#include <intrin.h>
+#endif
+
+/**
+ * \name The two types of endianness
+ */
+/* @{ */
+#define SDL_LIL_ENDIAN 1234
+#define SDL_BIG_ENDIAN 4321
+/* @} */
+
+#ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */
+#ifdef __linux__
+#include <endian.h>
+#define SDL_BYTEORDER __BYTE_ORDER
+#elif defined(__OpenBSD__)
+#include <endian.h>
+#define SDL_BYTEORDER BYTE_ORDER
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+#include <sys/endian.h>
+#define SDL_BYTEORDER BYTE_ORDER
+#else
+#if defined(__hppa__) || \
+ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
+ (defined(__MIPS__) && defined(__MIPSEB__)) || \
+ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
+ defined(__sparc__)
+#define SDL_BYTEORDER SDL_BIG_ENDIAN
+#else
+#define SDL_BYTEORDER SDL_LIL_ENDIAN
+#endif
+#endif /* __linux__ */
+#endif /* !SDL_BYTEORDER */
+
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_endian.h
+ */
+#if (defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) || \
+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
+#define SDL_Swap16(x) __builtin_bswap16(x)
+#elif defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ int result;
+
+ __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
+ return (Uint16)result;
+}
+#elif defined(__GNUC__) && defined(__aarch64__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("rev16 %w1, %w0" : "=r"(x) : "r"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#elif defined(_MSC_VER)
+#pragma intrinsic(_byteswap_ushort)
+#define SDL_Swap16(x) _byteswap_ushort(x)
+#elif defined(__WATCOMC__) && defined(__386__)
+extern _inline Uint16 SDL_Swap16(Uint16);
+#pragma aux SDL_Swap16 = \
+ "xchg al, ah" \
+ parm [ax] \
+ modify [ax];
+#else
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ return SDL_static_cast(Uint16, ((x << 8) | (x >> 8)));
+}
+#endif
+
+#if (defined(__clang__) && (__clang_major__ > 2 || (__clang_major__ == 2 && __clang_minor__ >= 6))) || \
+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+#define SDL_Swap32(x) __builtin_bswap32(x)
+#elif defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswap %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswapl %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ Uint32 result;
+
+ __asm__("rlwimi %0,%2,24,16,23": "=&r"(result): "0" (x>>24), "r"(x));
+ __asm__("rlwimi %0,%2,8,8,15" : "=&r"(result): "0" (result), "r"(x));
+ __asm__("rlwimi %0,%2,24,0,7" : "=&r"(result): "0" (result), "r"(x));
+ return result;
+}
+#elif defined(__GNUC__) && defined(__aarch64__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("rev %w1, %w0": "=r"(x):"r"(x));
+ return x;
+}
+#elif defined(__GNUC__) && (defined(__m68k__) && !defined(__mcoldfire__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern _inline Uint32 SDL_Swap32(Uint32);
+#pragma aux SDL_Swap32 = \
+ "bswap eax" \
+ parm [eax] \
+ modify [eax];
+#elif defined(_MSC_VER)
+#pragma intrinsic(_byteswap_ulong)
+#define SDL_Swap32(x) _byteswap_ulong(x)
+#else
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) |
+ ((x >> 8) & 0x0000FF00) | (x >> 24)));
+}
+#endif
+
+#if (defined(__clang__) && (__clang_major__ > 2 || (__clang_major__ == 2 && __clang_minor__ >= 6))) || \
+ (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+#define SDL_Swap64(x) __builtin_bswap64(x)
+#elif defined(__GNUC__) && defined(__i386__) && \
+ !(__GNUC__ == 2 && __GNUC_MINOR__ <= 95 /* broken gcc version */)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ union {
+ struct {
+ Uint32 a, b;
+ } s;
+ Uint64 u;
+ } v;
+ v.u = x;
+ __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r"(v.s.a), "=r"(v.s.b)
+ : "0" (v.s.a), "1"(v.s.b));
+ return v.u;
+}
+#elif defined(__GNUC__) && defined(__x86_64__)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ __asm__("bswapq %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern _inline Uint64 SDL_Swap64(Uint64);
+#pragma aux SDL_Swap64 = \
+ "bswap eax" \
+ "bswap edx" \
+ "xchg eax,edx" \
+ parm [eax edx] \
+ modify [eax edx];
+#elif defined(_MSC_VER)
+#pragma intrinsic(_byteswap_uint64)
+#define SDL_Swap64(x) _byteswap_uint64(x)
+#else
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ Uint32 hi, lo;
+
+ /* Separate into high and low 32-bit values and swap them */
+ lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x >>= 32;
+ hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x = SDL_Swap32(lo);
+ x <<= 32;
+ x |= SDL_Swap32(hi);
+ return (x);
+}
+#endif
+
+
+SDL_FORCE_INLINE float
+SDL_SwapFloat(float x)
+{
+ union {
+ float f;
+ Uint32 ui32;
+ } swapper;
+ swapper.f = x;
+ swapper.ui32 = SDL_Swap32(swapper.ui32);
+ return swapper.f;
+}
+
+
+/**
+ * \name Swap to native
+ * Byteswap item from the specified endianness to the native endianness.
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define SDL_SwapLE16(X) (X)
+#define SDL_SwapLE32(X) (X)
+#define SDL_SwapLE64(X) (X)
+#define SDL_SwapFloatLE(X) (X)
+#define SDL_SwapBE16(X) SDL_Swap16(X)
+#define SDL_SwapBE32(X) SDL_Swap32(X)
+#define SDL_SwapBE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatBE(X) SDL_SwapFloat(X)
+#else
+#define SDL_SwapLE16(X) SDL_Swap16(X)
+#define SDL_SwapLE32(X) SDL_Swap32(X)
+#define SDL_SwapLE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatLE(X) SDL_SwapFloat(X)
+#define SDL_SwapBE16(X) (X)
+#define SDL_SwapBE32(X) (X)
+#define SDL_SwapBE64(X) (X)
+#define SDL_SwapFloatBE(X) (X)
+#endif
+/* @} *//* Swap to native */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_endian_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_error.h b/Client/ThirdParty/SDL2/include/SDL_error.h
new file mode 100644
index 0000000..f61a200
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_error.h
@@ -0,0 +1,155 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_error.h
+ *
+ * Simple error message routines for SDL.
+ */
+
+#ifndef SDL_error_h_
+#define SDL_error_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public functions */
+
+
+/**
+ * Set the SDL error message for the current thread.
+ *
+ * Calling this function will replace any previous error message that was set.
+ *
+ * This function always returns -1, since SDL frequently uses -1 to signify an
+ * failing result, leading to this idiom:
+ *
+ * ```c
+ * if (error_code) {
+ * return SDL_SetError("This operation has failed: %d", error_code);
+ * }
+ * ```
+ *
+ * \param fmt a printf()-style message format string
+ * \param ... additional parameters matching % tokens in the `fmt` string, if
+ * any
+ * \returns always -1.
+ *
+ * \sa SDL_ClearError
+ * \sa SDL_GetError
+ */
+extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * Retrieve a message about the last error that occurred on the current
+ * thread.
+ *
+ * It is possible for multiple errors to occur before calling SDL_GetError().
+ * Only the last error is returned.
+ *
+ * The message is only applicable when an SDL function has signaled an error.
+ * You must check the return values of SDL function calls to determine when to
+ * appropriately call SDL_GetError(). You should _not_ use the results of
+ * SDL_GetError() to decide if an error has occurred! Sometimes SDL will set
+ * an error string even when reporting success.
+ *
+ * SDL will _not_ clear the error string for successful API calls. You _must_
+ * check return values for failure cases before you can assume the error
+ * string applies.
+ *
+ * Error strings are set per-thread, so an error set in a different thread
+ * will not interfere with the current thread's operation.
+ *
+ * The returned string is internally allocated and must not be freed by the
+ * application.
+ *
+ * \returns a message with information about the specific error that occurred,
+ * or an empty string if there hasn't been an error message set since
+ * the last call to SDL_ClearError(). The message is only applicable
+ * when an SDL function has signaled an error. You must check the
+ * return values of SDL function calls to determine when to
+ * appropriately call SDL_GetError().
+ *
+ * \sa SDL_ClearError
+ * \sa SDL_SetError
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetError(void);
+
+/**
+ * Get the last error message that was set for the current thread.
+ *
+ * This allows the caller to copy the error string into a provided buffer, but
+ * otherwise operates exactly the same as SDL_GetError().
+ *
+ * \param errstr A buffer to fill with the last error message that was set for
+ * the current thread
+ * \param maxlen The size of the buffer pointed to by the errstr parameter
+ * \returns the pointer passed in as the `errstr` parameter.
+ *
+ * \sa SDL_GetError
+ */
+extern DECLSPEC char * SDLCALL SDL_GetErrorMsg(char *errstr, int maxlen);
+
+/**
+ * Clear any previous error message for this thread.
+ *
+ * \sa SDL_GetError
+ * \sa SDL_SetError
+ */
+extern DECLSPEC void SDLCALL SDL_ClearError(void);
+
+/**
+ * \name Internal error functions
+ *
+ * \internal
+ * Private error reporting function - used internally.
+ */
+/* @{ */
+#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM)
+#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED)
+#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param))
+typedef enum
+{
+ SDL_ENOMEM,
+ SDL_EFREAD,
+ SDL_EFWRITE,
+ SDL_EFSEEK,
+ SDL_UNSUPPORTED,
+ SDL_LASTERROR
+} SDL_errorcode;
+/* SDL_Error() unconditionally returns -1. */
+extern DECLSPEC int SDLCALL SDL_Error(SDL_errorcode code);
+/* @} *//* Internal error functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_error_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_events.h b/Client/ThirdParty/SDL2/include/SDL_events.h
new file mode 100644
index 0000000..c3037b2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_events.h
@@ -0,0 +1,1098 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_events.h
+ *
+ * Include file for SDL event handling.
+ */
+
+#ifndef SDL_events_h_
+#define SDL_events_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_keyboard.h"
+#include "SDL_mouse.h"
+#include "SDL_joystick.h"
+#include "SDL_gamecontroller.h"
+#include "SDL_quit.h"
+#include "SDL_gesture.h"
+#include "SDL_touch.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General keyboard/mouse state definitions */
+#define SDL_RELEASED 0
+#define SDL_PRESSED 1
+
+/**
+ * The types of events that can be delivered.
+ */
+typedef enum
+{
+ SDL_FIRSTEVENT = 0, /**< Unused (do not remove) */
+
+ /* Application events */
+ SDL_QUIT = 0x100, /**< User-requested quit */
+
+ /* These application events have special meaning on iOS, see README-ios.md for details */
+ SDL_APP_TERMINATING, /**< The application is being terminated by the OS
+ Called on iOS in applicationWillTerminate()
+ Called on Android in onDestroy()
+ */
+ SDL_APP_LOWMEMORY, /**< The application is low on memory, free memory if possible.
+ Called on iOS in applicationDidReceiveMemoryWarning()
+ Called on Android in onLowMemory()
+ */
+ SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
+ Called on iOS in applicationWillResignActive()
+ Called on Android in onPause()
+ */
+ SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
+ Called on iOS in applicationDidEnterBackground()
+ Called on Android in onPause()
+ */
+ SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
+ Called on iOS in applicationWillEnterForeground()
+ Called on Android in onResume()
+ */
+ SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive
+ Called on iOS in applicationDidBecomeActive()
+ Called on Android in onResume()
+ */
+
+ SDL_LOCALECHANGED, /**< The user's locale preferences have changed. */
+
+ /* Display events */
+ SDL_DISPLAYEVENT = 0x150, /**< Display state change */
+
+ /* Window events */
+ SDL_WINDOWEVENT = 0x200, /**< Window state change */
+ SDL_SYSWMEVENT, /**< System specific event */
+
+ /* Keyboard events */
+ SDL_KEYDOWN = 0x300, /**< Key pressed */
+ SDL_KEYUP, /**< Key released */
+ SDL_TEXTEDITING, /**< Keyboard text editing (composition) */
+ SDL_TEXTINPUT, /**< Keyboard text input */
+ SDL_KEYMAPCHANGED, /**< Keymap changed due to a system event such as an
+ input language or keyboard layout change.
+ */
+
+ /* Mouse events */
+ SDL_MOUSEMOTION = 0x400, /**< Mouse moved */
+ SDL_MOUSEBUTTONDOWN, /**< Mouse button pressed */
+ SDL_MOUSEBUTTONUP, /**< Mouse button released */
+ SDL_MOUSEWHEEL, /**< Mouse wheel motion */
+
+ /* Joystick events */
+ SDL_JOYAXISMOTION = 0x600, /**< Joystick axis motion */
+ SDL_JOYBALLMOTION, /**< Joystick trackball motion */
+ SDL_JOYHATMOTION, /**< Joystick hat position change */
+ SDL_JOYBUTTONDOWN, /**< Joystick button pressed */
+ SDL_JOYBUTTONUP, /**< Joystick button released */
+ SDL_JOYDEVICEADDED, /**< A new joystick has been inserted into the system */
+ SDL_JOYDEVICEREMOVED, /**< An opened joystick has been removed */
+
+ /* Game controller events */
+ SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */
+ SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */
+ SDL_CONTROLLERBUTTONUP, /**< Game controller button released */
+ SDL_CONTROLLERDEVICEADDED, /**< A new Game controller has been inserted into the system */
+ SDL_CONTROLLERDEVICEREMOVED, /**< An opened Game controller has been removed */
+ SDL_CONTROLLERDEVICEREMAPPED, /**< The controller mapping was updated */
+ SDL_CONTROLLERTOUCHPADDOWN, /**< Game controller touchpad was touched */
+ SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */
+ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */
+ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */
+
+ /* Touch events */
+ SDL_FINGERDOWN = 0x700,
+ SDL_FINGERUP,
+ SDL_FINGERMOTION,
+
+ /* Gesture events */
+ SDL_DOLLARGESTURE = 0x800,
+ SDL_DOLLARRECORD,
+ SDL_MULTIGESTURE,
+
+ /* Clipboard events */
+ SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard changed */
+
+ /* Drag and drop events */
+ SDL_DROPFILE = 0x1000, /**< The system requests a file open */
+ SDL_DROPTEXT, /**< text/plain drag-and-drop event */
+ SDL_DROPBEGIN, /**< A new set of drops is beginning (NULL filename) */
+ SDL_DROPCOMPLETE, /**< Current set of drops is now complete (NULL filename) */
+
+ /* Audio hotplug events */
+ SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
+ SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */
+
+ /* Sensor events */
+ SDL_SENSORUPDATE = 0x1200, /**< A sensor was updated */
+
+ /* Render events */
+ SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
+ SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
+
+ /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
+ * and should be allocated with SDL_RegisterEvents()
+ */
+ SDL_USEREVENT = 0x8000,
+
+ /**
+ * This last event is only for bounding internal arrays
+ */
+ SDL_LASTEVENT = 0xFFFF
+} SDL_EventType;
+
+/**
+ * \brief Fields shared by every event
+ */
+typedef struct SDL_CommonEvent
+{
+ Uint32 type;
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_CommonEvent;
+
+/**
+ * \brief Display state change event data (event.display.*)
+ */
+typedef struct SDL_DisplayEvent
+{
+ Uint32 type; /**< ::SDL_DISPLAYEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 display; /**< The associated display index */
+ Uint8 event; /**< ::SDL_DisplayEventID */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1; /**< event dependent data */
+} SDL_DisplayEvent;
+
+/**
+ * \brief Window state change event data (event.window.*)
+ */
+typedef struct SDL_WindowEvent
+{
+ Uint32 type; /**< ::SDL_WINDOWEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The associated window */
+ Uint8 event; /**< ::SDL_WindowEventID */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1; /**< event dependent data */
+ Sint32 data2; /**< event dependent data */
+} SDL_WindowEvent;
+
+/**
+ * \brief Keyboard button event structure (event.key.*)
+ */
+typedef struct SDL_KeyboardEvent
+{
+ Uint32 type; /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 repeat; /**< Non-zero if this is a key repeat */
+ Uint8 padding2;
+ Uint8 padding3;
+ SDL_Keysym keysym; /**< The key that was pressed or released */
+} SDL_KeyboardEvent;
+
+#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32)
+/**
+ * \brief Keyboard text editing event structure (event.edit.*)
+ */
+typedef struct SDL_TextEditingEvent
+{
+ Uint32 type; /**< ::SDL_TEXTEDITING */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */
+ Sint32 start; /**< The start cursor of selected editing text */
+ Sint32 length; /**< The length of selected editing text */
+} SDL_TextEditingEvent;
+
+
+#define SDL_TEXTINPUTEVENT_TEXT_SIZE (32)
+/**
+ * \brief Keyboard text input event structure (event.text.*)
+ */
+typedef struct SDL_TextInputEvent
+{
+ Uint32 type; /**< ::SDL_TEXTINPUT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */
+} SDL_TextInputEvent;
+
+/**
+ * \brief Mouse motion event structure (event.motion.*)
+ */
+typedef struct SDL_MouseMotionEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Uint32 state; /**< The current button state */
+ Sint32 x; /**< X coordinate, relative to window */
+ Sint32 y; /**< Y coordinate, relative to window */
+ Sint32 xrel; /**< The relative motion in the X direction */
+ Sint32 yrel; /**< The relative motion in the Y direction */
+} SDL_MouseMotionEvent;
+
+/**
+ * \brief Mouse button event structure (event.button.*)
+ */
+typedef struct SDL_MouseButtonEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Uint8 button; /**< The mouse button index */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
+ Uint8 padding1;
+ Sint32 x; /**< X coordinate, relative to window */
+ Sint32 y; /**< Y coordinate, relative to window */
+} SDL_MouseButtonEvent;
+
+/**
+ * \brief Mouse wheel event structure (event.wheel.*)
+ */
+typedef struct SDL_MouseWheelEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEWHEEL */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
+ Sint32 y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
+ Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
+} SDL_MouseWheelEvent;
+
+/**
+ * \brief Joystick axis motion event structure (event.jaxis.*)
+ */
+typedef struct SDL_JoyAxisEvent
+{
+ Uint32 type; /**< ::SDL_JOYAXISMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 axis; /**< The joystick axis index */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value; /**< The axis value (range: -32768 to 32767) */
+ Uint16 padding4;
+} SDL_JoyAxisEvent;
+
+/**
+ * \brief Joystick trackball motion event structure (event.jball.*)
+ */
+typedef struct SDL_JoyBallEvent
+{
+ Uint32 type; /**< ::SDL_JOYBALLMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 ball; /**< The joystick trackball index */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 xrel; /**< The relative motion in the X direction */
+ Sint16 yrel; /**< The relative motion in the Y direction */
+} SDL_JoyBallEvent;
+
+/**
+ * \brief Joystick hat position change event structure (event.jhat.*)
+ */
+typedef struct SDL_JoyHatEvent
+{
+ Uint32 type; /**< ::SDL_JOYHATMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 hat; /**< The joystick hat index */
+ Uint8 value; /**< The hat position value.
+ * \sa ::SDL_HAT_LEFTUP ::SDL_HAT_UP ::SDL_HAT_RIGHTUP
+ * \sa ::SDL_HAT_LEFT ::SDL_HAT_CENTERED ::SDL_HAT_RIGHT
+ * \sa ::SDL_HAT_LEFTDOWN ::SDL_HAT_DOWN ::SDL_HAT_RIGHTDOWN
+ *
+ * Note that zero means the POV is centered.
+ */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyHatEvent;
+
+/**
+ * \brief Joystick button event structure (event.jbutton.*)
+ */
+typedef struct SDL_JoyButtonEvent
+{
+ Uint32 type; /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 button; /**< The joystick button index */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyButtonEvent;
+
+/**
+ * \brief Joystick device event structure (event.jdevice.*)
+ */
+typedef struct SDL_JoyDeviceEvent
+{
+ Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
+} SDL_JoyDeviceEvent;
+
+
+/**
+ * \brief Game controller axis motion event structure (event.caxis.*)
+ */
+typedef struct SDL_ControllerAxisEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERAXISMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value; /**< The axis value (range: -32768 to 32767) */
+ Uint16 padding4;
+} SDL_ControllerAxisEvent;
+
+
+/**
+ * \brief Game controller button event structure (event.cbutton.*)
+ */
+typedef struct SDL_ControllerButtonEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 button; /**< The controller button (SDL_GameControllerButton) */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_ControllerButtonEvent;
+
+
+/**
+ * \brief Controller device event structure (event.cdevice.*)
+ */
+typedef struct SDL_ControllerDeviceEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
+} SDL_ControllerDeviceEvent;
+
+/**
+ * \brief Game controller touchpad event structure (event.ctouchpad.*)
+ */
+typedef struct SDL_ControllerTouchpadEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Sint32 touchpad; /**< The index of the touchpad */
+ Sint32 finger; /**< The index of the finger on the touchpad */
+ float x; /**< Normalized in the range 0...1 with 0 being on the left */
+ float y; /**< Normalized in the range 0...1 with 0 being at the top */
+ float pressure; /**< Normalized in the range 0...1 */
+} SDL_ControllerTouchpadEvent;
+
+/**
+ * \brief Game controller sensor event structure (event.csensor.*)
+ */
+typedef struct SDL_ControllerSensorEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */
+ float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
+} SDL_ControllerSensorEvent;
+
+/**
+ * \brief Audio device event structure (event.adevice.*)
+ */
+typedef struct SDL_AudioDeviceEvent
+{
+ Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
+ Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+} SDL_AudioDeviceEvent;
+
+
+/**
+ * \brief Touch finger event structure (event.tfinger.*)
+ */
+typedef struct SDL_TouchFingerEvent
+{
+ Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ SDL_FingerID fingerId;
+ float x; /**< Normalized in the range 0...1 */
+ float y; /**< Normalized in the range 0...1 */
+ float dx; /**< Normalized in the range -1...1 */
+ float dy; /**< Normalized in the range -1...1 */
+ float pressure; /**< Normalized in the range 0...1 */
+ Uint32 windowID; /**< The window underneath the finger, if any */
+} SDL_TouchFingerEvent;
+
+
+/**
+ * \brief Multiple Finger Gesture Event (event.mgesture.*)
+ */
+typedef struct SDL_MultiGestureEvent
+{
+ Uint32 type; /**< ::SDL_MULTIGESTURE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ float dTheta;
+ float dDist;
+ float x;
+ float y;
+ Uint16 numFingers;
+ Uint16 padding;
+} SDL_MultiGestureEvent;
+
+
+/**
+ * \brief Dollar Gesture Event (event.dgesture.*)
+ */
+typedef struct SDL_DollarGestureEvent
+{
+ Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ SDL_GestureID gestureId;
+ Uint32 numFingers;
+ float error;
+ float x; /**< Normalized center of gesture */
+ float y; /**< Normalized center of gesture */
+} SDL_DollarGestureEvent;
+
+
+/**
+ * \brief An event used to request a file open by the system (event.drop.*)
+ * This event is enabled by default, you can disable it with SDL_EventState().
+ * \note If this event is enabled, you must free the filename in the event.
+ */
+typedef struct SDL_DropEvent
+{
+ Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
+ Uint32 windowID; /**< The window that was dropped on, if any */
+} SDL_DropEvent;
+
+
+/**
+ * \brief Sensor event structure (event.sensor.*)
+ */
+typedef struct SDL_SensorEvent
+{
+ Uint32 type; /**< ::SDL_SENSORUPDATE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The instance ID of the sensor */
+ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
+} SDL_SensorEvent;
+
+/**
+ * \brief The "quit requested" event
+ */
+typedef struct SDL_QuitEvent
+{
+ Uint32 type; /**< ::SDL_QUIT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_QuitEvent;
+
+/**
+ * \brief OS Specific event
+ */
+typedef struct SDL_OSEvent
+{
+ Uint32 type; /**< ::SDL_QUIT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_OSEvent;
+
+/**
+ * \brief A user-defined event type (event.user.*)
+ */
+typedef struct SDL_UserEvent
+{
+ Uint32 type; /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The associated window if any */
+ Sint32 code; /**< User defined event code */
+ void *data1; /**< User defined data pointer */
+ void *data2; /**< User defined data pointer */
+} SDL_UserEvent;
+
+
+struct SDL_SysWMmsg;
+typedef struct SDL_SysWMmsg SDL_SysWMmsg;
+
+/**
+ * \brief A video driver dependent system event (event.syswm.*)
+ * This event is disabled by default, you can enable it with SDL_EventState()
+ *
+ * \note If you want to use this event, you should include SDL_syswm.h.
+ */
+typedef struct SDL_SysWMEvent
+{
+ Uint32 type; /**< ::SDL_SYSWMEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */
+} SDL_SysWMEvent;
+
+/**
+ * \brief General event structure
+ */
+typedef union SDL_Event
+{
+ Uint32 type; /**< Event type, shared with all events */
+ SDL_CommonEvent common; /**< Common event data */
+ SDL_DisplayEvent display; /**< Display event data */
+ SDL_WindowEvent window; /**< Window event data */
+ SDL_KeyboardEvent key; /**< Keyboard event data */
+ SDL_TextEditingEvent edit; /**< Text editing event data */
+ SDL_TextInputEvent text; /**< Text input event data */
+ SDL_MouseMotionEvent motion; /**< Mouse motion event data */
+ SDL_MouseButtonEvent button; /**< Mouse button event data */
+ SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */
+ SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */
+ SDL_JoyBallEvent jball; /**< Joystick ball event data */
+ SDL_JoyHatEvent jhat; /**< Joystick hat event data */
+ SDL_JoyButtonEvent jbutton; /**< Joystick button event data */
+ SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */
+ SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */
+ SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
+ SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
+ SDL_ControllerTouchpadEvent ctouchpad; /**< Game Controller touchpad event data */
+ SDL_ControllerSensorEvent csensor; /**< Game Controller sensor event data */
+ SDL_AudioDeviceEvent adevice; /**< Audio device event data */
+ SDL_SensorEvent sensor; /**< Sensor event data */
+ SDL_QuitEvent quit; /**< Quit request event data */
+ SDL_UserEvent user; /**< Custom event data */
+ SDL_SysWMEvent syswm; /**< System dependent window event data */
+ SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
+ SDL_MultiGestureEvent mgesture; /**< Gesture event data */
+ SDL_DollarGestureEvent dgesture; /**< Gesture event data */
+ SDL_DropEvent drop; /**< Drag and drop event data */
+
+ /* This is necessary for ABI compatibility between Visual C++ and GCC.
+ Visual C++ will respect the push pack pragma and use 52 bytes (size of
+ SDL_TextEditingEvent, the largest structure for 32-bit and 64-bit
+ architectures) for this union, and GCC will use the alignment of the
+ largest datatype within the union, which is 8 bytes on 64-bit
+ architectures.
+
+ So... we'll add padding to force the size to be 56 bytes for both.
+
+ On architectures where pointers are 16 bytes, this needs rounding up to
+ the next multiple of 16, 64, and on architectures where pointers are
+ even larger the size of SDL_UserEvent will dominate as being 3 pointers.
+ */
+ Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)];
+} SDL_Event;
+
+/* Make sure we haven't broken binary compatibility */
+SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding));
+
+
+/* Function prototypes */
+
+/**
+ * Pump the event loop, gathering events from the input devices.
+ *
+ * This function updates the event queue and internal input device state.
+ *
+ * **WARNING**: This should only be run in the thread that initialized the
+ * video subsystem, and for extra safety, you should consider only doing those
+ * things on the main thread in any case.
+ *
+ * SDL_PumpEvents() gathers all the pending input information from devices and
+ * places it in the event queue. Without calls to SDL_PumpEvents() no events
+ * would ever be placed on the queue. Often the need for calls to
+ * SDL_PumpEvents() is hidden from the user since SDL_PollEvent() and
+ * SDL_WaitEvent() implicitly call SDL_PumpEvents(). However, if you are not
+ * polling or waiting for events (e.g. you are filtering them), then you must
+ * call SDL_PumpEvents() to force an event queue update.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_WaitEvent
+ */
+extern DECLSPEC void SDLCALL SDL_PumpEvents(void);
+
+/* @{ */
+typedef enum
+{
+ SDL_ADDEVENT,
+ SDL_PEEKEVENT,
+ SDL_GETEVENT
+} SDL_eventaction;
+
+/**
+ * Check the event queue for messages and optionally return them.
+ *
+ * `action` may be any of the following:
+ *
+ * - `SDL_ADDEVENT`: up to `numevents` events will be added to the back of the
+ * event queue.
+ * - `SDL_PEEKEVENT`: `numevents` events at the front of the event queue,
+ * within the specified minimum and maximum type, will be returned to the
+ * caller and will _not_ be removed from the queue.
+ * - `SDL_GETEVENT`: up to `numevents` events at the front of the event queue,
+ * within the specified minimum and maximum type, will be returned to the
+ * caller and will be removed from the queue.
+ *
+ * You may have to call SDL_PumpEvents() before calling this function.
+ * Otherwise, the events may not be ready to be filtered when you call
+ * SDL_PeepEvents().
+ *
+ * This function is thread-safe.
+ *
+ * \param events destination buffer for the retrieved events
+ * \param numevents if action is SDL_ADDEVENT, the number of events to add
+ * back to the event queue; if action is SDL_PEEKEVENT or
+ * SDL_GETEVENT, the maximum number of events to retrieve
+ * \param action action to take; see [[#action|Remarks]] for details
+ * \param minType minimum value of the event type to be considered;
+ * SDL_FIRSTEVENT is a safe choice
+ * \param maxType maximum value of the event type to be considered;
+ * SDL_LASTEVENT is a safe choice
+ * \returns the number of events actually stored or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event * events, int numevents,
+ SDL_eventaction action,
+ Uint32 minType, Uint32 maxType);
+/* @} */
+
+/**
+ * Check for the existence of a certain event type in the event queue.
+ *
+ * If you need to check for a range of event types, use SDL_HasEvents()
+ * instead.
+ *
+ * \param type the type of event to be queried; see SDL_EventType for details
+ * \returns SDL_TRUE if events matching `type` are present, or SDL_FALSE if
+ * events matching `type` are not present.
+ *
+ * \sa SDL_HasEvents
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasEvent(Uint32 type);
+
+
+/**
+ * Check for the existence of certain event types in the event queue.
+ *
+ * If you need to check for a single event type, use SDL_HasEvent() instead.
+ *
+ * \param minType the low end of event type to be queried, inclusive; see
+ * SDL_EventType for details
+ * \param maxType the high end of event type to be queried, inclusive; see
+ * SDL_EventType for details
+ * \returns SDL_TRUE if events with type >= `minType` and <= `maxType` are
+ * present, or SDL_FALSE if not.
+ *
+ * \sa SDL_HasEvents
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasEvents(Uint32 minType, Uint32 maxType);
+
+/**
+ * Clear events of a specific type from the event queue.
+ *
+ * This will unconditionally remove any events from the queue that match
+ * `type`. If you need to remove a range of event types, use SDL_FlushEvents()
+ * instead.
+ *
+ * It's also normal to just ignore events you don't care about in your event
+ * loop without calling this function.
+ *
+ * This function only affects currently queued events. If you want to make
+ * sure that all pending OS events are flushed, you can call SDL_PumpEvents()
+ * on the main thread immediately before the flush call.
+ *
+ * \param type the type of event to be cleared; see SDL_EventType for details
+ *
+ * \sa SDL_FlushEvents
+ */
+extern DECLSPEC void SDLCALL SDL_FlushEvent(Uint32 type);
+
+/**
+ * Clear events of a range of types from the event queue.
+ *
+ * This will unconditionally remove any events from the queue that are in the
+ * range of `minType` to `maxType`, inclusive. If you need to remove a single
+ * event type, use SDL_FlushEvent() instead.
+ *
+ * It's also normal to just ignore events you don't care about in your event
+ * loop without calling this function.
+ *
+ * This function only affects currently queued events. If you want to make
+ * sure that all pending OS events are flushed, you can call SDL_PumpEvents()
+ * on the main thread immediately before the flush call.
+ *
+ * \param minType the low end of event type to be cleared, inclusive; see
+ * SDL_EventType for details
+ * \param maxType the high end of event type to be cleared, inclusive; see
+ * SDL_EventType for details
+ *
+ * \sa SDL_FlushEvent
+ */
+extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType);
+
+/**
+ * Poll for currently pending events.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`. The 1 returned refers to
+ * this event, immediately stored in the SDL Event structure -- not an event
+ * to follow.
+ *
+ * If `event` is NULL, it simply returns 1 if there is an event in the queue,
+ * but will not remove it from the queue.
+ *
+ * As this function implicitly calls SDL_PumpEvents(), you can only call this
+ * function in the thread that set the video mode.
+ *
+ * SDL_PollEvent() is the favored way of receiving system events since it can
+ * be done from the main loop and does not suspend the main loop while waiting
+ * on an event to be posted.
+ *
+ * The common practice is to fully process the event queue once every frame,
+ * usually as a first step before updating the game's state:
+ *
+ * ```c
+ * while (game_is_still_running) {
+ * SDL_Event event;
+ * while (SDL_PollEvent(&event)) { // poll until all events are handled!
+ * // decide what to do with this event.
+ * }
+ *
+ * // update game state, draw the current frame
+ * }
+ * ```
+ *
+ * \param event the SDL_Event structure to be filled with the next event from
+ * the queue, or NULL
+ * \returns 1 if there is a pending event or 0 if there are none available.
+ *
+ * \sa SDL_GetEventFilter
+ * \sa SDL_PeepEvents
+ * \sa SDL_PushEvent
+ * \sa SDL_SetEventFilter
+ * \sa SDL_WaitEvent
+ * \sa SDL_WaitEventTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event);
+
+/**
+ * Wait indefinitely for the next available event.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`.
+ *
+ * As this function implicitly calls SDL_PumpEvents(), you can only call this
+ * function in the thread that initialized the video subsystem.
+ *
+ * \param event the SDL_Event structure to be filled in with the next event
+ * from the queue, or NULL
+ * \returns 1 on success or 0 if there was an error while waiting for events;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_WaitEventTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event);
+
+/**
+ * Wait until the specified timeout (in milliseconds) for the next available
+ * event.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`.
+ *
+ * As this function implicitly calls SDL_PumpEvents(), you can only call this
+ * function in the thread that initialized the video subsystem.
+ *
+ * \param event the SDL_Event structure to be filled in with the next event
+ * from the queue, or NULL
+ * \param timeout the maximum number of milliseconds to wait for the next
+ * available event
+ * \returns 1 on success or 0 if there was an error while waiting for events;
+ * call SDL_GetError() for more information. This also returns 0 if
+ * the timeout elapsed without an event arriving.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_WaitEvent
+ */
+extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event * event,
+ int timeout);
+
+/**
+ * Add an event to the event queue.
+ *
+ * The event queue can actually be used as a two way communication channel.
+ * Not only can events be read from the queue, but the user can also push
+ * their own events onto it. `event` is a pointer to the event structure you
+ * wish to push onto the queue. The event is copied into the queue, and the
+ * caller may dispose of the memory pointed to after SDL_PushEvent() returns.
+ *
+ * Note: Pushing device input events onto the queue doesn't modify the state
+ * of the device within SDL.
+ *
+ * This function is thread-safe, and can be called from other threads safely.
+ *
+ * Note: Events pushed onto the queue with SDL_PushEvent() get passed through
+ * the event filter but events added with SDL_PeepEvents() do not.
+ *
+ * For pushing application-specific events, please use SDL_RegisterEvents() to
+ * get an event type that does not conflict with other code that also wants
+ * its own custom event types.
+ *
+ * \param event the SDL_Event to be added to the queue
+ * \returns 1 on success, 0 if the event was filtered, or a negative error
+ * code on failure; call SDL_GetError() for more information. A
+ * common reason for error is the event queue being full.
+ *
+ * \sa SDL_PeepEvents
+ * \sa SDL_PollEvent
+ * \sa SDL_RegisterEvents
+ */
+extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event);
+
+/**
+ * A function pointer used for callbacks that watch the event queue.
+ *
+ * \param userdata what was passed as `userdata` to SDL_SetEventFilter()
+ * or SDL_AddEventWatch, etc
+ * \param event the event that triggered the callback
+ * \returns 1 to permit event to be added to the queue, and 0 to disallow
+ * it. When used with SDL_AddEventWatch, the return value is ignored.
+ *
+ * \sa SDL_SetEventFilter
+ * \sa SDL_AddEventWatch
+ */
+typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event);
+
+/**
+ * Set up a filter to process all events before they change internal state and
+ * are posted to the internal event queue.
+ *
+ * If the filter function returns 1 when called, then the event will be added
+ * to the internal queue. If it returns 0, then the event will be dropped from
+ * the queue, but the internal state will still be updated. This allows
+ * selective filtering of dynamically arriving events.
+ *
+ * **WARNING**: Be very careful of what you do in the event filter function,
+ * as it may run in a different thread!
+ *
+ * On platforms that support it, if the quit event is generated by an
+ * interrupt signal (e.g. pressing Ctrl-C), it will be delivered to the
+ * application at the next event poll.
+ *
+ * There is one caveat when dealing with the ::SDL_QuitEvent event type. The
+ * event filter is only called when the window manager desires to close the
+ * application window. If the event filter returns 1, then the window will be
+ * closed, otherwise the window will remain open if possible.
+ *
+ * Note: Disabled events never make it to the event filter function; see
+ * SDL_EventState().
+ *
+ * Note: If you just want to inspect events without filtering, you should use
+ * SDL_AddEventWatch() instead.
+ *
+ * Note: Events pushed onto the queue with SDL_PushEvent() get passed through
+ * the event filter, but events pushed onto the queue with SDL_PeepEvents() do
+ * not.
+ *
+ * \param filter An SDL_EventFilter function to call when an event happens
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \sa SDL_AddEventWatch
+ * \sa SDL_EventState
+ * \sa SDL_GetEventFilter
+ * \sa SDL_PeepEvents
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Query the current event filter.
+ *
+ * This function can be used to "chain" filters, by saving the existing filter
+ * before replacing it with a function that will call that saved filter.
+ *
+ * \param filter the current callback function will be stored here
+ * \param userdata the pointer that is passed to the current event filter will
+ * be stored here
+ * \returns SDL_TRUE on success or SDL_FALSE if there is no event filter set.
+ *
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter * filter,
+ void **userdata);
+
+/**
+ * Add a callback to be triggered when an event is added to the event queue.
+ *
+ * `filter` will be called when an event happens, and its return value is
+ * ignored.
+ *
+ * **WARNING**: Be very careful of what you do in the event filter function,
+ * as it may run in a different thread!
+ *
+ * If the quit event is generated by a signal (e.g. SIGINT), it will bypass
+ * the internal queue and be delivered to the watch callback immediately, and
+ * arrive at the next event poll.
+ *
+ * Note: the callback is called for events posted by the user through
+ * SDL_PushEvent(), but not for disabled events, nor for events by a filter
+ * callback set with SDL_SetEventFilter(), nor for events posted by the user
+ * through SDL_PeepEvents().
+ *
+ * \param filter an SDL_EventFilter function to call when an event happens.
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \sa SDL_DelEventWatch
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC void SDLCALL SDL_AddEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Remove an event watch callback added with SDL_AddEventWatch().
+ *
+ * This function takes the same input as SDL_AddEventWatch() to identify and
+ * delete the corresponding callback.
+ *
+ * \param filter the function originally passed to SDL_AddEventWatch()
+ * \param userdata the pointer originally passed to SDL_AddEventWatch()
+ *
+ * \sa SDL_AddEventWatch
+ */
+extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Run a specific filter function on the current event queue, removing any
+ * events for which the filter returns 0.
+ *
+ * See SDL_SetEventFilter() for more information. Unlike SDL_SetEventFilter(),
+ * this function does not change the filter permanently, it only uses the
+ * supplied filter until this function returns.
+ *
+ * \param filter the SDL_EventFilter function to call when an event happens
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \sa SDL_GetEventFilter
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter,
+ void *userdata);
+
+/* @{ */
+#define SDL_QUERY -1
+#define SDL_IGNORE 0
+#define SDL_DISABLE 0
+#define SDL_ENABLE 1
+
+/**
+ * Set the state of processing events by type.
+ *
+ * `state` may be any of the following:
+ *
+ * - `SDL_QUERY`: returns the current processing state of the specified event
+ * - `SDL_IGNORE` (aka `SDL_DISABLE`): the event will automatically be dropped
+ * from the event queue and will not be filtered
+ * - `SDL_ENABLE`: the event will be processed normally
+ *
+ * \param type the type of event; see SDL_EventType for details
+ * \param state how to process the event
+ * \returns `SDL_DISABLE` or `SDL_ENABLE`, representing the processing state
+ * of the event before this function makes any changes to it.
+ *
+ * \sa SDL_GetEventState
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint32 type, int state);
+/* @} */
+#define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY)
+
+/**
+ * Allocate a set of user-defined events, and return the beginning event
+ * number for that set of events.
+ *
+ * Calling this function with `numevents` <= 0 is an error and will return
+ * (Uint32)-1.
+ *
+ * Note, (Uint32)-1 means the maximum unsigned 32-bit integer value (or
+ * 0xFFFFFFFF), but is clearer to write.
+ *
+ * \param numevents the number of events to be allocated
+ * \returns the beginning event number, or (Uint32)-1 if there are not enough
+ * user-defined events left.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_events_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_filesystem.h b/Client/ThirdParty/SDL2/include/SDL_filesystem.h
new file mode 100644
index 0000000..9dbd28f
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_filesystem.h
@@ -0,0 +1,145 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_filesystem.h
+ *
+ * \brief Include file for filesystem SDL API functions
+ */
+
+#ifndef SDL_filesystem_h_
+#define SDL_filesystem_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the directory where the application was run from.
+ *
+ * This is not necessarily a fast call, so you should call this once near
+ * startup and save the string if you need it.
+ *
+ * **Mac OS X and iOS Specific Functionality**: If the application is in a
+ * ".app" bundle, this function returns the Resource directory (e.g.
+ * MyApp.app/Contents/Resources/). This behaviour can be overridden by adding
+ * a property to the Info.plist file. Adding a string key with the name
+ * SDL_FILESYSTEM_BASE_DIR_TYPE with a supported value will change the
+ * behaviour.
+ *
+ * Supported values for the SDL_FILESYSTEM_BASE_DIR_TYPE property (Given an
+ * application in /Applications/SDLApp/MyApp.app):
+ *
+ * - `resource`: bundle resource directory (the default). For example:
+ * `/Applications/SDLApp/MyApp.app/Contents/Resources`
+ * - `bundle`: the Bundle directory. Fpr example:
+ * `/Applications/SDLApp/MyApp.app/`
+ * - `parent`: the containing directory of the bundle. For example:
+ * `/Applications/SDLApp/`
+ *
+ * The returned path is guaranteed to end with a path separator ('\' on
+ * Windows, '/' on most other platforms).
+ *
+ * The pointer returned is owned by the caller. Please call SDL_free() on the
+ * pointer when done with it.
+ *
+ * \returns an absolute path in UTF-8 encoding to the application data
+ * directory. NULL will be returned on error or when the platform
+ * doesn't implement this functionality, call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_GetPrefPath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetBasePath(void);
+
+/**
+ * Get the user-and-app-specific path where files can be written.
+ *
+ * Get the "pref dir". This is meant to be where users can write personal
+ * files (preferences and save games, etc) that are specific to your
+ * application. This directory is unique per user, per application.
+ *
+ * This function will decide the appropriate location in the native
+ * filesystem, create the directory if necessary, and return a string of the
+ * absolute path to the directory in UTF-8 encoding.
+ *
+ * On Windows, the string might look like:
+ *
+ * `C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\`
+ *
+ * On Linux, the string might look like"
+ *
+ * `/home/bob/.local/share/My Program Name/`
+ *
+ * On Mac OS X, the string might look like:
+ *
+ * `/Users/bob/Library/Application Support/My Program Name/`
+ *
+ * You should assume the path returned by this function is the only safe place
+ * to write files (and that SDL_GetBasePath(), while it might be writable, or
+ * even the parent of the returned path, isn't where you should be writing
+ * things).
+ *
+ * Both the org and app strings may become part of a directory name, so please
+ * follow these rules:
+ *
+ * - Try to use the same org string (_including case-sensitivity_) for all
+ * your applications that use this function.
+ * - Always use a unique app string for each one, and make sure it never
+ * changes for an app once you've decided on it.
+ * - Unicode characters are legal, as long as it's UTF-8 encoded, but...
+ * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
+ * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
+ *
+ * The returned path is guaranteed to end with a path separator ('\' on
+ * Windows, '/' on most other platforms).
+ *
+ * The pointer returned is owned by the caller. Please call SDL_free() on the
+ * pointer when done with it.
+ *
+ * \param org the name of your organization
+ * \param app the name of your application
+ * \returns a UTF-8 string of the user directory in platform-dependent
+ * notation. NULL if there's a problem (creating directory failed,
+ * etc.).
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_GetBasePath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_filesystem_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_gamecontroller.h b/Client/ThirdParty/SDL2/include/SDL_gamecontroller.h
new file mode 100644
index 0000000..cf1bd48
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_gamecontroller.h
@@ -0,0 +1,870 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gamecontroller.h
+ *
+ * Include file for SDL game controller event handling
+ */
+
+#ifndef SDL_gamecontroller_h_
+#define SDL_gamecontroller_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_rwops.h"
+#include "SDL_sensor.h"
+#include "SDL_joystick.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_gamecontroller.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_GAMECONTROLLER flag. This causes SDL to scan the system
+ * for game controllers, and load appropriate drivers.
+ *
+ * If you would like to receive controller updates while the application
+ * is in the background, you should set the following hint before calling
+ * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+ */
+
+/**
+ * The gamecontroller structure used to identify an SDL game controller
+ */
+struct _SDL_GameController;
+typedef struct _SDL_GameController SDL_GameController;
+
+typedef enum
+{
+ SDL_CONTROLLER_TYPE_UNKNOWN = 0,
+ SDL_CONTROLLER_TYPE_XBOX360,
+ SDL_CONTROLLER_TYPE_XBOXONE,
+ SDL_CONTROLLER_TYPE_PS3,
+ SDL_CONTROLLER_TYPE_PS4,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO,
+ SDL_CONTROLLER_TYPE_VIRTUAL,
+ SDL_CONTROLLER_TYPE_PS5,
+ SDL_CONTROLLER_TYPE_AMAZON_LUNA,
+ SDL_CONTROLLER_TYPE_GOOGLE_STADIA
+} SDL_GameControllerType;
+
+typedef enum
+{
+ SDL_CONTROLLER_BINDTYPE_NONE = 0,
+ SDL_CONTROLLER_BINDTYPE_BUTTON,
+ SDL_CONTROLLER_BINDTYPE_AXIS,
+ SDL_CONTROLLER_BINDTYPE_HAT
+} SDL_GameControllerBindType;
+
+/**
+ * Get the SDL joystick layer binding for this controller button/axis mapping
+ */
+typedef struct SDL_GameControllerButtonBind
+{
+ SDL_GameControllerBindType bindType;
+ union
+ {
+ int button;
+ int axis;
+ struct {
+ int hat;
+ int hat_mask;
+ } hat;
+ } value;
+
+} SDL_GameControllerButtonBind;
+
+
+/**
+ * To count the number of game controllers in the system for the following:
+ *
+ * ```c
+ * int nJoysticks = SDL_NumJoysticks();
+ * int nGameControllers = 0;
+ * for (int i = 0; i < nJoysticks; i++) {
+ * if (SDL_IsGameController(i)) {
+ * nGameControllers++;
+ * }
+ * }
+ * ```
+ *
+ * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping() you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
+ * guid,name,mappings
+ *
+ * Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
+ * Under Windows there is a reserved GUID of "xinput" that covers any XInput devices.
+ * The mapping format for joystick is:
+ * bX - a joystick button, index X
+ * hX.Y - hat X with value Y
+ * aX - axis X of the joystick
+ * Buttons can be used as a controller axis and vice versa.
+ *
+ * This string shows an example of a valid mapping for a controller
+ *
+ * ```c
+ * "03000000341a00003608000000000000,PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7",
+ * ```
+ */
+
+/**
+ * Load a set of Game Controller mappings from a seekable SDL data stream.
+ *
+ * You can call this function several times, if needed, to load different
+ * database files.
+ *
+ * If a new mapping is loaded for an already known controller GUID, the later
+ * version will overwrite the one currently loaded.
+ *
+ * Mappings not belonging to the current platform or with no platform field
+ * specified will be ignored (i.e. mappings for Linux will be ignored in
+ * Windows, etc).
+ *
+ * This function will load the text database entirely in memory before
+ * processing it, so take this into consideration if you are in a memory
+ * constrained environment.
+ *
+ * \param rw the data stream for the mappings to be added
+ * \param freerw non-zero to close the stream after being read
+ * \returns the number of mappings added or -1 on error; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GameControllerAddMapping
+ * \sa SDL_GameControllerAddMappingsFromFile
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMappingsFromRW(SDL_RWops * rw, int freerw);
+
+/**
+ * Load a set of mappings from a file, filtered by the current SDL_GetPlatform()
+ *
+ * Convenience macro.
+ */
+#define SDL_GameControllerAddMappingsFromFile(file) SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(file, "rb"), 1)
+
+/**
+ * Add support for controllers that SDL is unaware of or to cause an existing
+ * controller to have a different binding.
+ *
+ * The mapping string has the format "GUID,name,mapping", where GUID is the
+ * string value from SDL_JoystickGetGUIDString(), name is the human readable
+ * string for the device and mappings are controller mappings to joystick
+ * ones. Under Windows there is a reserved GUID of "xinput" that covers all
+ * XInput devices. The mapping format for joystick is: {| |bX |a joystick
+ * button, index X |- |hX.Y |hat X with value Y |- |aX |axis X of the joystick
+ * |} Buttons can be used as a controller axes and vice versa.
+ *
+ * This string shows an example of a valid mapping for a controller:
+ *
+ * ```c
+ * "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7"
+ * ```
+ *
+ * \param mappingString the mapping string
+ * \returns 1 if a new mapping is added, 0 if an existing mapping is updated,
+ * -1 on error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_GameControllerMapping
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping(const char* mappingString);
+
+/**
+ * Get the number of mappings installed.
+ *
+ * \returns the number of mappings.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerNumMappings(void);
+
+/**
+ * Get the mapping at a particular index.
+ *
+ * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
+ * the index is out of range.
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForIndex(int mapping_index);
+
+/**
+ * Get the game controller mapping string for a given GUID.
+ *
+ * The returned string must be freed with SDL_free().
+ *
+ * \param guid a structure containing the GUID for which a mapping is desired
+ * \returns a mapping string or NULL on error; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUID
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid);
+
+/**
+ * Get the current mapping of a Game Controller.
+ *
+ * The returned string must be freed with SDL_free().
+ *
+ * Details about mappings are discussed with SDL_GameControllerAddMapping().
+ *
+ * \param gamecontroller the game controller you want to get the current
+ * mapping for
+ * \returns a string that has the controller's mapping or NULL if no mapping
+ * is available; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerAddMapping
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMapping(SDL_GameController *gamecontroller);
+
+/**
+ * Check if the given joystick is supported by the game controller interface.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, up to
+ * SDL_NumJoysticks()
+ * \returns SDL_TRUE if the given joystick is supported by the game controller
+ * interface, SDL_FALSE if it isn't or it's an invalid index.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsGameController(int joystick_index);
+
+/**
+ * Get the implementation dependent name for the game controller.
+ *
+ * This function can be called before any controllers are opened.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the implementation-dependent name for the game controller, or NULL
+ * if there is no name or the index is invalid.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerName
+ * \sa SDL_GameControllerOpen
+ * \sa SDL_IsGameController
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index);
+
+/**
+ * Get the type of a game controller.
+ *
+ * This can be called before any controllers are opened.
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the controller type.
+ */
+extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerTypeForIndex(int joystick_index);
+
+/**
+ * Get the mapping of a game controller.
+ *
+ * This can be called before any controllers are opened.
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
+ * no mapping is available.
+ */
+extern DECLSPEC char *SDLCALL SDL_GameControllerMappingForDeviceIndex(int joystick_index);
+
+/**
+ * Open a game controller for use.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * The index passed as an argument refers to the N'th game controller on the
+ * system. This index is not the value which will identify this controller in
+ * future controller events. The joystick's instance id (SDL_JoystickID) will
+ * be used there instead.
+ *
+ * \param joystick_index the device_index of a device, up to
+ * SDL_NumJoysticks()
+ * \returns a gamecontroller identifier or NULL if an error occurred; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerClose
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_IsGameController
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_index);
+
+/**
+ * Get the SDL_GameController associated with an instance id.
+ *
+ * \param joyid the instance id to get the SDL_GameController for
+ * \returns an SDL_GameController on success or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid);
+
+/**
+ * Get the SDL_GameController associated with a player index.
+ *
+ * Please note that the player index is _not_ the device index, nor is it the
+ * instance id!
+ *
+ * \param player_index the player index, which is not the device index or the
+ * instance id!
+ * \returns the SDL_GameController associated with a player index.
+ *
+ * \sa SDL_GameControllerGetPlayerIndex
+ * \sa SDL_GameControllerSetPlayerIndex
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index);
+
+/**
+ * Get the implementation-dependent name for an opened game controller.
+ *
+ * This is the same name as returned by SDL_GameControllerNameForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns the implementation dependent name for the game controller, or NULL
+ * if there is no name or the identifier passed is invalid.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller);
+
+/**
+ * Get the type of this currently opened controller
+ *
+ * This is the same name as returned by SDL_GameControllerTypeForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the controller type.
+ */
+extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_GameController *gamecontroller);
+
+/**
+ * Get the player index of an opened game controller.
+ *
+ * For XInput controllers this returns the XInput user index.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the player index for controller, or -1 if it's not available.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller);
+
+/**
+ * Set the player index of an opened game controller.
+ *
+ * \param gamecontroller the game controller object to adjust.
+ * \param player_index Player index to assign to this controller.
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index);
+
+/**
+ * Get the USB vendor ID of an opened controller, if available.
+ *
+ * If the vendor ID isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB vendor ID, or zero if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetVendor(SDL_GameController *gamecontroller);
+
+/**
+ * Get the USB product ID of an opened controller, if available.
+ *
+ * If the product ID isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB product ID, or zero if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProduct(SDL_GameController *gamecontroller);
+
+/**
+ * Get the product version of an opened controller, if available.
+ *
+ * If the product version isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB product version, or zero if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller);
+
+/**
+ * Get the serial number of an opened controller, if available.
+ *
+ * Returns the serial number of the controller, or NULL if it is not
+ * available.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the serial number, or NULL if unavailable.
+ */
+extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
+
+/**
+ * Check if a controller has been opened and is currently connected.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns SDL_TRUE if the controller has been opened and is currently
+ * connected, or SDL_FALSE if not.
+ *
+ * \sa SDL_GameControllerClose
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerGetAttached(SDL_GameController *gamecontroller);
+
+/**
+ * Get the Joystick ID from a Game Controller.
+ *
+ * This function will give you a SDL_Joystick object, which allows you to use
+ * the SDL_Joystick functions with a SDL_GameController object. This would be
+ * useful for getting a joystick's position at any given time, even if it
+ * hasn't moved (moving it would produce an event, which would have the axis'
+ * value).
+ *
+ * The pointer returned is owned by the SDL_GameController. You should not
+ * call SDL_JoystickClose() on it, for example, since doing so will likely
+ * cause SDL to crash.
+ *
+ * \param gamecontroller the game controller object that you want to get a
+ * joystick from
+ * \returns a SDL_Joystick object; call SDL_GetError() for more information.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller);
+
+/**
+ * Query or change current state of Game Controller events.
+ *
+ * If controller events are disabled, you must call SDL_GameControllerUpdate()
+ * yourself and check the state of the controller when you want controller
+ * information.
+ *
+ * Any number can be passed to SDL_GameControllerEventState(), but only -1, 0,
+ * and 1 will have any effect. Other numbers will just be returned.
+ *
+ * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE`
+ * \returns the same value passed to the function, with exception to -1
+ * (SDL_QUERY), which will return the current state.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickEventState
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerEventState(int state);
+
+/**
+ * Manually pump game controller updates if not using the loop.
+ *
+ * This function is called automatically by the event loop if events are
+ * enabled. Under such circumstances, it will not be necessary to call this
+ * function.
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void);
+
+
+/**
+ * The list of axes available from a controller
+ *
+ * Thumbstick axis values range from SDL_JOYSTICK_AXIS_MIN to SDL_JOYSTICK_AXIS_MAX,
+ * and are centered within ~8000 of zero, though advanced UI will allow users to set
+ * or autodetect the dead zone, which varies between controllers.
+ *
+ * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX.
+ */
+typedef enum
+{
+ SDL_CONTROLLER_AXIS_INVALID = -1,
+ SDL_CONTROLLER_AXIS_LEFTX,
+ SDL_CONTROLLER_AXIS_LEFTY,
+ SDL_CONTROLLER_AXIS_RIGHTX,
+ SDL_CONTROLLER_AXIS_RIGHTY,
+ SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+ SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+ SDL_CONTROLLER_AXIS_MAX
+} SDL_GameControllerAxis;
+
+/**
+ * Convert a string into SDL_GameControllerAxis enum.
+ *
+ * This function is called internally to translate SDL_GameController mapping
+ * strings for the underlying joystick device into the consistent
+ * SDL_GameController mapping. You do not normally need to call this function
+ * unless you are parsing SDL_GameController mappings in your own code.
+ *
+ * Note specially that "righttrigger" and "lefttrigger" map to
+ * `SDL_CONTROLLER_AXIS_TRIGGERRIGHT` and `SDL_CONTROLLER_AXIS_TRIGGERLEFT`,
+ * respectively.
+ *
+ * \param str string representing a SDL_GameController axis
+ * \returns the SDL_GameControllerAxis enum corresponding to the input string,
+ * or `SDL_CONTROLLER_AXIS_INVALID` if no match was found.
+ *
+ * \sa SDL_GameControllerGetStringForAxis
+ */
+extern DECLSPEC SDL_GameControllerAxis SDLCALL SDL_GameControllerGetAxisFromString(const char *str);
+
+/**
+ * Convert from an SDL_GameControllerAxis enum to a string.
+ *
+ * The caller should not SDL_free() the returned string.
+ *
+ * \param axis an enum value for a given SDL_GameControllerAxis
+ * \returns a string for the given axis, or NULL if an invalid axis is
+ * specified. The string returned is of the format used by
+ * SDL_GameController mapping strings.
+ *
+ * \sa SDL_GameControllerGetAxisFromString
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis);
+
+/**
+ * Get the SDL joystick layer binding for a controller axis mapping.
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis enum value (one of the SDL_GameControllerAxis values)
+ * \returns a SDL_GameControllerButtonBind describing the bind. On failure
+ * (like the given Controller axis doesn't exist on the device), its
+ * `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetBindForButton
+ */
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller,
+ SDL_GameControllerAxis axis);
+
+/**
+ * Query whether a game controller has a given axis.
+ *
+ * This merely reports whether the controller's mapping defined this axis, as
+ * that is all the information SDL has about the physical device.
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis enum value (an SDL_GameControllerAxis value)
+ * \returns SDL_TRUE if the controller has this axis, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL
+SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+/**
+ * Get the current state of an axis control on a game controller.
+ *
+ * The axis indices start at index 0.
+ *
+ * The state is a value ranging from -32768 to 32767. Triggers, however, range
+ * from 0 to 32767 (they never return a negative value).
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis index (one of the SDL_GameControllerAxis values)
+ * \returns axis state (including 0) on success or 0 (also) on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetButton
+ */
+extern DECLSPEC Sint16 SDLCALL
+SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+/**
+ * The list of buttons available from a controller
+ */
+typedef enum
+{
+ SDL_CONTROLLER_BUTTON_INVALID = -1,
+ SDL_CONTROLLER_BUTTON_A,
+ SDL_CONTROLLER_BUTTON_B,
+ SDL_CONTROLLER_BUTTON_X,
+ SDL_CONTROLLER_BUTTON_Y,
+ SDL_CONTROLLER_BUTTON_BACK,
+ SDL_CONTROLLER_BUTTON_GUIDE,
+ SDL_CONTROLLER_BUTTON_START,
+ SDL_CONTROLLER_BUTTON_LEFTSTICK,
+ SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+ SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+ SDL_CONTROLLER_BUTTON_DPAD_UP,
+ SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+ SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+ SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+ SDL_CONTROLLER_BUTTON_MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
+ SDL_CONTROLLER_BUTTON_PADDLE1, /* Xbox Elite paddle P1 */
+ SDL_CONTROLLER_BUTTON_PADDLE2, /* Xbox Elite paddle P3 */
+ SDL_CONTROLLER_BUTTON_PADDLE3, /* Xbox Elite paddle P2 */
+ SDL_CONTROLLER_BUTTON_PADDLE4, /* Xbox Elite paddle P4 */
+ SDL_CONTROLLER_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */
+ SDL_CONTROLLER_BUTTON_MAX
+} SDL_GameControllerButton;
+
+/**
+ * Convert a string into an SDL_GameControllerButton enum.
+ *
+ * This function is called internally to translate SDL_GameController mapping
+ * strings for the underlying joystick device into the consistent
+ * SDL_GameController mapping. You do not normally need to call this function
+ * unless you are parsing SDL_GameController mappings in your own code.
+ *
+ * \param str string representing a SDL_GameController axis
+ * \returns the SDL_GameControllerButton enum corresponding to the input
+ * string, or `SDL_CONTROLLER_AXIS_INVALID` if no match was found.
+ */
+extern DECLSPEC SDL_GameControllerButton SDLCALL SDL_GameControllerGetButtonFromString(const char *str);
+
+/**
+ * Convert from an SDL_GameControllerButton enum to a string.
+ *
+ * The caller should not SDL_free() the returned string.
+ *
+ * \param button an enum value for a given SDL_GameControllerButton
+ * \returns a string for the given button, or NULL if an invalid axis is
+ * specified. The string returned is of the format used by
+ * SDL_GameController mapping strings.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetButtonFromString
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForButton(SDL_GameControllerButton button);
+
+/**
+ * Get the SDL joystick layer binding for a controller button mapping.
+ *
+ * \param gamecontroller a game controller
+ * \param button an button enum value (an SDL_GameControllerButton value)
+ * \returns a SDL_GameControllerButtonBind describing the bind. On failure
+ * (like the given Controller button doesn't exist on the device),
+ * its `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetBindForAxis
+ */
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Query whether a game controller has a given button.
+ *
+ * This merely reports whether the controller's mapping defined this button,
+ * as that is all the information SDL has about the physical device.
+ *
+ * \param gamecontroller a game controller
+ * \param button a button enum value (an SDL_GameControllerButton value)
+ * \returns SDL_TRUE if the controller has this button, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Get the current state of a button on a game controller.
+ *
+ * \param gamecontroller a game controller
+ * \param button a button index (one of the SDL_GameControllerButton values)
+ * \returns 1 for pressed state or 0 for not pressed state or error; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetAxis
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Get the number of touchpads on a game controller.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller);
+
+/**
+ * Get the number of supported simultaneous fingers on a touchpad on a game
+ * controller.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, int touchpad);
+
+/**
+ * Get the current state of a finger on a touchpad on a game controller.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure);
+
+/**
+ * Return whether a game controller has a particular sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \returns SDL_TRUE if the sensor exists, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Set whether data reporting for a game controller sensor is enabled.
+ *
+ * \param gamecontroller The controller to update
+ * \param type The type of sensor to enable/disable
+ * \param enabled Whether data reporting should be enabled
+ * \returns 0 or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled);
+
+/**
+ * Query whether sensor data reporting is enabled for a game controller.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \returns SDL_TRUE if the sensor is enabled, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Get the data rate (number of events per second) of a game controller
+ * sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \return the data rate, or 0.0f if the data rate is not available.
+ */
+extern DECLSPEC float SDLCALL SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Get the current state of a game controller sensor.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ * See SDL_sensor.h for the details for each type of sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \param data A pointer filled with the current sensor state
+ * \param num_values The number of values to write to data
+ * \return 0 or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values);
+
+/**
+ * Start a rumble effect on a game controller.
+ *
+ * Each call to this function cancels any previous rumble effect, and calling
+ * it with 0 intensity stops any rumbling.
+ *
+ * \param gamecontroller The controller to vibrate
+ * \param low_frequency_rumble The intensity of the low frequency (left)
+ * rumble motor, from 0 to 0xFFFF
+ * \param high_frequency_rumble The intensity of the high frequency (right)
+ * rumble motor, from 0 to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if rumble isn't supported on this controller
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
+
+/**
+ * Start a rumble effect in the game controller's triggers.
+ *
+ * Each call to this function cancels any previous trigger rumble effect, and
+ * calling it with 0 intensity stops any rumbling.
+ *
+ * Note that this is rumbling of the _triggers_ and not the game controller as
+ * a whole. The first controller to offer this feature was the PlayStation 5's
+ * DualShock 5.
+ *
+ * \param gamecontroller The controller to vibrate
+ * \param left_rumble The intensity of the left trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param right_rumble The intensity of the right trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if trigger rumble isn't supported on this controller
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms);
+
+/**
+ * Query whether a game controller has an LED.
+ *
+ * \param gamecontroller The controller to query
+ * \returns SDL_TRUE, or SDL_FALSE if this controller does not have a
+ * modifiable LED
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasLED(SDL_GameController *gamecontroller);
+
+/**
+ * Update a game controller's LED color.
+ *
+ * \param gamecontroller The controller to update
+ * \param red The intensity of the red LED
+ * \param green The intensity of the green LED
+ * \param blue The intensity of the blue LED
+ * \returns 0, or -1 if this controller does not have a modifiable LED
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue);
+
+/**
+ * Send a controller specific effect packet
+ *
+ * \param gamecontroller The controller to affect
+ * \param data The data to send to the controller
+ * \param size The size of the data to send to the controller
+ * \returns 0, or -1 if this controller or driver doesn't support effect
+ * packets
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSendEffect(SDL_GameController *gamecontroller, const void *data, int size);
+
+/**
+ * Close a game controller previously opened with SDL_GameControllerOpen().
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ *
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerClose(SDL_GameController *gamecontroller);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_gamecontroller_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_gesture.h b/Client/ThirdParty/SDL2/include/SDL_gesture.h
new file mode 100644
index 0000000..530b3d5
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_gesture.h
@@ -0,0 +1,117 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gesture.h
+ *
+ * Include file for SDL gesture event handling.
+ */
+
+#ifndef SDL_gesture_h_
+#define SDL_gesture_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "SDL_touch.h"
+
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_GestureID;
+
+/* Function prototypes */
+
+/**
+ * Begin recording a gesture on a specified touch device or all touch devices.
+ *
+ * If the parameter `touchId` is -1 (i.e., all devices), this function will
+ * always return 1, regardless of whether there actually are any devices.
+ *
+ * \param touchId the touch device id, or -1 for all touch devices
+ * \returns 1 on success or 0 if the specified device could not be found.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchDevice
+ */
+extern DECLSPEC int SDLCALL SDL_RecordGesture(SDL_TouchID touchId);
+
+
+/**
+ * Save all currently loaded Dollar Gesture templates.
+ *
+ * \param dst a SDL_RWops to save to
+ * \returns the number of saved templates on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadDollarTemplates
+ * \sa SDL_SaveDollarTemplate
+ */
+extern DECLSPEC int SDLCALL SDL_SaveAllDollarTemplates(SDL_RWops *dst);
+
+/**
+ * Save a currently loaded Dollar Gesture template.
+ *
+ * \param gestureId a gesture id
+ * \param dst a SDL_RWops to save to
+ * \returns 1 on success or 0 on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadDollarTemplates
+ * \sa SDL_SaveAllDollarTemplates
+ */
+extern DECLSPEC int SDLCALL SDL_SaveDollarTemplate(SDL_GestureID gestureId,SDL_RWops *dst);
+
+
+/**
+ * Load Dollar Gesture templates from a file.
+ *
+ * \param touchId a touch id
+ * \param src a SDL_RWops to load from
+ * \returns the number of loaded templates on success or a negative error code
+ * (or 0) on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SaveAllDollarTemplates
+ * \sa SDL_SaveDollarTemplate
+ */
+extern DECLSPEC int SDLCALL SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_gesture_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_haptic.h b/Client/ThirdParty/SDL2/include/SDL_haptic.h
new file mode 100644
index 0000000..bb53ed3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_haptic.h
@@ -0,0 +1,1320 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_haptic.h
+ *
+ * \brief The SDL haptic subsystem allows you to control haptic (force feedback)
+ * devices.
+ *
+ * The basic usage is as follows:
+ * - Initialize the subsystem (::SDL_INIT_HAPTIC).
+ * - Open a haptic device.
+ * - SDL_HapticOpen() to open from index.
+ * - SDL_HapticOpenFromJoystick() to open from an existing joystick.
+ * - Create an effect (::SDL_HapticEffect).
+ * - Upload the effect with SDL_HapticNewEffect().
+ * - Run the effect with SDL_HapticRunEffect().
+ * - (optional) Free the effect with SDL_HapticDestroyEffect().
+ * - Close the haptic device with SDL_HapticClose().
+ *
+ * \par Simple rumble example:
+ * \code
+ * SDL_Haptic *haptic;
+ *
+ * // Open the device
+ * haptic = SDL_HapticOpen( 0 );
+ * if (haptic == NULL)
+ * return -1;
+ *
+ * // Initialize simple rumble
+ * if (SDL_HapticRumbleInit( haptic ) != 0)
+ * return -1;
+ *
+ * // Play effect at 50% strength for 2 seconds
+ * if (SDL_HapticRumblePlay( haptic, 0.5, 2000 ) != 0)
+ * return -1;
+ * SDL_Delay( 2000 );
+ *
+ * // Clean up
+ * SDL_HapticClose( haptic );
+ * \endcode
+ *
+ * \par Complete example:
+ * \code
+ * int test_haptic( SDL_Joystick * joystick ) {
+ * SDL_Haptic *haptic;
+ * SDL_HapticEffect effect;
+ * int effect_id;
+ *
+ * // Open the device
+ * haptic = SDL_HapticOpenFromJoystick( joystick );
+ * if (haptic == NULL) return -1; // Most likely joystick isn't haptic
+ *
+ * // See if it can do sine waves
+ * if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_SINE)==0) {
+ * SDL_HapticClose(haptic); // No sine effect
+ * return -1;
+ * }
+ *
+ * // Create the effect
+ * memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default
+ * effect.type = SDL_HAPTIC_SINE;
+ * effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
+ * effect.periodic.direction.dir[0] = 18000; // Force comes from south
+ * effect.periodic.period = 1000; // 1000 ms
+ * effect.periodic.magnitude = 20000; // 20000/32767 strength
+ * effect.periodic.length = 5000; // 5 seconds long
+ * effect.periodic.attack_length = 1000; // Takes 1 second to get max strength
+ * effect.periodic.fade_length = 1000; // Takes 1 second to fade away
+ *
+ * // Upload the effect
+ * effect_id = SDL_HapticNewEffect( haptic, &effect );
+ *
+ * // Test the effect
+ * SDL_HapticRunEffect( haptic, effect_id, 1 );
+ * SDL_Delay( 5000); // Wait for the effect to finish
+ *
+ * // We destroy the effect, although closing the device also does this
+ * SDL_HapticDestroyEffect( haptic, effect_id );
+ *
+ * // Close the device
+ * SDL_HapticClose(haptic);
+ *
+ * return 0; // Success
+ * }
+ * \endcode
+ */
+
+#ifndef SDL_haptic_h_
+#define SDL_haptic_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_joystick.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* FIXME: For SDL 2.1, adjust all the magnitude variables to be Uint16 (0xFFFF).
+ *
+ * At the moment the magnitude variables are mixed between signed/unsigned, and
+ * it is also not made clear that ALL of those variables expect a max of 0x7FFF.
+ *
+ * Some platforms may have higher precision than that (Linux FF, Windows XInput)
+ * so we should fix the inconsistency in favor of higher possible precision,
+ * adjusting for platforms that use different scales.
+ * -flibit
+ */
+
+/**
+ * \typedef SDL_Haptic
+ *
+ * \brief The haptic structure used to identify an SDL haptic.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticOpenFromJoystick
+ * \sa SDL_HapticClose
+ */
+struct _SDL_Haptic;
+typedef struct _SDL_Haptic SDL_Haptic;
+
+
+/**
+ * \name Haptic features
+ *
+ * Different haptic features a device can have.
+ */
+/* @{ */
+
+/**
+ * \name Haptic effects
+ */
+/* @{ */
+
+/**
+ * \brief Constant effect supported.
+ *
+ * Constant haptic effect.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_CONSTANT (1u<<0)
+
+/**
+ * \brief Sine wave effect supported.
+ *
+ * Periodic haptic effect that simulates sine waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SINE (1u<<1)
+
+/**
+ * \brief Left/Right effect supported.
+ *
+ * Haptic effect for direct control over high/low frequency motors.
+ *
+ * \sa SDL_HapticLeftRight
+ * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
+ * we ran out of bits, and this is important for XInput devices.
+ */
+#define SDL_HAPTIC_LEFTRIGHT (1u<<2)
+
+/* !!! FIXME: put this back when we have more bits in 2.1 */
+/* #define SDL_HAPTIC_SQUARE (1<<2) */
+
+/**
+ * \brief Triangle wave effect supported.
+ *
+ * Periodic haptic effect that simulates triangular waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_TRIANGLE (1u<<3)
+
+/**
+ * \brief Sawtoothup wave effect supported.
+ *
+ * Periodic haptic effect that simulates saw tooth up waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SAWTOOTHUP (1u<<4)
+
+/**
+ * \brief Sawtoothdown wave effect supported.
+ *
+ * Periodic haptic effect that simulates saw tooth down waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5)
+
+/**
+ * \brief Ramp effect supported.
+ *
+ * Ramp haptic effect.
+ *
+ * \sa SDL_HapticRamp
+ */
+#define SDL_HAPTIC_RAMP (1u<<6)
+
+/**
+ * \brief Spring effect supported - uses axes position.
+ *
+ * Condition haptic effect that simulates a spring. Effect is based on the
+ * axes position.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_SPRING (1u<<7)
+
+/**
+ * \brief Damper effect supported - uses axes velocity.
+ *
+ * Condition haptic effect that simulates dampening. Effect is based on the
+ * axes velocity.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_DAMPER (1u<<8)
+
+/**
+ * \brief Inertia effect supported - uses axes acceleration.
+ *
+ * Condition haptic effect that simulates inertia. Effect is based on the axes
+ * acceleration.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_INERTIA (1u<<9)
+
+/**
+ * \brief Friction effect supported - uses axes movement.
+ *
+ * Condition haptic effect that simulates friction. Effect is based on the
+ * axes movement.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_FRICTION (1u<<10)
+
+/**
+ * \brief Custom effect is supported.
+ *
+ * User defined custom haptic effect.
+ */
+#define SDL_HAPTIC_CUSTOM (1u<<11)
+
+/* @} *//* Haptic effects */
+
+/* These last few are features the device has, not effects */
+
+/**
+ * \brief Device can set global gain.
+ *
+ * Device supports setting the global gain.
+ *
+ * \sa SDL_HapticSetGain
+ */
+#define SDL_HAPTIC_GAIN (1u<<12)
+
+/**
+ * \brief Device can set autocenter.
+ *
+ * Device supports setting autocenter.
+ *
+ * \sa SDL_HapticSetAutocenter
+ */
+#define SDL_HAPTIC_AUTOCENTER (1u<<13)
+
+/**
+ * \brief Device can be queried for effect status.
+ *
+ * Device supports querying effect status.
+ *
+ * \sa SDL_HapticGetEffectStatus
+ */
+#define SDL_HAPTIC_STATUS (1u<<14)
+
+/**
+ * \brief Device can be paused.
+ *
+ * Devices supports being paused.
+ *
+ * \sa SDL_HapticPause
+ * \sa SDL_HapticUnpause
+ */
+#define SDL_HAPTIC_PAUSE (1u<<15)
+
+
+/**
+ * \name Direction encodings
+ */
+/* @{ */
+
+/**
+ * \brief Uses polar coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_POLAR 0
+
+/**
+ * \brief Uses cartesian coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_CARTESIAN 1
+
+/**
+ * \brief Uses spherical coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_SPHERICAL 2
+
+/**
+ * \brief Use this value to play an effect on the steering wheel axis. This
+ * provides better compatibility across platforms and devices as SDL will guess
+ * the correct axis.
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_STEERING_AXIS 3
+
+/* @} *//* Direction encodings */
+
+/* @} *//* Haptic features */
+
+/*
+ * Misc defines.
+ */
+
+/**
+ * \brief Used to play a device an infinite number of times.
+ *
+ * \sa SDL_HapticRunEffect
+ */
+#define SDL_HAPTIC_INFINITY 4294967295U
+
+
+/**
+ * \brief Structure that represents a haptic direction.
+ *
+ * This is the direction where the force comes from,
+ * instead of the direction in which the force is exerted.
+ *
+ * Directions can be specified by:
+ * - ::SDL_HAPTIC_POLAR : Specified by polar coordinates.
+ * - ::SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates.
+ * - ::SDL_HAPTIC_SPHERICAL : Specified by spherical coordinates.
+ *
+ * Cardinal directions of the haptic device are relative to the positioning
+ * of the device. North is considered to be away from the user.
+ *
+ * The following diagram represents the cardinal directions:
+ * \verbatim
+ .--.
+ |__| .-------.
+ |=.| |.-----.|
+ |--| || ||
+ | | |'-----'|
+ |__|~')_____('
+ [ COMPUTER ]
+
+
+ North (0,-1)
+ ^
+ |
+ |
+ (-1,0) West <----[ HAPTIC ]----> East (1,0)
+ |
+ |
+ v
+ South (0,1)
+
+
+ [ USER ]
+ \|||/
+ (o o)
+ ---ooO-(_)-Ooo---
+ \endverbatim
+ *
+ * If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a
+ * degree starting north and turning clockwise. ::SDL_HAPTIC_POLAR only uses
+ * the first \c dir parameter. The cardinal directions would be:
+ * - North: 0 (0 degrees)
+ * - East: 9000 (90 degrees)
+ * - South: 18000 (180 degrees)
+ * - West: 27000 (270 degrees)
+ *
+ * If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions
+ * (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses
+ * the first three \c dir parameters. The cardinal directions would be:
+ * - North: 0,-1, 0
+ * - East: 1, 0, 0
+ * - South: 0, 1, 0
+ * - West: -1, 0, 0
+ *
+ * The Z axis represents the height of the effect if supported, otherwise
+ * it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you
+ * can use any multiple you want, only the direction matters.
+ *
+ * If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations.
+ * The first two \c dir parameters are used. The \c dir parameters are as
+ * follows (all values are in hundredths of degrees):
+ * - Degrees from (1, 0) rotated towards (0, 1).
+ * - Degrees towards (0, 0, 1) (device needs at least 3 axes).
+ *
+ *
+ * Example of force coming from the south with all encodings (force coming
+ * from the south means the user will have to pull the stick to counteract):
+ * \code
+ * SDL_HapticDirection direction;
+ *
+ * // Cartesian directions
+ * direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding.
+ * direction.dir[0] = 0; // X position
+ * direction.dir[1] = 1; // Y position
+ * // Assuming the device has 2 axes, we don't need to specify third parameter.
+ *
+ * // Polar directions
+ * direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding.
+ * direction.dir[0] = 18000; // Polar only uses first parameter
+ *
+ * // Spherical coordinates
+ * direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding
+ * direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters.
+ * \endcode
+ *
+ * \sa SDL_HAPTIC_POLAR
+ * \sa SDL_HAPTIC_CARTESIAN
+ * \sa SDL_HAPTIC_SPHERICAL
+ * \sa SDL_HAPTIC_STEERING_AXIS
+ * \sa SDL_HapticEffect
+ * \sa SDL_HapticNumAxes
+ */
+typedef struct SDL_HapticDirection
+{
+ Uint8 type; /**< The type of encoding. */
+ Sint32 dir[3]; /**< The encoded direction. */
+} SDL_HapticDirection;
+
+
+/**
+ * \brief A structure containing a template for a Constant effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_CONSTANT effect.
+ *
+ * A constant effect applies a constant force in the specified direction
+ * to the joystick.
+ *
+ * \sa SDL_HAPTIC_CONSTANT
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticConstant
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_CONSTANT */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Constant */
+ Sint16 level; /**< Strength of the constant effect. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticConstant;
+
+/**
+ * \brief A structure containing a template for a Periodic effect.
+ *
+ * The struct handles the following effects:
+ * - ::SDL_HAPTIC_SINE
+ * - ::SDL_HAPTIC_LEFTRIGHT
+ * - ::SDL_HAPTIC_TRIANGLE
+ * - ::SDL_HAPTIC_SAWTOOTHUP
+ * - ::SDL_HAPTIC_SAWTOOTHDOWN
+ *
+ * A periodic effect consists in a wave-shaped effect that repeats itself
+ * over time. The type determines the shape of the wave and the parameters
+ * determine the dimensions of the wave.
+ *
+ * Phase is given by hundredth of a degree meaning that giving the phase a value
+ * of 9000 will displace it 25% of its period. Here are sample values:
+ * - 0: No phase displacement.
+ * - 9000: Displaced 25% of its period.
+ * - 18000: Displaced 50% of its period.
+ * - 27000: Displaced 75% of its period.
+ * - 36000: Displaced 100% of its period, same as 0, but 0 is preferred.
+ *
+ * Examples:
+ * \verbatim
+ SDL_HAPTIC_SINE
+ __ __ __ __
+ / \ / \ / \ /
+ / \__/ \__/ \__/
+
+ SDL_HAPTIC_SQUARE
+ __ __ __ __ __
+ | | | | | | | | | |
+ | |__| |__| |__| |__| |
+
+ SDL_HAPTIC_TRIANGLE
+ /\ /\ /\ /\ /\
+ / \ / \ / \ / \ /
+ / \/ \/ \/ \/
+
+ SDL_HAPTIC_SAWTOOTHUP
+ /| /| /| /| /| /| /|
+ / | / | / | / | / | / | / |
+ / |/ |/ |/ |/ |/ |/ |
+
+ SDL_HAPTIC_SAWTOOTHDOWN
+ \ |\ |\ |\ |\ |\ |\ |
+ \ | \ | \ | \ | \ | \ | \ |
+ \| \| \| \| \| \| \|
+ \endverbatim
+ *
+ * \sa SDL_HAPTIC_SINE
+ * \sa SDL_HAPTIC_LEFTRIGHT
+ * \sa SDL_HAPTIC_TRIANGLE
+ * \sa SDL_HAPTIC_SAWTOOTHUP
+ * \sa SDL_HAPTIC_SAWTOOTHDOWN
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticPeriodic
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT,
+ ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or
+ ::SDL_HAPTIC_SAWTOOTHDOWN */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Periodic */
+ Uint16 period; /**< Period of the wave. */
+ Sint16 magnitude; /**< Peak value; if negative, equivalent to 180 degrees extra phase shift. */
+ Sint16 offset; /**< Mean value of the wave. */
+ Uint16 phase; /**< Positive phase shift given by hundredth of a degree. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticPeriodic;
+
+/**
+ * \brief A structure containing a template for a Condition effect.
+ *
+ * The struct handles the following effects:
+ * - ::SDL_HAPTIC_SPRING: Effect based on axes position.
+ * - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity.
+ * - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration.
+ * - ::SDL_HAPTIC_FRICTION: Effect based on axes movement.
+ *
+ * Direction is handled by condition internals instead of a direction member.
+ * The condition effect specific members have three parameters. The first
+ * refers to the X axis, the second refers to the Y axis and the third
+ * refers to the Z axis. The right terms refer to the positive side of the
+ * axis and the left terms refer to the negative side of the axis. Please
+ * refer to the ::SDL_HapticDirection diagram for which side is positive and
+ * which is negative.
+ *
+ * \sa SDL_HapticDirection
+ * \sa SDL_HAPTIC_SPRING
+ * \sa SDL_HAPTIC_DAMPER
+ * \sa SDL_HAPTIC_INERTIA
+ * \sa SDL_HAPTIC_FRICTION
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticCondition
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER,
+ ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION */
+ SDL_HapticDirection direction; /**< Direction of the effect - Not used ATM. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Condition */
+ Uint16 right_sat[3]; /**< Level when joystick is to the positive side; max 0xFFFF. */
+ Uint16 left_sat[3]; /**< Level when joystick is to the negative side; max 0xFFFF. */
+ Sint16 right_coeff[3]; /**< How fast to increase the force towards the positive side. */
+ Sint16 left_coeff[3]; /**< How fast to increase the force towards the negative side. */
+ Uint16 deadband[3]; /**< Size of the dead zone; max 0xFFFF: whole axis-range when 0-centered. */
+ Sint16 center[3]; /**< Position of the dead zone. */
+} SDL_HapticCondition;
+
+/**
+ * \brief A structure containing a template for a Ramp effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_RAMP effect.
+ *
+ * The ramp effect starts at start strength and ends at end strength.
+ * It augments in linear fashion. If you use attack and fade with a ramp
+ * the effects get added to the ramp effect making the effect become
+ * quadratic instead of linear.
+ *
+ * \sa SDL_HAPTIC_RAMP
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticRamp
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_RAMP */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Ramp */
+ Sint16 start; /**< Beginning strength level. */
+ Sint16 end; /**< Ending strength level. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticRamp;
+
+/**
+ * \brief A structure containing a template for a Left/Right effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
+ *
+ * The Left/Right effect is used to explicitly control the large and small
+ * motors, commonly found in modern game controllers. The small (right) motor
+ * is high frequency, and the large (left) motor is low frequency.
+ *
+ * \sa SDL_HAPTIC_LEFTRIGHT
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticLeftRight
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect in milliseconds. */
+
+ /* Rumble */
+ Uint16 large_magnitude; /**< Control of the large controller motor. */
+ Uint16 small_magnitude; /**< Control of the small controller motor. */
+} SDL_HapticLeftRight;
+
+/**
+ * \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_CUSTOM effect.
+ *
+ * A custom force feedback effect is much like a periodic effect, where the
+ * application can define its exact shape. You will have to allocate the
+ * data yourself. Data should consist of channels * samples Uint16 samples.
+ *
+ * If channels is one, the effect is rotated using the defined direction.
+ * Otherwise it uses the samples in data for the different axes.
+ *
+ * \sa SDL_HAPTIC_CUSTOM
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticCustom
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_CUSTOM */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Custom */
+ Uint8 channels; /**< Axes to use, minimum of one. */
+ Uint16 period; /**< Sample periods. */
+ Uint16 samples; /**< Amount of samples. */
+ Uint16 *data; /**< Should contain channels*samples items. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticCustom;
+
+/**
+ * \brief The generic template for any haptic effect.
+ *
+ * All values max at 32767 (0x7FFF). Signed values also can be negative.
+ * Time values unless specified otherwise are in milliseconds.
+ *
+ * You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767
+ * value. Neither delay, interval, attack_length nor fade_length support
+ * ::SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends.
+ *
+ * Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of
+ * ::SDL_HAPTIC_INFINITY.
+ *
+ * Button triggers may not be supported on all devices, it is advised to not
+ * use them if possible. Buttons start at index 1 instead of index 0 like
+ * the joystick.
+ *
+ * If both attack_length and fade_level are 0, the envelope is not used,
+ * otherwise both values are used.
+ *
+ * Common parts:
+ * \code
+ * // Replay - All effects have this
+ * Uint32 length; // Duration of effect (ms).
+ * Uint16 delay; // Delay before starting effect.
+ *
+ * // Trigger - All effects have this
+ * Uint16 button; // Button that triggers effect.
+ * Uint16 interval; // How soon before effect can be triggered again.
+ *
+ * // Envelope - All effects except condition effects have this
+ * Uint16 attack_length; // Duration of the attack (ms).
+ * Uint16 attack_level; // Level at the start of the attack.
+ * Uint16 fade_length; // Duration of the fade out (ms).
+ * Uint16 fade_level; // Level at the end of the fade.
+ * \endcode
+ *
+ *
+ * Here we have an example of a constant effect evolution in time:
+ * \verbatim
+ Strength
+ ^
+ |
+ | effect level --> _________________
+ | / \
+ | / \
+ | / \
+ | / \
+ | attack_level --> | \
+ | | | <--- fade_level
+ |
+ +--------------------------------------------------> Time
+ [--] [---]
+ attack_length fade_length
+
+ [------------------][-----------------------]
+ delay length
+ \endverbatim
+ *
+ * Note either the attack_level or the fade_level may be above the actual
+ * effect level.
+ *
+ * \sa SDL_HapticConstant
+ * \sa SDL_HapticPeriodic
+ * \sa SDL_HapticCondition
+ * \sa SDL_HapticRamp
+ * \sa SDL_HapticLeftRight
+ * \sa SDL_HapticCustom
+ */
+typedef union SDL_HapticEffect
+{
+ /* Common for all force feedback effects */
+ Uint16 type; /**< Effect type. */
+ SDL_HapticConstant constant; /**< Constant effect. */
+ SDL_HapticPeriodic periodic; /**< Periodic effect. */
+ SDL_HapticCondition condition; /**< Condition effect. */
+ SDL_HapticRamp ramp; /**< Ramp effect. */
+ SDL_HapticLeftRight leftright; /**< Left/Right effect. */
+ SDL_HapticCustom custom; /**< Custom effect. */
+} SDL_HapticEffect;
+
+
+/* Function prototypes */
+/**
+ * Count the number of haptic devices attached to the system.
+ *
+ * \returns the number of haptic devices detected on the system or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticName
+ */
+extern DECLSPEC int SDLCALL SDL_NumHaptics(void);
+
+/**
+ * Get the implementation dependent name of a haptic device.
+ *
+ * This can be called before any joysticks are opened. If no name can be
+ * found, this function returns NULL.
+ *
+ * \param device_index index of the device to query.
+ * \returns the name of the device or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_NumHaptics
+ */
+extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index);
+
+/**
+ * Open a haptic device for use.
+ *
+ * The index passed as an argument refers to the N'th haptic device on this
+ * system.
+ *
+ * When opening a haptic device, its gain will be set to maximum and
+ * autocenter will be disabled. To modify these values use SDL_HapticSetGain()
+ * and SDL_HapticSetAutocenter().
+ *
+ * \param device_index index of the device to open
+ * \returns the device identifier or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticClose
+ * \sa SDL_HapticIndex
+ * \sa SDL_HapticOpenFromJoystick
+ * \sa SDL_HapticOpenFromMouse
+ * \sa SDL_HapticPause
+ * \sa SDL_HapticSetAutocenter
+ * \sa SDL_HapticSetGain
+ * \sa SDL_HapticStopAll
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpen(int device_index);
+
+/**
+ * Check if the haptic device at the designated index has been opened.
+ *
+ * \param device_index the index of the device to query
+ * \returns 1 if it has been opened, 0 if it hasn't or on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticIndex
+ * \sa SDL_HapticOpen
+ */
+extern DECLSPEC int SDLCALL SDL_HapticOpened(int device_index);
+
+/**
+ * Get the index of a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the index of the specified haptic device or a negative error code
+ * on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticOpened
+ */
+extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic);
+
+/**
+ * Query whether or not the current mouse has haptic capabilities.
+ *
+ * \returns SDL_TRUE if the mouse is haptic or SDL_FALSE if it isn't.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpenFromMouse
+ */
+extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void);
+
+/**
+ * Try to open a haptic device from the current mouse.
+ *
+ * \returns the haptic device identifier or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_MouseIsHaptic
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromMouse(void);
+
+/**
+ * Query if a joystick has haptic features.
+ *
+ * \param joystick the SDL_Joystick to test for haptic capabilities
+ * \returns SDL_TRUE if the joystick is haptic, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpenFromJoystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick);
+
+/**
+ * Open a haptic device for use from a joystick device.
+ *
+ * You must still close the haptic device separately. It will not be closed
+ * with the joystick.
+ *
+ * When opened from a joystick you should first close the haptic device before
+ * closing the joystick device. If not, on some implementations the haptic
+ * device will also get unallocated and you'll be unable to use force feedback
+ * on that device.
+ *
+ * \param joystick the SDL_Joystick to create a haptic device from
+ * \returns a valid haptic device identifier on success or NULL on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticClose
+ * \sa SDL_HapticOpen
+ * \sa SDL_JoystickIsHaptic
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromJoystick(SDL_Joystick *
+ joystick);
+
+/**
+ * Close a haptic device previously opened with SDL_HapticOpen().
+ *
+ * \param haptic the SDL_Haptic device to close
+ *
+ * \sa SDL_HapticOpen
+ */
+extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic);
+
+/**
+ * Get the number of effects a haptic device can store.
+ *
+ * On some platforms this isn't fully supported, and therefore is an
+ * approximation. Always check to see if your created effect was actually
+ * created and do not rely solely on SDL_HapticNumEffects().
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the number of effects the haptic device can store or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNumEffectsPlaying
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic);
+
+/**
+ * Get the number of effects a haptic device can play at the same time.
+ *
+ * This is not supported on all platforms, but will always return a value.
+ *
+ * \param haptic the SDL_Haptic device to query maximum playing effects
+ * \returns the number of effects the haptic device can play at the same time
+ * or a negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNumEffects
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic);
+
+/**
+ * Get the haptic device's supported features in bitwise manner.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns a list of supported haptic features in bitwise manner (OR'd), or 0
+ * on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticEffectSupported
+ * \sa SDL_HapticNumEffects
+ */
+extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic);
+
+
+/**
+ * Get the number of haptic axes the device has.
+ *
+ * The number of haptic axes might be useful if working with the
+ * SDL_HapticDirection effect.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the number of axes on success or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumAxes(SDL_Haptic * haptic);
+
+/**
+ * Check to see if an effect is supported by a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \param effect the desired effect to query
+ * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNewEffect
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic,
+ SDL_HapticEffect *
+ effect);
+
+/**
+ * Create a new haptic effect on a specified device.
+ *
+ * \param haptic an SDL_Haptic device to create the effect on
+ * \param effect an SDL_HapticEffect structure containing the properties of
+ * the effect to create
+ * \returns the ID of the effect on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticRunEffect
+ * \sa SDL_HapticUpdateEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic,
+ SDL_HapticEffect * effect);
+
+/**
+ * Update the properties of an effect.
+ *
+ * Can be used dynamically, although behavior when dynamically changing
+ * direction may be strange. Specifically the effect may re-upload itself and
+ * start playing from the start. You also cannot change the type either when
+ * running SDL_HapticUpdateEffect().
+ *
+ * \param haptic the SDL_Haptic device that has the effect
+ * \param effect the identifier of the effect to update
+ * \param data an SDL_HapticEffect structure containing the new effect
+ * properties to use
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticNewEffect
+ * \sa SDL_HapticRunEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic,
+ int effect,
+ SDL_HapticEffect * data);
+
+/**
+ * Run the haptic effect on its associated haptic device.
+ *
+ * To repeat the effect over and over indefinitely, set `iterations` to
+ * `SDL_HAPTIC_INFINITY`. (Repeats the envelope - attack and fade.) To make
+ * one instance of the effect last indefinitely (so the effect does not fade),
+ * set the effect's `length` in its structure/union to `SDL_HAPTIC_INFINITY`
+ * instead.
+ *
+ * \param haptic the SDL_Haptic device to run the effect on
+ * \param effect the ID of the haptic effect to run
+ * \param iterations the number of iterations to run the effect; use
+ * `SDL_HAPTIC_INFINITY` to repeat forever
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticGetEffectStatus
+ * \sa SDL_HapticStopEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic,
+ int effect,
+ Uint32 iterations);
+
+/**
+ * Stop the haptic effect on its associated haptic device.
+ *
+ * *
+ *
+ * \param haptic the SDL_Haptic device to stop the effect on
+ * \param effect the ID of the haptic effect to stop
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticRunEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Destroy a haptic effect on the device.
+ *
+ * This will stop the effect if it's running. Effects are automatically
+ * destroyed when the device is closed.
+ *
+ * \param haptic the SDL_Haptic device to destroy the effect on
+ * \param effect the ID of the haptic effect to destroy
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNewEffect
+ */
+extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Get the status of the current effect on the specified haptic device.
+ *
+ * Device must support the SDL_HAPTIC_STATUS feature.
+ *
+ * \param haptic the SDL_Haptic device to query for the effect status on
+ * \param effect the ID of the haptic effect to query its status
+ * \returns 0 if it isn't playing, 1 if it is playing, or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticRunEffect
+ * \sa SDL_HapticStopEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Set the global gain of the specified haptic device.
+ *
+ * Device must support the SDL_HAPTIC_GAIN feature.
+ *
+ * The user may specify the maximum gain by setting the environment variable
+ * `SDL_HAPTIC_GAIN_MAX` which should be between 0 and 100. All calls to
+ * SDL_HapticSetGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the
+ * maximum.
+ *
+ * \param haptic the SDL_Haptic device to set the gain on
+ * \param gain value to set the gain to, should be between 0 and 100 (0 - 100)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain);
+
+/**
+ * Set the global autocenter of the device.
+ *
+ * Autocenter should be between 0 and 100. Setting it to 0 will disable
+ * autocentering.
+ *
+ * Device must support the SDL_HAPTIC_AUTOCENTER feature.
+ *
+ * \param haptic the SDL_Haptic device to set autocentering on
+ * \param autocenter value to set autocenter to (0-100)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic,
+ int autocenter);
+
+/**
+ * Pause a haptic device.
+ *
+ * Device must support the `SDL_HAPTIC_PAUSE` feature. Call
+ * SDL_HapticUnpause() to resume playback.
+ *
+ * Do not modify the effects nor add new ones while the device is paused. That
+ * can cause all sorts of weird errors.
+ *
+ * \param haptic the SDL_Haptic device to pause
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticUnpause
+ */
+extern DECLSPEC int SDLCALL SDL_HapticPause(SDL_Haptic * haptic);
+
+/**
+ * Unpause a haptic device.
+ *
+ * Call to unpause after SDL_HapticPause().
+ *
+ * \param haptic the SDL_Haptic device to unpause
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticPause
+ */
+extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic);
+
+/**
+ * Stop all the currently playing effects on a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to stop
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_HapticStopAll(SDL_Haptic * haptic);
+
+/**
+ * Check whether rumble is supported on a haptic device.
+ *
+ * \param haptic haptic device to check for rumble support
+ * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleStop
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic);
+
+/**
+ * Initialize a haptic device for simple rumble playback.
+ *
+ * \param haptic the haptic device to initialize for simple rumble playback
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleStop
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic);
+
+/**
+ * Run a simple rumble effect on a haptic device.
+ *
+ * \param haptic the haptic device to play the rumble effect on
+ * \param strength strength of the rumble to play as a 0-1 float value
+ * \param length length of the rumble to play in milliseconds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumbleStop
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length );
+
+/**
+ * Stop the simple rumble on a haptic device.
+ *
+ * \param haptic the haptic device to stop the rumble effect on
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_haptic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_hints.h b/Client/ThirdParty/SDL2/include/SDL_hints.h
new file mode 100644
index 0000000..c3ae80d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_hints.h
@@ -0,0 +1,1840 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_hints.h
+ *
+ * Official documentation for SDL configuration variables
+ *
+ * This file contains functions to set and get configuration hints,
+ * as well as listing each of them alphabetically.
+ *
+ * The convention for naming hints is SDL_HINT_X, where "SDL_X" is
+ * the environment variable that can be used to override the default.
+ *
+ * In general these hints are just that - they may or may not be
+ * supported or applicable on any given platform, but they provide
+ * a way for an application or user to give the library a hint as
+ * to how they would like the library to work.
+ */
+
+#ifndef SDL_hints_h_
+#define SDL_hints_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief A variable controlling whether the Android / iOS built-in
+ * accelerometer should be listed as a joystick device.
+ *
+ * This variable can be set to the following values:
+ * "0" - The accelerometer is not listed as a joystick
+ * "1" - The accelerometer is available as a 3 axis joystick (the default).
+ */
+#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK"
+
+/**
+ * \brief Specify the behavior of Alt+Tab while the keyboard is grabbed.
+ *
+ * By default, SDL emulates Alt+Tab functionality while the keyboard is grabbed
+ * and your window is full-screen. This prevents the user from getting stuck in
+ * your application if you've enabled keyboard grab.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will not handle Alt+Tab. Your application is responsible
+ for handling Alt+Tab while the keyboard is grabbed.
+ * "1" - SDL will minimize your window when Alt+Tab is pressed (default)
+*/
+#define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED"
+
+/**
+ * \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it.
+ * This is a debugging aid for developers and not expected to be used by end users. The default is "1"
+ *
+ * This variable can be set to the following values:
+ * "0" - don't allow topmost
+ * "1" - allow topmost
+ */
+#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"
+
+/**
+ * \brief Android APK expansion main file version. Should be a string number like "1", "2" etc.
+ *
+ * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION.
+ *
+ * If both hints were set then SDL_RWFromFile() will look into expansion files
+ * after a given relative path was not found in the internal storage and assets.
+ *
+ * By default this hint is not set and the APK expansion files are not searched.
+ */
+#define SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION"
+
+/**
+ * \brief Android APK expansion patch file version. Should be a string number like "1", "2" etc.
+ *
+ * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION.
+ *
+ * If both hints were set then SDL_RWFromFile() will look into expansion files
+ * after a given relative path was not found in the internal storage and assets.
+ *
+ * By default this hint is not set and the APK expansion files are not searched.
+ */
+#define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"
+
+/**
+ * \brief A variable to control whether the event loop will block itself when the app is paused.
+ *
+ * The variable can be set to the following values:
+ * "0" - Non blocking.
+ * "1" - Blocking. (default)
+ *
+ * The value should be set before SDL is initialized.
+ */
+#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE"
+
+/**
+ * \brief A variable to control whether SDL will pause audio in background
+ * (Requires SDL_ANDROID_BLOCK_ON_PAUSE as "Non blocking")
+ *
+ * The variable can be set to the following values:
+ * "0" - Non paused.
+ * "1" - Paused. (default)
+ *
+ * The value should be set before SDL is initialized.
+ */
+#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO"
+
+/**
+ * \brief A variable to control whether we trap the Android back button to handle it manually.
+ * This is necessary for the right mouse button to work on some Android devices, or
+ * to be able to trap the back button for use in your code reliably. If set to true,
+ * the back button will show up as an SDL_KEYDOWN / SDL_KEYUP pair with a keycode of
+ * SDL_SCANCODE_AC_BACK.
+ *
+ * The variable can be set to the following values:
+ * "0" - Back button will be handled as usual for system. (default)
+ * "1" - Back button will be trapped, allowing you to handle the key press
+ * manually. (This will also let right mouse click work on systems
+ * where the right mouse button functions as back.)
+ *
+ * The value of this hint is used at runtime, so it can be changed at any time.
+ */
+#define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON"
+
+/**
+ * \brief A variable controlling whether controllers used with the Apple TV
+ * generate UI events.
+ *
+ * When UI events are generated by controller input, the app will be
+ * backgrounded when the Apple TV remote's menu button is pressed, and when the
+ * pause or B buttons on gamepads are pressed.
+ *
+ * More information about properly making use of controllers for the Apple TV
+ * can be found here:
+ * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/
+ *
+ * This variable can be set to the following values:
+ * "0" - Controller input does not generate UI events (the default).
+ * "1" - Controller input generates UI events.
+ */
+#define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS"
+
+/**
+ * \brief A variable controlling whether the Apple TV remote's joystick axes
+ * will automatically match the rotation of the remote.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remote orientation does not affect joystick axes (the default).
+ * "1" - Joystick axes are based on the orientation of the remote.
+ */
+#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION"
+
+/**
+ * \brief A variable controlling the audio category on iOS and Mac OS X
+ *
+ * This variable can be set to the following values:
+ *
+ * "ambient" - Use the AVAudioSessionCategoryAmbient audio category, will be muted by the phone mute switch (default)
+ * "playback" - Use the AVAudioSessionCategoryPlayback category
+ *
+ * For more information, see Apple's documentation:
+ * https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html
+ */
+#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
+
+/**
+ * \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your program ("My Game 2: The Revenge")
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: probably the application's name or "SDL Application" if SDL
+ * doesn't have any better information.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME"
+
+/**
+ * \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing ("audio stream" is
+ * probably sufficient in many cases, but this could be useful for something
+ * like "team chat" if you have a headset playing VoIP audio separately).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "audio stream" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME"
+
+/**
+ * \brief Specify an application role for an audio device.
+ *
+ * Some audio backends (such as Pipewire) allow you to describe the role of
+ * your audio stream. Among other things, this description might show up in
+ * a system control panel or software for displaying and manipulating media
+ * playback/capture graphs.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing (Game, Music, Movie,
+ * etc...).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "Game" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE"
+
+/**
+ * \brief A variable controlling speed/quality tradeoff of audio resampling.
+ *
+ * If available, SDL can use libsamplerate ( http://www.mega-nerd.com/SRC/ )
+ * to handle audio resampling. There are different resampling modes available
+ * that produce different levels of quality, using more CPU.
+ *
+ * If this hint isn't specified to a valid setting, or libsamplerate isn't
+ * available, SDL will use the default, internal resampling algorithm.
+ *
+ * Note that this is currently only applicable to resampling audio that is
+ * being written to a device for playback or audio being read from a device
+ * for capture. SDL_AudioCVT always uses the default resampler (although this
+ * might change for SDL 2.1).
+ *
+ * This hint is currently only checked at audio subsystem initialization.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" or "default" - Use SDL's internal resampling (Default when not set - low quality, fast)
+ * "1" or "fast" - Use fast, slightly higher quality resampling, if available
+ * "2" or "medium" - Use medium quality resampling, if available
+ * "3" or "best" - Use high quality resampling, if available
+ */
+#define SDL_HINT_AUDIO_RESAMPLING_MODE "SDL_AUDIO_RESAMPLING_MODE"
+
+/**
+ * \brief A variable controlling whether SDL updates joystick state when getting input events
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - You'll call SDL_JoystickUpdate() manually
+ * "1" - SDL will automatically call SDL_JoystickUpdate() (default)
+ *
+ * This hint can be toggled on and off at runtime.
+ */
+#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS"
+
+/**
+ * \brief A variable controlling whether SDL updates sensor state when getting input events
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - You'll call SDL_SensorUpdate() manually
+ * "1" - SDL will automatically call SDL_SensorUpdate() (default)
+ *
+ * This hint can be toggled on and off at runtime.
+ */
+#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS"
+
+/**
+ * \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs.
+ *
+ * The bitmap header version 4 is required for proper alpha channel support and
+ * SDL will use it when required. Should this not be desired, this hint can
+ * force the use of the 40 byte header version which is supported everywhere.
+ *
+ * The variable can be set to the following values:
+ * "0" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file with an alpha mask. SDL will use the bitmap
+ * header version 4 and set the alpha mask accordingly.
+ * "1" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file without an alpha mask. The alpha channel data
+ * will be in the file, but applications are going to ignore it.
+ *
+ * The default value is "0".
+ */
+#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT"
+
+/**
+ * \brief Override for SDL_GetDisplayUsableBounds()
+ *
+ * If set, this hint will override the expected results for
+ * SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want
+ * to do this, but this allows an embedded system to request that some of the
+ * screen be reserved for other uses when paired with a well-behaved
+ * application.
+ *
+ * The contents of this hint must be 4 comma-separated integers, the first
+ * is the bounds x, then y, width and height, in that order.
+ */
+#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
+
+/**
+ * \brief Disable giving back control to the browser automatically
+ * when running with asyncify
+ *
+ * With -s ASYNCIFY, SDL2 calls emscripten_sleep during operations
+ * such as refreshing the screen or polling events.
+ *
+ * This hint only applies to the emscripten platform
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable emscripten_sleep calls (if you give back browser control manually or use asyncify for other purposes)
+ * "1" - Enable emscripten_sleep calls (the default)
+ */
+#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY"
+
+/**
+ * \brief override the binding element for keyboard inputs for Emscripten builds
+ *
+ * This hint only applies to the emscripten platform
+ *
+ * The variable can be one of
+ * "#window" - The javascript window object (this is the default)
+ * "#document" - The javascript document object
+ * "#screen" - the javascript window.screen object
+ * "#canvas" - the WebGL canvas element
+ * any other string without a leading # sign applies to the element on the page with that ID.
+ */
+#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
+
+/**
+ * \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
+ *
+ * The variable can be set to the following values:
+ * "0" - Do not scan for Steam Controllers
+ * "1" - Scan for Steam Controllers (the default)
+ *
+ * The default value is "1". This hint must be set before initializing the joystick subsystem.
+ */
+#define SDL_HINT_ENABLE_STEAM_CONTROLLERS "SDL_ENABLE_STEAM_CONTROLLERS"
+
+/**
+ * \brief A variable controlling whether SDL logs all events pushed onto its internal queue.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - Don't log any events (default)
+ * "1" - Log all events except mouse and finger motion, which are pretty spammy.
+ * "2" - Log all events.
+ *
+ * This is generally meant to be used to debug SDL itself, but can be useful
+ * for application developers that need better visibility into what is going
+ * on in the event queue. Logged events are sent through SDL_Log(), which
+ * means by default they appear on stdout on most platforms or maybe
+ * OutputDebugString() on Windows, and can be funneled by the app with
+ * SDL_LogSetOutputFunction(), etc.
+ *
+ * This hint can be toggled on and off at runtime, if you only need to log
+ * events for a small subset of program execution.
+ */
+#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING"
+
+/**
+ * \brief A variable controlling how 3D acceleration is used to accelerate the SDL screen surface.
+ *
+ * SDL can try to accelerate the SDL screen surface by using streaming
+ * textures with a 3D rendering engine. This variable controls whether and
+ * how this is done.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable 3D acceleration
+ * "1" - Enable 3D acceleration, using the default renderer.
+ * "X" - Enable 3D acceleration, using X where X is one of the valid rendering drivers. (e.g. "direct3d", "opengl", etc.)
+ *
+ * By default SDL tries to make a best guess for each platform whether
+ * to use acceleration or not.
+ */
+#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION"
+
+/**
+ * \brief A variable that lets you manually hint extra gamecontroller db entries.
+ *
+ * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping()
+ */
+#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG"
+
+/**
+ * \brief A variable that lets you provide a file with extra gamecontroller db entries.
+ *
+ * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping()
+ */
+#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE"
+
+/**
+ * \brief A variable that overrides the automatic controller type detection
+ *
+ * The variable should be comma separated entries, in the form: VID/PID=type
+ *
+ * The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd
+ *
+ * The type should be one of:
+ * Xbox360
+ * XboxOne
+ * PS3
+ * PS4
+ * PS5
+ * SwitchPro
+ *
+ * This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ */
+#define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE"
+
+/**
+ * \brief A variable containing a list of devices to skip when scanning for game controllers.
+ *
+ * The format of the string is a comma separated list of USB VID/PID pairs
+ * in hexadecimal form, e.g.
+ *
+ * 0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ * The variable can also take the form of @file, in which case the named
+ * file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES "SDL_GAMECONTROLLER_IGNORE_DEVICES"
+
+/**
+ * \brief If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable.
+ *
+ * The format of the string is a comma separated list of USB VID/PID pairs
+ * in hexadecimal form, e.g.
+ *
+ * 0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ * The variable can also take the form of @file, in which case the named
+ * file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
+
+/**
+ * \brief If set, game controller face buttons report their values according to their labels instead of their positional layout.
+ *
+ * For example, on Nintendo Switch controllers, normally you'd get:
+ *
+ * (Y)
+ * (X) (B)
+ * (A)
+ *
+ * but if this hint is set, you'll get:
+ *
+ * (X)
+ * (Y) (A)
+ * (B)
+ *
+ * The variable can be set to the following values:
+ * "0" - Report the face buttons by position, as though they were on an Xbox controller.
+ * "1" - Report the face buttons by label instead of position
+ *
+ * The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS"
+
+/**
+ * \brief A variable controlling whether grabbing input grabs the keyboard
+ *
+ * This variable can be set to the following values:
+ * "0" - Grab will affect only the mouse
+ * "1" - Grab will affect mouse and keyboard
+ *
+ * By default SDL will not grab the keyboard so system shortcuts still work.
+ */
+#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD"
+
+/**
+ * \brief A variable controlling whether the idle timer is disabled on iOS.
+ *
+ * When an iOS app does not receive touches for some time, the screen is
+ * dimmed automatically. For games where the accelerometer is the only input
+ * this is problematic. This functionality can be disabled by setting this
+ * hint.
+ *
+ * As of SDL 2.0.4, SDL_EnableScreenSaver() and SDL_DisableScreenSaver()
+ * accomplish the same thing on iOS. They should be preferred over this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Enable idle timer
+ * "1" - Disable idle timer
+ */
+#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED"
+
+/**
+ * \brief A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_TEXTEDITING events.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL_TEXTEDITING events are sent, and it is the application's
+ * responsibility to render the text from these events and
+ * differentiate it somehow from committed text. (default)
+ * "1" - If supported by the IME then SDL_TEXTEDITING events are not sent,
+ * and text that is being composed will be rendered in its own UI.
+ */
+#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
+
+/**
+ * \brief A variable controlling whether the home indicator bar on iPhone X
+ * should be hidden.
+ *
+ * This variable can be set to the following values:
+ * "0" - The indicator bar is not hidden (default for windowed applications)
+ * "1" - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications)
+ * "2" - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action (default for fullscreen applications)
+ */
+#define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR"
+
+/**
+ * \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable joystick & gamecontroller input events when the
+ * application is in the background.
+ * "1" - Enable joystick & gamecontroller input events when the
+ * application is in the background.
+ *
+ * The default value is "0". This hint may be set at any time.
+ */
+#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
+
+/**
+ * \brief A variable controlling whether the HIDAPI joystick drivers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI drivers are not used
+ * "1" - HIDAPI drivers are used (the default)
+ *
+ * This variable is the default for all drivers, but can be overridden by the hints for specific drivers below.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
+
+ /**
+ * \brief A variable controlling whether Switch Joy-Cons should be treated the same as Switch Pro Controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - basic Joy-Con support with no analog input (the default)
+ * "1" - Joy-Cons treated as half full Pro Controllers with analog inputs and sensors
+ *
+ * This does not combine Joy-Cons into a single controller. That's up to the user.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS"
+
+ /**
+ * \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_LUNA "SDL_JOYSTICK_HIDAPI_LUNA"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4"
+
+/**
+ * \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - extended reports are not enabled (the default)
+ * "1" - extended reports
+ *
+ * Extended input reports allow rumble on Bluetooth PS4 controllers, but
+ * break DirectInput handling for applications that don't use SDL.
+ *
+ * Once extended reports are enabled, they can not be disabled without
+ * power cycling the controller.
+ *
+ * For compatibility with applications written for versions of SDL prior
+ * to the introduction of PS5 controller support, this value will also
+ * control the state of extended reports on PS5 controllers when the
+ * SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE hint is not explicitly set.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS5 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5"
+
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller.
+ *
+ * This variable can be set to the following values:
+ * "0" - player LEDs are not enabled
+ * "1" - player LEDs are enabled (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED"
+
+/**
+ * \brief A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - extended reports are not enabled (the default)
+ * "1" - extended reports
+ *
+ * Extended input reports allow rumble on Bluetooth PS5 controllers, but
+ * break DirectInput handling for applications that don't use SDL.
+ *
+ * Once extended reports are enabled, they can not be disabled without
+ * power cycling the controller.
+ *
+ * For compatibility with applications written for versions of SDL prior
+ * to the introduction of PS5 controller support, this value defaults to
+ * the value of SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Steam Controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH"
+
+/**
+ * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch controller is opened
+ *
+ * This variable can be set to the following values:
+ * "0" - home button LED is left off
+ * "1" - home button LED is turned on (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
+
+ /**
+ * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices.
+ *
+ * This variable can be set to the following values:
+ * "0" - RAWINPUT drivers are not used
+ * "1" - RAWINPUT drivers are used (the default)
+ *
+ */
+#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT"
+
+ /**
+ * \brief A variable controlling whether the RAWINPUT driver should pull correlated data from XInput.
+ *
+ * This variable can be set to the following values:
+ * "0" - RAWINPUT driver will only use data from raw input APIs
+ * "1" - RAWINPUT driver will also pull data from XInput, providing
+ * better trigger axes, guide button presses, and rumble support
+ * for Xbox controllers
+ *
+ * The default is "1". This hint applies to any joysticks opened after setting the hint.
+ */
+#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT"
+
+ /**
+ * \brief A variable controlling whether a separate thread should be used
+ * for handling joystick detection and raw input messages on Windows
+ *
+ * This variable can be set to the following values:
+ * "0" - A separate thread is not used (the default)
+ * "1" - A separate thread is used for handling raw input messages
+ *
+ */
+#define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
+
+/**
+ * \brief Determines whether SDL enforces that DRM master is required in order
+ * to initialize the KMSDRM video backend.
+ *
+ * The DRM subsystem has a concept of a "DRM master" which is a DRM client that
+ * has the ability to set planes, set cursor, etc. When SDL is DRM master, it
+ * can draw to the screen using the SDL rendering APIs. Without DRM master, SDL
+ * is still able to process input and query attributes of attached displays,
+ * but it cannot change display state or draw to the screen directly.
+ *
+ * In some cases, it can be useful to have the KMSDRM backend even if it cannot
+ * be used for rendering. An app may want to use SDL for input processing while
+ * using another rendering API (such as an MMAL overlay on Raspberry Pi) or
+ * using its own code to render to DRM overlays that SDL doesn't support.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL will allow usage of the KMSDRM backend without DRM master
+ * "1" - SDL Will require DRM master to use the KMSDRM backend (default)
+ */
+#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER"
+
+ /**
+ * \brief A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values.
+ *
+ * This variable can be set to the following values:
+ * "0" - Return unfiltered joystick axis values (the default)
+ * "1" - Return axis values with deadzones taken into account
+ */
+#define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES"
+
+/**
+* \brief When set don't force the SDL app to become a foreground process
+*
+* This hint only applies to Mac OS X.
+*
+*/
+#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP"
+
+/**
+ * \brief A variable that determines whether ctrl+click should generate a right-click event on Mac
+ *
+ * If present, holding ctrl while left clicking will generate a right click
+ * event when on Mac.
+ */
+#define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK"
+
+/**
+ * \brief A variable setting the double click radius, in pixels.
+ */
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS"
+
+/**
+ * \brief A variable setting the double click time, in milliseconds.
+ */
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME"
+
+/**
+ * \brief Allow mouse click events when clicking to focus an SDL window
+ *
+ * This variable can be set to the following values:
+ * "0" - Ignore mouse clicks that activate a window
+ * "1" - Generate events for mouse clicks that activate a window
+ *
+ * By default SDL will ignore mouse clicks that activate a window
+ */
+#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH"
+
+/**
+ * \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode
+ */
+#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE"
+
+/**
+ * \brief A variable controlling whether relative mouse mode is implemented using mouse warping
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse mode uses raw input
+ * "1" - Relative mouse mode uses mouse warping
+ *
+ * By default SDL will use raw input for relative mouse mode
+ */
+#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP"
+
+/**
+ * \brief A variable controlling whether relative mouse motion is affected by renderer scaling
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative motion is unaffected by DPI or renderer's logical size
+ * "1" - Relative motion is scaled according to DPI scaling and logical size
+ *
+ * By default relative mouse deltas are affected by DPI and renderer scaling
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SCALING "SDL_MOUSE_RELATIVE_SCALING"
+
+/**
+ * \brief A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE"
+
+/**
+ * \brief A variable controlling whether mouse events should generate synthetic touch events
+ *
+ * This variable can be set to the following values:
+ * "0" - Mouse events will not generate touch events (default for desktop platforms)
+ * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS)
+ */
+#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS"
+
+/**
+ * \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
+ *
+ * This hint only applies to Unix-like platforms, and should set before
+ * any calls to SDL_Init()
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will install a SIGINT and SIGTERM handler, and when it
+ * catches a signal, convert it into an SDL_QUIT event.
+ * "1" - SDL will not install a signal handler at all.
+ */
+#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS"
+
+/**
+ * \brief A variable controlling what driver to use for OpenGL ES contexts.
+ *
+ * On some platforms, currently Windows and X11, OpenGL drivers may support
+ * creating contexts with an OpenGL ES profile. By default SDL uses these
+ * profiles, when available, otherwise it attempts to load an OpenGL ES
+ * library, e.g. that provided by the ANGLE project. This variable controls
+ * whether SDL follows this default behaviour or will always load an
+ * OpenGL ES library.
+ *
+ * Circumstances where this is useful include
+ * - Testing an app with a particular OpenGL ES implementation, e.g ANGLE,
+ * or emulator, e.g. those from ARM, Imagination or Qualcomm.
+ * - Resolving OpenGL ES function addresses at link time by linking with
+ * the OpenGL ES library instead of querying them at run time with
+ * SDL_GL_GetProcAddress().
+ *
+ * Caution: for an application to work with the default behaviour across
+ * different OpenGL drivers it must query the OpenGL ES function
+ * addresses at run time using SDL_GL_GetProcAddress().
+ *
+ * This variable is ignored on most platforms because OpenGL ES is native
+ * or not supported.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use ES profile of OpenGL, if available. (Default when not set.)
+ * "1" - Load OpenGL ES library using the default library names.
+ *
+ */
+#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER"
+
+/**
+ * \brief A variable controlling which orientations are allowed on iOS/Android.
+ *
+ * In some circumstances it is necessary to be able to explicitly control
+ * which UI orientations are allowed.
+ *
+ * This variable is a space delimited list of the following values:
+ * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
+ */
+#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
+
+/**
+ * \brief Override for SDL_GetPreferredLocales()
+ *
+ * If set, this will be favored over anything the OS might report for the
+ * user's preferred locales. Changing this hint at runtime will not generate
+ * a SDL_LOCALECHANGED event (but if you can change the hint, you can push
+ * your own event, if you want).
+ *
+ * The format of this hint is a comma-separated list of language and locale,
+ * combined with an underscore, as is a common format: "en_GB". Locale is
+ * optional: "en". So you might have a list like this: "en_GB,jp,es_PT"
+ */
+#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES"
+
+/**
+ * \brief A variable describing the content orientation on QtWayland-based platforms.
+ *
+ * On QtWayland platforms, windows are rotated client-side to allow for custom
+ * transitions. In order to correctly position overlays (e.g. volume bar) and
+ * gestures (e.g. events view, close/minimize gestures), the system needs to
+ * know in which orientation the application is currently drawing its contents.
+ *
+ * This does not cause the window to be rotated or resized, the application
+ * needs to take care of drawing the content in the right orientation (the
+ * framebuffer is always in portrait mode).
+ *
+ * This variable can be one of the following values:
+ * "primary" (default), "portrait", "landscape", "inverted-portrait", "inverted-landscape"
+ */
+#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION"
+
+/**
+ * \brief Flags to set on QtWayland windows to integrate with the native window manager.
+ *
+ * On QtWayland platforms, this hint controls the flags to set on the windows.
+ * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures.
+ *
+ * This variable is a space-separated list of the following values (empty = no flags):
+ * "OverridesSystemGestures", "StaysOnTop", "BypassWindowManager"
+ */
+#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS"
+
+/**
+ * \brief A variable controlling whether the 2D render API is compatible or efficient.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - Don't use batching to make rendering more efficient.
+ * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls.
+ *
+ * Up to SDL 2.0.9, the render API would draw immediately when requested. Now
+ * it batches up draw requests and sends them all to the GPU only when forced
+ * to (during SDL_RenderPresent, when changing render targets, by updating a
+ * texture that the batch needs, etc). This is significantly more efficient,
+ * but it can cause problems for apps that expect to render on top of the
+ * render API's output. As such, SDL will disable batching if a specific
+ * render backend is requested (since this might indicate that the app is
+ * planning to use the underlying graphics API directly). This hint can
+ * be used to explicitly request batching in this instance. It is a contract
+ * that you will either never use the underlying graphics API directly, or
+ * if you do, you will call SDL_RenderFlush() before you do so any current
+ * batch goes to the GPU before your work begins. Not following this contract
+ * will result in undefined behavior.
+ */
+#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING"
+
+/**
+ * \brief A variable controlling whether to enable Direct3D 11+'s Debug Layer.
+ *
+ * This variable does not have any effect on the Direct3D 9 based renderer.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable Debug Layer use
+ * "1" - Enable Debug Layer use
+ *
+ * By default, SDL does not use Direct3D Debug Layer.
+ */
+#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG"
+
+/**
+ * \brief A variable controlling whether the Direct3D device is initialized for thread-safe operations.
+ *
+ * This variable can be set to the following values:
+ * "0" - Thread-safety is not enabled (faster)
+ * "1" - Thread-safety is enabled
+ *
+ * By default the Direct3D device is created with thread-safety disabled.
+ */
+#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE"
+
+/**
+ * \brief A variable specifying which render driver to use.
+ *
+ * If the application doesn't pick a specific renderer to use, this variable
+ * specifies the name of the preferred renderer. If the preferred renderer
+ * can't be initialized, the normal default renderer is used.
+ *
+ * This variable is case insensitive and can be set to the following values:
+ * "direct3d"
+ * "opengl"
+ * "opengles2"
+ * "opengles"
+ * "metal"
+ * "software"
+ *
+ * The default varies by platform, but it's the first one in the list that
+ * is available on the current platform.
+ */
+#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER"
+
+/**
+ * \brief A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
+ *
+ * This variable can be set to the following values:
+ * "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen
+ * "1" or "overscan" - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
+ *
+ * By default letterbox is used
+ */
+#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE "SDL_RENDER_LOGICAL_SIZE_MODE"
+
+/**
+ * \brief A variable controlling whether the OpenGL render driver uses shaders if they are available.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable shaders
+ * "1" - Enable shaders
+ *
+ * By default shaders are used if OpenGL supports them.
+ */
+#define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS"
+
+/**
+ * \brief A variable controlling the scaling quality
+ *
+ * This variable can be set to the following values:
+ * "0" or "nearest" - Nearest pixel sampling
+ * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D)
+ * "2" or "best" - Currently this is the same as "linear"
+ *
+ * By default nearest pixel sampling is used
+ */
+#define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY"
+
+/**
+ * \brief A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable vsync
+ * "1" - Enable vsync
+ *
+ * By default SDL does not sync screen surface updates with vertical refresh.
+ */
+#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
+
+ /**
+ * \brief A variable to control whether the return key on the soft keyboard
+ * should hide the soft keyboard on Android and iOS.
+ *
+ * The variable can be set to the following values:
+ * "0" - The return key will be handled as a key event. This is the behaviour of SDL <= 2.0.3. (default)
+ * "1" - The return key will hide the keyboard.
+ *
+ * The value of this hint is used at runtime, so it can be changed at any time.
+ */
+#define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME"
+
+/**
+ * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI
+ *
+ * Also known as Z-order. The variable can take a negative or positive value.
+ * The default is 10000.
+ */
+#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER"
+
+/**
+ * \brief Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime.
+ *
+ * On some platforms, like Linux, a realtime priority thread may be subject to restrictions
+ * that require special handling by the application. This hint exists to let SDL know that
+ * the app is prepared to handle said restrictions.
+ *
+ * On Linux, SDL will apply the following configuration to any thread that becomes realtime:
+ * * The SCHED_RESET_ON_FORK bit will be set on the scheduling policy,
+ * * An RLIMIT_RTTIME budget will be configured to the rtkit specified limit.
+ * * Exceeding this limit will result in the kernel sending SIGKILL to the app,
+ * * Refer to the man pages for more information.
+ *
+ * This variable can be set to the following values:
+ * "0" - default platform specific behaviour
+ * "1" - Force SDL_THREAD_PRIORITY_TIME_CRITICAL to a realtime scheduling policy
+ */
+#define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL"
+
+/**
+* \brief A string specifying additional information to use with SDL_SetThreadPriority.
+*
+* By default SDL_SetThreadPriority will make appropriate system changes in order to
+* apply a thread priority. For example on systems using pthreads the scheduler policy
+* is changed automatically to a policy that works well with a given priority.
+* Code which has specific requirements can override SDL's default behavior with this hint.
+*
+* pthread hint values are "current", "other", "fifo" and "rr".
+* Currently no other platform hint values are defined but may be in the future.
+*
+* \note On Linux, the kernel may send SIGKILL to realtime tasks which exceed the distro
+* configured execution budget for rtkit. This budget can be queried through RLIMIT_RTTIME
+* after calling SDL_SetThreadPriority().
+*/
+#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY"
+
+/**
+* \brief A string specifying SDL's threads stack size in bytes or "0" for the backend's default size
+*
+* Use this hint in case you need to set SDL's threads stack size to other than the default.
+* This is specially useful if you build SDL against a non glibc libc library (such as musl) which
+* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
+* Support for this hint is currently available only in the pthread, Windows, and PSP backend.
+*
+* Instead of this hint, in 2.0.9 and later, you can use
+* SDL_CreateThreadWithStackSize(). This hint only works with the classic
+* SDL_CreateThread().
+*/
+#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE"
+
+/**
+ * \brief A variable that controls the timer resolution, in milliseconds.
+ *
+ * The higher resolution the timer, the more frequently the CPU services
+ * timer interrupts, and the more precise delays are, but this takes up
+ * power and CPU time. This hint is only used on Windows.
+ *
+ * See this blog post for more information:
+ * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
+ *
+ * If this variable is set to "0", the system timer resolution is not set.
+ *
+ * The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"
+
+/**
+ * \brief A variable controlling whether touch events should generate synthetic mouse events
+ *
+ * This variable can be set to the following values:
+ * "0" - Touch events will not generate mouse events
+ * "1" - Touch events will generate mouse events
+ *
+ * By default SDL will generate mouse events for touch events
+ */
+#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS"
+
+/**
+ * \brief A variable controlling whether the Android / tvOS remotes
+ * should be listed as joystick devices, instead of sending keyboard events.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remotes send enter/escape/arrow key events
+ * "1" - Remotes are available as 2 axis, 2 button joysticks (the default).
+ */
+#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK"
+
+/**
+ * \brief A variable controlling whether the screensaver is enabled.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable screensaver
+ * "1" - Enable screensaver
+ *
+ * By default SDL will disable the screensaver.
+ */
+#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER"
+
+/**
+ * \brief Tell the video driver that we only want a double buffer.
+ *
+ * By default, most lowlevel 2D APIs will use a triple buffer scheme that
+ * wastes no CPU time on waiting for vsync after issuing a flip, but
+ * introduces a frame of latency. On the other hand, using a double buffer
+ * scheme instead is recommended for cases where low latency is an important
+ * factor because we save a whole frame of latency.
+ * We do so by waiting for vsync immediately after issuing a flip, usually just
+ * after eglSwapBuffers call in the backend's *_SwapWindow function.
+ *
+ * Since it's driver-specific, it's only supported where possible and
+ * implemented. Currently supported the following drivers:
+ *
+ * - KMSDRM (kmsdrm)
+ * - Raspberry Pi (raspberrypi)
+ */
+#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER"
+
+/**
+ * \brief A variable controlling whether the graphics context is externally managed.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL will manage graphics contexts that are attached to windows.
+ * "1" - Disable graphics context management on windows.
+ *
+ * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the
+ * context will be automatically saved and restored when pausing the application. Additionally, some
+ * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this
+ * behavior, which is desireable when the application manages the graphics context, such as
+ * an externally managed OpenGL context or attaching a Vulkan surface to the window.
+ */
+#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT"
+
+/**
+ * \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS)
+ */
+#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
+
+/**
+ * \brief A variable that dictates policy for fullscreen Spaces on Mac OS X.
+ *
+ * This hint only applies to Mac OS X.
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable Spaces support (FULLSCREEN_DESKTOP won't use them and
+ * SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen"
+ * button on their titlebars).
+ * "1" - Enable Spaces support (FULLSCREEN_DESKTOP will use them and
+ * SDL_WINDOW_RESIZABLE windows will offer the "fullscreen"
+ * button on their titlebars).
+ *
+ * The default value is "1". Spaces are disabled regardless of this hint if
+ * the OS isn't at least Mac OS X Lion (10.7). This hint must be set before
+ * any windows are created.
+ */
+#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES"
+
+/**
+ * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false.
+ * \warning Before SDL 2.0.14, this defaulted to true! In 2.0.14, we're
+ * seeing if "true" causes more problems than it solves in modern times.
+ *
+ */
+#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
+
+/**
+ * \brief A variable controlling whether the libdecor Wayland backend is allowed to be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - libdecor use is disabled.
+ * "1" - libdecor use is enabled (default).
+ *
+ * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
+
+/**
+* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
+*
+* If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has
+* SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly
+* created SDL_Window:
+*
+* 1. Its pixel format will be set to the same pixel format as this SDL_Window. This is
+* needed for example when sharing an OpenGL context across multiple windows.
+*
+* 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for
+* OpenGL rendering.
+*
+* This variable can be set to the following values:
+* The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should
+* share a pixel format with.
+*/
+#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"
+
+/**
+* \brief A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries
+*
+* SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It
+* can use two different sets of binaries, those compiled by the user from source
+* or those provided by the Chrome browser. In the later case, these binaries require
+* that SDL loads a DLL providing the shader compiler.
+*
+* This variable can be set to the following values:
+* "d3dcompiler_46.dll" - default, best for Vista or later.
+* "d3dcompiler_43.dll" - for XP support.
+* "none" - do not load any library, useful if you compiled ANGLE from source and included the compiler in your binaries.
+*
+*/
+#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
+
+/**
+ * \brief A variable controlling whether X11 should use GLX or EGL by default
+ *
+ * This variable can be set to the following values:
+ * "0" - Use GLX
+ * "1" - Use EGL
+ *
+ * By default SDL will use GLX when both are present.
+ */
+#define SDL_HINT_VIDEO_X11_FORCE_EGL "SDL_VIDEO_X11_FORCE_EGL"
+
+/**
+ * \brief A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable _NET_WM_BYPASS_COMPOSITOR
+ * "1" - Enable _NET_WM_BYPASS_COMPOSITOR
+ *
+ * By default SDL will use _NET_WM_BYPASS_COMPOSITOR
+ *
+ */
+#define SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR"
+
+/**
+ * \brief A variable controlling whether the X11 _NET_WM_PING protocol should be supported.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable _NET_WM_PING
+ * "1" - Enable _NET_WM_PING
+ *
+ * By default SDL will use _NET_WM_PING, but for applications that know they
+ * will not always be able to respond to ping requests in a timely manner they can
+ * turn it off to avoid the window manager thinking the app is hung.
+ * The hint is checked in CreateWindow.
+ */
+#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING"
+
+/**
+ * \brief A variable forcing the visual ID chosen for new X11 windows
+ *
+ */
+#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID"
+
+/**
+ * \brief A variable controlling whether the X11 Xinerama extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable Xinerama
+ * "1" - Enable Xinerama
+ *
+ * By default SDL will use Xinerama if it is available.
+ */
+#define SDL_HINT_VIDEO_X11_XINERAMA "SDL_VIDEO_X11_XINERAMA"
+
+/**
+ * \brief A variable controlling whether the X11 XRandR extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable XRandR
+ * "1" - Enable XRandR
+ *
+ * By default SDL will not use XRandR because of window manager issues.
+ */
+#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR"
+
+/**
+ * \brief A variable controlling whether the X11 VidMode extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable XVidMode
+ * "1" - Enable XVidMode
+ *
+ * By default SDL will use XVidMode if it is available.
+ */
+#define SDL_HINT_VIDEO_X11_XVIDMODE "SDL_VIDEO_X11_XVIDMODE"
+
+/**
+ * \brief Controls how the fact chunk affects the loading of a WAVE file.
+ *
+ * The fact chunk stores information about the number of samples of a WAVE
+ * file. The Standards Update from Microsoft notes that this value can be used
+ * to 'determine the length of the data in seconds'. This is especially useful
+ * for compressed formats (for which this is a mandatory chunk) if they produce
+ * multiple sample frames per block and truncating the block is not allowed.
+ * The fact chunk can exactly specify how many sample frames there should be
+ * in this case.
+ *
+ * Unfortunately, most application seem to ignore the fact chunk and so SDL
+ * ignores it by default as well.
+ *
+ * This variable can be set to the following values:
+ *
+ * "truncate" - Use the number of samples to truncate the wave data if
+ * the fact chunk is present and valid
+ * "strict" - Like "truncate", but raise an error if the fact chunk
+ * is invalid, not present for non-PCM formats, or if the
+ * data chunk doesn't have that many samples
+ * "ignorezero" - Like "truncate", but ignore fact chunk if the number of
+ * samples is zero
+ * "ignore" - Ignore fact chunk entirely (default)
+ */
+#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK"
+
+/**
+ * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file.
+ *
+ * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE
+ * file) is not always reliable. In case the size is wrong, it's possible to
+ * just ignore it and step through the chunks until a fixed limit is reached.
+ *
+ * Note that files that have trailing data unrelated to the WAVE file or
+ * corrupt files may slow down the loading process without a reliable boundary.
+ * By default, SDL stops after 10000 chunks to prevent wasting time. Use the
+ * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value.
+ *
+ * This variable can be set to the following values:
+ *
+ * "force" - Always use the RIFF chunk size as a boundary for the chunk search
+ * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default)
+ * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB
+ * "maximum" - Search for chunks until the end of file (not recommended)
+ */
+#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE"
+
+/**
+ * \brief Controls how a truncated WAVE file is handled.
+ *
+ * A WAVE file is considered truncated if any of the chunks are incomplete or
+ * the data chunk size is not a multiple of the block size. By default, SDL
+ * decodes until the first incomplete block, as most applications seem to do.
+ *
+ * This variable can be set to the following values:
+ *
+ * "verystrict" - Raise an error if the file is truncated
+ * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored
+ * "dropframe" - Decode until the first incomplete sample frame
+ * "dropblock" - Decode until the first incomplete block (default)
+ */
+#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION"
+
+/**
+ * \brief Tell SDL not to name threads on Windows with the 0x406D1388 Exception.
+ * The 0x406D1388 Exception is a trick used to inform Visual Studio of a
+ * thread's name, but it tends to cause problems with other debuggers,
+ * and the .NET runtime. Note that SDL 2.0.6 and later will still use
+ * the (safer) SetThreadDescription API, introduced in the Windows 10
+ * Creators Update, if available.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will raise the 0x406D1388 Exception to name threads.
+ * This is the default behavior of SDL <= 2.0.4.
+ * "1" - SDL will not raise this exception, and threads will be unnamed. (default)
+ * This is necessary with .NET languages or debuggers that aren't Visual Studio.
+ */
+#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING"
+
+/**
+ * \brief A variable controlling whether the windows message loop is processed by SDL
+ *
+ * This variable can be set to the following values:
+ * "0" - The window message loop is not run
+ * "1" - The window message loop is processed in SDL_PumpEvents()
+ *
+ * By default SDL will process the windows message loop
+ */
+#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP"
+
+/**
+ * \brief Force SDL to use Critical Sections for mutexes on Windows.
+ * On Windows 7 and newer, Slim Reader/Writer Locks are available.
+ * They offer better performance, allocate no kernel ressources and
+ * use less memory. SDL will fall back to Critical Sections on older
+ * OS versions or if forced to by this hint.
+ * This also affects Condition Variables. When SRW mutexes are used,
+ * SDL will use Windows Condition Variables as well. Else, a generic
+ * SDL_cond implementation will be used that works with all mutexes.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use SRW Locks when available. If not, fall back to Critical Sections. (default)
+ * "1" - Force the use of Critical Sections in all cases.
+ *
+ */
+#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS"
+
+/**
+ * \brief Force SDL to use Kernel Semaphores on Windows.
+ * Kernel Semaphores are inter-process and require a context
+ * switch on every interaction. On Windows 8 and newer, the
+ * WaitOnAddress API is available. Using that and atomics to
+ * implement semaphores increases performance.
+ * SDL will fall back to Kernel Objects on older OS versions
+ * or if forced to by this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use Atomics and WaitOnAddress API when available. If not, fall back to Kernel Objects. (default)
+ * "1" - Force the use of Kernel Objects in all cases.
+ *
+ */
+#define SDL_HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL"
+
+/**
+ * \brief A variable to specify custom icon resource id from RC file on Windows platform
+ */
+#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON"
+#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL"
+
+/**
+ * \brief Tell SDL not to generate window-close events for Alt+F4 on Windows.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will generate a window-close event when it sees Alt+F4.
+ * "1" - SDL will only do normal key handling for Alt+F4.
+ */
+#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
+
+/**
+ * \brief Use the D3D9Ex API introduced in Windows Vista, instead of normal D3D9.
+ * Direct3D 9Ex contains changes to state management that can eliminate device
+ * loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may require
+ * some changes to your application to cope with the new behavior, so this
+ * is disabled by default.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * For more information on Direct3D 9Ex, see:
+ * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/graphics-apis-in-windows-vista#direct3d-9ex
+ * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/direct3d-9ex-improvements
+ *
+ * This variable can be set to the following values:
+ * "0" - Use the original Direct3D 9 API (default)
+ * "1" - Use the Direct3D 9Ex API on Vista and later (and fall back if D3D9Ex is unavailable)
+ *
+ */
+#define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX"
+
+/**
+ * \brief A variable controlling whether the window frame and title bar are interactive when the cursor is hidden
+ *
+ * This variable can be set to the following values:
+ * "0" - The window frame is not interactive when the cursor is hidden (no move, resize, etc)
+ * "1" - The window frame is interactive when the cursor is hidden
+ *
+ * By default SDL will allow interaction with the window frame when the cursor is hidden
+ */
+#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"
+
+/** \brief Allows back-button-press events on Windows Phone to be marked as handled
+ *
+ * Windows Phone devices typically feature a Back button. When pressed,
+ * the OS will emit back-button-press events, which apps are expected to
+ * handle in an appropriate manner. If apps do not explicitly mark these
+ * events as 'Handled', then the OS will invoke its default behavior for
+ * unhandled back-button-press events, which on Windows Phone 8 and 8.1 is to
+ * terminate the app (and attempt to switch to the previous app, or to the
+ * device's home screen).
+ *
+ * Setting the SDL_HINT_WINRT_HANDLE_BACK_BUTTON hint to "1" will cause SDL
+ * to mark back-button-press events as Handled, if and when one is sent to
+ * the app.
+ *
+ * Internally, Windows Phone sends back button events as parameters to
+ * special back-button-press callback functions. Apps that need to respond
+ * to back-button-press events are expected to register one or more
+ * callback functions for such, shortly after being launched (during the
+ * app's initialization phase). After the back button is pressed, the OS
+ * will invoke these callbacks. If the app's callback(s) do not explicitly
+ * mark the event as handled by the time they return, or if the app never
+ * registers one of these callback, the OS will consider the event
+ * un-handled, and it will apply its default back button behavior (terminate
+ * the app).
+ *
+ * SDL registers its own back-button-press callback with the Windows Phone
+ * OS. This callback will emit a pair of SDL key-press events (SDL_KEYDOWN
+ * and SDL_KEYUP), each with a scancode of SDL_SCANCODE_AC_BACK, after which
+ * it will check the contents of the hint, SDL_HINT_WINRT_HANDLE_BACK_BUTTON.
+ * If the hint's value is set to "1", the back button event's Handled
+ * property will get set to 'true'. If the hint's value is set to something
+ * else, or if it is unset, SDL will leave the event's Handled property
+ * alone. (By default, the OS sets this property to 'false', to note.)
+ *
+ * SDL apps can either set SDL_HINT_WINRT_HANDLE_BACK_BUTTON well before a
+ * back button is pressed, or can set it in direct-response to a back button
+ * being pressed.
+ *
+ * In order to get notified when a back button is pressed, SDL apps should
+ * register a callback function with SDL_AddEventWatch(), and have it listen
+ * for SDL_KEYDOWN events that have a scancode of SDL_SCANCODE_AC_BACK.
+ * (Alternatively, SDL_KEYUP events can be listened-for. Listening for
+ * either event type is suitable.) Any value of SDL_HINT_WINRT_HANDLE_BACK_BUTTON
+ * set by such a callback, will be applied to the OS' current
+ * back-button-press event.
+ *
+ * More details on back button behavior in Windows Phone apps can be found
+ * at the following page, on Microsoft's developer site:
+ * http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj247550(v=vs.105).aspx
+ */
+#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON"
+
+/** \brief Label text for a WinRT app's privacy policy link
+ *
+ * Network-enabled WinRT apps must include a privacy policy. On Windows 8, 8.1, and RT,
+ * Microsoft mandates that this policy be available via the Windows Settings charm.
+ * SDL provides code to add a link there, with its label text being set via the
+ * optional hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL.
+ *
+ * Please note that a privacy policy's contents are not set via this hint. A separate
+ * hint, SDL_HINT_WINRT_PRIVACY_POLICY_URL, is used to link to the actual text of the
+ * policy.
+ *
+ * The contents of this hint should be encoded as a UTF8 string.
+ *
+ * The default value is "Privacy Policy". This hint should only be set during app
+ * initialization, preferably before any calls to SDL_Init().
+ *
+ * For additional information on linking to a privacy policy, see the documentation for
+ * SDL_HINT_WINRT_PRIVACY_POLICY_URL.
+ */
+#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL"
+
+/**
+ * \brief A URL to a WinRT app's privacy policy
+ *
+ * All network-enabled WinRT apps must make a privacy policy available to its
+ * users. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be
+ * be available in the Windows Settings charm, as accessed from within the app.
+ * SDL provides code to add a URL-based link there, which can point to the app's
+ * privacy policy.
+ *
+ * To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL
+ * before calling any SDL_Init() functions. The contents of the hint should
+ * be a valid URL. For example, "http://www.example.com".
+ *
+ * The default value is "", which will prevent SDL from adding a privacy policy
+ * link to the Settings charm. This hint should only be set during app init.
+ *
+ * The label text of an app's "Privacy Policy" link may be customized via another
+ * hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL.
+ *
+ * Please note that on Windows Phone, Microsoft does not provide standard UI
+ * for displaying a privacy policy link, and as such, SDL_HINT_WINRT_PRIVACY_POLICY_URL
+ * will not get used on that platform. Network-enabled phone apps should display
+ * their privacy policy through some other, in-app means.
+ */
+#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL"
+
+/**
+ * \brief Mark X11 windows as override-redirect.
+ *
+ * If set, this _might_ increase framerate at the expense of the desktop
+ * not working as expected. Override-redirect windows aren't noticed by the
+ * window manager at all.
+ *
+ * You should probably only use this for fullscreen windows, and you probably
+ * shouldn't even use it for that. But it's here if you want to try!
+ */
+#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT"
+
+/**
+ * \brief A variable that lets you disable the detection and use of Xinput gamepad devices
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable XInput detection (only uses direct input)
+ * "1" - Enable XInput detection (the default)
+ */
+#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED"
+
+/**
+ * \brief A variable that causes SDL to use the old axis and button mapping for XInput devices.
+ *
+ * This hint is for backwards compatibility only and will be removed in SDL 2.1
+ *
+ * The default value is "0". This hint must be set before SDL_Init()
+ */
+#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING"
+
+/**
+ * \brief A variable that causes SDL to not ignore audio "monitors"
+ *
+ * This is currently only used for PulseAudio and ignored elsewhere.
+ *
+ * By default, SDL ignores audio devices that aren't associated with physical
+ * hardware. Changing this hint to "1" will expose anything SDL sees that
+ * appears to be an audio source or sink. This will add "devices" to the list
+ * that the user probably doesn't want or need, but it can be useful in
+ * scenarios where you want to hook up SDL to some sort of virtual device,
+ * etc.
+ *
+ * The default value is "0". This hint must be set before SDL_Init().
+ *
+ * This hint is available since SDL 2.0.16. Before then, virtual devices are
+ * always ignored.
+ */
+#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS"
+
+
+/**
+ * \brief An enumeration of hint priorities
+ */
+typedef enum
+{
+ SDL_HINT_DEFAULT,
+ SDL_HINT_NORMAL,
+ SDL_HINT_OVERRIDE
+} SDL_HintPriority;
+
+
+/**
+ * Set a hint with a specific priority.
+ *
+ * The priority controls the behavior when setting a hint that already has a
+ * value. Hints will replace existing hints of their priority and lower.
+ * Environment variables are considered to have override priority.
+ *
+ * \param name the hint to set
+ * \param value the value of the hint variable
+ * \param priority the SDL_HintPriority level for the hint
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name,
+ const char *value,
+ SDL_HintPriority priority);
+
+/**
+ * Set a hint with normal priority.
+ *
+ * Hints will not be set if there is an existing override hint or environment
+ * variable that takes precedence. You can use SDL_SetHintWithPriority() to
+ * set the hint with override priority instead.
+ *
+ * \param name the hint to set
+ * \param value the value of the hint variable
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHintWithPriority
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
+ const char *value);
+
+/**
+ * Get the value of a hint.
+ *
+ * \param name the hint to query
+ * \returns the string value of a hint or NULL if the hint isn't set.
+ *
+ * \sa SDL_SetHint
+ * \sa SDL_SetHintWithPriority
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
+
+/**
+ * Get the boolean value of a hint variable.
+ *
+ * \param name the name of the hint to get the boolean value from
+ * \param default_value the value to return if the hint does not exist
+ * \returns the boolean value of a hint or the provided default value if the
+ * hint does not exist.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value);
+
+/**
+ * Type definition of the hint callback function.
+ *
+ * \param userdata what was passed as `userdata` to SDL_AddHintCallback()
+ * \param name what was passed as `name` to SDL_AddHintCallback()
+ * \param oldValue the previous hint value
+ * \param newValue the new value hint is to be set to
+ */
+typedef void (SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
+
+/**
+ * Add a function to watch a particular hint.
+ *
+ * \param name the hint to watch
+ * \param callback An SDL_HintCallback function that will be called when the
+ * hint value changes
+ * \param userdata a pointer to pass to the callback function
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DelHintCallback
+ */
+extern DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+/**
+ * Remove a function watching a particular hint.
+ *
+ * \param name the hint being watched
+ * \param callback An SDL_HintCallback function that will be called when the
+ * hint value changes
+ * \param userdata a pointer being passed to the callback function
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AddHintCallback
+ */
+extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+/**
+ * Clear all hints.
+ *
+ * This function is automatically called during SDL_Quit().
+ */
+extern DECLSPEC void SDLCALL SDL_ClearHints(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_hints_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_joystick.h b/Client/ThirdParty/SDL2/include/SDL_joystick.h
new file mode 100644
index 0000000..8be4b73
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_joystick.h
@@ -0,0 +1,821 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_joystick.h
+ *
+ * Include file for SDL joystick event handling
+ *
+ * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks(), with the exact joystick
+ * behind a device_index changing as joysticks are plugged and unplugged.
+ *
+ * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
+ * then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in.
+ *
+ * The term "player_index" is the number assigned to a player on a specific
+ * controller. For XInput controllers this returns the XInput user index.
+ * Many joysticks will not be able to supply this information.
+ *
+ * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of
+ * the device (a X360 wired controller for example). This identifier is platform dependent.
+ */
+
+#ifndef SDL_joystick_h_
+#define SDL_joystick_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_joystick.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system
+ * for joysticks, and load appropriate drivers.
+ *
+ * If you would like to receive joystick updates while the application
+ * is in the background, you should set the following hint before calling
+ * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+ */
+
+/**
+ * The joystick structure used to identify an SDL joystick
+ */
+struct _SDL_Joystick;
+typedef struct _SDL_Joystick SDL_Joystick;
+
+/* A structure that encodes the stable unique id for a joystick device */
+typedef struct {
+ Uint8 data[16];
+} SDL_JoystickGUID;
+
+/**
+ * This is a unique ID for a joystick for the time it is connected to the system,
+ * and is never reused for the lifetime of the application. If the joystick is
+ * disconnected and reconnected, it will get a new ID.
+ *
+ * The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
+ */
+typedef Sint32 SDL_JoystickID;
+
+typedef enum
+{
+ SDL_JOYSTICK_TYPE_UNKNOWN,
+ SDL_JOYSTICK_TYPE_GAMECONTROLLER,
+ SDL_JOYSTICK_TYPE_WHEEL,
+ SDL_JOYSTICK_TYPE_ARCADE_STICK,
+ SDL_JOYSTICK_TYPE_FLIGHT_STICK,
+ SDL_JOYSTICK_TYPE_DANCE_PAD,
+ SDL_JOYSTICK_TYPE_GUITAR,
+ SDL_JOYSTICK_TYPE_DRUM_KIT,
+ SDL_JOYSTICK_TYPE_ARCADE_PAD,
+ SDL_JOYSTICK_TYPE_THROTTLE
+} SDL_JoystickType;
+
+typedef enum
+{
+ SDL_JOYSTICK_POWER_UNKNOWN = -1,
+ SDL_JOYSTICK_POWER_EMPTY, /* <= 5% */
+ SDL_JOYSTICK_POWER_LOW, /* <= 20% */
+ SDL_JOYSTICK_POWER_MEDIUM, /* <= 70% */
+ SDL_JOYSTICK_POWER_FULL, /* <= 100% */
+ SDL_JOYSTICK_POWER_WIRED,
+ SDL_JOYSTICK_POWER_MAX
+} SDL_JoystickPowerLevel;
+
+/* Set max recognized G-force from accelerometer
+ See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
+ */
+#define SDL_IPHONE_MAX_GFORCE 5.0
+
+
+/* Function prototypes */
+
+/**
+ * Locking for multi-threaded access to the joystick API
+ *
+ * If you are using the joystick API or handling events from multiple threads
+ * you should use these locking functions to protect access to the joysticks.
+ *
+ * In particular, you are guaranteed that the joystick list won't change, so
+ * the API functions that take a joystick index will be valid, and joystick
+ * and game controller events will not be delivered.
+ */
+extern DECLSPEC void SDLCALL SDL_LockJoysticks(void);
+
+
+/**
+ * Unlocking for multi-threaded access to the joystick API
+ *
+ * If you are using the joystick API or handling events from multiple threads
+ * you should use these locking functions to protect access to the joysticks.
+ *
+ * In particular, you are guaranteed that the joystick list won't change, so
+ * the API functions that take a joystick index will be valid, and joystick
+ * and game controller events will not be delivered.
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void);
+
+/**
+ * Count the number of joysticks attached to the system.
+ *
+ * \returns the number of attached joysticks on success or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickName
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_NumJoysticks(void);
+
+/**
+ * Get the implementation dependent name of a joystick.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system)
+ * \returns the name of the selected joystick. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickName
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index);
+
+/**
+ * Get the player index of a joystick, or -1 if it's not available This can be
+ * called before any joysticks are opened.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetDevicePlayerIndex(int device_index);
+
+/**
+ * Get the implementation-dependent GUID for the joystick at a given device
+ * index.
+ *
+ * This function can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the GUID of the selected joystick. If called on an invalid index,
+ * this function returns a zero GUID
+ *
+ * \sa SDL_JoystickGetGUID
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetDeviceGUID(int device_index);
+
+/**
+ * Get the USB vendor ID of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the vendor ID isn't
+ * available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the USB vendor ID of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceVendor(int device_index);
+
+/**
+ * Get the USB product ID of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the product ID isn't
+ * available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the USB product ID of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProduct(int device_index);
+
+/**
+ * Get the product version of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the product version
+ * isn't available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the product version of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProductVersion(int device_index);
+
+/**
+ * Get the type of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the SDL_JoystickType of the selected joystick. If called on an
+ * invalid index, this function returns `SDL_JOYSTICK_TYPE_UNKNOWN`
+ */
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetDeviceType(int device_index);
+
+/**
+ * Get the instance ID of a joystick.
+ *
+ * This can be called before any joysticks are opened. If the index is out of
+ * range, this function will return -1.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the instance id of the selected joystick. If called on an invalid
+ * index, this function returns zero
+ */
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickGetDeviceInstanceID(int device_index);
+
+/**
+ * Open a joystick for use.
+ *
+ * The `device_index` argument refers to the N'th joystick presently
+ * recognized by SDL on the system. It is **NOT** the same as the instance ID
+ * used to identify the joystick in future events. See
+ * SDL_JoystickInstanceID() for more details about instance IDs.
+ *
+ * The joystick subsystem must be initialized before a joystick can be opened
+ * for use.
+ *
+ * \param device_index the index of the joystick to query
+ * \returns a joystick identifier or NULL if an error occurred; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickClose
+ * \sa SDL_JoystickInstanceID
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index);
+
+/**
+ * Get the SDL_Joystick associated with an instance id.
+ *
+ * \param instance_id the instance id to get the SDL_Joystick for
+ * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id);
+
+/**
+ * Get the SDL_Joystick associated with a player index.
+ *
+ * \param player_index the player index to get the SDL_Joystick for
+ * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index);
+
+/**
+ * Attach a new virtual joystick.
+ *
+ * \returns the joystick's device index, or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type,
+ int naxes,
+ int nbuttons,
+ int nhats);
+
+/**
+ * Detach a virtual joystick.
+ *
+ * \param device_index a value previously returned from
+ * SDL_JoystickAttachVirtual()
+ * \returns 0 on success, or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
+
+/**
+ * Query whether or not the joystick at a given device index is virtual.
+ *
+ * \param device_index a joystick device index.
+ * \returns SDL_TRUE if the joystick is virtual, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
+
+/**
+ * Set values on an opened, virtual-joystick's axis.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param axis the specific axis on the virtual joystick to set.
+ * \param value the new value for the specified axis.
+ * \returns 0 on success, -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value);
+
+/**
+ * Set values on an opened, virtual-joystick's button.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param button the specific button on the virtual joystick to set.
+ * \param value the new value for the specified button.
+ * \returns 0 on success, -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value);
+
+/**
+ * Set values on an opened, virtual-joystick's hat.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param hat the specific hat on the virtual joystick to set.
+ * \param value the new value for the specified hat.
+ * \returns 0 on success, -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value);
+
+/**
+ * Get the implementation dependent name of a joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the name of the selected joystick. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNameForIndex
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick *joystick);
+
+/**
+ * Get the player index of an opened joystick.
+ *
+ * For XInput controllers this returns the XInput user index. Many joysticks
+ * will not be able to supply this information.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the player index, or -1 if it's not available.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick);
+
+/**
+ * Set the player index of an opened joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \param player_index the player index to set.
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index);
+
+/**
+ * Get the implementation-dependent GUID for the joystick.
+ *
+ * This function requires an open joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the GUID of the given joystick. If called on an invalid index,
+ * this function returns a zero GUID; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick *joystick);
+
+/**
+ * Get the USB vendor ID of an opened joystick, if available.
+ *
+ * If the vendor ID isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the USB vendor ID of the selected joystick, or 0 if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetVendor(SDL_Joystick *joystick);
+
+/**
+ * Get the USB product ID of an opened joystick, if available.
+ *
+ * If the product ID isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the USB product ID of the selected joystick, or 0 if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProduct(SDL_Joystick *joystick);
+
+/**
+ * Get the product version of an opened joystick, if available.
+ *
+ * If the product version isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the product version of the selected joystick, or 0 if unavailable.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProductVersion(SDL_Joystick *joystick);
+
+/**
+ * Get the serial number of an opened joystick, if available.
+ *
+ * Returns the serial number of the joystick, or NULL if it is not available.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the serial number of the selected joystick, or NULL if
+ * unavailable.
+ */
+extern DECLSPEC const char * SDLCALL SDL_JoystickGetSerial(SDL_Joystick *joystick);
+
+/**
+ * Get the type of an opened joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the SDL_JoystickType of the selected joystick.
+ */
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetType(SDL_Joystick *joystick);
+
+/**
+ * Get an ASCII string representation for a given SDL_JoystickGUID.
+ *
+ * You should supply at least 33 bytes for pszGUID.
+ *
+ * \param guid the SDL_JoystickGUID you wish to convert to string
+ * \param pszGUID buffer in which to write the ASCII string
+ * \param cbGUID the size of pszGUID
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUID
+ * \sa SDL_JoystickGetGUIDFromString
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID);
+
+/**
+ * Convert a GUID string into a SDL_JoystickGUID structure.
+ *
+ * Performs no error checking. If this function is given a string containing
+ * an invalid GUID, the function will silently succeed, but the GUID generated
+ * will not be useful.
+ *
+ * \param pchGUID string containing an ASCII representation of a GUID
+ * \returns a SDL_JoystickGUID structure.
+ *
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUIDFromString(const char *pchGUID);
+
+/**
+ * Get the status of a specified joystick.
+ *
+ * \param joystick the joystick to query
+ * \returns SDL_TRUE if the joystick has been opened, SDL_FALSE if it has not;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickClose
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAttached(SDL_Joystick *joystick);
+
+/**
+ * Get the instance ID of an opened joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the instance ID of the specified joystick on success or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickInstanceID(SDL_Joystick *joystick);
+
+/**
+ * Get the number of general axis controls on a joystick.
+ *
+ * Often, the directional pad on a game controller will either look like 4
+ * separate buttons or a POV hat, and not axes, but all of this is up to the
+ * device and platform.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of axis controls/number of axes on success or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_JoystickGetAxis
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumAxes(SDL_Joystick *joystick);
+
+/**
+ * Get the number of trackballs on a joystick.
+ *
+ * Joystick trackballs have only relative motion events associated with them
+ * and their state cannot be polled.
+ *
+ * Most joysticks do not have trackballs.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of trackballs on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickGetBall
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumBalls(SDL_Joystick *joystick);
+
+/**
+ * Get the number of POV hats on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of POV hats on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickGetHat
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumHats(SDL_Joystick *joystick);
+
+/**
+ * Get the number of buttons on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of buttons on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickGetButton
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick *joystick);
+
+/**
+ * Update the current state of the open joysticks.
+ *
+ * This is called automatically by the event loop if any joystick events are
+ * enabled.
+ *
+ * \sa SDL_JoystickEventState
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickUpdate(void);
+
+/**
+ * Enable/disable joystick event polling.
+ *
+ * If joystick events are disabled, you must call SDL_JoystickUpdate()
+ * yourself and manually check the state of the joystick when you want
+ * joystick information.
+ *
+ * It is recommended that you leave joystick event handling enabled.
+ *
+ * **WARNING**: Calling this function may delete all events currently in SDL's
+ * event queue.
+ *
+ * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE`
+ * \returns 1 if enabled, 0 if disabled, or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ *
+ * If `state` is `SDL_QUERY` then the current state is returned,
+ * otherwise the new processing state is returned.
+ *
+ * \sa SDL_GameControllerEventState
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickEventState(int state);
+
+#define SDL_JOYSTICK_AXIS_MAX 32767
+#define SDL_JOYSTICK_AXIS_MIN -32768
+/**
+ * Get the current state of an axis control on a joystick.
+ *
+ * SDL makes no promises about what part of the joystick any given axis refers
+ * to. Your game should have some sort of configuration UI to let users
+ * specify what each axis should be bound to. Alternately, SDL's higher-level
+ * Game Controller API makes a great effort to apply order to this lower-level
+ * interface, so you know that a specific axis is the "left thumb stick," etc.
+ *
+ * The value returned by SDL_JoystickGetAxis() is a signed integer (-32768 to
+ * 32767) representing the current position of the axis. It may be necessary
+ * to impose certain tolerances on these values to account for jitter.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param axis the axis to query; the axis indices start at index 0
+ * \returns a 16-bit signed integer representing the current position of the
+ * axis or 0 on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickNumAxes
+ */
+extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick *joystick,
+ int axis);
+
+/**
+ * Get the initial state of an axis control on a joystick.
+ *
+ * The state is a value ranging from -32768 to 32767.
+ *
+ * The axis indices start at index 0.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param axis the axis to query; the axis indices start at index 0
+ * \param state Upon return, the initial value is supplied here.
+ * \return SDL_TRUE if this axis has any initial value, or SDL_FALSE if not.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick,
+ int axis, Sint16 *state);
+
+/**
+ * \name Hat positions
+ */
+/* @{ */
+#define SDL_HAT_CENTERED 0x00
+#define SDL_HAT_UP 0x01
+#define SDL_HAT_RIGHT 0x02
+#define SDL_HAT_DOWN 0x04
+#define SDL_HAT_LEFT 0x08
+#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP)
+#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN)
+#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP)
+#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN)
+/* @} */
+
+/**
+ * Get the current state of a POV hat on a joystick.
+ *
+ * The returned value will be one of the following positions:
+ *
+ * - `SDL_HAT_CENTERED`
+ * - `SDL_HAT_UP`
+ * - `SDL_HAT_RIGHT`
+ * - `SDL_HAT_DOWN`
+ * - `SDL_HAT_LEFT`
+ * - `SDL_HAT_RIGHTUP`
+ * - `SDL_HAT_RIGHTDOWN`
+ * - `SDL_HAT_LEFTUP`
+ * - `SDL_HAT_LEFTDOWN`
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param hat the hat index to get the state from; indices start at index 0
+ * \returns the current hat position.
+ *
+ * \sa SDL_JoystickNumHats
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetHat(SDL_Joystick *joystick,
+ int hat);
+
+/**
+ * Get the ball axis change since the last poll.
+ *
+ * Trackballs can only return relative motion since the last call to
+ * SDL_JoystickGetBall(), these motion deltas are placed into `dx` and `dy`.
+ *
+ * Most joysticks do not have trackballs.
+ *
+ * \param joystick the SDL_Joystick to query
+ * \param ball the ball index to query; ball indices start at index 0
+ * \param dx stores the difference in the x axis position since the last poll
+ * \param dy stores the difference in the y axis position since the last poll
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_JoystickNumBalls
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick *joystick,
+ int ball, int *dx, int *dy);
+
+/**
+ * Get the current state of a button on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param button the button index to get the state from; indices start at
+ * index 0
+ * \returns 1 if the specified button is pressed, 0 otherwise.
+ *
+ * \sa SDL_JoystickNumButtons
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick *joystick,
+ int button);
+
+/**
+ * Start a rumble effect.
+ *
+ * Each call to this function cancels any previous rumble effect, and calling
+ * it with 0 intensity stops any rumbling.
+ *
+ * \param joystick The joystick to vibrate
+ * \param low_frequency_rumble The intensity of the low frequency (left)
+ * rumble motor, from 0 to 0xFFFF
+ * \param high_frequency_rumble The intensity of the high frequency (right)
+ * rumble motor, from 0 to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if rumble isn't supported on this joystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
+
+/**
+ * Start a rumble effect in the joystick's triggers
+ *
+ * Each call to this function cancels any previous trigger rumble effect, and
+ * calling it with 0 intensity stops any rumbling.
+ *
+ * Note that this function is for _trigger_ rumble; the first joystick to
+ * support this was the PlayStation 5's DualShock 5 controller. If you want
+ * the (more common) whole-controller rumble, use SDL_JoystickRumble()
+ * instead.
+ *
+ * \param joystick The joystick to vibrate
+ * \param left_rumble The intensity of the left trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param right_rumble The intensity of the right trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if trigger rumble isn't supported on this joystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms);
+
+/**
+ * Query whether a joystick has an LED.
+ *
+ * An example of a joystick LED is the light on the back of a PlayStation 4's
+ * DualShock 4 controller.
+ *
+ * \param joystick The joystick to query
+ * \return SDL_TRUE if the joystick has a modifiable LED, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasLED(SDL_Joystick *joystick);
+
+/**
+ * Update a joystick's LED color.
+ *
+ * An example of a joystick LED is the light on the back of a PlayStation 4's
+ * DualShock 4 controller.
+ *
+ * \param joystick The joystick to update
+ * \param red The intensity of the red LED
+ * \param green The intensity of the green LED
+ * \param blue The intensity of the blue LED
+ * \returns 0 on success, -1 if this joystick does not have a modifiable LED
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
+
+/**
+ * Send a joystick specific effect packet
+ *
+ * \param joystick The joystick to affect
+ * \param data The data to send to the joystick
+ * \param size The size of the data to send to the joystick
+ * \returns 0, or -1 if this joystick or driver doesn't support effect packets
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size);
+
+/**
+ * Close a joystick previously opened with SDL_JoystickOpen().
+ *
+ * \param joystick The joystick device to close
+ *
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick *joystick);
+
+/**
+ * Get the battery level of a joystick as SDL_JoystickPowerLevel.
+ *
+ * \param joystick the SDL_Joystick to query
+ * \returns the current battery level as SDL_JoystickPowerLevel on success or
+ * `SDL_JOYSTICK_POWER_UNKNOWN` if it is unknown
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_JoystickPowerLevel SDLCALL SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_joystick_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_keyboard.h b/Client/ThirdParty/SDL2/include/SDL_keyboard.h
new file mode 100644
index 0000000..4260b5e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_keyboard.h
@@ -0,0 +1,294 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_keyboard.h
+ *
+ * Include file for SDL keyboard event handling
+ */
+
+#ifndef SDL_keyboard_h_
+#define SDL_keyboard_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_keycode.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The SDL keysym structure, used in key events.
+ *
+ * \note If you are looking for translated character input, see the ::SDL_TEXTINPUT event.
+ */
+typedef struct SDL_Keysym
+{
+ SDL_Scancode scancode; /**< SDL physical key code - see ::SDL_Scancode for details */
+ SDL_Keycode sym; /**< SDL virtual key code - see ::SDL_Keycode for details */
+ Uint16 mod; /**< current key modifiers */
+ Uint32 unused;
+} SDL_Keysym;
+
+/* Function prototypes */
+
+/**
+ * Query the window which currently has keyboard focus.
+ *
+ * \returns the window with keyboard focus.
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void);
+
+/**
+ * Get a snapshot of the current state of the keyboard.
+ *
+ * The pointer returned is a pointer to an internal SDL array. It will be
+ * valid for the whole lifetime of the application and should not be freed by
+ * the caller.
+ *
+ * A array element with a value of 1 means that the key is pressed and a value
+ * of 0 means that it is not. Indexes into this array are obtained by using
+ * SDL_Scancode values.
+ *
+ * Use SDL_PumpEvents() to update the state array.
+ *
+ * This function gives you the current state after all events have been
+ * processed, so if a key or button has been pressed and released before you
+ * process events, then the pressed state will never show up in the
+ * SDL_GetKeyboardState() calls.
+ *
+ * Note: This function doesn't take into account whether shift has been
+ * pressed or not.
+ *
+ * \param numkeys if non-NULL, receives the length of the returned array
+ * \returns a pointer to an array of key states.
+ *
+ * \sa SDL_PumpEvents
+ */
+extern DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys);
+
+/**
+ * Get the current key modifier state for the keyboard.
+ *
+ * \returns an OR'd combination of the modifier keys for the keyboard. See
+ * SDL_Keymod for details.
+ *
+ * \sa SDL_GetKeyboardState
+ * \sa SDL_SetModState
+ */
+extern DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void);
+
+/**
+ * Set the current key modifier state for the keyboard.
+ *
+ * The inverse of SDL_GetModState(), SDL_SetModState() allows you to impose
+ * modifier key states on your application. Simply pass your desired modifier
+ * states into `modstate`. This value may be a bitwise, OR'd combination of
+ * SDL_Keymod values.
+ *
+ * This does not change the keyboard state, only the key modifier flags that
+ * SDL reports.
+ *
+ * \param modstate the desired SDL_Keymod for the keyboard
+ *
+ * \sa SDL_GetModState
+ */
+extern DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate);
+
+/**
+ * Get the key code corresponding to the given scancode according to the
+ * current keyboard layout.
+ *
+ * See SDL_Keycode for details.
+ *
+ * \param scancode the desired SDL_Scancode to query
+ * \returns the SDL_Keycode that corresponds to the given SDL_Scancode.
+ *
+ * \sa SDL_GetKeyName
+ * \sa SDL_GetScancodeFromKey
+ */
+extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode);
+
+/**
+ * Get the scancode corresponding to the given key code according to the
+ * current keyboard layout.
+ *
+ * See SDL_Scancode for details.
+ *
+ * \param key the desired SDL_Keycode to query
+ * \returns the SDL_Scancode that corresponds to the given SDL_Keycode.
+ *
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetScancodeName
+ */
+extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key);
+
+/**
+ * Get a human-readable name for a scancode.
+ *
+ * See SDL_Scancode for details.
+ *
+ * **Warning**: The returned name is by design not stable across platforms,
+ * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left
+ * Windows" under Microsoft Windows, and some scancodes like
+ * `SDL_SCANCODE_NONUSBACKSLASH` don't have any name at all. There are even
+ * scancodes that share names, e.g. `SDL_SCANCODE_RETURN` and
+ * `SDL_SCANCODE_RETURN2` (both called "Return"). This function is therefore
+ * unsuitable for creating a stable cross-platform two-way mapping between
+ * strings and scancodes.
+ *
+ * \param scancode the desired SDL_Scancode to query
+ * \returns a pointer to the name for the scancode. If the scancode doesn't
+ * have a name this function returns an empty string ("").
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetScancodeFromKey
+ * \sa SDL_GetScancodeFromName
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetScancodeName(SDL_Scancode scancode);
+
+/**
+ * Get a scancode from a human-readable name.
+ *
+ * \param name the human-readable scancode name
+ * \returns the SDL_Scancode, or `SDL_SCANCODE_UNKNOWN` if the name wasn't
+ * recognized; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyFromName
+ * \sa SDL_GetScancodeFromKey
+ * \sa SDL_GetScancodeName
+ */
+extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name);
+
+/**
+ * Get a human-readable name for a key.
+ *
+ * See SDL_Scancode and SDL_Keycode for details.
+ *
+ * \param key the desired SDL_Keycode to query
+ * \returns a pointer to a UTF-8 string that stays valid at least until the
+ * next call to this function. If you need it around any longer, you
+ * must copy it. If the key doesn't have a name, this function
+ * returns an empty string ("").
+ *
+ * \sa SDL_GetKeyFromName
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetScancodeFromKey
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key);
+
+/**
+ * Get a key code from a human-readable name.
+ *
+ * \param name the human-readable key name
+ * \returns key code, or `SDLK_UNKNOWN` if the name wasn't recognized; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetKeyName
+ * \sa SDL_GetScancodeFromName
+ */
+extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name);
+
+/**
+ * Start accepting Unicode text input events.
+ *
+ * This function will start accepting Unicode text input events in the focused
+ * SDL window, and start emitting SDL_TextInputEvent (SDL_TEXTINPUT) and
+ * SDL_TextEditingEvent (SDL_TEXTEDITING) events. Please use this function in
+ * pair with SDL_StopTextInput().
+ *
+ * On some platforms using this function activates the screen keyboard.
+ *
+ * \sa SDL_SetTextInputRect
+ * \sa SDL_StopTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_StartTextInput(void);
+
+/**
+ * Check whether or not Unicode text input events are enabled.
+ *
+ * \returns SDL_TRUE if text input events are enabled else SDL_FALSE.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputActive(void);
+
+/**
+ * Stop receiving any text input events.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_StopTextInput(void);
+
+/**
+ * Set the rectangle used to type Unicode text inputs.
+ *
+ * \param rect the SDL_Rect structure representing the rectangle to receive
+ * text (ignored if NULL)
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_SetTextInputRect(SDL_Rect *rect);
+
+/**
+ * Check whether the platform has screen keyboard support.
+ *
+ * \returns SDL_TRUE if the platform has some screen keyboard support or
+ * SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ * \sa SDL_IsScreenKeyboardShown
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasScreenKeyboardSupport(void);
+
+/**
+ * Check whether the screen keyboard is shown for given window.
+ *
+ * \param window the window for which screen keyboard should be queried
+ * \returns SDL_TRUE if screen keyboard is shown or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasScreenKeyboardSupport
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenKeyboardShown(SDL_Window *window);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_keyboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_keycode.h b/Client/ThirdParty/SDL2/include/SDL_keycode.h
new file mode 100644
index 0000000..4fb0d39
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_keycode.h
@@ -0,0 +1,351 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_keycode.h
+ *
+ * Defines constants which identify keyboard keys and modifiers.
+ */
+
+#ifndef SDL_keycode_h_
+#define SDL_keycode_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_scancode.h"
+
+/**
+ * \brief The SDL virtual key representation.
+ *
+ * Values of this type are used to represent keyboard keys using the current
+ * layout of the keyboard. These values include Unicode values representing
+ * the unmodified character that would be generated by pressing the key, or
+ * an SDLK_* constant for those keys that do not generate characters.
+ *
+ * A special exception is the number keys at the top of the keyboard which
+ * always map to SDLK_0...SDLK_9, regardless of layout.
+ */
+typedef Sint32 SDL_Keycode;
+
+#define SDLK_SCANCODE_MASK (1<<30)
+#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK)
+
+typedef enum
+{
+ SDLK_UNKNOWN = 0,
+
+ SDLK_RETURN = '\r',
+ SDLK_ESCAPE = '\x1B',
+ SDLK_BACKSPACE = '\b',
+ SDLK_TAB = '\t',
+ SDLK_SPACE = ' ',
+ SDLK_EXCLAIM = '!',
+ SDLK_QUOTEDBL = '"',
+ SDLK_HASH = '#',
+ SDLK_PERCENT = '%',
+ SDLK_DOLLAR = '$',
+ SDLK_AMPERSAND = '&',
+ SDLK_QUOTE = '\'',
+ SDLK_LEFTPAREN = '(',
+ SDLK_RIGHTPAREN = ')',
+ SDLK_ASTERISK = '*',
+ SDLK_PLUS = '+',
+ SDLK_COMMA = ',',
+ SDLK_MINUS = '-',
+ SDLK_PERIOD = '.',
+ SDLK_SLASH = '/',
+ SDLK_0 = '0',
+ SDLK_1 = '1',
+ SDLK_2 = '2',
+ SDLK_3 = '3',
+ SDLK_4 = '4',
+ SDLK_5 = '5',
+ SDLK_6 = '6',
+ SDLK_7 = '7',
+ SDLK_8 = '8',
+ SDLK_9 = '9',
+ SDLK_COLON = ':',
+ SDLK_SEMICOLON = ';',
+ SDLK_LESS = '<',
+ SDLK_EQUALS = '=',
+ SDLK_GREATER = '>',
+ SDLK_QUESTION = '?',
+ SDLK_AT = '@',
+
+ /*
+ Skip uppercase letters
+ */
+
+ SDLK_LEFTBRACKET = '[',
+ SDLK_BACKSLASH = '\\',
+ SDLK_RIGHTBRACKET = ']',
+ SDLK_CARET = '^',
+ SDLK_UNDERSCORE = '_',
+ SDLK_BACKQUOTE = '`',
+ SDLK_a = 'a',
+ SDLK_b = 'b',
+ SDLK_c = 'c',
+ SDLK_d = 'd',
+ SDLK_e = 'e',
+ SDLK_f = 'f',
+ SDLK_g = 'g',
+ SDLK_h = 'h',
+ SDLK_i = 'i',
+ SDLK_j = 'j',
+ SDLK_k = 'k',
+ SDLK_l = 'l',
+ SDLK_m = 'm',
+ SDLK_n = 'n',
+ SDLK_o = 'o',
+ SDLK_p = 'p',
+ SDLK_q = 'q',
+ SDLK_r = 'r',
+ SDLK_s = 's',
+ SDLK_t = 't',
+ SDLK_u = 'u',
+ SDLK_v = 'v',
+ SDLK_w = 'w',
+ SDLK_x = 'x',
+ SDLK_y = 'y',
+ SDLK_z = 'z',
+
+ SDLK_CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK),
+
+ SDLK_F1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1),
+ SDLK_F2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2),
+ SDLK_F3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3),
+ SDLK_F4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4),
+ SDLK_F5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5),
+ SDLK_F6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6),
+ SDLK_F7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7),
+ SDLK_F8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8),
+ SDLK_F9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9),
+ SDLK_F10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10),
+ SDLK_F11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11),
+ SDLK_F12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12),
+
+ SDLK_PRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN),
+ SDLK_SCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK),
+ SDLK_PAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE),
+ SDLK_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT),
+ SDLK_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME),
+ SDLK_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP),
+ SDLK_DELETE = '\x7F',
+ SDLK_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END),
+ SDLK_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN),
+ SDLK_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT),
+ SDLK_LEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT),
+ SDLK_DOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN),
+ SDLK_UP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP),
+
+ SDLK_NUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR),
+ SDLK_KP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE),
+ SDLK_KP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY),
+ SDLK_KP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS),
+ SDLK_KP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS),
+ SDLK_KP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER),
+ SDLK_KP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1),
+ SDLK_KP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2),
+ SDLK_KP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3),
+ SDLK_KP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4),
+ SDLK_KP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5),
+ SDLK_KP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6),
+ SDLK_KP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7),
+ SDLK_KP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8),
+ SDLK_KP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9),
+ SDLK_KP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0),
+ SDLK_KP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD),
+
+ SDLK_APPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION),
+ SDLK_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER),
+ SDLK_KP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS),
+ SDLK_F13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13),
+ SDLK_F14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14),
+ SDLK_F15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15),
+ SDLK_F16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16),
+ SDLK_F17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17),
+ SDLK_F18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18),
+ SDLK_F19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19),
+ SDLK_F20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20),
+ SDLK_F21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21),
+ SDLK_F22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22),
+ SDLK_F23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23),
+ SDLK_F24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24),
+ SDLK_EXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE),
+ SDLK_HELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP),
+ SDLK_MENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU),
+ SDLK_SELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT),
+ SDLK_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP),
+ SDLK_AGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN),
+ SDLK_UNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO),
+ SDLK_CUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT),
+ SDLK_COPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY),
+ SDLK_PASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE),
+ SDLK_FIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND),
+ SDLK_MUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE),
+ SDLK_VOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP),
+ SDLK_VOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN),
+ SDLK_KP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA),
+ SDLK_KP_EQUALSAS400 =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400),
+
+ SDLK_ALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE),
+ SDLK_SYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ),
+ SDLK_CANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL),
+ SDLK_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR),
+ SDLK_PRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR),
+ SDLK_RETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2),
+ SDLK_SEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR),
+ SDLK_OUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT),
+ SDLK_OPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER),
+ SDLK_CLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN),
+ SDLK_CRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL),
+ SDLK_EXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL),
+
+ SDLK_KP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00),
+ SDLK_KP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000),
+ SDLK_THOUSANDSSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR),
+ SDLK_DECIMALSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR),
+ SDLK_CURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT),
+ SDLK_CURRENCYSUBUNIT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT),
+ SDLK_KP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN),
+ SDLK_KP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN),
+ SDLK_KP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE),
+ SDLK_KP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE),
+ SDLK_KP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB),
+ SDLK_KP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE),
+ SDLK_KP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A),
+ SDLK_KP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B),
+ SDLK_KP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C),
+ SDLK_KP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D),
+ SDLK_KP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E),
+ SDLK_KP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F),
+ SDLK_KP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR),
+ SDLK_KP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER),
+ SDLK_KP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT),
+ SDLK_KP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS),
+ SDLK_KP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER),
+ SDLK_KP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND),
+ SDLK_KP_DBLAMPERSAND =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND),
+ SDLK_KP_VERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR),
+ SDLK_KP_DBLVERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR),
+ SDLK_KP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON),
+ SDLK_KP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH),
+ SDLK_KP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE),
+ SDLK_KP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT),
+ SDLK_KP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM),
+ SDLK_KP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE),
+ SDLK_KP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL),
+ SDLK_KP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR),
+ SDLK_KP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD),
+ SDLK_KP_MEMSUBTRACT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT),
+ SDLK_KP_MEMMULTIPLY =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY),
+ SDLK_KP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE),
+ SDLK_KP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS),
+ SDLK_KP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR),
+ SDLK_KP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY),
+ SDLK_KP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY),
+ SDLK_KP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL),
+ SDLK_KP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL),
+ SDLK_KP_HEXADECIMAL =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL),
+
+ SDLK_LCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL),
+ SDLK_LSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT),
+ SDLK_LALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT),
+ SDLK_LGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI),
+ SDLK_RCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL),
+ SDLK_RSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT),
+ SDLK_RALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT),
+ SDLK_RGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI),
+
+ SDLK_MODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE),
+
+ SDLK_AUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT),
+ SDLK_AUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV),
+ SDLK_AUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP),
+ SDLK_AUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY),
+ SDLK_AUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE),
+ SDLK_MEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT),
+ SDLK_WWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW),
+ SDLK_MAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL),
+ SDLK_CALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR),
+ SDLK_COMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER),
+ SDLK_AC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH),
+ SDLK_AC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME),
+ SDLK_AC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK),
+ SDLK_AC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD),
+ SDLK_AC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP),
+ SDLK_AC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH),
+ SDLK_AC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS),
+
+ SDLK_BRIGHTNESSDOWN =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN),
+ SDLK_BRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP),
+ SDLK_DISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH),
+ SDLK_KBDILLUMTOGGLE =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE),
+ SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),
+ SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),
+ SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),
+ SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP),
+ SDLK_APP1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP1),
+ SDLK_APP2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP2),
+
+ SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND),
+ SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD)
+} SDL_KeyCode;
+
+/**
+ * \brief Enumeration of valid key mods (possibly OR'd together).
+ */
+typedef enum
+{
+ KMOD_NONE = 0x0000,
+ KMOD_LSHIFT = 0x0001,
+ KMOD_RSHIFT = 0x0002,
+ KMOD_LCTRL = 0x0040,
+ KMOD_RCTRL = 0x0080,
+ KMOD_LALT = 0x0100,
+ KMOD_RALT = 0x0200,
+ KMOD_LGUI = 0x0400,
+ KMOD_RGUI = 0x0800,
+ KMOD_NUM = 0x1000,
+ KMOD_CAPS = 0x2000,
+ KMOD_MODE = 0x4000,
+ KMOD_RESERVED = 0x8000,
+
+ KMOD_CTRL = KMOD_LCTRL | KMOD_RCTRL,
+ KMOD_SHIFT = KMOD_LSHIFT | KMOD_RSHIFT,
+ KMOD_ALT = KMOD_LALT | KMOD_RALT,
+ KMOD_GUI = KMOD_LGUI | KMOD_RGUI
+} SDL_Keymod;
+
+#endif /* SDL_keycode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_loadso.h b/Client/ThirdParty/SDL2/include/SDL_loadso.h
new file mode 100644
index 0000000..e6a33a0
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_loadso.h
@@ -0,0 +1,109 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_loadso.h
+ *
+ * System dependent library loading routines
+ *
+ * Some things to keep in mind:
+ * \li These functions only work on C function names. Other languages may
+ * have name mangling and intrinsic language support that varies from
+ * compiler to compiler.
+ * \li Make sure you declare your function pointers with the same calling
+ * convention as the actual library function. Your code will crash
+ * mysteriously if you do not do this.
+ * \li Avoid namespace collisions. If you load a symbol from the library,
+ * it is not defined whether or not it goes into the global symbol
+ * namespace for the application. If it does and it conflicts with
+ * symbols in your code or other shared libraries, you will not get
+ * the results you expect. :)
+ */
+
+#ifndef SDL_loadso_h_
+#define SDL_loadso_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Dynamically load a shared object.
+ *
+ * \param sofile a system-dependent name of the object file
+ * \returns an opaque pointer to the object handle or NULL if there was an
+ * error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_LoadFunction
+ * \sa SDL_UnloadObject
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile);
+
+/**
+ * Look up the address of the named function in a shared object.
+ *
+ * This function pointer is no longer valid after calling SDL_UnloadObject().
+ *
+ * This function can only look up C function names. Other languages may have
+ * name mangling and intrinsic language support that varies from compiler to
+ * compiler.
+ *
+ * Make sure you declare your function pointers with the same calling
+ * convention as the actual library function. Your code will crash
+ * mysteriously if you do not do this.
+ *
+ * If the requested function doesn't exist, NULL is returned.
+ *
+ * \param handle a valid shared object handle returned by SDL_LoadObject()
+ * \param name the name of the function to look up
+ * \returns a pointer to the function or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_LoadObject
+ * \sa SDL_UnloadObject
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle,
+ const char *name);
+
+/**
+ * Unload a shared object from memory.
+ *
+ * \param handle a valid shared object handle returned by SDL_LoadObject()
+ *
+ * \sa SDL_LoadFunction
+ * \sa SDL_LoadObject
+ */
+extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_loadso_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_locale.h b/Client/ThirdParty/SDL2/include/SDL_locale.h
new file mode 100644
index 0000000..cb4b043
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_locale.h
@@ -0,0 +1,101 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_locale.h
+ *
+ * Include file for SDL locale services
+ */
+
+#ifndef _SDL_locale_h
+#define _SDL_locale_h
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+
+typedef struct SDL_Locale
+{
+ const char *language; /**< A language name, like "en" for English. */
+ const char *country; /**< A country, like "US" for America. Can be NULL. */
+} SDL_Locale;
+
+/**
+ * Report the user's preferred locale.
+ *
+ * This returns an array of SDL_Locale structs, the final item zeroed out.
+ * When the caller is done with this array, it should call SDL_free() on the
+ * returned value; all the memory involved is allocated in a single block, so
+ * a single SDL_free() will suffice.
+ *
+ * Returned language strings are in the format xx, where 'xx' is an ISO-639
+ * language specifier (such as "en" for English, "de" for German, etc).
+ * Country strings are in the format YY, where "YY" is an ISO-3166 country
+ * code (such as "US" for the United States, "CA" for Canada, etc). Country
+ * might be NULL if there's no specific guidance on them (so you might get {
+ * "en", "US" } for American English, but { "en", NULL } means "English
+ * language, generically"). Language strings are never NULL, except to
+ * terminate the array.
+ *
+ * Please note that not all of these strings are 2 characters; some are three
+ * or more.
+ *
+ * The returned list of locales are in the order of the user's preference. For
+ * example, a German citizen that is fluent in US English and knows enough
+ * Japanese to navigate around Tokyo might have a list like: { "de", "en_US",
+ * "jp", NULL }. Someone from England might prefer British English (where
+ * "color" is spelled "colour", etc), but will settle for anything like it: {
+ * "en_GB", "en", NULL }.
+ *
+ * This function returns NULL on error, including when the platform does not
+ * supply this information at all.
+ *
+ * This might be a "slow" call that has to query the operating system. It's
+ * best to ask for this once and save the results. However, this list can
+ * change, usually because the user has changed a system preference outside of
+ * your program; SDL will send an SDL_LOCALECHANGED event in this case, if
+ * possible, and you can call this function again to get an updated copy of
+ * preferred locales.
+ *
+ * \return array of locales, terminated with a locale with a NULL language
+ * field. Will return NULL on error.
+ */
+extern DECLSPEC SDL_Locale * SDLCALL SDL_GetPreferredLocales(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_locale_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_log.h b/Client/ThirdParty/SDL2/include/SDL_log.h
new file mode 100644
index 0000000..e85961a
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_log.h
@@ -0,0 +1,376 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_log.h
+ *
+ * Simple log messages with categories and priorities.
+ *
+ * By default logs are quiet, but if you're debugging SDL you might want:
+ *
+ * SDL_LogSetAllPriority(SDL_LOG_PRIORITY_WARN);
+ *
+ * Here's where the messages go on different platforms:
+ * Windows: debug output stream
+ * Android: log output
+ * Others: standard error output (stderr)
+ */
+
+#ifndef SDL_log_h_
+#define SDL_log_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief The maximum size of a log message
+ *
+ * Messages longer than the maximum size will be truncated
+ */
+#define SDL_MAX_LOG_MESSAGE 4096
+
+/**
+ * \brief The predefined log categories
+ *
+ * By default the application category is enabled at the INFO level,
+ * the assert category is enabled at the WARN level, test is enabled
+ * at the VERBOSE level and all other categories are enabled at the
+ * CRITICAL level.
+ */
+typedef enum
+{
+ SDL_LOG_CATEGORY_APPLICATION,
+ SDL_LOG_CATEGORY_ERROR,
+ SDL_LOG_CATEGORY_ASSERT,
+ SDL_LOG_CATEGORY_SYSTEM,
+ SDL_LOG_CATEGORY_AUDIO,
+ SDL_LOG_CATEGORY_VIDEO,
+ SDL_LOG_CATEGORY_RENDER,
+ SDL_LOG_CATEGORY_INPUT,
+ SDL_LOG_CATEGORY_TEST,
+
+ /* Reserved for future SDL library use */
+ SDL_LOG_CATEGORY_RESERVED1,
+ SDL_LOG_CATEGORY_RESERVED2,
+ SDL_LOG_CATEGORY_RESERVED3,
+ SDL_LOG_CATEGORY_RESERVED4,
+ SDL_LOG_CATEGORY_RESERVED5,
+ SDL_LOG_CATEGORY_RESERVED6,
+ SDL_LOG_CATEGORY_RESERVED7,
+ SDL_LOG_CATEGORY_RESERVED8,
+ SDL_LOG_CATEGORY_RESERVED9,
+ SDL_LOG_CATEGORY_RESERVED10,
+
+ /* Beyond this point is reserved for application use, e.g.
+ enum {
+ MYAPP_CATEGORY_AWESOME1 = SDL_LOG_CATEGORY_CUSTOM,
+ MYAPP_CATEGORY_AWESOME2,
+ MYAPP_CATEGORY_AWESOME3,
+ ...
+ };
+ */
+ SDL_LOG_CATEGORY_CUSTOM
+} SDL_LogCategory;
+
+/**
+ * \brief The predefined log priorities
+ */
+typedef enum
+{
+ SDL_LOG_PRIORITY_VERBOSE = 1,
+ SDL_LOG_PRIORITY_DEBUG,
+ SDL_LOG_PRIORITY_INFO,
+ SDL_LOG_PRIORITY_WARN,
+ SDL_LOG_PRIORITY_ERROR,
+ SDL_LOG_PRIORITY_CRITICAL,
+ SDL_NUM_LOG_PRIORITIES
+} SDL_LogPriority;
+
+
+/**
+ * Set the priority of all log categories.
+ *
+ * \param priority the SDL_LogPriority to assign
+ *
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority);
+
+/**
+ * Set the priority of a particular log category.
+ *
+ * \param category the category to assign a priority to
+ * \param priority the SDL_LogPriority to assign
+ *
+ * \sa SDL_LogGetPriority
+ * \sa SDL_LogSetAllPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetPriority(int category,
+ SDL_LogPriority priority);
+
+/**
+ * Get the priority of a particular log category.
+ *
+ * \param category the category to query
+ * \returns the SDL_LogPriority for the requested category
+ *
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC SDL_LogPriority SDLCALL SDL_LogGetPriority(int category);
+
+/**
+ * Reset all priorities to default.
+ *
+ * This is called by SDL_Quit().
+ *
+ * \sa SDL_LogSetAllPriority
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogResetPriorities(void);
+
+/**
+ * Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO.
+ *
+ * = * \param fmt a printf() style message format string
+ *
+ * \param ... additional parameters matching % tokens in the `fmt` string, if
+ * any
+ *
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_VERBOSE.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_DEBUG.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_INFO.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_WARN.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ */
+extern DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_ERROR.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_CRITICAL.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with the specified category and priority.
+ *
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogMessage(int category,
+ SDL_LogPriority priority,
+ SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(3);
+
+/**
+ * Log a message with the specified category and priority.
+ *
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param fmt a printf() style message format string
+ * \param ap a variable argument list
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogMessageV(int category,
+ SDL_LogPriority priority,
+ const char *fmt, va_list ap);
+
+/**
+ * The prototype for the log output callback function.
+ *
+ * This function is called by SDL when there is new text to be logged.
+ *
+ * \param userdata what was passed as `userdata` to SDL_LogSetOutputFunction()
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param message the message being output
+ */
+typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message);
+
+/**
+ * Get the current log output function.
+ *
+ * \param callback an SDL_LogOutputFunction filled in with the current log
+ * callback
+ * \param userdata a pointer filled in with the pointer that is passed to
+ * `callback`
+ *
+ * \sa SDL_LogSetOutputFunction
+ */
+extern DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata);
+
+/**
+ * Replace the default log output function with one of your own.
+ *
+ * \param callback an SDL_LogOutputFunction to call instead of the default
+ * \param userdata a pointer that is passed to `callback`
+ *
+ * \sa SDL_LogGetOutputFunction
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_log_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_main.h b/Client/ThirdParty/SDL2/include/SDL_main.h
new file mode 100644
index 0000000..087193b
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_main.h
@@ -0,0 +1,186 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_main_h_
+#define SDL_main_h_
+
+#include "SDL_stdinc.h"
+
+/**
+ * \file SDL_main.h
+ *
+ * Redefine main() on some platforms so that it is called by SDL.
+ */
+
+#ifndef SDL_MAIN_HANDLED
+#if defined(__WIN32__)
+/* On Windows SDL provides WinMain(), which parses the command line and passes
+ the arguments to your main function.
+
+ If you provide your own WinMain(), you may define SDL_MAIN_HANDLED
+ */
+#define SDL_MAIN_AVAILABLE
+
+#elif defined(__WINRT__)
+/* On WinRT, SDL provides a main function that initializes CoreApplication,
+ creating an instance of IFrameworkView in the process.
+
+ Please note that #include'ing SDL_main.h is not enough to get a main()
+ function working. In non-XAML apps, the file,
+ src/main/winrt/SDL_WinRT_main_NonXAML.cpp, or a copy of it, must be compiled
+ into the app itself. In XAML apps, the function, SDL_WinRTRunApp must be
+ called, with a pointer to the Direct3D-hosted XAML control passed in.
+*/
+#define SDL_MAIN_NEEDED
+
+#elif defined(__IPHONEOS__)
+/* On iOS SDL provides a main function that creates an application delegate
+ and starts the iOS application run loop.
+
+ If you link with SDL dynamically on iOS, the main function can't be in a
+ shared library, so you need to link with libSDLmain.a, which includes a
+ stub main function that calls into the shared library to start execution.
+
+ See src/video/uikit/SDL_uikitappdelegate.m for more details.
+ */
+#define SDL_MAIN_NEEDED
+
+#elif defined(__ANDROID__)
+/* On Android SDL provides a Java class in SDLActivity.java that is the
+ main activity entry point.
+
+ See docs/README-android.md for more details on extending that class.
+ */
+#define SDL_MAIN_NEEDED
+
+/* We need to export SDL_main so it can be launched from Java */
+#define SDLMAIN_DECLSPEC DECLSPEC
+
+#elif defined(__NACL__)
+/* On NACL we use ppapi_simple to set up the application helper code,
+ then wait for the first PSE_INSTANCE_DIDCHANGEVIEW event before
+ starting the user main function.
+ All user code is run in a separate thread by ppapi_simple, thus
+ allowing for blocking io to take place via nacl_io
+*/
+#define SDL_MAIN_NEEDED
+
+#endif
+#endif /* SDL_MAIN_HANDLED */
+
+#ifndef SDLMAIN_DECLSPEC
+#define SDLMAIN_DECLSPEC
+#endif
+
+/**
+ * \file SDL_main.h
+ *
+ * The application's main() function must be called with C linkage,
+ * and should be declared like this:
+ * \code
+ * #ifdef __cplusplus
+ * extern "C"
+ * #endif
+ * int main(int argc, char *argv[])
+ * {
+ * }
+ * \endcode
+ */
+
+#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE)
+#define main SDL_main
+#endif
+
+#include "begin_code.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The prototype for the application's main() function
+ */
+typedef int (*SDL_main_func)(int argc, char *argv[]);
+extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]);
+
+
+/**
+ * Circumvent failure of SDL_Init() when not using SDL_main() as an entry
+ * point.
+ *
+ * This function is defined in SDL_main.h, along with the preprocessor rule to
+ * redefine main() as SDL_main(). Thus to ensure that your main() function
+ * will not be changed it is necessary to define SDL_MAIN_HANDLED before
+ * including SDL.h.
+ *
+ * \sa SDL_Init
+ */
+extern DECLSPEC void SDLCALL SDL_SetMainReady(void);
+
+#ifdef __WIN32__
+
+/**
+ * This can be called to set the application class at startup
+ */
+extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, void *hInst);
+extern DECLSPEC void SDLCALL SDL_UnregisterApp(void);
+
+#endif /* __WIN32__ */
+
+
+#ifdef __WINRT__
+
+/**
+ * Initialize and launch an SDL/WinRT application.
+ *
+ * \param mainFunction the SDL app's C-style main(), an SDL_main_func
+ * \param reserved reserved for future use; should be NULL
+ * \returns 0 on success or -1 on failure; call SDL_GetError() to retrieve
+ * more information on the failure.
+ *
+ * \since This function is available since SDL 2.0.3.
+ */
+extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved);
+
+#endif /* __WINRT__ */
+
+#if defined(__IPHONEOS__)
+
+/**
+ * Initializes and launches an SDL application.
+ *
+ * \param argc The argc parameter from the application's main() function
+ * \param argv The argv parameter from the application's main() function
+ * \param mainFunction The SDL app's C-style main(), an SDL_main_func
+ * \return the return value from mainFunction
+ */
+extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction);
+
+#endif /* __IPHONEOS__ */
+
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_main_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_messagebox.h b/Client/ThirdParty/SDL2/include/SDL_messagebox.h
new file mode 100644
index 0000000..c2aef70
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_messagebox.h
@@ -0,0 +1,191 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_messagebox_h_
+#define SDL_messagebox_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_video.h" /* For SDL_Window */
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * SDL_MessageBox flags. If supported will display warning icon, etc.
+ */
+typedef enum
+{
+ SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */
+ SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */
+ SDL_MESSAGEBOX_INFORMATION = 0x00000040, /**< informational dialog */
+ SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT = 0x00000080, /**< buttons placed left to right */
+ SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT = 0x00000100 /**< buttons placed right to left */
+} SDL_MessageBoxFlags;
+
+/**
+ * Flags for SDL_MessageBoxButtonData.
+ */
+typedef enum
+{
+ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001, /**< Marks the default button when return is hit */
+ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002 /**< Marks the default button when escape is hit */
+} SDL_MessageBoxButtonFlags;
+
+/**
+ * Individual button data.
+ */
+typedef struct
+{
+ Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */
+ int buttonid; /**< User defined button id (value returned via SDL_ShowMessageBox) */
+ const char * text; /**< The UTF-8 button text */
+} SDL_MessageBoxButtonData;
+
+/**
+ * RGB value used in a message box color scheme
+ */
+typedef struct
+{
+ Uint8 r, g, b;
+} SDL_MessageBoxColor;
+
+typedef enum
+{
+ SDL_MESSAGEBOX_COLOR_BACKGROUND,
+ SDL_MESSAGEBOX_COLOR_TEXT,
+ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER,
+ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND,
+ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED,
+ SDL_MESSAGEBOX_COLOR_MAX
+} SDL_MessageBoxColorType;
+
+/**
+ * A set of colors to use for message box dialogs
+ */
+typedef struct
+{
+ SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX];
+} SDL_MessageBoxColorScheme;
+
+/**
+ * MessageBox structure containing title, text, window, etc.
+ */
+typedef struct
+{
+ Uint32 flags; /**< ::SDL_MessageBoxFlags */
+ SDL_Window *window; /**< Parent window, can be NULL */
+ const char *title; /**< UTF-8 title */
+ const char *message; /**< UTF-8 message text */
+
+ int numbuttons;
+ const SDL_MessageBoxButtonData *buttons;
+
+ const SDL_MessageBoxColorScheme *colorScheme; /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */
+} SDL_MessageBoxData;
+
+/**
+ * Create a modal message box.
+ *
+ * If your needs aren't complex, it might be easier to use
+ * SDL_ShowSimpleMessageBox.
+ *
+ * This function should be called on the thread that created the parent
+ * window, or on the main thread if the messagebox has no parent. It will
+ * block execution of that thread until the user clicks a button or closes the
+ * messagebox.
+ *
+ * This function may be called at any time, even before SDL_Init(). This makes
+ * it useful for reporting errors like a failure to create a renderer or
+ * OpenGL context.
+ *
+ * On X11, SDL rolls its own dialog box with X11 primitives instead of a
+ * formal toolkit like GTK+ or Qt.
+ *
+ * Note that if SDL_Init() would fail because there isn't any available video
+ * target, this function is likely to fail for the same reasons. If this is a
+ * concern, check the return value from this function and fall back to writing
+ * to stderr if you can.
+ *
+ * \param messageboxdata the SDL_MessageBoxData structure with title, text and
+ * other options
+ * \param buttonid the pointer to which user id of hit button should be copied
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ShowSimpleMessageBox
+ */
+extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+/**
+ * Display a simple modal message box.
+ *
+ * If your needs aren't complex, this function is preferred over
+ * SDL_ShowMessageBox.
+ *
+ * `flags` may be any of the following:
+ *
+ * - `SDL_MESSAGEBOX_ERROR`: error dialog
+ * - `SDL_MESSAGEBOX_WARNING`: warning dialog
+ * - `SDL_MESSAGEBOX_INFORMATION`: informational dialog
+ *
+ * This function should be called on the thread that created the parent
+ * window, or on the main thread if the messagebox has no parent. It will
+ * block execution of that thread until the user clicks a button or closes the
+ * messagebox.
+ *
+ * This function may be called at any time, even before SDL_Init(). This makes
+ * it useful for reporting errors like a failure to create a renderer or
+ * OpenGL context.
+ *
+ * On X11, SDL rolls its own dialog box with X11 primitives instead of a
+ * formal toolkit like GTK+ or Qt.
+ *
+ * Note that if SDL_Init() would fail because there isn't any available video
+ * target, this function is likely to fail for the same reasons. If this is a
+ * concern, check the return value from this function and fall back to writing
+ * to stderr if you can.
+ *
+ * \param flags an SDL_MessageBoxFlags value
+ * \param title UTF-8 title text
+ * \param message UTF-8 message text
+ * \param window the parent window, or NULL for no parent
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_ShowMessageBox
+ */
+extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_messagebox_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_metal.h b/Client/ThirdParty/SDL2/include/SDL_metal.h
new file mode 100644
index 0000000..60bcb6e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_metal.h
@@ -0,0 +1,104 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_metal.h
+ *
+ * Header file for functions to creating Metal layers and views on SDL windows.
+ */
+
+#ifndef SDL_metal_h_
+#define SDL_metal_h_
+
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS).
+ *
+ * \note This can be cast directly to an NSView or UIView.
+ */
+typedef void *SDL_MetalView;
+
+/**
+ * \name Metal support functions
+ */
+/* @{ */
+
+/**
+ * Create a CAMetalLayer-backed NSView/UIView and attach it to the specified
+ * window.
+ *
+ * On macOS, this does *not* associate a MTLDevice with the CAMetalLayer on
+ * its own. It is up to user code to do that.
+ *
+ * The returned handle can be casted directly to a NSView or UIView. To access
+ * the backing CAMetalLayer, call SDL_Metal_GetLayer().
+ *
+ * \sa SDL_Metal_DestroyView
+ * \sa SDL_Metal_GetLayer
+ */
+extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window);
+
+/**
+ * Destroy an existing SDL_MetalView object.
+ *
+ * This should be called before SDL_DestroyWindow, if SDL_Metal_CreateView was
+ * called after SDL_CreateWindow.
+ *
+ * \sa SDL_Metal_CreateView
+ */
+extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view);
+
+/**
+ * Get a pointer to the backing CAMetalLayer for the given view.
+ *
+ * \sa SDL_MetalCreateView
+ */
+extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view);
+
+/**
+ * Get the size of a window's underlying drawable in pixels (for use with
+ * setting viewport, scissor & etc).
+ *
+ * \param window SDL_Window from which the drawable size should be queried
+ * \param w Pointer to variable for storing the width in pixels, may be NULL
+ *
+ * \sa SDL_GetWindowSize
+ * \sa SDL_CreateWindow
+ */
+extern DECLSPEC void SDLCALL SDL_Metal_GetDrawableSize(SDL_Window* window, int *w,
+ int *h);
+
+/* @} *//* Metal support functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_metal_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_misc.h b/Client/ThirdParty/SDL2/include/SDL_misc.h
new file mode 100644
index 0000000..7cd4d57
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_misc.h
@@ -0,0 +1,79 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_misc.h
+ *
+ * \brief Include file for SDL API functions that don't fit elsewhere.
+ */
+
+#ifndef SDL_misc_h_
+#define SDL_misc_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Open a URL/URI in the browser or other appropriate external application.
+ *
+ * Open a URL in a separate, system-provided application. How this works will
+ * vary wildly depending on the platform. This will likely launch what makes
+ * sense to handle a specific URL's protocol (a web browser for `http://`,
+ * etc), but it might also be able to launch file managers for directories and
+ * other things.
+ *
+ * What happens when you open a URL varies wildly as well: your game window
+ * may lose focus (and may or may not lose focus if your game was fullscreen
+ * or grabbing input at the time). On mobile devices, your app will likely
+ * move to the background or your process might be paused. Any given platform
+ * may or may not handle a given URL.
+ *
+ * If this is unimplemented (or simply unavailable) for a platform, this will
+ * fail with an error. A successful result does not mean the URL loaded, just
+ * that we launched _something_ to handle it (or at least believe we did).
+ *
+ * All this to say: this function can be useful, but you should definitely
+ * test it on every platform you target.
+ *
+ * \param url A valid URL/URI to open. Use `file:///full/path/to/file` for
+ * local files, if supported.
+ * \returns 0 on success, or -1 on error; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available in SDL 2.0.14 and newer
+ */
+extern DECLSPEC int SDLCALL SDL_OpenURL(const char *url);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_misc_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_mouse.h b/Client/ThirdParty/SDL2/include/SDL_mouse.h
new file mode 100644
index 0000000..8fbe38f
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_mouse.h
@@ -0,0 +1,432 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_mouse.h
+ *
+ * Include file for SDL mouse event handling.
+ */
+
+#ifndef SDL_mouse_h_
+#define SDL_mouse_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SDL_Cursor SDL_Cursor; /**< Implementation dependent */
+
+/**
+ * \brief Cursor types for SDL_CreateSystemCursor().
+ */
+typedef enum
+{
+ SDL_SYSTEM_CURSOR_ARROW, /**< Arrow */
+ SDL_SYSTEM_CURSOR_IBEAM, /**< I-beam */
+ SDL_SYSTEM_CURSOR_WAIT, /**< Wait */
+ SDL_SYSTEM_CURSOR_CROSSHAIR, /**< Crosshair */
+ SDL_SYSTEM_CURSOR_WAITARROW, /**< Small wait cursor (or Wait if not available) */
+ SDL_SYSTEM_CURSOR_SIZENWSE, /**< Double arrow pointing northwest and southeast */
+ SDL_SYSTEM_CURSOR_SIZENESW, /**< Double arrow pointing northeast and southwest */
+ SDL_SYSTEM_CURSOR_SIZEWE, /**< Double arrow pointing west and east */
+ SDL_SYSTEM_CURSOR_SIZENS, /**< Double arrow pointing north and south */
+ SDL_SYSTEM_CURSOR_SIZEALL, /**< Four pointed arrow pointing north, south, east, and west */
+ SDL_SYSTEM_CURSOR_NO, /**< Slashed circle or crossbones */
+ SDL_SYSTEM_CURSOR_HAND, /**< Hand */
+ SDL_NUM_SYSTEM_CURSORS
+} SDL_SystemCursor;
+
+/**
+ * \brief Scroll direction types for the Scroll event
+ */
+typedef enum
+{
+ SDL_MOUSEWHEEL_NORMAL, /**< The scroll direction is normal */
+ SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */
+} SDL_MouseWheelDirection;
+
+/* Function prototypes */
+
+/**
+ * Get the window which currently has mouse focus.
+ *
+ * \returns the window with mouse focus.
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void);
+
+/**
+ * Retrieve the current state of the mouse.
+ *
+ * The current button state is returned as a button bitmask, which can be
+ * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the
+ * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the
+ * mouse cursor position relative to the focus window. You can pass NULL for
+ * either `x` or `y`.
+ *
+ * \param x the x coordinate of the mouse cursor position relative to the
+ * focus window
+ * \param y the y coordinate of the mouse cursor position relative to the
+ * focus window
+ * \returns a 32-bit button bitmask of the current button state.
+ *
+ * \sa SDL_GetGlobalMouseState
+ * \sa SDL_GetRelativeMouseState
+ * \sa SDL_PumpEvents
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(int *x, int *y);
+
+/**
+ * Get the current state of the mouse in relation to the desktop.
+ *
+ * This works similarly to SDL_GetMouseState(), but the coordinates will be
+ * reported relative to the top-left of the desktop. This can be useful if you
+ * need to track the mouse outside of a specific window and SDL_CaptureMouse()
+ * doesn't fit your needs. For example, it could be useful if you need to
+ * track the mouse while dragging a window, where coordinates relative to a
+ * window might not be in sync at all times.
+ *
+ * Note: SDL_GetMouseState() returns the mouse position as SDL understands it
+ * from the last pump of the event queue. This function, however, queries the
+ * OS for the current mouse position, and as such, might be a slightly less
+ * efficient function. Unless you know what you're doing and have a good
+ * reason to use this function, you probably want SDL_GetMouseState() instead.
+ *
+ * \param x filled in with the current X coord relative to the desktop; can be
+ * NULL
+ * \param y filled in with the current Y coord relative to the desktop; can be
+ * NULL
+ * \returns the current button state as a bitmask which can be tested using
+ * the SDL_BUTTON(X) macros.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_CaptureMouse
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetGlobalMouseState(int *x, int *y);
+
+/**
+ * Retrieve the relative state of the mouse.
+ *
+ * The current button state is returned as a button bitmask, which can be
+ * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the
+ * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the
+ * mouse deltas since the last call to SDL_GetRelativeMouseState() or since
+ * event initialization. You can pass NULL for either `x` or `y`.
+ *
+ * \param x a pointer filled with the last recorded x coordinate of the mouse
+ * \param y a pointer filled with the last recorded y coordinate of the mouse
+ * \returns a 32-bit button bitmask of the relative button state.
+ *
+ * \sa SDL_GetMouseState
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(int *x, int *y);
+
+/**
+ * Move the mouse cursor to the given position within the window.
+ *
+ * This function generates a mouse motion event.
+ *
+ * Note that this function will appear to succeed, but not actually move the
+ * mouse when used over Microsoft Remote Desktop.
+ *
+ * \param window the window to move the mouse into, or NULL for the current
+ * mouse focus
+ * \param x the x coordinate within the window
+ * \param y the y coordinate within the window
+ *
+ * \sa SDL_WarpMouseGlobal
+ */
+extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window,
+ int x, int y);
+
+/**
+ * Move the mouse to the given position in global screen space.
+ *
+ * This function generates a mouse motion event.
+ *
+ * A failure of this function usually means that it is unsupported by a
+ * platform.
+ *
+ * Note that this function will appear to succeed, but not actually move the
+ * mouse when used over Microsoft Remote Desktop.
+ *
+ * \param x the x coordinate
+ * \param y the y coordinate
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_WarpMouseInWindow
+ */
+extern DECLSPEC int SDLCALL SDL_WarpMouseGlobal(int x, int y);
+
+/**
+ * Set relative mouse mode.
+ *
+ * While the mouse is in relative mode, the cursor is hidden, and the driver
+ * will try to report continuous motion in the current window. Only relative
+ * motion events will be delivered, the mouse position will not change.
+ *
+ * Note that this function will not be able to provide continuous relative
+ * motion when used over Microsoft Remote Desktop, instead motion is limited
+ * to the bounds of the screen.
+ *
+ * This function will flush any pending mouse motion.
+ *
+ * \param enabled SDL_TRUE to enable relative mode, SDL_FALSE to disable.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * If relative mode is not supported, this returns -1.
+ *
+ * \sa SDL_GetRelativeMouseMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled);
+
+/**
+ * Capture the mouse and to track input outside an SDL window.
+ *
+ * Capturing enables your app to obtain mouse events globally, instead of just
+ * within your window. Not all video targets support this function. When
+ * capturing is enabled, the current window will get all mouse events, but
+ * unlike relative mode, no change is made to the cursor and it is not
+ * restrained to your window.
+ *
+ * This function may also deny mouse input to other windows--both those in
+ * your application and others on the system--so you should use this function
+ * sparingly, and in small bursts. For example, you might want to track the
+ * mouse while the user is dragging something, until the user releases a mouse
+ * button. It is not recommended that you capture the mouse for long periods
+ * of time, such as the entire time your app is running. For that, you should
+ * probably use SDL_SetRelativeMouseMode() or SDL_SetWindowGrab(), depending
+ * on your goals.
+ *
+ * While captured, mouse events still report coordinates relative to the
+ * current (foreground) window, but those coordinates may be outside the
+ * bounds of the window (including negative values). Capturing is only allowed
+ * for the foreground window. If the window loses focus while capturing, the
+ * capture will be disabled automatically.
+ *
+ * While capturing is enabled, the current window will have the
+ * `SDL_WINDOW_MOUSE_CAPTURE` flag set.
+ *
+ * \param enabled SDL_TRUE to enable capturing, SDL_FALSE to disable.
+ * \returns 0 on success or -1 if not supported; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetGlobalMouseState
+ */
+extern DECLSPEC int SDLCALL SDL_CaptureMouse(SDL_bool enabled);
+
+/**
+ * Query whether relative mouse mode is enabled.
+ *
+ * \returns SDL_TRUE if relative mode is enabled or SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetRelativeMouseMode
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void);
+
+/**
+ * Create a cursor using the specified bitmap data and mask (in MSB format).
+ *
+ * `mask` has to be in MSB (Most Significant Bit) format.
+ *
+ * The cursor width (`w`) must be a multiple of 8 bits.
+ *
+ * The cursor is created in black and white according to the following:
+ *
+ * - data=0, mask=1: white
+ * - data=1, mask=1: black
+ * - data=0, mask=0: transparent
+ * - data=1, mask=0: inverted color if possible, black if not.
+ *
+ * Cursors created with this function must be freed with SDL_FreeCursor().
+ *
+ * If you want to have a color cursor, or create your cursor from an
+ * SDL_Surface, you should use SDL_CreateColorCursor(). Alternately, you can
+ * hide the cursor and draw your own as part of your game's rendering, but it
+ * will be bound to the framerate.
+ *
+ * Also, since SDL 2.0.0, SDL_CreateSystemCursor() is available, which
+ * provides twelve readily available system cursors to pick from.
+ *
+ * \param data the color value for each pixel of the cursor
+ * \param mask the mask value for each pixel of the cursor
+ * \param w the width of the cursor
+ * \param h the height of the cursor
+ * \param hot_x the X-axis location of the upper left corner of the cursor
+ * relative to the actual mouse position
+ * \param hot_y the Y-axis location of the upper left corner of the cursor
+ * relative to the actual mouse position
+ * \returns a new cursor with the specified parameters on success or NULL on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_FreeCursor
+ * \sa SDL_SetCursor
+ * \sa SDL_ShowCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data,
+ const Uint8 * mask,
+ int w, int h, int hot_x,
+ int hot_y);
+
+/**
+ * Create a color cursor.
+ *
+ * \param surface an SDL_Surface structure representing the cursor image
+ * \param hot_x the x position of the cursor hot spot
+ * \param hot_y the y position of the cursor hot spot
+ * \returns the new cursor on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateCursor
+ * \sa SDL_FreeCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface,
+ int hot_x,
+ int hot_y);
+
+/**
+ * Create a system cursor.
+ *
+ * \param id an SDL_SystemCursor enum value
+ * \returns a cursor on success or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_FreeCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id);
+
+/**
+ * Set the active cursor.
+ *
+ * This function sets the currently active cursor to the specified one. If the
+ * cursor is currently visible, the change will be immediately represented on
+ * the display. SDL_SetCursor(NULL) can be used to force cursor redraw, if
+ * this is desired for any reason.
+ *
+ * \param cursor a cursor to make active
+ *
+ * \sa SDL_CreateCursor
+ * \sa SDL_GetCursor
+ * \sa SDL_ShowCursor
+ */
+extern DECLSPEC void SDLCALL SDL_SetCursor(SDL_Cursor * cursor);
+
+/**
+ * Get the active cursor.
+ *
+ * This function returns a pointer to the current cursor which is owned by the
+ * library. It is not necessary to free the cursor with SDL_FreeCursor().
+ *
+ * \returns the active cursor or NULL if there is no mouse.
+ *
+ * \sa SDL_SetCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void);
+
+/**
+ * Get the default cursor.
+ *
+ * \returns the default cursor on success or NULL on failure.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateSystemCursor
+ */
+extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void);
+
+/**
+ * Free a previously-created cursor.
+ *
+ * Use this function to free cursor resources created with SDL_CreateCursor(),
+ * SDL_CreateColorCursor() or SDL_CreateSystemCursor().
+ *
+ * \param cursor the cursor to free
+ *
+ * \sa SDL_CreateColorCursor
+ * \sa SDL_CreateCursor
+ * \sa SDL_CreateSystemCursor
+ */
+extern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor * cursor);
+
+/**
+ * Toggle whether or not the cursor is shown.
+ *
+ * The cursor starts off displayed but can be turned off. Passing `SDL_ENABLE`
+ * displays the cursor and passing `SDL_DISABLE` hides it.
+ *
+ * The current state of the mouse cursor can be queried by passing
+ * `SDL_QUERY`; either `SDL_DISABLE` or `SDL_ENABLE` will be returned.
+ *
+ * \param toggle `SDL_ENABLE` to show the cursor, `SDL_DISABLE` to hide it,
+ * `SDL_QUERY` to query the current state without changing it.
+ * \returns `SDL_ENABLE` if the cursor is shown, or `SDL_DISABLE` if the
+ * cursor is hidden, or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateCursor
+ * \sa SDL_SetCursor
+ */
+extern DECLSPEC int SDLCALL SDL_ShowCursor(int toggle);
+
+/**
+ * Used as a mask when testing buttons in buttonstate.
+ *
+ * - Button 1: Left mouse button
+ * - Button 2: Middle mouse button
+ * - Button 3: Right mouse button
+ */
+#define SDL_BUTTON(X) (1 << ((X)-1))
+#define SDL_BUTTON_LEFT 1
+#define SDL_BUTTON_MIDDLE 2
+#define SDL_BUTTON_RIGHT 3
+#define SDL_BUTTON_X1 4
+#define SDL_BUTTON_X2 5
+#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT)
+#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE)
+#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT)
+#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1)
+#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2)
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_mouse_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_mutex.h b/Client/ThirdParty/SDL2/include/SDL_mutex.h
new file mode 100644
index 0000000..2f27f19
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_mutex.h
@@ -0,0 +1,435 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_mutex_h_
+#define SDL_mutex_h_
+
+/**
+ * \file SDL_mutex.h
+ *
+ * Functions to provide thread synchronization primitives.
+ */
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Synchronization functions which can time out return this value
+ * if they time out.
+ */
+#define SDL_MUTEX_TIMEDOUT 1
+
+/**
+ * This is the timeout value which corresponds to never time out.
+ */
+#define SDL_MUTEX_MAXWAIT (~(Uint32)0)
+
+
+/**
+ * \name Mutex functions
+ */
+/* @{ */
+
+/* The SDL mutex structure, defined in SDL_sysmutex.c */
+struct SDL_mutex;
+typedef struct SDL_mutex SDL_mutex;
+
+/**
+ * Create a new mutex.
+ *
+ * All newly-created mutexes begin in the _unlocked_ state.
+ *
+ * Calls to SDL_LockMutex() will not return while the mutex is locked by
+ * another thread. See SDL_TryLockMutex() to attempt to lock without blocking.
+ *
+ * SDL mutexes are reentrant.
+ *
+ * \returns the initialized and unlocked mutex or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_DestroyMutex
+ * \sa SDL_LockMutex
+ * \sa SDL_TryLockMutex
+ * \sa SDL_UnlockMutex
+ */
+extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void);
+
+/**
+ * Lock the mutex.
+ *
+ * This will block until the mutex is available, which is to say it is in the
+ * unlocked state and the OS has chosen the caller as the next thread to lock
+ * it. Of all threads waiting to lock the mutex, only one may do so at a time.
+ *
+ * It is legal for the owning thread to lock an already-locked mutex. It must
+ * unlock it the same number of times before it is actually made available for
+ * other threads in the system (this is known as a "recursive mutex").
+ *
+ * \param mutex the mutex to lock
+ * \return 0, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex);
+#define SDL_mutexP(m) SDL_LockMutex(m)
+
+/**
+ * Try to lock a mutex without blocking.
+ *
+ * This works just like SDL_LockMutex(), but if the mutex is not available,
+ * this function returns `SDL_MUTEX_TIMEOUT` immediately.
+ *
+ * This technique is useful if you need exclusive access to a resource but
+ * don't want to wait for it, and will return to it to try again later.
+ *
+ * \param mutex the mutex to try to lock
+ * \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for
+ * more information.
+ *
+ * \sa SDL_CreateMutex
+ * \sa SDL_DestroyMutex
+ * \sa SDL_LockMutex
+ * \sa SDL_UnlockMutex
+ */
+extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex);
+
+/**
+ * Unlock the mutex.
+ *
+ * It is legal for the owning thread to lock an already-locked mutex. It must
+ * unlock it the same number of times before it is actually made available for
+ * other threads in the system (this is known as a "recursive mutex").
+ *
+ * It is an error to unlock a mutex that has not been locked by the current
+ * thread, and doing so results in undefined behavior.
+ *
+ * It is also an error to unlock a mutex that isn't locked at all.
+ *
+ * \param mutex the mutex to unlock.
+ * \returns 0, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex);
+#define SDL_mutexV(m) SDL_UnlockMutex(m)
+
+/**
+ * Destroy a mutex created with SDL_CreateMutex().
+ *
+ * This function must be called on any mutex that is no longer needed. Failure
+ * to destroy a mutex will result in a system memory or resource leak. While
+ * it is safe to destroy a mutex that is _unlocked_, it is not safe to attempt
+ * to destroy a locked mutex, and may result in undefined behavior depending
+ * on the platform.
+ *
+ * \param mutex the mutex to destroy
+ *
+ * \sa SDL_CreateMutex
+ * \sa SDL_LockMutex
+ * \sa SDL_TryLockMutex
+ * \sa SDL_UnlockMutex
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex);
+
+/* @} *//* Mutex functions */
+
+
+/**
+ * \name Semaphore functions
+ */
+/* @{ */
+
+/* The SDL semaphore structure, defined in SDL_syssem.c */
+struct SDL_semaphore;
+typedef struct SDL_semaphore SDL_sem;
+
+/**
+ * Create a semaphore.
+ *
+ * This function creates a new semaphore and initializes it with the value
+ * `initial_value`. Each wait operation on the semaphore will atomically
+ * decrement the semaphore value and potentially block if the semaphore value
+ * is 0. Each post operation will atomically increment the semaphore value and
+ * wake waiting threads and allow them to retry the wait operation.
+ *
+ * \param initial_value the starting value of the semaphore
+ * \returns a new semaphore or NULL on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
+
+/**
+ * Destroy a semaphore.
+ *
+ * It is not safe to destroy a semaphore if there are threads currently
+ * waiting on it.
+ *
+ * \param sem the semaphore to destroy
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem);
+
+/**
+ * Wait until a semaphore has a positive value and then decrements it.
+ *
+ * This function suspends the calling thread until either the semaphore
+ * pointed to by `sem` has a positive value or the call is interrupted by a
+ * signal or error. If the call is successful it will atomically decrement the
+ * semaphore value.
+ *
+ * This function is the equivalent of calling SDL_SemWaitTimeout() with a time
+ * length of `SDL_MUTEX_MAXWAIT`.
+ *
+ * \param sem the semaphore wait on
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem);
+
+/**
+ * See if a semaphore has a positive value and decrement it if it does.
+ *
+ * This function checks to see if the semaphore pointed to by `sem` has a
+ * positive value and atomically decrements the semaphore value if it does. If
+ * the semaphore doesn't have a positive value, the function immediately
+ * returns SDL_MUTEX_TIMEDOUT.
+ *
+ * \param sem the semaphore to wait on
+ * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait would
+ * block, or a negative error code on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem);
+
+/**
+ * Wait until a semaphore has a positive value and then decrements it.
+ *
+ * This function suspends the calling thread until either the semaphore
+ * pointed to by `sem` has a positive value, the call is interrupted by a
+ * signal or error, or the specified time has elapsed. If the call is
+ * successful it will atomically decrement the semaphore value.
+ *
+ * \param sem the semaphore to wait on
+ * \param ms the length of the timeout, in milliseconds
+ * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not
+ * succeed in the allotted time, or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemPost
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ */
+extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem * sem, Uint32 ms);
+
+/**
+ * Atomically increment a semaphore's value and wake waiting threads.
+ *
+ * \param sem the semaphore to increment
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSemaphore
+ * \sa SDL_DestroySemaphore
+ * \sa SDL_SemTryWait
+ * \sa SDL_SemValue
+ * \sa SDL_SemWait
+ * \sa SDL_SemWaitTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem);
+
+/**
+ * Get the current value of a semaphore.
+ *
+ * \param sem the semaphore to query
+ * \returns the current value of the semaphore.
+ *
+ * \sa SDL_CreateSemaphore
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem);
+
+/* @} *//* Semaphore functions */
+
+
+/**
+ * \name Condition variable functions
+ */
+/* @{ */
+
+/* The SDL condition variable structure, defined in SDL_syscond.c */
+struct SDL_cond;
+typedef struct SDL_cond SDL_cond;
+
+/**
+ * Create a condition variable.
+ *
+ * \returns a new condition variable or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
+
+/**
+ * Destroy a condition variable.
+ *
+ * \param cond the condition variable to destroy
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond);
+
+/**
+ * Restart one of the threads that are waiting on the condition variable.
+ *
+ * \param cond the condition variable to signal
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond);
+
+/**
+ * Restart all threads that are waiting on the condition variable.
+ *
+ * \param cond the condition variable to signal
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond);
+
+/**
+ * Wait until a condition variable is signaled.
+ *
+ * This function unlocks the specified `mutex` and waits for another thread to
+ * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
+ * `cond`. Once the condition variable is signaled, the mutex is re-locked and
+ * the function returns.
+ *
+ * The mutex must be locked before calling this function.
+ *
+ * This function is the equivalent of calling SDL_CondWaitTimeout() with a
+ * time length of `SDL_MUTEX_MAXWAIT`.
+ *
+ * \param cond the condition variable to wait on
+ * \param mutex the mutex used to coordinate thread access
+ * \returns 0 when it is signaled or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWaitTimeout
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
+
+/**
+ * Wait until a condition variable is signaled or a certain time has passed.
+ *
+ * This function unlocks the specified `mutex` and waits for another thread to
+ * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
+ * `cond`, or for the specified time to elapse. Once the condition variable is
+ * signaled or the time elapsed, the mutex is re-locked and the function
+ * returns.
+ *
+ * The mutex must be locked before calling this function.
+ *
+ * \param cond the condition variable to wait on
+ * \param mutex the mutex used to coordinate thread access
+ * \param ms the maximum time to wait, in milliseconds, or `SDL_MUTEX_MAXWAIT`
+ * to wait indefinitely
+ * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if
+ * the condition is not signaled in the allotted time, or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \sa SDL_CondBroadcast
+ * \sa SDL_CondSignal
+ * \sa SDL_CondWait
+ * \sa SDL_CreateCond
+ * \sa SDL_DestroyCond
+ */
+extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond,
+ SDL_mutex * mutex, Uint32 ms);
+
+/* @} *//* Condition variable functions */
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_mutex_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_name.h b/Client/ThirdParty/SDL2/include/SDL_name.h
new file mode 100644
index 0000000..21e1b79
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_name.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDLname_h_
+#define SDLname_h_
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define NeedFunctionPrototypes 1
+#endif
+
+#define SDL_NAME(X) SDL_##X
+
+#endif /* SDLname_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengl.h b/Client/ThirdParty/SDL2/include/SDL_opengl.h
new file mode 100644
index 0000000..95b51ae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengl.h
@@ -0,0 +1,2183 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengl.h
+ *
+ * This is a simple file to encapsulate the OpenGL API headers.
+ */
+
+/**
+ * \def NO_SDL_GLEXT
+ *
+ * Define this if you have your own version of glext.h and want to disable the
+ * version included in SDL_opengl.h.
+ */
+
+#ifndef SDL_opengl_h_
+#define SDL_opengl_h_
+
+#include "SDL_config.h"
+
+#ifndef __IPHONEOS__ /* No OpenGL on iOS. */
+
+/*
+ * Mesa 3-D graphics library
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef __gl_h_
+#define __gl_h_
+
+#if defined(USE_MGL_NAMESPACE)
+#include "gl_mangle.h"
+#endif
+
+
+/**********************************************************************
+ * Begin system-specific stuff.
+ */
+
+#if defined(_WIN32) && !defined(__WIN32__) && !defined(__CYGWIN__)
+#define __WIN32__
+#endif
+
+#if defined(__WIN32__) && !defined(__CYGWIN__)
+# if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
+# define GLAPI __declspec(dllexport)
+# elif (defined(_MSC_VER) || defined(__MINGW32__)) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
+# define GLAPI __declspec(dllimport)
+# else /* for use with static link lib build of Win32 edition only */
+# define GLAPI extern
+# endif /* _STATIC_MESA support */
+# if defined(__MINGW32__) && defined(GL_NO_STDCALL) || defined(UNDER_CE) /* The generated DLLs by MingW with STDCALL are not compatible with the ones done by Microsoft's compilers */
+# define GLAPIENTRY
+# else
+# define GLAPIENTRY __stdcall
+# endif
+#elif defined(__CYGWIN__) && defined(USE_OPENGL32) /* use native windows opengl32 */
+# define GLAPI extern
+# define GLAPIENTRY __stdcall
+#elif defined(__OS2__) || defined(__EMX__) /* native os/2 opengl */
+# define GLAPI extern
+# define GLAPIENTRY _System
+# define APIENTRY _System
+# if defined(__GNUC__) && !defined(_System)
+# define _System
+# endif
+#elif (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+# define GLAPI __attribute__((visibility("default")))
+# define GLAPIENTRY
+#endif /* WIN32 && !CYGWIN */
+
+/*
+ * WINDOWS: Include windows.h here to define APIENTRY.
+ * It is also useful when applications include this file by
+ * including only glut.h, since glut.h depends on windows.h.
+ * Applications needing to include windows.h with parms other
+ * than "WIN32_LEAN_AND_MEAN" may include windows.h before
+ * glut.h or gl.h.
+ */
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY GLAPIENTRY
+#endif
+
+/* "P" suffix to be used for a pointer to a function */
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+
+#ifndef GLAPIENTRYP
+#define GLAPIENTRYP GLAPIENTRY *
+#endif
+
+#if defined(PRAGMA_EXPORT_SUPPORTED)
+#pragma export on
+#endif
+
+/*
+ * End system-specific stuff.
+ **********************************************************************/
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define GL_VERSION_1_1 1
+#define GL_VERSION_1_2 1
+#define GL_VERSION_1_3 1
+#define GL_ARB_imaging 1
+
+
+/*
+ * Datatypes
+ */
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef signed char GLbyte; /* 1-byte signed */
+typedef short GLshort; /* 2-byte signed */
+typedef int GLint; /* 4-byte signed */
+typedef unsigned char GLubyte; /* 1-byte unsigned */
+typedef unsigned short GLushort; /* 2-byte unsigned */
+typedef unsigned int GLuint; /* 4-byte unsigned */
+typedef int GLsizei; /* 4-byte signed */
+typedef float GLfloat; /* single precision float */
+typedef float GLclampf; /* single precision float in [0,1] */
+typedef double GLdouble; /* double precision float */
+typedef double GLclampd; /* double precision float in [0,1] */
+
+
+
+/*
+ * Constants
+ */
+
+/* Boolean values */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* Data types */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_DOUBLE 0x140A
+
+/* Primitives */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON 0x0009
+
+/* Vertex Arrays */
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+
+/* Matrix Mode */
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_TEXTURE 0x1702
+
+/* Points */
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_RANGE 0x0B12
+
+/* Lines */
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+
+/* Polygons */
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_FILL 0x8037
+
+/* Display Lists */
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_LIST_MODE 0x0B30
+
+/* Depth buffer */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_COMPONENT 0x1902
+
+/* Lighting */
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_SHININESS 0x1601
+#define GL_EMISSION 0x1600
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_SHADE_MODEL 0x0B54
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_NORMALIZE 0x0BA1
+
+/* User clipping planes */
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+
+/* Accumulation buffer */
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_ACCUM 0x0100
+#define GL_ADD 0x0104
+#define GL_LOAD 0x0101
+#define GL_MULT 0x0103
+#define GL_RETURN 0x0102
+
+/* Alpha testing */
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+
+/* Blending */
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_DST 0x0BE0
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+
+/* Render Mode */
+#define GL_FEEDBACK 0x1C01
+#define GL_RENDER 0x1C00
+#define GL_SELECT 0x1C02
+
+/* Feedback */
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+
+/* Selection */
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+
+/* Fog */
+#define GL_FOG 0x0B60
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_COLOR 0x0B66
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_LINEAR 0x2601
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+
+/* Logic Ops */
+#define GL_LOGIC_OP 0x0BF1
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_CLEAR 0x1500
+#define GL_SET 0x150F
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_NOOP 0x1505
+#define GL_INVERT 0x150A
+#define GL_AND 0x1501
+#define GL_NAND 0x150E
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_XOR 0x1506
+#define GL_EQUIV 0x1509
+#define GL_AND_REVERSE 0x1502
+#define GL_AND_INVERTED 0x1504
+#define GL_OR_REVERSE 0x150B
+#define GL_OR_INVERTED 0x150D
+
+/* Stencil */
+#define GL_STENCIL_BITS 0x0D57
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_INDEX 0x1901
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+
+/* Buffers, Pixel Drawing/Reading */
+#define GL_NONE 0
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+/*GL_FRONT 0x0404 */
+/*GL_BACK 0x0405 */
+/*GL_FRONT_AND_BACK 0x0408 */
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_COLOR_INDEX 0x1900
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_ALPHA_BITS 0x0D55
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_INDEX_BITS 0x0D51
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_READ_BUFFER 0x0C02
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_BITMAP 0x1A00
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_DITHER 0x0BD0
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+
+/* Implementation limits */
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+
+/* Gets */
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_MODE 0x0C30
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_RENDER_MODE 0x0C40
+#define GL_RGBA_MODE 0x0C31
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_VIEWPORT 0x0BA2
+
+/* Evaluators */
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+
+/* Hints */
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_FOG_HINT 0x0C54
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* Scissor box */
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+
+/* Pixel Mode / Transfer */
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+
+/* Texture mapping */
+#define GL_TEXTURE_ENV 0x2300
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_LINEAR 0x2400
+#define GL_EYE_PLANE 0x2502
+#define GL_SPHERE_MAP 0x2402
+#define GL_DECAL 0x2101
+#define GL_MODULATE 0x2100
+#define GL_NEAREST 0x2600
+#define GL_REPEAT 0x2901
+#define GL_CLAMP 0x2900
+#define GL_S 0x2000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+
+/* Utility */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* Errors */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* glPush/PopAttrib bits */
+#define GL_CURRENT_BIT 0x00000001
+#define GL_POINT_BIT 0x00000002
+#define GL_LINE_BIT 0x00000004
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_HINT_BIT 0x00008000
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0x000FFFFF
+
+
+/* OpenGL 1.1 */
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_ALL_CLIENT_ATTRIB_BITS 0xFFFFFFFF
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+
+
+
+/*
+ * Miscellaneous
+ */
+
+GLAPI void GLAPIENTRY glClearIndex( GLfloat c );
+
+GLAPI void GLAPIENTRY glClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha );
+
+GLAPI void GLAPIENTRY glClear( GLbitfield mask );
+
+GLAPI void GLAPIENTRY glIndexMask( GLuint mask );
+
+GLAPI void GLAPIENTRY glColorMask( GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha );
+
+GLAPI void GLAPIENTRY glAlphaFunc( GLenum func, GLclampf ref );
+
+GLAPI void GLAPIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor );
+
+GLAPI void GLAPIENTRY glLogicOp( GLenum opcode );
+
+GLAPI void GLAPIENTRY glCullFace( GLenum mode );
+
+GLAPI void GLAPIENTRY glFrontFace( GLenum mode );
+
+GLAPI void GLAPIENTRY glPointSize( GLfloat size );
+
+GLAPI void GLAPIENTRY glLineWidth( GLfloat width );
+
+GLAPI void GLAPIENTRY glLineStipple( GLint factor, GLushort pattern );
+
+GLAPI void GLAPIENTRY glPolygonMode( GLenum face, GLenum mode );
+
+GLAPI void GLAPIENTRY glPolygonOffset( GLfloat factor, GLfloat units );
+
+GLAPI void GLAPIENTRY glPolygonStipple( const GLubyte *mask );
+
+GLAPI void GLAPIENTRY glGetPolygonStipple( GLubyte *mask );
+
+GLAPI void GLAPIENTRY glEdgeFlag( GLboolean flag );
+
+GLAPI void GLAPIENTRY glEdgeFlagv( const GLboolean *flag );
+
+GLAPI void GLAPIENTRY glScissor( GLint x, GLint y, GLsizei width, GLsizei height);
+
+GLAPI void GLAPIENTRY glClipPlane( GLenum plane, const GLdouble *equation );
+
+GLAPI void GLAPIENTRY glGetClipPlane( GLenum plane, GLdouble *equation );
+
+GLAPI void GLAPIENTRY glDrawBuffer( GLenum mode );
+
+GLAPI void GLAPIENTRY glReadBuffer( GLenum mode );
+
+GLAPI void GLAPIENTRY glEnable( GLenum cap );
+
+GLAPI void GLAPIENTRY glDisable( GLenum cap );
+
+GLAPI GLboolean GLAPIENTRY glIsEnabled( GLenum cap );
+
+
+GLAPI void GLAPIENTRY glEnableClientState( GLenum cap ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glDisableClientState( GLenum cap ); /* 1.1 */
+
+
+GLAPI void GLAPIENTRY glGetBooleanv( GLenum pname, GLboolean *params );
+
+GLAPI void GLAPIENTRY glGetDoublev( GLenum pname, GLdouble *params );
+
+GLAPI void GLAPIENTRY glGetFloatv( GLenum pname, GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetIntegerv( GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glPushAttrib( GLbitfield mask );
+
+GLAPI void GLAPIENTRY glPopAttrib( void );
+
+
+GLAPI void GLAPIENTRY glPushClientAttrib( GLbitfield mask ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glPopClientAttrib( void ); /* 1.1 */
+
+
+GLAPI GLint GLAPIENTRY glRenderMode( GLenum mode );
+
+GLAPI GLenum GLAPIENTRY glGetError( void );
+
+GLAPI const GLubyte * GLAPIENTRY glGetString( GLenum name );
+
+GLAPI void GLAPIENTRY glFinish( void );
+
+GLAPI void GLAPIENTRY glFlush( void );
+
+GLAPI void GLAPIENTRY glHint( GLenum target, GLenum mode );
+
+
+/*
+ * Depth Buffer
+ */
+
+GLAPI void GLAPIENTRY glClearDepth( GLclampd depth );
+
+GLAPI void GLAPIENTRY glDepthFunc( GLenum func );
+
+GLAPI void GLAPIENTRY glDepthMask( GLboolean flag );
+
+GLAPI void GLAPIENTRY glDepthRange( GLclampd near_val, GLclampd far_val );
+
+
+/*
+ * Accumulation Buffer
+ */
+
+GLAPI void GLAPIENTRY glClearAccum( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha );
+
+GLAPI void GLAPIENTRY glAccum( GLenum op, GLfloat value );
+
+
+/*
+ * Transformation
+ */
+
+GLAPI void GLAPIENTRY glMatrixMode( GLenum mode );
+
+GLAPI void GLAPIENTRY glOrtho( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble near_val, GLdouble far_val );
+
+GLAPI void GLAPIENTRY glFrustum( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble near_val, GLdouble far_val );
+
+GLAPI void GLAPIENTRY glViewport( GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+GLAPI void GLAPIENTRY glPushMatrix( void );
+
+GLAPI void GLAPIENTRY glPopMatrix( void );
+
+GLAPI void GLAPIENTRY glLoadIdentity( void );
+
+GLAPI void GLAPIENTRY glLoadMatrixd( const GLdouble *m );
+GLAPI void GLAPIENTRY glLoadMatrixf( const GLfloat *m );
+
+GLAPI void GLAPIENTRY glMultMatrixd( const GLdouble *m );
+GLAPI void GLAPIENTRY glMultMatrixf( const GLfloat *m );
+
+GLAPI void GLAPIENTRY glRotated( GLdouble angle,
+ GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glRotatef( GLfloat angle,
+ GLfloat x, GLfloat y, GLfloat z );
+
+GLAPI void GLAPIENTRY glScaled( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glScalef( GLfloat x, GLfloat y, GLfloat z );
+
+GLAPI void GLAPIENTRY glTranslated( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glTranslatef( GLfloat x, GLfloat y, GLfloat z );
+
+
+/*
+ * Display Lists
+ */
+
+GLAPI GLboolean GLAPIENTRY glIsList( GLuint list );
+
+GLAPI void GLAPIENTRY glDeleteLists( GLuint list, GLsizei range );
+
+GLAPI GLuint GLAPIENTRY glGenLists( GLsizei range );
+
+GLAPI void GLAPIENTRY glNewList( GLuint list, GLenum mode );
+
+GLAPI void GLAPIENTRY glEndList( void );
+
+GLAPI void GLAPIENTRY glCallList( GLuint list );
+
+GLAPI void GLAPIENTRY glCallLists( GLsizei n, GLenum type,
+ const GLvoid *lists );
+
+GLAPI void GLAPIENTRY glListBase( GLuint base );
+
+
+/*
+ * Drawing Functions
+ */
+
+GLAPI void GLAPIENTRY glBegin( GLenum mode );
+
+GLAPI void GLAPIENTRY glEnd( void );
+
+
+GLAPI void GLAPIENTRY glVertex2d( GLdouble x, GLdouble y );
+GLAPI void GLAPIENTRY glVertex2f( GLfloat x, GLfloat y );
+GLAPI void GLAPIENTRY glVertex2i( GLint x, GLint y );
+GLAPI void GLAPIENTRY glVertex2s( GLshort x, GLshort y );
+
+GLAPI void GLAPIENTRY glVertex3d( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glVertex3f( GLfloat x, GLfloat y, GLfloat z );
+GLAPI void GLAPIENTRY glVertex3i( GLint x, GLint y, GLint z );
+GLAPI void GLAPIENTRY glVertex3s( GLshort x, GLshort y, GLshort z );
+
+GLAPI void GLAPIENTRY glVertex4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w );
+GLAPI void GLAPIENTRY glVertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+GLAPI void GLAPIENTRY glVertex4i( GLint x, GLint y, GLint z, GLint w );
+GLAPI void GLAPIENTRY glVertex4s( GLshort x, GLshort y, GLshort z, GLshort w );
+
+GLAPI void GLAPIENTRY glVertex2dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glVertex2fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glVertex2iv( const GLint *v );
+GLAPI void GLAPIENTRY glVertex2sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glVertex3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glVertex3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glVertex3iv( const GLint *v );
+GLAPI void GLAPIENTRY glVertex3sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glVertex4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glVertex4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glVertex4iv( const GLint *v );
+GLAPI void GLAPIENTRY glVertex4sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glNormal3b( GLbyte nx, GLbyte ny, GLbyte nz );
+GLAPI void GLAPIENTRY glNormal3d( GLdouble nx, GLdouble ny, GLdouble nz );
+GLAPI void GLAPIENTRY glNormal3f( GLfloat nx, GLfloat ny, GLfloat nz );
+GLAPI void GLAPIENTRY glNormal3i( GLint nx, GLint ny, GLint nz );
+GLAPI void GLAPIENTRY glNormal3s( GLshort nx, GLshort ny, GLshort nz );
+
+GLAPI void GLAPIENTRY glNormal3bv( const GLbyte *v );
+GLAPI void GLAPIENTRY glNormal3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glNormal3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glNormal3iv( const GLint *v );
+GLAPI void GLAPIENTRY glNormal3sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glIndexd( GLdouble c );
+GLAPI void GLAPIENTRY glIndexf( GLfloat c );
+GLAPI void GLAPIENTRY glIndexi( GLint c );
+GLAPI void GLAPIENTRY glIndexs( GLshort c );
+GLAPI void GLAPIENTRY glIndexub( GLubyte c ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glIndexdv( const GLdouble *c );
+GLAPI void GLAPIENTRY glIndexfv( const GLfloat *c );
+GLAPI void GLAPIENTRY glIndexiv( const GLint *c );
+GLAPI void GLAPIENTRY glIndexsv( const GLshort *c );
+GLAPI void GLAPIENTRY glIndexubv( const GLubyte *c ); /* 1.1 */
+
+GLAPI void GLAPIENTRY glColor3b( GLbyte red, GLbyte green, GLbyte blue );
+GLAPI void GLAPIENTRY glColor3d( GLdouble red, GLdouble green, GLdouble blue );
+GLAPI void GLAPIENTRY glColor3f( GLfloat red, GLfloat green, GLfloat blue );
+GLAPI void GLAPIENTRY glColor3i( GLint red, GLint green, GLint blue );
+GLAPI void GLAPIENTRY glColor3s( GLshort red, GLshort green, GLshort blue );
+GLAPI void GLAPIENTRY glColor3ub( GLubyte red, GLubyte green, GLubyte blue );
+GLAPI void GLAPIENTRY glColor3ui( GLuint red, GLuint green, GLuint blue );
+GLAPI void GLAPIENTRY glColor3us( GLushort red, GLushort green, GLushort blue );
+
+GLAPI void GLAPIENTRY glColor4b( GLbyte red, GLbyte green,
+ GLbyte blue, GLbyte alpha );
+GLAPI void GLAPIENTRY glColor4d( GLdouble red, GLdouble green,
+ GLdouble blue, GLdouble alpha );
+GLAPI void GLAPIENTRY glColor4f( GLfloat red, GLfloat green,
+ GLfloat blue, GLfloat alpha );
+GLAPI void GLAPIENTRY glColor4i( GLint red, GLint green,
+ GLint blue, GLint alpha );
+GLAPI void GLAPIENTRY glColor4s( GLshort red, GLshort green,
+ GLshort blue, GLshort alpha );
+GLAPI void GLAPIENTRY glColor4ub( GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha );
+GLAPI void GLAPIENTRY glColor4ui( GLuint red, GLuint green,
+ GLuint blue, GLuint alpha );
+GLAPI void GLAPIENTRY glColor4us( GLushort red, GLushort green,
+ GLushort blue, GLushort alpha );
+
+
+GLAPI void GLAPIENTRY glColor3bv( const GLbyte *v );
+GLAPI void GLAPIENTRY glColor3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glColor3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glColor3iv( const GLint *v );
+GLAPI void GLAPIENTRY glColor3sv( const GLshort *v );
+GLAPI void GLAPIENTRY glColor3ubv( const GLubyte *v );
+GLAPI void GLAPIENTRY glColor3uiv( const GLuint *v );
+GLAPI void GLAPIENTRY glColor3usv( const GLushort *v );
+
+GLAPI void GLAPIENTRY glColor4bv( const GLbyte *v );
+GLAPI void GLAPIENTRY glColor4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glColor4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glColor4iv( const GLint *v );
+GLAPI void GLAPIENTRY glColor4sv( const GLshort *v );
+GLAPI void GLAPIENTRY glColor4ubv( const GLubyte *v );
+GLAPI void GLAPIENTRY glColor4uiv( const GLuint *v );
+GLAPI void GLAPIENTRY glColor4usv( const GLushort *v );
+
+
+GLAPI void GLAPIENTRY glTexCoord1d( GLdouble s );
+GLAPI void GLAPIENTRY glTexCoord1f( GLfloat s );
+GLAPI void GLAPIENTRY glTexCoord1i( GLint s );
+GLAPI void GLAPIENTRY glTexCoord1s( GLshort s );
+
+GLAPI void GLAPIENTRY glTexCoord2d( GLdouble s, GLdouble t );
+GLAPI void GLAPIENTRY glTexCoord2f( GLfloat s, GLfloat t );
+GLAPI void GLAPIENTRY glTexCoord2i( GLint s, GLint t );
+GLAPI void GLAPIENTRY glTexCoord2s( GLshort s, GLshort t );
+
+GLAPI void GLAPIENTRY glTexCoord3d( GLdouble s, GLdouble t, GLdouble r );
+GLAPI void GLAPIENTRY glTexCoord3f( GLfloat s, GLfloat t, GLfloat r );
+GLAPI void GLAPIENTRY glTexCoord3i( GLint s, GLint t, GLint r );
+GLAPI void GLAPIENTRY glTexCoord3s( GLshort s, GLshort t, GLshort r );
+
+GLAPI void GLAPIENTRY glTexCoord4d( GLdouble s, GLdouble t, GLdouble r, GLdouble q );
+GLAPI void GLAPIENTRY glTexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q );
+GLAPI void GLAPIENTRY glTexCoord4i( GLint s, GLint t, GLint r, GLint q );
+GLAPI void GLAPIENTRY glTexCoord4s( GLshort s, GLshort t, GLshort r, GLshort q );
+
+GLAPI void GLAPIENTRY glTexCoord1dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord1fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord1iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord1sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glTexCoord2dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord2fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord2iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord2sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glTexCoord3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord3iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord3sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glTexCoord4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glTexCoord4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glTexCoord4iv( const GLint *v );
+GLAPI void GLAPIENTRY glTexCoord4sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glRasterPos2d( GLdouble x, GLdouble y );
+GLAPI void GLAPIENTRY glRasterPos2f( GLfloat x, GLfloat y );
+GLAPI void GLAPIENTRY glRasterPos2i( GLint x, GLint y );
+GLAPI void GLAPIENTRY glRasterPos2s( GLshort x, GLshort y );
+
+GLAPI void GLAPIENTRY glRasterPos3d( GLdouble x, GLdouble y, GLdouble z );
+GLAPI void GLAPIENTRY glRasterPos3f( GLfloat x, GLfloat y, GLfloat z );
+GLAPI void GLAPIENTRY glRasterPos3i( GLint x, GLint y, GLint z );
+GLAPI void GLAPIENTRY glRasterPos3s( GLshort x, GLshort y, GLshort z );
+
+GLAPI void GLAPIENTRY glRasterPos4d( GLdouble x, GLdouble y, GLdouble z, GLdouble w );
+GLAPI void GLAPIENTRY glRasterPos4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+GLAPI void GLAPIENTRY glRasterPos4i( GLint x, GLint y, GLint z, GLint w );
+GLAPI void GLAPIENTRY glRasterPos4s( GLshort x, GLshort y, GLshort z, GLshort w );
+
+GLAPI void GLAPIENTRY glRasterPos2dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glRasterPos2fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glRasterPos2iv( const GLint *v );
+GLAPI void GLAPIENTRY glRasterPos2sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glRasterPos3dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glRasterPos3fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glRasterPos3iv( const GLint *v );
+GLAPI void GLAPIENTRY glRasterPos3sv( const GLshort *v );
+
+GLAPI void GLAPIENTRY glRasterPos4dv( const GLdouble *v );
+GLAPI void GLAPIENTRY glRasterPos4fv( const GLfloat *v );
+GLAPI void GLAPIENTRY glRasterPos4iv( const GLint *v );
+GLAPI void GLAPIENTRY glRasterPos4sv( const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glRectd( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 );
+GLAPI void GLAPIENTRY glRectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 );
+GLAPI void GLAPIENTRY glRecti( GLint x1, GLint y1, GLint x2, GLint y2 );
+GLAPI void GLAPIENTRY glRects( GLshort x1, GLshort y1, GLshort x2, GLshort y2 );
+
+
+GLAPI void GLAPIENTRY glRectdv( const GLdouble *v1, const GLdouble *v2 );
+GLAPI void GLAPIENTRY glRectfv( const GLfloat *v1, const GLfloat *v2 );
+GLAPI void GLAPIENTRY glRectiv( const GLint *v1, const GLint *v2 );
+GLAPI void GLAPIENTRY glRectsv( const GLshort *v1, const GLshort *v2 );
+
+
+/*
+ * Vertex Arrays (1.1)
+ */
+
+GLAPI void GLAPIENTRY glVertexPointer( GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glNormalPointer( GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glColorPointer( GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glIndexPointer( GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glTexCoordPointer( GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glEdgeFlagPointer( GLsizei stride, const GLvoid *ptr );
+
+GLAPI void GLAPIENTRY glGetPointerv( GLenum pname, GLvoid **params );
+
+GLAPI void GLAPIENTRY glArrayElement( GLint i );
+
+GLAPI void GLAPIENTRY glDrawArrays( GLenum mode, GLint first, GLsizei count );
+
+GLAPI void GLAPIENTRY glDrawElements( GLenum mode, GLsizei count,
+ GLenum type, const GLvoid *indices );
+
+GLAPI void GLAPIENTRY glInterleavedArrays( GLenum format, GLsizei stride,
+ const GLvoid *pointer );
+
+/*
+ * Lighting
+ */
+
+GLAPI void GLAPIENTRY glShadeModel( GLenum mode );
+
+GLAPI void GLAPIENTRY glLightf( GLenum light, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glLighti( GLenum light, GLenum pname, GLint param );
+GLAPI void GLAPIENTRY glLightfv( GLenum light, GLenum pname,
+ const GLfloat *params );
+GLAPI void GLAPIENTRY glLightiv( GLenum light, GLenum pname,
+ const GLint *params );
+
+GLAPI void GLAPIENTRY glGetLightfv( GLenum light, GLenum pname,
+ GLfloat *params );
+GLAPI void GLAPIENTRY glGetLightiv( GLenum light, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glLightModelf( GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glLightModeli( GLenum pname, GLint param );
+GLAPI void GLAPIENTRY glLightModelfv( GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glLightModeliv( GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glMaterialf( GLenum face, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glMateriali( GLenum face, GLenum pname, GLint param );
+GLAPI void GLAPIENTRY glMaterialfv( GLenum face, GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glMaterialiv( GLenum face, GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glGetMaterialfv( GLenum face, GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetMaterialiv( GLenum face, GLenum pname, GLint *params );
+
+GLAPI void GLAPIENTRY glColorMaterial( GLenum face, GLenum mode );
+
+
+/*
+ * Raster functions
+ */
+
+GLAPI void GLAPIENTRY glPixelZoom( GLfloat xfactor, GLfloat yfactor );
+
+GLAPI void GLAPIENTRY glPixelStoref( GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glPixelStorei( GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glPixelTransferf( GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glPixelTransferi( GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glPixelMapfv( GLenum map, GLsizei mapsize,
+ const GLfloat *values );
+GLAPI void GLAPIENTRY glPixelMapuiv( GLenum map, GLsizei mapsize,
+ const GLuint *values );
+GLAPI void GLAPIENTRY glPixelMapusv( GLenum map, GLsizei mapsize,
+ const GLushort *values );
+
+GLAPI void GLAPIENTRY glGetPixelMapfv( GLenum map, GLfloat *values );
+GLAPI void GLAPIENTRY glGetPixelMapuiv( GLenum map, GLuint *values );
+GLAPI void GLAPIENTRY glGetPixelMapusv( GLenum map, GLushort *values );
+
+GLAPI void GLAPIENTRY glBitmap( GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig,
+ GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap );
+
+GLAPI void GLAPIENTRY glReadPixels( GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glDrawPixels( GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glCopyPixels( GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum type );
+
+/*
+ * Stenciling
+ */
+
+GLAPI void GLAPIENTRY glStencilFunc( GLenum func, GLint ref, GLuint mask );
+
+GLAPI void GLAPIENTRY glStencilMask( GLuint mask );
+
+GLAPI void GLAPIENTRY glStencilOp( GLenum fail, GLenum zfail, GLenum zpass );
+
+GLAPI void GLAPIENTRY glClearStencil( GLint s );
+
+
+
+/*
+ * Texture mapping
+ */
+
+GLAPI void GLAPIENTRY glTexGend( GLenum coord, GLenum pname, GLdouble param );
+GLAPI void GLAPIENTRY glTexGenf( GLenum coord, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glTexGeni( GLenum coord, GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glTexGendv( GLenum coord, GLenum pname, const GLdouble *params );
+GLAPI void GLAPIENTRY glTexGenfv( GLenum coord, GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glTexGeniv( GLenum coord, GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexGendv( GLenum coord, GLenum pname, GLdouble *params );
+GLAPI void GLAPIENTRY glGetTexGenfv( GLenum coord, GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetTexGeniv( GLenum coord, GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glTexEnvf( GLenum target, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glTexEnvi( GLenum target, GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glTexEnvfv( GLenum target, GLenum pname, const GLfloat *params );
+GLAPI void GLAPIENTRY glTexEnviv( GLenum target, GLenum pname, const GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetTexEnviv( GLenum target, GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glTexParameterf( GLenum target, GLenum pname, GLfloat param );
+GLAPI void GLAPIENTRY glTexParameteri( GLenum target, GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glTexParameterfv( GLenum target, GLenum pname,
+ const GLfloat *params );
+GLAPI void GLAPIENTRY glTexParameteriv( GLenum target, GLenum pname,
+ const GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexParameterfv( GLenum target,
+ GLenum pname, GLfloat *params);
+GLAPI void GLAPIENTRY glGetTexParameteriv( GLenum target,
+ GLenum pname, GLint *params );
+
+GLAPI void GLAPIENTRY glGetTexLevelParameterfv( GLenum target, GLint level,
+ GLenum pname, GLfloat *params );
+GLAPI void GLAPIENTRY glGetTexLevelParameteriv( GLenum target, GLint level,
+ GLenum pname, GLint *params );
+
+
+GLAPI void GLAPIENTRY glTexImage1D( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glTexImage2D( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glGetTexImage( GLenum target, GLint level,
+ GLenum format, GLenum type,
+ GLvoid *pixels );
+
+
+/* 1.1 functions */
+
+GLAPI void GLAPIENTRY glGenTextures( GLsizei n, GLuint *textures );
+
+GLAPI void GLAPIENTRY glDeleteTextures( GLsizei n, const GLuint *textures);
+
+GLAPI void GLAPIENTRY glBindTexture( GLenum target, GLuint texture );
+
+GLAPI void GLAPIENTRY glPrioritizeTextures( GLsizei n,
+ const GLuint *textures,
+ const GLclampf *priorities );
+
+GLAPI GLboolean GLAPIENTRY glAreTexturesResident( GLsizei n,
+ const GLuint *textures,
+ GLboolean *residences );
+
+GLAPI GLboolean GLAPIENTRY glIsTexture( GLuint texture );
+
+
+GLAPI void GLAPIENTRY glTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset,
+ GLsizei width, GLenum format,
+ GLenum type, const GLvoid *pixels );
+
+
+GLAPI void GLAPIENTRY glTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+GLAPI void GLAPIENTRY glCopyTexImage1D( GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLint border );
+
+
+GLAPI void GLAPIENTRY glCopyTexImage2D( GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLint border );
+
+
+GLAPI void GLAPIENTRY glCopyTexSubImage1D( GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y,
+ GLsizei width );
+
+
+GLAPI void GLAPIENTRY glCopyTexSubImage2D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+
+/*
+ * Evaluators
+ */
+
+GLAPI void GLAPIENTRY glMap1d( GLenum target, GLdouble u1, GLdouble u2,
+ GLint stride,
+ GLint order, const GLdouble *points );
+GLAPI void GLAPIENTRY glMap1f( GLenum target, GLfloat u1, GLfloat u2,
+ GLint stride,
+ GLint order, const GLfloat *points );
+
+GLAPI void GLAPIENTRY glMap2d( GLenum target,
+ GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
+ GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
+ const GLdouble *points );
+GLAPI void GLAPIENTRY glMap2f( GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points );
+
+GLAPI void GLAPIENTRY glGetMapdv( GLenum target, GLenum query, GLdouble *v );
+GLAPI void GLAPIENTRY glGetMapfv( GLenum target, GLenum query, GLfloat *v );
+GLAPI void GLAPIENTRY glGetMapiv( GLenum target, GLenum query, GLint *v );
+
+GLAPI void GLAPIENTRY glEvalCoord1d( GLdouble u );
+GLAPI void GLAPIENTRY glEvalCoord1f( GLfloat u );
+
+GLAPI void GLAPIENTRY glEvalCoord1dv( const GLdouble *u );
+GLAPI void GLAPIENTRY glEvalCoord1fv( const GLfloat *u );
+
+GLAPI void GLAPIENTRY glEvalCoord2d( GLdouble u, GLdouble v );
+GLAPI void GLAPIENTRY glEvalCoord2f( GLfloat u, GLfloat v );
+
+GLAPI void GLAPIENTRY glEvalCoord2dv( const GLdouble *u );
+GLAPI void GLAPIENTRY glEvalCoord2fv( const GLfloat *u );
+
+GLAPI void GLAPIENTRY glMapGrid1d( GLint un, GLdouble u1, GLdouble u2 );
+GLAPI void GLAPIENTRY glMapGrid1f( GLint un, GLfloat u1, GLfloat u2 );
+
+GLAPI void GLAPIENTRY glMapGrid2d( GLint un, GLdouble u1, GLdouble u2,
+ GLint vn, GLdouble v1, GLdouble v2 );
+GLAPI void GLAPIENTRY glMapGrid2f( GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 );
+
+GLAPI void GLAPIENTRY glEvalPoint1( GLint i );
+
+GLAPI void GLAPIENTRY glEvalPoint2( GLint i, GLint j );
+
+GLAPI void GLAPIENTRY glEvalMesh1( GLenum mode, GLint i1, GLint i2 );
+
+GLAPI void GLAPIENTRY glEvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 );
+
+
+/*
+ * Fog
+ */
+
+GLAPI void GLAPIENTRY glFogf( GLenum pname, GLfloat param );
+
+GLAPI void GLAPIENTRY glFogi( GLenum pname, GLint param );
+
+GLAPI void GLAPIENTRY glFogfv( GLenum pname, const GLfloat *params );
+
+GLAPI void GLAPIENTRY glFogiv( GLenum pname, const GLint *params );
+
+
+/*
+ * Selection and Feedback
+ */
+
+GLAPI void GLAPIENTRY glFeedbackBuffer( GLsizei size, GLenum type, GLfloat *buffer );
+
+GLAPI void GLAPIENTRY glPassThrough( GLfloat token );
+
+GLAPI void GLAPIENTRY glSelectBuffer( GLsizei size, GLuint *buffer );
+
+GLAPI void GLAPIENTRY glInitNames( void );
+
+GLAPI void GLAPIENTRY glLoadName( GLuint name );
+
+GLAPI void GLAPIENTRY glPushName( GLuint name );
+
+GLAPI void GLAPIENTRY glPopName( void );
+
+
+
+/*
+ * OpenGL 1.2
+ */
+
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_TEXTURE_BINDING_3D 0x806A
+
+GLAPI void GLAPIENTRY glDrawRangeElements( GLenum mode, GLuint start,
+ GLuint end, GLsizei count, GLenum type, const GLvoid *indices );
+
+GLAPI void GLAPIENTRY glTexImage3D( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLsizei depth, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+GLAPI void GLAPIENTRY glTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth,
+ GLenum format,
+ GLenum type, const GLvoid *pixels);
+
+GLAPI void GLAPIENTRY glCopyTexSubImage3D( GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint zoffset, GLint x,
+ GLint y, GLsizei width,
+ GLsizei height );
+
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+
+
+/*
+ * GL_ARB_imaging
+ */
+
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_BLEND_EQUATION 0x8009
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_BLEND_COLOR 0x8005
+
+
+GLAPI void GLAPIENTRY glColorTable( GLenum target, GLenum internalformat,
+ GLsizei width, GLenum format,
+ GLenum type, const GLvoid *table );
+
+GLAPI void GLAPIENTRY glColorSubTable( GLenum target,
+ GLsizei start, GLsizei count,
+ GLenum format, GLenum type,
+ const GLvoid *data );
+
+GLAPI void GLAPIENTRY glColorTableParameteriv(GLenum target, GLenum pname,
+ const GLint *params);
+
+GLAPI void GLAPIENTRY glColorTableParameterfv(GLenum target, GLenum pname,
+ const GLfloat *params);
+
+GLAPI void GLAPIENTRY glCopyColorSubTable( GLenum target, GLsizei start,
+ GLint x, GLint y, GLsizei width );
+
+GLAPI void GLAPIENTRY glCopyColorTable( GLenum target, GLenum internalformat,
+ GLint x, GLint y, GLsizei width );
+
+GLAPI void GLAPIENTRY glGetColorTable( GLenum target, GLenum format,
+ GLenum type, GLvoid *table );
+
+GLAPI void GLAPIENTRY glGetColorTableParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetColorTableParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glBlendEquation( GLenum mode );
+
+GLAPI void GLAPIENTRY glBlendColor( GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha );
+
+GLAPI void GLAPIENTRY glHistogram( GLenum target, GLsizei width,
+ GLenum internalformat, GLboolean sink );
+
+GLAPI void GLAPIENTRY glResetHistogram( GLenum target );
+
+GLAPI void GLAPIENTRY glGetHistogram( GLenum target, GLboolean reset,
+ GLenum format, GLenum type,
+ GLvoid *values );
+
+GLAPI void GLAPIENTRY glGetHistogramParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetHistogramParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glMinmax( GLenum target, GLenum internalformat,
+ GLboolean sink );
+
+GLAPI void GLAPIENTRY glResetMinmax( GLenum target );
+
+GLAPI void GLAPIENTRY glGetMinmax( GLenum target, GLboolean reset,
+ GLenum format, GLenum types,
+ GLvoid *values );
+
+GLAPI void GLAPIENTRY glGetMinmaxParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetMinmaxParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glConvolutionFilter1D( GLenum target,
+ GLenum internalformat, GLsizei width, GLenum format, GLenum type,
+ const GLvoid *image );
+
+GLAPI void GLAPIENTRY glConvolutionFilter2D( GLenum target,
+ GLenum internalformat, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid *image );
+
+GLAPI void GLAPIENTRY glConvolutionParameterf( GLenum target, GLenum pname,
+ GLfloat params );
+
+GLAPI void GLAPIENTRY glConvolutionParameterfv( GLenum target, GLenum pname,
+ const GLfloat *params );
+
+GLAPI void GLAPIENTRY glConvolutionParameteri( GLenum target, GLenum pname,
+ GLint params );
+
+GLAPI void GLAPIENTRY glConvolutionParameteriv( GLenum target, GLenum pname,
+ const GLint *params );
+
+GLAPI void GLAPIENTRY glCopyConvolutionFilter1D( GLenum target,
+ GLenum internalformat, GLint x, GLint y, GLsizei width );
+
+GLAPI void GLAPIENTRY glCopyConvolutionFilter2D( GLenum target,
+ GLenum internalformat, GLint x, GLint y, GLsizei width,
+ GLsizei height);
+
+GLAPI void GLAPIENTRY glGetConvolutionFilter( GLenum target, GLenum format,
+ GLenum type, GLvoid *image );
+
+GLAPI void GLAPIENTRY glGetConvolutionParameterfv( GLenum target, GLenum pname,
+ GLfloat *params );
+
+GLAPI void GLAPIENTRY glGetConvolutionParameteriv( GLenum target, GLenum pname,
+ GLint *params );
+
+GLAPI void GLAPIENTRY glSeparableFilter2D( GLenum target,
+ GLenum internalformat, GLsizei width, GLsizei height, GLenum format,
+ GLenum type, const GLvoid *row, const GLvoid *column );
+
+GLAPI void GLAPIENTRY glGetSeparableFilter( GLenum target, GLenum format,
+ GLenum type, GLvoid *row, GLvoid *column, GLvoid *span );
+
+
+
+
+/*
+ * OpenGL 1.3
+ */
+
+/* multitexture */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+/* texture_cube_map */
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+/* texture_compression */
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+/* multisample */
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_MULTISAMPLE_BIT 0x20000000
+/* transpose_matrix */
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+/* texture_env_combine */
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+/* texture_env_dot3 */
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+/* texture_border_clamp */
+#define GL_CLAMP_TO_BORDER 0x812D
+
+GLAPI void GLAPIENTRY glActiveTexture( GLenum texture );
+
+GLAPI void GLAPIENTRY glClientActiveTexture( GLenum texture );
+
+GLAPI void GLAPIENTRY glCompressedTexImage1D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexImage3D( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexSubImage1D( GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data );
+
+GLAPI void GLAPIENTRY glGetCompressedTexImage( GLenum target, GLint lod, GLvoid *img );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1d( GLenum target, GLdouble s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1f( GLenum target, GLfloat s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1i( GLenum target, GLint s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1s( GLenum target, GLshort s );
+
+GLAPI void GLAPIENTRY glMultiTexCoord1sv( GLenum target, const GLshort *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2d( GLenum target, GLdouble s, GLdouble t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2f( GLenum target, GLfloat s, GLfloat t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2i( GLenum target, GLint s, GLint t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2s( GLenum target, GLshort s, GLshort t );
+
+GLAPI void GLAPIENTRY glMultiTexCoord2sv( GLenum target, const GLshort *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3d( GLenum target, GLdouble s, GLdouble t, GLdouble r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, GLfloat r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3i( GLenum target, GLint s, GLint t, GLint r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3s( GLenum target, GLshort s, GLshort t, GLshort r );
+
+GLAPI void GLAPIENTRY glMultiTexCoord3sv( GLenum target, const GLshort *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4d( GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4dv( GLenum target, const GLdouble *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4fv( GLenum target, const GLfloat *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4i( GLenum target, GLint s, GLint t, GLint r, GLint q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4iv( GLenum target, const GLint *v );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4s( GLenum target, GLshort s, GLshort t, GLshort r, GLshort q );
+
+GLAPI void GLAPIENTRY glMultiTexCoord4sv( GLenum target, const GLshort *v );
+
+
+GLAPI void GLAPIENTRY glLoadTransposeMatrixd( const GLdouble m[16] );
+
+GLAPI void GLAPIENTRY glLoadTransposeMatrixf( const GLfloat m[16] );
+
+GLAPI void GLAPIENTRY glMultTransposeMatrixd( const GLdouble m[16] );
+
+GLAPI void GLAPIENTRY glMultTransposeMatrixf( const GLfloat m[16] );
+
+GLAPI void GLAPIENTRY glSampleCoverage( GLclampf value, GLboolean invert );
+
+
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, GLvoid *img);
+
+
+
+/*
+ * GL_ARB_multitexture (ARB extension 1 and OpenGL 1.2.1)
+ */
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+
+GLAPI void GLAPIENTRY glActiveTextureARB(GLenum texture);
+GLAPI void GLAPIENTRY glClientActiveTextureARB(GLenum texture);
+GLAPI void GLAPIENTRY glMultiTexCoord1dARB(GLenum target, GLdouble s);
+GLAPI void GLAPIENTRY glMultiTexCoord1dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord1fARB(GLenum target, GLfloat s);
+GLAPI void GLAPIENTRY glMultiTexCoord1fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord1iARB(GLenum target, GLint s);
+GLAPI void GLAPIENTRY glMultiTexCoord1ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord1sARB(GLenum target, GLshort s);
+GLAPI void GLAPIENTRY glMultiTexCoord1svARB(GLenum target, const GLshort *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2dARB(GLenum target, GLdouble s, GLdouble t);
+GLAPI void GLAPIENTRY glMultiTexCoord2dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t);
+GLAPI void GLAPIENTRY glMultiTexCoord2fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2iARB(GLenum target, GLint s, GLint t);
+GLAPI void GLAPIENTRY glMultiTexCoord2ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord2sARB(GLenum target, GLshort s, GLshort t);
+GLAPI void GLAPIENTRY glMultiTexCoord2svARB(GLenum target, const GLshort *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void GLAPIENTRY glMultiTexCoord3dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void GLAPIENTRY glMultiTexCoord3fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3iARB(GLenum target, GLint s, GLint t, GLint r);
+GLAPI void GLAPIENTRY glMultiTexCoord3ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord3sARB(GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void GLAPIENTRY glMultiTexCoord3svARB(GLenum target, const GLshort *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4dARB(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void GLAPIENTRY glMultiTexCoord4dvARB(GLenum target, const GLdouble *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void GLAPIENTRY glMultiTexCoord4fvARB(GLenum target, const GLfloat *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4iARB(GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void GLAPIENTRY glMultiTexCoord4ivARB(GLenum target, const GLint *v);
+GLAPI void GLAPIENTRY glMultiTexCoord4sARB(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void GLAPIENTRY glMultiTexCoord4svARB(GLenum target, const GLshort *v);
+
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+
+#endif /* GL_ARB_multitexture */
+
+
+
+/*
+ * Define this token if you want "old-style" header file behaviour (extensions
+ * defined in gl.h). Otherwise, extensions will be included from glext.h.
+ */
+#if !defined(NO_SDL_GLEXT) && !defined(GL_GLEXT_LEGACY)
+#include "SDL_opengl_glext.h"
+#endif /* GL_GLEXT_LEGACY */
+
+
+
+/*
+ * ???. GL_MESA_packed_depth_stencil
+ * XXX obsolete
+ */
+#ifndef GL_MESA_packed_depth_stencil
+#define GL_MESA_packed_depth_stencil 1
+
+#define GL_DEPTH_STENCIL_MESA 0x8750
+#define GL_UNSIGNED_INT_24_8_MESA 0x8751
+#define GL_UNSIGNED_INT_8_24_REV_MESA 0x8752
+#define GL_UNSIGNED_SHORT_15_1_MESA 0x8753
+#define GL_UNSIGNED_SHORT_1_15_REV_MESA 0x8754
+
+#endif /* GL_MESA_packed_depth_stencil */
+
+
+#ifndef GL_ATI_blend_equation_separate
+#define GL_ATI_blend_equation_separate 1
+
+#define GL_ALPHA_BLEND_EQUATION_ATI 0x883D
+
+GLAPI void GLAPIENTRY glBlendEquationSeparateATI( GLenum modeRGB, GLenum modeA );
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEATIPROC) (GLenum modeRGB, GLenum modeA);
+
+#endif /* GL_ATI_blend_equation_separate */
+
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GLAPI void APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+
+/**
+ ** NOTE!!!!! If you add new functions to this file, or update
+ ** glext.h be sure to regenerate the gl_mangle.h file. See comments
+ ** in that file for details.
+ **/
+
+
+
+/**********************************************************************
+ * Begin system-specific stuff
+ */
+#if defined(PRAGMA_EXPORT_SUPPORTED)
+#pragma export off
+#endif
+
+/*
+ * End system-specific stuff
+ **********************************************************************/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl_h_ */
+
+#endif /* !__IPHONEOS__ */
+
+#endif /* SDL_opengl_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengl_glext.h b/Client/ThirdParty/SDL2/include/SDL_opengl_glext.h
new file mode 100644
index 0000000..6a402b1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengl_glext.h
@@ -0,0 +1,11180 @@
+#ifndef __glext_h_
+#define __glext_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2014 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** http://www.opengl.org/registry/
+**
+** Khronos $Revision: 26745 $ on $Date: 2014-05-21 03:12:26 -0700 (Wed, 21 May 2014) $
+*/
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+
+#define GL_GLEXT_VERSION 20140521
+
+/* Generated C header for:
+ * API: gl
+ * Profile: compatibility
+ * Versions considered: .*
+ * Versions emitted: 1\.[2-9]|[234]\.[0-9]
+ * Default extensions included: gl
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GLAPI void APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_VERSION_1_2 */
+
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC) (GLenum target, GLint level, void *img);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC) (const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum texture);
+GLAPI void APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GLAPI void APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glGetCompressedTexImage (GLenum target, GLint level, void *img);
+GLAPI void APIENTRY glClientActiveTexture (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1d (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1f (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1i (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1s (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2i (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2s (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dv (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fv (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4i (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4iv (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4sv (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glLoadTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixd (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixf (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m);
+#endif
+#endif /* GL_VERSION_1_3 */
+
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC) (GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI void APIENTRY glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+GLAPI void APIENTRY glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+GLAPI void APIENTRY glPointParameterf (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glPointParameteri (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameteriv (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFogCoordf (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfv (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoordd (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddv (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointer (GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bv (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dv (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fv (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3i (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3iv (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3s (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3sv (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubv (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uiv (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3us (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usv (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glWindowPos2d (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2f (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2i (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos2s (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2sv (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3d (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dv (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3f (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fv (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3i (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3iv (const GLint *v);
+GLAPI void APIENTRY glWindowPos3s (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3sv (const GLshort *v);
+GLAPI void APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void APIENTRY glBlendEquation (GLenum mode);
+#endif
+#endif /* GL_VERSION_1_4 */
+
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+#include <stddef.h>
+#ifdef __MACOSX__
+typedef long GLsizeiptr;
+typedef long GLintptr;
+#else
+typedef ptrdiff_t GLsizeiptr;
+typedef ptrdiff_t GLintptr;
+#endif
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_COORD 0x8451
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC2_ALPHA 0x858A
+typedef void (APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQuery (GLuint id);
+GLAPI void APIENTRY glBeginQuery (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQuery (GLenum target);
+GLAPI void APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectiv (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBuffer (GLuint buffer);
+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI void APIENTRY glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI void *APIENTRY glMapBuffer (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBuffer (GLenum target);
+GLAPI void APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_VERSION_1_5 */
+
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+typedef char GLchar;
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_TEXTURE_COORDS 0x8871
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GLAPI void APIENTRY glCompileShader (GLuint shader);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum type);
+GLAPI void APIENTRY glDeleteProgram (GLuint program);
+GLAPI void APIENTRY glDeleteShader (GLuint shader);
+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
+GLAPI void APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GLAPI GLboolean APIENTRY glIsProgram (GLuint program);
+GLAPI GLboolean APIENTRY glIsShader (GLuint shader);
+GLAPI void APIENTRY glLinkProgram (GLuint program);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GLAPI void APIENTRY glUseProgram (GLuint program);
+GLAPI void APIENTRY glUniform1f (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glValidateProgram (GLuint program);
+GLAPI void APIENTRY glVertexAttrib1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1s (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2s (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nbv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4Niv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4Nsv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4Nubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4Nuiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4Nusv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_VERSION_2_0 */
+
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
+#endif /* GL_VERSION_2_1 */
+
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_INDEX 0x8222
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_ALPHA_INTEGER 0x8D97
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC) (GLenum target, GLenum clamp);
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI void APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glEnablei (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisablei (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GLAPI void APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedback (void);
+GLAPI void APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glClampColor (GLenum target, GLenum clamp);
+GLAPI void APIENTRY glBeginConditionalRender (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRender (void);
+GLAPI void APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glVertexAttribI1i (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2i (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3i (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1ui (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2ui (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3ui (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bv (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4sv (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubv (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usv (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocation (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1ui (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI void APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI void APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI void APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
+GLAPI GLboolean APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebuffer (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatus (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmap (GLenum target);
+GLAPI void APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI void APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void *APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glBindVertexArray (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArray (GLuint array);
+#endif
+#endif /* GL_VERSION_3_0 */
+
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC) (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GLAPI void APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GLAPI void APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glPrimitiveRestartIndex (GLuint index);
+GLAPI void APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GLAPI void APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformName (GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+GLAPI GLuint APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GLAPI void APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+#endif
+#endif /* GL_VERSION_3_1 */
+
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+typedef struct __GLsync *GLsync;
+#ifndef GLEXT_64_TYPES_DEFINED
+/* This code block is duplicated in glxext.h, so must be protected */
+#define GLEXT_64_TYPES_DEFINED
+/* Define int32_t, int64_t, and uint64_t types for UST/MSC */
+/* (as used in the GL_EXT_timer_query extension). */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+#elif defined(__sun__) || defined(__digital__)
+#include <inttypes.h>
+#if defined(__STDC__)
+#if defined(__arch64__) || defined(_LP64)
+typedef long int int64_t;
+typedef unsigned long int uint64_t;
+#else
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#endif /* __arch64__ */
+#endif /* __STDC__ */
+#elif defined( __VMS ) || defined(__sgi)
+#include <inttypes.h>
+#elif defined(__SCO__) || defined(__USLC__)
+#include <stdint.h>
+#elif defined(__UNIXOS2__) || defined(__SOL64__)
+typedef long int int32_t;
+typedef long long int int64_t;
+typedef unsigned long long int uint64_t;
+#elif defined(_WIN32) && defined(__GNUC__)
+#include <stdint.h>
+#elif defined(_WIN32)
+typedef __int32 int32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+/* Fallback if nothing above works */
+#include <inttypes.h>
+#endif
+#endif
+typedef uint64_t GLuint64;
+typedef int64_t GLint64;
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC) (GLenum mode);
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GLAPI void APIENTRY glMultiDrawElementsBaseVertex (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+GLAPI void APIENTRY glProvokingVertex (GLenum mode);
+GLAPI GLsync APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GLAPI GLboolean APIENTRY glIsSync (GLsync sync);
+GLAPI void APIENTRY glDeleteSync (GLsync sync);
+GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glTexImage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexImage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+#endif
+#endif /* GL_VERSION_3_2 */
+
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_SRC1_COLOR 0x88F9
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+#define GL_INT_2_10_10_10_REV 0x8D9F
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64 *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC) (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC) (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC) (GLenum type, GLuint value);
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC) (GLenum type, const GLuint *value);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC) (GLenum texture, GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC) (GLenum texture, GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC) (GLenum type, GLuint coords);
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC) (GLenum type, const GLuint *coords);
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC) (GLenum type, const GLuint *color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC) (GLenum type, GLuint color);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC) (GLenum type, const GLuint *color);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindFragDataLocationIndexed (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataIndex (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GLAPI GLboolean APIENTRY glIsSampler (GLuint sampler);
+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GLAPI void APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GLAPI void APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GLAPI void APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glQueryCounter (GLuint id, GLenum target);
+GLAPI void APIENTRY glGetQueryObjecti64v (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64v (GLuint id, GLenum pname, GLuint64 *params);
+GLAPI void APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GLAPI void APIENTRY glVertexAttribP1ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP1uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP2ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP2uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP3ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP3uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexAttribP4ui (GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI void APIENTRY glVertexAttribP4uiv (GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI void APIENTRY glVertexP2ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP2uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP3ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP3uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glVertexP4ui (GLenum type, GLuint value);
+GLAPI void APIENTRY glVertexP4uiv (GLenum type, const GLuint *value);
+GLAPI void APIENTRY glTexCoordP1ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP1uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP2ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP2uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glTexCoordP4ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glTexCoordP4uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP1ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP1uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP2ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP2uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP3ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP3uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glMultiTexCoordP4ui (GLenum texture, GLenum type, GLuint coords);
+GLAPI void APIENTRY glMultiTexCoordP4uiv (GLenum texture, GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glNormalP3ui (GLenum type, GLuint coords);
+GLAPI void APIENTRY glNormalP3uiv (GLenum type, const GLuint *coords);
+GLAPI void APIENTRY glColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP3uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glColorP4ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glColorP4uiv (GLenum type, const GLuint *color);
+GLAPI void APIENTRY glSecondaryColorP3ui (GLenum type, GLuint color);
+GLAPI void APIENTRY glSecondaryColorP3uiv (GLenum type, const GLuint *color);
+#endif
+#endif /* GL_VERSION_3_3 */
+
+#ifndef GL_VERSION_4_0
+#define GL_VERSION_4_0 1
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define GL_PATCHES 0x000E
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_ISOLINES 0x8E7A
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (APIENTRYP PFNGLUNIFORM1DPROC) (GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLUNIFORM2DPROC) (GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLUNIFORM3DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLUNIFORM4DPROC) (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLUNIFORM1DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM2DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM3DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORM4DVPROC) (GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3DVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, GLdouble *params);
+typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices);
+typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATCHPARAMETERFVPROC) (GLenum pname, const GLfloat *values);
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKPROC) (GLenum mode, GLuint id);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) (GLenum mode, GLuint id, GLuint stream);
+typedef void (APIENTRYP PFNGLBEGINQUERYINDEXEDPROC) (GLenum target, GLuint index, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYINDEXEDPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETQUERYINDEXEDIVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShading (GLfloat value);
+GLAPI void APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GLAPI void APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GLAPI void APIENTRY glUniform1d (GLint location, GLdouble x);
+GLAPI void APIENTRY glUniform2d (GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glUniform3d (GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glUniform4d (GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glUniform1dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform2dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform3dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniform4dv (GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix2x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix3x4dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x2dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glUniformMatrix4x3dv (GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *params);
+GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values);
+GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices);
+GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params);
+GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values);
+GLAPI void APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GLAPI void APIENTRY glPatchParameterfv (GLenum pname, const GLfloat *values);
+GLAPI void APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedback (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedback (void);
+GLAPI void APIENTRY glResumeTransformFeedback (void);
+GLAPI void APIENTRY glDrawTransformFeedback (GLenum mode, GLuint id);
+GLAPI void APIENTRY glDrawTransformFeedbackStream (GLenum mode, GLuint id, GLuint stream);
+GLAPI void APIENTRY glBeginQueryIndexed (GLenum target, GLuint index, GLuint id);
+GLAPI void APIENTRY glEndQueryIndexed (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pname, GLint *params);
+#endif
+#endif /* GL_VERSION_4_0 */
+
+#ifndef GL_VERSION_4_1
+#define GL_VERSION_4_1 1
+#define GL_FIXED 0x140C
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_RGB565 0x8D62
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_UNDEFINED_VERTEX 0x8260
+typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DPROC) (GLuint program, GLint location, GLdouble v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DPROC) (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLVIEWPORTARRAYVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (APIENTRYP PFNGLVIEWPORTINDEXEDFVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLSCISSORARRAYVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLSCISSORINDEXEDVPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYVPROC) (GLuint first, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDPROC) (GLuint index, GLdouble n, GLdouble f);
+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReleaseShaderCompiler (void);
+GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GLAPI void APIENTRY glClearDepthf (GLfloat d);
+GLAPI void APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GLAPI void APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GLAPI void APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GLAPI void APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GLAPI void APIENTRY glBindProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GLAPI void APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GLAPI GLboolean APIENTRY glIsProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1d (GLuint program, GLint location, GLdouble v0);
+GLAPI void APIENTRY glProgramUniform1dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2d (GLuint program, GLint location, GLdouble v0, GLdouble v1);
+GLAPI void APIENTRY glProgramUniform2dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2);
+GLAPI void APIENTRY glProgramUniform3dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4d (GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3);
+GLAPI void APIENTRY glProgramUniform4dv (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GLAPI void APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glVertexAttribL1d (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2d (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3d (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dv (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdv (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glViewportArrayv (GLuint first, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glViewportIndexedf (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GLAPI void APIENTRY glViewportIndexedfv (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glScissorArrayv (GLuint first, GLsizei count, const GLint *v);
+GLAPI void APIENTRY glScissorIndexed (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glScissorIndexedv (GLuint index, const GLint *v);
+GLAPI void APIENTRY glDepthRangeArrayv (GLuint first, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glDepthRangeIndexed (GLuint index, GLdouble n, GLdouble f);
+GLAPI void APIENTRY glGetFloati_v (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data);
+#endif
+#endif /* GL_VERSION_4_1 */
+
+#ifndef GL_VERSION_4_2
+#define GL_VERSION_4_2 1
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (APIENTRYP PFNGLTEXSTORAGE1DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) (GLenum mode, GLuint id, GLsizei instancecount);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params);
+GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers);
+GLAPI void APIENTRY glTexStorage1D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glDrawTransformFeedbackInstanced (GLenum mode, GLuint id, GLsizei instancecount);
+GLAPI void APIENTRY glDrawTransformFeedbackStreamInstanced (GLenum mode, GLuint id, GLuint stream, GLsizei instancecount);
+#endif
+#endif /* GL_VERSION_4_2 */
+
+#ifndef GL_VERSION_4_3
+#define GL_VERSION_4_3 1
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_MAX_WIDTH 0x827E
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_MIPMAP 0x8293
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_COLOR_ENCODING 0x8296
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_FILTER 0x829A
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_NAME_LENGTH 0x92F9
+#define GL_TYPE 0x92FA
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_OFFSET 0x92FC
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_DISPLAY_LIST 0x82E7
+typedef void (APIENTRYP PFNGLCLEARBUFFERDATAPROC) (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARBUFFERSUBDATAPROC) (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+typedef void (APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTUREVIEWPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearBufferData (GLenum target, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearBufferSubData (GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params);
+GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level);
+GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glInvalidateBufferData (GLuint buffer);
+GLAPI void APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GLAPI void APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glMultiDrawArraysIndirect (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding);
+GLAPI void APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureView (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+GLAPI void APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribLFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GLAPI void APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GLAPI void APIENTRY glPopDebugGroup (void);
+GLAPI void APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GLAPI void APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_VERSION_4_3 */
+
+#ifndef GL_VERSION_4_4
+#define GL_VERSION_4_4 1
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define GL_MAP_PERSISTENT_BIT 0x0040
+#define GL_MAP_COHERENT_BIT 0x0080
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+#define GL_CLEAR_TEXTURE 0x9365
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLBINDBUFFERSBASEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLBINDBUFFERSRANGEPROC) (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDSAMPLERSPROC) (GLuint first, GLsizei count, const GLuint *samplers);
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
+typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC) (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferStorage (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glClearTexImage (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glBindBuffersBase (GLenum target, GLuint first, GLsizei count, const GLuint *buffers);
+GLAPI void APIENTRY glBindBuffersRange (GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes);
+GLAPI void APIENTRY glBindTextures (GLuint first, GLsizei count, const GLuint *textures);
+GLAPI void APIENTRY glBindSamplers (GLuint first, GLsizei count, const GLuint *samplers);
+GLAPI void APIENTRY glBindImageTextures (GLuint first, GLsizei count, const GLuint *textures);
+GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizei *strides);
+#endif
+#endif /* GL_VERSION_4_4 */
+
+#ifndef GL_ARB_ES2_compatibility
+#define GL_ARB_ES2_compatibility 1
+#endif /* GL_ARB_ES2_compatibility */
+
+#ifndef GL_ARB_ES3_compatibility
+#define GL_ARB_ES3_compatibility 1
+#endif /* GL_ARB_ES3_compatibility */
+
+#ifndef GL_ARB_arrays_of_arrays
+#define GL_ARB_arrays_of_arrays 1
+#endif /* GL_ARB_arrays_of_arrays */
+
+#ifndef GL_ARB_base_instance
+#define GL_ARB_base_instance 1
+#endif /* GL_ARB_base_instance */
+
+#ifndef GL_ARB_bindless_texture
+#define GL_ARB_bindless_texture 1
+typedef uint64_t GLuint64EXT;
+#define GL_UNSIGNED_INT64_ARB 0x140F
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLEARBPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64ARBPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTARBPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64ARBPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VARBPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VARBPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleARB (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleARB (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentARB (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleARB (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentARB (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64ARB (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vARB (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64ARB (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentARB (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentARB (GLuint64 handle);
+GLAPI void APIENTRY glVertexAttribL1ui64ARB (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL1ui64vARB (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLui64vARB (GLuint index, GLenum pname, GLuint64EXT *params);
+#endif
+#endif /* GL_ARB_bindless_texture */
+
+#ifndef GL_ARB_blend_func_extended
+#define GL_ARB_blend_func_extended 1
+#endif /* GL_ARB_blend_func_extended */
+
+#ifndef GL_ARB_buffer_storage
+#define GL_ARB_buffer_storage 1
+#endif /* GL_ARB_buffer_storage */
+
+#ifndef GL_ARB_cl_event
+#define GL_ARB_cl_event 1
+struct _cl_context;
+struct _cl_event;
+#define GL_SYNC_CL_EVENT_ARB 0x8240
+#define GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+typedef GLsync (APIENTRYP PFNGLCREATESYNCFROMCLEVENTARBPROC) (struct _cl_context *context, struct _cl_event *event, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glCreateSyncFromCLeventARB (struct _cl_context *context, struct _cl_event *event, GLbitfield flags);
+#endif
+#endif /* GL_ARB_cl_event */
+
+#ifndef GL_ARB_clear_buffer_object
+#define GL_ARB_clear_buffer_object 1
+#endif /* GL_ARB_clear_buffer_object */
+
+#ifndef GL_ARB_clear_texture
+#define GL_ARB_clear_texture 1
+#endif /* GL_ARB_clear_texture */
+
+#ifndef GL_ARB_color_buffer_float
+#define GL_ARB_color_buffer_float 1
+#define GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define GL_CLAMP_READ_COLOR_ARB 0x891C
+#define GL_FIXED_ONLY_ARB 0x891D
+typedef void (APIENTRYP PFNGLCLAMPCOLORARBPROC) (GLenum target, GLenum clamp);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClampColorARB (GLenum target, GLenum clamp);
+#endif
+#endif /* GL_ARB_color_buffer_float */
+
+#ifndef GL_ARB_compatibility
+#define GL_ARB_compatibility 1
+#endif /* GL_ARB_compatibility */
+
+#ifndef GL_ARB_compressed_texture_pixel_storage
+#define GL_ARB_compressed_texture_pixel_storage 1
+#endif /* GL_ARB_compressed_texture_pixel_storage */
+
+#ifndef GL_ARB_compute_shader
+#define GL_ARB_compute_shader 1
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#endif /* GL_ARB_compute_shader */
+
+#ifndef GL_ARB_compute_variable_group_size
+#define GL_ARB_compute_variable_group_size 1
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344
+#define GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB
+#define GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345
+#define GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF
+typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEGROUPSIZEARBPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDispatchComputeGroupSizeARB (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z, GLuint group_size_x, GLuint group_size_y, GLuint group_size_z);
+#endif
+#endif /* GL_ARB_compute_variable_group_size */
+
+#ifndef GL_ARB_conservative_depth
+#define GL_ARB_conservative_depth 1
+#endif /* GL_ARB_conservative_depth */
+
+#ifndef GL_ARB_copy_buffer
+#define GL_ARB_copy_buffer 1
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#endif /* GL_ARB_copy_buffer */
+
+#ifndef GL_ARB_copy_image
+#define GL_ARB_copy_image 1
+#endif /* GL_ARB_copy_image */
+
+#ifndef GL_ARB_debug_output
+#define GL_ARB_debug_output 1
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define GL_DEBUG_SOURCE_API_ARB 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECONTROLARBPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTARBPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKARBPROC) (GLDEBUGPROCARB callback, const void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGARBPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageControlARB (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertARB (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackARB (GLDEBUGPROCARB callback, const void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogARB (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+#endif
+#endif /* GL_ARB_debug_output */
+
+#ifndef GL_ARB_depth_buffer_float
+#define GL_ARB_depth_buffer_float 1
+#endif /* GL_ARB_depth_buffer_float */
+
+#ifndef GL_ARB_depth_clamp
+#define GL_ARB_depth_clamp 1
+#endif /* GL_ARB_depth_clamp */
+
+#ifndef GL_ARB_depth_texture
+#define GL_ARB_depth_texture 1
+#define GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#endif /* GL_ARB_depth_texture */
+
+#ifndef GL_ARB_draw_buffers
+#define GL_ARB_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define GL_DRAW_BUFFER0_ARB 0x8825
+#define GL_DRAW_BUFFER1_ARB 0x8826
+#define GL_DRAW_BUFFER2_ARB 0x8827
+#define GL_DRAW_BUFFER3_ARB 0x8828
+#define GL_DRAW_BUFFER4_ARB 0x8829
+#define GL_DRAW_BUFFER5_ARB 0x882A
+#define GL_DRAW_BUFFER6_ARB 0x882B
+#define GL_DRAW_BUFFER7_ARB 0x882C
+#define GL_DRAW_BUFFER8_ARB 0x882D
+#define GL_DRAW_BUFFER9_ARB 0x882E
+#define GL_DRAW_BUFFER10_ARB 0x882F
+#define GL_DRAW_BUFFER11_ARB 0x8830
+#define GL_DRAW_BUFFER12_ARB 0x8831
+#define GL_DRAW_BUFFER13_ARB 0x8832
+#define GL_DRAW_BUFFER14_ARB 0x8833
+#define GL_DRAW_BUFFER15_ARB 0x8834
+typedef void (APIENTRYP PFNGLDRAWBUFFERSARBPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersARB (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_ARB_draw_buffers */
+
+#ifndef GL_ARB_draw_buffers_blend
+#define GL_ARB_draw_buffers_blend 1
+typedef void (APIENTRYP PFNGLBLENDEQUATIONIARBPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEIARBPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLBLENDFUNCIARBPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEIARBPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationiARB (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateiARB (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glBlendFunciARB (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateiARB (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+#endif
+#endif /* GL_ARB_draw_buffers_blend */
+
+#ifndef GL_ARB_draw_elements_base_vertex
+#define GL_ARB_draw_elements_base_vertex 1
+#endif /* GL_ARB_draw_elements_base_vertex */
+
+#ifndef GL_ARB_draw_indirect
+#define GL_ARB_draw_indirect 1
+#endif /* GL_ARB_draw_indirect */
+
+#ifndef GL_ARB_draw_instanced
+#define GL_ARB_draw_instanced 1
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDARBPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDARBPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedARB (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedARB (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_ARB_draw_instanced */
+
+#ifndef GL_ARB_enhanced_layouts
+#define GL_ARB_enhanced_layouts 1
+#endif /* GL_ARB_enhanced_layouts */
+
+#ifndef GL_ARB_explicit_attrib_location
+#define GL_ARB_explicit_attrib_location 1
+#endif /* GL_ARB_explicit_attrib_location */
+
+#ifndef GL_ARB_explicit_uniform_location
+#define GL_ARB_explicit_uniform_location 1
+#endif /* GL_ARB_explicit_uniform_location */
+
+#ifndef GL_ARB_fragment_coord_conventions
+#define GL_ARB_fragment_coord_conventions 1
+#endif /* GL_ARB_fragment_coord_conventions */
+
+#ifndef GL_ARB_fragment_layer_viewport
+#define GL_ARB_fragment_layer_viewport 1
+#endif /* GL_ARB_fragment_layer_viewport */
+
+#ifndef GL_ARB_fragment_program
+#define GL_ARB_fragment_program 1
+#define GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define GL_PROGRAM_LENGTH_ARB 0x8627
+#define GL_PROGRAM_FORMAT_ARB 0x8876
+#define GL_PROGRAM_BINDING_ARB 0x8677
+#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define GL_PROGRAM_STRING_ARB 0x8628
+#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define GL_CURRENT_MATRIX_ARB 0x8641
+#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define GL_MATRIX0_ARB 0x88C0
+#define GL_MATRIX1_ARB 0x88C1
+#define GL_MATRIX2_ARB 0x88C2
+#define GL_MATRIX3_ARB 0x88C3
+#define GL_MATRIX4_ARB 0x88C4
+#define GL_MATRIX5_ARB 0x88C5
+#define GL_MATRIX6_ARB 0x88C6
+#define GL_MATRIX7_ARB 0x88C7
+#define GL_MATRIX8_ARB 0x88C8
+#define GL_MATRIX9_ARB 0x88C9
+#define GL_MATRIX10_ARB 0x88CA
+#define GL_MATRIX11_ARB 0x88CB
+#define GL_MATRIX12_ARB 0x88CC
+#define GL_MATRIX13_ARB 0x88CD
+#define GL_MATRIX14_ARB 0x88CE
+#define GL_MATRIX15_ARB 0x88CF
+#define GL_MATRIX16_ARB 0x88D0
+#define GL_MATRIX17_ARB 0x88D1
+#define GL_MATRIX18_ARB 0x88D2
+#define GL_MATRIX19_ARB 0x88D3
+#define GL_MATRIX20_ARB 0x88D4
+#define GL_MATRIX21_ARB 0x88D5
+#define GL_MATRIX22_ARB 0x88D6
+#define GL_MATRIX23_ARB 0x88D7
+#define GL_MATRIX24_ARB 0x88D8
+#define GL_MATRIX25_ARB 0x88D9
+#define GL_MATRIX26_ARB 0x88DA
+#define GL_MATRIX27_ARB 0x88DB
+#define GL_MATRIX28_ARB 0x88DC
+#define GL_MATRIX29_ARB 0x88DD
+#define GL_MATRIX30_ARB 0x88DE
+#define GL_MATRIX31_ARB 0x88DF
+typedef void (APIENTRYP PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const void *string);
+typedef void (APIENTRYP PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, void *string);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMARBPROC) (GLuint program);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramStringARB (GLenum target, GLenum format, GLsizei len, const void *string);
+GLAPI void APIENTRY glBindProgramARB (GLenum target, GLuint program);
+GLAPI void APIENTRY glDeleteProgramsARB (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glGenProgramsARB (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glProgramEnvParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramEnvParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramEnvParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramEnvParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameter4dARB (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramLocalParameter4dvARB (GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glProgramLocalParameter4fARB (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramLocalParameter4fvARB (GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetProgramEnvParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramEnvParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramLocalParameterdvARB (GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetProgramLocalParameterfvARB (GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringARB (GLenum target, GLenum pname, void *string);
+GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
+#endif
+#endif /* GL_ARB_fragment_program */
+
+#ifndef GL_ARB_fragment_program_shadow
+#define GL_ARB_fragment_program_shadow 1
+#endif /* GL_ARB_fragment_program_shadow */
+
+#ifndef GL_ARB_fragment_shader
+#define GL_ARB_fragment_shader 1
+#define GL_FRAGMENT_SHADER_ARB 0x8B30
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#endif /* GL_ARB_fragment_shader */
+
+#ifndef GL_ARB_framebuffer_no_attachments
+#define GL_ARB_framebuffer_no_attachments 1
+#endif /* GL_ARB_framebuffer_no_attachments */
+
+#ifndef GL_ARB_framebuffer_object
+#define GL_ARB_framebuffer_object 1
+#endif /* GL_ARB_framebuffer_object */
+
+#ifndef GL_ARB_framebuffer_sRGB
+#define GL_ARB_framebuffer_sRGB 1
+#endif /* GL_ARB_framebuffer_sRGB */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+#endif /* GL_KHR_context_flush_control */
+
+#ifndef GL_ARB_geometry_shader4
+#define GL_ARB_geometry_shader4 1
+#define GL_LINES_ADJACENCY_ARB 0x000A
+#define GL_LINE_STRIP_ADJACENCY_ARB 0x000B
+#define GL_TRIANGLES_ADJACENCY_ARB 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
+#define GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIARBPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEARBPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriARB (GLuint program, GLenum pname, GLint value);
+GLAPI void APIENTRY glFramebufferTextureARB (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+#endif /* GL_ARB_geometry_shader4 */
+
+#ifndef GL_ARB_get_program_binary
+#define GL_ARB_get_program_binary 1
+#endif /* GL_ARB_get_program_binary */
+
+#ifndef GL_ARB_gpu_shader5
+#define GL_ARB_gpu_shader5 1
+#endif /* GL_ARB_gpu_shader5 */
+
+#ifndef GL_ARB_gpu_shader_fp64
+#define GL_ARB_gpu_shader_fp64 1
+#endif /* GL_ARB_gpu_shader_fp64 */
+
+#ifndef GL_ARB_half_float_pixel
+#define GL_ARB_half_float_pixel 1
+typedef unsigned short GLhalfARB;
+#define GL_HALF_FLOAT_ARB 0x140B
+#endif /* GL_ARB_half_float_pixel */
+
+#ifndef GL_ARB_half_float_vertex
+#define GL_ARB_half_float_vertex 1
+#endif /* GL_ARB_half_float_vertex */
+
+#ifndef GL_ARB_imaging
+#define GL_ARB_imaging 1
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_EQUATION 0x8009
+#define GL_CONVOLUTION_1D 0x8010
+#define GL_CONVOLUTION_2D 0x8011
+#define GL_SEPARABLE_2D 0x8012
+#define GL_CONVOLUTION_BORDER_MODE 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define GL_REDUCE 0x8016
+#define GL_CONVOLUTION_FORMAT 0x8017
+#define GL_CONVOLUTION_WIDTH 0x8018
+#define GL_CONVOLUTION_HEIGHT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define GL_HISTOGRAM 0x8024
+#define GL_PROXY_HISTOGRAM 0x8025
+#define GL_HISTOGRAM_WIDTH 0x8026
+#define GL_HISTOGRAM_FORMAT 0x8027
+#define GL_HISTOGRAM_RED_SIZE 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define GL_HISTOGRAM_SINK 0x802D
+#define GL_MINMAX 0x802E
+#define GL_MINMAX_FORMAT 0x802F
+#define GL_MINMAX_SINK 0x8030
+#define GL_TABLE_TOO_LARGE 0x8031
+#define GL_COLOR_MATRIX 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define GL_COLOR_TABLE 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define GL_PROXY_COLOR_TABLE 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define GL_COLOR_TABLE_SCALE 0x80D6
+#define GL_COLOR_TABLE_BIAS 0x80D7
+#define GL_COLOR_TABLE_FORMAT 0x80D8
+#define GL_COLOR_TABLE_WIDTH 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define GL_CONSTANT_BORDER 0x8151
+#define GL_REPLICATE_BORDER 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR 0x8154
+typedef void (APIENTRYP PFNGLCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLEPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPROC) (GLenum target, GLenum format, GLenum type, void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTERPROC) (GLenum target, GLenum format, GLenum type, void *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTERPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTable (GLenum target, GLenum format, GLenum type, void *table);
+GLAPI void APIENTRY glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteri (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, void *image);
+GLAPI void APIENTRY glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilter (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+GLAPI void APIENTRY glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+GLAPI void APIENTRY glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmax (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogram (GLenum target);
+GLAPI void APIENTRY glResetMinmax (GLenum target);
+#endif
+#endif /* GL_ARB_imaging */
+
+#ifndef GL_ARB_indirect_parameters
+#define GL_ARB_indirect_parameters 1
+#define GL_PARAMETER_BUFFER_ARB 0x80EE
+#define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
+#endif
+#endif /* GL_ARB_indirect_parameters */
+
+#ifndef GL_ARB_instanced_arrays
+#define GL_ARB_instanced_arrays 1
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORARBPROC) (GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor);
+#endif
+#endif /* GL_ARB_instanced_arrays */
+
+#ifndef GL_ARB_internalformat_query
+#define GL_ARB_internalformat_query 1
+#endif /* GL_ARB_internalformat_query */
+
+#ifndef GL_ARB_internalformat_query2
+#define GL_ARB_internalformat_query2 1
+#define GL_SRGB_DECODE_ARB 0x8299
+#endif /* GL_ARB_internalformat_query2 */
+
+#ifndef GL_ARB_invalidate_subdata
+#define GL_ARB_invalidate_subdata 1
+#endif /* GL_ARB_invalidate_subdata */
+
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_ARB_map_buffer_alignment 1
+#endif /* GL_ARB_map_buffer_alignment */
+
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+#endif /* GL_ARB_map_buffer_range */
+
+#ifndef GL_ARB_matrix_palette
+#define GL_ARB_matrix_palette 1
+#define GL_MATRIX_PALETTE_ARB 0x8840
+#define GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+typedef void (APIENTRYP PFNGLCURRENTPALETTEMATRIXARBPROC) (GLint index);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUBVARBPROC) (GLint size, const GLubyte *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUSVARBPROC) (GLint size, const GLushort *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXUIVARBPROC) (GLint size, const GLuint *indices);
+typedef void (APIENTRYP PFNGLMATRIXINDEXPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCurrentPaletteMatrixARB (GLint index);
+GLAPI void APIENTRY glMatrixIndexubvARB (GLint size, const GLubyte *indices);
+GLAPI void APIENTRY glMatrixIndexusvARB (GLint size, const GLushort *indices);
+GLAPI void APIENTRY glMatrixIndexuivARB (GLint size, const GLuint *indices);
+GLAPI void APIENTRY glMatrixIndexPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_ARB_matrix_palette */
+
+#ifndef GL_ARB_multi_bind
+#define GL_ARB_multi_bind 1
+#endif /* GL_ARB_multi_bind */
+
+#ifndef GL_ARB_multi_draw_indirect
+#define GL_ARB_multi_draw_indirect 1
+#endif /* GL_ARB_multi_draw_indirect */
+
+#ifndef GL_ARB_multisample
+#define GL_ARB_multisample 1
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEARBPROC) (GLfloat value, GLboolean invert);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleCoverageARB (GLfloat value, GLboolean invert);
+#endif
+#endif /* GL_ARB_multisample */
+
+#ifndef GL_ARB_multitexture
+#define GL_ARB_multitexture 1
+#define GL_TEXTURE0_ARB 0x84C0
+#define GL_TEXTURE1_ARB 0x84C1
+#define GL_TEXTURE2_ARB 0x84C2
+#define GL_TEXTURE3_ARB 0x84C3
+#define GL_TEXTURE4_ARB 0x84C4
+#define GL_TEXTURE5_ARB 0x84C5
+#define GL_TEXTURE6_ARB 0x84C6
+#define GL_TEXTURE7_ARB 0x84C7
+#define GL_TEXTURE8_ARB 0x84C8
+#define GL_TEXTURE9_ARB 0x84C9
+#define GL_TEXTURE10_ARB 0x84CA
+#define GL_TEXTURE11_ARB 0x84CB
+#define GL_TEXTURE12_ARB 0x84CC
+#define GL_TEXTURE13_ARB 0x84CD
+#define GL_TEXTURE14_ARB 0x84CE
+#define GL_TEXTURE15_ARB 0x84CF
+#define GL_TEXTURE16_ARB 0x84D0
+#define GL_TEXTURE17_ARB 0x84D1
+#define GL_TEXTURE18_ARB 0x84D2
+#define GL_TEXTURE19_ARB 0x84D3
+#define GL_TEXTURE20_ARB 0x84D4
+#define GL_TEXTURE21_ARB 0x84D5
+#define GL_TEXTURE22_ARB 0x84D6
+#define GL_TEXTURE23_ARB 0x84D7
+#define GL_TEXTURE24_ARB 0x84D8
+#define GL_TEXTURE25_ARB 0x84D9
+#define GL_TEXTURE26_ARB 0x84DA
+#define GL_TEXTURE27_ARB 0x84DB
+#define GL_TEXTURE28_ARB 0x84DC
+#define GL_TEXTURE29_ARB 0x84DD
+#define GL_TEXTURE30_ARB 0x84DE
+#define GL_TEXTURE31_ARB 0x84DF
+#define GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+typedef void (APIENTRYP PFNGLACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREARBPROC) (GLenum texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FARBPROC) (GLenum target, GLfloat s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IARBPROC) (GLenum target, GLint s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SARBPROC) (GLenum target, GLshort s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DARBPROC) (GLenum target, GLdouble s, GLdouble t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FARBPROC) (GLenum target, GLfloat s, GLfloat t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IARBPROC) (GLenum target, GLint s, GLint t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SARBPROC) (GLenum target, GLshort s, GLshort t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IARBPROC) (GLenum target, GLint s, GLint t, GLint r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVARBPROC) (GLenum target, const GLshort *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DARBPROC) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVARBPROC) (GLenum target, const GLdouble *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FARBPROC) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVARBPROC) (GLenum target, const GLfloat *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IARBPROC) (GLenum target, GLint s, GLint t, GLint r, GLint q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVARBPROC) (GLenum target, const GLint *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SARBPROC) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVARBPROC) (GLenum target, const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glClientActiveTextureARB (GLenum texture);
+GLAPI void APIENTRY glMultiTexCoord1dARB (GLenum target, GLdouble s);
+GLAPI void APIENTRY glMultiTexCoord1dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord1fARB (GLenum target, GLfloat s);
+GLAPI void APIENTRY glMultiTexCoord1fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord1iARB (GLenum target, GLint s);
+GLAPI void APIENTRY glMultiTexCoord1ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord1sARB (GLenum target, GLshort s);
+GLAPI void APIENTRY glMultiTexCoord1svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord2dARB (GLenum target, GLdouble s, GLdouble t);
+GLAPI void APIENTRY glMultiTexCoord2dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord2fARB (GLenum target, GLfloat s, GLfloat t);
+GLAPI void APIENTRY glMultiTexCoord2fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord2iARB (GLenum target, GLint s, GLint t);
+GLAPI void APIENTRY glMultiTexCoord2ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord2sARB (GLenum target, GLshort s, GLshort t);
+GLAPI void APIENTRY glMultiTexCoord2svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord3dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI void APIENTRY glMultiTexCoord3dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord3fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI void APIENTRY glMultiTexCoord3fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord3iARB (GLenum target, GLint s, GLint t, GLint r);
+GLAPI void APIENTRY glMultiTexCoord3ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord3sARB (GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI void APIENTRY glMultiTexCoord3svARB (GLenum target, const GLshort *v);
+GLAPI void APIENTRY glMultiTexCoord4dARB (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI void APIENTRY glMultiTexCoord4dvARB (GLenum target, const GLdouble *v);
+GLAPI void APIENTRY glMultiTexCoord4fARB (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI void APIENTRY glMultiTexCoord4fvARB (GLenum target, const GLfloat *v);
+GLAPI void APIENTRY glMultiTexCoord4iARB (GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI void APIENTRY glMultiTexCoord4ivARB (GLenum target, const GLint *v);
+GLAPI void APIENTRY glMultiTexCoord4sARB (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI void APIENTRY glMultiTexCoord4svARB (GLenum target, const GLshort *v);
+#endif
+#endif /* GL_ARB_multitexture */
+
+#ifndef GL_ARB_occlusion_query
+#define GL_ARB_occlusion_query 1
+#define GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define GL_CURRENT_QUERY_ARB 0x8865
+#define GL_QUERY_RESULT_ARB 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define GL_SAMPLES_PASSED_ARB 0x8914
+typedef void (APIENTRYP PFNGLGENQUERIESARBPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEQUERIESARBPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISQUERYARBPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINQUERYARBPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLENDQUERYARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETQUERYIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVARBPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVARBPROC) (GLuint id, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenQueriesARB (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteQueriesARB (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsQueryARB (GLuint id);
+GLAPI void APIENTRY glBeginQueryARB (GLenum target, GLuint id);
+GLAPI void APIENTRY glEndQueryARB (GLenum target);
+GLAPI void APIENTRY glGetQueryivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectivARB (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_ARB_occlusion_query */
+
+#ifndef GL_ARB_occlusion_query2
+#define GL_ARB_occlusion_query2 1
+#endif /* GL_ARB_occlusion_query2 */
+
+#ifndef GL_ARB_pixel_buffer_object
+#define GL_ARB_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#endif /* GL_ARB_pixel_buffer_object */
+
+#ifndef GL_ARB_point_parameters
+#define GL_ARB_point_parameters 1
+#define GL_POINT_SIZE_MIN_ARB 0x8126
+#define GL_POINT_SIZE_MAX_ARB 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFARBPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVARBPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfARB (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_ARB_point_parameters */
+
+#ifndef GL_ARB_point_sprite
+#define GL_ARB_point_sprite 1
+#define GL_POINT_SPRITE_ARB 0x8861
+#define GL_COORD_REPLACE_ARB 0x8862
+#endif /* GL_ARB_point_sprite */
+
+#ifndef GL_ARB_program_interface_query
+#define GL_ARB_program_interface_query 1
+#endif /* GL_ARB_program_interface_query */
+
+#ifndef GL_ARB_provoking_vertex
+#define GL_ARB_provoking_vertex 1
+#endif /* GL_ARB_provoking_vertex */
+
+#ifndef GL_ARB_query_buffer_object
+#define GL_ARB_query_buffer_object 1
+#endif /* GL_ARB_query_buffer_object */
+
+#ifndef GL_ARB_robust_buffer_access_behavior
+#define GL_ARB_robust_buffer_access_behavior 1
+#endif /* GL_ARB_robust_buffer_access_behavior */
+
+#ifndef GL_ARB_robustness
+#define GL_ARB_robustness 1
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSARBPROC) (void);
+typedef void (APIENTRYP PFNGLGETNTEXIMAGEARBPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img);
+typedef void (APIENTRYP PFNGLREADNPIXELSARBPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, GLsizei bufSize, void *img);
+typedef void (APIENTRYP PFNGLGETNUNIFORMFVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMUIVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (APIENTRYP PFNGLGETNUNIFORMDVARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNMAPDVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+typedef void (APIENTRYP PFNGLGETNMAPFVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+typedef void (APIENTRYP PFNGLGETNMAPIVARBPROC) (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPFVARBPROC) (GLenum map, GLsizei bufSize, GLfloat *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVARBPROC) (GLenum map, GLsizei bufSize, GLuint *values);
+typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVARBPROC) (GLenum map, GLsizei bufSize, GLushort *values);
+typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEARBPROC) (GLsizei bufSize, GLubyte *pattern);
+typedef void (APIENTRYP PFNGLGETNCOLORTABLEARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERARBPROC) (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+typedef void (APIENTRYP PFNGLGETNHISTOGRAMARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+typedef void (APIENTRYP PFNGLGETNMINMAXARBPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glGetGraphicsResetStatusARB (void);
+GLAPI void APIENTRY glGetnTexImageARB (GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *img);
+GLAPI void APIENTRY glReadnPixelsARB (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GLAPI void APIENTRY glGetnCompressedTexImageARB (GLenum target, GLint lod, GLsizei bufSize, void *img);
+GLAPI void APIENTRY glGetnUniformfvARB (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GLAPI void APIENTRY glGetnUniformivARB (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GLAPI void APIENTRY glGetnUniformuivARB (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GLAPI void APIENTRY glGetnUniformdvARB (GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
+GLAPI void APIENTRY glGetnMapdvARB (GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
+GLAPI void APIENTRY glGetnMapfvARB (GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
+GLAPI void APIENTRY glGetnMapivARB (GLenum target, GLenum query, GLsizei bufSize, GLint *v);
+GLAPI void APIENTRY glGetnPixelMapfvARB (GLenum map, GLsizei bufSize, GLfloat *values);
+GLAPI void APIENTRY glGetnPixelMapuivARB (GLenum map, GLsizei bufSize, GLuint *values);
+GLAPI void APIENTRY glGetnPixelMapusvARB (GLenum map, GLsizei bufSize, GLushort *values);
+GLAPI void APIENTRY glGetnPolygonStippleARB (GLsizei bufSize, GLubyte *pattern);
+GLAPI void APIENTRY glGetnColorTableARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
+GLAPI void APIENTRY glGetnConvolutionFilterARB (GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
+GLAPI void APIENTRY glGetnSeparableFilterARB (GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
+GLAPI void APIENTRY glGetnHistogramARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
+#endif
+#endif /* GL_ARB_robustness */
+
+#ifndef GL_ARB_robustness_isolation
+#define GL_ARB_robustness_isolation 1
+#endif /* GL_ARB_robustness_isolation */
+
+#ifndef GL_ARB_sample_shading
+#define GL_ARB_sample_shading 1
+#define GL_SAMPLE_SHADING_ARB 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+typedef void (APIENTRYP PFNGLMINSAMPLESHADINGARBPROC) (GLfloat value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value);
+#endif
+#endif /* GL_ARB_sample_shading */
+
+#ifndef GL_ARB_sampler_objects
+#define GL_ARB_sampler_objects 1
+#endif /* GL_ARB_sampler_objects */
+
+#ifndef GL_ARB_seamless_cube_map
+#define GL_ARB_seamless_cube_map 1
+#endif /* GL_ARB_seamless_cube_map */
+
+#ifndef GL_ARB_seamless_cubemap_per_texture
+#define GL_ARB_seamless_cubemap_per_texture 1
+#endif /* GL_ARB_seamless_cubemap_per_texture */
+
+#ifndef GL_ARB_separate_shader_objects
+#define GL_ARB_separate_shader_objects 1
+#endif /* GL_ARB_separate_shader_objects */
+
+#ifndef GL_ARB_shader_atomic_counters
+#define GL_ARB_shader_atomic_counters 1
+#endif /* GL_ARB_shader_atomic_counters */
+
+#ifndef GL_ARB_shader_bit_encoding
+#define GL_ARB_shader_bit_encoding 1
+#endif /* GL_ARB_shader_bit_encoding */
+
+#ifndef GL_ARB_shader_draw_parameters
+#define GL_ARB_shader_draw_parameters 1
+#endif /* GL_ARB_shader_draw_parameters */
+
+#ifndef GL_ARB_shader_group_vote
+#define GL_ARB_shader_group_vote 1
+#endif /* GL_ARB_shader_group_vote */
+
+#ifndef GL_ARB_shader_image_load_store
+#define GL_ARB_shader_image_load_store 1
+#endif /* GL_ARB_shader_image_load_store */
+
+#ifndef GL_ARB_shader_image_size
+#define GL_ARB_shader_image_size 1
+#endif /* GL_ARB_shader_image_size */
+
+#ifndef GL_ARB_shader_objects
+#define GL_ARB_shader_objects 1
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef char GLcharARB;
+#define GL_PROGRAM_OBJECT_ARB 0x8B40
+#define GL_SHADER_OBJECT_ARB 0x8B48
+#define GL_OBJECT_TYPE_ARB 0x8B4E
+#define GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define GL_FLOAT_VEC2_ARB 0x8B50
+#define GL_FLOAT_VEC3_ARB 0x8B51
+#define GL_FLOAT_VEC4_ARB 0x8B52
+#define GL_INT_VEC2_ARB 0x8B53
+#define GL_INT_VEC3_ARB 0x8B54
+#define GL_INT_VEC4_ARB 0x8B55
+#define GL_BOOL_ARB 0x8B56
+#define GL_BOOL_VEC2_ARB 0x8B57
+#define GL_BOOL_VEC3_ARB 0x8B58
+#define GL_BOOL_VEC4_ARB 0x8B59
+#define GL_FLOAT_MAT2_ARB 0x8B5A
+#define GL_FLOAT_MAT3_ARB 0x8B5B
+#define GL_FLOAT_MAT4_ARB 0x8B5C
+#define GL_SAMPLER_1D_ARB 0x8B5D
+#define GL_SAMPLER_2D_ARB 0x8B5E
+#define GL_SAMPLER_3D_ARB 0x8B5F
+#define GL_SAMPLER_CUBE_ARB 0x8B60
+#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+typedef void (APIENTRYP PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj);
+typedef GLhandleARB (APIENTRYP PFNGLGETHANDLEARBPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLDETACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB attachedObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType);
+typedef void (APIENTRYP PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length);
+typedef void (APIENTRYP PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj);
+typedef GLhandleARB (APIENTRYP PFNGLCREATEPROGRAMOBJECTARBPROC) (void);
+typedef void (APIENTRYP PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj);
+typedef void (APIENTRYP PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMARBPROC) (GLhandleARB programObj);
+typedef void (APIENTRYP PFNGLUNIFORM1FARBPROC) (GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLUNIFORM2FARBPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLUNIFORM3FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLUNIFORM4FARBPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLUNIFORM1IARBPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2IARBPROC) (GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4IARBPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM2FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM3FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM4FVARBPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORM1IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4IVARBPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVARBPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERFVARBPROC) (GLhandleARB obj, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+typedef void (APIENTRYP PFNGLGETATTACHEDOBJECTSARBPROC) (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETUNIFORMFVARBPROC) (GLhandleARB programObj, GLint location, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMIVARBPROC) (GLhandleARB programObj, GLint location, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteObjectARB (GLhandleARB obj);
+GLAPI GLhandleARB APIENTRY glGetHandleARB (GLenum pname);
+GLAPI void APIENTRY glDetachObjectARB (GLhandleARB containerObj, GLhandleARB attachedObj);
+GLAPI GLhandleARB APIENTRY glCreateShaderObjectARB (GLenum shaderType);
+GLAPI void APIENTRY glShaderSourceARB (GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length);
+GLAPI void APIENTRY glCompileShaderARB (GLhandleARB shaderObj);
+GLAPI GLhandleARB APIENTRY glCreateProgramObjectARB (void);
+GLAPI void APIENTRY glAttachObjectARB (GLhandleARB containerObj, GLhandleARB obj);
+GLAPI void APIENTRY glLinkProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUseProgramObjectARB (GLhandleARB programObj);
+GLAPI void APIENTRY glValidateProgramARB (GLhandleARB programObj);
+GLAPI void APIENTRY glUniform1fARB (GLint location, GLfloat v0);
+GLAPI void APIENTRY glUniform2fARB (GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glUniform3fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glUniform4fARB (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glUniform1iARB (GLint location, GLint v0);
+GLAPI void APIENTRY glUniform2iARB (GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glUniform3iARB (GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glUniform4iARB (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glUniform1fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform2fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform3fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform4fvARB (GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glUniform1ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform2ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform3ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniform4ivARB (GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glUniformMatrix2fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix3fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glUniformMatrix4fvARB (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glGetObjectParameterfvARB (GLhandleARB obj, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectParameterivARB (GLhandleARB obj, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetInfoLogARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
+GLAPI void APIENTRY glGetAttachedObjectsARB (GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj);
+GLAPI GLint APIENTRY glGetUniformLocationARB (GLhandleARB programObj, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveUniformARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI void APIENTRY glGetUniformfvARB (GLhandleARB programObj, GLint location, GLfloat *params);
+GLAPI void APIENTRY glGetUniformivARB (GLhandleARB programObj, GLint location, GLint *params);
+GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source);
+#endif
+#endif /* GL_ARB_shader_objects */
+
+#ifndef GL_ARB_shader_precision
+#define GL_ARB_shader_precision 1
+#endif /* GL_ARB_shader_precision */
+
+#ifndef GL_ARB_shader_stencil_export
+#define GL_ARB_shader_stencil_export 1
+#endif /* GL_ARB_shader_stencil_export */
+
+#ifndef GL_ARB_shader_storage_buffer_object
+#define GL_ARB_shader_storage_buffer_object 1
+#endif /* GL_ARB_shader_storage_buffer_object */
+
+#ifndef GL_ARB_shader_subroutine
+#define GL_ARB_shader_subroutine 1
+#endif /* GL_ARB_shader_subroutine */
+
+#ifndef GL_ARB_shader_texture_lod
+#define GL_ARB_shader_texture_lod 1
+#endif /* GL_ARB_shader_texture_lod */
+
+#ifndef GL_ARB_shading_language_100
+#define GL_ARB_shading_language_100 1
+#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#endif /* GL_ARB_shading_language_100 */
+
+#ifndef GL_ARB_shading_language_420pack
+#define GL_ARB_shading_language_420pack 1
+#endif /* GL_ARB_shading_language_420pack */
+
+#ifndef GL_ARB_shading_language_include
+#define GL_ARB_shading_language_include 1
+#define GL_SHADER_INCLUDE_ARB 0x8DAE
+#define GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define GL_NAMED_STRING_TYPE_ARB 0x8DEA
+typedef void (APIENTRYP PFNGLNAMEDSTRINGARBPROC) (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+typedef void (APIENTRYP PFNGLDELETENAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLCOMPILESHADERINCLUDEARBPROC) (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGARBPROC) (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+typedef void (APIENTRYP PFNGLGETNAMEDSTRINGIVARBPROC) (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glNamedStringARB (GLenum type, GLint namelen, const GLchar *name, GLint stringlen, const GLchar *string);
+GLAPI void APIENTRY glDeleteNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glCompileShaderIncludeARB (GLuint shader, GLsizei count, const GLchar *const*path, const GLint *length);
+GLAPI GLboolean APIENTRY glIsNamedStringARB (GLint namelen, const GLchar *name);
+GLAPI void APIENTRY glGetNamedStringARB (GLint namelen, const GLchar *name, GLsizei bufSize, GLint *stringlen, GLchar *string);
+GLAPI void APIENTRY glGetNamedStringivARB (GLint namelen, const GLchar *name, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ARB_shading_language_include */
+
+#ifndef GL_ARB_shading_language_packing
+#define GL_ARB_shading_language_packing 1
+#endif /* GL_ARB_shading_language_packing */
+
+#ifndef GL_ARB_shadow
+#define GL_ARB_shadow 1
+#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+#endif /* GL_ARB_shadow */
+
+#ifndef GL_ARB_shadow_ambient
+#define GL_ARB_shadow_ambient 1
+#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#endif /* GL_ARB_shadow_ambient */
+
+#ifndef GL_ARB_sparse_texture
+#define GL_ARB_sparse_texture 1
+#define GL_TEXTURE_SPARSE_ARB 0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7
+#define GL_MIN_SPARSE_LEVEL_ARB 0x919B
+#define GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
+typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+#endif
+#endif /* GL_ARB_sparse_texture */
+
+#ifndef GL_ARB_stencil_texturing
+#define GL_ARB_stencil_texturing 1
+#endif /* GL_ARB_stencil_texturing */
+
+#ifndef GL_ARB_sync
+#define GL_ARB_sync 1
+#endif /* GL_ARB_sync */
+
+#ifndef GL_ARB_tessellation_shader
+#define GL_ARB_tessellation_shader 1
+#endif /* GL_ARB_tessellation_shader */
+
+#ifndef GL_ARB_texture_border_clamp
+#define GL_ARB_texture_border_clamp 1
+#define GL_CLAMP_TO_BORDER_ARB 0x812D
+#endif /* GL_ARB_texture_border_clamp */
+
+#ifndef GL_ARB_texture_buffer_object
+#define GL_ARB_texture_buffer_object 1
+#define GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+typedef void (APIENTRYP PFNGLTEXBUFFERARBPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferARB (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+#endif /* GL_ARB_texture_buffer_object */
+
+#ifndef GL_ARB_texture_buffer_object_rgb32
+#define GL_ARB_texture_buffer_object_rgb32 1
+#endif /* GL_ARB_texture_buffer_object_rgb32 */
+
+#ifndef GL_ARB_texture_buffer_range
+#define GL_ARB_texture_buffer_range 1
+#endif /* GL_ARB_texture_buffer_range */
+
+#ifndef GL_ARB_texture_compression
+#define GL_ARB_texture_compression 1
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DARBPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint level, void *img);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCompressedTexImage3DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage2DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexImage1DARB (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage3DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage2DARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glCompressedTexSubImage1DARB (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void *img);
+#endif
+#endif /* GL_ARB_texture_compression */
+
+#ifndef GL_ARB_texture_compression_bptc
+#define GL_ARB_texture_compression_bptc 1
+#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+#endif /* GL_ARB_texture_compression_bptc */
+
+#ifndef GL_ARB_texture_compression_rgtc
+#define GL_ARB_texture_compression_rgtc 1
+#endif /* GL_ARB_texture_compression_rgtc */
+
+#ifndef GL_ARB_texture_cube_map
+#define GL_ARB_texture_cube_map 1
+#define GL_NORMAL_MAP_ARB 0x8511
+#define GL_REFLECTION_MAP_ARB 0x8512
+#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#endif /* GL_ARB_texture_cube_map */
+
+#ifndef GL_ARB_texture_cube_map_array
+#define GL_ARB_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#endif /* GL_ARB_texture_cube_map_array */
+
+#ifndef GL_ARB_texture_env_add
+#define GL_ARB_texture_env_add 1
+#endif /* GL_ARB_texture_env_add */
+
+#ifndef GL_ARB_texture_env_combine
+#define GL_ARB_texture_env_combine 1
+#define GL_COMBINE_ARB 0x8570
+#define GL_COMBINE_RGB_ARB 0x8571
+#define GL_COMBINE_ALPHA_ARB 0x8572
+#define GL_SOURCE0_RGB_ARB 0x8580
+#define GL_SOURCE1_RGB_ARB 0x8581
+#define GL_SOURCE2_RGB_ARB 0x8582
+#define GL_SOURCE0_ALPHA_ARB 0x8588
+#define GL_SOURCE1_ALPHA_ARB 0x8589
+#define GL_SOURCE2_ALPHA_ARB 0x858A
+#define GL_OPERAND0_RGB_ARB 0x8590
+#define GL_OPERAND1_RGB_ARB 0x8591
+#define GL_OPERAND2_RGB_ARB 0x8592
+#define GL_OPERAND0_ALPHA_ARB 0x8598
+#define GL_OPERAND1_ALPHA_ARB 0x8599
+#define GL_OPERAND2_ALPHA_ARB 0x859A
+#define GL_RGB_SCALE_ARB 0x8573
+#define GL_ADD_SIGNED_ARB 0x8574
+#define GL_INTERPOLATE_ARB 0x8575
+#define GL_SUBTRACT_ARB 0x84E7
+#define GL_CONSTANT_ARB 0x8576
+#define GL_PRIMARY_COLOR_ARB 0x8577
+#define GL_PREVIOUS_ARB 0x8578
+#endif /* GL_ARB_texture_env_combine */
+
+#ifndef GL_ARB_texture_env_crossbar
+#define GL_ARB_texture_env_crossbar 1
+#endif /* GL_ARB_texture_env_crossbar */
+
+#ifndef GL_ARB_texture_env_dot3
+#define GL_ARB_texture_env_dot3 1
+#define GL_DOT3_RGB_ARB 0x86AE
+#define GL_DOT3_RGBA_ARB 0x86AF
+#endif /* GL_ARB_texture_env_dot3 */
+
+#ifndef GL_ARB_texture_float
+#define GL_ARB_texture_float 1
+#define GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define GL_RGBA32F_ARB 0x8814
+#define GL_RGB32F_ARB 0x8815
+#define GL_ALPHA32F_ARB 0x8816
+#define GL_INTENSITY32F_ARB 0x8817
+#define GL_LUMINANCE32F_ARB 0x8818
+#define GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define GL_RGBA16F_ARB 0x881A
+#define GL_RGB16F_ARB 0x881B
+#define GL_ALPHA16F_ARB 0x881C
+#define GL_INTENSITY16F_ARB 0x881D
+#define GL_LUMINANCE16F_ARB 0x881E
+#define GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#endif /* GL_ARB_texture_float */
+
+#ifndef GL_ARB_texture_gather
+#define GL_ARB_texture_gather 1
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+#endif /* GL_ARB_texture_gather */
+
+#ifndef GL_ARB_texture_mirror_clamp_to_edge
+#define GL_ARB_texture_mirror_clamp_to_edge 1
+#endif /* GL_ARB_texture_mirror_clamp_to_edge */
+
+#ifndef GL_ARB_texture_mirrored_repeat
+#define GL_ARB_texture_mirrored_repeat 1
+#define GL_MIRRORED_REPEAT_ARB 0x8370
+#endif /* GL_ARB_texture_mirrored_repeat */
+
+#ifndef GL_ARB_texture_multisample
+#define GL_ARB_texture_multisample 1
+#endif /* GL_ARB_texture_multisample */
+
+#ifndef GL_ARB_texture_non_power_of_two
+#define GL_ARB_texture_non_power_of_two 1
+#endif /* GL_ARB_texture_non_power_of_two */
+
+#ifndef GL_ARB_texture_query_levels
+#define GL_ARB_texture_query_levels 1
+#endif /* GL_ARB_texture_query_levels */
+
+#ifndef GL_ARB_texture_query_lod
+#define GL_ARB_texture_query_lod 1
+#endif /* GL_ARB_texture_query_lod */
+
+#ifndef GL_ARB_texture_rectangle
+#define GL_ARB_texture_rectangle 1
+#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#endif /* GL_ARB_texture_rectangle */
+
+#ifndef GL_ARB_texture_rg
+#define GL_ARB_texture_rg 1
+#endif /* GL_ARB_texture_rg */
+
+#ifndef GL_ARB_texture_rgb10_a2ui
+#define GL_ARB_texture_rgb10_a2ui 1
+#endif /* GL_ARB_texture_rgb10_a2ui */
+
+#ifndef GL_ARB_texture_stencil8
+#define GL_ARB_texture_stencil8 1
+#endif /* GL_ARB_texture_stencil8 */
+
+#ifndef GL_ARB_texture_storage
+#define GL_ARB_texture_storage 1
+#endif /* GL_ARB_texture_storage */
+
+#ifndef GL_ARB_texture_storage_multisample
+#define GL_ARB_texture_storage_multisample 1
+#endif /* GL_ARB_texture_storage_multisample */
+
+#ifndef GL_ARB_texture_swizzle
+#define GL_ARB_texture_swizzle 1
+#endif /* GL_ARB_texture_swizzle */
+
+#ifndef GL_ARB_texture_view
+#define GL_ARB_texture_view 1
+#endif /* GL_ARB_texture_view */
+
+#ifndef GL_ARB_timer_query
+#define GL_ARB_timer_query 1
+#endif /* GL_ARB_timer_query */
+
+#ifndef GL_ARB_transform_feedback2
+#define GL_ARB_transform_feedback2 1
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#endif /* GL_ARB_transform_feedback2 */
+
+#ifndef GL_ARB_transform_feedback3
+#define GL_ARB_transform_feedback3 1
+#endif /* GL_ARB_transform_feedback3 */
+
+#ifndef GL_ARB_transform_feedback_instanced
+#define GL_ARB_transform_feedback_instanced 1
+#endif /* GL_ARB_transform_feedback_instanced */
+
+#ifndef GL_ARB_transpose_matrix
+#define GL_ARB_transpose_matrix 1
+#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFARBPROC) (const GLfloat *m);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDARBPROC) (const GLdouble *m);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLoadTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glLoadTransposeMatrixdARB (const GLdouble *m);
+GLAPI void APIENTRY glMultTransposeMatrixfARB (const GLfloat *m);
+GLAPI void APIENTRY glMultTransposeMatrixdARB (const GLdouble *m);
+#endif
+#endif /* GL_ARB_transpose_matrix */
+
+#ifndef GL_ARB_uniform_buffer_object
+#define GL_ARB_uniform_buffer_object 1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#endif /* GL_ARB_uniform_buffer_object */
+
+#ifndef GL_ARB_vertex_array_bgra
+#define GL_ARB_vertex_array_bgra 1
+#endif /* GL_ARB_vertex_array_bgra */
+
+#ifndef GL_ARB_vertex_array_object
+#define GL_ARB_vertex_array_object 1
+#endif /* GL_ARB_vertex_array_object */
+
+#ifndef GL_ARB_vertex_attrib_64bit
+#define GL_ARB_vertex_attrib_64bit 1
+#endif /* GL_ARB_vertex_attrib_64bit */
+
+#ifndef GL_ARB_vertex_attrib_binding
+#define GL_ARB_vertex_attrib_binding 1
+#endif /* GL_ARB_vertex_attrib_binding */
+
+#ifndef GL_ARB_vertex_blend
+#define GL_ARB_vertex_blend 1
+#define GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define GL_VERTEX_BLEND_ARB 0x86A7
+#define GL_CURRENT_WEIGHT_ARB 0x86A8
+#define GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define GL_WEIGHT_ARRAY_ARB 0x86AD
+#define GL_MODELVIEW0_ARB 0x1700
+#define GL_MODELVIEW1_ARB 0x850A
+#define GL_MODELVIEW2_ARB 0x8722
+#define GL_MODELVIEW3_ARB 0x8723
+#define GL_MODELVIEW4_ARB 0x8724
+#define GL_MODELVIEW5_ARB 0x8725
+#define GL_MODELVIEW6_ARB 0x8726
+#define GL_MODELVIEW7_ARB 0x8727
+#define GL_MODELVIEW8_ARB 0x8728
+#define GL_MODELVIEW9_ARB 0x8729
+#define GL_MODELVIEW10_ARB 0x872A
+#define GL_MODELVIEW11_ARB 0x872B
+#define GL_MODELVIEW12_ARB 0x872C
+#define GL_MODELVIEW13_ARB 0x872D
+#define GL_MODELVIEW14_ARB 0x872E
+#define GL_MODELVIEW15_ARB 0x872F
+#define GL_MODELVIEW16_ARB 0x8730
+#define GL_MODELVIEW17_ARB 0x8731
+#define GL_MODELVIEW18_ARB 0x8732
+#define GL_MODELVIEW19_ARB 0x8733
+#define GL_MODELVIEW20_ARB 0x8734
+#define GL_MODELVIEW21_ARB 0x8735
+#define GL_MODELVIEW22_ARB 0x8736
+#define GL_MODELVIEW23_ARB 0x8737
+#define GL_MODELVIEW24_ARB 0x8738
+#define GL_MODELVIEW25_ARB 0x8739
+#define GL_MODELVIEW26_ARB 0x873A
+#define GL_MODELVIEW27_ARB 0x873B
+#define GL_MODELVIEW28_ARB 0x873C
+#define GL_MODELVIEW29_ARB 0x873D
+#define GL_MODELVIEW30_ARB 0x873E
+#define GL_MODELVIEW31_ARB 0x873F
+typedef void (APIENTRYP PFNGLWEIGHTBVARBPROC) (GLint size, const GLbyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTSVARBPROC) (GLint size, const GLshort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTIVARBPROC) (GLint size, const GLint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTFVARBPROC) (GLint size, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLWEIGHTDVARBPROC) (GLint size, const GLdouble *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUBVARBPROC) (GLint size, const GLubyte *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUSVARBPROC) (GLint size, const GLushort *weights);
+typedef void (APIENTRYP PFNGLWEIGHTUIVARBPROC) (GLint size, const GLuint *weights);
+typedef void (APIENTRYP PFNGLWEIGHTPOINTERARBPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXBLENDARBPROC) (GLint count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWeightbvARB (GLint size, const GLbyte *weights);
+GLAPI void APIENTRY glWeightsvARB (GLint size, const GLshort *weights);
+GLAPI void APIENTRY glWeightivARB (GLint size, const GLint *weights);
+GLAPI void APIENTRY glWeightfvARB (GLint size, const GLfloat *weights);
+GLAPI void APIENTRY glWeightdvARB (GLint size, const GLdouble *weights);
+GLAPI void APIENTRY glWeightubvARB (GLint size, const GLubyte *weights);
+GLAPI void APIENTRY glWeightusvARB (GLint size, const GLushort *weights);
+GLAPI void APIENTRY glWeightuivARB (GLint size, const GLuint *weights);
+GLAPI void APIENTRY glWeightPointerARB (GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glVertexBlendARB (GLint count);
+#endif
+#endif /* GL_ARB_vertex_blend */
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+#ifdef __MACOSX__ /* The OS X headers haven't caught up with Khronos yet */
+typedef long GLsizeiptrARB;
+typedef long GLintptrARB;
+#else
+typedef ptrdiff_t GLsizeiptrARB;
+typedef ptrdiff_t GLintptrARB;
+#endif
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+typedef void (APIENTRYP PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERARBPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLBUFFERDATAARBPROC) (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data);
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAARBPROC) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data);
+typedef void *(APIENTRYP PFNGLMAPBUFFERARBPROC) (GLenum target, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERARBPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBufferARB (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffersARB (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffersARB (GLsizei n, GLuint *buffers);
+GLAPI GLboolean APIENTRY glIsBufferARB (GLuint buffer);
+GLAPI void APIENTRY glBufferDataARB (GLenum target, GLsizeiptrARB size, const void *data, GLenum usage);
+GLAPI void APIENTRY glBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void *data);
+GLAPI void APIENTRY glGetBufferSubDataARB (GLenum target, GLintptrARB offset, GLsizeiptrARB size, void *data);
+GLAPI void *APIENTRY glMapBufferARB (GLenum target, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapBufferARB (GLenum target);
+GLAPI void APIENTRY glGetBufferParameterivARB (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetBufferPointervARB (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_ARB_vertex_buffer_object */
+
+#ifndef GL_ARB_vertex_program
+#define GL_ARB_vertex_program 1
+#define GL_COLOR_SUM_ARB 0x8458
+#define GL_VERTEX_PROGRAM_ARB 0x8620
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttrib1dARB (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fARB (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sARB (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dARB (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fARB (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sARB (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sARB (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NbvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4NivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4NsvARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4NubARB (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4NubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4NuivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4NusvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttrib4bvARB (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttrib4dARB (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvARB (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fARB (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvARB (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4ivARB (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttrib4sARB (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svARB (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubvARB (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttrib4uivARB (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttrib4usvARB (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribPointerARB (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glEnableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glDisableVertexAttribArrayARB (GLuint index);
+GLAPI void APIENTRY glGetVertexAttribdvARB (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvARB (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivARB (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervARB (GLuint index, GLenum pname, void **pointer);
+#endif
+#endif /* GL_ARB_vertex_program */
+
+#ifndef GL_ARB_vertex_shader
+#define GL_ARB_vertex_shader 1
+#define GL_VERTEX_SHADER_ARB 0x8B31
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONARBPROC) (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBARBPROC) (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONARBPROC) (GLhandleARB programObj, const GLcharARB *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindAttribLocationARB (GLhandleARB programObj, GLuint index, const GLcharARB *name);
+GLAPI void APIENTRY glGetActiveAttribARB (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name);
+GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcharARB *name);
+#endif
+#endif /* GL_ARB_vertex_shader */
+
+#ifndef GL_ARB_vertex_type_10f_11f_11f_rev
+#define GL_ARB_vertex_type_10f_11f_11f_rev 1
+#endif /* GL_ARB_vertex_type_10f_11f_11f_rev */
+
+#ifndef GL_ARB_vertex_type_2_10_10_10_rev
+#define GL_ARB_vertex_type_2_10_10_10_rev 1
+#endif /* GL_ARB_vertex_type_2_10_10_10_rev */
+
+#ifndef GL_ARB_viewport_array
+#define GL_ARB_viewport_array 1
+#endif /* GL_ARB_viewport_array */
+
+#ifndef GL_ARB_window_pos
+#define GL_ARB_window_pos 1
+typedef void (APIENTRYP PFNGLWINDOWPOS2DARBPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FARBPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IARBPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SARBPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVARBPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DARBPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVARBPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FARBPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVARBPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IARBPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVARBPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SARBPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVARBPROC) (const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dARB (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fARB (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iARB (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sARB (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svARB (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dARB (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvARB (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fARB (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvARB (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iARB (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivARB (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sARB (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svARB (const GLshort *v);
+#endif
+#endif /* GL_ARB_window_pos */
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#endif /* GL_KHR_debug */
+
+#ifndef GL_KHR_texture_compression_astc_hdr
+#define GL_KHR_texture_compression_astc_hdr 1
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif /* GL_KHR_texture_compression_astc_hdr */
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif /* GL_KHR_texture_compression_astc_ldr */
+
+#ifndef GL_OES_byte_coordinates
+#define GL_OES_byte_coordinates 1
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2BOESPROC) (GLenum texture, GLbyte s, GLbyte t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4BOESPROC) (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4BVOESPROC) (GLenum texture, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD1BOESPROC) (GLbyte s);
+typedef void (APIENTRYP PFNGLTEXCOORD1BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD2BOESPROC) (GLbyte s, GLbyte t);
+typedef void (APIENTRYP PFNGLTEXCOORD2BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD3BOESPROC) (GLbyte s, GLbyte t, GLbyte r);
+typedef void (APIENTRYP PFNGLTEXCOORD3BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD4BOESPROC) (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+typedef void (APIENTRYP PFNGLTEXCOORD4BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX2BOESPROC) (GLbyte x);
+typedef void (APIENTRYP PFNGLVERTEX2BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX3BOESPROC) (GLbyte x, GLbyte y);
+typedef void (APIENTRYP PFNGLVERTEX3BVOESPROC) (const GLbyte *coords);
+typedef void (APIENTRYP PFNGLVERTEX4BOESPROC) (GLbyte x, GLbyte y, GLbyte z);
+typedef void (APIENTRYP PFNGLVERTEX4BVOESPROC) (const GLbyte *coords);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiTexCoord1bOES (GLenum texture, GLbyte s);
+GLAPI void APIENTRY glMultiTexCoord1bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord2bOES (GLenum texture, GLbyte s, GLbyte t);
+GLAPI void APIENTRY glMultiTexCoord2bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord3bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r);
+GLAPI void APIENTRY glMultiTexCoord3bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glMultiTexCoord4bOES (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+GLAPI void APIENTRY glMultiTexCoord4bvOES (GLenum texture, const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord1bOES (GLbyte s);
+GLAPI void APIENTRY glTexCoord1bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord2bOES (GLbyte s, GLbyte t);
+GLAPI void APIENTRY glTexCoord2bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord3bOES (GLbyte s, GLbyte t, GLbyte r);
+GLAPI void APIENTRY glTexCoord3bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glTexCoord4bOES (GLbyte s, GLbyte t, GLbyte r, GLbyte q);
+GLAPI void APIENTRY glTexCoord4bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex2bOES (GLbyte x);
+GLAPI void APIENTRY glVertex2bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex3bOES (GLbyte x, GLbyte y);
+GLAPI void APIENTRY glVertex3bvOES (const GLbyte *coords);
+GLAPI void APIENTRY glVertex4bOES (GLbyte x, GLbyte y, GLbyte z);
+GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords);
+#endif
+#endif /* GL_OES_byte_coordinates */
+
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif /* GL_OES_compressed_paletted_texture */
+
+#ifndef GL_OES_fixed_point
+#define GL_OES_fixed_point 1
+typedef GLint GLfixed;
+#define GL_FIXED_OES 0x140C
+typedef void (APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref);
+typedef void (APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLfixed depth);
+typedef void (APIENTRYP PFNGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation);
+typedef void (APIENTRYP PFNGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLFOGXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum plane, GLfixed *equation);
+typedef void (APIENTRYP PFNGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLLINEWIDTHXOESPROC) (GLfixed width);
+typedef void (APIENTRYP PFNGLLOADMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *param);
+typedef void (APIENTRYP PFNGLMULTMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (APIENTRYP PFNGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz);
+typedef void (APIENTRYP PFNGLORTHOXOESPROC) (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size);
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units);
+typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLACCUMXOESPROC) (GLenum op, GLfixed value);
+typedef void (APIENTRYP PFNGLBITMAPXOESPROC) (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap);
+typedef void (APIENTRYP PFNGLBLENDCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCLEARACCUMXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+typedef void (APIENTRYP PFNGLCOLOR3XOESPROC) (GLfixed red, GLfixed green, GLfixed blue);
+typedef void (APIENTRYP PFNGLCOLOR3XVOESPROC) (const GLfixed *components);
+typedef void (APIENTRYP PFNGLCOLOR4XVOESPROC) (const GLfixed *components);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLEVALCOORD1XOESPROC) (GLfixed u);
+typedef void (APIENTRYP PFNGLEVALCOORD1XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLEVALCOORD2XOESPROC) (GLfixed u, GLfixed v);
+typedef void (APIENTRYP PFNGLEVALCOORD2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLFEEDBACKBUFFERXOESPROC) (GLsizei n, GLenum type, const GLfixed *buffer);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETMAPXVOESPROC) (GLenum target, GLenum query, GLfixed *v);
+typedef void (APIENTRYP PFNGLGETMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLGETPIXELMAPXVPROC) (GLenum map, GLint size, GLfixed *values);
+typedef void (APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERXVOESPROC) (GLenum target, GLint level, GLenum pname, GLfixed *params);
+typedef void (APIENTRYP PFNGLINDEXXOESPROC) (GLfixed component);
+typedef void (APIENTRYP PFNGLINDEXXVOESPROC) (const GLfixed *component);
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMAP1XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+typedef void (APIENTRYP PFNGLMAP2XOESPROC) (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+typedef void (APIENTRYP PFNGLMAPGRID1XOESPROC) (GLint n, GLfixed u1, GLfixed u2);
+typedef void (APIENTRYP PFNGLMAPGRID2XOESPROC) (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXXOESPROC) (const GLfixed *m);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1XOESPROC) (GLenum texture, GLfixed s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2XOESPROC) (GLenum texture, GLfixed s, GLfixed t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3XOESPROC) (GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4XVOESPROC) (GLenum texture, const GLfixed *coords);
+typedef void (APIENTRYP PFNGLNORMAL3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLPASSTHROUGHXOESPROC) (GLfixed token);
+typedef void (APIENTRYP PFNGLPIXELMAPXPROC) (GLenum map, GLint size, const GLfixed *values);
+typedef void (APIENTRYP PFNGLPIXELSTOREXPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFERXOESPROC) (GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLPIXELZOOMXOESPROC) (GLfixed xfactor, GLfixed yfactor);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESXOESPROC) (GLsizei n, const GLuint *textures, const GLfixed *priorities);
+typedef void (APIENTRYP PFNGLRASTERPOS2XOESPROC) (GLfixed x, GLfixed y);
+typedef void (APIENTRYP PFNGLRASTERPOS2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRASTERPOS3XOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLRASTERPOS3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRASTERPOS4XOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+typedef void (APIENTRYP PFNGLRASTERPOS4XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLRECTXOESPROC) (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+typedef void (APIENTRYP PFNGLRECTXVOESPROC) (const GLfixed *v1, const GLfixed *v2);
+typedef void (APIENTRYP PFNGLTEXCOORD1XOESPROC) (GLfixed s);
+typedef void (APIENTRYP PFNGLTEXCOORD1XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD2XOESPROC) (GLfixed s, GLfixed t);
+typedef void (APIENTRYP PFNGLTEXCOORD2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD3XOESPROC) (GLfixed s, GLfixed t, GLfixed r);
+typedef void (APIENTRYP PFNGLTEXCOORD3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXCOORD4XOESPROC) (GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+typedef void (APIENTRYP PFNGLTEXCOORD4XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param);
+typedef void (APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params);
+typedef void (APIENTRYP PFNGLVERTEX2XOESPROC) (GLfixed x);
+typedef void (APIENTRYP PFNGLVERTEX2XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLVERTEX3XOESPROC) (GLfixed x, GLfixed y);
+typedef void (APIENTRYP PFNGLVERTEX3XVOESPROC) (const GLfixed *coords);
+typedef void (APIENTRYP PFNGLVERTEX4XOESPROC) (GLfixed x, GLfixed y, GLfixed z);
+typedef void (APIENTRYP PFNGLVERTEX4XVOESPROC) (const GLfixed *coords);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAlphaFuncxOES (GLenum func, GLfixed ref);
+GLAPI void APIENTRY glClearColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glClearDepthxOES (GLfixed depth);
+GLAPI void APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation);
+GLAPI void APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glDepthRangexOES (GLfixed n, GLfixed f);
+GLAPI void APIENTRY glFogxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glFogxvOES (GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glFrustumxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GLAPI void APIENTRY glGetClipPlanexOES (GLenum plane, GLfixed *equation);
+GLAPI void APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexEnvxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glLightModelxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glLineWidthxOES (GLfixed width);
+GLAPI void APIENTRY glLoadMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *param);
+GLAPI void APIENTRY glMultMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMultiTexCoord4xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GLAPI void APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz);
+GLAPI void APIENTRY glOrthoxOES (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
+GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glPointSizexOES (GLfixed size);
+GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units);
+GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert);
+GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glAccumxOES (GLenum op, GLfixed value);
+GLAPI void APIENTRY glBitmapxOES (GLsizei width, GLsizei height, GLfixed xorig, GLfixed yorig, GLfixed xmove, GLfixed ymove, const GLubyte *bitmap);
+GLAPI void APIENTRY glBlendColorxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glClearAccumxOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
+GLAPI void APIENTRY glColor3xOES (GLfixed red, GLfixed green, GLfixed blue);
+GLAPI void APIENTRY glColor3xvOES (const GLfixed *components);
+GLAPI void APIENTRY glColor4xvOES (const GLfixed *components);
+GLAPI void APIENTRY glConvolutionParameterxOES (GLenum target, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glConvolutionParameterxvOES (GLenum target, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glEvalCoord1xOES (GLfixed u);
+GLAPI void APIENTRY glEvalCoord1xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glEvalCoord2xOES (GLfixed u, GLfixed v);
+GLAPI void APIENTRY glEvalCoord2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glFeedbackBufferxOES (GLsizei n, GLenum type, const GLfixed *buffer);
+GLAPI void APIENTRY glGetConvolutionParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetHistogramParameterxvOES (GLenum target, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetLightxOES (GLenum light, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetMapxvOES (GLenum target, GLenum query, GLfixed *v);
+GLAPI void APIENTRY glGetMaterialxOES (GLenum face, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glGetPixelMapxv (GLenum map, GLint size, GLfixed *values);
+GLAPI void APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glGetTexLevelParameterxvOES (GLenum target, GLint level, GLenum pname, GLfixed *params);
+GLAPI void APIENTRY glIndexxOES (GLfixed component);
+GLAPI void APIENTRY glIndexxvOES (const GLfixed *component);
+GLAPI void APIENTRY glLoadTransposeMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMap1xOES (GLenum target, GLfixed u1, GLfixed u2, GLint stride, GLint order, GLfixed points);
+GLAPI void APIENTRY glMap2xOES (GLenum target, GLfixed u1, GLfixed u2, GLint ustride, GLint uorder, GLfixed v1, GLfixed v2, GLint vstride, GLint vorder, GLfixed points);
+GLAPI void APIENTRY glMapGrid1xOES (GLint n, GLfixed u1, GLfixed u2);
+GLAPI void APIENTRY glMapGrid2xOES (GLint n, GLfixed u1, GLfixed u2, GLfixed v1, GLfixed v2);
+GLAPI void APIENTRY glMultTransposeMatrixxOES (const GLfixed *m);
+GLAPI void APIENTRY glMultiTexCoord1xOES (GLenum texture, GLfixed s);
+GLAPI void APIENTRY glMultiTexCoord1xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord2xOES (GLenum texture, GLfixed s, GLfixed t);
+GLAPI void APIENTRY glMultiTexCoord2xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord3xOES (GLenum texture, GLfixed s, GLfixed t, GLfixed r);
+GLAPI void APIENTRY glMultiTexCoord3xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glMultiTexCoord4xvOES (GLenum texture, const GLfixed *coords);
+GLAPI void APIENTRY glNormal3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glPassThroughxOES (GLfixed token);
+GLAPI void APIENTRY glPixelMapx (GLenum map, GLint size, const GLfixed *values);
+GLAPI void APIENTRY glPixelStorex (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glPixelTransferxOES (GLenum pname, GLfixed param);
+GLAPI void APIENTRY glPixelZoomxOES (GLfixed xfactor, GLfixed yfactor);
+GLAPI void APIENTRY glPrioritizeTexturesxOES (GLsizei n, const GLuint *textures, const GLfixed *priorities);
+GLAPI void APIENTRY glRasterPos2xOES (GLfixed x, GLfixed y);
+GLAPI void APIENTRY glRasterPos2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRasterPos3xOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glRasterPos3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRasterPos4xOES (GLfixed x, GLfixed y, GLfixed z, GLfixed w);
+GLAPI void APIENTRY glRasterPos4xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glRectxOES (GLfixed x1, GLfixed y1, GLfixed x2, GLfixed y2);
+GLAPI void APIENTRY glRectxvOES (const GLfixed *v1, const GLfixed *v2);
+GLAPI void APIENTRY glTexCoord1xOES (GLfixed s);
+GLAPI void APIENTRY glTexCoord1xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord2xOES (GLfixed s, GLfixed t);
+GLAPI void APIENTRY glTexCoord2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord3xOES (GLfixed s, GLfixed t, GLfixed r);
+GLAPI void APIENTRY glTexCoord3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexCoord4xOES (GLfixed s, GLfixed t, GLfixed r, GLfixed q);
+GLAPI void APIENTRY glTexCoord4xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param);
+GLAPI void APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params);
+GLAPI void APIENTRY glVertex2xOES (GLfixed x);
+GLAPI void APIENTRY glVertex2xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glVertex3xOES (GLfixed x, GLfixed y);
+GLAPI void APIENTRY glVertex3xvOES (const GLfixed *coords);
+GLAPI void APIENTRY glVertex4xOES (GLfixed x, GLfixed y, GLfixed z);
+GLAPI void APIENTRY glVertex4xvOES (const GLfixed *coords);
+#endif
+#endif /* GL_OES_fixed_point */
+
+#ifndef GL_OES_query_matrix
+#define GL_OES_query_matrix 1
+typedef GLbitfield (APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed *mantissa, GLint *exponent);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLbitfield APIENTRY glQueryMatrixxOES (GLfixed *mantissa, GLint *exponent);
+#endif
+#endif /* GL_OES_query_matrix */
+
+#ifndef GL_OES_read_format
+#define GL_OES_read_format 1
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#endif /* GL_OES_read_format */
+
+#ifndef GL_OES_single_precision
+#define GL_OES_single_precision 1
+typedef void (APIENTRYP PFNGLCLEARDEPTHFOESPROC) (GLclampf depth);
+typedef void (APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation);
+typedef void (APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf n, GLclampf f);
+typedef void (APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+typedef void (APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum plane, GLfloat *equation);
+typedef void (APIENTRYP PFNGLORTHOFOESPROC) (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glClearDepthfOES (GLclampf depth);
+GLAPI void APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation);
+GLAPI void APIENTRY glDepthRangefOES (GLclampf n, GLclampf f);
+GLAPI void APIENTRY glFrustumfOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+GLAPI void APIENTRY glGetClipPlanefOES (GLenum plane, GLfloat *equation);
+GLAPI void APIENTRY glOrthofOES (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
+#endif
+#endif /* GL_OES_single_precision */
+
+#ifndef GL_3DFX_multisample
+#define GL_3DFX_multisample 1
+#define GL_MULTISAMPLE_3DFX 0x86B2
+#define GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define GL_SAMPLES_3DFX 0x86B4
+#define GL_MULTISAMPLE_BIT_3DFX 0x20000000
+#endif /* GL_3DFX_multisample */
+
+#ifndef GL_3DFX_tbuffer
+#define GL_3DFX_tbuffer 1
+typedef void (APIENTRYP PFNGLTBUFFERMASK3DFXPROC) (GLuint mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTbufferMask3DFX (GLuint mask);
+#endif
+#endif /* GL_3DFX_tbuffer */
+
+#ifndef GL_3DFX_texture_compression_FXT1
+#define GL_3DFX_texture_compression_FXT1 1
+#define GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+#endif /* GL_3DFX_texture_compression_FXT1 */
+
+#ifndef GL_AMD_blend_minmax_factor
+#define GL_AMD_blend_minmax_factor 1
+#define GL_FACTOR_MIN_AMD 0x901C
+#define GL_FACTOR_MAX_AMD 0x901D
+#endif /* GL_AMD_blend_minmax_factor */
+
+#ifndef GL_AMD_conservative_depth
+#define GL_AMD_conservative_depth 1
+#endif /* GL_AMD_conservative_depth */
+
+#ifndef GL_AMD_debug_output
+#define GL_AMD_debug_output 1
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
+typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
+GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam);
+GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
+#endif
+#endif /* GL_AMD_debug_output */
+
+#ifndef GL_AMD_depth_clamp_separate
+#define GL_AMD_depth_clamp_separate 1
+#define GL_DEPTH_CLAMP_NEAR_AMD 0x901E
+#define GL_DEPTH_CLAMP_FAR_AMD 0x901F
+#endif /* GL_AMD_depth_clamp_separate */
+
+#ifndef GL_AMD_draw_buffers_blend
+#define GL_AMD_draw_buffers_blend 1
+typedef void (APIENTRYP PFNGLBLENDFUNCINDEXEDAMDPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONINDEXEDAMDPROC) (GLuint buf, GLenum mode);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEINDEXEDAMDPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncIndexedAMD (GLuint buf, GLenum src, GLenum dst);
+GLAPI void APIENTRY glBlendFuncSeparateIndexedAMD (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GLAPI void APIENTRY glBlendEquationIndexedAMD (GLuint buf, GLenum mode);
+GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+#endif
+#endif /* GL_AMD_draw_buffers_blend */
+
+#ifndef GL_AMD_gcn_shader
+#define GL_AMD_gcn_shader 1
+#endif /* GL_AMD_gcn_shader */
+
+#ifndef GL_AMD_gpu_shader_int64
+#define GL_AMD_gpu_shader_int64 1
+typedef int64_t GLint64EXT;
+#define GL_INT64_NV 0x140E
+#define GL_UNSIGNED_INT64_NV 0x140F
+#define GL_INT8_NV 0x8FE0
+#define GL_INT8_VEC2_NV 0x8FE1
+#define GL_INT8_VEC3_NV 0x8FE2
+#define GL_INT8_VEC4_NV 0x8FE3
+#define GL_INT16_NV 0x8FE4
+#define GL_INT16_VEC2_NV 0x8FE5
+#define GL_INT16_VEC3_NV 0x8FE6
+#define GL_INT16_VEC4_NV 0x8FE7
+#define GL_INT64_VEC2_NV 0x8FE9
+#define GL_INT64_VEC3_NV 0x8FEA
+#define GL_INT64_VEC4_NV 0x8FEB
+#define GL_UNSIGNED_INT8_NV 0x8FEC
+#define GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define GL_UNSIGNED_INT16_NV 0x8FF0
+#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define GL_FLOAT16_NV 0x8FF8
+#define GL_FLOAT16_VEC2_NV 0x8FF9
+#define GL_FLOAT16_VEC3_NV 0x8FFA
+#define GL_FLOAT16_VEC4_NV 0x8FFB
+typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4I64VNVPROC) (GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64NVPROC) (GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64NVPROC) (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLUNIFORM1UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLGETUNIFORMI64VNVPROC) (GLuint program, GLint location, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64NVPROC) (GLuint program, GLint location, GLint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64NVPROC) (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64NVPROC) (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniform1i64NV (GLint location, GLint64EXT x);
+GLAPI void APIENTRY glUniform2i64NV (GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glUniform3i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glUniform4i64NV (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glUniform1i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform2i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform3i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform4i64vNV (GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glUniform1ui64NV (GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glUniform2ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glUniform3ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glUniform4ui64NV (GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glUniform1ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform2ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform3ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glUniform4ui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glGetUniformi64vNV (GLuint program, GLint location, GLint64EXT *params);
+GLAPI void APIENTRY glGetUniformui64vNV (GLuint program, GLint location, GLuint64EXT *params);
+GLAPI void APIENTRY glProgramUniform1i64NV (GLuint program, GLint location, GLint64EXT x);
+GLAPI void APIENTRY glProgramUniform2i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glProgramUniform3i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glProgramUniform4i64NV (GLuint program, GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glProgramUniform1i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4i64vNV (GLuint program, GLint location, GLsizei count, const GLint64EXT *value);
+GLAPI void APIENTRY glProgramUniform1ui64NV (GLuint program, GLint location, GLuint64EXT x);
+GLAPI void APIENTRY glProgramUniform2ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glProgramUniform3ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glProgramUniform4ui64NV (GLuint program, GLint location, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glProgramUniform1ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform2ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform3ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniform4ui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_AMD_gpu_shader_int64 */
+
+#ifndef GL_AMD_interleaved_elements
+#define GL_AMD_interleaved_elements 1
+#define GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4
+#define GL_VERTEX_ID_SWIZZLE_AMD 0x91A5
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPARAMETERIAMDPROC) (GLuint index, GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribParameteriAMD (GLuint index, GLenum pname, GLint param);
+#endif
+#endif /* GL_AMD_interleaved_elements */
+
+#ifndef GL_AMD_multi_draw_indirect
+#define GL_AMD_multi_draw_indirect 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTAMDPROC) (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTAMDPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectAMD (GLenum mode, const void *indirect, GLsizei primcount, GLsizei stride);
+GLAPI void APIENTRY glMultiDrawElementsIndirectAMD (GLenum mode, GLenum type, const void *indirect, GLsizei primcount, GLsizei stride);
+#endif
+#endif /* GL_AMD_multi_draw_indirect */
+
+#ifndef GL_AMD_name_gen_delete
+#define GL_AMD_name_gen_delete 1
+#define GL_DATA_BUFFER_AMD 0x9151
+#define GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define GL_QUERY_OBJECT_AMD 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define GL_SAMPLER_OBJECT_AMD 0x9155
+typedef void (APIENTRYP PFNGLGENNAMESAMDPROC) (GLenum identifier, GLuint num, GLuint *names);
+typedef void (APIENTRYP PFNGLDELETENAMESAMDPROC) (GLenum identifier, GLuint num, const GLuint *names);
+typedef GLboolean (APIENTRYP PFNGLISNAMEAMDPROC) (GLenum identifier, GLuint name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenNamesAMD (GLenum identifier, GLuint num, GLuint *names);
+GLAPI void APIENTRY glDeleteNamesAMD (GLenum identifier, GLuint num, const GLuint *names);
+GLAPI GLboolean APIENTRY glIsNameAMD (GLenum identifier, GLuint name);
+#endif
+#endif /* GL_AMD_name_gen_delete */
+
+#ifndef GL_AMD_occlusion_query_event
+#define GL_AMD_occlusion_query_event 1
+#define GL_OCCLUSION_QUERY_EVENT_MASK_AMD 0x874F
+#define GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD 0x00000001
+#define GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD 0x00000002
+#define GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD 0x00000004
+#define GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD 0x00000008
+#define GL_QUERY_ALL_EVENT_BITS_AMD 0xFFFFFFFF
+typedef void (APIENTRYP PFNGLQUERYOBJECTPARAMETERUIAMDPROC) (GLenum target, GLuint id, GLenum pname, GLuint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glQueryObjectParameteruiAMD (GLenum target, GLuint id, GLenum pname, GLuint param);
+#endif
+#endif /* GL_AMD_occlusion_query_event */
+
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data);
+typedef void (APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+typedef void (APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GLAPI void APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GLAPI void APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GLAPI void APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GLAPI void APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data);
+GLAPI void APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GLAPI void APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList);
+GLAPI void APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+#endif /* GL_AMD_performance_monitor */
+
+#ifndef GL_AMD_pinned_memory
+#define GL_AMD_pinned_memory 1
+#define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+#endif /* GL_AMD_pinned_memory */
+
+#ifndef GL_AMD_query_buffer_object
+#define GL_AMD_query_buffer_object 1
+#define GL_QUERY_BUFFER_AMD 0x9192
+#define GL_QUERY_BUFFER_BINDING_AMD 0x9193
+#define GL_QUERY_RESULT_NO_WAIT_AMD 0x9194
+#endif /* GL_AMD_query_buffer_object */
+
+#ifndef GL_AMD_sample_positions
+#define GL_AMD_sample_positions 1
+#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F
+typedef void (APIENTRYP PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat *val);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLfloat *val);
+#endif
+#endif /* GL_AMD_sample_positions */
+
+#ifndef GL_AMD_seamless_cubemap_per_texture
+#define GL_AMD_seamless_cubemap_per_texture 1
+#endif /* GL_AMD_seamless_cubemap_per_texture */
+
+#ifndef GL_AMD_shader_atomic_counter_ops
+#define GL_AMD_shader_atomic_counter_ops 1
+#endif /* GL_AMD_shader_atomic_counter_ops */
+
+#ifndef GL_AMD_shader_stencil_export
+#define GL_AMD_shader_stencil_export 1
+#endif /* GL_AMD_shader_stencil_export */
+
+#ifndef GL_AMD_shader_trinary_minmax
+#define GL_AMD_shader_trinary_minmax 1
+#endif /* GL_AMD_shader_trinary_minmax */
+
+#ifndef GL_AMD_sparse_texture
+#define GL_AMD_sparse_texture 1
+#define GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197
+#define GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
+#define GL_MIN_SPARSE_LEVEL_AMD 0x919B
+#define GL_MIN_LOD_WARNING_AMD 0x919C
+#define GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001
+typedef void (APIENTRYP PFNGLTEXSTORAGESPARSEAMDPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGESPARSEAMDPROC) (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexStorageSparseAMD (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+GLAPI void APIENTRY glTextureStorageSparseAMD (GLuint texture, GLenum target, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei layers, GLbitfield flags);
+#endif
+#endif /* GL_AMD_sparse_texture */
+
+#ifndef GL_AMD_stencil_operation_extended
+#define GL_AMD_stencil_operation_extended 1
+#define GL_SET_AMD 0x874A
+#define GL_REPLACE_VALUE_AMD 0x874B
+#define GL_STENCIL_OP_VALUE_AMD 0x874C
+#define GL_STENCIL_BACK_OP_VALUE_AMD 0x874D
+typedef void (APIENTRYP PFNGLSTENCILOPVALUEAMDPROC) (GLenum face, GLuint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value);
+#endif
+#endif /* GL_AMD_stencil_operation_extended */
+
+#ifndef GL_AMD_texture_texture4
+#define GL_AMD_texture_texture4 1
+#endif /* GL_AMD_texture_texture4 */
+
+#ifndef GL_AMD_transform_feedback3_lines_triangles
+#define GL_AMD_transform_feedback3_lines_triangles 1
+#endif /* GL_AMD_transform_feedback3_lines_triangles */
+
+#ifndef GL_AMD_transform_feedback4
+#define GL_AMD_transform_feedback4 1
+#define GL_STREAM_RASTERIZATION_AMD 0x91A0
+#endif /* GL_AMD_transform_feedback4 */
+
+#ifndef GL_AMD_vertex_shader_layer
+#define GL_AMD_vertex_shader_layer 1
+#endif /* GL_AMD_vertex_shader_layer */
+
+#ifndef GL_AMD_vertex_shader_tessellator
+#define GL_AMD_vertex_shader_tessellator 1
+#define GL_SAMPLER_BUFFER_AMD 0x9001
+#define GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define GL_TESSELLATION_MODE_AMD 0x9004
+#define GL_TESSELLATION_FACTOR_AMD 0x9005
+#define GL_DISCRETE_AMD 0x9006
+#define GL_CONTINUOUS_AMD 0x9007
+typedef void (APIENTRYP PFNGLTESSELLATIONFACTORAMDPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLTESSELLATIONMODEAMDPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTessellationFactorAMD (GLfloat factor);
+GLAPI void APIENTRY glTessellationModeAMD (GLenum mode);
+#endif
+#endif /* GL_AMD_vertex_shader_tessellator */
+
+#ifndef GL_AMD_vertex_shader_viewport_index
+#define GL_AMD_vertex_shader_viewport_index 1
+#endif /* GL_AMD_vertex_shader_viewport_index */
+
+#ifndef GL_APPLE_aux_depth_stencil
+#define GL_APPLE_aux_depth_stencil 1
+#define GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+#endif /* GL_APPLE_aux_depth_stencil */
+
+#ifndef GL_APPLE_client_storage
+#define GL_APPLE_client_storage 1
+#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+#endif /* GL_APPLE_client_storage */
+
+#ifndef GL_APPLE_element_array
+#define GL_APPLE_element_array 1
+#define GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+typedef void (APIENTRYP PFNGLELEMENTPOINTERAPPLEPROC) (GLenum type, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTARRAYAPPLEPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWRANGEELEMENTARRAYAPPLEPROC) (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerAPPLE (GLenum type, const void *pointer);
+GLAPI void APIENTRY glDrawElementArrayAPPLE (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, GLint first, GLsizei count);
+GLAPI void APIENTRY glMultiDrawElementArrayAPPLE (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawRangeElementArrayAPPLE (GLenum mode, GLuint start, GLuint end, const GLint *first, const GLsizei *count, GLsizei primcount);
+#endif
+#endif /* GL_APPLE_element_array */
+
+#ifndef GL_APPLE_fence
+#define GL_APPLE_fence 1
+#define GL_DRAW_PIXELS_APPLE 0x8A0A
+#define GL_FENCE_APPLE 0x8A0B
+typedef void (APIENTRYP PFNGLGENFENCESAPPLEPROC) (GLsizei n, GLuint *fences);
+typedef void (APIENTRYP PFNGLDELETEFENCESAPPLEPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLSETFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLISFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCEAPPLEPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLFINISHFENCEAPPLEPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTOBJECTAPPLEPROC) (GLenum object, GLuint name);
+typedef void (APIENTRYP PFNGLFINISHOBJECTAPPLEPROC) (GLenum object, GLint name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenFencesAPPLE (GLsizei n, GLuint *fences);
+GLAPI void APIENTRY glDeleteFencesAPPLE (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glSetFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glIsFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceAPPLE (GLuint fence);
+GLAPI void APIENTRY glFinishFenceAPPLE (GLuint fence);
+GLAPI GLboolean APIENTRY glTestObjectAPPLE (GLenum object, GLuint name);
+GLAPI void APIENTRY glFinishObjectAPPLE (GLenum object, GLint name);
+#endif
+#endif /* GL_APPLE_fence */
+
+#ifndef GL_APPLE_float_pixels
+#define GL_APPLE_float_pixels 1
+#define GL_HALF_APPLE 0x140B
+#define GL_RGBA_FLOAT32_APPLE 0x8814
+#define GL_RGB_FLOAT32_APPLE 0x8815
+#define GL_ALPHA_FLOAT32_APPLE 0x8816
+#define GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define GL_RGBA_FLOAT16_APPLE 0x881A
+#define GL_RGB_FLOAT16_APPLE 0x881B
+#define GL_ALPHA_FLOAT16_APPLE 0x881C
+#define GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define GL_COLOR_FLOAT_APPLE 0x8A0F
+#endif /* GL_APPLE_float_pixels */
+
+#ifndef GL_APPLE_flush_buffer_range
+#define GL_APPLE_flush_buffer_range 1
+#define GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+typedef void (APIENTRYP PFNGLBUFFERPARAMETERIAPPLEPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC) (GLenum target, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferParameteriAPPLE (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glFlushMappedBufferRangeAPPLE (GLenum target, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_APPLE_flush_buffer_range */
+
+#ifndef GL_APPLE_object_purgeable
+#define GL_APPLE_object_purgeable 1
+#define GL_BUFFER_OBJECT_APPLE 0x85B3
+#define GL_RELEASED_APPLE 0x8A19
+#define GL_VOLATILE_APPLE 0x8A1A
+#define GL_RETAINED_APPLE 0x8A1B
+#define GL_UNDEFINED_APPLE 0x8A1C
+#define GL_PURGEABLE_APPLE 0x8A1D
+typedef GLenum (APIENTRYP PFNGLOBJECTPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef GLenum (APIENTRYP PFNGLOBJECTUNPURGEABLEAPPLEPROC) (GLenum objectType, GLuint name, GLenum option);
+typedef void (APIENTRYP PFNGLGETOBJECTPARAMETERIVAPPLEPROC) (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLenum APIENTRY glObjectPurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI GLenum APIENTRY glObjectUnpurgeableAPPLE (GLenum objectType, GLuint name, GLenum option);
+GLAPI void APIENTRY glGetObjectParameterivAPPLE (GLenum objectType, GLuint name, GLenum pname, GLint *params);
+#endif
+#endif /* GL_APPLE_object_purgeable */
+
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define GL_RGB_RAW_422_APPLE 0x8A51
+#endif /* GL_APPLE_rgb_422 */
+
+#ifndef GL_APPLE_row_bytes
+#define GL_APPLE_row_bytes 1
+#define GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+#endif /* GL_APPLE_row_bytes */
+
+#ifndef GL_APPLE_specular_vector
+#define GL_APPLE_specular_vector 1
+#define GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#endif /* GL_APPLE_specular_vector */
+
+#ifndef GL_APPLE_texture_range
+#define GL_APPLE_texture_range 1
+#define GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define GL_STORAGE_CACHED_APPLE 0x85BE
+#define GL_STORAGE_SHARED_APPLE 0x85BF
+typedef void (APIENTRYP PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, const void *pointer);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERPOINTERVAPPLEPROC) (GLenum target, GLenum pname, void **params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureRangeAPPLE (GLenum target, GLsizei length, const void *pointer);
+GLAPI void APIENTRY glGetTexParameterPointervAPPLE (GLenum target, GLenum pname, void **params);
+#endif
+#endif /* GL_APPLE_texture_range */
+
+#ifndef GL_APPLE_transform_hint
+#define GL_APPLE_transform_hint 1
+#define GL_TRANSFORM_HINT_APPLE 0x85B1
+#endif /* GL_APPLE_transform_hint */
+
+#ifndef GL_APPLE_vertex_array_object
+#define GL_APPLE_vertex_array_object 1
+#define GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYAPPLEPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSAPPLEPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSAPPLEPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYAPPLEPROC) (GLuint array);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindVertexArrayAPPLE (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArraysAPPLE (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArraysAPPLE (GLsizei n, GLuint *arrays);
+GLAPI GLboolean APIENTRY glIsVertexArrayAPPLE (GLuint array);
+#endif
+#endif /* GL_APPLE_vertex_array_object */
+
+#ifndef GL_APPLE_vertex_array_range
+#define GL_APPLE_vertex_array_range 1
+#define GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define GL_STORAGE_CLIENT_APPLE 0x85B4
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGEAPPLEPROC) (GLsizei length, void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYPARAMETERIAPPLEPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexArrayRangeAPPLE (GLsizei length, void *pointer);
+GLAPI void APIENTRY glFlushVertexArrayRangeAPPLE (GLsizei length, void *pointer);
+GLAPI void APIENTRY glVertexArrayParameteriAPPLE (GLenum pname, GLint param);
+#endif
+#endif /* GL_APPLE_vertex_array_range */
+
+#ifndef GL_APPLE_vertex_program_evaluators
+#define GL_APPLE_vertex_program_evaluators 1
+#define GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBAPPLEPROC) (GLuint index, GLenum pname);
+typedef GLboolean (APIENTRYP PFNGLISVERTEXATTRIBENABLEDAPPLEPROC) (GLuint index, GLenum pname);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB1FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2DAPPLEPROC) (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLMAPVERTEXATTRIB2FAPPLEPROC) (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glEnableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glDisableVertexAttribAPPLE (GLuint index, GLenum pname);
+GLAPI GLboolean APIENTRY glIsVertexAttribEnabledAPPLE (GLuint index, GLenum pname);
+GLAPI void APIENTRY glMapVertexAttrib1dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib1fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI void APIENTRY glMapVertexAttrib2dAPPLE (GLuint index, GLuint size, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI void APIENTRY glMapVertexAttrib2fAPPLE (GLuint index, GLuint size, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+#endif
+#endif /* GL_APPLE_vertex_program_evaluators */
+
+#ifndef GL_APPLE_ycbcr_422
+#define GL_APPLE_ycbcr_422 1
+#define GL_YCBCR_422_APPLE 0x85B9
+#endif /* GL_APPLE_ycbcr_422 */
+
+#ifndef GL_ATI_draw_buffers
+#define GL_ATI_draw_buffers 1
+#define GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define GL_DRAW_BUFFER0_ATI 0x8825
+#define GL_DRAW_BUFFER1_ATI 0x8826
+#define GL_DRAW_BUFFER2_ATI 0x8827
+#define GL_DRAW_BUFFER3_ATI 0x8828
+#define GL_DRAW_BUFFER4_ATI 0x8829
+#define GL_DRAW_BUFFER5_ATI 0x882A
+#define GL_DRAW_BUFFER6_ATI 0x882B
+#define GL_DRAW_BUFFER7_ATI 0x882C
+#define GL_DRAW_BUFFER8_ATI 0x882D
+#define GL_DRAW_BUFFER9_ATI 0x882E
+#define GL_DRAW_BUFFER10_ATI 0x882F
+#define GL_DRAW_BUFFER11_ATI 0x8830
+#define GL_DRAW_BUFFER12_ATI 0x8831
+#define GL_DRAW_BUFFER13_ATI 0x8832
+#define GL_DRAW_BUFFER14_ATI 0x8833
+#define GL_DRAW_BUFFER15_ATI 0x8834
+typedef void (APIENTRYP PFNGLDRAWBUFFERSATIPROC) (GLsizei n, const GLenum *bufs);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawBuffersATI (GLsizei n, const GLenum *bufs);
+#endif
+#endif /* GL_ATI_draw_buffers */
+
+#ifndef GL_ATI_element_array
+#define GL_ATI_element_array 1
+#define GL_ELEMENT_ARRAY_ATI 0x8768
+#define GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+typedef void (APIENTRYP PFNGLELEMENTPOINTERATIPROC) (GLenum type, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWELEMENTARRAYATIPROC) (GLenum mode, GLsizei count);
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTARRAYATIPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glElementPointerATI (GLenum type, const void *pointer);
+GLAPI void APIENTRY glDrawElementArrayATI (GLenum mode, GLsizei count);
+GLAPI void APIENTRY glDrawRangeElementArrayATI (GLenum mode, GLuint start, GLuint end, GLsizei count);
+#endif
+#endif /* GL_ATI_element_array */
+
+#ifndef GL_ATI_envmap_bumpmap
+#define GL_ATI_envmap_bumpmap 1
+#define GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define GL_BUMP_TEX_UNITS_ATI 0x8778
+#define GL_DUDV_ATI 0x8779
+#define GL_DU8DV8_ATI 0x877A
+#define GL_BUMP_ENVMAP_ATI 0x877B
+#define GL_BUMP_TARGET_ATI 0x877C
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERIVATIPROC) (GLenum pname, const GLint *param);
+typedef void (APIENTRYP PFNGLTEXBUMPPARAMETERFVATIPROC) (GLenum pname, const GLfloat *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERIVATIPROC) (GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETTEXBUMPPARAMETERFVATIPROC) (GLenum pname, GLfloat *param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBumpParameterivATI (GLenum pname, const GLint *param);
+GLAPI void APIENTRY glTexBumpParameterfvATI (GLenum pname, const GLfloat *param);
+GLAPI void APIENTRY glGetTexBumpParameterivATI (GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetTexBumpParameterfvATI (GLenum pname, GLfloat *param);
+#endif
+#endif /* GL_ATI_envmap_bumpmap */
+
+#ifndef GL_ATI_fragment_shader
+#define GL_ATI_fragment_shader 1
+#define GL_FRAGMENT_SHADER_ATI 0x8920
+#define GL_REG_0_ATI 0x8921
+#define GL_REG_1_ATI 0x8922
+#define GL_REG_2_ATI 0x8923
+#define GL_REG_3_ATI 0x8924
+#define GL_REG_4_ATI 0x8925
+#define GL_REG_5_ATI 0x8926
+#define GL_REG_6_ATI 0x8927
+#define GL_REG_7_ATI 0x8928
+#define GL_REG_8_ATI 0x8929
+#define GL_REG_9_ATI 0x892A
+#define GL_REG_10_ATI 0x892B
+#define GL_REG_11_ATI 0x892C
+#define GL_REG_12_ATI 0x892D
+#define GL_REG_13_ATI 0x892E
+#define GL_REG_14_ATI 0x892F
+#define GL_REG_15_ATI 0x8930
+#define GL_REG_16_ATI 0x8931
+#define GL_REG_17_ATI 0x8932
+#define GL_REG_18_ATI 0x8933
+#define GL_REG_19_ATI 0x8934
+#define GL_REG_20_ATI 0x8935
+#define GL_REG_21_ATI 0x8936
+#define GL_REG_22_ATI 0x8937
+#define GL_REG_23_ATI 0x8938
+#define GL_REG_24_ATI 0x8939
+#define GL_REG_25_ATI 0x893A
+#define GL_REG_26_ATI 0x893B
+#define GL_REG_27_ATI 0x893C
+#define GL_REG_28_ATI 0x893D
+#define GL_REG_29_ATI 0x893E
+#define GL_REG_30_ATI 0x893F
+#define GL_REG_31_ATI 0x8940
+#define GL_CON_0_ATI 0x8941
+#define GL_CON_1_ATI 0x8942
+#define GL_CON_2_ATI 0x8943
+#define GL_CON_3_ATI 0x8944
+#define GL_CON_4_ATI 0x8945
+#define GL_CON_5_ATI 0x8946
+#define GL_CON_6_ATI 0x8947
+#define GL_CON_7_ATI 0x8948
+#define GL_CON_8_ATI 0x8949
+#define GL_CON_9_ATI 0x894A
+#define GL_CON_10_ATI 0x894B
+#define GL_CON_11_ATI 0x894C
+#define GL_CON_12_ATI 0x894D
+#define GL_CON_13_ATI 0x894E
+#define GL_CON_14_ATI 0x894F
+#define GL_CON_15_ATI 0x8950
+#define GL_CON_16_ATI 0x8951
+#define GL_CON_17_ATI 0x8952
+#define GL_CON_18_ATI 0x8953
+#define GL_CON_19_ATI 0x8954
+#define GL_CON_20_ATI 0x8955
+#define GL_CON_21_ATI 0x8956
+#define GL_CON_22_ATI 0x8957
+#define GL_CON_23_ATI 0x8958
+#define GL_CON_24_ATI 0x8959
+#define GL_CON_25_ATI 0x895A
+#define GL_CON_26_ATI 0x895B
+#define GL_CON_27_ATI 0x895C
+#define GL_CON_28_ATI 0x895D
+#define GL_CON_29_ATI 0x895E
+#define GL_CON_30_ATI 0x895F
+#define GL_CON_31_ATI 0x8960
+#define GL_MOV_ATI 0x8961
+#define GL_ADD_ATI 0x8963
+#define GL_MUL_ATI 0x8964
+#define GL_SUB_ATI 0x8965
+#define GL_DOT3_ATI 0x8966
+#define GL_DOT4_ATI 0x8967
+#define GL_MAD_ATI 0x8968
+#define GL_LERP_ATI 0x8969
+#define GL_CND_ATI 0x896A
+#define GL_CND0_ATI 0x896B
+#define GL_DOT2_ADD_ATI 0x896C
+#define GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define GL_NUM_PASSES_ATI 0x8970
+#define GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define GL_SWIZZLE_STR_ATI 0x8976
+#define GL_SWIZZLE_STQ_ATI 0x8977
+#define GL_SWIZZLE_STR_DR_ATI 0x8978
+#define GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define GL_SWIZZLE_STRQ_ATI 0x897A
+#define GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+#define GL_RED_BIT_ATI 0x00000001
+#define GL_GREEN_BIT_ATI 0x00000002
+#define GL_BLUE_BIT_ATI 0x00000004
+#define GL_2X_BIT_ATI 0x00000001
+#define GL_4X_BIT_ATI 0x00000002
+#define GL_8X_BIT_ATI 0x00000004
+#define GL_HALF_BIT_ATI 0x00000008
+#define GL_QUARTER_BIT_ATI 0x00000010
+#define GL_EIGHTH_BIT_ATI 0x00000020
+#define GL_SATURATE_BIT_ATI 0x00000040
+#define GL_COMP_BIT_ATI 0x00000002
+#define GL_NEGATE_BIT_ATI 0x00000004
+#define GL_BIAS_BIT_ATI 0x00000008
+typedef GLuint (APIENTRYP PFNGLGENFRAGMENTSHADERSATIPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLBINDFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDELETEFRAGMENTSHADERATIPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLENDFRAGMENTSHADERATIPROC) (void);
+typedef void (APIENTRYP PFNGLPASSTEXCOORDATIPROC) (GLuint dst, GLuint coord, GLenum swizzle);
+typedef void (APIENTRYP PFNGLSAMPLEMAPATIPROC) (GLuint dst, GLuint interp, GLenum swizzle);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLCOLORFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP1ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP2ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+typedef void (APIENTRYP PFNGLALPHAFRAGMENTOP3ATIPROC) (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+typedef void (APIENTRYP PFNGLSETFRAGMENTSHADERCONSTANTATIPROC) (GLuint dst, const GLfloat *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenFragmentShadersATI (GLuint range);
+GLAPI void APIENTRY glBindFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glDeleteFragmentShaderATI (GLuint id);
+GLAPI void APIENTRY glBeginFragmentShaderATI (void);
+GLAPI void APIENTRY glEndFragmentShaderATI (void);
+GLAPI void APIENTRY glPassTexCoordATI (GLuint dst, GLuint coord, GLenum swizzle);
+GLAPI void APIENTRY glSampleMapATI (GLuint dst, GLuint interp, GLenum swizzle);
+GLAPI void APIENTRY glColorFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glColorFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glColorFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMask, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glAlphaFragmentOp1ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod);
+GLAPI void APIENTRY glAlphaFragmentOp2ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod);
+GLAPI void APIENTRY glAlphaFragmentOp3ATI (GLenum op, GLuint dst, GLuint dstMod, GLuint arg1, GLuint arg1Rep, GLuint arg1Mod, GLuint arg2, GLuint arg2Rep, GLuint arg2Mod, GLuint arg3, GLuint arg3Rep, GLuint arg3Mod);
+GLAPI void APIENTRY glSetFragmentShaderConstantATI (GLuint dst, const GLfloat *value);
+#endif
+#endif /* GL_ATI_fragment_shader */
+
+#ifndef GL_ATI_map_object_buffer
+#define GL_ATI_map_object_buffer 1
+typedef void *(APIENTRYP PFNGLMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUNMAPOBJECTBUFFERATIPROC) (GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void *APIENTRY glMapObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUnmapObjectBufferATI (GLuint buffer);
+#endif
+#endif /* GL_ATI_map_object_buffer */
+
+#ifndef GL_ATI_meminfo
+#define GL_ATI_meminfo 1
+#define GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+#endif /* GL_ATI_meminfo */
+
+#ifndef GL_ATI_pixel_format_float
+#define GL_ATI_pixel_format_float 1
+#define GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#endif /* GL_ATI_pixel_format_float */
+
+#ifndef GL_ATI_pn_triangles
+#define GL_ATI_pn_triangles 1
+#define GL_PN_TRIANGLES_ATI 0x87F0
+#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+typedef void (APIENTRYP PFNGLPNTRIANGLESIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPNTRIANGLESFATIPROC) (GLenum pname, GLfloat param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPNTrianglesiATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glPNTrianglesfATI (GLenum pname, GLfloat param);
+#endif
+#endif /* GL_ATI_pn_triangles */
+
+#ifndef GL_ATI_separate_stencil
+#define GL_ATI_separate_stencil 1
+#define GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEATIPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEATIPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilOpSeparateATI (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI void APIENTRY glStencilFuncSeparateATI (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask);
+#endif
+#endif /* GL_ATI_separate_stencil */
+
+#ifndef GL_ATI_text_fragment_shader
+#define GL_ATI_text_fragment_shader 1
+#define GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+#endif /* GL_ATI_text_fragment_shader */
+
+#ifndef GL_ATI_texture_env_combine3
+#define GL_ATI_texture_env_combine3 1
+#define GL_MODULATE_ADD_ATI 0x8744
+#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define GL_MODULATE_SUBTRACT_ATI 0x8746
+#endif /* GL_ATI_texture_env_combine3 */
+
+#ifndef GL_ATI_texture_float
+#define GL_ATI_texture_float 1
+#define GL_RGBA_FLOAT32_ATI 0x8814
+#define GL_RGB_FLOAT32_ATI 0x8815
+#define GL_ALPHA_FLOAT32_ATI 0x8816
+#define GL_INTENSITY_FLOAT32_ATI 0x8817
+#define GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define GL_RGBA_FLOAT16_ATI 0x881A
+#define GL_RGB_FLOAT16_ATI 0x881B
+#define GL_ALPHA_FLOAT16_ATI 0x881C
+#define GL_INTENSITY_FLOAT16_ATI 0x881D
+#define GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+#endif /* GL_ATI_texture_float */
+
+#ifndef GL_ATI_texture_mirror_once
+#define GL_ATI_texture_mirror_once 1
+#define GL_MIRROR_CLAMP_ATI 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+#endif /* GL_ATI_texture_mirror_once */
+
+#ifndef GL_ATI_vertex_array_object
+#define GL_ATI_vertex_array_object 1
+#define GL_STATIC_ATI 0x8760
+#define GL_DYNAMIC_ATI 0x8761
+#define GL_PRESERVE_ATI 0x8762
+#define GL_DISCARD_ATI 0x8763
+#define GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+typedef GLuint (APIENTRYP PFNGLNEWOBJECTBUFFERATIPROC) (GLsizei size, const void *pointer, GLenum usage);
+typedef GLboolean (APIENTRYP PFNGLISOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLUPDATEOBJECTBUFFERATIPROC) (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERFVATIPROC) (GLuint buffer, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETOBJECTBUFFERIVATIPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFREEOBJECTBUFFERATIPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLARRAYOBJECTATIPROC) (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTFVATIPROC) (GLenum array, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETARRAYOBJECTIVATIPROC) (GLenum array, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLVARIANTARRAYOBJECTATIPROC) (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTFVATIPROC) (GLuint id, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVARIANTARRAYOBJECTIVATIPROC) (GLuint id, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glNewObjectBufferATI (GLsizei size, const void *pointer, GLenum usage);
+GLAPI GLboolean APIENTRY glIsObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glUpdateObjectBufferATI (GLuint buffer, GLuint offset, GLsizei size, const void *pointer, GLenum preserve);
+GLAPI void APIENTRY glGetObjectBufferfvATI (GLuint buffer, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetObjectBufferivATI (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFreeObjectBufferATI (GLuint buffer);
+GLAPI void APIENTRY glArrayObjectATI (GLenum array, GLint size, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetArrayObjectfvATI (GLenum array, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetArrayObjectivATI (GLenum array, GLenum pname, GLint *params);
+GLAPI void APIENTRY glVariantArrayObjectATI (GLuint id, GLenum type, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVariantArrayObjectfvATI (GLuint id, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVariantArrayObjectivATI (GLuint id, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ATI_vertex_array_object */
+
+#ifndef GL_ATI_vertex_attrib_array_object
+#define GL_ATI_vertex_attrib_array_object 1
+typedef void (APIENTRYP PFNGLVERTEXATTRIBARRAYOBJECTATIPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTFVATIPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBARRAYOBJECTIVATIPROC) (GLuint index, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribArrayObjectATI (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint buffer, GLuint offset);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectfvATI (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribArrayObjectivATI (GLuint index, GLenum pname, GLint *params);
+#endif
+#endif /* GL_ATI_vertex_attrib_array_object */
+
+#ifndef GL_ATI_vertex_streams
+#define GL_ATI_vertex_streams 1
+#define GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define GL_VERTEX_STREAM0_ATI 0x876C
+#define GL_VERTEX_STREAM1_ATI 0x876D
+#define GL_VERTEX_STREAM2_ATI 0x876E
+#define GL_VERTEX_STREAM3_ATI 0x876F
+#define GL_VERTEX_STREAM4_ATI 0x8770
+#define GL_VERTEX_STREAM5_ATI 0x8771
+#define GL_VERTEX_STREAM6_ATI 0x8772
+#define GL_VERTEX_STREAM7_ATI 0x8773
+#define GL_VERTEX_SOURCE_ATI 0x8774
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SATIPROC) (GLenum stream, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IATIPROC) (GLenum stream, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FATIPROC) (GLenum stream, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DATIPROC) (GLenum stream, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM1DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SATIPROC) (GLenum stream, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IATIPROC) (GLenum stream, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FATIPROC) (GLenum stream, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DATIPROC) (GLenum stream, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM2DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IATIPROC) (GLenum stream, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SATIPROC) (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IATIPROC) (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FATIPROC) (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DATIPROC) (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXSTREAM4DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BATIPROC) (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3BVATIPROC) (GLenum stream, const GLbyte *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SATIPROC) (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3SVATIPROC) (GLenum stream, const GLshort *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IATIPROC) (GLenum stream, GLint nx, GLint ny, GLint nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3IVATIPROC) (GLenum stream, const GLint *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FATIPROC) (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3FVATIPROC) (GLenum stream, const GLfloat *coords);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DATIPROC) (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+typedef void (APIENTRYP PFNGLNORMALSTREAM3DVATIPROC) (GLenum stream, const GLdouble *coords);
+typedef void (APIENTRYP PFNGLCLIENTACTIVEVERTEXSTREAMATIPROC) (GLenum stream);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVIATIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLVERTEXBLENDENVFATIPROC) (GLenum pname, GLfloat param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexStream1sATI (GLenum stream, GLshort x);
+GLAPI void APIENTRY glVertexStream1svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream1iATI (GLenum stream, GLint x);
+GLAPI void APIENTRY glVertexStream1ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream1fATI (GLenum stream, GLfloat x);
+GLAPI void APIENTRY glVertexStream1fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream1dATI (GLenum stream, GLdouble x);
+GLAPI void APIENTRY glVertexStream1dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream2sATI (GLenum stream, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexStream2svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream2iATI (GLenum stream, GLint x, GLint y);
+GLAPI void APIENTRY glVertexStream2ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream2fATI (GLenum stream, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexStream2fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream2dATI (GLenum stream, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexStream2dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream3sATI (GLenum stream, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream3iATI (GLenum stream, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream3fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream3dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glVertexStream4sATI (GLenum stream, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexStream4svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glVertexStream4iATI (GLenum stream, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexStream4ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glVertexStream4fATI (GLenum stream, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexStream4fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glVertexStream4dATI (GLenum stream, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexStream4dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glNormalStream3bATI (GLenum stream, GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI void APIENTRY glNormalStream3bvATI (GLenum stream, const GLbyte *coords);
+GLAPI void APIENTRY glNormalStream3sATI (GLenum stream, GLshort nx, GLshort ny, GLshort nz);
+GLAPI void APIENTRY glNormalStream3svATI (GLenum stream, const GLshort *coords);
+GLAPI void APIENTRY glNormalStream3iATI (GLenum stream, GLint nx, GLint ny, GLint nz);
+GLAPI void APIENTRY glNormalStream3ivATI (GLenum stream, const GLint *coords);
+GLAPI void APIENTRY glNormalStream3fATI (GLenum stream, GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI void APIENTRY glNormalStream3fvATI (GLenum stream, const GLfloat *coords);
+GLAPI void APIENTRY glNormalStream3dATI (GLenum stream, GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI void APIENTRY glNormalStream3dvATI (GLenum stream, const GLdouble *coords);
+GLAPI void APIENTRY glClientActiveVertexStreamATI (GLenum stream);
+GLAPI void APIENTRY glVertexBlendEnviATI (GLenum pname, GLint param);
+GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param);
+#endif
+#endif /* GL_ATI_vertex_streams */
+
+#ifndef GL_EXT_422_pixels
+#define GL_EXT_422_pixels 1
+#define GL_422_EXT 0x80CC
+#define GL_422_REV_EXT 0x80CD
+#define GL_422_AVERAGE_EXT 0x80CE
+#define GL_422_REV_AVERAGE_EXT 0x80CF
+#endif /* GL_EXT_422_pixels */
+
+#ifndef GL_EXT_abgr
+#define GL_EXT_abgr 1
+#define GL_ABGR_EXT 0x8000
+#endif /* GL_EXT_abgr */
+
+#ifndef GL_EXT_bgra
+#define GL_EXT_bgra 1
+#define GL_BGR_EXT 0x80E0
+#define GL_BGRA_EXT 0x80E1
+#endif /* GL_EXT_bgra */
+
+#ifndef GL_EXT_bindable_uniform
+#define GL_EXT_bindable_uniform 1
+#define GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+typedef void (APIENTRYP PFNGLUNIFORMBUFFEREXTPROC) (GLuint program, GLint location, GLuint buffer);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMBUFFERSIZEEXTPROC) (GLuint program, GLint location);
+typedef GLintptr (APIENTRYP PFNGLGETUNIFORMOFFSETEXTPROC) (GLuint program, GLint location);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUniformBufferEXT (GLuint program, GLint location, GLuint buffer);
+GLAPI GLint APIENTRY glGetUniformBufferSizeEXT (GLuint program, GLint location);
+GLAPI GLintptr APIENTRY glGetUniformOffsetEXT (GLuint program, GLint location);
+#endif
+#endif /* GL_EXT_bindable_uniform */
+
+#ifndef GL_EXT_blend_color
+#define GL_EXT_blend_color 1
+#define GL_CONSTANT_COLOR_EXT 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define GL_CONSTANT_ALPHA_EXT 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define GL_BLEND_COLOR_EXT 0x8005
+typedef void (APIENTRYP PFNGLBLENDCOLOREXTPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendColorEXT (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#endif
+#endif /* GL_EXT_blend_color */
+
+#ifndef GL_EXT_blend_equation_separate
+#define GL_EXT_blend_equation_separate 1
+#define GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparateEXT (GLenum modeRGB, GLenum modeAlpha);
+#endif
+#endif /* GL_EXT_blend_equation_separate */
+
+#ifndef GL_EXT_blend_func_separate
+#define GL_EXT_blend_func_separate 1
+#define GL_BLEND_DST_RGB_EXT 0x80C8
+#define GL_BLEND_SRC_RGB_EXT 0x80C9
+#define GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT 0x80CB
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateEXT (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+#endif /* GL_EXT_blend_func_separate */
+
+#ifndef GL_EXT_blend_logic_op
+#define GL_EXT_blend_logic_op 1
+#endif /* GL_EXT_blend_logic_op */
+
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#define GL_FUNC_ADD_EXT 0x8006
+#define GL_BLEND_EQUATION_EXT 0x8009
+typedef void (APIENTRYP PFNGLBLENDEQUATIONEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_blend_minmax */
+
+#ifndef GL_EXT_blend_subtract
+#define GL_EXT_blend_subtract 1
+#define GL_FUNC_SUBTRACT_EXT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+#endif /* GL_EXT_blend_subtract */
+
+#ifndef GL_EXT_clip_volume_hint
+#define GL_EXT_clip_volume_hint 1
+#define GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+#endif /* GL_EXT_clip_volume_hint */
+
+#ifndef GL_EXT_cmyka
+#define GL_EXT_cmyka 1
+#define GL_CMYK_EXT 0x800C
+#define GL_CMYKA_EXT 0x800D
+#define GL_PACK_CMYK_HINT_EXT 0x800E
+#define GL_UNPACK_CMYK_HINT_EXT 0x800F
+#endif /* GL_EXT_cmyka */
+
+#ifndef GL_EXT_color_subtable
+#define GL_EXT_color_subtable 1
+typedef void (APIENTRYP PFNGLCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCOPYCOLORSUBTABLEEXTPROC) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorSubTableEXT (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glCopyColorSubTableEXT (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width);
+#endif
+#endif /* GL_EXT_color_subtable */
+
+#ifndef GL_EXT_compiled_vertex_array
+#define GL_EXT_compiled_vertex_array 1
+#define GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+typedef void (APIENTRYP PFNGLLOCKARRAYSEXTPROC) (GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLUNLOCKARRAYSEXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLockArraysEXT (GLint first, GLsizei count);
+GLAPI void APIENTRY glUnlockArraysEXT (void);
+#endif
+#endif /* GL_EXT_compiled_vertex_array */
+
+#ifndef GL_EXT_convolution
+#define GL_EXT_convolution 1
+#define GL_CONVOLUTION_1D_EXT 0x8010
+#define GL_CONVOLUTION_2D_EXT 0x8011
+#define GL_SEPARABLE_2D_EXT 0x8012
+#define GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define GL_REDUCE_EXT 0x8016
+#define GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint params);
+typedef void (APIENTRYP PFNGLCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER1DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYCONVOLUTIONFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *image);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSEPARABLEFILTEREXTPROC) (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+typedef void (APIENTRYP PFNGLSEPARABLEFILTER2DEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *image);
+GLAPI void APIENTRY glConvolutionParameterfEXT (GLenum target, GLenum pname, GLfloat params);
+GLAPI void APIENTRY glConvolutionParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glConvolutionParameteriEXT (GLenum target, GLenum pname, GLint params);
+GLAPI void APIENTRY glConvolutionParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyConvolutionFilter1DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyConvolutionFilter2DEXT (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetConvolutionFilterEXT (GLenum target, GLenum format, GLenum type, void *image);
+GLAPI void APIENTRY glGetConvolutionParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetConvolutionParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetSeparableFilterEXT (GLenum target, GLenum format, GLenum type, void *row, void *column, void *span);
+GLAPI void APIENTRY glSeparableFilter2DEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *row, const void *column);
+#endif
+#endif /* GL_EXT_convolution */
+
+#ifndef GL_EXT_coordinate_frame
+#define GL_EXT_coordinate_frame 1
+#define GL_TANGENT_ARRAY_EXT 0x8439
+#define GL_BINORMAL_ARRAY_EXT 0x843A
+#define GL_CURRENT_TANGENT_EXT 0x843B
+#define GL_CURRENT_BINORMAL_EXT 0x843C
+#define GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define GL_MAP1_TANGENT_EXT 0x8444
+#define GL_MAP2_TANGENT_EXT 0x8445
+#define GL_MAP1_BINORMAL_EXT 0x8446
+#define GL_MAP2_BINORMAL_EXT 0x8447
+typedef void (APIENTRYP PFNGLTANGENT3BEXTPROC) (GLbyte tx, GLbyte ty, GLbyte tz);
+typedef void (APIENTRYP PFNGLTANGENT3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLTANGENT3DEXTPROC) (GLdouble tx, GLdouble ty, GLdouble tz);
+typedef void (APIENTRYP PFNGLTANGENT3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLTANGENT3FEXTPROC) (GLfloat tx, GLfloat ty, GLfloat tz);
+typedef void (APIENTRYP PFNGLTANGENT3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLTANGENT3IEXTPROC) (GLint tx, GLint ty, GLint tz);
+typedef void (APIENTRYP PFNGLTANGENT3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLTANGENT3SEXTPROC) (GLshort tx, GLshort ty, GLshort tz);
+typedef void (APIENTRYP PFNGLTANGENT3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLBINORMAL3BEXTPROC) (GLbyte bx, GLbyte by, GLbyte bz);
+typedef void (APIENTRYP PFNGLBINORMAL3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLBINORMAL3DEXTPROC) (GLdouble bx, GLdouble by, GLdouble bz);
+typedef void (APIENTRYP PFNGLBINORMAL3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLBINORMAL3FEXTPROC) (GLfloat bx, GLfloat by, GLfloat bz);
+typedef void (APIENTRYP PFNGLBINORMAL3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLBINORMAL3IEXTPROC) (GLint bx, GLint by, GLint bz);
+typedef void (APIENTRYP PFNGLBINORMAL3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLBINORMAL3SEXTPROC) (GLshort bx, GLshort by, GLshort bz);
+typedef void (APIENTRYP PFNGLBINORMAL3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLTANGENTPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLBINORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTangent3bEXT (GLbyte tx, GLbyte ty, GLbyte tz);
+GLAPI void APIENTRY glTangent3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glTangent3dEXT (GLdouble tx, GLdouble ty, GLdouble tz);
+GLAPI void APIENTRY glTangent3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glTangent3fEXT (GLfloat tx, GLfloat ty, GLfloat tz);
+GLAPI void APIENTRY glTangent3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glTangent3iEXT (GLint tx, GLint ty, GLint tz);
+GLAPI void APIENTRY glTangent3ivEXT (const GLint *v);
+GLAPI void APIENTRY glTangent3sEXT (GLshort tx, GLshort ty, GLshort tz);
+GLAPI void APIENTRY glTangent3svEXT (const GLshort *v);
+GLAPI void APIENTRY glBinormal3bEXT (GLbyte bx, GLbyte by, GLbyte bz);
+GLAPI void APIENTRY glBinormal3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glBinormal3dEXT (GLdouble bx, GLdouble by, GLdouble bz);
+GLAPI void APIENTRY glBinormal3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glBinormal3fEXT (GLfloat bx, GLfloat by, GLfloat bz);
+GLAPI void APIENTRY glBinormal3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glBinormal3iEXT (GLint bx, GLint by, GLint bz);
+GLAPI void APIENTRY glBinormal3ivEXT (const GLint *v);
+GLAPI void APIENTRY glBinormal3sEXT (GLshort bx, GLshort by, GLshort bz);
+GLAPI void APIENTRY glBinormal3svEXT (const GLshort *v);
+GLAPI void APIENTRY glTangentPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glBinormalPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_coordinate_frame */
+
+#ifndef GL_EXT_copy_texture
+#define GL_EXT_copy_texture 1
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyTexImage1DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTexImage2DEXT (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glCopyTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_EXT_copy_texture */
+
+#ifndef GL_EXT_cull_vertex
+#define GL_EXT_cull_vertex 1
+#define GL_CULL_VERTEX_EXT 0x81AA
+#define GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+typedef void (APIENTRYP PFNGLCULLPARAMETERDVEXTPROC) (GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLCULLPARAMETERFVEXTPROC) (GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCullParameterdvEXT (GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glCullParameterfvEXT (GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_cull_vertex */
+
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+typedef void (APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GLAPI void APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+#endif /* GL_EXT_debug_label */
+
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+typedef void (APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GLAPI void APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GLAPI void APIENTRY glPopGroupMarkerEXT (void);
+#endif
+#endif /* GL_EXT_debug_marker */
+
+#ifndef GL_EXT_depth_bounds_test
+#define GL_EXT_depth_bounds_test 1
+#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define GL_DEPTH_BOUNDS_EXT 0x8891
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSEXTPROC) (GLclampd zmin, GLclampd zmax);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthBoundsEXT (GLclampd zmin, GLclampd zmax);
+#endif
+#endif /* GL_EXT_depth_bounds_test */
+
+#ifndef GL_EXT_direct_state_access
+#define GL_EXT_direct_state_access 1
+#define GL_PROGRAM_MATRIX_EXT 0x8E2D
+#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
+#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
+typedef void (APIENTRYP PFNGLMATRIXLOADFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADIDENTITYEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXROTATEFEXTPROC) (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXROTATEDEXTPROC) (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXSCALEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEFEXTPROC) (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLMATRIXTRANSLATEDEXTPROC) (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLMATRIXFRUSTUMEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXORTHOEXTPROC) (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLMATRIXPOPEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLMATRIXPUSHEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLBINDMULTITEXTUREEXTPROC) (GLenum texunit, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLMULTITEXCOORDPOINTEREXTPROC) (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLMULTITEXENVFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXENVIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENDEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+typedef void (APIENTRYP PFNGLMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENFEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXGENIEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXENVFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXENVIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENDVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENFVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXGENIVEXTPROC) (GLenum texunit, GLenum coord, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLGETFLOATINDEXEDVEXTPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEINDEXEDVEXTPROC) (GLenum target, GLuint index, GLdouble *data);
+typedef void (APIENTRYP PFNGLGETPOINTERINDEXEDVEXTPROC) (GLenum target, GLuint index, void **data);
+typedef void (APIENTRYP PFNGLENABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDINDEXEDEXTPROC) (GLenum target, GLuint index);
+typedef void (APIENTRYP PFNGLGETINTEGERINDEXEDVEXTPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (APIENTRYP PFNGLGETBOOLEANINDEXEDVEXTPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) (GLuint texture, GLenum target, GLint lod, void *img);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) (GLenum texunit, GLenum target, GLint lod, void *img);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXLOADTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEFEXTPROC) (GLenum mode, const GLfloat *m);
+typedef void (APIENTRYP PFNGLMATRIXMULTTRANSPOSEDEXTPROC) (GLenum mode, const GLdouble *m);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFEREXTPROC) (GLuint buffer, GLenum access);
+typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFEREXTPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) (GLuint buffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) (GLuint buffer, GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFEREXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLMULTITEXBUFFEREXTPROC) (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) (GLuint texture, GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) (GLenum texunit, GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) (GLuint program, GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLENABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEIEXTPROC) (GLenum array, GLuint index);
+typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLdouble *params);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) (GLuint program, GLenum target, GLuint index, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) (GLuint program, GLenum target, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) (GLuint program, GLenum target, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMIVEXTPROC) (GLuint program, GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) (GLuint program, GLenum target, GLenum pname, void *string);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) (GLuint renderbuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) (GLuint framebuffer, GLenum target);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATETEXTUREMIPMAPEXTPROC) (GLuint texture, GLenum target);
+typedef void (APIENTRYP PFNGLGENERATEMULTITEXMIPMAPEXTPROC) (GLenum texunit, GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERREADBUFFEREXTPROC) (GLuint framebuffer, GLenum mode);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+typedef void (APIENTRYP PFNGLTEXTURERENDERBUFFEREXTPROC) (GLuint texture, GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLMULTITEXRENDERBUFFEREXTPROC) (GLenum texunit, GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYEXTPROC) (GLuint vaobj, GLenum array);
+typedef void (APIENTRYP PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) (GLuint vaobj, GLuint index);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERVEXTPROC) (GLuint vaobj, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERVEXTPROC) (GLuint vaobj, GLenum pname, void **param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
+typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) (GLuint framebuffer, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) (GLuint framebuffer, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DEXTPROC) (GLuint program, GLint location, GLdouble x);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DEXTPROC) (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4DVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEEXTPROC) (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+typedef void (APIENTRYP PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoaddEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultfEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultdEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixLoadIdentityEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixRotatefEXT (GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixRotatedEXT (GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixScalefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixScaledEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixTranslatefEXT (GLenum mode, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glMatrixTranslatedEXT (GLenum mode, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glMatrixFrustumEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixOrthoEXT (GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glMatrixPopEXT (GLenum mode);
+GLAPI void APIENTRY glMatrixPushEXT (GLenum mode);
+GLAPI void APIENTRY glClientAttribDefaultEXT (GLbitfield mask);
+GLAPI void APIENTRY glPushClientAttribDefaultEXT (GLbitfield mask);
+GLAPI void APIENTRY glTextureParameterfEXT (GLuint texture, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glTextureParameteriEXT (GLuint texture, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetTextureImageEXT (GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+GLAPI void APIENTRY glGetTextureParameterfvEXT (GLuint texture, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureParameterivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureLevelParameterfvEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetTextureLevelParameterivEXT (GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glBindMultiTextureEXT (GLenum texunit, GLenum target, GLuint texture);
+GLAPI void APIENTRY glMultiTexCoordPointerEXT (GLenum texunit, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glMultiTexEnvfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexEnviEXT (GLenum texunit, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexGendEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
+GLAPI void APIENTRY glMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
+GLAPI void APIENTRY glMultiTexGenfEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexGeniEXT (GLenum texunit, GLenum coord, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetMultiTexEnvfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexEnvivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexGendvEXT (GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetMultiTexGenfvEXT (GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexGenivEXT (GLenum texunit, GLenum coord, GLenum pname, GLint *params);
+GLAPI void APIENTRY glMultiTexParameteriEXT (GLenum texunit, GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexParameterfEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI void APIENTRY glCopyMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI void APIENTRY glCopyMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glCopyMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetMultiTexImageEXT (GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+GLAPI void APIENTRY glGetMultiTexParameterfvEXT (GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexParameterivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexLevelParameterfvEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMultiTexLevelParameterivEXT (GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI void APIENTRY glMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glCopyMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glEnableClientStateIndexedEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glDisableClientStateIndexedEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glGetFloatIndexedvEXT (GLenum target, GLuint index, GLfloat *data);
+GLAPI void APIENTRY glGetDoubleIndexedvEXT (GLenum target, GLuint index, GLdouble *data);
+GLAPI void APIENTRY glGetPointerIndexedvEXT (GLenum target, GLuint index, void **data);
+GLAPI void APIENTRY glEnableIndexedEXT (GLenum target, GLuint index);
+GLAPI void APIENTRY glDisableIndexedEXT (GLenum target, GLuint index);
+GLAPI GLboolean APIENTRY glIsEnabledIndexedEXT (GLenum target, GLuint index);
+GLAPI void APIENTRY glGetIntegerIndexedvEXT (GLenum target, GLuint index, GLint *data);
+GLAPI void APIENTRY glGetBooleanIndexedvEXT (GLenum target, GLuint index, GLboolean *data);
+GLAPI void APIENTRY glCompressedTextureImage3DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureImage2DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureImage1DEXT (GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage3DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage2DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedTextureSubImage1DEXT (GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glGetCompressedTextureImageEXT (GLuint texture, GLenum target, GLint lod, void *img);
+GLAPI void APIENTRY glCompressedMultiTexImage3DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexImage2DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexImage1DEXT (GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage3DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage2DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glCompressedMultiTexSubImage1DEXT (GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *bits);
+GLAPI void APIENTRY glGetCompressedMultiTexImageEXT (GLenum texunit, GLenum target, GLint lod, void *img);
+GLAPI void APIENTRY glMatrixLoadTransposefEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixLoadTransposedEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glMatrixMultTransposefEXT (GLenum mode, const GLfloat *m);
+GLAPI void APIENTRY glMatrixMultTransposedEXT (GLenum mode, const GLdouble *m);
+GLAPI void APIENTRY glNamedBufferDataEXT (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI void APIENTRY glNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI void *APIENTRY glMapNamedBufferEXT (GLuint buffer, GLenum access);
+GLAPI GLboolean APIENTRY glUnmapNamedBufferEXT (GLuint buffer);
+GLAPI void APIENTRY glGetNamedBufferParameterivEXT (GLuint buffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedBufferPointervEXT (GLuint buffer, GLenum pname, void **params);
+GLAPI void APIENTRY glGetNamedBufferSubDataEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI void APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0);
+GLAPI void APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GLAPI void APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI void APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI void APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0);
+GLAPI void APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1);
+GLAPI void APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI void APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI void APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GLAPI void APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glTextureBufferEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glMultiTexBufferEXT (GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI void APIENTRY glTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTextureParameterIivEXT (GLuint texture, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTextureParameterIuivEXT (GLuint texture, GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetMultiTexParameterIivEXT (GLenum texunit, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMultiTexParameterIuivEXT (GLenum texunit, GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0);
+GLAPI void APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glNamedProgramLocalParameters4fvEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4iEXT (GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4ivEXT (GLuint program, GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glNamedProgramLocalParametersI4ivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4uiEXT (GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glNamedProgramLocalParameterI4uivEXT (GLuint program, GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glNamedProgramLocalParametersI4uivEXT (GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterIivEXT (GLuint program, GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterIuivEXT (GLuint program, GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glEnableClientStateiEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glDisableClientStateiEXT (GLenum array, GLuint index);
+GLAPI void APIENTRY glGetFloati_vEXT (GLenum pname, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetDoublei_vEXT (GLenum pname, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetPointeri_vEXT (GLenum pname, GLuint index, void **params);
+GLAPI void APIENTRY glNamedProgramStringEXT (GLuint program, GLenum target, GLenum format, GLsizei len, const void *string);
+GLAPI void APIENTRY glNamedProgramLocalParameter4dEXT (GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glNamedProgramLocalParameter4dvEXT (GLuint program, GLenum target, GLuint index, const GLdouble *params);
+GLAPI void APIENTRY glNamedProgramLocalParameter4fEXT (GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glNamedProgramLocalParameter4fvEXT (GLuint program, GLenum target, GLuint index, const GLfloat *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterdvEXT (GLuint program, GLenum target, GLuint index, GLdouble *params);
+GLAPI void APIENTRY glGetNamedProgramLocalParameterfvEXT (GLuint program, GLenum target, GLuint index, GLfloat *params);
+GLAPI void APIENTRY glGetNamedProgramivEXT (GLuint program, GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetNamedProgramStringEXT (GLuint program, GLenum target, GLenum pname, void *string);
+GLAPI void APIENTRY glNamedRenderbufferStorageEXT (GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetNamedRenderbufferParameterivEXT (GLuint renderbuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleEXT (GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleCoverageEXT (GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI GLenum APIENTRY glCheckNamedFramebufferStatusEXT (GLuint framebuffer, GLenum target);
+GLAPI void APIENTRY glNamedFramebufferTexture1DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTexture2DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTexture3DEXT (GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glNamedFramebufferRenderbufferEXT (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetNamedFramebufferAttachmentParameterivEXT (GLuint framebuffer, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateTextureMipmapEXT (GLuint texture, GLenum target);
+GLAPI void APIENTRY glGenerateMultiTexMipmapEXT (GLenum texunit, GLenum target);
+GLAPI void APIENTRY glFramebufferDrawBufferEXT (GLuint framebuffer, GLenum mode);
+GLAPI void APIENTRY glFramebufferDrawBuffersEXT (GLuint framebuffer, GLsizei n, const GLenum *bufs);
+GLAPI void APIENTRY glFramebufferReadBufferEXT (GLuint framebuffer, GLenum mode);
+GLAPI void APIENTRY glGetFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glNamedCopyBufferSubDataEXT (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI void APIENTRY glNamedFramebufferTextureEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glNamedFramebufferTextureLayerEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glNamedFramebufferTextureFaceEXT (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face);
+GLAPI void APIENTRY glTextureRenderbufferEXT (GLuint texture, GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glMultiTexRenderbufferEXT (GLenum texunit, GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glVertexArrayVertexOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayEdgeFlagOffsetEXT (GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayIndexOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayNormalOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayMultiTexCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayFogCoordOffsetEXT (GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArraySecondaryColorOffsetEXT (GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayVertexAttribOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glVertexArrayVertexAttribIOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glEnableVertexArrayEXT (GLuint vaobj, GLenum array);
+GLAPI void APIENTRY glDisableVertexArrayEXT (GLuint vaobj, GLenum array);
+GLAPI void APIENTRY glEnableVertexArrayAttribEXT (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glDisableVertexArrayAttribEXT (GLuint vaobj, GLuint index);
+GLAPI void APIENTRY glGetVertexArrayIntegervEXT (GLuint vaobj, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayPointervEXT (GLuint vaobj, GLenum pname, void **param);
+GLAPI void APIENTRY glGetVertexArrayIntegeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+GLAPI void APIENTRY glGetVertexArrayPointeri_vEXT (GLuint vaobj, GLuint index, GLenum pname, void **param);
+GLAPI void *APIENTRY glMapNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI void APIENTRY glFlushMappedNamedBufferRangeEXT (GLuint buffer, GLintptr offset, GLsizeiptr length);
+GLAPI void APIENTRY glNamedBufferStorageEXT (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags);
+GLAPI void APIENTRY glClearNamedBufferDataEXT (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glClearNamedBufferSubDataEXT (GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data);
+GLAPI void APIENTRY glNamedFramebufferParameteriEXT (GLuint framebuffer, GLenum pname, GLint param);
+GLAPI void APIENTRY glGetNamedFramebufferParameterivEXT (GLuint framebuffer, GLenum pname, GLint *params);
+GLAPI void APIENTRY glProgramUniform1dEXT (GLuint program, GLint location, GLdouble x);
+GLAPI void APIENTRY glProgramUniform2dEXT (GLuint program, GLint location, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glProgramUniform3dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glProgramUniform4dEXT (GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramUniform1dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform2dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform3dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniform4dvEXT (GLuint program, GLint location, GLsizei count, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix2x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix3x4dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x2dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glProgramUniformMatrix4x3dvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble *value);
+GLAPI void APIENTRY glTextureBufferRangeEXT (GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GLAPI void APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GLAPI void APIENTRY glTextureStorage2DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glTextureStorage3DMultisampleEXT (GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI void APIENTRY glVertexArrayBindVertexBufferEXT (GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GLAPI void APIENTRY glVertexArrayVertexAttribFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribIFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex);
+GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor);
+GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
+GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident);
+GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor);
+#endif
+#endif /* GL_EXT_direct_state_access */
+
+#ifndef GL_EXT_draw_buffers2
+#define GL_EXT_draw_buffers2 1
+typedef void (APIENTRYP PFNGLCOLORMASKINDEXEDEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorMaskIndexedEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+#endif
+#endif /* GL_EXT_draw_buffers2 */
+
+#ifndef GL_EXT_draw_instanced
+#define GL_EXT_draw_instanced 1
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
+GLAPI void APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_draw_instanced */
+
+#ifndef GL_EXT_draw_range_elements
+#define GL_EXT_draw_range_elements 1
+#define GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+#endif
+#endif /* GL_EXT_draw_range_elements */
+
+#ifndef GL_EXT_fog_coord
+#define GL_EXT_fog_coord 1
+#define GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define GL_FOG_COORDINATE_EXT 0x8451
+#define GL_FRAGMENT_DEPTH_EXT 0x8452
+#define GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+typedef void (APIENTRYP PFNGLFOGCOORDFEXTPROC) (GLfloat coord);
+typedef void (APIENTRYP PFNGLFOGCOORDFVEXTPROC) (const GLfloat *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDEXTPROC) (GLdouble coord);
+typedef void (APIENTRYP PFNGLFOGCOORDDVEXTPROC) (const GLdouble *coord);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogCoordfEXT (GLfloat coord);
+GLAPI void APIENTRY glFogCoordfvEXT (const GLfloat *coord);
+GLAPI void APIENTRY glFogCoorddEXT (GLdouble coord);
+GLAPI void APIENTRY glFogCoorddvEXT (const GLdouble *coord);
+GLAPI void APIENTRY glFogCoordPointerEXT (GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_fog_coord */
+
+#ifndef GL_EXT_framebuffer_blit
+#define GL_EXT_framebuffer_blit 1
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+#endif /* GL_EXT_framebuffer_blit */
+
+#ifndef GL_EXT_framebuffer_multisample
+#define GL_EXT_framebuffer_multisample 1
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_EXT_framebuffer_multisample */
+
+#ifndef GL_EXT_framebuffer_multisample_blit_scaled
+#define GL_EXT_framebuffer_multisample_blit_scaled 1
+#define GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
+#define GL_SCALED_RESOLVE_NICEST_EXT 0x90BB
+#endif /* GL_EXT_framebuffer_multisample_blit_scaled */
+
+#ifndef GL_EXT_framebuffer_object
+#define GL_EXT_framebuffer_object 1
+#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define GL_FRAMEBUFFER_EXT 0x8D40
+#define GL_RENDERBUFFER_EXT 0x8D41
+#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define GL_STENCIL_INDEX1_EXT 0x8D46
+#define GL_STENCIL_INDEX4_EXT 0x8D47
+#define GL_STENCIL_INDEX8_EXT 0x8D48
+#define GL_STENCIL_INDEX16_EXT 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFEREXTPROC) (GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFEREXTPROC) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSEXTPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSEXTPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEEXTPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFEREXTPROC) (GLuint framebuffer);
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFEREXTPROC) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSEXTPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSEXTPROC) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPEXTPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glIsRenderbufferEXT (GLuint renderbuffer);
+GLAPI void APIENTRY glBindRenderbufferEXT (GLenum target, GLuint renderbuffer);
+GLAPI void APIENTRY glDeleteRenderbuffersEXT (GLsizei n, const GLuint *renderbuffers);
+GLAPI void APIENTRY glGenRenderbuffersEXT (GLsizei n, GLuint *renderbuffers);
+GLAPI void APIENTRY glRenderbufferStorageEXT (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glGetRenderbufferParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI GLboolean APIENTRY glIsFramebufferEXT (GLuint framebuffer);
+GLAPI void APIENTRY glBindFramebufferEXT (GLenum target, GLuint framebuffer);
+GLAPI void APIENTRY glDeleteFramebuffersEXT (GLsizei n, const GLuint *framebuffers);
+GLAPI void APIENTRY glGenFramebuffersEXT (GLsizei n, GLuint *framebuffers);
+GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT (GLenum target);
+GLAPI void APIENTRY glFramebufferTexture1DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture2DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTexture3DEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI void APIENTRY glFramebufferRenderbufferEXT (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI void APIENTRY glGetFramebufferAttachmentParameterivEXT (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGenerateMipmapEXT (GLenum target);
+#endif
+#endif /* GL_EXT_framebuffer_object */
+
+#ifndef GL_EXT_framebuffer_sRGB
+#define GL_EXT_framebuffer_sRGB 1
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#endif /* GL_EXT_framebuffer_sRGB */
+
+#ifndef GL_EXT_geometry_shader4
+#define GL_EXT_geometry_shader4 1
+#define GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define GL_LINES_ADJACENCY_EXT 0x000A
+#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+#endif
+#endif /* GL_EXT_geometry_shader4 */
+
+#ifndef GL_EXT_gpu_program_parameters
+#define GL_EXT_gpu_program_parameters 1
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERS4FVEXTPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramEnvParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, GLsizei count, const GLfloat *params);
+#endif
+#endif /* GL_EXT_gpu_program_parameters */
+
+#ifndef GL_EXT_gpu_shader4
+#define GL_EXT_gpu_shader4 1
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
+#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params);
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLUNIFORM1UIEXTPROC) (GLint location, GLuint v0);
+typedef void (APIENTRYP PFNGLUNIFORM2UIEXTPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (APIENTRYP PFNGLUNIFORM3UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (APIENTRYP PFNGLUNIFORM4UIEXTPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params);
+GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GLAPI GLint APIENTRY glGetFragDataLocationEXT (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glUniform1uiEXT (GLint location, GLuint v0);
+GLAPI void APIENTRY glUniform2uiEXT (GLint location, GLuint v0, GLuint v1);
+GLAPI void APIENTRY glUniform3uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI void APIENTRY glUniform4uiEXT (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value);
+GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value);
+#endif
+#endif /* GL_EXT_gpu_shader4 */
+
+#ifndef GL_EXT_histogram
+#define GL_EXT_histogram 1
+#define GL_HISTOGRAM_EXT 0x8024
+#define GL_PROXY_HISTOGRAM_EXT 0x8025
+#define GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define GL_HISTOGRAM_SINK_EXT 0x802D
+#define GL_MINMAX_EXT 0x802E
+#define GL_MINMAX_FORMAT_EXT 0x802F
+#define GL_MINMAX_SINK_EXT 0x8030
+#define GL_TABLE_TOO_LARGE_EXT 0x8031
+typedef void (APIENTRYP PFNGLGETHISTOGRAMEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETHISTOGRAMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMINMAXEXTPROC) (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMINMAXPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLHISTOGRAMEXTPROC) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLMINMAXEXTPROC) (GLenum target, GLenum internalformat, GLboolean sink);
+typedef void (APIENTRYP PFNGLRESETHISTOGRAMEXTPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLRESETMINMAXEXTPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetHistogramEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetHistogramParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetHistogramParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMinmaxEXT (GLenum target, GLboolean reset, GLenum format, GLenum type, void *values);
+GLAPI void APIENTRY glGetMinmaxParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMinmaxParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glHistogramEXT (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glMinmaxEXT (GLenum target, GLenum internalformat, GLboolean sink);
+GLAPI void APIENTRY glResetHistogramEXT (GLenum target);
+GLAPI void APIENTRY glResetMinmaxEXT (GLenum target);
+#endif
+#endif /* GL_EXT_histogram */
+
+#ifndef GL_EXT_index_array_formats
+#define GL_EXT_index_array_formats 1
+#define GL_IUI_V2F_EXT 0x81AD
+#define GL_IUI_V3F_EXT 0x81AE
+#define GL_IUI_N3F_V2F_EXT 0x81AF
+#define GL_IUI_N3F_V3F_EXT 0x81B0
+#define GL_T2F_IUI_V2F_EXT 0x81B1
+#define GL_T2F_IUI_V3F_EXT 0x81B2
+#define GL_T2F_IUI_N3F_V2F_EXT 0x81B3
+#define GL_T2F_IUI_N3F_V3F_EXT 0x81B4
+#endif /* GL_EXT_index_array_formats */
+
+#ifndef GL_EXT_index_func
+#define GL_EXT_index_func 1
+#define GL_INDEX_TEST_EXT 0x81B5
+#define GL_INDEX_TEST_FUNC_EXT 0x81B6
+#define GL_INDEX_TEST_REF_EXT 0x81B7
+typedef void (APIENTRYP PFNGLINDEXFUNCEXTPROC) (GLenum func, GLclampf ref);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexFuncEXT (GLenum func, GLclampf ref);
+#endif
+#endif /* GL_EXT_index_func */
+
+#ifndef GL_EXT_index_material
+#define GL_EXT_index_material 1
+#define GL_INDEX_MATERIAL_EXT 0x81B8
+#define GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9
+#define GL_INDEX_MATERIAL_FACE_EXT 0x81BA
+typedef void (APIENTRYP PFNGLINDEXMATERIALEXTPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIndexMaterialEXT (GLenum face, GLenum mode);
+#endif
+#endif /* GL_EXT_index_material */
+
+#ifndef GL_EXT_index_texture
+#define GL_EXT_index_texture 1
+#endif /* GL_EXT_index_texture */
+
+#ifndef GL_EXT_light_texture
+#define GL_EXT_light_texture 1
+#define GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define GL_FRAGMENT_NORMAL_EXT 0x834A
+#define GL_FRAGMENT_COLOR_EXT 0x834C
+#define GL_ATTENUATION_EXT 0x834D
+#define GL_SHADOW_ATTENUATION_EXT 0x834E
+#define GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define GL_TEXTURE_LIGHT_EXT 0x8350
+#define GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+typedef void (APIENTRYP PFNGLAPPLYTEXTUREEXTPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLTEXTURELIGHTEXTPROC) (GLenum pname);
+typedef void (APIENTRYP PFNGLTEXTUREMATERIALEXTPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glApplyTextureEXT (GLenum mode);
+GLAPI void APIENTRY glTextureLightEXT (GLenum pname);
+GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode);
+#endif
+#endif /* GL_EXT_light_texture */
+
+#ifndef GL_EXT_misc_attribute
+#define GL_EXT_misc_attribute 1
+#endif /* GL_EXT_misc_attribute */
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GLAPI void APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount);
+#endif
+#endif /* GL_EXT_multi_draw_arrays */
+
+#ifndef GL_EXT_multisample
+#define GL_EXT_multisample 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define GL_SAMPLE_MASK_EXT 0x80A0
+#define GL_1PASS_EXT 0x80A1
+#define GL_2PASS_0_EXT 0x80A2
+#define GL_2PASS_1_EXT 0x80A3
+#define GL_4PASS_0_EXT 0x80A4
+#define GL_4PASS_1_EXT 0x80A5
+#define GL_4PASS_2_EXT 0x80A6
+#define GL_4PASS_3_EXT 0x80A7
+#define GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define GL_SAMPLES_EXT 0x80A9
+#define GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define GL_SAMPLE_PATTERN_EXT 0x80AC
+#define GL_MULTISAMPLE_BIT_EXT 0x20000000
+typedef void (APIENTRYP PFNGLSAMPLEMASKEXTPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNEXTPROC) (GLenum pattern);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskEXT (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern);
+#endif
+#endif /* GL_EXT_multisample */
+
+#ifndef GL_EXT_packed_depth_stencil
+#define GL_EXT_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+#endif /* GL_EXT_packed_depth_stencil */
+
+#ifndef GL_EXT_packed_float
+#define GL_EXT_packed_float 1
+#define GL_R11F_G11F_B10F_EXT 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+#endif /* GL_EXT_packed_float */
+
+#ifndef GL_EXT_packed_pixels
+#define GL_EXT_packed_pixels 1
+#define GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+#endif /* GL_EXT_packed_pixels */
+
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#define GL_COLOR_INDEX1_EXT 0x80E2
+#define GL_COLOR_INDEX2_EXT 0x80E3
+#define GL_COLOR_INDEX4_EXT 0x80E4
+#define GL_COLOR_INDEX8_EXT 0x80E5
+#define GL_COLOR_INDEX12_EXT 0x80E6
+#define GL_COLOR_INDEX16_EXT 0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+typedef void (APIENTRYP PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEEXTPROC) (GLenum target, GLenum format, GLenum type, void *data);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableEXT (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glGetColorTableEXT (GLenum target, GLenum format, GLenum type, void *data);
+GLAPI void APIENTRY glGetColorTableParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetColorTableParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_paletted_texture */
+
+#ifndef GL_EXT_pixel_buffer_object
+#define GL_EXT_pixel_buffer_object 1
+#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#endif /* GL_EXT_pixel_buffer_object */
+
+#ifndef GL_EXT_pixel_transform
+#define GL_EXT_pixel_transform 1
+#define GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define GL_CUBIC_EXT 0x8334
+#define GL_AVERAGE_EXT 0x8335
+#define GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIEXTPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFEXTPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTRANSFORMPARAMETERFVEXTPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTransformParameteriEXT (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTransformParameterfEXT (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTransformParameterivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTransformParameterfvEXT (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTransformParameterivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTransformParameterfvEXT (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_EXT_pixel_transform */
+
+#ifndef GL_EXT_pixel_transform_color_table
+#define GL_EXT_pixel_transform_color_table 1
+#endif /* GL_EXT_pixel_transform_color_table */
+
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfEXT (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvEXT (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_EXT_point_parameters */
+
+#ifndef GL_EXT_polygon_offset
+#define GL_EXT_polygon_offset 1
+#define GL_POLYGON_OFFSET_EXT 0x8037
+#define GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETEXTPROC) (GLfloat factor, GLfloat bias);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonOffsetEXT (GLfloat factor, GLfloat bias);
+#endif
+#endif /* GL_EXT_polygon_offset */
+
+#ifndef GL_EXT_provoking_vertex
+#define GL_EXT_provoking_vertex 1
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define GL_PROVOKING_VERTEX_EXT 0x8E4F
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProvokingVertexEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_provoking_vertex */
+
+#ifndef GL_EXT_rescale_normal
+#define GL_EXT_rescale_normal 1
+#define GL_RESCALE_NORMAL_EXT 0x803A
+#endif /* GL_EXT_rescale_normal */
+
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#define GL_COLOR_SUM_EXT 0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BEXTPROC) (GLbyte red, GLbyte green, GLbyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVEXTPROC) (const GLbyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DEXTPROC) (GLdouble red, GLdouble green, GLdouble blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVEXTPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IEXTPROC) (GLint red, GLint green, GLint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVEXTPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SEXTPROC) (GLshort red, GLshort green, GLshort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVEXTPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVEXTPROC) (const GLubyte *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIEXTPROC) (GLuint red, GLuint green, GLuint blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVEXTPROC) (const GLuint *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USEXTPROC) (GLushort red, GLushort green, GLushort blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVEXTPROC) (const GLushort *v);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSecondaryColor3bEXT (GLbyte red, GLbyte green, GLbyte blue);
+GLAPI void APIENTRY glSecondaryColor3bvEXT (const GLbyte *v);
+GLAPI void APIENTRY glSecondaryColor3dEXT (GLdouble red, GLdouble green, GLdouble blue);
+GLAPI void APIENTRY glSecondaryColor3dvEXT (const GLdouble *v);
+GLAPI void APIENTRY glSecondaryColor3fEXT (GLfloat red, GLfloat green, GLfloat blue);
+GLAPI void APIENTRY glSecondaryColor3fvEXT (const GLfloat *v);
+GLAPI void APIENTRY glSecondaryColor3iEXT (GLint red, GLint green, GLint blue);
+GLAPI void APIENTRY glSecondaryColor3ivEXT (const GLint *v);
+GLAPI void APIENTRY glSecondaryColor3sEXT (GLshort red, GLshort green, GLshort blue);
+GLAPI void APIENTRY glSecondaryColor3svEXT (const GLshort *v);
+GLAPI void APIENTRY glSecondaryColor3ubEXT (GLubyte red, GLubyte green, GLubyte blue);
+GLAPI void APIENTRY glSecondaryColor3ubvEXT (const GLubyte *v);
+GLAPI void APIENTRY glSecondaryColor3uiEXT (GLuint red, GLuint green, GLuint blue);
+GLAPI void APIENTRY glSecondaryColor3uivEXT (const GLuint *v);
+GLAPI void APIENTRY glSecondaryColor3usEXT (GLushort red, GLushort green, GLushort blue);
+GLAPI void APIENTRY glSecondaryColor3usvEXT (const GLushort *v);
+GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_secondary_color */
+
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#define GL_ACTIVE_PROGRAM_EXT 0x8B8D
+typedef void (APIENTRYP PFNGLUSESHADERPROGRAMEXTPROC) (GLenum type, GLuint program);
+typedef void (APIENTRYP PFNGLACTIVEPROGRAMEXTPROC) (GLuint program);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROGRAMEXTPROC) (GLenum type, const GLchar *string);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glUseShaderProgramEXT (GLenum type, GLuint program);
+GLAPI void APIENTRY glActiveProgramEXT (GLuint program);
+GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *string);
+#endif
+#endif /* GL_EXT_separate_shader_objects */
+
+#ifndef GL_EXT_separate_specular_color
+#define GL_EXT_separate_specular_color 1
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif /* GL_EXT_separate_specular_color */
+
+#ifndef GL_EXT_shader_image_load_formatted
+#define GL_EXT_shader_image_load_formatted 1
+#endif /* GL_EXT_shader_image_load_formatted */
+
+#ifndef GL_EXT_shader_image_load_store
+#define GL_EXT_shader_image_load_store 1
+#define GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define GL_IMAGE_1D_EXT 0x904C
+#define GL_IMAGE_2D_EXT 0x904D
+#define GL_IMAGE_3D_EXT 0x904E
+#define GL_IMAGE_2D_RECT_EXT 0x904F
+#define GL_IMAGE_CUBE_EXT 0x9050
+#define GL_IMAGE_BUFFER_EXT 0x9051
+#define GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define GL_INT_IMAGE_1D_EXT 0x9057
+#define GL_INT_IMAGE_2D_EXT 0x9058
+#define GL_INT_IMAGE_3D_EXT 0x9059
+#define GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define GL_INT_IMAGE_CUBE_EXT 0x905B
+#define GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREEXTPROC) (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+typedef void (APIENTRYP PFNGLMEMORYBARRIEREXTPROC) (GLbitfield barriers);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindImageTextureEXT (GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format);
+GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers);
+#endif
+#endif /* GL_EXT_shader_image_load_store */
+
+#ifndef GL_EXT_shader_integer_mix
+#define GL_EXT_shader_integer_mix 1
+#endif /* GL_EXT_shader_integer_mix */
+
+#ifndef GL_EXT_shadow_funcs
+#define GL_EXT_shadow_funcs 1
+#endif /* GL_EXT_shadow_funcs */
+
+#ifndef GL_EXT_shared_texture_palette
+#define GL_EXT_shared_texture_palette 1
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+#endif /* GL_EXT_shared_texture_palette */
+
+#ifndef GL_EXT_stencil_clear_tag
+#define GL_EXT_stencil_clear_tag 1
+#define GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+typedef void (APIENTRYP PFNGLSTENCILCLEARTAGEXTPROC) (GLsizei stencilTagBits, GLuint stencilClearTag);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStencilClearTagEXT (GLsizei stencilTagBits, GLuint stencilClearTag);
+#endif
+#endif /* GL_EXT_stencil_clear_tag */
+
+#ifndef GL_EXT_stencil_two_side
+#define GL_EXT_stencil_two_side 1
+#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+typedef void (APIENTRYP PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveStencilFaceEXT (GLenum face);
+#endif
+#endif /* GL_EXT_stencil_two_side */
+
+#ifndef GL_EXT_stencil_wrap
+#define GL_EXT_stencil_wrap 1
+#define GL_INCR_WRAP_EXT 0x8507
+#define GL_DECR_WRAP_EXT 0x8508
+#endif /* GL_EXT_stencil_wrap */
+
+#ifndef GL_EXT_subtexture
+#define GL_EXT_subtexture 1
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexSubImage1DEXT (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage2DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_EXT_subtexture */
+
+#ifndef GL_EXT_texture
+#define GL_EXT_texture 1
+#define GL_ALPHA4_EXT 0x803B
+#define GL_ALPHA8_EXT 0x803C
+#define GL_ALPHA12_EXT 0x803D
+#define GL_ALPHA16_EXT 0x803E
+#define GL_LUMINANCE4_EXT 0x803F
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE12_EXT 0x8041
+#define GL_LUMINANCE16_EXT 0x8042
+#define GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define GL_INTENSITY_EXT 0x8049
+#define GL_INTENSITY4_EXT 0x804A
+#define GL_INTENSITY8_EXT 0x804B
+#define GL_INTENSITY12_EXT 0x804C
+#define GL_INTENSITY16_EXT 0x804D
+#define GL_RGB2_EXT 0x804E
+#define GL_RGB4_EXT 0x804F
+#define GL_RGB5_EXT 0x8050
+#define GL_RGB8_EXT 0x8051
+#define GL_RGB10_EXT 0x8052
+#define GL_RGB12_EXT 0x8053
+#define GL_RGB16_EXT 0x8054
+#define GL_RGBA2_EXT 0x8055
+#define GL_RGBA4_EXT 0x8056
+#define GL_RGB5_A1_EXT 0x8057
+#define GL_RGBA8_EXT 0x8058
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGBA12_EXT 0x805A
+#define GL_RGBA16_EXT 0x805B
+#define GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define GL_REPLACE_EXT 0x8062
+#define GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define GL_PROXY_TEXTURE_2D_EXT 0x8064
+#define GL_TEXTURE_TOO_LARGE_EXT 0x8065
+#endif /* GL_EXT_texture */
+
+#ifndef GL_EXT_texture3D
+#define GL_EXT_texture3D 1
+#define GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define GL_TEXTURE_3D_EXT 0x806F
+#define GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define GL_TEXTURE_DEPTH_EXT 0x8071
+#define GL_TEXTURE_WRAP_R_EXT 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+typedef void (APIENTRYP PFNGLTEXIMAGE3DEXTPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage3DEXT (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage3DEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_EXT_texture3D */
+
+#ifndef GL_EXT_texture_array
+#define GL_EXT_texture_array 1
+#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+#endif /* GL_EXT_texture_array */
+
+#ifndef GL_EXT_texture_buffer_object
+#define GL_EXT_texture_buffer_object 1
+#define GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+typedef void (APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer);
+#endif
+#endif /* GL_EXT_texture_buffer_object */
+
+#ifndef GL_EXT_texture_compression_latc
+#define GL_EXT_texture_compression_latc 1
+#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+#endif /* GL_EXT_texture_compression_latc */
+
+#ifndef GL_EXT_texture_compression_rgtc
+#define GL_EXT_texture_compression_rgtc 1
+#define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#endif /* GL_EXT_texture_compression_rgtc */
+
+#ifndef GL_EXT_texture_compression_s3tc
+#define GL_EXT_texture_compression_s3tc 1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#endif /* GL_EXT_texture_compression_s3tc */
+
+#ifndef GL_EXT_texture_cube_map
+#define GL_EXT_texture_cube_map 1
+#define GL_NORMAL_MAP_EXT 0x8511
+#define GL_REFLECTION_MAP_EXT 0x8512
+#define GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+#endif /* GL_EXT_texture_cube_map */
+
+#ifndef GL_EXT_texture_env_add
+#define GL_EXT_texture_env_add 1
+#endif /* GL_EXT_texture_env_add */
+
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#define GL_COMBINE_EXT 0x8570
+#define GL_COMBINE_RGB_EXT 0x8571
+#define GL_COMBINE_ALPHA_EXT 0x8572
+#define GL_RGB_SCALE_EXT 0x8573
+#define GL_ADD_SIGNED_EXT 0x8574
+#define GL_INTERPOLATE_EXT 0x8575
+#define GL_CONSTANT_EXT 0x8576
+#define GL_PRIMARY_COLOR_EXT 0x8577
+#define GL_PREVIOUS_EXT 0x8578
+#define GL_SOURCE0_RGB_EXT 0x8580
+#define GL_SOURCE1_RGB_EXT 0x8581
+#define GL_SOURCE2_RGB_EXT 0x8582
+#define GL_SOURCE0_ALPHA_EXT 0x8588
+#define GL_SOURCE1_ALPHA_EXT 0x8589
+#define GL_SOURCE2_ALPHA_EXT 0x858A
+#define GL_OPERAND0_RGB_EXT 0x8590
+#define GL_OPERAND1_RGB_EXT 0x8591
+#define GL_OPERAND2_RGB_EXT 0x8592
+#define GL_OPERAND0_ALPHA_EXT 0x8598
+#define GL_OPERAND1_ALPHA_EXT 0x8599
+#define GL_OPERAND2_ALPHA_EXT 0x859A
+#endif /* GL_EXT_texture_env_combine */
+
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#define GL_DOT3_RGB_EXT 0x8740
+#define GL_DOT3_RGBA_EXT 0x8741
+#endif /* GL_EXT_texture_env_dot3 */
+
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif /* GL_EXT_texture_filter_anisotropic */
+
+#ifndef GL_EXT_texture_integer
+#define GL_EXT_texture_integer 1
+#define GL_RGBA32UI_EXT 0x8D70
+#define GL_RGB32UI_EXT 0x8D71
+#define GL_ALPHA32UI_EXT 0x8D72
+#define GL_INTENSITY32UI_EXT 0x8D73
+#define GL_LUMINANCE32UI_EXT 0x8D74
+#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define GL_RGBA16UI_EXT 0x8D76
+#define GL_RGB16UI_EXT 0x8D77
+#define GL_ALPHA16UI_EXT 0x8D78
+#define GL_INTENSITY16UI_EXT 0x8D79
+#define GL_LUMINANCE16UI_EXT 0x8D7A
+#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define GL_RGBA8UI_EXT 0x8D7C
+#define GL_RGB8UI_EXT 0x8D7D
+#define GL_ALPHA8UI_EXT 0x8D7E
+#define GL_INTENSITY8UI_EXT 0x8D7F
+#define GL_LUMINANCE8UI_EXT 0x8D80
+#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define GL_RGBA32I_EXT 0x8D82
+#define GL_RGB32I_EXT 0x8D83
+#define GL_ALPHA32I_EXT 0x8D84
+#define GL_INTENSITY32I_EXT 0x8D85
+#define GL_LUMINANCE32I_EXT 0x8D86
+#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define GL_RGBA16I_EXT 0x8D88
+#define GL_RGB16I_EXT 0x8D89
+#define GL_ALPHA16I_EXT 0x8D8A
+#define GL_INTENSITY16I_EXT 0x8D8B
+#define GL_LUMINANCE16I_EXT 0x8D8C
+#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define GL_RGBA8I_EXT 0x8D8E
+#define GL_RGB8I_EXT 0x8D8F
+#define GL_ALPHA8I_EXT 0x8D90
+#define GL_INTENSITY8I_EXT 0x8D91
+#define GL_LUMINANCE8I_EXT 0x8D92
+#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define GL_RED_INTEGER_EXT 0x8D94
+#define GL_GREEN_INTEGER_EXT 0x8D95
+#define GL_BLUE_INTEGER_EXT 0x8D96
+#define GL_ALPHA_INTEGER_EXT 0x8D97
+#define GL_RGB_INTEGER_EXT 0x8D98
+#define GL_RGBA_INTEGER_EXT 0x8D99
+#define GL_BGR_INTEGER_EXT 0x8D9A
+#define GL_BGRA_INTEGER_EXT 0x8D9B
+#define GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLCLEARCOLORIIEXTPROC) (GLint red, GLint green, GLint blue, GLint alpha);
+typedef void (APIENTRYP PFNGLCLEARCOLORIUIEXTPROC) (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params);
+GLAPI void APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glClearColorIiEXT (GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI void APIENTRY glClearColorIuiEXT (GLuint red, GLuint green, GLuint blue, GLuint alpha);
+#endif
+#endif /* GL_EXT_texture_integer */
+
+#ifndef GL_EXT_texture_lod_bias
+#define GL_EXT_texture_lod_bias 1
+#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#endif /* GL_EXT_texture_lod_bias */
+
+#ifndef GL_EXT_texture_mirror_clamp
+#define GL_EXT_texture_mirror_clamp 1
+#define GL_MIRROR_CLAMP_EXT 0x8742
+#define GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#endif /* GL_EXT_texture_mirror_clamp */
+
+#ifndef GL_EXT_texture_object
+#define GL_EXT_texture_object 1
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define GL_TEXTURE_3D_BINDING_EXT 0x806A
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTEXTPROC) (GLsizei n, const GLuint *textures, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDTEXTUREEXTPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESEXTPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESEXTPROC) (GLsizei n, GLuint *textures);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREEXTPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESEXTPROC) (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreTexturesResidentEXT (GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI void APIENTRY glBindTextureEXT (GLenum target, GLuint texture);
+GLAPI void APIENTRY glDeleteTexturesEXT (GLsizei n, const GLuint *textures);
+GLAPI void APIENTRY glGenTexturesEXT (GLsizei n, GLuint *textures);
+GLAPI GLboolean APIENTRY glIsTextureEXT (GLuint texture);
+GLAPI void APIENTRY glPrioritizeTexturesEXT (GLsizei n, const GLuint *textures, const GLclampf *priorities);
+#endif
+#endif /* GL_EXT_texture_object */
+
+#ifndef GL_EXT_texture_perturb_normal
+#define GL_EXT_texture_perturb_normal 1
+#define GL_PERTURB_EXT 0x85AE
+#define GL_TEXTURE_NORMAL_EXT 0x85AF
+typedef void (APIENTRYP PFNGLTEXTURENORMALEXTPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureNormalEXT (GLenum mode);
+#endif
+#endif /* GL_EXT_texture_perturb_normal */
+
+#ifndef GL_EXT_texture_sRGB
+#define GL_EXT_texture_sRGB 1
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB8_EXT 0x8C41
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define GL_SLUMINANCE_EXT 0x8C46
+#define GL_SLUMINANCE8_EXT 0x8C47
+#define GL_COMPRESSED_SRGB_EXT 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#endif /* GL_EXT_texture_sRGB */
+
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#endif /* GL_EXT_texture_sRGB_decode */
+
+#ifndef GL_EXT_texture_shared_exponent
+#define GL_EXT_texture_shared_exponent 1
+#define GL_RGB9_E5_EXT 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+#endif /* GL_EXT_texture_shared_exponent */
+
+#ifndef GL_EXT_texture_snorm
+#define GL_EXT_texture_snorm 1
+#define GL_ALPHA_SNORM 0x9010
+#define GL_LUMINANCE_SNORM 0x9011
+#define GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define GL_INTENSITY_SNORM 0x9013
+#define GL_ALPHA8_SNORM 0x9014
+#define GL_LUMINANCE8_SNORM 0x9015
+#define GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define GL_INTENSITY8_SNORM 0x9017
+#define GL_ALPHA16_SNORM 0x9018
+#define GL_LUMINANCE16_SNORM 0x9019
+#define GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define GL_INTENSITY16_SNORM 0x901B
+#define GL_RED_SNORM 0x8F90
+#define GL_RG_SNORM 0x8F91
+#define GL_RGB_SNORM 0x8F92
+#define GL_RGBA_SNORM 0x8F93
+#endif /* GL_EXT_texture_snorm */
+
+#ifndef GL_EXT_texture_swizzle
+#define GL_EXT_texture_swizzle 1
+#define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+#endif /* GL_EXT_texture_swizzle */
+
+#ifndef GL_EXT_timer_query
+#define GL_EXT_timer_query 1
+#define GL_TIME_ELAPSED_EXT 0x88BF
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GLAPI void APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+#endif /* GL_EXT_timer_query */
+
+#ifndef GL_EXT_transform_feedback
+#define GL_EXT_transform_feedback 1
+#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKEXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETEXTPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEEXTPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackEXT (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackEXT (void);
+GLAPI void APIENTRY glBindBufferRangeEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetEXT (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseEXT (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsEXT (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingEXT (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+#endif
+#endif /* GL_EXT_transform_feedback */
+
+#ifndef GL_EXT_vertex_array
+#define GL_EXT_vertex_array 1
+#define GL_VERTEX_ARRAY_EXT 0x8074
+#define GL_NORMAL_ARRAY_EXT 0x8075
+#define GL_COLOR_ARRAY_EXT 0x8076
+#define GL_INDEX_ARRAY_EXT 0x8077
+#define GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+typedef void (APIENTRYP PFNGLARRAYELEMENTEXTPROC) (GLint i);
+typedef void (APIENTRYP PFNGLCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLDRAWARRAYSEXTPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTEREXTPROC) (GLsizei stride, GLsizei count, const GLboolean *pointer);
+typedef void (APIENTRYP PFNGLGETPOINTERVEXTPROC) (GLenum pname, void **params);
+typedef void (APIENTRYP PFNGLINDEXPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTEREXTPROC) (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glArrayElementEXT (GLint i);
+GLAPI void APIENTRY glColorPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glDrawArraysEXT (GLenum mode, GLint first, GLsizei count);
+GLAPI void APIENTRY glEdgeFlagPointerEXT (GLsizei stride, GLsizei count, const GLboolean *pointer);
+GLAPI void APIENTRY glGetPointervEXT (GLenum pname, void **params);
+GLAPI void APIENTRY glIndexPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glNormalPointerEXT (GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glTexCoordPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+GLAPI void APIENTRY glVertexPointerEXT (GLint size, GLenum type, GLsizei stride, GLsizei count, const void *pointer);
+#endif
+#endif /* GL_EXT_vertex_array */
+
+#ifndef GL_EXT_vertex_array_bgra
+#define GL_EXT_vertex_array_bgra 1
+#endif /* GL_EXT_vertex_array_bgra */
+
+#ifndef GL_EXT_vertex_attrib_64bit
+#define GL_EXT_vertex_attrib_64bit 1
+#define GL_DOUBLE_VEC2_EXT 0x8FFC
+#define GL_DOUBLE_VEC3_EXT 0x8FFD
+#define GL_DOUBLE_VEC4_EXT 0x8FFE
+#define GL_DOUBLE_MAT2_EXT 0x8F46
+#define GL_DOUBLE_MAT3_EXT 0x8F47
+#define GL_DOUBLE_MAT4_EXT 0x8F48
+#define GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define GL_DOUBLE_MAT4x3_EXT 0x8F4E
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DEXTPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DEXTPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DEXTPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4DVEXTPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLDVEXTPROC) (GLuint index, GLenum pname, GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1dEXT (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttribL2dEXT (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttribL3dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttribL4dEXT (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttribL1dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL2dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL3dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribL4dvEXT (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribLPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribLdvEXT (GLuint index, GLenum pname, GLdouble *params);
+#endif
+#endif /* GL_EXT_vertex_attrib_64bit */
+
+#ifndef GL_EXT_vertex_shader
+#define GL_EXT_vertex_shader 1
+#define GL_VERTEX_SHADER_EXT 0x8780
+#define GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define GL_OP_INDEX_EXT 0x8782
+#define GL_OP_NEGATE_EXT 0x8783
+#define GL_OP_DOT3_EXT 0x8784
+#define GL_OP_DOT4_EXT 0x8785
+#define GL_OP_MUL_EXT 0x8786
+#define GL_OP_ADD_EXT 0x8787
+#define GL_OP_MADD_EXT 0x8788
+#define GL_OP_FRAC_EXT 0x8789
+#define GL_OP_MAX_EXT 0x878A
+#define GL_OP_MIN_EXT 0x878B
+#define GL_OP_SET_GE_EXT 0x878C
+#define GL_OP_SET_LT_EXT 0x878D
+#define GL_OP_CLAMP_EXT 0x878E
+#define GL_OP_FLOOR_EXT 0x878F
+#define GL_OP_ROUND_EXT 0x8790
+#define GL_OP_EXP_BASE_2_EXT 0x8791
+#define GL_OP_LOG_BASE_2_EXT 0x8792
+#define GL_OP_POWER_EXT 0x8793
+#define GL_OP_RECIP_EXT 0x8794
+#define GL_OP_RECIP_SQRT_EXT 0x8795
+#define GL_OP_SUB_EXT 0x8796
+#define GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define GL_OP_MOV_EXT 0x8799
+#define GL_OUTPUT_VERTEX_EXT 0x879A
+#define GL_OUTPUT_COLOR0_EXT 0x879B
+#define GL_OUTPUT_COLOR1_EXT 0x879C
+#define GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define GL_OUTPUT_FOG_EXT 0x87BD
+#define GL_SCALAR_EXT 0x87BE
+#define GL_VECTOR_EXT 0x87BF
+#define GL_MATRIX_EXT 0x87C0
+#define GL_VARIANT_EXT 0x87C1
+#define GL_INVARIANT_EXT 0x87C2
+#define GL_LOCAL_CONSTANT_EXT 0x87C3
+#define GL_LOCAL_EXT 0x87C4
+#define GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define GL_X_EXT 0x87D5
+#define GL_Y_EXT 0x87D6
+#define GL_Z_EXT 0x87D7
+#define GL_W_EXT 0x87D8
+#define GL_NEGATIVE_X_EXT 0x87D9
+#define GL_NEGATIVE_Y_EXT 0x87DA
+#define GL_NEGATIVE_Z_EXT 0x87DB
+#define GL_NEGATIVE_W_EXT 0x87DC
+#define GL_ZERO_EXT 0x87DD
+#define GL_ONE_EXT 0x87DE
+#define GL_NEGATIVE_ONE_EXT 0x87DF
+#define GL_NORMALIZED_RANGE_EXT 0x87E0
+#define GL_FULL_RANGE_EXT 0x87E1
+#define GL_CURRENT_VERTEX_EXT 0x87E2
+#define GL_MVP_MATRIX_EXT 0x87E3
+#define GL_VARIANT_VALUE_EXT 0x87E4
+#define GL_VARIANT_DATATYPE_EXT 0x87E5
+#define GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define GL_VARIANT_ARRAY_EXT 0x87E8
+#define GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define GL_INVARIANT_VALUE_EXT 0x87EA
+#define GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+typedef void (APIENTRYP PFNGLBEGINVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLENDVERTEXSHADEREXTPROC) (void);
+typedef void (APIENTRYP PFNGLBINDVERTEXSHADEREXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLGENVERTEXSHADERSEXTPROC) (GLuint range);
+typedef void (APIENTRYP PFNGLDELETEVERTEXSHADEREXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLSHADEROP1EXTPROC) (GLenum op, GLuint res, GLuint arg1);
+typedef void (APIENTRYP PFNGLSHADEROP2EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+typedef void (APIENTRYP PFNGLSHADEROP3EXTPROC) (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+typedef void (APIENTRYP PFNGLSWIZZLEEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLWRITEMASKEXTPROC) (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+typedef void (APIENTRYP PFNGLINSERTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef void (APIENTRYP PFNGLEXTRACTCOMPONENTEXTPROC) (GLuint res, GLuint src, GLuint num);
+typedef GLuint (APIENTRYP PFNGLGENSYMBOLSEXTPROC) (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+typedef void (APIENTRYP PFNGLSETINVARIANTEXTPROC) (GLuint id, GLenum type, const void *addr);
+typedef void (APIENTRYP PFNGLSETLOCALCONSTANTEXTPROC) (GLuint id, GLenum type, const void *addr);
+typedef void (APIENTRYP PFNGLVARIANTBVEXTPROC) (GLuint id, const GLbyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTSVEXTPROC) (GLuint id, const GLshort *addr);
+typedef void (APIENTRYP PFNGLVARIANTIVEXTPROC) (GLuint id, const GLint *addr);
+typedef void (APIENTRYP PFNGLVARIANTFVEXTPROC) (GLuint id, const GLfloat *addr);
+typedef void (APIENTRYP PFNGLVARIANTDVEXTPROC) (GLuint id, const GLdouble *addr);
+typedef void (APIENTRYP PFNGLVARIANTUBVEXTPROC) (GLuint id, const GLubyte *addr);
+typedef void (APIENTRYP PFNGLVARIANTUSVEXTPROC) (GLuint id, const GLushort *addr);
+typedef void (APIENTRYP PFNGLVARIANTUIVEXTPROC) (GLuint id, const GLuint *addr);
+typedef void (APIENTRYP PFNGLVARIANTPOINTEREXTPROC) (GLuint id, GLenum type, GLuint stride, const void *addr);
+typedef void (APIENTRYP PFNGLENABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLDISABLEVARIANTCLIENTSTATEEXTPROC) (GLuint id);
+typedef GLuint (APIENTRYP PFNGLBINDLIGHTPARAMETEREXTPROC) (GLenum light, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDMATERIALPARAMETEREXTPROC) (GLenum face, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXGENPARAMETEREXTPROC) (GLenum unit, GLenum coord, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDTEXTUREUNITPARAMETEREXTPROC) (GLenum unit, GLenum value);
+typedef GLuint (APIENTRYP PFNGLBINDPARAMETEREXTPROC) (GLenum value);
+typedef GLboolean (APIENTRYP PFNGLISVARIANTENABLEDEXTPROC) (GLuint id, GLenum cap);
+typedef void (APIENTRYP PFNGLGETVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETVARIANTPOINTERVEXTPROC) (GLuint id, GLenum value, void **data);
+typedef void (APIENTRYP PFNGLGETINVARIANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETINVARIANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTBOOLEANVEXTPROC) (GLuint id, GLenum value, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTINTEGERVEXTPROC) (GLuint id, GLenum value, GLint *data);
+typedef void (APIENTRYP PFNGLGETLOCALCONSTANTFLOATVEXTPROC) (GLuint id, GLenum value, GLfloat *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVertexShaderEXT (void);
+GLAPI void APIENTRY glEndVertexShaderEXT (void);
+GLAPI void APIENTRY glBindVertexShaderEXT (GLuint id);
+GLAPI GLuint APIENTRY glGenVertexShadersEXT (GLuint range);
+GLAPI void APIENTRY glDeleteVertexShaderEXT (GLuint id);
+GLAPI void APIENTRY glShaderOp1EXT (GLenum op, GLuint res, GLuint arg1);
+GLAPI void APIENTRY glShaderOp2EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2);
+GLAPI void APIENTRY glShaderOp3EXT (GLenum op, GLuint res, GLuint arg1, GLuint arg2, GLuint arg3);
+GLAPI void APIENTRY glSwizzleEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glWriteMaskEXT (GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW);
+GLAPI void APIENTRY glInsertComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI void APIENTRY glExtractComponentEXT (GLuint res, GLuint src, GLuint num);
+GLAPI GLuint APIENTRY glGenSymbolsEXT (GLenum datatype, GLenum storagetype, GLenum range, GLuint components);
+GLAPI void APIENTRY glSetInvariantEXT (GLuint id, GLenum type, const void *addr);
+GLAPI void APIENTRY glSetLocalConstantEXT (GLuint id, GLenum type, const void *addr);
+GLAPI void APIENTRY glVariantbvEXT (GLuint id, const GLbyte *addr);
+GLAPI void APIENTRY glVariantsvEXT (GLuint id, const GLshort *addr);
+GLAPI void APIENTRY glVariantivEXT (GLuint id, const GLint *addr);
+GLAPI void APIENTRY glVariantfvEXT (GLuint id, const GLfloat *addr);
+GLAPI void APIENTRY glVariantdvEXT (GLuint id, const GLdouble *addr);
+GLAPI void APIENTRY glVariantubvEXT (GLuint id, const GLubyte *addr);
+GLAPI void APIENTRY glVariantusvEXT (GLuint id, const GLushort *addr);
+GLAPI void APIENTRY glVariantuivEXT (GLuint id, const GLuint *addr);
+GLAPI void APIENTRY glVariantPointerEXT (GLuint id, GLenum type, GLuint stride, const void *addr);
+GLAPI void APIENTRY glEnableVariantClientStateEXT (GLuint id);
+GLAPI void APIENTRY glDisableVariantClientStateEXT (GLuint id);
+GLAPI GLuint APIENTRY glBindLightParameterEXT (GLenum light, GLenum value);
+GLAPI GLuint APIENTRY glBindMaterialParameterEXT (GLenum face, GLenum value);
+GLAPI GLuint APIENTRY glBindTexGenParameterEXT (GLenum unit, GLenum coord, GLenum value);
+GLAPI GLuint APIENTRY glBindTextureUnitParameterEXT (GLenum unit, GLenum value);
+GLAPI GLuint APIENTRY glBindParameterEXT (GLenum value);
+GLAPI GLboolean APIENTRY glIsVariantEnabledEXT (GLuint id, GLenum cap);
+GLAPI void APIENTRY glGetVariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetVariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetVariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetVariantPointervEXT (GLuint id, GLenum value, void **data);
+GLAPI void APIENTRY glGetInvariantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetInvariantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetInvariantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+GLAPI void APIENTRY glGetLocalConstantBooleanvEXT (GLuint id, GLenum value, GLboolean *data);
+GLAPI void APIENTRY glGetLocalConstantIntegervEXT (GLuint id, GLenum value, GLint *data);
+GLAPI void APIENTRY glGetLocalConstantFloatvEXT (GLuint id, GLenum value, GLfloat *data);
+#endif
+#endif /* GL_EXT_vertex_shader */
+
+#ifndef GL_EXT_vertex_weighting
+#define GL_EXT_vertex_weighting 1
+#define GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define GL_VERTEX_WEIGHTING_EXT 0x8509
+#define GL_MODELVIEW0_EXT 0x1700
+#define GL_MODELVIEW1_EXT 0x850A
+#define GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFEXTPROC) (GLfloat weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTFVEXTPROC) (const GLfloat *weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexWeightfEXT (GLfloat weight);
+GLAPI void APIENTRY glVertexWeightfvEXT (const GLfloat *weight);
+GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_EXT_vertex_weighting */
+
+#ifndef GL_EXT_x11_sync_object
+#define GL_EXT_x11_sync_object 1
+#define GL_SYNC_X11_FENCE_EXT 0x90E1
+typedef GLsync (APIENTRYP PFNGLIMPORTSYNCEXTPROC) (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLsync APIENTRY glImportSyncEXT (GLenum external_sync_type, GLintptr external_sync, GLbitfield flags);
+#endif
+#endif /* GL_EXT_x11_sync_object */
+
+#ifndef GL_GREMEDY_frame_terminator
+#define GL_GREMEDY_frame_terminator 1
+typedef void (APIENTRYP PFNGLFRAMETERMINATORGREMEDYPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameTerminatorGREMEDY (void);
+#endif
+#endif /* GL_GREMEDY_frame_terminator */
+
+#ifndef GL_GREMEDY_string_marker
+#define GL_GREMEDY_string_marker 1
+typedef void (APIENTRYP PFNGLSTRINGMARKERGREMEDYPROC) (GLsizei len, const void *string);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glStringMarkerGREMEDY (GLsizei len, const void *string);
+#endif
+#endif /* GL_GREMEDY_string_marker */
+
+#ifndef GL_HP_convolution_border_modes
+#define GL_HP_convolution_border_modes 1
+#define GL_IGNORE_BORDER_HP 0x8150
+#define GL_CONSTANT_BORDER_HP 0x8151
+#define GL_REPLICATE_BORDER_HP 0x8153
+#define GL_CONVOLUTION_BORDER_COLOR_HP 0x8154
+#endif /* GL_HP_convolution_border_modes */
+
+#ifndef GL_HP_image_transform
+#define GL_HP_image_transform 1
+#define GL_IMAGE_SCALE_X_HP 0x8155
+#define GL_IMAGE_SCALE_Y_HP 0x8156
+#define GL_IMAGE_TRANSLATE_X_HP 0x8157
+#define GL_IMAGE_TRANSLATE_Y_HP 0x8158
+#define GL_IMAGE_ROTATE_ANGLE_HP 0x8159
+#define GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A
+#define GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B
+#define GL_IMAGE_MAG_FILTER_HP 0x815C
+#define GL_IMAGE_MIN_FILTER_HP 0x815D
+#define GL_IMAGE_CUBIC_WEIGHT_HP 0x815E
+#define GL_CUBIC_HP 0x815F
+#define GL_AVERAGE_HP 0x8160
+#define GL_IMAGE_TRANSFORM_2D_HP 0x8161
+#define GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIHPPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFHPPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERIVHPPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETIMAGETRANSFORMPARAMETERFVHPPROC) (GLenum target, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glImageTransformParameteriHP (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glImageTransformParameterfHP (GLenum target, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glImageTransformParameterivHP (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glImageTransformParameterfvHP (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetImageTransformParameterivHP (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetImageTransformParameterfvHP (GLenum target, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_HP_image_transform */
+
+#ifndef GL_HP_occlusion_test
+#define GL_HP_occlusion_test 1
+#define GL_OCCLUSION_TEST_HP 0x8165
+#define GL_OCCLUSION_TEST_RESULT_HP 0x8166
+#endif /* GL_HP_occlusion_test */
+
+#ifndef GL_HP_texture_lighting
+#define GL_HP_texture_lighting 1
+#define GL_TEXTURE_LIGHTING_MODE_HP 0x8167
+#define GL_TEXTURE_POST_SPECULAR_HP 0x8168
+#define GL_TEXTURE_PRE_SPECULAR_HP 0x8169
+#endif /* GL_HP_texture_lighting */
+
+#ifndef GL_IBM_cull_vertex
+#define GL_IBM_cull_vertex 1
+#define GL_CULL_VERTEX_IBM 103050
+#endif /* GL_IBM_cull_vertex */
+
+#ifndef GL_IBM_multimode_draw_arrays
+#define GL_IBM_multimode_draw_arrays 1
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWARRAYSIBMPROC) (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+typedef void (APIENTRYP PFNGLMULTIMODEDRAWELEMENTSIBMPROC) (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiModeDrawArraysIBM (const GLenum *mode, const GLint *first, const GLsizei *count, GLsizei primcount, GLint modestride);
+GLAPI void APIENTRY glMultiModeDrawElementsIBM (const GLenum *mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, GLint modestride);
+#endif
+#endif /* GL_IBM_multimode_draw_arrays */
+
+#ifndef GL_IBM_rasterpos_clip
+#define GL_IBM_rasterpos_clip 1
+#define GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262
+#endif /* GL_IBM_rasterpos_clip */
+
+#ifndef GL_IBM_static_data
+#define GL_IBM_static_data 1
+#define GL_ALL_STATIC_DATA_IBM 103060
+#define GL_STATIC_VERTEX_ARRAY_IBM 103061
+typedef void (APIENTRYP PFNGLFLUSHSTATICDATAIBMPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushStaticDataIBM (GLenum target);
+#endif
+#endif /* GL_IBM_static_data */
+
+#ifndef GL_IBM_texture_mirrored_repeat
+#define GL_IBM_texture_mirrored_repeat 1
+#define GL_MIRRORED_REPEAT_IBM 0x8370
+#endif /* GL_IBM_texture_mirrored_repeat */
+
+#ifndef GL_IBM_vertex_array_lists
+#define GL_IBM_vertex_array_lists 1
+#define GL_VERTEX_ARRAY_LIST_IBM 103070
+#define GL_NORMAL_ARRAY_LIST_IBM 103071
+#define GL_COLOR_ARRAY_LIST_IBM 103072
+#define GL_INDEX_ARRAY_LIST_IBM 103073
+#define GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+typedef void (APIENTRYP PFNGLCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERLISTIBMPROC) (GLint stride, const GLboolean **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLINDEXPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLNORMALPOINTERLISTIBMPROC) (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+typedef void (APIENTRYP PFNGLVERTEXPOINTERLISTIBMPROC) (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glSecondaryColorPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glEdgeFlagPointerListIBM (GLint stride, const GLboolean **pointer, GLint ptrstride);
+GLAPI void APIENTRY glFogCoordPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glIndexPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glNormalPointerListIBM (GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glTexCoordPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+GLAPI void APIENTRY glVertexPointerListIBM (GLint size, GLenum type, GLint stride, const void **pointer, GLint ptrstride);
+#endif
+#endif /* GL_IBM_vertex_array_lists */
+
+#ifndef GL_INGR_blend_func_separate
+#define GL_INGR_blend_func_separate 1
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEINGRPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+#endif
+#endif /* GL_INGR_blend_func_separate */
+
+#ifndef GL_INGR_color_clamp
+#define GL_INGR_color_clamp 1
+#define GL_RED_MIN_CLAMP_INGR 0x8560
+#define GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define GL_RED_MAX_CLAMP_INGR 0x8564
+#define GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define GL_ALPHA_MAX_CLAMP_INGR 0x8567
+#endif /* GL_INGR_color_clamp */
+
+#ifndef GL_INGR_interlace_read
+#define GL_INGR_interlace_read 1
+#define GL_INTERLACE_READ_INGR 0x8568
+#endif /* GL_INGR_interlace_read */
+
+#ifndef GL_INTEL_fragment_shader_ordering
+#define GL_INTEL_fragment_shader_ordering 1
+#endif /* GL_INTEL_fragment_shader_ordering */
+
+#ifndef GL_INTEL_map_texture
+#define GL_INTEL_map_texture 1
+#define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
+#define GL_LAYOUT_DEFAULT_INTEL 0
+#define GL_LAYOUT_LINEAR_INTEL 1
+#define GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2
+typedef void (APIENTRYP PFNGLSYNCTEXTUREINTELPROC) (GLuint texture);
+typedef void (APIENTRYP PFNGLUNMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level);
+typedef void *(APIENTRYP PFNGLMAPTEXTURE2DINTELPROC) (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSyncTextureINTEL (GLuint texture);
+GLAPI void APIENTRY glUnmapTexture2DINTEL (GLuint texture, GLint level);
+GLAPI void *APIENTRY glMapTexture2DINTEL (GLuint texture, GLint level, GLbitfield access, GLint *stride, GLenum *layout);
+#endif
+#endif /* GL_INTEL_map_texture */
+
+#ifndef GL_INTEL_parallel_arrays
+#define GL_INTEL_parallel_arrays 1
+#define GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+typedef void (APIENTRYP PFNGLVERTEXPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLNORMALPOINTERVINTELPROC) (GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLCOLORPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERVINTELPROC) (GLint size, GLenum type, const void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexPointervINTEL (GLint size, GLenum type, const void **pointer);
+GLAPI void APIENTRY glNormalPointervINTEL (GLenum type, const void **pointer);
+GLAPI void APIENTRY glColorPointervINTEL (GLint size, GLenum type, const void **pointer);
+GLAPI void APIENTRY glTexCoordPointervINTEL (GLint size, GLenum type, const void **pointer);
+#endif
+#endif /* GL_INTEL_parallel_arrays */
+
+#ifndef GL_INTEL_performance_query
+#define GL_INTEL_performance_query 1
+#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
+#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001
+#define GL_PERFQUERY_WAIT_INTEL 0x83FB
+#define GL_PERFQUERY_FLUSH_INTEL 0x83FA
+#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9
+#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0
+#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1
+#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2
+#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3
+#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4
+#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5
+#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8
+#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9
+#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA
+#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB
+#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC
+#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD
+#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE
+#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF
+#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500
+typedef void (APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle);
+typedef void (APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle);
+typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId);
+typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId);
+typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId);
+typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle);
+GLAPI void APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle);
+GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId);
+GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId);
+GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue);
+GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten);
+GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId);
+GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask);
+#endif
+#endif /* GL_INTEL_performance_query */
+
+#ifndef GL_MESAX_texture_stack
+#define GL_MESAX_texture_stack 1
+#define GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+#endif /* GL_MESAX_texture_stack */
+
+#ifndef GL_MESA_pack_invert
+#define GL_MESA_pack_invert 1
+#define GL_PACK_INVERT_MESA 0x8758
+#endif /* GL_MESA_pack_invert */
+
+#ifndef GL_MESA_resize_buffers
+#define GL_MESA_resize_buffers 1
+typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glResizeBuffersMESA (void);
+#endif
+#endif /* GL_MESA_resize_buffers */
+
+#ifndef GL_MESA_window_pos
+#define GL_MESA_window_pos 1
+typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FMESAPROC) (GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IMESAPROC) (GLint x, GLint y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SMESAPROC) (GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DMESAPROC) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FMESAPROC) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IMESAPROC) (GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SMESAPROC) (GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVMESAPROC) (const GLshort *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DMESAPROC) (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4DVMESAPROC) (const GLdouble *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FMESAPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4FVMESAPROC) (const GLfloat *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IMESAPROC) (GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4IVMESAPROC) (const GLint *v);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SMESAPROC) (GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLWINDOWPOS4SVMESAPROC) (const GLshort *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glWindowPos2dMESA (GLdouble x, GLdouble y);
+GLAPI void APIENTRY glWindowPos2dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos2fMESA (GLfloat x, GLfloat y);
+GLAPI void APIENTRY glWindowPos2fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos2iMESA (GLint x, GLint y);
+GLAPI void APIENTRY glWindowPos2ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos2sMESA (GLshort x, GLshort y);
+GLAPI void APIENTRY glWindowPos2svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos3dMESA (GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glWindowPos3dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos3fMESA (GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glWindowPos3fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos3iMESA (GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glWindowPos3ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos3sMESA (GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glWindowPos3svMESA (const GLshort *v);
+GLAPI void APIENTRY glWindowPos4dMESA (GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glWindowPos4dvMESA (const GLdouble *v);
+GLAPI void APIENTRY glWindowPos4fMESA (GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glWindowPos4fvMESA (const GLfloat *v);
+GLAPI void APIENTRY glWindowPos4iMESA (GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glWindowPos4ivMESA (const GLint *v);
+GLAPI void APIENTRY glWindowPos4sMESA (GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v);
+#endif
+#endif /* GL_MESA_window_pos */
+
+#ifndef GL_MESA_ycbcr_texture
+#define GL_MESA_ycbcr_texture 1
+#define GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define GL_YCBCR_MESA 0x8757
+#endif /* GL_MESA_ycbcr_texture */
+
+#ifndef GL_NVX_conditional_render
+#define GL_NVX_conditional_render 1
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNVX (GLuint id);
+GLAPI void APIENTRY glEndConditionalRenderNVX (void);
+#endif
+#endif /* GL_NVX_conditional_render */
+
+#ifndef GL_NVX_gpu_memory_info
+#define GL_NVX_gpu_memory_info 1
+#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+#endif /* GL_NVX_gpu_memory_info */
+
+#ifndef GL_NV_bindless_multi_draw_indirect
+#define GL_NV_bindless_multi_draw_indirect 1
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTBINDLESSNVPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMultiDrawArraysIndirectBindlessNV (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+GLAPI void APIENTRY glMultiDrawElementsIndirectBindlessNV (GLenum mode, GLenum type, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount);
+#endif
+#endif /* GL_NV_bindless_multi_draw_indirect */
+
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint64 APIENTRY glGetTextureHandleNV (GLuint texture);
+GLAPI GLuint64 APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GLAPI void APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GLAPI GLuint64 APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GLAPI void APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GLAPI void APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GLAPI void APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GLAPI void APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GLAPI void APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GLAPI void APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GLAPI GLboolean APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GLAPI GLboolean APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
+
+#ifndef GL_NV_blend_equation_advanced
+#define GL_NV_blend_equation_advanced 1
+#define GL_BLEND_OVERLAP_NV 0x9281
+#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define GL_BLUE_NV 0x1905
+#define GL_COLORBURN_NV 0x929A
+#define GL_COLORDODGE_NV 0x9299
+#define GL_CONJOINT_NV 0x9284
+#define GL_CONTRAST_NV 0x92A1
+#define GL_DARKEN_NV 0x9297
+#define GL_DIFFERENCE_NV 0x929E
+#define GL_DISJOINT_NV 0x9283
+#define GL_DST_ATOP_NV 0x928F
+#define GL_DST_IN_NV 0x928B
+#define GL_DST_NV 0x9287
+#define GL_DST_OUT_NV 0x928D
+#define GL_DST_OVER_NV 0x9289
+#define GL_EXCLUSION_NV 0x92A0
+#define GL_GREEN_NV 0x1904
+#define GL_HARDLIGHT_NV 0x929B
+#define GL_HARDMIX_NV 0x92A9
+#define GL_HSL_COLOR_NV 0x92AF
+#define GL_HSL_HUE_NV 0x92AD
+#define GL_HSL_LUMINOSITY_NV 0x92B0
+#define GL_HSL_SATURATION_NV 0x92AE
+#define GL_INVERT_OVG_NV 0x92B4
+#define GL_INVERT_RGB_NV 0x92A3
+#define GL_LIGHTEN_NV 0x9298
+#define GL_LINEARBURN_NV 0x92A5
+#define GL_LINEARDODGE_NV 0x92A4
+#define GL_LINEARLIGHT_NV 0x92A7
+#define GL_MINUS_CLAMPED_NV 0x92B3
+#define GL_MINUS_NV 0x929F
+#define GL_MULTIPLY_NV 0x9294
+#define GL_OVERLAY_NV 0x9296
+#define GL_PINLIGHT_NV 0x92A8
+#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define GL_PLUS_CLAMPED_NV 0x92B1
+#define GL_PLUS_DARKER_NV 0x9292
+#define GL_PLUS_NV 0x9291
+#define GL_RED_NV 0x1903
+#define GL_SCREEN_NV 0x9295
+#define GL_SOFTLIGHT_NV 0x929C
+#define GL_SRC_ATOP_NV 0x928E
+#define GL_SRC_IN_NV 0x928A
+#define GL_SRC_NV 0x9286
+#define GL_SRC_OUT_NV 0x928C
+#define GL_SRC_OVER_NV 0x9288
+#define GL_UNCORRELATED_NV 0x9282
+#define GL_VIVIDLIGHT_NV 0x92A6
+#define GL_XOR_NV 0x1506
+typedef void (APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLBLENDBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendParameteriNV (GLenum pname, GLint value);
+GLAPI void APIENTRY glBlendBarrierNV (void);
+#endif
+#endif /* GL_NV_blend_equation_advanced */
+
+#ifndef GL_NV_blend_equation_advanced_coherent
+#define GL_NV_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285
+#endif /* GL_NV_blend_equation_advanced_coherent */
+
+#ifndef GL_NV_blend_square
+#define GL_NV_blend_square 1
+#endif /* GL_NV_blend_square */
+
+#ifndef GL_NV_compute_program5
+#define GL_NV_compute_program5 1
+#define GL_COMPUTE_PROGRAM_NV 0x90FB
+#define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
+#endif /* GL_NV_compute_program5 */
+
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV 0x8E13
+#define GL_QUERY_NO_WAIT_NV 0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GLAPI void APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_copy_depth_to_color
+#define GL_NV_copy_depth_to_color 1
+#define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+#endif /* GL_NV_copy_depth_to_color */
+
+#ifndef GL_NV_copy_image
+#define GL_NV_copy_image 1
+typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCopyImageSubDataNV (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+#endif /* GL_NV_copy_image */
+
+#ifndef GL_NV_deep_texture3D
+#define GL_NV_deep_texture3D 1
+#define GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0
+#define GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1
+#endif /* GL_NV_deep_texture3D */
+
+#ifndef GL_NV_depth_buffer_float
+#define GL_NV_depth_buffer_float 1
+#define GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+typedef void (APIENTRYP PFNGLDEPTHRANGEDNVPROC) (GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRYP PFNGLCLEARDEPTHDNVPROC) (GLdouble depth);
+typedef void (APIENTRYP PFNGLDEPTHBOUNDSDNVPROC) (GLdouble zmin, GLdouble zmax);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDepthRangedNV (GLdouble zNear, GLdouble zFar);
+GLAPI void APIENTRY glClearDepthdNV (GLdouble depth);
+GLAPI void APIENTRY glDepthBoundsdNV (GLdouble zmin, GLdouble zmax);
+#endif
+#endif /* GL_NV_depth_buffer_float */
+
+#ifndef GL_NV_depth_clamp
+#define GL_NV_depth_clamp 1
+#define GL_DEPTH_CLAMP_NV 0x864F
+#endif /* GL_NV_depth_clamp */
+
+#ifndef GL_NV_draw_texture
+#define GL_NV_draw_texture 1
+typedef void (APIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawTextureNV (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
+#endif
+#endif /* GL_NV_draw_texture */
+
+#ifndef GL_NV_evaluators
+#define GL_NV_evaluators 1
+#define GL_EVAL_2D_NV 0x86C0
+#define GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define GL_MAP_TESSELLATION_NV 0x86C2
+#define GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+typedef void (APIENTRYP PFNGLMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points);
+typedef void (APIENTRYP PFNGLMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPCONTROLPOINTSNVPROC) (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERIVNVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPPARAMETERFVNVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERIVNVPROC) (GLenum target, GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETMAPATTRIBPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLEVALMAPSNVPROC) (GLenum target, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLint uorder, GLint vorder, GLboolean packed, const void *points);
+GLAPI void APIENTRY glMapParameterivNV (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glMapParameterfvNV (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetMapControlPointsNV (GLenum target, GLuint index, GLenum type, GLsizei ustride, GLsizei vstride, GLboolean packed, void *points);
+GLAPI void APIENTRY glGetMapParameterivNV (GLenum target, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapParameterfvNV (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetMapAttribParameterivNV (GLenum target, GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetMapAttribParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glEvalMapsNV (GLenum target, GLenum mode);
+#endif
+#endif /* GL_NV_evaluators */
+
+#ifndef GL_NV_explicit_multisample
+#define GL_NV_explicit_multisample 1
+#define GL_SAMPLE_POSITION_NV 0x8E50
+#define GL_SAMPLE_MASK_NV 0x8E51
+#define GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVNVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (APIENTRYP PFNGLSAMPLEMASKINDEXEDNVPROC) (GLuint index, GLbitfield mask);
+typedef void (APIENTRYP PFNGLTEXRENDERBUFFERNVPROC) (GLenum target, GLuint renderbuffer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetMultisamplefvNV (GLenum pname, GLuint index, GLfloat *val);
+GLAPI void APIENTRY glSampleMaskIndexedNV (GLuint index, GLbitfield mask);
+GLAPI void APIENTRY glTexRenderbufferNV (GLenum target, GLuint renderbuffer);
+#endif
+#endif /* GL_NV_explicit_multisample */
+
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+typedef void (APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GLAPI void APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GLAPI GLboolean APIENTRY glIsFenceNV (GLuint fence);
+GLAPI GLboolean APIENTRY glTestFenceNV (GLuint fence);
+GLAPI void APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GLAPI void APIENTRY glFinishFenceNV (GLuint fence);
+GLAPI void APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+#endif /* GL_NV_fence */
+
+#ifndef GL_NV_float_buffer
+#define GL_NV_float_buffer 1
+#define GL_FLOAT_R_NV 0x8880
+#define GL_FLOAT_RG_NV 0x8881
+#define GL_FLOAT_RGB_NV 0x8882
+#define GL_FLOAT_RGBA_NV 0x8883
+#define GL_FLOAT_R16_NV 0x8884
+#define GL_FLOAT_R32_NV 0x8885
+#define GL_FLOAT_RG16_NV 0x8886
+#define GL_FLOAT_RG32_NV 0x8887
+#define GL_FLOAT_RGB16_NV 0x8888
+#define GL_FLOAT_RGB32_NV 0x8889
+#define GL_FLOAT_RGBA16_NV 0x888A
+#define GL_FLOAT_RGBA32_NV 0x888B
+#define GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define GL_FLOAT_RGBA_MODE_NV 0x888E
+#endif /* GL_NV_float_buffer */
+
+#ifndef GL_NV_fog_distance
+#define GL_NV_fog_distance 1
+#define GL_FOG_DISTANCE_MODE_NV 0x855A
+#define GL_EYE_RADIAL_NV 0x855B
+#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+#endif /* GL_NV_fog_distance */
+
+#ifndef GL_NV_fragment_program
+#define GL_NV_fragment_program 1
+#define GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define GL_FRAGMENT_PROGRAM_NV 0x8870
+#define GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define GL_PROGRAM_ERROR_STRING_NV 0x8874
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4FVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMNAMEDPARAMETER4DVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERFVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMNAMEDPARAMETERDVNVPROC) (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramNamedParameter4fNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramNamedParameter4fvNV (GLuint id, GLsizei len, const GLubyte *name, const GLfloat *v);
+GLAPI void APIENTRY glProgramNamedParameter4dNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramNamedParameter4dvNV (GLuint id, GLsizei len, const GLubyte *name, const GLdouble *v);
+GLAPI void APIENTRY glGetProgramNamedParameterfvNV (GLuint id, GLsizei len, const GLubyte *name, GLfloat *params);
+GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, const GLubyte *name, GLdouble *params);
+#endif
+#endif /* GL_NV_fragment_program */
+
+#ifndef GL_NV_fragment_program2
+#define GL_NV_fragment_program2 1
+#define GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+#endif /* GL_NV_fragment_program2 */
+
+#ifndef GL_NV_fragment_program4
+#define GL_NV_fragment_program4 1
+#endif /* GL_NV_fragment_program4 */
+
+#ifndef GL_NV_fragment_program_option
+#define GL_NV_fragment_program_option 1
+#endif /* GL_NV_fragment_program_option */
+
+#ifndef GL_NV_framebuffer_multisample_coverage
+#define GL_NV_framebuffer_multisample_coverage 1
+#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glRenderbufferStorageMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_NV_framebuffer_multisample_coverage */
+
+#ifndef GL_NV_geometry_program4
+#define GL_NV_geometry_program4 1
+#define GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+typedef void (APIENTRYP PFNGLPROGRAMVERTEXLIMITNVPROC) (GLenum target, GLint limit);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREFACEEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramVertexLimitNV (GLenum target, GLint limit);
+GLAPI void APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI void APIENTRY glFramebufferTextureLayerEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachment, GLuint texture, GLint level, GLenum face);
+#endif
+#endif /* GL_NV_geometry_program4 */
+
+#ifndef GL_NV_geometry_shader4
+#define GL_NV_geometry_shader4 1
+#endif /* GL_NV_geometry_shader4 */
+
+#ifndef GL_NV_gpu_program4
+#define GL_NV_gpu_program4 1
+#define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMLOCALPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4INVPROC) (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4IVNVPROC) (GLenum target, GLuint index, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4IVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UINVPROC) (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERI4UIVNVPROC) (GLenum target, GLuint index, const GLuint *params);
+typedef void (APIENTRYP PFNGLPROGRAMENVPARAMETERSI4UIVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMLOCALPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIIVNVPROC) (GLenum target, GLuint index, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMENVPARAMETERIUIVNVPROC) (GLenum target, GLuint index, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramLocalParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramLocalParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramLocalParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramLocalParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramLocalParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4iNV (GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glProgramEnvParameterI4ivNV (GLenum target, GLuint index, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4ivNV (GLenum target, GLuint index, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramEnvParameterI4uiNV (GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glProgramEnvParameterI4uivNV (GLenum target, GLuint index, const GLuint *params);
+GLAPI void APIENTRY glProgramEnvParametersI4uivNV (GLenum target, GLuint index, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramLocalParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIivNV (GLenum target, GLuint index, GLint *params);
+GLAPI void APIENTRY glGetProgramEnvParameterIuivNV (GLenum target, GLuint index, GLuint *params);
+#endif
+#endif /* GL_NV_gpu_program4 */
+
+#ifndef GL_NV_gpu_program5
+#define GL_NV_gpu_program5 1
+#define GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F
+#define GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
+#define GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45
+typedef void (APIENTRYP PFNGLPROGRAMSUBROUTINEPARAMETERSUIVNVPROC) (GLenum target, GLsizei count, const GLuint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSUBROUTINEPARAMETERUIVNVPROC) (GLenum target, GLuint index, GLuint *param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramSubroutineParametersuivNV (GLenum target, GLsizei count, const GLuint *params);
+GLAPI void APIENTRY glGetProgramSubroutineParameteruivNV (GLenum target, GLuint index, GLuint *param);
+#endif
+#endif /* GL_NV_gpu_program5 */
+
+#ifndef GL_NV_gpu_program5_mem_extended
+#define GL_NV_gpu_program5_mem_extended 1
+#endif /* GL_NV_gpu_program5_mem_extended */
+
+#ifndef GL_NV_gpu_shader5
+#define GL_NV_gpu_shader5 1
+#endif /* GL_NV_gpu_shader5 */
+
+#ifndef GL_NV_half_float
+#define GL_NV_half_float 1
+typedef unsigned short GLhalfNV;
+#define GL_HALF_FLOAT_NV 0x140B
+typedef void (APIENTRYP PFNGLVERTEX2HNVPROC) (GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEX2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX3HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEX3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEX4HNVPROC) (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEX4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLNORMAL3HNVPROC) (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+typedef void (APIENTRYP PFNGLNORMAL3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLCOLOR4HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+typedef void (APIENTRYP PFNGLCOLOR4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD1HNVPROC) (GLhalfNV s);
+typedef void (APIENTRYP PFNGLTEXCOORD1HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2HNVPROC) (GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLTEXCOORD2HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD3HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLTEXCOORD3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4HNVPROC) (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLTEXCOORD4HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HNVPROC) (GLenum target, GLhalfNV s);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
+typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
+typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4HVNVPROC) (GLuint index, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex3hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertex3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertex4hNV (GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertex4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glNormal3hNV (GLhalfNV nx, GLhalfNV ny, GLhalfNV nz);
+GLAPI void APIENTRY glNormal3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glColor4hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue, GLhalfNV alpha);
+GLAPI void APIENTRY glColor4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord1hNV (GLhalfNV s);
+GLAPI void APIENTRY glTexCoord1hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord2hNV (GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glTexCoord2hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord3hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glTexCoord3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glTexCoord4hNV (GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glTexCoord4hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord1hNV (GLenum target, GLhalfNV s);
+GLAPI void APIENTRY glMultiTexCoord1hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord2hNV (GLenum target, GLhalfNV s, GLhalfNV t);
+GLAPI void APIENTRY glMultiTexCoord2hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r);
+GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
+GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v);
+GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
+GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
+GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
+GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
+GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
+GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
+GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x);
+GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y);
+GLAPI void APIENTRY glVertexAttrib2hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib3hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z);
+GLAPI void APIENTRY glVertexAttrib3hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttrib4hNV (GLuint index, GLhalfNV x, GLhalfNV y, GLhalfNV z, GLhalfNV w);
+GLAPI void APIENTRY glVertexAttrib4hvNV (GLuint index, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
+#endif
+#endif /* GL_NV_half_float */
+
+#ifndef GL_NV_light_max_exponent
+#define GL_NV_light_max_exponent 1
+#define GL_MAX_SHININESS_NV 0x8504
+#define GL_MAX_SPOT_EXPONENT_NV 0x8505
+#endif /* GL_NV_light_max_exponent */
+
+#ifndef GL_NV_multisample_coverage
+#define GL_NV_multisample_coverage 1
+#define GL_COLOR_SAMPLES_NV 0x8E20
+#endif /* GL_NV_multisample_coverage */
+
+#ifndef GL_NV_multisample_filter_hint
+#define GL_NV_multisample_filter_hint 1
+#define GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+#endif /* GL_NV_multisample_filter_hint */
+
+#ifndef GL_NV_occlusion_query
+#define GL_NV_occlusion_query 1
+#define GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define GL_PIXEL_COUNT_NV 0x8866
+#define GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+typedef void (APIENTRYP PFNGLGENOCCLUSIONQUERIESNVPROC) (GLsizei n, GLuint *ids);
+typedef void (APIENTRYP PFNGLDELETEOCCLUSIONQUERIESNVPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLBEGINOCCLUSIONQUERYNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLENDOCCLUSIONQUERYNVPROC) (void);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETOCCLUSIONQUERYUIVNVPROC) (GLuint id, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenOcclusionQueriesNV (GLsizei n, GLuint *ids);
+GLAPI void APIENTRY glDeleteOcclusionQueriesNV (GLsizei n, const GLuint *ids);
+GLAPI GLboolean APIENTRY glIsOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glBeginOcclusionQueryNV (GLuint id);
+GLAPI void APIENTRY glEndOcclusionQueryNV (void);
+GLAPI void APIENTRY glGetOcclusionQueryivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetOcclusionQueryuivNV (GLuint id, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_NV_occlusion_query */
+
+#ifndef GL_NV_packed_depth_stencil
+#define GL_NV_packed_depth_stencil 1
+#define GL_DEPTH_STENCIL_NV 0x84F9
+#define GL_UNSIGNED_INT_24_8_NV 0x84FA
+#endif /* GL_NV_packed_depth_stencil */
+
+#ifndef GL_NV_parameter_buffer_object
+#define GL_NV_parameter_buffer_object 1
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSFVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params);
+typedef void (APIENTRYP PFNGLPROGRAMBUFFERPARAMETERSIUIVNVPROC) (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glProgramBufferParametersfvNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLfloat *params);
+GLAPI void APIENTRY glProgramBufferParametersIivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLint *params);
+GLAPI void APIENTRY glProgramBufferParametersIuivNV (GLenum target, GLuint bindingIndex, GLuint wordIndex, GLsizei count, const GLuint *params);
+#endif
+#endif /* GL_NV_parameter_buffer_object */
+
+#ifndef GL_NV_parameter_buffer_object2
+#define GL_NV_parameter_buffer_object2 1
+#endif /* GL_NV_parameter_buffer_object2 */
+
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV 0x9070
+#define GL_PATH_FORMAT_PS_NV 0x9071
+#define GL_STANDARD_FONT_NAME_NV 0x9072
+#define GL_SYSTEM_FONT_NAME_NV 0x9073
+#define GL_FILE_NAME_NV 0x9074
+#define GL_PATH_STROKE_WIDTH_NV 0x9075
+#define GL_PATH_END_CAPS_NV 0x9076
+#define GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define GL_PATH_JOIN_STYLE_NV 0x9079
+#define GL_PATH_MITER_LIMIT_NV 0x907A
+#define GL_PATH_DASH_CAPS_NV 0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define GL_PATH_DASH_OFFSET_NV 0x907E
+#define GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define GL_PATH_FILL_MODE_NV 0x9080
+#define GL_PATH_FILL_MASK_NV 0x9081
+#define GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define GL_PATH_STROKE_MASK_NV 0x9084
+#define GL_COUNT_UP_NV 0x9088
+#define GL_COUNT_DOWN_NV 0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define GL_CONVEX_HULL_NV 0x908B
+#define GL_BOUNDING_BOX_NV 0x908D
+#define GL_TRANSLATE_X_NV 0x908E
+#define GL_TRANSLATE_Y_NV 0x908F
+#define GL_TRANSLATE_2D_NV 0x9090
+#define GL_TRANSLATE_3D_NV 0x9091
+#define GL_AFFINE_2D_NV 0x9092
+#define GL_AFFINE_3D_NV 0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define GL_UTF8_NV 0x909A
+#define GL_UTF16_NV 0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV 0x909D
+#define GL_PATH_COORD_COUNT_NV 0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define GL_SQUARE_NV 0x90A3
+#define GL_ROUND_NV 0x90A4
+#define GL_TRIANGULAR_NV 0x90A5
+#define GL_BEVEL_NV 0x90A6
+#define GL_MITER_REVERT_NV 0x90A7
+#define GL_MITER_TRUNCATE_NV 0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define GL_USE_MISSING_GLYPH_NV 0x90AA
+#define GL_PATH_ERROR_POSITION_NV 0x90AB
+#define GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define GL_ADJACENT_PAIRS_NV 0x90AE
+#define GL_FIRST_TO_REST_NV 0x90AF
+#define GL_PATH_GEN_MODE_NV 0x90B0
+#define GL_PATH_GEN_COEFF_NV 0x90B1
+#define GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define GL_PATH_STENCIL_REF_NV 0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define GL_MOVE_TO_RESETS_NV 0x90B5
+#define GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define GL_CLOSE_PATH_NV 0x00
+#define GL_MOVE_TO_NV 0x02
+#define GL_RELATIVE_MOVE_TO_NV 0x03
+#define GL_LINE_TO_NV 0x04
+#define GL_RELATIVE_LINE_TO_NV 0x05
+#define GL_HORIZONTAL_LINE_TO_NV 0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV 0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV 0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV 0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define GL_SMALL_CW_ARC_TO_NV 0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define GL_LARGE_CCW_ARC_TO_NV 0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define GL_LARGE_CW_ARC_TO_NV 0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define GL_RESTART_PATH_NV 0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define GL_RECT_NV 0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define GL_ARC_TO_NV 0xFE
+#define GL_RELATIVE_ARC_TO_NV 0xFF
+#define GL_BOLD_BIT_NV 0x01
+#define GL_ITALIC_BIT_NV 0x02
+#define GL_GLYPH_WIDTH_BIT_NV 0x01
+#define GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define GL_PRIMARY_COLOR_NV 0x852C
+#define GL_SECONDARY_COLOR_NV 0x852D
+typedef GLuint (APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode);
+typedef void (APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENIVNVPROC) (GLenum color, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHCOLORGENFVNVPROC) (GLenum color, GLenum pname, GLfloat *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENIVNVPROC) (GLenum texCoordSet, GLenum pname, GLint *value);
+typedef void (APIENTRYP PFNGLGETPATHTEXGENFVNVPROC) (GLenum texCoordSet, GLenum pname, GLfloat *value);
+typedef GLboolean (APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLuint APIENTRY glGenPathsNV (GLsizei range);
+GLAPI void APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GLAPI GLboolean APIENTRY glIsPathNV (GLuint path);
+GLAPI void APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GLAPI void APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GLAPI void APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GLAPI void APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GLAPI void APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GLAPI void APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GLAPI void APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GLAPI void APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GLAPI void APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GLAPI void APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GLAPI void APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GLAPI void APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GLAPI void APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GLAPI void APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GLAPI void APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GLAPI void APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs);
+GLAPI void APIENTRY glPathFogGenNV (GLenum genMode);
+GLAPI void APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GLAPI void APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GLAPI void APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GLAPI void APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GLAPI void APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GLAPI void APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GLAPI void APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GLAPI void APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GLAPI void APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GLAPI void APIENTRY glGetPathColorGenivNV (GLenum color, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathColorGenfvNV (GLenum color, GLenum pname, GLfloat *value);
+GLAPI void APIENTRY glGetPathTexGenivNV (GLenum texCoordSet, GLenum pname, GLint *value);
+GLAPI void APIENTRY glGetPathTexGenfvNV (GLenum texCoordSet, GLenum pname, GLfloat *value);
+GLAPI GLboolean APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GLAPI GLboolean APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GLAPI GLfloat APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GLAPI GLboolean APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_pixel_data_range
+#define GL_NV_pixel_data_range 1
+#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, const void *pointer);
+typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelDataRangeNV (GLenum target, GLsizei length, const void *pointer);
+GLAPI void APIENTRY glFlushPixelDataRangeNV (GLenum target);
+#endif
+#endif /* GL_NV_pixel_data_range */
+
+#ifndef GL_NV_point_sprite
+#define GL_NV_point_sprite 1
+#define GL_POINT_SPRITE_NV 0x8861
+#define GL_COORD_REPLACE_NV 0x8862
+#define GL_POINT_SPRITE_R_MODE_NV 0x8863
+typedef void (APIENTRYP PFNGLPOINTPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glPointParameterivNV (GLenum pname, const GLint *params);
+#endif
+#endif /* GL_NV_point_sprite */
+
+#ifndef GL_NV_present_video
+#define GL_NV_present_video 1
+#define GL_FRAME_NV 0x8E26
+#define GL_FIELDS_NV 0x8E27
+#define GL_CURRENT_TIME_NV 0x8E28
+#define GL_NUM_FILL_STREAMS_NV 0x8E29
+#define GL_PRESENT_TIME_NV 0x8E2A
+#define GL_PRESENT_DURATION_NV 0x8E2B
+typedef void (APIENTRYP PFNGLPRESENTFRAMEKEYEDNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+typedef void (APIENTRYP PFNGLPRESENTFRAMEDUALFILLNVPROC) (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+typedef void (APIENTRYP PFNGLGETVIDEOIVNVPROC) (GLuint video_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUIVNVPROC) (GLuint video_slot, GLenum pname, GLuint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOI64VNVPROC) (GLuint video_slot, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVIDEOUI64VNVPROC) (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPresentFrameKeyedNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLuint key0, GLenum target1, GLuint fill1, GLuint key1);
+GLAPI void APIENTRY glPresentFrameDualFillNV (GLuint video_slot, GLuint64EXT minPresentTime, GLuint beginPresentTimeId, GLuint presentDurationId, GLenum type, GLenum target0, GLuint fill0, GLenum target1, GLuint fill1, GLenum target2, GLuint fill2, GLenum target3, GLuint fill3);
+GLAPI void APIENTRY glGetVideoivNV (GLuint video_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideouivNV (GLuint video_slot, GLenum pname, GLuint *params);
+GLAPI void APIENTRY glGetVideoi64vNV (GLuint video_slot, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVideoui64vNV (GLuint video_slot, GLenum pname, GLuint64EXT *params);
+#endif
+#endif /* GL_NV_present_video */
+
+#ifndef GL_NV_primitive_restart
+#define GL_NV_primitive_restart 1
+#define GL_PRIMITIVE_RESTART_NV 0x8558
+#define GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTNVPROC) (void);
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXNVPROC) (GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPrimitiveRestartNV (void);
+GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index);
+#endif
+#endif /* GL_NV_primitive_restart */
+
+#ifndef GL_NV_register_combiners
+#define GL_NV_register_combiners 1
+#define GL_REGISTER_COMBINERS_NV 0x8522
+#define GL_VARIABLE_A_NV 0x8523
+#define GL_VARIABLE_B_NV 0x8524
+#define GL_VARIABLE_C_NV 0x8525
+#define GL_VARIABLE_D_NV 0x8526
+#define GL_VARIABLE_E_NV 0x8527
+#define GL_VARIABLE_F_NV 0x8528
+#define GL_VARIABLE_G_NV 0x8529
+#define GL_CONSTANT_COLOR0_NV 0x852A
+#define GL_CONSTANT_COLOR1_NV 0x852B
+#define GL_SPARE0_NV 0x852E
+#define GL_SPARE1_NV 0x852F
+#define GL_DISCARD_NV 0x8530
+#define GL_E_TIMES_F_NV 0x8531
+#define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define GL_UNSIGNED_IDENTITY_NV 0x8536
+#define GL_UNSIGNED_INVERT_NV 0x8537
+#define GL_EXPAND_NORMAL_NV 0x8538
+#define GL_EXPAND_NEGATE_NV 0x8539
+#define GL_HALF_BIAS_NORMAL_NV 0x853A
+#define GL_HALF_BIAS_NEGATE_NV 0x853B
+#define GL_SIGNED_IDENTITY_NV 0x853C
+#define GL_SIGNED_NEGATE_NV 0x853D
+#define GL_SCALE_BY_TWO_NV 0x853E
+#define GL_SCALE_BY_FOUR_NV 0x853F
+#define GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define GL_COMBINER_INPUT_NV 0x8542
+#define GL_COMBINER_MAPPING_NV 0x8543
+#define GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define GL_COMBINER_MUX_SUM_NV 0x8547
+#define GL_COMBINER_SCALE_NV 0x8548
+#define GL_COMBINER_BIAS_NV 0x8549
+#define GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define GL_COLOR_SUM_CLAMP_NV 0x854F
+#define GL_COMBINER0_NV 0x8550
+#define GL_COMBINER1_NV 0x8551
+#define GL_COMBINER2_NV 0x8552
+#define GL_COMBINER3_NV 0x8553
+#define GL_COMBINER4_NV 0x8554
+#define GL_COMBINER5_NV 0x8555
+#define GL_COMBINER6_NV 0x8556
+#define GL_COMBINER7_NV 0x8557
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFVNVPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERFNVPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERIVNVPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOMBINERPARAMETERINVPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLCOMBINERINPUTNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLCOMBINEROUTPUTNVPROC) (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+typedef void (APIENTRYP PFNGLFINALCOMBINERINPUTNVPROC) (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) (GLenum variable, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) (GLenum variable, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerParameterfvNV (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glCombinerParameterfNV (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glCombinerParameterivNV (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCombinerParameteriNV (GLenum pname, GLint param);
+GLAPI void APIENTRY glCombinerInputNV (GLenum stage, GLenum portion, GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glCombinerOutputNV (GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput, GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct, GLboolean cdDotProduct, GLboolean muxSum);
+GLAPI void APIENTRY glFinalCombinerInputNV (GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage);
+GLAPI void APIENTRY glGetCombinerInputParameterfvNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerInputParameterivNV (GLenum stage, GLenum portion, GLenum variable, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterfvNV (GLenum stage, GLenum portion, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetCombinerOutputParameterivNV (GLenum stage, GLenum portion, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterfvNV (GLenum variable, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFinalCombinerInputParameterivNV (GLenum variable, GLenum pname, GLint *params);
+#endif
+#endif /* GL_NV_register_combiners */
+
+#ifndef GL_NV_register_combiners2
+#define GL_NV_register_combiners2 1
+#define GL_PER_STAGE_CONSTANTS_NV 0x8535
+typedef void (APIENTRYP PFNGLCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOMBINERSTAGEPARAMETERFVNVPROC) (GLenum stage, GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glCombinerStageParameterfvNV (GLenum stage, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_NV_register_combiners2 */
+
+#ifndef GL_NV_shader_atomic_counters
+#define GL_NV_shader_atomic_counters 1
+#endif /* GL_NV_shader_atomic_counters */
+
+#ifndef GL_NV_shader_atomic_float
+#define GL_NV_shader_atomic_float 1
+#endif /* GL_NV_shader_atomic_float */
+
+#ifndef GL_NV_shader_buffer_load
+#define GL_NV_shader_buffer_load 1
+#define GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define GL_GPU_ADDRESS_NV 0x8F34
+#define GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+typedef void (APIENTRYP PFNGLMAKEBUFFERRESIDENTNVPROC) (GLenum target, GLenum access);
+typedef void (APIENTRYP PFNGLMAKEBUFFERNONRESIDENTNVPROC) (GLenum target);
+typedef GLboolean (APIENTRYP PFNGLISBUFFERRESIDENTNVPROC) (GLenum target);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERRESIDENTNVPROC) (GLuint buffer, GLenum access);
+typedef void (APIENTRYP PFNGLMAKENAMEDBUFFERNONRESIDENTNVPROC) (GLuint buffer);
+typedef GLboolean (APIENTRYP PFNGLISNAMEDBUFFERRESIDENTNVPROC) (GLuint buffer);
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERUI64VNVPROC) (GLenum target, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERUI64VNVPROC) (GLuint buffer, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64VNVPROC) (GLenum value, GLuint64EXT *result);
+typedef void (APIENTRYP PFNGLUNIFORMUI64NVPROC) (GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLUNIFORMUI64VNVPROC) (GLint location, GLsizei count, const GLuint64EXT *value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64NVPROC) (GLuint program, GLint location, GLuint64EXT value);
+typedef void (APIENTRYP PFNGLPROGRAMUNIFORMUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glMakeBufferResidentNV (GLenum target, GLenum access);
+GLAPI void APIENTRY glMakeBufferNonResidentNV (GLenum target);
+GLAPI GLboolean APIENTRY glIsBufferResidentNV (GLenum target);
+GLAPI void APIENTRY glMakeNamedBufferResidentNV (GLuint buffer, GLenum access);
+GLAPI void APIENTRY glMakeNamedBufferNonResidentNV (GLuint buffer);
+GLAPI GLboolean APIENTRY glIsNamedBufferResidentNV (GLuint buffer);
+GLAPI void APIENTRY glGetBufferParameterui64vNV (GLenum target, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetNamedBufferParameterui64vNV (GLuint buffer, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glGetIntegerui64vNV (GLenum value, GLuint64EXT *result);
+GLAPI void APIENTRY glUniformui64NV (GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glUniformui64vNV (GLint location, GLsizei count, const GLuint64EXT *value);
+GLAPI void APIENTRY glProgramUniformui64NV (GLuint program, GLint location, GLuint64EXT value);
+GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64EXT *value);
+#endif
+#endif /* GL_NV_shader_buffer_load */
+
+#ifndef GL_NV_shader_buffer_store
+#define GL_NV_shader_buffer_store 1
+#define GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010
+#endif /* GL_NV_shader_buffer_store */
+
+#ifndef GL_NV_shader_storage_buffer_object
+#define GL_NV_shader_storage_buffer_object 1
+#endif /* GL_NV_shader_storage_buffer_object */
+
+#ifndef GL_NV_shader_thread_group
+#define GL_NV_shader_thread_group 1
+#define GL_WARP_SIZE_NV 0x9339
+#define GL_WARPS_PER_SM_NV 0x933A
+#define GL_SM_COUNT_NV 0x933B
+#endif /* GL_NV_shader_thread_group */
+
+#ifndef GL_NV_shader_thread_shuffle
+#define GL_NV_shader_thread_shuffle 1
+#endif /* GL_NV_shader_thread_shuffle */
+
+#ifndef GL_NV_tessellation_program5
+#define GL_NV_tessellation_program5 1
+#define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+#endif /* GL_NV_tessellation_program5 */
+
+#ifndef GL_NV_texgen_emboss
+#define GL_NV_texgen_emboss 1
+#define GL_EMBOSS_LIGHT_NV 0x855D
+#define GL_EMBOSS_CONSTANT_NV 0x855E
+#define GL_EMBOSS_MAP_NV 0x855F
+#endif /* GL_NV_texgen_emboss */
+
+#ifndef GL_NV_texgen_reflection
+#define GL_NV_texgen_reflection 1
+#define GL_NORMAL_MAP_NV 0x8511
+#define GL_REFLECTION_MAP_NV 0x8512
+#endif /* GL_NV_texgen_reflection */
+
+#ifndef GL_NV_texture_barrier
+#define GL_NV_texture_barrier 1
+typedef void (APIENTRYP PFNGLTEXTUREBARRIERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureBarrierNV (void);
+#endif
+#endif /* GL_NV_texture_barrier */
+
+#ifndef GL_NV_texture_compression_vtc
+#define GL_NV_texture_compression_vtc 1
+#endif /* GL_NV_texture_compression_vtc */
+
+#ifndef GL_NV_texture_env_combine4
+#define GL_NV_texture_env_combine4 1
+#define GL_COMBINE4_NV 0x8503
+#define GL_SOURCE3_RGB_NV 0x8583
+#define GL_SOURCE3_ALPHA_NV 0x858B
+#define GL_OPERAND3_RGB_NV 0x8593
+#define GL_OPERAND3_ALPHA_NV 0x859B
+#endif /* GL_NV_texture_env_combine4 */
+
+#ifndef GL_NV_texture_expand_normal
+#define GL_NV_texture_expand_normal 1
+#define GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#endif /* GL_NV_texture_expand_normal */
+
+#ifndef GL_NV_texture_multisample
+#define GL_NV_texture_multisample 1
+#define GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045
+#define GL_TEXTURE_COLOR_SAMPLES_NV 0x9046
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLENVPROC) (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE2DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+typedef void (APIENTRYP PFNGLTEXTUREIMAGE3DMULTISAMPLECOVERAGENVPROC) (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage2DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTexImage3DMultisampleCoverageNV (GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage2DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage3DMultisampleNV (GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage2DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+#endif
+#endif /* GL_NV_texture_multisample */
+
+#ifndef GL_NV_texture_rectangle
+#define GL_NV_texture_rectangle 1
+#define GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+#endif /* GL_NV_texture_rectangle */
+
+#ifndef GL_NV_texture_shader
+#define GL_NV_texture_shader 1
+#define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define GL_SHADER_CONSISTENT_NV 0x86DD
+#define GL_TEXTURE_SHADER_NV 0x86DE
+#define GL_SHADER_OPERATION_NV 0x86DF
+#define GL_CULL_MODES_NV 0x86E0
+#define GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
+#define GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2
+#define GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
+#define GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define GL_CONST_EYE_NV 0x86E5
+#define GL_PASS_THROUGH_NV 0x86E6
+#define GL_CULL_FRAGMENT_NV 0x86E7
+#define GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define GL_DOT_PRODUCT_NV 0x86EC
+#define GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define GL_HILO_NV 0x86F4
+#define GL_DSDT_NV 0x86F5
+#define GL_DSDT_MAG_NV 0x86F6
+#define GL_DSDT_MAG_VIB_NV 0x86F7
+#define GL_HILO16_NV 0x86F8
+#define GL_SIGNED_HILO_NV 0x86F9
+#define GL_SIGNED_HILO16_NV 0x86FA
+#define GL_SIGNED_RGBA_NV 0x86FB
+#define GL_SIGNED_RGBA8_NV 0x86FC
+#define GL_SIGNED_RGB_NV 0x86FE
+#define GL_SIGNED_RGB8_NV 0x86FF
+#define GL_SIGNED_LUMINANCE_NV 0x8701
+#define GL_SIGNED_LUMINANCE8_NV 0x8702
+#define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define GL_SIGNED_ALPHA_NV 0x8705
+#define GL_SIGNED_ALPHA8_NV 0x8706
+#define GL_SIGNED_INTENSITY_NV 0x8707
+#define GL_SIGNED_INTENSITY8_NV 0x8708
+#define GL_DSDT8_NV 0x8709
+#define GL_DSDT8_MAG8_NV 0x870A
+#define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define GL_HI_SCALE_NV 0x870E
+#define GL_LO_SCALE_NV 0x870F
+#define GL_DS_SCALE_NV 0x8710
+#define GL_DT_SCALE_NV 0x8711
+#define GL_MAGNITUDE_SCALE_NV 0x8712
+#define GL_VIBRANCE_SCALE_NV 0x8713
+#define GL_HI_BIAS_NV 0x8714
+#define GL_LO_BIAS_NV 0x8715
+#define GL_DS_BIAS_NV 0x8716
+#define GL_DT_BIAS_NV 0x8717
+#define GL_MAGNITUDE_BIAS_NV 0x8718
+#define GL_VIBRANCE_BIAS_NV 0x8719
+#define GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define GL_TEXTURE_HI_SIZE_NV 0x871B
+#define GL_TEXTURE_LO_SIZE_NV 0x871C
+#define GL_TEXTURE_DS_SIZE_NV 0x871D
+#define GL_TEXTURE_DT_SIZE_NV 0x871E
+#define GL_TEXTURE_MAG_SIZE_NV 0x871F
+#endif /* GL_NV_texture_shader */
+
+#ifndef GL_NV_texture_shader2
+#define GL_NV_texture_shader2 1
+#define GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#endif /* GL_NV_texture_shader2 */
+
+#ifndef GL_NV_texture_shader3
+#define GL_NV_texture_shader3 1
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define GL_HILO8_NV 0x885E
+#define GL_SIGNED_HILO8_NV 0x885F
+#define GL_FORCE_BLUE_TO_ONE_NV 0x8860
+#endif /* GL_NV_texture_shader3 */
+
+#ifndef GL_NV_transform_feedback
+#define GL_NV_transform_feedback 1
+#define GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define GL_TEXTURE_COORD_NV 0x8C79
+#define GL_CLIP_DISTANCE_NV 0x8C7A
+#define GL_VERTEX_ID_NV 0x8C7B
+#define GL_PRIMITIVE_ID_NV 0x8C7C
+#define GL_GENERIC_ATTRIB_NV 0x8C7D
+#define GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define GL_ACTIVE_VARYINGS_NV 0x8C81
+#define GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define GL_RASTERIZER_DISCARD_NV 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+#define GL_LAYER_NV 0x8DAA
+#define GL_NEXT_BUFFER_NV -2
+#define GL_SKIP_COMPONENTS4_NV -3
+#define GL_SKIP_COMPONENTS3_NV -4
+#define GL_SKIP_COMPONENTS2_NV -5
+#define GL_SKIP_COMPONENTS1_NV -6
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKNVPROC) (GLenum primitiveMode);
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKATTRIBSNVPROC) (GLuint count, const GLint *attribs, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGENVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (APIENTRYP PFNGLBINDBUFFEROFFSETNVPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+typedef void (APIENTRYP PFNGLBINDBUFFERBASENVPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSNVPROC) (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+typedef void (APIENTRYP PFNGLACTIVEVARYINGNVPROC) (GLuint program, const GLchar *name);
+typedef GLint (APIENTRYP PFNGLGETVARYINGLOCATIONNVPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETACTIVEVARYINGNVPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGNVPROC) (GLuint program, GLuint index, GLint *location);
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKSTREAMATTRIBSNVPROC) (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginTransformFeedbackNV (GLenum primitiveMode);
+GLAPI void APIENTRY glEndTransformFeedbackNV (void);
+GLAPI void APIENTRY glTransformFeedbackAttribsNV (GLuint count, const GLint *attribs, GLenum bufferMode);
+GLAPI void APIENTRY glBindBufferRangeNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI void APIENTRY glBindBufferOffsetNV (GLenum target, GLuint index, GLuint buffer, GLintptr offset);
+GLAPI void APIENTRY glBindBufferBaseNV (GLenum target, GLuint index, GLuint buffer);
+GLAPI void APIENTRY glTransformFeedbackVaryingsNV (GLuint program, GLsizei count, const GLint *locations, GLenum bufferMode);
+GLAPI void APIENTRY glActiveVaryingNV (GLuint program, const GLchar *name);
+GLAPI GLint APIENTRY glGetVaryingLocationNV (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetActiveVaryingNV (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI void APIENTRY glGetTransformFeedbackVaryingNV (GLuint program, GLuint index, GLint *location);
+GLAPI void APIENTRY glTransformFeedbackStreamAttribsNV (GLsizei count, const GLint *attribs, GLsizei nbuffers, const GLint *bufstreams, GLenum bufferMode);
+#endif
+#endif /* GL_NV_transform_feedback */
+
+#ifndef GL_NV_transform_feedback2
+#define GL_NV_transform_feedback2 1
+#define GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+typedef void (APIENTRYP PFNGLBINDTRANSFORMFEEDBACKNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSNVPROC) (GLsizei n, const GLuint *ids);
+typedef void (APIENTRYP PFNGLGENTRANSFORMFEEDBACKSNVPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (APIENTRYP PFNGLISTRANSFORMFEEDBACKNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKNVPROC) (void);
+typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKNVPROC) (GLenum mode, GLuint id);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindTransformFeedbackNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteTransformFeedbacksNV (GLsizei n, const GLuint *ids);
+GLAPI void APIENTRY glGenTransformFeedbacksNV (GLsizei n, GLuint *ids);
+GLAPI GLboolean APIENTRY glIsTransformFeedbackNV (GLuint id);
+GLAPI void APIENTRY glPauseTransformFeedbackNV (void);
+GLAPI void APIENTRY glResumeTransformFeedbackNV (void);
+GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
+#endif
+#endif /* GL_NV_transform_feedback2 */
+
+#ifndef GL_NV_vdpau_interop
+#define GL_NV_vdpau_interop 1
+typedef GLintptr GLvdpauSurfaceNV;
+#define GL_SURFACE_STATE_NV 0x86EB
+#define GL_SURFACE_REGISTERED_NV 0x86FD
+#define GL_SURFACE_MAPPED_NV 0x8700
+#define GL_WRITE_DISCARD_NV 0x88BE
+typedef void (APIENTRYP PFNGLVDPAUINITNVPROC) (const void *vdpDevice, const void *getProcAddress);
+typedef void (APIENTRYP PFNGLVDPAUFININVPROC) (void);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+typedef GLboolean (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface);
+typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access);
+typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVDPAUInitNV (const void *vdpDevice, const void *getProcAddress);
+GLAPI void APIENTRY glVDPAUFiniNV (void);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames);
+GLAPI GLboolean APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface);
+GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access);
+GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces);
+GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces);
+#endif
+#endif /* GL_NV_vdpau_interop */
+
+#ifndef GL_NV_vertex_array_range
+#define GL_NV_vertex_array_range 1
+#define GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+typedef void (APIENTRYP PFNGLFLUSHVERTEXARRAYRANGENVPROC) (void);
+typedef void (APIENTRYP PFNGLVERTEXARRAYRANGENVPROC) (GLsizei length, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushVertexArrayRangeNV (void);
+GLAPI void APIENTRY glVertexArrayRangeNV (GLsizei length, const void *pointer);
+#endif
+#endif /* GL_NV_vertex_array_range */
+
+#ifndef GL_NV_vertex_array_range2
+#define GL_NV_vertex_array_range2 1
+#define GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#endif /* GL_NV_vertex_array_range2 */
+
+#ifndef GL_NV_vertex_attrib_integer_64bit
+#define GL_NV_vertex_attrib_integer_64bit 1
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64NVPROC) (GLuint index, GLint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64NVPROC) (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4I64VNVPROC) (GLuint index, const GLint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64NVPROC) (GLuint index, GLuint64EXT x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64NVPROC) (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL2UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL3UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBL4UI64VNVPROC) (GLuint index, const GLuint64EXT *v);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLI64VNVPROC) (GLuint index, GLenum pname, GLint64EXT *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VNVPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBLFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribL1i64NV (GLuint index, GLint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2i64NV (GLuint index, GLint64EXT x, GLint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4i64NV (GLuint index, GLint64EXT x, GLint64EXT y, GLint64EXT z, GLint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4i64vNV (GLuint index, const GLint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL1ui64NV (GLuint index, GLuint64EXT x);
+GLAPI void APIENTRY glVertexAttribL2ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y);
+GLAPI void APIENTRY glVertexAttribL3ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z);
+GLAPI void APIENTRY glVertexAttribL4ui64NV (GLuint index, GLuint64EXT x, GLuint64EXT y, GLuint64EXT z, GLuint64EXT w);
+GLAPI void APIENTRY glVertexAttribL1ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL2ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL3ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glVertexAttribL4ui64vNV (GLuint index, const GLuint64EXT *v);
+GLAPI void APIENTRY glGetVertexAttribLi64vNV (GLuint index, GLenum pname, GLint64EXT *params);
+GLAPI void APIENTRY glGetVertexAttribLui64vNV (GLuint index, GLenum pname, GLuint64EXT *params);
+GLAPI void APIENTRY glVertexAttribLFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+#endif
+#endif /* GL_NV_vertex_attrib_integer_64bit */
+
+#ifndef GL_NV_vertex_buffer_unified_memory
+#define GL_NV_vertex_buffer_unified_memory 1
+#define GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+typedef void (APIENTRYP PFNGLBUFFERADDRESSRANGENVPROC) (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+typedef void (APIENTRYP PFNGLVERTEXFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLNORMALFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLINDEXFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLTEXCOORDFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLEDGEFLAGFORMATNVPROC) (GLsizei stride);
+typedef void (APIENTRYP PFNGLSECONDARYCOLORFORMATNVPROC) (GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLFOGCOORDFORMATNVPROC) (GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIFORMATNVPROC) (GLuint index, GLint size, GLenum type, GLsizei stride);
+typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBufferAddressRangeNV (GLenum pname, GLuint index, GLuint64EXT address, GLsizeiptr length);
+GLAPI void APIENTRY glVertexFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glNormalFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glIndexFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glTexCoordFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glEdgeFlagFormatNV (GLsizei stride);
+GLAPI void APIENTRY glSecondaryColorFormatNV (GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glFogCoordFormatNV (GLenum type, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribFormatNV (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride);
+GLAPI void APIENTRY glVertexAttribIFormatNV (GLuint index, GLint size, GLenum type, GLsizei stride);
+GLAPI void APIENTRY glGetIntegerui64i_vNV (GLenum value, GLuint index, GLuint64EXT *result);
+#endif
+#endif /* GL_NV_vertex_buffer_unified_memory */
+
+#ifndef GL_NV_vertex_program
+#define GL_NV_vertex_program 1
+#define GL_VERTEX_PROGRAM_NV 0x8620
+#define GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define GL_CURRENT_ATTRIB_NV 0x8626
+#define GL_PROGRAM_LENGTH_NV 0x8627
+#define GL_PROGRAM_STRING_NV 0x8628
+#define GL_MODELVIEW_PROJECTION_NV 0x8629
+#define GL_IDENTITY_NV 0x862A
+#define GL_INVERSE_NV 0x862B
+#define GL_TRANSPOSE_NV 0x862C
+#define GL_INVERSE_TRANSPOSE_NV 0x862D
+#define GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define GL_MAX_TRACK_MATRICES_NV 0x862F
+#define GL_MATRIX0_NV 0x8630
+#define GL_MATRIX1_NV 0x8631
+#define GL_MATRIX2_NV 0x8632
+#define GL_MATRIX3_NV 0x8633
+#define GL_MATRIX4_NV 0x8634
+#define GL_MATRIX5_NV 0x8635
+#define GL_MATRIX6_NV 0x8636
+#define GL_MATRIX7_NV 0x8637
+#define GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define GL_CURRENT_MATRIX_NV 0x8641
+#define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define GL_PROGRAM_PARAMETER_NV 0x8644
+#define GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define GL_PROGRAM_TARGET_NV 0x8646
+#define GL_PROGRAM_RESIDENT_NV 0x8647
+#define GL_TRACK_MATRIX_NV 0x8648
+#define GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+typedef GLboolean (APIENTRYP PFNGLAREPROGRAMSRESIDENTNVPROC) (GLsizei n, const GLuint *programs, GLboolean *residences);
+typedef void (APIENTRYP PFNGLBINDPROGRAMNVPROC) (GLenum target, GLuint id);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLEXECUTEPROGRAMNVPROC) (GLenum target, GLuint id, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGENPROGRAMSNVPROC) (GLsizei n, GLuint *programs);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERDVNVPROC) (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMPARAMETERFVNVPROC) (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVNVPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMSTRINGNVPROC) (GLuint id, GLenum pname, GLubyte *program);
+typedef void (APIENTRYP PFNGLGETTRACKMATRIXIVNVPROC) (GLenum target, GLuint address, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVNVPROC) (GLuint index, GLenum pname, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVNVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVNVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVNVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMNVPROC) (GLuint id);
+typedef void (APIENTRYP PFNGLLOADPROGRAMNVPROC) (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DNVPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4DVNVPROC) (GLenum target, GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FNVPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETER4FVNVPROC) (GLenum target, GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4DVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLPROGRAMPARAMETERS4FVNVPROC) (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREQUESTRESIDENTPROGRAMSNVPROC) (GLsizei n, const GLuint *programs);
+typedef void (APIENTRYP PFNGLTRACKMATRIXNVPROC) (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERNVPROC) (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DNVPROC) (GLuint index, GLdouble x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FNVPROC) (GLuint index, GLfloat x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SNVPROC) (GLuint index, GLshort x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DNVPROC) (GLuint index, GLdouble x, GLdouble y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FNVPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SNVPROC) (GLuint index, GLshort x, GLshort y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DNVPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVNVPROC) (GLuint index, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SNVPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVNVPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBNVPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVNVPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS1SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS2SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS3SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4DVNVPROC) (GLuint index, GLsizei count, const GLdouble *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4FVNVPROC) (GLuint index, GLsizei count, const GLfloat *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4SVNVPROC) (GLuint index, GLsizei count, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBS4UBVNVPROC) (GLuint index, GLsizei count, const GLubyte *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLboolean APIENTRY glAreProgramsResidentNV (GLsizei n, const GLuint *programs, GLboolean *residences);
+GLAPI void APIENTRY glBindProgramNV (GLenum target, GLuint id);
+GLAPI void APIENTRY glDeleteProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glExecuteProgramNV (GLenum target, GLuint id, const GLfloat *params);
+GLAPI void APIENTRY glGenProgramsNV (GLsizei n, GLuint *programs);
+GLAPI void APIENTRY glGetProgramParameterdvNV (GLenum target, GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetProgramParameterfvNV (GLenum target, GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetProgramivNV (GLuint id, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramStringNV (GLuint id, GLenum pname, GLubyte *program);
+GLAPI void APIENTRY glGetTrackMatrixivNV (GLenum target, GLuint address, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribdvNV (GLuint index, GLenum pname, GLdouble *params);
+GLAPI void APIENTRY glGetVertexAttribfvNV (GLuint index, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVertexAttribivNV (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribPointervNV (GLuint index, GLenum pname, void **pointer);
+GLAPI GLboolean APIENTRY glIsProgramNV (GLuint id);
+GLAPI void APIENTRY glLoadProgramNV (GLenum target, GLuint id, GLsizei len, const GLubyte *program);
+GLAPI void APIENTRY glProgramParameter4dNV (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glProgramParameter4dvNV (GLenum target, GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameter4fNV (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glProgramParameter4fvNV (GLenum target, GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glProgramParameters4dvNV (GLenum target, GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glProgramParameters4fvNV (GLenum target, GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glRequestResidentProgramsNV (GLsizei n, const GLuint *programs);
+GLAPI void APIENTRY glTrackMatrixNV (GLenum target, GLuint address, GLenum matrix, GLenum transform);
+GLAPI void APIENTRY glVertexAttribPointerNV (GLuint index, GLint fsize, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glVertexAttrib1dNV (GLuint index, GLdouble x);
+GLAPI void APIENTRY glVertexAttrib1dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib1fNV (GLuint index, GLfloat x);
+GLAPI void APIENTRY glVertexAttrib1fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib1sNV (GLuint index, GLshort x);
+GLAPI void APIENTRY glVertexAttrib1svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib2dNV (GLuint index, GLdouble x, GLdouble y);
+GLAPI void APIENTRY glVertexAttrib2dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib2fNV (GLuint index, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glVertexAttrib2fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib2sNV (GLuint index, GLshort x, GLshort y);
+GLAPI void APIENTRY glVertexAttrib2svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib3dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI void APIENTRY glVertexAttrib3dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib3fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glVertexAttrib3fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib3sNV (GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI void APIENTRY glVertexAttrib3svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4dNV (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI void APIENTRY glVertexAttrib4dvNV (GLuint index, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttrib4fNV (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glVertexAttrib4fvNV (GLuint index, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttrib4sNV (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI void APIENTRY glVertexAttrib4svNV (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttrib4ubNV (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI void APIENTRY glVertexAttrib4ubvNV (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribs1dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs1fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs1svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs2dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs2fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs2svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs3dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs3fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs3svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4dvNV (GLuint index, GLsizei count, const GLdouble *v);
+GLAPI void APIENTRY glVertexAttribs4fvNV (GLuint index, GLsizei count, const GLfloat *v);
+GLAPI void APIENTRY glVertexAttribs4svNV (GLuint index, GLsizei count, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GLubyte *v);
+#endif
+#endif /* GL_NV_vertex_program */
+
+#ifndef GL_NV_vertex_program1_1
+#define GL_NV_vertex_program1_1 1
+#endif /* GL_NV_vertex_program1_1 */
+
+#ifndef GL_NV_vertex_program2
+#define GL_NV_vertex_program2 1
+#endif /* GL_NV_vertex_program2 */
+
+#ifndef GL_NV_vertex_program2_option
+#define GL_NV_vertex_program2_option 1
+#endif /* GL_NV_vertex_program2_option */
+
+#ifndef GL_NV_vertex_program3
+#define GL_NV_vertex_program3 1
+#endif /* GL_NV_vertex_program3 */
+
+#ifndef GL_NV_vertex_program4
+#define GL_NV_vertex_program4 1
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x);
+GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y);
+GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z);
+GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x);
+GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y);
+GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v);
+GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v);
+GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v);
+GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v);
+GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v);
+GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v);
+GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_NV_vertex_program4 */
+
+#ifndef GL_NV_video_capture
+#define GL_NV_video_capture 1
+#define GL_VIDEO_BUFFER_NV 0x9020
+#define GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define GL_FIELD_UPPER_NV 0x9022
+#define GL_FIELD_LOWER_NV 0x9023
+#define GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define GL_PARTIAL_SUCCESS_NV 0x902E
+#define GL_SUCCESS_NV 0x902F
+#define GL_FAILURE_NV 0x9030
+#define GL_YCBYCR8_422_NV 0x9031
+#define GL_YCBAYCR8A_4224_NV 0x9032
+#define GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+typedef void (APIENTRYP PFNGLBEGINVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMBUFFERNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+typedef void (APIENTRYP PFNGLBINDVIDEOCAPTURESTREAMTEXTURENVPROC) (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLENDVIDEOCAPTURENVPROC) (GLuint video_capture_slot);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTUREIVNVPROC) (GLuint video_capture_slot, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETVIDEOCAPTURESTREAMDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+typedef GLenum (APIENTRYP PFNGLVIDEOCAPTURENVPROC) (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERIVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERFVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLVIDEOCAPTURESTREAMPARAMETERDVNVPROC) (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBeginVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glBindVideoCaptureStreamBufferNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLintptrARB offset);
+GLAPI void APIENTRY glBindVideoCaptureStreamTextureNV (GLuint video_capture_slot, GLuint stream, GLenum frame_region, GLenum target, GLuint texture);
+GLAPI void APIENTRY glEndVideoCaptureNV (GLuint video_capture_slot);
+GLAPI void APIENTRY glGetVideoCaptureivNV (GLuint video_capture_slot, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetVideoCaptureStreamdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, GLdouble *params);
+GLAPI GLenum APIENTRY glVideoCaptureNV (GLuint video_capture_slot, GLuint *sequence_num, GLuint64EXT *capture_time);
+GLAPI void APIENTRY glVideoCaptureStreamParameterivNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterfvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot, GLuint stream, GLenum pname, const GLdouble *params);
+#endif
+#endif /* GL_NV_video_capture */
+
+#ifndef GL_OML_interlace
+#define GL_OML_interlace 1
+#define GL_INTERLACE_OML 0x8980
+#define GL_INTERLACE_READ_OML 0x8981
+#endif /* GL_OML_interlace */
+
+#ifndef GL_OML_resample
+#define GL_OML_resample 1
+#define GL_PACK_RESAMPLE_OML 0x8984
+#define GL_UNPACK_RESAMPLE_OML 0x8985
+#define GL_RESAMPLE_REPLICATE_OML 0x8986
+#define GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define GL_RESAMPLE_AVERAGE_OML 0x8988
+#define GL_RESAMPLE_DECIMATE_OML 0x8989
+#endif /* GL_OML_resample */
+
+#ifndef GL_OML_subsample
+#define GL_OML_subsample 1
+#define GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+#endif /* GL_OML_subsample */
+
+#ifndef GL_PGI_misc_hints
+#define GL_PGI_misc_hints 1
+#define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
+#define GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD
+#define GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE
+#define GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202
+#define GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204
+#define GL_ALWAYS_FAST_HINT_PGI 0x1A20C
+#define GL_ALWAYS_SOFT_HINT_PGI 0x1A20D
+#define GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E
+#define GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F
+#define GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210
+#define GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211
+#define GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216
+#define GL_STRICT_LIGHTING_HINT_PGI 0x1A217
+#define GL_STRICT_SCISSOR_HINT_PGI 0x1A218
+#define GL_FULL_STIPPLE_HINT_PGI 0x1A219
+#define GL_CLIP_NEAR_HINT_PGI 0x1A220
+#define GL_CLIP_FAR_HINT_PGI 0x1A221
+#define GL_WIDE_LINE_HINT_PGI 0x1A222
+#define GL_BACK_NORMALS_HINT_PGI 0x1A223
+typedef void (APIENTRYP PFNGLHINTPGIPROC) (GLenum target, GLint mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glHintPGI (GLenum target, GLint mode);
+#endif
+#endif /* GL_PGI_misc_hints */
+
+#ifndef GL_PGI_vertex_hints
+#define GL_PGI_vertex_hints 1
+#define GL_VERTEX_DATA_HINT_PGI 0x1A22A
+#define GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B
+#define GL_MATERIAL_SIDE_HINT_PGI 0x1A22C
+#define GL_MAX_VERTEX_HINT_PGI 0x1A22D
+#define GL_COLOR3_BIT_PGI 0x00010000
+#define GL_COLOR4_BIT_PGI 0x00020000
+#define GL_EDGEFLAG_BIT_PGI 0x00040000
+#define GL_INDEX_BIT_PGI 0x00080000
+#define GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define GL_NORMAL_BIT_PGI 0x08000000
+#define GL_TEXCOORD1_BIT_PGI 0x10000000
+#define GL_TEXCOORD2_BIT_PGI 0x20000000
+#define GL_TEXCOORD3_BIT_PGI 0x40000000
+#define GL_TEXCOORD4_BIT_PGI 0x80000000
+#define GL_VERTEX23_BIT_PGI 0x00000004
+#define GL_VERTEX4_BIT_PGI 0x00000008
+#endif /* GL_PGI_vertex_hints */
+
+#ifndef GL_REND_screen_coordinates
+#define GL_REND_screen_coordinates 1
+#define GL_SCREEN_COORDINATES_REND 0x8490
+#define GL_INVERTED_SCREEN_W_REND 0x8491
+#endif /* GL_REND_screen_coordinates */
+
+#ifndef GL_S3_s3tc
+#define GL_S3_s3tc 1
+#define GL_RGB_S3TC 0x83A0
+#define GL_RGB4_S3TC 0x83A1
+#define GL_RGBA_S3TC 0x83A2
+#define GL_RGBA4_S3TC 0x83A3
+#define GL_RGBA_DXT5_S3TC 0x83A4
+#define GL_RGBA4_DXT5_S3TC 0x83A5
+#endif /* GL_S3_s3tc */
+
+#ifndef GL_SGIS_detail_texture
+#define GL_SGIS_detail_texture 1
+#define GL_DETAIL_TEXTURE_2D_SGIS 0x8095
+#define GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define GL_LINEAR_DETAIL_SGIS 0x8097
+#define GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098
+#define GL_LINEAR_DETAIL_COLOR_SGIS 0x8099
+#define GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A
+#define GL_DETAIL_TEXTURE_MODE_SGIS 0x809B
+#define GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+typedef void (APIENTRYP PFNGLDETAILTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETDETAILTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDetailTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetDetailTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+#endif /* GL_SGIS_detail_texture */
+
+#ifndef GL_SGIS_fog_function
+#define GL_SGIS_fog_function 1
+#define GL_FOG_FUNC_SGIS 0x812A
+#define GL_FOG_FUNC_POINTS_SGIS 0x812B
+#define GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C
+typedef void (APIENTRYP PFNGLFOGFUNCSGISPROC) (GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETFOGFUNCSGISPROC) (GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFogFuncSGIS (GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetFogFuncSGIS (GLfloat *points);
+#endif
+#endif /* GL_SGIS_fog_function */
+
+#ifndef GL_SGIS_generate_mipmap
+#define GL_SGIS_generate_mipmap 1
+#define GL_GENERATE_MIPMAP_SGIS 0x8191
+#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+#endif /* GL_SGIS_generate_mipmap */
+
+#ifndef GL_SGIS_multisample
+#define GL_SGIS_multisample 1
+#define GL_MULTISAMPLE_SGIS 0x809D
+#define GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define GL_SAMPLE_MASK_SGIS 0x80A0
+#define GL_1PASS_SGIS 0x80A1
+#define GL_2PASS_0_SGIS 0x80A2
+#define GL_2PASS_1_SGIS 0x80A3
+#define GL_4PASS_0_SGIS 0x80A4
+#define GL_4PASS_1_SGIS 0x80A5
+#define GL_4PASS_2_SGIS 0x80A6
+#define GL_4PASS_3_SGIS 0x80A7
+#define GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define GL_SAMPLES_SGIS 0x80A9
+#define GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define GL_SAMPLE_PATTERN_SGIS 0x80AC
+typedef void (APIENTRYP PFNGLSAMPLEMASKSGISPROC) (GLclampf value, GLboolean invert);
+typedef void (APIENTRYP PFNGLSAMPLEPATTERNSGISPROC) (GLenum pattern);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSampleMaskSGIS (GLclampf value, GLboolean invert);
+GLAPI void APIENTRY glSamplePatternSGIS (GLenum pattern);
+#endif
+#endif /* GL_SGIS_multisample */
+
+#ifndef GL_SGIS_pixel_texture
+#define GL_SGIS_pixel_texture 1
+#define GL_PIXEL_TEXTURE_SGIS 0x8353
+#define GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define GL_PIXEL_GROUP_COLOR_SGIS 0x8356
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERISGISPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERIVSGISPROC) (GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPIXELTEXGENPARAMETERFVSGISPROC) (GLenum pname, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenParameteriSGIS (GLenum pname, GLint param);
+GLAPI void APIENTRY glPixelTexGenParameterivSGIS (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glPixelTexGenParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPixelTexGenParameterfvSGIS (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterivSGIS (GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetPixelTexGenParameterfvSGIS (GLenum pname, GLfloat *params);
+#endif
+#endif /* GL_SGIS_pixel_texture */
+
+#ifndef GL_SGIS_point_line_texgen
+#define GL_SGIS_point_line_texgen 1
+#define GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define GL_EYE_POINT_SGIS 0x81F4
+#define GL_OBJECT_POINT_SGIS 0x81F5
+#define GL_EYE_LINE_SGIS 0x81F6
+#define GL_OBJECT_LINE_SGIS 0x81F7
+#endif /* GL_SGIS_point_line_texgen */
+
+#ifndef GL_SGIS_point_parameters
+#define GL_SGIS_point_parameters 1
+#define GL_POINT_SIZE_MIN_SGIS 0x8126
+#define GL_POINT_SIZE_MAX_SGIS 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define GL_DISTANCE_ATTENUATION_SGIS 0x8129
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFSGISPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVSGISPROC) (GLenum pname, const GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPointParameterfSGIS (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glPointParameterfvSGIS (GLenum pname, const GLfloat *params);
+#endif
+#endif /* GL_SGIS_point_parameters */
+
+#ifndef GL_SGIS_sharpen_texture
+#define GL_SGIS_sharpen_texture 1
+#define GL_LINEAR_SHARPEN_SGIS 0x80AD
+#define GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE
+#define GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF
+#define GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+typedef void (APIENTRYP PFNGLSHARPENTEXFUNCSGISPROC) (GLenum target, GLsizei n, const GLfloat *points);
+typedef void (APIENTRYP PFNGLGETSHARPENTEXFUNCSGISPROC) (GLenum target, GLfloat *points);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSharpenTexFuncSGIS (GLenum target, GLsizei n, const GLfloat *points);
+GLAPI void APIENTRY glGetSharpenTexFuncSGIS (GLenum target, GLfloat *points);
+#endif
+#endif /* GL_SGIS_sharpen_texture */
+
+#ifndef GL_SGIS_texture4D
+#define GL_SGIS_texture4D 1
+#define GL_PACK_SKIP_VOLUMES_SGIS 0x8130
+#define GL_PACK_IMAGE_DEPTH_SGIS 0x8131
+#define GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132
+#define GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133
+#define GL_TEXTURE_4D_SGIS 0x8134
+#define GL_PROXY_TEXTURE_4D_SGIS 0x8135
+#define GL_TEXTURE_4DSIZE_SGIS 0x8136
+#define GL_TEXTURE_WRAP_Q_SGIS 0x8137
+#define GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138
+#define GL_TEXTURE_4D_BINDING_SGIS 0x814F
+typedef void (APIENTRYP PFNGLTEXIMAGE4DSGISPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE4DSGISPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTexImage4DSGIS (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glTexSubImage4DSGIS (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint woffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei size4d, GLenum format, GLenum type, const void *pixels);
+#endif
+#endif /* GL_SGIS_texture4D */
+
+#ifndef GL_SGIS_texture_border_clamp
+#define GL_SGIS_texture_border_clamp 1
+#define GL_CLAMP_TO_BORDER_SGIS 0x812D
+#endif /* GL_SGIS_texture_border_clamp */
+
+#ifndef GL_SGIS_texture_color_mask
+#define GL_SGIS_texture_color_mask 1
+#define GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF
+typedef void (APIENTRYP PFNGLTEXTURECOLORMASKSGISPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTextureColorMaskSGIS (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+#endif
+#endif /* GL_SGIS_texture_color_mask */
+
+#ifndef GL_SGIS_texture_edge_clamp
+#define GL_SGIS_texture_edge_clamp 1
+#define GL_CLAMP_TO_EDGE_SGIS 0x812F
+#endif /* GL_SGIS_texture_edge_clamp */
+
+#ifndef GL_SGIS_texture_filter4
+#define GL_SGIS_texture_filter4 1
+#define GL_FILTER4_SGIS 0x8146
+#define GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147
+typedef void (APIENTRYP PFNGLGETTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLfloat *weights);
+typedef void (APIENTRYP PFNGLTEXFILTERFUNCSGISPROC) (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetTexFilterFuncSGIS (GLenum target, GLenum filter, GLfloat *weights);
+GLAPI void APIENTRY glTexFilterFuncSGIS (GLenum target, GLenum filter, GLsizei n, const GLfloat *weights);
+#endif
+#endif /* GL_SGIS_texture_filter4 */
+
+#ifndef GL_SGIS_texture_lod
+#define GL_SGIS_texture_lod 1
+#define GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+#endif /* GL_SGIS_texture_lod */
+
+#ifndef GL_SGIS_texture_select
+#define GL_SGIS_texture_select 1
+#define GL_DUAL_ALPHA4_SGIS 0x8110
+#define GL_DUAL_ALPHA8_SGIS 0x8111
+#define GL_DUAL_ALPHA12_SGIS 0x8112
+#define GL_DUAL_ALPHA16_SGIS 0x8113
+#define GL_DUAL_LUMINANCE4_SGIS 0x8114
+#define GL_DUAL_LUMINANCE8_SGIS 0x8115
+#define GL_DUAL_LUMINANCE12_SGIS 0x8116
+#define GL_DUAL_LUMINANCE16_SGIS 0x8117
+#define GL_DUAL_INTENSITY4_SGIS 0x8118
+#define GL_DUAL_INTENSITY8_SGIS 0x8119
+#define GL_DUAL_INTENSITY12_SGIS 0x811A
+#define GL_DUAL_INTENSITY16_SGIS 0x811B
+#define GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C
+#define GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D
+#define GL_QUAD_ALPHA4_SGIS 0x811E
+#define GL_QUAD_ALPHA8_SGIS 0x811F
+#define GL_QUAD_LUMINANCE4_SGIS 0x8120
+#define GL_QUAD_LUMINANCE8_SGIS 0x8121
+#define GL_QUAD_INTENSITY4_SGIS 0x8122
+#define GL_QUAD_INTENSITY8_SGIS 0x8123
+#define GL_DUAL_TEXTURE_SELECT_SGIS 0x8124
+#define GL_QUAD_TEXTURE_SELECT_SGIS 0x8125
+#endif /* GL_SGIS_texture_select */
+
+#ifndef GL_SGIX_async
+#define GL_SGIX_async 1
+#define GL_ASYNC_MARKER_SGIX 0x8329
+typedef void (APIENTRYP PFNGLASYNCMARKERSGIXPROC) (GLuint marker);
+typedef GLint (APIENTRYP PFNGLFINISHASYNCSGIXPROC) (GLuint *markerp);
+typedef GLint (APIENTRYP PFNGLPOLLASYNCSGIXPROC) (GLuint *markerp);
+typedef GLuint (APIENTRYP PFNGLGENASYNCMARKERSSGIXPROC) (GLsizei range);
+typedef void (APIENTRYP PFNGLDELETEASYNCMARKERSSGIXPROC) (GLuint marker, GLsizei range);
+typedef GLboolean (APIENTRYP PFNGLISASYNCMARKERSGIXPROC) (GLuint marker);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glAsyncMarkerSGIX (GLuint marker);
+GLAPI GLint APIENTRY glFinishAsyncSGIX (GLuint *markerp);
+GLAPI GLint APIENTRY glPollAsyncSGIX (GLuint *markerp);
+GLAPI GLuint APIENTRY glGenAsyncMarkersSGIX (GLsizei range);
+GLAPI void APIENTRY glDeleteAsyncMarkersSGIX (GLuint marker, GLsizei range);
+GLAPI GLboolean APIENTRY glIsAsyncMarkerSGIX (GLuint marker);
+#endif
+#endif /* GL_SGIX_async */
+
+#ifndef GL_SGIX_async_histogram
+#define GL_SGIX_async_histogram 1
+#define GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+#endif /* GL_SGIX_async_histogram */
+
+#ifndef GL_SGIX_async_pixel
+#define GL_SGIX_async_pixel 1
+#define GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+#endif /* GL_SGIX_async_pixel */
+
+#ifndef GL_SGIX_blend_alpha_minmax
+#define GL_SGIX_blend_alpha_minmax 1
+#define GL_ALPHA_MIN_SGIX 0x8320
+#define GL_ALPHA_MAX_SGIX 0x8321
+#endif /* GL_SGIX_blend_alpha_minmax */
+
+#ifndef GL_SGIX_calligraphic_fragment
+#define GL_SGIX_calligraphic_fragment 1
+#define GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183
+#endif /* GL_SGIX_calligraphic_fragment */
+
+#ifndef GL_SGIX_clipmap
+#define GL_SGIX_clipmap 1
+#define GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170
+#define GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171
+#define GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172
+#define GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173
+#define GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176
+#define GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177
+#define GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D
+#define GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E
+#define GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F
+#endif /* GL_SGIX_clipmap */
+
+#ifndef GL_SGIX_convolution_accuracy
+#define GL_SGIX_convolution_accuracy 1
+#define GL_CONVOLUTION_HINT_SGIX 0x8316
+#endif /* GL_SGIX_convolution_accuracy */
+
+#ifndef GL_SGIX_depth_pass_instrument
+#define GL_SGIX_depth_pass_instrument 1
+#endif /* GL_SGIX_depth_pass_instrument */
+
+#ifndef GL_SGIX_depth_texture
+#define GL_SGIX_depth_texture 1
+#define GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define GL_DEPTH_COMPONENT32_SGIX 0x81A7
+#endif /* GL_SGIX_depth_texture */
+
+#ifndef GL_SGIX_flush_raster
+#define GL_SGIX_flush_raster 1
+typedef void (APIENTRYP PFNGLFLUSHRASTERSGIXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFlushRasterSGIX (void);
+#endif
+#endif /* GL_SGIX_flush_raster */
+
+#ifndef GL_SGIX_fog_offset
+#define GL_SGIX_fog_offset 1
+#define GL_FOG_OFFSET_SGIX 0x8198
+#define GL_FOG_OFFSET_VALUE_SGIX 0x8199
+#endif /* GL_SGIX_fog_offset */
+
+#ifndef GL_SGIX_fragment_lighting
+#define GL_SGIX_fragment_lighting 1
+#define GL_FRAGMENT_LIGHTING_SGIX 0x8400
+#define GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401
+#define GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404
+#define GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405
+#define GL_CURRENT_RASTER_NORMAL_SGIX 0x8406
+#define GL_LIGHT_ENV_MODE_SGIX 0x8407
+#define GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define GL_FRAGMENT_LIGHT0_SGIX 0x840C
+#define GL_FRAGMENT_LIGHT1_SGIX 0x840D
+#define GL_FRAGMENT_LIGHT2_SGIX 0x840E
+#define GL_FRAGMENT_LIGHT3_SGIX 0x840F
+#define GL_FRAGMENT_LIGHT4_SGIX 0x8410
+#define GL_FRAGMENT_LIGHT5_SGIX 0x8411
+#define GL_FRAGMENT_LIGHT6_SGIX 0x8412
+#define GL_FRAGMENT_LIGHT7_SGIX 0x8413
+typedef void (APIENTRYP PFNGLFRAGMENTCOLORMATERIALSGIXPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFSGIXPROC) (GLenum light, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTISGIXPROC) (GLenum light, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTLIGHTMODELIVSGIXPROC) (GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFSGIXPROC) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALISGIXPROC) (GLenum face, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTFVSGIXPROC) (GLenum light, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTLIGHTIVSGIXPROC) (GLenum light, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALFVSGIXPROC) (GLenum face, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETFRAGMENTMATERIALIVSGIXPROC) (GLenum face, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLIGHTENVISGIXPROC) (GLenum pname, GLint param);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFragmentColorMaterialSGIX (GLenum face, GLenum mode);
+GLAPI void APIENTRY glFragmentLightfSGIX (GLenum light, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightfvSGIX (GLenum light, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightiSGIX (GLenum light, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightivSGIX (GLenum light, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentLightModelfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentLightModelfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentLightModeliSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentLightModelivSGIX (GLenum pname, const GLint *params);
+GLAPI void APIENTRY glFragmentMaterialfSGIX (GLenum face, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glFragmentMaterialfvSGIX (GLenum face, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glFragmentMaterialiSGIX (GLenum face, GLenum pname, GLint param);
+GLAPI void APIENTRY glFragmentMaterialivSGIX (GLenum face, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glGetFragmentLightfvSGIX (GLenum light, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentLightivSGIX (GLenum light, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetFragmentMaterialfvSGIX (GLenum face, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetFragmentMaterialivSGIX (GLenum face, GLenum pname, GLint *params);
+GLAPI void APIENTRY glLightEnviSGIX (GLenum pname, GLint param);
+#endif
+#endif /* GL_SGIX_fragment_lighting */
+
+#ifndef GL_SGIX_framezoom
+#define GL_SGIX_framezoom 1
+#define GL_FRAMEZOOM_SGIX 0x818B
+#define GL_FRAMEZOOM_FACTOR_SGIX 0x818C
+#define GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D
+typedef void (APIENTRYP PFNGLFRAMEZOOMSGIXPROC) (GLint factor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFrameZoomSGIX (GLint factor);
+#endif
+#endif /* GL_SGIX_framezoom */
+
+#ifndef GL_SGIX_igloo_interface
+#define GL_SGIX_igloo_interface 1
+typedef void (APIENTRYP PFNGLIGLOOINTERFACESGIXPROC) (GLenum pname, const void *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glIglooInterfaceSGIX (GLenum pname, const void *params);
+#endif
+#endif /* GL_SGIX_igloo_interface */
+
+#ifndef GL_SGIX_instruments
+#define GL_SGIX_instruments 1
+#define GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181
+typedef GLint (APIENTRYP PFNGLGETINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLINSTRUMENTSBUFFERSGIXPROC) (GLsizei size, GLint *buffer);
+typedef GLint (APIENTRYP PFNGLPOLLINSTRUMENTSSGIXPROC) (GLint *marker_p);
+typedef void (APIENTRYP PFNGLREADINSTRUMENTSSGIXPROC) (GLint marker);
+typedef void (APIENTRYP PFNGLSTARTINSTRUMENTSSGIXPROC) (void);
+typedef void (APIENTRYP PFNGLSTOPINSTRUMENTSSGIXPROC) (GLint marker);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI GLint APIENTRY glGetInstrumentsSGIX (void);
+GLAPI void APIENTRY glInstrumentsBufferSGIX (GLsizei size, GLint *buffer);
+GLAPI GLint APIENTRY glPollInstrumentsSGIX (GLint *marker_p);
+GLAPI void APIENTRY glReadInstrumentsSGIX (GLint marker);
+GLAPI void APIENTRY glStartInstrumentsSGIX (void);
+GLAPI void APIENTRY glStopInstrumentsSGIX (GLint marker);
+#endif
+#endif /* GL_SGIX_instruments */
+
+#ifndef GL_SGIX_interlace
+#define GL_SGIX_interlace 1
+#define GL_INTERLACE_SGIX 0x8094
+#endif /* GL_SGIX_interlace */
+
+#ifndef GL_SGIX_ir_instrument1
+#define GL_SGIX_ir_instrument1 1
+#define GL_IR_INSTRUMENT1_SGIX 0x817F
+#endif /* GL_SGIX_ir_instrument1 */
+
+#ifndef GL_SGIX_list_priority
+#define GL_SGIX_list_priority 1
+#define GL_LIST_PRIORITY_SGIX 0x8182
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFSGIXPROC) (GLuint list, GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERFVSGIXPROC) (GLuint list, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLLISTPARAMETERISGIXPROC) (GLuint list, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLLISTPARAMETERIVSGIXPROC) (GLuint list, GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGetListParameterfvSGIX (GLuint list, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetListParameterivSGIX (GLuint list, GLenum pname, GLint *params);
+GLAPI void APIENTRY glListParameterfSGIX (GLuint list, GLenum pname, GLfloat param);
+GLAPI void APIENTRY glListParameterfvSGIX (GLuint list, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glListParameteriSGIX (GLuint list, GLenum pname, GLint param);
+GLAPI void APIENTRY glListParameterivSGIX (GLuint list, GLenum pname, const GLint *params);
+#endif
+#endif /* GL_SGIX_list_priority */
+
+#ifndef GL_SGIX_pixel_texture
+#define GL_SGIX_pixel_texture 1
+#define GL_PIXEL_TEX_GEN_SGIX 0x8139
+#define GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B
+typedef void (APIENTRYP PFNGLPIXELTEXGENSGIXPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPixelTexGenSGIX (GLenum mode);
+#endif
+#endif /* GL_SGIX_pixel_texture */
+
+#ifndef GL_SGIX_pixel_tiles
+#define GL_SGIX_pixel_tiles 1
+#define GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define GL_PIXEL_TILE_WIDTH_SGIX 0x8140
+#define GL_PIXEL_TILE_HEIGHT_SGIX 0x8141
+#define GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142
+#define GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143
+#define GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144
+#define GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145
+#endif /* GL_SGIX_pixel_tiles */
+
+#ifndef GL_SGIX_polynomial_ffd
+#define GL_SGIX_polynomial_ffd 1
+#define GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001
+#define GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002
+#define GL_GEOMETRY_DEFORMATION_SGIX 0x8194
+#define GL_TEXTURE_DEFORMATION_SGIX 0x8195
+#define GL_DEFORMATIONS_MASK_SGIX 0x8196
+#define GL_MAX_DEFORMATION_ORDER_SGIX 0x8197
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3DSGIXPROC) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+typedef void (APIENTRYP PFNGLDEFORMATIONMAP3FSGIXPROC) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+typedef void (APIENTRYP PFNGLDEFORMSGIXPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLLOADIDENTITYDEFORMATIONMAPSGIXPROC) (GLbitfield mask);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDeformationMap3dSGIX (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, GLdouble w1, GLdouble w2, GLint wstride, GLint worder, const GLdouble *points);
+GLAPI void APIENTRY glDeformationMap3fSGIX (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, GLfloat w1, GLfloat w2, GLint wstride, GLint worder, const GLfloat *points);
+GLAPI void APIENTRY glDeformSGIX (GLbitfield mask);
+GLAPI void APIENTRY glLoadIdentityDeformationMapSGIX (GLbitfield mask);
+#endif
+#endif /* GL_SGIX_polynomial_ffd */
+
+#ifndef GL_SGIX_reference_plane
+#define GL_SGIX_reference_plane 1
+#define GL_REFERENCE_PLANE_SGIX 0x817D
+#define GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E
+typedef void (APIENTRYP PFNGLREFERENCEPLANESGIXPROC) (const GLdouble *equation);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation);
+#endif
+#endif /* GL_SGIX_reference_plane */
+
+#ifndef GL_SGIX_resample
+#define GL_SGIX_resample 1
+#define GL_PACK_RESAMPLE_SGIX 0x842C
+#define GL_UNPACK_RESAMPLE_SGIX 0x842D
+#define GL_RESAMPLE_REPLICATE_SGIX 0x842E
+#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F
+#define GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#endif /* GL_SGIX_resample */
+
+#ifndef GL_SGIX_scalebias_hint
+#define GL_SGIX_scalebias_hint 1
+#define GL_SCALEBIAS_HINT_SGIX 0x8322
+#endif /* GL_SGIX_scalebias_hint */
+
+#ifndef GL_SGIX_shadow
+#define GL_SGIX_shadow 1
+#define GL_TEXTURE_COMPARE_SGIX 0x819A
+#define GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+#endif /* GL_SGIX_shadow */
+
+#ifndef GL_SGIX_shadow_ambient
+#define GL_SGIX_shadow_ambient 1
+#define GL_SHADOW_AMBIENT_SGIX 0x80BF
+#endif /* GL_SGIX_shadow_ambient */
+
+#ifndef GL_SGIX_sprite
+#define GL_SGIX_sprite 1
+#define GL_SPRITE_SGIX 0x8148
+#define GL_SPRITE_MODE_SGIX 0x8149
+#define GL_SPRITE_AXIS_SGIX 0x814A
+#define GL_SPRITE_TRANSLATION_SGIX 0x814B
+#define GL_SPRITE_AXIAL_SGIX 0x814C
+#define GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D
+#define GL_SPRITE_EYE_ALIGNED_SGIX 0x814E
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFSGIXPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERFVSGIXPROC) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERISGIXPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLSPRITEPARAMETERIVSGIXPROC) (GLenum pname, const GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glSpriteParameterfSGIX (GLenum pname, GLfloat param);
+GLAPI void APIENTRY glSpriteParameterfvSGIX (GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glSpriteParameteriSGIX (GLenum pname, GLint param);
+GLAPI void APIENTRY glSpriteParameterivSGIX (GLenum pname, const GLint *params);
+#endif
+#endif /* GL_SGIX_sprite */
+
+#ifndef GL_SGIX_subsample
+#define GL_SGIX_subsample 1
+#define GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0
+#define GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1
+#define GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2
+#define GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3
+#define GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4
+#endif /* GL_SGIX_subsample */
+
+#ifndef GL_SGIX_tag_sample_buffer
+#define GL_SGIX_tag_sample_buffer 1
+typedef void (APIENTRYP PFNGLTAGSAMPLEBUFFERSGIXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glTagSampleBufferSGIX (void);
+#endif
+#endif /* GL_SGIX_tag_sample_buffer */
+
+#ifndef GL_SGIX_texture_add_env
+#define GL_SGIX_texture_add_env 1
+#define GL_TEXTURE_ENV_BIAS_SGIX 0x80BE
+#endif /* GL_SGIX_texture_add_env */
+
+#ifndef GL_SGIX_texture_coordinate_clamp
+#define GL_SGIX_texture_coordinate_clamp 1
+#define GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+#endif /* GL_SGIX_texture_coordinate_clamp */
+
+#ifndef GL_SGIX_texture_lod_bias
+#define GL_SGIX_texture_lod_bias 1
+#define GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E
+#define GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F
+#define GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190
+#endif /* GL_SGIX_texture_lod_bias */
+
+#ifndef GL_SGIX_texture_multi_buffer
+#define GL_SGIX_texture_multi_buffer 1
+#define GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#endif /* GL_SGIX_texture_multi_buffer */
+
+#ifndef GL_SGIX_texture_scale_bias
+#define GL_SGIX_texture_scale_bias 1
+#define GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#endif /* GL_SGIX_texture_scale_bias */
+
+#ifndef GL_SGIX_vertex_preclip
+#define GL_SGIX_vertex_preclip 1
+#define GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+#endif /* GL_SGIX_vertex_preclip */
+
+#ifndef GL_SGIX_ycrcb
+#define GL_SGIX_ycrcb 1
+#define GL_YCRCB_422_SGIX 0x81BB
+#define GL_YCRCB_444_SGIX 0x81BC
+#endif /* GL_SGIX_ycrcb */
+
+#ifndef GL_SGIX_ycrcb_subsample
+#define GL_SGIX_ycrcb_subsample 1
+#endif /* GL_SGIX_ycrcb_subsample */
+
+#ifndef GL_SGIX_ycrcba
+#define GL_SGIX_ycrcba 1
+#define GL_YCRCB_SGIX 0x8318
+#define GL_YCRCBA_SGIX 0x8319
+#endif /* GL_SGIX_ycrcba */
+
+#ifndef GL_SGI_color_matrix
+#define GL_SGI_color_matrix 1
+#define GL_COLOR_MATRIX_SGI 0x80B1
+#define GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#endif /* GL_SGI_color_matrix */
+
+#ifndef GL_SGI_color_table
+#define GL_SGI_color_table 1
+#define GL_COLOR_TABLE_SGI 0x80D0
+#define GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+typedef void (APIENTRYP PFNGLCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRYP PFNGLCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRYP PFNGLCOPYCOLORTABLESGIPROC) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+typedef void (APIENTRYP PFNGLGETCOLORTABLESGIPROC) (GLenum target, GLenum format, GLenum type, void *table);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERFVSGIPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETCOLORTABLEPARAMETERIVSGIPROC) (GLenum target, GLenum pname, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColorTableSGI (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const void *table);
+GLAPI void APIENTRY glColorTableParameterfvSGI (GLenum target, GLenum pname, const GLfloat *params);
+GLAPI void APIENTRY glColorTableParameterivSGI (GLenum target, GLenum pname, const GLint *params);
+GLAPI void APIENTRY glCopyColorTableSGI (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width);
+GLAPI void APIENTRY glGetColorTableSGI (GLenum target, GLenum format, GLenum type, void *table);
+GLAPI void APIENTRY glGetColorTableParameterfvSGI (GLenum target, GLenum pname, GLfloat *params);
+GLAPI void APIENTRY glGetColorTableParameterivSGI (GLenum target, GLenum pname, GLint *params);
+#endif
+#endif /* GL_SGI_color_table */
+
+#ifndef GL_SGI_texture_color_table
+#define GL_SGI_texture_color_table 1
+#define GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+#endif /* GL_SGI_texture_color_table */
+
+#ifndef GL_SUNX_constant_data
+#define GL_SUNX_constant_data 1
+#define GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+typedef void (APIENTRYP PFNGLFINISHTEXTURESUNXPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glFinishTextureSUNX (void);
+#endif
+#endif /* GL_SUNX_constant_data */
+
+#ifndef GL_SUN_convolution_border_modes
+#define GL_SUN_convolution_border_modes 1
+#define GL_WRAP_BORDER_SUN 0x81D4
+#endif /* GL_SUN_convolution_border_modes */
+
+#ifndef GL_SUN_global_alpha
+#define GL_SUN_global_alpha 1
+#define GL_GLOBAL_ALPHA_SUN 0x81D9
+#define GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORBSUNPROC) (GLbyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORSSUNPROC) (GLshort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORISUNPROC) (GLint factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORFSUNPROC) (GLfloat factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORDSUNPROC) (GLdouble factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUBSUNPROC) (GLubyte factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUSSUNPROC) (GLushort factor);
+typedef void (APIENTRYP PFNGLGLOBALALPHAFACTORUISUNPROC) (GLuint factor);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGlobalAlphaFactorbSUN (GLbyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorsSUN (GLshort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoriSUN (GLint factor);
+GLAPI void APIENTRY glGlobalAlphaFactorfSUN (GLfloat factor);
+GLAPI void APIENTRY glGlobalAlphaFactordSUN (GLdouble factor);
+GLAPI void APIENTRY glGlobalAlphaFactorubSUN (GLubyte factor);
+GLAPI void APIENTRY glGlobalAlphaFactorusSUN (GLushort factor);
+GLAPI void APIENTRY glGlobalAlphaFactoruiSUN (GLuint factor);
+#endif
+#endif /* GL_SUN_global_alpha */
+
+#ifndef GL_SUN_mesh_array
+#define GL_SUN_mesh_array 1
+#define GL_QUAD_MESH_SUN 0x8614
+#define GL_TRIANGLE_MESH_SUN 0x8615
+typedef void (APIENTRYP PFNGLDRAWMESHARRAYSSUNPROC) (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawMeshArraysSUN (GLenum mode, GLint first, GLsizei count, GLsizei width);
+#endif
+#endif /* GL_SUN_mesh_array */
+
+#ifndef GL_SUN_slice_accum
+#define GL_SUN_slice_accum 1
+#define GL_SLICE_ACCUM_SUN 0x85CC
+#endif /* GL_SUN_slice_accum */
+
+#ifndef GL_SUN_triangle_list
+#define GL_SUN_triangle_list 1
+#define GL_RESTART_SUN 0x0001
+#define GL_REPLACE_MIDDLE_SUN 0x0002
+#define GL_REPLACE_OLDEST_SUN 0x0003
+#define GL_TRIANGLE_LIST_SUN 0x81D7
+#define GL_REPLACEMENT_CODE_SUN 0x81D8
+#define GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define GL_R1UI_V3F_SUN 0x85C4
+#define GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define GL_R1UI_C3F_V3F_SUN 0x85C6
+#define GL_R1UI_N3F_V3F_SUN 0x85C7
+#define GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define GL_R1UI_T2F_V3F_SUN 0x85C9
+#define GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUISUNPROC) (GLuint code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSSUNPROC) (GLushort code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBSUNPROC) (GLubyte code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVSUNPROC) (const GLuint *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUSVSUNPROC) (const GLushort *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUBVSUNPROC) (const GLubyte *code);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEPOINTERSUNPROC) (GLenum type, GLsizei stride, const void **pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glReplacementCodeuiSUN (GLuint code);
+GLAPI void APIENTRY glReplacementCodeusSUN (GLushort code);
+GLAPI void APIENTRY glReplacementCodeubSUN (GLubyte code);
+GLAPI void APIENTRY glReplacementCodeuivSUN (const GLuint *code);
+GLAPI void APIENTRY glReplacementCodeusvSUN (const GLushort *code);
+GLAPI void APIENTRY glReplacementCodeubvSUN (const GLubyte *code);
+GLAPI void APIENTRY glReplacementCodePointerSUN (GLenum type, GLsizei stride, const void **pointer);
+#endif
+#endif /* GL_SUN_triangle_list */
+
+#ifndef GL_SUN_vertex
+#define GL_SUN_vertex 1
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX2FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FSUNPROC) (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4UBVERTEX3FVSUNPROC) (const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FSUNPROC) (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4UBVERTEX3FVSUNPROC) (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLTEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FSUNPROC) (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (APIENTRYP PFNGLTEXCOORD4FCOLOR4FNORMAL3FVERTEX4FVSUNPROC) (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FSUNPROC) (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUIVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FSUNPROC) (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4UBVERTEX3FVSUNPROC) (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUINORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUICOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FSUNPROC) (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRYP PFNGLREPLACEMENTCODEUITEXCOORD2FCOLOR4FNORMAL3FVERTEX3FVSUNPROC) (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glColor4ubVertex2fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y);
+GLAPI void APIENTRY glColor4ubVertex2fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor4ubVertex3fSUN (GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4ubVertex3fvSUN (const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glColor3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor3fVertex3fvSUN (const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glNormal3fVertex3fSUN (GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glNormal3fVertex3fvSUN (const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fSUN (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glColor4fNormal3fVertex3fvSUN (const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fVertex3fSUN (GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fVertex3fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fVertex4fvSUN (const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fSUN (GLfloat s, GLfloat t, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4ubVertex3fvSUN (const GLfloat *tc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fSUN (GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glTexCoord2fColor4fNormal3fVertex3fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fSUN (GLfloat s, GLfloat t, GLfloat p, GLfloat q, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI void APIENTRY glTexCoord4fColor4fNormal3fVertex4fvSUN (const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fSUN (GLuint rc, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiVertex3fvSUN (const GLuint *rc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fSUN (GLuint rc, GLubyte r, GLubyte g, GLubyte b, GLubyte a, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4ubVertex3fvSUN (const GLuint *rc, const GLubyte *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fSUN (GLuint rc, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *n, const GLfloat *v);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN (GLuint rc, GLfloat s, GLfloat t, GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLfloat nx, GLfloat ny, GLfloat nz, GLfloat x, GLfloat y, GLfloat z);
+GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (const GLuint *rc, const GLfloat *tc, const GLfloat *c, const GLfloat *n, const GLfloat *v);
+#endif
+#endif /* GL_SUN_vertex */
+
+#ifndef GL_WIN_phong_shading
+#define GL_WIN_phong_shading 1
+#define GL_PHONG_WIN 0x80EA
+#define GL_PHONG_HINT_WIN 0x80EB
+#endif /* GL_WIN_phong_shading */
+
+#ifndef GL_WIN_specular_fog
+#define GL_WIN_specular_fog 1
+#define GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+#endif /* GL_WIN_specular_fog */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengles.h b/Client/ThirdParty/SDL2/include/SDL_opengles.h
new file mode 100644
index 0000000..7ebf4cc
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengles.h
@@ -0,0 +1,39 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengles.h
+ *
+ * This is a simple file to encapsulate the OpenGL ES 1.X API headers.
+ */
+#include "SDL_config.h"
+
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+#else
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengles2.h b/Client/ThirdParty/SDL2/include/SDL_opengles2.h
new file mode 100644
index 0000000..ce114ae
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengles2.h
@@ -0,0 +1,52 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_opengles2.h
+ *
+ * This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
+ */
+#include "SDL_config.h"
+
+#ifndef _MSC_VER
+
+#ifdef __IPHONEOS__
+#include <OpenGLES/ES2/gl.h>
+#include <OpenGLES/ES2/glext.h>
+#else
+#include <GLES2/gl2platform.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#endif
+
+#else /* _MSC_VER */
+
+/* OpenGL ES2 headers for Visual Studio */
+#include "SDL_opengles2_khrplatform.h"
+#include "SDL_opengles2_gl2platform.h"
+#include "SDL_opengles2_gl2.h"
+#include "SDL_opengles2_gl2ext.h"
+
+#endif /* _MSC_VER */
+
+#ifndef APIENTRY
+#define APIENTRY GL_APIENTRY
+#endif
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2.h b/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2.h
new file mode 100644
index 0000000..c62fb0a
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2.h
@@ -0,0 +1,621 @@
+#ifndef __gl2_h_
+#define __gl2_h_
+
+/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */
+
+/*#include <GLES2/gl2platform.h>*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/*-------------------------------------------------------------------------
+ * Data type definitions
+ *-----------------------------------------------------------------------*/
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef khronos_int8_t GLbyte;
+typedef short GLshort;
+typedef int GLint;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned int GLuint;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+
+/* GL types for handling large vertex buffer objects */
+typedef khronos_intptr_t GLintptr;
+typedef khronos_ssize_t GLsizeiptr;
+
+/* OpenGL ES core versions */
+#define GL_ES_VERSION_2_0 1
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+
+/* Boolean */
+#define GL_FALSE 0
+#define GL_TRUE 1
+
+/* BeginMode */
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+
+/* AlphaFunction (not supported in ES20) */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* BlendingFactorDest */
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+
+/* BlendingFactorSrc */
+/* GL_ZERO */
+/* GL_ONE */
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+/* GL_SRC_ALPHA */
+/* GL_ONE_MINUS_SRC_ALPHA */
+/* GL_DST_ALPHA */
+/* GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD 0x8006
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_COLOR 0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STATIC_DRAW 0x88E4
+#define GL_DYNAMIC_DRAW 0x88E8
+
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+
+/* CullFaceMode */
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_FRONT_AND_BACK 0x0408
+
+/* DepthFunction */
+/* GL_NEVER */
+/* GL_LESS */
+/* GL_EQUAL */
+/* GL_LEQUAL */
+/* GL_GREATER */
+/* GL_NOTEQUAL */
+/* GL_GEQUAL */
+/* GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_CULL_FACE 0x0B44
+#define GL_BLEND 0x0BE2
+#define GL_DITHER 0x0BD0
+#define GL_STENCIL_TEST 0x0B90
+#define GL_DEPTH_TEST 0x0B71
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_COVERAGE 0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH 0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VIEWPORT 0x0BA2
+#define GL_SCISSOR_BOX 0x0C10
+/* GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+/* GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+
+/* GetTextureParameter */
+/* GL_TEXTURE_MAG_FILTER */
+/* GL_TEXTURE_MIN_FILTER */
+/* GL_TEXTURE_WRAP_S */
+/* GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+
+/* DataType */
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+/* PixelType */
+/* GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_DELETE_STATUS 0x8B80
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+
+/* StencilOp */
+/* GL_ZERO */
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_INVERT 0x150A
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+
+/* StringName */
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+/* TextureMinFilter */
+/* GL_NEAREST */
+/* GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+/* TextureTarget */
+/* GL_TEXTURE_2D */
+#define GL_TEXTURE 0x1702
+
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MIRRORED_REPEAT 0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_CUBE 0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_COMPILER 0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_LOW_INT 0x8DF3
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_HIGH_INT 0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGB565 0x8D62
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_STENCIL_INDEX8 0x8D48
+
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+
+#define GL_NONE 0
+
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+
+/*-------------------------------------------------------------------------
+ * GL core functions.
+ *-----------------------------------------------------------------------*/
+
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation ( GLenum mode );
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLclampf depth);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2_h_ */
+
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2ext.h b/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2ext.h
new file mode 100644
index 0000000..e8ca8b1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2ext.h
@@ -0,0 +1,2050 @@
+#ifndef __gl2ext_h_
+#define __gl2ext_h_
+
+/* $Revision: 22801 $ on $Date:: 2013-08-21 03:20:48 -0700 #$ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+#ifndef GL_APIENTRYP
+# define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+/* New types shared by several extensions */
+
+#ifndef __gl3_h_
+/* These are defined with respect to <inttypes.h> in the
+ * Apple extension spec, but they are also used by non-APPLE
+ * extensions, and in the Khronos header we use the Khronos
+ * portable types in khrplatform.h, which must be defined.
+ */
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef struct __GLsync *GLsync;
+#endif
+
+
+/*------------------------------------------------------------------------*
+ * OES extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_ETC1_RGB8_OES 0x8D64
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_PALETTE4_RGB8_OES 0x8B90
+#define GL_PALETTE4_RGBA8_OES 0x8B91
+#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define GL_PALETTE4_RGBA4_OES 0x8B93
+#define GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define GL_PALETTE8_RGB8_OES 0x8B95
+#define GL_PALETTE8_RGBA8_OES 0x8B96
+#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define GL_PALETTE8_RGBA4_OES 0x8B98
+#define GL_PALETTE8_RGB5_A1_OES 0x8B99
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_DEPTH_COMPONENT24_OES 0x81A6
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#endif
+
+/* GL_OES_depth_texture */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+typedef void* GLeglImageOES;
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+/* GLeglImageOES defined in GL_OES_EGL_image already. */
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_UNSIGNED_INT 0x1405
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_WRITE_ONLY_OES 0x88B9
+#define GL_BUFFER_ACCESS_OES 0x88BB
+#define GL_BUFFER_MAPPED_OES 0x88BC
+#define GL_BUFFER_MAP_POINTER_OES 0x88BD
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_ALPHA8_OES 0x803C
+#define GL_DEPTH_COMPONENT16_OES 0x81A5
+/* reuse GL_DEPTH_COMPONENT24_OES */
+/* reuse GL_DEPTH24_STENCIL8_OES */
+/* reuse GL_DEPTH_COMPONENT32_OES */
+#define GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define GL_LUMINANCE8_OES 0x8040
+#define GL_RGBA4_OES 0x8056
+#define GL_RGB5_A1_OES 0x8057
+#define GL_RGB565_OES 0x8D62
+/* reuse GL_RGB8_OES */
+/* reuse GL_RGBA8_OES */
+/* reuse GL_RGB10_EXT */
+/* reuse GL_RGB10_A2_EXT */
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_RGB8_OES 0x8051
+#define GL_RGBA8_OES 0x8058
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_STENCIL_INDEX1_OES 0x8D46
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_STENCIL_INDEX4_OES 0x8D47
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_TEXTURE_WRAP_R_OES 0x8072
+#define GL_TEXTURE_3D_OES 0x806F
+#define GL_TEXTURE_BINDING_3D_OES 0x806A
+#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define GL_SAMPLER_3D_OES 0x8B5F
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#endif
+
+/* GL_OES_texture_float */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_HALF_FLOAT_OES 0x8D61
+#endif
+
+/* GL_OES_texture_half_float_linear */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_texture_npot */
+/* No new tokens introduced by this extension. */
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#endif
+
+/* GL_OES_vertex_half_float */
+/* GL_HALF_FLOAT_OES defined in GL_OES_texture_half_float already. */
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define GL_INT_10_10_10_2_OES 0x8DF7
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension tokens
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+typedef void (GL_APIENTRYP GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define GL_DEBUG_SOURCE_API_KHR 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define GL_BUFFER_KHR 0x82E0
+#define GL_SHADER_KHR 0x82E1
+#define GL_PROGRAM_KHR 0x82E2
+#define GL_QUERY_KHR 0x82E3
+/* PROGRAM_PIPELINE only in GL */
+#define GL_SAMPLER_KHR 0x82E6
+/* DISPLAY_LIST only in GL */
+#define GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define GL_DEBUG_OUTPUT_KHR 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define GL_STACK_OVERFLOW_KHR 0x0503
+#define GL_STACK_UNDERFLOW_KHR 0x0504
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#endif
+
+/*------------------------------------------------------------------------*
+ * AMD extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_3DC_X_AMD 0x87F9
+#define GL_3DC_XY_AMD 0x87FA
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_ATC_RGB_AMD 0x8C92
+#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#endif
+
+/* GL_AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_COUNTER_TYPE_AMD 0x8BC0
+#define GL_COUNTER_RANGE_AMD 0x8BC1
+#define GL_UNSIGNED_INT64_AMD 0x8BC2
+#define GL_PERCENTAGE_AMD 0x8BC3
+#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define GL_PERFMON_RESULT_AMD 0x8BC6
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_Z400_BINARY_AMD 0x8740
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_STENCIL_OES 0x84F9
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT32_OES 0x81A7
+#define GL_DEPTH24_STENCIL8_OES 0x88F0
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define GL_MAX_SAMPLES_ANGLE 0x8D57
+#endif
+
+/* GL_ANGLE_instanced_arrays */
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_PROGRAM_BINARY_ANGLE 0x93A6
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+#endif
+
+/* GL_ANGLE_translated_shader_source */
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+/* No new tokens introduced by this extension. */
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define GL_MAX_SAMPLES_APPLE 0x8D57
+#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_RGB_422_APPLE 0x8A1F
+#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+
+#define GL_SYNC_OBJECT_APPLE 0x8A53
+#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define GL_OBJECT_TYPE_APPLE 0x9112
+#define GL_SYNC_CONDITION_APPLE 0x9113
+#define GL_SYNC_STATUS_APPLE 0x9114
+#define GL_SYNC_FLAGS_APPLE 0x9115
+#define GL_SYNC_FENCE_APPLE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define GL_UNSIGNALED_APPLE 0x9118
+#define GL_SIGNALED_APPLE 0x9119
+#define GL_ALREADY_SIGNALED_APPLE 0x911A
+#define GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define GL_CONDITION_SATISFIED_APPLE 0x911C
+#define GL_WAIT_FAILED_APPLE 0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_MALI_SHADER_BINARY_ARM 0x8F60
+#endif
+
+/* GL_ARM_rgba8 */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT 0x8007
+#define GL_MAX_EXT 0x8008
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_RGBA16F_EXT 0x881A
+#define GL_RGB16F_EXT 0x881B
+#define GL_RG16F_EXT 0x822F
+#define GL_R16F_EXT 0x822D
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define GL_PROGRAM_OBJECT_EXT 0x8B40
+#define GL_SHADER_OBJECT_EXT 0x8B48
+#define GL_BUFFER_OBJECT_EXT 0x9151
+#define GL_QUERY_OBJECT_EXT 0x9153
+#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#endif
+
+/* GL_EXT_debug_marker */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT 0x1800
+#define GL_DEPTH_EXT 0x1801
+#define GL_STENCIL_EXT 0x1802
+#endif
+
+#ifndef GL_EXT_disjoint_timer_query
+#define GL_QUERY_COUNTER_BITS_EXT 0x8864
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#define GL_TIMESTAMP_EXT 0x8E28
+#define GL_GPU_DISJOINT_EXT 0x8FBB
+#endif
+
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define GL_DRAW_BUFFER0_EXT 0x8825
+#define GL_DRAW_BUFFER1_EXT 0x8826
+#define GL_DRAW_BUFFER2_EXT 0x8827
+#define GL_DRAW_BUFFER3_EXT 0x8828
+#define GL_DRAW_BUFFER4_EXT 0x8829
+#define GL_DRAW_BUFFER5_EXT 0x882A
+#define GL_DRAW_BUFFER6_EXT 0x882B
+#define GL_DRAW_BUFFER7_EXT 0x882C
+#define GL_DRAW_BUFFER8_EXT 0x882D
+#define GL_DRAW_BUFFER9_EXT 0x882E
+#define GL_DRAW_BUFFER10_EXT 0x882F
+#define GL_DRAW_BUFFER11_EXT 0x8830
+#define GL_DRAW_BUFFER12_EXT 0x8831
+#define GL_DRAW_BUFFER13_EXT 0x8832
+#define GL_DRAW_BUFFER14_EXT 0x8833
+#define GL_DRAW_BUFFER15_EXT 0x8834
+#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#endif
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_MAP_READ_BIT_EXT 0x0001
+#define GL_MAP_WRITE_BIT_EXT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define GL_MAX_SAMPLES_EXT 0x8D57
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define GL_MULTIVIEW_EXT 0x90F1
+#define GL_DRAW_BUFFER_EXT 0x0C01
+#define GL_READ_BUFFER_EXT 0x0C02
+#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#define GL_CURRENT_QUERY_EXT 0x8865
+#define GL_QUERY_RESULT_EXT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+/* reuse GL_NO_ERROR */
+#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define GL_ACTIVE_PROGRAM_EXT 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#endif
+
+/* GL_EXT_shader_texture_lod */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_SRGB_EXT 0x8C40
+#define GL_SRGB_ALPHA_EXT 0x8C42
+#define GL_SRGB8_ALPHA8_EXT 0x8C43
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#endif
+
+/* GL_EXT_sRGB_write_control */
+#ifndef GL_EXT_sRGB_write_control
+#define GL_EXT_sRGB_write_control 1
+#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT 0x80E1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_RED_EXT 0x1903
+#define GL_RG_EXT 0x8227
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#endif
+
+/* GL_EXT_texture_sRGB_decode */
+#ifndef GL_EXT_texture_sRGB_decode
+#define GL_EXT_texture_sRGB_decode 1
+#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define GL_DECODE_EXT 0x8A49
+#define GL_SKIP_DECODE_EXT 0x8A4A
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define GL_ALPHA8_EXT 0x803C
+#define GL_LUMINANCE8_EXT 0x8040
+#define GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define GL_RGBA32F_EXT 0x8814
+#define GL_RGB32F_EXT 0x8815
+#define GL_ALPHA32F_EXT 0x8816
+#define GL_LUMINANCE32F_EXT 0x8818
+#define GL_LUMINANCE_ALPHA32F_EXT 0x8819
+/* reuse GL_RGBA16F_EXT */
+/* reuse GL_RGB16F_EXT */
+#define GL_ALPHA16F_EXT 0x881C
+#define GL_LUMINANCE16F_EXT 0x881E
+#define GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define GL_RGB10_A2_EXT 0x8059
+#define GL_RGB10_EXT 0x8052
+#define GL_BGRA8_EXT 0x93A1
+#define GL_R8_EXT 0x8229
+#define GL_RG8_EXT 0x822B
+#define GL_R32F_EXT 0x822E
+#define GL_RG32F_EXT 0x8230
+#define GL_R16F_EXT 0x822D
+#define GL_RG16F_EXT 0x822F
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_SHADER_BINARY_DMP 0x9250
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_GCCSO_SHADER_BINARY_FJ 0x9260
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_SGX_PROGRAM_BINARY_IMG 0x9130
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_BGRA_IMG 0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_SGX_BINARY_IMG 0x8C0A
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define GL_MAX_SAMPLES_IMG 0x9135
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define GL_COVERAGE_SAMPLES_NV 0x8ED4
+#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+#define GL_COVERAGE_BUFFER_BIT_NV 0x00008000
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define GL_DRAW_BUFFER0_NV 0x8825
+#define GL_DRAW_BUFFER1_NV 0x8826
+#define GL_DRAW_BUFFER2_NV 0x8827
+#define GL_DRAW_BUFFER3_NV 0x8828
+#define GL_DRAW_BUFFER4_NV 0x8829
+#define GL_DRAW_BUFFER5_NV 0x882A
+#define GL_DRAW_BUFFER6_NV 0x882B
+#define GL_DRAW_BUFFER7_NV 0x882C
+#define GL_DRAW_BUFFER8_NV 0x882D
+#define GL_DRAW_BUFFER9_NV 0x882E
+#define GL_DRAW_BUFFER10_NV 0x882F
+#define GL_DRAW_BUFFER11_NV 0x8830
+#define GL_DRAW_BUFFER12_NV 0x8831
+#define GL_DRAW_BUFFER13_NV 0x8832
+#define GL_DRAW_BUFFER14_NV 0x8833
+#define GL_DRAW_BUFFER15_NV 0x8834
+#define GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define GL_COLOR_ATTACHMENT15_NV 0x8CEF
+#endif
+
+/* GL_NV_draw_instanced */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+/* GL_COLOR_ATTACHMENT{0-15}_NV defined in GL_NV_draw_buffers already. */
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_READ_FRAMEBUFFER_NV 0x8CA8
+#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6
+#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56
+#define GL_MAX_SAMPLES_NV 0x8D57
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_READ_BUFFER_NV 0x0C02
+#endif
+
+/* GL_NV_read_buffer_front */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_depth_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_read_stencil */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_SLUMINANCE_NV 0x8C46
+#define GL_SLUMINANCE_ALPHA_NV 0x8C44
+#define GL_SRGB8_NV 0x8C41
+#define GL_SLUMINANCE8_NV 0x8C47
+#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45
+#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+#define GL_ETC1_SRGB8_NV 0x88EE
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_TEXTURE_BORDER_COLOR_NV 0x1004
+#define GL_CLAMP_TO_BORDER_NV 0x812D
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+/* No new tokens introduced by this extension. */
+
+/* GL_NV_texture_npot_2D_mipmap */
+/* No new tokens introduced by this extension. */
+
+/*------------------------------------------------------------------------*
+ * QCOM extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_ALPHA_TEST_QCOM 0x0BC0
+#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define GL_ALPHA_TEST_REF_QCOM 0x0BC2
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+#endif
+
+/* GL_QCOM_driver_control */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define GL_STATE_RESTORE 0x8BDC
+#endif
+
+/* GL_QCOM_extended_get2 */
+/* No new tokens introduced by this extension. */
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_WRITEONLY_RENDERING_QCOM 0x8823
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_SHADER_BINARY_VIV 0x8FC4
+#endif
+
+/*------------------------------------------------------------------------*
+ * End of extension tokens, start of corresponding extension functions
+ *------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*
+ * OES extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_OES_compressed_ETC1_RGB8_texture */
+#ifndef GL_OES_compressed_ETC1_RGB8_texture
+#define GL_OES_compressed_ETC1_RGB8_texture 1
+#endif
+
+/* GL_OES_compressed_paletted_texture */
+#ifndef GL_OES_compressed_paletted_texture
+#define GL_OES_compressed_paletted_texture 1
+#endif
+
+/* GL_OES_depth24 */
+#ifndef GL_OES_depth24
+#define GL_OES_depth24 1
+#endif
+
+/* GL_OES_depth32 */
+#ifndef GL_OES_depth32
+#define GL_OES_depth32 1
+#endif
+
+/* GL_OES_depth_texture */
+#ifndef GL_OES_depth_texture
+#define GL_OES_depth_texture 1
+#endif
+
+/* GL_OES_EGL_image */
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image);
+GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image);
+#endif
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+#endif
+
+/* GL_OES_EGL_image_external */
+#ifndef GL_OES_EGL_image_external
+#define GL_OES_EGL_image_external 1
+/* glEGLImageTargetTexture2DOES defined in GL_OES_EGL_image already. */
+#endif
+
+/* GL_OES_element_index_uint */
+#ifndef GL_OES_element_index_uint
+#define GL_OES_element_index_uint 1
+#endif
+
+/* GL_OES_fbo_render_mipmap */
+#ifndef GL_OES_fbo_render_mipmap
+#define GL_OES_fbo_render_mipmap 1
+#endif
+
+/* GL_OES_fragment_precision_high */
+#ifndef GL_OES_fragment_precision_high
+#define GL_OES_fragment_precision_high 1
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_OES_get_program_binary
+#define GL_OES_get_program_binary 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+#endif
+
+/* GL_OES_mapbuffer */
+#ifndef GL_OES_mapbuffer
+#define GL_OES_mapbuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, GLvoid **params);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, GLvoid **params);
+#endif
+
+/* GL_OES_packed_depth_stencil */
+#ifndef GL_OES_packed_depth_stencil
+#define GL_OES_packed_depth_stencil 1
+#endif
+
+/* GL_OES_required_internalformat */
+#ifndef GL_OES_required_internalformat
+#define GL_OES_required_internalformat 1
+#endif
+
+/* GL_OES_rgb8_rgba8 */
+#ifndef GL_OES_rgb8_rgba8
+#define GL_OES_rgb8_rgba8 1
+#endif
+
+/* GL_OES_standard_derivatives */
+#ifndef GL_OES_standard_derivatives
+#define GL_OES_standard_derivatives 1
+#endif
+
+/* GL_OES_stencil1 */
+#ifndef GL_OES_stencil1
+#define GL_OES_stencil1 1
+#endif
+
+/* GL_OES_stencil4 */
+#ifndef GL_OES_stencil4
+#define GL_OES_stencil4 1
+#endif
+
+#ifndef GL_OES_surfaceless_context
+#define GL_OES_surfaceless_context 1
+#endif
+
+/* GL_OES_texture_3D */
+#ifndef GL_OES_texture_3D
+#define GL_OES_texture_3D 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+#endif
+
+/* GL_OES_texture_float */
+#ifndef GL_OES_texture_float
+#define GL_OES_texture_float 1
+#endif
+
+/* GL_OES_texture_float_linear */
+#ifndef GL_OES_texture_float_linear
+#define GL_OES_texture_float_linear 1
+#endif
+
+/* GL_OES_texture_half_float */
+#ifndef GL_OES_texture_half_float
+#define GL_OES_texture_half_float 1
+#endif
+
+/* GL_OES_texture_half_float_linear */
+#ifndef GL_OES_texture_half_float_linear
+#define GL_OES_texture_half_float_linear 1
+#endif
+
+/* GL_OES_texture_npot */
+#ifndef GL_OES_texture_npot
+#define GL_OES_texture_npot 1
+#endif
+
+/* GL_OES_vertex_array_object */
+#ifndef GL_OES_vertex_array_object
+#define GL_OES_vertex_array_object 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array);
+#endif
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array);
+#endif
+
+/* GL_OES_vertex_half_float */
+#ifndef GL_OES_vertex_half_float
+#define GL_OES_vertex_half_float 1
+#endif
+
+/* GL_OES_vertex_type_10_10_10_2 */
+#ifndef GL_OES_vertex_type_10_10_10_2
+#define GL_OES_vertex_type_10_10_10_2 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * KHR extension functions
+ *------------------------------------------------------------------------*/
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void);
+GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, GLvoid **params);
+#endif
+
+#ifndef GL_KHR_texture_compression_astc_ldr
+#define GL_KHR_texture_compression_astc_ldr 1
+#endif
+
+
+/*------------------------------------------------------------------------*
+ * AMD extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_AMD_compressed_3DC_texture */
+#ifndef GL_AMD_compressed_3DC_texture
+#define GL_AMD_compressed_3DC_texture 1
+#endif
+
+/* GL_AMD_compressed_ATC_texture */
+#ifndef GL_AMD_compressed_ATC_texture
+#define GL_AMD_compressed_ATC_texture 1
+#endif
+
+/* AMD_performance_monitor */
+#ifndef GL_AMD_performance_monitor
+#define GL_AMD_performance_monitor 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors);
+GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor);
+GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors);
+typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *countersList);
+typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor);
+typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten);
+#endif
+
+/* GL_AMD_program_binary_Z400 */
+#ifndef GL_AMD_program_binary_Z400
+#define GL_AMD_program_binary_Z400 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ANGLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ANGLE_depth_texture */
+#ifndef GL_ANGLE_depth_texture
+#define GL_ANGLE_depth_texture 1
+#endif
+
+/* GL_ANGLE_framebuffer_blit */
+#ifndef GL_ANGLE_framebuffer_blit
+#define GL_ANGLE_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_ANGLE_framebuffer_multisample */
+#ifndef GL_ANGLE_framebuffer_multisample
+#define GL_ANGLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+#ifndef GL_ANGLE_instanced_arrays
+#define GL_ANGLE_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_ANGLE_pack_reverse_row_order */
+#ifndef GL_ANGLE_pack_reverse_row_order
+#define GL_ANGLE_pack_reverse_row_order 1
+#endif
+
+/* GL_ANGLE_program_binary */
+#ifndef GL_ANGLE_program_binary
+#define GL_ANGLE_program_binary 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt3 */
+#ifndef GL_ANGLE_texture_compression_dxt3
+#define GL_ANGLE_texture_compression_dxt3 1
+#endif
+
+/* GL_ANGLE_texture_compression_dxt5 */
+#ifndef GL_ANGLE_texture_compression_dxt5
+#define GL_ANGLE_texture_compression_dxt5 1
+#endif
+
+/* GL_ANGLE_texture_usage */
+#ifndef GL_ANGLE_texture_usage
+#define GL_ANGLE_texture_usage 1
+#endif
+
+#ifndef GL_ANGLE_translated_shader_source
+#define GL_ANGLE_translated_shader_source 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+#endif
+
+/*------------------------------------------------------------------------*
+ * APPLE extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_APPLE_copy_texture_levels */
+#ifndef GL_APPLE_copy_texture_levels
+#define GL_APPLE_copy_texture_levels 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
+#endif
+
+/* GL_APPLE_framebuffer_multisample */
+#ifndef GL_APPLE_framebuffer_multisample
+#define GL_APPLE_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void);
+#endif
+
+/* GL_APPLE_rgb_422 */
+#ifndef GL_APPLE_rgb_422
+#define GL_APPLE_rgb_422 1
+#endif
+
+/* GL_APPLE_sync */
+#ifndef GL_APPLE_sync
+#define GL_APPLE_sync 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+#endif
+
+/* GL_APPLE_texture_format_BGRA8888 */
+#ifndef GL_APPLE_texture_format_BGRA8888
+#define GL_APPLE_texture_format_BGRA8888 1
+#endif
+
+/* GL_APPLE_texture_max_level */
+#ifndef GL_APPLE_texture_max_level
+#define GL_APPLE_texture_max_level 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * ARM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_ARM_mali_program_binary */
+#ifndef GL_ARM_mali_program_binary
+#define GL_ARM_mali_program_binary 1
+#endif
+
+/* GL_ARM_mali_shader_binary */
+#ifndef GL_ARM_mali_shader_binary
+#define GL_ARM_mali_shader_binary 1
+#endif
+
+/* GL_ARM_rgba8 */
+#ifndef GL_ARM_rgba8
+#define GL_ARM_rgba8 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * EXT extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_EXT_blend_minmax 1
+#endif
+
+/* GL_EXT_color_buffer_half_float */
+#ifndef GL_EXT_color_buffer_half_float
+#define GL_EXT_color_buffer_half_float 1
+#endif
+
+/* GL_EXT_debug_label */
+#ifndef GL_EXT_debug_label
+#define GL_EXT_debug_label 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
+#endif
+
+/* GL_EXT_debug_marker */
+#ifndef GL_EXT_debug_marker
+#define GL_EXT_debug_marker 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker);
+GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void);
+#endif
+typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
+typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void);
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_EXT_discard_framebuffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+#endif
+
+#ifndef GL_EXT_disjoint_timer_query
+#define GL_EXT_disjoint_timer_query 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target);
+GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params);
+#endif
+typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params);
+#endif /* GL_EXT_disjoint_timer_query */
+
+#ifndef GL_EXT_draw_buffers
+#define GL_EXT_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs);
+#endif /* GL_EXT_draw_buffers */
+
+/* GL_EXT_map_buffer_range */
+#ifndef GL_EXT_map_buffer_range
+#define GL_EXT_map_buffer_range 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+#endif
+
+/* GL_EXT_multisampled_render_to_texture */
+#ifndef GL_EXT_multisampled_render_to_texture
+#define GL_EXT_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/* GL_EXT_multiview_draw_buffers */
+#ifndef GL_EXT_multiview_draw_buffers
+#define GL_EXT_multiview_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index);
+GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices);
+GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data);
+#endif
+
+#ifndef GL_EXT_multi_draw_arrays
+#define GL_EXT_multi_draw_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+#endif /* GL_GLEXT_PROTOTYPES */
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
+#endif
+
+/* GL_EXT_occlusion_query_boolean */
+#ifndef GL_EXT_occlusion_query_boolean
+#define GL_EXT_occlusion_query_boolean 1
+/* All entry points also exist in GL_EXT_disjoint_timer_query */
+#endif
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_EXT_read_format_bgra 1
+#endif
+
+/* GL_EXT_robustness */
+#ifndef GL_EXT_robustness
+#define GL_EXT_robustness 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+#endif
+
+/* GL_EXT_separate_shader_objects */
+#ifndef GL_EXT_separate_shader_objects
+#define GL_EXT_separate_shader_objects 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint x);
+GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint x, GLint y);
+GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z);
+GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat x);
+GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint x, GLint y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+#endif
+
+/* GL_EXT_shader_framebuffer_fetch */
+#ifndef GL_EXT_shader_framebuffer_fetch
+#define GL_EXT_shader_framebuffer_fetch 1
+#endif
+
+/* GL_EXT_shader_texture_lod */
+#ifndef GL_EXT_shader_texture_lod
+#define GL_EXT_shader_texture_lod 1
+#endif
+
+/* GL_EXT_shadow_samplers */
+#ifndef GL_EXT_shadow_samplers
+#define GL_EXT_shadow_samplers 1
+#endif
+
+/* GL_EXT_sRGB */
+#ifndef GL_EXT_sRGB
+#define GL_EXT_sRGB 1
+#endif
+
+/* GL_EXT_texture_compression_dxt1 */
+#ifndef GL_EXT_texture_compression_dxt1
+#define GL_EXT_texture_compression_dxt1 1
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_EXT_texture_filter_anisotropic 1
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_EXT_texture_format_BGRA8888 1
+#endif
+
+/* GL_EXT_texture_rg */
+#ifndef GL_EXT_texture_rg
+#define GL_EXT_texture_rg 1
+#endif
+
+/* GL_EXT_texture_storage */
+#ifndef GL_EXT_texture_storage
+#define GL_EXT_texture_storage 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_EXT_texture_type_2_10_10_10_REV 1
+#endif
+
+/* GL_EXT_unpack_subimage */
+#ifndef GL_EXT_unpack_subimage
+#define GL_EXT_unpack_subimage 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * DMP extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_DMP_shader_binary */
+#ifndef GL_DMP_shader_binary
+#define GL_DMP_shader_binary 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * FJ extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_FJ_shader_binary_GCCSO */
+#ifndef GL_FJ_shader_binary_GCCSO
+#define GL_FJ_shader_binary_GCCSO 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * IMG extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_IMG_program_binary */
+#ifndef GL_IMG_program_binary
+#define GL_IMG_program_binary 1
+#endif
+
+/* GL_IMG_read_format */
+#ifndef GL_IMG_read_format
+#define GL_IMG_read_format 1
+#endif
+
+/* GL_IMG_shader_binary */
+#ifndef GL_IMG_shader_binary
+#define GL_IMG_shader_binary 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc */
+#ifndef GL_IMG_texture_compression_pvrtc
+#define GL_IMG_texture_compression_pvrtc 1
+#endif
+
+/* GL_IMG_texture_compression_pvrtc2 */
+#ifndef GL_IMG_texture_compression_pvrtc2
+#define GL_IMG_texture_compression_pvrtc2 1
+#endif
+
+/* GL_IMG_multisampled_render_to_texture */
+#ifndef GL_IMG_multisampled_render_to_texture
+#define GL_IMG_multisampled_render_to_texture 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+#endif
+
+/*------------------------------------------------------------------------*
+ * NV extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_NV_coverage_sample */
+#ifndef GL_NV_coverage_sample
+#define GL_NV_coverage_sample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask);
+GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation);
+#endif
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation);
+#endif
+
+/* GL_NV_depth_nonlinear */
+#ifndef GL_NV_depth_nonlinear
+#define GL_NV_depth_nonlinear 1
+#endif
+
+/* GL_NV_draw_buffers */
+#ifndef GL_NV_draw_buffers
+#define GL_NV_draw_buffers 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs);
+#endif
+
+/* GL_NV_draw_instanced */
+#ifndef GL_NV_draw_instanced
+#define GL_NV_draw_instanced 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
+#endif
+
+/* GL_NV_fbo_color_attachments */
+#ifndef GL_NV_fbo_color_attachments
+#define GL_NV_fbo_color_attachments 1
+#endif
+
+/* GL_NV_fence */
+#ifndef GL_NV_fence
+#define GL_NV_fence 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences);
+GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences);
+GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence);
+GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence);
+GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition);
+#endif
+typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences);
+typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences);
+typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence);
+typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence);
+typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition);
+#endif
+
+/* GL_NV_framebuffer_blit */
+#ifndef GL_NV_framebuffer_blit
+#define GL_NV_framebuffer_blit 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+#endif
+
+/* GL_NV_framebuffer_multisample */
+#ifndef GL_NV_framebuffer_multisample
+#define GL_NV_framebuffer_multisample 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+#endif
+
+/* GL_NV_generate_mipmap_sRGB */
+#ifndef GL_NV_generate_mipmap_sRGB
+#define GL_NV_generate_mipmap_sRGB 1
+#endif
+
+/* GL_NV_instanced_arrays */
+#ifndef GL_NV_instanced_arrays
+#define GL_NV_instanced_arrays 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor);
+#endif
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor);
+#endif
+
+/* GL_NV_read_buffer */
+#ifndef GL_NV_read_buffer
+#define GL_NV_read_buffer 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode);
+#endif
+typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode);
+#endif
+
+/* GL_NV_read_buffer_front */
+#ifndef GL_NV_read_buffer_front
+#define GL_NV_read_buffer_front 1
+#endif
+
+/* GL_NV_read_depth */
+#ifndef GL_NV_read_depth
+#define GL_NV_read_depth 1
+#endif
+
+/* GL_NV_read_depth_stencil */
+#ifndef GL_NV_read_depth_stencil
+#define GL_NV_read_depth_stencil 1
+#endif
+
+/* GL_NV_read_stencil */
+#ifndef GL_NV_read_stencil
+#define GL_NV_read_stencil 1
+#endif
+
+/* GL_NV_shadow_samplers_array */
+#ifndef GL_NV_shadow_samplers_array
+#define GL_NV_shadow_samplers_array 1
+#endif
+
+/* GL_NV_shadow_samplers_cube */
+#ifndef GL_NV_shadow_samplers_cube
+#define GL_NV_shadow_samplers_cube 1
+#endif
+
+/* GL_NV_sRGB_formats */
+#ifndef GL_NV_sRGB_formats
+#define GL_NV_sRGB_formats 1
+#endif
+
+/* GL_NV_texture_border_clamp */
+#ifndef GL_NV_texture_border_clamp
+#define GL_NV_texture_border_clamp 1
+#endif
+
+/* GL_NV_texture_compression_s3tc_update */
+#ifndef GL_NV_texture_compression_s3tc_update
+#define GL_NV_texture_compression_s3tc_update 1
+#endif
+
+/* GL_NV_texture_npot_2D_mipmap */
+#ifndef GL_NV_texture_npot_2D_mipmap
+#define GL_NV_texture_npot_2D_mipmap 1
+#endif
+
+/*------------------------------------------------------------------------*
+ * QCOM extension functions
+ *------------------------------------------------------------------------*/
+
+/* GL_QCOM_alpha_test */
+#ifndef GL_QCOM_alpha_test
+#define GL_QCOM_alpha_test 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref);
+#endif
+typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref);
+#endif
+
+/* GL_QCOM_binning_control */
+#ifndef GL_QCOM_binning_control
+#define GL_QCOM_binning_control 1
+#endif
+
+/* GL_QCOM_driver_control */
+#ifndef GL_QCOM_driver_control
+#define GL_QCOM_driver_control 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls);
+GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl);
+GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl);
+#endif
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls);
+typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString);
+typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl);
+#endif
+
+/* GL_QCOM_extended_get */
+#ifndef GL_QCOM_extended_get
+#define GL_QCOM_extended_get 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures);
+GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, GLvoid **params);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLvoid *texels);
+typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, GLvoid **params);
+#endif
+
+/* GL_QCOM_extended_get2 */
+#ifndef GL_QCOM_extended_get2
+#define GL_QCOM_extended_get2 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program);
+GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms);
+typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length);
+#endif
+
+/* GL_QCOM_perfmon_global_mode */
+#ifndef GL_QCOM_perfmon_global_mode
+#define GL_QCOM_perfmon_global_mode 1
+#endif
+
+/* GL_QCOM_writeonly_rendering */
+#ifndef GL_QCOM_writeonly_rendering
+#define GL_QCOM_writeonly_rendering 1
+#endif
+
+/* GL_QCOM_tiled_rendering */
+#ifndef GL_QCOM_tiled_rendering
+#define GL_QCOM_tiled_rendering 1
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask);
+#endif
+typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
+typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask);
+#endif
+
+/*------------------------------------------------------------------------*
+ * VIV extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_VIV_shader_binary */
+#ifndef GL_VIV_shader_binary
+#define GL_VIV_shader_binary 1
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gl2ext_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2platform.h b/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2platform.h
new file mode 100644
index 0000000..c325686
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengles2_gl2platform.h
@@ -0,0 +1,30 @@
+#ifndef __gl2platform_h_
+#define __gl2platform_h_
+
+/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */
+
+/*
+ * This document is licensed under the SGI Free Software B License Version
+ * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ .
+ */
+
+/* Platform-specific types and definitions for OpenGL ES 2.X gl2.h
+ *
+ * Adopters may modify khrplatform.h and this file to suit their platform.
+ * You are encouraged to submit all modifications to the Khronos group so that
+ * they can be included in future versions of this file. Please submit changes
+ * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla)
+ * by filing a bug against product "OpenGL-ES" component "Registry".
+ */
+
+/*#include <KHR/khrplatform.h>*/
+
+#ifndef GL_APICALL
+#define GL_APICALL KHRONOS_APICALL
+#endif
+
+#ifndef GL_APIENTRY
+#define GL_APIENTRY KHRONOS_APIENTRY
+#endif
+
+#endif /* __gl2platform_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_opengles2_khrplatform.h b/Client/ThirdParty/SDL2/include/SDL_opengles2_khrplatform.h
new file mode 100644
index 0000000..c9e6f17
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_opengles2_khrplatform.h
@@ -0,0 +1,282 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2009 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * $Revision: 23298 $ on $Date: 2013-09-30 17:07:13 -0700 (Mon, 30 Sep 2013) $
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by sending them to the public Khronos Bugzilla
+ * (http://khronos.org/bugzilla) by filing a bug against product
+ * "Khronos (general)" component "Registry".
+ *
+ * A predefined template which fills in some of the bug fields can be
+ * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
+ * must create a Bugzilla login first.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_pixels.h b/Client/ThirdParty/SDL2/include/SDL_pixels.h
new file mode 100644
index 0000000..a6d464c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_pixels.h
@@ -0,0 +1,613 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_pixels.h
+ *
+ * Header for the enumerated pixel format definitions.
+ */
+
+#ifndef SDL_pixels_h_
+#define SDL_pixels_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_endian.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Transparency definitions
+ *
+ * These define alpha as the opacity of a surface.
+ */
+/* @{ */
+#define SDL_ALPHA_OPAQUE 255
+#define SDL_ALPHA_TRANSPARENT 0
+/* @} */
+
+/** Pixel type. */
+typedef enum
+{
+ SDL_PIXELTYPE_UNKNOWN,
+ SDL_PIXELTYPE_INDEX1,
+ SDL_PIXELTYPE_INDEX4,
+ SDL_PIXELTYPE_INDEX8,
+ SDL_PIXELTYPE_PACKED8,
+ SDL_PIXELTYPE_PACKED16,
+ SDL_PIXELTYPE_PACKED32,
+ SDL_PIXELTYPE_ARRAYU8,
+ SDL_PIXELTYPE_ARRAYU16,
+ SDL_PIXELTYPE_ARRAYU32,
+ SDL_PIXELTYPE_ARRAYF16,
+ SDL_PIXELTYPE_ARRAYF32
+} SDL_PixelType;
+
+/** Bitmap pixel order, high bit -> low bit. */
+typedef enum
+{
+ SDL_BITMAPORDER_NONE,
+ SDL_BITMAPORDER_4321,
+ SDL_BITMAPORDER_1234
+} SDL_BitmapOrder;
+
+/** Packed component order, high bit -> low bit. */
+typedef enum
+{
+ SDL_PACKEDORDER_NONE,
+ SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDORDER_RGBX,
+ SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDORDER_BGRX,
+ SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDORDER_BGRA
+} SDL_PackedOrder;
+
+/** Array component order, low byte -> high byte. */
+/* !!! FIXME: in 2.1, make these not overlap differently with
+ !!! FIXME: SDL_PACKEDORDER_*, so we can simplify SDL_ISPIXELFORMAT_ALPHA */
+typedef enum
+{
+ SDL_ARRAYORDER_NONE,
+ SDL_ARRAYORDER_RGB,
+ SDL_ARRAYORDER_RGBA,
+ SDL_ARRAYORDER_ARGB,
+ SDL_ARRAYORDER_BGR,
+ SDL_ARRAYORDER_BGRA,
+ SDL_ARRAYORDER_ABGR
+} SDL_ArrayOrder;
+
+/** Packed component layout. */
+typedef enum
+{
+ SDL_PACKEDLAYOUT_NONE,
+ SDL_PACKEDLAYOUT_332,
+ SDL_PACKEDLAYOUT_4444,
+ SDL_PACKEDLAYOUT_1555,
+ SDL_PACKEDLAYOUT_5551,
+ SDL_PACKEDLAYOUT_565,
+ SDL_PACKEDLAYOUT_8888,
+ SDL_PACKEDLAYOUT_2101010,
+ SDL_PACKEDLAYOUT_1010102
+} SDL_PackedLayout;
+
+#define SDL_DEFINE_PIXELFOURCC(A, B, C, D) SDL_FOURCC(A, B, C, D)
+
+#define SDL_DEFINE_PIXELFORMAT(type, order, layout, bits, bytes) \
+ ((1 << 28) | ((type) << 24) | ((order) << 20) | ((layout) << 16) | \
+ ((bits) << 8) | ((bytes) << 0))
+
+#define SDL_PIXELFLAG(X) (((X) >> 28) & 0x0F)
+#define SDL_PIXELTYPE(X) (((X) >> 24) & 0x0F)
+#define SDL_PIXELORDER(X) (((X) >> 20) & 0x0F)
+#define SDL_PIXELLAYOUT(X) (((X) >> 16) & 0x0F)
+#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF)
+#define SDL_BYTESPERPIXEL(X) \
+ (SDL_ISPIXELFORMAT_FOURCC(X) ? \
+ ((((X) == SDL_PIXELFORMAT_YUY2) || \
+ ((X) == SDL_PIXELFORMAT_UYVY) || \
+ ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF))
+
+#define SDL_ISPIXELFORMAT_INDEXED(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
+
+#define SDL_ISPIXELFORMAT_PACKED(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED8) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED16) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32)))
+
+#define SDL_ISPIXELFORMAT_ARRAY(format) \
+ (!SDL_ISPIXELFORMAT_FOURCC(format) && \
+ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU8) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU16) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYU32) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF16) || \
+ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_ARRAYF32)))
+
+#define SDL_ISPIXELFORMAT_ALPHA(format) \
+ ((SDL_ISPIXELFORMAT_PACKED(format) && \
+ ((SDL_PIXELORDER(format) == SDL_PACKEDORDER_ARGB) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_RGBA) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \
+ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA))) || \
+ (SDL_ISPIXELFORMAT_ARRAY(format) && \
+ ((SDL_PIXELORDER(format) == SDL_ARRAYORDER_ARGB) || \
+ (SDL_PIXELORDER(format) == SDL_ARRAYORDER_RGBA) || \
+ (SDL_PIXELORDER(format) == SDL_ARRAYORDER_ABGR) || \
+ (SDL_PIXELORDER(format) == SDL_ARRAYORDER_BGRA))))
+
+/* The flag is set to 1 because 0x1? is not in the printable ASCII range */
+#define SDL_ISPIXELFORMAT_FOURCC(format) \
+ ((format) && (SDL_PIXELFLAG(format) != 1))
+
+/* Note: If you modify this list, update SDL_GetPixelFormatName() */
+typedef enum
+{
+ SDL_PIXELFORMAT_UNKNOWN,
+ SDL_PIXELFORMAT_INDEX1LSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_4321, 0,
+ 1, 0),
+ SDL_PIXELFORMAT_INDEX1MSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,
+ 1, 0),
+ SDL_PIXELFORMAT_INDEX4LSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,
+ 4, 0),
+ SDL_PIXELFORMAT_INDEX4MSB =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_1234, 0,
+ 4, 0),
+ SDL_PIXELFORMAT_INDEX8 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0, 8, 1),
+ SDL_PIXELFORMAT_RGB332 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_332, 8, 1),
+ SDL_PIXELFORMAT_XRGB4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_4444, 12, 2),
+ SDL_PIXELFORMAT_RGB444 = SDL_PIXELFORMAT_XRGB4444,
+ SDL_PIXELFORMAT_XBGR4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_4444, 12, 2),
+ SDL_PIXELFORMAT_BGR444 = SDL_PIXELFORMAT_XBGR4444,
+ SDL_PIXELFORMAT_XRGB1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_1555, 15, 2),
+ SDL_PIXELFORMAT_RGB555 = SDL_PIXELFORMAT_XRGB1555,
+ SDL_PIXELFORMAT_XBGR1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_1555, 15, 2),
+ SDL_PIXELFORMAT_BGR555 = SDL_PIXELFORMAT_XBGR1555,
+ SDL_PIXELFORMAT_ARGB4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_RGBA4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_ABGR4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_BGRA4444 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_4444, 16, 2),
+ SDL_PIXELFORMAT_ARGB1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_1555, 16, 2),
+ SDL_PIXELFORMAT_RGBA5551 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_5551, 16, 2),
+ SDL_PIXELFORMAT_ABGR1555 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_1555, 16, 2),
+ SDL_PIXELFORMAT_BGRA5551 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_5551, 16, 2),
+ SDL_PIXELFORMAT_RGB565 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_565, 16, 2),
+ SDL_PIXELFORMAT_BGR565 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_565, 16, 2),
+ SDL_PIXELFORMAT_RGB24 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0,
+ 24, 3),
+ SDL_PIXELFORMAT_BGR24 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0,
+ 24, 3),
+ SDL_PIXELFORMAT_XRGB8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_RGB888 = SDL_PIXELFORMAT_XRGB8888,
+ SDL_PIXELFORMAT_RGBX8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_XBGR8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_BGR888 = SDL_PIXELFORMAT_XBGR8888,
+ SDL_PIXELFORMAT_BGRX8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX,
+ SDL_PACKEDLAYOUT_8888, 24, 4),
+ SDL_PIXELFORMAT_ARGB8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_RGBA8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBA,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_ABGR8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_BGRA8888 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA,
+ SDL_PACKEDLAYOUT_8888, 32, 4),
+ SDL_PIXELFORMAT_ARGB2101010 =
+ SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
+ SDL_PACKEDLAYOUT_2101010, 32, 4),
+
+ /* Aliases for RGBA byte arrays of color data, for the current platform */
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888,
+ SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888,
+ SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888,
+#else
+ SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888,
+ SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888,
+ SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888,
+#endif
+
+ SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */
+ SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
+ SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */
+ SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'),
+ SDL_PIXELFORMAT_YUY2 = /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
+ SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'),
+ SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
+ SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
+ SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
+ SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'),
+ SDL_PIXELFORMAT_NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */
+ SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'),
+ SDL_PIXELFORMAT_NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */
+ SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'),
+ SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */
+ SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ')
+} SDL_PixelFormatEnum;
+
+typedef struct SDL_Color
+{
+ Uint8 r;
+ Uint8 g;
+ Uint8 b;
+ Uint8 a;
+} SDL_Color;
+#define SDL_Colour SDL_Color
+
+typedef struct SDL_Palette
+{
+ int ncolors;
+ SDL_Color *colors;
+ Uint32 version;
+ int refcount;
+} SDL_Palette;
+
+/**
+ * \note Everything in the pixel format structure is read-only.
+ */
+typedef struct SDL_PixelFormat
+{
+ Uint32 format;
+ SDL_Palette *palette;
+ Uint8 BitsPerPixel;
+ Uint8 BytesPerPixel;
+ Uint8 padding[2];
+ Uint32 Rmask;
+ Uint32 Gmask;
+ Uint32 Bmask;
+ Uint32 Amask;
+ Uint8 Rloss;
+ Uint8 Gloss;
+ Uint8 Bloss;
+ Uint8 Aloss;
+ Uint8 Rshift;
+ Uint8 Gshift;
+ Uint8 Bshift;
+ Uint8 Ashift;
+ int refcount;
+ struct SDL_PixelFormat *next;
+} SDL_PixelFormat;
+
+/**
+ * Get the human readable name of a pixel format.
+ *
+ * \param format the pixel format to query
+ * \returns the human readable name of the specified pixel format or
+ * `SDL_PIXELFORMAT_UNKNOWN` if the format isn't recognized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(Uint32 format);
+
+/**
+ * Convert one of the enumerated pixel formats to a bpp value and RGBA masks.
+ *
+ * \param format one of the SDL_PixelFormatEnum values
+ * \param bpp a bits per pixel value; usually 15, 16, or 32
+ * \param Rmask a pointer filled in with the red mask for the format
+ * \param Gmask a pointer filled in with the green mask for the format
+ * \param Bmask a pointer filled in with the blue mask for the format
+ * \param Amask a pointer filled in with the alpha mask for the format
+ * \returns SDL_TRUE on success or SDL_FALSE if the conversion wasn't
+ * possible; call SDL_GetError() for more information.
+ *
+ * \sa SDL_MasksToPixelFormatEnum
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_PixelFormatEnumToMasks(Uint32 format,
+ int *bpp,
+ Uint32 * Rmask,
+ Uint32 * Gmask,
+ Uint32 * Bmask,
+ Uint32 * Amask);
+
+/**
+ * Convert a bpp value and RGBA masks to an enumerated pixel format.
+ *
+ * This will return `SDL_PIXELFORMAT_UNKNOWN` if the conversion wasn't
+ * possible.
+ *
+ * \param bpp a bits per pixel value; usually 15, 16, or 32
+ * \param Rmask the red mask for the format
+ * \param Gmask the green mask for the format
+ * \param Bmask the blue mask for the format
+ * \param Amask the alpha mask for the format
+ * \returns one of the SDL_PixelFormatEnum values
+ *
+ * \sa SDL_PixelFormatEnumToMasks
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MasksToPixelFormatEnum(int bpp,
+ Uint32 Rmask,
+ Uint32 Gmask,
+ Uint32 Bmask,
+ Uint32 Amask);
+
+/**
+ * Create an SDL_PixelFormat structure corresponding to a pixel format.
+ *
+ * Returned structure may come from a shared global cache (i.e. not newly
+ * allocated), and hence should not be modified, especially the palette. Weird
+ * errors such as `Blit combination not supported` may occur.
+ *
+ * \param pixel_format one of the SDL_PixelFormatEnum values
+ * \returns the new SDL_PixelFormat structure or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_FreeFormat
+ */
+extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_AllocFormat(Uint32 pixel_format);
+
+/**
+ * Free an SDL_PixelFormat structure allocated by SDL_AllocFormat().
+ *
+ * \param format the SDL_PixelFormat structure to free
+ *
+ * \sa SDL_AllocFormat
+ */
+extern DECLSPEC void SDLCALL SDL_FreeFormat(SDL_PixelFormat *format);
+
+/**
+ * Create a palette structure with the specified number of color entries.
+ *
+ * The palette entries are initialized to white.
+ *
+ * \param ncolors represents the number of color entries in the color palette
+ * \returns a new SDL_Palette structure on success or NULL on failure (e.g. if
+ * there wasn't enough memory); call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_FreePalette
+ */
+extern DECLSPEC SDL_Palette *SDLCALL SDL_AllocPalette(int ncolors);
+
+/**
+ * Set the palette for a pixel format structure.
+ *
+ * \param format the SDL_PixelFormat structure that will use the palette
+ * \param palette the SDL_Palette structure that will be used
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocPalette
+ * \sa SDL_FreePalette
+ */
+extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format,
+ SDL_Palette *palette);
+
+/**
+ * Set a range of colors in a palette.
+ *
+ * \param palette the SDL_Palette structure to modify
+ * \param colors an array of SDL_Color structures to copy into the palette
+ * \param firstcolor the index of the first palette entry to modify
+ * \param ncolors the number of entries to modify
+ * \returns 0 on success or a negative error code if not all of the colors
+ * could be set; call SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocPalette
+ * \sa SDL_CreateRGBSurface
+ */
+extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette,
+ const SDL_Color * colors,
+ int firstcolor, int ncolors);
+
+/**
+ * Free a palette created with SDL_AllocPalette().
+ *
+ * \param palette the SDL_Palette structure to be freed
+ *
+ * \sa SDL_AllocPalette
+ */
+extern DECLSPEC void SDLCALL SDL_FreePalette(SDL_Palette * palette);
+
+/**
+ * Map an RGB triple to an opaque pixel value for a given pixel format.
+ *
+ * This function maps the RGB color value to the specified pixel format and
+ * returns the pixel value best approximating the given RGB color value for
+ * the given pixel format.
+ *
+ * If the format has a palette (8-bit) the index of the closest matching color
+ * in the palette will be returned.
+ *
+ * If the specified pixel format has an alpha component it will be returned as
+ * all 1 bits (fully opaque).
+ *
+ * If the pixel format bpp (color depth) is less than 32-bpp then the unused
+ * upper bits of the return value can safely be ignored (e.g., with a 16-bpp
+ * format the return value can be assigned to a Uint16, and similarly a Uint8
+ * for an 8-bpp format).
+ *
+ * \param format an SDL_PixelFormat structure describing the pixel format
+ * \param r the red component of the pixel in the range 0-255
+ * \param g the green component of the pixel in the range 0-255
+ * \param b the blue component of the pixel in the range 0-255
+ * \returns a pixel value
+ *
+ * \sa SDL_GetRGB
+ * \sa SDL_GetRGBA
+ * \sa SDL_MapRGBA
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format,
+ Uint8 r, Uint8 g, Uint8 b);
+
+/**
+ * Map an RGBA quadruple to a pixel value for a given pixel format.
+ *
+ * This function maps the RGBA color value to the specified pixel format and
+ * returns the pixel value best approximating the given RGBA color value for
+ * the given pixel format.
+ *
+ * If the specified pixel format has no alpha component the alpha value will
+ * be ignored (as it will be in formats with a palette).
+ *
+ * If the format has a palette (8-bit) the index of the closest matching color
+ * in the palette will be returned.
+ *
+ * If the pixel format bpp (color depth) is less than 32-bpp then the unused
+ * upper bits of the return value can safely be ignored (e.g., with a 16-bpp
+ * format the return value can be assigned to a Uint16, and similarly a Uint8
+ * for an 8-bpp format).
+ *
+ * \param format an SDL_PixelFormat structure describing the format of the
+ * pixel
+ * \param r the red component of the pixel in the range 0-255
+ * \param g the green component of the pixel in the range 0-255
+ * \param b the blue component of the pixel in the range 0-255
+ * \param a the alpha component of the pixel in the range 0-255
+ * \returns a pixel value
+ *
+ * \sa SDL_GetRGB
+ * \sa SDL_GetRGBA
+ * \sa SDL_MapRGB
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format,
+ Uint8 r, Uint8 g, Uint8 b,
+ Uint8 a);
+
+/**
+ * Get RGB values from a pixel in the specified format.
+ *
+ * This function uses the entire 8-bit [0..255] range when converting color
+ * components from pixel formats with less than 8-bits per RGB component
+ * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff,
+ * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]).
+ *
+ * \param pixel a pixel value
+ * \param format an SDL_PixelFormat structure describing the format of the
+ * pixel
+ * \param r a pointer filled in with the red component
+ * \param g a pointer filled in with the green component
+ * \param b a pointer filled in with the blue component
+ *
+ * \sa SDL_GetRGBA
+ * \sa SDL_MapRGB
+ * \sa SDL_MapRGBA
+ */
+extern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel,
+ const SDL_PixelFormat * format,
+ Uint8 * r, Uint8 * g, Uint8 * b);
+
+/**
+ * Get RGBA values from a pixel in the specified format.
+ *
+ * This function uses the entire 8-bit [0..255] range when converting color
+ * components from pixel formats with less than 8-bits per RGB component
+ * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff,
+ * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]).
+ *
+ * If the surface has no alpha component, the alpha will be returned as 0xff
+ * (100% opaque).
+ *
+ * \param pixel a pixel value
+ * \param format an SDL_PixelFormat structure describing the format of the
+ * pixel
+ * \param r a pointer filled in with the red component
+ * \param g a pointer filled in with the green component
+ * \param b a pointer filled in with the blue component
+ * \param a a pointer filled in with the alpha component
+ *
+ * \sa SDL_GetRGB
+ * \sa SDL_MapRGB
+ * \sa SDL_MapRGBA
+ */
+extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel,
+ const SDL_PixelFormat * format,
+ Uint8 * r, Uint8 * g, Uint8 * b,
+ Uint8 * a);
+
+/**
+ * Calculate a 256 entry gamma ramp for a gamma value.
+ *
+ * \param gamma a gamma value where 0.0 is black and 1.0 is identity
+ * \param ramp an array of 256 values filled in with the gamma ramp
+ *
+ * \sa SDL_SetWindowGammaRamp
+ */
+extern DECLSPEC void SDLCALL SDL_CalculateGammaRamp(float gamma, Uint16 * ramp);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_pixels_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_platform.h b/Client/ThirdParty/SDL2/include/SDL_platform.h
new file mode 100644
index 0000000..1516da3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_platform.h
@@ -0,0 +1,233 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_platform.h
+ *
+ * Try to get a standard set of platform defines.
+ */
+
+#ifndef SDL_platform_h_
+#define SDL_platform_h_
+
+#if defined(_AIX)
+#undef __AIX__
+#define __AIX__ 1
+#endif
+#if defined(__HAIKU__)
+#undef __HAIKU__
+#define __HAIKU__ 1
+#endif
+#if defined(bsdi) || defined(__bsdi) || defined(__bsdi__)
+#undef __BSDI__
+#define __BSDI__ 1
+#endif
+#if defined(_arch_dreamcast)
+#undef __DREAMCAST__
+#define __DREAMCAST__ 1
+#endif
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#undef __FREEBSD__
+#define __FREEBSD__ 1
+#endif
+#if defined(hpux) || defined(__hpux) || defined(__hpux__)
+#undef __HPUX__
+#define __HPUX__ 1
+#endif
+#if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE)
+#undef __IRIX__
+#define __IRIX__ 1
+#endif
+#if (defined(linux) || defined(__linux) || defined(__linux__))
+#undef __LINUX__
+#define __LINUX__ 1
+#endif
+#if defined(ANDROID) || defined(__ANDROID__)
+#undef __ANDROID__
+#undef __LINUX__ /* do we need to do this? */
+#define __ANDROID__ 1
+#endif
+
+#if defined(__APPLE__)
+/* lets us know what version of Mac OS X we're compiling on */
+#include "AvailabilityMacros.h"
+#include "TargetConditionals.h"
+
+/* Fix building with older SDKs that don't define these
+ See this for more information:
+ https://stackoverflow.com/questions/12132933/preprocessor-macro-for-os-x-targets
+*/
+#ifndef TARGET_OS_MACCATALYST
+#define TARGET_OS_MACCATALYST 0
+#endif
+#ifndef TARGET_OS_IOS
+#define TARGET_OS_IOS 0
+#endif
+#ifndef TARGET_OS_IPHONE
+#define TARGET_OS_IPHONE 0
+#endif
+#ifndef TARGET_OS_TV
+#define TARGET_OS_TV 0
+#endif
+#ifndef TARGET_OS_SIMULATOR
+#define TARGET_OS_SIMULATOR 0
+#endif
+
+#if TARGET_OS_TV
+#undef __TVOS__
+#define __TVOS__ 1
+#endif
+#if TARGET_OS_IPHONE
+/* if compiling for iOS */
+#undef __IPHONEOS__
+#define __IPHONEOS__ 1
+#undef __MACOSX__
+#else
+/* if not compiling for iOS */
+#undef __MACOSX__
+#define __MACOSX__ 1
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+# error SDL for Mac OS X only supports deploying on 10.6 and above.
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
+#endif /* TARGET_OS_IPHONE */
+#endif /* defined(__APPLE__) */
+
+#if defined(__NetBSD__)
+#undef __NETBSD__
+#define __NETBSD__ 1
+#endif
+#if defined(__OpenBSD__)
+#undef __OPENBSD__
+#define __OPENBSD__ 1
+#endif
+#if defined(__OS2__) || defined(__EMX__)
+#undef __OS2__
+#define __OS2__ 1
+#endif
+#if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE)
+#undef __OSF__
+#define __OSF__ 1
+#endif
+#if defined(__QNXNTO__)
+#undef __QNXNTO__
+#define __QNXNTO__ 1
+#endif
+#if defined(riscos) || defined(__riscos) || defined(__riscos__)
+#undef __RISCOS__
+#define __RISCOS__ 1
+#endif
+#if defined(__sun) && defined(__SVR4)
+#undef __SOLARIS__
+#define __SOLARIS__ 1
+#endif
+
+#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+/* Try to find out if we're compiling for WinRT or non-WinRT */
+#if defined(_MSC_VER) && defined(__has_include)
+#if __has_include(<winapifamily.h>)
+#define HAVE_WINAPIFAMILY_H 1
+#else
+#define HAVE_WINAPIFAMILY_H 0
+#endif
+
+/* If _USING_V110_SDK71_ is defined it means we are using the Windows XP toolset. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1700 && !_USING_V110_SDK71_) /* _MSC_VER == 1700 for Visual Studio 2012 */
+#define HAVE_WINAPIFAMILY_H 1
+#else
+#define HAVE_WINAPIFAMILY_H 0
+#endif
+
+#if HAVE_WINAPIFAMILY_H
+#include <winapifamily.h>
+#define WINAPI_FAMILY_WINRT (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP))
+#else
+#define WINAPI_FAMILY_WINRT 0
+#endif /* HAVE_WINAPIFAMILY_H */
+
+#if WINAPI_FAMILY_WINRT
+#undef __WINRT__
+#define __WINRT__ 1
+#else
+#undef __WINDOWS__
+#define __WINDOWS__ 1
+#endif
+#endif /* defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) */
+
+#if defined(__WINDOWS__)
+#undef __WIN32__
+#define __WIN32__ 1
+#endif
+#if defined(__PSP__)
+#undef __PSP__
+#define __PSP__ 1
+#endif
+
+/* The NACL compiler defines __native_client__ and __pnacl__
+ * Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi
+ */
+#if defined(__native_client__)
+#undef __LINUX__
+#undef __NACL__
+#define __NACL__ 1
+#endif
+#if defined(__pnacl__)
+#undef __LINUX__
+#undef __PNACL__
+#define __PNACL__ 1
+/* PNACL with newlib supports static linking only */
+#define __SDL_NOGETPROCADDR__
+#endif
+
+#if defined(__vita__)
+#define __VITA__ 1
+#endif
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the name of the platform.
+ *
+ * Here are the names returned for some (but not all) supported platforms:
+ *
+ * - "Windows"
+ * - "Mac OS X"
+ * - "Linux"
+ * - "iOS"
+ * - "Android"
+ *
+ * \returns the name of the platform. If the correct platform name is not
+ * available, returns a string beginning with the text "Unknown".
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetPlatform (void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_platform_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_power.h b/Client/ThirdParty/SDL2/include/SDL_power.h
new file mode 100644
index 0000000..872be18
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_power.h
@@ -0,0 +1,86 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_power_h_
+#define SDL_power_h_
+
+/**
+ * \file SDL_power.h
+ *
+ * Header for the SDL power management routines.
+ */
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The basic state for the system's power supply.
+ */
+typedef enum
+{
+ SDL_POWERSTATE_UNKNOWN, /**< cannot determine power status */
+ SDL_POWERSTATE_ON_BATTERY, /**< Not plugged in, running on the battery */
+ SDL_POWERSTATE_NO_BATTERY, /**< Plugged in, no battery available */
+ SDL_POWERSTATE_CHARGING, /**< Plugged in, charging battery */
+ SDL_POWERSTATE_CHARGED /**< Plugged in, battery charged */
+} SDL_PowerState;
+
+
+/**
+ * Get the current power supply details.
+ *
+ * You should never take a battery status as absolute truth. Batteries
+ * (especially failing batteries) are delicate hardware, and the values
+ * reported here are best estimates based on what that hardware reports. It's
+ * not uncommon for older batteries to lose stored power much faster than it
+ * reports, or completely drain when reporting it has 20 percent left, etc.
+ *
+ * Battery status can change at any time; if you are concerned with power
+ * state, you should call this function frequently, and perhaps ignore changes
+ * until they seem to be stable for a few seconds.
+ *
+ * It's possible a platform can only report battery percentage or time left
+ * but not both.
+ *
+ * \param secs seconds of battery life left, you can pass a NULL here if you
+ * don't care, will return -1 if we can't determine a value, or
+ * we're not running on a battery
+ * \param pct percentage of battery life left, between 0 and 100, you can pass
+ * a NULL here if you don't care, will return -1 if we can't
+ * determine a value, or we're not running on a battery
+ * \returns an SDL_PowerState enum representing the current battery state.
+ */
+extern DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *secs, int *pct);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_power_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_quit.h b/Client/ThirdParty/SDL2/include/SDL_quit.h
new file mode 100644
index 0000000..2825050
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_quit.h
@@ -0,0 +1,58 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_quit.h
+ *
+ * Include file for SDL quit event handling.
+ */
+
+#ifndef SDL_quit_h_
+#define SDL_quit_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+/**
+ * \file SDL_quit.h
+ *
+ * An ::SDL_QUIT event is generated when the user tries to close the application
+ * window. If it is ignored or filtered out, the window will remain open.
+ * If it is not ignored or filtered, it is queued normally and the window
+ * is allowed to close. When the window is closed, screen updates will
+ * complete, but have no effect.
+ *
+ * SDL_Init() installs signal handlers for SIGINT (keyboard interrupt)
+ * and SIGTERM (system termination request), if handlers do not already
+ * exist, that generate ::SDL_QUIT events as well. There is no way
+ * to determine the cause of an ::SDL_QUIT event, but setting a signal
+ * handler in your application will override the default generation of
+ * quit events for that signal.
+ *
+ * \sa SDL_Quit()
+ */
+
+/* There are no functions directly affecting the quit event */
+
+#define SDL_QuitRequested() \
+ (SDL_PumpEvents(), (SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_QUIT,SDL_QUIT) > 0))
+
+#endif /* SDL_quit_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_rect.h b/Client/ThirdParty/SDL2/include/SDL_rect.h
new file mode 100644
index 0000000..a17ea44
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_rect.h
@@ -0,0 +1,218 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_rect.h
+ *
+ * Header file for SDL_rect definition and management functions.
+ */
+
+#ifndef SDL_rect_h_
+#define SDL_rect_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_pixels.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The structure that defines a point (integer)
+ *
+ * \sa SDL_EnclosePoints
+ * \sa SDL_PointInRect
+ */
+typedef struct SDL_Point
+{
+ int x;
+ int y;
+} SDL_Point;
+
+/**
+ * The structure that defines a point (floating point)
+ *
+ * \sa SDL_EnclosePoints
+ * \sa SDL_PointInRect
+ */
+typedef struct SDL_FPoint
+{
+ float x;
+ float y;
+} SDL_FPoint;
+
+
+/**
+ * A rectangle, with the origin at the upper left (integer).
+ *
+ * \sa SDL_RectEmpty
+ * \sa SDL_RectEquals
+ * \sa SDL_HasIntersection
+ * \sa SDL_IntersectRect
+ * \sa SDL_UnionRect
+ * \sa SDL_EnclosePoints
+ */
+typedef struct SDL_Rect
+{
+ int x, y;
+ int w, h;
+} SDL_Rect;
+
+
+/**
+ * A rectangle, with the origin at the upper left (floating point).
+ */
+typedef struct SDL_FRect
+{
+ float x;
+ float y;
+ float w;
+ float h;
+} SDL_FRect;
+
+
+/**
+ * Returns true if point resides inside a rectangle.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r)
+{
+ return ( (p->x >= r->x) && (p->x < (r->x + r->w)) &&
+ (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Returns true if the rectangle has no area.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
+{
+ return ((!r) || (r->w <= 0) || (r->h <= 0)) ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Returns true if the two rectangles are equal.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_RectEquals(const SDL_Rect *a, const SDL_Rect *b)
+{
+ return (a && b && (a->x == b->x) && (a->y == b->y) &&
+ (a->w == b->w) && (a->h == b->h)) ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Determine whether two rectangles intersect.
+ *
+ * If either pointer is NULL the function will return SDL_FALSE.
+ *
+ * \param A an SDL_Rect structure representing the first rectangle
+ * \param B an SDL_Rect structure representing the second rectangle
+ * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_IntersectRect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasIntersection(const SDL_Rect * A,
+ const SDL_Rect * B);
+
+/**
+ * Calculate the intersection of two rectangles.
+ *
+ * If `result` is NULL then this function will return SDL_FALSE.
+ *
+ * \param A an SDL_Rect structure representing the first rectangle
+ * \param B an SDL_Rect structure representing the second rectangle
+ * \param result an SDL_Rect structure filled in with the intersection of
+ * rectangles `A` and `B`
+ * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasIntersection
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect * A,
+ const SDL_Rect * B,
+ SDL_Rect * result);
+
+/**
+ * Calculate the union of two rectangles.
+ *
+ * \param A an SDL_Rect structure representing the first rectangle
+ * \param B an SDL_Rect structure representing the second rectangle
+ * \param result an SDL_Rect structure filled in with the union of rectangles
+ * `A` and `B`
+ */
+extern DECLSPEC void SDLCALL SDL_UnionRect(const SDL_Rect * A,
+ const SDL_Rect * B,
+ SDL_Rect * result);
+
+/**
+ * Calculate a minimal rectangle enclosing a set of points.
+ *
+ * If `clip` is not NULL then only points inside of the clipping rectangle are
+ * considered.
+ *
+ * \param points an array of SDL_Point structures representing points to be
+ * enclosed
+ * \param count the number of structures in the `points` array
+ * \param clip an SDL_Rect used for clipping or NULL to enclose all points
+ * \param result an SDL_Rect structure filled in with the minimal enclosing
+ * rectangle
+ * \returns SDL_TRUE if any points were enclosed or SDL_FALSE if all the
+ * points were outside of the clipping rectangle.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_EnclosePoints(const SDL_Point * points,
+ int count,
+ const SDL_Rect * clip,
+ SDL_Rect * result);
+
+/**
+ * Calculate the intersection of a rectangle and line segment.
+ *
+ * This function is used to clip a line segment to a rectangle. A line segment
+ * contained entirely within the rectangle or that does not intersect will
+ * remain unchanged. A line segment that crosses the rectangle at either or
+ * both ends will be clipped to the boundary of the rectangle and the new
+ * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary.
+ *
+ * \param rect an SDL_Rect structure representing the rectangle to intersect
+ * \param X1 a pointer to the starting X-coordinate of the line
+ * \param Y1 a pointer to the starting Y-coordinate of the line
+ * \param X2 a pointer to the ending X-coordinate of the line
+ * \param Y2 a pointer to the ending Y-coordinate of the line
+ * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRectAndLine(const SDL_Rect *
+ rect, int *X1,
+ int *Y1, int *X2,
+ int *Y2);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_rect_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_render.h b/Client/ThirdParty/SDL2/include/SDL_render.h
new file mode 100644
index 0000000..d80f4d3
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_render.h
@@ -0,0 +1,1625 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_render.h
+ *
+ * Header file for SDL 2D rendering functions.
+ *
+ * This API supports the following features:
+ * * single pixel points
+ * * single pixel lines
+ * * filled rectangles
+ * * texture images
+ *
+ * The primitives may be drawn in opaque, blended, or additive modes.
+ *
+ * The texture images may be drawn in opaque, blended, or additive modes.
+ * They can have an additional color tint or alpha modulation applied to
+ * them, and may also be stretched with linear interpolation.
+ *
+ * This API is designed to accelerate simple 2D operations. You may
+ * want more functionality such as polygons and particle effects and
+ * in that case you should use SDL's OpenGL/Direct3D support or one
+ * of the many good 3D engines.
+ *
+ * These functions must be called from the main thread.
+ * See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995
+ */
+
+#ifndef SDL_render_h_
+#define SDL_render_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_rect.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Flags used when creating a rendering context
+ */
+typedef enum
+{
+ SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */
+ SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware
+ acceleration */
+ SDL_RENDERER_PRESENTVSYNC = 0x00000004, /**< Present is synchronized
+ with the refresh rate */
+ SDL_RENDERER_TARGETTEXTURE = 0x00000008 /**< The renderer supports
+ rendering to texture */
+} SDL_RendererFlags;
+
+/**
+ * Information on the capabilities of a render driver or context.
+ */
+typedef struct SDL_RendererInfo
+{
+ const char *name; /**< The name of the renderer */
+ Uint32 flags; /**< Supported ::SDL_RendererFlags */
+ Uint32 num_texture_formats; /**< The number of available texture formats */
+ Uint32 texture_formats[16]; /**< The available texture formats */
+ int max_texture_width; /**< The maximum texture width */
+ int max_texture_height; /**< The maximum texture height */
+} SDL_RendererInfo;
+
+/**
+ * The scaling mode for a texture.
+ */
+typedef enum
+{
+ SDL_ScaleModeNearest, /**< nearest pixel sampling */
+ SDL_ScaleModeLinear, /**< linear filtering */
+ SDL_ScaleModeBest /**< anisotropic filtering */
+} SDL_ScaleMode;
+
+/**
+ * The access pattern allowed for a texture.
+ */
+typedef enum
+{
+ SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */
+ SDL_TEXTUREACCESS_STREAMING, /**< Changes frequently, lockable */
+ SDL_TEXTUREACCESS_TARGET /**< Texture can be used as a render target */
+} SDL_TextureAccess;
+
+/**
+ * The texture channel modulation used in SDL_RenderCopy().
+ */
+typedef enum
+{
+ SDL_TEXTUREMODULATE_NONE = 0x00000000, /**< No modulation */
+ SDL_TEXTUREMODULATE_COLOR = 0x00000001, /**< srcC = srcC * color */
+ SDL_TEXTUREMODULATE_ALPHA = 0x00000002 /**< srcA = srcA * alpha */
+} SDL_TextureModulate;
+
+/**
+ * Flip constants for SDL_RenderCopyEx
+ */
+typedef enum
+{
+ SDL_FLIP_NONE = 0x00000000, /**< Do not flip */
+ SDL_FLIP_HORIZONTAL = 0x00000001, /**< flip horizontally */
+ SDL_FLIP_VERTICAL = 0x00000002 /**< flip vertically */
+} SDL_RendererFlip;
+
+/**
+ * A structure representing rendering state
+ */
+struct SDL_Renderer;
+typedef struct SDL_Renderer SDL_Renderer;
+
+/**
+ * An efficient driver-specific representation of pixel data
+ */
+struct SDL_Texture;
+typedef struct SDL_Texture SDL_Texture;
+
+
+/* Function prototypes */
+
+/**
+ * Get the number of 2D rendering drivers available for the current display.
+ *
+ * A render driver is a set of code that handles rendering and texture
+ * management on a particular display. Normally there is only one, but some
+ * drivers may have several available with different capabilities.
+ *
+ * There may be none if SDL was compiled without render support.
+ *
+ * \returns a number >= 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_GetRenderDriverInfo
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void);
+
+/**
+ * Get info about a specific 2D rendering driver for the current display.
+ *
+ * \param index the index of the driver to query information about
+ * \param info an SDL_RendererInfo structure to be filled with information on
+ * the rendering driver
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_GetNumRenderDrivers
+ */
+extern DECLSPEC int SDLCALL SDL_GetRenderDriverInfo(int index,
+ SDL_RendererInfo * info);
+
+/**
+ * Create a window and default renderer.
+ *
+ * \param width the width of the window
+ * \param height the height of the window
+ * \param window_flags the flags used to create the window (see
+ * SDL_CreateWindow())
+ * \param window a pointer filled with the window, or NULL on error
+ * \param renderer a pointer filled with the renderer, or NULL on error
+ * \returns 0 on success, or -1 on error; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_CreateWindow
+ */
+extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(
+ int width, int height, Uint32 window_flags,
+ SDL_Window **window, SDL_Renderer **renderer);
+
+
+/**
+ * Create a 2D rendering context for a window.
+ *
+ * \param window the window where rendering is displayed
+ * \param index the index of the rendering driver to initialize, or -1 to
+ * initialize the first one supporting the requested flags
+ * \param flags 0, or one or more SDL_RendererFlags OR'd together
+ * \returns a valid rendering context or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateSoftwareRenderer
+ * \sa SDL_DestroyRenderer
+ * \sa SDL_GetNumRenderDrivers
+ * \sa SDL_GetRendererInfo
+ */
+extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window * window,
+ int index, Uint32 flags);
+
+/**
+ * Create a 2D software rendering context for a surface.
+ *
+ * Two other API which can be used to create SDL_Renderer:
+ * SDL_CreateRenderer() and SDL_CreateWindowAndRenderer(). These can _also_
+ * create a software renderer, but they are intended to be used with an
+ * SDL_Window as the final destination and not an SDL_Surface.
+ *
+ * \param surface the SDL_Surface structure representing the surface where
+ * rendering is done
+ * \returns a valid rendering context or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ * \sa SDL_CreateWindowRenderer
+ * \sa SDL_DestroyRenderer
+ */
+extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface * surface);
+
+/**
+ * Get the renderer associated with a window.
+ *
+ * \param window the window to query
+ * \returns the rendering context on success or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ */
+extern DECLSPEC SDL_Renderer * SDLCALL SDL_GetRenderer(SDL_Window * window);
+
+/**
+ * Get information about a rendering context.
+ *
+ * \param renderer the rendering context
+ * \param info an SDL_RendererInfo structure filled with information about the
+ * current renderer
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRenderer
+ */
+extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer * renderer,
+ SDL_RendererInfo * info);
+
+/**
+ * Get the output size in pixels of a rendering context.
+ *
+ * Due to high-dpi displays, you might end up with a rendering context that
+ * has more pixels than the window that contains it, so use this instead of
+ * SDL_GetWindowSize() to decide how much drawing area you have.
+ *
+ * \param renderer the rendering context
+ * \param w an int filled with the width
+ * \param h an int filled with the height
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetRenderer
+ */
+extern DECLSPEC int SDLCALL SDL_GetRendererOutputSize(SDL_Renderer * renderer,
+ int *w, int *h);
+
+/**
+ * Create a texture for a rendering context.
+ *
+ * You can set the texture scaling method by setting
+ * `SDL_HINT_RENDER_SCALE_QUALITY` before creating the texture.
+ *
+ * \param renderer the rendering context
+ * \param format one of the enumerated values in SDL_PixelFormatEnum
+ * \param access one of the enumerated values in SDL_TextureAccess
+ * \param w the width of the texture in pixels
+ * \param h the height of the texture in pixels
+ * \returns a pointer to the created texture or NULL if no rendering context
+ * was active, the format was unsupported, or the width or height
+ * were out of range; call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateTextureFromSurface
+ * \sa SDL_DestroyTexture
+ * \sa SDL_QueryTexture
+ * \sa SDL_UpdateTexture
+ */
+extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,
+ Uint32 format,
+ int access, int w,
+ int h);
+
+/**
+ * Create a texture from an existing surface.
+ *
+ * The surface is not modified or freed by this function.
+ *
+ * The SDL_TextureAccess hint for the created texture is
+ * `SDL_TEXTUREACCESS_STATIC`.
+ *
+ * The pixel format of the created texture may be different from the pixel
+ * format of the surface. Use SDL_QueryTexture() to query the pixel format of
+ * the texture.
+ *
+ * \param renderer the rendering context
+ * \param surface the SDL_Surface structure containing pixel data used to fill
+ * the texture
+ * \returns the created texture or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_DestroyTexture
+ * \sa SDL_QueryTexture
+ */
+extern DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);
+
+/**
+ * Query the attributes of a texture.
+ *
+ * \param texture the texture to query
+ * \param format a pointer filled in with the raw format of the texture; the
+ * actual format may differ, but pixel transfers will use this
+ * format (one of the SDL_PixelFormatEnum values)
+ * \param access a pointer filled in with the actual access to the texture
+ * (one of the SDL_TextureAccess values)
+ * \param w a pointer filled in with the width of the texture in pixels
+ * \param h a pointer filled in with the height of the texture in pixels
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateTexture
+ */
+extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture * texture,
+ Uint32 * format, int *access,
+ int *w, int *h);
+
+/**
+ * Set an additional color value multiplied into render copy operations.
+ *
+ * When this texture is rendered, during the copy operation each source color
+ * channel is modulated by the appropriate color value according to the
+ * following formula:
+ *
+ * `srcC = srcC * (color / 255)`
+ *
+ * Color modulation is not always supported by the renderer; it will return -1
+ * if color modulation is not supported.
+ *
+ * \param texture the texture to update
+ * \param r the red color value multiplied into copy operations
+ * \param g the green color value multiplied into copy operations
+ * \param b the blue color value multiplied into copy operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureColorMod
+ * \sa SDL_SetTextureAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture * texture,
+ Uint8 r, Uint8 g, Uint8 b);
+
+
+/**
+ * Get the additional color value multiplied into render copy operations.
+ *
+ * \param texture the texture to query
+ * \param r a pointer filled in with the current red color value
+ * \param g a pointer filled in with the current green color value
+ * \param b a pointer filled in with the current blue color value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureAlphaMod
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureColorMod(SDL_Texture * texture,
+ Uint8 * r, Uint8 * g,
+ Uint8 * b);
+
+/**
+ * Set an additional alpha value multiplied into render copy operations.
+ *
+ * When this texture is rendered, during the copy operation the source alpha
+ * value is modulated by this alpha value according to the following formula:
+ *
+ * `srcA = srcA * (alpha / 255)`
+ *
+ * Alpha modulation is not always supported by the renderer; it will return -1
+ * if alpha modulation is not supported.
+ *
+ * \param texture the texture to update
+ * \param alpha the source alpha value multiplied into copy operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureAlphaMod
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture * texture,
+ Uint8 alpha);
+
+/**
+ * Get the additional alpha value multiplied into render copy operations.
+ *
+ * \param texture the texture to query
+ * \param alpha a pointer filled in with the current alpha value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureColorMod
+ * \sa SDL_SetTextureAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureAlphaMod(SDL_Texture * texture,
+ Uint8 * alpha);
+
+/**
+ * Set the blend mode for a texture, used by SDL_RenderCopy().
+ *
+ * If the blend mode is not supported, the closest supported mode is chosen
+ * and this function returns -1.
+ *
+ * \param texture the texture to update
+ * \param blendMode the SDL_BlendMode to use for texture blending
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetTextureBlendMode
+ * \sa SDL_RenderCopy
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureBlendMode(SDL_Texture * texture,
+ SDL_BlendMode blendMode);
+
+/**
+ * Get the blend mode used for texture copy operations.
+ *
+ * \param texture the texture to query
+ * \param blendMode a pointer filled in with the current SDL_BlendMode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetTextureBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture * texture,
+ SDL_BlendMode *blendMode);
+
+/**
+ * Set the scale mode used for texture scale operations.
+ *
+ * If the scale mode is not supported, the closest supported mode is chosen.
+ *
+ * \param texture The texture to update.
+ * \param scaleMode the SDL_ScaleMode to use for texture scaling.
+ * \returns 0 on success, or -1 if the texture is not valid.
+ *
+ * \sa SDL_GetTextureScaleMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetTextureScaleMode(SDL_Texture * texture,
+ SDL_ScaleMode scaleMode);
+
+/**
+ * Get the scale mode used for texture scale operations.
+ *
+ * \param texture the texture to query.
+ * \param scaleMode a pointer filled in with the current scale mode.
+ * \return 0 on success, or -1 if the texture is not valid.
+ *
+ * \sa SDL_SetTextureScaleMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture * texture,
+ SDL_ScaleMode *scaleMode);
+
+/**
+ * Update the given texture rectangle with new pixel data.
+ *
+ * The pixel data must be in the pixel format of the texture. Use
+ * SDL_QueryTexture() to query the pixel format of the texture.
+ *
+ * This is a fairly slow function, intended for use with static textures that
+ * do not change often.
+ *
+ * If the texture is intended to be updated often, it is preferred to create
+ * the texture as streaming and use the locking functions referenced below.
+ * While this function will work with streaming textures, for optimization
+ * reasons you may not get the pixels back if you lock the texture afterward.
+ *
+ * \param texture the texture to update
+ * \param rect an SDL_Rect structure representing the area to update, or NULL
+ * to update the entire texture
+ * \param pixels the raw pixel data in the format of the texture
+ * \param pitch the number of bytes in a row of pixel data, including padding
+ * between lines
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_LockTexture
+ * \sa SDL_UnlockTexture
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const void *pixels, int pitch);
+
+/**
+ * Update a rectangle within a planar YV12 or IYUV texture with new pixel
+ * data.
+ *
+ * You can use SDL_UpdateTexture() as long as your pixel data is a contiguous
+ * block of Y and U/V planes in the proper order, but this function is
+ * available if your pixel data is not contiguous.
+ *
+ * \param texture the texture to update
+ * \param rect a pointer to the rectangle of pixels to update, or NULL to
+ * update the entire texture
+ * \param Yplane the raw pixel data for the Y plane
+ * \param Ypitch the number of bytes between rows of pixel data for the Y
+ * plane
+ * \param Uplane the raw pixel data for the U plane
+ * \param Upitch the number of bytes between rows of pixel data for the U
+ * plane
+ * \param Vplane the raw pixel data for the V plane
+ * \param Vpitch the number of bytes between rows of pixel data for the V
+ * plane
+ * \returns 0 on success or -1 if the texture is not valid; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_UpdateTexture
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *Uplane, int Upitch,
+ const Uint8 *Vplane, int Vpitch);
+
+/**
+ * Update a rectangle within a planar NV12 or NV21 texture with new pixels.
+ *
+ * You can use SDL_UpdateTexture() as long as your pixel data is a contiguous
+ * block of NV12/21 planes in the proper order, but this function is available
+ * if your pixel data is not contiguous.
+ *
+ * \param texture the texture to update
+ * \param rect a pointer to the rectangle of pixels to update, or NULL to
+ * update the entire texture.
+ * \param Yplane the raw pixel data for the Y plane.
+ * \param Ypitch the number of bytes between rows of pixel data for the Y
+ * plane.
+ * \param UVplane the raw pixel data for the UV plane.
+ * \param UVpitch the number of bytes between rows of pixel data for the UV
+ * plane.
+ * \return 0 on success, or -1 if the texture is not valid.
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateNVTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *UVplane, int UVpitch);
+
+/**
+ * Lock a portion of the texture for **write-only** pixel access.
+ *
+ * As an optimization, the pixels made available for editing don't necessarily
+ * contain the old texture data. This is a write-only operation, and if you
+ * need to keep a copy of the texture data you should do that at the
+ * application level.
+ *
+ * You must use SDL_UnlockTexture() to unlock the pixels and apply any
+ * changes.
+ *
+ * \param texture the texture to lock for access, which was created with
+ * `SDL_TEXTUREACCESS_STREAMING`
+ * \param rect an SDL_Rect structure representing the area to lock for access;
+ * NULL to lock the entire texture
+ * \param pixels this is filled in with a pointer to the locked pixels,
+ * appropriately offset by the locked area
+ * \param pitch this is filled in with the pitch of the locked pixels; the
+ * pitch is the length of one row in bytes
+ * \returns 0 on success or a negative error code if the texture is not valid
+ * or was not created with `SDL_TEXTUREACCESS_STREAMING`; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_UnlockTexture
+ */
+extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture * texture,
+ const SDL_Rect * rect,
+ void **pixels, int *pitch);
+
+/**
+ * Lock a portion of the texture for **write-only** pixel access, and expose
+ * it as a SDL surface.
+ *
+ * Besides providing an SDL_Surface instead of raw pixel data, this function
+ * operates like SDL_LockTexture.
+ *
+ * As an optimization, the pixels made available for editing don't necessarily
+ * contain the old texture data. This is a write-only operation, and if you
+ * need to keep a copy of the texture data you should do that at the
+ * application level.
+ *
+ * You must use SDL_UnlockTexture() to unlock the pixels and apply any
+ * changes.
+ *
+ * The returned surface is freed internally after calling SDL_UnlockTexture()
+ * or SDL_DestroyTexture(). The caller should not free it.
+ *
+ * \param texture the texture to lock for access, which was created with
+ * `SDL_TEXTUREACCESS_STREAMING`
+ * \param rect a pointer to the rectangle to lock for access. If the rect is
+ * NULL, the entire texture will be locked
+ * \param surface this is filled in with an SDL surface representing the
+ * locked area
+ * \returns 0 on success, or -1 if the texture is not valid or was not created
+ * with `SDL_TEXTUREACCESS_STREAMING`
+ *
+ * \sa SDL_LockTexture
+ * \sa SDL_UnlockTexture
+ */
+extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture,
+ const SDL_Rect *rect,
+ SDL_Surface **surface);
+
+/**
+ * Unlock a texture, uploading the changes to video memory, if needed.
+ *
+ * **Warning**: Please note that SDL_LockTexture() is intended to be
+ * write-only; it will notguarantee the previous contents of the texture will
+ * be provided. You must fully initialize any area of a texture that you lock
+ * before unlocking it, as the pixels might otherwise be uninitialized memory.
+ *
+ * Which is to say: locking and immediately unlocking a texture can result in
+ * corrupted textures, depending on the renderer in use.
+ *
+ * \param texture a texture locked by SDL_LockTexture()
+ *
+ * \sa SDL_LockTexture
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture * texture);
+
+/**
+ * Determine whether a renderer supports the use of render targets.
+ *
+ * \param renderer the renderer that will be checked
+ * \returns SDL_TRUE if supported or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetRenderTarget
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderTargetSupported(SDL_Renderer *renderer);
+
+/**
+ * Set a texture as the current rendering target.
+ *
+ * Before using this function, you should check the
+ * `SDL_RENDERER_TARGETTEXTURE` bit in the flags of SDL_RendererInfo to see if
+ * render targets are supported.
+ *
+ * The default render target is the window for which the renderer was created.
+ * To stop rendering to a texture and render to the window again, call this
+ * function with a NULL `texture`.
+ *
+ * \param renderer the rendering context
+ * \param texture the targeted texture, which must be created with the
+ * `SDL_TEXTUREACCESS_TARGET` flag, or NULL to render to the
+ * window instead of a texture.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetRenderTarget
+ */
+extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer,
+ SDL_Texture *texture);
+
+/**
+ * Get the current render target.
+ *
+ * The default render target is the window for which the renderer was created,
+ * and is reported a NULL here.
+ *
+ * \param renderer the rendering context
+ * \returns the current render target or NULL for the default render target.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetRenderTarget
+ */
+extern DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer);
+
+/**
+ * Set a device independent resolution for rendering.
+ *
+ * This function uses the viewport and scaling functionality to allow a fixed
+ * logical resolution for rendering, regardless of the actual output
+ * resolution. If the actual output resolution doesn't have the same aspect
+ * ratio the output rendering will be centered within the output display.
+ *
+ * If the output display is a window, mouse and touch events in the window
+ * will be filtered and scaled so they seem to arrive within the logical
+ * resolution. The SDL_HINT_MOUSE_RELATIVE_SCALING hint controls whether
+ * relative motion events are also scaled.
+ *
+ * If this function results in scaling or subpixel drawing by the rendering
+ * backend, it will be handled using the appropriate quality hints.
+ *
+ * \param renderer the renderer for which resolution should be set
+ * \param w the width of the logical resolution
+ * \param h the height of the logical resolution
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderGetLogicalSize
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h);
+
+/**
+ * Get device independent resolution for rendering.
+ *
+ * This may return 0 for `w` and `h` if the SDL_Renderer has never had its
+ * logical size set by SDL_RenderSetLogicalSize() and never had a render
+ * target set.
+ *
+ * \param renderer a rendering context
+ * \param w an int to be filled with the width
+ * \param h an int to be filled with the height
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h);
+
+/**
+ * Set whether to force integer scales for resolution-independent rendering.
+ *
+ * This function restricts the logical viewport to integer values - that is,
+ * when a resolution is between two multiples of a logical size, the viewport
+ * size is rounded down to the lower multiple.
+ *
+ * \param renderer the renderer for which integer scaling should be set
+ * \param enable enable or disable the integer scaling for rendering
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_RenderGetIntegerScale
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetIntegerScale(SDL_Renderer * renderer,
+ SDL_bool enable);
+
+/**
+ * Get whether integer scales are forced for resolution-independent rendering.
+ *
+ * \param renderer the renderer from which integer scaling should be queried
+ * \returns SDL_TRUE if integer scales are forced or SDL_FALSE if not and on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_RenderSetIntegerScale
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer);
+
+/**
+ * Set the drawing area for rendering on the current target.
+ *
+ * When the window is resized, the viewport is reset to fill the entire new
+ * window size.
+ *
+ * \param renderer the rendering context
+ * \param rect the SDL_Rect structure representing the drawing area, or NULL
+ * to set the viewport to the entire target
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderGetViewport
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetViewport(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Get the drawing area for the current target.
+ *
+ * \param renderer the rendering context
+ * \param rect an SDL_Rect structure filled in with the current drawing area
+ *
+ * \sa SDL_RenderSetViewport
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetViewport(SDL_Renderer * renderer,
+ SDL_Rect * rect);
+
+/**
+ * Set the clip rectangle for rendering on the specified target.
+ *
+ * \param renderer the rendering context for which clip rectangle should be
+ * set
+ * \param rect an SDL_Rect structure representing the clip area, relative to
+ * the viewport, or NULL to disable clipping
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderGetClipRect
+ * \sa SDL_RenderIsClipEnabled
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetClipRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Get the clip rectangle for the current target.
+ *
+ * \param renderer the rendering context from which clip rectangle should be
+ * queried
+ * \param rect an SDL_Rect structure filled in with the current clipping area
+ * or an empty rectangle if clipping is disabled
+ *
+ * \sa SDL_RenderIsClipEnabled
+ * \sa SDL_RenderSetClipRect
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetClipRect(SDL_Renderer * renderer,
+ SDL_Rect * rect);
+
+/**
+ * Get whether clipping is enabled on the given renderer.
+ *
+ * \param renderer the renderer from which clip state should be queried
+ * \returns SDL_TRUE if clipping is enabled or SDL_FALSE if not; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_RenderGetClipRect
+ * \sa SDL_RenderSetClipRect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderIsClipEnabled(SDL_Renderer * renderer);
+
+
+/**
+ * Set the drawing scale for rendering on the current target.
+ *
+ * The drawing coordinates are scaled by the x/y scaling factors before they
+ * are used by the renderer. This allows resolution independent drawing with a
+ * single coordinate system.
+ *
+ * If this results in scaling or subpixel drawing by the rendering backend, it
+ * will be handled using the appropriate quality hints. For best results use
+ * integer scaling factors.
+ *
+ * \param renderer a rendering context
+ * \param scaleX the horizontal scaling factor
+ * \param scaleY the vertical scaling factor
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderGetScale
+ * \sa SDL_RenderSetLogicalSize
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetScale(SDL_Renderer * renderer,
+ float scaleX, float scaleY);
+
+/**
+ * Get the drawing scale for the current target.
+ *
+ * \param renderer the renderer from which drawing scale should be queried
+ * \param scaleX a pointer filled in with the horizontal scaling factor
+ * \param scaleY a pointer filled in with the vertical scaling factor
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderSetScale
+ */
+extern DECLSPEC void SDLCALL SDL_RenderGetScale(SDL_Renderer * renderer,
+ float *scaleX, float *scaleY);
+
+/**
+ * Set the color used for drawing operations (Rect, Line and Clear).
+ *
+ * Set the color for drawing or filling rectangles, lines, and points, and for
+ * SDL_RenderClear().
+ *
+ * \param renderer the rendering context
+ * \param r the red value used to draw on the rendering target
+ * \param g the green value used to draw on the rendering target
+ * \param b the blue value used to draw on the rendering target
+ * \param a the alpha value used to draw on the rendering target; usually
+ * `SDL_ALPHA_OPAQUE` (255). Use SDL_SetRenderDrawBlendMode to
+ * specify how the alpha channel is used
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetRenderDrawColor
+ * \sa SDL_RenderClear
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ */
+extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer * renderer,
+ Uint8 r, Uint8 g, Uint8 b,
+ Uint8 a);
+
+/**
+ * Get the color used for drawing operations (Rect, Line and Clear).
+ *
+ * \param renderer the rendering context
+ * \param r a pointer filled in with the red value used to draw on the
+ * rendering target
+ * \param g a pointer filled in with the green value used to draw on the
+ * rendering target
+ * \param b a pointer filled in with the blue value used to draw on the
+ * rendering target
+ * \param a a pointer filled in with the alpha value used to draw on the
+ * rendering target; usually `SDL_ALPHA_OPAQUE` (255)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_GetRenderDrawColor(SDL_Renderer * renderer,
+ Uint8 * r, Uint8 * g, Uint8 * b,
+ Uint8 * a);
+
+/**
+ * Set the blend mode used for drawing operations (Fill and Line).
+ *
+ * If the blend mode is not supported, the closest supported mode is chosen.
+ *
+ * \param renderer the rendering context
+ * \param blendMode the SDL_BlendMode to use for blending
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetRenderDrawBlendMode
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ */
+extern DECLSPEC int SDLCALL SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer,
+ SDL_BlendMode blendMode);
+
+/**
+ * Get the blend mode used for drawing operations.
+ *
+ * \param renderer the rendering context
+ * \param blendMode a pointer filled in with the current SDL_BlendMode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetRenderDrawBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer,
+ SDL_BlendMode *blendMode);
+
+/**
+ * Clear the current rendering target with the drawing color.
+ *
+ * This function clears the entire rendering target, ignoring the viewport and
+ * the clip rectangle.
+ *
+ * \param renderer the rendering context
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer * renderer);
+
+/**
+ * Draw a point on the current rendering target.
+ *
+ * SDL_RenderDrawPoint() draws a single point. If you want to draw multiple,
+ * use SDL_RenderDrawPoints() instead.
+ *
+ * \param renderer the rendering context
+ * \param x the x coordinate of the point
+ * \param y the y coordinate of the point
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPoint(SDL_Renderer * renderer,
+ int x, int y);
+
+/**
+ * Draw multiple points on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param points an array of SDL_Point structures that represent the points to
+ * draw
+ * \param count the number of points to draw
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPoints(SDL_Renderer * renderer,
+ const SDL_Point * points,
+ int count);
+
+/**
+ * Draw a line on the current rendering target.
+ *
+ * SDL_RenderDrawLine() draws the line to include both end points. If you want
+ * to draw multiple, connecting lines use SDL_RenderDrawLines() instead.
+ *
+ * \param renderer the rendering context
+ * \param x1 the x coordinate of the start point
+ * \param y1 the y coordinate of the start point
+ * \param x2 the x coordinate of the end point
+ * \param y2 the y coordinate of the end point
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLine(SDL_Renderer * renderer,
+ int x1, int y1, int x2, int y2);
+
+/**
+ * Draw a series of connected lines on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param points an array of SDL_Point structures representing points along
+ * the lines
+ * \param count the number of points, drawing count-1 lines
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLines(SDL_Renderer * renderer,
+ const SDL_Point * points,
+ int count);
+
+/**
+ * Draw a rectangle on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param rect an SDL_Rect structure representing the rectangle to draw, or
+ * NULL to outline the entire rendering target
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Draw some number of rectangles on the current rendering target.
+ *
+ * \param renderer the rendering context
+ * \param rects an array of SDL_Rect structures representing the rectangles to
+ * be drawn
+ * \param count the number of rectangles
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRects(SDL_Renderer * renderer,
+ const SDL_Rect * rects,
+ int count);
+
+/**
+ * Fill a rectangle on the current rendering target with the drawing color.
+ *
+ * The current drawing color is set by SDL_SetRenderDrawColor(), and the
+ * color's alpha value is ignored unless blending is enabled with the
+ * appropriate call to SDL_SetRenderDrawBlendMode().
+ *
+ * \param renderer the rendering context
+ * \param rect the SDL_Rect structure representing the rectangle to fill, or
+ * NULL for the entire rendering target
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRects
+ * \sa SDL_RenderPresent
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRect(SDL_Renderer * renderer,
+ const SDL_Rect * rect);
+
+/**
+ * Fill some number of rectangles on the current rendering target with the
+ * drawing color.
+ *
+ * \param renderer the rendering context
+ * \param rects an array of SDL_Rect structures representing the rectangles to
+ * be filled
+ * \param count the number of rectangles
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderPresent
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRects(SDL_Renderer * renderer,
+ const SDL_Rect * rects,
+ int count);
+
+/**
+ * Copy a portion of the texture to the current rendering target.
+ *
+ * The texture is blended with the destination based on its blend mode set
+ * with SDL_SetTextureBlendMode().
+ *
+ * The texture color is affected based on its color modulation set by
+ * SDL_SetTextureColorMod().
+ *
+ * The texture alpha is affected based on its alpha modulation set by
+ * SDL_SetTextureAlphaMod().
+ *
+ * \param renderer the rendering context
+ * \param texture the source texture
+ * \param srcrect the source SDL_Rect structure or NULL for the entire texture
+ * \param dstrect the destination SDL_Rect structure or NULL for the entire
+ * rendering target; the texture will be stretched to fill the
+ * given rectangle
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderCopyEx
+ * \sa SDL_SetTextureAlphaMod
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect);
+
+/**
+ * Copy a portion of the texture to the current rendering, with optional
+ * rotation and flipping.
+ *
+ * Copy a portion of the texture to the current rendering target, optionally
+ * rotating it by angle around the given center and also flipping it
+ * top-bottom and/or left-right.
+ *
+ * The texture is blended with the destination based on its blend mode set
+ * with SDL_SetTextureBlendMode().
+ *
+ * The texture color is affected based on its color modulation set by
+ * SDL_SetTextureColorMod().
+ *
+ * The texture alpha is affected based on its alpha modulation set by
+ * SDL_SetTextureAlphaMod().
+ *
+ * \param renderer the rendering context
+ * \param texture the source texture
+ * \param srcrect the source SDL_Rect structure or NULL for the entire texture
+ * \param dstrect the destination SDL_Rect structure or NULL for the entire
+ * rendering target
+ * \param angle an angle in degrees that indicates the rotation that will be
+ * applied to dstrect, rotating it in a clockwise direction
+ * \param center a pointer to a point indicating the point around which
+ * dstrect will be rotated (if NULL, rotation will be done
+ * around `dstrect.w / 2`, `dstrect.h / 2`)
+ * \param flip a SDL_RendererFlip value stating which flipping actions should
+ * be performed on the texture
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RenderCopy
+ * \sa SDL_SetTextureAlphaMod
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_SetTextureColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_Rect * dstrect,
+ const double angle,
+ const SDL_Point *center,
+ const SDL_RendererFlip flip);
+
+
+/**
+ * Draw a point on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw a point.
+ * \param x The x coordinate of the point.
+ * \param y The y coordinate of the point.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer,
+ float x, float y);
+
+/**
+ * Draw multiple points on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw multiple points.
+ * \param points The points to draw
+ * \param count The number of points to draw
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer,
+ const SDL_FPoint * points,
+ int count);
+
+/**
+ * Draw a line on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw a line.
+ * \param x1 The x coordinate of the start point.
+ * \param y1 The y coordinate of the start point.
+ * \param x2 The x coordinate of the end point.
+ * \param y2 The y coordinate of the end point.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer,
+ float x1, float y1, float x2, float y2);
+
+/**
+ * Draw a series of connected lines on the current rendering target at
+ * subpixel precision.
+ *
+ * \param renderer The renderer which should draw multiple lines.
+ * \param points The points along the lines
+ * \param count The number of points, drawing count-1 lines
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer,
+ const SDL_FPoint * points,
+ int count);
+
+/**
+ * Draw a rectangle on the current rendering target at subpixel precision.
+ *
+ * \param renderer The renderer which should draw a rectangle.
+ * \param rect A pointer to the destination rectangle, or NULL to outline the
+ * entire rendering target.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer,
+ const SDL_FRect * rect);
+
+/**
+ * Draw some number of rectangles on the current rendering target at subpixel
+ * precision.
+ *
+ * \param renderer The renderer which should draw multiple rectangles.
+ * \param rects A pointer to an array of destination rectangles.
+ * \param count The number of rectangles.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer,
+ const SDL_FRect * rects,
+ int count);
+
+/**
+ * Fill a rectangle on the current rendering target with the drawing color at
+ * subpixel precision.
+ *
+ * \param renderer The renderer which should fill a rectangle.
+ * \param rect A pointer to the destination rectangle, or NULL for the entire
+ * rendering target.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer,
+ const SDL_FRect * rect);
+
+/**
+ * Fill some number of rectangles on the current rendering target with the
+ * drawing color at subpixel precision.
+ *
+ * \param renderer The renderer which should fill multiple rectangles.
+ * \param rects A pointer to an array of destination rectangles.
+ * \param count The number of rectangles.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer,
+ const SDL_FRect * rects,
+ int count);
+
+/**
+ * Copy a portion of the texture to the current rendering target at subpixel
+ * precision.
+ *
+ * \param renderer The renderer which should copy parts of a texture.
+ * \param texture The source texture.
+ * \param srcrect A pointer to the source rectangle, or NULL for the entire
+ * texture.
+ * \param dstrect A pointer to the destination rectangle, or NULL for the
+ * entire rendering target.
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_FRect * dstrect);
+
+/**
+ * Copy a portion of the source texture to the current rendering target, with
+ * rotation and flipping, at subpixel precision.
+ *
+ * \param renderer The renderer which should copy parts of a texture.
+ * \param texture The source texture.
+ * \param srcrect A pointer to the source rectangle, or NULL for the entire
+ * texture.
+ * \param dstrect A pointer to the destination rectangle, or NULL for the
+ * entire rendering target.
+ * \param angle An angle in degrees that indicates the rotation that will be
+ * applied to dstrect, rotating it in a clockwise direction
+ * \param center A pointer to a point indicating the point around which
+ * dstrect will be rotated (if NULL, rotation will be done
+ * around dstrect.w/2, dstrect.h/2).
+ * \param flip An SDL_RendererFlip value stating which flipping actions should
+ * be performed on the texture
+ * \return 0 on success, or -1 on error
+ */
+extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
+ SDL_Texture * texture,
+ const SDL_Rect * srcrect,
+ const SDL_FRect * dstrect,
+ const double angle,
+ const SDL_FPoint *center,
+ const SDL_RendererFlip flip);
+
+/**
+ * Read pixels from the current rendering target to an array of pixels.
+ *
+ * **WARNING**: This is a very slow operation, and should not be used
+ * frequently.
+ *
+ * `pitch` specifies the number of bytes between rows in the destination
+ * `pixels` data. This allows you to write to a subrectangle or have padded
+ * rows in the destination. Generally, `pitch` should equal the number of
+ * pixels per row in the `pixels` data times the number of bytes per pixel,
+ * but it might contain additional padding (for example, 24bit RGB Windows
+ * Bitmap data pads all rows to multiples of 4 bytes).
+ *
+ * \param renderer the rendering context
+ * \param rect an SDL_Rect structure representing the area to read, or NULL
+ * for the entire render target
+ * \param format an SDL_PixelFormatEnum value of the desired format of the
+ * pixel data, or 0 to use the format of the rendering target
+ * \param pixels a pointer to the pixel data to copy into
+ * \param pitch the pitch of the `pixels` parameter
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderReadPixels(SDL_Renderer * renderer,
+ const SDL_Rect * rect,
+ Uint32 format,
+ void *pixels, int pitch);
+
+/**
+ * Update the screen with any rendering performed since the previous call.
+ *
+ * SDL's rendering functions operate on a backbuffer; that is, calling a
+ * rendering function such as SDL_RenderDrawLine() does not directly put a
+ * line on the screen, but rather updates the backbuffer. As such, you compose
+ * your entire scene and *present* the composed backbuffer to the screen as a
+ * complete picture.
+ *
+ * Therefore, when using SDL's rendering API, one does all drawing intended
+ * for the frame, and then calls this function once per frame to present the
+ * final drawing to the user.
+ *
+ * The backbuffer should be considered invalidated after each present; do not
+ * assume that previous contents will exist between frames. You are strongly
+ * encouraged to call SDL_RenderClear() to initialize the backbuffer before
+ * starting each new frame's drawing, even if you plan to overwrite every
+ * pixel.
+ *
+ * \param renderer the rendering context
+ *
+ * \sa SDL_RenderClear
+ * \sa SDL_RenderDrawLine
+ * \sa SDL_RenderDrawLines
+ * \sa SDL_RenderDrawPoint
+ * \sa SDL_RenderDrawPoints
+ * \sa SDL_RenderDrawRect
+ * \sa SDL_RenderDrawRects
+ * \sa SDL_RenderFillRect
+ * \sa SDL_RenderFillRects
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_SetRenderDrawColor
+ */
+extern DECLSPEC void SDLCALL SDL_RenderPresent(SDL_Renderer * renderer);
+
+/**
+ * Destroy the specified texture.
+ *
+ * Passing NULL or an otherwise invalid texture will set the SDL error message
+ * to "Invalid texture".
+ *
+ * \param texture the texture to destroy
+ *
+ * \sa SDL_CreateTexture
+ * \sa SDL_CreateTextureFromSurface
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture);
+
+/**
+ * Destroy the rendering context for a window and free associated textures.
+ *
+ * \param renderer the rendering context
+ *
+ * \sa SDL_CreateRenderer
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer);
+
+/**
+ * Force the rendering context to flush any pending commands to the underlying
+ * rendering API.
+ *
+ * You do not need to (and in fact, shouldn't) call this function unless you
+ * are planning to call into OpenGL/Direct3D/Metal/whatever directly in
+ * addition to using an SDL_Renderer.
+ *
+ * This is for a very-specific case: if you are using SDL's render API, you
+ * asked for a specific renderer backend (OpenGL, Direct3D, etc), you set
+ * SDL_HINT_RENDER_BATCHING to "1", and you plan to make OpenGL/D3D/whatever
+ * calls in addition to SDL render API calls. If all of this applies, you
+ * should call SDL_RenderFlush() between calls to SDL's render API and the
+ * low-level API you're using in cooperation.
+ *
+ * In all other cases, you can ignore this function. This is only here to get
+ * maximum performance out of a specific situation. In all other cases, SDL
+ * will do the right thing, perhaps at a performance loss.
+ *
+ * This function is first available in SDL 2.0.10, and is not needed in 2.0.9
+ * and earlier, as earlier versions did not queue rendering commands at all,
+ * instead flushing them to the OS immediately.
+ *
+ * \param renderer the rendering context
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.10.
+ */
+extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer);
+
+
+/**
+ * Bind an OpenGL/ES/ES2 texture to the current context.
+ *
+ * This is for use with OpenGL instructions when rendering OpenGL primitives
+ * directly.
+ *
+ * If not NULL, `texw` and `texh` will be filled with the width and height
+ * values suitable for the provided texture. In most cases, both will be 1.0,
+ * however, on systems that support the GL_ARB_texture_rectangle extension,
+ * these values will actually be the pixel width and height used to create the
+ * texture, so this factor needs to be taken into account when providing
+ * texture coordinates to OpenGL.
+ *
+ * You need a renderer to create an SDL_Texture, therefore you can only use
+ * this function with an implicit OpenGL context from SDL_CreateRenderer(),
+ * not with your own OpenGL context. If you need control over your OpenGL
+ * context, you need to write your own texture-loading methods.
+ *
+ * Also note that SDL may upload RGB textures as BGR (or vice-versa), and
+ * re-order the color channels in the shaders phase, so the uploaded texture
+ * may have swapped color channels.
+ *
+ * \param texture the texture to bind to the current OpenGL/ES/ES2 context
+ * \param texw a pointer to a float value which will be filled with the
+ * texture width or NULL if you don't need that value
+ * \param texh a pointer to a float value which will be filled with the
+ * texture height or NULL if you don't need that value
+ * \returns 0 on success, or -1 if the operation is not supported; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_MakeCurrent
+ * \sa SDL_GL_UnbindTexture
+ */
+extern DECLSPEC int SDLCALL SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh);
+
+/**
+ * Unbind an OpenGL/ES/ES2 texture from the current context.
+ *
+ * See SDL_GL_BindTexture() for examples on how to use these functions
+ *
+ * \param texture the texture to unbind from the current OpenGL/ES/ES2 context
+ * \returns 0 on success, or -1 if the operation is not supported
+ *
+ * \sa SDL_GL_BindTexture
+ * \sa SDL_GL_MakeCurrent
+ */
+extern DECLSPEC int SDLCALL SDL_GL_UnbindTexture(SDL_Texture *texture);
+
+/**
+ * Get the CAMetalLayer associated with the given Metal renderer.
+ *
+ * This function returns `void *`, so SDL doesn't have to include Metal's
+ * headers, but it can be safely cast to a `CAMetalLayer *`.
+ *
+ * \param renderer The renderer to query
+ * \returns a `CAMetalLayer *` on success, or NULL if the renderer isn't a
+ * Metal renderer
+ *
+ * \sa SDL_RenderGetMetalCommandEncoder
+ */
+extern DECLSPEC void *SDLCALL SDL_RenderGetMetalLayer(SDL_Renderer * renderer);
+
+/**
+ * Get the Metal command encoder for the current frame
+ *
+ * This function returns `void *`, so SDL doesn't have to include Metal's
+ * headers, but it can be safely cast to an `id<MTLRenderCommandEncoder>`.
+ *
+ * \param renderer The renderer to query
+ * \returns an `id<MTLRenderCommandEncoder>` on success, or NULL if the
+ * renderer isn't a Metal renderer.
+ *
+ * \sa SDL_RenderGetMetalLayer
+ */
+extern DECLSPEC void *SDLCALL SDL_RenderGetMetalCommandEncoder(SDL_Renderer * renderer);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_render_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_revision.h b/Client/ThirdParty/SDL2/include/SDL_revision.h
new file mode 100644
index 0000000..2376375
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_revision.h
@@ -0,0 +1,2 @@
+#define SDL_REVISION "https://github.com/libsdl-org/SDL.git@25f9ed87ff6947d9576fc9d79dee0784e638ac58"
+#define SDL_REVISION_NUMBER 0
diff --git a/Client/ThirdParty/SDL2/include/SDL_rwops.h b/Client/ThirdParty/SDL2/include/SDL_rwops.h
new file mode 100644
index 0000000..52b3a6c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_rwops.h
@@ -0,0 +1,412 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_rwops.h
+ *
+ * This file provides a general interface for SDL to read and write
+ * data streams. It can easily be extended to files, memory, etc.
+ */
+
+#ifndef SDL_rwops_h_
+#define SDL_rwops_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* RWops Types */
+#define SDL_RWOPS_UNKNOWN 0U /**< Unknown stream type */
+#define SDL_RWOPS_WINFILE 1U /**< Win32 file */
+#define SDL_RWOPS_STDFILE 2U /**< Stdio file */
+#define SDL_RWOPS_JNIFILE 3U /**< Android asset */
+#define SDL_RWOPS_MEMORY 4U /**< Memory stream */
+#define SDL_RWOPS_MEMORY_RO 5U /**< Read-Only memory stream */
+#if defined(__VITA__)
+#define SDL_RWOPS_VITAFILE 6U /**< Vita file */
+#endif
+
+/**
+ * This is the read/write operation structure -- very basic.
+ */
+typedef struct SDL_RWops
+{
+ /**
+ * Return the size of the file in this rwops, or -1 if unknown
+ */
+ Sint64 (SDLCALL * size) (struct SDL_RWops * context);
+
+ /**
+ * Seek to \c offset relative to \c whence, one of stdio's whence values:
+ * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END
+ *
+ * \return the final offset in the data stream, or -1 on error.
+ */
+ Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset,
+ int whence);
+
+ /**
+ * Read up to \c maxnum objects each of size \c size from the data
+ * stream to the area pointed at by \c ptr.
+ *
+ * \return the number of objects read, or 0 at error or end of file.
+ */
+ size_t (SDLCALL * read) (struct SDL_RWops * context, void *ptr,
+ size_t size, size_t maxnum);
+
+ /**
+ * Write exactly \c num objects each of size \c size from the area
+ * pointed at by \c ptr to data stream.
+ *
+ * \return the number of objects written, or 0 at error or end of file.
+ */
+ size_t (SDLCALL * write) (struct SDL_RWops * context, const void *ptr,
+ size_t size, size_t num);
+
+ /**
+ * Close and free an allocated SDL_RWops structure.
+ *
+ * \return 0 if successful or -1 on write error when flushing data.
+ */
+ int (SDLCALL * close) (struct SDL_RWops * context);
+
+ Uint32 type;
+ union
+ {
+#if defined(__ANDROID__)
+ struct
+ {
+ void *asset;
+ } androidio;
+#elif defined(__WIN32__)
+ struct
+ {
+ SDL_bool append;
+ void *h;
+ struct
+ {
+ void *data;
+ size_t size;
+ size_t left;
+ } buffer;
+ } windowsio;
+#elif defined(__VITA__)
+ struct
+ {
+ int h;
+ struct
+ {
+ void *data;
+ size_t size;
+ size_t left;
+ } buffer;
+ } vitaio;
+#endif
+
+#ifdef HAVE_STDIO_H
+ struct
+ {
+ SDL_bool autoclose;
+ FILE *fp;
+ } stdio;
+#endif
+ struct
+ {
+ Uint8 *base;
+ Uint8 *here;
+ Uint8 *stop;
+ } mem;
+ struct
+ {
+ void *data1;
+ void *data2;
+ } unknown;
+ } hidden;
+
+} SDL_RWops;
+
+
+/**
+ * \name RWFrom functions
+ *
+ * Functions to create SDL_RWops structures from various data streams.
+ */
+/* @{ */
+
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file,
+ const char *mode);
+
+#ifdef HAVE_STDIO_H
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(FILE * fp,
+ SDL_bool autoclose);
+#else
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFP(void * fp,
+ SDL_bool autoclose);
+#endif
+
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, int size);
+extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem,
+ int size);
+
+/* @} *//* RWFrom functions */
+
+
+extern DECLSPEC SDL_RWops *SDLCALL SDL_AllocRW(void);
+extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area);
+
+#define RW_SEEK_SET 0 /**< Seek from the beginning of data */
+#define RW_SEEK_CUR 1 /**< Seek relative to current read point */
+#define RW_SEEK_END 2 /**< Seek relative to the end of data */
+
+/**
+ * Use this macro to get the size of the data stream in an SDL_RWops.
+ *
+ * \param context the SDL_RWops to get the size of the data stream from
+ * \returns the size of the data stream in the SDL_RWops on success, -1 if
+ * unknown or a negative error code on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context);
+
+/**
+ * Seek within an SDL_RWops data stream.
+ *
+ * This function seeks to byte `offset`, relative to `whence`.
+ *
+ * `whence` may be any of the following values:
+ *
+ * - `RW_SEEK_SET`: seek from the beginning of data
+ * - `RW_SEEK_CUR`: seek relative to current read point
+ * - `RW_SEEK_END`: seek relative to the end of data
+ *
+ * If this stream can not seek, it will return -1.
+ *
+ * SDL_RWseek() is actually a wrapper function that calls the SDL_RWops's
+ * `seek` method appropriately, to simplify application development.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param offset an offset in bytes, relative to **whence** location; can be
+ * negative
+ * \param whence any of `RW_SEEK_SET`, `RW_SEEK_CUR`, `RW_SEEK_END`
+ * \returns the final offset in the data stream after the seek or -1 on error.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWtell
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context,
+ Sint64 offset, int whence);
+
+/**
+ * Determine the current read/write offset in an SDL_RWops data stream.
+ *
+ * SDL_RWtell is actually a wrapper function that calls the SDL_RWops's `seek`
+ * method, with an offset of 0 bytes from `RW_SEEK_CUR`, to simplify
+ * application development.
+ *
+ * \param context a SDL_RWops data stream object from which to get the current
+ * offset
+ * \returns the current offset in the stream, or -1 if the information can not
+ * be determined.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context);
+
+/**
+ * Read from a data source.
+ *
+ * This function reads up to `maxnum` objects each of size `size` from the
+ * data source to the area pointed at by `ptr`. This function may read less
+ * objects than requested. It will return zero when there has been an error or
+ * the data stream is completely read.
+ *
+ * SDL_RWread() is actually a function wrapper that calls the SDL_RWops's
+ * `read` method appropriately, to simplify application development.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param ptr a pointer to a buffer to read data into
+ * \param size the size of each object to read, in bytes
+ * \param maxnum the maximum number of objects to be read
+ * \returns the number of objects read, or 0 at error or end of file; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context,
+ void *ptr, size_t size,
+ size_t maxnum);
+
+/**
+ * Write to an SDL_RWops data stream.
+ *
+ * This function writes exactly `num` objects each of size `size` from the
+ * area pointed at by `ptr` to the stream. If this fails for any reason, it'll
+ * return less than `num` to demonstrate how far the write progressed. On
+ * success, it returns `num`.
+ *
+ * SDL_RWwrite is actually a function wrapper that calls the SDL_RWops's
+ * `write` method appropriately, to simplify application development.
+ *
+ * \param context a pointer to an SDL_RWops structure
+ * \param ptr a pointer to a buffer containing data to write
+ * \param size the size of an object to write, in bytes
+ * \param num the number of objects to write
+ * \returns the number of objects written, which will be less than **num** on
+ * error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_RWclose
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ */
+extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context,
+ const void *ptr, size_t size,
+ size_t num);
+
+/**
+ * Close and free an allocated SDL_RWops structure.
+ *
+ * SDL_RWclose() closes and cleans up the SDL_RWops stream. It releases any
+ * resources used by the stream and frees the SDL_RWops itself with
+ * SDL_FreeRW(). This returns 0 on success, or -1 if the stream failed to
+ * flush to its output (e.g. to disk).
+ *
+ * Note that if this fails to flush the stream to disk, this function reports
+ * an error, but the SDL_RWops is still invalid once this function returns.
+ *
+ * SDL_RWclose() is actually a macro that calls the SDL_RWops's `close` method
+ * appropriately, to simplify application development.
+ *
+ * \param context SDL_RWops structure to close
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_RWFromConstMem
+ * \sa SDL_RWFromFile
+ * \sa SDL_RWFromFP
+ * \sa SDL_RWFromMem
+ * \sa SDL_RWread
+ * \sa SDL_RWseek
+ * \sa SDL_RWwrite
+ */
+extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context);
+
+/**
+ * Load all the data from an SDL data stream.
+ *
+ * The data is allocated with a zero byte at the end (null terminated) for
+ * convenience. This extra byte is not included in the value reported via
+ * `datasize`.
+ *
+ * The data should be freed with SDL_free().
+ *
+ * \param src the SDL_RWops to read all available data from
+ * \param datasize if not NULL, will store the number of bytes read
+ * \param freesrc if non-zero, calls SDL_RWclose() on `src` before returning
+ * \returns the data, or NULL if there was an error.
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops *src,
+ size_t *datasize,
+ int freesrc);
+
+/**
+ * Load all the data from a file path.
+ *
+ * The data is allocated with a zero byte at the end (null terminated) for
+ * convenience. This extra byte is not included in the value reported via
+ * `datasize`.
+ *
+ * The data should be freed with SDL_free().
+ *
+ * \param file the path to read all available data from
+ * \param datasize if not NULL, will store the number of bytes read
+ * \returns the data, or NULL if there was an error.
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize);
+
+/**
+ * \name Read endian functions
+ *
+ * Read an item of the specified endianness and return in native format.
+ */
+/* @{ */
+extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src);
+extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src);
+extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src);
+extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src);
+extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src);
+extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src);
+extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src);
+/* @} *//* Read endian functions */
+
+/**
+ * \name Write endian functions
+ *
+ * Write an item of native format to the specified endianness.
+ */
+/* @{ */
+extern DECLSPEC size_t SDLCALL SDL_WriteU8(SDL_RWops * dst, Uint8 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteLE16(SDL_RWops * dst, Uint16 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteBE16(SDL_RWops * dst, Uint16 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteLE32(SDL_RWops * dst, Uint32 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteBE32(SDL_RWops * dst, Uint32 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteLE64(SDL_RWops * dst, Uint64 value);
+extern DECLSPEC size_t SDLCALL SDL_WriteBE64(SDL_RWops * dst, Uint64 value);
+/* @} *//* Write endian functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_rwops_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_scancode.h b/Client/ThirdParty/SDL2/include/SDL_scancode.h
new file mode 100644
index 0000000..e54c1e0
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_scancode.h
@@ -0,0 +1,413 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_scancode.h
+ *
+ * Defines keyboard scancodes.
+ */
+
+#ifndef SDL_scancode_h_
+#define SDL_scancode_h_
+
+#include "SDL_stdinc.h"
+
+/**
+ * \brief The SDL keyboard scancode representation.
+ *
+ * Values of this type are used to represent keyboard keys, among other places
+ * in the \link SDL_Keysym::scancode key.keysym.scancode \endlink field of the
+ * SDL_Event structure.
+ *
+ * The values in this enumeration are based on the USB usage page standard:
+ * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
+ */
+typedef enum
+{
+ SDL_SCANCODE_UNKNOWN = 0,
+
+ /**
+ * \name Usage page 0x07
+ *
+ * These values are from usage page 0x07 (USB keyboard page).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_A = 4,
+ SDL_SCANCODE_B = 5,
+ SDL_SCANCODE_C = 6,
+ SDL_SCANCODE_D = 7,
+ SDL_SCANCODE_E = 8,
+ SDL_SCANCODE_F = 9,
+ SDL_SCANCODE_G = 10,
+ SDL_SCANCODE_H = 11,
+ SDL_SCANCODE_I = 12,
+ SDL_SCANCODE_J = 13,
+ SDL_SCANCODE_K = 14,
+ SDL_SCANCODE_L = 15,
+ SDL_SCANCODE_M = 16,
+ SDL_SCANCODE_N = 17,
+ SDL_SCANCODE_O = 18,
+ SDL_SCANCODE_P = 19,
+ SDL_SCANCODE_Q = 20,
+ SDL_SCANCODE_R = 21,
+ SDL_SCANCODE_S = 22,
+ SDL_SCANCODE_T = 23,
+ SDL_SCANCODE_U = 24,
+ SDL_SCANCODE_V = 25,
+ SDL_SCANCODE_W = 26,
+ SDL_SCANCODE_X = 27,
+ SDL_SCANCODE_Y = 28,
+ SDL_SCANCODE_Z = 29,
+
+ SDL_SCANCODE_1 = 30,
+ SDL_SCANCODE_2 = 31,
+ SDL_SCANCODE_3 = 32,
+ SDL_SCANCODE_4 = 33,
+ SDL_SCANCODE_5 = 34,
+ SDL_SCANCODE_6 = 35,
+ SDL_SCANCODE_7 = 36,
+ SDL_SCANCODE_8 = 37,
+ SDL_SCANCODE_9 = 38,
+ SDL_SCANCODE_0 = 39,
+
+ SDL_SCANCODE_RETURN = 40,
+ SDL_SCANCODE_ESCAPE = 41,
+ SDL_SCANCODE_BACKSPACE = 42,
+ SDL_SCANCODE_TAB = 43,
+ SDL_SCANCODE_SPACE = 44,
+
+ SDL_SCANCODE_MINUS = 45,
+ SDL_SCANCODE_EQUALS = 46,
+ SDL_SCANCODE_LEFTBRACKET = 47,
+ SDL_SCANCODE_RIGHTBRACKET = 48,
+ SDL_SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return
+ * key on ISO keyboards and at the right end
+ * of the QWERTY row on ANSI keyboards.
+ * Produces REVERSE SOLIDUS (backslash) and
+ * VERTICAL LINE in a US layout, REVERSE
+ * SOLIDUS and VERTICAL LINE in a UK Mac
+ * layout, NUMBER SIGN and TILDE in a UK
+ * Windows layout, DOLLAR SIGN and POUND SIGN
+ * in a Swiss German layout, NUMBER SIGN and
+ * APOSTROPHE in a German layout, GRAVE
+ * ACCENT and POUND SIGN in a French Mac
+ * layout, and ASTERISK and MICRO SIGN in a
+ * French Windows layout.
+ */
+ SDL_SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code
+ * instead of 49 for the same key, but all
+ * OSes I've seen treat the two codes
+ * identically. So, as an implementor, unless
+ * your keyboard generates both of those
+ * codes and your OS treats them differently,
+ * you should generate SDL_SCANCODE_BACKSLASH
+ * instead of this code. As a user, you
+ * should not rely on this code because SDL
+ * will never generate it with most (all?)
+ * keyboards.
+ */
+ SDL_SCANCODE_SEMICOLON = 51,
+ SDL_SCANCODE_APOSTROPHE = 52,
+ SDL_SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI
+ * and ISO keyboards). Produces GRAVE ACCENT and
+ * TILDE in a US Windows layout and in US and UK
+ * Mac layouts on ANSI keyboards, GRAVE ACCENT
+ * and NOT SIGN in a UK Windows layout, SECTION
+ * SIGN and PLUS-MINUS SIGN in US and UK Mac
+ * layouts on ISO keyboards, SECTION SIGN and
+ * DEGREE SIGN in a Swiss German layout (Mac:
+ * only on ISO keyboards), CIRCUMFLEX ACCENT and
+ * DEGREE SIGN in a German layout (Mac: only on
+ * ISO keyboards), SUPERSCRIPT TWO and TILDE in a
+ * French Windows layout, COMMERCIAL AT and
+ * NUMBER SIGN in a French Mac layout on ISO
+ * keyboards, and LESS-THAN SIGN and GREATER-THAN
+ * SIGN in a Swiss German, German, or French Mac
+ * layout on ANSI keyboards.
+ */
+ SDL_SCANCODE_COMMA = 54,
+ SDL_SCANCODE_PERIOD = 55,
+ SDL_SCANCODE_SLASH = 56,
+
+ SDL_SCANCODE_CAPSLOCK = 57,
+
+ SDL_SCANCODE_F1 = 58,
+ SDL_SCANCODE_F2 = 59,
+ SDL_SCANCODE_F3 = 60,
+ SDL_SCANCODE_F4 = 61,
+ SDL_SCANCODE_F5 = 62,
+ SDL_SCANCODE_F6 = 63,
+ SDL_SCANCODE_F7 = 64,
+ SDL_SCANCODE_F8 = 65,
+ SDL_SCANCODE_F9 = 66,
+ SDL_SCANCODE_F10 = 67,
+ SDL_SCANCODE_F11 = 68,
+ SDL_SCANCODE_F12 = 69,
+
+ SDL_SCANCODE_PRINTSCREEN = 70,
+ SDL_SCANCODE_SCROLLLOCK = 71,
+ SDL_SCANCODE_PAUSE = 72,
+ SDL_SCANCODE_INSERT = 73, /**< insert on PC, help on some Mac keyboards (but
+ does send code 73, not 117) */
+ SDL_SCANCODE_HOME = 74,
+ SDL_SCANCODE_PAGEUP = 75,
+ SDL_SCANCODE_DELETE = 76,
+ SDL_SCANCODE_END = 77,
+ SDL_SCANCODE_PAGEDOWN = 78,
+ SDL_SCANCODE_RIGHT = 79,
+ SDL_SCANCODE_LEFT = 80,
+ SDL_SCANCODE_DOWN = 81,
+ SDL_SCANCODE_UP = 82,
+
+ SDL_SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards
+ */
+ SDL_SCANCODE_KP_DIVIDE = 84,
+ SDL_SCANCODE_KP_MULTIPLY = 85,
+ SDL_SCANCODE_KP_MINUS = 86,
+ SDL_SCANCODE_KP_PLUS = 87,
+ SDL_SCANCODE_KP_ENTER = 88,
+ SDL_SCANCODE_KP_1 = 89,
+ SDL_SCANCODE_KP_2 = 90,
+ SDL_SCANCODE_KP_3 = 91,
+ SDL_SCANCODE_KP_4 = 92,
+ SDL_SCANCODE_KP_5 = 93,
+ SDL_SCANCODE_KP_6 = 94,
+ SDL_SCANCODE_KP_7 = 95,
+ SDL_SCANCODE_KP_8 = 96,
+ SDL_SCANCODE_KP_9 = 97,
+ SDL_SCANCODE_KP_0 = 98,
+ SDL_SCANCODE_KP_PERIOD = 99,
+
+ SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
+ * keyboards have over ANSI ones,
+ * located between left shift and Y.
+ * Produces GRAVE ACCENT and TILDE in a
+ * US or UK Mac layout, REVERSE SOLIDUS
+ * (backslash) and VERTICAL LINE in a
+ * US or UK Windows layout, and
+ * LESS-THAN SIGN and GREATER-THAN SIGN
+ * in a Swiss German, German, or French
+ * layout. */
+ SDL_SCANCODE_APPLICATION = 101, /**< windows contextual menu, compose */
+ SDL_SCANCODE_POWER = 102, /**< The USB document says this is a status flag,
+ * not a physical key - but some Mac keyboards
+ * do have a power key. */
+ SDL_SCANCODE_KP_EQUALS = 103,
+ SDL_SCANCODE_F13 = 104,
+ SDL_SCANCODE_F14 = 105,
+ SDL_SCANCODE_F15 = 106,
+ SDL_SCANCODE_F16 = 107,
+ SDL_SCANCODE_F17 = 108,
+ SDL_SCANCODE_F18 = 109,
+ SDL_SCANCODE_F19 = 110,
+ SDL_SCANCODE_F20 = 111,
+ SDL_SCANCODE_F21 = 112,
+ SDL_SCANCODE_F22 = 113,
+ SDL_SCANCODE_F23 = 114,
+ SDL_SCANCODE_F24 = 115,
+ SDL_SCANCODE_EXECUTE = 116,
+ SDL_SCANCODE_HELP = 117,
+ SDL_SCANCODE_MENU = 118,
+ SDL_SCANCODE_SELECT = 119,
+ SDL_SCANCODE_STOP = 120,
+ SDL_SCANCODE_AGAIN = 121, /**< redo */
+ SDL_SCANCODE_UNDO = 122,
+ SDL_SCANCODE_CUT = 123,
+ SDL_SCANCODE_COPY = 124,
+ SDL_SCANCODE_PASTE = 125,
+ SDL_SCANCODE_FIND = 126,
+ SDL_SCANCODE_MUTE = 127,
+ SDL_SCANCODE_VOLUMEUP = 128,
+ SDL_SCANCODE_VOLUMEDOWN = 129,
+/* not sure whether there's a reason to enable these */
+/* SDL_SCANCODE_LOCKINGCAPSLOCK = 130, */
+/* SDL_SCANCODE_LOCKINGNUMLOCK = 131, */
+/* SDL_SCANCODE_LOCKINGSCROLLLOCK = 132, */
+ SDL_SCANCODE_KP_COMMA = 133,
+ SDL_SCANCODE_KP_EQUALSAS400 = 134,
+
+ SDL_SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see
+ footnotes in USB doc */
+ SDL_SCANCODE_INTERNATIONAL2 = 136,
+ SDL_SCANCODE_INTERNATIONAL3 = 137, /**< Yen */
+ SDL_SCANCODE_INTERNATIONAL4 = 138,
+ SDL_SCANCODE_INTERNATIONAL5 = 139,
+ SDL_SCANCODE_INTERNATIONAL6 = 140,
+ SDL_SCANCODE_INTERNATIONAL7 = 141,
+ SDL_SCANCODE_INTERNATIONAL8 = 142,
+ SDL_SCANCODE_INTERNATIONAL9 = 143,
+ SDL_SCANCODE_LANG1 = 144, /**< Hangul/English toggle */
+ SDL_SCANCODE_LANG2 = 145, /**< Hanja conversion */
+ SDL_SCANCODE_LANG3 = 146, /**< Katakana */
+ SDL_SCANCODE_LANG4 = 147, /**< Hiragana */
+ SDL_SCANCODE_LANG5 = 148, /**< Zenkaku/Hankaku */
+ SDL_SCANCODE_LANG6 = 149, /**< reserved */
+ SDL_SCANCODE_LANG7 = 150, /**< reserved */
+ SDL_SCANCODE_LANG8 = 151, /**< reserved */
+ SDL_SCANCODE_LANG9 = 152, /**< reserved */
+
+ SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
+ SDL_SCANCODE_SYSREQ = 154,
+ SDL_SCANCODE_CANCEL = 155,
+ SDL_SCANCODE_CLEAR = 156,
+ SDL_SCANCODE_PRIOR = 157,
+ SDL_SCANCODE_RETURN2 = 158,
+ SDL_SCANCODE_SEPARATOR = 159,
+ SDL_SCANCODE_OUT = 160,
+ SDL_SCANCODE_OPER = 161,
+ SDL_SCANCODE_CLEARAGAIN = 162,
+ SDL_SCANCODE_CRSEL = 163,
+ SDL_SCANCODE_EXSEL = 164,
+
+ SDL_SCANCODE_KP_00 = 176,
+ SDL_SCANCODE_KP_000 = 177,
+ SDL_SCANCODE_THOUSANDSSEPARATOR = 178,
+ SDL_SCANCODE_DECIMALSEPARATOR = 179,
+ SDL_SCANCODE_CURRENCYUNIT = 180,
+ SDL_SCANCODE_CURRENCYSUBUNIT = 181,
+ SDL_SCANCODE_KP_LEFTPAREN = 182,
+ SDL_SCANCODE_KP_RIGHTPAREN = 183,
+ SDL_SCANCODE_KP_LEFTBRACE = 184,
+ SDL_SCANCODE_KP_RIGHTBRACE = 185,
+ SDL_SCANCODE_KP_TAB = 186,
+ SDL_SCANCODE_KP_BACKSPACE = 187,
+ SDL_SCANCODE_KP_A = 188,
+ SDL_SCANCODE_KP_B = 189,
+ SDL_SCANCODE_KP_C = 190,
+ SDL_SCANCODE_KP_D = 191,
+ SDL_SCANCODE_KP_E = 192,
+ SDL_SCANCODE_KP_F = 193,
+ SDL_SCANCODE_KP_XOR = 194,
+ SDL_SCANCODE_KP_POWER = 195,
+ SDL_SCANCODE_KP_PERCENT = 196,
+ SDL_SCANCODE_KP_LESS = 197,
+ SDL_SCANCODE_KP_GREATER = 198,
+ SDL_SCANCODE_KP_AMPERSAND = 199,
+ SDL_SCANCODE_KP_DBLAMPERSAND = 200,
+ SDL_SCANCODE_KP_VERTICALBAR = 201,
+ SDL_SCANCODE_KP_DBLVERTICALBAR = 202,
+ SDL_SCANCODE_KP_COLON = 203,
+ SDL_SCANCODE_KP_HASH = 204,
+ SDL_SCANCODE_KP_SPACE = 205,
+ SDL_SCANCODE_KP_AT = 206,
+ SDL_SCANCODE_KP_EXCLAM = 207,
+ SDL_SCANCODE_KP_MEMSTORE = 208,
+ SDL_SCANCODE_KP_MEMRECALL = 209,
+ SDL_SCANCODE_KP_MEMCLEAR = 210,
+ SDL_SCANCODE_KP_MEMADD = 211,
+ SDL_SCANCODE_KP_MEMSUBTRACT = 212,
+ SDL_SCANCODE_KP_MEMMULTIPLY = 213,
+ SDL_SCANCODE_KP_MEMDIVIDE = 214,
+ SDL_SCANCODE_KP_PLUSMINUS = 215,
+ SDL_SCANCODE_KP_CLEAR = 216,
+ SDL_SCANCODE_KP_CLEARENTRY = 217,
+ SDL_SCANCODE_KP_BINARY = 218,
+ SDL_SCANCODE_KP_OCTAL = 219,
+ SDL_SCANCODE_KP_DECIMAL = 220,
+ SDL_SCANCODE_KP_HEXADECIMAL = 221,
+
+ SDL_SCANCODE_LCTRL = 224,
+ SDL_SCANCODE_LSHIFT = 225,
+ SDL_SCANCODE_LALT = 226, /**< alt, option */
+ SDL_SCANCODE_LGUI = 227, /**< windows, command (apple), meta */
+ SDL_SCANCODE_RCTRL = 228,
+ SDL_SCANCODE_RSHIFT = 229,
+ SDL_SCANCODE_RALT = 230, /**< alt gr, option */
+ SDL_SCANCODE_RGUI = 231, /**< windows, command (apple), meta */
+
+ SDL_SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered
+ * by any of the above, but since there's a
+ * special KMOD_MODE for it I'm adding it here
+ */
+
+ /* @} *//* Usage page 0x07 */
+
+ /**
+ * \name Usage page 0x0C
+ *
+ * These values are mapped from usage page 0x0C (USB consumer page).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_AUDIONEXT = 258,
+ SDL_SCANCODE_AUDIOPREV = 259,
+ SDL_SCANCODE_AUDIOSTOP = 260,
+ SDL_SCANCODE_AUDIOPLAY = 261,
+ SDL_SCANCODE_AUDIOMUTE = 262,
+ SDL_SCANCODE_MEDIASELECT = 263,
+ SDL_SCANCODE_WWW = 264,
+ SDL_SCANCODE_MAIL = 265,
+ SDL_SCANCODE_CALCULATOR = 266,
+ SDL_SCANCODE_COMPUTER = 267,
+ SDL_SCANCODE_AC_SEARCH = 268,
+ SDL_SCANCODE_AC_HOME = 269,
+ SDL_SCANCODE_AC_BACK = 270,
+ SDL_SCANCODE_AC_FORWARD = 271,
+ SDL_SCANCODE_AC_STOP = 272,
+ SDL_SCANCODE_AC_REFRESH = 273,
+ SDL_SCANCODE_AC_BOOKMARKS = 274,
+
+ /* @} *//* Usage page 0x0C */
+
+ /**
+ * \name Walther keys
+ *
+ * These are values that Christian Walther added (for mac keyboard?).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_BRIGHTNESSDOWN = 275,
+ SDL_SCANCODE_BRIGHTNESSUP = 276,
+ SDL_SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display
+ switch, video mode switch */
+ SDL_SCANCODE_KBDILLUMTOGGLE = 278,
+ SDL_SCANCODE_KBDILLUMDOWN = 279,
+ SDL_SCANCODE_KBDILLUMUP = 280,
+ SDL_SCANCODE_EJECT = 281,
+ SDL_SCANCODE_SLEEP = 282,
+
+ SDL_SCANCODE_APP1 = 283,
+ SDL_SCANCODE_APP2 = 284,
+
+ /* @} *//* Walther keys */
+
+ /**
+ * \name Usage page 0x0C (additional media keys)
+ *
+ * These values are mapped from usage page 0x0C (USB consumer page).
+ */
+ /* @{ */
+
+ SDL_SCANCODE_AUDIOREWIND = 285,
+ SDL_SCANCODE_AUDIOFASTFORWARD = 286,
+
+ /* @} *//* Usage page 0x0C (additional media keys) */
+
+ /* Add any other keys here. */
+
+ SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes
+ for array bounds */
+} SDL_Scancode;
+
+#endif /* SDL_scancode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_sensor.h b/Client/ThirdParty/SDL2/include/SDL_sensor.h
new file mode 100644
index 0000000..3bab8a4
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_sensor.h
@@ -0,0 +1,271 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_sensor.h
+ *
+ * Include file for SDL sensor event handling
+ *
+ */
+
+#ifndef SDL_sensor_h_
+#define SDL_sensor_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+/**
+ * \brief SDL_sensor.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_SENSOR flag. This causes SDL to scan the system
+ * for sensors, and load appropriate drivers.
+ */
+
+struct _SDL_Sensor;
+typedef struct _SDL_Sensor SDL_Sensor;
+
+/**
+ * This is a unique ID for a sensor for the time it is connected to the system,
+ * and is never reused for the lifetime of the application.
+ *
+ * The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
+ */
+typedef Sint32 SDL_SensorID;
+
+/* The different sensors defined by SDL
+ *
+ * Additional sensors may be available, using platform dependent semantics.
+ *
+ * Hare are the additional Android sensors:
+ * https://developer.android.com/reference/android/hardware/SensorEvent.html#values
+ */
+typedef enum
+{
+ SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */
+ SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */
+ SDL_SENSOR_ACCEL, /**< Accelerometer */
+ SDL_SENSOR_GYRO /**< Gyroscope */
+} SDL_SensorType;
+
+/**
+ * Accelerometer sensor
+ *
+ * The accelerometer returns the current acceleration in SI meters per
+ * second squared. This measurement includes the force of gravity, so
+ * a device at rest will have an value of SDL_STANDARD_GRAVITY away
+ * from the center of the earth.
+ *
+ * values[0]: Acceleration on the x axis
+ * values[1]: Acceleration on the y axis
+ * values[2]: Acceleration on the z axis
+ *
+ * For phones held in portrait mode and game controllers held in front of you,
+ * the axes are defined as follows:
+ * -X ... +X : left ... right
+ * -Y ... +Y : bottom ... top
+ * -Z ... +Z : farther ... closer
+ *
+ * The axis data is not changed when the phone is rotated.
+ *
+ * \sa SDL_GetDisplayOrientation()
+ */
+#define SDL_STANDARD_GRAVITY 9.80665f
+
+/**
+ * Gyroscope sensor
+ *
+ * The gyroscope returns the current rate of rotation in radians per second.
+ * The rotation is positive in the counter-clockwise direction. That is,
+ * an observer looking from a positive location on one of the axes would
+ * see positive rotation on that axis when it appeared to be rotating
+ * counter-clockwise.
+ *
+ * values[0]: Angular speed around the x axis (pitch)
+ * values[1]: Angular speed around the y axis (yaw)
+ * values[2]: Angular speed around the z axis (roll)
+ *
+ * For phones held in portrait mode and game controllers held in front of you,
+ * the axes are defined as follows:
+ * -X ... +X : left ... right
+ * -Y ... +Y : bottom ... top
+ * -Z ... +Z : farther ... closer
+ *
+ * The axis data is not changed when the phone or controller is rotated.
+ *
+ * \sa SDL_GetDisplayOrientation()
+ */
+
+/* Function prototypes */
+
+/**
+ * Locking for multi-threaded access to the sensor API
+ *
+ * If you are using the sensor API or handling events from multiple threads
+ * you should use these locking functions to protect access to the sensors.
+ *
+ * In particular, you are guaranteed that the sensor list won't change, so the
+ * API functions that take a sensor index will be valid, and sensor events
+ * will not be delivered.
+ */
+extern DECLSPEC void SDLCALL SDL_LockSensors(void);
+extern DECLSPEC void SDLCALL SDL_UnlockSensors(void);
+
+/**
+ * Count the number of sensors attached to the system right now.
+ *
+ * \returns the number of sensors detected.
+ */
+extern DECLSPEC int SDLCALL SDL_NumSensors(void);
+
+/**
+ * Get the implementation dependent name of a sensor.
+ *
+ * \param device_index The sensor to obtain name from
+ * \returns the sensor name, or NULL if `device_index` is out of range.
+ */
+extern DECLSPEC const char *SDLCALL SDL_SensorGetDeviceName(int device_index);
+
+/**
+ * Get the type of a sensor.
+ *
+ * \param device_index The sensor to get the type from
+ * \returns the SDL_SensorType, or `SDL_SENSOR_INVALID` if `device_index` is
+ * out of range.
+ */
+extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetDeviceType(int device_index);
+
+/**
+ * Get the platform dependent type of a sensor.
+ *
+ * \param device_index The sensor to check
+ * \returns the sensor platform dependent type, or -1 if `device_index` is out
+ * of range.
+ */
+extern DECLSPEC int SDLCALL SDL_SensorGetDeviceNonPortableType(int device_index);
+
+/**
+ * Get the instance ID of a sensor.
+ *
+ * \param device_index The sensor to get instance id from
+ * \returns the sensor instance ID, or -1 if `device_index` is out of range.
+ */
+extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetDeviceInstanceID(int device_index);
+
+/**
+ * Open a sensor for use.
+ *
+ * \param device_index The sensor to open
+ * \returns an SDL_Sensor sensor object, or NULL if an error occurred.
+ */
+extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorOpen(int device_index);
+
+/**
+ * Return the SDL_Sensor associated with an instance id.
+ *
+ * \param instance_id The sensor from instance id
+ * \returns an SDL_Sensor object.
+ */
+extern DECLSPEC SDL_Sensor *SDLCALL SDL_SensorFromInstanceID(SDL_SensorID instance_id);
+
+/**
+ * Get the implementation dependent name of a sensor
+ *
+ * \param sensor The SDL_Sensor object
+ * \returns the sensor name, or NULL if `sensor` is NULL.
+ */
+extern DECLSPEC const char *SDLCALL SDL_SensorGetName(SDL_Sensor *sensor);
+
+/**
+ * Get the type of a sensor.
+ *
+ * \param sensor The SDL_Sensor object to inspect
+ * \returns the SDL_SensorType type, or `SDL_SENSOR_INVALID` if `sensor` is
+ * NULL.
+ */
+extern DECLSPEC SDL_SensorType SDLCALL SDL_SensorGetType(SDL_Sensor *sensor);
+
+/**
+ * Get the platform dependent type of a sensor.
+ *
+ * \param sensor The SDL_Sensor object to inspect
+ * \returns the sensor platform dependent type, or -1 if `sensor` is NULL.
+ */
+extern DECLSPEC int SDLCALL SDL_SensorGetNonPortableType(SDL_Sensor *sensor);
+
+/**
+ * Get the instance ID of a sensor.
+ *
+ * \param sensor The SDL_Sensor object to inspect
+ * \returns the sensor instance ID, or -1 if `sensor` is NULL.
+ */
+extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetInstanceID(SDL_Sensor *sensor);
+
+/**
+ * Get the current state of an opened sensor.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ *
+ * \param sensor The SDL_Sensor object to query
+ * \param data A pointer filled with the current sensor state
+ * \param num_values The number of values to write to data
+ * \returns 0 or -1 if an error occurred.
+ */
+extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values);
+
+/**
+ * Close a sensor previously opened with SDL_SensorOpen().
+ *
+ * \param sensor The SDL_Sensor object to close
+ */
+extern DECLSPEC void SDLCALL SDL_SensorClose(SDL_Sensor * sensor);
+
+/**
+ * Update the current state of the open sensors.
+ *
+ * This is called automatically by the event loop if sensor events are
+ * enabled.
+ *
+ * This needs to be called from the thread that initialized the sensor
+ * subsystem.
+ */
+extern DECLSPEC void SDLCALL SDL_SensorUpdate(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#include "close_code.h"
+
+#endif /* SDL_sensor_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_shape.h b/Client/ThirdParty/SDL2/include/SDL_shape.h
new file mode 100644
index 0000000..8903e04
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_shape.h
@@ -0,0 +1,147 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_shape_h_
+#define SDL_shape_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_surface.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file SDL_shape.h
+ *
+ * Header file for the shaped window API.
+ */
+
+#define SDL_NONSHAPEABLE_WINDOW -1
+#define SDL_INVALID_SHAPE_ARGUMENT -2
+#define SDL_WINDOW_LACKS_SHAPE -3
+
+/**
+ * Create a window that can be shaped with the specified position, dimensions,
+ * and flags.
+ *
+ * \param title The title of the window, in UTF-8 encoding.
+ * \param x The x position of the window, ::SDL_WINDOWPOS_CENTERED, or
+ * ::SDL_WINDOWPOS_UNDEFINED.
+ * \param y The y position of the window, ::SDL_WINDOWPOS_CENTERED, or
+ * ::SDL_WINDOWPOS_UNDEFINED.
+ * \param w The width of the window.
+ * \param h The height of the window.
+ * \param flags The flags for the window, a mask of SDL_WINDOW_BORDERLESS with
+ * any of the following: ::SDL_WINDOW_OPENGL,
+ * ::SDL_WINDOW_INPUT_GRABBED, ::SDL_WINDOW_HIDDEN,
+ * ::SDL_WINDOW_RESIZABLE, ::SDL_WINDOW_MAXIMIZED,
+ * ::SDL_WINDOW_MINIMIZED, ::SDL_WINDOW_BORDERLESS is always set,
+ * and ::SDL_WINDOW_FULLSCREEN is always unset.
+ * \return the window created, or NULL if window creation failed.
+ *
+ * \sa SDL_DestroyWindow
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_CreateShapedWindow(const char *title,unsigned int x,unsigned int y,unsigned int w,unsigned int h,Uint32 flags);
+
+/**
+ * Return whether the given window is a shaped window.
+ *
+ * \param window The window to query for being shaped.
+ * \return SDL_TRUE if the window is a window that can be shaped, SDL_FALSE if
+ * the window is unshaped or NULL.
+ *
+ * \sa SDL_CreateShapedWindow
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsShapedWindow(const SDL_Window *window);
+
+/** \brief An enum denoting the specific type of contents present in an SDL_WindowShapeParams union. */
+typedef enum {
+ /** \brief The default mode, a binarized alpha cutoff of 1. */
+ ShapeModeDefault,
+ /** \brief A binarized alpha cutoff with a given integer value. */
+ ShapeModeBinarizeAlpha,
+ /** \brief A binarized alpha cutoff with a given integer value, but with the opposite comparison. */
+ ShapeModeReverseBinarizeAlpha,
+ /** \brief A color key is applied. */
+ ShapeModeColorKey
+} WindowShapeMode;
+
+#define SDL_SHAPEMODEALPHA(mode) (mode == ShapeModeDefault || mode == ShapeModeBinarizeAlpha || mode == ShapeModeReverseBinarizeAlpha)
+
+/** \brief A union containing parameters for shaped windows. */
+typedef union {
+ /** \brief A cutoff alpha value for binarization of the window shape's alpha channel. */
+ Uint8 binarizationCutoff;
+ SDL_Color colorKey;
+} SDL_WindowShapeParams;
+
+/** \brief A struct that tags the SDL_WindowShapeParams union with an enum describing the type of its contents. */
+typedef struct SDL_WindowShapeMode {
+ /** \brief The mode of these window-shape parameters. */
+ WindowShapeMode mode;
+ /** \brief Window-shape parameters. */
+ SDL_WindowShapeParams parameters;
+} SDL_WindowShapeMode;
+
+/**
+ * Set the shape and parameters of a shaped window.
+ *
+ * \param window The shaped window whose parameters should be set.
+ * \param shape A surface encoding the desired shape for the window.
+ * \param shape_mode The parameters to set for the shaped window.
+ * \return 0 on success, SDL_INVALID_SHAPE_ARGUMENT on an invalid shape
+ * argument, or SDL_NONSHAPEABLE_WINDOW if the SDL_Window given does
+ * not reference a valid shaped window.
+ *
+ * \sa SDL_WindowShapeMode
+ * \sa SDL_GetShapedWindowMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode);
+
+/**
+ * Get the shape parameters of a shaped window.
+ *
+ * \param window The shaped window whose parameters should be retrieved.
+ * \param shape_mode An empty shape-mode structure to fill, or NULL to check
+ * whether the window has a shape.
+ * \return 0 if the window has a shape and, provided shape_mode was not NULL,
+ * shape_mode has been filled with the mode data,
+ * SDL_NONSHAPEABLE_WINDOW if the SDL_Window given is not a shaped
+ * window, or SDL_WINDOW_LACKS_SHAPE if the SDL_Window given is a
+ * shapeable window currently lacking a shape.
+ *
+ * \sa SDL_WindowShapeMode
+ * \sa SDL_SetWindowShape
+ */
+extern DECLSPEC int SDLCALL SDL_GetShapedWindowMode(SDL_Window *window,SDL_WindowShapeMode *shape_mode);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_shape_h_ */
diff --git a/Client/ThirdParty/SDL2/include/SDL_stdinc.h b/Client/ThirdParty/SDL2/include/SDL_stdinc.h
new file mode 100644
index 0000000..f64219d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_stdinc.h
@@ -0,0 +1,694 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_stdinc.h
+ *
+ * This is a general header that includes C language support.
+ */
+
+#ifndef SDL_stdinc_h_
+#define SDL_stdinc_h_
+
+#include "SDL_config.h"
+
+#ifdef __APPLE__
+#ifndef _DARWIN_C_SOURCE
+#define _DARWIN_C_SOURCE 1 /* for memset_pattern4() */
+#endif
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if defined(STDC_HEADERS)
+# include <stdlib.h>
+# include <stddef.h>
+# include <stdarg.h>
+#else
+# if defined(HAVE_STDLIB_H)
+# include <stdlib.h>
+# elif defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# endif
+# if defined(HAVE_STDDEF_H)
+# include <stddef.h>
+# endif
+# if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+#if defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+# include <stdint.h>
+#endif
+#ifdef HAVE_CTYPE_H
+# include <ctype.h>
+#endif
+#ifdef HAVE_MATH_H
+# if defined(__WINRT__)
+/* Defining _USE_MATH_DEFINES is required to get M_PI to be defined on
+ WinRT. See http://msdn.microsoft.com/en-us/library/4hwaceh6.aspx
+ for more information.
+*/
+# define _USE_MATH_DEFINES
+# endif
+# include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+# include <float.h>
+#endif
+#if defined(HAVE_ALLOCA) && !defined(alloca)
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# elif defined(__GNUC__)
+# define alloca __builtin_alloca
+# elif defined(_MSC_VER)
+# include <malloc.h>
+# define alloca _alloca
+# elif defined(__WATCOMC__)
+# include <malloc.h>
+# elif defined(__BORLANDC__)
+# include <malloc.h>
+# elif defined(__DMC__)
+# include <stdlib.h>
+# elif defined(__AIX__)
+#pragma alloca
+# elif defined(__MRC__)
+void *alloca(unsigned);
+# else
+char *alloca();
+# endif
+#endif
+
+/**
+ * The number of elements in an array.
+ */
+#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0]))
+#define SDL_TABLESIZE(table) SDL_arraysize(table)
+
+/**
+ * Macro useful for building other macros with strings in them
+ *
+ * e.g. #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n")
+ */
+#define SDL_STRINGIFY_ARG(arg) #arg
+
+/**
+ * \name Cast operators
+ *
+ * Use proper C++ casts when compiled as C++ to be compatible with the option
+ * -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above).
+ */
+/* @{ */
+#ifdef __cplusplus
+#define SDL_reinterpret_cast(type, expression) reinterpret_cast<type>(expression)
+#define SDL_static_cast(type, expression) static_cast<type>(expression)
+#define SDL_const_cast(type, expression) const_cast<type>(expression)
+#else
+#define SDL_reinterpret_cast(type, expression) ((type)(expression))
+#define SDL_static_cast(type, expression) ((type)(expression))
+#define SDL_const_cast(type, expression) ((type)(expression))
+#endif
+/* @} *//* Cast operators */
+
+/* Define a four character code as a Uint32 */
+#define SDL_FOURCC(A, B, C, D) \
+ ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \
+ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24))
+
+/**
+ * \name Basic data types
+ */
+/* @{ */
+
+#ifdef __CC_ARM
+/* ARM's compiler throws warnings if we use an enum: like "SDL_bool x = a < b;" */
+#define SDL_FALSE 0
+#define SDL_TRUE 1
+typedef int SDL_bool;
+#else
+typedef enum
+{
+ SDL_FALSE = 0,
+ SDL_TRUE = 1
+} SDL_bool;
+#endif
+
+/**
+ * \brief A signed 8-bit integer type.
+ */
+#define SDL_MAX_SINT8 ((Sint8)0x7F) /* 127 */
+#define SDL_MIN_SINT8 ((Sint8)(~0x7F)) /* -128 */
+typedef int8_t Sint8;
+/**
+ * \brief An unsigned 8-bit integer type.
+ */
+#define SDL_MAX_UINT8 ((Uint8)0xFF) /* 255 */
+#define SDL_MIN_UINT8 ((Uint8)0x00) /* 0 */
+typedef uint8_t Uint8;
+/**
+ * \brief A signed 16-bit integer type.
+ */
+#define SDL_MAX_SINT16 ((Sint16)0x7FFF) /* 32767 */
+#define SDL_MIN_SINT16 ((Sint16)(~0x7FFF)) /* -32768 */
+typedef int16_t Sint16;
+/**
+ * \brief An unsigned 16-bit integer type.
+ */
+#define SDL_MAX_UINT16 ((Uint16)0xFFFF) /* 65535 */
+#define SDL_MIN_UINT16 ((Uint16)0x0000) /* 0 */
+typedef uint16_t Uint16;
+/**
+ * \brief A signed 32-bit integer type.
+ */
+#define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) /* 2147483647 */
+#define SDL_MIN_SINT32 ((Sint32)(~0x7FFFFFFF)) /* -2147483648 */
+typedef int32_t Sint32;
+/**
+ * \brief An unsigned 32-bit integer type.
+ */
+#define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu) /* 4294967295 */
+#define SDL_MIN_UINT32 ((Uint32)0x00000000) /* 0 */
+typedef uint32_t Uint32;
+
+/**
+ * \brief A signed 64-bit integer type.
+ */
+#define SDL_MAX_SINT64 ((Sint64)0x7FFFFFFFFFFFFFFFll) /* 9223372036854775807 */
+#define SDL_MIN_SINT64 ((Sint64)(~0x7FFFFFFFFFFFFFFFll)) /* -9223372036854775808 */
+typedef int64_t Sint64;
+/**
+ * \brief An unsigned 64-bit integer type.
+ */
+#define SDL_MAX_UINT64 ((Uint64)0xFFFFFFFFFFFFFFFFull) /* 18446744073709551615 */
+#define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */
+typedef uint64_t Uint64;
+
+/* @} *//* Basic data types */
+
+/* Make sure we have macros for printing width-based integers.
+ * <stdint.h> should define these but this is not true all platforms.
+ * (for example win32) */
+#ifndef SDL_PRIs64
+#ifdef PRIs64
+#define SDL_PRIs64 PRIs64
+#elif defined(__WIN32__)
+#define SDL_PRIs64 "I64d"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIs64 "ld"
+#else
+#define SDL_PRIs64 "lld"
+#endif
+#endif
+#ifndef SDL_PRIu64
+#ifdef PRIu64
+#define SDL_PRIu64 PRIu64
+#elif defined(__WIN32__)
+#define SDL_PRIu64 "I64u"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIu64 "lu"
+#else
+#define SDL_PRIu64 "llu"
+#endif
+#endif
+#ifndef SDL_PRIx64
+#ifdef PRIx64
+#define SDL_PRIx64 PRIx64
+#elif defined(__WIN32__)
+#define SDL_PRIx64 "I64x"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIx64 "lx"
+#else
+#define SDL_PRIx64 "llx"
+#endif
+#endif
+#ifndef SDL_PRIX64
+#ifdef PRIX64
+#define SDL_PRIX64 PRIX64
+#elif defined(__WIN32__)
+#define SDL_PRIX64 "I64X"
+#elif defined(__LINUX__) && defined(__LP64__)
+#define SDL_PRIX64 "lX"
+#else
+#define SDL_PRIX64 "llX"
+#endif
+#endif
+#ifndef SDL_PRIs32
+#ifdef PRId32
+#define SDL_PRIs32 PRId32
+#else
+#define SDL_PRIs32 "d"
+#endif
+#endif
+#ifndef SDL_PRIu32
+#ifdef PRIu32
+#define SDL_PRIu32 PRIu32
+#else
+#define SDL_PRIu32 "u"
+#endif
+#endif
+#ifndef SDL_PRIx32
+#ifdef PRIx32
+#define SDL_PRIx32 PRIx32
+#else
+#define SDL_PRIx32 "x"
+#endif
+#endif
+#ifndef SDL_PRIX32
+#ifdef PRIX32
+#define SDL_PRIX32 PRIX32
+#else
+#define SDL_PRIX32 "X"
+#endif
+#endif
+
+/* Annotations to help code analysis tools */
+#ifdef SDL_DISABLE_ANALYZE_MACROS
+#define SDL_IN_BYTECAP(x)
+#define SDL_INOUT_Z_CAP(x)
+#define SDL_OUT_Z_CAP(x)
+#define SDL_OUT_CAP(x)
+#define SDL_OUT_BYTECAP(x)
+#define SDL_OUT_Z_BYTECAP(x)
+#define SDL_PRINTF_FORMAT_STRING
+#define SDL_SCANF_FORMAT_STRING
+#define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#else
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */
+#include <sal.h>
+
+#define SDL_IN_BYTECAP(x) _In_bytecount_(x)
+#define SDL_INOUT_Z_CAP(x) _Inout_z_cap_(x)
+#define SDL_OUT_Z_CAP(x) _Out_z_cap_(x)
+#define SDL_OUT_CAP(x) _Out_cap_(x)
+#define SDL_OUT_BYTECAP(x) _Out_bytecap_(x)
+#define SDL_OUT_Z_BYTECAP(x) _Out_z_bytecap_(x)
+
+#define SDL_PRINTF_FORMAT_STRING _Printf_format_string_
+#define SDL_SCANF_FORMAT_STRING _Scanf_format_string_impl_
+#else
+#define SDL_IN_BYTECAP(x)
+#define SDL_INOUT_Z_CAP(x)
+#define SDL_OUT_Z_CAP(x)
+#define SDL_OUT_CAP(x)
+#define SDL_OUT_BYTECAP(x)
+#define SDL_OUT_Z_BYTECAP(x)
+#define SDL_PRINTF_FORMAT_STRING
+#define SDL_SCANF_FORMAT_STRING
+#endif
+#if defined(__GNUC__)
+#define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 )))
+#define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 )))
+#else
+#define SDL_PRINTF_VARARG_FUNC( fmtargnumber )
+#define SDL_SCANF_VARARG_FUNC( fmtargnumber )
+#endif
+#endif /* SDL_DISABLE_ANALYZE_MACROS */
+
+#define SDL_COMPILE_TIME_ASSERT(name, x) \
+ typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1]
+/** \cond */
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1);
+SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1);
+SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2);
+SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2);
+SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4);
+SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4);
+SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8);
+SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
+#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
+/** \endcond */
+
+/* Check to make sure enums are the size of ints, for structure packing.
+ For both Watcom C/C++ and Borland C/C++ the compiler option that makes
+ enums having the size of an int must be enabled.
+ This is "-b" for Borland C/C++ and "-ei" for Watcom C/C++ (v11).
+*/
+
+/** \cond */
+#ifndef DOXYGEN_SHOULD_IGNORE_THIS
+#if !defined(__ANDROID__) && !defined(__VITA__)
+ /* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */
+typedef enum
+{
+ DUMMY_ENUM_VALUE
+} SDL_DUMMY_ENUM;
+
+SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int));
+#endif
+#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
+/** \endcond */
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_ALLOCA
+#define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count))
+#define SDL_stack_free(data)
+#else
+#define SDL_stack_alloc(type, count) (type*)SDL_malloc(sizeof(type)*(count))
+#define SDL_stack_free(data) SDL_free(data)
+#endif
+
+extern DECLSPEC void *SDLCALL SDL_malloc(size_t size);
+extern DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size);
+extern DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size);
+extern DECLSPEC void SDLCALL SDL_free(void *mem);
+
+typedef void *(SDLCALL *SDL_malloc_func)(size_t size);
+typedef void *(SDLCALL *SDL_calloc_func)(size_t nmemb, size_t size);
+typedef void *(SDLCALL *SDL_realloc_func)(void *mem, size_t size);
+typedef void (SDLCALL *SDL_free_func)(void *mem);
+
+/**
+ * Get the current set of SDL memory functions
+ */
+extern DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func,
+ SDL_calloc_func *calloc_func,
+ SDL_realloc_func *realloc_func,
+ SDL_free_func *free_func);
+
+/**
+ * Replace SDL's memory allocation functions with a custom set
+ */
+extern DECLSPEC int SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func,
+ SDL_calloc_func calloc_func,
+ SDL_realloc_func realloc_func,
+ SDL_free_func free_func);
+
+/**
+ * Get the number of outstanding (unfreed) allocations
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAllocations(void);
+
+extern DECLSPEC char *SDLCALL SDL_getenv(const char *name);
+extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite);
+
+extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, const void *));
+
+extern DECLSPEC int SDLCALL SDL_abs(int x);
+
+/* !!! FIXME: these have side effects. You probably shouldn't use them. */
+/* !!! FIXME: Maybe we do forceinline functions of SDL_mini, SDL_minf, etc? */
+#define SDL_min(x, y) (((x) < (y)) ? (x) : (y))
+#define SDL_max(x, y) (((x) > (y)) ? (x) : (y))
+
+extern DECLSPEC int SDLCALL SDL_isalpha(int x);
+extern DECLSPEC int SDLCALL SDL_isalnum(int x);
+extern DECLSPEC int SDLCALL SDL_isblank(int x);
+extern DECLSPEC int SDLCALL SDL_iscntrl(int x);
+extern DECLSPEC int SDLCALL SDL_isdigit(int x);
+extern DECLSPEC int SDLCALL SDL_isxdigit(int x);
+extern DECLSPEC int SDLCALL SDL_ispunct(int x);
+extern DECLSPEC int SDLCALL SDL_isspace(int x);
+extern DECLSPEC int SDLCALL SDL_isupper(int x);
+extern DECLSPEC int SDLCALL SDL_islower(int x);
+extern DECLSPEC int SDLCALL SDL_isprint(int x);
+extern DECLSPEC int SDLCALL SDL_isgraph(int x);
+extern DECLSPEC int SDLCALL SDL_toupper(int x);
+extern DECLSPEC int SDLCALL SDL_tolower(int x);
+
+extern DECLSPEC Uint32 SDLCALL SDL_crc32(Uint32 crc, const void *data, size_t len);
+
+extern DECLSPEC void *SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len);
+
+#define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x)))
+#define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x)))
+#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x)))
+
+/* Note that memset() is a byte assignment and this is a 32-bit assignment, so they're not directly equivalent. */
+SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
+{
+#ifdef __APPLE__
+ memset_pattern4(dst, &val, dwords * 4);
+#elif defined(__GNUC__) && defined(__i386__)
+ int u0, u1, u2;
+ __asm__ __volatile__ (
+ "cld \n\t"
+ "rep ; stosl \n\t"
+ : "=&D" (u0), "=&a" (u1), "=&c" (u2)
+ : "0" (dst), "1" (val), "2" (SDL_static_cast(Uint32, dwords))
+ : "memory"
+ );
+#else
+ size_t _n = (dwords + 3) / 4;
+ Uint32 *_p = SDL_static_cast(Uint32 *, dst);
+ Uint32 _val = (val);
+ if (dwords == 0) {
+ return;
+ }
+
+ /* !!! FIXME: there are better ways to do this, but this is just to clean this up for now. */
+ #ifdef __clang__
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+ #endif
+
+ switch (dwords % 4) {
+ case 0: do { *_p++ = _val; /* fallthrough */
+ case 3: *_p++ = _val; /* fallthrough */
+ case 2: *_p++ = _val; /* fallthrough */
+ case 1: *_p++ = _val; /* fallthrough */
+ } while ( --_n );
+ }
+
+ #ifdef __clang__
+ #pragma clang diagnostic pop
+ #endif
+
+#endif
+}
+
+extern DECLSPEC void *SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len);
+
+extern DECLSPEC void *SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len);
+extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len);
+
+extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr);
+extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
+extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen);
+extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr);
+extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle);
+
+extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2);
+extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen);
+extern DECLSPEC int SDLCALL SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2);
+extern DECLSPEC int SDLCALL SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t len);
+
+extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str);
+extern DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen);
+extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes);
+extern DECLSPEC size_t SDLCALL SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen);
+extern DECLSPEC char *SDLCALL SDL_strdup(const char *str);
+extern DECLSPEC char *SDLCALL SDL_strrev(char *str);
+extern DECLSPEC char *SDLCALL SDL_strupr(char *str);
+extern DECLSPEC char *SDLCALL SDL_strlwr(char *str);
+extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c);
+extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c);
+extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle);
+extern DECLSPEC char *SDLCALL SDL_strtokr(char *s1, const char *s2, char **saveptr);
+extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str);
+
+extern DECLSPEC char *SDLCALL SDL_itoa(int value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_uitoa(unsigned int value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_lltoa(Sint64 value, char *str, int radix);
+extern DECLSPEC char *SDLCALL SDL_ulltoa(Uint64 value, char *str, int radix);
+
+extern DECLSPEC int SDLCALL SDL_atoi(const char *str);
+extern DECLSPEC double SDLCALL SDL_atof(const char *str);
+extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base);
+extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base);
+extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *str, char **endp, int base);
+extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *str, char **endp, int base);
+extern DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp);
+
+extern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2);
+extern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen);
+extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2);
+extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len);
+
+extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2);
+extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap);
+extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3);
+extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap);
+
+#ifndef HAVE_M_PI
+#ifndef M_PI
+#define M_PI 3.14159265358979323846264338327950288 /**< pi */
+#endif
+#endif
+
+extern DECLSPEC double SDLCALL SDL_acos(double x);
+extern DECLSPEC float SDLCALL SDL_acosf(float x);
+extern DECLSPEC double SDLCALL SDL_asin(double x);
+extern DECLSPEC float SDLCALL SDL_asinf(float x);
+extern DECLSPEC double SDLCALL SDL_atan(double x);
+extern DECLSPEC float SDLCALL SDL_atanf(float x);
+extern DECLSPEC double SDLCALL SDL_atan2(double x, double y);
+extern DECLSPEC float SDLCALL SDL_atan2f(float x, float y);
+extern DECLSPEC double SDLCALL SDL_ceil(double x);
+extern DECLSPEC float SDLCALL SDL_ceilf(float x);
+extern DECLSPEC double SDLCALL SDL_copysign(double x, double y);
+extern DECLSPEC float SDLCALL SDL_copysignf(float x, float y);
+extern DECLSPEC double SDLCALL SDL_cos(double x);
+extern DECLSPEC float SDLCALL SDL_cosf(float x);
+extern DECLSPEC double SDLCALL SDL_exp(double x);
+extern DECLSPEC float SDLCALL SDL_expf(float x);
+extern DECLSPEC double SDLCALL SDL_fabs(double x);
+extern DECLSPEC float SDLCALL SDL_fabsf(float x);
+extern DECLSPEC double SDLCALL SDL_floor(double x);
+extern DECLSPEC float SDLCALL SDL_floorf(float x);
+extern DECLSPEC double SDLCALL SDL_trunc(double x);
+extern DECLSPEC float SDLCALL SDL_truncf(float x);
+extern DECLSPEC double SDLCALL SDL_fmod(double x, double y);
+extern DECLSPEC float SDLCALL SDL_fmodf(float x, float y);
+extern DECLSPEC double SDLCALL SDL_log(double x);
+extern DECLSPEC float SDLCALL SDL_logf(float x);
+extern DECLSPEC double SDLCALL SDL_log10(double x);
+extern DECLSPEC float SDLCALL SDL_log10f(float x);
+extern DECLSPEC double SDLCALL SDL_pow(double x, double y);
+extern DECLSPEC float SDLCALL SDL_powf(float x, float y);
+extern DECLSPEC double SDLCALL SDL_round(double x);
+extern DECLSPEC float SDLCALL SDL_roundf(float x);
+extern DECLSPEC long SDLCALL SDL_lround(double x);
+extern DECLSPEC long SDLCALL SDL_lroundf(float x);
+extern DECLSPEC double SDLCALL SDL_scalbn(double x, int n);
+extern DECLSPEC float SDLCALL SDL_scalbnf(float x, int n);
+extern DECLSPEC double SDLCALL SDL_sin(double x);
+extern DECLSPEC float SDLCALL SDL_sinf(float x);
+extern DECLSPEC double SDLCALL SDL_sqrt(double x);
+extern DECLSPEC float SDLCALL SDL_sqrtf(float x);
+extern DECLSPEC double SDLCALL SDL_tan(double x);
+extern DECLSPEC float SDLCALL SDL_tanf(float x);
+
+/* The SDL implementation of iconv() returns these error codes */
+#define SDL_ICONV_ERROR (size_t)-1
+#define SDL_ICONV_E2BIG (size_t)-2
+#define SDL_ICONV_EILSEQ (size_t)-3
+#define SDL_ICONV_EINVAL (size_t)-4
+
+/* SDL_iconv_* are now always real symbols/types, not macros or inlined. */
+typedef struct _SDL_iconv_t *SDL_iconv_t;
+extern DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode,
+ const char *fromcode);
+extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd);
+extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf,
+ size_t * inbytesleft, char **outbuf,
+ size_t * outbytesleft);
+/**
+ * This function converts a string between encodings in one pass, returning a
+ * string that must be freed with SDL_free() or NULL on error.
+ */
+extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode,
+ const char *fromcode,
+ const char *inbuf,
+ size_t inbytesleft);
+#define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1)
+
+/* force builds using Clang's static analysis tools to use literal C runtime
+ here, since there are possibly tests that are ineffective otherwise. */
+#if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS)
+
+/* The analyzer knows about strlcpy even when the system doesn't provide it */
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char* dst, const char* src, size_t size);
+#endif
+
+/* The analyzer knows about strlcat even when the system doesn't provide it */
+#ifndef HAVE_STRLCAT
+size_t strlcat(char* dst, const char* src, size_t size);
+#endif
+
+#define SDL_malloc malloc
+#define SDL_calloc calloc
+#define SDL_realloc realloc
+#define SDL_free free
+#define SDL_memset memset
+#define SDL_memcpy memcpy
+#define SDL_memmove memmove
+#define SDL_memcmp memcmp
+#define SDL_strlcpy strlcpy
+#define SDL_strlcat strlcat
+#define SDL_strlen strlen
+#define SDL_wcslen wcslen
+#define SDL_wcslcpy wcslcpy
+#define SDL_wcslcat wcslcat
+#define SDL_strdup strdup
+#define SDL_wcsdup wcsdup
+#define SDL_strchr strchr
+#define SDL_strrchr strrchr
+#define SDL_strstr strstr
+#define SDL_wcsstr wcsstr
+#define SDL_strtokr strtok_r
+#define SDL_strcmp strcmp
+#define SDL_wcscmp wcscmp
+#define SDL_strncmp strncmp
+#define SDL_wcsncmp wcsncmp
+#define SDL_strcasecmp strcasecmp
+#define SDL_strncasecmp strncasecmp
+#define SDL_sscanf sscanf
+#define SDL_vsscanf vsscanf
+#define SDL_snprintf snprintf
+#define SDL_vsnprintf vsnprintf
+#endif
+
+SDL_FORCE_INLINE void *SDL_memcpy4(SDL_OUT_BYTECAP(dwords*4) void *dst, SDL_IN_BYTECAP(dwords*4) const void *src, size_t dwords)
+{
+ return SDL_memcpy(dst, src, dwords * 4);
+}
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_stdinc_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_surface.h b/Client/ThirdParty/SDL2/include/SDL_surface.h
new file mode 100644
index 0000000..5325ed2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_surface.h
@@ -0,0 +1,887 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_surface.h
+ *
+ * Header file for ::SDL_Surface definition and management functions.
+ */
+
+#ifndef SDL_surface_h_
+#define SDL_surface_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_blendmode.h"
+#include "SDL_rwops.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name Surface flags
+ *
+ * These are the currently supported flags for the ::SDL_Surface.
+ *
+ * \internal
+ * Used internally (read-only).
+ */
+/* @{ */
+#define SDL_SWSURFACE 0 /**< Just here for compatibility */
+#define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */
+#define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */
+#define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */
+#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */
+/* @} *//* Surface flags */
+
+/**
+ * Evaluates to true if the surface needs to be locked before access.
+ */
+#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0)
+
+/**
+ * \brief A collection of pixels used in software blitting.
+ *
+ * \note This structure should be treated as read-only, except for \c pixels,
+ * which, if not NULL, contains the raw pixel data for the surface.
+ */
+typedef struct SDL_Surface
+{
+ Uint32 flags; /**< Read-only */
+ SDL_PixelFormat *format; /**< Read-only */
+ int w, h; /**< Read-only */
+ int pitch; /**< Read-only */
+ void *pixels; /**< Read-write */
+
+ /** Application data associated with the surface */
+ void *userdata; /**< Read-write */
+
+ /** information needed for surfaces requiring locks */
+ int locked; /**< Read-only */
+
+ /** list of BlitMap that hold a reference to this surface */
+ void *list_blitmap; /**< Private */
+
+ /** clipping information */
+ SDL_Rect clip_rect; /**< Read-only */
+
+ /** info for fast blit mapping to other surfaces */
+ struct SDL_BlitMap *map; /**< Private */
+
+ /** Reference count -- used when freeing surface */
+ int refcount; /**< Read-mostly */
+} SDL_Surface;
+
+/**
+ * \brief The type of function used for surface blitting functions.
+ */
+typedef int (SDLCALL *SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
+ struct SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * \brief The formula used for converting between YUV and RGB
+ */
+typedef enum
+{
+ SDL_YUV_CONVERSION_JPEG, /**< Full range JPEG */
+ SDL_YUV_CONVERSION_BT601, /**< BT.601 (the default) */
+ SDL_YUV_CONVERSION_BT709, /**< BT.709 */
+ SDL_YUV_CONVERSION_AUTOMATIC /**< BT.601 for SD content, BT.709 for HD content */
+} SDL_YUV_CONVERSION_MODE;
+
+/**
+ * Allocate a new RGB surface.
+ *
+ * If `depth` is 4 or 8 bits, an empty palette is allocated for the surface.
+ * If `depth` is greater than 8 bits, the pixel format is set using the
+ * [RGBA]mask parameters.
+ *
+ * The [RGBA]mask parameters are the bitmasks used to extract that color from
+ * a pixel. For instance, `Rmask` being 0xFF000000 means the red data is
+ * stored in the most significant byte. Using zeros for the RGB masks sets a
+ * default value, based on the depth. For example:
+ *
+ * ```c++
+ * SDL_CreateRGBSurface(0,w,h,32,0,0,0,0);
+ * ```
+ *
+ * However, using zero for the Amask results in an Amask of 0.
+ *
+ * By default surfaces with an alpha mask are set up for blending as with:
+ *
+ * ```c++
+ * SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND)
+ * ```
+ *
+ * You can change this by calling SDL_SetSurfaceBlendMode() and selecting a
+ * different `blendMode`.
+ *
+ * \param flags the flags are unused and should be set to 0
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param Rmask the red mask for the pixels
+ * \param Gmask the green mask for the pixels
+ * \param Bmask the blue mask for the pixels
+ * \param Amask the alpha mask for the pixels
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_CreateRGBSurfaceWithFormat
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface
+ (Uint32 flags, int width, int height, int depth,
+ Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
+
+
+/* !!! FIXME for 2.1: why does this ask for depth? Format provides that. */
+/**
+ * Allocate a new RGB surface with a specific pixel format.
+ *
+ * This function operates mostly like SDL_CreateRGBSurface(), except instead
+ * of providing pixel color masks, you provide it with a predefined format
+ * from SDL_PixelFormatEnum.
+ *
+ * \param flags the flags are unused and should be set to 0
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param format the SDL_PixelFormatEnum for the new surface's pixel format.
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurface
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormat
+ (Uint32 flags, int width, int height, int depth, Uint32 format);
+
+/**
+ * Allocate a new RGB surface with existing pixel data.
+ *
+ * This function operates mostly like SDL_CreateRGBSurface(), except it does
+ * not allocate memory for the pixel data, instead the caller provides an
+ * existing buffer of data for the surface to use.
+ *
+ * No copy is made of the pixel data. Pixel data is not managed automatically;
+ * you must free the surface before you free the pixel data.
+ *
+ * \param pixels a pointer to existing pixel data
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param pitch the pitch of the surface in bytes
+ * \param Rmask the red mask for the pixels
+ * \param Gmask the green mask for the pixels
+ * \param Bmask the blue mask for the pixels
+ * \param Amask the alpha mask for the pixels
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurface
+ * \sa SDL_CreateRGBSurfaceWithFormat
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
+ int width,
+ int height,
+ int depth,
+ int pitch,
+ Uint32 Rmask,
+ Uint32 Gmask,
+ Uint32 Bmask,
+ Uint32 Amask);
+
+/* !!! FIXME for 2.1: why does this ask for depth? Format provides that. */
+/**
+ * Allocate a new RGB surface with with a specific pixel format and existing
+ * pixel data.
+ *
+ * This function operates mostly like SDL_CreateRGBSurfaceFrom(), except
+ * instead of providing pixel color masks, you provide it with a predefined
+ * format from SDL_PixelFormatEnum.
+ *
+ * No copy is made of the pixel data. Pixel data is not managed automatically;
+ * you must free the surface before you free the pixel data.
+ *
+ * \param pixels a pointer to existing pixel data
+ * \param width the width of the surface
+ * \param height the height of the surface
+ * \param depth the depth of the surface in bits
+ * \param pitch the pitch of the surface in bytes
+ * \param format the SDL_PixelFormatEnum for the new surface's pixel format.
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_CreateRGBSurfaceWithFormat
+ * \sa SDL_FreeSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormatFrom
+ (void *pixels, int width, int height, int depth, int pitch, Uint32 format);
+
+/**
+ * Free an RGB surface.
+ *
+ * It is safe to pass NULL to this function.
+ *
+ * \param surface the SDL_Surface to free.
+ *
+ * \sa SDL_CreateRGBSurface
+ * \sa SDL_CreateRGBSurfaceFrom
+ * \sa SDL_LoadBMP
+ * \sa SDL_LoadBMP_RW
+ */
+extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface);
+
+/**
+ * Set the palette used by a surface.
+ *
+ * A single palette can be shared with many surfaces.
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param palette the SDL_Palette structure to use
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface * surface,
+ SDL_Palette * palette);
+
+/**
+ * Set up a surface for directly accessing the pixels.
+ *
+ * Between calls to SDL_LockSurface() / SDL_UnlockSurface(), you can write to
+ * and read from `surface->pixels`, using the pixel format stored in
+ * `surface->format`. Once you are done accessing the surface, you should use
+ * SDL_UnlockSurface() to release it.
+ *
+ * Not all surfaces require locking. If `SDL_MUSTLOCK(surface)` evaluates to
+ * 0, then you can read and write to the surface at any time, and the pixel
+ * format of the surface will not change.
+ *
+ * \param surface the SDL_Surface structure to be locked
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_MUSTLOCK
+ * \sa SDL_UnlockSurface
+ */
+extern DECLSPEC int SDLCALL SDL_LockSurface(SDL_Surface * surface);
+
+/**
+ * Release a surface after directly accessing the pixels.
+ *
+ * \param surface the SDL_Surface structure to be unlocked
+ *
+ * \sa SDL_LockSurface
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface * surface);
+
+/**
+ * Load a BMP image from a seekable SDL data stream.
+ *
+ * The new surface should be freed with SDL_FreeSurface().
+ *
+ * \param src the data stream for the surface
+ * \param freesrc non-zero to close the stream after being read
+ * \returns a pointer to a new SDL_Surface structure or NULL if there was an
+ * error; call SDL_GetError() for more information.
+ *
+ * \sa SDL_FreeSurface
+ * \sa SDL_LoadBMP
+ * \sa SDL_SaveBMP_RW
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops * src,
+ int freesrc);
+
+/**
+ * Load a surface from a file.
+ *
+ * Convenience macro.
+ */
+#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)
+
+/**
+ * Save a surface to a seekable SDL data stream in BMP format.
+ *
+ * Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
+ * BMP directly. Other RGB formats with 8-bit or higher get converted to a
+ * 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
+ * surface before they are saved. YUV and paletted 1-bit and 4-bit formats are
+ * not supported.
+ *
+ * \param surface the SDL_Surface structure containing the image to be saved
+ * \param dst a data stream to save to
+ * \param freedst non-zero to close the stream after being written
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_LoadBMP_RW
+ * \sa SDL_SaveBMP
+ */
+extern DECLSPEC int SDLCALL SDL_SaveBMP_RW
+ (SDL_Surface * surface, SDL_RWops * dst, int freedst);
+
+/**
+ * Save a surface to a file.
+ *
+ * Convenience macro.
+ */
+#define SDL_SaveBMP(surface, file) \
+ SDL_SaveBMP_RW(surface, SDL_RWFromFile(file, "wb"), 1)
+
+/**
+ * Set the RLE acceleration hint for a surface.
+ *
+ * If RLE is enabled, color key and alpha blending blits are much faster, but
+ * the surface must be locked before directly accessing the pixels.
+ *
+ * \param surface the SDL_Surface structure to optimize
+ * \param flag 0 to disable, non-zero to enable RLE acceleration
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_LockSurface
+ * \sa SDL_UnlockSurface
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface * surface,
+ int flag);
+
+/**
+ * Returns whether the surface is RLE enabled
+ *
+ * It is safe to pass a NULL `surface` here; it will return SDL_FALSE.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \returns SDL_TRUE if the surface is RLE enabled, SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetSurfaceRLE
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSurfaceRLE(SDL_Surface * surface);
+
+/**
+ * Set the color key (transparent pixel) in a surface.
+ *
+ * The color key defines a pixel value that will be treated as transparent in
+ * a blit. For example, one can use this to specify that cyan pixels should be
+ * considered transparent, and therefore not rendered.
+ *
+ * It is a pixel of the format used by the surface, as generated by
+ * SDL_MapRGB().
+ *
+ * RLE acceleration can substantially speed up blitting of images with large
+ * horizontal runs of transparent pixels. See SDL_SetSurfaceRLE() for details.
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param flag SDL_TRUE to enable color key, SDL_FALSE to disable color key
+ * \param key the transparent pixel
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_GetColorKey
+ */
+extern DECLSPEC int SDLCALL SDL_SetColorKey(SDL_Surface * surface,
+ int flag, Uint32 key);
+
+/**
+ * Returns whether the surface has a color key
+ *
+ * It is safe to pass a NULL `surface` here; it will return SDL_FALSE.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \return SDL_TRUE if the surface has a color key, SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetColorKey
+ * \sa SDL_GetColorKey
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasColorKey(SDL_Surface * surface);
+
+/**
+ * Get the color key (transparent pixel) for a surface.
+ *
+ * The color key is a pixel of the format used by the surface, as generated by
+ * SDL_MapRGB().
+ *
+ * If the surface doesn't have color key enabled this function returns -1.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param key a pointer filled in with the transparent pixel
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_SetColorKey
+ */
+extern DECLSPEC int SDLCALL SDL_GetColorKey(SDL_Surface * surface,
+ Uint32 * key);
+
+/**
+ * Set an additional color value multiplied into blit operations.
+ *
+ * When this surface is blitted, during the blit operation each source color
+ * channel is modulated by the appropriate color value according to the
+ * following formula:
+ *
+ * `srcC = srcC * (color / 255)`
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param r the red color value multiplied into blit operations
+ * \param g the green color value multiplied into blit operations
+ * \param b the blue color value multiplied into blit operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceColorMod
+ * \sa SDL_SetSurfaceAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface * surface,
+ Uint8 r, Uint8 g, Uint8 b);
+
+
+/**
+ * Get the additional color value multiplied into blit operations.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param r a pointer filled in with the current red color value
+ * \param g a pointer filled in with the current green color value
+ * \param b a pointer filled in with the current blue color value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceAlphaMod
+ * \sa SDL_SetSurfaceColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface * surface,
+ Uint8 * r, Uint8 * g,
+ Uint8 * b);
+
+/**
+ * Set an additional alpha value used in blit operations.
+ *
+ * When this surface is blitted, during the blit operation the source alpha
+ * value is modulated by this alpha value according to the following formula:
+ *
+ * `srcA = srcA * (alpha / 255)`
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param alpha the alpha value multiplied into blit operations
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceAlphaMod
+ * \sa SDL_SetSurfaceColorMod
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface * surface,
+ Uint8 alpha);
+
+/**
+ * Get the additional alpha value used in blit operations.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param alpha a pointer filled in with the current alpha value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceColorMod
+ * \sa SDL_SetSurfaceAlphaMod
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface * surface,
+ Uint8 * alpha);
+
+/**
+ * Set the blend mode used for blit operations.
+ *
+ * To copy a surface to another surface (or texture) without blending with the
+ * existing data, the blendmode of the SOURCE surface should be set to
+ * `SDL_BLENDMODE_NONE`.
+ *
+ * \param surface the SDL_Surface structure to update
+ * \param blendMode the SDL_BlendMode to use for blit blending
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetSurfaceBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface * surface,
+ SDL_BlendMode blendMode);
+
+/**
+ * Get the blend mode used for blit operations.
+ *
+ * \param surface the SDL_Surface structure to query
+ * \param blendMode a pointer filled in with the current SDL_BlendMode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetSurfaceBlendMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface * surface,
+ SDL_BlendMode *blendMode);
+
+/**
+ * Set the clipping rectangle for a surface.
+ *
+ * When `surface` is the destination of a blit, only the area within the clip
+ * rectangle is drawn into.
+ *
+ * Note that blits are automatically clipped to the edges of the source and
+ * destination surfaces.
+ *
+ * \param surface the SDL_Surface structure to be clipped
+ * \param rect the SDL_Rect structure representing the clipping rectangle, or
+ * NULL to disable clipping
+ * \returns SDL_TRUE if the rectangle intersects the surface, otherwise
+ * SDL_FALSE and blits will be completely clipped.
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_GetClipRect
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetClipRect(SDL_Surface * surface,
+ const SDL_Rect * rect);
+
+/**
+ * Get the clipping rectangle for a surface.
+ *
+ * When `surface` is the destination of a blit, only the area within the clip
+ * rectangle is drawn into.
+ *
+ * \param surface the SDL_Surface structure representing the surface to be
+ * clipped
+ * \param rect an SDL_Rect structure filled in with the clipping rectangle for
+ * the surface
+ *
+ * \sa SDL_BlitSurface
+ * \sa SDL_SetClipRect
+ */
+extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface * surface,
+ SDL_Rect * rect);
+
+/*
+ * Creates a new surface identical to the existing surface.
+ *
+ * The returned surface should be freed with SDL_FreeSurface().
+ *
+ * \param surface the surface to duplicate.
+ * \returns a copy of the surface, or NULL on failure; call SDL_GetError() for
+ * more information.
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_DuplicateSurface(SDL_Surface * surface);
+
+/**
+ * Copy an existing surface to a new surface of the specified format.
+ *
+ * This function is used to optimize images for faster *repeat* blitting. This
+ * is accomplished by converting the original and storing the result as a new
+ * surface. The new, optimized surface can then be used as the source for
+ * future blits, making them faster.
+ *
+ * \param src the existing SDL_Surface structure to convert
+ * \param fmt the SDL_PixelFormat structure that the new surface is optimized
+ * for
+ * \param flags the flags are unused and should be set to 0; this is a
+ * leftover from SDL 1.2's API
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocFormat
+ * \sa SDL_ConvertSurfaceFormat
+ * \sa SDL_CreateRGBSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface
+ (SDL_Surface * src, const SDL_PixelFormat * fmt, Uint32 flags);
+
+/**
+ * Copy an existing surface to a new surface of the specified format enum.
+ *
+ * This function operates just like SDL_ConvertSurface(), but accepts an
+ * SDL_PixelFormatEnum value instead of an SDL_PixelFormat structure. As such,
+ * it might be easier to call but it doesn't have access to palette
+ * information for the destination surface, in case that would be important.
+ *
+ * \param src the existing SDL_Surface structure to convert
+ * \param pixel_format the SDL_PixelFormatEnum that the new surface is
+ * optimized for
+ * \param flags the flags are unused and should be set to 0; this is a
+ * leftover from SDL 1.2's API
+ * \returns the new SDL_Surface structure that is created or NULL if it fails;
+ * call SDL_GetError() for more information.
+ *
+ * \sa SDL_AllocFormat
+ * \sa SDL_ConvertSurfaceFormat
+ * \sa SDL_CreateRGBSurface
+ */
+extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat
+ (SDL_Surface * src, Uint32 pixel_format, Uint32 flags);
+
+/**
+ * Copy a block of pixels of one format to another format.
+ *
+ * \param width the width of the block to copy, in pixels
+ * \param height the height of the block to copy, in pixels
+ * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format
+ * \param src a pointer to the source pixels
+ * \param src_pitch the pitch of the block to copy, in bytes
+ * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format
+ * \param dst a pointer to be filled in with new pixel data
+ * \param dst_pitch the pitch of the destination pixels, in bytes
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height,
+ Uint32 src_format,
+ const void * src, int src_pitch,
+ Uint32 dst_format,
+ void * dst, int dst_pitch);
+
+/**
+ * Perform a fast fill of a rectangle with a specific color.
+ *
+ * `color` should be a pixel of the format used by the surface, and can be
+ * generated by SDL_MapRGB() or SDL_MapRGBA(). If the color value contains an
+ * alpha component then the destination is simply filled with that alpha
+ * information, no blending takes place.
+ *
+ * If there is a clip rectangle set on the destination (set via
+ * SDL_SetClipRect()), then this function will fill based on the intersection
+ * of the clip rectangle and `rect`.
+ *
+ * \param dst the SDL_Surface structure that is the drawing target
+ * \param rect the SDL_Rect structure representing the rectangle to fill, or
+ * NULL to fill the entire surface
+ * \param color the color to fill with
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_FillRects
+ */
+extern DECLSPEC int SDLCALL SDL_FillRect
+ (SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);
+
+/**
+ * Perform a fast fill of a set of rectangles with a specific color.
+ *
+ * `color` should be a pixel of the format used by the surface, and can be
+ * generated by SDL_MapRGB() or SDL_MapRGBA(). If the color value contains an
+ * alpha component then the destination is simply filled with that alpha
+ * information, no blending takes place.
+ *
+ * If there is a clip rectangle set on the destination (set via
+ * SDL_SetClipRect()), then this function will fill based on the intersection
+ * of the clip rectangle and `rect`.
+ *
+ * \param dst the SDL_Surface structure that is the drawing target
+ * \param rects an array of SDL_Rects representing the rectangles to fill.
+ * \param count the number of rectangles in the array
+ * \param color the color to fill with
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_FillRect
+ */
+extern DECLSPEC int SDLCALL SDL_FillRects
+ (SDL_Surface * dst, const SDL_Rect * rects, int count, Uint32 color);
+
+/* !!! FIXME: merge this documentation with the wiki */
+/**
+ * Performs a fast blit from the source surface to the destination surface.
+ *
+ * This assumes that the source and destination rectangles are
+ * the same size. If either \c srcrect or \c dstrect are NULL, the entire
+ * surface (\c src or \c dst) is copied. The final blit rectangles are saved
+ * in \c srcrect and \c dstrect after all clipping is performed.
+ *
+ * \returns 0 if the blit is successful, otherwise it returns -1.
+ *
+ * The blit function should not be called on a locked surface.
+ *
+ * The blit semantics for surfaces with and without blending and colorkey
+ * are defined as follows:
+ * \verbatim
+ RGBA->RGB:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source alpha-channel and per-surface alpha)
+ SDL_SRCCOLORKEY ignored.
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy RGB.
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ RGB values of the source color key, ignoring alpha in the
+ comparison.
+
+ RGB->RGBA:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source per-surface alpha)
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy RGB, set destination alpha to source per-surface alpha value.
+ both:
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ source color key.
+
+ RGBA->RGBA:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source alpha-channel and per-surface alpha)
+ SDL_SRCCOLORKEY ignored.
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy all of RGBA to the destination.
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ RGB values of the source color key, ignoring alpha in the
+ comparison.
+
+ RGB->RGB:
+ Source surface blend mode set to SDL_BLENDMODE_BLEND:
+ alpha-blend (using the source per-surface alpha)
+ Source surface blend mode set to SDL_BLENDMODE_NONE:
+ copy RGB.
+ both:
+ if SDL_SRCCOLORKEY set, only copy the pixels matching the
+ source color key.
+ \endverbatim
+ *
+ * You should call SDL_BlitSurface() unless you know exactly how SDL
+ * blitting works internally and how to use the other blit functions.
+ */
+#define SDL_BlitSurface SDL_UpperBlit
+
+/**
+ * Perform a fast blit from the source surface to the destination surface.
+ *
+ * SDL_UpperBlit() has been replaced by SDL_BlitSurface(), which is merely a
+ * macro for this function with a less confusing name.
+ *
+ * \sa SDL_BlitSurface
+ */
+extern DECLSPEC int SDLCALL SDL_UpperBlit
+ (SDL_Surface * src, const SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * Perform low-level surface blitting only.
+ *
+ * This is a semi-private blit function and it performs low-level surface
+ * blitting, assuming the input rectangles have already been clipped.
+ *
+ * Unless you know what you're doing, you should be using SDL_BlitSurface()
+ * instead.
+ *
+ * \param src the SDL_Surface structure to be copied from
+ * \param srcrect the SDL_Rect structure representing the rectangle to be
+ * copied, or NULL to copy the entire surface
+ * \param dst the SDL_Surface structure that is the blit target
+ * \param dstrect the SDL_Rect structure representing the rectangle that is
+ * copied into
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitSurface
+ */
+extern DECLSPEC int SDLCALL SDL_LowerBlit
+ (SDL_Surface * src, SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+
+ /**
+ * Perform a fast, low quality, stretch blit between two surfaces of the
+ * same format.
+ *
+ * Please use SDL_BlitScaled() instead.
+ */
+extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface * src,
+ const SDL_Rect * srcrect,
+ SDL_Surface * dst,
+ const SDL_Rect * dstrect);
+
+/**
+ * Perform bilinear scaling between two surfaces of the same format, 32BPP.
+ */
+extern DECLSPEC int SDLCALL SDL_SoftStretchLinear(SDL_Surface * src,
+ const SDL_Rect * srcrect,
+ SDL_Surface * dst,
+ const SDL_Rect * dstrect);
+
+
+#define SDL_BlitScaled SDL_UpperBlitScaled
+
+/**
+ * Perform a scaled surface copy to a destination surface.
+ *
+ * SDL_UpperBlitScaled() has been replaced by SDL_BlitScaled(), which is
+ * merely a macro for this function with a less confusing name.
+ *
+ * \sa SDL_BlitScaled
+ */
+extern DECLSPEC int SDLCALL SDL_UpperBlitScaled
+ (SDL_Surface * src, const SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * Perform low-level surface scaled blitting only.
+ *
+ * This is a semi-private function and it performs low-level surface blitting,
+ * assuming the input rectangles have already been clipped.
+ *
+ * \param src the SDL_Surface structure to be copied from
+ * \param srcrect the SDL_Rect structure representing the rectangle to be
+ * copied
+ * \param dst the SDL_Surface structure that is the blit target
+ * \param dstrect the SDL_Rect structure representing the rectangle that is
+ * copied into
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_BlitScaled
+ */
+extern DECLSPEC int SDLCALL SDL_LowerBlitScaled
+ (SDL_Surface * src, SDL_Rect * srcrect,
+ SDL_Surface * dst, SDL_Rect * dstrect);
+
+/**
+ * Set the YUV conversion mode
+ */
+extern DECLSPEC void SDLCALL SDL_SetYUVConversionMode(SDL_YUV_CONVERSION_MODE mode);
+
+/**
+ * Get the YUV conversion mode
+ */
+extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionMode(void);
+
+/**
+ * Get the YUV conversion mode, returning the correct mode for the resolution
+ * when the current conversion mode is SDL_YUV_CONVERSION_AUTOMATIC
+ */
+extern DECLSPEC SDL_YUV_CONVERSION_MODE SDLCALL SDL_GetYUVConversionModeForResolution(int width, int height);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_surface_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_system.h b/Client/ThirdParty/SDL2/include/SDL_system.h
new file mode 100644
index 0000000..5f12787
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_system.h
@@ -0,0 +1,475 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_system.h
+ *
+ * Include file for platform specific SDL API functions
+ */
+
+#ifndef SDL_system_h_
+#define SDL_system_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_keyboard.h"
+#include "SDL_render.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Platform specific functions for Windows */
+#ifdef __WIN32__
+
+typedef void (SDLCALL * SDL_WindowsMessageHook)(void *userdata, void *hWnd, unsigned int message, Uint64 wParam, Sint64 lParam);
+
+/**
+ * Set a callback for every Windows message, run before TranslateMessage().
+ *
+ * \param callback The SDL_WindowsMessageHook function to call.
+ * \param userdata a pointer to pass to every iteration of `callback`
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata);
+
+/**
+ * Get the D3D9 adapter index that matches the specified display index.
+ *
+ * The returned adapter index can be passed to `IDirect3D9::CreateDevice` and
+ * controls on which monitor a full screen application will appear.
+ *
+ * \param displayIndex the display index for which to get the D3D9 adapter
+ * index
+ * \returns the D3D9 adapter index on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex( int displayIndex );
+
+typedef struct IDirect3DDevice9 IDirect3DDevice9;
+
+/**
+ * Get the D3D9 device associated with a renderer.
+ *
+ * Once you are done using the device, you should release it to avoid a
+ * resource leak.
+ *
+ * \param renderer the renderer from which to get the associated D3D device
+ * \returns the D3D9 device associated with given renderer or NULL if it is
+ * not a D3D9 renderer; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer);
+
+typedef struct ID3D11Device ID3D11Device;
+
+/**
+ * Get the D3D11 device associated with a renderer.
+ *
+ * Once you are done using the device, you should release it to avoid a
+ * resource leak.
+ *
+ * \param renderer the renderer from which to get the associated D3D11 device
+ * \returns the D3D11 device associated with given renderer or NULL if it is
+ * not a D3D11 renderer; call SDL_GetError() for more information.
+ */
+extern DECLSPEC ID3D11Device* SDLCALL SDL_RenderGetD3D11Device(SDL_Renderer * renderer);
+
+/**
+ * Get the DXGI Adapter and Output indices for the specified display index.
+ *
+ * The DXGI Adapter and Output indices can be passed to `EnumAdapters` and
+ * `EnumOutputs` respectively to get the objects required to create a DX10 or
+ * DX11 device and swap chain.
+ *
+ * Before SDL 2.0.4 this function did not return a value. Since SDL 2.0.4 it
+ * returns an SDL_bool.
+ *
+ * \param displayIndex the display index for which to get both indices
+ * \param adapterIndex a pointer to be filled in with the adapter index
+ * \param outputIndex a pointer to be filled in with the output index
+ * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.2.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo( int displayIndex, int *adapterIndex, int *outputIndex );
+
+#endif /* __WIN32__ */
+
+
+/* Platform specific functions for Linux */
+#ifdef __LINUX__
+
+/**
+ * Sets the UNIX nice value for a thread.
+ *
+ * This uses setpriority() if possible, and RealtimeKit if available.
+ *
+ * \param threadID the Unix thread ID to change priority of.
+ * \param priority The new, Unix-specific, priority value.
+ * \returns 0 on success, or -1 on error.
+ */
+extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority);
+
+#endif /* __LINUX__ */
+
+/* Platform specific functions for iOS */
+#ifdef __IPHONEOS__
+
+#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam)
+extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam);
+
+#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled)
+extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled);
+
+#endif /* __IPHONEOS__ */
+
+
+/* Platform specific functions for Android */
+#ifdef __ANDROID__
+
+/**
+ * Get the Android Java Native Interface Environment of the current thread.
+ *
+ * This is the JNIEnv one needs to access the Java virtual machine from native
+ * code, and is needed for many Android APIs to be usable from C.
+ *
+ * The prototype of the function in SDL's code actually declare a void* return
+ * type, even if the implementation returns a pointer to a JNIEnv. The
+ * rationale being that the SDL headers can avoid including jni.h.
+ *
+ * \returns a pointer to Java native interface object (JNIEnv) to which the
+ * current thread is attached, or 0 on error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetActivity
+ */
+extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(void);
+
+/**
+ * Retrieve the Java instance of the Android activity class.
+ *
+ * The prototype of the function in SDL's code actually declares a void*
+ * return type, even if the implementation returns a jobject. The rationale
+ * being that the SDL headers can avoid including jni.h.
+ *
+ * The jobject returned by the function is a local reference and must be
+ * released by the caller. See the PushLocalFrame() and PopLocalFrame() or
+ * DeleteLocalRef() functions of the Java native interface:
+ *
+ * https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html
+ *
+ * \returns the jobject representing the instance of the Activity class of the
+ * Android application, or NULL on error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetJNIEnv
+ */
+extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void);
+
+/**
+ * Query Android API level of the current device.
+ *
+ * - API level 30: Android 11
+ * - API level 29: Android 10
+ * - API level 28: Android 9
+ * - API level 27: Android 8.1
+ * - API level 26: Android 8.0
+ * - API level 25: Android 7.1
+ * - API level 24: Android 7.0
+ * - API level 23: Android 6.0
+ * - API level 22: Android 5.1
+ * - API level 21: Android 5.0
+ * - API level 20: Android 4.4W
+ * - API level 19: Android 4.4
+ * - API level 18: Android 4.3
+ * - API level 17: Android 4.2
+ * - API level 16: Android 4.1
+ * - API level 15: Android 4.0.3
+ * - API level 14: Android 4.0
+ * - API level 13: Android 3.2
+ * - API level 12: Android 3.1
+ * - API level 11: Android 3.0
+ * - API level 10: Android 2.3.3
+ *
+ * \returns the Android API level.
+ */
+extern DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void);
+
+/**
+ * Query if the application is running on Android TV.
+ *
+ * \returns SDL_TRUE if this is Android TV, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void);
+
+/**
+ * Query if the application is running on a Chromebook.
+ *
+ * \returns SDL_TRUE if this is a Chromebook, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void);
+
+/**
+ * Query if the application is running on a Samsung DeX docking station.
+ *
+ * \returns SDL_TRUE if this is a DeX docking station, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void);
+
+/**
+ * Trigger the Android system back button behavior.
+ */
+extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void);
+
+/**
+ See the official Android developer guide for more information:
+ http://developer.android.com/guide/topics/data/data-storage.html
+*/
+#define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01
+#define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02
+
+/**
+ * Get the path used for internal storage for this application.
+ *
+ * This path is unique to your application and cannot be written to by other
+ * applications.
+ *
+ * Your internal storage path is typically:
+ * `/data/data/your.app.package/files`.
+ *
+ * \returns the path used for internal storage or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetExternalStorageState
+ */
+extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(void);
+
+/**
+ * Get the current state of external storage.
+ *
+ * The current state of external storage, a bitmask of these values:
+ * `SDL_ANDROID_EXTERNAL_STORAGE_READ`, `SDL_ANDROID_EXTERNAL_STORAGE_WRITE`.
+ *
+ * If external storage is currently unavailable, this will return 0.
+ *
+ * \returns the current state of external storage on success or 0 on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetExternalStoragePath
+ */
+extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(void);
+
+/**
+ * Get the path used for external storage for this application.
+ *
+ * This path is unique to your application, but is public and can be written
+ * to by other applications.
+ *
+ * Your external storage path is typically:
+ * `/storage/sdcard0/Android/data/your.app.package/files`.
+ *
+ * \returns the path used for external storage for this application on success
+ * or NULL on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AndroidGetExternalStorageState
+ */
+extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void);
+
+/**
+ * Request permissions at runtime.
+ *
+ * This blocks the calling thread until the permission is granted or denied.
+ *
+ * \param permission The permission to request.
+ * \returns SDL_TRUE if the permission was granted, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AndroidRequestPermission(const char *permission);
+
+/**
+ * Shows an Android toast notification.
+ *
+ * Toasts are a sort of lightweight notification that are unique to Android.
+ *
+ * https://developer.android.com/guide/topics/ui/notifiers/toasts
+ *
+ * Shows toast in UI thread.
+ *
+ * For the `gravity` parameter, choose a value from here, or -1 if you don't
+ * have a preference:
+ *
+ * https://developer.android.com/reference/android/view/Gravity
+ *
+ * \param message text message to be shown
+ * \param duration 0=short, 1=long
+ * \param gravity where the notification should appear on the screen.
+ * \param xoffset set this parameter only when gravity >=0
+ * \param yoffset set this parameter only when gravity >=0
+ * \returns 0 if success, -1 if any error occurs.
+ */
+extern DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset);
+
+#endif /* __ANDROID__ */
+
+/* Platform specific functions for WinRT */
+#ifdef __WINRT__
+
+/**
+ * \brief WinRT / Windows Phone path types
+ */
+typedef enum
+{
+ /** \brief The installed app's root directory.
+ Files here are likely to be read-only. */
+ SDL_WINRT_PATH_INSTALLED_LOCATION,
+
+ /** \brief The app's local data store. Files may be written here */
+ SDL_WINRT_PATH_LOCAL_FOLDER,
+
+ /** \brief The app's roaming data store. Unsupported on Windows Phone.
+ Files written here may be copied to other machines via a network
+ connection.
+ */
+ SDL_WINRT_PATH_ROAMING_FOLDER,
+
+ /** \brief The app's temporary data store. Unsupported on Windows Phone.
+ Files written here may be deleted at any time. */
+ SDL_WINRT_PATH_TEMP_FOLDER
+} SDL_WinRT_Path;
+
+
+/**
+ * \brief WinRT Device Family
+ */
+typedef enum
+{
+ /** \brief Unknown family */
+ SDL_WINRT_DEVICEFAMILY_UNKNOWN,
+
+ /** \brief Desktop family*/
+ SDL_WINRT_DEVICEFAMILY_DESKTOP,
+
+ /** \brief Mobile family (for example smartphone) */
+ SDL_WINRT_DEVICEFAMILY_MOBILE,
+
+ /** \brief XBox family */
+ SDL_WINRT_DEVICEFAMILY_XBOX,
+} SDL_WinRT_DeviceFamily;
+
+
+/**
+ * Retrieve a WinRT defined path on the local file system.
+ *
+ * Not all paths are available on all versions of Windows. This is especially
+ * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path
+ * for more information on which path types are supported where.
+ *
+ * Documentation on most app-specific path types on WinRT can be found on
+ * MSDN, at the URL:
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
+ *
+ * \param pathType the type of path to retrieve, one of SDL_WinRT_Path
+ * \returns a UCS-2 string (16-bit, wide-char) containing the path, or NULL if
+ * the path is not available for any reason; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.3.
+ *
+ * \sa SDL_WinRTGetFSPathUTF8
+ */
+extern DECLSPEC const wchar_t * SDLCALL SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType);
+
+/**
+ * Retrieve a WinRT defined path on the local file system.
+ *
+ * Not all paths are available on all versions of Windows. This is especially
+ * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path
+ * for more information on which path types are supported where.
+ *
+ * Documentation on most app-specific path types on WinRT can be found on
+ * MSDN, at the URL:
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
+ *
+ * \param pathType the type of path to retrieve, one of SDL_WinRT_Path
+ * \returns a UTF-8 string (8-bit, multi-byte) containing the path, or NULL if
+ * the path is not available for any reason; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.3.
+ *
+ * \sa SDL_WinRTGetFSPathUNICODE
+ */
+extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType);
+
+/**
+ * Detects the device family of WinRT plattform at runtime.
+ *
+ * \returns a value from the SDL_WinRT_DeviceFamily enum.
+ */
+extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily();
+
+#endif /* __WINRT__ */
+
+/**
+ * Query if the current device is a tablet.
+ *
+ * If SDL can't determine this, it will return SDL_FALSE.
+ *
+ * \returns SDL_TRUE if the device is a tablet, SDL_FALSE otherwise.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsTablet(void);
+
+/* Functions used by iOS application delegates to notify SDL about state changes */
+extern DECLSPEC void SDLCALL SDL_OnApplicationWillTerminate(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidReceiveMemoryWarning(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationWillResignActive(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidEnterBackground(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationWillEnterForeground(void);
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidBecomeActive(void);
+#ifdef __IPHONEOS__
+extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void);
+#endif
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_system_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_syswm.h b/Client/ThirdParty/SDL2/include/SDL_syswm.h
new file mode 100644
index 0000000..046a096
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_syswm.h
@@ -0,0 +1,378 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_syswm.h
+ *
+ * Include file for SDL custom system window manager hooks.
+ */
+
+#ifndef SDL_syswm_h_
+#define SDL_syswm_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+#include "SDL_version.h"
+
+/**
+ * \brief SDL_syswm.h
+ *
+ * Your application has access to a special type of event ::SDL_SYSWMEVENT,
+ * which contains window-manager specific information and arrives whenever
+ * an unhandled window event occurs. This event is ignored by default, but
+ * you can enable it with SDL_EventState().
+ */
+struct SDL_SysWMinfo;
+
+#if !defined(SDL_PROTOTYPES_ONLY)
+
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX /* don't define min() and max(). */
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_WINRT)
+#include <Inspectable.h>
+#endif
+
+/* This is the structure for custom window manager events */
+#if defined(SDL_VIDEO_DRIVER_X11)
+#if defined(__APPLE__) && defined(__MACH__)
+/* conflicts with Quickdraw.h */
+#define Cursor X11Cursor
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#if defined(__APPLE__) && defined(__MACH__)
+/* matches the re-define above */
+#undef Cursor
+#endif
+
+#endif /* defined(SDL_VIDEO_DRIVER_X11) */
+
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+#include <directfb.h>
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+#ifdef __OBJC__
+@class NSWindow;
+#else
+typedef struct _NSWindow NSWindow;
+#endif
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+#ifdef __OBJC__
+#include <UIKit/UIKit.h>
+#else
+typedef struct _UIWindow UIWindow;
+typedef struct _UIViewController UIViewController;
+#endif
+typedef Uint32 GLuint;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+typedef struct ANativeWindow ANativeWindow;
+typedef void *EGLSurface;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+#include "SDL_egl.h"
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_OS2)
+#define INCL_WIN
+#include <os2.h>
+#endif
+#endif /* SDL_PROTOTYPES_ONLY */
+
+#if defined(SDL_VIDEO_DRIVER_KMSDRM)
+struct gbm_device;
+#endif
+
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(SDL_PROTOTYPES_ONLY)
+/**
+ * These are the various supported windowing subsystems
+ */
+typedef enum
+{
+ SDL_SYSWM_UNKNOWN,
+ SDL_SYSWM_WINDOWS,
+ SDL_SYSWM_X11,
+ SDL_SYSWM_DIRECTFB,
+ SDL_SYSWM_COCOA,
+ SDL_SYSWM_UIKIT,
+ SDL_SYSWM_WAYLAND,
+ SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
+ SDL_SYSWM_WINRT,
+ SDL_SYSWM_ANDROID,
+ SDL_SYSWM_VIVANTE,
+ SDL_SYSWM_OS2,
+ SDL_SYSWM_HAIKU,
+ SDL_SYSWM_KMSDRM
+} SDL_SYSWM_TYPE;
+
+/**
+ * The custom event structure.
+ */
+struct SDL_SysWMmsg
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ struct {
+ HWND hwnd; /**< The window for the message */
+ UINT msg; /**< The type of message */
+ WPARAM wParam; /**< WORD message parameter */
+ LPARAM lParam; /**< LONG message parameter */
+ } win;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ struct {
+ XEvent event;
+ } x11;
+#endif
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ struct {
+ DFBEvent event;
+ } dfb;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ struct
+ {
+ /* Latest version of Xcode clang complains about empty structs in C v. C++:
+ error: empty struct has size 0 in C, size 1 in C++
+ */
+ int dummy;
+ /* No Cocoa window events yet */
+ } cocoa;
+#endif
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+ struct
+ {
+ int dummy;
+ /* No UIKit window events yet */
+ } uikit;
+#endif
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ struct
+ {
+ int dummy;
+ /* No Vivante window events yet */
+ } vivante;
+#endif
+#if defined(SDL_VIDEO_DRIVER_OS2)
+ struct
+ {
+ BOOL fFrame; /**< TRUE if hwnd is a frame window */
+ HWND hwnd; /**< The window receiving the message */
+ ULONG msg; /**< The message identifier */
+ MPARAM mp1; /**< The first first message parameter */
+ MPARAM mp2; /**< The second first message parameter */
+ } os2;
+#endif
+ /* Can't have an empty union */
+ int dummy;
+ } msg;
+};
+
+/**
+ * The custom window manager information structure.
+ *
+ * When this structure is returned, it holds information about which
+ * low level system it is using, and will be one of SDL_SYSWM_TYPE.
+ */
+struct SDL_SysWMinfo
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ struct
+ {
+ HWND window; /**< The window handle */
+ HDC hdc; /**< The window device context */
+ HINSTANCE hinstance; /**< The instance handle */
+ } win;
+#endif
+#if defined(SDL_VIDEO_DRIVER_WINRT)
+ struct
+ {
+ IInspectable * window; /**< The WinRT CoreWindow */
+ } winrt;
+#endif
+#if defined(SDL_VIDEO_DRIVER_X11)
+ struct
+ {
+ Display *display; /**< The X11 display */
+ Window window; /**< The X11 window */
+ } x11;
+#endif
+#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ struct
+ {
+ IDirectFB *dfb; /**< The directfb main interface */
+ IDirectFBWindow *window; /**< The directfb window handle */
+ IDirectFBSurface *surface; /**< The directfb client surface */
+ } dfb;
+#endif
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ struct
+ {
+#if defined(__OBJC__) && defined(__has_feature)
+ #if __has_feature(objc_arc)
+ NSWindow __unsafe_unretained *window; /**< The Cocoa window */
+ #else
+ NSWindow *window; /**< The Cocoa window */
+ #endif
+#else
+ NSWindow *window; /**< The Cocoa window */
+#endif
+ } cocoa;
+#endif
+#if defined(SDL_VIDEO_DRIVER_UIKIT)
+ struct
+ {
+#if defined(__OBJC__) && defined(__has_feature)
+ #if __has_feature(objc_arc)
+ UIWindow __unsafe_unretained *window; /**< The UIKit window */
+ #else
+ UIWindow *window; /**< The UIKit window */
+ #endif
+#else
+ UIWindow *window; /**< The UIKit window */
+#endif
+ GLuint framebuffer; /**< The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */
+ GLuint colorbuffer; /**< The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */
+ GLuint resolveFramebuffer; /**< The Framebuffer Object which holds the resolve color Renderbuffer, when MSAA is used. */
+ } uikit;
+#endif
+#if defined(SDL_VIDEO_DRIVER_WAYLAND)
+ struct
+ {
+ struct wl_display *display; /**< Wayland display */
+ struct wl_surface *surface; /**< Wayland surface */
+ void *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
+ struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */
+ struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */
+ } wl;
+#endif
+#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
+ struct
+ {
+ void *connection; /**< Mir display server connection */
+ void *surface; /**< Mir surface */
+ } mir;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_ANDROID)
+ struct
+ {
+ ANativeWindow *window;
+ EGLSurface surface;
+ } android;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_OS2)
+ struct
+ {
+ HWND hwnd; /**< The window handle */
+ HWND hwndFrame; /**< The frame window handle */
+ } os2;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ struct
+ {
+ EGLNativeDisplayType display;
+ EGLNativeWindowType window;
+ } vivante;
+#endif
+
+#if defined(SDL_VIDEO_DRIVER_KMSDRM)
+ struct
+ {
+ int dev_index; /**< Device index (ex: the X in /dev/dri/cardX) */
+ int drm_fd; /**< DRM FD (unavailable on Vulkan windows) */
+ struct gbm_device *gbm_dev; /**< GBM device (unavailable on Vulkan windows) */
+ } kmsdrm;
+#endif
+
+ /* Make sure this union is always 64 bytes (8 64-bit pointers). */
+ /* Be careful not to overflow this if you add a new target! */
+ Uint8 dummy[64];
+ } info;
+};
+
+#endif /* SDL_PROTOTYPES_ONLY */
+
+typedef struct SDL_SysWMinfo SDL_SysWMinfo;
+
+
+/**
+ * Get driver-specific information about a window.
+ *
+ * You must include SDL_syswm.h for the declaration of SDL_SysWMinfo.
+ *
+ * The caller must initialize the `info` structure's version by using
+ * `SDL_VERSION(&info.version)`, and then this function will fill in the rest
+ * of the structure with information about the given window.
+ *
+ * \param window the window about which information is being requested
+ * \param info an SDL_SysWMinfo structure filled in with window information
+ * \returns SDL_TRUE if the function is implemented and the `version` member
+ * of the `info` struct is valid, or SDL_FALSE if the information
+ * could not be retrieved; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowWMInfo(SDL_Window * window,
+ SDL_SysWMinfo * info);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_syswm_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test.h b/Client/ThirdParty/SDL2/include/SDL_test.h
new file mode 100644
index 0000000..66fde83
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test.h
@@ -0,0 +1,69 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_h_
+#define SDL_test_h_
+
+#include "SDL.h"
+#include "SDL_test_assert.h"
+#include "SDL_test_common.h"
+#include "SDL_test_compare.h"
+#include "SDL_test_crc32.h"
+#include "SDL_test_font.h"
+#include "SDL_test_fuzzer.h"
+#include "SDL_test_harness.h"
+#include "SDL_test_images.h"
+#include "SDL_test_log.h"
+#include "SDL_test_md5.h"
+#include "SDL_test_memory.h"
+#include "SDL_test_random.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global definitions */
+
+/*
+ * Note: Maximum size of SDLTest log message is less than SDL's limit
+ * to ensure we can fit additional information such as the timestamp.
+ */
+#define SDLTEST_MAX_LOGMESSAGE_LENGTH 3584
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_assert.h b/Client/ThirdParty/SDL2/include/SDL_test_assert.h
new file mode 100644
index 0000000..d8e9d7d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_assert.h
@@ -0,0 +1,105 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_assert.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ *
+ * Assert API for test code and test cases
+ *
+ */
+
+#ifndef SDL_test_assert_h_
+#define SDL_test_assert_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Fails the assert.
+ */
+#define ASSERT_FAIL 0
+
+/**
+ * \brief Passes the assert.
+ */
+#define ASSERT_PASS 1
+
+/**
+ * \brief Assert that logs and break execution flow on failures.
+ *
+ * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0).
+ * \param assertDescription Message to log with the assert describing it.
+ */
+void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * \brief Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters.
+ *
+ * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0).
+ * \param assertDescription Message to log with the assert describing it.
+ *
+ * \returns the assertCondition so it can be used to externally to break execution flow if desired.
+ */
+int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * \brief Explicitly pass without checking an assertion condition. Updates assertion counter.
+ *
+ * \param assertDescription Message to log with the assert describing it.
+ */
+void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * \brief Resets the assert summary counters to zero.
+ */
+void SDLTest_ResetAssertSummary(void);
+
+/**
+ * \brief Logs summary of all assertions (total, pass, fail) since last reset as INFO or ERROR.
+ */
+void SDLTest_LogAssertSummary(void);
+
+
+/**
+ * \brief Converts the current assert summary state to a test result.
+ *
+ * \returns TEST_RESULT_PASSED, TEST_RESULT_FAILED, or TEST_RESULT_NO_ASSERT
+ */
+int SDLTest_AssertSummaryToTestResult(void);
+
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_assert_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_common.h b/Client/ThirdParty/SDL2/include/SDL_test_common.h
new file mode 100644
index 0000000..97f036d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_common.h
@@ -0,0 +1,230 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_common.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/* Ported from original test\common.h file. */
+
+#ifndef SDL_test_common_h_
+#define SDL_test_common_h_
+
+#include "SDL.h"
+
+#if defined(__PSP__)
+#define DEFAULT_WINDOW_WIDTH 480
+#define DEFAULT_WINDOW_HEIGHT 272
+#elif defined(__VITA__)
+#define DEFAULT_WINDOW_WIDTH 960
+#define DEFAULT_WINDOW_HEIGHT 544
+#else
+#define DEFAULT_WINDOW_WIDTH 640
+#define DEFAULT_WINDOW_HEIGHT 480
+#endif
+
+#define VERBOSE_VIDEO 0x00000001
+#define VERBOSE_MODES 0x00000002
+#define VERBOSE_RENDER 0x00000004
+#define VERBOSE_EVENT 0x00000008
+#define VERBOSE_AUDIO 0x00000010
+
+typedef struct
+{
+ /* SDL init flags */
+ char **argv;
+ Uint32 flags;
+ Uint32 verbose;
+
+ /* Video info */
+ const char *videodriver;
+ int display;
+ const char *window_title;
+ const char *window_icon;
+ Uint32 window_flags;
+ SDL_bool flash_on_focus_loss;
+ int window_x;
+ int window_y;
+ int window_w;
+ int window_h;
+ int window_minW;
+ int window_minH;
+ int window_maxW;
+ int window_maxH;
+ int logical_w;
+ int logical_h;
+ float scale;
+ int depth;
+ int refresh_rate;
+ int num_windows;
+ SDL_Window **windows;
+
+ /* Renderer info */
+ const char *renderdriver;
+ Uint32 render_flags;
+ SDL_bool skip_renderer;
+ SDL_Renderer **renderers;
+ SDL_Texture **targets;
+
+ /* Audio info */
+ const char *audiodriver;
+ SDL_AudioSpec audiospec;
+
+ /* GL settings */
+ int gl_red_size;
+ int gl_green_size;
+ int gl_blue_size;
+ int gl_alpha_size;
+ int gl_buffer_size;
+ int gl_depth_size;
+ int gl_stencil_size;
+ int gl_double_buffer;
+ int gl_accum_red_size;
+ int gl_accum_green_size;
+ int gl_accum_blue_size;
+ int gl_accum_alpha_size;
+ int gl_stereo;
+ int gl_multisamplebuffers;
+ int gl_multisamplesamples;
+ int gl_retained_backing;
+ int gl_accelerated;
+ int gl_major_version;
+ int gl_minor_version;
+ int gl_debug;
+ int gl_profile_mask;
+} SDLTest_CommonState;
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+/**
+ * \brief Parse command line parameters and create common state.
+ *
+ * \param argv Array of command line parameters
+ * \param flags Flags indicating which subsystem to initialize (i.e. SDL_INIT_VIDEO | SDL_INIT_AUDIO)
+ *
+ * \returns a newly allocated common state object.
+ */
+SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags);
+
+/**
+ * \brief Process one common argument.
+ *
+ * \param state The common state describing the test window to create.
+ * \param index The index of the argument to process in argv[].
+ *
+ * \returns the number of arguments processed (i.e. 1 for --fullscreen, 2 for --video [videodriver], or -1 on error.
+ */
+int SDLTest_CommonArg(SDLTest_CommonState * state, int index);
+
+
+/**
+ * \brief Logs command line usage info.
+ *
+ * This logs the appropriate command line options for the subsystems in use
+ * plus other common options, and then any application-specific options.
+ * This uses the SDL_Log() function and splits up output to be friendly to
+ * 80-character-wide terminals.
+ *
+ * \param state The common state describing the test window for the app.
+ * \param argv0 argv[0], as passed to main/SDL_main.
+ * \param options an array of strings for application specific options. The last element of the array should be NULL.
+ */
+void SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options);
+
+/**
+ * \brief Returns common usage information
+ *
+ * You should (probably) be using SDLTest_CommonLogUsage() instead, but this
+ * function remains for binary compatibility. Strings returned from this
+ * function are valid until SDLTest_CommonQuit() is called, in which case
+ * those strings' memory is freed and can no longer be used.
+ *
+ * \param state The common state describing the test window to create.
+ * \returns a string with usage information
+ */
+const char *SDLTest_CommonUsage(SDLTest_CommonState * state);
+
+/**
+ * \brief Open test window.
+ *
+ * \param state The common state describing the test window to create.
+ *
+ * \returns SDL_TRUE if initialization succeeded, false otherwise
+ */
+SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state);
+
+/**
+ * \brief Easy argument handling when test app doesn't need any custom args.
+ *
+ * \param state The common state describing the test window to create.
+ * \param argc argc, as supplied to SDL_main
+ * \param argv argv, as supplied to SDL_main
+ *
+ * \returns SDL_FALSE if app should quit, true otherwise.
+ */
+SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState * state, const int argc, char **argv);
+
+/**
+ * \brief Common event handler for test windows.
+ *
+ * \param state The common state used to create test window.
+ * \param event The event to handle.
+ * \param done Flag indicating we are done.
+ *
+ */
+void SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done);
+
+/**
+ * \brief Close test window.
+ *
+ * \param state The common state used to create test window.
+ *
+ */
+void SDLTest_CommonQuit(SDLTest_CommonState * state);
+
+/**
+ * \brief Draws various window information (position, size, etc.) to the renderer.
+ *
+ * \param renderer The renderer to draw to.
+ * \param window The window whose information should be displayed.
+ *
+ */
+void SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_common_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_compare.h b/Client/ThirdParty/SDL2/include/SDL_test_compare.h
new file mode 100644
index 0000000..ee42c9d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_compare.h
@@ -0,0 +1,69 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_compare.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Defines comparison functions (i.e. for surfaces).
+
+*/
+
+#ifndef SDL_test_compare_h_
+#define SDL_test_compare_h_
+
+#include "SDL.h"
+
+#include "SDL_test_images.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Compares a surface and with reference image data for equality
+ *
+ * \param surface Surface used in comparison
+ * \param referenceSurface Test Surface used in comparison
+ * \param allowable_error Allowable difference (=sum of squared difference for each RGB component) in blending accuracy.
+ *
+ * \returns 0 if comparison succeeded, >0 (=number of pixels for which the comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ.
+ */
+int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_compare_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_crc32.h b/Client/ThirdParty/SDL2/include/SDL_test_crc32.h
new file mode 100644
index 0000000..f41e24e
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_crc32.h
@@ -0,0 +1,124 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_crc32.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Implements CRC32 calculations (default output is Perl String::CRC32 compatible).
+
+*/
+
+#ifndef SDL_test_crc32_h_
+#define SDL_test_crc32_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ------------ Definitions --------- */
+
+/* Definition shared by all CRC routines */
+
+#ifndef CrcUint32
+ #define CrcUint32 unsigned int
+#endif
+#ifndef CrcUint8
+ #define CrcUint8 unsigned char
+#endif
+
+#ifdef ORIGINAL_METHOD
+ #define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+#else
+ #define CRC32_POLY 0xEDB88320 /* Perl String::CRC32 compatible */
+#endif
+
+/**
+ * Data structure for CRC32 (checksum) computation
+ */
+ typedef struct {
+ CrcUint32 crc32_table[256]; /* CRC table */
+ } SDLTest_Crc32Context;
+
+/* ---------- Function Prototypes ------------- */
+
+/**
+ * \brief Initialize the CRC context
+ *
+ * Note: The function initializes the crc table required for all crc calculations.
+ *
+ * \param crcContext pointer to context variable
+ *
+ * \returns 0 for OK, -1 on error
+ *
+ */
+ int SDLTest_Crc32Init(SDLTest_Crc32Context * crcContext);
+
+
+/**
+ * \brief calculate a crc32 from a data block
+ *
+ * \param crcContext pointer to context variable
+ * \param inBuf input buffer to checksum
+ * \param inLen length of input buffer
+ * \param crc32 pointer to Uint32 to store the final CRC into
+ *
+ * \returns 0 for OK, -1 on error
+ *
+ */
+int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+
+/* Same routine broken down into three steps */
+int SDLTest_Crc32CalcStart(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);
+int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);
+int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+
+
+/**
+ * \brief clean up CRC context
+ *
+ * \param crcContext pointer to context variable
+ *
+ * \returns 0 for OK, -1 on error
+ *
+*/
+
+int SDLTest_Crc32Done(SDLTest_Crc32Context * crcContext);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_crc32_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_font.h b/Client/ThirdParty/SDL2/include/SDL_test_font.h
new file mode 100644
index 0000000..daa6670
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_font.h
@@ -0,0 +1,81 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_font.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_font_h_
+#define SDL_test_font_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+#define FONT_CHARACTER_SIZE 8
+
+/**
+ * \brief Draw a string in the currently set font.
+ *
+ * \param renderer The renderer to draw on.
+ * \param x The X coordinate of the upper left corner of the character.
+ * \param y The Y coordinate of the upper left corner of the character.
+ * \param c The character to draw.
+ *
+ * \returns 0 on success, -1 on failure.
+ */
+int SDLTest_DrawCharacter(SDL_Renderer *renderer, int x, int y, char c);
+
+/**
+ * \brief Draw a string in the currently set font.
+ *
+ * \param renderer The renderer to draw on.
+ * \param x The X coordinate of the upper left corner of the string.
+ * \param y The Y coordinate of the upper left corner of the string.
+ * \param s The string to draw.
+ *
+ * \returns 0 on success, -1 on failure.
+ */
+int SDLTest_DrawString(SDL_Renderer *renderer, int x, int y, const char *s);
+
+
+/**
+ * \brief Cleanup textures used by font drawing functions.
+ */
+void SDLTest_CleanupTextDrawing(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_font_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_fuzzer.h b/Client/ThirdParty/SDL2/include/SDL_test_fuzzer.h
new file mode 100644
index 0000000..84278bf
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_fuzzer.h
@@ -0,0 +1,386 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_fuzzer.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Data generators for fuzzing test data in a reproducible way.
+
+*/
+
+#ifndef SDL_test_fuzzer_h_
+#define SDL_test_fuzzer_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ Based on GSOC code by Markus Kauppila <markus.kauppila@gmail.com>
+*/
+
+
+/**
+ * \file
+ * Note: The fuzzer implementation uses a static instance of random context
+ * internally which makes it thread-UNsafe.
+ */
+
+/**
+ * Initializes the fuzzer for a test
+ *
+ * \param execKey Execution "Key" that initializes the random number generator uniquely for the test.
+ *
+ */
+void SDLTest_FuzzerInit(Uint64 execKey);
+
+
+/**
+ * Returns a random Uint8
+ *
+ * \returns a generated integer
+ */
+Uint8 SDLTest_RandomUint8(void);
+
+/**
+ * Returns a random Sint8
+ *
+ * \returns a generated signed integer
+ */
+Sint8 SDLTest_RandomSint8(void);
+
+
+/**
+ * Returns a random Uint16
+ *
+ * \returns a generated integer
+ */
+Uint16 SDLTest_RandomUint16(void);
+
+/**
+ * Returns a random Sint16
+ *
+ * \returns a generated signed integer
+ */
+Sint16 SDLTest_RandomSint16(void);
+
+
+/**
+ * Returns a random integer
+ *
+ * \returns a generated integer
+ */
+Sint32 SDLTest_RandomSint32(void);
+
+
+/**
+ * Returns a random positive integer
+ *
+ * \returns a generated integer
+ */
+Uint32 SDLTest_RandomUint32(void);
+
+/**
+ * Returns random Uint64.
+ *
+ * \returns a generated integer
+ */
+Uint64 SDLTest_RandomUint64(void);
+
+
+/**
+ * Returns random Sint64.
+ *
+ * \returns a generated signed integer
+ */
+Sint64 SDLTest_RandomSint64(void);
+
+/**
+ * \returns a random float in range [0.0 - 1.0]
+ */
+float SDLTest_RandomUnitFloat(void);
+
+/**
+ * \returns a random double in range [0.0 - 1.0]
+ */
+double SDLTest_RandomUnitDouble(void);
+
+/**
+ * \returns a random float.
+ *
+ */
+float SDLTest_RandomFloat(void);
+
+/**
+ * \returns a random double.
+ *
+ */
+double SDLTest_RandomDouble(void);
+
+/**
+ * Returns a random boundary value for Uint8 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint8BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint8BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint8BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint8BoundaryValue(0, 255, SDL_FALSE) returns 0 (error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Uint16 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint16BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint16BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint16BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint16BoundaryValue(0, 0xFFFF, SDL_FALSE) returns 0 (error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Uint32 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint32BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint32BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint32BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint32BoundaryValue(0, 0xFFFFFFFF, SDL_FALSE) returns 0 (with error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Uint64 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomUint64BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20
+ * RandomUint64BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21
+ * RandomUint64BoundaryValue(0, 99, SDL_FALSE) returns 100
+ * RandomUint64BoundaryValue(0, 0xFFFFFFFFFFFFFFFF, SDL_FALSE) returns 0 (with error set)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or 0 with error set
+ */
+Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Sint8 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint8BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint8BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint8BoundaryValue(SINT8_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint8BoundaryValue(SINT8_MIN, SINT8_MAX, SDL_FALSE) returns SINT8_MIN (== error value) with error set
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT8_MIN with error set
+ */
+Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain);
+
+
+/**
+ * Returns a random boundary value for Sint16 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint16BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint16BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint16BoundaryValue(SINT16_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint16BoundaryValue(SINT16_MIN, SINT16_MAX, SDL_FALSE) returns SINT16_MIN (== error value) with error set
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT16_MIN with error set
+ */
+Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Sint32 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint32BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint32BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint32BoundaryValue(SINT32_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint32BoundaryValue(SINT32_MIN, SINT32_MAX, SDL_FALSE) returns SINT32_MIN (== error value)
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT32_MIN with error set
+ */
+Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain);
+
+/**
+ * Returns a random boundary value for Sint64 within the given boundaries.
+ * Boundaries are inclusive, see the usage examples below. If validDomain
+ * is true, the function will only return valid boundaries, otherwise non-valid
+ * boundaries are also possible.
+ * If boundary1 > boundary2, the values are swapped
+ *
+ * Usage examples:
+ * RandomSint64BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20
+ * RandomSint64BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9
+ * RandomSint64BoundaryValue(SINT64_MIN, 99, SDL_FALSE) returns 100
+ * RandomSint64BoundaryValue(SINT64_MIN, SINT64_MAX, SDL_FALSE) returns SINT64_MIN (== error value) and error set
+ *
+ * \param boundary1 Lower boundary limit
+ * \param boundary2 Upper boundary limit
+ * \param validDomain Should the generated boundary be valid (=within the bounds) or not?
+ *
+ * \returns a random boundary value for the given range and domain or SINT64_MIN with error set
+ */
+Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain);
+
+
+/**
+ * Returns integer in range [min, max] (inclusive).
+ * Min and max values can be negative values.
+ * If Max in smaller than min, then the values are swapped.
+ * Min and max are the same value, that value will be returned.
+ *
+ * \param min Minimum inclusive value of returned random number
+ * \param max Maximum inclusive value of returned random number
+ *
+ * \returns a generated random integer in range
+ */
+Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max);
+
+
+/**
+ * Generates random null-terminated string. The minimum length for
+ * the string is 1 character, maximum length for the string is 255
+ * characters and it can contain ASCII characters from 32 to 126.
+ *
+ * Note: Returned string needs to be deallocated.
+ *
+ * \returns a newly allocated random string; or NULL if length was invalid or string could not be allocated.
+ */
+char * SDLTest_RandomAsciiString(void);
+
+
+/**
+ * Generates random null-terminated string. The maximum length for
+ * the string is defined by the maxLength parameter.
+ * String can contain ASCII characters from 32 to 126.
+ *
+ * Note: Returned string needs to be deallocated.
+ *
+ * \param maxLength The maximum length of the generated string.
+ *
+ * \returns a newly allocated random string; or NULL if maxLength was invalid or string could not be allocated.
+ */
+char * SDLTest_RandomAsciiStringWithMaximumLength(int maxLength);
+
+
+/**
+ * Generates random null-terminated string. The length for
+ * the string is defined by the size parameter.
+ * String can contain ASCII characters from 32 to 126.
+ *
+ * Note: Returned string needs to be deallocated.
+ *
+ * \param size The length of the generated string
+ *
+ * \returns a newly allocated random string; or NULL if size was invalid or string could not be allocated.
+ */
+char * SDLTest_RandomAsciiStringOfSize(int size);
+
+/**
+ * Get the invocation count for the fuzzer since last ...FuzzerInit.
+ *
+ * \returns the invocation count.
+ */
+int SDLTest_GetFuzzerInvocationCount(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_fuzzer_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_harness.h b/Client/ThirdParty/SDL2/include/SDL_test_harness.h
new file mode 100644
index 0000000..106464c
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_harness.h
@@ -0,0 +1,134 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_harness.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ Defines types for test case definitions and the test execution harness API.
+
+ Based on original GSOC code by Markus Kauppila <markus.kauppila@gmail.com>
+*/
+
+#ifndef SDL_test_h_arness_h
+#define SDL_test_h_arness_h
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ! Definitions for test case structures */
+#define TEST_ENABLED 1
+#define TEST_DISABLED 0
+
+/* ! Definition of all the possible test return values of the test case method */
+#define TEST_ABORTED -1
+#define TEST_STARTED 0
+#define TEST_COMPLETED 1
+#define TEST_SKIPPED 2
+
+/* ! Definition of all the possible test results for the harness */
+#define TEST_RESULT_PASSED 0
+#define TEST_RESULT_FAILED 1
+#define TEST_RESULT_NO_ASSERT 2
+#define TEST_RESULT_SKIPPED 3
+#define TEST_RESULT_SETUP_FAILURE 4
+
+/* !< Function pointer to a test case setup function (run before every test) */
+typedef void (*SDLTest_TestCaseSetUpFp)(void *arg);
+
+/* !< Function pointer to a test case function */
+typedef int (*SDLTest_TestCaseFp)(void *arg);
+
+/* !< Function pointer to a test case teardown function (run after every test) */
+typedef void (*SDLTest_TestCaseTearDownFp)(void *arg);
+
+/**
+ * Holds information about a single test case.
+ */
+typedef struct SDLTest_TestCaseReference {
+ /* !< Func2Stress */
+ SDLTest_TestCaseFp testCase;
+ /* !< Short name (or function name) "Func2Stress" */
+ char *name;
+ /* !< Long name or full description "This test pushes func2() to the limit." */
+ char *description;
+ /* !< Set to TEST_ENABLED or TEST_DISABLED (test won't be run) */
+ int enabled;
+} SDLTest_TestCaseReference;
+
+/**
+ * Holds information about a test suite (multiple test cases).
+ */
+typedef struct SDLTest_TestSuiteReference {
+ /* !< "PlatformSuite" */
+ char *name;
+ /* !< The function that is run before each test. NULL skips. */
+ SDLTest_TestCaseSetUpFp testSetUp;
+ /* !< The test cases that are run as part of the suite. Last item should be NULL. */
+ const SDLTest_TestCaseReference **testCases;
+ /* !< The function that is run after each test. NULL skips. */
+ SDLTest_TestCaseTearDownFp testTearDown;
+} SDLTest_TestSuiteReference;
+
+
+/**
+ * \brief Generates a random run seed string for the harness. The generated seed will contain alphanumeric characters (0-9A-Z).
+ *
+ * Note: The returned string needs to be deallocated by the caller.
+ *
+ * \param length The length of the seed string to generate
+ *
+ * \returns the generated seed string
+ */
+char *SDLTest_GenerateRunSeed(const int length);
+
+/**
+ * \brief Execute a test suite using the given run seed and execution key.
+ *
+ * \param testSuites Suites containing the test case.
+ * \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one.
+ * \param userExecKey Custom execution key provided by user, or 0 to autogenerate one.
+ * \param filter Filter specification. NULL disables. Case sensitive.
+ * \param testIterations Number of iterations to run each test case.
+ *
+ * \returns the test run result: 0 when all tests passed, 1 if any tests failed.
+ */
+int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_h_arness_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_images.h b/Client/ThirdParty/SDL2/include/SDL_test_images.h
new file mode 100644
index 0000000..a379cf1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_images.h
@@ -0,0 +1,78 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_images.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ Defines some images for tests.
+
+*/
+
+#ifndef SDL_test_images_h_
+#define SDL_test_images_h_
+
+#include "SDL.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ *Type for test images.
+ */
+typedef struct SDLTest_SurfaceImage_s {
+ int width;
+ int height;
+ unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
+ const char *pixel_data;
+} SDLTest_SurfaceImage_t;
+
+/* Test images */
+SDL_Surface *SDLTest_ImageBlit(void);
+SDL_Surface *SDLTest_ImageBlitColor(void);
+SDL_Surface *SDLTest_ImageBlitAlpha(void);
+SDL_Surface *SDLTest_ImageBlitBlendAdd(void);
+SDL_Surface *SDLTest_ImageBlitBlend(void);
+SDL_Surface *SDLTest_ImageBlitBlendMod(void);
+SDL_Surface *SDLTest_ImageBlitBlendNone(void);
+SDL_Surface *SDLTest_ImageBlitBlendAll(void);
+SDL_Surface *SDLTest_ImageFace(void);
+SDL_Surface *SDLTest_ImagePrimitives(void);
+SDL_Surface *SDLTest_ImagePrimitivesBlend(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_images_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_log.h b/Client/ThirdParty/SDL2/include/SDL_test_log.h
new file mode 100644
index 0000000..0caddca
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_log.h
@@ -0,0 +1,67 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_log.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ *
+ * Wrapper to log in the TEST category
+ *
+ */
+
+#ifndef SDL_test_log_h_
+#define SDL_test_log_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Prints given message with a timestamp in the TEST category and INFO priority.
+ *
+ * \param fmt Message to be logged
+ */
+void SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * \brief Prints given message with a timestamp in the TEST category and the ERROR priority.
+ *
+ * \param fmt Message to be logged
+ */
+void SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_log_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_md5.h b/Client/ThirdParty/SDL2/include/SDL_test_md5.h
new file mode 100644
index 0000000..ca29757
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_md5.h
@@ -0,0 +1,129 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_md5.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+ ***********************************************************************
+ ** Header file for implementation of MD5 **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ ** Revised (for MD5): RLR 4/27/91 **
+ ** -- G modified to have y&~z instead of y&z **
+ ** -- FF, GG, HH modified to add in last register done **
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
+ ** -- distinct additive constant for each step **
+ ** -- round 4 added, working mod 7 **
+ ***********************************************************************
+*/
+
+/*
+ ***********************************************************************
+ ** Message-digest routines: **
+ ** To form the message digest for a message M **
+ ** (1) Initialize a context buffer mdContext using MD5Init **
+ ** (2) Call MD5Update on mdContext and M **
+ ** (3) Call MD5Final on mdContext **
+ ** The message digest is now in mdContext->digest[0...15] **
+ ***********************************************************************
+*/
+
+#ifndef SDL_test_md5_h_
+#define SDL_test_md5_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ------------ Definitions --------- */
+
+/* typedef a 32-bit type */
+ typedef unsigned long int MD5UINT4;
+
+/* Data structure for MD5 (Message-Digest) computation */
+ typedef struct {
+ MD5UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ MD5UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after Md5Final call */
+ } SDLTest_Md5Context;
+
+/* ---------- Function Prototypes ------------- */
+
+/**
+ * \brief initialize the context
+ *
+ * \param mdContext pointer to context variable
+ *
+ * Note: The function initializes the message-digest context
+ * mdContext. Call before each new use of the context -
+ * all fields are set to zero.
+ */
+ void SDLTest_Md5Init(SDLTest_Md5Context * mdContext);
+
+
+/**
+ * \brief update digest from variable length data
+ *
+ * \param mdContext pointer to context variable
+ * \param inBuf pointer to data array/string
+ * \param inLen length of data array/string
+ *
+ * Note: The function updates the message-digest context to account
+ * for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+*/
+
+ void SDLTest_Md5Update(SDLTest_Md5Context * mdContext, unsigned char *inBuf,
+ unsigned int inLen);
+
+
+/**
+ * \brief complete digest computation
+ *
+ * \param mdContext pointer to context variable
+ *
+ * Note: The function terminates the message-digest computation and
+ * ends with the desired message digest in mdContext.digest[0..15].
+ * Always call before using the digest[] variable.
+*/
+
+ void SDLTest_Md5Final(SDLTest_Md5Context * mdContext);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_md5_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_memory.h b/Client/ThirdParty/SDL2/include/SDL_test_memory.h
new file mode 100644
index 0000000..4a19c1d
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_memory.h
@@ -0,0 +1,63 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_memory.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_memory_h_
+#define SDL_test_memory_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief Start tracking SDL memory allocations
+ *
+ * \note This should be called before any other SDL functions for complete tracking coverage
+ */
+int SDLTest_TrackAllocations(void);
+
+/**
+ * \brief Print a log of any outstanding allocations
+ *
+ * \note This can be called after SDL_Quit()
+ */
+void SDLTest_LogAllocations(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_memory_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_test_random.h b/Client/ThirdParty/SDL2/include/SDL_test_random.h
new file mode 100644
index 0000000..8297f94
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_test_random.h
@@ -0,0 +1,115 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_test_random.h
+ *
+ * Include file for SDL test framework.
+ *
+ * This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+/*
+
+ A "32-bit Multiply with carry random number generator. Very fast.
+ Includes a list of recommended multipliers.
+
+ multiply-with-carry generator: x(n) = a*x(n-1) + carry mod 2^32.
+ period: (a*2^31)-1
+
+*/
+
+#ifndef SDL_test_random_h_
+#define SDL_test_random_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* --- Definitions */
+
+/*
+ * Macros that return a random number in a specific format.
+ */
+#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c))
+
+/*
+ * Context structure for the random number generator state.
+ */
+ typedef struct {
+ unsigned int a;
+ unsigned int x;
+ unsigned int c;
+ unsigned int ah;
+ unsigned int al;
+ } SDLTest_RandomContext;
+
+
+/* --- Function prototypes */
+
+/**
+ * \brief Initialize random number generator with two integers.
+ *
+ * Note: The random sequence of numbers returned by ...Random() is the
+ * same for the same two integers and has a period of 2^31.
+ *
+ * \param rndContext pointer to context structure
+ * \param xi integer that defines the random sequence
+ * \param ci integer that defines the random sequence
+ *
+ */
+ void SDLTest_RandomInit(SDLTest_RandomContext * rndContext, unsigned int xi,
+ unsigned int ci);
+
+/**
+ * \brief Initialize random number generator based on current system time.
+ *
+ * \param rndContext pointer to context structure
+ *
+ */
+ void SDLTest_RandomInitTime(SDLTest_RandomContext *rndContext);
+
+
+/**
+ * \brief Initialize random number generator based on current system time.
+ *
+ * Note: ...RandomInit() or ...RandomInitTime() must have been called
+ * before using this function.
+ *
+ * \param rndContext pointer to context structure
+ *
+ * \returns a random number (32bit unsigned integer)
+ *
+ */
+ unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_random_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_thread.h b/Client/ThirdParty/SDL2/include/SDL_thread.h
new file mode 100644
index 0000000..b344150
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_thread.h
@@ -0,0 +1,454 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_thread_h_
+#define SDL_thread_h_
+
+/**
+ * \file SDL_thread.h
+ *
+ * Header for the SDL thread management routines.
+ */
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+/* Thread synchronization primitives */
+#include "SDL_atomic.h"
+#include "SDL_mutex.h"
+
+#if defined(__WIN32__)
+#include <process.h> /* _beginthreadex() and _endthreadex() */
+#endif
+#if defined(__OS2__) /* for _beginthread() and _endthread() */
+#ifndef __EMX__
+#include <process.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The SDL thread structure, defined in SDL_thread.c */
+struct SDL_Thread;
+typedef struct SDL_Thread SDL_Thread;
+
+/* The SDL thread ID */
+typedef unsigned long SDL_threadID;
+
+/* Thread local storage ID, 0 is the invalid ID */
+typedef unsigned int SDL_TLSID;
+
+/**
+ * The SDL thread priority.
+ *
+ * SDL will make system changes as necessary in order to apply the thread priority.
+ * Code which attempts to control thread state related to priority should be aware
+ * that calling SDL_SetThreadPriority may alter such state.
+ * SDL_HINT_THREAD_PRIORITY_POLICY can be used to control aspects of this behavior.
+ *
+ * \note On many systems you require special privileges to set high or time critical priority.
+ */
+typedef enum {
+ SDL_THREAD_PRIORITY_LOW,
+ SDL_THREAD_PRIORITY_NORMAL,
+ SDL_THREAD_PRIORITY_HIGH,
+ SDL_THREAD_PRIORITY_TIME_CRITICAL
+} SDL_ThreadPriority;
+
+/**
+ * The function passed to SDL_CreateThread().
+ *
+ * \param data what was passed as `data` to SDL_CreateThread()
+ * \returns a value that can be reported through SDL_WaitThread().
+ */
+typedef int (SDLCALL * SDL_ThreadFunction) (void *data);
+
+
+#if defined(__WIN32__)
+/**
+ * \file SDL_thread.h
+ *
+ * We compile SDL into a DLL. This means, that it's the DLL which
+ * creates a new thread for the calling process with the SDL_CreateThread()
+ * API. There is a problem with this, that only the RTL of the SDL2.DLL will
+ * be initialized for those threads, and not the RTL of the calling
+ * application!
+ *
+ * To solve this, we make a little hack here.
+ *
+ * We'll always use the caller's _beginthread() and _endthread() APIs to
+ * start a new thread. This way, if it's the SDL2.DLL which uses this API,
+ * then the RTL of SDL2.DLL will be used to create the new thread, and if it's
+ * the application, then the RTL of the application will be used.
+ *
+ * So, in short:
+ * Always use the _beginthread() and _endthread() of the calling runtime
+ * library!
+ */
+#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
+
+typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread)
+ (void *, unsigned, unsigned (__stdcall *func)(void *),
+ void * /*arg*/, unsigned, unsigned * /* threadID */);
+typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
+
+#ifndef SDL_beginthread
+#define SDL_beginthread _beginthreadex
+#endif
+#ifndef SDL_endthread
+#define SDL_endthread _endthreadex
+#endif
+
+/**
+ * Create a thread.
+ */
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+ const char *name, const size_t stacksize, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+
+/**
+ * Create a thread.
+ */
+#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
+#undef SDL_CreateThread
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#undef SDL_CreateThreadWithStackSize
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#else
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, data, (pfnSDL_CurrentBeginThread)_beginthreadex, (pfnSDL_CurrentEndThread)SDL_endthread)
+#endif
+
+#elif defined(__OS2__)
+/*
+ * just like the windows case above: We compile SDL2
+ * into a dll with Watcom's runtime statically linked.
+ */
+#define SDL_PASSED_BEGINTHREAD_ENDTHREAD
+
+typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void * /*arg*/);
+typedef void (*pfnSDL_CurrentEndThread)(void);
+
+#ifndef SDL_beginthread
+#define SDL_beginthread _beginthread
+#endif
+#ifndef SDL_endthread
+#define SDL_endthread _endthread
+#endif
+
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread);
+
+#if defined(SDL_CreateThread) && SDL_DYNAMIC_API
+#undef SDL_CreateThread
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#undef SDL_CreateThreadWithStackSize
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#else
+#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread)
+#endif
+
+#else
+
+/**
+ * Create a new thread with a default stack size.
+ *
+ * This is equivalent to calling:
+ *
+ * ```c
+ * SDL_CreateThreadWithStackSize(fn, name, 0, data);
+ * ```
+ *
+ * \param fn the SDL_ThreadFunction function to call in the new thread
+ * \param name the name of the thread
+ * \param data a pointer that is passed to `fn`
+ * \returns an opaque pointer to the new thread object on success, NULL if the
+ * new thread could not be created; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_CreateThreadWithStackSize
+ * \sa SDL_WaitThread
+ */
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data);
+
+/**
+ * Create a new thread with a specific stack size.
+ *
+ * SDL makes an attempt to report `name` to the system, so that debuggers can
+ * display it. Not all platforms support this.
+ *
+ * Thread naming is a little complicated: Most systems have very small limits
+ * for the string length (Haiku has 32 bytes, Linux currently has 16, Visual
+ * C++ 6.0 has _nine_!), and possibly other arbitrary rules. You'll have to
+ * see what happens with your system's debugger. The name should be UTF-8 (but
+ * using the naming limits of C identifiers is a better bet). There are no
+ * requirements for thread naming conventions, so long as the string is
+ * null-terminated UTF-8, but these guidelines are helpful in choosing a name:
+ *
+ * https://stackoverflow.com/questions/149932/naming-conventions-for-threads
+ *
+ * If a system imposes requirements, SDL will try to munge the string for it
+ * (truncate, etc), but the original string contents will be available from
+ * SDL_GetThreadName().
+ *
+ * The size (in bytes) of the new stack can be specified. Zero means "use the
+ * system default" which might be wildly different between platforms. x86
+ * Linux generally defaults to eight megabytes, an embedded device might be a
+ * few kilobytes instead. You generally need to specify a stack that is a
+ * multiple of the system's page size (in many cases, this is 4 kilobytes, but
+ * check your system documentation).
+ *
+ * In SDL 2.1, stack size will be folded into the original SDL_CreateThread
+ * function, but for backwards compatibility, this is currently a separate
+ * function.
+ *
+ * \param fn the SDL_ThreadFunction function to call in the new thread
+ * \param name the name of the thread
+ * \param stacksize the size, in bytes, to allocate for the new thread stack.
+ * \param data a pointer that is passed to `fn`
+ * \returns an opaque pointer to the new thread object on success, NULL if the
+ * new thread could not be created; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_WaitThread
+ */
+extern DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data);
+
+#endif
+
+/**
+ * Get the thread name as it was specified in SDL_CreateThread().
+ *
+ * This is internal memory, not to be freed by the caller, and remains valid
+ * until the specified thread is cleaned up by SDL_WaitThread().
+ *
+ * \param thread the thread to query
+ * \returns a pointer to a UTF-8 string that names the specified thread, or
+ * NULL if it doesn't have a name.
+ *
+ * \sa SDL_CreateThread
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread);
+
+/**
+ * Get the thread identifier for the current thread.
+ *
+ * This thread identifier is as reported by the underlying operating system.
+ * If SDL is running on a platform that does not support threads the return
+ * value will always be zero.
+ *
+ * This function also returns a valid thread ID when called from the main
+ * thread.
+ *
+ * \returns the ID of the current thread.
+ *
+ * \sa SDL_GetThreadID
+ */
+extern DECLSPEC SDL_threadID SDLCALL SDL_ThreadID(void);
+
+/**
+ * Get the thread identifier for the specified thread.
+ *
+ * This thread identifier is as reported by the underlying operating system.
+ * If SDL is running on a platform that does not support threads the return
+ * value will always be zero.
+ *
+ * \param thread the thread to query
+ * \returns the ID of the specified thread, or the ID of the current thread if
+ * `thread` is NULL.
+ *
+ * \sa SDL_ThreadID
+ */
+extern DECLSPEC SDL_threadID SDLCALL SDL_GetThreadID(SDL_Thread * thread);
+
+/**
+ * Set the priority for the current thread.
+ *
+ * Note that some platforms will not let you alter the priority (or at least,
+ * promote the thread to a higher priority) at all, and some require you to be
+ * an administrator account. Be prepared for this to fail.
+ *
+ * \param priority the SDL_ThreadPriority to set
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority);
+
+/**
+ * Wait for a thread to finish.
+ *
+ * Threads that haven't been detached will remain (as a "zombie") until this
+ * function cleans them up. Not doing so is a resource leak.
+ *
+ * Once a thread has been cleaned up through this function, the SDL_Thread
+ * that references it becomes invalid and should not be referenced again. As
+ * such, only one thread may call SDL_WaitThread() on another.
+ *
+ * The return code for the thread function is placed in the area pointed to by
+ * `status`, if `status` is not NULL.
+ *
+ * You may not wait on a thread that has been used in a call to
+ * SDL_DetachThread(). Use either that function or this one, but not both, or
+ * behavior is undefined.
+ *
+ * It is safe to pass a NULL thread to this function; it is a no-op.
+ *
+ * Note that the thread pointer is freed by this function and is not valid
+ * afterward.
+ *
+ * \param thread the SDL_Thread pointer that was returned from the
+ * SDL_CreateThread() call that started this thread
+ * \param status pointer to an integer that will receive the value returned
+ * from the thread function by its 'return', or NULL to not
+ * receive such value back.
+ *
+ * \sa SDL_CreateThread
+ * \sa SDL_DetachThread
+ */
+extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
+
+/**
+ * Let a thread clean up on exit without intervention.
+ *
+ * A thread may be "detached" to signify that it should not remain until
+ * another thread has called SDL_WaitThread() on it. Detaching a thread is
+ * useful for long-running threads that nothing needs to synchronize with or
+ * further manage. When a detached thread is done, it simply goes away.
+ *
+ * There is no way to recover the return code of a detached thread. If you
+ * need this, don't detach the thread and instead use SDL_WaitThread().
+ *
+ * Once a thread is detached, you should usually assume the SDL_Thread isn't
+ * safe to reference again, as it will become invalid immediately upon the
+ * detached thread's exit, instead of remaining until someone has called
+ * SDL_WaitThread() to finally clean it up. As such, don't detach the same
+ * thread more than once.
+ *
+ * If a thread has already exited when passed to SDL_DetachThread(), it will
+ * stop waiting for a call to SDL_WaitThread() and clean up immediately. It is
+ * not safe to detach a thread that might be used with SDL_WaitThread().
+ *
+ * You may not call SDL_WaitThread() on a thread that has been detached. Use
+ * either that function or this one, but not both, or behavior is undefined.
+ *
+ * It is safe to pass NULL to this function; it is a no-op.
+ *
+ * \param thread the SDL_Thread pointer that was returned from the
+ * SDL_CreateThread() call that started this thread
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_CreateThread
+ * \sa SDL_WaitThread
+ */
+extern DECLSPEC void SDLCALL SDL_DetachThread(SDL_Thread * thread);
+
+/**
+ * Create a piece of thread-local storage.
+ *
+ * This creates an identifier that is globally visible to all threads but
+ * refers to data that is thread-specific.
+ *
+ * \returns the newly created thread local storage identifier or 0 on error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_TLSGet
+ * \sa SDL_TLSSet
+ */
+extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate(void);
+
+/**
+ * Get the current thread's value associated with a thread local storage ID.
+ *
+ * \param id the thread local storage ID
+ * \returns the value associated with the ID for the current thread or NULL if
+ * no value has been set; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_TLSCreate
+ * \sa SDL_TLSSet
+ */
+extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id);
+
+/**
+ * Set the current thread's value associated with a thread local storage ID.
+ *
+ * The function prototype for `destructor` is:
+ *
+ * ```c
+ * void destructor(void *value)
+ * ```
+ *
+ * where its parameter `value` is what was passed as `value` to SDL_TLSSet().
+ *
+ * \param id the thread local storage ID
+ * \param value the value to associate with the ID for the current thread
+ * \param destructor a function called when the thread exits, to free the
+ * value
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_TLSCreate
+ * \sa SDL_TLSGet
+ */
+extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void*));
+
+/**
+ * Cleanup all TLS data for this thread.
+ */
+extern DECLSPEC void SDLCALL SDL_TLSCleanup(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_thread_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_timer.h b/Client/ThirdParty/SDL2/include/SDL_timer.h
new file mode 100644
index 0000000..04696dc
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_timer.h
@@ -0,0 +1,172 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_timer_h_
+#define SDL_timer_h_
+
+/**
+ * \file SDL_timer.h
+ *
+ * Header for the SDL time management routines.
+ */
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the number of milliseconds since SDL library initialization.
+ *
+ * This value wraps if the program runs for more than ~49 days.
+ *
+ * \returns an unsigned 32-bit value representing the number of milliseconds
+ * since the SDL library initialized.
+ *
+ * \sa SDL_TICKS_PASSED
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void);
+
+/**
+ * Compare SDL ticks values, and return true if `A` has passed `B`.
+ *
+ * For example, if you want to wait 100 ms, you could do this:
+ *
+ * ```c++
+ * Uint32 timeout = SDL_GetTicks() + 100;
+ * while (!SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
+ * // ... do work until timeout has elapsed
+ * }
+ * ```
+ */
+#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0)
+
+/**
+ * Get the current value of the high resolution counter.
+ *
+ * This function is typically used for profiling.
+ *
+ * The counter values are only meaningful relative to each other. Differences
+ * between values can be converted to times by using
+ * SDL_GetPerformanceFrequency().
+ *
+ * \returns the current counter value.
+ *
+ * \sa SDL_GetPerformanceFrequency
+ */
+extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void);
+
+/**
+ * Get the count per second of the high resolution counter.
+ *
+ * \returns a platform-specific count per second.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetPerformanceCounter
+ */
+extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void);
+
+/**
+ * Wait a specified number of milliseconds before returning.
+ *
+ * This function waits a specified number of milliseconds before returning. It
+ * waits at least the specified time, but possibly longer due to OS
+ * scheduling.
+ *
+ * \param ms the number of milliseconds to delay
+ */
+extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms);
+
+/**
+ * Function prototype for the timer callback function.
+ *
+ * The callback function is passed the current timer interval and returns
+ * the next timer interval. If the returned value is the same as the one
+ * passed in, the periodic alarm continues, otherwise a new alarm is
+ * scheduled. If the callback returns 0, the periodic alarm is cancelled.
+ */
+typedef Uint32 (SDLCALL * SDL_TimerCallback) (Uint32 interval, void *param);
+
+/**
+ * Definition of the timer ID type.
+ */
+typedef int SDL_TimerID;
+
+/**
+ * Call a callback function at a future time.
+ *
+ * If you use this function, you must pass `SDL_INIT_TIMER` to SDL_Init().
+ *
+ * The callback function is passed the current timer interval and the user
+ * supplied parameter from the SDL_AddTimer() call and should return the next
+ * timer interval. If the value returned from the callback is 0, the timer is
+ * canceled.
+ *
+ * The callback is run on a separate thread.
+ *
+ * Timers take into account the amount of time it took to execute the
+ * callback. For example, if the callback took 250 ms to execute and returned
+ * 1000 (ms), the timer would only wait another 750 ms before its next
+ * iteration.
+ *
+ * Timing may be inexact due to OS scheduling. Be sure to note the current
+ * time with SDL_GetTicks() or SDL_GetPerformanceCounter() in case your
+ * callback needs to adjust for variances.
+ *
+ * \param interval the timer delay, in milliseconds, passed to `callback`
+ * \param callback the SDL_TimerCallback function to call when the specified
+ * `interval` elapses
+ * \param param a pointer that is passed to `callback`
+ * \returns a timer ID or 0 if an error occurs; call SDL_GetError() for more
+ * information.
+ *
+ * \sa SDL_RemoveTimer
+ */
+extern DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval,
+ SDL_TimerCallback callback,
+ void *param);
+
+/**
+ * Remove a timer created with SDL_AddTimer().
+ *
+ * \param id the ID of the timer to remove
+ * \returns SDL_TRUE if the timer is removed or SDL_FALSE if the timer wasn't
+ * found.
+ *
+ * \sa SDL_AddTimer
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RemoveTimer(SDL_TimerID id);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_timer_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_touch.h b/Client/ThirdParty/SDL2/include/SDL_touch.h
new file mode 100644
index 0000000..f370a67
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_touch.h
@@ -0,0 +1,138 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_touch.h
+ *
+ * Include file for SDL touch event handling.
+ */
+
+#ifndef SDL_touch_h_
+#define SDL_touch_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_error.h"
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_TouchID;
+typedef Sint64 SDL_FingerID;
+
+typedef enum
+{
+ SDL_TOUCH_DEVICE_INVALID = -1,
+ SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */
+ SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */
+ SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */
+} SDL_TouchDeviceType;
+
+typedef struct SDL_Finger
+{
+ SDL_FingerID id;
+ float x;
+ float y;
+ float pressure;
+} SDL_Finger;
+
+/* Used as the device ID for mouse events simulated with touch input */
+#define SDL_TOUCH_MOUSEID ((Uint32)-1)
+
+/* Used as the SDL_TouchID for touch events simulated with mouse input */
+#define SDL_MOUSE_TOUCHID ((Sint64)-1)
+
+
+/**
+ * Get the number of registered touch devices.
+ *
+ * On some platforms SDL first sees the touch device if it was actually used.
+ * Therefore SDL_GetNumTouchDevices() may return 0 although devices are
+ * available. After using all devices at least once the number will be
+ * correct.
+ *
+ * This was fixed for Android in SDL 2.0.1.
+ *
+ * \returns the number of registered touch devices.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchDevice
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void);
+
+/**
+ * Get the touch ID with the given index.
+ *
+ * \param index the touch device index
+ * \returns the touch ID with the given index on success or 0 if the index is
+ * invalid; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumTouchDevices
+ */
+extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index);
+
+/**
+ * Get the type of the given touch device.
+ */
+extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID);
+
+/**
+ * Get the number of active fingers for a given touch device.
+ *
+ * \param touchID the ID of a touch device
+ * \returns the number of active fingers for a given touch device on success
+ * or 0 on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchFinger
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID);
+
+/**
+ * Get the finger object for specified touch device ID and finger index.
+ *
+ * The returned resource is owned by SDL and should not be deallocated.
+ *
+ * \param touchID the ID of the requested touch device
+ * \param index the index of the requested finger
+ * \returns a pointer to the SDL_Finger object or NULL if no object at the
+ * given ID and index could be found.
+ *
+ * \sa SDL_RecordGesture
+ */
+extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_touch_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_types.h b/Client/ThirdParty/SDL2/include/SDL_types.h
new file mode 100644
index 0000000..4267f36
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_types.h
@@ -0,0 +1,29 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_types.h
+ *
+ * \deprecated
+ */
+
+/* DEPRECATED */
+#include "SDL_stdinc.h"
diff --git a/Client/ThirdParty/SDL2/include/SDL_version.h b/Client/ThirdParty/SDL2/include/SDL_version.h
new file mode 100644
index 0000000..f4f8be2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_version.h
@@ -0,0 +1,172 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_version.h
+ *
+ * This header defines the current SDL version.
+ */
+
+#ifndef SDL_version_h_
+#define SDL_version_h_
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Information about the version of SDL in use.
+ *
+ * Represents the library's version as three levels: major revision
+ * (increments with massive changes, additions, and enhancements),
+ * minor revision (increments with backwards-compatible changes to the
+ * major revision), and patchlevel (increments with fixes to the minor
+ * revision).
+ *
+ * \sa SDL_VERSION
+ * \sa SDL_GetVersion
+ */
+typedef struct SDL_version
+{
+ Uint8 major; /**< major version */
+ Uint8 minor; /**< minor version */
+ Uint8 patch; /**< update version */
+} SDL_version;
+
+/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
+*/
+#define SDL_MAJOR_VERSION 2
+#define SDL_MINOR_VERSION 0
+#define SDL_PATCHLEVEL 16
+
+/**
+ * Macro to determine SDL version program was compiled against.
+ *
+ * This macro fills in a SDL_version structure with the version of the
+ * library you compiled against. This is determined by what header the
+ * compiler uses. Note that if you dynamically linked the library, you might
+ * have a slightly newer or older version at runtime. That version can be
+ * determined with SDL_GetVersion(), which, unlike SDL_VERSION(),
+ * is not a macro.
+ *
+ * \param x A pointer to a SDL_version struct to initialize.
+ *
+ * \sa SDL_version
+ * \sa SDL_GetVersion
+ */
+#define SDL_VERSION(x) \
+{ \
+ (x)->major = SDL_MAJOR_VERSION; \
+ (x)->minor = SDL_MINOR_VERSION; \
+ (x)->patch = SDL_PATCHLEVEL; \
+}
+
+/**
+ * This macro turns the version numbers into a numeric value:
+ * \verbatim
+ (1,2,3) -> (1203)
+ \endverbatim
+ *
+ * This assumes that there will never be more than 100 patchlevels.
+ */
+#define SDL_VERSIONNUM(X, Y, Z) \
+ ((X)*1000 + (Y)*100 + (Z))
+
+/**
+ * This is the version number macro for the current SDL version.
+ */
+#define SDL_COMPILEDVERSION \
+ SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL)
+
+/**
+ * This macro will evaluate to true if compiled with SDL at least X.Y.Z.
+ */
+#define SDL_VERSION_ATLEAST(X, Y, Z) \
+ (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
+
+/**
+ * Get the version of SDL that is linked against your program.
+ *
+ * If you are linking to SDL dynamically, then it is possible that the current
+ * version will be different than the version you compiled against. This
+ * function returns the current version, while SDL_VERSION() is a macro that
+ * tells you what version you compiled with.
+ *
+ * This function may be called safely at any time, even before SDL_Init().
+ *
+ * \param ver the SDL_version structure that contains the version information
+ *
+ * \sa SDL_GetRevision
+ */
+extern DECLSPEC void SDLCALL SDL_GetVersion(SDL_version * ver);
+
+/**
+ * Get the code revision of SDL that is linked against your program.
+ *
+ * This value is the revision of the code you are linked with and may be
+ * different from the code you are compiling with, which is found in the
+ * constant SDL_REVISION.
+ *
+ * The revision is arbitrary string (a hash value) uniquely identifying the
+ * exact revision of the SDL library in use, and is only useful in comparing
+ * against other revisions. It is NOT an incrementing number.
+ *
+ * If SDL wasn't built from a git repository with the appropriate tools, this
+ * will return an empty string.
+ *
+ * Prior to SDL 2.0.16, before development moved to GitHub, this returned a
+ * hash for a Mercurial repository.
+ *
+ * You shouldn't use this function for anything but logging it for debugging
+ * purposes. The string is not intended to be reliable in any way.
+ *
+ * \returns an arbitrary string, uniquely identifying the exact revision of
+ * the SDL library in use.
+ *
+ * \sa SDL_GetVersion
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetRevision(void);
+
+/**
+ * Obsolete function, do not use.
+ *
+ * When SDL was hosted in a Mercurial repository, and was built carefully,
+ * this would return the revision number that the build was created from.
+ * This number was not reliable for several reasons, but more importantly,
+ * SDL is now hosted in a git repository, which does not offer numbers at
+ * all, only hashes. This function only ever returns zero now. Don't use it.
+ */
+extern SDL_DEPRECATED DECLSPEC int SDLCALL SDL_GetRevisionNumber(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_version_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_video.h b/Client/ThirdParty/SDL2/include/SDL_video.h
new file mode 100644
index 0000000..b6eb255
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_video.h
@@ -0,0 +1,1901 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_video.h
+ *
+ * Header file for SDL video functions.
+ */
+
+#ifndef SDL_video_h_
+#define SDL_video_h_
+
+#include "SDL_stdinc.h"
+#include "SDL_pixels.h"
+#include "SDL_rect.h"
+#include "SDL_surface.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The structure that defines a display mode
+ *
+ * \sa SDL_GetNumDisplayModes()
+ * \sa SDL_GetDisplayMode()
+ * \sa SDL_GetDesktopDisplayMode()
+ * \sa SDL_GetCurrentDisplayMode()
+ * \sa SDL_GetClosestDisplayMode()
+ * \sa SDL_SetWindowDisplayMode()
+ * \sa SDL_GetWindowDisplayMode()
+ */
+typedef struct
+{
+ Uint32 format; /**< pixel format */
+ int w; /**< width, in screen coordinates */
+ int h; /**< height, in screen coordinates */
+ int refresh_rate; /**< refresh rate (or zero for unspecified) */
+ void *driverdata; /**< driver-specific data, initialize to 0 */
+} SDL_DisplayMode;
+
+/**
+ * \brief The type used to identify a window
+ *
+ * \sa SDL_CreateWindow()
+ * \sa SDL_CreateWindowFrom()
+ * \sa SDL_DestroyWindow()
+ * \sa SDL_FlashWindow()
+ * \sa SDL_GetWindowData()
+ * \sa SDL_GetWindowFlags()
+ * \sa SDL_GetWindowGrab()
+ * \sa SDL_GetWindowKeyboardGrab()
+ * \sa SDL_GetWindowMouseGrab()
+ * \sa SDL_GetWindowPosition()
+ * \sa SDL_GetWindowSize()
+ * \sa SDL_GetWindowTitle()
+ * \sa SDL_HideWindow()
+ * \sa SDL_MaximizeWindow()
+ * \sa SDL_MinimizeWindow()
+ * \sa SDL_RaiseWindow()
+ * \sa SDL_RestoreWindow()
+ * \sa SDL_SetWindowData()
+ * \sa SDL_SetWindowFullscreen()
+ * \sa SDL_SetWindowGrab()
+ * \sa SDL_SetWindowKeyboardGrab()
+ * \sa SDL_SetWindowMouseGrab()
+ * \sa SDL_SetWindowIcon()
+ * \sa SDL_SetWindowPosition()
+ * \sa SDL_SetWindowSize()
+ * \sa SDL_SetWindowBordered()
+ * \sa SDL_SetWindowResizable()
+ * \sa SDL_SetWindowTitle()
+ * \sa SDL_ShowWindow()
+ */
+typedef struct SDL_Window SDL_Window;
+
+/**
+ * \brief The flags on a window
+ *
+ * \sa SDL_GetWindowFlags()
+ */
+typedef enum
+{
+ SDL_WINDOW_FULLSCREEN = 0x00000001, /**< fullscreen window */
+ SDL_WINDOW_OPENGL = 0x00000002, /**< window usable with OpenGL context */
+ SDL_WINDOW_SHOWN = 0x00000004, /**< window is visible */
+ SDL_WINDOW_HIDDEN = 0x00000008, /**< window is not visible */
+ SDL_WINDOW_BORDERLESS = 0x00000010, /**< no window decoration */
+ SDL_WINDOW_RESIZABLE = 0x00000020, /**< window can be resized */
+ SDL_WINDOW_MINIMIZED = 0x00000040, /**< window is minimized */
+ SDL_WINDOW_MAXIMIZED = 0x00000080, /**< window is maximized */
+ SDL_WINDOW_MOUSE_GRABBED = 0x00000100, /**< window has grabbed mouse input */
+ SDL_WINDOW_INPUT_FOCUS = 0x00000200, /**< window has input focus */
+ SDL_WINDOW_MOUSE_FOCUS = 0x00000400, /**< window has mouse focus */
+ SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
+ SDL_WINDOW_FOREIGN = 0x00000800, /**< window not created by SDL */
+ SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000, /**< window should be created in high-DPI mode if supported.
+ On macOS NSHighResolutionCapable must be set true in the
+ application's Info.plist for this to have any effect. */
+ SDL_WINDOW_MOUSE_CAPTURE = 0x00004000, /**< window has mouse captured (unrelated to MOUSE_GRABBED) */
+ SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000, /**< window should always be above others */
+ SDL_WINDOW_SKIP_TASKBAR = 0x00010000, /**< window should not be added to the taskbar */
+ SDL_WINDOW_UTILITY = 0x00020000, /**< window should be treated as a utility window */
+ SDL_WINDOW_TOOLTIP = 0x00040000, /**< window should be treated as a tooltip */
+ SDL_WINDOW_POPUP_MENU = 0x00080000, /**< window should be treated as a popup menu */
+ SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000, /**< window has grabbed keyboard input */
+ SDL_WINDOW_VULKAN = 0x10000000, /**< window usable for Vulkan surface */
+ SDL_WINDOW_METAL = 0x20000000, /**< window usable for Metal view */
+
+ SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
+} SDL_WindowFlags;
+
+/**
+ * \brief Used to indicate that you don't care what the window position is.
+ */
+#define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000u
+#define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X))
+#define SDL_WINDOWPOS_UNDEFINED SDL_WINDOWPOS_UNDEFINED_DISPLAY(0)
+#define SDL_WINDOWPOS_ISUNDEFINED(X) \
+ (((X)&0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK)
+
+/**
+ * \brief Used to indicate that the window position should be centered.
+ */
+#define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000u
+#define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X))
+#define SDL_WINDOWPOS_CENTERED SDL_WINDOWPOS_CENTERED_DISPLAY(0)
+#define SDL_WINDOWPOS_ISCENTERED(X) \
+ (((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK)
+
+/**
+ * \brief Event subtype for window events
+ */
+typedef enum
+{
+ SDL_WINDOWEVENT_NONE, /**< Never used */
+ SDL_WINDOWEVENT_SHOWN, /**< Window has been shown */
+ SDL_WINDOWEVENT_HIDDEN, /**< Window has been hidden */
+ SDL_WINDOWEVENT_EXPOSED, /**< Window has been exposed and should be
+ redrawn */
+ SDL_WINDOWEVENT_MOVED, /**< Window has been moved to data1, data2
+ */
+ SDL_WINDOWEVENT_RESIZED, /**< Window has been resized to data1xdata2 */
+ SDL_WINDOWEVENT_SIZE_CHANGED, /**< The window size has changed, either as
+ a result of an API call or through the
+ system or user changing the window size. */
+ SDL_WINDOWEVENT_MINIMIZED, /**< Window has been minimized */
+ SDL_WINDOWEVENT_MAXIMIZED, /**< Window has been maximized */
+ SDL_WINDOWEVENT_RESTORED, /**< Window has been restored to normal size
+ and position */
+ SDL_WINDOWEVENT_ENTER, /**< Window has gained mouse focus */
+ SDL_WINDOWEVENT_LEAVE, /**< Window has lost mouse focus */
+ SDL_WINDOWEVENT_FOCUS_GAINED, /**< Window has gained keyboard focus */
+ SDL_WINDOWEVENT_FOCUS_LOST, /**< Window has lost keyboard focus */
+ SDL_WINDOWEVENT_CLOSE, /**< The window manager requests that the window be closed */
+ SDL_WINDOWEVENT_TAKE_FOCUS, /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */
+ SDL_WINDOWEVENT_HIT_TEST /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */
+} SDL_WindowEventID;
+
+/**
+ * \brief Event subtype for display events
+ */
+typedef enum
+{
+ SDL_DISPLAYEVENT_NONE, /**< Never used */
+ SDL_DISPLAYEVENT_ORIENTATION, /**< Display orientation has changed to data1 */
+ SDL_DISPLAYEVENT_CONNECTED, /**< Display has been added to the system */
+ SDL_DISPLAYEVENT_DISCONNECTED /**< Display has been removed from the system */
+} SDL_DisplayEventID;
+
+/**
+ * \brief Display orientation
+ */
+typedef enum
+{
+ SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */
+ SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */
+ SDL_ORIENTATION_LANDSCAPE_FLIPPED, /**< The display is in landscape mode, with the left side up, relative to portrait mode */
+ SDL_ORIENTATION_PORTRAIT, /**< The display is in portrait mode */
+ SDL_ORIENTATION_PORTRAIT_FLIPPED /**< The display is in portrait mode, upside down */
+} SDL_DisplayOrientation;
+
+/**
+ * \brief Window flash operation
+ */
+typedef enum
+{
+ SDL_FLASH_CANCEL, /**< Cancel any window flash state */
+ SDL_FLASH_BRIEFLY, /**< Flash the window briefly to get attention */
+ SDL_FLASH_UNTIL_FOCUSED, /**< Flash the window until it gets focus */
+} SDL_FlashOperation;
+
+/**
+ * \brief An opaque handle to an OpenGL context.
+ */
+typedef void *SDL_GLContext;
+
+/**
+ * \brief OpenGL configuration attributes
+ */
+typedef enum
+{
+ SDL_GL_RED_SIZE,
+ SDL_GL_GREEN_SIZE,
+ SDL_GL_BLUE_SIZE,
+ SDL_GL_ALPHA_SIZE,
+ SDL_GL_BUFFER_SIZE,
+ SDL_GL_DOUBLEBUFFER,
+ SDL_GL_DEPTH_SIZE,
+ SDL_GL_STENCIL_SIZE,
+ SDL_GL_ACCUM_RED_SIZE,
+ SDL_GL_ACCUM_GREEN_SIZE,
+ SDL_GL_ACCUM_BLUE_SIZE,
+ SDL_GL_ACCUM_ALPHA_SIZE,
+ SDL_GL_STEREO,
+ SDL_GL_MULTISAMPLEBUFFERS,
+ SDL_GL_MULTISAMPLESAMPLES,
+ SDL_GL_ACCELERATED_VISUAL,
+ SDL_GL_RETAINED_BACKING,
+ SDL_GL_CONTEXT_MAJOR_VERSION,
+ SDL_GL_CONTEXT_MINOR_VERSION,
+ SDL_GL_CONTEXT_EGL,
+ SDL_GL_CONTEXT_FLAGS,
+ SDL_GL_CONTEXT_PROFILE_MASK,
+ SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
+ SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
+ SDL_GL_CONTEXT_RELEASE_BEHAVIOR,
+ SDL_GL_CONTEXT_RESET_NOTIFICATION,
+ SDL_GL_CONTEXT_NO_ERROR
+} SDL_GLattr;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_PROFILE_CORE = 0x0001,
+ SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002,
+ SDL_GL_CONTEXT_PROFILE_ES = 0x0004 /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
+} SDL_GLprofile;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001,
+ SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
+ SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG = 0x0004,
+ SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008
+} SDL_GLcontextFlag;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000,
+ SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001
+} SDL_GLcontextReleaseFlag;
+
+typedef enum
+{
+ SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000,
+ SDL_GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001
+} SDL_GLContextResetNotification;
+
+/* Function prototypes */
+
+/**
+ * Get the number of video drivers compiled into SDL.
+ *
+ * \returns a number >= 1 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetVideoDriver
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void);
+
+/**
+ * Get the name of a built in video driver.
+ *
+ * The video drivers are presented in the order in which they are normally
+ * checked during initialization.
+ *
+ * \param index the index of a video driver
+ * \returns the name of the video driver with the given **index**.
+ *
+ * \sa SDL_GetNumVideoDrivers
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetVideoDriver(int index);
+
+/**
+ * Initialize the video subsystem, optionally specifying a video driver.
+ *
+ * This function initializes the video subsystem, setting up a connection to
+ * the window manager, etc, and determines the available display modes and
+ * pixel formats, but does not initialize a window or graphics mode.
+ *
+ * If you use this function and you haven't used the SDL_INIT_VIDEO flag with
+ * either SDL_Init() or SDL_InitSubSystem(), you should call SDL_VideoQuit()
+ * before calling SDL_Quit().
+ *
+ * It is safe to call this function multiple times. SDL_VideoInit() will call
+ * SDL_VideoQuit() itself if the video subsystem has already been initialized.
+ *
+ * You can use SDL_GetNumVideoDrivers() and SDL_GetVideoDriver() to find a
+ * specific `driver_name`.
+ *
+ * \param driver_name the name of a video driver to initialize, or NULL for
+ * the default driver
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetNumVideoDrivers
+ * \sa SDL_GetVideoDriver
+ * \sa SDL_InitSubSystem
+ * \sa SDL_VideoQuit
+ */
+extern DECLSPEC int SDLCALL SDL_VideoInit(const char *driver_name);
+
+/**
+ * Shut down the video subsystem, if initialized with SDL_VideoInit().
+ *
+ * This function closes all windows, and restores the original video mode.
+ *
+ * \sa SDL_VideoInit
+ */
+extern DECLSPEC void SDLCALL SDL_VideoQuit(void);
+
+/**
+ * Get the name of the currently initialized video driver.
+ *
+ * \returns the name of the current video driver or NULL if no driver has been
+ * initialized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumVideoDrivers
+ * \sa SDL_GetVideoDriver
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetCurrentVideoDriver(void);
+
+/**
+ * Get the number of available video displays.
+ *
+ * \returns a number >= 1 or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetDisplayBounds
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumVideoDisplays(void);
+
+/**
+ * Get the name of a display in UTF-8 encoding.
+ *
+ * \param displayIndex the index of display from which the name should be
+ * queried
+ * \returns the name of a display or NULL for an invalid display index or
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetDisplayName(int displayIndex);
+
+/**
+ * Get the desktop area represented by a display.
+ *
+ * The primary display (`displayIndex` zero) is always located at 0,0.
+ *
+ * \param displayIndex the index of the display to query
+ * \param rect the SDL_Rect structure filled in with the display bounds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect);
+
+/**
+ * Get the usable desktop area represented by a display.
+ *
+ * The primary display (`displayIndex` zero) is always located at 0,0.
+ *
+ * This is the same area as SDL_GetDisplayBounds() reports, but with portions
+ * reserved by the system removed. For example, on Apple's macOS, this
+ * subtracts the area occupied by the menu bar and dock.
+ *
+ * Setting a window to be fullscreen generally bypasses these unusable areas,
+ * so these are good guidelines for the maximum space available to a
+ * non-fullscreen window.
+ *
+ * The parameter `rect` is ignored if it is NULL.
+ *
+ * This function also returns -1 if the parameter `displayIndex` is out of
+ * range.
+ *
+ * \param displayIndex the index of the display to query the usable bounds
+ * from
+ * \param rect the SDL_Rect structure filled in with the display bounds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetDisplayBounds
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect);
+
+/**
+ * Get the dots/pixels-per-inch for a display.
+ *
+ * Diagonal, horizontal and vertical DPI can all be optionally returned if the
+ * appropriate parameter is non-NULL.
+ *
+ * A failure of this function usually means that either no DPI information is
+ * available or the `displayIndex` is out of range.
+ *
+ * \param displayIndex the index of the display from which DPI information
+ * should be queried
+ * \param ddpi a pointer filled in with the diagonal DPI of the display; may
+ * be NULL
+ * \param hdpi a pointer filled in with the horizontal DPI of the display; may
+ * be NULL
+ * \param vdpi a pointer filled in with the vertical DPI of the display; may
+ * be NULL
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
+
+/**
+ * Get the orientation of a display.
+ *
+ * \param displayIndex the index of the display to query
+ * \returns The SDL_DisplayOrientation enum value of the display, or
+ * `SDL_ORIENTATION_UNKNOWN` if it isn't available.
+ *
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetDisplayOrientation(int displayIndex);
+
+/**
+ * Get the number of available display modes.
+ *
+ * The `displayIndex` needs to be in the range from 0 to
+ * SDL_GetNumVideoDisplays() - 1.
+ *
+ * \param displayIndex the index of the display to query
+ * \returns a number >= 1 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumDisplayModes(int displayIndex);
+
+/**
+ * Get information about a specific display mode.
+ *
+ * The display modes are sorted in this priority:
+ *
+ * - width -> largest to smallest
+ * - height -> largest to smallest
+ * - bits per pixel -> more colors to fewer colors
+ * - packed pixel layout -> largest to smallest
+ * - refresh rate -> highest to lowest
+ *
+ * \param displayIndex the index of the display to query
+ * \param modeIndex the index of the display mode to query
+ * \param mode an SDL_DisplayMode structure filled in with the mode at
+ * `modeIndex`
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetNumDisplayModes
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayMode(int displayIndex, int modeIndex,
+ SDL_DisplayMode * mode);
+
+/**
+ * Get information about the desktop's display mode.
+ *
+ * There's a difference between this function and SDL_GetCurrentDisplayMode()
+ * when SDL runs fullscreen and has changed the resolution. In that case this
+ * function will return the previous native display mode, and not the current
+ * display mode.
+ *
+ * \param displayIndex the index of the display to query
+ * \param mode an SDL_DisplayMode structure filled in with the current display
+ * mode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetCurrentDisplayMode
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetDesktopDisplayMode(int displayIndex, SDL_DisplayMode * mode);
+
+/**
+ * Get information about the current display mode.
+ *
+ * There's a difference between this function and SDL_GetDesktopDisplayMode()
+ * when SDL runs fullscreen and has changed the resolution. In that case this
+ * function will return the current display mode, and not the previous native
+ * display mode.
+ *
+ * \param displayIndex the index of the display to query
+ * \param mode an SDL_DisplayMode structure filled in with the current display
+ * mode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetDesktopDisplayMode
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_GetNumVideoDisplays
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC int SDLCALL SDL_GetCurrentDisplayMode(int displayIndex, SDL_DisplayMode * mode);
+
+
+/**
+ * Get the closest match to the requested display mode.
+ *
+ * The available display modes are scanned and `closest` is filled in with the
+ * closest mode matching the requested mode and returned. The mode format and
+ * refresh rate default to the desktop mode if they are set to 0. The modes
+ * are scanned with size being first priority, format being second priority,
+ * and finally checking the refresh rate. If all the available modes are too
+ * small, then NULL is returned.
+ *
+ * \param displayIndex the index of the display to query
+ * \param mode an SDL_DisplayMode structure containing the desired display
+ * mode
+ * \param closest an SDL_DisplayMode structure filled in with the closest
+ * match of the available display modes
+ * \returns the passed in value `closest` or NULL if no matching video mode
+ * was available; call SDL_GetError() for more information.
+ *
+ * \sa SDL_GetDisplayMode
+ * \sa SDL_GetNumDisplayModes
+ */
+extern DECLSPEC SDL_DisplayMode * SDLCALL SDL_GetClosestDisplayMode(int displayIndex, const SDL_DisplayMode * mode, SDL_DisplayMode * closest);
+
+/**
+ * Get the index of the display associated with a window.
+ *
+ * \param window the window to query
+ * \returns the index of the display containing the center of the window on
+ * success or a negative error code on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \sa SDL_GetDisplayBounds
+ * \sa SDL_GetNumVideoDisplays
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowDisplayIndex(SDL_Window * window);
+
+/**
+ * Set the display mode to use when a window is visible at fullscreen.
+ *
+ * This only affects the display mode used when the window is fullscreen. To
+ * change the window size when the window is not fullscreen, use
+ * SDL_SetWindowSize().
+ *
+ * \param window the window to affect
+ * \param mode the SDL_DisplayMode structure representing the mode to use, or
+ * NULL to use the window's dimensions and the desktop's format
+ * and refresh rate
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowDisplayMode
+ * \sa SDL_SetWindowFullscreen
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowDisplayMode(SDL_Window * window,
+ const SDL_DisplayMode * mode);
+
+/**
+ * Query the display mode to use when a window is visible at fullscreen.
+ *
+ * \param window the window to query
+ * \param mode an SDL_DisplayMode structure filled in with the fullscreen
+ * display mode
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetWindowDisplayMode
+ * \sa SDL_SetWindowFullscreen
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowDisplayMode(SDL_Window * window,
+ SDL_DisplayMode * mode);
+
+/**
+ * Get the pixel format associated with the window.
+ *
+ * \param window the window to query
+ * \returns the pixel format of the window on success or
+ * SDL_PIXELFORMAT_UNKNOWN on failure; call SDL_GetError() for more
+ * information.
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
+
+/**
+ * Create a window with the specified position, dimensions, and flags.
+ *
+ * `flags` may be any of the following OR'd together:
+ *
+ * - `SDL_WINDOW_FULLSCREEN`: fullscreen window
+ * - `SDL_WINDOW_FULLSCREEN_DESKTOP`: fullscreen window at desktop resolution
+ * - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context
+ * - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance
+ * - `SDL_WINDOW_METAL`: window usable with a Metal instance
+ * - `SDL_WINDOW_HIDDEN`: window is not visible
+ * - `SDL_WINDOW_BORDERLESS`: no window decoration
+ * - `SDL_WINDOW_RESIZABLE`: window can be resized
+ * - `SDL_WINDOW_MINIMIZED`: window is minimized
+ * - `SDL_WINDOW_MAXIMIZED`: window is maximized
+ * - `SDL_WINDOW_INPUT_GRABBED`: window has grabbed input focus
+ * - `SDL_WINDOW_ALLOW_HIGHDPI`: window should be created in high-DPI mode if
+ * supported (>= SDL 2.0.1)
+ *
+ * `SDL_WINDOW_SHOWN` is ignored by SDL_CreateWindow(). The SDL_Window is
+ * implicitly shown if SDL_WINDOW_HIDDEN is not set. `SDL_WINDOW_SHOWN` may be
+ * queried later using SDL_GetWindowFlags().
+ *
+ * On Apple's macOS, you **must** set the NSHighResolutionCapable Info.plist
+ * property to YES, otherwise you will not receive a High-DPI OpenGL canvas.
+ *
+ * If the window is created with the `SDL_WINDOW_ALLOW_HIGHDPI` flag, its size
+ * in pixels may differ from its size in screen coordinates on platforms with
+ * high-DPI support (e.g. iOS and macOS). Use SDL_GetWindowSize() to query the
+ * client area's size in screen coordinates, and SDL_GL_GetDrawableSize() or
+ * SDL_GetRendererOutputSize() to query the drawable size in pixels.
+ *
+ * If the window is set fullscreen, the width and height parameters `w` and
+ * `h` will not be used. However, invalid size parameters (e.g. too large) may
+ * still fail. Window size is actually limited to 16384 x 16384 for all
+ * platforms at window creation.
+ *
+ * If the window is created with any of the SDL_WINDOW_OPENGL or
+ * SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function
+ * (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the
+ * corresponding UnloadLibrary function is called by SDL_DestroyWindow().
+ *
+ * If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver,
+ * SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail.
+ *
+ * If SDL_WINDOW_METAL is specified on an OS that does not support Metal,
+ * SDL_CreateWindow() will fail.
+ *
+ * On non-Apple devices, SDL requires you to either not link to the Vulkan
+ * loader or link to a dynamic library version. This limitation may be removed
+ * in a future version of SDL.
+ *
+ * \param title the title of the window, in UTF-8 encoding
+ * \param x the x position of the window, `SDL_WINDOWPOS_CENTERED`, or
+ * `SDL_WINDOWPOS_UNDEFINED`
+ * \param y the y position of the window, `SDL_WINDOWPOS_CENTERED`, or
+ * `SDL_WINDOWPOS_UNDEFINED`
+ * \param w the width of the window, in screen coordinates
+ * \param h the height of the window, in screen coordinates
+ * \param flags 0, or one or more SDL_WindowFlags OR'd together
+ * \returns the window that was created or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CreateWindowFrom
+ * \sa SDL_DestroyWindow
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title,
+ int x, int y, int w,
+ int h, Uint32 flags);
+
+/**
+ * Create an SDL window from an existing native window.
+ *
+ * In some cases (e.g. OpenGL) and on some platforms (e.g. Microsoft Windows)
+ * the hint `SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT` needs to be configured
+ * before using SDL_CreateWindowFrom().
+ *
+ * \param data a pointer to driver-dependent window creation data, typically
+ * your native window cast to a void*
+ * \returns the window that was created or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_DestroyWindow
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowFrom(const void *data);
+
+/**
+ * Get the numeric ID of a window.
+ *
+ * The numeric ID is what SDL_WindowEvent references, and is necessary to map
+ * these events to specific SDL_Window objects.
+ *
+ * \param window the window to query
+ * \returns the ID of the window on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetWindowFromID
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetWindowID(SDL_Window * window);
+
+/**
+ * Get a window from a stored ID.
+ *
+ * The numeric ID is what SDL_WindowEvent references, and is necessary to map
+ * these events to specific SDL_Window objects.
+ *
+ * \param id the ID of the window
+ * \returns the window associated with `id` or NULL if it doesn't exist; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowID
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromID(Uint32 id);
+
+/**
+ * Get the window flags.
+ *
+ * \param window the window to query
+ * \returns a mask of the SDL_WindowFlags associated with `window`
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_HideWindow
+ * \sa SDL_MaximizeWindow
+ * \sa SDL_MinimizeWindow
+ * \sa SDL_SetWindowFullscreen
+ * \sa SDL_SetWindowGrab
+ * \sa SDL_ShowWindow
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetWindowFlags(SDL_Window * window);
+
+/**
+ * Set the title of a window.
+ *
+ * This string is expected to be in UTF-8 encoding.
+ *
+ * \param window the window to change
+ * \param title the desired window title in UTF-8 format
+ *
+ * \sa SDL_GetWindowTitle
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowTitle(SDL_Window * window,
+ const char *title);
+
+/**
+ * Get the title of a window.
+ *
+ * \param window the window to query
+ * \returns the title of the window in UTF-8 format or "" if there is no
+ * title.
+ *
+ * \sa SDL_SetWindowTitle
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window * window);
+
+/**
+ * Set the icon for a window.
+ *
+ * \param window the window to change
+ * \param icon an SDL_Surface structure containing the icon for the window
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowIcon(SDL_Window * window,
+ SDL_Surface * icon);
+
+/**
+ * Associate an arbitrary named pointer with a window.
+ *
+ * `name` is case-sensitive.
+ *
+ * \param window the window to associate with the pointer
+ * \param name the name of the pointer
+ * \param userdata the associated pointer
+ * \returns the previous value associated with `name`.
+ *
+ * \sa SDL_GetWindowData
+ */
+extern DECLSPEC void* SDLCALL SDL_SetWindowData(SDL_Window * window,
+ const char *name,
+ void *userdata);
+
+/**
+ * Retrieve the data pointer associated with a window.
+ *
+ * \param window the window to query
+ * \param name the name of the pointer
+ * \returns the value associated with `name`.
+ *
+ * \sa SDL_SetWindowData
+ */
+extern DECLSPEC void *SDLCALL SDL_GetWindowData(SDL_Window * window,
+ const char *name);
+
+/**
+ * Set the position of a window.
+ *
+ * The window coordinate origin is the upper left of the display.
+ *
+ * \param window the window to reposition
+ * \param x the x coordinate of the window in screen coordinates, or
+ * `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED`
+ * \param y the y coordinate of the window in screen coordinates, or
+ * `SDL_WINDOWPOS_CENTERED` or `SDL_WINDOWPOS_UNDEFINED`
+ *
+ * \sa SDL_GetWindowPosition
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowPosition(SDL_Window * window,
+ int x, int y);
+
+/**
+ * Get the position of a window.
+ *
+ * If you do not need the value for one of the positions a NULL may be passed
+ * in the `x` or `y` parameter.
+ *
+ * \param window the window to query
+ * \param x a pointer filled in with the x position of the window, in screen
+ * coordinates, may be NULL
+ * \param y a pointer filled in with the y position of the window, in screen
+ * coordinates, may be NULL
+ *
+ * \sa SDL_SetWindowPosition
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowPosition(SDL_Window * window,
+ int *x, int *y);
+
+/**
+ * Set the size of a window's client area.
+ *
+ * The window size in screen coordinates may differ from the size in pixels,
+ * if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform
+ * with high-dpi support (e.g. iOS or macOS). Use SDL_GL_GetDrawableSize() or
+ * SDL_GetRendererOutputSize() to get the real client area size in pixels.
+ *
+ * Fullscreen windows automatically match the size of the display mode, and
+ * you should use SDL_SetWindowDisplayMode() to change their size.
+ *
+ * \param window the window to change
+ * \param w the width of the window in pixels, in screen coordinates, must be
+ * > 0
+ * \param h the height of the window in pixels, in screen coordinates, must be
+ * > 0
+ *
+ * \sa SDL_GetWindowSize
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window * window, int w,
+ int h);
+
+/**
+ * Get the size of a window's client area.
+ *
+ * NULL can safely be passed as the `w` or `h` parameter if the width or
+ * height value is not desired.
+ *
+ * The window size in screen coordinates may differ from the size in pixels,
+ * if the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a platform
+ * with high-dpi support (e.g. iOS or macOS). Use SDL_GL_GetDrawableSize(),
+ * SDL_Vulkan_GetDrawableSize(), or SDL_GetRendererOutputSize() to get the
+ * real client area size in pixels.
+ *
+ * \param window the window to query the width and height from
+ * \param w a pointer filled in with the width of the window, in screen
+ * coordinates, may be NULL
+ * \param h a pointer filled in with the height of the window, in screen
+ * coordinates, may be NULL
+ *
+ * \sa SDL_GL_GetDrawableSize
+ * \sa SDL_Vulkan_GetDrawableSize
+ * \sa SDL_SetWindowSize
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window * window, int *w,
+ int *h);
+
+/**
+ * Get the size of a window's borders (decorations) around the client area.
+ *
+ * Note: If this function fails (returns -1), the size values will be
+ * initialized to 0, 0, 0, 0 (if a non-NULL pointer is provided), as if the
+ * window in question was borderless.
+ *
+ * Note: This function may fail on systems where the window has not yet been
+ * decorated by the display server (for example, immediately after calling
+ * SDL_CreateWindow). It is recommended that you wait at least until the
+ * window has been presented and composited, so that the window system has a
+ * chance to decorate the window and provide the border dimensions to SDL.
+ *
+ * This function also returns -1 if getting the information is not supported.
+ *
+ * \param window the window to query the size values of the border
+ * (decorations) from
+ * \param top pointer to variable for storing the size of the top border; NULL
+ * is permitted
+ * \param left pointer to variable for storing the size of the left border;
+ * NULL is permitted
+ * \param bottom pointer to variable for storing the size of the bottom
+ * border; NULL is permitted
+ * \param right pointer to variable for storing the size of the right border;
+ * NULL is permitted
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetWindowSize
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowBordersSize(SDL_Window * window,
+ int *top, int *left,
+ int *bottom, int *right);
+
+/**
+ * Set the minimum size of a window's client area.
+ *
+ * \param window the window to change
+ * \param min_w the minimum width of the window in pixels
+ * \param min_h the minimum height of the window in pixels
+ *
+ * \sa SDL_GetWindowMinimumSize
+ * \sa SDL_SetWindowMaximumSize
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowMinimumSize(SDL_Window * window,
+ int min_w, int min_h);
+
+/**
+ * Get the minimum size of a window's client area.
+ *
+ * \param window the window to query
+ * \param w a pointer filled in with the minimum width of the window, may be
+ * NULL
+ * \param h a pointer filled in with the minimum height of the window, may be
+ * NULL
+ *
+ * \sa SDL_GetWindowMaximumSize
+ * \sa SDL_SetWindowMinimumSize
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowMinimumSize(SDL_Window * window,
+ int *w, int *h);
+
+/**
+ * Set the maximum size of a window's client area.
+ *
+ * \param window the window to change
+ * \param max_w the maximum width of the window in pixels
+ * \param max_h the maximum height of the window in pixels
+ *
+ * \sa SDL_GetWindowMaximumSize
+ * \sa SDL_SetWindowMinimumSize
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowMaximumSize(SDL_Window * window,
+ int max_w, int max_h);
+
+/**
+ * Get the maximum size of a window's client area.
+ *
+ * \param window the window to query
+ * \param w a pointer filled in with the maximum width of the window, may be
+ * NULL
+ * \param h a pointer filled in with the maximum height of the window, may be
+ * NULL
+ *
+ * \sa SDL_GetWindowMinimumSize
+ * \sa SDL_SetWindowMaximumSize
+ */
+extern DECLSPEC void SDLCALL SDL_GetWindowMaximumSize(SDL_Window * window,
+ int *w, int *h);
+
+/**
+ * Set the border state of a window.
+ *
+ * This will add or remove the window's `SDL_WINDOW_BORDERLESS` flag and add
+ * or remove the border from the actual window. This is a no-op if the
+ * window's border already matches the requested state.
+ *
+ * You can't change the border state of a fullscreen window.
+ *
+ * \param window the window of which to change the border state
+ * \param bordered SDL_FALSE to remove border, SDL_TRUE to add border
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetWindowFlags
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowBordered(SDL_Window * window,
+ SDL_bool bordered);
+
+/**
+ * Set the user-resizable state of a window.
+ *
+ * This will add or remove the window's `SDL_WINDOW_RESIZABLE` flag and
+ * allow/disallow user resizing of the window. This is a no-op if the window's
+ * resizable state already matches the requested state.
+ *
+ * You can't change the resizable state of a fullscreen window.
+ *
+ * \param window the window of which to change the resizable state
+ * \param resizable SDL_TRUE to allow resizing, SDL_FALSE to disallow
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetWindowFlags
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowResizable(SDL_Window * window,
+ SDL_bool resizable);
+
+/**
+ * \brief Set the window to always be above the others.
+ *
+ * This will add or remove the window's `SDL_WINDOW_ALWAYS_ON_TOP`
+ * flag. This will bring the window to the front and keep the window above
+ * the rest.
+ *
+ * \param window The window of which to change the always on top state.
+ * \param on_top SDL_TRUE to set the window always on top, SDL_FALSE to disable.
+ *
+ * \sa SDL_SetWindowAlwaysOnTop
+ */
+
+extern DECLSPEC void SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window * window,
+ SDL_bool on_top);
+/**
+ * Show a window.
+ *
+ * \param window the window to show
+ *
+ * \sa SDL_HideWindow
+ * \sa SDL_RaiseWindow
+ */
+extern DECLSPEC void SDLCALL SDL_ShowWindow(SDL_Window * window);
+
+/**
+ * Hide a window.
+ *
+ * \param window the window to hide
+ *
+ * \sa SDL_ShowWindow
+ */
+extern DECLSPEC void SDLCALL SDL_HideWindow(SDL_Window * window);
+
+/**
+ * Raise a window above other windows and set the input focus.
+ *
+ * \param window the window to raise
+ */
+extern DECLSPEC void SDLCALL SDL_RaiseWindow(SDL_Window * window);
+
+/**
+ * Make a window as large as possible.
+ *
+ * \param window the window to maximize
+ *
+ * \sa SDL_MinimizeWindow
+ * \sa SDL_RestoreWindow
+ */
+extern DECLSPEC void SDLCALL SDL_MaximizeWindow(SDL_Window * window);
+
+/**
+ * Minimize a window to an iconic representation.
+ *
+ * \param window the window to minimize
+ *
+ * \sa SDL_MaximizeWindow
+ * \sa SDL_RestoreWindow
+ */
+extern DECLSPEC void SDLCALL SDL_MinimizeWindow(SDL_Window * window);
+
+/**
+ * Restore the size and position of a minimized or maximized window.
+ *
+ * \param window the window to restore
+ *
+ * \sa SDL_MaximizeWindow
+ * \sa SDL_MinimizeWindow
+ */
+extern DECLSPEC void SDLCALL SDL_RestoreWindow(SDL_Window * window);
+
+/**
+ * Set a window's fullscreen state.
+ *
+ * `flags` may be `SDL_WINDOW_FULLSCREEN`, for "real" fullscreen with a
+ * videomode change; `SDL_WINDOW_FULLSCREEN_DESKTOP` for "fake" fullscreen
+ * that takes the size of the desktop; and 0 for windowed mode.
+ *
+ * \param window the window to change
+ * \param flags `SDL_WINDOW_FULLSCREEN`, `SDL_WINDOW_FULLSCREEN_DESKTOP` or 0
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetWindowDisplayMode
+ * \sa SDL_SetWindowDisplayMode
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window,
+ Uint32 flags);
+
+/**
+ * Get the SDL surface associated with the window.
+ *
+ * A new surface will be created with the optimal format for the window, if
+ * necessary. This surface will be freed when the window is destroyed. Do not
+ * free this surface.
+ *
+ * This surface will be invalidated if the window is resized. After resizing a
+ * window this function must be called again to return a valid surface.
+ *
+ * You may not combine this with 3D or the rendering API on this window.
+ *
+ * This function is affected by `SDL_HINT_FRAMEBUFFER_ACCELERATION`.
+ *
+ * \param window the window to query
+ * \returns the surface associated with the window, or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_UpdateWindowSurface
+ * \sa SDL_UpdateWindowSurfaceRects
+ */
+extern DECLSPEC SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window * window);
+
+/**
+ * Copy the window surface to the screen.
+ *
+ * This is the function you use to reflect any changes to the surface on the
+ * screen.
+ *
+ * This function is equivalent to the SDL 1.2 API SDL_Flip().
+ *
+ * \param window the window to update
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowSurface
+ * \sa SDL_UpdateWindowSurfaceRects
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window);
+
+/**
+ * Copy areas of the window surface to the screen.
+ *
+ * This is the function you use to reflect changes to portions of the surface
+ * on the screen.
+ *
+ * This function is equivalent to the SDL 1.2 API SDL_UpdateRects().
+ *
+ * \param window the window to update
+ * \param rects an array of SDL_Rect structures representing areas of the
+ * surface to copy
+ * \param numrects the number of rectangles
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowSurface
+ * \sa SDL_UpdateWindowSurface
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
+ const SDL_Rect * rects,
+ int numrects);
+
+/**
+ * Set a window's input grab mode.
+ *
+ * When input is grabbed the mouse is confined to the window.
+ *
+ * If the caller enables a grab while another window is currently grabbed, the
+ * other window loses its grab in favor of the caller's window.
+ *
+ * \param window the window for which the input grab mode should be set
+ * \param grabbed SDL_TRUE to grab input or SDL_FALSE to release input
+ *
+ * \sa SDL_GetGrabbedWindow
+ * \sa SDL_GetWindowGrab
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+/**
+ * Set a window's keyboard grab mode.
+ *
+ * If the caller enables a grab while another window is currently grabbed, the
+ * other window loses its grab in favor of the caller's window.
+ *
+ * \param window The window for which the keyboard grab mode should be set.
+ * \param grabbed This is SDL_TRUE to grab keyboard, and SDL_FALSE to release.
+ *
+ * \sa SDL_GetWindowKeyboardGrab
+ * \sa SDL_SetWindowMouseGrab
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+/**
+ * Set a window's mouse grab mode.
+ *
+ * \param window The window for which the mouse grab mode should be set.
+ *
+ * \sa SDL_GetWindowMouseGrab
+ * \sa SDL_SetWindowKeyboardGrab
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowMouseGrab(SDL_Window * window,
+ SDL_bool grabbed);
+
+/**
+ * Get a window's input grab mode.
+ *
+ * \param window the window to query
+ * \returns SDL_TRUE if input is grabbed, SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
+
+/**
+ * Get a window's keyboard grab mode.
+ *
+ * \param window the window to query
+ * \returns SDL_TRUE if keyboard is grabbed, and SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetWindowKeyboardGrab
+ * \sa SDL_GetWindowGrab
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window * window);
+
+/**
+ * Get a window's mouse grab mode.
+ *
+ * \param window the window to query
+ * \returns SDL_TRUE if mouse is grabbed, and SDL_FALSE otherwise.
+ *
+ * \sa SDL_SetWindowKeyboardGrab
+ * \sa SDL_GetWindowGrab
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window * window);
+
+/**
+ * Get the window that currently has an input grab enabled.
+ *
+ * \returns the window if input is grabbed or NULL otherwise.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetWindowGrab
+ * \sa SDL_SetWindowGrab
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void);
+
+/**
+ * Set the brightness (gamma multiplier) for a given window's display.
+ *
+ * Despite the name and signature, this method sets the brightness of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().) The
+ * brightness set will not follow the window if it is moved to another
+ * display.
+ *
+ * Many platforms will refuse to set the display brightness in modern times.
+ * You are better off using a shader to adjust gamma during rendering, or
+ * something similar.
+ *
+ * \param window the window used to select the display whose brightness will
+ * be changed
+ * \param brightness the brightness (gamma multiplier) value to set where 0.0
+ * is completely dark and 1.0 is normal brightness
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowBrightness
+ * \sa SDL_SetWindowGammaRamp
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowBrightness(SDL_Window * window, float brightness);
+
+/**
+ * Get the brightness (gamma multiplier) for a given window's display.
+ *
+ * Despite the name and signature, this method retrieves the brightness of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().)
+ *
+ * \param window the window used to select the display whose brightness will
+ * be queried
+ * \returns the brightness for the display where 0.0 is completely dark and
+ * 1.0 is normal brightness.
+ *
+ * \sa SDL_SetWindowBrightness
+ */
+extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
+
+/**
+ * Set the opacity for a window.
+ *
+ * The parameter `opacity` will be clamped internally between 0.0f
+ * (transparent) and 1.0f (opaque).
+ *
+ * This function also returns -1 if setting the opacity isn't supported.
+ *
+ * \param window the window which will be made transparent or opaque
+ * \param opacity the opacity value (0.0f - transparent, 1.0f - opaque)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetWindowOpacity
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window * window, float opacity);
+
+/**
+ * Get the opacity of a window.
+ *
+ * If transparency isn't supported on this platform, opacity will be reported
+ * as 1.0f without error.
+ *
+ * The parameter `opacity` is ignored if it is NULL.
+ *
+ * This function also returns -1 if an invalid window was provided.
+ *
+ * \param window the window to get the current opacity value from
+ * \param out_opacity the float filled in (0.0f - transparent, 1.0f - opaque)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_SetWindowOpacity
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity);
+
+/**
+ * Set the window as a modal for another window.
+ *
+ * \param modal_window the window that should be set modal
+ * \param parent_window the parent window for the modal window
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window);
+
+/**
+ * Explicitly set input focus to the window.
+ *
+ * You almost certainly want SDL_RaiseWindow() instead of this function. Use
+ * this with caution, as you might give focus to a window that is completely
+ * obscured by other windows.
+ *
+ * \param window the window that should get the input focus
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_RaiseWindow
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowInputFocus(SDL_Window * window);
+
+/**
+ * Set the gamma ramp for the display that owns a given window.
+ *
+ * Set the gamma translation table for the red, green, and blue channels of
+ * the video hardware. Each table is an array of 256 16-bit quantities,
+ * representing a mapping between the input and output for that channel. The
+ * input is the index into the array, and the output is the 16-bit gamma value
+ * at that index, scaled to the output color precision.
+ *
+ * Despite the name and signature, this method sets the gamma ramp of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().) The gamma
+ * ramp set will not follow the window if it is moved to another display.
+ *
+ * \param window the window used to select the display whose gamma ramp will
+ * be changed
+ * \param red a 256 element array of 16-bit quantities representing the
+ * translation table for the red channel, or NULL
+ * \param green a 256 element array of 16-bit quantities representing the
+ * translation table for the green channel, or NULL
+ * \param blue a 256 element array of 16-bit quantities representing the
+ * translation table for the blue channel, or NULL
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GetWindowGammaRamp
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowGammaRamp(SDL_Window * window,
+ const Uint16 * red,
+ const Uint16 * green,
+ const Uint16 * blue);
+
+/**
+ * Get the gamma ramp for a given window's display.
+ *
+ * Despite the name and signature, this method retrieves the gamma ramp of the
+ * entire display, not an individual window. A window is considered to be
+ * owned by the display that contains the window's center pixel. (The index of
+ * this display can be retrieved using SDL_GetWindowDisplayIndex().)
+ *
+ * \param window the window used to select the display whose gamma ramp will
+ * be queried
+ * \param red a 256 element array of 16-bit quantities filled in with the
+ * translation table for the red channel, or NULL
+ * \param green a 256 element array of 16-bit quantities filled in with the
+ * translation table for the green channel, or NULL
+ * \param blue a 256 element array of 16-bit quantities filled in with the
+ * translation table for the blue channel, or NULL
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_SetWindowGammaRamp
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowGammaRamp(SDL_Window * window,
+ Uint16 * red,
+ Uint16 * green,
+ Uint16 * blue);
+
+/**
+ * Possible return values from the SDL_HitTest callback.
+ *
+ * \sa SDL_HitTest
+ */
+typedef enum
+{
+ SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */
+ SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */
+ SDL_HITTEST_RESIZE_TOPLEFT,
+ SDL_HITTEST_RESIZE_TOP,
+ SDL_HITTEST_RESIZE_TOPRIGHT,
+ SDL_HITTEST_RESIZE_RIGHT,
+ SDL_HITTEST_RESIZE_BOTTOMRIGHT,
+ SDL_HITTEST_RESIZE_BOTTOM,
+ SDL_HITTEST_RESIZE_BOTTOMLEFT,
+ SDL_HITTEST_RESIZE_LEFT
+} SDL_HitTestResult;
+
+/**
+ * Callback used for hit-testing.
+ *
+ * \param win the SDL_Window where hit-testing was set on
+ * \param area an SDL_Point which should be hit-tested
+ * \param data what was passed as `callback_data` to SDL_SetWindowHitTest()
+ * \return an SDL_HitTestResult value.
+ *
+ * \sa SDL_SetWindowHitTest
+ */
+typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win,
+ const SDL_Point *area,
+ void *data);
+
+/**
+ * Provide a callback that decides if a window region has special properties.
+ *
+ * Normally windows are dragged and resized by decorations provided by the
+ * system window manager (a title bar, borders, etc), but for some apps, it
+ * makes sense to drag them from somewhere else inside the window itself; for
+ * example, one might have a borderless window that wants to be draggable from
+ * any part, or simulate its own title bar, etc.
+ *
+ * This function lets the app provide a callback that designates pieces of a
+ * given window as special. This callback is run during event processing if we
+ * need to tell the OS to treat a region of the window specially; the use of
+ * this callback is known as "hit testing."
+ *
+ * Mouse input may not be delivered to your application if it is within a
+ * special area; the OS will often apply that input to moving the window or
+ * resizing the window and not deliver it to the application.
+ *
+ * Specifying NULL for a callback disables hit-testing. Hit-testing is
+ * disabled by default.
+ *
+ * Platforms that don't support this functionality will return -1
+ * unconditionally, even if you're attempting to disable hit-testing.
+ *
+ * Your callback may fire at any time, and its firing does not indicate any
+ * specific behavior (for example, on Windows, this certainly might fire when
+ * the OS is deciding whether to drag your window, but it fires for lots of
+ * other reasons, too, some unrelated to anything you probably care about _and
+ * when the mouse isn't actually at the location it is testing_). Since this
+ * can fire at any time, you should try to keep your callback efficient,
+ * devoid of allocations, etc.
+ *
+ * \param window the window to set hit-testing on
+ * \param callback the function to call when doing a hit-test
+ * \param callback_data an app-defined void pointer passed to **callback**
+ * \returns 0 on success or -1 on error (including unsupported); call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window * window,
+ SDL_HitTest callback,
+ void *callback_data);
+
+/**
+ * Request a window to demand attention from the user.
+ *
+ * \param window the window to be flashed
+ * \param operation the flash operation
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ */
+extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window * window, SDL_FlashOperation operation);
+
+/**
+ * Destroy a window.
+ *
+ * If `window` is NULL, this function will return immediately after setting
+ * the SDL error message to "Invalid window". See SDL_GetError().
+ *
+ * \param window the window to destroy
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_CreateWindowFrom
+ */
+extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window * window);
+
+
+/**
+ * Check whether the screensaver is currently enabled.
+ *
+ * The screensaver is disabled by default since SDL 2.0.2. Before SDL 2.0.2
+ * the screensaver was enabled by default.
+ *
+ * The default can also be changed using `SDL_HINT_VIDEO_ALLOW_SCREENSAVER`.
+ *
+ * \returns SDL_TRUE if the screensaver is enabled, SDL_FALSE if it is
+ * disabled.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DisableScreenSaver
+ * \sa SDL_EnableScreenSaver
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenSaverEnabled(void);
+
+/**
+ * Allow the screen to be blanked by a screen saver.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DisableScreenSaver
+ * \sa SDL_IsScreenSaverEnabled
+ */
+extern DECLSPEC void SDLCALL SDL_EnableScreenSaver(void);
+
+/**
+ * Prevent the screen from being blanked by a screen saver.
+ *
+ * If you disable the screensaver, it is automatically re-enabled when SDL
+ * quits.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_EnableScreenSaver
+ * \sa SDL_IsScreenSaverEnabled
+ */
+extern DECLSPEC void SDLCALL SDL_DisableScreenSaver(void);
+
+
+/**
+ * \name OpenGL support functions
+ */
+/* @{ */
+
+/**
+ * Dynamically load an OpenGL library.
+ *
+ * This should be done after initializing the video driver, but before
+ * creating any OpenGL windows. If no OpenGL library is loaded, the default
+ * library will be loaded upon creation of the first OpenGL window.
+ *
+ * If you do this, you need to retrieve all of the GL functions used in your
+ * program from the dynamic library using SDL_GL_GetProcAddress().
+ *
+ * \param path the platform dependent OpenGL library name, or NULL to open the
+ * default OpenGL library
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_GetProcAddress
+ * \sa SDL_GL_UnloadLibrary
+ */
+extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path);
+
+/**
+ * Get an OpenGL function by name.
+ *
+ * If the GL library is loaded at runtime with SDL_GL_LoadLibrary(), then all
+ * GL functions must be retrieved this way. Usually this is used to retrieve
+ * function pointers to OpenGL extensions.
+ *
+ * There are some quirks to looking up OpenGL functions that require some
+ * extra care from the application. If you code carefully, you can handle
+ * these quirks without any platform-specific code, though:
+ *
+ * - On Windows, function pointers are specific to the current GL context;
+ * this means you need to have created a GL context and made it current
+ * before calling SDL_GL_GetProcAddress(). If you recreate your context or
+ * create a second context, you should assume that any existing function
+ * pointers aren't valid to use with it. This is (currently) a
+ * Windows-specific limitation, and in practice lots of drivers don't suffer
+ * this limitation, but it is still the way the wgl API is documented to
+ * work and you should expect crashes if you don't respect it. Store a copy
+ * of the function pointers that comes and goes with context lifespan.
+ * - On X11, function pointers returned by this function are valid for any
+ * context, and can even be looked up before a context is created at all.
+ * This means that, for at least some common OpenGL implementations, if you
+ * look up a function that doesn't exist, you'll get a non-NULL result that
+ * is _NOT_ safe to call. You must always make sure the function is actually
+ * available for a given GL context before calling it, by checking for the
+ * existence of the appropriate extension with SDL_GL_ExtensionSupported(),
+ * or verifying that the version of OpenGL you're using offers the function
+ * as core functionality.
+ * - Some OpenGL drivers, on all platforms, *will* return NULL if a function
+ * isn't supported, but you can't count on this behavior. Check for
+ * extensions you use, and if you get a NULL anyway, act as if that
+ * extension wasn't available. This is probably a bug in the driver, but you
+ * can code defensively for this scenario anyhow.
+ * - Just because you're on Linux/Unix, don't assume you'll be using X11.
+ * Next-gen display servers are waiting to replace it, and may or may not
+ * make the same promises about function pointers.
+ * - OpenGL function pointers must be declared `APIENTRY` as in the example
+ * code. This will ensure the proper calling convention is followed on
+ * platforms where this matters (Win32) thereby avoiding stack corruption.
+ *
+ * \param proc the name of an OpenGL function
+ * \returns a pointer to the named OpenGL function. The returned pointer
+ * should be cast to the appropriate function signature.
+ *
+ * \sa SDL_GL_ExtensionSupported
+ * \sa SDL_GL_LoadLibrary
+ * \sa SDL_GL_UnloadLibrary
+ */
+extern DECLSPEC void *SDLCALL SDL_GL_GetProcAddress(const char *proc);
+
+/**
+ * Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary().
+ *
+ * \sa SDL_GL_LoadLibrary
+ */
+extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void);
+
+/**
+ * Check if an OpenGL extension is supported for the current context.
+ *
+ * This function operates on the current GL context; you must have created a
+ * context and it must be current before calling this function. Do not assume
+ * that all contexts you create will have the same set of extensions
+ * available, or that recreating an existing context will offer the same
+ * extensions again.
+ *
+ * While it's probably not a massive overhead, this function is not an O(1)
+ * operation. Check the extensions you care about after creating the GL
+ * context and save that information somewhere instead of calling the function
+ * every time you need to know.
+ *
+ * \param extension the name of the extension to check
+ * \returns SDL_TRUE if the extension is supported, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char
+ *extension);
+
+/**
+ * Reset all previously set OpenGL context attributes to their default values.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GL_GetAttribute
+ * \sa SDL_GL_SetAttribute
+ */
+extern DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void);
+
+/**
+ * Set an OpenGL window attribute before window creation.
+ *
+ * This function sets the OpenGL attribute `attr` to `value`. The requested
+ * attributes should be set before creating an OpenGL window. You should use
+ * SDL_GL_GetAttribute() to check the values after creating the OpenGL
+ * context, since the values obtained can differ from the requested ones.
+ *
+ * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to set
+ * \param value the desired value for the attribute
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_GetAttribute
+ * \sa SDL_GL_ResetAttributes
+ */
+extern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);
+
+/**
+ * Get the actual value for an attribute from the current context.
+ *
+ * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to get
+ * \param value a pointer filled in with the current value of `attr`
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_ResetAttributes
+ * \sa SDL_GL_SetAttribute
+ */
+extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value);
+
+/**
+ * Create an OpenGL context for an OpenGL window, and make it current.
+ *
+ * Windows users new to OpenGL should note that, for historical reasons, GL
+ * functions added after OpenGL version 1.1 are not available by default.
+ * Those functions must be loaded at run-time, either with an OpenGL
+ * extension-handling library or with SDL_GL_GetProcAddress() and its related
+ * functions.
+ *
+ * SDL_GLContext is an alias for `void *`. It's opaque to the application.
+ *
+ * \param window the window to associate with the context
+ * \returns the OpenGL context associated with `window` or NULL on error; call
+ * SDL_GetError() for more details.
+ *
+ * \sa SDL_GL_DeleteContext
+ * \sa SDL_GL_MakeCurrent
+ */
+extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *
+ window);
+
+/**
+ * Set up an OpenGL context for rendering into an OpenGL window.
+ *
+ * The context must have been created with a compatible window.
+ *
+ * \param window the window to associate with the context
+ * \param context the OpenGL context to associate with the window
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \sa SDL_GL_CreateContext
+ */
+extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window * window,
+ SDL_GLContext context);
+
+/**
+ * Get the currently active OpenGL window.
+ *
+ * \returns the currently active OpenGL window on success or NULL on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void);
+
+/**
+ * Get the currently active OpenGL context.
+ *
+ * \returns the currently active OpenGL context or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_MakeCurrent
+ */
+extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void);
+
+/**
+ * Get the size of a window's underlying drawable in pixels.
+ *
+ * This returns info useful for calling glViewport().
+ *
+ * This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI
+ * drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a
+ * platform with high-DPI support (Apple calls this "Retina"), and not
+ * disabled by the `SDL_HINT_VIDEO_HIGHDPI_DISABLED` hint.
+ *
+ * \param window the window from which the drawable size should be queried
+ * \param w a pointer to variable for storing the width in pixels, may be NULL
+ * \param h a pointer to variable for storing the height in pixels, may be
+ * NULL
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_CreateWindow
+ * \sa SDL_GetWindowSize
+ */
+extern DECLSPEC void SDLCALL SDL_GL_GetDrawableSize(SDL_Window * window, int *w,
+ int *h);
+
+/**
+ * Set the swap interval for the current OpenGL context.
+ *
+ * Some systems allow specifying -1 for the interval, to enable adaptive
+ * vsync. Adaptive vsync works the same as vsync, but if you've already missed
+ * the vertical retrace for a given frame, it swaps buffers immediately, which
+ * might be less jarring for the user during occasional framerate drops. If an
+ * application requests adaptive vsync and the system does not support it,
+ * this function will fail and return -1. In such a case, you should probably
+ * retry the call with 1 for the interval.
+ *
+ * Adaptive vsync is implemented for some glX drivers with
+ * GLX_EXT_swap_control_tear:
+ *
+ * https://www.opengl.org/registry/specs/EXT/glx_swap_control_tear.txt
+ *
+ * and for some Windows drivers with WGL_EXT_swap_control_tear:
+ *
+ * https://www.opengl.org/registry/specs/EXT/wgl_swap_control_tear.txt
+ *
+ * Read more on the Khronos wiki:
+ * https://www.khronos.org/opengl/wiki/Swap_Interval#Adaptive_Vsync
+ *
+ * \param interval 0 for immediate updates, 1 for updates synchronized with
+ * the vertical retrace, -1 for adaptive vsync
+ * \returns 0 on success or -1 if setting the swap interval is not supported;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_GetSwapInterval
+ */
+extern DECLSPEC int SDLCALL SDL_GL_SetSwapInterval(int interval);
+
+/**
+ * Get the swap interval for the current OpenGL context.
+ *
+ * If the system can't determine the swap interval, or there isn't a valid
+ * current context, this function will return 0 as a safe default.
+ *
+ * \returns 0 if there is no vertical retrace synchronization, 1 if the buffer
+ * swap is synchronized with the vertical retrace, and -1 if late
+ * swaps happen immediately instead of waiting for the next retrace;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GL_SetSwapInterval
+ */
+extern DECLSPEC int SDLCALL SDL_GL_GetSwapInterval(void);
+
+/**
+ * Update a window with OpenGL rendering.
+ *
+ * This is used with double-buffered OpenGL contexts, which are the default.
+ *
+ * On macOS, make sure you bind 0 to the draw framebuffer before swapping the
+ * window, otherwise nothing will happen. If you aren't using
+ * glBindFramebuffer(), this is the default and you won't have to do anything
+ * extra.
+ *
+ * \param window the window to change
+ */
+extern DECLSPEC void SDLCALL SDL_GL_SwapWindow(SDL_Window * window);
+
+/**
+ * Delete an OpenGL context.
+ *
+ * \param context the OpenGL context to be deleted
+ *
+ * \sa SDL_GL_CreateContext
+ */
+extern DECLSPEC void SDLCALL SDL_GL_DeleteContext(SDL_GLContext context);
+
+/* @} *//* OpenGL support functions */
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_video_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Client/ThirdParty/SDL2/include/SDL_vulkan.h b/Client/ThirdParty/SDL2/include/SDL_vulkan.h
new file mode 100644
index 0000000..006c5aa
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/SDL_vulkan.h
@@ -0,0 +1,213 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 2017, Mark Callow
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_vulkan.h
+ *
+ * Header file for functions to creating Vulkan surfaces on SDL windows.
+ */
+
+#ifndef SDL_vulkan_h_
+#define SDL_vulkan_h_
+
+#include "SDL_video.h"
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Avoid including vulkan.h, don't define VkInstance if it's already included */
+#ifdef VULKAN_H_
+#define NO_SDL_VULKAN_TYPEDEFS
+#endif
+#ifndef NO_SDL_VULKAN_TYPEDEFS
+#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+
+#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
+#else
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#endif
+
+VK_DEFINE_HANDLE(VkInstance)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
+
+#endif /* !NO_SDL_VULKAN_TYPEDEFS */
+
+typedef VkInstance SDL_vulkanInstance;
+typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */
+
+/**
+ * \name Vulkan support functions
+ *
+ * \note SDL_Vulkan_GetInstanceExtensions & SDL_Vulkan_CreateSurface API
+ * is compatable with Tizen's implementation of Vulkan in SDL.
+ */
+/* @{ */
+
+/**
+ * Dynamically load the Vulkan loader library.
+ *
+ * This should be called after initializing the video driver, but before
+ * creating any Vulkan windows. If no Vulkan loader library is loaded, the
+ * default library will be loaded upon creation of the first Vulkan window.
+ *
+ * It is fairly common for Vulkan applications to link with libvulkan instead
+ * of explicitly loading it at run time. This will work with SDL provided the
+ * application links to a dynamic library and both it and SDL use the same
+ * search path.
+ *
+ * If you specify a non-NULL `path`, an application should retrieve all of the
+ * Vulkan functions it uses from the dynamic library using
+ * SDL_Vulkan_GetVkGetInstanceProcAddr unless you can guarantee `path` points
+ * to the same vulkan loader library the application linked to.
+ *
+ * On Apple devices, if `path` is NULL, SDL will attempt to find the
+ * `vkGetInstanceProcAddr` address within all the Mach-O images of the current
+ * process. This is because it is fairly common for Vulkan applications to
+ * link with libvulkan (and historically MoltenVK was provided as a static
+ * library). If it is not found, on macOS, SDL will attempt to load
+ * `vulkan.framework/vulkan`, `libvulkan.1.dylib`,
+ * `MoltenVK.framework/MoltenVK`, and `libMoltenVK.dylib`, in that order. On
+ * iOS, SDL will attempt to load `libMoltenVK.dylib`. Applications using a
+ * dynamic framework or .dylib must ensure it is included in its application
+ * bundle.
+ *
+ * On non-Apple devices, application linking with a static libvulkan is not
+ * supported. Either do not link to the Vulkan loader or link to a dynamic
+ * library version.
+ *
+ * \param path The platform dependent Vulkan loader library name or NULL
+ * \returns 0 on success or -1 if the library couldn't be loaded; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_GetVkInstanceProcAddr
+ * \sa SDL_Vulkan_UnloadLibrary
+ */
+extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path);
+
+/**
+ * Get the address of the `vkGetInstanceProcAddr` function.
+ *
+ * This should be called after either calling SDL_Vulkan_LoadLibrary() or
+ * creating an SDL_Window with the `SDL_WINDOW_VULKAN` flag.
+ *
+ * \returns the function pointer for `vkGetInstanceProcAddr` or NULL on error.
+ */
+extern DECLSPEC void *SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void);
+
+/**
+ * Unload the Vulkan library previously loaded by SDL_Vulkan_LoadLibrary()
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_LoadLibrary
+ */
+extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
+
+/**
+ * Get the names of the Vulkan instance extensions needed to create a surface
+ * with SDL_Vulkan_CreateSurface.
+ *
+ * If `pNames` is NULL, then the number of required Vulkan instance extensions
+ * is returned in `pCount`. Otherwise, `pCount` must point to a variable set
+ * to the number of elements in the `pNames` array, and on return the variable
+ * is overwritten with the number of names actually written to `pNames`. If
+ * `pCount` is less than the number of required extensions, at most `pCount`
+ * structures will be written. If `pCount` is smaller than the number of
+ * required extensions, SDL_FALSE will be returned instead of SDL_TRUE, to
+ * indicate that not all the required extensions were returned.
+ *
+ * The `window` parameter is currently needed to be valid as of SDL 2.0.8,
+ * however, this parameter will likely be removed in future releases
+ *
+ * \param window A window for which the required Vulkan instance extensions
+ * should be retrieved (will be deprecated in a future release)
+ * \param pCount A pointer to an unsigned int corresponding to the number of
+ * extensions to be returned
+ * \param pNames NULL or a pointer to an array to be filled with required
+ * Vulkan instance extensions
+ * \returns SDL_TRUE on success, SDL_FALSE on error.
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_CreateSurface
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_GetInstanceExtensions(SDL_Window *window,
+ unsigned int *pCount,
+ const char **pNames);
+
+/**
+ * Create a Vulkan rendering surface for a window.
+ *
+ * The `window` must have been created with the `SDL_WINDOW_VULKAN` flag and
+ * `instance` must have been created with extensions returned by
+ * SDL_Vulkan_GetInstanceExtensions() enabled.
+ *
+ * \param window The window to which to attach the Vulkan surface
+ * \param instance The Vulkan instance handle
+ * \param surface A pointer to a VkSurfaceKHR handle to output the newly
+ * created surface
+ * \returns SDL_TRUE on success, SDL_FALSE on error.
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_Vulkan_GetInstanceExtensions
+ * \sa SDL_Vulkan_GetDrawableSize
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR* surface);
+
+/**
+ * Get the size of the window's underlying drawable dimensions in pixels.
+ *
+ * This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI
+ * drawable, i.e. the window was created with `SDL_WINDOW_ALLOW_HIGHDPI` on a
+ * platform with high-DPI support (Apple calls this "Retina"), and not
+ * disabled by the `SDL_HINT_VIDEO_HIGHDPI_DISABLED` hint.
+ *
+ * \param window an SDL_Window for which the size is to be queried
+ * \param w Pointer to the variable to write the width to or NULL
+ * \param h Pointer to the variable to write the height to or NULL
+ *
+ * \since This function is available in SDL 2.0.8
+ *
+ * \sa SDL_GetWindowSize
+ * \sa SDL_CreateWindow
+ * \sa SDL_Vulkan_CreateSurface
+ */
+extern DECLSPEC void SDLCALL SDL_Vulkan_GetDrawableSize(SDL_Window * window,
+ int *w, int *h);
+
+/* @} *//* Vulkan support functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_vulkan_h_ */
diff --git a/Client/ThirdParty/SDL2/include/begin_code.h b/Client/ThirdParty/SDL2/include/begin_code.h
new file mode 100644
index 0000000..37bf975
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/begin_code.h
@@ -0,0 +1,166 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file begin_code.h
+ *
+ * This file sets things up for C dynamic library function definitions,
+ * static inlined functions, and structures aligned at 4-byte alignment.
+ * If you don't like ugly C preprocessor code, don't look at this file. :)
+ */
+
+/* This shouldn't be nested -- included it around code only. */
+#ifdef _begin_code_h
+#error Nested inclusion of begin_code.h
+#endif
+#define _begin_code_h
+
+#ifndef SDL_DEPRECATED
+# if (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */
+# define SDL_DEPRECATED __attribute__((deprecated))
+# else
+# define SDL_DEPRECATED
+# endif
+#endif
+
+#ifndef SDL_UNUSED
+# ifdef __GNUC__
+# define SDL_UNUSED __attribute__((unused))
+# else
+# define SDL_UNUSED
+# endif
+#endif
+
+/* Some compilers use a special export keyword */
+#ifndef DECLSPEC
+# if defined(__WIN32__) || defined(__WINRT__) || defined(__CYGWIN__)
+# ifdef DLL_EXPORT
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC
+# endif
+# elif defined(__OS2__)
+# ifdef BUILD_SDL
+# define DECLSPEC __declspec(dllexport)
+# else
+# define DECLSPEC
+# endif
+# else
+# if defined(__GNUC__) && __GNUC__ >= 4
+# define DECLSPEC __attribute__ ((visibility("default")))
+# else
+# define DECLSPEC
+# endif
+# endif
+#endif
+
+/* By default SDL uses the C calling convention */
+#ifndef SDLCALL
+#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__)
+#define SDLCALL __cdecl
+#elif defined(__OS2__) || defined(__EMX__)
+#define SDLCALL _System
+# if defined (__GNUC__) && !defined(_System)
+# define _System /* for old EMX/GCC compat. */
+# endif
+#else
+#define SDLCALL
+#endif
+#endif /* SDLCALL */
+
+/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */
+#ifdef __SYMBIAN32__
+#undef DECLSPEC
+#define DECLSPEC
+#endif /* __SYMBIAN32__ */
+
+/* Force structure packing at 4 byte alignment.
+ This is necessary if the header is included in code which has structure
+ packing set to an alternate value, say for loading structures from disk.
+ The packing is reset to the previous value in close_code.h
+ */
+#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
+#ifdef _MSC_VER
+#pragma warning(disable: 4103)
+#endif
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wpragma-pack"
+#endif
+#ifdef __BORLANDC__
+#pragma nopackwarning
+#endif
+#ifdef _M_X64
+/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
+#pragma pack(push,8)
+#else
+#pragma pack(push,4)
+#endif
+#endif /* Compiler needs structure packing set */
+
+#ifndef SDL_INLINE
+#if defined(__GNUC__)
+#define SDL_INLINE __inline__
+#elif defined(_MSC_VER) || defined(__BORLANDC__) || \
+ defined(__DMC__) || defined(__SC__) || \
+ defined(__WATCOMC__) || defined(__LCC__) || \
+ defined(__DECC) || defined(__CC_ARM)
+#define SDL_INLINE __inline
+#ifndef __inline__
+#define __inline__ __inline
+#endif
+#else
+#define SDL_INLINE inline
+#ifndef __inline__
+#define __inline__ inline
+#endif
+#endif
+#endif /* SDL_INLINE not defined */
+
+#ifndef SDL_FORCE_INLINE
+#if defined(_MSC_VER)
+#define SDL_FORCE_INLINE __forceinline
+#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
+#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__
+#else
+#define SDL_FORCE_INLINE static SDL_INLINE
+#endif
+#endif /* SDL_FORCE_INLINE not defined */
+
+#ifndef SDL_NORETURN
+#if defined(__GNUC__)
+#define SDL_NORETURN __attribute__((noreturn))
+#elif defined(_MSC_VER)
+#define SDL_NORETURN __declspec(noreturn)
+#else
+#define SDL_NORETURN
+#endif
+#endif /* SDL_NORETURN not defined */
+
+/* Apparently this is needed by several Windows compilers */
+#if !defined(__MACH__)
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif /* NULL */
+#endif /* ! Mac OS X - breaks precompiled headers */
diff --git a/Client/ThirdParty/SDL2/include/close_code.h b/Client/ThirdParty/SDL2/include/close_code.h
new file mode 100644
index 0000000..c65a216
--- /dev/null
+++ b/Client/ThirdParty/SDL2/include/close_code.h
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file close_code.h
+ *
+ * This file reverses the effects of begin_code.h and should be included
+ * after you finish any function and structure declarations in your headers
+ */
+
+#ifndef _begin_code_h
+#error close_code.h included without matching begin_code.h
+#endif
+#undef _begin_code_h
+
+/* Reset structure packing at previous byte alignment */
+#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__)
+#ifdef __BORLANDC__
+#pragma nopackwarning
+#endif
+#pragma pack(pop)
+#endif /* Compiler needs structure packing set */
diff --git a/Client/ThirdParty/SDL2/lib/x64/SDL2.dll b/Client/ThirdParty/SDL2/lib/x64/SDL2.dll
new file mode 100644
index 0000000..4553fa9
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x64/SDL2.dll
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x64/SDL2.lib b/Client/ThirdParty/SDL2/lib/x64/SDL2.lib
new file mode 100644
index 0000000..ea6fa42
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x64/SDL2.lib
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x64/SDL2main.lib b/Client/ThirdParty/SDL2/lib/x64/SDL2main.lib
new file mode 100644
index 0000000..20a2421
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x64/SDL2main.lib
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x64/SDL2test.lib b/Client/ThirdParty/SDL2/lib/x64/SDL2test.lib
new file mode 100644
index 0000000..96eaf22
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x64/SDL2test.lib
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x86/SDL2.dll b/Client/ThirdParty/SDL2/lib/x86/SDL2.dll
new file mode 100644
index 0000000..2ee35e1
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x86/SDL2.dll
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x86/SDL2.lib b/Client/ThirdParty/SDL2/lib/x86/SDL2.lib
new file mode 100644
index 0000000..0efa0fd
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x86/SDL2.lib
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x86/SDL2main.lib b/Client/ThirdParty/SDL2/lib/x86/SDL2main.lib
new file mode 100644
index 0000000..c838eb2
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x86/SDL2main.lib
Binary files differ
diff --git a/Client/ThirdParty/SDL2/lib/x86/SDL2test.lib b/Client/ThirdParty/SDL2/lib/x86/SDL2test.lib
new file mode 100644
index 0000000..4048779
--- /dev/null
+++ b/Client/ThirdParty/SDL2/lib/x86/SDL2test.lib
Binary files differ
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.cpp b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.cpp
new file mode 100644
index 0000000..3ea12a3
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.cpp
@@ -0,0 +1,43 @@
+// MyClass.cpp
+//
+#include "stdafx.h"
+#include "MyClass.h"
+
+
+// Initialization of protected static data members:
+void* MyClass::mpStaticMemory = NULL;
+const double MyClass::mPI = 3.141592;
+std::string MyClass::mStaticStr = "Init Value";
+
+
+// Invoke the StaticConstructor & StaticDestructor of the class:
+// Make sure you put this AFTER the initialization of the static data members!
+INVOKE_STATIC_CONSTRUCTOR(MyClass);
+
+
+// Default Constructor:
+MyClass::MyClass()
+{
+// PI = 5.0; // Cannot be done, as PI is const
+ mStaticStr = "Modified by Default Constructor";
+}
+
+// Destructor:
+MyClass::~MyClass()
+{
+ mStaticStr = "Modified by Default Destructor";
+}
+
+// Static Constructor:
+void MyClass::StaticConstructor()
+{
+ mStaticStr = "Modified by Static Constructor";
+ mpStaticMemory = new double[10];
+}
+
+// Static Destructor:
+void MyClass::StaticDestructor()
+{
+ delete[] mpStaticMemory;
+}
+
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.h b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.h
new file mode 100644
index 0000000..5f86f22
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyClass.h
@@ -0,0 +1,36 @@
+// MyClass.h
+//
+#include <string>
+#include <StaticConstructor.h>
+
+
+class MyClass
+{
+protected:
+ // Declaration of protected static data members:
+ // Cannot be initialized here (C++ language limitation)
+ static void* mpStaticMemory;
+ static const double mPI;
+ static std::string mStaticStr;
+
+public:
+ // Static function members to get the static data members (to unify the Tests):
+ static const double& PI() { return mPI; };
+ static std::string& StaticStr() { return mStaticStr; };
+
+public:
+ // Default Constructor:
+ MyClass();
+
+ // Destructor:
+ virtual ~MyClass();
+
+ // Static Constructor:
+ // (Should be called by INVOKE_STATIC_CONSTRUCTOR macro in the CPP file)
+ STATIC_CONSTRUCTOR();
+
+ // Static Destructor:
+ // (Should be called by INVOKE_STATIC_CONSTRUCTOR macro in the CPP file)
+ STATIC_DESTRUCTOR();
+};
+
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyTemplate.h b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyTemplate.h
new file mode 100644
index 0000000..a0a147c
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/MyTemplate.h
@@ -0,0 +1,48 @@
+// MyTemplate.h
+//
+#include <string>
+#include <StaticConstructor.h>
+
+
+template <typename Type>
+class MyTemplate
+{
+protected:
+ // Declaration and initialization of protected static Data-Function member:
+ STATIC_DF_MEMBER(Type*, pStaticMemory, NULL);
+
+public:
+ // Declaration and initialization of public static Data-Function members:
+ STATIC_DF_MEMBER(const double, PI, 3.141592);
+ STATIC_DF_MEMBER(std::string, StaticStr, "Init Value");
+
+public:
+ // Default Constructor:
+ MyTemplate()
+ {
+ // PI() = 5.0; // Cannot be done, as PI is const
+ StaticStr() = "Modified by Default Constructor";
+ }
+
+ // Destructor:
+ virtual ~MyTemplate()
+ {
+ StaticStr() = "Modified by Default Destructor";
+ }
+
+ // Static Constructor:
+ // (Should be called by INVOKE_STATIC_CONSTRUCTOR macro in one CPP file)
+ STATIC_CONSTRUCTOR()
+ {
+ StaticStr() = "Modified by Static Constructor";
+ pStaticMemory() = new Type[10];
+ }
+
+ // Static Destructor:
+ // (Should be called by INVOKE_STATIC_CONSTRUCTOR macro in one CPP file)
+ STATIC_DESTRUCTOR()
+ {
+ delete[] pStaticMemory();
+ }
+};
+
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.cpp b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.cpp
new file mode 100644
index 0000000..26ff046
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.cpp
@@ -0,0 +1,76 @@
+// StaticConstructorSample.cpp : Defines the entry point for the console application.
+//
+#include "stdafx.h"
+#include <iostream>
+#include <string>
+
+// Sample Files:
+#include "MyClass.h"
+#include "MyTemplate.h"
+
+
+// Sample code for StartUp
+STATIC_STARTUP_CODE()
+{
+ std::cout << "Starting up..." << std::endl;
+}
+
+// Sample code for FinishUp
+STATIC_FINISHUP_CODE()
+{
+ std::cout << "Finishing up..." << std::endl;
+}
+
+
+// Template for testing each Type:
+template <typename Type>
+void TestType(const std::string& strType)
+{
+ using namespace std;
+
+ // Static Constructor should have been already invoked:
+ cout << "Show static data members before creating any instance of " << strType << ":" << endl;
+ cout << "String: " << Type::StaticStr() << endl;
+ cout << "PI: " << Type::PI() << endl;
+
+ // Temporary block:
+ // Destructor of local variable will be called at the end of this block.
+ {
+ Type myObj;
+ cout << "Show static data members after creating an instance of " << strType << ":" << endl;
+ cout << "String: " << myObj.StaticStr() << endl;
+ cout << "PI: " << myObj.PI() << endl;
+ }
+
+ cout << "Show static data members after destroying the instance of " << strType << ":" << endl;
+ cout << "String: " << Type::StaticStr() << endl;
+ cout << "PI: " << Type::PI() << endl;
+ cout << endl;
+}
+
+
+// Declaration of alias (class names) for the template instaces:
+typedef MyTemplate<int> MyTemplateInt;
+typedef MyTemplate<double> MyTemplateDouble;
+
+// Invoke the StaticConstructor & StaticDestructor for each one of the template instances:
+// Should be called with alias (class names) for the template instaces.
+INVOKE_STATIC_CONSTRUCTOR(MyTemplateInt);
+INVOKE_STATIC_CONSTRUCTOR(MyTemplateDouble);
+
+
+// Main:
+int _tmain(int argc, _TCHAR* argv[])
+{
+ // Static Constructors have already been called before entering this function...
+
+ // Run the same tests for each one of the classes:
+ TestType<MyClass>("MyClass");
+ TestType<MyTemplateInt>("MyTemplateInt");
+ TestType<MyTemplateDouble>("MyTemplateDouble");
+
+ // Static Destructors will be called after exiting this function...
+ return 0;
+}
+
+
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.sln b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.sln
new file mode 100644
index 0000000..265f06c
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StaticConstructorSample", "StaticConstructorSample.vcproj", "{41329043-C008-486E-99A9-BC1A0B4DF9A5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {41329043-C008-486E-99A9-BC1A0B4DF9A5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {41329043-C008-486E-99A9-BC1A0B4DF9A5}.Debug|Win32.Build.0 = Debug|Win32
+ {41329043-C008-486E-99A9-BC1A0B4DF9A5}.Release|Win32.ActiveCfg = Release|Win32
+ {41329043-C008-486E-99A9-BC1A0B4DF9A5}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.vcproj b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.vcproj
new file mode 100644
index 0000000..0f66ceb
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/StaticConstructorSample.vcproj
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="StaticConstructorSample"
+ ProjectGUID="{41329043-C008-486E-99A9-BC1A0B4DF9A5}"
+ RootNamespace="StaticConstructorSample"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="include"
+ >
+ <File
+ RelativePath="..\include\StaticConstructor.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Sample Files"
+ >
+ <File
+ RelativePath=".\MyClass.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MyClass.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MyTemplate.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Project Files"
+ >
+ <File
+ RelativePath=".\StaticConstructorSample.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\stdafx.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\stdafx.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.cpp b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.cpp
new file mode 100644
index 0000000..88d97ab
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// StaticConstructorSample.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.h b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.h
new file mode 100644
index 0000000..022bc3b
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/StaticConstructorSample/stdafx.h
@@ -0,0 +1,24 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+// The following macros define the minimum required platform. The minimum required platform
+// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
+// your application. The macros work by enabling all features available on platform versions up to and
+// including the version specified.
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
+#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+// STL includes
+#include <stdio.h>
+#include <tchar.h>
+
+
+// TODO: reference additional headers your program requires here
diff --git a/Client/ThirdParty/StaticConstructor/include/StaticConstructor.h b/Client/ThirdParty/StaticConstructor/include/StaticConstructor.h
new file mode 100644
index 0000000..22310bd
--- /dev/null
+++ b/Client/ThirdParty/StaticConstructor/include/StaticConstructor.h
@@ -0,0 +1,126 @@
+//////////////////////////////////////////////////////////////////////////////
+// AUTHOR: Hugo Gonzlez Castro
+// TITLE: Static Constructor in C++
+// DESCRIPTION: An easy way to implement static constructors and
+// static destructors in standard C++.
+// VERSION: v1.2 - 2011/11/27
+// LICENSE: CPOL (Code Project Open License).
+// Please, do not remove nor modify this header.
+// URL: http://www.codeproject.com/KB/cpp/StaticConstructor.aspx
+//////////////////////////////////////////////////////////////////////////////
+#ifndef _STATIC_CONSTRUCTOR_H_
+#define _STATIC_CONSTRUCTOR_H_
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// DECLARATIONS (macros to use):
+//////////////////////////////////////////////////////////////////////////////
+
+
+// REQUIRED macro to invoke the static constructor/destructor of a class:
+// place the call to this macro out of the definition of the class, in a .CPP file
+// (avoid using it in .H files unless they are included only once).
+// Make sure you put this AFTER the initialization of the static data members!
+// For templates, should be called with alias (typedef) for the template instaces.
+//////////////////////////////////////////////////////////////////////////////
+#define INVOKE_STATIC_CONSTRUCTOR(ClassName) \
+ INVOKE_STATIC_CONSTRUCTOR_EXPANDED(ClassName)
+
+
+// OPTIONAL macros to help to declare the header of the static constructor/destructor:
+// place the calls to these macros inside the definition of the class/template, in a .H file
+//////////////////////////////////////////////////////////////////////////////
+#define STATIC_CONSTRUCTOR() static void StaticConstructor()
+#define STATIC_DESTRUCTOR() static void StaticDestructor()
+
+
+// OPTIONAL macro to declare static Data-Function members with inline initialization:
+// place the call to this macro inside the definition of the class/template.
+//////////////////////////////////////////////////////////////////////////////
+// STATIC DF MEMBER (static Data-Function member):
+// "a static function member with a static local (data) variable declared inside".
+// The TypeName can be or not a CONST type.
+//////////////////////////////////////////////////////////////////////////////
+#define STATIC_DF_MEMBER(TypeName, DFMemberName, InitValue) \
+ STATIC_DF_MEMBER_EXPANDED(TypeName, DFMemberName, InitValue)
+
+
+// OPTIONAL macros to run code at startup and finishup. Place outside classes.
+// Place the static code inside {} after one of these macros.
+//////////////////////////////////////////////////////////////////////////////
+#define STATIC_STARTUP_CODE() STATIC_STARTUP_CODE_EXPANDED()
+#define STATIC_FINISHUP_CODE() STATIC_FINISHUP_CODE_EXPANDED()
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+// IMPLEMENTATION (do not directly use these macros):
+//////////////////////////////////////////////////////////////////////////////
+
+
+// Definition of special class to invoke
+// the static constructor/destructor from
+// its own non-static constructor/destructor.
+template<typename ClassName>
+class StaticInvoker
+{
+public:
+ // Default Constructor:
+ StaticInvoker()
+ {
+ // Call to the static constructor of ClassName:
+ ClassName::StaticConstructor();
+ }
+
+ // Destructor:
+ virtual ~StaticInvoker()
+ {
+ // Call to the static destructor of ClassName:
+ ClassName::StaticDestructor();
+ }
+};
+
+
+// Macro with expanded name:
+#define INVOKE_STATIC_CONSTRUCTOR_EXPANDED(ClassName) \
+ /* Single instance of this invoker class, so its constructor is called only once */ \
+ StaticInvoker<ClassName> staticInvokerOf_##ClassName;
+
+
+// STATIC DF MEMBER (static Data-Function member):
+// "a static function member with a static local (data) variable declared inside".
+// The TypeName can be or not a CONST type.
+#define STATIC_DF_MEMBER_EXPANDED(TypeName, DFMemberName, InitValue) \
+ static TypeName& DFMemberName() \
+ { \
+ static TypeName DFMemberName(InitValue); \
+ return DFMemberName; \
+ }
+
+
+// Expanded macro to run code at startup.
+#define STATIC_STARTUP_CODE_EXPANDED() \
+ class StartUpCode \
+ { \
+ public: \
+ StartUpCode(); \
+ }; \
+ StartUpCode myStartUpCode; \
+ StartUpCode::StartUpCode()
+
+
+// Expanded macro to run code at finishup.
+#define STATIC_FINISHUP_CODE_EXPANDED() \
+ class FinishUpCode \
+ { \
+ public: \
+ FinishUpCode() {}; \
+ virtual ~FinishUpCode(); \
+ }; \
+ FinishUpCode myFinishUpCode; \
+ FinishUpCode::~FinishUpCode()
+
+
+
+#endif // _STATIC_CONSTRUCTOR_H_
diff --git a/Client/ThirdParty/freetype/ChangeLog b/Client/ThirdParty/freetype/ChangeLog
new file mode 100644
index 0000000..e649d31
--- /dev/null
+++ b/Client/ThirdParty/freetype/ChangeLog
@@ -0,0 +1,7815 @@
+2021-07-18 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.11.0 released.
+ ==========================
+
+
+ Tag sources with `VER-2-11-0'.
+
+ * docs/VERSION.TXT: Add entry for version 2.11.0.
+ * docs/CHANGES: Updated.
+
+ * README, src/base/ftver.rc, builds/windows/vc2010/index.html,
+ builds/windows/visualc/index.html,
+ builds/windows/visualce/index.html,
+ builds/wince/vc2005-ce/index.html,
+ builds/wince/vc2008-ce/index.html, docs/freetype-config.1:
+ s/2.10.4/2.11.0/, s/2104/2110/.
+
+ * include/freetype/freetype.h (FREETYPE_MINOR): Set to 11.
+ (FREETYPE_PATCH): Set to 0.
+
+ * builds/unix/configure.raw (version_info): Set to 24:0:18.
+ * CMakeLists.txt (VERSION_MINOR): Set to 11.
+ (VERSION_PATCH): Set to 0.
+
+ * builds/toplevel.mk (dist): Ignore more git-related files.
+
+2021-07-17 David Turner <david@freetype.org>
+
+ * src/smooth/ftgrays.c: Fix compilation if `FT_LONG64` is undefined.
+
+ The code assumed that if `__SSE2__` is defined, then 64-bit integer
+ types are available. This is not the case apparently for certain
+ multilib compiler targets like 'x86_32.x86' used by Gentoo.
+
+ This patch fixes the issue by disabling the special code path when
+ 64-bit integer types are not available.
+
+ Fixes #1071.
+
+2021-07-16 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
+
+ [tests] Allow arbitrary build directories.
+
+ * tests/issue-1063/main.c (main): I am building with a build
+ directory that is not directly inside the source tree, so the path
+ `../tests/data/As.I.Lay.Dying.ttf` does not resolve to the test
+ input file. This change passes the test data directory as an
+ environment variable to allow arbitrary build directories.
+
+ * tests/meson.build: Updated.
+
+2021-07-16 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
+
+ * tests/issue-1063/main.c (main): Fix uninitialized variable.
+
+ I tried running `meson test` but the test just crashed and gdb
+ reported that the face argument to `FT_Get_Char_Index` was nonsense.
+ With this change the test prints 'Could not open file: ' as it
+ should.
+
+2021-07-16 Werner Lemberg <wl@gnu.org>
+
+ [smooth] Minor fixes.
+
+ * src/smooth/ftgrays.c (gray_render_conic): Move variable and
+ structure declarations to beginning of function. Inspite of C99
+ compliance we still do this for the sake of backward compatibility.
+ This also avoids a shadowing declaration of `count`.
+ (gray_convert_glyph_inner): Fix typo.
+
+2021-07-15 Ben Wagner <bungeman@chromium.org>
+
+ * src/smooth/ftgrays.c: Guard inclusion of `emmintrin.h`.
+
+ Guard inclusion of `emmintrin.h` with `#ifdef __SSE2__`. The gcc
+ version of this header, `xmmintrin.h`, and `mmintrin.h` check that
+ the appropriate defines are set before defining anything (are
+ internally guarded). However, the clang versions of these includes
+ are not internally guarded. As a result of this, externally guard
+ the inclusion of these headers.
+
+2021-07-15 David Turner <david@freetype.org>
+
+ [smooth] Implement Bézier quadratic arc flattening with DDA.
+
+ Benchmarking shows that this provides a very slighty performance
+ boost when rendering fonts with lots of quadratic Bézier arcs,
+ compared to the recursive arc splitting, but only when SSE2 is
+ available, or on 64-bit CPUs.
+
+ On a 2017 Core i5-7300U CPU on Linux/x86_64:
+
+ ftbench -p -s10 -t5 -cb DroidSansFallbackFull.ttf
+
+ Before: 4.033 us/op (best of 5 runs for all numbers)
+ After: 3.876 us/op
+
+ ftbench -p -s60 -t5 -cb DroidSansFallbackFull.ttf
+
+ Before: 13.467 us/op
+ After: 13.385 us/op
+
+ * src/smooth/ftgrays.c (gray_render_conic): New implementation
+ based on DDA and optionally SSE2.
+
+2021-07-15 David Turner <david@freetype.org>
+
+ [smooth] Minor speedup to smooth rasterizer.
+
+ This speeds up the smooth rasterizer by avoiding conditional
+ branches in the hot path.
+
+ - Define a fixed 'null cell', which will be pointed to whenever the
+ current cell is outside of the current target region. This avoids
+ a `ras.cell != NULL` check in the `FT_INTEGRATE` macro.
+
+ - Also use the null cell as a sentinel at the end of all `ycells`
+ linked-lists, by setting its x coordinate to `INT_MAX`. This
+ avoids a `if (!cell)` check in `gray_set_cell` as well.
+
+ - Slightly change the worker struct fields to perform a little less
+ operations during rendering.
+
+ Example results (on a 2013 Corei5-3337U CPU)
+
+ out/ftbench -p -s10 -t5 -bc DroidSansFallbackFull.ttf
+
+ Before: 5.472 us/op
+ After: 5.275 us/op
+
+ out/ftbench -p -s60 -t5 -bc DroidSansFallbackFull.ttf
+
+ Before: 17.988 us/op
+ After: 17.389 us/op
+
+ * src/smooth/ftgrays.c (grat_TWorker): Replace `num_cells` field with
+ `cell_free` and `cell_limit`.
+ (NULL_CELL_PTR, CELL_MAX_X_VALUE, CELL_IS_NULL): New macros.
+ (gray_dump_cells, gray_set_cell, gray_sweep, gray_sweep_direct,
+ gray_convert_glyph_inner, gray_convert_glyph): Updated.
+
+2021-07-15 David Turner <david@freetype.org>
+
+ [tests] Rewrite download script in Python3.
+
+ This commit replaces the bash script with a Python script that does
+ the same work, plus avoiding to download anything if the files are
+ already installed with the right content.
+
+ We now use the first 8 bytes of each file's sha256 hash for the
+ digest.
+
+ * tests/scripts/download-test-fonts.sh: Removed.
+ * tests/scripts/download-test-fonts.py: New script.
+ * tests/README.md: Updated.
+
+2021-07-15 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
+
+ Support architectures where `long` is smaller than pointers.
+
+ I am currently trying to compile FreeType for CHERI-extended ISAs
+ (CHERI-RISC-V and Arm's Morello), but I am getting compiler warnings
+ from the `FT_UINT_TO_POINTER` macro. When compiling with the CHERI
+ Clang compiler, not using `uinptr_t` for casts between integers an
+ pointers results in the following `-Werror` build failures:
+
+ ```
+ In file included from .../src/truetype/truetype.c:22:
+ .../src/truetype/ttgload.c:1925:22: error:
+ cast from provenance-free integer type to pointer type will
+ give pointer that can not be dereferenced
+ [-Werror,-Wcheri-capability-misuse]
+ node->data = FT_UINT_TO_POINTER( glyph_index );
+ ^
+ .../include/freetype/internal/compiler-macros.h:79:34: note:
+ expanded from macro 'FT_UINT_TO_POINTER'
+ ```
+
+ * include/freetype/internal/compiler-macros.h (FT_UINT_TO_POINTER):
+ The ISO C standard compliant fix for this would be to use
+ `uintptr_t` from `stdint.h`, but I am not sure if this is supported
+ by the minimum compiler version. Therefore, use the
+ compiler-defined `__UINTPTR_TYPE__` macro (supported in GCC 4.6+ and
+ Clang since about 3.0) before checking for `_WIN64` and falling back
+ to `unsigned long`.
+
+2021-07-13 Oleg Oshmyan <chortos@inbox.lv>
+
+ [base] Fix `FT_Open_Face`'s handling of user-supplied streams.
+
+ This was already true (though undocumented) most of the time, but
+ not if `FT_NEW` inside `FT_Stream_New` failed or if the
+ `FT_OPEN_XXX` flags were bad.
+
+ Normally, `FT_Open_Face` calls `FT_Stream_New`, which returns the
+ user-supplied stream unchanged, and in case of any subsequent error
+ in `FT_Open_Face`, the stream is closed via `FT_Stream_Free`.
+
+ Up to now, however, `FT_Stream_New` allocates a new stream even if
+ it is already given one by the user. If this allocation fails, the
+ user-supplied stream is not returned to `FT_Open_Face` and never
+ closed. Moreover, the user cannot detect this situation: all they
+ see is that `FT_Open_Face` returns `FT_Err_Out_Of_Memory`, but that
+ can also happen after a different allocation fails within the main
+ body of `FT_Open_Face`, when the user's stream has already been
+ closed by `FT_Open_Face`. It is plausible that the user stream's
+ `close` method frees memory allocated for the stream object itself,
+ so the user cannot defensively free it upon `FT_Open_Face` failure
+ lest it ends up doubly freed. All in all, this ends up leaking the
+ memory/resources used by user's stream.
+
+ Furthermore, `FT_Stream_New` simply returns an error if the
+ `FT_OPEN_XXX` flags are unsupported, which can mean either an
+ invalid combination of flags or a perfectly innocent
+ `FT_OPEN_STREAM` on a FreeType build that lacks stream support.
+ With this patch, the user-supplied stream is closed even in these
+ cases, so the user can be sure that if `FT_Open_Face` failed, the
+ stream is definitely closed.
+
+ * src/base/ftobjs.c (FT_Stream_New): Don't allocate a buffer
+ unnecessarily.
+ Move error-handling code to make the control flow more obvious.
+ Close user-supplied stream if the flags are unsupported.
+ `FT_Stream_Open` always sets `pathname.pointer`, so remove the
+ redundant (re)assignment. None of the `FT_Stream_Open...` functions
+ uses `stream->memory`, so keep just one assignment at the end,
+ shared among all possible control flow paths.
+ ('Unsupported flags' that may need a stream closure can be either an
+ invalid combination of multiple `FT_OPEN_XXX` mode flags or a clean
+ `FT_OPEN_STREAM` flag on a FreeType build that lacks stream
+ support.)
+
+2021-07-13 Oleg Oshmyan <chortos@inbox.lv>
+
+ [base] Reject combinations of incompatible `FT_OPEN_XXX` flags.
+
+ The three modes are mutually exclusive, and the documentation of the
+ `FT_OPEN_XXX` constants notes this. However, there was no check to
+ validate this in the code, and the documentation on `FT_Open_Args`
+ claimed that the corresponding bits were checked in a well-defined
+ order, implying it was valid (if useless) to specify more than one.
+ Ironically, this documented order did not agree with the actual
+ code, so it could not be relied upon; hopefully, nobody did this and
+ nobody will be hurt by the new validation.
+
+ Even if multiple mode bits were allowed, they could cause memory
+ leaks: if both `FT_OPEN_STREAM` and `stream` are set along with
+ either `FT_OPEN_MEMORY` or `FT_OPEN_PATHNAME`, then `FT_Stream_New`
+ allocated a new stream but `FT_Open_Face` marked it as an 'external'
+ stream, so the stream object was never released.
+
+ * src/base/ftobjs.c (FT_Stream_New): Reject incompatible
+ `FT_OPEN_XXX` flags.
+
+2021-07-12 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
+
+ * meson.build: Fix build for other UNIX systems (e.g., FreeBSD).
+
+ Without this change the build of `unix/ftsystem.c` fails because the
+ `ftconfig.h` header that defines macros such as `HAVE_UNISTD_H` and
+ `HAVE_FCNTL_H` is only being generated for Linux, macOS, and Cygwin
+ systems:
+
+ ```
+ .../builds/unix/ftsystem.c:258:32: error:
+ use of undeclared identifier 'O_RDONLY'
+ file = open( filepathname, O_RDONLY );
+ ```
+
+ Instead of hardcoding a list of operating systems for this check,
+ update the logic that decides whether to build the file and set a
+ boolean flag that can be checked instead.
+
+2021-07-12 Werner Lemberg <wl@gnu.org>
+
+ [autofit] More clean-ups.
+
+ * src/autofit/afhints.h (AF_GlyphHintsRec): Remove the no longer
+ needed fields `xmin_delta` and `xmax_delta`.
+
+ * src/autofit/afhints.c (af_glyph_hints_reload),
+ src/autofit/afloader.c (af_loader_load_glyph): Updated.
+
+2021-07-12 Werner Lemberg <wl@gnu.org>
+
+ Small clean-ups for the last few commits.
+
+ * include/freetype/fttrace.h (afwarp): Removed.
+
+2021-07-12 David Turner <david@freetype.org>
+
+ Remove obsolete `AF_Angle` type and related sources.
+
+ * src/autofit/afangles.c: File removed. Functions related to
+ sorting moved to...
+ * src/autofit/afhints.c (af_sort_pos, af_sort_and_quantize_widths):
+ This file.
+ * src/autofit/afangles.h: File removed.
+ * src/autofit/aftypes.h: Updated.
+ * src/autofit/autofit.c: Updated.
+
+ * src/autofit/rules.mk (AUTOF_DRV_SRC): Updated.
+
+2021-07-12 David Turner <david@freetype.org>
+
+ Remove experimental auto-hinting 'warp' mode.
+
+ This feature was always experimental, and probably never worked
+ properly. This patch completely removes it from the source code,
+ except for a documentation block describing it for historical
+ purposes.
+
+ * devel/ftoption.h, include/freetype/config/ftoption.h: Remove
+ `AF_CONFIG_OPTION_USE_WARPER`.
+
+ * include/freetype/ftdriver.h: Document 'warping' property as
+ obsolete.
+
+ * src/autofit/afwarp.c, src/autofit/afwarp.h: Files removed.
+ * src/autofit/*: Remove any code related to warp mode.
+
+2021-07-12 David Turner <david@freetype.org>
+
+ Remove experimental 'Latin2' writing system (`FT_OPTION_AUTOFIT2`).
+
+ This code has always been experimental and was never compiled anyway
+ (`FT_OPTION_AUTOFIT2` does not appear in `ftoption.h` or even any of
+ our build files).
+
+ * include/freetype/internal/fttrace.h (aflatin2): Removed.
+ * src/autofit/aflatin2.h, src/autofit/aflatin2.c: Files removed.
+ * src/autofit/afloader.c: Remove undocumented hook to activate
+ Latin2 system.
+ * src/autofit/afstyles.h: Remove `ltn2_dflt` style definition.
+ * src/autofit/afwrtsys.h: Remove `LATIN2` writing system definition.
+ * src/autofit/autofit.c: Updated.
+
+2021-07-05 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftlcdfil.c (FT_Library_SetLcdGeometry): Fix argument.
+
+ Reported by Hin-Tak.
+
+2021-07-03 Werner Lemberg <wl@gnu.org>
+
+ * meson_options.txt: Sort alphabetically; no final full stops.
+
+2021-07-01 Ben Wagner <bungeman@chromium.org>
+
+ * src/truetype/ttgxvar.c (tt_set_mm_blend): Test `coords`.
+
+ It is undefined behavior to pass `NULL` to `memcpy`. `coords' is
+ passed to `memcpy` but `TT_Get_MM_Blend` and `TT_Get_Var_Design`
+ explictly call `tt_set_mm_blend` with `coords` as `NULL`. In
+ addition, `TT_Set_MM_Blend` has a similar possible issue.
+
+2021-06-30 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Support PaintScale in 'COLR' v1 parsing.
+
+ * include/freetype/ftcolor.h (FT_PaintFormat): Renumber values, add
+ `FT_COLR_PAINTFORMAT_SCALE`.
+ (FT_PaintScale): New structure to represent 'PaintScale*' tables.
+ (FT_COLR_Paint): Updated.
+
+ * src/sfnt/ttcolr.c (FT_PaintFormat_Internal): New enumeration.
+ (read_paint): Parse 'PaintScale' and friends.
+
+2021-06-30 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Handle fonts without layer list in 'COLR' v1.
+
+ 'COLR' v1 fonts do not necessarily need to have a layer list; for
+ this reason, 'fontTools' recently started generating fonts in a way
+ that drops the layer list if there are no layers in it. This
+ results in the layer list offset becoming zero, which FreeType
+ treated as an invalid table. Fix that and handle the case for layer
+ list offset being 0. This slightly changes how we need to calculate
+ the starting offset for paints.
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr): Handle case of layer list
+ offset being zero without outright rejecting table.
+
+2021-06-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/raster/ftraster.c (Render_Single_Pass): Simplify `band_stack'.
+
+2021-06-29 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Do not skip the second pass without dropout control.
+
+ The second pass also fixes horizontal lines through the pixel centers.
+
+ * src/raster/ftraster.c (black_TWorker): Do not use `second_pass'.
+ (Render_Glyph): Skip the second pass only with the appropriate flag.
+
+2021-06-29 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Handle sub-band stack locally.
+
+ * src/raster/ftraster.c (black_TWorker): Move `band_stack' from here..
+ (Render_Single_Pass): ... to here and accept limit arguments.
+ (Render_Glyph): Updated.
+
+2021-06-25 Anurag Thakur <anuthadev@gmail.com>
+
+ [CI] Introduce linux CI and refactor job names.
+
+ * .gitlab-ci.yml: Added jobs for building freetype on linux.
+
+2021-06-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Handle Bézier stack locally.
+
+ * src/raster/ftraster.c (black_TWorker): Move `arcs' from here...
+ (Conic_To, Cubic_To): ... to here to tighten their scope.
+ (Bezier_Up, Bezier_Down): ... Take the current `arc' argument.
+
+2021-06-28 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Improve paint limit checks
+
+ Paint tables can appear before the `base_glyphs_v1` offset if the
+ font is produced with the layer list before the base glyph list. In
+ this case paint tables can occur after the layer list but before the
+ base glyph list. Checks in the 'COLR' v1 code were rejecting fonts
+ with this layout. Improve these checks by calculating a minimum
+ offset after which paint tables can occur and use that in safety
+ checks.
+
+ * src/sfnt/ttcolr.c (Colr, tt_face_load_colr): Declare
+ `paint_start_v1` and calculate that as the minimum of the end of
+ layer list and base glyph list.
+ (get_child_table_pointer, read_paint, tt_face_get_paint_layers):
+ Use that in safety checks.
+
+2021-06-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Clean up vertical sweep.
+
+ * src/raster/ftraster.c (black_TWorker): Replace the current line
+ offset with the pointer and drop the increment.
+ (Function_Sweep_Init): Take values as arguments instead of pointers.
+ (Vertical_Sweep_*, Horizontal_Sweep_Init, Draw_Sweep): Updated.
+
+2021-06-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Make `band_top' local variable.
+
+ * src/raster/ftraster.c (black_TWorker): Move `band_top' from here...
+ (Render_Single_Pass): ... to here, and refactor.
+ (Render_Glyph): Updated.
+
+2021-06-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Adjust sub-band bisecting limits.
+
+ We can bisect a band until it is just a single scan line. This might
+ be slow and cause time-outs but if we need to impose limits it should
+ be elsewhere.
+
+ * src/raster/ftraster.c (Render_Single_Pass): Tweak sub-banding.
+
+2021-06-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/raster/ftraster.c (Render_Single_Pass): Remove dead code.
+
+2021-06-25 Werner Lemberg <wl@gnu.org>
+
+ [base] Add trace level to logging output.
+
+ Some practical debugging work has shown that displaying level X of
+ an `FT_TRACEX` macro in the output of `FT2_DEBUG="... -v"` would be
+ very helpful to find out which trace level should be selected. As
+ an example, we now get output like
+
+ ```
+ [ttobjs:2] TTF driver
+ [ttobjs:2] SFNT driver
+ [sfobjs:2] not a font using the SFNT container format
+ [t1objs:2] Type 1 driver
+ [stream:7] FT_Stream_EnterFrame: 14 bytes
+ ```
+
+ * include/freetype/internal/ftdebug.h (FT_LOGGING_TAGX): New macro.
+ (FT_LOG): Use it to add the trace level to the logging tag.
+
+ * include/freetype/internal/fttrace.h (FT_MAX_TRACE_LEVEL_LENGTH):
+ Adjust.
+
+ * docs/DEBUG: Updated.
+
+2021-06-24 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth, raster] Fix up and align error codes.
+
+ FT_Render_Glyph picked up FAILURE or 1 returned from the raster
+ function, which became a confusing error code. Instead, return
+ Raster_Overflow in the unlikely event that banding does not help or
+ another meaningful error.
+
+ * src/smooth/ftgrays.c (gray_convert_glyph_inner, gray_convert_glyph):
+ Use Raster_Overflow when the rendering pool is exhausted and return it
+ if banding does not help.
+ (gray_raster_render): Use Smooth_Err_Ok.
+
+ * src/raster/ftraster.c (Render_Single_Pass): Return Raster_Overflow
+ if banding does not help or another error code.
+
+2021-06-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth, raster] Remove synonymous error macros.
+
+ * src/smooth/ftgays.c [STANDALONE_]: s/ErrRaster_/Smooth_Err_/.
+ (gray_convert_glyph_inner): Updated accordingly.
+
+ * src/raster/ftraster.c [STANDALONE_]: Do not abbreviate error macros.
+ (New_Profile, End_Profile, Insert_Y_Turn, Line_Up, Bezier_Up,
+ Decompose_Curve, Draw_Sweep, Render_Single_Pass, ft_black_render):
+ Updated accordingly.
+
+2021-06-22 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] s/PaintTransformed/PaintTransform/, s/transformed/transform/.
+
+ * include/freetype/ftcolor.h (FT_PaintTransformed, FT_PaintFormat,
+ FT_COLR_Paint): Do it to make it harmonize with other names such as
+ 'PaintTranslate'.
+
+ * src/sfnt/ttcolr.c (read_paint, tt_face_get_paint): Ditto.
+
+2021-06-22 Dominik Röttsches <drott@chromium.org>
+
+ Move 'COLR' API to `ftcolor.h`.
+
+ * include/freetype/freetype.h: Cut section layer managament
+ containing 'COLR' v0 and v1 API and move it to `ftcolor.h` as
+ requested by Werner on freetype-devel.
+ * include/freetype/ftcolor.h: Paste that section.
+
+2021-06-19 Werner Lemberg <david@freetype.org>
+
+ [truetype] Fix integer overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35312
+
+ * src/truetype/ttinterp.c (Ins_JMPR): Use `ADD_LONG`.
+
+2021-06-19 Werner Lemberg <david@freetype.org>
+
+ [autofit] Prevent hinting if there are too many segments.
+
+ This speeds up handling of broken glyphs.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35309
+
+ * src/autofit/aflatin.c (af_latin_hints_compute_segments): Implement
+ it.
+
+2021-06-18 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sdf/ftsdfrend.c (ft_(b)sdf_render): Do not FT_ERROR routinely.
+
+2021-06-16 David Turner <david@freetype.org>
+
+ [autofit] Fix return value of `FT_Load_Glyph`.
+
+ * src/autofit/afglobal.c (af_face_globals_get_metrics): The issue is
+ that `style_metrics_init` sometimes returns -1 without clearing
+ `error`. While looping to `Again`, the next operation is
+ successful, but -1 is still returned by the function. The fix is to
+ set `error` to 0 appropriately.
+
+ Fixes #1063.
+
+2021-06-15 David Turner <david@freetype.org>
+
+ [meson] Add first regression test to FreeType.
+
+ * tests/README.md: New file that explains how to build and run the
+ tests with the Meson build.
+
+ * tests/scripts/download-test-fonts.sh: New bash script to download
+ test font files to the `tests/data` folder.
+
+ * meson.build, meson_options.txt: Add 'tests' option to enable
+ building and running the test programs (disabled by default).
+
+ * tests/meson.build: New file.
+
+ * tests/issue-1063/main.c: Simple regression test to exhibit issue
+ 1063.
+
+ * .gitignore: Ignore the content of the `tests/data` folder for
+ now.
+
+2021-06-12 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [type42] Fix new memory leak.
+
+ We need to inverse inheritance of FT_GlyphSlot_Internal so that we
+ have a chance to free the rendered bitmap from the parent slot.
+
+ * src/type42/t42objs.c (T42_GlyphSlot_Init): Remove the internal parts
+ of the child `ttslot' and replace it with the parent structure.
+ (T42_GlyphSlot_Done): Updated accordingly.
+
+2021-06-12 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix another assertion.
+
+ * src/psaux/psintrp.c (cf2_interpT2CharString)
+ <cf2_escCALLOTHERSUBR>: Convert assertion into error, since the
+ problem can happen with invalid user input.
+
+ Test case is file
+
+ fuzzing/corpora/legacy/oss-fuzz/5754332360212480-unknown-read
+
+ in the `freetype2-testing` repository.
+
+2021-06-12 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix assertions.
+
+ * src/psaux/pshints.c (cf2_hintmap_adjustHints): Check for overflow
+ before emitting an assertion error.
+
+ Test case is file
+
+ fuzzing/corpora/legacy/oss-fuzz/4594115297673216-integer-overflow
+
+ in the `freetype2-testing` repository.
+
+2021-06-09 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttinterp.c (TT_RunIns): Optimize tracing.
+
+2021-06-09 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sdf] Fix SDF positioning.
+
+ * src/sdf/ftsdfrend.c (ft_sdf_render, ft_bsdf_render): Add padding to
+ `bitmap_top' and `bitmap_left'.
+
+ * sdf/sdf/ftsdf.c (sdf_generate_with_overlaps): Fix VC++ warning.
+
+2021-06-08 Werner Lemberg <wl@gnu.org>
+
+ Fix 'devel' build for 'COLR' v1.
+
+ * devel/ftoption.h: Synchronize with
+ `include/freetype/config/ftoption.h`.
+
+2021-06-08 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Sanitize cmap4 table better.
+
+ Fixes #1062.
+
+ * src/sfnt/ttcmap.c (tt_cmap4_validate): Handle a too-small value of
+ `length` gracefully.
+
+2021-06-08 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Pointer validity check when reading 'COLR' v1 layers
+
+ * src/sfnt/ttcolr.c (tt_face_get_paint_layers): In addition to the
+ existing sanity checks, ensure that the pointer to the layer to be
+ read is within the 'COLR' v1 table.
+
+2021-06-08 Werner Lemberg <wl@gnu.org>
+
+ * src/sdf/ftsdfcommon.c: Fix inclusion of header files.
+
+2021-06-08 Werner Lemberg <wl@gnu.org>
+
+ [sdf] Make `make multi` work.
+
+ * src/sdf/ftsdf.c: Include `ftbitmap.h`.
+
+ * src/sdf/ftsdfcommon.h: Move function bodies to `ftsdfcommon.c`.
+ Include `ftobjs.h` to get definitions of `FT_LOCAL` and friends.
+
+ * src/sdf/ftsdfcommon.c: New file.
+
+ * src/sdf/rules.mk, src/sdf/sdf.c: Updated.
+
+2021-06-08 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Use 8 bits for final SDF output instead of 16bits.
+
+ Since 8-bits is enough to represent SDF data we no longer require
+ 16-bits for this purpose. Also, we now normalize the output data
+ to use the entire 8-bit range efficiently. For example: if we use
+ 3.5 format with a spread of 1 we basically only use the starting
+ 5-bits. By normalizing we can use the entire 8-bit range.
+
+ * include/freetype/freetype.h (FT_Render_Mode): Updated description
+ for `FT_RENDER_MODE_SDF` regarding this change.
+
+ * include/freetype/ftimage.h (FT_Pixel_Mode): Removed
+ `FT_PIXEL_MODE_GRAY16` since no longer required.
+
+ * include/freetype/fttypes.h (FT_F6Dot10): Removed since no longer
+ required.
+
+ * src/sdf/ftsdfrend.c (ft_sdf_render, ft_bsdf_render): Allocate 8-bit
+ bitmap instead of 16-bit buffer.
+
+ * src/sdf/ftsdfcommon.h (map_fixed_to_sdf): Added function to convert
+ 16.16 distance value to our desired format.
+
+ * src/sdf/ftsdf.c (sdf_generate_with_overlaps,
+ sdf_generate_bounding_box): Use the new `map_fixed_to_sdf` function
+ and also use 8-bit output buffer.
+
+ * src/sdf/ftbsdf.c (finalize_sdf): Output to a 8-bit buffer instead
+ of 16-bit buffer.
+
+2021-06-02 Ben Wagner <bungeman@chromium.org>
+ Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix fallout from 2021-05-29 change.
+
+ * src/sfnt/ttcolr.c (find_base_glyph_record,
+ find_base_glyph_v1_record): Adjust binary search.
+
+ Needs to be updated with change to unsigned.
+
+2021-06-02 Werner Lemberg <wl@gnu.org>
+
+ * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Fix tracing.
+
+ Problem reported by Alexei.
+
+2021-06-02 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix MSVC compiler warnings.
+
+ * src/psaux/afmparse.c (afm_parse_track_kern, afm_parse_kern_pairs):
+ Add cast.
+
+2021-05-29 Werner Lemberg <wl@gnu.org>
+
+ Fix compilation errors and (some) warnings for clang++.
+
+ * src/autofit/afmodule.c (AF_GlyphHintsRec): Make it static.
+
+ * src/cache/ftcache.c (FTC_Cache_NewNode), src/cache/ftcsbits.c
+ (ftc_snode_compare): Remove semicolon.
+
+ * src/cff/cffparse.c (cff_parser_run): Add `break` statement.
+
+ * src/cid/cidload.c (cid_hex_to_binary): Add cast.
+
+ * src/sdf/ftbsdf.c (CHECK_NEIGHBOR): Use `do {} while(0)` loop.
+ (bsdf_init_distance_map, finalize_sdf, bsdf_raster_render): Add
+ casts.
+ * src/sdf/ftsdf.c (sdf_generate_bounding_box,
+ sdf_generate_with_overlaps): Ditto.
+ * src/sdf/ftsdfcommon.h (square_root): Ditto.
+ * src/sdf/ftsdfrend.c (sdf_property_get, ft_sdf_render,
+ ft_bsdf_render): Ditto.
+
+ * src/sfnt/ttcolr.c (find_base_glyph_record,
+ find_base_glyph_v1_record): Fix variable signedness.
+ (read_color_line): Add cast.
+ (read_paint): Add casts.
+ Fix signedness issue.
+ (tt_face_get_colorline_stops) Fix signedness issues.
+
+ * src/sfnt/ttpost.c (load_format_20): Add casts.
+
+ * src/truetype/ttsubpix.c (TWEAK_RULES, TWEAK_RULES_EXCEPTIONS):
+ Remove final semicolons.
+
+2021-05-29 Werner Lemberg <wl@gnu.org>
+
+ [build] Allow overriding of `ANSIFLAGS` for GNU make build.
+
+ * builds/*: Implement it.
+
+2021-05-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [type42] Fix auto-hinting.
+
+ The autohinter could not access the base (unscaled) outline in the
+ child TrueType glyph slot. We now share the internal parts between
+ the parent and child glyph slots. Fixes #1057.
+
+ * src/type42/t42objs.c (T42_GlyphSlot_Init): Remove the internal parts
+ of `T42_GlyphSlot' and replace it with the child TrueType structure.
+ (T42_GlyphSlot_Done): Updated accordingly.
+
+2021-05-25 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Guard and trace AFM kern data allocation.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=31543
+
+ * include/freetype/internal/fttrace.h: Add 'afmparse' trace
+ component.
+
+ * src/psaux/afmparse.c (FT_COMPONENT): Define.
+ (afm_parse_track_kern, afm_parse_kern_pairs): Protect against
+ allocations bombs.
+ Add tracing.
+ (afm_parse_kern_data): Don't allow multiple kern data sections.
+
+2021-05-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * meson.build (ft2_public_headers): Add missing `ftcid.h'.
+
+ Fixes #1058.
+
+2021-05-20 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [type42] Avoid some memory zeroing.
+
+ * src/type42/t42objs.c (T42_Open_Face): Tweak allocation macro.
+ * src/type42/t42parse.c (t42_parse_sfnts): Ditto.
+
+2021-05-19 Nikolaus Waxweiler <madigens@gmail.com>
+
+ [CMake] Update dependency finders.
+
+ 1. Fixes CMake using any found HarfBuzz version lower than the minimum
+ required. This is based on HALX99's merge request at
+ https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests/31
+ 2. Update FindHarfBuzz.cmake from
+ https://github.com/WebKit/WebKit/blob/1ce32454/Source/cmake/FindHarfBuzz.cmake
+ and guard post-CMake-3.1 features to keep the minimum version unchanged
+ 3. Update FindBrotliDec.cmake to stop the warnings, based on what
+ https://github.com/google/woff2/blob/a0d0ed7d/cmake/FindBrotliDec.cmake
+ is doing
+
+ * CMakeLists.txt, builds/cmake/FindHarfBuzz.cmake: Implement 1 and 2.
+ * builds/cmake/FindBrotliDec.cmake: Implement 3.
+
+2021-05-19 Ben Wagner <bungeman@chromium.org>
+
+ [gzip] Use exact type for `ft_gzip_alloc` and `ft_gzip_free`.
+
+ While a function pointer may be cast to another function pointer
+ type, it is required to cast the function pointer back to the
+ original function pointer type before calling it. If a parameter is
+ a pointer the exact pointer type is required. Using a pointer to a
+ different underlying type is technically undefined behavior. The
+ wrapper functions `ft_gzip_alloc` and `ft_gzip_free` took
+ `FT_Memory` (a `FT_MemoryRec_*`) instead of `voidpf` (`void*`), so
+ when gzip calls these callbacks through `alloc_func` or `free_func`
+ it invokes undefined behavior. On most platforms this works out as
+ expected, but newer undefined behavior detectors and targets like
+ wasm can detect this and will produce an error.
+
+ * src/gzip/ftgzip.c (ft_gzip_alloc, ft_gzip_free): Update signatures
+ to exactly match `alloc_func` and `free_func`, respectively.
+ Internally, cast the `void*` opaque pointer to `FT_Memory`.
+
+2021-05-18 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Prioritize the anti-aliasing renderer module.
+
+ * modules.cfg: Reorder the renderers.
+ * include/freetype/config/ftmodule.h: Ditto.
+
+2021-05-16 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sfnt] Additional guards on the POST table.
+
+ Fixes timeout (#1055) analyzed by Ben Wagner, reported as
+
+ https://crbug.com/1194092
+
+ * src/sfnt/ttload.c (tt_face_load_post): Check POST format.
+ * src/sfnt/sfobjs.c (sfnt_load_face): Synthesize the missing unicode
+ charmap only if the glyph names exist.
+ * src/psnames/psmodule.c (ps_unicode_value): Short cut ".notdef" and
+ ".null".
+
+2021-05-13 Daniel McArdle <dmcardle@chromium.org>
+
+ [psaux] Use doubling allocation strategy for CF2_ArrStack.
+
+ Fixes timeout reported as
+
+ https://crbug.com/1206181
+
+ * src/psaux/psarrst.c (cf2_arrstack_{push,init}): Implement it.
+ * src/psaux/psarrst.h (CF2_ArrStackiRec): Drop `chunk'.
+
+2021-05-12 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (FT_MAX_GRAY_SPANS): Increase from 10 to 16.
+
+ Ten was barely enough for two slanted stems. Sixteen can actually fit
+ a bit more complicated scanlines.
+
+2021-05-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (FT_GRAY_SET): Adjust for better code.
+
+2021-05-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Faster bitmap sweeping.
+
+ Selecting the fill rule or checking the direct mode each time we call
+ `gray_hline' is sub-optimal. This effectively splits the direct mode
+ into a separate code path while inlining `gray_hline' and saving 5-7%
+ of rendering time.
+
+ * src/smooth/ftgrays.c (gray_hline): Eliminated in favor of...
+ (FT_FILL_RULE, FT_GRAY_SET): ... these new macros...
+ (gray_sweep): ... inlined here.
+ (gray_sweep_direct): New function that handles the direct span buffer.
+ (gray_TWorker): Remove the span buffer.
+ (gray_raster_render, gray_convert_glyph): Updated.
+
+2021-05-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (gray_hline): Simplify even-odd computations.
+
+ It is too bad the even-odd rule is not used much.
+
+2021-05-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [type1] Avoid MM memory zeroing.
+
+ * src/type1/t1load.c (t1_allocate_blend, parse_blend_design_map):
+ Tweak allocation macros.
+ * src/type1/t1objs.c (T1_Face_Done): Minor.
+
+2021-05-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/bdf/bdflib.c (_bdf_list_ensure): Tweak allocation macro.
+
+2021-05-06 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/psaux/psobjs.c (ps_parser_load_field): Tweak allocation macro.
+
+2021-05-06 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/sfobjs.c (sfnt_load_face): Tweak allocation macro.
+
+2021-05-06 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/cid/cidload.c (cid_read_subrs): Tweak allocation macro.
+
+2021-05-06 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Tweak allocation.
+
+2021-05-05 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cff,psaux] Avoid memory zeroing (contd.).
+
+ * src/cff/cffload.c (cff_blend_doBlend, cff_blend_build_vector): Tweak
+ allocation macros.
+ * src/psaux/psarrst.c (cf2_arrstack_setNumElements): Ditto.
+ * src/psaux/psstack.c (cf2_stack_init): Ditto.
+
+2021-05-04 Ben Wagner <bungeman@chromium.org>
+
+ * src/cid/cidload.c (cid_hex_to_binary): Improve return value.
+
+ Add argument to return the actual number of bytes that were decoded.
+ The actual number of bytes decoded can be quite variable depending
+ on the number of ignored 'whitespace' bytes or early termination
+ with `>`.
+ (cid_face_open): Updated to use this calculated value. This avoids
+ trusting `parser->binary_length` is always be correct and reading
+ uninitialized bits if fewer are actually decoded.
+
+ First reported as
+
+ https://crbug.com/1203240
+
+2021-05-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sfnt] Streamline POST format 2.0 handing.
+
+ To reduce memory allocations, we read an entire Pascal-string buffer
+ and convert it to a C-string buffer. We also reject tables with
+ Postscript glyph names exceeding 63 bytes.
+
+ * src/sfnt/ttpost.c (load_format20): Implement it.
+ (load_post_names): Check the minimal POST table size.
+ (load_format25, tt_face_free_ps_names): Updated accordingly.
+
+2021-05-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf,pcf] Avoid memory zeroing (contd.).
+
+ * src/bdf/bdflib.c (bdf_create_property, _bdf_add_comment,
+ _bdf_add_property, bdf_load_font): Tweak allocation macros.
+ * src/pcf/pcfread.c (pcf_get_properties, pcf_get_metrics): Ditto.
+
+2021-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/cid/cidload.c (cid_read_subrs): Tweak allocaton macro.
+
+2021-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sfnt] Avoid some memory zeroing.
+
+ * src/sfnt/sfobjs.c (sfnt_open_font, sfnt_init_face,
+ tt_name_ascii_from_{utf16,other}): Tweak allocaton macros.
+ * src/sfnt/ttload.c (tt_face_load_name): Ditto.
+
+2021-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/ttpost.c (load_format_{20,25}): Tweak allocaton macros.
+
+2021-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/pngshim.c (Load_SBit_Png): Tweak allocaton macro.
+
+2021-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [truetype] Avoid some memory zeroing.
+
+ * src/truetype/ttinterp.c (Init_Context): Tweak allocation macro.
+ * src/truetype/ttpload.c (tt_face_load_cvt): Ditto.
+
+2021-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [woff2] Avoid some memory zeroing.
+
+ * src/sfnt/sfwoff2.c (store_loca, woff2_open_font): Tweak macros.
+
+2021-04-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/gzip/ftgzip.c (ft_gzip_alloc): Zero out memory again.
+
+2021-04-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [lzw] Preserve decompression stack when relocating to heap.
+
+ * src/lzw/ftzopen.c (ft_lzwstate_stack_grow): Copy stack when
+ relocating to heap.
+
+2021-04-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/cid/cidgload.c (cid_load_glyph): Restore the glyph_length check.
+
+2021-04-27 Werner Lemberg <wl@gnu.org>
+
+ * src/psmodule.c (ps_unicodes_init): Ignore empty glyph names.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33637
+
+2021-04-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/sfobjs.c (sfnt_init_face): Revert macro change.
+
+2021-04-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cff] Avoid some memory zeroing.
+
+ * src/cff/cffparse.c (cff_parser_init): Tweak memory macro.
+ * src/cff/cffload.c (cff_index_load_offsets, cff_index_get_pointers,
+ cff_charset_load, cff_vstore_load): Ditto.
+
+2021-04-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pfr] Avoid some memory zeroing.
+
+ * src/pfr/pfrobjs.c (pfr_face_init) : Tweak memory macro.
+ * src/pfr/pfrload.c (pfr_extra_item_load_stem_snaps,
+ pfr_phy_font_load): Ditto.
+
+2021-04-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/winfonts/winfnt.c (FNT_Face_Init): Tweak memory macro.
+
+2021-04-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [psaux,psnames] Avoid some memory zeroing.
+
+ * src/psaux/psstack.c (cf2_stack_init): Tweak memory macro.
+ * src/psnames/psmodule.c (ps_unicodes_init): Ditto.
+
+2021-04-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] Avoid some memory zeroing.
+
+ * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Use FT_QNEW_ARRAY.
+ * src/base/ftsnames.c (FT_Get_Sfnt_{Name,LangTag}): Ditto.
+
+2021-04-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf,pcf] Avoid some memory zeroing.
+
+ * src/pcf/pcfread.c (pcf_read_TOC, pcf_get_properties, pcf_load_font):
+ Tweak memory macros.
+ * src/bdf/bdfdrivr.c (BDF_Face_Init): Ditto.
+ * src/bdf/bdflib.c (_bdf_readstreami, bdf_create_property,
+ _bdf_parse_glyphs, _bdf_parse_start): Ditto.
+ (_bdf_add_property): Do not handle zero size.
+
+2021-04-25 Issam E. Maghni <issam.e.maghni@mailbox.org>
+
+ * builds/meson/process_ftoption_h.py: Add LF at EOF.
+
+ This fixes
+
+ .../ftoption.h:1030:10: error:
+ no newline at end of file [-Werror,-Wnewline-eof]
+
+ for the generated `ftoption.h` file.
+
+2021-04-24 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/cff/cffload.c (cff_index_get_pointers): s/FT_QALLOC/FT_ALLOC/.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (Mac_Read_POST_Resource): s/FT_ALLOC/FT_QALLOC/.
+ * builds/mac/ftmac.c (FT_New_Face_From_SFNT, read_lwfn): Ditto.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sdf/ftsdf.c (sdf_{edge,contour,shape}_new): Use FT_QALLOC.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sfnt] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/sfnt/sfdriver.c (get_win_string, get_apple_string,
+ sfnt_get_var_ps_name): Do not zero out the buffer.
+ * src/sfnt/sfobjs.c (sfnt_init_face): Ditto.
+ * src/sfnt/sfwoff.c (woff_open_font): Ditto.
+ * src/sfnt/sfwoff2.c (woff2_open_font): Ditto.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cff,type1,type42] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/cff/cffload.c (cff_index_get_pointers, cff_index_get_name):
+ Do not zero out the buffer.
+ * src/cff/cffdrivr.c (cff_ps_get_font_info): Ditto.
+ * src/type1/t1load.c (parse_subrs, parse_charstrings,
+ parse_blend_axis_types): Ditto.
+ * src/type1/t1parse.c (T1_New_Parser, T1_Get_Private_Dict): Ditto.
+ * src/type42/t42parse.c (t42_parser_init): Ditto.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cid] s/FT_ALLOC/FT_QALLOC/ and clean up.
+
+ * src/cid/cidgload.c (cid_load_glyph): Do not zero out the buffer.
+ * src/cid/cidload.c (cid_face_open, cid_read_subrs): Ditto.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pfr] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/pfr/pfrload.c (pfr_extra_item_load_font_id, pfr_aux_name_load):
+ Do not zero out the buffer.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bzip2,gzip] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/bzip2/ftbzip2.c (ft_bzip2_alloc): Do not zero out the buffer.
+ * src/gzip/ftgzip.c (ft_gzip_alloc, FT_Stream_OpenGzip): Ditto.
+
+2021-04-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf,bdf,winfonts] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/pcf/pcfread.c (pcf_interpret_style): Do not zero out the buffer.
+ * src/bdf/bdfdrivr.c (bdf_interpret_style): Ditto.
+ * src/winfonts/winfnt.c (FNT_Face_Init, FNT_Load_Glyph): Ditto.
+
+2021-04-22 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cache] Optimize SBit copying.
+
+ * src/cache/ftcsbits.c (ftc_snode_load): Do not initialize the buffer.
+ (ftc_sbit_copy_bitmap): Accept zero size, s/FT_ALLOC/FT_QALLOC/.
+
+2021-04-22 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [gxvalid,otvalid] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/gxvalid/gxvmod.c (gxv_load_table): Do not zero out the buffer.
+ * src/otvalid/otvmod.c (otv_load_table): Ditto.
+
+2021-04-22 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [psaux] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/psaux/psobjs.c (ps_table_done, ps_parser_load_field): Do not
+ zero out the buffer.
+
+2021-04-22 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+ * src/base/ftobjs.c (open_face_PS_from_sfnt_stream,
+ Mac_Read_sfnt_Resource): Do not zero out the buffer.
+ * src/base/ftmac.c (FT_New_Face_From_SFNT, read_lwfn): Ditto.
+ * src/base/ftrfork.c (raccess_make_file_name,
+ raccess_guess_darwin_hfsplus, raccess_guess_darwin_newvfs): Ditto.
+
+2021-04-20 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cache] Restore SBit copying for unowned (BDF) bitmaps.
+
+ * src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): Restore.
+ (ftc_snode_load): Check ownership and copy unowned bitmaps.
+
+2021-04-19 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Return in 'COLR' v1 when layer pointer outside table
+
+ * src/sfnt/ttcolr.c (tt_face_get_paint_layers): Add missing return
+ when paint pointer outside table.
+ (read_paint): Add missing return when paint pointer outside table.
+
+2021-04-18 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cache] Switch to lazy SBit setting.
+
+ * src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): Removed.
+ (ftc_snode_load): Take the bitmap ownership instead of copying.
+
+2021-04-16 Daniel Welty <@danielwelty>
+
+ * src/cache/ftcsbits.c (ftc_snode_load): Properly handle short pitch.
+
+2021-04-16 Werner Lemberg <wl@gnu.org>
+
+ * builds/unix/freetype2.m4: Fix help string formatting.
+
+ The indented `dnl` macros inserted unwanted horizontal space.
+
+ Problem reported by Ozkan Sezer <sezeroz@gmail.com>.
+
+2021-04-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Safeguard 'COLR' v1 layer extraction
+
+ * src/sfnt/ttcolr.c (tt_face_get_paint_layers): Do not output
+ layer pointer to iterator if it is outside the 'COLR' table.
+ (read_paint): Do not attempt to read layers that are outside the
+ table.
+
+2021-04-02 Ben Wagner <bungeman@chromium.org>
+
+ [base] Complete `ft_glyphslot_clear`.
+
+ * src/base/ftobjs.c (ft_glyphslot_clear): This function is intended
+ to reset all the values of a glyph slot. However, it was not
+ resetting the values of the advances and `glyph_index`. Reset the
+ advances and `glyph_index` to zero.
+
+2021-04-02 Ben Wagner <bungeman@chromium.org>
+
+ [truetype] Prevent glyph program state from persisting.
+
+ `FDEF` instructions are specified as allowed only in 'prep' or
+ 'fpgm'. FreeType has attempted to prevent their use in the glyph
+ program, but they were still allowed in glyph programs if defined in
+ a function defined in 'prep' or 'fpgm' and called from the glyph
+ program.
+
+ Similarly, `IDEF` instructions are specified not to be able to
+ modify any existing instruction. FreeType has attempted to prevent
+ their use in the glyph program, but they can still be used like
+ `FDEF`.
+
+ This change stores the initial bytecode range type and disallows the
+ use of `FDEF` and `IDEF` while running the glyph program.
+
+ Most other state is copied from the `TT_Size` into the execution
+ context. However, it is possible for a glyph program to use `WS` to
+ write to the storage area or `WCVTP`, `WCVTF`, and `DELTAC[123]` to
+ write to the control value table.
+
+ Allowing any change to the global state from the glyph program is
+ problematic as the outlines of any given glyph may change based on
+ the order the glyphs are loaded or even how many times they are
+ loaded. There exist fonts that write to the storage area or the
+ control value table in the glyph program, so their use should not be
+ an error.
+
+ Possible solutions to using these in the glyph program are
+
+ * ignore the writes;
+ * value-level copy on write, discard modified values when finished;
+ * array-level copy on write, discard the copy when finished;
+ * array-level copy up-front.
+
+ Ignoring the writes may break otherwise good uses. A full copy
+ up-front was implemented, but was quite heavy as even well behaved
+ fonts required a full copy and the memory management that goes along
+ with it. Value-level copy on write could use less memory but
+ requires a great deal more record keeping and complexity. This
+ change implements array-level copy on write. If any attempt is made
+ to write to the control value table or the storage area when the
+ initial bytecode range was in a glyph program, the relevant array
+ will be copied to a designated storage area and the copy used for
+ the rest of the glyph program's execution.
+
+ * src/truetype/ttinterp.h (TT_ExecContextRec): New fields
+ `iniRange`, `glyfCvtSize`, `glyfCvt`, `origCvt`, `glyfStoreSize`,
+ `glyfStorage`, and `origStorage`.
+
+ * src/truetype/ttinterp.c (Modify_CVT_Check): New function to handle
+ `exc->glyfCvt`.
+ (Write_CVT, Write_CVT_Stretched, Move_CVT, Move_CVT_Stretched): Use
+ it.
+ (Ins_WS): Handle `exc->glyfStorage`.
+ (Ins_FDEF, Ins_IDEF): Updated.
+ (TT_RunIns): Updated.
+ (TT_Done_Context): Free 'glyf' CVT working and storage area.
+ (TT_Load_Context): Fix/add casts.
+
+ * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Fix cast.
+
+2021-03-30 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Check validity of pointer location of `read_color_line`.
+
+ * src/sfnt/ttcolr.c (get_child_table_pointer): New function to fetch
+ child table pointer early for all paint formats that compute a child
+ table pointer.
+ (read_color_line, read_paint): Updated.
+ (tt_face_get_colorline_stops): Check `colr->table`.
+
+2021-03-28 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [docs] Update docwriter stylesheet for 1.3.1.
+
+ This change is required to support docwriter 1.3.1.
+
+ See
+
+ https://gitlab.freedesktop.org/freetype/docwriter/-/merge_requests/101
+
+ for more information.
+
+ * docs/markdown/stylesheets/extra.css:
+ (.wy-nav-content, .md-sidebar--secondary): Remove.
+
+2021-03-16 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/pngshim.c (Load_SBit_Png): Free `rows` once later.
+
+2021-03-16 Ben Wagner <bungeman@google.com>
+
+ [sfnt] Fix memory leak in png loading.
+
+ Reported as
+
+ https://bugs.chromium.org/p/chromium/issues/detail?id=1182552
+
+ Memory is allocated and the pointer assigned to `rows` inside a
+ 'setjmp' scope. This memory must be freed outside the 'setjmp'
+ scope after a 'longjmp'. Since `rows` is a local and modified
+ inside the 'setjmp' scope it must be marked volatile or it will have
+ an indeterminate value after the 'longjmp'.
+
+ * src/sfnt/pngshim.c (Load_SBit_Png): Fix memory leak of `rows`.
+
+2021-03-16 Christopher Degawa <ccom@randomderp.com>
+
+ * CMakeLists.txt: Don't limit generation of 'pkg-config' file to UNIX.
+
+ mingw-w64 uses the 'pkg-config' files but does not set UNIX.
+
+2021-03-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (gray_set_cell): Refactor to fix VC++ warning.
+
+2021-03-13 Werner Lemberg <wl@gnu.org>
+
+ Handle various VC++ compiler warnings.
+
+ Fixes #1039.
+
+ * src/base/ftstroke.c (ft_stroker_inside, ft_stroker_outside):
+ Initialize `sigma`.
+
+ * src/sdf/ftsdf.c (sdf_generate_with_overlaps): Exit immediately if
+ function arguments are invalid.
+ * src/sdf/ftsdfrend.c (sdf_property_set) <"overlaps">: Fix cast.
+
+ * src/sfnt/sfwoff2.c (woff2_decompress)
+ [!FT_CONFIG_OPTION_USE_BROTLI]: Use `FT_UNUSED`.
+
+ * src/truetype/ttgxvar.c (TT_Get_MM_Var): Initialize `fvar_head`.
+
+2021-03-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Reduce copying during integration phase.
+
+ We now record `cover' and `area' directly into the linked list. This
+ makes rendering faster by 10% or even more at larger sizes.
+
+ * src/smooth/ftgrays.c (FT_INTEGRATE): Write directly.
+ (gray_TWorker): Add direct cell reference and remove unused fields.
+ (gray_set_cell): Consolidate the linked list management and pointers.
+ (gray_convert_glyph, gray_convert_glyph_inner): Updated.
+
+2021-03-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (FT_INTEGRATE): New convenience macro.
+ (gray_render_line, gray_render_scanline): Use it.
+
+2021-03-09 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (gray_render_line): Rearrange conditionals.
+
+ These produce faster or more optimizable code.
+
+2021-03-08 Tim-Philipp Müller <tim@centricular.com>
+
+ [meson] Fix 'mmap' handling on Windows.
+
+ * meson.build (ft2_sources): Always use `windows/ftsystem.c` on
+ Windows unless mmap has been disabled.
+
+ https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests/5#note_829289
+
+2021-03-07 Tim-Philipp Müller <tim@centricular.com>
+
+ [ci] Add basic support for Meson builds with MSVC on Windows.
+
+ This adds meson jobs for VS2017 (x86 and x86_64).
+
+ * .gitlab-ci.yml: New file.
+
+2021-03-07 Tim-Philipp Müller <tim@centricular.com>
+
+ [meson] Add subproject fallbacks for 'libpng' and 'zlib'.
+
+ * subprojects/libpng.wrap, subprojects/zlib.wrap: New files.
+
+ * meson.build: Updated.
+
+2021-03-07 Xavier Claessens <xavier.claessens@collabora.com>
+
+ [meson] Make it work with Windows.
+
+ * meson.build: Do not process `ftconfig.h` when not using
+ `ftconfig.h.in`.
+
+ Fixes #1029.
+
+2021-02-25 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix memory leak.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28148
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Reject fonts that have
+ multiple tables with the same tag. While not explicitly forbidden
+ in the OpenType specification, it is implicitly forbidden by
+ describing a binary search algorithm for tables that only works
+ reliably if table tags are unique.
+
+2021-02-22 Werner Lemberg <wl@gnu.org>
+
+ * CMakeLists.txt: Update location of `LICENSE.TXT`.
+
+ Fixes #1035.
+
+2021-02-19 Werner Lemberg <wl@gnu.org>
+
+ * builds/unix/ax_pthread.m4: Update from 'autoconf-archive'.
+
+ A bunch of fixes were added recently to its git repository.
+
+2021-02-17 Werner Lemberg <wl@gnu.org>
+
+ [unix] Updates for autoconf 2.71.
+
+ This fixes warnings reported by autoupdate.
+
+ * builds/unix/ax_pthread.m4: Replace `as_echo` with `AS_ECHO`.
+
+ * builds/unix/configure.raw: Remove obsolete `AC_HEADER_STDC`.
+ Don't escape back quotes in messages for `AC_MSG_WARN`.
+
+2021-02-16 Werner Lemberg <wl@gnu.org>
+
+ * builds/toplevel.mk: Fix previous commit.
+
+ <top_level>: Use `TOP_DIR` in `wildcard` function.
+ (check_out_submodule, copy_submodule): Move down to come after
+ definition of `all` rule.
+ Call `mkdir` conditionally.
+
+2021-02-16 Werner Lemberg <wl@gnu.org>
+
+ * builds/toplevel.mk: Use rules for handling 'dlg'.
+
+ Suggested by Alexei.
+
+ (check_out_submodule, copy_submodule): New targets.
+ <top-level>: Replace calls to `shell` with rules.
+
+2021-02-16 Werner Lemberg <wl@gnu.org>
+
+ * builds/toplevel.mk: Avoid side effects of `shell`.
+
+ We use a dummy variable to catch its output. Otherwise the `make`
+ program is going to interpret the return value of `shell`; this can
+ cause obscure warning or error messages or even be harmful.
+
+2021-02-16 Werner Lemberg <wl@gnu.org>
+
+ Move 'dlg' submodule to `subprojects` directory.
+
+ This is for future changes with Meson, which doesn't allow a
+ different name for its `subprojects` directory. Having both a
+ `submodules` and a `subprojects` directory is confusing.
+
+ * .gitmodules, autogen.sh (copy_submodule_files, DLG_INC_DIR,
+ DLG_SRC_DIR): Updated.
+
+ * builds/toplevel.mk (<top-level>, do-dist),
+ builds/windows/vc2010/script.bat: Updated.
+
+ * src/tools/no-copyright: Updated.
+
+2021-02-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Update paint format values to support non-variable paints.
+
+ * freetype.h (FT_PaintFormat): Update paint format identifiers after
+ a specification change. The specification was updated to have
+ sibling formats, variable and non-variable variants for each.
+ Reflect that here.
+
+ * sfnt/ttcolr.c (read_paint): Remove parsing of variable indices as
+ the non-variable formats no longer have them.
+
+2021-02-15 Daniel E <daniel.engberg.lists@pyret.net>
+
+ * CMakeLists.txt: Improve 'bz2' support.
+
+ Not all distributions such as FreeBSD provide a `.pc` file for
+ '(lib)bz2' so follow autotools and add it to `Libs.private` instead.
+
+2021-02-13 Werner Lemberg <wl@gnu.org>
+
+ * src/tools/update-copyright-year: Fix single-year entry handling.
+
+ The fix from 2021-01-17 didn't cover the case where the year to be
+ updated is identical to the current year.
+
+2021-02-13 Werner Lemberg <wl@gnu.org>
+
+ Add new function `FT_Get_Transform`.
+
+ See
+
+ https://github.com/harfbuzz/harfbuzz/issues/2428
+
+ for some reasons to introduce this function.
+
+ * include/freetype/freetype.h, src/base/ftobjs.c (FT_Get_Transform):
+ Implement it.
+
+2021-02-12 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Decorate `qsort` callbacks with `cdecl`.
+
+ * include/freetype/internal/compiler-macros.h (FT_COMPARE_DEF):
+ Add new macro.
+
+ * src/base/ftrfork.c, src/bdf/bdflib.c, src/gxvalid/gxvcommn.c,
+ src/psaux/afmparse.c, src/psnames/psmodule.c, src/type1/t1afm.c,
+ src/sfnt/sfwoff.c, src/sfnt/sfwoff2.c: Update `qsort` callbacks.
+
+ Fixes #1026 when compiling FreeType with an unusual calling
+ convention while the C library function `qsort` still expects
+ `cdecl`.
+
+2021-02-10 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Implement 'COLR' v1 sweep gradients.
+
+ * freetype.h (FT_PaintSweepGradient): Add `FT_PaintSweepGradient` to
+ represent a 'COLR' v1 sweep gradient.
+ Update format.
+ (FT_PaintFormat): Update shifted paint formats.
+ Sync with spec.
+ * sfnt/ttcolr.c (read_paint): Logic to parse sweep gradients.
+ Fix struct access in radial gradient implementation.
+
+2021-02-09 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Provide optional root transform for 'COLR' v1 glyph graph.
+
+ * include/freetype/freetype.h (FT_Get_Color_Glyph_Paint):
+ Additional function argument `root_transform` to control whether
+ root transform should be returned.
+ (FT_OpaquePaint): Additional tracking field to denote whether
+ root transform is to be returned.
+ * include/freetype/internal/sfnt.h
+ (TT_Get_Color_Glyph_Paint_Func): Propagate additional argument.
+ * src/base/ftobjs.c (FT_Get_Color_Glyph_Paint): Ditto.
+ * src/sfnt/ttcolr.c (tt_face_get_colr_glyph_paint): Return root
+ transform reflecting the size and tranform configured on
+ `FT_Face`.
+ (read_paint): Initialize and track status of insert_root_transform
+ flag.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ * meson.build: s/freetype2_dep/freetype_dep/.
+
+ Many projects (e.g., fontconfig, cairo) hardcode the `freetype_dep`
+ variable name to use FreeType as subproject because that was the
+ variable name in Centricular's Meson port of FreeType. While they
+ should stop hardcoding that variable name, it does not cost us
+ anything to keep using that name to ease transition.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ [meson] Fix handling of HarfBuzz library.
+
+ * meson.build (harfbuzz_dep): Do not fall back to HarfBuzz by
+ default.
+
+ Otherwise it causes a dependency cycle:
+
+ cairo => fontconfig => freetype2 => harfbuzz => cairo
+
+ Meson will still fall back to HarfBuzz subprojects if the `harfbuzz`
+ option is set to `enabled` instead of `auto` and a
+ `subprojects/harfbuzz.wrap` file is present. In that case it is the
+ responsibility of the main project to set the proper options on each
+ subproject to break the dependency cycle.
+
+ Fixes: #1028.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ [meson] Fix dependency lookup and generate `ftconfig.h`.
+
+ - zlib: If not found on the system, meson can build it as a
+ subproject. We thus never use the (outdated) zlib support that
+ comes with FreeType. Doing so has the additional advantage that
+ the zlib code can be shared with other projects like GLib if both
+ are subprojects of an application.
+ - harfbuzz: Build as a subproject if not found on the system.
+ - 'QUESTION: What if the compiler doesn't support `-D` but uses `/D`
+ instead as on Windows?' Answer: Meson translate arguments for us.
+ - visibility: Replace self-made code with meson-specific solution.
+
+ * meson.build (ft2_defines): Rewrite logic to set and handle it.
+ (process_header_command): New variable, previously called
+ `ftoption_command`.
+ (ftoption_command, ftconfig_command): New variables.
+ (zlib_option): Removed.
+ (zlib_dep): New variable.
+ (ft2_deps): Updated.
+ (harfbuzz_dep): Updated.
+ (ftconfig_h_in, ftconfig_h): New variables.
+ (ft2_sources): Updated.
+ (ft2_lib): Updated, handle visibility.
+ (summary): Updted.
+
+ * meson_options.txt (zlib): Updated.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ * meson.build: Fix resource compilation on Windows.
+
+ This is copied from GStreamer's meson port of FreeType.
+
+ (ft2_sources): Add both debug and resource file (the latter for
+ Windows only).
+ (ft2_debug_src): Removed.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ * meson.build: s/ft2_libtool_version/ft2_pkgconfig_version/.
+
+ (freetype2_dep): Use it.
+
+ `ft2_libtool_version` would be the shared library version, not the
+ one we should use in file `freetype2.pc`.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ * meson.build: Use `meson.override_dependency`.
+
+ This is a new meson mechanism to avoid other projects to hard-code
+ the `freetype2_dep` variable name in their build definition. It
+ also ensures that meson does not mix system and subproject versions
+ of FreeType inside of the same project.
+
+ Also remove outdated TODO because `declare_dependency` was already
+ there.
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ * meson.build (bzip2_dep): Simplify.
+
+ We remove `static:false` from `find_library('bz2')`.
+
+ I don't know whether the previous code was a workaround for an old
+ meson bug, but at least with version >=0.55.0 (which FreeType uses)
+ it picks the shared library when both are available.
+
+ File `freetype2.pc` still contains the full path to file `libbz2.so`
+ instead of `-lbz2` – that we need to do this is a meson bug even
+ present in the current version (0.57.0).
+
+2021-02-09 Xavier Claessens <xavier.claessens@collabora.com>
+
+ * meson.build: Set project version.
+
+2021-02-04 Werner Lemberg <wl@gnu.org>
+
+ [base] Fix Netpbm tracing message.
+
+ * src/base/ftobjs.c (FT_Render_Glyph_Internal): Don't emit Netpbm
+ warning if there is nothing to output.
+
+2021-02-04 Werner Lemberg <wl@gnu.org>
+
+ * src/*: Don't use more than one '\n' in `FT_TRACE` and `FT_ERROR`.
+
+ This ensures good logging output, with all lines having a proper
+ prefix (if requested).
+
+ This is a continuation of a similar patch from 2020-12-02, which
+ missed some locations.
+
+2021-02-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/unix/configure.raw [mmap]: Restore default path.
+
+ Fixes #1023.
+
+2021-02-03 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix integer overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30154
+
+ * src/psaux/psblues.c (cf2_blues_capture): Use `SUB_INT32`.
+
+2021-02-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/unix/configure.raw [mmap support]: Explicitly handle Windows.
+
+ Fixes #1024.
+
+2021-01-31 Werner Lemberg <wl@gnu.org>
+
+ * builds/unix/configure.raw [mmap support]: Correctly handle Windows.
+
+ Fixes #1024.
+
+2021-01-31 Werner Lemberg <wl@gnu.org>
+
+ * builds/windows/ftdebug.c: Synchronize with `src/base/ftdebug.c`.
+
+2021-01-31 Werner Lemberg <wl@gnu.org>
+
+ Always provide logging API.
+
+ It's easier to have stubs if FT_DEBUG_LOGGING is undefined than to
+ modify `ftexport.sym` conditionally.
+
+ Problem reported by Alexei.
+
+ * src/base/ftdebug.c: Include `ftlogging.h`.
+ (FT_Trace_Set_Level, FT_Trace_Set_Default_Level, FT_Set_Log_Handler,
+ FT_Set_Default_Log_Handler) [!FT_DEBUG_LOGGING]: Provide stubs.
+
+2021-01-31 Werner Lemberg <wl@gnu.org>
+
+ * builds/unix/configure.raw: Fix typo.
+
+ Bug introduced in Vincent's last commit bb33f03.
+
+ Fixes issue #1021.
+
+2021-01-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftstroke.c (FT_Stroker_EndSubPath): Ignore tiny gaps.
+
+ Fixes bug #1020.
+
+2021-01-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [stroker] Minor clean-up.
+
+ * src/base/ftstroke.c (FT_Stroker_{ConicTo,CubicTo}): Reset the last
+ line length.
+ (FT_Stroker_EndSubPath): Call `ft_stroker_process_corner'.
+
+2021-01-27 Vincent Torri <vincent.torri@gmail.com>
+
+ * builds/windows/ftsystem.c: Add shared memory support on Windows.
+
+ * CMakeLists.txt (BASE_SRCS), builds/unix/configure.raw (FTSYS_SRC),
+ builds/windows/vc2010/freetype.vcxproj,
+ builds/windows/visualc/freetype.vcproj, meson.build (ft2_sources):
+ Add it (conditionally).
+
+2021-01-23 Werner Lemberg <wl@gnu.org>
+
+ Require HarfBuzz 2.0.0.
+
+ This is needed to make commit f1f9705f9 work.
+
+ * CMakeLists.txt (HARFBUZZ_MIN_VERSION), builds/unix/configure.raw
+ (harfbuzz_pkg), meson.build (harfbuzz_dep): Updated.
+
+2021-01-22 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * autogen.sh: Absorb `version.sed'.
+ * version.sed: Removed.
+
+2021-01-19 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * srd/base/ftlcdfil.c (FT_Library_SetLcdGeometry): Fix return value.
+
+2021-01-15 Nikolaus Waxweiler <madigens@gmail.com>
+
+ [afshaper] Fix hb_ot_tags_from_script deprecation warning.
+
+ * autofit/afshaper.c (af_shaper_get_coverage): Copy the source code
+ of the function as suggested in
+ https://github.com/harfbuzz/harfbuzz/issues/2737 and adjust to handle
+ at most three tags.
+
+2021-01-17 Werner Lemberg <wl@gnu.org>
+
+ * src/tools/update-copyright-year: Fix single-year entry handling.
+
+2021-01-16 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/unix/unixddef.mk: Remove the second DEVEL_DIR definition.
+
+2021-01-14 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Additional checks for 'colr' table presence.
+
+ * sfnt/ttcolr.c (tt_face_get_colr_glyph_paint,
+ tt_face_get_colorline_stops, tt_face_get_paint): Additional checks
+ for whether colr table is present. Prevents crashes when these
+ methods are called on non-COLR fonts.
+
+2021-01-13 Dominik Röttsches <drott@chromium.org>
+
+ Add config option to test for 'COLR' v1 support in headers.
+
+ * include/freetype/config/ftoption.h (TT_SUPPORT_COLRV1): New macro
+ so that clients can test whether the FreeType checkout that they are
+ building against supports the 'COLR' v1 API. This is intended to be
+ a temporary solution until 'COLR' v1 support is released in a
+ FreeType version and such a check can be made by using the version
+ number instead.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ [base] Fill 'COLR' v1 API templates to make them work (#59703).
+
+ * src/base/ftobjs.c (FT_Get_Color_Glyph_Paint, FT_Get_Paint_Layers,
+ FT_Get_Paint, FT_Get_Colorline_Stops): Add basic sanity checks,
+ check for existence of `FT_Face`, check arguments and delegate calls
+ for the respective 'COLR' v1 API to the SFNT driver.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Register 'COLR' v1 API in driver (#59703).
+
+ * include/freetype/internal/sfnt.h (TT_Get_Color_Glyph_Paint_Func,
+ TT_Get_Paint_Layers_Func, TT_Get_Colorline_Stops_Func,
+ TT_Get_Paint_Func): New function pointer types.
+ (SFNT_Interface): Add them.
+ (FT_DEFINE_SFNT_INTERFACE): Updated.
+
+ * src/sfnt/sfdriver.c (PUT_COLOR_LAYERS_V1): New macro.
+ (sfnt_interface): Add new function pointers.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Add 'COLR' v1 API to retrieve color layers (#59703).
+
+ * src/sfnt/ttcolr.c (tt_face_get_paint_layers): New function to get
+ the layers of a `PaintColrLayers` table in the font, using an
+ `FT_LayerIterator` from an `FT_PaintColrLayers` object retrieved via
+ `tt_face_get_paint`.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Add 'COLR' v1 API to iterate color stops (#59703).
+
+ * src/sfnt/ttcolr.c (tt_face_get_colorline_stops): New function to
+ return the current `FT_ColorStop` object from `FT_ColorStopIterator`.
+ Also increment the iterator.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Add API to get actual paint from `FT_OpaquePaint` (#59703).
+
+ * src/sfnt/ttcolr.c (tt_face_get_paint): New function to resolve an
+ `FT_OpaquePaint` paint reference into an `FT_COLR_Paint` object of a
+ certain format, which contains the detailed information stored in a
+ paint of the respective format.
+ (read_paint): New function to provide the format specific parsing
+ and to populate the data members of each specific `FT_COLR_Paint`
+ subtype.
+ (read_color_line): New function to parse retrieved color line
+ information into an `FT_ColorLine` object, which has information
+ about the color line extend mode as well as an
+ `FT_ColorStopIterator` object.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ [sfnt] Add API to retrieve 'COLR' v1 root paint (#59703).
+
+ * src/sfnt/ttcolr.c (BaseGlyphV1Record): New structure.
+ (tt_face_load_colr): Handle version 1 table header.
+ (find_base_glyph_v1_record): New auxiliary function.
+ (tt_face_get_colr_glyph_paint): New function to find the root
+ `FT_OpaquePaint` object for a given glyph ID.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ Add new methods required for 'COLR' v1 to public API (#59703).
+
+ * include/freetype/freetype.h (FT_Get_Color_Glyph_Paint): New method
+ for retrieving the root paint object for a color glyph by specifying
+ a glyph ID.
+ (FT_Get_Paint_Layers): New method for retrieving the layers of a
+ `PaintColorGlyph`.
+ (FT_Get_ColorLine_Stops): New method for retrieving the stops of a
+ color.
+ (FT_Get_Paint): New method for resolving an `FT_OpaquePaint` into an
+ `FT_COLR_Paint` object.
+
+2020-12-16 Dominik Röttsches <drott@chromium.org>
+
+ Add types required for 'COLR' v1 to public API (#59703).
+
+ * include/freetype/freetype.h (FT_PaintFormat, FT_ColorStopIterator,
+ FT_ColorIndex, FT_ColorStop, FT_PaintExtend, FT_ColorLine,
+ FT_Affine23, FT_CompositeMode, FT_OpaquePaint, FT_PaintColrLayers,
+ FT_PaintSolid, FT_PaintLinearGradient, FT_PaintRadialGradient,
+ FT_PaintGlyph, FT_PaintColrGlyph, FT_PaintTransformed,
+ FT_PaintTranslate, FT_PaintRotate, FT_PaintSkew, FT_PaintComposite,
+ FT_COLR_Paint): Adding structs and enum to represent paint format,
+ color stop information, gradient extend information, structs to
+ reference paint offsets, and to define transforms and compositions.
+ Adding a union type to represent the union of the structs,
+ distinguished by `FT_PaintFormat`.
+
+2021-01-10 Werner Lemberg <wl@gnu.org>
+
+ * builds/*: s/BUILD_DIR/PLATFORM_DIR/.
+
+ The old variable name caused confusion.
+
+2021-01-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds] Revert `FTMODULE_H' changes.
+
+ * builds/toplevel.mk, builds/freetype.mk: Revert changes.
+
+2021-01-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds/windows] Fix up DLG build with VC++.
+
+ * builds/windows/vc2010/script.bat: Copy headers to include/.
+ * builds/windows/vc2010/freetype.vcxproj: Remove DLG paths.
+
+2021-01-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds] Relocate `FTMODULE_H'.
+
+ * builds/toplevel.mk: Place `FTMODULE_H' in include/.
+ * builds/freetype.mk: Simplify included path.
+
+2021-01-07 Werner Lemberg <wl@gnu.org>
+
+ Fix ABI incompatibility.
+
+ * include/freetype/ftimage.h (FT_Pixel_Mode): Don't insert
+ `FT_PIXEL_MODE_GRAY16' but append it.
+
+ * src/base/ftobjs.c (pixel_modes): Updated.
+
+2021-01-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [dlg] Move the headers to include/dlg to simplify their use.
+
+ * autogen.sh, builds/toplevel.mk: Copy headers to include/dlg.
+ * builds/freetype.mk, builds/windows/vc2010/freetype.vcxproj:
+ Simplify included path.
+ * include/freetype/internal/ftdebug.h: Simplify #include.
+ * src/dlg/rules.mk, .gitignore: Updated.
+
+2021-01-06 Werner Lemberg <wl@gnu.org>
+
+ * meson.build: Add summary.
+
+ Based on a patch from Vincent Torri <vincent.torri@gmail.com>.
+
+2021-01-06 Torsten Hilbrich <emacs.nolkaf@hilbrich.tk>
+
+ * meson.build: Fix 'png' build option (#59458).
+
+ Without this patch, 'png' is always required.
+
+2021-01-04 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds/windows] Add SDF to VC2010 project.
+
+ * builds/windows/vc2010/freetype.vcxproj: Updated;
+ AfterBuild conveniences.
+
+2020-12-26 Werner Lemberg <wl@gnu.org>
+
+ [sdf] Use 'counter-clockwise', not 'anti-clockwise'.
+
+ We prefer US nomenclature.
+
+ * src/sdf/ftsdf.c (SDF_Contour_Orientation):
+ s/SDF_ORIENTATION-ACW/SDF_ORIENTATION_CCW/.
+ Update all users.
+
+2020-12-26 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftobjs.c (pixel_modes): Updated.
+
+2020-12-26 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Remove custom memory tracker.
+
+ The internal FreeType memory tracker is sufficient.
+
+ * src/sdf/ftsdf.c (FT_DEBUG_INNER, FT_ASSIGNP_INNER, SDF_MemoryUser,
+ sdf_alloc, sdf_free, SDF_ALLOC, SDF_FREE,
+ SDF_MEMORY_TRACKER_DECLARE, SDF_MEMORY_TRACKER_SETUP,
+ SDF_MEMORY_TRACKER_DONE): Removed.
+
+ s/SDF_ALLOC/FT_ALLOC/.
+ s/SDF_FREE/FT_FREE/.
+
+ Other updates.
+
+2020-12-24 Werner Lemberg <wl@gnu.org>
+
+ [sdf] Fix `make multi`.
+
+ * src/sdf/ftsdf.c: Include `ftoutln.h`.
+
+2020-12-24 Werner Lemberg <wl@gnu.org>
+
+ [sdf] Fix tracing.
+
+ * include/freetype/internal.fttrace.h: Add 'bsdf' component.
+
+ * src/sdf/ftbsdf.c, src/sdf/ftsdf.c (FT_COMPONENT): Define.
+
+2020-08-21 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add debugging function.
+
+ * src/sdf/ftsdf.c (sdf_shape_dump): New function.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add 'bsdf' renderer to 'sdf' module.
+
+ * src/sdf/ftsdfrend.c (ft_bsdf_render): New function.
+
+ (ft_bitmap_sdf_renderer_class): New structure.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add interface functions for the 'bsdf' rasterizer.
+
+ * src/sdf/ftsdf.c (bsdf_raster_new, bsdf_raster_reset,
+ bsdf_raster_set_mode, bsdf_raster_render, bsdf_raster_done): New
+ functions.
+
+ (ft_bitmap_sdf_raster): New variable.
+
+ * src/sdf/ftsdf.h: Updated.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add function to copy SDF data into output bitmap.
+
+ * src/sdf/ftbsdf.c (finalize_sdf): New function.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add '8-point sequential Euclidean distance mapping' algorithm.
+
+ * src/sdf/ftbsdf.c (compare_neighbor, first_pass, second_pass,
+ edt8): New functions.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add function to copy source bitmap to distance map.
+
+ * src/sdf/ftbsdf.c (bsdf_init_distance_map): New function.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add functions to compute pixel edge distances.
+
+ * src/sdf/ftbsdf.c (compute_edge_distance, bsdf_approximate_edge):
+ New functions.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add function to find edge pixels in a grid of alpha values.
+
+ * src/sdf/ftbsdf.c (bsdf_is_edge): New function.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add essential structures for the 'bsdf' rasterizer.
+
+ * src/sdf/ftbsdf.c (ONE): New macro.
+ (BSDF_TRaster, ED, BSDF_Worker): New structures.
+ (zero_ed): New constant.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add 'sdf' module to non-gnumake build systems.
+
+ * include/freetype/config/ftmodule.h: Add both the 'sdf' and 'bsdf'
+ renderers to the list of modules.
+
+ * CMakeLists.txt (BASE_SRCS): Add 'sdf' single-object module.
+
+2020-08-20 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Added basic overlapping contour support.
+
+ * src/sdf/ftsdf.c (sdf_generate_with_overlaps): New function.
+ (sdf_raster_render): Enable it.
+
+2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add build infrastructure.
+
+ * src/sdf/module.mk, src/sdf/rules.mk: New files.
+
+ * src/sdf/ftsdf.h (ft_sdf_raster): New forward declaration.
+
+ * include/freetype/ftmoderr.h (FT_MODERRDEF): Add error definition
+ for the 'sdf' module.
+
+ * include/freetype/internal/fttrace.h (FT_TRACE_DEF): Add trace
+ definition for the `sdf' module.
+
+ * modules.cfg (RASTER_MODULES): Add the `sdf' module to the list of
+ rasterizers.
+
+2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add interface functions for the 'sdf' rasterizer.
+
+ * src/sdf/ftsdf.c (sdf_raster_new, sdf_raster_reset,
+ sdf_raster_set_mode, sdf_raster_render, sdf_raster_done): New
+ functions.
+ (ft_sdf_raster): New structure.
+
+2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add subdivision and bounding box optimization.
+
+ * src/sdf/ftsdf.c (sdf_generate_bounding_box): New function, which
+ is an optimized version of `sdf_generate`.
+ (sdf_generate_subdivision): New function.
+
+2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add function to generate SDF.
+
+ * src/sdf/ftsdf.c (sdf_generate): New function, currently disabled.
+ This is a proof-of-concept implementation: It doesn't use any
+ optimization, it simply checks all grid points against all contours.
+
+2020-08-19 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add functions to get shortest distance from any edge/contour.
+
+ * src/sdf/ftsdf.c (sdf_edge_get_min_distance): New function.
+ (sdf_contour_get_min_distance): New function, currently disabled.
+
+2020-08-18 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add shortest distance finding functions.
+
+ * src/sdf/ftsdf.c (get_min_distance_line, get_min_distance_conic,
+ get_min_distance_cubic): New functions. Note that
+ `get_min_distance_conic` comes with two implementations (using an
+ analytical and an iterative method, to be controlled with the
+ `USE_NEWTON_FOR_CONIC` macro).
+
+2020-08-18 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add function to resolve corner distances.
+
+ * src/sdf/ftsdf.c (resolve_corner): New function.
+
+2020-08-18 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add essential math functions.
+
+ * src/sdf/ftsdf.c (cube_root, arc_cos) [!USE_NEWTON_FOR_CONIC]: New
+ auxiliary functions.
+
+ * src/sdf/ftsdf.c (solve_quadratic_equation, solve_cubic_equation)
+ [!USE_NEWTON_FOR_CONIC]: New functions.
+
+2020-08-18 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add utility functions for contours.
+
+ * src/sdf/ftsdf.c (get_control_box, get_contour_orientation): New
+ functions.
+ (split_conic, split_cubic, split_sdf_conic, split_sdf_cubic,
+ split_sdf_shape): New functions.
+
+2020-08-17 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add functions to decompose `FT_Outline`.
+
+ * src/sdf/ftsdf.c (sdf_move_to, sdf_line_to, sdf_conic_to,
+ sdf_cubic_to): New auxiliary decomposition functions.
+ (sdf_compose_funcs): New structure.
+ (sdf_outline_decompose): New function.
+
+2020-08-17 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Structs, enums, macros, and functions for 'sdf' rasterizer.
+
+ * src/sdf/ftsdf.c (FT_DEBUG_INNER, FT_ASSIGNP_INNER)
+ [FT_DEBUG_LEVEL_TRACE && FT_DEBUG_MEMORY]: New macros.
+ (SDF_MemoryUser) [FT_DEBUG_LEVEL_TRACE && FT_DEBUG_MEMORY]: New
+ struct for memory usage tracing.
+ (sdf_alloc, sdf_free) [FT_DEBUG_LEVEL_TRACE && FT_DEBUG_MEMORY]: New
+ functions for memory usage tracing.
+
+ (SDF_ALLOC, SDF_FREE): New macros for memory management.
+ (SDF_MEMORY_TRACKER_DECLARE, SDF_MEMORY_TRACKER_SETUP,
+ SDF_MEMORY_TRACKER_DONE): New macros to set up memory usage tracing.
+
+ (USE_NEWTON_FOR_CONIC, MAX_NEWTON_DIVISIONS, MAX_NEWTON_STEPS,
+ CORNER_CHECK_EPSILON, CG_DIMEN): New configuration macros for
+ controlling the process of finding the shortest distance.
+
+ (MUL_26D6, VEC_26D6_DOT): New auxiliary macros.
+
+ (SDF_TRaster, SDF_Edge, SDF_Contour, SDF_Shape, SDF_Signed_Distance,
+ SDF_Params): New structs for setting up SDF data.
+ (SDF_Edge_Type, SDF_Contour_Orientation): New enums for SDF data.
+
+ (zero_vector, null_edge, null_contour, null_shape, max_sdf): Useful
+ constants.
+
+ (sdf_edge_new, sdf_edge_done, sdf_contour_new, sdf_contour_done,
+ sdf_shape_new, sdf_shape_done): New constructors and destructors.
+
+2020-08-17 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add raster parameters structure.
+
+ * src/sdf/ftsdf.h (SDF_Raster_Params): New structure.
+
+ * src/sdf/sdf.c: Include source files in order to make a single
+ object of the module.
+
+2020-08-17 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add 'sdf' renderer.
+
+ * src/sdf/ftsdf.c: Add 'sdf' renderer along with its interface
+ functions.
+ Also add functions to set and get properties.
+
+2020-08-17 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add common elements for 'sdf' and 'bsdf' renderers.
+
+ * src/sdf/ftsdfrend.h (SDF_Rendere_Module, ft_sdf_renderer_class,
+ ft_bitmap_sdf_renderer_class): New structures.
+
+ * src/sdf/ftsdfcommon.h (DEFAULT_SPREAD, MIN_SPREAD_MAX_SPREAD,
+ USE_SQUARED_DISTANCES): New macros.
+ (FT_INT_26D6, FT_INT_16D16, FT_26D6_16D16): New macros.
+ (FT_CALL, VECTOR_LENGTH_16D16): New macros.
+ (FT_26D6_Vec, FT_16D16_Vec, FT_16D16, FT_26D6, FT_6D10, FT_CBox):
+ New typedefs.
+ (square_root): New macro.
+
+ * src/sdf/ftsdferrs.h: Add module error setup.
+
+2020-08-16 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [sdf] Add files for new 'sdf' module.
+
+ Here is a breakdown of what the files will contain.
+
+ * src/sdf/ftsdfrend.c, src/sdf/ftsdfrend.h: The 'sdf' and 'bsdf'
+ renderers.
+
+ * src/sdf/ftsdf.c, src/sdf/ftsdf.h: The rasterizer for the 'sdf'
+ renderer.
+ * src/sdf/ftbsdf.c, src/sdf/ftbsdf.h: The rasterizer for the 'bsdf'
+ renderer.
+
+ * src/sdf/ftsdfcommon.h: Commmon properties and functions for both
+ rasterizers.
+ * src/sdf/ftsdferrs.h: Common error defines.
+
+ * src/sdf/sdf.c: For building a single object of the entire module.
+
+2020-08-16 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [base] Allow renderers of different formats.
+
+ * src/base/ftobjs.c (FT_Render_Glyph_Internal): Do not return if the
+ glyph's slot format is `FT_GLYPH_FORMAT_BITMAP`. The forthcoming
+ 'bsdf' renderer will require bitmaps for processing.
+
+ * src/base/ftobjs.c (ft_add_renderer, ft_remove_renderer): Remove
+ renderer's glyph format check before adding and removing them. The
+ 'bsdf' renderer will have a format `FT_GLYPH_FORMAT_BITMAP`.
+
+2020-08-16 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ Add data types required for the forthcoming 'sdf' module.
+
+ * include/freetype/freetype.h (FT_Render_Mode): Add new render mode
+ `FT_RENDER_MODE_SDF`, which will be used to generate SDF.
+
+ * include/freetype/ftimage.h (FT_Pixel_Mode): Add new pixel mode
+ `FT_PIXEL_MODE_GRAY16`, which will be the output of the 'sdf'
+ module.
+ (FT_RASTER_FLAG_SDF): New raster flag to be used internally by the
+ 'sdf' module.
+
+ * include/freetype/fttypes.h (FT_F6Dot10): New data type.
+
+2020-08-16 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ [base] Allow renderers of different formats.
+
+ * src/base/ftobjs.c (FT_Render_Glyph_Internal): Do not return if the
+ glyph's slot format is `FT_GLYPH_FORMAT_BITMAP`. The forthcoming
+ 'bsdf' renderer will require bitmaps for processing.
+
+ * src/base/ftobjs.c (ft_add_renderer, ft_remove_renderer): Remove
+ renderer's glyph format check before adding and removing them. The
+ 'bsdf' renderer will have a format `FT_GLYPH_FORMAT_BITMAP`.
+
+2020-12-23 Werner Lemberg <wl@gnu.org>
+
+ * builds/windows/detect.mk (COPY): Make it work with `shell`.
+
+ Without this patch, we get the error
+
+ builds/toplevel.mk:127: *** missing separator. Stop.
+
+ Reported by Anuj, with a solution from Alexei.
+
+2020-12-23 Ignacio Casal Quinteiro <qignacio@amazon.com>
+
+ * meson.build (ft2_defines): Fix builds on Windows.
+
+2020-12-18 Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
+
+ [autofit] Fix double division in stem darkening.
+
+ The old code used to divide the darkening amount by em_ratio twice,
+ leading to unnecessarily bold stems on certain fonts with higher
+ units per em (e.g. Inter). This patch fixes it.
+
+ The return value of af_loader_compute_darkening was also changed to
+ use 16.16 fixed point to get rid of a redundant truncation operation.
+ This should slightly improve the precision, although it's still
+ bottlenecked by the emboldening function, which uses 26.6 fixed point.
+
+ * src/autofit/afloader.[ch]
+ (af_loader_compute_darkening): Return FT_Fixed.
+ (af_loader_embolden_glyph_in_slot): Revise calculations.
+
+2020-12-17 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * include/freetype/ftmodapi.h (FT_FACE_DRIVER_NAME): New public macro.
+
+ The driver name is needed for `FT_Property_Set' and `FT_Property_Get'.
+
+2020-12-16 Chris Liddell <chris.liddell@artifex.com>
+
+ [truetype] Fix incremental metrics (#59503).
+
+ * src/truetype/ttgload.c (tt_get_metrics, load_truetype_glyph):
+ Previously, the code would populate the phantom points before
+ calling the `get_glyph_metrics` callback. For formats like PCL XL
+ format 1, class 2 downloaded fonts (where metrics are removed from
+ the TTF header), this causes problems when the hinting program uses
+ the phantom points (misplaced and distorted glyphs) due to the
+ metrics being unset (all zeros).
+ (tt_get_metrics_incr_overrides): Renamed to...
+ (tt_get_metrics_incremental): ... this. Updated caller
+
+ * include/freetype/ftincrem.h: Update the documentation to make it
+ clearer that `get_glyph_metrics` is to retrieve metrics from a
+ non-standard source, but *not* for the purpose of imposing custom
+ metrics.
+
+2020-12-14 Werner Lemberg <wl@gnu.org>
+
+ [type42] Pacify static analysis tools (#59682).
+
+ * src/type42/t42objs.c (T42_Size_Init, T42_GlyphSlot_Init): Avoid
+ warnings about uninitialized variables.
+
+2020-12-07 Werner Lemberg <wl@gnu.org>
+
+ * builds/unix/configure.raw: Don't set `FT_DEBUG_LOGGING`.
+
+ All debug options are handled exclusively in `ftoption.h`.
+
+2020-12-07 Werner Lemberg <wl@gnu.org>
+
+ * src/*: More fixes for using a '\n' in `FT_TRACE` and `FT_ERROR`.
+
+2020-12-07 Werner Lemberg <wl@gnu.org>
+
+ */*: s/FT_LOGGING/FT_DEBUG_LOGGING/.
+
+2020-12-05 Werner Lemberg <wl@gnu.org>
+
+ * builds/toplevel.mk (do-dist): Remove `submodules` directory.
+
+2020-12-02 Werner Lemberg <wl@gnu.org>
+
+ * src/*: Don't use more than one '\n' in `FT_TRACE` and `FT_ERROR`.
+
+ This ensures good logging output, with all lines having a proper
+ prefix (if requested).
+
+2020-12-02 Werner Lemberg <wl@gnu.org>
+
+ [base] Don't close 'stderr' after logging.
+
+ * src/base/ftdebug.c, builds/windows/ftdebug.c (ft_logging_deinit):
+ Fix it.
+
+2020-12-02 Werner Lemberg <wl@gnu.org>
+
+ * submodules/dlg: Updated to commit 9f0c8b22.
+
+2020-12-02 Werner Lemberg <wl@gnu.org>
+
+ * src/bdf/bdflib.c: Fix `-Wformat` warning.
+
+2020-12-02 Werner Lemberg <wl@gnu.org>
+
+ Improve setup for 'dlg' library.
+
+ * autogen.sh (copy_submodule_file), builds/toplevel.mk: Redirect
+ stderr to `/dev/null`.
+
+ * builds/toplevel.mk: Move code block to handle 'dlg' stuff into
+ `check_platform` conditional.
+ Also fix wildcard expressions for guarding `git submodule` commands.
+ Also make file copying work with non-Unix platforms (untested).
+
+2020-12-01 Werner Lemberg <wl@gnu.org>
+
+ [build] Use gcc (and clang) in C99 mode.
+
+ Other compilers are unchanged.
+
+ * builds/compiler/gcc-dev.mk, builds/compiler/gcc.mk (ANSIFLAGS):
+ s/-ansi/-std=c99/.
+
+ * builds/freetype.mk (FT_CFLAGS): Remove `-std=c99`.
+
+ * builds/unix/configure.raw: Handle C99.
+ Remove no longer needed test for gcc 4.6 and earlier.
+
+2020-12-01 Werner Lemberg <wl@gnu.org>
+
+ [dlg] Fix compiler warnings.
+
+ * src/dlg/dlgwrap.c: Duplicate some feature test macros from
+ `dlg.c`, which must come first before loading standard headers. For
+ example, `freetype.h` loads `stdio.h` if compiled in debug mode.
+
+2020-12-01 Werner Lemberg <wl@gnu.org>
+
+ * src/type42/t42parse.c: Fix `-Wformat` warnings.
+
+2020-12-01 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [builds/unix] Check for 'pthread' library.
+
+ * builds/unix/ax_pthread.m4: New file, taken from 'autoconf-archive'
+ git repository.
+
+ * builds/unix/configure.raw: Check for 'pthread'; also check whether
+ it works.
+
+2020-12-01 Werner Lemberg <wl@gnu.org>
+
+ [base] Implement vertical alignment of log printing.
+
+ Based on a patch by Priyesh.
+
+ * include/freetype/internal/fttrace.h (FT_MAX_TRACE_LEVEL_LENGTH):
+ New macro.
+
+ * src/base/ftdebug.c, builds/windows/ftdebug.c (ft_log_handler):
+ Print logs after a fixed width to handle different lengths of
+ `FT_COMPONENT` entries.
+ Use `ft_strrchr` to check for final newline character.
+
+2020-11-30 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ Update logging related documentation.
+
+ * docs/DEBUG: Updates related to `FT_LOGGING`.
+
+ * README.git: Updates related to logging.
+
+2020-11-30 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ * src/*: Fix `-Wformat` warnings.
+
+2020-11-30 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [builds/windows] Changes to build 'dlg' with FreeType on Windows.
+
+ We only support Visual C++ 2010 and newer.
+
+ * builds/windows/vc2010/script.bat: New windows batch file to copy
+ necessary 'dlg' files from `submodules/dlg` to `src/dlg`. This file
+ is used as a pre-built event in Visual C++.
+
+ * builds/windows/ftdebug.c: Synchronize with `src/base/ftdebug.c`.
+
+ * builds/windows/vc2010/freetype.vcxproj.filters: Add
+ `src/dlgwrap.c`.
+
+ * builds/windows/vc2010/freetype.vcxproj
+ (AdditionalIncludeDirectories): Add include files of dlg for 'Debug'
+ and 'Debug Static' configurations on both 'x64' and 'win32'
+ platforms.
+ (PreprocessorDefinitions): Add `FT_LOGGING` for 'Debug' and 'Debug
+ Static' configurations on both 'x64' and 'win32' platforms.
+ Add `DLG_STATIC' for 'Debug' configuration on 'x64' and 'win32'
+ platforms.
+ (DisableLanguageExtensions): We need to disable the `/Za` option
+ when building 'dlg' with FreeType as 'dlg' strictly follows the C99
+ standard. Visual C++ produces behaves unexpectedly when
+ compiling a C99 file with `/Za` option enabled.
+
+2020-11-30 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [base] Add public API to change log handling function.
+
+ * include/freetype/ftlogging.h (FT_Custom_Log_Handler): New function
+ typedef to store the custom callback logging function.
+ (FT_Set_Log_Handler, FT_Set_Default_Log_Handler): New functions to
+ set and reset custom log handler.
+
+ * include/freetype/internal/ftdebug.h (custom_output_handler): New
+ variable to support a custom callback logging function.
+ (FT_Logging_Callback): A new function typedef to print log using
+ custom callback logging function, which is set using
+ `FT_Set_Log_Handler`.
+ (FT_Log): Use it.
+
+ * src/base/ftdebug.c (FT_Set_Log_Handler,
+ FT_Set_Default_Log_Handler, FT_Logging_Callback): Add function
+ definitions.
+
+2020-11-28 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [base] Add public API to change the levels of tracing components.
+
+ * include/freetype/ftlogging.h: New header file.
+
+ * include/freetype/internal/ftdebug.h [FT_LOGGING]: Include
+ `ftlogging.h`.
+
+ * src/base/ftdebug.c (ft_custom_trace_level): New variable.
+ (ft_debug_init): Update to support change of levels of tracing
+ components of FreeType at run-time.
+ (FT_Trace_Set_Level): New function to change the levels of tracing
+ components at run-time.
+ (FT_Trace_Set_Default_Level): New function to reset the levels of
+ tracing components back to default.
+
+2020-11-28 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [base] Updates to print timestamp and name of `FT_COMPONENT` in logs.
+
+ * include/freetype/internal/ftdebug.h (FT_LOGGING_TAG,
+ FT_LOGGING_TAG_): New macros to resolve the value of `FT_COMPONENT'
+ into a string.
+ (ft_add_tag, ft_remove_tag): New functions to add and remove dlg tags.
+
+ * src/base/ftdebug.c: Add new variables to control the logging of
+ timestamp and name of `FT_COMPONENT` along with actual logs.
+ (ft_add_tag, ft_remove_tag): Add function definitions.
+ (ft_log_handler): Updates to print timestamp and name of
+ `FT_COMPONENT`.
+ (ft_debug_init) [FT_LOGGING]: Users can now control the logging of
+ timestamp and name of `FT_COMPONENT` by adding tags in the
+ `FT2_DEBUG` environment variable.
+
+2020-11-27 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [base] Add functions and variables to print logs to a file.
+
+ * include/freetype/internal/ftdebug.h: Added dlg's header files.
+ (FT_LOG): New macro to redirect trace logs to dlg's API's whenever
+ `FT_LOGGING' is defined.
+ (ft_logging_init, ft_logging_deinit): New functions to handle
+ initialization and uninitialization of logging related variables.
+ (ft_log_handler): New function to handle logs of FreeType.
+
+ * src/base/ftdebug.c: Add necessary logging related variables.
+ (ft_logging_init, ft_logging_deinit, ft_log_handler): Add function
+ definitions.
+
+ * src/base/ftinit.c (FT_Init_FreeType) [FT_LOGGING]: Call
+ `ft_logging_init`.
+ (FT_Done_FreeType) [FT_LOGGING]: Call `ft_logging_deinit`.
+
+ * src/base/ftobjs.c (FT_New_Library): Call `ft_debug_init` only if
+ `FT_LOGGING` is not defined.
+
+2020-11-27 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ [builds] Necessary changes to make 'dlg' compile.
+
+ * autogen.sh (copy_submodule_files): New script to copy all the
+ necessary source and include files from `submodules/dlg` to
+ `src/dlg`.
+
+ * src/dlg/dlgwrap.c: New wrapper file for `src/dlg.c`. It enables
+ the build of 'dlg' if the `FT_LOGGING` macro is defined.
+
+ * src/dlg/rules.mk: New sub-Makefile.
+
+ * builds/freetype.mk (DLG_DIR): New variable to include the
+ header files of the 'dlg' library.
+ (INCLUDES): Add `DLG_DIR`.
+ (FT_CFLAGS): Add `-std=c99' flag.
+ Include `src/dlg/rules.mk` file to build 'dlg' library.
+ (OBJ_S, OBJ_M): Add `DLG_OBJS_M` and `DLG_OBJS_S`.
+
+ * builds/toplevel.mk: For builds directly from the git repository
+ we need to copy files from `submodule/dlg` to `src/dlg`.
+
+ * include/freetype/config/ftoption.h, devel/ftoption.h (FT_LOGGING):
+ New macro to enable or disable the logging facility in FreeType.
+
+2020-11-27 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ * .gitmodules: Add 'dlg' library's git repository as submodule.
+
+2020-12-01 Werner Lemberg <wl@gnu.org>
+
+ * src/tools/chktrcmp.py (trace_use_pat): Update to current use.
+
+2020-11-20 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [cff,cid,type1] Demote old engine for lack of CFF2.
+
+ * src/cff/cffobjs.c (cff_driver_init): Always default to Adobe engine.
+ * src/cid/cidobjs.c (cid_driver_init): Ditto.
+ * src/type1/t1objs.c (T1_Driver_Init): Ditto.
+
+2020-11-09 Werner Lemberg <wl@gnu.org>
+
+ * src/type42/t42parse.c (t42_parse_sfnts): More tracing messages.
+
+2020-11-04 Werner Lemberg <wl@gnu.org>
+
+ * meson.build: Fix .pc file generation.
+
+ For backwards compatibility we need the libtool version, not the .so
+ number.
+
+ Reported by Nikolaus.
+
+2020-10-28 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Minor update to forthcoming OpenType 1.8.4 standard.
+
+ * src/truetype/ttgxvar.c (ft_var_load_item_variation_store): Limit
+ size of `regionCount`.
+
+2020-10-26 Werner Lemberg <wl@gnu.org>
+
+ * meson.build: Fix 'harfbuzz' and 'brotli' build options (#59347).
+
+ Without this patch, 'harfbuzz' and 'brotli' are always required.
+
+ Patch submitted anonymously in Savannah bug report.
+
+2020-10-23 Ben Wagner <bungeman@google.com>
+
+ * src/sfnt/pngshim.c (Load_SBit_Png): Fix memory leak (#59322).
+
+ The issue is that `rows` is allocated but will not be freed in the
+ event that the call to `png_read_image` fails and calls `longjmp`.
+
+2020-10-20 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.10.4 released.
+ ==========================
+
+
+ Tag sources with `VER-2-10-4'.
+
+ * docs/VERSION.TXT: Add entry for version 2.10.4.
+ * docs/CHANGES: Updated.
+
+ * README, src/base/ftver.rc, builds/windows/vc2010/index.html,
+ builds/windows/visualc/index.html,
+ builds/windows/visualce/index.html,
+ builds/wince/vc2005-ce/index.html,
+ builds/wince/vc2008-ce/index.html, docs/freetype-config.1:
+ s/2.10.3/2.10.4/, s/2103/2104/.
+
+ * include/freetype/freetype.h (FREETYPE_PATCH): Set to 4.
+
+ * builds/unix/configure.raw (version_info): Set to 23:4:17.
+ * CMakeLists.txt (VERSION_PATCH): Set to 4.
+
+2020-10-19 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix heap buffer overflow (#59308).
+
+ This is CVE-2020-15999.
+
+ * src/sfnt/pngshim.c (Load_SBit_Png): Test bitmap size earlier.
+
+2020-10-17 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/tt{colr,cpal}.c: Fix signedness warnings from VC++.
+
+2020-10-17 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/sfwoff2.c (Read255UShort): Tweak types to please VC++.
+
+2020-10-10 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.10.3 released.
+ ==========================
+
+
+ Tag sources with `VER-2-10-3'.
+
+ * docs/VERSION.TXT: Add entry for version 2.10.3.
+
+ * README, src/base/ftver.rc, builds/windows/vc2010/index.html,
+ builds/windows/visualc/index.html,
+ builds/windows/visualce/index.html,
+ builds/wince/vc2005-ce/index.html,
+ builds/wince/vc2008-ce/index.html, docs/freetype-config.1:
+ s/2.10.2/2.10.3/, s/2102/2103/.
+
+ * include/freetype/freetype.h (FREETYPE_PATCH): Set to 3.
+
+ * builds/unix/configure.raw (version_info): Set to 23:3:17.
+ * CMakeLists.txt (VERSION_PATCH): Set to 3.
+
+2020-09-25 Werner Lemberg <wl@gnu.org>
+
+ [autofit] Synchronize with ttfautohint.
+
+ This corresponds to the following commits in the ttfautohint git
+ repository:
+
+ bb6842bd3bd437b7b4a7921b0376c860f5e73d18 Typo, formatting.
+ d5c91ddb1cb310257a3dfe9a8e20e1fc51335faa Add Medefaidrin script.
+
+ * src/autofit/afblue.dat: Add blue zone data for Medefaidrin.
+ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+ * src/autofit/afscript.h: Add Medefaidrin standard characters.
+
+ * src/autofit/afranges.c, src/autofit/afstyles.h: Add Medefaidrin
+ data.
+
+2020-09-25 Werner Lemberg <wl@gnu.org>
+
+ Move `scripts/make_distribution_archives.py` to `src/tools`.
+
+ * scr/tools/scripts/make_distribution_archives.py: (_TOP_DIR,
+ _SCRIPT_DIR): Updated to new location.
+ (main): s/shutils.copyfile/shutils.copy/ to preserve file
+ permissions.
+ (main): Prefix source file paths with `git_dir` while copying files
+ to allow calls of the script from other places than the top-level
+ directory.
+
+2020-09-24 Werner Lemberg <wl@gnu.org>
+
+ * src/cff/cffgload.c (cff_slot_load): Scale `vertBearingY`.
+
+ Towards the end of the the function there is a call to
+ `FT_Outline_Get_CBox` that retrieves the glyph bbox in scaled units.
+ That sets `horiBearing{X,Y}` and `vertBearingX` but `vertBearingY`
+ is left alone, and is not scaled.
+
+ Patch from Eric Muller <emuller@amazon.com>.
+
+2020-09-24 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftobjs.c (FT_Load_Glyph): Trace glyph metrics.
+
+2020-09-22 Werner Lemberg <wl@gnu.org>
+
+ [meson] Move auxiliary scripts to `builds/meson`.
+
+ Suggested by Alexei.
+
+ * scripts/*.py: Move meson scripts to...
+ * builds/meson/*.py: ... this new location.
+
+ * meson.build: Updated.
+
+2020-09-21 David Turner <david@freetype.org>
+
+ Add python script for building tarballs.
+
+ * scripts/make_distribution_archives.py: New file.
+
+ This standalone Python script should be equivalent to running `make
+ dist` with the Make-based build system, with the following minor
+ differences:
+
+ - Since `make distclean` doesn't always clean up `objs/` properly,
+ `make dist` archives may contain some stale binaries like
+ `objs/.libs/libfreetype.so.6` or others.
+
+ - `config.guess` and `config.sub` are not updated unless option
+ `--gnu-config-dir=DIR` is used to specify the location of these
+ files.
+
+ - Some bits of the auto-generated reference documentation may
+ appear in slightly different order, probably due to issues related
+ to mkdocs and docwriter.
+
+ As an example, the call
+
+ scripts/make_distribution_archives.py /tmp/freetype2-dist
+
+ creates the following files under `/tmp/freetype2-dist`:
+
+ freetype-<version>.tar.gz
+ freetype-<version>.tar.xz
+ ft<winversion>.zip
+
+2020-09-21 Werner Lemberg <wl@gnu.org>
+
+ * scripts/extract_freetype_version.py: Fix regex typos.
+
+2020-09-21 David Turner <david@freetype.org>
+
+ Add Meson build project file.
+
+ Example usage:
+
+ # Configure Meson build in directory `build-meson` to generate
+ # release binaries comparable to to the ones from the
+ # autotools/make build system.
+ meson setup build-meson \
+ --prefix=/usr/local \
+ --buildtype=debugoptimized \
+ --strip \
+ -Db_ndebug=true
+
+ # After configuring the Meson build with the above command,
+ # compile and install to `/usr/local/`; this includes a pkg-config
+ # file.
+ ninja -C build-meson install
+
+ # Alternatively, compile and install to `/tmp/aa/usr/local/...`
+ # for packaging.
+ DESTDIR=/tmp/aa ninja -C build-meson install
+
+ # Generate documentation under `build-meson/docs`.
+ ninja -C build-meson docs
+
+ Library size comparison for stripped `libfreetype.so` generated by
+ all three build systems:
+
+ - Default build (autotools + libtool): 712 KiB
+ - CMake build (RelWithDebInfo): 712 KiB
+ - Meson build: 712 KiB
+
+
+ * meson.build: New top-level Meson build file for the library.
+
+ * meson_options.txt: New file. It holds user-selectable options for
+ the build, which can be printed with `meson configure`, and selected
+ at `meson setup` or `meson --reconfigure` time with
+ `-D<option>=<value>`.
+
+ * scripts/parse_modules_cfg.py: A script invoked by `meson.build` to
+ parse `modules.cfg` and extract important information out of it
+ (i.e., the list of modules).
+
+ * scripts/process_ftoption_h.py: New script invoked by `meson.build`
+ to process the original `ftoption.h` file. It enables or disables
+ configuration macro variables based on the available dependencies.
+ This is similar to what other build systems are using (i.e., Meson's
+ `configure_file()` command is not used here).
+
+ * scripts/extract_freetype_version.py: New script invoked by
+ `meson.build` to extract the FreeType version number from
+ `<freetype/freetype.h>`.
+
+ * scripts/extract_libtool_version.py: New script invoked by
+ `meson.build` to extract the libtool `revision_info` data from
+ `builds/unix/configure.raw`, and to generate the corresponding
+ shared library suffix.
+
+ * scripts/generate_reference_docs.py: New script invoked by
+ `meson.build` to generate the FreeType 2 reference documentation
+ (using the `docwriter` and `mkdocs` packages, which must be already
+ installed).
+
+2020-09-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Improve the second pass (#58373).
+
+ Besides dropout control the second horizontal sweep is supposed to
+ clean up straight horizontal edges that are mishandled by the first
+ vertical sweep when a line passes through pixel centers. This line
+ would present as perfectly aligned span edges in the second sweep.
+
+ * src/raster/ftraster.c (Horizontal_Sweep_Span): Replace the old
+ implementation with a better one focusing on aligned span edges only.
+
+2020-09-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Tune SMART macro (#58352).
+
+ Windows seems to perform smart dropout control at 26.6 precision.
+ To mimick Windows independent of increased precision, we need to tweak
+ the macro so that some close calls break down rather than up.
+
+ * src/raster/ftraster.c (SMART): Tweak the macro.
+
+2020-09-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Introduce SMART macro.
+
+ * src/raster/ftraster.c (SMART): New macro for smart dropout rounding.
+ (Verstical_Sweep_Drop, Horizontal_Sweep_Drop): Use it.
+
+2020-09-03 Boris Dalstein <dalboris@gmail.com>
+
+ [build] Make CMake install basic version information.
+
+ * CMakeLists.txt: Do it.
+
+2020-09-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [truetype] Reduce Infinality footprint (cont'd).
+
+ * src/truetype/ttinterp.c (Ins_DELTAP): Shrink variable scope.
+ (Ins_SHPIX, Ins_MIRP): Revise if-logic.
+
+2020-09-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [truetype] Reduce Infinality footprint.
+
+ * src/truetype/ttinterp.c (Ins_SHPIX, Ins_MSIRP, Ins_MIAP, Ins_MDRP,
+ Ins_MIRP): Shrink variable scopes and consolidate ifdefs.
+
+2020-09-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [truetype] Refactor compensation color.
+
+ * src/truetype/ttinterp.h (TT_Round_Func): Change the last argument.
+ * src/truetype/ttinterp.c (Ins_ROUND, Ins_NROUND, Ins_MDAP, Ins_MIAP,
+ Ins_MDRP, Ins_MIRP): Move compensation retrieval from here...
+ (Round_*): ... to here.
+ * src/truetype/ttobjs.c (tt_size_init_bytecode): Reserve zero
+ compensation at color index 3.
+
+2020-08-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Don't set target in direct mode.
+
+ * src/smooth/ftsmooth.c (ft_smooth_raster_overlap): Remove assignment.
+ (ft_smooth_raster_lcd) [!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Ditto.
+
+2020-08-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftsmooth.c (ft_smooth_raster_overlap): Limit width.
+
+ Segmentation fault reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=24729
+
+2020-08-22 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgload.c (TT_Get_VMetrics): Add tracing message.
+
+2020-08-05 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [truetype] Retain OVERLAP_SIMPLE and OVERLAP_COMPOUND.
+
+ For glyphs with OVERLAP_SIMPLE or OVERLAP_COMPOUND, set
+ FT_OUTLINE_OVERLAP to render them with direct oversampling, which
+ mitigates artifacts (see 3bb512bc9f62).
+
+ * include/freetype/ftimage.h (FT_OUTLINE_OVERLAP): Redefine to rhyme
+ with OVERLAP_SIMPLE.
+ * src/base/ftgloadr.c (FT_GlyphLoader_Rewind): Reset outline flags.
+ * src/truetype/ttgload.c
+ (TT_Load_Simple_Glyph): Retain OVERLAP_SIMPLE.
+ (load_truetype_glyph): Retain OVERLAP_COMPOUND.
+
+2020-08-04 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttgload.c (TT_Load_Glyph): More tracing.
+
+2020-07-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Hide internal functions with SunPro.
+
+ * include/freetype/internal/compiler-macros.h
+ (FT_INTERNAL_FUNCTION_ATTRIBUTE) <__SUNPRO_C>: Define as __hidden.
+
+2020-07-28 Anuj Verma <anujv@iitbhilai.ac.in>
+
+ Fix static compilation with Visual C.
+
+ * include/freetype/internal/compiler-macros.h
+ (FT_INTERNAL_FUNCTION_ATTRIBUTE) <_WIN32>: Define as empty.
+
+2020-07-28 Priyesh Kumar <priyeshkkumar@gmail.com>
+
+ Fix `-Wformat' compiler warnings.
+
+ * src/*: Fix format specifiers.
+
+ * builds/unix/ftsystem.c (FT_Stream_Open): Ditto.
+
+2020-07-25 Werner Lemberg <wl@gnu.org>
+
+ Fix `-Wformat' compiler warnings.
+
+ Problem reported by Priyesh kumar <priyeshkkumar@gmail.com>
+
+ * src/base/ftoutln.c (FT_Outline_Decompose): Fix number of arguments
+ to tracing macro.
+
+ * src/bdf/bdfdrivr.c (bdf_cmap_char_next, bdf_get_bdf_property):
+ Ditto.
+
+ * src/cache/ftcbasic.c (ftc_basic_family_get_count): Ditto.
+ Reformulate message.
+
+ * src/pcf/pcfdrivr.c (pcf_get_bdf_property): Ditto.
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Ditto.
+ Trace table offset, too.
+
+ * src/truetype/ttgxvar.c (ft_var_apply_tuple): Ditto.
+
+2020-07-23 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_decompress): Fix compiler warning.
+
+ Reported by Hin-Tak.
+
+2020-07-12 Werner Lemberg <wl@gnu.org>
+
+ * builds/unix/configure.raw: Fix inclusion of `ftoption.h'.
+
+2020-07-07 Werner Lemberg <wl@gnu.org>
+
+ Fix clang warnings.
+
+ * include/freetype/internal/autohint.h
+ (FT_DECLARE_AUTOHINTER_INTERFACE): New macro.
+ * src/autofit/afmodule.h: Use it to declare
+ `af_autofitter_interface'.
+
+ * include/freetype/internal/ftobjs.h (FT_DECLARE_GLYPH): New macro.
+ * src/base/ftbase.h: Use it to declare `ft_bitmap_glyph_class' and
+ `ft_outline_glyph_class'.
+
+ * src/base/ftglyph.c: Include `ftbase.h'.
+
+ * src/cff/cffparse.c (cff_parser_run): Fix type of `t2_size'.
+
+ * src/pcf/pcfdrivr.c (pcf_cmap_char_next): Fix type of `result'.
+
+ * src/psaux/psauxmod.c (psaux_module_class): Use `FT_DEFINE_MODULE'.
+ * src/psaux/psauxmod.h: Declare `afm_parser_funcs',
+ `t1_cmap_classes', `cff_decoder_funcs', and `psaux_module_class'.
+
+ * src/pshinter/pshmod.c: Include `pshmod.h'.
+
+ * src/sfnt/sfwoff2.c (ROUND4, WRITE_SHORT): Fix implicit sign
+ conversion.
+ (compute_ULong_sum): Fix return type.
+ Fix implicit sign conversion.
+ (store_points): Fix type of `last_flag', `repeat_count', and `flag'.
+ Use casts to avoid warnings.
+ (reconstruct_glyf): Fix implicit sign conversion.
+ Use cast to avoid warning.
+ (get_x_mins): Fix implicit sign conversion.
+ * src/sfnt/ttcmap.c: Undef `TTCMAPCITEM'.
+ * src/sfnt/ttcmap.h: Define `TTCMAPCITEM' and include `ttcmapc.h' to
+ declare cmap classes.
+
+ * src/smooth/ftsmooth.c (ft_smooth_overlap_spans): Use cast.
+
+ * src/truetype/ttinterp.c (Ins_MIAP): Fix typo.
+
+2020-07-07 David Turner <david@freetype.org>
+
+ [build] Really fix multi and C++ builds.
+
+ The following builds were still failing due to previous changes:
+
+ make multi
+ make multi CC="c++"
+ make CC="c++"
+
+ This patch fixes the issues, which were missing includes to get the
+ right macro definitions in multi-build mode.
+
+ Also, `FT_UNUSED' is actually used by third-party code, so move it
+ back to `public-macros.h' to avoid breaking it.
+
+ * include/freetype/config/public-macros.h (FT_EXPORT): Remove
+ special definition for C++.
+ (FT_UNUSED): Define here instead of...
+ * include/freetype/config/compiler-macros.h: ... here.
+ (FT_FUNCTION_DECLARATION): Remove special definition for C++.
+ (FT_LOCAL_ARRAY_DEF): Fix definition.
+
+ * src/cache/ftccback.h, src/lzw/ftzopen.h, src/gxvalid/gxvmort.h,
+ src/gxvalid/gxvmorx.h: Add `FT_BEGIN_HEADER' and `FT_END_HEADER'.
+
+2020-07-06 David Turner <david@freetype.org>
+
+ [build] Fix multi and C++ builds.
+
+ The following builds were failing due to previous changes:
+
+ make multi
+ make multi CC="c++"
+
+ * include/freetype/config/ftconfig.h: Remove `FT_END_HEADER'.
+
+ * include/freetype/config/ftheader.h (FT_BEGIN_HEADER,
+ FT_END_HEADER): Protect against redefinition.
+
+ * src/cache/ftccache.h, src/cache/ftcmru.h, src/pcf/pcfutil.h,
+ src/psaux/pserror.h, src/psaux/psft.h, src/psaux/psstack.h,
+ src/sfnt/woff2tags.h: Include `compiler-macros.h'.
+
+ * src/sfnt/woff2tags.c: Include `woff2tags.h'.
+
+2020-07-06 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Improve `t1_decoder_parse_metrics' (#58646).
+
+ * src/psaux/t1decode.c (t1_decoder_parse_metrics): Copy
+ corresponding code from old engine's `t1_decoder_parse_charstrings'
+ function to handle `op_callsubr' and `op_return'.
+
+2020-07-05 David Turner <david@freetype.org>
+
+ [build] Improve visibility support of library function names.
+
+ * include/freetype/config/public-macros.h
+ (FT_PUBLIC_FUNCTION_ATTRIBUTE): New macro to tag functions as
+ public (and thus exportable).
+ (FT_EXPORT): Use it.
+
+ * include/freetype/config/compiler-macros.h
+ (FT_INTERNAL_FUNCTION_ATTRIBUTE): New macro to tag functions as
+ internal to the library (and thus hidden). Note that on ELF
+ systems, all internal functions have hidden visibility, which avoids
+ the need to enforce this when invoking the compiler (e.g., with an
+ option like `-fvisibility=hidden').
+
+ (FT_FUNCTION_DECLARATION, FT_FUNCTION_DEFINITION): New base macros
+ to deal with C and C++ linkage issues at the same time.
+
+ (FT_LOCAL, FT_LOCAL_DEF, FT_LOCAL_ARRAY, FT_LOCAL_ARRAY_DEF,
+ FT_BASE, FT_BASE_DEF, FT_EXPORT_VAR, FT_BASE_CALLBACK,
+ FT_BASE_CALLBACK_DEF): Redefined using new macros.
+
+2020-07-05 David Turner <david@freetype.org>
+
+ [build] Split off more stuff from `ftconfig.h'.
+
+ * builds/unix/ftconfig.h.in, builds/vms/ftconfig.h,
+ include/freetype/config/ftconfig.h: Split off macro definitions
+ required by the FreeType API headers to...
+ * include/freetype/config/public-macros.h: ...this new file.
+
+ * builds/unix/ftconfig.h.in, builds/vms/ftconfig.h,
+ include/freetype/config/ftconfig.h: Split off macro definitions used
+ by the library but not to be exposed to clients to...
+ * include/freetype/config/compiler-macros.h: ...this new file.
+
+ * include/freetype/internal/*.h, src/raster/ftraster.h: Include
+ `compiler-macros.h' where needed.
+
+2020-07-05 David Turner <david@freetype.org>
+
+ [build] Move mac support code to `mac-support.h'.
+
+ * builds/unix/ftconfig.h.in, builds/vms/ftconfig.h,
+ include/freetype/config/ftconfig.h: Split off mac-specific stuff
+ to...
+ * include/freetype/config/mac-support.h: ...this new file.
+
+ * CMakeLists.txt, builds/unix/configure.raw: Remove `/undef ->
+ #undef' string replacement; the affected code is no longer part of
+ the `ftconfig.h' template.
+
+2020-07-05 David Turner <david@freetype.org>
+
+ [build] Put integer type definitions into `integer-types.h'.
+
+ Refactor some of the `ftconfig.h' headers and template to move the
+ definition of the FreeType integer types (e.g., `FT_Int16') to a
+ common header file `freetype/config/integer-types.h'.
+
+ * builds/unix/ftconfig.h.in, builds/vms/ftconfig.h,
+ include/freetype/config/ftconfig.h: Split off integer type
+ definition stuff to...
+ * include/freetype/config/integer-types.h: ...this new file.
+
+ * builds/unix/ftconfig.h.in: Control the definition of
+ `FT_SIZEOF_INT' and `FT_SIZEOF_LONG' with macro
+ `FT_USE_AUTOCONF_SIZEOF_TYPES'. If these are not defined, auto
+ detection happens in `integer-types.h' as usual based on `INTXX_MAX'
+ values. Otherwise the autoconf-detected values are used.
+
+ * builds/unix/configure.raw (CPPFLAGS): Don't include path to
+ `config' directory. Instead, ...
+ (FT_CONFIG_STANDARD_LIBRARY_H): Use complete path.
+
+2020-07-05 David Turner <david@freetype.org>
+
+ [build] Rename `build/unix/ftconfig.in' to `ftconfig.h.in'.
+
+ Since we are no longer limited to 8.3 file names, it is simpler to
+ follow the usual conventions for template files.
+
+ * builds/unix/ftconfig.in: Renamed to...
+ * builds/unix/ftconfig.h.in: ...this.
+
+ * CMakeLists.txt, builds/unix/configure.raw: Updated.
+
+2020-07-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Introduce direct oversampling for overlaps.
+
+ This implements oversampling to mitigate artifacts in pixels partially
+ covered by overlapping contours. It turns out that the 4x4
+ oversampling is sufficient but, at least, quadruples the rendering
+ time. The outline has to set FT_OUTLINE_OVERLAP to use this method.
+
+ * include/freetype/ftimage.h (FT_OUTLINE_OVERLAP): New flag.
+ * src/smooth/ftsmooth.c (ft_smooth_render): Check it to...
+ (ft_smooth_raster_overlap): ... inflate outline and set up direct
+ rendering for oversampling with...
+ (ft_smooth_overlap_spans): ... new span function that integrates them.
+
+2020-07-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Use direct rendering mode in Harmony.
+
+ Instead of rendering 3 bitmaps side by side and reshuffling, we use
+ direct rendering to deliver the bitmaps on each third byte.
+
+ * src/smooth/ftsmooth.c (ft_smooth_raster_lcd)
+ [!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Set up direct mode with...
+ (ft_smooth_lcd_spans): ... new span function.
+
+2020-07-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Separate LCD paths from gray rendering.
+
+ This makes `ft_smooth_render' a lot smaller and easier to follow. It
+ also cleanly separates Harmony and ClearType-style LCD rendering
+ algorithms. Now I only wish to move LCD filtering and geometry from
+ FT_Library to FT_Renderer.
+
+ * src/smooth/ftsmooth.c (ft_smooth_render): Move LCD code from here...
+ (ft_smooth_raster_lcd, ft_smooth_raster_lcdv): ... to here.
+ [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Reorganize #ifdef's.
+
+2020-06-20 Sebastian Rasmussen <sebras@gmail.com>
+
+ [cff] Fix handling of `style_name == NULL' (#58630).
+
+ * src/cff/cffobjs.c (cff_face_init): If a call to `cff_strcpy' fails
+ by returning NULL in `cff_face_init', `remove_style' is still
+ called. This means that the NULL pointer is dereferenced, causing a
+ crash.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [cff] Fix another two memory leaks (#58629).
+
+ * src/cff/cffobjs.c (cff_size_init): If a call to `funcs->create'
+ fails to allocate one of the `internal->subfont' variables, make
+ sure to free `internal->topfont' and any successfully allocated
+ subfonts.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [psaux] Fix memory leak (#58626).
+
+ * src/psaux/psstack.c (cf2_stack_init): If `cf2_stack_init' fails to
+ allocate the stack, return error early.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [base] Fix memory leak (#58624).
+
+ * src/base/ftobjs.c (FT_New_Size): Avoid trying to free
+ `size->internal' unless `size' has been allocated. This mistake
+ appeared in the fix for issue #58611.
+
+2020-06-19 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] Rework d1180b5f9598 until further notice.
+
+ * src/base/ftoutln.c (FT_Outline_Get_Orientation): Reject large
+ outlines.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [cff, cid] Fix segfaults in case of error (#58621).
+
+ * src/cff/cffobjs.c (cff_slot_done), src/cid/cidobjs.c
+ (cid_slot_done): If `ft_glyphslot_init' fails to allocate
+ `internal', then the class' `done_slot' callback (called by
+ `ft_glyphslot_done') must not dereference the pointer to `internal'.
+
+2020-06-19 Werner Lemberg <wl@gnu.org>
+
+ [base] Fix UBSAN error.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23166
+
+ * src/base/ftoutln.c (FT_Outline_Get_Orientation): Avoid values
+ larger than 32 bits.
+
+2020-06-19 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix segfault.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=23402
+
+ * src/sfnt/sfwoff2.c (get_x_mins): Check whether `loca' table
+ exists.
+
+2020-06-19 Stephen McDowell <svenevs.dev@gmail.com>
+
+ [sfnt] Support Intel compilers.
+
+ * src/sfnt/pngshim.c (premultiply_data): Intel compilers do not
+ currently support `__builtin_shuffle'.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [base] Fix memory leak (#58611).
+
+ * src/base/ftobjs.c (FT_New_Size): When the call to `clazz->init_size'
+ fails, make sure to free `size->internal'.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [cff] Fix memory leak (#58610).
+
+ * src/cff/cffobjs.c (cff_size_init): When the call to
+ `funcs->create' fails, make sure to free `internal'.
+
+2020-06-19 Werner Lemberg <wl@gnu.org>
+
+ * src/cff/cffload.c (cff_index_get_pointers): Rename `t' to `tbl'.
+
+2020-06-19 Sebastian Rasmussen <sebras@gmail.com>
+
+ [cff] Free table upon error allocating other data (#58609).
+
+ * src/cff/cffload.c (cff_index_get_pointers): When new_bytes fails
+ to allocate, make sure to free the table. Do the same for both
+ allocations if there is a later error.
+
+2020-06-13 Werner Lemberg <wl@gnu.org>
+
+ Remove redundant inclusion of `ft2build.h'.
+
+ * */*: Remove `#include <ft2build.h>' where possible.
+
+ * include/freetype/freetype.h: Remove cpp error about missing
+ inclusion of `ft2build.h'.
+
+2020-06-08 David Turner <david@freetype.org>
+
+ Make macros for header file names optional.
+
+ We no longer have to take care of the 8.3 file name limit; this
+ allows us (a) to introduce longer, meaningful file names, and (b) to
+ avoid macro names in `#include' lines altogether since some
+ compilers (most notably Visual C++) doesn't support this properly.
+
+ */*: Replace
+
+ #include FOO_H
+
+ with
+
+ #include <freetype/foo.h>
+
+ or something similar. Also update the documentation.
+
+2020-06-02 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/ttcmap.c (tt_face_build_cmaps): Trace number of cmaps.
+
+2020-05-18 David Turner <david@freetype.org>
+
+ Remove obsolete HAVE_STDINT_H probing macro.
+
+ This macro was updated by the unix configure script and the
+ `CMakeLists.txt' one, but is never used in the source tree (nor is
+ <stdint.h> included anywhere).
+
+ * CMakeLists.txt, builds/unix/ftconfig.in: Don't handle
+ `HAVE_STDINT_H'.
+
+2020-05-18 David Turner <david@freetype.org>
+
+ Remove Jamfile files from the tree.
+
+ These have not been used in a very, very long time, so better remove
+ them. A corresponding patch will be submitted to the
+ `freetype2-demos' repository.
+
+ * src/Jamfile, src/*/Jamfile, Jamrules: Delete.
+
+2020-05-12 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Turn on LCD filtering during FreeType initialization.
+
+ * src/smooth/ftsmooth.c (ft_smooth_init): Enable LCD filtering.
+
+ * include/freetype/ftlcdfil.h: Document it, remove patent warnings.
+ * include/freetype/freetype.h (FT_Render_Mode): Updated.
+ * include/freetype/config/ftoption.h, devel/ftoption.h
+ [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Do not mention patents.
+
+2020-05-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Stop using dedicated LCD modules and classes.
+
+ The LCD modules were never truly independent. They mostly served as
+ a way to disable patented LCD rendering, which is no longer necessary.
+ The `smooth' module now handles LCD modes as well.
+
+ * src/smooth/ftsmooth.c (ft_smooth_lcd_renderer_class.
+ ft_smooth_lcdv_renderer_class): Deleted.
+ (ft_render_smooth): Reworked from `ft_render_smooth_generic'.
+ * src/smooth/ftsmooth.h: Remove dedicated LCD classes.
+ * src/smooth/module.mk: Remove dedicated LCD modules.
+ * include/freetype/config/ftmodule.h: Ditto.
+ * builds/amiga/include/config/ftmodule.h: Ditto.
+ * include/freetype/ftmodapi.h: Do not mention LCD modules.
+
+2020-05-09 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.10.2 released.
+ ==========================
+
+
+ Tag sources with `VER-2-10-2'.
+
+ * docs/VERSION.TXT: Add entry for version 2.10.2.
+
+ * README, Jamfile (RefDoc), src/base/ftver.rc,
+ builds/windows/vc2010/index.html, builds/windows/visualc/index.html,
+ builds/windows/visualce/index.html,
+ builds/wince/vc2005-ce/index.html,
+ builds/wince/vc2008-ce/index.html, docs/freetype-config.1:
+ s/2.10.1/2.10.2/, s/2101/2102/.
+
+ * include/freetype/freetype.h (FREETYPE_PATCH): Set to 2.
+
+ * builds/unix/configure.raw (version_info): Set to 23:2:17.
+ * CMakeLists.txt (VERSION_PATCH): Set to 2.
+
+ * docs/CHANGES: Updated.
+
+2020-05-08 Jakub Alba <jalba@vewd.com>
+
+ * src/truetype/ttinterp.c (TT_RunIns): Adjust loop counter (#58319).
+
+ The font that exceeds the old limit is Icono Regular, version
+ 1.00000.
+
+2020-05-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/freetype.mk: Refactor for readability.
+
+2020-05-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds] Clean up Windows CE project files.
+
+ Remove version from filenames that caused a lot of polution in the
+ release process. Use VERSIONINFO resource instead.
+
+ * builds/wince/vc2005-ce/freetype.vcproj,
+ builds/wince/vc2008-ce/freetype.vcproj,
+ builds/windows/visualce/freetype.vcproj,
+ builds/windows/visualce/freetype.dsp: s/2101//g, but add `ftver.rc'.
+ * builds/wince/vc2008-ce/index.html,
+ builds/wince/vc2005-ce/index.html,
+ builds/windows/visualce/index.html: s/2101//g.
+
+2020-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * devel/ft2build.h: Override FT_CONFIG_MODULES_H here as well.
+
+2020-05-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds/unix] Consolidate marco overrides (for the demos to see them).
+
+ * builds/unix/unix-cc.in (FT_CONFIG_MODULES_H, FT_CONFIG_OPTIONS_H):
+ Override them here...
+ * builds/freetype.mk: ... instead of here.
+
+2020-04-08 Werner Lemberg <wl@gnu.org>
+
+ Allow setting `CC' in Unix build (#58051).
+
+ * builds/unix/unix-cc.in (CC): Use `override'. The command line
+ value of `CC' (if any) is stored already in `CCraw'.
+
+2020-04-04 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Return if single stream operation fails.
+
+ * src/sfnt/sfwoff2.c (get_x_mins): Do it.
+
+ * src/sfnt/woff2tags.c: Remove unused include.
+
+2020-03-22 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [docs] Fix building docs if `srcdir' != `builddir'.
+
+ `docs/reference/*' was moved one directory up in commit 237fed6.
+
+ * builds/unix/unix-def.in (PIP): Remove variable.
+
+ * configure: Create `docs' directory and copy assets from
+ `docs/markdown'.
+
+ * docs/README: Output directory is `reference'.
+
+2020-03-21 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [docwriter] Drop support for Python < 3.5.
+
+ Python versions < 3.5 have reached end-of-life and as such, no
+ security or bug fixes will be provided for those versions. See
+
+ https://devguide.python.org/#status-of-python-branches
+
+ for more information.
+
+ * Jamfile (RefDoc): Add `site' parameter.
+
+ * builds/detect.mk (std_setup): Update Python version requirement.
+
+ * builds/freetype.mk (refdoc-venv): Use pip as `python -m pip'.
+
+ * builds/unix/ax_compare_version.m4,
+ builds/unix/ax_prog_python_version.m4: Macros to detect Python
+ version. New files.
+
+ * builds/unix/configure.raw: Check for Python >= 3.5 and remove
+ check for `pip'.
+
+ * docs/CHANGES, docs/INSTALL.GNU, docs/README: Updated.
+
+2020-03-02 Moazin Khatti <moazinkhatri@gmail.com>
+
+ [gzip] Support `gzip' encoded header conditionally.
+
+ In order to support `gzip' encoded header the call to
+ `inflateInit2' was modified in commit 6a92b1fadde26477a9179.
+ However, this code breaks with the outdated internal version
+ of zlib. This is a temporary fix to conditionally support
+ `gzip' encoded header whenever a system installation of zlib
+ is being used.
+
+ Problem report in
+
+ https://lists.nongnu.org/archive/html/freetype-devel/2020-02/msg00023.html
+
+ * src/gzip/ftgzip.c (FT_Gzip_Uncompress): Change the the call to
+ `inflateInit2' depending on whether the system installation is
+ being used or the internal copy.
+
+2020-02-29 Ben Wagner <bungeman@google.com>
+
+ [truetype] Fix state of `FT_Face' for buggy `gvar' tables (#57923).
+
+ By resetting the blend as implemented with this commit fonts with
+ invalid `gvar' tables may keep calling into `ft_var_load_gvar' from
+ `tt_set_mm_blend' and failing, but the font was invalid anyway and
+ we want to keep seeing the failure in `tt_set_mm_blend'.
+
+ * src/truetype/ttgxvar.c (ft_var_load_gvar): Calculate length of
+ offset array once.
+ Allocate arrays after `FT_FRAME_ENTER' (extra check before
+ allocating and avoid needing to free array later if error entering
+ frame).
+ Always call `FT_FRAME_EXIT'.
+ Consistently set counts immediately after array initialized.
+ Reset the blend (particularly `blend->glyphoffsets') on failure.
+
+2020-03-01 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [docs] Update docwriter stylesheet.
+
+ This change is required to support docwriter 1.2.1.
+
+ See
+
+ https://github.com/freetype/docwriter/issues/36
+
+ for more information.
+
+ * docs/markdown/stylesheets/extra.css:
+ (.md-typeset code) -> (.md-typeset pre>code)
+ (pre) -> (pre>code)
+ (p, .md-typeset p, h4): Remove commented styles.
+ (table.index): Remove unused styles.
+
+2020-02-28 Ben Wagner <bungeman@google.com>
+
+ [truetype] Add better checks for loading `gvar' table (#57905).
+
+ * src/truetype/ttgxvar.c (ft_var_load_gvar): Delay settings of any
+ `blend->xxxcount' values until the corresponding data has been
+ checked.
+ Also do some sanitizing to avoid a too early exit.
+
+ (TT_Vary_Apply_Glyph_Deltas): Improve tracing message.
+
+2020-02-27 Werner Lemberg <wl@gnu.org>
+
+ Make `FT_HAS_*' and `FT_IS_*' really return true (#57906).
+
+ * include/freetype/freetype.h (FT_HAS_*, FT_IS_*): Implement it.
+
+2020-02-25 Dominik Röttsches <drott@chromium.org>
+
+ Fix for CFF space glyph regression (#57541).
+
+ * src/psaux/psft.c (cf2_decoder_parse_substrings): Replace early-out
+ with FT_OFFSET.
+
+2020-02-22 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix font table access.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20778
+
+ * src/sfnt/sfwoff2.c (get_x_mins): Explicitly check for presence of
+ `head' table, which might not have been processed yet.
+
+2020-02-21 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Make `t1_decoder_parse_metrics' handle `op_div' (#57519).
+
+ * src/psaux/t1decode.c (t1_decoder_parse_metrics): Copy
+ corresponding code from old engine's `t1_decoder_parse_charstrings'
+ function.
+
+2020-02-19 Nikolaus Waxweiler <nikolaus.waxweiler@daltonmaag.com>
+
+ [autofit] Add support for Hanifi Rohingya script.
+
+ * src/autofit/afblue.dat: Add blue zone data for Hanifi Rohingya.
+ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+ * src/autofit/afscript.h: Add Hanifi Rohingya standard character.
+
+ * src/autofit/afranges.c, src/autofit/afstyles.h: Add Hanifi
+ Rohingya data.
+
+2020-02-19 Werner Lemberg <wl@gnu.org>
+
+ Require HarfBuzz 1.8.
+
+ * builds/unix/configure.raw, CMakeLists.txt: Request HarfBuzz 1.8.0
+ or newer.
+
+ We are going to add auto-hinter support for Hanifi Rohingya, which
+ was introduced in Unicode 11.0.
+
+2020-02-12 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/ttcmap.c (tt_face_build_cmaps): Ignore version (#57708).
+
+2020-02-04 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttinterp.c (TT_RunIns): Adjust loop counter (#57732).
+
+ The font that exceeds the old limit is Constantine, version 1.001.
+
+2020-01-04 Werner Lemberg <wl@gnu.org>
+
+ [base] Fix `FREETYPE_PROPERTIES=type1:hinting-engine=adobe`.
+
+ * src/base/ftpsprop.c (ps_property_set) [hinting-engine]: Avoid an
+ incorrect return value that caused a warning. The function did the
+ right thing, though.
+
+2020-01-03 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix memory leaks and a runtime warning.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19773
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18101
+
+ * src/sfnt/sfwoff2.c (compute_ULong_sum): Add missing cast.
+ (reconstruct_hmtx): Add missing deallocation calls.
+
+2020-01-02 Dominik Röttsches <drott@chromium.org>
+
+ [truetype] Fix UBSan warning on offset to nullptr (#57501).
+
+ * src/truetype/ttinterp.c (Ins_CALL): Fail if `exc->FDefs' is null.
+
+2019-12-31 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Allow bitmap-only fonts (#57394).
+
+ * src/sfnt/sfwoff2.c (reconstruct_font): Fix test for `glyf' and
+ `loca' tables.
+
+2019-12-21 Hugh McMaster <hugh.mcmaster@outlook.com>
+
+ [docs] (2/2) Fix generation of API documentation (#56745).
+
+ Creating the API Reference in the (new) `reference' sub-directory is
+ consistent with other documentation sub-topics, such as `design',
+ `glyphs' and `tutorial'.
+
+ This patch fixes broken hyperlinks in the documentation pointing to
+ and from the API Reference. It also allows web assets to load from
+ their relative paths.
+
+ * builds/freetype.mk (DOC_DIR): Adjust.
+ (refdoc, refdoc-venv): Add `--site' argument.
+
+ * builds/toplevel.mk (do-dist): Updated.
+
+2019-12-21 Hugh McMaster <hugh.mcmaster@outlook.com>
+
+ [docs] (1/2) Move static web assets (#56745).
+
+ * docs/reference/*: Move ...
+ * docs: ... one directory up.
+
+2019-12-21 Dominik Röttsches <drott@chromium.org>
+
+ Fix more UBSan warnings on adding offset to nullptr (#57432).
+
+ * src/truetype/ttinterp.c (Ins_LOOPCALL), src/psaux/psft.c
+ (cf2_initLocalRegionBuffer): Use `FT_OFFSET'.
+
+2019-12-16 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Fix UBSan warnings on adding offsets to nullptr.
+
+ Reported as
+
+ https://bugs.chromium.org/p/chromium/issues/detail?id=1032152
+
+ * src/truetype/ttinterp.c (Ins_FDEF, Ins_IDEF): Use `FT_OFFSET'.
+
+2019-12-14 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Fix integer overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19305
+
+ * src/truetype/ttinterp.c (Ins_MIRP): Use `ADD_LONG'.
+
+2019-12-13 Werner Lemberg <wl@gnu.org>
+
+ Another bunch of UBSan warnings on adding offsets to nullptr.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19427
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19433
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19441
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19451
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19452
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19457
+
+ * src/autofit/aflatin.c (af_latin_hints_compute_segments,
+ af_latin_hints_compute_edges): Use `FT_OFFSET'.
+
+ * src/base/ftstream.c (FT_Stream_EnterFrame): Use `FT_OFFSET'.
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings): Exit early
+ if there is no charstring.
+
+ * src/psaux/psobjs.c (t1_decrypt): Use `FT_OFFSET'.
+
+ * src/smooth/ftsmooth.c (ft_smooth_render_generic): Exit early for
+ zero bitmap dimensions.
+
+2019-12-09 Dominik Röttsches <drott@chromium.org>
+
+ Fix more UBSan warnings on adding offset to nullptr (#57384).
+
+ * src/smooth/ftsmooth.c (ft_smooth_render_generic),
+ src/psaux/psobjs.c (ps_table_add): Use `FT_OFFSET'.
+
+2019-12-05 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttinterp.c (TT_RunIns): Use `FT_OFFSET'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/chromium/issues/detail?id=1030614
+
+2019-12-03 Werner Lemberg <wl@gnu.org>
+
+ More nullptr offset UBSan warnings (#57331, #57347).
+
+ * src/autofit/afcjk.c (af_cjk_hints_compute_segments),
+ src/psaux/psft.c (cf2_getSeacComponent), src/truetype/ttinterp.c
+ (Ins_UNKNOWN): Use `FT_OFFSET'.
+
+2019-11-29 Dominik Röttsches <drott@chromium.org>
+
+ Avoid more nullptr offset UBSan warnings (#57316).
+
+ * src/base/ftoutln.c (FT_Outline_Transform): Bail on empty points.
+ * src/cff/cffload.c (cff_subfont_load): Use `FT_OFFSET'.
+ * src/psaux/psft.c (cf2_decoder_parse_substrings): Early out if
+ `charstring_base' or `charstring_len' are null.
+ * src/sfnt/ttload.c (tt_face_load_name): Use `FT_OFFSET'.
+
+2019-11-23 John Stracke <jstracke@Google.com>
+
+ [base] Really fix #57194.
+
+ Apply accidentally missed second part of patch.
+
+ * src/base/ftgloadr.c (FT_GlyphLoader_CheckPoints): Call
+ `FT_GlyphLoader_CreateExtra'.
+
+2019-11-23 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Avoid sanitizer warning (#57289).
+
+ * src/truetype/ttpload.c (tt_face_get_device_metrics): Use
+ `FT_OFFSET'.
+
+2019-11-23 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [truetype] Fix integer overflow (#57287).
+
+ * src/truetype/ttgload.c (compute_glyph_metrics): Use `SUB_LONG'.
+
+2019-11-23 Ben Wagner <bungeman@google.com>
+
+ [sfnt] Avoid sanitizer warning (#57286).
+
+ * src/sfnt/ttcmap.c (tt_face_build_cmaps): Avoid possible `NULL +
+ offset' computation.
+ Tag `table' as `const'.
+
+2019-11-23 John Stracke <jstracke@Google.com>
+ Werner Lemberg <wl@gnu.org>
+
+ [base] Fix `NULL + offset' sanitizer warnings (#57194).
+
+ * src/base/ftgloadr.c (FT_GlyphLoader_Adjust_Points,
+ FT_GlyphLoader_Adjust_Subglyphs): Use `FT_OFFSET'.
+ (FT_GlyphLoader_CreateExtra): Add short cut if some values are zero.
+
+2019-11-23 Werner Lemberg <wl@gnu.org>
+
+ * include/freetype/internal/ftmemory.h (FT_OFFSET): New macro.
+
+ Use this for `base + offset' pointer calculations where `base' can
+ be NULL (triggering a sanitizer warning even if the resulting
+ pointer gets never dereferenced since it is undefined behaviour
+ in C).
+
+ Suggested by Ben Wagner.
+
+2019-11-23 Ben Wagner <bungeman@google.com>
+
+ [sfnt] Ensure OTTO fonts have tables (#57285).
+
+ * src/sfnt/ttload.c (tt_face_load_font_dir): Add test.
+
+2019-11-23 Behdad Esfahbod <behdad@behdad.org>
+
+ Minor fixes for recent compilers.
+
+ * src/gzip/infutil.h (inflate_mask): Add `const'.
+
+ * src/autofit/aflatin2.c: Include `ft2build.h'.
+
+2019-11-07 Nikolaus Waxweiler <madigens@gmail.com>
+
+ * CMakeLists.txt: Minor additions to the notes, compile
+ builds/unix/ftsystem.c instead of src/base/ftsystem.c on UNIX.
+
+ The latter change is based on the code proposed by rim in #55235.
+
+2019-10-25 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Check `num_fonts' for TTCs.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18494
+
+2019-10-22 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Avoid undefined shift.
+
+ Also improve tracing.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18390
+
+2019-10-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/pngshim.c (premultiply_data): Optimize for __SSE__ only.
+
+2019-10-10 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (reconstruct_glyf): Check `triplet_size'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18108
+
+2019-10-09 John Tytgat <John.Tytgat@esko.com>
+
+ [cff] Fix FT_FACE_FLAG_GLYPH_NAMES for CFF2 based fonts (#57023).
+
+ * src/cff/cffobjs.c (cff_face_init): Don't set
+ FT_FACE_FLAG_GLYPH_NAMES for CFF2 based fonts.
+
+2019-10-08 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix SFNT table checks.
+
+ Also reduce number of SFNT table lookups.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18065
+
+ * include/freetype/internal/wofftypes.h (WOFF2_InfoRec): Add fields
+ `glyf_table', `loca_table', and `head_table'.
+
+ * src/sfnt/sfwoff2.c (reconstruct_glyf): Update signature.
+ Use table pointers in `info' parameter.
+ (get_x_mins): Check `maxp_table'
+ Use table pointers in `info' parameter.
+ (reconstruct_font): Use and set table pointers in `info' parameter.
+ Fix check for `glyf' and `loca' tables.
+ Update call to `reconstruct_glyf'.
+ (woff2_open_font): Updated.
+
+2019-10-06 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (reconstruct_glyf): Fix reallocation.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=18046
+
+2019-10-06 Werner Lemberg <wl@gnu.org>
+
+ Improve memory debugging.
+
+ * include/freetype/internal/ftmemory.h (FT_MEM_FREE): Use
+ `FT_DEBUG_INNER' to set source code file name and line.
+
+ * src/base/ftdbgmem.c (ft_mem_table_remove): Better formatting of
+ tracing message.
+
+2019-10-03 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2 (reconstruct_font): Fix reallocation.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17966
+
+2019-10-01 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftstroke.c (ft_stroker_inside): Speed up.
+
+2019-10-01 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2 (woff2_open_font): Initialize `woff2.ttc_fonts'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17804
+
+2019-09-30 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (reconstruct_font): Fix memory leak.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17812
+
+2019-09-30 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Reject fonts without `head' table.
+
+ Also fix memory deallocation in case of error.
+
+ `head' problem reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17820
+
+ * src/sfnt/sfwoff2.c (reconstruct_glyf): Don't use `stream_close'.
+ Abort if `head_table' is NULL.
+ Don't free `transformed_buf' in case of error.
+ (woff2_open_font): Don't set `uncompressed_buf' to NULL.
+
+2019-09-29 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix compiler warnings.
+
+ Problem reported by Alexei.
+
+ * src/sfnt/sfwoff2.c (reconstruct_glyf): Initialize `x_min'.
+ (reconstruct_font): Initialize `num_hmetrics'.
+ (woff2_open_font): Initialize `info'.
+
+2019-09-28 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Fix sanity check.
+
+ Correct thinkos in patch from 2019-09-01.
+
+2019-09-28 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix memory leaks.
+
+ One of them reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17766
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Free `info->x_mins' and
+ `woff2->ttc_fonts'.
+
+ (reconstruct_glyf): Initialize `info->x_mins'.
+
+2019-09-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftstroke.c (ft_stroker_cap): Speed up caps.
+
+2019-09-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftstroke.c (ft_stroker_outside): Speed up clipped miter.
+ * include/freetype/ftstroke.h: Wordsmith miter docs.
+
+2019-09-25 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Check (sum of) table sizes.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17684
+
+2019-09-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftstroke.c (ft_stroke_border_arcto): Speed up calculations.
+
+2019-09-20 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Fix memory leaks.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16896
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Fix error handling.
+ Free `uncompressed_buf'.
+ (reconstruct_font): Free `transformed_buf'.
+
+2019-09-17 Werner Lemberg <wl@gnu.org>
+
+ * src/otvalid/otvcommon.c (otv_Coverage_get_last): Guard `count'.
+
+ Problem reported by Marc Schönefeld <marc.schoenefeld@gmx.org>.
+
+2019-09-17 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Check table index.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17100
+
+2019-09-15 Avi Halachmi (:avih) <avihpit@yahoo.com>
+
+ [cmake] Don't fail if brotli is missing (#56894).
+
+ The libs which cmake controls are commented out at
+
+ include/freetype/config/ftoption.h
+
+ and cmake un-comment each enabled library, but the brotli option was
+ not commented out, therefore `FT_CONFIG_OPTION_USE_BROTLI' remained
+ defined even if brotli was missing/disabled/etc.
+
+ Comment it such that cmake can control it, which means leaving it
+ undefined if brotli is missing.
+
+ * include/freetype/config/ftoption.h: Fix typo.
+
+2019-09-05 Werner Lemberg <wl@gnu.org>
+
+ [cmake] Add brotli support.
+
+ * CMakeLists.txt (FT_WITH_BROTLI): New option.
+
+ * builds/cmake/FindBrotliDec.cmake: New file.
+
+2019-09-05 Werner Lemberg <wl@gnu.org>
+
+ Fix handling of `AF_CONFIG_OPTION_INDIC'.
+
+ * devel/ftoption.h, include/freetype/config/ftoption.h:
+ `AF_CONFIG_OPTION_INDIC' needs `AF_CONFIG_OPTION_CJK'.
+
+2019-09-05 Werner Lemberg <wl@gnu.org>
+
+ CMakeLists.txt: Fix generation of DLL related stuff (#56852).
+
+ Extract `version_info' variable from `builds/unix/configure.raw' and
+ use the data to correctly set `LIBRARY_VERSION' and
+ `LIBRARY_SOVERSION'.
+
+ Also use the data to set `ft_version' field in `freetype2.pc'.
+ Also fix the needed minimum version of HarfBuzz in `freetype2.pc'.
+
+2019-09-03 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (compute_ULong_sum): Fix undefined shift.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16933
+
+2019-09-01 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Add sanity check.
+
+ Don't trust `totalSfntSize' unconditionally.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16893
+
+2019-08-27 Dominik Röttsches <drott@chromium.org>
+
+ [woff2] Don't use `FT_UInt64' (#56815).
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Use `FT_UInt32' for
+ `file_offset'. This fixes builds on platforms where `FT_LONG64' is
+ not defined while still being sufficient to store a file offset.
+
+2019-08-27 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Prevent crash in `TT_Set_Named_Instance' (#56813).
+
+ * src/truetype/ttgxvar.c (TT_Set_Named_Instance): Fix error
+ handling.
+
+2019-08-27 Werner Lemberg <wl@gnu.org>
+
+ [woff2] Fix compiler warnings.
+
+ * src/sfnt/sfwoff2.c (read_num_hmetrics): Remove unused argument
+ `table_len'.
+ Update caller.
+ (triplet_decode, compute_bbox, store_loca, reconstruct_glyf): Make
+ `i' variable unsigned.
+ (reconstruct_glyph): Remove condition which is always false.
+ (reconstruct_html): Removed unused argument `transformed_size'.
+ Update caller.
+
+ * src/sfnt/woff2tags.c (woff2_known_tags): Remove condition which is
+ always false.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Check whether known tag is in array bounds.
+
+ If table tag is not 0x3f, we expect a value between 0 and 62. If
+ this is not the case, exit with errors.
+
+ * src/sfnt/sfwoff2/c: Check whether table tag makes sense.
+
+ * src/sfnt/woff2tags.c: Return 0 if tag is out of bounds.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ * src/sfnt/sfwoff2.c: Improve trace comments.
+
+ Adjust tracing levels for comments, and more formatting.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Support `hmtx' reconstruction when `glyf' is untransformed.
+
+ `reconstruct_hmtx' requires `info->x_mins' and `info->num_glyphs' to
+ reconstruct the hmtx table. In case glyf is not transformed, we
+ call `get_x_mins' which does the necessary work.
+
+ * src/sfnt/sfwoff2.c (get_x_mins): New function.
+ (reconstruct_font): Call get_x_mins.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [sfnt] Support `face->num_faces' for WOFF2 fonts.
+
+ Set correct value of `face->num_faces' for WOFF2 fonts. This is
+ being handled separately because we only load the tables for the
+ requested font face in `woff2_open_font' and create a single-face
+ sfnt stream.
+
+ The full discussion is at:
+
+ https://lists.gnu.org/archive/html/freetype-devel/2019-08/msg00000.html
+
+ * src/sfnt/sfobjs.c (sfnt_open_font): Add parameter
+ `woff2_num_faces'.
+ (sfnt_init_face): Introduce variable `woff2_num_faces', and change
+ `face->root.num_faces' if `woff2_num_faces' is set.
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Validate requested face
+ index and handle negative face indices.
+
+ * src/sfnt/sfwoff2.h (woff2_open_font): Add parameter `num_faces' to
+ declaration.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Improve memory and error handling.
+
+ Free up memory after use, and improve error handling.
+
+ * src/sfnt/sfwoff2.c (reconstruct_font, woff2_open_font): Implement
+ changes.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Avoid too many calls to `FT_REALLOC'.
+
+ We do this by using `totalSfntSize' as an initial reference, and
+ extending the buffer when required. This reduces rendering time
+ considerably.
+
+ * include/freetype/internal/wofftypes.h (WOFF2_HeaderRec): Add
+ `totalSfntSize', rename `total_sfnt_size' to `actual_sfnt_size'.
+
+ * src/sfnt/sfwoff2.c (write_buf): Add parameter `dst_size' to keep
+ track of and update total size of stream.
+
+ (WRITE_SFNT_BUF, WRITE_SFNT_BUF_AT): Modify macros accordingly.
+
+ (pad4, store_loca, reconstruct_glyf, reconstruct_hmtx,
+ reconstruct_font): Update parameters to accept `sfnt_size'.
+
+ (woff2_open_font): Add variable `sfnt_size'. Use WOFF2 header field
+ `totalSfntSize' as initial reference (if value makes sense) and
+ allocate `totalSfntSize' bytes for the sfnt stream. `write_buf'
+ handles reallocation if and when required. Also resize the stream
+ to `actual_sfnt_size' after reconstruction.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Reconstruct `loca', `hmtx', and swap out stream.
+
+ Add necessary functions to reconstruct loca and hmtx tables (the two
+ remaining tables that can have a transform). `woff2_open_font' is
+ now capable of loading a woff2 font face. This code may still need
+ more refining and better memory management.
+
+ * include/freetype/internal/wofftypes.h (WOFF2_HeaderRec): Add total
+ (final) size of sfnt stream.
+
+ (WOFF2_InfoRec): Add header checksum value.
+
+ * src/sfnt/sfobjs.c (sfnt_open_font): Change `face_instance_index'
+ parameter to its pointer so its value can be modified by
+ `woff2_open_font'.
+
+ * src/sfnt/sfwoff2.c: (WRITE_SFNT_BUF_AT): New macro to write into
+ sfnt buffer at given position.
+
+ (write_buf): Add parameter `extend_buf' which allows caller to
+ specify whether buffer should be reallocated before copying data.
+
+ (WRITE_SFNT_BUF): Updated.
+
+ (pad4, store_loca, reconstruct_htmx): New functions.
+
+ (reconstruct_glyf): Calculate loca values and store them.
+
+ (reconstruct_font): Call `reconstruct_hmtx', write table record
+ entries, and calculate table checksums. Also calculate font
+ checksum and update `checksumAdjustment' entry in head table.
+
+ (woff2_open_font): Open stream for sfnt buffer, swap out input
+ stream and return.
+
+ * src/sfnt/sfwoff2.h (woff2_open_font): Modify parameter to accept
+ pointer to `face_index'.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Reconstruct transformed `glyf' table.
+
+ Reconstruct `glyf' table if it is transformed in the uncompressed
+ table stream. Also add necessary structures, macros and functions.
+
+ * include/freetype/internal/wofftypes.h (WOFF2_InfoRec,
+ WOFF2_SubstreamRec, WOFF2_PointRec): New structures.
+ (WOFF2_TableRec): s/OrigLength/dst_length/.
+
+ * src/sfnt/sfwoff2.c (READ_255USHORT, READ_BASE128): Use
+ `FT_SET_ERROR' to set implicit `error' variable.
+
+ (WRITE_SHORT): New macro.
+
+ (N_CONTOUR_STREAM, N_POINTS_STREAM, FLAG_STREAM, GLYPH_STREAM,
+ COMPOSITE_STREAM, BBOX_STREAM, INSTRUCTION_STREAM): New macros to
+ refer to substreams of the transformed `glyf' tables.
+
+ (Read255UShort, ReadBase128): Return errors set by `FT_READ_XXX'
+ macros.
+
+ (with_sign, safe_int_addition): New functions to add sign to values
+ based on a flag and perform safe addition respectively.
+
+ (triplet_decode): Decode variable-length (flag, xCoordinate,
+ yCoordinate) triplet for a simple glyph. See
+
+ https://www.w3.org/TR/WOFF2/#triplet_decoding
+
+ (store_points, compute_bbox, composteGlyph_size, reconstruct_glyf):
+ New functions.
+
+ (reconstruct_font): Call `reconstruct_glyf'.
+
+ * src/sfnt/sfwoff2.h: Add required constants.
+
+ * src/sfnt/woff2tags.h: Move out constants to `sfwoff2.h'.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Copy un-transformed tables to sfnt stream.
+
+ Copy un-transformed tables to the sfnt stream.
+
+ * src/sfnt/sfwoff2.c: (WRITE_SFNT_BUF): New macro.
+ (write_buf): New function. Extend memory of `dst' buffer and copy
+ bytes from `src'.
+ (compute_ULong_sum): New function. Calculate checksum of table.
+ (reconstruct_font): Change `FT_Byte* sfnt' to `FT_Byte**
+ sfnt_bytes'. This has been done because we reallocate memory to
+ `sfnt' multiple times, which may change the pointer value of `sfnt'.
+ This new pointer must be propogated back to the caller. Same reason
+ for using a double pointer in `write_buf'.
+
+ * src/sfnt/woff2tags.h (WOFF2_DEFAULT_MAX_SIZE): New macro used for
+ overflow checking.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Create stream for uncompressed buffer.
+
+ Uncompressed buffer is now an `FT_Stream'.
+
+ Perform basic checks and start iterating over tables.
+
+ * src/sfnt/sfwoff2.c (stream_close, find_table, read_num_hmetrics):
+ New functions.
+ (reconstruct_font): Modify parameters and iterate over tables.
+ (woff2_open_font): Updated.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Handle TTCs and start reconstructing font.
+
+ We `handle' TTCs by modifying the `indices' array to point to only
+ those tables that are part of the requested `face_index'.
+
+ Set and use `num_tables' in `WOFF2_TtcFont'.
+
+ * src/sfnt/sfwoff2.c (reconstruct_font): New function.
+ (woff2_open_font): Start reconstruction of font.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Get known tags from function.
+
+ Change `KnownTags' to a function (`woff2_known_tags'). This avoids
+ introducing a global constant array. This function returns the
+ specified index without *any* checks. The caller must ensure that
+ `index' is within array limits.
+
+ * src/sfnt/sfwoff2.c (woff2_open_font): Change `KnownTags[...]'
+ notation to `woff2_known_tags( ... )'.
+
+ * src/sfnt/woff2tags.c: Perform changes.
+
+ * src/sfnt/woff2tags.h: Update definitions.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Minor.
+
+ * src/sfnt/sfwoff2.c (woff2_uncompress): Add error message
+ (woff2_open_font): Free `uncompressed_buf'.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Uncompress Brotli streams and `face_index' support.
+
+ WOFF2 compressed stream is now uncompressed if Brotli is available.
+ This data is stored in a separate buffer (uncompressed_buf) because
+ it does not contain direct table data. Certain tables have
+ transformations applied to them, and they must be reconstructed
+ before we can write those tables to the SFNT stream.
+
+ `face_index' is now being passed as a parameter to
+ `woff2_open_font'.
+
+ * src/sfnt/sfobjs.c (sfnt_open_font): Add parameter
+ `face_instance_index'.
+
+ * src/sfnt/sfwoff2.c (woff2_uncompress): New function.
+ (woff2_open_font): Call `woff2_uncompress'.
+ (compute_first_table_offset): Fix return type.
+
+ * src/sfnt/sfwoff2.h (woff2_open_font): Modify declaration.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ * builds/unix/configure.raw: Change argument name to `brotli'.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ Add Brotli dependency and required checks.
+
+ Brotli is required for decompressing WOFF2 font directory streams.
+ The library is thus being added as an optional dependency for
+ FreeType.
+
+ * builds/unix/configure.raw: Add checks for `libbrotlidec'.
+ (REQUIRES_PRIVATE, LIBS_PRIVATE, LIBSSTATIC_CONFIG): Updated.
+
+ * devel/ftoption.h, include/freetype/config/ftoption.h
+ (FT_CONFIG_OPTION_USE_BROTLI): New macro.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Write SFNT Offset table.
+
+ * src/sfnt/sfwoff2.c (WRITE_USHORT, WRITE_ULONG): New macros.
+ (compare_tags): New function.
+ (woff2_open_font): Implement it.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ * src/sfnt/sfwoff2.c: #undef macros.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [woff2] Read table and collection directory.
+
+ * include/freetype/internal/wofftypes.h (WOFF2_TtcFontRec): New
+ structure.
+ (WOFF2_HeaderRec): Add more fields.
+
+ * src/sfnt/sfwoff2.c (READ_255USHORT, READ_BASE128, ROUND4): New
+ macros.
+ (Read255UShort, CollectionHeaderSize, compute_first_table_offset):
+ New functions.
+ (ReadBase128): Use `FT_READ_BYTE'.
+ (woff2_open_font): Add functionality to read table directory and
+ collection directory (if present).
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [sfnt] Include `woff2tags.c' for building.
+
+ * src/sfnt/rules.mk (SFNT_DRV_SRC): Add `woff2tags.c'.
+
+ * src/sfnt/sfnt.c: Include `woff2tags.c'.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [sfnt] Add WOFF2 constants.
+
+ Add constants required for WOFF2, and known table tags as defined in
+ the specification. See
+
+ https://www.w3.org/TR/WOFF2/#table_dir_format
+
+ for details.
+
+ * src/sfnt/woff2tags.c, src/sfnt/woff2tags.h: New files.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [sfnt] Read WOFF 2 header.
+
+ Check for WOFF2 tag, call `woff2_open_font', and implement it to read
+ header according to specification.
+
+ * include/freetype/internal/fttrace.h: Add `sfwoff2.c'.
+
+ * src/sfnt/rules.mk (SFNT_DRV_SRC): Add `sfwoff2.c'.
+
+ * src/sfnt/sfnt.c: Include `sfwoff2.c'.
+
+ * src/sfnt/sfobjs.c (sfnt_open_font): Check for `wOF2' tag and call
+ `woff2_open_font'.
+
+ * src/sfnt/sfwoff2.c, src/sfnt/sfwoff2.h: New files.
+
+2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ Add structures for WOFF2.
+
+ Add structures and macro for WOFF 2 header and table directory.
+
+ * include/freetype/internal/wofftypes.h (WOFF2_HeaderRec,
+ WOFF2_TableRec_): New structures.
+
+ * include/freetype/tttags.h (TTAG_wOF2): New macro.
+
+2019-08-26 Werner Lemberg <wl@gnu.org>
+
+ * src/psaux/cffdecode.c (cff_operator_seac): Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16470
+
+2019-08-26 Werner Lemberg <wl@gnu.org>
+
+ [type1] Fix `FT_Get_Var_Axis_Flags' (#56804).
+
+ * src/type1/t1load.c (T1_Get_MM_Var): Allocate space for axis flags.
+ Also remove redundant assignment.
+
+2019-07-24 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftbbox.c (cubic_peak): Sanitize left shift (#56586).
+
+2019-07-22 Weiyi Wu <w1w2y3@gmail.com>
+
+ * src/cid/cidload.c (cid_hex_to_binary): Fix typo (#56653).
+
+2019-07-12 Werner Lemberg <wl@gnu.org>
+
+ [sfnt, winfonts] Avoid memory leaks in case of error (#56587).
+
+ * src/sfnt/sfwoff.c (woff_open_font): Call `FT_FRAME_EXIT' in case
+ of error.
+
+ * src/winfonts/winfnt.c (fnt_face_get_dll_font): Ditto.
+
+2019-07-12 Ben Wagner <bungeman@google.com>
+
+ Properly handle phantom points for variation fonts (#56601).
+
+ * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Scale phantom
+ points if HVAR and/or VVAR is present.
+
+2019-07-04 Werner Lemberg <wl@gnu.org>
+
+ [psaux] (2/2) Handle fonts that use SEAC for ligatures (#56580).
+
+ The same as previous commit but for the old engine.
+
+ * src/psaux/t1decode.c (t1operator_seac): Implement it.
+
+2019-07-04 Chris Liddell <chris.liddell@artifex.com>
+
+ [psaux] (1/2) Handle fonts that use SEAC for ligatures (#56580).
+
+ As originally intended, a Type 1 SEAC charstring would be used for
+ an accented glyph (like `acaron' or `uumlaut'), where the advance
+ width of the SEAC glyph is the same as that of the `base' glyph
+ (like `a' or `u'). In this case it is not uncommon for the SEAC
+ glyph to not use an (H)SBW opcode of its own but to rely on the
+ value from the base glyph.
+
+ However, out-of-spec fonts also use SEAC glyphs for ligatures (like
+ `oe' or `fi'), and in those cases the overall advance width is
+ greater than that of the `base' glyph. For this reason we have to
+ allow that the SEAC glyph can have an (H)SBW value of its own, and
+ if it has, retain this value, rather than the one from the base
+ glyph.
+
+ * src/psaux/psintrp.c (cf2_interpT2CharString) <cf2_escSEAC>:
+ Implement it.
+
+2019-07-01 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.10.1 released.
+ ==========================
+
+
+ Tag sources with `VER-2-10-1'.
+
+ * docs/VERSION.TXT: Add entry for version 2.10.1.
+
+ * README, Jamfile (RefDoc), src/base/ftver.rc,
+ builds/windows/vc2010/freetype.vcxproj,
+ builds/windows/vc2010/index.html,
+ builds/windows/visualc/freetype.dsp,
+ builds/windows/visualc/freetype.vcproj,
+ builds/windows/visualc/index.html,
+ builds/windows/visualce/freetype.dsp,
+ builds/windows/visualce/freetype.vcproj,
+ builds/windows/visualce/index.html,
+ builds/wince/vc2005-ce/freetype.vcproj,
+ builds/wince/vc2005-ce/index.html,
+ builds/wince/vc2008-ce/freetype.vcproj,
+ builds/wince/vc2008-ce/index.html: s/2.10.0/2.10.1/, s/2100/2101/.
+
+ * include/freetype/freetype.h (FREETYPE_PATCH): Set to 1.
+
+ * builds/unix/configure.raw (version_info): Set to 23:1:17.
+ * CMakeLists.txt (VERSION_PATCH): Set to 1.
+
+ * include/freetype/fterrors.h (FT_Error_String): Fix C++ compilation.
+
+2019-06-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/bdf/bdfdrivr.c (bdf_cmap_char_{index,next}): Fix inequality.
+
+ Reported by Armin Hasitzka.
+
+2019-06-16 Werner Lemberg <wl@gnu.org>
+
+ * src/tools/apinames.c: Formatting, minor edits.
+
+2019-06-16 Werner Lemberg <wl@gnu.org>
+
+ [autofit] Disable hinting if no blue zones are available (#56450).
+
+ * src/autofit/afglobal.c (af_face_global_get_metrics): Start again
+ (with dummy hinter module) if no blue zones are present.
+
+ * src/autofit/aflatin.c (af_latin_metrics_init_blues): Change
+ signature to return error code.
+ If no blue zones are found, update `glyph_styles' array to hold
+ AF_STYLE_NONE_DFLT instead of the current style.
+ (af_latin_metrics_init): Return internal error code if no blue zones
+ are found.
+
+2019-06-16 Werner Lemberg <wl@gnu.org>
+
+ Towards better VMS support.
+
+ More to come.
+
+ * builds/vms/LIBS.OPT_IA64, builds/vms/_LINK.OPT_IA64,
+ builds/vms/vmslib.dat: New files provided by Jouk Jansen
+ <joukj@hrem.nano.tudelft.nl>.
+
+ * builds/vms/ftconfig.h: Update, also from Jouk.
+
+2019-06-13 Werner Lemberg <wl@gnu.org>
+
+ * src/autofit/aflatin.c (af_latin_metrics_init_widths): Minor.
+
+2019-06-13 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Restore the span buffering for direct mode only.
+
+ The buffer size FT_MAX_GRAY_SPANS is set to 10 spans, which should be
+ enough to cover the entire scanline for simple glyphs in most cases:
+ each slightly slanted edge needs up to two spans, plus a filling span
+ in-between. This is not new, we used to do it before cb4388783cecc.
+
+ * src/smooth/ftgrays.c (gray_TWorker): Add `spans' and `num_spans'.
+ (gray_hline, gray_sweep): Implement the span buffering.
+ (gray_raster_render): Use negative `num_spans' to avoid the direct
+ mode.
+
+2019-06-12 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * include/freetype/ftmodapi.h (FT_DebugHook_Func): Return error.
+
+ Fix a warning by adding a return value as in `TT_RunIns',
+ which should not be a compatibility issue.
+
+2019-06-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttobjs.c (tt_check_trickyness_family): Add `const'.
+
+2019-06-11 Moazin Khatti <moazinkhatri@gmail.com>
+
+ [gzip] Add support for `gzip' encoded header.
+
+ * src/gzip/ftgzip.c (FT_Gzip_Uncompress): Modify the the call to
+ `inflateInit2' to enable support for `gzip' encoded headers.
+
+2019-06-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [type1,type42] Use `const' for string literals.
+
+ * include/freetype/internal/psaux.h (PS_Table_FuncsRec): Updated.
+ * include/freetype/internal/t1types.h (T1_EncodingRec): Updated.
+ * src/psaux/psobjs.[ch] (ps_table_add): Updated.
+ * src/type1/t1load.c (T1_Open_Face, parse_encoding): Updated.
+ * src/type42/t42objs.c (T42_Open_Face): Updated.
+ * src/type42/t42parse.c (t42_parse_encoding): Updated.
+
+ * src/cff/cffobjs.c (cff_face_init): Minor.
+
+2019-06-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf,pcf] Use `const' for string literals.
+
+ * src/bdf/bdf.h (bdf_property_t): Updated `name'.
+ * src/bdf/bdflib.c (_bdf_list_split,bdf_create_property,
+ _bdf_add_property,_bdf_ato*): Updated.
+ * src/bdf/bdfdrivr.c (bdf_interpret_style): Updated.
+ * src/pcf/pcfread.c (pcf_intrpret_style): Ditto.
+
+2019-06-07 Philip Race <philip.race@oracle.com>
+
+ * src/base/ftinit.c (FT_Set_Default_Properties): Fix crash.
+
+ Terminate loop at end of environment.
+
+2019-05-31 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Solidify VC2005 builds.
+
+ * include/freetype/internal/ftcalc.h (FT_MSB) [_MSC_VER]: Explicitly
+ declare `_BitScanReverse' intrinsic.
+ * builds/windows/visualc/freetype.vcproj [Debug]: Disable intrinsics.
+
+2019-05-30 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [sfnt] Separate WOFF sources and headers.
+
+ Move WOFF sources and headers to separate files.
+
+ * include/freetype/internal/wofftypes.h, src/sfnt/sfwoff.c,
+ src/sfnt/sfwoff.h: New files.
+
+ * include/freetype/internal/fttrace.h: Register `sfwoff.c'.
+
+ * include/freetype/internal/internal.h: Define
+ FT_INTERNAL_WOFF_TYPES_H.
+
+ * include/freetype/internal/sfnt.h: Include FT_INTERNAL_WOFF_TYPES_H.
+
+ * include/freetype/internal/tttypes.h: Move out WOFF structures.
+
+ * src/sfnt/rules.mk: Add `sfwoff.c'.
+
+ * src/sfnt/sfnt.c: Include `sfwoff.c'.
+
+ * src/sfnt/sfobjs.c: Include `sfwoff.h', move out WOFF sources.
+
+2019-05-30 Werner Lemberg <wl@gnu.org>
+
+ [base] Fix `make multi'.
+
+ Reported by Nikhil.
+
+ * src/base/fterrors.c: Include FT_INTERNAL_DEBUG_H.
+
+2019-05-29 Ben Wagner <bungeman@google.com>
+
+ [truetype] Fix copy-and-paste error (#56409).
+
+ * src/truetype/ttgload.c (load_truetype_glyph): Use correct indices
+ into `unrounded' array for phantom points.
+
+2019-05-29 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Fix 32bit builds (#56404).
+
+ Patch suggested by Ben Wagner <bungeman@google.com>.
+
+ * src/truetype/ttgxvar.c (FT_fixedToInt, FT_fixedToFdot6): Remove
+ harmful cast to unsigned type.
+
+2019-05-26 Ben Wagner <bungeman@google.com>
+
+ * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Improve accuracy.
+
+2019-05-23 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Draw glyphs without deltas in variation font (#56374).
+
+ * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Always fill
+ `unrounded' array.
+
+2019-05-21 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttinterp.c (opcode_name): Improve mnemonics.
+
+2019-05-16 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Actually scale varied CVT values.
+
+ Up to now, only the unscaled CVT values were varied; in other words,
+ the `CVAR' data was never used for bytecode hinting.
+
+ * src/truetype/ttgxvar.c (tt_cvt_ready_iterator): New auxiliary
+ function.
+ (tt_face_vary_cvt): Use it to trigger rescaling of CVT values.
+
+2019-05-16 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Use 26.6 format for storing unscaled CVT values.
+
+ If `CVAR' data is applied to variation fonts, fractional values are
+ possible.
+
+ * include/freetype/internal/tttypes.h (TT_FaceRec): Change type of
+ `cvt' from `FT_Short' to `FT_Int32'.
+
+ * src/truetype/ttgxvar.c (FT_fdot6ToFixed): New macro.
+ (tt_face_vary_cvt): Use it to update code to 26.6 format.
+
+ * src/truetype/ttobjs.c (tt_size_run_prep): Update code to 26.6
+ format.
+
+ * src/truetype/ttpload.c (tt_face_load_cvt): Stora data in 26.6
+ format.
+
+2019-05-16 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgload.c (load_truetype_glyph): Init `unrounded'.
+
+ This fixes linear advance width values for spacing glyphs. Bug
+ introduced 2019-05-09.
+
+2019-05-16 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Avoid code duplication.
+
+ * src/truetype/ttobjs.c (tt_size_run_prep): Scale CVT values in this
+ function.
+ (tt_size_ready_bytecode): Updated.
+ * src/truetype/ttgload.c (tt_loader_init): Updated.
+
+2019-05-13 Jouk Jansen <joukj@hrem.nano.tudelft.nl>
+
+ * vms_make.com: Updated. Handle `bzip2' directory, too.
+
+2019-05-13 Werner Lemberg <wl@gnu.org>
+
+ * src/psaux/psfont.c (cf2_font_setup): Fix compiler warning.
+
+2019-05-12 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Doh. Fix last commit to make it work.
+
+ Very embarassing :-)
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14701
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14705
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14710
+
+ * src/truetype/ttgload.c (IS_DEFAULT_INSTANCE): Move up and add
+ argument; update all callers.
+ (TT_Process_Simple_Glyph): Use it. The `unrounded' array is active
+ for variation fonts only, thus also enclose related code with
+ `#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT ... #endif' where
+ necessary.
+ Revert commit a113e5d from 2019-05-09, and don't use `extra_points2'
+ but allocate a temporary array.
+ Speed up the scaling of the `unrounded' array.
+
+ * src/truetype/ttgxvar.c (FT_fixedToInt, FT_FixedToFdot6): Fix type
+ conversions and rounding. The unsigned type must have more or equal
+ bits to the signed type.
+
+2019-05-09 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Increase precision of font variation (#54371).
+
+ This patch makes FreeType use font units in 26.6 format internally
+ instead of integers.
+
+ * src/truetype/ttgxvar.c (FT_fixedToFdot6): New macro.
+ (TT_Vary_Apply_Glyph_Deltas): Add argument to output unrounded font
+ coordinates.
+ * src/truetype/ttgxvar.h: Updated.
+
+ * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Use
+ `extra_points2' array to temporarily hold unrounded point
+ coordinates; use them to compute scaled coordinates and linear
+ advance width and height.
+ (load_truetype_code): Adjust similarly.
+
+2019-05-09 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Minor.
+
+2019-05-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Faster fractions.
+
+ * src/smooth/ftgrays.c (SUBPIXELS): Replace with...
+ (FRACT): A fractional coordinate macro to use in...
+ (gray_render_line, gray_render_scanline): ... here.
+
+2019-05-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/raster/ftraster.c (Draw_Sweep): Unbreak.
+
+2019-05-05 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/raster/ftraster.c: Clean-ups.
+
+2019-05-05 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgxvar.c: More use of `FT_fdot14ToFixed'.
+
+2019-05-04 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/smooth/ftgrays.c (gray_render_line): Small shortcut.
+
+2019-05-04 Werner Lemberg <wl@gnu.org>
+
+ Various clang 8.0 static analyzer fixes.
+
+ Reported by Sender Ghost <lightside@gmx.com>.
+
+ * src/autofit/afcjk.c (af_cjk_hints_compute_edges): Catch a corner
+ case where `edge->first' could be NULL.
+
+ * src/pfr/pfrobjs.c (pfr_slot_load): Remove unnecessary test of
+ `size'.
+
+ * src/raster/ftraster.c (Draw_Sweep): Catch a corner case where
+ `draw_right' might be NULL.
+
+ * src/sfnt/ttmtx.c (tt_face_get_metrics): Fix limit test for
+ `aadvance'.
+ Ensure `abearing' always hold a meaningful result.
+
+ * src/truetype/ttgload.c (load_truetype_glyph): Ensure `subglyph' is
+ not NULL before accessing it.
+ * src/truetype/ttgxvar.c (TT_Set_Named_Instance): Remove unnecessary
+ test of `namedstyle'.
+
+ * src/type42/t42parse.c (t42_parser_done): Ensure
+ `parser->root.funcs.done' is not NULL before accessing it.
+
+2019-05-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Miscellaneous macro updates.
+
+ * src/base/ftoutln.c (SCALED): Updated.
+ * src/smooth/ftgrays.c (SCALED): Ditto.
+ (FLOOR, ROUND, CEILING): Removed.
+ * src/psaux/psfixed.h (cf2_fracToFixed): Updated.
+
+2019-05-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Tweak LCD filtering.
+
+ * src/base/ftlcdfil.c (ft_lcd_filter_fir, _ft_lcd_filter_legacy):
+ Choose direction from bitmap's pixel_mode.
+ * include/freetype/internal/ftobjs.c (FT_Bitmap_LcdFilterFunc):
+ Updated.
+ * src/smooth/ftsmooth.c (ft_smooth_render_generic): Updated.
+
+2019-05-02 Werner Lemberg <wl@gnu.org>
+
+ * vms_make.com: Updated (#56253).
+
+ Remove no longer existing directories (`autohint', `otlayout').
+ Update used base extensions.
+ Activate `autofit' module.
+ Add `gxvalid' module.
+ Update copyright notices.
+
+2019-04-29 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Simplify cubic Bézier flattening.
+
+ The previous implementation is correct but it is too complex.
+ The revised algorithm is based on the fact that each split moves
+ the control points closer to the trisection points on the chord.
+ The corresponding distances are good surrogates for the curve
+ deviation from the straight line.
+
+ This cubic flattening algorithm is somewhat similar to the conic
+ algorithm based the distance from the control point to the middle of
+ the chord. The cubic distances, however, decrease less predictably
+ but are easy enough to calculate on each step.
+
+ The new algorithm produces slightly larger number of splits, which is
+ compensated by its simplicity. The overall rendering performance is
+ improved by 1-2%. The larger number of splits does not necessarily
+ result in higher quality, which stays comparable.
+
+ * src/smooth/ftgrays.c (gray_render_cubic): Replace the split
+ condition.
+
+2019-04-26 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Bithacks and cosmetics.
+
+ * src/smooth/ftgrays.c (gray_record_cell, gray_set_cell, gray_hline,
+ gray_render_conic, gray_convert_glyph_inner): Updated.
+
+2019-04-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Optimize Bézier bisections.
+
+ This change makes bisections faster by 20-30%. When inlined into
+ `gray_render_cubic', this makes the function faster by 10% and is
+ noticeable in the overall rendering performance.
+
+ * src/raster/ftraster.c (Split_Conic, Split_Cubic): Use shifts and
+ refactor.
+ * src/smooth/ftgrays.c (gray_split_conic, gray_split_cubic): Ditto.
+ * src/base/ftstroke.c (ft_conic_split, ft_cubic_split): Ditto.
+ * src/base/ftbbox.c (cubic_peak): Use shifts.
+
+2019-04-23 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/ttcmap.c (tt_cmap12_next): Remove dead code.
+
+ Found by clang 8.0's static analyzer and reported by Sender Ghost
+ <lightside@gmx.com>.
+
+2019-04-23 Werner Lemberg <wl@gnu.org>
+
+ [base] Fix thinko in previous commit.
+
+ * src/base/ftbitmap.c (FT_Bitmap_Blend): Check final width, not
+ target pitch.
+
+ Problem reported by Sender Ghost <lightside@gmx.com>.
+
+2019-04-22 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftbitmap.c (FT_Bitmap_Blend): Check target pitch.
+
+ Problem reported by Sender Ghost <lightside@gmx.com>.
+
+2019-04-22 Werner Lemberg <wl@gnu.org>
+
+ Fix return value of `FT_Set_Named_Instance' (#56186).
+
+ * src/truetype/ttgxvar.c (TT_Set_Named_Instance): Correctly handle
+ internal return value -1 of `TT_Set_Var_Design'.
+
+2019-04-18 Werner Lemberg <wl@gnu.org>
+
+ [pcf] Fix handling of undefined glyph (#56067).
+
+ This commit fixes the changes from 2018-07-21, which broke charmap
+ iteration. We now add the default character as a new glyph with
+ index 0, thus increasing the number of glyphs by one (as before).
+
+ * src/pcf/pcfread.c (pcf_get_metrics): Adjust to new artificial
+ glyph with index 0.
+ Limit number of elements to 65534.
+ (pcf_get_bitmaps): Ditto.
+ Unify two loops into one; this avoids allocation of an intermediate
+ array.
+ (pcf_get_encodings): Don't flip indices but copy glyph metrics of
+ default character to index 0.
+ Also handle invalid default character.
+
+ * docs/CHANGES: Updated.
+
+2019-04-15 Minmin Gong <gongminmin@msn.com>
+
+ * CMakeLists.txt: Avoid rewriting of unchanged configuration files.
+
+ Reported as
+
+ https://savannah.nongnu.org/patch/index.php?9755
+
+2019-04-15 JDG <JonathanG@iQmetrix.com>
+
+ * src/tools/apinames.c (main): Fix error message.
+
+ Reported as
+
+ https://savannah.nongnu.org/patch/?9796
+
+2019-04-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Fix segfault in direct mode (#56092).
+
+ * src/base/ftoutln.c (FT_Outline_Render): Set missing clip_box for
+ direct mode.
+ * src/smooth/ftgrays.c (gray_raster_render): Use it.
+
+2019-04-06 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/ttcmap.c (tt_get_glyph_name): Pacify compiler (#56061).
+
+ This is for Visual Studio 2019 on ARM.
+
+2019-04-06 Werner Lemberg <wl@gnu.org>
+
+ For distribution, replace `.tar.bz2' with `.tar.xz' bundles.
+
+ * builds/toplevel.mk (build): Do it.
+
+ * README, docs/CHANGES, docs/release: Updated.
+
+2019-04-06 Antony Lee <anntzer.lee@gmail.com>
+
+ Make `glyph_name' parameter to `FT_Get_Name_Index' a `const'.
+
+ * include/freetype/freetype.h (FT_Get_Name_Index),
+ include/freetype/internal/ftobjs.h (FT_Face_GetGlyphNameIndexFunc),
+ include/freetype/internal/services/svgldict.h
+ (FT_GlyphDict_NameIndexFunc), src/base/ftobjs.c (FT_Get_Name_Index),
+ src/cff/cffdrivr.c (cff_get_name_index), src/sfnt/sfdriver.c
+ (sfnt_get_name_index), src/type1/t1driver.c (t1_get_name_index),
+ src/type42/t42drivr.c (t42_get_name_index): Add `const' to second
+ argument.
+
+2019-03-31 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [cff] Fix boundary checks.
+
+ 642bc7590c701c8cd35a9f60fa899cfa518b17ff introduced dynamically
+ allocated memory when parsing CFF files with the "old" engine. Bounds
+ checks have never been updated, however, leading to pointless
+ comparisons of pointers in some cases. This commit presents a
+ solution for bounds checks in the CFF module with an extended logic
+ for the "old" engine while staying as concise as possible for the
+ "new" one.
+
+ * src/cff/cffparse.h: Introduce the struct `CFF_T2_StringRec' and
+ the additional field `t2_strings' within `CFF_ParserRec'.
+
+ * src/cff/cffparse.c (cff_parser_within_limits): Move all boundary
+ checks into this new function and update the rest of `cffparse.c' to
+ use it.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12137
+
+2019-03-20 Werner Lemberg <wl@gnu.org>
+
+ [autofit] Fix Mongolian blue zone characters.
+
+ * src/autofit/afblue.dat: Use U+200D (ZERO-WIDTH JOINER) characters
+ to get medial forms for some Mongolian characters.
+ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+2019-03-19 Werner Lemberg <wl@gnu.org>
+
+ [autofit] Add support for Mongolian script.
+
+ As a de-facto standard, layouts using this script are constructed
+ horizontally line by line, then the lines are rotated clockwise for
+ vertical display.
+
+ * src/autofit/afblue.dat: Add blue zone data for Mongolian.
+ * src/autofit/afblue.c, src/autofit/afblue.h: Regenerated.
+
+ * src/autofit/afscript.h: Add Mongolian standard characters.
+
+ * src/autofit/afranges.c, src/autofit/afstyles.h: Add Mongolian
+ data.
+
+2019-03-15 Werner Lemberg <wl@gnu.org>
+
+ * Version 2.10.0 released.
+ ==========================
+
+
+ Tag sources with `VER-2-10-0'.
+
+ * docs/VERSION.TXT: Add entry for version 2.10.0.
+ * docs/CHANGES: Updated.
+
+ * README, Jamfile (RefDoc), src/base/ftver.rc,
+ builds/windows/vc2010/freetype.vcxproj,
+ builds/windows/vc2010/index.html,
+ builds/windows/visualc/freetype.dsp,
+ builds/windows/visualc/freetype.vcproj,
+ builds/windows/visualc/index.html,
+ builds/windows/visualce/freetype.dsp,
+ builds/windows/visualce/freetype.vcproj,
+ builds/windows/visualce/index.html,
+ builds/wince/vc2005-ce/freetype.vcproj,
+ builds/wince/vc2005-ce/index.html,
+ builds/wince/vc2008-ce/freetype.vcproj,
+ builds/wince/vc2008-ce/index.html: s/2.9.1/2.10.0/, s/291/2100/.
+
+ * include/freetype/freetype.h (FREETYPE_MINOR): Set to 10.
+ (FREETYPE_PATCH): Set to 0.
+
+ * builds/unix/configure.raw (version_info): Set to 23:0:17.
+ * CMakeLists.txt (VERSION_MINOR): Set to 10.
+ (VERSION_PATCH): Set to 0.
+
+ * builds/toplevel.mk (version, winversion): Since the minor version
+ number has two digits now, never omit the patch number. We would
+ get ambiguous zip file names otherwise.
+ (dist): Remove remnants of `docmaker' tool.
+ (do-dist): Remove unused intermediate files.
+
+ * src/cff/cffparse.c (destrict_c2s_item): Guard function with
+ CFF_CONFIG_OPTION_OLD_ENGINE macro.
+
+2019-03-07 Andrei Alexeyev <0x416b617269@gmail.com>
+ Werner Lemberg <wl@gnu.org>
+
+ Fix invalid function pointer casts.
+
+ This change should allow Freetype to work on WASM/Emscripten without
+ needing `-s EMULATE_FUNCTION_POINTER_CASTS=1'.
+
+ * src/autofit/afdummy.c (af_dummy_hints_apply): Fix signature.
+
+ * src/cid/cidload.c (cid_parse_font_matrix, parse_fd_array,
+ parse_expansion_factor, parse_font_name): Return `void', not
+ `FT_Error'.
+
+ * include/freetype/internal/ftobjs.h (FT_CMap_CharVarIsDefaultFunc):
+ Fix signature.
+
+2019-03-05 Werner Lemberg <wl@gnu.org>
+
+ [base] Handle numeric overflow (#55827).
+
+ * src/base/ftglyph.c (FT_Glyph_Get_CBox): Use `FT_PIX_CEIL_LONG'.
+
+2019-03-05 Sebastian Rasmussen <sebras@gmail.com>
+
+ [psaux] Fix use of uninitialized memory (#55832).
+
+ * src/psaux/psintrp.c (cf2_interpT2CharString): The call to
+ `cf2_arrstack_setCount' may fail because the allocator ran out of
+ memory. When this happens the stack is still written to before the
+ error condition is checked. This means that FreeType writes outside
+ of allocated memory. This commit moves the error check prior to the
+ stack assignment, hence the function now properly returns with an
+ error condition.
+
+2019-02-23 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftbitmap.c (FT_Bitmap_Blend): No fractional offsets.
+
+ The function only provided a framework without an actual
+ implementation, which this commit removes.
+
+2019-02-23 Werner Lemberg <wl@gnu.org>
+
+ * src/tools/update-copyright-year: Insert `(C)'.
+
+2019-02-21 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [truetype] Mask numeric overflows.
+
+ * src/truetype/ttinterp.c (Move_CVT, Move_CVT_Stretched, Ins_MIRP):
+ Mask numeric overflows.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11681
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11734
+
+2019-02-21 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [psaux] Mask numeric overflow.
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings): Mask numeric
+ overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=13041
+
+2019-02-16 Wink Saville <wink@saville.com>
+
+ * src/autofit/afwarp.h (af_warper_compute): Fix declaration.
+
+2019-02-02 Nikolaus Waxweiler <madigens@gmail.com>
+
+ [truetype] Apply MVAR hasc, hdsc and hlgp metrics to current FT_Face metrics.
+
+ Instead of setting typo or win metrics as the new `FT_Face' metrics
+ indiscriminately, apply only typo deltas to the currently active
+ `FT_Face' metrics. This prevents line height differences when the
+ default outlines were used as the regular face and instances for
+ everything else, for example.
+
+ * src/truetype/ttgxvar.c (tt_apply_mvar): Implement.
+
+2019-02-02 Nikolaus Waxweiler <madigens@gmail.com>
+
+ [sfnt] Use typo metrics if OS/2 fsSelection USE_TYPO_METRICS bit is set.
+
+ If the `OS/2' table exists and `fsSelection' bit 7
+ (USE_TYPO_METRICS) is set, use the `sTypo*' set of values to compute
+ the `FT_Face's ascender, descender, and height. Otherwise, fall
+ back to old behavior.
+
+ * src/sfnt/sfobjs.c (sfnt_load_face): Implement.
+
+2019-01-18 John Tytgat <John.Tytgat@esko.com>
+
+ [sfnt] Handle TT fonts having two PostScript font names (#55471).
+
+ * src/sfnt/sfdriver.c (sfnt_get_name_id): Prefer English over any
+ other language found for PostScript font names.
+
+2019-01-08 Chris Liddell <chris.liddell@artifex.com>
+
+ [psaux] Fix closepath (#55414).
+
+ All of the Type 1 path building is done with code common to the
+ revised CFF engine, with the exception of closepath, which was still
+ calling ps_builder_close_contour(), thus previously cached segments
+ were not always written to the path, and glyph corruption, or even
+ invalid outlines were possible.
+
+ * src/psauc/psinterp.c (cf2_interpT2CharString) <cf2_cmdCLOSEPATH>:
+ Switch to calling `cf2_glyphpath_closeOpenPath'.
+
+2018-12-29 Werner Lemberg <wl@gnu.org>
+
+ * src/autofit/aflatin2.c: Some fixes from `aflatin.c' (#55310).
+
+2018-12-25 Werner Lemberg <wl@gnu.org>
+
+ * src/psaux/cffdecode.c (cff_operaor_seac): Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11915
+
+2018-12-12 Werner Lemberg <wl@gnu.org>
+
+ [gxvalid] Fix compiler warnings.
+
+ * src/gxvalid/gxvjust.c (gxv_just_check_max_gid),
+ src/gxvalid/gxvmort.c (gxv_mort_coverage_validate): Use `FT_UNUSED'.
+
+2018-12-11 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgload.c (TT_Hint_Glyph): Remove useless test.
+
+ `control_len' only gets its value from `n_ins' (and vice versa),
+ which is always read as `unsigned short' and thus can't be larger
+ than 0xFFFF.
+
+2018-12-04 Werner Lemberg <wl@gnu.org>
+
+ [bdf] Ignore data after `ENDFONT'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10798
+
+ * src/bdf/bdflib.c (_bdf_parse_end): New function.
+ (_bdf_parse_glyphs): Switch to `_bdf_parse_end' after `ENDFONT' has
+ been encountered.
+
+2018-12-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/windows/visualc/freetype.dsp: Dust off.
+
+2018-11-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/windows/vc2010/freetype.vcxproj: Simplify.
+
+2018-11-27 Chris Liddell <chris.liddell@artifex.com>
+
+ [type1,cff] Add FT_{Set,Get}_MM_WeightVector API calls.
+
+ For multiple master fonts, common usage (in Postscript) is to modify
+ the WeightVector of an existing font instance, this addition
+ supports that use.
+
+ * include/freetype/ftmm.h, src/base/ftmm.c (FT_Set_MM_WeightVector,
+ FT_Get_MM_WeightVector): New API functions.
+
+ * include/freetype/internalservices/svmm.h
+ (FT_Set_MM_WeightVector_Func, FT_Get_MM_WeightVector_Func): New
+ function types.
+ (MultiMasters): Add `set_mm_weightvector' and `get_mm_weightvector'
+ members.
+ (FT_DEFINE_SERVICE_MULTIMASTERSREC): Updated.
+
+ * src/cffcffdrivr.c (cff_set_mm_weightvector,
+ cff_get_mm_weightvector): New functions.
+ (cff_service_multi_masters): Register them.
+
+ * src/truetype/ttdriver.c (tt_service_gx_multi_masters): Updated.
+ This driver doesn't use the new interface.
+
+ * src/type1/t1load.c (T1_Set_MM_WeightVector,
+ T1_Get_MM_WeightVector): New functions.
+ * src/type1/t1driver.c (t1_service_multi_masters): Register them.
+ * src/type1/t1load.h: Updated.
+
+2018-11-27 Ben Wagner <bungeman@google.com>
+
+ [cff] Fix compiler warning (#55105).
+
+ * src/cff/cffparse.c (cff_parser_run): Guard label only used if
+ CFF_CONFIG_OPTION_OLD_ENGINE is active.
+
+2018-11-27 Ben Wagner <bungeman@google.com>
+
+ [truetype] Fix numeric overflow (#55103).
+
+ * src/truetype/ttgload.c (compute_glyph_metrics): Use `SUB_LONG'.
+
+2018-11-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [builds] Belated DLL support with vc2002-vc2008.
+
+ The solution and project files should be automatically upgraded for
+ the approriate Visual C++ version.
+
+ * builds/windows/visualc/freetype.{sln,vcproj}: Major upgrades.
+ * builds/windows/visualc/index.html: Document the change.
+ * builds/windows/vc2005, builds/windows/vc2008: Removed as redundant.
+
+2018-11-22 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ * src/cff/cffparse.c: Please the compiler.
+
+2018-11-22 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [cff] Fix memory overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9869
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10869
+
+ * src/cff/cffparse.c (destruct_t2s_item, cff_parser_run): Store
+ evaluated T2 charstrings in separately allocated memory.
+
+2018-11-18 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/windows/{visualc,vc2005,vc2008}/freetype.vcproj: Fix it.
+
+2018-11-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Placeholder only for library-enabled LCD filtering.
+
+ * src/smooth/ftsmooth.c (ft_smooth_init): Add disabled
+ `FT_Library_SetLcdFilter' call.
+
+2018-11-09 Young Xiao <yangx92@hotmail.com>
+
+ [psaux] Add safety guard (#54985).
+
+ * src/psaux/psobjs.c (cff_builder_close_contour): Do it.
+
+2018-11-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * builds/unix/configure.raw: Require `windows.h' for windres.
+
+2018-11-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [ftstroke] Fix unpredictable failures (#54986).
+
+ * src/base/ftstroke.c (ft_sroke_border_lineto): Fix lineto check.
+
+2018-11-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [ftstroke] Fix unpredictable failures (#54976).
+
+ * src/base/ftstroke.c (ft_sroke_border_close): Set the start tags.
+
+2018-11-07 Ben Wagner <bungeman@google.com>
+
+ [truetype] Fix VF check from 2018-09-12 (#54973).
+
+ * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Use correct
+ offsets for estimates.
+
+2018-11-06 Werner Lemberg <wl@gnu.org>
+
+ [pshinter] Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11242
+
+ * src/pshinter/pshrec.c (ps_dimension_add_t1stem): Implement it.
+
+2018-11-06 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix timeout in old CFF engine.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11260
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings)
+ <cff_op_sqrt> [CFF_CONFIG_OPTION_OLD_ENGINE]: Fix potential endless
+ loop.
+
+2018-11-04 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttgxvar.c: Use enum definitions.
+
+2018-11-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttgxvar.c (ft_var_apply_tuple): Adjust condition.
+
+2018-11-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttgxvar.c (ft_var_apply_tuple): Tracing tweaks.
+
+2018-11-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Revert due to specs: [truetype] Speed up variation IUP.
+
+2018-11-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttgxvar.c (ft_var_get_item_delta): Fixed logic.
+
+ Reported and tested by Behdad.
+
+2018-11-02 Shailesh Mistry <shailesh.mistry@hotmail.co.uk>
+
+ [autofit] Prevent SEGV.
+
+ See
+
+ https://bugs.ghostscript.com/show_bug.cgi?id=697545
+
+ for more details on how the bug was found.
+
+ * src/autofit/afloader.c (af_loader_load_glyph): Propagate error
+ code.
+
+2018-10-31 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [truetype] Speed up variation IUP.
+
+ * src/truetype/ttgxvar.c (tt_delta_interpolate): Separate trivial
+ snapping to the same position from true interpolation.
+
+2018-10-31 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/type1/t1load.c (t1_set_mm_blend): Optimized.
+
+2018-10-31 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/truetype/ttgxvar.c (ft_var_get_item_delta): Optimized.
+
+2018-10-29 Werner Lemberg <wl@gnu.org>
+
+ [base] Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11080
+
+ * src/base/ftoutln.c (FT_Outline_Get_Orientation): Use `MUL_LONG'.
+
+2018-10-29 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10988
+
+ * src/cff/cffparse.c (cff_parser_run)
+ [CFF_CONFIG_OPTION_OLD_ENGINE]: Use `NEG_LONG'.
+
+2018-10-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sfnt] Make `head' timestamps unsigned.
+
+ It's been more than 2^31 seconds since 1904.
+
+ * include/freetype/tttables.h (TT_Header): Change field types.
+ * src/sfnt/ttload.c (tt_face_load_generic_header): Updated.
+
+2018-10-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Revert: Align FreeType with standard C memory management.
+
+2018-10-27 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix numeric overflow.
+
+ Triggered by
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11157
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings) <cff_op_blend>
+ [CFF_CONFIG_OPTION_OLD_ENGINE]: Fix integer overflow.
+
+2018-10-20 Werner Lemberg <wl@gnu.org>
+
+ Avoid endless loop while tracing (#54858).
+
+ * src/type1/t1load.c (parse_buildchar): Guard tracing stuff with
+ FT_DEBUG_LEVEL_TRACE.
+
+2018-10-17 David Demelier <markand@malikania.fr>
+
+ * CMakeLists.txt: Specify `RUNTIME DESTINATION'.
+
+ This is needed for DLL builds.
+
+2018-10-07 Werner Lemberg <wl@gnu.org>
+
+ A missing Unicode cmap is not a fatal error.
+
+ This is a follow-up to the previous commit.
+
+ * src/cff/cffobjs.c (cff_face_init), src/sfnt/sfobjs.c
+ (sfnt_load_face), src/type1/t1objs.c (T1_Face_Init),
+ src/type42/t42objs.c (T42_Face_Init): Implement it.
+
+2018-10-07 Werner Lemberg <wl@gnu.org>
+
+ Fix handling of FT_CONFIG_OPTION_ADOBE_GLYPH_LIST (#54794).
+
+ * src/cff/cffcmap.c (cff_cmap_unicode_init), src/psaux/t1cmap.c
+ (t1_cmap_unicode_init), src/sfnt/ttcmap.c (tt_cmap_unicode_init):
+ Check `unicodes_init' field.
+
+2018-10-03 Werner Lemberg <wl@gnu.org>
+
+ [ftgrays] Fix typo in stand-alone mode (#54771).
+
+ * src/smooth/ftgrays.c (FT_THROW) [STANDALONE_ &&
+ FT_DEBUG_LEVEL_TRACE]: Fix call to `FT_ERR_CAT'.
+
+2018-10-02 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix segfault.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10768
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings)
+ <cff_op_callothersubr> [CFF_CONFIG_OPTION_OLD_ENGINE]: Check
+ argument.
+
+2018-10-02 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10740
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings) <cff_op_roll>
+ [CFF_CONFIG_OPTION_OLD_ENGINE]: Use NEG_INT.
+
+2018-10-02 Werner Lemberg <wl@gnu.org>
+
+ [pshinter] Handle numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10550
+
+ * src/pshinter/pshglob.c (psh_blues_snap_stem): Mask numeric
+ overflow.
+
+2018-09-27 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Align FreeType with standard C memory management.
+
+ * include/freetype/ftsystem.h: Include FT_TYPES_H.
+ (*FT_Alloc_Func, *FT_Realloc_Func): Use size_t for the size arguments.
+ * src/raster/ftmisc.h: Ditto.
+
+ * builds/amiga/src/base/ftsystem.c, builds/unix/ftsystem.c,
+ * builds/vms/ftsystem.c, src/base/ftsystem.c (ft_alloc, ft_realloc):
+ Use size_t for the size arguments.
+
+ * src/base/ftdbgmem.c (ft_mem_debug_alloc, ft_mem_debug_realloc): Use
+ FT_Offset, aka size_t, for the size arguments.
+
+2018-09-25 Werner Lemberg <wl@gnu.org>
+
+ Fix handling of `FT_Bool'.
+
+ Before this commit we had code like
+
+ (FT_Bool)( globals->glyph_styles[gindex] & 0x8000)
+
+ Since `FT_Bool' is defined to be an `unsigned char', the code
+ evaluated to something like
+
+ (unsigned char)( 0x8532 & 0x8000)
+
+ which in turn expanded to
+
+ (unsigned char)( 0x8000)
+
+ and finally yielded 0x00 – i.e., false – not as expected.
+
+ Problem reported and analyzed by Tony Smith <tony.smith@macro4.com>.
+
+ * include/freetype/fttypes.h (FT_BOOL): Add a comparison against
+ zero so that we always have a Boolean expression.
+
+ */*: Replace castings to `FT_Bool' with calls to `FT_BOOL' where
+ possible.
+
+2018-09-23 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf] Speed up charmap access.
+
+ This makes FT_Get_Char_Index and FT_Get_Next_Char 4-5 times faster.
+
+ * src/bdf/bdfdrivr.c (bdf_cmap_char_{index,next}): Help binary search
+ with continuous prediction.
+
+2018-09-22 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bimap): Another tweak.
+
+ This one should be clearer. When the rounded monochrome bbox collapses
+ we add a pixel that covers most if not all original cbox.
+
+2018-09-21 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bimap): Further tweak.
+
+2018-09-21 Ben Wagner <bungeman@google.com>
+
+ Improve auto-hinter handling of bitmap fonts (#54681).
+
+ For bitmap fonts, `FT_Load_Glyph' should either return an error or
+ not set the format to `FT_GLYPH_FORMAT_OUTLINE'. However, in this
+ case `FT_Load_Glyph' calls into the auto-hinter which calls back
+ into `FT_Load_Glyph' with `FT_LOAD_NO_SCALE' in the flags, which
+ marks the glyph as `FT_GLYPH_FORMAT_OUTLINE' with an empty path
+ (even though it doesn't have any path). It appears that the
+ auto-hinter should not be called when the face doesn't have
+ outlines. The current test for using the auto-hinter in
+ `FT_Load_Glyph' checks whether the driver supports scalable
+ outlines, but not if the face supports scalable outlines.
+
+ * src/base/ftobjs.c (FT_Load_Glyph): Directly check whether we have
+ scalable outlines.
+
+2018-09-21 Werner Lemberg <wl@gnu.org>
+
+ [raster] Fix disappearing vertical lines (#54589).
+
+ * src/raster/ftraster.c (Vertical_Sweep_Span): Handle special case
+ where both left and right outline exactly pass pixel centers.
+
+2018-09-20 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bimap): Tiny rounding tweak.
+
+ This adds pixels in case a contour goes through the center
+ and they need to be turned on in the b/w rasterizer.
+
+2018-09-20 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf] Replace charmap implementation.
+
+ PCF comes with charmap lookup table, aka PCF encodings. Using it
+ directly makes FT_Get_Char_Index and FT_Get_Next_Char 4-5 times
+ faster than the original BDF-like binary searches.
+
+ * src/pcf/pcf.h (PCF_EncodingRec): Removed.
+ (PCF_FaceRec): Remove `nencodings' and `encodings'.
+ * src/pcf/pcfdrivr.c (pcf_cmap_char_{index,next}): Replaced.
+ * src/pcf/pcfread.c (pcf_get_encodings): Store data differently.
+
+2018-09-20 Werner Lemberg <wl@gnu.org>
+
+ [base] Remove unused function `FT_GlyphLoader_CopyPoints'.
+
+ * include/freetype/internal/ftgloadr.h, src/base/ftgloadr.c
+ (FT_GlyphLoader_CopyPoints): Do it.
+
+2018-09-19 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf] Prepare to replace charmap implementation.
+
+ * src/pcf/pcf.h (PCF_FaceRec): Updated to include...
+ (PCF_EncRec): ... this new structure to store charmap geometry.
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Store charmap geometry.
+
+2018-09-18 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Remove unused fields.
+
+ * src/pcf.h (PCF_FaceRec): Remove `charmap' and `charmap_handle'.
+ * src/bdfdrvr.h (BDF_FaceRec): Ditto.
+ * src/winfonts/winfnt.h (FNT_FaceRec): Ditto.
+
+2018-09-17 Werner Lemberg <wl@gnu.org>
+
+ [pshinter] Handle numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10396
+
+ * src/pshinter/pshglob.c: Include FT_INTERNAL_CALC_H.
+ (psh_blues_snap_stem): Mask numeric overflow.
+
+2018-09-13 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Some fixes for VF checks.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10317
+
+ * src/truetype/ttgxvar.c (ft_var_load_gvar): Properly exit memory
+ frame if we have invalid glyph variation data offsets.
+ (tt_face_vary_cvt): Protect against missing `tuplecoords' array.
+ Fix typo.
+
+2018-09-13 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfdriver.c (sfnt_get_var_ps_name): Fix last commit.
+
+2018-09-13 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/sfdriver.c (sfnt_get_var_ps_name): Check `result'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10316
+
+2018-09-12 John Tytgat <John.Tytgat@esko.com>
+
+ [sfnt] Better PS name handling (#54629).
+
+ * src/sfnt/sfdriver (IS_WIN, IS_APPLE): Omit language ID checks.
+ (get_win_string, get_apple_string): Return NULL when the PostScript
+ font name characters is not according to specification.
+ (get_win_string): Make trace output work if the high byte if
+ non-zero.
+ (sfnt_get_var_ps_name, sfnt_get_ps_name): Previously we preferred
+ Win PS name (when there is also an Apple PS name); change this into
+ a fallback to Apple PS name in case the Win PS name is invalid.
+
+2018-09-12 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Improve VF check.
+
+ Triggered by
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10255
+
+ * src/truetype/ttgxvar.c (ft_var_load_gvar): Use better limit check
+ for `tupleCount'.
+
+2018-09-12 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgxvar.c (ft_var_load_gvar): Check `glyphoffsets'.
+
+2018-09-10 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ * src/pshinter/pshrec.c (t2_hints_stems): Mask numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10215
+
+2018-09-09 Ben Wagner <bungeman@google.com>
+
+ * builds/freetype.mk (refdoc-venv): Ensure python version (#54631).
+
+2018-09-07 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Fix assertion failure.
+
+ Triggered by
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10212
+
+ * src/truetype/ttgload.c (load_truetype_glyph): Reintroduce
+ `opened_frame' (removed in a change from 2018-08-26) to handle
+ deallocation of the second frame.
+
+2018-09-05 Werner Lemberg <wl@gnu.org>
+
+ Synchronize `ftdebug.c' files.
+
+ * builds/amiga/src/base/ftdebug.c, builds/wince/ftdebug.c,
+ builds/windows/ftdebug.c: Synchronize with `src/base/ftdebug.c'.
+
+2018-09-05 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ Add documentation guidelines file.
+
+ * docs/DOCGUIDE: New file.
+
+2018-09-04 Werner Lemberg <wl@gnu.org>
+
+ * devel/ftoption.h: Synchronize with master `ftoption.h'.
+
+2018-09-03 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [docwriter] Don't break code snippets accross lines.
+
+ Reported as
+
+ https://lists.nongnu.org/archive/html/freetype-devel/2018-08/msg00124.html
+
+ * docs/reference/markdown/stylesheets/extra.css (.md-typeset code):
+ Add rule `white-space'.
+
+2018-09-03 Werner Lemberg <wl@gnu.org>
+
+ */*: s/PSNames/psnames/.
+
+ Only tracing messages are affected.
+
+2018-09-03 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix heap buffer overflow in CPAL handling.
+
+ * src/sfnt/ttcpal.c (tt_face_palette_set): Fix boundary test.
+ (tt_face_load_cpal): Updated.
+
+2018-09-01 Werner Lemberg <wl@gnu.org>
+
+ Remove `FT_Outline_{New,Done}_Internal'.
+
+ These public API functions(!) were always undocumented and have
+ escaped all clean-up efforts until now.
+
+ * include/freetype/ftoutln.h (FT_Outline_New_Internal,
+ FT_Outline_Done_Internal): Removed.
+
+ * src/base/ftoutln.h (FT_Outline_New_Internal,
+ FT_Outline_Done_Internal): Merge into...
+ (FT_Outline_New, FT_Outline_Done): ... these functions.
+
+ * docs/README: Updated.
+
+2018-08-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Check glyph format.
+
+2018-08-31 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [errors] Refine the macro logic surrounding `FT_Error_String'.
+
+ * include/freetype/fterrors.h (FT_INCLUDE_ERR_PROTOS,
+ FT_ERR_PROTOS_DEFINED): Undefine `FT_INCLUDE_ERR_PROTOS' after
+ checking it and introduce a new macro that takes proper care of
+ multiple-inclusion protection.
+
+2018-08-31 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftdebug.c (FT_Throw): Restore missing `FT_UNUSED' calls.
+
+2018-08-31 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftdebug.c (FT_Throw): Reduce chattiness.
+
+2018-08-31 Werner Lemberg <wl@gnu.org>
+
+ * src/autofit/afhints.c (af_glyph_hints_reload): Add initialization.
+
+2018-08-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ Consolidate bitmap presetting and size assessment.
+
+ * include/freetype/internal/ftobjs.h (ft_glyphslot_preset_bitmap):
+ Change return type.
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Return the bitmap
+ size assessment.
+
+ * src/raster/ftrend1.c (ft_raster1_render): Use it to refuse the
+ rendering of enourmous or far-fetched outlines.
+ * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto.
+
+2018-08-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Correct mono.
+
+2018-08-30 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [errors] Introduce a macro to control `FT_Error_String'.
+
+ * devel/ftoption.h (FT_CONFIG_OPTION_ERROR_STRINGS),
+ include/freetype/config/ftoption.h (FT_CONFIG_OPTION_ERROR_STRINGS):
+ New macro.
+
+2018-08-30 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [errors] Introduce `FT_Error_String'.
+
+ * include/freetype/fterrors.h (FT_Error_String),
+ src/base/fterrors.c (FT_Error_String): Implement `FT_Error_String'.
+
+ * src/base/ftbase.c, src/base/Jamfile (_source),
+ src/base/rules.mk (BASE_SRC): Add `fterrors.c' to the build logic.
+
+ * src/base/ftdebug.c (FT_Throw): Use `FT_Error_String'.
+
+2018-08-30 Werner Lemberg <wl@gnu.org>
+
+ [autofit] Trace `before' and `after' edges of strong points.
+
+ * src/autofit/afhints.h (AF_PointRec) [FT_DEBUG_AUTOFIT]: New arrays
+ `before' and `after'.
+
+ * src/autofit/afhints.c (af_get_strong_edge_index): New auxiliary
+ function.
+ (af_glyph_hints_dump_points): Trace `before' and `after' edges.
+ (af_glyph_hints_align_strong_points) [FT_DEBUG_AUTOFIT]: Set
+ `before' and `after' information.
+
+2018-08-30 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] Overflow-resistant bitmap presetting.
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Implement it.
+
+2018-08-29 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ Fix numeric overflows.
+
+ * src/pshint/pshalgo.c (psh_hint_align, psh_hint_align_light,
+ psh_hint_table_find_strong_points): Fix numeric overflows.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10083
+
+2018-08-29 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix handling of `roll' op in old engine.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10080
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings) <cff_op_roll>
+ [CFF_CONFIG_OPTION_OLD_ENGINE]: Use modulo for loop count, as
+ documented in the specification.
+
+2018-08-26 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttobjs.c (tt_size_read_bytecode): Trace CVT values.
+
+2018-08-26 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ * configure: Copy assets required by docwriter.
+
+ Copy directory `docs/reference/markdown' when FreeType is compiled in a
+ different directory.
+
+ Fixes `make refdoc' if builddir != srcdir.
+
+ Reported as
+
+ https://lists.nongnu.org/archive/html/freetype-devel/2018-08/msg00083.html
+
+2018-08-26 Werner Lemberg <wl@gnu.org>
+
+ * src/pshint/pshalgo.c (psh_hint_overlap): Fix numeric overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10057
+
+2018-08-26 Werner Lemberg <wl@gnu.org>
+
+ Minor tracing adjustments.
+
+ * src/base/ftstream.c (FT_Stream_EnterFrame, FT_Stream_ExitFrame):
+ Trace.
+
+ * src/truetype/ttgload.c (TT_Access_Glyph_Frame): Remove tracing.
+
+2018-08-26 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Avoid nested frames.
+
+ Triggered by
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10054
+
+ * src/truetype/ttgload.c (load_truetype_glyph): Don't use variable
+ `opened_frame' to trace whether a frame must be closed at the end of
+ function: This fails because `TT_Vary_Apply_Glyph_Deltas' (which
+ gets called for space glyphs) uses a frame by itself. Instead,
+ close the frame after loading the header, then use another frame for
+ the remaining part of the glyph later on.
+
+ Also avoid calling `tt_get_metrics' twice under some circumstances.
+
+2018-08-26 Werner Lemberg <wl@gnu.org>
+
+ Various minor clean-ups.
+
+ * src/base/ftapi.c: Remove. Unused.
+ * src/base/Jamfile (_sources): Updated.
+
+ * src/base/ftstream.c (FT_Stream_ReleaseFrame): Remove redundant
+ code.
+
+2018-08-25 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ Convert documentation markup to Markdown.
+
+ It is the result of a GSoC 2018 project; this separate ChangeLog
+ commit covers the last four commits
+
+ ae5d1a4cec37557f31aec270332cfe886a62f9a0
+ 53c69ce04faed3dcc68ca0f54cb8d703d8babf69
+ 195728d5ba38f34fb2c2c20807c01656f2f59b66
+ c962db28ea59225f0105c03d907d4a9b71765687
+
+ * docs/reference/markdown/images/favico.ico,
+ docs/reference/markdown/javascripts/extra.js,
+ docs/reference/markdown/stylesheets/extra.css: New files.
+
+ * docs/reference/.gitignore, docs/reference/README: Updated.
+
+ * src/tools/docmaker/*: Removed. It has been replaced with
+ `docwriter', a python package available at
+
+ https://pypi.org/project/docwriter/
+
+ * Jamfile: Updated.
+ * builds/ansi/ansi-def.mk, builds/beos/beos-def.mk,
+ builds/dos/dos-def.mk, builds/os2/os2-def.mk (BIN),
+ builds/unix/unixddef.mk, builds/windows/win32-def.mk: New variable.
+
+ * builds/unix/configure.raw: Check for `python' and `pip'.
+ If not present, warn that `make refdoc' will fail.
+ * builds/unix/unix-def.in (PYTHON, PIP, BIN): New variables.
+
+ * builds/freetype.mk (PYTHON, PIP, VENV_NAME, VENV_DIR, ENV_PYTHON,
+ ENV_PIP): New variables.
+ (refdoc): Updated.
+ (refdoc-venv): New target.
+ (.PHONY): Updated.
+
+2018-08-23 Werner Lemberg <wl@gnu.org>
+
+ Add macros for handling over-/underflowing `FT_Int64' values.
+
+ * include/freetype/internal/ftcalc.h (ADD_INT64, SUB_INT64,
+ MUL_INT64, DIV_INT64) [FT_LONG64]: New macros.
+
+ * src/base/ftcalc.c (ft_corner_orientation) [FT_LONG64]: Use
+ `SUB_INT64' and `MUL_INT64'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=10028
+
+2018-08-22 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Improve legibility of `glyf' parsing.
+
+ * src/truetype/ttgload.c (ON_CURVE_POINT, X_SHORT_VECTOR,
+ Y_SHORT_VECTOR, REPEAT_FLAG, X_POSITIVE, SAME_X, Y_POSITIVE, SAME_Y,
+ OVERLAP_SIMPLE): New macros.
+ (TT_Load_Simple_Glyph): Use new macros to make code more readable.
+ Remove useless adjustment of `outline->tags' elements.
+
+2018-08-21 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/ttcpal.c (tt_face_load_cpal): Add missing safety check.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9981
+
+2018-08-18 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Avoid slow PS font parsing in case of error.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9955
+
+ * src/psaux/psobjs.c (ps_parser_to_bytes): Set `parser->cursor' even
+ in case of error to avoid potential re-scanning.
+
+2018-08-18 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix heap buffer overflow in old engine.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9967
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings)
+ <cff_op_blend> [CFF_CONFIG_OPTION_OLD_ENGINE]: `num_designs' must be
+ non-zero.
+
+2018-08-16 Young Xiao <yangx92@hotmail.com>
+
+ * builds/mac/ftmac.c (parse_fond): Fix buffer overrun.
+
+ Reported as bug #54515, duplicate of #43540.
+
+2018-08-16 Werner Lemberg <wl@gnu.org>
+
+ * builds/*/ftsystem.c (FT_COMPONENT): Updated also.
+
+2018-08-15 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf] Don't track duplicate encodings.
+
+ There is no harm except some umbiguity in broken fonts with duplicate
+ encodings.
+
+ * src/bdf/bdflib.c (_bdf_parse_glyphs): Remove duplicate tracking.
+ (_bdf_parse_t): Remove large `have' bitfield.
+
+2018-08-15 Werner Lemberg <wl@gnu.org>
+
+ Don't use `trace_' prefix for FT_COMPONENT arguments.
+
+ * include/freetype/internal/ftdebug.h (FT_TRACE_COMP,
+ FT_TRACE_COMP_): New auxiliary macros to add `trace_' prefix.
+ (FT_TRACE): Use `FT_TRACE_COMP'.
+
+ */* (FT_COMPONENT): Updated.
+
+2018-08-14 Werner Lemberg <wl@gnu.org>
+
+ Use formatting string in FT_TRACEX calls for non-simple arguments.
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings)
+ <cff_op_hstem, cff_op_hintmask, cff_op_hlineto, cff_op_vhcurveto>:
+ Do it.
+
+ * src/psaux/pshints.c (cf2_hintmap_build): Ditto.
+
+ * src/psaux/psintrp.c (cf2_interpT2CharString) <cf2_cmdHSTEM,
+ cf2_cmdVSTEM, cf2_cmdHLINETO, cf2_cmdRRCURVETO, cf2_cmdCALLSUBR,
+ cf2_escHSTEM3, cf2_cmdHINTMASK, cf2_cmdHVCURVETO>: Ditto.
+
+ * src/truetype/ttinterp.c (TT_RunIns): Ditto.
+
+2018-08-14 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf] Remove unused fields.
+
+ * src/bdf/bdf.h (bdf_font_t): Remove `nmod', `umod', and `modified',
+ which were set but never used.
+ * src/bdf/bdflib.c (_bdf_parse_{glyphs,properties}, bdf_load_font):
+ Updated accordingly.
+
+2018-08-14 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix another segv in old engine.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9872
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings)
+ [CFF_CONFIG_OPTION_OLD_ENGINE]: Disallow invalid T1 opcodes in
+ dictionaries.
+
+2018-08-14 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix missing error handling.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9865
+
+ * src/psaux/cffparse.c (cff_parser_run)
+ [CFF_CONFIG_OPTION_OLD_ENGINE]: Don't ignore return value of
+ `parse_charstrings_old'.
+
+2018-08-14 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf] Remove unused overflow storage.
+
+ * src/bdf/bdf.h (bdf_glyphlist_t): Remove this type.
+ (bdf_font_t): Remove `overflow' field.
+ * src/bdf/bdflib.c (bdf_free_font): Remove `overflow' freeing.
+
+2018-08-14 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix segv in old engine.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9864
+
+ * src/psaux/cffdecode.c (cff_decoder_parse_charstrings)
+ <cff_op_random> [CFF_CONFIG_OPTION_OLD_ENGINE]: Use top dict's
+ `random' field directly if parsing dictionaries.
+
+2018-08-13 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [bdf] Use unsigned types.
+
+ * src/bdf/bdf.h (bdf_glyph_t): Unsign `encoding'.
+ (bdf_font_t): Unsign `default_char'.
+ * src/bdf/bdfdrivr.h (BDF_encoding_el): Unsign `enc'.
+
+ * src/bdf/bdflib.c (_bdf_add_property, _bdf_parse_glyphs,
+ _bdf_parse_start): Updated accordingly.
+ * src/bdf/bdfdrivr.c (bdf_cmap_char_{index,next}): Ditto.
+
+2018-08-13 Werner Lemberg <wl@gnu.org>
+
+ * src/type42/t42parse.c (t42_parse_sfnts): One more format check.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9832
+
+2018-08-11 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftcalc.c (FT_Matrix_Check): Fix integer overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9811
+
+2018-08-10 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/sfnt/ttsbit.c (tt_sbit_decoder_load_compound): Follow specs.
+
+2018-08-10 Ben Wagner <bungeman@google.com>
+
+ * src/sfnt/sfobjs.c (sfnt_done_face): Fix memory leak (#54435).
+
+2018-08-10 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftobjs.c (FT_Render_Glyph_Internal): Improve tracing.
+
+2018-08-10 Werner Lemberg <wl@gnu.org>
+
+ Fix clang warnings.
+
+ * src/base/ftdebug.c (ft_trace_level_enabled,
+ ft_trace_level_disabled): Add `static' keyword.
+
+2018-08-09 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster, smooth] Reinstate bitmap size limits.
+
+ This again moves outline and bitmap size checks one level up.
+
+ * src/base/ftoutln.c (FT_Outline_Render): Explicitly reject enormous
+ outlines.
+ * src/raster/ftrend1.c (ft_raster1_render): Reject enormous bitmaps
+ and, therefore, outlines that require them.
+ * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto.
+
+ * src/raster/ftraster.c (ft_black_render): Remove outline size checks.
+ * src/smooth/ftgrays.c (gray_raster_render): Ditto.
+ [STANDALONE]: Remove `FT_Outline_Get_CBox' copy.
+
+2018-08-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf] Revert massive unsigning.
+
+2018-08-08 Werner Lemberg <wl@gnu.org>
+
+ [smooth] Improve tracing.
+
+ * src/smooth/ftgrays.c (gray_convert_glyph_inner): Only use tracing
+ if called the first time.
+ (gray_convert_glyph): Updated.
+
+2018-08-08 Werner Lemberg <wl@gnu.org>
+
+ Add internal functions `FT_Trace_Disable' and `FT_Trace_Enable'.
+
+ It sometimes makes sense to suppress tracing informations, for
+ example, if it outputs identical messages again and again.
+
+ * include/freetype/internal/ftdebug.h: Make `ft_trace_levels' a
+ pointer.
+ (FT_Trace_Disable, FT_Trace_Enable): New declarations.
+
+ * src/base/ftdebug.c (ft_trace_levels): Rename to...
+ (ft_trace_levels_enabled): ... this.
+ (ft_trace_levels_disabled): New array.
+ (ft_trace_levels): New pointer.
+ (FT_Trace_Disable, FT_Trace_Enable): Implement.
+ (ft_debug_init): Updated.
+
+2018-08-08 Werner Lemberg <wl@gnu.org>
+
+ Debugging improvements.
+
+ * src/base/ftobjs.c (pixel_modes): Move this array to top level
+ from ...
+ (FT_Load_Glyph): ... here.
+ (FT_Render_Glyph_Internal): Use `width' x `height' in trace message.
+ Use `pixel_modes'.
+
+2018-08-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf] Massive unsigning (part 2).
+
+ Treat all size related properties as unsigned values.
+
+ * src/pcf/pcf.h (PCF_ParsePropertyRec): Use unsigned `name' and
+ `value'.
+ * src/pcf/pcfread.c (pcf_get_properties, pcf_load_font): Updated
+ parsing code and handling of AVERAGE_WIDTH, POINT_SIZE, PIXEL_SIZE,
+ RESOLUTION_X and RESOLUTION_Y.
+
+2018-08-08 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf] Massive unsigning (part 1).
+
+ Unofficial specifications hesitate to use unsigned 32-bit integers.
+ Negative values caused a lot of trouble in the past and it is safer
+ and easier to treat some properties as unsigned.
+
+ * src/pcf/pcf.h (PCF_AccelRec): Use unsigned values for `fontAscent',
+ `fontDescent', and `maxOverlap'.
+ * src/pcf/pcfread.c (pcf_load_font, pcf_get_accel): Updated.
+ * src/pcf/pcfdrivr.c (PCF_Glyph_Load, PCF_Size_Select,
+ PCF_Size_Request): Updated.
+
+2018-08-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/pcf/pcfread.c (pcf_get_bitmaps): Unsign `offsets' and
+ `bitmapSizes'.
+
+2018-08-06 Werner Lemberg <wl@gnu.org>
+
+ * devel/ftoption.h: Synchronize with main `ftoption.h'.
+
+2018-08-06 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [pcf] Use unsigned types.
+
+ * src/pcf/pcf.h (PCF_Encoding): Use unsigned `enc'.
+ * src/pcf/pcfdrivr.c (pcf_cmap_char_{index,next}): Ditto.
+ * src/pcf/pcfread.c (pcf_get_encodings): Use unsigned types.
+
+2018-08-05 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgload.c (compute_glyph_metrics): Fix overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/chromium/issues/detail?id=777151
+
+2018-08-04 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttinterp.c (opcode_name): Fix typos.
+
+2018-08-04 Werner Lemberg <wl@gnu.org>
+
+ Fix clang warnings.
+
+ * src/base/ftoutln.c (FT_Outline_EmboldenXY): Fix type of
+ `orientation'.
+
+ * src/gxvalid/gxvcommn.c (gx_lookup_value_read): Fix signature.
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Fix type of some variables.
+ Add cast.
+
+ * src/type1/t1load.c (parse_weight_vector): Fix cast.
+
+2018-07-31 Werner Lemberg <wl@gnu.org>
+
+ * src/cid/cidtoken.h: Handle `XUID' keyword.
+
+2018-07-31 Werner Lemberg <wl@gnu.org>
+
+ [cid] Trace PostScript dictionaries.
+
+ * src/cid/cidload.c: Include FT_INTERNAL_POSTSCRIPT_AUX_H.
+ (cid_load_keyword, cid_parse_font_matrix, parse_fd_array,
+ parse_expansion_factor, cid_parse_dict): Add tracing calls.
+ (parse_font_name): New function to trace `/FontName' keywords in
+ /FDArray dict.
+ (cid_field_records): Register `parse_font_name'.
+
+2018-07-30 Werner Lemberg <wl@gnu.org>
+
+ [cff] Fix typo.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9409
+
+ * src/cff/cffdrivr.c (cff_get_cid_from_glyph_index): Fix boundary
+ check.
+
+2018-07-29 Werner Lemberg <wl@gnu.org>
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Another thinko.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9608
+
+2018-07-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Fix Harmony memory management.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9501
+
+ * src/smooth/ftgrays.c (ft_smooth_render_generic): Restore buffer
+ after each rendering in case of failure.
+
+2018-07-28 Werner Lemberg <wl@gnu.org>
+
+ [type1] Avoid segfaults with `FT_Get_PS_Font_Value'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9610
+
+ * src/type1/t1driver.c (t1_ps_get_font_value): Protect against NULL.
+
+2018-07-27 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Make `TT_Set_MM_Blend' idempotent (#54388).
+
+ * src/truetype/ttgxvar.c (tt_set_mm_blend): Correctly set
+ `face->doblend' if the current call to the function yields the same
+ blend coordinates as the previous call.
+
+2018-07-27 Werner Lemberg <wl@gnu.org>
+
+ [psaux, type1]: More tracing improvements.
+
+ * src/psaux/psintrp.c (cf2_interpT2CharString): Trace skipped
+ outline commands.
+
+ * src/psaux/t1decode.c (t1_decoder_parse_charstring): Fix
+ missing case.
+ (t1_decoder_parse_metrics): Make tracing output more compact.
+
+ * src/type1/t1gload.c (T1_Compute_Max_Advance): Be less verbose.
+ (T1_Get_Advances): Add tracing.
+
+2018-07-25 Werner Lemberg <wl@gnu.org>
+
+ [psaux, type1] Trace PostScript dictionaries and other things.
+
+ The tracing of /Encoding, /Subrs, and /Charstrings is rudimentary
+ right now.
+
+ * src/psaux/psobjs.c (ps_parser_load_field,
+ ps_parser_load_field_table): Add tracing calls.
+
+ * src/psaux/t1decode.c (t1_decoder_parse_charstrings): Make tracing
+ output more compact.
+
+ * src/type1/t1gload.c (T1_Compute_Max_Advance, T1_Get_Advances): Add
+ tracing messages.
+
+ * src/type1/t1load.c (parse_blend_axis_types,
+ parse_blend_design_positions, parse_blend_design_map,
+ parse_weight_vector, t1_load_keyword, t1_parse_font_matrix,
+ parse_encoding, parse_subrs, parse_charstrings, T1_Open_Face): Add
+ tracing calls.
+
+ * src/type1/t1objs.c (T1_Face_Init): Add tracing call.
+
+ * src/sfnt/sfobjs.c (sfnt_init_face): Make tracing message more
+ verbose.
+
+2018-07-25 Werner Lemberg <wl@gnu.org>
+
+ Fix minor ASAN run-time warnings.
+
+ * src/base/ftutil.c (ft_mem_alloc, ft_mem_realloc): Only call
+ `FT_MEM_ZERO' if we actually have a buffer.
+ (ft_mem_dup): Only call `ft_memcpy' if we actually have a buffer.
+
+2018-07-24 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [build] Fortify dllexport/dllimport attributes (#53969,#54330).
+
+ We no longer use predefined _DLL, which can be defined for static
+ builds too with /MD. We use DLL_EXPORT and DLL_IMPORT instead,
+ following libtool convention.
+
+ * CMakeLists.txt [WIN32], builds/windows/vc2010/freetype.vcxproj:
+ Define DLL_EXPORT manually.
+
+ * include/freetype/config/ftconfig.h, builds/unix/ftconfig.in,
+ builds/vms/ftconfig.h, builds/windows/vc2010/index.html,
+ src/base/ftver.rc: /_DLL/d, s/FT2_DLLIMPORT/DLL_IMPORT/.
+
+2018-07-24 Werner Lemberg <wl@gnu.org>
+
+ [type1] Check relationship between number of axes and designs.
+
+ For Multiple Masters fonts we don't support intermediate designs;
+ this implies that
+
+ number_of_designs == 2 ^^ number_of_axes
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9557
+
+ * src/type1/t1load.c (T1_Open_Face): Ensure above constraint.
+ (T1_Get_MM_Var): Remove now redundant test.
+
+2018-07-24 Hin-Tak Leung <htl10@users.sourceforge.net>
+
+ [truetype] Match ttdebug's naming of instruction mnemonics.
+
+ * src/truetype/ttinterp.c: The form used in ttdebug,
+ "MDRP[G,B,W,?]", etc., is slightly more readable than
+ "MDRP[00,01,02,03]".
+
+2018-07-24 Werner Lemberg <wl@gnu.org>
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Thinko.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9561
+
+2018-07-22 Werner Lemberg <wl@gnu.org>
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Check index of defaultChar.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9527
+
+2018-07-22 Werner Lemberg <wl@gnu.org>
+
+ * src/pcf/pcfread.c (pcf_load_font): Fix number of glyphs.
+
+ This is an oversight of the module change 2018-07-21.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9524
+
+2018-07-22 Werner Lemberg <wl@gnu.org>
+
+ [cid] Sanitize `BlueShift' and `BlueFuzz'.
+
+ This code is taken from the type1 module.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9510
+
+ * src/cid/cidload.c (parse_fd_array): Set some private dict default
+ values.
+ (cid_face_open): Do the sanitizing.
+ Fix some tracing messages.
+
+2018-07-21 Werner Lemberg <wl@gnu.org>
+
+ [pcf] Fix handling of the undefined glyph.
+
+ This change makes the driver use the `defaultChar' property of PCF
+ files.
+
+ * src/pcf/pcf.h (PCF_FaceRec): Change type of `defaultChar' to
+ unsigned.
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Read `defaultChar' as
+ unsigned.
+ Validate `defaultChar'.
+ If `defaultChar' doesn't point to glyph index zero, swap glyphs with
+ index zero and index `defaultChar' and adjust the encodings
+ accordingly.
+
+ * src/pcf/pcfdrivr.c (pcf_cmap_char_index, pcf_cmap_char_next,
+ PCF_Glyph_Load): Undo change from 2002-06-16 which always enforced
+ the first character in the font to be the default character.
+
+2018-07-20 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ Move the legacy fuzz target to the `freetype-testing' repository.
+
+ It can now be found at
+
+ https://github.com/freetype/freetype2-testing/tree/master/fuzzing/src/legacy
+
+ * src/tools/ftfuzzer: Remove this folder and its contents from the
+ repository.
+
+2018-07-20 Werner Lemberg <wl@gnu.org>
+
+ [cff] Avoid left-shift of negative numbers (#54322).
+
+ * src/cff/cffgload.c (cff_slot_load): Use multiplication.
+
+2018-07-17 Werner Lemberg <wl@gnu.org>
+
+ Allow FT_ENCODING_NONE for `FT_Select_Charmap'.
+
+ This is a valid encoding tag for BDF, PCF, and Windows FNT, and
+ there is no reason to disallow it for these formats.
+
+ * src/base/ftobjs.c (FT_Select_Charmap): Implement it.
+
+2018-07-17 Werner Lemberg <wl@gnu.org>
+
+ * src/pcf/pcfread.c (pcf_get_encodings): Trace `defaultChar'.
+
+2018-07-16 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ * include/freetype/internal/ftcalc.h: Add macros for handling
+ harmless over-/underflowing `FT_Int' values.
+
+ * src/sfnt/sfdriver.c (fixed2float): Fix negation of
+ `(int)(-2147483648)'.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9423
+
+2018-07-16 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgxvar.c (tt_set_mm_blend): Fix off-by-one error.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9412
+
+2018-07-12 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftoutln.c (FT_Outline_Get_Orientation): Init `cbox'.
+
+ Taken from patch #9667, written by Steve Langasek
+ <vorlon@debian.org>.
+
+ This fixes a build failure (most probably a bug in gcc) on ppc64el
+ when building with -O3.
+
+2018-07-05 Werner Lemberg <wl@gnu.org>
+
+ Fix typo (#54238).
+
+ * src/base/ftcolor.c (FT_Palette_Set_Foreground_Color)
+ [!TT_CONFIG_OPTION_COLOR_LAYERS]: Add return value.
+
+2018-07-05 Werner Lemberg <wl@gnu.org>
+
+ Adjust table size comparisons (#54242).
+
+ * src/sfnt/ttcpal.c (tt_face_load_cpal): Implement it.
+
+2018-07-05 Werner Lemberg <wl@gnu.org>
+
+ Fix more 32bit issues (#54208).
+
+ * src/cff/cffload.c (cff_blend_build_vector): Convert assertion into
+ run-time error.
+
+ * src/truetype/ttgxvar.c (ft_var_to_normalized): Protect against
+ numeric overflow.
+
+2018-07-04 Werner Lemberg <wl@gnu.org>
+
+ Fix 32bit build warnings (#54239).
+
+ * src/base/ftbitmap.c (FT_Bitmap_Blend): Add casts to avoid signed
+ vs. unsigned comparisons.
+
+ * srb/sfnt/ttcolr.c (tt_face_get_colr_layer): Ditto.
+
+2018-07-02 Jeff Carey <Jeff.Carey@monotype.com>
+
+ * src/psnames/psmodule.c (ps_unicodes_init): Fix alloc debugging.
+
+2018-07-02 Werner Lemberg <wl@gnu.org>
+
+ s/palette_types/palette_flags/.
+
+ Suggested by Behdad.
+
+2018-07-02 Werner Lemberg <wl@gnu.org>
+
+ Make `FT_Get_Color_Glyph_Layer' return FT_Bool.
+
+ * include/freetype/freetype.h, src/base/ftobjs.c
+ (FT_Get_Color_Glyph_Layer, FT_Render_Glyph_Internal): Updated.
+
+ * include/freetype/internal/sfnt.h (TT_Get_Colr_Layer_Func),
+ src/sfnt/ttcolr.h, src/sfnt/ttcolr.c (tt_face_get_colr_layer):
+ Updated.
+
+2018-07-01 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftobjs.c (FT_Get_Color_Glyph_Layer): Guard SFNT function.
+
+ Reported by Behdad.
+
+2018-06-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/fttrigon.c (FT_Tan): Improve accuracy.
+ (FT_Vector_Rotate): Simplify.
+
+2018-06-28 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * src/base/ftobjs.c (FT_Set_Charmap): Robustify.
+
+2018-06-25 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Fix memory leak.
+
+ * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Add initializers.
+ Fix typo in `goto' destination.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9071
+
+2018-06-25 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgxvar.c (tt_face_vary_cvt): Add initializers.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=9070
+
+2018-06-24 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Increase precision while applying VF deltas.
+
+ It turned out that we incorrectly round CVT and glyph point deltas
+ before accumulation, leading to severe positioning errors if there
+ are many delta values to sum up.
+
+ Problem reported by Akiem Helmling <akiem@underware.nl> and analyzed
+ by Behdad.
+
+ * src/truetype/ttgxvar.c (ft_var_readpackeddelta): Return deltas in
+ 16.16 format.
+ (tt_face_var_cvt): Collect deltas in `cvt_deltas', which is a 16.16
+ format array, and add the accumulated values to the CVT at the end
+ of the function.
+ (TT_Vary_Apply_Glyph_Deltas): Store data in `points_org' and
+ `points_out' in 16.16 format.
+ Collect deltas in `point_deltas_x' and `point_deltas_y', which are
+ 16.16 format arrays, and add the accumulated values to the glyph
+ coordinates at the end of the function.
+
+2018-06-24 Werner Lemberg <wl@gnu.org>
+
+ New base function `FT_Matrix_Check' (#54019).
+
+ * src/base/ftcalc.c (FT_Matrix_Check): New base function to properly
+ reject degenerate font matrices.
+
+ * include/freetype/internal/ftcalc.h: Updated.
+
+ * src/cff/cffparse.c (cff_parse_font_matrix), src/cid/cidload.c
+ (cid_parse_font_matrix), src/type1/t1load.c (t1_parse_font_matrix),
+ src/type42/t42parse.c (t42_parse_font_matrix): Use
+ `FT_Matrix_Check'.
+
+2018-06-23 Werner Lemberg <wl@gnu.org>
+
+ Fix typo.
+
+ Reported by Behdad.
+
+ * src/base/ftcolor.c (FT_Palette_Data_Get)
+ [!TT_CONFIG_OPTION_COLOR_LAYERS]: s/apalette/apalette_data/.
+
+2018-06-21 Werner Lemberg <wl@gnu.org>
+
+ s/FT_PALETTE_USABLE_WITH_/FT_PALETTE_FOR_/.
+
+ * include/freetype/ftcolor.h, include/freetype/internal/sfnt.h,
+ src/sfnt/ttcolr.c: Do it.
+
+2018-06-19 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix CPAL heap buffer overflow.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8968
+
+ * src/sfnt/ttcpal.c (tt_face_load_cpal): Guard CPAL version 1
+ offsets.
+
+2018-06-19 Werner Lemberg <wl@gnu.org>
+
+ Doh. Don't use CPAL or COLR data if tables are missing.
+
+ Reported by Alexei.
+
+ * src/sfnt/ttcolr.c (tt_face_get_colr_layer): Return immediately if
+ `colr' is NULL.
+
+ * src/sfnt/ttcpal.c (tt_face_palette_set): Return immediately, if
+ `cpal' is NULL.
+
+2018-06-17 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] Introduce `FT_New_Glyph'.
+
+ This function facilitates access to full capabilities of FreeType
+ rendering engine for custom glyphs. This can be quite useful for
+ consistent rendering of mathematical and chemical formulas, e.g.
+
+ https://bugs.chromium.org/p/chromium/issues/detail?id=757078
+
+ * include/freetype/ftglyph.h, src/base/ftglyph.c (FT_New_Glyph): New
+ function.
+
+2018-06-17 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ [bdf] Fix underflow of an unsigned value.
+
+ bdflib.c:1562 could be reached with `font->glyphs_used == 0'. That
+ caused an underflow of the unsigned value which results in undefined
+ behaviour.
+
+ * src/bdf/bdflib.c (_bdf_parse_glyphs): Bail out earlier than before
+ if the `ENCODING' keyword cannot be found.
+
+2018-06-17 Werner Lemberg <wl@gnu.org>
+
+ [base] Add tracing for `FT_Bitmap_Blend'.
+
+ * include/freetype/internal/fttrace.h (trace_bitmap): New
+ enumeration.
+
+ * src/base/ftbitmap.c (FT_COMPONENT): Define.
+ (FT_Bitmap_Blend): Add `FT_TRACE5' calls.
+
+2018-06-17 Werner Lemberg <wl@gnu.org>
+
+ s/trace_bitmap/trace_checksum/.
+
+ * include/freetype/internal/fttrace.h: s/bitmap/checksum/.
+
+ * src/base/ftobjs.c (FT_COMPONENT): s/trace_bitmap/trace_checksum/.
+ Adjust code.
+
+2018-06-16 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix color glyph layer loading.
+
+ * src/sfnt/ttcolr.c (Colr): Add `table_size' field.
+ (tt_face_load_colr): Set it.
+ (tt_face_get_colr_layer): Check pointer limit for layer entries.
+
+2018-06-16 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix color palette loading.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8933
+
+ * src/sfnt/ttcpal.c (Cpal): Add `table_size' field.
+ (tt_face_load_cpal): Set it.
+ (tt_face_palette_set): Check pointer limit for color entries.
+
+2018-06-16 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftbitmap.c (FT_Bitmap_Blend): Avoid integer overflow.
+
+2018-06-16 Werner Lemberg <wl@gnu.org>
+
+ Add `FT_Bitmap_Blend' API.
+
+ Still missing: Support for negative bitmap pitch and subpixel offset
+ of source bitmap.
+
+ * include/freetype/ftbitmap.h, src/base/ftbitmap.c
+ (FT_Bitmap_Blend): New function.
+
+2018-06-14 Werner Lemberg <wl@gnu.org>
+
+ Replace `FT_Get_GlyphLayers' with `FT_Get_Color_Glyph_Layer'.
+
+ This avoids any additional allocation of COLR related structures in
+ a glyph slot.
+
+ * include/freetype/freetype.h (FT_Glyph_Layer, FT_Glyph_LayerRec,
+ FT_Get_GlyphLayers): Removed.
+
+ * include/freetype/internal/ftobjs.h (FT_Colr_InternalRec): Removed.
+ (FT_Slot_InternalRec): Remove `color_layers'.
+
+ * include/freetype/internal/sfnt.h (TT_Load_Colr_Layer_Func):
+ Removed.
+ (SFNT_Interface, FT_DEFINE_SFNT_INTERFACE): Remove
+ `load_colr_layer'.
+
+ * src/base/ftobjs.c (ft_glyph_slot_done): Updated.
+ (FT_Render_Glyph_Internal): Use `FT_Get_Color_Glyph_Layer'.
+ (FT_Get_GlyphLayers): Removed.
+
+ * src/sfnt/sfdriver.c (sfnt_interface): Updated.
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr_layers): Removed.
+ * src/sfnt/ttcolr.h: Updated.
+
+ * src/truetype/ttgload.c (TT_Load_Glyph): Updated.
+
+2018-06-14 Werner Lemberg <wl@gnu.org>
+
+ Provide iterative API to access `COLR' data.
+
+ This solution doesn't store any data in an `FT_GlyphSlot' object.
+
+ * include/freetype/freetype.h (FT_LayerIterator): New structure.
+ (FT_Get_Color_Glyph_Layer): New function.
+
+ * include/freetype/internal/sfnt.h (TT_Get_Colr_Layer_Func): New
+ function type.
+ (SFNT_Interface, FT_DEFINE_SFNT_INTERFACE): Add it.
+
+ * src/base/ftobjs.c (FT_Get_Color_Glyph_Layer): Implement it.
+
+ * src/sfnt/ttcolr.c (tt_face_get_colr_layer): New function.
+ * src/sfnt/ttcolr.h: Updated.
+
+ * src/sfnt/sfdriver.c (sfnt_interface): Updated.
+
+2018-06-14 Werner Lemberg <wl@gnu.org>
+
+ Add glyph index and glyph load flags to glyph slot.
+
+ * include/freetype/freetype.h (FT_GlyphSlotRec): Rename unused
+ `reserved' field to `glyph_index'.
+
+ * include/freetype/internal/ftobjs.h (FT_Slot_InternalRec): Add
+ `load_flags' field.
+
+ * src/base/ftobjs.c (FT_Load_Glyph): Set new fields.
+
+2018-06-14 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Move `CPAL' stuff into separate files.
+
+ * src/sfnt/sfdriver.c: Include `ttcpal.h'.
+ * src/sfnt/sfnt.c: Include `ttcpal.c'.
+
+ * src/sfnt/ttcolr.c, src/sfnt/ttcolr.h: Move CPAL stuff to ...
+ * src/sfnt/ttcpal.c, src/sfnt/ttcpal.c: ... these new files.
+
+ * src/sfnt/Jamfile (_sources), src/sfnt/rules.mk (SFNT_DRV_SRC):
+ Updated.
+
+ * include/freetype/internal/fttrace.h: Add support for `colr' and
+ `cpal'.
+ Sort entries.
+
+2018-06-13 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Separate `CPAL' and `COLR' table handling.
+
+ Later on we want to support the `SVG' table also, which needs `CPAL'
+ (but not `COLR').
+
+ * include/freetype/internal/sfnt.h (SFNT_Interface): Add `load_cpal'
+ and `free_cpal' fields.
+ (FT_DEFINE_SFNT_INTERFACE): Updated.
+
+ * include/freetype/internal/tttypes.h (TT_FaceRec): Replace
+ `colr_and_cpal' fields with `cpal' and `colr'.
+
+ * src/sfnt/sfdriver.c (sfnt_interface): Updated.
+
+ * src/sfnt/sfobjs.c (sfnt_load_face, sfnt_done_face): Updated.
+
+ * src/sfnt/ttcolr.c (Colr, Cpal): Add `table' field.
+ (ColrCpal): Removed.
+ (tt_face_load_colr): Split off CPAL handling into...
+ (tt_face_load_cpal): ... this new function.
+ (tt_face_free_colr): Split off CPAL handling into...
+ (tt_face_free_cpal): ... this new function.
+ (tt_face_load_colr_layers, tt_face_palette_set): Updated.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+ * src/truetype/ttgload.c (TT_Load_Glyph): Updated.
+
+2018-06-12 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix `sizeof' thinko.
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr, tt_face_palette_set): Don't
+ use `sizeof' for computing array limit.
+
+2018-06-12 Werner Lemberg <wl@gnu.org>
+
+ Finish CPAL/COLR support (4/4).
+
+ * src/sfnt/ttcolr.c (tt_face_find_color): Removed.
+ (tt_face_colr_blend_layer): Use `face->palette' instead of calling
+ `tt_face_find_color'.
+ Use and set text foreground color.
+
+2018-06-12 Werner Lemberg <wl@gnu.org>
+
+ Finish CPAL/COLR support (3/4).
+
+ * src/base/ftcolor.c: Include FT_INTERNAL_SFNT_H.
+ (FT_Palette_Select, FT_Palette_Set_Foreground_Color): Implement
+ functions.
+
+2018-06-12 Werner Lemberg <wl@gnu.org>
+
+ Finish CPAL/COLR support (2/4).
+
+ * src/sfnt/ttcolr.c (tt_face_palette_set): New function.
+ (tt_face_load_colr): Allocate `face->palette' and call
+ `tt_face_palette_set'.
+ Adjust return error code in case of error.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+ * include/freetype/internal/sfnt.h (TT_Set_Palette_Func): New
+ function type.
+ (SFNT_Interface, FT_DEFINE_SFNT_INTERFACE): Add it.
+
+ * src/sfnt/sfdriver.c (sfnt_interface), src/sfnt/sfobjs.c
+ (sfnt_done_face): Updated.
+
+2018-06-12 Werner Lemberg <wl@gnu.org>
+
+ Finish CPAL/COLR support (1/4).
+
+ * include/freetype/internal/tttypes.h (TT_FaceRec): New fields
+ `palette_index', `palette', `have_foreground_color' and
+ `foreground_color'.
+
+2018-06-12 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Minor.
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr_layers):
+ s/palette_index/palette_entry_index/ for consistency.
+ Adjust return error code in case of error.
+
+2018-06-11 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Clean up.
+
+ * src/raster/ftraster.c (black_TWorker, SCALED, Set_High_Precision):
+ Clean up after 5-level gray removal (8dc8635874).
+ (Vertical_Sweep_Span): Be brief.
+
+2018-06-10 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix compiler warnings.
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr, tt_face_load_colr_layers,
+ tt_face_colr_blend_layer): Add `NULL' initializers.
+
+2018-06-10 Werner Lemberg <wl@gnu.org>
+
+ s/FT_Palette/FT_Palette_Data/, s/palette/palette_data/.
+
+ * include/freetype/ftcolor.h, include/freetype/internal/tttypes.h,
+ src/base/ftcolor.c, src/sfnt/sfobjs.c, src/sfnt/ttcolr.c: Updated.
+
+2018-06-10 Nikolaus Waxweiler <madigens@gmail.com>
+
+ CMakeLists: also accept IOS_PLATFORM=SIMULATOR64
+
+ This might be needed to build FreeType for the iOS simulator. See
+ https://savannah.nongnu.org/bugs/index.php?54048. Patch contributed
+ by Steve Robinson.
+
+ * CMakeLists.txt: Accept IOS_PLATFORM=SIMULATOR64
+
+2018-06-10 Werner Lemberg <wl@gnu.org>
+
+ Implement `FT_Palette_Get'.
+
+ * src/base/ftcolor.c: New file.
+
+ * src/base/Jamefile (_sources), src/base/rules.mk (BASE_SRC),
+ src/base/ftbase.c: Add `ftcolor.c'.
+
+2018-06-10 Werner Lemberg <wl@gnu.org>
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr): Improve overflow checks.
+
+2018-06-09 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [raster] Deal with pitch sign earlier.
+
+ * src/raster/ftraster.c (black_TWorker): Remove unused `traceG',
+ s/bTarget/bOrigin/.
+ (Render_Glyph): Set `ras.bOrigin' at the bottom-left corner.
+ (Vertical_Sweep_Init, {Vertical,Horizontal}_Sweep_{Span,Drop}):
+ Updated accordingly.
+
+2018-06-09 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Read `CPAL' version 1 tables.
+
+ * include/freetype/internal.tttypes.h: Include FT_COLOR_H.
+ (TT_FaceRec): Add `palette' field.
+
+ * src/sfnt/ttcolr.c: Include FT_COLOR_H.
+ (Cpal): Remove all data covered by the new `palette' field in
+ `TT_FaceRec'.
+ (tt_face_load_colr): Updated.
+ Read `CPAL' version 1 data.
+ (tt_face_load_colr_layers, tt_face_find_color): Updated.
+
+ * src/sfnt/sfobjs.c (sfnt_done_face): Free glyph color palette data.
+
+2018-06-07 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] API for Harmony LCD rendering.
+
+ This introduces `FT_Library_SetLcdGeometry' for setting up arbitrary
+ LCD subpixel geometry including non-striped patterns.
+
+ * src/base/ftlcdfil.c (FT_Library_SetLcdGeometry): New function.
+ * include/freetype/ftlcdfil.h: Document it.
+ * include/freetype/freetype.h: Minor.
+ * include/freetype/ftchapters.h: Minor.
+
+2018-06-06 Werner Lemberg <wl@gnu.org>
+
+ ftcolor.h: Redesign API.
+
+ While going to implement it I noticed that I need access to most of
+ the `CPAL' elements; I thus plan to add a `cpal' field to
+ `TT_FaceRec', which makes most of the previously suggested API
+ functions obsolete because the fields will be directly accessible.
+
+2018-06-06 Parth Wazurkar <parthwazurkar@gmail.com>
+
+ [bdf, pcf] Remove deprecated FT_FACE_FLAG_FAST_GLYPHS flag.
+
+ * src/bdf/bdfdrivr.c (BDF_Face_Init): Remove deprecated
+ FT_FACE_FLAG_FAST_GLYPHS flag.
+
+ * src/pcf/pcfread.c (pcf_load_font): Remove deprecated
+ FT_FACE_FLAG_FAST_GLYPHS flag.
+
+2018-06-06 Werner Lemberg <wl@gnu.org>
+
+ [smooth, raster] Limit bitmap size (#54019).
+
+ * src/raster/ftraster.c [STANDALONE] (FT_Outline_Get_CBox): Add
+ function.
+ [!STANDALONE]: Include FT_OUTLINE_H.
+ (ft_black_render): Compute CBox and reject glyphs larger than
+ 0xFFFF x 0xFFFF.
+
+ * src/smooth/ftgrays.c (gray_raster_render): Reject glyphs larger
+ than 0xFFFF x 0xFFFF.
+
+2018-06-03 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ * src/smooth/ftgrays.c (gray_convert_glyph): Remove unused variables.
+
+2018-06-03 Werner Lemberg <wl@gnu.org>
+
+ * src/tools/glnames.py (main): Emit header in `light' comment style.
+
+2018-06-02 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Attempt to mitigate bug #54019.
+
+ The robust rendering of estra large glyphs came with unbearable cost.
+ The old way of bisecting should fail but fail faster.
+
+ * src/smooth/ftgrays.c (gray_convert_glyph): Switch back to bisecting
+ in y-direction.
+
+2018-06-02 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttinterp.c (Ins_MIRP): Use SUB_LONG; avoid FT_ABS.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8706
+
+2018-06-02 Werner Lemberg <wl@gnu.org>
+
+ * src/autofit/afwarp.h: Use AF_CONFIG_OPTION_USE_WARPER (#54033).
+
+2018-05-31 Werner Lemberg <wl@gnu.org>
+
+ * src/raster/ftraster.c (black_TWorker_): Remove `gTarget' field.
+
+ This is no longer used.
+
+2018-05-31 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Get colors from `CPAL' table in right order (#54015).
+
+ * src/sfnt/ttcolr.c (tt_face_find_color): Fix it.
+
+2018-05-30 Werner Lemberg <wl@gnu.org>
+
+ ftcolor.h: Improve API design, fix typos (#54011, #54014).
+
+ * include/freetype/ftcolor.h (FT_Palette_Get_Names): Replace with...
+ (FT_Palette_Get_Name_IDs): ... this function.
+ (FT_Palette_Get_Entry_Names): Replace with...
+ (FT_Palette_Get_Entry_Name_IDs): ... this function
+ s/FT_Palette_Set_Foreground_COlor/FT_Palette_Set_Foreground_Color/.
+
+2018-05-30 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ Beautify a3cfed5e87232c933bdc64f43e8ebebcfd18b41b.
+
+ * src/autofit/afloader.c (af_loader_load_glyph): Move the
+ initialisationand declaration of variables into the if-block.
+
+2018-05-30 Armin Hasitzka <prince.cherusker@gmail.com>
+
+ Fix pointer underflow.
+
+ The declaration of `edge2' can be reached with `edge1 == NULL' and
+ `axis->edges == 0' which results in undefined behaviour.
+
+ * src/autofit/afloader.c (af_loader_load_glyph): Initialise `edge2'
+ after checking `axis->num_edges > 1'. `edge1 != NULL' can be assumed.
+
+2018-05-30 Werner Lemberg <wl@gnu.org>
+
+ Various minor color fixes.
+
+ * include/freetype/config/ftheader.h (FT_COLOR_H): New macro.
+
+ * include/freetype/internal/ftobjs.h (FT_Colr_Internal): Change
+ type of `load_flags' to `FT_Int32'.
+
+ * include/freetype/internal/sfnt.h (TT_Load_Colr_Layer_Func): Change
+ type of `idx' to `FT_UInt'.
+ (TT_Blend_Colr_Func): Change type of `color_index' to `FT_UInt'.
+
+ * src/base/ftobjs.c (FT_Render_Glyph_Internal): Change type of
+ `load_flags' to `FT_Int32'.
+
+ * src/sfnt/ttcolr.c (find_base_glyph_record,
+ tt_face_load_colr_layers): Change type of `glyph_id' to `FT_UInt'.
+ (tt_face_find_color, tt_face_colr_blend_layer): Change type of
+ `color_index' to `FT_UInt'.
+ Fix signedness and type issues.
+
+ * src/sfnt/ttcolr.h: Updated.
+
+2018-05-25 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
+
+ [docmaker] Fix missing `Defined in (...)' under Windows/Cygwin.
+
+ This platform uses backslashes for paths, which docmaker didn't
+ understand correctly.
+
+ * src/tools/docmaker/tohtml.py (HtmlFormatter::blockEnter): Use
+ `os.path.normpath' to normalize the path for the platform being
+ used.
+
+2018-05-24 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [smooth] Formalize Harmony LCD rendering.
+
+ This generalizes magic outline shifts that make Harmony LCD
+ rendering work in terms of precise two-dimensional RGB subpixel
+ positions. These coordinates are now set in time of the `smooth'
+ module initialization and later used to shift a glyph outline for
+ rendering. FT_RENDER_MODE_LCD and FT_RENDER_MODE_LCD_V use the same
+ coordinates. The letter, however, rotates them before using.
+ The LCD bitmap padding is also calculated using these coordinates.
+
+ * include/freetype/internal/ftobjs.h (FT_LibraryRec): New array field
+ `lcd_geometry'.
+ * src/base/ftlcdfil.c (ft_lcd_padding): Reworked.
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): Updated accordingly.
+
+ * src/smooth/ftsmooth.c [!FT_CONFIG_OPTION_SUBPIXEL_RENDERING]
+ (ft_smooth_init): Initialize `lcd_geometry'.
+ (ft_smooth_render_generic): Formalize outline shifts.
+
+2018-05-22 Werner Lemberg <wl@gnu.org>
+
+ [truetype] Reject elements of composites with invalid glyph indices.
+
+ Reported as
+
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8413
+
+ * src/truetype/ttgload.c (TT_Load_Composite_Glyph): Implement it.
+
+2018-05-22 Werner Lemberg <wl@gnu.org>
+
+ * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Trace # of points.
+
+2018-05-20 Werner Lemberg <wl@gnu.org>
+
+ * include/freetype/ftcolor.h: New file.
+
+ This is an interface to the `CPAL' OpenType table. No
+ implementation yet.
+
+2018-05-18 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ * include/freetype/internal/ftcalc.h (FT_MSB): Verified `_MSC_VER'.
+
+ Actually `_BitScanReverse' is available since VS2005.
+
+2018-05-18 Werner Lemberg <wl@gnu.org>
+
+ * include/freetype/internal/ftcalc.h (FT_MSB): Use `_MSC_VER' value.
+
+ Older VC versions don't provide `_BitScanReverse'. We test for VC
+ 2013.
+
+ Reported by John Emmas <john@creativepost.co.uk>.
+
+2018-05-17 Werner Lemberg <wl@gnu.org>
+
+ s/inline/__inline/ for MSVC.
+
+ Reported by John Emmas <john@creativepost.co.uk>.
+
+ * include/freetype/internal/ftcalc.h (FT_MSB) [_MSC_VER]: Do it.
+
+2018-05-16 Werner Lemberg <wl@gnu.org>
+
+ Add function `FT_Get_GlyphLayers' to access `COLR' table data.
+
+ * include/freetype/internal/ftobjs.h (FT_Glyph_LayerRec): Move this
+ structure to...
+ * include/freetype/freetype.h (FT_Glyph_LayerRec): ... this
+ header file.
+ (FT_Glyph_Layer): New typedef.
+ Update code to use it where appropriate.
+
+ * src/base/ftobjs.c (FT_Get_GlyphLayers): New function.
+
+2018-05-15 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [base] Fix mono bitmap presetting (#53896).
+
+ It is rather fundamental to set monochrome bitmap based on rounded
+ CBox because the b/w rasterizer turns on pixels when their centers are
+ inside the glyph outline. The dropout control is unpredictable and can
+ distort narrow glyphs if the bitmap is too wide.
+
+ Reported by Chris Liddell.
+
+ * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): If BBox boundaries
+ are too close, adjust them before rounding.
+
+2018-05-15 Werner Lemberg <wl@gnu.org>
+
+ [psaux] Fix compiler warning (#53915).
+
+ * src/psaux/psft.c (cf2_freeT1SeacComponent): Do it.
+
+2018-05-15 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Fix memory leak in handling `COLR' data.
+
+ * src/truetype/ttgload.c (TT_Load_Glyph): Free old `layers' array
+ before reassigning allocated memory.
+ Only allocate `color_layers' if we don't have one already.
+
+2018-05-15 Werner Lemberg <wl@gnu.org>
+
+ [sfnt] If `COLR' is present, don't assume that all glyphs use it.
+
+ * src/sfnt/ttcolr.c (tt_face_load_colr_layers): Return FT_Err_Ok if
+ current glyph is not a `COLR' base glyph.
+
+ * src/truetype/ttgload.c (TT_Load_Glyph): Don't allocate
+ `color_layers' if there are no color layers.
+
+2018-05-14 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftobjs.c (FT_Load_Glyph): Fix signature of `pixel_modes'.
+
+2018-05-14 Werner Lemberg <wl@gnu.org>
+
+ Provide dummy functions if `TT_CONFIG_OPTION_SFNT_NAMES' is not set.
+
+ * src/base/ftsnames.c [!TT_CONFIG_OPTION_SFNT_NAMES]: Implement it.
+
+2018-05-13 Werner Lemberg <wl@gnu.org>
+
+ * src/base/ftobjs.c (FT_Load_Glyph): Improve tracing.
+
+2018-05-13 Shao Yu Zhang <shaozhang@fb.com>
+ Werner Lemberg <wl@gnu.org>
+
+ [sfnt] Preliminary support of colored layer outlines (#44689).
+
+ This commit enables OpenType's COLR/CPAL table handling; a typical
+ application are color emojis that can be scaled to any size.
+
+ If the color palette does not exist or is invalid, the rendering
+ step rasterizes the outline instead. The current implementation
+ assumes that the foreground is black.
+
+ Enable this by defining option TT_CONFIG_OPTION_COLOR_LAYERS.
+
+ There are still some issues with metrics; additionally, an API to
+ fetch color layers is missing.
+
+ * devel/ftoption.h, include/freetype/config/ftoption.h
+ (TT_CONFIG_OPTION_COLOR_LAYERS): New macro.
+
+ * include/freetype/internal/ftobjs.h (FT_Glyph_LayerRec,
+ FT_Colr_InternalRec): New structures.
+ (FT_Slot_InternalRec): Add `color_layers' field.
+
+ * include/freetype/internal/sfnt.h (TT_Load_Colr_Layer_Func,
+ TT_Blend_Colr_Func): New function types.
+ (SFNT_Interface): Add `load_colr', `free_colr', `load_colr_layer',
+ and `colr_blend' fields.
+
+ * include/freetype/internal/tttypes.h (TT_FaceRec): Add
+ `colr_and_cpal' field.
+
+ * include/freetype/internal/tttags. (TTAG_COLR, TTAG_CPAL): New
+ macros.
+
+ * src/sfnt/ttcolr.c, src/sfnt/ttcolr.h: New files.
+
+ * src/base/ftobjs.c (ft_glyphslot_done, FT_Render_Glyph_Internal):
+ Handle glyph color layers.
+
+ * src/sfnt/Jamfile (_sources), src/sfnt/rules.mk (SFNT_DRV_SRC): Add
+ `ttcolr.c'.
+
+ * src/sfnt/sfdriver.c: Include `ttcolr.h'.
+ (PUT_COLOR_LAYERS): New macro.
+ Update call to `FT_DEFINE_SFNT_INTERFACE'.
+
+ * src/sfnt/sfnt.c: Include `ttcolr.c'.
+
+ * src/sfnt/sfobjs.c (sfnt_load_face): Load `COLR' and `CPAL' tables.
+ (sfnt_done_face): Updated.
+
+ * src/truetype/ttgload.c (TT_Load_Glyph): Handle color layers.
+
+2018-05-12 Arkady Shapkin <arkady.shapkin@gmail.com>
+
+ Use MS VC++'s _BitScanReverse to calculate MSB (patch #9636).
+
+ * include/freetype/internal/ftcalc.h (FT_MSB) [_MSC_VER]: Implement
+ it.
+
+2018-05-10 Alan Coopersmith <alan.coopersmith@oracle.com>
+
+ Fix DLL compilation on Solaris.
+
+ AC_COMPILE_IFELSE only tries to compile a `*.c' to a `*.o'. The
+ Solaris Studio 12.1 through 12.5 compilers see the
+ `-fvisibility=hidden' flag, but ignore it with a warning of:
+
+ cc: Warning: Option -fvisibility=hidden passed to ld,
+ if ld is invoked, ignored otherwise
+
+ AC_LINK_IFELSE does the compile and then tries to link the result,
+ at which point the Solaris linker will issue an error:
+
+ ld: fatal: option '-fvisibility=hidden' is incompatible with
+ building a dynamic executable
+
+ If we don't use AC_LINK_IFELSE to catch the error, then configure
+ will fail further tests which attempt to link, such as those testing
+ dependencies like `libbz2'.
+
+ Also, don't try adding `-fvisibility' if we have already added
+ `-xldscope', just use one of them, since Sun Studio 12 and earlier
+ compilers only issue a warning, and don't try passing through to the
+ linker to generate an error, so AC_LINK_IFELSE doesn't catch them.
+
+ Tested on Solaris 11.4 beta with compiler versions:
+
+ Sun Studio 8 (Sun C 5.5)
+ Sun Studio 10 (Sun C 5.7)
+ Sun Studio 11 (Sun C 5.8)
+ Sun Studio 12 (Sun C 5.9)
+ Sun Studio 12.1 (Sun C 5.10)
+ Oracle Solaris Studio 12.2 (Sun C 5.11)
+ Oracle Solaris Studio 12.3 (Sun C 5.12)
+ Oracle Solaris Studio 12.4 (Sun C 5.13)
+ Oracle Developer Studio 12.5 (Sun C 5.14)
+ Oracle Developer Studio 12.6 (Sun C 5.15)
+ gcc 5.5.0
+ gcc 7.3.0
+
+ and verified the libfreetype.so.6 generated by each of those
+ compilers exported the same set of symbols.
+
+ * builds/unix/configure.raw: Implement it.
+
+2018-05-08 Werner Lemberg <wl@gnu.org>
+
+ [autofit] Avoid potential SEGV if running out of memory.
+
+ Problem reported by Shailesh Mistry <shailesh.mistry@hotmail.co.uk>.
+
+ * src/autofit/afshaper.c (af_shaper_buf_create,
+ af_shaper_buf_destroy) [!FT_CONFIG_OPTION_USE_HARFBUZZ]: Don't
+ allocate and free a four-byte buffer. Instead, make those functions
+ no-ops; the calling functions will provide a pointer to a buffer
+ instead.
+
+ * src/autofit/afcjk.c (af_cjk_metrics_init_widths,
+ af_cjk_metrics_init_blues, af_cjk_metrics_check_digits),
+ src/autofit/aflatin.c (af_latin_metrics_init_widths,
+ af_latin_metrics_init_blues, af_latin_metrics_check_digits)
+ [!FT_CONFIG_OPTION_USE_HARFBUZZ]: Use pointer to local variable for
+ `shaper_buf'.
+
+2018-05-07 Nikolaus Waxweiler <madigens@gmail.com>
+
+ [cmake] Allow using project as subfolder in other project.
+
+ * CMakeLists.txt: Test for CMake build directory being different
+ from source directory. Provide other parts of the build system
+ access the full include directory.
+
+2018-05-07 Werner Lemberg <wl@gnu.org>
+
+ [build] Suppress configure's `nothing to be done' message.
+
+ This is due to calling the configure script via `make' (within the
+ top-level `configure' wrapper script). The same can happen for all
+ other secondary make targets that are used to only modify the
+ primary one, e.g., `make setup devel'.
+
+ * builds/dos/detect.mk (emx, turboc, watcom, borlandc, borlandc16),
+ builds/os2/detect (visualage, watcom, borlandc, devel),
+ builds/unix/detect.mk (devel, lcc, unix), builds/windows/detect.mk
+ (visualc, watcom, visualage, lcc, mingw32, bcc32, devel-bcc,
+ devel-gcc): Use no-op recipe.
+
+2018-05-04 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+
+ Support symbol visibility features of Sun / Oracle C compilers.
+
+ Reported by Kiyoshi Kanazawa:
+ https://lists.gnu.org/archive/html/freetype-devel/2018-05/msg00008.html
+ Thanks to the suggestions by Alexei and Alan Coopersmith.
+
+ * builds/unix/configure.raw: Check if "-xldscope=hidden" is
+ accepted, and if so, it is added to CFLAGS. This is the option
+ making Sun / Oracle C compilers hide the symbols from global
+ scope.
+ * include/freetype/config/ftconfig.h: Use "__global" prefix
+ for FT_EXPORT() macro, if SunPro C is newer than Sun ONE
+ Studio 8 (2003).
+ * builds/unix/ftconfig.in: Ditto.
+ * builds/vms/ftconfig.h: Ditto.
+
+2018-05-02 Nikolaus Waxweiler <madigens@gmail.com>
+
+ Unbreak CMake Windows installation
+
+ * CMakeLists.txt: Generate ftconfig.h on non-UNIX.
+
+2018-05-02 Werner Lemberg <wl@gnu.org>
+
+ Remove FT_CONFIG_OPTION_PIC and related code.
+
+ */* [FT_CONFIG_OPTION_PIC]: Remove all code guarded by this
+ preprocessor symbol.
+
+ */*: Replace `XXX_GET' macros (which could be either a function in
+ PIC mode or an array in non-PIC mode) with `xxx' arrays.
+
+ * include/freetype/internal/ftpic.h, src/autofit/afpic.c,
+ src/autofit/afpic.h, src/base/basepic.c, src/base/basepic.h,
+ src/base/ftpic.c, src/cff/cffpic.c, src/cff/cffpic.h,
+ src/pshinter/pshpic.c, src/pshinter/pshpic.h, src/psnames/pspic.c,
+ src/psnames/pspic.h, src/raster/rastpic.c, src/raster/rastpic.h,
+ src/sfnt/sfntpic.c, src/sfnt/sfntpic.h, src/smooth/ftspic.c,
+ src/smooth/ftspic.h, src/truetype/ttpic.c, src/truetype/ttpic.h:
+ Removed.
+
+
+----------------------------------------------------------------------------
+
+Copyright (C) 2018-2021 by
+David Turner, Robert Wilhelm, and Werner Lemberg.
+
+This file is part of the FreeType project, and may only be used, modified,
+and distributed under the terms of the FreeType project license,
+LICENSE.TXT. By continuing to use, modify, or distribute this file you
+indicate that you have read the license and understand and accept it
+fully.
+
+
+Local Variables:
+version-control: never
+coding: utf-8
+End:
diff --git a/Client/ThirdParty/freetype/FTL.TXT b/Client/ThirdParty/freetype/FTL.TXT
new file mode 100644
index 0000000..c406d15
--- /dev/null
+++ b/Client/ThirdParty/freetype/FTL.TXT
@@ -0,0 +1,169 @@
+ The FreeType Project LICENSE
+ ----------------------------
+
+ 2006-Jan-27
+
+ Copyright 1996-2002, 2006 by
+ David Turner, Robert Wilhelm, and Werner Lemberg
+
+
+
+Introduction
+============
+
+ The FreeType Project is distributed in several archive packages;
+ some of them may contain, in addition to the FreeType font engine,
+ various tools and contributions which rely on, or relate to, the
+ FreeType Project.
+
+ This license applies to all files found in such packages, and
+ which do not fall under their own explicit license. The license
+ affects thus the FreeType font engine, the test programs,
+ documentation and makefiles, at the very least.
+
+ This license was inspired by the BSD, Artistic, and IJG
+ (Independent JPEG Group) licenses, which all encourage inclusion
+ and use of free software in commercial and freeware products
+ alike. As a consequence, its main points are that:
+
+ o We don't promise that this software works. However, we will be
+ interested in any kind of bug reports. (`as is' distribution)
+
+ o You can use this software for whatever you want, in parts or
+ full form, without having to pay us. (`royalty-free' usage)
+
+ o You may not pretend that you wrote this software. If you use
+ it, or only parts of it, in a program, you must acknowledge
+ somewhere in your documentation that you have used the
+ FreeType code. (`credits')
+
+ We specifically permit and encourage the inclusion of this
+ software, with or without modifications, in commercial products.
+ We disclaim all warranties covering The FreeType Project and
+ assume no liability related to The FreeType Project.
+
+
+ Finally, many people asked us for a preferred form for a
+ credit/disclaimer to use in compliance with this license. We thus
+ encourage you to use the following text:
+
+ """
+ Portions of this software are copyright © <year> The FreeType
+ Project (www.freetype.org). All rights reserved.
+ """
+
+ Please replace <year> with the value from the FreeType version you
+ actually use.
+
+
+Legal Terms
+===========
+
+0. Definitions
+--------------
+
+ Throughout this license, the terms `package', `FreeType Project',
+ and `FreeType archive' refer to the set of files originally
+ distributed by the authors (David Turner, Robert Wilhelm, and
+ Werner Lemberg) as the `FreeType Project', be they named as alpha,
+ beta or final release.
+
+ `You' refers to the licensee, or person using the project, where
+ `using' is a generic term including compiling the project's source
+ code as well as linking it to form a `program' or `executable'.
+ This program is referred to as `a program using the FreeType
+ engine'.
+
+ This license applies to all files distributed in the original
+ FreeType Project, including all source code, binaries and
+ documentation, unless otherwise stated in the file in its
+ original, unmodified form as distributed in the original archive.
+ If you are unsure whether or not a particular file is covered by
+ this license, you must contact us to verify this.
+
+ The FreeType Project is copyright (C) 1996-2000 by David Turner,
+ Robert Wilhelm, and Werner Lemberg. All rights reserved except as
+ specified below.
+
+1. No Warranty
+--------------
+
+ THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO
+ USE, OF THE FREETYPE PROJECT.
+
+2. Redistribution
+-----------------
+
+ This license grants a worldwide, royalty-free, perpetual and
+ irrevocable right and license to use, execute, perform, compile,
+ display, copy, create derivative works of, distribute and
+ sublicense the FreeType Project (in both source and object code
+ forms) and derivative works thereof for any purpose; and to
+ authorize others to exercise some or all of the rights granted
+ herein, subject to the following conditions:
+
+ o Redistribution of source code must retain this license file
+ (`FTL.TXT') unaltered; any additions, deletions or changes to
+ the original files must be clearly indicated in accompanying
+ documentation. The copyright notices of the unaltered,
+ original files must be preserved in all copies of source
+ files.
+
+ o Redistribution in binary form must provide a disclaimer that
+ states that the software is based in part of the work of the
+ FreeType Team, in the distribution documentation. We also
+ encourage you to put an URL to the FreeType web page in your
+ documentation, though this isn't mandatory.
+
+ These conditions apply to any software derived from or based on
+ the FreeType Project, not just the unmodified files. If you use
+ our work, you must acknowledge us. However, no fee need be paid
+ to us.
+
+3. Advertising
+--------------
+
+ Neither the FreeType authors and contributors nor you shall use
+ the name of the other for commercial, advertising, or promotional
+ purposes without specific prior written permission.
+
+ We suggest, but do not require, that you use one or more of the
+ following phrases to refer to this software in your documentation
+ or advertising materials: `FreeType Project', `FreeType Engine',
+ `FreeType library', or `FreeType Distribution'.
+
+ As you have not signed this license, you are not required to
+ accept it. However, as the FreeType Project is copyrighted
+ material, only this license, or another one contracted with the
+ authors, grants you the right to use, distribute, and modify it.
+ Therefore, by using, distributing, or modifying the FreeType
+ Project, you indicate that you understand and accept all the terms
+ of this license.
+
+4. Contacts
+-----------
+
+ There are two mailing lists related to FreeType:
+
+ o freetype@nongnu.org
+
+ Discusses general use and applications of FreeType, as well as
+ future and wanted additions to the library and distribution.
+ If you are looking for support, start in this list if you
+ haven't found anything to help you in the documentation.
+
+ o freetype-devel@nongnu.org
+
+ Discusses bugs, as well as engine internals, design issues,
+ specific licenses, porting, etc.
+
+ Our home page can be found at
+
+ https://www.freetype.org
+
+
+--- end of FTL.TXT ---
diff --git a/Client/ThirdParty/freetype/GPLv2.TXT b/Client/ThirdParty/freetype/GPLv2.TXT
new file mode 100644
index 0000000..b2fe7b6
--- /dev/null
+++ b/Client/ThirdParty/freetype/GPLv2.TXT
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Client/ThirdParty/freetype/LICENSE.TXT b/Client/ThirdParty/freetype/LICENSE.TXT
new file mode 100644
index 0000000..b1def65
--- /dev/null
+++ b/Client/ThirdParty/freetype/LICENSE.TXT
@@ -0,0 +1,42 @@
+FREETYPE LICENSES
+-----------------
+
+The FreeType 2 font engine is copyrighted work and cannot be used
+legally without a software license. In order to make this project
+usable to a vast majority of developers, we distribute it under two
+mutually exclusive open-source licenses.
+
+This means that *you* must choose *one* of the two licenses described
+below, then obey all its terms and conditions when using FreeType 2 in
+any of your projects or products.
+
+ - The FreeType License, found in the file `docs/FTL.TXT`, which is
+ similar to the original BSD license *with* an advertising clause
+ that forces you to explicitly cite the FreeType project in your
+ product's documentation. All details are in the license file.
+ This license is suited to products which don't use the GNU General
+ Public License.
+
+ Note that this license is compatible to the GNU General Public
+ License version 3, but not version 2.
+
+ - The GNU General Public License version 2, found in
+ `docs/GPLv2.TXT` (any later version can be used also), for
+ programs which already use the GPL. Note that the FTL is
+ incompatible with GPLv2 due to its advertisement clause.
+
+The contributed BDF and PCF drivers come with a license similar to
+that of the X Window System. It is compatible to the above two
+licenses (see files `src/bdf/README` and `src/pcf/README`). The same
+holds for the source code files `src/base/fthash.c` and
+`include/freetype/internal/fthash.h`; they wer part of the BDF driver
+in earlier FreeType versions.
+
+The gzip module uses the zlib license (see `src/gzip/zlib.h`) which
+too is compatible to the above two licenses.
+
+The MD5 checksum support (only used for debugging in development
+builds) is in the public domain.
+
+
+--- end of LICENSE.TXT ---
diff --git a/Client/ThirdParty/freetype/README.md b/Client/ThirdParty/freetype/README.md
new file mode 100644
index 0000000..2bbe154
--- /dev/null
+++ b/Client/ThirdParty/freetype/README.md
@@ -0,0 +1,23 @@
+FreeType 2.11.0
+=========================
+###### FreeType Windows libraries (win32/win64)
+Compiled with VS Express 2017 (SDK 10.0.19041.0)
+> The *freetype* libraries use the *Universal CRT* and therefore **_requires_** Visual C++ 2015-2019 Redistributable to be present on system.
+###### Supported operating systems
+- Windows 10 version 1507 or higher
+- Windows Server 2016
+- Windows 8.1
+- Windows Server 2012 R2
+- Windows 7 SP1
+###### Hash values for DLL files
+| filename | sha256 |
+| :-- | :-- |
+| release dll\\win32\\**freetype.dll** | `74359C9397A2E9B258BA874176B6727ADF6220B6ADD2863C434D92943A453345` |
+| release dll\\win32\\**freetype.lib** | `FF9793CBBF37BA7B945B06156244697B416449D758903CCEC9CBF4A3B2BB5C0D` |
+| release dll\\win64\\**freetype.dll** | `317DC3F85F2D0632F832F774E30D5FA15E9DA02F3C28ADC1DD96A708F1B11887` |
+| release dll\\win64\\**freetype.lib** | `E016F8AFA960DA588269AB9786DB7B5A670A1CCD767606CBBF74056ACE33ABF5` |
+###### Hash values for static library files
+| filename | sha256 |
+| :-- | :-- |
+| release static\\vs2015-2019\\win32\\**freetype.lib** | `6E4DEAAC7E8BB5E34F932D22C4F43446BD8EBC5B9C4159CE5A9AF5BC197B7AB8` |
+| release static\\vs2015-2019\\win64\\**freetype.lib** | `70500CA574A5E226E0927248E76AB7D357B79829F0898842D617CEE62FE77D6C` |
diff --git a/Client/ThirdParty/freetype/include/freetype/config/ftconfig.h b/Client/ThirdParty/freetype/include/freetype/config/ftconfig.h
new file mode 100644
index 0000000..65effcb
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/ftconfig.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+ *
+ * ftconfig.h
+ *
+ * ANSI-specific configuration file (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This header file contains a number of macro definitions that are used by
+ * the rest of the engine. Most of the macros here are automatically
+ * determined at compile time, and you should not need to change it to port
+ * FreeType, except to compile the library with a non-ANSI compiler.
+ *
+ * Note however that if some specific modifications are needed, we advise
+ * you to place a modified copy in your build directory.
+ *
+ * The build directory is usually `builds/<system>`, and contains
+ * system-specific files that are always included first when building the
+ * library.
+ *
+ * This ANSI version should stay in `include/config/`.
+ *
+ */
+
+#ifndef FTCONFIG_H_
+#define FTCONFIG_H_
+
+#include <ft2build.h>
+#include FT_CONFIG_OPTIONS_H
+#include FT_CONFIG_STANDARD_LIBRARY_H
+
+#include <freetype/config/integer-types.h>
+#include <freetype/config/public-macros.h>
+#include <freetype/config/mac-support.h>
+
+#endif /* FTCONFIG_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/ftheader.h b/Client/ThirdParty/freetype/include/freetype/config/ftheader.h
new file mode 100644
index 0000000..e46d314
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/ftheader.h
@@ -0,0 +1,824 @@
+/****************************************************************************
+ *
+ * ftheader.h
+ *
+ * Build macros of the FreeType 2 library.
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#ifndef FTHEADER_H_
+#define FTHEADER_H_
+
+
+ /*@***********************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_BEGIN_HEADER */
+ /* */
+ /* <Description> */
+ /* This macro is used in association with @FT_END_HEADER in header */
+ /* files to ensure that the declarations within are properly */
+ /* encapsulated in an `extern "C" { .. }` block when included from a */
+ /* C++ compiler. */
+ /* */
+#ifndef FT_BEGIN_HEADER
+# ifdef __cplusplus
+# define FT_BEGIN_HEADER extern "C" {
+# else
+# define FT_BEGIN_HEADER /* nothing */
+# endif
+#endif
+
+
+ /*@***********************************************************************/
+ /* */
+ /* <Macro> */
+ /* FT_END_HEADER */
+ /* */
+ /* <Description> */
+ /* This macro is used in association with @FT_BEGIN_HEADER in header */
+ /* files to ensure that the declarations within are properly */
+ /* encapsulated in an `extern "C" { .. }` block when included from a */
+ /* C++ compiler. */
+ /* */
+#ifndef FT_END_HEADER
+# ifdef __cplusplus
+# define FT_END_HEADER }
+# else
+# define FT_END_HEADER /* nothing */
+# endif
+#endif
+
+
+ /**************************************************************************
+ *
+ * Aliases for the FreeType 2 public and configuration files.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @section:
+ * header_file_macros
+ *
+ * @title:
+ * Header File Macros
+ *
+ * @abstract:
+ * Macro definitions used to `#include` specific header files.
+ *
+ * @description:
+ * In addition to the normal scheme of including header files like
+ *
+ * ```
+ * #include <freetype/freetype.h>
+ * #include <freetype/ftmm.h>
+ * #include <freetype/ftglyph.h>
+ * ```
+ *
+ * it is possible to used named macros instead. They can be used
+ * directly in `#include` statements as in
+ *
+ * ```
+ * #include FT_FREETYPE_H
+ * #include FT_MULTIPLE_MASTERS_H
+ * #include FT_GLYPH_H
+ * ```
+ *
+ * These macros were introduced to overcome the infamous 8.3~naming rule
+ * required by DOS (and `FT_MULTIPLE_MASTERS_H` is a lot more meaningful
+ * than `ftmm.h`).
+ *
+ */
+
+
+ /* configuration files */
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_CONFIG_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * FreeType~2 configuration data.
+ *
+ */
+#ifndef FT_CONFIG_CONFIG_H
+#define FT_CONFIG_CONFIG_H <freetype/config/ftconfig.h>
+#endif
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_STANDARD_LIBRARY_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * FreeType~2 interface to the standard C library functions.
+ *
+ */
+#ifndef FT_CONFIG_STANDARD_LIBRARY_H
+#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h>
+#endif
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_OPTIONS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * FreeType~2 project-specific configuration options.
+ *
+ */
+#ifndef FT_CONFIG_OPTIONS_H
+#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h>
+#endif
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CONFIG_MODULES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * list of FreeType~2 modules that are statically linked to new library
+ * instances in @FT_Init_FreeType.
+ *
+ */
+#ifndef FT_CONFIG_MODULES_H
+#define FT_CONFIG_MODULES_H <freetype/config/ftmodule.h>
+#endif
+
+ /* */
+
+ /* public headers */
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_FREETYPE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * base FreeType~2 API.
+ *
+ */
+#define FT_FREETYPE_H <freetype/freetype.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ERRORS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * list of FreeType~2 error codes (and messages).
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_ERRORS_H <freetype/fterrors.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_MODULE_ERRORS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * list of FreeType~2 module error offsets (and messages).
+ *
+ */
+#define FT_MODULE_ERRORS_H <freetype/ftmoderr.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_SYSTEM_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 interface to low-level operations (i.e., memory management
+ * and stream i/o).
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_SYSTEM_H <freetype/ftsystem.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IMAGE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing type
+ * definitions related to glyph images (i.e., bitmaps, outlines,
+ * scan-converter parameters).
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_IMAGE_H <freetype/ftimage.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TYPES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * basic data types defined by FreeType~2.
+ *
+ * It is included by @FT_FREETYPE_H.
+ *
+ */
+#define FT_TYPES_H <freetype/fttypes.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_LIST_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * list management API of FreeType~2.
+ *
+ * (Most applications will never need to include this file.)
+ *
+ */
+#define FT_LIST_H <freetype/ftlist.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_OUTLINE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * scalable outline management API of FreeType~2.
+ *
+ */
+#define FT_OUTLINE_H <freetype/ftoutln.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_SIZES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * API which manages multiple @FT_Size objects per face.
+ *
+ */
+#define FT_SIZES_H <freetype/ftsizes.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_MODULE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * module management API of FreeType~2.
+ *
+ */
+#define FT_MODULE_H <freetype/ftmodapi.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_RENDER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * renderer module management API of FreeType~2.
+ *
+ */
+#define FT_RENDER_H <freetype/ftrender.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_DRIVER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * structures and macros related to the driver modules.
+ *
+ */
+#define FT_DRIVER_H <freetype/ftdriver.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_AUTOHINTER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * structures and macros related to the auto-hinting module.
+ *
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
+ *
+ */
+#define FT_AUTOHINTER_H FT_DRIVER_H
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CFF_DRIVER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * structures and macros related to the CFF driver module.
+ *
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
+ *
+ */
+#define FT_CFF_DRIVER_H FT_DRIVER_H
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_DRIVER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * structures and macros related to the TrueType driver module.
+ *
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
+ *
+ */
+#define FT_TRUETYPE_DRIVER_H FT_DRIVER_H
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_PCF_DRIVER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing
+ * structures and macros related to the PCF driver module.
+ *
+ * Deprecated since version~2.9; use @FT_DRIVER_H instead.
+ *
+ */
+#define FT_PCF_DRIVER_H FT_DRIVER_H
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TYPE1_TABLES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * types and API specific to the Type~1 format.
+ *
+ */
+#define FT_TYPE1_TABLES_H <freetype/t1tables.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_IDS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * enumeration values which identify name strings, languages, encodings,
+ * etc. This file really contains a _large_ set of constant macro
+ * definitions, taken from the TrueType and OpenType specifications.
+ *
+ */
+#define FT_TRUETYPE_IDS_H <freetype/ttnameid.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_TABLES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * types and API specific to the TrueType (as well as OpenType) format.
+ *
+ */
+#define FT_TRUETYPE_TABLES_H <freetype/tttables.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TRUETYPE_TAGS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of TrueType four-byte 'tags' which identify blocks in
+ * SFNT-based font formats (i.e., TrueType and OpenType).
+ *
+ */
+#define FT_TRUETYPE_TAGS_H <freetype/tttags.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_BDF_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which accesses BDF-specific strings from a face.
+ *
+ */
+#define FT_BDF_H <freetype/ftbdf.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CID_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which access CID font information from a face.
+ *
+ */
+#define FT_CID_H <freetype/ftcid.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_GZIP_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which supports gzip-compressed files.
+ *
+ */
+#define FT_GZIP_H <freetype/ftgzip.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_LZW_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which supports LZW-compressed files.
+ *
+ */
+#define FT_LZW_H <freetype/ftlzw.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_BZIP2_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which supports bzip2-compressed files.
+ *
+ */
+#define FT_BZIP2_H <freetype/ftbzip2.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_WINFONTS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * definitions of an API which supports Windows FNT files.
+ *
+ */
+#define FT_WINFONTS_H <freetype/ftwinfnt.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_GLYPH_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * API of the optional glyph management component.
+ *
+ */
+#define FT_GLYPH_H <freetype/ftglyph.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_BITMAP_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * API of the optional bitmap conversion component.
+ *
+ */
+#define FT_BITMAP_H <freetype/ftbitmap.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_BBOX_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * API of the optional exact bounding box computation routines.
+ *
+ */
+#define FT_BBOX_H <freetype/ftbbox.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_CACHE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * API of the optional FreeType~2 cache sub-system.
+ *
+ */
+#define FT_CACHE_H <freetype/ftcache.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_MAC_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * Macintosh-specific FreeType~2 API. The latter is used to access fonts
+ * embedded in resource forks.
+ *
+ * This header file must be explicitly included by client applications
+ * compiled on the Mac (note that the base API still works though).
+ *
+ */
+#define FT_MAC_H <freetype/ftmac.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_MULTIPLE_MASTERS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * optional multiple-masters management API of FreeType~2.
+ *
+ */
+#define FT_MULTIPLE_MASTERS_H <freetype/ftmm.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_SFNT_NAMES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * optional FreeType~2 API which accesses embedded 'name' strings in
+ * SFNT-based font formats (i.e., TrueType and OpenType).
+ *
+ */
+#define FT_SFNT_NAMES_H <freetype/ftsnames.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_OPENTYPE_VALIDATE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * optional FreeType~2 API which validates OpenType tables ('BASE',
+ * 'GDEF', 'GPOS', 'GSUB', 'JSTF').
+ *
+ */
+#define FT_OPENTYPE_VALIDATE_H <freetype/ftotval.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_GX_VALIDATE_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * optional FreeType~2 API which validates TrueTypeGX/AAT tables ('feat',
+ * 'mort', 'morx', 'bsln', 'just', 'kern', 'opbd', 'trak', 'prop').
+ *
+ */
+#define FT_GX_VALIDATE_H <freetype/ftgxval.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_PFR_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which accesses PFR-specific data.
+ *
+ */
+#define FT_PFR_H <freetype/ftpfr.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_STROKER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which provides functions to stroke outline paths.
+ */
+#define FT_STROKER_H <freetype/ftstroke.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_SYNTHESIS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which performs artificial obliquing and emboldening.
+ */
+#define FT_SYNTHESIS_H <freetype/ftsynth.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_FONT_FORMATS_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which provides functions specific to font formats.
+ */
+#define FT_FONT_FORMATS_H <freetype/ftfntfmt.h>
+
+ /* deprecated */
+#define FT_XFREE86_H FT_FONT_FORMATS_H
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_TRIGONOMETRY_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which performs trigonometric computations (e.g.,
+ * cosines and arc tangents).
+ */
+#define FT_TRIGONOMETRY_H <freetype/fttrigon.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_LCD_FILTER_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which performs color filtering for subpixel rendering.
+ */
+#define FT_LCD_FILTER_H <freetype/ftlcdfil.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_INCREMENTAL_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which performs incremental glyph loading.
+ */
+#define FT_INCREMENTAL_H <freetype/ftincrem.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_GASP_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which returns entries from the TrueType GASP table.
+ */
+#define FT_GASP_H <freetype/ftgasp.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ADVANCES_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which returns individual and ranged glyph advances.
+ */
+#define FT_ADVANCES_H <freetype/ftadvanc.h>
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_COLOR_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which handles the OpenType 'CPAL' table.
+ */
+#define FT_COLOR_H <freetype/ftcolor.h>
+
+
+ /* */
+
+ /* These header files don't need to be included by the user. */
+#define FT_ERROR_DEFINITIONS_H <freetype/fterrdef.h>
+#define FT_PARAMETER_TAGS_H <freetype/ftparams.h>
+
+ /* Deprecated macros. */
+#define FT_UNPATENTED_HINTING_H <freetype/ftparams.h>
+#define FT_TRUETYPE_UNPATENTED_H <freetype/ftparams.h>
+
+ /* `FT_CACHE_H` is the only header file needed for the cache subsystem. */
+#define FT_CACHE_IMAGE_H FT_CACHE_H
+#define FT_CACHE_SMALL_BITMAPS_H FT_CACHE_H
+#define FT_CACHE_CHARMAP_H FT_CACHE_H
+
+ /* The internals of the cache sub-system are no longer exposed. We */
+ /* default to `FT_CACHE_H` at the moment just in case, but we know */
+ /* of no rogue client that uses them. */
+ /* */
+#define FT_CACHE_MANAGER_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_MRU_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_MANAGER_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_CACHE_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_GLYPH_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_IMAGE_H FT_CACHE_H
+#define FT_CACHE_INTERNAL_SBITS_H FT_CACHE_H
+
+/* TODO(david): Move this section below to a different header */
+#ifdef FT2_BUILD_LIBRARY
+#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
+
+ /* We disable the warning `conditional expression is constant' here */
+ /* in order to compile cleanly with the maximum level of warnings. */
+ /* In particular, the warning complains about stuff like `while(0)' */
+ /* which is very useful in macro definitions. There is no benefit */
+ /* in having it enabled. */
+#pragma warning( disable : 4127 )
+
+#endif /* _MSC_VER */
+#endif /* FT2_BUILD_LIBRARY */
+
+#endif /* FTHEADER_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/ftmodule.h b/Client/ThirdParty/freetype/include/freetype/config/ftmodule.h
new file mode 100644
index 0000000..d4ba3f7
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/ftmodule.h
@@ -0,0 +1,32 @@
+/*
+ * This file registers the FreeType modules compiled into the library.
+ *
+ * If you use GNU make, this file IS NOT USED! Instead, it is created in
+ * the objects directory (normally `<topdir>/objs/`) based on information
+ * from `<topdir>/modules.cfg`.
+ *
+ * Please read `docs/INSTALL.ANY` and `docs/CUSTOMIZE` how to compile
+ * FreeType without GNU make.
+ *
+ */
+
+FT_USE_MODULE( FT_Module_Class, autofit_module_class )
+FT_USE_MODULE( FT_Driver_ClassRec, tt_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, t1_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, cff_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, t1cid_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, pfr_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
+FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
+FT_USE_MODULE( FT_Module_Class, psaux_module_class )
+FT_USE_MODULE( FT_Module_Class, psnames_module_class )
+FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
+FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class )
+
+/* EOF */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/ftoption.h b/Client/ThirdParty/freetype/include/freetype/config/ftoption.h
new file mode 100644
index 0000000..4227fd3
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/ftoption.h
@@ -0,0 +1,1011 @@
+/****************************************************************************
+ *
+ * ftoption.h
+ *
+ * User-selectable configuration macros (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTOPTION_H_
+#define FTOPTION_H_
+
+
+#include <ft2build.h>
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * USER-SELECTABLE CONFIGURATION MACROS
+ *
+ * This file contains the default configuration macro definitions for a
+ * standard build of the FreeType library. There are three ways to use
+ * this file to build project-specific versions of the library:
+ *
+ * - You can modify this file by hand, but this is not recommended in
+ * cases where you would like to build several versions of the library
+ * from a single source directory.
+ *
+ * - You can put a copy of this file in your build directory, more
+ * precisely in `$BUILD/freetype/config/ftoption.h`, where `$BUILD` is
+ * the name of a directory that is included _before_ the FreeType include
+ * path during compilation.
+ *
+ * The default FreeType Makefiles use the build directory
+ * `builds/<system>` by default, but you can easily change that for your
+ * own projects.
+ *
+ * - Copy the file <ft2build.h> to `$BUILD/ft2build.h` and modify it
+ * slightly to pre-define the macro `FT_CONFIG_OPTIONS_H` used to locate
+ * this file during the build. For example,
+ *
+ * ```
+ * #define FT_CONFIG_OPTIONS_H <myftoptions.h>
+ * #include <freetype/config/ftheader.h>
+ * ```
+ *
+ * will use `$BUILD/myftoptions.h` instead of this file for macro
+ * definitions.
+ *
+ * Note also that you can similarly pre-define the macro
+ * `FT_CONFIG_MODULES_H` used to locate the file listing of the modules
+ * that are statically linked to the library at compile time. By
+ * default, this file is `<freetype/config/ftmodule.h>`.
+ *
+ * We highly recommend using the third method whenever possible.
+ *
+ */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*#************************************************************************
+ *
+ * If you enable this configuration option, FreeType recognizes an
+ * environment variable called `FREETYPE_PROPERTIES`, which can be used to
+ * control the various font drivers and modules. The controllable
+ * properties are listed in the section @properties.
+ *
+ * You have to undefine this configuration option on platforms that lack
+ * the concept of environment variables (and thus don't have the `getenv`
+ * function), for example Windows CE.
+ *
+ * `FREETYPE_PROPERTIES` has the following syntax form (broken here into
+ * multiple lines for better readability).
+ *
+ * ```
+ * <optional whitespace>
+ * <module-name1> ':'
+ * <property-name1> '=' <property-value1>
+ * <whitespace>
+ * <module-name2> ':'
+ * <property-name2> '=' <property-value2>
+ * ...
+ * ```
+ *
+ * Example:
+ *
+ * ```
+ * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
+ * cff:no-stem-darkening=1
+ * ```
+ *
+ */
+#define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
+
+
+ /**************************************************************************
+ *
+ * Uncomment the line below if you want to activate LCD rendering
+ * technology similar to ClearType in this build of the library. This
+ * technology triples the resolution in the direction color subpixels. To
+ * mitigate color fringes inherent to this technology, you also need to
+ * explicitly set up LCD filtering.
+ *
+ * When this macro is not defined, FreeType offers alternative LCD
+ * rendering technology that produces excellent output.
+ */
+/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
+
+ /**************************************************************************
+ *
+ * Many compilers provide a non-ANSI 64-bit data type that can be used by
+ * FreeType to speed up some computations. However, this will create some
+ * problems when compiling the library in strict ANSI mode.
+ *
+ * For this reason, the use of 64-bit integers is normally disabled when
+ * the `__STDC__` macro is defined. You can however disable this by
+ * defining the macro `FT_CONFIG_OPTION_FORCE_INT64` here.
+ *
+ * For most compilers, this will only create compilation warnings when
+ * building the library.
+ *
+ * ObNote: The compiler-specific 64-bit integers are detected in the
+ * file `ftconfig.h` either statically or through the `configure`
+ * script on supported platforms.
+ */
+#undef FT_CONFIG_OPTION_FORCE_INT64
+
+
+ /**************************************************************************
+ *
+ * If this macro is defined, do not try to use an assembler version of
+ * performance-critical functions (e.g., @FT_MulFix). You should only do
+ * that to verify that the assembler function works properly, or to execute
+ * benchmark tests of the various implementations.
+ */
+/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */
+
+
+ /**************************************************************************
+ *
+ * If this macro is defined, try to use an inlined assembler version of the
+ * @FT_MulFix function, which is a 'hotspot' when loading and hinting
+ * glyphs, and which should be executed as fast as possible.
+ *
+ * Note that if your compiler or CPU is not supported, this will default to
+ * the standard and portable implementation found in `ftcalc.c`.
+ */
+#define FT_CONFIG_OPTION_INLINE_MULFIX
+
+
+ /**************************************************************************
+ *
+ * LZW-compressed file support.
+ *
+ * FreeType now handles font files that have been compressed with the
+ * `compress` program. This is mostly used to parse many of the PCF
+ * files that come with various X11 distributions. The implementation
+ * uses NetBSD's `zopen` to partially uncompress the file on the fly (see
+ * `src/lzw/ftgzip.c`).
+ *
+ * Define this macro if you want to enable this 'feature'.
+ */
+#define FT_CONFIG_OPTION_USE_LZW
+
+
+ /**************************************************************************
+ *
+ * Gzip-compressed file support.
+ *
+ * FreeType now handles font files that have been compressed with the
+ * `gzip` program. This is mostly used to parse many of the PCF files
+ * that come with XFree86. The implementation uses 'zlib' to partially
+ * uncompress the file on the fly (see `src/gzip/ftgzip.c`).
+ *
+ * Define this macro if you want to enable this 'feature'. See also the
+ * macro `FT_CONFIG_OPTION_SYSTEM_ZLIB` below.
+ */
+#define FT_CONFIG_OPTION_USE_ZLIB
+
+
+ /**************************************************************************
+ *
+ * ZLib library selection
+ *
+ * This macro is only used when `FT_CONFIG_OPTION_USE_ZLIB` is defined.
+ * It allows FreeType's 'ftgzip' component to link to the system's
+ * installation of the ZLib library. This is useful on systems like
+ * Unix or VMS where it generally is already available.
+ *
+ * If you let it undefined, the component will use its own copy of the
+ * zlib sources instead. These have been modified to be included
+ * directly within the component and **not** export external function
+ * names. This allows you to link any program with FreeType _and_ ZLib
+ * without linking conflicts.
+ *
+ * Do not `#undef` this macro here since the build system might define
+ * it for certain configurations only.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
+/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */
+
+
+ /**************************************************************************
+ *
+ * Bzip2-compressed file support.
+ *
+ * FreeType now handles font files that have been compressed with the
+ * `bzip2` program. This is mostly used to parse many of the PCF files
+ * that come with XFree86. The implementation uses `libbz2` to partially
+ * uncompress the file on the fly (see `src/bzip2/ftbzip2.c`). Contrary
+ * to gzip, bzip2 currently is not included and need to use the system
+ * available bzip2 implementation.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
+/* #define FT_CONFIG_OPTION_USE_BZIP2 */
+
+
+ /**************************************************************************
+ *
+ * Define to disable the use of file stream functions and types, `FILE`,
+ * `fopen`, etc. Enables the use of smaller system libraries on embedded
+ * systems that have multiple system libraries, some with or without file
+ * stream support, in the cases where file stream support is not necessary
+ * such as memory loading of font files.
+ */
+/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */
+
+
+ /**************************************************************************
+ *
+ * PNG bitmap support.
+ *
+ * FreeType now handles loading color bitmap glyphs in the PNG format.
+ * This requires help from the external libpng library. Uncompressed
+ * color bitmaps do not need any external libraries and will be supported
+ * regardless of this configuration.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
+/* #define FT_CONFIG_OPTION_USE_PNG */
+
+
+ /**************************************************************************
+ *
+ * HarfBuzz support.
+ *
+ * FreeType uses the HarfBuzz library to improve auto-hinting of OpenType
+ * fonts. If available, many glyphs not directly addressable by a font's
+ * character map will be hinted also.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
+/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */
+
+
+ /**************************************************************************
+ *
+ * Brotli support.
+ *
+ * FreeType uses the Brotli library to provide support for decompressing
+ * WOFF2 streams.
+ *
+ * Define this macro if you want to enable this 'feature'.
+ *
+ * If you use a build system like cmake or the `configure` script,
+ * options set by those programs have precedence, overwriting the value
+ * here with the configured one.
+ */
+/* #define FT_CONFIG_OPTION_USE_BROTLI */
+
+
+ /**************************************************************************
+ *
+ * Glyph Postscript Names handling
+ *
+ * By default, FreeType 2 is compiled with the 'psnames' module. This
+ * module is in charge of converting a glyph name string into a Unicode
+ * value, or return a Macintosh standard glyph name for the use with the
+ * TrueType 'post' table.
+ *
+ * Undefine this macro if you do not want 'psnames' compiled in your
+ * build of FreeType. This has the following effects:
+ *
+ * - The TrueType driver will provide its own set of glyph names, if you
+ * build it to support postscript names in the TrueType 'post' table,
+ * but will not synthesize a missing Unicode charmap.
+ *
+ * - The Type~1 driver will not be able to synthesize a Unicode charmap
+ * out of the glyphs found in the fonts.
+ *
+ * You would normally undefine this configuration macro when building a
+ * version of FreeType that doesn't contain a Type~1 or CFF driver.
+ */
+#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ /**************************************************************************
+ *
+ * Postscript Names to Unicode Values support
+ *
+ * By default, FreeType~2 is built with the 'psnames' module compiled in.
+ * Among other things, the module is used to convert a glyph name into a
+ * Unicode value. This is especially useful in order to synthesize on
+ * the fly a Unicode charmap from the CFF/Type~1 driver through a big
+ * table named the 'Adobe Glyph List' (AGL).
+ *
+ * Undefine this macro if you do not want the Adobe Glyph List compiled
+ * in your 'psnames' module. The Type~1 driver will not be able to
+ * synthesize a Unicode charmap out of the glyphs found in the fonts.
+ */
+#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+ /**************************************************************************
+ *
+ * Support for Mac fonts
+ *
+ * Define this macro if you want support for outline fonts in Mac format
+ * (mac dfont, mac resource, macbinary containing a mac resource) on
+ * non-Mac platforms.
+ *
+ * Note that the 'FOND' resource isn't checked.
+ */
+#define FT_CONFIG_OPTION_MAC_FONTS
+
+
+ /**************************************************************************
+ *
+ * Guessing methods to access embedded resource forks
+ *
+ * Enable extra Mac fonts support on non-Mac platforms (e.g., GNU/Linux).
+ *
+ * Resource forks which include fonts data are stored sometimes in
+ * locations which users or developers don't expected. In some cases,
+ * resource forks start with some offset from the head of a file. In
+ * other cases, the actual resource fork is stored in file different from
+ * what the user specifies. If this option is activated, FreeType tries
+ * to guess whether such offsets or different file names must be used.
+ *
+ * Note that normal, direct access of resource forks is controlled via
+ * the `FT_CONFIG_OPTION_MAC_FONTS` option.
+ */
+#ifdef FT_CONFIG_OPTION_MAC_FONTS
+#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
+#endif
+
+
+ /**************************************************************************
+ *
+ * Allow the use of `FT_Incremental_Interface` to load typefaces that
+ * contain no glyph data, but supply it via a callback function. This is
+ * required by clients supporting document formats which supply font data
+ * incrementally as the document is parsed, such as the Ghostscript
+ * interpreter for the PostScript language.
+ */
+#define FT_CONFIG_OPTION_INCREMENTAL
+
+
+ /**************************************************************************
+ *
+ * The size in bytes of the render pool used by the scan-line converter to
+ * do all of its work.
+ */
+#define FT_RENDER_POOL_SIZE 16384L
+
+
+ /**************************************************************************
+ *
+ * FT_MAX_MODULES
+ *
+ * The maximum number of modules that can be registered in a single
+ * FreeType library object. 32~is the default.
+ */
+#define FT_MAX_MODULES 32
+
+
+ /**************************************************************************
+ *
+ * Debug level
+ *
+ * FreeType can be compiled in debug or trace mode. In debug mode,
+ * errors are reported through the 'ftdebug' component. In trace mode,
+ * additional messages are sent to the standard output during execution.
+ *
+ * Define `FT_DEBUG_LEVEL_ERROR` to build the library in debug mode.
+ * Define `FT_DEBUG_LEVEL_TRACE` to build it in trace mode.
+ *
+ * Don't define any of these macros to compile in 'release' mode!
+ *
+ * Do not `#undef` these macros here since the build system might define
+ * them for certain configurations only.
+ */
+/* #define FT_DEBUG_LEVEL_ERROR */
+/* #define FT_DEBUG_LEVEL_TRACE */
+
+
+ /**************************************************************************
+ *
+ * Logging
+ *
+ * Compiling FreeType in debug or trace mode makes FreeType write error
+ * and trace log messages to `stderr`. Enabling this macro
+ * automatically forces the `FT_DEBUG_LEVEL_ERROR` and
+ * `FT_DEBUG_LEVEL_TRACE` macros and allows FreeType to write error and
+ * trace log messages to a file instead of `stderr`. For writing logs
+ * to a file, FreeType uses an the external `dlg` library (the source
+ * code is in `src/dlg`).
+ *
+ * This option needs a C99 compiler.
+ */
+/* #define FT_DEBUG_LOGGING */
+
+
+ /**************************************************************************
+ *
+ * Autofitter debugging
+ *
+ * If `FT_DEBUG_AUTOFIT` is defined, FreeType provides some means to
+ * control the autofitter behaviour for debugging purposes with global
+ * boolean variables (consequently, you should **never** enable this
+ * while compiling in 'release' mode):
+ *
+ * ```
+ * _af_debug_disable_horz_hints
+ * _af_debug_disable_vert_hints
+ * _af_debug_disable_blue_hints
+ * ```
+ *
+ * Additionally, the following functions provide dumps of various
+ * internal autofit structures to stdout (using `printf`):
+ *
+ * ```
+ * af_glyph_hints_dump_points
+ * af_glyph_hints_dump_segments
+ * af_glyph_hints_dump_edges
+ * af_glyph_hints_get_num_segments
+ * af_glyph_hints_get_segment_offset
+ * ```
+ *
+ * As an argument, they use another global variable:
+ *
+ * ```
+ * _af_debug_hints
+ * ```
+ *
+ * Please have a look at the `ftgrid` demo program to see how those
+ * variables and macros should be used.
+ *
+ * Do not `#undef` these macros here since the build system might define
+ * them for certain configurations only.
+ */
+/* #define FT_DEBUG_AUTOFIT */
+
+
+ /**************************************************************************
+ *
+ * Memory Debugging
+ *
+ * FreeType now comes with an integrated memory debugger that is capable
+ * of detecting simple errors like memory leaks or double deletes. To
+ * compile it within your build of the library, you should define
+ * `FT_DEBUG_MEMORY` here.
+ *
+ * Note that the memory debugger is only activated at runtime when when
+ * the _environment_ variable `FT2_DEBUG_MEMORY` is defined also!
+ *
+ * Do not `#undef` this macro here since the build system might define it
+ * for certain configurations only.
+ */
+/* #define FT_DEBUG_MEMORY */
+
+
+ /**************************************************************************
+ *
+ * Module errors
+ *
+ * If this macro is set (which is _not_ the default), the higher byte of
+ * an error code gives the module in which the error has occurred, while
+ * the lower byte is the real error code.
+ *
+ * Setting this macro makes sense for debugging purposes only, since it
+ * would break source compatibility of certain programs that use
+ * FreeType~2.
+ *
+ * More details can be found in the files `ftmoderr.h` and `fterrors.h`.
+ */
+#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+
+ /**************************************************************************
+ *
+ * Error Strings
+ *
+ * If this macro is set, `FT_Error_String` will return meaningful
+ * descriptions. This is not enabled by default to reduce the overall
+ * size of FreeType.
+ *
+ * More details can be found in the file `fterrors.h`.
+ */
+/* #define FT_CONFIG_OPTION_ERROR_STRINGS */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** S F N T D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_EMBEDDED_BITMAPS` if you want to support
+ * embedded bitmaps in all formats using the 'sfnt' module (namely
+ * TrueType~& OpenType).
+ */
+#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_COLOR_LAYERS` if you want to support colored
+ * outlines (from the 'COLR'/'CPAL' tables) in all formats using the 'sfnt'
+ * module (namely TrueType~& OpenType).
+ */
+#define TT_CONFIG_OPTION_COLOR_LAYERS
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to
+ * load and enumerate the glyph Postscript names in a TrueType or OpenType
+ * file.
+ *
+ * Note that when you do not compile the 'psnames' module by undefining the
+ * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will
+ * contain additional code used to read the PS Names table from a font.
+ *
+ * (By default, the module uses 'psnames' to extract glyph names.)
+ */
+#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_SFNT_NAMES` if your applications need to access
+ * the internal name table in a SFNT-based format like TrueType or
+ * OpenType. The name table contains various strings used to describe the
+ * font, like family name, copyright, version, etc. It does not contain
+ * any glyph name though.
+ *
+ * Accessing SFNT names is done through the functions declared in
+ * `ftsnames.h`.
+ */
+#define TT_CONFIG_OPTION_SFNT_NAMES
+
+
+ /**************************************************************************
+ *
+ * TrueType CMap support
+ *
+ * Here you can fine-tune which TrueType CMap table format shall be
+ * supported.
+ */
+#define TT_CONFIG_CMAP_FORMAT_0
+#define TT_CONFIG_CMAP_FORMAT_2
+#define TT_CONFIG_CMAP_FORMAT_4
+#define TT_CONFIG_CMAP_FORMAT_6
+#define TT_CONFIG_CMAP_FORMAT_8
+#define TT_CONFIG_CMAP_FORMAT_10
+#define TT_CONFIG_CMAP_FORMAT_12
+#define TT_CONFIG_CMAP_FORMAT_13
+#define TT_CONFIG_CMAP_FORMAT_14
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` if you want to compile a
+ * bytecode interpreter in the TrueType driver.
+ *
+ * By undefining this, you will only compile the code necessary to load
+ * TrueType glyphs without hinting.
+ *
+ * Do not `#undef` this macro here, since the build system might define it
+ * for certain configurations only.
+ */
+#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_SUBPIXEL_HINTING` if you want to compile
+ * subpixel hinting support into the TrueType driver. This modifies the
+ * TrueType hinting mechanism when anything but `FT_RENDER_MODE_MONO` is
+ * requested.
+ *
+ * In particular, it modifies the bytecode interpreter to interpret (or
+ * not) instructions in a certain way so that all TrueType fonts look like
+ * they do in a Windows ClearType (DirectWrite) environment. See [1] for a
+ * technical overview on what this means. See `ttinterp.h` for more
+ * details on the LEAN option.
+ *
+ * There are three possible values.
+ *
+ * Value 1:
+ * This value is associated with the 'Infinality' moniker, contributed by
+ * an individual nicknamed Infinality with the goal of making TrueType
+ * fonts render better than on Windows. A high amount of configurability
+ * and flexibility, down to rules for single glyphs in fonts, but also
+ * very slow. Its experimental and slow nature and the original
+ * developer losing interest meant that this option was never enabled in
+ * default builds.
+ *
+ * The corresponding interpreter version is v38.
+ *
+ * Value 2:
+ * The new default mode for the TrueType driver. The Infinality code
+ * base was stripped to the bare minimum and all configurability removed
+ * in the name of speed and simplicity. The configurability was mainly
+ * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'.
+ * Legacy fonts are fonts that modify vertical stems to achieve clean
+ * black-and-white bitmaps. The new mode focuses on applying a minimal
+ * set of rules to all fonts indiscriminately so that modern and web
+ * fonts render well while legacy fonts render okay.
+ *
+ * The corresponding interpreter version is v40.
+ *
+ * Value 3:
+ * Compile both, making both v38 and v40 available (the latter is the
+ * default).
+ *
+ * By undefining these, you get rendering behavior like on Windows without
+ * ClearType, i.e., Windows XP without ClearType enabled and Win9x
+ * (interpreter version v35). Or not, depending on how much hinting blood
+ * and testing tears the font designer put into a given font. If you
+ * define one or both subpixel hinting options, you can switch between
+ * between v35 and the ones you define (using `FT_Property_Set`).
+ *
+ * This option requires `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` to be
+ * defined.
+ *
+ * [1]
+ * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx
+ */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */
+#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED` to compile the
+ * TrueType glyph loader to use Apple's definition of how to handle
+ * component offsets in composite glyphs.
+ *
+ * Apple and MS disagree on the default behavior of component offsets in
+ * composites. Apple says that they should be scaled by the scaling
+ * factors in the transformation matrix (roughly, it's more complex) while
+ * MS says they should not. OpenType defines two bits in the composite
+ * flags array which can be used to disambiguate, but old fonts will not
+ * have them.
+ *
+ * https://www.microsoft.com/typography/otspec/glyf.htm
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html
+ */
+#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_GX_VAR_SUPPORT` if you want to include support
+ * for Apple's distortable font technology ('fvar', 'gvar', 'cvar', and
+ * 'avar' tables). Tagged 'Font Variations', this is now part of OpenType
+ * also. This has many similarities to Type~1 Multiple Masters support.
+ */
+#define TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+
+ /**************************************************************************
+ *
+ * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an
+ * embedded 'BDF~' table within SFNT-based bitmap formats.
+ */
+#define TT_CONFIG_OPTION_BDF
+
+
+ /**************************************************************************
+ *
+ * Option `TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES` controls the maximum
+ * number of bytecode instructions executed for a single run of the
+ * bytecode interpreter, needed to prevent infinite loops. You don't want
+ * to change this except for very special situations (e.g., making a
+ * library fuzzer spend less time to handle broken fonts).
+ *
+ * It is not expected that this value is ever modified by a configuring
+ * script; instead, it gets surrounded with `#ifndef ... #endif` so that
+ * the value can be set as a preprocessor option on the compiler's command
+ * line.
+ */
+#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES
+#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L
+#endif
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * `T1_MAX_DICT_DEPTH` is the maximum depth of nest dictionaries and arrays
+ * in the Type~1 stream (see `t1load.c`). A minimum of~4 is required.
+ */
+#define T1_MAX_DICT_DEPTH 5
+
+
+ /**************************************************************************
+ *
+ * `T1_MAX_SUBRS_CALLS` details the maximum number of nested sub-routine
+ * calls during glyph loading.
+ */
+#define T1_MAX_SUBRS_CALLS 16
+
+
+ /**************************************************************************
+ *
+ * `T1_MAX_CHARSTRING_OPERANDS` is the charstring stack's capacity. A
+ * minimum of~16 is required.
+ *
+ * The Chinese font 'MingTiEG-Medium' (covering the CNS 11643 character
+ * set) needs 256.
+ */
+#define T1_MAX_CHARSTRINGS_OPERANDS 256
+
+
+ /**************************************************************************
+ *
+ * Define this configuration macro if you want to prevent the compilation
+ * of the 't1afm' module, which is in charge of reading Type~1 AFM files
+ * into an existing face. Note that if set, the Type~1 driver will be
+ * unable to produce kerning distances.
+ */
+#undef T1_CONFIG_OPTION_NO_AFM
+
+
+ /**************************************************************************
+ *
+ * Define this configuration macro if you want to prevent the compilation
+ * of the Multiple Masters font support in the Type~1 driver.
+ */
+#undef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+ /**************************************************************************
+ *
+ * `T1_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe Type~1
+ * engine gets compiled into FreeType. If defined, it is possible to
+ * switch between the two engines using the `hinting-engine` property of
+ * the 'type1' driver module.
+ */
+/* #define T1_CONFIG_OPTION_OLD_ENGINE */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** C F F D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * Using `CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4}` it is
+ * possible to set up the default values of the four control points that
+ * define the stem darkening behaviour of the (new) CFF engine. For more
+ * details please read the documentation of the `darkening-parameters`
+ * property (file `ftdriver.h`), which allows the control at run-time.
+ *
+ * Do **not** undefine these macros!
+ */
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 500
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 400
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 1000
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 275
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 1667
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 275
+
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 2333
+#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 0
+
+
+ /**************************************************************************
+ *
+ * `CFF_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe CFF engine
+ * gets compiled into FreeType. If defined, it is possible to switch
+ * between the two engines using the `hinting-engine` property of the 'cff'
+ * driver module.
+ */
+/* #define CFF_CONFIG_OPTION_OLD_ENGINE */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** P C F D R I V E R C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * There are many PCF fonts just called 'Fixed' which look completely
+ * different, and which have nothing to do with each other. When selecting
+ * 'Fixed' in KDE or Gnome one gets results that appear rather random, the
+ * style changes often if one changes the size and one cannot select some
+ * fonts at all. This option makes the 'pcf' module prepend the foundry
+ * name (plus a space) to the family name.
+ *
+ * We also check whether we have 'wide' characters; all put together, we
+ * get family names like 'Sony Fixed' or 'Misc Fixed Wide'.
+ *
+ * If this option is activated, it can be controlled with the
+ * `no-long-family-names` property of the 'pcf' driver module.
+ */
+/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * Compile 'autofit' module with CJK (Chinese, Japanese, Korean) script
+ * support.
+ */
+#define AF_CONFIG_OPTION_CJK
+
+
+ /**************************************************************************
+ *
+ * Compile 'autofit' module with fallback Indic script support, covering
+ * some scripts that the 'latin' submodule of the 'autofit' module doesn't
+ * (yet) handle. Currently, this needs option `AF_CONFIG_OPTION_CJK`.
+ */
+#ifdef AF_CONFIG_OPTION_CJK
+#define AF_CONFIG_OPTION_INDIC
+#endif
+
+
+ /**************************************************************************
+ *
+ * Use TrueType-like size metrics for 'light' auto-hinting.
+ *
+ * It is strongly recommended to avoid this option, which exists only to
+ * help some legacy applications retain its appearance and behaviour with
+ * respect to auto-hinted TrueType fonts.
+ *
+ * The very reason this option exists at all are GNU/Linux distributions
+ * like Fedora that did not un-patch the following change (which was
+ * present in FreeType between versions 2.4.6 and 2.7.1, inclusive).
+ *
+ * ```
+ * 2011-07-16 Steven Chu <steven.f.chu@gmail.com>
+ *
+ * [truetype] Fix metrics on size request for scalable fonts.
+ * ```
+ *
+ * This problematic commit is now reverted (more or less).
+ */
+/* #define AF_CONFIG_OPTION_TT_SIZE_METRICS */
+
+ /* */
+
+
+ /*
+ * This macro is obsolete. Support has been removed in FreeType version
+ * 2.5.
+ */
+/* #define FT_CONFIG_OPTION_OLD_INTERNALS */
+
+
+ /*
+ * The next three macros are defined if native TrueType hinting is
+ * requested by the definitions above. Don't change this.
+ */
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+#define TT_USE_BYTECODE_INTERPRETER
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1
+#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+#endif
+
+#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2
+#define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+#endif
+#endif
+#endif
+
+
+ /*
+ * The TT_SUPPORT_COLRV1 macro is defined to indicate to clients that this
+ * version of FreeType has support for 'COLR' v1 API. This definition is
+ * useful to FreeType clients that want to build in support for 'COLR' v1
+ * depending on a tip-of-tree checkout before it is officially released in
+ * FreeType, and while the feature cannot yet be tested against using
+ * version macros. Don't change this macro. This may be removed once the
+ * feature is in a FreeType release version and version macros can be used
+ * to test for availability.
+ */
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+#define TT_SUPPORT_COLRV1
+#endif
+
+
+ /*
+ * Check CFF darkening parameters. The checks are the same as in function
+ * `cff_property_set` in file `cffdrivr.c`.
+ */
+#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 < 0 || \
+ \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 < 0 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 < 0 || \
+ \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 > \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 > \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 > \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 || \
+ \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 > 500 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 > 500 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 > 500 || \
+ CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 > 500
+#error "Invalid CFF darkening parameters!"
+#endif
+
+FT_END_HEADER
+
+
+#endif /* FTOPTION_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/ftstdlib.h b/Client/ThirdParty/freetype/include/freetype/config/ftstdlib.h
new file mode 100644
index 0000000..fea21ff
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/ftstdlib.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+ *
+ * ftstdlib.h
+ *
+ * ANSI-specific library and header configuration file (specification
+ * only).
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to group all `#includes` to the ANSI~C library that
+ * FreeType normally requires. It also defines macros to rename the
+ * standard functions within the FreeType source code.
+ *
+ * Load a file which defines `FTSTDLIB_H_` before this one to override it.
+ *
+ */
+
+
+#ifndef FTSTDLIB_H_
+#define FTSTDLIB_H_
+
+
+#include <stddef.h>
+
+#define ft_ptrdiff_t ptrdiff_t
+
+
+ /**************************************************************************
+ *
+ * integer limits
+ *
+ * `UINT_MAX` and `ULONG_MAX` are used to automatically compute the size of
+ * `int` and `long` in bytes at compile-time. So far, this works for all
+ * platforms the library has been tested on.
+ *
+ * Note that on the extremely rare platforms that do not provide integer
+ * types that are _exactly_ 16 and 32~bits wide (e.g., some old Crays where
+ * `int` is 36~bits), we do not make any guarantee about the correct
+ * behaviour of FreeType~2 with all fonts.
+ *
+ * In these cases, `ftconfig.h` will refuse to compile anyway with a
+ * message like 'couldn't find 32-bit type' or something similar.
+ *
+ */
+
+
+#include <limits.h>
+
+#define FT_CHAR_BIT CHAR_BIT
+#define FT_USHORT_MAX USHRT_MAX
+#define FT_INT_MAX INT_MAX
+#define FT_INT_MIN INT_MIN
+#define FT_UINT_MAX UINT_MAX
+#define FT_LONG_MIN LONG_MIN
+#define FT_LONG_MAX LONG_MAX
+#define FT_ULONG_MAX ULONG_MAX
+
+
+ /**************************************************************************
+ *
+ * character and string processing
+ *
+ */
+
+
+#include <string.h>
+
+#define ft_memchr memchr
+#define ft_memcmp memcmp
+#define ft_memcpy memcpy
+#define ft_memmove memmove
+#define ft_memset memset
+#define ft_strcat strcat
+#define ft_strcmp strcmp
+#define ft_strcpy strcpy
+#define ft_strlen strlen
+#define ft_strncmp strncmp
+#define ft_strncpy strncpy
+#define ft_strrchr strrchr
+#define ft_strstr strstr
+
+
+ /**************************************************************************
+ *
+ * file handling
+ *
+ */
+
+
+#include <stdio.h>
+
+#define FT_FILE FILE
+#define ft_fclose fclose
+#define ft_fopen fopen
+#define ft_fread fread
+#define ft_fseek fseek
+#define ft_ftell ftell
+#define ft_sprintf sprintf
+
+
+ /**************************************************************************
+ *
+ * sorting
+ *
+ */
+
+
+#include <stdlib.h>
+
+#define ft_qsort qsort
+
+
+ /**************************************************************************
+ *
+ * memory allocation
+ *
+ */
+
+
+#define ft_scalloc calloc
+#define ft_sfree free
+#define ft_smalloc malloc
+#define ft_srealloc realloc
+
+
+ /**************************************************************************
+ *
+ * miscellaneous
+ *
+ */
+
+
+#define ft_strtol strtol
+#define ft_getenv getenv
+
+
+ /**************************************************************************
+ *
+ * execution control
+ *
+ */
+
+
+#include <setjmp.h>
+
+#define ft_jmp_buf jmp_buf /* note: this cannot be a typedef since */
+ /* `jmp_buf` is defined as a macro */
+ /* on certain platforms */
+
+#define ft_longjmp longjmp
+#define ft_setjmp( b ) setjmp( *(ft_jmp_buf*) &(b) ) /* same thing here */
+
+
+ /* The following is only used for debugging purposes, i.e., if */
+ /* `FT_DEBUG_LEVEL_ERROR` or `FT_DEBUG_LEVEL_TRACE` are defined. */
+
+#include <stdarg.h>
+
+
+#endif /* FTSTDLIB_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/integer-types.h b/Client/ThirdParty/freetype/include/freetype/config/integer-types.h
new file mode 100644
index 0000000..4bb3eed
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/integer-types.h
@@ -0,0 +1,245 @@
+/****************************************************************************
+ *
+ * config/integer-types.h
+ *
+ * FreeType integer types definitions.
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+#ifndef FREETYPE_CONFIG_INTEGER_TYPES_H_
+#define FREETYPE_CONFIG_INTEGER_TYPES_H_
+
+ /* There are systems (like the Texas Instruments 'C54x) where a `char` */
+ /* has 16~bits. ANSI~C says that `sizeof(char)` is always~1. Since an */
+ /* `int` has 16~bits also for this system, `sizeof(int)` gives~1 which */
+ /* is probably unexpected. */
+ /* */
+ /* `CHAR_BIT` (defined in `limits.h`) gives the number of bits in a */
+ /* `char` type. */
+
+#ifndef FT_CHAR_BIT
+#define FT_CHAR_BIT CHAR_BIT
+#endif
+
+#ifndef FT_SIZEOF_INT
+
+ /* The size of an `int` type. */
+#if FT_UINT_MAX == 0xFFFFUL
+#define FT_SIZEOF_INT ( 16 / FT_CHAR_BIT )
+#elif FT_UINT_MAX == 0xFFFFFFFFUL
+#define FT_SIZEOF_INT ( 32 / FT_CHAR_BIT )
+#elif FT_UINT_MAX > 0xFFFFFFFFUL && FT_UINT_MAX == 0xFFFFFFFFFFFFFFFFUL
+#define FT_SIZEOF_INT ( 64 / FT_CHAR_BIT )
+#else
+#error "Unsupported size of `int' type!"
+#endif
+
+#endif /* !defined(FT_SIZEOF_INT) */
+
+#ifndef FT_SIZEOF_LONG
+
+ /* The size of a `long` type. A five-byte `long` (as used e.g. on the */
+ /* DM642) is recognized but avoided. */
+#if FT_ULONG_MAX == 0xFFFFFFFFUL
+#define FT_SIZEOF_LONG ( 32 / FT_CHAR_BIT )
+#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFUL
+#define FT_SIZEOF_LONG ( 32 / FT_CHAR_BIT )
+#elif FT_ULONG_MAX > 0xFFFFFFFFUL && FT_ULONG_MAX == 0xFFFFFFFFFFFFFFFFUL
+#define FT_SIZEOF_LONG ( 64 / FT_CHAR_BIT )
+#else
+#error "Unsupported size of `long' type!"
+#endif
+
+#endif /* !defined(FT_SIZEOF_LONG) */
+
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int16
+ *
+ * @description:
+ * A typedef for a 16bit signed integer type.
+ */
+ typedef signed short FT_Int16;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt16
+ *
+ * @description:
+ * A typedef for a 16bit unsigned integer type.
+ */
+ typedef unsigned short FT_UInt16;
+
+ /* */
+
+
+ /* this #if 0 ... #endif clause is for documentation purposes */
+#if 0
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int32
+ *
+ * @description:
+ * A typedef for a 32bit signed integer type. The size depends on the
+ * configuration.
+ */
+ typedef signed XXX FT_Int32;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt32
+ *
+ * A typedef for a 32bit unsigned integer type. The size depends on the
+ * configuration.
+ */
+ typedef unsigned XXX FT_UInt32;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int64
+ *
+ * A typedef for a 64bit signed integer type. The size depends on the
+ * configuration. Only defined if there is real 64bit support;
+ * otherwise, it gets emulated with a structure (if necessary).
+ */
+ typedef signed XXX FT_Int64;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt64
+ *
+ * A typedef for a 64bit unsigned integer type. The size depends on the
+ * configuration. Only defined if there is real 64bit support;
+ * otherwise, it gets emulated with a structure (if necessary).
+ */
+ typedef unsigned XXX FT_UInt64;
+
+ /* */
+
+#endif
+
+#if FT_SIZEOF_INT == ( 32 / FT_CHAR_BIT )
+
+ typedef signed int FT_Int32;
+ typedef unsigned int FT_UInt32;
+
+#elif FT_SIZEOF_LONG == ( 32 / FT_CHAR_BIT )
+
+ typedef signed long FT_Int32;
+ typedef unsigned long FT_UInt32;
+
+#else
+#error "no 32bit type found -- please check your configuration files"
+#endif
+
+
+ /* look up an integer type that is at least 32~bits */
+#if FT_SIZEOF_INT >= ( 32 / FT_CHAR_BIT )
+
+ typedef int FT_Fast;
+ typedef unsigned int FT_UFast;
+
+#elif FT_SIZEOF_LONG >= ( 32 / FT_CHAR_BIT )
+
+ typedef long FT_Fast;
+ typedef unsigned long FT_UFast;
+
+#endif
+
+
+ /* determine whether we have a 64-bit `int` type for platforms without */
+ /* Autoconf */
+#if FT_SIZEOF_LONG == ( 64 / FT_CHAR_BIT )
+
+ /* `FT_LONG64` must be defined if a 64-bit type is available */
+#define FT_LONG64
+#define FT_INT64 long
+#define FT_UINT64 unsigned long
+
+ /**************************************************************************
+ *
+ * A 64-bit data type may create compilation problems if you compile in
+ * strict ANSI mode. To avoid them, we disable other 64-bit data types if
+ * `__STDC__` is defined. You can however ignore this rule by defining the
+ * `FT_CONFIG_OPTION_FORCE_INT64` configuration macro.
+ */
+#elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
+
+#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L
+
+#define FT_LONG64
+#define FT_INT64 long long int
+#define FT_UINT64 unsigned long long int
+
+#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+
+ /* this compiler provides the `__int64` type */
+#define FT_LONG64
+#define FT_INT64 __int64
+#define FT_UINT64 unsigned __int64
+
+#elif defined( __BORLANDC__ ) /* Borland C++ */
+
+ /* XXXX: We should probably check the value of `__BORLANDC__` in order */
+ /* to test the compiler version. */
+
+ /* this compiler provides the `__int64` type */
+#define FT_LONG64
+#define FT_INT64 __int64
+#define FT_UINT64 unsigned __int64
+
+#elif defined( __WATCOMC__ ) /* Watcom C++ */
+
+ /* Watcom doesn't provide 64-bit data types */
+
+#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */
+
+#define FT_LONG64
+#define FT_INT64 long long int
+#define FT_UINT64 unsigned long long int
+
+#elif defined( __GNUC__ )
+
+ /* GCC provides the `long long` type */
+#define FT_LONG64
+#define FT_INT64 long long int
+#define FT_UINT64 unsigned long long int
+
+#endif /* __STDC_VERSION__ >= 199901L */
+
+#endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
+
+#ifdef FT_LONG64
+ typedef FT_INT64 FT_Int64;
+ typedef FT_UINT64 FT_UInt64;
+#endif
+
+
+#endif /* FREETYPE_CONFIG_INTEGER_TYPES_H_ */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/mac-support.h b/Client/ThirdParty/freetype/include/freetype/config/mac-support.h
new file mode 100644
index 0000000..ef58d8b
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/mac-support.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ *
+ * config/mac-support.h
+ *
+ * Mac/OS X support configuration header.
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+#ifndef FREETYPE_CONFIG_MAC_SUPPORT_H_
+#define FREETYPE_CONFIG_MAC_SUPPORT_H_
+
+ /**************************************************************************
+ *
+ * Mac support
+ *
+ * This is the only necessary change, so it is defined here instead
+ * providing a new configuration file.
+ */
+#if defined( __APPLE__ ) || ( defined( __MWERKS__ ) && defined( macintosh ) )
+ /* No Carbon frameworks for 64bit 10.4.x. */
+ /* `AvailabilityMacros.h` is available since Mac OS X 10.2, */
+ /* so guess the system version by maximum errno before inclusion. */
+#include <errno.h>
+#ifdef ECANCELED /* defined since 10.2 */
+#include "AvailabilityMacros.h"
+#endif
+#if defined( __LP64__ ) && \
+ ( MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 )
+#undef FT_MACINTOSH
+#endif
+
+#elif defined( __SC__ ) || defined( __MRC__ )
+ /* Classic MacOS compilers */
+#include "ConditionalMacros.h"
+#if TARGET_OS_MAC
+#define FT_MACINTOSH 1
+#endif
+
+#endif /* Mac support */
+
+#endif /* FREETYPE_CONFIG_MAC_SUPPORT_H_ */
diff --git a/Client/ThirdParty/freetype/include/freetype/config/public-macros.h b/Client/ThirdParty/freetype/include/freetype/config/public-macros.h
new file mode 100644
index 0000000..fed414e
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/config/public-macros.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+ *
+ * config/public-macros.h
+ *
+ * Define a set of compiler macros used in public FreeType headers.
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /*
+ * The definitions in this file are used by the public FreeType headers
+ * and thus should be considered part of the public API.
+ *
+ * Other compiler-specific macro definitions that are not exposed by the
+ * FreeType API should go into
+ * `include/freetype/internal/compiler-macros.h` instead.
+ */
+#ifndef FREETYPE_CONFIG_PUBLIC_MACROS_H_
+#define FREETYPE_CONFIG_PUBLIC_MACROS_H_
+
+ /*
+ * `FT_BEGIN_HEADER` and `FT_END_HEADER` might have already been defined
+ * by `freetype/config/ftheader.h`, but we don't want to include this
+ * header here, so redefine the macros here only when needed. Their
+ * definition is very stable, so keeping them in sync with the ones in the
+ * header should not be a maintenance issue.
+ */
+#ifndef FT_BEGIN_HEADER
+#ifdef __cplusplus
+#define FT_BEGIN_HEADER extern "C" {
+#else
+#define FT_BEGIN_HEADER /* empty */
+#endif
+#endif /* FT_BEGIN_HEADER */
+
+#ifndef FT_END_HEADER
+#ifdef __cplusplus
+#define FT_END_HEADER }
+#else
+#define FT_END_HEADER /* empty */
+#endif
+#endif /* FT_END_HEADER */
+
+
+FT_BEGIN_HEADER
+
+ /*
+ * Mark a function declaration as public. This ensures it will be
+ * properly exported to client code. Place this before a function
+ * declaration.
+ *
+ * NOTE: This macro should be considered an internal implementation
+ * detail, and not part of the FreeType API. It is only defined here
+ * because it is needed by `FT_EXPORT`.
+ */
+
+ /* Visual C, mingw */
+#if defined( WIN32 )
+
+#if defined( FT2_BUILD_LIBRARY ) && defined( DLL_EXPORT )
+#define FT_PUBLIC_FUNCTION_ATTRIBUTE __declspec( dllexport )
+#elif defined( DLL_IMPORT )
+#define FT_PUBLIC_FUNCTION_ATTRIBUTE __declspec( dllimport )
+#endif
+
+ /* gcc, clang */
+#elif ( defined( __GNUC__ ) && __GNUC__ >= 4 ) || defined( __clang__ )
+#define FT_PUBLIC_FUNCTION_ATTRIBUTE \
+ __attribute__(( visibility( "default" ) ))
+
+ /* Sun */
+#elif defined( __SUNPRO_C ) && __SUNPRO_C >= 0x550
+#define FT_PUBLIC_FUNCTION_ATTRIBUTE __global
+#endif
+
+
+#ifndef FT_PUBLIC_FUNCTION_ATTRIBUTE
+#define FT_PUBLIC_FUNCTION_ATTRIBUTE /* empty */
+#endif
+
+
+ /*
+ * Define a public FreeType API function. This ensures it is properly
+ * exported or imported at build time. The macro parameter is the
+ * function's return type as in:
+ *
+ * FT_EXPORT( FT_Bool )
+ * FT_Object_Method( FT_Object obj,
+ * ... );
+ *
+ * NOTE: This requires that all `FT_EXPORT` uses are inside
+ * `FT_BEGIN_HEADER ... FT_END_HEADER` blocks. This guarantees that the
+ * functions are exported with C linkage, even when the header is included
+ * by a C++ source file.
+ */
+#define FT_EXPORT( x ) FT_PUBLIC_FUNCTION_ATTRIBUTE extern x
+
+ /*
+ * `FT_UNUSED` indicates that a given parameter is not used -- this is
+ * only used to get rid of unpleasant compiler warnings.
+ *
+ * Technically, this was not meant to be part of the public API, but some
+ * third-party code depends on it.
+ */
+#ifndef FT_UNUSED
+#define FT_UNUSED( arg ) ( (arg) = (arg) )
+#endif
+
+
+FT_END_HEADER
+
+#endif /* FREETYPE_CONFIG_PUBLIC_MACROS_H_ */
diff --git a/Client/ThirdParty/freetype/include/freetype/freetype.h b/Client/ThirdParty/freetype/include/freetype/freetype.h
new file mode 100644
index 0000000..77fede3
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/freetype.h
@@ -0,0 +1,4833 @@
+/****************************************************************************
+ *
+ * freetype.h
+ *
+ * FreeType high-level API and common types (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FREETYPE_H_
+#define FREETYPE_H_
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include <freetype/fttypes.h>
+#include <freetype/fterrors.h>
+
+
+FT_BEGIN_HEADER
+
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * preamble
+ *
+ * @title:
+ * Preamble
+ *
+ * @abstract:
+ * What FreeType is and isn't
+ *
+ * @description:
+ * FreeType is a library that provides access to glyphs in font files. It
+ * scales the glyph images and their metrics to a requested size, and it
+ * rasterizes the glyph images to produce pixel or subpixel alpha coverage
+ * bitmaps.
+ *
+ * Note that FreeType is _not_ a text layout engine. You have to use
+ * higher-level libraries like HarfBuzz, Pango, or ICU for that.
+ *
+ * Note also that FreeType does _not_ perform alpha blending or
+ * compositing the resulting bitmaps or pixmaps by itself. Use your
+ * favourite graphics library (for example, Cairo or Skia) to further
+ * process FreeType's output.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * header_inclusion
+ *
+ * @title:
+ * FreeType's header inclusion scheme
+ *
+ * @abstract:
+ * How client applications should include FreeType header files.
+ *
+ * @description:
+ * To be as flexible as possible (and for historical reasons), you must
+ * load file `ft2build.h` first before other header files, for example
+ *
+ * ```
+ * #include <ft2build.h>
+ *
+ * #include <freetype/freetype.h>
+ * #include <freetype/ftoutln.h>
+ * ```
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * user_allocation
+ *
+ * @title:
+ * User allocation
+ *
+ * @abstract:
+ * How client applications should allocate FreeType data structures.
+ *
+ * @description:
+ * FreeType assumes that structures allocated by the user and passed as
+ * arguments are zeroed out except for the actual data. In other words,
+ * it is recommended to use `calloc` (or variants of it) instead of
+ * `malloc` for allocation.
+ *
+ */
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* B A S I C T Y P E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * base_interface
+ *
+ * @title:
+ * Base Interface
+ *
+ * @abstract:
+ * The FreeType~2 base font interface.
+ *
+ * @description:
+ * This section describes the most important public high-level API
+ * functions of FreeType~2.
+ *
+ * @order:
+ * FT_Library
+ * FT_Face
+ * FT_Size
+ * FT_GlyphSlot
+ * FT_CharMap
+ * FT_Encoding
+ * FT_ENC_TAG
+ *
+ * FT_FaceRec
+ *
+ * FT_FACE_FLAG_SCALABLE
+ * FT_FACE_FLAG_FIXED_SIZES
+ * FT_FACE_FLAG_FIXED_WIDTH
+ * FT_FACE_FLAG_HORIZONTAL
+ * FT_FACE_FLAG_VERTICAL
+ * FT_FACE_FLAG_COLOR
+ * FT_FACE_FLAG_SFNT
+ * FT_FACE_FLAG_CID_KEYED
+ * FT_FACE_FLAG_TRICKY
+ * FT_FACE_FLAG_KERNING
+ * FT_FACE_FLAG_MULTIPLE_MASTERS
+ * FT_FACE_FLAG_VARIATION
+ * FT_FACE_FLAG_GLYPH_NAMES
+ * FT_FACE_FLAG_EXTERNAL_STREAM
+ * FT_FACE_FLAG_HINTER
+ *
+ * FT_HAS_HORIZONTAL
+ * FT_HAS_VERTICAL
+ * FT_HAS_KERNING
+ * FT_HAS_FIXED_SIZES
+ * FT_HAS_GLYPH_NAMES
+ * FT_HAS_COLOR
+ * FT_HAS_MULTIPLE_MASTERS
+ *
+ * FT_IS_SFNT
+ * FT_IS_SCALABLE
+ * FT_IS_FIXED_WIDTH
+ * FT_IS_CID_KEYED
+ * FT_IS_TRICKY
+ * FT_IS_NAMED_INSTANCE
+ * FT_IS_VARIATION
+ *
+ * FT_STYLE_FLAG_BOLD
+ * FT_STYLE_FLAG_ITALIC
+ *
+ * FT_SizeRec
+ * FT_Size_Metrics
+ *
+ * FT_GlyphSlotRec
+ * FT_Glyph_Metrics
+ * FT_SubGlyph
+ *
+ * FT_Bitmap_Size
+ *
+ * FT_Init_FreeType
+ * FT_Done_FreeType
+ *
+ * FT_New_Face
+ * FT_Done_Face
+ * FT_Reference_Face
+ * FT_New_Memory_Face
+ * FT_Face_Properties
+ * FT_Open_Face
+ * FT_Open_Args
+ * FT_Parameter
+ * FT_Attach_File
+ * FT_Attach_Stream
+ *
+ * FT_Set_Char_Size
+ * FT_Set_Pixel_Sizes
+ * FT_Request_Size
+ * FT_Select_Size
+ * FT_Size_Request_Type
+ * FT_Size_RequestRec
+ * FT_Size_Request
+ * FT_Set_Transform
+ * FT_Get_Transform
+ * FT_Load_Glyph
+ * FT_Get_Char_Index
+ * FT_Get_First_Char
+ * FT_Get_Next_Char
+ * FT_Get_Name_Index
+ * FT_Load_Char
+ *
+ * FT_OPEN_MEMORY
+ * FT_OPEN_STREAM
+ * FT_OPEN_PATHNAME
+ * FT_OPEN_DRIVER
+ * FT_OPEN_PARAMS
+ *
+ * FT_LOAD_DEFAULT
+ * FT_LOAD_RENDER
+ * FT_LOAD_MONOCHROME
+ * FT_LOAD_LINEAR_DESIGN
+ * FT_LOAD_NO_SCALE
+ * FT_LOAD_NO_HINTING
+ * FT_LOAD_NO_BITMAP
+ * FT_LOAD_NO_AUTOHINT
+ * FT_LOAD_COLOR
+ *
+ * FT_LOAD_VERTICAL_LAYOUT
+ * FT_LOAD_IGNORE_TRANSFORM
+ * FT_LOAD_FORCE_AUTOHINT
+ * FT_LOAD_NO_RECURSE
+ * FT_LOAD_PEDANTIC
+ *
+ * FT_LOAD_TARGET_NORMAL
+ * FT_LOAD_TARGET_LIGHT
+ * FT_LOAD_TARGET_MONO
+ * FT_LOAD_TARGET_LCD
+ * FT_LOAD_TARGET_LCD_V
+ *
+ * FT_LOAD_TARGET_MODE
+ *
+ * FT_Render_Glyph
+ * FT_Render_Mode
+ * FT_Get_Kerning
+ * FT_Kerning_Mode
+ * FT_Get_Track_Kerning
+ * FT_Get_Glyph_Name
+ * FT_Get_Postscript_Name
+ *
+ * FT_CharMapRec
+ * FT_Select_Charmap
+ * FT_Set_Charmap
+ * FT_Get_Charmap_Index
+ *
+ * FT_Get_FSType_Flags
+ * FT_Get_SubGlyph_Info
+ *
+ * FT_Face_Internal
+ * FT_Size_Internal
+ * FT_Slot_Internal
+ *
+ * FT_FACE_FLAG_XXX
+ * FT_STYLE_FLAG_XXX
+ * FT_OPEN_XXX
+ * FT_LOAD_XXX
+ * FT_LOAD_TARGET_XXX
+ * FT_SUBGLYPH_FLAG_XXX
+ * FT_FSTYPE_XXX
+ *
+ * FT_HAS_FAST_GLYPHS
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Glyph_Metrics
+ *
+ * @description:
+ * A structure to model the metrics of a single glyph. The values are
+ * expressed in 26.6 fractional pixel format; if the flag
+ * @FT_LOAD_NO_SCALE has been used while loading the glyph, values are
+ * expressed in font units instead.
+ *
+ * @fields:
+ * width ::
+ * The glyph's width.
+ *
+ * height ::
+ * The glyph's height.
+ *
+ * horiBearingX ::
+ * Left side bearing for horizontal layout.
+ *
+ * horiBearingY ::
+ * Top side bearing for horizontal layout.
+ *
+ * horiAdvance ::
+ * Advance width for horizontal layout.
+ *
+ * vertBearingX ::
+ * Left side bearing for vertical layout.
+ *
+ * vertBearingY ::
+ * Top side bearing for vertical layout. Larger positive values mean
+ * further below the vertical glyph origin.
+ *
+ * vertAdvance ::
+ * Advance height for vertical layout. Positive values mean the glyph
+ * has a positive advance downward.
+ *
+ * @note:
+ * If not disabled with @FT_LOAD_NO_HINTING, the values represent
+ * dimensions of the hinted glyph (in case hinting is applicable).
+ *
+ * Stroking a glyph with an outside border does not increase
+ * `horiAdvance` or `vertAdvance`; you have to manually adjust these
+ * values to account for the added width and height.
+ *
+ * FreeType doesn't use the 'VORG' table data for CFF fonts because it
+ * doesn't have an interface to quickly retrieve the glyph height. The
+ * y~coordinate of the vertical origin can be simply computed as
+ * `vertBearingY + height` after loading a glyph.
+ */
+ typedef struct FT_Glyph_Metrics_
+ {
+ FT_Pos width;
+ FT_Pos height;
+
+ FT_Pos horiBearingX;
+ FT_Pos horiBearingY;
+ FT_Pos horiAdvance;
+
+ FT_Pos vertBearingX;
+ FT_Pos vertBearingY;
+ FT_Pos vertAdvance;
+
+ } FT_Glyph_Metrics;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Bitmap_Size
+ *
+ * @description:
+ * This structure models the metrics of a bitmap strike (i.e., a set of
+ * glyphs for a given point size and resolution) in a bitmap font. It is
+ * used for the `available_sizes` field of @FT_Face.
+ *
+ * @fields:
+ * height ::
+ * The vertical distance, in pixels, between two consecutive baselines.
+ * It is always positive.
+ *
+ * width ::
+ * The average width, in pixels, of all glyphs in the strike.
+ *
+ * size ::
+ * The nominal size of the strike in 26.6 fractional points. This
+ * field is not very useful.
+ *
+ * x_ppem ::
+ * The horizontal ppem (nominal width) in 26.6 fractional pixels.
+ *
+ * y_ppem ::
+ * The vertical ppem (nominal height) in 26.6 fractional pixels.
+ *
+ * @note:
+ * Windows FNT:
+ * The nominal size given in a FNT font is not reliable. If the driver
+ * finds it incorrect, it sets `size` to some calculated values, and
+ * `x_ppem` and `y_ppem` to the pixel width and height given in the
+ * font, respectively.
+ *
+ * TrueType embedded bitmaps:
+ * `size`, `width`, and `height` values are not contained in the bitmap
+ * strike itself. They are computed from the global font parameters.
+ */
+ typedef struct FT_Bitmap_Size_
+ {
+ FT_Short height;
+ FT_Short width;
+
+ FT_Pos size;
+
+ FT_Pos x_ppem;
+ FT_Pos y_ppem;
+
+ } FT_Bitmap_Size;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* O B J E C T C L A S S E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Library
+ *
+ * @description:
+ * A handle to a FreeType library instance. Each 'library' is completely
+ * independent from the others; it is the 'root' of a set of objects like
+ * fonts, faces, sizes, etc.
+ *
+ * It also embeds a memory manager (see @FT_Memory), as well as a
+ * scan-line converter object (see @FT_Raster).
+ *
+ * [Since 2.5.6] In multi-threaded applications it is easiest to use one
+ * `FT_Library` object per thread. In case this is too cumbersome, a
+ * single `FT_Library` object across threads is possible also, as long as
+ * a mutex lock is used around @FT_New_Face and @FT_Done_Face.
+ *
+ * @note:
+ * Library objects are normally created by @FT_Init_FreeType, and
+ * destroyed with @FT_Done_FreeType. If you need reference-counting
+ * (cf. @FT_Reference_Library), use @FT_New_Library and @FT_Done_Library.
+ */
+ typedef struct FT_LibraryRec_ *FT_Library;
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * module_management
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Module
+ *
+ * @description:
+ * A handle to a given FreeType module object. A module can be a font
+ * driver, a renderer, or anything else that provides services to the
+ * former.
+ */
+ typedef struct FT_ModuleRec_* FT_Module;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Driver
+ *
+ * @description:
+ * A handle to a given FreeType font driver object. A font driver is a
+ * module capable of creating faces from font files.
+ */
+ typedef struct FT_DriverRec_* FT_Driver;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Renderer
+ *
+ * @description:
+ * A handle to a given FreeType renderer. A renderer is a module in
+ * charge of converting a glyph's outline image to a bitmap. It supports
+ * a single glyph image format, and one or more target surface depths.
+ */
+ typedef struct FT_RendererRec_* FT_Renderer;
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * base_interface
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Face
+ *
+ * @description:
+ * A handle to a typographic face object. A face object models a given
+ * typeface, in a given style.
+ *
+ * @note:
+ * A face object also owns a single @FT_GlyphSlot object, as well as one
+ * or more @FT_Size objects.
+ *
+ * Use @FT_New_Face or @FT_Open_Face to create a new face object from a
+ * given filepath or a custom input stream.
+ *
+ * Use @FT_Done_Face to destroy it (along with its slot and sizes).
+ *
+ * An `FT_Face` object can only be safely used from one thread at a time.
+ * Similarly, creation and destruction of `FT_Face` with the same
+ * @FT_Library object can only be done from one thread at a time. On the
+ * other hand, functions like @FT_Load_Glyph and its siblings are
+ * thread-safe and do not need the lock to be held as long as the same
+ * `FT_Face` object is not used from multiple threads at the same time.
+ *
+ * @also:
+ * See @FT_FaceRec for the publicly accessible fields of a given face
+ * object.
+ */
+ typedef struct FT_FaceRec_* FT_Face;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Size
+ *
+ * @description:
+ * A handle to an object that models a face scaled to a given character
+ * size.
+ *
+ * @note:
+ * An @FT_Face has one _active_ @FT_Size object that is used by functions
+ * like @FT_Load_Glyph to determine the scaling transformation that in
+ * turn is used to load and hint glyphs and metrics.
+ *
+ * You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size
+ * or even @FT_Select_Size to change the content (i.e., the scaling
+ * values) of the active @FT_Size.
+ *
+ * You can use @FT_New_Size to create additional size objects for a given
+ * @FT_Face, but they won't be used by other functions until you activate
+ * it through @FT_Activate_Size. Only one size can be activated at any
+ * given time per face.
+ *
+ * @also:
+ * See @FT_SizeRec for the publicly accessible fields of a given size
+ * object.
+ */
+ typedef struct FT_SizeRec_* FT_Size;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_GlyphSlot
+ *
+ * @description:
+ * A handle to a given 'glyph slot'. A slot is a container that can hold
+ * any of the glyphs contained in its parent face.
+ *
+ * In other words, each time you call @FT_Load_Glyph or @FT_Load_Char,
+ * the slot's content is erased by the new glyph data, i.e., the glyph's
+ * metrics, its image (bitmap or outline), and other control information.
+ *
+ * @also:
+ * See @FT_GlyphSlotRec for the publicly accessible glyph fields.
+ */
+ typedef struct FT_GlyphSlotRec_* FT_GlyphSlot;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_CharMap
+ *
+ * @description:
+ * A handle to a character map (usually abbreviated to 'charmap'). A
+ * charmap is used to translate character codes in a given encoding into
+ * glyph indexes for its parent's face. Some font formats may provide
+ * several charmaps per font.
+ *
+ * Each face object owns zero or more charmaps, but only one of them can
+ * be 'active', providing the data used by @FT_Get_Char_Index or
+ * @FT_Load_Char.
+ *
+ * The list of available charmaps in a face is available through the
+ * `face->num_charmaps` and `face->charmaps` fields of @FT_FaceRec.
+ *
+ * The currently active charmap is available as `face->charmap`. You
+ * should call @FT_Set_Charmap to change it.
+ *
+ * @note:
+ * When a new face is created (either through @FT_New_Face or
+ * @FT_Open_Face), the library looks for a Unicode charmap within the
+ * list and automatically activates it. If there is no Unicode charmap,
+ * FreeType doesn't set an 'active' charmap.
+ *
+ * @also:
+ * See @FT_CharMapRec for the publicly accessible fields of a given
+ * character map.
+ */
+ typedef struct FT_CharMapRec_* FT_CharMap;
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ENC_TAG
+ *
+ * @description:
+ * This macro converts four-letter tags into an unsigned long. It is
+ * used to define 'encoding' identifiers (see @FT_Encoding).
+ *
+ * @note:
+ * Since many 16-bit compilers don't like 32-bit enumerations, you should
+ * redefine this macro in case of problems to something like this:
+ *
+ * ```
+ * #define FT_ENC_TAG( value, a, b, c, d ) value
+ * ```
+ *
+ * to get a simple enumeration without assigning special numbers.
+ */
+
+#ifndef FT_ENC_TAG
+#define FT_ENC_TAG( value, a, b, c, d ) \
+ value = ( ( (FT_UInt32)(a) << 24 ) | \
+ ( (FT_UInt32)(b) << 16 ) | \
+ ( (FT_UInt32)(c) << 8 ) | \
+ (FT_UInt32)(d) )
+
+#endif /* FT_ENC_TAG */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Encoding
+ *
+ * @description:
+ * An enumeration to specify character sets supported by charmaps. Used
+ * in the @FT_Select_Charmap API function.
+ *
+ * @note:
+ * Despite the name, this enumeration lists specific character
+ * repertories (i.e., charsets), and not text encoding methods (e.g.,
+ * UTF-8, UTF-16, etc.).
+ *
+ * Other encodings might be defined in the future.
+ *
+ * @values:
+ * FT_ENCODING_NONE ::
+ * The encoding value~0 is reserved for all formats except BDF, PCF,
+ * and Windows FNT; see below for more information.
+ *
+ * FT_ENCODING_UNICODE ::
+ * The Unicode character set. This value covers all versions of the
+ * Unicode repertoire, including ASCII and Latin-1. Most fonts include
+ * a Unicode charmap, but not all of them.
+ *
+ * For example, if you want to access Unicode value U+1F028 (and the
+ * font contains it), use value 0x1F028 as the input value for
+ * @FT_Get_Char_Index.
+ *
+ * FT_ENCODING_MS_SYMBOL ::
+ * Microsoft Symbol encoding, used to encode mathematical symbols and
+ * wingdings. For more information, see
+ * 'https://www.microsoft.com/typography/otspec/recom.htm#non-standard-symbol-fonts',
+ * 'http://www.kostis.net/charsets/symbol.htm', and
+ * 'http://www.kostis.net/charsets/wingding.htm'.
+ *
+ * This encoding uses character codes from the PUA (Private Unicode
+ * Area) in the range U+F020-U+F0FF.
+ *
+ * FT_ENCODING_SJIS ::
+ * Shift JIS encoding for Japanese. More info at
+ * 'https://en.wikipedia.org/wiki/Shift_JIS'. See note on multi-byte
+ * encodings below.
+ *
+ * FT_ENCODING_PRC ::
+ * Corresponds to encoding systems mainly for Simplified Chinese as
+ * used in People's Republic of China (PRC). The encoding layout is
+ * based on GB~2312 and its supersets GBK and GB~18030.
+ *
+ * FT_ENCODING_BIG5 ::
+ * Corresponds to an encoding system for Traditional Chinese as used in
+ * Taiwan and Hong Kong.
+ *
+ * FT_ENCODING_WANSUNG ::
+ * Corresponds to the Korean encoding system known as Extended Wansung
+ * (MS Windows code page 949). For more information see
+ * 'https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit949.txt'.
+ *
+ * FT_ENCODING_JOHAB ::
+ * The Korean standard character set (KS~C 5601-1992), which
+ * corresponds to MS Windows code page 1361. This character set
+ * includes all possible Hangul character combinations.
+ *
+ * FT_ENCODING_ADOBE_LATIN_1 ::
+ * Corresponds to a Latin-1 encoding as defined in a Type~1 PostScript
+ * font. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_ADOBE_STANDARD ::
+ * Adobe Standard encoding, as found in Type~1, CFF, and OpenType/CFF
+ * fonts. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_ADOBE_EXPERT ::
+ * Adobe Expert encoding, as found in Type~1, CFF, and OpenType/CFF
+ * fonts. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_ADOBE_CUSTOM ::
+ * Corresponds to a custom encoding, as found in Type~1, CFF, and
+ * OpenType/CFF fonts. It is limited to 256 character codes.
+ *
+ * FT_ENCODING_APPLE_ROMAN ::
+ * Apple roman encoding. Many TrueType and OpenType fonts contain a
+ * charmap for this 8-bit encoding, since older versions of Mac OS are
+ * able to use it.
+ *
+ * FT_ENCODING_OLD_LATIN_2 ::
+ * This value is deprecated and was neither used nor reported by
+ * FreeType. Don't use or test for it.
+ *
+ * FT_ENCODING_MS_SJIS ::
+ * Same as FT_ENCODING_SJIS. Deprecated.
+ *
+ * FT_ENCODING_MS_GB2312 ::
+ * Same as FT_ENCODING_PRC. Deprecated.
+ *
+ * FT_ENCODING_MS_BIG5 ::
+ * Same as FT_ENCODING_BIG5. Deprecated.
+ *
+ * FT_ENCODING_MS_WANSUNG ::
+ * Same as FT_ENCODING_WANSUNG. Deprecated.
+ *
+ * FT_ENCODING_MS_JOHAB ::
+ * Same as FT_ENCODING_JOHAB. Deprecated.
+ *
+ * @note:
+ * By default, FreeType enables a Unicode charmap and tags it with
+ * `FT_ENCODING_UNICODE` when it is either provided or can be generated
+ * from PostScript glyph name dictionaries in the font file. All other
+ * encodings are considered legacy and tagged only if explicitly defined
+ * in the font file. Otherwise, `FT_ENCODING_NONE` is used.
+ *
+ * `FT_ENCODING_NONE` is set by the BDF and PCF drivers if the charmap is
+ * neither Unicode nor ISO-8859-1 (otherwise it is set to
+ * `FT_ENCODING_UNICODE`). Use @FT_Get_BDF_Charset_ID to find out which
+ * encoding is really present. If, for example, the `cs_registry` field
+ * is 'KOI8' and the `cs_encoding` field is 'R', the font is encoded in
+ * KOI8-R.
+ *
+ * `FT_ENCODING_NONE` is always set (with a single exception) by the
+ * winfonts driver. Use @FT_Get_WinFNT_Header and examine the `charset`
+ * field of the @FT_WinFNT_HeaderRec structure to find out which encoding
+ * is really present. For example, @FT_WinFNT_ID_CP1251 (204) means
+ * Windows code page 1251 (for Russian).
+ *
+ * `FT_ENCODING_NONE` is set if `platform_id` is @TT_PLATFORM_MACINTOSH
+ * and `encoding_id` is not `TT_MAC_ID_ROMAN` (otherwise it is set to
+ * `FT_ENCODING_APPLE_ROMAN`).
+ *
+ * If `platform_id` is @TT_PLATFORM_MACINTOSH, use the function
+ * @FT_Get_CMap_Language_ID to query the Mac language ID that may be
+ * needed to be able to distinguish Apple encoding variants. See
+ *
+ * https://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/Readme.txt
+ *
+ * to get an idea how to do that. Basically, if the language ID is~0,
+ * don't use it, otherwise subtract 1 from the language ID. Then examine
+ * `encoding_id`. If, for example, `encoding_id` is `TT_MAC_ID_ROMAN`
+ * and the language ID (minus~1) is `TT_MAC_LANGID_GREEK`, it is the
+ * Greek encoding, not Roman. `TT_MAC_ID_ARABIC` with
+ * `TT_MAC_LANGID_FARSI` means the Farsi variant the Arabic encoding.
+ */
+ typedef enum FT_Encoding_
+ {
+ FT_ENC_TAG( FT_ENCODING_NONE, 0, 0, 0, 0 ),
+
+ FT_ENC_TAG( FT_ENCODING_MS_SYMBOL, 's', 'y', 'm', 'b' ),
+ FT_ENC_TAG( FT_ENCODING_UNICODE, 'u', 'n', 'i', 'c' ),
+
+ FT_ENC_TAG( FT_ENCODING_SJIS, 's', 'j', 'i', 's' ),
+ FT_ENC_TAG( FT_ENCODING_PRC, 'g', 'b', ' ', ' ' ),
+ FT_ENC_TAG( FT_ENCODING_BIG5, 'b', 'i', 'g', '5' ),
+ FT_ENC_TAG( FT_ENCODING_WANSUNG, 'w', 'a', 'n', 's' ),
+ FT_ENC_TAG( FT_ENCODING_JOHAB, 'j', 'o', 'h', 'a' ),
+
+ /* for backward compatibility */
+ FT_ENCODING_GB2312 = FT_ENCODING_PRC,
+ FT_ENCODING_MS_SJIS = FT_ENCODING_SJIS,
+ FT_ENCODING_MS_GB2312 = FT_ENCODING_PRC,
+ FT_ENCODING_MS_BIG5 = FT_ENCODING_BIG5,
+ FT_ENCODING_MS_WANSUNG = FT_ENCODING_WANSUNG,
+ FT_ENCODING_MS_JOHAB = FT_ENCODING_JOHAB,
+
+ FT_ENC_TAG( FT_ENCODING_ADOBE_STANDARD, 'A', 'D', 'O', 'B' ),
+ FT_ENC_TAG( FT_ENCODING_ADOBE_EXPERT, 'A', 'D', 'B', 'E' ),
+ FT_ENC_TAG( FT_ENCODING_ADOBE_CUSTOM, 'A', 'D', 'B', 'C' ),
+ FT_ENC_TAG( FT_ENCODING_ADOBE_LATIN_1, 'l', 'a', 't', '1' ),
+
+ FT_ENC_TAG( FT_ENCODING_OLD_LATIN_2, 'l', 'a', 't', '2' ),
+
+ FT_ENC_TAG( FT_ENCODING_APPLE_ROMAN, 'a', 'r', 'm', 'n' )
+
+ } FT_Encoding;
+
+
+ /* these constants are deprecated; use the corresponding `FT_Encoding` */
+ /* values instead */
+#define ft_encoding_none FT_ENCODING_NONE
+#define ft_encoding_unicode FT_ENCODING_UNICODE
+#define ft_encoding_symbol FT_ENCODING_MS_SYMBOL
+#define ft_encoding_latin_1 FT_ENCODING_ADOBE_LATIN_1
+#define ft_encoding_latin_2 FT_ENCODING_OLD_LATIN_2
+#define ft_encoding_sjis FT_ENCODING_SJIS
+#define ft_encoding_gb2312 FT_ENCODING_PRC
+#define ft_encoding_big5 FT_ENCODING_BIG5
+#define ft_encoding_wansung FT_ENCODING_WANSUNG
+#define ft_encoding_johab FT_ENCODING_JOHAB
+
+#define ft_encoding_adobe_standard FT_ENCODING_ADOBE_STANDARD
+#define ft_encoding_adobe_expert FT_ENCODING_ADOBE_EXPERT
+#define ft_encoding_adobe_custom FT_ENCODING_ADOBE_CUSTOM
+#define ft_encoding_apple_roman FT_ENCODING_APPLE_ROMAN
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_CharMapRec
+ *
+ * @description:
+ * The base charmap structure.
+ *
+ * @fields:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * encoding ::
+ * An @FT_Encoding tag identifying the charmap. Use this with
+ * @FT_Select_Charmap.
+ *
+ * platform_id ::
+ * An ID number describing the platform for the following encoding ID.
+ * This comes directly from the TrueType specification and gets
+ * emulated for other formats.
+ *
+ * encoding_id ::
+ * A platform-specific encoding number. This also comes from the
+ * TrueType specification and gets emulated similarly.
+ */
+ typedef struct FT_CharMapRec_
+ {
+ FT_Face face;
+ FT_Encoding encoding;
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+
+ } FT_CharMapRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* B A S E O B J E C T C L A S S E S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Face_Internal
+ *
+ * @description:
+ * An opaque handle to an `FT_Face_InternalRec` structure that models the
+ * private data of a given @FT_Face object.
+ *
+ * This structure might change between releases of FreeType~2 and is not
+ * generally available to client applications.
+ */
+ typedef struct FT_Face_InternalRec_* FT_Face_Internal;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_FaceRec
+ *
+ * @description:
+ * FreeType root face class structure. A face object models a typeface
+ * in a font file.
+ *
+ * @fields:
+ * num_faces ::
+ * The number of faces in the font file. Some font formats can have
+ * multiple faces in a single font file.
+ *
+ * face_index ::
+ * This field holds two different values. Bits 0-15 are the index of
+ * the face in the font file (starting with value~0). They are set
+ * to~0 if there is only one face in the font file.
+ *
+ * [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation
+ * fonts only, holding the named instance index for the current face
+ * index (starting with value~1; value~0 indicates font access without
+ * a named instance). For non-variation fonts, bits 16-30 are ignored.
+ * If we have the third named instance of face~4, say, `face_index` is
+ * set to 0x00030004.
+ *
+ * Bit 31 is always zero (this is, `face_index` is always a positive
+ * value).
+ *
+ * [Since 2.9] Changing the design coordinates with
+ * @FT_Set_Var_Design_Coordinates or @FT_Set_Var_Blend_Coordinates does
+ * not influence the named instance index value (only
+ * @FT_Set_Named_Instance does that).
+ *
+ * face_flags ::
+ * A set of bit flags that give important information about the face;
+ * see @FT_FACE_FLAG_XXX for the details.
+ *
+ * style_flags ::
+ * The lower 16~bits contain a set of bit flags indicating the style of
+ * the face; see @FT_STYLE_FLAG_XXX for the details.
+ *
+ * [Since 2.6.1] Bits 16-30 hold the number of named instances
+ * available for the current face if we have a GX or OpenType variation
+ * (sub)font. Bit 31 is always zero (this is, `style_flags` is always
+ * a positive value). Note that a variation font has always at least
+ * one named instance, namely the default instance.
+ *
+ * num_glyphs ::
+ * The number of glyphs in the face. If the face is scalable and has
+ * sbits (see `num_fixed_sizes`), it is set to the number of outline
+ * glyphs.
+ *
+ * For CID-keyed fonts (not in an SFNT wrapper) this value gives the
+ * highest CID used in the font.
+ *
+ * family_name ::
+ * The face's family name. This is an ASCII string, usually in
+ * English, that describes the typeface's family (like 'Times New
+ * Roman', 'Bodoni', 'Garamond', etc). This is a least common
+ * denominator used to list fonts. Some formats (TrueType & OpenType)
+ * provide localized and Unicode versions of this string. Applications
+ * should use the format-specific interface to access them. Can be
+ * `NULL` (e.g., in fonts embedded in a PDF file).
+ *
+ * In case the font doesn't provide a specific family name entry,
+ * FreeType tries to synthesize one, deriving it from other name
+ * entries.
+ *
+ * style_name ::
+ * The face's style name. This is an ASCII string, usually in English,
+ * that describes the typeface's style (like 'Italic', 'Bold',
+ * 'Condensed', etc). Not all font formats provide a style name, so
+ * this field is optional, and can be set to `NULL`. As for
+ * `family_name`, some formats provide localized and Unicode versions
+ * of this string. Applications should use the format-specific
+ * interface to access them.
+ *
+ * num_fixed_sizes ::
+ * The number of bitmap strikes in the face. Even if the face is
+ * scalable, there might still be bitmap strikes, which are called
+ * 'sbits' in that case.
+ *
+ * available_sizes ::
+ * An array of @FT_Bitmap_Size for all bitmap strikes in the face. It
+ * is set to `NULL` if there is no bitmap strike.
+ *
+ * Note that FreeType tries to sanitize the strike data since they are
+ * sometimes sloppy or incorrect, but this can easily fail.
+ *
+ * num_charmaps ::
+ * The number of charmaps in the face.
+ *
+ * charmaps ::
+ * An array of the charmaps of the face.
+ *
+ * generic ::
+ * A field reserved for client uses. See the @FT_Generic type
+ * description.
+ *
+ * bbox ::
+ * The font bounding box. Coordinates are expressed in font units (see
+ * `units_per_EM`). The box is large enough to contain any glyph from
+ * the font. Thus, `bbox.yMax` can be seen as the 'maximum ascender',
+ * and `bbox.yMin` as the 'minimum descender'. Only relevant for
+ * scalable formats.
+ *
+ * Note that the bounding box might be off by (at least) one pixel for
+ * hinted fonts. See @FT_Size_Metrics for further discussion.
+ *
+ * Note that the bounding box does not vary in OpenType variable fonts
+ * and should only be used in relation to the default instance.
+ *
+ * units_per_EM ::
+ * The number of font units per EM square for this face. This is
+ * typically 2048 for TrueType fonts, and 1000 for Type~1 fonts. Only
+ * relevant for scalable formats.
+ *
+ * ascender ::
+ * The typographic ascender of the face, expressed in font units. For
+ * font formats not having this information, it is set to `bbox.yMax`.
+ * Only relevant for scalable formats.
+ *
+ * descender ::
+ * The typographic descender of the face, expressed in font units. For
+ * font formats not having this information, it is set to `bbox.yMin`.
+ * Note that this field is negative for values below the baseline.
+ * Only relevant for scalable formats.
+ *
+ * height ::
+ * This value is the vertical distance between two consecutive
+ * baselines, expressed in font units. It is always positive. Only
+ * relevant for scalable formats.
+ *
+ * If you want the global glyph height, use `ascender - descender`.
+ *
+ * max_advance_width ::
+ * The maximum advance width, in font units, for all glyphs in this
+ * face. This can be used to make word wrapping computations faster.
+ * Only relevant for scalable formats.
+ *
+ * max_advance_height ::
+ * The maximum advance height, in font units, for all glyphs in this
+ * face. This is only relevant for vertical layouts, and is set to
+ * `height` for fonts that do not provide vertical metrics. Only
+ * relevant for scalable formats.
+ *
+ * underline_position ::
+ * The position, in font units, of the underline line for this face.
+ * It is the center of the underlining stem. Only relevant for
+ * scalable formats.
+ *
+ * underline_thickness ::
+ * The thickness, in font units, of the underline for this face. Only
+ * relevant for scalable formats.
+ *
+ * glyph ::
+ * The face's associated glyph slot(s).
+ *
+ * size ::
+ * The current active size for this face.
+ *
+ * charmap ::
+ * The current active charmap for this face.
+ *
+ * @note:
+ * Fields may be changed after a call to @FT_Attach_File or
+ * @FT_Attach_Stream.
+ *
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `ascender`, `descender`, `height`,
+ * `underline_position`, and `underline_thickness`.
+ *
+ * Especially for TrueType fonts see also the documentation for
+ * @FT_Size_Metrics.
+ */
+ typedef struct FT_FaceRec_
+ {
+ FT_Long num_faces;
+ FT_Long face_index;
+
+ FT_Long face_flags;
+ FT_Long style_flags;
+
+ FT_Long num_glyphs;
+
+ FT_String* family_name;
+ FT_String* style_name;
+
+ FT_Int num_fixed_sizes;
+ FT_Bitmap_Size* available_sizes;
+
+ FT_Int num_charmaps;
+ FT_CharMap* charmaps;
+
+ FT_Generic generic;
+
+ /*# The following member variables (down to `underline_thickness`) */
+ /*# are only relevant to scalable outlines; cf. @FT_Bitmap_Size */
+ /*# for bitmap fonts. */
+ FT_BBox bbox;
+
+ FT_UShort units_per_EM;
+ FT_Short ascender;
+ FT_Short descender;
+ FT_Short height;
+
+ FT_Short max_advance_width;
+ FT_Short max_advance_height;
+
+ FT_Short underline_position;
+ FT_Short underline_thickness;
+
+ FT_GlyphSlot glyph;
+ FT_Size size;
+ FT_CharMap charmap;
+
+ /*@private begin */
+
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Stream stream;
+
+ FT_ListRec sizes_list;
+
+ FT_Generic autohint; /* face-specific auto-hinter data */
+ void* extensions; /* unused */
+
+ FT_Face_Internal internal;
+
+ /*@private end */
+
+ } FT_FaceRec;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_FACE_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flags used in the `face_flags` field of the @FT_FaceRec
+ * structure. They inform client applications of properties of the
+ * corresponding face.
+ *
+ * @values:
+ * FT_FACE_FLAG_SCALABLE ::
+ * The face contains outline glyphs. Note that a face can contain
+ * bitmap strikes also, i.e., a face can have both this flag and
+ * @FT_FACE_FLAG_FIXED_SIZES set.
+ *
+ * FT_FACE_FLAG_FIXED_SIZES ::
+ * The face contains bitmap strikes. See also the `num_fixed_sizes`
+ * and `available_sizes` fields of @FT_FaceRec.
+ *
+ * FT_FACE_FLAG_FIXED_WIDTH ::
+ * The face contains fixed-width characters (like Courier, Lucida,
+ * MonoType, etc.).
+ *
+ * FT_FACE_FLAG_SFNT ::
+ * The face uses the SFNT storage scheme. For now, this means TrueType
+ * and OpenType.
+ *
+ * FT_FACE_FLAG_HORIZONTAL ::
+ * The face contains horizontal glyph metrics. This should be set for
+ * all common formats.
+ *
+ * FT_FACE_FLAG_VERTICAL ::
+ * The face contains vertical glyph metrics. This is only available in
+ * some formats, not all of them.
+ *
+ * FT_FACE_FLAG_KERNING ::
+ * The face contains kerning information. If set, the kerning distance
+ * can be retrieved using the function @FT_Get_Kerning. Otherwise the
+ * function always return the vector (0,0). Note that FreeType doesn't
+ * handle kerning data from the SFNT 'GPOS' table (as present in many
+ * OpenType fonts).
+ *
+ * FT_FACE_FLAG_FAST_GLYPHS ::
+ * THIS FLAG IS DEPRECATED. DO NOT USE OR TEST IT.
+ *
+ * FT_FACE_FLAG_MULTIPLE_MASTERS ::
+ * The face contains multiple masters and is capable of interpolating
+ * between them. Supported formats are Adobe MM, TrueType GX, and
+ * OpenType variation fonts.
+ *
+ * See section @multiple_masters for API details.
+ *
+ * FT_FACE_FLAG_GLYPH_NAMES ::
+ * The face contains glyph names, which can be retrieved using
+ * @FT_Get_Glyph_Name. Note that some TrueType fonts contain broken
+ * glyph name tables. Use the function @FT_Has_PS_Glyph_Names when
+ * needed.
+ *
+ * FT_FACE_FLAG_EXTERNAL_STREAM ::
+ * Used internally by FreeType to indicate that a face's stream was
+ * provided by the client application and should not be destroyed when
+ * @FT_Done_Face is called. Don't read or test this flag.
+ *
+ * FT_FACE_FLAG_HINTER ::
+ * The font driver has a hinting machine of its own. For example, with
+ * TrueType fonts, it makes sense to use data from the SFNT 'gasp'
+ * table only if the native TrueType hinting engine (with the bytecode
+ * interpreter) is available and active.
+ *
+ * FT_FACE_FLAG_CID_KEYED ::
+ * The face is CID-keyed. In that case, the face is not accessed by
+ * glyph indices but by CID values. For subsetted CID-keyed fonts this
+ * has the consequence that not all index values are a valid argument
+ * to @FT_Load_Glyph. Only the CID values for which corresponding
+ * glyphs in the subsetted font exist make `FT_Load_Glyph` return
+ * successfully; in all other cases you get an
+ * `FT_Err_Invalid_Argument` error.
+ *
+ * Note that CID-keyed fonts that are in an SFNT wrapper (this is, all
+ * OpenType/CFF fonts) don't have this flag set since the glyphs are
+ * accessed in the normal way (using contiguous indices); the
+ * 'CID-ness' isn't visible to the application.
+ *
+ * FT_FACE_FLAG_TRICKY ::
+ * The face is 'tricky', this is, it always needs the font format's
+ * native hinting engine to get a reasonable result. A typical example
+ * is the old Chinese font `mingli.ttf` (but not `mingliu.ttc`) that
+ * uses TrueType bytecode instructions to move and scale all of its
+ * subglyphs.
+ *
+ * It is not possible to auto-hint such fonts using
+ * @FT_LOAD_FORCE_AUTOHINT; it will also ignore @FT_LOAD_NO_HINTING.
+ * You have to set both @FT_LOAD_NO_HINTING and @FT_LOAD_NO_AUTOHINT to
+ * really disable hinting; however, you probably never want this except
+ * for demonstration purposes.
+ *
+ * Currently, there are about a dozen TrueType fonts in the list of
+ * tricky fonts; they are hard-coded in file `ttobjs.c`.
+ *
+ * FT_FACE_FLAG_COLOR ::
+ * [Since 2.5.1] The face has color glyph tables. See @FT_LOAD_COLOR
+ * for more information.
+ *
+ * FT_FACE_FLAG_VARIATION ::
+ * [Since 2.9] Set if the current face (or named instance) has been
+ * altered with @FT_Set_MM_Design_Coordinates,
+ * @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates.
+ * This flag is unset by a call to @FT_Set_Named_Instance.
+ */
+#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
+#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
+#define FT_FACE_FLAG_FIXED_WIDTH ( 1L << 2 )
+#define FT_FACE_FLAG_SFNT ( 1L << 3 )
+#define FT_FACE_FLAG_HORIZONTAL ( 1L << 4 )
+#define FT_FACE_FLAG_VERTICAL ( 1L << 5 )
+#define FT_FACE_FLAG_KERNING ( 1L << 6 )
+#define FT_FACE_FLAG_FAST_GLYPHS ( 1L << 7 )
+#define FT_FACE_FLAG_MULTIPLE_MASTERS ( 1L << 8 )
+#define FT_FACE_FLAG_GLYPH_NAMES ( 1L << 9 )
+#define FT_FACE_FLAG_EXTERNAL_STREAM ( 1L << 10 )
+#define FT_FACE_FLAG_HINTER ( 1L << 11 )
+#define FT_FACE_FLAG_CID_KEYED ( 1L << 12 )
+#define FT_FACE_FLAG_TRICKY ( 1L << 13 )
+#define FT_FACE_FLAG_COLOR ( 1L << 14 )
+#define FT_FACE_FLAG_VARIATION ( 1L << 15 )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_HORIZONTAL
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains horizontal
+ * metrics (this is true for all font formats though).
+ *
+ * @also:
+ * @FT_HAS_VERTICAL can be used to check for vertical metrics.
+ *
+ */
+#define FT_HAS_HORIZONTAL( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_HORIZONTAL ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_VERTICAL
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains real
+ * vertical metrics (and not only synthesized ones).
+ *
+ */
+#define FT_HAS_VERTICAL( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_VERTICAL ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_KERNING
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains kerning data
+ * that can be accessed with @FT_Get_Kerning.
+ *
+ */
+#define FT_HAS_KERNING( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_KERNING ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_SCALABLE
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a scalable
+ * font face (true for TrueType, Type~1, Type~42, CID, OpenType/CFF, and
+ * PFR font formats).
+ *
+ */
+#define FT_IS_SCALABLE( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SCALABLE ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_SFNT
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a font whose
+ * format is based on the SFNT storage scheme. This usually means:
+ * TrueType fonts, OpenType fonts, as well as SFNT-based embedded bitmap
+ * fonts.
+ *
+ * If this macro is true, all functions defined in @FT_SFNT_NAMES_H and
+ * @FT_TRUETYPE_TABLES_H are available.
+ *
+ */
+#define FT_IS_SFNT( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SFNT ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_FIXED_WIDTH
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a font face
+ * that contains fixed-width (or 'monospace', 'fixed-pitch', etc.)
+ * glyphs.
+ *
+ */
+#define FT_IS_FIXED_WIDTH( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_WIDTH ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_FIXED_SIZES
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains some
+ * embedded bitmaps. See the `available_sizes` field of the @FT_FaceRec
+ * structure.
+ *
+ */
+#define FT_HAS_FIXED_SIZES( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_FIXED_SIZES ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_FAST_GLYPHS
+ *
+ * @description:
+ * Deprecated.
+ *
+ */
+#define FT_HAS_FAST_GLYPHS( face ) 0
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_GLYPH_NAMES
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains some glyph
+ * names that can be accessed through @FT_Get_Glyph_Name.
+ *
+ */
+#define FT_HAS_GLYPH_NAMES( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_MULTIPLE_MASTERS
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains some
+ * multiple masters. The functions provided by @FT_MULTIPLE_MASTERS_H
+ * are then available to choose the exact design you want.
+ *
+ */
+#define FT_HAS_MULTIPLE_MASTERS( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_NAMED_INSTANCE
+ *
+ * @description:
+ * A macro that returns true whenever a face object is a named instance
+ * of a GX or OpenType variation font.
+ *
+ * [Since 2.9] Changing the design coordinates with
+ * @FT_Set_Var_Design_Coordinates or @FT_Set_Var_Blend_Coordinates does
+ * not influence the return value of this macro (only
+ * @FT_Set_Named_Instance does that).
+ *
+ * @since:
+ * 2.7
+ *
+ */
+#define FT_IS_NAMED_INSTANCE( face ) \
+ ( !!( (face)->face_index & 0x7FFF0000L ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_VARIATION
+ *
+ * @description:
+ * A macro that returns true whenever a face object has been altered by
+ * @FT_Set_MM_Design_Coordinates, @FT_Set_Var_Design_Coordinates, or
+ * @FT_Set_Var_Blend_Coordinates.
+ *
+ * @since:
+ * 2.9
+ *
+ */
+#define FT_IS_VARIATION( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_VARIATION ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_CID_KEYED
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains a CID-keyed
+ * font. See the discussion of @FT_FACE_FLAG_CID_KEYED for more details.
+ *
+ * If this macro is true, all functions defined in @FT_CID_H are
+ * available.
+ *
+ */
+#define FT_IS_CID_KEYED( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_CID_KEYED ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IS_TRICKY
+ *
+ * @description:
+ * A macro that returns true whenever a face represents a 'tricky' font.
+ * See the discussion of @FT_FACE_FLAG_TRICKY for more details.
+ *
+ */
+#define FT_IS_TRICKY( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_TRICKY ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_COLOR
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains tables for
+ * color glyphs.
+ *
+ * @since:
+ * 2.5.1
+ *
+ */
+#define FT_HAS_COLOR( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_COLOR ) )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_STYLE_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flags to indicate the style of a given face. These are
+ * used in the `style_flags` field of @FT_FaceRec.
+ *
+ * @values:
+ * FT_STYLE_FLAG_ITALIC ::
+ * The face style is italic or oblique.
+ *
+ * FT_STYLE_FLAG_BOLD ::
+ * The face is bold.
+ *
+ * @note:
+ * The style information as provided by FreeType is very basic. More
+ * details are beyond the scope and should be done on a higher level (for
+ * example, by analyzing various fields of the 'OS/2' table in SFNT based
+ * fonts).
+ */
+#define FT_STYLE_FLAG_ITALIC ( 1 << 0 )
+#define FT_STYLE_FLAG_BOLD ( 1 << 1 )
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Size_Internal
+ *
+ * @description:
+ * An opaque handle to an `FT_Size_InternalRec` structure, used to model
+ * private data of a given @FT_Size object.
+ */
+ typedef struct FT_Size_InternalRec_* FT_Size_Internal;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_Metrics
+ *
+ * @description:
+ * The size metrics structure gives the metrics of a size object.
+ *
+ * @fields:
+ * x_ppem ::
+ * The width of the scaled EM square in pixels, hence the term 'ppem'
+ * (pixels per EM). It is also referred to as 'nominal width'.
+ *
+ * y_ppem ::
+ * The height of the scaled EM square in pixels, hence the term 'ppem'
+ * (pixels per EM). It is also referred to as 'nominal height'.
+ *
+ * x_scale ::
+ * A 16.16 fractional scaling value to convert horizontal metrics from
+ * font units to 26.6 fractional pixels. Only relevant for scalable
+ * font formats.
+ *
+ * y_scale ::
+ * A 16.16 fractional scaling value to convert vertical metrics from
+ * font units to 26.6 fractional pixels. Only relevant for scalable
+ * font formats.
+ *
+ * ascender ::
+ * The ascender in 26.6 fractional pixels, rounded up to an integer
+ * value. See @FT_FaceRec for the details.
+ *
+ * descender ::
+ * The descender in 26.6 fractional pixels, rounded down to an integer
+ * value. See @FT_FaceRec for the details.
+ *
+ * height ::
+ * The height in 26.6 fractional pixels, rounded to an integer value.
+ * See @FT_FaceRec for the details.
+ *
+ * max_advance ::
+ * The maximum advance width in 26.6 fractional pixels, rounded to an
+ * integer value. See @FT_FaceRec for the details.
+ *
+ * @note:
+ * The scaling values, if relevant, are determined first during a size
+ * changing operation. The remaining fields are then set by the driver.
+ * For scalable formats, they are usually set to scaled values of the
+ * corresponding fields in @FT_FaceRec. Some values like ascender or
+ * descender are rounded for historical reasons; more precise values (for
+ * outline fonts) can be derived by scaling the corresponding @FT_FaceRec
+ * values manually, with code similar to the following.
+ *
+ * ```
+ * scaled_ascender = FT_MulFix( face->ascender,
+ * size_metrics->y_scale );
+ * ```
+ *
+ * Note that due to glyph hinting and the selected rendering mode these
+ * values are usually not exact; consequently, they must be treated as
+ * unreliable with an error margin of at least one pixel!
+ *
+ * Indeed, the only way to get the exact metrics is to render _all_
+ * glyphs. As this would be a definite performance hit, it is up to
+ * client applications to perform such computations.
+ *
+ * The `FT_Size_Metrics` structure is valid for bitmap fonts also.
+ *
+ *
+ * **TrueType fonts with native bytecode hinting**
+ *
+ * All applications that handle TrueType fonts with native hinting must
+ * be aware that TTFs expect different rounding of vertical font
+ * dimensions. The application has to cater for this, especially if it
+ * wants to rely on a TTF's vertical data (for example, to properly align
+ * box characters vertically).
+ *
+ * Only the application knows _in advance_ that it is going to use native
+ * hinting for TTFs! FreeType, on the other hand, selects the hinting
+ * mode not at the time of creating an @FT_Size object but much later,
+ * namely while calling @FT_Load_Glyph.
+ *
+ * Here is some pseudo code that illustrates a possible solution.
+ *
+ * ```
+ * font_format = FT_Get_Font_Format( face );
+ *
+ * if ( !strcmp( font_format, "TrueType" ) &&
+ * do_native_bytecode_hinting )
+ * {
+ * ascender = ROUND( FT_MulFix( face->ascender,
+ * size_metrics->y_scale ) );
+ * descender = ROUND( FT_MulFix( face->descender,
+ * size_metrics->y_scale ) );
+ * }
+ * else
+ * {
+ * ascender = size_metrics->ascender;
+ * descender = size_metrics->descender;
+ * }
+ *
+ * height = size_metrics->height;
+ * max_advance = size_metrics->max_advance;
+ * ```
+ */
+ typedef struct FT_Size_Metrics_
+ {
+ FT_UShort x_ppem; /* horizontal pixels per EM */
+ FT_UShort y_ppem; /* vertical pixels per EM */
+
+ FT_Fixed x_scale; /* scaling values used to convert font */
+ FT_Fixed y_scale; /* units to 26.6 fractional pixels */
+
+ FT_Pos ascender; /* ascender in 26.6 frac. pixels */
+ FT_Pos descender; /* descender in 26.6 frac. pixels */
+ FT_Pos height; /* text height in 26.6 frac. pixels */
+ FT_Pos max_advance; /* max horizontal advance, in 26.6 pixels */
+
+ } FT_Size_Metrics;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SizeRec
+ *
+ * @description:
+ * FreeType root size class structure. A size object models a face
+ * object at a given size.
+ *
+ * @fields:
+ * face ::
+ * Handle to the parent face object.
+ *
+ * generic ::
+ * A typeless pointer, unused by the FreeType library or any of its
+ * drivers. It can be used by client applications to link their own
+ * data to each size object.
+ *
+ * metrics ::
+ * Metrics for this size object. This field is read-only.
+ */
+ typedef struct FT_SizeRec_
+ {
+ FT_Face face; /* parent face object */
+ FT_Generic generic; /* generic pointer for client uses */
+ FT_Size_Metrics metrics; /* size metrics */
+ FT_Size_Internal internal;
+
+ } FT_SizeRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SubGlyph
+ *
+ * @description:
+ * The subglyph structure is an internal object used to describe
+ * subglyphs (for example, in the case of composites).
+ *
+ * @note:
+ * The subglyph implementation is not part of the high-level API, hence
+ * the forward structure declaration.
+ *
+ * You can however retrieve subglyph information with
+ * @FT_Get_SubGlyph_Info.
+ */
+ typedef struct FT_SubGlyphRec_* FT_SubGlyph;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Slot_Internal
+ *
+ * @description:
+ * An opaque handle to an `FT_Slot_InternalRec` structure, used to model
+ * private data of a given @FT_GlyphSlot object.
+ */
+ typedef struct FT_Slot_InternalRec_* FT_Slot_Internal;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_GlyphSlotRec
+ *
+ * @description:
+ * FreeType root glyph slot class structure. A glyph slot is a container
+ * where individual glyphs can be loaded, be they in outline or bitmap
+ * format.
+ *
+ * @fields:
+ * library ::
+ * A handle to the FreeType library instance this slot belongs to.
+ *
+ * face ::
+ * A handle to the parent face object.
+ *
+ * next ::
+ * In some cases (like some font tools), several glyph slots per face
+ * object can be a good thing. As this is rare, the glyph slots are
+ * listed through a direct, single-linked list using its `next` field.
+ *
+ * glyph_index ::
+ * [Since 2.10] The glyph index passed as an argument to @FT_Load_Glyph
+ * while initializing the glyph slot.
+ *
+ * generic ::
+ * A typeless pointer unused by the FreeType library or any of its
+ * drivers. It can be used by client applications to link their own
+ * data to each glyph slot object.
+ *
+ * metrics ::
+ * The metrics of the last loaded glyph in the slot. The returned
+ * values depend on the last load flags (see the @FT_Load_Glyph API
+ * function) and can be expressed either in 26.6 fractional pixels or
+ * font units.
+ *
+ * Note that even when the glyph image is transformed, the metrics are
+ * not.
+ *
+ * linearHoriAdvance ::
+ * The advance width of the unhinted glyph. Its value is expressed in
+ * 16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when
+ * loading the glyph. This field can be important to perform correct
+ * WYSIWYG layout. Only relevant for outline glyphs.
+ *
+ * linearVertAdvance ::
+ * The advance height of the unhinted glyph. Its value is expressed in
+ * 16.16 fractional pixels, unless @FT_LOAD_LINEAR_DESIGN is set when
+ * loading the glyph. This field can be important to perform correct
+ * WYSIWYG layout. Only relevant for outline glyphs.
+ *
+ * advance ::
+ * This shorthand is, depending on @FT_LOAD_IGNORE_TRANSFORM, the
+ * transformed (hinted) advance width for the glyph, in 26.6 fractional
+ * pixel format. As specified with @FT_LOAD_VERTICAL_LAYOUT, it uses
+ * either the `horiAdvance` or the `vertAdvance` value of `metrics`
+ * field.
+ *
+ * format ::
+ * This field indicates the format of the image contained in the glyph
+ * slot. Typically @FT_GLYPH_FORMAT_BITMAP, @FT_GLYPH_FORMAT_OUTLINE,
+ * or @FT_GLYPH_FORMAT_COMPOSITE, but other values are possible.
+ *
+ * bitmap ::
+ * This field is used as a bitmap descriptor. Note that the address
+ * and content of the bitmap buffer can change between calls of
+ * @FT_Load_Glyph and a few other functions.
+ *
+ * bitmap_left ::
+ * The bitmap's left bearing expressed in integer pixels.
+ *
+ * bitmap_top ::
+ * The bitmap's top bearing expressed in integer pixels. This is the
+ * distance from the baseline to the top-most glyph scanline, upwards
+ * y~coordinates being **positive**.
+ *
+ * outline ::
+ * The outline descriptor for the current glyph image if its format is
+ * @FT_GLYPH_FORMAT_OUTLINE. Once a glyph is loaded, `outline` can be
+ * transformed, distorted, emboldened, etc. However, it must not be
+ * freed.
+ *
+ * [Since 2.10.1] If @FT_LOAD_NO_SCALE is set, outline coordinates of
+ * OpenType variation fonts for a selected instance are internally
+ * handled as 26.6 fractional font units but returned as (rounded)
+ * integers, as expected. To get unrounded font units, don't use
+ * @FT_LOAD_NO_SCALE but load the glyph with @FT_LOAD_NO_HINTING and
+ * scale it, using the font's `units_per_EM` value as the ppem.
+ *
+ * num_subglyphs ::
+ * The number of subglyphs in a composite glyph. This field is only
+ * valid for the composite glyph format that should normally only be
+ * loaded with the @FT_LOAD_NO_RECURSE flag.
+ *
+ * subglyphs ::
+ * An array of subglyph descriptors for composite glyphs. There are
+ * `num_subglyphs` elements in there. Currently internal to FreeType.
+ *
+ * control_data ::
+ * Certain font drivers can also return the control data for a given
+ * glyph image (e.g. TrueType bytecode, Type~1 charstrings, etc.).
+ * This field is a pointer to such data; it is currently internal to
+ * FreeType.
+ *
+ * control_len ::
+ * This is the length in bytes of the control data. Currently internal
+ * to FreeType.
+ *
+ * other ::
+ * Reserved.
+ *
+ * lsb_delta ::
+ * The difference between hinted and unhinted left side bearing while
+ * auto-hinting is active. Zero otherwise.
+ *
+ * rsb_delta ::
+ * The difference between hinted and unhinted right side bearing while
+ * auto-hinting is active. Zero otherwise.
+ *
+ * @note:
+ * If @FT_Load_Glyph is called with default flags (see @FT_LOAD_DEFAULT)
+ * the glyph image is loaded in the glyph slot in its native format
+ * (e.g., an outline glyph for TrueType and Type~1 formats). [Since 2.9]
+ * The prospective bitmap metrics are calculated according to
+ * @FT_LOAD_TARGET_XXX and other flags even for the outline glyph, even
+ * if @FT_LOAD_RENDER is not set.
+ *
+ * This image can later be converted into a bitmap by calling
+ * @FT_Render_Glyph. This function searches the current renderer for the
+ * native image's format, then invokes it.
+ *
+ * The renderer is in charge of transforming the native image through the
+ * slot's face transformation fields, then converting it into a bitmap
+ * that is returned in `slot->bitmap`.
+ *
+ * Note that `slot->bitmap_left` and `slot->bitmap_top` are also used to
+ * specify the position of the bitmap relative to the current pen
+ * position (e.g., coordinates (0,0) on the baseline). Of course,
+ * `slot->format` is also changed to @FT_GLYPH_FORMAT_BITMAP.
+ *
+ * Here is a small pseudo code fragment that shows how to use `lsb_delta`
+ * and `rsb_delta` to do fractional positioning of glyphs:
+ *
+ * ```
+ * FT_GlyphSlot slot = face->glyph;
+ * FT_Pos origin_x = 0;
+ *
+ *
+ * for all glyphs do
+ * <load glyph with `FT_Load_Glyph'>
+ *
+ * FT_Outline_Translate( slot->outline, origin_x & 63, 0 );
+ *
+ * <save glyph image, or render glyph, or ...>
+ *
+ * <compute kern between current and next glyph
+ * and add it to `origin_x'>
+ *
+ * origin_x += slot->advance.x;
+ * origin_x += slot->lsb_delta - slot->rsb_delta;
+ * endfor
+ * ```
+ *
+ * Here is another small pseudo code fragment that shows how to use
+ * `lsb_delta` and `rsb_delta` to improve integer positioning of glyphs:
+ *
+ * ```
+ * FT_GlyphSlot slot = face->glyph;
+ * FT_Pos origin_x = 0;
+ * FT_Pos prev_rsb_delta = 0;
+ *
+ *
+ * for all glyphs do
+ * <compute kern between current and previous glyph
+ * and add it to `origin_x'>
+ *
+ * <load glyph with `FT_Load_Glyph'>
+ *
+ * if ( prev_rsb_delta - slot->lsb_delta > 32 )
+ * origin_x -= 64;
+ * else if ( prev_rsb_delta - slot->lsb_delta < -31 )
+ * origin_x += 64;
+ *
+ * prev_rsb_delta = slot->rsb_delta;
+ *
+ * <save glyph image, or render glyph, or ...>
+ *
+ * origin_x += slot->advance.x;
+ * endfor
+ * ```
+ *
+ * If you use strong auto-hinting, you **must** apply these delta values!
+ * Otherwise you will experience far too large inter-glyph spacing at
+ * small rendering sizes in most cases. Note that it doesn't harm to use
+ * the above code for other hinting modes also, since the delta values
+ * are zero then.
+ */
+ typedef struct FT_GlyphSlotRec_
+ {
+ FT_Library library;
+ FT_Face face;
+ FT_GlyphSlot next;
+ FT_UInt glyph_index; /* new in 2.10; was reserved previously */
+ FT_Generic generic;
+
+ FT_Glyph_Metrics metrics;
+ FT_Fixed linearHoriAdvance;
+ FT_Fixed linearVertAdvance;
+ FT_Vector advance;
+
+ FT_Glyph_Format format;
+
+ FT_Bitmap bitmap;
+ FT_Int bitmap_left;
+ FT_Int bitmap_top;
+
+ FT_Outline outline;
+
+ FT_UInt num_subglyphs;
+ FT_SubGlyph subglyphs;
+
+ void* control_data;
+ long control_len;
+
+ FT_Pos lsb_delta;
+ FT_Pos rsb_delta;
+
+ void* other;
+
+ FT_Slot_Internal internal;
+
+ } FT_GlyphSlotRec;
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* F U N C T I O N S */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Init_FreeType
+ *
+ * @description:
+ * Initialize a new FreeType library object. The set of modules that are
+ * registered by this function is determined at build time.
+ *
+ * @output:
+ * alibrary ::
+ * A handle to a new library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * In case you want to provide your own memory allocating routines, use
+ * @FT_New_Library instead, followed by a call to @FT_Add_Default_Modules
+ * (or a series of calls to @FT_Add_Module) and
+ * @FT_Set_Default_Properties.
+ *
+ * See the documentation of @FT_Library and @FT_Face for multi-threading
+ * issues.
+ *
+ * If you need reference-counting (cf. @FT_Reference_Library), use
+ * @FT_New_Library and @FT_Done_Library.
+ *
+ * If compilation option `FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES` is
+ * set, this function reads the `FREETYPE_PROPERTIES` environment
+ * variable to control driver properties. See section @properties for
+ * more.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Init_FreeType( FT_Library *alibrary );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_FreeType
+ *
+ * @description:
+ * Destroy a given FreeType library object and all of its children,
+ * including resources, drivers, faces, sizes, etc.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Done_FreeType( FT_Library library );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_OPEN_XXX
+ *
+ * @description:
+ * A list of bit field constants used within the `flags` field of the
+ * @FT_Open_Args structure.
+ *
+ * @values:
+ * FT_OPEN_MEMORY ::
+ * This is a memory-based stream.
+ *
+ * FT_OPEN_STREAM ::
+ * Copy the stream from the `stream` field.
+ *
+ * FT_OPEN_PATHNAME ::
+ * Create a new input stream from a C~path name.
+ *
+ * FT_OPEN_DRIVER ::
+ * Use the `driver` field.
+ *
+ * FT_OPEN_PARAMS ::
+ * Use the `num_params` and `params` fields.
+ *
+ * @note:
+ * The `FT_OPEN_MEMORY`, `FT_OPEN_STREAM`, and `FT_OPEN_PATHNAME` flags
+ * are mutually exclusive.
+ */
+#define FT_OPEN_MEMORY 0x1
+#define FT_OPEN_STREAM 0x2
+#define FT_OPEN_PATHNAME 0x4
+#define FT_OPEN_DRIVER 0x8
+#define FT_OPEN_PARAMS 0x10
+
+
+ /* these constants are deprecated; use the corresponding `FT_OPEN_XXX` */
+ /* values instead */
+#define ft_open_memory FT_OPEN_MEMORY
+#define ft_open_stream FT_OPEN_STREAM
+#define ft_open_pathname FT_OPEN_PATHNAME
+#define ft_open_driver FT_OPEN_DRIVER
+#define ft_open_params FT_OPEN_PARAMS
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Parameter
+ *
+ * @description:
+ * A simple structure to pass more or less generic parameters to
+ * @FT_Open_Face and @FT_Face_Properties.
+ *
+ * @fields:
+ * tag ::
+ * A four-byte identification tag.
+ *
+ * data ::
+ * A pointer to the parameter data.
+ *
+ * @note:
+ * The ID and function of parameters are driver-specific. See section
+ * @parameter_tags for more information.
+ */
+ typedef struct FT_Parameter_
+ {
+ FT_ULong tag;
+ FT_Pointer data;
+
+ } FT_Parameter;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Open_Args
+ *
+ * @description:
+ * A structure to indicate how to open a new font file or stream. A
+ * pointer to such a structure can be used as a parameter for the
+ * functions @FT_Open_Face and @FT_Attach_Stream.
+ *
+ * @fields:
+ * flags ::
+ * A set of bit flags indicating how to use the structure.
+ *
+ * memory_base ::
+ * The first byte of the file in memory.
+ *
+ * memory_size ::
+ * The size in bytes of the file in memory.
+ *
+ * pathname ::
+ * A pointer to an 8-bit file pathname. The pointer is not owned by
+ * FreeType.
+ *
+ * stream ::
+ * A handle to a source stream object.
+ *
+ * driver ::
+ * This field is exclusively used by @FT_Open_Face; it simply specifies
+ * the font driver to use for opening the face. If set to `NULL`,
+ * FreeType tries to load the face with each one of the drivers in its
+ * list.
+ *
+ * num_params ::
+ * The number of extra parameters.
+ *
+ * params ::
+ * Extra parameters passed to the font driver when opening a new face.
+ *
+ * @note:
+ * The stream type is determined by the contents of `flags`:
+ *
+ * If the @FT_OPEN_MEMORY bit is set, assume that this is a memory file
+ * of `memory_size` bytes, located at `memory_address`. The data are not
+ * copied, and the client is responsible for releasing and destroying
+ * them _after_ the corresponding call to @FT_Done_Face.
+ *
+ * Otherwise, if the @FT_OPEN_STREAM bit is set, assume that a custom
+ * input stream `stream` is used.
+ *
+ * Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this is a
+ * normal file and use `pathname` to open it.
+ *
+ * If none of the above bits are set or if multiple are set at the same
+ * time, the flags are invalid and @FT_Open_Face fails.
+ *
+ * If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to open
+ * the file with the driver whose handler is in `driver`.
+ *
+ * If the @FT_OPEN_PARAMS bit is set, the parameters given by
+ * `num_params` and `params` is used. They are ignored otherwise.
+ *
+ * Ideally, both the `pathname` and `params` fields should be tagged as
+ * 'const'; this is missing for API backward compatibility. In other
+ * words, applications should treat them as read-only.
+ */
+ typedef struct FT_Open_Args_
+ {
+ FT_UInt flags;
+ const FT_Byte* memory_base;
+ FT_Long memory_size;
+ FT_String* pathname;
+ FT_Stream stream;
+ FT_Module driver;
+ FT_Int num_params;
+ FT_Parameter* params;
+
+ } FT_Open_Args;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face
+ *
+ * @description:
+ * Call @FT_Open_Face to open a font by its pathname.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * pathname ::
+ * A path to the font file.
+ *
+ * face_index ::
+ * See @FT_Open_Face for a detailed description of this parameter.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object. If `face_index` is greater than or
+ * equal to zero, it must be non-`NULL`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Use @FT_Done_Face to destroy the created @FT_Face object (along with
+ * its slot and sizes).
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Face( FT_Library library,
+ const char* filepathname,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Memory_Face
+ *
+ * @description:
+ * Call @FT_Open_Face to open a font that has been loaded into memory.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * file_base ::
+ * A pointer to the beginning of the font data.
+ *
+ * file_size ::
+ * The size of the memory chunk used by the font data.
+ *
+ * face_index ::
+ * See @FT_Open_Face for a detailed description of this parameter.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object. If `face_index` is greater than or
+ * equal to zero, it must be non-`NULL`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You must not deallocate the memory before calling @FT_Done_Face.
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Memory_Face( FT_Library library,
+ const FT_Byte* file_base,
+ FT_Long file_size,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Open_Face
+ *
+ * @description:
+ * Create a face object from a given resource described by @FT_Open_Args.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * args ::
+ * A pointer to an `FT_Open_Args` structure that must be filled by the
+ * caller.
+ *
+ * face_index ::
+ * This field holds two different values. Bits 0-15 are the index of
+ * the face in the font file (starting with value~0). Set it to~0 if
+ * there is only one face in the font file.
+ *
+ * [Since 2.6.1] Bits 16-30 are relevant to GX and OpenType variation
+ * fonts only, specifying the named instance index for the current face
+ * index (starting with value~1; value~0 makes FreeType ignore named
+ * instances). For non-variation fonts, bits 16-30 are ignored.
+ * Assuming that you want to access the third named instance in face~4,
+ * `face_index` should be set to 0x00030004. If you want to access
+ * face~4 without variation handling, simply set `face_index` to
+ * value~4.
+ *
+ * `FT_Open_Face` and its siblings can be used to quickly check whether
+ * the font format of a given font resource is supported by FreeType.
+ * In general, if the `face_index` argument is negative, the function's
+ * return value is~0 if the font format is recognized, or non-zero
+ * otherwise. The function allocates a more or less empty face handle
+ * in `*aface` (if `aface` isn't `NULL`); the only two useful fields in
+ * this special case are `face->num_faces` and `face->style_flags`.
+ * For any negative value of `face_index`, `face->num_faces` gives the
+ * number of faces within the font file. For the negative value
+ * '-(N+1)' (with 'N' a non-negative 16-bit value), bits 16-30 in
+ * `face->style_flags` give the number of named instances in face 'N'
+ * if we have a variation font (or zero otherwise). After examination,
+ * the returned @FT_Face structure should be deallocated with a call to
+ * @FT_Done_Face.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object. If `face_index` is greater than or
+ * equal to zero, it must be non-`NULL`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Unlike FreeType 1.x, this function automatically creates a glyph slot
+ * for the face object that can be accessed directly through
+ * `face->glyph`.
+ *
+ * Each new face object created with this function also owns a default
+ * @FT_Size object, accessible as `face->size`.
+ *
+ * One @FT_Library instance can have multiple face objects, this is,
+ * @FT_Open_Face and its siblings can be called multiple times using the
+ * same `library` argument.
+ *
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Face.
+ *
+ * If `FT_OPEN_STREAM` is set in `args->flags`, the stream in
+ * `args->stream` is automatically closed before this function returns
+ * any error (including `FT_Err_Invalid_Argument`).
+ *
+ * @example:
+ * To loop over all faces, use code similar to the following snippet
+ * (omitting the error handling).
+ *
+ * ```
+ * ...
+ * FT_Face face;
+ * FT_Long i, num_faces;
+ *
+ *
+ * error = FT_Open_Face( library, args, -1, &face );
+ * if ( error ) { ... }
+ *
+ * num_faces = face->num_faces;
+ * FT_Done_Face( face );
+ *
+ * for ( i = 0; i < num_faces; i++ )
+ * {
+ * ...
+ * error = FT_Open_Face( library, args, i, &face );
+ * ...
+ * FT_Done_Face( face );
+ * ...
+ * }
+ * ```
+ *
+ * To loop over all valid values for `face_index`, use something similar
+ * to the following snippet, again without error handling. The code
+ * accesses all faces immediately (thus only a single call of
+ * `FT_Open_Face` within the do-loop), with and without named instances.
+ *
+ * ```
+ * ...
+ * FT_Face face;
+ *
+ * FT_Long num_faces = 0;
+ * FT_Long num_instances = 0;
+ *
+ * FT_Long face_idx = 0;
+ * FT_Long instance_idx = 0;
+ *
+ *
+ * do
+ * {
+ * FT_Long id = ( instance_idx << 16 ) + face_idx;
+ *
+ *
+ * error = FT_Open_Face( library, args, id, &face );
+ * if ( error ) { ... }
+ *
+ * num_faces = face->num_faces;
+ * num_instances = face->style_flags >> 16;
+ *
+ * ...
+ *
+ * FT_Done_Face( face );
+ *
+ * if ( instance_idx < num_instances )
+ * instance_idx++;
+ * else
+ * {
+ * face_idx++;
+ * instance_idx = 0;
+ * }
+ *
+ * } while ( face_idx < num_faces )
+ * ```
+ */
+ FT_EXPORT( FT_Error )
+ FT_Open_Face( FT_Library library,
+ const FT_Open_Args* args,
+ FT_Long face_index,
+ FT_Face *aface );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Attach_File
+ *
+ * @description:
+ * Call @FT_Attach_Stream to attach a file.
+ *
+ * @inout:
+ * face ::
+ * The target face object.
+ *
+ * @input:
+ * filepathname ::
+ * The pathname.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Attach_File( FT_Face face,
+ const char* filepathname );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Attach_Stream
+ *
+ * @description:
+ * 'Attach' data to a face object. Normally, this is used to read
+ * additional information for the face object. For example, you can
+ * attach an AFM file that comes with a Type~1 font to get the kerning
+ * values and other metrics.
+ *
+ * @inout:
+ * face ::
+ * The target face object.
+ *
+ * @input:
+ * parameters ::
+ * A pointer to @FT_Open_Args that must be filled by the caller.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The meaning of the 'attach' (i.e., what really happens when the new
+ * file is read) is not fixed by FreeType itself. It really depends on
+ * the font format (and thus the font driver).
+ *
+ * Client applications are expected to know what they are doing when
+ * invoking this function. Most drivers simply do not implement file or
+ * stream attachments.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Attach_Stream( FT_Face face,
+ FT_Open_Args* parameters );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Reference_Face
+ *
+ * @description:
+ * A counter gets initialized to~1 at the time an @FT_Face structure is
+ * created. This function increments the counter. @FT_Done_Face then
+ * only destroys a face if the counter is~1, otherwise it simply
+ * decrements the counter.
+ *
+ * This function helps in managing life-cycles of structures that
+ * reference @FT_Face objects.
+ *
+ * @input:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.4.2
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Reference_Face( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Face
+ *
+ * @description:
+ * Discard a given face object, as well as all of its child slots and
+ * sizes.
+ *
+ * @input:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Face.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Done_Face( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Select_Size
+ *
+ * @description:
+ * Select a bitmap strike. To be more precise, this function sets the
+ * scaling factors of the active @FT_Size object in a face so that
+ * bitmaps from this particular strike are taken by @FT_Load_Glyph and
+ * friends.
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @input:
+ * strike_index ::
+ * The index of the bitmap strike in the `available_sizes` field of
+ * @FT_FaceRec structure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * For bitmaps embedded in outline fonts it is common that only a subset
+ * of the available glyphs at a given ppem value is available. FreeType
+ * silently uses outlines if there is no bitmap for a given glyph index.
+ *
+ * For GX and OpenType variation fonts, a bitmap strike makes sense only
+ * if the default instance is active (this is, no glyph variation takes
+ * place); otherwise, FreeType simply ignores bitmap strikes. The same
+ * is true for all named instances that are different from the default
+ * instance.
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Select_Size( FT_Face face,
+ FT_Int strike_index );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Size_Request_Type
+ *
+ * @description:
+ * An enumeration type that lists the supported size request types, i.e.,
+ * what input size (in font units) maps to the requested output size (in
+ * pixels, as computed from the arguments of @FT_Size_Request).
+ *
+ * @values:
+ * FT_SIZE_REQUEST_TYPE_NOMINAL ::
+ * The nominal size. The `units_per_EM` field of @FT_FaceRec is used
+ * to determine both scaling values.
+ *
+ * This is the standard scaling found in most applications. In
+ * particular, use this size request type for TrueType fonts if they
+ * provide optical scaling or something similar. Note, however, that
+ * `units_per_EM` is a rather abstract value which bears no relation to
+ * the actual size of the glyphs in a font.
+ *
+ * FT_SIZE_REQUEST_TYPE_REAL_DIM ::
+ * The real dimension. The sum of the `ascender` and (minus of) the
+ * `descender` fields of @FT_FaceRec is used to determine both scaling
+ * values.
+ *
+ * FT_SIZE_REQUEST_TYPE_BBOX ::
+ * The font bounding box. The width and height of the `bbox` field of
+ * @FT_FaceRec are used to determine the horizontal and vertical
+ * scaling value, respectively.
+ *
+ * FT_SIZE_REQUEST_TYPE_CELL ::
+ * The `max_advance_width` field of @FT_FaceRec is used to determine
+ * the horizontal scaling value; the vertical scaling value is
+ * determined the same way as @FT_SIZE_REQUEST_TYPE_REAL_DIM does.
+ * Finally, both scaling values are set to the smaller one. This type
+ * is useful if you want to specify the font size for, say, a window of
+ * a given dimension and 80x24 cells.
+ *
+ * FT_SIZE_REQUEST_TYPE_SCALES ::
+ * Specify the scaling values directly.
+ *
+ * @note:
+ * The above descriptions only apply to scalable formats. For bitmap
+ * formats, the behaviour is up to the driver.
+ *
+ * See the note section of @FT_Size_Metrics if you wonder how size
+ * requesting relates to scaling values.
+ */
+ typedef enum FT_Size_Request_Type_
+ {
+ FT_SIZE_REQUEST_TYPE_NOMINAL,
+ FT_SIZE_REQUEST_TYPE_REAL_DIM,
+ FT_SIZE_REQUEST_TYPE_BBOX,
+ FT_SIZE_REQUEST_TYPE_CELL,
+ FT_SIZE_REQUEST_TYPE_SCALES,
+
+ FT_SIZE_REQUEST_TYPE_MAX
+
+ } FT_Size_Request_Type;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_RequestRec
+ *
+ * @description:
+ * A structure to model a size request.
+ *
+ * @fields:
+ * type ::
+ * See @FT_Size_Request_Type.
+ *
+ * width ::
+ * The desired width, given as a 26.6 fractional point value (with 72pt
+ * = 1in).
+ *
+ * height ::
+ * The desired height, given as a 26.6 fractional point value (with
+ * 72pt = 1in).
+ *
+ * horiResolution ::
+ * The horizontal resolution (dpi, i.e., pixels per inch). If set to
+ * zero, `width` is treated as a 26.6 fractional **pixel** value, which
+ * gets internally rounded to an integer.
+ *
+ * vertResolution ::
+ * The vertical resolution (dpi, i.e., pixels per inch). If set to
+ * zero, `height` is treated as a 26.6 fractional **pixel** value,
+ * which gets internally rounded to an integer.
+ *
+ * @note:
+ * If `width` is zero, the horizontal scaling value is set equal to the
+ * vertical scaling value, and vice versa.
+ *
+ * If `type` is `FT_SIZE_REQUEST_TYPE_SCALES`, `width` and `height` are
+ * interpreted directly as 16.16 fractional scaling values, without any
+ * further modification, and both `horiResolution` and `vertResolution`
+ * are ignored.
+ */
+ typedef struct FT_Size_RequestRec_
+ {
+ FT_Size_Request_Type type;
+ FT_Long width;
+ FT_Long height;
+ FT_UInt horiResolution;
+ FT_UInt vertResolution;
+
+ } FT_Size_RequestRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Size_Request
+ *
+ * @description:
+ * A handle to a size request structure.
+ */
+ typedef struct FT_Size_RequestRec_ *FT_Size_Request;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Request_Size
+ *
+ * @description:
+ * Resize the scale of the active @FT_Size object in a face.
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @input:
+ * req ::
+ * A pointer to a @FT_Size_RequestRec.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Although drivers may select the bitmap strike matching the request,
+ * you should not rely on this if you intend to select a particular
+ * bitmap strike. Use @FT_Select_Size instead in that case.
+ *
+ * The relation between the requested size and the resulting glyph size
+ * is dependent entirely on how the size is defined in the source face.
+ * The font designer chooses the final size of each glyph relative to
+ * this size. For more information refer to
+ * 'https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'.
+ *
+ * Contrary to @FT_Set_Char_Size, this function doesn't have special code
+ * to normalize zero-valued widths, heights, or resolutions (which lead
+ * to errors in most cases).
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Request_Size( FT_Face face,
+ FT_Size_Request req );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Char_Size
+ *
+ * @description:
+ * Call @FT_Request_Size to request the nominal size (in points).
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object.
+ *
+ * @input:
+ * char_width ::
+ * The nominal width, in 26.6 fractional points.
+ *
+ * char_height ::
+ * The nominal height, in 26.6 fractional points.
+ *
+ * horz_resolution ::
+ * The horizontal resolution in dpi.
+ *
+ * vert_resolution ::
+ * The vertical resolution in dpi.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * While this function allows fractional points as input values, the
+ * resulting ppem value for the given resolution is always rounded to the
+ * nearest integer.
+ *
+ * If either the character width or height is zero, it is set equal to
+ * the other value.
+ *
+ * If either the horizontal or vertical resolution is zero, it is set
+ * equal to the other value.
+ *
+ * A character width or height smaller than 1pt is set to 1pt; if both
+ * resolution values are zero, they are set to 72dpi.
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Char_Size( FT_Face face,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Pixel_Sizes
+ *
+ * @description:
+ * Call @FT_Request_Size to request the nominal size (in pixels).
+ *
+ * @inout:
+ * face ::
+ * A handle to the target face object.
+ *
+ * @input:
+ * pixel_width ::
+ * The nominal width, in pixels.
+ *
+ * pixel_height ::
+ * The nominal height, in pixels.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should not rely on the resulting glyphs matching or being
+ * constrained to this pixel size. Refer to @FT_Request_Size to
+ * understand how requested sizes relate to actual sizes.
+ *
+ * Don't use this function if you are using the FreeType cache API.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Pixel_Sizes( FT_Face face,
+ FT_UInt pixel_width,
+ FT_UInt pixel_height );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Load_Glyph
+ *
+ * @description:
+ * Load a glyph into the glyph slot of a face object.
+ *
+ * @inout:
+ * face ::
+ * A handle to the target face object where the glyph is loaded.
+ *
+ * @input:
+ * glyph_index ::
+ * The index of the glyph in the font file. For CID-keyed fonts
+ * (either in PS or in CFF format) this argument specifies the CID
+ * value.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The @FT_LOAD_XXX
+ * constants can be used to control the glyph loading process (e.g.,
+ * whether the outline should be scaled, whether to load bitmaps or
+ * not, whether to hint the outline, etc).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The loaded glyph may be transformed. See @FT_Set_Transform for the
+ * details.
+ *
+ * For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned
+ * for invalid CID values (this is, for CID values that don't have a
+ * corresponding glyph in the font). See the discussion of the
+ * @FT_FACE_FLAG_CID_KEYED flag for more details.
+ *
+ * If you receive `FT_Err_Glyph_Too_Big`, try getting the glyph outline
+ * at EM size, then scale it manually and fill it as a graphics
+ * operation.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Load_Glyph( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Int32 load_flags );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Load_Char
+ *
+ * @description:
+ * Load a glyph into the glyph slot of a face object, accessed by its
+ * character code.
+ *
+ * @inout:
+ * face ::
+ * A handle to a target face object where the glyph is loaded.
+ *
+ * @input:
+ * char_code ::
+ * The glyph's character code, according to the current charmap used in
+ * the face.
+ *
+ * load_flags ::
+ * A flag indicating what to load for this glyph. The @FT_LOAD_XXX
+ * constants can be used to control the glyph loading process (e.g.,
+ * whether the outline should be scaled, whether to load bitmaps or
+ * not, whether to hint the outline, etc).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function simply calls @FT_Get_Char_Index and @FT_Load_Glyph.
+ *
+ * Many fonts contain glyphs that can't be loaded by this function since
+ * its glyph indices are not listed in any of the font's charmaps.
+ *
+ * If no active cmap is set up (i.e., `face->charmap` is zero), the call
+ * to @FT_Get_Char_Index is omitted, and the function behaves identically
+ * to @FT_Load_Glyph.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Load_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_Int32 load_flags );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_LOAD_XXX
+ *
+ * @description:
+ * A list of bit field constants for @FT_Load_Glyph to indicate what kind
+ * of operations to perform during glyph loading.
+ *
+ * @values:
+ * FT_LOAD_DEFAULT ::
+ * Corresponding to~0, this value is used as the default glyph load
+ * operation. In this case, the following happens:
+ *
+ * 1. FreeType looks for a bitmap for the glyph corresponding to the
+ * face's current size. If one is found, the function returns. The
+ * bitmap data can be accessed from the glyph slot (see note below).
+ *
+ * 2. If no embedded bitmap is searched for or found, FreeType looks
+ * for a scalable outline. If one is found, it is loaded from the font
+ * file, scaled to device pixels, then 'hinted' to the pixel grid in
+ * order to optimize it. The outline data can be accessed from the
+ * glyph slot (see note below).
+ *
+ * Note that by default the glyph loader doesn't render outlines into
+ * bitmaps. The following flags are used to modify this default
+ * behaviour to more specific and useful cases.
+ *
+ * FT_LOAD_NO_SCALE ::
+ * Don't scale the loaded outline glyph but keep it in font units.
+ *
+ * This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and
+ * unsets @FT_LOAD_RENDER.
+ *
+ * If the font is 'tricky' (see @FT_FACE_FLAG_TRICKY for more), using
+ * `FT_LOAD_NO_SCALE` usually yields meaningless outlines because the
+ * subglyphs must be scaled and positioned with hinting instructions.
+ * This can be solved by loading the font without `FT_LOAD_NO_SCALE`
+ * and setting the character size to `font->units_per_EM`.
+ *
+ * FT_LOAD_NO_HINTING ::
+ * Disable hinting. This generally generates 'blurrier' bitmap glyphs
+ * when the glyph are rendered in any of the anti-aliased modes. See
+ * also the note below.
+ *
+ * This flag is implied by @FT_LOAD_NO_SCALE.
+ *
+ * FT_LOAD_RENDER ::
+ * Call @FT_Render_Glyph after the glyph is loaded. By default, the
+ * glyph is rendered in @FT_RENDER_MODE_NORMAL mode. This can be
+ * overridden by @FT_LOAD_TARGET_XXX or @FT_LOAD_MONOCHROME.
+ *
+ * This flag is unset by @FT_LOAD_NO_SCALE.
+ *
+ * FT_LOAD_NO_BITMAP ::
+ * Ignore bitmap strikes when loading. Bitmap-only fonts ignore this
+ * flag.
+ *
+ * @FT_LOAD_NO_SCALE always sets this flag.
+ *
+ * FT_LOAD_VERTICAL_LAYOUT ::
+ * Load the glyph for vertical text layout. In particular, the
+ * `advance` value in the @FT_GlyphSlotRec structure is set to the
+ * `vertAdvance` value of the `metrics` field.
+ *
+ * In case @FT_HAS_VERTICAL doesn't return true, you shouldn't use this
+ * flag currently. Reason is that in this case vertical metrics get
+ * synthesized, and those values are not always consistent across
+ * various font formats.
+ *
+ * FT_LOAD_FORCE_AUTOHINT ::
+ * Prefer the auto-hinter over the font's native hinter. See also the
+ * note below.
+ *
+ * FT_LOAD_PEDANTIC ::
+ * Make the font driver perform pedantic verifications during glyph
+ * loading and hinting. This is mostly used to detect broken glyphs in
+ * fonts. By default, FreeType tries to handle broken fonts also.
+ *
+ * In particular, errors from the TrueType bytecode engine are not
+ * passed to the application if this flag is not set; this might result
+ * in partially hinted or distorted glyphs in case a glyph's bytecode
+ * is buggy.
+ *
+ * FT_LOAD_NO_RECURSE ::
+ * Don't load composite glyphs recursively. Instead, the font driver
+ * fills the `num_subglyph` and `subglyphs` values of the glyph slot;
+ * it also sets `glyph->format` to @FT_GLYPH_FORMAT_COMPOSITE. The
+ * description of subglyphs can then be accessed with
+ * @FT_Get_SubGlyph_Info.
+ *
+ * Don't use this flag for retrieving metrics information since some
+ * font drivers only return rudimentary data.
+ *
+ * This flag implies @FT_LOAD_NO_SCALE and @FT_LOAD_IGNORE_TRANSFORM.
+ *
+ * FT_LOAD_IGNORE_TRANSFORM ::
+ * Ignore the transform matrix set by @FT_Set_Transform.
+ *
+ * FT_LOAD_MONOCHROME ::
+ * This flag is used with @FT_LOAD_RENDER to indicate that you want to
+ * render an outline glyph to a 1-bit monochrome bitmap glyph, with
+ * 8~pixels packed into each byte of the bitmap data.
+ *
+ * Note that this has no effect on the hinting algorithm used. You
+ * should rather use @FT_LOAD_TARGET_MONO so that the
+ * monochrome-optimized hinting algorithm is used.
+ *
+ * FT_LOAD_LINEAR_DESIGN ::
+ * Keep `linearHoriAdvance` and `linearVertAdvance` fields of
+ * @FT_GlyphSlotRec in font units. See @FT_GlyphSlotRec for details.
+ *
+ * FT_LOAD_NO_AUTOHINT ::
+ * Disable the auto-hinter. See also the note below.
+ *
+ * FT_LOAD_COLOR ::
+ * Load colored glyphs. There are slight differences depending on the
+ * font format.
+ *
+ * [Since 2.5] Load embedded color bitmap images. The resulting color
+ * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format,
+ * with pre-multiplied color channels. If the flag is not set and
+ * color bitmaps are found, they are converted to 256-level gray
+ * bitmaps, using the @FT_PIXEL_MODE_GRAY format.
+ *
+ * [Since 2.10, experimental] If the glyph index contains an entry in
+ * the face's 'COLR' table with a 'CPAL' palette table (as defined in
+ * the OpenType specification), make @FT_Render_Glyph provide a default
+ * blending of the color glyph layers associated with the glyph index,
+ * using the same bitmap format as embedded color bitmap images. This
+ * is mainly for convenience; for full control of color layers use
+ * @FT_Get_Color_Glyph_Layer and FreeType's color functions like
+ * @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering
+ * so that the client application can handle blending by itself.
+ *
+ * FT_LOAD_COMPUTE_METRICS ::
+ * [Since 2.6.1] Compute glyph metrics from the glyph data, without the
+ * use of bundled metrics tables (for example, the 'hdmx' table in
+ * TrueType fonts). This flag is mainly used by font validating or
+ * font editing applications, which need to ignore, verify, or edit
+ * those tables.
+ *
+ * Currently, this flag is only implemented for TrueType fonts.
+ *
+ * FT_LOAD_BITMAP_METRICS_ONLY ::
+ * [Since 2.7.1] Request loading of the metrics and bitmap image
+ * information of a (possibly embedded) bitmap glyph without allocating
+ * or copying the bitmap image data itself. No effect if the target
+ * glyph is not a bitmap image.
+ *
+ * This flag unsets @FT_LOAD_RENDER.
+ *
+ * FT_LOAD_CROP_BITMAP ::
+ * Ignored. Deprecated.
+ *
+ * FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ::
+ * Ignored. Deprecated.
+ *
+ * @note:
+ * By default, hinting is enabled and the font's native hinter (see
+ * @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter. You can
+ * disable hinting by setting @FT_LOAD_NO_HINTING or change the
+ * precedence by setting @FT_LOAD_FORCE_AUTOHINT. You can also set
+ * @FT_LOAD_NO_AUTOHINT in case you don't want the auto-hinter to be used
+ * at all.
+ *
+ * See the description of @FT_FACE_FLAG_TRICKY for a special exception
+ * (affecting only a handful of Asian fonts).
+ *
+ * Besides deciding which hinter to use, you can also decide which
+ * hinting algorithm to use. See @FT_LOAD_TARGET_XXX for details.
+ *
+ * Note that the auto-hinter needs a valid Unicode cmap (either a native
+ * one or synthesized by FreeType) for producing correct results. If a
+ * font provides an incorrect mapping (for example, assigning the
+ * character code U+005A, LATIN CAPITAL LETTER~Z, to a glyph depicting a
+ * mathematical integral sign), the auto-hinter might produce useless
+ * results.
+ *
+ */
+#define FT_LOAD_DEFAULT 0x0
+#define FT_LOAD_NO_SCALE ( 1L << 0 )
+#define FT_LOAD_NO_HINTING ( 1L << 1 )
+#define FT_LOAD_RENDER ( 1L << 2 )
+#define FT_LOAD_NO_BITMAP ( 1L << 3 )
+#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 )
+#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 )
+#define FT_LOAD_CROP_BITMAP ( 1L << 6 )
+#define FT_LOAD_PEDANTIC ( 1L << 7 )
+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 )
+#define FT_LOAD_NO_RECURSE ( 1L << 10 )
+#define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 )
+#define FT_LOAD_MONOCHROME ( 1L << 12 )
+#define FT_LOAD_LINEAR_DESIGN ( 1L << 13 )
+#define FT_LOAD_NO_AUTOHINT ( 1L << 15 )
+ /* Bits 16-19 are used by `FT_LOAD_TARGET_` */
+#define FT_LOAD_COLOR ( 1L << 20 )
+#define FT_LOAD_COMPUTE_METRICS ( 1L << 21 )
+#define FT_LOAD_BITMAP_METRICS_ONLY ( 1L << 22 )
+
+ /* */
+
+ /* used internally only by certain font drivers */
+#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 )
+#define FT_LOAD_SBITS_ONLY ( 1L << 14 )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_LOAD_TARGET_XXX
+ *
+ * @description:
+ * A list of values to select a specific hinting algorithm for the
+ * hinter. You should OR one of these values to your `load_flags` when
+ * calling @FT_Load_Glyph.
+ *
+ * Note that a font's native hinters may ignore the hinting algorithm you
+ * have specified (e.g., the TrueType bytecode interpreter). You can set
+ * @FT_LOAD_FORCE_AUTOHINT to ensure that the auto-hinter is used.
+ *
+ * @values:
+ * FT_LOAD_TARGET_NORMAL ::
+ * The default hinting algorithm, optimized for standard gray-level
+ * rendering. For monochrome output, use @FT_LOAD_TARGET_MONO instead.
+ *
+ * FT_LOAD_TARGET_LIGHT ::
+ * A lighter hinting algorithm for gray-level modes. Many generated
+ * glyphs are fuzzier but better resemble their original shape. This
+ * is achieved by snapping glyphs to the pixel grid only vertically
+ * (Y-axis), as is done by FreeType's new CFF engine or Microsoft's
+ * ClearType font renderer. This preserves inter-glyph spacing in
+ * horizontal text. The snapping is done either by the native font
+ * driver, if the driver itself and the font support it, or by the
+ * auto-hinter.
+ *
+ * Advance widths are rounded to integer values; however, using the
+ * `lsb_delta` and `rsb_delta` fields of @FT_GlyphSlotRec, it is
+ * possible to get fractional advance widths for subpixel positioning
+ * (which is recommended to use).
+ *
+ * If configuration option `AF_CONFIG_OPTION_TT_SIZE_METRICS` is
+ * active, TrueType-like metrics are used to make this mode behave
+ * similarly as in unpatched FreeType versions between 2.4.6 and 2.7.1
+ * (inclusive).
+ *
+ * FT_LOAD_TARGET_MONO ::
+ * Strong hinting algorithm that should only be used for monochrome
+ * output. The result is probably unpleasant if the glyph is rendered
+ * in non-monochrome modes.
+ *
+ * Note that for outline fonts only the TrueType font driver has proper
+ * monochrome hinting support, provided the TTFs contain hints for B/W
+ * rendering (which most fonts no longer provide). If these conditions
+ * are not met it is very likely that you get ugly results at smaller
+ * sizes.
+ *
+ * FT_LOAD_TARGET_LCD ::
+ * A variant of @FT_LOAD_TARGET_LIGHT optimized for horizontally
+ * decimated LCD displays.
+ *
+ * FT_LOAD_TARGET_LCD_V ::
+ * A variant of @FT_LOAD_TARGET_NORMAL optimized for vertically
+ * decimated LCD displays.
+ *
+ * @note:
+ * You should use only _one_ of the `FT_LOAD_TARGET_XXX` values in your
+ * `load_flags`. They can't be ORed.
+ *
+ * If @FT_LOAD_RENDER is also set, the glyph is rendered in the
+ * corresponding mode (i.e., the mode that matches the used algorithm
+ * best). An exception is `FT_LOAD_TARGET_MONO` since it implies
+ * @FT_LOAD_MONOCHROME.
+ *
+ * You can use a hinting algorithm that doesn't correspond to the same
+ * rendering mode. As an example, it is possible to use the 'light'
+ * hinting algorithm and have the results rendered in horizontal LCD
+ * pixel mode, with code like
+ *
+ * ```
+ * FT_Load_Glyph( face, glyph_index,
+ * load_flags | FT_LOAD_TARGET_LIGHT );
+ *
+ * FT_Render_Glyph( face->glyph, FT_RENDER_MODE_LCD );
+ * ```
+ *
+ * In general, you should stick with one rendering mode. For example,
+ * switching between @FT_LOAD_TARGET_NORMAL and @FT_LOAD_TARGET_MONO
+ * enforces a lot of recomputation for TrueType fonts, which is slow.
+ * Another reason is caching: Selecting a different mode usually causes
+ * changes in both the outlines and the rasterized bitmaps; it is thus
+ * necessary to empty the cache after a mode switch to avoid false hits.
+ *
+ */
+#define FT_LOAD_TARGET_( x ) ( (FT_Int32)( (x) & 15 ) << 16 )
+
+#define FT_LOAD_TARGET_NORMAL FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )
+#define FT_LOAD_TARGET_LIGHT FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT )
+#define FT_LOAD_TARGET_MONO FT_LOAD_TARGET_( FT_RENDER_MODE_MONO )
+#define FT_LOAD_TARGET_LCD FT_LOAD_TARGET_( FT_RENDER_MODE_LCD )
+#define FT_LOAD_TARGET_LCD_V FT_LOAD_TARGET_( FT_RENDER_MODE_LCD_V )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_LOAD_TARGET_MODE
+ *
+ * @description:
+ * Return the @FT_Render_Mode corresponding to a given
+ * @FT_LOAD_TARGET_XXX value.
+ *
+ */
+#define FT_LOAD_TARGET_MODE( x ) ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) )
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Transform
+ *
+ * @description:
+ * Set the transformation that is applied to glyph images when they are
+ * loaded into a glyph slot through @FT_Load_Glyph.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to the transformation's 2x2 matrix. Use `NULL` for the
+ * identity matrix.
+ * delta ::
+ * A pointer to the translation vector. Use `NULL` for the null
+ * vector.
+ *
+ * @note:
+ * This function is provided as a convenience, but keep in mind that
+ * @FT_Matrix coefficients are only 16.16 fixed-point values, which can
+ * limit the accuracy of the results. Using floating-point computations
+ * to perform the transform directly in client code instead will always
+ * yield better numbers.
+ *
+ * The transformation is only applied to scalable image formats after the
+ * glyph has been loaded. It means that hinting is unaltered by the
+ * transformation and is performed on the character size given in the
+ * last call to @FT_Set_Char_Size or @FT_Set_Pixel_Sizes.
+ *
+ * Note that this also transforms the `face.glyph.advance` field, but
+ * **not** the values in `face.glyph.metrics`.
+ */
+ FT_EXPORT( void )
+ FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Transform
+ *
+ * @description:
+ * Return the transformation that is applied to glyph images when they
+ * are loaded into a glyph slot through @FT_Load_Glyph. See
+ * @FT_Set_Transform for more details.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @output:
+ * matrix ::
+ * A pointer to a transformation's 2x2 matrix. Set this to NULL if you
+ * are not interested in the value.
+ *
+ * delta ::
+ * A pointer a translation vector. Set this to NULL if you are not
+ * interested in the value.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+ FT_EXPORT( void )
+ FT_Get_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Render_Mode
+ *
+ * @description:
+ * Render modes supported by FreeType~2. Each mode corresponds to a
+ * specific type of scanline conversion performed on the outline.
+ *
+ * For bitmap fonts and embedded bitmaps the `bitmap->pixel_mode` field
+ * in the @FT_GlyphSlotRec structure gives the format of the returned
+ * bitmap.
+ *
+ * All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity,
+ * indicating pixel coverage. Use linear alpha blending and gamma
+ * correction to correctly render non-monochrome glyph bitmaps onto a
+ * surface; see @FT_Render_Glyph.
+ *
+ * The @FT_RENDER_MODE_SDF is a special render mode that uses up to 256
+ * distance values, indicating the signed distance from the grid position
+ * to the nearest outline.
+ *
+ * @values:
+ * FT_RENDER_MODE_NORMAL ::
+ * Default render mode; it corresponds to 8-bit anti-aliased bitmaps.
+ *
+ * FT_RENDER_MODE_LIGHT ::
+ * This is equivalent to @FT_RENDER_MODE_NORMAL. It is only defined as
+ * a separate value because render modes are also used indirectly to
+ * define hinting algorithm selectors. See @FT_LOAD_TARGET_XXX for
+ * details.
+ *
+ * FT_RENDER_MODE_MONO ::
+ * This mode corresponds to 1-bit bitmaps (with 2~levels of opacity).
+ *
+ * FT_RENDER_MODE_LCD ::
+ * This mode corresponds to horizontal RGB and BGR subpixel displays
+ * like LCD screens. It produces 8-bit bitmaps that are 3~times the
+ * width of the original glyph outline in pixels, and which use the
+ * @FT_PIXEL_MODE_LCD mode.
+ *
+ * FT_RENDER_MODE_LCD_V ::
+ * This mode corresponds to vertical RGB and BGR subpixel displays
+ * (like PDA screens, rotated LCD displays, etc.). It produces 8-bit
+ * bitmaps that are 3~times the height of the original glyph outline in
+ * pixels and use the @FT_PIXEL_MODE_LCD_V mode.
+ *
+ * FT_RENDER_MODE_SDF ::
+ * This mode corresponds to 8-bit, single-channel signed distance field
+ * (SDF) bitmaps. Each pixel in the SDF grid is the value from the
+ * pixel's position to the nearest glyph's outline. The distances are
+ * calculated from the center of the pixel and are positive if they are
+ * filled by the outline (i.e., inside the outline) and negative
+ * otherwise. Check the note below on how to convert the output values
+ * to usable data.
+ *
+ * @note:
+ * The selected render mode only affects vector glyphs of a font.
+ * Embedded bitmaps often have a different pixel mode like
+ * @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform them
+ * into 8-bit pixmaps.
+ *
+ * For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized
+ * distances that are packed into unsigned 8-bit values. To get pixel
+ * values in floating point representation use the following pseudo-C
+ * code for the conversion.
+ *
+ * ```
+ * // Load glyph and render using FT_RENDER_MODE_SDF,
+ * // then use the output buffer as follows.
+ *
+ * ...
+ * FT_Byte buffer = glyph->bitmap->buffer;
+ *
+ *
+ * for pixel in buffer
+ * {
+ * // `sd` is the signed distance and `spread` is the current spread;
+ * // the default spread is 2 and can be changed.
+ *
+ * float sd = (float)pixel - 128.0f;
+ *
+ *
+ * // Convert to pixel values.
+ * sd = ( sd / 128.0f ) * spread;
+ *
+ * // Store `sd` in a buffer or use as required.
+ * }
+ *
+ * ```
+ */
+ typedef enum FT_Render_Mode_
+ {
+ FT_RENDER_MODE_NORMAL = 0,
+ FT_RENDER_MODE_LIGHT,
+ FT_RENDER_MODE_MONO,
+ FT_RENDER_MODE_LCD,
+ FT_RENDER_MODE_LCD_V,
+ FT_RENDER_MODE_SDF,
+
+ FT_RENDER_MODE_MAX
+
+ } FT_Render_Mode;
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Render_Mode` values instead */
+#define ft_render_mode_normal FT_RENDER_MODE_NORMAL
+#define ft_render_mode_mono FT_RENDER_MODE_MONO
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Render_Glyph
+ *
+ * @description:
+ * Convert a given glyph image to a bitmap. It does so by inspecting the
+ * glyph image format, finding the relevant renderer, and invoking it.
+ *
+ * @inout:
+ * slot ::
+ * A handle to the glyph slot containing the image to convert.
+ *
+ * @input:
+ * render_mode ::
+ * The render mode used to render the glyph image into a bitmap. See
+ * @FT_Render_Mode for a list of possible values.
+ *
+ * If @FT_RENDER_MODE_NORMAL is used, a previous call of @FT_Load_Glyph
+ * with flag @FT_LOAD_COLOR makes FT_Render_Glyph provide a default
+ * blending of colored glyph layers associated with the current glyph
+ * slot (provided the font contains such layers) instead of rendering
+ * the glyph slot's outline. This is an experimental feature; see
+ * @FT_LOAD_COLOR for more information.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * To get meaningful results, font scaling values must be set with
+ * functions like @FT_Set_Char_Size before calling `FT_Render_Glyph`.
+ *
+ * When FreeType outputs a bitmap of a glyph, it really outputs an alpha
+ * coverage map. If a pixel is completely covered by a filled-in
+ * outline, the bitmap contains 0xFF at that pixel, meaning that
+ * 0xFF/0xFF fraction of that pixel is covered, meaning the pixel is 100%
+ * black (or 0% bright). If a pixel is only 50% covered (value 0x80),
+ * the pixel is made 50% black (50% bright or a middle shade of grey).
+ * 0% covered means 0% black (100% bright or white).
+ *
+ * On high-DPI screens like on smartphones and tablets, the pixels are so
+ * small that their chance of being completely covered and therefore
+ * completely black are fairly good. On the low-DPI screens, however,
+ * the situation is different. The pixels are too large for most of the
+ * details of a glyph and shades of gray are the norm rather than the
+ * exception.
+ *
+ * This is relevant because all our screens have a second problem: they
+ * are not linear. 1~+~1 is not~2. Twice the value does not result in
+ * twice the brightness. When a pixel is only 50% covered, the coverage
+ * map says 50% black, and this translates to a pixel value of 128 when
+ * you use 8~bits per channel (0-255). However, this does not translate
+ * to 50% brightness for that pixel on our sRGB and gamma~2.2 screens.
+ * Due to their non-linearity, they dwell longer in the darks and only a
+ * pixel value of about 186 results in 50% brightness -- 128 ends up too
+ * dark on both bright and dark backgrounds. The net result is that dark
+ * text looks burnt-out, pixely and blotchy on bright background, bright
+ * text too frail on dark backgrounds, and colored text on colored
+ * background (for example, red on green) seems to have dark halos or
+ * 'dirt' around it. The situation is especially ugly for diagonal stems
+ * like in 'w' glyph shapes where the quality of FreeType's anti-aliasing
+ * depends on the correct display of grays. On high-DPI screens where
+ * smaller, fully black pixels reign supreme, this doesn't matter, but on
+ * our low-DPI screens with all the gray shades, it does. 0% and 100%
+ * brightness are the same things in linear and non-linear space, just
+ * all the shades in-between aren't.
+ *
+ * The blending function for placing text over a background is
+ *
+ * ```
+ * dst = alpha * src + (1 - alpha) * dst ,
+ * ```
+ *
+ * which is known as the OVER operator.
+ *
+ * To correctly composite an anti-aliased pixel of a glyph onto a
+ * surface,
+ *
+ * 1. take the foreground and background colors (e.g., in sRGB space)
+ * and apply gamma to get them in a linear space,
+ *
+ * 2. use OVER to blend the two linear colors using the glyph pixel
+ * as the alpha value (remember, the glyph bitmap is an alpha coverage
+ * bitmap), and
+ *
+ * 3. apply inverse gamma to the blended pixel and write it back to
+ * the image.
+ *
+ * Internal testing at Adobe found that a target inverse gamma of~1.8 for
+ * step~3 gives good results across a wide range of displays with an sRGB
+ * gamma curve or a similar one.
+ *
+ * This process can cost performance. There is an approximation that
+ * does not need to know about the background color; see
+ * https://bel.fi/alankila/lcd/ and
+ * https://bel.fi/alankila/lcd/alpcor.html for details.
+ *
+ * **ATTENTION**: Linear blending is even more important when dealing
+ * with subpixel-rendered glyphs to prevent color-fringing! A
+ * subpixel-rendered glyph must first be filtered with a filter that
+ * gives equal weight to the three color primaries and does not exceed a
+ * sum of 0x100, see section @lcd_rendering. Then the only difference to
+ * gray linear blending is that subpixel-rendered linear blending is done
+ * 3~times per pixel: red foreground subpixel to red background subpixel
+ * and so on for green and blue.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_Render_Mode render_mode );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Kerning_Mode
+ *
+ * @description:
+ * An enumeration to specify the format of kerning values returned by
+ * @FT_Get_Kerning.
+ *
+ * @values:
+ * FT_KERNING_DEFAULT ::
+ * Return grid-fitted kerning distances in 26.6 fractional pixels.
+ *
+ * FT_KERNING_UNFITTED ::
+ * Return un-grid-fitted kerning distances in 26.6 fractional pixels.
+ *
+ * FT_KERNING_UNSCALED ::
+ * Return the kerning vector in original font units.
+ *
+ * @note:
+ * `FT_KERNING_DEFAULT` returns full pixel values; it also makes FreeType
+ * heuristically scale down kerning distances at small ppem values so
+ * that they don't become too big.
+ *
+ * Both `FT_KERNING_DEFAULT` and `FT_KERNING_UNFITTED` use the current
+ * horizontal scaling factor (as set e.g. with @FT_Set_Char_Size) to
+ * convert font units to pixels.
+ */
+ typedef enum FT_Kerning_Mode_
+ {
+ FT_KERNING_DEFAULT = 0,
+ FT_KERNING_UNFITTED,
+ FT_KERNING_UNSCALED
+
+ } FT_Kerning_Mode;
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Kerning_Mode` values instead */
+#define ft_kerning_default FT_KERNING_DEFAULT
+#define ft_kerning_unfitted FT_KERNING_UNFITTED
+#define ft_kerning_unscaled FT_KERNING_UNSCALED
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Kerning
+ *
+ * @description:
+ * Return the kerning vector between two glyphs of the same face.
+ *
+ * @input:
+ * face ::
+ * A handle to a source face object.
+ *
+ * left_glyph ::
+ * The index of the left glyph in the kern pair.
+ *
+ * right_glyph ::
+ * The index of the right glyph in the kern pair.
+ *
+ * kern_mode ::
+ * See @FT_Kerning_Mode for more information. Determines the scale and
+ * dimension of the returned kerning vector.
+ *
+ * @output:
+ * akerning ::
+ * The kerning vector. This is either in font units, fractional pixels
+ * (26.6 format), or pixels for scalable formats, and in pixels for
+ * fixed-sizes formats.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Only horizontal layouts (left-to-right & right-to-left) are supported
+ * by this method. Other layouts, or more sophisticated kernings, are
+ * out of the scope of this API function -- they can be implemented
+ * through format-specific interfaces.
+ *
+ * Kerning for OpenType fonts implemented in a 'GPOS' table is not
+ * supported; use @FT_HAS_KERNING to find out whether a font has data
+ * that can be extracted with `FT_Get_Kerning`.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Kerning( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_UInt kern_mode,
+ FT_Vector *akerning );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Track_Kerning
+ *
+ * @description:
+ * Return the track kerning for a given face object at a given size.
+ *
+ * @input:
+ * face ::
+ * A handle to a source face object.
+ *
+ * point_size ::
+ * The point size in 16.16 fractional points.
+ *
+ * degree ::
+ * The degree of tightness. Increasingly negative values represent
+ * tighter track kerning, while increasingly positive values represent
+ * looser track kerning. Value zero means no track kerning.
+ *
+ * @output:
+ * akerning ::
+ * The kerning in 16.16 fractional points, to be uniformly applied
+ * between all glyphs.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Currently, only the Type~1 font driver supports track kerning, using
+ * data from AFM files (if attached with @FT_Attach_File or
+ * @FT_Attach_Stream).
+ *
+ * Only very few AFM files come with track kerning data; please refer to
+ * Adobe's AFM specification for more details.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Track_Kerning( FT_Face face,
+ FT_Fixed point_size,
+ FT_Int degree,
+ FT_Fixed* akerning );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Glyph_Name
+ *
+ * @description:
+ * Retrieve the ASCII name of a given glyph in a face. This only works
+ * for those faces where @FT_HAS_GLYPH_NAMES(face) returns~1.
+ *
+ * @input:
+ * face ::
+ * A handle to a source face object.
+ *
+ * glyph_index ::
+ * The glyph index.
+ *
+ * buffer_max ::
+ * The maximum number of bytes available in the buffer.
+ *
+ * @output:
+ * buffer ::
+ * A pointer to a target buffer where the name is copied to.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * An error is returned if the face doesn't provide glyph names or if the
+ * glyph index is invalid. In all cases of failure, the first byte of
+ * `buffer` is set to~0 to indicate an empty name.
+ *
+ * The glyph name is truncated to fit within the buffer if it is too
+ * long. The returned string is always zero-terminated.
+ *
+ * Be aware that FreeType reorders glyph indices internally so that glyph
+ * index~0 always corresponds to the 'missing glyph' (called '.notdef').
+ *
+ * This function always returns an error if the config macro
+ * `FT_CONFIG_OPTION_NO_GLYPH_NAMES` is not defined in `ftoption.h`.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Glyph_Name( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Postscript_Name
+ *
+ * @description:
+ * Retrieve the ASCII PostScript name of a given face, if available.
+ * This only works with PostScript, TrueType, and OpenType fonts.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @return:
+ * A pointer to the face's PostScript name. `NULL` if unavailable.
+ *
+ * @note:
+ * The returned pointer is owned by the face and is destroyed with it.
+ *
+ * For variation fonts, this string changes if you select a different
+ * instance, and you have to call `FT_Get_PostScript_Name` again to
+ * retrieve it. FreeType follows Adobe TechNote #5902, 'Generating
+ * PostScript Names for Fonts Using OpenType Font Variations'.
+ *
+ * https://download.macromedia.com/pub/developer/opentype/tech-notes/5902.AdobePSNameGeneration.html
+ *
+ * [Since 2.9] Special PostScript names for named instances are only
+ * returned if the named instance is set with @FT_Set_Named_Instance (and
+ * the font has corresponding entries in its 'fvar' table). If
+ * @FT_IS_VARIATION returns true, the algorithmically derived PostScript
+ * name is provided, not looking up special entries for named instances.
+ */
+ FT_EXPORT( const char* )
+ FT_Get_Postscript_Name( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Select_Charmap
+ *
+ * @description:
+ * Select a given charmap by its encoding tag (as listed in
+ * `freetype.h`).
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @input:
+ * encoding ::
+ * A handle to the selected encoding.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function returns an error if no charmap in the face corresponds
+ * to the encoding queried here.
+ *
+ * Because many fonts contain more than a single cmap for Unicode
+ * encoding, this function has some special code to select the one that
+ * covers Unicode best ('best' in the sense that a UCS-4 cmap is
+ * preferred to a UCS-2 cmap). It is thus preferable to @FT_Set_Charmap
+ * in this case.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Select_Charmap( FT_Face face,
+ FT_Encoding encoding );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Charmap
+ *
+ * @description:
+ * Select a given charmap for character code to glyph index mapping.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @input:
+ * charmap ::
+ * A handle to the selected charmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function returns an error if the charmap is not part of the face
+ * (i.e., if it is not listed in the `face->charmaps` table).
+ *
+ * It also fails if an OpenType type~14 charmap is selected (which
+ * doesn't map character codes to glyph indices at all).
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Charmap( FT_Face face,
+ FT_CharMap charmap );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Charmap_Index
+ *
+ * @description:
+ * Retrieve index of a given charmap.
+ *
+ * @input:
+ * charmap ::
+ * A handle to a charmap.
+ *
+ * @return:
+ * The index into the array of character maps within the face to which
+ * `charmap` belongs. If an error occurs, -1 is returned.
+ *
+ */
+ FT_EXPORT( FT_Int )
+ FT_Get_Charmap_Index( FT_CharMap charmap );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Char_Index
+ *
+ * @description:
+ * Return the glyph index of a given character code. This function uses
+ * the currently selected charmap to do the mapping.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character code.
+ *
+ * @return:
+ * The glyph index. 0~means 'undefined character code'.
+ *
+ * @note:
+ * If you use FreeType to manipulate the contents of font files directly,
+ * be aware that the glyph index returned by this function doesn't always
+ * correspond to the internal indices used within the file. This is done
+ * to ensure that value~0 always corresponds to the 'missing glyph'. If
+ * the first glyph is not named '.notdef', then for Type~1 and Type~42
+ * fonts, '.notdef' will be moved into the glyph ID~0 position, and
+ * whatever was there will be moved to the position '.notdef' had. For
+ * Type~1 fonts, if there is no '.notdef' glyph at all, then one will be
+ * created at index~0 and whatever was there will be moved to the last
+ * index -- Type~42 fonts are considered invalid under this condition.
+ */
+ FT_EXPORT( FT_UInt )
+ FT_Get_Char_Index( FT_Face face,
+ FT_ULong charcode );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_First_Char
+ *
+ * @description:
+ * Return the first character code in the current charmap of a given
+ * face, together with its corresponding glyph index.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @output:
+ * agindex ::
+ * Glyph index of first character code. 0~if charmap is empty.
+ *
+ * @return:
+ * The charmap's first character code.
+ *
+ * @note:
+ * You should use this function together with @FT_Get_Next_Char to parse
+ * all character codes available in a given charmap. The code should
+ * look like this:
+ *
+ * ```
+ * FT_ULong charcode;
+ * FT_UInt gindex;
+ *
+ *
+ * charcode = FT_Get_First_Char( face, &gindex );
+ * while ( gindex != 0 )
+ * {
+ * ... do something with (charcode,gindex) pair ...
+ *
+ * charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ * }
+ * ```
+ *
+ * Be aware that character codes can have values up to 0xFFFFFFFF; this
+ * might happen for non-Unicode or malformed cmaps. However, even with
+ * regular Unicode encoding, so-called 'last resort fonts' (using SFNT
+ * cmap format 13, see function @FT_Get_CMap_Format) normally have
+ * entries for all Unicode characters up to 0x1FFFFF, which can cause *a
+ * lot* of iterations.
+ *
+ * Note that `*agindex` is set to~0 if the charmap is empty. The result
+ * itself can be~0 in two cases: if the charmap is empty or if the
+ * value~0 is the first valid character code.
+ */
+ FT_EXPORT( FT_ULong )
+ FT_Get_First_Char( FT_Face face,
+ FT_UInt *agindex );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Next_Char
+ *
+ * @description:
+ * Return the next character code in the current charmap of a given face
+ * following the value `char_code`, as well as the corresponding glyph
+ * index.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * char_code ::
+ * The starting character code.
+ *
+ * @output:
+ * agindex ::
+ * Glyph index of next character code. 0~if charmap is empty.
+ *
+ * @return:
+ * The charmap's next character code.
+ *
+ * @note:
+ * You should use this function with @FT_Get_First_Char to walk over all
+ * character codes available in a given charmap. See the note for that
+ * function for a simple code example.
+ *
+ * Note that `*agindex` is set to~0 when there are no more codes in the
+ * charmap.
+ */
+ FT_EXPORT( FT_ULong )
+ FT_Get_Next_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_UInt *agindex );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_Properties
+ *
+ * @description:
+ * Set or override certain (library or module-wide) properties on a
+ * face-by-face basis. Useful for finer-grained control and avoiding
+ * locks on shared structures (threads can modify their own faces as they
+ * see fit).
+ *
+ * Contrary to @FT_Property_Set, this function uses @FT_Parameter so that
+ * you can pass multiple properties to the target face in one call. Note
+ * that only a subset of the available properties can be controlled.
+ *
+ * * @FT_PARAM_TAG_STEM_DARKENING (stem darkening, corresponding to the
+ * property `no-stem-darkening` provided by the 'autofit', 'cff',
+ * 'type1', and 't1cid' modules; see @no-stem-darkening).
+ *
+ * * @FT_PARAM_TAG_LCD_FILTER_WEIGHTS (LCD filter weights, corresponding
+ * to function @FT_Library_SetLcdFilterWeights).
+ *
+ * * @FT_PARAM_TAG_RANDOM_SEED (seed value for the CFF, Type~1, and CID
+ * 'random' operator, corresponding to the `random-seed` property
+ * provided by the 'cff', 'type1', and 't1cid' modules; see
+ * @random-seed).
+ *
+ * Pass `NULL` as `data` in @FT_Parameter for a given tag to reset the
+ * option and use the library or module default again.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * num_properties ::
+ * The number of properties that follow.
+ *
+ * properties ::
+ * A handle to an @FT_Parameter array with `num_properties` elements.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @example:
+ * Here is an example that sets three properties. You must define
+ * `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` to make the LCD filter examples
+ * work.
+ *
+ * ```
+ * FT_Parameter property1;
+ * FT_Bool darken_stems = 1;
+ *
+ * FT_Parameter property2;
+ * FT_LcdFiveTapFilter custom_weight =
+ * { 0x11, 0x44, 0x56, 0x44, 0x11 };
+ *
+ * FT_Parameter property3;
+ * FT_Int32 random_seed = 314159265;
+ *
+ * FT_Parameter properties[3] = { property1,
+ * property2,
+ * property3 };
+ *
+ *
+ * property1.tag = FT_PARAM_TAG_STEM_DARKENING;
+ * property1.data = &darken_stems;
+ *
+ * property2.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS;
+ * property2.data = custom_weight;
+ *
+ * property3.tag = FT_PARAM_TAG_RANDOM_SEED;
+ * property3.data = &random_seed;
+ *
+ * FT_Face_Properties( face, 3, properties );
+ * ```
+ *
+ * The next example resets a single property to its default value.
+ *
+ * ```
+ * FT_Parameter property;
+ *
+ *
+ * property.tag = FT_PARAM_TAG_LCD_FILTER_WEIGHTS;
+ * property.data = NULL;
+ *
+ * FT_Face_Properties( face, 1, &property );
+ * ```
+ *
+ * @since:
+ * 2.8
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Face_Properties( FT_Face face,
+ FT_UInt num_properties,
+ FT_Parameter* properties );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Name_Index
+ *
+ * @description:
+ * Return the glyph index of a given glyph name.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * glyph_name ::
+ * The glyph name.
+ *
+ * @return:
+ * The glyph index. 0~means 'undefined character code'.
+ */
+ FT_EXPORT( FT_UInt )
+ FT_Get_Name_Index( FT_Face face,
+ const FT_String* glyph_name );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_SUBGLYPH_FLAG_XXX
+ *
+ * @description:
+ * A list of constants describing subglyphs. Please refer to the 'glyf'
+ * table description in the OpenType specification for the meaning of the
+ * various flags (which get synthesized for non-OpenType subglyphs).
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
+ *
+ * @values:
+ * FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS ::
+ * FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ::
+ * FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID ::
+ * FT_SUBGLYPH_FLAG_SCALE ::
+ * FT_SUBGLYPH_FLAG_XY_SCALE ::
+ * FT_SUBGLYPH_FLAG_2X2 ::
+ * FT_SUBGLYPH_FLAG_USE_MY_METRICS ::
+ *
+ */
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_WORDS 1
+#define FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES 2
+#define FT_SUBGLYPH_FLAG_ROUND_XY_TO_GRID 4
+#define FT_SUBGLYPH_FLAG_SCALE 8
+#define FT_SUBGLYPH_FLAG_XY_SCALE 0x40
+#define FT_SUBGLYPH_FLAG_2X2 0x80
+#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_SubGlyph_Info
+ *
+ * @description:
+ * Retrieve a description of a given subglyph. Only use it if
+ * `glyph->format` is @FT_GLYPH_FORMAT_COMPOSITE; an error is returned
+ * otherwise.
+ *
+ * @input:
+ * glyph ::
+ * The source glyph slot.
+ *
+ * sub_index ::
+ * The index of the subglyph. Must be less than
+ * `glyph->num_subglyphs`.
+ *
+ * @output:
+ * p_index ::
+ * The glyph index of the subglyph.
+ *
+ * p_flags ::
+ * The subglyph flags, see @FT_SUBGLYPH_FLAG_XXX.
+ *
+ * p_arg1 ::
+ * The subglyph's first argument (if any).
+ *
+ * p_arg2 ::
+ * The subglyph's second argument (if any).
+ *
+ * p_transform ::
+ * The subglyph transformation (if any).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The values of `*p_arg1`, `*p_arg2`, and `*p_transform` must be
+ * interpreted depending on the flags returned in `*p_flags`. See the
+ * OpenType specification for details.
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf#composite-glyph-description
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_SubGlyph_Info( FT_GlyphSlot glyph,
+ FT_UInt sub_index,
+ FT_Int *p_index,
+ FT_UInt *p_flags,
+ FT_Int *p_arg1,
+ FT_Int *p_arg2,
+ FT_Matrix *p_transform );
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * base_interface
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_FSTYPE_XXX
+ *
+ * @description:
+ * A list of bit flags used in the `fsType` field of the OS/2 table in a
+ * TrueType or OpenType font and the `FSType` entry in a PostScript font.
+ * These bit flags are returned by @FT_Get_FSType_Flags; they inform
+ * client applications of embedding and subsetting restrictions
+ * associated with a font.
+ *
+ * See
+ * https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/FontPolicies.pdf
+ * for more details.
+ *
+ * @values:
+ * FT_FSTYPE_INSTALLABLE_EMBEDDING ::
+ * Fonts with no fsType bit set may be embedded and permanently
+ * installed on the remote system by an application.
+ *
+ * FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING ::
+ * Fonts that have only this bit set must not be modified, embedded or
+ * exchanged in any manner without first obtaining permission of the
+ * font software copyright owner.
+ *
+ * FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING ::
+ * The font may be embedded and temporarily loaded on the remote
+ * system. Documents containing Preview & Print fonts must be opened
+ * 'read-only'; no edits can be applied to the document.
+ *
+ * FT_FSTYPE_EDITABLE_EMBEDDING ::
+ * The font may be embedded but must only be installed temporarily on
+ * other systems. In contrast to Preview & Print fonts, documents
+ * containing editable fonts may be opened for reading, editing is
+ * permitted, and changes may be saved.
+ *
+ * FT_FSTYPE_NO_SUBSETTING ::
+ * The font may not be subsetted prior to embedding.
+ *
+ * FT_FSTYPE_BITMAP_EMBEDDING_ONLY ::
+ * Only bitmaps contained in the font may be embedded; no outline data
+ * may be embedded. If there are no bitmaps available in the font,
+ * then the font is unembeddable.
+ *
+ * @note:
+ * The flags are ORed together, thus more than a single value can be
+ * returned.
+ *
+ * While the `fsType` flags can indicate that a font may be embedded, a
+ * license with the font vendor may be separately required to use the
+ * font in this way.
+ */
+#define FT_FSTYPE_INSTALLABLE_EMBEDDING 0x0000
+#define FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING 0x0002
+#define FT_FSTYPE_PREVIEW_AND_PRINT_EMBEDDING 0x0004
+#define FT_FSTYPE_EDITABLE_EMBEDDING 0x0008
+#define FT_FSTYPE_NO_SUBSETTING 0x0100
+#define FT_FSTYPE_BITMAP_EMBEDDING_ONLY 0x0200
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_FSType_Flags
+ *
+ * @description:
+ * Return the `fsType` flags for a font.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @return:
+ * The `fsType` flags, see @FT_FSTYPE_XXX.
+ *
+ * @note:
+ * Use this function rather than directly reading the `fs_type` field in
+ * the @PS_FontInfoRec structure, which is only guaranteed to return the
+ * correct results for Type~1 fonts.
+ *
+ * @since:
+ * 2.3.8
+ *
+ */
+ FT_EXPORT( FT_UShort )
+ FT_Get_FSType_Flags( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * glyph_variants
+ *
+ * @title:
+ * Unicode Variation Sequences
+ *
+ * @abstract:
+ * The FreeType~2 interface to Unicode Variation Sequences (UVS), using
+ * the SFNT cmap format~14.
+ *
+ * @description:
+ * Many characters, especially for CJK scripts, have variant forms. They
+ * are a sort of grey area somewhere between being totally irrelevant and
+ * semantically distinct; for this reason, the Unicode consortium decided
+ * to introduce Variation Sequences (VS), consisting of a Unicode base
+ * character and a variation selector instead of further extending the
+ * already huge number of characters.
+ *
+ * Unicode maintains two different sets, namely 'Standardized Variation
+ * Sequences' and registered 'Ideographic Variation Sequences' (IVS),
+ * collected in the 'Ideographic Variation Database' (IVD).
+ *
+ * https://unicode.org/Public/UCD/latest/ucd/StandardizedVariants.txt
+ * https://unicode.org/reports/tr37/ https://unicode.org/ivd/
+ *
+ * To date (January 2017), the character with the most ideographic
+ * variations is U+9089, having 32 such IVS.
+ *
+ * Three Mongolian Variation Selectors have the values U+180B-U+180D; 256
+ * generic Variation Selectors are encoded in the ranges U+FE00-U+FE0F
+ * and U+E0100-U+E01EF. IVS currently use Variation Selectors from the
+ * range U+E0100-U+E01EF only.
+ *
+ * A VS consists of the base character value followed by a single
+ * Variation Selector. For example, to get the first variation of
+ * U+9089, you have to write the character sequence `U+9089 U+E0100`.
+ *
+ * Adobe and MS decided to support both standardized and ideographic VS
+ * with a new cmap subtable (format~14). It is an odd subtable because
+ * it is not a mapping of input code points to glyphs, but contains lists
+ * of all variations supported by the font.
+ *
+ * A variation may be either 'default' or 'non-default' for a given font.
+ * A default variation is the one you will get for that code point if you
+ * look it up in the standard Unicode cmap. A non-default variation is a
+ * different glyph.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetCharVariantIndex
+ *
+ * @description:
+ * Return the glyph index of a given character code as modified by the
+ * variation selector.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character code point in Unicode.
+ *
+ * variantSelector ::
+ * The Unicode code point of the variation selector.
+ *
+ * @return:
+ * The glyph index. 0~means either 'undefined character code', or
+ * 'undefined selector code', or 'no variation selector cmap subtable',
+ * or 'current CharMap is not Unicode'.
+ *
+ * @note:
+ * If you use FreeType to manipulate the contents of font files directly,
+ * be aware that the glyph index returned by this function doesn't always
+ * correspond to the internal indices used within the file. This is done
+ * to ensure that value~0 always corresponds to the 'missing glyph'.
+ *
+ * This function is only meaningful if
+ * a) the font has a variation selector cmap sub table, and
+ * b) the current charmap has a Unicode encoding.
+ *
+ * @since:
+ * 2.3.6
+ *
+ */
+ FT_EXPORT( FT_UInt )
+ FT_Face_GetCharVariantIndex( FT_Face face,
+ FT_ULong charcode,
+ FT_ULong variantSelector );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetCharVariantIsDefault
+ *
+ * @description:
+ * Check whether this variation of this Unicode character is the one to
+ * be found in the charmap.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character codepoint in Unicode.
+ *
+ * variantSelector ::
+ * The Unicode codepoint of the variation selector.
+ *
+ * @return:
+ * 1~if found in the standard (Unicode) cmap, 0~if found in the variation
+ * selector cmap, or -1 if it is not a variation.
+ *
+ * @note:
+ * This function is only meaningful if the font has a variation selector
+ * cmap subtable.
+ *
+ * @since:
+ * 2.3.6
+ *
+ */
+ FT_EXPORT( FT_Int )
+ FT_Face_GetCharVariantIsDefault( FT_Face face,
+ FT_ULong charcode,
+ FT_ULong variantSelector );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetVariantSelectors
+ *
+ * @description:
+ * Return a zero-terminated list of Unicode variation selectors found in
+ * the font.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * @return:
+ * A pointer to an array of selector code points, or `NULL` if there is
+ * no valid variation selector cmap subtable.
+ *
+ * @note:
+ * The last item in the array is~0; the array is owned by the @FT_Face
+ * object but can be overwritten or released on the next call to a
+ * FreeType function.
+ *
+ * @since:
+ * 2.3.6
+ *
+ */
+ FT_EXPORT( FT_UInt32* )
+ FT_Face_GetVariantSelectors( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetVariantsOfChar
+ *
+ * @description:
+ * Return a zero-terminated list of Unicode variation selectors found for
+ * the specified character code.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * charcode ::
+ * The character codepoint in Unicode.
+ *
+ * @return:
+ * A pointer to an array of variation selector code points that are
+ * active for the given character, or `NULL` if the corresponding list is
+ * empty.
+ *
+ * @note:
+ * The last item in the array is~0; the array is owned by the @FT_Face
+ * object but can be overwritten or released on the next call to a
+ * FreeType function.
+ *
+ * @since:
+ * 2.3.6
+ *
+ */
+ FT_EXPORT( FT_UInt32* )
+ FT_Face_GetVariantsOfChar( FT_Face face,
+ FT_ULong charcode );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_GetCharsOfVariant
+ *
+ * @description:
+ * Return a zero-terminated list of Unicode character codes found for the
+ * specified variation selector.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face object.
+ *
+ * variantSelector ::
+ * The variation selector code point in Unicode.
+ *
+ * @return:
+ * A list of all the code points that are specified by this selector
+ * (both default and non-default codes are returned) or `NULL` if there
+ * is no valid cmap or the variation selector is invalid.
+ *
+ * @note:
+ * The last item in the array is~0; the array is owned by the @FT_Face
+ * object but can be overwritten or released on the next call to a
+ * FreeType function.
+ *
+ * @since:
+ * 2.3.6
+ *
+ */
+ FT_EXPORT( FT_UInt32* )
+ FT_Face_GetCharsOfVariant( FT_Face face,
+ FT_ULong variantSelector );
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * computations
+ *
+ * @title:
+ * Computations
+ *
+ * @abstract:
+ * Crunching fixed numbers and vectors.
+ *
+ * @description:
+ * This section contains various functions used to perform computations
+ * on 16.16 fixed-float numbers or 2d vectors.
+ *
+ * **Attention**: Most arithmetic functions take `FT_Long` as arguments.
+ * For historical reasons, FreeType was designed under the assumption
+ * that `FT_Long` is a 32-bit integer; results can thus be undefined if
+ * the arguments don't fit into 32 bits.
+ *
+ * @order:
+ * FT_MulDiv
+ * FT_MulFix
+ * FT_DivFix
+ * FT_RoundFix
+ * FT_CeilFix
+ * FT_FloorFix
+ * FT_Vector_Transform
+ * FT_Matrix_Multiply
+ * FT_Matrix_Invert
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_MulDiv
+ *
+ * @description:
+ * Compute `(a*b)/c` with maximum accuracy, using a 64-bit intermediate
+ * integer whenever necessary.
+ *
+ * This function isn't necessarily as fast as some processor-specific
+ * operations, but is at least completely portable.
+ *
+ * @input:
+ * a ::
+ * The first multiplier.
+ *
+ * b ::
+ * The second multiplier.
+ *
+ * c ::
+ * The divisor.
+ *
+ * @return:
+ * The result of `(a*b)/c`. This function never traps when trying to
+ * divide by zero; it simply returns 'MaxInt' or 'MinInt' depending on
+ * the signs of `a` and `b`.
+ */
+ FT_EXPORT( FT_Long )
+ FT_MulDiv( FT_Long a,
+ FT_Long b,
+ FT_Long c );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_MulFix
+ *
+ * @description:
+ * Compute `(a*b)/0x10000` with maximum accuracy. Its main use is to
+ * multiply a given value by a 16.16 fixed-point factor.
+ *
+ * @input:
+ * a ::
+ * The first multiplier.
+ *
+ * b ::
+ * The second multiplier. Use a 16.16 factor here whenever possible
+ * (see note below).
+ *
+ * @return:
+ * The result of `(a*b)/0x10000`.
+ *
+ * @note:
+ * This function has been optimized for the case where the absolute value
+ * of `a` is less than 2048, and `b` is a 16.16 scaling factor. As this
+ * happens mainly when scaling from notional units to fractional pixels
+ * in FreeType, it resulted in noticeable speed improvements between
+ * versions 2.x and 1.x.
+ *
+ * As a conclusion, always try to place a 16.16 factor as the _second_
+ * argument of this function; this can make a great difference.
+ */
+ FT_EXPORT( FT_Long )
+ FT_MulFix( FT_Long a,
+ FT_Long b );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_DivFix
+ *
+ * @description:
+ * Compute `(a*0x10000)/b` with maximum accuracy. Its main use is to
+ * divide a given value by a 16.16 fixed-point factor.
+ *
+ * @input:
+ * a ::
+ * The numerator.
+ *
+ * b ::
+ * The denominator. Use a 16.16 factor here.
+ *
+ * @return:
+ * The result of `(a*0x10000)/b`.
+ */
+ FT_EXPORT( FT_Long )
+ FT_DivFix( FT_Long a,
+ FT_Long b );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_RoundFix
+ *
+ * @description:
+ * Round a 16.16 fixed number.
+ *
+ * @input:
+ * a ::
+ * The number to be rounded.
+ *
+ * @return:
+ * `a` rounded to the nearest 16.16 fixed integer, halfway cases away
+ * from zero.
+ *
+ * @note:
+ * The function uses wrap-around arithmetic.
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_RoundFix( FT_Fixed a );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_CeilFix
+ *
+ * @description:
+ * Compute the smallest following integer of a 16.16 fixed number.
+ *
+ * @input:
+ * a ::
+ * The number for which the ceiling function is to be computed.
+ *
+ * @return:
+ * `a` rounded towards plus infinity.
+ *
+ * @note:
+ * The function uses wrap-around arithmetic.
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_CeilFix( FT_Fixed a );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_FloorFix
+ *
+ * @description:
+ * Compute the largest previous integer of a 16.16 fixed number.
+ *
+ * @input:
+ * a ::
+ * The number for which the floor function is to be computed.
+ *
+ * @return:
+ * `a` rounded towards minus infinity.
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_FloorFix( FT_Fixed a );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_Transform
+ *
+ * @description:
+ * Transform a single vector through a 2x2 matrix.
+ *
+ * @inout:
+ * vector ::
+ * The target vector to transform.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to the source 2x2 matrix.
+ *
+ * @note:
+ * The result is undefined if either `vector` or `matrix` is invalid.
+ */
+ FT_EXPORT( void )
+ FT_Vector_Transform( FT_Vector* vector,
+ const FT_Matrix* matrix );
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * version
+ *
+ * @title:
+ * FreeType Version
+ *
+ * @abstract:
+ * Functions and macros related to FreeType versions.
+ *
+ * @description:
+ * Note that those functions and macros are of limited use because even a
+ * new release of FreeType with only documentation changes increases the
+ * version number.
+ *
+ * @order:
+ * FT_Library_Version
+ *
+ * FREETYPE_MAJOR
+ * FREETYPE_MINOR
+ * FREETYPE_PATCH
+ *
+ * FT_Face_CheckTrueTypePatents
+ * FT_Face_SetUnpatentedHinting
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FREETYPE_XXX
+ *
+ * @description:
+ * These three macros identify the FreeType source code version. Use
+ * @FT_Library_Version to access them at runtime.
+ *
+ * @values:
+ * FREETYPE_MAJOR ::
+ * The major version number.
+ * FREETYPE_MINOR ::
+ * The minor version number.
+ * FREETYPE_PATCH ::
+ * The patch level.
+ *
+ * @note:
+ * The version number of FreeType if built as a dynamic link library with
+ * the 'libtool' package is _not_ controlled by these three macros.
+ *
+ */
+#define FREETYPE_MAJOR 2
+#define FREETYPE_MINOR 11
+#define FREETYPE_PATCH 0
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Library_Version
+ *
+ * @description:
+ * Return the version of the FreeType library being used. This is useful
+ * when dynamically linking to the library, since one cannot use the
+ * macros @FREETYPE_MAJOR, @FREETYPE_MINOR, and @FREETYPE_PATCH.
+ *
+ * @input:
+ * library ::
+ * A source library handle.
+ *
+ * @output:
+ * amajor ::
+ * The major version number.
+ *
+ * aminor ::
+ * The minor version number.
+ *
+ * apatch ::
+ * The patch version number.
+ *
+ * @note:
+ * The reason why this function takes a `library` argument is because
+ * certain programs implement library initialization in a custom way that
+ * doesn't use @FT_Init_FreeType.
+ *
+ * In such cases, the library version might not be available before the
+ * library object has been created.
+ */
+ FT_EXPORT( void )
+ FT_Library_Version( FT_Library library,
+ FT_Int *amajor,
+ FT_Int *aminor,
+ FT_Int *apatch );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_CheckTrueTypePatents
+ *
+ * @description:
+ * Deprecated, does nothing.
+ *
+ * @input:
+ * face ::
+ * A face handle.
+ *
+ * @return:
+ * Always returns false.
+ *
+ * @note:
+ * Since May 2010, TrueType hinting is no longer patented.
+ *
+ * @since:
+ * 2.3.5
+ *
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Face_CheckTrueTypePatents( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Face_SetUnpatentedHinting
+ *
+ * @description:
+ * Deprecated, does nothing.
+ *
+ * @input:
+ * face ::
+ * A face handle.
+ *
+ * value ::
+ * New boolean setting.
+ *
+ * @return:
+ * Always returns false.
+ *
+ * @note:
+ * Since May 2010, TrueType hinting is no longer patented.
+ *
+ * @since:
+ * 2.3.5
+ *
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Face_SetUnpatentedHinting( FT_Face face,
+ FT_Bool value );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FREETYPE_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftadvanc.h b/Client/ThirdParty/freetype/include/freetype/ftadvanc.h
new file mode 100644
index 0000000..3a13bd3
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftadvanc.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+ *
+ * ftadvanc.h
+ *
+ * Quick computation of advance widths (specification only).
+ *
+ * Copyright (C) 2008-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTADVANC_H_
+#define FTADVANC_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * quick_advance
+ *
+ * @title:
+ * Quick retrieval of advance values
+ *
+ * @abstract:
+ * Retrieve horizontal and vertical advance values without processing
+ * glyph outlines, if possible.
+ *
+ * @description:
+ * This section contains functions to quickly extract advance values
+ * without handling glyph outlines, if possible.
+ *
+ * @order:
+ * FT_Get_Advance
+ * FT_Get_Advances
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_ADVANCE_FLAG_FAST_ONLY
+ *
+ * @description:
+ * A bit-flag to be OR-ed with the `flags` parameter of the
+ * @FT_Get_Advance and @FT_Get_Advances functions.
+ *
+ * If set, it indicates that you want these functions to fail if the
+ * corresponding hinting mode or font driver doesn't allow for very quick
+ * advance computation.
+ *
+ * Typically, glyphs that are either unscaled, unhinted, bitmapped, or
+ * light-hinted can have their advance width computed very quickly.
+ *
+ * Normal and bytecode hinted modes that require loading, scaling, and
+ * hinting of the glyph outline, are extremely slow by comparison.
+ */
+#define FT_ADVANCE_FLAG_FAST_ONLY 0x20000000L
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Advance
+ *
+ * @description:
+ * Retrieve the advance value of a given glyph outline in an @FT_Face.
+ *
+ * @input:
+ * face ::
+ * The source @FT_Face handle.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * load_flags ::
+ * A set of bit flags similar to those used when calling
+ * @FT_Load_Glyph, used to determine what kind of advances you need.
+ *
+ * @output:
+ * padvance ::
+ * The advance value. If scaling is performed (based on the value of
+ * `load_flags`), the advance value is in 16.16 format. Otherwise, it
+ * is in font units.
+ *
+ * If @FT_LOAD_VERTICAL_LAYOUT is set, this is the vertical advance
+ * corresponding to a vertical layout. Otherwise, it is the horizontal
+ * advance in a horizontal layout.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and if
+ * the corresponding font backend doesn't have a quick way to retrieve
+ * the advances.
+ *
+ * A scaled advance is returned in 16.16 format but isn't transformed by
+ * the affine transformation specified by @FT_Set_Transform.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Advance( FT_Face face,
+ FT_UInt gindex,
+ FT_Int32 load_flags,
+ FT_Fixed *padvance );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Advances
+ *
+ * @description:
+ * Retrieve the advance values of several glyph outlines in an @FT_Face.
+ *
+ * @input:
+ * face ::
+ * The source @FT_Face handle.
+ *
+ * start ::
+ * The first glyph index.
+ *
+ * count ::
+ * The number of advance values you want to retrieve.
+ *
+ * load_flags ::
+ * A set of bit flags similar to those used when calling
+ * @FT_Load_Glyph.
+ *
+ * @output:
+ * padvance ::
+ * The advance values. This array, to be provided by the caller, must
+ * contain at least `count` elements.
+ *
+ * If scaling is performed (based on the value of `load_flags`), the
+ * advance values are in 16.16 format. Otherwise, they are in font
+ * units.
+ *
+ * If @FT_LOAD_VERTICAL_LAYOUT is set, these are the vertical advances
+ * corresponding to a vertical layout. Otherwise, they are the
+ * horizontal advances in a horizontal layout.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @note:
+ * This function may fail if you use @FT_ADVANCE_FLAG_FAST_ONLY and if
+ * the corresponding font backend doesn't have a quick way to retrieve
+ * the advances.
+ *
+ * Scaled advances are returned in 16.16 format but aren't transformed by
+ * the affine transformation specified by @FT_Set_Transform.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Advances( FT_Face face,
+ FT_UInt start,
+ FT_UInt count,
+ FT_Int32 load_flags,
+ FT_Fixed *padvances );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTADVANC_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftbbox.h b/Client/ThirdParty/freetype/include/freetype/ftbbox.h
new file mode 100644
index 0000000..713aedb
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftbbox.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ *
+ * ftbbox.h
+ *
+ * FreeType exact bbox computation (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This component has a _single_ role: to compute exact outline bounding
+ * boxes.
+ *
+ * It is separated from the rest of the engine for various technical
+ * reasons. It may well be integrated in 'ftoutln' later.
+ *
+ */
+
+
+#ifndef FTBBOX_H_
+#define FTBBOX_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * outline_processing
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_BBox
+ *
+ * @description:
+ * Compute the exact bounding box of an outline. This is slower than
+ * computing the control box. However, it uses an advanced algorithm
+ * that returns _very_ quickly when the two boxes coincide. Otherwise,
+ * the outline Bezier arcs are traversed to extract their extrema.
+ *
+ * @input:
+ * outline ::
+ * A pointer to the source outline.
+ *
+ * @output:
+ * abbox ::
+ * The outline's exact bounding box.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If the font is tricky and the glyph has been loaded with
+ * @FT_LOAD_NO_SCALE, the resulting BBox is meaningless. To get
+ * reasonable values for the BBox it is necessary to load the glyph at a
+ * large ppem value (so that the hinting instructions can properly shift
+ * and scale the subglyphs), then extracting the BBox, which can be
+ * eventually converted back to font units.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Get_BBox( FT_Outline* outline,
+ FT_BBox *abbox );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTBBOX_H_ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftbdf.h b/Client/ThirdParty/freetype/include/freetype/ftbdf.h
new file mode 100644
index 0000000..c428506
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftbdf.h
@@ -0,0 +1,212 @@
+/****************************************************************************
+ *
+ * ftbdf.h
+ *
+ * FreeType API for accessing BDF-specific strings (specification).
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTBDF_H_
+#define FTBDF_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * bdf_fonts
+ *
+ * @title:
+ * BDF and PCF Files
+ *
+ * @abstract:
+ * BDF and PCF specific API.
+ *
+ * @description:
+ * This section contains the declaration of functions specific to BDF and
+ * PCF fonts.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * BDF_PropertyType
+ *
+ * @description:
+ * A list of BDF property types.
+ *
+ * @values:
+ * BDF_PROPERTY_TYPE_NONE ::
+ * Value~0 is used to indicate a missing property.
+ *
+ * BDF_PROPERTY_TYPE_ATOM ::
+ * Property is a string atom.
+ *
+ * BDF_PROPERTY_TYPE_INTEGER ::
+ * Property is a 32-bit signed integer.
+ *
+ * BDF_PROPERTY_TYPE_CARDINAL ::
+ * Property is a 32-bit unsigned integer.
+ */
+ typedef enum BDF_PropertyType_
+ {
+ BDF_PROPERTY_TYPE_NONE = 0,
+ BDF_PROPERTY_TYPE_ATOM = 1,
+ BDF_PROPERTY_TYPE_INTEGER = 2,
+ BDF_PROPERTY_TYPE_CARDINAL = 3
+
+ } BDF_PropertyType;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * BDF_Property
+ *
+ * @description:
+ * A handle to a @BDF_PropertyRec structure to model a given BDF/PCF
+ * property.
+ */
+ typedef struct BDF_PropertyRec_* BDF_Property;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * BDF_PropertyRec
+ *
+ * @description:
+ * This structure models a given BDF/PCF property.
+ *
+ * @fields:
+ * type ::
+ * The property type.
+ *
+ * u.atom ::
+ * The atom string, if type is @BDF_PROPERTY_TYPE_ATOM. May be
+ * `NULL`, indicating an empty string.
+ *
+ * u.integer ::
+ * A signed integer, if type is @BDF_PROPERTY_TYPE_INTEGER.
+ *
+ * u.cardinal ::
+ * An unsigned integer, if type is @BDF_PROPERTY_TYPE_CARDINAL.
+ */
+ typedef struct BDF_PropertyRec_
+ {
+ BDF_PropertyType type;
+ union {
+ const char* atom;
+ FT_Int32 integer;
+ FT_UInt32 cardinal;
+
+ } u;
+
+ } BDF_PropertyRec;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_BDF_Charset_ID
+ *
+ * @description:
+ * Retrieve a BDF font character set identity, according to the BDF
+ * specification.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * @output:
+ * acharset_encoding ::
+ * Charset encoding, as a C~string, owned by the face.
+ *
+ * acharset_registry ::
+ * Charset registry, as a C~string, owned by the face.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with BDF faces, returning an error otherwise.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_BDF_Charset_ID( FT_Face face,
+ const char* *acharset_encoding,
+ const char* *acharset_registry );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_BDF_Property
+ *
+ * @description:
+ * Retrieve a BDF property from a BDF or PCF font file.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * name ::
+ * The property name.
+ *
+ * @output:
+ * aproperty ::
+ * The property.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function works with BDF _and_ PCF fonts. It returns an error
+ * otherwise. It also returns an error if the property is not in the
+ * font.
+ *
+ * A 'property' is a either key-value pair within the STARTPROPERTIES
+ * ... ENDPROPERTIES block of a BDF font or a key-value pair from the
+ * `info->props` array within a `FontRec` structure of a PCF font.
+ *
+ * Integer properties are always stored as 'signed' within PCF fonts;
+ * consequently, @BDF_PROPERTY_TYPE_CARDINAL is a possible return value
+ * for BDF fonts only.
+ *
+ * In case of error, `aproperty->type` is always set to
+ * @BDF_PROPERTY_TYPE_NONE.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_BDF_Property( FT_Face face,
+ const char* prop_name,
+ BDF_PropertyRec *aproperty );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* FTBDF_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftbitmap.h b/Client/ThirdParty/freetype/include/freetype/ftbitmap.h
new file mode 100644
index 0000000..11c45b0
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftbitmap.h
@@ -0,0 +1,329 @@
+/****************************************************************************
+ *
+ * ftbitmap.h
+ *
+ * FreeType utility functions for bitmaps (specification).
+ *
+ * Copyright (C) 2004-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTBITMAP_H_
+#define FTBITMAP_H_
+
+
+#include <freetype/freetype.h>
+#include <freetype/ftcolor.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * bitmap_handling
+ *
+ * @title:
+ * Bitmap Handling
+ *
+ * @abstract:
+ * Handling FT_Bitmap objects.
+ *
+ * @description:
+ * This section contains functions for handling @FT_Bitmap objects,
+ * automatically adjusting the target's bitmap buffer size as needed.
+ *
+ * Note that none of the functions changes the bitmap's 'flow' (as
+ * indicated by the sign of the `pitch` field in @FT_Bitmap).
+ *
+ * To set the flow, assign an appropriate positive or negative value to
+ * the `pitch` field of the target @FT_Bitmap object after calling
+ * @FT_Bitmap_Init but before calling any of the other functions
+ * described here.
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Init
+ *
+ * @description:
+ * Initialize a pointer to an @FT_Bitmap structure.
+ *
+ * @inout:
+ * abitmap ::
+ * A pointer to the bitmap structure.
+ *
+ * @note:
+ * A deprecated name for the same function is `FT_Bitmap_New`.
+ */
+ FT_EXPORT( void )
+ FT_Bitmap_Init( FT_Bitmap *abitmap );
+
+
+ /* deprecated */
+ FT_EXPORT( void )
+ FT_Bitmap_New( FT_Bitmap *abitmap );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Copy
+ *
+ * @description:
+ * Copy a bitmap into another one.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * source ::
+ * A handle to the source bitmap.
+ *
+ * @output:
+ * target ::
+ * A handle to the target bitmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * `source->buffer` and `target->buffer` must neither be equal nor
+ * overlap.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Copy( FT_Library library,
+ const FT_Bitmap *source,
+ FT_Bitmap *target );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Embolden
+ *
+ * @description:
+ * Embolden a bitmap. The new bitmap will be about `xStrength` pixels
+ * wider and `yStrength` pixels higher. The left and bottom borders are
+ * kept unchanged.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * xStrength ::
+ * How strong the glyph is emboldened horizontally. Expressed in 26.6
+ * pixel format.
+ *
+ * yStrength ::
+ * How strong the glyph is emboldened vertically. Expressed in 26.6
+ * pixel format.
+ *
+ * @inout:
+ * bitmap ::
+ * A handle to the target bitmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The current implementation restricts `xStrength` to be less than or
+ * equal to~8 if bitmap is of pixel_mode @FT_PIXEL_MODE_MONO.
+ *
+ * If you want to embolden the bitmap owned by a @FT_GlyphSlotRec, you
+ * should call @FT_GlyphSlot_Own_Bitmap on the slot first.
+ *
+ * Bitmaps in @FT_PIXEL_MODE_GRAY2 and @FT_PIXEL_MODE_GRAY@ format are
+ * converted to @FT_PIXEL_MODE_GRAY format (i.e., 8bpp).
+ */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Embolden( FT_Library library,
+ FT_Bitmap* bitmap,
+ FT_Pos xStrength,
+ FT_Pos yStrength );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Convert
+ *
+ * @description:
+ * Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp to
+ * a bitmap object with depth 8bpp, making the number of used bytes per
+ * line (a.k.a. the 'pitch') a multiple of `alignment`.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * source ::
+ * The source bitmap.
+ *
+ * alignment ::
+ * The pitch of the bitmap is a multiple of this argument. Common
+ * values are 1, 2, or 4.
+ *
+ * @output:
+ * target ::
+ * The target bitmap.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * It is possible to call @FT_Bitmap_Convert multiple times without
+ * calling @FT_Bitmap_Done (the memory is simply reallocated).
+ *
+ * Use @FT_Bitmap_Done to finally remove the bitmap object.
+ *
+ * The `library` argument is taken to have access to FreeType's memory
+ * handling functions.
+ *
+ * `source->buffer` and `target->buffer` must neither be equal nor
+ * overlap.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Convert( FT_Library library,
+ const FT_Bitmap *source,
+ FT_Bitmap *target,
+ FT_Int alignment );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Blend
+ *
+ * @description:
+ * Blend a bitmap onto another bitmap, using a given color.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * source ::
+ * The source bitmap, which can have any @FT_Pixel_Mode format.
+ *
+ * source_offset ::
+ * The offset vector to the upper left corner of the source bitmap in
+ * 26.6 pixel format. It should represent an integer offset; the
+ * function will set the lowest six bits to zero to enforce that.
+ *
+ * color ::
+ * The color used to draw `source` onto `target`.
+ *
+ * @inout:
+ * target ::
+ * A handle to an `FT_Bitmap` object. It should be either initialized
+ * as empty with a call to @FT_Bitmap_Init, or it should be of type
+ * @FT_PIXEL_MODE_BGRA.
+ *
+ * atarget_offset ::
+ * The offset vector to the upper left corner of the target bitmap in
+ * 26.6 pixel format. It should represent an integer offset; the
+ * function will set the lowest six bits to zero to enforce that.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function doesn't perform clipping.
+ *
+ * The bitmap in `target` gets allocated or reallocated as needed; the
+ * vector `atarget_offset` is updated accordingly.
+ *
+ * In case of allocation or reallocation, the bitmap's pitch is set to
+ * `4 * width`. Both `source` and `target` must have the same bitmap
+ * flow (as indicated by the sign of the `pitch` field).
+ *
+ * `source->buffer` and `target->buffer` must neither be equal nor
+ * overlap.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Blend( FT_Library library,
+ const FT_Bitmap* source,
+ const FT_Vector source_offset,
+ FT_Bitmap* target,
+ FT_Vector *atarget_offset,
+ FT_Color color );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GlyphSlot_Own_Bitmap
+ *
+ * @description:
+ * Make sure that a glyph slot owns `slot->bitmap`.
+ *
+ * @input:
+ * slot ::
+ * The glyph slot.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function is to be used in combination with @FT_Bitmap_Embolden.
+ */
+ FT_EXPORT( FT_Error )
+ FT_GlyphSlot_Own_Bitmap( FT_GlyphSlot slot );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Bitmap_Done
+ *
+ * @description:
+ * Destroy a bitmap object initialized with @FT_Bitmap_Init.
+ *
+ * @input:
+ * library ::
+ * A handle to a library object.
+ *
+ * bitmap ::
+ * The bitmap object to be freed.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The `library` argument is taken to have access to FreeType's memory
+ * handling functions.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Bitmap_Done( FT_Library library,
+ FT_Bitmap *bitmap );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTBITMAP_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftbzip2.h b/Client/ThirdParty/freetype/include/freetype/ftbzip2.h
new file mode 100644
index 0000000..afd2a82
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftbzip2.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+ *
+ * ftbzip2.h
+ *
+ * Bzip2-compressed stream support.
+ *
+ * Copyright (C) 2010-2021 by
+ * Joel Klinghed.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTBZIP2_H_
+#define FTBZIP2_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @section:
+ * bzip2
+ *
+ * @title:
+ * BZIP2 Streams
+ *
+ * @abstract:
+ * Using bzip2-compressed font files.
+ *
+ * @description:
+ * In certain builds of the library, bzip2 compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a bzip2 compressed
+ * stream from it and re-open the face with it.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream,
+ * which significantly undermines the performance.
+ *
+ * This section contains the declaration of Bzip2-specific functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenBzip2
+ *
+ * @description:
+ * Open a new stream to parse bzip2-compressed font files. This is
+ * mainly used to support the compressed `*.pcf.bz2` fonts that come with
+ * XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close` on the new stream will
+ * **not** call `FT_Stream_Close` on the source stream. None of the
+ * stream objects will be released to the heap.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with bzip2 support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenBzip2( FT_Stream stream,
+ FT_Stream source );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTBZIP2_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftcache.h b/Client/ThirdParty/freetype/include/freetype/ftcache.h
new file mode 100644
index 0000000..70399a3
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftcache.h
@@ -0,0 +1,1087 @@
+/****************************************************************************
+ *
+ * ftcache.h
+ *
+ * FreeType Cache subsystem (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTCACHE_H_
+#define FTCACHE_H_
+
+
+#include <freetype/ftglyph.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * cache_subsystem
+ *
+ * @title:
+ * Cache Sub-System
+ *
+ * @abstract:
+ * How to cache face, size, and glyph data with FreeType~2.
+ *
+ * @description:
+ * This section describes the FreeType~2 cache sub-system, which is used
+ * to limit the number of concurrently opened @FT_Face and @FT_Size
+ * objects, as well as caching information like character maps and glyph
+ * images while limiting their maximum memory usage.
+ *
+ * Note that all types and functions begin with the `FTC_` prefix.
+ *
+ * The cache is highly portable and thus doesn't know anything about the
+ * fonts installed on your system, or how to access them. This implies
+ * the following scheme:
+ *
+ * First, available or installed font faces are uniquely identified by
+ * @FTC_FaceID values, provided to the cache by the client. Note that
+ * the cache only stores and compares these values, and doesn't try to
+ * interpret them in any way.
+ *
+ * Second, the cache calls, only when needed, a client-provided function
+ * to convert an @FTC_FaceID into a new @FT_Face object. The latter is
+ * then completely managed by the cache, including its termination
+ * through @FT_Done_Face. To monitor termination of face objects, the
+ * finalizer callback in the `generic` field of the @FT_Face object can
+ * be used, which might also be used to store the @FTC_FaceID of the
+ * face.
+ *
+ * Clients are free to map face IDs to anything else. The most simple
+ * usage is to associate them to a (pathname,face_index) pair that is
+ * used to call @FT_New_Face. However, more complex schemes are also
+ * possible.
+ *
+ * Note that for the cache to work correctly, the face ID values must be
+ * **persistent**, which means that the contents they point to should not
+ * change at runtime, or that their value should not become invalid.
+ *
+ * If this is unavoidable (e.g., when a font is uninstalled at runtime),
+ * you should call @FTC_Manager_RemoveFaceID as soon as possible, to let
+ * the cache get rid of any references to the old @FTC_FaceID it may keep
+ * internally. Failure to do so will lead to incorrect behaviour or even
+ * crashes.
+ *
+ * To use the cache, start with calling @FTC_Manager_New to create a new
+ * @FTC_Manager object, which models a single cache instance. You can
+ * then look up @FT_Face and @FT_Size objects with
+ * @FTC_Manager_LookupFace and @FTC_Manager_LookupSize, respectively.
+ *
+ * If you want to use the charmap caching, call @FTC_CMapCache_New, then
+ * later use @FTC_CMapCache_Lookup to perform the equivalent of
+ * @FT_Get_Char_Index, only much faster.
+ *
+ * If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New,
+ * then later use @FTC_ImageCache_Lookup to retrieve the corresponding
+ * @FT_Glyph objects from the cache.
+ *
+ * If you need lots of small bitmaps, it is much more memory efficient to
+ * call @FTC_SBitCache_New followed by @FTC_SBitCache_Lookup. This
+ * returns @FTC_SBitRec structures, which are used to store small bitmaps
+ * directly. (A small bitmap is one whose metrics and dimensions all fit
+ * into 8-bit integers).
+ *
+ * We hope to also provide a kerning cache in the near future.
+ *
+ *
+ * @order:
+ * FTC_Manager
+ * FTC_FaceID
+ * FTC_Face_Requester
+ *
+ * FTC_Manager_New
+ * FTC_Manager_Reset
+ * FTC_Manager_Done
+ * FTC_Manager_LookupFace
+ * FTC_Manager_LookupSize
+ * FTC_Manager_RemoveFaceID
+ *
+ * FTC_Node
+ * FTC_Node_Unref
+ *
+ * FTC_ImageCache
+ * FTC_ImageCache_New
+ * FTC_ImageCache_Lookup
+ *
+ * FTC_SBit
+ * FTC_SBitCache
+ * FTC_SBitCache_New
+ * FTC_SBitCache_Lookup
+ *
+ * FTC_CMapCache
+ * FTC_CMapCache_New
+ * FTC_CMapCache_Lookup
+ *
+ *************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** BASIC TYPE DEFINITIONS *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_FaceID
+ *
+ * @description:
+ * An opaque pointer type that is used to identity face objects. The
+ * contents of such objects is application-dependent.
+ *
+ * These pointers are typically used to point to a user-defined structure
+ * containing a font file path, and face index.
+ *
+ * @note:
+ * Never use `NULL` as a valid @FTC_FaceID.
+ *
+ * Face IDs are passed by the client to the cache manager that calls,
+ * when needed, the @FTC_Face_Requester to translate them into new
+ * @FT_Face objects.
+ *
+ * If the content of a given face ID changes at runtime, or if the value
+ * becomes invalid (e.g., when uninstalling a font), you should
+ * immediately call @FTC_Manager_RemoveFaceID before any other cache
+ * function.
+ *
+ * Failure to do so will result in incorrect behaviour or even memory
+ * leaks and crashes.
+ */
+ typedef FT_Pointer FTC_FaceID;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FTC_Face_Requester
+ *
+ * @description:
+ * A callback function provided by client applications. It is used by
+ * the cache manager to translate a given @FTC_FaceID into a new valid
+ * @FT_Face object, on demand.
+ *
+ * @input:
+ * face_id ::
+ * The face ID to resolve.
+ *
+ * library ::
+ * A handle to a FreeType library object.
+ *
+ * req_data ::
+ * Application-provided request data (see note below).
+ *
+ * @output:
+ * aface ::
+ * A new @FT_Face handle.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The third parameter `req_data` is the same as the one passed by the
+ * client when @FTC_Manager_New is called.
+ *
+ * The face requester should not perform funny things on the returned
+ * face object, like creating a new @FT_Size for it, or setting a
+ * transformation through @FT_Set_Transform!
+ */
+ typedef FT_Error
+ (*FTC_Face_Requester)( FTC_FaceID face_id,
+ FT_Library library,
+ FT_Pointer req_data,
+ FT_Face* aface );
+
+ /* */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** CACHE MANAGER OBJECT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_Manager
+ *
+ * @description:
+ * This object corresponds to one instance of the cache-subsystem. It is
+ * used to cache one or more @FT_Face objects, along with corresponding
+ * @FT_Size objects.
+ *
+ * The manager intentionally limits the total number of opened @FT_Face
+ * and @FT_Size objects to control memory usage. See the `max_faces` and
+ * `max_sizes` parameters of @FTC_Manager_New.
+ *
+ * The manager is also used to cache 'nodes' of various types while
+ * limiting their total memory usage.
+ *
+ * All limitations are enforced by keeping lists of managed objects in
+ * most-recently-used order, and flushing old nodes to make room for new
+ * ones.
+ */
+ typedef struct FTC_ManagerRec_* FTC_Manager;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_Node
+ *
+ * @description:
+ * An opaque handle to a cache node object. Each cache node is
+ * reference-counted. A node with a count of~0 might be flushed out of a
+ * full cache whenever a lookup request is performed.
+ *
+ * If you look up nodes, you have the ability to 'acquire' them, i.e., to
+ * increment their reference count. This will prevent the node from
+ * being flushed out of the cache until you explicitly 'release' it (see
+ * @FTC_Node_Unref).
+ *
+ * See also @FTC_SBitCache_Lookup and @FTC_ImageCache_Lookup.
+ */
+ typedef struct FTC_NodeRec_* FTC_Node;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_New
+ *
+ * @description:
+ * Create a new cache manager.
+ *
+ * @input:
+ * library ::
+ * The parent FreeType library handle to use.
+ *
+ * max_faces ::
+ * Maximum number of opened @FT_Face objects managed by this cache
+ * instance. Use~0 for defaults.
+ *
+ * max_sizes ::
+ * Maximum number of opened @FT_Size objects managed by this cache
+ * instance. Use~0 for defaults.
+ *
+ * max_bytes ::
+ * Maximum number of bytes to use for cached data nodes. Use~0 for
+ * defaults. Note that this value does not account for managed
+ * @FT_Face and @FT_Size objects.
+ *
+ * requester ::
+ * An application-provided callback used to translate face IDs into
+ * real @FT_Face objects.
+ *
+ * req_data ::
+ * A generic pointer that is passed to the requester each time it is
+ * called (see @FTC_Face_Requester).
+ *
+ * @output:
+ * amanager ::
+ * A handle to a new manager object. 0~in case of failure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FTC_Manager_New( FT_Library library,
+ FT_UInt max_faces,
+ FT_UInt max_sizes,
+ FT_ULong max_bytes,
+ FTC_Face_Requester requester,
+ FT_Pointer req_data,
+ FTC_Manager *amanager );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_Reset
+ *
+ * @description:
+ * Empty a given cache manager. This simply gets rid of all the
+ * currently cached @FT_Face and @FT_Size objects within the manager.
+ *
+ * @inout:
+ * manager ::
+ * A handle to the manager.
+ */
+ FT_EXPORT( void )
+ FTC_Manager_Reset( FTC_Manager manager );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_Done
+ *
+ * @description:
+ * Destroy a given manager after emptying it.
+ *
+ * @input:
+ * manager ::
+ * A handle to the target cache manager object.
+ */
+ FT_EXPORT( void )
+ FTC_Manager_Done( FTC_Manager manager );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_LookupFace
+ *
+ * @description:
+ * Retrieve the @FT_Face object that corresponds to a given face ID
+ * through a cache manager.
+ *
+ * @input:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * face_id ::
+ * The ID of the face object.
+ *
+ * @output:
+ * aface ::
+ * A handle to the face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned @FT_Face object is always owned by the manager. You
+ * should never try to discard it yourself.
+ *
+ * The @FT_Face object doesn't necessarily have a current size object
+ * (i.e., face->size can be~0). If you need a specific 'font size', use
+ * @FTC_Manager_LookupSize instead.
+ *
+ * Never change the face's transformation matrix (i.e., never call the
+ * @FT_Set_Transform function) on a returned face! If you need to
+ * transform glyphs, do it yourself after glyph loading.
+ *
+ * When you perform a lookup, out-of-memory errors are detected _within_
+ * the lookup and force incremental flushes of the cache until enough
+ * memory is released for the lookup to succeed.
+ *
+ * If a lookup fails with `FT_Err_Out_Of_Memory` the cache has already
+ * been completely flushed, and still no memory was available for the
+ * operation.
+ */
+ FT_EXPORT( FT_Error )
+ FTC_Manager_LookupFace( FTC_Manager manager,
+ FTC_FaceID face_id,
+ FT_Face *aface );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_ScalerRec
+ *
+ * @description:
+ * A structure used to describe a given character size in either pixels
+ * or points to the cache manager. See @FTC_Manager_LookupSize.
+ *
+ * @fields:
+ * face_id ::
+ * The source face ID.
+ *
+ * width ::
+ * The character width.
+ *
+ * height ::
+ * The character height.
+ *
+ * pixel ::
+ * A Boolean. If 1, the `width` and `height` fields are interpreted as
+ * integer pixel character sizes. Otherwise, they are expressed as
+ * 1/64th of points.
+ *
+ * x_res ::
+ * Only used when `pixel` is value~0 to indicate the horizontal
+ * resolution in dpi.
+ *
+ * y_res ::
+ * Only used when `pixel` is value~0 to indicate the vertical
+ * resolution in dpi.
+ *
+ * @note:
+ * This type is mainly used to retrieve @FT_Size objects through the
+ * cache manager.
+ */
+ typedef struct FTC_ScalerRec_
+ {
+ FTC_FaceID face_id;
+ FT_UInt width;
+ FT_UInt height;
+ FT_Int pixel;
+ FT_UInt x_res;
+ FT_UInt y_res;
+
+ } FTC_ScalerRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_Scaler
+ *
+ * @description:
+ * A handle to an @FTC_ScalerRec structure.
+ */
+ typedef struct FTC_ScalerRec_* FTC_Scaler;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_LookupSize
+ *
+ * @description:
+ * Retrieve the @FT_Size object that corresponds to a given
+ * @FTC_ScalerRec pointer through a cache manager.
+ *
+ * @input:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * scaler ::
+ * A scaler handle.
+ *
+ * @output:
+ * asize ::
+ * A handle to the size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned @FT_Size object is always owned by the manager. You
+ * should never try to discard it by yourself.
+ *
+ * You can access the parent @FT_Face object simply as `size->face` if
+ * you need it. Note that this object is also owned by the manager.
+ *
+ * @note:
+ * When you perform a lookup, out-of-memory errors are detected _within_
+ * the lookup and force incremental flushes of the cache until enough
+ * memory is released for the lookup to succeed.
+ *
+ * If a lookup fails with `FT_Err_Out_Of_Memory` the cache has already
+ * been completely flushed, and still no memory is available for the
+ * operation.
+ */
+ FT_EXPORT( FT_Error )
+ FTC_Manager_LookupSize( FTC_Manager manager,
+ FTC_Scaler scaler,
+ FT_Size *asize );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Node_Unref
+ *
+ * @description:
+ * Decrement a cache node's internal reference count. When the count
+ * reaches 0, it is not destroyed but becomes eligible for subsequent
+ * cache flushes.
+ *
+ * @input:
+ * node ::
+ * The cache node handle.
+ *
+ * manager ::
+ * The cache manager handle.
+ */
+ FT_EXPORT( void )
+ FTC_Node_Unref( FTC_Node node,
+ FTC_Manager manager );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_Manager_RemoveFaceID
+ *
+ * @description:
+ * A special function used to indicate to the cache manager that a given
+ * @FTC_FaceID is no longer valid, either because its content changed, or
+ * because it was deallocated or uninstalled.
+ *
+ * @input:
+ * manager ::
+ * The cache manager handle.
+ *
+ * face_id ::
+ * The @FTC_FaceID to be removed.
+ *
+ * @note:
+ * This function flushes all nodes from the cache corresponding to this
+ * `face_id`, with the exception of nodes with a non-null reference
+ * count.
+ *
+ * Such nodes are however modified internally so as to never appear in
+ * later lookups with the same `face_id` value, and to be immediately
+ * destroyed when released by all their users.
+ *
+ */
+ FT_EXPORT( void )
+ FTC_Manager_RemoveFaceID( FTC_Manager manager,
+ FTC_FaceID face_id );
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_CMapCache
+ *
+ * @description:
+ * An opaque handle used to model a charmap cache. This cache is to hold
+ * character codes -> glyph indices mappings.
+ *
+ */
+ typedef struct FTC_CMapCacheRec_* FTC_CMapCache;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_CMapCache_New
+ *
+ * @description:
+ * Create a new charmap cache.
+ *
+ * @input:
+ * manager ::
+ * A handle to the cache manager.
+ *
+ * @output:
+ * acache ::
+ * A new cache handle. `NULL` in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Like all other caches, this one will be destroyed with the cache
+ * manager.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FTC_CMapCache_New( FTC_Manager manager,
+ FTC_CMapCache *acache );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_CMapCache_Lookup
+ *
+ * @description:
+ * Translate a character code into a glyph index, using the charmap
+ * cache.
+ *
+ * @input:
+ * cache ::
+ * A charmap cache handle.
+ *
+ * face_id ::
+ * The source face ID.
+ *
+ * cmap_index ::
+ * The index of the charmap in the source face. Any negative value
+ * means to use the cache @FT_Face's default charmap.
+ *
+ * char_code ::
+ * The character code (in the corresponding charmap).
+ *
+ * @return:
+ * Glyph index. 0~means 'no glyph'.
+ *
+ */
+ FT_EXPORT( FT_UInt )
+ FTC_CMapCache_Lookup( FTC_CMapCache cache,
+ FTC_FaceID face_id,
+ FT_Int cmap_index,
+ FT_UInt32 char_code );
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** IMAGE CACHE OBJECT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_ImageTypeRec
+ *
+ * @description:
+ * A structure used to model the type of images in a glyph cache.
+ *
+ * @fields:
+ * face_id ::
+ * The face ID.
+ *
+ * width ::
+ * The width in pixels.
+ *
+ * height ::
+ * The height in pixels.
+ *
+ * flags ::
+ * The load flags, as in @FT_Load_Glyph.
+ *
+ */
+ typedef struct FTC_ImageTypeRec_
+ {
+ FTC_FaceID face_id;
+ FT_UInt width;
+ FT_UInt height;
+ FT_Int32 flags;
+
+ } FTC_ImageTypeRec;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_ImageType
+ *
+ * @description:
+ * A handle to an @FTC_ImageTypeRec structure.
+ *
+ */
+ typedef struct FTC_ImageTypeRec_* FTC_ImageType;
+
+
+ /* */
+
+
+#define FTC_IMAGE_TYPE_COMPARE( d1, d2 ) \
+ ( (d1)->face_id == (d2)->face_id && \
+ (d1)->width == (d2)->width && \
+ (d1)->flags == (d2)->flags )
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_ImageCache
+ *
+ * @description:
+ * A handle to a glyph image cache object. They are designed to hold
+ * many distinct glyph images while not exceeding a certain memory
+ * threshold.
+ */
+ typedef struct FTC_ImageCacheRec_* FTC_ImageCache;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_ImageCache_New
+ *
+ * @description:
+ * Create a new glyph image cache.
+ *
+ * @input:
+ * manager ::
+ * The parent manager for the image cache.
+ *
+ * @output:
+ * acache ::
+ * A handle to the new glyph image cache object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FTC_ImageCache_New( FTC_Manager manager,
+ FTC_ImageCache *acache );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_ImageCache_Lookup
+ *
+ * @description:
+ * Retrieve a given glyph image from a glyph image cache.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source glyph image cache.
+ *
+ * type ::
+ * A pointer to a glyph image type descriptor.
+ *
+ * gindex ::
+ * The glyph index to retrieve.
+ *
+ * @output:
+ * aglyph ::
+ * The corresponding @FT_Glyph object. 0~in case of failure.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned glyph is owned and managed by the glyph image cache.
+ * Never try to transform or discard it manually! You can however create
+ * a copy with @FT_Glyph_Copy and modify the new one.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the glyph image, after increasing its reference count.
+ * This ensures that the node (as well as the @FT_Glyph) will always be
+ * kept in the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the @FT_Glyph could be flushed out of the cache on the next call
+ * to one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ */
+ FT_EXPORT( FT_Error )
+ FTC_ImageCache_Lookup( FTC_ImageCache cache,
+ FTC_ImageType type,
+ FT_UInt gindex,
+ FT_Glyph *aglyph,
+ FTC_Node *anode );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_ImageCache_LookupScaler
+ *
+ * @description:
+ * A variant of @FTC_ImageCache_Lookup that uses an @FTC_ScalerRec to
+ * specify the face ID and its size.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source glyph image cache.
+ *
+ * scaler ::
+ * A pointer to a scaler descriptor.
+ *
+ * load_flags ::
+ * The corresponding load flags.
+ *
+ * gindex ::
+ * The glyph index to retrieve.
+ *
+ * @output:
+ * aglyph ::
+ * The corresponding @FT_Glyph object. 0~in case of failure.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned glyph is owned and managed by the glyph image cache.
+ * Never try to transform or discard it manually! You can however create
+ * a copy with @FT_Glyph_Copy and modify the new one.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the glyph image, after increasing its reference count.
+ * This ensures that the node (as well as the @FT_Glyph) will always be
+ * kept in the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the @FT_Glyph could be flushed out of the cache on the next call
+ * to one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ *
+ * Calls to @FT_Set_Char_Size and friends have no effect on cached
+ * glyphs; you should always use the FreeType cache API instead.
+ */
+ FT_EXPORT( FT_Error )
+ FTC_ImageCache_LookupScaler( FTC_ImageCache cache,
+ FTC_Scaler scaler,
+ FT_ULong load_flags,
+ FT_UInt gindex,
+ FT_Glyph *aglyph,
+ FTC_Node *anode );
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_SBit
+ *
+ * @description:
+ * A handle to a small bitmap descriptor. See the @FTC_SBitRec structure
+ * for details.
+ */
+ typedef struct FTC_SBitRec_* FTC_SBit;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FTC_SBitRec
+ *
+ * @description:
+ * A very compact structure used to describe a small glyph bitmap.
+ *
+ * @fields:
+ * width ::
+ * The bitmap width in pixels.
+ *
+ * height ::
+ * The bitmap height in pixels.
+ *
+ * left ::
+ * The horizontal distance from the pen position to the left bitmap
+ * border (a.k.a. 'left side bearing', or 'lsb').
+ *
+ * top ::
+ * The vertical distance from the pen position (on the baseline) to the
+ * upper bitmap border (a.k.a. 'top side bearing'). The distance is
+ * positive for upwards y~coordinates.
+ *
+ * format ::
+ * The format of the glyph bitmap (monochrome or gray).
+ *
+ * max_grays ::
+ * Maximum gray level value (in the range 1 to~255).
+ *
+ * pitch ::
+ * The number of bytes per bitmap line. May be positive or negative.
+ *
+ * xadvance ::
+ * The horizontal advance width in pixels.
+ *
+ * yadvance ::
+ * The vertical advance height in pixels.
+ *
+ * buffer ::
+ * A pointer to the bitmap pixels.
+ */
+ typedef struct FTC_SBitRec_
+ {
+ FT_Byte width;
+ FT_Byte height;
+ FT_Char left;
+ FT_Char top;
+
+ FT_Byte format;
+ FT_Byte max_grays;
+ FT_Short pitch;
+ FT_Char xadvance;
+ FT_Char yadvance;
+
+ FT_Byte* buffer;
+
+ } FTC_SBitRec;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FTC_SBitCache
+ *
+ * @description:
+ * A handle to a small bitmap cache. These are special cache objects
+ * used to store small glyph bitmaps (and anti-aliased pixmaps) in a much
+ * more efficient way than the traditional glyph image cache implemented
+ * by @FTC_ImageCache.
+ */
+ typedef struct FTC_SBitCacheRec_* FTC_SBitCache;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_SBitCache_New
+ *
+ * @description:
+ * Create a new cache to store small glyph bitmaps.
+ *
+ * @input:
+ * manager ::
+ * A handle to the source cache manager.
+ *
+ * @output:
+ * acache ::
+ * A handle to the new sbit cache. `NULL` in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FTC_SBitCache_New( FTC_Manager manager,
+ FTC_SBitCache *acache );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_SBitCache_Lookup
+ *
+ * @description:
+ * Look up a given small glyph bitmap in a given sbit cache and 'lock' it
+ * to prevent its flushing from the cache until needed.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source sbit cache.
+ *
+ * type ::
+ * A pointer to the glyph image type descriptor.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * sbit ::
+ * A handle to a small bitmap descriptor.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The small bitmap descriptor and its bit buffer are owned by the cache
+ * and should never be freed by the application. They might as well
+ * disappear from memory on the next cache lookup, so don't treat them as
+ * persistent data.
+ *
+ * The descriptor's `buffer` field is set to~0 to indicate a missing
+ * glyph bitmap.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the bitmap, after increasing its reference count. This
+ * ensures that the node (as well as the image) will always be kept in
+ * the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the bitmap could be flushed out of the cache on the next call to
+ * one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ */
+ FT_EXPORT( FT_Error )
+ FTC_SBitCache_Lookup( FTC_SBitCache cache,
+ FTC_ImageType type,
+ FT_UInt gindex,
+ FTC_SBit *sbit,
+ FTC_Node *anode );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FTC_SBitCache_LookupScaler
+ *
+ * @description:
+ * A variant of @FTC_SBitCache_Lookup that uses an @FTC_ScalerRec to
+ * specify the face ID and its size.
+ *
+ * @input:
+ * cache ::
+ * A handle to the source sbit cache.
+ *
+ * scaler ::
+ * A pointer to the scaler descriptor.
+ *
+ * load_flags ::
+ * The corresponding load flags.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * sbit ::
+ * A handle to a small bitmap descriptor.
+ *
+ * anode ::
+ * Used to return the address of the corresponding cache node after
+ * incrementing its reference count (see note below).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The small bitmap descriptor and its bit buffer are owned by the cache
+ * and should never be freed by the application. They might as well
+ * disappear from memory on the next cache lookup, so don't treat them as
+ * persistent data.
+ *
+ * The descriptor's `buffer` field is set to~0 to indicate a missing
+ * glyph bitmap.
+ *
+ * If `anode` is _not_ `NULL`, it receives the address of the cache node
+ * containing the bitmap, after increasing its reference count. This
+ * ensures that the node (as well as the image) will always be kept in
+ * the cache until you call @FTC_Node_Unref to 'release' it.
+ *
+ * If `anode` is `NULL`, the cache node is left unchanged, which means
+ * that the bitmap could be flushed out of the cache on the next call to
+ * one of the caching sub-system APIs. Don't assume that it is
+ * persistent!
+ */
+ FT_EXPORT( FT_Error )
+ FTC_SBitCache_LookupScaler( FTC_SBitCache cache,
+ FTC_Scaler scaler,
+ FT_ULong load_flags,
+ FT_UInt gindex,
+ FTC_SBit *sbit,
+ FTC_Node *anode );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTCACHE_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftchapters.h b/Client/ThirdParty/freetype/include/freetype/ftchapters.h
new file mode 100644
index 0000000..4f32cc8
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftchapters.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+ *
+ * This file defines the structure of the FreeType reference.
+ * It is used by the python script that generates the HTML files.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * general_remarks
+ *
+ * @title:
+ * General Remarks
+ *
+ * @sections:
+ * preamble
+ * header_inclusion
+ * user_allocation
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * core_api
+ *
+ * @title:
+ * Core API
+ *
+ * @sections:
+ * version
+ * basic_types
+ * base_interface
+ * glyph_variants
+ * color_management
+ * layer_management
+ * glyph_management
+ * mac_specific
+ * sizes_management
+ * header_file_macros
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * format_specific
+ *
+ * @title:
+ * Format-Specific API
+ *
+ * @sections:
+ * multiple_masters
+ * truetype_tables
+ * type1_tables
+ * sfnt_names
+ * bdf_fonts
+ * cid_fonts
+ * pfr_fonts
+ * winfnt_fonts
+ * font_formats
+ * gasp_table
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * module_specific
+ *
+ * @title:
+ * Controlling FreeType Modules
+ *
+ * @sections:
+ * auto_hinter
+ * cff_driver
+ * t1_cid_driver
+ * tt_driver
+ * pcf_driver
+ * properties
+ * parameter_tags
+ * lcd_rendering
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * cache_subsystem
+ *
+ * @title:
+ * Cache Sub-System
+ *
+ * @sections:
+ * cache_subsystem
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * support_api
+ *
+ * @title:
+ * Support API
+ *
+ * @sections:
+ * computations
+ * list_processing
+ * outline_processing
+ * quick_advance
+ * bitmap_handling
+ * raster
+ * glyph_stroker
+ * system_interface
+ * module_management
+ * gzip
+ * lzw
+ * bzip2
+ * debugging_apis
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @chapter:
+ * error_codes
+ *
+ * @title:
+ * Error Codes
+ *
+ * @sections:
+ * error_enumerations
+ * error_code_values
+ *
+ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftcid.h b/Client/ThirdParty/freetype/include/freetype/ftcid.h
new file mode 100644
index 0000000..9a415bd
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftcid.h
@@ -0,0 +1,167 @@
+/****************************************************************************
+ *
+ * ftcid.h
+ *
+ * FreeType API for accessing CID font information (specification).
+ *
+ * Copyright (C) 2007-2021 by
+ * Dereg Clegg and Michael Toftdal.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTCID_H_
+#define FTCID_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * cid_fonts
+ *
+ * @title:
+ * CID Fonts
+ *
+ * @abstract:
+ * CID-keyed font-specific API.
+ *
+ * @description:
+ * This section contains the declaration of CID-keyed font-specific
+ * functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CID_Registry_Ordering_Supplement
+ *
+ * @description:
+ * Retrieve the Registry/Ordering/Supplement triple (also known as the
+ * "R/O/S") from a CID-keyed font.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * @output:
+ * registry ::
+ * The registry, as a C~string, owned by the face.
+ *
+ * ordering ::
+ * The ordering, as a C~string, owned by the face.
+ *
+ * supplement ::
+ * The supplement.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with CID faces, returning an error
+ * otherwise.
+ *
+ * @since:
+ * 2.3.6
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_CID_Registry_Ordering_Supplement( FT_Face face,
+ const char* *registry,
+ const char* *ordering,
+ FT_Int *supplement );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CID_Is_Internally_CID_Keyed
+ *
+ * @description:
+ * Retrieve the type of the input face, CID keyed or not. In contrast
+ * to the @FT_IS_CID_KEYED macro this function returns successfully also
+ * for CID-keyed fonts in an SFNT wrapper.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * @output:
+ * is_cid ::
+ * The type of the face as an @FT_Bool.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with CID faces and OpenType fonts, returning
+ * an error otherwise.
+ *
+ * @since:
+ * 2.3.9
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_CID_Is_Internally_CID_Keyed( FT_Face face,
+ FT_Bool *is_cid );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CID_From_Glyph_Index
+ *
+ * @description:
+ * Retrieve the CID of the input glyph index.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * glyph_index ::
+ * The input glyph index.
+ *
+ * @output:
+ * cid ::
+ * The CID as an @FT_UInt.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with CID faces and OpenType fonts, returning
+ * an error otherwise.
+ *
+ * @since:
+ * 2.3.9
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_CID_From_Glyph_Index( FT_Face face,
+ FT_UInt glyph_index,
+ FT_UInt *cid );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTCID_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftcolor.h b/Client/ThirdParty/freetype/include/freetype/ftcolor.h
new file mode 100644
index 0000000..59e6f15
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftcolor.h
@@ -0,0 +1,1609 @@
+/****************************************************************************
+ *
+ * ftcolor.h
+ *
+ * FreeType's glyph color management (specification).
+ *
+ * Copyright (C) 2018-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTCOLOR_H_
+#define FTCOLOR_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * color_management
+ *
+ * @title:
+ * Glyph Color Management
+ *
+ * @abstract:
+ * Retrieving and manipulating OpenType's 'CPAL' table data.
+ *
+ * @description:
+ * The functions described here allow access and manipulation of color
+ * palette entries in OpenType's 'CPAL' tables.
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Color
+ *
+ * @description:
+ * This structure models a BGRA color value of a 'CPAL' palette entry.
+ *
+ * The used color space is sRGB; the colors are not pre-multiplied, and
+ * alpha values must be explicitly set.
+ *
+ * @fields:
+ * blue ::
+ * Blue value.
+ *
+ * green ::
+ * Green value.
+ *
+ * red ::
+ * Red value.
+ *
+ * alpha ::
+ * Alpha value, giving the red, green, and blue color's opacity.
+ *
+ * @since:
+ * 2.10
+ */
+ typedef struct FT_Color_
+ {
+ FT_Byte blue;
+ FT_Byte green;
+ FT_Byte red;
+ FT_Byte alpha;
+
+ } FT_Color;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PALETTE_XXX
+ *
+ * @description:
+ * A list of bit field constants used in the `palette_flags` array of the
+ * @FT_Palette_Data structure to indicate for which background a palette
+ * with a given index is usable.
+ *
+ * @values:
+ * FT_PALETTE_FOR_LIGHT_BACKGROUND ::
+ * The palette is appropriate to use when displaying the font on a
+ * light background such as white.
+ *
+ * FT_PALETTE_FOR_DARK_BACKGROUND ::
+ * The palette is appropriate to use when displaying the font on a dark
+ * background such as black.
+ *
+ * @since:
+ * 2.10
+ */
+#define FT_PALETTE_FOR_LIGHT_BACKGROUND 0x01
+#define FT_PALETTE_FOR_DARK_BACKGROUND 0x02
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Palette_Data
+ *
+ * @description:
+ * This structure holds the data of the 'CPAL' table.
+ *
+ * @fields:
+ * num_palettes ::
+ * The number of palettes.
+ *
+ * palette_name_ids ::
+ * An optional read-only array of palette name IDs with `num_palettes`
+ * elements, corresponding to entries like 'dark' or 'light' in the
+ * font's 'name' table.
+ *
+ * An empty name ID in the 'CPAL' table gets represented as value
+ * 0xFFFF.
+ *
+ * `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
+ *
+ * palette_flags ::
+ * An optional read-only array of palette flags with `num_palettes`
+ * elements. Possible values are an ORed combination of
+ * @FT_PALETTE_FOR_LIGHT_BACKGROUND and
+ * @FT_PALETTE_FOR_DARK_BACKGROUND.
+ *
+ * `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
+ *
+ * num_palette_entries ::
+ * The number of entries in a single palette. All palettes have the
+ * same size.
+ *
+ * palette_entry_name_ids ::
+ * An optional read-only array of palette entry name IDs with
+ * `num_palette_entries`. In each palette, entries with the same index
+ * have the same function. For example, index~0 might correspond to
+ * string 'outline' in the font's 'name' table to indicate that this
+ * palette entry is used for outlines, index~1 might correspond to
+ * 'fill' to indicate the filling color palette entry, etc.
+ *
+ * An empty entry name ID in the 'CPAL' table gets represented as value
+ * 0xFFFF.
+ *
+ * `NULL` if the font's 'CPAL' table doesn't contain appropriate data.
+ *
+ * @note:
+ * Use function @FT_Get_Sfnt_Name to map name IDs and entry name IDs to
+ * name strings.
+ *
+ * Use function @FT_Palette_Select to get the colors associated with a
+ * palette entry.
+ *
+ * @since:
+ * 2.10
+ */
+ typedef struct FT_Palette_Data_ {
+ FT_UShort num_palettes;
+ const FT_UShort* palette_name_ids;
+ const FT_UShort* palette_flags;
+
+ FT_UShort num_palette_entries;
+ const FT_UShort* palette_entry_name_ids;
+
+ } FT_Palette_Data;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Data_Get
+ *
+ * @description:
+ * Retrieve the face's color palette data.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * @output:
+ * apalette ::
+ * A pointer to an @FT_Palette_Data structure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * All arrays in the returned @FT_Palette_Data structure are read-only.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Data_Get( FT_Face face,
+ FT_Palette_Data *apalette );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Select
+ *
+ * @description:
+ * This function has two purposes.
+ *
+ * (1) It activates a palette for rendering color glyphs, and
+ *
+ * (2) it retrieves all (unmodified) color entries of this palette. This
+ * function returns a read-write array, which means that a calling
+ * application can modify the palette entries on demand.
+ *
+ * A corollary of (2) is that calling the function, then modifying some
+ * values, then calling the function again with the same arguments resets
+ * all color entries to the original 'CPAL' values; all user modifications
+ * are lost.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * palette_index ::
+ * The palette index.
+ *
+ * @output:
+ * apalette ::
+ * An array of color entries for a palette with index `palette_index`,
+ * having `num_palette_entries` elements (as found in the
+ * `FT_Palette_Data` structure). If `apalette` is set to `NULL`, no
+ * array gets returned (and no color entries can be modified).
+ *
+ * In case the font doesn't support color palettes, `NULL` is returned.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The array pointed to by `apalette_entries` is owned and managed by
+ * FreeType.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Select( FT_Face face,
+ FT_UShort palette_index,
+ FT_Color* *apalette );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Set_Foreground_Color
+ *
+ * @description:
+ * 'COLR' uses palette index 0xFFFF to indicate a 'text foreground
+ * color'. This function sets this value.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * foreground_color ::
+ * An `FT_Color` structure to define the text foreground color.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If this function isn't called, the text foreground color is set to
+ * white opaque (BGRA value 0xFFFFFFFF) if
+ * @FT_PALETTE_FOR_DARK_BACKGROUND is present for the current palette,
+ * and black opaque (BGRA value 0x000000FF) otherwise, including the case
+ * that no palette types are available in the 'CPAL' table.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Set_Foreground_Color( FT_Face face,
+ FT_Color foreground_color );
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * layer_management
+ *
+ * @title:
+ * Glyph Layer Management
+ *
+ * @abstract:
+ * Retrieving and manipulating OpenType's 'COLR' table data.
+ *
+ * @description:
+ * The functions described here allow access of colored glyph layer data
+ * in OpenType's 'COLR' tables.
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_LayerIterator
+ *
+ * @description:
+ * This iterator object is needed for @FT_Get_Color_Glyph_Layer.
+ *
+ * @fields:
+ * num_layers ::
+ * The number of glyph layers for the requested glyph index. Will be
+ * set by @FT_Get_Color_Glyph_Layer.
+ *
+ * layer ::
+ * The current layer. Will be set by @FT_Get_Color_Glyph_Layer.
+ *
+ * p ::
+ * An opaque pointer into 'COLR' table data. The caller must set this
+ * to `NULL` before the first call of @FT_Get_Color_Glyph_Layer.
+ */
+ typedef struct FT_LayerIterator_
+ {
+ FT_UInt num_layers;
+ FT_UInt layer;
+ FT_Byte* p;
+
+ } FT_LayerIterator;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Color_Glyph_Layer
+ *
+ * @description:
+ * This is an interface to the 'COLR' table in OpenType fonts to
+ * iteratively retrieve the colored glyph layers associated with the
+ * current glyph slot.
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/colr
+ *
+ * The glyph layer data for a given glyph index, if present, provides an
+ * alternative, multi-color glyph representation: Instead of rendering
+ * the outline or bitmap with the given glyph index, glyphs with the
+ * indices and colors returned by this function are rendered layer by
+ * layer.
+ *
+ * The returned elements are ordered in the z~direction from bottom to
+ * top; the 'n'th element should be rendered with the associated palette
+ * color and blended on top of the already rendered layers (elements 0,
+ * 1, ..., n-1).
+ *
+ * @input:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * base_glyph ::
+ * The glyph index the colored glyph layers are associated with.
+ *
+ * @inout:
+ * iterator ::
+ * An @FT_LayerIterator object. For the first call you should set
+ * `iterator->p` to `NULL`. For all following calls, simply use the
+ * same object again.
+ *
+ * @output:
+ * aglyph_index ::
+ * The glyph index of the current layer.
+ *
+ * acolor_index ::
+ * The color index into the font face's color palette of the current
+ * layer. The value 0xFFFF is special; it doesn't reference a palette
+ * entry but indicates that the text foreground color should be used
+ * instead (to be set up by the application outside of FreeType).
+ *
+ * The color palette can be retrieved with @FT_Palette_Select.
+ *
+ * @return:
+ * Value~1 if everything is OK. If there are no more layers (or if there
+ * are no layers at all), value~0 gets returned. In case of an error,
+ * value~0 is returned also.
+ *
+ * @note:
+ * This function is necessary if you want to handle glyph layers by
+ * yourself. In particular, functions that operate with @FT_GlyphRec
+ * objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access
+ * to this information.
+ *
+ * Note that @FT_Render_Glyph is able to handle colored glyph layers
+ * automatically if the @FT_LOAD_COLOR flag is passed to a previous call
+ * to @FT_Load_Glyph. [This is an experimental feature.]
+ *
+ * @example:
+ * ```
+ * FT_Color* palette;
+ * FT_LayerIterator iterator;
+ *
+ * FT_Bool have_layers;
+ * FT_UInt layer_glyph_index;
+ * FT_UInt layer_color_index;
+ *
+ *
+ * error = FT_Palette_Select( face, palette_index, &palette );
+ * if ( error )
+ * palette = NULL;
+ *
+ * iterator.p = NULL;
+ * have_layers = FT_Get_Color_Glyph_Layer( face,
+ * glyph_index,
+ * &layer_glyph_index,
+ * &layer_color_index,
+ * &iterator );
+ *
+ * if ( palette && have_layers )
+ * {
+ * do
+ * {
+ * FT_Color layer_color;
+ *
+ *
+ * if ( layer_color_index == 0xFFFF )
+ * layer_color = text_foreground_color;
+ * else
+ * layer_color = palette[layer_color_index];
+ *
+ * // Load and render glyph `layer_glyph_index', then
+ * // blend resulting pixmap (using color `layer_color')
+ * // with previously created pixmaps.
+ *
+ * } while ( FT_Get_Color_Glyph_Layer( face,
+ * glyph_index,
+ * &layer_glyph_index,
+ * &layer_color_index,
+ * &iterator ) );
+ * }
+ * ```
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Get_Color_Glyph_Layer( FT_Face face,
+ FT_UInt base_glyph,
+ FT_UInt *aglyph_index,
+ FT_UInt *acolor_index,
+ FT_LayerIterator* iterator );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PaintFormat
+ *
+ * @description:
+ * Enumeration describing the different paint format types of the v1
+ * extensions to the 'COLR' table, see
+ * 'https://github.com/googlefonts/colr-gradients-spec'.
+ *
+ * The enumeration values losely correspond with the format numbers of
+ * the specification: FreeType always returns a fully specified 'Paint'
+ * structure for the 'Transform', 'Translate', 'Scale', 'Rotate', and
+ * 'Skew' table types even though the specification has different formats
+ * depending on whether or not a center is specified, whether the scale
+ * is uniform in x and y~direction or not, etc. Also, only non-variable
+ * format identifiers are listed in this enumeration; as soon as support
+ * for variable 'COLR' v1 fonts is implemented, interpolation is
+ * performed dependent on axis coordinates, which are configured on the
+ * @FT_Face through @FT_Set_Var_Design_Coordinates. This implies that
+ * always static, readily interpolated values are returned in the 'Paint'
+ * structures.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef enum FT_PaintFormat_
+ {
+ FT_COLR_PAINTFORMAT_COLR_LAYERS = 1,
+ FT_COLR_PAINTFORMAT_SOLID = 2,
+ FT_COLR_PAINTFORMAT_LINEAR_GRADIENT = 4,
+ FT_COLR_PAINTFORMAT_RADIAL_GRADIENT = 6,
+ FT_COLR_PAINTFORMAT_SWEEP_GRADIENT = 8,
+ FT_COLR_PAINTFORMAT_GLYPH = 10,
+ FT_COLR_PAINTFORMAT_COLR_GLYPH = 11,
+ FT_COLR_PAINTFORMAT_TRANSFORM = 12,
+ FT_COLR_PAINTFORMAT_TRANSLATE = 14,
+ FT_COLR_PAINTFORMAT_SCALE = 16,
+ FT_COLR_PAINTFORMAT_ROTATE = 24,
+ FT_COLR_PAINTFORMAT_SKEW = 28,
+ FT_COLR_PAINTFORMAT_COMPOSITE = 32,
+ FT_COLR_PAINT_FORMAT_MAX = 33,
+ FT_COLR_PAINTFORMAT_UNSUPPORTED = 255
+
+ } FT_PaintFormat;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ColorStopIterator
+ *
+ * @description:
+ * This iterator object is needed for @FT_Get_Colorline_Stops. It keeps
+ * state while iterating over the stops of an @FT_ColorLine,
+ * representing the `ColorLine` struct of the v1 extensions to 'COLR',
+ * see 'https://github.com/googlefonts/colr-gradients-spec'.
+ *
+ * @fields:
+ * num_color_stops ::
+ * The number of color stops for the requested glyph index. Set by
+ * @FT_Get_Colorline_Stops.
+ *
+ * current_color_stop ::
+ * The current color stop. Set by @FT_Get_Colorline_Stops.
+ *
+ * p ::
+ * An opaque pointer into 'COLR' table data. The caller must set this
+ * to `NULL` before the first call of @FT_Get_Colorline_Stops.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_ColorStopIterator_
+ {
+ FT_UInt num_color_stops;
+ FT_UInt current_color_stop;
+
+ FT_Byte* p;
+
+ } FT_ColorStopIterator;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ColorIndex
+ *
+ * @description:
+ * A structure representing a `ColorIndex` value of the 'COLR' v1
+ * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+ *
+ * @fields:
+ * palette_index ::
+ * The palette index into a 'CPAL' palette.
+ *
+ * alpha ::
+ * Alpha transparency value multiplied with the value from 'CPAL'.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_ColorIndex_
+ {
+ FT_UInt16 palette_index;
+ FT_F2Dot14 alpha;
+
+ } FT_ColorIndex;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ColorStop
+ *
+ * @description:
+ * A structure representing a `ColorStop` value of the 'COLR' v1
+ * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+ *
+ * @fields:
+ * stop_offset ::
+ * The stop offset between 0 and 1 along the gradient.
+ *
+ * color ::
+ * The color information for this stop, see @FT_ColorIndex.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_ColorStop_
+ {
+ FT_F2Dot14 stop_offset;
+ FT_ColorIndex color;
+
+ } FT_ColorStop;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PaintExtend
+ *
+ * @description:
+ * An enumeration representing the 'Extend' mode of the 'COLR' v1
+ * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+ * It describes how the gradient fill continues at the other boundaries.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef enum FT_PaintExtend_
+ {
+ FT_COLR_PAINT_EXTEND_PAD = 0,
+ FT_COLR_PAINT_EXTEND_REPEAT = 1,
+ FT_COLR_PAINT_EXTEND_REFLECT = 2
+
+ } FT_PaintExtend;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ColorLine
+ *
+ * @description:
+ * A structure representing a `ColorLine` value of the 'COLR' v1
+ * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+ * It describes a list of color stops along the defined gradient.
+ *
+ * @fields:
+ * extend ::
+ * The extend mode at the outer boundaries, see @FT_PaintExtend.
+ *
+ * color_stop_iterator ::
+ * The @FT_ColorStopIterator used to enumerate and retrieve the
+ * actual @FT_ColorStop's.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_ColorLine_
+ {
+ FT_PaintExtend extend;
+ FT_ColorStopIterator color_stop_iterator;
+
+ } FT_ColorLine;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Affine23
+ *
+ * @description:
+ * A structure used to store a 2x3 matrix. Coefficients are in
+ * 16.16 fixed-point format. The computation performed is
+ *
+ * ```
+ * x' = x*xx + y*xy + dx
+ * y' = x*yx + y*yy + dy
+ * ```
+ *
+ * @fields:
+ * xx ::
+ * Matrix coefficient.
+ *
+ * xy ::
+ * Matrix coefficient.
+ *
+ * dx ::
+ * x translation.
+ *
+ * yx ::
+ * Matrix coefficient.
+ *
+ * yy ::
+ * Matrix coefficient.
+ *
+ * dy ::
+ * y translation.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_Affine_23_
+ {
+ FT_Fixed xx, xy, dx;
+ FT_Fixed yx, yy, dy;
+
+ } FT_Affine23;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Composite_Mode
+ *
+ * @description:
+ * An enumeration listing the 'COLR' v1 composite modes used in
+ * @FT_PaintComposite. For more details on each paint mode, see
+ * 'https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators'.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef enum FT_Composite_Mode_
+ {
+ FT_COLR_COMPOSITE_CLEAR = 0,
+ FT_COLR_COMPOSITE_SRC = 1,
+ FT_COLR_COMPOSITE_DEST = 2,
+ FT_COLR_COMPOSITE_SRC_OVER = 3,
+ FT_COLR_COMPOSITE_DEST_OVER = 4,
+ FT_COLR_COMPOSITE_SRC_IN = 5,
+ FT_COLR_COMPOSITE_DEST_IN = 6,
+ FT_COLR_COMPOSITE_SRC_OUT = 7,
+ FT_COLR_COMPOSITE_DEST_OUT = 8,
+ FT_COLR_COMPOSITE_SRC_ATOP = 9,
+ FT_COLR_COMPOSITE_DEST_ATOP = 10,
+ FT_COLR_COMPOSITE_XOR = 11,
+ FT_COLR_COMPOSITE_SCREEN = 12,
+ FT_COLR_COMPOSITE_OVERLAY = 13,
+ FT_COLR_COMPOSITE_DARKEN = 14,
+ FT_COLR_COMPOSITE_LIGHTEN = 15,
+ FT_COLR_COMPOSITE_COLOR_DODGE = 16,
+ FT_COLR_COMPOSITE_COLOR_BURN = 17,
+ FT_COLR_COMPOSITE_HARD_LIGHT = 18,
+ FT_COLR_COMPOSITE_SOFT_LIGHT = 19,
+ FT_COLR_COMPOSITE_DIFFERENCE = 20,
+ FT_COLR_COMPOSITE_EXCLUSION = 21,
+ FT_COLR_COMPOSITE_MULTIPLY = 22,
+ FT_COLR_COMPOSITE_HSL_HUE = 23,
+ FT_COLR_COMPOSITE_HSL_SATURATION = 24,
+ FT_COLR_COMPOSITE_HSL_COLOR = 25,
+ FT_COLR_COMPOSITE_HSL_LUMINOSITY = 26,
+ FT_COLR_COMPOSITE_MAX = 27
+
+ } FT_Composite_Mode;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_OpaquePaint
+ *
+ * @description:
+ * A structure representing an offset to a `Paint` value stored in any
+ * of the paint tables of a 'COLR' v1 font. Compare Offset<24> there.
+ * When 'COLR' v1 paint tables represented by FreeType objects such as
+ * @FT_PaintColrLayers, @FT_PaintComposite, or @FT_PaintTransform
+ * reference downstream nested paint tables, we do not immediately
+ * retrieve them but encapsulate their location in this type. Use
+ * @FT_Get_Paint to retrieve the actual @FT_COLR_Paint object that
+ * describes the details of the respective paint table.
+ *
+ * @fields:
+ * p ::
+ * An internal offset to a Paint table, needs to be set to NULL before
+ * passing this struct as an argument to @FT_Get_Paint.
+ *
+ * insert_root_transform ::
+ * An internal boolean to track whether an initial root transform is
+ * to be provided. Do not set this value.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_Opaque_Paint_
+ {
+ FT_Byte* p;
+ FT_Bool insert_root_transform;
+ } FT_OpaquePaint;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintColrLayers
+ *
+ * @description:
+ * A structure representing a `PaintColrLayers` table of a 'COLR' v1
+ * font. This table describes a set of layers that are to be composited
+ * with composite mode `FT_COLR_COMPOSITE_SRC_OVER`. The return value
+ * of this function is an @FT_LayerIterator initialized so that it can
+ * be used with @FT_Get_Paint_Layers to retrieve the @FT_OpaquePaint
+ * objects as references to each layer.
+ *
+ * @fields:
+ * layer_iterator ::
+ * The layer iterator that describes the layers of this paint.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintColrLayers_
+ {
+ FT_LayerIterator layer_iterator;
+
+ } FT_PaintColrLayers;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintSolid
+ *
+ * @description:
+ * A structure representing a `PaintSolid` value of the 'COLR' v1
+ * extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+ * Using a `PaintSolid` value means that the glyph layer filled with
+ * this paint is solid-colored and does not contain a gradient.
+ *
+ * @fields:
+ * color ::
+ * The color information for this solid paint, see @FT_ColorIndex.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintSolid_
+ {
+ FT_ColorIndex color;
+
+ } FT_PaintSolid;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintLinearGradient
+ *
+ * @description:
+ * A structure representing a `PaintLinearGradient` value of the 'COLR'
+ * v1 extensions, see
+ * 'https://github.com/googlefonts/colr-gradients-spec'. The glyph
+ * layer filled with this paint is drawn filled with a linear gradient.
+ *
+ * @fields:
+ * colorline ::
+ * The @FT_ColorLine information for this paint, i.e., the list of
+ * color stops along the gradient.
+ *
+ * p0 ::
+ * The starting point of the gradient definition (in font units).
+ *
+ * p1 ::
+ * The end point of the gradient definition (in font units).
+ *
+ * p2 ::
+ * Optional point~p2 to rotate the gradient (in font units).
+ * Otherwise equal to~p0.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintLinearGradient_
+ {
+ FT_ColorLine colorline;
+
+ /* TODO: Potentially expose those as x0, y0 etc. */
+ FT_Vector p0;
+ FT_Vector p1;
+ FT_Vector p2;
+
+ } FT_PaintLinearGradient;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintRadialGradient
+ *
+ * @description:
+ * A structure representing a `PaintRadialGradient` value of the 'COLR'
+ * v1 extensions, see
+ * 'https://github.com/googlefonts/colr-gradients-spec'. The glyph
+ * layer filled with this paint is drawn filled filled with a radial
+ * gradient.
+ *
+ * @fields:
+ * colorline ::
+ * The @FT_ColorLine information for this paint, i.e., the list of
+ * color stops along the gradient.
+ *
+ * c0 ::
+ * The center of the starting point of the radial gradient (in font
+ * units).
+ *
+ * r0 ::
+ * The radius of the starting circle of the radial gradient (in font
+ * units).
+ *
+ * c1 ::
+ * The center of the end point of the radial gradient (in font units).
+ *
+ * r1 ::
+ * The radius of the end circle of the radial gradient (in font
+ * units).
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintRadialGradient_
+ {
+ FT_ColorLine colorline;
+
+ FT_Vector c0;
+ FT_UShort r0;
+ FT_Vector c1;
+ FT_UShort r1;
+
+ } FT_PaintRadialGradient;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintSweepGradient
+ *
+ * @description:
+ * A structure representing a `PaintSweepGradient` value of the 'COLR'
+ * v1 extensions, see
+ * 'https://github.com/googlefonts/colr-gradients-spec'. The glyph
+ * layer filled with this paint is drawn filled with a sweep gradient
+ * from `start_angle` to `end_angle`.
+ *
+ * @fields:
+ * colorline ::
+ * The @FT_ColorLine information for this paint, i.e., the list of
+ * color stops along the gradient.
+ *
+ * center ::
+ * The center of the sweep gradient (in font units).
+ *
+ * start_angle ::
+ * The start angle of the sweep gradient, in 16.16 fixed point format
+ * specifying degrees. Values are given counter-clockwise, starting
+ * from the (positive) y~axis.
+ *
+ * end_angle ::
+ * The end angle of the sweep gradient, in 16.16 fixed point format
+ * specifying degrees. Values are given counter-clockwise, starting
+ * from the (positive) y~axis.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintSweepGradient_
+ {
+ FT_ColorLine colorline;
+
+ FT_Vector center;
+ FT_Fixed start_angle;
+ FT_Fixed end_angle;
+
+ } FT_PaintSweepGradient;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintGlyph
+ *
+ * @description:
+ * A structure representing a 'COLR' v1 `PaintGlyph` paint table.
+ *
+ * @fields:
+ * paint ::
+ * An opaque paint object pointing to a `Paint` table that serves as
+ * the fill for the glyph ID.
+ *
+ * glyphID ::
+ * The glyph ID from the 'glyf' table, which serves as the contour
+ * information that is filled with paint.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintGlyph_
+ {
+ FT_OpaquePaint paint;
+ FT_UInt glyphID;
+
+ } FT_PaintGlyph;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintColrGlyph
+ *
+ * @description:
+ * A structure representing a 'COLR' v1 `PaintColorGlyph` paint table.
+ *
+ * @fields:
+ * glyphID ::
+ * The glyph ID from the `BaseGlyphV1List` table that is drawn for
+ * this paint.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintColrGlyph_
+ {
+ FT_UInt glyphID;
+
+ } FT_PaintColrGlyph;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintTransform
+ *
+ * @description:
+ * A structure representing a 'COLR' v1 `PaintTransform` paint table.
+ *
+ * @fields:
+ * paint ::
+ * An opaque paint that is subject to being transformed.
+ *
+ * affine ::
+ * A 2x3 transformation matrix in @FT_Affine23 format.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintTransform_
+ {
+ FT_OpaquePaint paint;
+ FT_Affine23 affine;
+
+ } FT_PaintTransform;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintTranslate
+ *
+ * @description:
+ * A structure representing a 'COLR' v1 `PaintTranslate` paint table.
+ * Used for translating downstream paints by a given x and y~delta.
+ *
+ * @fields:
+ * paint ::
+ * An @FT_OpaquePaint object referencing the paint that is to be
+ * rotated.
+ *
+ * dx ::
+ * Translation in x~direction (in font units).
+ *
+ * dy ::
+ * Translation in y~direction (in font units).
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintTranslate_
+ {
+ FT_OpaquePaint paint;
+
+ FT_Fixed dx;
+ FT_Fixed dy;
+
+ } FT_PaintTranslate;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintScale
+ *
+ * @description:
+ * A structure representing all of the 'COLR' v1 'PaintScale*' paint
+ * tables. Used for scaling downstream paints by a given x and y~scale,
+ * with a given center. This structure is used for all 'PaintScale*'
+ * types that are part of specification; fields of this structure are
+ * filled accordingly. If there is a center, the center values are set,
+ * otherwise they are set to the zero coordinate. If the source font
+ * file has 'PaintScaleUniform*' set, the scale values are set
+ * accordingly to the same value.
+ *
+ * @fields:
+ * paint ::
+ * An @FT_OpaquePaint object referencing the paint that is to be
+ * scaled.
+ *
+ * scale_x ::
+ * Scale factor in x~direction.
+ *
+ * scale_y ::
+ * Scale factor in y~direction.
+ *
+ * center_x ::
+ * x~coordinate of center point to scale from.
+ *
+ * center_y ::
+ * y~coordinate of center point to scale from.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward-compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintScale_
+ {
+ FT_OpaquePaint paint;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Fixed center_x;
+ FT_Fixed center_y;
+
+ } FT_PaintScale;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintRotate
+ *
+ * @description:
+ * A structure representing a 'COLR' v1 `PaintRotate` paint table. Used
+ * for rotating downstream paints with a given center and angle.
+ *
+ * @fields:
+ * paint ::
+ * An @FT_OpaquePaint object referencing the paint that is to be
+ * rotated.
+ *
+ * angle ::
+ * The rotation angle that is to be applied.
+ *
+ * center_x ::
+ * The x~coordinate of the pivot point of the rotation (in font
+ * units).
+ *
+ * center_y ::
+ * The y~coordinate of the pivot point of the rotation (in font
+ * units).
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+
+ typedef struct FT_PaintRotate_
+ {
+ FT_OpaquePaint paint;
+
+ FT_Fixed angle;
+
+ FT_Fixed center_x;
+ FT_Fixed center_y;
+
+ } FT_PaintRotate;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintSkew
+ *
+ * @description:
+ * A structure representing a 'COLR' v1 `PaintSkew` paint table. Used
+ * for skewing or shearing downstream paints by a given center and
+ * angle.
+ *
+ * @fields:
+ * paint ::
+ * An @FT_OpaquePaint object referencing the paint that is to be
+ * skewed.
+ *
+ * x_skew_angle ::
+ * The skewing angle in x~direction.
+ *
+ * y_skew_angle ::
+ * The skewing angle in y~direction.
+ *
+ * center_x ::
+ * The x~coordinate of the pivot point of the skew (in font units).
+ *
+ * center_y ::
+ * The y~coordinate of the pivot point of the skew (in font units).
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintSkew_
+ {
+ FT_OpaquePaint paint;
+
+ FT_Fixed x_skew_angle;
+ FT_Fixed y_skew_angle;
+
+ FT_Fixed center_x;
+ FT_Fixed center_y;
+
+ } FT_PaintSkew;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_PaintComposite
+ *
+ * @description:
+ * A structure representing a 'COLR'v1 `PaintComposite` paint table.
+ * Used for compositing two paints in a 'COLR' v1 directed acycling
+ * graph.
+ *
+ * @fields:
+ * source_paint ::
+ * An @FT_OpaquePaint object referencing the source that is to be
+ * composited.
+ *
+ * composite_mode ::
+ * An @FT_Composite_Mode enum value determining the composition
+ * operation.
+ *
+ * backdrop_paint ::
+ * An @FT_OpaquePaint object referencing the backdrop paint that
+ * `source_paint` is composited onto.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_PaintComposite_
+ {
+ FT_OpaquePaint source_paint;
+ FT_Composite_Mode composite_mode;
+ FT_OpaquePaint backdrop_paint;
+
+ } FT_PaintComposite;
+
+
+ /**************************************************************************
+ *
+ * @union:
+ * FT_COLR_Paint
+ *
+ * @description:
+ * A union object representing format and details of a paint table of a
+ * 'COLR' v1 font, see
+ * 'https://github.com/googlefonts/colr-gradients-spec'. Use
+ * @FT_Get_Paint to retrieve a @FT_COLR_Paint for an @FT_OpaquePaint
+ * object.
+ *
+ * @fields:
+ * format ::
+ * The gradient format for this Paint structure.
+ *
+ * u ::
+ * Union of all paint table types:
+ *
+ * * @FT_PaintColrLayers
+ * * @FT_PaintGlyph
+ * * @FT_PaintSolid
+ * * @FT_PaintLinearGradient
+ * * @FT_PaintRadialGradient
+ * * @FT_PaintSweepGradient
+ * * @FT_PaintTransform
+ * * @FT_PaintTranslate
+ * * @FT_PaintRotate
+ * * @FT_PaintSkew
+ * * @FT_PaintComposite
+ * * @FT_PaintColrGlyph
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef struct FT_COLR_Paint_
+ {
+ FT_PaintFormat format;
+
+ union
+ {
+ FT_PaintColrLayers colr_layers;
+ FT_PaintGlyph glyph;
+ FT_PaintSolid solid;
+ FT_PaintLinearGradient linear_gradient;
+ FT_PaintRadialGradient radial_gradient;
+ FT_PaintSweepGradient sweep_gradient;
+ FT_PaintTransform transform;
+ FT_PaintTranslate translate;
+ FT_PaintScale scale;
+ FT_PaintRotate rotate;
+ FT_PaintSkew skew;
+ FT_PaintComposite composite;
+ FT_PaintColrGlyph colr_glyph;
+
+ } u;
+
+ } FT_COLR_Paint;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Color_Root_Transform
+ *
+ * @description:
+ * An enumeration to specify whether @FT_Get_Color_Glyph_Paint is to
+ * return a root transform to configure the client's graphics context
+ * matrix.
+ *
+ * @values:
+ * FT_COLOR_INCLUDE_ROOT_TRANSFORM ::
+ * Do include the root transform as the initial @FT_COLR_Paint object.
+ *
+ * FT_COLOR_NO_ROOT_TRANSFORM ::
+ * Do not output an initial root transform.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ typedef enum FT_Color_Root_Transform_
+ {
+ FT_COLOR_INCLUDE_ROOT_TRANSFORM,
+ FT_COLOR_NO_ROOT_TRANSFORM,
+
+ FT_COLOR_ROOT_TRANSFORM_MAX
+
+ } FT_Color_Root_Transform;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Color_Glyph_Paint
+ *
+ * @description:
+ * This is the starting point and interface to color gradient
+ * information in a 'COLR' v1 table in OpenType fonts to recursively
+ * retrieve the paint tables for the directed acyclic graph of a colored
+ * glyph, given a glyph ID.
+ *
+ * https://github.com/googlefonts/colr-gradients-spec
+ *
+ * In a 'COLR' v1 font, each color glyph defines a directed acyclic
+ * graph of nested paint tables, such as `PaintGlyph`, `PaintSolid`,
+ * `PaintLinearGradient`, `PaintRadialGradient`, and so on. Using this
+ * function and specifying a glyph ID, one retrieves the root paint
+ * table for this glyph ID.
+ *
+ * This function allows control whether an initial root transform is
+ * returned to configure scaling, transform, and translation correctly
+ * on the client's graphics context. The initial root transform is
+ * computed and returned according to the values configured for @FT_Size
+ * and @FT_Set_Transform on the @FT_Face object, see below for details
+ * of the `root_transform` parameter. This has implications for a
+ * client 'COLR' v1 implementation: When this function returns an
+ * initially computed root transform, at the time of executing the
+ * @FT_PaintGlyph operation, the contours should be retrieved using
+ * @FT_Load_Glyph at unscaled, untransformed size. This is because the
+ * root transform applied to the graphics context will take care of
+ * correct scaling.
+ *
+ * Alternatively, to allow hinting of contours, at the time of executing
+ * @FT_Load_Glyph, the current graphics context transformation matrix
+ * can be decomposed into a scaling matrix and a remainder, and
+ * @FT_Load_Glyph can be used to retrieve the contours at scaled size.
+ * Care must then be taken to blit or clip to the graphics context with
+ * taking this remainder transformation into account.
+ *
+ * @input:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * base_glyph ::
+ * The glyph index for which to retrieve the root paint table.
+ *
+ * root_transform ::
+ * Specifies whether an initially computed root is returned by the
+ * @FT_PaintTransform operation to account for the activated size
+ * (see @FT_Activate_Size) and the configured transform and translate
+ * (see @FT_Set_Transform).
+ *
+ * This root transform is returned before nodes of the glyph graph of
+ * the font are returned. Subsequent @FT_COLR_Paint structures
+ * contain unscaled and untransformed values. The inserted root
+ * transform enables the client application to apply an initial
+ * transform to its graphics context. When executing subsequent
+ * FT_COLR_Paint operations, values from @FT_COLR_Paint operations
+ * will ultimately be correctly scaled because of the root transform
+ * applied to the graphics context. Use
+ * @FT_COLOR_INCLUDE_ROOT_TRANSFORM to include the root transform, use
+ * @FT_COLOR_NO_ROOT_TRANSFORM to not include it. The latter may be
+ * useful when traversing the 'COLR' v1 glyph graph and reaching a
+ * @FT_PaintColrGlyph. When recursing into @FT_PaintColrGlyph and
+ * painting that inline, no additional root transform is needed as it
+ * has already been applied to the graphics context at the beginning
+ * of drawing this glyph.
+ *
+ * @output:
+ * paint ::
+ * The @FT_OpaquePaint object that references the actual paint table.
+ *
+ * The respective actual @FT_COLR_Paint object is retrieved via
+ * @FT_Get_Paint.
+ *
+ * @return:
+ * Value~1 if everything is OK. If no color glyph is found, or the root
+ * paint could not be retrieved, value~0 gets returned. In case of an
+ * error, value~0 is returned also.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Get_Color_Glyph_Paint( FT_Face face,
+ FT_UInt base_glyph,
+ FT_Color_Root_Transform root_transform,
+ FT_OpaquePaint* paint );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Paint_Layers
+ *
+ * @description:
+ * Access the layers of a `PaintColrLayers` table.
+ *
+ * If the root paint of a color glyph, or a nested paint of a 'COLR'
+ * glyph is a `PaintColrLayers` table, this function retrieves the
+ * layers of the `PaintColrLayers` table.
+ *
+ * The @FT_PaintColrLayers object contains an @FT_LayerIterator, which
+ * is used here to iterate over the layers. Each layer is returned as
+ * an @FT_OpaquePaint object, which then can be used with @FT_Get_Paint
+ * to retrieve the actual paint object.
+ *
+ * @input:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * @inout:
+ * iterator ::
+ * The @FT_LayerIterator from an @FT_PaintColrLayers object, for which
+ * the layers are to be retrieved. The internal state of the iterator
+ * is incremented after one call to this function for retrieving one
+ * layer.
+ *
+ * @output:
+ * paint ::
+ * The @FT_OpaquePaint object that references the actual paint table.
+ * The respective actual @FT_COLR_Paint object is retrieved via
+ * @FT_Get_Paint.
+ *
+ * @return:
+ * Value~1 if everything is OK. Value~0 gets returned when the paint
+ * object can not be retrieved or any other error occurs.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Get_Paint_Layers( FT_Face face,
+ FT_LayerIterator* iterator,
+ FT_OpaquePaint* paint );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Colorline_Stops
+ *
+ * @description:
+ * This is an interface to color gradient information in a 'COLR' v1
+ * table in OpenType fonts to iteratively retrieve the gradient and
+ * solid fill information for colored glyph layers for a specified glyph
+ * ID.
+ *
+ * https://github.com/googlefonts/colr-gradients-spec
+ *
+ * @input:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * @inout:
+ * iterator ::
+ * The retrieved @FT_ColorStopIterator, configured on an @FT_ColorLine,
+ * which in turn got retrieved via paint information in
+ * @FT_PaintLinearGradient or @FT_PaintRadialGradient.
+ *
+ * @output:
+ * color_stop ::
+ * Color index and alpha value for the retrieved color stop.
+ *
+ * @return:
+ * Value~1 if everything is OK. If there are no more color stops,
+ * value~0 gets returned. In case of an error, value~0 is returned
+ * also.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Get_Colorline_Stops( FT_Face face,
+ FT_ColorStop* color_stop,
+ FT_ColorStopIterator* iterator );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Paint
+ *
+ * @description:
+ * Access the details of a paint using an @FT_OpaquePaint opaque paint
+ * object, which internally stores the offset to the respective `Paint`
+ * object in the 'COLR' table.
+ *
+ * @input:
+ * face ::
+ * A handle to the parent face object.
+ *
+ * opaque_paint ::
+ * The opaque paint object for which the underlying @FT_COLR_Paint
+ * data is to be retrieved.
+ *
+ * @output:
+ * paint ::
+ * The specific @FT_COLR_Paint object containing information coming
+ * from one of the font's `Paint*` tables.
+ *
+ * @return:
+ * Value~1 if everything is OK. Value~0 if no details can be found for
+ * this paint or any other error occured.
+ *
+ * @since:
+ * 2.11 -- **currently experimental only!** There might be changes
+ * without retaining backward compatibility of both the API and ABI.
+ *
+ */
+ FT_EXPORT( FT_Bool )
+ FT_Get_Paint( FT_Face face,
+ FT_OpaquePaint opaque_paint,
+ FT_COLR_Paint* paint );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTCOLOR_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftdriver.h b/Client/ThirdParty/freetype/include/freetype/ftdriver.h
new file mode 100644
index 0000000..4936639
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftdriver.h
@@ -0,0 +1,1193 @@
+/****************************************************************************
+ *
+ * ftdriver.h
+ *
+ * FreeType API for controlling driver modules (specification only).
+ *
+ * Copyright (C) 2017-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTDRIVER_H_
+#define FTDRIVER_H_
+
+#include <freetype/freetype.h>
+#include <freetype/ftparams.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * auto_hinter
+ *
+ * @title:
+ * The auto-hinter
+ *
+ * @abstract:
+ * Controlling the auto-hinting module.
+ *
+ * @description:
+ * While FreeType's auto-hinter doesn't expose API functions by itself,
+ * it is possible to control its behaviour with @FT_Property_Set and
+ * @FT_Property_Get. The following lists the available properties
+ * together with the necessary macros and structures.
+ *
+ * Note that the auto-hinter's module name is 'autofitter' for historical
+ * reasons.
+ *
+ * Available properties are @increase-x-height, @no-stem-darkening
+ * (experimental), @darkening-parameters (experimental),
+ * @glyph-to-script-map (experimental), @fallback-script (experimental),
+ * and @default-script (experimental), as documented in the @properties
+ * section.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * cff_driver
+ *
+ * @title:
+ * The CFF driver
+ *
+ * @abstract:
+ * Controlling the CFF driver module.
+ *
+ * @description:
+ * While FreeType's CFF driver doesn't expose API functions by itself, it
+ * is possible to control its behaviour with @FT_Property_Set and
+ * @FT_Property_Get.
+ *
+ * The CFF driver's module name is 'cff'.
+ *
+ * Available properties are @hinting-engine, @no-stem-darkening,
+ * @darkening-parameters, and @random-seed, as documented in the
+ * @properties section.
+ *
+ *
+ * **Hinting and anti-aliasing principles of the new engine**
+ *
+ * The rasterizer is positioning horizontal features (e.g., ascender
+ * height & x-height, or crossbars) on the pixel grid and minimizing the
+ * amount of anti-aliasing applied to them, while placing vertical
+ * features (vertical stems) on the pixel grid without hinting, thus
+ * representing the stem position and weight accurately. Sometimes the
+ * vertical stems may be only partially black. In this context,
+ * 'anti-aliasing' means that stems are not positioned exactly on pixel
+ * borders, causing a fuzzy appearance.
+ *
+ * There are two principles behind this approach.
+ *
+ * 1) No hinting in the horizontal direction: Unlike 'superhinted'
+ * TrueType, which changes glyph widths to accommodate regular
+ * inter-glyph spacing, Adobe's approach is 'faithful to the design' in
+ * representing both the glyph width and the inter-glyph spacing designed
+ * for the font. This makes the screen display as close as it can be to
+ * the result one would get with infinite resolution, while preserving
+ * what is considered the key characteristics of each glyph. Note that
+ * the distances between unhinted and grid-fitted positions at small
+ * sizes are comparable to kerning values and thus would be noticeable
+ * (and distracting) while reading if hinting were applied.
+ *
+ * One of the reasons to not hint horizontally is anti-aliasing for LCD
+ * screens: The pixel geometry of modern displays supplies three vertical
+ * subpixels as the eye moves horizontally across each visible pixel. On
+ * devices where we can be certain this characteristic is present a
+ * rasterizer can take advantage of the subpixels to add increments of
+ * weight. In Western writing systems this turns out to be the more
+ * critical direction anyway; the weights and spacing of vertical stems
+ * (see above) are central to Armenian, Cyrillic, Greek, and Latin type
+ * designs. Even when the rasterizer uses greyscale anti-aliasing instead
+ * of color (a necessary compromise when one doesn't know the screen
+ * characteristics), the unhinted vertical features preserve the design's
+ * weight and spacing much better than aliased type would.
+ *
+ * 2) Alignment in the vertical direction: Weights and spacing along the
+ * y~axis are less critical; what is much more important is the visual
+ * alignment of related features (like cap-height and x-height). The
+ * sense of alignment for these is enhanced by the sharpness of grid-fit
+ * edges, while the cruder vertical resolution (full pixels instead of
+ * 1/3 pixels) is less of a problem.
+ *
+ * On the technical side, horizontal alignment zones for ascender,
+ * x-height, and other important height values (traditionally called
+ * 'blue zones') as defined in the font are positioned independently,
+ * each being rounded to the nearest pixel edge, taking care of overshoot
+ * suppression at small sizes, stem darkening, and scaling.
+ *
+ * Hstems (this is, hint values defined in the font to help align
+ * horizontal features) that fall within a blue zone are said to be
+ * 'captured' and are aligned to that zone. Uncaptured stems are moved
+ * in one of four ways, top edge up or down, bottom edge up or down.
+ * Unless there are conflicting hstems, the smallest movement is taken to
+ * minimize distortion.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * pcf_driver
+ *
+ * @title:
+ * The PCF driver
+ *
+ * @abstract:
+ * Controlling the PCF driver module.
+ *
+ * @description:
+ * While FreeType's PCF driver doesn't expose API functions by itself, it
+ * is possible to control its behaviour with @FT_Property_Set and
+ * @FT_Property_Get. Right now, there is a single property
+ * @no-long-family-names available if FreeType is compiled with
+ * PCF_CONFIG_OPTION_LONG_FAMILY_NAMES.
+ *
+ * The PCF driver's module name is 'pcf'.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * t1_cid_driver
+ *
+ * @title:
+ * The Type 1 and CID drivers
+ *
+ * @abstract:
+ * Controlling the Type~1 and CID driver modules.
+ *
+ * @description:
+ * It is possible to control the behaviour of FreeType's Type~1 and
+ * Type~1 CID drivers with @FT_Property_Set and @FT_Property_Get.
+ *
+ * Behind the scenes, both drivers use the Adobe CFF engine for hinting;
+ * however, the used properties must be specified separately.
+ *
+ * The Type~1 driver's module name is 'type1'; the CID driver's module
+ * name is 't1cid'.
+ *
+ * Available properties are @hinting-engine, @no-stem-darkening,
+ * @darkening-parameters, and @random-seed, as documented in the
+ * @properties section.
+ *
+ * Please see the @cff_driver section for more details on the new hinting
+ * engine.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * tt_driver
+ *
+ * @title:
+ * The TrueType driver
+ *
+ * @abstract:
+ * Controlling the TrueType driver module.
+ *
+ * @description:
+ * While FreeType's TrueType driver doesn't expose API functions by
+ * itself, it is possible to control its behaviour with @FT_Property_Set
+ * and @FT_Property_Get. The following lists the available properties
+ * together with the necessary macros and structures.
+ *
+ * The TrueType driver's module name is 'truetype'.
+ *
+ * A single property @interpreter-version is available, as documented in
+ * the @properties section.
+ *
+ * We start with a list of definitions, kindly provided by Greg
+ * Hitchcock.
+ *
+ * _Bi-Level Rendering_
+ *
+ * Monochromatic rendering, exclusively used in the early days of
+ * TrueType by both Apple and Microsoft. Microsoft's GDI interface
+ * supported hinting of the right-side bearing point, such that the
+ * advance width could be non-linear. Most often this was done to
+ * achieve some level of glyph symmetry. To enable reasonable
+ * performance (e.g., not having to run hinting on all glyphs just to get
+ * the widths) there was a bit in the head table indicating if the side
+ * bearing was hinted, and additional tables, 'hdmx' and 'LTSH', to cache
+ * hinting widths across multiple sizes and device aspect ratios.
+ *
+ * _Font Smoothing_
+ *
+ * Microsoft's GDI implementation of anti-aliasing. Not traditional
+ * anti-aliasing as the outlines were hinted before the sampling. The
+ * widths matched the bi-level rendering.
+ *
+ * _ClearType Rendering_
+ *
+ * Technique that uses physical subpixels to improve rendering on LCD
+ * (and other) displays. Because of the higher resolution, many methods
+ * of improving symmetry in glyphs through hinting the right-side bearing
+ * were no longer necessary. This lead to what GDI calls 'natural
+ * widths' ClearType, see
+ * http://rastertragedy.com/RTRCh4.htm#Sec21. Since hinting
+ * has extra resolution, most non-linearity went away, but it is still
+ * possible for hints to change the advance widths in this mode.
+ *
+ * _ClearType Compatible Widths_
+ *
+ * One of the earliest challenges with ClearType was allowing the
+ * implementation in GDI to be selected without requiring all UI and
+ * documents to reflow. To address this, a compatible method of
+ * rendering ClearType was added where the font hints are executed once
+ * to determine the width in bi-level rendering, and then re-run in
+ * ClearType, with the difference in widths being absorbed in the font
+ * hints for ClearType (mostly in the white space of hints); see
+ * http://rastertragedy.com/RTRCh4.htm#Sec20. Somewhat by
+ * definition, compatible width ClearType allows for non-linear widths,
+ * but only when the bi-level version has non-linear widths.
+ *
+ * _ClearType Subpixel Positioning_
+ *
+ * One of the nice benefits of ClearType is the ability to more crisply
+ * display fractional widths; unfortunately, the GDI model of integer
+ * bitmaps did not support this. However, the WPF and Direct Write
+ * frameworks do support fractional widths. DWrite calls this 'natural
+ * mode', not to be confused with GDI's 'natural widths'. Subpixel
+ * positioning, in the current implementation of Direct Write,
+ * unfortunately does not support hinted advance widths, see
+ * http://rastertragedy.com/RTRCh4.htm#Sec22. Note that the
+ * TrueType interpreter fully allows the advance width to be adjusted in
+ * this mode, just the DWrite client will ignore those changes.
+ *
+ * _ClearType Backward Compatibility_
+ *
+ * This is a set of exceptions made in the TrueType interpreter to
+ * minimize hinting techniques that were problematic with the extra
+ * resolution of ClearType; see
+ * http://rastertragedy.com/RTRCh4.htm#Sec1 and
+ * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx.
+ * This technique is not to be confused with ClearType compatible widths.
+ * ClearType backward compatibility has no direct impact on changing
+ * advance widths, but there might be an indirect impact on disabling
+ * some deltas. This could be worked around in backward compatibility
+ * mode.
+ *
+ * _Native ClearType Mode_
+ *
+ * (Not to be confused with 'natural widths'.) This mode removes all the
+ * exceptions in the TrueType interpreter when running with ClearType.
+ * Any issues on widths would still apply, though.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * properties
+ *
+ * @title:
+ * Driver properties
+ *
+ * @abstract:
+ * Controlling driver modules.
+ *
+ * @description:
+ * Driver modules can be controlled by setting and unsetting properties,
+ * using the functions @FT_Property_Set and @FT_Property_Get. This
+ * section documents the available properties, together with auxiliary
+ * macros and structures.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_HINTING_XXX
+ *
+ * @description:
+ * A list of constants used for the @hinting-engine property to select
+ * the hinting engine for CFF, Type~1, and CID fonts.
+ *
+ * @values:
+ * FT_HINTING_FREETYPE ::
+ * Use the old FreeType hinting engine.
+ *
+ * FT_HINTING_ADOBE ::
+ * Use the hinting engine contributed by Adobe.
+ *
+ * @since:
+ * 2.9
+ *
+ */
+#define FT_HINTING_FREETYPE 0
+#define FT_HINTING_ADOBE 1
+
+ /* these constants (introduced in 2.4.12) are deprecated */
+#define FT_CFF_HINTING_FREETYPE FT_HINTING_FREETYPE
+#define FT_CFF_HINTING_ADOBE FT_HINTING_ADOBE
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * hinting-engine
+ *
+ * @description:
+ * Thanks to Adobe, which contributed a new hinting (and parsing) engine,
+ * an application can select between 'freetype' and 'adobe' if compiled
+ * with `CFF_CONFIG_OPTION_OLD_ENGINE`. If this configuration macro
+ * isn't defined, 'hinting-engine' does nothing.
+ *
+ * The same holds for the Type~1 and CID modules if compiled with
+ * `T1_CONFIG_OPTION_OLD_ENGINE`.
+ *
+ * For the 'cff' module, the default engine is 'adobe'. For both the
+ * 'type1' and 't1cid' modules, the default engine is 'adobe', too.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 'adobe' or 'freetype').
+ *
+ * @example:
+ * The following example code demonstrates how to select Adobe's hinting
+ * engine for the 'cff' module (omitting the error handling).
+ *
+ * ```
+ * FT_Library library;
+ * FT_UInt hinting_engine = FT_HINTING_ADOBE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "cff",
+ * "hinting-engine", &hinting_engine );
+ * ```
+ *
+ * @since:
+ * 2.4.12 (for 'cff' module)
+ *
+ * 2.9 (for 'type1' and 't1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * no-stem-darkening
+ *
+ * @description:
+ * All glyphs that pass through the auto-hinter will be emboldened unless
+ * this property is set to TRUE. The same is true for the CFF, Type~1,
+ * and CID font modules if the 'Adobe' engine is selected (which is the
+ * default).
+ *
+ * Stem darkening emboldens glyphs at smaller sizes to make them more
+ * readable on common low-DPI screens when using linear alpha blending
+ * and gamma correction, see @FT_Render_Glyph. When not using linear
+ * alpha blending and gamma correction, glyphs will appear heavy and
+ * fuzzy!
+ *
+ * Gamma correction essentially lightens fonts since shades of grey are
+ * shifted to higher pixel values (=~higher brightness) to match the
+ * original intention to the reality of our screens. The side-effect is
+ * that glyphs 'thin out'. Mac OS~X and Adobe's proprietary font
+ * rendering library implement a counter-measure: stem darkening at
+ * smaller sizes where shades of gray dominate. By emboldening a glyph
+ * slightly in relation to its pixel size, individual pixels get higher
+ * coverage of filled-in outlines and are therefore 'blacker'. This
+ * counteracts the 'thinning out' of glyphs, making text remain readable
+ * at smaller sizes.
+ *
+ * For the auto-hinter, stem-darkening is experimental currently and thus
+ * switched off by default (this is, `no-stem-darkening` is set to TRUE
+ * by default). Total consistency with the CFF driver is not achieved
+ * right now because the emboldening method differs and glyphs must be
+ * scaled down on the Y-axis to keep outline points inside their
+ * precomputed blue zones. The smaller the size (especially 9ppem and
+ * down), the higher the loss of emboldening versus the CFF driver.
+ *
+ * Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 1 and 0 for 'on' and 'off', respectively). It
+ * can also be set per face using @FT_Face_Properties with
+ * @FT_PARAM_TAG_STEM_DARKENING.
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_Bool no_stem_darkening = TRUE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "cff",
+ * "no-stem-darkening", &no_stem_darkening );
+ * ```
+ *
+ * @since:
+ * 2.4.12 (for 'cff' module)
+ *
+ * 2.6.2 (for 'autofitter' module)
+ *
+ * 2.9 (for 'type1' and 't1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * darkening-parameters
+ *
+ * @description:
+ * By default, the Adobe hinting engine, as used by the CFF, Type~1, and
+ * CID font drivers, darkens stems as follows (if the `no-stem-darkening`
+ * property isn't set):
+ *
+ * ```
+ * stem width <= 0.5px: darkening amount = 0.4px
+ * stem width = 1px: darkening amount = 0.275px
+ * stem width = 1.667px: darkening amount = 0.275px
+ * stem width >= 2.333px: darkening amount = 0px
+ * ```
+ *
+ * and piecewise linear in-between. At configuration time, these four
+ * control points can be set with the macro
+ * `CFF_CONFIG_OPTION_DARKENING_PARAMETERS`; the CFF, Type~1, and CID
+ * drivers share these values. At runtime, the control points can be
+ * changed using the `darkening-parameters` property (see the example
+ * below that demonstrates this for the Type~1 driver).
+ *
+ * The x~values give the stem width, and the y~values the darkening
+ * amount. The unit is 1000th of pixels. All coordinate values must be
+ * positive; the x~values must be monotonically increasing; the y~values
+ * must be monotonically decreasing and smaller than or equal to 500
+ * (corresponding to half a pixel); the slope of each linear piece must
+ * be shallower than -1 (e.g., -.4).
+ *
+ * The auto-hinter provides this property, too, as an experimental
+ * feature. See @no-stem-darkening for more.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable, using eight comma-separated integers without spaces. Here
+ * the above example, using `\` to break the line for readability.
+ *
+ * ```
+ * FREETYPE_PROPERTIES=\
+ * type1:darkening-parameters=500,300,1000,200,1500,100,2000,0
+ * ```
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_Int darken_params[8] = { 500, 300, // x1, y1
+ * 1000, 200, // x2, y2
+ * 1500, 100, // x3, y3
+ * 2000, 0 }; // x4, y4
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "type1",
+ * "darkening-parameters", darken_params );
+ * ```
+ *
+ * @since:
+ * 2.5.1 (for 'cff' module)
+ *
+ * 2.6.2 (for 'autofitter' module)
+ *
+ * 2.9 (for 'type1' and 't1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * random-seed
+ *
+ * @description:
+ * By default, the seed value for the CFF 'random' operator and the
+ * similar '0 28 callothersubr pop' command for the Type~1 and CID
+ * drivers is set to a random value. However, mainly for debugging
+ * purposes, it is often necessary to use a known value as a seed so that
+ * the pseudo-random number sequences generated by 'random' are
+ * repeatable.
+ *
+ * The `random-seed` property does that. Its argument is a signed 32bit
+ * integer; if the value is zero or negative, the seed given by the
+ * `intitialRandomSeed` private DICT operator in a CFF file gets used (or
+ * a default value if there is no such operator). If the value is
+ * positive, use it instead of `initialRandomSeed`, which is consequently
+ * ignored.
+ *
+ * @note:
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable. It can also be set per face using @FT_Face_Properties with
+ * @FT_PARAM_TAG_RANDOM_SEED.
+ *
+ * @since:
+ * 2.8 (for 'cff' module)
+ *
+ * 2.9 (for 'type1' and 't1cid' modules)
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * no-long-family-names
+ *
+ * @description:
+ * If `PCF_CONFIG_OPTION_LONG_FAMILY_NAMES` is active while compiling
+ * FreeType, the PCF driver constructs long family names.
+ *
+ * There are many PCF fonts just called 'Fixed' which look completely
+ * different, and which have nothing to do with each other. When
+ * selecting 'Fixed' in KDE or Gnome one gets results that appear rather
+ * random, the style changes often if one changes the size and one cannot
+ * select some fonts at all. The improve this situation, the PCF module
+ * prepends the foundry name (plus a space) to the family name. It also
+ * checks whether there are 'wide' characters; all put together, family
+ * names like 'Sony Fixed' or 'Misc Fixed Wide' are constructed.
+ *
+ * If `no-long-family-names` is set, this feature gets switched off.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values 1 and 0 for 'on' and 'off', respectively).
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_Bool no_long_family_names = TRUE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "pcf",
+ * "no-long-family-names",
+ * &no_long_family_names );
+ * ```
+ *
+ * @since:
+ * 2.8
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_INTERPRETER_VERSION_XXX
+ *
+ * @description:
+ * A list of constants used for the @interpreter-version property to
+ * select the hinting engine for Truetype fonts.
+ *
+ * The numeric value in the constant names represents the version number
+ * as returned by the 'GETINFO' bytecode instruction.
+ *
+ * @values:
+ * TT_INTERPRETER_VERSION_35 ::
+ * Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
+ * Windows~98; only grayscale and B/W rasterizing is supported.
+ *
+ * TT_INTERPRETER_VERSION_38 ::
+ * Version~38 corresponds to MS rasterizer v.1.9; it is roughly
+ * equivalent to the hinting provided by DirectWrite ClearType (as can
+ * be found, for example, in the Internet Explorer~9 running on
+ * Windows~7). It is used in FreeType to select the 'Infinality'
+ * subpixel hinting code. The code may be removed in a future version.
+ *
+ * TT_INTERPRETER_VERSION_40 ::
+ * Version~40 corresponds to MS rasterizer v.2.1; it is roughly
+ * equivalent to the hinting provided by DirectWrite ClearType (as can
+ * be found, for example, in Microsoft's Edge Browser on Windows~10).
+ * It is used in FreeType to select the 'minimal' subpixel hinting
+ * code, a stripped-down and higher performance version of the
+ * 'Infinality' code.
+ *
+ * @note:
+ * This property controls the behaviour of the bytecode interpreter and
+ * thus how outlines get hinted. It does **not** control how glyph get
+ * rasterized! In particular, it does not control subpixel color
+ * filtering.
+ *
+ * If FreeType has not been compiled with the configuration option
+ * `TT_CONFIG_OPTION_SUBPIXEL_HINTING`, selecting version~38 or~40 causes
+ * an `FT_Err_Unimplemented_Feature` error.
+ *
+ * Depending on the graphics framework, Microsoft uses different bytecode
+ * and rendering engines. As a consequence, the version numbers returned
+ * by a call to the 'GETINFO' bytecode instruction are more convoluted
+ * than desired.
+ *
+ * Here are two tables that try to shed some light on the possible values
+ * for the MS rasterizer engine, together with the additional features
+ * introduced by it.
+ *
+ * ```
+ * GETINFO framework version feature
+ * -------------------------------------------------------------------
+ * 3 GDI (Win 3.1), v1.0 16-bit, first version
+ * TrueImage
+ * 33 GDI (Win NT 3.1), v1.5 32-bit
+ * HP Laserjet
+ * 34 GDI (Win 95) v1.6 font smoothing,
+ * new SCANTYPE opcode
+ * 35 GDI (Win 98/2000) v1.7 (UN)SCALED_COMPONENT_OFFSET
+ * bits in composite glyphs
+ * 36 MGDI (Win CE 2) v1.6+ classic ClearType
+ * 37 GDI (XP and later), v1.8 ClearType
+ * GDI+ old (before Vista)
+ * 38 GDI+ old (Vista, Win 7), v1.9 subpixel ClearType,
+ * WPF Y-direction ClearType,
+ * additional error checking
+ * 39 DWrite (before Win 8) v2.0 subpixel ClearType flags
+ * in GETINFO opcode,
+ * bug fixes
+ * 40 GDI+ (after Win 7), v2.1 Y-direction ClearType flag
+ * DWrite (Win 8) in GETINFO opcode,
+ * Gray ClearType
+ * ```
+ *
+ * The 'version' field gives a rough orientation only, since some
+ * applications provided certain features much earlier (as an example,
+ * Microsoft Reader used subpixel and Y-direction ClearType already in
+ * Windows 2000). Similarly, updates to a given framework might include
+ * improved hinting support.
+ *
+ * ```
+ * version sampling rendering comment
+ * x y x y
+ * --------------------------------------------------------------
+ * v1.0 normal normal B/W B/W bi-level
+ * v1.6 high high gray gray grayscale
+ * v1.8 high normal color-filter B/W (GDI) ClearType
+ * v1.9 high high color-filter gray Color ClearType
+ * v2.1 high normal gray B/W Gray ClearType
+ * v2.1 high high gray gray Gray ClearType
+ * ```
+ *
+ * Color and Gray ClearType are the two available variants of
+ * 'Y-direction ClearType', meaning grayscale rasterization along the
+ * Y-direction; the name used in the TrueType specification for this
+ * feature is 'symmetric smoothing'. 'Classic ClearType' is the original
+ * algorithm used before introducing a modified version in Win~XP.
+ * Another name for v1.6's grayscale rendering is 'font smoothing', and
+ * 'Color ClearType' is sometimes also called 'DWrite ClearType'. To
+ * differentiate between today's Color ClearType and the earlier
+ * ClearType variant with B/W rendering along the vertical axis, the
+ * latter is sometimes called 'GDI ClearType'.
+ *
+ * 'Normal' and 'high' sampling describe the (virtual) resolution to
+ * access the rasterized outline after the hinting process. 'Normal'
+ * means 1 sample per grid line (i.e., B/W). In the current Microsoft
+ * implementation, 'high' means an extra virtual resolution of 16x16 (or
+ * 16x1) grid lines per pixel for bytecode instructions like 'MIRP'.
+ * After hinting, these 16 grid lines are mapped to 6x5 (or 6x1) grid
+ * lines for color filtering if Color ClearType is activated.
+ *
+ * Note that 'Gray ClearType' is essentially the same as v1.6's grayscale
+ * rendering. However, the GETINFO instruction handles it differently:
+ * v1.6 returns bit~12 (hinting for grayscale), while v2.1 returns
+ * bits~13 (hinting for ClearType), 18 (symmetrical smoothing), and~19
+ * (Gray ClearType). Also, this mode respects bits 2 and~3 for the
+ * version~1 gasp table exclusively (like Color ClearType), while v1.6
+ * only respects the values of version~0 (bits 0 and~1).
+ *
+ * Keep in mind that the features of the above interpreter versions might
+ * not map exactly to FreeType features or behavior because it is a
+ * fundamentally different library with different internals.
+ *
+ */
+#define TT_INTERPRETER_VERSION_35 35
+#define TT_INTERPRETER_VERSION_38 38
+#define TT_INTERPRETER_VERSION_40 40
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * interpreter-version
+ *
+ * @description:
+ * Currently, three versions are available, two representing the bytecode
+ * interpreter with subpixel hinting support (old 'Infinality' code and
+ * new stripped-down and higher performance 'minimal' code) and one
+ * without, respectively. The default is subpixel support if
+ * `TT_CONFIG_OPTION_SUBPIXEL_HINTING` is defined, and no subpixel
+ * support otherwise (since it isn't available then).
+ *
+ * If subpixel hinting is on, many TrueType bytecode instructions behave
+ * differently compared to B/W or grayscale rendering (except if 'native
+ * ClearType' is selected by the font). Microsoft's main idea is to
+ * render at a much increased horizontal resolution, then sampling down
+ * the created output to subpixel precision. However, many older fonts
+ * are not suited to this and must be specially taken care of by applying
+ * (hardcoded) tweaks in Microsoft's interpreter.
+ *
+ * Details on subpixel hinting and some of the necessary tweaks can be
+ * found in Greg Hitchcock's whitepaper at
+ * 'https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
+ * Note that FreeType currently doesn't really 'subpixel hint' (6x1, 6x2,
+ * or 6x5 supersampling) like discussed in the paper. Depending on the
+ * chosen interpreter, it simply ignores instructions on vertical stems
+ * to arrive at very similar results.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * This property can be set via the `FREETYPE_PROPERTIES` environment
+ * variable (using values '35', '38', or '40').
+ *
+ * @example:
+ * The following example code demonstrates how to deactivate subpixel
+ * hinting (omitting the error handling).
+ *
+ * ```
+ * FT_Library library;
+ * FT_Face face;
+ * FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "truetype",
+ * "interpreter-version",
+ * &interpreter_version );
+ * ```
+ *
+ * @since:
+ * 2.5
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * glyph-to-script-map
+ *
+ * @description:
+ * **Experimental only**
+ *
+ * The auto-hinter provides various script modules to hint glyphs.
+ * Examples of supported scripts are Latin or CJK. Before a glyph is
+ * auto-hinted, the Unicode character map of the font gets examined, and
+ * the script is then determined based on Unicode character ranges, see
+ * below.
+ *
+ * OpenType fonts, however, often provide much more glyphs than character
+ * codes (small caps, superscripts, ligatures, swashes, etc.), to be
+ * controlled by so-called 'features'. Handling OpenType features can be
+ * quite complicated and thus needs a separate library on top of
+ * FreeType.
+ *
+ * The mapping between glyph indices and scripts (in the auto-hinter
+ * sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an array
+ * with `num_glyphs` elements, as found in the font's @FT_Face structure.
+ * The `glyph-to-script-map` property returns a pointer to this array,
+ * which can be modified as needed. Note that the modification should
+ * happen before the first glyph gets processed by the auto-hinter so
+ * that the global analysis of the font shapes actually uses the modified
+ * mapping.
+ *
+ * @example:
+ * The following example code demonstrates how to access it (omitting the
+ * error handling).
+ *
+ * ```
+ * FT_Library library;
+ * FT_Face face;
+ * FT_Prop_GlyphToScriptMap prop;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ * FT_New_Face( library, "foo.ttf", 0, &face );
+ *
+ * prop.face = face;
+ *
+ * FT_Property_Get( library, "autofitter",
+ * "glyph-to-script-map", &prop );
+ *
+ * // adjust `prop.map' as needed right here
+ *
+ * FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT );
+ * ```
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_AUTOHINTER_SCRIPT_XXX
+ *
+ * @description:
+ * **Experimental only**
+ *
+ * A list of constants used for the @glyph-to-script-map property to
+ * specify the script submodule the auto-hinter should use for hinting a
+ * particular glyph.
+ *
+ * @values:
+ * FT_AUTOHINTER_SCRIPT_NONE ::
+ * Don't auto-hint this glyph.
+ *
+ * FT_AUTOHINTER_SCRIPT_LATIN ::
+ * Apply the latin auto-hinter. For the auto-hinter, 'latin' is a very
+ * broad term, including Cyrillic and Greek also since characters from
+ * those scripts share the same design constraints.
+ *
+ * By default, characters from the following Unicode ranges are
+ * assigned to this submodule.
+ *
+ * ```
+ * U+0020 - U+007F // Basic Latin (no control characters)
+ * U+00A0 - U+00FF // Latin-1 Supplement (no control characters)
+ * U+0100 - U+017F // Latin Extended-A
+ * U+0180 - U+024F // Latin Extended-B
+ * U+0250 - U+02AF // IPA Extensions
+ * U+02B0 - U+02FF // Spacing Modifier Letters
+ * U+0300 - U+036F // Combining Diacritical Marks
+ * U+0370 - U+03FF // Greek and Coptic
+ * U+0400 - U+04FF // Cyrillic
+ * U+0500 - U+052F // Cyrillic Supplement
+ * U+1D00 - U+1D7F // Phonetic Extensions
+ * U+1D80 - U+1DBF // Phonetic Extensions Supplement
+ * U+1DC0 - U+1DFF // Combining Diacritical Marks Supplement
+ * U+1E00 - U+1EFF // Latin Extended Additional
+ * U+1F00 - U+1FFF // Greek Extended
+ * U+2000 - U+206F // General Punctuation
+ * U+2070 - U+209F // Superscripts and Subscripts
+ * U+20A0 - U+20CF // Currency Symbols
+ * U+2150 - U+218F // Number Forms
+ * U+2460 - U+24FF // Enclosed Alphanumerics
+ * U+2C60 - U+2C7F // Latin Extended-C
+ * U+2DE0 - U+2DFF // Cyrillic Extended-A
+ * U+2E00 - U+2E7F // Supplemental Punctuation
+ * U+A640 - U+A69F // Cyrillic Extended-B
+ * U+A720 - U+A7FF // Latin Extended-D
+ * U+FB00 - U+FB06 // Alphab. Present. Forms (Latin Ligatures)
+ * U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols
+ * U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement
+ * ```
+ *
+ * FT_AUTOHINTER_SCRIPT_CJK ::
+ * Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old
+ * Vietnamese, and some other scripts.
+ *
+ * By default, characters from the following Unicode ranges are
+ * assigned to this submodule.
+ *
+ * ```
+ * U+1100 - U+11FF // Hangul Jamo
+ * U+2E80 - U+2EFF // CJK Radicals Supplement
+ * U+2F00 - U+2FDF // Kangxi Radicals
+ * U+2FF0 - U+2FFF // Ideographic Description Characters
+ * U+3000 - U+303F // CJK Symbols and Punctuation
+ * U+3040 - U+309F // Hiragana
+ * U+30A0 - U+30FF // Katakana
+ * U+3100 - U+312F // Bopomofo
+ * U+3130 - U+318F // Hangul Compatibility Jamo
+ * U+3190 - U+319F // Kanbun
+ * U+31A0 - U+31BF // Bopomofo Extended
+ * U+31C0 - U+31EF // CJK Strokes
+ * U+31F0 - U+31FF // Katakana Phonetic Extensions
+ * U+3200 - U+32FF // Enclosed CJK Letters and Months
+ * U+3300 - U+33FF // CJK Compatibility
+ * U+3400 - U+4DBF // CJK Unified Ideographs Extension A
+ * U+4DC0 - U+4DFF // Yijing Hexagram Symbols
+ * U+4E00 - U+9FFF // CJK Unified Ideographs
+ * U+A960 - U+A97F // Hangul Jamo Extended-A
+ * U+AC00 - U+D7AF // Hangul Syllables
+ * U+D7B0 - U+D7FF // Hangul Jamo Extended-B
+ * U+F900 - U+FAFF // CJK Compatibility Ideographs
+ * U+FE10 - U+FE1F // Vertical forms
+ * U+FE30 - U+FE4F // CJK Compatibility Forms
+ * U+FF00 - U+FFEF // Halfwidth and Fullwidth Forms
+ * U+1B000 - U+1B0FF // Kana Supplement
+ * U+1D300 - U+1D35F // Tai Xuan Hing Symbols
+ * U+1F200 - U+1F2FF // Enclosed Ideographic Supplement
+ * U+20000 - U+2A6DF // CJK Unified Ideographs Extension B
+ * U+2A700 - U+2B73F // CJK Unified Ideographs Extension C
+ * U+2B740 - U+2B81F // CJK Unified Ideographs Extension D
+ * U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement
+ * ```
+ *
+ * FT_AUTOHINTER_SCRIPT_INDIC ::
+ * Apply the indic auto-hinter, covering all major scripts from the
+ * Indian sub-continent and some other related scripts like Thai, Lao,
+ * or Tibetan.
+ *
+ * By default, characters from the following Unicode ranges are
+ * assigned to this submodule.
+ *
+ * ```
+ * U+0900 - U+0DFF // Indic Range
+ * U+0F00 - U+0FFF // Tibetan
+ * U+1900 - U+194F // Limbu
+ * U+1B80 - U+1BBF // Sundanese
+ * U+A800 - U+A82F // Syloti Nagri
+ * U+ABC0 - U+ABFF // Meetei Mayek
+ * U+11800 - U+118DF // Sharada
+ * ```
+ *
+ * Note that currently Indic support is rudimentary only, missing blue
+ * zone support.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+#define FT_AUTOHINTER_SCRIPT_NONE 0
+#define FT_AUTOHINTER_SCRIPT_LATIN 1
+#define FT_AUTOHINTER_SCRIPT_CJK 2
+#define FT_AUTOHINTER_SCRIPT_INDIC 3
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Prop_GlyphToScriptMap
+ *
+ * @description:
+ * **Experimental only**
+ *
+ * The data exchange structure for the @glyph-to-script-map property.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+ typedef struct FT_Prop_GlyphToScriptMap_
+ {
+ FT_Face face;
+ FT_UShort* map;
+
+ } FT_Prop_GlyphToScriptMap;
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * fallback-script
+ *
+ * @description:
+ * **Experimental only**
+ *
+ * If no auto-hinter script module can be assigned to a glyph, a fallback
+ * script gets assigned to it (see also the @glyph-to-script-map
+ * property). By default, this is @FT_AUTOHINTER_SCRIPT_CJK. Using the
+ * `fallback-script` property, this fallback value can be changed.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * It's important to use the right timing for changing this value: The
+ * creation of the glyph-to-script map that eventually uses the fallback
+ * script value gets triggered either by setting or reading a
+ * face-specific property like @glyph-to-script-map, or by auto-hinting
+ * any glyph from that face. In particular, if you have already created
+ * an @FT_Face structure but not loaded any glyph (using the
+ * auto-hinter), a change of the fallback script will affect this face.
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_UInt fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "fallback-script", &fallback_script );
+ * ```
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * default-script
+ *
+ * @description:
+ * **Experimental only**
+ *
+ * If FreeType gets compiled with `FT_CONFIG_OPTION_USE_HARFBUZZ` to make
+ * the HarfBuzz library access OpenType features for getting better glyph
+ * coverages, this property sets the (auto-fitter) script to be used for
+ * the default (OpenType) script data of a font's GSUB table. Features
+ * for the default script are intended for all scripts not explicitly
+ * handled in GSUB; an example is a 'dlig' feature, containing the
+ * combination of the characters 'T', 'E', and 'L' to form a 'TEL'
+ * ligature.
+ *
+ * By default, this is @FT_AUTOHINTER_SCRIPT_LATIN. Using the
+ * `default-script` property, this default value can be changed.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * It's important to use the right timing for changing this value: The
+ * creation of the glyph-to-script map that eventually uses the default
+ * script value gets triggered either by setting or reading a
+ * face-specific property like @glyph-to-script-map, or by auto-hinting
+ * any glyph from that face. In particular, if you have already created
+ * an @FT_Face structure but not loaded any glyph (using the
+ * auto-hinter), a change of the default script will affect this face.
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_UInt default_script = FT_AUTOHINTER_SCRIPT_NONE;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "default-script", &default_script );
+ * ```
+ *
+ * @since:
+ * 2.5.3
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * increase-x-height
+ *
+ * @description:
+ * For ppem values in the range 6~<= ppem <= `increase-x-height`, round
+ * up the font's x~height much more often than normally. If the value is
+ * set to~0, which is the default, this feature is switched off. Use
+ * this property to improve the legibility of small font sizes if
+ * necessary.
+ *
+ * @note:
+ * This property can be used with @FT_Property_Get also.
+ *
+ * Set this value right after calling @FT_Set_Char_Size, but before
+ * loading any glyph (using the auto-hinter).
+ *
+ * @example:
+ * ```
+ * FT_Library library;
+ * FT_Face face;
+ * FT_Prop_IncreaseXHeight prop;
+ *
+ *
+ * FT_Init_FreeType( &library );
+ * FT_New_Face( library, "foo.ttf", 0, &face );
+ * FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 );
+ *
+ * prop.face = face;
+ * prop.limit = 14;
+ *
+ * FT_Property_Set( library, "autofitter",
+ * "increase-x-height", &prop );
+ * ```
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Prop_IncreaseXHeight
+ *
+ * @description:
+ * The data exchange structure for the @increase-x-height property.
+ *
+ */
+ typedef struct FT_Prop_IncreaseXHeight_
+ {
+ FT_Face face;
+ FT_UInt limit;
+
+ } FT_Prop_IncreaseXHeight;
+
+
+ /**************************************************************************
+ *
+ * @property:
+ * warping
+ *
+ * @description:
+ * **Obsolete**
+ *
+ * This property was always experimental and probably never worked
+ * correctly. It was entirely removed from the FreeType~2 sources. This
+ * entry is only here for historical reference.
+ *
+ * Warping only worked in 'normal' auto-hinting mode replacing it. The
+ * idea of the code was to slightly scale and shift a glyph along the
+ * non-hinted dimension (which is usually the horizontal axis) so that as
+ * much of its segments were aligned (more or less) to the grid. To find
+ * out a glyph's optimal scaling and shifting value, various parameter
+ * combinations were tried and scored.
+ *
+ * @since:
+ * 2.6
+ *
+ */
+
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* FTDRIVER_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/fterrdef.h b/Client/ThirdParty/freetype/include/freetype/fterrdef.h
new file mode 100644
index 0000000..6e9c4cc
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/fterrdef.h
@@ -0,0 +1,279 @@
+/****************************************************************************
+ *
+ * fterrdef.h
+ *
+ * FreeType error codes (specification).
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * error_code_values
+ *
+ * @title:
+ * Error Code Values
+ *
+ * @abstract:
+ * All possible error codes returned by FreeType functions.
+ *
+ * @description:
+ * The list below is taken verbatim from the file `fterrdef.h` (loaded
+ * automatically by including `FT_FREETYPE_H`). The first argument of the
+ * `FT_ERROR_DEF_` macro is the error label; by default, the prefix
+ * `FT_Err_` gets added so that you get error names like
+ * `FT_Err_Cannot_Open_Resource`. The second argument is the error code,
+ * and the last argument an error string, which is not used by FreeType.
+ *
+ * Within your application you should **only** use error names and
+ * **never** its numeric values! The latter might (and actually do)
+ * change in forthcoming FreeType versions.
+ *
+ * Macro `FT_NOERRORDEF_` defines `FT_Err_Ok`, which is always zero. See
+ * the 'Error Enumerations' subsection how to automatically generate a
+ * list of error strings.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Err_XXX
+ *
+ */
+
+ /* generic errors */
+
+ FT_NOERRORDEF_( Ok, 0x00,
+ "no error" )
+
+ FT_ERRORDEF_( Cannot_Open_Resource, 0x01,
+ "cannot open resource" )
+ FT_ERRORDEF_( Unknown_File_Format, 0x02,
+ "unknown file format" )
+ FT_ERRORDEF_( Invalid_File_Format, 0x03,
+ "broken file" )
+ FT_ERRORDEF_( Invalid_Version, 0x04,
+ "invalid FreeType version" )
+ FT_ERRORDEF_( Lower_Module_Version, 0x05,
+ "module version is too low" )
+ FT_ERRORDEF_( Invalid_Argument, 0x06,
+ "invalid argument" )
+ FT_ERRORDEF_( Unimplemented_Feature, 0x07,
+ "unimplemented feature" )
+ FT_ERRORDEF_( Invalid_Table, 0x08,
+ "broken table" )
+ FT_ERRORDEF_( Invalid_Offset, 0x09,
+ "broken offset within table" )
+ FT_ERRORDEF_( Array_Too_Large, 0x0A,
+ "array allocation size too large" )
+ FT_ERRORDEF_( Missing_Module, 0x0B,
+ "missing module" )
+ FT_ERRORDEF_( Missing_Property, 0x0C,
+ "missing property" )
+
+ /* glyph/character errors */
+
+ FT_ERRORDEF_( Invalid_Glyph_Index, 0x10,
+ "invalid glyph index" )
+ FT_ERRORDEF_( Invalid_Character_Code, 0x11,
+ "invalid character code" )
+ FT_ERRORDEF_( Invalid_Glyph_Format, 0x12,
+ "unsupported glyph image format" )
+ FT_ERRORDEF_( Cannot_Render_Glyph, 0x13,
+ "cannot render this glyph format" )
+ FT_ERRORDEF_( Invalid_Outline, 0x14,
+ "invalid outline" )
+ FT_ERRORDEF_( Invalid_Composite, 0x15,
+ "invalid composite glyph" )
+ FT_ERRORDEF_( Too_Many_Hints, 0x16,
+ "too many hints" )
+ FT_ERRORDEF_( Invalid_Pixel_Size, 0x17,
+ "invalid pixel size" )
+
+ /* handle errors */
+
+ FT_ERRORDEF_( Invalid_Handle, 0x20,
+ "invalid object handle" )
+ FT_ERRORDEF_( Invalid_Library_Handle, 0x21,
+ "invalid library handle" )
+ FT_ERRORDEF_( Invalid_Driver_Handle, 0x22,
+ "invalid module handle" )
+ FT_ERRORDEF_( Invalid_Face_Handle, 0x23,
+ "invalid face handle" )
+ FT_ERRORDEF_( Invalid_Size_Handle, 0x24,
+ "invalid size handle" )
+ FT_ERRORDEF_( Invalid_Slot_Handle, 0x25,
+ "invalid glyph slot handle" )
+ FT_ERRORDEF_( Invalid_CharMap_Handle, 0x26,
+ "invalid charmap handle" )
+ FT_ERRORDEF_( Invalid_Cache_Handle, 0x27,
+ "invalid cache manager handle" )
+ FT_ERRORDEF_( Invalid_Stream_Handle, 0x28,
+ "invalid stream handle" )
+
+ /* driver errors */
+
+ FT_ERRORDEF_( Too_Many_Drivers, 0x30,
+ "too many modules" )
+ FT_ERRORDEF_( Too_Many_Extensions, 0x31,
+ "too many extensions" )
+
+ /* memory errors */
+
+ FT_ERRORDEF_( Out_Of_Memory, 0x40,
+ "out of memory" )
+ FT_ERRORDEF_( Unlisted_Object, 0x41,
+ "unlisted object" )
+
+ /* stream errors */
+
+ FT_ERRORDEF_( Cannot_Open_Stream, 0x51,
+ "cannot open stream" )
+ FT_ERRORDEF_( Invalid_Stream_Seek, 0x52,
+ "invalid stream seek" )
+ FT_ERRORDEF_( Invalid_Stream_Skip, 0x53,
+ "invalid stream skip" )
+ FT_ERRORDEF_( Invalid_Stream_Read, 0x54,
+ "invalid stream read" )
+ FT_ERRORDEF_( Invalid_Stream_Operation, 0x55,
+ "invalid stream operation" )
+ FT_ERRORDEF_( Invalid_Frame_Operation, 0x56,
+ "invalid frame operation" )
+ FT_ERRORDEF_( Nested_Frame_Access, 0x57,
+ "nested frame access" )
+ FT_ERRORDEF_( Invalid_Frame_Read, 0x58,
+ "invalid frame read" )
+
+ /* raster errors */
+
+ FT_ERRORDEF_( Raster_Uninitialized, 0x60,
+ "raster uninitialized" )
+ FT_ERRORDEF_( Raster_Corrupted, 0x61,
+ "raster corrupted" )
+ FT_ERRORDEF_( Raster_Overflow, 0x62,
+ "raster overflow" )
+ FT_ERRORDEF_( Raster_Negative_Height, 0x63,
+ "negative height while rastering" )
+
+ /* cache errors */
+
+ FT_ERRORDEF_( Too_Many_Caches, 0x70,
+ "too many registered caches" )
+
+ /* TrueType and SFNT errors */
+
+ FT_ERRORDEF_( Invalid_Opcode, 0x80,
+ "invalid opcode" )
+ FT_ERRORDEF_( Too_Few_Arguments, 0x81,
+ "too few arguments" )
+ FT_ERRORDEF_( Stack_Overflow, 0x82,
+ "stack overflow" )
+ FT_ERRORDEF_( Code_Overflow, 0x83,
+ "code overflow" )
+ FT_ERRORDEF_( Bad_Argument, 0x84,
+ "bad argument" )
+ FT_ERRORDEF_( Divide_By_Zero, 0x85,
+ "division by zero" )
+ FT_ERRORDEF_( Invalid_Reference, 0x86,
+ "invalid reference" )
+ FT_ERRORDEF_( Debug_OpCode, 0x87,
+ "found debug opcode" )
+ FT_ERRORDEF_( ENDF_In_Exec_Stream, 0x88,
+ "found ENDF opcode in execution stream" )
+ FT_ERRORDEF_( Nested_DEFS, 0x89,
+ "nested DEFS" )
+ FT_ERRORDEF_( Invalid_CodeRange, 0x8A,
+ "invalid code range" )
+ FT_ERRORDEF_( Execution_Too_Long, 0x8B,
+ "execution context too long" )
+ FT_ERRORDEF_( Too_Many_Function_Defs, 0x8C,
+ "too many function definitions" )
+ FT_ERRORDEF_( Too_Many_Instruction_Defs, 0x8D,
+ "too many instruction definitions" )
+ FT_ERRORDEF_( Table_Missing, 0x8E,
+ "SFNT font table missing" )
+ FT_ERRORDEF_( Horiz_Header_Missing, 0x8F,
+ "horizontal header (hhea) table missing" )
+ FT_ERRORDEF_( Locations_Missing, 0x90,
+ "locations (loca) table missing" )
+ FT_ERRORDEF_( Name_Table_Missing, 0x91,
+ "name table missing" )
+ FT_ERRORDEF_( CMap_Table_Missing, 0x92,
+ "character map (cmap) table missing" )
+ FT_ERRORDEF_( Hmtx_Table_Missing, 0x93,
+ "horizontal metrics (hmtx) table missing" )
+ FT_ERRORDEF_( Post_Table_Missing, 0x94,
+ "PostScript (post) table missing" )
+ FT_ERRORDEF_( Invalid_Horiz_Metrics, 0x95,
+ "invalid horizontal metrics" )
+ FT_ERRORDEF_( Invalid_CharMap_Format, 0x96,
+ "invalid character map (cmap) format" )
+ FT_ERRORDEF_( Invalid_PPem, 0x97,
+ "invalid ppem value" )
+ FT_ERRORDEF_( Invalid_Vert_Metrics, 0x98,
+ "invalid vertical metrics" )
+ FT_ERRORDEF_( Could_Not_Find_Context, 0x99,
+ "could not find context" )
+ FT_ERRORDEF_( Invalid_Post_Table_Format, 0x9A,
+ "invalid PostScript (post) table format" )
+ FT_ERRORDEF_( Invalid_Post_Table, 0x9B,
+ "invalid PostScript (post) table" )
+ FT_ERRORDEF_( DEF_In_Glyf_Bytecode, 0x9C,
+ "found FDEF or IDEF opcode in glyf bytecode" )
+ FT_ERRORDEF_( Missing_Bitmap, 0x9D,
+ "missing bitmap in strike" )
+
+ /* CFF, CID, and Type 1 errors */
+
+ FT_ERRORDEF_( Syntax_Error, 0xA0,
+ "opcode syntax error" )
+ FT_ERRORDEF_( Stack_Underflow, 0xA1,
+ "argument stack underflow" )
+ FT_ERRORDEF_( Ignore, 0xA2,
+ "ignore" )
+ FT_ERRORDEF_( No_Unicode_Glyph_Name, 0xA3,
+ "no Unicode glyph name found" )
+ FT_ERRORDEF_( Glyph_Too_Big, 0xA4,
+ "glyph too big for hinting" )
+
+ /* BDF errors */
+
+ FT_ERRORDEF_( Missing_Startfont_Field, 0xB0,
+ "`STARTFONT' field missing" )
+ FT_ERRORDEF_( Missing_Font_Field, 0xB1,
+ "`FONT' field missing" )
+ FT_ERRORDEF_( Missing_Size_Field, 0xB2,
+ "`SIZE' field missing" )
+ FT_ERRORDEF_( Missing_Fontboundingbox_Field, 0xB3,
+ "`FONTBOUNDINGBOX' field missing" )
+ FT_ERRORDEF_( Missing_Chars_Field, 0xB4,
+ "`CHARS' field missing" )
+ FT_ERRORDEF_( Missing_Startchar_Field, 0xB5,
+ "`STARTCHAR' field missing" )
+ FT_ERRORDEF_( Missing_Encoding_Field, 0xB6,
+ "`ENCODING' field missing" )
+ FT_ERRORDEF_( Missing_Bbx_Field, 0xB7,
+ "`BBX' field missing" )
+ FT_ERRORDEF_( Bbx_Too_Big, 0xB8,
+ "`BBX' too big" )
+ FT_ERRORDEF_( Corrupted_Font_Header, 0xB9,
+ "Font header corrupted or missing fields" )
+ FT_ERRORDEF_( Corrupted_Font_Glyphs, 0xBA,
+ "Font glyphs corrupted or missing fields" )
+
+ /* */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/fterrors.h b/Client/ThirdParty/freetype/include/freetype/fterrors.h
new file mode 100644
index 0000000..151941d
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/fterrors.h
@@ -0,0 +1,296 @@
+/****************************************************************************
+ *
+ * fterrors.h
+ *
+ * FreeType error code handling (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * error_enumerations
+ *
+ * @title:
+ * Error Enumerations
+ *
+ * @abstract:
+ * How to handle errors and error strings.
+ *
+ * @description:
+ * The header file `fterrors.h` (which is automatically included by
+ * `freetype.h` defines the handling of FreeType's enumeration
+ * constants. It can also be used to generate error message strings
+ * with a small macro trick explained below.
+ *
+ * **Error Formats**
+ *
+ * The configuration macro `FT_CONFIG_OPTION_USE_MODULE_ERRORS` can be
+ * defined in `ftoption.h` in order to make the higher byte indicate the
+ * module where the error has happened (this is not compatible with
+ * standard builds of FreeType~2, however). See the file `ftmoderr.h`
+ * for more details.
+ *
+ * **Error Message Strings**
+ *
+ * Error definitions are set up with special macros that allow client
+ * applications to build a table of error message strings. The strings
+ * are not included in a normal build of FreeType~2 to save space (most
+ * client applications do not use them).
+ *
+ * To do so, you have to define the following macros before including
+ * this file.
+ *
+ * ```
+ * FT_ERROR_START_LIST
+ * ```
+ *
+ * This macro is called before anything else to define the start of the
+ * error list. It is followed by several `FT_ERROR_DEF` calls.
+ *
+ * ```
+ * FT_ERROR_DEF( e, v, s )
+ * ```
+ *
+ * This macro is called to define one single error. 'e' is the error
+ * code identifier (e.g., `Invalid_Argument`), 'v' is the error's
+ * numerical value, and 's' is the corresponding error string.
+ *
+ * ```
+ * FT_ERROR_END_LIST
+ * ```
+ *
+ * This macro ends the list.
+ *
+ * Additionally, you have to undefine `FTERRORS_H_` before #including
+ * this file.
+ *
+ * Here is a simple example.
+ *
+ * ```
+ * #undef FTERRORS_H_
+ * #define FT_ERRORDEF( e, v, s ) { e, s },
+ * #define FT_ERROR_START_LIST {
+ * #define FT_ERROR_END_LIST { 0, NULL } };
+ *
+ * const struct
+ * {
+ * int err_code;
+ * const char* err_msg;
+ * } ft_errors[] =
+ *
+ * #include <freetype/fterrors.h>
+ * ```
+ *
+ * An alternative to using an array is a switch statement.
+ *
+ * ```
+ * #undef FTERRORS_H_
+ * #define FT_ERROR_START_LIST switch ( error_code ) {
+ * #define FT_ERRORDEF( e, v, s ) case v: return s;
+ * #define FT_ERROR_END_LIST }
+ * ```
+ *
+ * If you use `FT_CONFIG_OPTION_USE_MODULE_ERRORS`, `error_code` should
+ * be replaced with `FT_ERROR_BASE(error_code)` in the last example.
+ */
+
+ /* */
+
+ /* In previous FreeType versions we used `__FTERRORS_H__`. However, */
+ /* using two successive underscores in a non-system symbol name */
+ /* violates the C (and C++) standard, so it was changed to the */
+ /* current form. In spite of this, we have to make */
+ /* */
+ /* ``` */
+ /* #undefine __FTERRORS_H__ */
+ /* ``` */
+ /* */
+ /* work for backward compatibility. */
+ /* */
+#if !( defined( FTERRORS_H_ ) && defined ( __FTERRORS_H__ ) )
+#define FTERRORS_H_
+#define __FTERRORS_H__
+
+
+ /* include module base error codes */
+#include <freetype/ftmoderr.h>
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** SETUP MACROS *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#undef FT_NEED_EXTERN_C
+
+
+ /* FT_ERR_PREFIX is used as a prefix for error identifiers. */
+ /* By default, we use `FT_Err_`. */
+ /* */
+#ifndef FT_ERR_PREFIX
+#define FT_ERR_PREFIX FT_Err_
+#endif
+
+
+ /* FT_ERR_BASE is used as the base for module-specific errors. */
+ /* */
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+
+#ifndef FT_ERR_BASE
+#define FT_ERR_BASE FT_Mod_Err_Base
+#endif
+
+#else
+
+#undef FT_ERR_BASE
+#define FT_ERR_BASE 0
+
+#endif /* FT_CONFIG_OPTION_USE_MODULE_ERRORS */
+
+
+ /* If FT_ERRORDEF is not defined, we need to define a simple */
+ /* enumeration type. */
+ /* */
+#ifndef FT_ERRORDEF
+
+#define FT_INCLUDE_ERR_PROTOS
+
+#define FT_ERRORDEF( e, v, s ) e = v,
+#define FT_ERROR_START_LIST enum {
+#define FT_ERROR_END_LIST FT_ERR_CAT( FT_ERR_PREFIX, Max ) };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+ extern "C" {
+#endif
+
+#endif /* !FT_ERRORDEF */
+
+
+ /* this macro is used to define an error */
+#define FT_ERRORDEF_( e, v, s ) \
+ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )
+
+ /* this is only used for <module>_Err_Ok, which must be 0! */
+#define FT_NOERRORDEF_( e, v, s ) \
+ FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )
+
+
+#ifdef FT_ERROR_START_LIST
+ FT_ERROR_START_LIST
+#endif
+
+
+ /* now include the error codes */
+#include <freetype/fterrdef.h>
+
+
+#ifdef FT_ERROR_END_LIST
+ FT_ERROR_END_LIST
+#endif
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** SIMPLE CLEANUP *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+#ifdef FT_NEED_EXTERN_C
+ }
+#endif
+
+#undef FT_ERROR_START_LIST
+#undef FT_ERROR_END_LIST
+
+#undef FT_ERRORDEF
+#undef FT_ERRORDEF_
+#undef FT_NOERRORDEF_
+
+#undef FT_NEED_EXTERN_C
+#undef FT_ERR_BASE
+
+ /* FT_ERR_PREFIX is needed internally */
+#ifndef FT2_BUILD_LIBRARY
+#undef FT_ERR_PREFIX
+#endif
+
+ /* FT_INCLUDE_ERR_PROTOS: Control whether function prototypes should be */
+ /* included with */
+ /* */
+ /* #include <freetype/fterrors.h> */
+ /* */
+ /* This is only true where `FT_ERRORDEF` is */
+ /* undefined. */
+ /* */
+ /* FT_ERR_PROTOS_DEFINED: Actual multiple-inclusion protection of */
+ /* `fterrors.h`. */
+#ifdef FT_INCLUDE_ERR_PROTOS
+#undef FT_INCLUDE_ERR_PROTOS
+
+#ifndef FT_ERR_PROTOS_DEFINED
+#define FT_ERR_PROTOS_DEFINED
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Error_String
+ *
+ * @description:
+ * Retrieve the description of a valid FreeType error code.
+ *
+ * @input:
+ * error_code ::
+ * A valid FreeType error code.
+ *
+ * @return:
+ * A C~string or `NULL`, if any error occurred.
+ *
+ * @note:
+ * FreeType has to be compiled with `FT_CONFIG_OPTION_ERROR_STRINGS` or
+ * `FT_DEBUG_LEVEL_ERROR` to get meaningful descriptions.
+ * 'error_string' will be `NULL` otherwise.
+ *
+ * Module identification will be ignored:
+ *
+ * ```c
+ * strcmp( FT_Error_String( FT_Err_Unknown_File_Format ),
+ * FT_Error_String( BDF_Err_Unknown_File_Format ) ) == 0;
+ * ```
+ */
+ FT_EXPORT( const char* )
+ FT_Error_String( FT_Error error_code );
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* FT_ERR_PROTOS_DEFINED */
+
+#endif /* FT_INCLUDE_ERR_PROTOS */
+
+#endif /* !(FTERRORS_H_ && __FTERRORS_H__) */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftfntfmt.h b/Client/ThirdParty/freetype/include/freetype/ftfntfmt.h
new file mode 100644
index 0000000..8e68a4a
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftfntfmt.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+ *
+ * ftfntfmt.h
+ *
+ * Support functions for font formats.
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTFNTFMT_H_
+#define FTFNTFMT_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * font_formats
+ *
+ * @title:
+ * Font Formats
+ *
+ * @abstract:
+ * Getting the font format.
+ *
+ * @description:
+ * The single function in this section can be used to get the font format.
+ * Note that this information is not needed normally; however, there are
+ * special cases (like in PDF devices) where it is important to
+ * differentiate, in spite of FreeType's uniform API.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Font_Format
+ *
+ * @description:
+ * Return a string describing the format of a given face. Possible values
+ * are 'TrueType', 'Type~1', 'BDF', 'PCF', 'Type~42', 'CID~Type~1', 'CFF',
+ * 'PFR', and 'Windows~FNT'.
+ *
+ * The return value is suitable to be used as an X11 FONT_PROPERTY.
+ *
+ * @input:
+ * face ::
+ * Input face handle.
+ *
+ * @return:
+ * Font format string. `NULL` in case of error.
+ *
+ * @note:
+ * A deprecated name for the same function is `FT_Get_X11_Font_Format`.
+ */
+ FT_EXPORT( const char* )
+ FT_Get_Font_Format( FT_Face face );
+
+
+ /* deprecated */
+ FT_EXPORT( const char* )
+ FT_Get_X11_Font_Format( FT_Face face );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTFNTFMT_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftgasp.h b/Client/ThirdParty/freetype/include/freetype/ftgasp.h
new file mode 100644
index 0000000..76c45eb
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftgasp.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+ *
+ * ftgasp.h
+ *
+ * Access of TrueType's 'gasp' table (specification).
+ *
+ * Copyright (C) 2007-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTGASP_H_
+#define FTGASP_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * gasp_table
+ *
+ * @title:
+ * Gasp Table
+ *
+ * @abstract:
+ * Retrieving TrueType 'gasp' table entries.
+ *
+ * @description:
+ * The function @FT_Get_Gasp can be used to query a TrueType or OpenType
+ * font for specific entries in its 'gasp' table, if any. This is mainly
+ * useful when implementing native TrueType hinting with the bytecode
+ * interpreter to duplicate the Windows text rendering results.
+ */
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_GASP_XXX
+ *
+ * @description:
+ * A list of values and/or bit-flags returned by the @FT_Get_Gasp
+ * function.
+ *
+ * @values:
+ * FT_GASP_NO_TABLE ::
+ * This special value means that there is no GASP table in this face.
+ * It is up to the client to decide what to do.
+ *
+ * FT_GASP_DO_GRIDFIT ::
+ * Grid-fitting and hinting should be performed at the specified ppem.
+ * This **really** means TrueType bytecode interpretation. If this bit
+ * is not set, no hinting gets applied.
+ *
+ * FT_GASP_DO_GRAY ::
+ * Anti-aliased rendering should be performed at the specified ppem.
+ * If not set, do monochrome rendering.
+ *
+ * FT_GASP_SYMMETRIC_SMOOTHING ::
+ * If set, smoothing along multiple axes must be used with ClearType.
+ *
+ * FT_GASP_SYMMETRIC_GRIDFIT ::
+ * Grid-fitting must be used with ClearType's symmetric smoothing.
+ *
+ * @note:
+ * The bit-flags `FT_GASP_DO_GRIDFIT` and `FT_GASP_DO_GRAY` are to be
+ * used for standard font rasterization only. Independently of that,
+ * `FT_GASP_SYMMETRIC_SMOOTHING` and `FT_GASP_SYMMETRIC_GRIDFIT` are to
+ * be used if ClearType is enabled (and `FT_GASP_DO_GRIDFIT` and
+ * `FT_GASP_DO_GRAY` are consequently ignored).
+ *
+ * 'ClearType' is Microsoft's implementation of LCD rendering, partly
+ * protected by patents.
+ *
+ * @since:
+ * 2.3.0
+ */
+#define FT_GASP_NO_TABLE -1
+#define FT_GASP_DO_GRIDFIT 0x01
+#define FT_GASP_DO_GRAY 0x02
+#define FT_GASP_SYMMETRIC_GRIDFIT 0x04
+#define FT_GASP_SYMMETRIC_SMOOTHING 0x08
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Gasp
+ *
+ * @description:
+ * For a TrueType or OpenType font file, return the rasterizer behaviour
+ * flags from the font's 'gasp' table corresponding to a given character
+ * pixel size.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * ppem ::
+ * The vertical character pixel size.
+ *
+ * @return:
+ * Bit flags (see @FT_GASP_XXX), or @FT_GASP_NO_TABLE if there is no
+ * 'gasp' table in the face.
+ *
+ * @note:
+ * If you want to use the MM functionality of OpenType variation fonts
+ * (i.e., using @FT_Set_Var_Design_Coordinates and friends), call this
+ * function **after** setting an instance since the return values can
+ * change.
+ *
+ * @since:
+ * 2.3.0
+ */
+ FT_EXPORT( FT_Int )
+ FT_Get_Gasp( FT_Face face,
+ FT_UInt ppem );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTGASP_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftglyph.h b/Client/ThirdParty/freetype/include/freetype/ftglyph.h
new file mode 100644
index 0000000..479267b
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftglyph.h
@@ -0,0 +1,664 @@
+/****************************************************************************
+ *
+ * ftglyph.h
+ *
+ * FreeType convenience functions to handle glyphs (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file contains the definition of several convenience functions that
+ * can be used by client applications to easily retrieve glyph bitmaps and
+ * outlines from a given face.
+ *
+ * These functions should be optional if you are writing a font server or
+ * text layout engine on top of FreeType. However, they are pretty handy
+ * for many other simple uses of the library.
+ *
+ */
+
+
+#ifndef FTGLYPH_H_
+#define FTGLYPH_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * glyph_management
+ *
+ * @title:
+ * Glyph Management
+ *
+ * @abstract:
+ * Generic interface to manage individual glyph data.
+ *
+ * @description:
+ * This section contains definitions used to manage glyph data through
+ * generic @FT_Glyph objects. Each of them can contain a bitmap,
+ * a vector outline, or even images in other formats. These objects are
+ * detached from @FT_Face, contrary to @FT_GlyphSlot.
+ *
+ */
+
+
+ /* forward declaration to a private type */
+ typedef struct FT_Glyph_Class_ FT_Glyph_Class;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Glyph
+ *
+ * @description:
+ * Handle to an object used to model generic glyph images. It is a
+ * pointer to the @FT_GlyphRec structure and can contain a glyph bitmap
+ * or pointer.
+ *
+ * @note:
+ * Glyph objects are not owned by the library. You must thus release
+ * them manually (through @FT_Done_Glyph) _before_ calling
+ * @FT_Done_FreeType.
+ */
+ typedef struct FT_GlyphRec_* FT_Glyph;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_GlyphRec
+ *
+ * @description:
+ * The root glyph structure contains a given glyph image plus its advance
+ * width in 16.16 fixed-point format.
+ *
+ * @fields:
+ * library ::
+ * A handle to the FreeType library object.
+ *
+ * clazz ::
+ * A pointer to the glyph's class. Private.
+ *
+ * format ::
+ * The format of the glyph's image.
+ *
+ * advance ::
+ * A 16.16 vector that gives the glyph's advance width.
+ */
+ typedef struct FT_GlyphRec_
+ {
+ FT_Library library;
+ const FT_Glyph_Class* clazz;
+ FT_Glyph_Format format;
+ FT_Vector advance;
+
+ } FT_GlyphRec;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_BitmapGlyph
+ *
+ * @description:
+ * A handle to an object used to model a bitmap glyph image. This is a
+ * sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec.
+ */
+ typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_BitmapGlyphRec
+ *
+ * @description:
+ * A structure used for bitmap glyph images. This really is a
+ * 'sub-class' of @FT_GlyphRec.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_Glyph fields.
+ *
+ * left ::
+ * The left-side bearing, i.e., the horizontal distance from the
+ * current pen position to the left border of the glyph bitmap.
+ *
+ * top ::
+ * The top-side bearing, i.e., the vertical distance from the current
+ * pen position to the top border of the glyph bitmap. This distance
+ * is positive for upwards~y!
+ *
+ * bitmap ::
+ * A descriptor for the bitmap.
+ *
+ * @note:
+ * You can typecast an @FT_Glyph to @FT_BitmapGlyph if you have
+ * `glyph->format == FT_GLYPH_FORMAT_BITMAP`. This lets you access the
+ * bitmap's contents easily.
+ *
+ * The corresponding pixel buffer is always owned by @FT_BitmapGlyph and
+ * is thus created and destroyed with it.
+ */
+ typedef struct FT_BitmapGlyphRec_
+ {
+ FT_GlyphRec root;
+ FT_Int left;
+ FT_Int top;
+ FT_Bitmap bitmap;
+
+ } FT_BitmapGlyphRec;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_OutlineGlyph
+ *
+ * @description:
+ * A handle to an object used to model an outline glyph image. This is a
+ * sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec.
+ */
+ typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_OutlineGlyphRec
+ *
+ * @description:
+ * A structure used for outline (vectorial) glyph images. This really is
+ * a 'sub-class' of @FT_GlyphRec.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_Glyph fields.
+ *
+ * outline ::
+ * A descriptor for the outline.
+ *
+ * @note:
+ * You can typecast an @FT_Glyph to @FT_OutlineGlyph if you have
+ * `glyph->format == FT_GLYPH_FORMAT_OUTLINE`. This lets you access the
+ * outline's content easily.
+ *
+ * As the outline is extracted from a glyph slot, its coordinates are
+ * expressed normally in 26.6 pixels, unless the flag @FT_LOAD_NO_SCALE
+ * was used in @FT_Load_Glyph or @FT_Load_Char.
+ *
+ * The outline's tables are always owned by the object and are destroyed
+ * with it.
+ */
+ typedef struct FT_OutlineGlyphRec_
+ {
+ FT_GlyphRec root;
+ FT_Outline outline;
+
+ } FT_OutlineGlyphRec;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Glyph
+ *
+ * @description:
+ * A function used to create a new empty glyph image. Note that the
+ * created @FT_Glyph object must be released with @FT_Done_Glyph.
+ *
+ * @input:
+ * library ::
+ * A handle to the FreeType library object.
+ *
+ * format ::
+ * The format of the glyph's image.
+ *
+ * @output:
+ * aglyph ::
+ * A handle to the glyph object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Glyph( FT_Library library,
+ FT_Glyph_Format format,
+ FT_Glyph *aglyph );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Glyph
+ *
+ * @description:
+ * A function used to extract a glyph image from a slot. Note that the
+ * created @FT_Glyph object must be released with @FT_Done_Glyph.
+ *
+ * @input:
+ * slot ::
+ * A handle to the source glyph slot.
+ *
+ * @output:
+ * aglyph ::
+ * A handle to the glyph object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Because `*aglyph->advance.x` and `*aglyph->advance.y` are 16.16
+ * fixed-point numbers, `slot->advance.x` and `slot->advance.y` (which
+ * are in 26.6 fixed-point format) must be in the range ]-32768;32768[.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Glyph( FT_GlyphSlot slot,
+ FT_Glyph *aglyph );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Copy
+ *
+ * @description:
+ * A function used to copy a glyph image. Note that the created
+ * @FT_Glyph object must be released with @FT_Done_Glyph.
+ *
+ * @input:
+ * source ::
+ * A handle to the source glyph object.
+ *
+ * @output:
+ * target ::
+ * A handle to the target glyph object. 0~in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_Copy( FT_Glyph source,
+ FT_Glyph *target );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Transform
+ *
+ * @description:
+ * Transform a glyph image if its format is scalable.
+ *
+ * @inout:
+ * glyph ::
+ * A handle to the target glyph object.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to a 2x2 matrix to apply.
+ *
+ * delta ::
+ * A pointer to a 2d vector to apply. Coordinates are expressed in
+ * 1/64th of a pixel.
+ *
+ * @return:
+ * FreeType error code (if not 0, the glyph format is not scalable).
+ *
+ * @note:
+ * The 2x2 transformation matrix is also applied to the glyph's advance
+ * vector.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_Transform( FT_Glyph glyph,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Glyph_BBox_Mode
+ *
+ * @description:
+ * The mode how the values of @FT_Glyph_Get_CBox are returned.
+ *
+ * @values:
+ * FT_GLYPH_BBOX_UNSCALED ::
+ * Return unscaled font units.
+ *
+ * FT_GLYPH_BBOX_SUBPIXELS ::
+ * Return unfitted 26.6 coordinates.
+ *
+ * FT_GLYPH_BBOX_GRIDFIT ::
+ * Return grid-fitted 26.6 coordinates.
+ *
+ * FT_GLYPH_BBOX_TRUNCATE ::
+ * Return coordinates in integer pixels.
+ *
+ * FT_GLYPH_BBOX_PIXELS ::
+ * Return grid-fitted pixel coordinates.
+ */
+ typedef enum FT_Glyph_BBox_Mode_
+ {
+ FT_GLYPH_BBOX_UNSCALED = 0,
+ FT_GLYPH_BBOX_SUBPIXELS = 0,
+ FT_GLYPH_BBOX_GRIDFIT = 1,
+ FT_GLYPH_BBOX_TRUNCATE = 2,
+ FT_GLYPH_BBOX_PIXELS = 3
+
+ } FT_Glyph_BBox_Mode;
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Glyph_BBox_Mode` values instead */
+#define ft_glyph_bbox_unscaled FT_GLYPH_BBOX_UNSCALED
+#define ft_glyph_bbox_subpixels FT_GLYPH_BBOX_SUBPIXELS
+#define ft_glyph_bbox_gridfit FT_GLYPH_BBOX_GRIDFIT
+#define ft_glyph_bbox_truncate FT_GLYPH_BBOX_TRUNCATE
+#define ft_glyph_bbox_pixels FT_GLYPH_BBOX_PIXELS
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Get_CBox
+ *
+ * @description:
+ * Return a glyph's 'control box'. The control box encloses all the
+ * outline's points, including Bezier control points. Though it
+ * coincides with the exact bounding box for most glyphs, it can be
+ * slightly larger in some situations (like when rotating an outline that
+ * contains Bezier outside arcs).
+ *
+ * Computing the control box is very fast, while getting the bounding box
+ * can take much more time as it needs to walk over all segments and arcs
+ * in the outline. To get the latter, you can use the 'ftbbox'
+ * component, which is dedicated to this single task.
+ *
+ * @input:
+ * glyph ::
+ * A handle to the source glyph object.
+ *
+ * mode ::
+ * The mode that indicates how to interpret the returned bounding box
+ * values.
+ *
+ * @output:
+ * acbox ::
+ * The glyph coordinate bounding box. Coordinates are expressed in
+ * 1/64th of pixels if it is grid-fitted.
+ *
+ * @note:
+ * Coordinates are relative to the glyph origin, using the y~upwards
+ * convention.
+ *
+ * If the glyph has been loaded with @FT_LOAD_NO_SCALE, `bbox_mode` must
+ * be set to @FT_GLYPH_BBOX_UNSCALED to get unscaled font units in 26.6
+ * pixel format. The value @FT_GLYPH_BBOX_SUBPIXELS is another name for
+ * this constant.
+ *
+ * If the font is tricky and the glyph has been loaded with
+ * @FT_LOAD_NO_SCALE, the resulting CBox is meaningless. To get
+ * reasonable values for the CBox it is necessary to load the glyph at a
+ * large ppem value (so that the hinting instructions can properly shift
+ * and scale the subglyphs), then extracting the CBox, which can be
+ * eventually converted back to font units.
+ *
+ * Note that the maximum coordinates are exclusive, which means that one
+ * can compute the width and height of the glyph image (be it in integer
+ * or 26.6 pixels) as:
+ *
+ * ```
+ * width = bbox.xMax - bbox.xMin;
+ * height = bbox.yMax - bbox.yMin;
+ * ```
+ *
+ * Note also that for 26.6 coordinates, if `bbox_mode` is set to
+ * @FT_GLYPH_BBOX_GRIDFIT, the coordinates will also be grid-fitted,
+ * which corresponds to:
+ *
+ * ```
+ * bbox.xMin = FLOOR(bbox.xMin);
+ * bbox.yMin = FLOOR(bbox.yMin);
+ * bbox.xMax = CEILING(bbox.xMax);
+ * bbox.yMax = CEILING(bbox.yMax);
+ * ```
+ *
+ * To get the bbox in pixel coordinates, set `bbox_mode` to
+ * @FT_GLYPH_BBOX_TRUNCATE.
+ *
+ * To get the bbox in grid-fitted pixel coordinates, set `bbox_mode` to
+ * @FT_GLYPH_BBOX_PIXELS.
+ */
+ FT_EXPORT( void )
+ FT_Glyph_Get_CBox( FT_Glyph glyph,
+ FT_UInt bbox_mode,
+ FT_BBox *acbox );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_To_Bitmap
+ *
+ * @description:
+ * Convert a given glyph object to a bitmap glyph object.
+ *
+ * @inout:
+ * the_glyph ::
+ * A pointer to a handle to the target glyph.
+ *
+ * @input:
+ * render_mode ::
+ * An enumeration that describes how the data is rendered.
+ *
+ * origin ::
+ * A pointer to a vector used to translate the glyph image before
+ * rendering. Can be~0 (if no translation). The origin is expressed
+ * in 26.6 pixels.
+ *
+ * destroy ::
+ * A boolean that indicates that the original glyph image should be
+ * destroyed by this function. It is never destroyed in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function does nothing if the glyph format isn't scalable.
+ *
+ * The glyph image is translated with the `origin` vector before
+ * rendering.
+ *
+ * The first parameter is a pointer to an @FT_Glyph handle, that will be
+ * _replaced_ by this function (with newly allocated data). Typically,
+ * you would use (omitting error handling):
+ *
+ * ```
+ * FT_Glyph glyph;
+ * FT_BitmapGlyph glyph_bitmap;
+ *
+ *
+ * // load glyph
+ * error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAULT );
+ *
+ * // extract glyph image
+ * error = FT_Get_Glyph( face->glyph, &glyph );
+ *
+ * // convert to a bitmap (default render mode + destroying old)
+ * if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
+ * {
+ * error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL,
+ * 0, 1 );
+ * if ( error ) // `glyph' unchanged
+ * ...
+ * }
+ *
+ * // access bitmap content by typecasting
+ * glyph_bitmap = (FT_BitmapGlyph)glyph;
+ *
+ * // do funny stuff with it, like blitting/drawing
+ * ...
+ *
+ * // discard glyph image (bitmap or not)
+ * FT_Done_Glyph( glyph );
+ * ```
+ *
+ * Here is another example, again without error handling:
+ *
+ * ```
+ * FT_Glyph glyphs[MAX_GLYPHS]
+ *
+ *
+ * ...
+ *
+ * for ( idx = 0; i < MAX_GLYPHS; i++ )
+ * error = FT_Load_Glyph( face, idx, FT_LOAD_DEFAULT ) ||
+ * FT_Get_Glyph ( face->glyph, &glyphs[idx] );
+ *
+ * ...
+ *
+ * for ( idx = 0; i < MAX_GLYPHS; i++ )
+ * {
+ * FT_Glyph bitmap = glyphs[idx];
+ *
+ *
+ * ...
+ *
+ * // after this call, `bitmap' no longer points into
+ * // the `glyphs' array (and the old value isn't destroyed)
+ * FT_Glyph_To_Bitmap( &bitmap, FT_RENDER_MODE_MONO, 0, 0 );
+ *
+ * ...
+ *
+ * FT_Done_Glyph( bitmap );
+ * }
+ *
+ * ...
+ *
+ * for ( idx = 0; i < MAX_GLYPHS; i++ )
+ * FT_Done_Glyph( glyphs[idx] );
+ * ```
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
+ FT_Render_Mode render_mode,
+ FT_Vector* origin,
+ FT_Bool destroy );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Glyph
+ *
+ * @description:
+ * Destroy a given glyph.
+ *
+ * @input:
+ * glyph ::
+ * A handle to the target glyph object.
+ */
+ FT_EXPORT( void )
+ FT_Done_Glyph( FT_Glyph glyph );
+
+ /* */
+
+
+ /* other helpful functions */
+
+ /**************************************************************************
+ *
+ * @section:
+ * computations
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Matrix_Multiply
+ *
+ * @description:
+ * Perform the matrix operation `b = a*b`.
+ *
+ * @input:
+ * a ::
+ * A pointer to matrix `a`.
+ *
+ * @inout:
+ * b ::
+ * A pointer to matrix `b`.
+ *
+ * @note:
+ * The result is undefined if either `a` or `b` is zero.
+ *
+ * Since the function uses wrap-around arithmetic, results become
+ * meaningless if the arguments are very large.
+ */
+ FT_EXPORT( void )
+ FT_Matrix_Multiply( const FT_Matrix* a,
+ FT_Matrix* b );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Matrix_Invert
+ *
+ * @description:
+ * Invert a 2x2 matrix. Return an error if it can't be inverted.
+ *
+ * @inout:
+ * matrix ::
+ * A pointer to the target matrix. Remains untouched in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Matrix_Invert( FT_Matrix* matrix );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTGLYPH_H_ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftgxval.h b/Client/ThirdParty/freetype/include/freetype/ftgxval.h
new file mode 100644
index 0000000..21bbbde
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftgxval.h
@@ -0,0 +1,354 @@
+/****************************************************************************
+ *
+ * ftgxval.h
+ *
+ * FreeType API for validating TrueTypeGX/AAT tables (specification).
+ *
+ * Copyright (C) 2004-2021 by
+ * Masatake YAMATO, Redhat K.K,
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+/****************************************************************************
+ *
+ * gxvalid is derived from both gxlayout module and otvalid module.
+ * Development of gxlayout is supported by the Information-technology
+ * Promotion Agency(IPA), Japan.
+ *
+ */
+
+
+#ifndef FTGXVAL_H_
+#define FTGXVAL_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * gx_validation
+ *
+ * @title:
+ * TrueTypeGX/AAT Validation
+ *
+ * @abstract:
+ * An API to validate TrueTypeGX/AAT tables.
+ *
+ * @description:
+ * This section contains the declaration of functions to validate some
+ * TrueTypeGX tables (feat, mort, morx, bsln, just, kern, opbd, trak,
+ * prop, lcar).
+ *
+ * @order:
+ * FT_TrueTypeGX_Validate
+ * FT_TrueTypeGX_Free
+ *
+ * FT_ClassicKern_Validate
+ * FT_ClassicKern_Free
+ *
+ * FT_VALIDATE_GX_LENGTH
+ * FT_VALIDATE_GXXXX
+ * FT_VALIDATE_CKERNXXX
+ *
+ */
+
+ /**************************************************************************
+ *
+ *
+ * Warning: Use `FT_VALIDATE_XXX` to validate a table.
+ * Following definitions are for gxvalid developers.
+ *
+ *
+ */
+
+#define FT_VALIDATE_feat_INDEX 0
+#define FT_VALIDATE_mort_INDEX 1
+#define FT_VALIDATE_morx_INDEX 2
+#define FT_VALIDATE_bsln_INDEX 3
+#define FT_VALIDATE_just_INDEX 4
+#define FT_VALIDATE_kern_INDEX 5
+#define FT_VALIDATE_opbd_INDEX 6
+#define FT_VALIDATE_trak_INDEX 7
+#define FT_VALIDATE_prop_INDEX 8
+#define FT_VALIDATE_lcar_INDEX 9
+#define FT_VALIDATE_GX_LAST_INDEX FT_VALIDATE_lcar_INDEX
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_VALIDATE_GX_LENGTH
+ *
+ * @description:
+ * The number of tables checked in this module. Use it as a parameter
+ * for the `table-length` argument of function @FT_TrueTypeGX_Validate.
+ */
+#define FT_VALIDATE_GX_LENGTH ( FT_VALIDATE_GX_LAST_INDEX + 1 )
+
+ /* */
+
+ /* Up to 0x1000 is used by otvalid.
+ Ox2xxx is reserved for feature OT extension. */
+#define FT_VALIDATE_GX_START 0x4000
+#define FT_VALIDATE_GX_BITFIELD( tag ) \
+ ( FT_VALIDATE_GX_START << FT_VALIDATE_##tag##_INDEX )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_GXXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_TrueTypeGX_Validate to
+ * indicate which TrueTypeGX/AAT Type tables should be validated.
+ *
+ * @values:
+ * FT_VALIDATE_feat ::
+ * Validate 'feat' table.
+ *
+ * FT_VALIDATE_mort ::
+ * Validate 'mort' table.
+ *
+ * FT_VALIDATE_morx ::
+ * Validate 'morx' table.
+ *
+ * FT_VALIDATE_bsln ::
+ * Validate 'bsln' table.
+ *
+ * FT_VALIDATE_just ::
+ * Validate 'just' table.
+ *
+ * FT_VALIDATE_kern ::
+ * Validate 'kern' table.
+ *
+ * FT_VALIDATE_opbd ::
+ * Validate 'opbd' table.
+ *
+ * FT_VALIDATE_trak ::
+ * Validate 'trak' table.
+ *
+ * FT_VALIDATE_prop ::
+ * Validate 'prop' table.
+ *
+ * FT_VALIDATE_lcar ::
+ * Validate 'lcar' table.
+ *
+ * FT_VALIDATE_GX ::
+ * Validate all TrueTypeGX tables (feat, mort, morx, bsln, just, kern,
+ * opbd, trak, prop and lcar).
+ *
+ */
+
+#define FT_VALIDATE_feat FT_VALIDATE_GX_BITFIELD( feat )
+#define FT_VALIDATE_mort FT_VALIDATE_GX_BITFIELD( mort )
+#define FT_VALIDATE_morx FT_VALIDATE_GX_BITFIELD( morx )
+#define FT_VALIDATE_bsln FT_VALIDATE_GX_BITFIELD( bsln )
+#define FT_VALIDATE_just FT_VALIDATE_GX_BITFIELD( just )
+#define FT_VALIDATE_kern FT_VALIDATE_GX_BITFIELD( kern )
+#define FT_VALIDATE_opbd FT_VALIDATE_GX_BITFIELD( opbd )
+#define FT_VALIDATE_trak FT_VALIDATE_GX_BITFIELD( trak )
+#define FT_VALIDATE_prop FT_VALIDATE_GX_BITFIELD( prop )
+#define FT_VALIDATE_lcar FT_VALIDATE_GX_BITFIELD( lcar )
+
+#define FT_VALIDATE_GX ( FT_VALIDATE_feat | \
+ FT_VALIDATE_mort | \
+ FT_VALIDATE_morx | \
+ FT_VALIDATE_bsln | \
+ FT_VALIDATE_just | \
+ FT_VALIDATE_kern | \
+ FT_VALIDATE_opbd | \
+ FT_VALIDATE_trak | \
+ FT_VALIDATE_prop | \
+ FT_VALIDATE_lcar )
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_TrueTypeGX_Validate
+ *
+ * @description:
+ * Validate various TrueTypeGX tables to assure that all offsets and
+ * indices are valid. The idea is that a higher-level library that
+ * actually does the text layout can access those tables without error
+ * checking (which can be quite time consuming).
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field that specifies the tables to be validated. See
+ * @FT_VALIDATE_GXXXX for possible values.
+ *
+ * table_length ::
+ * The size of the `tables` array. Normally, @FT_VALIDATE_GX_LENGTH
+ * should be passed.
+ *
+ * @output:
+ * tables ::
+ * The array where all validated sfnt tables are stored. The array
+ * itself must be allocated by a client.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with TrueTypeGX fonts, returning an error
+ * otherwise.
+ *
+ * After use, the application should deallocate the buffers pointed to by
+ * each `tables` element, by calling @FT_TrueTypeGX_Free. A `NULL` value
+ * indicates that the table either doesn't exist in the font, the
+ * application hasn't asked for validation, or the validator doesn't have
+ * the ability to validate the sfnt table.
+ */
+ FT_EXPORT( FT_Error )
+ FT_TrueTypeGX_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes tables[FT_VALIDATE_GX_LENGTH],
+ FT_UInt table_length );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_TrueTypeGX_Free
+ *
+ * @description:
+ * Free the buffer allocated by TrueTypeGX validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer allocated by @FT_TrueTypeGX_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_TrueTypeGX_Validate only.
+ */
+ FT_EXPORT( void )
+ FT_TrueTypeGX_Free( FT_Face face,
+ FT_Bytes table );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_CKERNXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_ClassicKern_Validate to
+ * indicate the classic kern dialect or dialects. If the selected type
+ * doesn't fit, @FT_ClassicKern_Validate regards the table as invalid.
+ *
+ * @values:
+ * FT_VALIDATE_MS ::
+ * Handle the 'kern' table as a classic Microsoft kern table.
+ *
+ * FT_VALIDATE_APPLE ::
+ * Handle the 'kern' table as a classic Apple kern table.
+ *
+ * FT_VALIDATE_CKERN ::
+ * Handle the 'kern' as either classic Apple or Microsoft kern table.
+ */
+#define FT_VALIDATE_MS ( FT_VALIDATE_GX_START << 0 )
+#define FT_VALIDATE_APPLE ( FT_VALIDATE_GX_START << 1 )
+
+#define FT_VALIDATE_CKERN ( FT_VALIDATE_MS | FT_VALIDATE_APPLE )
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_ClassicKern_Validate
+ *
+ * @description:
+ * Validate classic (16-bit format) kern table to assure that the
+ * offsets and indices are valid. The idea is that a higher-level
+ * library that actually does the text layout can access those tables
+ * without error checking (which can be quite time consuming).
+ *
+ * The 'kern' table validator in @FT_TrueTypeGX_Validate deals with both
+ * the new 32-bit format and the classic 16-bit format, while
+ * FT_ClassicKern_Validate only supports the classic 16-bit format.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field that specifies the dialect to be validated. See
+ * @FT_VALIDATE_CKERNXXX for possible values.
+ *
+ * @output:
+ * ckern_table ::
+ * A pointer to the kern table.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * After use, the application should deallocate the buffers pointed to by
+ * `ckern_table`, by calling @FT_ClassicKern_Free. A `NULL` value
+ * indicates that the table doesn't exist in the font.
+ */
+ FT_EXPORT( FT_Error )
+ FT_ClassicKern_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *ckern_table );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_ClassicKern_Free
+ *
+ * @description:
+ * Free the buffer allocated by classic Kern validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer that is allocated by
+ * @FT_ClassicKern_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_ClassicKern_Validate only.
+ */
+ FT_EXPORT( void )
+ FT_ClassicKern_Free( FT_Face face,
+ FT_Bytes table );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTGXVAL_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftgzip.h b/Client/ThirdParty/freetype/include/freetype/ftgzip.h
new file mode 100644
index 0000000..ba82bab
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftgzip.h
@@ -0,0 +1,151 @@
+/****************************************************************************
+ *
+ * ftgzip.h
+ *
+ * Gzip-compressed stream support.
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTGZIP_H_
+#define FTGZIP_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @section:
+ * gzip
+ *
+ * @title:
+ * GZIP Streams
+ *
+ * @abstract:
+ * Using gzip-compressed font files.
+ *
+ * @description:
+ * In certain builds of the library, gzip compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a gzipped stream from it
+ * and re-open the face with it.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream,
+ * which significantly undermines the performance.
+ *
+ * This section contains the declaration of Gzip-specific functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenGzip
+ *
+ * @description:
+ * Open a new stream to parse gzip-compressed font files. This is mainly
+ * used to support the compressed `*.pcf.gz` fonts that come with
+ * XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close` on the new stream will
+ * **not** call `FT_Stream_Close` on the source stream. None of the
+ * stream objects will be released to the heap.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with zlib support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenGzip( FT_Stream stream,
+ FT_Stream source );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Gzip_Uncompress
+ *
+ * @description:
+ * Decompress a zipped input buffer into an output buffer. This function
+ * is modeled after zlib's `uncompress` function.
+ *
+ * @input:
+ * memory ::
+ * A FreeType memory handle.
+ *
+ * input ::
+ * The input buffer.
+ *
+ * input_len ::
+ * The length of the input buffer.
+ *
+ * @output:
+ * output ::
+ * The output buffer.
+ *
+ * @inout:
+ * output_len ::
+ * Before calling the function, this is the total size of the output
+ * buffer, which must be large enough to hold the entire uncompressed
+ * data (so the size of the uncompressed data must be known in
+ * advance). After calling the function, `output_len` is the size of
+ * the used data in `output`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with zlib support.
+ *
+ * @since:
+ * 2.5.1
+ */
+ FT_EXPORT( FT_Error )
+ FT_Gzip_Uncompress( FT_Memory memory,
+ FT_Byte* output,
+ FT_ULong* output_len,
+ const FT_Byte* input,
+ FT_ULong input_len );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTGZIP_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftimage.h b/Client/ThirdParty/freetype/include/freetype/ftimage.h
new file mode 100644
index 0000000..66a8b89
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftimage.h
@@ -0,0 +1,1276 @@
+/****************************************************************************
+ *
+ * ftimage.h
+ *
+ * FreeType glyph image formats and default raster interface
+ * (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * Note: A 'raster' is simply a scan-line converter, used to render
+ * FT_Outlines into FT_Bitmaps.
+ *
+ */
+
+
+#ifndef FTIMAGE_H_
+#define FTIMAGE_H_
+
+
+ /* STANDALONE_ is from ftgrays.c */
+#ifndef STANDALONE_
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Pos
+ *
+ * @description:
+ * The type FT_Pos is used to store vectorial coordinates. Depending on
+ * the context, these can represent distances in integer font units, or
+ * 16.16, or 26.6 fixed-point pixel coordinates.
+ */
+ typedef signed long FT_Pos;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Vector
+ *
+ * @description:
+ * A simple structure used to store a 2D vector; coordinates are of the
+ * FT_Pos type.
+ *
+ * @fields:
+ * x ::
+ * The horizontal coordinate.
+ * y ::
+ * The vertical coordinate.
+ */
+ typedef struct FT_Vector_
+ {
+ FT_Pos x;
+ FT_Pos y;
+
+ } FT_Vector;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_BBox
+ *
+ * @description:
+ * A structure used to hold an outline's bounding box, i.e., the
+ * coordinates of its extrema in the horizontal and vertical directions.
+ *
+ * @fields:
+ * xMin ::
+ * The horizontal minimum (left-most).
+ *
+ * yMin ::
+ * The vertical minimum (bottom-most).
+ *
+ * xMax ::
+ * The horizontal maximum (right-most).
+ *
+ * yMax ::
+ * The vertical maximum (top-most).
+ *
+ * @note:
+ * The bounding box is specified with the coordinates of the lower left
+ * and the upper right corner. In PostScript, those values are often
+ * called (llx,lly) and (urx,ury), respectively.
+ *
+ * If `yMin` is negative, this value gives the glyph's descender.
+ * Otherwise, the glyph doesn't descend below the baseline. Similarly,
+ * if `ymax` is positive, this value gives the glyph's ascender.
+ *
+ * `xMin` gives the horizontal distance from the glyph's origin to the
+ * left edge of the glyph's bounding box. If `xMin` is negative, the
+ * glyph extends to the left of the origin.
+ */
+ typedef struct FT_BBox_
+ {
+ FT_Pos xMin, yMin;
+ FT_Pos xMax, yMax;
+
+ } FT_BBox;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Pixel_Mode
+ *
+ * @description:
+ * An enumeration type used to describe the format of pixels in a given
+ * bitmap. Note that additional formats may be added in the future.
+ *
+ * @values:
+ * FT_PIXEL_MODE_NONE ::
+ * Value~0 is reserved.
+ *
+ * FT_PIXEL_MODE_MONO ::
+ * A monochrome bitmap, using 1~bit per pixel. Note that pixels are
+ * stored in most-significant order (MSB), which means that the
+ * left-most pixel in a byte has value 128.
+ *
+ * FT_PIXEL_MODE_GRAY ::
+ * An 8-bit bitmap, generally used to represent anti-aliased glyph
+ * images. Each pixel is stored in one byte. Note that the number of
+ * 'gray' levels is stored in the `num_grays` field of the @FT_Bitmap
+ * structure (it generally is 256).
+ *
+ * FT_PIXEL_MODE_GRAY2 ::
+ * A 2-bit per pixel bitmap, used to represent embedded anti-aliased
+ * bitmaps in font files according to the OpenType specification. We
+ * haven't found a single font using this format, however.
+ *
+ * FT_PIXEL_MODE_GRAY4 ::
+ * A 4-bit per pixel bitmap, representing embedded anti-aliased bitmaps
+ * in font files according to the OpenType specification. We haven't
+ * found a single font using this format, however.
+ *
+ * FT_PIXEL_MODE_LCD ::
+ * An 8-bit bitmap, representing RGB or BGR decimated glyph images used
+ * for display on LCD displays; the bitmap is three times wider than
+ * the original glyph image. See also @FT_RENDER_MODE_LCD.
+ *
+ * FT_PIXEL_MODE_LCD_V ::
+ * An 8-bit bitmap, representing RGB or BGR decimated glyph images used
+ * for display on rotated LCD displays; the bitmap is three times
+ * taller than the original glyph image. See also
+ * @FT_RENDER_MODE_LCD_V.
+ *
+ * FT_PIXEL_MODE_BGRA ::
+ * [Since 2.5] An image with four 8-bit channels per pixel,
+ * representing a color image (such as emoticons) with alpha channel.
+ * For each pixel, the format is BGRA, which means, the blue channel
+ * comes first in memory. The color channels are pre-multiplied and in
+ * the sRGB colorspace. For example, full red at half-translucent
+ * opacity will be represented as '00,00,80,80', not '00,00,FF,80'.
+ * See also @FT_LOAD_COLOR.
+ */
+ typedef enum FT_Pixel_Mode_
+ {
+ FT_PIXEL_MODE_NONE = 0,
+ FT_PIXEL_MODE_MONO,
+ FT_PIXEL_MODE_GRAY,
+ FT_PIXEL_MODE_GRAY2,
+ FT_PIXEL_MODE_GRAY4,
+ FT_PIXEL_MODE_LCD,
+ FT_PIXEL_MODE_LCD_V,
+ FT_PIXEL_MODE_BGRA,
+
+ FT_PIXEL_MODE_MAX /* do not remove */
+
+ } FT_Pixel_Mode;
+
+
+ /* these constants are deprecated; use the corresponding `FT_Pixel_Mode` */
+ /* values instead. */
+#define ft_pixel_mode_none FT_PIXEL_MODE_NONE
+#define ft_pixel_mode_mono FT_PIXEL_MODE_MONO
+#define ft_pixel_mode_grays FT_PIXEL_MODE_GRAY
+#define ft_pixel_mode_pal2 FT_PIXEL_MODE_GRAY2
+#define ft_pixel_mode_pal4 FT_PIXEL_MODE_GRAY4
+
+ /* */
+
+ /* For debugging, the @FT_Pixel_Mode enumeration must stay in sync */
+ /* with the `pixel_modes` array in file `ftobjs.c`. */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Bitmap
+ *
+ * @description:
+ * A structure used to describe a bitmap or pixmap to the raster. Note
+ * that we now manage pixmaps of various depths through the `pixel_mode`
+ * field.
+ *
+ * @fields:
+ * rows ::
+ * The number of bitmap rows.
+ *
+ * width ::
+ * The number of pixels in bitmap row.
+ *
+ * pitch ::
+ * The pitch's absolute value is the number of bytes taken by one
+ * bitmap row, including padding. However, the pitch is positive when
+ * the bitmap has a 'down' flow, and negative when it has an 'up' flow.
+ * In all cases, the pitch is an offset to add to a bitmap pointer in
+ * order to go down one row.
+ *
+ * Note that 'padding' means the alignment of a bitmap to a byte
+ * border, and FreeType functions normally align to the smallest
+ * possible integer value.
+ *
+ * For the B/W rasterizer, `pitch` is always an even number.
+ *
+ * To change the pitch of a bitmap (say, to make it a multiple of 4),
+ * use @FT_Bitmap_Convert. Alternatively, you might use callback
+ * functions to directly render to the application's surface; see the
+ * file `example2.cpp` in the tutorial for a demonstration.
+ *
+ * buffer ::
+ * A typeless pointer to the bitmap buffer. This value should be
+ * aligned on 32-bit boundaries in most cases.
+ *
+ * num_grays ::
+ * This field is only used with @FT_PIXEL_MODE_GRAY; it gives the
+ * number of gray levels used in the bitmap.
+ *
+ * pixel_mode ::
+ * The pixel mode, i.e., how pixel bits are stored. See @FT_Pixel_Mode
+ * for possible values.
+ *
+ * palette_mode ::
+ * This field is intended for paletted pixel modes; it indicates how
+ * the palette is stored. Not used currently.
+ *
+ * palette ::
+ * A typeless pointer to the bitmap palette; this field is intended for
+ * paletted pixel modes. Not used currently.
+ */
+ typedef struct FT_Bitmap_
+ {
+ unsigned int rows;
+ unsigned int width;
+ int pitch;
+ unsigned char* buffer;
+ unsigned short num_grays;
+ unsigned char pixel_mode;
+ unsigned char palette_mode;
+ void* palette;
+
+ } FT_Bitmap;
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * outline_processing
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Outline
+ *
+ * @description:
+ * This structure is used to describe an outline to the scan-line
+ * converter.
+ *
+ * @fields:
+ * n_contours ::
+ * The number of contours in the outline.
+ *
+ * n_points ::
+ * The number of points in the outline.
+ *
+ * points ::
+ * A pointer to an array of `n_points` @FT_Vector elements, giving the
+ * outline's point coordinates.
+ *
+ * tags ::
+ * A pointer to an array of `n_points` chars, giving each outline
+ * point's type.
+ *
+ * If bit~0 is unset, the point is 'off' the curve, i.e., a Bezier
+ * control point, while it is 'on' if set.
+ *
+ * Bit~1 is meaningful for 'off' points only. If set, it indicates a
+ * third-order Bezier arc control point; and a second-order control
+ * point if unset.
+ *
+ * If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in
+ * the OpenType specification; the value is the same as the argument to
+ * the 'SCANMODE' instruction).
+ *
+ * Bits 3 and~4 are reserved for internal purposes.
+ *
+ * contours ::
+ * An array of `n_contours` shorts, giving the end point of each
+ * contour within the outline. For example, the first contour is
+ * defined by the points '0' to `contours[0]`, the second one is
+ * defined by the points `contours[0]+1` to `contours[1]`, etc.
+ *
+ * flags ::
+ * A set of bit flags used to characterize the outline and give hints
+ * to the scan-converter and hinter on how to convert/grid-fit it. See
+ * @FT_OUTLINE_XXX.
+ *
+ * @note:
+ * The B/W rasterizer only checks bit~2 in the `tags` array for the first
+ * point of each contour. The drop-out mode as given with
+ * @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and
+ * @FT_OUTLINE_INCLUDE_STUBS in `flags` is then overridden.
+ */
+ typedef struct FT_Outline_
+ {
+ short n_contours; /* number of contours in glyph */
+ short n_points; /* number of points in the glyph */
+
+ FT_Vector* points; /* the outline's points */
+ char* tags; /* the points flags */
+ short* contours; /* the contour end points */
+
+ int flags; /* outline masks */
+
+ } FT_Outline;
+
+ /* */
+
+ /* Following limits must be consistent with */
+ /* FT_Outline.{n_contours,n_points} */
+#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX
+#define FT_OUTLINE_POINTS_MAX SHRT_MAX
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_OUTLINE_XXX
+ *
+ * @description:
+ * A list of bit-field constants used for the flags in an outline's
+ * `flags` field.
+ *
+ * @values:
+ * FT_OUTLINE_NONE ::
+ * Value~0 is reserved.
+ *
+ * FT_OUTLINE_OWNER ::
+ * If set, this flag indicates that the outline's field arrays (i.e.,
+ * `points`, `flags`, and `contours`) are 'owned' by the outline
+ * object, and should thus be freed when it is destroyed.
+ *
+ * FT_OUTLINE_EVEN_ODD_FILL ::
+ * By default, outlines are filled using the non-zero winding rule. If
+ * set to 1, the outline will be filled using the even-odd fill rule
+ * (only works with the smooth rasterizer).
+ *
+ * FT_OUTLINE_REVERSE_FILL ::
+ * By default, outside contours of an outline are oriented in
+ * clock-wise direction, as defined in the TrueType specification.
+ * This flag is set if the outline uses the opposite direction
+ * (typically for Type~1 fonts). This flag is ignored by the scan
+ * converter.
+ *
+ * FT_OUTLINE_IGNORE_DROPOUTS ::
+ * By default, the scan converter will try to detect drop-outs in an
+ * outline and correct the glyph bitmap to ensure consistent shape
+ * continuity. If set, this flag hints the scan-line converter to
+ * ignore such cases. See below for more information.
+ *
+ * FT_OUTLINE_SMART_DROPOUTS ::
+ * Select smart dropout control. If unset, use simple dropout control.
+ * Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more
+ * information.
+ *
+ * FT_OUTLINE_INCLUDE_STUBS ::
+ * If set, turn pixels on for 'stubs', otherwise exclude them. Ignored
+ * if @FT_OUTLINE_IGNORE_DROPOUTS is set. See below for more
+ * information.
+ *
+ * FT_OUTLINE_OVERLAP ::
+ * This flag indicates that this outline contains overlapping contrours
+ * and the anti-aliased renderer should perform oversampling to
+ * mitigate possible artifacts. This flag should _not_ be set for
+ * well designed glyphs without overlaps because it quadruples the
+ * rendering time.
+ *
+ * FT_OUTLINE_HIGH_PRECISION ::
+ * This flag indicates that the scan-line converter should try to
+ * convert this outline to bitmaps with the highest possible quality.
+ * It is typically set for small character sizes. Note that this is
+ * only a hint that might be completely ignored by a given
+ * scan-converter.
+ *
+ * FT_OUTLINE_SINGLE_PASS ::
+ * This flag is set to force a given scan-converter to only use a
+ * single pass over the outline to render a bitmap glyph image.
+ * Normally, it is set for very large character sizes. It is only a
+ * hint that might be completely ignored by a given scan-converter.
+ *
+ * @note:
+ * The flags @FT_OUTLINE_IGNORE_DROPOUTS, @FT_OUTLINE_SMART_DROPOUTS, and
+ * @FT_OUTLINE_INCLUDE_STUBS are ignored by the smooth rasterizer.
+ *
+ * There exists a second mechanism to pass the drop-out mode to the B/W
+ * rasterizer; see the `tags` field in @FT_Outline.
+ *
+ * Please refer to the description of the 'SCANTYPE' instruction in the
+ * OpenType specification (in file `ttinst1.doc`) how simple drop-outs,
+ * smart drop-outs, and stubs are defined.
+ */
+#define FT_OUTLINE_NONE 0x0
+#define FT_OUTLINE_OWNER 0x1
+#define FT_OUTLINE_EVEN_ODD_FILL 0x2
+#define FT_OUTLINE_REVERSE_FILL 0x4
+#define FT_OUTLINE_IGNORE_DROPOUTS 0x8
+#define FT_OUTLINE_SMART_DROPOUTS 0x10
+#define FT_OUTLINE_INCLUDE_STUBS 0x20
+#define FT_OUTLINE_OVERLAP 0x40
+
+#define FT_OUTLINE_HIGH_PRECISION 0x100
+#define FT_OUTLINE_SINGLE_PASS 0x200
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_OUTLINE_XXX` values instead */
+#define ft_outline_none FT_OUTLINE_NONE
+#define ft_outline_owner FT_OUTLINE_OWNER
+#define ft_outline_even_odd_fill FT_OUTLINE_EVEN_ODD_FILL
+#define ft_outline_reverse_fill FT_OUTLINE_REVERSE_FILL
+#define ft_outline_ignore_dropouts FT_OUTLINE_IGNORE_DROPOUTS
+#define ft_outline_high_precision FT_OUTLINE_HIGH_PRECISION
+#define ft_outline_single_pass FT_OUTLINE_SINGLE_PASS
+
+ /* */
+
+#define FT_CURVE_TAG( flag ) ( flag & 0x03 )
+
+ /* see the `tags` field in `FT_Outline` for a description of the values */
+#define FT_CURVE_TAG_ON 0x01
+#define FT_CURVE_TAG_CONIC 0x00
+#define FT_CURVE_TAG_CUBIC 0x02
+
+#define FT_CURVE_TAG_HAS_SCANMODE 0x04
+
+#define FT_CURVE_TAG_TOUCH_X 0x08 /* reserved for TrueType hinter */
+#define FT_CURVE_TAG_TOUCH_Y 0x10 /* reserved for TrueType hinter */
+
+#define FT_CURVE_TAG_TOUCH_BOTH ( FT_CURVE_TAG_TOUCH_X | \
+ FT_CURVE_TAG_TOUCH_Y )
+ /* values 0x20, 0x40, and 0x80 are reserved */
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_CURVE_TAG_XXX` values instead */
+#define FT_Curve_Tag_On FT_CURVE_TAG_ON
+#define FT_Curve_Tag_Conic FT_CURVE_TAG_CONIC
+#define FT_Curve_Tag_Cubic FT_CURVE_TAG_CUBIC
+#define FT_Curve_Tag_Touch_X FT_CURVE_TAG_TOUCH_X
+#define FT_Curve_Tag_Touch_Y FT_CURVE_TAG_TOUCH_Y
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_MoveToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'move to'
+ * function during outline walking/decomposition.
+ *
+ * A 'move to' is emitted to start a new contour in an outline.
+ *
+ * @input:
+ * to ::
+ * A pointer to the target point of the 'move to'.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
+ typedef int
+ (*FT_Outline_MoveToFunc)( const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_MoveTo_Func FT_Outline_MoveToFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_LineToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'line to'
+ * function during outline walking/decomposition.
+ *
+ * A 'line to' is emitted to indicate a segment in the outline.
+ *
+ * @input:
+ * to ::
+ * A pointer to the target point of the 'line to'.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
+ typedef int
+ (*FT_Outline_LineToFunc)( const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_LineTo_Func FT_Outline_LineToFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_ConicToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'conic to'
+ * function during outline walking or decomposition.
+ *
+ * A 'conic to' is emitted to indicate a second-order Bezier arc in the
+ * outline.
+ *
+ * @input:
+ * control ::
+ * An intermediate control point between the last position and the new
+ * target in `to`.
+ *
+ * to ::
+ * A pointer to the target end point of the conic arc.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
+ typedef int
+ (*FT_Outline_ConicToFunc)( const FT_Vector* control,
+ const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_ConicTo_Func FT_Outline_ConicToFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Outline_CubicToFunc
+ *
+ * @description:
+ * A function pointer type used to describe the signature of a 'cubic to'
+ * function during outline walking or decomposition.
+ *
+ * A 'cubic to' is emitted to indicate a third-order Bezier arc.
+ *
+ * @input:
+ * control1 ::
+ * A pointer to the first Bezier control point.
+ *
+ * control2 ::
+ * A pointer to the second Bezier control point.
+ *
+ * to ::
+ * A pointer to the target end point.
+ *
+ * user ::
+ * A typeless pointer, which is passed from the caller of the
+ * decomposition function.
+ *
+ * @return:
+ * Error code. 0~means success.
+ */
+ typedef int
+ (*FT_Outline_CubicToFunc)( const FT_Vector* control1,
+ const FT_Vector* control2,
+ const FT_Vector* to,
+ void* user );
+
+#define FT_Outline_CubicTo_Func FT_Outline_CubicToFunc
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Outline_Funcs
+ *
+ * @description:
+ * A structure to hold various function pointers used during outline
+ * decomposition in order to emit segments, conic, and cubic Beziers.
+ *
+ * @fields:
+ * move_to ::
+ * The 'move to' emitter.
+ *
+ * line_to ::
+ * The segment emitter.
+ *
+ * conic_to ::
+ * The second-order Bezier arc emitter.
+ *
+ * cubic_to ::
+ * The third-order Bezier arc emitter.
+ *
+ * shift ::
+ * The shift that is applied to coordinates before they are sent to the
+ * emitter.
+ *
+ * delta ::
+ * The delta that is applied to coordinates before they are sent to the
+ * emitter, but after the shift.
+ *
+ * @note:
+ * The point coordinates sent to the emitters are the transformed version
+ * of the original coordinates (this is important for high accuracy
+ * during scan-conversion). The transformation is simple:
+ *
+ * ```
+ * x' = (x << shift) - delta
+ * y' = (y << shift) - delta
+ * ```
+ *
+ * Set the values of `shift` and `delta` to~0 to get the original point
+ * coordinates.
+ */
+ typedef struct FT_Outline_Funcs_
+ {
+ FT_Outline_MoveToFunc move_to;
+ FT_Outline_LineToFunc line_to;
+ FT_Outline_ConicToFunc conic_to;
+ FT_Outline_CubicToFunc cubic_to;
+
+ int shift;
+ FT_Pos delta;
+
+ } FT_Outline_Funcs;
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_IMAGE_TAG
+ *
+ * @description:
+ * This macro converts four-letter tags to an unsigned long type.
+ *
+ * @note:
+ * Since many 16-bit compilers don't like 32-bit enumerations, you should
+ * redefine this macro in case of problems to something like this:
+ *
+ * ```
+ * #define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) value
+ * ```
+ *
+ * to get a simple enumeration without assigning special numbers.
+ */
+#ifndef FT_IMAGE_TAG
+#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 ) \
+ value = ( ( (unsigned long)_x1 << 24 ) | \
+ ( (unsigned long)_x2 << 16 ) | \
+ ( (unsigned long)_x3 << 8 ) | \
+ (unsigned long)_x4 )
+#endif /* FT_IMAGE_TAG */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Glyph_Format
+ *
+ * @description:
+ * An enumeration type used to describe the format of a given glyph
+ * image. Note that this version of FreeType only supports two image
+ * formats, even though future font drivers will be able to register
+ * their own format.
+ *
+ * @values:
+ * FT_GLYPH_FORMAT_NONE ::
+ * The value~0 is reserved.
+ *
+ * FT_GLYPH_FORMAT_COMPOSITE ::
+ * The glyph image is a composite of several other images. This format
+ * is _only_ used with @FT_LOAD_NO_RECURSE, and is used to report
+ * compound glyphs (like accented characters).
+ *
+ * FT_GLYPH_FORMAT_BITMAP ::
+ * The glyph image is a bitmap, and can be described as an @FT_Bitmap.
+ * You generally need to access the `bitmap` field of the
+ * @FT_GlyphSlotRec structure to read it.
+ *
+ * FT_GLYPH_FORMAT_OUTLINE ::
+ * The glyph image is a vectorial outline made of line segments and
+ * Bezier arcs; it can be described as an @FT_Outline; you generally
+ * want to access the `outline` field of the @FT_GlyphSlotRec structure
+ * to read it.
+ *
+ * FT_GLYPH_FORMAT_PLOTTER ::
+ * The glyph image is a vectorial path with no inside and outside
+ * contours. Some Type~1 fonts, like those in the Hershey family,
+ * contain glyphs in this format. These are described as @FT_Outline,
+ * but FreeType isn't currently capable of rendering them correctly.
+ */
+ typedef enum FT_Glyph_Format_
+ {
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_NONE, 0, 0, 0, 0 ),
+
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' )
+
+ } FT_Glyph_Format;
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_Glyph_Format` values instead. */
+#define ft_glyph_format_none FT_GLYPH_FORMAT_NONE
+#define ft_glyph_format_composite FT_GLYPH_FORMAT_COMPOSITE
+#define ft_glyph_format_bitmap FT_GLYPH_FORMAT_BITMAP
+#define ft_glyph_format_outline FT_GLYPH_FORMAT_OUTLINE
+#define ft_glyph_format_plotter FT_GLYPH_FORMAT_PLOTTER
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** R A S T E R D E F I N I T I O N S *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * raster
+ *
+ * @title:
+ * Scanline Converter
+ *
+ * @abstract:
+ * How vectorial outlines are converted into bitmaps and pixmaps.
+ *
+ * @description:
+ * A raster or a rasterizer is a scan converter in charge of producing a
+ * pixel coverage bitmap that can be used as an alpha channel when
+ * compositing a glyph with a background. FreeType comes with two
+ * rasterizers: bilevel `raster1` and anti-aliased `smooth` are two
+ * separate modules. They are usually called from the high-level
+ * @FT_Load_Glyph or @FT_Render_Glyph functions and produce the entire
+ * coverage bitmap at once, while staying largely invisible to users.
+ *
+ * Instead of working with complete coverage bitmaps, it is also possible
+ * to intercept consecutive pixel runs on the same scanline with the same
+ * coverage, called _spans_, and process them individually. Only the
+ * `smooth` rasterizer permits this when calling @FT_Outline_Render with
+ * @FT_Raster_Params as described below.
+ *
+ * Working with either complete bitmaps or spans it is important to think
+ * of them as colorless coverage objects suitable as alpha channels to
+ * blend arbitrary colors with a background. For best results, it is
+ * recommended to use gamma correction, too.
+ *
+ * This section also describes the public API needed to set up alternative
+ * @FT_Renderer modules.
+ *
+ * @order:
+ * FT_Span
+ * FT_SpanFunc
+ * FT_Raster_Params
+ * FT_RASTER_FLAG_XXX
+ *
+ * FT_Raster
+ * FT_Raster_NewFunc
+ * FT_Raster_DoneFunc
+ * FT_Raster_ResetFunc
+ * FT_Raster_SetModeFunc
+ * FT_Raster_RenderFunc
+ * FT_Raster_Funcs
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Span
+ *
+ * @description:
+ * A structure to model a single span of consecutive pixels when
+ * rendering an anti-aliased bitmap.
+ *
+ * @fields:
+ * x ::
+ * The span's horizontal start position.
+ *
+ * len ::
+ * The span's length in pixels.
+ *
+ * coverage ::
+ * The span color/coverage, ranging from 0 (background) to 255
+ * (foreground).
+ *
+ * @note:
+ * This structure is used by the span drawing callback type named
+ * @FT_SpanFunc that takes the y~coordinate of the span as a parameter.
+ *
+ * The anti-aliased rasterizer produces coverage values from 0 to 255,
+ * this is, from completely transparent to completely opaque.
+ */
+ typedef struct FT_Span_
+ {
+ short x;
+ unsigned short len;
+ unsigned char coverage;
+
+ } FT_Span;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_SpanFunc
+ *
+ * @description:
+ * A function used as a call-back by the anti-aliased renderer in order
+ * to let client applications draw themselves the pixel spans on each
+ * scan line.
+ *
+ * @input:
+ * y ::
+ * The scanline's upward y~coordinate.
+ *
+ * count ::
+ * The number of spans to draw on this scanline.
+ *
+ * spans ::
+ * A table of `count` spans to draw on the scanline.
+ *
+ * user ::
+ * User-supplied data that is passed to the callback.
+ *
+ * @note:
+ * This callback allows client applications to directly render the spans
+ * of the anti-aliased bitmap to any kind of surfaces.
+ *
+ * This can be used to write anti-aliased outlines directly to a given
+ * background bitmap using alpha compositing. It can also be used for
+ * oversampling and averaging.
+ */
+ typedef void
+ (*FT_SpanFunc)( int y,
+ int count,
+ const FT_Span* spans,
+ void* user );
+
+#define FT_Raster_Span_Func FT_SpanFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_BitTest_Func
+ *
+ * @description:
+ * Deprecated, unimplemented.
+ */
+ typedef int
+ (*FT_Raster_BitTest_Func)( int y,
+ int x,
+ void* user );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_BitSet_Func
+ *
+ * @description:
+ * Deprecated, unimplemented.
+ */
+ typedef void
+ (*FT_Raster_BitSet_Func)( int y,
+ int x,
+ void* user );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_RASTER_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flag constants as used in the `flags` field of a
+ * @FT_Raster_Params structure.
+ *
+ * @values:
+ * FT_RASTER_FLAG_DEFAULT ::
+ * This value is 0.
+ *
+ * FT_RASTER_FLAG_AA ::
+ * This flag is set to indicate that an anti-aliased glyph image should
+ * be generated. Otherwise, it will be monochrome (1-bit).
+ *
+ * FT_RASTER_FLAG_DIRECT ::
+ * This flag is set to indicate direct rendering. In this mode, client
+ * applications must provide their own span callback. This lets them
+ * directly draw or compose over an existing bitmap. If this bit is
+ * _not_ set, the target pixmap's buffer _must_ be zeroed before
+ * rendering and the output will be clipped to its size.
+ *
+ * Direct rendering is only possible with anti-aliased glyphs.
+ *
+ * FT_RASTER_FLAG_CLIP ::
+ * This flag is only used in direct rendering mode. If set, the output
+ * will be clipped to a box specified in the `clip_box` field of the
+ * @FT_Raster_Params structure. Otherwise, the `clip_box` is
+ * effectively set to the bounding box and all spans are generated.
+ *
+ * FT_RASTER_FLAG_SDF ::
+ * This flag is set to indicate that a signed distance field glyph
+ * image should be generated. This is only used while rendering with
+ * the @FT_RENDER_MODE_SDF render mode.
+ */
+#define FT_RASTER_FLAG_DEFAULT 0x0
+#define FT_RASTER_FLAG_AA 0x1
+#define FT_RASTER_FLAG_DIRECT 0x2
+#define FT_RASTER_FLAG_CLIP 0x4
+#define FT_RASTER_FLAG_SDF 0x8
+
+ /* these constants are deprecated; use the corresponding */
+ /* `FT_RASTER_FLAG_XXX` values instead */
+#define ft_raster_flag_default FT_RASTER_FLAG_DEFAULT
+#define ft_raster_flag_aa FT_RASTER_FLAG_AA
+#define ft_raster_flag_direct FT_RASTER_FLAG_DIRECT
+#define ft_raster_flag_clip FT_RASTER_FLAG_CLIP
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Raster_Params
+ *
+ * @description:
+ * A structure to hold the parameters used by a raster's render function,
+ * passed as an argument to @FT_Outline_Render.
+ *
+ * @fields:
+ * target ::
+ * The target bitmap.
+ *
+ * source ::
+ * A pointer to the source glyph image (e.g., an @FT_Outline).
+ *
+ * flags ::
+ * The rendering flags.
+ *
+ * gray_spans ::
+ * The gray span drawing callback.
+ *
+ * black_spans ::
+ * Unused.
+ *
+ * bit_test ::
+ * Unused.
+ *
+ * bit_set ::
+ * Unused.
+ *
+ * user ::
+ * User-supplied data that is passed to each drawing callback.
+ *
+ * clip_box ::
+ * An optional span clipping box expressed in _integer_ pixels
+ * (not in 26.6 fixed-point units).
+ *
+ * @note:
+ * The @FT_RASTER_FLAG_AA bit flag must be set in the `flags` to
+ * generate an anti-aliased glyph bitmap, otherwise a monochrome bitmap
+ * is generated. The `target` should have appropriate pixel mode and its
+ * dimensions define the clipping region.
+ *
+ * If both @FT_RASTER_FLAG_AA and @FT_RASTER_FLAG_DIRECT bit flags
+ * are set in `flags`, the raster calls an @FT_SpanFunc callback
+ * `gray_spans` with `user` data as an argument ignoring `target`. This
+ * allows direct composition over a pre-existing user surface to perform
+ * the span drawing and composition. To optionally clip the spans, set
+ * the @FT_RASTER_FLAG_CLIP flag and `clip_box`. The monochrome raster
+ * does not support the direct mode.
+ *
+ * The gray-level rasterizer always uses 256 gray levels. If you want
+ * fewer gray levels, you have to use @FT_RASTER_FLAG_DIRECT and reduce
+ * the levels in the callback function.
+ */
+ typedef struct FT_Raster_Params_
+ {
+ const FT_Bitmap* target;
+ const void* source;
+ int flags;
+ FT_SpanFunc gray_spans;
+ FT_SpanFunc black_spans; /* unused */
+ FT_Raster_BitTest_Func bit_test; /* unused */
+ FT_Raster_BitSet_Func bit_set; /* unused */
+ void* user;
+ FT_BBox clip_box;
+
+ } FT_Raster_Params;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Raster
+ *
+ * @description:
+ * An opaque handle (pointer) to a raster object. Each object can be
+ * used independently to convert an outline into a bitmap or pixmap.
+ *
+ * @note:
+ * In FreeType 2, all rasters are now encapsulated within specific
+ * @FT_Renderer modules and only used in their context.
+ *
+ */
+ typedef struct FT_RasterRec_* FT_Raster;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_NewFunc
+ *
+ * @description:
+ * A function used to create a new raster object.
+ *
+ * @input:
+ * memory ::
+ * A handle to the memory allocator.
+ *
+ * @output:
+ * raster ::
+ * A handle to the new raster object.
+ *
+ * @return:
+ * Error code. 0~means success.
+ *
+ * @note:
+ * The `memory` parameter is a typeless pointer in order to avoid
+ * un-wanted dependencies on the rest of the FreeType code. In practice,
+ * it is an @FT_Memory object, i.e., a handle to the standard FreeType
+ * memory allocator. However, this field can be completely ignored by a
+ * given raster implementation.
+ */
+ typedef int
+ (*FT_Raster_NewFunc)( void* memory,
+ FT_Raster* raster );
+
+#define FT_Raster_New_Func FT_Raster_NewFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_DoneFunc
+ *
+ * @description:
+ * A function used to destroy a given raster object.
+ *
+ * @input:
+ * raster ::
+ * A handle to the raster object.
+ */
+ typedef void
+ (*FT_Raster_DoneFunc)( FT_Raster raster );
+
+#define FT_Raster_Done_Func FT_Raster_DoneFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_ResetFunc
+ *
+ * @description:
+ * FreeType used to provide an area of memory called the 'render pool'
+ * available to all registered rasterizers. This was not thread safe,
+ * however, and now FreeType never allocates this pool.
+ *
+ * This function is called after a new raster object is created.
+ *
+ * @input:
+ * raster ::
+ * A handle to the new raster object.
+ *
+ * pool_base ::
+ * Previously, the address in memory of the render pool. Set this to
+ * `NULL`.
+ *
+ * pool_size ::
+ * Previously, the size in bytes of the render pool. Set this to 0.
+ *
+ * @note:
+ * Rasterizers should rely on dynamic or stack allocation if they want to
+ * (a handle to the memory allocator is passed to the rasterizer
+ * constructor).
+ */
+ typedef void
+ (*FT_Raster_ResetFunc)( FT_Raster raster,
+ unsigned char* pool_base,
+ unsigned long pool_size );
+
+#define FT_Raster_Reset_Func FT_Raster_ResetFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_SetModeFunc
+ *
+ * @description:
+ * This function is a generic facility to change modes or attributes in a
+ * given raster. This can be used for debugging purposes, or simply to
+ * allow implementation-specific 'features' in a given raster module.
+ *
+ * @input:
+ * raster ::
+ * A handle to the new raster object.
+ *
+ * mode ::
+ * A 4-byte tag used to name the mode or property.
+ *
+ * args ::
+ * A pointer to the new mode/property to use.
+ */
+ typedef int
+ (*FT_Raster_SetModeFunc)( FT_Raster raster,
+ unsigned long mode,
+ void* args );
+
+#define FT_Raster_Set_Mode_Func FT_Raster_SetModeFunc
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Raster_RenderFunc
+ *
+ * @description:
+ * Invoke a given raster to scan-convert a given glyph image into a
+ * target bitmap.
+ *
+ * @input:
+ * raster ::
+ * A handle to the raster object.
+ *
+ * params ::
+ * A pointer to an @FT_Raster_Params structure used to store the
+ * rendering parameters.
+ *
+ * @return:
+ * Error code. 0~means success.
+ *
+ * @note:
+ * The exact format of the source image depends on the raster's glyph
+ * format defined in its @FT_Raster_Funcs structure. It can be an
+ * @FT_Outline or anything else in order to support a large array of
+ * glyph formats.
+ *
+ * Note also that the render function can fail and return a
+ * `FT_Err_Unimplemented_Feature` error code if the raster used does not
+ * support direct composition.
+ */
+ typedef int
+ (*FT_Raster_RenderFunc)( FT_Raster raster,
+ const FT_Raster_Params* params );
+
+#define FT_Raster_Render_Func FT_Raster_RenderFunc
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Raster_Funcs
+ *
+ * @description:
+ * A structure used to describe a given raster class to the library.
+ *
+ * @fields:
+ * glyph_format ::
+ * The supported glyph format for this raster.
+ *
+ * raster_new ::
+ * The raster constructor.
+ *
+ * raster_reset ::
+ * Used to reset the render pool within the raster.
+ *
+ * raster_render ::
+ * A function to render a glyph into a given bitmap.
+ *
+ * raster_done ::
+ * The raster destructor.
+ */
+ typedef struct FT_Raster_Funcs_
+ {
+ FT_Glyph_Format glyph_format;
+
+ FT_Raster_NewFunc raster_new;
+ FT_Raster_ResetFunc raster_reset;
+ FT_Raster_SetModeFunc raster_set_mode;
+ FT_Raster_RenderFunc raster_render;
+ FT_Raster_DoneFunc raster_done;
+
+ } FT_Raster_Funcs;
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTIMAGE_H_ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftincrem.h b/Client/ThirdParty/freetype/include/freetype/ftincrem.h
new file mode 100644
index 0000000..229b947
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftincrem.h
@@ -0,0 +1,348 @@
+/****************************************************************************
+ *
+ * ftincrem.h
+ *
+ * FreeType incremental loading (specification).
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTINCREM_H_
+#define FTINCREM_H_
+
+#include <freetype/freetype.h>
+#include <freetype/ftparams.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @section:
+ * incremental
+ *
+ * @title:
+ * Incremental Loading
+ *
+ * @abstract:
+ * Custom Glyph Loading.
+ *
+ * @description:
+ * This section contains various functions used to perform so-called
+ * 'incremental' glyph loading. This is a mode where all glyphs loaded
+ * from a given @FT_Face are provided by the client application.
+ *
+ * Apart from that, all other tables are loaded normally from the font
+ * file. This mode is useful when FreeType is used within another
+ * engine, e.g., a PostScript Imaging Processor.
+ *
+ * To enable this mode, you must use @FT_Open_Face, passing an
+ * @FT_Parameter with the @FT_PARAM_TAG_INCREMENTAL tag and an
+ * @FT_Incremental_Interface value. See the comments for
+ * @FT_Incremental_InterfaceRec for an example.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Incremental
+ *
+ * @description:
+ * An opaque type describing a user-provided object used to implement
+ * 'incremental' glyph loading within FreeType. This is used to support
+ * embedded fonts in certain environments (e.g., PostScript
+ * interpreters), where the glyph data isn't in the font file, or must be
+ * overridden by different values.
+ *
+ * @note:
+ * It is up to client applications to create and implement
+ * @FT_Incremental objects, as long as they provide implementations for
+ * the methods @FT_Incremental_GetGlyphDataFunc,
+ * @FT_Incremental_FreeGlyphDataFunc and
+ * @FT_Incremental_GetGlyphMetricsFunc.
+ *
+ * See the description of @FT_Incremental_InterfaceRec to understand how
+ * to use incremental objects with FreeType.
+ *
+ */
+ typedef struct FT_IncrementalRec_* FT_Incremental;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_MetricsRec
+ *
+ * @description:
+ * A small structure used to contain the basic glyph metrics returned by
+ * the @FT_Incremental_GetGlyphMetricsFunc method.
+ *
+ * @fields:
+ * bearing_x ::
+ * Left bearing, in font units.
+ *
+ * bearing_y ::
+ * Top bearing, in font units.
+ *
+ * advance ::
+ * Horizontal component of glyph advance, in font units.
+ *
+ * advance_v ::
+ * Vertical component of glyph advance, in font units.
+ *
+ * @note:
+ * These correspond to horizontal or vertical metrics depending on the
+ * value of the `vertical` argument to the function
+ * @FT_Incremental_GetGlyphMetricsFunc.
+ *
+ */
+ typedef struct FT_Incremental_MetricsRec_
+ {
+ FT_Long bearing_x;
+ FT_Long bearing_y;
+ FT_Long advance;
+ FT_Long advance_v; /* since 2.3.12 */
+
+ } FT_Incremental_MetricsRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_Metrics
+ *
+ * @description:
+ * A handle to an @FT_Incremental_MetricsRec structure.
+ *
+ */
+ typedef struct FT_Incremental_MetricsRec_* FT_Incremental_Metrics;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Incremental_GetGlyphDataFunc
+ *
+ * @description:
+ * A function called by FreeType to access a given glyph's data bytes
+ * during @FT_Load_Glyph or @FT_Load_Char if incremental loading is
+ * enabled.
+ *
+ * Note that the format of the glyph's data bytes depends on the font
+ * file format. For TrueType, it must correspond to the raw bytes within
+ * the 'glyf' table. For PostScript formats, it must correspond to the
+ * **unencrypted** charstring bytes, without any `lenIV` header. It is
+ * undefined for any other format.
+ *
+ * @input:
+ * incremental ::
+ * Handle to an opaque @FT_Incremental handle provided by the client
+ * application.
+ *
+ * glyph_index ::
+ * Index of relevant glyph.
+ *
+ * @output:
+ * adata ::
+ * A structure describing the returned glyph data bytes (which will be
+ * accessed as a read-only byte block).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If this function returns successfully the method
+ * @FT_Incremental_FreeGlyphDataFunc will be called later to release the
+ * data bytes.
+ *
+ * Nested calls to @FT_Incremental_GetGlyphDataFunc can happen for
+ * compound glyphs.
+ *
+ */
+ typedef FT_Error
+ (*FT_Incremental_GetGlyphDataFunc)( FT_Incremental incremental,
+ FT_UInt glyph_index,
+ FT_Data* adata );
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Incremental_FreeGlyphDataFunc
+ *
+ * @description:
+ * A function used to release the glyph data bytes returned by a
+ * successful call to @FT_Incremental_GetGlyphDataFunc.
+ *
+ * @input:
+ * incremental ::
+ * A handle to an opaque @FT_Incremental handle provided by the client
+ * application.
+ *
+ * data ::
+ * A structure describing the glyph data bytes (which will be accessed
+ * as a read-only byte block).
+ *
+ */
+ typedef void
+ (*FT_Incremental_FreeGlyphDataFunc)( FT_Incremental incremental,
+ FT_Data* data );
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Incremental_GetGlyphMetricsFunc
+ *
+ * @description:
+ * A function used to retrieve the basic metrics of a given glyph index
+ * before accessing its data. This allows for handling font types such
+ * as PCL~XL Format~1, Class~2 downloaded TrueType fonts, where the glyph
+ * metrics (`hmtx` and `vmtx` tables) are permitted to be omitted from
+ * the font, and the relevant metrics included in the header of the glyph
+ * outline data. Importantly, this is not intended to allow custom glyph
+ * metrics (for example, Postscript Metrics dictionaries), because that
+ * conflicts with the requirements of outline hinting. Such custom
+ * metrics must be handled separately, by the calling application.
+ *
+ * @input:
+ * incremental ::
+ * A handle to an opaque @FT_Incremental handle provided by the client
+ * application.
+ *
+ * glyph_index ::
+ * Index of relevant glyph.
+ *
+ * vertical ::
+ * If true, return vertical metrics.
+ *
+ * ametrics ::
+ * This parameter is used for both input and output. The original
+ * glyph metrics, if any, in font units. If metrics are not available
+ * all the values must be set to zero.
+ *
+ * @output:
+ * ametrics ::
+ * The glyph metrics in font units.
+ *
+ */
+ typedef FT_Error
+ (*FT_Incremental_GetGlyphMetricsFunc)
+ ( FT_Incremental incremental,
+ FT_UInt glyph_index,
+ FT_Bool vertical,
+ FT_Incremental_MetricsRec *ametrics );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_FuncsRec
+ *
+ * @description:
+ * A table of functions for accessing fonts that load data incrementally.
+ * Used in @FT_Incremental_InterfaceRec.
+ *
+ * @fields:
+ * get_glyph_data ::
+ * The function to get glyph data. Must not be null.
+ *
+ * free_glyph_data ::
+ * The function to release glyph data. Must not be null.
+ *
+ * get_glyph_metrics ::
+ * The function to get glyph metrics. May be null if the font does not
+ * require it.
+ *
+ */
+ typedef struct FT_Incremental_FuncsRec_
+ {
+ FT_Incremental_GetGlyphDataFunc get_glyph_data;
+ FT_Incremental_FreeGlyphDataFunc free_glyph_data;
+ FT_Incremental_GetGlyphMetricsFunc get_glyph_metrics;
+
+ } FT_Incremental_FuncsRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Incremental_InterfaceRec
+ *
+ * @description:
+ * A structure to be used with @FT_Open_Face to indicate that the user
+ * wants to support incremental glyph loading. You should use it with
+ * @FT_PARAM_TAG_INCREMENTAL as in the following example:
+ *
+ * ```
+ * FT_Incremental_InterfaceRec inc_int;
+ * FT_Parameter parameter;
+ * FT_Open_Args open_args;
+ *
+ *
+ * // set up incremental descriptor
+ * inc_int.funcs = my_funcs;
+ * inc_int.object = my_object;
+ *
+ * // set up optional parameter
+ * parameter.tag = FT_PARAM_TAG_INCREMENTAL;
+ * parameter.data = &inc_int;
+ *
+ * // set up FT_Open_Args structure
+ * open_args.flags = FT_OPEN_PATHNAME | FT_OPEN_PARAMS;
+ * open_args.pathname = my_font_pathname;
+ * open_args.num_params = 1;
+ * open_args.params = &parameter; // we use one optional argument
+ *
+ * // open the font
+ * error = FT_Open_Face( library, &open_args, index, &face );
+ * ...
+ * ```
+ *
+ */
+ typedef struct FT_Incremental_InterfaceRec_
+ {
+ const FT_Incremental_FuncsRec* funcs;
+ FT_Incremental object;
+
+ } FT_Incremental_InterfaceRec;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Incremental_Interface
+ *
+ * @description:
+ * A pointer to an @FT_Incremental_InterfaceRec structure.
+ *
+ */
+ typedef FT_Incremental_InterfaceRec* FT_Incremental_Interface;
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTINCREM_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftlcdfil.h b/Client/ThirdParty/freetype/include/freetype/ftlcdfil.h
new file mode 100644
index 0000000..107a174
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftlcdfil.h
@@ -0,0 +1,323 @@
+/****************************************************************************
+ *
+ * ftlcdfil.h
+ *
+ * FreeType API for color filtering of subpixel bitmap glyphs
+ * (specification).
+ *
+ * Copyright (C) 2006-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTLCDFIL_H_
+#define FTLCDFIL_H_
+
+#include <freetype/freetype.h>
+#include <freetype/ftparams.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @section:
+ * lcd_rendering
+ *
+ * @title:
+ * Subpixel Rendering
+ *
+ * @abstract:
+ * API to control subpixel rendering.
+ *
+ * @description:
+ * FreeType provides two alternative subpixel rendering technologies.
+ * Should you define `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` in your
+ * `ftoption.h` file, this enables ClearType-style rendering.
+ * Otherwise, Harmony LCD rendering is enabled. These technologies are
+ * controlled differently and API described below, although always
+ * available, performs its function when appropriate method is enabled
+ * and does nothing otherwise.
+ *
+ * ClearType-style LCD rendering exploits the color-striped structure of
+ * LCD pixels, increasing the available resolution in the direction of
+ * the stripe (usually horizontal RGB) by a factor of~3. Using the
+ * subpixel coverages unfiltered can create severe color fringes
+ * especially when rendering thin features. Indeed, to produce
+ * black-on-white text, the nearby color subpixels must be dimmed
+ * evenly. Therefore, an equalizing 5-tap FIR filter should be applied
+ * to subpixel coverages regardless of pixel boundaries and should have
+ * these properties:
+ *
+ * 1. It should be symmetrical, like {~a, b, c, b, a~}, to avoid
+ * any shifts in appearance.
+ *
+ * 2. It should be color-balanced, meaning a~+ b~=~c, to reduce color
+ * fringes by distributing the computed coverage for one subpixel to
+ * all subpixels equally.
+ *
+ * 3. It should be normalized, meaning 2a~+ 2b~+ c~=~1.0 to maintain
+ * overall brightness.
+ *
+ * Boxy 3-tap filter {0, 1/3, 1/3, 1/3, 0} is sharper but is less
+ * forgiving of non-ideal gamma curves of a screen (and viewing angles),
+ * beveled filters are fuzzier but more tolerant.
+ *
+ * Use the @FT_Library_SetLcdFilter or @FT_Library_SetLcdFilterWeights
+ * API to specify a low-pass filter, which is then applied to
+ * subpixel-rendered bitmaps generated through @FT_Render_Glyph.
+ *
+ * Harmony LCD rendering is suitable to panels with any regular subpixel
+ * structure, not just monitors with 3 color striped subpixels, as long
+ * as the color subpixels have fixed positions relative to the pixel
+ * center. In this case, each color channel can be rendered separately
+ * after shifting the outline opposite to the subpixel shift so that the
+ * coverage maps are aligned. This method is immune to color fringes
+ * because the shifts do not change integral coverage.
+ *
+ * The subpixel geometry must be specified by xy-coordinates for each
+ * subpixel. By convention they may come in the RGB order: {{-1/3, 0},
+ * {0, 0}, {1/3, 0}} for standard RGB striped panel or {{-1/6, 1/4},
+ * {-1/6, -1/4}, {1/3, 0}} for a certain PenTile panel.
+ *
+ * Use the @FT_Library_SetLcdGeometry API to specify subpixel positions.
+ * If one follows the RGB order convention, the same order applies to the
+ * resulting @FT_PIXEL_MODE_LCD and @FT_PIXEL_MODE_LCD_V bitmaps. Note,
+ * however, that the coordinate frame for the latter must be rotated
+ * clockwise. Harmony with default LCD geometry is equivalent to
+ * ClearType with light filter.
+ *
+ * As a result of ClearType filtering or Harmony shifts, the resulting
+ * dimensions of LCD bitmaps can be slightly wider or taller than the
+ * dimensions the original outline with regard to the pixel grid.
+ * For example, for @FT_RENDER_MODE_LCD, the filter adds 2~subpixels to
+ * the left, and 2~subpixels to the right. The bitmap offset values are
+ * adjusted accordingly, so clients shouldn't need to modify their layout
+ * and glyph positioning code when enabling the filter.
+ *
+ * The ClearType and Harmony rendering is applicable to glyph bitmaps
+ * rendered through @FT_Render_Glyph, @FT_Load_Glyph, @FT_Load_Char, and
+ * @FT_Glyph_To_Bitmap, when @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V
+ * is specified. This API does not control @FT_Outline_Render and
+ * @FT_Outline_Get_Bitmap.
+ *
+ * The described algorithms can completely remove color artefacts when
+ * combined with gamma-corrected alpha blending in linear space. Each of
+ * the 3~alpha values (subpixels) must by independently used to blend one
+ * color channel. That is, red alpha blends the red channel of the text
+ * color with the red channel of the background pixel.
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_LcdFilter
+ *
+ * @description:
+ * A list of values to identify various types of LCD filters.
+ *
+ * @values:
+ * FT_LCD_FILTER_NONE ::
+ * Do not perform filtering. When used with subpixel rendering, this
+ * results in sometimes severe color fringes.
+ *
+ * FT_LCD_FILTER_DEFAULT ::
+ * This is a beveled, normalized, and color-balanced five-tap filter
+ * with weights of [0x08 0x4D 0x56 0x4D 0x08] in 1/256th units.
+ *
+ * FT_LCD_FILTER_LIGHT ::
+ * this is a boxy, normalized, and color-balanced three-tap filter with
+ * weights of [0x00 0x55 0x56 0x55 0x00] in 1/256th units.
+ *
+ * FT_LCD_FILTER_LEGACY ::
+ * FT_LCD_FILTER_LEGACY1 ::
+ * This filter corresponds to the original libXft color filter. It
+ * provides high contrast output but can exhibit really bad color
+ * fringes if glyphs are not extremely well hinted to the pixel grid.
+ * This filter is only provided for comparison purposes, and might be
+ * disabled or stay unsupported in the future. The second value is
+ * provided for compatibility with FontConfig, which historically used
+ * different enumeration, sometimes incorrectly forwarded to FreeType.
+ *
+ * @since:
+ * 2.3.0 (`FT_LCD_FILTER_LEGACY1` since 2.6.2)
+ */
+ typedef enum FT_LcdFilter_
+ {
+ FT_LCD_FILTER_NONE = 0,
+ FT_LCD_FILTER_DEFAULT = 1,
+ FT_LCD_FILTER_LIGHT = 2,
+ FT_LCD_FILTER_LEGACY1 = 3,
+ FT_LCD_FILTER_LEGACY = 16,
+
+ FT_LCD_FILTER_MAX /* do not remove */
+
+ } FT_LcdFilter;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Library_SetLcdFilter
+ *
+ * @description:
+ * This function is used to change filter applied to LCD decimated
+ * bitmaps, like the ones used when calling @FT_Render_Glyph with
+ * @FT_RENDER_MODE_LCD or @FT_RENDER_MODE_LCD_V.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library instance.
+ *
+ * filter ::
+ * The filter type.
+ *
+ * You can use @FT_LCD_FILTER_NONE here to disable this feature, or
+ * @FT_LCD_FILTER_DEFAULT to use a default filter that should work well
+ * on most LCD screens.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Since 2.10.3 the LCD filtering is enabled with @FT_LCD_FILTER_DEFAULT.
+ * It is no longer necessary to call this function explicitly except
+ * to choose a different filter or disable filtering altogether with
+ * @FT_LCD_FILTER_NONE.
+ *
+ * This function does nothing but returns `FT_Err_Unimplemented_Feature`
+ * if the configuration macro `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` is
+ * not defined in your build of the library.
+ *
+ * @since:
+ * 2.3.0
+ */
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdFilter( FT_Library library,
+ FT_LcdFilter filter );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Library_SetLcdFilterWeights
+ *
+ * @description:
+ * This function can be used to enable LCD filter with custom weights,
+ * instead of using presets in @FT_Library_SetLcdFilter.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library instance.
+ *
+ * weights ::
+ * A pointer to an array; the function copies the first five bytes and
+ * uses them to specify the filter weights in 1/256th units.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function does nothing but returns `FT_Err_Unimplemented_Feature`
+ * if the configuration macro `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` is
+ * not defined in your build of the library.
+ *
+ * LCD filter weights can also be set per face using @FT_Face_Properties
+ * with @FT_PARAM_TAG_LCD_FILTER_WEIGHTS.
+ *
+ * @since:
+ * 2.4.0
+ */
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdFilterWeights( FT_Library library,
+ unsigned char *weights );
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_LcdFiveTapFilter
+ *
+ * @description:
+ * A typedef for passing the five LCD filter weights to
+ * @FT_Face_Properties within an @FT_Parameter structure.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_LCD_FILTER_FIVE_TAPS 5
+
+ typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Library_SetLcdGeometry
+ *
+ * @description:
+ * This function can be used to modify default positions of color
+ * subpixels, which controls Harmony LCD rendering.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library instance.
+ *
+ * sub ::
+ * A pointer to an array of 3 vectors in 26.6 fractional pixel format;
+ * the function modifies the default values, see the note below.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Subpixel geometry examples:
+ *
+ * - {{-21, 0}, {0, 0}, {21, 0}} is the default, corresponding to 3 color
+ * stripes shifted by a third of a pixel. This could be an RGB panel.
+ *
+ * - {{21, 0}, {0, 0}, {-21, 0}} looks the same as the default but can
+ * specify a BGR panel instead, while keeping the bitmap in the same
+ * RGB888 format.
+ *
+ * - {{0, 21}, {0, 0}, {0, -21}} is the vertical RGB, but the bitmap
+ * stays RGB888 as a result.
+ *
+ * - {{-11, 16}, {-11, -16}, {22, 0}} is a certain PenTile arrangement.
+ *
+ * This function does nothing and returns `FT_Err_Unimplemented_Feature`
+ * in the context of ClearType-style subpixel rendering when
+ * `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` is defined in your build of the
+ * library.
+ *
+ * @since:
+ * 2.10.0
+ */
+ FT_EXPORT( FT_Error )
+ FT_Library_SetLcdGeometry( FT_Library library,
+ FT_Vector sub[3] );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTLCDFIL_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftlist.h b/Client/ThirdParty/freetype/include/freetype/ftlist.h
new file mode 100644
index 0000000..55f0159
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftlist.h
@@ -0,0 +1,296 @@
+/****************************************************************************
+ *
+ * ftlist.h
+ *
+ * Generic list support for FreeType (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file implements functions relative to list processing. Its data
+ * structures are defined in `freetype.h`.
+ *
+ */
+
+
+#ifndef FTLIST_H_
+#define FTLIST_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * list_processing
+ *
+ * @title:
+ * List Processing
+ *
+ * @abstract:
+ * Simple management of lists.
+ *
+ * @description:
+ * This section contains various definitions related to list processing
+ * using doubly-linked nodes.
+ *
+ * @order:
+ * FT_List
+ * FT_ListNode
+ * FT_ListRec
+ * FT_ListNodeRec
+ *
+ * FT_List_Add
+ * FT_List_Insert
+ * FT_List_Find
+ * FT_List_Remove
+ * FT_List_Up
+ * FT_List_Iterate
+ * FT_List_Iterator
+ * FT_List_Finalize
+ * FT_List_Destructor
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Find
+ *
+ * @description:
+ * Find the list node for a given listed object.
+ *
+ * @input:
+ * list ::
+ * A pointer to the parent list.
+ * data ::
+ * The address of the listed object.
+ *
+ * @return:
+ * List node. `NULL` if it wasn't found.
+ */
+ FT_EXPORT( FT_ListNode )
+ FT_List_Find( FT_List list,
+ void* data );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Add
+ *
+ * @description:
+ * Append an element to the end of a list.
+ *
+ * @inout:
+ * list ::
+ * A pointer to the parent list.
+ * node ::
+ * The node to append.
+ */
+ FT_EXPORT( void )
+ FT_List_Add( FT_List list,
+ FT_ListNode node );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Insert
+ *
+ * @description:
+ * Insert an element at the head of a list.
+ *
+ * @inout:
+ * list ::
+ * A pointer to parent list.
+ * node ::
+ * The node to insert.
+ */
+ FT_EXPORT( void )
+ FT_List_Insert( FT_List list,
+ FT_ListNode node );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Remove
+ *
+ * @description:
+ * Remove a node from a list. This function doesn't check whether the
+ * node is in the list!
+ *
+ * @input:
+ * node ::
+ * The node to remove.
+ *
+ * @inout:
+ * list ::
+ * A pointer to the parent list.
+ */
+ FT_EXPORT( void )
+ FT_List_Remove( FT_List list,
+ FT_ListNode node );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Up
+ *
+ * @description:
+ * Move a node to the head/top of a list. Used to maintain LRU lists.
+ *
+ * @inout:
+ * list ::
+ * A pointer to the parent list.
+ * node ::
+ * The node to move.
+ */
+ FT_EXPORT( void )
+ FT_List_Up( FT_List list,
+ FT_ListNode node );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_List_Iterator
+ *
+ * @description:
+ * An FT_List iterator function that is called during a list parse by
+ * @FT_List_Iterate.
+ *
+ * @input:
+ * node ::
+ * The current iteration list node.
+ *
+ * user ::
+ * A typeless pointer passed to @FT_List_Iterate. Can be used to point
+ * to the iteration's state.
+ */
+ typedef FT_Error
+ (*FT_List_Iterator)( FT_ListNode node,
+ void* user );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Iterate
+ *
+ * @description:
+ * Parse a list and calls a given iterator function on each element.
+ * Note that parsing is stopped as soon as one of the iterator calls
+ * returns a non-zero value.
+ *
+ * @input:
+ * list ::
+ * A handle to the list.
+ * iterator ::
+ * An iterator function, called on each node of the list.
+ * user ::
+ * A user-supplied field that is passed as the second argument to the
+ * iterator.
+ *
+ * @return:
+ * The result (a FreeType error code) of the last iterator call.
+ */
+ FT_EXPORT( FT_Error )
+ FT_List_Iterate( FT_List list,
+ FT_List_Iterator iterator,
+ void* user );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_List_Destructor
+ *
+ * @description:
+ * An @FT_List iterator function that is called during a list
+ * finalization by @FT_List_Finalize to destroy all elements in a given
+ * list.
+ *
+ * @input:
+ * system ::
+ * The current system object.
+ *
+ * data ::
+ * The current object to destroy.
+ *
+ * user ::
+ * A typeless pointer passed to @FT_List_Iterate. It can be used to
+ * point to the iteration's state.
+ */
+ typedef void
+ (*FT_List_Destructor)( FT_Memory memory,
+ void* data,
+ void* user );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_List_Finalize
+ *
+ * @description:
+ * Destroy all elements in the list as well as the list itself.
+ *
+ * @input:
+ * list ::
+ * A handle to the list.
+ *
+ * destroy ::
+ * A list destructor that will be applied to each element of the list.
+ * Set this to `NULL` if not needed.
+ *
+ * memory ::
+ * The current memory object that handles deallocation.
+ *
+ * user ::
+ * A user-supplied field that is passed as the last argument to the
+ * destructor.
+ *
+ * @note:
+ * This function expects that all nodes added by @FT_List_Add or
+ * @FT_List_Insert have been dynamically allocated.
+ */
+ FT_EXPORT( void )
+ FT_List_Finalize( FT_List list,
+ FT_List_Destructor destroy,
+ FT_Memory memory,
+ void* user );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTLIST_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftlogging.h b/Client/ThirdParty/freetype/include/freetype/ftlogging.h
new file mode 100644
index 0000000..a558b85
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftlogging.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+ *
+ * ftlogging.h
+ *
+ * Additional debugging APIs.
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTLOGGING_H_
+#define FTLOGGING_H_
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * debugging_apis
+ *
+ * @title:
+ * External Debugging APIs
+ *
+ * @abstract:
+ * Public APIs to control the `FT_DEBUG_LOGGING` macro.
+ *
+ * @description:
+ * This section contains the declarations of public functions that
+ * enables fine control of what the `FT_DEBUG_LOGGING` macro outputs.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Trace_Set_Level
+ *
+ * @description:
+ * Change the levels of tracing components of FreeType at run time.
+ *
+ * @input:
+ * tracing_level ::
+ * New tracing value.
+ *
+ * @example:
+ * The following call makes FreeType trace everything but the 'memory'
+ * component.
+ *
+ * ```
+ * FT_Trace_Set_Level( "any:7 memory:0 );
+ * ```
+ *
+ * @note:
+ * This function does nothing if compilation option `FT_DEBUG_LOGGING`
+ * isn't set.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+ FT_EXPORT( void )
+ FT_Trace_Set_Level( const char* tracing_level );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Trace_Set_Default_Level
+ *
+ * @description:
+ * Reset tracing value of FreeType's components to the default value
+ * (i.e., to the value of the `FT2_DEBUG` environment value or to NULL
+ * if `FT2_DEBUG` is not set).
+ *
+ * @note:
+ * This function does nothing if compilation option `FT_DEBUG_LOGGING`
+ * isn't set.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+ FT_EXPORT( void )
+ FT_Trace_Set_Default_Level( void );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Custom_Log_Handler
+ *
+ * @description:
+ * A function typedef that is used to handle the logging of tracing and
+ * debug messages on a file system.
+ *
+ * @input:
+ * ft_component ::
+ * The name of `FT_COMPONENT` from which the current debug or error
+ * message is produced.
+ *
+ * fmt ::
+ * Actual debug or tracing message.
+ *
+ * args::
+ * Arguments of debug or tracing messages.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+ typedef void
+ (*FT_Custom_Log_Handler)( const char* ft_component,
+ const char* fmt,
+ va_list args );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Log_Handler
+ *
+ * @description:
+ * A function to set a custom log handler.
+ *
+ * @input:
+ * handler ::
+ * New logging function.
+ *
+ * @note:
+ * This function does nothing if compilation option `FT_DEBUG_LOGGING`
+ * isn't set.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+ FT_EXPORT( void )
+ FT_Set_Log_Handler( FT_Custom_Log_Handler handler );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Default_Log_Handler
+ *
+ * @description:
+ * A function to undo the effect of @FT_Set_Log_Handler, resetting the
+ * log handler to FreeType's built-in version.
+ *
+ * @note:
+ * This function does nothing if compilation option `FT_DEBUG_LOGGING`
+ * isn't set.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+ FT_EXPORT( void )
+ FT_Set_Default_Log_Handler( void );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTLOGGING_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftlzw.h b/Client/ThirdParty/freetype/include/freetype/ftlzw.h
new file mode 100644
index 0000000..fce1c9c
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftlzw.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+ *
+ * ftlzw.h
+ *
+ * LZW-compressed stream support.
+ *
+ * Copyright (C) 2004-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTLZW_H_
+#define FTLZW_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @section:
+ * lzw
+ *
+ * @title:
+ * LZW Streams
+ *
+ * @abstract:
+ * Using LZW-compressed font files.
+ *
+ * @description:
+ * In certain builds of the library, LZW compression recognition is
+ * automatically handled when calling @FT_New_Face or @FT_Open_Face.
+ * This means that if no font driver is capable of handling the raw
+ * compressed file, the library will try to open a LZW stream from it and
+ * re-open the face with it.
+ *
+ * The stream implementation is very basic and resets the decompression
+ * process each time seeking backwards is needed within the stream,
+ * which significantly undermines the performance.
+ *
+ * This section contains the declaration of LZW-specific functions.
+ *
+ */
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stream_OpenLZW
+ *
+ * @description:
+ * Open a new stream to parse LZW-compressed font files. This is mainly
+ * used to support the compressed `*.pcf.Z` fonts that come with XFree86.
+ *
+ * @input:
+ * stream ::
+ * The target embedding stream.
+ *
+ * source ::
+ * The source stream.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source stream must be opened _before_ calling this function.
+ *
+ * Calling the internal function `FT_Stream_Close` on the new stream will
+ * **not** call `FT_Stream_Close` on the source stream. None of the
+ * stream objects will be released to the heap.
+ *
+ * This function may return `FT_Err_Unimplemented_Feature` if your build
+ * of FreeType was not compiled with LZW support.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stream_OpenLZW( FT_Stream stream,
+ FT_Stream source );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTLZW_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftmac.h b/Client/ThirdParty/freetype/include/freetype/ftmac.h
new file mode 100644
index 0000000..607af9b
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftmac.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+ *
+ * ftmac.h
+ *
+ * Additional Mac-specific API.
+ *
+ * Copyright (C) 1996-2021 by
+ * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+/****************************************************************************
+ *
+ * NOTE: Include this file after `FT_FREETYPE_H` and after any
+ * Mac-specific headers (because this header uses Mac types such as
+ * 'Handle', 'FSSpec', 'FSRef', etc.)
+ *
+ */
+
+
+#ifndef FTMAC_H_
+#define FTMAC_H_
+
+
+
+
+FT_BEGIN_HEADER
+
+
+ /* gcc-3.1 and later can warn about functions tagged as deprecated */
+#ifndef FT_DEPRECATED_ATTRIBUTE
+#if defined( __GNUC__ ) && \
+ ( ( __GNUC__ >= 4 ) || \
+ ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 1 ) ) )
+#define FT_DEPRECATED_ATTRIBUTE __attribute__(( deprecated ))
+#else
+#define FT_DEPRECATED_ATTRIBUTE
+#endif
+#endif
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * mac_specific
+ *
+ * @title:
+ * Mac Specific Interface
+ *
+ * @abstract:
+ * Only available on the Macintosh.
+ *
+ * @description:
+ * The following definitions are only available if FreeType is compiled
+ * on a Macintosh.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face_From_FOND
+ *
+ * @description:
+ * Create a new face object from a FOND resource.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * fond ::
+ * A FOND resource.
+ *
+ * face_index ::
+ * Only supported for the -1 'sanity check' special case.
+ *
+ * @output:
+ * aface ::
+ * A handle to a new face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @example:
+ * This function can be used to create @FT_Face objects from fonts that
+ * are installed in the system as follows.
+ *
+ * ```
+ * fond = GetResource( 'FOND', fontName );
+ * error = FT_New_Face_From_FOND( library, fond, 0, &face );
+ * ```
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Face_From_FOND( FT_Library library,
+ Handle fond,
+ FT_Long face_index,
+ FT_Face *aface )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GetFile_From_Mac_Name
+ *
+ * @description:
+ * Return an FSSpec for the disk file containing the named font.
+ *
+ * @input:
+ * fontName ::
+ * Mac OS name of the font (e.g., Times New Roman Bold).
+ *
+ * @output:
+ * pathSpec ::
+ * FSSpec to the file. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * face_index ::
+ * Index of the face. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_GetFile_From_Mac_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GetFile_From_Mac_ATS_Name
+ *
+ * @description:
+ * Return an FSSpec for the disk file containing the named font.
+ *
+ * @input:
+ * fontName ::
+ * Mac OS name of the font in ATS framework.
+ *
+ * @output:
+ * pathSpec ::
+ * FSSpec to the file. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * face_index ::
+ * Index of the face. For passing to @FT_New_Face_From_FSSpec.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_GetFile_From_Mac_ATS_Name( const char* fontName,
+ FSSpec* pathSpec,
+ FT_Long* face_index )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_GetFilePath_From_Mac_ATS_Name
+ *
+ * @description:
+ * Return a pathname of the disk file and face index for given font name
+ * that is handled by ATS framework.
+ *
+ * @input:
+ * fontName ::
+ * Mac OS name of the font in ATS framework.
+ *
+ * @output:
+ * path ::
+ * Buffer to store pathname of the file. For passing to @FT_New_Face.
+ * The client must allocate this buffer before calling this function.
+ *
+ * maxPathSize ::
+ * Lengths of the buffer `path` that client allocated.
+ *
+ * face_index ::
+ * Index of the face. For passing to @FT_New_Face.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_GetFilePath_From_Mac_ATS_Name( const char* fontName,
+ UInt8* path,
+ UInt32 maxPathSize,
+ FT_Long* face_index )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face_From_FSSpec
+ *
+ * @description:
+ * Create a new face object from a given resource and typeface index
+ * using an FSSpec to the font file.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * spec ::
+ * FSSpec to the font file.
+ *
+ * face_index ::
+ * The index of the face within the resource. The first face has
+ * index~0.
+ * @output:
+ * aface ::
+ * A handle to a new face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * @FT_New_Face_From_FSSpec is identical to @FT_New_Face except it
+ * accepts an FSSpec instead of a path.
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Face_From_FSSpec( FT_Library library,
+ const FSSpec *spec,
+ FT_Long face_index,
+ FT_Face *aface )
+ FT_DEPRECATED_ATTRIBUTE;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Face_From_FSRef
+ *
+ * @description:
+ * Create a new face object from a given resource and typeface index
+ * using an FSRef to the font file.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library resource.
+ *
+ * @input:
+ * spec ::
+ * FSRef to the font file.
+ *
+ * face_index ::
+ * The index of the face within the resource. The first face has
+ * index~0.
+ * @output:
+ * aface ::
+ * A handle to a new face object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * @FT_New_Face_From_FSRef is identical to @FT_New_Face except it accepts
+ * an FSRef instead of a path.
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Face_From_FSRef( FT_Library library,
+ const FSRef *ref,
+ FT_Long face_index,
+ FT_Face *aface )
+ FT_DEPRECATED_ATTRIBUTE;
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* FTMAC_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftmm.h b/Client/ThirdParty/freetype/include/freetype/ftmm.h
new file mode 100644
index 0000000..32579e9
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftmm.h
@@ -0,0 +1,752 @@
+/****************************************************************************
+ *
+ * ftmm.h
+ *
+ * FreeType Multiple Master font interface (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTMM_H_
+#define FTMM_H_
+
+
+#include <freetype/t1tables.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * multiple_masters
+ *
+ * @title:
+ * Multiple Masters
+ *
+ * @abstract:
+ * How to manage Multiple Masters fonts.
+ *
+ * @description:
+ * The following types and functions are used to manage Multiple Master
+ * fonts, i.e., the selection of specific design instances by setting
+ * design axis coordinates.
+ *
+ * Besides Adobe MM fonts, the interface supports Apple's TrueType GX and
+ * OpenType variation fonts. Some of the routines only work with Adobe
+ * MM fonts, others will work with all three types. They are similar
+ * enough that a consistent interface makes sense.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_MM_Axis
+ *
+ * @description:
+ * A structure to model a given axis in design space for Multiple Masters
+ * fonts.
+ *
+ * This structure can't be used for TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @fields:
+ * name ::
+ * The axis's name.
+ *
+ * minimum ::
+ * The axis's minimum design coordinate.
+ *
+ * maximum ::
+ * The axis's maximum design coordinate.
+ */
+ typedef struct FT_MM_Axis_
+ {
+ FT_String* name;
+ FT_Long minimum;
+ FT_Long maximum;
+
+ } FT_MM_Axis;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Multi_Master
+ *
+ * @description:
+ * A structure to model the axes and space of a Multiple Masters font.
+ *
+ * This structure can't be used for TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @fields:
+ * num_axis ::
+ * Number of axes. Cannot exceed~4.
+ *
+ * num_designs ::
+ * Number of designs; should be normally 2^num_axis even though the
+ * Type~1 specification strangely allows for intermediate designs to be
+ * present. This number cannot exceed~16.
+ *
+ * axis ::
+ * A table of axis descriptors.
+ */
+ typedef struct FT_Multi_Master_
+ {
+ FT_UInt num_axis;
+ FT_UInt num_designs;
+ FT_MM_Axis axis[T1_MAX_MM_AXIS];
+
+ } FT_Multi_Master;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Var_Axis
+ *
+ * @description:
+ * A structure to model a given axis in design space for Multiple
+ * Masters, TrueType GX, and OpenType variation fonts.
+ *
+ * @fields:
+ * name ::
+ * The axis's name. Not always meaningful for TrueType GX or OpenType
+ * variation fonts.
+ *
+ * minimum ::
+ * The axis's minimum design coordinate.
+ *
+ * def ::
+ * The axis's default design coordinate. FreeType computes meaningful
+ * default values for Adobe MM fonts.
+ *
+ * maximum ::
+ * The axis's maximum design coordinate.
+ *
+ * tag ::
+ * The axis's tag (the equivalent to 'name' for TrueType GX and
+ * OpenType variation fonts). FreeType provides default values for
+ * Adobe MM fonts if possible.
+ *
+ * strid ::
+ * The axis name entry in the font's 'name' table. This is another
+ * (and often better) version of the 'name' field for TrueType GX or
+ * OpenType variation fonts. Not meaningful for Adobe MM fonts.
+ *
+ * @note:
+ * The fields `minimum`, `def`, and `maximum` are 16.16 fractional values
+ * for TrueType GX and OpenType variation fonts. For Adobe MM fonts, the
+ * values are integers.
+ */
+ typedef struct FT_Var_Axis_
+ {
+ FT_String* name;
+
+ FT_Fixed minimum;
+ FT_Fixed def;
+ FT_Fixed maximum;
+
+ FT_ULong tag;
+ FT_UInt strid;
+
+ } FT_Var_Axis;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Var_Named_Style
+ *
+ * @description:
+ * A structure to model a named instance in a TrueType GX or OpenType
+ * variation font.
+ *
+ * This structure can't be used for Adobe MM fonts.
+ *
+ * @fields:
+ * coords ::
+ * The design coordinates for this instance. This is an array with one
+ * entry for each axis.
+ *
+ * strid ::
+ * The entry in 'name' table identifying this instance.
+ *
+ * psid ::
+ * The entry in 'name' table identifying a PostScript name for this
+ * instance. Value 0xFFFF indicates a missing entry.
+ */
+ typedef struct FT_Var_Named_Style_
+ {
+ FT_Fixed* coords;
+ FT_UInt strid;
+ FT_UInt psid; /* since 2.7.1 */
+
+ } FT_Var_Named_Style;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_MM_Var
+ *
+ * @description:
+ * A structure to model the axes and space of an Adobe MM, TrueType GX,
+ * or OpenType variation font.
+ *
+ * Some fields are specific to one format and not to the others.
+ *
+ * @fields:
+ * num_axis ::
+ * The number of axes. The maximum value is~4 for Adobe MM fonts; no
+ * limit in TrueType GX or OpenType variation fonts.
+ *
+ * num_designs ::
+ * The number of designs; should be normally 2^num_axis for Adobe MM
+ * fonts. Not meaningful for TrueType GX or OpenType variation fonts
+ * (where every glyph could have a different number of designs).
+ *
+ * num_namedstyles ::
+ * The number of named styles; a 'named style' is a tuple of design
+ * coordinates that has a string ID (in the 'name' table) associated
+ * with it. The font can tell the user that, for example,
+ * [Weight=1.5,Width=1.1] is 'Bold'. Another name for 'named style' is
+ * 'named instance'.
+ *
+ * For Adobe Multiple Masters fonts, this value is always zero because
+ * the format does not support named styles.
+ *
+ * axis ::
+ * An axis descriptor table. TrueType GX and OpenType variation fonts
+ * contain slightly more data than Adobe MM fonts. Memory management
+ * of this pointer is done internally by FreeType.
+ *
+ * namedstyle ::
+ * A named style (instance) table. Only meaningful for TrueType GX and
+ * OpenType variation fonts. Memory management of this pointer is done
+ * internally by FreeType.
+ */
+ typedef struct FT_MM_Var_
+ {
+ FT_UInt num_axis;
+ FT_UInt num_designs;
+ FT_UInt num_namedstyles;
+ FT_Var_Axis* axis;
+ FT_Var_Named_Style* namedstyle;
+
+ } FT_MM_Var;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Multi_Master
+ *
+ * @description:
+ * Retrieve a variation descriptor of a given Adobe MM font.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * @output:
+ * amaster ::
+ * The Multiple Masters descriptor.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Multi_Master( FT_Face face,
+ FT_Multi_Master *amaster );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_MM_Var
+ *
+ * @description:
+ * Retrieve a variation descriptor for a given font.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * @output:
+ * amaster ::
+ * The variation descriptor. Allocates a data structure, which the
+ * user must deallocate with a call to @FT_Done_MM_Var after use.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_MM_Var( FT_Face face,
+ FT_MM_Var* *amaster );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_MM_Var
+ *
+ * @description:
+ * Free the memory allocated by @FT_Get_MM_Var.
+ *
+ * @input:
+ * library ::
+ * A handle of the face's parent library object that was used in the
+ * call to @FT_Get_MM_Var to create `amaster`.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Done_MM_Var( FT_Library library,
+ FT_MM_Var *amaster );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_MM_Design_Coordinates
+ *
+ * @description:
+ * For Adobe MM fonts, choose an interpolated font design through design
+ * coordinates.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * num_coords ::
+ * The number of available design coordinates. If it is larger than
+ * the number of axes, ignore the excess values. If it is smaller than
+ * the number of axes, use default values for the remaining axes.
+ *
+ * coords ::
+ * An array of design coordinates.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * [Since 2.8.1] To reset all axes to the default values, call the
+ * function with `num_coords` set to zero and `coords` set to `NULL`.
+ *
+ * [Since 2.9] If `num_coords` is larger than zero, this function sets
+ * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field
+ * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero,
+ * this bit flag gets unset.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_MM_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Var_Design_Coordinates
+ *
+ * @description:
+ * Choose an interpolated font design through design coordinates.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * num_coords ::
+ * The number of available design coordinates. If it is larger than
+ * the number of axes, ignore the excess values. If it is smaller than
+ * the number of axes, use default values for the remaining axes.
+ *
+ * coords ::
+ * An array of design coordinates.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * [Since 2.8.1] To reset all axes to the default values, call the
+ * function with `num_coords` set to zero and `coords` set to `NULL`.
+ * [Since 2.9] 'Default values' means the currently selected named
+ * instance (or the base font if no named instance is selected).
+ *
+ * [Since 2.9] If `num_coords` is larger than zero, this function sets
+ * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field
+ * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero,
+ * this bit flag gets unset.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Var_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Var_Design_Coordinates
+ *
+ * @description:
+ * Get the design coordinates of the currently selected interpolated
+ * font.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * num_coords ::
+ * The number of design coordinates to retrieve. If it is larger than
+ * the number of axes, set the excess values to~0.
+ *
+ * @output:
+ * coords ::
+ * The design coordinates array.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.7.1
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Var_Design_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_MM_Blend_Coordinates
+ *
+ * @description:
+ * Choose an interpolated font design through normalized blend
+ * coordinates.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * num_coords ::
+ * The number of available design coordinates. If it is larger than
+ * the number of axes, ignore the excess values. If it is smaller than
+ * the number of axes, use default values for the remaining axes.
+ *
+ * coords ::
+ * The design coordinates array (each element must be between 0 and 1.0
+ * for Adobe MM fonts, and between -1.0 and 1.0 for TrueType GX and
+ * OpenType variation fonts).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * [Since 2.8.1] To reset all axes to the default values, call the
+ * function with `num_coords` set to zero and `coords` set to `NULL`.
+ * [Since 2.9] 'Default values' means the currently selected named
+ * instance (or the base font if no named instance is selected).
+ *
+ * [Since 2.9] If `num_coords` is larger than zero, this function sets
+ * the @FT_FACE_FLAG_VARIATION bit in @FT_Face's `face_flags` field
+ * (i.e., @FT_IS_VARIATION will return true). If `num_coords` is zero,
+ * this bit flag gets unset.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_MM_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_MM_Blend_Coordinates
+ *
+ * @description:
+ * Get the normalized blend coordinates of the currently selected
+ * interpolated font.
+ *
+ * This function works with all supported variation formats.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * num_coords ::
+ * The number of normalized blend coordinates to retrieve. If it is
+ * larger than the number of axes, set the excess values to~0.5 for
+ * Adobe MM fonts, and to~0 for TrueType GX and OpenType variation
+ * fonts.
+ *
+ * @output:
+ * coords ::
+ * The normalized blend coordinates array.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.7.1
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_MM_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Var_Blend_Coordinates
+ *
+ * @description:
+ * This is another name of @FT_Set_MM_Blend_Coordinates.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Var_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Var_Blend_Coordinates
+ *
+ * @description:
+ * This is another name of @FT_Get_MM_Blend_Coordinates.
+ *
+ * @since:
+ * 2.7.1
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Var_Blend_Coordinates( FT_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_MM_WeightVector
+ *
+ * @description:
+ * For Adobe MM fonts, choose an interpolated font design by directly
+ * setting the weight vector.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * @input:
+ * len ::
+ * The length of the weight vector array. If it is larger than the
+ * number of designs, the extra values are ignored. If it is less than
+ * the number of designs, the remaining values are set to zero.
+ *
+ * weightvector ::
+ * An array representing the weight vector.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Adobe Multiple Master fonts limit the number of designs, and thus the
+ * length of the weight vector to~16.
+ *
+ * If `len` is zero and `weightvector` is `NULL`, the weight vector array
+ * is reset to the default values.
+ *
+ * The Adobe documentation also states that the values in the
+ * WeightVector array must total 1.0 +/-~0.001. In practice this does
+ * not seem to be enforced, so is not enforced here, either.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_MM_WeightVector( FT_Face face,
+ FT_UInt len,
+ FT_Fixed* weightvector );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_MM_WeightVector
+ *
+ * @description:
+ * For Adobe MM fonts, retrieve the current weight vector of the font.
+ *
+ * This function can't be used with TrueType GX or OpenType variation
+ * fonts.
+ *
+ * @inout:
+ * face ::
+ * A handle to the source face.
+ *
+ * len ::
+ * A pointer to the size of the array to be filled. If the size of the
+ * array is less than the number of designs, `FT_Err_Invalid_Argument`
+ * is returned, and `len` is set to the required size (the number of
+ * designs). If the size of the array is greater than the number of
+ * designs, the remaining entries are set to~0. On successful
+ * completion, `len` is set to the number of designs (i.e., the number
+ * of values written to the array).
+ *
+ * @output:
+ * weightvector ::
+ * An array to be filled.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * Adobe Multiple Master fonts limit the number of designs, and thus the
+ * length of the WeightVector to~16.
+ *
+ * @since:
+ * 2.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_MM_WeightVector( FT_Face face,
+ FT_UInt* len,
+ FT_Fixed* weightvector );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VAR_AXIS_FLAG_XXX
+ *
+ * @description:
+ * A list of bit flags used in the return value of
+ * @FT_Get_Var_Axis_Flags.
+ *
+ * @values:
+ * FT_VAR_AXIS_FLAG_HIDDEN ::
+ * The variation axis should not be exposed to user interfaces.
+ *
+ * @since:
+ * 2.8.1
+ */
+#define FT_VAR_AXIS_FLAG_HIDDEN 1
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Var_Axis_Flags
+ *
+ * @description:
+ * Get the 'flags' field of an OpenType Variation Axis Record.
+ *
+ * Not meaningful for Adobe MM fonts (`*flags` is always zero).
+ *
+ * @input:
+ * master ::
+ * The variation descriptor.
+ *
+ * axis_index ::
+ * The index of the requested variation axis.
+ *
+ * @output:
+ * flags ::
+ * The 'flags' field. See @FT_VAR_AXIS_FLAG_XXX for possible values.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.8.1
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Var_Axis_Flags( FT_MM_Var* master,
+ FT_UInt axis_index,
+ FT_UInt* flags );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Named_Instance
+ *
+ * @description:
+ * Set or change the current named instance.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * instance_index ::
+ * The index of the requested instance, starting with value 1. If set
+ * to value 0, FreeType switches to font access without a named
+ * instance.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The function uses the value of `instance_index` to set bits 16-30 of
+ * the face's `face_index` field. It also resets any variation applied
+ * to the font, and the @FT_FACE_FLAG_VARIATION bit of the face's
+ * `face_flags` field gets reset to zero (i.e., @FT_IS_VARIATION will
+ * return false).
+ *
+ * For Adobe MM fonts (which don't have named instances) this function
+ * simply resets the current face to the default instance.
+ *
+ * @since:
+ * 2.9
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Named_Instance( FT_Face face,
+ FT_UInt instance_index );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTMM_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftmodapi.h b/Client/ThirdParty/freetype/include/freetype/ftmodapi.h
new file mode 100644
index 0000000..cb15423
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftmodapi.h
@@ -0,0 +1,806 @@
+/****************************************************************************
+ *
+ * ftmodapi.h
+ *
+ * FreeType modules public interface (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTMODAPI_H_
+#define FTMODAPI_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * module_management
+ *
+ * @title:
+ * Module Management
+ *
+ * @abstract:
+ * How to add, upgrade, remove, and control modules from FreeType.
+ *
+ * @description:
+ * The definitions below are used to manage modules within FreeType.
+ * Internal and external modules can be added, upgraded, and removed at
+ * runtime. For example, an alternative renderer or proprietary font
+ * driver can be registered and prioritized. Additionally, some module
+ * properties can also be controlled.
+ *
+ * Here is a list of existing values of the `module_name` field in the
+ * @FT_Module_Class structure.
+ *
+ * ```
+ * autofitter
+ * bdf
+ * cff
+ * gxvalid
+ * otvalid
+ * pcf
+ * pfr
+ * psaux
+ * pshinter
+ * psnames
+ * raster1
+ * sfnt
+ * smooth
+ * truetype
+ * type1
+ * type42
+ * t1cid
+ * winfonts
+ * ```
+ *
+ * Note that the FreeType Cache sub-system is not a FreeType module.
+ *
+ * @order:
+ * FT_Module
+ * FT_Module_Constructor
+ * FT_Module_Destructor
+ * FT_Module_Requester
+ * FT_Module_Class
+ *
+ * FT_Add_Module
+ * FT_Get_Module
+ * FT_Remove_Module
+ * FT_Add_Default_Modules
+ *
+ * FT_FACE_DRIVER_NAME
+ * FT_Property_Set
+ * FT_Property_Get
+ * FT_Set_Default_Properties
+ *
+ * FT_New_Library
+ * FT_Done_Library
+ * FT_Reference_Library
+ *
+ * FT_Renderer
+ * FT_Renderer_Class
+ *
+ * FT_Get_Renderer
+ * FT_Set_Renderer
+ *
+ * FT_Set_Debug_Hook
+ *
+ */
+
+
+ /* module bit flags */
+#define FT_MODULE_FONT_DRIVER 1 /* this module is a font driver */
+#define FT_MODULE_RENDERER 2 /* this module is a renderer */
+#define FT_MODULE_HINTER 4 /* this module is a glyph hinter */
+#define FT_MODULE_STYLER 8 /* this module is a styler */
+
+#define FT_MODULE_DRIVER_SCALABLE 0x100 /* the driver supports */
+ /* scalable fonts */
+#define FT_MODULE_DRIVER_NO_OUTLINES 0x200 /* the driver does not */
+ /* support vector outlines */
+#define FT_MODULE_DRIVER_HAS_HINTER 0x400 /* the driver provides its */
+ /* own hinter */
+#define FT_MODULE_DRIVER_HINTS_LIGHTLY 0x800 /* the driver's hinter */
+ /* produces LIGHT hints */
+
+
+ /* deprecated values */
+#define ft_module_font_driver FT_MODULE_FONT_DRIVER
+#define ft_module_renderer FT_MODULE_RENDERER
+#define ft_module_hinter FT_MODULE_HINTER
+#define ft_module_styler FT_MODULE_STYLER
+
+#define ft_module_driver_scalable FT_MODULE_DRIVER_SCALABLE
+#define ft_module_driver_no_outlines FT_MODULE_DRIVER_NO_OUTLINES
+#define ft_module_driver_has_hinter FT_MODULE_DRIVER_HAS_HINTER
+#define ft_module_driver_hints_lightly FT_MODULE_DRIVER_HINTS_LIGHTLY
+
+
+ typedef FT_Pointer FT_Module_Interface;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Module_Constructor
+ *
+ * @description:
+ * A function used to initialize (not create) a new module object.
+ *
+ * @input:
+ * module ::
+ * The module to initialize.
+ */
+ typedef FT_Error
+ (*FT_Module_Constructor)( FT_Module module );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Module_Destructor
+ *
+ * @description:
+ * A function used to finalize (not destroy) a given module object.
+ *
+ * @input:
+ * module ::
+ * The module to finalize.
+ */
+ typedef void
+ (*FT_Module_Destructor)( FT_Module module );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Module_Requester
+ *
+ * @description:
+ * A function used to query a given module for a specific interface.
+ *
+ * @input:
+ * module ::
+ * The module to be searched.
+ *
+ * name ::
+ * The name of the interface in the module.
+ */
+ typedef FT_Module_Interface
+ (*FT_Module_Requester)( FT_Module module,
+ const char* name );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Module_Class
+ *
+ * @description:
+ * The module class descriptor. While being a public structure necessary
+ * for FreeType's module bookkeeping, most of the fields are essentially
+ * internal, not to be used directly by an application.
+ *
+ * @fields:
+ * module_flags ::
+ * Bit flags describing the module.
+ *
+ * module_size ::
+ * The size of one module object/instance in bytes.
+ *
+ * module_name ::
+ * The name of the module.
+ *
+ * module_version ::
+ * The version, as a 16.16 fixed number (major.minor).
+ *
+ * module_requires ::
+ * The version of FreeType this module requires, as a 16.16 fixed
+ * number (major.minor). Starts at version 2.0, i.e., 0x20000.
+ *
+ * module_interface ::
+ * A typeless pointer to a structure (which varies between different
+ * modules) that holds the module's interface functions. This is
+ * essentially what `get_interface` returns.
+ *
+ * module_init ::
+ * The initializing function.
+ *
+ * module_done ::
+ * The finalizing function.
+ *
+ * get_interface ::
+ * The interface requesting function.
+ */
+ typedef struct FT_Module_Class_
+ {
+ FT_ULong module_flags;
+ FT_Long module_size;
+ const FT_String* module_name;
+ FT_Fixed module_version;
+ FT_Fixed module_requires;
+
+ const void* module_interface;
+
+ FT_Module_Constructor module_init;
+ FT_Module_Destructor module_done;
+ FT_Module_Requester get_interface;
+
+ } FT_Module_Class;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Add_Module
+ *
+ * @description:
+ * Add a new module to a given library instance.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library object.
+ *
+ * @input:
+ * clazz ::
+ * A pointer to class descriptor for the module.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * An error will be returned if a module already exists by that name, or
+ * if the module requires a version of FreeType that is too great.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Add_Module( FT_Library library,
+ const FT_Module_Class* clazz );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Module
+ *
+ * @description:
+ * Find a module by its name.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object.
+ *
+ * module_name ::
+ * The module's name (as an ASCII string).
+ *
+ * @return:
+ * A module handle. 0~if none was found.
+ *
+ * @note:
+ * FreeType's internal modules aren't documented very well, and you
+ * should look up the source code for details.
+ */
+ FT_EXPORT( FT_Module )
+ FT_Get_Module( FT_Library library,
+ const char* module_name );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Remove_Module
+ *
+ * @description:
+ * Remove a given module from a library instance.
+ *
+ * @inout:
+ * library ::
+ * A handle to a library object.
+ *
+ * @input:
+ * module ::
+ * A handle to a module object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The module object is destroyed by the function in case of success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Remove_Module( FT_Library library,
+ FT_Module module );
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_FACE_DRIVER_NAME
+ *
+ * @description:
+ * A macro that retrieves the name of a font driver from a face object.
+ *
+ * @note:
+ * The font driver name is a valid `module_name` for @FT_Property_Set
+ * and @FT_Property_Get. This is not the same as @FT_Get_Font_Format.
+ *
+ * @since:
+ * 2.11
+ *
+ */
+#define FT_FACE_DRIVER_NAME( face ) \
+ ( ( *(FT_Module_Class**)( ( face )->driver ) )->module_name )
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Property_Set
+ *
+ * @description:
+ * Set a property for a given module.
+ *
+ * @input:
+ * library ::
+ * A handle to the library the module is part of.
+ *
+ * module_name ::
+ * The module name.
+ *
+ * property_name ::
+ * The property name. Properties are described in section
+ * @properties.
+ *
+ * Note that only a few modules have properties.
+ *
+ * value ::
+ * A generic pointer to a variable or structure that gives the new
+ * value of the property. The exact definition of `value` is
+ * dependent on the property; see section @properties.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If `module_name` isn't a valid module name, or `property_name`
+ * doesn't specify a valid property, or if `value` doesn't represent a
+ * valid value for the given property, an error is returned.
+ *
+ * The following example sets property 'bar' (a simple integer) in
+ * module 'foo' to value~1.
+ *
+ * ```
+ * FT_UInt bar;
+ *
+ *
+ * bar = 1;
+ * FT_Property_Set( library, "foo", "bar", &bar );
+ * ```
+ *
+ * Note that the FreeType Cache sub-system doesn't recognize module
+ * property changes. To avoid glyph lookup confusion within the cache
+ * you should call @FTC_Manager_Reset to completely flush the cache if a
+ * module property gets changed after @FTC_Manager_New has been called.
+ *
+ * It is not possible to set properties of the FreeType Cache sub-system
+ * itself with FT_Property_Set; use @FTC_Property_Set instead.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Property_Set( FT_Library library,
+ const FT_String* module_name,
+ const FT_String* property_name,
+ const void* value );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Property_Get
+ *
+ * @description:
+ * Get a module's property value.
+ *
+ * @input:
+ * library ::
+ * A handle to the library the module is part of.
+ *
+ * module_name ::
+ * The module name.
+ *
+ * property_name ::
+ * The property name. Properties are described in section
+ * @properties.
+ *
+ * @inout:
+ * value ::
+ * A generic pointer to a variable or structure that gives the value
+ * of the property. The exact definition of `value` is dependent on
+ * the property; see section @properties.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If `module_name` isn't a valid module name, or `property_name`
+ * doesn't specify a valid property, or if `value` doesn't represent a
+ * valid value for the given property, an error is returned.
+ *
+ * The following example gets property 'baz' (a range) in module 'foo'.
+ *
+ * ```
+ * typedef range_
+ * {
+ * FT_Int32 min;
+ * FT_Int32 max;
+ *
+ * } range;
+ *
+ * range baz;
+ *
+ *
+ * FT_Property_Get( library, "foo", "baz", &baz );
+ * ```
+ *
+ * It is not possible to retrieve properties of the FreeType Cache
+ * sub-system with FT_Property_Get; use @FTC_Property_Get instead.
+ *
+ * @since:
+ * 2.4.11
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Property_Get( FT_Library library,
+ const FT_String* module_name,
+ const FT_String* property_name,
+ void* value );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Default_Properties
+ *
+ * @description:
+ * If compilation option `FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES` is
+ * set, this function reads the `FREETYPE_PROPERTIES` environment
+ * variable to control driver properties. See section @properties for
+ * more.
+ *
+ * If the compilation option is not set, this function does nothing.
+ *
+ * `FREETYPE_PROPERTIES` has the following syntax form (broken here into
+ * multiple lines for better readability).
+ *
+ * ```
+ * <optional whitespace>
+ * <module-name1> ':'
+ * <property-name1> '=' <property-value1>
+ * <whitespace>
+ * <module-name2> ':'
+ * <property-name2> '=' <property-value2>
+ * ...
+ * ```
+ *
+ * Example:
+ *
+ * ```
+ * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
+ * cff:no-stem-darkening=0
+ * ```
+ *
+ * @inout:
+ * library ::
+ * A handle to a new library object.
+ *
+ * @since:
+ * 2.8
+ */
+ FT_EXPORT( void )
+ FT_Set_Default_Properties( FT_Library library );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Reference_Library
+ *
+ * @description:
+ * A counter gets initialized to~1 at the time an @FT_Library structure
+ * is created. This function increments the counter. @FT_Done_Library
+ * then only destroys a library if the counter is~1, otherwise it simply
+ * decrements the counter.
+ *
+ * This function helps in managing life-cycles of structures that
+ * reference @FT_Library objects.
+ *
+ * @input:
+ * library ::
+ * A handle to a target library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @since:
+ * 2.4.2
+ */
+ FT_EXPORT( FT_Error )
+ FT_Reference_Library( FT_Library library );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Library
+ *
+ * @description:
+ * This function is used to create a new FreeType library instance from a
+ * given memory object. It is thus possible to use libraries with
+ * distinct memory allocators within the same program. Note, however,
+ * that the used @FT_Memory structure is expected to remain valid for the
+ * life of the @FT_Library object.
+ *
+ * Normally, you would call this function (followed by a call to
+ * @FT_Add_Default_Modules or a series of calls to @FT_Add_Module, and a
+ * call to @FT_Set_Default_Properties) instead of @FT_Init_FreeType to
+ * initialize the FreeType library.
+ *
+ * Don't use @FT_Done_FreeType but @FT_Done_Library to destroy a library
+ * instance.
+ *
+ * @input:
+ * memory ::
+ * A handle to the original memory object.
+ *
+ * @output:
+ * alibrary ::
+ * A pointer to handle of a new library object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Library.
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Library( FT_Memory memory,
+ FT_Library *alibrary );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Library
+ *
+ * @description:
+ * Discard a given library object. This closes all drivers and discards
+ * all resource objects.
+ *
+ * @input:
+ * library ::
+ * A handle to the target library.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * See the discussion of reference counters in the description of
+ * @FT_Reference_Library.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Done_Library( FT_Library library );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_DebugHook_Func
+ *
+ * @description:
+ * A drop-in replacement (or rather a wrapper) for the bytecode or
+ * charstring interpreter's main loop function.
+ *
+ * Its job is essentially
+ *
+ * - to activate debug mode to enforce single-stepping,
+ *
+ * - to call the main loop function to interpret the next opcode, and
+ *
+ * - to show the changed context to the user.
+ *
+ * An example for such a main loop function is `TT_RunIns` (declared in
+ * FreeType's internal header file `src/truetype/ttinterp.h`).
+ *
+ * Have a look at the source code of the `ttdebug` FreeType demo program
+ * for an example of a drop-in replacement.
+ *
+ * @inout:
+ * arg ::
+ * A typeless pointer, to be cast to the main loop function's data
+ * structure (which depends on the font module). For TrueType fonts
+ * it is bytecode interpreter's execution context, `TT_ExecContext`,
+ * which is declared in FreeType's internal header file `tttypes.h`.
+ */
+ typedef FT_Error
+ (*FT_DebugHook_Func)( void* arg );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_DEBUG_HOOK_XXX
+ *
+ * @description:
+ * A list of named debug hook indices.
+ *
+ * @values:
+ * FT_DEBUG_HOOK_TRUETYPE::
+ * This hook index identifies the TrueType bytecode debugger.
+ */
+#define FT_DEBUG_HOOK_TRUETYPE 0
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Debug_Hook
+ *
+ * @description:
+ * Set a debug hook function for debugging the interpreter of a font
+ * format.
+ *
+ * While this is a public API function, an application needs access to
+ * FreeType's internal header files to do something useful.
+ *
+ * Have a look at the source code of the `ttdebug` FreeType demo program
+ * for an example of its usage.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library object.
+ *
+ * @input:
+ * hook_index ::
+ * The index of the debug hook. You should use defined enumeration
+ * macros like @FT_DEBUG_HOOK_TRUETYPE.
+ *
+ * debug_hook ::
+ * The function used to debug the interpreter.
+ *
+ * @note:
+ * Currently, four debug hook slots are available, but only one (for the
+ * TrueType interpreter) is defined.
+ */
+ FT_EXPORT( void )
+ FT_Set_Debug_Hook( FT_Library library,
+ FT_UInt hook_index,
+ FT_DebugHook_Func debug_hook );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Add_Default_Modules
+ *
+ * @description:
+ * Add the set of default drivers to a given library object. This is
+ * only useful when you create a library object with @FT_New_Library
+ * (usually to plug a custom memory manager).
+ *
+ * @inout:
+ * library ::
+ * A handle to a new library object.
+ */
+ FT_EXPORT( void )
+ FT_Add_Default_Modules( FT_Library library );
+
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * truetype_engine
+ *
+ * @title:
+ * The TrueType Engine
+ *
+ * @abstract:
+ * TrueType bytecode support.
+ *
+ * @description:
+ * This section contains a function used to query the level of TrueType
+ * bytecode support compiled in this version of the library.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_TrueTypeEngineType
+ *
+ * @description:
+ * A list of values describing which kind of TrueType bytecode engine is
+ * implemented in a given FT_Library instance. It is used by the
+ * @FT_Get_TrueType_Engine_Type function.
+ *
+ * @values:
+ * FT_TRUETYPE_ENGINE_TYPE_NONE ::
+ * The library doesn't implement any kind of bytecode interpreter.
+ *
+ * FT_TRUETYPE_ENGINE_TYPE_UNPATENTED ::
+ * Deprecated and removed.
+ *
+ * FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
+ * The library implements a bytecode interpreter that covers the full
+ * instruction set of the TrueType virtual machine (this was governed
+ * by patents until May 2010, hence the name).
+ *
+ * @since:
+ * 2.2
+ *
+ */
+ typedef enum FT_TrueTypeEngineType_
+ {
+ FT_TRUETYPE_ENGINE_TYPE_NONE = 0,
+ FT_TRUETYPE_ENGINE_TYPE_UNPATENTED,
+ FT_TRUETYPE_ENGINE_TYPE_PATENTED
+
+ } FT_TrueTypeEngineType;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_TrueType_Engine_Type
+ *
+ * @description:
+ * Return an @FT_TrueTypeEngineType value to indicate which level of the
+ * TrueType virtual machine a given library instance supports.
+ *
+ * @input:
+ * library ::
+ * A library instance.
+ *
+ * @return:
+ * A value indicating which level is supported.
+ *
+ * @since:
+ * 2.2
+ *
+ */
+ FT_EXPORT( FT_TrueTypeEngineType )
+ FT_Get_TrueType_Engine_Type( FT_Library library );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTMODAPI_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftmoderr.h b/Client/ThirdParty/freetype/include/freetype/ftmoderr.h
new file mode 100644
index 0000000..b417cd5
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftmoderr.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+ *
+ * ftmoderr.h
+ *
+ * FreeType module error offsets (specification).
+ *
+ * Copyright (C) 2001-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This file is used to define the FreeType module error codes.
+ *
+ * If the macro `FT_CONFIG_OPTION_USE_MODULE_ERRORS` in `ftoption.h` is
+ * set, the lower byte of an error value identifies the error code as
+ * usual. In addition, the higher byte identifies the module. For
+ * example, the error `FT_Err_Invalid_File_Format` has value 0x0003, the
+ * error `TT_Err_Invalid_File_Format` has value 0x1303, the error
+ * `T1_Err_Invalid_File_Format` has value 0x1403, etc.
+ *
+ * Note that `FT_Err_Ok`, `TT_Err_Ok`, etc. are always equal to zero,
+ * including the high byte.
+ *
+ * If `FT_CONFIG_OPTION_USE_MODULE_ERRORS` isn't set, the higher byte of an
+ * error value is set to zero.
+ *
+ * To hide the various `XXX_Err_` prefixes in the source code, FreeType
+ * provides some macros in `fttypes.h`.
+ *
+ * FT_ERR( err )
+ *
+ * Add current error module prefix (as defined with the `FT_ERR_PREFIX`
+ * macro) to `err`. For example, in the BDF module the line
+ *
+ * ```
+ * error = FT_ERR( Invalid_Outline );
+ * ```
+ *
+ * expands to
+ *
+ * ```
+ * error = BDF_Err_Invalid_Outline;
+ * ```
+ *
+ * For simplicity, you can always use `FT_Err_Ok` directly instead of
+ * `FT_ERR( Ok )`.
+ *
+ * FT_ERR_EQ( errcode, err )
+ * FT_ERR_NEQ( errcode, err )
+ *
+ * Compare error code `errcode` with the error `err` for equality and
+ * inequality, respectively. Example:
+ *
+ * ```
+ * if ( FT_ERR_EQ( error, Invalid_Outline ) )
+ * ...
+ * ```
+ *
+ * Using this macro you don't have to think about error prefixes. Of
+ * course, if module errors are not active, the above example is the
+ * same as
+ *
+ * ```
+ * if ( error == FT_Err_Invalid_Outline )
+ * ...
+ * ```
+ *
+ * FT_ERROR_BASE( errcode )
+ * FT_ERROR_MODULE( errcode )
+ *
+ * Get base error and module error code, respectively.
+ *
+ * It can also be used to create a module error message table easily with
+ * something like
+ *
+ * ```
+ * #undef FTMODERR_H_
+ * #define FT_MODERRDEF( e, v, s ) { FT_Mod_Err_ ## e, s },
+ * #define FT_MODERR_START_LIST {
+ * #define FT_MODERR_END_LIST { 0, 0 } };
+ *
+ * const struct
+ * {
+ * int mod_err_offset;
+ * const char* mod_err_msg
+ * } ft_mod_errors[] =
+ *
+ * #include <freetype/ftmoderr.h>
+ * ```
+ *
+ */
+
+
+#ifndef FTMODERR_H_
+#define FTMODERR_H_
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** SETUP MACROS *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#undef FT_NEED_EXTERN_C
+
+#ifndef FT_MODERRDEF
+
+#ifdef FT_CONFIG_OPTION_USE_MODULE_ERRORS
+#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = v,
+#else
+#define FT_MODERRDEF( e, v, s ) FT_Mod_Err_ ## e = 0,
+#endif
+
+#define FT_MODERR_START_LIST enum {
+#define FT_MODERR_END_LIST FT_Mod_Err_Max };
+
+#ifdef __cplusplus
+#define FT_NEED_EXTERN_C
+ extern "C" {
+#endif
+
+#endif /* !FT_MODERRDEF */
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** LIST MODULE ERROR BASES *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#ifdef FT_MODERR_START_LIST
+ FT_MODERR_START_LIST
+#endif
+
+
+ FT_MODERRDEF( Base, 0x000, "base module" )
+ FT_MODERRDEF( Autofit, 0x100, "autofitter module" )
+ FT_MODERRDEF( BDF, 0x200, "BDF module" )
+ FT_MODERRDEF( Bzip2, 0x300, "Bzip2 module" )
+ FT_MODERRDEF( Cache, 0x400, "cache module" )
+ FT_MODERRDEF( CFF, 0x500, "CFF module" )
+ FT_MODERRDEF( CID, 0x600, "CID module" )
+ FT_MODERRDEF( Gzip, 0x700, "Gzip module" )
+ FT_MODERRDEF( LZW, 0x800, "LZW module" )
+ FT_MODERRDEF( OTvalid, 0x900, "OpenType validation module" )
+ FT_MODERRDEF( PCF, 0xA00, "PCF module" )
+ FT_MODERRDEF( PFR, 0xB00, "PFR module" )
+ FT_MODERRDEF( PSaux, 0xC00, "PS auxiliary module" )
+ FT_MODERRDEF( PShinter, 0xD00, "PS hinter module" )
+ FT_MODERRDEF( PSnames, 0xE00, "PS names module" )
+ FT_MODERRDEF( Raster, 0xF00, "raster module" )
+ FT_MODERRDEF( SFNT, 0x1000, "SFNT module" )
+ FT_MODERRDEF( Smooth, 0x1100, "smooth raster module" )
+ FT_MODERRDEF( TrueType, 0x1200, "TrueType module" )
+ FT_MODERRDEF( Type1, 0x1300, "Type 1 module" )
+ FT_MODERRDEF( Type42, 0x1400, "Type 42 module" )
+ FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
+ FT_MODERRDEF( GXvalid, 0x1600, "GX validation module" )
+ FT_MODERRDEF( Sdf, 0x1700, "Signed distance field raster module" )
+
+
+#ifdef FT_MODERR_END_LIST
+ FT_MODERR_END_LIST
+#endif
+
+
+ /*******************************************************************/
+ /*******************************************************************/
+ /***** *****/
+ /***** CLEANUP *****/
+ /***** *****/
+ /*******************************************************************/
+ /*******************************************************************/
+
+
+#ifdef FT_NEED_EXTERN_C
+ }
+#endif
+
+#undef FT_MODERR_START_LIST
+#undef FT_MODERR_END_LIST
+#undef FT_MODERRDEF
+#undef FT_NEED_EXTERN_C
+
+
+#endif /* FTMODERR_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftotval.h b/Client/ThirdParty/freetype/include/freetype/ftotval.h
new file mode 100644
index 0000000..00f9727
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftotval.h
@@ -0,0 +1,206 @@
+/****************************************************************************
+ *
+ * ftotval.h
+ *
+ * FreeType API for validating OpenType tables (specification).
+ *
+ * Copyright (C) 2004-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+/****************************************************************************
+ *
+ *
+ * Warning: This module might be moved to a different library in the
+ * future to avoid a tight dependency between FreeType and the
+ * OpenType specification.
+ *
+ *
+ */
+
+
+#ifndef FTOTVAL_H_
+#define FTOTVAL_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * ot_validation
+ *
+ * @title:
+ * OpenType Validation
+ *
+ * @abstract:
+ * An API to validate OpenType tables.
+ *
+ * @description:
+ * This section contains the declaration of functions to validate some
+ * OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).
+ *
+ * @order:
+ * FT_OpenType_Validate
+ * FT_OpenType_Free
+ *
+ * FT_VALIDATE_OTXXX
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_VALIDATE_OTXXX
+ *
+ * @description:
+ * A list of bit-field constants used with @FT_OpenType_Validate to
+ * indicate which OpenType tables should be validated.
+ *
+ * @values:
+ * FT_VALIDATE_BASE ::
+ * Validate BASE table.
+ *
+ * FT_VALIDATE_GDEF ::
+ * Validate GDEF table.
+ *
+ * FT_VALIDATE_GPOS ::
+ * Validate GPOS table.
+ *
+ * FT_VALIDATE_GSUB ::
+ * Validate GSUB table.
+ *
+ * FT_VALIDATE_JSTF ::
+ * Validate JSTF table.
+ *
+ * FT_VALIDATE_MATH ::
+ * Validate MATH table.
+ *
+ * FT_VALIDATE_OT ::
+ * Validate all OpenType tables (BASE, GDEF, GPOS, GSUB, JSTF, MATH).
+ *
+ */
+#define FT_VALIDATE_BASE 0x0100
+#define FT_VALIDATE_GDEF 0x0200
+#define FT_VALIDATE_GPOS 0x0400
+#define FT_VALIDATE_GSUB 0x0800
+#define FT_VALIDATE_JSTF 0x1000
+#define FT_VALIDATE_MATH 0x2000
+
+#define FT_VALIDATE_OT ( FT_VALIDATE_BASE | \
+ FT_VALIDATE_GDEF | \
+ FT_VALIDATE_GPOS | \
+ FT_VALIDATE_GSUB | \
+ FT_VALIDATE_JSTF | \
+ FT_VALIDATE_MATH )
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_OpenType_Validate
+ *
+ * @description:
+ * Validate various OpenType tables to assure that all offsets and
+ * indices are valid. The idea is that a higher-level library that
+ * actually does the text layout can access those tables without error
+ * checking (which can be quite time consuming).
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * validation_flags ::
+ * A bit field that specifies the tables to be validated. See
+ * @FT_VALIDATE_OTXXX for possible values.
+ *
+ * @output:
+ * BASE_table ::
+ * A pointer to the BASE table.
+ *
+ * GDEF_table ::
+ * A pointer to the GDEF table.
+ *
+ * GPOS_table ::
+ * A pointer to the GPOS table.
+ *
+ * GSUB_table ::
+ * A pointer to the GSUB table.
+ *
+ * JSTF_table ::
+ * A pointer to the JSTF table.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with OpenType fonts, returning an error
+ * otherwise.
+ *
+ * After use, the application should deallocate the five tables with
+ * @FT_OpenType_Free. A `NULL` value indicates that the table either
+ * doesn't exist in the font, or the application hasn't asked for
+ * validation.
+ */
+ FT_EXPORT( FT_Error )
+ FT_OpenType_Validate( FT_Face face,
+ FT_UInt validation_flags,
+ FT_Bytes *BASE_table,
+ FT_Bytes *GDEF_table,
+ FT_Bytes *GPOS_table,
+ FT_Bytes *GSUB_table,
+ FT_Bytes *JSTF_table );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_OpenType_Free
+ *
+ * @description:
+ * Free the buffer allocated by OpenType validator.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * table ::
+ * The pointer to the buffer that is allocated by
+ * @FT_OpenType_Validate.
+ *
+ * @note:
+ * This function must be used to free the buffer allocated by
+ * @FT_OpenType_Validate only.
+ */
+ FT_EXPORT( void )
+ FT_OpenType_Free( FT_Face face,
+ FT_Bytes table );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTOTVAL_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftoutln.h b/Client/ThirdParty/freetype/include/freetype/ftoutln.h
new file mode 100644
index 0000000..6bb5f80
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftoutln.h
@@ -0,0 +1,586 @@
+/****************************************************************************
+ *
+ * ftoutln.h
+ *
+ * Support for the FT_Outline type used to store glyph shapes of
+ * most scalable font formats (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTOUTLN_H_
+#define FTOUTLN_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * outline_processing
+ *
+ * @title:
+ * Outline Processing
+ *
+ * @abstract:
+ * Functions to create, transform, and render vectorial glyph images.
+ *
+ * @description:
+ * This section contains routines used to create and destroy scalable
+ * glyph images known as 'outlines'. These can also be measured,
+ * transformed, and converted into bitmaps and pixmaps.
+ *
+ * @order:
+ * FT_Outline
+ * FT_Outline_New
+ * FT_Outline_Done
+ * FT_Outline_Copy
+ * FT_Outline_Translate
+ * FT_Outline_Transform
+ * FT_Outline_Embolden
+ * FT_Outline_EmboldenXY
+ * FT_Outline_Reverse
+ * FT_Outline_Check
+ *
+ * FT_Outline_Get_CBox
+ * FT_Outline_Get_BBox
+ *
+ * FT_Outline_Get_Bitmap
+ * FT_Outline_Render
+ * FT_Outline_Decompose
+ * FT_Outline_Funcs
+ * FT_Outline_MoveToFunc
+ * FT_Outline_LineToFunc
+ * FT_Outline_ConicToFunc
+ * FT_Outline_CubicToFunc
+ *
+ * FT_Orientation
+ * FT_Outline_Get_Orientation
+ *
+ * FT_OUTLINE_XXX
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Decompose
+ *
+ * @description:
+ * Walk over an outline's structure to decompose it into individual
+ * segments and Bezier arcs. This function also emits 'move to'
+ * operations to indicate the start of new contours in the outline.
+ *
+ * @input:
+ * outline ::
+ * A pointer to the source target.
+ *
+ * func_interface ::
+ * A table of 'emitters', i.e., function pointers called during
+ * decomposition to indicate path operations.
+ *
+ * @inout:
+ * user ::
+ * A typeless pointer that is passed to each emitter during the
+ * decomposition. It can be used to store the state during the
+ * decomposition.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * A contour that contains a single point only is represented by a 'move
+ * to' operation followed by 'line to' to the same point. In most cases,
+ * it is best to filter this out before using the outline for stroking
+ * purposes (otherwise it would result in a visible dot when round caps
+ * are used).
+ *
+ * Similarly, the function returns success for an empty outline also
+ * (doing nothing, this is, not calling any emitter); if necessary, you
+ * should filter this out, too.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Decompose( FT_Outline* outline,
+ const FT_Outline_Funcs* func_interface,
+ void* user );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_New
+ *
+ * @description:
+ * Create a new outline of a given size.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object from where the outline is allocated.
+ * Note however that the new outline will **not** necessarily be
+ * **freed**, when destroying the library, by @FT_Done_FreeType.
+ *
+ * numPoints ::
+ * The maximum number of points within the outline. Must be smaller
+ * than or equal to 0xFFFF (65535).
+ *
+ * numContours ::
+ * The maximum number of contours within the outline. This value must
+ * be in the range 0 to `numPoints`.
+ *
+ * @output:
+ * anoutline ::
+ * A handle to the new outline.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The reason why this function takes a `library` parameter is simply to
+ * use the library's memory allocator.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_New( FT_Library library,
+ FT_UInt numPoints,
+ FT_Int numContours,
+ FT_Outline *anoutline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Done
+ *
+ * @description:
+ * Destroy an outline created with @FT_Outline_New.
+ *
+ * @input:
+ * library ::
+ * A handle of the library object used to allocate the outline.
+ *
+ * outline ::
+ * A pointer to the outline object to be discarded.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If the outline's 'owner' field is not set, only the outline descriptor
+ * will be released.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Done( FT_Library library,
+ FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Check
+ *
+ * @description:
+ * Check the contents of an outline descriptor.
+ *
+ * @input:
+ * outline ::
+ * A handle to a source outline.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * An empty outline, or an outline with a single point only is also
+ * valid.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Check( FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_CBox
+ *
+ * @description:
+ * Return an outline's 'control box'. The control box encloses all the
+ * outline's points, including Bezier control points. Though it
+ * coincides with the exact bounding box for most glyphs, it can be
+ * slightly larger in some situations (like when rotating an outline that
+ * contains Bezier outside arcs).
+ *
+ * Computing the control box is very fast, while getting the bounding box
+ * can take much more time as it needs to walk over all segments and arcs
+ * in the outline. To get the latter, you can use the 'ftbbox'
+ * component, which is dedicated to this single task.
+ *
+ * @input:
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @output:
+ * acbox ::
+ * The outline's control box.
+ *
+ * @note:
+ * See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
+ */
+ FT_EXPORT( void )
+ FT_Outline_Get_CBox( const FT_Outline* outline,
+ FT_BBox *acbox );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Translate
+ *
+ * @description:
+ * Apply a simple translation to the points of an outline.
+ *
+ * @inout:
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * @input:
+ * xOffset ::
+ * The horizontal offset.
+ *
+ * yOffset ::
+ * The vertical offset.
+ */
+ FT_EXPORT( void )
+ FT_Outline_Translate( const FT_Outline* outline,
+ FT_Pos xOffset,
+ FT_Pos yOffset );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Copy
+ *
+ * @description:
+ * Copy an outline into another one. Both objects must have the same
+ * sizes (number of points & number of contours) when this function is
+ * called.
+ *
+ * @input:
+ * source ::
+ * A handle to the source outline.
+ *
+ * @output:
+ * target ::
+ * A handle to the target outline.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Copy( const FT_Outline* source,
+ FT_Outline *target );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Transform
+ *
+ * @description:
+ * Apply a simple 2x2 matrix to all of an outline's points. Useful for
+ * applying rotations, slanting, flipping, etc.
+ *
+ * @inout:
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * @input:
+ * matrix ::
+ * A pointer to the transformation matrix.
+ *
+ * @note:
+ * You can use @FT_Outline_Translate if you need to translate the
+ * outline's points.
+ */
+ FT_EXPORT( void )
+ FT_Outline_Transform( const FT_Outline* outline,
+ const FT_Matrix* matrix );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Embolden
+ *
+ * @description:
+ * Embolden an outline. The new outline will be at most 4~times
+ * `strength` pixels wider and higher. You may think of the left and
+ * bottom borders as unchanged.
+ *
+ * Negative `strength` values to reduce the outline thickness are
+ * possible also.
+ *
+ * @inout:
+ * outline ::
+ * A handle to the target outline.
+ *
+ * @input:
+ * strength ::
+ * How strong the glyph is emboldened. Expressed in 26.6 pixel format.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The used algorithm to increase or decrease the thickness of the glyph
+ * doesn't change the number of points; this means that certain
+ * situations like acute angles or intersections are sometimes handled
+ * incorrectly.
+ *
+ * If you need 'better' metrics values you should call
+ * @FT_Outline_Get_CBox or @FT_Outline_Get_BBox.
+ *
+ * To get meaningful results, font scaling values must be set with
+ * functions like @FT_Set_Char_Size before calling FT_Render_Glyph.
+ *
+ * @example:
+ * ```
+ * FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
+ *
+ * if ( face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
+ * FT_Outline_Embolden( &face->glyph->outline, strength );
+ * ```
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Embolden( FT_Outline* outline,
+ FT_Pos strength );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_EmboldenXY
+ *
+ * @description:
+ * Embolden an outline. The new outline will be `xstrength` pixels wider
+ * and `ystrength` pixels higher. Otherwise, it is similar to
+ * @FT_Outline_Embolden, which uses the same strength in both directions.
+ *
+ * @since:
+ * 2.4.10
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_EmboldenXY( FT_Outline* outline,
+ FT_Pos xstrength,
+ FT_Pos ystrength );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Reverse
+ *
+ * @description:
+ * Reverse the drawing direction of an outline. This is used to ensure
+ * consistent fill conventions for mirrored glyphs.
+ *
+ * @inout:
+ * outline ::
+ * A pointer to the target outline descriptor.
+ *
+ * @note:
+ * This function toggles the bit flag @FT_OUTLINE_REVERSE_FILL in the
+ * outline's `flags` field.
+ *
+ * It shouldn't be used by a normal client application, unless it knows
+ * what it is doing.
+ */
+ FT_EXPORT( void )
+ FT_Outline_Reverse( FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_Bitmap
+ *
+ * @description:
+ * Render an outline within a bitmap. The outline's image is simply
+ * OR-ed to the target bitmap.
+ *
+ * @input:
+ * library ::
+ * A handle to a FreeType library object.
+ *
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @inout:
+ * abitmap ::
+ * A pointer to the target bitmap descriptor.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function does **not create** the bitmap, it only renders an
+ * outline image within the one you pass to it! Consequently, the
+ * various fields in `abitmap` should be set accordingly.
+ *
+ * It will use the raster corresponding to the default glyph format.
+ *
+ * The value of the `num_grays` field in `abitmap` is ignored. If you
+ * select the gray-level rasterizer, and you want less than 256 gray
+ * levels, you have to use @FT_Outline_Render directly.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Get_Bitmap( FT_Library library,
+ FT_Outline* outline,
+ const FT_Bitmap *abitmap );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Render
+ *
+ * @description:
+ * Render an outline within a bitmap using the current scan-convert.
+ *
+ * @input:
+ * library ::
+ * A handle to a FreeType library object.
+ *
+ * outline ::
+ * A pointer to the source outline descriptor.
+ *
+ * @inout:
+ * params ::
+ * A pointer to an @FT_Raster_Params structure used to describe the
+ * rendering operation.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This advanced function uses @FT_Raster_Params as an argument.
+ * The field `params.source` will be set to `outline` before the scan
+ * converter is called, which means that the value you give to it is
+ * actually ignored. Either `params.target` must point to preallocated
+ * bitmap, or @FT_RASTER_FLAG_DIRECT must be set in `params.flags`
+ * allowing FreeType rasterizer to be used for direct composition,
+ * translucency, etc. See @FT_Raster_Params for more details.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Outline_Render( FT_Library library,
+ FT_Outline* outline,
+ FT_Raster_Params* params );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Orientation
+ *
+ * @description:
+ * A list of values used to describe an outline's contour orientation.
+ *
+ * The TrueType and PostScript specifications use different conventions
+ * to determine whether outline contours should be filled or unfilled.
+ *
+ * @values:
+ * FT_ORIENTATION_TRUETYPE ::
+ * According to the TrueType specification, clockwise contours must be
+ * filled, and counter-clockwise ones must be unfilled.
+ *
+ * FT_ORIENTATION_POSTSCRIPT ::
+ * According to the PostScript specification, counter-clockwise
+ * contours must be filled, and clockwise ones must be unfilled.
+ *
+ * FT_ORIENTATION_FILL_RIGHT ::
+ * This is identical to @FT_ORIENTATION_TRUETYPE, but is used to
+ * remember that in TrueType, everything that is to the right of the
+ * drawing direction of a contour must be filled.
+ *
+ * FT_ORIENTATION_FILL_LEFT ::
+ * This is identical to @FT_ORIENTATION_POSTSCRIPT, but is used to
+ * remember that in PostScript, everything that is to the left of the
+ * drawing direction of a contour must be filled.
+ *
+ * FT_ORIENTATION_NONE ::
+ * The orientation cannot be determined. That is, different parts of
+ * the glyph have different orientation.
+ *
+ */
+ typedef enum FT_Orientation_
+ {
+ FT_ORIENTATION_TRUETYPE = 0,
+ FT_ORIENTATION_POSTSCRIPT = 1,
+ FT_ORIENTATION_FILL_RIGHT = FT_ORIENTATION_TRUETYPE,
+ FT_ORIENTATION_FILL_LEFT = FT_ORIENTATION_POSTSCRIPT,
+ FT_ORIENTATION_NONE
+
+ } FT_Orientation;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_Get_Orientation
+ *
+ * @description:
+ * This function analyzes a glyph outline and tries to compute its fill
+ * orientation (see @FT_Orientation). This is done by integrating the
+ * total area covered by the outline. The positive integral corresponds
+ * to the clockwise orientation and @FT_ORIENTATION_POSTSCRIPT is
+ * returned. The negative integral corresponds to the counter-clockwise
+ * orientation and @FT_ORIENTATION_TRUETYPE is returned.
+ *
+ * Note that this will return @FT_ORIENTATION_TRUETYPE for empty
+ * outlines.
+ *
+ * @input:
+ * outline ::
+ * A handle to the source outline.
+ *
+ * @return:
+ * The orientation.
+ *
+ */
+ FT_EXPORT( FT_Orientation )
+ FT_Outline_Get_Orientation( FT_Outline* outline );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTOUTLN_H_ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftparams.h b/Client/ThirdParty/freetype/include/freetype/ftparams.h
new file mode 100644
index 0000000..04a3f44
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftparams.h
@@ -0,0 +1,203 @@
+/****************************************************************************
+ *
+ * ftparams.h
+ *
+ * FreeType API for possible FT_Parameter tags (specification only).
+ *
+ * Copyright (C) 2017-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTPARAMS_H_
+#define FTPARAMS_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * parameter_tags
+ *
+ * @title:
+ * Parameter Tags
+ *
+ * @abstract:
+ * Macros for driver property and font loading parameter tags.
+ *
+ * @description:
+ * This section contains macros for the @FT_Parameter structure that are
+ * used with various functions to activate some special functionality or
+ * different behaviour of various components of FreeType.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
+ *
+ * @description:
+ * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
+ * family names in the 'name' table (introduced in OpenType version 1.4).
+ * Use this for backward compatibility with legacy systems that have a
+ * four-faces-per-family restriction.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY \
+ FT_MAKE_TAG( 'i', 'g', 'p', 'f' )
+
+
+ /* this constant is deprecated */
+#define FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY \
+ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
+ *
+ * @description:
+ * A tag for @FT_Parameter to make @FT_Open_Face ignore typographic
+ * subfamily names in the 'name' table (introduced in OpenType version
+ * 1.4). Use this for backward compatibility with legacy systems that
+ * have a four-faces-per-family restriction.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY \
+ FT_MAKE_TAG( 'i', 'g', 'p', 's' )
+
+
+ /* this constant is deprecated */
+#define FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY \
+ FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_INCREMENTAL
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Open_Face to indicate
+ * incremental glyph loading.
+ *
+ */
+#define FT_PARAM_TAG_INCREMENTAL \
+ FT_MAKE_TAG( 'i', 'n', 'c', 'r' )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_LCD_FILTER_WEIGHTS
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Face_Properties. The
+ * corresponding argument specifies the five LCD filter weights for a
+ * given face (if using @FT_LOAD_TARGET_LCD, for example), overriding the
+ * global default values or the values set up with
+ * @FT_Library_SetLcdFilterWeights.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \
+ FT_MAKE_TAG( 'l', 'c', 'd', 'f' )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_RANDOM_SEED
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Face_Properties. The
+ * corresponding 32bit signed integer argument overrides the font
+ * driver's random seed value with a face-specific one; see @random-seed.
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_RANDOM_SEED \
+ FT_MAKE_TAG( 's', 'e', 'e', 'd' )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_STEM_DARKENING
+ *
+ * @description:
+ * An @FT_Parameter tag to be used with @FT_Face_Properties. The
+ * corresponding Boolean argument specifies whether to apply stem
+ * darkening, overriding the global default values or the values set up
+ * with @FT_Property_Set (see @no-stem-darkening).
+ *
+ * This is a passive setting that only takes effect if the font driver or
+ * autohinter honors it, which the CFF, Type~1, and CID drivers always
+ * do, but the autohinter only in 'light' hinting mode (as of version
+ * 2.9).
+ *
+ * @since:
+ * 2.8
+ *
+ */
+#define FT_PARAM_TAG_STEM_DARKENING \
+ FT_MAKE_TAG( 'd', 'a', 'r', 'k' )
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_PARAM_TAG_UNPATENTED_HINTING
+ *
+ * @description:
+ * Deprecated, no effect.
+ *
+ * Previously: A constant used as the tag of an @FT_Parameter structure
+ * to indicate that unpatented methods only should be used by the
+ * TrueType bytecode interpreter for a typeface opened by @FT_Open_Face.
+ *
+ */
+#define FT_PARAM_TAG_UNPATENTED_HINTING \
+ FT_MAKE_TAG( 'u', 'n', 'p', 'a' )
+
+
+ /* */
+
+
+FT_END_HEADER
+
+
+#endif /* FTPARAMS_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftpfr.h b/Client/ThirdParty/freetype/include/freetype/ftpfr.h
new file mode 100644
index 0000000..fbdb14c
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftpfr.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+ *
+ * ftpfr.h
+ *
+ * FreeType API for accessing PFR-specific data (specification only).
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTPFR_H_
+#define FTPFR_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * pfr_fonts
+ *
+ * @title:
+ * PFR Fonts
+ *
+ * @abstract:
+ * PFR/TrueDoc-specific API.
+ *
+ * @description:
+ * This section contains the declaration of PFR-specific functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Metrics
+ *
+ * @description:
+ * Return the outline and metrics resolutions of a given PFR face.
+ *
+ * @input:
+ * face ::
+ * Handle to the input face. It can be a non-PFR face.
+ *
+ * @output:
+ * aoutline_resolution ::
+ * Outline resolution. This is equivalent to `face->units_per_EM` for
+ * non-PFR fonts. Optional (parameter can be `NULL`).
+ *
+ * ametrics_resolution ::
+ * Metrics resolution. This is equivalent to `outline_resolution` for
+ * non-PFR fonts. Optional (parameter can be `NULL`).
+ *
+ * ametrics_x_scale ::
+ * A 16.16 fixed-point number used to scale distance expressed in
+ * metrics units to device subpixels. This is equivalent to
+ * `face->size->x_scale`, but for metrics only. Optional (parameter
+ * can be `NULL`).
+ *
+ * ametrics_y_scale ::
+ * Same as `ametrics_x_scale` but for the vertical direction.
+ * optional (parameter can be `NULL`).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If the input face is not a PFR, this function will return an error.
+ * However, in all cases, it will return valid values.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PFR_Metrics( FT_Face face,
+ FT_UInt *aoutline_resolution,
+ FT_UInt *ametrics_resolution,
+ FT_Fixed *ametrics_x_scale,
+ FT_Fixed *ametrics_y_scale );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Kerning
+ *
+ * @description:
+ * Return the kerning pair corresponding to two glyphs in a PFR face.
+ * The distance is expressed in metrics units, unlike the result of
+ * @FT_Get_Kerning.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * left ::
+ * Index of the left glyph.
+ *
+ * right ::
+ * Index of the right glyph.
+ *
+ * @output:
+ * avector ::
+ * A kerning vector.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function always return distances in original PFR metrics units.
+ * This is unlike @FT_Get_Kerning with the @FT_KERNING_UNSCALED mode,
+ * which always returns distances converted to outline units.
+ *
+ * You can use the value of the `x_scale` and `y_scale` parameters
+ * returned by @FT_Get_PFR_Metrics to scale these to device subpixels.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PFR_Kerning( FT_Face face,
+ FT_UInt left,
+ FT_UInt right,
+ FT_Vector *avector );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PFR_Advance
+ *
+ * @description:
+ * Return a given glyph advance, expressed in original metrics units,
+ * from a PFR font.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * gindex ::
+ * The glyph index.
+ *
+ * @output:
+ * aadvance ::
+ * The glyph advance in metrics units.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You can use the `x_scale` or `y_scale` results of @FT_Get_PFR_Metrics
+ * to convert the advance to device subpixels (i.e., 1/64th of pixels).
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PFR_Advance( FT_Face face,
+ FT_UInt gindex,
+ FT_Pos *aadvance );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTPFR_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftrender.h b/Client/ThirdParty/freetype/include/freetype/ftrender.h
new file mode 100644
index 0000000..48d489d
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftrender.h
@@ -0,0 +1,244 @@
+/****************************************************************************
+ *
+ * ftrender.h
+ *
+ * FreeType renderer modules public interface (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTRENDER_H_
+#define FTRENDER_H_
+
+
+#include <freetype/ftmodapi.h>
+#include <freetype/ftglyph.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * module_management
+ *
+ */
+
+
+ /* create a new glyph object */
+ typedef FT_Error
+ (*FT_Glyph_InitFunc)( FT_Glyph glyph,
+ FT_GlyphSlot slot );
+
+ /* destroys a given glyph object */
+ typedef void
+ (*FT_Glyph_DoneFunc)( FT_Glyph glyph );
+
+ typedef void
+ (*FT_Glyph_TransformFunc)( FT_Glyph glyph,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta );
+
+ typedef void
+ (*FT_Glyph_GetBBoxFunc)( FT_Glyph glyph,
+ FT_BBox* abbox );
+
+ typedef FT_Error
+ (*FT_Glyph_CopyFunc)( FT_Glyph source,
+ FT_Glyph target );
+
+ typedef FT_Error
+ (*FT_Glyph_PrepareFunc)( FT_Glyph glyph,
+ FT_GlyphSlot slot );
+
+/* deprecated */
+#define FT_Glyph_Init_Func FT_Glyph_InitFunc
+#define FT_Glyph_Done_Func FT_Glyph_DoneFunc
+#define FT_Glyph_Transform_Func FT_Glyph_TransformFunc
+#define FT_Glyph_BBox_Func FT_Glyph_GetBBoxFunc
+#define FT_Glyph_Copy_Func FT_Glyph_CopyFunc
+#define FT_Glyph_Prepare_Func FT_Glyph_PrepareFunc
+
+
+ struct FT_Glyph_Class_
+ {
+ FT_Long glyph_size;
+ FT_Glyph_Format glyph_format;
+
+ FT_Glyph_InitFunc glyph_init;
+ FT_Glyph_DoneFunc glyph_done;
+ FT_Glyph_CopyFunc glyph_copy;
+ FT_Glyph_TransformFunc glyph_transform;
+ FT_Glyph_GetBBoxFunc glyph_bbox;
+ FT_Glyph_PrepareFunc glyph_prepare;
+ };
+
+
+ typedef FT_Error
+ (*FT_Renderer_RenderFunc)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin );
+
+ typedef FT_Error
+ (*FT_Renderer_TransformFunc)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ const FT_Matrix* matrix,
+ const FT_Vector* delta );
+
+
+ typedef void
+ (*FT_Renderer_GetCBoxFunc)( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_BBox* cbox );
+
+
+ typedef FT_Error
+ (*FT_Renderer_SetModeFunc)( FT_Renderer renderer,
+ FT_ULong mode_tag,
+ FT_Pointer mode_ptr );
+
+/* deprecated identifiers */
+#define FTRenderer_render FT_Renderer_RenderFunc
+#define FTRenderer_transform FT_Renderer_TransformFunc
+#define FTRenderer_getCBox FT_Renderer_GetCBoxFunc
+#define FTRenderer_setMode FT_Renderer_SetModeFunc
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Renderer_Class
+ *
+ * @description:
+ * The renderer module class descriptor.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_Module_Class fields.
+ *
+ * glyph_format ::
+ * The glyph image format this renderer handles.
+ *
+ * render_glyph ::
+ * A method used to render the image that is in a given glyph slot into
+ * a bitmap.
+ *
+ * transform_glyph ::
+ * A method used to transform the image that is in a given glyph slot.
+ *
+ * get_glyph_cbox ::
+ * A method used to access the glyph's cbox.
+ *
+ * set_mode ::
+ * A method used to pass additional parameters.
+ *
+ * raster_class ::
+ * For @FT_GLYPH_FORMAT_OUTLINE renderers only. This is a pointer to
+ * its raster's class.
+ */
+ typedef struct FT_Renderer_Class_
+ {
+ FT_Module_Class root;
+
+ FT_Glyph_Format glyph_format;
+
+ FT_Renderer_RenderFunc render_glyph;
+ FT_Renderer_TransformFunc transform_glyph;
+ FT_Renderer_GetCBoxFunc get_glyph_cbox;
+ FT_Renderer_SetModeFunc set_mode;
+
+ FT_Raster_Funcs* raster_class;
+
+ } FT_Renderer_Class;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Renderer
+ *
+ * @description:
+ * Retrieve the current renderer for a given glyph format.
+ *
+ * @input:
+ * library ::
+ * A handle to the library object.
+ *
+ * format ::
+ * The glyph format.
+ *
+ * @return:
+ * A renderer handle. 0~if none found.
+ *
+ * @note:
+ * An error will be returned if a module already exists by that name, or
+ * if the module requires a version of FreeType that is too great.
+ *
+ * To add a new renderer, simply use @FT_Add_Module. To retrieve a
+ * renderer by its name, use @FT_Get_Module.
+ */
+ FT_EXPORT( FT_Renderer )
+ FT_Get_Renderer( FT_Library library,
+ FT_Glyph_Format format );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Set_Renderer
+ *
+ * @description:
+ * Set the current renderer to use, and set additional mode.
+ *
+ * @inout:
+ * library ::
+ * A handle to the library object.
+ *
+ * @input:
+ * renderer ::
+ * A handle to the renderer object.
+ *
+ * num_params ::
+ * The number of additional parameters.
+ *
+ * parameters ::
+ * Additional parameters.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * In case of success, the renderer will be used to convert glyph images
+ * in the renderer's known format into bitmaps.
+ *
+ * This doesn't change the current renderer for other formats.
+ *
+ * Currently, no FreeType renderer module uses `parameters`; you should
+ * thus always pass `NULL` as the value.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Set_Renderer( FT_Library library,
+ FT_Renderer renderer,
+ FT_UInt num_params,
+ FT_Parameter* parameters );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTRENDER_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftsizes.h b/Client/ThirdParty/freetype/include/freetype/ftsizes.h
new file mode 100644
index 0000000..2236639
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftsizes.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+ *
+ * ftsizes.h
+ *
+ * FreeType size objects management (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * Typical application would normally not need to use these functions.
+ * However, they have been placed in a public API for the rare cases where
+ * they are needed.
+ *
+ */
+
+
+#ifndef FTSIZES_H_
+#define FTSIZES_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * sizes_management
+ *
+ * @title:
+ * Size Management
+ *
+ * @abstract:
+ * Managing multiple sizes per face.
+ *
+ * @description:
+ * When creating a new face object (e.g., with @FT_New_Face), an @FT_Size
+ * object is automatically created and used to store all pixel-size
+ * dependent information, available in the `face->size` field.
+ *
+ * It is however possible to create more sizes for a given face, mostly
+ * in order to manage several character pixel sizes of the same font
+ * family and style. See @FT_New_Size and @FT_Done_Size.
+ *
+ * Note that @FT_Set_Pixel_Sizes and @FT_Set_Char_Size only modify the
+ * contents of the current 'active' size; you thus need to use
+ * @FT_Activate_Size to change it.
+ *
+ * 99% of applications won't need the functions provided here, especially
+ * if they use the caching sub-system, so be cautious when using these.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_New_Size
+ *
+ * @description:
+ * Create a new size object from a given face object.
+ *
+ * @input:
+ * face ::
+ * A handle to a parent face object.
+ *
+ * @output:
+ * asize ::
+ * A handle to a new size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You need to call @FT_Activate_Size in order to select the new size for
+ * upcoming calls to @FT_Set_Pixel_Sizes, @FT_Set_Char_Size,
+ * @FT_Load_Glyph, @FT_Load_Char, etc.
+ */
+ FT_EXPORT( FT_Error )
+ FT_New_Size( FT_Face face,
+ FT_Size* size );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Done_Size
+ *
+ * @description:
+ * Discard a given size object. Note that @FT_Done_Face automatically
+ * discards all size objects allocated with @FT_New_Size.
+ *
+ * @input:
+ * size ::
+ * A handle to a target size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Done_Size( FT_Size size );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Activate_Size
+ *
+ * @description:
+ * Even though it is possible to create several size objects for a given
+ * face (see @FT_New_Size for details), functions like @FT_Load_Glyph or
+ * @FT_Load_Char only use the one that has been activated last to
+ * determine the 'current character pixel size'.
+ *
+ * This function can be used to 'activate' a previously created size
+ * object.
+ *
+ * @input:
+ * size ::
+ * A handle to a target size object.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If `face` is the size's parent face object, this function changes the
+ * value of `face->size` to the input size handle.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Activate_Size( FT_Size size );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTSIZES_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftsnames.h b/Client/ThirdParty/freetype/include/freetype/ftsnames.h
new file mode 100644
index 0000000..c7f6581
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftsnames.h
@@ -0,0 +1,272 @@
+/****************************************************************************
+ *
+ * ftsnames.h
+ *
+ * Simple interface to access SFNT 'name' tables (which are used
+ * to hold font names, copyright info, notices, etc.) (specification).
+ *
+ * This is _not_ used to retrieve glyph names!
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSNAMES_H_
+#define FTSNAMES_H_
+
+
+#include <freetype/freetype.h>
+#include <freetype/ftparams.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * sfnt_names
+ *
+ * @title:
+ * SFNT Names
+ *
+ * @abstract:
+ * Access the names embedded in TrueType and OpenType files.
+ *
+ * @description:
+ * The TrueType and OpenType specifications allow the inclusion of a
+ * special names table ('name') in font files. This table contains
+ * textual (and internationalized) information regarding the font, like
+ * family name, copyright, version, etc.
+ *
+ * The definitions below are used to access them if available.
+ *
+ * Note that this has nothing to do with glyph names!
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SfntName
+ *
+ * @description:
+ * A structure used to model an SFNT 'name' table entry.
+ *
+ * @fields:
+ * platform_id ::
+ * The platform ID for `string`. See @TT_PLATFORM_XXX for possible
+ * values.
+ *
+ * encoding_id ::
+ * The encoding ID for `string`. See @TT_APPLE_ID_XXX, @TT_MAC_ID_XXX,
+ * @TT_ISO_ID_XXX, @TT_MS_ID_XXX, and @TT_ADOBE_ID_XXX for possible
+ * values.
+ *
+ * language_id ::
+ * The language ID for `string`. See @TT_MAC_LANGID_XXX and
+ * @TT_MS_LANGID_XXX for possible values.
+ *
+ * Registered OpenType values for `language_id` are always smaller than
+ * 0x8000; values equal or larger than 0x8000 usually indicate a
+ * language tag string (introduced in OpenType version 1.6). Use
+ * function @FT_Get_Sfnt_LangTag with `language_id` as its argument to
+ * retrieve the associated language tag.
+ *
+ * name_id ::
+ * An identifier for `string`. See @TT_NAME_ID_XXX for possible
+ * values.
+ *
+ * string ::
+ * The 'name' string. Note that its format differs depending on the
+ * (platform,encoding) pair, being either a string of bytes (without a
+ * terminating `NULL` byte) or containing UTF-16BE entities.
+ *
+ * string_len ::
+ * The length of `string` in bytes.
+ *
+ * @note:
+ * Please refer to the TrueType or OpenType specification for more
+ * details.
+ */
+ typedef struct FT_SfntName_
+ {
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+ FT_UShort language_id;
+ FT_UShort name_id;
+
+ FT_Byte* string; /* this string is *not* null-terminated! */
+ FT_UInt string_len; /* in bytes */
+
+ } FT_SfntName;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_Name_Count
+ *
+ * @description:
+ * Retrieve the number of name strings in the SFNT 'name' table.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * @return:
+ * The number of strings in the 'name' table.
+ *
+ * @note:
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_SFNT_NAMES` is not defined in `ftoption.h`.
+ */
+ FT_EXPORT( FT_UInt )
+ FT_Get_Sfnt_Name_Count( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_Name
+ *
+ * @description:
+ * Retrieve a string of the SFNT 'name' table for a given index.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * idx ::
+ * The index of the 'name' string.
+ *
+ * @output:
+ * aname ::
+ * The indexed @FT_SfntName structure.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The `string` array returned in the `aname` structure is not
+ * null-terminated. Note that you don't have to deallocate `string` by
+ * yourself; FreeType takes care of it if you call @FT_Done_Face.
+ *
+ * Use @FT_Get_Sfnt_Name_Count to get the total number of available
+ * 'name' table entries, then do a loop until you get the right platform,
+ * encoding, and name ID.
+ *
+ * 'name' table format~1 entries can use language tags also, see
+ * @FT_Get_Sfnt_LangTag.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_SFNT_NAMES` is not defined in `ftoption.h`.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Sfnt_Name( FT_Face face,
+ FT_UInt idx,
+ FT_SfntName *aname );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SfntLangTag
+ *
+ * @description:
+ * A structure to model a language tag entry from an SFNT 'name' table.
+ *
+ * @fields:
+ * string ::
+ * The language tag string, encoded in UTF-16BE (without trailing
+ * `NULL` bytes).
+ *
+ * string_len ::
+ * The length of `string` in **bytes**.
+ *
+ * @note:
+ * Please refer to the TrueType or OpenType specification for more
+ * details.
+ *
+ * @since:
+ * 2.8
+ */
+ typedef struct FT_SfntLangTag_
+ {
+ FT_Byte* string; /* this string is *not* null-terminated! */
+ FT_UInt string_len; /* in bytes */
+
+ } FT_SfntLangTag;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_LangTag
+ *
+ * @description:
+ * Retrieve the language tag associated with a language ID of an SFNT
+ * 'name' table entry.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * langID ::
+ * The language ID, as returned by @FT_Get_Sfnt_Name. This is always a
+ * value larger than 0x8000.
+ *
+ * @output:
+ * alangTag ::
+ * The language tag associated with the 'name' table entry's language
+ * ID.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The `string` array returned in the `alangTag` structure is not
+ * null-terminated. Note that you don't have to deallocate `string` by
+ * yourself; FreeType takes care of it if you call @FT_Done_Face.
+ *
+ * Only 'name' table format~1 supports language tags. For format~0
+ * tables, this function always returns FT_Err_Invalid_Table. For
+ * invalid format~1 language ID values, FT_Err_Invalid_Argument is
+ * returned.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_SFNT_NAMES` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.8
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_Sfnt_LangTag( FT_Face face,
+ FT_UInt langID,
+ FT_SfntLangTag *alangTag );
+
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTSNAMES_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftstroke.h b/Client/ThirdParty/freetype/include/freetype/ftstroke.h
new file mode 100644
index 0000000..88b2a8a
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftstroke.h
@@ -0,0 +1,773 @@
+/****************************************************************************
+ *
+ * ftstroke.h
+ *
+ * FreeType path stroker (specification).
+ *
+ * Copyright (C) 2002-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSTROKE_H_
+#define FTSTROKE_H_
+
+#include <freetype/ftoutln.h>
+#include <freetype/ftglyph.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * glyph_stroker
+ *
+ * @title:
+ * Glyph Stroker
+ *
+ * @abstract:
+ * Generating bordered and stroked glyphs.
+ *
+ * @description:
+ * This component generates stroked outlines of a given vectorial glyph.
+ * It also allows you to retrieve the 'outside' and/or the 'inside'
+ * borders of the stroke.
+ *
+ * This can be useful to generate 'bordered' glyph, i.e., glyphs
+ * displayed with a colored (and anti-aliased) border around their
+ * shape.
+ *
+ * @order:
+ * FT_Stroker
+ *
+ * FT_Stroker_LineJoin
+ * FT_Stroker_LineCap
+ * FT_StrokerBorder
+ *
+ * FT_Outline_GetInsideBorder
+ * FT_Outline_GetOutsideBorder
+ *
+ * FT_Glyph_Stroke
+ * FT_Glyph_StrokeBorder
+ *
+ * FT_Stroker_New
+ * FT_Stroker_Set
+ * FT_Stroker_Rewind
+ * FT_Stroker_ParseOutline
+ * FT_Stroker_Done
+ *
+ * FT_Stroker_BeginSubPath
+ * FT_Stroker_EndSubPath
+ *
+ * FT_Stroker_LineTo
+ * FT_Stroker_ConicTo
+ * FT_Stroker_CubicTo
+ *
+ * FT_Stroker_GetBorderCounts
+ * FT_Stroker_ExportBorder
+ * FT_Stroker_GetCounts
+ * FT_Stroker_Export
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Stroker
+ *
+ * @description:
+ * Opaque handle to a path stroker object.
+ */
+ typedef struct FT_StrokerRec_* FT_Stroker;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Stroker_LineJoin
+ *
+ * @description:
+ * These values determine how two joining lines are rendered in a
+ * stroker.
+ *
+ * @values:
+ * FT_STROKER_LINEJOIN_ROUND ::
+ * Used to render rounded line joins. Circular arcs are used to join
+ * two lines smoothly.
+ *
+ * FT_STROKER_LINEJOIN_BEVEL ::
+ * Used to render beveled line joins. The outer corner of the joined
+ * lines is filled by enclosing the triangular region of the corner
+ * with a straight line between the outer corners of each stroke.
+ *
+ * FT_STROKER_LINEJOIN_MITER_FIXED ::
+ * Used to render mitered line joins, with fixed bevels if the miter
+ * limit is exceeded. The outer edges of the strokes for the two
+ * segments are extended until they meet at an angle. A bevel join
+ * (see above) is used if the segments meet at too sharp an angle and
+ * the outer edges meet beyond a distance corresponding to the meter
+ * limit. This prevents long spikes being created.
+ * `FT_STROKER_LINEJOIN_MITER_FIXED` generates a miter line join as
+ * used in PostScript and PDF.
+ *
+ * FT_STROKER_LINEJOIN_MITER_VARIABLE ::
+ * FT_STROKER_LINEJOIN_MITER ::
+ * Used to render mitered line joins, with variable bevels if the miter
+ * limit is exceeded. The intersection of the strokes is clipped
+ * perpendicularly to the bisector, at a distance corresponding to
+ * the miter limit. This prevents long spikes being created.
+ * `FT_STROKER_LINEJOIN_MITER_VARIABLE` generates a mitered line join
+ * as used in XPS. `FT_STROKER_LINEJOIN_MITER` is an alias for
+ * `FT_STROKER_LINEJOIN_MITER_VARIABLE`, retained for backward
+ * compatibility.
+ */
+ typedef enum FT_Stroker_LineJoin_
+ {
+ FT_STROKER_LINEJOIN_ROUND = 0,
+ FT_STROKER_LINEJOIN_BEVEL = 1,
+ FT_STROKER_LINEJOIN_MITER_VARIABLE = 2,
+ FT_STROKER_LINEJOIN_MITER = FT_STROKER_LINEJOIN_MITER_VARIABLE,
+ FT_STROKER_LINEJOIN_MITER_FIXED = 3
+
+ } FT_Stroker_LineJoin;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Stroker_LineCap
+ *
+ * @description:
+ * These values determine how the end of opened sub-paths are rendered in
+ * a stroke.
+ *
+ * @values:
+ * FT_STROKER_LINECAP_BUTT ::
+ * The end of lines is rendered as a full stop on the last point
+ * itself.
+ *
+ * FT_STROKER_LINECAP_ROUND ::
+ * The end of lines is rendered as a half-circle around the last point.
+ *
+ * FT_STROKER_LINECAP_SQUARE ::
+ * The end of lines is rendered as a square around the last point.
+ */
+ typedef enum FT_Stroker_LineCap_
+ {
+ FT_STROKER_LINECAP_BUTT = 0,
+ FT_STROKER_LINECAP_ROUND,
+ FT_STROKER_LINECAP_SQUARE
+
+ } FT_Stroker_LineCap;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_StrokerBorder
+ *
+ * @description:
+ * These values are used to select a given stroke border in
+ * @FT_Stroker_GetBorderCounts and @FT_Stroker_ExportBorder.
+ *
+ * @values:
+ * FT_STROKER_BORDER_LEFT ::
+ * Select the left border, relative to the drawing direction.
+ *
+ * FT_STROKER_BORDER_RIGHT ::
+ * Select the right border, relative to the drawing direction.
+ *
+ * @note:
+ * Applications are generally interested in the 'inside' and 'outside'
+ * borders. However, there is no direct mapping between these and the
+ * 'left' and 'right' ones, since this really depends on the glyph's
+ * drawing orientation, which varies between font formats.
+ *
+ * You can however use @FT_Outline_GetInsideBorder and
+ * @FT_Outline_GetOutsideBorder to get these.
+ */
+ typedef enum FT_StrokerBorder_
+ {
+ FT_STROKER_BORDER_LEFT = 0,
+ FT_STROKER_BORDER_RIGHT
+
+ } FT_StrokerBorder;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_GetInsideBorder
+ *
+ * @description:
+ * Retrieve the @FT_StrokerBorder value corresponding to the 'inside'
+ * borders of a given outline.
+ *
+ * @input:
+ * outline ::
+ * The source outline handle.
+ *
+ * @return:
+ * The border index. @FT_STROKER_BORDER_RIGHT for empty or invalid
+ * outlines.
+ */
+ FT_EXPORT( FT_StrokerBorder )
+ FT_Outline_GetInsideBorder( FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Outline_GetOutsideBorder
+ *
+ * @description:
+ * Retrieve the @FT_StrokerBorder value corresponding to the 'outside'
+ * borders of a given outline.
+ *
+ * @input:
+ * outline ::
+ * The source outline handle.
+ *
+ * @return:
+ * The border index. @FT_STROKER_BORDER_LEFT for empty or invalid
+ * outlines.
+ */
+ FT_EXPORT( FT_StrokerBorder )
+ FT_Outline_GetOutsideBorder( FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_New
+ *
+ * @description:
+ * Create a new stroker object.
+ *
+ * @input:
+ * library ::
+ * FreeType library handle.
+ *
+ * @output:
+ * astroker ::
+ * A new stroker object handle. `NULL` in case of error.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_New( FT_Library library,
+ FT_Stroker *astroker );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_Set
+ *
+ * @description:
+ * Reset a stroker object's attributes.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * radius ::
+ * The border radius.
+ *
+ * line_cap ::
+ * The line cap style.
+ *
+ * line_join ::
+ * The line join style.
+ *
+ * miter_limit ::
+ * The maximum reciprocal sine of half-angle at the miter join,
+ * expressed as 16.16 fixed point value.
+ *
+ * @note:
+ * The `radius` is expressed in the same units as the outline
+ * coordinates.
+ *
+ * The `miter_limit` multiplied by the `radius` gives the maximum size
+ * of a miter spike, at which it is clipped for
+ * @FT_STROKER_LINEJOIN_MITER_VARIABLE or replaced with a bevel join for
+ * @FT_STROKER_LINEJOIN_MITER_FIXED.
+ *
+ * This function calls @FT_Stroker_Rewind automatically.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Set( FT_Stroker stroker,
+ FT_Fixed radius,
+ FT_Stroker_LineCap line_cap,
+ FT_Stroker_LineJoin line_join,
+ FT_Fixed miter_limit );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_Rewind
+ *
+ * @description:
+ * Reset a stroker object without changing its attributes. You should
+ * call this function before beginning a new series of calls to
+ * @FT_Stroker_BeginSubPath or @FT_Stroker_EndSubPath.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Rewind( FT_Stroker stroker );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_ParseOutline
+ *
+ * @description:
+ * A convenience function used to parse a whole outline with the stroker.
+ * The resulting outline(s) can be retrieved later by functions like
+ * @FT_Stroker_GetCounts and @FT_Stroker_Export.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * outline ::
+ * The source outline.
+ *
+ * opened ::
+ * A boolean. If~1, the outline is treated as an open path instead of
+ * a closed one.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If `opened` is~0 (the default), the outline is treated as a closed
+ * path, and the stroker generates two distinct 'border' outlines.
+ *
+ * If `opened` is~1, the outline is processed as an open path, and the
+ * stroker generates a single 'stroke' outline.
+ *
+ * This function calls @FT_Stroker_Rewind automatically.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_ParseOutline( FT_Stroker stroker,
+ FT_Outline* outline,
+ FT_Bool opened );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_BeginSubPath
+ *
+ * @description:
+ * Start a new sub-path in the stroker.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * to ::
+ * A pointer to the start vector.
+ *
+ * open ::
+ * A boolean. If~1, the sub-path is treated as an open one.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function is useful when you need to stroke a path that is not
+ * stored as an @FT_Outline object.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_BeginSubPath( FT_Stroker stroker,
+ FT_Vector* to,
+ FT_Bool open );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_EndSubPath
+ *
+ * @description:
+ * Close the current sub-path in the stroker.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should call this function after @FT_Stroker_BeginSubPath. If the
+ * subpath was not 'opened', this function 'draws' a single line segment
+ * to the start position when needed.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_EndSubPath( FT_Stroker stroker );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_LineTo
+ *
+ * @description:
+ * 'Draw' a single line segment in the stroker's current sub-path, from
+ * the last position.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * to ::
+ * A pointer to the destination point.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should call this function between @FT_Stroker_BeginSubPath and
+ * @FT_Stroker_EndSubPath.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_LineTo( FT_Stroker stroker,
+ FT_Vector* to );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_ConicTo
+ *
+ * @description:
+ * 'Draw' a single quadratic Bezier in the stroker's current sub-path,
+ * from the last position.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * control ::
+ * A pointer to a Bezier control point.
+ *
+ * to ::
+ * A pointer to the destination point.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should call this function between @FT_Stroker_BeginSubPath and
+ * @FT_Stroker_EndSubPath.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_ConicTo( FT_Stroker stroker,
+ FT_Vector* control,
+ FT_Vector* to );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_CubicTo
+ *
+ * @description:
+ * 'Draw' a single cubic Bezier in the stroker's current sub-path, from
+ * the last position.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * control1 ::
+ * A pointer to the first Bezier control point.
+ *
+ * control2 ::
+ * A pointer to second Bezier control point.
+ *
+ * to ::
+ * A pointer to the destination point.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * You should call this function between @FT_Stroker_BeginSubPath and
+ * @FT_Stroker_EndSubPath.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_CubicTo( FT_Stroker stroker,
+ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_GetBorderCounts
+ *
+ * @description:
+ * Call this function once you have finished parsing your paths with the
+ * stroker. It returns the number of points and contours necessary to
+ * export one of the 'border' or 'stroke' outlines generated by the
+ * stroker.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * border ::
+ * The border index.
+ *
+ * @output:
+ * anum_points ::
+ * The number of points.
+ *
+ * anum_contours ::
+ * The number of contours.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * When an outline, or a sub-path, is 'closed', the stroker generates two
+ * independent 'border' outlines, named 'left' and 'right'.
+ *
+ * When the outline, or a sub-path, is 'opened', the stroker merges the
+ * 'border' outlines with caps. The 'left' border receives all points,
+ * while the 'right' border becomes empty.
+ *
+ * Use the function @FT_Stroker_GetCounts instead if you want to retrieve
+ * the counts associated to both borders.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_GetBorderCounts( FT_Stroker stroker,
+ FT_StrokerBorder border,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_ExportBorder
+ *
+ * @description:
+ * Call this function after @FT_Stroker_GetBorderCounts to export the
+ * corresponding border to your own @FT_Outline structure.
+ *
+ * Note that this function appends the border points and contours to your
+ * outline, but does not try to resize its arrays.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * border ::
+ * The border index.
+ *
+ * outline ::
+ * The target outline handle.
+ *
+ * @note:
+ * Always call this function after @FT_Stroker_GetBorderCounts to get
+ * sure that there is enough room in your @FT_Outline object to receive
+ * all new data.
+ *
+ * When an outline, or a sub-path, is 'closed', the stroker generates two
+ * independent 'border' outlines, named 'left' and 'right'.
+ *
+ * When the outline, or a sub-path, is 'opened', the stroker merges the
+ * 'border' outlines with caps. The 'left' border receives all points,
+ * while the 'right' border becomes empty.
+ *
+ * Use the function @FT_Stroker_Export instead if you want to retrieve
+ * all borders at once.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_ExportBorder( FT_Stroker stroker,
+ FT_StrokerBorder border,
+ FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_GetCounts
+ *
+ * @description:
+ * Call this function once you have finished parsing your paths with the
+ * stroker. It returns the number of points and contours necessary to
+ * export all points/borders from the stroked outline/path.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * @output:
+ * anum_points ::
+ * The number of points.
+ *
+ * anum_contours ::
+ * The number of contours.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Stroker_GetCounts( FT_Stroker stroker,
+ FT_UInt *anum_points,
+ FT_UInt *anum_contours );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_Export
+ *
+ * @description:
+ * Call this function after @FT_Stroker_GetBorderCounts to export all
+ * borders to your own @FT_Outline structure.
+ *
+ * Note that this function appends the border points and contours to your
+ * outline, but does not try to resize its arrays.
+ *
+ * @input:
+ * stroker ::
+ * The target stroker handle.
+ *
+ * outline ::
+ * The target outline handle.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Export( FT_Stroker stroker,
+ FT_Outline* outline );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Stroker_Done
+ *
+ * @description:
+ * Destroy a stroker object.
+ *
+ * @input:
+ * stroker ::
+ * A stroker handle. Can be `NULL`.
+ */
+ FT_EXPORT( void )
+ FT_Stroker_Done( FT_Stroker stroker );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_Stroke
+ *
+ * @description:
+ * Stroke a given outline glyph object with a given stroker.
+ *
+ * @inout:
+ * pglyph ::
+ * Source glyph handle on input, new glyph handle on output.
+ *
+ * @input:
+ * stroker ::
+ * A stroker handle.
+ *
+ * destroy ::
+ * A Boolean. If~1, the source glyph object is destroyed on success.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source glyph is untouched in case of error.
+ *
+ * Adding stroke may yield a significantly wider and taller glyph
+ * depending on how large of a radius was used to stroke the glyph. You
+ * may need to manually adjust horizontal and vertical advance amounts to
+ * account for this added size.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_Stroke( FT_Glyph *pglyph,
+ FT_Stroker stroker,
+ FT_Bool destroy );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Glyph_StrokeBorder
+ *
+ * @description:
+ * Stroke a given outline glyph object with a given stroker, but only
+ * return either its inside or outside border.
+ *
+ * @inout:
+ * pglyph ::
+ * Source glyph handle on input, new glyph handle on output.
+ *
+ * @input:
+ * stroker ::
+ * A stroker handle.
+ *
+ * inside ::
+ * A Boolean. If~1, return the inside border, otherwise the outside
+ * border.
+ *
+ * destroy ::
+ * A Boolean. If~1, the source glyph object is destroyed on success.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The source glyph is untouched in case of error.
+ *
+ * Adding stroke may yield a significantly wider and taller glyph
+ * depending on how large of a radius was used to stroke the glyph. You
+ * may need to manually adjust horizontal and vertical advance amounts to
+ * account for this added size.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
+ FT_Stroker stroker,
+ FT_Bool inside,
+ FT_Bool destroy );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* FTSTROKE_H_ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftsynth.h b/Client/ThirdParty/freetype/include/freetype/ftsynth.h
new file mode 100644
index 0000000..861dcb5
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftsynth.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+ *
+ * ftsynth.h
+ *
+ * FreeType synthesizing code for emboldening and slanting
+ * (specification).
+ *
+ * Copyright (C) 2000-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********* *********/
+ /********* WARNING, THIS IS ALPHA CODE! THIS API *********/
+ /********* IS DUE TO CHANGE UNTIL STRICTLY NOTIFIED BY THE *********/
+ /********* FREETYPE DEVELOPMENT TEAM *********/
+ /********* *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /* Main reason for not lifting the functions in this module to a */
+ /* 'standard' API is that the used parameters for emboldening and */
+ /* slanting are not configurable. Consider the functions as a */
+ /* code resource that should be copied into the application and */
+ /* adapted to the particular needs. */
+
+
+#ifndef FTSYNTH_H_
+#define FTSYNTH_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /* Embolden a glyph by a 'reasonable' value (which is highly a matter of */
+ /* taste). This function is actually a convenience function, providing */
+ /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden. */
+ /* */
+ /* For emboldened outlines the height, width, and advance metrics are */
+ /* increased by the strength of the emboldening -- this even affects */
+ /* mono-width fonts! */
+ /* */
+ /* You can also call @FT_Outline_Get_CBox to get precise values. */
+ FT_EXPORT( void )
+ FT_GlyphSlot_Embolden( FT_GlyphSlot slot );
+
+ /* Slant an outline glyph to the right by about 12 degrees. */
+ FT_EXPORT( void )
+ FT_GlyphSlot_Oblique( FT_GlyphSlot slot );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTSYNTH_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftsystem.h b/Client/ThirdParty/freetype/include/freetype/ftsystem.h
new file mode 100644
index 0000000..e5abb85
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftsystem.h
@@ -0,0 +1,352 @@
+/****************************************************************************
+ *
+ * ftsystem.h
+ *
+ * FreeType low-level system interface definition (specification).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSYSTEM_H_
+#define FTSYSTEM_H_
+
+
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * system_interface
+ *
+ * @title:
+ * System Interface
+ *
+ * @abstract:
+ * How FreeType manages memory and i/o.
+ *
+ * @description:
+ * This section contains various definitions related to memory management
+ * and i/o access. You need to understand this information if you want to
+ * use a custom memory manager or you own i/o streams.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * M E M O R Y M A N A G E M E N T
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Memory
+ *
+ * @description:
+ * A handle to a given memory manager object, defined with an
+ * @FT_MemoryRec structure.
+ *
+ */
+ typedef struct FT_MemoryRec_* FT_Memory;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Alloc_Func
+ *
+ * @description:
+ * A function used to allocate `size` bytes from `memory`.
+ *
+ * @input:
+ * memory ::
+ * A handle to the source memory manager.
+ *
+ * size ::
+ * The size in bytes to allocate.
+ *
+ * @return:
+ * Address of new memory block. 0~in case of failure.
+ *
+ */
+ typedef void*
+ (*FT_Alloc_Func)( FT_Memory memory,
+ long size );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Free_Func
+ *
+ * @description:
+ * A function used to release a given block of memory.
+ *
+ * @input:
+ * memory ::
+ * A handle to the source memory manager.
+ *
+ * block ::
+ * The address of the target memory block.
+ *
+ */
+ typedef void
+ (*FT_Free_Func)( FT_Memory memory,
+ void* block );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Realloc_Func
+ *
+ * @description:
+ * A function used to re-allocate a given block of memory.
+ *
+ * @input:
+ * memory ::
+ * A handle to the source memory manager.
+ *
+ * cur_size ::
+ * The block's current size in bytes.
+ *
+ * new_size ::
+ * The block's requested new size.
+ *
+ * block ::
+ * The block's current address.
+ *
+ * @return:
+ * New block address. 0~in case of memory shortage.
+ *
+ * @note:
+ * In case of error, the old block must still be available.
+ *
+ */
+ typedef void*
+ (*FT_Realloc_Func)( FT_Memory memory,
+ long cur_size,
+ long new_size,
+ void* block );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_MemoryRec
+ *
+ * @description:
+ * A structure used to describe a given memory manager to FreeType~2.
+ *
+ * @fields:
+ * user ::
+ * A generic typeless pointer for user data.
+ *
+ * alloc ::
+ * A pointer type to an allocation function.
+ *
+ * free ::
+ * A pointer type to an memory freeing function.
+ *
+ * realloc ::
+ * A pointer type to a reallocation function.
+ *
+ */
+ struct FT_MemoryRec_
+ {
+ void* user;
+ FT_Alloc_Func alloc;
+ FT_Free_Func free;
+ FT_Realloc_Func realloc;
+ };
+
+
+ /**************************************************************************
+ *
+ * I / O M A N A G E M E N T
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Stream
+ *
+ * @description:
+ * A handle to an input stream.
+ *
+ * @also:
+ * See @FT_StreamRec for the publicly accessible fields of a given stream
+ * object.
+ *
+ */
+ typedef struct FT_StreamRec_* FT_Stream;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_StreamDesc
+ *
+ * @description:
+ * A union type used to store either a long or a pointer. This is used
+ * to store a file descriptor or a `FILE*` in an input stream.
+ *
+ */
+ typedef union FT_StreamDesc_
+ {
+ long value;
+ void* pointer;
+
+ } FT_StreamDesc;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Stream_IoFunc
+ *
+ * @description:
+ * A function used to seek and read data from a given input stream.
+ *
+ * @input:
+ * stream ::
+ * A handle to the source stream.
+ *
+ * offset ::
+ * The offset of read in stream (always from start).
+ *
+ * buffer ::
+ * The address of the read buffer.
+ *
+ * count ::
+ * The number of bytes to read from the stream.
+ *
+ * @return:
+ * The number of bytes effectively read by the stream.
+ *
+ * @note:
+ * This function might be called to perform a seek or skip operation with
+ * a `count` of~0. A non-zero return value then indicates an error.
+ *
+ */
+ typedef unsigned long
+ (*FT_Stream_IoFunc)( FT_Stream stream,
+ unsigned long offset,
+ unsigned char* buffer,
+ unsigned long count );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Stream_CloseFunc
+ *
+ * @description:
+ * A function used to close a given input stream.
+ *
+ * @input:
+ * stream ::
+ * A handle to the target stream.
+ *
+ */
+ typedef void
+ (*FT_Stream_CloseFunc)( FT_Stream stream );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_StreamRec
+ *
+ * @description:
+ * A structure used to describe an input stream.
+ *
+ * @input:
+ * base ::
+ * For memory-based streams, this is the address of the first stream
+ * byte in memory. This field should always be set to `NULL` for
+ * disk-based streams.
+ *
+ * size ::
+ * The stream size in bytes.
+ *
+ * In case of compressed streams where the size is unknown before
+ * actually doing the decompression, the value is set to 0x7FFFFFFF.
+ * (Note that this size value can occur for normal streams also; it is
+ * thus just a hint.)
+ *
+ * pos ::
+ * The current position within the stream.
+ *
+ * descriptor ::
+ * This field is a union that can hold an integer or a pointer. It is
+ * used by stream implementations to store file descriptors or `FILE*`
+ * pointers.
+ *
+ * pathname ::
+ * This field is completely ignored by FreeType. However, it is often
+ * useful during debugging to use it to store the stream's filename
+ * (where available).
+ *
+ * read ::
+ * The stream's input function.
+ *
+ * close ::
+ * The stream's close function.
+ *
+ * memory ::
+ * The memory manager to use to preload frames. This is set internally
+ * by FreeType and shouldn't be touched by stream implementations.
+ *
+ * cursor ::
+ * This field is set and used internally by FreeType when parsing
+ * frames. In particular, the `FT_GET_XXX` macros use this instead of
+ * the `pos` field.
+ *
+ * limit ::
+ * This field is set and used internally by FreeType when parsing
+ * frames.
+ *
+ */
+ typedef struct FT_StreamRec_
+ {
+ unsigned char* base;
+ unsigned long size;
+ unsigned long pos;
+
+ FT_StreamDesc descriptor;
+ FT_StreamDesc pathname;
+ FT_Stream_IoFunc read;
+ FT_Stream_CloseFunc close;
+
+ FT_Memory memory;
+ unsigned char* cursor;
+ unsigned char* limit;
+
+ } FT_StreamRec;
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTSYSTEM_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/fttrigon.h b/Client/ThirdParty/freetype/include/freetype/fttrigon.h
new file mode 100644
index 0000000..dbe7b0d
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/fttrigon.h
@@ -0,0 +1,350 @@
+/****************************************************************************
+ *
+ * fttrigon.h
+ *
+ * FreeType trigonometric functions (specification).
+ *
+ * Copyright (C) 2001-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTTRIGON_H_
+#define FTTRIGON_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * computations
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Angle
+ *
+ * @description:
+ * This type is used to model angle values in FreeType. Note that the
+ * angle is a 16.16 fixed-point value expressed in degrees.
+ *
+ */
+ typedef FT_Fixed FT_Angle;
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_PI
+ *
+ * @description:
+ * The angle pi expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_PI ( 180L << 16 )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_2PI
+ *
+ * @description:
+ * The angle 2*pi expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_2PI ( FT_ANGLE_PI * 2 )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_PI2
+ *
+ * @description:
+ * The angle pi/2 expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_PI2 ( FT_ANGLE_PI / 2 )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_ANGLE_PI4
+ *
+ * @description:
+ * The angle pi/4 expressed in @FT_Angle units.
+ *
+ */
+#define FT_ANGLE_PI4 ( FT_ANGLE_PI / 4 )
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Sin
+ *
+ * @description:
+ * Return the sinus of a given angle in fixed-point format.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ * @return:
+ * The sinus value.
+ *
+ * @note:
+ * If you need both the sinus and cosinus for a given angle, use the
+ * function @FT_Vector_Unit.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Sin( FT_Angle angle );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Cos
+ *
+ * @description:
+ * Return the cosinus of a given angle in fixed-point format.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ * @return:
+ * The cosinus value.
+ *
+ * @note:
+ * If you need both the sinus and cosinus for a given angle, use the
+ * function @FT_Vector_Unit.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Cos( FT_Angle angle );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Tan
+ *
+ * @description:
+ * Return the tangent of a given angle in fixed-point format.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ * @return:
+ * The tangent value.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Tan( FT_Angle angle );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Atan2
+ *
+ * @description:
+ * Return the arc-tangent corresponding to a given vector (x,y) in the 2d
+ * plane.
+ *
+ * @input:
+ * x ::
+ * The horizontal vector coordinate.
+ *
+ * y ::
+ * The vertical vector coordinate.
+ *
+ * @return:
+ * The arc-tangent value (i.e. angle).
+ *
+ */
+ FT_EXPORT( FT_Angle )
+ FT_Atan2( FT_Fixed x,
+ FT_Fixed y );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Angle_Diff
+ *
+ * @description:
+ * Return the difference between two angles. The result is always
+ * constrained to the ]-PI..PI] interval.
+ *
+ * @input:
+ * angle1 ::
+ * First angle.
+ *
+ * angle2 ::
+ * Second angle.
+ *
+ * @return:
+ * Constrained value of `angle2-angle1`.
+ *
+ */
+ FT_EXPORT( FT_Angle )
+ FT_Angle_Diff( FT_Angle angle1,
+ FT_Angle angle2 );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_Unit
+ *
+ * @description:
+ * Return the unit vector corresponding to a given angle. After the
+ * call, the value of `vec.x` will be `cos(angle)`, and the value of
+ * `vec.y` will be `sin(angle)`.
+ *
+ * This function is useful to retrieve both the sinus and cosinus of a
+ * given angle quickly.
+ *
+ * @output:
+ * vec ::
+ * The address of target vector.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_Unit( FT_Vector* vec,
+ FT_Angle angle );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_Rotate
+ *
+ * @description:
+ * Rotate a vector by a given angle.
+ *
+ * @inout:
+ * vec ::
+ * The address of target vector.
+ *
+ * @input:
+ * angle ::
+ * The input angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_Rotate( FT_Vector* vec,
+ FT_Angle angle );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_Length
+ *
+ * @description:
+ * Return the length of a given vector.
+ *
+ * @input:
+ * vec ::
+ * The address of target vector.
+ *
+ * @return:
+ * The vector length, expressed in the same units that the original
+ * vector coordinates.
+ *
+ */
+ FT_EXPORT( FT_Fixed )
+ FT_Vector_Length( FT_Vector* vec );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_Polarize
+ *
+ * @description:
+ * Compute both the length and angle of a given vector.
+ *
+ * @input:
+ * vec ::
+ * The address of source vector.
+ *
+ * @output:
+ * length ::
+ * The vector length.
+ *
+ * angle ::
+ * The vector angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_Polarize( FT_Vector* vec,
+ FT_Fixed *length,
+ FT_Angle *angle );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Vector_From_Polar
+ *
+ * @description:
+ * Compute vector coordinates from a length and angle.
+ *
+ * @output:
+ * vec ::
+ * The address of source vector.
+ *
+ * @input:
+ * length ::
+ * The vector length.
+ *
+ * angle ::
+ * The vector angle.
+ *
+ */
+ FT_EXPORT( void )
+ FT_Vector_From_Polar( FT_Vector* vec,
+ FT_Fixed length,
+ FT_Angle angle );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTTRIGON_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/fttypes.h b/Client/ThirdParty/freetype/include/freetype/fttypes.h
new file mode 100644
index 0000000..d5ca1c4
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/fttypes.h
@@ -0,0 +1,615 @@
+/****************************************************************************
+ *
+ * fttypes.h
+ *
+ * FreeType simple types definitions (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTTYPES_H_
+#define FTTYPES_H_
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include <freetype/ftsystem.h>
+#include <freetype/ftimage.h>
+
+#include <stddef.h>
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * basic_types
+ *
+ * @title:
+ * Basic Data Types
+ *
+ * @abstract:
+ * The basic data types defined by the library.
+ *
+ * @description:
+ * This section contains the basic data types defined by FreeType~2,
+ * ranging from simple scalar types to bitmap descriptors. More
+ * font-specific structures are defined in a different section.
+ *
+ * @order:
+ * FT_Byte
+ * FT_Bytes
+ * FT_Char
+ * FT_Int
+ * FT_UInt
+ * FT_Int16
+ * FT_UInt16
+ * FT_Int32
+ * FT_UInt32
+ * FT_Int64
+ * FT_UInt64
+ * FT_Short
+ * FT_UShort
+ * FT_Long
+ * FT_ULong
+ * FT_Bool
+ * FT_Offset
+ * FT_PtrDist
+ * FT_String
+ * FT_Tag
+ * FT_Error
+ * FT_Fixed
+ * FT_Pointer
+ * FT_Pos
+ * FT_Vector
+ * FT_BBox
+ * FT_Matrix
+ * FT_FWord
+ * FT_UFWord
+ * FT_F2Dot14
+ * FT_UnitVector
+ * FT_F26Dot6
+ * FT_Data
+ *
+ * FT_MAKE_TAG
+ *
+ * FT_Generic
+ * FT_Generic_Finalizer
+ *
+ * FT_Bitmap
+ * FT_Pixel_Mode
+ * FT_Palette_Mode
+ * FT_Glyph_Format
+ * FT_IMAGE_TAG
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Bool
+ *
+ * @description:
+ * A typedef of unsigned char, used for simple booleans. As usual,
+ * values 1 and~0 represent true and false, respectively.
+ */
+ typedef unsigned char FT_Bool;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_FWord
+ *
+ * @description:
+ * A signed 16-bit integer used to store a distance in original font
+ * units.
+ */
+ typedef signed short FT_FWord; /* distance in FUnits */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UFWord
+ *
+ * @description:
+ * An unsigned 16-bit integer used to store a distance in original font
+ * units.
+ */
+ typedef unsigned short FT_UFWord; /* unsigned distance */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Char
+ *
+ * @description:
+ * A simple typedef for the _signed_ char type.
+ */
+ typedef signed char FT_Char;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Byte
+ *
+ * @description:
+ * A simple typedef for the _unsigned_ char type.
+ */
+ typedef unsigned char FT_Byte;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Bytes
+ *
+ * @description:
+ * A typedef for constant memory areas.
+ */
+ typedef const FT_Byte* FT_Bytes;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Tag
+ *
+ * @description:
+ * A typedef for 32-bit tags (as used in the SFNT format).
+ */
+ typedef FT_UInt32 FT_Tag;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_String
+ *
+ * @description:
+ * A simple typedef for the char type, usually used for strings.
+ */
+ typedef char FT_String;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Short
+ *
+ * @description:
+ * A typedef for signed short.
+ */
+ typedef signed short FT_Short;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UShort
+ *
+ * @description:
+ * A typedef for unsigned short.
+ */
+ typedef unsigned short FT_UShort;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Int
+ *
+ * @description:
+ * A typedef for the int type.
+ */
+ typedef signed int FT_Int;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_UInt
+ *
+ * @description:
+ * A typedef for the unsigned int type.
+ */
+ typedef unsigned int FT_UInt;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Long
+ *
+ * @description:
+ * A typedef for signed long.
+ */
+ typedef signed long FT_Long;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_ULong
+ *
+ * @description:
+ * A typedef for unsigned long.
+ */
+ typedef unsigned long FT_ULong;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_F2Dot14
+ *
+ * @description:
+ * A signed 2.14 fixed-point type used for unit vectors.
+ */
+ typedef signed short FT_F2Dot14;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_F26Dot6
+ *
+ * @description:
+ * A signed 26.6 fixed-point type used for vectorial pixel coordinates.
+ */
+ typedef signed long FT_F26Dot6;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Fixed
+ *
+ * @description:
+ * This type is used to store 16.16 fixed-point values, like scaling
+ * values or matrix coefficients.
+ */
+ typedef signed long FT_Fixed;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Error
+ *
+ * @description:
+ * The FreeType error code type. A value of~0 is always interpreted as a
+ * successful operation.
+ */
+ typedef int FT_Error;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Pointer
+ *
+ * @description:
+ * A simple typedef for a typeless pointer.
+ */
+ typedef void* FT_Pointer;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_Offset
+ *
+ * @description:
+ * This is equivalent to the ANSI~C `size_t` type, i.e., the largest
+ * _unsigned_ integer type used to express a file size or position, or a
+ * memory block size.
+ */
+ typedef size_t FT_Offset;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_PtrDist
+ *
+ * @description:
+ * This is equivalent to the ANSI~C `ptrdiff_t` type, i.e., the largest
+ * _signed_ integer type used to express the distance between two
+ * pointers.
+ */
+ typedef ft_ptrdiff_t FT_PtrDist;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_UnitVector
+ *
+ * @description:
+ * A simple structure used to store a 2D vector unit vector. Uses
+ * FT_F2Dot14 types.
+ *
+ * @fields:
+ * x ::
+ * Horizontal coordinate.
+ *
+ * y ::
+ * Vertical coordinate.
+ */
+ typedef struct FT_UnitVector_
+ {
+ FT_F2Dot14 x;
+ FT_F2Dot14 y;
+
+ } FT_UnitVector;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Matrix
+ *
+ * @description:
+ * A simple structure used to store a 2x2 matrix. Coefficients are in
+ * 16.16 fixed-point format. The computation performed is:
+ *
+ * ```
+ * x' = x*xx + y*xy
+ * y' = x*yx + y*yy
+ * ```
+ *
+ * @fields:
+ * xx ::
+ * Matrix coefficient.
+ *
+ * xy ::
+ * Matrix coefficient.
+ *
+ * yx ::
+ * Matrix coefficient.
+ *
+ * yy ::
+ * Matrix coefficient.
+ */
+ typedef struct FT_Matrix_
+ {
+ FT_Fixed xx, xy;
+ FT_Fixed yx, yy;
+
+ } FT_Matrix;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Data
+ *
+ * @description:
+ * Read-only binary data represented as a pointer and a length.
+ *
+ * @fields:
+ * pointer ::
+ * The data.
+ *
+ * length ::
+ * The length of the data in bytes.
+ */
+ typedef struct FT_Data_
+ {
+ const FT_Byte* pointer;
+ FT_Int length;
+
+ } FT_Data;
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * FT_Generic_Finalizer
+ *
+ * @description:
+ * Describe a function used to destroy the 'client' data of any FreeType
+ * object. See the description of the @FT_Generic type for details of
+ * usage.
+ *
+ * @input:
+ * The address of the FreeType object that is under finalization. Its
+ * client data is accessed through its `generic` field.
+ */
+ typedef void (*FT_Generic_Finalizer)( void* object );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_Generic
+ *
+ * @description:
+ * Client applications often need to associate their own data to a
+ * variety of FreeType core objects. For example, a text layout API
+ * might want to associate a glyph cache to a given size object.
+ *
+ * Some FreeType object contains a `generic` field, of type `FT_Generic`,
+ * which usage is left to client applications and font servers.
+ *
+ * It can be used to store a pointer to client-specific data, as well as
+ * the address of a 'finalizer' function, which will be called by
+ * FreeType when the object is destroyed (for example, the previous
+ * client example would put the address of the glyph cache destructor in
+ * the `finalizer` field).
+ *
+ * @fields:
+ * data ::
+ * A typeless pointer to any client-specified data. This field is
+ * completely ignored by the FreeType library.
+ *
+ * finalizer ::
+ * A pointer to a 'generic finalizer' function, which will be called
+ * when the object is destroyed. If this field is set to `NULL`, no
+ * code will be called.
+ */
+ typedef struct FT_Generic_
+ {
+ void* data;
+ FT_Generic_Finalizer finalizer;
+
+ } FT_Generic;
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_MAKE_TAG
+ *
+ * @description:
+ * This macro converts four-letter tags that are used to label TrueType
+ * tables into an unsigned long, to be used within FreeType.
+ *
+ * @note:
+ * The produced values **must** be 32-bit integers. Don't redefine this
+ * macro.
+ */
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
+ (FT_Tag) \
+ ( ( (FT_ULong)_x1 << 24 ) | \
+ ( (FT_ULong)_x2 << 16 ) | \
+ ( (FT_ULong)_x3 << 8 ) | \
+ (FT_ULong)_x4 )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /* */
+ /* L I S T M A N A G E M E N T */
+ /* */
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * list_processing
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_ListNode
+ *
+ * @description:
+ * Many elements and objects in FreeType are listed through an @FT_List
+ * record (see @FT_ListRec). As its name suggests, an FT_ListNode is a
+ * handle to a single list element.
+ */
+ typedef struct FT_ListNodeRec_* FT_ListNode;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_List
+ *
+ * @description:
+ * A handle to a list record (see @FT_ListRec).
+ */
+ typedef struct FT_ListRec_* FT_List;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ListNodeRec
+ *
+ * @description:
+ * A structure used to hold a single list element.
+ *
+ * @fields:
+ * prev ::
+ * The previous element in the list. `NULL` if first.
+ *
+ * next ::
+ * The next element in the list. `NULL` if last.
+ *
+ * data ::
+ * A typeless pointer to the listed object.
+ */
+ typedef struct FT_ListNodeRec_
+ {
+ FT_ListNode prev;
+ FT_ListNode next;
+ void* data;
+
+ } FT_ListNodeRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_ListRec
+ *
+ * @description:
+ * A structure used to hold a simple doubly-linked list. These are used
+ * in many parts of FreeType.
+ *
+ * @fields:
+ * head ::
+ * The head (first element) of doubly-linked list.
+ *
+ * tail ::
+ * The tail (last element) of doubly-linked list.
+ */
+ typedef struct FT_ListRec_
+ {
+ FT_ListNode head;
+ FT_ListNode tail;
+
+ } FT_ListRec;
+
+ /* */
+
+
+#define FT_IS_EMPTY( list ) ( (list).head == 0 )
+#define FT_BOOL( x ) ( (FT_Bool)( (x) != 0 ) )
+
+ /* concatenate C tokens */
+#define FT_ERR_XCAT( x, y ) x ## y
+#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y )
+
+ /* see `ftmoderr.h` for descriptions of the following macros */
+
+#define FT_ERR( e ) FT_ERR_CAT( FT_ERR_PREFIX, e )
+
+#define FT_ERROR_BASE( x ) ( (x) & 0xFF )
+#define FT_ERROR_MODULE( x ) ( (x) & 0xFF00U )
+
+#define FT_ERR_EQ( x, e ) \
+ ( FT_ERROR_BASE( x ) == FT_ERROR_BASE( FT_ERR( e ) ) )
+#define FT_ERR_NEQ( x, e ) \
+ ( FT_ERROR_BASE( x ) != FT_ERROR_BASE( FT_ERR( e ) ) )
+
+
+FT_END_HEADER
+
+#endif /* FTTYPES_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ftwinfnt.h b/Client/ThirdParty/freetype/include/freetype/ftwinfnt.h
new file mode 100644
index 0000000..b1ef3b6
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ftwinfnt.h
@@ -0,0 +1,276 @@
+/****************************************************************************
+ *
+ * ftwinfnt.h
+ *
+ * FreeType API for accessing Windows fnt-specific data.
+ *
+ * Copyright (C) 2003-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTWINFNT_H_
+#define FTWINFNT_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * winfnt_fonts
+ *
+ * @title:
+ * Window FNT Files
+ *
+ * @abstract:
+ * Windows FNT-specific API.
+ *
+ * @description:
+ * This section contains the declaration of Windows FNT-specific
+ * functions.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_WinFNT_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `charset` byte in @FT_WinFNT_HeaderRec.
+ * Exact mapping tables for the various 'cpXXXX' encodings (except for
+ * 'cp1361') can be found at 'ftp://ftp.unicode.org/Public/' in the
+ * `MAPPINGS/VENDORS/MICSFT/WINDOWS` subdirectory. 'cp1361' is roughly a
+ * superset of `MAPPINGS/OBSOLETE/EASTASIA/KSC/JOHAB.TXT`.
+ *
+ * @values:
+ * FT_WinFNT_ID_DEFAULT ::
+ * This is used for font enumeration and font creation as a 'don't
+ * care' value. Valid font files don't contain this value. When
+ * querying for information about the character set of the font that is
+ * currently selected into a specified device context, this return
+ * value (of the related Windows API) simply denotes failure.
+ *
+ * FT_WinFNT_ID_SYMBOL ::
+ * There is no known mapping table available.
+ *
+ * FT_WinFNT_ID_MAC ::
+ * Mac Roman encoding.
+ *
+ * FT_WinFNT_ID_OEM ::
+ * From Michael Poettgen <michael@poettgen.de>:
+ *
+ * The 'Windows Font Mapping' article says that `FT_WinFNT_ID_OEM` is
+ * used for the charset of vector fonts, like `modern.fon`,
+ * `roman.fon`, and `script.fon` on Windows.
+ *
+ * The 'CreateFont' documentation says: The `FT_WinFNT_ID_OEM` value
+ * specifies a character set that is operating-system dependent.
+ *
+ * The 'IFIMETRICS' documentation from the 'Windows Driver Development
+ * Kit' says: This font supports an OEM-specific character set. The
+ * OEM character set is system dependent.
+ *
+ * In general OEM, as opposed to ANSI (i.e., 'cp1252'), denotes the
+ * second default codepage that most international versions of Windows
+ * have. It is one of the OEM codepages from
+ *
+ * https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers
+ * ,
+ *
+ * and is used for the 'DOS boxes', to support legacy applications. A
+ * German Windows version for example usually uses ANSI codepage 1252
+ * and OEM codepage 850.
+ *
+ * FT_WinFNT_ID_CP874 ::
+ * A superset of Thai TIS 620 and ISO 8859-11.
+ *
+ * FT_WinFNT_ID_CP932 ::
+ * A superset of Japanese Shift-JIS (with minor deviations).
+ *
+ * FT_WinFNT_ID_CP936 ::
+ * A superset of simplified Chinese GB 2312-1980 (with different
+ * ordering and minor deviations).
+ *
+ * FT_WinFNT_ID_CP949 ::
+ * A superset of Korean Hangul KS~C 5601-1987 (with different ordering
+ * and minor deviations).
+ *
+ * FT_WinFNT_ID_CP950 ::
+ * A superset of traditional Chinese Big~5 ETen (with different
+ * ordering and minor deviations).
+ *
+ * FT_WinFNT_ID_CP1250 ::
+ * A superset of East European ISO 8859-2 (with slightly different
+ * ordering).
+ *
+ * FT_WinFNT_ID_CP1251 ::
+ * A superset of Russian ISO 8859-5 (with different ordering).
+ *
+ * FT_WinFNT_ID_CP1252 ::
+ * ANSI encoding. A superset of ISO 8859-1.
+ *
+ * FT_WinFNT_ID_CP1253 ::
+ * A superset of Greek ISO 8859-7 (with minor modifications).
+ *
+ * FT_WinFNT_ID_CP1254 ::
+ * A superset of Turkish ISO 8859-9.
+ *
+ * FT_WinFNT_ID_CP1255 ::
+ * A superset of Hebrew ISO 8859-8 (with some modifications).
+ *
+ * FT_WinFNT_ID_CP1256 ::
+ * A superset of Arabic ISO 8859-6 (with different ordering).
+ *
+ * FT_WinFNT_ID_CP1257 ::
+ * A superset of Baltic ISO 8859-13 (with some deviations).
+ *
+ * FT_WinFNT_ID_CP1258 ::
+ * For Vietnamese. This encoding doesn't cover all necessary
+ * characters.
+ *
+ * FT_WinFNT_ID_CP1361 ::
+ * Korean (Johab).
+ */
+
+#define FT_WinFNT_ID_CP1252 0
+#define FT_WinFNT_ID_DEFAULT 1
+#define FT_WinFNT_ID_SYMBOL 2
+#define FT_WinFNT_ID_MAC 77
+#define FT_WinFNT_ID_CP932 128
+#define FT_WinFNT_ID_CP949 129
+#define FT_WinFNT_ID_CP1361 130
+#define FT_WinFNT_ID_CP936 134
+#define FT_WinFNT_ID_CP950 136
+#define FT_WinFNT_ID_CP1253 161
+#define FT_WinFNT_ID_CP1254 162
+#define FT_WinFNT_ID_CP1258 163
+#define FT_WinFNT_ID_CP1255 177
+#define FT_WinFNT_ID_CP1256 178
+#define FT_WinFNT_ID_CP1257 186
+#define FT_WinFNT_ID_CP1251 204
+#define FT_WinFNT_ID_CP874 222
+#define FT_WinFNT_ID_CP1250 238
+#define FT_WinFNT_ID_OEM 255
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_WinFNT_HeaderRec
+ *
+ * @description:
+ * Windows FNT Header info.
+ */
+ typedef struct FT_WinFNT_HeaderRec_
+ {
+ FT_UShort version;
+ FT_ULong file_size;
+ FT_Byte copyright[60];
+ FT_UShort file_type;
+ FT_UShort nominal_point_size;
+ FT_UShort vertical_resolution;
+ FT_UShort horizontal_resolution;
+ FT_UShort ascent;
+ FT_UShort internal_leading;
+ FT_UShort external_leading;
+ FT_Byte italic;
+ FT_Byte underline;
+ FT_Byte strike_out;
+ FT_UShort weight;
+ FT_Byte charset;
+ FT_UShort pixel_width;
+ FT_UShort pixel_height;
+ FT_Byte pitch_and_family;
+ FT_UShort avg_width;
+ FT_UShort max_width;
+ FT_Byte first_char;
+ FT_Byte last_char;
+ FT_Byte default_char;
+ FT_Byte break_char;
+ FT_UShort bytes_per_row;
+ FT_ULong device_offset;
+ FT_ULong face_name_offset;
+ FT_ULong bits_pointer;
+ FT_ULong bits_offset;
+ FT_Byte reserved;
+ FT_ULong flags;
+ FT_UShort A_space;
+ FT_UShort B_space;
+ FT_UShort C_space;
+ FT_UShort color_table_offset;
+ FT_ULong reserved1[4];
+
+ } FT_WinFNT_HeaderRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_WinFNT_Header
+ *
+ * @description:
+ * A handle to an @FT_WinFNT_HeaderRec structure.
+ */
+ typedef struct FT_WinFNT_HeaderRec_* FT_WinFNT_Header;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_WinFNT_Header
+ *
+ * @description:
+ * Retrieve a Windows FNT font info header.
+ *
+ * @input:
+ * face ::
+ * A handle to the input face.
+ *
+ * @output:
+ * aheader ::
+ * The WinFNT header.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function only works with Windows FNT faces, returning an error
+ * otherwise.
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_WinFNT_Header( FT_Face face,
+ FT_WinFNT_HeaderRec *aheader );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* FTWINFNT_H_ */
+
+
+/* END */
+
+
+/* Local Variables: */
+/* coding: utf-8 */
+/* End: */
diff --git a/Client/ThirdParty/freetype/include/freetype/t1tables.h b/Client/ThirdParty/freetype/include/freetype/t1tables.h
new file mode 100644
index 0000000..546ec1c
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/t1tables.h
@@ -0,0 +1,773 @@
+/****************************************************************************
+ *
+ * t1tables.h
+ *
+ * Basic Type 1/Type 2 tables definitions and interface (specification
+ * only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef T1TABLES_H_
+#define T1TABLES_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * type1_tables
+ *
+ * @title:
+ * Type 1 Tables
+ *
+ * @abstract:
+ * Type~1-specific font tables.
+ *
+ * @description:
+ * This section contains the definition of Type~1-specific tables,
+ * including structures related to other PostScript font formats.
+ *
+ * @order:
+ * PS_FontInfoRec
+ * PS_FontInfo
+ * PS_PrivateRec
+ * PS_Private
+ *
+ * CID_FaceDictRec
+ * CID_FaceDict
+ * CID_FaceInfoRec
+ * CID_FaceInfo
+ *
+ * FT_Has_PS_Glyph_Names
+ * FT_Get_PS_Font_Info
+ * FT_Get_PS_Font_Private
+ * FT_Get_PS_Font_Value
+ *
+ * T1_Blend_Flags
+ * T1_EncodingType
+ * PS_Dict_Keys
+ *
+ */
+
+
+ /* Note that we separate font data in PS_FontInfoRec and PS_PrivateRec */
+ /* structures in order to support Multiple Master fonts. */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_FontInfoRec
+ *
+ * @description:
+ * A structure used to model a Type~1 or Type~2 FontInfo dictionary.
+ * Note that for Multiple Master fonts, each instance has its own
+ * FontInfo dictionary.
+ */
+ typedef struct PS_FontInfoRec_
+ {
+ FT_String* version;
+ FT_String* notice;
+ FT_String* full_name;
+ FT_String* family_name;
+ FT_String* weight;
+ FT_Long italic_angle;
+ FT_Bool is_fixed_pitch;
+ FT_Short underline_position;
+ FT_UShort underline_thickness;
+
+ } PS_FontInfoRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_FontInfo
+ *
+ * @description:
+ * A handle to a @PS_FontInfoRec structure.
+ */
+ typedef struct PS_FontInfoRec_* PS_FontInfo;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * T1_FontInfo
+ *
+ * @description:
+ * This type is equivalent to @PS_FontInfoRec. It is deprecated but kept
+ * to maintain source compatibility between various versions of FreeType.
+ */
+ typedef PS_FontInfoRec T1_FontInfo;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_PrivateRec
+ *
+ * @description:
+ * A structure used to model a Type~1 or Type~2 private dictionary. Note
+ * that for Multiple Master fonts, each instance has its own Private
+ * dictionary.
+ */
+ typedef struct PS_PrivateRec_
+ {
+ FT_Int unique_id;
+ FT_Int lenIV;
+
+ FT_Byte num_blue_values;
+ FT_Byte num_other_blues;
+ FT_Byte num_family_blues;
+ FT_Byte num_family_other_blues;
+
+ FT_Short blue_values[14];
+ FT_Short other_blues[10];
+
+ FT_Short family_blues [14];
+ FT_Short family_other_blues[10];
+
+ FT_Fixed blue_scale;
+ FT_Int blue_shift;
+ FT_Int blue_fuzz;
+
+ FT_UShort standard_width[1];
+ FT_UShort standard_height[1];
+
+ FT_Byte num_snap_widths;
+ FT_Byte num_snap_heights;
+ FT_Bool force_bold;
+ FT_Bool round_stem_up;
+
+ FT_Short snap_widths [13]; /* including std width */
+ FT_Short snap_heights[13]; /* including std height */
+
+ FT_Fixed expansion_factor;
+
+ FT_Long language_group;
+ FT_Long password;
+
+ FT_Short min_feature[2];
+
+ } PS_PrivateRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * PS_Private
+ *
+ * @description:
+ * A handle to a @PS_PrivateRec structure.
+ */
+ typedef struct PS_PrivateRec_* PS_Private;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * T1_Private
+ *
+ * @description:
+ * This type is equivalent to @PS_PrivateRec. It is deprecated but kept
+ * to maintain source compatibility between various versions of FreeType.
+ */
+ typedef PS_PrivateRec T1_Private;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * T1_Blend_Flags
+ *
+ * @description:
+ * A set of flags used to indicate which fields are present in a given
+ * blend dictionary (font info or private). Used to support Multiple
+ * Masters fonts.
+ *
+ * @values:
+ * T1_BLEND_UNDERLINE_POSITION ::
+ * T1_BLEND_UNDERLINE_THICKNESS ::
+ * T1_BLEND_ITALIC_ANGLE ::
+ * T1_BLEND_BLUE_VALUES ::
+ * T1_BLEND_OTHER_BLUES ::
+ * T1_BLEND_STANDARD_WIDTH ::
+ * T1_BLEND_STANDARD_HEIGHT ::
+ * T1_BLEND_STEM_SNAP_WIDTHS ::
+ * T1_BLEND_STEM_SNAP_HEIGHTS ::
+ * T1_BLEND_BLUE_SCALE ::
+ * T1_BLEND_BLUE_SHIFT ::
+ * T1_BLEND_FAMILY_BLUES ::
+ * T1_BLEND_FAMILY_OTHER_BLUES ::
+ * T1_BLEND_FORCE_BOLD ::
+ */
+ typedef enum T1_Blend_Flags_
+ {
+ /* required fields in a FontInfo blend dictionary */
+ T1_BLEND_UNDERLINE_POSITION = 0,
+ T1_BLEND_UNDERLINE_THICKNESS,
+ T1_BLEND_ITALIC_ANGLE,
+
+ /* required fields in a Private blend dictionary */
+ T1_BLEND_BLUE_VALUES,
+ T1_BLEND_OTHER_BLUES,
+ T1_BLEND_STANDARD_WIDTH,
+ T1_BLEND_STANDARD_HEIGHT,
+ T1_BLEND_STEM_SNAP_WIDTHS,
+ T1_BLEND_STEM_SNAP_HEIGHTS,
+ T1_BLEND_BLUE_SCALE,
+ T1_BLEND_BLUE_SHIFT,
+ T1_BLEND_FAMILY_BLUES,
+ T1_BLEND_FAMILY_OTHER_BLUES,
+ T1_BLEND_FORCE_BOLD,
+
+ T1_BLEND_MAX /* do not remove */
+
+ } T1_Blend_Flags;
+
+
+ /* these constants are deprecated; use the corresponding */
+ /* `T1_Blend_Flags` values instead */
+#define t1_blend_underline_position T1_BLEND_UNDERLINE_POSITION
+#define t1_blend_underline_thickness T1_BLEND_UNDERLINE_THICKNESS
+#define t1_blend_italic_angle T1_BLEND_ITALIC_ANGLE
+#define t1_blend_blue_values T1_BLEND_BLUE_VALUES
+#define t1_blend_other_blues T1_BLEND_OTHER_BLUES
+#define t1_blend_standard_widths T1_BLEND_STANDARD_WIDTH
+#define t1_blend_standard_height T1_BLEND_STANDARD_HEIGHT
+#define t1_blend_stem_snap_widths T1_BLEND_STEM_SNAP_WIDTHS
+#define t1_blend_stem_snap_heights T1_BLEND_STEM_SNAP_HEIGHTS
+#define t1_blend_blue_scale T1_BLEND_BLUE_SCALE
+#define t1_blend_blue_shift T1_BLEND_BLUE_SHIFT
+#define t1_blend_family_blues T1_BLEND_FAMILY_BLUES
+#define t1_blend_family_other_blues T1_BLEND_FAMILY_OTHER_BLUES
+#define t1_blend_force_bold T1_BLEND_FORCE_BOLD
+#define t1_blend_max T1_BLEND_MAX
+
+ /* */
+
+
+ /* maximum number of Multiple Masters designs, as defined in the spec */
+#define T1_MAX_MM_DESIGNS 16
+
+ /* maximum number of Multiple Masters axes, as defined in the spec */
+#define T1_MAX_MM_AXIS 4
+
+ /* maximum number of elements in a design map */
+#define T1_MAX_MM_MAP_POINTS 20
+
+
+ /* this structure is used to store the BlendDesignMap entry for an axis */
+ typedef struct PS_DesignMap_
+ {
+ FT_Byte num_points;
+ FT_Long* design_points;
+ FT_Fixed* blend_points;
+
+ } PS_DesignMapRec, *PS_DesignMap;
+
+ /* backward compatible definition */
+ typedef PS_DesignMapRec T1_DesignMap;
+
+
+ typedef struct PS_BlendRec_
+ {
+ FT_UInt num_designs;
+ FT_UInt num_axis;
+
+ FT_String* axis_names[T1_MAX_MM_AXIS];
+ FT_Fixed* design_pos[T1_MAX_MM_DESIGNS];
+ PS_DesignMapRec design_map[T1_MAX_MM_AXIS];
+
+ FT_Fixed* weight_vector;
+ FT_Fixed* default_weight_vector;
+
+ PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1];
+ PS_Private privates [T1_MAX_MM_DESIGNS + 1];
+
+ FT_ULong blend_bitflags;
+
+ FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];
+
+ /* since 2.3.0 */
+
+ /* undocumented, optional: the default design instance; */
+ /* corresponds to default_weight_vector -- */
+ /* num_default_design_vector == 0 means it is not present */
+ /* in the font and associated metrics files */
+ FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];
+ FT_UInt num_default_design_vector;
+
+ } PS_BlendRec, *PS_Blend;
+
+
+ /* backward compatible definition */
+ typedef PS_BlendRec T1_Blend;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceDictRec
+ *
+ * @description:
+ * A structure used to represent data in a CID top-level dictionary. In
+ * most cases, they are part of the font's '/FDArray' array. Within a
+ * CID font file, such (internal) subfont dictionaries are enclosed by
+ * '%ADOBeginFontDict' and '%ADOEndFontDict' comments.
+ *
+ * Note that `CID_FaceDictRec` misses a field for the '/FontName'
+ * keyword, specifying the subfont's name (the top-level font name is
+ * given by the '/CIDFontName' keyword). This is an oversight, but it
+ * doesn't limit the 'cid' font module's functionality because FreeType
+ * neither needs this entry nor gives access to CID subfonts.
+ */
+ typedef struct CID_FaceDictRec_
+ {
+ PS_PrivateRec private_dict;
+
+ FT_UInt len_buildchar;
+ FT_Fixed forcebold_threshold;
+ FT_Pos stroke_width;
+ FT_Fixed expansion_factor; /* this is a duplicate of */
+ /* `private_dict->expansion_factor' */
+ FT_Byte paint_type;
+ FT_Byte font_type;
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+ FT_UInt num_subrs;
+ FT_ULong subrmap_offset;
+ FT_Int sd_bytes;
+
+ } CID_FaceDictRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceDict
+ *
+ * @description:
+ * A handle to a @CID_FaceDictRec structure.
+ */
+ typedef struct CID_FaceDictRec_* CID_FaceDict;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FontDict
+ *
+ * @description:
+ * This type is equivalent to @CID_FaceDictRec. It is deprecated but
+ * kept to maintain source compatibility between various versions of
+ * FreeType.
+ */
+ typedef CID_FaceDictRec CID_FontDict;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceInfoRec
+ *
+ * @description:
+ * A structure used to represent CID Face information.
+ */
+ typedef struct CID_FaceInfoRec_
+ {
+ FT_String* cid_font_name;
+ FT_Fixed cid_version;
+ FT_Int cid_font_type;
+
+ FT_String* registry;
+ FT_String* ordering;
+ FT_Int supplement;
+
+ PS_FontInfoRec font_info;
+ FT_BBox font_bbox;
+ FT_ULong uid_base;
+
+ FT_Int num_xuid;
+ FT_ULong xuid[16];
+
+ FT_ULong cidmap_offset;
+ FT_Int fd_bytes;
+ FT_Int gd_bytes;
+ FT_ULong cid_count;
+
+ FT_Int num_dicts;
+ CID_FaceDict font_dicts;
+
+ FT_ULong data_offset;
+
+ } CID_FaceInfoRec;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_FaceInfo
+ *
+ * @description:
+ * A handle to a @CID_FaceInfoRec structure.
+ */
+ typedef struct CID_FaceInfoRec_* CID_FaceInfo;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * CID_Info
+ *
+ * @description:
+ * This type is equivalent to @CID_FaceInfoRec. It is deprecated but kept
+ * to maintain source compatibility between various versions of FreeType.
+ */
+ typedef CID_FaceInfoRec CID_Info;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Has_PS_Glyph_Names
+ *
+ * @description:
+ * Return true if a given face provides reliable PostScript glyph names.
+ * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that
+ * certain fonts (mostly TrueType) contain incorrect glyph name tables.
+ *
+ * When this function returns true, the caller is sure that the glyph
+ * names returned by @FT_Get_Glyph_Name are reliable.
+ *
+ * @input:
+ * face ::
+ * face handle
+ *
+ * @return:
+ * Boolean. True if glyph names are reliable.
+ *
+ */
+ FT_EXPORT( FT_Int )
+ FT_Has_PS_Glyph_Names( FT_Face face );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PS_Font_Info
+ *
+ * @description:
+ * Retrieve the @PS_FontInfoRec structure corresponding to a given
+ * PostScript font.
+ *
+ * @input:
+ * face ::
+ * PostScript face handle.
+ *
+ * @output:
+ * afont_info ::
+ * Output font info structure pointer.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * String pointers within the @PS_FontInfoRec structure are owned by the
+ * face and don't need to be freed by the caller. Missing entries in
+ * the font's FontInfo dictionary are represented by `NULL` pointers.
+ *
+ * If the font's format is not PostScript-based, this function will
+ * return the `FT_Err_Invalid_Argument` error code.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PS_Font_Info( FT_Face face,
+ PS_FontInfo afont_info );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PS_Font_Private
+ *
+ * @description:
+ * Retrieve the @PS_PrivateRec structure corresponding to a given
+ * PostScript font.
+ *
+ * @input:
+ * face ::
+ * PostScript face handle.
+ *
+ * @output:
+ * afont_private ::
+ * Output private dictionary structure pointer.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The string pointers within the @PS_PrivateRec structure are owned by
+ * the face and don't need to be freed by the caller.
+ *
+ * If the font's format is not PostScript-based, this function returns
+ * the `FT_Err_Invalid_Argument` error code.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Get_PS_Font_Private( FT_Face face,
+ PS_Private afont_private );
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * T1_EncodingType
+ *
+ * @description:
+ * An enumeration describing the 'Encoding' entry in a Type 1 dictionary.
+ *
+ * @values:
+ * T1_ENCODING_TYPE_NONE ::
+ * T1_ENCODING_TYPE_ARRAY ::
+ * T1_ENCODING_TYPE_STANDARD ::
+ * T1_ENCODING_TYPE_ISOLATIN1 ::
+ * T1_ENCODING_TYPE_EXPERT ::
+ *
+ * @since:
+ * 2.4.8
+ */
+ typedef enum T1_EncodingType_
+ {
+ T1_ENCODING_TYPE_NONE = 0,
+ T1_ENCODING_TYPE_ARRAY,
+ T1_ENCODING_TYPE_STANDARD,
+ T1_ENCODING_TYPE_ISOLATIN1,
+ T1_ENCODING_TYPE_EXPERT
+
+ } T1_EncodingType;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * PS_Dict_Keys
+ *
+ * @description:
+ * An enumeration used in calls to @FT_Get_PS_Font_Value to identify the
+ * Type~1 dictionary entry to retrieve.
+ *
+ * @values:
+ * PS_DICT_FONT_TYPE ::
+ * PS_DICT_FONT_MATRIX ::
+ * PS_DICT_FONT_BBOX ::
+ * PS_DICT_PAINT_TYPE ::
+ * PS_DICT_FONT_NAME ::
+ * PS_DICT_UNIQUE_ID ::
+ * PS_DICT_NUM_CHAR_STRINGS ::
+ * PS_DICT_CHAR_STRING_KEY ::
+ * PS_DICT_CHAR_STRING ::
+ * PS_DICT_ENCODING_TYPE ::
+ * PS_DICT_ENCODING_ENTRY ::
+ * PS_DICT_NUM_SUBRS ::
+ * PS_DICT_SUBR ::
+ * PS_DICT_STD_HW ::
+ * PS_DICT_STD_VW ::
+ * PS_DICT_NUM_BLUE_VALUES ::
+ * PS_DICT_BLUE_VALUE ::
+ * PS_DICT_BLUE_FUZZ ::
+ * PS_DICT_NUM_OTHER_BLUES ::
+ * PS_DICT_OTHER_BLUE ::
+ * PS_DICT_NUM_FAMILY_BLUES ::
+ * PS_DICT_FAMILY_BLUE ::
+ * PS_DICT_NUM_FAMILY_OTHER_BLUES ::
+ * PS_DICT_FAMILY_OTHER_BLUE ::
+ * PS_DICT_BLUE_SCALE ::
+ * PS_DICT_BLUE_SHIFT ::
+ * PS_DICT_NUM_STEM_SNAP_H ::
+ * PS_DICT_STEM_SNAP_H ::
+ * PS_DICT_NUM_STEM_SNAP_V ::
+ * PS_DICT_STEM_SNAP_V ::
+ * PS_DICT_FORCE_BOLD ::
+ * PS_DICT_RND_STEM_UP ::
+ * PS_DICT_MIN_FEATURE ::
+ * PS_DICT_LEN_IV ::
+ * PS_DICT_PASSWORD ::
+ * PS_DICT_LANGUAGE_GROUP ::
+ * PS_DICT_VERSION ::
+ * PS_DICT_NOTICE ::
+ * PS_DICT_FULL_NAME ::
+ * PS_DICT_FAMILY_NAME ::
+ * PS_DICT_WEIGHT ::
+ * PS_DICT_IS_FIXED_PITCH ::
+ * PS_DICT_UNDERLINE_POSITION ::
+ * PS_DICT_UNDERLINE_THICKNESS ::
+ * PS_DICT_FS_TYPE ::
+ * PS_DICT_ITALIC_ANGLE ::
+ *
+ * @since:
+ * 2.4.8
+ */
+ typedef enum PS_Dict_Keys_
+ {
+ /* conventionally in the font dictionary */
+ PS_DICT_FONT_TYPE, /* FT_Byte */
+ PS_DICT_FONT_MATRIX, /* FT_Fixed */
+ PS_DICT_FONT_BBOX, /* FT_Fixed */
+ PS_DICT_PAINT_TYPE, /* FT_Byte */
+ PS_DICT_FONT_NAME, /* FT_String* */
+ PS_DICT_UNIQUE_ID, /* FT_Int */
+ PS_DICT_NUM_CHAR_STRINGS, /* FT_Int */
+ PS_DICT_CHAR_STRING_KEY, /* FT_String* */
+ PS_DICT_CHAR_STRING, /* FT_String* */
+ PS_DICT_ENCODING_TYPE, /* T1_EncodingType */
+ PS_DICT_ENCODING_ENTRY, /* FT_String* */
+
+ /* conventionally in the font Private dictionary */
+ PS_DICT_NUM_SUBRS, /* FT_Int */
+ PS_DICT_SUBR, /* FT_String* */
+ PS_DICT_STD_HW, /* FT_UShort */
+ PS_DICT_STD_VW, /* FT_UShort */
+ PS_DICT_NUM_BLUE_VALUES, /* FT_Byte */
+ PS_DICT_BLUE_VALUE, /* FT_Short */
+ PS_DICT_BLUE_FUZZ, /* FT_Int */
+ PS_DICT_NUM_OTHER_BLUES, /* FT_Byte */
+ PS_DICT_OTHER_BLUE, /* FT_Short */
+ PS_DICT_NUM_FAMILY_BLUES, /* FT_Byte */
+ PS_DICT_FAMILY_BLUE, /* FT_Short */
+ PS_DICT_NUM_FAMILY_OTHER_BLUES, /* FT_Byte */
+ PS_DICT_FAMILY_OTHER_BLUE, /* FT_Short */
+ PS_DICT_BLUE_SCALE, /* FT_Fixed */
+ PS_DICT_BLUE_SHIFT, /* FT_Int */
+ PS_DICT_NUM_STEM_SNAP_H, /* FT_Byte */
+ PS_DICT_STEM_SNAP_H, /* FT_Short */
+ PS_DICT_NUM_STEM_SNAP_V, /* FT_Byte */
+ PS_DICT_STEM_SNAP_V, /* FT_Short */
+ PS_DICT_FORCE_BOLD, /* FT_Bool */
+ PS_DICT_RND_STEM_UP, /* FT_Bool */
+ PS_DICT_MIN_FEATURE, /* FT_Short */
+ PS_DICT_LEN_IV, /* FT_Int */
+ PS_DICT_PASSWORD, /* FT_Long */
+ PS_DICT_LANGUAGE_GROUP, /* FT_Long */
+
+ /* conventionally in the font FontInfo dictionary */
+ PS_DICT_VERSION, /* FT_String* */
+ PS_DICT_NOTICE, /* FT_String* */
+ PS_DICT_FULL_NAME, /* FT_String* */
+ PS_DICT_FAMILY_NAME, /* FT_String* */
+ PS_DICT_WEIGHT, /* FT_String* */
+ PS_DICT_IS_FIXED_PITCH, /* FT_Bool */
+ PS_DICT_UNDERLINE_POSITION, /* FT_Short */
+ PS_DICT_UNDERLINE_THICKNESS, /* FT_UShort */
+ PS_DICT_FS_TYPE, /* FT_UShort */
+ PS_DICT_ITALIC_ANGLE, /* FT_Long */
+
+ PS_DICT_MAX = PS_DICT_ITALIC_ANGLE
+
+ } PS_Dict_Keys;
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_PS_Font_Value
+ *
+ * @description:
+ * Retrieve the value for the supplied key from a PostScript font.
+ *
+ * @input:
+ * face ::
+ * PostScript face handle.
+ *
+ * key ::
+ * An enumeration value representing the dictionary key to retrieve.
+ *
+ * idx ::
+ * For array values, this specifies the index to be returned.
+ *
+ * value ::
+ * A pointer to memory into which to write the value.
+ *
+ * valen_len ::
+ * The size, in bytes, of the memory supplied for the value.
+ *
+ * @output:
+ * value ::
+ * The value matching the above key, if it exists.
+ *
+ * @return:
+ * The amount of memory (in bytes) required to hold the requested value
+ * (if it exists, -1 otherwise).
+ *
+ * @note:
+ * The values returned are not pointers into the internal structures of
+ * the face, but are 'fresh' copies, so that the memory containing them
+ * belongs to the calling application. This also enforces the
+ * 'read-only' nature of these values, i.e., this function cannot be
+ * used to manipulate the face.
+ *
+ * `value` is a void pointer because the values returned can be of
+ * various types.
+ *
+ * If either `value` is `NULL` or `value_len` is too small, just the
+ * required memory size for the requested entry is returned.
+ *
+ * The `idx` parameter is used, not only to retrieve elements of, for
+ * example, the FontMatrix or FontBBox, but also to retrieve name keys
+ * from the CharStrings dictionary, and the charstrings themselves. It
+ * is ignored for atomic values.
+ *
+ * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To
+ * get the value as in the font stream, you need to divide by 65536000.0
+ * (to remove the FT_Fixed scale, and the x1000 scale).
+ *
+ * IMPORTANT: Only key/value pairs read by the FreeType interpreter can
+ * be retrieved. So, for example, PostScript procedures such as NP, ND,
+ * and RD are not available. Arbitrary keys are, obviously, not be
+ * available either.
+ *
+ * If the font's format is not PostScript-based, this function returns
+ * the `FT_Err_Invalid_Argument` error code.
+ *
+ * @since:
+ * 2.4.8
+ *
+ */
+ FT_EXPORT( FT_Long )
+ FT_Get_PS_Font_Value( FT_Face face,
+ PS_Dict_Keys key,
+ FT_UInt idx,
+ void *value,
+ FT_Long value_len );
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* T1TABLES_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/ttnameid.h b/Client/ThirdParty/freetype/include/freetype/ttnameid.h
new file mode 100644
index 0000000..72f9f76
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/ttnameid.h
@@ -0,0 +1,1235 @@
+/****************************************************************************
+ *
+ * ttnameid.h
+ *
+ * TrueType name ID definitions (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef TTNAMEID_H_
+#define TTNAMEID_H_
+
+
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * truetype_tables
+ */
+
+
+ /**************************************************************************
+ *
+ * Possible values for the 'platform' identifier code in the name records
+ * of an SFNT 'name' table.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_PLATFORM_XXX
+ *
+ * @description:
+ * A list of valid values for the `platform_id` identifier code in
+ * @FT_CharMapRec and @FT_SfntName structures.
+ *
+ * @values:
+ * TT_PLATFORM_APPLE_UNICODE ::
+ * Used by Apple to indicate a Unicode character map and/or name entry.
+ * See @TT_APPLE_ID_XXX for corresponding `encoding_id` values. Note
+ * that name entries in this format are coded as big-endian UCS-2
+ * character codes _only_.
+ *
+ * TT_PLATFORM_MACINTOSH ::
+ * Used by Apple to indicate a MacOS-specific charmap and/or name
+ * entry. See @TT_MAC_ID_XXX for corresponding `encoding_id` values.
+ * Note that most TrueType fonts contain an Apple roman charmap to be
+ * usable on MacOS systems (even if they contain a Microsoft charmap as
+ * well).
+ *
+ * TT_PLATFORM_ISO ::
+ * This value was used to specify ISO/IEC 10646 charmaps. It is
+ * however now deprecated. See @TT_ISO_ID_XXX for a list of
+ * corresponding `encoding_id` values.
+ *
+ * TT_PLATFORM_MICROSOFT ::
+ * Used by Microsoft to indicate Windows-specific charmaps. See
+ * @TT_MS_ID_XXX for a list of corresponding `encoding_id` values.
+ * Note that most fonts contain a Unicode charmap using
+ * (`TT_PLATFORM_MICROSOFT`, @TT_MS_ID_UNICODE_CS).
+ *
+ * TT_PLATFORM_CUSTOM ::
+ * Used to indicate application-specific charmaps.
+ *
+ * TT_PLATFORM_ADOBE ::
+ * This value isn't part of any font format specification, but is used
+ * by FreeType to report Adobe-specific charmaps in an @FT_CharMapRec
+ * structure. See @TT_ADOBE_ID_XXX.
+ */
+
+#define TT_PLATFORM_APPLE_UNICODE 0
+#define TT_PLATFORM_MACINTOSH 1
+#define TT_PLATFORM_ISO 2 /* deprecated */
+#define TT_PLATFORM_MICROSOFT 3
+#define TT_PLATFORM_CUSTOM 4
+#define TT_PLATFORM_ADOBE 7 /* artificial */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_APPLE_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id` for
+ * @TT_PLATFORM_APPLE_UNICODE charmaps and name entries.
+ *
+ * @values:
+ * TT_APPLE_ID_DEFAULT ::
+ * Unicode version 1.0.
+ *
+ * TT_APPLE_ID_UNICODE_1_1 ::
+ * Unicode 1.1; specifies Hangul characters starting at U+34xx.
+ *
+ * TT_APPLE_ID_ISO_10646 ::
+ * Deprecated (identical to preceding).
+ *
+ * TT_APPLE_ID_UNICODE_2_0 ::
+ * Unicode 2.0 and beyond (UTF-16 BMP only).
+ *
+ * TT_APPLE_ID_UNICODE_32 ::
+ * Unicode 3.1 and beyond, using UTF-32.
+ *
+ * TT_APPLE_ID_VARIANT_SELECTOR ::
+ * From Adobe, not Apple. Not a normal cmap. Specifies variations on
+ * a real cmap.
+ *
+ * TT_APPLE_ID_FULL_UNICODE ::
+ * Used for fallback fonts that provide complete Unicode coverage with
+ * a type~13 cmap.
+ */
+
+#define TT_APPLE_ID_DEFAULT 0 /* Unicode 1.0 */
+#define TT_APPLE_ID_UNICODE_1_1 1 /* specify Hangul at U+34xx */
+#define TT_APPLE_ID_ISO_10646 2 /* deprecated */
+#define TT_APPLE_ID_UNICODE_2_0 3 /* or later */
+#define TT_APPLE_ID_UNICODE_32 4 /* 2.0 or later, full repertoire */
+#define TT_APPLE_ID_VARIANT_SELECTOR 5 /* variation selector data */
+#define TT_APPLE_ID_FULL_UNICODE 6 /* used with type 13 cmaps */
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_MAC_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id` for
+ * @TT_PLATFORM_MACINTOSH charmaps and name entries.
+ */
+
+#define TT_MAC_ID_ROMAN 0
+#define TT_MAC_ID_JAPANESE 1
+#define TT_MAC_ID_TRADITIONAL_CHINESE 2
+#define TT_MAC_ID_KOREAN 3
+#define TT_MAC_ID_ARABIC 4
+#define TT_MAC_ID_HEBREW 5
+#define TT_MAC_ID_GREEK 6
+#define TT_MAC_ID_RUSSIAN 7
+#define TT_MAC_ID_RSYMBOL 8
+#define TT_MAC_ID_DEVANAGARI 9
+#define TT_MAC_ID_GURMUKHI 10
+#define TT_MAC_ID_GUJARATI 11
+#define TT_MAC_ID_ORIYA 12
+#define TT_MAC_ID_BENGALI 13
+#define TT_MAC_ID_TAMIL 14
+#define TT_MAC_ID_TELUGU 15
+#define TT_MAC_ID_KANNADA 16
+#define TT_MAC_ID_MALAYALAM 17
+#define TT_MAC_ID_SINHALESE 18
+#define TT_MAC_ID_BURMESE 19
+#define TT_MAC_ID_KHMER 20
+#define TT_MAC_ID_THAI 21
+#define TT_MAC_ID_LAOTIAN 22
+#define TT_MAC_ID_GEORGIAN 23
+#define TT_MAC_ID_ARMENIAN 24
+#define TT_MAC_ID_MALDIVIAN 25
+#define TT_MAC_ID_SIMPLIFIED_CHINESE 25
+#define TT_MAC_ID_TIBETAN 26
+#define TT_MAC_ID_MONGOLIAN 27
+#define TT_MAC_ID_GEEZ 28
+#define TT_MAC_ID_SLAVIC 29
+#define TT_MAC_ID_VIETNAMESE 30
+#define TT_MAC_ID_SINDHI 31
+#define TT_MAC_ID_UNINTERP 32
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_ISO_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id` for @TT_PLATFORM_ISO
+ * charmaps and name entries.
+ *
+ * Their use is now deprecated.
+ *
+ * @values:
+ * TT_ISO_ID_7BIT_ASCII ::
+ * ASCII.
+ * TT_ISO_ID_10646 ::
+ * ISO/10646.
+ * TT_ISO_ID_8859_1 ::
+ * Also known as Latin-1.
+ */
+
+#define TT_ISO_ID_7BIT_ASCII 0
+#define TT_ISO_ID_10646 1
+#define TT_ISO_ID_8859_1 2
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_MS_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id` for
+ * @TT_PLATFORM_MICROSOFT charmaps and name entries.
+ *
+ * @values:
+ * TT_MS_ID_SYMBOL_CS ::
+ * Microsoft symbol encoding. See @FT_ENCODING_MS_SYMBOL.
+ *
+ * TT_MS_ID_UNICODE_CS ::
+ * Microsoft WGL4 charmap, matching Unicode. See @FT_ENCODING_UNICODE.
+ *
+ * TT_MS_ID_SJIS ::
+ * Shift JIS Japanese encoding. See @FT_ENCODING_SJIS.
+ *
+ * TT_MS_ID_PRC ::
+ * Chinese encodings as used in the People's Republic of China (PRC).
+ * This means the encodings GB~2312 and its supersets GBK and GB~18030.
+ * See @FT_ENCODING_PRC.
+ *
+ * TT_MS_ID_BIG_5 ::
+ * Traditional Chinese as used in Taiwan and Hong Kong. See
+ * @FT_ENCODING_BIG5.
+ *
+ * TT_MS_ID_WANSUNG ::
+ * Korean Extended Wansung encoding. See @FT_ENCODING_WANSUNG.
+ *
+ * TT_MS_ID_JOHAB ::
+ * Korean Johab encoding. See @FT_ENCODING_JOHAB.
+ *
+ * TT_MS_ID_UCS_4 ::
+ * UCS-4 or UTF-32 charmaps. This has been added to the OpenType
+ * specification version 1.4 (mid-2001).
+ */
+
+#define TT_MS_ID_SYMBOL_CS 0
+#define TT_MS_ID_UNICODE_CS 1
+#define TT_MS_ID_SJIS 2
+#define TT_MS_ID_PRC 3
+#define TT_MS_ID_BIG_5 4
+#define TT_MS_ID_WANSUNG 5
+#define TT_MS_ID_JOHAB 6
+#define TT_MS_ID_UCS_4 10
+
+ /* this value is deprecated */
+#define TT_MS_ID_GB2312 TT_MS_ID_PRC
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_ADOBE_ID_XXX
+ *
+ * @description:
+ * A list of valid values for the `encoding_id` for @TT_PLATFORM_ADOBE
+ * charmaps. This is a FreeType-specific extension!
+ *
+ * @values:
+ * TT_ADOBE_ID_STANDARD ::
+ * Adobe standard encoding.
+ * TT_ADOBE_ID_EXPERT ::
+ * Adobe expert encoding.
+ * TT_ADOBE_ID_CUSTOM ::
+ * Adobe custom encoding.
+ * TT_ADOBE_ID_LATIN_1 ::
+ * Adobe Latin~1 encoding.
+ */
+
+#define TT_ADOBE_ID_STANDARD 0
+#define TT_ADOBE_ID_EXPERT 1
+#define TT_ADOBE_ID_CUSTOM 2
+#define TT_ADOBE_ID_LATIN_1 3
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_MAC_LANGID_XXX
+ *
+ * @description:
+ * Possible values of the language identifier field in the name records
+ * of the SFNT 'name' table if the 'platform' identifier code is
+ * @TT_PLATFORM_MACINTOSH. These values are also used as return values
+ * for function @FT_Get_CMap_Language_ID.
+ *
+ * The canonical source for Apple's IDs is
+ *
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html
+ */
+
+#define TT_MAC_LANGID_ENGLISH 0
+#define TT_MAC_LANGID_FRENCH 1
+#define TT_MAC_LANGID_GERMAN 2
+#define TT_MAC_LANGID_ITALIAN 3
+#define TT_MAC_LANGID_DUTCH 4
+#define TT_MAC_LANGID_SWEDISH 5
+#define TT_MAC_LANGID_SPANISH 6
+#define TT_MAC_LANGID_DANISH 7
+#define TT_MAC_LANGID_PORTUGUESE 8
+#define TT_MAC_LANGID_NORWEGIAN 9
+#define TT_MAC_LANGID_HEBREW 10
+#define TT_MAC_LANGID_JAPANESE 11
+#define TT_MAC_LANGID_ARABIC 12
+#define TT_MAC_LANGID_FINNISH 13
+#define TT_MAC_LANGID_GREEK 14
+#define TT_MAC_LANGID_ICELANDIC 15
+#define TT_MAC_LANGID_MALTESE 16
+#define TT_MAC_LANGID_TURKISH 17
+#define TT_MAC_LANGID_CROATIAN 18
+#define TT_MAC_LANGID_CHINESE_TRADITIONAL 19
+#define TT_MAC_LANGID_URDU 20
+#define TT_MAC_LANGID_HINDI 21
+#define TT_MAC_LANGID_THAI 22
+#define TT_MAC_LANGID_KOREAN 23
+#define TT_MAC_LANGID_LITHUANIAN 24
+#define TT_MAC_LANGID_POLISH 25
+#define TT_MAC_LANGID_HUNGARIAN 26
+#define TT_MAC_LANGID_ESTONIAN 27
+#define TT_MAC_LANGID_LETTISH 28
+#define TT_MAC_LANGID_SAAMISK 29
+#define TT_MAC_LANGID_FAEROESE 30
+#define TT_MAC_LANGID_FARSI 31
+#define TT_MAC_LANGID_RUSSIAN 32
+#define TT_MAC_LANGID_CHINESE_SIMPLIFIED 33
+#define TT_MAC_LANGID_FLEMISH 34
+#define TT_MAC_LANGID_IRISH 35
+#define TT_MAC_LANGID_ALBANIAN 36
+#define TT_MAC_LANGID_ROMANIAN 37
+#define TT_MAC_LANGID_CZECH 38
+#define TT_MAC_LANGID_SLOVAK 39
+#define TT_MAC_LANGID_SLOVENIAN 40
+#define TT_MAC_LANGID_YIDDISH 41
+#define TT_MAC_LANGID_SERBIAN 42
+#define TT_MAC_LANGID_MACEDONIAN 43
+#define TT_MAC_LANGID_BULGARIAN 44
+#define TT_MAC_LANGID_UKRAINIAN 45
+#define TT_MAC_LANGID_BYELORUSSIAN 46
+#define TT_MAC_LANGID_UZBEK 47
+#define TT_MAC_LANGID_KAZAKH 48
+#define TT_MAC_LANGID_AZERBAIJANI 49
+#define TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT 49
+#define TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT 50
+#define TT_MAC_LANGID_ARMENIAN 51
+#define TT_MAC_LANGID_GEORGIAN 52
+#define TT_MAC_LANGID_MOLDAVIAN 53
+#define TT_MAC_LANGID_KIRGHIZ 54
+#define TT_MAC_LANGID_TAJIKI 55
+#define TT_MAC_LANGID_TURKMEN 56
+#define TT_MAC_LANGID_MONGOLIAN 57
+#define TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT 57
+#define TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT 58
+#define TT_MAC_LANGID_PASHTO 59
+#define TT_MAC_LANGID_KURDISH 60
+#define TT_MAC_LANGID_KASHMIRI 61
+#define TT_MAC_LANGID_SINDHI 62
+#define TT_MAC_LANGID_TIBETAN 63
+#define TT_MAC_LANGID_NEPALI 64
+#define TT_MAC_LANGID_SANSKRIT 65
+#define TT_MAC_LANGID_MARATHI 66
+#define TT_MAC_LANGID_BENGALI 67
+#define TT_MAC_LANGID_ASSAMESE 68
+#define TT_MAC_LANGID_GUJARATI 69
+#define TT_MAC_LANGID_PUNJABI 70
+#define TT_MAC_LANGID_ORIYA 71
+#define TT_MAC_LANGID_MALAYALAM 72
+#define TT_MAC_LANGID_KANNADA 73
+#define TT_MAC_LANGID_TAMIL 74
+#define TT_MAC_LANGID_TELUGU 75
+#define TT_MAC_LANGID_SINHALESE 76
+#define TT_MAC_LANGID_BURMESE 77
+#define TT_MAC_LANGID_KHMER 78
+#define TT_MAC_LANGID_LAO 79
+#define TT_MAC_LANGID_VIETNAMESE 80
+#define TT_MAC_LANGID_INDONESIAN 81
+#define TT_MAC_LANGID_TAGALOG 82
+#define TT_MAC_LANGID_MALAY_ROMAN_SCRIPT 83
+#define TT_MAC_LANGID_MALAY_ARABIC_SCRIPT 84
+#define TT_MAC_LANGID_AMHARIC 85
+#define TT_MAC_LANGID_TIGRINYA 86
+#define TT_MAC_LANGID_GALLA 87
+#define TT_MAC_LANGID_SOMALI 88
+#define TT_MAC_LANGID_SWAHILI 89
+#define TT_MAC_LANGID_RUANDA 90
+#define TT_MAC_LANGID_RUNDI 91
+#define TT_MAC_LANGID_CHEWA 92
+#define TT_MAC_LANGID_MALAGASY 93
+#define TT_MAC_LANGID_ESPERANTO 94
+#define TT_MAC_LANGID_WELSH 128
+#define TT_MAC_LANGID_BASQUE 129
+#define TT_MAC_LANGID_CATALAN 130
+#define TT_MAC_LANGID_LATIN 131
+#define TT_MAC_LANGID_QUECHUA 132
+#define TT_MAC_LANGID_GUARANI 133
+#define TT_MAC_LANGID_AYMARA 134
+#define TT_MAC_LANGID_TATAR 135
+#define TT_MAC_LANGID_UIGHUR 136
+#define TT_MAC_LANGID_DZONGKHA 137
+#define TT_MAC_LANGID_JAVANESE 138
+#define TT_MAC_LANGID_SUNDANESE 139
+
+ /* The following codes are new as of 2000-03-10 */
+#define TT_MAC_LANGID_GALICIAN 140
+#define TT_MAC_LANGID_AFRIKAANS 141
+#define TT_MAC_LANGID_BRETON 142
+#define TT_MAC_LANGID_INUKTITUT 143
+#define TT_MAC_LANGID_SCOTTISH_GAELIC 144
+#define TT_MAC_LANGID_MANX_GAELIC 145
+#define TT_MAC_LANGID_IRISH_GAELIC 146
+#define TT_MAC_LANGID_TONGAN 147
+#define TT_MAC_LANGID_GREEK_POLYTONIC 148
+#define TT_MAC_LANGID_GREELANDIC 149
+#define TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT 150
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_MS_LANGID_XXX
+ *
+ * @description:
+ * Possible values of the language identifier field in the name records
+ * of the SFNT 'name' table if the 'platform' identifier code is
+ * @TT_PLATFORM_MICROSOFT. These values are also used as return values
+ * for function @FT_Get_CMap_Language_ID.
+ *
+ * The canonical source for Microsoft's IDs is
+ *
+ * https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings ,
+ *
+ * however, we only provide macros for language identifiers present in
+ * the OpenType specification: Microsoft has abandoned the concept of
+ * LCIDs (language code identifiers), and format~1 of the 'name' table
+ * provides a better mechanism for languages not covered here.
+ *
+ * More legacy values not listed in the reference can be found in the
+ * @FT_TRUETYPE_IDS_H header file.
+ */
+
+#define TT_MS_LANGID_ARABIC_SAUDI_ARABIA 0x0401
+#define TT_MS_LANGID_ARABIC_IRAQ 0x0801
+#define TT_MS_LANGID_ARABIC_EGYPT 0x0C01
+#define TT_MS_LANGID_ARABIC_LIBYA 0x1001
+#define TT_MS_LANGID_ARABIC_ALGERIA 0x1401
+#define TT_MS_LANGID_ARABIC_MOROCCO 0x1801
+#define TT_MS_LANGID_ARABIC_TUNISIA 0x1C01
+#define TT_MS_LANGID_ARABIC_OMAN 0x2001
+#define TT_MS_LANGID_ARABIC_YEMEN 0x2401
+#define TT_MS_LANGID_ARABIC_SYRIA 0x2801
+#define TT_MS_LANGID_ARABIC_JORDAN 0x2C01
+#define TT_MS_LANGID_ARABIC_LEBANON 0x3001
+#define TT_MS_LANGID_ARABIC_KUWAIT 0x3401
+#define TT_MS_LANGID_ARABIC_UAE 0x3801
+#define TT_MS_LANGID_ARABIC_BAHRAIN 0x3C01
+#define TT_MS_LANGID_ARABIC_QATAR 0x4001
+#define TT_MS_LANGID_BULGARIAN_BULGARIA 0x0402
+#define TT_MS_LANGID_CATALAN_CATALAN 0x0403
+#define TT_MS_LANGID_CHINESE_TAIWAN 0x0404
+#define TT_MS_LANGID_CHINESE_PRC 0x0804
+#define TT_MS_LANGID_CHINESE_HONG_KONG 0x0C04
+#define TT_MS_LANGID_CHINESE_SINGAPORE 0x1004
+#define TT_MS_LANGID_CHINESE_MACAO 0x1404
+#define TT_MS_LANGID_CZECH_CZECH_REPUBLIC 0x0405
+#define TT_MS_LANGID_DANISH_DENMARK 0x0406
+#define TT_MS_LANGID_GERMAN_GERMANY 0x0407
+#define TT_MS_LANGID_GERMAN_SWITZERLAND 0x0807
+#define TT_MS_LANGID_GERMAN_AUSTRIA 0x0C07
+#define TT_MS_LANGID_GERMAN_LUXEMBOURG 0x1007
+#define TT_MS_LANGID_GERMAN_LIECHTENSTEIN 0x1407
+#define TT_MS_LANGID_GREEK_GREECE 0x0408
+#define TT_MS_LANGID_ENGLISH_UNITED_STATES 0x0409
+#define TT_MS_LANGID_ENGLISH_UNITED_KINGDOM 0x0809
+#define TT_MS_LANGID_ENGLISH_AUSTRALIA 0x0C09
+#define TT_MS_LANGID_ENGLISH_CANADA 0x1009
+#define TT_MS_LANGID_ENGLISH_NEW_ZEALAND 0x1409
+#define TT_MS_LANGID_ENGLISH_IRELAND 0x1809
+#define TT_MS_LANGID_ENGLISH_SOUTH_AFRICA 0x1C09
+#define TT_MS_LANGID_ENGLISH_JAMAICA 0x2009
+#define TT_MS_LANGID_ENGLISH_CARIBBEAN 0x2409
+#define TT_MS_LANGID_ENGLISH_BELIZE 0x2809
+#define TT_MS_LANGID_ENGLISH_TRINIDAD 0x2C09
+#define TT_MS_LANGID_ENGLISH_ZIMBABWE 0x3009
+#define TT_MS_LANGID_ENGLISH_PHILIPPINES 0x3409
+#define TT_MS_LANGID_ENGLISH_INDIA 0x4009
+#define TT_MS_LANGID_ENGLISH_MALAYSIA 0x4409
+#define TT_MS_LANGID_ENGLISH_SINGAPORE 0x4809
+#define TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT 0x040A
+#define TT_MS_LANGID_SPANISH_MEXICO 0x080A
+#define TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT 0x0C0A
+#define TT_MS_LANGID_SPANISH_GUATEMALA 0x100A
+#define TT_MS_LANGID_SPANISH_COSTA_RICA 0x140A
+#define TT_MS_LANGID_SPANISH_PANAMA 0x180A
+#define TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC 0x1C0A
+#define TT_MS_LANGID_SPANISH_VENEZUELA 0x200A
+#define TT_MS_LANGID_SPANISH_COLOMBIA 0x240A
+#define TT_MS_LANGID_SPANISH_PERU 0x280A
+#define TT_MS_LANGID_SPANISH_ARGENTINA 0x2C0A
+#define TT_MS_LANGID_SPANISH_ECUADOR 0x300A
+#define TT_MS_LANGID_SPANISH_CHILE 0x340A
+#define TT_MS_LANGID_SPANISH_URUGUAY 0x380A
+#define TT_MS_LANGID_SPANISH_PARAGUAY 0x3C0A
+#define TT_MS_LANGID_SPANISH_BOLIVIA 0x400A
+#define TT_MS_LANGID_SPANISH_EL_SALVADOR 0x440A
+#define TT_MS_LANGID_SPANISH_HONDURAS 0x480A
+#define TT_MS_LANGID_SPANISH_NICARAGUA 0x4C0A
+#define TT_MS_LANGID_SPANISH_PUERTO_RICO 0x500A
+#define TT_MS_LANGID_SPANISH_UNITED_STATES 0x540A
+#define TT_MS_LANGID_FINNISH_FINLAND 0x040B
+#define TT_MS_LANGID_FRENCH_FRANCE 0x040C
+#define TT_MS_LANGID_FRENCH_BELGIUM 0x080C
+#define TT_MS_LANGID_FRENCH_CANADA 0x0C0C
+#define TT_MS_LANGID_FRENCH_SWITZERLAND 0x100C
+#define TT_MS_LANGID_FRENCH_LUXEMBOURG 0x140C
+#define TT_MS_LANGID_FRENCH_MONACO 0x180C
+#define TT_MS_LANGID_HEBREW_ISRAEL 0x040D
+#define TT_MS_LANGID_HUNGARIAN_HUNGARY 0x040E
+#define TT_MS_LANGID_ICELANDIC_ICELAND 0x040F
+#define TT_MS_LANGID_ITALIAN_ITALY 0x0410
+#define TT_MS_LANGID_ITALIAN_SWITZERLAND 0x0810
+#define TT_MS_LANGID_JAPANESE_JAPAN 0x0411
+#define TT_MS_LANGID_KOREAN_KOREA 0x0412
+#define TT_MS_LANGID_DUTCH_NETHERLANDS 0x0413
+#define TT_MS_LANGID_DUTCH_BELGIUM 0x0813
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL 0x0414
+#define TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK 0x0814
+#define TT_MS_LANGID_POLISH_POLAND 0x0415
+#define TT_MS_LANGID_PORTUGUESE_BRAZIL 0x0416
+#define TT_MS_LANGID_PORTUGUESE_PORTUGAL 0x0816
+#define TT_MS_LANGID_ROMANSH_SWITZERLAND 0x0417
+#define TT_MS_LANGID_ROMANIAN_ROMANIA 0x0418
+#define TT_MS_LANGID_RUSSIAN_RUSSIA 0x0419
+#define TT_MS_LANGID_CROATIAN_CROATIA 0x041A
+#define TT_MS_LANGID_SERBIAN_SERBIA_LATIN 0x081A
+#define TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC 0x0C1A
+#define TT_MS_LANGID_CROATIAN_BOSNIA_HERZEGOVINA 0x101A
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA 0x141A
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_LATIN 0x181A
+#define TT_MS_LANGID_SERBIAN_BOSNIA_HERZ_CYRILLIC 0x1C1A
+#define TT_MS_LANGID_BOSNIAN_BOSNIA_HERZ_CYRILLIC 0x201A
+#define TT_MS_LANGID_SLOVAK_SLOVAKIA 0x041B
+#define TT_MS_LANGID_ALBANIAN_ALBANIA 0x041C
+#define TT_MS_LANGID_SWEDISH_SWEDEN 0x041D
+#define TT_MS_LANGID_SWEDISH_FINLAND 0x081D
+#define TT_MS_LANGID_THAI_THAILAND 0x041E
+#define TT_MS_LANGID_TURKISH_TURKEY 0x041F
+#define TT_MS_LANGID_URDU_PAKISTAN 0x0420
+#define TT_MS_LANGID_INDONESIAN_INDONESIA 0x0421
+#define TT_MS_LANGID_UKRAINIAN_UKRAINE 0x0422
+#define TT_MS_LANGID_BELARUSIAN_BELARUS 0x0423
+#define TT_MS_LANGID_SLOVENIAN_SLOVENIA 0x0424
+#define TT_MS_LANGID_ESTONIAN_ESTONIA 0x0425
+#define TT_MS_LANGID_LATVIAN_LATVIA 0x0426
+#define TT_MS_LANGID_LITHUANIAN_LITHUANIA 0x0427
+#define TT_MS_LANGID_TAJIK_TAJIKISTAN 0x0428
+#define TT_MS_LANGID_VIETNAMESE_VIET_NAM 0x042A
+#define TT_MS_LANGID_ARMENIAN_ARMENIA 0x042B
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN 0x042C
+#define TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC 0x082C
+#define TT_MS_LANGID_BASQUE_BASQUE 0x042D
+#define TT_MS_LANGID_UPPER_SORBIAN_GERMANY 0x042E
+#define TT_MS_LANGID_LOWER_SORBIAN_GERMANY 0x082E
+#define TT_MS_LANGID_MACEDONIAN_MACEDONIA 0x042F
+#define TT_MS_LANGID_SETSWANA_SOUTH_AFRICA 0x0432
+#define TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA 0x0434
+#define TT_MS_LANGID_ISIZULU_SOUTH_AFRICA 0x0435
+#define TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA 0x0436
+#define TT_MS_LANGID_GEORGIAN_GEORGIA 0x0437
+#define TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS 0x0438
+#define TT_MS_LANGID_HINDI_INDIA 0x0439
+#define TT_MS_LANGID_MALTESE_MALTA 0x043A
+#define TT_MS_LANGID_SAMI_NORTHERN_NORWAY 0x043B
+#define TT_MS_LANGID_SAMI_NORTHERN_SWEDEN 0x083B
+#define TT_MS_LANGID_SAMI_NORTHERN_FINLAND 0x0C3B
+#define TT_MS_LANGID_SAMI_LULE_NORWAY 0x103B
+#define TT_MS_LANGID_SAMI_LULE_SWEDEN 0x143B
+#define TT_MS_LANGID_SAMI_SOUTHERN_NORWAY 0x183B
+#define TT_MS_LANGID_SAMI_SOUTHERN_SWEDEN 0x1C3B
+#define TT_MS_LANGID_SAMI_SKOLT_FINLAND 0x203B
+#define TT_MS_LANGID_SAMI_INARI_FINLAND 0x243B
+#define TT_MS_LANGID_IRISH_IRELAND 0x083C
+#define TT_MS_LANGID_MALAY_MALAYSIA 0x043E
+#define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM 0x083E
+#define TT_MS_LANGID_KAZAKH_KAZAKHSTAN 0x043F
+#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/ 0x0440
+#define TT_MS_LANGID_KISWAHILI_KENYA 0x0441
+#define TT_MS_LANGID_TURKMEN_TURKMENISTAN 0x0442
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN 0x0443
+#define TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC 0x0843
+#define TT_MS_LANGID_TATAR_RUSSIA 0x0444
+#define TT_MS_LANGID_BENGALI_INDIA 0x0445
+#define TT_MS_LANGID_BENGALI_BANGLADESH 0x0845
+#define TT_MS_LANGID_PUNJABI_INDIA 0x0446
+#define TT_MS_LANGID_GUJARATI_INDIA 0x0447
+#define TT_MS_LANGID_ODIA_INDIA 0x0448
+#define TT_MS_LANGID_TAMIL_INDIA 0x0449
+#define TT_MS_LANGID_TELUGU_INDIA 0x044A
+#define TT_MS_LANGID_KANNADA_INDIA 0x044B
+#define TT_MS_LANGID_MALAYALAM_INDIA 0x044C
+#define TT_MS_LANGID_ASSAMESE_INDIA 0x044D
+#define TT_MS_LANGID_MARATHI_INDIA 0x044E
+#define TT_MS_LANGID_SANSKRIT_INDIA 0x044F
+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA /* Cyrillic */ 0x0450
+#define TT_MS_LANGID_MONGOLIAN_PRC 0x0850
+#define TT_MS_LANGID_TIBETAN_PRC 0x0451
+#define TT_MS_LANGID_WELSH_UNITED_KINGDOM 0x0452
+#define TT_MS_LANGID_KHMER_CAMBODIA 0x0453
+#define TT_MS_LANGID_LAO_LAOS 0x0454
+#define TT_MS_LANGID_GALICIAN_GALICIAN 0x0456
+#define TT_MS_LANGID_KONKANI_INDIA 0x0457
+#define TT_MS_LANGID_SYRIAC_SYRIA 0x045A
+#define TT_MS_LANGID_SINHALA_SRI_LANKA 0x045B
+#define TT_MS_LANGID_INUKTITUT_CANADA 0x045D
+#define TT_MS_LANGID_INUKTITUT_CANADA_LATIN 0x085D
+#define TT_MS_LANGID_AMHARIC_ETHIOPIA 0x045E
+#define TT_MS_LANGID_TAMAZIGHT_ALGERIA 0x085F
+#define TT_MS_LANGID_NEPALI_NEPAL 0x0461
+#define TT_MS_LANGID_FRISIAN_NETHERLANDS 0x0462
+#define TT_MS_LANGID_PASHTO_AFGHANISTAN 0x0463
+#define TT_MS_LANGID_FILIPINO_PHILIPPINES 0x0464
+#define TT_MS_LANGID_DHIVEHI_MALDIVES 0x0465
+#define TT_MS_LANGID_HAUSA_NIGERIA 0x0468
+#define TT_MS_LANGID_YORUBA_NIGERIA 0x046A
+#define TT_MS_LANGID_QUECHUA_BOLIVIA 0x046B
+#define TT_MS_LANGID_QUECHUA_ECUADOR 0x086B
+#define TT_MS_LANGID_QUECHUA_PERU 0x0C6B
+#define TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA 0x046C
+#define TT_MS_LANGID_BASHKIR_RUSSIA 0x046D
+#define TT_MS_LANGID_LUXEMBOURGISH_LUXEMBOURG 0x046E
+#define TT_MS_LANGID_GREENLANDIC_GREENLAND 0x046F
+#define TT_MS_LANGID_IGBO_NIGERIA 0x0470
+#define TT_MS_LANGID_YI_PRC 0x0478
+#define TT_MS_LANGID_MAPUDUNGUN_CHILE 0x047A
+#define TT_MS_LANGID_MOHAWK_MOHAWK 0x047C
+#define TT_MS_LANGID_BRETON_FRANCE 0x047E
+#define TT_MS_LANGID_UIGHUR_PRC 0x0480
+#define TT_MS_LANGID_MAORI_NEW_ZEALAND 0x0481
+#define TT_MS_LANGID_OCCITAN_FRANCE 0x0482
+#define TT_MS_LANGID_CORSICAN_FRANCE 0x0483
+#define TT_MS_LANGID_ALSATIAN_FRANCE 0x0484
+#define TT_MS_LANGID_YAKUT_RUSSIA 0x0485
+#define TT_MS_LANGID_KICHE_GUATEMALA 0x0486
+#define TT_MS_LANGID_KINYARWANDA_RWANDA 0x0487
+#define TT_MS_LANGID_WOLOF_SENEGAL 0x0488
+#define TT_MS_LANGID_DARI_AFGHANISTAN 0x048C
+
+ /* */
+
+
+ /* legacy macro definitions not present in OpenType 1.8.1 */
+#define TT_MS_LANGID_ARABIC_GENERAL 0x0001
+#define TT_MS_LANGID_CATALAN_SPAIN \
+ TT_MS_LANGID_CATALAN_CATALAN
+#define TT_MS_LANGID_CHINESE_GENERAL 0x0004
+#define TT_MS_LANGID_CHINESE_MACAU \
+ TT_MS_LANGID_CHINESE_MACAO
+#define TT_MS_LANGID_GERMAN_LIECHTENSTEI \
+ TT_MS_LANGID_GERMAN_LIECHTENSTEIN
+#define TT_MS_LANGID_ENGLISH_GENERAL 0x0009
+#define TT_MS_LANGID_ENGLISH_INDONESIA 0x3809
+#define TT_MS_LANGID_ENGLISH_HONG_KONG 0x3C09
+#define TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT \
+ TT_MS_LANGID_SPANISH_SPAIN_MODERN_SORT
+#define TT_MS_LANGID_SPANISH_LATIN_AMERICA 0xE40AU
+#define TT_MS_LANGID_FRENCH_WEST_INDIES 0x1C0C
+#define TT_MS_LANGID_FRENCH_REUNION 0x200C
+#define TT_MS_LANGID_FRENCH_CONGO 0x240C
+ /* which was formerly: */
+#define TT_MS_LANGID_FRENCH_ZAIRE \
+ TT_MS_LANGID_FRENCH_CONGO
+#define TT_MS_LANGID_FRENCH_SENEGAL 0x280C
+#define TT_MS_LANGID_FRENCH_CAMEROON 0x2C0C
+#define TT_MS_LANGID_FRENCH_COTE_D_IVOIRE 0x300C
+#define TT_MS_LANGID_FRENCH_MALI 0x340C
+#define TT_MS_LANGID_FRENCH_MOROCCO 0x380C
+#define TT_MS_LANGID_FRENCH_HAITI 0x3C0C
+#define TT_MS_LANGID_FRENCH_NORTH_AFRICA 0xE40CU
+#define TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA \
+ TT_MS_LANGID_KOREAN_KOREA
+#define TT_MS_LANGID_KOREAN_JOHAB_KOREA 0x0812
+#define TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND \
+ TT_MS_LANGID_ROMANSH_SWITZERLAND
+#define TT_MS_LANGID_MOLDAVIAN_MOLDAVIA 0x0818
+#define TT_MS_LANGID_RUSSIAN_MOLDAVIA 0x0819
+#define TT_MS_LANGID_URDU_INDIA 0x0820
+#define TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA 0x0827
+#define TT_MS_LANGID_SLOVENE_SLOVENIA \
+ TT_MS_LANGID_SLOVENIAN_SLOVENIA
+#define TT_MS_LANGID_FARSI_IRAN 0x0429
+#define TT_MS_LANGID_BASQUE_SPAIN \
+ TT_MS_LANGID_BASQUE_BASQUE
+#define TT_MS_LANGID_SORBIAN_GERMANY \
+ TT_MS_LANGID_UPPER_SORBIAN_GERMANY
+#define TT_MS_LANGID_SUTU_SOUTH_AFRICA 0x0430
+#define TT_MS_LANGID_TSONGA_SOUTH_AFRICA 0x0431
+#define TT_MS_LANGID_TSWANA_SOUTH_AFRICA \
+ TT_MS_LANGID_SETSWANA_SOUTH_AFRICA
+#define TT_MS_LANGID_VENDA_SOUTH_AFRICA 0x0433
+#define TT_MS_LANGID_XHOSA_SOUTH_AFRICA \
+ TT_MS_LANGID_ISIXHOSA_SOUTH_AFRICA
+#define TT_MS_LANGID_ZULU_SOUTH_AFRICA \
+ TT_MS_LANGID_ISIZULU_SOUTH_AFRICA
+#define TT_MS_LANGID_SAAMI_LAPONIA 0x043B
+ /* the next two values are incorrectly inverted */
+#define TT_MS_LANGID_IRISH_GAELIC_IRELAND 0x043C
+#define TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM 0x083C
+#define TT_MS_LANGID_YIDDISH_GERMANY 0x043D
+#define TT_MS_LANGID_KAZAK_KAZAKSTAN \
+ TT_MS_LANGID_KAZAKH_KAZAKHSTAN
+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZ_REPUBLIC \
+ TT_MS_LANGID_KYRGYZ_KYRGYZSTAN
+#define TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN \
+ TT_MS_LANGID_KYRGYZ_KYRGYZSTAN
+#define TT_MS_LANGID_SWAHILI_KENYA \
+ TT_MS_LANGID_KISWAHILI_KENYA
+#define TT_MS_LANGID_TATAR_TATARSTAN \
+ TT_MS_LANGID_TATAR_RUSSIA
+#define TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN 0x0846
+#define TT_MS_LANGID_ORIYA_INDIA \
+ TT_MS_LANGID_ODIA_INDIA
+#define TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN \
+ TT_MS_LANGID_MONGOLIAN_PRC
+#define TT_MS_LANGID_TIBETAN_CHINA \
+ TT_MS_LANGID_TIBETAN_PRC
+#define TT_MS_LANGID_DZONGHKA_BHUTAN 0x0851
+#define TT_MS_LANGID_TIBETAN_BHUTAN \
+ TT_MS_LANGID_DZONGHKA_BHUTAN
+#define TT_MS_LANGID_WELSH_WALES \
+ TT_MS_LANGID_WELSH_UNITED_KINGDOM
+#define TT_MS_LANGID_BURMESE_MYANMAR 0x0455
+#define TT_MS_LANGID_GALICIAN_SPAIN \
+ TT_MS_LANGID_GALICIAN_GALICIAN
+#define TT_MS_LANGID_MANIPURI_INDIA /* Bengali */ 0x0458
+#define TT_MS_LANGID_SINDHI_INDIA /* Arabic */ 0x0459
+#define TT_MS_LANGID_SINDHI_PAKISTAN 0x0859
+#define TT_MS_LANGID_SINHALESE_SRI_LANKA \
+ TT_MS_LANGID_SINHALA_SRI_LANKA
+#define TT_MS_LANGID_CHEROKEE_UNITED_STATES 0x045C
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO /* Arabic */ 0x045F
+#define TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN \
+ TT_MS_LANGID_TAMAZIGHT_ALGERIA
+#define TT_MS_LANGID_KASHMIRI_PAKISTAN /* Arabic */ 0x0460
+#define TT_MS_LANGID_KASHMIRI_SASIA 0x0860
+#define TT_MS_LANGID_KASHMIRI_INDIA \
+ TT_MS_LANGID_KASHMIRI_SASIA
+#define TT_MS_LANGID_NEPALI_INDIA 0x0861
+#define TT_MS_LANGID_DIVEHI_MALDIVES \
+ TT_MS_LANGID_DHIVEHI_MALDIVES
+#define TT_MS_LANGID_EDO_NIGERIA 0x0466
+#define TT_MS_LANGID_FULFULDE_NIGERIA 0x0467
+#define TT_MS_LANGID_IBIBIO_NIGERIA 0x0469
+#define TT_MS_LANGID_SEPEDI_SOUTH_AFRICA \
+ TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA
+#define TT_MS_LANGID_SOTHO_SOUTHERN_SOUTH_AFRICA \
+ TT_MS_LANGID_SESOTHO_SA_LEBOA_SOUTH_AFRICA
+#define TT_MS_LANGID_KANURI_NIGERIA 0x0471
+#define TT_MS_LANGID_OROMO_ETHIOPIA 0x0472
+#define TT_MS_LANGID_TIGRIGNA_ETHIOPIA 0x0473
+#define TT_MS_LANGID_TIGRIGNA_ERYTHREA 0x0873
+#define TT_MS_LANGID_TIGRIGNA_ERYTREA \
+ TT_MS_LANGID_TIGRIGNA_ERYTHREA
+#define TT_MS_LANGID_GUARANI_PARAGUAY 0x0474
+#define TT_MS_LANGID_HAWAIIAN_UNITED_STATES 0x0475
+#define TT_MS_LANGID_LATIN 0x0476
+#define TT_MS_LANGID_SOMALI_SOMALIA 0x0477
+#define TT_MS_LANGID_YI_CHINA \
+ TT_MS_LANGID_YI_PRC
+#define TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES 0x0479
+#define TT_MS_LANGID_UIGHUR_CHINA \
+ TT_MS_LANGID_UIGHUR_PRC
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_NAME_ID_XXX
+ *
+ * @description:
+ * Possible values of the 'name' identifier field in the name records of
+ * an SFNT 'name' table. These values are platform independent.
+ */
+
+#define TT_NAME_ID_COPYRIGHT 0
+#define TT_NAME_ID_FONT_FAMILY 1
+#define TT_NAME_ID_FONT_SUBFAMILY 2
+#define TT_NAME_ID_UNIQUE_ID 3
+#define TT_NAME_ID_FULL_NAME 4
+#define TT_NAME_ID_VERSION_STRING 5
+#define TT_NAME_ID_PS_NAME 6
+#define TT_NAME_ID_TRADEMARK 7
+
+ /* the following values are from the OpenType spec */
+#define TT_NAME_ID_MANUFACTURER 8
+#define TT_NAME_ID_DESIGNER 9
+#define TT_NAME_ID_DESCRIPTION 10
+#define TT_NAME_ID_VENDOR_URL 11
+#define TT_NAME_ID_DESIGNER_URL 12
+#define TT_NAME_ID_LICENSE 13
+#define TT_NAME_ID_LICENSE_URL 14
+ /* number 15 is reserved */
+#define TT_NAME_ID_TYPOGRAPHIC_FAMILY 16
+#define TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY 17
+#define TT_NAME_ID_MAC_FULL_NAME 18
+
+ /* The following code is new as of 2000-01-21 */
+#define TT_NAME_ID_SAMPLE_TEXT 19
+
+ /* This is new in OpenType 1.3 */
+#define TT_NAME_ID_CID_FINDFONT_NAME 20
+
+ /* This is new in OpenType 1.5 */
+#define TT_NAME_ID_WWS_FAMILY 21
+#define TT_NAME_ID_WWS_SUBFAMILY 22
+
+ /* This is new in OpenType 1.7 */
+#define TT_NAME_ID_LIGHT_BACKGROUND 23
+#define TT_NAME_ID_DARK_BACKGROUND 24
+
+ /* This is new in OpenType 1.8 */
+#define TT_NAME_ID_VARIATIONS_PREFIX 25
+
+ /* these two values are deprecated */
+#define TT_NAME_ID_PREFERRED_FAMILY TT_NAME_ID_TYPOGRAPHIC_FAMILY
+#define TT_NAME_ID_PREFERRED_SUBFAMILY TT_NAME_ID_TYPOGRAPHIC_SUBFAMILY
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * TT_UCR_XXX
+ *
+ * @description:
+ * Possible bit mask values for the `ulUnicodeRangeX` fields in an SFNT
+ * 'OS/2' table.
+ */
+
+ /* ulUnicodeRange1 */
+ /* --------------- */
+
+ /* Bit 0 Basic Latin */
+#define TT_UCR_BASIC_LATIN (1L << 0) /* U+0020-U+007E */
+ /* Bit 1 C1 Controls and Latin-1 Supplement */
+#define TT_UCR_LATIN1_SUPPLEMENT (1L << 1) /* U+0080-U+00FF */
+ /* Bit 2 Latin Extended-A */
+#define TT_UCR_LATIN_EXTENDED_A (1L << 2) /* U+0100-U+017F */
+ /* Bit 3 Latin Extended-B */
+#define TT_UCR_LATIN_EXTENDED_B (1L << 3) /* U+0180-U+024F */
+ /* Bit 4 IPA Extensions */
+ /* Phonetic Extensions */
+ /* Phonetic Extensions Supplement */
+#define TT_UCR_IPA_EXTENSIONS (1L << 4) /* U+0250-U+02AF */
+ /* U+1D00-U+1D7F */
+ /* U+1D80-U+1DBF */
+ /* Bit 5 Spacing Modifier Letters */
+ /* Modifier Tone Letters */
+#define TT_UCR_SPACING_MODIFIER (1L << 5) /* U+02B0-U+02FF */
+ /* U+A700-U+A71F */
+ /* Bit 6 Combining Diacritical Marks */
+ /* Combining Diacritical Marks Supplement */
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS (1L << 6) /* U+0300-U+036F */
+ /* U+1DC0-U+1DFF */
+ /* Bit 7 Greek and Coptic */
+#define TT_UCR_GREEK (1L << 7) /* U+0370-U+03FF */
+ /* Bit 8 Coptic */
+#define TT_UCR_COPTIC (1L << 8) /* U+2C80-U+2CFF */
+ /* Bit 9 Cyrillic */
+ /* Cyrillic Supplement */
+ /* Cyrillic Extended-A */
+ /* Cyrillic Extended-B */
+#define TT_UCR_CYRILLIC (1L << 9) /* U+0400-U+04FF */
+ /* U+0500-U+052F */
+ /* U+2DE0-U+2DFF */
+ /* U+A640-U+A69F */
+ /* Bit 10 Armenian */
+#define TT_UCR_ARMENIAN (1L << 10) /* U+0530-U+058F */
+ /* Bit 11 Hebrew */
+#define TT_UCR_HEBREW (1L << 11) /* U+0590-U+05FF */
+ /* Bit 12 Vai */
+#define TT_UCR_VAI (1L << 12) /* U+A500-U+A63F */
+ /* Bit 13 Arabic */
+ /* Arabic Supplement */
+#define TT_UCR_ARABIC (1L << 13) /* U+0600-U+06FF */
+ /* U+0750-U+077F */
+ /* Bit 14 NKo */
+#define TT_UCR_NKO (1L << 14) /* U+07C0-U+07FF */
+ /* Bit 15 Devanagari */
+#define TT_UCR_DEVANAGARI (1L << 15) /* U+0900-U+097F */
+ /* Bit 16 Bengali */
+#define TT_UCR_BENGALI (1L << 16) /* U+0980-U+09FF */
+ /* Bit 17 Gurmukhi */
+#define TT_UCR_GURMUKHI (1L << 17) /* U+0A00-U+0A7F */
+ /* Bit 18 Gujarati */
+#define TT_UCR_GUJARATI (1L << 18) /* U+0A80-U+0AFF */
+ /* Bit 19 Oriya */
+#define TT_UCR_ORIYA (1L << 19) /* U+0B00-U+0B7F */
+ /* Bit 20 Tamil */
+#define TT_UCR_TAMIL (1L << 20) /* U+0B80-U+0BFF */
+ /* Bit 21 Telugu */
+#define TT_UCR_TELUGU (1L << 21) /* U+0C00-U+0C7F */
+ /* Bit 22 Kannada */
+#define TT_UCR_KANNADA (1L << 22) /* U+0C80-U+0CFF */
+ /* Bit 23 Malayalam */
+#define TT_UCR_MALAYALAM (1L << 23) /* U+0D00-U+0D7F */
+ /* Bit 24 Thai */
+#define TT_UCR_THAI (1L << 24) /* U+0E00-U+0E7F */
+ /* Bit 25 Lao */
+#define TT_UCR_LAO (1L << 25) /* U+0E80-U+0EFF */
+ /* Bit 26 Georgian */
+ /* Georgian Supplement */
+#define TT_UCR_GEORGIAN (1L << 26) /* U+10A0-U+10FF */
+ /* U+2D00-U+2D2F */
+ /* Bit 27 Balinese */
+#define TT_UCR_BALINESE (1L << 27) /* U+1B00-U+1B7F */
+ /* Bit 28 Hangul Jamo */
+#define TT_UCR_HANGUL_JAMO (1L << 28) /* U+1100-U+11FF */
+ /* Bit 29 Latin Extended Additional */
+ /* Latin Extended-C */
+ /* Latin Extended-D */
+#define TT_UCR_LATIN_EXTENDED_ADDITIONAL (1L << 29) /* U+1E00-U+1EFF */
+ /* U+2C60-U+2C7F */
+ /* U+A720-U+A7FF */
+ /* Bit 30 Greek Extended */
+#define TT_UCR_GREEK_EXTENDED (1L << 30) /* U+1F00-U+1FFF */
+ /* Bit 31 General Punctuation */
+ /* Supplemental Punctuation */
+#define TT_UCR_GENERAL_PUNCTUATION (1L << 31) /* U+2000-U+206F */
+ /* U+2E00-U+2E7F */
+
+ /* ulUnicodeRange2 */
+ /* --------------- */
+
+ /* Bit 32 Superscripts And Subscripts */
+#define TT_UCR_SUPERSCRIPTS_SUBSCRIPTS (1L << 0) /* U+2070-U+209F */
+ /* Bit 33 Currency Symbols */
+#define TT_UCR_CURRENCY_SYMBOLS (1L << 1) /* U+20A0-U+20CF */
+ /* Bit 34 Combining Diacritical Marks For Symbols */
+#define TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB \
+ (1L << 2) /* U+20D0-U+20FF */
+ /* Bit 35 Letterlike Symbols */
+#define TT_UCR_LETTERLIKE_SYMBOLS (1L << 3) /* U+2100-U+214F */
+ /* Bit 36 Number Forms */
+#define TT_UCR_NUMBER_FORMS (1L << 4) /* U+2150-U+218F */
+ /* Bit 37 Arrows */
+ /* Supplemental Arrows-A */
+ /* Supplemental Arrows-B */
+ /* Miscellaneous Symbols and Arrows */
+#define TT_UCR_ARROWS (1L << 5) /* U+2190-U+21FF */
+ /* U+27F0-U+27FF */
+ /* U+2900-U+297F */
+ /* U+2B00-U+2BFF */
+ /* Bit 38 Mathematical Operators */
+ /* Supplemental Mathematical Operators */
+ /* Miscellaneous Mathematical Symbols-A */
+ /* Miscellaneous Mathematical Symbols-B */
+#define TT_UCR_MATHEMATICAL_OPERATORS (1L << 6) /* U+2200-U+22FF */
+ /* U+2A00-U+2AFF */
+ /* U+27C0-U+27EF */
+ /* U+2980-U+29FF */
+ /* Bit 39 Miscellaneous Technical */
+#define TT_UCR_MISCELLANEOUS_TECHNICAL (1L << 7) /* U+2300-U+23FF */
+ /* Bit 40 Control Pictures */
+#define TT_UCR_CONTROL_PICTURES (1L << 8) /* U+2400-U+243F */
+ /* Bit 41 Optical Character Recognition */
+#define TT_UCR_OCR (1L << 9) /* U+2440-U+245F */
+ /* Bit 42 Enclosed Alphanumerics */
+#define TT_UCR_ENCLOSED_ALPHANUMERICS (1L << 10) /* U+2460-U+24FF */
+ /* Bit 43 Box Drawing */
+#define TT_UCR_BOX_DRAWING (1L << 11) /* U+2500-U+257F */
+ /* Bit 44 Block Elements */
+#define TT_UCR_BLOCK_ELEMENTS (1L << 12) /* U+2580-U+259F */
+ /* Bit 45 Geometric Shapes */
+#define TT_UCR_GEOMETRIC_SHAPES (1L << 13) /* U+25A0-U+25FF */
+ /* Bit 46 Miscellaneous Symbols */
+#define TT_UCR_MISCELLANEOUS_SYMBOLS (1L << 14) /* U+2600-U+26FF */
+ /* Bit 47 Dingbats */
+#define TT_UCR_DINGBATS (1L << 15) /* U+2700-U+27BF */
+ /* Bit 48 CJK Symbols and Punctuation */
+#define TT_UCR_CJK_SYMBOLS (1L << 16) /* U+3000-U+303F */
+ /* Bit 49 Hiragana */
+#define TT_UCR_HIRAGANA (1L << 17) /* U+3040-U+309F */
+ /* Bit 50 Katakana */
+ /* Katakana Phonetic Extensions */
+#define TT_UCR_KATAKANA (1L << 18) /* U+30A0-U+30FF */
+ /* U+31F0-U+31FF */
+ /* Bit 51 Bopomofo */
+ /* Bopomofo Extended */
+#define TT_UCR_BOPOMOFO (1L << 19) /* U+3100-U+312F */
+ /* U+31A0-U+31BF */
+ /* Bit 52 Hangul Compatibility Jamo */
+#define TT_UCR_HANGUL_COMPATIBILITY_JAMO (1L << 20) /* U+3130-U+318F */
+ /* Bit 53 Phags-Pa */
+#define TT_UCR_CJK_MISC (1L << 21) /* U+A840-U+A87F */
+#define TT_UCR_KANBUN TT_UCR_CJK_MISC /* deprecated */
+#define TT_UCR_PHAGSPA
+ /* Bit 54 Enclosed CJK Letters and Months */
+#define TT_UCR_ENCLOSED_CJK_LETTERS_MONTHS (1L << 22) /* U+3200-U+32FF */
+ /* Bit 55 CJK Compatibility */
+#define TT_UCR_CJK_COMPATIBILITY (1L << 23) /* U+3300-U+33FF */
+ /* Bit 56 Hangul Syllables */
+#define TT_UCR_HANGUL (1L << 24) /* U+AC00-U+D7A3 */
+ /* Bit 57 High Surrogates */
+ /* High Private Use Surrogates */
+ /* Low Surrogates */
+
+ /* According to OpenType specs v.1.3+, */
+ /* setting bit 57 implies that there is */
+ /* at least one codepoint beyond the */
+ /* Basic Multilingual Plane that is */
+ /* supported by this font. So it really */
+ /* means >= U+10000. */
+#define TT_UCR_SURROGATES (1L << 25) /* U+D800-U+DB7F */
+ /* U+DB80-U+DBFF */
+ /* U+DC00-U+DFFF */
+#define TT_UCR_NON_PLANE_0 TT_UCR_SURROGATES
+ /* Bit 58 Phoenician */
+#define TT_UCR_PHOENICIAN (1L << 26) /*U+10900-U+1091F*/
+ /* Bit 59 CJK Unified Ideographs */
+ /* CJK Radicals Supplement */
+ /* Kangxi Radicals */
+ /* Ideographic Description Characters */
+ /* CJK Unified Ideographs Extension A */
+ /* CJK Unified Ideographs Extension B */
+ /* Kanbun */
+#define TT_UCR_CJK_UNIFIED_IDEOGRAPHS (1L << 27) /* U+4E00-U+9FFF */
+ /* U+2E80-U+2EFF */
+ /* U+2F00-U+2FDF */
+ /* U+2FF0-U+2FFF */
+ /* U+3400-U+4DB5 */
+ /*U+20000-U+2A6DF*/
+ /* U+3190-U+319F */
+ /* Bit 60 Private Use */
+#define TT_UCR_PRIVATE_USE (1L << 28) /* U+E000-U+F8FF */
+ /* Bit 61 CJK Strokes */
+ /* CJK Compatibility Ideographs */
+ /* CJK Compatibility Ideographs Supplement */
+#define TT_UCR_CJK_COMPATIBILITY_IDEOGRAPHS (1L << 29) /* U+31C0-U+31EF */
+ /* U+F900-U+FAFF */
+ /*U+2F800-U+2FA1F*/
+ /* Bit 62 Alphabetic Presentation Forms */
+#define TT_UCR_ALPHABETIC_PRESENTATION_FORMS (1L << 30) /* U+FB00-U+FB4F */
+ /* Bit 63 Arabic Presentation Forms-A */
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_A (1L << 31) /* U+FB50-U+FDFF */
+
+ /* ulUnicodeRange3 */
+ /* --------------- */
+
+ /* Bit 64 Combining Half Marks */
+#define TT_UCR_COMBINING_HALF_MARKS (1L << 0) /* U+FE20-U+FE2F */
+ /* Bit 65 Vertical forms */
+ /* CJK Compatibility Forms */
+#define TT_UCR_CJK_COMPATIBILITY_FORMS (1L << 1) /* U+FE10-U+FE1F */
+ /* U+FE30-U+FE4F */
+ /* Bit 66 Small Form Variants */
+#define TT_UCR_SMALL_FORM_VARIANTS (1L << 2) /* U+FE50-U+FE6F */
+ /* Bit 67 Arabic Presentation Forms-B */
+#define TT_UCR_ARABIC_PRESENTATION_FORMS_B (1L << 3) /* U+FE70-U+FEFE */
+ /* Bit 68 Halfwidth and Fullwidth Forms */
+#define TT_UCR_HALFWIDTH_FULLWIDTH_FORMS (1L << 4) /* U+FF00-U+FFEF */
+ /* Bit 69 Specials */
+#define TT_UCR_SPECIALS (1L << 5) /* U+FFF0-U+FFFD */
+ /* Bit 70 Tibetan */
+#define TT_UCR_TIBETAN (1L << 6) /* U+0F00-U+0FFF */
+ /* Bit 71 Syriac */
+#define TT_UCR_SYRIAC (1L << 7) /* U+0700-U+074F */
+ /* Bit 72 Thaana */
+#define TT_UCR_THAANA (1L << 8) /* U+0780-U+07BF */
+ /* Bit 73 Sinhala */
+#define TT_UCR_SINHALA (1L << 9) /* U+0D80-U+0DFF */
+ /* Bit 74 Myanmar */
+#define TT_UCR_MYANMAR (1L << 10) /* U+1000-U+109F */
+ /* Bit 75 Ethiopic */
+ /* Ethiopic Supplement */
+ /* Ethiopic Extended */
+#define TT_UCR_ETHIOPIC (1L << 11) /* U+1200-U+137F */
+ /* U+1380-U+139F */
+ /* U+2D80-U+2DDF */
+ /* Bit 76 Cherokee */
+#define TT_UCR_CHEROKEE (1L << 12) /* U+13A0-U+13FF */
+ /* Bit 77 Unified Canadian Aboriginal Syllabics */
+#define TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS (1L << 13) /* U+1400-U+167F */
+ /* Bit 78 Ogham */
+#define TT_UCR_OGHAM (1L << 14) /* U+1680-U+169F */
+ /* Bit 79 Runic */
+#define TT_UCR_RUNIC (1L << 15) /* U+16A0-U+16FF */
+ /* Bit 80 Khmer */
+ /* Khmer Symbols */
+#define TT_UCR_KHMER (1L << 16) /* U+1780-U+17FF */
+ /* U+19E0-U+19FF */
+ /* Bit 81 Mongolian */
+#define TT_UCR_MONGOLIAN (1L << 17) /* U+1800-U+18AF */
+ /* Bit 82 Braille Patterns */
+#define TT_UCR_BRAILLE (1L << 18) /* U+2800-U+28FF */
+ /* Bit 83 Yi Syllables */
+ /* Yi Radicals */
+#define TT_UCR_YI (1L << 19) /* U+A000-U+A48F */
+ /* U+A490-U+A4CF */
+ /* Bit 84 Tagalog */
+ /* Hanunoo */
+ /* Buhid */
+ /* Tagbanwa */
+#define TT_UCR_PHILIPPINE (1L << 20) /* U+1700-U+171F */
+ /* U+1720-U+173F */
+ /* U+1740-U+175F */
+ /* U+1760-U+177F */
+ /* Bit 85 Old Italic */
+#define TT_UCR_OLD_ITALIC (1L << 21) /*U+10300-U+1032F*/
+ /* Bit 86 Gothic */
+#define TT_UCR_GOTHIC (1L << 22) /*U+10330-U+1034F*/
+ /* Bit 87 Deseret */
+#define TT_UCR_DESERET (1L << 23) /*U+10400-U+1044F*/
+ /* Bit 88 Byzantine Musical Symbols */
+ /* Musical Symbols */
+ /* Ancient Greek Musical Notation */
+#define TT_UCR_MUSICAL_SYMBOLS (1L << 24) /*U+1D000-U+1D0FF*/
+ /*U+1D100-U+1D1FF*/
+ /*U+1D200-U+1D24F*/
+ /* Bit 89 Mathematical Alphanumeric Symbols */
+#define TT_UCR_MATH_ALPHANUMERIC_SYMBOLS (1L << 25) /*U+1D400-U+1D7FF*/
+ /* Bit 90 Private Use (plane 15) */
+ /* Private Use (plane 16) */
+#define TT_UCR_PRIVATE_USE_SUPPLEMENTARY (1L << 26) /*U+F0000-U+FFFFD*/
+ /*U+100000-U+10FFFD*/
+ /* Bit 91 Variation Selectors */
+ /* Variation Selectors Supplement */
+#define TT_UCR_VARIATION_SELECTORS (1L << 27) /* U+FE00-U+FE0F */
+ /*U+E0100-U+E01EF*/
+ /* Bit 92 Tags */
+#define TT_UCR_TAGS (1L << 28) /*U+E0000-U+E007F*/
+ /* Bit 93 Limbu */
+#define TT_UCR_LIMBU (1L << 29) /* U+1900-U+194F */
+ /* Bit 94 Tai Le */
+#define TT_UCR_TAI_LE (1L << 30) /* U+1950-U+197F */
+ /* Bit 95 New Tai Lue */
+#define TT_UCR_NEW_TAI_LUE (1L << 31) /* U+1980-U+19DF */
+
+ /* ulUnicodeRange4 */
+ /* --------------- */
+
+ /* Bit 96 Buginese */
+#define TT_UCR_BUGINESE (1L << 0) /* U+1A00-U+1A1F */
+ /* Bit 97 Glagolitic */
+#define TT_UCR_GLAGOLITIC (1L << 1) /* U+2C00-U+2C5F */
+ /* Bit 98 Tifinagh */
+#define TT_UCR_TIFINAGH (1L << 2) /* U+2D30-U+2D7F */
+ /* Bit 99 Yijing Hexagram Symbols */
+#define TT_UCR_YIJING (1L << 3) /* U+4DC0-U+4DFF */
+ /* Bit 100 Syloti Nagri */
+#define TT_UCR_SYLOTI_NAGRI (1L << 4) /* U+A800-U+A82F */
+ /* Bit 101 Linear B Syllabary */
+ /* Linear B Ideograms */
+ /* Aegean Numbers */
+#define TT_UCR_LINEAR_B (1L << 5) /*U+10000-U+1007F*/
+ /*U+10080-U+100FF*/
+ /*U+10100-U+1013F*/
+ /* Bit 102 Ancient Greek Numbers */
+#define TT_UCR_ANCIENT_GREEK_NUMBERS (1L << 6) /*U+10140-U+1018F*/
+ /* Bit 103 Ugaritic */
+#define TT_UCR_UGARITIC (1L << 7) /*U+10380-U+1039F*/
+ /* Bit 104 Old Persian */
+#define TT_UCR_OLD_PERSIAN (1L << 8) /*U+103A0-U+103DF*/
+ /* Bit 105 Shavian */
+#define TT_UCR_SHAVIAN (1L << 9) /*U+10450-U+1047F*/
+ /* Bit 106 Osmanya */
+#define TT_UCR_OSMANYA (1L << 10) /*U+10480-U+104AF*/
+ /* Bit 107 Cypriot Syllabary */
+#define TT_UCR_CYPRIOT_SYLLABARY (1L << 11) /*U+10800-U+1083F*/
+ /* Bit 108 Kharoshthi */
+#define TT_UCR_KHAROSHTHI (1L << 12) /*U+10A00-U+10A5F*/
+ /* Bit 109 Tai Xuan Jing Symbols */
+#define TT_UCR_TAI_XUAN_JING (1L << 13) /*U+1D300-U+1D35F*/
+ /* Bit 110 Cuneiform */
+ /* Cuneiform Numbers and Punctuation */
+#define TT_UCR_CUNEIFORM (1L << 14) /*U+12000-U+123FF*/
+ /*U+12400-U+1247F*/
+ /* Bit 111 Counting Rod Numerals */
+#define TT_UCR_COUNTING_ROD_NUMERALS (1L << 15) /*U+1D360-U+1D37F*/
+ /* Bit 112 Sundanese */
+#define TT_UCR_SUNDANESE (1L << 16) /* U+1B80-U+1BBF */
+ /* Bit 113 Lepcha */
+#define TT_UCR_LEPCHA (1L << 17) /* U+1C00-U+1C4F */
+ /* Bit 114 Ol Chiki */
+#define TT_UCR_OL_CHIKI (1L << 18) /* U+1C50-U+1C7F */
+ /* Bit 115 Saurashtra */
+#define TT_UCR_SAURASHTRA (1L << 19) /* U+A880-U+A8DF */
+ /* Bit 116 Kayah Li */
+#define TT_UCR_KAYAH_LI (1L << 20) /* U+A900-U+A92F */
+ /* Bit 117 Rejang */
+#define TT_UCR_REJANG (1L << 21) /* U+A930-U+A95F */
+ /* Bit 118 Cham */
+#define TT_UCR_CHAM (1L << 22) /* U+AA00-U+AA5F */
+ /* Bit 119 Ancient Symbols */
+#define TT_UCR_ANCIENT_SYMBOLS (1L << 23) /*U+10190-U+101CF*/
+ /* Bit 120 Phaistos Disc */
+#define TT_UCR_PHAISTOS_DISC (1L << 24) /*U+101D0-U+101FF*/
+ /* Bit 121 Carian */
+ /* Lycian */
+ /* Lydian */
+#define TT_UCR_OLD_ANATOLIAN (1L << 25) /*U+102A0-U+102DF*/
+ /*U+10280-U+1029F*/
+ /*U+10920-U+1093F*/
+ /* Bit 122 Domino Tiles */
+ /* Mahjong Tiles */
+#define TT_UCR_GAME_TILES (1L << 26) /*U+1F030-U+1F09F*/
+ /*U+1F000-U+1F02F*/
+ /* Bit 123-127 Reserved for process-internal usage */
+
+ /* */
+
+ /* for backward compatibility with older FreeType versions */
+#define TT_UCR_ARABIC_PRESENTATION_A \
+ TT_UCR_ARABIC_PRESENTATION_FORMS_A
+#define TT_UCR_ARABIC_PRESENTATION_B \
+ TT_UCR_ARABIC_PRESENTATION_FORMS_B
+
+#define TT_UCR_COMBINING_DIACRITICS \
+ TT_UCR_COMBINING_DIACRITICAL_MARKS
+#define TT_UCR_COMBINING_DIACRITICS_SYMB \
+ TT_UCR_COMBINING_DIACRITICAL_MARKS_SYMB
+
+
+FT_END_HEADER
+
+#endif /* TTNAMEID_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/tttables.h b/Client/ThirdParty/freetype/include/freetype/tttables.h
new file mode 100644
index 0000000..c33d990
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/tttables.h
@@ -0,0 +1,855 @@
+/****************************************************************************
+ *
+ * tttables.h
+ *
+ * Basic SFNT/TrueType tables definitions and interface
+ * (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef TTTABLES_H_
+#define TTTABLES_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+ /**************************************************************************
+ *
+ * @section:
+ * truetype_tables
+ *
+ * @title:
+ * TrueType Tables
+ *
+ * @abstract:
+ * TrueType-specific table types and functions.
+ *
+ * @description:
+ * This section contains definitions of some basic tables specific to
+ * TrueType and OpenType as well as some routines used to access and
+ * process them.
+ *
+ * @order:
+ * TT_Header
+ * TT_HoriHeader
+ * TT_VertHeader
+ * TT_OS2
+ * TT_Postscript
+ * TT_PCLT
+ * TT_MaxProfile
+ *
+ * FT_Sfnt_Tag
+ * FT_Get_Sfnt_Table
+ * FT_Load_Sfnt_Table
+ * FT_Sfnt_Table_Info
+ *
+ * FT_Get_CMap_Language_ID
+ * FT_Get_CMap_Format
+ *
+ * FT_PARAM_TAG_UNPATENTED_HINTING
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Header
+ *
+ * @description:
+ * A structure to model a TrueType font header table. All fields follow
+ * the OpenType specification. The 64-bit timestamps are stored in
+ * two-element arrays `Created` and `Modified`, first the upper then
+ * the lower 32~bits.
+ */
+ typedef struct TT_Header_
+ {
+ FT_Fixed Table_Version;
+ FT_Fixed Font_Revision;
+
+ FT_Long CheckSum_Adjust;
+ FT_Long Magic_Number;
+
+ FT_UShort Flags;
+ FT_UShort Units_Per_EM;
+
+ FT_ULong Created [2];
+ FT_ULong Modified[2];
+
+ FT_Short xMin;
+ FT_Short yMin;
+ FT_Short xMax;
+ FT_Short yMax;
+
+ FT_UShort Mac_Style;
+ FT_UShort Lowest_Rec_PPEM;
+
+ FT_Short Font_Direction;
+ FT_Short Index_To_Loc_Format;
+ FT_Short Glyph_Data_Format;
+
+ } TT_Header;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_HoriHeader
+ *
+ * @description:
+ * A structure to model a TrueType horizontal header, the 'hhea' table,
+ * as well as the corresponding horizontal metrics table, 'hmtx'.
+ *
+ * @fields:
+ * Version ::
+ * The table version.
+ *
+ * Ascender ::
+ * The font's ascender, i.e., the distance from the baseline to the
+ * top-most of all glyph points found in the font.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoAscender` field of the 'OS/2' table instead
+ * if you want the correct one.
+ *
+ * Descender ::
+ * The font's descender, i.e., the distance from the baseline to the
+ * bottom-most of all glyph points found in the font. It is negative.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoDescender` field of the 'OS/2' table
+ * instead if you want the correct one.
+ *
+ * Line_Gap ::
+ * The font's line gap, i.e., the distance to add to the ascender and
+ * descender to get the BTB, i.e., the baseline-to-baseline distance
+ * for the font.
+ *
+ * advance_Width_Max ::
+ * This field is the maximum of all advance widths found in the font.
+ * It can be used to compute the maximum width of an arbitrary string
+ * of text.
+ *
+ * min_Left_Side_Bearing ::
+ * The minimum left side bearing of all glyphs within the font.
+ *
+ * min_Right_Side_Bearing ::
+ * The minimum right side bearing of all glyphs within the font.
+ *
+ * xMax_Extent ::
+ * The maximum horizontal extent (i.e., the 'width' of a glyph's
+ * bounding box) for all glyphs in the font.
+ *
+ * caret_Slope_Rise ::
+ * The rise coefficient of the cursor's slope of the cursor
+ * (slope=rise/run).
+ *
+ * caret_Slope_Run ::
+ * The run coefficient of the cursor's slope.
+ *
+ * caret_Offset ::
+ * The cursor's offset for slanted fonts.
+ *
+ * Reserved ::
+ * 8~reserved bytes.
+ *
+ * metric_Data_Format ::
+ * Always~0.
+ *
+ * number_Of_HMetrics ::
+ * Number of HMetrics entries in the 'hmtx' table -- this value can be
+ * smaller than the total number of glyphs in the font.
+ *
+ * long_metrics ::
+ * A pointer into the 'hmtx' table.
+ *
+ * short_metrics ::
+ * A pointer into the 'hmtx' table.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `caret_Slope_Rise`,
+ * `caret_Slope_Run`, and `caret_Offset`.
+ */
+ typedef struct TT_HoriHeader_
+ {
+ FT_Fixed Version;
+ FT_Short Ascender;
+ FT_Short Descender;
+ FT_Short Line_Gap;
+
+ FT_UShort advance_Width_Max; /* advance width maximum */
+
+ FT_Short min_Left_Side_Bearing; /* minimum left-sb */
+ FT_Short min_Right_Side_Bearing; /* minimum right-sb */
+ FT_Short xMax_Extent; /* xmax extents */
+ FT_Short caret_Slope_Rise;
+ FT_Short caret_Slope_Run;
+ FT_Short caret_Offset;
+
+ FT_Short Reserved[4];
+
+ FT_Short metric_Data_Format;
+ FT_UShort number_Of_HMetrics;
+
+ /* The following fields are not defined by the OpenType specification */
+ /* but they are used to connect the metrics header to the relevant */
+ /* 'hmtx' table. */
+
+ void* long_metrics;
+ void* short_metrics;
+
+ } TT_HoriHeader;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_VertHeader
+ *
+ * @description:
+ * A structure used to model a TrueType vertical header, the 'vhea'
+ * table, as well as the corresponding vertical metrics table, 'vmtx'.
+ *
+ * @fields:
+ * Version ::
+ * The table version.
+ *
+ * Ascender ::
+ * The font's ascender, i.e., the distance from the baseline to the
+ * top-most of all glyph points found in the font.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoAscender` field of the 'OS/2' table instead
+ * if you want the correct one.
+ *
+ * Descender ::
+ * The font's descender, i.e., the distance from the baseline to the
+ * bottom-most of all glyph points found in the font. It is negative.
+ *
+ * This value is invalid in many fonts, as it is usually set by the
+ * font designer, and often reflects only a portion of the glyphs found
+ * in the font (maybe ASCII).
+ *
+ * You should use the `sTypoDescender` field of the 'OS/2' table
+ * instead if you want the correct one.
+ *
+ * Line_Gap ::
+ * The font's line gap, i.e., the distance to add to the ascender and
+ * descender to get the BTB, i.e., the baseline-to-baseline distance
+ * for the font.
+ *
+ * advance_Height_Max ::
+ * This field is the maximum of all advance heights found in the font.
+ * It can be used to compute the maximum height of an arbitrary string
+ * of text.
+ *
+ * min_Top_Side_Bearing ::
+ * The minimum top side bearing of all glyphs within the font.
+ *
+ * min_Bottom_Side_Bearing ::
+ * The minimum bottom side bearing of all glyphs within the font.
+ *
+ * yMax_Extent ::
+ * The maximum vertical extent (i.e., the 'height' of a glyph's
+ * bounding box) for all glyphs in the font.
+ *
+ * caret_Slope_Rise ::
+ * The rise coefficient of the cursor's slope of the cursor
+ * (slope=rise/run).
+ *
+ * caret_Slope_Run ::
+ * The run coefficient of the cursor's slope.
+ *
+ * caret_Offset ::
+ * The cursor's offset for slanted fonts.
+ *
+ * Reserved ::
+ * 8~reserved bytes.
+ *
+ * metric_Data_Format ::
+ * Always~0.
+ *
+ * number_Of_VMetrics ::
+ * Number of VMetrics entries in the 'vmtx' table -- this value can be
+ * smaller than the total number of glyphs in the font.
+ *
+ * long_metrics ::
+ * A pointer into the 'vmtx' table.
+ *
+ * short_metrics ::
+ * A pointer into the 'vmtx' table.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `Ascender`, `Descender`,
+ * `Line_Gap`, `caret_Slope_Rise`, `caret_Slope_Run`, and `caret_Offset`.
+ */
+ typedef struct TT_VertHeader_
+ {
+ FT_Fixed Version;
+ FT_Short Ascender;
+ FT_Short Descender;
+ FT_Short Line_Gap;
+
+ FT_UShort advance_Height_Max; /* advance height maximum */
+
+ FT_Short min_Top_Side_Bearing; /* minimum top-sb */
+ FT_Short min_Bottom_Side_Bearing; /* minimum bottom-sb */
+ FT_Short yMax_Extent; /* ymax extents */
+ FT_Short caret_Slope_Rise;
+ FT_Short caret_Slope_Run;
+ FT_Short caret_Offset;
+
+ FT_Short Reserved[4];
+
+ FT_Short metric_Data_Format;
+ FT_UShort number_Of_VMetrics;
+
+ /* The following fields are not defined by the OpenType specification */
+ /* but they are used to connect the metrics header to the relevant */
+ /* 'vmtx' table. */
+
+ void* long_metrics;
+ void* short_metrics;
+
+ } TT_VertHeader;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_OS2
+ *
+ * @description:
+ * A structure to model a TrueType 'OS/2' table. All fields comply to
+ * the OpenType specification.
+ *
+ * Note that we now support old Mac fonts that do not include an 'OS/2'
+ * table. In this case, the `version` field is always set to 0xFFFF.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `sCapHeight`, `sTypoAscender`,
+ * `sTypoDescender`, `sTypoLineGap`, `sxHeight`, `usWinAscent`,
+ * `usWinDescent`, `yStrikeoutPosition`, `yStrikeoutSize`,
+ * `ySubscriptXOffset`, `ySubScriptXSize`, `ySubscriptYOffset`,
+ * `ySubscriptYSize`, `ySuperscriptXOffset`, `ySuperscriptXSize`,
+ * `ySuperscriptYOffset`, and `ySuperscriptYSize`.
+ *
+ * Possible values for bits in the `ulUnicodeRangeX` fields are given by
+ * the @TT_UCR_XXX macros.
+ */
+
+ typedef struct TT_OS2_
+ {
+ FT_UShort version; /* 0x0001 - more or 0xFFFF */
+ FT_Short xAvgCharWidth;
+ FT_UShort usWeightClass;
+ FT_UShort usWidthClass;
+ FT_UShort fsType;
+ FT_Short ySubscriptXSize;
+ FT_Short ySubscriptYSize;
+ FT_Short ySubscriptXOffset;
+ FT_Short ySubscriptYOffset;
+ FT_Short ySuperscriptXSize;
+ FT_Short ySuperscriptYSize;
+ FT_Short ySuperscriptXOffset;
+ FT_Short ySuperscriptYOffset;
+ FT_Short yStrikeoutSize;
+ FT_Short yStrikeoutPosition;
+ FT_Short sFamilyClass;
+
+ FT_Byte panose[10];
+
+ FT_ULong ulUnicodeRange1; /* Bits 0-31 */
+ FT_ULong ulUnicodeRange2; /* Bits 32-63 */
+ FT_ULong ulUnicodeRange3; /* Bits 64-95 */
+ FT_ULong ulUnicodeRange4; /* Bits 96-127 */
+
+ FT_Char achVendID[4];
+
+ FT_UShort fsSelection;
+ FT_UShort usFirstCharIndex;
+ FT_UShort usLastCharIndex;
+ FT_Short sTypoAscender;
+ FT_Short sTypoDescender;
+ FT_Short sTypoLineGap;
+ FT_UShort usWinAscent;
+ FT_UShort usWinDescent;
+
+ /* only version 1 and higher: */
+
+ FT_ULong ulCodePageRange1; /* Bits 0-31 */
+ FT_ULong ulCodePageRange2; /* Bits 32-63 */
+
+ /* only version 2 and higher: */
+
+ FT_Short sxHeight;
+ FT_Short sCapHeight;
+ FT_UShort usDefaultChar;
+ FT_UShort usBreakChar;
+ FT_UShort usMaxContext;
+
+ /* only version 5 and higher: */
+
+ FT_UShort usLowerOpticalPointSize; /* in twips (1/20th points) */
+ FT_UShort usUpperOpticalPointSize; /* in twips (1/20th points) */
+
+ } TT_OS2;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_Postscript
+ *
+ * @description:
+ * A structure to model a TrueType 'post' table. All fields comply to
+ * the OpenType specification. This structure does not reference a
+ * font's PostScript glyph names; use @FT_Get_Glyph_Name to retrieve
+ * them.
+ *
+ * @note:
+ * For an OpenType variation font, the values of the following fields can
+ * change after a call to @FT_Set_Var_Design_Coordinates (and friends) if
+ * the font contains an 'MVAR' table: `underlinePosition` and
+ * `underlineThickness`.
+ */
+ typedef struct TT_Postscript_
+ {
+ FT_Fixed FormatType;
+ FT_Fixed italicAngle;
+ FT_Short underlinePosition;
+ FT_Short underlineThickness;
+ FT_ULong isFixedPitch;
+ FT_ULong minMemType42;
+ FT_ULong maxMemType42;
+ FT_ULong minMemType1;
+ FT_ULong maxMemType1;
+
+ /* Glyph names follow in the 'post' table, but we don't */
+ /* load them by default. */
+
+ } TT_Postscript;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_PCLT
+ *
+ * @description:
+ * A structure to model a TrueType 'PCLT' table. All fields comply to
+ * the OpenType specification.
+ */
+ typedef struct TT_PCLT_
+ {
+ FT_Fixed Version;
+ FT_ULong FontNumber;
+ FT_UShort Pitch;
+ FT_UShort xHeight;
+ FT_UShort Style;
+ FT_UShort TypeFamily;
+ FT_UShort CapHeight;
+ FT_UShort SymbolSet;
+ FT_Char TypeFace[16];
+ FT_Char CharacterComplement[8];
+ FT_Char FileName[6];
+ FT_Char StrokeWeight;
+ FT_Char WidthType;
+ FT_Byte SerifStyle;
+ FT_Byte Reserved;
+
+ } TT_PCLT;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * TT_MaxProfile
+ *
+ * @description:
+ * The maximum profile ('maxp') table contains many max values, which can
+ * be used to pre-allocate arrays for speeding up glyph loading and
+ * hinting.
+ *
+ * @fields:
+ * version ::
+ * The version number.
+ *
+ * numGlyphs ::
+ * The number of glyphs in this TrueType font.
+ *
+ * maxPoints ::
+ * The maximum number of points in a non-composite TrueType glyph. See
+ * also `maxCompositePoints`.
+ *
+ * maxContours ::
+ * The maximum number of contours in a non-composite TrueType glyph.
+ * See also `maxCompositeContours`.
+ *
+ * maxCompositePoints ::
+ * The maximum number of points in a composite TrueType glyph. See
+ * also `maxPoints`.
+ *
+ * maxCompositeContours ::
+ * The maximum number of contours in a composite TrueType glyph. See
+ * also `maxContours`.
+ *
+ * maxZones ::
+ * The maximum number of zones used for glyph hinting.
+ *
+ * maxTwilightPoints ::
+ * The maximum number of points in the twilight zone used for glyph
+ * hinting.
+ *
+ * maxStorage ::
+ * The maximum number of elements in the storage area used for glyph
+ * hinting.
+ *
+ * maxFunctionDefs ::
+ * The maximum number of function definitions in the TrueType bytecode
+ * for this font.
+ *
+ * maxInstructionDefs ::
+ * The maximum number of instruction definitions in the TrueType
+ * bytecode for this font.
+ *
+ * maxStackElements ::
+ * The maximum number of stack elements used during bytecode
+ * interpretation.
+ *
+ * maxSizeOfInstructions ::
+ * The maximum number of TrueType opcodes used for glyph hinting.
+ *
+ * maxComponentElements ::
+ * The maximum number of simple (i.e., non-composite) glyphs in a
+ * composite glyph.
+ *
+ * maxComponentDepth ::
+ * The maximum nesting depth of composite glyphs.
+ *
+ * @note:
+ * This structure is only used during font loading.
+ */
+ typedef struct TT_MaxProfile_
+ {
+ FT_Fixed version;
+ FT_UShort numGlyphs;
+ FT_UShort maxPoints;
+ FT_UShort maxContours;
+ FT_UShort maxCompositePoints;
+ FT_UShort maxCompositeContours;
+ FT_UShort maxZones;
+ FT_UShort maxTwilightPoints;
+ FT_UShort maxStorage;
+ FT_UShort maxFunctionDefs;
+ FT_UShort maxInstructionDefs;
+ FT_UShort maxStackElements;
+ FT_UShort maxSizeOfInstructions;
+ FT_UShort maxComponentElements;
+ FT_UShort maxComponentDepth;
+
+ } TT_MaxProfile;
+
+
+ /**************************************************************************
+ *
+ * @enum:
+ * FT_Sfnt_Tag
+ *
+ * @description:
+ * An enumeration to specify indices of SFNT tables loaded and parsed by
+ * FreeType during initialization of an SFNT font. Used in the
+ * @FT_Get_Sfnt_Table API function.
+ *
+ * @values:
+ * FT_SFNT_HEAD ::
+ * To access the font's @TT_Header structure.
+ *
+ * FT_SFNT_MAXP ::
+ * To access the font's @TT_MaxProfile structure.
+ *
+ * FT_SFNT_OS2 ::
+ * To access the font's @TT_OS2 structure.
+ *
+ * FT_SFNT_HHEA ::
+ * To access the font's @TT_HoriHeader structure.
+ *
+ * FT_SFNT_VHEA ::
+ * To access the font's @TT_VertHeader structure.
+ *
+ * FT_SFNT_POST ::
+ * To access the font's @TT_Postscript structure.
+ *
+ * FT_SFNT_PCLT ::
+ * To access the font's @TT_PCLT structure.
+ */
+ typedef enum FT_Sfnt_Tag_
+ {
+ FT_SFNT_HEAD,
+ FT_SFNT_MAXP,
+ FT_SFNT_OS2,
+ FT_SFNT_HHEA,
+ FT_SFNT_VHEA,
+ FT_SFNT_POST,
+ FT_SFNT_PCLT,
+
+ FT_SFNT_MAX
+
+ } FT_Sfnt_Tag;
+
+ /* these constants are deprecated; use the corresponding `FT_Sfnt_Tag` */
+ /* values instead */
+#define ft_sfnt_head FT_SFNT_HEAD
+#define ft_sfnt_maxp FT_SFNT_MAXP
+#define ft_sfnt_os2 FT_SFNT_OS2
+#define ft_sfnt_hhea FT_SFNT_HHEA
+#define ft_sfnt_vhea FT_SFNT_VHEA
+#define ft_sfnt_post FT_SFNT_POST
+#define ft_sfnt_pclt FT_SFNT_PCLT
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_Sfnt_Table
+ *
+ * @description:
+ * Return a pointer to a given SFNT table stored within a face.
+ *
+ * @input:
+ * face ::
+ * A handle to the source.
+ *
+ * tag ::
+ * The index of the SFNT table.
+ *
+ * @return:
+ * A type-less pointer to the table. This will be `NULL` in case of
+ * error, or if the corresponding table was not found **OR** loaded from
+ * the file.
+ *
+ * Use a typecast according to `tag` to access the structure elements.
+ *
+ * @note:
+ * The table is owned by the face object and disappears with it.
+ *
+ * This function is only useful to access SFNT tables that are loaded by
+ * the sfnt, truetype, and opentype drivers. See @FT_Sfnt_Tag for a
+ * list.
+ *
+ * @example:
+ * Here is an example demonstrating access to the 'vhea' table.
+ *
+ * ```
+ * TT_VertHeader* vert_header;
+ *
+ *
+ * vert_header =
+ * (TT_VertHeader*)FT_Get_Sfnt_Table( face, FT_SFNT_VHEA );
+ * ```
+ */
+ FT_EXPORT( void* )
+ FT_Get_Sfnt_Table( FT_Face face,
+ FT_Sfnt_Tag tag );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Load_Sfnt_Table
+ *
+ * @description:
+ * Load any SFNT font table into client memory.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * tag ::
+ * The four-byte tag of the table to load. Use value~0 if you want to
+ * access the whole font file. Otherwise, you can use one of the
+ * definitions found in the @FT_TRUETYPE_TAGS_H file, or forge a new
+ * one with @FT_MAKE_TAG.
+ *
+ * offset ::
+ * The starting offset in the table (or file if tag~==~0).
+ *
+ * @output:
+ * buffer ::
+ * The target buffer address. The client must ensure that the memory
+ * array is big enough to hold the data.
+ *
+ * @inout:
+ * length ::
+ * If the `length` parameter is `NULL`, try to load the whole table.
+ * Return an error code if it fails.
+ *
+ * Else, if `*length` is~0, exit immediately while returning the
+ * table's (or file) full size in it.
+ *
+ * Else the number of bytes to read from the table or file, from the
+ * starting offset.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * If you need to determine the table's length you should first call this
+ * function with `*length` set to~0, as in the following example:
+ *
+ * ```
+ * FT_ULong length = 0;
+ *
+ *
+ * error = FT_Load_Sfnt_Table( face, tag, 0, NULL, &length );
+ * if ( error ) { ... table does not exist ... }
+ *
+ * buffer = malloc( length );
+ * if ( buffer == NULL ) { ... not enough memory ... }
+ *
+ * error = FT_Load_Sfnt_Table( face, tag, 0, buffer, &length );
+ * if ( error ) { ... could not load table ... }
+ * ```
+ *
+ * Note that structures like @TT_Header or @TT_OS2 can't be used with
+ * this function; they are limited to @FT_Get_Sfnt_Table. Reason is that
+ * those structures depend on the processor architecture, with varying
+ * size (e.g. 32bit vs. 64bit) or order (big endian vs. little endian).
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Load_Sfnt_Table( FT_Face face,
+ FT_ULong tag,
+ FT_Long offset,
+ FT_Byte* buffer,
+ FT_ULong* length );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Sfnt_Table_Info
+ *
+ * @description:
+ * Return information on an SFNT table.
+ *
+ * @input:
+ * face ::
+ * A handle to the source face.
+ *
+ * table_index ::
+ * The index of an SFNT table. The function returns
+ * FT_Err_Table_Missing for an invalid value.
+ *
+ * @inout:
+ * tag ::
+ * The name tag of the SFNT table. If the value is `NULL`,
+ * `table_index` is ignored, and `length` returns the number of SFNT
+ * tables in the font.
+ *
+ * @output:
+ * length ::
+ * The length of the SFNT table (or the number of SFNT tables,
+ * depending on `tag`).
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * While parsing fonts, FreeType handles SFNT tables with length zero as
+ * missing.
+ *
+ */
+ FT_EXPORT( FT_Error )
+ FT_Sfnt_Table_Info( FT_Face face,
+ FT_UInt table_index,
+ FT_ULong *tag,
+ FT_ULong *length );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CMap_Language_ID
+ *
+ * @description:
+ * Return cmap language ID as specified in the OpenType standard.
+ * Definitions of language ID values are in file @FT_TRUETYPE_IDS_H.
+ *
+ * @input:
+ * charmap ::
+ * The target charmap.
+ *
+ * @return:
+ * The language ID of `charmap`. If `charmap` doesn't belong to an SFNT
+ * face, just return~0 as the default value.
+ *
+ * For a format~14 cmap (to access Unicode IVS), the return value is
+ * 0xFFFFFFFF.
+ */
+ FT_EXPORT( FT_ULong )
+ FT_Get_CMap_Language_ID( FT_CharMap charmap );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Get_CMap_Format
+ *
+ * @description:
+ * Return the format of an SFNT 'cmap' table.
+ *
+ * @input:
+ * charmap ::
+ * The target charmap.
+ *
+ * @return:
+ * The format of `charmap`. If `charmap` doesn't belong to an SFNT face,
+ * return -1.
+ */
+ FT_EXPORT( FT_Long )
+ FT_Get_CMap_Format( FT_CharMap charmap );
+
+ /* */
+
+
+FT_END_HEADER
+
+#endif /* TTTABLES_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/freetype/tttags.h b/Client/ThirdParty/freetype/include/freetype/tttags.h
new file mode 100644
index 0000000..47ccc6d
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/freetype/tttags.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+ *
+ * tttags.h
+ *
+ * Tags for TrueType and OpenType tables (specification only).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef TTAGS_H_
+#define TTAGS_H_
+
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+#define TTAG_avar FT_MAKE_TAG( 'a', 'v', 'a', 'r' )
+#define TTAG_BASE FT_MAKE_TAG( 'B', 'A', 'S', 'E' )
+#define TTAG_bdat FT_MAKE_TAG( 'b', 'd', 'a', 't' )
+#define TTAG_BDF FT_MAKE_TAG( 'B', 'D', 'F', ' ' )
+#define TTAG_bhed FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
+#define TTAG_bloc FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
+#define TTAG_bsln FT_MAKE_TAG( 'b', 's', 'l', 'n' )
+#define TTAG_CBDT FT_MAKE_TAG( 'C', 'B', 'D', 'T' )
+#define TTAG_CBLC FT_MAKE_TAG( 'C', 'B', 'L', 'C' )
+#define TTAG_CFF FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
+#define TTAG_CFF2 FT_MAKE_TAG( 'C', 'F', 'F', '2' )
+#define TTAG_CID FT_MAKE_TAG( 'C', 'I', 'D', ' ' )
+#define TTAG_cmap FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
+#define TTAG_COLR FT_MAKE_TAG( 'C', 'O', 'L', 'R' )
+#define TTAG_CPAL FT_MAKE_TAG( 'C', 'P', 'A', 'L' )
+#define TTAG_cvar FT_MAKE_TAG( 'c', 'v', 'a', 'r' )
+#define TTAG_cvt FT_MAKE_TAG( 'c', 'v', 't', ' ' )
+#define TTAG_DSIG FT_MAKE_TAG( 'D', 'S', 'I', 'G' )
+#define TTAG_EBDT FT_MAKE_TAG( 'E', 'B', 'D', 'T' )
+#define TTAG_EBLC FT_MAKE_TAG( 'E', 'B', 'L', 'C' )
+#define TTAG_EBSC FT_MAKE_TAG( 'E', 'B', 'S', 'C' )
+#define TTAG_feat FT_MAKE_TAG( 'f', 'e', 'a', 't' )
+#define TTAG_FOND FT_MAKE_TAG( 'F', 'O', 'N', 'D' )
+#define TTAG_fpgm FT_MAKE_TAG( 'f', 'p', 'g', 'm' )
+#define TTAG_fvar FT_MAKE_TAG( 'f', 'v', 'a', 'r' )
+#define TTAG_gasp FT_MAKE_TAG( 'g', 'a', 's', 'p' )
+#define TTAG_GDEF FT_MAKE_TAG( 'G', 'D', 'E', 'F' )
+#define TTAG_glyf FT_MAKE_TAG( 'g', 'l', 'y', 'f' )
+#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
+#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_gvar FT_MAKE_TAG( 'g', 'v', 'a', 'r' )
+#define TTAG_HVAR FT_MAKE_TAG( 'H', 'V', 'A', 'R' )
+#define TTAG_hdmx FT_MAKE_TAG( 'h', 'd', 'm', 'x' )
+#define TTAG_head FT_MAKE_TAG( 'h', 'e', 'a', 'd' )
+#define TTAG_hhea FT_MAKE_TAG( 'h', 'h', 'e', 'a' )
+#define TTAG_hmtx FT_MAKE_TAG( 'h', 'm', 't', 'x' )
+#define TTAG_JSTF FT_MAKE_TAG( 'J', 'S', 'T', 'F' )
+#define TTAG_just FT_MAKE_TAG( 'j', 'u', 's', 't' )
+#define TTAG_kern FT_MAKE_TAG( 'k', 'e', 'r', 'n' )
+#define TTAG_lcar FT_MAKE_TAG( 'l', 'c', 'a', 'r' )
+#define TTAG_loca FT_MAKE_TAG( 'l', 'o', 'c', 'a' )
+#define TTAG_LTSH FT_MAKE_TAG( 'L', 'T', 'S', 'H' )
+#define TTAG_LWFN FT_MAKE_TAG( 'L', 'W', 'F', 'N' )
+#define TTAG_MATH FT_MAKE_TAG( 'M', 'A', 'T', 'H' )
+#define TTAG_maxp FT_MAKE_TAG( 'm', 'a', 'x', 'p' )
+#define TTAG_META FT_MAKE_TAG( 'M', 'E', 'T', 'A' )
+#define TTAG_MMFX FT_MAKE_TAG( 'M', 'M', 'F', 'X' )
+#define TTAG_MMSD FT_MAKE_TAG( 'M', 'M', 'S', 'D' )
+#define TTAG_mort FT_MAKE_TAG( 'm', 'o', 'r', 't' )
+#define TTAG_morx FT_MAKE_TAG( 'm', 'o', 'r', 'x' )
+#define TTAG_MVAR FT_MAKE_TAG( 'M', 'V', 'A', 'R' )
+#define TTAG_name FT_MAKE_TAG( 'n', 'a', 'm', 'e' )
+#define TTAG_opbd FT_MAKE_TAG( 'o', 'p', 'b', 'd' )
+#define TTAG_OS2 FT_MAKE_TAG( 'O', 'S', '/', '2' )
+#define TTAG_OTTO FT_MAKE_TAG( 'O', 'T', 'T', 'O' )
+#define TTAG_PCLT FT_MAKE_TAG( 'P', 'C', 'L', 'T' )
+#define TTAG_POST FT_MAKE_TAG( 'P', 'O', 'S', 'T' )
+#define TTAG_post FT_MAKE_TAG( 'p', 'o', 's', 't' )
+#define TTAG_prep FT_MAKE_TAG( 'p', 'r', 'e', 'p' )
+#define TTAG_prop FT_MAKE_TAG( 'p', 'r', 'o', 'p' )
+#define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' )
+#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' )
+#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' )
+#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )
+#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' )
+#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' )
+#define TTAG_ttcf FT_MAKE_TAG( 't', 't', 'c', 'f' )
+#define TTAG_TYP1 FT_MAKE_TAG( 'T', 'Y', 'P', '1' )
+#define TTAG_typ1 FT_MAKE_TAG( 't', 'y', 'p', '1' )
+#define TTAG_VDMX FT_MAKE_TAG( 'V', 'D', 'M', 'X' )
+#define TTAG_vhea FT_MAKE_TAG( 'v', 'h', 'e', 'a' )
+#define TTAG_vmtx FT_MAKE_TAG( 'v', 'm', 't', 'x' )
+#define TTAG_VVAR FT_MAKE_TAG( 'V', 'V', 'A', 'R' )
+#define TTAG_wOFF FT_MAKE_TAG( 'w', 'O', 'F', 'F' )
+#define TTAG_wOF2 FT_MAKE_TAG( 'w', 'O', 'F', '2' )
+
+/* used by "Keyboard.dfont" on legacy Mac OS X */
+#define TTAG_0xA5kbd FT_MAKE_TAG( 0xA5, 'k', 'b', 'd' )
+
+/* used by "LastResort.dfont" on legacy Mac OS X */
+#define TTAG_0xA5lst FT_MAKE_TAG( 0xA5, 'l', 's', 't' )
+
+
+FT_END_HEADER
+
+#endif /* TTAGS_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/include/ft2build.h b/Client/ThirdParty/freetype/include/ft2build.h
new file mode 100644
index 0000000..62686b1
--- /dev/null
+++ b/Client/ThirdParty/freetype/include/ft2build.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ *
+ * ft2build.h
+ *
+ * FreeType 2 build and setup macros.
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * This is the 'entry point' for FreeType header file inclusions, to be
+ * loaded before all other header files.
+ *
+ * A typical example is
+ *
+ * ```
+ * #include <ft2build.h>
+ * #include <freetype/freetype.h>
+ * ```
+ *
+ */
+
+
+#ifndef FT2BUILD_H_
+#define FT2BUILD_H_
+
+#include <freetype/config/ftheader.h>
+
+#endif /* FT2BUILD_H_ */
+
+
+/* END */
diff --git a/Client/ThirdParty/freetype/release dll/win32/freetype.dll b/Client/ThirdParty/freetype/release dll/win32/freetype.dll
new file mode 100644
index 0000000..ff22e9c
--- /dev/null
+++ b/Client/ThirdParty/freetype/release dll/win32/freetype.dll
Binary files differ
diff --git a/Client/ThirdParty/freetype/release dll/win32/freetype.lib b/Client/ThirdParty/freetype/release dll/win32/freetype.lib
new file mode 100644
index 0000000..c51537d
--- /dev/null
+++ b/Client/ThirdParty/freetype/release dll/win32/freetype.lib
Binary files differ
diff --git a/Client/ThirdParty/freetype/release dll/win64/freetype.dll b/Client/ThirdParty/freetype/release dll/win64/freetype.dll
new file mode 100644
index 0000000..8826b70
--- /dev/null
+++ b/Client/ThirdParty/freetype/release dll/win64/freetype.dll
Binary files differ
diff --git a/Client/ThirdParty/freetype/release dll/win64/freetype.lib b/Client/ThirdParty/freetype/release dll/win64/freetype.lib
new file mode 100644
index 0000000..db5e476
--- /dev/null
+++ b/Client/ThirdParty/freetype/release dll/win64/freetype.lib
Binary files differ
diff --git a/Client/ThirdParty/freetype/release static/README.TXT b/Client/ThirdParty/freetype/release static/README.TXT
new file mode 100644
index 0000000..bd26007
--- /dev/null
+++ b/Client/ThirdParty/freetype/release static/README.TXT
@@ -0,0 +1 @@
+These static libraries will only work with visual studio 2015-2019
diff --git a/Client/ThirdParty/freetype/release static/vs2015-2019/win32/freetype.lib b/Client/ThirdParty/freetype/release static/vs2015-2019/win32/freetype.lib
new file mode 100644
index 0000000..bbfaf4c
--- /dev/null
+++ b/Client/ThirdParty/freetype/release static/vs2015-2019/win32/freetype.lib
Binary files differ
diff --git a/Client/ThirdParty/freetype/release static/vs2015-2019/win64/freetype.lib b/Client/ThirdParty/freetype/release static/vs2015-2019/win64/freetype.lib
new file mode 100644
index 0000000..cdf3193
--- /dev/null
+++ b/Client/ThirdParty/freetype/release static/vs2015-2019/win64/freetype.lib
Binary files differ
diff --git a/Client/ThirdParty/glad/glad.c b/Client/ThirdParty/glad/glad.c
new file mode 100644
index 0000000..c0703ae
--- /dev/null
+++ b/Client/ThirdParty/glad/glad.c
@@ -0,0 +1,1850 @@
+/*
+
+ OpenGL loader generated by glad 0.1.34 on Tue Nov 2 08:57:31 2021.
+
+ Language/Generator: C/C++
+ Specification: gl
+ APIs: gl=3.3
+ Profile: compatibility
+ Extensions:
+ GL_ARB_map_buffer_alignment,
+ GL_ARB_map_buffer_range
+ Loader: True
+ Local files: True
+ Omit khrplatform: False
+ Reproducible: False
+
+ Commandline:
+ --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --local-files --extensions="GL_ARB_map_buffer_alignment,GL_ARB_map_buffer_range"
+ Online:
+ https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_map_buffer_alignment&extensions=GL_ARB_map_buffer_range
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "glad.h"
+
+static void* get_proc(const char *namez);
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#ifndef _WINDOWS_
+#undef APIENTRY
+#endif
+#include <windows.h>
+static HMODULE libGL;
+
+typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*);
+static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
+
+#ifdef _MSC_VER
+#ifdef __has_include
+ #if __has_include(<winapifamily.h>)
+ #define HAVE_WINAPIFAMILY 1
+ #endif
+#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+ #define HAVE_WINAPIFAMILY 1
+#endif
+#endif
+
+#ifdef HAVE_WINAPIFAMILY
+ #include <winapifamily.h>
+ #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+ #define IS_UWP 1
+ #endif
+#endif
+
+static
+int open_gl(void) {
+#ifndef IS_UWP
+ libGL = LoadLibraryW(L"opengl32.dll");
+ if(libGL != NULL) {
+ void (* tmp)(void);
+ tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress");
+ gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp;
+ return gladGetProcAddressPtr != NULL;
+ }
+#endif
+
+ return 0;
+}
+
+static
+void close_gl(void) {
+ if(libGL != NULL) {
+ FreeLibrary((HMODULE) libGL);
+ libGL = NULL;
+ }
+}
+#else
+#include <dlfcn.h>
+static void* libGL;
+
+#if !defined(__APPLE__) && !defined(__HAIKU__)
+typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
+static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
+#endif
+
+static
+int open_gl(void) {
+#ifdef __APPLE__
+ static const char *NAMES[] = {
+ "../Frameworks/OpenGL.framework/OpenGL",
+ "/Library/Frameworks/OpenGL.framework/OpenGL",
+ "/System/Library/Frameworks/OpenGL.framework/OpenGL",
+ "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
+ };
+#else
+ static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
+#endif
+
+ unsigned int index = 0;
+ for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
+ libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
+
+ if(libGL != NULL) {
+#if defined(__APPLE__) || defined(__HAIKU__)
+ return 1;
+#else
+ gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
+ "glXGetProcAddressARB");
+ return gladGetProcAddressPtr != NULL;
+#endif
+ }
+ }
+
+ return 0;
+}
+
+static
+void close_gl(void) {
+ if(libGL != NULL) {
+ dlclose(libGL);
+ libGL = NULL;
+ }
+}
+#endif
+
+static
+void* get_proc(const char *namez) {
+ void* result = NULL;
+ if(libGL == NULL) return NULL;
+
+#if !defined(__APPLE__) && !defined(__HAIKU__)
+ if(gladGetProcAddressPtr != NULL) {
+ result = gladGetProcAddressPtr(namez);
+ }
+#endif
+ if(result == NULL) {
+#if defined(_WIN32) || defined(__CYGWIN__)
+ result = (void*)GetProcAddress((HMODULE) libGL, namez);
+#else
+ result = dlsym(libGL, namez);
+#endif
+ }
+
+ return result;
+}
+
+int gladLoadGL(void) {
+ int status = 0;
+
+ if(open_gl()) {
+ status = gladLoadGLLoader(&get_proc);
+ close_gl();
+ }
+
+ return status;
+}
+
+struct gladGLversionStruct GLVersion = { 0, 0 };
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define _GLAD_IS_SOME_NEW_VERSION 1
+#endif
+
+static int max_loaded_major;
+static int max_loaded_minor;
+
+static const char *exts = NULL;
+static int num_exts_i = 0;
+static char **exts_i = NULL;
+
+static int get_exts(void) {
+#ifdef _GLAD_IS_SOME_NEW_VERSION
+ if(max_loaded_major < 3) {
+#endif
+ exts = (const char *)glGetString(GL_EXTENSIONS);
+#ifdef _GLAD_IS_SOME_NEW_VERSION
+ } else {
+ unsigned int index;
+
+ num_exts_i = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
+ if (num_exts_i > 0) {
+ exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i));
+ }
+
+ if (exts_i == NULL) {
+ return 0;
+ }
+
+ for(index = 0; index < (unsigned)num_exts_i; index++) {
+ const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index);
+ size_t len = strlen(gl_str_tmp);
+
+ char *local_str = (char*)malloc((len+1) * sizeof(char));
+ if(local_str != NULL) {
+ memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char));
+ }
+ exts_i[index] = local_str;
+ }
+ }
+#endif
+ return 1;
+}
+
+static void free_exts(void) {
+ if (exts_i != NULL) {
+ int index;
+ for(index = 0; index < num_exts_i; index++) {
+ free((char *)exts_i[index]);
+ }
+ free((void *)exts_i);
+ exts_i = NULL;
+ }
+}
+
+static int has_ext(const char *ext) {
+#ifdef _GLAD_IS_SOME_NEW_VERSION
+ if(max_loaded_major < 3) {
+#endif
+ const char *extensions;
+ const char *loc;
+ const char *terminator;
+ extensions = exts;
+ if(extensions == NULL || ext == NULL) {
+ return 0;
+ }
+
+ while(1) {
+ loc = strstr(extensions, ext);
+ if(loc == NULL) {
+ return 0;
+ }
+
+ terminator = loc + strlen(ext);
+ if((loc == extensions || *(loc - 1) == ' ') &&
+ (*terminator == ' ' || *terminator == '\0')) {
+ return 1;
+ }
+ extensions = terminator;
+ }
+#ifdef _GLAD_IS_SOME_NEW_VERSION
+ } else {
+ int index;
+ if(exts_i == NULL) return 0;
+ for(index = 0; index < num_exts_i; index++) {
+ const char *e = exts_i[index];
+
+ if(exts_i[index] != NULL && strcmp(e, ext) == 0) {
+ return 1;
+ }
+ }
+ }
+#endif
+
+ return 0;
+}
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+PFNGLACCUMPROC glad_glAccum = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
+PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
+PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINPROC glad_glBegin = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBITMAPPROC glad_glBitmap = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCALLLISTPROC glad_glCallList = NULL;
+PFNGLCALLLISTSPROC glad_glCallLists = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
+PFNGLCOLOR3BPROC glad_glColor3b = NULL;
+PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
+PFNGLCOLOR3DPROC glad_glColor3d = NULL;
+PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
+PFNGLCOLOR3FPROC glad_glColor3f = NULL;
+PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
+PFNGLCOLOR3IPROC glad_glColor3i = NULL;
+PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
+PFNGLCOLOR3SPROC glad_glColor3s = NULL;
+PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
+PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
+PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
+PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
+PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
+PFNGLCOLOR3USPROC glad_glColor3us = NULL;
+PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
+PFNGLCOLOR4BPROC glad_glColor4b = NULL;
+PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
+PFNGLCOLOR4DPROC glad_glColor4d = NULL;
+PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
+PFNGLCOLOR4FPROC glad_glColor4f = NULL;
+PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
+PFNGLCOLOR4IPROC glad_glColor4i = NULL;
+PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
+PFNGLCOLOR4SPROC glad_glColor4s = NULL;
+PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
+PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
+PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
+PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
+PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
+PFNGLCOLOR4USPROC glad_glColor4us = NULL;
+PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
+PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
+PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
+PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
+PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
+PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
+PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
+PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDPROC glad_glEnd = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDLISTPROC glad_glEndList = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
+PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
+PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
+PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
+PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
+PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
+PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
+PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
+PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
+PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
+PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
+PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
+PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
+PFNGLFOGFPROC glad_glFogf = NULL;
+PFNGLFOGFVPROC glad_glFogfv = NULL;
+PFNGLFOGIPROC glad_glFogi = NULL;
+PFNGLFOGIVPROC glad_glFogiv = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLFRUSTUMPROC glad_glFrustum = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENLISTSPROC glad_glGenLists = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
+PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
+PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
+PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
+PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
+PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
+PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
+PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
+PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
+PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
+PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
+PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
+PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
+PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
+PFNGLINDEXDPROC glad_glIndexd = NULL;
+PFNGLINDEXDVPROC glad_glIndexdv = NULL;
+PFNGLINDEXFPROC glad_glIndexf = NULL;
+PFNGLINDEXFVPROC glad_glIndexfv = NULL;
+PFNGLINDEXIPROC glad_glIndexi = NULL;
+PFNGLINDEXIVPROC glad_glIndexiv = NULL;
+PFNGLINDEXSPROC glad_glIndexs = NULL;
+PFNGLINDEXSVPROC glad_glIndexsv = NULL;
+PFNGLINDEXUBPROC glad_glIndexub = NULL;
+PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
+PFNGLINITNAMESPROC glad_glInitNames = NULL;
+PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISLISTPROC glad_glIsList = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
+PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
+PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
+PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
+PFNGLLIGHTFPROC glad_glLightf = NULL;
+PFNGLLIGHTFVPROC glad_glLightfv = NULL;
+PFNGLLIGHTIPROC glad_glLighti = NULL;
+PFNGLLIGHTIVPROC glad_glLightiv = NULL;
+PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLISTBASEPROC glad_glListBase = NULL;
+PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
+PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
+PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
+PFNGLLOADNAMEPROC glad_glLoadName = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAP1DPROC glad_glMap1d = NULL;
+PFNGLMAP1FPROC glad_glMap1f = NULL;
+PFNGLMAP2DPROC glad_glMap2d = NULL;
+PFNGLMAP2FPROC glad_glMap2f = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
+PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
+PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
+PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
+PFNGLMATERIALFPROC glad_glMaterialf = NULL;
+PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
+PFNGLMATERIALIPROC glad_glMateriali = NULL;
+PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
+PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
+PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
+PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
+PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
+PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
+PFNGLNEWLISTPROC glad_glNewList = NULL;
+PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
+PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
+PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
+PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
+PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
+PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
+PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
+PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
+PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
+PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
+PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
+PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
+PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
+PFNGLORTHOPROC glad_glOrtho = NULL;
+PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
+PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
+PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
+PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
+PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
+PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
+PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
+PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
+PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
+PFNGLPOPNAMEPROC glad_glPopName = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
+PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
+PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
+PFNGLPUSHNAMEPROC glad_glPushName = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
+PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
+PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
+PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
+PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
+PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
+PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
+PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
+PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
+PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
+PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
+PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
+PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
+PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
+PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
+PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
+PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
+PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
+PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
+PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
+PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
+PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
+PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
+PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLRECTDPROC glad_glRectd = NULL;
+PFNGLRECTDVPROC glad_glRectdv = NULL;
+PFNGLRECTFPROC glad_glRectf = NULL;
+PFNGLRECTFVPROC glad_glRectfv = NULL;
+PFNGLRECTIPROC glad_glRecti = NULL;
+PFNGLRECTIVPROC glad_glRectiv = NULL;
+PFNGLRECTSPROC glad_glRects = NULL;
+PFNGLRECTSVPROC glad_glRectsv = NULL;
+PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLROTATEDPROC glad_glRotated = NULL;
+PFNGLROTATEFPROC glad_glRotatef = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCALEDPROC glad_glScaled = NULL;
+PFNGLSCALEFPROC glad_glScalef = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
+PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
+PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
+PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
+PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
+PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
+PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
+PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
+PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
+PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
+PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
+PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
+PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
+PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
+PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
+PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
+PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
+PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
+PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
+PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
+PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
+PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
+PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
+PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
+PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
+PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
+PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
+PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
+PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
+PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
+PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
+PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
+PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
+PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
+PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
+PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
+PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
+PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
+PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
+PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
+PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
+PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
+PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
+PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
+PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
+PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
+PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
+PFNGLTEXGENDPROC glad_glTexGend = NULL;
+PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
+PFNGLTEXGENFPROC glad_glTexGenf = NULL;
+PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
+PFNGLTEXGENIPROC glad_glTexGeni = NULL;
+PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
+PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
+PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
+PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
+PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
+PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
+PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
+PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
+PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
+PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
+PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
+PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
+PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
+PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
+PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
+PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
+PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
+PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
+PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
+PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
+PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
+PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
+PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
+PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
+PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
+PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
+PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
+PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
+PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
+PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
+PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
+int GLAD_GL_ARB_map_buffer_alignment = 0;
+int GLAD_GL_ARB_map_buffer_range = 0;
+static void load_GL_VERSION_1_0(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_1_0) return;
+ glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
+ glad_glFrontFace = (PFNGLFRONTFACEPROC)load("glFrontFace");
+ glad_glHint = (PFNGLHINTPROC)load("glHint");
+ glad_glLineWidth = (PFNGLLINEWIDTHPROC)load("glLineWidth");
+ glad_glPointSize = (PFNGLPOINTSIZEPROC)load("glPointSize");
+ glad_glPolygonMode = (PFNGLPOLYGONMODEPROC)load("glPolygonMode");
+ glad_glScissor = (PFNGLSCISSORPROC)load("glScissor");
+ glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC)load("glTexParameterf");
+ glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)load("glTexParameterfv");
+ glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC)load("glTexParameteri");
+ glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)load("glTexParameteriv");
+ glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC)load("glTexImage1D");
+ glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC)load("glTexImage2D");
+ glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC)load("glDrawBuffer");
+ glad_glClear = (PFNGLCLEARPROC)load("glClear");
+ glad_glClearColor = (PFNGLCLEARCOLORPROC)load("glClearColor");
+ glad_glClearStencil = (PFNGLCLEARSTENCILPROC)load("glClearStencil");
+ glad_glClearDepth = (PFNGLCLEARDEPTHPROC)load("glClearDepth");
+ glad_glStencilMask = (PFNGLSTENCILMASKPROC)load("glStencilMask");
+ glad_glColorMask = (PFNGLCOLORMASKPROC)load("glColorMask");
+ glad_glDepthMask = (PFNGLDEPTHMASKPROC)load("glDepthMask");
+ glad_glDisable = (PFNGLDISABLEPROC)load("glDisable");
+ glad_glEnable = (PFNGLENABLEPROC)load("glEnable");
+ glad_glFinish = (PFNGLFINISHPROC)load("glFinish");
+ glad_glFlush = (PFNGLFLUSHPROC)load("glFlush");
+ glad_glBlendFunc = (PFNGLBLENDFUNCPROC)load("glBlendFunc");
+ glad_glLogicOp = (PFNGLLOGICOPPROC)load("glLogicOp");
+ glad_glStencilFunc = (PFNGLSTENCILFUNCPROC)load("glStencilFunc");
+ glad_glStencilOp = (PFNGLSTENCILOPPROC)load("glStencilOp");
+ glad_glDepthFunc = (PFNGLDEPTHFUNCPROC)load("glDepthFunc");
+ glad_glPixelStoref = (PFNGLPIXELSTOREFPROC)load("glPixelStoref");
+ glad_glPixelStorei = (PFNGLPIXELSTOREIPROC)load("glPixelStorei");
+ glad_glReadBuffer = (PFNGLREADBUFFERPROC)load("glReadBuffer");
+ glad_glReadPixels = (PFNGLREADPIXELSPROC)load("glReadPixels");
+ glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC)load("glGetBooleanv");
+ glad_glGetDoublev = (PFNGLGETDOUBLEVPROC)load("glGetDoublev");
+ glad_glGetError = (PFNGLGETERRORPROC)load("glGetError");
+ glad_glGetFloatv = (PFNGLGETFLOATVPROC)load("glGetFloatv");
+ glad_glGetIntegerv = (PFNGLGETINTEGERVPROC)load("glGetIntegerv");
+ glad_glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
+ glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC)load("glGetTexImage");
+ glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)load("glGetTexParameterfv");
+ glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)load("glGetTexParameteriv");
+ glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC)load("glGetTexLevelParameterfv");
+ glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC)load("glGetTexLevelParameteriv");
+ glad_glIsEnabled = (PFNGLISENABLEDPROC)load("glIsEnabled");
+ glad_glDepthRange = (PFNGLDEPTHRANGEPROC)load("glDepthRange");
+ glad_glViewport = (PFNGLVIEWPORTPROC)load("glViewport");
+ glad_glNewList = (PFNGLNEWLISTPROC)load("glNewList");
+ glad_glEndList = (PFNGLENDLISTPROC)load("glEndList");
+ glad_glCallList = (PFNGLCALLLISTPROC)load("glCallList");
+ glad_glCallLists = (PFNGLCALLLISTSPROC)load("glCallLists");
+ glad_glDeleteLists = (PFNGLDELETELISTSPROC)load("glDeleteLists");
+ glad_glGenLists = (PFNGLGENLISTSPROC)load("glGenLists");
+ glad_glListBase = (PFNGLLISTBASEPROC)load("glListBase");
+ glad_glBegin = (PFNGLBEGINPROC)load("glBegin");
+ glad_glBitmap = (PFNGLBITMAPPROC)load("glBitmap");
+ glad_glColor3b = (PFNGLCOLOR3BPROC)load("glColor3b");
+ glad_glColor3bv = (PFNGLCOLOR3BVPROC)load("glColor3bv");
+ glad_glColor3d = (PFNGLCOLOR3DPROC)load("glColor3d");
+ glad_glColor3dv = (PFNGLCOLOR3DVPROC)load("glColor3dv");
+ glad_glColor3f = (PFNGLCOLOR3FPROC)load("glColor3f");
+ glad_glColor3fv = (PFNGLCOLOR3FVPROC)load("glColor3fv");
+ glad_glColor3i = (PFNGLCOLOR3IPROC)load("glColor3i");
+ glad_glColor3iv = (PFNGLCOLOR3IVPROC)load("glColor3iv");
+ glad_glColor3s = (PFNGLCOLOR3SPROC)load("glColor3s");
+ glad_glColor3sv = (PFNGLCOLOR3SVPROC)load("glColor3sv");
+ glad_glColor3ub = (PFNGLCOLOR3UBPROC)load("glColor3ub");
+ glad_glColor3ubv = (PFNGLCOLOR3UBVPROC)load("glColor3ubv");
+ glad_glColor3ui = (PFNGLCOLOR3UIPROC)load("glColor3ui");
+ glad_glColor3uiv = (PFNGLCOLOR3UIVPROC)load("glColor3uiv");
+ glad_glColor3us = (PFNGLCOLOR3USPROC)load("glColor3us");
+ glad_glColor3usv = (PFNGLCOLOR3USVPROC)load("glColor3usv");
+ glad_glColor4b = (PFNGLCOLOR4BPROC)load("glColor4b");
+ glad_glColor4bv = (PFNGLCOLOR4BVPROC)load("glColor4bv");
+ glad_glColor4d = (PFNGLCOLOR4DPROC)load("glColor4d");
+ glad_glColor4dv = (PFNGLCOLOR4DVPROC)load("glColor4dv");
+ glad_glColor4f = (PFNGLCOLOR4FPROC)load("glColor4f");
+ glad_glColor4fv = (PFNGLCOLOR4FVPROC)load("glColor4fv");
+ glad_glColor4i = (PFNGLCOLOR4IPROC)load("glColor4i");
+ glad_glColor4iv = (PFNGLCOLOR4IVPROC)load("glColor4iv");
+ glad_glColor4s = (PFNGLCOLOR4SPROC)load("glColor4s");
+ glad_glColor4sv = (PFNGLCOLOR4SVPROC)load("glColor4sv");
+ glad_glColor4ub = (PFNGLCOLOR4UBPROC)load("glColor4ub");
+ glad_glColor4ubv = (PFNGLCOLOR4UBVPROC)load("glColor4ubv");
+ glad_glColor4ui = (PFNGLCOLOR4UIPROC)load("glColor4ui");
+ glad_glColor4uiv = (PFNGLCOLOR4UIVPROC)load("glColor4uiv");
+ glad_glColor4us = (PFNGLCOLOR4USPROC)load("glColor4us");
+ glad_glColor4usv = (PFNGLCOLOR4USVPROC)load("glColor4usv");
+ glad_glEdgeFlag = (PFNGLEDGEFLAGPROC)load("glEdgeFlag");
+ glad_glEdgeFlagv = (PFNGLEDGEFLAGVPROC)load("glEdgeFlagv");
+ glad_glEnd = (PFNGLENDPROC)load("glEnd");
+ glad_glIndexd = (PFNGLINDEXDPROC)load("glIndexd");
+ glad_glIndexdv = (PFNGLINDEXDVPROC)load("glIndexdv");
+ glad_glIndexf = (PFNGLINDEXFPROC)load("glIndexf");
+ glad_glIndexfv = (PFNGLINDEXFVPROC)load("glIndexfv");
+ glad_glIndexi = (PFNGLINDEXIPROC)load("glIndexi");
+ glad_glIndexiv = (PFNGLINDEXIVPROC)load("glIndexiv");
+ glad_glIndexs = (PFNGLINDEXSPROC)load("glIndexs");
+ glad_glIndexsv = (PFNGLINDEXSVPROC)load("glIndexsv");
+ glad_glNormal3b = (PFNGLNORMAL3BPROC)load("glNormal3b");
+ glad_glNormal3bv = (PFNGLNORMAL3BVPROC)load("glNormal3bv");
+ glad_glNormal3d = (PFNGLNORMAL3DPROC)load("glNormal3d");
+ glad_glNormal3dv = (PFNGLNORMAL3DVPROC)load("glNormal3dv");
+ glad_glNormal3f = (PFNGLNORMAL3FPROC)load("glNormal3f");
+ glad_glNormal3fv = (PFNGLNORMAL3FVPROC)load("glNormal3fv");
+ glad_glNormal3i = (PFNGLNORMAL3IPROC)load("glNormal3i");
+ glad_glNormal3iv = (PFNGLNORMAL3IVPROC)load("glNormal3iv");
+ glad_glNormal3s = (PFNGLNORMAL3SPROC)load("glNormal3s");
+ glad_glNormal3sv = (PFNGLNORMAL3SVPROC)load("glNormal3sv");
+ glad_glRasterPos2d = (PFNGLRASTERPOS2DPROC)load("glRasterPos2d");
+ glad_glRasterPos2dv = (PFNGLRASTERPOS2DVPROC)load("glRasterPos2dv");
+ glad_glRasterPos2f = (PFNGLRASTERPOS2FPROC)load("glRasterPos2f");
+ glad_glRasterPos2fv = (PFNGLRASTERPOS2FVPROC)load("glRasterPos2fv");
+ glad_glRasterPos2i = (PFNGLRASTERPOS2IPROC)load("glRasterPos2i");
+ glad_glRasterPos2iv = (PFNGLRASTERPOS2IVPROC)load("glRasterPos2iv");
+ glad_glRasterPos2s = (PFNGLRASTERPOS2SPROC)load("glRasterPos2s");
+ glad_glRasterPos2sv = (PFNGLRASTERPOS2SVPROC)load("glRasterPos2sv");
+ glad_glRasterPos3d = (PFNGLRASTERPOS3DPROC)load("glRasterPos3d");
+ glad_glRasterPos3dv = (PFNGLRASTERPOS3DVPROC)load("glRasterPos3dv");
+ glad_glRasterPos3f = (PFNGLRASTERPOS3FPROC)load("glRasterPos3f");
+ glad_glRasterPos3fv = (PFNGLRASTERPOS3FVPROC)load("glRasterPos3fv");
+ glad_glRasterPos3i = (PFNGLRASTERPOS3IPROC)load("glRasterPos3i");
+ glad_glRasterPos3iv = (PFNGLRASTERPOS3IVPROC)load("glRasterPos3iv");
+ glad_glRasterPos3s = (PFNGLRASTERPOS3SPROC)load("glRasterPos3s");
+ glad_glRasterPos3sv = (PFNGLRASTERPOS3SVPROC)load("glRasterPos3sv");
+ glad_glRasterPos4d = (PFNGLRASTERPOS4DPROC)load("glRasterPos4d");
+ glad_glRasterPos4dv = (PFNGLRASTERPOS4DVPROC)load("glRasterPos4dv");
+ glad_glRasterPos4f = (PFNGLRASTERPOS4FPROC)load("glRasterPos4f");
+ glad_glRasterPos4fv = (PFNGLRASTERPOS4FVPROC)load("glRasterPos4fv");
+ glad_glRasterPos4i = (PFNGLRASTERPOS4IPROC)load("glRasterPos4i");
+ glad_glRasterPos4iv = (PFNGLRASTERPOS4IVPROC)load("glRasterPos4iv");
+ glad_glRasterPos4s = (PFNGLRASTERPOS4SPROC)load("glRasterPos4s");
+ glad_glRasterPos4sv = (PFNGLRASTERPOS4SVPROC)load("glRasterPos4sv");
+ glad_glRectd = (PFNGLRECTDPROC)load("glRectd");
+ glad_glRectdv = (PFNGLRECTDVPROC)load("glRectdv");
+ glad_glRectf = (PFNGLRECTFPROC)load("glRectf");
+ glad_glRectfv = (PFNGLRECTFVPROC)load("glRectfv");
+ glad_glRecti = (PFNGLRECTIPROC)load("glRecti");
+ glad_glRectiv = (PFNGLRECTIVPROC)load("glRectiv");
+ glad_glRects = (PFNGLRECTSPROC)load("glRects");
+ glad_glRectsv = (PFNGLRECTSVPROC)load("glRectsv");
+ glad_glTexCoord1d = (PFNGLTEXCOORD1DPROC)load("glTexCoord1d");
+ glad_glTexCoord1dv = (PFNGLTEXCOORD1DVPROC)load("glTexCoord1dv");
+ glad_glTexCoord1f = (PFNGLTEXCOORD1FPROC)load("glTexCoord1f");
+ glad_glTexCoord1fv = (PFNGLTEXCOORD1FVPROC)load("glTexCoord1fv");
+ glad_glTexCoord1i = (PFNGLTEXCOORD1IPROC)load("glTexCoord1i");
+ glad_glTexCoord1iv = (PFNGLTEXCOORD1IVPROC)load("glTexCoord1iv");
+ glad_glTexCoord1s = (PFNGLTEXCOORD1SPROC)load("glTexCoord1s");
+ glad_glTexCoord1sv = (PFNGLTEXCOORD1SVPROC)load("glTexCoord1sv");
+ glad_glTexCoord2d = (PFNGLTEXCOORD2DPROC)load("glTexCoord2d");
+ glad_glTexCoord2dv = (PFNGLTEXCOORD2DVPROC)load("glTexCoord2dv");
+ glad_glTexCoord2f = (PFNGLTEXCOORD2FPROC)load("glTexCoord2f");
+ glad_glTexCoord2fv = (PFNGLTEXCOORD2FVPROC)load("glTexCoord2fv");
+ glad_glTexCoord2i = (PFNGLTEXCOORD2IPROC)load("glTexCoord2i");
+ glad_glTexCoord2iv = (PFNGLTEXCOORD2IVPROC)load("glTexCoord2iv");
+ glad_glTexCoord2s = (PFNGLTEXCOORD2SPROC)load("glTexCoord2s");
+ glad_glTexCoord2sv = (PFNGLTEXCOORD2SVPROC)load("glTexCoord2sv");
+ glad_glTexCoord3d = (PFNGLTEXCOORD3DPROC)load("glTexCoord3d");
+ glad_glTexCoord3dv = (PFNGLTEXCOORD3DVPROC)load("glTexCoord3dv");
+ glad_glTexCoord3f = (PFNGLTEXCOORD3FPROC)load("glTexCoord3f");
+ glad_glTexCoord3fv = (PFNGLTEXCOORD3FVPROC)load("glTexCoord3fv");
+ glad_glTexCoord3i = (PFNGLTEXCOORD3IPROC)load("glTexCoord3i");
+ glad_glTexCoord3iv = (PFNGLTEXCOORD3IVPROC)load("glTexCoord3iv");
+ glad_glTexCoord3s = (PFNGLTEXCOORD3SPROC)load("glTexCoord3s");
+ glad_glTexCoord3sv = (PFNGLTEXCOORD3SVPROC)load("glTexCoord3sv");
+ glad_glTexCoord4d = (PFNGLTEXCOORD4DPROC)load("glTexCoord4d");
+ glad_glTexCoord4dv = (PFNGLTEXCOORD4DVPROC)load("glTexCoord4dv");
+ glad_glTexCoord4f = (PFNGLTEXCOORD4FPROC)load("glTexCoord4f");
+ glad_glTexCoord4fv = (PFNGLTEXCOORD4FVPROC)load("glTexCoord4fv");
+ glad_glTexCoord4i = (PFNGLTEXCOORD4IPROC)load("glTexCoord4i");
+ glad_glTexCoord4iv = (PFNGLTEXCOORD4IVPROC)load("glTexCoord4iv");
+ glad_glTexCoord4s = (PFNGLTEXCOORD4SPROC)load("glTexCoord4s");
+ glad_glTexCoord4sv = (PFNGLTEXCOORD4SVPROC)load("glTexCoord4sv");
+ glad_glVertex2d = (PFNGLVERTEX2DPROC)load("glVertex2d");
+ glad_glVertex2dv = (PFNGLVERTEX2DVPROC)load("glVertex2dv");
+ glad_glVertex2f = (PFNGLVERTEX2FPROC)load("glVertex2f");
+ glad_glVertex2fv = (PFNGLVERTEX2FVPROC)load("glVertex2fv");
+ glad_glVertex2i = (PFNGLVERTEX2IPROC)load("glVertex2i");
+ glad_glVertex2iv = (PFNGLVERTEX2IVPROC)load("glVertex2iv");
+ glad_glVertex2s = (PFNGLVERTEX2SPROC)load("glVertex2s");
+ glad_glVertex2sv = (PFNGLVERTEX2SVPROC)load("glVertex2sv");
+ glad_glVertex3d = (PFNGLVERTEX3DPROC)load("glVertex3d");
+ glad_glVertex3dv = (PFNGLVERTEX3DVPROC)load("glVertex3dv");
+ glad_glVertex3f = (PFNGLVERTEX3FPROC)load("glVertex3f");
+ glad_glVertex3fv = (PFNGLVERTEX3FVPROC)load("glVertex3fv");
+ glad_glVertex3i = (PFNGLVERTEX3IPROC)load("glVertex3i");
+ glad_glVertex3iv = (PFNGLVERTEX3IVPROC)load("glVertex3iv");
+ glad_glVertex3s = (PFNGLVERTEX3SPROC)load("glVertex3s");
+ glad_glVertex3sv = (PFNGLVERTEX3SVPROC)load("glVertex3sv");
+ glad_glVertex4d = (PFNGLVERTEX4DPROC)load("glVertex4d");
+ glad_glVertex4dv = (PFNGLVERTEX4DVPROC)load("glVertex4dv");
+ glad_glVertex4f = (PFNGLVERTEX4FPROC)load("glVertex4f");
+ glad_glVertex4fv = (PFNGLVERTEX4FVPROC)load("glVertex4fv");
+ glad_glVertex4i = (PFNGLVERTEX4IPROC)load("glVertex4i");
+ glad_glVertex4iv = (PFNGLVERTEX4IVPROC)load("glVertex4iv");
+ glad_glVertex4s = (PFNGLVERTEX4SPROC)load("glVertex4s");
+ glad_glVertex4sv = (PFNGLVERTEX4SVPROC)load("glVertex4sv");
+ glad_glClipPlane = (PFNGLCLIPPLANEPROC)load("glClipPlane");
+ glad_glColorMaterial = (PFNGLCOLORMATERIALPROC)load("glColorMaterial");
+ glad_glFogf = (PFNGLFOGFPROC)load("glFogf");
+ glad_glFogfv = (PFNGLFOGFVPROC)load("glFogfv");
+ glad_glFogi = (PFNGLFOGIPROC)load("glFogi");
+ glad_glFogiv = (PFNGLFOGIVPROC)load("glFogiv");
+ glad_glLightf = (PFNGLLIGHTFPROC)load("glLightf");
+ glad_glLightfv = (PFNGLLIGHTFVPROC)load("glLightfv");
+ glad_glLighti = (PFNGLLIGHTIPROC)load("glLighti");
+ glad_glLightiv = (PFNGLLIGHTIVPROC)load("glLightiv");
+ glad_glLightModelf = (PFNGLLIGHTMODELFPROC)load("glLightModelf");
+ glad_glLightModelfv = (PFNGLLIGHTMODELFVPROC)load("glLightModelfv");
+ glad_glLightModeli = (PFNGLLIGHTMODELIPROC)load("glLightModeli");
+ glad_glLightModeliv = (PFNGLLIGHTMODELIVPROC)load("glLightModeliv");
+ glad_glLineStipple = (PFNGLLINESTIPPLEPROC)load("glLineStipple");
+ glad_glMaterialf = (PFNGLMATERIALFPROC)load("glMaterialf");
+ glad_glMaterialfv = (PFNGLMATERIALFVPROC)load("glMaterialfv");
+ glad_glMateriali = (PFNGLMATERIALIPROC)load("glMateriali");
+ glad_glMaterialiv = (PFNGLMATERIALIVPROC)load("glMaterialiv");
+ glad_glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC)load("glPolygonStipple");
+ glad_glShadeModel = (PFNGLSHADEMODELPROC)load("glShadeModel");
+ glad_glTexEnvf = (PFNGLTEXENVFPROC)load("glTexEnvf");
+ glad_glTexEnvfv = (PFNGLTEXENVFVPROC)load("glTexEnvfv");
+ glad_glTexEnvi = (PFNGLTEXENVIPROC)load("glTexEnvi");
+ glad_glTexEnviv = (PFNGLTEXENVIVPROC)load("glTexEnviv");
+ glad_glTexGend = (PFNGLTEXGENDPROC)load("glTexGend");
+ glad_glTexGendv = (PFNGLTEXGENDVPROC)load("glTexGendv");
+ glad_glTexGenf = (PFNGLTEXGENFPROC)load("glTexGenf");
+ glad_glTexGenfv = (PFNGLTEXGENFVPROC)load("glTexGenfv");
+ glad_glTexGeni = (PFNGLTEXGENIPROC)load("glTexGeni");
+ glad_glTexGeniv = (PFNGLTEXGENIVPROC)load("glTexGeniv");
+ glad_glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC)load("glFeedbackBuffer");
+ glad_glSelectBuffer = (PFNGLSELECTBUFFERPROC)load("glSelectBuffer");
+ glad_glRenderMode = (PFNGLRENDERMODEPROC)load("glRenderMode");
+ glad_glInitNames = (PFNGLINITNAMESPROC)load("glInitNames");
+ glad_glLoadName = (PFNGLLOADNAMEPROC)load("glLoadName");
+ glad_glPassThrough = (PFNGLPASSTHROUGHPROC)load("glPassThrough");
+ glad_glPopName = (PFNGLPOPNAMEPROC)load("glPopName");
+ glad_glPushName = (PFNGLPUSHNAMEPROC)load("glPushName");
+ glad_glClearAccum = (PFNGLCLEARACCUMPROC)load("glClearAccum");
+ glad_glClearIndex = (PFNGLCLEARINDEXPROC)load("glClearIndex");
+ glad_glIndexMask = (PFNGLINDEXMASKPROC)load("glIndexMask");
+ glad_glAccum = (PFNGLACCUMPROC)load("glAccum");
+ glad_glPopAttrib = (PFNGLPOPATTRIBPROC)load("glPopAttrib");
+ glad_glPushAttrib = (PFNGLPUSHATTRIBPROC)load("glPushAttrib");
+ glad_glMap1d = (PFNGLMAP1DPROC)load("glMap1d");
+ glad_glMap1f = (PFNGLMAP1FPROC)load("glMap1f");
+ glad_glMap2d = (PFNGLMAP2DPROC)load("glMap2d");
+ glad_glMap2f = (PFNGLMAP2FPROC)load("glMap2f");
+ glad_glMapGrid1d = (PFNGLMAPGRID1DPROC)load("glMapGrid1d");
+ glad_glMapGrid1f = (PFNGLMAPGRID1FPROC)load("glMapGrid1f");
+ glad_glMapGrid2d = (PFNGLMAPGRID2DPROC)load("glMapGrid2d");
+ glad_glMapGrid2f = (PFNGLMAPGRID2FPROC)load("glMapGrid2f");
+ glad_glEvalCoord1d = (PFNGLEVALCOORD1DPROC)load("glEvalCoord1d");
+ glad_glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC)load("glEvalCoord1dv");
+ glad_glEvalCoord1f = (PFNGLEVALCOORD1FPROC)load("glEvalCoord1f");
+ glad_glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC)load("glEvalCoord1fv");
+ glad_glEvalCoord2d = (PFNGLEVALCOORD2DPROC)load("glEvalCoord2d");
+ glad_glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC)load("glEvalCoord2dv");
+ glad_glEvalCoord2f = (PFNGLEVALCOORD2FPROC)load("glEvalCoord2f");
+ glad_glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC)load("glEvalCoord2fv");
+ glad_glEvalMesh1 = (PFNGLEVALMESH1PROC)load("glEvalMesh1");
+ glad_glEvalPoint1 = (PFNGLEVALPOINT1PROC)load("glEvalPoint1");
+ glad_glEvalMesh2 = (PFNGLEVALMESH2PROC)load("glEvalMesh2");
+ glad_glEvalPoint2 = (PFNGLEVALPOINT2PROC)load("glEvalPoint2");
+ glad_glAlphaFunc = (PFNGLALPHAFUNCPROC)load("glAlphaFunc");
+ glad_glPixelZoom = (PFNGLPIXELZOOMPROC)load("glPixelZoom");
+ glad_glPixelTransferf = (PFNGLPIXELTRANSFERFPROC)load("glPixelTransferf");
+ glad_glPixelTransferi = (PFNGLPIXELTRANSFERIPROC)load("glPixelTransferi");
+ glad_glPixelMapfv = (PFNGLPIXELMAPFVPROC)load("glPixelMapfv");
+ glad_glPixelMapuiv = (PFNGLPIXELMAPUIVPROC)load("glPixelMapuiv");
+ glad_glPixelMapusv = (PFNGLPIXELMAPUSVPROC)load("glPixelMapusv");
+ glad_glCopyPixels = (PFNGLCOPYPIXELSPROC)load("glCopyPixels");
+ glad_glDrawPixels = (PFNGLDRAWPIXELSPROC)load("glDrawPixels");
+ glad_glGetClipPlane = (PFNGLGETCLIPPLANEPROC)load("glGetClipPlane");
+ glad_glGetLightfv = (PFNGLGETLIGHTFVPROC)load("glGetLightfv");
+ glad_glGetLightiv = (PFNGLGETLIGHTIVPROC)load("glGetLightiv");
+ glad_glGetMapdv = (PFNGLGETMAPDVPROC)load("glGetMapdv");
+ glad_glGetMapfv = (PFNGLGETMAPFVPROC)load("glGetMapfv");
+ glad_glGetMapiv = (PFNGLGETMAPIVPROC)load("glGetMapiv");
+ glad_glGetMaterialfv = (PFNGLGETMATERIALFVPROC)load("glGetMaterialfv");
+ glad_glGetMaterialiv = (PFNGLGETMATERIALIVPROC)load("glGetMaterialiv");
+ glad_glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC)load("glGetPixelMapfv");
+ glad_glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC)load("glGetPixelMapuiv");
+ glad_glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC)load("glGetPixelMapusv");
+ glad_glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC)load("glGetPolygonStipple");
+ glad_glGetTexEnvfv = (PFNGLGETTEXENVFVPROC)load("glGetTexEnvfv");
+ glad_glGetTexEnviv = (PFNGLGETTEXENVIVPROC)load("glGetTexEnviv");
+ glad_glGetTexGendv = (PFNGLGETTEXGENDVPROC)load("glGetTexGendv");
+ glad_glGetTexGenfv = (PFNGLGETTEXGENFVPROC)load("glGetTexGenfv");
+ glad_glGetTexGeniv = (PFNGLGETTEXGENIVPROC)load("glGetTexGeniv");
+ glad_glIsList = (PFNGLISLISTPROC)load("glIsList");
+ glad_glFrustum = (PFNGLFRUSTUMPROC)load("glFrustum");
+ glad_glLoadIdentity = (PFNGLLOADIDENTITYPROC)load("glLoadIdentity");
+ glad_glLoadMatrixf = (PFNGLLOADMATRIXFPROC)load("glLoadMatrixf");
+ glad_glLoadMatrixd = (PFNGLLOADMATRIXDPROC)load("glLoadMatrixd");
+ glad_glMatrixMode = (PFNGLMATRIXMODEPROC)load("glMatrixMode");
+ glad_glMultMatrixf = (PFNGLMULTMATRIXFPROC)load("glMultMatrixf");
+ glad_glMultMatrixd = (PFNGLMULTMATRIXDPROC)load("glMultMatrixd");
+ glad_glOrtho = (PFNGLORTHOPROC)load("glOrtho");
+ glad_glPopMatrix = (PFNGLPOPMATRIXPROC)load("glPopMatrix");
+ glad_glPushMatrix = (PFNGLPUSHMATRIXPROC)load("glPushMatrix");
+ glad_glRotated = (PFNGLROTATEDPROC)load("glRotated");
+ glad_glRotatef = (PFNGLROTATEFPROC)load("glRotatef");
+ glad_glScaled = (PFNGLSCALEDPROC)load("glScaled");
+ glad_glScalef = (PFNGLSCALEFPROC)load("glScalef");
+ glad_glTranslated = (PFNGLTRANSLATEDPROC)load("glTranslated");
+ glad_glTranslatef = (PFNGLTRANSLATEFPROC)load("glTranslatef");
+}
+static void load_GL_VERSION_1_1(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_1_1) return;
+ glad_glDrawArrays = (PFNGLDRAWARRAYSPROC)load("glDrawArrays");
+ glad_glDrawElements = (PFNGLDRAWELEMENTSPROC)load("glDrawElements");
+ glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
+ glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC)load("glPolygonOffset");
+ glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC)load("glCopyTexImage1D");
+ glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)load("glCopyTexImage2D");
+ glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC)load("glCopyTexSubImage1D");
+ glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)load("glCopyTexSubImage2D");
+ glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC)load("glTexSubImage1D");
+ glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)load("glTexSubImage2D");
+ glad_glBindTexture = (PFNGLBINDTEXTUREPROC)load("glBindTexture");
+ glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC)load("glDeleteTextures");
+ glad_glGenTextures = (PFNGLGENTEXTURESPROC)load("glGenTextures");
+ glad_glIsTexture = (PFNGLISTEXTUREPROC)load("glIsTexture");
+ glad_glArrayElement = (PFNGLARRAYELEMENTPROC)load("glArrayElement");
+ glad_glColorPointer = (PFNGLCOLORPOINTERPROC)load("glColorPointer");
+ glad_glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC)load("glDisableClientState");
+ glad_glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC)load("glEdgeFlagPointer");
+ glad_glEnableClientState = (PFNGLENABLECLIENTSTATEPROC)load("glEnableClientState");
+ glad_glIndexPointer = (PFNGLINDEXPOINTERPROC)load("glIndexPointer");
+ glad_glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC)load("glInterleavedArrays");
+ glad_glNormalPointer = (PFNGLNORMALPOINTERPROC)load("glNormalPointer");
+ glad_glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC)load("glTexCoordPointer");
+ glad_glVertexPointer = (PFNGLVERTEXPOINTERPROC)load("glVertexPointer");
+ glad_glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC)load("glAreTexturesResident");
+ glad_glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC)load("glPrioritizeTextures");
+ glad_glIndexub = (PFNGLINDEXUBPROC)load("glIndexub");
+ glad_glIndexubv = (PFNGLINDEXUBVPROC)load("glIndexubv");
+ glad_glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC)load("glPopClientAttrib");
+ glad_glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC)load("glPushClientAttrib");
+}
+static void load_GL_VERSION_1_2(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_1_2) return;
+ glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)load("glDrawRangeElements");
+ glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC)load("glTexImage3D");
+ glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)load("glTexSubImage3D");
+ glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)load("glCopyTexSubImage3D");
+}
+static void load_GL_VERSION_1_3(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_1_3) return;
+ glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC)load("glActiveTexture");
+ glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)load("glSampleCoverage");
+ glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)load("glCompressedTexImage3D");
+ glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)load("glCompressedTexImage2D");
+ glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC)load("glCompressedTexImage1D");
+ glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)load("glCompressedTexSubImage3D");
+ glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)load("glCompressedTexSubImage2D");
+ glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)load("glCompressedTexSubImage1D");
+ glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC)load("glGetCompressedTexImage");
+ glad_glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC)load("glClientActiveTexture");
+ glad_glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC)load("glMultiTexCoord1d");
+ glad_glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC)load("glMultiTexCoord1dv");
+ glad_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC)load("glMultiTexCoord1f");
+ glad_glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC)load("glMultiTexCoord1fv");
+ glad_glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC)load("glMultiTexCoord1i");
+ glad_glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC)load("glMultiTexCoord1iv");
+ glad_glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC)load("glMultiTexCoord1s");
+ glad_glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC)load("glMultiTexCoord1sv");
+ glad_glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC)load("glMultiTexCoord2d");
+ glad_glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC)load("glMultiTexCoord2dv");
+ glad_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC)load("glMultiTexCoord2f");
+ glad_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC)load("glMultiTexCoord2fv");
+ glad_glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC)load("glMultiTexCoord2i");
+ glad_glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC)load("glMultiTexCoord2iv");
+ glad_glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC)load("glMultiTexCoord2s");
+ glad_glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC)load("glMultiTexCoord2sv");
+ glad_glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC)load("glMultiTexCoord3d");
+ glad_glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC)load("glMultiTexCoord3dv");
+ glad_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC)load("glMultiTexCoord3f");
+ glad_glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC)load("glMultiTexCoord3fv");
+ glad_glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC)load("glMultiTexCoord3i");
+ glad_glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC)load("glMultiTexCoord3iv");
+ glad_glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC)load("glMultiTexCoord3s");
+ glad_glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC)load("glMultiTexCoord3sv");
+ glad_glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC)load("glMultiTexCoord4d");
+ glad_glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC)load("glMultiTexCoord4dv");
+ glad_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC)load("glMultiTexCoord4f");
+ glad_glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC)load("glMultiTexCoord4fv");
+ glad_glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC)load("glMultiTexCoord4i");
+ glad_glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC)load("glMultiTexCoord4iv");
+ glad_glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC)load("glMultiTexCoord4s");
+ glad_glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC)load("glMultiTexCoord4sv");
+ glad_glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC)load("glLoadTransposeMatrixf");
+ glad_glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC)load("glLoadTransposeMatrixd");
+ glad_glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC)load("glMultTransposeMatrixf");
+ glad_glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC)load("glMultTransposeMatrixd");
+}
+static void load_GL_VERSION_1_4(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_1_4) return;
+ glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)load("glBlendFuncSeparate");
+ glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC)load("glMultiDrawArrays");
+ glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC)load("glMultiDrawElements");
+ glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC)load("glPointParameterf");
+ glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC)load("glPointParameterfv");
+ glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC)load("glPointParameteri");
+ glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC)load("glPointParameteriv");
+ glad_glFogCoordf = (PFNGLFOGCOORDFPROC)load("glFogCoordf");
+ glad_glFogCoordfv = (PFNGLFOGCOORDFVPROC)load("glFogCoordfv");
+ glad_glFogCoordd = (PFNGLFOGCOORDDPROC)load("glFogCoordd");
+ glad_glFogCoorddv = (PFNGLFOGCOORDDVPROC)load("glFogCoorddv");
+ glad_glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC)load("glFogCoordPointer");
+ glad_glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC)load("glSecondaryColor3b");
+ glad_glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC)load("glSecondaryColor3bv");
+ glad_glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC)load("glSecondaryColor3d");
+ glad_glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC)load("glSecondaryColor3dv");
+ glad_glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)load("glSecondaryColor3f");
+ glad_glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC)load("glSecondaryColor3fv");
+ glad_glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC)load("glSecondaryColor3i");
+ glad_glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC)load("glSecondaryColor3iv");
+ glad_glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC)load("glSecondaryColor3s");
+ glad_glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC)load("glSecondaryColor3sv");
+ glad_glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC)load("glSecondaryColor3ub");
+ glad_glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC)load("glSecondaryColor3ubv");
+ glad_glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC)load("glSecondaryColor3ui");
+ glad_glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC)load("glSecondaryColor3uiv");
+ glad_glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC)load("glSecondaryColor3us");
+ glad_glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC)load("glSecondaryColor3usv");
+ glad_glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC)load("glSecondaryColorPointer");
+ glad_glWindowPos2d = (PFNGLWINDOWPOS2DPROC)load("glWindowPos2d");
+ glad_glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC)load("glWindowPos2dv");
+ glad_glWindowPos2f = (PFNGLWINDOWPOS2FPROC)load("glWindowPos2f");
+ glad_glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC)load("glWindowPos2fv");
+ glad_glWindowPos2i = (PFNGLWINDOWPOS2IPROC)load("glWindowPos2i");
+ glad_glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC)load("glWindowPos2iv");
+ glad_glWindowPos2s = (PFNGLWINDOWPOS2SPROC)load("glWindowPos2s");
+ glad_glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC)load("glWindowPos2sv");
+ glad_glWindowPos3d = (PFNGLWINDOWPOS3DPROC)load("glWindowPos3d");
+ glad_glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC)load("glWindowPos3dv");
+ glad_glWindowPos3f = (PFNGLWINDOWPOS3FPROC)load("glWindowPos3f");
+ glad_glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC)load("glWindowPos3fv");
+ glad_glWindowPos3i = (PFNGLWINDOWPOS3IPROC)load("glWindowPos3i");
+ glad_glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC)load("glWindowPos3iv");
+ glad_glWindowPos3s = (PFNGLWINDOWPOS3SPROC)load("glWindowPos3s");
+ glad_glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC)load("glWindowPos3sv");
+ glad_glBlendColor = (PFNGLBLENDCOLORPROC)load("glBlendColor");
+ glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC)load("glBlendEquation");
+}
+static void load_GL_VERSION_1_5(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_1_5) return;
+ glad_glGenQueries = (PFNGLGENQUERIESPROC)load("glGenQueries");
+ glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC)load("glDeleteQueries");
+ glad_glIsQuery = (PFNGLISQUERYPROC)load("glIsQuery");
+ glad_glBeginQuery = (PFNGLBEGINQUERYPROC)load("glBeginQuery");
+ glad_glEndQuery = (PFNGLENDQUERYPROC)load("glEndQuery");
+ glad_glGetQueryiv = (PFNGLGETQUERYIVPROC)load("glGetQueryiv");
+ glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC)load("glGetQueryObjectiv");
+ glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)load("glGetQueryObjectuiv");
+ glad_glBindBuffer = (PFNGLBINDBUFFERPROC)load("glBindBuffer");
+ glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)load("glDeleteBuffers");
+ glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers");
+ glad_glIsBuffer = (PFNGLISBUFFERPROC)load("glIsBuffer");
+ glad_glBufferData = (PFNGLBUFFERDATAPROC)load("glBufferData");
+ glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC)load("glBufferSubData");
+ glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC)load("glGetBufferSubData");
+ glad_glMapBuffer = (PFNGLMAPBUFFERPROC)load("glMapBuffer");
+ glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)load("glUnmapBuffer");
+ glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv");
+ glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC)load("glGetBufferPointerv");
+}
+static void load_GL_VERSION_2_0(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_2_0) return;
+ glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)load("glBlendEquationSeparate");
+ glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC)load("glDrawBuffers");
+ glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)load("glStencilOpSeparate");
+ glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)load("glStencilFuncSeparate");
+ glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)load("glStencilMaskSeparate");
+ glad_glAttachShader = (PFNGLATTACHSHADERPROC)load("glAttachShader");
+ glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)load("glBindAttribLocation");
+ glad_glCompileShader = (PFNGLCOMPILESHADERPROC)load("glCompileShader");
+ glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC)load("glCreateProgram");
+ glad_glCreateShader = (PFNGLCREATESHADERPROC)load("glCreateShader");
+ glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC)load("glDeleteProgram");
+ glad_glDeleteShader = (PFNGLDELETESHADERPROC)load("glDeleteShader");
+ glad_glDetachShader = (PFNGLDETACHSHADERPROC)load("glDetachShader");
+ glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)load("glDisableVertexAttribArray");
+ glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)load("glEnableVertexAttribArray");
+ glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)load("glGetActiveAttrib");
+ glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)load("glGetActiveUniform");
+ glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)load("glGetAttachedShaders");
+ glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)load("glGetAttribLocation");
+ glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)load("glGetProgramiv");
+ glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)load("glGetProgramInfoLog");
+ glad_glGetShaderiv = (PFNGLGETSHADERIVPROC)load("glGetShaderiv");
+ glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)load("glGetShaderInfoLog");
+ glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)load("glGetShaderSource");
+ glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)load("glGetUniformLocation");
+ glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC)load("glGetUniformfv");
+ glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC)load("glGetUniformiv");
+ glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC)load("glGetVertexAttribdv");
+ glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)load("glGetVertexAttribfv");
+ glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)load("glGetVertexAttribiv");
+ glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)load("glGetVertexAttribPointerv");
+ glad_glIsProgram = (PFNGLISPROGRAMPROC)load("glIsProgram");
+ glad_glIsShader = (PFNGLISSHADERPROC)load("glIsShader");
+ glad_glLinkProgram = (PFNGLLINKPROGRAMPROC)load("glLinkProgram");
+ glad_glShaderSource = (PFNGLSHADERSOURCEPROC)load("glShaderSource");
+ glad_glUseProgram = (PFNGLUSEPROGRAMPROC)load("glUseProgram");
+ glad_glUniform1f = (PFNGLUNIFORM1FPROC)load("glUniform1f");
+ glad_glUniform2f = (PFNGLUNIFORM2FPROC)load("glUniform2f");
+ glad_glUniform3f = (PFNGLUNIFORM3FPROC)load("glUniform3f");
+ glad_glUniform4f = (PFNGLUNIFORM4FPROC)load("glUniform4f");
+ glad_glUniform1i = (PFNGLUNIFORM1IPROC)load("glUniform1i");
+ glad_glUniform2i = (PFNGLUNIFORM2IPROC)load("glUniform2i");
+ glad_glUniform3i = (PFNGLUNIFORM3IPROC)load("glUniform3i");
+ glad_glUniform4i = (PFNGLUNIFORM4IPROC)load("glUniform4i");
+ glad_glUniform1fv = (PFNGLUNIFORM1FVPROC)load("glUniform1fv");
+ glad_glUniform2fv = (PFNGLUNIFORM2FVPROC)load("glUniform2fv");
+ glad_glUniform3fv = (PFNGLUNIFORM3FVPROC)load("glUniform3fv");
+ glad_glUniform4fv = (PFNGLUNIFORM4FVPROC)load("glUniform4fv");
+ glad_glUniform1iv = (PFNGLUNIFORM1IVPROC)load("glUniform1iv");
+ glad_glUniform2iv = (PFNGLUNIFORM2IVPROC)load("glUniform2iv");
+ glad_glUniform3iv = (PFNGLUNIFORM3IVPROC)load("glUniform3iv");
+ glad_glUniform4iv = (PFNGLUNIFORM4IVPROC)load("glUniform4iv");
+ glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)load("glUniformMatrix2fv");
+ glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)load("glUniformMatrix3fv");
+ glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)load("glUniformMatrix4fv");
+ glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)load("glValidateProgram");
+ glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC)load("glVertexAttrib1d");
+ glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC)load("glVertexAttrib1dv");
+ glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)load("glVertexAttrib1f");
+ glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)load("glVertexAttrib1fv");
+ glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC)load("glVertexAttrib1s");
+ glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC)load("glVertexAttrib1sv");
+ glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC)load("glVertexAttrib2d");
+ glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC)load("glVertexAttrib2dv");
+ glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)load("glVertexAttrib2f");
+ glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)load("glVertexAttrib2fv");
+ glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC)load("glVertexAttrib2s");
+ glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC)load("glVertexAttrib2sv");
+ glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC)load("glVertexAttrib3d");
+ glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC)load("glVertexAttrib3dv");
+ glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)load("glVertexAttrib3f");
+ glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)load("glVertexAttrib3fv");
+ glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC)load("glVertexAttrib3s");
+ glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC)load("glVertexAttrib3sv");
+ glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC)load("glVertexAttrib4Nbv");
+ glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC)load("glVertexAttrib4Niv");
+ glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC)load("glVertexAttrib4Nsv");
+ glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC)load("glVertexAttrib4Nub");
+ glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC)load("glVertexAttrib4Nubv");
+ glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC)load("glVertexAttrib4Nuiv");
+ glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC)load("glVertexAttrib4Nusv");
+ glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC)load("glVertexAttrib4bv");
+ glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC)load("glVertexAttrib4d");
+ glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC)load("glVertexAttrib4dv");
+ glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)load("glVertexAttrib4f");
+ glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)load("glVertexAttrib4fv");
+ glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC)load("glVertexAttrib4iv");
+ glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC)load("glVertexAttrib4s");
+ glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC)load("glVertexAttrib4sv");
+ glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC)load("glVertexAttrib4ubv");
+ glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)load("glVertexAttrib4uiv");
+ glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)load("glVertexAttrib4usv");
+ glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)load("glVertexAttribPointer");
+}
+static void load_GL_VERSION_2_1(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_2_1) return;
+ glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC)load("glUniformMatrix2x3fv");
+ glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC)load("glUniformMatrix3x2fv");
+ glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC)load("glUniformMatrix2x4fv");
+ glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC)load("glUniformMatrix4x2fv");
+ glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC)load("glUniformMatrix3x4fv");
+ glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC)load("glUniformMatrix4x3fv");
+}
+static void load_GL_VERSION_3_0(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_3_0) return;
+ glad_glColorMaski = (PFNGLCOLORMASKIPROC)load("glColorMaski");
+ glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC)load("glGetBooleani_v");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
+ glad_glEnablei = (PFNGLENABLEIPROC)load("glEnablei");
+ glad_glDisablei = (PFNGLDISABLEIPROC)load("glDisablei");
+ glad_glIsEnabledi = (PFNGLISENABLEDIPROC)load("glIsEnabledi");
+ glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC)load("glBeginTransformFeedback");
+ glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC)load("glEndTransformFeedback");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
+ glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC)load("glTransformFeedbackVaryings");
+ glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)load("glGetTransformFeedbackVarying");
+ glad_glClampColor = (PFNGLCLAMPCOLORPROC)load("glClampColor");
+ glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC)load("glBeginConditionalRender");
+ glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC)load("glEndConditionalRender");
+ glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)load("glVertexAttribIPointer");
+ glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC)load("glGetVertexAttribIiv");
+ glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC)load("glGetVertexAttribIuiv");
+ glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC)load("glVertexAttribI1i");
+ glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC)load("glVertexAttribI2i");
+ glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC)load("glVertexAttribI3i");
+ glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC)load("glVertexAttribI4i");
+ glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC)load("glVertexAttribI1ui");
+ glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC)load("glVertexAttribI2ui");
+ glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC)load("glVertexAttribI3ui");
+ glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC)load("glVertexAttribI4ui");
+ glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC)load("glVertexAttribI1iv");
+ glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC)load("glVertexAttribI2iv");
+ glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC)load("glVertexAttribI3iv");
+ glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC)load("glVertexAttribI4iv");
+ glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC)load("glVertexAttribI1uiv");
+ glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC)load("glVertexAttribI2uiv");
+ glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC)load("glVertexAttribI3uiv");
+ glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC)load("glVertexAttribI4uiv");
+ glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC)load("glVertexAttribI4bv");
+ glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC)load("glVertexAttribI4sv");
+ glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC)load("glVertexAttribI4ubv");
+ glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC)load("glVertexAttribI4usv");
+ glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC)load("glGetUniformuiv");
+ glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC)load("glBindFragDataLocation");
+ glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC)load("glGetFragDataLocation");
+ glad_glUniform1ui = (PFNGLUNIFORM1UIPROC)load("glUniform1ui");
+ glad_glUniform2ui = (PFNGLUNIFORM2UIPROC)load("glUniform2ui");
+ glad_glUniform3ui = (PFNGLUNIFORM3UIPROC)load("glUniform3ui");
+ glad_glUniform4ui = (PFNGLUNIFORM4UIPROC)load("glUniform4ui");
+ glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC)load("glUniform1uiv");
+ glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC)load("glUniform2uiv");
+ glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC)load("glUniform3uiv");
+ glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC)load("glUniform4uiv");
+ glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC)load("glTexParameterIiv");
+ glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC)load("glTexParameterIuiv");
+ glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC)load("glGetTexParameterIiv");
+ glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC)load("glGetTexParameterIuiv");
+ glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)load("glClearBufferiv");
+ glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)load("glClearBufferuiv");
+ glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)load("glClearBufferfv");
+ glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)load("glClearBufferfi");
+ glad_glGetStringi = (PFNGLGETSTRINGIPROC)load("glGetStringi");
+ glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer");
+ glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer");
+ glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers");
+ glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers");
+ glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage");
+ glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv");
+ glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer");
+ glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer");
+ glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers");
+ glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers");
+ glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus");
+ glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)load("glFramebufferTexture1D");
+ glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D");
+ glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)load("glFramebufferTexture3D");
+ glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer");
+ glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv");
+ glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap");
+ glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)load("glBlitFramebuffer");
+ glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glRenderbufferStorageMultisample");
+ glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC)load("glFramebufferTextureLayer");
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)load("glMapBufferRange");
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)load("glFlushMappedBufferRange");
+ glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)load("glBindVertexArray");
+ glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)load("glDeleteVertexArrays");
+ glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)load("glGenVertexArrays");
+ glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC)load("glIsVertexArray");
+}
+static void load_GL_VERSION_3_1(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_3_1) return;
+ glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)load("glDrawArraysInstanced");
+ glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)load("glDrawElementsInstanced");
+ glad_glTexBuffer = (PFNGLTEXBUFFERPROC)load("glTexBuffer");
+ glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)load("glPrimitiveRestartIndex");
+ glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC)load("glCopyBufferSubData");
+ glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC)load("glGetUniformIndices");
+ glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC)load("glGetActiveUniformsiv");
+ glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC)load("glGetActiveUniformName");
+ glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)load("glGetUniformBlockIndex");
+ glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC)load("glGetActiveUniformBlockiv");
+ glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)load("glGetActiveUniformBlockName");
+ glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)load("glUniformBlockBinding");
+ glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)load("glBindBufferRange");
+ glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)load("glBindBufferBase");
+ glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC)load("glGetIntegeri_v");
+}
+static void load_GL_VERSION_3_2(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_3_2) return;
+ glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)load("glDrawElementsBaseVertex");
+ glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)load("glDrawRangeElementsBaseVertex");
+ glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)load("glDrawElementsInstancedBaseVertex");
+ glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)load("glMultiDrawElementsBaseVertex");
+ glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC)load("glProvokingVertex");
+ glad_glFenceSync = (PFNGLFENCESYNCPROC)load("glFenceSync");
+ glad_glIsSync = (PFNGLISSYNCPROC)load("glIsSync");
+ glad_glDeleteSync = (PFNGLDELETESYNCPROC)load("glDeleteSync");
+ glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)load("glClientWaitSync");
+ glad_glWaitSync = (PFNGLWAITSYNCPROC)load("glWaitSync");
+ glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC)load("glGetInteger64v");
+ glad_glGetSynciv = (PFNGLGETSYNCIVPROC)load("glGetSynciv");
+ glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC)load("glGetInteger64i_v");
+ glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC)load("glGetBufferParameteri64v");
+ glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC)load("glFramebufferTexture");
+ glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)load("glTexImage2DMultisample");
+ glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC)load("glTexImage3DMultisample");
+ glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC)load("glGetMultisamplefv");
+ glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC)load("glSampleMaski");
+}
+static void load_GL_VERSION_3_3(GLADloadproc load) {
+ if(!GLAD_GL_VERSION_3_3) return;
+ glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)load("glBindFragDataLocationIndexed");
+ glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC)load("glGetFragDataIndex");
+ glad_glGenSamplers = (PFNGLGENSAMPLERSPROC)load("glGenSamplers");
+ glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC)load("glDeleteSamplers");
+ glad_glIsSampler = (PFNGLISSAMPLERPROC)load("glIsSampler");
+ glad_glBindSampler = (PFNGLBINDSAMPLERPROC)load("glBindSampler");
+ glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC)load("glSamplerParameteri");
+ glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC)load("glSamplerParameteriv");
+ glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC)load("glSamplerParameterf");
+ glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC)load("glSamplerParameterfv");
+ glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC)load("glSamplerParameterIiv");
+ glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC)load("glSamplerParameterIuiv");
+ glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC)load("glGetSamplerParameteriv");
+ glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC)load("glGetSamplerParameterIiv");
+ glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC)load("glGetSamplerParameterfv");
+ glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC)load("glGetSamplerParameterIuiv");
+ glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC)load("glQueryCounter");
+ glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC)load("glGetQueryObjecti64v");
+ glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC)load("glGetQueryObjectui64v");
+ glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)load("glVertexAttribDivisor");
+ glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC)load("glVertexAttribP1ui");
+ glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC)load("glVertexAttribP1uiv");
+ glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC)load("glVertexAttribP2ui");
+ glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC)load("glVertexAttribP2uiv");
+ glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC)load("glVertexAttribP3ui");
+ glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC)load("glVertexAttribP3uiv");
+ glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC)load("glVertexAttribP4ui");
+ glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC)load("glVertexAttribP4uiv");
+ glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC)load("glVertexP2ui");
+ glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC)load("glVertexP2uiv");
+ glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC)load("glVertexP3ui");
+ glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC)load("glVertexP3uiv");
+ glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC)load("glVertexP4ui");
+ glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC)load("glVertexP4uiv");
+ glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC)load("glTexCoordP1ui");
+ glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC)load("glTexCoordP1uiv");
+ glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC)load("glTexCoordP2ui");
+ glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC)load("glTexCoordP2uiv");
+ glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC)load("glTexCoordP3ui");
+ glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC)load("glTexCoordP3uiv");
+ glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC)load("glTexCoordP4ui");
+ glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC)load("glTexCoordP4uiv");
+ glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC)load("glMultiTexCoordP1ui");
+ glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC)load("glMultiTexCoordP1uiv");
+ glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC)load("glMultiTexCoordP2ui");
+ glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC)load("glMultiTexCoordP2uiv");
+ glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC)load("glMultiTexCoordP3ui");
+ glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC)load("glMultiTexCoordP3uiv");
+ glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC)load("glMultiTexCoordP4ui");
+ glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC)load("glMultiTexCoordP4uiv");
+ glad_glNormalP3ui = (PFNGLNORMALP3UIPROC)load("glNormalP3ui");
+ glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC)load("glNormalP3uiv");
+ glad_glColorP3ui = (PFNGLCOLORP3UIPROC)load("glColorP3ui");
+ glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC)load("glColorP3uiv");
+ glad_glColorP4ui = (PFNGLCOLORP4UIPROC)load("glColorP4ui");
+ glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC)load("glColorP4uiv");
+ glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC)load("glSecondaryColorP3ui");
+ glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC)load("glSecondaryColorP3uiv");
+}
+static void load_GL_ARB_map_buffer_range(GLADloadproc load) {
+ if(!GLAD_GL_ARB_map_buffer_range) return;
+ glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)load("glMapBufferRange");
+ glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC)load("glFlushMappedBufferRange");
+}
+static int find_extensionsGL(void) {
+ if (!get_exts()) return 0;
+ GLAD_GL_ARB_map_buffer_alignment = has_ext("GL_ARB_map_buffer_alignment");
+ GLAD_GL_ARB_map_buffer_range = has_ext("GL_ARB_map_buffer_range");
+ free_exts();
+ return 1;
+}
+
+static void find_coreGL(void) {
+
+ /* Thank you @elmindreda
+ * https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
+ * https://github.com/glfw/glfw/blob/master/src/context.c#L36
+ */
+ int i, major, minor;
+
+ const char* version;
+ const char* prefixes[] = {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ NULL
+ };
+
+ version = (const char*) glGetString(GL_VERSION);
+ if (!version) return;
+
+ for (i = 0; prefixes[i]; i++) {
+ const size_t length = strlen(prefixes[i]);
+ if (strncmp(version, prefixes[i], length) == 0) {
+ version += length;
+ break;
+ }
+ }
+
+/* PR #18 */
+#ifdef _MSC_VER
+ sscanf_s(version, "%d.%d", &major, &minor);
+#else
+ sscanf(version, "%d.%d", &major, &minor);
+#endif
+
+ GLVersion.major = major; GLVersion.minor = minor;
+ max_loaded_major = major; max_loaded_minor = minor;
+ GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+ GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+ GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+ GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+ GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+ GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
+ GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+ GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
+ GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
+ GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
+ GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
+ GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
+ if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 3)) {
+ max_loaded_major = 3;
+ max_loaded_minor = 3;
+ }
+}
+
+int gladLoadGLLoader(GLADloadproc load) {
+ GLVersion.major = 0; GLVersion.minor = 0;
+ glGetString = (PFNGLGETSTRINGPROC)load("glGetString");
+ if(glGetString == NULL) return 0;
+ if(glGetString(GL_VERSION) == NULL) return 0;
+ find_coreGL();
+ load_GL_VERSION_1_0(load);
+ load_GL_VERSION_1_1(load);
+ load_GL_VERSION_1_2(load);
+ load_GL_VERSION_1_3(load);
+ load_GL_VERSION_1_4(load);
+ load_GL_VERSION_1_5(load);
+ load_GL_VERSION_2_0(load);
+ load_GL_VERSION_2_1(load);
+ load_GL_VERSION_3_0(load);
+ load_GL_VERSION_3_1(load);
+ load_GL_VERSION_3_2(load);
+ load_GL_VERSION_3_3(load);
+
+ if (!find_extensionsGL()) return 0;
+ load_GL_ARB_map_buffer_range(load);
+ return GLVersion.major != 0 || GLVersion.minor != 0;
+}
+
diff --git a/Client/ThirdParty/glad/glad.h b/Client/ThirdParty/glad/glad.h
new file mode 100644
index 0000000..646b24f
--- /dev/null
+++ b/Client/ThirdParty/glad/glad.h
@@ -0,0 +1,3621 @@
+/*
+
+ OpenGL loader generated by glad 0.1.34 on Tue Nov 2 08:57:31 2021.
+
+ Language/Generator: C/C++
+ Specification: gl
+ APIs: gl=3.3
+ Profile: compatibility
+ Extensions:
+ GL_ARB_map_buffer_alignment,
+ GL_ARB_map_buffer_range
+ Loader: True
+ Local files: True
+ Omit khrplatform: False
+ Reproducible: False
+
+ Commandline:
+ --profile="compatibility" --api="gl=3.3" --generator="c" --spec="gl" --local-files --extensions="GL_ARB_map_buffer_alignment,GL_ARB_map_buffer_range"
+ Online:
+ https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gl%3D3.3&extensions=GL_ARB_map_buffer_alignment&extensions=GL_ARB_map_buffer_range
+*/
+
+
+#ifndef __glad_h_
+#define __glad_h_
+
+#ifdef __gl_h_
+#error OpenGL header already included, remove this include, glad already provides it
+#endif
+#define __gl_h_
+
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#define APIENTRY __stdcall
+#endif
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY APIENTRY
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct gladGLversionStruct {
+ int major;
+ int minor;
+};
+
+typedef void* (* GLADloadproc)(const char *name);
+
+#ifndef GLAPI
+# if defined(GLAD_GLAPI_EXPORT)
+# if defined(_WIN32) || defined(__CYGWIN__)
+# if defined(GLAD_GLAPI_EXPORT_BUILD)
+# if defined(__GNUC__)
+# define GLAPI __attribute__ ((dllexport)) extern
+# else
+# define GLAPI __declspec(dllexport) extern
+# endif
+# else
+# if defined(__GNUC__)
+# define GLAPI __attribute__ ((dllimport)) extern
+# else
+# define GLAPI __declspec(dllimport) extern
+# endif
+# endif
+# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD)
+# define GLAPI __attribute__ ((visibility ("default"))) extern
+# else
+# define GLAPI extern
+# endif
+# else
+# define GLAPI extern
+# endif
+#endif
+
+GLAPI struct gladGLversionStruct GLVersion;
+
+GLAPI int gladLoadGL(void);
+
+GLAPI int gladLoadGLLoader(GLADloadproc);
+
+#include "khrplatform.h"
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+typedef khronos_intptr_t GLintptr;
+typedef khronos_intptr_t GLintptrARB;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_ssize_t GLsizeiptrARB;
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void (APIENTRY *GLVULKANPROCNV)(void);
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_POINTS 0x0000
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_STRIP 0x0003
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_QUADS 0x0007
+#define GL_NEVER 0x0200
+#define GL_LESS 0x0201
+#define GL_EQUAL 0x0202
+#define GL_LEQUAL 0x0203
+#define GL_GREATER 0x0204
+#define GL_NOTEQUAL 0x0205
+#define GL_GEQUAL 0x0206
+#define GL_ALWAYS 0x0207
+#define GL_ZERO 0
+#define GL_ONE 1
+#define GL_SRC_COLOR 0x0300
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_DST_ALPHA 0x0304
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_DST_COLOR 0x0306
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_NONE 0
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_FRONT 0x0404
+#define GL_BACK 0x0405
+#define GL_LEFT 0x0406
+#define GL_RIGHT 0x0407
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_NO_ERROR 0
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVALID_OPERATION 0x0502
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_CW 0x0900
+#define GL_CCW 0x0901
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_FRONT_FACE 0x0B46
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_VIEWPORT 0x0BA2
+#define GL_DITHER 0x0BD0
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND 0x0BE2
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_READ_BUFFER 0x0C02
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_STEREO 0x0C33
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_DONT_CARE 0x1100
+#define GL_FASTEST 0x1101
+#define GL_NICEST 0x1102
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_CLEAR 0x1500
+#define GL_AND 0x1501
+#define GL_AND_REVERSE 0x1502
+#define GL_COPY 0x1503
+#define GL_AND_INVERTED 0x1504
+#define GL_NOOP 0x1505
+#define GL_XOR 0x1506
+#define GL_OR 0x1507
+#define GL_NOR 0x1508
+#define GL_EQUIV 0x1509
+#define GL_INVERT 0x150A
+#define GL_OR_REVERSE 0x150B
+#define GL_COPY_INVERTED 0x150C
+#define GL_OR_INVERTED 0x150D
+#define GL_NAND 0x150E
+#define GL_SET 0x150F
+#define GL_TEXTURE 0x1702
+#define GL_COLOR 0x1800
+#define GL_DEPTH 0x1801
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_INDEX 0x1901
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_RED 0x1903
+#define GL_GREEN 0x1904
+#define GL_BLUE 0x1905
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_POINT 0x1B00
+#define GL_LINE 0x1B01
+#define GL_FILL 0x1B02
+#define GL_KEEP 0x1E00
+#define GL_REPLACE 0x1E01
+#define GL_INCR 0x1E02
+#define GL_DECR 0x1E03
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_REPEAT 0x2901
+#define GL_CURRENT_BIT 0x00000001
+#define GL_POINT_BIT 0x00000002
+#define GL_LINE_BIT 0x00000004
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_FOG_BIT 0x00000080
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_ENABLE_BIT 0x00002000
+#define GL_HINT_BIT 0x00008000
+#define GL_EVAL_BIT 0x00010000
+#define GL_LIST_BIT 0x00020000
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_QUAD_STRIP 0x0008
+#define GL_POLYGON 0x0009
+#define GL_ACCUM 0x0100
+#define GL_LOAD 0x0101
+#define GL_RETURN 0x0102
+#define GL_MULT 0x0103
+#define GL_ADD 0x0104
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_2D 0x0600
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_POINT_TOKEN 0x0701
+#define GL_LINE_TOKEN 0x0702
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+#define GL_COEFF 0x0A00
+#define GL_ORDER 0x0A01
+#define GL_DOMAIN 0x0A02
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LIST_MODE 0x0B30
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_INDEX 0x0B33
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_EDGE_FLAG 0x0B43
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_SHADE_MODEL 0x0B54
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_FOG 0x0B60
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_START 0x0B63
+#define GL_FOG_END 0x0B64
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_COLOR 0x0B66
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_NORMALIZE 0x0BA1
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_LOGIC_OP 0x0BF1
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_INDEX_MODE 0x0C30
+#define GL_RGBA_MODE 0x0C31
+#define GL_RENDER_MODE 0x0C40
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_FOG_HINT 0x0C54
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_STENCIL 0x0D11
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_RED_SCALE 0x0D14
+#define GL_RED_BIAS 0x0D15
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GREEN_BIAS 0x0D19
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_INDEX_BITS 0x0D51
+#define GL_RED_BITS 0x0D52
+#define GL_GREEN_BITS 0x0D53
+#define GL_BLUE_BITS 0x0D54
+#define GL_ALPHA_BITS 0x0D55
+#define GL_DEPTH_BITS 0x0D56
+#define GL_STENCIL_BITS 0x0D57
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_AMBIENT 0x1200
+#define GL_DIFFUSE 0x1201
+#define GL_SPECULAR 0x1202
+#define GL_POSITION 0x1203
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_2_BYTES 0x1407
+#define GL_3_BYTES 0x1408
+#define GL_4_BYTES 0x1409
+#define GL_EMISSION 0x1600
+#define GL_SHININESS 0x1601
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_COLOR_INDEXES 0x1603
+#define GL_MODELVIEW 0x1700
+#define GL_PROJECTION 0x1701
+#define GL_COLOR_INDEX 0x1900
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_BITMAP 0x1A00
+#define GL_RENDER 0x1C00
+#define GL_FEEDBACK 0x1C01
+#define GL_SELECT 0x1C02
+#define GL_FLAT 0x1D00
+#define GL_SMOOTH 0x1D01
+#define GL_S 0x2000
+#define GL_T 0x2001
+#define GL_R 0x2002
+#define GL_Q 0x2003
+#define GL_MODULATE 0x2100
+#define GL_DECAL 0x2101
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV 0x2300
+#define GL_EYE_LINEAR 0x2400
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_SPHERE_MAP 0x2402
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_OBJECT_PLANE 0x2501
+#define GL_EYE_PLANE 0x2502
+#define GL_CLAMP 0x2900
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_DOUBLE 0x140A
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_R3_G3_B2 0x2A10
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB8 0x8051
+#define GL_RGB10 0x8052
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGB5_A1 0x8057
+#define GL_RGBA8 0x8058
+#define GL_RGB10_A2 0x8059
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_COLOR_ARRAY 0x8076
+#define GL_INDEX_ARRAY 0x8077
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_C3F_V3F 0x2A24
+#define GL_N3F_V3F 0x2A25
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_V4F 0x2A28
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_SUBTRACT 0x84E7
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_EQUATION 0x8009
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_MIN 0x8007
+#define GL_MAX 0x8008
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_COORD 0x8451
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC2_ALPHA 0x858A
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RG 0x8226
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_RGBA32F 0x8814
+#define GL_RGB32F 0x8815
+#define GL_RGBA16F 0x881A
+#define GL_RGB16F 0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_FIXED_ONLY 0x891D
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_RGB9_E5 0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI 0x8D70
+#define GL_RGB32UI 0x8D71
+#define GL_RGBA16UI 0x8D76
+#define GL_RGB16UI 0x8D77
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGB8UI 0x8D7D
+#define GL_RGBA32I 0x8D82
+#define GL_RGB32I 0x8D83
+#define GL_RGBA16I 0x8D88
+#define GL_RGB16I 0x8D89
+#define GL_RGBA8I 0x8D8E
+#define GL_RGB8I 0x8D8F
+#define GL_RED_INTEGER 0x8D94
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_QUERY_WAIT 0x8E13
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_INDEX 0x8222
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_HALF_FLOAT 0x140B
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_RG 0x8227
+#define GL_RG_INTEGER 0x8228
+#define GL_R8 0x8229
+#define GL_R16 0x822A
+#define GL_RG8 0x822B
+#define GL_RG16 0x822C
+#define GL_R16F 0x822D
+#define GL_R32F 0x822E
+#define GL_RG16F 0x822F
+#define GL_RG32F 0x8230
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_ALPHA_INTEGER 0x8D97
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_R8_SNORM 0x8F94
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_R16_SNORM 0x8F98
+#define GL_RG16_SNORM 0x8F99
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX 0xFFFFFFFF
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_OBJECT_TYPE 0x9112
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_STATUS 0x9114
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_UNSIGNALED 0x9118
+#define GL_SIGNALED 0x9119
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_WAIT_FAILED 0x911D
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_SRC1_COLOR 0x88F9
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_RGB10_A2UI 0x906F
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TIMESTAMP 0x8E28
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#ifndef GL_VERSION_1_0
+#define GL_VERSION_1_0 1
+GLAPI int GLAD_GL_VERSION_1_0;
+typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum mode);
+GLAPI PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum mode);
+GLAPI PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+typedef void (APIENTRYP PFNGLHINTPROC)(GLenum target, GLenum mode);
+GLAPI PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat width);
+GLAPI PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+typedef void (APIENTRYP PFNGLPOINTSIZEPROC)(GLfloat size);
+GLAPI PFNGLPOINTSIZEPROC glad_glPointSize;
+#define glPointSize glad_glPointSize
+typedef void (APIENTRYP PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode);
+GLAPI PFNGLPOLYGONMODEPROC glad_glPolygonMode;
+#define glPolygonMode glad_glPolygonMode
+typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param);
+GLAPI PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat *params);
+GLAPI PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param);
+GLAPI PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint *params);
+GLAPI PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
+#define glTexImage1D glad_glTexImage1D
+typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+typedef void (APIENTRYP PFNGLDRAWBUFFERPROC)(GLenum buf);
+GLAPI PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
+#define glDrawBuffer glad_glDrawBuffer
+typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield mask);
+GLAPI PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint s);
+GLAPI PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+typedef void (APIENTRYP PFNGLCLEARDEPTHPROC)(GLdouble depth);
+GLAPI PFNGLCLEARDEPTHPROC glad_glClearDepth;
+#define glClearDepth glad_glClearDepth
+typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint mask);
+GLAPI PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GLAPI PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean flag);
+GLAPI PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap);
+GLAPI PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum cap);
+GLAPI PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+typedef void (APIENTRYP PFNGLFINISHPROC)(void);
+GLAPI PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+typedef void (APIENTRYP PFNGLFLUSHPROC)(void);
+GLAPI PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor);
+GLAPI PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+typedef void (APIENTRYP PFNGLLOGICOPPROC)(GLenum opcode);
+GLAPI PFNGLLOGICOPPROC glad_glLogicOp;
+#define glLogicOp glad_glLogicOp
+typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask);
+GLAPI PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass);
+GLAPI PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum func);
+GLAPI PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+typedef void (APIENTRYP PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param);
+GLAPI PFNGLPIXELSTOREFPROC glad_glPixelStoref;
+#define glPixelStoref glad_glPixelStoref
+typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param);
+GLAPI PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+typedef void (APIENTRYP PFNGLREADBUFFERPROC)(GLenum src);
+GLAPI PFNGLREADBUFFERPROC glad_glReadBuffer;
+#define glReadBuffer glad_glReadBuffer
+typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GLAPI PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean *data);
+GLAPI PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+typedef void (APIENTRYP PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble *data);
+GLAPI PFNGLGETDOUBLEVPROC glad_glGetDoublev;
+#define glGetDoublev glad_glGetDoublev
+typedef GLenum (APIENTRYP PFNGLGETERRORPROC)(void);
+GLAPI PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum pname, GLfloat *data);
+GLAPI PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum pname, GLint *data);
+GLAPI PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC)(GLenum name);
+GLAPI PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void *pixels);
+GLAPI PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
+#define glGetTexImage glad_glGetTexImage
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
+GLAPI PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
+#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
+typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint *params);
+GLAPI PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
+#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
+typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum cap);
+GLAPI PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+typedef void (APIENTRYP PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f);
+GLAPI PFNGLDEPTHRANGEPROC glad_glDepthRange;
+#define glDepthRange glad_glDepthRange
+typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+typedef void (APIENTRYP PFNGLNEWLISTPROC)(GLuint list, GLenum mode);
+GLAPI PFNGLNEWLISTPROC glad_glNewList;
+#define glNewList glad_glNewList
+typedef void (APIENTRYP PFNGLENDLISTPROC)(void);
+GLAPI PFNGLENDLISTPROC glad_glEndList;
+#define glEndList glad_glEndList
+typedef void (APIENTRYP PFNGLCALLLISTPROC)(GLuint list);
+GLAPI PFNGLCALLLISTPROC glad_glCallList;
+#define glCallList glad_glCallList
+typedef void (APIENTRYP PFNGLCALLLISTSPROC)(GLsizei n, GLenum type, const void *lists);
+GLAPI PFNGLCALLLISTSPROC glad_glCallLists;
+#define glCallLists glad_glCallLists
+typedef void (APIENTRYP PFNGLDELETELISTSPROC)(GLuint list, GLsizei range);
+GLAPI PFNGLDELETELISTSPROC glad_glDeleteLists;
+#define glDeleteLists glad_glDeleteLists
+typedef GLuint (APIENTRYP PFNGLGENLISTSPROC)(GLsizei range);
+GLAPI PFNGLGENLISTSPROC glad_glGenLists;
+#define glGenLists glad_glGenLists
+typedef void (APIENTRYP PFNGLLISTBASEPROC)(GLuint base);
+GLAPI PFNGLLISTBASEPROC glad_glListBase;
+#define glListBase glad_glListBase
+typedef void (APIENTRYP PFNGLBEGINPROC)(GLenum mode);
+GLAPI PFNGLBEGINPROC glad_glBegin;
+#define glBegin glad_glBegin
+typedef void (APIENTRYP PFNGLBITMAPPROC)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+GLAPI PFNGLBITMAPPROC glad_glBitmap;
+#define glBitmap glad_glBitmap
+typedef void (APIENTRYP PFNGLCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
+GLAPI PFNGLCOLOR3BPROC glad_glColor3b;
+#define glColor3b glad_glColor3b
+typedef void (APIENTRYP PFNGLCOLOR3BVPROC)(const GLbyte *v);
+GLAPI PFNGLCOLOR3BVPROC glad_glColor3bv;
+#define glColor3bv glad_glColor3bv
+typedef void (APIENTRYP PFNGLCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
+GLAPI PFNGLCOLOR3DPROC glad_glColor3d;
+#define glColor3d glad_glColor3d
+typedef void (APIENTRYP PFNGLCOLOR3DVPROC)(const GLdouble *v);
+GLAPI PFNGLCOLOR3DVPROC glad_glColor3dv;
+#define glColor3dv glad_glColor3dv
+typedef void (APIENTRYP PFNGLCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
+GLAPI PFNGLCOLOR3FPROC glad_glColor3f;
+#define glColor3f glad_glColor3f
+typedef void (APIENTRYP PFNGLCOLOR3FVPROC)(const GLfloat *v);
+GLAPI PFNGLCOLOR3FVPROC glad_glColor3fv;
+#define glColor3fv glad_glColor3fv
+typedef void (APIENTRYP PFNGLCOLOR3IPROC)(GLint red, GLint green, GLint blue);
+GLAPI PFNGLCOLOR3IPROC glad_glColor3i;
+#define glColor3i glad_glColor3i
+typedef void (APIENTRYP PFNGLCOLOR3IVPROC)(const GLint *v);
+GLAPI PFNGLCOLOR3IVPROC glad_glColor3iv;
+#define glColor3iv glad_glColor3iv
+typedef void (APIENTRYP PFNGLCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
+GLAPI PFNGLCOLOR3SPROC glad_glColor3s;
+#define glColor3s glad_glColor3s
+typedef void (APIENTRYP PFNGLCOLOR3SVPROC)(const GLshort *v);
+GLAPI PFNGLCOLOR3SVPROC glad_glColor3sv;
+#define glColor3sv glad_glColor3sv
+typedef void (APIENTRYP PFNGLCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
+GLAPI PFNGLCOLOR3UBPROC glad_glColor3ub;
+#define glColor3ub glad_glColor3ub
+typedef void (APIENTRYP PFNGLCOLOR3UBVPROC)(const GLubyte *v);
+GLAPI PFNGLCOLOR3UBVPROC glad_glColor3ubv;
+#define glColor3ubv glad_glColor3ubv
+typedef void (APIENTRYP PFNGLCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
+GLAPI PFNGLCOLOR3UIPROC glad_glColor3ui;
+#define glColor3ui glad_glColor3ui
+typedef void (APIENTRYP PFNGLCOLOR3UIVPROC)(const GLuint *v);
+GLAPI PFNGLCOLOR3UIVPROC glad_glColor3uiv;
+#define glColor3uiv glad_glColor3uiv
+typedef void (APIENTRYP PFNGLCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
+GLAPI PFNGLCOLOR3USPROC glad_glColor3us;
+#define glColor3us glad_glColor3us
+typedef void (APIENTRYP PFNGLCOLOR3USVPROC)(const GLushort *v);
+GLAPI PFNGLCOLOR3USVPROC glad_glColor3usv;
+#define glColor3usv glad_glColor3usv
+typedef void (APIENTRYP PFNGLCOLOR4BPROC)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+GLAPI PFNGLCOLOR4BPROC glad_glColor4b;
+#define glColor4b glad_glColor4b
+typedef void (APIENTRYP PFNGLCOLOR4BVPROC)(const GLbyte *v);
+GLAPI PFNGLCOLOR4BVPROC glad_glColor4bv;
+#define glColor4bv glad_glColor4bv
+typedef void (APIENTRYP PFNGLCOLOR4DPROC)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+GLAPI PFNGLCOLOR4DPROC glad_glColor4d;
+#define glColor4d glad_glColor4d
+typedef void (APIENTRYP PFNGLCOLOR4DVPROC)(const GLdouble *v);
+GLAPI PFNGLCOLOR4DVPROC glad_glColor4dv;
+#define glColor4dv glad_glColor4dv
+typedef void (APIENTRYP PFNGLCOLOR4FPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI PFNGLCOLOR4FPROC glad_glColor4f;
+#define glColor4f glad_glColor4f
+typedef void (APIENTRYP PFNGLCOLOR4FVPROC)(const GLfloat *v);
+GLAPI PFNGLCOLOR4FVPROC glad_glColor4fv;
+#define glColor4fv glad_glColor4fv
+typedef void (APIENTRYP PFNGLCOLOR4IPROC)(GLint red, GLint green, GLint blue, GLint alpha);
+GLAPI PFNGLCOLOR4IPROC glad_glColor4i;
+#define glColor4i glad_glColor4i
+typedef void (APIENTRYP PFNGLCOLOR4IVPROC)(const GLint *v);
+GLAPI PFNGLCOLOR4IVPROC glad_glColor4iv;
+#define glColor4iv glad_glColor4iv
+typedef void (APIENTRYP PFNGLCOLOR4SPROC)(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+GLAPI PFNGLCOLOR4SPROC glad_glColor4s;
+#define glColor4s glad_glColor4s
+typedef void (APIENTRYP PFNGLCOLOR4SVPROC)(const GLshort *v);
+GLAPI PFNGLCOLOR4SVPROC glad_glColor4sv;
+#define glColor4sv glad_glColor4sv
+typedef void (APIENTRYP PFNGLCOLOR4UBPROC)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+GLAPI PFNGLCOLOR4UBPROC glad_glColor4ub;
+#define glColor4ub glad_glColor4ub
+typedef void (APIENTRYP PFNGLCOLOR4UBVPROC)(const GLubyte *v);
+GLAPI PFNGLCOLOR4UBVPROC glad_glColor4ubv;
+#define glColor4ubv glad_glColor4ubv
+typedef void (APIENTRYP PFNGLCOLOR4UIPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+GLAPI PFNGLCOLOR4UIPROC glad_glColor4ui;
+#define glColor4ui glad_glColor4ui
+typedef void (APIENTRYP PFNGLCOLOR4UIVPROC)(const GLuint *v);
+GLAPI PFNGLCOLOR4UIVPROC glad_glColor4uiv;
+#define glColor4uiv glad_glColor4uiv
+typedef void (APIENTRYP PFNGLCOLOR4USPROC)(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+GLAPI PFNGLCOLOR4USPROC glad_glColor4us;
+#define glColor4us glad_glColor4us
+typedef void (APIENTRYP PFNGLCOLOR4USVPROC)(const GLushort *v);
+GLAPI PFNGLCOLOR4USVPROC glad_glColor4usv;
+#define glColor4usv glad_glColor4usv
+typedef void (APIENTRYP PFNGLEDGEFLAGPROC)(GLboolean flag);
+GLAPI PFNGLEDGEFLAGPROC glad_glEdgeFlag;
+#define glEdgeFlag glad_glEdgeFlag
+typedef void (APIENTRYP PFNGLEDGEFLAGVPROC)(const GLboolean *flag);
+GLAPI PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
+#define glEdgeFlagv glad_glEdgeFlagv
+typedef void (APIENTRYP PFNGLENDPROC)(void);
+GLAPI PFNGLENDPROC glad_glEnd;
+#define glEnd glad_glEnd
+typedef void (APIENTRYP PFNGLINDEXDPROC)(GLdouble c);
+GLAPI PFNGLINDEXDPROC glad_glIndexd;
+#define glIndexd glad_glIndexd
+typedef void (APIENTRYP PFNGLINDEXDVPROC)(const GLdouble *c);
+GLAPI PFNGLINDEXDVPROC glad_glIndexdv;
+#define glIndexdv glad_glIndexdv
+typedef void (APIENTRYP PFNGLINDEXFPROC)(GLfloat c);
+GLAPI PFNGLINDEXFPROC glad_glIndexf;
+#define glIndexf glad_glIndexf
+typedef void (APIENTRYP PFNGLINDEXFVPROC)(const GLfloat *c);
+GLAPI PFNGLINDEXFVPROC glad_glIndexfv;
+#define glIndexfv glad_glIndexfv
+typedef void (APIENTRYP PFNGLINDEXIPROC)(GLint c);
+GLAPI PFNGLINDEXIPROC glad_glIndexi;
+#define glIndexi glad_glIndexi
+typedef void (APIENTRYP PFNGLINDEXIVPROC)(const GLint *c);
+GLAPI PFNGLINDEXIVPROC glad_glIndexiv;
+#define glIndexiv glad_glIndexiv
+typedef void (APIENTRYP PFNGLINDEXSPROC)(GLshort c);
+GLAPI PFNGLINDEXSPROC glad_glIndexs;
+#define glIndexs glad_glIndexs
+typedef void (APIENTRYP PFNGLINDEXSVPROC)(const GLshort *c);
+GLAPI PFNGLINDEXSVPROC glad_glIndexsv;
+#define glIndexsv glad_glIndexsv
+typedef void (APIENTRYP PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz);
+GLAPI PFNGLNORMAL3BPROC glad_glNormal3b;
+#define glNormal3b glad_glNormal3b
+typedef void (APIENTRYP PFNGLNORMAL3BVPROC)(const GLbyte *v);
+GLAPI PFNGLNORMAL3BVPROC glad_glNormal3bv;
+#define glNormal3bv glad_glNormal3bv
+typedef void (APIENTRYP PFNGLNORMAL3DPROC)(GLdouble nx, GLdouble ny, GLdouble nz);
+GLAPI PFNGLNORMAL3DPROC glad_glNormal3d;
+#define glNormal3d glad_glNormal3d
+typedef void (APIENTRYP PFNGLNORMAL3DVPROC)(const GLdouble *v);
+GLAPI PFNGLNORMAL3DVPROC glad_glNormal3dv;
+#define glNormal3dv glad_glNormal3dv
+typedef void (APIENTRYP PFNGLNORMAL3FPROC)(GLfloat nx, GLfloat ny, GLfloat nz);
+GLAPI PFNGLNORMAL3FPROC glad_glNormal3f;
+#define glNormal3f glad_glNormal3f
+typedef void (APIENTRYP PFNGLNORMAL3FVPROC)(const GLfloat *v);
+GLAPI PFNGLNORMAL3FVPROC glad_glNormal3fv;
+#define glNormal3fv glad_glNormal3fv
+typedef void (APIENTRYP PFNGLNORMAL3IPROC)(GLint nx, GLint ny, GLint nz);
+GLAPI PFNGLNORMAL3IPROC glad_glNormal3i;
+#define glNormal3i glad_glNormal3i
+typedef void (APIENTRYP PFNGLNORMAL3IVPROC)(const GLint *v);
+GLAPI PFNGLNORMAL3IVPROC glad_glNormal3iv;
+#define glNormal3iv glad_glNormal3iv
+typedef void (APIENTRYP PFNGLNORMAL3SPROC)(GLshort nx, GLshort ny, GLshort nz);
+GLAPI PFNGLNORMAL3SPROC glad_glNormal3s;
+#define glNormal3s glad_glNormal3s
+typedef void (APIENTRYP PFNGLNORMAL3SVPROC)(const GLshort *v);
+GLAPI PFNGLNORMAL3SVPROC glad_glNormal3sv;
+#define glNormal3sv glad_glNormal3sv
+typedef void (APIENTRYP PFNGLRASTERPOS2DPROC)(GLdouble x, GLdouble y);
+GLAPI PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
+#define glRasterPos2d glad_glRasterPos2d
+typedef void (APIENTRYP PFNGLRASTERPOS2DVPROC)(const GLdouble *v);
+GLAPI PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
+#define glRasterPos2dv glad_glRasterPos2dv
+typedef void (APIENTRYP PFNGLRASTERPOS2FPROC)(GLfloat x, GLfloat y);
+GLAPI PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
+#define glRasterPos2f glad_glRasterPos2f
+typedef void (APIENTRYP PFNGLRASTERPOS2FVPROC)(const GLfloat *v);
+GLAPI PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
+#define glRasterPos2fv glad_glRasterPos2fv
+typedef void (APIENTRYP PFNGLRASTERPOS2IPROC)(GLint x, GLint y);
+GLAPI PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
+#define glRasterPos2i glad_glRasterPos2i
+typedef void (APIENTRYP PFNGLRASTERPOS2IVPROC)(const GLint *v);
+GLAPI PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
+#define glRasterPos2iv glad_glRasterPos2iv
+typedef void (APIENTRYP PFNGLRASTERPOS2SPROC)(GLshort x, GLshort y);
+GLAPI PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
+#define glRasterPos2s glad_glRasterPos2s
+typedef void (APIENTRYP PFNGLRASTERPOS2SVPROC)(const GLshort *v);
+GLAPI PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
+#define glRasterPos2sv glad_glRasterPos2sv
+typedef void (APIENTRYP PFNGLRASTERPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
+#define glRasterPos3d glad_glRasterPos3d
+typedef void (APIENTRYP PFNGLRASTERPOS3DVPROC)(const GLdouble *v);
+GLAPI PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
+#define glRasterPos3dv glad_glRasterPos3dv
+typedef void (APIENTRYP PFNGLRASTERPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
+#define glRasterPos3f glad_glRasterPos3f
+typedef void (APIENTRYP PFNGLRASTERPOS3FVPROC)(const GLfloat *v);
+GLAPI PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
+#define glRasterPos3fv glad_glRasterPos3fv
+typedef void (APIENTRYP PFNGLRASTERPOS3IPROC)(GLint x, GLint y, GLint z);
+GLAPI PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
+#define glRasterPos3i glad_glRasterPos3i
+typedef void (APIENTRYP PFNGLRASTERPOS3IVPROC)(const GLint *v);
+GLAPI PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
+#define glRasterPos3iv glad_glRasterPos3iv
+typedef void (APIENTRYP PFNGLRASTERPOS3SPROC)(GLshort x, GLshort y, GLshort z);
+GLAPI PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
+#define glRasterPos3s glad_glRasterPos3s
+typedef void (APIENTRYP PFNGLRASTERPOS3SVPROC)(const GLshort *v);
+GLAPI PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
+#define glRasterPos3sv glad_glRasterPos3sv
+typedef void (APIENTRYP PFNGLRASTERPOS4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
+#define glRasterPos4d glad_glRasterPos4d
+typedef void (APIENTRYP PFNGLRASTERPOS4DVPROC)(const GLdouble *v);
+GLAPI PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
+#define glRasterPos4dv glad_glRasterPos4dv
+typedef void (APIENTRYP PFNGLRASTERPOS4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
+#define glRasterPos4f glad_glRasterPos4f
+typedef void (APIENTRYP PFNGLRASTERPOS4FVPROC)(const GLfloat *v);
+GLAPI PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
+#define glRasterPos4fv glad_glRasterPos4fv
+typedef void (APIENTRYP PFNGLRASTERPOS4IPROC)(GLint x, GLint y, GLint z, GLint w);
+GLAPI PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
+#define glRasterPos4i glad_glRasterPos4i
+typedef void (APIENTRYP PFNGLRASTERPOS4IVPROC)(const GLint *v);
+GLAPI PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
+#define glRasterPos4iv glad_glRasterPos4iv
+typedef void (APIENTRYP PFNGLRASTERPOS4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
+#define glRasterPos4s glad_glRasterPos4s
+typedef void (APIENTRYP PFNGLRASTERPOS4SVPROC)(const GLshort *v);
+GLAPI PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
+#define glRasterPos4sv glad_glRasterPos4sv
+typedef void (APIENTRYP PFNGLRECTDPROC)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+GLAPI PFNGLRECTDPROC glad_glRectd;
+#define glRectd glad_glRectd
+typedef void (APIENTRYP PFNGLRECTDVPROC)(const GLdouble *v1, const GLdouble *v2);
+GLAPI PFNGLRECTDVPROC glad_glRectdv;
+#define glRectdv glad_glRectdv
+typedef void (APIENTRYP PFNGLRECTFPROC)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+GLAPI PFNGLRECTFPROC glad_glRectf;
+#define glRectf glad_glRectf
+typedef void (APIENTRYP PFNGLRECTFVPROC)(const GLfloat *v1, const GLfloat *v2);
+GLAPI PFNGLRECTFVPROC glad_glRectfv;
+#define glRectfv glad_glRectfv
+typedef void (APIENTRYP PFNGLRECTIPROC)(GLint x1, GLint y1, GLint x2, GLint y2);
+GLAPI PFNGLRECTIPROC glad_glRecti;
+#define glRecti glad_glRecti
+typedef void (APIENTRYP PFNGLRECTIVPROC)(const GLint *v1, const GLint *v2);
+GLAPI PFNGLRECTIVPROC glad_glRectiv;
+#define glRectiv glad_glRectiv
+typedef void (APIENTRYP PFNGLRECTSPROC)(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+GLAPI PFNGLRECTSPROC glad_glRects;
+#define glRects glad_glRects
+typedef void (APIENTRYP PFNGLRECTSVPROC)(const GLshort *v1, const GLshort *v2);
+GLAPI PFNGLRECTSVPROC glad_glRectsv;
+#define glRectsv glad_glRectsv
+typedef void (APIENTRYP PFNGLTEXCOORD1DPROC)(GLdouble s);
+GLAPI PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
+#define glTexCoord1d glad_glTexCoord1d
+typedef void (APIENTRYP PFNGLTEXCOORD1DVPROC)(const GLdouble *v);
+GLAPI PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
+#define glTexCoord1dv glad_glTexCoord1dv
+typedef void (APIENTRYP PFNGLTEXCOORD1FPROC)(GLfloat s);
+GLAPI PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
+#define glTexCoord1f glad_glTexCoord1f
+typedef void (APIENTRYP PFNGLTEXCOORD1FVPROC)(const GLfloat *v);
+GLAPI PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
+#define glTexCoord1fv glad_glTexCoord1fv
+typedef void (APIENTRYP PFNGLTEXCOORD1IPROC)(GLint s);
+GLAPI PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
+#define glTexCoord1i glad_glTexCoord1i
+typedef void (APIENTRYP PFNGLTEXCOORD1IVPROC)(const GLint *v);
+GLAPI PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
+#define glTexCoord1iv glad_glTexCoord1iv
+typedef void (APIENTRYP PFNGLTEXCOORD1SPROC)(GLshort s);
+GLAPI PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
+#define glTexCoord1s glad_glTexCoord1s
+typedef void (APIENTRYP PFNGLTEXCOORD1SVPROC)(const GLshort *v);
+GLAPI PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
+#define glTexCoord1sv glad_glTexCoord1sv
+typedef void (APIENTRYP PFNGLTEXCOORD2DPROC)(GLdouble s, GLdouble t);
+GLAPI PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
+#define glTexCoord2d glad_glTexCoord2d
+typedef void (APIENTRYP PFNGLTEXCOORD2DVPROC)(const GLdouble *v);
+GLAPI PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
+#define glTexCoord2dv glad_glTexCoord2dv
+typedef void (APIENTRYP PFNGLTEXCOORD2FPROC)(GLfloat s, GLfloat t);
+GLAPI PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
+#define glTexCoord2f glad_glTexCoord2f
+typedef void (APIENTRYP PFNGLTEXCOORD2FVPROC)(const GLfloat *v);
+GLAPI PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
+#define glTexCoord2fv glad_glTexCoord2fv
+typedef void (APIENTRYP PFNGLTEXCOORD2IPROC)(GLint s, GLint t);
+GLAPI PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
+#define glTexCoord2i glad_glTexCoord2i
+typedef void (APIENTRYP PFNGLTEXCOORD2IVPROC)(const GLint *v);
+GLAPI PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
+#define glTexCoord2iv glad_glTexCoord2iv
+typedef void (APIENTRYP PFNGLTEXCOORD2SPROC)(GLshort s, GLshort t);
+GLAPI PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
+#define glTexCoord2s glad_glTexCoord2s
+typedef void (APIENTRYP PFNGLTEXCOORD2SVPROC)(const GLshort *v);
+GLAPI PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
+#define glTexCoord2sv glad_glTexCoord2sv
+typedef void (APIENTRYP PFNGLTEXCOORD3DPROC)(GLdouble s, GLdouble t, GLdouble r);
+GLAPI PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
+#define glTexCoord3d glad_glTexCoord3d
+typedef void (APIENTRYP PFNGLTEXCOORD3DVPROC)(const GLdouble *v);
+GLAPI PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
+#define glTexCoord3dv glad_glTexCoord3dv
+typedef void (APIENTRYP PFNGLTEXCOORD3FPROC)(GLfloat s, GLfloat t, GLfloat r);
+GLAPI PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
+#define glTexCoord3f glad_glTexCoord3f
+typedef void (APIENTRYP PFNGLTEXCOORD3FVPROC)(const GLfloat *v);
+GLAPI PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
+#define glTexCoord3fv glad_glTexCoord3fv
+typedef void (APIENTRYP PFNGLTEXCOORD3IPROC)(GLint s, GLint t, GLint r);
+GLAPI PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
+#define glTexCoord3i glad_glTexCoord3i
+typedef void (APIENTRYP PFNGLTEXCOORD3IVPROC)(const GLint *v);
+GLAPI PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
+#define glTexCoord3iv glad_glTexCoord3iv
+typedef void (APIENTRYP PFNGLTEXCOORD3SPROC)(GLshort s, GLshort t, GLshort r);
+GLAPI PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
+#define glTexCoord3s glad_glTexCoord3s
+typedef void (APIENTRYP PFNGLTEXCOORD3SVPROC)(const GLshort *v);
+GLAPI PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
+#define glTexCoord3sv glad_glTexCoord3sv
+typedef void (APIENTRYP PFNGLTEXCOORD4DPROC)(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
+#define glTexCoord4d glad_glTexCoord4d
+typedef void (APIENTRYP PFNGLTEXCOORD4DVPROC)(const GLdouble *v);
+GLAPI PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
+#define glTexCoord4dv glad_glTexCoord4dv
+typedef void (APIENTRYP PFNGLTEXCOORD4FPROC)(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
+#define glTexCoord4f glad_glTexCoord4f
+typedef void (APIENTRYP PFNGLTEXCOORD4FVPROC)(const GLfloat *v);
+GLAPI PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
+#define glTexCoord4fv glad_glTexCoord4fv
+typedef void (APIENTRYP PFNGLTEXCOORD4IPROC)(GLint s, GLint t, GLint r, GLint q);
+GLAPI PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
+#define glTexCoord4i glad_glTexCoord4i
+typedef void (APIENTRYP PFNGLTEXCOORD4IVPROC)(const GLint *v);
+GLAPI PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
+#define glTexCoord4iv glad_glTexCoord4iv
+typedef void (APIENTRYP PFNGLTEXCOORD4SPROC)(GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
+#define glTexCoord4s glad_glTexCoord4s
+typedef void (APIENTRYP PFNGLTEXCOORD4SVPROC)(const GLshort *v);
+GLAPI PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
+#define glTexCoord4sv glad_glTexCoord4sv
+typedef void (APIENTRYP PFNGLVERTEX2DPROC)(GLdouble x, GLdouble y);
+GLAPI PFNGLVERTEX2DPROC glad_glVertex2d;
+#define glVertex2d glad_glVertex2d
+typedef void (APIENTRYP PFNGLVERTEX2DVPROC)(const GLdouble *v);
+GLAPI PFNGLVERTEX2DVPROC glad_glVertex2dv;
+#define glVertex2dv glad_glVertex2dv
+typedef void (APIENTRYP PFNGLVERTEX2FPROC)(GLfloat x, GLfloat y);
+GLAPI PFNGLVERTEX2FPROC glad_glVertex2f;
+#define glVertex2f glad_glVertex2f
+typedef void (APIENTRYP PFNGLVERTEX2FVPROC)(const GLfloat *v);
+GLAPI PFNGLVERTEX2FVPROC glad_glVertex2fv;
+#define glVertex2fv glad_glVertex2fv
+typedef void (APIENTRYP PFNGLVERTEX2IPROC)(GLint x, GLint y);
+GLAPI PFNGLVERTEX2IPROC glad_glVertex2i;
+#define glVertex2i glad_glVertex2i
+typedef void (APIENTRYP PFNGLVERTEX2IVPROC)(const GLint *v);
+GLAPI PFNGLVERTEX2IVPROC glad_glVertex2iv;
+#define glVertex2iv glad_glVertex2iv
+typedef void (APIENTRYP PFNGLVERTEX2SPROC)(GLshort x, GLshort y);
+GLAPI PFNGLVERTEX2SPROC glad_glVertex2s;
+#define glVertex2s glad_glVertex2s
+typedef void (APIENTRYP PFNGLVERTEX2SVPROC)(const GLshort *v);
+GLAPI PFNGLVERTEX2SVPROC glad_glVertex2sv;
+#define glVertex2sv glad_glVertex2sv
+typedef void (APIENTRYP PFNGLVERTEX3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLVERTEX3DPROC glad_glVertex3d;
+#define glVertex3d glad_glVertex3d
+typedef void (APIENTRYP PFNGLVERTEX3DVPROC)(const GLdouble *v);
+GLAPI PFNGLVERTEX3DVPROC glad_glVertex3dv;
+#define glVertex3dv glad_glVertex3dv
+typedef void (APIENTRYP PFNGLVERTEX3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLVERTEX3FPROC glad_glVertex3f;
+#define glVertex3f glad_glVertex3f
+typedef void (APIENTRYP PFNGLVERTEX3FVPROC)(const GLfloat *v);
+GLAPI PFNGLVERTEX3FVPROC glad_glVertex3fv;
+#define glVertex3fv glad_glVertex3fv
+typedef void (APIENTRYP PFNGLVERTEX3IPROC)(GLint x, GLint y, GLint z);
+GLAPI PFNGLVERTEX3IPROC glad_glVertex3i;
+#define glVertex3i glad_glVertex3i
+typedef void (APIENTRYP PFNGLVERTEX3IVPROC)(const GLint *v);
+GLAPI PFNGLVERTEX3IVPROC glad_glVertex3iv;
+#define glVertex3iv glad_glVertex3iv
+typedef void (APIENTRYP PFNGLVERTEX3SPROC)(GLshort x, GLshort y, GLshort z);
+GLAPI PFNGLVERTEX3SPROC glad_glVertex3s;
+#define glVertex3s glad_glVertex3s
+typedef void (APIENTRYP PFNGLVERTEX3SVPROC)(const GLshort *v);
+GLAPI PFNGLVERTEX3SVPROC glad_glVertex3sv;
+#define glVertex3sv glad_glVertex3sv
+typedef void (APIENTRYP PFNGLVERTEX4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI PFNGLVERTEX4DPROC glad_glVertex4d;
+#define glVertex4d glad_glVertex4d
+typedef void (APIENTRYP PFNGLVERTEX4DVPROC)(const GLdouble *v);
+GLAPI PFNGLVERTEX4DVPROC glad_glVertex4dv;
+#define glVertex4dv glad_glVertex4dv
+typedef void (APIENTRYP PFNGLVERTEX4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI PFNGLVERTEX4FPROC glad_glVertex4f;
+#define glVertex4f glad_glVertex4f
+typedef void (APIENTRYP PFNGLVERTEX4FVPROC)(const GLfloat *v);
+GLAPI PFNGLVERTEX4FVPROC glad_glVertex4fv;
+#define glVertex4fv glad_glVertex4fv
+typedef void (APIENTRYP PFNGLVERTEX4IPROC)(GLint x, GLint y, GLint z, GLint w);
+GLAPI PFNGLVERTEX4IPROC glad_glVertex4i;
+#define glVertex4i glad_glVertex4i
+typedef void (APIENTRYP PFNGLVERTEX4IVPROC)(const GLint *v);
+GLAPI PFNGLVERTEX4IVPROC glad_glVertex4iv;
+#define glVertex4iv glad_glVertex4iv
+typedef void (APIENTRYP PFNGLVERTEX4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI PFNGLVERTEX4SPROC glad_glVertex4s;
+#define glVertex4s glad_glVertex4s
+typedef void (APIENTRYP PFNGLVERTEX4SVPROC)(const GLshort *v);
+GLAPI PFNGLVERTEX4SVPROC glad_glVertex4sv;
+#define glVertex4sv glad_glVertex4sv
+typedef void (APIENTRYP PFNGLCLIPPLANEPROC)(GLenum plane, const GLdouble *equation);
+GLAPI PFNGLCLIPPLANEPROC glad_glClipPlane;
+#define glClipPlane glad_glClipPlane
+typedef void (APIENTRYP PFNGLCOLORMATERIALPROC)(GLenum face, GLenum mode);
+GLAPI PFNGLCOLORMATERIALPROC glad_glColorMaterial;
+#define glColorMaterial glad_glColorMaterial
+typedef void (APIENTRYP PFNGLFOGFPROC)(GLenum pname, GLfloat param);
+GLAPI PFNGLFOGFPROC glad_glFogf;
+#define glFogf glad_glFogf
+typedef void (APIENTRYP PFNGLFOGFVPROC)(GLenum pname, const GLfloat *params);
+GLAPI PFNGLFOGFVPROC glad_glFogfv;
+#define glFogfv glad_glFogfv
+typedef void (APIENTRYP PFNGLFOGIPROC)(GLenum pname, GLint param);
+GLAPI PFNGLFOGIPROC glad_glFogi;
+#define glFogi glad_glFogi
+typedef void (APIENTRYP PFNGLFOGIVPROC)(GLenum pname, const GLint *params);
+GLAPI PFNGLFOGIVPROC glad_glFogiv;
+#define glFogiv glad_glFogiv
+typedef void (APIENTRYP PFNGLLIGHTFPROC)(GLenum light, GLenum pname, GLfloat param);
+GLAPI PFNGLLIGHTFPROC glad_glLightf;
+#define glLightf glad_glLightf
+typedef void (APIENTRYP PFNGLLIGHTFVPROC)(GLenum light, GLenum pname, const GLfloat *params);
+GLAPI PFNGLLIGHTFVPROC glad_glLightfv;
+#define glLightfv glad_glLightfv
+typedef void (APIENTRYP PFNGLLIGHTIPROC)(GLenum light, GLenum pname, GLint param);
+GLAPI PFNGLLIGHTIPROC glad_glLighti;
+#define glLighti glad_glLighti
+typedef void (APIENTRYP PFNGLLIGHTIVPROC)(GLenum light, GLenum pname, const GLint *params);
+GLAPI PFNGLLIGHTIVPROC glad_glLightiv;
+#define glLightiv glad_glLightiv
+typedef void (APIENTRYP PFNGLLIGHTMODELFPROC)(GLenum pname, GLfloat param);
+GLAPI PFNGLLIGHTMODELFPROC glad_glLightModelf;
+#define glLightModelf glad_glLightModelf
+typedef void (APIENTRYP PFNGLLIGHTMODELFVPROC)(GLenum pname, const GLfloat *params);
+GLAPI PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
+#define glLightModelfv glad_glLightModelfv
+typedef void (APIENTRYP PFNGLLIGHTMODELIPROC)(GLenum pname, GLint param);
+GLAPI PFNGLLIGHTMODELIPROC glad_glLightModeli;
+#define glLightModeli glad_glLightModeli
+typedef void (APIENTRYP PFNGLLIGHTMODELIVPROC)(GLenum pname, const GLint *params);
+GLAPI PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
+#define glLightModeliv glad_glLightModeliv
+typedef void (APIENTRYP PFNGLLINESTIPPLEPROC)(GLint factor, GLushort pattern);
+GLAPI PFNGLLINESTIPPLEPROC glad_glLineStipple;
+#define glLineStipple glad_glLineStipple
+typedef void (APIENTRYP PFNGLMATERIALFPROC)(GLenum face, GLenum pname, GLfloat param);
+GLAPI PFNGLMATERIALFPROC glad_glMaterialf;
+#define glMaterialf glad_glMaterialf
+typedef void (APIENTRYP PFNGLMATERIALFVPROC)(GLenum face, GLenum pname, const GLfloat *params);
+GLAPI PFNGLMATERIALFVPROC glad_glMaterialfv;
+#define glMaterialfv glad_glMaterialfv
+typedef void (APIENTRYP PFNGLMATERIALIPROC)(GLenum face, GLenum pname, GLint param);
+GLAPI PFNGLMATERIALIPROC glad_glMateriali;
+#define glMateriali glad_glMateriali
+typedef void (APIENTRYP PFNGLMATERIALIVPROC)(GLenum face, GLenum pname, const GLint *params);
+GLAPI PFNGLMATERIALIVPROC glad_glMaterialiv;
+#define glMaterialiv glad_glMaterialiv
+typedef void (APIENTRYP PFNGLPOLYGONSTIPPLEPROC)(const GLubyte *mask);
+GLAPI PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
+#define glPolygonStipple glad_glPolygonStipple
+typedef void (APIENTRYP PFNGLSHADEMODELPROC)(GLenum mode);
+GLAPI PFNGLSHADEMODELPROC glad_glShadeModel;
+#define glShadeModel glad_glShadeModel
+typedef void (APIENTRYP PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param);
+GLAPI PFNGLTEXENVFPROC glad_glTexEnvf;
+#define glTexEnvf glad_glTexEnvf
+typedef void (APIENTRYP PFNGLTEXENVFVPROC)(GLenum target, GLenum pname, const GLfloat *params);
+GLAPI PFNGLTEXENVFVPROC glad_glTexEnvfv;
+#define glTexEnvfv glad_glTexEnvfv
+typedef void (APIENTRYP PFNGLTEXENVIPROC)(GLenum target, GLenum pname, GLint param);
+GLAPI PFNGLTEXENVIPROC glad_glTexEnvi;
+#define glTexEnvi glad_glTexEnvi
+typedef void (APIENTRYP PFNGLTEXENVIVPROC)(GLenum target, GLenum pname, const GLint *params);
+GLAPI PFNGLTEXENVIVPROC glad_glTexEnviv;
+#define glTexEnviv glad_glTexEnviv
+typedef void (APIENTRYP PFNGLTEXGENDPROC)(GLenum coord, GLenum pname, GLdouble param);
+GLAPI PFNGLTEXGENDPROC glad_glTexGend;
+#define glTexGend glad_glTexGend
+typedef void (APIENTRYP PFNGLTEXGENDVPROC)(GLenum coord, GLenum pname, const GLdouble *params);
+GLAPI PFNGLTEXGENDVPROC glad_glTexGendv;
+#define glTexGendv glad_glTexGendv
+typedef void (APIENTRYP PFNGLTEXGENFPROC)(GLenum coord, GLenum pname, GLfloat param);
+GLAPI PFNGLTEXGENFPROC glad_glTexGenf;
+#define glTexGenf glad_glTexGenf
+typedef void (APIENTRYP PFNGLTEXGENFVPROC)(GLenum coord, GLenum pname, const GLfloat *params);
+GLAPI PFNGLTEXGENFVPROC glad_glTexGenfv;
+#define glTexGenfv glad_glTexGenfv
+typedef void (APIENTRYP PFNGLTEXGENIPROC)(GLenum coord, GLenum pname, GLint param);
+GLAPI PFNGLTEXGENIPROC glad_glTexGeni;
+#define glTexGeni glad_glTexGeni
+typedef void (APIENTRYP PFNGLTEXGENIVPROC)(GLenum coord, GLenum pname, const GLint *params);
+GLAPI PFNGLTEXGENIVPROC glad_glTexGeniv;
+#define glTexGeniv glad_glTexGeniv
+typedef void (APIENTRYP PFNGLFEEDBACKBUFFERPROC)(GLsizei size, GLenum type, GLfloat *buffer);
+GLAPI PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
+#define glFeedbackBuffer glad_glFeedbackBuffer
+typedef void (APIENTRYP PFNGLSELECTBUFFERPROC)(GLsizei size, GLuint *buffer);
+GLAPI PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
+#define glSelectBuffer glad_glSelectBuffer
+typedef GLint (APIENTRYP PFNGLRENDERMODEPROC)(GLenum mode);
+GLAPI PFNGLRENDERMODEPROC glad_glRenderMode;
+#define glRenderMode glad_glRenderMode
+typedef void (APIENTRYP PFNGLINITNAMESPROC)(void);
+GLAPI PFNGLINITNAMESPROC glad_glInitNames;
+#define glInitNames glad_glInitNames
+typedef void (APIENTRYP PFNGLLOADNAMEPROC)(GLuint name);
+GLAPI PFNGLLOADNAMEPROC glad_glLoadName;
+#define glLoadName glad_glLoadName
+typedef void (APIENTRYP PFNGLPASSTHROUGHPROC)(GLfloat token);
+GLAPI PFNGLPASSTHROUGHPROC glad_glPassThrough;
+#define glPassThrough glad_glPassThrough
+typedef void (APIENTRYP PFNGLPOPNAMEPROC)(void);
+GLAPI PFNGLPOPNAMEPROC glad_glPopName;
+#define glPopName glad_glPopName
+typedef void (APIENTRYP PFNGLPUSHNAMEPROC)(GLuint name);
+GLAPI PFNGLPUSHNAMEPROC glad_glPushName;
+#define glPushName glad_glPushName
+typedef void (APIENTRYP PFNGLCLEARACCUMPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI PFNGLCLEARACCUMPROC glad_glClearAccum;
+#define glClearAccum glad_glClearAccum
+typedef void (APIENTRYP PFNGLCLEARINDEXPROC)(GLfloat c);
+GLAPI PFNGLCLEARINDEXPROC glad_glClearIndex;
+#define glClearIndex glad_glClearIndex
+typedef void (APIENTRYP PFNGLINDEXMASKPROC)(GLuint mask);
+GLAPI PFNGLINDEXMASKPROC glad_glIndexMask;
+#define glIndexMask glad_glIndexMask
+typedef void (APIENTRYP PFNGLACCUMPROC)(GLenum op, GLfloat value);
+GLAPI PFNGLACCUMPROC glad_glAccum;
+#define glAccum glad_glAccum
+typedef void (APIENTRYP PFNGLPOPATTRIBPROC)(void);
+GLAPI PFNGLPOPATTRIBPROC glad_glPopAttrib;
+#define glPopAttrib glad_glPopAttrib
+typedef void (APIENTRYP PFNGLPUSHATTRIBPROC)(GLbitfield mask);
+GLAPI PFNGLPUSHATTRIBPROC glad_glPushAttrib;
+#define glPushAttrib glad_glPushAttrib
+typedef void (APIENTRYP PFNGLMAP1DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+GLAPI PFNGLMAP1DPROC glad_glMap1d;
+#define glMap1d glad_glMap1d
+typedef void (APIENTRYP PFNGLMAP1FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+GLAPI PFNGLMAP1FPROC glad_glMap1f;
+#define glMap1f glad_glMap1f
+typedef void (APIENTRYP PFNGLMAP2DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+GLAPI PFNGLMAP2DPROC glad_glMap2d;
+#define glMap2d glad_glMap2d
+typedef void (APIENTRYP PFNGLMAP2FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+GLAPI PFNGLMAP2FPROC glad_glMap2f;
+#define glMap2f glad_glMap2f
+typedef void (APIENTRYP PFNGLMAPGRID1DPROC)(GLint un, GLdouble u1, GLdouble u2);
+GLAPI PFNGLMAPGRID1DPROC glad_glMapGrid1d;
+#define glMapGrid1d glad_glMapGrid1d
+typedef void (APIENTRYP PFNGLMAPGRID1FPROC)(GLint un, GLfloat u1, GLfloat u2);
+GLAPI PFNGLMAPGRID1FPROC glad_glMapGrid1f;
+#define glMapGrid1f glad_glMapGrid1f
+typedef void (APIENTRYP PFNGLMAPGRID2DPROC)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+GLAPI PFNGLMAPGRID2DPROC glad_glMapGrid2d;
+#define glMapGrid2d glad_glMapGrid2d
+typedef void (APIENTRYP PFNGLMAPGRID2FPROC)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+GLAPI PFNGLMAPGRID2FPROC glad_glMapGrid2f;
+#define glMapGrid2f glad_glMapGrid2f
+typedef void (APIENTRYP PFNGLEVALCOORD1DPROC)(GLdouble u);
+GLAPI PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
+#define glEvalCoord1d glad_glEvalCoord1d
+typedef void (APIENTRYP PFNGLEVALCOORD1DVPROC)(const GLdouble *u);
+GLAPI PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
+#define glEvalCoord1dv glad_glEvalCoord1dv
+typedef void (APIENTRYP PFNGLEVALCOORD1FPROC)(GLfloat u);
+GLAPI PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
+#define glEvalCoord1f glad_glEvalCoord1f
+typedef void (APIENTRYP PFNGLEVALCOORD1FVPROC)(const GLfloat *u);
+GLAPI PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
+#define glEvalCoord1fv glad_glEvalCoord1fv
+typedef void (APIENTRYP PFNGLEVALCOORD2DPROC)(GLdouble u, GLdouble v);
+GLAPI PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
+#define glEvalCoord2d glad_glEvalCoord2d
+typedef void (APIENTRYP PFNGLEVALCOORD2DVPROC)(const GLdouble *u);
+GLAPI PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
+#define glEvalCoord2dv glad_glEvalCoord2dv
+typedef void (APIENTRYP PFNGLEVALCOORD2FPROC)(GLfloat u, GLfloat v);
+GLAPI PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
+#define glEvalCoord2f glad_glEvalCoord2f
+typedef void (APIENTRYP PFNGLEVALCOORD2FVPROC)(const GLfloat *u);
+GLAPI PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
+#define glEvalCoord2fv glad_glEvalCoord2fv
+typedef void (APIENTRYP PFNGLEVALMESH1PROC)(GLenum mode, GLint i1, GLint i2);
+GLAPI PFNGLEVALMESH1PROC glad_glEvalMesh1;
+#define glEvalMesh1 glad_glEvalMesh1
+typedef void (APIENTRYP PFNGLEVALPOINT1PROC)(GLint i);
+GLAPI PFNGLEVALPOINT1PROC glad_glEvalPoint1;
+#define glEvalPoint1 glad_glEvalPoint1
+typedef void (APIENTRYP PFNGLEVALMESH2PROC)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+GLAPI PFNGLEVALMESH2PROC glad_glEvalMesh2;
+#define glEvalMesh2 glad_glEvalMesh2
+typedef void (APIENTRYP PFNGLEVALPOINT2PROC)(GLint i, GLint j);
+GLAPI PFNGLEVALPOINT2PROC glad_glEvalPoint2;
+#define glEvalPoint2 glad_glEvalPoint2
+typedef void (APIENTRYP PFNGLALPHAFUNCPROC)(GLenum func, GLfloat ref);
+GLAPI PFNGLALPHAFUNCPROC glad_glAlphaFunc;
+#define glAlphaFunc glad_glAlphaFunc
+typedef void (APIENTRYP PFNGLPIXELZOOMPROC)(GLfloat xfactor, GLfloat yfactor);
+GLAPI PFNGLPIXELZOOMPROC glad_glPixelZoom;
+#define glPixelZoom glad_glPixelZoom
+typedef void (APIENTRYP PFNGLPIXELTRANSFERFPROC)(GLenum pname, GLfloat param);
+GLAPI PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
+#define glPixelTransferf glad_glPixelTransferf
+typedef void (APIENTRYP PFNGLPIXELTRANSFERIPROC)(GLenum pname, GLint param);
+GLAPI PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
+#define glPixelTransferi glad_glPixelTransferi
+typedef void (APIENTRYP PFNGLPIXELMAPFVPROC)(GLenum map, GLsizei mapsize, const GLfloat *values);
+GLAPI PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
+#define glPixelMapfv glad_glPixelMapfv
+typedef void (APIENTRYP PFNGLPIXELMAPUIVPROC)(GLenum map, GLsizei mapsize, const GLuint *values);
+GLAPI PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
+#define glPixelMapuiv glad_glPixelMapuiv
+typedef void (APIENTRYP PFNGLPIXELMAPUSVPROC)(GLenum map, GLsizei mapsize, const GLushort *values);
+GLAPI PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
+#define glPixelMapusv glad_glPixelMapusv
+typedef void (APIENTRYP PFNGLCOPYPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+GLAPI PFNGLCOPYPIXELSPROC glad_glCopyPixels;
+#define glCopyPixels glad_glCopyPixels
+typedef void (APIENTRYP PFNGLDRAWPIXELSPROC)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLDRAWPIXELSPROC glad_glDrawPixels;
+#define glDrawPixels glad_glDrawPixels
+typedef void (APIENTRYP PFNGLGETCLIPPLANEPROC)(GLenum plane, GLdouble *equation);
+GLAPI PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
+#define glGetClipPlane glad_glGetClipPlane
+typedef void (APIENTRYP PFNGLGETLIGHTFVPROC)(GLenum light, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETLIGHTFVPROC glad_glGetLightfv;
+#define glGetLightfv glad_glGetLightfv
+typedef void (APIENTRYP PFNGLGETLIGHTIVPROC)(GLenum light, GLenum pname, GLint *params);
+GLAPI PFNGLGETLIGHTIVPROC glad_glGetLightiv;
+#define glGetLightiv glad_glGetLightiv
+typedef void (APIENTRYP PFNGLGETMAPDVPROC)(GLenum target, GLenum query, GLdouble *v);
+GLAPI PFNGLGETMAPDVPROC glad_glGetMapdv;
+#define glGetMapdv glad_glGetMapdv
+typedef void (APIENTRYP PFNGLGETMAPFVPROC)(GLenum target, GLenum query, GLfloat *v);
+GLAPI PFNGLGETMAPFVPROC glad_glGetMapfv;
+#define glGetMapfv glad_glGetMapfv
+typedef void (APIENTRYP PFNGLGETMAPIVPROC)(GLenum target, GLenum query, GLint *v);
+GLAPI PFNGLGETMAPIVPROC glad_glGetMapiv;
+#define glGetMapiv glad_glGetMapiv
+typedef void (APIENTRYP PFNGLGETMATERIALFVPROC)(GLenum face, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
+#define glGetMaterialfv glad_glGetMaterialfv
+typedef void (APIENTRYP PFNGLGETMATERIALIVPROC)(GLenum face, GLenum pname, GLint *params);
+GLAPI PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
+#define glGetMaterialiv glad_glGetMaterialiv
+typedef void (APIENTRYP PFNGLGETPIXELMAPFVPROC)(GLenum map, GLfloat *values);
+GLAPI PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
+#define glGetPixelMapfv glad_glGetPixelMapfv
+typedef void (APIENTRYP PFNGLGETPIXELMAPUIVPROC)(GLenum map, GLuint *values);
+GLAPI PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
+#define glGetPixelMapuiv glad_glGetPixelMapuiv
+typedef void (APIENTRYP PFNGLGETPIXELMAPUSVPROC)(GLenum map, GLushort *values);
+GLAPI PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
+#define glGetPixelMapusv glad_glGetPixelMapusv
+typedef void (APIENTRYP PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte *mask);
+GLAPI PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
+#define glGetPolygonStipple glad_glGetPolygonStipple
+typedef void (APIENTRYP PFNGLGETTEXENVFVPROC)(GLenum target, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
+#define glGetTexEnvfv glad_glGetTexEnvfv
+typedef void (APIENTRYP PFNGLGETTEXENVIVPROC)(GLenum target, GLenum pname, GLint *params);
+GLAPI PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
+#define glGetTexEnviv glad_glGetTexEnviv
+typedef void (APIENTRYP PFNGLGETTEXGENDVPROC)(GLenum coord, GLenum pname, GLdouble *params);
+GLAPI PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
+#define glGetTexGendv glad_glGetTexGendv
+typedef void (APIENTRYP PFNGLGETTEXGENFVPROC)(GLenum coord, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
+#define glGetTexGenfv glad_glGetTexGenfv
+typedef void (APIENTRYP PFNGLGETTEXGENIVPROC)(GLenum coord, GLenum pname, GLint *params);
+GLAPI PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
+#define glGetTexGeniv glad_glGetTexGeniv
+typedef GLboolean (APIENTRYP PFNGLISLISTPROC)(GLuint list);
+GLAPI PFNGLISLISTPROC glad_glIsList;
+#define glIsList glad_glIsList
+typedef void (APIENTRYP PFNGLFRUSTUMPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI PFNGLFRUSTUMPROC glad_glFrustum;
+#define glFrustum glad_glFrustum
+typedef void (APIENTRYP PFNGLLOADIDENTITYPROC)(void);
+GLAPI PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
+#define glLoadIdentity glad_glLoadIdentity
+typedef void (APIENTRYP PFNGLLOADMATRIXFPROC)(const GLfloat *m);
+GLAPI PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
+#define glLoadMatrixf glad_glLoadMatrixf
+typedef void (APIENTRYP PFNGLLOADMATRIXDPROC)(const GLdouble *m);
+GLAPI PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
+#define glLoadMatrixd glad_glLoadMatrixd
+typedef void (APIENTRYP PFNGLMATRIXMODEPROC)(GLenum mode);
+GLAPI PFNGLMATRIXMODEPROC glad_glMatrixMode;
+#define glMatrixMode glad_glMatrixMode
+typedef void (APIENTRYP PFNGLMULTMATRIXFPROC)(const GLfloat *m);
+GLAPI PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
+#define glMultMatrixf glad_glMultMatrixf
+typedef void (APIENTRYP PFNGLMULTMATRIXDPROC)(const GLdouble *m);
+GLAPI PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
+#define glMultMatrixd glad_glMultMatrixd
+typedef void (APIENTRYP PFNGLORTHOPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLAPI PFNGLORTHOPROC glad_glOrtho;
+#define glOrtho glad_glOrtho
+typedef void (APIENTRYP PFNGLPOPMATRIXPROC)(void);
+GLAPI PFNGLPOPMATRIXPROC glad_glPopMatrix;
+#define glPopMatrix glad_glPopMatrix
+typedef void (APIENTRYP PFNGLPUSHMATRIXPROC)(void);
+GLAPI PFNGLPUSHMATRIXPROC glad_glPushMatrix;
+#define glPushMatrix glad_glPushMatrix
+typedef void (APIENTRYP PFNGLROTATEDPROC)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLROTATEDPROC glad_glRotated;
+#define glRotated glad_glRotated
+typedef void (APIENTRYP PFNGLROTATEFPROC)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLROTATEFPROC glad_glRotatef;
+#define glRotatef glad_glRotatef
+typedef void (APIENTRYP PFNGLSCALEDPROC)(GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLSCALEDPROC glad_glScaled;
+#define glScaled glad_glScaled
+typedef void (APIENTRYP PFNGLSCALEFPROC)(GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLSCALEFPROC glad_glScalef;
+#define glScalef glad_glScalef
+typedef void (APIENTRYP PFNGLTRANSLATEDPROC)(GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLTRANSLATEDPROC glad_glTranslated;
+#define glTranslated glad_glTranslated
+typedef void (APIENTRYP PFNGLTRANSLATEFPROC)(GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLTRANSLATEFPROC glad_glTranslatef;
+#define glTranslatef glad_glTranslatef
+#endif
+#ifndef GL_VERSION_1_1
+#define GL_VERSION_1_1 1
+GLAPI int GLAD_GL_VERSION_1_1;
+typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count);
+GLAPI PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices);
+GLAPI PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+typedef void (APIENTRYP PFNGLGETPOINTERVPROC)(GLenum pname, void **params);
+GLAPI PFNGLGETPOINTERVPROC glad_glGetPointerv;
+#define glGetPointerv glad_glGetPointerv
+typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units);
+GLAPI PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
+GLAPI PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
+#define glCopyTexImage1D glad_glCopyTexImage1D
+typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GLAPI PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+GLAPI PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
+#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
+#define glTexSubImage1D glad_glTexSubImage1D
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture);
+GLAPI PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures);
+GLAPI PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei n, GLuint *textures);
+GLAPI PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint texture);
+GLAPI PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+typedef void (APIENTRYP PFNGLARRAYELEMENTPROC)(GLint i);
+GLAPI PFNGLARRAYELEMENTPROC glad_glArrayElement;
+#define glArrayElement glad_glArrayElement
+typedef void (APIENTRYP PFNGLCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLCOLORPOINTERPROC glad_glColorPointer;
+#define glColorPointer glad_glColorPointer
+typedef void (APIENTRYP PFNGLDISABLECLIENTSTATEPROC)(GLenum array);
+GLAPI PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
+#define glDisableClientState glad_glDisableClientState
+typedef void (APIENTRYP PFNGLEDGEFLAGPOINTERPROC)(GLsizei stride, const void *pointer);
+GLAPI PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
+#define glEdgeFlagPointer glad_glEdgeFlagPointer
+typedef void (APIENTRYP PFNGLENABLECLIENTSTATEPROC)(GLenum array);
+GLAPI PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
+#define glEnableClientState glad_glEnableClientState
+typedef void (APIENTRYP PFNGLINDEXPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLINDEXPOINTERPROC glad_glIndexPointer;
+#define glIndexPointer glad_glIndexPointer
+typedef void (APIENTRYP PFNGLINTERLEAVEDARRAYSPROC)(GLenum format, GLsizei stride, const void *pointer);
+GLAPI PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
+#define glInterleavedArrays glad_glInterleavedArrays
+typedef void (APIENTRYP PFNGLNORMALPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLNORMALPOINTERPROC glad_glNormalPointer;
+#define glNormalPointer glad_glNormalPointer
+typedef void (APIENTRYP PFNGLTEXCOORDPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
+#define glTexCoordPointer glad_glTexCoordPointer
+typedef void (APIENTRYP PFNGLVERTEXPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
+#define glVertexPointer glad_glVertexPointer
+typedef GLboolean (APIENTRYP PFNGLARETEXTURESRESIDENTPROC)(GLsizei n, const GLuint *textures, GLboolean *residences);
+GLAPI PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
+#define glAreTexturesResident glad_glAreTexturesResident
+typedef void (APIENTRYP PFNGLPRIORITIZETEXTURESPROC)(GLsizei n, const GLuint *textures, const GLfloat *priorities);
+GLAPI PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
+#define glPrioritizeTextures glad_glPrioritizeTextures
+typedef void (APIENTRYP PFNGLINDEXUBPROC)(GLubyte c);
+GLAPI PFNGLINDEXUBPROC glad_glIndexub;
+#define glIndexub glad_glIndexub
+typedef void (APIENTRYP PFNGLINDEXUBVPROC)(const GLubyte *c);
+GLAPI PFNGLINDEXUBVPROC glad_glIndexubv;
+#define glIndexubv glad_glIndexubv
+typedef void (APIENTRYP PFNGLPOPCLIENTATTRIBPROC)(void);
+GLAPI PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
+#define glPopClientAttrib glad_glPopClientAttrib
+typedef void (APIENTRYP PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield mask);
+GLAPI PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
+#define glPushClientAttrib glad_glPushClientAttrib
+#endif
+#ifndef GL_VERSION_1_2
+#define GL_VERSION_1_2 1
+GLAPI int GLAD_GL_VERSION_1_2;
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GLAPI PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
+#define glDrawRangeElements glad_glDrawRangeElements
+typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
+#define glTexImage3D glad_glTexImage3D
+typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GLAPI PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
+#define glTexSubImage3D glad_glTexSubImage3D
+typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
+#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
+#endif
+#ifndef GL_VERSION_1_3
+#define GL_VERSION_1_3 1
+GLAPI int GLAD_GL_VERSION_1_3;
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture);
+GLAPI PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert);
+GLAPI PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GLAPI PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
+#define glCompressedTexImage3D glad_glCompressedTexImage3D
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GLAPI PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data);
+GLAPI PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
+#define glCompressedTexImage1D glad_glCompressedTexImage1D
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
+#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data);
+GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
+#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
+typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void *img);
+GLAPI PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
+#define glGetCompressedTexImage glad_glGetCompressedTexImage
+typedef void (APIENTRYP PFNGLCLIENTACTIVETEXTUREPROC)(GLenum texture);
+GLAPI PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
+#define glClientActiveTexture glad_glClientActiveTexture
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DPROC)(GLenum target, GLdouble s);
+GLAPI PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
+#define glMultiTexCoord1d glad_glMultiTexCoord1d
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1DVPROC)(GLenum target, const GLdouble *v);
+GLAPI PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
+#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FPROC)(GLenum target, GLfloat s);
+GLAPI PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
+#define glMultiTexCoord1f glad_glMultiTexCoord1f
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1FVPROC)(GLenum target, const GLfloat *v);
+GLAPI PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
+#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IPROC)(GLenum target, GLint s);
+GLAPI PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
+#define glMultiTexCoord1i glad_glMultiTexCoord1i
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1IVPROC)(GLenum target, const GLint *v);
+GLAPI PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
+#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SPROC)(GLenum target, GLshort s);
+GLAPI PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
+#define glMultiTexCoord1s glad_glMultiTexCoord1s
+typedef void (APIENTRYP PFNGLMULTITEXCOORD1SVPROC)(GLenum target, const GLshort *v);
+GLAPI PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
+#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DPROC)(GLenum target, GLdouble s, GLdouble t);
+GLAPI PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
+#define glMultiTexCoord2d glad_glMultiTexCoord2d
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2DVPROC)(GLenum target, const GLdouble *v);
+GLAPI PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
+#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FPROC)(GLenum target, GLfloat s, GLfloat t);
+GLAPI PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
+#define glMultiTexCoord2f glad_glMultiTexCoord2f
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2FVPROC)(GLenum target, const GLfloat *v);
+GLAPI PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
+#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IPROC)(GLenum target, GLint s, GLint t);
+GLAPI PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
+#define glMultiTexCoord2i glad_glMultiTexCoord2i
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2IVPROC)(GLenum target, const GLint *v);
+GLAPI PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
+#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SPROC)(GLenum target, GLshort s, GLshort t);
+GLAPI PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
+#define glMultiTexCoord2s glad_glMultiTexCoord2s
+typedef void (APIENTRYP PFNGLMULTITEXCOORD2SVPROC)(GLenum target, const GLshort *v);
+GLAPI PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
+#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r);
+GLAPI PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
+#define glMultiTexCoord3d glad_glMultiTexCoord3d
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3DVPROC)(GLenum target, const GLdouble *v);
+GLAPI PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
+#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+GLAPI PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
+#define glMultiTexCoord3f glad_glMultiTexCoord3f
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3FVPROC)(GLenum target, const GLfloat *v);
+GLAPI PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
+#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IPROC)(GLenum target, GLint s, GLint t, GLint r);
+GLAPI PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
+#define glMultiTexCoord3i glad_glMultiTexCoord3i
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3IVPROC)(GLenum target, const GLint *v);
+GLAPI PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
+#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SPROC)(GLenum target, GLshort s, GLshort t, GLshort r);
+GLAPI PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
+#define glMultiTexCoord3s glad_glMultiTexCoord3s
+typedef void (APIENTRYP PFNGLMULTITEXCOORD3SVPROC)(GLenum target, const GLshort *v);
+GLAPI PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
+#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+GLAPI PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
+#define glMultiTexCoord4d glad_glMultiTexCoord4d
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4DVPROC)(GLenum target, const GLdouble *v);
+GLAPI PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
+#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+GLAPI PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
+#define glMultiTexCoord4f glad_glMultiTexCoord4f
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4FVPROC)(GLenum target, const GLfloat *v);
+GLAPI PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
+#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q);
+GLAPI PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
+#define glMultiTexCoord4i glad_glMultiTexCoord4i
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4IVPROC)(GLenum target, const GLint *v);
+GLAPI PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
+#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q);
+GLAPI PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
+#define glMultiTexCoord4s glad_glMultiTexCoord4s
+typedef void (APIENTRYP PFNGLMULTITEXCOORD4SVPROC)(GLenum target, const GLshort *v);
+GLAPI PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
+#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXFPROC)(const GLfloat *m);
+GLAPI PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
+#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
+typedef void (APIENTRYP PFNGLLOADTRANSPOSEMATRIXDPROC)(const GLdouble *m);
+GLAPI PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
+#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXFPROC)(const GLfloat *m);
+GLAPI PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
+#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
+typedef void (APIENTRYP PFNGLMULTTRANSPOSEMATRIXDPROC)(const GLdouble *m);
+GLAPI PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
+#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
+#endif
+#ifndef GL_VERSION_1_4
+#define GL_VERSION_1_4 1
+GLAPI int GLAD_GL_VERSION_1_4;
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount);
+GLAPI PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
+#define glMultiDrawArrays glad_glMultiDrawArrays
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount);
+GLAPI PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
+#define glMultiDrawElements glad_glMultiDrawElements
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param);
+GLAPI PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
+#define glPointParameterf glad_glPointParameterf
+typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat *params);
+GLAPI PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
+#define glPointParameterfv glad_glPointParameterfv
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param);
+GLAPI PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
+#define glPointParameteri glad_glPointParameteri
+typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint *params);
+GLAPI PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
+#define glPointParameteriv glad_glPointParameteriv
+typedef void (APIENTRYP PFNGLFOGCOORDFPROC)(GLfloat coord);
+GLAPI PFNGLFOGCOORDFPROC glad_glFogCoordf;
+#define glFogCoordf glad_glFogCoordf
+typedef void (APIENTRYP PFNGLFOGCOORDFVPROC)(const GLfloat *coord);
+GLAPI PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
+#define glFogCoordfv glad_glFogCoordfv
+typedef void (APIENTRYP PFNGLFOGCOORDDPROC)(GLdouble coord);
+GLAPI PFNGLFOGCOORDDPROC glad_glFogCoordd;
+#define glFogCoordd glad_glFogCoordd
+typedef void (APIENTRYP PFNGLFOGCOORDDVPROC)(const GLdouble *coord);
+GLAPI PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
+#define glFogCoorddv glad_glFogCoorddv
+typedef void (APIENTRYP PFNGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
+#define glFogCoordPointer glad_glFogCoordPointer
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue);
+GLAPI PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
+#define glSecondaryColor3b glad_glSecondaryColor3b
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3BVPROC)(const GLbyte *v);
+GLAPI PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
+#define glSecondaryColor3bv glad_glSecondaryColor3bv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue);
+GLAPI PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
+#define glSecondaryColor3d glad_glSecondaryColor3d
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3DVPROC)(const GLdouble *v);
+GLAPI PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
+#define glSecondaryColor3dv glad_glSecondaryColor3dv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue);
+GLAPI PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
+#define glSecondaryColor3f glad_glSecondaryColor3f
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3FVPROC)(const GLfloat *v);
+GLAPI PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
+#define glSecondaryColor3fv glad_glSecondaryColor3fv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IPROC)(GLint red, GLint green, GLint blue);
+GLAPI PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
+#define glSecondaryColor3i glad_glSecondaryColor3i
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3IVPROC)(const GLint *v);
+GLAPI PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
+#define glSecondaryColor3iv glad_glSecondaryColor3iv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue);
+GLAPI PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
+#define glSecondaryColor3s glad_glSecondaryColor3s
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3SVPROC)(const GLshort *v);
+GLAPI PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
+#define glSecondaryColor3sv glad_glSecondaryColor3sv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue);
+GLAPI PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
+#define glSecondaryColor3ub glad_glSecondaryColor3ub
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UBVPROC)(const GLubyte *v);
+GLAPI PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
+#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue);
+GLAPI PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
+#define glSecondaryColor3ui glad_glSecondaryColor3ui
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3UIVPROC)(const GLuint *v);
+GLAPI PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
+#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue);
+GLAPI PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
+#define glSecondaryColor3us glad_glSecondaryColor3us
+typedef void (APIENTRYP PFNGLSECONDARYCOLOR3USVPROC)(const GLushort *v);
+GLAPI PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
+#define glSecondaryColor3usv glad_glSecondaryColor3usv
+typedef void (APIENTRYP PFNGLSECONDARYCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
+#define glSecondaryColorPointer glad_glSecondaryColorPointer
+typedef void (APIENTRYP PFNGLWINDOWPOS2DPROC)(GLdouble x, GLdouble y);
+GLAPI PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
+#define glWindowPos2d glad_glWindowPos2d
+typedef void (APIENTRYP PFNGLWINDOWPOS2DVPROC)(const GLdouble *v);
+GLAPI PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
+#define glWindowPos2dv glad_glWindowPos2dv
+typedef void (APIENTRYP PFNGLWINDOWPOS2FPROC)(GLfloat x, GLfloat y);
+GLAPI PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
+#define glWindowPos2f glad_glWindowPos2f
+typedef void (APIENTRYP PFNGLWINDOWPOS2FVPROC)(const GLfloat *v);
+GLAPI PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
+#define glWindowPos2fv glad_glWindowPos2fv
+typedef void (APIENTRYP PFNGLWINDOWPOS2IPROC)(GLint x, GLint y);
+GLAPI PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
+#define glWindowPos2i glad_glWindowPos2i
+typedef void (APIENTRYP PFNGLWINDOWPOS2IVPROC)(const GLint *v);
+GLAPI PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
+#define glWindowPos2iv glad_glWindowPos2iv
+typedef void (APIENTRYP PFNGLWINDOWPOS2SPROC)(GLshort x, GLshort y);
+GLAPI PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
+#define glWindowPos2s glad_glWindowPos2s
+typedef void (APIENTRYP PFNGLWINDOWPOS2SVPROC)(const GLshort *v);
+GLAPI PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
+#define glWindowPos2sv glad_glWindowPos2sv
+typedef void (APIENTRYP PFNGLWINDOWPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
+#define glWindowPos3d glad_glWindowPos3d
+typedef void (APIENTRYP PFNGLWINDOWPOS3DVPROC)(const GLdouble *v);
+GLAPI PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
+#define glWindowPos3dv glad_glWindowPos3dv
+typedef void (APIENTRYP PFNGLWINDOWPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
+#define glWindowPos3f glad_glWindowPos3f
+typedef void (APIENTRYP PFNGLWINDOWPOS3FVPROC)(const GLfloat *v);
+GLAPI PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
+#define glWindowPos3fv glad_glWindowPos3fv
+typedef void (APIENTRYP PFNGLWINDOWPOS3IPROC)(GLint x, GLint y, GLint z);
+GLAPI PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
+#define glWindowPos3i glad_glWindowPos3i
+typedef void (APIENTRYP PFNGLWINDOWPOS3IVPROC)(const GLint *v);
+GLAPI PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
+#define glWindowPos3iv glad_glWindowPos3iv
+typedef void (APIENTRYP PFNGLWINDOWPOS3SPROC)(GLshort x, GLshort y, GLshort z);
+GLAPI PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
+#define glWindowPos3s glad_glWindowPos3s
+typedef void (APIENTRYP PFNGLWINDOWPOS3SVPROC)(const GLshort *v);
+GLAPI PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
+#define glWindowPos3sv glad_glWindowPos3sv
+typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum mode);
+GLAPI PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+#endif
+#ifndef GL_VERSION_1_5
+#define GL_VERSION_1_5 1
+GLAPI int GLAD_GL_VERSION_1_5;
+typedef void (APIENTRYP PFNGLGENQUERIESPROC)(GLsizei n, GLuint *ids);
+GLAPI PFNGLGENQUERIESPROC glad_glGenQueries;
+#define glGenQueries glad_glGenQueries
+typedef void (APIENTRYP PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint *ids);
+GLAPI PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
+#define glDeleteQueries glad_glDeleteQueries
+typedef GLboolean (APIENTRYP PFNGLISQUERYPROC)(GLuint id);
+GLAPI PFNGLISQUERYPROC glad_glIsQuery;
+#define glIsQuery glad_glIsQuery
+typedef void (APIENTRYP PFNGLBEGINQUERYPROC)(GLenum target, GLuint id);
+GLAPI PFNGLBEGINQUERYPROC glad_glBeginQuery;
+#define glBeginQuery glad_glBeginQuery
+typedef void (APIENTRYP PFNGLENDQUERYPROC)(GLenum target);
+GLAPI PFNGLENDQUERYPROC glad_glEndQuery;
+#define glEndQuery glad_glEndQuery
+typedef void (APIENTRYP PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint *params);
+GLAPI PFNGLGETQUERYIVPROC glad_glGetQueryiv;
+#define glGetQueryiv glad_glGetQueryiv
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint *params);
+GLAPI PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
+#define glGetQueryObjectiv glad_glGetQueryObjectiv
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint *params);
+GLAPI PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
+#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer);
+GLAPI PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint *buffers);
+GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers);
+GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint buffer);
+GLAPI PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GLAPI PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GLAPI PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+GLAPI PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
+#define glGetBufferSubData glad_glGetBufferSubData
+typedef void * (APIENTRYP PFNGLMAPBUFFERPROC)(GLenum target, GLenum access);
+GLAPI PFNGLMAPBUFFERPROC glad_glMapBuffer;
+#define glMapBuffer glad_glMapBuffer
+typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC)(GLenum target);
+GLAPI PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
+#define glUnmapBuffer glad_glUnmapBuffer
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
+GLAPI PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void **params);
+GLAPI PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
+#define glGetBufferPointerv glad_glGetBufferPointerv
+#endif
+#ifndef GL_VERSION_2_0
+#define GL_VERSION_2_0 1
+GLAPI int GLAD_GL_VERSION_2_0;
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha);
+GLAPI PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum *bufs);
+GLAPI PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
+#define glDrawBuffers glad_glDrawBuffers
+typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GLAPI PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask);
+GLAPI PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask);
+GLAPI PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader);
+GLAPI PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar *name);
+GLAPI PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader);
+GLAPI PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC)(void);
+GLAPI PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum type);
+GLAPI PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program);
+GLAPI PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader);
+GLAPI PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader);
+GLAPI PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+GLAPI PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index);
+GLAPI PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GLAPI PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GLAPI PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar *name);
+GLAPI PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint *params);
+GLAPI PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint *params);
+GLAPI PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GLAPI PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar *name);
+GLAPI PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat *params);
+GLAPI PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint *params);
+GLAPI PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble *params);
+GLAPI PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
+#define glGetVertexAttribdv glad_glGetVertexAttribdv
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint *params);
+GLAPI PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void **pointer);
+GLAPI PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint program);
+GLAPI PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint shader);
+GLAPI PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program);
+GLAPI PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GLAPI PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program);
+GLAPI PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0);
+GLAPI PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1);
+GLAPI PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GLAPI PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GLAPI PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint location, GLint v0);
+GLAPI PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1);
+GLAPI PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2);
+GLAPI PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GLAPI PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat *value);
+GLAPI PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat *value);
+GLAPI PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat *value);
+GLAPI PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat *value);
+GLAPI PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint *value);
+GLAPI PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint *value);
+GLAPI PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint *value);
+GLAPI PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint *value);
+GLAPI PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint program);
+GLAPI PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x);
+GLAPI PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
+#define glVertexAttrib1d glad_glVertexAttrib1d
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble *v);
+GLAPI PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
+#define glVertexAttrib1dv glad_glVertexAttrib1dv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x);
+GLAPI PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat *v);
+GLAPI PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x);
+GLAPI PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
+#define glVertexAttrib1s glad_glVertexAttrib1s
+typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort *v);
+GLAPI PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
+#define glVertexAttrib1sv glad_glVertexAttrib1sv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y);
+GLAPI PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
+#define glVertexAttrib2d glad_glVertexAttrib2d
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble *v);
+GLAPI PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
+#define glVertexAttrib2dv glad_glVertexAttrib2dv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y);
+GLAPI PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat *v);
+GLAPI PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y);
+GLAPI PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
+#define glVertexAttrib2s glad_glVertexAttrib2s
+typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort *v);
+GLAPI PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
+#define glVertexAttrib2sv glad_glVertexAttrib2sv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z);
+GLAPI PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
+#define glVertexAttrib3d glad_glVertexAttrib3d
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble *v);
+GLAPI PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
+#define glVertexAttrib3dv glad_glVertexAttrib3dv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GLAPI PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat *v);
+GLAPI PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z);
+GLAPI PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
+#define glVertexAttrib3s glad_glVertexAttrib3s
+typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort *v);
+GLAPI PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
+#define glVertexAttrib3sv glad_glVertexAttrib3sv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte *v);
+GLAPI PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
+#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint *v);
+GLAPI PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
+#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort *v);
+GLAPI PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
+#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
+GLAPI PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
+#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte *v);
+GLAPI PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
+#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint *v);
+GLAPI PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
+#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort *v);
+GLAPI PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
+#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte *v);
+GLAPI PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
+#define glVertexAttrib4bv glad_glVertexAttrib4bv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+GLAPI PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
+#define glVertexAttrib4d glad_glVertexAttrib4d
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble *v);
+GLAPI PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
+#define glVertexAttrib4dv glad_glVertexAttrib4dv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GLAPI PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat *v);
+GLAPI PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint *v);
+GLAPI PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
+#define glVertexAttrib4iv glad_glVertexAttrib4iv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
+GLAPI PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
+#define glVertexAttrib4s glad_glVertexAttrib4s
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort *v);
+GLAPI PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
+#define glVertexAttrib4sv glad_glVertexAttrib4sv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte *v);
+GLAPI PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
+#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint *v);
+GLAPI PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
+#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort *v);
+GLAPI PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
+#define glVertexAttrib4usv glad_glVertexAttrib4usv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GLAPI PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+#endif
+#ifndef GL_VERSION_2_1
+#define GL_VERSION_2_1 1
+GLAPI int GLAD_GL_VERSION_2_1;
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
+#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
+#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
+#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
+#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
+#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
+#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
+#endif
+#ifndef GL_VERSION_3_0
+#define GL_VERSION_3_0 1
+GLAPI int GLAD_GL_VERSION_3_0;
+typedef void (APIENTRYP PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GLAPI PFNGLCOLORMASKIPROC glad_glColorMaski;
+#define glColorMaski glad_glColorMaski
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean *data);
+GLAPI PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
+#define glGetBooleani_v glad_glGetBooleani_v
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint *data);
+GLAPI PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
+#define glGetIntegeri_v glad_glGetIntegeri_v
+typedef void (APIENTRYP PFNGLENABLEIPROC)(GLenum target, GLuint index);
+GLAPI PFNGLENABLEIPROC glad_glEnablei;
+#define glEnablei glad_glEnablei
+typedef void (APIENTRYP PFNGLDISABLEIPROC)(GLenum target, GLuint index);
+GLAPI PFNGLDISABLEIPROC glad_glDisablei;
+#define glDisablei glad_glDisablei
+typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC)(GLenum target, GLuint index);
+GLAPI PFNGLISENABLEDIPROC glad_glIsEnabledi;
+#define glIsEnabledi glad_glIsEnabledi
+typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode);
+GLAPI PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
+#define glBeginTransformFeedback glad_glBeginTransformFeedback
+typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC)(void);
+GLAPI PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
+#define glEndTransformFeedback glad_glEndTransformFeedback
+typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GLAPI PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
+#define glBindBufferRange glad_glBindBufferRange
+typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer);
+GLAPI PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
+#define glBindBufferBase glad_glBindBufferBase
+typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GLAPI PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
+#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GLAPI PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
+#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
+typedef void (APIENTRYP PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp);
+GLAPI PFNGLCLAMPCOLORPROC glad_glClampColor;
+#define glClampColor glad_glClampColor
+typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode);
+GLAPI PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
+#define glBeginConditionalRender glad_glBeginConditionalRender
+typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC)(void);
+GLAPI PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
+#define glEndConditionalRender glad_glEndConditionalRender
+typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
+#define glVertexAttribIPointer glad_glVertexAttribIPointer
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint *params);
+GLAPI PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
+#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
+typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint *params);
+GLAPI PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
+#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x);
+GLAPI PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
+#define glVertexAttribI1i glad_glVertexAttribI1i
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y);
+GLAPI PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
+#define glVertexAttribI2i glad_glVertexAttribI2i
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z);
+GLAPI PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
+#define glVertexAttribI3i glad_glVertexAttribI3i
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w);
+GLAPI PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
+#define glVertexAttribI4i glad_glVertexAttribI4i
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x);
+GLAPI PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
+#define glVertexAttribI1ui glad_glVertexAttribI1ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y);
+GLAPI PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
+#define glVertexAttribI2ui glad_glVertexAttribI2ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z);
+GLAPI PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
+#define glVertexAttribI3ui glad_glVertexAttribI3ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GLAPI PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
+#define glVertexAttribI4ui glad_glVertexAttribI4ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint *v);
+GLAPI PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
+#define glVertexAttribI1iv glad_glVertexAttribI1iv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint *v);
+GLAPI PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
+#define glVertexAttribI2iv glad_glVertexAttribI2iv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint *v);
+GLAPI PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
+#define glVertexAttribI3iv glad_glVertexAttribI3iv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint *v);
+GLAPI PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
+#define glVertexAttribI4iv glad_glVertexAttribI4iv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint *v);
+GLAPI PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
+#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint *v);
+GLAPI PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
+#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint *v);
+GLAPI PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
+#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint *v);
+GLAPI PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
+#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte *v);
+GLAPI PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
+#define glVertexAttribI4bv glad_glVertexAttribI4bv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort *v);
+GLAPI PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
+#define glVertexAttribI4sv glad_glVertexAttribI4sv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte *v);
+GLAPI PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
+#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort *v);
+GLAPI PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
+#define glVertexAttribI4usv glad_glVertexAttribI4usv
+typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint *params);
+GLAPI PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
+#define glGetUniformuiv glad_glGetUniformuiv
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar *name);
+GLAPI PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
+#define glBindFragDataLocation glad_glBindFragDataLocation
+typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar *name);
+GLAPI PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
+#define glGetFragDataLocation glad_glGetFragDataLocation
+typedef void (APIENTRYP PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0);
+GLAPI PFNGLUNIFORM1UIPROC glad_glUniform1ui;
+#define glUniform1ui glad_glUniform1ui
+typedef void (APIENTRYP PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1);
+GLAPI PFNGLUNIFORM2UIPROC glad_glUniform2ui;
+#define glUniform2ui glad_glUniform2ui
+typedef void (APIENTRYP PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2);
+GLAPI PFNGLUNIFORM3UIPROC glad_glUniform3ui;
+#define glUniform3ui glad_glUniform3ui
+typedef void (APIENTRYP PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GLAPI PFNGLUNIFORM4UIPROC glad_glUniform4ui;
+#define glUniform4ui glad_glUniform4ui
+typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint *value);
+GLAPI PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
+#define glUniform1uiv glad_glUniform1uiv
+typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint *value);
+GLAPI PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
+#define glUniform2uiv glad_glUniform2uiv
+typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint *value);
+GLAPI PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
+#define glUniform3uiv glad_glUniform3uiv
+typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint *value);
+GLAPI PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
+#define glUniform4uiv glad_glUniform4uiv
+typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint *params);
+GLAPI PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
+#define glTexParameterIiv glad_glTexParameterIiv
+typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint *params);
+GLAPI PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
+#define glTexParameterIuiv glad_glTexParameterIuiv
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint *params);
+GLAPI PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
+#define glGetTexParameterIiv glad_glGetTexParameterIiv
+typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint *params);
+GLAPI PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
+#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
+typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint *value);
+GLAPI PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
+#define glClearBufferiv glad_glClearBufferiv
+typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint *value);
+GLAPI PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
+#define glClearBufferuiv glad_glClearBufferuiv
+typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GLAPI PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
+#define glClearBufferfv glad_glClearBufferfv
+typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GLAPI PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
+#define glClearBufferfi glad_glClearBufferfi
+typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC)(GLenum name, GLuint index);
+GLAPI PFNGLGETSTRINGIPROC glad_glGetStringi;
+#define glGetStringi glad_glGetStringi
+typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer);
+GLAPI PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer);
+GLAPI PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint *renderbuffers);
+GLAPI PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint *renderbuffers);
+GLAPI PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params);
+GLAPI PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer);
+GLAPI PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer);
+GLAPI PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint *framebuffers);
+GLAPI PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint *framebuffers);
+GLAPI PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target);
+GLAPI PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
+#define glFramebufferTexture1D glad_glFramebufferTexture1D
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GLAPI PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+GLAPI PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
+#define glFramebufferTexture3D glad_glFramebufferTexture3D
+typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GLAPI PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum target);
+GLAPI PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GLAPI PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
+#define glBlitFramebuffer glad_glBlitFramebuffer
+typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
+#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GLAPI PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
+#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
+typedef void * (APIENTRYP PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GLAPI PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
+#define glMapBufferRange glad_glMapBufferRange
+typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length);
+GLAPI PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
+#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array);
+GLAPI PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
+#define glBindVertexArray glad_glBindVertexArray
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint *arrays);
+GLAPI PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
+#define glDeleteVertexArrays glad_glDeleteVertexArrays
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint *arrays);
+GLAPI PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
+#define glGenVertexArrays glad_glGenVertexArrays
+typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC)(GLuint array);
+GLAPI PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
+#define glIsVertexArray glad_glIsVertexArray
+#endif
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+GLAPI int GLAD_GL_VERSION_3_1;
+typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GLAPI PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
+#define glDrawArraysInstanced glad_glDrawArraysInstanced
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GLAPI PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
+#define glDrawElementsInstanced glad_glDrawElementsInstanced
+typedef void (APIENTRYP PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer);
+GLAPI PFNGLTEXBUFFERPROC glad_glTexBuffer;
+#define glTexBuffer glad_glTexBuffer
+typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index);
+GLAPI PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
+#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
+typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GLAPI PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
+#define glCopyBufferSubData glad_glCopyBufferSubData
+typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GLAPI PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
+#define glGetUniformIndices glad_glGetUniformIndices
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GLAPI PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
+#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName);
+GLAPI PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
+#define glGetActiveUniformName glad_glGetActiveUniformName
+typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar *uniformBlockName);
+GLAPI PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
+#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GLAPI PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
+#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
+typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GLAPI PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
+#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
+typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GLAPI PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
+#define glUniformBlockBinding glad_glUniformBlockBinding
+#endif
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+GLAPI int GLAD_GL_VERSION_3_2;
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
+#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
+typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GLAPI PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
+#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
+typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GLAPI PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
+#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
+typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex);
+GLAPI PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
+#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
+typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC)(GLenum mode);
+GLAPI PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
+#define glProvokingVertex glad_glProvokingVertex
+typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
+GLAPI PFNGLFENCESYNCPROC glad_glFenceSync;
+#define glFenceSync glad_glFenceSync
+typedef GLboolean (APIENTRYP PFNGLISSYNCPROC)(GLsync sync);
+GLAPI PFNGLISSYNCPROC glad_glIsSync;
+#define glIsSync glad_glIsSync
+typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync);
+GLAPI PFNGLDELETESYNCPROC glad_glDeleteSync;
+#define glDeleteSync glad_glDeleteSync
+typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
+#define glClientWaitSync glad_glClientWaitSync
+typedef void (APIENTRYP PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+GLAPI PFNGLWAITSYNCPROC glad_glWaitSync;
+#define glWaitSync glad_glWaitSync
+typedef void (APIENTRYP PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 *data);
+GLAPI PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
+#define glGetInteger64v glad_glGetInteger64v
+typedef void (APIENTRYP PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values);
+GLAPI PFNGLGETSYNCIVPROC glad_glGetSynciv;
+#define glGetSynciv glad_glGetSynciv
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 *data);
+GLAPI PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
+#define glGetInteger64i_v glad_glGetInteger64i_v
+typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 *params);
+GLAPI PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
+#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
+typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level);
+GLAPI PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
+#define glFramebufferTexture glad_glFramebufferTexture
+typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GLAPI PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
+#define glTexImage2DMultisample glad_glTexImage2DMultisample
+typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+GLAPI PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
+#define glTexImage3DMultisample glad_glTexImage3DMultisample
+typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat *val);
+GLAPI PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
+#define glGetMultisamplefv glad_glGetMultisamplefv
+typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask);
+GLAPI PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
+#define glSampleMaski glad_glSampleMaski
+#endif
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+GLAPI int GLAD_GL_VERSION_3_3;
+typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GLAPI PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
+#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
+typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar *name);
+GLAPI PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
+#define glGetFragDataIndex glad_glGetFragDataIndex
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint *samplers);
+GLAPI PFNGLGENSAMPLERSPROC glad_glGenSamplers;
+#define glGenSamplers glad_glGenSamplers
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint *samplers);
+GLAPI PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
+#define glDeleteSamplers glad_glDeleteSamplers
+typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC)(GLuint sampler);
+GLAPI PFNGLISSAMPLERPROC glad_glIsSampler;
+#define glIsSampler glad_glIsSampler
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler);
+GLAPI PFNGLBINDSAMPLERPROC glad_glBindSampler;
+#define glBindSampler glad_glBindSampler
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param);
+GLAPI PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
+#define glSamplerParameteri glad_glSamplerParameteri
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint *param);
+GLAPI PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
+#define glSamplerParameteriv glad_glSamplerParameteriv
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param);
+GLAPI PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
+#define glSamplerParameterf glad_glSamplerParameterf
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat *param);
+GLAPI PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
+#define glSamplerParameterfv glad_glSamplerParameterfv
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint *param);
+GLAPI PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
+#define glSamplerParameterIiv glad_glSamplerParameterIiv
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint *param);
+GLAPI PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
+#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint *params);
+GLAPI PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
+#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint *params);
+GLAPI PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
+#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat *params);
+GLAPI PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
+#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
+typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint *params);
+GLAPI PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
+#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
+typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target);
+GLAPI PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
+#define glQueryCounter glad_glQueryCounter
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 *params);
+GLAPI PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
+#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
+typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 *params);
+GLAPI PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
+#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor);
+GLAPI PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
+#define glVertexAttribDivisor glad_glVertexAttribDivisor
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
+#define glVertexAttribP1ui glad_glVertexAttribP1ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
+#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
+#define glVertexAttribP2ui glad_glVertexAttribP2ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
+#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
+#define glVertexAttribP3ui glad_glVertexAttribP3ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
+#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value);
+GLAPI PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
+#define glVertexAttribP4ui glad_glVertexAttribP4ui
+typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value);
+GLAPI PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
+#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
+typedef void (APIENTRYP PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value);
+GLAPI PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
+#define glVertexP2ui glad_glVertexP2ui
+typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint *value);
+GLAPI PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
+#define glVertexP2uiv glad_glVertexP2uiv
+typedef void (APIENTRYP PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value);
+GLAPI PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
+#define glVertexP3ui glad_glVertexP3ui
+typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint *value);
+GLAPI PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
+#define glVertexP3uiv glad_glVertexP3uiv
+typedef void (APIENTRYP PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value);
+GLAPI PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
+#define glVertexP4ui glad_glVertexP4ui
+typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint *value);
+GLAPI PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
+#define glVertexP4uiv glad_glVertexP4uiv
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords);
+GLAPI PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
+#define glTexCoordP1ui glad_glTexCoordP1ui
+typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint *coords);
+GLAPI PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
+#define glTexCoordP1uiv glad_glTexCoordP1uiv
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords);
+GLAPI PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
+#define glTexCoordP2ui glad_glTexCoordP2ui
+typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint *coords);
+GLAPI PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
+#define glTexCoordP2uiv glad_glTexCoordP2uiv
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords);
+GLAPI PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
+#define glTexCoordP3ui glad_glTexCoordP3ui
+typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint *coords);
+GLAPI PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
+#define glTexCoordP3uiv glad_glTexCoordP3uiv
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords);
+GLAPI PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
+#define glTexCoordP4ui glad_glTexCoordP4ui
+typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint *coords);
+GLAPI PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
+#define glTexCoordP4uiv glad_glTexCoordP4uiv
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords);
+GLAPI PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
+#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
+GLAPI PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
+#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords);
+GLAPI PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
+#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
+GLAPI PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
+#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords);
+GLAPI PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
+#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
+GLAPI PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
+#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords);
+GLAPI PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
+#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
+typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint *coords);
+GLAPI PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
+#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
+typedef void (APIENTRYP PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords);
+GLAPI PFNGLNORMALP3UIPROC glad_glNormalP3ui;
+#define glNormalP3ui glad_glNormalP3ui
+typedef void (APIENTRYP PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint *coords);
+GLAPI PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
+#define glNormalP3uiv glad_glNormalP3uiv
+typedef void (APIENTRYP PFNGLCOLORP3UIPROC)(GLenum type, GLuint color);
+GLAPI PFNGLCOLORP3UIPROC glad_glColorP3ui;
+#define glColorP3ui glad_glColorP3ui
+typedef void (APIENTRYP PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint *color);
+GLAPI PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
+#define glColorP3uiv glad_glColorP3uiv
+typedef void (APIENTRYP PFNGLCOLORP4UIPROC)(GLenum type, GLuint color);
+GLAPI PFNGLCOLORP4UIPROC glad_glColorP4ui;
+#define glColorP4ui glad_glColorP4ui
+typedef void (APIENTRYP PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint *color);
+GLAPI PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
+#define glColorP4uiv glad_glColorP4uiv
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color);
+GLAPI PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
+#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
+typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint *color);
+GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
+#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
+#endif
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#ifndef GL_ARB_map_buffer_alignment
+#define GL_ARB_map_buffer_alignment 1
+GLAPI int GLAD_GL_ARB_map_buffer_alignment;
+#endif
+#ifndef GL_ARB_map_buffer_range
+#define GL_ARB_map_buffer_range 1
+GLAPI int GLAD_GL_ARB_map_buffer_range;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Client/ThirdParty/glad/khrplatform.h b/Client/ThirdParty/glad/khrplatform.h
new file mode 100644
index 0000000..dd22d92
--- /dev/null
+++ b/Client/ThirdParty/glad/khrplatform.h
@@ -0,0 +1,290 @@
+#ifndef __khrplatform_h_
+#define __khrplatform_h_
+
+/*
+** Copyright (c) 2008-2018 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* Khronos platform-specific types and definitions.
+ *
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ * 67a3e0864c2d75ea5287b9f3d2eb74a745936692
+ *
+ * Adopters may modify this file to suit their platform. Adopters are
+ * encouraged to submit platform specific modifications to the Khronos
+ * group so that they can be included in future versions of this file.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
+ *
+ *
+ * See the Implementer's Guidelines for information about where this file
+ * should be located on your system and for more details of its use:
+ * http://www.khronos.org/registry/implementers_guide.pdf
+ *
+ * This file should be included as
+ * #include <KHR/khrplatform.h>
+ * by Khronos client API header files that use its types and defines.
+ *
+ * The types in khrplatform.h should only be used to define API-specific types.
+ *
+ * Types defined in khrplatform.h:
+ * khronos_int8_t signed 8 bit
+ * khronos_uint8_t unsigned 8 bit
+ * khronos_int16_t signed 16 bit
+ * khronos_uint16_t unsigned 16 bit
+ * khronos_int32_t signed 32 bit
+ * khronos_uint32_t unsigned 32 bit
+ * khronos_int64_t signed 64 bit
+ * khronos_uint64_t unsigned 64 bit
+ * khronos_intptr_t signed same number of bits as a pointer
+ * khronos_uintptr_t unsigned same number of bits as a pointer
+ * khronos_ssize_t signed size
+ * khronos_usize_t unsigned size
+ * khronos_float_t signed 32 bit floating point
+ * khronos_time_ns_t unsigned 64 bit time in nanoseconds
+ * khronos_utime_nanoseconds_t unsigned time interval or absolute time in
+ * nanoseconds
+ * khronos_stime_nanoseconds_t signed time interval in nanoseconds
+ * khronos_boolean_enum_t enumerated boolean type. This should
+ * only be used as a base type when a client API's boolean type is
+ * an enum. Client APIs which use an integer or other type for
+ * booleans cannot use this as the base type for their boolean.
+ *
+ * Tokens defined in khrplatform.h:
+ *
+ * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
+ *
+ * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
+ * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
+ *
+ * Calling convention macros defined in this file:
+ * KHRONOS_APICALL
+ * KHRONOS_APIENTRY
+ * KHRONOS_APIATTRIBUTES
+ *
+ * These may be used in function prototypes as:
+ *
+ * KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
+ * int arg1,
+ * int arg2) KHRONOS_APIATTRIBUTES;
+ */
+
+#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
+# define KHRONOS_STATIC 1
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APICALL
+ *-------------------------------------------------------------------------
+ * This precedes the return type of the function in the function prototype.
+ */
+#if defined(KHRONOS_STATIC)
+ /* If the preprocessor constant KHRONOS_STATIC is defined, make the
+ * header compatible with static linking. */
+# define KHRONOS_APICALL
+#elif defined(_WIN32)
+# define KHRONOS_APICALL __declspec(dllimport)
+#elif defined (__SYMBIAN32__)
+# define KHRONOS_APICALL IMPORT_C
+#elif defined(__ANDROID__)
+# define KHRONOS_APICALL __attribute__((visibility("default")))
+#else
+# define KHRONOS_APICALL
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIENTRY
+ *-------------------------------------------------------------------------
+ * This follows the return type of the function and precedes the function
+ * name in the function prototype.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define KHRONOS_APIENTRY __stdcall
+#else
+# define KHRONOS_APIENTRY
+#endif
+
+/*-------------------------------------------------------------------------
+ * Definition of KHRONOS_APIATTRIBUTES
+ *-------------------------------------------------------------------------
+ * This follows the closing parenthesis of the function prototype arguments.
+ */
+#if defined (__ARMCC_2__)
+#define KHRONOS_APIATTRIBUTES __softfp
+#else
+#define KHRONOS_APIATTRIBUTES
+#endif
+
+/*-------------------------------------------------------------------------
+ * basic type definitions
+ *-----------------------------------------------------------------------*/
+#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
+
+
+/*
+ * Using <stdint.h>
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__VMS ) || defined(__sgi)
+
+/*
+ * Using <inttypes.h>
+ */
+#include <inttypes.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
+
+/*
+ * Win32
+ */
+typedef __int32 khronos_int32_t;
+typedef unsigned __int32 khronos_uint32_t;
+typedef __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif defined(__sun__) || defined(__digital__)
+
+/*
+ * Sun or Digital
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#if defined(__arch64__) || defined(_LP64)
+typedef long int khronos_int64_t;
+typedef unsigned long int khronos_uint64_t;
+#else
+typedef long long int khronos_int64_t;
+typedef unsigned long long int khronos_uint64_t;
+#endif /* __arch64__ */
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#elif 0
+
+/*
+ * Hypothetical platform with no float or int64 support
+ */
+typedef int khronos_int32_t;
+typedef unsigned int khronos_uint32_t;
+#define KHRONOS_SUPPORT_INT64 0
+#define KHRONOS_SUPPORT_FLOAT 0
+
+#else
+
+/*
+ * Generic fallback
+ */
+#include <stdint.h>
+typedef int32_t khronos_int32_t;
+typedef uint32_t khronos_uint32_t;
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#define KHRONOS_SUPPORT_INT64 1
+#define KHRONOS_SUPPORT_FLOAT 1
+
+#endif
+
+
+/*
+ * Types that are (so far) the same on all platforms
+ */
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+
+/*
+ * Types that differ between LLP64 and LP64 architectures - in LLP64,
+ * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
+ * to be the only LLP64 architecture in current use.
+ */
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef unsigned long long int khronos_uintptr_t;
+typedef signed long long int khronos_ssize_t;
+typedef unsigned long long int khronos_usize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef unsigned long int khronos_uintptr_t;
+typedef signed long int khronos_ssize_t;
+typedef unsigned long int khronos_usize_t;
+#endif
+
+#if KHRONOS_SUPPORT_FLOAT
+/*
+ * Float type
+ */
+typedef float khronos_float_t;
+#endif
+
+#if KHRONOS_SUPPORT_INT64
+/* Time types
+ *
+ * These types can be used to represent a time interval in nanoseconds or
+ * an absolute Unadjusted System Time. Unadjusted System Time is the number
+ * of nanoseconds since some arbitrary system event (e.g. since the last
+ * time the system booted). The Unadjusted System Time is an unsigned
+ * 64 bit value that wraps back to 0 every 584 years. Time intervals
+ * may be either signed or unsigned.
+ */
+typedef khronos_uint64_t khronos_utime_nanoseconds_t;
+typedef khronos_int64_t khronos_stime_nanoseconds_t;
+#endif
+
+/*
+ * Dummy value used to pad enum types to 32 bits.
+ */
+#ifndef KHRONOS_MAX_ENUM
+#define KHRONOS_MAX_ENUM 0x7FFFFFFF
+#endif
+
+/*
+ * Enumerated boolean type
+ *
+ * Values other than zero should be considered to be true. Therefore
+ * comparisons should not be made against KHRONOS_TRUE.
+ */
+typedef enum {
+ KHRONOS_FALSE = 0,
+ KHRONOS_TRUE = 1,
+ KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
+} khronos_boolean_enum_t;
+
+#endif /* __khrplatform_h_ */
diff --git a/Client/ThirdParty/imgui/.editorconfig b/Client/ThirdParty/imgui/.editorconfig
new file mode 100644
index 0000000..c6dc600
--- /dev/null
+++ b/Client/ThirdParty/imgui/.editorconfig
@@ -0,0 +1,24 @@
+# See http://editorconfig.org to read about the EditorConfig format.
+# - In theory automatically supported by VS2017+ and most common IDE or text editors.
+# - In practice VS2019 stills gets trailing whitespaces wrong :(
+# - Suggest install to trim whitespaces: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer
+# - Alternative for older VS2010 to VS2015: https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig
+
+# top-most EditorConfig file
+root = true
+
+# Default settings:
+# Use 4 spaces as indentation
+[*]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[imstb_*]
+indent_size = 3
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab
+indent_size = 4
diff --git a/Client/ThirdParty/imgui/.gitattributes b/Client/ThirdParty/imgui/.gitattributes
new file mode 100644
index 0000000..d48470e
--- /dev/null
+++ b/Client/ThirdParty/imgui/.gitattributes
@@ -0,0 +1,30 @@
+* text=auto
+
+*.c text
+*.cpp text
+*.h text
+*.m text
+*.mm text
+*.md text
+*.txt text
+*.html text
+*.bat text
+*.frag text
+*.vert text
+*.mkb text
+*.icf text
+
+*.sln text eol=crlf
+*.vcxproj text eol=crlf
+*.vcxproj.filters text eol=crlf
+*.natvis text eol=crlf
+
+Makefile text eol=lf
+*.sh text eol=lf
+*.pbxproj text eol=lf
+*.storyboard text eol=lf
+*.plist text eol=lf
+
+*.png binary
+*.ttf binary
+*.lib binary
diff --git a/Client/ThirdParty/imgui/.github/FUNDING.yml b/Client/ThirdParty/imgui/.github/FUNDING.yml
new file mode 100644
index 0000000..2aa08b4
--- /dev/null
+++ b/Client/ThirdParty/imgui/.github/FUNDING.yml
@@ -0,0 +1 @@
+custom: ['https://github.com/ocornut/imgui/wiki/Sponsors']
diff --git a/Client/ThirdParty/imgui/.github/issue_template.md b/Client/ThirdParty/imgui/.github/issue_template.md
new file mode 100644
index 0000000..fdd0943
--- /dev/null
+++ b/Client/ThirdParty/imgui/.github/issue_template.md
@@ -0,0 +1,46 @@
+(Click "Preview" above ^ to turn URL into clickable links)
+
+1. FOR FIRST-TIME USERS ISSUES COMPILING/LINKING/RUNNING or LOADING FONTS, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions).
+
+2. PLEASE CAREFULLY READ: [FAQ](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md)
+
+3. PLEASE CAREFULLY READ: [Issue Submitting Guidelines](https://github.com/ocornut/imgui/issues/2261)
+
+4. PLEASE MAKE SURE that you have: read the FAQ; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the links above.
+
+5. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
+
+6. Delete points 1-6 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
+
+Thank you!
+
+----
+
+_(you may also go to Demo>About Window, and click "Config/Build Information" to obtain a bunch of detailed information that you can paste here)_
+
+**Version/Branch of Dear ImGui:**
+
+Version: XXX
+Branch: XXX _(master/viewport/docking/etc.)_
+
+**Back-end/Renderer/Compiler/OS**
+
+Back-ends: imgui_impl_XXX.cpp + imgui_impl_XXX.cpp _(or specify if using a custom engine/back-end)_
+Compiler: XXX _(if the question is related to building or platform specific features)_
+Operating System: XXX
+
+**My Issue/Question:**
+
+XXX _(please provide as much context as possible)_
+
+**Screenshots/Video**
+
+XXX _(you can drag files here)_
+
+**Standalone, minimal, complete and verifiable example:** _(see https://github.com/ocornut/imgui/issues/2261)_
+```
+// Here's some code anyone can copy and paste to reproduce your issue
+ImGui::Begin("Example Bug");
+MoreCodeToExplainMyIssue();
+ImGui::End();
+```
diff --git a/Client/ThirdParty/imgui/.github/pull_request_template.md b/Client/ThirdParty/imgui/.github/pull_request_template.md
new file mode 100644
index 0000000..187d710
--- /dev/null
+++ b/Client/ThirdParty/imgui/.github/pull_request_template.md
@@ -0,0 +1,6 @@
+(Click "Preview" to turn any http URL into a clickable link)
+
+1. PLEASE CAREFULLY READ: [Issue Submitting Guidelines](https://github.com/ocornut/imgui/issues/2261)
+
+2. Clear this template before submitting your PR.
+
diff --git a/Client/ThirdParty/imgui/.github/workflows/build.yml b/Client/ThirdParty/imgui/.github/workflows/build.yml
new file mode 100644
index 0000000..fc8cbba
--- /dev/null
+++ b/Client/ThirdParty/imgui/.github/workflows/build.yml
@@ -0,0 +1,530 @@
+name: build
+
+on:
+ push:
+ pull_request:
+ workflow_run:
+ # Use a workflow as a trigger of scheduled builds. Forked repositories can disable scheduled builds by disabling
+ # "scheduled" workflow, while maintaining ability to perform local CI builds.
+ workflows:
+ - scheduled
+ branches:
+ - master
+ - docking
+ types:
+ - requested
+
+jobs:
+ Windows:
+ runs-on: windows-2019
+ env:
+ VS_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\
+ MSBUILD_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Dependencies
+ shell: powershell
+ run: |
+ Invoke-WebRequest -Uri "https://www.libsdl.org/release/SDL2-devel-2.0.10-VC.zip" -OutFile "SDL2-devel-2.0.10-VC.zip"
+ Expand-Archive -Path SDL2-devel-2.0.10-VC.zip
+ echo "SDL2_DIR=$(pwd)\SDL2-devel-2.0.10-VC\SDL2-2.0.10\" >>${env:GITHUB_ENV}
+
+ Invoke-WebRequest -Uri "https://github.com/ocornut/imgui/files/3789205/vulkan-sdk-1.1.121.2.zip" -OutFile vulkan-sdk-1.1.121.2.zip
+ Expand-Archive -Path vulkan-sdk-1.1.121.2.zip
+ echo "VULKAN_SDK=$(pwd)\vulkan-sdk-1.1.121.2\" >>${env:GITHUB_ENV}
+
+ - name: Fix Projects
+ shell: powershell
+ run: |
+ # WARNING: This will need updating if toolset/sdk change in project files!
+ gci -recurse -filter "*.vcxproj" | ForEach-Object {
+ # Fix SDK and toolset for most samples.
+ (Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
+ (Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
+ # Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
+ (Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
+ (Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
+ }
+
+ # Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long.
+ - name: Build example_null (extra warnings, mingw 64-bit)
+ run: mingw32-make -C examples/example_null WITH_EXTRA_WARNINGS=1
+
+ - name: Build example_null (mingw 64-bit, as DLL)
+ shell: bash
+ run: |
+ echo '#ifdef _EXPORT' > example_single_file.cpp
+ echo '# define IMGUI_API __declspec(dllexport)' >> example_single_file.cpp
+ echo '#else' >> example_single_file.cpp
+ echo '# define IMGUI_API __declspec(dllimport)' >> example_single_file.cpp
+ echo '#endif' >> example_single_file.cpp
+ echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
+ echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
+ g++ -I. -Wall -Wformat -D_EXPORT -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
+ g++ -I. -Wall -Wformat -o example_null.exe examples/example_null/main.cpp -L. -limgui
+ rm -f example_null.exe libimgui.* example_single_file.*
+
+ - name: Build example_null (extra warnings, msvc 64-bit)
+ shell: cmd
+ run: |
+ cd examples\example_null
+ call "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat"
+ .\build_win32.bat /W4
+
+ - name: Build example_null (single file build)
+ shell: bash
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp -limm32
+
+ - name: Build example_null (with IMGUI_DISABLE_WIN32_FUNCTIONS)
+ shell: bash
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_DISABLE_WIN32_FUNCTIONS
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file.exe example_single_file.cpp -limm32
+
+ - name: Build example_null (as DLL)
+ shell: cmd
+ run: |
+ call "%VS_PATH%\VC\Auxiliary\Build\vcvars64.bat"
+
+ echo #ifdef _EXPORT > example_single_file.cpp
+ echo # define IMGUI_API __declspec(dllexport) >> example_single_file.cpp
+ echo #else >> example_single_file.cpp
+ echo # define IMGUI_API __declspec(dllimport) >> example_single_file.cpp
+ echo #endif >> example_single_file.cpp
+ echo #define IMGUI_IMPLEMENTATION >> example_single_file.cpp
+ echo #include "misc/single_file/imgui_single_file.h" >> example_single_file.cpp
+
+ cl.exe /D_USRDLL /D_WINDLL /D_EXPORT /I. example_single_file.cpp /LD /FeImGui.dll /link
+ cl.exe /I. ImGui.lib /Feexample_null.exe examples/example_null/main.cpp
+
+ - name: Build Win32 example_glfw_opengl2
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+
+ - name: Build Win32 example_glfw_opengl3
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build Win32 example_glfw_vulkan
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build Win32 example_sdl_vulkan
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build Win32 example_sdl_opengl2
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build Win32 example_sdl_opengl3
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+
+ - name: Build Win32 example_sdl_directx11
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build Win32 example_win32_directx9
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+
+ - name: Build Win32 example_win32_directx10
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+
+ - name: Build Win32 example_win32_directx11
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=Win32 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_glfw_opengl2
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_glfw_opengl3
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
+
+ - name: Build x64 example_glfw_vulkan
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
+
+ - name: Build x64 example_sdl_vulkan
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_sdl_opengl2
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_sdl_opengl3
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_sdl_directx11
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_sdl_directx11/example_sdl_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
+
+ - name: Build x64 example_win32_directx9
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx9/example_win32_directx9.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_win32_directx10
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx10/example_win32_directx10.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_win32_directx11
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx11/example_win32_directx11.vcxproj /p:Platform=x64 /p:Configuration=Release'
+ if: github.event_name == 'workflow_run'
+
+ - name: Build x64 example_win32_directx12
+ shell: cmd
+ run: '"%MSBUILD_PATH%\MSBuild.exe" examples/example_win32_directx12/example_win32_directx12.vcxproj /p:Platform=x64 /p:Configuration=Release'
+
+ Linux:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libglfw3-dev libsdl2-dev gcc-multilib g++-multilib libfreetype6-dev libvulkan-dev
+
+ - name: Build example_null (extra warnings, gcc 32-bit)
+ run: |
+ make -C examples/example_null clean
+ CXXFLAGS="$CXXFLAGS -m32 -Werror" make -C examples/example_null WITH_EXTRA_WARNINGS=1
+
+ - name: Build example_null (extra warnings, gcc 64-bit)
+ run: |
+ make -C examples/example_null clean
+ CXXFLAGS="$CXXFLAGS -m64 -Werror" make -C examples/example_null WITH_EXTRA_WARNINGS=1
+
+ - name: Build example_null (extra warnings, clang 32-bit)
+ run: |
+ make -C examples/example_null clean
+ CXXFLAGS="$CXXFLAGS -m32 -Werror" CXX=clang++ make -C examples/example_null WITH_EXTRA_WARNINGS=1
+
+ - name: Build example_null (extra warnings, clang 64-bit)
+ run: |
+ make -C examples/example_null clean
+ CXXFLAGS="$CXXFLAGS -m64 -Werror" CXX=clang++ make -C examples/example_null WITH_EXTRA_WARNINGS=1
+
+ - name: Build example_null (extra warnings, empty IM_ASSERT)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IM_ASSERT(x)
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -Wextra -Werror -Wno-zero-as-null-pointer-constant -Wno-double-promotion -Wno-variadic-macros -Wno-empty-body -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (freetype)
+ run: |
+ make -C examples/example_null clean
+ make -C examples/example_null WITH_FREETYPE=1
+
+ - name: Build example_null (single file build)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with ImWchar32)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_USE_WCHAR32
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define ImTextureID void*
+ #define ImDrawIdx unsigned int
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with IMGUI_DISABLE_OBSOLETE_FUNCTIONS)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with IMGUI_DISABLE_DEMO_WINDOWS and IMGUI_DISABLE_METRICS_WINDOW)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_DISABLE_DEMO_WINDOWS
+ #define IMGUI_DISABLE_METRICS_WINDOW
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with IMGUI_DISABLE_FILE_FUNCTIONS)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_DISABLE_FILE_FUNCTIONS
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with IMGUI_USE_BGRA_PACKED_COLOR)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_USE_BGRA_PACKED_COLOR
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (with IM_VEC2_CLASS_EXTRA and IM_VEC4_CLASS_EXTRA)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ struct MyVec2 { float x; float y; MyVec2(float x, float y) : x(x), y(y) { } };
+ struct MyVec4 { float x; float y; float z; float w;
+ MyVec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { } };
+ #define IM_VEC2_CLASS_EXTRA \
+ ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
+ operator MyVec2() const { return MyVec2(x, y); }
+ #define IM_VEC4_CLASS_EXTRA \
+ ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
+ operator MyVec4() const { return MyVec4(x, y, z, w); }
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (without c++ runtime, Clang)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_IMPLEMENTATION
+ #define IMGUI_DISABLE_DEMO_WINDOWS
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
+
+ - name: Build example_glfw_opengl2
+ run: make -C examples/example_glfw_opengl2
+
+ - name: Build example_glfw_opengl3
+ run: make -C examples/example_glfw_opengl3
+ if: github.event_name == 'workflow_run'
+
+ - name: Build example_sdl_opengl2
+ run: make -C examples/example_sdl_opengl2
+ if: github.event_name == 'workflow_run'
+
+ - name: Build example_sdl_opengl3
+ run: make -C examples/example_sdl_opengl3
+
+ - name: Build with IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+ run: g++ -c -I. -DIMGUI_IMPL_VULKAN_NO_PROTOTYPES=1 backends/imgui_impl_vulkan.cpp
+
+ MacOS:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Dependencies
+ run: |
+ brew install glfw3 sdl2
+
+ - name: Build example_null (extra warnings, clang 64-bit)
+ run: make -C examples/example_null WITH_EXTRA_WARNINGS=1
+
+ - name: Build example_null (single file build)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ clang++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
+
+ - name: Build example_null (without c++ runtime)
+ run: |
+ cat > example_single_file.cpp <<'EOF'
+
+ #define IMGUI_IMPLEMENTATION
+ #include "misc/single_file/imgui_single_file.h"
+ #include "examples/example_null/main.cpp"
+
+ EOF
+ clang++ -I. -Wall -Wformat -nodefaultlibs -fno-rtti -fno-exceptions -fno-threadsafe-statics -lc -lm -o example_single_file example_single_file.cpp
+
+ - name: Build example_glfw_opengl2
+ run: make -C examples/example_glfw_opengl2
+
+ - name: Build example_glfw_opengl3
+ run: make -C examples/example_glfw_opengl3
+ if: github.event_name == 'workflow_run'
+
+ - name: Build example_glfw_metal
+ run: make -C examples/example_glfw_metal
+
+ - name: Build example_sdl_metal
+ run: make -C examples/example_sdl_metal
+
+ - name: Build example_sdl_opengl2
+ run: make -C examples/example_sdl_opengl2
+ if: github.event_name == 'workflow_run'
+
+ - name: Build example_sdl_opengl3
+ run: make -C examples/example_sdl_opengl3
+
+ - name: Build example_apple_metal
+ run: xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos
+
+ - name: Build example_apple_opengl2
+ run: xcodebuild -project examples/example_apple_opengl2/example_apple_opengl2.xcodeproj -target example_osx_opengl2
+
+ iOS:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Build example_apple_metal
+ run: |
+ # Code signing is required, but we disable it because it is irrelevant for CI builds.
+ xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_ios CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
+
+ Emscripten:
+ runs-on: ubuntu-18.04
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Dependencies
+ run: |
+ wget -q https://github.com/emscripten-core/emsdk/archive/master.tar.gz
+ tar -xvf master.tar.gz
+ emsdk-master/emsdk update
+ emsdk-master/emsdk install latest
+ emsdk-master/emsdk activate latest
+
+ - name: Build example_emscripten_opengl3
+ run: |
+ pushd emsdk-master
+ source ./emsdk_env.sh
+ popd
+ make -C examples/example_emscripten_opengl3
+
+ - name: Build example_emscripten_wgpu
+ run: |
+ pushd emsdk-master
+ source ./emsdk_env.sh
+ popd
+ make -C examples/example_emscripten_wgpu
+
+ Android:
+ runs-on: ubuntu-18.04
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Build example_android_opengl3
+ run: |
+ cd examples/example_android_opengl3/android
+ gradle assembleDebug
+
+ Discord-CI:
+ runs-on: ubuntu-18.04
+ if: always()
+ needs: [Windows, Linux, MacOS, iOS, Emscripten, Android]
+ steps:
+ - uses: dearimgui/github_discord_notifier@latest
+ with:
+ discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
+ github-token: ${{ github.token }}
+ action-task: discord-jobs
+ discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
+ discord-username: GitHub Actions
+ discord-job-new-failure-message: ''
+ discord-job-fixed-failure-message: ''
+ discord-job-new-failure-embed: |
+ {
+ "title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
+ "description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke [{{ job.name }}]({{ job.url }}) build job.\nFailing steps: {{ failing_steps }}",
+ "url": "{{ job.url }}",
+ "color": "0xFF0000",
+ "timestamp": "{{ run.updated_at }}"
+ }
+ discord-job-fixed-failure-embed: |
+ {
+ "title": "`{{ github.branch }}` branch is no longer failing!",
+ "description": "Build failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
+ "color": "0x00FF00",
+ "url": "{{ github.context.payload.head_commit.url }}",
+ "timestamp": "{{ run.completed_at }}"
+ }
diff --git a/Client/ThirdParty/imgui/.github/workflows/scheduled.yml b/Client/ThirdParty/imgui/.github/workflows/scheduled.yml
new file mode 100644
index 0000000..2a08578
--- /dev/null
+++ b/Client/ThirdParty/imgui/.github/workflows/scheduled.yml
@@ -0,0 +1,15 @@
+#
+# This is a dummy workflow used to trigger scheduled builds. Forked repositories most likely should disable this
+# workflow to avoid daily builds of inactive repositories.
+#
+name: scheduled
+
+on:
+ schedule:
+ - cron: '0 9 * * *'
+
+jobs:
+ scheduled:
+ runs-on: ubuntu-latest
+ steps:
+ - run: exit 0
diff --git a/Client/ThirdParty/imgui/.github/workflows/static-analysis.yml b/Client/ThirdParty/imgui/.github/workflows/static-analysis.yml
new file mode 100644
index 0000000..f3e6b2d
--- /dev/null
+++ b/Client/ThirdParty/imgui/.github/workflows/static-analysis.yml
@@ -0,0 +1,77 @@
+name: static-analysis
+
+on:
+ workflow_run:
+ # Perform static analysis together with build workflow. Build triggers of "build" workflow do not need to be repeated here.
+ workflows:
+ - build
+ types:
+ - requested
+
+jobs:
+ PVS-Studio:
+ runs-on: ubuntu-18.04
+ steps:
+ - uses: actions/checkout@v1
+ with:
+ fetch-depth: 1
+
+ - name: Install Dependencies
+ env:
+ # The Secret variable setup in GitHub must be in format: "name_or_email key", on a single line
+ PVS_STUDIO_LICENSE: ${{ secrets.PVS_STUDIO_LICENSE }}
+ run: |
+ if [[ "$PVS_STUDIO_LICENSE" != "" ]];
+ then
+ wget -q https://files.viva64.com/etc/pubkey.txt
+ sudo apt-key add pubkey.txt
+ sudo wget -O /etc/apt/sources.list.d/viva64.list https://files.viva64.com/etc/viva64.list
+ sudo apt-get update
+ sudo apt-get install -y pvs-studio
+ pvs-studio-analyzer credentials -o pvs-studio.lic $PVS_STUDIO_LICENSE
+ fi
+
+ - name: PVS-Studio static analysis
+ run: |
+ if [[ ! -f pvs-studio.lic ]];
+ then
+ echo "PVS Studio license is missing. No analysis will be performed."
+ echo "If you have a PVS Studio license please create a project secret named PVS_STUDIO_LICENSE with your license."
+ echo "You may use a free license. More information at https://www.viva64.com/en/b/0457/"
+ exit 0
+ fi
+ cd examples/example_null
+ pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
+ pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
+ plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log
+
+ Discord-CI:
+ runs-on: ubuntu-18.04
+ needs: [PVS-Studio]
+ if: always()
+ steps:
+ - uses: dearimgui/github_discord_notifier@latest
+ with:
+ discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
+ github-token: ${{ github.token }}
+ action-task: discord-jobs
+ discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
+ discord-username: GitHub Actions
+ discord-job-new-failure-message: ''
+ discord-job-fixed-failure-message: ''
+ discord-job-new-failure-embed: |
+ {
+ "title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
+ "description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke static analysis [{{ job.name }}]({{ job.url }}) job.\nFailing steps: {{ failing_steps }}",
+ "url": "{{ job.url }}",
+ "color": "0xFF0000",
+ "timestamp": "{{ run.updated_at }}"
+ }
+ discord-job-fixed-failure-embed: |
+ {
+ "title": "`{{ github.branch }}` branch is no longer failing!",
+ "description": "Static analysis failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
+ "color": "0x00FF00",
+ "url": "{{ github.context.payload.head_commit.url }}",
+ "timestamp": "{{ run.completed_at }}"
+ }
diff --git a/Client/ThirdParty/imgui/.gitignore b/Client/ThirdParty/imgui/.gitignore
new file mode 100644
index 0000000..86bed60
--- /dev/null
+++ b/Client/ThirdParty/imgui/.gitignore
@@ -0,0 +1,53 @@
+## OSX artifacts
+.DS_Store
+
+## Dear ImGui artifacts
+imgui.ini
+
+## General build artifacts
+*.o
+*.obj
+*.exe
+examples/build/*
+examples/*/Debug/*
+examples/*/Release/*
+examples/*/x64/*
+
+## Visual Studio artifacts
+.vs
+ipch
+*.opensdf
+*.log
+*.pdb
+*.ilk
+*.user
+*.sdf
+*.suo
+*.VC.db
+*.VC.VC.opendb
+
+## Commonly used CMake directories
+/build*/
+
+## Xcode artifacts
+project.xcworkspace
+xcuserdata
+
+## Emscripten artifacts
+examples/*.o.tmp
+examples/*.out.js
+examples/*.out.wasm
+examples/example_emscripten_opengl3/web/*
+examples/example_emscripten_wgpu/web/*
+
+## JetBrains IDE artifacts
+.idea
+cmake-build-*
+
+## Unix executables from our example Makefiles
+examples/example_glfw_opengl2/example_glfw_opengl2
+examples/example_glfw_opengl3/example_glfw_opengl3
+examples/example_glut_opengl2/example_glut_opengl2
+examples/example_null/example_null
+examples/example_sdl_opengl2/example_sdl_opengl2
+examples/example_sdl_opengl3/example_sdl_opengl3
diff --git a/Client/ThirdParty/imgui/LICENSE.txt b/Client/ThirdParty/imgui/LICENSE.txt
new file mode 100644
index 0000000..780533d
--- /dev/null
+++ b/Client/ThirdParty/imgui/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2021 Omar Cornut
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_allegro5.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_allegro5.cpp
new file mode 100644
index 0000000..ccb1396
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_allegro5.cpp
@@ -0,0 +1,478 @@
+// dear imgui: Renderer + Platform Backend for Allegro 5
+// (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Platform: Clipboard support (from Allegro 5.1.12)
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// Issues:
+// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
+// [ ] Platform: Missing gamepad support.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-02-18: Change blending equation to preserve alpha in output buffer.
+// 2020-08-10: Inputs: Fixed horizontal mouse wheel direction.
+// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
+// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
+// 2019-05-11: Inputs: Don't filter character value from ALLEGRO_EVENT_KEY_CHAR before calling AddInputCharacter().
+// 2019-04-30: Renderer: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2018-11-30: Platform: Added touchscreen support.
+// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
+// 2018-06-13: Platform: Added clipboard support (from Allegro 5.1.12).
+// 2018-06-13: Renderer: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-06-13: Renderer: Backup/restore transform and clipping rectangle.
+// 2018-06-11: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
+// 2018-04-18: Misc: Renamed file from imgui_impl_a5.cpp to imgui_impl_allegro5.cpp.
+// 2018-04-18: Misc: Added support for 32-bit vertex indices to avoid conversion at runtime. Added imconfig_allegro5.h to enforce 32-bit indices when included from imgui.h.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplAllegro5_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+
+#include <stdint.h> // uint64_t
+#include <cstring> // memcpy
+#include "imgui.h"
+#include "imgui_impl_allegro5.h"
+
+// Allegro
+#include <allegro5/allegro.h>
+#include <allegro5/allegro_primitives.h>
+#ifdef _WIN32
+#include <allegro5/allegro_windows.h>
+#endif
+#define ALLEGRO_HAS_CLIPBOARD (ALLEGRO_VERSION_INT >= ((5 << 24) | (1 << 16) | (12 << 8))) // Clipboard only supported from Allegro 5.1.12
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#endif
+
+// Allegro Data
+struct ImGui_ImplAllegro5_Data
+{
+ ALLEGRO_DISPLAY* Display;
+ ALLEGRO_BITMAP* Texture;
+ double Time;
+ ALLEGRO_MOUSE_CURSOR* MouseCursorInvisible;
+ ALLEGRO_VERTEX_DECL* VertexDecl;
+ char* ClipboardTextData;
+
+ ImGui_ImplAllegro5_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+static ImGui_ImplAllegro5_Data* ImGui_ImplAllegro5_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplAllegro5_Data*)ImGui::GetIO().BackendPlatformUserData : NULL; }
+
+struct ImDrawVertAllegro
+{
+ ImVec2 pos;
+ ImVec2 uv;
+ ALLEGRO_COLOR col;
+};
+
+static void ImGui_ImplAllegro5_SetupRenderState(ImDrawData* draw_data)
+{
+ // Setup blending
+ al_set_separate_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA, ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA);
+
+ // Setup orthographic projection matrix
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
+ {
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ ALLEGRO_TRANSFORM transform;
+ al_identity_transform(&transform);
+ al_use_transform(&transform);
+ al_orthographic_transform(&transform, L, T, 1.0f, R, B, -1.0f);
+ al_use_projection_transform(&transform);
+ }
+}
+
+// Render function.
+void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ // Backup Allegro state that will be modified
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ ALLEGRO_TRANSFORM last_transform = *al_get_current_transform();
+ ALLEGRO_TRANSFORM last_projection_transform = *al_get_current_projection_transform();
+ int last_clip_x, last_clip_y, last_clip_w, last_clip_h;
+ al_get_clipping_rectangle(&last_clip_x, &last_clip_y, &last_clip_w, &last_clip_h);
+ int last_blender_op, last_blender_src, last_blender_dst;
+ al_get_blender(&last_blender_op, &last_blender_src, &last_blender_dst);
+
+ // Setup desired render state
+ ImGui_ImplAllegro5_SetupRenderState(draw_data);
+
+ // Render command lists
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+
+ // Allegro's implementation of al_draw_indexed_prim() for DX9 is completely broken. Unindex our buffers ourselves.
+ // FIXME-OPT: Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 float as well..
+ static ImVector<ImDrawVertAllegro> vertices;
+ vertices.resize(cmd_list->IdxBuffer.Size);
+ for (int i = 0; i < cmd_list->IdxBuffer.Size; i++)
+ {
+ const ImDrawVert* src_v = &cmd_list->VtxBuffer[cmd_list->IdxBuffer[i]];
+ ImDrawVertAllegro* dst_v = &vertices[i];
+ dst_v->pos = src_v->pos;
+ dst_v->uv = src_v->uv;
+ unsigned char* c = (unsigned char*)&src_v->col;
+ dst_v->col = al_map_rgba(c[0], c[1], c[2], c[3]);
+ }
+
+ const int* indices = NULL;
+ if (sizeof(ImDrawIdx) == 2)
+ {
+ // FIXME-OPT: Unfortunately Allegro doesn't support 16-bit indices.. You can '#define ImDrawIdx int' in imconfig.h to request Dear ImGui to output 32-bit indices.
+ // Otherwise, we convert them from 16-bit to 32-bit at runtime here, which works perfectly but is a little wasteful.
+ static ImVector<int> indices_converted;
+ indices_converted.resize(cmd_list->IdxBuffer.Size);
+ for (int i = 0; i < cmd_list->IdxBuffer.Size; ++i)
+ indices_converted[i] = (int)cmd_list->IdxBuffer.Data[i];
+ indices = indices_converted.Data;
+ }
+ else if (sizeof(ImDrawIdx) == 4)
+ {
+ indices = (const int*)cmd_list->IdxBuffer.Data;
+ }
+
+ // Render command lists
+ int idx_offset = 0;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplAllegro5_SetupRenderState(draw_data);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle, Draw
+ ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID();
+ al_set_clipping_rectangle(clip_min.x, clip_min.y, clip_max.x - clip_min.x, clip_max.y - clip_min.y);
+ al_draw_prim(&vertices[0], bd->VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
+ }
+ idx_offset += pcmd->ElemCount;
+ }
+ }
+
+ // Restore modified Allegro state
+ al_set_blender(last_blender_op, last_blender_src, last_blender_dst);
+ al_set_clipping_rectangle(last_clip_x, last_clip_y, last_clip_w, last_clip_h);
+ al_use_transform(&last_transform);
+ al_use_projection_transform(&last_projection_transform);
+}
+
+bool ImGui_ImplAllegro5_CreateDeviceObjects()
+{
+ // Build texture atlas
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Create texture
+ int flags = al_get_new_bitmap_flags();
+ int fmt = al_get_new_bitmap_format();
+ al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
+ al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE);
+ ALLEGRO_BITMAP* img = al_create_bitmap(width, height);
+ al_set_new_bitmap_flags(flags);
+ al_set_new_bitmap_format(fmt);
+ if (!img)
+ return false;
+
+ ALLEGRO_LOCKED_REGION* locked_img = al_lock_bitmap(img, al_get_bitmap_format(img), ALLEGRO_LOCK_WRITEONLY);
+ if (!locked_img)
+ {
+ al_destroy_bitmap(img);
+ return false;
+ }
+ memcpy(locked_img->data, pixels, sizeof(int) * width * height);
+ al_unlock_bitmap(img);
+
+ // Convert software texture to hardware texture.
+ ALLEGRO_BITMAP* cloned_img = al_clone_bitmap(img);
+ al_destroy_bitmap(img);
+ if (!cloned_img)
+ return false;
+
+ // Store our identifier
+ io.Fonts->SetTexID((void*)cloned_img);
+ bd->Texture = cloned_img;
+
+ // Create an invisible mouse cursor
+ // Because al_hide_mouse_cursor() seems to mess up with the actual inputs..
+ ALLEGRO_BITMAP* mouse_cursor = al_create_bitmap(8, 8);
+ bd->MouseCursorInvisible = al_create_mouse_cursor(mouse_cursor, 0, 0);
+ al_destroy_bitmap(mouse_cursor);
+
+ return true;
+}
+
+void ImGui_ImplAllegro5_InvalidateDeviceObjects()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ if (bd->Texture)
+ {
+ io.Fonts->SetTexID(NULL);
+ al_destroy_bitmap(bd->Texture);
+ bd->Texture = NULL;
+ }
+ if (bd->MouseCursorInvisible)
+ {
+ al_destroy_mouse_cursor(bd->MouseCursorInvisible);
+ bd->MouseCursorInvisible = NULL;
+ }
+}
+
+#if ALLEGRO_HAS_CLIPBOARD
+static const char* ImGui_ImplAllegro5_GetClipboardText(void*)
+{
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ if (bd->ClipboardTextData)
+ al_free(bd->ClipboardTextData);
+ bd->ClipboardTextData = al_get_clipboard_text(bd->Display);
+ return bd->ClipboardTextData;
+}
+
+static void ImGui_ImplAllegro5_SetClipboardText(void*, const char* text)
+{
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ al_set_clipboard_text(bd->Display, text);
+}
+#endif
+
+bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplAllegro5_Data* bd = IM_NEW(ImGui_ImplAllegro5_Data)();
+ io.BackendPlatformUserData = (void*)bd;
+ io.BackendPlatformName = io.BackendRendererName = "imgui_impl_allegro5";
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+
+ bd->Display = display;
+
+ // Create custom vertex declaration.
+ // Unfortunately Allegro doesn't support 32-bit packed colors so we have to convert them to 4 floats.
+ // We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion.
+ ALLEGRO_VERTEX_ELEMENT elems[] =
+ {
+ { ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, pos) },
+ { ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, uv) },
+ { ALLEGRO_PRIM_COLOR_ATTR, 0, IM_OFFSETOF(ImDrawVertAllegro, col) },
+ { 0, 0, 0 }
+ };
+ bd->VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro));
+
+ io.KeyMap[ImGuiKey_Tab] = ALLEGRO_KEY_TAB;
+ io.KeyMap[ImGuiKey_LeftArrow] = ALLEGRO_KEY_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = ALLEGRO_KEY_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = ALLEGRO_KEY_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = ALLEGRO_KEY_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = ALLEGRO_KEY_PGUP;
+ io.KeyMap[ImGuiKey_PageDown] = ALLEGRO_KEY_PGDN;
+ io.KeyMap[ImGuiKey_Home] = ALLEGRO_KEY_HOME;
+ io.KeyMap[ImGuiKey_End] = ALLEGRO_KEY_END;
+ io.KeyMap[ImGuiKey_Insert] = ALLEGRO_KEY_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE;
+ io.KeyMap[ImGuiKey_Space] = ALLEGRO_KEY_SPACE;
+ io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER;
+ io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = ALLEGRO_KEY_PAD_ENTER;
+ io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A;
+ io.KeyMap[ImGuiKey_C] = ALLEGRO_KEY_C;
+ io.KeyMap[ImGuiKey_V] = ALLEGRO_KEY_V;
+ io.KeyMap[ImGuiKey_X] = ALLEGRO_KEY_X;
+ io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y;
+ io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z;
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+
+#if ALLEGRO_HAS_CLIPBOARD
+ io.SetClipboardTextFn = ImGui_ImplAllegro5_SetClipboardText;
+ io.GetClipboardTextFn = ImGui_ImplAllegro5_GetClipboardText;
+ io.ClipboardUserData = NULL;
+#endif
+
+ return true;
+}
+
+void ImGui_ImplAllegro5_Shutdown()
+{
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplAllegro5_InvalidateDeviceObjects();
+ if (bd->VertexDecl)
+ al_destroy_vertex_decl(bd->VertexDecl);
+ if (bd->ClipboardTextData)
+ al_free(bd->ClipboardTextData);
+
+ io.BackendPlatformUserData = NULL;
+ io.BackendPlatformName = io.BackendRendererName = NULL;
+ IM_DELETE(bd);
+}
+
+// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* ev)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+
+ switch (ev->type)
+ {
+ case ALLEGRO_EVENT_MOUSE_AXES:
+ if (ev->mouse.display == bd->Display)
+ {
+ io.MouseWheel += ev->mouse.dz;
+ io.MouseWheelH -= ev->mouse.dw;
+ io.MousePos = ImVec2(ev->mouse.x, ev->mouse.y);
+ }
+ return true;
+ case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
+ case ALLEGRO_EVENT_MOUSE_BUTTON_UP:
+ if (ev->mouse.display == bd->Display && ev->mouse.button <= 5)
+ io.MouseDown[ev->mouse.button - 1] = (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN);
+ return true;
+ case ALLEGRO_EVENT_TOUCH_MOVE:
+ if (ev->touch.display == bd->Display)
+ io.MousePos = ImVec2(ev->touch.x, ev->touch.y);
+ return true;
+ case ALLEGRO_EVENT_TOUCH_BEGIN:
+ case ALLEGRO_EVENT_TOUCH_END:
+ case ALLEGRO_EVENT_TOUCH_CANCEL:
+ if (ev->touch.display == bd->Display && ev->touch.primary)
+ io.MouseDown[0] = (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN);
+ return true;
+ case ALLEGRO_EVENT_MOUSE_LEAVE_DISPLAY:
+ if (ev->mouse.display == bd->Display)
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+ return true;
+ case ALLEGRO_EVENT_KEY_CHAR:
+ if (ev->keyboard.display == bd->Display)
+ if (ev->keyboard.unichar != 0)
+ io.AddInputCharacter((unsigned int)ev->keyboard.unichar);
+ return true;
+ case ALLEGRO_EVENT_KEY_DOWN:
+ case ALLEGRO_EVENT_KEY_UP:
+ if (ev->keyboard.display == bd->Display)
+ io.KeysDown[ev->keyboard.keycode] = (ev->type == ALLEGRO_EVENT_KEY_DOWN);
+ return true;
+ case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT:
+ if (ev->display.source == bd->Display)
+ io.AddFocusEvent(false);
+ return true;
+ case ALLEGRO_EVENT_DISPLAY_SWITCH_IN:
+ if (ev->display.source == bd->Display)
+ {
+ io.AddFocusEvent(true);
+#if defined(ALLEGRO_UNSTABLE)
+ al_clear_keyboard_state(bd->Display);
+#endif
+ }
+ return true;
+ }
+ return false;
+}
+
+static void ImGui_ImplAllegro5_UpdateMouseCursor()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return;
+
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
+ if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
+ {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ al_set_mouse_cursor(bd->Display, bd->MouseCursorInvisible);
+ }
+ else
+ {
+ ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_DEFAULT;
+ switch (imgui_cursor)
+ {
+ case ImGuiMouseCursor_TextInput: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_EDIT; break;
+ case ImGuiMouseCursor_ResizeAll: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break;
+ case ImGuiMouseCursor_ResizeNS: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_N; break;
+ case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break;
+ case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break;
+ case ImGuiMouseCursor_ResizeNWSE: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NW; break;
+ case ImGuiMouseCursor_NotAllowed: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_UNAVAILABLE; break;
+ }
+ al_set_system_mouse_cursor(bd->Display, cursor_id);
+ }
+}
+
+void ImGui_ImplAllegro5_NewFrame()
+{
+ ImGui_ImplAllegro5_Data* bd = ImGui_ImplAllegro5_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplAllegro5_Init()?");
+
+ if (!bd->Texture)
+ ImGui_ImplAllegro5_CreateDeviceObjects();
+
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup display size (every frame to accommodate for window resizing)
+ int w, h;
+ w = al_get_display_width(bd->Display);
+ h = al_get_display_height(bd->Display);
+ io.DisplaySize = ImVec2((float)w, (float)h);
+
+ // Setup time step
+ double current_time = al_get_time();
+ io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
+ bd->Time = current_time;
+
+ // Setup inputs
+ ALLEGRO_KEYBOARD_STATE keys;
+ al_get_keyboard_state(&keys);
+ io.KeyCtrl = al_key_down(&keys, ALLEGRO_KEY_LCTRL) || al_key_down(&keys, ALLEGRO_KEY_RCTRL);
+ io.KeyShift = al_key_down(&keys, ALLEGRO_KEY_LSHIFT) || al_key_down(&keys, ALLEGRO_KEY_RSHIFT);
+ io.KeyAlt = al_key_down(&keys, ALLEGRO_KEY_ALT) || al_key_down(&keys, ALLEGRO_KEY_ALTGR);
+ io.KeySuper = al_key_down(&keys, ALLEGRO_KEY_LWIN) || al_key_down(&keys, ALLEGRO_KEY_RWIN);
+
+ ImGui_ImplAllegro5_UpdateMouseCursor();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_allegro5.h b/Client/ThirdParty/imgui/backends/imgui_impl_allegro5.h
new file mode 100644
index 0000000..06c7120
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_allegro5.h
@@ -0,0 +1,31 @@
+// dear imgui: Renderer + Platform Backend for Allegro 5
+// (Info: Allegro 5 is a cross-platform general purpose library for handling windows, inputs, graphics, etc.)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Platform: Clipboard support (from Allegro 5.1.12)
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// Issues:
+// [ ] Renderer: The renderer is suboptimal as we need to unindex our buffers and convert vertices manually.
+// [ ] Platform: Missing gamepad support.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct ALLEGRO_DISPLAY;
+union ALLEGRO_EVENT;
+
+IMGUI_IMPL_API bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display);
+IMGUI_IMPL_API void ImGui_ImplAllegro5_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplAllegro5_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data);
+IMGUI_IMPL_API bool ImGui_ImplAllegro5_ProcessEvent(ALLEGRO_EVENT* event);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API bool ImGui_ImplAllegro5_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplAllegro5_InvalidateDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_android.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_android.cpp
new file mode 100644
index 0000000..aae8e6b
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_android.cpp
@@ -0,0 +1,187 @@
+// dear imgui: Platform Binding for Android native app
+// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
+
+// Implemented features:
+// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
+// Missing features:
+// [ ] Platform: Clipboard support.
+// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
+// Important:
+// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
+// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-03-04: Initial version.
+
+#include "imgui.h"
+#include "imgui_impl_android.h"
+#include <time.h>
+#include <map>
+#include <queue>
+#include <android/native_window.h>
+#include <android/input.h>
+#include <android/keycodes.h>
+#include <android/log.h>
+
+// Android data
+static double g_Time = 0.0;
+static ANativeWindow* g_Window;
+static char g_LogTag[] = "ImGuiExample";
+static std::map<int32_t, std::queue<int32_t>> g_KeyEventQueues; // FIXME: Remove dependency on map and queue once we use upcoming input queue.
+
+int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ int32_t event_type = AInputEvent_getType(input_event);
+ switch (event_type)
+ {
+ case AINPUT_EVENT_TYPE_KEY:
+ {
+ int32_t event_key_code = AKeyEvent_getKeyCode(input_event);
+ int32_t event_action = AKeyEvent_getAction(input_event);
+ int32_t event_meta_state = AKeyEvent_getMetaState(input_event);
+
+ io.KeyCtrl = ((event_meta_state & AMETA_CTRL_ON) != 0);
+ io.KeyShift = ((event_meta_state & AMETA_SHIFT_ON) != 0);
+ io.KeyAlt = ((event_meta_state & AMETA_ALT_ON) != 0);
+
+ switch (event_action)
+ {
+ // FIXME: AKEY_EVENT_ACTION_DOWN and AKEY_EVENT_ACTION_UP occur at once as soon as a touch pointer
+ // goes up from a key. We use a simple key event queue/ and process one event per key per frame in
+ // ImGui_ImplAndroid_NewFrame()...or consider using IO queue, if suitable: https://github.com/ocornut/imgui/issues/2787
+ case AKEY_EVENT_ACTION_DOWN:
+ case AKEY_EVENT_ACTION_UP:
+ g_KeyEventQueues[event_key_code].push(event_action);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case AINPUT_EVENT_TYPE_MOTION:
+ {
+ int32_t event_action = AMotionEvent_getAction(input_event);
+ int32_t event_pointer_index = (event_action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
+ event_action &= AMOTION_EVENT_ACTION_MASK;
+ switch (event_action)
+ {
+ case AMOTION_EVENT_ACTION_DOWN:
+ case AMOTION_EVENT_ACTION_UP:
+ // Physical mouse buttons (and probably other physical devices) also invoke the actions AMOTION_EVENT_ACTION_DOWN/_UP,
+ // but we have to process them separately to identify the actual button pressed. This is done below via
+ // AMOTION_EVENT_ACTION_BUTTON_PRESS/_RELEASE. Here, we only process "FINGER" input (and "UNKNOWN", as a fallback).
+ if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
+ || (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
+ {
+ io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN);
+ io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
+ }
+ break;
+ case AMOTION_EVENT_ACTION_BUTTON_PRESS:
+ case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
+ {
+ int32_t button_state = AMotionEvent_getButtonState(input_event);
+ io.MouseDown[0] = ((button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
+ io.MouseDown[1] = ((button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
+ io.MouseDown[2] = ((button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
+ }
+ break;
+ case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse)
+ case AMOTION_EVENT_ACTION_MOVE: // Touch pointer moves while DOWN
+ io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
+ break;
+ case AMOTION_EVENT_ACTION_SCROLL:
+ io.MouseWheel = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_VSCROLL, event_pointer_index);
+ io.MouseWheelH = AMotionEvent_getAxisValue(input_event, AMOTION_EVENT_AXIS_HSCROLL, event_pointer_index);
+ break;
+ default:
+ break;
+ }
+ }
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+bool ImGui_ImplAndroid_Init(ANativeWindow* window)
+{
+ g_Window = window;
+ g_Time = 0.0;
+
+ // Setup backend capabilities flags
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendPlatformName = "imgui_impl_android";
+
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
+ io.KeyMap[ImGuiKey_Tab] = AKEYCODE_TAB;
+ io.KeyMap[ImGuiKey_LeftArrow] = AKEYCODE_DPAD_LEFT; // also covers physical keyboard arrow key
+ io.KeyMap[ImGuiKey_RightArrow] = AKEYCODE_DPAD_RIGHT; // also covers physical keyboard arrow key
+ io.KeyMap[ImGuiKey_UpArrow] = AKEYCODE_DPAD_UP; // also covers physical keyboard arrow key
+ io.KeyMap[ImGuiKey_DownArrow] = AKEYCODE_DPAD_DOWN; // also covers physical keyboard arrow key
+ io.KeyMap[ImGuiKey_PageUp] = AKEYCODE_PAGE_UP;
+ io.KeyMap[ImGuiKey_PageDown] = AKEYCODE_PAGE_DOWN;
+ io.KeyMap[ImGuiKey_Home] = AKEYCODE_MOVE_HOME;
+ io.KeyMap[ImGuiKey_End] = AKEYCODE_MOVE_END;
+ io.KeyMap[ImGuiKey_Insert] = AKEYCODE_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = AKEYCODE_FORWARD_DEL;
+ io.KeyMap[ImGuiKey_Backspace] = AKEYCODE_DEL;
+ io.KeyMap[ImGuiKey_Space] = AKEYCODE_SPACE;
+ io.KeyMap[ImGuiKey_Enter] = AKEYCODE_ENTER;
+ io.KeyMap[ImGuiKey_Escape] = AKEYCODE_ESCAPE;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = AKEYCODE_NUMPAD_ENTER;
+ io.KeyMap[ImGuiKey_A] = AKEYCODE_A;
+ io.KeyMap[ImGuiKey_C] = AKEYCODE_C;
+ io.KeyMap[ImGuiKey_V] = AKEYCODE_V;
+ io.KeyMap[ImGuiKey_X] = AKEYCODE_X;
+ io.KeyMap[ImGuiKey_Y] = AKEYCODE_Y;
+ io.KeyMap[ImGuiKey_Z] = AKEYCODE_Z;
+
+ return true;
+}
+
+void ImGui_ImplAndroid_Shutdown()
+{
+}
+
+void ImGui_ImplAndroid_NewFrame()
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Process queued key events
+ // FIXME: This is a workaround for multiple key event actions occurring at once (see above) and can be removed once we use upcoming input queue.
+ for (auto& key_queue : g_KeyEventQueues)
+ {
+ if (key_queue.second.empty())
+ continue;
+ io.KeysDown[key_queue.first] = (key_queue.second.front() == AKEY_EVENT_ACTION_DOWN);
+ key_queue.second.pop();
+ }
+
+ // Setup display size (every frame to accommodate for window resizing)
+ int32_t window_width = ANativeWindow_getWidth(g_Window);
+ int32_t window_height = ANativeWindow_getHeight(g_Window);
+ int display_width = window_width;
+ int display_height = window_height;
+
+ io.DisplaySize = ImVec2((float)window_width, (float)window_height);
+ if (window_width > 0 && window_height > 0)
+ io.DisplayFramebufferScale = ImVec2((float)display_width / window_width, (float)display_height / window_height);
+
+ // Setup time step
+ struct timespec current_timespec;
+ clock_gettime(CLOCK_MONOTONIC, &current_timespec);
+ double current_time = (double)(current_timespec.tv_sec) + (current_timespec.tv_nsec / 1000000000.0);
+ io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
+ g_Time = current_time;
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_android.h b/Client/ThirdParty/imgui/backends/imgui_impl_android.h
new file mode 100644
index 0000000..92b466b
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_android.h
@@ -0,0 +1,27 @@
+// dear imgui: Platform Binding for Android native app
+// This needs to be used along with the OpenGL 3 Renderer (imgui_impl_opengl3)
+
+// Implemented features:
+// [X] Platform: Keyboard arrays indexed using AKEYCODE_* codes, e.g. ImGui::IsKeyPressed(AKEYCODE_SPACE).
+// Missing features:
+// [ ] Platform: Clipboard support.
+// [ ] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// [ ] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: Check if this is even possible with Android.
+// Important:
+// - FIXME: On-screen keyboard currently needs to be enabled by the application (see examples/ and issue #3446)
+// - FIXME: Unicode character inputs needs to be passed by Dear ImGui by the application (see examples/ and issue #3446)
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+
+struct ANativeWindow;
+struct AInputEvent;
+
+IMGUI_IMPL_API bool ImGui_ImplAndroid_Init(ANativeWindow* window);
+IMGUI_IMPL_API int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event);
+IMGUI_IMPL_API void ImGui_ImplAndroid_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplAndroid_NewFrame();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx10.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_dx10.cpp
new file mode 100644
index 0000000..5be46f6
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx10.cpp
@@ -0,0 +1,578 @@
+// dear imgui: Renderer Backend for DirectX10
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer.
+// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
+// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: DirectX10: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-07-13: DirectX10: Fixed unreleased resources in Init and Shutdown functions.
+// 2018-06-08: Misc: Extracted imgui_impl_dx10.cpp/.h away from the old combined DX10+Win32 example.
+// 2018-06-08: DirectX10: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-04-09: Misc: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) on other backends.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2016-05-07: DirectX10: Disabling depth-write.
+
+#include "imgui.h"
+#include "imgui_impl_dx10.h"
+
+// DirectX
+#include <stdio.h>
+#include <d3d10_1.h>
+#include <d3d10.h>
+#include <d3dcompiler.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
+#endif
+
+// DirectX data
+struct ImGui_ImplDX10_Data
+{
+ ID3D10Device* pd3dDevice;
+ IDXGIFactory* pFactory;
+ ID3D10Buffer* pVB;
+ ID3D10Buffer* pIB;
+ ID3D10VertexShader* pVertexShader;
+ ID3D10InputLayout* pInputLayout;
+ ID3D10Buffer* pVertexConstantBuffer;
+ ID3D10PixelShader* pPixelShader;
+ ID3D10SamplerState* pFontSampler;
+ ID3D10ShaderResourceView* pFontTextureView;
+ ID3D10RasterizerState* pRasterizerState;
+ ID3D10BlendState* pBlendState;
+ ID3D10DepthStencilState* pDepthStencilState;
+ int VertexBufferSize;
+ int IndexBufferSize;
+
+ ImGui_ImplDX10_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
+};
+
+struct VERTEX_CONSTANT_BUFFER
+{
+ float mvp[4][4];
+};
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX10_Data* ImGui_ImplDX10_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplDX10_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device* ctx)
+{
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+
+ // Setup viewport
+ D3D10_VIEWPORT vp;
+ memset(&vp, 0, sizeof(D3D10_VIEWPORT));
+ vp.Width = (UINT)draw_data->DisplaySize.x;
+ vp.Height = (UINT)draw_data->DisplaySize.y;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = vp.TopLeftY = 0;
+ ctx->RSSetViewports(1, &vp);
+
+ // Bind shader and vertex buffers
+ unsigned int stride = sizeof(ImDrawVert);
+ unsigned int offset = 0;
+ ctx->IASetInputLayout(bd->pInputLayout);
+ ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
+ ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
+ ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->VSSetShader(bd->pVertexShader);
+ ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
+ ctx->PSSetShader(bd->pPixelShader);
+ ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
+ ctx->GSSetShader(NULL);
+
+ // Setup render state
+ const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
+ ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
+ ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
+ ctx->RSSetState(bd->pRasterizerState);
+}
+
+// Render function
+void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+ ID3D10Device* ctx = bd->pd3dDevice;
+
+ // Create and grow vertex/index buffers if needed
+ if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
+ D3D10_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
+ desc.Usage = D3D10_USAGE_DYNAMIC;
+ desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
+ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
+ desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ if (ctx->CreateBuffer(&desc, NULL, &bd->pVB) < 0)
+ return;
+ }
+
+ if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
+ D3D10_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D10_BUFFER_DESC));
+ desc.Usage = D3D10_USAGE_DYNAMIC;
+ desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
+ desc.BindFlags = D3D10_BIND_INDEX_BUFFER;
+ desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+ if (ctx->CreateBuffer(&desc, NULL, &bd->pIB) < 0)
+ return;
+ }
+
+ // Copy and convert all vertices into a single contiguous buffer
+ ImDrawVert* vtx_dst = NULL;
+ ImDrawIdx* idx_dst = NULL;
+ bd->pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst);
+ bd->pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst);
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ bd->pVB->Unmap();
+ bd->pIB->Unmap();
+
+ // Setup orthographic projection matrix into our constant buffer
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ {
+ void* mapped_resource;
+ if (bd->pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
+ return;
+ VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource;
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ float mvp[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ };
+ memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
+ bd->pVertexConstantBuffer->Unmap();
+ }
+
+ // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
+ struct BACKUP_DX10_STATE
+ {
+ UINT ScissorRectsCount, ViewportsCount;
+ D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ ID3D10RasterizerState* RS;
+ ID3D10BlendState* BlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+ UINT StencilRef;
+ ID3D10DepthStencilState* DepthStencilState;
+ ID3D10ShaderResourceView* PSShaderResource;
+ ID3D10SamplerState* PSSampler;
+ ID3D10PixelShader* PS;
+ ID3D10VertexShader* VS;
+ ID3D10GeometryShader* GS;
+ D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology;
+ ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
+ UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
+ DXGI_FORMAT IndexBufferFormat;
+ ID3D10InputLayout* InputLayout;
+ };
+ BACKUP_DX10_STATE old = {};
+ old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
+ ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
+ ctx->RSGetState(&old.RS);
+ ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
+ ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
+ ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
+ ctx->PSGetSamplers(0, 1, &old.PSSampler);
+ ctx->PSGetShader(&old.PS);
+ ctx->VSGetShader(&old.VS);
+ ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
+ ctx->GSGetShader(&old.GS);
+ ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
+ ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
+ ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+ ctx->IAGetInputLayout(&old.InputLayout);
+
+ // Setup desired DX state
+ ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_vtx_offset = 0;
+ int global_idx_offset = 0;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplDX10_SetupRenderState(draw_data, ctx);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle
+ const D3D10_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+ ctx->RSSetScissorRects(1, &r);
+
+ // Bind texture, Draw
+ ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID();
+ ctx->PSSetShaderResources(0, 1, &texture_srv);
+ ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+
+ // Restore modified DX state
+ ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
+ ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
+ ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
+ ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
+ ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
+ ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
+ ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
+ ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release();
+ ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release();
+ ctx->GSSetShader(old.GS); if (old.GS) old.GS->Release();
+ ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
+ ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
+ ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
+ ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
+ ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+}
+
+static void ImGui_ImplDX10_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Upload texture to graphics system
+ {
+ D3D10_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D10_USAGE_DEFAULT;
+ desc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+
+ ID3D10Texture2D* pTexture = NULL;
+ D3D10_SUBRESOURCE_DATA subResource;
+ subResource.pSysMem = pixels;
+ subResource.SysMemPitch = desc.Width * 4;
+ subResource.SysMemSlicePitch = 0;
+ bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
+ IM_ASSERT(pTexture != NULL);
+
+ // Create texture view
+ D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
+ ZeroMemory(&srv_desc, sizeof(srv_desc));
+ srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
+ srv_desc.Texture2D.MipLevels = desc.MipLevels;
+ srv_desc.Texture2D.MostDetailedMip = 0;
+ bd->pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &bd->pFontTextureView);
+ pTexture->Release();
+ }
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
+
+ // Create texture sampler
+ {
+ D3D10_SAMPLER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP;
+ desc.MipLODBias = 0.f;
+ desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
+ desc.MinLOD = 0.f;
+ desc.MaxLOD = 0.f;
+ bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+ }
+}
+
+bool ImGui_ImplDX10_CreateDeviceObjects()
+{
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+ if (!bd->pd3dDevice)
+ return false;
+ if (bd->pFontSampler)
+ ImGui_ImplDX10_InvalidateDeviceObjects();
+
+ // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
+ // If you would like to use this DX10 sample code but remove this dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
+ // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // See https://github.com/ocornut/imgui/pull/638 for sources and details.
+
+ // Create the vertex shader
+ {
+ static const char* vertexShader =
+ "cbuffer vertexBuffer : register(b0) \
+ {\
+ float4x4 ProjectionMatrix; \
+ };\
+ struct VS_INPUT\
+ {\
+ float2 pos : POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ PS_INPUT main(VS_INPUT input)\
+ {\
+ PS_INPUT output;\
+ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
+ output.col = input.col;\
+ output.uv = input.uv;\
+ return output;\
+ }";
+
+ ID3DBlob* vertexShaderBlob;
+ if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
+ return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pVertexShader) != S_OK)
+ {
+ vertexShaderBlob->Release();
+ return false;
+ }
+
+ // Create the input layout
+ D3D10_INPUT_ELEMENT_DESC local_layout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D10_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D10_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D10_INPUT_PER_VERTEX_DATA, 0 },
+ };
+ if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
+ {
+ vertexShaderBlob->Release();
+ return false;
+ }
+ vertexShaderBlob->Release();
+
+ // Create the constant buffer
+ {
+ D3D10_BUFFER_DESC desc;
+ desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
+ desc.Usage = D3D10_USAGE_DYNAMIC;
+ desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER;
+ desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer);
+ }
+ }
+
+ // Create the pixel shader
+ {
+ static const char* pixelShader =
+ "struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ sampler sampler0;\
+ Texture2D texture0;\
+ \
+ float4 main(PS_INPUT input) : SV_Target\
+ {\
+ float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
+ return out_col; \
+ }";
+
+ ID3DBlob* pixelShaderBlob;
+ if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
+ return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), &bd->pPixelShader) != S_OK)
+ {
+ pixelShaderBlob->Release();
+ return false;
+ }
+ pixelShaderBlob->Release();
+ }
+
+ // Create the blending setup
+ {
+ D3D10_BLEND_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.AlphaToCoverageEnable = false;
+ desc.BlendEnable[0] = true;
+ desc.SrcBlend = D3D10_BLEND_SRC_ALPHA;
+ desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
+ desc.BlendOp = D3D10_BLEND_OP_ADD;
+ desc.SrcBlendAlpha = D3D10_BLEND_ONE;
+ desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+ desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+ desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
+ bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
+ }
+
+ // Create the rasterizer state
+ {
+ D3D10_RASTERIZER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.FillMode = D3D10_FILL_SOLID;
+ desc.CullMode = D3D10_CULL_NONE;
+ desc.ScissorEnable = true;
+ desc.DepthClipEnable = true;
+ bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
+ }
+
+ // Create depth-stencil State
+ {
+ D3D10_DEPTH_STENCIL_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D10_COMPARISON_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
+ desc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
+ desc.BackFace = desc.FrontFace;
+ bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
+ }
+
+ ImGui_ImplDX10_CreateFontsTexture();
+
+ return true;
+}
+
+void ImGui_ImplDX10_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+ if (!bd->pd3dDevice)
+ return;
+
+ if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; }
+ if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; }
+ if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; }
+ if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; }
+ if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = NULL; }
+ if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; }
+ if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = NULL; }
+ if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = NULL; }
+}
+
+bool ImGui_ImplDX10_Init(ID3D10Device* device)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplDX10_Data* bd = IM_NEW(ImGui_ImplDX10_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_dx10";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ // Get factory from device
+ IDXGIDevice* pDXGIDevice = NULL;
+ IDXGIAdapter* pDXGIAdapter = NULL;
+ IDXGIFactory* pFactory = NULL;
+ if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
+ if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
+ if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
+ {
+ bd->pd3dDevice = device;
+ bd->pFactory = pFactory;
+ }
+ if (pDXGIDevice) pDXGIDevice->Release();
+ if (pDXGIAdapter) pDXGIAdapter->Release();
+ bd->pd3dDevice->AddRef();
+
+ return true;
+}
+
+void ImGui_ImplDX10_Shutdown()
+{
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplDX10_InvalidateDeviceObjects();
+ if (bd->pFactory) { bd->pFactory->Release(); }
+ if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+void ImGui_ImplDX10_NewFrame()
+{
+ ImGui_ImplDX10_Data* bd = ImGui_ImplDX10_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX10_Init()?");
+
+ if (!bd->pFontSampler)
+ ImGui_ImplDX10_CreateDeviceObjects();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx10.h b/Client/ThirdParty/imgui/backends/imgui_impl_dx10.h
new file mode 100644
index 0000000..31e62ac
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx10.h
@@ -0,0 +1,25 @@
+// dear imgui: Renderer Backend for DirectX10
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture backend. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct ID3D10Device;
+
+IMGUI_IMPL_API bool ImGui_ImplDX10_Init(ID3D10Device* device);
+IMGUI_IMPL_API void ImGui_ImplDX10_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplDX10_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API void ImGui_ImplDX10_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_ImplDX10_CreateDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx11.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_dx11.cpp
new file mode 100644
index 0000000..bfe5dca
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx11.cpp
@@ -0,0 +1,594 @@
+// dear imgui: Renderer Backend for DirectX11
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
+// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
+// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
+// 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility.
+// 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions.
+// 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example.
+// 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2016-05-07: DirectX11: Disabling depth-write.
+
+#include "imgui.h"
+#include "imgui_impl_dx11.h"
+
+// DirectX
+#include <stdio.h>
+#include <d3d11.h>
+#include <d3dcompiler.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
+#endif
+
+// DirectX11 data
+struct ImGui_ImplDX11_Data
+{
+ ID3D11Device* pd3dDevice;
+ ID3D11DeviceContext* pd3dDeviceContext;
+ IDXGIFactory* pFactory;
+ ID3D11Buffer* pVB;
+ ID3D11Buffer* pIB;
+ ID3D11VertexShader* pVertexShader;
+ ID3D11InputLayout* pInputLayout;
+ ID3D11Buffer* pVertexConstantBuffer;
+ ID3D11PixelShader* pPixelShader;
+ ID3D11SamplerState* pFontSampler;
+ ID3D11ShaderResourceView* pFontTextureView;
+ ID3D11RasterizerState* pRasterizerState;
+ ID3D11BlendState* pBlendState;
+ ID3D11DepthStencilState* pDepthStencilState;
+ int VertexBufferSize;
+ int IndexBufferSize;
+
+ ImGui_ImplDX11_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
+};
+
+struct VERTEX_CONSTANT_BUFFER
+{
+ float mvp[4][4];
+};
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx)
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+
+ // Setup viewport
+ D3D11_VIEWPORT vp;
+ memset(&vp, 0, sizeof(D3D11_VIEWPORT));
+ vp.Width = draw_data->DisplaySize.x;
+ vp.Height = draw_data->DisplaySize.y;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = vp.TopLeftY = 0;
+ ctx->RSSetViewports(1, &vp);
+
+ // Setup shader and vertex buffers
+ unsigned int stride = sizeof(ImDrawVert);
+ unsigned int offset = 0;
+ ctx->IASetInputLayout(bd->pInputLayout);
+ ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset);
+ ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0);
+ ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->VSSetShader(bd->pVertexShader, NULL, 0);
+ ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
+ ctx->PSSetShader(bd->pPixelShader, NULL, 0);
+ ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
+ ctx->GSSetShader(NULL, NULL, 0);
+ ctx->HSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
+ ctx->DSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
+ ctx->CSSetShader(NULL, NULL, 0); // In theory we should backup and restore this as well.. very infrequently used..
+
+ // Setup blend state
+ const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
+ ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff);
+ ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0);
+ ctx->RSSetState(bd->pRasterizerState);
+}
+
+// Render function
+void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ ID3D11DeviceContext* ctx = bd->pd3dDeviceContext;
+
+ // Create and grow vertex/index buffers if needed
+ if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert);
+ desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVB) < 0)
+ return;
+ }
+ if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
+ D3D11_BUFFER_DESC desc;
+ memset(&desc, 0, sizeof(D3D11_BUFFER_DESC));
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx);
+ desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ if (bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pIB) < 0)
+ return;
+ }
+
+ // Upload vertex/index data into a single contiguous GPU buffer
+ D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource;
+ if (ctx->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK)
+ return;
+ if (ctx->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK)
+ return;
+ ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData;
+ ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ ctx->Unmap(bd->pVB, 0);
+ ctx->Unmap(bd->pIB, 0);
+
+ // Setup orthographic projection matrix into our constant buffer
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped_resource;
+ if (ctx->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK)
+ return;
+ VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData;
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ float mvp[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ };
+ memcpy(&constant_buffer->mvp, mvp, sizeof(mvp));
+ ctx->Unmap(bd->pVertexConstantBuffer, 0);
+ }
+
+ // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!)
+ struct BACKUP_DX11_STATE
+ {
+ UINT ScissorRectsCount, ViewportsCount;
+ D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ ID3D11RasterizerState* RS;
+ ID3D11BlendState* BlendState;
+ FLOAT BlendFactor[4];
+ UINT SampleMask;
+ UINT StencilRef;
+ ID3D11DepthStencilState* DepthStencilState;
+ ID3D11ShaderResourceView* PSShaderResource;
+ ID3D11SamplerState* PSSampler;
+ ID3D11PixelShader* PS;
+ ID3D11VertexShader* VS;
+ ID3D11GeometryShader* GS;
+ UINT PSInstancesCount, VSInstancesCount, GSInstancesCount;
+ ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation
+ D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology;
+ ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer;
+ UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset;
+ DXGI_FORMAT IndexBufferFormat;
+ ID3D11InputLayout* InputLayout;
+ };
+ BACKUP_DX11_STATE old = {};
+ old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
+ ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
+ ctx->RSGetState(&old.RS);
+ ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask);
+ ctx->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef);
+ ctx->PSGetShaderResources(0, 1, &old.PSShaderResource);
+ ctx->PSGetSamplers(0, 1, &old.PSSampler);
+ old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256;
+ ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount);
+ ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount);
+ ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer);
+ ctx->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount);
+
+ ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology);
+ ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset);
+ ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset);
+ ctx->IAGetInputLayout(&old.InputLayout);
+
+ // Setup desired DX state
+ ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_idx_offset = 0;
+ int global_vtx_offset = 0;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplDX11_SetupRenderState(draw_data, ctx);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle
+ const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+ ctx->RSSetScissorRects(1, &r);
+
+ // Bind texture, Draw
+ ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
+ ctx->PSSetShaderResources(0, 1, &texture_srv);
+ ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+
+ // Restore modified DX state
+ ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects);
+ ctx->RSSetViewports(old.ViewportsCount, old.Viewports);
+ ctx->RSSetState(old.RS); if (old.RS) old.RS->Release();
+ ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release();
+ ctx->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release();
+ ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release();
+ ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release();
+ ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release();
+ for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release();
+ ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release();
+ ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release();
+ ctx->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release();
+ for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release();
+ ctx->IASetPrimitiveTopology(old.PrimitiveTopology);
+ ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release();
+ ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release();
+ ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
+}
+
+static void ImGui_ImplDX11_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Upload texture to graphics system
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ desc.CPUAccessFlags = 0;
+
+ ID3D11Texture2D* pTexture = NULL;
+ D3D11_SUBRESOURCE_DATA subResource;
+ subResource.pSysMem = pixels;
+ subResource.SysMemPitch = desc.Width * 4;
+ subResource.SysMemSlicePitch = 0;
+ bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
+ IM_ASSERT(pTexture != NULL);
+
+ // Create texture view
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ ZeroMemory(&srvDesc, sizeof(srvDesc));
+ srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = desc.MipLevels;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
+ pTexture->Release();
+ }
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);
+
+ // Create texture sampler
+ {
+ D3D11_SAMPLER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.MipLODBias = 0.f;
+ desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
+ desc.MinLOD = 0.f;
+ desc.MaxLOD = 0.f;
+ bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+ }
+}
+
+bool ImGui_ImplDX11_CreateDeviceObjects()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ if (!bd->pd3dDevice)
+ return false;
+ if (bd->pFontSampler)
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+
+ // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
+ // If you would like to use this DX11 sample code but remove this dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
+ // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // See https://github.com/ocornut/imgui/pull/638 for sources and details.
+
+ // Create the vertex shader
+ {
+ static const char* vertexShader =
+ "cbuffer vertexBuffer : register(b0) \
+ {\
+ float4x4 ProjectionMatrix; \
+ };\
+ struct VS_INPUT\
+ {\
+ float2 pos : POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ PS_INPUT main(VS_INPUT input)\
+ {\
+ PS_INPUT output;\
+ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
+ output.col = input.col;\
+ output.uv = input.uv;\
+ return output;\
+ }";
+
+ ID3DBlob* vertexShaderBlob;
+ if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_4_0", 0, 0, &vertexShaderBlob, NULL)))
+ return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), NULL, &bd->pVertexShader) != S_OK)
+ {
+ vertexShaderBlob->Release();
+ return false;
+ }
+
+ // Create the input layout
+ D3D11_INPUT_ELEMENT_DESC local_layout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+ if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK)
+ {
+ vertexShaderBlob->Release();
+ return false;
+ }
+ vertexShaderBlob->Release();
+
+ // Create the constant buffer
+ {
+ D3D11_BUFFER_DESC desc;
+ desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER);
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+ bd->pd3dDevice->CreateBuffer(&desc, NULL, &bd->pVertexConstantBuffer);
+ }
+ }
+
+ // Create the pixel shader
+ {
+ static const char* pixelShader =
+ "struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ sampler sampler0;\
+ Texture2D texture0;\
+ \
+ float4 main(PS_INPUT input) : SV_Target\
+ {\
+ float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
+ return out_col; \
+ }";
+
+ ID3DBlob* pixelShaderBlob;
+ if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_4_0", 0, 0, &pixelShaderBlob, NULL)))
+ return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), NULL, &bd->pPixelShader) != S_OK)
+ {
+ pixelShaderBlob->Release();
+ return false;
+ }
+ pixelShaderBlob->Release();
+ }
+
+ // Create the blending setup
+ {
+ D3D11_BLEND_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.AlphaToCoverageEnable = false;
+ desc.RenderTarget[0].BlendEnable = true;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
+ bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState);
+ }
+
+ // Create the rasterizer state
+ {
+ D3D11_RASTERIZER_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.FillMode = D3D11_FILL_SOLID;
+ desc.CullMode = D3D11_CULL_NONE;
+ desc.ScissorEnable = true;
+ desc.DepthClipEnable = true;
+ bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState);
+ }
+
+ // Create depth-stencil State
+ {
+ D3D11_DEPTH_STENCIL_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ desc.BackFace = desc.FrontFace;
+ bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
+ }
+
+ ImGui_ImplDX11_CreateFontsTexture();
+
+ return true;
+}
+
+void ImGui_ImplDX11_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ if (!bd->pd3dDevice)
+ return;
+
+ if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; }
+ if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; }
+ if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = NULL; }
+ if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = NULL; }
+ if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = NULL; }
+ if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = NULL; }
+ if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = NULL; }
+ if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = NULL; }
+}
+
+bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_dx11";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ // Get factory from device
+ IDXGIDevice* pDXGIDevice = NULL;
+ IDXGIAdapter* pDXGIAdapter = NULL;
+ IDXGIFactory* pFactory = NULL;
+
+ if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK)
+ if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK)
+ if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK)
+ {
+ bd->pd3dDevice = device;
+ bd->pd3dDeviceContext = device_context;
+ bd->pFactory = pFactory;
+ }
+ if (pDXGIDevice) pDXGIDevice->Release();
+ if (pDXGIAdapter) pDXGIAdapter->Release();
+ bd->pd3dDevice->AddRef();
+ bd->pd3dDeviceContext->AddRef();
+
+ return true;
+}
+
+void ImGui_ImplDX11_Shutdown()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplDX11_InvalidateDeviceObjects();
+ if (bd->pFactory) { bd->pFactory->Release(); }
+ if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
+ if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); }
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+void ImGui_ImplDX11_NewFrame()
+{
+ ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX11_Init()?");
+
+ if (!bd->pFontSampler)
+ ImGui_ImplDX11_CreateDeviceObjects();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx11.h b/Client/ThirdParty/imgui/backends/imgui_impl_dx11.h
new file mode 100644
index 0000000..a83bce1
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx11.h
@@ -0,0 +1,26 @@
+// dear imgui: Renderer Backend for DirectX11
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct ID3D11Device;
+struct ID3D11DeviceContext;
+
+IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
+IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx12.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_dx12.cpp
new file mode 100644
index 0000000..5058885
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx12.cpp
@@ -0,0 +1,746 @@
+// dear imgui: Renderer Backend for DirectX12
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
+// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
+// To build this on 32-bit systems:
+// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in the 'example_win32_direct12/example_win32_direct12.vcxproj' project file)
+// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
+// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
+// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file)
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
+// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
+// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
+// 2020-09-08: DirectX12: Clarified support for building on 32-bit systems by redefining ImTextureID.
+// 2019-10-18: DirectX12: *BREAKING CHANGE* Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function.
+// 2019-05-29: DirectX12: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: DirectX12: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-03-29: Misc: Various minor tidying up.
+// 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile().
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-06-12: DirectX12: Moved the ID3D12GraphicsCommandList* parameter from NewFrame() to RenderDrawData().
+// 2018-06-08: Misc: Extracted imgui_impl_dx12.cpp/.h away from the old combined DX12+Win32 example.
+// 2018-06-08: DirectX12: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle (to ease support for future multi-viewport).
+// 2018-02-22: Merged into master with all Win32 code synchronized to other examples.
+
+#include "imgui.h"
+#include "imgui_impl_dx12.h"
+
+// DirectX
+#include <d3d12.h>
+#include <dxgi1_4.h>
+#include <d3dcompiler.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
+#endif
+
+// DirectX data
+struct ImGui_ImplDX12_RenderBuffers
+{
+ ID3D12Resource* IndexBuffer;
+ ID3D12Resource* VertexBuffer;
+ int IndexBufferSize;
+ int VertexBufferSize;
+};
+
+struct ImGui_ImplDX12_Data
+{
+ ID3D12Device* pd3dDevice;
+ ID3D12RootSignature* pRootSignature;
+ ID3D12PipelineState* pPipelineState;
+ DXGI_FORMAT RTVFormat;
+ ID3D12Resource* pFontTextureResource;
+ D3D12_CPU_DESCRIPTOR_HANDLE hFontSrvCpuDescHandle;
+ D3D12_GPU_DESCRIPTOR_HANDLE hFontSrvGpuDescHandle;
+
+ ImGui_ImplDX12_RenderBuffers* pFrameResources;
+ UINT numFramesInFlight;
+ UINT frameIndex;
+
+ ImGui_ImplDX12_Data() { memset(this, 0, sizeof(*this)); frameIndex = UINT_MAX; }
+};
+
+struct VERTEX_CONSTANT_BUFFER
+{
+ float mvp[4][4];
+};
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX12_Data* ImGui_ImplDX12_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplDX12_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+static void ImGui_ImplDX12_SetupRenderState(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx, ImGui_ImplDX12_RenderBuffers* fr)
+{
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+
+ // Setup orthographic projection matrix into our constant buffer
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
+ VERTEX_CONSTANT_BUFFER vertex_constant_buffer;
+ {
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ float mvp[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ };
+ memcpy(&vertex_constant_buffer.mvp, mvp, sizeof(mvp));
+ }
+
+ // Setup viewport
+ D3D12_VIEWPORT vp;
+ memset(&vp, 0, sizeof(D3D12_VIEWPORT));
+ vp.Width = draw_data->DisplaySize.x;
+ vp.Height = draw_data->DisplaySize.y;
+ vp.MinDepth = 0.0f;
+ vp.MaxDepth = 1.0f;
+ vp.TopLeftX = vp.TopLeftY = 0.0f;
+ ctx->RSSetViewports(1, &vp);
+
+ // Bind shader and vertex buffers
+ unsigned int stride = sizeof(ImDrawVert);
+ unsigned int offset = 0;
+ D3D12_VERTEX_BUFFER_VIEW vbv;
+ memset(&vbv, 0, sizeof(D3D12_VERTEX_BUFFER_VIEW));
+ vbv.BufferLocation = fr->VertexBuffer->GetGPUVirtualAddress() + offset;
+ vbv.SizeInBytes = fr->VertexBufferSize * stride;
+ vbv.StrideInBytes = stride;
+ ctx->IASetVertexBuffers(0, 1, &vbv);
+ D3D12_INDEX_BUFFER_VIEW ibv;
+ memset(&ibv, 0, sizeof(D3D12_INDEX_BUFFER_VIEW));
+ ibv.BufferLocation = fr->IndexBuffer->GetGPUVirtualAddress();
+ ibv.SizeInBytes = fr->IndexBufferSize * sizeof(ImDrawIdx);
+ ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
+ ctx->IASetIndexBuffer(&ibv);
+ ctx->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ ctx->SetPipelineState(bd->pPipelineState);
+ ctx->SetGraphicsRootSignature(bd->pRootSignature);
+ ctx->SetGraphicsRoot32BitConstants(0, 16, &vertex_constant_buffer, 0);
+
+ // Setup blend factor
+ const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f };
+ ctx->OMSetBlendFactor(blend_factor);
+}
+
+template<typename T>
+static inline void SafeRelease(T*& res)
+{
+ if (res)
+ res->Release();
+ res = NULL;
+}
+
+// Render function
+void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* ctx)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ // FIXME: I'm assuming that this only gets called once per frame!
+ // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+ bd->frameIndex = bd->frameIndex + 1;
+ ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[bd->frameIndex % bd->numFramesInFlight];
+
+ // Create and grow vertex/index buffers if needed
+ if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ SafeRelease(fr->VertexBuffer);
+ fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
+ D3D12_HEAP_PROPERTIES props;
+ memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
+ props.Type = D3D12_HEAP_TYPE_UPLOAD;
+ props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ D3D12_RESOURCE_DESC desc;
+ memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ desc.Width = fr->VertexBufferSize * sizeof(ImDrawVert);
+ desc.Height = 1;
+ desc.DepthOrArraySize = 1;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_UNKNOWN;
+ desc.SampleDesc.Count = 1;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->VertexBuffer)) < 0)
+ return;
+ }
+ if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ SafeRelease(fr->IndexBuffer);
+ fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
+ D3D12_HEAP_PROPERTIES props;
+ memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
+ props.Type = D3D12_HEAP_TYPE_UPLOAD;
+ props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ D3D12_RESOURCE_DESC desc;
+ memset(&desc, 0, sizeof(D3D12_RESOURCE_DESC));
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ desc.Width = fr->IndexBufferSize * sizeof(ImDrawIdx);
+ desc.Height = 1;
+ desc.DepthOrArraySize = 1;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_UNKNOWN;
+ desc.SampleDesc.Count = 1;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ if (bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&fr->IndexBuffer)) < 0)
+ return;
+ }
+
+ // Upload vertex/index data into a single contiguous GPU buffer
+ void* vtx_resource, *idx_resource;
+ D3D12_RANGE range;
+ memset(&range, 0, sizeof(D3D12_RANGE));
+ if (fr->VertexBuffer->Map(0, &range, &vtx_resource) != S_OK)
+ return;
+ if (fr->IndexBuffer->Map(0, &range, &idx_resource) != S_OK)
+ return;
+ ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource;
+ ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ fr->VertexBuffer->Unmap(0, &range);
+ fr->IndexBuffer->Unmap(0, &range);
+
+ // Setup desired DX state
+ ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_vtx_offset = 0;
+ int global_idx_offset = 0;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplDX12_SetupRenderState(draw_data, ctx, fr);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply Scissor/clipping rectangle, Bind texture, Draw
+ const D3D12_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+ D3D12_GPU_DESCRIPTOR_HANDLE texture_handle = {};
+ texture_handle.ptr = (UINT64)pcmd->GetTexID();
+ ctx->SetGraphicsRootDescriptorTable(1, texture_handle);
+ ctx->RSSetScissorRects(1, &r);
+ ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+}
+
+static void ImGui_ImplDX12_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Upload texture to graphics system
+ {
+ D3D12_HEAP_PROPERTIES props;
+ memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
+ props.Type = D3D12_HEAP_TYPE_DEFAULT;
+ props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+
+ D3D12_RESOURCE_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ desc.Alignment = 0;
+ desc.Width = width;
+ desc.Height = height;
+ desc.DepthOrArraySize = 1;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ ID3D12Resource* pTexture = NULL;
+ bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
+ D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
+
+ UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
+ UINT uploadSize = height * uploadPitch;
+ desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ desc.Alignment = 0;
+ desc.Width = uploadSize;
+ desc.Height = 1;
+ desc.DepthOrArraySize = 1;
+ desc.MipLevels = 1;
+ desc.Format = DXGI_FORMAT_UNKNOWN;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ desc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ props.Type = D3D12_HEAP_TYPE_UPLOAD;
+ props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+
+ ID3D12Resource* uploadBuffer = NULL;
+ HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
+ D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
+ IM_ASSERT(SUCCEEDED(hr));
+
+ void* mapped = NULL;
+ D3D12_RANGE range = { 0, uploadSize };
+ hr = uploadBuffer->Map(0, &range, &mapped);
+ IM_ASSERT(SUCCEEDED(hr));
+ for (int y = 0; y < height; y++)
+ memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4);
+ uploadBuffer->Unmap(0, &range);
+
+ D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
+ srcLocation.pResource = uploadBuffer;
+ srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srcLocation.PlacedFootprint.Footprint.Width = width;
+ srcLocation.PlacedFootprint.Footprint.Height = height;
+ srcLocation.PlacedFootprint.Footprint.Depth = 1;
+ srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch;
+
+ D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
+ dstLocation.pResource = pTexture;
+ dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dstLocation.SubresourceIndex = 0;
+
+ D3D12_RESOURCE_BARRIER barrier = {};
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = pTexture;
+ barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
+
+ ID3D12Fence* fence = NULL;
+ hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
+ IM_ASSERT(SUCCEEDED(hr));
+
+ HANDLE event = CreateEvent(0, 0, 0, 0);
+ IM_ASSERT(event != NULL);
+
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+ queueDesc.NodeMask = 1;
+
+ ID3D12CommandQueue* cmdQueue = NULL;
+ hr = bd->pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue));
+ IM_ASSERT(SUCCEEDED(hr));
+
+ ID3D12CommandAllocator* cmdAlloc = NULL;
+ hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
+ IM_ASSERT(SUCCEEDED(hr));
+
+ ID3D12GraphicsCommandList* cmdList = NULL;
+ hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList));
+ IM_ASSERT(SUCCEEDED(hr));
+
+ cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL);
+ cmdList->ResourceBarrier(1, &barrier);
+
+ hr = cmdList->Close();
+ IM_ASSERT(SUCCEEDED(hr));
+
+ cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
+ hr = cmdQueue->Signal(fence, 1);
+ IM_ASSERT(SUCCEEDED(hr));
+
+ fence->SetEventOnCompletion(1, event);
+ WaitForSingleObject(event, INFINITE);
+
+ cmdList->Release();
+ cmdAlloc->Release();
+ cmdQueue->Release();
+ CloseHandle(event);
+ fence->Release();
+ uploadBuffer->Release();
+
+ // Create texture view
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ ZeroMemory(&srvDesc, sizeof(srvDesc));
+ srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = desc.MipLevels;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, bd->hFontSrvCpuDescHandle);
+ SafeRelease(bd->pFontTextureResource);
+ bd->pFontTextureResource = pTexture;
+ }
+
+ // Store our identifier
+ // READ THIS IF THE STATIC_ASSERT() TRIGGERS:
+ // - Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
+ // - This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
+ // [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in the 'example_win32_direct12/example_win32_direct12.vcxproj' project file)
+ // [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
+ // [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
+ // [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in the example_win32_direct12/build_win32.bat file)
+ static_assert(sizeof(ImTextureID) >= sizeof(bd->hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
+ io.Fonts->SetTexID((ImTextureID)bd->hFontSrvGpuDescHandle.ptr);
+}
+
+bool ImGui_ImplDX12_CreateDeviceObjects()
+{
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+ if (!bd || !bd->pd3dDevice)
+ return false;
+ if (bd->pPipelineState)
+ ImGui_ImplDX12_InvalidateDeviceObjects();
+
+ // Create the root signature
+ {
+ D3D12_DESCRIPTOR_RANGE descRange = {};
+ descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ descRange.NumDescriptors = 1;
+ descRange.BaseShaderRegister = 0;
+ descRange.RegisterSpace = 0;
+ descRange.OffsetInDescriptorsFromTableStart = 0;
+
+ D3D12_ROOT_PARAMETER param[2] = {};
+
+ param[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
+ param[0].Constants.ShaderRegister = 0;
+ param[0].Constants.RegisterSpace = 0;
+ param[0].Constants.Num32BitValues = 16;
+ param[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+
+ param[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ param[1].DescriptorTable.NumDescriptorRanges = 1;
+ param[1].DescriptorTable.pDescriptorRanges = &descRange;
+ param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+
+ D3D12_STATIC_SAMPLER_DESC staticSampler = {};
+ staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
+ staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ staticSampler.MipLODBias = 0.f;
+ staticSampler.MaxAnisotropy = 0;
+ staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
+ staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
+ staticSampler.MinLOD = 0.f;
+ staticSampler.MaxLOD = 0.f;
+ staticSampler.ShaderRegister = 0;
+ staticSampler.RegisterSpace = 0;
+ staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+
+ D3D12_ROOT_SIGNATURE_DESC desc = {};
+ desc.NumParameters = _countof(param);
+ desc.pParameters = param;
+ desc.NumStaticSamplers = 1;
+ desc.pStaticSamplers = &staticSampler;
+ desc.Flags =
+ D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
+ D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS;
+
+ // Load d3d12.dll and D3D12SerializeRootSignature() function address dynamically to facilitate using with D3D12On7.
+ // See if any version of d3d12.dll is already loaded in the process. If so, give preference to that.
+ static HINSTANCE d3d12_dll = ::GetModuleHandleA("d3d12.dll");
+ if (d3d12_dll == NULL)
+ {
+ // Attempt to load d3d12.dll from local directories. This will only succeed if
+ // (1) the current OS is Windows 7, and
+ // (2) there exists a version of d3d12.dll for Windows 7 (D3D12On7) in one of the following directories.
+ // See https://github.com/ocornut/imgui/pull/3696 for details.
+ const char* localD3d12Paths[] = { ".\\d3d12.dll", ".\\d3d12on7\\d3d12.dll", ".\\12on7\\d3d12.dll" }; // A. current directory, B. used by some games, C. used in Microsoft D3D12On7 sample
+ for (int i = 0; i < IM_ARRAYSIZE(localD3d12Paths); i++)
+ if ((d3d12_dll = ::LoadLibraryA(localD3d12Paths[i])) != NULL)
+ break;
+
+ // If failed, we are on Windows >= 10.
+ if (d3d12_dll == NULL)
+ d3d12_dll = ::LoadLibraryA("d3d12.dll");
+
+ if (d3d12_dll == NULL)
+ return false;
+ }
+
+ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignatureFn = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)::GetProcAddress(d3d12_dll, "D3D12SerializeRootSignature");
+ if (D3D12SerializeRootSignatureFn == NULL)
+ return false;
+
+ ID3DBlob* blob = NULL;
+ if (D3D12SerializeRootSignatureFn(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK)
+ return false;
+
+ bd->pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&bd->pRootSignature));
+ blob->Release();
+ }
+
+ // By using D3DCompile() from <d3dcompiler.h> / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A)
+ // If you would like to use this DX12 sample code but remove this dependency you can:
+ // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution]
+ // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL.
+ // See https://github.com/ocornut/imgui/pull/638 for sources and details.
+
+ D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
+ memset(&psoDesc, 0, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
+ psoDesc.NodeMask = 1;
+ psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ psoDesc.pRootSignature = bd->pRootSignature;
+ psoDesc.SampleMask = UINT_MAX;
+ psoDesc.NumRenderTargets = 1;
+ psoDesc.RTVFormats[0] = bd->RTVFormat;
+ psoDesc.SampleDesc.Count = 1;
+ psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+
+ ID3DBlob* vertexShaderBlob;
+ ID3DBlob* pixelShaderBlob;
+
+ // Create the vertex shader
+ {
+ static const char* vertexShader =
+ "cbuffer vertexBuffer : register(b0) \
+ {\
+ float4x4 ProjectionMatrix; \
+ };\
+ struct VS_INPUT\
+ {\
+ float2 pos : POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ \
+ PS_INPUT main(VS_INPUT input)\
+ {\
+ PS_INPUT output;\
+ output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\
+ output.col = input.col;\
+ output.uv = input.uv;\
+ return output;\
+ }";
+
+ if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &vertexShaderBlob, NULL)))
+ return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ psoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() };
+
+ // Create the input layout
+ static D3D12_INPUT_ELEMENT_DESC local_layout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)IM_OFFSETOF(ImDrawVert, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)IM_OFFSETOF(ImDrawVert, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
+ };
+ psoDesc.InputLayout = { local_layout, 3 };
+ }
+
+ // Create the pixel shader
+ {
+ static const char* pixelShader =
+ "struct PS_INPUT\
+ {\
+ float4 pos : SV_POSITION;\
+ float4 col : COLOR0;\
+ float2 uv : TEXCOORD0;\
+ };\
+ SamplerState sampler0 : register(s0);\
+ Texture2D texture0 : register(t0);\
+ \
+ float4 main(PS_INPUT input) : SV_Target\
+ {\
+ float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \
+ return out_col; \
+ }";
+
+ if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &pixelShaderBlob, NULL)))
+ {
+ vertexShaderBlob->Release();
+ return false; // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob!
+ }
+ psoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() };
+ }
+
+ // Create the blending setup
+ {
+ D3D12_BLEND_DESC& desc = psoDesc.BlendState;
+ desc.AlphaToCoverageEnable = false;
+ desc.RenderTarget[0].BlendEnable = true;
+ desc.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
+ desc.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
+ desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
+ desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ }
+
+ // Create the rasterizer state
+ {
+ D3D12_RASTERIZER_DESC& desc = psoDesc.RasterizerState;
+ desc.FillMode = D3D12_FILL_MODE_SOLID;
+ desc.CullMode = D3D12_CULL_MODE_NONE;
+ desc.FrontCounterClockwise = FALSE;
+ desc.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
+ desc.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
+ desc.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
+ desc.DepthClipEnable = true;
+ desc.MultisampleEnable = FALSE;
+ desc.AntialiasedLineEnable = FALSE;
+ desc.ForcedSampleCount = 0;
+ desc.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+ }
+
+ // Create depth-stencil State
+ {
+ D3D12_DEPTH_STENCIL_DESC& desc = psoDesc.DepthStencilState;
+ desc.DepthEnable = false;
+ desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
+ desc.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS;
+ desc.StencilEnable = false;
+ desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D12_STENCIL_OP_KEEP;
+ desc.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS;
+ desc.BackFace = desc.FrontFace;
+ }
+
+ HRESULT result_pipeline_state = bd->pd3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&bd->pPipelineState));
+ vertexShaderBlob->Release();
+ pixelShaderBlob->Release();
+ if (result_pipeline_state != S_OK)
+ return false;
+
+ ImGui_ImplDX12_CreateFontsTexture();
+
+ return true;
+}
+
+void ImGui_ImplDX12_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+ if (!bd || !bd->pd3dDevice)
+ return;
+ ImGuiIO& io = ImGui::GetIO();
+
+ SafeRelease(bd->pRootSignature);
+ SafeRelease(bd->pPipelineState);
+ SafeRelease(bd->pFontTextureResource);
+ io.Fonts->SetTexID(NULL); // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
+
+ for (UINT i = 0; i < bd->numFramesInFlight; i++)
+ {
+ ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i];
+ SafeRelease(fr->IndexBuffer);
+ SafeRelease(fr->VertexBuffer);
+ }
+}
+
+bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
+ D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplDX12_Data* bd = IM_NEW(ImGui_ImplDX12_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_dx12";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ bd->pd3dDevice = device;
+ bd->RTVFormat = rtv_format;
+ bd->hFontSrvCpuDescHandle = font_srv_cpu_desc_handle;
+ bd->hFontSrvGpuDescHandle = font_srv_gpu_desc_handle;
+ bd->pFrameResources = new ImGui_ImplDX12_RenderBuffers[num_frames_in_flight];
+ bd->numFramesInFlight = num_frames_in_flight;
+ bd->frameIndex = UINT_MAX;
+ IM_UNUSED(cbv_srv_heap); // Unused in master branch (will be used by multi-viewports)
+
+ // Create buffers with a default size (they will later be grown as needed)
+ for (int i = 0; i < num_frames_in_flight; i++)
+ {
+ ImGui_ImplDX12_RenderBuffers* fr = &bd->pFrameResources[i];
+ fr->IndexBuffer = NULL;
+ fr->VertexBuffer = NULL;
+ fr->IndexBufferSize = 10000;
+ fr->VertexBufferSize = 5000;
+ }
+
+ return true;
+}
+
+void ImGui_ImplDX12_Shutdown()
+{
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplDX12_InvalidateDeviceObjects();
+ delete[] bd->pFrameResources;
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+void ImGui_ImplDX12_NewFrame()
+{
+ ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX12_Init()?");
+
+ if (!bd->pPipelineState)
+ ImGui_ImplDX12_CreateDeviceObjects();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx12.h b/Client/ThirdParty/imgui/backends/imgui_impl_dx12.h
new file mode 100644
index 0000000..899c822
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx12.h
@@ -0,0 +1,39 @@
+// dear imgui: Renderer Backend for DirectX12
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'.
+// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
+// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+#include <dxgiformat.h> // DXGI_FORMAT
+
+struct ID3D12Device;
+struct ID3D12DescriptorHeap;
+struct ID3D12GraphicsCommandList;
+struct D3D12_CPU_DESCRIPTOR_HANDLE;
+struct D3D12_GPU_DESCRIPTOR_HANDLE;
+
+// cmd_list is the command list that the implementation will use to render imgui draw lists.
+// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate
+// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle.
+// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture.
+IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap,
+ D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle);
+IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx9.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_dx9.cpp
new file mode 100644
index 0000000..9234cb0
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx9.cpp
@@ -0,0 +1,378 @@
+// dear imgui: Renderer Backend for DirectX9
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-06-25: DirectX9: Explicitly disable texture state stages after >= 1.
+// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
+// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
+// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
+// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
+// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: DirectX9: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-03-29: Misc: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects().
+// 2019-01-16: Misc: Disabled fog before drawing UI's. Fixes issue #2288.
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-06-08: Misc: Extracted imgui_impl_dx9.cpp/.h away from the old combined DX9+Win32 example.
+// 2018-06-08: DirectX9: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-05-07: Render: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+
+#include "imgui.h"
+#include "imgui_impl_dx9.h"
+
+// DirectX
+#include <d3d9.h>
+
+// DirectX data
+struct ImGui_ImplDX9_Data
+{
+ LPDIRECT3DDEVICE9 pd3dDevice;
+ LPDIRECT3DVERTEXBUFFER9 pVB;
+ LPDIRECT3DINDEXBUFFER9 pIB;
+ LPDIRECT3DTEXTURE9 FontTexture;
+ int VertexBufferSize;
+ int IndexBufferSize;
+
+ ImGui_ImplDX9_Data() { memset(this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
+};
+
+struct CUSTOMVERTEX
+{
+ float pos[3];
+ D3DCOLOR col;
+ float uv[2];
+};
+#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
+
+#ifdef IMGUI_USE_BGRA_PACKED_COLOR
+#define IMGUI_COL_TO_DX9_ARGB(_COL) (_COL)
+#else
+#define IMGUI_COL_TO_DX9_ARGB(_COL) (((_COL) & 0xFF00FF00) | (((_COL) & 0xFF0000) >> 16) | (((_COL) & 0xFF) << 16))
+#endif
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplDX9_Data* ImGui_ImplDX9_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplDX9_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
+{
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+
+ // Setup viewport
+ D3DVIEWPORT9 vp;
+ vp.X = vp.Y = 0;
+ vp.Width = (DWORD)draw_data->DisplaySize.x;
+ vp.Height = (DWORD)draw_data->DisplaySize.y;
+ vp.MinZ = 0.0f;
+ vp.MaxZ = 1.0f;
+ bd->pd3dDevice->SetViewport(&vp);
+
+ // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
+ bd->pd3dDevice->SetPixelShader(NULL);
+ bd->pd3dDevice->SetVertexShader(NULL);
+ bd->pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ bd->pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+ bd->pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ bd->pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+ bd->pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ bd->pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+ bd->pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+ bd->pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ bd->pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
+ bd->pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
+ bd->pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+ bd->pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ bd->pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
+ bd->pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
+ bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ bd->pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+ bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ bd->pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
+ bd->pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ bd->pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ bd->pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+ // Setup orthographic projection matrix
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ // Being agnostic of whether <d3dx9.h> or <DirectXMath.h> can be used, we aren't relying on D3DXMatrixIdentity()/D3DXMatrixOrthoOffCenterLH() or DirectX::XMMatrixIdentity()/DirectX::XMMatrixOrthographicOffCenterLH()
+ {
+ float L = draw_data->DisplayPos.x + 0.5f;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x + 0.5f;
+ float T = draw_data->DisplayPos.y + 0.5f;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y + 0.5f;
+ D3DMATRIX mat_identity = { { { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } } };
+ D3DMATRIX mat_projection =
+ { { {
+ 2.0f/(R-L), 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f/(T-B), 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.0f,
+ (L+R)/(L-R), (T+B)/(B-T), 0.5f, 1.0f
+ } } };
+ bd->pd3dDevice->SetTransform(D3DTS_WORLD, &mat_identity);
+ bd->pd3dDevice->SetTransform(D3DTS_VIEW, &mat_identity);
+ bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_projection);
+ }
+}
+
+// Render function.
+void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ // Create and grow buffers if needed
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+ if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ bd->VertexBufferSize = draw_data->TotalVtxCount + 5000;
+ if (bd->pd3dDevice->CreateVertexBuffer(bd->VertexBufferSize * sizeof(CUSTOMVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &bd->pVB, NULL) < 0)
+ return;
+ }
+ if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
+ if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, NULL) < 0)
+ return;
+ }
+
+ // Backup the DX9 state
+ IDirect3DStateBlock9* d3d9_state_block = NULL;
+ if (bd->pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
+ return;
+ if (d3d9_state_block->Capture() < 0)
+ {
+ d3d9_state_block->Release();
+ return;
+ }
+
+ // Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
+ D3DMATRIX last_world, last_view, last_projection;
+ bd->pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
+ bd->pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
+ bd->pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
+
+ // Allocate buffers
+ CUSTOMVERTEX* vtx_dst;
+ ImDrawIdx* idx_dst;
+ if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
+ {
+ d3d9_state_block->Release();
+ return;
+ }
+ if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
+ {
+ bd->pVB->Unlock();
+ d3d9_state_block->Release();
+ return;
+ }
+
+ // Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
+ // FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
+ // 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
+ // 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawVert* vtx_src = cmd_list->VtxBuffer.Data;
+ for (int i = 0; i < cmd_list->VtxBuffer.Size; i++)
+ {
+ vtx_dst->pos[0] = vtx_src->pos.x;
+ vtx_dst->pos[1] = vtx_src->pos.y;
+ vtx_dst->pos[2] = 0.0f;
+ vtx_dst->col = IMGUI_COL_TO_DX9_ARGB(vtx_src->col);
+ vtx_dst->uv[0] = vtx_src->uv.x;
+ vtx_dst->uv[1] = vtx_src->uv.y;
+ vtx_dst++;
+ vtx_src++;
+ }
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ bd->pVB->Unlock();
+ bd->pIB->Unlock();
+ bd->pd3dDevice->SetStreamSource(0, bd->pVB, 0, sizeof(CUSTOMVERTEX));
+ bd->pd3dDevice->SetIndices(bd->pIB);
+ bd->pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
+
+ // Setup desired DX state
+ ImGui_ImplDX9_SetupRenderState(draw_data);
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_vtx_offset = 0;
+ int global_idx_offset = 0;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplDX9_SetupRenderState(draw_data);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply Scissor/clipping rectangle, Bind texture, Draw
+ const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y };
+ const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
+ bd->pd3dDevice->SetTexture(0, texture);
+ bd->pd3dDevice->SetScissorRect(&r);
+ bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+
+ // Restore the DX9 transform
+ bd->pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
+ bd->pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
+ bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
+
+ // Restore the DX9 state
+ d3d9_state_block->Apply();
+ d3d9_state_block->Release();
+}
+
+bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplDX9_Data* bd = IM_NEW(ImGui_ImplDX9_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_dx9";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ bd->pd3dDevice = device;
+ bd->pd3dDevice->AddRef();
+
+ return true;
+}
+
+void ImGui_ImplDX9_Shutdown()
+{
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplDX9_InvalidateDeviceObjects();
+ if (bd->pd3dDevice) { bd->pd3dDevice->Release(); }
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+static bool ImGui_ImplDX9_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+ unsigned char* pixels;
+ int width, height, bytes_per_pixel;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixel);
+
+ // Convert RGBA32 to BGRA32 (because RGBA32 is not well supported by DX9 devices)
+#ifndef IMGUI_USE_BGRA_PACKED_COLOR
+ if (io.Fonts->TexPixelsUseColors)
+ {
+ ImU32* dst_start = (ImU32*)ImGui::MemAlloc((size_t)width * height * bytes_per_pixel);
+ for (ImU32* src = (ImU32*)pixels, *dst = dst_start, *dst_end = dst_start + (size_t)width * height; dst < dst_end; src++, dst++)
+ *dst = IMGUI_COL_TO_DX9_ARGB(*src);
+ pixels = (unsigned char*)dst_start;
+ }
+#endif
+
+ // Upload texture to graphics system
+ bd->FontTexture = NULL;
+ if (bd->pd3dDevice->CreateTexture(width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &bd->FontTexture, NULL) < 0)
+ return false;
+ D3DLOCKED_RECT tex_locked_rect;
+ if (bd->FontTexture->LockRect(0, &tex_locked_rect, NULL, 0) != D3D_OK)
+ return false;
+ for (int y = 0; y < height; y++)
+ memcpy((unsigned char*)tex_locked_rect.pBits + (size_t)tex_locked_rect.Pitch * y, pixels + (size_t)width * bytes_per_pixel * y, (size_t)width * bytes_per_pixel);
+ bd->FontTexture->UnlockRect(0);
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)bd->FontTexture);
+
+#ifndef IMGUI_USE_BGRA_PACKED_COLOR
+ if (io.Fonts->TexPixelsUseColors)
+ ImGui::MemFree(pixels);
+#endif
+
+ return true;
+}
+
+bool ImGui_ImplDX9_CreateDeviceObjects()
+{
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+ if (!bd || !bd->pd3dDevice)
+ return false;
+ if (!ImGui_ImplDX9_CreateFontsTexture())
+ return false;
+ return true;
+}
+
+void ImGui_ImplDX9_InvalidateDeviceObjects()
+{
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+ if (!bd || !bd->pd3dDevice)
+ return;
+ if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; }
+ if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; }
+ if (bd->FontTexture) { bd->FontTexture->Release(); bd->FontTexture = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied bd->pFontTextureView to io.Fonts->TexID so let's clear that as well.
+}
+
+void ImGui_ImplDX9_NewFrame()
+{
+ ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplDX9_Init()?");
+
+ if (!bd->FontTexture)
+ ImGui_ImplDX9_CreateDeviceObjects();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_dx9.h b/Client/ThirdParty/imgui/backends/imgui_impl_dx9.h
new file mode 100644
index 0000000..6dc805b
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_dx9.h
@@ -0,0 +1,25 @@
+// dear imgui: Renderer Backend for DirectX9
+// This needs to be used along with a Platform Backend (e.g. Win32)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct IDirect3DDevice9;
+
+IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
+IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API bool ImGui_ImplDX9_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplDX9_InvalidateDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_glfw.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_glfw.cpp
new file mode 100644
index 0000000..bf2a654
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_glfw.cpp
@@ -0,0 +1,454 @@
+// dear imgui: Platform Backend for GLFW
+// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
+// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
+// (Requires: GLFW 3.1+)
+
+// Implemented features:
+// [X] Platform: Clipboard support.
+// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+).
+// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback().
+// 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback().
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors.
+// 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor).
+// 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown.
+// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
+// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
+// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
+// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
+// 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them.
+// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
+// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
+// 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples.
+// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
+// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()).
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set.
+// 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
+// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
+// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
+// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
+// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
+
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+
+// GLFW
+#include <GLFW/glfw3.h>
+#ifdef _WIN32
+#undef APIENTRY
+#define GLFW_EXPOSE_NATIVE_WIN32
+#include <GLFW/glfw3native.h> // for glfwGetWin32Window
+#endif
+#define GLFW_HAS_WINDOW_TOPMOST (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ GLFW_FLOATING
+#define GLFW_HAS_WINDOW_HOVERED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ GLFW_HOVERED
+#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwSetWindowOpacity
+#define GLFW_HAS_PER_MONITOR_DPI (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ glfwGetMonitorContentScale
+#define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwCreateWindowSurface
+#ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released?
+#define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR
+#else
+#define GLFW_HAS_NEW_CURSORS (0)
+#endif
+
+// GLFW data
+enum GlfwClientApi
+{
+ GlfwClientApi_Unknown,
+ GlfwClientApi_OpenGL,
+ GlfwClientApi_Vulkan
+};
+
+struct ImGui_ImplGlfw_Data
+{
+ GLFWwindow* Window;
+ GlfwClientApi ClientApi;
+ double Time;
+ GLFWwindow* MouseWindow;
+ bool MouseJustPressed[ImGuiMouseButton_COUNT];
+ GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT];
+ bool InstalledCallbacks;
+
+ // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
+ GLFWwindowfocusfun PrevUserCallbackWindowFocus;
+ GLFWcursorenterfun PrevUserCallbackCursorEnter;
+ GLFWmousebuttonfun PrevUserCallbackMousebutton;
+ GLFWscrollfun PrevUserCallbackScroll;
+ GLFWkeyfun PrevUserCallbackKey;
+ GLFWcharfun PrevUserCallbackChar;
+ GLFWmonitorfun PrevUserCallbackMonitor;
+
+ ImGui_ImplGlfw_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+// - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks
+// (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks.
+// - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it.
+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
+}
+
+// Functions
+static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
+{
+ return glfwGetClipboardString((GLFWwindow*)user_data);
+}
+
+static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text)
+{
+ glfwSetClipboardString((GLFWwindow*)user_data, text);
+}
+
+void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods)
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if (bd->PrevUserCallbackMousebutton != NULL && window == bd->Window)
+ bd->PrevUserCallbackMousebutton(window, button, action, mods);
+
+ if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(bd->MouseJustPressed))
+ bd->MouseJustPressed[button] = true;
+}
+
+void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if (bd->PrevUserCallbackScroll != NULL && window == bd->Window)
+ bd->PrevUserCallbackScroll(window, xoffset, yoffset);
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseWheelH += (float)xoffset;
+ io.MouseWheel += (float)yoffset;
+}
+
+void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if (bd->PrevUserCallbackKey != NULL && window == bd->Window)
+ bd->PrevUserCallbackKey(window, key, scancode, action, mods);
+
+ ImGuiIO& io = ImGui::GetIO();
+ if (key >= 0 && key < IM_ARRAYSIZE(io.KeysDown))
+ {
+ if (action == GLFW_PRESS)
+ io.KeysDown[key] = true;
+ if (action == GLFW_RELEASE)
+ io.KeysDown[key] = false;
+ }
+
+ // Modifiers are not reliable across systems
+ io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
+ io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT];
+ io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT];
+#ifdef _WIN32
+ io.KeySuper = false;
+#else
+ io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
+#endif
+}
+
+void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused)
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if (bd->PrevUserCallbackWindowFocus != NULL && window == bd->Window)
+ bd->PrevUserCallbackWindowFocus(window, focused);
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.AddFocusEvent(focused != 0);
+}
+
+void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered)
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if (bd->PrevUserCallbackCursorEnter != NULL && window == bd->Window)
+ bd->PrevUserCallbackCursorEnter(window, entered);
+
+ if (entered)
+ bd->MouseWindow = window;
+ if (!entered && bd->MouseWindow == window)
+ bd->MouseWindow = NULL;
+}
+
+void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c)
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if (bd->PrevUserCallbackChar != NULL && window == bd->Window)
+ bd->PrevUserCallbackChar(window, c);
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.AddInputCharacter(c);
+}
+
+void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
+{
+ // Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too.
+}
+
+static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)();
+ io.BackendPlatformUserData = (void*)bd;
+ io.BackendPlatformName = "imgui_impl_glfw";
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+
+ bd->Window = window;
+ bd->Time = 0.0;
+
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
+ io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
+ io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP;
+ io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN;
+ io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME;
+ io.KeyMap[ImGuiKey_End] = GLFW_KEY_END;
+ io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE;
+ io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE;
+ io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER;
+ io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = GLFW_KEY_KP_ENTER;
+ io.KeyMap[ImGuiKey_A] = GLFW_KEY_A;
+ io.KeyMap[ImGuiKey_C] = GLFW_KEY_C;
+ io.KeyMap[ImGuiKey_V] = GLFW_KEY_V;
+ io.KeyMap[ImGuiKey_X] = GLFW_KEY_X;
+ io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y;
+ io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z;
+
+ io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
+ io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
+ io.ClipboardUserData = bd->Window;
+#if defined(_WIN32)
+ io.ImeWindowHandle = (void*)glfwGetWin32Window(bd->Window);
+#endif
+
+ // Create mouse cursors
+ // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist,
+ // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting.
+ // Missing cursors will return NULL and our _UpdateMouseCursor() function will use the Arrow cursor instead.)
+ GLFWerrorfun prev_error_callback = glfwSetErrorCallback(NULL);
+ bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
+#if GLFW_HAS_NEW_CURSORS
+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR);
+#else
+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
+#endif
+ glfwSetErrorCallback(prev_error_callback);
+
+ // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
+ bd->PrevUserCallbackWindowFocus = NULL;
+ bd->PrevUserCallbackMousebutton = NULL;
+ bd->PrevUserCallbackScroll = NULL;
+ bd->PrevUserCallbackKey = NULL;
+ bd->PrevUserCallbackChar = NULL;
+ bd->PrevUserCallbackMonitor = NULL;
+ if (install_callbacks)
+ {
+ bd->InstalledCallbacks = true;
+ bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback);
+ bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback);
+ bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback);
+ bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback);
+ bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback);
+ bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback);
+ bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
+ }
+
+ bd->ClientApi = client_api;
+ return true;
+}
+
+bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks)
+{
+ return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL);
+}
+
+bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks)
+{
+ return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan);
+}
+
+bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks)
+{
+ return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Unknown);
+}
+
+void ImGui_ImplGlfw_Shutdown()
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ if (bd->InstalledCallbacks)
+ {
+ glfwSetWindowFocusCallback(bd->Window, bd->PrevUserCallbackWindowFocus);
+ glfwSetCursorEnterCallback(bd->Window, bd->PrevUserCallbackCursorEnter);
+ glfwSetMouseButtonCallback(bd->Window, bd->PrevUserCallbackMousebutton);
+ glfwSetScrollCallback(bd->Window, bd->PrevUserCallbackScroll);
+ glfwSetKeyCallback(bd->Window, bd->PrevUserCallbackKey);
+ glfwSetCharCallback(bd->Window, bd->PrevUserCallbackChar);
+ glfwSetMonitorCallback(bd->PrevUserCallbackMonitor);
+ }
+
+ for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
+ glfwDestroyCursor(bd->MouseCursors[cursor_n]);
+
+ io.BackendPlatformName = NULL;
+ io.BackendPlatformUserData = NULL;
+ IM_DELETE(bd);
+}
+
+static void ImGui_ImplGlfw_UpdateMousePosAndButtons()
+{
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ ImGuiIO& io = ImGui::GetIO();
+
+ const ImVec2 mouse_pos_prev = io.MousePos;
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+
+ // Update mouse buttons
+ // (if a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame)
+ for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
+ {
+ io.MouseDown[i] = bd->MouseJustPressed[i] || glfwGetMouseButton(bd->Window, i) != 0;
+ bd->MouseJustPressed[i] = false;
+ }
+
+#ifdef __EMSCRIPTEN__
+ const bool focused = true;
+#else
+ const bool focused = glfwGetWindowAttrib(bd->Window, GLFW_FOCUSED) != 0;
+#endif
+ GLFWwindow* mouse_window = (bd->MouseWindow == bd->Window || focused) ? bd->Window : NULL;
+
+ // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+ if (io.WantSetMousePos && focused)
+ glfwSetCursorPos(bd->Window, (double)mouse_pos_prev.x, (double)mouse_pos_prev.y);
+
+ // Set Dear ImGui mouse position from OS position
+ if (mouse_window != NULL)
+ {
+ double mouse_x, mouse_y;
+ glfwGetCursorPos(mouse_window, &mouse_x, &mouse_y);
+ io.MousePos = ImVec2((float)mouse_x, (float)mouse_y);
+ }
+}
+
+static void ImGui_ImplGlfw_UpdateMouseCursor()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
+ return;
+
+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
+ if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
+ {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+ }
+ else
+ {
+ // Show OS mouse cursor
+ // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here.
+ glfwSetCursor(bd->Window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
+ glfwSetInputMode(bd->Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ }
+}
+
+static void ImGui_ImplGlfw_UpdateGamepads()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ memset(io.NavInputs, 0, sizeof(io.NavInputs));
+ if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
+ return;
+
+ // Update gamepad inputs
+ #define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; }
+ #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; }
+ int axes_count = 0, buttons_count = 0;
+ const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count);
+ const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count);
+ MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A
+ MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B
+ MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X
+ MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y
+ MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left
+ MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right
+ MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up
+ MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down
+ MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB
+ MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB
+ MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f);
+ MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f);
+ MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f);
+ MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f);
+ #undef MAP_BUTTON
+ #undef MAP_ANALOG
+ if (axes_count > 0 && buttons_count > 0)
+ io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
+ else
+ io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
+}
+
+void ImGui_ImplGlfw_NewFrame()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplGlfw_InitForXXX()?");
+
+ // Setup display size (every frame to accommodate for window resizing)
+ int w, h;
+ int display_w, display_h;
+ glfwGetWindowSize(bd->Window, &w, &h);
+ glfwGetFramebufferSize(bd->Window, &display_w, &display_h);
+ io.DisplaySize = ImVec2((float)w, (float)h);
+ if (w > 0 && h > 0)
+ io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
+
+ // Setup time step
+ double current_time = glfwGetTime();
+ io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f);
+ bd->Time = current_time;
+
+ ImGui_ImplGlfw_UpdateMousePosAndButtons();
+ ImGui_ImplGlfw_UpdateMouseCursor();
+
+ // Update game controllers (if enabled and available)
+ ImGui_ImplGlfw_UpdateGamepads();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_glfw.h b/Client/ThirdParty/imgui/backends/imgui_impl_glfw.h
new file mode 100644
index 0000000..5e1fb06
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_glfw.h
@@ -0,0 +1,41 @@
+// dear imgui: Platform Backend for GLFW
+// This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..)
+// (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.)
+
+// Implemented features:
+// [X] Platform: Clipboard support.
+// [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// [x] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. FIXME: 3 cursors types are missing from GLFW.
+// [X] Platform: Keyboard arrays indexed using GLFW_KEY_* codes, e.g. ImGui::IsKeyPressed(GLFW_KEY_SPACE).
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// About GLSL version:
+// The 'glsl_version' initialization parameter defaults to "#version 150" if NULL.
+// Only override if your GL version doesn't handle this GLSL version. Keep NULL if unsure!
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct GLFWwindow;
+struct GLFWmonitor;
+
+IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks);
+IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks);
+IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks);
+IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame();
+
+// GLFW callbacks
+// - When calling Init with 'install_callbacks=true': GLFW callbacks will be installed for you. They will call user's previously installed callbacks, if any.
+// - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call those function yourself from your own GLFW callbacks.
+IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused);
+IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered);
+IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
+IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
+IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
+IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c);
+IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event);
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_glut.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_glut.cpp
new file mode 100644
index 0000000..85bea77
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_glut.cpp
@@ -0,0 +1,217 @@
+// dear imgui: Platform Backend for GLUT/FreeGLUT
+// This needs to be used along with a Renderer (e.g. OpenGL2)
+
+// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
+// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
+// !!! Nowadays, prefer using GLFW or SDL instead!
+
+// Issues:
+// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
+// [ ] Platform: Missing mouse cursor shape/visibility support.
+// [ ] Platform: Missing clipboard support (not supported by Glut).
+// [ ] Platform: Missing gamepad support.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2019-04-03: Misc: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h.
+// 2019-03-25: Misc: Made io.DeltaTime always above zero.
+// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
+// 2018-03-22: Added GLUT Platform binding.
+
+#include "imgui.h"
+#include "imgui_impl_glut.h"
+#ifdef __APPLE__
+#include <GLUT/glut.h>
+#else
+#include <GL/freeglut.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
+#endif
+
+static int g_Time = 0; // Current time, in milliseconds
+
+bool ImGui_ImplGLUT_Init()
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+#ifdef FREEGLUT
+ io.BackendPlatformName = "imgui_impl_glut (freeglut)";
+#else
+ io.BackendPlatformName = "imgui_impl_glut";
+#endif
+
+ g_Time = 0;
+
+ // Glut has 1 function for characters and one for "special keys". We map the characters in the 0..255 range and the keys above.
+ io.KeyMap[ImGuiKey_Tab] = '\t'; // == 9 == CTRL+I
+ io.KeyMap[ImGuiKey_LeftArrow] = 256 + GLUT_KEY_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = 256 + GLUT_KEY_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = 256 + GLUT_KEY_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = 256 + GLUT_KEY_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = 256 + GLUT_KEY_PAGE_UP;
+ io.KeyMap[ImGuiKey_PageDown] = 256 + GLUT_KEY_PAGE_DOWN;
+ io.KeyMap[ImGuiKey_Home] = 256 + GLUT_KEY_HOME;
+ io.KeyMap[ImGuiKey_End] = 256 + GLUT_KEY_END;
+ io.KeyMap[ImGuiKey_Insert] = 256 + GLUT_KEY_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = 127;
+ io.KeyMap[ImGuiKey_Backspace] = 8; // == CTRL+H
+ io.KeyMap[ImGuiKey_Space] = ' ';
+ io.KeyMap[ImGuiKey_Enter] = 13; // == CTRL+M
+ io.KeyMap[ImGuiKey_Escape] = 27;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = 13; // == CTRL+M
+ io.KeyMap[ImGuiKey_A] = 'A';
+ io.KeyMap[ImGuiKey_C] = 'C';
+ io.KeyMap[ImGuiKey_V] = 'V';
+ io.KeyMap[ImGuiKey_X] = 'X';
+ io.KeyMap[ImGuiKey_Y] = 'Y';
+ io.KeyMap[ImGuiKey_Z] = 'Z';
+
+ return true;
+}
+
+void ImGui_ImplGLUT_InstallFuncs()
+{
+ glutReshapeFunc(ImGui_ImplGLUT_ReshapeFunc);
+ glutMotionFunc(ImGui_ImplGLUT_MotionFunc);
+ glutPassiveMotionFunc(ImGui_ImplGLUT_MotionFunc);
+ glutMouseFunc(ImGui_ImplGLUT_MouseFunc);
+#ifdef __FREEGLUT_EXT_H__
+ glutMouseWheelFunc(ImGui_ImplGLUT_MouseWheelFunc);
+#endif
+ glutKeyboardFunc(ImGui_ImplGLUT_KeyboardFunc);
+ glutKeyboardUpFunc(ImGui_ImplGLUT_KeyboardUpFunc);
+ glutSpecialFunc(ImGui_ImplGLUT_SpecialFunc);
+ glutSpecialUpFunc(ImGui_ImplGLUT_SpecialUpFunc);
+}
+
+void ImGui_ImplGLUT_Shutdown()
+{
+}
+
+void ImGui_ImplGLUT_NewFrame()
+{
+ // Setup time step
+ ImGuiIO& io = ImGui::GetIO();
+ int current_time = glutGet(GLUT_ELAPSED_TIME);
+ int delta_time_ms = (current_time - g_Time);
+ if (delta_time_ms <= 0)
+ delta_time_ms = 1;
+ io.DeltaTime = delta_time_ms / 1000.0f;
+ g_Time = current_time;
+
+ // Start the frame
+ ImGui::NewFrame();
+}
+
+static void ImGui_ImplGLUT_UpdateKeyboardMods()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ int mods = glutGetModifiers();
+ io.KeyCtrl = (mods & GLUT_ACTIVE_CTRL) != 0;
+ io.KeyShift = (mods & GLUT_ACTIVE_SHIFT) != 0;
+ io.KeyAlt = (mods & GLUT_ACTIVE_ALT) != 0;
+}
+
+void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y)
+{
+ // Send character to imgui
+ //printf("char_down_func %d '%c'\n", c, c);
+ ImGuiIO& io = ImGui::GetIO();
+ if (c >= 32)
+ io.AddInputCharacter((unsigned int)c);
+
+ // Store letters in KeysDown[] array as both uppercase and lowercase + Handle GLUT translating CTRL+A..CTRL+Z as 1..26.
+ // This is a hacky mess but GLUT is unable to distinguish e.g. a TAB key from CTRL+I so this is probably the best we can do here.
+ if (c >= 1 && c <= 26)
+ io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = true;
+ else if (c >= 'a' && c <= 'z')
+ io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = true;
+ else if (c >= 'A' && c <= 'Z')
+ io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = true;
+ else
+ io.KeysDown[c] = true;
+ ImGui_ImplGLUT_UpdateKeyboardMods();
+ (void)x; (void)y; // Unused
+}
+
+void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y)
+{
+ //printf("char_up_func %d '%c'\n", c, c);
+ ImGuiIO& io = ImGui::GetIO();
+ if (c >= 1 && c <= 26)
+ io.KeysDown[c] = io.KeysDown[c - 1 + 'a'] = io.KeysDown[c - 1 + 'A'] = false;
+ else if (c >= 'a' && c <= 'z')
+ io.KeysDown[c] = io.KeysDown[c - 'a' + 'A'] = false;
+ else if (c >= 'A' && c <= 'Z')
+ io.KeysDown[c] = io.KeysDown[c - 'A' + 'a'] = false;
+ else
+ io.KeysDown[c] = false;
+ ImGui_ImplGLUT_UpdateKeyboardMods();
+ (void)x; (void)y; // Unused
+}
+
+void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y)
+{
+ //printf("key_down_func %d\n", key);
+ ImGuiIO& io = ImGui::GetIO();
+ if (key + 256 < IM_ARRAYSIZE(io.KeysDown))
+ io.KeysDown[key + 256] = true;
+ ImGui_ImplGLUT_UpdateKeyboardMods();
+ (void)x; (void)y; // Unused
+}
+
+void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y)
+{
+ //printf("key_up_func %d\n", key);
+ ImGuiIO& io = ImGui::GetIO();
+ if (key + 256 < IM_ARRAYSIZE(io.KeysDown))
+ io.KeysDown[key + 256] = false;
+ ImGui_ImplGLUT_UpdateKeyboardMods();
+ (void)x; (void)y; // Unused
+}
+
+void ImGui_ImplGLUT_MouseFunc(int glut_button, int state, int x, int y)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.MousePos = ImVec2((float)x, (float)y);
+ int button = -1;
+ if (glut_button == GLUT_LEFT_BUTTON) button = 0;
+ if (glut_button == GLUT_RIGHT_BUTTON) button = 1;
+ if (glut_button == GLUT_MIDDLE_BUTTON) button = 2;
+ if (button != -1 && state == GLUT_DOWN)
+ io.MouseDown[button] = true;
+ if (button != -1 && state == GLUT_UP)
+ io.MouseDown[button] = false;
+}
+
+#ifdef __FREEGLUT_EXT_H__
+void ImGui_ImplGLUT_MouseWheelFunc(int button, int dir, int x, int y)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.MousePos = ImVec2((float)x, (float)y);
+ if (dir > 0)
+ io.MouseWheel += 1.0;
+ else if (dir < 0)
+ io.MouseWheel -= 1.0;
+ (void)button; // Unused
+}
+#endif
+
+void ImGui_ImplGLUT_ReshapeFunc(int w, int h)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.DisplaySize = ImVec2((float)w, (float)h);
+}
+
+void ImGui_ImplGLUT_MotionFunc(int x, int y)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.MousePos = ImVec2((float)x, (float)y);
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_glut.h b/Client/ThirdParty/imgui/backends/imgui_impl_glut.h
new file mode 100644
index 0000000..96c779f
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_glut.h
@@ -0,0 +1,37 @@
+// dear imgui: Platform Backend for GLUT/FreeGLUT
+// This needs to be used along with a Renderer (e.g. OpenGL2)
+
+// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
+// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
+// !!! Nowadays, prefer using GLFW or SDL instead!
+
+// Issues:
+// [ ] Platform: GLUT is unable to distinguish e.g. Backspace from CTRL+H or TAB from CTRL+I
+// [ ] Platform: Missing mouse cursor shape/visibility support.
+// [ ] Platform: Missing clipboard support (not supported by Glut).
+// [ ] Platform: Missing gamepad support.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+IMGUI_IMPL_API bool ImGui_ImplGLUT_Init();
+IMGUI_IMPL_API void ImGui_ImplGLUT_InstallFuncs();
+IMGUI_IMPL_API void ImGui_ImplGLUT_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplGLUT_NewFrame();
+
+// You can call ImGui_ImplGLUT_InstallFuncs() to get all those functions installed automatically,
+// or call them yourself from your own GLUT handlers. We are using the same weird names as GLUT for consistency..
+//---------------------------------------- GLUT name --------------------------------------------- Decent Name ---------
+IMGUI_IMPL_API void ImGui_ImplGLUT_ReshapeFunc(int w, int h); // ~ ResizeFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_MotionFunc(int x, int y); // ~ MouseMoveFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_MouseFunc(int button, int state, int x, int y); // ~ MouseButtonFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_MouseWheelFunc(int button, int dir, int x, int y); // ~ MouseWheelFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_KeyboardFunc(unsigned char c, int x, int y); // ~ CharPressedFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_KeyboardUpFunc(unsigned char c, int x, int y); // ~ CharReleasedFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_SpecialFunc(int key, int x, int y); // ~ KeyPressedFunc
+IMGUI_IMPL_API void ImGui_ImplGLUT_SpecialUpFunc(int key, int x, int y); // ~ KeyReleasedFunc
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_marmalade.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_marmalade.cpp
new file mode 100644
index 0000000..aa6b320
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_marmalade.cpp
@@ -0,0 +1,318 @@
+// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
+// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
+// Missing features:
+// [ ] Renderer: Clipping rectangles are not honored.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
+// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
+// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+
+#include "imgui.h"
+#include "imgui_impl_marmalade.h"
+
+#include <s3eClipboard.h>
+#include <s3ePointer.h>
+#include <s3eKeyboard.h>
+#include <IwTexture.h>
+#include <IwGx.h>
+
+// Data
+static double g_Time = 0.0f;
+static bool g_MousePressed[3] = { false, false, false };
+static CIwTexture* g_FontTexture = NULL;
+static char* g_ClipboardText = NULL;
+static bool g_osdKeyboardEnabled = false;
+
+// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
+static ImVec2 g_RenderScale = ImVec2(1.0f, 1.0f);
+
+// Render function.
+void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ // Render command lists
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+ const int nVert = cmd_list->VtxBuffer.Size;
+ CIwFVec2* pVertStream = IW_GX_ALLOC(CIwFVec2, nVert);
+ CIwFVec2* pUVStream = IW_GX_ALLOC(CIwFVec2, nVert);
+ CIwColour* pColStream = IW_GX_ALLOC(CIwColour, nVert);
+
+ for (int i = 0; i < nVert; i++)
+ {
+ // FIXME-OPT: optimize multiplication on GPU using vertex shader/projection matrix.
+ pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
+ pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
+ pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
+ pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y;
+ pColStream[i] = cmd_list->VtxBuffer[i].col;
+ }
+
+ IwGxSetVertStreamScreenSpace(pVertStream, nVert);
+ IwGxSetUVStream(pUVStream);
+ IwGxSetColStream(pColStream, nVert);
+ IwGxSetNormStream(0);
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // FIXME: Not honoring ClipRect fields.
+ CIwMaterial* pCurrentMaterial = IW_GX_ALLOC_MATERIAL();
+ pCurrentMaterial->SetShadeMode(CIwMaterial::SHADE_FLAT);
+ pCurrentMaterial->SetCullMode(CIwMaterial::CULL_NONE);
+ pCurrentMaterial->SetFiltering(false);
+ pCurrentMaterial->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
+ pCurrentMaterial->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_NORMAL);
+ pCurrentMaterial->SetAlphaTestMode(CIwMaterial::ALPHATEST_DISABLED);
+ pCurrentMaterial->SetTexture((CIwTexture*)pcmd->GetTexID());
+ IwGxSetMaterial(pCurrentMaterial);
+ IwGxDrawPrims(IW_GX_TRI_LIST, (uint16*)idx_buffer, pcmd->ElemCount);
+ }
+ idx_buffer += pcmd->ElemCount;
+ }
+ IwGxFlush();
+ }
+
+ // TODO: restore modified state (i.e. mvp matrix)
+}
+
+static const char* ImGui_Marmalade_GetClipboardText(void* /*user_data*/)
+{
+ if (!s3eClipboardAvailable())
+ return NULL;
+
+ if (int size = s3eClipboardGetText(NULL, 0))
+ {
+ if (g_ClipboardText)
+ delete[] g_ClipboardText;
+ g_ClipboardText = new char[size];
+ g_ClipboardText[0] = '\0';
+ s3eClipboardGetText(g_ClipboardText, size);
+ }
+
+ return g_ClipboardText;
+}
+
+static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* text)
+{
+ if (s3eClipboardAvailable())
+ s3eClipboardSetText(text);
+}
+
+int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data)
+{
+ // pEvent->m_Button is of type s3ePointerButton and indicates which mouse
+ // button was pressed. For touchscreen this should always have the value
+ // S3E_POINTER_BUTTON_SELECT
+ s3ePointerEvent* pEvent = (s3ePointerEvent*)system_data;
+
+ if (pEvent->m_Pressed == 1)
+ {
+ if (pEvent->m_Button == S3E_POINTER_BUTTON_LEFTMOUSE)
+ g_MousePressed[0] = true;
+ if (pEvent->m_Button == S3E_POINTER_BUTTON_RIGHTMOUSE)
+ g_MousePressed[1] = true;
+ if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE)
+ g_MousePressed[2] = true;
+ if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP)
+ io.MouseWheel += pEvent->m_y;
+ if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN)
+ io.MouseWheel += pEvent->m_y;
+ }
+
+ return 0;
+}
+
+int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ s3eKeyboardEvent* e = (s3eKeyboardEvent*)system_data;
+ if (e->m_Pressed == 1)
+ io.KeysDown[e->m_Key] = true;
+ if (e->m_Pressed == 0)
+ io.KeysDown[e->m_Key] = false;
+
+ io.KeyCtrl = s3eKeyboardGetState(s3eKeyLeftControl) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightControl) == S3E_KEY_STATE_DOWN;
+ io.KeyShift = s3eKeyboardGetState(s3eKeyLeftShift) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightShift) == S3E_KEY_STATE_DOWN;
+ io.KeyAlt = s3eKeyboardGetState(s3eKeyLeftAlt) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightAlt) == S3E_KEY_STATE_DOWN;
+ io.KeySuper = s3eKeyboardGetState(s3eKeyLeftWindows) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightWindows) == S3E_KEY_STATE_DOWN;
+
+ return 0;
+}
+
+int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
+ io.AddInputCharacter((unsigned int)e->m_Char);
+
+ return 0;
+}
+
+bool ImGui_Marmalade_CreateDeviceObjects()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // Upload texture to graphics system
+ g_FontTexture = new CIwTexture();
+ g_FontTexture->SetModifiable(true);
+ CIwImage& image = g_FontTexture->GetImage();
+ image.SetFormat(CIwImage::ARGB_8888);
+ image.SetWidth(width);
+ image.SetHeight(height);
+ image.SetBuffers(); // allocates and own buffers
+ image.ReadTexels(pixels);
+ g_FontTexture->SetMipMapping(false);
+ g_FontTexture->SetFiltering(false);
+ g_FontTexture->Upload();
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)g_FontTexture);
+
+ return true;
+}
+
+void ImGui_Marmalade_InvalidateDeviceObjects()
+{
+ if (g_ClipboardText)
+ {
+ delete[] g_ClipboardText;
+ g_ClipboardText = NULL;
+ }
+
+ if (g_FontTexture)
+ {
+ ImGui::GetIO().Fonts->SetTexID(0);
+ delete g_FontTexture;
+ g_FontTexture = NULL;
+ }
+}
+
+bool ImGui_Marmalade_Init(bool install_callbacks)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade";
+
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
+ io.KeyMap[ImGuiKey_Tab] = s3eKeyTab
+ io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft;
+ io.KeyMap[ImGuiKey_RightArrow] = s3eKeyRight;
+ io.KeyMap[ImGuiKey_UpArrow] = s3eKeyUp;
+ io.KeyMap[ImGuiKey_DownArrow] = s3eKeyDown;
+ io.KeyMap[ImGuiKey_PageUp] = s3eKeyPageUp;
+ io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown;
+ io.KeyMap[ImGuiKey_Home] = s3eKeyHome;
+ io.KeyMap[ImGuiKey_End] = s3eKeyEnd;
+ io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert;
+ io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete;
+ io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace;
+ io.KeyMap[ImGuiKey_Space] = s3eKeySpace;
+ io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
+ io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter;
+ io.KeyMap[ImGuiKey_A] = s3eKeyA;
+ io.KeyMap[ImGuiKey_C] = s3eKeyC;
+ io.KeyMap[ImGuiKey_V] = s3eKeyV;
+ io.KeyMap[ImGuiKey_X] = s3eKeyX;
+ io.KeyMap[ImGuiKey_Y] = s3eKeyY;
+ io.KeyMap[ImGuiKey_Z] = s3eKeyZ;
+
+ io.SetClipboardTextFn = ImGui_Marmalade_SetClipboardText;
+ io.GetClipboardTextFn = ImGui_Marmalade_GetClipboardText;
+
+ if (install_callbacks)
+ {
+ s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, ImGui_Marmalade_PointerButtonEventCallback, 0);
+ s3eKeyboardRegister(S3E_KEYBOARD_KEY_EVENT, ImGui_Marmalade_KeyCallback, 0);
+ s3eKeyboardRegister(S3E_KEYBOARD_CHAR_EVENT, ImGui_Marmalade_CharCallback, 0);
+ }
+
+ return true;
+}
+
+void ImGui_Marmalade_Shutdown()
+{
+ ImGui_Marmalade_InvalidateDeviceObjects();
+}
+
+void ImGui_Marmalade_NewFrame()
+{
+ if (!g_FontTexture)
+ ImGui_Marmalade_CreateDeviceObjects();
+
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup display size (every frame to accommodate for window resizing)
+ int w = IwGxGetScreenWidth(), h = IwGxGetScreenHeight();
+ io.DisplaySize = ImVec2((float)w, (float)h);
+ // For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
+ io.DisplayFramebufferScale = g_scale;
+
+ // Setup time step
+ double current_time = s3eTimerGetUST() / 1000.0f;
+ io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
+ g_Time = current_time;
+
+ double mouse_x, mouse_y;
+ mouse_x = s3ePointerGetX();
+ mouse_y = s3ePointerGetY();
+ io.MousePos = ImVec2((float)mouse_x / g_scale.x, (float)mouse_y / g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.)
+
+ for (int i = 0; i < 3; i++)
+ {
+ io.MouseDown[i] = g_MousePressed[i] || s3ePointerGetState((s3ePointerButton)i) != S3E_POINTER_STATE_UP; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
+ g_MousePressed[i] = false;
+ }
+
+ // TODO: Hide OS mouse cursor if ImGui is drawing it
+ // s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
+
+ // Show/hide OSD keyboard
+ if (io.WantTextInput)
+ {
+ // Some text input widget is active?
+ if (!g_osdKeyboardEnabled)
+ {
+ g_osdKeyboardEnabled = true;
+ s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 1); // show OSD keyboard
+ }
+ }
+ else
+ {
+ // No text input widget is active
+ if (g_osdKeyboardEnabled)
+ {
+ g_osdKeyboardEnabled = false;
+ s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 0); // hide OSD keyboard
+ }
+ }
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_marmalade.h b/Client/ThirdParty/imgui/backends/imgui_impl_marmalade.h
new file mode 100644
index 0000000..87aaa47
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_marmalade.h
@@ -0,0 +1,28 @@
+// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
+// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+IMGUI_IMPL_API bool ImGui_Marmalade_Init(bool install_callbacks);
+IMGUI_IMPL_API void ImGui_Marmalade_Shutdown();
+IMGUI_IMPL_API void ImGui_Marmalade_NewFrame();
+IMGUI_IMPL_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API void ImGui_Marmalade_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_Marmalade_CreateDeviceObjects();
+
+// Callbacks (installed by default if you enable 'install_callbacks' during initialization)
+// You can also handle inputs yourself and use those as a reference.
+IMGUI_IMPL_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data);
+IMGUI_IMPL_API int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data);
+IMGUI_IMPL_API int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data);
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_metal.h b/Client/ThirdParty/imgui/backends/imgui_impl_metal.h
new file mode 100644
index 0000000..c0c6018
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_metal.h
@@ -0,0 +1,29 @@
+// dear imgui: Renderer Backend for Metal
+// This needs to be used along with a Platform Backend (e.g. OSX)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h" // IMGUI_IMPL_API
+
+@class MTLRenderPassDescriptor;
+@protocol MTLDevice, MTLCommandBuffer, MTLRenderCommandEncoder;
+
+IMGUI_IMPL_API bool ImGui_ImplMetal_Init(id<MTLDevice> device);
+IMGUI_IMPL_API void ImGui_ImplMetal_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor* renderPassDescriptor);
+IMGUI_IMPL_API void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data,
+ id<MTLCommandBuffer> commandBuffer,
+ id<MTLRenderCommandEncoder> commandEncoder);
+
+// Called by Init/NewFrame/Shutdown
+IMGUI_IMPL_API bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device);
+IMGUI_IMPL_API void ImGui_ImplMetal_DestroyFontsTexture();
+IMGUI_IMPL_API bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device);
+IMGUI_IMPL_API void ImGui_ImplMetal_DestroyDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_metal.mm b/Client/ThirdParty/imgui/backends/imgui_impl_metal.mm
new file mode 100644
index 0000000..18dcc91
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_metal.mm
@@ -0,0 +1,556 @@
+// dear imgui: Renderer Backend for Metal
+// This needs to be used along with a Platform Backend (e.g. OSX)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-24: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464)
+// 2021-05-19: Metal: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-02-18: Metal: Change blending equation to preserve alpha in output buffer.
+// 2021-01-25: Metal: Fixed texture storage mode when building on Mac Catalyst.
+// 2019-05-29: Metal: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: Metal: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-02-11: Metal: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-07-05: Metal: Added new Metal backend implementation.
+
+#include "imgui.h"
+#include "imgui_impl_metal.h"
+
+#import <Metal/Metal.h>
+// #import <QuartzCore/CAMetalLayer.h> // Not supported in XCode 9.2. Maybe a macro to detect the SDK version can be used (something like #if MACOS_SDK >= 10.13 ...)
+#import <simd/simd.h>
+
+#pragma mark - Support classes
+
+// A wrapper around a MTLBuffer object that knows the last time it was reused
+@interface MetalBuffer : NSObject
+@property (nonatomic, strong) id<MTLBuffer> buffer;
+@property (nonatomic, assign) NSTimeInterval lastReuseTime;
+- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer;
+@end
+
+// An object that encapsulates the data necessary to uniquely identify a
+// render pipeline state. These are used as cache keys.
+@interface FramebufferDescriptor : NSObject<NSCopying>
+@property (nonatomic, assign) unsigned long sampleCount;
+@property (nonatomic, assign) MTLPixelFormat colorPixelFormat;
+@property (nonatomic, assign) MTLPixelFormat depthPixelFormat;
+@property (nonatomic, assign) MTLPixelFormat stencilPixelFormat;
+- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor;
+@end
+
+// A singleton that stores long-lived objects that are needed by the Metal
+// renderer backend. Stores the render pipeline state cache and the default
+// font texture, and manages the reusable buffer cache.
+@interface MetalContext : NSObject
+@property (nonatomic, strong) id<MTLDepthStencilState> depthStencilState;
+@property (nonatomic, strong) FramebufferDescriptor *framebufferDescriptor; // framebuffer descriptor for current frame; transient
+@property (nonatomic, strong) NSMutableDictionary *renderPipelineStateCache; // pipeline cache; keyed on framebuffer descriptors
+@property (nonatomic, strong, nullable) id<MTLTexture> fontTexture;
+@property (nonatomic, strong) NSMutableArray<MetalBuffer *> *bufferCache;
+@property (nonatomic, assign) NSTimeInterval lastBufferCachePurge;
+- (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device;
+- (void)makeFontTextureWithDevice:(id<MTLDevice>)device;
+- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device;
+- (void)enqueueReusableBuffer:(MetalBuffer *)buffer;
+- (id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device;
+- (void)emptyRenderPipelineStateCache;
+- (void)setupRenderState:(ImDrawData *)drawData
+ commandBuffer:(id<MTLCommandBuffer>)commandBuffer
+ commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
+ renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
+ vertexBuffer:(MetalBuffer *)vertexBuffer
+ vertexBufferOffset:(size_t)vertexBufferOffset;
+- (void)renderDrawData:(ImDrawData *)drawData
+ commandBuffer:(id<MTLCommandBuffer>)commandBuffer
+ commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder;
+@end
+
+static MetalContext *g_sharedMetalContext = nil;
+
+#pragma mark - ImGui API implementation
+
+bool ImGui_ImplMetal_Init(id<MTLDevice> device)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendRendererName = "imgui_impl_metal";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ g_sharedMetalContext = [[MetalContext alloc] init];
+ });
+
+ ImGui_ImplMetal_CreateDeviceObjects(device);
+
+ return true;
+}
+
+void ImGui_ImplMetal_Shutdown()
+{
+ ImGui_ImplMetal_DestroyDeviceObjects();
+}
+
+void ImGui_ImplMetal_NewFrame(MTLRenderPassDescriptor *renderPassDescriptor)
+{
+ IM_ASSERT(g_sharedMetalContext != nil && "No Metal context. Did you call ImGui_ImplMetal_Init() ?");
+
+ g_sharedMetalContext.framebufferDescriptor = [[FramebufferDescriptor alloc] initWithRenderPassDescriptor:renderPassDescriptor];
+}
+
+// Metal Render function.
+void ImGui_ImplMetal_RenderDrawData(ImDrawData* draw_data, id<MTLCommandBuffer> commandBuffer, id<MTLRenderCommandEncoder> commandEncoder)
+{
+ [g_sharedMetalContext renderDrawData:draw_data commandBuffer:commandBuffer commandEncoder:commandEncoder];
+}
+
+bool ImGui_ImplMetal_CreateFontsTexture(id<MTLDevice> device)
+{
+ [g_sharedMetalContext makeFontTextureWithDevice:device];
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.Fonts->SetTexID((__bridge void *)g_sharedMetalContext.fontTexture); // ImTextureID == void*
+
+ return (g_sharedMetalContext.fontTexture != nil);
+}
+
+void ImGui_ImplMetal_DestroyFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ g_sharedMetalContext.fontTexture = nil;
+ io.Fonts->SetTexID(nullptr);
+}
+
+bool ImGui_ImplMetal_CreateDeviceObjects(id<MTLDevice> device)
+{
+ [g_sharedMetalContext makeDeviceObjectsWithDevice:device];
+
+ ImGui_ImplMetal_CreateFontsTexture(device);
+
+ return true;
+}
+
+void ImGui_ImplMetal_DestroyDeviceObjects()
+{
+ ImGui_ImplMetal_DestroyFontsTexture();
+ [g_sharedMetalContext emptyRenderPipelineStateCache];
+}
+
+#pragma mark - MetalBuffer implementation
+
+@implementation MetalBuffer
+- (instancetype)initWithBuffer:(id<MTLBuffer>)buffer
+{
+ if ((self = [super init]))
+ {
+ _buffer = buffer;
+ _lastReuseTime = [NSDate date].timeIntervalSince1970;
+ }
+ return self;
+}
+@end
+
+#pragma mark - FramebufferDescriptor implementation
+
+@implementation FramebufferDescriptor
+- (instancetype)initWithRenderPassDescriptor:(MTLRenderPassDescriptor *)renderPassDescriptor
+{
+ if ((self = [super init]))
+ {
+ _sampleCount = renderPassDescriptor.colorAttachments[0].texture.sampleCount;
+ _colorPixelFormat = renderPassDescriptor.colorAttachments[0].texture.pixelFormat;
+ _depthPixelFormat = renderPassDescriptor.depthAttachment.texture.pixelFormat;
+ _stencilPixelFormat = renderPassDescriptor.stencilAttachment.texture.pixelFormat;
+ }
+ return self;
+}
+
+- (nonnull id)copyWithZone:(nullable NSZone *)zone
+{
+ FramebufferDescriptor *copy = [[FramebufferDescriptor allocWithZone:zone] init];
+ copy.sampleCount = self.sampleCount;
+ copy.colorPixelFormat = self.colorPixelFormat;
+ copy.depthPixelFormat = self.depthPixelFormat;
+ copy.stencilPixelFormat = self.stencilPixelFormat;
+ return copy;
+}
+
+- (NSUInteger)hash
+{
+ NSUInteger sc = _sampleCount & 0x3;
+ NSUInteger cf = _colorPixelFormat & 0x3FF;
+ NSUInteger df = _depthPixelFormat & 0x3FF;
+ NSUInteger sf = _stencilPixelFormat & 0x3FF;
+ NSUInteger hash = (sf << 22) | (df << 12) | (cf << 2) | sc;
+ return hash;
+}
+
+- (BOOL)isEqual:(id)object
+{
+ FramebufferDescriptor *other = object;
+ if (![other isKindOfClass:[FramebufferDescriptor class]])
+ return NO;
+ return other.sampleCount == self.sampleCount &&
+ other.colorPixelFormat == self.colorPixelFormat &&
+ other.depthPixelFormat == self.depthPixelFormat &&
+ other.stencilPixelFormat == self.stencilPixelFormat;
+}
+
+@end
+
+#pragma mark - MetalContext implementation
+
+@implementation MetalContext
+- (instancetype)init {
+ if ((self = [super init]))
+ {
+ _renderPipelineStateCache = [NSMutableDictionary dictionary];
+ _bufferCache = [NSMutableArray array];
+ _lastBufferCachePurge = [NSDate date].timeIntervalSince1970;
+ }
+ return self;
+}
+
+- (void)makeDeviceObjectsWithDevice:(id<MTLDevice>)device
+{
+ MTLDepthStencilDescriptor *depthStencilDescriptor = [[MTLDepthStencilDescriptor alloc] init];
+ depthStencilDescriptor.depthWriteEnabled = NO;
+ depthStencilDescriptor.depthCompareFunction = MTLCompareFunctionAlways;
+ self.depthStencilState = [device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
+}
+
+// We are retrieving and uploading the font atlas as a 4-channels RGBA texture here.
+// In theory we could call GetTexDataAsAlpha8() and upload a 1-channel texture to save on memory access bandwidth.
+// However, using a shader designed for 1-channel texture would make it less obvious to use the ImTextureID facility to render users own textures.
+// You can make that change in your implementation.
+- (void)makeFontTextureWithDevice:(id<MTLDevice>)device
+{
+ ImGuiIO &io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+ MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
+ width:(NSUInteger)width
+ height:(NSUInteger)height
+ mipmapped:NO];
+ textureDescriptor.usage = MTLTextureUsageShaderRead;
+#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
+ textureDescriptor.storageMode = MTLStorageModeManaged;
+#else
+ textureDescriptor.storageMode = MTLStorageModeShared;
+#endif
+ id <MTLTexture> texture = [device newTextureWithDescriptor:textureDescriptor];
+ [texture replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)width, (NSUInteger)height) mipmapLevel:0 withBytes:pixels bytesPerRow:(NSUInteger)width * 4];
+ self.fontTexture = texture;
+}
+
+- (MetalBuffer *)dequeueReusableBufferOfLength:(NSUInteger)length device:(id<MTLDevice>)device
+{
+ NSTimeInterval now = [NSDate date].timeIntervalSince1970;
+
+ // Purge old buffers that haven't been useful for a while
+ if (now - self.lastBufferCachePurge > 1.0)
+ {
+ NSMutableArray *survivors = [NSMutableArray array];
+ for (MetalBuffer *candidate in self.bufferCache)
+ {
+ if (candidate.lastReuseTime > self.lastBufferCachePurge)
+ {
+ [survivors addObject:candidate];
+ }
+ }
+ self.bufferCache = [survivors mutableCopy];
+ self.lastBufferCachePurge = now;
+ }
+
+ // See if we have a buffer we can reuse
+ MetalBuffer *bestCandidate = nil;
+ for (MetalBuffer *candidate in self.bufferCache)
+ if (candidate.buffer.length >= length && (bestCandidate == nil || bestCandidate.lastReuseTime > candidate.lastReuseTime))
+ bestCandidate = candidate;
+
+ if (bestCandidate != nil)
+ {
+ [self.bufferCache removeObject:bestCandidate];
+ bestCandidate.lastReuseTime = now;
+ return bestCandidate;
+ }
+
+ // No luck; make a new buffer
+ id<MTLBuffer> backing = [device newBufferWithLength:length options:MTLResourceStorageModeShared];
+ return [[MetalBuffer alloc] initWithBuffer:backing];
+}
+
+- (void)enqueueReusableBuffer:(MetalBuffer *)buffer
+{
+ [self.bufferCache addObject:buffer];
+}
+
+- (_Nullable id<MTLRenderPipelineState>)renderPipelineStateForFrameAndDevice:(id<MTLDevice>)device
+{
+ // Try to retrieve a render pipeline state that is compatible with the framebuffer config for this frame
+ // The hit rate for this cache should be very near 100%.
+ id<MTLRenderPipelineState> renderPipelineState = self.renderPipelineStateCache[self.framebufferDescriptor];
+
+ if (renderPipelineState == nil)
+ {
+ // No luck; make a new render pipeline state
+ renderPipelineState = [self _renderPipelineStateForFramebufferDescriptor:self.framebufferDescriptor device:device];
+ // Cache render pipeline state for later reuse
+ self.renderPipelineStateCache[self.framebufferDescriptor] = renderPipelineState;
+ }
+
+ return renderPipelineState;
+}
+
+- (id<MTLRenderPipelineState>)_renderPipelineStateForFramebufferDescriptor:(FramebufferDescriptor *)descriptor device:(id<MTLDevice>)device
+{
+ NSError *error = nil;
+
+ NSString *shaderSource = @""
+ "#include <metal_stdlib>\n"
+ "using namespace metal;\n"
+ "\n"
+ "struct Uniforms {\n"
+ " float4x4 projectionMatrix;\n"
+ "};\n"
+ "\n"
+ "struct VertexIn {\n"
+ " float2 position [[attribute(0)]];\n"
+ " float2 texCoords [[attribute(1)]];\n"
+ " uchar4 color [[attribute(2)]];\n"
+ "};\n"
+ "\n"
+ "struct VertexOut {\n"
+ " float4 position [[position]];\n"
+ " float2 texCoords;\n"
+ " float4 color;\n"
+ "};\n"
+ "\n"
+ "vertex VertexOut vertex_main(VertexIn in [[stage_in]],\n"
+ " constant Uniforms &uniforms [[buffer(1)]]) {\n"
+ " VertexOut out;\n"
+ " out.position = uniforms.projectionMatrix * float4(in.position, 0, 1);\n"
+ " out.texCoords = in.texCoords;\n"
+ " out.color = float4(in.color) / float4(255.0);\n"
+ " return out;\n"
+ "}\n"
+ "\n"
+ "fragment half4 fragment_main(VertexOut in [[stage_in]],\n"
+ " texture2d<half, access::sample> texture [[texture(0)]]) {\n"
+ " constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);\n"
+ " half4 texColor = texture.sample(linearSampler, in.texCoords);\n"
+ " return half4(in.color) * texColor;\n"
+ "}\n";
+
+ id<MTLLibrary> library = [device newLibraryWithSource:shaderSource options:nil error:&error];
+ if (library == nil)
+ {
+ NSLog(@"Error: failed to create Metal library: %@", error);
+ return nil;
+ }
+
+ id<MTLFunction> vertexFunction = [library newFunctionWithName:@"vertex_main"];
+ id<MTLFunction> fragmentFunction = [library newFunctionWithName:@"fragment_main"];
+
+ if (vertexFunction == nil || fragmentFunction == nil)
+ {
+ NSLog(@"Error: failed to find Metal shader functions in library: %@", error);
+ return nil;
+ }
+
+ MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
+ vertexDescriptor.attributes[0].offset = IM_OFFSETOF(ImDrawVert, pos);
+ vertexDescriptor.attributes[0].format = MTLVertexFormatFloat2; // position
+ vertexDescriptor.attributes[0].bufferIndex = 0;
+ vertexDescriptor.attributes[1].offset = IM_OFFSETOF(ImDrawVert, uv);
+ vertexDescriptor.attributes[1].format = MTLVertexFormatFloat2; // texCoords
+ vertexDescriptor.attributes[1].bufferIndex = 0;
+ vertexDescriptor.attributes[2].offset = IM_OFFSETOF(ImDrawVert, col);
+ vertexDescriptor.attributes[2].format = MTLVertexFormatUChar4; // color
+ vertexDescriptor.attributes[2].bufferIndex = 0;
+ vertexDescriptor.layouts[0].stepRate = 1;
+ vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
+ vertexDescriptor.layouts[0].stride = sizeof(ImDrawVert);
+
+ MTLRenderPipelineDescriptor *pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
+ pipelineDescriptor.vertexFunction = vertexFunction;
+ pipelineDescriptor.fragmentFunction = fragmentFunction;
+ pipelineDescriptor.vertexDescriptor = vertexDescriptor;
+ pipelineDescriptor.sampleCount = self.framebufferDescriptor.sampleCount;
+ pipelineDescriptor.colorAttachments[0].pixelFormat = self.framebufferDescriptor.colorPixelFormat;
+ pipelineDescriptor.colorAttachments[0].blendingEnabled = YES;
+ pipelineDescriptor.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
+ pipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
+ pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
+ pipelineDescriptor.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
+ pipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
+ pipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
+ pipelineDescriptor.depthAttachmentPixelFormat = self.framebufferDescriptor.depthPixelFormat;
+ pipelineDescriptor.stencilAttachmentPixelFormat = self.framebufferDescriptor.stencilPixelFormat;
+
+ id<MTLRenderPipelineState> renderPipelineState = [device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
+ if (error != nil)
+ {
+ NSLog(@"Error: failed to create Metal pipeline state: %@", error);
+ }
+
+ return renderPipelineState;
+}
+
+- (void)emptyRenderPipelineStateCache
+{
+ [self.renderPipelineStateCache removeAllObjects];
+}
+
+- (void)setupRenderState:(ImDrawData *)drawData
+ commandBuffer:(id<MTLCommandBuffer>)commandBuffer
+ commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
+ renderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState
+ vertexBuffer:(MetalBuffer *)vertexBuffer
+ vertexBufferOffset:(size_t)vertexBufferOffset
+{
+ [commandEncoder setCullMode:MTLCullModeNone];
+ [commandEncoder setDepthStencilState:g_sharedMetalContext.depthStencilState];
+
+ // Setup viewport, orthographic projection matrix
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to
+ // draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.
+ MTLViewport viewport =
+ {
+ .originX = 0.0,
+ .originY = 0.0,
+ .width = (double)(drawData->DisplaySize.x * drawData->FramebufferScale.x),
+ .height = (double)(drawData->DisplaySize.y * drawData->FramebufferScale.y),
+ .znear = 0.0,
+ .zfar = 1.0
+ };
+ [commandEncoder setViewport:viewport];
+
+ float L = drawData->DisplayPos.x;
+ float R = drawData->DisplayPos.x + drawData->DisplaySize.x;
+ float T = drawData->DisplayPos.y;
+ float B = drawData->DisplayPos.y + drawData->DisplaySize.y;
+ float N = (float)viewport.znear;
+ float F = (float)viewport.zfar;
+ const float ortho_projection[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 1/(F-N), 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), N/(F-N), 1.0f },
+ };
+ [commandEncoder setVertexBytes:&ortho_projection length:sizeof(ortho_projection) atIndex:1];
+
+ [commandEncoder setRenderPipelineState:renderPipelineState];
+
+ [commandEncoder setVertexBuffer:vertexBuffer.buffer offset:0 atIndex:0];
+ [commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0];
+}
+
+- (void)renderDrawData:(ImDrawData *)drawData
+ commandBuffer:(id<MTLCommandBuffer>)commandBuffer
+ commandEncoder:(id<MTLRenderCommandEncoder>)commandEncoder
+{
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ int fb_width = (int)(drawData->DisplaySize.x * drawData->FramebufferScale.x);
+ int fb_height = (int)(drawData->DisplaySize.y * drawData->FramebufferScale.y);
+ if (fb_width <= 0 || fb_height <= 0 || drawData->CmdListsCount == 0)
+ return;
+
+ id<MTLRenderPipelineState> renderPipelineState = [self renderPipelineStateForFrameAndDevice:commandBuffer.device];
+
+ size_t vertexBufferLength = (size_t)drawData->TotalVtxCount * sizeof(ImDrawVert);
+ size_t indexBufferLength = (size_t)drawData->TotalIdxCount * sizeof(ImDrawIdx);
+ MetalBuffer* vertexBuffer = [self dequeueReusableBufferOfLength:vertexBufferLength device:commandBuffer.device];
+ MetalBuffer* indexBuffer = [self dequeueReusableBufferOfLength:indexBufferLength device:commandBuffer.device];
+
+ [self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:0];
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_off = drawData->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = drawData->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
+
+ // Render command lists
+ size_t vertexBufferOffset = 0;
+ size_t indexBufferOffset = 0;
+ for (int n = 0; n < drawData->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = drawData->CmdLists[n];
+
+ memcpy((char *)vertexBuffer.buffer.contents + vertexBufferOffset, cmd_list->VtxBuffer.Data, (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy((char *)indexBuffer.buffer.contents + indexBufferOffset, cmd_list->IdxBuffer.Data, (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ [self setupRenderState:drawData commandBuffer:commandBuffer commandEncoder:commandEncoder renderPipelineState:renderPipelineState vertexBuffer:vertexBuffer vertexBufferOffset:vertexBufferOffset];
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+
+ // Clamp to viewport as setScissorRect() won't accept values that are off bounds
+ if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
+ if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
+ if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
+ if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle
+ MTLScissorRect scissorRect =
+ {
+ .x = NSUInteger(clip_min.x),
+ .y = NSUInteger(clip_min.y),
+ .width = NSUInteger(clip_max.x - clip_min.x),
+ .height = NSUInteger(clip_max.y - clip_min.y)
+ };
+ [commandEncoder setScissorRect:scissorRect];
+
+ // Bind texture, Draw
+ if (ImTextureID tex_id = pcmd->GetTexID())
+ [commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(tex_id) atIndex:0];
+
+ [commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
+ [commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
+ indexCount:pcmd->ElemCount
+ indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
+ indexBuffer:indexBuffer.buffer
+ indexBufferOffset:indexBufferOffset + pcmd->IdxOffset * sizeof(ImDrawIdx)];
+ }
+ }
+
+ vertexBufferOffset += (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
+ indexBufferOffset += (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
+ }
+
+ __weak id weakSelf = self;
+ [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
+ {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [weakSelf enqueueReusableBuffer:vertexBuffer];
+ [weakSelf enqueueReusableBuffer:indexBuffer];
+ });
+ }];
+}
+
+@end
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_opengl2.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_opengl2.cpp
new file mode 100644
index 0000000..ee52632
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_opengl2.cpp
@@ -0,0 +1,285 @@
+// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
+// **Prefer using the code in imgui_impl_opengl3.cpp**
+// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
+// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
+// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
+// confuse your GPU driver.
+// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
+// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
+// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-08-03: OpenGL: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications.
+// 2018-06-08: Misc: Extracted imgui_impl_opengl2.cpp/.h away from the old combined GLFW/SDL+OpenGL2 examples.
+// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplOpenGL2_RenderDrawData() in the .h file so you can call it yourself.
+// 2017-09-01: OpenGL: Save and restore current polygon mode.
+// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal).
+// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
+
+#include "imgui.h"
+#include "imgui_impl_opengl2.h"
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// Include OpenGL header (without an OpenGL loader) requires a bit of fiddling
+#if defined(_WIN32) && !defined(APIENTRY)
+#define APIENTRY __stdcall // It is customary to use APIENTRY for OpenGL function pointer declarations on all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
+#endif
+#if defined(_WIN32) && !defined(WINGDIAPI)
+#define WINGDIAPI __declspec(dllimport) // Some Windows OpenGL headers need this
+#endif
+#if defined(__APPLE__)
+#define GL_SILENCE_DEPRECATION
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+struct ImGui_ImplOpenGL2_Data
+{
+ GLuint FontTexture;
+
+ ImGui_ImplOpenGL2_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplOpenGL2_Data* ImGui_ImplOpenGL2_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL2_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+bool ImGui_ImplOpenGL2_Init()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplOpenGL2_Data* bd = IM_NEW(ImGui_ImplOpenGL2_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_opengl2";
+
+ return true;
+}
+
+void ImGui_ImplOpenGL2_Shutdown()
+{
+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplOpenGL2_DestroyDeviceObjects();
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+void ImGui_ImplOpenGL2_NewFrame()
+{
+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplOpenGL2_Init()?");
+
+ if (!bd->FontTexture)
+ ImGui_ImplOpenGL2_CreateDeviceObjects();
+}
+
+static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
+{
+ // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ //glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // In order to composite our output buffer we need to preserve alpha
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ glEnable(GL_SCISSOR_TEST);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glShadeModel(GL_SMOOTH);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
+ // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
+ // (DO NOT MODIFY THIS FILE! Add the code in your calling function)
+ // GLint last_program;
+ // glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
+ // glUseProgram(0);
+ // ImGui_ImplOpenGL2_RenderDrawData(...);
+ // glUseProgram(last_program)
+ // There are potentially many more states you could need to clear/setup that we can't access from default headers.
+ // e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
+
+ // Setup viewport, orthographic projection matrix
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(draw_data->DisplayPos.x, draw_data->DisplayPos.x + draw_data->DisplaySize.x, draw_data->DisplayPos.y + draw_data->DisplaySize.y, draw_data->DisplayPos.y, -1.0f, +1.0f);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+}
+
+// OpenGL2 Render function.
+// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
+// This is in order to be able to run within an OpenGL engine that doesn't do so.
+void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
+ int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
+ if (fb_width == 0 || fb_height == 0)
+ return;
+
+ // Backup GL state
+ GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+ GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
+ GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
+ GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
+ GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
+ GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
+ glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
+
+ // Setup desired GL state
+ ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
+
+ // Render command lists
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+ glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos)));
+ glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv)));
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col)));
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplOpenGL2_SetupRenderState(draw_data, fb_width, fb_height);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
+ glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
+
+ // Bind texture, Draw
+ glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
+ glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
+ }
+ idx_buffer += pcmd->ElemCount;
+ }
+ }
+
+ // Restore modified GL state
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glBindTexture(GL_TEXTURE_2D, (GLuint)last_texture);
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glPopAttrib();
+ glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
+ glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
+ glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
+ glShadeModel(last_shade_model);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
+}
+
+bool ImGui_ImplOpenGL2_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
+
+ // Upload texture to graphics system
+ GLint last_texture;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+ glGenTextures(1, &bd->FontTexture);
+ glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
+
+ // Restore state
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+
+ return true;
+}
+
+void ImGui_ImplOpenGL2_DestroyFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplOpenGL2_Data* bd = ImGui_ImplOpenGL2_GetBackendData();
+ if (bd->FontTexture)
+ {
+ glDeleteTextures(1, &bd->FontTexture);
+ io.Fonts->SetTexID(0);
+ bd->FontTexture = 0;
+ }
+}
+
+bool ImGui_ImplOpenGL2_CreateDeviceObjects()
+{
+ return ImGui_ImplOpenGL2_CreateFontsTexture();
+}
+
+void ImGui_ImplOpenGL2_DestroyDeviceObjects()
+{
+ ImGui_ImplOpenGL2_DestroyFontsTexture();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_opengl2.h b/Client/ThirdParty/imgui/backends/imgui_impl_opengl2.h
new file mode 100644
index 0000000..d00d27f
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_opengl2.h
@@ -0,0 +1,32 @@
+// dear imgui: Renderer Backend for OpenGL2 (legacy OpenGL, fixed pipeline)
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
+// **Prefer using the code in imgui_impl_opengl3.cpp**
+// This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read.
+// If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more
+// complicated, will require your code to reset every single OpenGL attributes to their initial state, and might
+// confuse your GPU driver.
+// The GL2 code is unable to reset attributes or even call e.g. "glUseProgram(0)" because they don't exist in that API.
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+IMGUI_IMPL_API bool ImGui_ImplOpenGL2_Init();
+IMGUI_IMPL_API void ImGui_ImplOpenGL2_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplOpenGL2_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data);
+
+// Called by Init/NewFrame/Shutdown
+IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateFontsTexture();
+IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyFontsTexture();
+IMGUI_IMPL_API bool ImGui_ImplOpenGL2_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplOpenGL2_DestroyDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_opengl3.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_opengl3.cpp
new file mode 100644
index 0000000..58664ea
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_opengl3.cpp
@@ -0,0 +1,778 @@
+// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
+// - Desktop GL: 2.x 3.x 4.x
+// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
+// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state.
+// 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader.
+// 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version.
+// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
+// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
+// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
+// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
+// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
+// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
+// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
+// 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
+// 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
+// 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
+// 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader.
+// 2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader.
+// 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders.
+// 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility.
+// 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call.
+// 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
+// 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
+// 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
+// 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
+// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
+// 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN.
+// 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
+// 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
+// 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
+// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.
+// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
+// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
+// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.
+// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".
+// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
+// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
+// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
+// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.
+// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
+// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
+// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
+
+//----------------------------------------
+// OpenGL GLSL GLSL
+// version version string
+//----------------------------------------
+// 2.0 110 "#version 110"
+// 2.1 120 "#version 120"
+// 3.0 130 "#version 130"
+// 3.1 140 "#version 140"
+// 3.2 150 "#version 150"
+// 3.3 330 "#version 330 core"
+// 4.0 400 "#version 400 core"
+// 4.1 410 "#version 410 core"
+// 4.2 420 "#version 410 core"
+// 4.3 430 "#version 430 core"
+// ES 2.0 100 "#version 100" = WebGL 1.0
+// ES 3.0 300 "#version 300 es" = WebGL 2.0
+//----------------------------------------
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#include "imgui_impl_opengl3.h"
+#include <stdio.h>
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// GL includes
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+#include <GLES2/gl2.h>
+#if defined(__EMSCRIPTEN__)
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+#endif
+#include <GLES2/gl2ext.h>
+#endif
+#elif defined(IMGUI_IMPL_OPENGL_ES3)
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
+#include <OpenGLES/ES3/gl.h> // Use GL ES 3
+#else
+#include <GLES3/gl3.h> // Use GL ES 3
+#endif
+#elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
+// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
+// Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w.
+// In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).
+// If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):
+// - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped
+// - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases
+// Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version.
+#define IMGL3W_IMPL
+#include "imgui_impl_opengl3_loader.h"
+#endif
+
+// Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension
+#ifndef IMGUI_IMPL_OPENGL_ES2
+#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+#elif defined(__EMSCRIPTEN__)
+#define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+#define glBindVertexArray glBindVertexArrayOES
+#define glGenVertexArrays glGenVertexArraysOES
+#define glDeleteVertexArrays glDeleteVertexArraysOES
+#define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
+#endif
+
+// Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have.
+#ifdef GL_POLYGON_MODE
+#define IMGUI_IMPL_HAS_POLYGON_MODE
+#endif
+
+// Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2)
+#define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
+#endif
+
+// Desktop GL 3.3+ has glBindSampler()
+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_3)
+#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
+#endif
+
+// Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
+#define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
+#endif
+
+// Desktop GL use extension detection
+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
+#define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
+#endif
+
+// OpenGL Data
+struct ImGui_ImplOpenGL3_Data
+{
+ GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
+ char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings.
+ GLuint FontTexture;
+ GLuint ShaderHandle;
+ GLint AttribLocationTex; // Uniforms location
+ GLint AttribLocationProjMtx;
+ GLuint AttribLocationVtxPos; // Vertex attributes location
+ GLuint AttribLocationVtxUV;
+ GLuint AttribLocationVtxColor;
+ unsigned int VboHandle, ElementsHandle;
+ bool HasClipOrigin;
+
+ ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Initialize our loader
+#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
+ if (imgl3wInit() != 0)
+ {
+ fprintf(stderr, "Failed to initialize OpenGL loader!\n");
+ return false;
+ }
+#endif
+
+ // Setup backend capabilities flags
+ ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_opengl3";
+
+ // Query for GL version (e.g. 320 for GL 3.2)
+#if !defined(IMGUI_IMPL_OPENGL_ES2)
+ GLint major = 0;
+ GLint minor = 0;
+ glGetIntegerv(GL_MAJOR_VERSION, &major);
+ glGetIntegerv(GL_MINOR_VERSION, &minor);
+ if (major == 0 && minor == 0)
+ {
+ // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
+ const char* gl_version = (const char*)glGetString(GL_VERSION);
+ sscanf(gl_version, "%d.%d", &major, &minor);
+ }
+ bd->GlVersion = (GLuint)(major * 100 + minor * 10);
+#else
+ bd->GlVersion = 200; // GLES 2
+#endif
+
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
+ if (bd->GlVersion >= 320)
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+#endif
+
+ // Store GLSL version string so we can refer to it later in case we recreate shaders.
+ // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
+ if (glsl_version == NULL)
+ {
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+ glsl_version = "#version 100";
+#elif defined(IMGUI_IMPL_OPENGL_ES3)
+ glsl_version = "#version 300 es";
+#elif defined(__APPLE__)
+ glsl_version = "#version 150";
+#else
+ glsl_version = "#version 130";
+#endif
+ }
+ IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
+ strcpy(bd->GlslVersionString, glsl_version);
+ strcat(bd->GlslVersionString, "\n");
+
+ // Make an arbitrary GL call (we don't actually need the result)
+ // IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
+ GLint current_texture;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
+
+ // Detect extensions we support
+ bd->HasClipOrigin = (bd->GlVersion >= 450);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
+ GLint num_extensions = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
+ for (GLint i = 0; i < num_extensions; i++)
+ {
+ const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
+ if (extension != NULL && strcmp(extension, "GL_ARB_clip_control") == 0)
+ bd->HasClipOrigin = true;
+ }
+#endif
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_Shutdown()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplOpenGL3_DestroyDeviceObjects();
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+void ImGui_ImplOpenGL3_NewFrame()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplOpenGL3_Init()?");
+
+ if (!bd->ShaderHandle)
+ ImGui_ImplOpenGL3_CreateDeviceObjects();
+}
+
+static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
+ glEnable(GL_BLEND);
+ glBlendEquation(GL_FUNC_ADD);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glEnable(GL_SCISSOR_TEST);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
+ if (bd->GlVersion >= 310)
+ glDisable(GL_PRIMITIVE_RESTART);
+#endif
+#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+#endif
+
+ // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
+#if defined(GL_CLIP_ORIGIN)
+ bool clip_origin_lower_left = true;
+ if (bd->HasClipOrigin)
+ {
+ GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
+ if (current_clip_origin == GL_UPPER_LEFT)
+ clip_origin_lower_left = false;
+ }
+#endif
+
+ // Setup viewport, orthographic projection matrix
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+#if defined(GL_CLIP_ORIGIN)
+ if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
+#endif
+ const float ortho_projection[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, -1.0f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
+ };
+ glUseProgram(bd->ShaderHandle);
+ glUniform1i(bd->AttribLocationTex, 0);
+ glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
+
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
+ if (bd->GlVersion >= 330)
+ glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
+#endif
+
+ (void)vertex_array_object;
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ glBindVertexArray(vertex_array_object);
+#endif
+
+ // Bind vertex/index buffers and setup attributes for ImDrawVert
+ glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle);
+ glEnableVertexAttribArray(bd->AttribLocationVtxPos);
+ glEnableVertexAttribArray(bd->AttribLocationVtxUV);
+ glEnableVertexAttribArray(bd->AttribLocationVtxColor);
+ glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));
+ glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));
+ glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));
+}
+
+// OpenGL3 Render function.
+// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
+// This is in order to be able to run within an OpenGL engine that doesn't do so.
+void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
+{
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
+ int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
+ if (fb_width <= 0 || fb_height <= 0)
+ return;
+
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Backup GL state
+ GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
+ glActiveTexture(GL_TEXTURE0);
+ GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
+ GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
+ GLuint last_sampler; if (bd->GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
+#endif
+ GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
+#endif
+#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
+ GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
+#endif
+ GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
+ GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
+ GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
+ GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
+ GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
+ GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
+ GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
+ GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
+ GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
+ GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
+ GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
+ GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
+ GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
+ GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
+#endif
+
+ // Setup desired GL state
+ // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
+ // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
+ GLuint vertex_array_object = 0;
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ glGenVertexArrays(1, &vertex_array_object);
+#endif
+ ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
+
+ // Render command lists
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+
+ // Upload vertex/index buffers
+ glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
+ glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y));
+
+ // Bind texture, Draw
+ glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
+ if (bd->GlVersion >= 320)
+ glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
+ else
+#endif
+ glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)));
+ }
+ }
+ }
+
+ // Destroy the temporary VAO
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ glDeleteVertexArrays(1, &vertex_array_object);
+#endif
+
+ // Restore modified GL state
+ glUseProgram(last_program);
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
+ if (bd->GlVersion >= 330)
+ glBindSampler(0, last_sampler);
+#endif
+ glActiveTexture(last_active_texture);
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ glBindVertexArray(last_vertex_array_object);
+#endif
+ glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
+ glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
+ glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
+ if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
+ if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
+ if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
+ if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
+ if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
+ if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
+#endif
+
+#ifdef IMGUI_IMPL_HAS_POLYGON_MODE
+ glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
+#endif
+ glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
+ glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
+ (void)bd; // Not all compilation paths use this
+}
+
+bool ImGui_ImplOpenGL3_CreateFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Build texture atlas
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
+
+ // Upload texture to graphics system
+ GLint last_texture;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+ glGenTextures(1, &bd->FontTexture);
+ glBindTexture(GL_TEXTURE_2D, bd->FontTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+#endif
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
+
+ // Restore state
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_DestroyFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ if (bd->FontTexture)
+ {
+ glDeleteTextures(1, &bd->FontTexture);
+ io.Fonts->SetTexID(0);
+ bd->FontTexture = 0;
+ }
+}
+
+// If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
+static bool CheckShader(GLuint handle, const char* desc)
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ GLint status = 0, log_length = 0;
+ glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
+ glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
+ if ((GLboolean)status == GL_FALSE)
+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString);
+ if (log_length > 1)
+ {
+ ImVector<char> buf;
+ buf.resize((int)(log_length + 1));
+ glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
+ fprintf(stderr, "%s\n", buf.begin());
+ }
+ return (GLboolean)status == GL_TRUE;
+}
+
+// If you get an error please report on GitHub. You may try different GL context version or GLSL version.
+static bool CheckProgram(GLuint handle, const char* desc)
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ GLint status = 0, log_length = 0;
+ glGetProgramiv(handle, GL_LINK_STATUS, &status);
+ glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
+ if ((GLboolean)status == GL_FALSE)
+ fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString);
+ if (log_length > 1)
+ {
+ ImVector<char> buf;
+ buf.resize((int)(log_length + 1));
+ glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
+ fprintf(stderr, "%s\n", buf.begin());
+ }
+ return (GLboolean)status == GL_TRUE;
+}
+
+bool ImGui_ImplOpenGL3_CreateDeviceObjects()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+
+ // Backup GL state
+ GLint last_texture, last_array_buffer;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ GLint last_vertex_array;
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
+#endif
+
+ // Parse GLSL version string
+ int glsl_version = 130;
+ sscanf(bd->GlslVersionString, "#version %d", &glsl_version);
+
+ const GLchar* vertex_shader_glsl_120 =
+ "uniform mat4 ProjMtx;\n"
+ "attribute vec2 Position;\n"
+ "attribute vec2 UV;\n"
+ "attribute vec4 Color;\n"
+ "varying vec2 Frag_UV;\n"
+ "varying vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_130 =
+ "uniform mat4 ProjMtx;\n"
+ "in vec2 Position;\n"
+ "in vec2 UV;\n"
+ "in vec4 Color;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_300_es =
+ "precision highp float;\n"
+ "layout (location = 0) in vec2 Position;\n"
+ "layout (location = 1) in vec2 UV;\n"
+ "layout (location = 2) in vec4 Color;\n"
+ "uniform mat4 ProjMtx;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* vertex_shader_glsl_410_core =
+ "layout (location = 0) in vec2 Position;\n"
+ "layout (location = 1) in vec2 UV;\n"
+ "layout (location = 2) in vec4 Color;\n"
+ "uniform mat4 ProjMtx;\n"
+ "out vec2 Frag_UV;\n"
+ "out vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Frag_UV = UV;\n"
+ " Frag_Color = Color;\n"
+ " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_120 =
+ "#ifdef GL_ES\n"
+ " precision mediump float;\n"
+ "#endif\n"
+ "uniform sampler2D Texture;\n"
+ "varying vec2 Frag_UV;\n"
+ "varying vec4 Frag_Color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_130 =
+ "uniform sampler2D Texture;\n"
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_300_es =
+ "precision mediump float;\n"
+ "uniform sampler2D Texture;\n"
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "layout (location = 0) out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ const GLchar* fragment_shader_glsl_410_core =
+ "in vec2 Frag_UV;\n"
+ "in vec4 Frag_Color;\n"
+ "uniform sampler2D Texture;\n"
+ "layout (location = 0) out vec4 Out_Color;\n"
+ "void main()\n"
+ "{\n"
+ " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
+ "}\n";
+
+ // Select shaders matching our GLSL versions
+ const GLchar* vertex_shader = NULL;
+ const GLchar* fragment_shader = NULL;
+ if (glsl_version < 130)
+ {
+ vertex_shader = vertex_shader_glsl_120;
+ fragment_shader = fragment_shader_glsl_120;
+ }
+ else if (glsl_version >= 410)
+ {
+ vertex_shader = vertex_shader_glsl_410_core;
+ fragment_shader = fragment_shader_glsl_410_core;
+ }
+ else if (glsl_version == 300)
+ {
+ vertex_shader = vertex_shader_glsl_300_es;
+ fragment_shader = fragment_shader_glsl_300_es;
+ }
+ else
+ {
+ vertex_shader = vertex_shader_glsl_130;
+ fragment_shader = fragment_shader_glsl_130;
+ }
+
+ // Create shaders
+ const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
+ GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vert_handle, 2, vertex_shader_with_version, NULL);
+ glCompileShader(vert_handle);
+ CheckShader(vert_handle, "vertex shader");
+
+ const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
+ GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(frag_handle, 2, fragment_shader_with_version, NULL);
+ glCompileShader(frag_handle);
+ CheckShader(frag_handle, "fragment shader");
+
+ // Link
+ bd->ShaderHandle = glCreateProgram();
+ glAttachShader(bd->ShaderHandle, vert_handle);
+ glAttachShader(bd->ShaderHandle, frag_handle);
+ glLinkProgram(bd->ShaderHandle);
+ CheckProgram(bd->ShaderHandle, "shader program");
+
+ glDetachShader(bd->ShaderHandle, vert_handle);
+ glDetachShader(bd->ShaderHandle, frag_handle);
+ glDeleteShader(vert_handle);
+ glDeleteShader(frag_handle);
+
+ bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture");
+ bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx");
+ bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position");
+ bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV");
+ bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color");
+
+ // Create buffers
+ glGenBuffers(1, &bd->VboHandle);
+ glGenBuffers(1, &bd->ElementsHandle);
+
+ ImGui_ImplOpenGL3_CreateFontsTexture();
+
+ // Restore modified GL state
+ glBindTexture(GL_TEXTURE_2D, last_texture);
+ glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
+#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
+ glBindVertexArray(last_vertex_array);
+#endif
+
+ return true;
+}
+
+void ImGui_ImplOpenGL3_DestroyDeviceObjects()
+{
+ ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
+ if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
+ if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
+ if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
+ ImGui_ImplOpenGL3_DestroyFontsTexture();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_opengl3.h b/Client/ThirdParty/imgui/backends/imgui_impl_opengl3.h
new file mode 100644
index 0000000..98c9aca
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_opengl3.h
@@ -0,0 +1,55 @@
+// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
+// - Desktop GL: 2.x 3.x 4.x
+// - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
+// [x] Renderer: Desktop GL only: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// About GLSL version:
+// The 'glsl_version' initialization parameter should be NULL (default) or a "#version XXX" string.
+// On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es"
+// Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp.
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+// Backend API
+IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
+
+// (Optional) Called by Init/NewFrame/Shutdown
+IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture();
+IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects();
+
+// Specific OpenGL ES versions
+//#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten
+//#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android
+
+// You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line.
+#if !defined(IMGUI_IMPL_OPENGL_ES2) \
+ && !defined(IMGUI_IMPL_OPENGL_ES3)
+
+// Try to detect GLES on matching platforms
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__))
+#define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es"
+#elif defined(__EMSCRIPTEN__)
+#define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100"
+#else
+// Otherwise imgui_impl_opengl3_loader.h will be used.
+#endif
+
+#endif
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_opengl3_loader.h b/Client/ThirdParty/imgui/backends/imgui_impl_opengl3_loader.h
new file mode 100644
index 0000000..9313ded
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_opengl3_loader.h
@@ -0,0 +1,752 @@
+//-----------------------------------------------------------------------------
+// About imgui_impl_opengl3_loader.h:
+//
+// We embed our own OpenGL loader to not require user to provide their own or to have to use ours,
+// which proved to be endless problems for users.
+// Our loader is custom-generated, based on gl3w but automatically filtered to only include
+// enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small.
+//
+// YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY.
+// THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE.
+//
+// Regenerate with:
+// python gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt
+//
+// More info:
+// https://github.com/dearimgui/gl3w_stripped
+// https://github.com/ocornut/imgui/issues/4445
+//-----------------------------------------------------------------------------
+
+/*
+ * This file was generated with gl3w_gen.py, part of imgl3w
+ * (hosted at https://github.com/dearimgui/gl3w_stripped)
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __gl3w_h_
+#define __gl3w_h_
+
+// Adapted from KHR/khrplatform.h to avoid including entire file.
+#ifndef __khrplatform_h_
+typedef float khronos_float_t;
+typedef signed char khronos_int8_t;
+typedef unsigned char khronos_uint8_t;
+typedef signed short int khronos_int16_t;
+typedef unsigned short int khronos_uint16_t;
+#ifdef _WIN64
+typedef signed long long int khronos_intptr_t;
+typedef signed long long int khronos_ssize_t;
+#else
+typedef signed long int khronos_intptr_t;
+typedef signed long int khronos_ssize_t;
+#endif
+
+#if defined(_MSC_VER) && !defined(__clang__)
+typedef signed __int64 khronos_int64_t;
+typedef unsigned __int64 khronos_uint64_t;
+#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
+#include <stdint.h>
+typedef int64_t khronos_int64_t;
+typedef uint64_t khronos_uint64_t;
+#else
+typedef signed long long khronos_int64_t;
+typedef unsigned long long khronos_uint64_t;
+#endif
+#endif // __khrplatform_h_
+
+#ifndef __gl_glcorearb_h_
+#define __gl_glcorearb_h_ 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+** Copyright 2013-2020 The Khronos Group Inc.
+** SPDX-License-Identifier: MIT
+**
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+** https://github.com/KhronosGroup/OpenGL-Registry
+*/
+#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+#endif
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+#ifndef APIENTRYP
+#define APIENTRYP APIENTRY *
+#endif
+#ifndef GLAPI
+#define GLAPI extern
+#endif
+/* glcorearb.h is for use with OpenGL core profile implementations.
+** It should should be placed in the same directory as gl.h and
+** included as <GL/glcorearb.h>.
+**
+** glcorearb.h includes only APIs in the latest OpenGL core profile
+** implementation together with APIs in newer ARB extensions which
+** can be supported by the core profile. It does not, and never will
+** include functionality removed from the core profile, such as
+** fixed-function vertex and fragment processing.
+**
+** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or
+** <GL/glext.h> in the same source file.
+*/
+/* Generated C header for:
+ * API: gl
+ * Profile: core
+ * Versions considered: .*
+ * Versions emitted: .*
+ * Default extensions included: glcore
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+#ifndef GL_VERSION_1_0
+typedef void GLvoid;
+typedef unsigned int GLenum;
+
+typedef khronos_float_t GLfloat;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned int GLbitfield;
+typedef double GLdouble;
+typedef unsigned int GLuint;
+typedef unsigned char GLboolean;
+typedef khronos_uint8_t GLubyte;
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_TRIANGLES 0x0004
+#define GL_ONE 1
+#define GL_SRC_ALPHA 0x0302
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_POLYGON_MODE 0x0B40
+#define GL_CULL_FACE 0x0B44
+#define GL_DEPTH_TEST 0x0B71
+#define GL_STENCIL_TEST 0x0B90
+#define GL_VIEWPORT 0x0BA2
+#define GL_BLEND 0x0BE2
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+#define GL_RGBA 0x1908
+#define GL_FILL 0x1B02
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_LINEAR 0x2601
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode);
+typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode);
+GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GLAPI void APIENTRY glClear (GLbitfield mask);
+GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GLAPI void APIENTRY glDisable (GLenum cap);
+GLAPI void APIENTRY glEnable (GLenum cap);
+GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param);
+GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GLAPI GLenum APIENTRY glGetError (void);
+GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GLAPI const GLubyte *APIENTRY glGetString (GLenum name);
+GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap);
+GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_VERSION_1_0 */
+#ifndef GL_VERSION_1_1
+typedef khronos_float_t GLclampf;
+typedef double GLclampd;
+#define GL_TEXTURE_BINDING_2D 0x8069
+typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture);
+GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+#endif
+#endif /* GL_VERSION_1_1 */
+#ifndef GL_VERSION_1_3
+#define GL_TEXTURE0 0x84C0
+#define GL_ACTIVE_TEXTURE 0x84E0
+typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glActiveTexture (GLenum texture);
+#endif
+#endif /* GL_VERSION_1_3 */
+#ifndef GL_VERSION_1_4
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_FUNC_ADD 0x8006
+typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GLAPI void APIENTRY glBlendEquation (GLenum mode);
+#endif
+#endif /* GL_VERSION_1_4 */
+#ifndef GL_VERSION_1_5
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_STREAM_DRAW 0x88E0
+typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+#endif
+#endif /* GL_VERSION_1_5 */
+#ifndef GL_VERSION_2_0
+typedef char GLchar;
+typedef khronos_int16_t GLshort;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint16_t GLushort;
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_UPPER_LEFT 0x8CA2
+typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glCompileShader (GLuint shader);
+GLAPI GLuint APIENTRY glCreateProgram (void);
+GLAPI GLuint APIENTRY glCreateShader (GLenum type);
+GLAPI void APIENTRY glDeleteProgram (GLuint program);
+GLAPI void APIENTRY glDeleteShader (GLuint shader);
+GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader);
+GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index);
+GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GLAPI void APIENTRY glLinkProgram (GLuint program);
+GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GLAPI void APIENTRY glUseProgram (GLuint program);
+GLAPI void APIENTRY glUniform1i (GLint location, GLint v0);
+GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+#endif
+#endif /* GL_VERSION_2_0 */
+#ifndef GL_VERSION_3_0
+typedef khronos_uint16_t GLhalf;
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MINOR_VERSION 0x821C
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index);
+GLAPI void APIENTRY glBindVertexArray (GLuint array);
+GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+#endif
+#endif /* GL_VERSION_3_0 */
+#ifndef GL_VERSION_3_1
+#define GL_VERSION_3_1 1
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#endif /* GL_VERSION_3_1 */
+#ifndef GL_VERSION_3_2
+#define GL_VERSION_3_2 1
+typedef struct __GLsync *GLsync;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_int64_t GLint64;
+typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+#endif
+#endif /* GL_VERSION_3_2 */
+#ifndef GL_VERSION_3_3
+#define GL_VERSION_3_3 1
+#define GL_SAMPLER_BINDING 0x8919
+typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+#ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+#endif
+#endif /* GL_VERSION_3_3 */
+#ifndef GL_VERSION_4_1
+typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data);
+#endif /* GL_VERSION_4_1 */
+#ifndef GL_VERSION_4_3
+typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#endif /* GL_VERSION_4_3 */
+#ifndef GL_VERSION_4_5
+#define GL_CLIP_ORIGIN 0x935C
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param);
+typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param);
+#endif /* GL_VERSION_4_5 */
+#ifndef GL_ARB_bindless_texture
+typedef khronos_uint64_t GLuint64EXT;
+#endif /* GL_ARB_bindless_texture */
+#ifndef GL_ARB_cl_event
+struct _cl_context;
+struct _cl_event;
+#endif /* GL_ARB_cl_event */
+#ifndef GL_ARB_clip_control
+#define GL_ARB_clip_control 1
+#endif /* GL_ARB_clip_control */
+#ifndef GL_ARB_debug_output
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#endif /* GL_ARB_debug_output */
+#ifndef GL_EXT_EGL_image_storage
+typedef void *GLeglImageOES;
+#endif /* GL_EXT_EGL_image_storage */
+#ifndef GL_EXT_direct_state_access
+typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params);
+typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params);
+typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param);
+typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param);
+#endif /* GL_EXT_direct_state_access */
+#ifndef GL_NV_draw_vulkan_image
+typedef void (APIENTRY *GLVULKANPROCNV)(void);
+#endif /* GL_NV_draw_vulkan_image */
+#ifndef GL_NV_gpu_shader5
+typedef khronos_int64_t GLint64EXT;
+#endif /* GL_NV_gpu_shader5 */
+#ifndef GL_NV_vertex_buffer_unified_memory
+typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result);
+#endif /* GL_NV_vertex_buffer_unified_memory */
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#ifndef GL3W_API
+#define GL3W_API
+#endif
+
+#ifndef __gl_h_
+#define __gl_h_
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GL3W_OK 0
+#define GL3W_ERROR_INIT -1
+#define GL3W_ERROR_LIBRARY_OPEN -2
+#define GL3W_ERROR_OPENGL_VERSION -3
+
+typedef void (*GL3WglProc)(void);
+typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
+
+/* gl3w api */
+GL3W_API int imgl3wInit(void);
+GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc);
+GL3W_API int imgl3wIsSupported(int major, int minor);
+GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
+
+/* gl3w internal state */
+union GL3WProcs {
+ GL3WglProc ptr[53];
+ struct {
+ PFNGLACTIVETEXTUREPROC ActiveTexture;
+ PFNGLATTACHSHADERPROC AttachShader;
+ PFNGLBINDBUFFERPROC BindBuffer;
+ PFNGLBINDSAMPLERPROC BindSampler;
+ PFNGLBINDTEXTUREPROC BindTexture;
+ PFNGLBINDVERTEXARRAYPROC BindVertexArray;
+ PFNGLBLENDEQUATIONPROC BlendEquation;
+ PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
+ PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
+ PFNGLBUFFERDATAPROC BufferData;
+ PFNGLCLEARPROC Clear;
+ PFNGLCLEARCOLORPROC ClearColor;
+ PFNGLCOMPILESHADERPROC CompileShader;
+ PFNGLCREATEPROGRAMPROC CreateProgram;
+ PFNGLCREATESHADERPROC CreateShader;
+ PFNGLDELETEBUFFERSPROC DeleteBuffers;
+ PFNGLDELETEPROGRAMPROC DeleteProgram;
+ PFNGLDELETESHADERPROC DeleteShader;
+ PFNGLDELETETEXTURESPROC DeleteTextures;
+ PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
+ PFNGLDETACHSHADERPROC DetachShader;
+ PFNGLDISABLEPROC Disable;
+ PFNGLDRAWELEMENTSPROC DrawElements;
+ PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex;
+ PFNGLENABLEPROC Enable;
+ PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray;
+ PFNGLGENBUFFERSPROC GenBuffers;
+ PFNGLGENTEXTURESPROC GenTextures;
+ PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
+ PFNGLGETATTRIBLOCATIONPROC GetAttribLocation;
+ PFNGLGETERRORPROC GetError;
+ PFNGLGETINTEGERVPROC GetIntegerv;
+ PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog;
+ PFNGLGETPROGRAMIVPROC GetProgramiv;
+ PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog;
+ PFNGLGETSHADERIVPROC GetShaderiv;
+ PFNGLGETSTRINGPROC GetString;
+ PFNGLGETSTRINGIPROC GetStringi;
+ PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation;
+ PFNGLISENABLEDPROC IsEnabled;
+ PFNGLLINKPROGRAMPROC LinkProgram;
+ PFNGLPIXELSTOREIPROC PixelStorei;
+ PFNGLPOLYGONMODEPROC PolygonMode;
+ PFNGLREADPIXELSPROC ReadPixels;
+ PFNGLSCISSORPROC Scissor;
+ PFNGLSHADERSOURCEPROC ShaderSource;
+ PFNGLTEXIMAGE2DPROC TexImage2D;
+ PFNGLTEXPARAMETERIPROC TexParameteri;
+ PFNGLUNIFORM1IPROC Uniform1i;
+ PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv;
+ PFNGLUSEPROGRAMPROC UseProgram;
+ PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer;
+ PFNGLVIEWPORTPROC Viewport;
+ } gl;
+};
+
+GL3W_API extern union GL3WProcs imgl3wProcs;
+
+/* OpenGL functions */
+#define glActiveTexture imgl3wProcs.gl.ActiveTexture
+#define glAttachShader imgl3wProcs.gl.AttachShader
+#define glBindBuffer imgl3wProcs.gl.BindBuffer
+#define glBindSampler imgl3wProcs.gl.BindSampler
+#define glBindTexture imgl3wProcs.gl.BindTexture
+#define glBindVertexArray imgl3wProcs.gl.BindVertexArray
+#define glBlendEquation imgl3wProcs.gl.BlendEquation
+#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
+#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
+#define glBufferData imgl3wProcs.gl.BufferData
+#define glClear imgl3wProcs.gl.Clear
+#define glClearColor imgl3wProcs.gl.ClearColor
+#define glCompileShader imgl3wProcs.gl.CompileShader
+#define glCreateProgram imgl3wProcs.gl.CreateProgram
+#define glCreateShader imgl3wProcs.gl.CreateShader
+#define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers
+#define glDeleteProgram imgl3wProcs.gl.DeleteProgram
+#define glDeleteShader imgl3wProcs.gl.DeleteShader
+#define glDeleteTextures imgl3wProcs.gl.DeleteTextures
+#define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays
+#define glDetachShader imgl3wProcs.gl.DetachShader
+#define glDisable imgl3wProcs.gl.Disable
+#define glDrawElements imgl3wProcs.gl.DrawElements
+#define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex
+#define glEnable imgl3wProcs.gl.Enable
+#define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray
+#define glGenBuffers imgl3wProcs.gl.GenBuffers
+#define glGenTextures imgl3wProcs.gl.GenTextures
+#define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays
+#define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation
+#define glGetError imgl3wProcs.gl.GetError
+#define glGetIntegerv imgl3wProcs.gl.GetIntegerv
+#define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog
+#define glGetProgramiv imgl3wProcs.gl.GetProgramiv
+#define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog
+#define glGetShaderiv imgl3wProcs.gl.GetShaderiv
+#define glGetString imgl3wProcs.gl.GetString
+#define glGetStringi imgl3wProcs.gl.GetStringi
+#define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation
+#define glIsEnabled imgl3wProcs.gl.IsEnabled
+#define glLinkProgram imgl3wProcs.gl.LinkProgram
+#define glPixelStorei imgl3wProcs.gl.PixelStorei
+#define glPolygonMode imgl3wProcs.gl.PolygonMode
+#define glReadPixels imgl3wProcs.gl.ReadPixels
+#define glScissor imgl3wProcs.gl.Scissor
+#define glShaderSource imgl3wProcs.gl.ShaderSource
+#define glTexImage2D imgl3wProcs.gl.TexImage2D
+#define glTexParameteri imgl3wProcs.gl.TexParameteri
+#define glUniform1i imgl3wProcs.gl.Uniform1i
+#define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv
+#define glUseProgram imgl3wProcs.gl.UseProgram
+#define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer
+#define glViewport imgl3wProcs.gl.Viewport
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#ifdef IMGL3W_IMPL
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#if defined(_WIN32)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
+
+static HMODULE libgl;
+typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
+static GL3WglGetProcAddr wgl_get_proc_address;
+
+static int open_libgl(void)
+{
+ libgl = LoadLibraryA("opengl32.dll");
+ if (!libgl)
+ return GL3W_ERROR_LIBRARY_OPEN;
+ wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
+ return GL3W_OK;
+}
+
+static void close_libgl(void) { FreeLibrary(libgl); }
+static GL3WglProc get_proc(const char *proc)
+{
+ GL3WglProc res;
+ res = (GL3WglProc)wgl_get_proc_address(proc);
+ if (!res)
+ res = (GL3WglProc)GetProcAddress(libgl, proc);
+ return res;
+}
+#elif defined(__APPLE__)
+#include <dlfcn.h>
+
+static void *libgl;
+static int open_libgl(void)
+{
+ libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
+ if (!libgl)
+ return GL3W_ERROR_LIBRARY_OPEN;
+ return GL3W_OK;
+}
+
+static void close_libgl(void) { dlclose(libgl); }
+
+static GL3WglProc get_proc(const char *proc)
+{
+ GL3WglProc res;
+ *(void **)(&res) = dlsym(libgl, proc);
+ return res;
+}
+#else
+#include <dlfcn.h>
+
+static void *libgl;
+static GL3WglProc (*glx_get_proc_address)(const GLubyte *);
+
+static int open_libgl(void)
+{
+ libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
+ if (!libgl)
+ return GL3W_ERROR_LIBRARY_OPEN;
+ *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
+ return GL3W_OK;
+}
+
+static void close_libgl(void) { dlclose(libgl); }
+
+static GL3WglProc get_proc(const char *proc)
+{
+ GL3WglProc res;
+ res = glx_get_proc_address((const GLubyte *)proc);
+ if (!res)
+ *(void **)(&res) = dlsym(libgl, proc);
+ return res;
+}
+#endif
+
+static struct { int major, minor; } version;
+
+static int parse_version(void)
+{
+ if (!glGetIntegerv)
+ return GL3W_ERROR_INIT;
+ glGetIntegerv(GL_MAJOR_VERSION, &version.major);
+ glGetIntegerv(GL_MINOR_VERSION, &version.minor);
+ if (version.major < 3)
+ return GL3W_ERROR_OPENGL_VERSION;
+ return GL3W_OK;
+}
+
+static void load_procs(GL3WGetProcAddressProc proc);
+
+int imgl3wInit(void)
+{
+ int res = open_libgl();
+ if (res)
+ return res;
+ atexit(close_libgl);
+ return imgl3wInit2(get_proc);
+}
+
+int imgl3wInit2(GL3WGetProcAddressProc proc)
+{
+ load_procs(proc);
+ return parse_version();
+}
+
+int imgl3wIsSupported(int major, int minor)
+{
+ if (major < 3)
+ return 0;
+ if (version.major == major)
+ return version.minor >= minor;
+ return version.major >= major;
+}
+
+GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); }
+
+static const char *proc_names[] = {
+ "glActiveTexture",
+ "glAttachShader",
+ "glBindBuffer",
+ "glBindSampler",
+ "glBindTexture",
+ "glBindVertexArray",
+ "glBlendEquation",
+ "glBlendEquationSeparate",
+ "glBlendFuncSeparate",
+ "glBufferData",
+ "glClear",
+ "glClearColor",
+ "glCompileShader",
+ "glCreateProgram",
+ "glCreateShader",
+ "glDeleteBuffers",
+ "glDeleteProgram",
+ "glDeleteShader",
+ "glDeleteTextures",
+ "glDeleteVertexArrays",
+ "glDetachShader",
+ "glDisable",
+ "glDrawElements",
+ "glDrawElementsBaseVertex",
+ "glEnable",
+ "glEnableVertexAttribArray",
+ "glGenBuffers",
+ "glGenTextures",
+ "glGenVertexArrays",
+ "glGetAttribLocation",
+ "glGetError",
+ "glGetIntegerv",
+ "glGetProgramInfoLog",
+ "glGetProgramiv",
+ "glGetShaderInfoLog",
+ "glGetShaderiv",
+ "glGetString",
+ "glGetStringi",
+ "glGetUniformLocation",
+ "glIsEnabled",
+ "glLinkProgram",
+ "glPixelStorei",
+ "glPolygonMode",
+ "glReadPixels",
+ "glScissor",
+ "glShaderSource",
+ "glTexImage2D",
+ "glTexParameteri",
+ "glUniform1i",
+ "glUniformMatrix4fv",
+ "glUseProgram",
+ "glVertexAttribPointer",
+ "glViewport",
+};
+
+GL3W_API union GL3WProcs imgl3wProcs;
+
+static void load_procs(GL3WGetProcAddressProc proc)
+{
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(proc_names); i++)
+ imgl3wProcs.ptr[i] = proc(proc_names[i]);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_osx.h b/Client/ThirdParty/imgui/backends/imgui_impl_osx.h
new file mode 100644
index 0000000..e4c1d04
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_osx.h
@@ -0,0 +1,24 @@
+// dear imgui: Platform Backend for OSX / Cocoa
+// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..)
+// [ALPHA] Early backend, not well tested. If you want a portable application, prefer using the GLFW or SDL platform Backends on Mac.
+
+// Implemented features:
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
+// Issues:
+// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h" // IMGUI_IMPL_API
+
+@class NSEvent;
+@class NSView;
+
+IMGUI_IMPL_API bool ImGui_ImplOSX_Init();
+IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
+IMGUI_IMPL_API bool ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view);
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_osx.mm b/Client/ThirdParty/imgui/backends/imgui_impl_osx.mm
new file mode 100644
index 0000000..97555e6
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_osx.mm
@@ -0,0 +1,387 @@
+// dear imgui: Platform Backend for OSX / Cocoa
+// This needs to be used along with a Renderer (e.g. OpenGL2, OpenGL3, Vulkan, Metal..)
+// [ALPHA] Early backend, not well tested. If you want a portable application, prefer using the GLFW or SDL platform Backends on Mac.
+
+// Implemented features:
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
+// Issues:
+// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_osx.h"
+#import <Cocoa/Cocoa.h>
+#include <mach/mach_time.h>
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards.
+// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.
+// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key.
+// 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state when CMD-tabbing into different application.
+// 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down.
+// 2020-10-28: Inputs: Added a fix for handling keypad-enter key.
+// 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap".
+// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
+// 2019-10-11: Inputs: Fix using Backspace key.
+// 2019-07-21: Re-added clipboard handlers as they are not enabled by default in core imgui.cpp (reverted 2019-05-18 change).
+// 2019-05-28: Inputs: Added mouse cursor shape and visibility support.
+// 2019-05-18: Misc: Removed clipboard handlers as they are now supported by core imgui.cpp.
+// 2019-05-11: Inputs: Don't filter character values before calling AddInputCharacter() apart from 0xF700..0xFFFF range.
+// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
+// 2018-07-07: Initial version.
+
+@class ImFocusObserver;
+
+// Data
+static double g_HostClockPeriod = 0.0;
+static double g_Time = 0.0;
+static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
+static bool g_MouseCursorHidden = false;
+static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
+static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
+static ImFocusObserver* g_FocusObserver = NULL;
+
+// Undocumented methods for creating cursors.
+@interface NSCursor()
++ (id)_windowResizeNorthWestSouthEastCursor;
++ (id)_windowResizeNorthEastSouthWestCursor;
++ (id)_windowResizeNorthSouthCursor;
++ (id)_windowResizeEastWestCursor;
+@end
+
+static void InitHostClockPeriod()
+{
+ struct mach_timebase_info info;
+ mach_timebase_info(&info);
+ g_HostClockPeriod = 1e-9 * ((double)info.denom / (double)info.numer); // Period is the reciprocal of frequency.
+}
+
+static double GetMachAbsoluteTimeInSeconds()
+{
+ return (double)mach_absolute_time() * g_HostClockPeriod;
+}
+
+static void resetKeys()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ memset(io.KeysDown, 0, sizeof(io.KeysDown));
+ io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
+}
+
+@interface ImFocusObserver : NSObject
+
+- (void)onApplicationBecomeActive:(NSNotification*)aNotification;
+- (void)onApplicationBecomeInactive:(NSNotification*)aNotification;
+
+@end
+
+@implementation ImFocusObserver
+
+- (void)onApplicationBecomeActive:(NSNotification*)aNotification
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.AddFocusEvent(true);
+}
+
+- (void)onApplicationBecomeInactive:(NSNotification*)aNotification
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.AddFocusEvent(false);
+
+ // Unfocused applications do not receive input events, therefore we must manually
+ // release any pressed keys when application loses focus, otherwise they would remain
+ // stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832
+ resetKeys();
+}
+
+@end
+
+// Functions
+bool ImGui_ImplOSX_Init()
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup backend capabilities flags
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ //io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+ //io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
+ //io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can set io.MouseHoveredViewport correctly (optional, not easy)
+ io.BackendPlatformName = "imgui_impl_osx";
+
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array.
+ const int offset_for_function_keys = 256 - 0xF700;
+ io.KeyMap[ImGuiKey_Tab] = '\t';
+ io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys;
+ io.KeyMap[ImGuiKey_Backspace] = 127;
+ io.KeyMap[ImGuiKey_Space] = 32;
+ io.KeyMap[ImGuiKey_Enter] = 13;
+ io.KeyMap[ImGuiKey_Escape] = 27;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = 3;
+ io.KeyMap[ImGuiKey_A] = 'A';
+ io.KeyMap[ImGuiKey_C] = 'C';
+ io.KeyMap[ImGuiKey_V] = 'V';
+ io.KeyMap[ImGuiKey_X] = 'X';
+ io.KeyMap[ImGuiKey_Y] = 'Y';
+ io.KeyMap[ImGuiKey_Z] = 'Z';
+
+ // Load cursors. Some of them are undocumented.
+ g_MouseCursorHidden = false;
+ g_MouseCursors[ImGuiMouseCursor_Arrow] = [NSCursor arrowCursor];
+ g_MouseCursors[ImGuiMouseCursor_TextInput] = [NSCursor IBeamCursor];
+ g_MouseCursors[ImGuiMouseCursor_ResizeAll] = [NSCursor closedHandCursor];
+ g_MouseCursors[ImGuiMouseCursor_Hand] = [NSCursor pointingHandCursor];
+ g_MouseCursors[ImGuiMouseCursor_NotAllowed] = [NSCursor operationNotAllowedCursor];
+ g_MouseCursors[ImGuiMouseCursor_ResizeNS] = [NSCursor respondsToSelector:@selector(_windowResizeNorthSouthCursor)] ? [NSCursor _windowResizeNorthSouthCursor] : [NSCursor resizeUpDownCursor];
+ g_MouseCursors[ImGuiMouseCursor_ResizeEW] = [NSCursor respondsToSelector:@selector(_windowResizeEastWestCursor)] ? [NSCursor _windowResizeEastWestCursor] : [NSCursor resizeLeftRightCursor];
+ g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = [NSCursor respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)] ? [NSCursor _windowResizeNorthEastSouthWestCursor] : [NSCursor closedHandCursor];
+ g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = [NSCursor respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)] ? [NSCursor _windowResizeNorthWestSouthEastCursor] : [NSCursor closedHandCursor];
+
+ // Note that imgui.cpp also include default OSX clipboard handlers which can be enabled
+ // by adding '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h and adding '-framework ApplicationServices' to your linker command-line.
+ // Since we are already in ObjC land here, it is easy for us to add a clipboard handler using the NSPasteboard api.
+ io.SetClipboardTextFn = [](void*, const char* str) -> void
+ {
+ NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+ [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
+ [pasteboard setString:[NSString stringWithUTF8String:str] forType:NSPasteboardTypeString];
+ };
+
+ io.GetClipboardTextFn = [](void*) -> const char*
+ {
+ NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+ NSString* available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:NSPasteboardTypeString]];
+ if (![available isEqualToString:NSPasteboardTypeString])
+ return NULL;
+
+ NSString* string = [pasteboard stringForType:NSPasteboardTypeString];
+ if (string == nil)
+ return NULL;
+
+ const char* string_c = (const char*)[string UTF8String];
+ size_t string_len = strlen(string_c);
+ static ImVector<char> s_clipboard;
+ s_clipboard.resize((int)string_len + 1);
+ strcpy(s_clipboard.Data, string_c);
+ return s_clipboard.Data;
+ };
+
+ g_FocusObserver = [[ImFocusObserver alloc] init];
+ [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
+ selector:@selector(onApplicationBecomeActive:)
+ name:NSApplicationDidBecomeActiveNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
+ selector:@selector(onApplicationBecomeInactive:)
+ name:NSApplicationDidResignActiveNotification
+ object:nil];
+
+ return true;
+}
+
+void ImGui_ImplOSX_Shutdown()
+{
+ g_FocusObserver = NULL;
+}
+
+static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
+{
+ // Update buttons
+ ImGuiIO& io = ImGui::GetIO();
+ for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
+ {
+ // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
+ io.MouseDown[i] = g_MouseJustPressed[i] || g_MouseDown[i];
+ g_MouseJustPressed[i] = false;
+ }
+
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return;
+
+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
+ if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
+ {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ if (!g_MouseCursorHidden)
+ {
+ g_MouseCursorHidden = true;
+ [NSCursor hide];
+ }
+ }
+ else
+ {
+ // Show OS mouse cursor
+ [g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set];
+ if (g_MouseCursorHidden)
+ {
+ g_MouseCursorHidden = false;
+ [NSCursor unhide];
+ }
+ }
+}
+
+void ImGui_ImplOSX_NewFrame(NSView* view)
+{
+ // Setup display size
+ ImGuiIO& io = ImGui::GetIO();
+ if (view)
+ {
+ const float dpi = (float)[view.window backingScaleFactor];
+ io.DisplaySize = ImVec2((float)view.bounds.size.width, (float)view.bounds.size.height);
+ io.DisplayFramebufferScale = ImVec2(dpi, dpi);
+ }
+
+ // Setup time step
+ if (g_Time == 0.0)
+ {
+ InitHostClockPeriod();
+ g_Time = GetMachAbsoluteTimeInSeconds();
+ }
+ double current_time = GetMachAbsoluteTimeInSeconds();
+ io.DeltaTime = (float)(current_time - g_Time);
+ g_Time = current_time;
+
+ ImGui_ImplOSX_UpdateMouseCursorAndButtons();
+}
+
+static int mapCharacterToKey(int c)
+{
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + 'A';
+ if (c == 25) // SHIFT+TAB -> TAB
+ return 9;
+ if (c >= 0 && c < 256)
+ return c;
+ if (c >= 0xF700 && c < 0xF700 + 256)
+ return c - 0xF700 + 256;
+ return -1;
+}
+
+bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
+{
+ ImGuiIO& io = ImGui::GetIO();
+
+ if (event.type == NSEventTypeLeftMouseDown || event.type == NSEventTypeRightMouseDown || event.type == NSEventTypeOtherMouseDown)
+ {
+ int button = (int)[event buttonNumber];
+ if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown))
+ g_MouseDown[button] = g_MouseJustPressed[button] = true;
+ return io.WantCaptureMouse;
+ }
+
+ if (event.type == NSEventTypeLeftMouseUp || event.type == NSEventTypeRightMouseUp || event.type == NSEventTypeOtherMouseUp)
+ {
+ int button = (int)[event buttonNumber];
+ if (button >= 0 && button < IM_ARRAYSIZE(g_MouseDown))
+ g_MouseDown[button] = false;
+ return io.WantCaptureMouse;
+ }
+
+ if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventTypeOtherMouseDragged)
+ {
+ NSPoint mousePoint = event.locationInWindow;
+ mousePoint = [view convertPoint:mousePoint fromView:nil];
+ mousePoint = NSMakePoint(mousePoint.x, view.bounds.size.height - mousePoint.y);
+ io.MousePos = ImVec2((float)mousePoint.x, (float)mousePoint.y);
+ }
+
+ if (event.type == NSEventTypeScrollWheel)
+ {
+ double wheel_dx = 0.0;
+ double wheel_dy = 0.0;
+
+ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
+ {
+ wheel_dx = [event scrollingDeltaX];
+ wheel_dy = [event scrollingDeltaY];
+ if ([event hasPreciseScrollingDeltas])
+ {
+ wheel_dx *= 0.1;
+ wheel_dy *= 0.1;
+ }
+ }
+ else
+ #endif // MAC_OS_X_VERSION_MAX_ALLOWED
+ {
+ wheel_dx = [event deltaX];
+ wheel_dy = [event deltaY];
+ }
+
+ if (fabs(wheel_dx) > 0.0)
+ io.MouseWheelH += (float)wheel_dx * 0.1f;
+ if (fabs(wheel_dy) > 0.0)
+ io.MouseWheel += (float)wheel_dy * 0.1f;
+ return io.WantCaptureMouse;
+ }
+
+ // FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm.
+ if (event.type == NSEventTypeKeyDown)
+ {
+ NSString* str = [event characters];
+ NSUInteger len = [str length];
+ for (NSUInteger i = 0; i < len; i++)
+ {
+ int c = [str characterAtIndex:i];
+ if (!io.KeySuper && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)
+ io.AddInputCharacter((unsigned int)c);
+
+ // We must reset in case we're pressing a sequence of special keys while keeping the command pressed
+ int key = mapCharacterToKey(c);
+ if (key != -1 && key < 256 && !io.KeySuper)
+ resetKeys();
+ if (key != -1)
+ io.KeysDown[key] = true;
+ }
+ return io.WantCaptureKeyboard;
+ }
+
+ if (event.type == NSEventTypeKeyUp)
+ {
+ NSString* str = [event characters];
+ NSUInteger len = [str length];
+ for (NSUInteger i = 0; i < len; i++)
+ {
+ int c = [str characterAtIndex:i];
+ int key = mapCharacterToKey(c);
+ if (key != -1)
+ io.KeysDown[key] = false;
+ }
+ return io.WantCaptureKeyboard;
+ }
+
+ if (event.type == NSEventTypeFlagsChanged)
+ {
+ unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
+
+ bool oldKeyCtrl = io.KeyCtrl;
+ bool oldKeyShift = io.KeyShift;
+ bool oldKeyAlt = io.KeyAlt;
+ bool oldKeySuper = io.KeySuper;
+ io.KeyCtrl = flags & NSEventModifierFlagControl;
+ io.KeyShift = flags & NSEventModifierFlagShift;
+ io.KeyAlt = flags & NSEventModifierFlagOption;
+ io.KeySuper = flags & NSEventModifierFlagCommand;
+
+ // We must reset them as we will not receive any keyUp event if they where pressed with a modifier
+ if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper))
+ resetKeys();
+ return io.WantCaptureKeyboard;
+ }
+
+ return false;
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_sdl.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_sdl.cpp
new file mode 100644
index 0000000..b725e0a
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_sdl.cpp
@@ -0,0 +1,449 @@
+// dear imgui: Platform Backend for SDL2
+// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
+// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
+// (Prefer SDL 2.0.5+ for full feature support.)
+
+// Implemented features:
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Platform: Clipboard support.
+// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
+// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// Missing features:
+// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-17: Calling io.AddFocusEvent() on SDL_WINDOWEVENT_FOCUS_GAINED/SDL_WINDOWEVENT_FOCUS_LOST.
+// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using SDL_GetMouseFocus() + SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, requires SDL 2.0.5+)
+// 2021-06-29: *BREAKING CHANGE* Removed 'SDL_Window* window' parameter to ImGui_ImplSDL2_NewFrame() which was unnecessary.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
+// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
+// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
+// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
+// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
+// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
+// 2019-04-23: Inputs: Added support for SDL_GameController (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
+// 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized.
+// 2018-12-21: Inputs: Workaround for Android/iOS which don't seem to handle focus related calls.
+// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
+// 2018-11-14: Changed the signature of ImGui_ImplSDL2_ProcessEvent() to take a 'const SDL_Event*'.
+// 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls.
+// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
+// 2018-06-08: Misc: Extracted imgui_impl_sdl.cpp/.h away from the old combined SDL2+OpenGL/Vulkan examples.
+// 2018-06-08: Misc: ImGui_ImplSDL2_InitForOpenGL() now takes a SDL_GLContext parameter.
+// 2018-05-09: Misc: Fixed clipboard paste memory leak (we didn't call SDL_FreeMemory on the data returned by SDL_GetClipboardText).
+// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag.
+// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS).
+// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes.
+// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
+// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS.
+// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert.
+// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1).
+// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers.
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+
+// SDL
+#include <SDL.h>
+#include <SDL_syswm.h>
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
+#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
+#else
+#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
+#endif
+#define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
+#define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
+
+// SDL Data
+struct ImGui_ImplSDL2_Data
+{
+ SDL_Window* Window;
+ Uint64 Time;
+ bool MousePressed[3];
+ SDL_Cursor* MouseCursors[ImGuiMouseCursor_COUNT];
+ char* ClipboardTextData;
+ bool MouseCanUseGlobalState;
+
+ ImGui_ImplSDL2_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+static ImGui_ImplSDL2_Data* ImGui_ImplSDL2_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplSDL2_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
+}
+
+// Functions
+static const char* ImGui_ImplSDL2_GetClipboardText(void*)
+{
+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+ if (bd->ClipboardTextData)
+ SDL_free(bd->ClipboardTextData);
+ bd->ClipboardTextData = SDL_GetClipboardText();
+ return bd->ClipboardTextData;
+}
+
+static void ImGui_ImplSDL2_SetClipboardText(void*, const char* text)
+{
+ SDL_SetClipboardText(text);
+}
+
+// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+// If you have multiple SDL events and some of them are not meant to be used by dear imgui, you may need to filter events based on their windowID field.
+bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+
+ switch (event->type)
+ {
+ case SDL_MOUSEWHEEL:
+ {
+ if (event->wheel.x > 0) io.MouseWheelH += 1;
+ if (event->wheel.x < 0) io.MouseWheelH -= 1;
+ if (event->wheel.y > 0) io.MouseWheel += 1;
+ if (event->wheel.y < 0) io.MouseWheel -= 1;
+ return true;
+ }
+ case SDL_MOUSEBUTTONDOWN:
+ {
+ if (event->button.button == SDL_BUTTON_LEFT) { bd->MousePressed[0] = true; }
+ if (event->button.button == SDL_BUTTON_RIGHT) { bd->MousePressed[1] = true; }
+ if (event->button.button == SDL_BUTTON_MIDDLE) { bd->MousePressed[2] = true; }
+ return true;
+ }
+ case SDL_TEXTINPUT:
+ {
+ io.AddInputCharactersUTF8(event->text.text);
+ return true;
+ }
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ {
+ int key = event->key.keysym.scancode;
+ IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown));
+ io.KeysDown[key] = (event->type == SDL_KEYDOWN);
+ io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0);
+ io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0);
+ io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0);
+#ifdef _WIN32
+ io.KeySuper = false;
+#else
+ io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0);
+#endif
+ return true;
+ }
+ case SDL_WINDOWEVENT:
+ {
+ if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
+ io.AddFocusEvent(true);
+ else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
+ io.AddFocusEvent(false);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool ImGui_ImplSDL2_Init(SDL_Window* window)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
+
+ // Check and store if we are on a SDL backend that supports global mouse position
+ // ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
+ bool mouse_can_use_global_state = false;
+#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
+ const char* sdl_backend = SDL_GetCurrentVideoDriver();
+ const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
+ for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
+ if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
+ mouse_can_use_global_state = true;
+#endif
+
+ // Setup backend capabilities flags
+ ImGui_ImplSDL2_Data* bd = IM_NEW(ImGui_ImplSDL2_Data)();
+ io.BackendPlatformUserData = (void*)bd;
+ io.BackendPlatformName = "imgui_impl_sdl";
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+
+ bd->Window = window;
+ bd->MouseCanUseGlobalState = mouse_can_use_global_state;
+
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
+ io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB;
+ io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = SDL_SCANCODE_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = SDL_SCANCODE_PAGEUP;
+ io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN;
+ io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME;
+ io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END;
+ io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE;
+ io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE;
+ io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN;
+ io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = SDL_SCANCODE_KP_ENTER;
+ io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A;
+ io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C;
+ io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V;
+ io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X;
+ io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y;
+ io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z;
+
+ io.SetClipboardTextFn = ImGui_ImplSDL2_SetClipboardText;
+ io.GetClipboardTextFn = ImGui_ImplSDL2_GetClipboardText;
+ io.ClipboardUserData = NULL;
+
+ // Load mouse cursors
+ bd->MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
+ bd->MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
+ bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
+ bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
+ bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
+
+#ifdef _WIN32
+ SDL_SysWMinfo info;
+ SDL_VERSION(&info.version);
+ if (SDL_GetWindowWMInfo(window, &info))
+ io.ImeWindowHandle = info.info.win.window;
+#else
+ (void)window;
+#endif
+
+ // Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
+ // Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
+ // (This is unfortunately a global SDL setting, so enabling it might have a side-effect on your application.
+ // It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
+ // you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED)
+#if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
+ SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
+#endif
+
+ return true;
+}
+
+bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context)
+{
+ IM_UNUSED(sdl_gl_context); // Viewport branch will need this.
+ return ImGui_ImplSDL2_Init(window);
+}
+
+bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window)
+{
+#if !SDL_HAS_VULKAN
+ IM_ASSERT(0 && "Unsupported");
+#endif
+ return ImGui_ImplSDL2_Init(window);
+}
+
+bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window)
+{
+#if !defined(_WIN32)
+ IM_ASSERT(0 && "Unsupported");
+#endif
+ return ImGui_ImplSDL2_Init(window);
+}
+
+bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window)
+{
+ return ImGui_ImplSDL2_Init(window);
+}
+
+bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window)
+{
+ return ImGui_ImplSDL2_Init(window);
+}
+
+void ImGui_ImplSDL2_Shutdown()
+{
+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+ IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ if (bd->ClipboardTextData)
+ SDL_free(bd->ClipboardTextData);
+ for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++)
+ SDL_FreeCursor(bd->MouseCursors[cursor_n]);
+
+ io.BackendPlatformName = NULL;
+ io.BackendPlatformUserData = NULL;
+ IM_DELETE(bd);
+}
+
+static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
+{
+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImVec2 mouse_pos_prev = io.MousePos;
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+
+ // Update mouse buttons
+ int mouse_x_local, mouse_y_local;
+ Uint32 mouse_buttons = SDL_GetMouseState(&mouse_x_local, &mouse_y_local);
+ io.MouseDown[0] = bd->MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
+ io.MouseDown[1] = bd->MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0;
+ io.MouseDown[2] = bd->MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0;
+ bd->MousePressed[0] = bd->MousePressed[1] = bd->MousePressed[2] = false;
+
+ // Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
+#if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
+ SDL_Window* focused_window = SDL_GetKeyboardFocus();
+ SDL_Window* hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus() : NULL; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.
+ SDL_Window* mouse_window = NULL;
+ if (hovered_window && bd->Window == hovered_window)
+ mouse_window = hovered_window;
+ else if (focused_window && bd->Window == focused_window)
+ mouse_window = focused_window;
+
+ // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
+ SDL_CaptureMouse(ImGui::IsAnyMouseDown() ? SDL_TRUE : SDL_FALSE);
+#else
+ // SDL 2.0.3 and non-windowed systems: single-viewport only
+ SDL_Window* mouse_window = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) ? bd->Window : NULL;
+#endif
+
+ if (mouse_window == NULL)
+ return;
+
+ // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+ if (io.WantSetMousePos)
+ SDL_WarpMouseInWindow(bd->Window, (int)mouse_pos_prev.x, (int)mouse_pos_prev.y);
+
+ // Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)
+ if (bd->MouseCanUseGlobalState)
+ {
+ // Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
+ // Unlike local position obtained earlier this will be valid when straying out of bounds.
+ int mouse_x_global, mouse_y_global;
+ SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
+ int window_x, window_y;
+ SDL_GetWindowPosition(mouse_window, &window_x, &window_y);
+ io.MousePos = ImVec2((float)(mouse_x_global - window_x), (float)(mouse_y_global - window_y));
+ }
+ else
+ {
+ io.MousePos = ImVec2((float)mouse_x_local, (float)mouse_y_local);
+ }
+}
+
+static void ImGui_ImplSDL2_UpdateMouseCursor()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return;
+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+
+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
+ if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None)
+ {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ SDL_ShowCursor(SDL_FALSE);
+ }
+ else
+ {
+ // Show OS mouse cursor
+ SDL_SetCursor(bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]);
+ SDL_ShowCursor(SDL_TRUE);
+ }
+}
+
+static void ImGui_ImplSDL2_UpdateGamepads()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ memset(io.NavInputs, 0, sizeof(io.NavInputs));
+ if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
+ return;
+
+ // Get gamepad
+ SDL_GameController* game_controller = SDL_GameControllerOpen(0);
+ if (!game_controller)
+ {
+ io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
+ return;
+ }
+
+ // Update gamepad inputs
+ #define MAP_BUTTON(NAV_NO, BUTTON_NO) { io.NavInputs[NAV_NO] = (SDL_GameControllerGetButton(game_controller, BUTTON_NO) != 0) ? 1.0f : 0.0f; }
+ #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float vn = (float)(SDL_GameControllerGetAxis(game_controller, AXIS_NO) - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
+ const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
+ MAP_BUTTON(ImGuiNavInput_Activate, SDL_CONTROLLER_BUTTON_A); // Cross / A
+ MAP_BUTTON(ImGuiNavInput_Cancel, SDL_CONTROLLER_BUTTON_B); // Circle / B
+ MAP_BUTTON(ImGuiNavInput_Menu, SDL_CONTROLLER_BUTTON_X); // Square / X
+ MAP_BUTTON(ImGuiNavInput_Input, SDL_CONTROLLER_BUTTON_Y); // Triangle / Y
+ MAP_BUTTON(ImGuiNavInput_DpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT); // D-Pad Left
+ MAP_BUTTON(ImGuiNavInput_DpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); // D-Pad Right
+ MAP_BUTTON(ImGuiNavInput_DpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP); // D-Pad Up
+ MAP_BUTTON(ImGuiNavInput_DpadDown, SDL_CONTROLLER_BUTTON_DPAD_DOWN); // D-Pad Down
+ MAP_BUTTON(ImGuiNavInput_FocusPrev, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_FocusNext, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
+ MAP_BUTTON(ImGuiNavInput_TweakSlow, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_TweakFast, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); // R1 / RB
+ MAP_ANALOG(ImGuiNavInput_LStickLeft, SDL_CONTROLLER_AXIS_LEFTX, -thumb_dead_zone, -32768);
+ MAP_ANALOG(ImGuiNavInput_LStickRight, SDL_CONTROLLER_AXIS_LEFTX, +thumb_dead_zone, +32767);
+ MAP_ANALOG(ImGuiNavInput_LStickUp, SDL_CONTROLLER_AXIS_LEFTY, -thumb_dead_zone, -32767);
+ MAP_ANALOG(ImGuiNavInput_LStickDown, SDL_CONTROLLER_AXIS_LEFTY, +thumb_dead_zone, +32767);
+
+ io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
+ #undef MAP_BUTTON
+ #undef MAP_ANALOG
+}
+
+void ImGui_ImplSDL2_NewFrame()
+{
+ ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDL2_Init()?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Setup display size (every frame to accommodate for window resizing)
+ int w, h;
+ int display_w, display_h;
+ SDL_GetWindowSize(bd->Window, &w, &h);
+ if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED)
+ w = h = 0;
+ SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h);
+ io.DisplaySize = ImVec2((float)w, (float)h);
+ if (w > 0 && h > 0)
+ io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h);
+
+ // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution)
+ static Uint64 frequency = SDL_GetPerformanceFrequency();
+ Uint64 current_time = SDL_GetPerformanceCounter();
+ io.DeltaTime = bd->Time > 0 ? (float)((double)(current_time - bd->Time) / frequency) : (float)(1.0f / 60.0f);
+ bd->Time = current_time;
+
+ ImGui_ImplSDL2_UpdateMousePosAndButtons();
+ ImGui_ImplSDL2_UpdateMouseCursor();
+
+ // Update game controllers (if enabled and available)
+ ImGui_ImplSDL2_UpdateGamepads();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_sdl.h b/Client/ThirdParty/imgui/backends/imgui_impl_sdl.h
new file mode 100644
index 0000000..d2439eb
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_sdl.h
@@ -0,0 +1,35 @@
+// dear imgui: Platform Backend for SDL2
+// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
+// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)
+
+// Implemented features:
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Platform: Clipboard support.
+// [X] Platform: Keyboard arrays indexed using SDL_SCANCODE_* codes, e.g. ImGui::IsKeyPressed(SDL_SCANCODE_SPACE).
+// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+// Missing features:
+// [ ] Platform: SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct SDL_Window;
+typedef union SDL_Event SDL_Event;
+
+IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
+IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
+IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
+IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
+IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window);
+IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
+IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
+#endif
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.cpp
new file mode 100644
index 0000000..bfc2b67
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.cpp
@@ -0,0 +1,238 @@
+// dear imgui: Renderer Backend for SDL_Renderer
+// (Requires: SDL 2.0.17+)
+
+// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
+// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
+// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
+// Missing features:
+// [ ] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// 2021-10-06: Backup and restore modified ClipRect/Viewport.
+// 2021-09-21: Initial version.
+
+#include "imgui.h"
+#include "imgui_impl_sdlrenderer.h"
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// SDL
+#include <SDL.h>
+#if !SDL_VERSION_ATLEAST(2,0,17)
+#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
+#endif
+
+// SDL_Renderer data
+struct ImGui_ImplSDLRenderer_Data
+{
+ SDL_Renderer* SDLRenderer;
+ SDL_Texture* FontTexture;
+ ImGui_ImplSDLRenderer_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+static ImGui_ImplSDLRenderer_Data* ImGui_ImplSDLRenderer_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplSDLRenderer_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+// Functions
+bool ImGui_ImplSDLRenderer_Init(SDL_Renderer* renderer)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+ IM_ASSERT(renderer != NULL && "SDL_Renderer not initialized!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplSDLRenderer_Data* bd = IM_NEW(ImGui_ImplSDLRenderer_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_sdlrenderer";
+
+ bd->SDLRenderer = renderer;
+
+ return true;
+}
+
+void ImGui_ImplSDLRenderer_Shutdown()
+{
+ ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplSDLRenderer_DestroyDeviceObjects();
+
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+static void ImGui_ImplSDLRenderer_SetupRenderState()
+{
+ ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
+
+ // Clear out any viewports and cliprect set by the user
+ // FIXME: Technically speaking there are lots of other things we could backup/setup/restore during our render process.
+ SDL_RenderSetViewport(bd->SDLRenderer, NULL);
+ SDL_RenderSetClipRect(bd->SDLRenderer, NULL);
+}
+
+void ImGui_ImplSDLRenderer_NewFrame()
+{
+ ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplSDLRenderer_Init()?");
+
+ if (!bd->FontTexture)
+ ImGui_ImplSDLRenderer_CreateDeviceObjects();
+}
+
+void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
+{
+ ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
+
+ // If there's a scale factor set by the user, use that instead
+ // If the user has specified a scale factor to SDL_Renderer already via SDL_RenderSetScale(), SDL will scale whatever we pass
+ // to SDL_RenderGeometryRaw() by that scale factor. In that case we don't want to be also scaling it ourselves here.
+ float rsx = 1.0f;
+ float rsy = 1.0f;
+ SDL_RenderGetScale(bd->SDLRenderer, &rsx, &rsy);
+ ImVec2 render_scale;
+ render_scale.x = (rsx == 1.0f) ? draw_data->FramebufferScale.x : 1.0f;
+ render_scale.y = (rsy == 1.0f) ? draw_data->FramebufferScale.y : 1.0f;
+
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ int fb_width = (int)(draw_data->DisplaySize.x * render_scale.x);
+ int fb_height = (int)(draw_data->DisplaySize.y * render_scale.y);
+ if (fb_width == 0 || fb_height == 0)
+ return;
+
+ // Backup SDL_Renderer state that will be modified to restore it afterwards
+ struct BackupSDLRendererState
+ {
+ SDL_Rect Viewport;
+ bool ClipEnabled;
+ SDL_Rect ClipRect;
+ };
+ BackupSDLRendererState old = {};
+ old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer);
+ SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport);
+ SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect);
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = render_scale;
+
+ // Render command lists
+ ImGui_ImplSDLRenderer_SetupRenderState();
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplSDLRenderer_SetupRenderState();
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+ if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
+ if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
+ if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
+ if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
+ SDL_RenderSetClipRect(bd->SDLRenderer, &r);
+
+ const float* xy = (const float*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos));
+ const float* uv = (const float*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv));
+ const int* color = (const int*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col));
+
+ // Bind texture, Draw
+ SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
+ SDL_RenderGeometryRaw(bd->SDLRenderer, tex,
+ xy, (int)sizeof(ImDrawVert),
+ color, (int)sizeof(ImDrawVert),
+ uv, (int)sizeof(ImDrawVert),
+ cmd_list->VtxBuffer.Size,
+ idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
+ }
+ }
+ }
+
+ // Restore modified SDL_Renderer state
+ SDL_RenderSetViewport(bd->SDLRenderer, &old.Viewport);
+ SDL_RenderSetClipRect(bd->SDLRenderer, old.ClipEnabled ? &old.ClipRect : NULL);
+}
+
+// Called by Init/NewFrame/Shutdown
+bool ImGui_ImplSDLRenderer_CreateFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
+
+ // Build texture atlas
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.
+
+ // Upload texture to graphics system
+ bd->FontTexture = SDL_CreateTexture(bd->SDLRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height);
+ if (bd->FontTexture == NULL)
+ {
+ SDL_Log("error creating texture");
+ return false;
+ }
+ SDL_UpdateTexture(bd->FontTexture, NULL, pixels, 4 * width);
+ SDL_SetTextureBlendMode(bd->FontTexture, SDL_BLENDMODE_BLEND);
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
+
+ return true;
+}
+
+void ImGui_ImplSDLRenderer_DestroyFontsTexture()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplSDLRenderer_Data* bd = ImGui_ImplSDLRenderer_GetBackendData();
+ if (bd->FontTexture)
+ {
+ io.Fonts->SetTexID(0);
+ SDL_DestroyTexture(bd->FontTexture);
+ bd->FontTexture = NULL;
+ }
+}
+
+bool ImGui_ImplSDLRenderer_CreateDeviceObjects()
+{
+ return ImGui_ImplSDLRenderer_CreateFontsTexture();
+}
+
+void ImGui_ImplSDLRenderer_DestroyDeviceObjects()
+{
+ ImGui_ImplSDLRenderer_DestroyFontsTexture();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.h b/Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.h
new file mode 100644
index 0000000..8c67fa3
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_sdlrenderer.h
@@ -0,0 +1,27 @@
+// dear imgui: Renderer Backend for SDL_Renderer
+// (Requires: SDL 2.0.17+)
+
+// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
+// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
+// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
+// Missing features:
+// [ ] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+struct SDL_Renderer;
+
+IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_Init(SDL_Renderer* renderer);
+IMGUI_IMPL_API void ImGui_ImplSDLRenderer_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplSDLRenderer_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data);
+
+// Called by Init/NewFrame/Shutdown
+IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_CreateFontsTexture();
+IMGUI_IMPL_API void ImGui_ImplSDLRenderer_DestroyFontsTexture();
+IMGUI_IMPL_API bool ImGui_ImplSDLRenderer_CreateDeviceObjects();
+IMGUI_IMPL_API void ImGui_ImplSDLRenderer_DestroyDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_vulkan.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_vulkan.cpp
new file mode 100644
index 0000000..e4f12f2
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_vulkan.cpp
@@ -0,0 +1,1474 @@
+// dear imgui: Renderer Backend for Vulkan
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+// Missing features:
+// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
+
+// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
+// You will use those if you want to use this rendering backend in your engine/app.
+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
+// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
+// Read comments in imgui_impl_vulkan.h.
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
+// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
+// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
+// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
+// 2020-09-07: Vulkan: Added VkPipeline parameter to ImGui_ImplVulkan_RenderDrawData (default to one passed to ImGui_ImplVulkan_Init).
+// 2020-05-04: Vulkan: Fixed crash if initial frame has no vertices.
+// 2020-04-26: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData didn't have vertices.
+// 2019-08-01: Vulkan: Added support for specifying multisample count. Set ImGui_ImplVulkan_InitInfo::MSAASamples to one of the VkSampleCountFlagBits values to use, default is non-multisampled as before.
+// 2019-05-29: Vulkan: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
+// 2019-04-30: Vulkan: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
+// 2019-04-04: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().
+// 2019-04-04: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
+// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
+// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
+// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
+// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
+// 2018-08-25: Vulkan: Fixed mishandled VkSurfaceCapabilitiesKHR::maxImageCount=0 case.
+// 2018-06-22: Inverted the parameters to ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends.
+// 2018-06-08: Misc: Extracted imgui_impl_vulkan.cpp/.h away from the old combined GLFW+Vulkan example.
+// 2018-06-08: Vulkan: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
+// 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
+// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
+// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy.
+// 2016-11-13: Vulkan: Fix validation layer warnings and errors and redeclare gl_PerVertex.
+// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources.
+// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active.
+
+#include "imgui_impl_vulkan.h"
+#include <stdio.h>
+
+// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
+// [Please zero-clear before use!]
+struct ImGui_ImplVulkanH_FrameRenderBuffers
+{
+ VkDeviceMemory VertexBufferMemory;
+ VkDeviceMemory IndexBufferMemory;
+ VkDeviceSize VertexBufferSize;
+ VkDeviceSize IndexBufferSize;
+ VkBuffer VertexBuffer;
+ VkBuffer IndexBuffer;
+};
+
+// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers
+// [Please zero-clear before use!]
+struct ImGui_ImplVulkanH_WindowRenderBuffers
+{
+ uint32_t Index;
+ uint32_t Count;
+ ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers;
+};
+
+// Vulkan data
+struct ImGui_ImplVulkan_Data
+{
+ ImGui_ImplVulkan_InitInfo VulkanInitInfo;
+ VkRenderPass RenderPass;
+ VkDeviceSize BufferMemoryAlignment;
+ VkPipelineCreateFlags PipelineCreateFlags;
+ VkDescriptorSetLayout DescriptorSetLayout;
+ VkPipelineLayout PipelineLayout;
+ VkDescriptorSet DescriptorSet;
+ VkPipeline Pipeline;
+ uint32_t Subpass;
+ VkShaderModule ShaderModuleVert;
+ VkShaderModule ShaderModuleFrag;
+
+ // Font data
+ VkSampler FontSampler;
+ VkDeviceMemory FontMemory;
+ VkImage FontImage;
+ VkImageView FontView;
+ VkDeviceMemory UploadBufferMemory;
+ VkBuffer UploadBuffer;
+
+ // Render buffers
+ ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers;
+
+ ImGui_ImplVulkan_Data()
+ {
+ memset(this, 0, sizeof(*this));
+ BufferMemoryAlignment = 256;
+ }
+};
+
+// Forward Declarations
+bool ImGui_ImplVulkan_CreateDeviceObjects();
+void ImGui_ImplVulkan_DestroyDeviceObjects();
+void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
+void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
+void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
+void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
+void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
+void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
+
+// Vulkan prototypes for use with custom loaders
+// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
+#ifdef VK_NO_PROTOTYPES
+static bool g_FunctionsLoaded = false;
+#else
+static bool g_FunctionsLoaded = true;
+#endif
+#ifdef VK_NO_PROTOTYPES
+#define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateMemory) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindBufferMemory) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkBindImageMemory) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindDescriptorSets) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindIndexBuffer) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindPipeline) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdBindVertexBuffers) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdCopyBufferToImage) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdDrawIndexed) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPipelineBarrier) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdPushConstants) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetScissor) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCmdSetViewport) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateBuffer) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateCommandPool) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateDescriptorSetLayout) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFence) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateFramebuffer) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateGraphicsPipelines) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImage) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateImageView) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreatePipelineLayout) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateRenderPass) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSampler) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSemaphore) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateShaderModule) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkCreateSwapchainKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyBuffer) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyCommandPool) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyDescriptorSetLayout) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFence) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyFramebuffer) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImage) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyImageView) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipeline) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyPipelineLayout) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyRenderPass) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySampler) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySemaphore) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroyShaderModule) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySurfaceKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDestroySwapchainKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkDeviceWaitIdle) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFlushMappedMemoryRanges) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeCommandBuffers) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkFreeMemory) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetBufferMemoryRequirements) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetImageMemoryRequirements) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceMemoryProperties) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfaceFormatsKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetPhysicalDeviceSurfacePresentModesKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkGetSwapchainImagesKHR) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkMapMemory) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkUnmapMemory) \
+ IMGUI_VULKAN_FUNC_MAP_MACRO(vkUpdateDescriptorSets)
+
+// Define function pointers
+#define IMGUI_VULKAN_FUNC_DEF(func) static PFN_##func func;
+IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF)
+#undef IMGUI_VULKAN_FUNC_DEF
+#endif // VK_NO_PROTOTYPES
+
+//-----------------------------------------------------------------------------
+// SHADERS
+//-----------------------------------------------------------------------------
+
+// glsl_shader.vert, compiled with:
+// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
+/*
+#version 450 core
+layout(location = 0) in vec2 aPos;
+layout(location = 1) in vec2 aUV;
+layout(location = 2) in vec4 aColor;
+layout(push_constant) uniform uPushConstant { vec2 uScale; vec2 uTranslate; } pc;
+
+out gl_PerVertex { vec4 gl_Position; };
+layout(location = 0) out struct { vec4 Color; vec2 UV; } Out;
+
+void main()
+{
+ Out.Color = aColor;
+ Out.UV = aUV;
+ gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1);
+}
+*/
+static uint32_t __glsl_shader_vert_spv[] =
+{
+ 0x07230203,0x00010000,0x00080001,0x0000002e,0x00000000,0x00020011,0x00000001,0x0006000b,
+ 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
+ 0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
+ 0x0000001b,0x0000001c,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
+ 0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43,
+ 0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f,
+ 0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005,
+ 0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x00000000,
+ 0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00040005,0x0000001c,
+ 0x736f5061,0x00000000,0x00060005,0x0000001e,0x73755075,0x6e6f4368,0x6e617473,0x00000074,
+ 0x00050006,0x0000001e,0x00000000,0x61635375,0x0000656c,0x00060006,0x0000001e,0x00000001,
+ 0x61725475,0x616c736e,0x00006574,0x00030005,0x00000020,0x00006370,0x00040047,0x0000000b,
+ 0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,
+ 0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047,
+ 0x00000019,0x00000002,0x00040047,0x0000001c,0x0000001e,0x00000000,0x00050048,0x0000001e,
+ 0x00000000,0x00000023,0x00000000,0x00050048,0x0000001e,0x00000001,0x00000023,0x00000008,
+ 0x00030047,0x0000001e,0x00000002,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,
+ 0x00030016,0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040017,
+ 0x00000008,0x00000006,0x00000002,0x0004001e,0x00000009,0x00000007,0x00000008,0x00040020,
+ 0x0000000a,0x00000003,0x00000009,0x0004003b,0x0000000a,0x0000000b,0x00000003,0x00040015,
+ 0x0000000c,0x00000020,0x00000001,0x0004002b,0x0000000c,0x0000000d,0x00000000,0x00040020,
+ 0x0000000e,0x00000001,0x00000007,0x0004003b,0x0000000e,0x0000000f,0x00000001,0x00040020,
+ 0x00000011,0x00000003,0x00000007,0x0004002b,0x0000000c,0x00000013,0x00000001,0x00040020,
+ 0x00000014,0x00000001,0x00000008,0x0004003b,0x00000014,0x00000015,0x00000001,0x00040020,
+ 0x00000017,0x00000003,0x00000008,0x0003001e,0x00000019,0x00000007,0x00040020,0x0000001a,
+ 0x00000003,0x00000019,0x0004003b,0x0000001a,0x0000001b,0x00000003,0x0004003b,0x00000014,
+ 0x0000001c,0x00000001,0x0004001e,0x0000001e,0x00000008,0x00000008,0x00040020,0x0000001f,
+ 0x00000009,0x0000001e,0x0004003b,0x0000001f,0x00000020,0x00000009,0x00040020,0x00000021,
+ 0x00000009,0x00000008,0x0004002b,0x00000006,0x00000028,0x00000000,0x0004002b,0x00000006,
+ 0x00000029,0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,
+ 0x00000005,0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012,
+ 0x0000000b,0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016,
+ 0x00000015,0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018,
+ 0x00000016,0x0004003d,0x00000008,0x0000001d,0x0000001c,0x00050041,0x00000021,0x00000022,
+ 0x00000020,0x0000000d,0x0004003d,0x00000008,0x00000023,0x00000022,0x00050085,0x00000008,
+ 0x00000024,0x0000001d,0x00000023,0x00050041,0x00000021,0x00000025,0x00000020,0x00000013,
+ 0x0004003d,0x00000008,0x00000026,0x00000025,0x00050081,0x00000008,0x00000027,0x00000024,
+ 0x00000026,0x00050051,0x00000006,0x0000002a,0x00000027,0x00000000,0x00050051,0x00000006,
+ 0x0000002b,0x00000027,0x00000001,0x00070050,0x00000007,0x0000002c,0x0000002a,0x0000002b,
+ 0x00000028,0x00000029,0x00050041,0x00000011,0x0000002d,0x0000001b,0x0000000d,0x0003003e,
+ 0x0000002d,0x0000002c,0x000100fd,0x00010038
+};
+
+// glsl_shader.frag, compiled with:
+// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
+/*
+#version 450 core
+layout(location = 0) out vec4 fColor;
+layout(set=0, binding=0) uniform sampler2D sTexture;
+layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
+void main()
+{
+ fColor = In.Color * texture(sTexture, In.UV.st);
+}
+*/
+static uint32_t __glsl_shader_frag_spv[] =
+{
+ 0x07230203,0x00010000,0x00080001,0x0000001e,0x00000000,0x00020011,0x00000001,0x0006000b,
+ 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
+ 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
+ 0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
+ 0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
+ 0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
+ 0x00005655,0x00030005,0x0000000d,0x00006e49,0x00050005,0x00000016,0x78655473,0x65727574,
+ 0x00000000,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,0x0000001e,
+ 0x00000000,0x00040047,0x00000016,0x00000022,0x00000000,0x00040047,0x00000016,0x00000021,
+ 0x00000000,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,
+ 0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,0x00000003,
+ 0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,0x00000006,
+ 0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,0x00000001,
+ 0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,0x00000020,
+ 0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,0x00000001,
+ 0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,0x00000000,
+ 0x00000001,0x00000000,0x0003001b,0x00000014,0x00000013,0x00040020,0x00000015,0x00000000,
+ 0x00000014,0x0004003b,0x00000015,0x00000016,0x00000000,0x0004002b,0x0000000e,0x00000018,
+ 0x00000001,0x00040020,0x00000019,0x00000001,0x0000000a,0x00050036,0x00000002,0x00000004,
+ 0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,0x00000010,0x00000011,0x0000000d,
+ 0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,0x0004003d,0x00000014,0x00000017,
+ 0x00000016,0x00050041,0x00000019,0x0000001a,0x0000000d,0x00000018,0x0004003d,0x0000000a,
+ 0x0000001b,0x0000001a,0x00050057,0x00000007,0x0000001c,0x00000017,0x0000001b,0x00050085,
+ 0x00000007,0x0000001d,0x00000012,0x0000001c,0x0003003e,0x00000009,0x0000001d,0x000100fd,
+ 0x00010038
+};
+
+//-----------------------------------------------------------------------------
+// FUNCTIONS
+//-----------------------------------------------------------------------------
+
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not tested and probably dysfunctional in this backend.
+static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
+static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ VkPhysicalDeviceMemoryProperties prop;
+ vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop);
+ for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
+ if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1 << i))
+ return i;
+ return 0xFFFFFFFF; // Unable to find memoryType
+}
+
+static void check_vk_result(VkResult err)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (!bd)
+ return;
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ if (v->CheckVkResultFn)
+ v->CheckVkResultFn(err);
+}
+
+static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ VkResult err;
+ if (buffer != VK_NULL_HANDLE)
+ vkDestroyBuffer(v->Device, buffer, v->Allocator);
+ if (buffer_memory != VK_NULL_HANDLE)
+ vkFreeMemory(v->Device, buffer_memory, v->Allocator);
+
+ VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment;
+ VkBufferCreateInfo buffer_info = {};
+ buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_info.size = vertex_buffer_size_aligned;
+ buffer_info.usage = usage;
+ buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer);
+ check_vk_result(err);
+
+ VkMemoryRequirements req;
+ vkGetBufferMemoryRequirements(v->Device, buffer, &req);
+ bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
+ VkMemoryAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ alloc_info.allocationSize = req.size;
+ alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory);
+ check_vk_result(err);
+
+ err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);
+ check_vk_result(err);
+ p_buffer_size = req.size;
+}
+
+static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+
+ // Bind pipeline and descriptor sets:
+ {
+ vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
+ VkDescriptorSet desc_set[1] = { bd->DescriptorSet };
+ vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, NULL);
+ }
+
+ // Bind Vertex And Index Buffer:
+ if (draw_data->TotalVtxCount > 0)
+ {
+ VkBuffer vertex_buffers[1] = { rb->VertexBuffer };
+ VkDeviceSize vertex_offset[1] = { 0 };
+ vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset);
+ vkCmdBindIndexBuffer(command_buffer, rb->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);
+ }
+
+ // Setup viewport:
+ {
+ VkViewport viewport;
+ viewport.x = 0;
+ viewport.y = 0;
+ viewport.width = (float)fb_width;
+ viewport.height = (float)fb_height;
+ viewport.minDepth = 0.0f;
+ viewport.maxDepth = 1.0f;
+ vkCmdSetViewport(command_buffer, 0, 1, &viewport);
+ }
+
+ // Setup scale and translation:
+ // Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
+ {
+ float scale[2];
+ scale[0] = 2.0f / draw_data->DisplaySize.x;
+ scale[1] = 2.0f / draw_data->DisplaySize.y;
+ float translate[2];
+ translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
+ translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
+ }
+}
+
+// Render function
+void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline)
+{
+ // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
+ int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
+ int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
+ if (fb_width <= 0 || fb_height <= 0)
+ return;
+
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ if (pipeline == VK_NULL_HANDLE)
+ pipeline = bd->Pipeline;
+
+ // Allocate array to store enough vertex/index buffers
+ ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers;
+ if (wrb->FrameRenderBuffers == NULL)
+ {
+ wrb->Index = 0;
+ wrb->Count = v->ImageCount;
+ wrb->FrameRenderBuffers = (ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
+ memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
+ }
+ IM_ASSERT(wrb->Count == v->ImageCount);
+ wrb->Index = (wrb->Index + 1) % wrb->Count;
+ ImGui_ImplVulkanH_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index];
+
+ if (draw_data->TotalVtxCount > 0)
+ {
+ // Create or resize the vertex/index buffers
+ size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
+ size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
+ if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)
+ CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
+ if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)
+ CreateOrResizeBuffer(rb->IndexBuffer, rb->IndexBufferMemory, rb->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
+
+ // Upload vertex/index data into a single contiguous GPU buffer
+ ImDrawVert* vtx_dst = NULL;
+ ImDrawIdx* idx_dst = NULL;
+ VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst));
+ check_vk_result(err);
+ err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst));
+ check_vk_result(err);
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ VkMappedMemoryRange range[2] = {};
+ range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ range[0].memory = rb->VertexBufferMemory;
+ range[0].size = VK_WHOLE_SIZE;
+ range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ range[1].memory = rb->IndexBufferMemory;
+ range[1].size = VK_WHOLE_SIZE;
+ err = vkFlushMappedMemoryRanges(v->Device, 2, range);
+ check_vk_result(err);
+ vkUnmapMemory(v->Device, rb->VertexBufferMemory);
+ vkUnmapMemory(v->Device, rb->IndexBufferMemory);
+ }
+
+ // Setup desired Vulkan state
+ ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
+
+ // Will project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
+ ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_vtx_offset = 0;
+ int global_idx_offset = 0;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+
+ // Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds
+ if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
+ if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
+ if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
+ if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle
+ VkRect2D scissor;
+ scissor.offset.x = (int32_t)(clip_min.x);
+ scissor.offset.y = (int32_t)(clip_min.y);
+ scissor.extent.width = (uint32_t)(clip_max.x - clip_min.x);
+ scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
+
+ // Draw
+ vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+
+ // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
+ // Our last values will leak into user/application rendering IF:
+ // - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
+ // - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
+ // If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
+ // In theory we should aim to backup/restore those values but I am not sure this is possible.
+ // We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
+ VkRect2D scissor = { { 0, 0 }, { (uint32_t)fb_width, (uint32_t)fb_height } };
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
+}
+
+bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+
+ unsigned char* pixels;
+ int width, height;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+ size_t upload_size = width * height * 4 * sizeof(char);
+
+ VkResult err;
+
+ // Create the Image:
+ {
+ VkImageCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ info.imageType = VK_IMAGE_TYPE_2D;
+ info.format = VK_FORMAT_R8G8B8A8_UNORM;
+ info.extent.width = width;
+ info.extent.height = height;
+ info.extent.depth = 1;
+ info.mipLevels = 1;
+ info.arrayLayers = 1;
+ info.samples = VK_SAMPLE_COUNT_1_BIT;
+ info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ err = vkCreateImage(v->Device, &info, v->Allocator, &bd->FontImage);
+ check_vk_result(err);
+ VkMemoryRequirements req;
+ vkGetImageMemoryRequirements(v->Device, bd->FontImage, &req);
+ VkMemoryAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ alloc_info.allocationSize = req.size;
+ alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory);
+ check_vk_result(err);
+ err = vkBindImageMemory(v->Device, bd->FontImage, bd->FontMemory, 0);
+ check_vk_result(err);
+ }
+
+ // Create the Image View:
+ {
+ VkImageViewCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ info.image = bd->FontImage;
+ info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ info.format = VK_FORMAT_R8G8B8A8_UNORM;
+ info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ info.subresourceRange.levelCount = 1;
+ info.subresourceRange.layerCount = 1;
+ err = vkCreateImageView(v->Device, &info, v->Allocator, &bd->FontView);
+ check_vk_result(err);
+ }
+
+ // Update the Descriptor Set:
+ {
+ VkDescriptorImageInfo desc_image[1] = {};
+ desc_image[0].sampler = bd->FontSampler;
+ desc_image[0].imageView = bd->FontView;
+ desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ VkWriteDescriptorSet write_desc[1] = {};
+ write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_desc[0].dstSet = bd->DescriptorSet;
+ write_desc[0].descriptorCount = 1;
+ write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ write_desc[0].pImageInfo = desc_image;
+ vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
+ }
+
+ // Create the Upload Buffer:
+ {
+ VkBufferCreateInfo buffer_info = {};
+ buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ buffer_info.size = upload_size;
+ buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &bd->UploadBuffer);
+ check_vk_result(err);
+ VkMemoryRequirements req;
+ vkGetBufferMemoryRequirements(v->Device, bd->UploadBuffer, &req);
+ bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
+ VkMemoryAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ alloc_info.allocationSize = req.size;
+ alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->UploadBufferMemory);
+ check_vk_result(err);
+ err = vkBindBufferMemory(v->Device, bd->UploadBuffer, bd->UploadBufferMemory, 0);
+ check_vk_result(err);
+ }
+
+ // Upload to Buffer:
+ {
+ char* map = NULL;
+ err = vkMapMemory(v->Device, bd->UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
+ check_vk_result(err);
+ memcpy(map, pixels, upload_size);
+ VkMappedMemoryRange range[1] = {};
+ range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
+ range[0].memory = bd->UploadBufferMemory;
+ range[0].size = upload_size;
+ err = vkFlushMappedMemoryRanges(v->Device, 1, range);
+ check_vk_result(err);
+ vkUnmapMemory(v->Device, bd->UploadBufferMemory);
+ }
+
+ // Copy to Image:
+ {
+ VkImageMemoryBarrier copy_barrier[1] = {};
+ copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ copy_barrier[0].image = bd->FontImage;
+ copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copy_barrier[0].subresourceRange.levelCount = 1;
+ copy_barrier[0].subresourceRange.layerCount = 1;
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier);
+
+ VkBufferImageCopy region = {};
+ region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ region.imageSubresource.layerCount = 1;
+ region.imageExtent.width = width;
+ region.imageExtent.height = height;
+ region.imageExtent.depth = 1;
+ vkCmdCopyBufferToImage(command_buffer, bd->UploadBuffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+
+ VkImageMemoryBarrier use_barrier[1] = {};
+ use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ use_barrier[0].image = bd->FontImage;
+ use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ use_barrier[0].subresourceRange.levelCount = 1;
+ use_barrier[0].subresourceRange.layerCount = 1;
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier);
+ }
+
+ // Store our identifier
+ io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontImage);
+
+ return true;
+}
+
+static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
+{
+ // Create the shader modules
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->ShaderModuleVert == VK_NULL_HANDLE)
+ {
+ VkShaderModuleCreateInfo vert_info = {};
+ vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
+ vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
+ VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert);
+ check_vk_result(err);
+ }
+ if (bd->ShaderModuleFrag == VK_NULL_HANDLE)
+ {
+ VkShaderModuleCreateInfo frag_info = {};
+ frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
+ frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
+ VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag);
+ check_vk_result(err);
+ }
+}
+
+static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->FontSampler)
+ return;
+
+ VkSamplerCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ info.magFilter = VK_FILTER_LINEAR;
+ info.minFilter = VK_FILTER_LINEAR;
+ info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ info.minLod = -1000;
+ info.maxLod = 1000;
+ info.maxAnisotropy = 1.0f;
+ VkResult err = vkCreateSampler(device, &info, allocator, &bd->FontSampler);
+ check_vk_result(err);
+}
+
+static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->DescriptorSetLayout)
+ return;
+
+ ImGui_ImplVulkan_CreateFontSampler(device, allocator);
+ VkSampler sampler[1] = { bd->FontSampler };
+ VkDescriptorSetLayoutBinding binding[1] = {};
+ binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ binding[0].descriptorCount = 1;
+ binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ binding[0].pImmutableSamplers = sampler;
+ VkDescriptorSetLayoutCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ info.bindingCount = 1;
+ info.pBindings = binding;
+ VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &bd->DescriptorSetLayout);
+ check_vk_result(err);
+}
+
+static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->PipelineLayout)
+ return;
+
+ // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
+ ImGui_ImplVulkan_CreateDescriptorSetLayout(device, allocator);
+ VkPushConstantRange push_constants[1] = {};
+ push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ push_constants[0].offset = sizeof(float) * 0;
+ push_constants[0].size = sizeof(float) * 4;
+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
+ VkPipelineLayoutCreateInfo layout_info = {};
+ layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ layout_info.setLayoutCount = 1;
+ layout_info.pSetLayouts = set_layout;
+ layout_info.pushConstantRangeCount = 1;
+ layout_info.pPushConstantRanges = push_constants;
+ VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &bd->PipelineLayout);
+ check_vk_result(err);
+}
+
+static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_CreateShaderModules(device, allocator);
+
+ VkPipelineShaderStageCreateInfo stage[2] = {};
+ stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
+ stage[0].module = bd->ShaderModuleVert;
+ stage[0].pName = "main";
+ stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+ stage[1].module = bd->ShaderModuleFrag;
+ stage[1].pName = "main";
+
+ VkVertexInputBindingDescription binding_desc[1] = {};
+ binding_desc[0].stride = sizeof(ImDrawVert);
+ binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
+
+ VkVertexInputAttributeDescription attribute_desc[3] = {};
+ attribute_desc[0].location = 0;
+ attribute_desc[0].binding = binding_desc[0].binding;
+ attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT;
+ attribute_desc[0].offset = IM_OFFSETOF(ImDrawVert, pos);
+ attribute_desc[1].location = 1;
+ attribute_desc[1].binding = binding_desc[0].binding;
+ attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT;
+ attribute_desc[1].offset = IM_OFFSETOF(ImDrawVert, uv);
+ attribute_desc[2].location = 2;
+ attribute_desc[2].binding = binding_desc[0].binding;
+ attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM;
+ attribute_desc[2].offset = IM_OFFSETOF(ImDrawVert, col);
+
+ VkPipelineVertexInputStateCreateInfo vertex_info = {};
+ vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertex_info.vertexBindingDescriptionCount = 1;
+ vertex_info.pVertexBindingDescriptions = binding_desc;
+ vertex_info.vertexAttributeDescriptionCount = 3;
+ vertex_info.pVertexAttributeDescriptions = attribute_desc;
+
+ VkPipelineInputAssemblyStateCreateInfo ia_info = {};
+ ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+
+ VkPipelineViewportStateCreateInfo viewport_info = {};
+ viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ viewport_info.viewportCount = 1;
+ viewport_info.scissorCount = 1;
+
+ VkPipelineRasterizationStateCreateInfo raster_info = {};
+ raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ raster_info.polygonMode = VK_POLYGON_MODE_FILL;
+ raster_info.cullMode = VK_CULL_MODE_NONE;
+ raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ raster_info.lineWidth = 1.0f;
+
+ VkPipelineMultisampleStateCreateInfo ms_info = {};
+ ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT;
+
+ VkPipelineColorBlendAttachmentState color_attachment[1] = {};
+ color_attachment[0].blendEnable = VK_TRUE;
+ color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
+ color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD;
+ color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD;
+ color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
+
+ VkPipelineDepthStencilStateCreateInfo depth_info = {};
+ depth_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+
+ VkPipelineColorBlendStateCreateInfo blend_info = {};
+ blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ blend_info.attachmentCount = 1;
+ blend_info.pAttachments = color_attachment;
+
+ VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dynamic_state = {};
+ dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states);
+ dynamic_state.pDynamicStates = dynamic_states;
+
+ ImGui_ImplVulkan_CreatePipelineLayout(device, allocator);
+
+ VkGraphicsPipelineCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ info.flags = bd->PipelineCreateFlags;
+ info.stageCount = 2;
+ info.pStages = stage;
+ info.pVertexInputState = &vertex_info;
+ info.pInputAssemblyState = &ia_info;
+ info.pViewportState = &viewport_info;
+ info.pRasterizationState = &raster_info;
+ info.pMultisampleState = &ms_info;
+ info.pDepthStencilState = &depth_info;
+ info.pColorBlendState = &blend_info;
+ info.pDynamicState = &dynamic_state;
+ info.layout = bd->PipelineLayout;
+ info.renderPass = renderPass;
+ info.subpass = subpass;
+ VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
+ check_vk_result(err);
+}
+
+bool ImGui_ImplVulkan_CreateDeviceObjects()
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ VkResult err;
+
+ if (!bd->FontSampler)
+ {
+ VkSamplerCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ info.magFilter = VK_FILTER_LINEAR;
+ info.minFilter = VK_FILTER_LINEAR;
+ info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
+ info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
+ info.minLod = -1000;
+ info.maxLod = 1000;
+ info.maxAnisotropy = 1.0f;
+ err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler);
+ check_vk_result(err);
+ }
+
+ if (!bd->DescriptorSetLayout)
+ {
+ VkSampler sampler[1] = {bd->FontSampler};
+ VkDescriptorSetLayoutBinding binding[1] = {};
+ binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ binding[0].descriptorCount = 1;
+ binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+ binding[0].pImmutableSamplers = sampler;
+ VkDescriptorSetLayoutCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ info.bindingCount = 1;
+ info.pBindings = binding;
+ err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout);
+ check_vk_result(err);
+ }
+
+ // Create Descriptor Set:
+ {
+ VkDescriptorSetAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorPool = v->DescriptorPool;
+ alloc_info.descriptorSetCount = 1;
+ alloc_info.pSetLayouts = &bd->DescriptorSetLayout;
+ err = vkAllocateDescriptorSets(v->Device, &alloc_info, &bd->DescriptorSet);
+ check_vk_result(err);
+ }
+
+ if (!bd->PipelineLayout)
+ {
+ // Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
+ VkPushConstantRange push_constants[1] = {};
+ push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+ push_constants[0].offset = sizeof(float) * 0;
+ push_constants[0].size = sizeof(float) * 4;
+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
+ VkPipelineLayoutCreateInfo layout_info = {};
+ layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ layout_info.setLayoutCount = 1;
+ layout_info.pSetLayouts = set_layout;
+ layout_info.pushConstantRangeCount = 1;
+ layout_info.pPushConstantRanges = push_constants;
+ err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd->PipelineLayout);
+ check_vk_result(err);
+ }
+
+ ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass);
+
+ return true;
+}
+
+void ImGui_ImplVulkan_DestroyFontUploadObjects()
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ if (bd->UploadBuffer)
+ {
+ vkDestroyBuffer(v->Device, bd->UploadBuffer, v->Allocator);
+ bd->UploadBuffer = VK_NULL_HANDLE;
+ }
+ if (bd->UploadBufferMemory)
+ {
+ vkFreeMemory(v->Device, bd->UploadBufferMemory, v->Allocator);
+ bd->UploadBufferMemory = VK_NULL_HANDLE;
+ }
+}
+
+void ImGui_ImplVulkan_DestroyDeviceObjects()
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator);
+ ImGui_ImplVulkan_DestroyFontUploadObjects();
+
+ if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
+ if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
+ if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
+ if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; }
+ if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }
+ if (bd->FontSampler) { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; }
+ if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
+ if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
+ if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
+}
+
+bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
+{
+ // Load function pointers
+ // You can use the default Vulkan loader using:
+ // ImGui_ImplVulkan_LoadFunctions([](const char* function_name, void*) { return vkGetInstanceProcAddr(your_vk_isntance, function_name); });
+ // But this would be equivalent to not setting VK_NO_PROTOTYPES.
+#ifdef VK_NO_PROTOTYPES
+#define IMGUI_VULKAN_FUNC_LOAD(func) \
+ func = reinterpret_cast<decltype(func)>(loader_func(#func, user_data)); \
+ if (func == NULL) \
+ return false;
+ IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD)
+#undef IMGUI_VULKAN_FUNC_LOAD
+#else
+ IM_UNUSED(loader_func);
+ IM_UNUSED(user_data);
+#endif
+ g_FunctionsLoaded = true;
+ return true;
+}
+
+bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
+{
+ IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
+
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();
+ io.BackendRendererUserData = (void*)bd;
+ io.BackendRendererName = "imgui_impl_vulkan";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ IM_ASSERT(info->Instance != VK_NULL_HANDLE);
+ IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE);
+ IM_ASSERT(info->Device != VK_NULL_HANDLE);
+ IM_ASSERT(info->Queue != VK_NULL_HANDLE);
+ IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE);
+ IM_ASSERT(info->MinImageCount >= 2);
+ IM_ASSERT(info->ImageCount >= info->MinImageCount);
+ IM_ASSERT(render_pass != VK_NULL_HANDLE);
+
+ bd->VulkanInitInfo = *info;
+ bd->RenderPass = render_pass;
+ bd->Subpass = info->Subpass;
+
+ ImGui_ImplVulkan_CreateDeviceObjects();
+
+ return true;
+}
+
+void ImGui_ImplVulkan_Shutdown()
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ ImGui_ImplVulkan_DestroyDeviceObjects();
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
+}
+
+void ImGui_ImplVulkan_NewFrame()
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplVulkan_Init()?");
+ IM_UNUSED(bd);
+}
+
+void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ IM_ASSERT(min_image_count >= 2);
+ if (bd->VulkanInitInfo.MinImageCount == min_image_count)
+ return;
+
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ VkResult err = vkDeviceWaitIdle(v->Device);
+ check_vk_result(err);
+ ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator);
+ bd->VulkanInitInfo.MinImageCount = min_image_count;
+}
+
+
+//-------------------------------------------------------------------------
+// Internal / Miscellaneous Vulkan Helpers
+// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
+//-------------------------------------------------------------------------
+// You probably do NOT need to use or care about those functions.
+// Those functions only exist because:
+// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
+// 2) the upcoming multi-viewport feature will need them internally.
+// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
+// but it is too much code to duplicate everywhere so we exceptionally expose them.
+//
+// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
+// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
+// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
+//-------------------------------------------------------------------------
+
+VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
+{
+ IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
+ IM_ASSERT(request_formats != NULL);
+ IM_ASSERT(request_formats_count > 0);
+
+ // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation
+ // Assuming that the default behavior is without setting this bit, there is no need for separate Swapchain image and image view format
+ // Additionally several new color spaces were introduced with Vulkan Spec v1.0.40,
+ // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used.
+ uint32_t avail_count;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, NULL);
+ ImVector<VkSurfaceFormatKHR> avail_format;
+ avail_format.resize((int)avail_count);
+ vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data);
+
+ // First check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available
+ if (avail_count == 1)
+ {
+ if (avail_format[0].format == VK_FORMAT_UNDEFINED)
+ {
+ VkSurfaceFormatKHR ret;
+ ret.format = request_formats[0];
+ ret.colorSpace = request_color_space;
+ return ret;
+ }
+ else
+ {
+ // No point in searching another format
+ return avail_format[0];
+ }
+ }
+ else
+ {
+ // Request several formats, the first found will be used
+ for (int request_i = 0; request_i < request_formats_count; request_i++)
+ for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
+ if (avail_format[avail_i].format == request_formats[request_i] && avail_format[avail_i].colorSpace == request_color_space)
+ return avail_format[avail_i];
+
+ // If none of the requested image formats could be found, use the first available
+ return avail_format[0];
+ }
+}
+
+VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count)
+{
+ IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
+ IM_ASSERT(request_modes != NULL);
+ IM_ASSERT(request_modes_count > 0);
+
+ // Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory
+ uint32_t avail_count = 0;
+ vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, NULL);
+ ImVector<VkPresentModeKHR> avail_modes;
+ avail_modes.resize((int)avail_count);
+ vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data);
+ //for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
+ // printf("[vulkan] avail_modes[%d] = %d\n", avail_i, avail_modes[avail_i]);
+
+ for (int request_i = 0; request_i < request_modes_count; request_i++)
+ for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++)
+ if (request_modes[request_i] == avail_modes[avail_i])
+ return request_modes[request_i];
+
+ return VK_PRESENT_MODE_FIFO_KHR; // Always available
+}
+
+void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator)
+{
+ IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE);
+ (void)physical_device;
+ (void)allocator;
+
+ // Create Command Buffers
+ VkResult err;
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
+ {
+ ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
+ ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
+ {
+ VkCommandPoolCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ info.queueFamilyIndex = queue_family;
+ err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool);
+ check_vk_result(err);
+ }
+ {
+ VkCommandBufferAllocateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ info.commandPool = fd->CommandPool;
+ info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ info.commandBufferCount = 1;
+ err = vkAllocateCommandBuffers(device, &info, &fd->CommandBuffer);
+ check_vk_result(err);
+ }
+ {
+ VkFenceCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+ err = vkCreateFence(device, &info, allocator, &fd->Fence);
+ check_vk_result(err);
+ }
+ {
+ VkSemaphoreCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ err = vkCreateSemaphore(device, &info, allocator, &fsd->ImageAcquiredSemaphore);
+ check_vk_result(err);
+ err = vkCreateSemaphore(device, &info, allocator, &fsd->RenderCompleteSemaphore);
+ check_vk_result(err);
+ }
+ }
+}
+
+int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode)
+{
+ if (present_mode == VK_PRESENT_MODE_MAILBOX_KHR)
+ return 3;
+ if (present_mode == VK_PRESENT_MODE_FIFO_KHR || present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)
+ return 2;
+ if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
+ return 1;
+ IM_ASSERT(0);
+ return 1;
+}
+
+// Also destroy old swap chain and in-flight frames data, if any.
+void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count)
+{
+ VkResult err;
+ VkSwapchainKHR old_swapchain = wd->Swapchain;
+ wd->Swapchain = VK_NULL_HANDLE;
+ err = vkDeviceWaitIdle(device);
+ check_vk_result(err);
+
+ // We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
+ // Destroy old Framebuffer
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
+ {
+ ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
+ ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
+ }
+ IM_FREE(wd->Frames);
+ IM_FREE(wd->FrameSemaphores);
+ wd->Frames = NULL;
+ wd->FrameSemaphores = NULL;
+ wd->ImageCount = 0;
+ if (wd->RenderPass)
+ vkDestroyRenderPass(device, wd->RenderPass, allocator);
+ if (wd->Pipeline)
+ vkDestroyPipeline(device, wd->Pipeline, allocator);
+
+ // If min image count was not specified, request different count of images dependent on selected present mode
+ if (min_image_count == 0)
+ min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd->PresentMode);
+
+ // Create Swapchain
+ {
+ VkSwapchainCreateInfoKHR info = {};
+ info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ info.surface = wd->Surface;
+ info.minImageCount = min_image_count;
+ info.imageFormat = wd->SurfaceFormat.format;
+ info.imageColorSpace = wd->SurfaceFormat.colorSpace;
+ info.imageArrayLayers = 1;
+ info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family
+ info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ info.presentMode = wd->PresentMode;
+ info.clipped = VK_TRUE;
+ info.oldSwapchain = old_swapchain;
+ VkSurfaceCapabilitiesKHR cap;
+ err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
+ check_vk_result(err);
+ if (info.minImageCount < cap.minImageCount)
+ info.minImageCount = cap.minImageCount;
+ else if (cap.maxImageCount != 0 && info.minImageCount > cap.maxImageCount)
+ info.minImageCount = cap.maxImageCount;
+
+ if (cap.currentExtent.width == 0xffffffff)
+ {
+ info.imageExtent.width = wd->Width = w;
+ info.imageExtent.height = wd->Height = h;
+ }
+ else
+ {
+ info.imageExtent.width = wd->Width = cap.currentExtent.width;
+ info.imageExtent.height = wd->Height = cap.currentExtent.height;
+ }
+ err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
+ check_vk_result(err);
+ err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL);
+ check_vk_result(err);
+ VkImage backbuffers[16] = {};
+ IM_ASSERT(wd->ImageCount >= min_image_count);
+ IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));
+ err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
+ check_vk_result(err);
+
+ IM_ASSERT(wd->Frames == NULL);
+ wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
+ wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);
+ memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
+ memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount);
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
+ wd->Frames[i].Backbuffer = backbuffers[i];
+ }
+ if (old_swapchain)
+ vkDestroySwapchainKHR(device, old_swapchain, allocator);
+
+ // Create the Render Pass
+ {
+ VkAttachmentDescription attachment = {};
+ attachment.format = wd->SurfaceFormat.format;
+ attachment.samples = VK_SAMPLE_COUNT_1_BIT;
+ attachment.loadOp = wd->ClearEnable ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ VkAttachmentReference color_attachment = {};
+ color_attachment.attachment = 0;
+ color_attachment.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ VkSubpassDescription subpass = {};
+ subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subpass.colorAttachmentCount = 1;
+ subpass.pColorAttachments = &color_attachment;
+ VkSubpassDependency dependency = {};
+ dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
+ dependency.dstSubpass = 0;
+ dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ dependency.srcAccessMask = 0;
+ dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ VkRenderPassCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ info.attachmentCount = 1;
+ info.pAttachments = &attachment;
+ info.subpassCount = 1;
+ info.pSubpasses = &subpass;
+ info.dependencyCount = 1;
+ info.pDependencies = &dependency;
+ err = vkCreateRenderPass(device, &info, allocator, &wd->RenderPass);
+ check_vk_result(err);
+
+ // We do not create a pipeline by default as this is also used by examples' main.cpp,
+ // but secondary viewport in multi-viewport mode may want to create one with:
+ //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass);
+ }
+
+ // Create The Image Views
+ {
+ VkImageViewCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ info.format = wd->SurfaceFormat.format;
+ info.components.r = VK_COMPONENT_SWIZZLE_R;
+ info.components.g = VK_COMPONENT_SWIZZLE_G;
+ info.components.b = VK_COMPONENT_SWIZZLE_B;
+ info.components.a = VK_COMPONENT_SWIZZLE_A;
+ VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
+ info.subresourceRange = image_range;
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
+ {
+ ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
+ info.image = fd->Backbuffer;
+ err = vkCreateImageView(device, &info, allocator, &fd->BackbufferView);
+ check_vk_result(err);
+ }
+ }
+
+ // Create Framebuffer
+ {
+ VkImageView attachment[1];
+ VkFramebufferCreateInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ info.renderPass = wd->RenderPass;
+ info.attachmentCount = 1;
+ info.pAttachments = attachment;
+ info.width = wd->Width;
+ info.height = wd->Height;
+ info.layers = 1;
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
+ {
+ ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
+ attachment[0] = fd->BackbufferView;
+ err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer);
+ check_vk_result(err);
+ }
+ }
+}
+
+// Create or resize window
+void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
+{
+ IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
+ (void)instance;
+ ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
+ ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
+}
+
+void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
+{
+ vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
+ //vkQueueWaitIdle(bd->Queue);
+
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
+ {
+ ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
+ ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
+ }
+ IM_FREE(wd->Frames);
+ IM_FREE(wd->FrameSemaphores);
+ wd->Frames = NULL;
+ wd->FrameSemaphores = NULL;
+ vkDestroyPipeline(device, wd->Pipeline, allocator);
+ vkDestroyRenderPass(device, wd->RenderPass, allocator);
+ vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
+ vkDestroySurfaceKHR(instance, wd->Surface, allocator);
+
+ *wd = ImGui_ImplVulkanH_Window();
+}
+
+void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)
+{
+ vkDestroyFence(device, fd->Fence, allocator);
+ vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
+ vkDestroyCommandPool(device, fd->CommandPool, allocator);
+ fd->Fence = VK_NULL_HANDLE;
+ fd->CommandBuffer = VK_NULL_HANDLE;
+ fd->CommandPool = VK_NULL_HANDLE;
+
+ vkDestroyImageView(device, fd->BackbufferView, allocator);
+ vkDestroyFramebuffer(device, fd->Framebuffer, allocator);
+}
+
+void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator)
+{
+ vkDestroySemaphore(device, fsd->ImageAcquiredSemaphore, allocator);
+ vkDestroySemaphore(device, fsd->RenderCompleteSemaphore, allocator);
+ fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE;
+}
+
+void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
+{
+ if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; }
+ if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; }
+ if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; }
+ if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; }
+ buffers->VertexBufferSize = 0;
+ buffers->IndexBufferSize = 0;
+}
+
+void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
+{
+ for (uint32_t n = 0; n < buffers->Count; n++)
+ ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
+ IM_FREE(buffers->FrameRenderBuffers);
+ buffers->FrameRenderBuffers = NULL;
+ buffers->Index = 0;
+ buffers->Count = 0;
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_vulkan.h b/Client/ThirdParty/imgui/backends/imgui_impl_vulkan.h
new file mode 100644
index 0000000..c770d0c
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_vulkan.h
@@ -0,0 +1,149 @@
+// dear imgui: Renderer Backend for Vulkan
+// This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
+
+// Implemented features:
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+// Missing features:
+// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
+// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
+
+// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
+// You will use those if you want to use this rendering backend in your engine/app.
+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
+// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
+// Read comments in imgui_impl_vulkan.h.
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+// [Configuration] in order to use a custom Vulkan function loader:
+// (1) You'll need to disable default Vulkan function prototypes.
+// We provide a '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' convenience configuration flag.
+// In order to make sure this is visible from the imgui_impl_vulkan.cpp compilation unit:
+// - Add '#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES' in your imconfig.h file
+// - Or as a compilation flag in your build system
+// - Or uncomment here (not recommended because you'd be modifying imgui sources!)
+// - Do not simply add it in a .cpp file!
+// (2) Call ImGui_ImplVulkan_LoadFunctions() before ImGui_ImplVulkan_Init() with your custom function.
+// If you have no idea what this is, leave it alone!
+//#define IMGUI_IMPL_VULKAN_NO_PROTOTYPES
+
+// Vulkan includes
+#if defined(IMGUI_IMPL_VULKAN_NO_PROTOTYPES) && !defined(VK_NO_PROTOTYPES)
+#define VK_NO_PROTOTYPES
+#endif
+#include <vulkan/vulkan.h>
+
+// Initialization data, for ImGui_ImplVulkan_Init()
+// [Please zero-clear before use!]
+struct ImGui_ImplVulkan_InitInfo
+{
+ VkInstance Instance;
+ VkPhysicalDevice PhysicalDevice;
+ VkDevice Device;
+ uint32_t QueueFamily;
+ VkQueue Queue;
+ VkPipelineCache PipelineCache;
+ VkDescriptorPool DescriptorPool;
+ uint32_t Subpass;
+ uint32_t MinImageCount; // >= 2
+ uint32_t ImageCount; // >= MinImageCount
+ VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT
+ const VkAllocationCallbacks* Allocator;
+ void (*CheckVkResultFn)(VkResult err);
+};
+
+// Called by user code
+IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
+IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
+IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
+IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
+IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
+
+// Optional: load Vulkan functions with a custom function loader
+// This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES
+IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = NULL);
+
+//-------------------------------------------------------------------------
+// Internal / Miscellaneous Vulkan Helpers
+// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
+//-------------------------------------------------------------------------
+// You probably do NOT need to use or care about those functions.
+// Those functions only exist because:
+// 1) they facilitate the readability and maintenance of the multiple main.cpp examples files.
+// 2) the upcoming multi-viewport feature will need them internally.
+// Generally we avoid exposing any kind of superfluous high-level helpers in the backends,
+// but it is too much code to duplicate everywhere so we exceptionally expose them.
+//
+// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
+// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
+// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
+//-------------------------------------------------------------------------
+
+struct ImGui_ImplVulkanH_Frame;
+struct ImGui_ImplVulkanH_Window;
+
+// Helpers
+IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
+IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
+IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
+IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
+IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
+
+// Helper structure to hold the data needed by one rendering frame
+// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
+// [Please zero-clear before use!]
+struct ImGui_ImplVulkanH_Frame
+{
+ VkCommandPool CommandPool;
+ VkCommandBuffer CommandBuffer;
+ VkFence Fence;
+ VkImage Backbuffer;
+ VkImageView BackbufferView;
+ VkFramebuffer Framebuffer;
+};
+
+struct ImGui_ImplVulkanH_FrameSemaphores
+{
+ VkSemaphore ImageAcquiredSemaphore;
+ VkSemaphore RenderCompleteSemaphore;
+};
+
+// Helper structure to hold the data needed by one rendering context into one OS window
+// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
+struct ImGui_ImplVulkanH_Window
+{
+ int Width;
+ int Height;
+ VkSwapchainKHR Swapchain;
+ VkSurfaceKHR Surface;
+ VkSurfaceFormatKHR SurfaceFormat;
+ VkPresentModeKHR PresentMode;
+ VkRenderPass RenderPass;
+ VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo
+ bool ClearEnable;
+ VkClearValue ClearValue;
+ uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
+ uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
+ uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
+ ImGui_ImplVulkanH_Frame* Frames;
+ ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;
+
+ ImGui_ImplVulkanH_Window()
+ {
+ memset(this, 0, sizeof(*this));
+ PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
+ ClearEnable = true;
+ }
+};
+
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_wgpu.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_wgpu.cpp
new file mode 100644
index 0000000..2f621ed
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_wgpu.cpp
@@ -0,0 +1,717 @@
+// dear imgui: Renderer for WebGPU
+// This needs to be used along with a Platform Binding (e.g. GLFW)
+// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-24: Fix for latest specs.
+// 2021-05-24: Add support for draw_data->FramebufferScale.
+// 2021-05-19: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
+// 2021-05-16: Update to latest WebGPU specs (compatible with Emscripten 2.0.20 and Chrome Canary 92).
+// 2021-02-18: Change blending equation to preserve alpha in output buffer.
+// 2021-01-28: Initial version.
+
+#include "imgui.h"
+#include "imgui_impl_wgpu.h"
+#include <limits.h>
+#include <webgpu/webgpu.h>
+
+#define HAS_EMSCRIPTEN_VERSION(major, minor, tiny) (__EMSCRIPTEN_major__ > (major) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ > (minor)) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ == (minor) && __EMSCRIPTEN_tiny__ >= (tiny)))
+
+#if defined(__EMSCRIPTEN__) && !HAS_EMSCRIPTEN_VERSION(2, 0, 20)
+#error "Requires at least emscripten 2.0.20"
+#endif
+
+// Dear ImGui prototypes from imgui_internal.h
+extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0);
+
+// WebGPU data
+static WGPUDevice g_wgpuDevice = NULL;
+static WGPUQueue g_defaultQueue = NULL;
+static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined;
+static WGPURenderPipeline g_pipelineState = NULL;
+
+struct RenderResources
+{
+ WGPUTexture FontTexture; // Font texture
+ WGPUTextureView FontTextureView; // Texture view for font texture
+ WGPUSampler Sampler; // Sampler for the font texture
+ WGPUBuffer Uniforms; // Shader uniforms
+ WGPUBindGroup CommonBindGroup; // Resources bind-group to bind the common resources to pipeline
+ ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
+ WGPUBindGroup ImageBindGroup; // Default font-resource of Dear ImGui
+ WGPUBindGroupLayout ImageBindGroupLayout; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
+};
+static RenderResources g_resources;
+
+struct FrameResources
+{
+ WGPUBuffer IndexBuffer;
+ WGPUBuffer VertexBuffer;
+ ImDrawIdx* IndexBufferHost;
+ ImDrawVert* VertexBufferHost;
+ int IndexBufferSize;
+ int VertexBufferSize;
+};
+static FrameResources* g_pFrameResources = NULL;
+static unsigned int g_numFramesInFlight = 0;
+static unsigned int g_frameIndex = UINT_MAX;
+
+struct Uniforms
+{
+ float MVP[4][4];
+};
+
+//-----------------------------------------------------------------------------
+// SHADERS
+//-----------------------------------------------------------------------------
+
+// glsl_shader.vert, compiled with:
+// # glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
+/*
+#version 450 core
+layout(location = 0) in vec2 aPos;
+layout(location = 1) in vec2 aUV;
+layout(location = 2) in vec4 aColor;
+layout(set=0, binding = 0) uniform transform { mat4 mvp; };
+
+out gl_PerVertex { vec4 gl_Position; };
+layout(location = 0) out struct { vec4 Color; vec2 UV; } Out;
+
+void main()
+{
+ Out.Color = aColor;
+ Out.UV = aUV;
+ gl_Position = mvp * vec4(aPos, 0, 1);
+}
+*/
+static uint32_t __glsl_shader_vert_spv[] =
+{
+ 0x07230203,0x00010000,0x00080007,0x0000002c,0x00000000,0x00020011,0x00000001,0x0006000b,
+ 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
+ 0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
+ 0x0000001b,0x00000023,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
+ 0x00000000,0x00030005,0x00000009,0x00000000,0x00050006,0x00000009,0x00000000,0x6f6c6f43,
+ 0x00000072,0x00040006,0x00000009,0x00000001,0x00005655,0x00030005,0x0000000b,0x0074754f,
+ 0x00040005,0x0000000f,0x6c6f4361,0x0000726f,0x00030005,0x00000015,0x00565561,0x00060005,
+ 0x00000019,0x505f6c67,0x65567265,0x78657472,0x00000000,0x00060006,0x00000019,0x00000000,
+ 0x505f6c67,0x7469736f,0x006e6f69,0x00030005,0x0000001b,0x00000000,0x00050005,0x0000001d,
+ 0x6e617274,0x726f6673,0x0000006d,0x00040006,0x0000001d,0x00000000,0x0070766d,0x00030005,
+ 0x0000001f,0x00000000,0x00040005,0x00000023,0x736f5061,0x00000000,0x00040047,0x0000000b,
+ 0x0000001e,0x00000000,0x00040047,0x0000000f,0x0000001e,0x00000002,0x00040047,0x00000015,
+ 0x0000001e,0x00000001,0x00050048,0x00000019,0x00000000,0x0000000b,0x00000000,0x00030047,
+ 0x00000019,0x00000002,0x00040048,0x0000001d,0x00000000,0x00000005,0x00050048,0x0000001d,
+ 0x00000000,0x00000023,0x00000000,0x00050048,0x0000001d,0x00000000,0x00000007,0x00000010,
+ 0x00030047,0x0000001d,0x00000002,0x00040047,0x0000001f,0x00000022,0x00000000,0x00040047,
+ 0x0000001f,0x00000021,0x00000000,0x00040047,0x00000023,0x0000001e,0x00000000,0x00020013,
+ 0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,0x00000006,0x00000020,0x00040017,
+ 0x00000007,0x00000006,0x00000004,0x00040017,0x00000008,0x00000006,0x00000002,0x0004001e,
+ 0x00000009,0x00000007,0x00000008,0x00040020,0x0000000a,0x00000003,0x00000009,0x0004003b,
+ 0x0000000a,0x0000000b,0x00000003,0x00040015,0x0000000c,0x00000020,0x00000001,0x0004002b,
+ 0x0000000c,0x0000000d,0x00000000,0x00040020,0x0000000e,0x00000001,0x00000007,0x0004003b,
+ 0x0000000e,0x0000000f,0x00000001,0x00040020,0x00000011,0x00000003,0x00000007,0x0004002b,
+ 0x0000000c,0x00000013,0x00000001,0x00040020,0x00000014,0x00000001,0x00000008,0x0004003b,
+ 0x00000014,0x00000015,0x00000001,0x00040020,0x00000017,0x00000003,0x00000008,0x0003001e,
+ 0x00000019,0x00000007,0x00040020,0x0000001a,0x00000003,0x00000019,0x0004003b,0x0000001a,
+ 0x0000001b,0x00000003,0x00040018,0x0000001c,0x00000007,0x00000004,0x0003001e,0x0000001d,
+ 0x0000001c,0x00040020,0x0000001e,0x00000002,0x0000001d,0x0004003b,0x0000001e,0x0000001f,
+ 0x00000002,0x00040020,0x00000020,0x00000002,0x0000001c,0x0004003b,0x00000014,0x00000023,
+ 0x00000001,0x0004002b,0x00000006,0x00000025,0x00000000,0x0004002b,0x00000006,0x00000026,
+ 0x3f800000,0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,
+ 0x0004003d,0x00000007,0x00000010,0x0000000f,0x00050041,0x00000011,0x00000012,0x0000000b,
+ 0x0000000d,0x0003003e,0x00000012,0x00000010,0x0004003d,0x00000008,0x00000016,0x00000015,
+ 0x00050041,0x00000017,0x00000018,0x0000000b,0x00000013,0x0003003e,0x00000018,0x00000016,
+ 0x00050041,0x00000020,0x00000021,0x0000001f,0x0000000d,0x0004003d,0x0000001c,0x00000022,
+ 0x00000021,0x0004003d,0x00000008,0x00000024,0x00000023,0x00050051,0x00000006,0x00000027,
+ 0x00000024,0x00000000,0x00050051,0x00000006,0x00000028,0x00000024,0x00000001,0x00070050,
+ 0x00000007,0x00000029,0x00000027,0x00000028,0x00000025,0x00000026,0x00050091,0x00000007,
+ 0x0000002a,0x00000022,0x00000029,0x00050041,0x00000011,0x0000002b,0x0000001b,0x0000000d,
+ 0x0003003e,0x0000002b,0x0000002a,0x000100fd,0x00010038
+};
+
+// glsl_shader.frag, compiled with:
+// # glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
+/*
+#version 450 core
+layout(location = 0) out vec4 fColor;
+layout(set=0, binding=1) uniform sampler s;
+layout(set=1, binding=0) uniform texture2D t;
+layout(location = 0) in struct { vec4 Color; vec2 UV; } In;
+void main()
+{
+ fColor = In.Color * texture(sampler2D(t, s), In.UV.st);
+}
+*/
+static uint32_t __glsl_shader_frag_spv[] =
+{
+ 0x07230203,0x00010000,0x00080007,0x00000023,0x00000000,0x00020011,0x00000001,0x0006000b,
+ 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
+ 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x00000009,0x0000000d,0x00030010,
+ 0x00000004,0x00000007,0x00030003,0x00000002,0x000001c2,0x00040005,0x00000004,0x6e69616d,
+ 0x00000000,0x00040005,0x00000009,0x6c6f4366,0x0000726f,0x00030005,0x0000000b,0x00000000,
+ 0x00050006,0x0000000b,0x00000000,0x6f6c6f43,0x00000072,0x00040006,0x0000000b,0x00000001,
+ 0x00005655,0x00030005,0x0000000d,0x00006e49,0x00030005,0x00000015,0x00000074,0x00030005,
+ 0x00000019,0x00000073,0x00040047,0x00000009,0x0000001e,0x00000000,0x00040047,0x0000000d,
+ 0x0000001e,0x00000000,0x00040047,0x00000015,0x00000022,0x00000001,0x00040047,0x00000015,
+ 0x00000021,0x00000000,0x00040047,0x00000019,0x00000022,0x00000000,0x00040047,0x00000019,
+ 0x00000021,0x00000001,0x00020013,0x00000002,0x00030021,0x00000003,0x00000002,0x00030016,
+ 0x00000006,0x00000020,0x00040017,0x00000007,0x00000006,0x00000004,0x00040020,0x00000008,
+ 0x00000003,0x00000007,0x0004003b,0x00000008,0x00000009,0x00000003,0x00040017,0x0000000a,
+ 0x00000006,0x00000002,0x0004001e,0x0000000b,0x00000007,0x0000000a,0x00040020,0x0000000c,
+ 0x00000001,0x0000000b,0x0004003b,0x0000000c,0x0000000d,0x00000001,0x00040015,0x0000000e,
+ 0x00000020,0x00000001,0x0004002b,0x0000000e,0x0000000f,0x00000000,0x00040020,0x00000010,
+ 0x00000001,0x00000007,0x00090019,0x00000013,0x00000006,0x00000001,0x00000000,0x00000000,
+ 0x00000000,0x00000001,0x00000000,0x00040020,0x00000014,0x00000000,0x00000013,0x0004003b,
+ 0x00000014,0x00000015,0x00000000,0x0002001a,0x00000017,0x00040020,0x00000018,0x00000000,
+ 0x00000017,0x0004003b,0x00000018,0x00000019,0x00000000,0x0003001b,0x0000001b,0x00000013,
+ 0x0004002b,0x0000000e,0x0000001d,0x00000001,0x00040020,0x0000001e,0x00000001,0x0000000a,
+ 0x00050036,0x00000002,0x00000004,0x00000000,0x00000003,0x000200f8,0x00000005,0x00050041,
+ 0x00000010,0x00000011,0x0000000d,0x0000000f,0x0004003d,0x00000007,0x00000012,0x00000011,
+ 0x0004003d,0x00000013,0x00000016,0x00000015,0x0004003d,0x00000017,0x0000001a,0x00000019,
+ 0x00050056,0x0000001b,0x0000001c,0x00000016,0x0000001a,0x00050041,0x0000001e,0x0000001f,
+ 0x0000000d,0x0000001d,0x0004003d,0x0000000a,0x00000020,0x0000001f,0x00050057,0x00000007,
+ 0x00000021,0x0000001c,0x00000020,0x00050085,0x00000007,0x00000022,0x00000012,0x00000021,
+ 0x0003003e,0x00000009,0x00000022,0x000100fd,0x00010038
+};
+
+static void SafeRelease(ImDrawIdx*& res)
+{
+ if (res)
+ delete[] res;
+ res = NULL;
+}
+static void SafeRelease(ImDrawVert*& res)
+{
+ if (res)
+ delete[] res;
+ res = NULL;
+}
+static void SafeRelease(WGPUBindGroupLayout& res)
+{
+ if (res)
+ wgpuBindGroupLayoutRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPUBindGroup& res)
+{
+ if (res)
+ wgpuBindGroupRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPUBuffer& res)
+{
+ if (res)
+ wgpuBufferRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPURenderPipeline& res)
+{
+ if (res)
+ wgpuRenderPipelineRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPUSampler& res)
+{
+ if (res)
+ wgpuSamplerRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPUShaderModule& res)
+{
+ if (res)
+ wgpuShaderModuleRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPUTextureView& res)
+{
+ if (res)
+ wgpuTextureViewRelease(res);
+ res = NULL;
+}
+static void SafeRelease(WGPUTexture& res)
+{
+ if (res)
+ wgpuTextureRelease(res);
+ res = NULL;
+}
+
+static void SafeRelease(RenderResources& res)
+{
+ SafeRelease(res.FontTexture);
+ SafeRelease(res.FontTextureView);
+ SafeRelease(res.Sampler);
+ SafeRelease(res.Uniforms);
+ SafeRelease(res.CommonBindGroup);
+ SafeRelease(res.ImageBindGroup);
+ SafeRelease(res.ImageBindGroupLayout);
+};
+
+static void SafeRelease(FrameResources& res)
+{
+ SafeRelease(res.IndexBuffer);
+ SafeRelease(res.VertexBuffer);
+ SafeRelease(res.IndexBufferHost);
+ SafeRelease(res.VertexBufferHost);
+}
+
+static WGPUProgrammableStageDescriptor ImGui_ImplWGPU_CreateShaderModule(uint32_t* binary_data, uint32_t binary_data_size)
+{
+ WGPUShaderModuleSPIRVDescriptor spirv_desc = {};
+ spirv_desc.chain.sType = WGPUSType_ShaderModuleSPIRVDescriptor;
+ spirv_desc.codeSize = binary_data_size;
+ spirv_desc.code = binary_data;
+
+ WGPUShaderModuleDescriptor desc = {};
+ desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&spirv_desc);
+
+ WGPUProgrammableStageDescriptor stage_desc = {};
+ stage_desc.module = wgpuDeviceCreateShaderModule(g_wgpuDevice, &desc);
+ stage_desc.entryPoint = "main";
+ return stage_desc;
+}
+
+static WGPUBindGroup ImGui_ImplWGPU_CreateImageBindGroup(WGPUBindGroupLayout layout, WGPUTextureView texture)
+{
+ WGPUBindGroupEntry image_bg_entries[] = { { nullptr, 0, 0, 0, 0, 0, texture } };
+
+ WGPUBindGroupDescriptor image_bg_descriptor = {};
+ image_bg_descriptor.layout = layout;
+ image_bg_descriptor.entryCount = sizeof(image_bg_entries) / sizeof(WGPUBindGroupEntry);
+ image_bg_descriptor.entries = image_bg_entries;
+ return wgpuDeviceCreateBindGroup(g_wgpuDevice, &image_bg_descriptor);
+}
+
+static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPassEncoder ctx, FrameResources* fr)
+{
+ // Setup orthographic projection matrix into our constant buffer
+ // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right).
+ {
+ float L = draw_data->DisplayPos.x;
+ float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
+ float T = draw_data->DisplayPos.y;
+ float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
+ float mvp[4][4] =
+ {
+ { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
+ { 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
+ { 0.0f, 0.0f, 0.5f, 0.0f },
+ { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
+ };
+ wgpuQueueWriteBuffer(g_defaultQueue, g_resources.Uniforms, 0, mvp, sizeof(mvp));
+ }
+
+ // Setup viewport
+ wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->FramebufferScale.x * draw_data->DisplaySize.x, draw_data->FramebufferScale.y * draw_data->DisplaySize.y, 0, 1);
+
+ // Bind shader and vertex buffers
+ wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, 0);
+ wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, 0);
+ wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState);
+ wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL);
+
+ // Setup blend factor
+ WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
+ wgpuRenderPassEncoderSetBlendConstant(ctx, &blend_color);
+}
+
+// Render function
+// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
+void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder)
+{
+ // Avoid rendering when minimized
+ if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
+ return;
+
+ // FIXME: Assuming that this only gets called once per frame!
+ // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator.
+ g_frameIndex = g_frameIndex + 1;
+ FrameResources* fr = &g_pFrameResources[g_frameIndex % g_numFramesInFlight];
+
+ // Create and grow vertex/index buffers if needed
+ if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
+ {
+ if (fr->VertexBuffer)
+ {
+ wgpuBufferDestroy(fr->VertexBuffer);
+ wgpuBufferRelease(fr->VertexBuffer);
+ }
+ SafeRelease(fr->VertexBufferHost);
+ fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
+
+ WGPUBufferDescriptor vb_desc =
+ {
+ NULL,
+ "Dear ImGui Vertex buffer",
+ WGPUBufferUsage_CopyDst | WGPUBufferUsage_Vertex,
+ fr->VertexBufferSize * sizeof(ImDrawVert),
+ false
+ };
+ fr->VertexBuffer = wgpuDeviceCreateBuffer(g_wgpuDevice, &vb_desc);
+ if (!fr->VertexBuffer)
+ return;
+
+ fr->VertexBufferHost = new ImDrawVert[fr->VertexBufferSize];
+ }
+ if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
+ {
+ if (fr->IndexBuffer)
+ {
+ wgpuBufferDestroy(fr->IndexBuffer);
+ wgpuBufferRelease(fr->IndexBuffer);
+ }
+ SafeRelease(fr->IndexBufferHost);
+ fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
+
+ WGPUBufferDescriptor ib_desc =
+ {
+ NULL,
+ "Dear ImGui Index buffer",
+ WGPUBufferUsage_CopyDst | WGPUBufferUsage_Index,
+ fr->IndexBufferSize * sizeof(ImDrawIdx),
+ false
+ };
+ fr->IndexBuffer = wgpuDeviceCreateBuffer(g_wgpuDevice, &ib_desc);
+ if (!fr->IndexBuffer)
+ return;
+
+ fr->IndexBufferHost = new ImDrawIdx[fr->IndexBufferSize];
+ }
+
+ // Upload vertex/index data into a single contiguous GPU buffer
+ ImDrawVert* vtx_dst = (ImDrawVert*)fr->VertexBufferHost;
+ ImDrawIdx* idx_dst = (ImDrawIdx*)fr->IndexBufferHost;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
+ memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
+ vtx_dst += cmd_list->VtxBuffer.Size;
+ idx_dst += cmd_list->IdxBuffer.Size;
+ }
+ int64_t vb_write_size = ((char*)vtx_dst - (char*)fr->VertexBufferHost + 3) & ~3;
+ int64_t ib_write_size = ((char*)idx_dst - (char*)fr->IndexBufferHost + 3) & ~3;
+ wgpuQueueWriteBuffer(g_defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
+ wgpuQueueWriteBuffer(g_defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
+
+ // Setup desired render state
+ ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
+
+ // Render command lists
+ // (Because we merged all buffers into a single one, we maintain our own offset into them)
+ int global_vtx_offset = 0;
+ int global_idx_offset = 0;
+ ImVec2 clip_scale = draw_data->FramebufferScale;
+ ImVec2 clip_off = draw_data->DisplayPos;
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback != NULL)
+ {
+ // User callback, registered via ImDrawList::AddCallback()
+ // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
+ if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
+ ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
+ else
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // Bind custom texture
+ ImTextureID tex_id = pcmd->GetTexID();
+ ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id));
+ auto bind_group = g_resources.ImageBindGroups.GetVoidPtr(tex_id_hash);
+ if (bind_group)
+ {
+ wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, NULL);
+ }
+ else
+ {
+ WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(g_resources.ImageBindGroupLayout, (WGPUTextureView)tex_id);
+ g_resources.ImageBindGroups.SetVoidPtr(tex_id_hash, image_bind_group);
+ wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, NULL);
+ }
+
+ // Project scissor/clipping rectangles into framebuffer space
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+ if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
+ continue;
+
+ // Apply scissor/clipping rectangle, Draw
+ wgpuRenderPassEncoderSetScissorRect(pass_encoder, (uint32_t)clip_min.x, (uint32_t)clip_min.y, (uint32_t)(clip_max.x - clip_min.x), (uint32_t)(clip_max.y - clip_min.y));
+ wgpuRenderPassEncoderDrawIndexed(pass_encoder, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
+ }
+ }
+ global_idx_offset += cmd_list->IdxBuffer.Size;
+ global_vtx_offset += cmd_list->VtxBuffer.Size;
+ }
+}
+
+static void ImGui_ImplWGPU_CreateFontsTexture()
+{
+ // Build texture atlas
+ ImGuiIO& io = ImGui::GetIO();
+ unsigned char* pixels;
+ int width, height, size_pp;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &size_pp);
+
+ // Upload texture to graphics system
+ {
+ WGPUTextureDescriptor tex_desc = {};
+ tex_desc.label = "Dear ImGui Font Texture";
+ tex_desc.dimension = WGPUTextureDimension_2D;
+ tex_desc.size.width = width;
+ tex_desc.size.height = height;
+ tex_desc.size.depthOrArrayLayers = 1;
+ tex_desc.sampleCount = 1;
+ tex_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ tex_desc.mipLevelCount = 1;
+ tex_desc.usage = WGPUTextureUsage_CopyDst | WGPUTextureUsage_TextureBinding;
+ g_resources.FontTexture = wgpuDeviceCreateTexture(g_wgpuDevice, &tex_desc);
+
+ WGPUTextureViewDescriptor tex_view_desc = {};
+ tex_view_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ tex_view_desc.dimension = WGPUTextureViewDimension_2D;
+ tex_view_desc.baseMipLevel = 0;
+ tex_view_desc.mipLevelCount = 1;
+ tex_view_desc.baseArrayLayer = 0;
+ tex_view_desc.arrayLayerCount = 1;
+ tex_view_desc.aspect = WGPUTextureAspect_All;
+ g_resources.FontTextureView = wgpuTextureCreateView(g_resources.FontTexture, &tex_view_desc);
+ }
+
+ // Upload texture data
+ {
+ WGPUImageCopyTexture dst_view = {};
+ dst_view.texture = g_resources.FontTexture;
+ dst_view.mipLevel = 0;
+ dst_view.origin = { 0, 0, 0 };
+ dst_view.aspect = WGPUTextureAspect_All;
+ WGPUTextureDataLayout layout = {};
+ layout.offset = 0;
+ layout.bytesPerRow = width * size_pp;
+ layout.rowsPerImage = height;
+ WGPUExtent3D size = { (uint32_t)width, (uint32_t)height, 1 };
+ wgpuQueueWriteTexture(g_defaultQueue, &dst_view, pixels, (uint32_t)(width * size_pp * height), &layout, &size);
+ }
+
+ // Create the associated sampler
+ {
+ WGPUSamplerDescriptor sampler_desc = {};
+ sampler_desc.minFilter = WGPUFilterMode_Linear;
+ sampler_desc.magFilter = WGPUFilterMode_Linear;
+ sampler_desc.mipmapFilter = WGPUFilterMode_Linear;
+ sampler_desc.addressModeU = WGPUAddressMode_Repeat;
+ sampler_desc.addressModeV = WGPUAddressMode_Repeat;
+ sampler_desc.addressModeW = WGPUAddressMode_Repeat;
+ sampler_desc.maxAnisotropy = 1;
+ g_resources.Sampler = wgpuDeviceCreateSampler(g_wgpuDevice, &sampler_desc);
+ }
+
+ // Store our identifier
+ static_assert(sizeof(ImTextureID) >= sizeof(g_resources.FontTexture), "Can't pack descriptor handle into TexID, 32-bit not supported yet.");
+ io.Fonts->SetTexID((ImTextureID)g_resources.FontTextureView);
+}
+
+static void ImGui_ImplWGPU_CreateUniformBuffer()
+{
+ WGPUBufferDescriptor ub_desc =
+ {
+ NULL,
+ "Dear ImGui Uniform buffer",
+ WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform,
+ sizeof(Uniforms),
+ false
+ };
+ g_resources.Uniforms = wgpuDeviceCreateBuffer(g_wgpuDevice, &ub_desc);
+}
+
+bool ImGui_ImplWGPU_CreateDeviceObjects()
+{
+ if (!g_wgpuDevice)
+ return false;
+ if (g_pipelineState)
+ ImGui_ImplWGPU_InvalidateDeviceObjects();
+
+ // Create render pipeline
+ WGPURenderPipelineDescriptor graphics_pipeline_desc = {};
+ graphics_pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
+ graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
+ graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW;
+ graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None;
+ graphics_pipeline_desc.multisample.count = 1;
+ graphics_pipeline_desc.multisample.mask = UINT_MAX;
+ graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false;
+ graphics_pipeline_desc.layout = nullptr; // Use automatic layout generation
+
+ // Create the vertex shader
+ WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_vert_spv, sizeof(__glsl_shader_vert_spv) / sizeof(uint32_t));
+ graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
+ graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
+
+ // Vertex input configuration
+ WGPUVertexAttribute attribute_desc[] =
+ {
+ { WGPUVertexFormat_Float32x2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 },
+ { WGPUVertexFormat_Float32x2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 },
+ { WGPUVertexFormat_Unorm8x4, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 },
+ };
+
+ WGPUVertexBufferLayout buffer_layouts[1];
+ buffer_layouts[0].arrayStride = sizeof(ImDrawVert);
+ buffer_layouts[0].stepMode = WGPUVertexStepMode_Vertex;
+ buffer_layouts[0].attributeCount = 3;
+ buffer_layouts[0].attributes = attribute_desc;
+
+ graphics_pipeline_desc.vertex.bufferCount = 1;
+ graphics_pipeline_desc.vertex.buffers = buffer_layouts;
+
+ // Create the pixel shader
+ WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_frag_spv, sizeof(__glsl_shader_frag_spv) / sizeof(uint32_t));
+
+ // Create the blending setup
+ WGPUBlendState blend_state = {};
+ blend_state.alpha.operation = WGPUBlendOperation_Add;
+ blend_state.alpha.srcFactor = WGPUBlendFactor_One;
+ blend_state.alpha.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
+ blend_state.color.operation = WGPUBlendOperation_Add;
+ blend_state.color.srcFactor = WGPUBlendFactor_SrcAlpha;
+ blend_state.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
+
+ WGPUColorTargetState color_state = {};
+ color_state.format = g_renderTargetFormat;
+ color_state.blend = &blend_state;
+ color_state.writeMask = WGPUColorWriteMask_All;
+
+ WGPUFragmentState fragment_state = {};
+ fragment_state.module = pixel_shader_desc.module;
+ fragment_state.entryPoint = pixel_shader_desc.entryPoint;
+ fragment_state.targetCount = 1;
+ fragment_state.targets = &color_state;
+
+ graphics_pipeline_desc.fragment = &fragment_state;
+
+ // Create depth-stencil State
+ WGPUDepthStencilState depth_stencil_state = {};
+ depth_stencil_state.depthBias = 0;
+ depth_stencil_state.depthBiasClamp = 0;
+ depth_stencil_state.depthBiasSlopeScale = 0;
+
+ // Configure disabled depth-stencil state
+ graphics_pipeline_desc.depthStencil = nullptr;
+
+ g_pipelineState = wgpuDeviceCreateRenderPipeline(g_wgpuDevice, &graphics_pipeline_desc);
+
+ ImGui_ImplWGPU_CreateFontsTexture();
+ ImGui_ImplWGPU_CreateUniformBuffer();
+
+ // Create resource bind group
+ WGPUBindGroupLayout bg_layouts[2];
+ bg_layouts[0] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 0);
+ bg_layouts[1] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 1);
+
+ WGPUBindGroupEntry common_bg_entries[] =
+ {
+ { nullptr, 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 },
+ { nullptr, 1, 0, 0, 0, g_resources.Sampler, 0 },
+ };
+
+ WGPUBindGroupDescriptor common_bg_descriptor = {};
+ common_bg_descriptor.layout = bg_layouts[0];
+ common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry);
+ common_bg_descriptor.entries = common_bg_entries;
+ g_resources.CommonBindGroup = wgpuDeviceCreateBindGroup(g_wgpuDevice, &common_bg_descriptor);
+
+ WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], g_resources.FontTextureView);
+ g_resources.ImageBindGroup = image_bind_group;
+ g_resources.ImageBindGroupLayout = bg_layouts[1];
+ g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&g_resources.FontTextureView, sizeof(ImTextureID)), image_bind_group);
+
+ SafeRelease(vertex_shader_desc.module);
+ SafeRelease(pixel_shader_desc.module);
+ SafeRelease(bg_layouts[0]);
+
+ return true;
+}
+
+void ImGui_ImplWGPU_InvalidateDeviceObjects()
+{
+ if (!g_wgpuDevice)
+ return;
+
+ SafeRelease(g_pipelineState);
+ SafeRelease(g_resources);
+
+ ImGuiIO& io = ImGui::GetIO();
+ io.Fonts->SetTexID(NULL); // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
+
+ for (unsigned int i = 0; i < g_numFramesInFlight; i++)
+ SafeRelease(g_pFrameResources[i]);
+}
+
+bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format)
+{
+ // Setup backend capabilities flags
+ ImGuiIO& io = ImGui::GetIO();
+ io.BackendRendererName = "imgui_impl_webgpu";
+ io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
+
+ g_wgpuDevice = device;
+ g_defaultQueue = wgpuDeviceGetQueue(g_wgpuDevice);
+ g_renderTargetFormat = rt_format;
+ g_pFrameResources = new FrameResources[num_frames_in_flight];
+ g_numFramesInFlight = num_frames_in_flight;
+ g_frameIndex = UINT_MAX;
+
+ g_resources.FontTexture = NULL;
+ g_resources.FontTextureView = NULL;
+ g_resources.Sampler = NULL;
+ g_resources.Uniforms = NULL;
+ g_resources.CommonBindGroup = NULL;
+ g_resources.ImageBindGroups.Data.reserve(100);
+ g_resources.ImageBindGroup = NULL;
+ g_resources.ImageBindGroupLayout = NULL;
+
+ // Create buffers with a default size (they will later be grown as needed)
+ for (int i = 0; i < num_frames_in_flight; i++)
+ {
+ FrameResources* fr = &g_pFrameResources[i];
+ fr->IndexBuffer = NULL;
+ fr->VertexBuffer = NULL;
+ fr->IndexBufferHost = NULL;
+ fr->VertexBufferHost = NULL;
+ fr->IndexBufferSize = 10000;
+ fr->VertexBufferSize = 5000;
+ }
+
+ return true;
+}
+
+void ImGui_ImplWGPU_Shutdown()
+{
+ ImGui_ImplWGPU_InvalidateDeviceObjects();
+ delete[] g_pFrameResources;
+ g_pFrameResources = NULL;
+ wgpuQueueRelease(g_defaultQueue);
+ g_wgpuDevice = NULL;
+ g_numFramesInFlight = 0;
+ g_frameIndex = UINT_MAX;
+}
+
+void ImGui_ImplWGPU_NewFrame()
+{
+ if (!g_pipelineState)
+ ImGui_ImplWGPU_CreateDeviceObjects();
+}
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_wgpu.h b/Client/ThirdParty/imgui/backends/imgui_impl_wgpu.h
new file mode 100644
index 0000000..ec10768
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_wgpu.h
@@ -0,0 +1,25 @@
+// dear imgui: Renderer for WebGPU
+// This needs to be used along with a Platform Binding (e.g. GLFW)
+// (Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.)
+
+// Implemented features:
+// [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID!
+// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+#include <webgpu/webgpu.h>
+
+IMGUI_IMPL_API bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextureFormat rt_format);
+IMGUI_IMPL_API void ImGui_ImplWGPU_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplWGPU_NewFrame();
+IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder pass_encoder);
+
+// Use if you want to reset your rendering device without losing Dear ImGui state.
+IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects();
+IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects();
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_win32.cpp b/Client/ThirdParty/imgui/backends/imgui_impl_win32.cpp
new file mode 100644
index 0000000..51fb470
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_win32.cpp
@@ -0,0 +1,616 @@
+// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
+// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
+
+// Implemented features:
+// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
+// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_win32.h"
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <tchar.h>
+#include <dwmapi.h>
+
+// Configuration flags to add in your imconfig.h file:
+//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant.
+
+// Using XInput for gamepad (will load DLL dynamically)
+#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+#include <xinput.h>
+typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
+typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
+#endif
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
+// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host windo doesn't have focus.
+// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
+// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
+// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
+// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
+// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
+// 2021-01-25: Inputs: Dynamically loading XInput DLL.
+// 2020-12-04: Misc: Fixed setting of io.DisplaySize to invalid/uninitialized data when after hwnd has been closed.
+// 2020-03-03: Inputs: Calling AddInputCharacterUTF16() to support surrogate pairs leading to codepoint >= 0x10000 (for more complete CJK inputs)
+// 2020-02-17: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(), ImGui_ImplWin32_GetDpiScaleForMonitor() helper functions.
+// 2020-01-14: Inputs: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD/IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT.
+// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
+// 2019-05-11: Inputs: Don't filter value from WM_CHAR before calling AddInputCharacter().
+// 2019-01-17: Misc: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created in a different thread or parent.
+// 2019-01-17: Inputs: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages.
+// 2019-01-15: Inputs: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is set by user application).
+// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
+// 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor.
+// 2018-06-10: Inputs: Fixed handling of mouse wheel messages to support fine position messages (typically sent by track-pads).
+// 2018-06-08: Misc: Extracted imgui_impl_win32.cpp/.h away from the old combined DX9/DX10/DX11/DX12 examples.
+// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
+// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
+// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
+// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set).
+// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
+// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support.
+// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert.
+// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag.
+// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read.
+// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging.
+// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set.
+
+struct ImGui_ImplWin32_Data
+{
+ HWND hWnd;
+ HWND MouseHwnd;
+ bool MouseTracked;
+ INT64 Time;
+ INT64 TicksPerSecond;
+ ImGuiMouseCursor LastMouseCursor;
+ bool HasGamepad;
+ bool WantUpdateHasGamepad;
+
+#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+ HMODULE XInputDLL;
+ PFN_XInputGetCapabilities XInputGetCapabilities;
+ PFN_XInputGetState XInputGetState;
+#endif
+
+ ImGui_ImplWin32_Data() { memset(this, 0, sizeof(*this)); }
+};
+
+// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not well tested and probably dysfunctional in this backend.
+// FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context.
+static ImGui_ImplWin32_Data* ImGui_ImplWin32_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplWin32_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
+}
+
+// Functions
+bool ImGui_ImplWin32_Init(void* hwnd)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
+
+ INT64 perf_frequency, perf_counter;
+ if (!::QueryPerformanceFrequency((LARGE_INTEGER*)&perf_frequency))
+ return false;
+ if (!::QueryPerformanceCounter((LARGE_INTEGER*)&perf_counter))
+ return false;
+
+ // Setup backend capabilities flags
+ ImGui_ImplWin32_Data* bd = IM_NEW(ImGui_ImplWin32_Data)();
+ io.BackendPlatformUserData = (void*)bd;
+ io.BackendPlatformName = "imgui_impl_win32";
+ io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional)
+ io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
+
+ bd->hWnd = (HWND)hwnd;
+ bd->WantUpdateHasGamepad = true;
+ bd->TicksPerSecond = perf_frequency;
+ bd->Time = perf_counter;
+ bd->LastMouseCursor = ImGuiMouseCursor_COUNT;
+
+ io.ImeWindowHandle = hwnd;
+
+ // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime.
+ io.KeyMap[ImGuiKey_Tab] = VK_TAB;
+ io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
+ io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
+ io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
+ io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
+ io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR;
+ io.KeyMap[ImGuiKey_PageDown] = VK_NEXT;
+ io.KeyMap[ImGuiKey_Home] = VK_HOME;
+ io.KeyMap[ImGuiKey_End] = VK_END;
+ io.KeyMap[ImGuiKey_Insert] = VK_INSERT;
+ io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
+ io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
+ io.KeyMap[ImGuiKey_Space] = VK_SPACE;
+ io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
+ io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
+ io.KeyMap[ImGuiKey_KeyPadEnter] = VK_RETURN;
+ io.KeyMap[ImGuiKey_A] = 'A';
+ io.KeyMap[ImGuiKey_C] = 'C';
+ io.KeyMap[ImGuiKey_V] = 'V';
+ io.KeyMap[ImGuiKey_X] = 'X';
+ io.KeyMap[ImGuiKey_Y] = 'Y';
+ io.KeyMap[ImGuiKey_Z] = 'Z';
+
+ // Dynamically load XInput library
+#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+ const char* xinput_dll_names[] =
+ {
+ "xinput1_4.dll", // Windows 8+
+ "xinput1_3.dll", // DirectX SDK
+ "xinput9_1_0.dll", // Windows Vista, Windows 7
+ "xinput1_2.dll", // DirectX SDK
+ "xinput1_1.dll" // DirectX SDK
+ };
+ for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
+ if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
+ {
+ bd->XInputDLL = dll;
+ bd->XInputGetCapabilities = (PFN_XInputGetCapabilities)::GetProcAddress(dll, "XInputGetCapabilities");
+ bd->XInputGetState = (PFN_XInputGetState)::GetProcAddress(dll, "XInputGetState");
+ break;
+ }
+#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+
+ return true;
+}
+
+void ImGui_ImplWin32_Shutdown()
+{
+ ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+ IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Unload XInput library
+#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+ if (bd->XInputDLL)
+ ::FreeLibrary(bd->XInputDLL);
+#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+
+ io.BackendPlatformName = NULL;
+ io.BackendPlatformUserData = NULL;
+ IM_DELETE(bd);
+}
+
+static bool ImGui_ImplWin32_UpdateMouseCursor()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
+ return false;
+
+ ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
+ if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor)
+ {
+ // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
+ ::SetCursor(NULL);
+ }
+ else
+ {
+ // Show OS mouse cursor
+ LPTSTR win32_cursor = IDC_ARROW;
+ switch (imgui_cursor)
+ {
+ case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break;
+ case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break;
+ case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break;
+ case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break;
+ case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break;
+ case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break;
+ case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break;
+ case ImGuiMouseCursor_Hand: win32_cursor = IDC_HAND; break;
+ case ImGuiMouseCursor_NotAllowed: win32_cursor = IDC_NO; break;
+ }
+ ::SetCursor(::LoadCursor(NULL, win32_cursor));
+ }
+ return true;
+}
+
+static void ImGui_ImplWin32_UpdateMousePos()
+{
+ ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+ ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(bd->hWnd != 0);
+
+ const ImVec2 mouse_pos_prev = io.MousePos;
+ io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+
+ // Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
+ HWND focused_window = ::GetForegroundWindow();
+ HWND hovered_window = bd->MouseHwnd;
+ HWND mouse_window = NULL;
+ if (hovered_window && (hovered_window == bd->hWnd || ::IsChild(hovered_window, bd->hWnd)))
+ mouse_window = hovered_window;
+ else if (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd)))
+ mouse_window = focused_window;
+ if (mouse_window == NULL)
+ return;
+
+ // Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
+ if (io.WantSetMousePos)
+ {
+ POINT pos = { (int)mouse_pos_prev.x, (int)mouse_pos_prev.y };
+ if (::ClientToScreen(bd->hWnd, &pos))
+ ::SetCursorPos(pos.x, pos.y);
+ }
+
+ // Set Dear ImGui mouse position from OS position
+ POINT pos;
+ if (::GetCursorPos(&pos) && ::ScreenToClient(mouse_window, &pos))
+ io.MousePos = ImVec2((float)pos.x, (float)pos.y);
+}
+
+// Gamepad navigation mapping
+static void ImGui_ImplWin32_UpdateGamepads()
+{
+#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+ memset(io.NavInputs, 0, sizeof(io.NavInputs));
+ if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
+ return;
+
+ // Calling XInputGetState() every frame on disconnected gamepads is unfortunately too slow.
+ // Instead we refresh gamepad availability by calling XInputGetCapabilities() _only_ after receiving WM_DEVICECHANGE.
+ if (bd->WantUpdateHasGamepad)
+ {
+ XINPUT_CAPABILITIES caps;
+ bd->HasGamepad = bd->XInputGetCapabilities ? (bd->XInputGetCapabilities(0, XINPUT_FLAG_GAMEPAD, &caps) == ERROR_SUCCESS) : false;
+ bd->WantUpdateHasGamepad = false;
+ }
+
+ io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
+ XINPUT_STATE xinput_state;
+ if (bd->HasGamepad && bd->XInputGetState && bd->XInputGetState(0, &xinput_state) == ERROR_SUCCESS)
+ {
+ const XINPUT_GAMEPAD& gamepad = xinput_state.Gamepad;
+ io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
+
+ #define MAP_BUTTON(NAV_NO, BUTTON_ENUM) { io.NavInputs[NAV_NO] = (gamepad.wButtons & BUTTON_ENUM) ? 1.0f : 0.0f; }
+ #define MAP_ANALOG(NAV_NO, VALUE, V0, V1) { float vn = (float)(VALUE - V0) / (float)(V1 - V0); if (vn > 1.0f) vn = 1.0f; if (vn > 0.0f && io.NavInputs[NAV_NO] < vn) io.NavInputs[NAV_NO] = vn; }
+ MAP_BUTTON(ImGuiNavInput_Activate, XINPUT_GAMEPAD_A); // Cross / A
+ MAP_BUTTON(ImGuiNavInput_Cancel, XINPUT_GAMEPAD_B); // Circle / B
+ MAP_BUTTON(ImGuiNavInput_Menu, XINPUT_GAMEPAD_X); // Square / X
+ MAP_BUTTON(ImGuiNavInput_Input, XINPUT_GAMEPAD_Y); // Triangle / Y
+ MAP_BUTTON(ImGuiNavInput_DpadLeft, XINPUT_GAMEPAD_DPAD_LEFT); // D-Pad Left
+ MAP_BUTTON(ImGuiNavInput_DpadRight, XINPUT_GAMEPAD_DPAD_RIGHT); // D-Pad Right
+ MAP_BUTTON(ImGuiNavInput_DpadUp, XINPUT_GAMEPAD_DPAD_UP); // D-Pad Up
+ MAP_BUTTON(ImGuiNavInput_DpadDown, XINPUT_GAMEPAD_DPAD_DOWN); // D-Pad Down
+ MAP_BUTTON(ImGuiNavInput_FocusPrev, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_FocusNext, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
+ MAP_BUTTON(ImGuiNavInput_TweakSlow, XINPUT_GAMEPAD_LEFT_SHOULDER); // L1 / LB
+ MAP_BUTTON(ImGuiNavInput_TweakFast, XINPUT_GAMEPAD_RIGHT_SHOULDER); // R1 / RB
+ MAP_ANALOG(ImGuiNavInput_LStickLeft, gamepad.sThumbLX, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32768);
+ MAP_ANALOG(ImGuiNavInput_LStickRight, gamepad.sThumbLX, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
+ MAP_ANALOG(ImGuiNavInput_LStickUp, gamepad.sThumbLY, +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, +32767);
+ MAP_ANALOG(ImGuiNavInput_LStickDown, gamepad.sThumbLY, -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, -32767);
+ #undef MAP_BUTTON
+ #undef MAP_ANALOG
+ }
+#endif // #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
+}
+
+void ImGui_ImplWin32_NewFrame()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWin32_Init()?");
+
+ // Setup display size (every frame to accommodate for window resizing)
+ RECT rect = { 0, 0, 0, 0 };
+ ::GetClientRect(bd->hWnd, &rect);
+ io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
+
+ // Setup time step
+ INT64 current_time = 0;
+ ::QueryPerformanceCounter((LARGE_INTEGER*)&current_time);
+ io.DeltaTime = (float)(current_time - bd->Time) / bd->TicksPerSecond;
+ bd->Time = current_time;
+
+ // Update OS mouse position
+ ImGui_ImplWin32_UpdateMousePos();
+
+ // Update OS mouse cursor with the cursor requested by imgui
+ ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor();
+ if (bd->LastMouseCursor != mouse_cursor)
+ {
+ bd->LastMouseCursor = mouse_cursor;
+ ImGui_ImplWin32_UpdateMouseCursor();
+ }
+
+ // Update game controllers (if enabled and available)
+ ImGui_ImplWin32_UpdateGamepads();
+}
+
+// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions.
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif
+#ifndef DBT_DEVNODES_CHANGED
+#define DBT_DEVNODES_CHANGED 0x0007
+#endif
+
+// Win32 message handler (process Win32 mouse/keyboard inputs, etc.)
+// Call from your application's message handler.
+// When implementing your own backend, you can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if Dear ImGui wants to use your inputs.
+// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+// Generally you may always pass all inputs to Dear ImGui, and hide them from your application based on those two flags.
+// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinates when dragging mouse outside of our window bounds.
+// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag.
+#if 0
+// Copy this line into your .cpp file to forward declare the function.
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+#endif
+IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (ImGui::GetCurrentContext() == NULL)
+ return 0;
+
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
+
+ switch (msg)
+ {
+ case WM_MOUSEMOVE:
+ // We need to call TrackMouseEvent in order to receive WM_MOUSELEAVE events
+ bd->MouseHwnd = hwnd;
+ if (!bd->MouseTracked)
+ {
+ TRACKMOUSEEVENT tme = { sizeof(tme), TME_LEAVE, hwnd, 0 };
+ ::TrackMouseEvent(&tme);
+ bd->MouseTracked = true;
+ }
+ break;
+ case WM_MOUSELEAVE:
+ if (bd->MouseHwnd == hwnd)
+ bd->MouseHwnd = NULL;
+ bd->MouseTracked = false;
+ break;
+ case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
+ case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK:
+ {
+ int button = 0;
+ if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { button = 0; }
+ if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { button = 1; }
+ if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { button = 2; }
+ if (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONDBLCLK) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
+ if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL)
+ ::SetCapture(hwnd);
+ io.MouseDown[button] = true;
+ return 0;
+ }
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_XBUTTONUP:
+ {
+ int button = 0;
+ if (msg == WM_LBUTTONUP) { button = 0; }
+ if (msg == WM_RBUTTONUP) { button = 1; }
+ if (msg == WM_MBUTTONUP) { button = 2; }
+ if (msg == WM_XBUTTONUP) { button = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1) ? 3 : 4; }
+ io.MouseDown[button] = false;
+ if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd)
+ ::ReleaseCapture();
+ return 0;
+ }
+ case WM_MOUSEWHEEL:
+ io.MouseWheel += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
+ return 0;
+ case WM_MOUSEHWHEEL:
+ io.MouseWheelH += (float)GET_WHEEL_DELTA_WPARAM(wParam) / (float)WHEEL_DELTA;
+ return 0;
+ case WM_KEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYDOWN:
+ case WM_SYSKEYUP:
+ {
+ bool down = (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
+ if (wParam < 256)
+ io.KeysDown[wParam] = down;
+ if (wParam == VK_CONTROL)
+ io.KeyCtrl = down;
+ if (wParam == VK_SHIFT)
+ io.KeyShift = down;
+ if (wParam == VK_MENU)
+ io.KeyAlt = down;
+ return 0;
+ }
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ io.AddFocusEvent(msg == WM_SETFOCUS);
+ return 0;
+ case WM_CHAR:
+ // You can also use ToAscii()+GetKeyboardState() to retrieve characters.
+ if (wParam > 0 && wParam < 0x10000)
+ io.AddInputCharacterUTF16((unsigned short)wParam);
+ return 0;
+ case WM_SETCURSOR:
+ if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
+ return 1;
+ return 0;
+ case WM_DEVICECHANGE:
+ if ((UINT)wParam == DBT_DEVNODES_CHANGED)
+ bd->WantUpdateHasGamepad = true;
+ return 0;
+ }
+ return 0;
+}
+
+
+//--------------------------------------------------------------------------------------------------------
+// DPI-related helpers (optional)
+//--------------------------------------------------------------------------------------------------------
+// - Use to enable DPI awareness without having to create an application manifest.
+// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
+// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
+// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
+// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
+//---------------------------------------------------------------------------------------------------------
+// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
+// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
+// If you are trying to implement your own backend for your own engine, you may ignore that noise.
+//---------------------------------------------------------------------------------------------------------
+
+// Perform our own check with RtlVerifyVersionInfo() instead of using functions from <VersionHelpers.h> as they
+// require a manifest to be functional for checks above 8.1. See https://github.com/ocornut/imgui/issues/4200
+static BOOL _IsWindowsVersionOrGreater(WORD major, WORD minor, WORD)
+{
+ typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG);
+ static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfoFn = NULL;
+ if (RtlVerifyVersionInfoFn == NULL)
+ if (HMODULE ntdllModule = ::GetModuleHandleA("ntdll.dll"))
+ RtlVerifyVersionInfoFn = (PFN_RtlVerifyVersionInfo)GetProcAddress(ntdllModule, "RtlVerifyVersionInfo");
+ if (RtlVerifyVersionInfoFn == NULL)
+ return FALSE;
+
+ RTL_OSVERSIONINFOEXW versionInfo = { };
+ ULONGLONG conditionMask = 0;
+ versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
+ versionInfo.dwMajorVersion = major;
+ versionInfo.dwMinorVersion = minor;
+ VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
+ return (RtlVerifyVersionInfoFn(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask) == 0) ? TRUE : FALSE;
+}
+
+#define _IsWindowsVistaOrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0600), LOBYTE(0x0600), 0) // _WIN32_WINNT_VISTA
+#define _IsWindows8OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0602), LOBYTE(0x0602), 0) // _WIN32_WINNT_WIN8
+#define _IsWindows8Point1OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0603), LOBYTE(0x0603), 0) // _WIN32_WINNT_WINBLUE
+#define _IsWindows10OrGreater() _IsWindowsVersionOrGreater(HIBYTE(0x0A00), LOBYTE(0x0A00), 0) // _WIN32_WINNT_WINTHRESHOLD / _WIN32_WINNT_WIN10
+
+#ifndef DPI_ENUMS_DECLARED
+typedef enum { PROCESS_DPI_UNAWARE = 0, PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS;
+typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE;
+#endif
+#ifndef _DPI_AWARENESS_CONTEXTS_
+DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3
+#endif
+#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 (DPI_AWARENESS_CONTEXT)-4
+#endif
+typedef HRESULT(WINAPI* PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); // Shcore.lib + dll, Windows 8.1+
+typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+
+typedef DPI_AWARENESS_CONTEXT(WINAPI* PFN_SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT); // User32.lib + dll, Windows 10 v1607+ (Creators Update)
+
+// Helper function to enable DPI awareness without setting up a manifest
+void ImGui_ImplWin32_EnableDpiAwareness()
+{
+ if (_IsWindows10OrGreater())
+ {
+ static HINSTANCE user32_dll = ::LoadLibraryA("user32.dll"); // Reference counted per-process
+ if (PFN_SetThreadDpiAwarenessContext SetThreadDpiAwarenessContextFn = (PFN_SetThreadDpiAwarenessContext)::GetProcAddress(user32_dll, "SetThreadDpiAwarenessContext"))
+ {
+ SetThreadDpiAwarenessContextFn(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+ return;
+ }
+ }
+ if (_IsWindows8Point1OrGreater())
+ {
+ static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
+ if (PFN_SetProcessDpiAwareness SetProcessDpiAwarenessFn = (PFN_SetProcessDpiAwareness)::GetProcAddress(shcore_dll, "SetProcessDpiAwareness"))
+ {
+ SetProcessDpiAwarenessFn(PROCESS_PER_MONITOR_DPI_AWARE);
+ return;
+ }
+ }
+#if _WIN32_WINNT >= 0x0600
+ ::SetProcessDPIAware();
+#endif
+}
+
+#if defined(_MSC_VER) && !defined(NOGDI)
+#pragma comment(lib, "gdi32") // Link with gdi32.lib for GetDeviceCaps(). MinGW will require linking with '-lgdi32'
+#endif
+
+float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor)
+{
+ UINT xdpi = 96, ydpi = 96;
+ if (_IsWindows8Point1OrGreater())
+ {
+ static HINSTANCE shcore_dll = ::LoadLibraryA("shcore.dll"); // Reference counted per-process
+ static PFN_GetDpiForMonitor GetDpiForMonitorFn = NULL;
+ if (GetDpiForMonitorFn == NULL && shcore_dll != NULL)
+ GetDpiForMonitorFn = (PFN_GetDpiForMonitor)::GetProcAddress(shcore_dll, "GetDpiForMonitor");
+ if (GetDpiForMonitorFn != NULL)
+ {
+ GetDpiForMonitorFn((HMONITOR)monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
+ IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
+ return xdpi / 96.0f;
+ }
+ }
+#ifndef NOGDI
+ const HDC dc = ::GetDC(NULL);
+ xdpi = ::GetDeviceCaps(dc, LOGPIXELSX);
+ ydpi = ::GetDeviceCaps(dc, LOGPIXELSY);
+ IM_ASSERT(xdpi == ydpi); // Please contact me if you hit this assert!
+ ::ReleaseDC(NULL, dc);
+#endif
+ return xdpi / 96.0f;
+}
+
+float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd)
+{
+ HMONITOR monitor = ::MonitorFromWindow((HWND)hwnd, MONITOR_DEFAULTTONEAREST);
+ return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
+}
+
+//---------------------------------------------------------------------------------------------------------
+// Transparency related helpers (optional)
+//--------------------------------------------------------------------------------------------------------
+
+#if defined(_MSC_VER)
+#pragma comment(lib, "dwmapi") // Link with dwmapi.lib. MinGW will require linking with '-ldwmapi'
+#endif
+
+// [experimental]
+// Borrowed from GLFW's function updateFramebufferTransparency() in src/win32_window.c
+// (the Dwm* functions are Vista era functions but we are borrowing logic from GLFW)
+void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
+{
+ if (!_IsWindowsVistaOrGreater())
+ return;
+
+ BOOL composition;
+ if (FAILED(::DwmIsCompositionEnabled(&composition)) || !composition)
+ return;
+
+ BOOL opaque;
+ DWORD color;
+ if (_IsWindows8OrGreater() || (SUCCEEDED(::DwmGetColorizationColor(&color, &opaque)) && !opaque))
+ {
+ HRGN region = ::CreateRectRgn(0, 0, -1, -1);
+ DWM_BLURBEHIND bb = {};
+ bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+ bb.hRgnBlur = region;
+ bb.fEnable = TRUE;
+ ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
+ ::DeleteObject(region);
+ }
+ else
+ {
+ DWM_BLURBEHIND bb = {};
+ bb.dwFlags = DWM_BB_ENABLE;
+ ::DwmEnableBlurBehindWindow((HWND)hwnd, &bb);
+ }
+}
+
+//---------------------------------------------------------------------------------------------------------
diff --git a/Client/ThirdParty/imgui/backends/imgui_impl_win32.h b/Client/ThirdParty/imgui/backends/imgui_impl_win32.h
new file mode 100644
index 0000000..768fe16
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/imgui_impl_win32.h
@@ -0,0 +1,42 @@
+// dear imgui: Platform Backend for Windows (standard windows API for 32 and 64 bits applications)
+// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
+
+// Implemented features:
+// [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui)
+// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
+// [X] Platform: Keyboard arrays indexed using VK_* Virtual Key Codes, e.g. ImGui::IsKeyPressed(VK_SPACE).
+// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#pragma once
+#include "imgui.h" // IMGUI_IMPL_API
+
+IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd);
+IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown();
+IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();
+
+// Win32 message handler your application need to call.
+// - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on <windows.h> from this helper.
+// - You should COPY the line below into your .cpp code to forward declare the function and then you can call it.
+#if 0
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+#endif
+
+// DPI-related helpers (optional)
+// - Use to enable DPI awareness without having to create an application manifest.
+// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
+// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
+// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
+// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
+IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness();
+IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd
+IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor
+
+// Transparency related helpers (optional) [experimental]
+// - Use to enable alpha compositing transparency with the desktop.
+// - Use together with e.g. clearing your framebuffer with zero-alpha.
+IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
diff --git a/Client/ThirdParty/imgui/backends/vulkan/generate_spv.sh b/Client/ThirdParty/imgui/backends/vulkan/generate_spv.sh
new file mode 100644
index 0000000..948ef77
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/vulkan/generate_spv.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+## -V: create SPIR-V binary
+## -x: save binary output as text-based 32-bit hexadecimal numbers
+## -o: output file
+glslangValidator -V -x -o glsl_shader.frag.u32 glsl_shader.frag
+glslangValidator -V -x -o glsl_shader.vert.u32 glsl_shader.vert
diff --git a/Client/ThirdParty/imgui/backends/vulkan/glsl_shader.frag b/Client/ThirdParty/imgui/backends/vulkan/glsl_shader.frag
new file mode 100644
index 0000000..ce7e6f7
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/vulkan/glsl_shader.frag
@@ -0,0 +1,14 @@
+#version 450 core
+layout(location = 0) out vec4 fColor;
+
+layout(set=0, binding=0) uniform sampler2D sTexture;
+
+layout(location = 0) in struct {
+ vec4 Color;
+ vec2 UV;
+} In;
+
+void main()
+{
+ fColor = In.Color * texture(sTexture, In.UV.st);
+}
diff --git a/Client/ThirdParty/imgui/backends/vulkan/glsl_shader.vert b/Client/ThirdParty/imgui/backends/vulkan/glsl_shader.vert
new file mode 100644
index 0000000..9425365
--- /dev/null
+++ b/Client/ThirdParty/imgui/backends/vulkan/glsl_shader.vert
@@ -0,0 +1,25 @@
+#version 450 core
+layout(location = 0) in vec2 aPos;
+layout(location = 1) in vec2 aUV;
+layout(location = 2) in vec4 aColor;
+
+layout(push_constant) uniform uPushConstant {
+ vec2 uScale;
+ vec2 uTranslate;
+} pc;
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+
+layout(location = 0) out struct {
+ vec4 Color;
+ vec2 UV;
+} Out;
+
+void main()
+{
+ Out.Color = aColor;
+ Out.UV = aUV;
+ gl_Position = vec4(aPos * pc.uScale + pc.uTranslate, 0, 1);
+}
diff --git a/Client/ThirdParty/imgui/docs/BACKENDS.md b/Client/ThirdParty/imgui/docs/BACKENDS.md
new file mode 100644
index 0000000..c878132
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/BACKENDS.md
@@ -0,0 +1,142 @@
+_(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md or view this file with any Markdown viewer)_
+
+## Dear ImGui: Backends
+
+**The backends/ folder contains backends for popular platforms/graphics API, which you can use in
+your application or engine to easily integrate Dear ImGui.** Each backend is typically self-contained in a pair of files: imgui_impl_XXXX.cpp + imgui_impl_XXXX.h.
+
+- The 'Platform' backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, windowing.<BR>
+ e.g. Windows ([imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp)), GLFW ([imgui_impl_glfw.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp)), SDL2 ([imgui_impl_sdl.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_sdl.cpp)), etc.
+
+- The 'Renderer' backends are in charge of: creating atlas texture, rendering imgui draw data.<BR>
+ e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp), etc.
+
+- For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.<BR>
+ e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)), Marmalade ([imgui_impl_marmalade.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_marmalade.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
+
+An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources.
+For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
+
+**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
+
+
+### What are backends
+
+Dear ImGui is highly portable and only requires a few things to run and render, typically:
+
+ - Required: providing mouse/keyboard inputs (fed into the `ImGuiIO` structure).
+ - Required: uploading the font atlas texture into graphics memory.
+ - Required: rendering indexed textured triangles with a clipping rectangle.
+
+ Extra features are opt-in, our backends try to support as many as possible:
+
+ - Optional: custom texture binding support.
+ - Optional: clipboard support.
+ - Optional: gamepad support.
+ - Optional: mouse cursor shape support.
+ - Optional: IME support.
+ - Optional: multi-viewports support.
+ etc.
+
+This is essentially what each backends are doing + obligatory portability cruft. Using default backends ensure you can get all those features including the ones that would be harder to implement on your side (e.g. multi-viewports support).
+
+It is important to understand the difference between the core Dear ImGui library (files in the root folder)
+and backends which we are describing here (backends/ folder).
+
+- Some issues may only be backend or platform specific.
+- You should be able to write backends for pretty much any platform and any 3D graphics API.
+ e.g. you can get creative and use software rendering or render remotely on a different machine.
+
+
+### Integrating a backend
+
+See "Getting Started" section of [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for more details.
+
+
+### List of backends
+
+In the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder:
+
+List of Platforms Backends:
+
+ imgui_impl_android.cpp ; Android native app API
+ imgui_impl_glfw.cpp ; GLFW (Windows, macOS, Linux, etc.) http://www.glfw.org/
+ imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
+ imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
+ imgui_impl_win32.cpp ; Win32 native API (Windows)
+ imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
+
+List of Renderer Backends:
+
+ imgui_impl_dx9.cpp ; DirectX9
+ imgui_impl_dx10.cpp ; DirectX10
+ imgui_impl_dx11.cpp ; DirectX11
+ imgui_impl_dx12.cpp ; DirectX12
+ imgui_impl_metal.mm ; Metal (with ObjC)
+ imgui_impl_opengl2.cpp ; OpenGL 2 (legacy, fixed pipeline <- don't use with modern OpenGL context)
+ imgui_impl_opengl3.cpp ; OpenGL 3/4, OpenGL ES 2, OpenGL ES 3 (modern programmable pipeline)
+ imgui_impl_sdlrenderer.cpp; SDL_Renderer (optional component of SDL2 available from SDL 2.0.18+)
+ imgui_impl_vulkan.cpp ; Vulkan
+ imgui_impl_wgpu.cpp ; WebGPU
+
+List of high-level Frameworks Backends (combining Platform + Renderer):
+
+ imgui_impl_allegro5.cpp
+ imgui_impl_marmalade.cpp
+
+Emscripten is also supported.
+The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible.
+
+### Backends for third-party frameworks, graphics API or other languages
+
+See https://github.com/ocornut/imgui/wiki/Bindings for the full list.
+
+### Recommended Backends
+
+If you are not sure which backend to use, the recommended platform/frameworks for portable applications:
+
+|Library |Website |Backend |Note |
+|--------|--------|--------|-----|
+| GLFW | https://github.com/glfw/glfw | imgui_impl_glfw.cpp | |
+| SDL2 | https://www.libsdl.org | imgui_impl_sdl.cpp | |
+| Sokol | https://github.com/floooh/sokol | [util/sokol_imgui.h](https://github.com/floooh/sokol/blob/master/util/sokol_imgui.h) | Lower-level than GLFW/SDL |
+
+
+### Using a custom engine?
+
+You will likely be tempted to start by rewrite your own backend using your own custom/high-level facilities...<BR>
+Think twice!
+
+If you are new to Dear ImGui, first try using the existing backends as-is.
+You will save lots of time integrating the library.
+You can LATER decide to rewrite yourself a custom backend if you really need to.
+In most situations, custom backends have less features and more bugs than the standard backends we provide.
+If you want portability, you can use multiple backends and choose between them either at compile time
+or at runtime.
+
+**Example A**: your engine is built over Windows + DirectX11 but you have your own high-level rendering
+system layered over DirectX11.<BR>
+Suggestion: try using imgui_impl_win32.cpp + imgui_impl_dx11.cpp first.
+Once it works, if you really need it you can replace the imgui_impl_dx11.cpp code with a
+custom renderer using your own rendering functions, and keep using the standard Win32 code etc.
+
+**Example B**: your engine runs on Windows, Mac, Linux and uses DirectX11, Metal, Vulkan respectively.<BR>
+Suggestion: use multiple generic backends!
+Once it works, if you really need it you can replace parts of backends with your own abstractions.
+
+**Example C**: your engine runs on platforms we can't provide public backends for (e.g. PS4/PS5, Switch),
+and you have high-level systems everywhere.<BR>
+Suggestion: try using a non-portable backend first (e.g. win32 + underlying graphics API) to get
+your desktop builds working first. This will get you running faster and get your acquainted with
+how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API.
+
+Also:
+The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows
+Dear ImGui windows to be seamlessly detached from the main application window. This is achieved using an
+extra layer to the Platform and Renderer backends, which allows Dear ImGui to communicate platform-specific
+requests such as: "create an additional OS window", "create a render context", "get the OS position of this
+window" etc. See 'ImGuiPlatformIO' for details.
+Supporting the multi-viewports feature correctly using 100% of your own abstractions is more difficult
+than supporting single-viewport.
+If you decide to use unmodified imgui_impl_XXXX.cpp files, you can automatically benefit from
+improvements and fixes related to viewports and platform windows without extra work on your side.
diff --git a/Client/ThirdParty/imgui/docs/CHANGELOG.txt b/Client/ThirdParty/imgui/docs/CHANGELOG.txt
new file mode 100644
index 0000000..bde6e9e
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/CHANGELOG.txt
@@ -0,0 +1,3338 @@
+dear imgui
+CHANGELOG
+
+This document holds the user-facing changelog that we also use in release notes.
+We generally fold multiple commits pertaining to the same topic as a single entry.
+Changes to backends are also included within the individual .cpp files of each backend.
+
+RELEASE NOTES: https://github.com/ocornut/imgui/releases
+REPORT ISSUES: https://github.com/ocornut/imgui/issues
+DISCUSS, ASK QUESTIONS: https://github.com/ocornut/imgui/discussions
+FAQ https://www.dearimgui.org/faq/
+WIKI https://github.com/ocornut/imgui/wiki
+
+WHEN TO UPDATE?
+
+- Keeping your copy of Dear ImGui updated regularly is recommended.
+- It is generally safe to sync to the latest commit in master or docking branches
+ The library is fairly stable and regressions tends to be fixed fast when reported.
+
+HOW TO UPDATE?
+
+- Overwrite every file except imconfig.h (if you have modified it).
+- You may also locally branch to modify imconfig.h and merge latest into your branch.
+- Read the `Breaking Changes` section (in imgui.cpp or here in the Changelog).
+- If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it.
+- If you are dropping this repository in your codebase, please leave the demo and text files in there, they will be useful.
+- You may diff your previous Changelog with the one you just copied and read that diff.
+- You may enable `IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in imconfig.h to forcefully disable legacy names and symbols.
+ Doing it every once in a while is a good way to make sure you are not using obsolete symbols. Dear ImGui is in active development,
+ and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
+- Please report any issue!
+
+-----------------------------------------------------------------------
+ VERSION 1.86 WIP (In Progress)
+-----------------------------------------------------------------------
+
+Breaking Changes:
+
+- Removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges.
+ Please open an issue if you think you really need this function. (#3841)
+
+Other Changes:
+
+- Added IsMouseTripleClicked() function. Tracking multi-click count in IO structure. (#3229) [@kudaba]
+- Modals: fixed issue hovering popups inside a child inside a modal. (#4676, #4527)
+- Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676)
+- Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of using the _NavEnableKeyboard
+ configuration flag. This is part of an effort to generalize the use of keyboard inputs. (#4023, #787).
+ Note that while this is active you can also moving windows (with arrow) and resize (shift+arrows).
+- Nav: tabbing now cycles through clipped items and scroll accordingly. (#4449)
+- Nav: pressing PageUp/PageDown/Home/End when in Menu layer automatically moves back to Main layer.
+- Nav: fixed resizing window from borders setting navigation to Menu layer.
+- Nav: prevent child from clipping items when using _NavFlattened and parent has a pending request.
+- Nav: pressing Esc to exit a child window reactivates the Nav highlight if it was disabled by mouse.
+- Nav: with ImGuiConfigFlags_NavEnableSetMousePos enabled: Fixed absolute mouse position when using
+ Home/End leads to scrolling. Fixed not setting mouse position when a failed move request (e.g. when
+ already at edge) reactivates the navigation highlight.
+- InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
+- InputText: made double-click select word, triple-line select line. Word delimitation logic differs
+ slightly from the one used by CTRL+arrows. (#2244)
+- InputText: fixed ReadOnly flag preventing callbacks from receiving the text buffer. (#4762) [@actondev]
+- Clipper: currently focused item is automatically included in clipper range.
+ Fixes issue where e.g. drag and dropping an item and scrolling ensure the item source location is
+ still submitted. (#3841, #1725) [@GamingMinds-DanielC, @ocornut]
+- Cliooer: added ForceDisplayRangeByIndices() to force a given item (or several) to be stepped out
+ during a clipping operation. (#3841) [@@GamingMinds-DanielC]
+- Clipper: rework so gamepad/keyboard navigation doesn't create spikes in number of items requested
+ by the clipper to display. (#3841)
+- Clipper: fixed content height declaration slightly mismatching the value of when not using a clipper.
+ (an additional ItemSpacing.y was declared, affecting scrollbar range).
+- Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose
+ tooltip when scrolling. (#143)
+- Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce
+ likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling
+ vkCmdSetScissor() explicitly every frame. (#4644)
+- Misc: Added missing ImGuiMouseCursor_NotAllowed cursor for software rendering (when the
+ io.MouseDrawCursor flag is enabled). (#4713) [@nobody-special666]
+- Misc: Fix MinGW DLL build issue (when IMGUI_API is defined). [@rokups]
+- CI: Add MinGW DLL build to test suite. [@rokups]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.85 (Released 2021-10-12)
+-----------------------------------------------------------------------
+
+This is the last release officially supporting C++03 and Visual Studio 2008/2010. (#4537)
+We expect that the next release will require a subset of the C++11 language (VS 2012~, GCC 4.8.1, Clang 3.3).
+We may use some C++11 language features but we will not use any C++ library headers.
+If you are stuck on ancient compiler you may need to stay at this version onward.
+
+Breaking Changes:
+
+- Removed GetWindowContentRegionWidth() function. keep inline redirection helper.
+ Can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead but it's not
+ very useful in practice, and the only use of it in the demo was illfit.
+ Using 'GetContentRegionAvail().x' is generally a better choice.
+
+Other Changes:
+
+- Debug: Stack Tool: Added "Stack Tool" available in "Demo->Tools->Stack Tool", "Metrics->Tools",
+ or by calling the ShowStackToolWindow() function. The tool run queries on hovered id to display
+ details about individual components that were hashed to create an ID. It helps understanding
+ the ID stack system and debugging potential ID collisions. (#4631) [@ocornut, @rokups]
+- Windows: Fixed background order of overlapping childs submitted sequentially. (#4493)
+- IsWindowFocused: Added ImGuiFocusedFlags_NoPopupHierarchy flag allowing to exclude child popups
+ from the tested windows when combined with _ChildWindows.
+- IsWindowHovered: Added ImGuiHoveredFlags_NoPopupHierarchy flag allowing to exclude child popups
+ from the tested windows when combined with _ChildWindows.
+- InputTextMultiline: Fixed label size not being included into window contents rect unless
+ the whole widget is clipped.
+- InputText: Allow activating/cancelling/validating input with gamepad nav events. (#2321, #4552)
+- InputText: Fixed selection rectangle appearing one frame late when selecting all.
+- TextUnformatted: Accept null ranges including (NULL,NULL) without asserting, in order to conform
+ to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615)
+- Disabled: Added assert guard for mismatching BeginDisabled()/EndDisabled() blocks. (#211)
+- Nav: Fixed using SetKeyboardFocusHere() on non-visible/clipped items. It now works and will scroll
+ toward the item. When called during a frame where the parent window is appearing, scrolling will
+ aim to center the item in the window. When calling during a frame where the parent window is already
+ visible, scrolling will aim to scroll as little as possible to make the item visible. We will later
+ expose scroll functions and flags in public API to select those behaviors. (#343, #4079, #2352)
+- Nav: Fixed using SetKeyboardFocusHere() from activating a different item on the next frame if
+ submitted items have changed during that frame. (#432)
+- Nav: Fixed toggling menu layer with Alt or exiting menu layer with Esc not moving mouse when
+ the ImGuiConfigFlags_NavEnableSetMousePos config flag is set.
+- Nav: Fixed a few widgets from not setting reference keyboard/gamepad navigation ID when
+ activated with mouse. More specifically: BeginTabItem(), the scrolling arrows of BeginTabBar(),
+ the arrow section of TreeNode(), the +/- buttons of InputInt()/InputFloat(), Selectable() with
+ ImGuiSelectableFlags_SelectOnRelease. More generally: any direct use of ButtonBehavior() with
+ the PressedOnClick/PressedOnDoubleClick/PressedOnRelease button policy.
+- Nav: Fixed an issue with losing focus on docked windows when pressing Alt while keyboard navigation
+ is disabled. (#4547, #4439) [@PathogenDavid]
+- Nav: Fixed vertical scoring offset when wrapping on Y in a decorated window.
+- Nav: Improve scrolling behavior when navigating to an item larger than view.
+- TreePush(): removed unnecessary/inconsistent legacy behavior where passing a NULL value to
+ the TreePush(const char*) and TreePush(const void*) functions would use an hard-coded replacement.
+ The only situation where that change would make a meaningful difference is TreePush((const char*)NULL)
+ (_explicitly_ casting a null pointer to const char*), which is unlikely and will now crash.
+ You may replace it with anything else.
+- ColorEdit4: Fixed not being able to change hue when saturation is 0. (#4014) [@rokups]
+- ColorEdit4: Fixed hue resetting to 0 when it is set to 255. [@rokups]
+- ColorEdit4: Fixed hue value jitter when source color is stored as RGB in 32-bit integer and perform
+ RGB<>HSV round trips every frames. [@rokups]
+- ColorPicker4: Fixed picker being unable to select exact 1.0f color when dragging toward the edges
+ of the SV square (previously picked 0.999989986f). (#3517) [@rokups]
+- Menus: Fixed vertical alignments of MenuItem() calls within a menu bar (broken in 1.84). (#4538)
+- Menus: Improve closing logic when moving diagonally in empty between between parent and child menus to
+ accommodate for varying font size and dpi.
+- Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510).
+- Menus: Fixed an assertion happening in some situations when closing nested menus (broken in 1.83). (#4640)
+- Drag and Drop: Fixed using BeginDragDropSource() inside a BeginChild() that returned false. (#4515)
+- PlotHistogram: Fixed zero-line position when manually specifying min<0 and max>0. (#4349) [@filippocrocchini]
+- Misc: Added asserts for missing PopItemFlag() calls.
+- Misc: Fixed printf-style format checks on Clang+MinGW. (#4626, #4183, #3592) [@guusw]
+- IO: Added 'io.WantCaptureMouseUnlessPopupClose' alternative to `io.WantCaptureMouse'. (#4480)
+ This allows apps to receive the click on void when that click is used to close popup (by default,
+ clicking on a void when a popup is open will close the popup but not release io.WantCaptureMouse).
+- Fonts: imgui_freetype: Fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL
+ (which apparently happens with Freetype 2.11). (#4394, #4145?).
+- Fonts: Fixed ImFontAtlas::ClearInputData() marking atlas as not built. (#4455, #3487)
+- Backends: Added more implicit asserts to detect invalid/redundant calls to Shutdown functions. (#4562)
+- Backends: OpenGL3: Fixed our custom GL loader conflicting with user using GL3W. (#4445) [@rokups]
+- Backends: WebGPU: Fixed for latest specs. (#4472, #4512) [@Kangz, @bfierz]
+- Backends: SDL_Renderer: Added SDL_Renderer backend compatible with upcoming SDL 2.0.18. (#3926) [@1bsyl]
+- Backends: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted via
+ a direct unclipped PushClipRect() call. (#4464)
+- Backends: OSX: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards. (#4557, #4563) [@lfnoise]
+- Backends: All renderers: Normalize clipping rect handling across backends. (#4464)
+- Examples: Added SDL + SDL_Renderer example in "examples/example_sdl_sdlrenderer/" folder. (#3926) [@1bsyl]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.84.2 (Released 2021-08-23)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.84.2
+
+- Disabled: Fixed nested BeginDisabled()/EndDisabled() calls. (#211, #4452, #4453, #4462) [@Legulysse]
+- Backends: OpenGL3: OpenGL: Fixed ES 3.0 shader ("#version 300 es") to use normal precision
+ floats. Avoid wobbly rendering at HD resolutions. (#4463) [@nicolasnoble]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.84.1 (Released 2021-08-20)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.84.1
+
+- Disabled: Fixed BeginDisabled(false) - BeginDisabled(true) was working. (#211, #4452, #4453)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.84 (Released 2021-08-20)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.84
+
+Breaking Changes:
+
+- Commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
+ - ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()
+ - ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder
+- Backends: OpenGL3: added a third source file "imgui_impl_opengl3_loader.h". [@rokups]
+- Backends: GLFW: backend now uses glfwSetCursorEnterCallback(). (#3751, #4377, #2445)
+- Backends: GLFW: backend now uses glfwSetWindowFocusCallback(). (#4388) [@thedmd]
+ - If calling ImGui_ImplGlfw_InitXXX with install_callbacks=true: this is already done for you.
+ - If calling ImGui_ImplGlfw_InitXXX with install_callbacks=false: you WILL NEED to register the GLFW callbacks
+ and forward them to the backend:
+ - Register glfwSetCursorEnterCallback, forward events to ImGui_ImplGlfw_CursorEnterCallback().
+ - Register glfwSetWindowFocusCallback, forward events to ImGui_ImplGlfw_WindowFocusCallback().
+- Backends: SDL2: removed unnecessary SDL_Window* parameter from ImGui_ImplSDL2_NewFrame(). (#3244) [@funchal]
+ Kept inline redirection function (will obsolete).
+- Backends: SDL2: backend needs to set 'SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1")' in order to
+ receive mouse clicks events on window focus, otherwise SDL doesn't emit the event. (#3751, #4377, #2445)
+ This is unfortunately a global SDL setting, so enabling it _might_ have a side-effect on your application.
+ It is unlikely to make a difference, but if your app absolutely needs to ignore the initial on-focus click:
+ you can ignore SDL_MOUSEBUTTONDOWN events coming right after a SDL_WINDOWEVENT_FOCUS_GAINED event).
+- Internals: (for custom widgets): because disabled items now sets HoveredId, if you want custom widgets to
+ not react as hovered when disabled, in the majority of use cases it is preferable to check the "hovered"
+ return value of ButtonBehavior() rather than (HoveredId == id).
+
+Other Changes:
+
+- IO: Added io.AddFocusEvent() api for backend to tell when host window has gained/lost focus. (#4388) [@thedmd]
+ If you use a custom backend, consider adding support for this!
+- Disabled: added BeginDisabled()/EndDisabled() api to create a scope where interactions are disabled. (#211)
+ - Added style.DisabledAlpha (default to 0.60f) and ImGuiStyleVar_DisabledAlpha. (#211)
+ - Unlike the internal-and-undocumented-but-somehow-known PushItemFlag(ImGuiItemFlags_Disabled), this also alters
+ visuals. Currently this is done by lowering alpha of all widgets. Future styling system may do that differently.
+ - Disabled items set HoveredId, allowing e.g. HoveredIdTimer to run. (#211, #3419) [@rokups]
+ - Disabled items more consistently release ActiveId if the active item got disabled. (#211)
+ - Nav: Fixed disabled items from being candidate for default focus. (#211, #787)
+ - Fixed Selectable() selection not showing when disabled. (#211)
+ - Fixed IsItemHovered() returning true on disabled item when navigated to. (#211)
+ - Fixed IsItemHovered() when popping disabled state after item, or when using Selectable_Disabled. (#211)
+- Windows: ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument displays a dot instead of a '*' so it
+ is independent from font style. When in a tab, the dot is displayed at the same position as the close button.
+ Added extra comments to clarify the purpose of this flag in the context of docked windows.
+- Tables: Added ImGuiTableColumnFlags_Disabled acting a master disable over (hidden from user/context menu). (#3935)
+- Tables: Clarified that TableSetColumnEnabled() requires the table to use the ImGuiTableFlags_Hideable flag,
+ because it manipulates the user-accessible show/hide state. (#3935)
+- Tables: Added ImGuiTableColumnFlags_NoHeaderLabel to request TableHeadersRow() to not submit label for a column.
+ Convenient for some small columns. Name will still appear in context menu. (#4206).
+- Tables: Fixed columns order on TableSetupScrollFreeze() if previous data got frozen columns out of their section.
+- Tables: Fixed invalid data in TableGetSortSpecs() when SpecsDirty flag is unset. (#4233)
+- TabBar: Fixed using more than 32 KB-worth of tab names. (#4176)
+- InputInt/InputFloat: When used with Steps values and _ReadOnly flag, the step button look disabled. (#211)
+- InputText: Fixed named filtering flags disabling newline or tabs in multiline inputs (#4409, #4410) [@kfsone]
+- Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272)
+- Drag and Drop: Fixed using AcceptDragDropPayload() with ImGuiDragDropFlags_AcceptNoPreviewTooltip. [@JeffM2501]
+- Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered.
+- Menus: Fixed hovering a disabled menu or menu item not closing other menus. (#211)
+- Popups: Fixed BeginPopup/OpenPopup sequence failing when there are no focused windows. (#4308) [@rokups]
+- Nav: Alt doesn't toggle menu layer if other modifiers are held. (#4439)
+- Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592)
+- Fonts: Functions with a 'float size_pixels' parameter can accept zero if it is set in ImFontSize::SizePixels.
+- Fonts: Prefer using U+FFFD character for fallback instead of '?', if available. (#4269)
+- Fonts: Use U+FF0E dot character to construct an ellipsis if U+002E '.' is not available. (#4269)
+- Fonts: Added U+FFFD ("replacement character") to default asian glyphs ranges. (#4269)
+- Fonts: Fixed calling ClearTexData() (clearing CPU side font data) triggering an assert in NewFrame(). (#3487)
+- DrawList: Fixed AddCircle/AddCircleFilled() with auto-tesselation not using accelerated paths for small circles.
+ Fixed AddCircle/AddCircleFilled() with 12 segments which had a broken edge. (#4419, #4421) [@thedmd]
+- Demo: Fixed requirement in 1.83 to link with imgui_demo.cpp if IMGUI_DISABLE_METRICS_WINDOW is not set. (#4171)
+ Normally the right way to disable compiling the demo is to set IMGUI_DISABLE_DEMO_WINDOWS, but we want to avoid
+ implying that the file is required.
+- Metrics: Fixed a crash when inspecting the individual draw command of a foreground drawlist. [@rokups]
+- Backends: Reorganized most backends (Win32, SDL, GLFW, OpenGL2/3, DX9/10/11/12, Vulkan, Allegro) to pull their
+ data from a single structure stored inside the main Dear ImGui context. This facilitate/allow usage of standard
+ backends with multiple-contexts BUT is only partially tested and not well supported. It is generally advised to
+ instead use the multi-viewports feature of docking branch where a single Dear ImGui context can be used across
+ multiple windows. (#586, #1851, #2004, #3012, #3934, #4141)
+- Backends: Win32: Rework to handle certain Windows 8.1/10 features without a manifest. (#4200, #4191)
+ - ImGui_ImplWin32_GetDpiScaleForMonitor() will handle per-monitor DPI on Windows 10 without a manifest.
+ - ImGui_ImplWin32_EnableDpiAwareness() will call SetProcessDpiAwareness() fallback on Windows 8.1 without a manifest.
+- Backends: Win32: IME functions are disabled by default for non-Visual Studio compilers (MinGW etc.). Enable with
+ '#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS' for those compilers. Undo change from 1.82. (#2590, #738, #4185, #4301)
+- Backends: Win32: Mouse position is correctly reported when the host window is hovered but not focused. (#2445, #2696, #3751, #4377)
+- Backends: Win32, SDL2, GLFW, OSX, Allegro: now calling io.AddFocusEvent() on focus gain/loss. (#4388) [@thedmd]
+ This allow us to ignore certain inputs on focus loss (previously relied on mouse loss but backends are now
+ reporting mouse even when host window is unfocused, as per #2445, #2696, #3751, #4377)
+- Backends: Fixed keyboard modifiers being reported when host window doesn't have focus. (#2622)
+- Backends: GLFW: Mouse position is correctly reported when the host window is hovered but not focused. (#3751, #4377, #2445)
+ (backend now uses glfwSetCursorEnterCallback(). If you called ImGui_ImplGlfw_InitXXX with install_callbacks=false, you will
+ need to install this callback and forward the data to the backend via ImGui_ImplGlfw_CursorEnterCallback).
+- Backends: SDL2: Mouse position is correctly reported when the host window is hovered but not focused. (#3751, #4377, #2445)
+ (enabled with SDL 2.0.5+ as SDL_GetMouseFocus() is only usable with SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH).
+- Backends: DX9: Explicitly disable texture state stages after >= 1. (#4268) [@NZJenkins]
+- Backends: DX12: Fix texture casting crash on 32-bit systems (introduced on 2021/05/19 and v1.83) + added comments
+ about building on 32-bit systems. (#4225) [@kingofthebongo2008]
+- Backends: OpenGL3: Embed our own minimal GL headers/loader (imgui_impl_opengl3_loader.h) based on gl3w.
+ Reduces the frequent issues and confusion coming from having to support multiple loaders and requiring users to use and
+ initialize the same loader as the backend. [@rokups]
+ Removed support for gl3w, glew, glad, glad2, glbinding2, glbinding3 (all now unnecessary).
+- Backends: OpenGL3: Handle GL_CLIP_ORIGIN on <4.5 contexts if "GL_ARB_clip_control" extension is detected. (#4170, #3998)
+- Backends: OpenGL3: Destroy vertex/fragment shader objects right after they are linked into main shader. (#4244) [@Crowbarous]
+- Backends: OpenGL3: Use OES_vertex_array extension on Emscripten + backup/restore current state. (#4266, #4267) [@harry75369]
+- Backends: GLFW: Installing and exposed ImGui_ImplGlfw_MonitorCallback() for forward compatibility with docking branch.
+- Backends: OSX: Added a fix for shortcuts using CTRL key instead of CMD key. (#4253) [@rokups]
+- Examples: DX12: Fixed handling of Alt+Enter in example app (using swapchain's ResizeBuffers). (#4346) [@PathogenDavid]
+- Examples: DX12: Removed unnecessary recreation of backend-owned device objects when window is resized. (#4347) [@PathogenDavid]
+- Examples: OpenGL3+GLFW,SDL: Remove include cruft to support variety of GL loaders (no longer necessary). [@rokups]
+- Examples: OSX+OpenGL2: Fix event forwarding (fix key remaining stuck when using shortcuts with Cmd/Super key).
+ Other OSX examples were not affected. (#4253, #1873) [@rokups]
+- Examples: Updated all .vcxproj to VS2015 (toolset v140) to facilitate usage with vcpkg.
+- Examples: SDL2: Accommodate for vcpkg install having headers in SDL2/SDL.h vs SDL.h.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.83 (Released 2021-05-24)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.83
+
+Breaking Changes:
+
+- Backends: Obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). (#3761) [@thedmd]
+ - If you are using official backends from the source tree: you have nothing to do.
+ - If you copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID().
+ Why are we doing this?
+ - This change will be required in the future when adding support for incremental texture atlas updates.
+ - Please note this won't break soon, but we are making the change ahead of time.
+
+Other Changes:
+
+- Scrolling: Fix scroll tracking with e.g. SetScrollHereX/Y() when WindowPadding < ItemSpacing.
+- Scrolling: Fix scroll snapping on edge of scroll region when both scrollbars are enabled.
+- Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010)
+- Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061)
+- Nav: Fixed toggling menu layer while an InputText() is active not stealing active id. (#787)
+- Nav: Fixed pressing Escape to leave menu layer while in a popup or child window. (#787)
+- Nav, InputText: Fixed accidental menu toggling while typing non-ascii characters using AltGR. [@rokups] (#370)
+- Nav: Fixed using SetItemDefaultFocus() on windows with _NavFlattened flag. (#787)
+- Nav: Fixed Tabbing initial activation from skipping the first item if it is tabbable through. (#787)
+- Nav: Fixed fast CTRL+Tab (where keys are only held for one single frame) from properly enabling the
+ menu layer of target window if it doesn't have other active layers.
+- Tables: Expose TableSetColumnEnabled() in public api. (#3935)
+- Tables: Better preserve widths when columns count changes. (#4046)
+- Tables: Sharing more memory buffers between tables, reducing general memory footprints. (#3740)
+- TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single
+ frame and then immediately standing still (would only affect automation/bots). [@rokups]
+- Menus: made MenuItem() in a menu bar reflect the 'selected' argument with a highlight. (#4128) [@mattelegende]
+- Drags, Sliders, Inputs: Specifying a NULL format to Float functions default them to "%.3f" to be
+ consistent with the compile-time default. (#3922)
+- DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler]
+- ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack]
+- InputText: Fix handling of paste failure (buffer full) which in some cases could corrupt the undo stack. (#4038)
+ (fix submitted to https://github.com/nothings/stb/pull/1158) [@Unit2Ed, @ocornut]
+- InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks]
+- InputText: Align caret/cursor to pixel coordinates. (#4080) [@elvissteinjr]
+- InputText: Fixed CTRL+Arrow or OSX double-click leaking the presence of spaces when ImGuiInputTextFlags_Password
+ is used. (#4155, #4156) [@michael-swan]
+- LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004)
+- LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004)
+- Combos: Changed the combo popup to use a different id to also using a context menu with the default item id.
+ Fixed using BeginPopupContextItem() with no parameter after a combo. (#4167)
+- Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash]
+- Tweak computation of io.Framerate so it is less biased toward high-values in the first 120 frames. (#4138)
+- Optimization: Disabling some of MSVC most aggressive Debug runtime checks for some simple/low-level functions
+ (e.g. ImVec2, ImVector) leading to a 10-20% increase of performances with MSVC "default" Debug settings.
+- ImDrawList: Add and use SSE-enabled ImRsqrt() in place of 1.0f / ImSqrt(). (#4091) [@wolfpld]
+- ImDrawList: Fixed/improved thickness of thick strokes with sharp angles. (#4053, #3366, #2964, #2868, #2518, #2183)
+ Effectively introduced a regression in 1.67 (Jan 2019), and a fix in 1.70 (Apr 2019) but the fix wasn't actually on
+ par with original version. Now incorporating the correct revert.
+- ImDrawList: Fixed PathArcTo() regression from 1.82 preventing use of counter-clockwise angles. (#4030, #3491) [@thedmd]
+- Demo: Improved popups demo and comments.
+- Metrics: Added "Fonts" section with same information as available in "Style Editor">"Fonts".
+- Backends: SDL2: Rework global mouse pos availability check listing supported platforms explicitly,
+ effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx]
+- Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961)
+ [@1025798851]
+- Backends: OSX: Fix keys remaining stuck when CMD-tabbing to a different application. (#3832) [@rokups]
+- Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to
+ workaround/fix state restoring issues. Unknown exactly why so, bit of a cargo-cult fix. (#3857)
+- Backends: DirectX9: explicitly setting up more graphics states to increase compatibility with unusual
+ non-default states. (#4063)
+- Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when
+ entering the rendering function. (#4045) [@Nemirtingas]
+- Backends: GLFW: Adding bound check in KeyCallback because GLFW appears to send -1 on some setups. [#4124]
+- Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of
+ VkPhysicalDeviceLimits::nonCoherentAtomSize. (#3957) [@AgentX1994]
+- Backends: WebGPU: Update to latest specs (Chrome Canary 92 and Emscripten 2.0.20). (#4116, #3632) [@bfierz, @Kangz]
+- Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones]
+- Examples: OpenGL: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx]
+- Examples: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (#3881)
+- Examples: Vulkan: Prefer using discrete GPU if there are more than one available. (#4012) [@rokups]
+- Examples: SDL2: Link with shell32.lib required by SDL2main.lib since SDL 2.0.12. [#3988]
+- Examples: Android: Make Android example build compatible with Gradle 7.0. (#3446)
+- Docs: Improvements to description of using colored glyphs/emojis. (#4169, #3369)
+- Docs: Improvements to minor mistakes in documentation comments (#3923) [@ANF-Studios]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.82 (Released 2021-02-15)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.82
+
+Breaking Changes:
+
+- Removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018):
+ - ImGui::SetScrollHere() --> use ImGui::SetScrollHereY()
+- ImDrawList: upgraded AddPolyline()/PathStroke()'s "bool closed" parameter to use "ImDrawFlags flags".
+ - bool closed = false --> use ImDrawFlags_None, or 0
+ - bool closed = true --> use ImDrawFlags_Closed
+ The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.
+ Difference may not be noticeable for most but zealous type-checking tools may report a need to change.
+- ImDrawList: upgraded AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags.
+ - ImDrawCornerFlags_TopLeft --> use ImDrawFlags_RoundCornersTopLeft
+ - ImDrawCornerFlags_BotRight --> use ImDrawFlags_RoundCornersBottomRight
+ - ImDrawCornerFlags_None --> use ImDrawFlags_RoundCornersNone etc.
+ Flags now sanely defaults to 0 instead of 0x0F, consistent with all other flags in the API.
+ IMPORTANT: The default with rounding > 0.0f is now "round all corners" vs old implicit "round no corners":
+ - rounding == 0.0f + flags == 0 --> meant no rounding --> unchanged (common use)
+ - rounding > 0.0f + flags != 0 --> meant rounding --> unchanged (common use)
+ - rounding == 0.0f + flags != 0 --> meant no rounding --> unchanged (unlikely use)
+ - rounding > 0.0f + flags == 0 --> meant no rounding --> BREAKING (unlikely use)!
+ - this ONLY matters for hardcoded use of 0 with rounding > 0.0f.
+ - fix by using named ImDrawFlags_RoundCornersNone or rounding == 0.0f!
+ - this is technically the only real breaking change which we can't solve automatically (it's also uncommon).
+ The old ImDrawCornersFlags used awkward default values of ~0 or 0xF (4 lower bits set) to signify "round all corners"
+ and we sometimes encouraged using them as shortcuts. As a result the legacy path still support use of hardcoded ~0
+ or any value from 0x1 or 0xF. They will behave the same with legacy paths enabled (will assert otherwise).
+ Courtesy of legacy untangling commity: [@rokups, @ocornut, @thedmd]
+- ImDrawList: clarified that PathArcTo()/PathArcToFast() won't render with radius < 0.0f. Previously it sorts
+ of accidentally worked but would lead to counter-clockwise paths which and have an effect on anti-aliasing.
+- InputText: renamed ImGuiInputTextFlags_AlwaysInsertMode to ImGuiInputTextFlags_AlwaysOverwrite, old name was an
+ incorrect description of behavior. Was ostly used by memory editor. Kept inline redirection function. (#2863)
+- Moved 'misc/natvis/imgui.natvis' to 'misc/debuggers/imgui.natvis' as we will provide scripts for other debuggers.
+- Style: renamed rarely used style.CircleSegmentMaxError (old default = 1.60f)
+ to style.CircleTessellationMaxError (new default = 0.30f) as its meaning changed. (#3808) [@thedmd]
+- Win32+MinGW: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly
+ disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their
+ imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. (#2590, #738) [@actboy168]
+ *EDIT* Undid in 1.84.
+- Backends: Win32: Pragma linking with dwmapi.lib (Vista-era, ~9 kb). MinGW users will need to link with -ldwmapi.
+
+Other Changes:
+
+- Window, Nav: Fixed crash when calling SetWindowFocus(NULL) at the time a new window appears. (#3865) [@nem0]
+- Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible
+ area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825)
+- Nav: Various fixes for losing gamepad/keyboard navigation reference point when a window reappears or
+ when it appears while gamepad/keyboard are not being used. (#787)
+- Drags: Fixed crash when using DragScalar() directly (not via common wrapper like DragFloat() etc.)
+ with ImGuiSliderFlags_AlwaysClamp + only one of either p_min or p_max set. (#3824) [@harry75369]
+- Drags, Sliders: Fixed a bug where editing value would use wrong number if there were digits right after
+ format specifier (e.g. using "%f123" as a format string). [@rokups]
+- Drags, Sliders: Fixed a bug where using custom formatting flags (',$,_) supported by stb_sprintf.h
+ would cause incorrect value to be displayed. (#3604) [@rokups]
+- Drags, Sliders: Support ImGuiSliderFlags_Logarithmic flag with integers. Because why not? (#3786)
+- Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872)
+- IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using
+ either of them, when the hovered location is located within a child window, e.g. InputTextMultiline().
+ This is intended to have no side effects, but brace yourself for the possible comeback.. (#3851, #1370)
+- Drag and Drop: can use BeginDragDropSource() for other than the left mouse button as long as the item
+ has an ID (for ID-less items will add new functionalities later). (#1637, #3885)
+- ImFontAtlas: Added 'bool TexPixelsUseColors' output to help backend decide of underlying texture format. (#3369)
+ This can currently only ever be set by the Freetype renderer.
+- imgui_freetype: Added ImGuiFreeTypeBuilderFlags_Bitmap flag to request Freetype loading bitmap data.
+ This may have an effect on size and must be called with correct size values. (#3879) [@metarutaiga]
+- ImDrawList: PathArcTo() now supports "int num_segments = 0" (new default) and adaptively tessellate.
+ The adaptive tessellation uses look up tables, tends to be faster than old PathArcTo() while maintaining
+ quality for large arcs (tessellation quality derived from "style.CircleTessellationMaxError") (#3491) [@thedmd]
+- ImDrawList: PathArcToFast() also adaptively tessellate efficiently. This means that large rounded corners
+ in e.g. hi-dpi settings will generally look better. (#3491) [@thedmd]
+- ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError
+ with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd]
+- Misc: Added GetAllocatorFunctions() to facilitate sharing allocators across DLL boundaries. (#3836)
+- Misc: Added 'debuggers/imgui.gdb' and 'debuggers/imgui.natstepfilter' (along with existing 'imgui.natvis')
+ scripts to configure popular debuggers into skipping trivial functions when using StepInto. [@rokups]
+- Backends: Android: Added native Android backend. (#3446) [@duddel]
+- Backends: Win32: Added ImGui_ImplWin32_EnableAlphaCompositing() to facilitate experimenting with
+ alpha compositing and transparent windows. (#2766, #3447 etc.).
+- Backends: OpenGL, Vulkan, DX9, DX10, DX11, DX12, Metal, WebGPU, Allegro: Rework blending equation to
+ preserve alpha in output buffer (using SrcBlendAlpha = ONE, DstBlendAlpha = ONE_MINUS_SRC_ALPHA consistently
+ accross all backends), facilitating compositing of the output buffer with another buffer.
+ (#2693, #2764, #2766, #2873, #3447, #3813, #3816) [@ocornut, @thedmd, @ShawnM427, @Ubpa, @aiekick]
+- Backends: DX9: Fix to support IMGUI_USE_BGRA_PACKED_COLOR. (#3844) [@Xiliusha]
+- Backends: DX9: Fix to support colored glyphs, using newly introduced 'TexPixelsUseColors' info. (#3844)
+- Examples: Android: Added Android + GL ES3 example. (#3446) [@duddel]
+- Examples: Reworked setup of clear color to be compatible with transparent values.
+- CI: Use a dedicated "scheduled" workflow to trigger scheduled builds. Forks may disable this workflow if
+ scheduled builds builds are not required. [@rokups]
+- Log/Capture: Added LogTextV, a va_list variant of LogText. [@PathogenDavid]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.81 (Released 2021-02-10)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.81
+
+Breaking Changes:
+
+- ListBox helpers:
+ - Renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox().
+ - Renamed ListBoxFooter() to EndListBox().
+ - Removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size.
+ In the redirection function, made vertical padding consistent regardless of (items_count <= height_in_items) or not.
+ - Kept inline redirection function for all threes (will obsolete).
+- imgui_freetype:
+ - Removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function.
+ Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too.
+ - The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags.
+ - Renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags.
+ - Renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API.
+
+Other Changes:
+
+- Viewports Added ImGui::GetMainViewport() as a way to get the bounds and work area of the host display. (#3789, #1542)
+ - In 'master' branch or without multi-viewports feature enabled:
+ - GetMainViewport()->Pos is always == (0,0)
+ - GetMainViewport()->Size is always == io.DisplaySize
+ - In 'docking' branch and with the multi-viewports feature enabled:
+ - GetMainViewport() will return information from your host Platform Window.
+ - In the future, we will support a "no main viewport" mode and this may return bounds of your main monitor.
+ - For forward compatibility with multi-viewports/multi-monitors:
+ - Code using (0,0) as a way to signify "upper-left of the host window" should use GetMainViewport()->Pos.
+ - Code using io.DisplaySize as a way to signify "size of the host window" should use GetMainViewport()->Size.
+ - We are also exposing a work area in ImGuiViewport ('WorkPos', 'WorkSize' vs 'Pos', 'Size' for full area):
+ - For a Platform Window, the work area is generally the full area minus space used by menu-bars.
+ - For a Platform Monitor, the work area is generally the full area minus space used by task-bars.
+ - All of this has been the case in 'docking' branch for a long time. What we've done is merely merging
+ a small chunk of the multi-viewport logic into 'master' to standardize some concepts ahead of time.
+- Tables: Fixed PopItemWidth() or multi-components items not restoring per-colum ItemWidth correctly. (#3760)
+- Window: Fixed minor title bar text clipping issue when FramePadding is small/zero and there are no
+ close button in the window. (#3731)
+- SliderInt: Fixed click/drag when v_min==v_max from setting the value to zero. (#3774) [@erwincoumans]
+ Would also repro with DragFloat() when using ImGuiSliderFlags_Logarithmic with v_min==v_max.
+- Menus: Fixed an issue with child-menu auto sizing (issue introduced in 1.80 on 2021/01/25) (#3779)
+- InputText: Fixed slightly off ScrollX tracking, noticeable with large values of FramePadding.x. (#3781)
+- InputText: Multiline: Fixed padding/cliprect not precisely matching single-line version. (#3781)
+- InputText: Multiline: Fixed FramePadding.y worth of vertical offset when aiming with mouse.
+- ListBox: Tweaked default height calculation.
+- Fonts: imgui_freetype: Facilitated using FreeType integration: [@Xipiryon, @ocornut]
+ - Use '#define IMGUI_ENABLE_FREETYPE' in imconfig.h should make it work with no other modifications
+ other than compiling misc/freetype/imgui_freetype.cpp and linking with FreeType.
+ - Use '#define IMGUI_ENABLE_STB_TRUETYPE' if you somehow need the stb_truetype rasterizer to be
+ compiled in along with the FreeType one, otherwise it is enabled by default.
+- Fonts: imgui_freetype: Added support for colored glyphs as supported by Freetype 2.10+ (for .ttf using CPAL/COLR
+ tables only). Enable the ImGuiFreeTypeBuilderFlags_LoadColor on a given font. Atlas always output directly
+ as RGBA8 in this situation. Likely to make sense with IMGUI_USE_WCHAR32. (#3369) [@pshurgal]
+- Fonts: Fixed CalcTextSize() width rounding so it behaves more like a ceil. This is in order for text wrapping
+ to have enough space when provided width precisely calculated with CalcTextSize().x. (#3776)
+ Note that the rounding of either positions and widths are technically undesirable (e.g. #3437, #791) but
+ variety of code is currently on it so we are first fixing current behavior before we'll eventually change it.
+- Log/Capture: Fix various new line/spacing issue when logging widgets. [@Xipiryon, @ocornut]
+- Log/Capture: Improved the ASCII look of various widgets, making large dumps more easily human readable.
+- ImDrawList: Fixed AddCircle()/AddCircleFilled() with (rad > 0.0f && rad < 1.0f && num_segments == 0). (#3738)
+ Would lead to a buffer read overflow.
+- ImDrawList: Clarified PathArcTo() need for a_min <= a_max with an assert.
+- ImDrawList: Fixed PathArcToFast() handling of a_min > a_max.
+- Metrics: Back-ported "Viewports" debug visualizer from 'docking' branch.
+- Demo: Added 'Examples->Fullscreen Window' demo using GetMainViewport() values. (#3789)
+- Demo: 'Simple Overlay' demo now moves under main menu-bar (if any) using GetMainViewport()'s work area.
+- Backends: Win32: Dynamically loading XInput DLL instead of linking with it, facilitate compiling with
+ old WindowSDK versions or running on Windows 7. (#3646, #3645, #3248, #2716) [@Demonese]
+- Backends: Vulkan: Add support for custom Vulkan function loader and VK_NO_PROTOTYPES. (#3759, #3227) [@Hossein-Noroozpour]
+ User needs to call ImGui_ImplVulkan_LoadFunctions() with their custom loader prior to other functions.
+- Backends: Metal: Fixed texture storage mode when building on Mac Catalyst. (#3748) [@Belinsky-L-V]
+- Backends: OSX: Fixed mouse position not being reported when mouse buttons other than left one are down. (#3762) [@rokups]
+- Backends: WebGPU: Added enderer backend for WebGPU support (imgui_impl_wgpu.cpp) (#3632) [@bfierz]
+ Please note that WebGPU is currently experimental, will not run on non-beta browsers, and may break.
+- Examples: WebGPU: Added Emscripten+WebGPU example. (#3632) [@bfierz]
+- Backends: GLFW: Added ImGui_ImplGlfw_InitForOther() initialization call to use with non OpenGL API. (#3632)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.80 (Released 2021-01-21)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.80
+
+Breaking Changes:
+
+- Added imgui_tables.cpp file! Manually constructed project files will need the new file added! (#3740)
+- Backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/. (#3513)
+- Renamed ImDrawList::AddBezierCurve() to ImDrawList::AddBezierCubic(). Kept inline redirection function (will obsolete).
+- Renamed ImDrawList::PathBezierCurveTo() to ImDrawList::PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete).
+- Removed redirecting functions/enums names that were marked obsolete in 1.60 (April 2018):
+ - io.RenderDrawListsFn pointer -> use ImGui::GetDrawData() value and call the render function of your backend
+ - ImGui::IsAnyWindowFocused() -> use ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)
+ - ImGui::IsAnyWindowHovered() -> use ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)
+ - ImGuiStyleVar_Count_ -> use ImGuiStyleVar_COUNT
+ - ImGuiMouseCursor_Count_ -> use ImGuiMouseCursor_COUNT
+- Removed redirecting functions/enums names that were marked obsolete in 1.61 (May 2018):
+ - InputFloat (... int decimal_precision ...) -> use InputFloat (... const char* format ...) with format = "%.Xf" where X was value for decimal_precision.
+ - same for InputFloat2()/InputFloat3()/InputFloat4() variants taking a `int decimal_precision` parameter.
+- Removed redirecting functions/enums names that were marked obsolete in 1.63 (August 2018):
+ - ImGui::IsItemDeactivatedAfterChange() -> use ImGui::IsItemDeactivatedAfterEdit().
+ - ImGuiCol_ModalWindowDarkening -> use ImGuiCol_ModalWindowDimBg
+ - ImGuiInputTextCallback -> use ImGuiTextEditCallback
+ - ImGuiInputTextCallbackData -> use ImGuiTextEditCallbackData
+- If you were still using the old names, while you are cleaning up, considering enabling
+ IMGUI_DISABLE_OBSOLETE_FUNCTIONS in imconfig.h even temporarily to have a pass at finding
+ and removing up old API calls, if any remaining.
+- Internals: Columns: renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* to reduce
+ confusion with Tables API. Keep redirection enums (will obsolete). (#125, #513, #913, #1204, #1444, #2142, #2707)
+- Renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature now applies
+ to other data structures. (#2636)
+
+Other Changes:
+
+- Tables: added new Tables Beta API as a replacement for old Columns. (#3740, #2957, #125)
+ Check out 'Demo->Tables' for many demos.
+ Read API comments in imgui.h for details. Read extra commentary in imgui_tables.cpp.
+ - Added 16 functions:
+ - BeginTable(), EndTable()
+ - TableNextRow(), TableNextColumn(), TableSetColumnIndex()
+ - TableSetupColumn(), TableSetupScrollFreeze()
+ - TableHeadersRow(), TableHeader()
+ - TableGetRowIndex(), TableGetColumnCount(), TableGetColumnIndex(), TableGetColumnName(), TableGetColumnFlags()
+ - TableGetSortSpecs(), TableSetBgColor()
+ - Added 3 flags sets:
+ - ImGuiTableFlags (29 flags for: features, decorations, sizing policies, padding, clipping, scrolling, sorting etc.)
+ - ImGuiTableColumnFlags (24 flags for: width policies, default settings, sorting options, indentation options etc.)
+ - ImGuiTableRowFlags (1 flag for: header row)
+ - Added 2 structures: ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs
+ - Added 2 enums: ImGuiSortDirection, ImGuiTableBgTarget
+ - Added 1 style variable: ImGuiStyleVar_CellPadding
+ - Added 5 style colors: ImGuiCol_TableHeaderBg, ImGuiCol_TableBorderStrong, ImGuiCol_TableBorderLight, ImGuiCol_TableRowBg, ImGuiCol_TableRowBgAlt.
+- Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again.
+- Tab Bar: Fixed using more than 128 tabs in a tab bar (scrolling policy recommended).
+- Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521)
+- Tab Bar: Fixed minor/unlikely bug skipping over a button when scrolling left with arrows.
+- Tab Bar: Requested ideal content size (for auto-fit) doesn't affect horizontal scrolling. (#3414)
+- Drag and Drop: Fix losing drop source ActiveID (and often source tooltip) when opening a TreeNode()
+ or CollapsingHeader() while dragging. (#1738)
+- Drag and Drop: Fix drag and drop to tie same-size drop targets by chosen the later one. Fixes dragging
+ into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat]
+- Checkbox: Added CheckboxFlags() helper with int* type (internals have a template version, not exposed).
+- Clipper: Fixed incorrect end-list positioning when using ImGuiListClipper with 1 item (bug in 1.79). (#3663) [@nyorain]
+- InputText: Fixed updating cursor/selection position when a callback altered the buffer in a way
+ where the byte count is unchanged but the decoded character count changes. (#3587) [@gqw]
+- InputText: Fixed switching from single to multi-line while preserving same ID.
+- Combo: Fixed using IsItemEdited() after Combo() not matching the return value from Combo(). (#2034)
+- DragFloat, DragInt: very slightly increased mouse drag threshold + expressing it as a factor of default value.
+- DragFloat, DragInt: added experimental io.ConfigDragClickToInputText feature to enable turning DragXXX widgets
+ into text input with a simple mouse click-release (without moving). (#3737)
+- Nav: Fixed IsItemFocused() from returning false when Nav highlight is hidden because mouse has moved.
+ It's essentially been always the case but it doesn't make much sense. Instead we will aim at exposing
+ feedback and control of keyboard/gamepad navigation highlight and mouse hover disable flag. (#787, #2048)
+- Metrics: Fixed mishandling of ImDrawCmd::VtxOffset in wireframe mesh renderer.
+- Metrics: Rebranded as "Dear ImGui Metrics/Debugger" to clarify its purpose.
+- ImDrawList: Added ImDrawList::AddQuadBezierCurve(), ImDrawList::PathQuadBezierCurveTo() quadratic bezier
+ helpers. (#3127, #3664, #3665) [@aiekick]
+- Fonts: Updated GetGlyphRangesJapanese() to include a larger 2999 ideograms selection of Joyo/Jinmeiyo
+ kanjis, from the previous 1946 ideograms selection. This will consume a some more memory but be generally
+ much more fitting for Japanese display, until we switch to a more dynamic atlas. (#3627) [@vaiorabbit]
+- Log/Capture: fix capture to work on clipped child windows.
+- Misc: Made the ItemFlags stack shared, so effectively the ButtonRepeat/AllowKeyboardFocus states
+ (and others exposed in internals such as PushItemFlag) are inherited by stacked Begin/End pairs,
+ vs previously a non-child stacked Begin() would reset those flags back to zero for the stacked window.
+- Misc: Replaced UTF-8 decoder with one based on branchless one by Christopher Wellons. [@rokups]
+ Super minor fix handling incomplete UTF-8 contents: if input does not contain enough bytes, decoder
+ returns IM_UNICODE_CODEPOINT_INVALID and consume remaining bytes (vs old decoded consumed only 1 byte).
+- Misc: Fix format warnings when using gnu printf extensions in a setup that supports them (gcc/mingw). (#3592)
+- Misc: Made EndFrame() assertion for key modifiers being unchanged during the frame (added in 1.76) more
+ lenient, allowing full mid-frame releases. This is to accommodate the use of mid-frame modal native
+ windows calls, which leads backends such as GLFW to send key clearing events on focus loss. (#3575)
+- Style: Changed default style.WindowRounding value to 0.0f (matches default for multi-viewports).
+- Style: Reduced the size of the resizing grip, made alpha less prominent.
+- Style: Classic: Increase the default alpha value of WindowBg to be closer to other styles.
+- Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width.
+- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...)
+ when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn]
+- Backends: OpenGL2: Backup and restore GL_SHADE_MODEL and disable GL_NORMAL_ARRAY state to increase
+ compatibility with legacy code. (#3671)
+- Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon]
+- Backends: OpenGL2, OpenGL3: Backup and restore GL_STENCIL_TEST enable state. (#3668)
+- Backends: Vulkan: Added support for specifying which sub-pass to reference during VkPipeline creation. (@3579) [@bdero]
+- Backends: DX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically. (#3696) [@Mattiwatti]
+- Backends: Win32: Fix setting of io.DisplaySize to invalid/uninitialized data after hwnd has been closed.
+- Backends: OSX: Fix keypad-enter key not working on MacOS. (#3554) [@rokups, @lfnoise]
+- Examples: Apple+Metal: Consolidated/simplified to get closer to other examples. (#3543) [@warrenm]
+- Examples: Apple+Metal: Forward events down so OS key combination like Cmd+Q can work. (#3554) [@rokups]
+- Examples: Emscripten: Renamed example_emscripten/ to example_emscripten_opengl3/. (#3632)
+- Examples: Emscripten: Added 'make serve' helper to spawn a web-server on localhost. (#3705) [@Horki]
+- Examples: DirectX12: Move ImGui::Render() call above the first barrier to clarify its lack of effect on the graphics pipe.
+- CI: Fix testing for Windows DLL builds. (#3603, #3601) [@iboB]
+- Docs: Improved the wiki and added a https://github.com/ocornut/imgui/wiki/Useful-Widgets page. [@Xipiryon]
+ [2021/05/20: moved to https://github.com/ocornut/imgui/wiki/Useful-Extensions]
+- Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md, and improved them.
+- Docs: Consistently renamed all occurrences of "binding" and "back-end" to "backend" in comments and docs.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.79 (Released 2020-10-08)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.79
+
+Breaking Changes:
+
+- Fonts: Removed ImFont::DisplayOffset in favor of ImFontConfig::GlyphOffset. DisplayOffset was applied
+ after scaling and not very meaningful/useful outside of being needed by the default ProggyClean font.
+ It was also getting in the way of better font scaling, so let's get rid of it now!
+ If you used DisplayOffset it was probably in association to rasterizing a font at a specific size,
+ in which case the corresponding offset may be reported into GlyphOffset. (#1619)
+ If you scaled this value after calling AddFontDefault(), this is now done automatically.
+- ImGuiListClipper: Renamed constructor parameters which created an ambiguous alternative to using
+ the ImGuiListClipper::Begin() function, with misleading edge cases. Always use ImGuiListClipper::Begin()!
+ Kept inline redirection function (will obsolete).
+ (note: imgui_memory_editor <0.40 from imgui_club/ used this old clipper API. Update your copy if needed).
+- Style: Renamed style.TabMinWidthForUnselectedCloseButton to style.TabMinWidthForCloseButton.
+- Renamed ImGuiSliderFlags_ClampOnInput to ImGuiSliderFlags_AlwaysClamp. Kept redirection enum (will obsolete).
+- Renamed OpenPopupContextItem() back to OpenPopupOnItemClick(), REVERTED CHANGE FROM 1.77.
+ For variety of reason this is more self-explanatory and less error-prone. Kept inline redirection function.
+- Removed return value from OpenPopupOnItemClick() - returned true on mouse release on an item - because it
+ is inconsistent with other popups API and makes others misleading. It's also and unnecessary: you can
+ use IsWindowAppearing() after BeginPopup() for a similar result.
+
+Other Changes:
+
+- Window: Fixed using non-zero pivot in SetNextWindowPos() when the window is collapsed. (#3433)
+- Nav: Fixed navigation resuming on first visible item when using gamepad. [@rokups]
+- Nav: Fixed using Alt to toggle the Menu layer when inside a Modal window. (#787)
+- Scrolling: Fixed SetScrollHere(0) functions edge snapping when called during a frame where
+ ContentSize is changing (issue introduced in 1.78). (#3452).
+- InputText: Added support for Page Up/Down in InputTextMultiline(). (#3430) [@Xipiryon]
+- InputText: Added selection helpers in ImGuiInputTextCallbackData().
+- InputText: Added ImGuiInputTextFlags_CallbackEdit to modify internally owned buffer after an edit.
+ (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the
+ underlying buffer while focus is active).
+- InputText: Fixed using ImGuiInputTextFlags_Password with InputTextMultiline(). (#3427, #3428)
+ It is a rather unusual or useless combination of features but no reason it shouldn't work!
+- InputText: Fixed minor scrolling glitch when erasing trailing lines in InputTextMultiline().
+- InputText: Fixed cursor being partially covered after using Ctrl+End key.
+- InputText: Fixed callback's helper DeleteChars() function when cursor is inside the deleted block. (#3454)
+- InputText: Made pressing Down arrow on the last line when it doesn't have a carriage return not move to
+ the end of the line (so it is consistent with Up arrow, and behave same as Notepad and Visual Studio.
+ Note that some other text editors instead would move the cursor to the end of the line). [@Xipiryon]
+- DragFloat, DragScalar: Fixed ImGuiSliderFlags_ClampOnInput not being honored in the special case
+ where v_min == v_max. (#3361)
+- SliderInt, SliderScalar: Fixed reaching of maximum value with inverted integer min/max ranges, both
+ with signed and unsigned types. Added reverse Sliders to Demo. (#3432, #3449) [@rokups]
+- Text: Bypass unnecessary formatting when using the TextColored()/TextWrapped()/TextDisabled() helpers
+ with a "%s" format string. (#3466)
+- CheckboxFlags: Display mixed-value/tristate marker when passed flags that have multiple bits set and
+ stored value matches neither zero neither the full set.
+- BeginMenuBar: Fixed minor bug where CursorPosMax gets pushed to CursorPos prior to calling BeginMenuBar(),
+ so e.g. calling the function at the end of a window would often add +ItemSpacing.y to scrolling range.
+- TreeNode, CollapsingHeader: Made clicking on arrow toggle toggle the open state on the Mouse Down event
+ rather than the Mouse Down+Up sequence, even if the _OpenOnArrow flag isn't set. This is standard behavior
+ and amends the change done in 1.76 which only affected cases were _OpenOnArrow flag was set.
+ (This is also necessary to support full multi/range-select/drag and drop operations.)
+- Tab Bar: Added TabItemButton() to submit tab that behave like a button. (#3291) [@Xipiryon]
+- Tab Bar: Added ImGuiTabItemFlags_Leading and ImGuiTabItemFlags_Trailing flags to position tabs or button
+ at either end of the tab bar. Those tabs won't be part of the scrolling region, and when reordering cannot
+ be moving outside of their section. Most often used with TabItemButton(). (#3291) [@Xipiryon]
+- Tab Bar: Added ImGuiTabItemFlags_NoReorder flag to disable reordering a given tab.
+- Tab Bar: Keep tab item close button visible while dragging a tab (independent of hovering state).
+- Tab Bar: Fixed a small bug where closing a tab that is not selected would leave a tab hole for a frame.
+- Tab Bar: Fixed a small bug where scrolling buttons (with ImGuiTabBarFlags_FittingPolicyScroll) would
+ generate an unnecessary extra draw call.
+- Tab Bar: Fixed a small bug where toggling a tab bar from Reorderable to not Reorderable would leave
+ tabs reordered in the tab list popup. [@Xipiryon]
+- Columns: Fix inverted ClipRect being passed to renderer when using certain primitives inside of
+ a fully clipped column. (#3475) [@szreder]
+- Popups, Tooltips: Fix edge cases issues with positioning popups and tooltips when they are larger than
+ viewport on either or both axises. [@Rokups]
+- Fonts: AddFontDefault() adjust its vertical offset based on floor(size/13) instead of always +1.
+ Was previously done by altering DisplayOffset.y but wouldn't work for DPI scaled font.
+- Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible.
+- Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console').
+- Backends: OpenGL3: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 contexts which have
+ the defines set by a loader. (#3467, #1985) [@jjwebb]
+- Backends: Vulkan: Some internal refactor aimed at allowing multi-viewport feature to create their
+ own render pass. (#3455, #3459) [@FunMiles]
+- Backends: DX12: Clarified that imgui_impl_dx12 can be compiled on 32-bit systems by redefining
+ the ImTextureID to be 64-bit (e.g. '#define ImTextureID ImU64' in imconfig.h). (#301)
+- Backends: DX12: Fix debug layer warning when scissor rect is zero-sized. (#3472, #3462) [@StoneWolf]
+- Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO]
+- Examples: Vulkan: Switch validation layer to use "VK_LAYER_KHRONOS_validation" instead of
+ "VK_LAYER_LUNARG_standard_validation" which is deprecated (#3459) [@FunMiles]
+- Examples: DX12: Enable breaking on any warning/error when debug interface is enabled.
+- Examples: DX12: Added '#define ImTextureID ImU64' in project and build files to also allow building
+ on 32-bit systems. Added project to default Visual Studio solution file. (#301)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.78 (Released 2020-08-18)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.78
+
+Breaking Changes:
+
+- Obsoleted use of the trailing 'float power=1.0f' parameter for those functions: [@Shironekoben, @ocornut]
+ - DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(), DragFloatRange2(), DragScalar(), DragScalarN()
+ - SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(), SliderScalar(), SliderScalarN()
+ - VSliderFloat(), VSliderScalar()
+ Replaced the final 'float power=1.0f' argument with ImGuiSliderFlags defaulting to 0 (as with all our flags).
+ Worked out a backward-compatibility scheme so hopefully most C++ codebase should not be affected.
+ In short, when calling those functions:
+ - If you omitted the 'power' parameter (likely!), you are not affected.
+ - If you set the 'power' parameter to 1.0f (same as previous default value):
+ - Your compiler may warn on float>int conversion.
+ - Everything else will work (but will assert if IMGUI_DISABLE_OBSOLETE_FUNCTIONS is defined).
+ - You can replace the 1.0f value with 0 to fix the warning, and be technically correct.
+ - If you set the 'power' parameter to >1.0f (to enable non-linear editing):
+ - Your compiler may warn on float>int conversion.
+ - Code will assert at runtime for IM_ASSERT(power == 1.0f) with the following assert description:
+ "Call Drag function with ImGuiSliderFlags_Logarithmic instead of using the old 'float power' function!".
+ - In case asserts are disabled, the code will not crash and enable the _Logarithmic flag.
+ - You can replace the >1.0f value with ImGuiSliderFlags_Logarithmic to fix the warning/assert
+ and get a _similar_ effect as previous uses of power >1.0f.
+ See https://github.com/ocornut/imgui/issues/3361 for all details.
+ For shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
+ Kept inline redirection functions (will obsolete) apart for: DragFloatRange2(), VSliderFloat(), VSliderScalar().
+ For those three the 'float power=1.0f' version was removed directly as they were most unlikely ever used.
+- DragInt, DragFloat, DragScalar: Obsoleted use of v_min > v_max to lock edits (introduced in 1.73, this was not
+ demoed nor documented much, will be replaced a more generic ReadOnly feature).
+
+Other Changes:
+
+- Nav: Fixed clicking on void (behind any windows) from not clearing the focused window.
+ This would be problematic e.g. in situation where the application relies on io.WantCaptureKeyboard
+ flag being cleared accordingly. (bug introduced in 1.77 WIP on 2020/06/16) (#3344, #2880)
+- Window: Fixed clicking over an item which hovering has been disabled (e.g inhibited by a popup)
+ from marking the window as moved.
+- Drag, Slider: Added ImGuiSliderFlags parameters.
+ - For float functions they replace the old trailing 'float power=1.0' parameter.
+ (See #3361 and the "Breaking Changes" block above for all details).
+ - Added ImGuiSliderFlags_Logarithmic flag to enable logarithmic editing
+ (generally more precision around zero), as a replacement to the old 'float power' parameter
+ which was obsoleted. (#1823, #1316, #642) [@Shironekoben, @AndrewBelt]
+ - Added ImGuiSliderFlags_ClampOnInput flag to force clamping value when using
+ CTRL+Click to type in a value manually. (#1829, #3209, #946, #413).
+ [note: RENAMED to ImGuiSliderFlags_AlwaysClamp in 1.79].
+ - Added ImGuiSliderFlags_NoRoundToFormat flag to disable rounding underlying
+ value to match precision of the display format string. (#642)
+ - Added ImGuiSliderFlags_NoInput flag to disable turning widget into a text input
+ with CTRL+Click or Nav Enter.
+- Nav, Slider: Fix using keyboard/gamepad controls with certain logarithmic sliders where
+ pushing a direction near zero values would be cancelled out. [@Shironekoben]
+- DragFloatRange2, DragIntRange2: Fixed an issue allowing to drag out of bounds when both
+ min and max value are on the same value. (#1441)
+- InputText, ImDrawList: Fixed assert triggering when drawing single line of text with more
+ than ~16 KB characters. (Note that current code is going to show corrupted display if after
+ clipping, more than 16 KB characters are visible in the same low-level ImDrawList::RenderText()
+ call. ImGui-level functions such as TextUnformatted() are not affected. This is quite rare
+ but it will be addressed later). (#3349)
+- Selectable: Fixed highlight/hit extent when used with horizontal scrolling (in or outside columns).
+ Also fixed related text clipping when used in a column after the first one. (#3187, #3386)
+- Scrolling: Avoid SetScroll, SetScrollFromPos functions from snapping on the edge of scroll
+ limits when close-enough by (WindowPadding - ItemPadding), which was a tweak with too many
+ side-effects. The behavior is still present in SetScrollHere functions as they are more explicitly
+ aiming at making widgets visible. May later be moved to a flag.
+- Tab Bar: Allow calling SetTabItemClosed() after a tab has been submitted (will process next frame).
+- InvisibleButton: Made public a small selection of ImGuiButtonFlags (previously in imgui_internal.h)
+ and allowed to pass them to InvisibleButton(): ImGuiButtonFlags_MouseButtonLeft/Right/Middle.
+ This is a small but rather important change because lots of multi-button behaviors could previously
+ only be achieved using lower-level/internal API. Now also available via high-level InvisibleButton()
+ with is a de-facto versatile building block to creating custom widgets with the public API.
+- Fonts: Fixed ImFontConfig::GlyphExtraSpacing and ImFontConfig::PixelSnapH settings being pulled
+ from the merged/target font settings when merging fonts, instead of being pulled from the source
+ font settings.
+- ImDrawList: Thick anti-aliased strokes (> 1.0f) with integer thickness now use a texture-based
+ path, reducing the amount of vertices/indices and CPU/GPU usage. (#3245) [@Shironekoben]
+ - This change will facilitate the wider use of thick borders in future style changes.
+ - Requires an extra bit of texture space (~64x64 by default), relies on GPU bilinear filtering.
+ - Set `io.AntiAliasedLinesUseTex = false` to disable rendering using this method.
+ - Clear `ImFontAtlasFlags_NoBakedLines` in ImFontAtlas::Flags to disable baking data in texture.
+- ImDrawList: changed AddCircle(), AddCircleFilled() default num_segments from 12 to 0, effectively
+ enabling auto-tessellation by default. Tweak tessellation in Style Editor->Rendering section, or
+ by modifying the 'style.CircleSegmentMaxError' value. [@ShironekoBen]
+- ImDrawList: Fixed minor bug introduced in 1.75 where AddCircle() with 12 segments would generate
+ an extra vertex. (This bug was mistakenly marked as fixed in earlier 1.77 release). [@ShironekoBen]
+- Demo: Improved "Custom Rendering"->"Canvas" demo with a grid, scrolling and context menu.
+ Also showcase using InvisibleButton() with multiple mouse buttons flags.
+- Demo: Improved "Layout & Scrolling" -> "Clipping" section.
+- Demo: Improved "Layout & Scrolling" -> "Child Windows" section.
+- Style Editor: Added preview of circle auto-tessellation when editing the corresponding value.
+- Backends: OpenGL3: Added support for glad2 loader. (#3330) [@moritz-h]
+- Backends: Allegro 5: Fixed horizontal scrolling direction with mouse wheel / touch pads (it seems
+ like Allegro 5 reports it differently from GLFW and SDL). (#3394, #2424, #1463) [@nobody-special666]
+- Examples: Vulkan: Fixed GLFW+Vulkan and SDL+Vulkan clear color not being set. (#3390) [@RoryO]
+- CI: Emscripten has stopped their support for their fastcomp backend, switching to latest sdk [@Xipiryon]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.77 (Released 2020-06-29)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.77
+
+Breaking Changes:
+
+- Removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular() function. Please
+ note that this is a Beta api and will likely be reworked in order to support multi-DPI across
+ multiple monitors.
+- Renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete).
+ [NOTE: THIS WAS REVERTED IN 1.79]
+- Removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor
+ of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems.
+ Kept inline redirection function (will obsolete).
+- Removed obsoleted CalcItemRectClosestPoint() entry point (has been asserting since December 2017).
+
+Other Changes:
+
+- TreeNode: Fixed bug where BeginDragDropSource() failed when the _OpenOnDoubleClick flag is
+ enabled (bug introduced in 1.76, but pre-1.76 it would also fail unless the _OpenOnArrow
+ flag was also set, and _OpenOnArrow is frequently set along with _OpenOnDoubleClick).
+- TreeNode: Fixed bug where dragging a payload over a TreeNode() with either _OpenOnDoubleClick
+ or _OpenOnArrow would open the node. (#143)
+- Windows: Fix unintended feedback loops when resizing windows close to main viewport edges. [@rokups]
+- Tabs: Added style.TabMinWidthForUnselectedCloseButton settings:
+ - Set to 0.0f (default) to always make a close button appear on hover (same as Chrome, VS).
+ - Set to FLT_MAX to only display a close button when selected (merely hovering is not enough).
+ - Set to an intermediary value to toggle behavior based on width (same as Firefox).
+- Tabs: Added a ImGuiTabItemFlags_NoTooltip flag to disable the tooltip for individual tab item
+ (vs ImGuiTabBarFlags_NoTooltip for entire tab bar). [@Xipiryon]
+- Popups: All functions capable of opening popups (OpenPopup*, BeginPopupContext*) now take a new
+ ImGuiPopupFlags sets of flags instead of a mouse button index. The API is automatically backward
+ compatible as ImGuiPopupFlags is guaranteed to hold mouse button index in the lower bits.
+- Popups: Added ImGuiPopupFlags_NoOpenOverExistingPopup for OpenPopup*/BeginPopupContext* functions
+ to first test for the presence of another popup at the same level.
+- Popups: Added ImGuiPopupFlags_NoOpenOverItems for BeginPopupContextWindow() - similar to testing
+ for !IsAnyItemHovered() prior to doing an OpenPopup().
+- Popups: Added ImGuiPopupFlags_AnyPopupId and ImGuiPopupFlags_AnyPopupLevel flags for IsPopupOpen(),
+ allowing to check if any popup is open at the current level, if a given popup is open at any popup
+ level, if any popup is open at all.
+- Popups: Fix an edge case where programmatically closing a popup while clicking on its empty space
+ would attempt to focus it and close other popups. (#2880)
+- Popups: Fix BeginPopupContextVoid() when clicking over the area made unavailable by a modal. (#1636)
+- Popups: Clarified some of the comments and function prototypes.
+- Modals: BeginPopupModal() doesn't set the ImGuiWindowFlags_NoSavedSettings flag anymore, and will
+ not always be auto-centered. Note that modals are more similar to regular windows than they are to
+ popups, so api and behavior may evolve further toward embracing this. (#915, #3091)
+ Enforce centering using e.g. SetNextWindowPos(io.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f,0.5f)).
+- Metrics: Added a "Settings" section with some details about persistent ini settings.
+- Nav, Menus: Fix vertical wrap-around in menus or popups created with multiple appending calls to
+ BeginMenu()/EndMenu() or BeginPopup(0/EndPopup(). (#3223, #1207) [@rokups]
+- Drag and Drop: Fixed unintended fallback "..." tooltip display during drag operation when
+ drag source uses _SourceNoPreviewTooltip flags. (#3160) [@rokups]
+- Columns: Lower overhead on column switches and switching to background channel.
+ Benefits Columns but was primarily made with Tables in mind!
+- Fonts: Fix GetGlyphRangesKorean() end-range to end at 0xD7A3 (instead of 0xD79D). (#348, #3217) [@marukrap]
+- ImDrawList: Fixed an issue where draw command merging or primitive unreserve while crossing the
+ VtxOffset boundary would lead to draw commands with wrong VtxOffset. (#3129, #3163, #3232, #2591)
+ [@thedmd, @Shironekoben, @sergeyn, @ocornut]
+- ImDrawList, ImDrawListSplitter, Columns: Fixed an issue where changing channels with different
+ TextureId, VtxOffset would incorrectly apply new settings to draw channels. (#3129, #3163)
+ [@ocornut, @thedmd, @Shironekoben]
+- ImDrawList, ImDrawListSplitter, Columns: Fixed an issue where starting a split when current
+ VtxOffset was not zero would lead to draw commands with wrong VtxOffset. (#2591)
+- ImDrawList, ImDrawListSplitter, Columns: Fixed an issue where starting a split right after
+ a callback draw command would incorrectly override the callback draw command.
+- Misc, Freetype: Fix for rare case where FT_Get_Char_Index() succeeds but FT_Load_Glyph() fails.
+- Docs: Improved and moved font documentation to docs/FONTS.md so it can be readable on the web.
+ Updated various links/wiki accordingly. Added FAQ entry about DPI. (#2861) [@ButternCream, @ocornut]
+- CI: Added CI test to verify we're never accidentally dragging libstdc++ (on some compiler setups,
+ static constructors for non-pod data seems to drag in libstdc++ due to thread-safety concerns).
+ Fixed a static constructor which led to this dependency on some compiler setups. [@rokups]
+- Backends: Win32: Support for #define NOGDI, won't try to call GetDeviceCaps(). (#3137, #2327)
+- Backends: Win32: Fix _WIN32_WINNT < 0x0600 (MinGW defaults to 0x502 == Windows 2003). (#3183)
+- Backends: SDL: Report a zero display-size when window is minimized, consistent with other backends,
+ making more render/clipping code use an early out path.
+- Backends: OpenGL: Fixed handling of GL 4.5+ glClipControl(GL_UPPER_LEFT) by inverting the
+ projection matrix top and bottom values. (#3143, #3146) [@u3shit]
+- Backends: OpenGL: On OSX, if unspecified by app, made default GLSL version 150. (#3199) [@albertvaka]
+- Backends: OpenGL: Fixed loader auto-detection to not interfere with ES2/ES3 defines. (#3246) [@funchal]
+- Backends: Vulkan: Fixed error in if initial frame has no vertices. (#3177)
+- Backends: Vulkan: Fixed edge case where render callbacks wouldn't be called if the ImDrawData
+ structure didn't have any vertices. (#2697) [@kudaba]
+- Backends: OSX: Added workaround to avoid fast mouse clicks. (#3261, #1992, #2525) [@nburrus]
+- Examples: GLFW+Vulkan, SDL+Vulkan: Fix for handling of minimized windows. (#3259)
+- Examples: Apple: Fixed example_apple_metal and example_apple_opengl2 using imgui_impl_osx.mm
+ not forwarding right and center mouse clicks. (#3260) [@nburrus]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.76 (Released 2020-04-12)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.76
+
+Other Changes:
+
+- Drag and Drop, Nav: Disabling navigation arrow keys when drag and drop is active. In the docking
+ branch pressing arrow keys while dragging a window from a tab could trigger an assert. (#3025)
+- BeginMenu: Using same ID multiple times appends content to a menu. (#1207) [@rokups]
+- BeginMenu: Fixed a bug where SetNextWindowXXX data before a BeginMenu() would not be cleared
+ when the menu is not open. (#3030)
+- InputText: Fixed password fields displaying ASCII spaces as blanks instead of using the '*'
+ glyph. (#2149, #515)
+- Selectable: Fixed honoring style.SelectableTextAlign with unspecified size. (#2347, #2601)
+- Selectable: Allow using ImGuiSelectableFlags_SpanAllColumns in other columns than first. (#125)
+- TreeNode: Made clicking on arrow with _OpenOnArrow toggle the open state on the Mouse Down
+ event rather than the Mouse Down+Up sequence (this is rather standard behavior).
+- ColorButton: Added ImGuiColorEditFlags_NoBorder flag to remove the border normally enforced
+ by default for standalone ColorButton.
+- Nav: Fixed interactions with ImGuiListClipper, so e.g. Home/End result would not clip the
+ landing item on the landing frame. (#787)
+- Nav: Fixed currently focused item from ever being clipped by ItemAdd(). (#787)
+- Scrolling: Fixed scrolling centering API leading to non-integer scrolling values and initial
+ cursor position. This would often get fixed after the fix item submission, but using the
+ ImGuiListClipper as the first thing after Begin() could largely break size calculations. (#3073)
+- Added optional support for Unicode plane 1-16 (#2538, #2541, #2815) [@cloudwu, @samhocevar]
+ - Compile-time enable with '#define IMGUI_USE_WCHAR32' in imconfig.h.
+ - More onsistent handling of unsupported code points (0xFFFD).
+ - Surrogate pairs are supported when submitting UTF-16 data via io.AddInputCharacterUTF16(),
+ allowing for more complete CJK input.
+ - sizeof(ImWchar) goes from 2 to 4. IM_UNICODE_CODEPOINT_MAX goes from 0xFFFF to 0x10FFFF.
+ - Various structures such as ImFont, ImFontGlyphRangesBuilder will use more memory, this
+ is currently not particularly efficient.
+- Columns: undid the change in 1.75 were Columns()/BeginColumns() were preemptively limited
+ to 64 columns with an assert. (#3037, #125)
+- Window: Fixed a bug with child window inheriting ItemFlags from their parent when the child
+ window also manipulate the ItemFlags stack. (#3024) [@Stanbroek]
+- Font: Fixed non-ASCII space occasionally creating unnecessary empty looking polygons.
+- Misc: Added an explicit compile-time test for non-scoped IM_ASSERT() macros to redirect users
+ to a solution rather than encourage people to add braces in the codebase.
+- Misc: Added additional checks in EndFrame() to verify that io.KeyXXX values have not been
+ tampered with between NewFrame() and EndFrame().
+- Misc: Made default clipboard handlers for Win32 and OSX use a buffer inside the main context
+ instead of a static buffer, so it can be freed properly on Shutdown. (#3110)
+- Misc, Freetype: Fixed support for IMGUI_STB_RECT_PACK_FILENAME compile time directive
+ in imgui_freetype.cpp (matching support in the regular code path). (#3062) [@DonKult]
+- Metrics: Made Tools section more prominent. Showing wire-frame mesh directly hovering the ImDrawCmd
+ instead of requiring to open it. Added options to disable bounding box and mesh display.
+ Added notes on inactive/gc-ed windows.
+- Demo: Added black and white and color gradients to Demo>Examples>Custom Rendering.
+- CI: Added more tests on the continuous-integration server: extra warnings for Clang/GCC, building
+ SDL+Metal example, building imgui_freetype.cpp, more compile-time imconfig.h settings: disabling
+ obsolete functions, enabling 32-bit ImDrawIdx, enabling 32-bit ImWchar, disabling demo. [@rokups]
+- Backends: OpenGL3: Fixed version check mistakenly testing for GL 4.0+ instead of 3.2+ to enable
+ ImGuiBackendFlags_RendererHasVtxOffset, leaving 3.2 contexts without it. (#3119, #2866) [@wolfpld]
+- Backends: OpenGL3: Added include support for older glbinding 2.x loader. (#3061) [@DonKult]
+- Backends: Win32: Added ImGui_ImplWin32_EnableDpiAwareness(), ImGui_ImplWin32_GetDpiScaleForHwnd(),
+ ImGui_ImplWin32_GetDpiScaleForMonitor() helpers functions (backported from the docking branch).
+ Those functions makes it easier for example apps to support hi-dpi features without setting up
+ a manifest.
+- Backends: Win32: Calling AddInputCharacterUTF16() from WM_CHAR message handler in order to support
+ high-plane surrogate pairs. (#2815) [@cloudwu, @samhocevar]
+- Backends: SDL: Added ImGui_ImplSDL2_InitForMetal() for API consistency (even though the function
+ currently does nothing).
+- Backends: SDL: Fixed mapping for ImGuiKey_KeyPadEnter. (#3031) [@Davido71]
+- Examples: Win32+DX12: Fixed resizing main window, enabled debug layer. (#3087, #3115) [@sergeyn]
+- Examples: SDL+DX11: Fixed resizing main window. (#3057) [@joeslay]
+- Examples: Added SDL+Metal example application. (#3017) [@coding-jackalope]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.75 (Released 2020-02-10)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.75
+
+Breaking Changes:
+
+- Removed redirecting functions/enums names that were marked obsolete in 1.53 (December 2017):
+ - ShowTestWindow() -> use ShowDemoWindow()
+ - IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow)
+ - IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)
+ - SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f)
+ - GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing()
+ - ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg
+ - ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding
+ - ImGuiTreeNodeFlags_AllowOverlapMode -> use ImGuiTreeNodeFlags_AllowItemOverlap
+ - IMGUI_DISABLE_TEST_WINDOWS -> use IMGUI_DISABLE_DEMO_WINDOWS
+ If you were still using the old names, while you are cleaning up, considering enabling
+ IMGUI_DISABLE_OBSOLETE_FUNCTIONS in imconfig.h even temporarily to have a pass at finding
+ and removing up old API calls, if any remaining.
+- Removed implicit default parameter to IsMouseDragging(int button = 0) to be consistent
+ with other mouse functions (none of the other functions have it).
+- Obsoleted calling ImDrawList::PrimReserve() with a negative count (which was vaguely
+ documented and rarely if ever used). Instead we added an explicit PrimUnreserve() API
+ which can be implemented faster. Also clarified pre-existing constraints which weren't
+ documented (can only unreserve from the last reserve call). If you suspect you ever
+ used that feature before (very unlikely, but grep for call to PrimReserve in your code),
+ you can #define IMGUI_DEBUG_PARANOID in imconfig.h to catch existing calls. [@ShironekoBen]
+- ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius.
+- Limiting Columns()/BeginColumns() api to 64 columns with an assert. While the current code
+ technically supports it, future code may not so we're putting the restriction ahead.
+ [Undid that change in 1.76]
+- imgui_internal.h: changed ImRect() default constructor initializes all fields to 0.0f instead
+ of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by
+ adding points into it without explicit initialization, you may need to fix your initial value.
+
+Other Changes:
+
+- Inputs: Added ImGuiMouseButton enum for convenience (e.g. ImGuiMouseButton_Right=1).
+ We forever guarantee that the existing value will not changes so existing code is free to use 0/1/2.
+- Nav: Fixed a bug where the initial CTRL-Tab press while in a child window sometimes selected
+ the current root window instead of always selecting the previous root window. (#787)
+- ColorEdit: Fix label alignment when using ImGuiColorEditFlags_NoInputs. (#2955) [@rokups]
+- ColorEdit: In HSV display of a RGB stored value, attempt to locally preserve Saturation
+ when Value==0.0 (similar to changes done in 1.73 for Hue). Removed Hue editing lock since
+ those improvements in 1.73 makes them unnecessary. (#2722, #2770). [@rokups]
+- ColorEdit: "Copy As" context-menu tool shows hex values with a '#' prefix instead of '0x'.
+- ColorEdit: "Copy As" content-menu tool shows hex values both with/without alpha when available.
+- InputText: Fix corruption or crash when executing undo after clearing input with ESC, as a
+ byproduct we are allowing to later undo the revert with a CTRL+Z. (#3008).
+- InputText: Fix using a combination of _CallbackResize (e.g. for std::string binding), along with the
+ _EnterReturnsTrue flag along with the rarely used property of using an InputText without persisting
+ user-side storage. Previously if you had e.g. a local unsaved std::string and reading result back
+ from the widget, the user string object wouldn't be resized when Enter key was pressed. (#3009)
+- MenuBar: Fix minor clipping issue where occasionally a menu text can overlap the right-most border.
+- Window: Fix SetNextWindowBgAlpha(1.0f) failing to override alpha component. (#3007) [@Albog]
+- Window: When testing for the presence of the ImGuiWindowFlags_NoBringToFrontOnFocus flag we
+ test both the focused/clicked window (which could be a child window) and the root window.
+- ImDrawList: AddCircle(), AddCircleFilled() API can now auto-tessellate when provided a segment
+ count of zero. Alter tessellation quality with 'style.CircleSegmentMaxError'. [@ShironekoBen]
+- ImDrawList: Add AddNgon(), AddNgonFilled() API with a guarantee on the explicit segment count.
+ In the current branch they are essentially the same as AddCircle(), AddCircleFilled() but as
+ we will rework the circle rendering functions to use textures and automatic segment count
+ selection, those new api can fill a gap. [@ShironekoBen]
+- Columns: ImDrawList::Channels* functions now work inside columns. Added extra comments to
+ suggest using user-owned ImDrawListSplitter instead of ImDrawList functions. [@rokups]
+- Misc: Added ImGuiMouseCursor_NotAllowed enum so it can be used by more shared widgets. [@rokups]
+- Misc: Added IMGUI_DISABLE compile-time definition to make all headers and sources empty.
+- Misc: Disable format checks when using stb_printf, to allow using extra formats.
+ Made IMGUI_USE_STB_SPRINTF a properly documented imconfig.h flag. (#2954) [@loicmolinari]
+- Misc: Added misc/single_file/imgui_single_file.h, We use this to validate compiling all *.cpp
+ files in a same compilation unit. Actual users of that technique (also called "Unity builds")
+ can generally provide this themselves, so we don't really recommend you use this. [@rokups]
+- CI: Added PVS-Studio static analysis on the continuous-integration server. [@rokups]
+- Backends: GLFW, SDL, Win32, OSX, Allegro: Added support for ImGuiMouseCursor_NotAllowed. [@rokups]
+- Backends: GLFW: Added support for the missing mouse cursors newly added in GLFW 3.4+. [@rokups]
+- Backends: SDL: Wayland: use SDL_GetMouseState (because there is no global mouse state available
+ on Wayland). (#2800, #2802) [@NeroBurner]
+- Backends: GLFW, SDL: report Windows key (io.KeySuper) as always released. Neither GLFW nor SDL can
+ correctly report the key release in every cases (e.g. when using Win+V) causing problems with some
+ widgets. The next release of GLFW (3.4+) will have a fix for it. However since it is both difficult
+ and discouraged to make use of this key for Windows application anyway, we just hide it. (#2976)
+- Backends: Win32: Added support for #define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD to disable all
+ XInput using code, and IMGUI_IMPL_WIN32_DISABLE_LINKING_XINPUT to disable linking with XInput,
+ the later may be problematic if compiling with recent Windows SDK and you want your app to run
+ on Windows 7. You can instead try linking with Xinput9_1_0.lib instead. (#2716)
+- Backends: Glut: Improved FreeGLUT support for MinGW. (#3004) [@podsvirov]
+- Backends: Emscripten: Avoid forcefully setting IMGUI_DISABLE_FILE_FUNCTIONS. (#3005) [@podsvirov]
+- Examples: OpenGL: Explicitly adding -DIMGUI_IMPL_OPENGL_LOADER_GL3W to Makefile to match linking
+ settings (otherwise if another loader such as Glew is accessible, the OpenGL3 backend might
+ automatically use it). (#2919, #2798)
+- Examples: OpenGL: Added support for glbinding OpenGL loader. (#2870) [@rokups]
+- Examples: Emscripten: Demonstrating embedding fonts in Makefile and code. (#2953) [@Oipo]
+- Examples: Metal: Wrapped main loop in @autoreleasepool block to ensure allocations get freed
+ even if underlying system event loop gets paused due to app nap. (#2910, #2917) [@bear24rw]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.74 (Released 2019-11-25)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.74
+
+Breaking Changes:
+
+- Removed redirecting functions/enums names that were marked obsolete in 1.52 (October 2017):
+ - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed
+ - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows)
+ - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding()
+ - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f)
+ - ImFont::Glyph -> use ImFontGlyph
+ If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out
+ the new names or equivalent features, or see how they were implemented until 1.73.
+- Inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used
+ by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function.
+ If you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can
+ add +io.KeyRepeatDelay to it to compensate for the fix.
+ The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0).
+ Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay).
+ Fixed the code and altered default io.KeyRepeatRate,Delay from 0.250,0.050 to 0.300,0.050 to compensate.
+ If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you.
+- Misc: Renamed IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS to IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS. (#1038)
+- Misc: Renamed IMGUI_DISABLE_MATH_FUNCTIONS to IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS.
+- Fonts: ImFontAtlas::AddCustomRectRegular() now requires an ID larger than 0x110000 (instead of 0x10000) to
+ conform with supporting Unicode planes 1-16 in a future update. ID below 0x110000 will now assert.
+- Backends: DX12: Added extra ID3D12DescriptorHeap parameter to ImGui_ImplDX12_Init() function.
+ The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate]
+
+Other Changes:
+
+- InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787)
+- InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578)
+- Layout: Fixed a couple of subtle bounding box vertical positioning issues relating to the handling of text
+ baseline alignment. The issue would generally manifest when laying out multiple items on a same line,
+ with varying heights and text baseline offsets.
+ Some specific examples, e.g. a button with regular frame padding followed by another item with a
+ multi-line label and no frame padding, such as: multi-line text, small button, tree node item, etc.
+ The second item was correctly offset to match text baseline, and would interact/display correctly,
+ but it wouldn't push the contents area boundary low enough.
+- Scrollbar: Fixed an issue where scrollbars wouldn't display on the frame following a frame where
+ all child window contents would be culled.
+- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j]
+- TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow
+ incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897)
+- TreeNode: The collapsing arrow accepts click even if modifier keys are being held, facilitating
+ interactions with custom multi-selections patterns. (#2886, #1896, #1861)
+- TreeNode: Added IsItemToggledOpen() to explicitly query if item was just open/closed, facilitating
+ interactions with custom multi-selections patterns. (#1896, #1861)
+- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data
+ to clarify how they are used, and more comments redirecting to the demo code. (#2844)
+- Error handling: Assert if user mistakenly calls End() instead of EndChild() on a child window. (#1651)
+- Misc: Optimized storage of window settings data (reducing allocation count).
+- Misc: Windows: Do not use _wfopen() if IMGUI_DISABLE_WIN32_FUNCTIONS is defined. (#2815)
+- Misc: Windows: Disabled win32 function by default when building with UWP. (#2892, #2895)
+- Misc: Using static_assert() when using C++11, instead of our own construct (avoid zealous Clang warnings).
+- Misc: Added IMGUI_DISABLE_FILE_FUNCTIONS/IMGUI_DISABLE_DEFAULT_FILE_FUNCTION to nullify or disable
+ default implementation of ImFileXXX functions linking with fopen/fclose/fread/fwrite. (#2734)
+- Docs: Improved and moved FAQ to docs/FAQ.md so it can be readable on the web. [@ButternCream, @ocornut]
+- Docs: Moved misc/fonts/README.txt to docs/FONTS.txt.
+- Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page.
+- Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups]
+- Metrics: Show wire-frame mesh and approximate surface area when hovering ImDrawCmd. [@ShironekoBen]
+- Metrics: Expose basic details of each window key/value state storage.
+- Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled.
+- Examples: Emscripten: Removed BINARYEN_TRAP_MODE=clamp from Makefile which was removed in Emscripten 1.39.0
+ but required prior to 1.39.0, making life easier for absolutely no-one. (#2877, #2878) [@podsvirov]
+- Backends: OpenGL2: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with
+ legacy OpenGL applications. (#3000)
+- Backends: OpenGL3: Fix building with pre-3.2 GL loaders which do not expose glDrawElementsBaseVertex(),
+ using runtime GL version to decide if we set ImGuiBackendFlags_RendererHasVtxOffset. (#2866, #2852) [@dpilawa]
+- Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics]
+- Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v]
+- CI: Set up a bunch of continuous-integration tests using GitHub Actions. We now compile many of the example
+ applications on Windows, Linux, MacOS, iOS, Emscripten. Removed Travis integration. (#2865) [@rokups]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.73 (Released 2019-09-24)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.73
+
+Other Changes:
+
+- Nav, Scrolling: Added support for Home/End key. (#787)
+- ColorEdit: Disable Hue edit when Saturation==0 instead of letting Hue values jump around.
+- ColorEdit, ColorPicker: In HSV display of a RGB stored value, attempt to locally preserve Hue
+ when Saturation==0, which reduces accidentally lossy interactions. (#2722, #2770) [@rokups]
+- ColorPicker: Made rendering aware of global style alpha of the picker can be faded out. (#2711)
+ Note that some elements won't accurately fade down with the same intensity, and the color wheel
+ when enabled will have small overlap glitches with (style.Alpha < 1.0).
+- TabBar: Fixed single-tab not shrinking their width down.
+- TabBar: Fixed clicking on a tab larger than tab-bar width creating a bouncing feedback loop.
+- TabBar: Feed desired width (sum of unclipped tabs width) into layout system to allow for auto-resize. (#2768)
+ (before 1.71 tab bars fed the sum of current width which created feedback loops in certain situations).
+- TabBar: Improved shrinking for large number of tabs to avoid leaving extraneous space on the right side.
+ Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right.
+- Columns, Separator: Fixed a bug where non-visible separators within columns would alter the next row position
+ differently than visible ones.
+- SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton]
+- DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edits to the value.
+- DragScalar: Fixed dragging of unsigned values on ARM cpu (float to uint cast is undefined). (#2780) [@dBagrat]
+- TreeNode: Added ImGuiTreeNodeFlags_SpanAvailWidth flag. (#2451, #2438, #1897) [@Melix19, @PathogenDavid]
+ This extends the hit-box to the right-most edge, even if the node is not framed.
+ (Note: this is not the default in order to allow adding other items on the same line. In the future we will
+ aim toward refactoring the hit-system to be front-to-back, allowing more natural overlapping of items,
+ and then we will be able to make this the default.)
+- TreeNode: Added ImGuiTreeNodeFlags_SpanFullWidth flag. This extends the hit-box to both the left-most and
+ right-most edge of the working area, bypassing indentation.
+- CollapsingHeader: Added support for ImGuiTreeNodeFlags_Bullet and ImGuiTreeNodeFlags_Leaf on framed nodes,
+ mostly for consistency. (#2159, #2160) [@goran-w]
+- Selectable: Added ImGuiSelectableFlags_AllowItemOverlap flag in public api (was previously internal only).
+- Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639)
+- Font: Better ellipsis ("...") drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly
+ unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set.
+ Otherwise we render ellipsis using '.' from the font from where we trim excessive spacing to make it as narrow
+ as possible. (#2775) [@rokups]
+- ImDrawList: Clarified the name of many parameters so reading the code is a little easier. (#2740)
+- ImDrawListSplitter: Fixed merging channels if the last submitted draw command used a different texture. (#2506)
+- Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94)
+- ImVector: Added find(), find_erase(), find_erase_unsorted() helpers.
+- Added a mechanism to compact/free the larger allocations of unused windows (buffers are compacted when
+ a window is unused for 60 seconds, as per io.ConfigWindowsMemoryCompactTimer = 60.0f). Note that memory
+ usage has never been reported as a problem, so this is merely a touch of overzealous luxury. (#2636)
+- Documentation: Various tweaks and improvements to the README page. [@ker0chan]
+- Backends: OpenGL3: Tweaked initialization code allow application calling ImGui_ImplOpenGL3_CreateFontsTexture()
+ before ImGui_ImplOpenGL3_NewFrame(), which sometimes can be convenient.
+- Backends: OpenGL3: Attempt to automatically detect default GL loader by using __has_include. (#2798) [@o-micron]
+- Backends: DX11: Fixed GSGetShader() call not passing an initialized instance count, which would
+ generally make the DX11 debug layer complain (bug added in 1.72).
+- Backends: Vulkan: Added support for specifying multisample count. Set 'ImGui_ImplVulkan_InitInfo::MSAASamples' to
+ one of the VkSampleCountFlagBits values to use, default is non-multisampled as before. (#2705, #2706) [@vilya]
+- Examples: OSX: Fix example_apple_opengl2/main.mm not forwarding mouse clicks and drags correctly. (#1961, #2710)
+ [@intonarumori, @ElectricMagic]
+- Misc: Updated stb_rect_pack.h from 0.99 to 1.00 (fixes by @rygorous: off-by-1 bug in best-fit heuristic,
+ fix handling of rectangles too large to fit inside texture). (#2762) [@tido64]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.72b (Released 2019-07-31)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.72b
+
+Other Changes:
+
+- Nav, Scrolling: Fixed programmatic scroll leading to a slightly incorrect scroll offset when
+ the window has decorations or a menu-bar (broken in 1.71). This was mostly noticeable when
+ a keyboard/gamepad movement led to scrolling the view, or using e.g. SetScrollHereY() function.
+- Nav: Made hovering non-MenuItem Selectable not re-assign the source item for keyboard navigation.
+- Nav: Fixed an issue with NavFlattened window flag (beta) where widgets not entirely fitting
+ in child window (often selectables because of their protruding sides) would be not considered
+ as entry points to to navigate toward the child window. (#787)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.72 (Released 2019-07-27)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.72
+
+Breaking Changes:
+
+- Removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017):
+ - ImGuiCol_Column*, ImGuiSetCond_* enums.
+ - IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow() functions.
+ - IMGUI_ONCE_UPON_A_FRAME macro.
+ If you were still using the old names, read "API Breaking Changes" section of imgui.cpp to find out
+ the new names or equivalent features.
+- Renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete).
+- Removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()).
+ Kept redirection function (will obsolete). (#581, #324)
+
+Other Changes:
+
+- Scrolling: Made mouse-wheel scrolling lock the underlying window until the mouse is moved again or
+ until a short delay expires (~2 seconds). This allow uninterrupted scroll even if child windows are
+ passing under the mouse cursor. (#2604)
+- Scrolling: Made it possible for mouse wheel and navigation-triggered scrolling to override a call to
+ SetScrollX()/SetScrollY(), making it possible to use a simpler stateless pattern for auto-scrolling:
+ // (Submit items..)
+ if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) // If scrolling at the already at the bottom..
+ ImGui::SetScrollHereY(1.0f); // ..make last item fully visible
+- Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco]
+- Scrolling: Mouse wheel scrolling while hovering a child window is automatically forwarded to parent window
+ if ScrollMax is zero on the scrolling axis.
+ Also still the case if ImGuiWindowFlags_NoScrollWithMouse is set (not new), but previously the forwarding
+ would be disabled if ImGuiWindowFlags_NoScrollbar was set on the child window, which is not the case
+ any more. Forwarding can still be disabled by setting ImGuiWindowFlags_NoInputs. (amend #1502, #1380).
+- Window: Fixed InnerClipRect right-most coordinates using wrong padding setting (introduced in 1.71).
+- Window: Fixed old SetWindowFontScale() api value from not being inherited by child window. Added
+ comments about the right way to scale your UI (load a font at the right side, rebuild atlas, scale style).
+- Scrollbar: Avoid overlapping the opposite side when window (often a child window) is forcibly too small.
+- Combo: Hide arrow when there's not enough space even for the square button.
+- InputText: Testing for newly added ImGuiKey_KeyPadEnter key. (#2677, #2005) [@amc522]
+- TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive).
+- Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column
+ would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666)
+- Columns: Made the right-most edge reaches up to the clipping rectangle (removing half of WindowPadding.x
+ worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset
+ the right-most column, otherwise it's clipping width won't match the other columns). (#125, #2666)
+- Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666)
+- Columns: Made GetColumnOffset() and GetColumnWidth() behave when there's no column set, consistently with
+ other column functions. (#2683)
+- InputTextMultiline: Fixed vertical scrolling tracking glitch.
+- Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because
+ of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d).
+- Style: Attenuated default opacity of ImGuiCol_Separator in Classic and Light styles.
+- Style: Added style.ColorButtonPosition (left/right, defaults to ImGuiDir_Right) to move the color button
+ of ColorEdit3/ColorEdit4 functions to either side of the inputs.
+- IO: Added ImGuiKey_KeyPadEnter and support in various backends (previously backends would need to
+ specifically redirect key-pad keys to their regular counterpart). This is a temporary attenuating measure
+ until we actually refactor and add whole sets of keys into the ImGuiKey enum. (#2677, #2005) [@amc522]
+- Misc: Made Button(), ColorButton() not trigger an "edited" event leading to IsItemDeactivatedAfterEdit()
+ returning true. This also effectively make ColorEdit4() not incorrect trigger IsItemDeactivatedAfterEdit()
+ when clicking the color button to open the picker popup. (#1875)
+- Misc: Added IMGUI_DISABLE_METRICS_WINDOW imconfig.h setting to explicitly compile out ShowMetricsWindow().
+- Debug, Metrics: Added "Tools->Item Picker" tool which allow clicking on a widget to break in the debugger
+ within the item code. The tool calls IM_DEBUG_BREAK() which can be redefined in imconfig.h if needed.
+- ImDrawList: Fixed CloneOutput() helper crashing. (#1860) [@gviot]
+- ImDrawList::ChannelsSplit(), ImDrawListSplitter: Fixed an issue with merging draw commands between
+ channel 0 and 1. (#2624)
+- ImDrawListSplitter: Fixed memory leak when using low-level split api (was not affecting ImDrawList api,
+ also this type was added in 1.71 and not advertised as a public-facing feature).
+- Fonts: binary_to_compressed_c.cpp: Display an error message if failing to open/read the input font file.
+- Demo: Log, Console: Using a simpler stateless pattern for auto-scrolling.
+- Demo: Widgets: Showing how to use the format parameter of Slider/Drag functions to display the name
+ of an enum value instead of the underlying integer value.
+- Demo: Renamed the "Help" menu to "Tools" (more accurate).
+- Backends: DX10/DX11: Backup, clear and restore Geometry Shader is any is bound when calling renderer.
+- Backends: DX11: Clear Hull Shader, Domain Shader, Compute Shader before rendering. Not backing/restoring them.
+- Backends: OSX: Disabled default native Mac clipboard copy/paste implementation in core library (added in 1.71),
+ because it needs application to be linked with '-framework ApplicationServices'. It can be explicitly
+ enabled back by using '#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS' in imconfig.h. Re-added
+ equivalent using NSPasteboard api in the imgui_impl_osx.mm experimental backend. (#2546)
+- Backends: SDL2: Added ImGui_ImplSDL2_InitForD3D() function to make D3D support more visible.
+ (#2482, #2632) [@josiahmanson]
+- Examples: Added SDL2+DirectX11 example application. (#2632, #2612, #2482) [@vincenthamm]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.71 (Released 2019-06-12)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.71
+
+Breaking Changes:
+
+- IO: changed AddInputCharacter(unsigned short c) signature to AddInputCharacter(unsigned int c).
+- Renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
+- Window: rendering of child windows outer decorations (e.g. bg color, border, scrollbars) is now
+ performed as part of their parent window, avoiding the creation of an extraneous draw commands.
+ If you have overlapping child windows with decorations, and relied on their relative z-order to be
+ mapped to submission their order, this will affect your rendering. The optimization is disabled
+ if the parent window has no visual output because it appears to be the most common situation leading
+ to the creation of overlapping child windows. Please reach out if you are affected by this change!
+
+Other Changes:
+
+- Window: clarified behavior of SetNextWindowContentSize(). Content size is defined as the size available
+ after removal of WindowPadding on each sides. So SetNextWindowContentSize(ImVec2(100,100)) + auto-resize
+ will always allow submitting a 100x100 item without creating a scrollbar, regarding of WindowPadding.
+ The exact meaning of ContentSize for decorated windows was previously ill-defined.
+- Window: Fixed auto-resize with AlwaysVerticalScrollbar or AlwaysHorizontalScrollbar flags.
+- Window: Fixed one case where auto-resize by double-clicking the resize grip would make either scrollbar
+ appear for a single frame after the resize.
+- Separator: Revert 1.70 "Declare its thickness (1.0f) to the layout" change. It's not incorrect
+ but it breaks existing some layout patterns. Will return back to it when we expose Separator flags.
+- Fixed InputScalar, InputScalarN, SliderScalarN, DragScalarN with non-visible label from inserting
+ style.ItemInnerSpacing.x worth of trailing spacing.
+- Fixed InputFloatX, SliderFloatX, DragFloatX functions erroneously reporting IsItemEdited() multiple
+ times when the text input doesn't match the formatted output value (e.g. input "1" shows "1.000").
+ It wasn't much of a problem because we typically use the return value instead of IsItemEdited() here.
+- Fixed uses of IsItemDeactivated(), IsItemDeactivatedAfterEdit() on multi-components widgets and
+ after EndGroup(). (#2550, #1875)
+- Fixed crash when appending with BeginMainMenuBar() more than once and no other window are showing. (#2567)
+- ColorEdit: Fixed the color picker popup only displaying inputs as HSV instead of showing multiple
+ options. (#2587, broken in 1.69 by #2384).
+- CollapsingHeader: Better clipping when a close button is enabled and it overlaps the label. (#600)
+- Scrollbar: Minor bounding box adjustment to cope with various border size.
+- Scrollbar, Style: Changed default style.ScrollbarSize from 16 to 14.
+- Combo: Fixed rounding not applying with the ImGuiComboFlags_NoArrowButton flag. (#2607) [@DucaRii]
+- Nav: Fixed gamepad/keyboard moving of window affecting contents size incorrectly, sometimes leading
+ to scrollbars appearing during the movement.
+- Nav: Fixed rare crash when e.g. releasing Alt-key while focusing a window with a menu at the same
+ frame as clearing the focus. This was in most noticeable in backends such as Glfw and SDL which
+ emits key release events when focusing another viewport, leading to Alt+clicking on void on another
+ viewport triggering the issue. (#2609)
+- TreeNode, CollapsingHeader: Fixed highlight frame not covering horizontal area fully when using
+ horizontal scrolling. (#2211, #2579)
+- TabBar: Fixed BeginTabBar() within a window with horizontal scrolling from creating a feedback
+ loop with the horizontal contents size.
+- Columns: Fixed Columns() within a window with horizontal scrolling from not covering the full
+ horizontal area (previously only worked with an explicit contents size). (#125)
+- Columns: Fixed Separator from creating an extraneous draw command. (#125)
+- Columns: Fixed Selectable with SpanAllColumns flag from creating an extraneous draw command. (#125)
+- Style: Added style.WindowMenuButtonPosition (left/right, defaults to ImGuiDir_Left) to move the
+ collapsing/docking button to the other side of the title bar.
+- Style: Made window close button cross slightly smaller.
+- Log/Capture: Fixed BeginTabItem() label not being included in a text log/capture.
+- ImDrawList: Added ImDrawCmd::VtxOffset value to support large meshes (64k+ vertices) using 16-bit indices.
+ The renderer backend needs to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' to enable
+ this, and honor the ImDrawCmd::VtxOffset field. Otherwise the value will always be zero. (#2591)
+ This has the advantage of preserving smaller index buffers and allowing to execute on hardware that do not
+ support 32-bit indices. Most examples backends have been modified to support the VtxOffset field.
+- ImDrawList: Added ImDrawCmd::IdxOffset value, equivalent to summing element count for each draw command.
+ This is provided for convenience and consistency with VtxOffset. (#2591)
+- ImDrawCallback: Allow to override the signature of ImDrawCallback by #define-ing it. This is meant to
+ facilitate custom rendering backends passing local render-specific data to the draw callback.
+- ImFontAtlas: FreeType: Added RasterizerFlags::Monochrome flag to disable font anti-aliasing. Combine
+ with RasterizerFlags::MonoHinting for best results. (#2545) [@HolyBlackCat]
+- ImFontGlyphRangesBuilder: Fixed unnecessarily over-sized buffer, which incidentally was also not
+ fully cleared. Fixed edge-case overflow when adding character 0xFFFF. (#2568). [@NIKE3500]
+- Demo: Added full "Dear ImGui" prefix to the title of "Dear ImGui Demo" and "Dear ImGui Metrics" windows.
+- Backends: Add native Mac clipboard copy/paste default implementation in core library to match what we are
+ dealing with Win32, and to facilitate integration in custom engines. (#2546) [@andrewwillmott]
+- Backends: OSX: imgui_impl_osx: Added mouse cursor support. (#2585, #1873) [@actboy168]
+- Examples/Backends: DirectX9/10/11/12, Metal, Vulkan, OpenGL3 (Desktop GL only): Added support for large meshes
+ (64k+ vertices) with 16-bit indices, enable 'ImGuiBackendFlags_RendererHasVtxOffset' in those backends. (#2591)
+- Examples/Backends: Don't filter characters under 0x10000 before calling io.AddInputCharacter(),
+ the filtering is done in io.AddInputCharacter() itself. This is in prevision for fuller Unicode
+ support. (#2538, #2541)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.70 (Released 2019-05-06)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.70
+
+Breaking Changes:
+
+- ImDrawList: Improved algorithm for mitre joints on thick lines, preserving correct thickness
+ up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines,
+ they will appear a little thicker now. (#2518) [@rmitton]
+- Obsoleted GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead.
+ Kept inline redirection function.
+- Examples: Vulkan: Added MinImageCount/ImageCount fields in ImGui_ImplVulkan_InitInfo, required
+ during initialization to specify the number of in-flight image requested by swap chains.
+ (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). (#2071, #1677) [@nathanvoglsam]
+- Examples: Vulkan: Tidying up the demo/internals helpers (most engine/app should not rely
+ on them but it is possible you have!).
+
+Other Changes:
+
+- ImDrawList: Added ImDrawCallback_ResetRenderState, a special ImDrawList::AddCallback() value
+ to request the renderer backend to reset its render state. (#2037, #1639, #2452)
+ Examples: Added support for ImDrawCallback_ResetRenderState in all renderer backends. Each
+ renderer code setting up initial render state has been moved to a function so it could be
+ called at the start of rendering and when a ResetRenderState is requested. [@ocornut, @bear24rw]
+- InputText: Fixed selection background rendering one frame after the cursor movement when
+ first transitioning from no-selection to has-selection. (Bug in 1.69) (#2436) [@Nazg-Gul]
+- InputText: Work-around for buggy standard libraries where isprint('\t') returns true. (#2467, #1336)
+- InputText: Fixed ImGuiInputTextFlags_AllowTabInput leading to two tabs characters being inserted
+ if the backend provided both Key and Character input. (#2467, #1336)
+- Layout: Added SetNextItemWidth() helper to avoid using PushItemWidth/PopItemWidth() for single items.
+ Note that SetNextItemWidth() currently only affect the same subset of items as PushItemWidth(),
+ generally referred to as the large framed+labeled items. Because the new SetNextItemWidth()
+ function is explicit we may later extend its effect to more items.
+- Layout: Fixed PushItemWidth(-width) for right-side alignment laying out some items (button, listbox, etc.)
+ with negative sizes if the 'width' argument was smaller than the available width at the time of item
+ submission.
+- Window: Fixed window with the AlwaysAutoResize flag unnecessarily extending their hovering boundaries
+ by a few pixels (this is used to facilitate resizing from borders when available for a given window).
+ One of the noticeable minor side effect was that navigating menus would have had a tendency to disable
+ highlight from parent menu items earlier than necessary while approaching the child menu.
+- Window: Close button is horizontally aligned with style.FramePadding.x.
+- Window: Fixed contents region being off by WindowBorderSize amount on the right when scrollbar is active.
+- Window: Fixed SetNextWindowSizeConstraints() with non-rounded positions making windows drift. (#2067, #2530)
+- Popups: Closing a popup restores the focused/nav window in place at the time of the popup opening,
+ instead of restoring the window that was in the window stack at the time of the OpenPopup call. (#2517)
+ Among other things, this allows opening a popup while no window are focused, and pressing Escape to
+ clear the focus again.
+- Popups: Fixed right-click from closing all popups instead of aiming at the hovered popup level
+ (regression in 1.67).
+- Selectable: With ImGuiSelectableFlags_AllowDoubleClick doesn't return true on the mouse button release
+ following the double-click. Only first mouse release + second mouse down (double-click) returns true.
+ Likewise for internal ButtonBehavior() with both _PressedOnClickRelease | _PressedOnDoubleClick. (#2503)
+- GetMouseDragDelta(): also returns the delta on the mouse button released frame. (#2419)
+- GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero.
+- Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood]
+- PlotLines, PlotHistogram: Ignore NaN values when calculating min/max bounds. (#2485)
+- Columns: Fixed boundary of clipping being off by 1 pixel within the left column. (#125)
+- Separator: Declare its thickness (1.0f) to the layout, making items around separator more symmetrical.
+- Combo, Slider, Scrollbar: Improve rendering in situation when there's only a few pixels available (<3 pixels).
+- Nav: Fixed Drag/Slider functions going into text input mode when keyboard CTRL is held while pressing NavActivate.
+- Drag and Drop: Fixed drag source with ImGuiDragDropFlags_SourceAllowNullID and null ID from receiving click
+ regardless of being covered by another window (it didn't honor correct hovering rules). (#2521)
+- ImDrawList: Improved algorithm for mitre joints on thick lines, preserving correct thickness up to 90 degrees
+ angles, also faster to output. (#2518) [@rmitton]
+- Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert
+ to using the ImGui::MemAlloc()/MemFree() calls directly.
+- Misc: Made IMGUI_CHECKVERSION() macro also check for matching size of ImDrawIdx.
+- Metrics: Added "Show windows rectangles" tool to visualize the different rectangles.
+- Demo: Improved trees in columns demo.
+- Examples: OpenGL: Added a test GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized
+ GL function loaders early, and help users understand what they are missing. (#2421)
+- Examples: SDL: Added support for SDL_GameController gamepads (enable with ImGuiConfigFlags_NavEnableGamepad). (#2509) [@DJLink]
+- Examples: Emscripten: Added Emscripten+SDL+GLES2 example. (#2494, #2492, #2351, #336) [@nicolasnoble, @redblobgames]
+- Examples: Metal: Added Glfw+Metal example. (#2527) [@bear24rw]
+- Examples: OpenGL3: Minor tweaks + not calling glBindBuffer more than necessary in the render loop.
+- Examples: Vulkan: Fixed in-flight buffers issues when using multi-viewports. (#2461, #2348, #2378, #2097)
+- Examples: Vulkan: Added missing support for 32-bit indices (#define ImDrawIdx unsigned int).
+- Examples: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
+- Examples: Vulkan: Added ImGui_ImplVulkan_SetMinImageCount() to change min image count at runtime. (#2071) [@nathanvoglsam]
+- Examples: DirectX9: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). (#2454)
+- Examples: DirectX10/11/12, Allegro, Marmalade: Render functions early out when display size is zero (minimized). (#2496)
+- Examples: GLUT: Fixed existing FreeGLUT example to work with regular GLUT. (#2465) [@andrewwillmott]
+- Examples: GLUT: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h. (#2465) [@andrewwillmott]
+- Examples: GLUT: Made io.DeltaTime always > 0. (#2430)
+- Examples: Visual Studio: Updated default platform toolset+sdk in vcproj files from v100+sdk7 (vs2010)
+ to v110+sdk8 (vs2012). This is mostly so we can remove reliance on DXSDK_DIR for the DX10/DX11 example,
+ which if existing and when switching to recent SDK ends up conflicting and creating warnings.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.69 (Released 2019-03-13)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.69
+
+Breaking Changes:
+
+- Renamed ColorEdit/ColorPicker's ImGuiColorEditFlags_RGB/_HSV/_HEX flags to respectively
+ ImGuiColorEditFlags_DisplayRGB/_DisplayHSV/_DisplayHex. This is because the addition of
+ new flag ImGuiColorEditFlags_InputHSV makes the earlier one ambiguous.
+ Kept redirection enum values (will obsolete). (#2384) [@haldean]
+- Renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete). (#2391)
+
+Other Changes:
+
+- Added GetBackgroundDrawList() helper to quickly get access to a ImDrawList that will be rendered
+ behind every other windows. (#2391, #545)
+- DragScalar, InputScalar, SliderScalar: Added support for u8/s8/u16/s16 data types (ImGuiDataType_S8, etc.)
+ We are reusing function instances of larger types to reduce code size. (#643, #320, #708, #1011)
+- Added InputTextWithHint() to display a description/hint in the text box when no text
+ has been entered. (#2400) [@Organic-Code, @ocornut]
+- Nav: Fixed a tap on AltGR (e.g. German keyboard) from navigating to the menu layer.
+- Nav: Fixed Ctrl+Tab keeping active InputText() of a previous window active after the switch. (#2380)
+- Fixed IsItemDeactivated()/IsItemDeactivatedAfterEdit() from not correctly returning true
+ when tabbing out of a focusable widget (Input/Slider/Drag) in most situations. (#2215, #1875)
+- InputInt, InputFloat, InputScalar: Fix to keep the label of the +/- buttons centered when
+ style.FramePadding.x is abnormally larger than style.FramePadding.y. Since the buttons are
+ meant to be square (to align with e.g. color button) we always use FramePadding.y. (#2367)
+- InputInt, InputScalar: +/- buttons now respects the natural type limits instead of
+ overflowing or underflowing the value.
+- InputText: Fixed an edge case crash that would happen if another widget sharing the same ID
+ is being swapped with an InputText that has yet to be activated.
+- InputText: Fixed various display corruption related to swapping the underlying buffer while
+ a input widget is active (both for writable and read-only paths). Often they would manifest
+ when manipulating the scrollbar of a multi-line input text.
+- ColorEdit, ColorPicker, ColorButton: Added ImGuiColorEditFlags_InputHSV to manipulate color
+ values encoded as HSV (in order to avoid HSV<>RGB round trips and associated singularities).
+ (#2383, #2384) [@haldean]
+- ColorPicker: Fixed a bug/assertion when displaying a color picker in a collapsed window
+ while dragging its title bar. (#2389)
+- ColorEdit: Fixed tooltip not honoring the ImGuiColorEditFlags_NoAlpha contract of never
+ reading the 4th float in the array (value was read and discarded). (#2384) [@haldean]
+- MenuItem, Selectable: Fixed disabled widget interfering with navigation (fix c2db7f63 in 1.67).
+- TabBar: Fixed a crash when using many BeginTabBar() recursively (didn't affect docking). (#2371)
+- TabBar: Added extra mis-usage error recovery. Past the assert, common mis-usage don't lead to
+ hard crashes any more, facilitating integration with scripting languages. (#1651)
+- TabBar: Fixed ImGuiTabItemFlags_SetSelected being ignored if the tab is not visible (with
+ scrolling policy enabled) or if is currently appearing.
+- TabBar: Fixed Tab tooltip code making drag and drop tooltip disappear during the frame where
+ the drag payload activate a tab.
+- TabBar: Reworked scrolling policy (when ImGuiTabBarFlags_FittingPolicyScroll is set) to
+ teleport the view when aiming at a tab far away the visible section, and otherwise accelerate
+ the scrolling speed to cap the scrolling time to 0.3 seconds.
+- Text: Fixed large Text/TextUnformatted calls not feeding their size into layout when starting
+ below the lower point of the current clipping rectangle. This bug has been there since v1.0!
+ It was hardly noticeable but would affect the scrolling range, which in turn would affect
+ some scrolling request functions when called during the appearing frame of a window.
+- Plot: Fixed divide-by-zero in PlotLines() when passing a count of 1. (#2387) [@Lectem]
+- Log/Capture: Fixed LogXXX functions emitting extraneous leading carriage return.
+- Log/Capture: Fixed an issue when empty string on a new line would not emit a carriage return.
+- Log/Capture: Fixed LogXXX functions 'auto_open_depth' parameter being treated as an absolute
+ tree depth instead of a relative one.
+- Log/Capture: Fixed CollapsingHeader trailing ascii representation being "#" instead of "##".
+- ImFont: Added GetGlyphRangesVietnamese() helper. (#2403)
+- Misc: Asserting in NewFrame() if style.WindowMinSize is zero or smaller than (1.0f,1.0f).
+- Demo: Using GetBackgroundDrawList() and GetForegroundDrawList() in "Custom Rendering" demo.
+- Demo: InputText: Demonstrating use of ImGuiInputTextFlags_CallbackResize. (#2006, #1443, #1008).
+- Examples: GLFW, SDL: Preserve DisplayFramebufferScale when main viewport is minimized.
+ (This is particularly useful for the viewport branch because we are not supporting per-viewport
+ frame-buffer scale. It fixes windows not refreshing when main viewport is minimized.) (#2416)
+- Examples: OpenGL: Fix to be able to run on ES 2.0 / WebGL 1.0. [@rmitton, @gabrielcuvillier]
+- Examples: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN
+ even if the OpenGL headers/loader happens to define the value. (#2366, #2186)
+- Examples: Allegro: Added support for touch events (emulating mouse). (#2219) [@dos1]
+- Examples: DirectX9: Minor changes to match the other DirectX examples more closely. (#2394)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.68 (Released 2019-02-19)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.68
+
+Breaking Changes:
+
+- Removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already).
+- Made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame).
+ If for some reason your time step calculation gives you a zero value, replace it with a arbitrarily small value!
+
+Other Changes:
+
+- Added .editorconfig file for text editors to standardize using spaces. (#2038) [@kudaba]
+- ImDrawData: Added FramebufferScale field (currently a copy of the value from io.DisplayFramebufferScale).
+ This is to allow render functions being written without pulling any data from ImGuiIO, allowing incoming
+ multi-viewport feature to behave on Retina display and with multiple displays.
+ If you are not using a custom backend, please update your render function code ahead of time,
+ and use draw_data->FramebufferScale instead of io.DisplayFramebufferScale. (#2306, #1676)
+- Added IsItemActivated() as an extension to the IsItemDeactivated/IsItemDeactivatedAfterEdit functions
+ which are useful to implement variety of undo patterns. (#820, #956, #1875)
+- InputText: Fixed a bug where ESCAPE would not restore the initial value in all situations. (#2321) [@relick]
+- InputText: Fixed a bug where ESCAPE would be first captured by the Keyboard Navigation code. (#2321, #787)
+- InputText: Fixed redo buffer exhaustion handling (rare) which could corrupt the undo character buffer. (#2333)
+ The way the redo/undo buffers work would have made it generally unnoticeable to the user.
+- Fixed range-version of PushID() and GetID() not honoring the ### operator to restart from the seed value.
+- Fixed CloseCurrentPopup() on a child-menu of a modal incorrectly closing the modal. (#2308)
+- Tabs: Added ImGuiTabBarFlags_TabListPopupButton flag to show a popup button on manual tab bars. (#261, #351)
+- Tabs: Removed ImGuiTabBarFlags_NoTabListPopupButton which was available in 1.67 but actually had zero use.
+- Tabs: Fixed a minor clipping glitch when changing style's FramePadding from frame to frame.
+- Tabs: Fixed border (when enabled) so it is aligned correctly mid-pixel and appears as bright as other borders.
+- Style, Selectable: Added ImGuiStyle::SelectableTextAlign and ImGuiStyleVar_SelectableTextAlign. (#2347) [@haldean]
+- Menus: Tweaked horizontal overlap between parent and child menu (to help convey relative depth)
+ from using style.ItemSpacing.x to style.ItemInnerSpacing.x, the later being expected to be smaller. (#1086)
+- RadioButton: Fixed label horizontal alignment to precisely match Checkbox().
+- Window: When resizing from an edge, the border is more visible and better follow the rounded corners.
+- Window: Fixed initial width of collapsed windows not taking account of contents width (broken in 1.67). (#2336, #176)
+- Scrollbar: Fade out and disable interaction when too small, in order to facilitate using the resize grab on very
+ small window, as well as reducing visual noise/overlap.
+- ListBox: Better optimized when clipped / non-visible.
+- InputTextMultiline: Better optimized when clipped / non-visible.
+- Font: Fixed high-level ImGui::CalcTextSize() used by most widgets from erroneously subtracting 1.0f*scale to
+ calculated text width. Among noticeable side-effects, it would make sequences of repeated Text/SameLine calls
+ not align the same as a single call, and create mismatch between high-level size calculation and those performed
+ with the lower-level ImDrawList api. (#792) [@SlNPacifist]
+- Font: Fixed building atlas when specifying duplicate/overlapping ranges within a same font. (#2353, #2233)
+- ImDrawList: Fixed AddCircle(), AddCircleFilled() angle step being off, which was visible when drawing a "circle"
+ with a small number of segments (e.g. an hexagon). (#2287) [@baktery]
+- ImGuiTextBuffer: Added append() function (unformatted).
+- ImFontAtlas: Added 0x2000-0x206F general punctuation range to default ChineseFull/ChineseSimplifiedCommon ranges. (#2093)
+- ImFontAtlas: FreeType: Added support for imgui allocators + custom FreeType only SetAllocatorFunctions. (#2285) [@Vuhdo]
+- ImFontAtlas: FreeType: Fixed using imgui_freetype.cpp in unity builds. (#2302)
+- Demo: Fixed "Log" demo not initializing properly, leading to the first line not showing before a Clear. (#2318) [@bluescan]
+- Demo: Added "Auto-scroll" option in Log/Console demos. (#2300) [@nicolasnoble, @ocornut]
+- Examples: Metal, OpenGL2, OpenGL3, Vulkan: Fixed offsetting of clipping rectangle with ImDrawData::DisplayPos != (0,0)
+ when the display frame-buffer scale scale is not (1,1). While this doesn't make a difference when using master branch,
+ this is effectively fixing support for multi-viewport with Mac Retina Displays on those examples. (#2306) [@rasky, @ocornut]
+ Also using ImDrawData::FramebufferScale instead of io.DisplayFramebufferScale.
+- Examples: Clarified the use the ImDrawData::DisplayPos to offset clipping rectangles.
+- Examples: Win32: Using GetForegroundWindow()+IsChild() instead of GetActiveWindow() to be compatible with windows created
+ in a different thread or parent. (#1951, #2087, #2156, #2232) [many people]
+- Examples: SDL: Using the SDL_WINDOW_ALLOW_HIGHDPI flag. (#2306, #1676) [@rasky]
+- Examples: Win32: Added support for XInput gamepads (if ImGuiConfigFlags_NavEnableGamepad is enabled).
+- Examples: Win32: Added support for mouse buttons 4 and 5 via WM_XBUTTON* messages. (#2264)
+- Examples: DirectX9: Explicitly disable fog (D3DRS_FOGENABLE) before drawing in case user state has it set. (#2288, #2230)
+- Examples: OpenGL2: Added #define GL_SILENCE_DEPRECATION to cope with newer XCode warnings.
+- Examples: OpenGL3: Using GLSL 4.10 shaders for any GLSL version over 410 (e.g. 430, 450). (#2329) [@BrutPitt]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.67 (Released 2019-01-14)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.67
+
+Breaking Changes:
+
+- Made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable
+ side-effect because the window would have ID zero. In particular it is causing problems in viewport/docking branches.
+- Renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges and removed its [Beta] mark.
+ The addition of new configuration options in the Docking branch is pushing for a little reorganization of those names.
+- Renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete).
+
+Other Changes:
+- Added BETA api for Tab Bar/Tabs widgets: (#261, #351)
+ - Added BeginTabBar(), EndTabBar(), BeginTabItem(), EndTabItem(), SetTabItemClosed() API.
+ - Added ImGuiTabBarFlags flags for BeginTabBar().
+ - Added ImGuiTabItemFlags flags for BeginTabItem().
+ - Style: Added ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive colors.
+ - Demo: Added Layout->Tabs demo code.
+ - Demo: Added "Documents" example app showcasing possible use for tabs.
+ This feature was merged from the Docking branch in order to allow the use of regular tabs in your code.
+ (It does not provide the docking/splitting/merging of windows available in the Docking branch)
+- Added ImGuiWindowFlags_UnsavedDocument window flag to append '*' to title without altering the ID, as a convenience
+ to avoid using the ### operator. In the Docking branch this also has an effect on tab closing behavior.
+- Window, Focus, Popup: Fixed an issue where closing a popup by clicking another window with the _NoMove flag would refocus
+ the parent window of the popup instead of the newly clicked window.
+- Window: Contents size is preserved while a window collapsed. Fix auto-resizing window losing their size for one frame when uncollapsed.
+- Window: Contents size is preserved while a window contents is hidden (unless it is hidden for resizing purpose).
+- Window: Resizing windows from edge is now enabled by default (io.ConfigWindowsResizeFromEdges=true). Note that
+ it only works _if_ the backend sets ImGuiBackendFlags_HasMouseCursors, which the standard backends do.
+- Window: Added io.ConfigWindowsMoveFromTitleBarOnly option. This is ignored by window with no title bars (often popups).
+ This affects clamping window within the visible area: with this option enabled title bars need to be visible. (#899)
+- Window: Fixed using SetNextWindowPos() on a child window (which wasn't really documented) position the cursor as expected
+ in the parent window, so there is no mismatch between the layout in parent and the position of the child window.
+- InputFloat: When using ImGuiInputTextFlags_ReadOnly the step buttons are disabled. (#2257)
+- DragFloat: Fixed broken mouse direction change with power!=1.0. (#2174, #2206) [@Joshhua5]
+- Nav: Fixed an keyboard issue where holding Activate/Space for longer than two frames on a button would unnecessary
+ keep the focus on the parent window, which could steal it from newly appearing windows. (#787)
+- Nav: Fixed animated window titles from being updated when displayed in the CTRL+Tab list. (#787)
+- Error recovery: Extraneous/undesired calls to End() are now being caught by an assert in the End() function closer
+ to the user call site (instead of being reported in EndFrame). Past the assert, they don't lead to crashes any more. (#1651)
+ Missing calls to End(), past the assert, should not lead to crashes or to the fallback Debug window appearing on screen.
+ Those changes makes it easier to integrate dear imgui with a scripting language allowing, given asserts are redirected
+ into e.g. an error log and stopping the script execution.
+- ImFontAtlas: Stb and FreeType: Atlas width is now properly based on total surface rather than glyph count (unless overridden with TexDesiredWidth).
+- ImFontAtlas: Stb and FreeType: Fixed atlas builder so missing glyphs won't influence the atlas texture width. (#2233)
+- ImFontAtlas: Stb and FreeType: Fixed atlas builder so duplicate glyphs (when merging fonts) won't be included in the rasterized atlas.
+- ImFontAtlas: FreeType: Fixed abnormally high atlas height.
+- ImFontAtlas: FreeType: Fixed support for any values of TexGlyphPadding (not just only 1).
+- ImDrawList: Optimized some of the functions for performance of debug builds where non-inline function call cost are non-negligible.
+ (Our test UI scene on VS2015 Debug Win64 with /RTC1 went ~5.9 ms -> ~4.9 ms. In Release same scene stays at ~0.3 ms.)
+- IO: Added BackendPlatformUserData, BackendRendererUserData, BackendLanguageUserData void* for storage use by backends.
+- IO: Renamed InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead!
+- IO: AddInputCharacter() goes into a queue which can receive as many characters as needed during the frame. This is useful
+ for automation to not have an upper limit on typing speed. Will later transition key/mouse to use the event queue later.
+- Style: Tweaked default value of style.DisplayWindowPadding from (20,20) to (19,19) so the default style as a value
+ which is the same as the title bar height.
+- Demo: "Simple Layout" and "Style Editor" are now using tabs.
+- Demo: Added a few more things under "Child windows" (changing ImGuiCol_ChildBg, positioning child, using IsItemHovered after a child).
+- Examples: DirectX10/11/12: Made imgui_impl_dx10/dx11/dx12.cpp link d3dcompiler.lib from the .cpp file to ease integration.
+- Examples: Allegro 5: Properly destroy globals on shutdown to allow for restart. (#2262) [@DomRe]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.66b (Released 2018-12-01)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.66b
+
+Other Changes:
+
+- Fixed a text rendering/clipping bug introduced in 1.66 (on 2018-10-12, commit ede3a3b9) that affect single ImDrawList::AddText()
+ calls with single strings larger than 10k. Text/TextUnformatted() calls were not affected, but e.g. InputText() was. [@pdoane]
+- When the focused window become inactive don't restore focus to a window with the ImGuiWindowFlags_NoInputs flag. (#2213) [@zzzyap]
+- Separator: Fixed Separator() outputting an extraneous empty line when captured into clipboard/text/file.
+- Demo: Added ShowAboutWindow() call, previously was only accessible from the demo window.
+- Demo: ShowAboutWindow() now display various Build/Config Information (compiler, os, etc.) that can easily be copied into bug reports.
+- Fixed build issue with osxcross and macOS. (#2218) [@dos1]
+- Examples: Setting up 'io.BackendPlatformName'/'io.BackendRendererName' fields to the current backend can be displayed in the About window.
+- Examples: SDL: changed the signature of ImGui_ImplSDL2_ProcessEvent() to use a const SDL_Event*. (#2187)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.66 (Released 2018-11-22)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.66
+
+Breaking Changes:
+
+- Renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete).
+- Renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files. (#2035, #2096)
+
+Other Changes:
+
+- Fixed calling SetNextWindowSize()/SetWindowSize() with non-integer values leading to
+ accidental alteration of window position. We now round the provided size. (#2067)
+- Fixed calling DestroyContext() always saving .ini data with the current context instead
+ of the supplied context pointer. (#2066)
+- Nav, Focus: Fixed ImGuiWindowFlags_NoBringToFrontOnFocus windows not being restoring focus
+ properly after the main menu bar or last focused window is deactivated.
+- Nav: Fixed an assert in certain circumstance (mostly when using popups) when mouse positions stop being valid. (#2168)
+- Nav: Fixed explicit directional input not re-highlighting current nav item if there is a single item in the window
+ and highlight has been previously disabled by the mouse. (#787)
+- DragFloat: Fixed a situation where dragging with value rounding enabled or with a power curve
+ erroneously wrapped the value to one of the min/max edge. (#2024, #708, #320, #2075).
+- DragFloat: Disabled using power curve when one edge is FLT_MAX (broken in 1.61). (#2024)
+- DragFloat: Disabled setting a default drag speed when one edge is FLT_MAX. (#2024)
+- SliderAngle: Added optional format argument to alter precision or localize the string. (#2150) [@podsvirov]
+- Window: Resizing from edges (with io.ConfigResizeWindowsFromEdges Beta flag) extends the hit region
+ of root floating windows outside the window, making it easier to resize windows. Resize grips are also
+ extended accordingly so there are no discontinuity when hovering between borders and corners. (#1495, #822)
+- Window: Added ImGuiWindowFlags_NoBackground flag to avoid rendering window background. This is mostly to allow
+ the creation of new flag combinations, as we could already use SetNextWindowBgAlpha(0.0f). (#1660) [@biojppm, @ocornut]
+- Window: Added ImGuiWindowFlags_NoDecoration helper flag which is essentially NoTitleBar+NoResize+NoScrollbar+NoCollapse.
+- Window: Added ImGuiWindowFlags_NoMouseInputs which is basically the old ImGuiWindowFlags_NoInputs (essentially
+ we have renamed ImGuiWindowFlags_NoInputs to ImGuiWindowFlags_NoMouseInputs). Made the new ImGuiWindowFlags_NoInputs
+ encompass both NoMouseInputs+NoNav, which is consistent with its description. (#1660, #787)
+- Window, Inputs: Fixed resizing from edges when io.MousePos is not pixel-rounded by rounding mouse position input. (#2110)
+- BeginChild(): Fixed BeginChild(const char*, ...) variation erroneously not applying the ID stack
+ to the provided string to uniquely identify the child window. This was undoing an intentional change
+ introduced in 1.50 and broken in 1.60. (#1698, #894, #713).
+- TextUnformatted(): Fixed a case where large-text path would read bytes past the text_end marker depending
+ on the position of new lines in the buffer (it wasn't affecting the output but still not the right thing to do!)
+- ListBox(): Fixed frame sizing when items_count==1 unnecessarily showing a scrollbar. (#2173) [@luk1337, @ocornut]
+- ListBox(): Tweaked frame sizing so list boxes will look more consistent when FramePadding is far from ItemSpacing.
+- RenderText(): Some optimization for very large text buffers, useful for non-optimized builds.
+- BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f.
+- ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different.
+- Demo: Split the contents of ShowDemoWindow() into smaller functions as it appears to speed up link time with VS. (#2152)
+- Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143)
+- ImGuiTextBuffer: Avoid heap allocation when empty.
+- ImDrawList: Fixed AddConvexPolyFilled() undefined behavior when passing points_count smaller than 3,
+ in particular, points_count==0 could lead to a memory stomp if the draw list was previously empty.
+- Examples: DirectX10, DirectX11: Removed seemingly unnecessary calls to invalidate and recreate device objects
+ in the WM_SIZE handler. (#2088) [@ice1000]
+- Examples: GLFW: User previously installed GLFW callbacks are now saved and chain-called by the default callbacks. (#1759)
+- Examples: OpenGL3: Added support for GL 4.5's glClipControl(GL_UPPER_LEFT). (#2186)
+- Examples: OpenGL3+GLFW: Fixed error condition when using the GLAD loader. (#2157) [@blackball]
+- Examples: OpenGL3+GLFW/SDL: Made main.cpp compile with IMGUI_IMPL_OPENGL_LOADER_CUSTOM (may be missing init). (#2178) [@doug-moen]
+- Examples: SDL2+Vulkan: Fixed application shutdown which could deadlock on Linux + Xorg. (#2181) [@eRabbit0]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.65 (Released 2018-09-06)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.65
+
+Breaking Changes:
+
+- Renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and
+ stb_rect_pack.h to imstb_rectpack.h. If you were conveniently using the imgui copy of those
+ STB headers in your project, you will have to update your include paths. (#1718, #2036)
+ The reason for this change is to avoid conflicts for projects that may also be importing
+ their own copy of the STB libraries. Note that imgui's copy of stb_textedit.h is modified.
+- Renamed io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427)
+
+Other Changes:
+
+- This is a minor release following the 1.64 refactor, with a little more shuffling of code.
+- Clarified and improved the source code sectioning in all files (easier to search or browse sections).
+- Nav: Removed the [Beta] tag from various descriptions of the gamepad/keyboard navigation system.
+ Although it is not perfect and will keep being improved, it is fairly functional and used by many. (#787)
+- Fixed a build issue with non-Cygwin GCC under Windows.
+- Demo: Added a "Configuration" block to make io.ConfigFlags/io.BackendFlags more prominent.
+- Examples: OpenGL3+SDL2: Fixed error condition when using the GLAD loader. (#2059, #2002) [@jiri]
+
+
+-----------------------------------------------------------------------
+ VERSION 1.64 (Released 2018-08-31)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.64
+
+Changes:
+
+- Moved README, CHANGELOG and TODO files to the docs/ folder.
+ If you are updating dear imgui by copying files, take the chance to delete the old files.
+- Added imgui_widgets.cpp file, extracted and moved widgets code out of imgui.cpp into imgui_widgets.cpp.
+ Re-ordered some of the code remaining in imgui.cpp.
+ NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTIONS HAS BEEN MOVED.
+ Because of this, any local modifications to imgui.cpp will likely conflict when you update.
+ If you have any modifications to imgui.cpp, it is suggested that you first update to 1.63, then
+ isolate your patches. You can peak at imgui_widgets.cpp from 1.64 to get a sense of what is included in it,
+ then separate your changes into several patches that can more easily be applied to 1.64 on a per-file basis.
+ What I found worked nicely for me, was to open the diff of the old patches in an interactive merge/diff tool,
+ search for the corresponding function in the new code and apply the chunks manually.
+- As a reminder, if you have any change to imgui.cpp it is a good habit to discuss them on the github,
+ so a solution applicable on the Master branch can be found. If your company has changes that you cannot
+ disclose you may also contact me privately.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.63 (Released 2018-08-29)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.63
+
+Breaking Changes:
+
+- Style: Renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features.
+ Kept redirection enum (will obsolete).
+- Changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecision over time.
+- Removed per-window ImGuiWindowFlags_ResizeFromAnySide Beta flag in favor `io.ConfigResizeWindowsFromEdges=true` to
+ enable the feature globally. (#1495)
+ The feature is not currently enabled by default because it is not satisfying enough, but will eventually be.
+- InputText: Renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData
+ for consistency. Kept redirection types (will obsolete).
+- InputText: Removed ImGuiTextEditCallbackData::ReadOnly because it is a duplication of (::Flags & ImGuiInputTextFlags_ReadOnly).
+- Renamed IsItemDeactivatedAfterChange() to IsItemDeactivatedAfterEdit() for consistency with new IsItemEdited() API.
+ Kept redirection function (will obsolete soonish as IsItemDeactivatedAfterChange() is very recent).
+- Renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to
+ io.ConfigMacOSXBehaviors for consistency. (#1427, #473)
+- Removed obsolete redirection functions: CollapsingHeader() variation with 2 bools - marked obsolete in v1.49, May 2016.
+
+Other Changes:
+
+- ArrowButton: Fixed to honor PushButtonRepeat() setting (and internals' ImGuiItemFlags_ButtonRepeat).
+- ArrowButton: Setup current line text baseline so that ArrowButton() + SameLine() + Text() are aligned properly.
+- Nav: Added a CTRL+TAB window list and changed the highlight system accordingly. The change is motivated by upcoming
+ Docking features. (#787)
+- Nav: Made CTRL+TAB skip menus + skip the current navigation window if is has the ImGuiWindow_NoNavFocus set. (#787)
+ While it was previously possible, you won't be able to CTRL-TAB out and immediately back in a window with the
+ ImGuiWindow_NoNavFocus flag.
+- Window: Allow menu and popups windows from ignoring the style.WindowMinSize values so short menus/popups are not padded. (#1909)
+- Window: Added global io.ConfigResizeWindowsFromEdges option to enable resizing windows from their edges and from
+ the lower-left corner. (#1495)
+- Window: Collapse button shows hovering highlight + clicking and dragging on it allows to drag the window as well.
+- Added IsItemEdited() to query if the last item modified its value (or was pressed). This is equivalent to the bool
+ returned by most widgets.
+ It is useful in some situation e.g. using InputText() with ImGuiInputTextFlags_EnterReturnsTrue. (#2034)
+- InputText: Added support for buffer size/capacity changes via the ImGuiInputTextFlags_CallbackResize flag. (#2006, #1443, #1008).
+- InputText: Fixed not tracking the cursor horizontally when modifying the text buffer through a callback.
+- InputText: Fixed minor off-by-one issue when submitting a buffer size smaller than the initial zero-terminated buffer contents.
+- InputText: Fixed a few pathological crash cases on single-line InputText widget with multiple millions characters worth of contents.
+ Because the current text drawing function reserve for a worst-case amount of vertices and how we handle horizontal clipping,
+ we currently just avoid displaying those single-line widgets when they are over a threshold of 2 millions characters,
+ until a better solution is found.
+- Drag and Drop: Fixed an incorrect assert when dropping a source that is submitted after the target (bug introduced with 1.62 changes
+ related to the addition of IsItemDeactivated()). (#1875, #143)
+- Drag and Drop: Fixed ImGuiDragDropFlags_SourceNoDisableHover to affect hovering state prior to calling IsItemHovered() + fixed description. (#143)
+- Drag and Drop: Calling BeginTooltip() between a BeginDragSource()/EndDragSource() or BeginDropTarget()/EndDropTarget() uses adjusted tooltip
+ settings matching the one created when calling BeginDragSource() without the ImGuiDragDropFlags_SourceNoPreviewTooltip flag. (#143)
+- Drag and Drop: Payload stays available and under the mouse if the source stops being submitted, however the tooltip is replaced by "...". (#1725)
+- Drag and Drop: Added ImGuiDragDropFlags_SourceAutoExpirePayload flag to force payload to expire if the source stops being submitted. (#1725, #143).
+- IsItemHovered(): Added ImGuiHoveredFlags_AllowWhenDisabled flag to query hovered status on disabled items. (#1940, #211)
+- Selectable: Added ImGuiSelectableFlags_Disabled flag in the public API. (#211)
+- ColorEdit4: Fixed a bug when text input or drag and drop leading to unsaturated HSV values would erroneously alter the resulting color. (#2050)
+- Misc: Added optional misc/stl/imgui_stl.h wrapper to use with STL types (e.g. InputText with std::string). (#2006, #1443, #1008)
+ [*EDIT* renamed to misc/std/imgui_stdlib.h in 1.66]
+- Misc: Added IMGUI_VERSION_NUM for easy compile-time testing. (#2025)
+- Misc: Added ImGuiMouseCursor_Hand cursor enum + corresponding software cursor. (#1913, 1914) [@aiekick, @ocornut]
+- Misc: Tweaked software mouse cursor offset to match the offset of the corresponding Windows 10 cursors.
+- Made assertion more clear when trying to call Begin() outside of the NewFrame()..EndFrame() scope. (#1987)
+- Fixed assertion when transitioning from an active ID to another within a group, affecting ColorPicker (broken in 1.62). (#2023, #820, #956, #1875).
+- Fixed PushID() from keeping alive the new ID Stack top value (if a previously active widget shared the ID it would be erroneously kept alive).
+- Fixed horizontal mouse wheel not forwarding the request to the parent window if ImGuiWindowFlags_NoScrollWithMouse is set. (#1463, #1380, #1502)
+- Fixed a include build issue for Cygwin in non-POSIX (Win32) mode. (#1917, #1319, #276)
+- ImDrawList: Improved handling for worst-case vertices reservation policy when large amount of text (e.g. 1+ million character strings)
+ are being submitted in a single call. It would typically have crashed InputTextMultiline(). (#200)
+- OS/Windows: Fixed missing ImmReleaseContext() call in the default Win32 IME handler. (#1932) [@vby]
+- Metrics: Changed io.MetricsActiveWindows to reflect the number of active windows (!= from visible windows), which is useful
+ for lazy/idle render mechanisms as new windows are typically not visible for one frame.
+- Metrics: Added io.MetricsRenderWindow to reflect the number of visible windows.
+- Metrics: Added io.MetricsActiveAllocations, moving away from the cross-context global counters than we previously used. (#1565, #1599, #586)
+- Demo: Added basic Drag and Drop demo. (#143)
+- Demo: Modified the Console example to use InsertChars() in the input text callback instead of poking directly into the buffer.
+ Although this won't make a difference in the example itself, using InsertChars() will honor the resizing callback properly. (#2006, #1443, #1008).
+- Demo: Clarified the use of IsItemHovered()/IsItemActive() right after being in the "Active, Focused, Hovered & Focused Tests" section.
+- Examples: Tweaked the main.cpp of each example.
+- Examples: Metal: Added Metal rendering backend. (#1929, #1873) [@warrenm]
+- Examples: OSX: Added early raw OSX platform backend. (#1873) [@pagghiu, @itamago, @ocornut]
+- Examples: Added mac OSX & iOS + Metal example in example_apple_metal/. (#1929, #1873) [@warrenm]
+- Examples: Added mac OSX + OpenGL2 example in example_apple_opengl2/. (#1873)
+- Examples: OpenGL3: Added shaders more versions of GLSL. (#1938, #1941, #1900, #1513, #1466, etc.)
+- Examples: OpenGL3: Tweaked the imgui_impl_opengl3.cpp to work as-is with Emscripten + WebGL 2.0. (#1941). [@o-micron]
+- Examples: OpenGL3: Made the example app default to GL 3.0 + GLSL 130 (instead of GL 3.2 + GLSL 150) unless on Mac.
+- Examples: OpenGL3: Added error output when shaders fail to compile/link.
+- Examples: OpenGL3: Added support for glew and glad OpenGL loaders out of the box. (#2001, #2002) [@jdumas]
+- Examples: OpenGL2: Disabling/restoring GL_LIGHTING and GL_COLOR_MATERIAL to increase compatibility with legacy OpenGL applications. (#1996)
+- Examples: DirectX10, DirectX11: Fixed unreleased resources in Init and Shutdown functions. (#1944)
+- Examples: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. (#1989) [@matt77hias]
+- Examples: Vulkan: Fixed handling of VkSurfaceCapabilitiesKHR::maxImageCount = 0 case. Tweaked present mode selections.
+- Examples: Win32, Glfw, SDL: Added support for the ImGuiMouseCursor_Hand cursor.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.62 (Released 2018-06-22)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.62
+
+Breaking Changes:
+
+- TreeNodeEx(): The helper ImGuiTreeNodeFlags_CollapsingHeader flag now include ImGuiTreeNodeFlags_NoTreePushOnOpen.
+ The flag was already set by CollapsingHeader().
+ The only difference is if you were using TreeNodeEx() manually with ImGuiTreeNodeFlags_CollapsingHeader and without
+ ImGuiTreeNodeFlags_NoTreePushOnOpen. In this case you can remove the ImGuiTreeNodeFlags_NoTreePushOnOpen flag from
+ your call (ImGuiTreeNodeFlags_CollapsingHeader & ~ImGuiTreeNodeFlags_NoTreePushOnOpen). (#1864)
+ This also apply if you were using internal's TreeNodeBehavior() with the ImGuiTreeNodeFlags_CollapsingHeader flag directly.
+- ImFontAtlas: Renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish new smaller variants and
+ discourage using the full set. (#1859)
+
+Other Changes:
+
+- Examples backends have been refactored to separate the platform code (e.g. Win32, Glfw, SDL2) from the renderer code (e.g. DirectX11, OpenGL3, Vulkan).
+ The "Platform" backends are in charge of: mouse/keyboard/gamepad inputs, cursor shape, timing, etc.
+ The "Renderer" backends are in charge of: creating the main font texture, rendering imgui draw data.
+ before: imgui_impl_dx11.cpp --> after: imgui_impl_win32.cpp + imgui_impl_dx11.cpp
+ before: imgui_impl_dx12.cpp --> after: imgui_impl_win32.cpp + imgui_impl_dx12.cpp
+ before: imgui_impl_glfw_gl3.cpp --> after: imgui_impl_glfw.cpp + imgui_impl_opengl2.cpp
+ before: imgui_impl_glfw_vulkan.cpp --> after: imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp
+ before: imgui_impl_sdl_gl3.cpp --> after: imgui_impl_sdl2.cpp + imgui_impl_opengl2.cpp
+ before: imgui_impl_sdl_gl3.cpp --> after: imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp etc.
+ - The idea is what we can now easily combine and maintain backends and reduce code redundancy. Individual files are
+ smaller and more reusable. Integration of imgui into a new/custom engine may also be easier as there is less overlap
+ between "windowing / inputs" and "rendering" code, so you may study or grab one half of the code and not the other.
+ - This change was motivated by the fact that adding support for the upcoming multi-viewport feature requires more work
+ from the Platform and Renderer backends, and the amount of redundancy across files was becoming too difficult to
+ maintain. If you use default backends, you'll benefit from an easy update path to support multi-viewports later
+ (for future ImGui 1.7x).
+ - This is not strictly a breaking change if you keep your old backends, but when you'll want to fully update your backends,
+ expect to have to reshuffle a few things.
+ - Each example still has its own main.cpp which you may refer you to understand how to initialize and glue everything together.
+ - Some frameworks (such as the Allegro, Marmalade) handle both the "platform" and "rendering" part, and your custom engine may as well.
+ - Read examples/README.txt for details.
+- Added IsItemDeactivated() to query if the last item was active previously and isn't anymore. Useful for Undo/Redo patterns. (#820, #956, #1875)
+- Added IsItemDeactivatedAfterChange() [*EDIT* renamed to IsItemDeactivatedAfterEdit() in 1.63] if the last item was active previously,
+ is not anymore, and during its active state modified a value. Note that you may still get false positive (e.g. drag value and while
+ holding return on the same value). (#820, #956, #1875)
+- Nav: Added support for PageUp/PageDown (explorer-style: first aim at bottom/top most item, when scroll a page worth of contents). (#787)
+- Nav: To keep the navigated item in view we also attempt to scroll the parent window as well as the current window. (#787)
+- ColorEdit3, ColorEdit4, ColorButton: Added ImGuiColorEditFlags_NoDragDrop flag to disable ColorEditX as drag target and ColorButton as drag source. (#1826)
+- BeginDragDropSource(): Offset tooltip position so it is off the mouse cursor, but also closer to it than regular tooltips,
+ and not clamped by viewport. (#1739)
+- BeginDragDropTarget(): Added ImGuiDragDropFlags_AcceptNoPreviewTooltip flag to request hiding the drag source tooltip
+ from the target site. (#143)
+- BeginCombo(), BeginMainMenuBar(), BeginChildFrame(): Temporary style modification are restored at the end of BeginXXX
+ instead of EndXXX, to not affect tooltips and child windows.
+- Popup: Improved handling of (erroneously) repeating calls to OpenPopup() to not close the popup's child popups. (#1497, #1533, #1865).
+- InputTextMultiline(): Fixed double navigation highlight when scrollbar is active. (#787)
+- InputText(): Fixed Undo corruption after pasting large amount of text (Redo will still fail when undo buffers are exhausted,
+ but text won't be corrupted).
+- SliderFloat(): When using keyboard/gamepad and a zero precision format string (e.g. "%.0f"), always step in integer units. (#1866)
+- ImFontConfig: Added GlyphMinAdvanceX/GlyphMaxAdvanceX settings useful to make a font appears monospaced, particularly useful
+ for icon fonts. (#1869)
+- ImFontAtlas: Added GetGlyphRangesChineseSimplifiedCommon() helper that returns a list of ~2500 most common Simplified Chinese
+ characters. (#1859) [@JX-Master, @ocornut]
+- Examples: OSX: Added imgui_impl_osx.mm backend to be used along with e.g. imgui_impl_opengl2.cpp. (#281, #1870) [@pagghiu, @itamago, @ocornut]
+- Examples: GLFW: Made it possible to Shutdown/Init the backend again (by resetting the time storage properly). (#1827) [@ice1000]
+- Examples: Win32: Fixed handling of mouse wheel messages to support sub-unit scrolling messages (typically sent by track-pads). (#1874) [@zx64]
+- Examples: SDL+Vulkan: Added SDL+Vulkan example.
+- Examples: Allegro5: Added support for ImGuiConfigFlags_NoMouseCursorChange flag. Added clipboard support.
+- Examples: Allegro5: Unindexing buffers ourselves as Allegro indexed drawing primitives are buggy in the DirectX9 backend
+ (will be fixed in Allegro 5.2.5+).
+- Examples: DirectX12: Moved the ID3D12GraphicsCommandList* parameter from ImGui_ImplDX12_NewFrame() to ImGui_ImplDX12_RenderDrawData() which makes a lots more sense. (#301)
+- Examples: Vulkan: Reordered parameters ImGui_ImplVulkan_RenderDrawData() to be consistent with other backends,
+ a good occasion since we refactored the code.
+- Examples: FreeGLUT: Added FreeGLUT backends. Added FreeGLUT+OpenGL2 example. (#801)
+- Examples: The functions in imgui_impl_xxx.cpp are prefixed with IMGUI_IMPL_API (which defaults to IMGUI_API) to facilitate
+ some uses. (#1888)
+- Examples: Fixed backends to use ImGuiMouseCursor_COUNT instead of old name ImGuiMouseCursor_Count_ so they can compile
+ with IMGUI_DISABLE_OBSOLETE_FUNCTIONS. (#1887)
+- Misc: Updated stb_textedit from 1.09 + patches to 1.12 + minor patches.
+- Internals: PushItemFlag() flags are inherited by BeginChild().
+
+
+-----------------------------------------------------------------------
+ VERSION 1.61 (Released 2018-05-14)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.61
+
+Breaking Changes:
+
+- DragInt(): The default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally
+ any more. If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format.
+ To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d,
+ giving time to users to upgrade their code.
+ If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your
+ codebase for e.g. "DragInt.*%f" to you find them.
+- InputFloat(): Obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more
+ flexible "const char* format", consistent with other functions. Kept redirection functions (will obsolete).
+- Misc: IM_DELETE() helper function added in 1.60 doesn't set the input pointer to NULL, more consistent with standard
+ expectation and allows passing r-values.
+
+Other Changes:
+
+- Added DragScalar, DragScalarN: supports signed/unsigned, 32/64 bits, float/double data types. (#643, #320, #708, #1011)
+- Added InputScalar, InputScalarN: supports signed/unsigned, 32/64 bits, float/double data types. (#643, #320, #708, #1011)
+- Added SliderScalar, SliderScalarN: supports signed/unsigned, 32/64 bits, float/double data types. (#643, #320, #708, #1011)
+- Window: Fixed pop-ups/tooltips/menus not honoring style.DisplaySafeAreaPadding as well as it should have (part of menus
+ displayed outside the safe area, etc.).
+- Window: Fixed windows using the ImGuiWindowFlags_NoSavedSettings flag from not using the same default position as other windows. (#1760)
+- Window: Relaxed the internal stack size checker to allow Push/Begin/Pop/.../End patterns to be used with PushStyleColor, PushStyleVar, PushFont without causing a false positive assert. (#1767)
+- Window: Fixed the default proportional item width lagging by one frame on resize.
+- Columns: Fixed a bug introduced in 1.51 where columns would affect the contents size of their container, often creating
+ feedback loops when ImGuiWindowFlags_AlwaysAutoResize was used. (#1760)
+- Settings: Fixed saving an empty .ini file if CreateContext/DestroyContext are called without a single call to NewFrame(). (#1741)
+- Settings: Added LoadIniSettingsFromDisk(), LoadIniSettingsFromMemory(), SaveIniSettingsToDisk(), SaveIniSettingsToMemory()
+ to manually load/save .ini settings. (#923, #993)
+- Settings: Added io.WantSaveIniSettings flag, which is set to notify the application that e.g. SaveIniSettingsToMemory()
+ should be called. (#923, #993)
+- Scrolling: Fixed a case where using SetScrollHere(1.0f) at the bottom of a window on the same frame the window height
+ has been growing would have the scroll clamped using the previous height. (#1804)
+- MenuBar: Made BeginMainMenuBar() honor style.DisplaySafeAreaPadding so the text can be made visible on TV settings that
+ don't display all pixels. (#1439) [@dougbinks]
+- InputText: On Mac OS X, filter out characters when the CMD modifier is held. (#1747) [@sivu]
+- InputText: On Mac OS X, support CMD+SHIFT+Z for Redo. CMD+Y is also supported as major apps seems to default to support both. (#1765) [@lfnoise]
+- InputText: Fixed returning true when edition is cancelled with ESC and the current buffer matches the initial value.
+- InputFloat,InputFloat2,InputFloat3,InputFloat4: Added variations taking a more flexible and consistent optional
+ "const char* format" parameter instead of "int decimal_precision". This allow using custom formats to display values
+ in scientific notation, and is generally more consistent with other API.
+ Obsoleted functions using the optional "int decimal_precision" parameter. (#648, #712)
+- DragFloat, DragInt: Cancel mouse tweak when current value is initially past the min/max boundaries and mouse is pushing
+ in the same direction (keyboard/gamepad version already did this).
+- DragFloat, DragInt: Honor natural type limits (e.g. INT_MAX, FLT_MAX) instead of wrapping around. (#708, #320)
+- DragFloat, SliderFloat: Fixes to allow input of scientific notation numbers when using CTRL+Click to input the value. (~#648, #1011)
+- DragFloat, SliderFloat: Rounding-on-write uses the provided format string instead of parsing the precision from the string,
+ which allows for finer uses of %e %g etc. (#648, #642)
+- DragFloat: Improved computation when using the power curve. Improved lost of input precision with very small steps.
+ Added an assert than power-curve requires a min/max range. (~#642)
+- DragFloat: The 'power' parameter is only honored if the min/max parameter are also setup.
+- DragInt, SliderInt: Fixed handling of large integers (we previously passed data around internally as float, which reduced
+ the range of valid integers).
+- ColorEdit: Fixed not being able to pass the ImGuiColorEditFlags_NoAlpha or ImGuiColorEditFlags_HDR flags to SetColorEditOptions().
+- Nav: Fixed hovering a Selectable() with the mouse so that it update the navigation cursor (as it happened in the pre-1.60 navigation branch). (#787)
+- Style: Changed default style.DisplaySafeAreaPadding values from (4,4) to (3,3) so it is smaller than FramePadding and has no effect on main menu bar on a computer. (#1439)
+- Fonts: When building font atlas, glyphs that are missing in the fonts are not using the glyph slot to render the default glyph. Saves space and allow merging fonts with
+ overlapping font ranges such as FontAwesome5 which split out the Brands separately from the Solid fonts. (#1703, #1671)
+- Misc: Added IMGUI_CHECKVERSION() macro to compare version string and data structure sizes in order to catch issues with mismatching compilation unit settings. (#1695, #1769)
+- Misc: Added IMGUI_DISABLE_MATH_FUNCTIONS in imconfig.h to make it easier to redefine wrappers for std/crt math functions.
+- Misc: Fix to allow compiling in unity builds where stb_rectpack/stb_truetype may be already included in the same compilation unit.
+- Demo: Simple Overlay: Added a context menu item to enable freely moving the window.
+- Demo: Added demo for DragScalar(), InputScalar(), SliderScalar(). (#643)
+- Examples: Calling IMGUI_CHECKVERSION() in the main.cpp of every example application.
+- Examples: Allegro 5: Added support for 32-bit indices setup via defining ImDrawIdx, to avoid an unnecessary conversion (Allegro 5 doesn't support 16-bit indices).
+- Examples: Allegro 5: Renamed backend from imgui_impl_a5.cpp to imgui_impl_allegro5.cpp.
+- Examples: DirectX 9: Saving/restoring Transform because they don't seem to be included in the StateBlock. Setting shading mode to Gouraud. (#1790, #1687) [@sr-tream]
+- Examples: SDL: Fixed clipboard paste memory leak in the SDL backend code. (#1803) [@eliasdaler]
+- Various minor fixes, tweaks, refactoring, comments.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.60 (Released 2018-04-07)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.60
+
+The gamepad/keyboard navigation branch (which has been in the work since July 2016) has been merged.
+Gamepad/keyboard navigation is still marked as Beta and has to be enabled explicitly.
+Various internal refactoring have also been done, as part of the navigation work and as part of the upcoming viewport/docking work.
+
+Breaking Changes:
+
+- Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render().
+ e.g. with example backends, call ImDrawData* draw_data = ImGui::GetDrawData(); ImGui_ImplXXXX_RenderDrawData(draw_data).
+- Reorganized context handling to be more explicit: (#1599)
+ - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
+ - removed Shutdown() function, as DestroyContext() serve this purpose. If you are using an old backend from the examples/ folder, remove the line that calls Shutdown().
+ - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
+ - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
+ - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
+- Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
+- Fonts: Moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths.
+- Fonts: Changed ImFont::DisplayOffset.y to defaults to 0 instead of +1. Fixed vertical rounding of Ascent/Descent to match TrueType renderer.
+ If you were adding or subtracting (not assigning) to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619)
+- BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment.
+- Obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
+- Obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
+- Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, not used by core, and honored by some backend ahead of merging the Nav branch).
+- Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered style colors as the closing cross uses regular button colors now.
+- Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
+- Removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it should be easy to replicate on your side (you can find the code in 1.53).
+- [EDITED] Window: BeginChild() with an explicit name doesn't include the hash within the internal window name. (#1698)
+ This change was erroneously introduced, undoing the change done for #894, #713, and not documented properly in the original
+ 1.60 release Changelog. It was fixed on 2018-09-28 (1.66) and I wrote this paragraph the same day.
+
+Other Changes:
+
+- Doc: Added a Changelog file in the repository to ease comparing versions (it goes back to dear imgui 1.48), until now it was only on GitHub.
+- Navigation: merged in the gamepad/keyboard navigation (about a million changes!). (#787, #323)
+ The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
+- To use Gamepad Navigation:
+ - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
+ - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Read imgui.cpp for more details.
+ - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping or download PNG/PSD at http://goo.gl/9LgVZW
+ - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details.
+- To use Keyboard Navigation:
+ - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
+ - Basic controls: arrows to navigate, Alt to enter menus, Space to activate item, Enter to edit text, Escape to cancel/close, Ctrl-Tab to focus windows, etc.
+ - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set.
+ For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details.
+- Navigation: SetItemDefaultFocus() sets the navigation position in addition to scrolling. (#787)
+- Navigation: Added IsItemFocused(), added IsAnyItemFocused(). (#787)
+- Navigation: Added window flags: ImGuiWindowFlags_NoNav (== ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus).
+- Navigation: Style: Added ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight colors. (#787)
+- Navigation: TreeNode: Added ImGuiTreeNodeFlags_NavLeftJumpsBackHere flag to allow Nav Left direction to jump back to parent tree node from any of its child. (#1079)
+- Navigation: IO: Added io.ConfigFlags (input), io.NavActive (output), io.NavVisible (output). (#787)
+- Context: Removed the default global context and font atlas instances, which caused various problems to users of multiple contexts and DLL users. (#1565, #1599)
+ YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. Existing apps will assert/crash without it.
+- Context: Added SetAllocatorFunctions() to rewire memory allocators (as a replacement to previous parameters to CreateContext()). Allocators are shared by all contexts and imgui helpers. (#1565, #586, #992, #1007, #1558)
+- Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. (#1599)
+- Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558)
+- IO: Added io.ConfigFlags for user application to store settings for imgui and for the backend:
+ - ImGuiConfigFlags_NavEnableKeyboard: Enable keyboard navigation.
+ - ImGuiConfigFlags_NavEnableGamepad: Enable gamepad navigation (provided ImGuiBackendFlags_HasGamepad is also set by backend).
+ - ImGuiConfigFlags_NavEnableSetMousePos: Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward.
+ - ImGuiConfigFlags_NoMouseCursorChange: Instruct backend to not alter mouse cursor shape and visibility (by default the example backend use mouse cursor API of the platform when available)
+ - ImGuiConfigFlags_NoMouse: Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information passed by the backend.
+ - ImGuiConfigFlags_IsSRGB, ImGuiConfigFlags_IsTouchScreen: Flags for general application use.
+- IO: Added io.BackendFlags for backend to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version.
+- IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example backends. (#1541)
+- IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker]
+- IO: Added IsAnyMouseDown() helper which is helpful for backends to handle mouse capturing.
+- Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else when dragging afterwards. (#1381, #1337)
+- Window: IsWindowHovered(): Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow flags (See Breaking Changes). Added to demo. (#1382)
+- Window: Added SetNextWindowBgAlpha() helper. Particularly helpful since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567)
+- Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Got broken on Dec 10 (1.53). (#1363)
+- ArrowButton: Added ArrowButton() given a cardinal direction (e.g. ImGuiDir_Left).
+- InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), CTRL+Insert (copy), Shift+Insert (paste). (#1541)
+- InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554)
+- InputText: Added ImGuiInputTextFlags_CharsScientific flag to also allow 'e'/'E' for input of values using scientific notation. Automatically used by InputFloat.
+- Style: Default style is now StyleColorsDark(), instead of the old StyleColorsClassic(). (#707)
+- Style: Enable window border by default. (#707)
+- Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181)
+- Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939).
+- Style: Close button nows display a cross before hovering. Fixed cross positioning being a little off. Uses button colors for highlight when hovering. (#707)
+- Popup: OpenPopup() Always reopen existing pop-ups. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533).
+- Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439)
+- Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497)
+- Popup: BeginPopup(): Exposed extra_flags parameter that are passed through to Begin(). (#1533)
+- Popup: BeginPopupModal: fixed the conditional test for SetNextWindowPos() which was polling the wrong window, which in practice made the test succeed all the time.
+- Tooltip: BeginTooltip() sets ImGuiWindowFlags_NoInputs flag.
+- Scrollbar: Fixed ScrollbarY enable test after ScrollbarX has been enabled being a little off (small regression from Nov 2017). (#1574)
+- Scrollbar: Fixed ScrollbarX enable test subtracting WindowPadding.x (this has been there since the addition of horizontal scroll bar!).
+- Columns: Clear offsets data when columns count changed. (#1525)
+- Columns: Fixed a memory leak of ImGuiColumnsSet's Columns vector. (#1529) [@unprompted]
+- Columns: Fixed resizing a window very small breaking some columns positioning (broken in 1.53).
+- Columns: The available column extent takes consideration of the right-most clipped pixel, so the right-most column may look a little wider but will contain the same amount of visible contents.
+- MenuBar: Fixed menu bar pushing a clipping rect outside of its allocated bound (usually unnoticeable).
+- TreeNode: nodes with the ImGuiTreeNodeFlags_Leaf flag correctly disable highlight when DragDrop is active. (#143, #581)
+- Drag and Drop: Increased payload type string to 32 characters instead of 8. (#143)
+- Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143)
+- DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559)
+- InputFloat: Allow inputing value using scientific notation e.g. "1e+10".
+- InputDouble: Added InputDouble() function. We use a format string instead of a decimal_precision parameter to also for "%e" and variants. (#1011)
+- Slider, Combo: Use ImGuiCol_FrameBgHovered color when hovered. (#1456) [@stfx]
+- Combo: BeginCombo(): Added ImGuiComboFlags_NoArrowButton to disable the arrow button and only display the wide value preview box.
+- Combo: BeginCombo(): Added ImGuiComboFlags_NoPreview to disable the preview and only display a square arrow button.
+- Combo: Arrow button isn't displayed over frame background so its blended color matches other buttons. Left side of the button isn't rounded.
+- PlotLines: plot a flat line if scale_min==scale_max. (#1621)
+- Fonts: Changed DisplayOffset.y to defaults to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer.
+ If you were adding or subtracting (not assigning) to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619)
+- Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622)
+- Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut]
+- Fonts: Moved extra_fonts/ to misc/fonts/.
+- ImFontAtlas: Fixed cfg.MergeMode not reusing existing glyphs if available (always overwrote).
+- ImFontAtlas: Handle stb_truetype stbtt_InitFont() and stbtt_PackBegin() possible failures more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527)
+- ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts. Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939)
+- ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613)
+- ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613)
+- ImDrawList: Fixed AddRect() with anti-aliasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646)
+- ImDrawList: Added CloneOutput() helper to facilitate the cloning of ImDrawData or ImDrawList for multi-threaded rendering.
+- Misc: Functions passed to libc qsort are explicitly marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul]
+- Misc: ImVec2: added [] operator. This is becoming desirable for some code working of either axes independently. Better adding it sooner than later.
+- Misc: NewFrame(): Added an assert to detect incorrect filling of the io.KeyMap[] array earlier. (#1555)
+- Misc: Added IM_OFFSETOF() helper in imgui.h (previously was in imgui_internal.h)
+- Misc: Added IM_NEW(), IM_DELETE() helpers in imgui.h (previously were in imgui_internal.h)
+- Misc: Added obsolete redirection function GetItemsLineHeightWithSpacing() (which redirects to GetFrameHeightWithSpacing()), as intended and stated in docs of 1.53.
+- Misc: Added misc/natvis/imgui.natvis for visual studio debugger users to easily visualize imgui internal types. Added to examples projects.
+- Misc: Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41)
+- Misc: Added IMGUI_STB_TRUETYPE_FILENAME and IMGUI_STB_RECT_PACK_FILENAME compile time directives to use another version of the stb_ files.
+- Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes).
+ (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/backend to pass information to the application in a standard manner.)
+- Metrics: Added display of Columns state.
+- Demo: Improved Selectable() examples. (#1528)
+- Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions.
+- Demo: Console: Using ImGuiCol_Text to be more friendly to color changes.
+- Demo: Using IM_COL32() instead of ImColor() in ImDrawList centric contexts. Trying to phase out use of the ImColor helper whenever possible.
+- Examples: Files in examples/ now include their own changelog so it is easier to occasionally update your backends if needed.
+- Examples: Using Dark theme by default. (#707). Tweaked demo code.
+- Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) [@tseeker]
+- Examples: All examples now setup the io.BackendFlags to signify they can honor mouse cursors, gamepad, etc.
+- Examples: DirectX10: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) in every other backends. (#1733)
+- Examples: DirectX12: Added DirectX 12 example. (#301) [@jdm3]
+- Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version from 330 to 150. (#1466, #1504)
+- Examples: OpenGL3+GLFW,SDL: Added a way to override the GLSL version string in the Init function. (#1466, #1504).
+- Examples: OpenGL3+GLFW,SDL: Creating VAO in the render function so it can be more easily used by multiple shared OpenGL contexts. (#1217)
+- Examples: OpenGL3+GLFW: Using 3.2 context instead of 3.3. (#1466)
+- Examples: OpenGL: Setting up glPixelStorei() explicitly before uploading texture.
+- Examples: OpenGL: Calls to glPolygonMode() are casting parameters as GLEnum to not fail with more strict backends. (#1628) [@ilia-glushchenko]
+- Examples: Win32 (DirectX9,10,11,12): Added support for mouse cursor shapes. (#1495)
+- Examples: Win32 (DirectX9,10,11,12: Support for windows using the CS_DBLCLKS class flag by handling the double-click messages (WM_LBUTTONDBLCLK etc.). (#1538, #754) [@ndandoulakis]
+- Examples: Win32 (DirectX9,10,11,12): Made the Win32 proc handlers not assert if there is no active context yet, to be more flexible with creation order. (#1565)
+- Examples: GLFW: Added support for mouse cursor shapes (the diagonal resize cursors are unfortunately not supported by GLFW at the moment. (#1495)
+- Examples: GLFW: Don't attempt to change the mouse cursor input mode if it is set to GLFW_CURSOR_DISABLED by the application. (#1202) [@PhilCK]
+- Examples: SDL: Added support for mouse cursor shapes. (#1626) [@olls]
+- Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging (SDL 2.0.4+ only, otherwise using SDL_WINDOW_INPUT_FOCUS instead of previously SDL_WINDOW_MOUSE_FOCUS). (#1559)
+- Examples: SDL: Enabled vsync by default so people don't come at us when the examples are running at 2000 FPS and burning a CPU core.
+- Examples: SDL: Using SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency() to handle frame-rate over 1000 FPS properly. (#996)
+- Examples: SDL: Using scan-code exclusively instead of a confusing mixture of scan-codes and key-codes.
+- Examples: SDL: Visual Studio: Added .vcxproj file. Using %SDL2_DIR% in the default .vcxproj and build files instead of %SDL_DIR%, the earlier being more standard.
+- Examples: Vulkan: Visual Studio: Added .vcxproj file.
+- Examples: Apple: Fixed filenames in OSX xcode project. Various other Mac friendly fixes. [@gerryhernandez etc.]
+- Examples: Visual Studio: Disabled extraneous function-level check in Release build.
+- Various fixes, tweaks, internal refactoring, optimizations, comments.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.53 (Released 2017-12-25)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.53
+
+Breaking Changes:
+
+- Renamed the emblematic `ShowTestWindow()` function to `ShowDemoWindow()`. Kept redirection function (will obsolete).
+- Renamed `GetItemsLineHeightWithSpacing()` to `GetFrameHeightWithSpacing()` for consistency. Kept redirection function (will obsolete).
+- Renamed `ImGuiTreeNodeFlags_AllowOverlapMode` flag to `ImGuiTreeNodeFlags_AllowItemOverlap`. Kept redirection enum (will obsolete).
+- Obsoleted `IsRootWindowFocused()` in favor of using `IsWindowFocused(ImGuiFocusedFlags_RootWindow)`. Kept redirection function (will obsolete). (#1382)
+- Obsoleted `IsRootWindowOrAnyChildFocused()` in favor of using `IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)`. Kept redirection function (will obsolete). (#1382)
+- Obsoleted `IsRootWindowOrAnyChildHovered()` in favor of using `IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows)`. Kept redirection function (will obsolete). (#1382)
+- Obsoleted `SetNextWindowContentWidth() in favor of using `SetNextWindowContentSize()`. Kept redirection function (will obsolete).
+- Renamed `ImGuiTextBuffer::append()` helper to `appendf()`, and `appendv()` to `appendfv()` for consistency. If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed.
+- ImDrawList: Removed 'bool anti_aliased = true' final parameter of `ImDrawList::AddPolyline()` and `ImDrawList::AddConvexPolyFilled()`. Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame.
+- Style, ImDrawList: Renamed `style.AntiAliasedShapes` to `style.AntiAliasedFill` for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags.
+- Style, Begin: Removed `ImGuiWindowFlags_ShowBorders` window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. `style.FrameBorderSize`, `style.WindowBorderSize`, `style.PopupBorderSize`).
+ Use `ImGui::ShowStyleEditor()` to look them up.
+ Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time.
+ It is recommended that you use the `StyleColorsClassic()`, `StyleColorsDark()`, `StyleColorsLight()` functions. Also see `ShowStyleSelector()`.
+- Style: Removed `ImGuiCol_ComboBg` in favor of combo boxes using `ImGuiCol_PopupBg` for consistency. Combo are normal pop-ups.
+- Style: Renamed `ImGuiCol_ChildWindowBg` to `ImGuiCol_ChildBg`.
+- Style: Renamed `style.ChildWindowRounding` to `style.ChildRounding`, `ImGuiStyleVar_ChildWindowRounding` to `ImGuiStyleVar_ChildRounding`.
+- Removed obsolete redirection functions: SetScrollPosHere() - marked obsolete in v1.42, July 2015.
+- Removed obsolete redirection functions: GetWindowFont(), GetWindowFontSize() - marked obsolete in v1.48, March 2016.
+
+Other Changes:
+
+- Added `io.OptCursorBlink` option to allow disabling cursor blinking. (#1427) [renamed to io.ConfigCursorBlink in 1.63]
+- Added `GetOverlayDrawList()` helper to quickly get access to a ImDrawList that will be rendered in front of every windows.
+- Added `GetFrameHeight()` helper which returns `(FontSize + style.FramePadding.y * 2)`.
+- Drag and Drop: Added Beta API to easily use drag and drop patterns between imgui widgets.
+ - Setup a source on a widget with `BeginDragDropSource()`, `SetDragDropPayload()`, `EndDragDropSource()` functions.
+ - Receive data with `BeginDragDropTarget()`, `AcceptDragDropPayload()`, `EndDragDropTarget()`.
+ - See ImGuiDragDropFlags for various options.
+ - The ColorEdit4() and ColorButton() widgets now support Drag and Drop.
+ - The API is tagged as Beta as it still may be subject to small changes.
+- Drag and Drop: When drag and drop is active, tree nodes and collapsing header can be opened by hovering on them for 0.7 seconds.
+- Renamed io.OSXBehaviors to io.OptMacOSXBehaviors. Should not affect users as the compile-time default is usually enough. (#473, #650)
+- Style: Added StyleColorsDark() style. (#707) [@dougbinks]
+- Style: Added StyleColorsLight() style. Best used with frame borders + thicker font than the default font. (#707)
+- Style: Added style.PopupRounding setting. (#1112)
+- Style: Added style.FrameBorderSize, style.WindowBorderSize, style.PopupBorderSize. Removed ImGuiWindowFlags_ShowBorders window flag!
+ Borders are now fully set up in the ImGuiStyle structure. Use ImGui::ShowStyleEditor() to look them up. (#707, fix #819, #1031)
+- Style: Various small changes to the classic style (most noticeably, buttons are now using blue shades). (#707)
+- Style: Renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
+- Style: Renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
+- Style: Removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. (#707)
+- Style: Made the ScaleAllSizes() helper rounds down every values so they are aligned on integers.
+- Focus: Added SetItemDefaultFocus(), which in the current (master) branch behave the same as doing `if (IsWindowAppearing()) SetScrollHere()`.
+ In the navigation branch this will also set the default focus. Prefer using this when creating combo boxes with `BeginCombo()` so your code will be forward-compatible with gamepad/keyboard navigation features. (#787)
+- Combo: Pop-up grows horizontally to accommodate for contents that is larger then the parent combo button.
+- Combo: Added BeginCombo()/EndCombo() API which allows use to submit content of any form and manage your selection state without relying on indices.
+- Combo: Added ImGuiComboFlags_PopupAlignLeft flag to BeginCombo() to prioritize keeping the pop-up on the left side (for small-button-looking combos).
+- Combo: Added ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, ImGuiComboFlags_HeightLargest to easily provide desired pop-up height.
+- Combo: You can use SetNextWindowSizeConstraints() before BeginCombo() to specify specific pop-up width/height constraints.
+- Combo: Offset popup position by border size so that a double border isn't so visible. (#707)
+- Combo: Recycling windows by using a stack number instead of a unique id, wasting less memory (like menus do).
+- InputText: Added ImGuiInputTextFlags_NoUndoRedo flag. (#1506, #1508) [@ibachar]
+- Window: Fixed auto-resize allocating too much space for scrollbar when SizeContents is bigger than maximum window size (fixes c0547d3). (#1417)
+- Window: Child windows with MenuBar use regular WindowPadding.y so layout look consistent as child or as a regular window.
+- Window: Begin(): Fixed appending into a child window with a second Begin() from a different window stack querying the wrong window for the window->Collapsed test.
+- Window: Calling IsItemActive(), IsItemHovered() etc. after a call to Begin() provides item data for the title bar, so you can easily test if the title bar is being hovered, etc. (#823)
+- Window: Made it possible to use SetNextWindowPos() on a child window.
+- Window: Fixed a one frame glitch. When an appearing window claimed the focus themselves, the title bar wouldn't use the focused color for one frame.
+- Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests for full usability. (#822)
+- Window: Sizing fixes when using SetNextWindowSize() on individual axises.
+- Window: Hide new window for one frame until they calculate their size. Also fixes SetNextWindowPos() given a non-zero pivot. (#1694)
+- Window: Made mouse wheel scrolling accommodate better to windows that are smaller than the scroll step.
+- Window: SetNextWindowContentSize() adjust for the size of decorations (title bar/menu bar), but _not_ for borders are we consistently make borders not affect layout.
+ If you need a non-child window of an exact size with border enabled but zero window padding, you'll need to accommodate for the border size yourself.
+- Window: Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. (#1380, #1502)
+- Window: Active Modal window always set the WantCaptureKeyboard flag. (#744)
+- Window: Moving window doesn't use accumulating MouseDelta so straying out of imgui boundaries keeps moved imgui window at the same cursor-relative position.
+- IsWindowFocused(): Added ImGuiFocusedFlags_ChildWindows flag to include child windows in the focused test. (#1382).
+- IsWindowFocused(): Added ImGuiFocusedFlags_RootWindow flag to start focused test from the root (top-most) window. Obsolete IsRootWindowFocused(). (#1382)
+- IsWindowHovered(): Added ImGuiHoveredFlags_ChildWindows flag to include child windows in the hovered test. (#1382).
+- IsWindowHovered(): Added ImGuiHoveredFlags_RootWindow flag to start hovered test from the root (top-most) window. The combination of both flags obsoletes IsRootWindowOrAnyChildHovered(). (#1382)
+- IsWindowHovered(): Fixed return value when an item is active to use the same logic as IsItemHovered(). (#1382, #1404)
+- IsWindowHovered(): Always return true when current window is being moved. (#1382)
+- Scrollbar: Fixed issues with vertical scrollbar flickering/appearing, typically when manually resizing and using a pattern of filling available height (e.g. full sized BeginChild).
+- Scrollbar: Minor graphical fix for when scrollbar don't have enough visible space to display the full grab.
+- Scrolling: Fixed padding and scrolling asymmetry where lower/right sides of a window wouldn't use WindowPadding properly + causing minor scrolling glitches.
+- Tree: TreePush with zero arguments was ambiguous. Resolved by making it call TreePush(const void*). [@JasonWilkins]
+- Tree: Renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. (#600, #1330)
+- MenuBar: Fixed minor rendering issues on the right size when resizing a window very small and using rounded window corners.
+- MenuBar: better software clipping to handle small windows, in particular child window don't have minimum constraints so we need to render clipped menus better.
+- BeginMenu(): Tweaked the Arrow/Triangle displayed on child menu items.
+- Columns: Clipping columns borders on Y axis on CPU because some Linux GPU drivers appears to be unhappy with triangle spanning large regions. (#125)
+- Columns: Added ImGuiColumnsFlags_GrowParentContentsSize to internal API to restore old content sizes behavior (may be obsolete). (#1444, #125)
+- Columns: Columns width is no longer lost when dragging a column to the right side of the window, until releasing the mouse button you have a chance to save them. (#1499, #125). [@ggtucker]
+- Columns: Fixed dragging when using a same of columns multiple times in the frame. (#125)
+- Indent(), Unindent(): Allow passing negative values.
+- ColorEdit4(): Made IsItemActive() return true when picker pop-up is active. (#1489)
+- ColorEdit4(): Tweaked tooltip so that the color button aligns more correctly with text.
+- ColorEdit4(): Support drag and drop. Color buttons can be used as drag sources, and ColorEdit widgets as drag targets. (#143)
+- ColorPicker4(): Fixed continuously returning true when holding mouse button on the sat/value/alpha locations. We only return true on value change. (#1489)
+- NewFrame(): using literal strings in the most-frequently firing IM_ASSERT expressions to increase the odd of programmers seeing them (especially those who don't use a debugger).
+- NewFrame() now asserts if neither Render or EndFrame have been called. Exposed EndFrame(). Made it legal to call EndFrame() more than one. (#1423)
+- ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from scratch.
+- ImFont: Added GetDebugName() helper.
+- ImFontAtlas: Added missing Thai punctuation in the GetGlyphRangesThai() ranges. (#1396) [@nProtect]
+- ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags.
+- ImDrawList: Added ImDrawList::AddImageRounded() helper. (#845) [@thedmd]
+- ImDrawList: Refactored to make ImDrawList independent of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some.
+- ImDrawList: Exposed ImDrawCornerFlags, replaced occurrences of ~0 with an explicit ImDrawCornerFlags_All. NB: Inversed BotLeft (prev 1<<3, now 1<<2) and BotRight (prev 1<<2, now 1<<3).
+- ImVector: Added ImVector::push_front() helper.
+- ImVector: Added ImVector::contains() helper.
+- ImVector: insert() uses grow_capacity() instead of using grow policy inconsistent with push_back().
+- Internals: Remove requirement to define IMGUI_DEFINE_PLACEMENT_NEW to use the IM_PLACEMENT_NEW macro. (#1103)
+- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_NoHoldingActiveID flag from incorrectly setting the ActiveIdClickOffset field.
+ This had no known effect within imgui code but could have affected custom drag and drop patterns. And it is more correct this way! (#1418)
+- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_AllowOverlapMode to avoid temporarily activating widgets on click before they have been correctly double-hovered. (#319, #600)
+- Internals: Added SplitterBehavior() helper. (#319)
+- Internals: Added IM_NEW(), IM_DELETE() helpers. (#484, #504, #1517)
+- Internals: Basic refactor of the settings API which now allows external elements to be loaded/saved.
+- Demo: Added ShowFontSelector() showing loaded fonts.
+- Demo: Added ShowStyleSelector() to select among default styles. (#707)
+- Demo: Renamed the emblematic ShowTestWindow() function to ShowDemoWindow().
+- Demo: Style Editor: Added a "Simplified settings" sections with check-boxes for border size and frame rounding. (#707, #1019)
+- Demo: Style Editor: Added combo box to select stock styles and select current font when multiple are loaded. (#707)
+- Demo: Style Editor: Using local storage so Save/Revert button makes more sense without code passing its storage. Added horizontal scroll bar. Fixed Save/Revert button to be always accessible. (#1211)
+- Demo: Console: Fixed context menu issue. (#1404)
+- Demo: Console: Fixed incorrect positioning which was hidden by a minor scroll issue (this would affect people who copied the Console code as is).
+- Demo: Constrained Resize: Added more test cases. (#1417)
+- Demo: Custom Rendering: Fixed clipping rectangle extruding out of parent window.
+- Demo: Layout: Removed unnecessary and misleading BeginChild/EndChild calls.
+- Demo: The "Color Picker with Palette" demo supports drag and drop. (#143)
+- Demo: Display better mouse cursor info for debugging backends.
+- Demo: Stopped using rand() function in demo code.
+- Examples: Added a handful of extra comments (about fonts, third-party libraries used in the examples, etc.).
+- Examples: DirectX9: Handle loss of D3D9 device (D3DERR_DEVICELOST). (#1464)
+- Examples: Added null_example/ which is helpful for quick testing on multiple compilers/settings without relying on graphics library.
+- Fix for using alloca() in "Clang with Microsoft Codechain" mode.
+- Various fixes, optimizations, comments.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.52 (2017-10-27)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.52
+
+Breaking Changes:
+
+- IO: `io.MousePos` needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing, instead of ImVec2(-1,-1) as previously) This is needed so we can clear `io.MouseDelta` field when the mouse is made available again.
+- Renamed `AlignFirstTextHeightToWidgets()` to `AlignTextToFramePadding()`. Kept inline redirection function (will obsolete).
+- Obsoleted the legacy 5 parameters version of Begin(). Please avoid using it. If you need a transparent window background, uses `PushStyleColor()`. The old size parameter there was also misleading and equivalent to calling `SetNextWindowSize(size, ImGuiCond_FirstTimeEver)`. Kept inline redirection function (will obsolete).
+- Obsoleted `IsItemHoveredRect()`, `IsMouseHoveringWindow()` in favor of using the newly introduced flags of `IsItemHovered()` and `IsWindowHovered()`. Kept inline redirection function (will obsolete). (#1382)
+- Obsoleted 'SetNextWindowPosCenter()' in favor of using 1SetNextWindowPos()` with a pivot value which allows to do the same and more. Keep inline redirection function.
+- Removed `IsItemRectHovered()`, `IsWindowRectHovered()` recently introduced in 1.51 which were merely the more consistent/correct names for the above functions which are now obsolete anyway. (#1382)
+- Changed `IsWindowHovered()` default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. (#1382)
+- Renamed imconfig.h's `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS` to `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS` for consistency.
+- Renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete).
+
+Other Changes:
+
+- ProgressBar: fixed rendering when straddling rounded area. (#1296)
+- SliderFloat, DragFloat: Using scientific notation e.g. "%.1e" in the displayed format string doesn't mistakenly trigger rounding of the value. [@MomentsInGraphics]
+- Combo, InputFloat, InputInt: Made the small button on the right side align properly with the equivalent colored button of ColorEdit4().
+- IO: Tweaked logic for `io.WantCaptureMouse` so it now outputs false when e.g. hovering over void while an InputText() is active. (#621) [@pdoane]
+- IO: Fixed `io.WantTextInput` from mistakenly outputting true when an activated Drag or Slider was previously turned into an InputText(). (#1317)
+- Misc: Added flags to `IsItemHovered()`, `IsWindowHovered()` to access advanced hovering-test behavior. Generally useful for pop-ups and drag and drop behaviors: (relates to ~#439, #1013, #143, #925)
+ - `ImGuiHoveredFlags_AllowWhenBlockedByPopup`
+ - `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem`
+ - `ImGuiHoveredFlags_AllowWhenOverlapped`
+ - `ImGuiHoveredFlags_RectOnly`
+- Input: Added `IsMousePosValid()` helper.
+- Input: Added `GetKeyPressedAmount()` to easily measure press count when the repeat rate is faster than the frame rate.
+- Input/Focus: Disabled TAB and Shift+TAB when CTRL key is held.
+- CheckBox: Now rendering a tick mark instead of a full square.
+- ColorEdit4: Added "Copy as..." option in context menu. (#346)
+- ColorPicker: Improved ColorPicker hue wheel color interpolation. (#1313) [@thevaber]
+- ColorButton: Reduced bordering artifact that would be particularly visible with an opaque Col_FrameBg and FrameRounding enabled.
+- ColorButton: Fixed rendering color button with a checkerboard if the transparency comes from the global style.Alpha and not from the actual source color.
+- TreeNode: Added `ImGuiTreeNodeFlags_FramePadding` flag to conveniently create a tree node with full padding at the beginning of a line, without having to call `AlignTextToFramePadding()`.
+- Trees: Fixed calling `SetNextTreeNodeOpen()` on a collapsed window leaking to the first tree node item of the next frame.
+- Layout: Horizontal layout is automatically enforced in a menu bar, so you can use non-MenuItem elements without calling SameLine().
+- Separator: Output a vertical separator when used inside a menu bar (or in general when horizontal layout is active, but that isn't exposed yet!).
+- Window: Added `IsWindowAppearing()` helper (helpful e.g. as a condition before initializing some of your own things.).
+- Window: Added pivot parameter to `SetNextWindowPos()`, making it possible to center or right align a window. Obsoleted `SetNextWindowPosCenter()`.
+- Window: Fixed title bar color of top-most window under a modal window.
+- Window: Fixed not being able to move a window by clicking on one of its child window. (#1337, #635)
+- Window: Fixed `Begin()` auto-fit calculation code that predict the presence of a scrollbar so it works better when window size constraints are used.
+- Window: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which in turn would set enable the Appearing condition for that frame.
+- Window: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow user creating a window called "Debug" without losing their custom flags.
+- Window: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move the parent window by clicking on SubChild. (#1381)
+- Popups: Pop-ups can be closed with a right-click anywhere, without altering focus under the pop-up. (~#439)
+- Popups: `BeginPopupContextItem()`, `BeginPopupContextWindow()` are now setup to allow reopening a context menu by right-clicking again. (~#439)
+- Popups: `BeginPopupContextItem()` now supports a NULL string identifier and uses the last item ID if available.
+- Popups: Added `OpenPopupOnItemClick()` helper which mimic `BeginPopupContextItem()` but doesn't do the BeginPopup().
+- MenuItem: Only activating on mouse release. [@Urmeli0815] (was already fixed in nav branch).
+- MenuItem: Made tick mark thicker (thick mark?).
+- MenuItem: Tweaks to be usable inside a menu bar (nb: it looks like a regular menu and thus is misleading, prefer using Button() and regular widgets in menu bar if you need to). (#1387)
+- ImDrawList: Fixed a rare draw call merging bug which could lead to undisplayed triangles. (#1172, #1368)
+- ImDrawList: Fixed a rare bug in `ChannelsMerge()` when all contents has been clipped, leading to an extraneous draw call being created. (#1172, #1368)
+- ImFont: Added `AddGlyph()` building helper for use by custom atlas builders.
+- ImFontAtlas: Added support for CustomRect API to submit custom rectangles to be packed into the atlas. You can map them as font glyphs, or use them for custom purposes.
+ After the atlas is built you can query the position of your rectangles in the texture and then copy your data there. You can use this features to create e.g. full color font-mapped icons.
+- ImFontAtlas: Fixed fall-back handling when merging fonts, if a glyph was missing from the second font input it could have used a glyph from the first one. (#1349) [@inolen]
+- ImFontAtlas: Fixed memory leak on build failure case when stbtt_InitFont failed (generally due to incorrect or supported font type). (#1391) (@Moka42)
+- ImFontConfig: Added `RasterizerMultiply` option to alter the brightness of individual fonts at rasterization time, which may help increasing readability for some.
+- ImFontConfig: Added `RasterizerFlags` to pass options to custom rasterizer (e.g. the [imgui_freetype](https://github.com/ocornut/imgui_club/tree/master/imgui_freetype) rasterizer in imgui_club has such options).
+- ImVector: added resize() variant with initialization value.
+- Misc: Changed the internal name formatting of child windows identifier to use slashes (instead of dots) as separator, more readable.
+- Misc: Fixed compilation with `IMGUI_DISABLE_OBSOLETE_FUNCTIONS` defined.
+- Misc: Marked all format+va_list functions with format attribute so GCC/Clang can warn about misuses.
+- Misc: Fixed compilation on NetBSD due to missing alloca.h (#1319) [@RyuKojiro]
+- Misc: Improved warnings compilation for newer versions of Clang. (#1324) (@waywardmonkeys)
+- Misc: Added `io.WantMoveMouse flags` (from Nav branch) and honored in Examples applications. Currently unused but trying to spread Examples applications code that supports it.
+- Misc: Added `IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS` support in imconfig.h to allow user reimplementing the `ImFormatString()` functions e.g. to use stb_printf(). (#1038)
+- Misc: [Windows] Fixed default Win32 `SetClipboardText()` handler leaving the Win32 clipboard handler unclosed on failure. [@pdoane]
+- Style: Added `ImGuiStyle::ScaleAllSizes(float)` helper to make it easier to have application transition e.g. from low to high DPI with a matching style.
+- Metrics: Draw window bounding boxes when hovering Pos/Size; List all draw layers; Trimming empty commands like Render() does.
+- Examples: OpenGL3: Save and restore sampler state. (#1145) [@nlguillemot]
+- Examples: OpenGL2, OpenGL3: Save and restore polygon mode. (#1307) [@JJscott]
+- Examples: DirectX11: Allow creating device with feature level 10 since we don't really need much for that example. (#1333)
+- Examples: DirectX9/10/12: Using the Win32 SetCapture/ReleaseCapture API to read mouse coordinates when they are out of bounds. (#1375) [@Gargaj, @ocornut]
+- Tools: Fixed binary_to_compressed_c tool to return 0 when successful. (#1350) [@benvanik]
+- Internals: Exposed more helpers and unfinished features in imgui_internal.h. (use at your own risk!).
+- Internals: A bunch of internal refactoring, hopefully haven't broken anything! Merged a bunch of internal changes from the upcoming Navigation branch.
+- Various tweaks, fixes and documentation changes.
+
+Beta Navigation Branch:
+(Lots of work has been done toward merging the Beta Gamepad/Keyboard Navigation branch (#787) in master.)
+(Please note that this branch is always kept up to date with master. If you are using the navigation branch, some of the changes include:)
+- Nav: Added `#define IMGUI_HAS_NAV` in imgui.h to ease sharing code between both branches. (#787)
+- Nav: MainMenuBar now releases focus when user gets out of the menu layer. (#787)
+- Nav: When applying focus to a window with only menus, the menu layer is automatically activated. (#787)
+- Nav: Added `ImGuiNavInput_KeyMenu` (~Alt key) aside from ImGuiNavInput_PadMenu input as it is one differentiator of pad vs keyboard that was detrimental to the keyboard experience. Although isn't officially supported, it makes the current experience better. (#787)
+- Nav: Move requests now wrap vertically inside Menus and Pop-ups. (#787)
+- Nav: Allow to collapse tree nodes with NavLeft and open them with NavRight. (#787, #1079).
+- Nav: It's now possible to navigate sibling of a menu-bar while navigating inside one of their child. If a Left<>Right navigation request fails to find a match we forward the request to the root menu. (#787, #126)
+- Nav: Fixed `SetItemDefaultFocus` from stealing default focus when we are initializing default focus for a menu bar layer. (#787)
+- Nav: Support for fall-back horizontal scrolling with PadLeft/PadRight (nb: fall-back scrolling is only used to navigate windows that have no interactive items). (#787)
+- Nav: Fixed tool-tip from being selectable in the window selection list. (#787)
+- Nav: `CollapsingHeader(bool*)` variant: fixed for `IsItemHovered()` not working properly in the nav branch. (#600, #787)
+- Nav: InputText: Fixed using Up/Down history callback feature when Nav is enabled. (#787)
+- Nav: InputTextMultiline: Fixed navigation/selection. Disabled selecting all when activating a multi-line text editor. (#787)
+- Nav: More consistently drawing a (thin) navigation rectangle hover filled frames such as tree nodes, collapsing header, menus. (#787)
+- Nav: Various internal refactoring.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.51 (2017-08-24)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.51
+
+Breaking Changes:
+
+Work on dear imgui has been gradually resuming. It means that fixes and new features should be tackled at a faster rate than last year. However, in order to move forward with the library and get rid of some cruft, I have taken the liberty to be a little bit more aggressive than usual with API breaking changes. Read the details below and search for those names in your code! In the grand scheme of things, those changes are small and should not affect everyone, but this is technically our most aggressive release so far in term of API breakage. If you want to be extra forward-facing, you can enable `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h to disable the obsolete names/redirection.
+
+- Renamed `IsItemHoveredRect()` to `IsItemRectHovered()`. Kept inline redirection function (will obsolete).
+- Renamed `IsMouseHoveringWindow()` to `IsWindowRectHovered()` for consistency. Kept inline redirection function (will obsolete).
+- Renamed `IsMouseHoveringAnyWindow()` to `IsAnyWindowHovered()` for consistency. Kept inline redirection function (will obsolete).
+- Renamed `ImGuiCol_Columns***` enums to `ImGuiCol_Separator***`. Kept redirection enums (will obsolete).
+- Renamed `ImGuiSetCond***` types and enums to `ImGuiCond***`. Kept redirection enums (will obsolete).
+- Renamed `GetStyleColName()` to `GetStyleColorName()` for consistency. Unlikely to be used by end-user!
+- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicitly to fix.
+- Marked the weird `IMGUI_ONCE_UPON_A_FRAME` helper macro as obsolete. Prefer using the more explicit `ImGuiOnceUponAFrame`.
+- Changed `ColorEdit4(const char* label, float col[4], bool show_alpha = true)` signature to `ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)`, where flags 0x01 is a safe no-op (hello dodgy backward compatibility!). The new `ColorEdit4`/`ColorPicker4` functions have lots of available flags! Check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
+- Changed signature of `ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)` to `ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))`. This function was rarely used and was very dodgy (no explicit ID!).
+- Changed `BeginPopupContextWindow(bool also_over_items=true, const char* str_id=NULL, int mouse_button=1)` signature to `(const char* str_id=NULL, int mouse_button=1, bool also_over_items=true)`. This is perhaps the most aggressive change in this update, but note that the majority of users relied on default parameters completely, so this will affect only a fraction of users of this already rarely used function.
+- Removed `IsPosHoveringAnyWindow()`, which was partly broken and misleading. In the vast majority of cases, people using that function wanted to use `io.WantCaptureMouse` flag. Replaced with IM_ASSERT + comment redirecting user to `io.WantCaptureMouse`. (#1237)
+- Removed the old `ValueColor()` helpers, they are equivalent to calling `Text(label)` + `SameLine()` + `ColorButton()`.
+- Removed `ColorEditMode()` and `ImGuiColorEditMode` type in favor of `ImGuiColorEditFlags` and parameters to the various Color*() functions. The `SetColorEditOptions()` function allows to initialize default but the user can still change them with right-click context menu. Commenting out your old call to `ColorEditMode()` may just be fine!
+
+Other Changes:
+
+- Added flags to `ColorEdit3()`, `ColorEdit4()`. The color edit widget now has a context-menu and access to the color picker. (#346)
+- Added flags to `ColorButton()`. (#346)
+- Added `ColorPicker3()`, `ColorPicker4()`. The API along with those of the updated `ColorEdit4()` was designed so you may use them in various situation and hopefully compose your own picker if required. There are a bunch of available flags, check the Demo window and comment for `ImGuiColorEditFlags_`. Some of the options it supports are: two color picker types (hue bar + sat/val rectangle, hue wheel + rotating sat/val triangle), display as u8 or float, lifting 0.0..1.0 constraints (currently rgba only), context menus, alpha bar, background checkerboard options, preview tooltip, basic revert. For simple use, calling the existing `ColorEdit4()` function as you did before will be enough, as you can now open the color picker from there. (#346) [@r-lyeh, @nem0, @thennequin, @dariomanesku and @ocornut]
+- Added `SetColorEditOptions()` to set default color options (e.g. if you want HSV over RGBA, float over u8, select a default picker mode etc. at startup time without a user intervention. Note that the user can still change options with the context menu unless disabled with `ImGuiColorFlags_NoOptions` or explicitly enforcing a display type/picker mode etc.).
+- Added user-facing `IsPopupOpen()` function. (#891) [@mkeeter]
+- Added `GetColorU32(u32)` variant that perform the style alpha multiply without a floating-point round trip, and helps makes code more consistent when using ImDrawList APIs.
+- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload.
+- Added `GetStyleColorVec4(ImGuiCol idx)` which is equivalent to accessing `ImGui::GetStyle().Colors[idx]` (aka return the raw style color without alpha alteration).
+- ImFontAtlas: Added `GlyphRangesBuilder` helper class, which makes it easier to build custom glyph ranges from your app/game localization data, or add into existing glyph ranges.
+- ImFontAtlas: Added `TexGlyphPadding` option. (#1282) [@jadwallis]
+- ImFontAtlas: Made it possible to override size of AddFontDefault() (even if it isn't really recommended!).
+- ImDrawList: Added `GetClipRectMin()`, `GetClipRectMax()` helpers.
+- Fixed Ini saving crash if the ImGuiWindowFlags_NoSavedSettings gets removed from a window after its creation (unlikely!). (#1000)
+- Fixed `PushID()`/`PopID()` from marking parent window as Accessed (which needlessly woke up the root "Debug" window when used outside of a regular window). (#747)
+- Fixed an assert when calling `CloseCurrentPopup()` twice in a row. [@nem0]
+- Window size can be loaded from .ini data even if ImGuiWindowFlags_NoResize flag is set. (#1048, #1056)
+- Columns: Added `SetColumnWidth()`. (#913) [@ggtucker]
+- Columns: Dragging a column preserve its width by default. (#913) [@ggtucker]
+- Columns: Fixed first column appearing wider than others. (#1266)
+- Columns: Fixed allocating space on the right-most side with the assumption of a vertical scrollbar. The space is only allocated when needed. (#125, #913, #893, #1138)
+- Columns: Fixed the right-most column from registering its content width to the parent window, which led to various issues when using auto-resizing window or e.g. horizontal scrolling. (#519, #125, #913)
+- Columns: Refactored some of the columns code internally toward a better API (not yet exposed) + minor optimizations. (#913) [@ggtucker, @ocornut]
+- Popups: Most pop-ups windows can be moved by the user after appearing (if they don't have explicit positions provided by caller, or e.g. sub-menu pop-up). The previous restriction was totally arbitrary. (#1252)
+- Tooltip: `SetTooltip()` is expanded immediately into a window, honoring current font / styling setting. Add internal mechanism to override tooltips. (#862)
+- PlotHistogram: bars are drawn based on zero-line, so negative values are going under. (#828)
+- Scrolling: Fixed return values of `GetScrollMaxX()`, `GetScrollMaxY()` when both scrollbars were enabled. Tweak demo to display more data. (#1271) [@degracode]
+- Scrolling: Fixes for Vertical Scrollbar not automatically getting enabled if enabled Horizontal Scrollbar straddle the vertical limit. (#1271, #246)
+- Scrolling: `SetScrollHere()`, `SetScrollFromPosY()`: Fixed Y scroll aiming when Horizontal Scrollbar is enabled. (#665).
+- [Windows] Clipboard: Fixed not closing Win32 clipboard on early open failure path. (#1264)
+- Removed an unnecessary dependency on int64_t which failed on some older compilers.
+- Demo: Rearranged everything under Widgets in a more consistent way.
+- Demo: Columns: Added Horizontal Scrolling demo. Tweaked another Columns demo. (#519, #125, #913)
+- Examples: OpenGL: Various makefiles for MINGW, Linux. (#1209, #1229, #1209) [@fr500, @acda]
+- Examples: Enabled vsync by default in example applications, so it doesn't confuse people that the sample run at 2000+ fps and waste an entire CPU. (#1213, #1151).
+- Various other small fixes, tweaks, comments, optimizations.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.50 (2017-06-02)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.50
+
+Breaking Changes:
+
+- Added a void* user_data parameter to Clipboard function handlers. (#875)
+- SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
+- Renamed ImDrawList::PathFill() - rarely used directly - to ImDrawList::PathFillConvex() for clarity and consistency.
+- Removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
+- Style: style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
+- BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().
+
+Other Changes:
+
+- InputText(): Added support for CTRL+Backspace (delete word).
+- InputText(): OSX uses Super+Arrows for home/end. Add Shortcut+Backspace support. (#650) [@michaelbartnett]
+- InputText(): Got rid of individual OSX-specific options in ImGuiIO, added a single io.OSXBehaviors flag. (#473, #650)
+- InputText(): Fixed pressing home key on last character when it isn't a trailing \n (#588, #815)
+- InputText(): Fixed state corruption/crash bug in stb_textedit.h redo logic when exhausting undo/redo char buffer. (#715. #681)
+- InputTextMultiline(): Fixed CTRL+DownArrow moving scrolling out of bounds.
+- InputTextMultiline(): Scrollbar fix for when input and latched internal buffers differs in a way that affects vertical scrollbar existence. (#725)
+- ImFormatString(): Fixed an overflow handling bug with implementation of vsnprintf() that do not return -1. (#793)
+- BeginChild(const char*) now applies stack id to provided label, consistent with other widgets. (#894, #713)
+- SameLine() with explicit X position is relative to left of group/columns. (ref #746, #125, #630)
+- SliderInt(), SliderFloat() supports reverse direction (where v_min > v_max). (#854)
+- SliderInt(), SliderFloat() better support for when v_min==v_max. (#919)
+- SliderInt(), SliderFloat() enforces writing back value when interacting, to be consistent with other widgets. (#919)
+- SliderInt, SliderFloat(): Fixed edge case where style.GrabMinSize being bigger than slider width can lead to a division by zero. (#919)
+- Added IsRectVisible() variation with explicit start-end positions. (#768) [@thedmd]
+- Fixed TextUnformatted() clipping bug in the large-text path when horizontal scroll has been applied. (#692, #246)
+- Fixed minor text clipping issue in window title when using font straying above usual line. (#699)
+- Fixed SetCursorScreenPos() fixed not adjusting CursorMaxPos as well.
+- Fixed scrolling offset when using SetScrollY(), SetScrollFromPosY(), SetScrollHere() with menu bar.
+- Fixed using IsItemActive() after EndGroup() or any widget using groups. (#840, #479)
+- Fixed IsItemActive() lagging by one frame on initial widget activation. (#840)
+- Fixed Separator() zero-height bounding box resulting in clipping when laying exactly on top line of clipping rectangle (#860)
+- Fixed PlotLines() PlotHistogram() calling with values_count == 0.
+- Fixed clicking on a window's void while staying still overzealously marking .ini settings as dirty. (#923)
+- Fixed assert triggering when a window has zero rendering but has a callback. (#810)
+- Scrollbar: Fixed rendering when sizes are negative to reduce glitches (which can happen with certain style settings and zero WindowMinSize).
+- EndGroup(): Made IsItemHovered() work when an item was activated within the group. (#849)
+- BulletText(): Fixed stopping to display formatted string after the '##' mark.
+- Closing the focused window restore focus to the first active root window in descending z-order .(part of #727)
+- Word-wrapping: Fixed a bug where we never wrapped after a 1 character word. [@sronsse]
+- Word-wrapping: Fixed TextWrapped() overriding wrap position if one is already set. (#690)
+- Word-wrapping: Fixed incorrect testing for negative wrap coordinates, they are perfectly legal. (#706)
+- ImGuiListClipper: Fixed automatic-height calc path dumbly having user display element 0 twice. (#661, #716)
+- ImGuiListClipper: Fix to behave within column. (#661, #662, #716)
+- ImDrawList: Renamed ImDrawList::PathFill() to ImDrawList::PathFillConvex() for clarity. (BREAKING API)
+- Columns: End() avoid calling Columns(1) if no columns set is open, not sure why it wasn't the case already (pros: faster, cons: exercise less code).
+- ColorButton(): Fix ColorButton showing wrong hex value for alpha. (#1068) [@codecat]
+- ColorEdit4(): better preserve inputting value out of 0..255 range, display then clamped in Hexadecimal form.
+- Shutdown() clear out some remaining pointers for sanity. (#836)
+- Added IMGUI_USE_BGRA_PACKED_COLOR option in imconfig.h (#767, #844) [@thedmd]
+- Style: Removed the inconsistent shadow under RenderCollapseTriangle() (~#707)
+- Style: Added ButtonTextAlign, ImGuiStyleVar_ButtonTextAlign. (#842)
+- ImFont: Allowing to use up to 0xFFFE glyphs in same font (increased from previous 0x8000).
+- ImFont: Added GetGlyphRangesThai() helper. [@nProtect]
+- ImFont: CalcWordWrapPositionA() fixed font scaling with fallback character.
+- ImFont: Calculate and store the approximate texture surface to get an idea of how costly each source font is.
+- ImFontConfig: Added GlyphOffset to explicitly offset glyphs at font build time, useful for merged fonts. Removed MergeGlyphCenterV. (BREAKING API)
+- Clarified asserts in CheckStacksSize() when there is a stack mismatch.
+- Context: Support for #define-ing GImGui and IMGUI_SET_CURRENT_CONTEXT_FUNC to enable custom thread-based hackery (#586)
+- Updated stb_truetype.h to 1.14 (added OTF support, removed warnings). (#883, #976)
+- Updated stb_rect_pack.h to 0.10 (removed warnings). (#883)
+- Added ImGuiMouseCursor_None enum value for convenient usage by app/backends.
+- Clipboard: Added a void* user_data parameter to Clipboard function handlers. (#875) (BREAKING API)
+- Internals: Refactor internal text alignment options to use ImVec2, removed ImGuiAlign. (#842, #222)
+- Internals: Renamed ImLoadFileToMemory to ImFileLoadToMemory to be consistent with ImFileOpen + fix mismatching .h name. (#917)
+- OS/Windows: Fixed Windows default clipboard handler leaving its buffer unfreed on application's exit. (#714)
+- OS/Windows: No default IME handler when compiling for Windows using GCC. (#738)
+- OS/Windows: Now using _wfopen() instead of fopen() to allow passing in paths/filenames with UTF-8 characters. (#917)
+- Tools: binary_to_compressed_c: Avoid ?? trigraphs sequences in string outputs which break some older compilers. (#839)
+- Demo: Added an extra 3-way columns demo.
+- Demo: ShowStyleEditor: show font character map / grid in more details.
+- Demo: Console: Fixed a completion bug when multiple candidates are equals and match until the end.
+- Demo: Fixed 1-byte off overflow in the ShowStyleEditor() combo usage. (#783) [@bear24rw]
+- Examples: Accessing ImVector fields directly, feel less stl-ey. (#810)
+- Examples: OpenGL*: Saving/restoring existing scissor rectangle for completeness. (#807)
+- Examples: OpenGL*: Saving/restoring active texture number (the value modified by glActiveTexture). (#1087, #1088, #1116)
+- Examples: OpenGL*: Saving/restoring separate color/alpha blend functions correctly. (#1120) [@greggman]
+- Examples: OpenGL2: Uploading font texture as RGBA32 to increase compatibility with users shaders for beginners. (#824)
+- Examples: Vulkan: Countless fixes and improvements. (#785, #804, #910, #1017, #1039, #1041, #1042, #1043, #1080) [@martty, @Loftilus, @ParticlePeter, @SaschaWillems]
+- Examples: DirectX9/10/10: Only call SetCursor(NULL) is io.MouseDrawCursor is set. (#585, #909)
+- Examples: DirectX9: Explicitly setting viewport to match that other examples are doing. (#937)
+- Examples: GLFW+OpenGL3: Fixed Shutdown() calling GL functions with NULL parameters if NewFrame was never called. (#800)
+- Examples: GLFW+OpenGL2: Renaming opengl_example/ to opengl2_example/ for clarity.
+- Examples: SDL+OpenGL: explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
+- Examples: SDL2: Added build .bat files for Win32.
+- Added various links to language/engine bindings.
+- Various other minor fixes, tweaks, comments, optimizations.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.49 (2016-05-09)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.49
+
+Breaking Changes:
+
+- Renamed `SetNextTreeNodeOpened()` to `SetNextTreeNodeOpen()` for consistency, no redirection.
+- Removed confusing set of `GetInternalState()`, `GetInternalStateSize()`, `SetInternalState()` functions. Now using `CreateContext()`, `DestroyContext()`, `GetCurrentContext()`, `SetCurrentContext()`. If you were using multiple contexts the change should be obvious and trivial.
+- Obsoleted old signature of `CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false)`, as extra parameters were badly designed and rarely used. Most uses were using 1 parameter and shouldn't affect you. You can replace the "default_open = true" flag in new API with `CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)`.
+- Changed `ImDrawList::PushClipRect(ImVec4 rect)` to `ImDraw::PushClipRect(ImVec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false)`. Note that higher-level `ImGui::PushClipRect()` is preferable because it will clip at logic/widget level, whereas `ImDrawList::PushClipRect()` only affect your renderer.
+- Title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore (see #655). If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
+ This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. (Or If this is confusing, just pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.)
+
+ ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
+ {
+ float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w));
+ float k = title_bg_col.w / new_a;
+ return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a);
+ }
+
+Other changes:
+
+- New version of ImGuiListClipper helper calculates item height automatically. See comments and demo code. (#662, #661, #660)
+- Added SetNextWindowSizeConstraints() to enable basic min/max and programmatic size constraints on window. Added demo. (#668)
+- Added PushClipRect()/PopClipRect() (previously part of imgui_internal.h). Changed ImDrawList::PushClipRect() prototype. (#610)
+- Added IsRootWindowOrAnyChildHovered() helper. (#615)
+- Added TreeNodeEx() functions. (#581, #600, #190)
+- Added ImGuiTreeNodeFlags_Selected flag to display TreeNode as "selected". (#581, #190)
+- Added ImGuiTreeNodeFlags_AllowOverlapMode flag. (#600)
+- Added ImGuiTreeNodeFlags_NoTreePushOnOpen flag (#590).
+- Added ImGuiTreeNodeFlags_NoAutoOpenOnLog flag (previously private).
+- Added ImGuiTreeNodeFlags_DefaultOpen flag (previously private).
+- Added ImGuiTreeNodeFlags_OpenOnDoubleClick flag.
+- Added ImGuiTreeNodeFlags_OpenOnArrow flag.
+- Added ImGuiTreeNodeFlags_Leaf flag, always opened, no arrow, for convenience. For simple use case prefer using TreeAdvanceToLabelPos()+Text().
+- Added ImGuiTreeNodeFlags_Bullet flag, to add a bullet to Leaf node or replace Arrow with a bullet.
+- Added TreeAdvanceToLabelPos(), GetTreeNodeToLabelSpacing() helpers. (#581, #324)
+- Added CreateContext()/DestroyContext()/GetCurrentContext()/SetCurrentContext(). Obsoleted nearly identical GetInternalState()/SetInternalState() functions. (#586, #269)
+- Added NewLine() to undo a SameLine() and as a shy reminder that horizontal layout support hasn't been implemented yet.
+- Added IsItemClicked() helper. (#581)
+- Added CollapsingHeader() variant with close button. (#600)
+- Fixed MenuBar missing lower border when borders are enabled.
+- InputText(): Fixed clipping of cursor rendering in case it gets out of the box (which can be forced w/ ImGuiInputTextFlags_NoHorizontalScroll. (#601)
+- Style: Changed default IndentSpacing from 22 to 21. (#581, #324)
+- Style: Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, which was inconsistent and causing visual artifact. (#655)
+ This broke the meaning of TitleBg and TitleBgActive. Only affect values where Alpha<1.0f. Fixed default theme. Read comments in "API BREAKING CHANGES" section to convert.
+- Relative rendering of order of Child windows creation is preserved, to allow more control with overlapping children. (#595)
+- Fixed GetWindowContentRegionMax() being off by ScrollbarSize amount when explicit SizeContents is set.
+- Indent(), Unindent(): optional non-default indenting width. (#324, #581)
+- Bullet(), BulletText(): Slightly bigger. Less polygons.
+- ButtonBehavior(): fixed subtle old bug when a repeating button would also return true on mouse release (barely noticeable unless RepeatRate is set to be very slow). (#656)
+- BeginMenu(): a menu that becomes disabled while open gets closed down, facilitate user's code. (#126)
+- BeginGroup(): fixed using within Columns set. (#630)
+- Fixed a lag in reading the currently hovered window when dragging a window. (#635)
+- Obsoleted 4 parameters version of CollapsingHeader(). Refactored code into TreeNodeBehavior. (#600, #579)
+- Scrollbar: minor fix for top-right rounding of scrollbar background when window has menu bar but no title bar.
+- MenuItem(): the check mark renders in disabled color when menu item is disabled.
+- Fixed clipping rectangle floating point representation to ensure renderer-side float point operations yield correct results in typical DirectX/GL settings. (#582, 597)
+- Fixed GetFrontMostModalRootWindow(), fixing missing fade-out when a combo pop was used stacked over a modal window. (#604)
+- ImDrawList: Added AddQuad(), AddQuadFilled() helpers.
+- ImDrawList: AddText() refactor, moving some code to ImFont, reserving less unused vertices when large vertical clipping occurs.
+- ImFont: Added RenderChar() helper.
+- ImFont: Added AddRemapChar() helper. (#609)
+- ImFontConfig: Clarified persistence requirement of GlyphRanges array. (#651)
+- ImGuiStorage: Added bool helper functions for completeness.
+- AddFontFromMemoryCompressedTTF(): Fix ImFontConfig propagation. (#587)
+- Renamed majority of use of the word "opened" to "open" for clarity. Renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(). (#625, #579)
+- Examples: OpenGL3: Saving/restoring glActiveTexture() state. (#602)
+- Examples: DirectX9: save/restore all device state.
+- Examples: DirectX9: Removed dependency on d3dx9.h, d3dx9.lib, dxguid.lib so it can be used in a DirectXMath.h only environment. (#611)
+- Examples: DirectX10/X11: Apply depth-stencil state (no use of depth buffer). (#640, #636)
+- Examples: DirectX11/X11: Added comments on removing dependency on D3DCompiler. (#638)
+- Examples: SDL: Initialize video+timer subsystem only.
+- Examples: Apple/iOS: lowered XCode project deployment target from 10.7 to 10.11. (#598, #575)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.48 (2016-04-09)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.48
+
+Breaking Changes:
+
+- Consistently honoring exact width passed to PushItemWidth() (when positive), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346)
+- Style: removed `style.WindowFillAlphaDefault` which was confusing and redundant, baked alpha into `ImGuiCol_WindowBg` color. If you had a custom WindowBg color but didn't change WindowFillAlphaDefault, multiply WindowBg alpha component by 0.7. Renamed `ImGuiCol_TooltipBg` to `ImGuiCol_PopupBG`, applies to other types of pop-ups. `bg_alpha` parameter of 5-parameters version of Begin() is an override. (#337)
+- InputText(): Added BufTextLen field in ImGuiTextEditCallbackData. Requesting user to update it if the buffer is modified in the callback. Added a temporary length-check assert to minimize panic for the 3 people using the callback. (#541)
+- Renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). (#340)
+
+Other Changes:
+
+- Consistently honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346)
+- Fixed clipping of child windows within parent not taking account of child outer clipping boundaries (including scrollbar, etc.). (#506)
+- TextUnformatted(): Fixed rare crash bug with large blurb of text (2k+) not finished with a '\n' and fully above the clipping Y line. (#535)
+- IO: Added 'KeySuper' field to hold CMD keyboard modifiers for OS X. Updated all examples accordingly. (#473)
+- Added ImGuiWindowFlags_ForceVerticalScrollbar, ImGuiWindowFlags_ForceHorizontalScrollbar flags. (#476)
+- Added IM_COL32 macros to generate a U32 packed color, convenient for direct use of ImDrawList api. (#346)
+- Added GetFontTexUvWhitePixel() helper, convenient for direct use of ImDrawList api.
+- Selectable(): Added ImGuiSelectableFlags_AllowDoubleClick flag to allow user reacting on double-click. (@zapolnov) (#516)
+- Begin(): made the close button explicitly set the boolean to false instead of toggling it. (#499)
+- BeginChild()/EndChild(): fixed incorrect layout to allow widgets submitted after an auto-fitted child window. (#540)
+- BeginChild(): Added ImGuiWindowFlags_AlwaysUseWindowPadding flag to ensure non-bordered child window uses window padding. (#462)
+- Fixed InputTextMultiLine(), ListBox(), BeginChildFrame(), ProgressBar(): outer frame not honoring bordering. (#462, #503)
+- Fixed Image(), ImageButtion() rendering a rectangle 1 px too large on each axis. (#457)
+- SetItemAllowOverlap(): Promoted from imgui_internal.h to public imgui.h api. (#517)
+- Combo(): Right-most button stays highlighted when pop-up is open.
+- Combo(): Display pop-up above if there's isn't enough space below / or select largest side. (#505)
+- DragFloat(), SliderFloat(), InputFloat(): fixed cases of erroneously returning true repeatedly after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564)
+- DragFloat(): Always apply value when mouse is held/widget active, so that an always-resetting variable (e.g. non saved local) can be passed.
+- InputText(): OS X friendly behaviors: Word movement uses ALT key; Shortcuts uses CMD key; Double-clicking text select a single word; Jumping to next word sets cursor to end of current word instead of beginning of current word. (@zhiayang), (#473)
+- InputText(): Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it if buffer is modified. Zero-ing structure properly before use. (#541)
+- CheckboxFlags(): Added support for testing/setting multiple flags at the same time. (@DMartinek) (#555)
+- TreeNode(), CollapsingHeader() fixed not being able to use "##" sequence in a formatted label.
+- ColorEdit4(): Empty label doesn't add InnerSpacing.x, matching behavior of other widgets. (#346)
+- ColorEdit4(): Removed unnecessary calls to scanf() when idle in hexadecimal edit mode.
+- BeginPopupContextItem(), BeginPopupContextWindow(): added early out optimization.
+- CaptureKeyboardFromApp() / CaptureMouseFromApp(): added argument to allow clearing the capture flag. (#533)
+- ImDrawList: Fixed index-overflow check broken by AddText() casting current index back to ImDrawIdx. (#514)
+- ImDrawList: Fixed incorrect removal of trailing draw command if it is a callback command.
+- ImDrawList: Allow windows with only a callback only to be functional. (#524)
+- ImDrawList: Fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. (#457)
+- ImDrawList: Fixed ImDrawList::AddCircle() to fit precisely within bounding box like AddCircleFilled() and AddRectFilled(). (#457)
+- ImDrawList: AddCircle(), AddRect() takes optional thickness parameter.
+- ImDrawList: Added AddTriangle().
+- ImDrawList: Added PrimQuadUV() helper to ease custom rendering of textured quads (require primitive reserve).
+- ImDrawList: Allow AddText(ImFont\* font, float font_size, ...) variant to take NULL/0.0f as default.
+- ImFontAtlas: heuristic increase default texture width up for large number of glyphs. (#491)
+- ImTextBuffer: Fixed empty() helper which was utterly broken.
+- Metrics: allow to inspect individual triangles in draw calls.
+- Demo: added more draw primitives in the Custom Rendering example. (#457)
+- Demo: extra comments and example for PushItemWidth(-1) patterns.
+- Demo: InputText password demo filters out blanks. (#515)
+- Demo: Fixed malloc/free mismatch and leak when destructing demo console, if it has been used. (@fungos) (#536)
+- Demo: plot code doesn't use ImVector to avoid heap allocation and be more friendly to custom allocator users. (#538)
+- Fixed compilation on DragonFly BSD (@mneumann) (#563)
+- Examples: Vulkan: Added a Vulkan example (@Loftilus) (#549)
+- Examples: DX10, DX11: Saving/restoring most device state so dropping render function in your codebase shouldn't have DX device side-effects. (#570)
+- Examples: DX10, DX11: Fixed ImGui_ImplDX??_NewFrame() from recreating device objects if render isn't called (g_pVB not set).
+- Examples: OpenGL3: Fix BindVertexArray/BindBuffer order. (@nlguillemot) (#527)
+- Examples: OpenGL: skip rendering and calling glViewport() if we have zero-fixed buffer. (#486)
+- Examples: SDL2+OpenGL3: Fix context creation options. Made ImGui_ImplSdlGL3_NewFrame() signature match GL2 one. (#468, #463)
+- Examples: SDL2+OpenGL2/3: Fix for high-dpi displays. (@nickgravelyn)
+- Various extra comments and clarification in the code.
+- Various other fixes and optimizations.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.47 (2015-12-25)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.47
+
+Changes:
+
+- Rebranding "ImGui" -> "dear imgui" as an optional first name to reduce ambiguity with IMGUI term. (#21)
+- Added ProgressBar(). (#333)
+- InputText(): Added ImGuiInputTextFlags_Password mode: hide display, disable logging/copying to clipboard. (#237, #363, #374)
+- Added GetColorU32() helper to retrieve color given enum with global alpha and extra applied.
+- Added ImGuiIO::ClearInputCharacters() superfluous helper.
+- Fixed ImDrawList draw command merging bug where using PopClipRect() along with PushTextureID()/PopTextureID() functions
+ would occasionally restore an incorrect clipping rectangle.
+- Fixed ImDrawList draw command merging so PushTextureID(XXX)/PopTextureID()/PushTextureID(XXX) sequence are now properly merged.
+- Fixed large popups positioning issues when their contents on either axis is larger than DisplaySize,
+ and WindowPadding < DisplaySafeAreaPadding.
+- Fixed border rendering in various situations when using non-pixel aligned glyphs.
+- Fixed border rendering of windows to always contain the border within the window.
+- Fixed Shutdown() leaking font atlas data if NewFrame() was never called. (#396, #303)
+- Fixed int>void\* warnings for 64-bit architectures with fancy warnings enabled.
+- Renamed the dubious Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
+- InputText(): Fixed and better handling of using keyboard while mouse button if being held and dragging. (#429)
+- InputText(): Replace OS IME (Input Method Editor) cursor on top-left when we are not text editing.
+- TreeNode(), CollapsingHeader(), Bullet(), BulletText(): various sizing and layout fixes to better support laying out
+ multiple item with different height on same line. (#414, #282)
+- Begin(): Initial window creation with ImGuiWindowFlags_NoBringToFrontOnFocus flag pushes it at the front of global window list.
+- BeginPopupContextWindow() and BeginPopupContextVoid() reopen window on subsequent click. (#439)
+- ColorEdit4(): Fixed broken tooltip on hovering the color button. (actually fixes #373, #380)
+- ImageButton(): uses FrameRounding up to a maximum of available framing size. (#394)
+- Columns: Fixed bug with indentation within columns, also making code a bit shorter/faster. (#414, #125)
+- Columns: Columns set with no implicit id include the columns count within the id to reduce collisions. (#125)
+- Columns: Removed one unnecessary allocation when columns are not used by a window. (#125)
+- ImFontAtlas: Tweaked GetGlyphRangesJapanese() so it is easier to modify.
+- ImFontAtlas: Updated stb_rect_pack.h to 0.08.
+- Metrics: Fixed computing ImDrawCmd bounding box when the draw buffer have been unindexed.
+- Demo: Added a simple "Property Editor" demo applet. (#125, #414)
+- Demo: Fixed assertion in "Custom Rendering" demo when holding both mouse buttons. (#393)
+- Demo: Lots of extra comments, fixes.
+- Demo: Tweaks to Style Editor.
+- Examples: Not clearing input data/tex data in atlas (will be required for dynamic atlas anyway).
+- Examples: Added /Zi (output debug information) to Win32 batch files.
+- Examples: Various fixes for resizing window and recreating graphic context.
+- Examples: OpenGL2/3: Save/restore viewport as part of default render function. (#392, #441).
+- Examples; OpenGL3: Fixed gl3w.c for Linux when compiled with a C++ compiler. (#411)
+- Examples: DirectX: Removed assumption about Unicode build in example main.cpp. (#399)
+- Examples: DirectX10: Added DirectX10 example. (#424)
+- Examples: DirectX11: Downgraded requirement from shader model 5.0 to 4.0. (#420)
+- Examples: DirectX11: Removed Debug flag from graphics context. (#415)
+- Examples: Added SDL+OpenGL3 example. (#356)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.46 (2015-10-18)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.46
+
+Changes:
+
+- Begin*(): added ImGuiWindowFlags_NoFocusOnAppearing flag. (#314)
+- Begin*(): added ImGuiWindowFlags_NoBringToFrontOnFocus flag.
+- Added GetDrawData() alternative to setting a Render function pointer in ImGuiIO structure.
+- Added SetClipboardText(), GetClipboardText() helper shortcuts that user code can call directly without reading
+ from the ImGuiIO structure (to match MemAlloc/MemFree)
+- Fixed handling of malformed UTF-8 at the end of a non-zero terminated string range.
+- Fixed mouse click detection when passing DeltaTime 0.0. (#338)
+- Fixed IsKeyReleased() and IsMouseReleased() returning true on the first frame.
+- Fixed using SetNextWindow\* functions on Modal windows with a ImGuiSetCond_Appearing condition. (#377)
+- IsMouseHoveringRect(): Added 'bool clip' parameter to disable clipping provided rectangle. (#316)
+- InputText(): added ImGuiInputTextFlags_ReadOnly flag. (#211)
+- InputText(): lose cursor/undo-stack when reactivating focus is buffer has changed size.
+- InputText(): fixed ignoring text inputs when ALT or ALTGR are pressed. (#334)
+- InputText(): fixed mouse-dragging not tracking the cursor when text doesn't fit. (#339)
+- InputText(): fixed cursor pixel-perfect alignment when horizontally scrolling.
+- InputText(): fixed crash when passing a buf_size==0 (which can be of use for read-only selectable text boxes). (#360)
+- InputFloat() fixed explicit precision modifier, both display and input were broken.
+- PlotHistogram(): improved rendering of histogram with a lot of values.
+- Dummy(): creates an item so functions such as IsItemHovered() can be used.
+- BeginChildFrame() helper: added the extra_flags parameter.
+- Scrollbar: fixed rounding of background + child window consistenly have ChildWindowBg color under ScrollbarBg fill. (#355).
+- Scrollbar: background color less translucent in default style so it works better when changing background color.
+- Scrollbar: fixed minor rendering offset when borders are enabled. (#365)
+- ImDrawList: fixed 1 leak per ImDrawList using the ChannelsSplit() API (via Columns). (#318)
+- ImDrawList: fixed rectangle rendering glitches with width/height <= 1/2 and rounding enabled.
+- ImDrawList: AddImage() uv parameters default to (0,0) and (1,1).
+- ImFontAtlas: Added TexDesiredWidth and tweaked default cheapo best-width choice. (#327)
+- ImFontAtlas: Added GetGlyphRangesKorean() helper to retrieve unicode ranges for Korean. (#348)
+- ImGuiTextFilter::Draw() helper return bool and build when filter is modified.
+- ImGuiTextBuffer: added c_str() helper.
+- ColorEdit4(): fixed hovering the color button always showing 1.0 alpha. (#373)
+- ColorConvertFloat4ToU32() round the floats instead of truncating them.
+- Window: Fixed window lower-right clipping limit so it plays more friendly with both OpenGL and DirectX coordinates.
+- Internal: Extracted a EndFrame() function out of Render() but kept it internal/private + clarified some asserts. (#335)
+- Internal: Added missing IMGUI_API definitions in imgui_internal.h (#326)
+- Internal: ImLoadFileToMemory() return void\* instead of taking void*\* + allow optional int\* file_size.
+- Demo: Horizontal scrollbar demo allows to enable simultanaeous scrollbars on both axises.
+- Tools: binary_to_compressed_c.cpp: added -nocompress option.
+- Examples: Added example for the Marmalade platform.
+- Examples: Added batch files to build Windows examples with VS.
+- Examples: OpenGL3: Saving/restoring more GL state correctly. (#347)
+- Examples: OpenGL2/3: Added msys2/mingw64 target to Makefiles.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.45 (2015-09-01)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.45
+
+Breaking Changes:
+
+- With the addition of better horizontal scrolling primitives I had to make some consistency fixes.
+ `GetCursorPos()` `SetCursorPos()` `GetContentRegionMax()` `GetWindowContentRegionMin()` `GetWindowContentRegionMax()`
+ are now incorporating the scrolling amount. They were incorrectly not incorporating this amount previously.
+ It PROBABLY shouldn't break anything, but that depends on how you used them. Namely:
+ - If you always used SetCursorPos() with values relative to GetCursorPos() there shouldn't be a problem.
+ However if you used absolute coordinates, note that SetCursorPosY(100.0f) will put you at +100 from the initial Y position (which may be scrolled out of the view), NOT at +100 from the window top border. Since there wasn't any official scrolling value on X axis (past just manually moving the cursor) this can only affect you if you used to set absolute coordinates on the Y axis which is hopefully rare/unlikely, and trivial to fix.
+ - The value of GetWindowContentRegionMax() isn't necessarily close to GetWindowWidth() if horizontally scrolling.
+ Previously they were roughly interchangeable (roughly because the content region exclude window padding).
+
+Other Changes:
+
+- Added Horizontal Scrollbar via ImGuiWindowFlags_HorizontalScroll (#246).
+- Added GetScrollX(), GetScrollX(), GetScrollMaxX() apis (#246).
+- Added SetNextWindowContentSize(), SetNextWindowContentWidth() to explicitly set the content size of a window, which
+ define the range of scrollbar. When set explicitly it also define the base value from which widget width are derived.
+- Added IO.WantTextInput telling when ImGui is expecting text input, so that e.g. OS on-screen keyboard can be enabled.
+- Added printf attribute to printf-like text formatting functions (Clang/GCC).
+- Added GetMousePosOnOpeningCurrentPopup() helper.
+- Added GetContentRegionAvailWidth() helper.
+- Malformed UTF-8 data don't terminate string, output 0xFFFD instead (#307).
+- ImDrawList: Added AddBezierCurve(), PathBezierCurveTo() API for cubic bezier curves (#311).
+- ImDrawList: Allow to override ImDrawIdx type (#292).
+- ImDrawList: Added an assert on overflowing index value (#292).
+- ImDrawList: Fixed issues with channels split/merge. Now functional without manually adding a draw cmd. Added comments.
+- ImDrawData: Added ScaleClipRects() helper useful when rendering scaled. (#287).
+- Fixed Bullet() inconsistent layout behaviour when clipped.
+- Fixed IsWindowHovered() not taking account of window hoverability (may be disabled because of a popup).
+- Fixed InvisibleButton() not honoring negative size consistently with other widgets that do so.
+- Fixed OpenPopup() accessing current window, effectively opening "Debug" when called from an empty window stack.
+- TreeNode(): Fixed IsItemHovered() result being inconsistent with interaction visuals (#282).
+- TreeNode(): Fixed mouse interaction padding past the node label being accounted for in layout (#282).
+- BeginChild(): Passing a ImGuiWindowFlags_NoMove inhibits moving parent window from this child.
+- BeginChild() fixed missing rounding for child sizes which leaked into layout and have items misaligned.
+- Begin(): Removed default name = "Debug" parameter. We already have a "Debug" window pushed to the stack in the first place so it's not really a useful default.
+- Begin(): Minor fixes with windows main clipping rectangle (e.g. child window with border).
+- Begin(): Window flags are only read on the first call of the frame. Subsequent calls ignore flags, which allows appending to a window without worryin about flags.
+- InputText(): ignore character input when ctrl/alt are held. (Normally those text input are ignored by most wrappers.) (#279).
+- Demo: Fixed incorrectly formed string passed to Combo (#298).
+- Demo: Added simple Log demo.
+- Demo: Added horizontal scrolling example + enabled in console, log and child examples (#246).
+- Style: made scrollbars rounded by default. Because nice. Minor menu bar background alpha tweak. (#246)
+- Metrics: display indices along with triangles count (#299) and some internal state.
+- ImGuiTextFilter::PassFilter() supports string range. Added [] helper to ImGuiTextBuffer.
+- ImGuiTextFilter::Draw() default parameter width=0.0f for no override, allow override with negative values.
+- Examples: OpenGL2/OpenGL3: fix for retina displays. Default font current lack crispness.
+- Examples: OpenGL2/OpenGL3: save/restore more GL state correctly.
+- Examples: DirectX9/DirectX11: resizing buffers dynamically (#299).
+- Examples: DirectX9/DirectX11: added missing middle mouse button to Windows event handler.
+- Examples: DirectX11: fix for Visual Studio 2015 presumably shipping with an updated version of DX11.
+- Examples: iOS: fixed missing files in project.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.44 (2015-08-08)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.44
+
+Breaking Changes:
+
+- imgui.cpp has been split intro extra files: imgui_demo.cpp, imgui_draw.cpp, imgui_internal.h.
+ Add the two extra .cpp to your project or #include them from another .cpp file. (#219)
+
+Other Changes:
+
+- Internal data structure and several useful functions are now exposed in imgui_internal.h. This should make it easier
+ and more natural to extend ImGui. However please note that none of the content in imgui_internal.h is guaranteed
+ for forward-compatibility and code using those types/functions may occasionally break. (#219)
+- All sample code is in imgui_demo.cpp. Please keep this file in your project and consider allowing your code to call
+ the ShowTestWindow() function as de-facto guide to ImGui features. It will be stripped out by the linker when unused.
+- Added GetContentRegionAvail() helper (basically GetContentRegionMax() - GetCursorPos()).
+- Added ImGuiWindowFlags_NoInputs for totally input-passthru window.
+- Button(): honor negative size consistently with other widgets that do so (width -100 to align the button 100 pixels
+ before the right-most position of the contents region).
+- InputTextMultiline(): honor negative size consistently with other widgets that do so.
+- Combo() clamp popup to lower edge of visible area.
+- InputInt(): value doesn't pass through an int>float>int casting chain, fix handling lost of precision with "large" integer.
+- InputInt() allow hexadecimal input (awkwardly via ImGuiInputTextFlags_CharsHexadecimal but we will allow format
+ string in InputInt* later).
+- Checkbox(), RadioButton(): fixed scaling of checkbox and radio button for the filling of "active" visual.
+- Columns: never assume horizontal space for scrollbar if NoScrollbar flag is explicitly set.
+- Slider: fixed using FramePadding between frame and grab visual. Scaling that spacing would look odd.
+- Fixed lower-right resize grip hit box not scaling along with its rendered size (#287)
+- ImDrawList: Fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (v1.43) being off by an extra PI for no reason.
+- ImDrawList: Added ImDrawList::AddText() shorthand helper.
+- ImDrawList: Add missing support for anti-aliased thick-lines (#133, also ref #288)
+- ImFontAtlas: Added AddFontFromMemoryCompressedBase85TTF() to load base85 encoded font string. Default font encoded
+ as base85 saves ~100 lines / 26 KB of source code. Added base85 output to the binary_to_compressed_c tool.
+- Build fix for MinGW (#276).
+- Examples: OpenGL3: Fixed running on script core profiles for OSX (#277).
+- Examples: OpenGL3: Simplified code using glBufferData for vertices as well (#277, #278)
+- Examples: DirectX11: Clear font texture view to ensure Release() doesn't get called twice (#290).
+- Updated to stb_truetype 1.07 (back to vanilla version as our minor changes are now in master & fix unlikely assert
+ with odd fonts (#280)
+
+
+-----------------------------------------------------------------------
+ VERSION 1.43 (2015-07-17)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.43
+
+Breaking Changes:
+
+- This is a rather important release and we unfortunately had to break the rendering API.
+ ImGui now requires you to render indexed vertices instead of non-indexed ones. The fix should be very easy.
+ Sorry for that! This change is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
+ Each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles
+ using indices from the index buffer.
+- If you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update
+ your copy and you can ignore the rest.
+- The signature of the io.RenderDrawListsFn handler has changed
+ From: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
+ To: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data)
+ With: argument 'cmd_lists' -> 'draw_data->CmdLists'
+ argument 'cmd_lists_count' -> 'draw_data->CmdListsCount'
+ ImDrawList 'commands' -> 'CmdBuffer'
+ ImDrawList 'vtx_buffer' -> 'VtxBuffer'
+ ImDrawList n/a -> 'IdxBuffer' (new)
+ ImDrawCmd 'vtx_count' -> 'ElemCount'
+ ImDrawCmd 'clip_rect' -> 'ClipRect'
+ ImDrawCmd 'user_callback' -> 'UserCallback'
+ ImDrawCmd 'texture_id' -> 'TextureId'
+- If you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index
+ the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
+ Refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. Please upgrade!
+
+Other Changes:
+
+- Added anti-aliasing on lines and shapes based on primitives by @MikkoMononen (#133).
+ Between the use of indexed-rendering and the fact that the entire rendering codebase has been optimized and massaged
+ enough, with anti-aliasing enabled ImGui 1.43 is now running FASTER than 1.41.
+ Made some extra effort in making the code run faster in your typical Debug build.
+- Anti-aliasing can be disabled in the ImGuiStyle structure via the AntiAliasedLines/AntiAliasedShapes fields for further gains.
+- ImDrawList: Added AddPolyline(), AddConvexPolyFilled() with optional anti-aliasing.
+- ImDrawList: Added stateful path building and stroking API. PathLineTo(), PathArcTo(), PathRect(), PathFill(), PathStroke()
+ with optional anti-aliasing.
+- ImDrawList: Added AddRectFilledMultiColor() helper.
+- ImDrawList: Added multi-channel rendering so out of order elements can be rendered in separate channels and then merged
+ back together (used by columns).
+- ImDrawList: Fixed merging draw commands when equal clip rectangles are in the two first commands.
+- ImDrawList: Fixed window draw lists not destructed properly on Shutdown().
+- ImDrawData: Added DeIndexAllBuffers() helper.
+- Added lots of new font options ImFontAtlas::AddFont() and the new ImFontConfig structure.
+ - Added support for oversampling (ImFontConfig: OversampleH, OversampleV) and sub-pixel positioning (ImFontConfig: PixelSnapH).
+ Oversampling allows sub-pixel positioning but can also be used as a way to get some leeway with scaling fonts without re-rasterizing.
+ - Added GlyphExtraSpacing option to add extra horizontal spacing between characters (#242).
+ - Added MergeMode option to merge glyphs from different font inputs into a same font (#182, #232).
+ - Added FontDataOwnedByAtlas option to keep ownership from the TTF data buffer and request the atlas to make a copy (#220).
+- Updated to stb_truetype 1.06 (+ minor mods) with better font rasterization.
+- InputText: Added ImGuiInputTextFlags_NoHorizontalScroll flag.
+- InputText: Added ImGuiInputTextFlags_AlwaysInsertMode flag.
+- InputText: Added HasSelection() helper in ImGuiTextEditCallbackData as a clarification.
+- InputText: Fix for using END key on a multi-line text editor (#275)
+- Columns: Dispatch render of each column in a sub-draw list and merge on closure, saving a lot of draw calls! (#125)
+- Popups: Fixed Combo boxes inside menus. (#272)
+- Style: Added GrabRounding setting to make the sliders etc. grabs rounded.
+- Changed SameLine() parameters from int to float.
+- Fixed incorrect assert triggering when code stole ActiveID from user moving a window by calling e.g. SetKeyboardFocusHere().
+- Fixed CollapsingHeader() label rendering outside its frame in columns context where ClipRect max isn't aligned with the
+ right-side of the header.
+- Metrics window: calculate bounding box of actual vertices when hovering a draw list.
+- Examples: Showing more information in the Fonts section.
+- Examples: Added a gratuitous About window.
+- Examples: Updated all examples code (OpenGL/DX9/DX11/SDL/Allegro/iOS) to use indexed rendering.
+- Examples: Fixed the SDL2 example to support Unicode text input (#274).
+
+
+-----------------------------------------------------------------------
+ VERSION 1.42 (2015-07-08)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.42
+
+Breaking Changes:
+
+- Renamed SetScrollPosHere() to SetScrollHere(). Kept inline redirection function (will obsolete).
+- Renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion and make scrolling API consistent,
+ because positions (e.g. cursor position) are not equivalent to scrolling amount.
+- Removed obsolete GetDefaultFontData() function that would assert anyway.
+ If you are updating from <1.30 you'll get a compile error instead of an assertion. (obsoleted 2015/01/11)
+
+Other Changes:
+
+- Added SDL2 example application (courtesy of @CedricGuillemet)
+- Added iOS example application (courtesy of @joeld42)
+- Added Allegro 5 example application (courtesy of @bggd)
+- Added TitleBgActive color in style so focused window is made visible. (#253)
+- Added CaptureKeyboardFromApp() / CaptureMouseFromApp() to manually enforce inputs capturing.
+- Added DragFloatRange2() DragIntRange2() helpers. (#76)
+- Added a Y centering ratio to SetScrollFromCursorPos() which can be used to aim the top or bottom of the window. (#150)
+- Added SetScrollY(), SetScrollFromPos(), GetCursorStartPos() for manual scrolling manipulations. (#150).
+- Added GetKeyIndex() helper for converting from ImGuiKey_\* enum to user's keycodes. Basically pulls from io.KeysMap[].
+- Added missing ImGuiKey_PageUp, ImGuiKey_PageDown so more UI code can be written without referring to implementation-side keycodes.
+- MenuItem() can be activated on release. (#245)
+- Allowing NewFrame() with DeltaTime==0.0f to not assert.
+- Fixed IsMouseDragging(). (#260)
+- Fixed PlotLines(), PlotHistogram() using incorrect hovering test so they would show their tooltip even when there is
+ a popup between mouse and the graph.
+- Fixed window padding being reported incorrectly for child windows with borders when parent have no borders.
+- Fixed a bug with TextUnformatted() clipping of long text blob when clipping y1 line sits on the first line of text. (#257)
+- Fixed text baseline alignment of small button (no padding) after regular buttons.
+- Fixed ListBoxHeader() not honoring negative sizes the same way as BeginChild() or BeginChildFrame(). (#263)
+- Fixed warnings for more pedantic compiler settings (#258).
+- ImVector<> cannot be re-defined anymore, cannot be replaced with std::vector<>. Allowed us to clean up and optimize
+ lots of code. Yeah! (#262)
+- ImDrawList: store pointer to their owner name for easier auditing/debugging.
+- Examples: added scroll tracking example with SetScrollFromCursorPos().
+- Examples: metrics windows render clip rectangle when hovering over a draw call.
+- Lots of small optimization (particularly to run faster on unoptimized builds) and tidying up.
+- Added font links in extra_fonts/ + instructions for using compressed fonts in C array.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.41 (2015-06-26)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.41
+
+Breaking Changes:
+
+- Changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent).
+ Only makes a difference when texture have transparency.
+- Changed Selectable() API from (label, selected, size) to (label, selected, flags, size).
+ Size override should be used very rarely so hopefully it doesn't affect many people. Sorry!
+
+Other Changes:
+
+- Added InputTextMultiline() multi-line text editor, vertical scrolling, selection, optimized enough to handle rather
+ big chunks of text in stateless context (thousands of lines are ok), option for allowing Tab to be input, option
+ for validating with Return or Ctrl+Return (#200).
+- Added modal window API, BeginPopupModal(), follows the popup api scheme. Modal windows can be closed by clicking
+ outside. By default the rest of the screen is dimmed (using ImGuiCol_ModalWindowDarkening). Modal windows can be stacked.
+- Added GetGlyphRangesCyrillic() helper (#237).
+- Added SetNextWindowPosCenter() to center a window prior to knowing its size. (#249)
+- Added IsWindowHovered() helper.
+- Added IsMouseReleased(), IsKeyReleased() helpers to allow to user to avoid tracking them. (#248)
+- Allow Set*WindowSize() calls to be used with popups.
+- Window: AutoFit can be triggered on each axis separately via SetNextWindowSize(), etc.
+- Window: fixed scrolling with mouse wheel while window was collapsed.
+- Window: fixed mouse wheel scroll issues.
+- DragFloat(), SliderFloat(): Fixed rounding of negative numbers which sometime made the negative lower bound unreachable.
+- InputText(): lifted character count limit.
+- InputText(): fixes in case of using per-window font scaling.
+- Selectable(), MenuItem(): do not use frame rounding for hovering/selection.
+- Selectable(): Added flag ImGuiSelectableFlags_DontClosePopups.
+- Selectable(): Added flag ImGuiSelectableFlags_SpanAllColumns (#125).
+- Combo(): Fixed issue with activating a Combo() not taking active id (#241).
+- ColorButton(), ColorEdit4(): fix to ensure that the colored square stays square when non-default padding settings are used.
+- BeginChildFrame(): returns bool like BeginChild() for clipping.
+- SetScrollPosHere(): takes account of item height + more accurate centering + fixed precision issue.
+- ImFont: ignoring '\r'.
+- ImFont: added GetCharAdvance() helper. Exposed font Ascent and font Descent.
+- ImFont: additional rendering optimizations.
+- Metrics windows display storage size.
+
+
+-----------------------------------------------------------------------
+ VERSION 1.40 (2015-05-31)
+-----------------------------------------------------------------------
+
+Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.40
+
+Breaking Changes:
+
+- The BeginPopup() API (introduced in 1.37) had to be changed to allow for stacked popups and menus.
+ Use OpenPopup() to toggle the opened state and BeginPopup() to append.**
+- The third parameter of Button(), 'repeat_if_held' has been removed. While it's been very rarely used,
+ some code will possibly break if you didn't rely on the default parameter.
+ Use PushButtonRepeat()/PopButtonRepeat() to configure repeat.
+- Renamed IsRectClipped() to !IsRectVisible() for consistency (opposite return value!). Kept inline redirection function (will obsolete)
+- Renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline indirection function (will obsolete).
+
+Other Changes:
+
+- Menus: Added a menu system! Menus are typically populated with menu items and sub-menus, but you can add any sort of
+ widgets in them (buttons, text inputs, sliders, etc.). (#126)
+- Menus: Added MenuItem() to append a menu item. Optional shortcut display, acts a button & toggle with checked/unchecked state,
+ disabled mode. Menu items can be used in any window.
+- Menus: Added BeginMenu() to append a sub-menu. Note that you generally want to add sub-menu inside a popup or a menu-bar.
+ They will work inside a normal window but it will be a bit unusual.
+- Menus: Added BeginMenuBar() to append to window menu-bar (set ImGuiWindowFlags_MenuBar to enable).
+- Menus: Added BeginMainMenuBar() helper to append to a fullscreen main menu-bar.
+- Popups: Support for stacked popups. Each popup level inhibit inputs to lower levels. The menus system is based on this. (#126).
+- Popups: Added BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid() to create a popup window on mouse-click.
+- Popups: Popups have borders by default (#197), attenuated border alpha in default theme.
+- Popups & Tooltip: Fit within display. Handling various positioning/sizing/scrolling edge cases. Better hysteresis when moving
+ in corners. Tooltip always tries to stay away from mouse-cursor.
+- Added ImGuiStorage::GetVoidPtrRef() for manipulating stored void*.
+- Added IsKeyDown() IsMouseDown() as convenience and for consistency with existing functions (instead of reading them from IO structures).
+- Added Dummy() helper to advance layout by a given size. Unlike InvisibleButton() this doesn't catch any click.
+- Added configurable io.KeyRepeatDelay, io.KeyRepeatRate keyboard and mouse repeat rate.
+- Added PushButtonRepeat() / PopButtonRepeat() to enable hold-button-to-repeat press on any button.
+- Removed the third 'repeat' parameter of Button().
+- Added IsAnyItemHovered() helper.
+- Added GetItemsLineHeightWithSpacing() helper.
+- Added ImGuiListClipper helper for clipping large list of evenly sized items, to avoid using CalcListClipping() directly.
+- Separator: within group start on group horizontal offset. (#205)
+- InputText: Fixed incorrect edit state after text buffer is appended to by user via the callback. (#206)
+- InputText: CTRL+letter-key shortcuts (e.g. CTRL+C/V/X) makes sure only CTRL is pressed. (#214)
+- InputText: Fixed cursor generating a zero-width wire-frame rectangle turning into a division by zero (would go unnoticed
+ unless you trapped exceptions).
+- InputFloatN/InputIntN: Flags parameter added to match scalar versions. (#218)
+- Selectable: Horizontal filling not declared to ItemSize() so Selectable(),SameLine() works and we can better auto-fit the window.
+- Selectable: Handling text baseline alignment for line that aren't of text height.
+- Combo: Empty label doesn't add ItemInnerSpacing alignment, matching other widgets.
+- EndGroup: Carries the text base offset from the last line of the group (sort of incorrect but better than nothing,
+ should use the first line of the group, will implement in the future).
+- Columns: distinguish columns-set ID from other widgets as a convenience, added asserts and sailors.
+- ListBox: ListBox() function only use public API to encourage creating custom versions. ListBoxHeader() can return false.
+- ListBox: Uses ImGuiListClipper and assume items of matching height, so large lists can be handled.
+- Plot: overlay label clipped within frame when not fitting.
+- Window: Added ImGuiSetCond_Appearing to test the hidden->visible transition in SetWindow***/SetNextWindow*** functions.
+- Window: Auto-fitting cancel out one worth of vertical spacing for vertical symmetry (like what group and tooltip do).
+- Window: Default item width for auto-resizing windows expressed as a factor of font height, scales better with different font.
+- Window: Fixed auto-fit calculation mismatch of whether a scrollbar will be added by maximum height clamping. Also honor NoScrollBar in the case of height clamping, not adding extra horizontal space.
+- Window: Hovering require to hover same child window. Reverted 860cf57 (December 3). Might break something if you have
+ child overlapping items in parent window.
+- Window: Fixed appending multiple times to an existing child via multiple BeginChild/EndChild calls to same child name.
+ Allows a simple form of out-of-order appending.
+- Window: Fixed auto-filling child window using WindowMinSize at their minimum size, irrelevant.
+- Metrics: Added io.MetricsActiveWindows counter. (#213.
+- Metrics: Added io.MetricsAllocs counter (number of active memory allocations).
+- Metrics: ShowMetricsWindow() shows popups stack, allocations.
+- Style: Added style.DisplayWindowPadding to prevent windows from reaching edges of display (similar to style.DisplaySafeAreaPadding which is still in effect and also affect popups/tooltips).
+- Style: Removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
+- Style: Added style.ScrollbarRounding. (#212)
+- Style: Added ImGuiCol_TextDisabled for disabled text. Added TextDisabled() helper.
+- Style: Added style.WindowTitleAlign alignment options, to e.g. center title on windows. (#222)
+- ImVector: tweak growth strategy, matches vector from VS2010.
+- ImFontAtlas: Added ClearFonts(), making the different clear funcs more explicit. (#224)
+- ImFontAtlas: Fixed appending new fonts without clearing existing fonts. Clearing input data left to application. (#224)
+- ImDrawList: Merge draw command better, cases of multiple Begin/End gets merged properly.
+- Store common stacked settings contiguously in memory to avoid heap allocation for unused features, and reduce cache misses.
+- Shutdown() tests for g.IO.Fonts not being NULL to ease use of multiple ImGui contexts. (#207)
+- Added IMGUI_DISABLE_OBSOLETE_FUNCTIONS define to disable the functions that are meant to be removed.
+- Examples: Added ? marks with tooltips next to various widgets. Added more comments in the demo window.
+- Examples: Added Menu-bar example.
+- Examples: Added Simple Layout example.
+- Examples: AutoResize demo doesn't use TextWrapped().
+- Examples: Console example uses standard malloc/free, makes more sense as a copy & pastable example.
+- Examples: DirectX9/11: Fixed key mapping for down arrow.
+- Examples: DirectX9/11: hide OS cursor if ImGui is drawing it. (#155)
+- Examples: DirectX11: explicitly set rasterizer state.
+- Examples: OpenGL3: Add conditional compilation of forward compat as required by glfw on OSX. (#229)
+- Fixed build with Visual Studio 2008 (possibly earlier versions as well).
+- Other fixes, comments, tweaks.
+
+
+-----------------------------------------------------------------------
+
+For older version, see https://github.com/ocornut/imgui/releases
+
diff --git a/Client/ThirdParty/imgui/docs/EXAMPLES.md b/Client/ThirdParty/imgui/docs/EXAMPLES.md
new file mode 100644
index 0000000..63b64d2
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/EXAMPLES.md
@@ -0,0 +1,246 @@
+_(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md or view this file with any Markdown viewer)_
+
+## Dear ImGui: Examples
+
+**The [examples/](https://github.com/ocornut/imgui/blob/master/examples) folder example applications (standalone, ready-to-build) for variety of
+platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder (see [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md)).
+
+The purpose of Examples is to showcase integration with backends, let you try Dear ImGui, and guide you toward
+integrating Dear ImGui in your own application/game/engine.
+**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
+
+You can find Windows binaries for some of those example applications at:
+ http://www.dearimgui.org/binaries
+
+
+### Getting Started
+
+Integration in a typical existing application, should take <20 lines when using standard backends.
+
+ At initialization:
+ call ImGui::CreateContext()
+ call ImGui_ImplXXXX_Init() for each backend.
+
+ At the beginning of your frame:
+ call ImGui_ImplXXXX_NewFrame() for each backend.
+ call ImGui::NewFrame()
+
+ At the end of your frame:
+ call ImGui::Render()
+ call ImGui_ImplXXXX_RenderDrawData() for your Renderer backend.
+
+ At shutdown:
+ call ImGui_ImplXXXX_Shutdown() for each backend.
+ call ImGui::DestroyContext()
+
+Example (using [backends/imgui_impl_win32.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_win32.cpp) + [backends/imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)):
+
+ // Create a Dear ImGui context, setup some options
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable some options
+
+ // Initialize Platform + Renderer backends (here: using imgui_impl_win32.cpp + imgui_impl_dx11.cpp)
+ ImGui_ImplWin32_Init(my_hwnd);
+ ImGui_ImplDX11_Init(my_d3d_device, my_d3d_device_context);
+
+ // Application main loop
+ while (true)
+ {
+ // Beginning of frame: update Renderer + Platform backend, start Dear ImGui frame
+ ImGui_ImplDX11_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // Any application code here
+ ImGui::Text("Hello, world!");
+
+ // End of frame: render Dear ImGui
+ ImGui::Render();
+ ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+
+ // Swap
+ g_pSwapChain->Present(1, 0);
+ }
+
+ // Shutdown
+ ImGui_ImplDX11_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+Please read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
+Please read the comments and instruction at the top of each file.
+Please read FAQ at http://www.dearimgui.org/faq
+
+If you are using of the backend provided here, you can add the backends/imgui_impl_xxxx(.cpp,.h)
+files to your project and use as-in. Each imgui_impl_xxxx.cpp file comes with its own individual
+Changelog, so if you want to update them later it will be easier to catch up with what changed.
+
+
+### Examples Applications
+
+[example_allegro5/](https://github.com/ocornut/imgui/blob/master/examples/example_allegro5/) <BR>
+Allegro 5 example. <BR>
+= main.cpp + imgui_impl_allegro5.cpp
+
+[example_android_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_android_opengl3/) <BR>
+Android + OpenGL3 (ES) example. <BR>
+= main.cpp + imgui_impl_android.cpp + imgui_impl_opengl3.cpp
+
+[example_apple_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_metal/) <BR>
+OSX & iOS + Metal example. <BR>
+= main.m + imgui_impl_osx.mm + imgui_impl_metal.mm <BR>
+It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
+(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
+You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
+
+[example_apple_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_apple_opengl2/) <BR>
+OSX + OpenGL2 example. <BR>
+= main.mm + imgui_impl_osx.mm + imgui_impl_opengl2.cpp <BR>
+(NB: imgui_impl_osx.mm is currently not as feature complete as other platforms backends.
+ You may prefer to use the GLFW Or SDL backends, which will also support Windows and Linux.)
+
+[example_emscripten_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_opengl3/) <BR>
+Emcripten + SDL2 + OpenGL3+/ES2/ES3 example. <BR>
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp <BR>
+Note that other examples based on SDL or GLFW + OpenGL could easily be modified to work with Emscripten.
+We provide this to make the Emscripten differences obvious, and have them not pollute all other examples.
+
+[example_emscripten_wgpu/](https://github.com/ocornut/imgui/blob/master/examples/example_emscripten_wgpu/) <BR>
+Emcripten + GLFW + WebGPU example. <BR>
+= main.cpp + imgui_impl_glfw.cpp + imgui_impl_wgpu.cpp
+
+[example_glfw_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_metal/) <BR>
+GLFW (Mac) + Metal example. <BR>
+= main.mm + imgui_impl_glfw.cpp + imgui_impl_metal.mm
+
+[example_glfw_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl2/) <BR>
+GLFW + OpenGL2 example (legacy, fixed pipeline). <BR>
+= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl2.cpp <BR>
+**DO NOT USE THIS IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** <BR>
+This code is mostly provided as a reference to learn about Dear ImGui integration, because it is shorter.
+If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
+make things more complicated, will require your code to reset many OpenGL attributes to their initial
+state, and might confuse your GPU driver. One star, not recommended.
+
+[example_glfw_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl3/) <BR>
+GLFW (Win32, Mac, Linux) + OpenGL3+/ES2/ES3 example (modern, programmable pipeline). <BR>
+= main.cpp + imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp <BR>
+This uses more modern OpenGL calls and custom shaders. <BR>
+This may actually also work with OpenGL 2.x contexts! <BR>
+Prefer using that if you are using modern OpenGL in your application (anything with shaders).
+
+[example_glfw_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_glfw_vulkan/) <BR>
+GLFW (Win32, Mac, Linux) + Vulkan example. <BR>
+= main.cpp + imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp <BR>
+This is quite long and tedious, because: Vulkan.
+For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
+
+[example_glut_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_glut_opengl2/) <BR>
+GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2 example. <BR>
+= main.cpp + imgui_impl_glut.cpp + imgui_impl_opengl2.cpp <BR>
+Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
+
+[example_marmalade/](https://github.com/ocornut/imgui/blob/master/examples/example_marmalade/) <BR>
+Marmalade example using IwGx. <BR>
+= main.cpp + imgui_impl_marmalade.cpp
+
+[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
+Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
+= main.cpp <BR>
+This is used to quickly test compilation of core imgui files in as many setups as possible.
+Because this application doesn't create a window nor a graphic context, there's no graphics output.
+
+[example_sdl_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_directx11/) <BR>
+SDL2 + DirectX11 example, Windows only. <BR>
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_dx11.cpp <BR>
+This to demonstrate usage of DirectX with SDL.
+
+[example_sdl_metal/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_metal/) <BR>
+SDL2 (Mac) + Metal example. <BR>
+= main.mm + imgui_impl_sdl.cpp + imgui_impl_metal.mm
+
+[example_sdl_opengl2/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_opengl2/) <BR>
+SDL2 (Win32, Mac, Linux etc.) + OpenGL example (legacy, fixed pipeline). <BR>
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl2.cpp <BR>
+**DO NOT USE OPENGL2 CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** <BR>
+This code is mostly provided as a reference to learn about Dear ImGui integration, because it is shorter.
+If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to
+make things more complicated, will require your code to reset many OpenGL attributes to their initial
+state, and might confuse your GPU driver. One star, not recommended.
+
+[example_sdl_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_opengl3/) <BR>
+SDL2 (Win32, Mac, Linux, etc.) + OpenGL3+/ES2/ES3 example. <BR>
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp <BR>
+This uses more modern OpenGL calls and custom shaders. <BR>
+This may actually also work with OpenGL 2.x contexts! <BR>
+
+[example_sdl_sdlrenderer/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_sdlrenderer/) <BR>
+SDL2 (Win32, Mac, Linux, etc.) + SDL_Renderer (most graphics backends are supported underneath) <BR>
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_sdlrenderer.cpp <BR>
+This requires SDL 2.0.17+ (expected to release November 2021) <BR>
+We do not really recommend using SDL_Renderer as it is a rather primitive API.
+
+[example_sdl_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl_vulkan/) <BR>
+SDL2 (Win32, Mac, Linux, etc.) + Vulkan example. <BR>
+= main.cpp + imgui_impl_sdl.cpp + imgui_impl_vulkan.cpp <BR>
+This is quite long and tedious, because: Vulkan. <BR>
+For this example, the main.cpp file exceptionally use helpers function from imgui_impl_vulkan.h/cpp.
+
+[example_win32_directx9/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx9/) <BR>
+DirectX9 example, Windows only. <BR>
+= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx9.cpp
+
+[example_win32_directx10/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx10/) <BR>
+DirectX10 example, Windows only. <BR>
+= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx10.cpp
+
+[example_win32_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx11/) <BR>
+DirectX11 example, Windows only. <BR>
+= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx11.cpp
+
+[example_win32_directx12/](https://github.com/ocornut/imgui/blob/master/examples/example_win32_directx12/) <BR>
+DirectX12 example, Windows only. <BR>
+= main.cpp + imgui_impl_win32.cpp + imgui_impl_dx12.cpp <BR>
+This is quite long and tedious, because: DirectX12.
+
+
+### Miscallaneous
+
+**Building**
+
+Unfortunately nowadays it is still tedious to create and maintain portable build files using external
+libraries (the kind we're using here to create a window and render 3D triangles) without relying on
+third party software and build systems. For most examples here we choose to provide:
+ - Makefiles for Linux/OSX
+ - Batch files for Visual Studio 2008+
+ - A .sln project file for Visual Studio 2012+
+ - Xcode project files for the Apple examples
+Please let us know if they don't work with your setup!
+You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those
+directly with a command-line compiler.
+
+If you are interested in using Cmake to build and links examples, see:
+ https://github.com/ocornut/imgui/pull/1713 and https://github.com/ocornut/imgui/pull/3027
+
+**About mouse cursor latency**
+
+Dear ImGui has no particular extra lag for most behaviors,
+e.g. the value of 'io.MousePos' provided at the time of NewFrame() will result in windows being moved
+to the right spot at the time of EndFrame()/Render(). At 60 FPS your experience should be pleasant.
+
+However, consider that OS mouse cursors are typically drawn through a very specific hardware accelerated
+path and will feel smoother than the majority of contents rendered via regular graphics API (including,
+but not limited to Dear ImGui windows). Because UI rendering and interaction happens on the same plane
+as the mouse, that disconnect may be jarring to particularly sensitive users.
+You may experiment with enabling the io.MouseDrawCursor flag to request Dear ImGui to draw a mouse cursor
+using the regular graphics API, to help you visualize the difference between a "hardware" cursor and a
+regularly rendered software cursor.
+However, rendering a mouse cursor at 60 FPS will feel sluggish so you likely won't want to enable that at
+all times. It might be beneficial for the user experience to switch to a software rendered cursor _only_
+when an interactive drag is in progress.
+
+Note that some setup or GPU drivers are likely to be causing extra display lag depending on their settings.
+If you feel that dragging windows feels laggy and you are not sure what the cause is: try to build a simple
+drawing a flat 2D shape directly under the mouse cursor!
+
diff --git a/Client/ThirdParty/imgui/docs/FAQ.md b/Client/ThirdParty/imgui/docs/FAQ.md
new file mode 100644
index 0000000..009027c
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/FAQ.md
@@ -0,0 +1,676 @@
+# FAQ (Frequenty Asked Questions)
+
+You may link to this document using short form:
+ https://www.dearimgui.org/faq
+or its real address:
+ https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
+or view this file with any Markdown viewer.
+
+
+## Index
+
+| **Q&A: Basics** |
+:---------------------------------------------------------- |
+| [Where is the documentation?](#q-where-is-the-documentation) |
+| [What is this library called?](#q-what-is-this-library-called) |
+| [Which version should I get?](#q-which-version-should-i-get) |
+| **Q&A: Integration** |
+| **[How to get started?](#q-how-to-get-started)** |
+| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)** |
+| [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) |
+| [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display) |
+| [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
+| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
+| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
+| **Q&A: Usage** |
+| **[About the ID Stack system..<br>Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
+| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
+| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) |
+| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |
+| [How can I display custom shapes? (using low-level ImDrawList API)](#q-how-can-i-display-custom-shapes-using-low-level-imdrawlist-api) |
+| **Q&A: Fonts, Text** |
+| [How should I handle DPI in my application?](#q-how-should-i-handle-dpi-in-my-application) |
+| [How can I load a different font than the default?](#q-how-can-i-load-a-different-font-than-the-default) |
+| [How can I easily use icons in my application?](#q-how-can-i-easily-use-icons-in-my-application) |
+| [How can I load multiple fonts?](#q-how-can-i-load-multiple-fonts) |
+| [How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?](#q-how-can-i-display-and-input-non-latin-characters-such-as-chinese-japanese-korean-cyrillic) |
+| **Q&A: Concerns** |
+| [Who uses Dear ImGui?](#q-who-uses-dear-imgui) |
+| [Can you create elaborate/serious tools with Dear ImGui?](#q-can-you-create-elaborateserious-tools-with-dear-imgui) |
+| [Can you reskin the look of Dear ImGui?](#q-can-you-reskin-the-look-of-dear-imgui) |
+| [Why using C++ (as opposed to C)?](#q-why-using-c-as-opposed-to-c) |
+| **Q&A: Community** |
+| [How can I help?](#q-how-can-i-help) |
+
+
+# Q&A: Basics
+
+### Q: Where is the documentation?
+
+**This library is poorly documented at the moment and expects the user to be acquainted with C/C++.**
+- The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
+- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
+- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
+- See documentation: [Backends](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md), [Examples](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md), [Fonts](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
+- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
+- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
+- The [Issues](https://github.com/ocornut/imgui/issues) and [Discussions](https://github.com/ocornut/imgui/discussions) sections can be searched for past questions and issues.
+- Your programming IDE is your friend, find the type or function declaration to find comments associated with it.
+- The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts.
+
+##### [Return to Index](#index)
+
+---
+
+### Q. What is this library called?
+
+**This library is called Dear ImGui**. Please refer to it as Dear ImGui (not ImGui, not IMGUI).
+
+(The library misleadingly started its life in 2014 as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations e.g. Unity uses it own implementation of the IMGUI paradigm. To reduce the ambiguity without affecting existing code bases, I have decided in December 2015 a fully qualified name "Dear ImGui" for this library.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: Which version should I get?
+I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
+
+You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch which includes:
+- [Docking features](https://github.com/ocornut/imgui/issues/2109)
+- [Multi-viewport features](https://github.com/ocornut/imgui/issues/1542)
+
+Many projects are using this branch and it is kept in sync with master regularly.
+
+##### [Return to Index](#index)
+
+----
+
+# Q&A: Integration
+
+### Q: How to get started?
+
+Read [EXAMPLES.md](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md). <BR>
+Read [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md). <BR>
+Read `PROGRAMMER GUIDE` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp). <BR>
+The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
+
+For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions).
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?
+
+You can read the `io.WantCaptureMouse`, `io.WantCaptureKeyboard` and `io.WantTextInput` flags from the ImGuiIO structure.
+- When `io.WantCaptureMouse` is set, you need to discard/hide the mouse inputs from your underlying application.
+- When `io.WantCaptureKeyboard` is set, you need to discard/hide the keyboard inputs from your underlying application.
+- When `io.WantTextInput` is set, you can notify your OS/engine to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS).
+
+Important: you should always pass your mouse/keyboard inputs to Dear ImGui, regardless of the value `io.WantCaptureMouse`/`io.WantCaptureKeyboard`. This is because e.g. we need to detect that you clicked in the void to unfocus its own windows, and other reasons.
+
+```cpp
+void MyLowLevelMouseButtonHandler(int button, bool down)
+{
+ // (1) ALWAYS forward mouse data to ImGui! This is automatic with default backends. With your own backend:
+ ImGuiIO& io = ImGui::GetIO();
+ io.MouseDown[button] = down;
+
+ // (2) ONLY forward mouse data to your underlying app/game.
+ if (!io.WantCaptureMouse)
+ my_game->HandleMouseData(...);
+}
+```
+
+
+**Note:** The `io.WantCaptureMouse` is more correct that any manual attempt to "check if the mouse is hovering a window" (don't do that!). It handle mouse dragging correctly (both dragging that started over your application or over a Dear ImGui window) and handle e.g. popup and modal windows blocking inputs.
+
+**Note:** Those flags are updated by `ImGui::NewFrame()`. However it is generally more correct and easier that you poll flags from the previous frame, then submit your inputs, then call `NewFrame()`. If you attempt to do the opposite (which is generally harder) you are likely going to submit your inputs after `NewFrame()`, and therefore too late.
+
+**Note:** If you are using a touch device, you may find use for an early call to `UpdateHoveredWindowAndCaptureFlags()` to correctly dispatch your initial touch. We will work on better out-of-the-box touch support in the future.
+
+**Note:** Text input widget releases focus on the "KeyDown" event of the Return key, so the subsequent "KeyUp" event that your application receive will typically have `io.WantCaptureKeyboard == false`. Depending on your application logic it may or not be inconvenient to receive that KeyUp event. You might want to track which key-downs were targeted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.)
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I enable keyboard or gamepad controls?
+- The gamepad/keyboard navigation is fairly functional and keeps being improved. The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. Gamepad support is particularly useful to use Dear ImGui on a game console (e.g. PS4, Switch, XB1) without a mouse connected!
+- Keyboard: set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard` to enable.
+- Gamepad: set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad` to enable (with a supporting backend).
+- See [Control Sheets for Gamepads](http://www.dearimgui.org/controls_sheets) (reference PNG/PSD for for PS4, XB1, Switch gamepads).
+- See `USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS` section of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for more details.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)
+- You can share your computer mouse seamlessly with your console/tablet/phone using solutions such as [Synergy](https://symless.com/synergy)
+This is the preferred solution for developer productivity.
+In particular, the [micro-synergy-client repository](https://github.com/symless/micro-synergy-client) has simple
+and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
+to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
+Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
+- Game console users: consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
+- You may also use a third party solution such as [netImgui](https://github.com/sammyfreg/netImgui), [Remote ImGui](https://github.com/JordiRos/remoteimgui) or [imgui-ws](https://github.com/ggerganov/imgui-ws) which sends the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine. See [Wiki](https://github.com/ocornut/imgui/wiki) index for most details.
+- For touch inputs, you can increase the hit box of widgets (via the `style.TouchPadding` setting) to accommodate for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing for screen real-estate and precision.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: I integrated Dear ImGui in my engine and little squares are showing instead of text...
+Your renderer is not using the font texture correctly or it hasn't been uploaded to the GPU.
+- If this happens using the standard backends: A) have you modified the font atlas after `ImGui_ImplXXX_NewFrame()`? B) maybe the texture failed to upload, which could happens if for some reason your texture is too big. Also see [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
+- If this happens with a custom backend: make sure you have uploaded the font texture to the GPU, that all shaders are rendering states are setup properly (e.g. texture is bound). Compare your code to existing backends and use a graphics debugger such as [RenderDoc](https://renderdoc.org) to debug your rendering states.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...
+### Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...
+You are probably mishandling the clipping rectangles in your render function.
+Each draw command needs the triangle rendered using the clipping rectangle provided in the ImDrawCmd structure (`ImDrawCmd->CllipRect`).
+Rectangles provided by Dear ImGui are defined as
+`(x1=left,y1=top,x2=right,y2=bottom)`
+and **NOT** as
+`(x1,y1,width,height)`
+Refer to rendering backends in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder for references of how to handle the `ClipRect` field.
+
+##### [Return to Index](#index)
+
+---
+
+# Q&A: Usage
+
+### Q: About the ID Stack system...
+### Q: Why is my widget not reacting when I click on it?
+### Q: How can I have widgets with an empty label?
+### Q: How can I have multiple widgets with the same label?
+### Q: How can I have multiple windows with the same label?
+
+A primer on labels and the ID Stack...
+
+Dear ImGui internally needs to uniquely identify UI elements.
+Elements that are typically not clickable (such as calls to the Text functions) don't need an ID.
+Interactive widgets (such as calls to Button buttons) need a unique ID.
+
+**Unique ID are used internally to track active widgets and occasionally associate state to widgets.<BR>
+Unique ID are implicitly built from the hash of multiple elements that identify the "path" to the UI element.**
+
+Since Dear ImGui 1.85 you can use `Demo>Tools>Stack Tool` or call `ImGui::ShowStackToolWindow()`. The tool display intermediate values leading to the creation of a unique ID, making things easier to debug and understand.
+
+![Stack tool](https://user-images.githubusercontent.com/8225057/136235657-a0ea5665-dcd1-423f-9be6-dc3f8ced8f12.png)
+
+- Unique ID are often derived from a string label and at minimum scoped within their host window:
+```cpp
+Begin("MyWindow");
+Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "OK")
+Button("Cancel"); // Label = "Cancel", ID = hash of ("MyWindow", "Cancel")
+End();
+```
+- Other elements such as tree nodes, etc. also pushes to the ID stack:
+```cpp
+Begin("MyWindow");
+if (TreeNode("MyTreeNode"))
+{
+ Button("OK"); // Label = "OK", ID = hash of ("MyWindow", "MyTreeNode", "OK")
+ TreePop();
+}
+End();
+```
+- Two items labeled "OK" in different windows or different tree locations won't collide:
+```cpp
+Begin("MyFirstWindow");
+Button("OK"); // Label = "OK", ID = hash of ("MyFirstWindow", "OK")
+End();
+Begin("MyOtherWindow");
+Button("OK"); // Label = "OK", ID = hash of ("MyOtherWindow", "OK")
+End();
+```
+
+- If you have a same ID twice in the same location, you'll have a conflict:
+```cpp
+Begin("MyWindow");
+Button("OK");
+Button("OK"); // ERROR: ID collision with the first button! Interacting with either button will trigger the first one.
+Button(""); // ERROR: ID collision with Begin("MyWindow")!
+End();
+```
+Fear not! this is easy to solve and there are many ways to solve it!
+
+- Solving ID conflict in a simple/local context:
+When passing a label you can optionally specify extra ID information within string itself.
+Use "##" to pass a complement to the ID that won't be visible to the end-user.
+This helps solving the simple collision cases when you know e.g. at compilation time which items
+are going to be created:
+```cpp
+Begin("MyWindow");
+Button("Play"); // Label = "Play", ID = hash of ("MyWindow", "Play")
+Button("Play##foo1"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo1") // Different from other buttons
+Button("Play##foo2"); // Label = "Play", ID = hash of ("MyWindow", "Play##foo2") // Different from other buttons
+Button("##foo"); // Label = "", ID = hash of ("MyWindow", "##foo") // Different from window
+End();
+```
+- If you want to completely hide the label, but still need an ID:
+```cpp
+Checkbox("##On", &b); // Label = "", ID = hash of (..., "##On") // No visible label, just a checkbox!
+```
+- Occasionally/rarely you might want change a label while preserving a constant ID. This allows
+you to animate labels. For example you may want to include varying information in a window title bar,
+but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID:
+```cpp
+Button("Hello###ID"); // Label = "Hello", ID = hash of (..., "###ID")
+Button("World###ID"); // Label = "World", ID = hash of (..., "###ID") // Same ID, different label
+
+sprintf(buf, "My game (%f FPS)###MyGame", fps);
+Begin(buf); // Variable title, ID = hash of "MyGame"
+```
+- Solving ID conflict in a more general manner:
+Use `PushID()` / `PopID()` to create scopes and manipulate the ID stack, as to avoid ID conflicts
+within the same window. This is the most convenient way of distinguishing ID when iterating and
+creating many UI elements programmatically.
+You can push a pointer, a string or an integer value into the ID stack.
+Remember that ID are formed from the concatenation of _everything_ pushed into the ID stack.
+At each level of the stack we store the seed used for items at this level of the ID stack.
+```cpp
+Begin("Window");
+for (int i = 0; i < 100; i++)
+{
+ PushID(i); // Push i to the id tack
+ Button("Click"); // Label = "Click", ID = hash of ("Window", i, "Click")
+ PopID();
+}
+for (int i = 0; i < 100; i++)
+{
+ MyObject* obj = Objects[i];
+ PushID(obj);
+ Button("Click"); // Label = "Click", ID = hash of ("Window", obj pointer, "Click")
+ PopID();
+}
+for (int i = 0; i < 100; i++)
+{
+ MyObject* obj = Objects[i];
+ PushID(obj->Name);
+ Button("Click"); // Label = "Click", ID = hash of ("Window", obj->Name, "Click")
+ PopID();
+}
+End();
+```
+- You can stack multiple prefixes into the ID stack:
+```cpp
+Button("Click"); // Label = "Click", ID = hash of (..., "Click")
+PushID("node");
+ Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
+ PushID(my_ptr);
+ Button("Click"); // Label = "Click", ID = hash of (..., "node", my_ptr, "Click")
+ PopID();
+PopID();
+```
+- Tree nodes implicitly creates a scope for you by calling `PushID()`:
+```cpp
+Button("Click"); // Label = "Click", ID = hash of (..., "Click")
+if (TreeNode("node")) // <-- this function call will do a PushID() for you (unless instructed not to, with a special flag)
+{
+ Button("Click"); // Label = "Click", ID = hash of (..., "node", "Click")
+ TreePop();
+}
+```
+
+When working with trees, ID are used to preserve the open/close state of each tree node.
+Depending on your use cases you may want to use strings, indices or pointers as ID.
+- e.g. when following a single pointer that may change over time, using a static string as ID
+will preserve your node open/closed state when the targeted object change.
+- e.g. when displaying a list of objects, using indices or pointers as ID will preserve the
+node open/closed state differently. See what makes more sense in your situation!
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I display an image? What is ImTextureID, how does it work?
+
+Short explanation:
+- Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki).
+- You may use functions such as `ImGui::Image()`, `ImGui::ImageButton()` or lower-level `ImDrawList::AddImage()` to emit draw calls that will use your own textures.
+- Actual textures are identified in a way that is up to the user/engine. Those identifiers are stored and passed as ImTextureID (void*) value.
+- Loading image files from the disk and turning them into a texture is not within the scope of Dear ImGui (for a good reason).
+
+**Please read documentations or tutorials on your graphics API to understand how to display textures on the screen before moving onward.**
+
+Long explanation:
+- Dear ImGui's job is to create "meshes", defined in a renderer-agnostic format made of draw commands and vertices. At the end of the frame those meshes (ImDrawList) will be displayed by your rendering function. They are made up of textured polygons and the code to render them is generally fairly short (a few dozen lines). In the examples/ folder we provide functions for popular graphics API (OpenGL, DirectX, etc.).
+- Each rendering function decides on a data type to represent "textures". The concept of what is a "texture" is entirely tied to your underlying engine/graphics API.
+ We carry the information to identify a "texture" in the ImTextureID type.
+ImTextureID is nothing more that a void*, aka 4/8 bytes worth of data: just enough to store 1 pointer or 1 integer of your choice.
+Dear ImGui doesn't know or understand what you are storing in ImTextureID, it merely pass ImTextureID values until they reach your rendering function.
+- In the [examples/](https://github.com/ocornut/imgui/tree/master/examples) backends, for each graphics API we decided on a type that is likely to be a good representation for specifying an image from the end-user perspective. This is what the _examples_ rendering functions are using:
+```cpp
+OpenGL:
+- ImTextureID = GLuint
+- See ImGui_ImplOpenGL3_RenderDrawData() function in imgui_impl_opengl3.cpp
+```
+```cpp
+DirectX9:
+- ImTextureID = LPDIRECT3DTEXTURE9
+- See ImGui_ImplDX9_RenderDrawData() function in imgui_impl_dx9.cpp
+```
+```cpp
+DirectX11:
+- ImTextureID = ID3D11ShaderResourceView*
+- See ImGui_ImplDX11_RenderDrawData() function in imgui_impl_dx11.cpp
+```
+```cpp
+DirectX12:
+- ImTextureID = D3D12_GPU_DESCRIPTOR_HANDLE
+- See ImGui_ImplDX12_RenderDrawData() function in imgui_impl_dx12.cpp
+```
+For example, in the OpenGL example backend we store raw OpenGL texture identifier (GLuint) inside ImTextureID.
+Whereas in the DirectX11 example backend we store a pointer to ID3D11ShaderResourceView inside ImTextureID, which is a higher-level structure tying together both the texture and information about its format and how to read it.
+
+- If you have a custom engine built over e.g. OpenGL, instead of passing GLuint around you may decide to use a high-level data type to carry information about the texture as well as how to display it (shaders, etc.). The decision of what to use as ImTextureID can always be made better knowing how your codebase is designed. If your engine has high-level data types for "textures" and "material" then you may want to use them.
+If you are starting with OpenGL or DirectX or Vulkan and haven't built much of a rendering engine over them, keeping the default ImTextureID representation suggested by the example backends is probably the best choice.
+(Advanced users may also decide to keep a low-level type in ImTextureID, and use ImDrawList callback and pass information to their renderer)
+
+User code may do:
+```cpp
+// Cast our texture type to ImTextureID / void*
+MyTexture* texture = g_CoffeeTableTexture;
+ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
+```
+The renderer function called after ImGui::Render() will receive that same value that the user code passed:
+```cpp
+// Cast ImTextureID / void* stored in the draw command as our texture type
+MyTexture* texture = (MyTexture*)pcmd->GetTexID();
+MyEngineBindTexture2D(texture);
+```
+Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
+This is by design and is actually a good thing, because it means your code has full control over your data types and how you display them.
+If you want to display an image file (e.g. PNG file) into the screen, please refer to documentation and tutorials for the graphics API you are using.
+
+Refer to [Image Loading and Displaying Examples](https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples) on the [Wiki](https://github.com/ocornut/imgui/wiki) to find simplified examples for loading textures with OpenGL, DirectX9 and DirectX11.
+
+C/C++ tip: a void* is pointer-sized storage. You may safely store any pointer or integer into it by casting your value to ImTextureID / void*, and vice-versa.
+Because both end-points (user code and rendering function) are under your control, you know exactly what is stored inside the ImTextureID / void*.
+Examples:
+```cpp
+GLuint my_tex = XXX;
+void* my_void_ptr;
+my_void_ptr = (void*)(intptr_t)my_tex; // cast a GLuint into a void* (we don't take its address! we literally store the value inside the pointer)
+my_tex = (GLuint)(intptr_t)my_void_ptr; // cast a void* into a GLuint
+
+ID3D11ShaderResourceView* my_dx11_srv = XXX;
+void* my_void_ptr;
+my_void_ptr = (void*)my_dx11_srv; // cast a ID3D11ShaderResourceView* into an opaque void*
+my_dx11_srv = (ID3D11ShaderResourceView*)my_void_ptr; // cast a void* into a ID3D11ShaderResourceView*
+```
+Finally, you may call `ImGui::ShowMetricsWindow()` to explore/visualize/understand how the ImDrawList are generated.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I use my own math types instead of ImVec2/ImVec4?
+
+You can edit [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) and setup the `IM_VEC2_CLASS_EXTRA`/`IM_VEC4_CLASS_EXTRA` macros to add implicit type conversions.
+This way you'll be able to use your own types everywhere, e.g. passing `MyVector2` or `glm::vec2` to ImGui functions instead of `ImVec2`.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I interact with standard C++ types (such as std::string and std::vector)?
+- Being highly portable (backends/bindings for several languages, frameworks, programming style, obscure or older platforms/compilers), and aiming for compatibility & performance suitable for every modern real-time game engines, dear imgui does not use any of std C++ types. We use raw types (e.g. char* instead of std::string) because they adapt to more use cases.
+- To use ImGui::InputText() with a std::string or any resizable string class, see [misc/cpp/imgui_stdlib.h](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.h).
+- To use combo boxes and list boxes with `std::vector` or any other data structure: the `BeginCombo()/EndCombo()` API
+lets you iterate and submit items yourself, so does the `ListBoxHeader()/ListBoxFooter()` API.
+Prefer using them over the old and awkward `Combo()/ListBox()` api.
+- Generally for most high-level types you should be able to access the underlying data type.
+You may write your own one-liner wrappers to facilitate user code (tip: add new functions in ImGui:: namespace from your code).
+- Dear ImGui applications often need to make intensive use of strings. It is expected that many of the strings you will pass
+to the API are raw literals (free in C/C++) or allocated in a manner that won't incur a large cost on your application.
+Please bear in mind that using `std::string` on applications with large amount of UI may incur unsatisfactory performances.
+Modern implementations of `std::string` often include small-string optimization (which is often a local buffer) but those
+are not configurable and not the same across implementations.
+- If you are finding your UI traversal cost to be too large, make sure your string usage is not leading to excessive amount
+of heap allocations. Consider using literals, statically sized buffers and your own helper functions. A common pattern
+is that you will need to build lots of strings on the fly, and their maximum length can be easily be scoped ahead.
+One possible implementation of a helper to facilitate printf-style building of strings: https://github.com/ocornut/Str
+This is a small helper where you can instance strings with configurable local buffers length. Many game engines will
+provide similar or better string helpers.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I display custom shapes? (using low-level ImDrawList API)
+
+- You can use the low-level `ImDrawList` api to render shapes within a window.
+```cpp
+ImGui::Begin("My shapes");
+
+ImDrawList* draw_list = ImGui::GetWindowDrawList();
+
+// Get the current ImGui cursor position
+ImVec2 p = ImGui::GetCursorScreenPos();
+
+// Draw a red circle
+draw_list->AddCircleFilled(ImVec2(p.x + 50, p.y + 50), 30.0f, IM_COL32(255, 0, 0, 255), 16);
+
+// Draw a 3 pixel thick yellow line
+draw_list->AddLine(ImVec2(p.x, p.y), ImVec2(p.x + 100.0f, p.y + 100.0f), IM_COL32(255, 255, 0, 255), 3.0f);
+
+// Advance the ImGui cursor to claim space in the window (otherwise the window will appears small and needs to be resized)
+ImGui::Dummy(ImVec2(200, 200));
+
+ImGui::End();
+```
+![ImDrawList usage](https://raw.githubusercontent.com/wiki/ocornut/imgui/tutorials/CustomRendering01.png)
+
+- Refer to "Demo > Examples > Custom Rendering" in the demo window and read the code of `ShowExampleAppCustomRendering()` in `imgui_demo.cpp` from more examples.
+- To generate colors: you can use the macro `IM_COL32(255,255,255,255)` to generate them at compile time, or use `ImGui::GetColorU32(IM_COL32(255,255,255,255))` or `ImGui::GetColorU32(ImVec4(1.0f,1.0f,1.0f,1.0f))` to generate a color that is multiplied by the current value of `style.Alpha`.
+- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui_internal.h"` to use the internally defined math operators, but instead prefer using your own math library and set it up in `imconfig.h`.
+- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other dear imgui windows (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated to a dear imgui window.
+- You can also create your own empty window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via `GetWindowDrawList()` and draw to it in any way you like.
+- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing `ImDrawListSharedData`, and then call your renderer function with your own ImDrawList or ImDrawData data.
+- Looking for fun? The [ImDrawList coding party 2020](https://github.com/ocornut/imgui/issues/3606) thread is full of "don't do this at home" extreme uses of the ImDrawList API.
+
+##### [Return to Index](#index)
+
+---
+
+# Q&A: Fonts, Text
+
+### Q: How should I handle DPI in my application?
+
+The short answer is: obtain the desired DPI scale, load your fonts resized with that scale (always round down fonts size to nearest integer), and scale your Style structure accordingly using `style.ScaleAllSizes()`.
+
+Your application may want to detect DPI change and reload the fonts and reset style between frames.
+
+Your ui code should avoid using hardcoded constants for size and positioning. Prefer to express values as multiple of reference values such as `ImGui::GetFontSize()` or `ImGui::GetFrameHeight()`. So e.g. instead of seeing a hardcoded height of 500 for a given item/window, you may want to use `30*ImGui::GetFontSize()` instead.
+
+Down the line Dear ImGui will provide a variety of standardized reference values to facilitate using this.
+
+Applications in the `examples/` folder are not DPI aware partly because they are unable to load a custom font from the file-system (may change that in the future).
+
+The reason DPI is not auto-magically solved in stock examples is that we don't yet have a satisfying solution for the "multi-dpi" problem (using the `docking` branch: when multiple viewport windows are over multiple monitors using different DPI scale). The current way to handle this on the application side is:
+- Create and maintain one font atlas per active DPI scale (e.g. by iterating `platform_io.Monitors[]` before `NewFrame()`).
+- Hook `platform_io.OnChangedViewport()` to detect when a `Begin()` call makes a Dear ImGui window change monitor (and therefore DPI).
+- In the hook: swap atlas, swap style with correctly sized one, remap the current font from one atlas to the other (may need to maintain a remapping table of your fonts at variying DPI scale).
+
+This approach is relatively easy and functional but come with two issues:
+- It's not possibly to reliably size or position a window ahead of `Begin()` without knowing on which monitor it'll land.
+- Style override may be lost during the `Begin()` call crossing monitor boundaries. You may need to do some custom scaling mumbo-jumbo if you want your `OnChangedViewport()` handler to preserve style overrides.
+
+Please note that if you are not using multi-viewports with multi-monitors using different DPI scale, you can ignore all of this and use the simpler technique recommended at the top.
+
+### Q: How can I load a different font than the default?
+Use the font atlas to load the TTF/OTF file you want:
+
+```cpp
+ImGuiIO& io = ImGui::GetIO();
+io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
+io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
+```
+
+Default is ProggyClean.ttf, monospace, rendered at size 13, embedded in dear imgui's source code.
+
+(Tip: monospace fonts are convenient because they allow to facilitate horizontal alignment directly at the string level.)
+
+(Read the [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) file for more details about font loading.)
+
+New programmers: remember that in C/C++ and most programming languages if you want to use a
+backslash \ within a string literal, you need to write it double backslash "\\":
+
+```cpp
+io.Fonts->AddFontFromFileTTF("MyFolder\MyFont.ttf", size); // WRONG (you are escaping the M here!)
+io.Fonts->AddFontFromFileTTF("MyFolder\\MyFont.ttf", size; // CORRECT (Windows only)
+io.Fonts->AddFontFromFileTTF("MyFolder/MyFont.ttf", size); // ALSO CORRECT
+```
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I easily use icons in my application?
+The most convenient and practical way is to merge an icon font such as FontAwesome inside you
+main font. Then you can refer to icons within your strings.
+You may want to see `ImFontConfig::GlyphMinAdvanceX` to make your icon look monospace to facilitate alignment.
+(Read the [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) file for more details about icons font loading.)
+With some extra effort, you may use colorful icon by registering custom rectangle space inside the font atlas,
+and copying your own graphics data into it. See docs/FONTS.md about using the AddCustomRectFontGlyph API.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I load multiple fonts?
+Use the font atlas to pack them into a single texture:
+(Read the [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md) file and the code in ImFontAtlas for more details.)
+
+```cpp
+ImGuiIO& io = ImGui::GetIO();
+ImFont* font0 = io.Fonts->AddFontDefault();
+ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
+ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
+io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
+// the first loaded font gets used by default
+// use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime
+
+// Options
+ImFontConfig config;
+config.OversampleH = 2;
+config.OversampleV = 1;
+config.GlyphOffset.y -= 1.0f; // Move everything by 1 pixels up
+config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
+io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, &config);
+
+// Combine multiple fonts into one (e.g. for icon fonts)
+static ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
+ImFontConfig config;
+config.MergeMode = true;
+io.Fonts->AddFontDefault();
+io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
+io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs
+```
+
+##### [Return to Index](#index)
+
+---
+
+### Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
+When loading a font, pass custom Unicode ranges to specify the glyphs to load.
+
+```cpp
+// Add default Japanese ranges
+io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
+
+// Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
+ImVector<ImWchar> ranges;
+ImFontGlyphRangesBuilder builder;
+builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
+builder.AddChar(0x7262); // Add a specific character
+builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
+builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
+io.Fonts->AddFontFromFileTTF("myfontfile.ttf", 16.0f, NULL, ranges.Data);
+```
+
+All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8
+by using the u8"hello" syntax. Specifying literal in your source code using a local code page
+(such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
+Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
+
+Text input: it is up to your application to pass the right character code by calling `io.AddInputCharacter()`.
+The applications in examples/ are doing that.
+Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode).
+You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state.
+Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
+the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly.
+
+##### [Return to Index](#index)
+
+---
+
+# Q&A: Concerns
+
+### Q: Who uses Dear ImGui?
+
+You may take a look at:
+
+- [Quotes](https://github.com/ocornut/imgui/wiki/Quotes)
+- [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui)
+- [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors)
+- [Gallery](https://github.com/ocornut/imgui/issues/4451)
+
+##### [Return to Index](#index)
+
+---
+
+### Q: Can you create elaborate/serious tools with Dear ImGui?
+
+Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library.
+
+Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might require you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful.
+
+Dear ImGui is built to be efficient and scalable toward the needs for AAA-quality applications running all day. The IMGUI paradigm offers different opportunities for optimization that the more typical RMGUI paradigm.
+
+##### [Return to Index](#index)
+
+---
+
+### Q: Can you reskin the look of Dear ImGui?
+
+Somehow. You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimized to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Dear ImGui is NOT designed to create user interface for games, although with ingenious use of the low-level API you can do it.
+
+A reasonably skinned application may look like (screenshot from [#2529](https://github.com/ocornut/imgui/issues/2529#issuecomment-524281119))
+![minipars](https://user-images.githubusercontent.com/314805/63589441-d9794f00-c5b1-11e9-8d96-cfc1b93702f7.png)
+
+##### [Return to Index](#index)
+
+---
+
+### Q: Why using C++ (as opposed to C)?
+
+Dear ImGui takes advantage of a few C++ languages features for convenience but nothing anywhere Boost insanity/quagmire. Dear ImGui does NOT require C++11 so it can be used with most old C++ compilers. Dear ImGui doesn't use any C++ header file. Language-wise, function overloading and default parameters are used to make the API easier to use and code more terse. Doing so I believe the API is sitting on a sweet spot and giving up on those features would make the API more cumbersome. Other features such as namespace, constructors and templates (in the case of the ImVector<> class) are also relied on as a convenience.
+
+There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/cimgui/cimgui) by Sonoro1234 and Stephan Dilly. It is designed for creating bindings to other languages. If possible, I would suggest using your target language functionalities to try replicating the function overloading and default parameters used in C++ else the API may be harder to use. Also see [Bindings](https://github.com/ocornut/imgui/wiki/Bindings) for various third-party bindings.
+
+##### [Return to Index](#index)
+
+---
+
+# Q&A: Community
+
+### Q: How can I help?
+- Businesses: please reach out to `contact AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people working on this project.
+- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
+- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help!
+- Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
+You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/4451). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps the library grow credibility, and help other teams and programmers with taking decisions.
+- If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues or sometimes incomplete PR.
+
+##### [Return to Index](#index)
+
diff --git a/Client/ThirdParty/imgui/docs/FONTS.md b/Client/ThirdParty/imgui/docs/FONTS.md
new file mode 100644
index 0000000..09c1cb9
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/FONTS.md
@@ -0,0 +1,397 @@
+_(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/FONTS.md or view this file with any Markdown viewer)_
+
+## Dear ImGui: Using Fonts
+
+The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer),
+a 13 pixels high, pixel-perfect font used by default. We embed it in the source code so you can use Dear ImGui without any file system access. ProggyClean does not scale smoothly, therefore it is recommended that you load your own file when using Dear ImGui in an application aiming to look nice and wanting to support multiple resolutions.
+
+You may also load external .TTF/.OTF files.
+In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) folder you can find a few suggested fonts, provided as a convenience.
+
+**Also read the FAQ:** https://www.dearimgui.org/faq (there is a Fonts section!)
+
+## Index
+- [Readme First](#readme-first)
+- [How should I handle DPI in my application?](#how-should-i-handle-dpi-in-my-application)
+- [Fonts Loading Instructions](#font-loading-instructions)
+- [Using Icon Fonts](#using-icon-fonts)
+- [Using FreeType Rasterizer (imgui_freetype)](#using-freetype-rasterizer-imgui_freetype)
+- [Using Colorful Glyphs/Emojis](#using-colorful-glyphsemojis)
+- [Using Custom Glyph Ranges](#using-custom-glyph-ranges)
+- [Using Custom Colorful Icons](#using-custom-colorful-icons)
+- [Using Font Data Embedded In Source Code](#using-font-data-embedded-in-source-code)
+- [About filenames](#about-filenames)
+- [Credits/Licenses For Fonts Included In Repository](#creditslicenses-for-fonts-included-in-repository)
+- [Font Links](#font-links)
+
+---------------------------------------
+ ## Readme First
+
+- You can use the `Metrics/Debugger` window (available in `Demo>Tools`) to browse your fonts and understand what's going on if you have an issue. You can also reach it in `Demo->Tools->Style Editor->Fonts`. The same information are also available in the Style Editor under Fonts.
+
+![imgui_capture_0008](https://user-images.githubusercontent.com/8225057/135429892-0e41ef8d-33c5-4991-bcf6-f997a0bcfd6b.png)
+
+- All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of `io.Fonts->GetTexDataAsAlpha8()`, `io.Fonts->GetTexDataAsRGBA32()` or `io.Fonts->Build()` will build the atlas.
+
+- Make sure your font ranges data are persistent (available during the calls to `GetTexDataAsAlpha8()`/`GetTexDataAsRGBA32()/`Build()`.
+
+- Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.:
+```cpp
+u8"hello"
+u8"こんにちは" // this will be encoded as UTF-8
+```
+
+##### [Return to Index](#index)
+
+## How should I handle DPI in my application?
+
+See [FAQ entry](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-should-i-handle-dpi-in-my-application).
+
+##### [Return to Index](#index)
+
+
+## Font Loading Instructions
+
+**Load default font:**
+```cpp
+ImGuiIO& io = ImGui::GetIO();
+io.Fonts->AddFontDefault();
+```
+
+
+**Load .TTF/.OTF file with:**
+```cpp
+ImGuiIO& io = ImGui::GetIO();
+io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
+```
+If you get an assert stating "Could not load font file!", your font filename is likely incorrect. Read "[About filenames](#about-filenames)" carefully.
+
+
+**Load multiple fonts:**
+```cpp
+// Init
+ImGuiIO& io = ImGui::GetIO();
+ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
+ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf", size_pixels);
+```
+```cpp
+// In application loop: select font at runtime
+ImGui::Text("Hello"); // use the default font (which is the first loaded font)
+ImGui::PushFont(font2);
+ImGui::Text("Hello with another font");
+ImGui::PopFont();
+```
+
+
+**For advanced options create a ImFontConfig structure and pass it to the AddFont() function (it will be copied internally):**
+```cpp
+ImFontConfig config;
+config.OversampleH = 2;
+config.OversampleV = 1;
+config.GlyphExtraSpacing.x = 1.0f;
+ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
+```
+
+
+**Combine multiple fonts into one:**
+```cpp
+// Load a first font
+ImFont* font = io.Fonts->AddFontDefault();
+
+// Add character ranges and merge into the previous font
+// The ranges array is not copied by the AddFont* functions and is used lazily
+// so ensure it is available at the time of building or calling GetTexDataAsRGBA32().
+static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // Will not be copied by AddFont* so keep in scope.
+ImFontConfig config;
+config.MergeMode = true;
+io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 18.0f, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge into first font
+io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 18.0f, &config, icons_ranges); // Merge into first font
+io.Fonts->Build();
+```
+
+**Add a fourth parameter to bake specific font ranges only:**
+
+```cpp
+// Basic Latin, Extended Latin
+io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault());
+
+// Default + Selection of 2500 Ideographs used by Simplified Chinese
+io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
+
+// Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
+io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
+```
+See [Using Custom Glyph Ranges](#using-custom-glyph-ranges) section to create your own ranges.
+
+
+**Example loading and using a Japanese font:**
+
+```cpp
+ImGuiIO& io = ImGui::GetIO();
+io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 20.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+```
+```cpp
+ImGui::Text(u8"こんにちは!テスト %d", 123);
+if (ImGui::Button(u8"ロード"))
+{
+ // do stuff
+}
+ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
+ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
+```
+
+![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02_jp.png)
+<br>_(settings: Dark style (left), Light style (right) / Font: NotoSansCJKjp-Medium, 20px / Rounding: 5)_
+
+**Font Atlas too large?**
+
+- If you have very large number of glyphs or multiple fonts, the texture may become too big for your graphics API. The typical result of failing to upload a texture is if every glyphs appears as white rectangles.
+- Mind the fact that some graphics drivers have texture size limitation. If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours.
+
+Some solutions:
+
+1. Reduce glyphs ranges by calculating them from source localization data.
+ You can use the `ImFontGlyphRangesBuilder` for this purpose and rebuilding your atlas between frames when new characters are needed. This will be the biggest win!
+2. You may reduce oversampling, e.g. `font_config.OversampleH = 2`, this will largely reduce your texture size.
+ Note that while OversampleH = 2 looks visibly very close to 3 in most situations, with OversampleH = 1 the quality drop will be noticeable.
+3. Set `io.Fonts.TexDesiredWidth` to specify a texture width to minimize texture height (see comment in `ImFontAtlas::Build()` function).
+4. Set `io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;` to disable rounding the texture height to the next power of two.
+5. Read about oversampling [here](https://github.com/nothings/stb/blob/master/tests/oversample).
+6. To support the extended range of unicode beyond 0xFFFF (e.g. emoticons, dingbats, symbols, shapes, ancient languages, etc...) add `#define IMGUI_USE_WCHAR32`in your `imconfig.h`.
+
+##### [Return to Index](#index)
+
+## Using Icon Fonts
+
+Using an icon font (such as [FontAwesome](http://fontawesome.io) or [OpenFontIcons](https://github.com/traverseda/OpenFontIcons)) is an easy and practical way to use icons in your Dear ImGui application.
+A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without having to change fonts back and forth.
+
+To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut: https://github.com/juliettef/IconFontCppHeaders.
+
+So you can use `ICON_FA_SEARCH` as a string that will render as a "Search" icon.
+
+Example Setup:
+```cpp
+// Merge icons into default tool font
+#include "IconsFontAwesome.h"
+ImGuiIO& io = ImGui::GetIO();
+io.Fonts->AddFontDefault();
+
+ImFontConfig config;
+config.MergeMode = true;
+config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
+static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
+io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);
+```
+Example Usage:
+```cpp
+// Usage, e.g.
+ImGui::Text("%s among %d items", ICON_FA_SEARCH, count);
+ImGui::Button(ICON_FA_SEARCH " Search");
+// C string _literals_ can be concatenated at compilation time, e.g. "hello" " world"
+// ICON_FA_SEARCH is defined as a string literal so this is the same as "A" "B" becoming "AB"
+```
+See Links below for other icons fonts and related tools.
+
+Here's an application using icons ("Avoyd", https://www.avoyd.com):
+![avoyd](https://user-images.githubusercontent.com/8225057/81696852-c15d9e80-9464-11ea-9cab-2a4d4fc84396.jpg)
+
+##### [Return to Index](#index)
+
+## Using FreeType Rasterizer (imgui_freetype)
+
+- Dear ImGui uses imstb\_truetype.h to rasterize fonts (with optional oversampling). This technique and its implementation are not ideal for fonts rendered at small sizes, which may appear a little blurry or hard to read.
+- There is an implementation of the ImFontAtlas builder using FreeType that you can use in the [misc/freetype/](https://github.com/ocornut/imgui/tree/master/misc/freetype) folder.
+- FreeType supports auto-hinting which tends to improve the readability of small fonts.
+- Read documentation in the [misc/freetype/](https://github.com/ocornut/imgui/tree/master/misc/freetype) folder.
+- Correct sRGB space blending will have an important effect on your font rendering quality.
+
+##### [Return to Index](#index)
+
+## Using Colorful Glyphs/Emojis
+
+- Rendering of colored emojis is only supported by imgui_freetype with FreeType 2.10+.
+- You will need to load fonts with the `ImGuiFreeTypeBuilderFlags_LoadColor` flag.
+- Emojis are frequently encoded in upper Unicode layers (character codes >0x10000) and will need dear imgui compiled with `IMGUI_USE_WCHAR32`.
+- Not all types of color fonts are supported by FreeType at the moment.
+- Stateful Unicode features such as skin tone modifiers are not supported by the text renderer.
+
+![colored glyphs](https://user-images.githubusercontent.com/8225057/106171241-9dc4ba80-6191-11eb-8a69-ca1467b206d1.png)
+
+```cpp
+io.Fonts->AddFontFromFileTTF("../../../imgui_dev/data/fonts/NotoSans-Regular.ttf", 16.0f);
+static ImWchar ranges[] = { 0x1, 0x1FFFF, 0 };
+static ImFontConfig cfg;
+cfg.OversampleH = cfg.OversampleV = 1;
+cfg.MergeMode = true;
+cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_LoadColor;
+io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\seguiemj.ttf", 16.0f, &cfg, ranges);
+```
+
+##### [Return to Index](#index)
+
+## Using Custom Glyph Ranges
+
+You can use the `ImFontGlyphRangesBuilder` helper to create glyph ranges based on text input. For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs.
+```cpp
+ImVector<ImWchar> ranges;
+ImFontGlyphRangesBuilder builder;
+builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
+builder.AddChar(0x7262); // Add a specific character
+builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
+builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
+
+io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
+io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted.
+```
+
+##### [Return to Index](#index)
+
+## Using Custom Colorful Icons
+
+As an alternative to rendering colorful glyphs using imgui_freetype with `ImGuiFreeTypeBuilderFlags_LoadColor`, you may allocate your own space in the texture atlas and write yourself into it. **(This is a BETA api, use if you are familiar with dear imgui and with your rendering backend)**
+
+- You can use the `ImFontAtlas::AddCustomRect()` and `ImFontAtlas::AddCustomRectFontGlyph()` api to register rectangles that will be packed into the font atlas texture. Register them before building the atlas, then call Build()`.
+- You can then use `ImFontAtlas::GetCustomRectByIndex(int)` to query the position/size of your rectangle within the texture, and blit/copy any graphics data of your choice into those rectangles.
+- This API is beta because it is likely to change in order to support multi-dpi (multiple viewports on multiple monitors with varying DPI scale).
+
+#### Pseudo-code:
+```cpp
+// Add font, then register two custom 13x13 rectangles mapped to glyph 'a' and 'b' of this font
+ImFont* font = io.Fonts->AddFontDefault();
+int rect_ids[2];
+rect_ids[0] = io.Fonts->AddCustomRectFontGlyph(font, 'a', 13, 13, 13+1);
+rect_ids[1] = io.Fonts->AddCustomRectFontGlyph(font, 'b', 13, 13, 13+1);
+
+// Build atlas
+io.Fonts->Build();
+
+// Retrieve texture in RGBA format
+unsigned char* tex_pixels = NULL;
+int tex_width, tex_height;
+io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_width, &tex_height);
+
+for (int rect_n = 0; rect_n < IM_ARRAYSIZE(rect_ids); rect_n++)
+{
+ int rect_id = rects_ids[rect_n];
+ if (const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(rect_id))
+ {
+ // Fill the custom rectangle with red pixels (in reality you would draw/copy your bitmap data here!)
+ for (int y = 0; y < rect->Height; y++)
+ {
+ ImU32* p = (ImU32*)tex_pixels + (rect->Y + y) * tex_width + (rect->X);
+ for (int x = rect->Width; x > 0; x--)
+ *p++ = IM_COL32(255, 0, 0, 255);
+ }
+ }
+}
+```
+
+##### [Return to Index](#index)
+
+## Using Font Data Embedded In Source Code
+
+- Compile and use [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp) to create a compressed C style array that you can embed in source code.
+- See the documentation in [binary_to_compressed_c.cpp](https://github.com/ocornut/imgui/blob/master/misc/fonts/binary_to_compressed_c.cpp) for instruction on how to use the tool.
+- You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see [README](https://github.com/ocornut/imgui/blob/master/docs/README.md)).
+- The tool can optionally output Base85 encoding to reduce the size of _source code_ but the read-only arrays in the actual binary will be about 20% bigger.
+
+Then load the font with:
+```cpp
+ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
+```
+or
+```cpp
+ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
+```
+
+##### [Return to Index](#index)
+
+## About filenames
+
+**Please note that many new C/C++ users have issues their files _because the filename they provide is wrong_.**
+
+Two things to watch for:
+- Make sure your IDE/debugger settings starts your executable from the right working directory. In Visual Studio you can change your working directory in project `Properties > General > Debugging > Working Directory`. People assume that their execution will start from the root folder of the project, where by default it oftens start from the folder where object or executable files are stored.
+```cpp
+// Relative filename depends on your Working Directory when running your program!
+io.Fonts->AddFontFromFileTTF("MyImage01.jpg", ...);
+
+// Load from the parent folder of your Working Directory
+io.Fonts->AddFontFromFileTTF("../MyImage01.jpg", ...);
+```
+- In C/C++ and most programming languages if you want to use a backslash `\` within a string literal, you need to write it double backslash `\\`. At it happens, Windows uses backslashes as a path separator, so be mindful.
+```cpp
+io.Fonts->AddFontFromFileTTF("MyFiles\MyImage01.jpg", ...); // This is INCORRECT!!
+io.Fonts->AddFontFromFileTTF("MyFiles\\MyImage01.jpg", ...); // This is CORRECT
+```
+In some situations, you may also use `/` path separator under Windows.
+
+##### [Return to Index](#index)
+
+## Credits/Licenses For Fonts Included In Repository
+
+Some fonts files are available in the `misc/fonts/` folder:
+
+**Roboto-Medium.ttf**, by Christian Robetson
+<br>Apache License 2.0
+<br>https://fonts.google.com/specimen/Roboto
+
+**Cousine-Regular.ttf**, by Steve Matteson
+<br>Digitized data copyright (c) 2010 Google Corporation.
+<br>Licensed under the SIL Open Font License, Version 1.1
+<br>https://fonts.google.com/specimen/Cousine
+
+**DroidSans.ttf**, by Steve Matteson
+<br>Apache License 2.0
+<br>https://www.fontsquirrel.com/fonts/droid-sans
+
+**ProggyClean.ttf**, by Tristan Grimmer
+<br>MIT License
+<br>(recommended loading setting: Size = 13.0, GlyphOffset.y = +1)
+<br>http://www.proggyfonts.net/
+
+**ProggyTiny.ttf**, by Tristan Grimmer
+<br>MIT License
+<br>(recommended loading setting: Size = 10.0, GlyphOffset.y = +1)
+<br>http://www.proggyfonts.net/
+
+**Karla-Regular.ttf**, by Jonathan Pinhorn
+<br>SIL OPEN FONT LICENSE Version 1.1
+
+##### [Return to Index](#index)
+
+## Font Links
+
+#### ICON FONTS
+
+- C/C++ header for icon fonts (#define with code points to use in source code string literals) https://github.com/juliettef/IconFontCppHeaders
+- FontAwesome https://fortawesome.github.io/Font-Awesome
+- OpenFontIcons https://github.com/traverseda/OpenFontIcons
+- Google Icon Fonts https://design.google.com/icons/
+- Kenney Icon Font (Game Controller Icons) https://github.com/nicodinh/kenney-icon-font
+- IcoMoon - Custom Icon font builder https://icomoon.io/app
+
+#### REGULAR FONTS
+
+- Google Noto Fonts (worldwide languages) https://www.google.com/get/noto/
+- Open Sans Fonts https://fonts.google.com/specimen/Open+Sans
+- (Japanese) M+ fonts by Coji Morishita http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
+
+#### MONOSPACE FONTS
+
+Pixel Perfect:
+- Proggy Fonts, by Tristan Grimmer http://www.proggyfonts.net or http://upperbounds.net
+- Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) https://github.com/kmar/Sweet16Font (also include an .inl file to use directly in dear imgui.)
+
+Regular:
+- Google Noto Mono Fonts https://www.google.com/get/noto/
+- Typefaces for source code beautification https://github.com/chrissimpkins/codeface
+- Programmation fonts http://s9w.github.io/font_compare/
+- Inconsolata http://www.levien.com/type/myfonts/inconsolata.html
+- Adobe Source Code Pro: Monospaced font family for ui & coding environments https://github.com/adobe-fonts/source-code-pro
+- Monospace/Fixed Width Programmer's Fonts http://www.lowing.org/fonts/
+
+Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing).
+
+##### [Return to Index](#index)
diff --git a/Client/ThirdParty/imgui/docs/README.md b/Client/ThirdParty/imgui/docs/README.md
new file mode 100644
index 0000000..7997a80
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/README.md
@@ -0,0 +1,243 @@
+Dear ImGui
+=====
+[![Build Status](https://github.com/ocornut/imgui/workflows/build/badge.svg)](https://github.com/ocornut/imgui/actions?workflow=build) [![Static Analysis Status](https://github.com/ocornut/imgui/workflows/static-analysis/badge.svg)](https://github.com/ocornut/imgui/actions?workflow=static-analysis)
+
+
+<sub>(This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If your company is using Dear ImGui, please consider reaching out.)</sub>
+
+Businesses: support continued development and maintenance via invoiced technical support, maintenance, sponsoring contracts:
+<br>&nbsp;&nbsp;_E-mail: contact @ dearimgui dot com_
+
+Individuals: support continued development and maintenance [here](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WGHNC6MBFLZ2S).
+
+Also see [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
+
+----
+
+Dear ImGui is a **bloat-free graphical user interface library for C++**. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).
+
+Dear ImGui is designed to **enable fast iterations** and to **empower programmers** to create **content creation tools and visualization / debug tools** (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries.
+
+Dear ImGui is particularly suited to integration in games engine (for tooling), real-time 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard.
+
+| [Usage](#usage) - [How it works](#how-it-works) - [Releases & Changelogs](#releases--changelogs) - [Demo](#demo) - [Integration](#integration) |
+:----------------------------------------------------------: |
+| [Upcoming changes](#upcoming-changes) - [Gallery](#gallery) - [Support, FAQ](#support-frequently-asked-questions-faq) - [How to help](#how-to-help) - [Sponsors](#sponsors) - [Credits](#credits) - [License](#license) |
+| [Wiki](https://github.com/ocornut/imgui/wiki) - [Languages & frameworks backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) - [Software using Dear ImGui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) - [User quotes](https://github.com/ocornut/imgui/wiki/Quotes) |
+
+### Usage
+
+**The core of Dear ImGui is self-contained within a few platform-agnostic files** which you can easily compile in your application/engine. They are all the files in the root folder of the repository (imgui*.cpp, imgui*.h).
+
+**No specific build process is required**. You can add the .cpp files to your existing project.
+
+You will need a backend to integrate Dear ImGui in your app. The backend passes mouse/keyboard/gamepad inputs and variety of settings to Dear ImGui, and is in charge of rendering the resulting vertices.
+
+**Backends for a variety of graphics api and rendering platforms** are provided in the [backends/](https://github.com/ocornut/imgui/tree/master/backends) folder, along with example applications in the [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder. See the [Integration](#integration) section of this document for details. You may also create your own backend. Anywhere where you can render textured triangles, you can render Dear ImGui.
+
+After Dear ImGui is setup in your application, you can use it from \_anywhere\_ in your program loop:
+
+Code:
+```cpp
+ImGui::Text("Hello, world %d", 123);
+if (ImGui::Button("Save"))
+ MySaveFunction();
+ImGui::InputText("string", buf, IM_ARRAYSIZE(buf));
+ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
+```
+Result:
+<br>![sample code output (dark)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v175/capture_readme_styles_0001.png) ![sample code output (light)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v175/capture_readme_styles_0002.png)
+<br>_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px)_
+
+Code:
+```cpp
+// Create a window called "My First Tool", with a menu bar.
+ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar);
+if (ImGui::BeginMenuBar())
+{
+ if (ImGui::BeginMenu("File"))
+ {
+ if (ImGui::MenuItem("Open..", "Ctrl+O")) { /* Do stuff */ }
+ if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Do stuff */ }
+ if (ImGui::MenuItem("Close", "Ctrl+W")) { my_tool_active = false; }
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+}
+
+// Edit a color (stored as ~4 floats)
+ImGui::ColorEdit4("Color", my_color);
+
+// Plot some values
+const float my_values[] = { 0.2f, 0.1f, 1.0f, 0.5f, 0.9f, 2.2f };
+ImGui::PlotLines("Frame Times", my_values, IM_ARRAYSIZE(my_values));
+
+// Display contents in a scrolling region
+ImGui::TextColored(ImVec4(1,1,0,1), "Important Stuff");
+ImGui::BeginChild("Scrolling");
+for (int n = 0; n < 50; n++)
+ ImGui::Text("%04d: Some text", n);
+ImGui::EndChild();
+ImGui::End();
+```
+Result:
+<br>![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v180/code_sample_04_color.gif)
+
+Dear ImGui allows you to **create elaborate tools** as well as very short-lived ones. On the extreme side of short-livedness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc.
+
+### How it works
+
+Check out the Wiki's [About the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#about-the-imgui-paradigm) section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize superfluous state duplication, state synchronization and state retention from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces.
+
+Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes required to render them is fairly small. Because Dear ImGui doesn't know or touch graphics state directly, you can call its functions anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate Dear ImGui with your existing codebase.
+
+_A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._
+
+### Releases & Changelogs
+
+See [Releases](https://github.com/ocornut/imgui/releases) page.
+Reading the changelogs is a good way to keep up to date with the things Dear ImGui has to offer, and maybe will give you ideas of some features that you've been ignoring until now!
+
+### Demo
+
+Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcasing variety of features and examples. The code is always available for reference in `imgui_demo.cpp`.
+
+![screenshot demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v167/v167-misc.png)
+
+You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let us know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here:
+- [imgui-demo-binaries-20210331.zip](https://www.dearimgui.org/binaries/imgui-demo-binaries-20210331.zip) (Windows, 1.83 WIP, built 2021/03/31, master branch) or [older demo binaries](https://www.dearimgui.org/binaries).
+
+The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.org/faq)).
+
+### Integration
+
+On most platforms and when using C++, **you should be able to use a combination of the [imgui_impl_xxxx](https://github.com/ocornut/imgui/tree/master/backends) backends without modification** (e.g. `imgui_impl_win32.cpp` + `imgui_impl_dx11.cpp`). If your engine supports multiple platforms, consider using more of the imgui_impl_xxxx files instead of rewriting them: this will be less work for you and you can get Dear ImGui running immediately. You can _later_ decide to rewrite a custom backend using your custom engine functions if you wish so.
+
+Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer at ease with those concepts, it should take you less than two hours to integrate Dear ImGui in your custom engine. **Make sure to spend time reading the [FAQ](https://www.dearimgui.org/faq), comments, and some of the examples/ application!**
+
+Officially maintained backends/bindings (in repository):
+- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU.
+- Platforms: GLFW, SDL2, Win32, Glut, OSX, Android.
+- Frameworks: Emscripten, Allegro5, Marmalade.
+
+[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
+- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
+- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GLEQ, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS & Switch (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SDL_Renderer, SFML, Sokol, Unity, Unreal Engine 4, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
+- Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages.
+
+[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
+- Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos etc.
+
+Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
+
+### Upcoming Changes
+
+Some of the goals for 2021 are:
+- Work on Docking (see [#2109](https://github.com/ocornut/imgui/issues/2109), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch)
+- Work on Multi-Viewport / Multiple OS windows. (see [#1542](https://github.com/ocornut/imgui/issues/1542), in public [docking](https://github.com/ocornut/imgui/tree/docking) branch looking for feedback)
+- Work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787))
+- Work on automation and testing system, both to test the library and end-user apps. (see [#435](https://github.com/ocornut/imgui/issues/435))
+- Make the examples look better, improve styles, improve font support, make the examples hi-DPI and multi-DPI aware.
+
+### Gallery
+
+For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/4451)!
+
+For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
+
+Custom engine
+[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png)
+
+Custom engine
+[![screenshot tool](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png)
+
+[Tracy Profiler](https://github.com/wolfpld/tracy)
+![tracy profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v176/tracy_profiler.png)
+
+### Support, Frequently Asked Questions (FAQ)
+
+See: [Frequently Asked Questions (FAQ)](https://github.com/ocornut/imgui/blob/master/docs/FAQ.md) where common questions are answered.
+
+See: [Wiki](https://github.com/ocornut/imgui/wiki) for many links, references, articles.
+
+See: [Articles about the IMGUI paradigm](https://github.com/ocornut/imgui/wiki#about-the-imgui-paradigm) to read/learn about the Immediate Mode GUI paradigm.
+
+Getting started? For first-time users having issues compiling/linking/running or issues loading fonts, please use [GitHub Discussions](https://github.com/ocornut/imgui/discussions).
+
+For other questions, bug reports, requests, feedback, you may post on [GitHub Issues](https://github.com/ocornut/imgui/issues). Please read and fill the New Issue template carefully.
+
+Private support is available for paying business customers (E-mail: _contact @ dearimgui dot com_).
+
+**Which version should I get?**
+
+We occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
+
+Advanced users may want to use the `docking` branch with [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features. This branch is kept in sync with master regularly.
+
+**Who uses Dear ImGui?**
+
+See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes), [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors), [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for an idea of who is using Dear ImGui. Please add your game/software if you can! Also see the [Gallery Threads](https://github.com/ocornut/imgui/issues/4451)!
+
+How to help
+-----------
+
+**How can I help?**
+
+- See [GitHub Forum/issues](https://github.com/ocornut/imgui/issues) and [Github Discussions](https://github.com/ocornut/imgui/discussions).
+- You may help with development and submit pull requests! Please understand that by submitting a PR you are also submitting a request for the maintainer to review your code and then take over its maintenance forever. PR should be crafted both in the interest in the end-users and also to ease the maintainer into understanding and accepting it.
+- See [Help wanted](https://github.com/ocornut/imgui/wiki/Help-Wanted) on the [Wiki](https://github.com/ocornut/imgui/wiki/) for some more ideas.
+- Have your company financially support this project (please reach by e-mail)
+
+**How can I help financing further development of Dear ImGui?**
+
+See [Sponsors](https://github.com/ocornut/imgui/wiki/Sponsors) page.
+
+Sponsors
+--------
+
+Ongoing Dear ImGui development is currently financially supported by users and private sponsors:
+
+*Platinum-chocolate sponsors*
+- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1)
+
+*Double-chocolate sponsors*
+- [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui)
+
+*Chocolate sponsors*
+- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [RAD Game Tools](http://www.radgametools.com/), [Supercell](https://supercell.com)
+
+*Salty-caramel sponsors*
+- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com)
+
+Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors.
+From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
+
+**THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**
+
+Dear ImGui is using software and services provided free of charge for open source projects:
+- [PVS-Studio](https://www.viva64.com/en/b/0570/) for static analysis.
+- [GitHub actions](https://github.com/features/actions) for continuous integration systems.
+- [OpenCppCoverage](https://github.com/OpenCppCoverage/OpenCppCoverage) for code coverage analysis.
+
+Credits
+-------
+
+Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://tearaway.mediamolecule.com) (PS Vita).
+
+Recurring contributors (2020): Omar Cornut [@ocornut](https://github.com/ocornut), Rokas Kupstys [@rokups](https://github.com/rokups), Ben Carter [@ShironekoBen](https://github.com/ShironekoBen).
+A large portion of work on automation systems, regression tests and other features are currently unpublished.
+
+Sponsoring, support contracts and other B2B transactions are hosted and handled by [Lizardcube](https://www.lizardcube.com).
+
+Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
+
+Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license).
+
+Embeds [stb_textedit.h, stb_truetype.h, stb_rect_pack.h](https://github.com/nothings/stb/) by Sean Barrett (public domain).
+
+Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. Also thank you to everyone posting feedback, questions and patches on GitHub.
+
+License
+-------
+
+Dear ImGui is licensed under the MIT License, see [LICENSE.txt](https://github.com/ocornut/imgui/blob/master/LICENSE.txt) for more information.
diff --git a/Client/ThirdParty/imgui/docs/TODO.txt b/Client/ThirdParty/imgui/docs/TODO.txt
new file mode 100644
index 0000000..9d005ed
--- /dev/null
+++ b/Client/ThirdParty/imgui/docs/TODO.txt
@@ -0,0 +1,404 @@
+dear imgui
+ISSUES & TODO LIST
+
+Issue numbers (#) refer to github issues listed at https://github.com/ocornut/imgui/issues/XXXX
+The list below consist mostly of ideas noted down before they are requested/discussed by users (at which point they usually exist on the github issue tracker).
+It's mostly a bunch of personal notes, probably incomplete. Feel free to query if you have any questions.
+
+ - doc/test: add a proper documentation+regression testing system (#435)
+ - doc/test: checklist app to verify backends/integration of imgui (test inputs, rendering, callback, etc.).
+ - doc/tips: tips of the day: website? applet in imgui_club?
+ - doc/wiki: work on the wiki https://github.com/ocornut/imgui/wiki
+
+ - window: preserve/restore relative focus ordering (persistent or not) (#2304) -> also see docking reference to same #.
+ - window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis). (#690)
+ - window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
+ - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
+ - window: begin with *p_open == false could return false.
+ - window: get size/pos helpers given names (see discussion in #249)
+ - window: a collapsed window can be stuck behind the main menu bar?
+ - window: when window is very small, prioritize resize button over close button.
+ - window: detect extra End() call that pop the "Debug" window out and assert at End() call site instead of at end of frame.
+ - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd.
+ - window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon?
+ - window: expose contents size. (#1045)
+ - window: using SetWindowPos() inside Begin() and moving the window with the mouse reacts a very ugly glitch. We should just defer the SetWindowPos() call.
+ - window: GetWindowSize() returns (0,0) when not calculated? (#1045)
+ - window: investigate better auto-positioning for new windows.
+ - window: top most window flag? (#2574)
+ - window/size: manually triggered auto-fit (double-click on grip) shouldn't resize window down to viewport size?
+ - window/size: how to allow to e.g. auto-size vertically to fit contents, but be horizontally resizable? Assuming SetNextWindowSize() is modified to treat -1.0f on each axis as "keep as-is" (would be good but might break erroneous code): Problem is UpdateWindowManualResize() and lots of code treat (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) together.
+ - window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false.
+ - window/child: background options for child windows, border option (disable rounding).
+ - window/child: allow resizing of child windows (possibly given min/max for each axis?.)
+ - window/child: the first draw command of a child window could be moved into the current draw command of the parent window (unless child+tooltip?).
+ - window/child: border could be emitted in parent as well.
+ - window/child: allow SetNextWindowContentSize() to work on child windows.
+ - window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero.
+ - window/tabbing: add a way to signify that a window or docked window requires attention (e.g. blinking title bar).
+ - window/id_stack: add e.g. window->GetIDFromPath() with support for leading / and ../ (#1390, #331)
+ ! scrolling: exposing horizontal scrolling with Shift+Wheel even when scrollbar is disabled expose lots of issues (#2424, #1463)
+ - scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse)
+ - scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet.
+ - scrolling: forward mouse wheel scrolling to parent window when at the edge of scrolling limits? (useful for listbox,tables?)
+ - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro)
+ - scrolling/style: shadows on scrollable areas to denote that there is more contents (see e.g. DaVinci Resolve ui)
+
+ - drawdata: make it easy to clone (or swap?) a full ImDrawData so user can easily save that data if they use threaded rendering. (e.g. #2646)
+ ! drawlist: add calctextsize func to facilitate consistent code from user pov (currently need to use ImGui or ImFont alternatives!)
+ - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack.
+ - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command).
+ - drawlist: primitives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api
+ - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally
+ - drawlist: non-AA strokes have gaps between points (#593, #288), glitch especially on RenderCheckmark() and ColorPicker4().
+ - drawlist: would be good to be able to deep copy of ImDrawData (we have a deep copy of ImDrawList now).
+ - drawlist: rendering: provide a way for imgui to output to a single/global vertex buffer, re-order indices only at the end of the frame (ref: https://gist.github.com/floooh/10388a0afbe08fce9e617d8aefa7d302)
+ - drawlist: callback: add an extra void* in ImDrawCallback to allow passing render-local data to the callback (would break API).
+ - drawlist: AddRect vs AddLine position confusing (#2441)
+ - drawlist: channel splitter should be external helper and not stored in ImDrawList.
+ - drawlist: Add quadratic bezier curves? (#3127)
+ - drawlist/opt: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. (#1962)
+ - drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation.
+ - drawlist/opt: thick AA line could be doable in same number of triangles as 1.0 AA line by storing gradient+full color in atlas.
+
+ - main: find a way to preserve relative orders of multiple reappearing windows (so an app toggling between "modes" e.g. fullscreen vs all tools) won't lose relative ordering.
+ - main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
+ - main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
+
+ - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395)
+ - widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h.
+ - widgets: add visuals for Disabled/ReadOnly mode and expose publicly (#211)
+ - widgets: add always-allow-overlap mode. This should perhaps be the default? one problem is that highlight after mouse-wheel scrolling gets deferred, makes scrolling more flickery.
+ - widgets: start exposing PushItemFlag() and ImGuiItemFlags
+ - widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260
+ - widgets: activate by identifier (trigger button, focus given id)
+ - widgets: a way to represent "mixed" values, so e.g. all values replaced with *, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) (#2644)
+ - widgets: checkbox: checkbox with custom glyph inside frame.
+ - widgets: coloredit: keep reporting as active when picker is on?
+ - widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
+ - selectable: using (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
+ - selectable: generic BeginSelectable()/EndSelectable() mechanism.
+ - selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
+
+ - input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile.
+ - input text: preserve scrolling when unfocused?
+ - input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
+ - input text: expose CursorPos in char filter event (#816)
+ - input text: try usage idiom of using InputText with data only exposed through get/set accessors, without extraneous copy/alloc. (#3009)
+ - input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return NULL if not active.
+ - input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701)
+ - input text: hover tooltip could show unclamped text
+ - input text: support for INSERT key to toggle overwrite mode. currently disabled because stb_textedit behavior is unsatisfactory on multi-line. (#2863)
+ - input text: option to Tab after an Enter validation.
+ - input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
+ - input text: easier ways to update buffer (from source char*) while owned. preserve some sort of cursor position for multi-line text.
+ - input text: add flag (e.g. ImGuiInputTextFlags_EscapeClearsBuffer) to clear instead of revert. what to do with focus? (also see #2890)
+ - input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725)
+ - input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependent). actually a very old bug but no one appears to have noticed it.
+ - input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
+ - input text: decorrelate layout from inputs - e.g. what's the easiest way to implement a nice IP/Mac address input editor?
+ - input text: global callback system so user can plug in an expression evaluator easily. (#1691)
+ - input text: force scroll to end or scroll to a given line/contents (so user can implement a log or a search feature)
+ - input text: a way to preview completion (e.g. disabled text completing from the cursor)
+ - input text: a side bar that could e.g. preview where errors are. probably left to the user to draw but we'd need to give them the info there.
+ - input text: a way for the user to provide syntax coloring.
+ - input text: Shift+TAB with ImGuiInputTextFlags_AllowTabInput could eat preceding blanks, up to tab_count.
+ - input text: facilitate patterns like if (InputText(..., obj.get_string_ref()) { obj.set_string(...); } relying on internally held buffer.
+ - input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
+ - input text multi-line: support for cut/paste without selection (cut/paste the current line)
+ - input text multi-line: line numbers? status bar? (follow up on #200)
+ - input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725)
+ - input text multi-line: better horizontal scrolling support (#383, #1224)
+ - input text multi-line: single call to AddText() should be coarse clipped on InputTextEx() end.
+ - input number: optional range min/max for Input*() functions
+ - input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
+ - input number: use mouse wheel to step up/down
+ - input number: applying arithmetics ops (+,-,*,/) messes up with text edit undo stack.
+
+ - layout: helper or a way to express ImGui::SameLine(ImGui::GetCursorStartPos().x + ImGui::CalcItemWidth() + ImGui::GetStyle().ItemInnerSpacing.x); in a simpler manner.
+ - layout, font: horizontal tab support, A) text mode: forward only tabs (e.g. every 4 characters/N pixels from pos x1), B) manual mode: explicit tab stops acting as mini columns, no clipping (for menu items, many kind of uses, also vaguely relate to #267, #395)
+ - layout: horizontal layout helper (#97)
+ - layout: horizontal flow until no space left (#404)
+ - layout: more generic alignment state (left/right/centered) for single items?
+ - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding.
+ - layout: vertical alignment of mixed height items (e.g. buttons) within a same line (#1284)
+ - layout: null layout mode were items are not rendered but user can query GetItemRectMin()/Max/Size.
+ - layout: (R&D) local multi-pass layout mode.
+ - layout: (R&D) bind authored layout data (created by an off-line tool), items fetch their pos/size at submission, self-optimize data structures to stable linear access.
+
+ - group: BeginGroup() needs a border option. (~#1496)
+ - group: IsHovered() after EndGroup() covers whole aabb rather than the intersection of individual items. Is that desirable?
+ - group: merge deactivation/activation within same group (fwd WasEdited flag). (#2550)
+
+!- color: the color conversion helpers/types are a mess and needs sorting out.
+ - color: (api breaking) ImGui::ColorConvertXXX functions should be loose ImColorConvertXX to match imgui_internals.h
+
+ - plot: full featured plot/graph api w/ scrolling, zooming etc. all bell & whistle. why not!
+ - plot: PlotLines() should use the polygon-stroke facilities, less vertices (currently issues with averaging normals)
+ - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
+ - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
+ - plot: option/feature: draw the zero line
+ - plot: option/feature: draw grid, vertical markers
+ - plot: option/feature: draw unit
+ - plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
+
+ - clipper: ability to disable the clipping through a simple flag/bool.
+ - clipper: ability to run without knowing full count in advance.
+ - clipper: horizontal clipping support. (#2580)
+
+ - separator: expose flags (#759)
+ - separator: take indent into consideration (optional)
+ - separator: width, thickness, centering (#1643)
+ - splitter: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
+
+ - dock: merge docking branch (#2109)
+ - dock: dock out from a collapsing header? would work nicely but need emitting window to keep submitting the code.
+
+ - tabs: "there is currently a problem because TabItem() will try to submit their own tooltip after 0.50 second, and this will have the effect of making your tooltip flicker once." -> tooltip priority work
+ - tabs: close button tends to overlap unsaved-document star
+ - tabs: consider showing the star at the same spot as the close button, like VS Code does.
+ - tabs: make EndTabBar fail if users doesn't respect BeginTabBar return value, for consistency/future-proofing.
+ - tabs: persistent order/focus in BeginTabBar() api (#261, #351)
+ - tabs: TabItem could honor SetNextItemWidth()?
+ - tabs: explicit api (even if internal) to cleanly manipulate tab order.
+ - tabs: Mouse wheel over tab bar could scroll? (#2702)
+
+ - image/image button: misalignment on padded/bordered button?
+ - image/image button: parameters are confusing, image() has tint_col,border_col whereas imagebutton() has bg_col/tint_col. Even thou they are different parameters ordering could be more consistent. can we fix that?
+ - image button: not taking an explicit id can be problematic. (#2464, #1390)
+ - button: provide a button that looks framed. (?)
+ - slider/drag: ctrl+click when format doesn't include a % character.. disable? display underlying value in default format? (see TempInputTextScalar)
+ - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt()
+ - slider: initial absolute click is imprecise. change to relative movement slider (same as scrollbar). (#1946)
+ - slider: add dragging-based widgets to edit values with mouse (on 2 axises), saving screen real-estate.
+ - slider: tint background based on value (e.g. v_min -> v_max, or use 0.0f either side of the sign)
+ - slider: relative dragging? + precision dragging
+ - slider: step option (#1183)
+ - slider: style: fill % of the bar instead of positioning a drag.
+ - knob: rotating knob widget (#942)
+ - drag float: support for reversed drags (min > max) (removed is_locked, also see fdc526e)
+ - drag float: up/down axis
+ - drag float: power != 0.0f with current value being outside the range keeps the value stuck.
+ - drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
+
+ - combo: use clipper: make it easier to disable clipper with a single flag.
+ - combo: flag for BeginCombo to not return true when unchanged (#1182)
+ - combo: a way/helper to customize the combo preview (#1658) -> exeperimental BeginComboPreview()
+ - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203)
+ - listbox: multiple selection.
+ - listbox: unselect option (#1208)
+ - listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash)
+ - listbox: user may want to initial scroll to focus on the one selected value?
+ - listbox: expose hovered item for a simplified ListBox api
+ - listbox: keyboard navigation.
+ - listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
+ - listbox: scrolling should track modified selection.
+ - listbox: future api should allow to enable horizontal scrolling (#2510)
+
+!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
+ - modals: make modal title bar blink when trying to click outside the modal
+ - modals: technically speaking, we could make Begin() with ImGuiWindowFlags_Modal work without involving popup. May help untangle a few things, as modals are more like regular windows than popups.
+ - popups: if the popup functions took explicit ImGuiID it would allow the user to manage the scope of those ID. (#331)
+ - popups: clicking outside (to close popup) and holding shouldn't drag window below.
+ - popups: add variant using global identifier similar to Begin/End (#402)
+ - popups: border options. richer api like BeginChild() perhaps? (#197)
+ - popups: flags could be reworked to allow both mouse buttons as index (0..5 and as flags using higher-bit) allowing to or them.
+ - popups/modals: although it is sometimes convenient that popups/modals lifetime is owned by imgui, we could also a bool-owned-by-user api as long as Begin() return value testing is enforced.
+
+ - tooltip: drag and drop with tooltip near monitor edges lose/changes its last direction instead of locking one. The drag and drop tooltip should always follow without changing direction.
+ - tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
+ - tooltip: tooltips with delay timers? or general timer policy? (instantaneous vs timed): IsItemHovered() with timer + implicit aabb-id for items with no ID. (#1485)
+ - tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers.
+
+ - menus: menu bars inside modal windows are acting weird.
+ - status-bar: add a per-window status bar helper similar to what menu-bar does.
+ - shortcuts: local-style shortcut api, e.g. parse "&Save"
+ - shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu
+ - shortcuts: programmatically access shortcuts "Focus("&Save"))
+ - menus: hovering a disabled BeginMenu or MenuItem won't close another menu
+ - menus: menu-bar: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin)
+ - menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer.
+ - menus: could merge draw call in most cases (how about storing an optional aabb in ImDrawCmd to move the burden of merging in a single spot).
+ - menus: would be nice if the Selectable() supported horizontal alignment (must be given the equivalent of WorkRect.Max.x matching the position of the shortcut column)
+
+ - tree node: add treenode/treepush int variants? not there because (void*) cast from int warns on some platforms/settings?
+ - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits?
+ - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
+ - tree node: tweak color scheme to distinguish headers from selected tree node (#581)
+ - tree node: leaf/non-leaf highlight mismatch.
+ - tree node: flag to disable formatting and/or detect "%s"
+ - tree node/opt: could avoid formatting when clipped (flag assuming we don't care about width/height, assume single line height? format only %s/%c to be able to count height?)
+
+ - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes?
+ - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437)
+ - settings/persistence: helpers to make TreeNodeBehavior persist (even during dev!) - may need to store some semantic and/or data type in ImGuiStoragePair
+
+ - style: better default styles. (#707)
+ - style: PushStyleVar: allow direct access to individual float X/Y elements.
+ - style: add a highlighted text color (for headers, etc.)
+ - style: border types: out-screen, in-screen, etc. (#447)
+ - style: add window shadow (fading away from the window. Paint-style calculation of vertices alpha after drawlist would be easier)
+ - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
+ - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
+ - style: global scale setting.
+ - style: FramePadding could be different for up vs down (#584)
+ - style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
+ - style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
+ - style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.
+ - style editor: color child window height expressed in multiple of line height.
+
+ - log: improve logging of ArrowButton, ListBox, TabItem
+ - log: carry on indent / tree depth when opening a child window
+ - log: enabling log ends up pushing and growing vertices buffers because we don't distinguish layout vs render clipping
+ - log: have more control over the log scope (e.g. stop logging when leaving current tree node scope)
+ - log: be able to log anything (e.g. right-click on a window/tree-node, shows context menu? log into tty/file/clipboard)
+ - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs.
+ - log: obsolete LogButtons() all together.
+ - log: LogButtons() options for specifying depth and/or hiding depth slider
+
+ - filters: set a current filter that tree node can automatically query to hide themselves
+ - filters: handle wild-cards (with implicit leading/trailing *), reg-exprs
+ - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
+
+ - drag and drop: fix/support/options for overlapping drag sources.
+ - drag and drop: focus drag target window on hold (even without open)
+ - drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725)
+ - drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233
+ - drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. (see 2018/01/11 post in #143)
+ - drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725)
+ - drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637)
+ - drag and drop: make it easier and provide a demo to have tooltip both are source and target site, with a more detailed one on target site (tooltip ordering problem)
+ - drag and drop: demo with reordering nodes (in a list, or a tree node). (#143)
+ - drag and drop: test integrating with os drag and drop (make it easy to do a naive WM_DROPFILE integration)
+ - drag and drop: allow for multiple payload types. (#143)
+ - drag and drop: make payload optional? payload promise? (see 2018/01/11 post in #143)
+ - drag and drop: (#143) "both an in-process pointer and a promise to generate a serialized version, for whether the drag ends inside or outside the same process"
+ - drag and drop: feedback when hovering a region blocked by modal (mouse cursor "NO"?)
+
+ - node/graph editors (#306) (also see https://github.com/ocornut/imgui/wiki#node-editors)
+ - pie menus patterns (#434)
+ - markup: simple markup language for color change? (#902)
+
+ - text: selectable text (for copy) as a generic feature (ItemFlags?)
+ - text: proper alignment options in imgui_internal.h
+ - text: it's currently impossible to have a window title with "##". perhaps an official workaround would be nice. \ style inhibitor? non-visible ascii code to insert between #?
+ - text: provided a framed text helper, e.g. https://pastebin.com/1Laxy8bT
+ - text: refactor TextUnformatted (or underlying function) to more explicitly request if we need width measurement or not
+ - text/layout/tabs: \t pulling position from base pos + step, or offset array (e.g. could be used in text edit, menus for simple icon+text alignment, etc.)
+ - text link/url button: underlined. should api expose an ID or use text contents as ID? which colors enum to use?
+ - text/wrapped: should be a more first-class citizen, e.g. wrapped text within a Selectable with known width.
+ - text/wrapped: custom separator for text wrapping. (#3002)
+ - text/wrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249)
+
+ - font: arbitrary line spacing. (#2945)
+ - font: MergeMode: flags to select overwriting or not (this is now very easy with refactored ImFontAtlasBuildWithStbTruetype)
+ - font: free the Alpha buffer if user only requested RGBA.
+!- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions).
+ - font: for the purpose of RenderTextEllipsis(), it might be useful that CalcTextSizeA() can ignore the trailing padding?
+ - font: a CalcTextHeight() helper could run faster than CalcTextSize().y
+ - font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX
+ - font: finish CustomRectRegister() to allow mapping Unicode codepoint to custom texture data
+ - font: remove ID from CustomRect registration, it seems unnecessary!
+ - font: make it easier to submit own bitmap font (same texture, another texture?). (#2127, #2575)
+ - font: PushFontSize API (#1018)
+ - font: MemoryTTF taking ownership confusing/not obvious, maybe default should be opposite?
+ - font: storing MinAdvanceX per font would allow us to skip calculating line width (under a threshold of character count) in loops looking for block width
+ - font/demo: add tools to show glyphs used by a text blob, display U16 value, list missing glyphs.
+ - font/demo: demonstrate use of ImFontGlyphRangesBuilder.
+ - font/atlas: add a missing Glyphs.reserve()
+ - font/atlas: incremental updates
+ - font/atlas: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier.
+ - font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
+ - font/draw: need to be able to specify wrap start position.
+ - font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines). also see #3349.
+ - font/draw: fix for drawing 16k+ visible characters in same call.
+ - font/draw: underline, squiggle line rendering helpers.
+ - font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct), would save on cache line.
+ - font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list?
+ - font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize)
+ - font: fix AddRemapChar() to work before atlas has been built.
+ - font: support for unicode codepoints higher than 0xFFFF? (pr #2815)
+ - font: (api breaking) remove "TTF" from symbol names. also because it now supports OTF.
+ - font/opt: Considering storing standalone AdvanceX table as 16-bit fixed point integer?
+ - font/opt: Glyph currently 40 bytes (2+9*4). Consider storing UV as 16 bits integer? (->32 bytes). X0/Y0/X1/Y1 as 16 fixed-point integers? Or X0/Y0 as float and X1/Y1 as fixed8_8?
+
+ - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line?)
+ - nav: configuration flag to disable global shortcuts (currently only CTRL-Tab) ?
+ ! nav: never clear NavId on some setup (e.g. gamepad centric)
+ - nav: scroll up/down if possible when move request fails
+ - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable.
+ - nav: code to focus child-window on restoring NavId appears to have issue: e.g. when focus change is implicit because of window closure.
+ - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view?
+ - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window"
+ - nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping().
+ - nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch)
+ - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name)
+ - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem
+ - nav: NavFlattened: init requests don't work properly on flattened siblings.
+ - nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings.
+ - nav: NavFlattened: ESC on a flattened child should select something.
+ - nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
+ - nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
+ - nav: simulate right-click or context activation? (SHIFT+F10)
+ - nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
+ - nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
+ - nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.
+ - nav/menus: allow pressing Menu to leave a sub-menu.
+ - nav/menus: a way to access the main menu bar with Alt? (currently needs CTRL+TAB) or last focused window menu bar?
+ - nav/menus: when using the main menu bar, even though we restore focus after, the underlying window loses its title bar highlight during menu manipulation. could we prevent it?
+ - nav/menus: main menu bar currently cannot restore a NULL focus. Could save NavWindow at the time of being focused, similarly to what popup do?
+ - nav/menus: Alt,Up could open the first menu (e.g. "File") currently it tends to nav into the window/collapse menu. Do do that we would need custom transition?
+ - nav/windowing: configure fade-in/fade-out delay on Ctrl+Tab?
+ - nav/windowing: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering.
+ - nav/windowing: Resizing window will currently fail with certain types of resizing constraints/callback applied
+ - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622)
+
+ - inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors.
+ - inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71)
+ - inputs: support track pad style scrolling & slider edit.
+ - inputs/io: backspace and arrows in the context of a text input could use system repeat rate.
+ - inputs/io: clarify/standardize/expose repeat rate and repeat delays (#1808)
+ - inputs/scrolling: support for smooth scrolling (#2462, #2569)
+
+ - misc: idle: expose "woken up" boolean (set by inputs) and/or animation time (for cursor blink) for backend to be able stop refreshing easily.
+ - misc: idle: if cursor blink if the _only_ visible animation, core imgui could rewrite vertex alpha to avoid CPU pass on ImGui:: calls.
+ - misc: idle: if cursor blink if the _only_ visible animation, could even expose a dirty rectangle that optionally can be leverage by some app to render in a smaller viewport, getting rid of much pixel shading cost.
+ - misc: no way to run a root-most GetID() with ImGui:: api since there's always a Debug window in the stack. (mentioned in #2960)
+ - misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?)
+ - misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682)
+ - misc: use more size_t in public api?
+ - misc: possible compile-time support for string view/range instead of char* would e.g. facilitate usage with Rust (#683)
+ - misc: possible compile-time support for wchar_t instead of char*?
+
+ - remote: make a system like RemoteImGui first-class citizen/project (#75)
+
+ - demo: find a way to demonstrate textures in the examples application, as it such a common issue for new users.
+ - demo: demonstrate using PushStyleVar() in more details.
+ - demo: add vertical separator demo
+ - demo: add virtual scrolling example?
+ - demo: demonstrate Plot offset
+ - demo: window size constraint: square demo is broken when resizing from edges (#1975), would need to rework the callback system to solve this
+
+ - examples: window minimize, maximize (#583)
+ - examples: provide a zero frame-rate/idle example.
+ - examples: dx11/dx12: try to use new swapchain blit models (#2970)
+ - backends: move to backends/ folder?
+ - backends: report it better when not able to create texture?
+ - backends: apple: example_apple should be using modern GL3.
+ - backends: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // issue: DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440)
+ - backends: opengl: rename imgui_impl_opengl2 to impl_opengl_legacy and imgui_impl_opengl3 to imgui_impl_opengl? (#1900)
+ - backends: opengl: could use a single vertex buffer and glBufferSubData for uploads?
+ - backends: opengl: explicitly disable GL_STENCIL_TEST in bindings.
+ - backends: vulkan: viewport: support for synchronized swapping of multiple swap chains.
+ - backends: bgfx: https://gist.github.com/RichardGale/6e2b74bc42b3005e08397236e4be0fd0
+ - backends: mscriptem: with refactored examples, we could provide a direct imgui_impl_emscripten platform layer (see eg. https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42)
+
+ - bindings: ways to use clang ast dump to generate bindings or helpers for bindings? (e.g. clang++ -Xclang -ast-dump=json imgui.h)
+
+ - optimization: replace vsnprintf with stb_printf? using IMGUI_USE_STB_SPRINTF.(#1038)
+ - optimization: add clipping for multi-component widgets (SliderFloatX, ColorEditX, etc.). one problem is that nav branch can't easily clip parent group when there is a move request.
+ - optimization: add a flag to disable most of rendering, for the case where the user expect to skip it (#335)
+ - optimization: fully covered window (covered by another with non-translucent bg + WindowRounding worth of padding) may want to clip rendering.
+ - optimization: use another hash function than crc32, e.g. FNV1a
+ - optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)?
+ - optimization: turn some the various stack vectors into statically-sized arrays
diff --git a/Client/ThirdParty/imgui/examples/README.txt b/Client/ThirdParty/imgui/examples/README.txt
new file mode 100644
index 0000000..6db2f3c
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/README.txt
@@ -0,0 +1,9 @@
+See BACKENDS and EXAMPLES files in the docs/ folder, or on the web at: https://github.com/ocornut/imgui/tree/master/docs
+
+Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app).
+Examples = Standalone applications showcasing integration with platforms/graphics api.
+
+Some Examples have extra README files in their respective directory, please check them too!
+
+Once Dear ImGui is running (in either examples or your own application/game/engine),
+run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API.
diff --git a/Client/ThirdParty/imgui/examples/example_allegro5/README.md b/Client/ThirdParty/imgui/examples/example_allegro5/README.md
new file mode 100644
index 0000000..d6d812e
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_allegro5/README.md
@@ -0,0 +1,36 @@
+
+# Configuration
+
+Dear ImGui outputs 16-bit vertex indices by default.
+Allegro doesn't support them natively, so we have two solutions: convert the indices manually in imgui_impl_allegro5.cpp, or compile dear imgui with 32-bit indices.
+You can either modify imconfig.h that comes with Dear ImGui (easier), or set a C++ preprocessor option IMGUI_USER_CONFIG to find to a filename.
+We are providing `imconfig_allegro5.h` that enables 32-bit indices.
+Note that the backend supports _BOTH_ 16-bit and 32-bit indices, but 32-bit indices will be slightly faster as they won't require a manual conversion.
+
+# How to Build
+
+### On Ubuntu 14.04+ and macOS
+
+```bash
+g++ -DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" -I .. -I ../.. main.cpp ../../backends/imgui_impl_allegro5.cpp ../../imgui*.cpp -lallegro -lallegro_main -lallegro_primitives -o allegro5_example
+```
+
+On macOS, install Allegro with homebrew: `brew install allegro`.
+
+### On Windows with Visual Studio's CLI
+
+You may install Allegro using vcpkg:
+```
+git clone https://github.com/Microsoft/vcpkg
+cd vcpkg
+bootstrap-vcpkg.bat
+vcpkg install allegro5 --triplet=x86-windows ; for win32
+vcpkg install allegro5 --triplet=x64-windows ; for win64
+vcpkg integrate install ; register include / libs in Visual Studio
+```
+
+Build:
+```
+set ALLEGRODIR=path_to_your_allegro5_folder
+cl /Zi /MD /I %ALLEGRODIR%\include /DIMGUI_USER_CONFIG=\"examples/example_allegro5/imconfig_allegro5.h\" /I .. /I ..\.. main.cpp ..\..\backends\imgui_impl_allegro5.cpp ..\..\imgui*.cpp /link /LIBPATH:%ALLEGRODIR%\lib allegro-5.0.10-monolith-md.lib user32.lib
+```
diff --git a/Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj b/Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj
new file mode 100644
index 0000000..69b0ece
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{73F235B5-7D31-4FC6-8682-DDC5A097B9C1}</ProjectGuid>
+ <RootNamespace>example_allegro5</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_allegro5.cpp" />
+ <ClCompile Include="imconfig_allegro5.h" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_allegro5.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj.filters
new file mode 100644
index 0000000..7fea78b
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_allegro5/example_allegro5.vcxproj.filters
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_allegro5.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="imconfig_allegro5.h">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_allegro5.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_allegro5/imconfig_allegro5.h b/Client/ThirdParty/imgui/examples/example_allegro5/imconfig_allegro5.h
new file mode 100644
index 0000000..35afa67
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_allegro5/imconfig_allegro5.h
@@ -0,0 +1,11 @@
+//-----------------------------------------------------------------------------
+// COMPILE-TIME OPTIONS FOR DEAR IMGUI ALLEGRO 5 EXAMPLE
+// See imconfig.h for the full template
+// Because Allegro doesn't support 16-bit vertex indices, we enable the compile-time option of imgui to use 32-bit indices
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+// Use 32-bit vertex indices because Allegro doesn't support 16-bit ones
+// This allows us to avoid converting vertices format at runtime
+#define ImDrawIdx int
diff --git a/Client/ThirdParty/imgui/examples/example_allegro5/main.cpp b/Client/ThirdParty/imgui/examples/example_allegro5/main.cpp
new file mode 100644
index 0000000..4fd379a
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_allegro5/main.cpp
@@ -0,0 +1,144 @@
+// Dear ImGui: standalone example application for Allegro 5
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// On Windows, you can install Allegro5 using vcpkg:
+// git clone https://github.com/Microsoft/vcpkg
+// cd vcpkg
+// bootstrap - vcpkg.bat
+// vcpkg install allegro5 --triplet=x86-windows ; for win32
+// vcpkg install allegro5 --triplet=x64-windows ; for win64
+// vcpkg integrate install ; register include and libs in Visual Studio
+
+#include <stdint.h>
+#include <allegro5/allegro.h>
+#include <allegro5/allegro_primitives.h>
+#include "imgui.h"
+#include "imgui_impl_allegro5.h"
+
+int main(int, char**)
+{
+ // Setup Allegro
+ al_init();
+ al_install_keyboard();
+ al_install_mouse();
+ al_init_primitives_addon();
+ al_set_new_display_flags(ALLEGRO_RESIZABLE);
+ ALLEGRO_DISPLAY* display = al_create_display(1280, 720);
+ al_set_window_title(display, "Dear ImGui Allegro 5 example");
+ ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue();
+ al_register_event_source(queue, al_get_display_event_source(display));
+ al_register_event_source(queue, al_get_keyboard_event_source());
+ al_register_event_source(queue, al_get_mouse_event_source());
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplAllegro5_Init(display);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool running = true;
+ while (running)
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ ALLEGRO_EVENT ev;
+ while (al_get_next_event(queue, &ev))
+ {
+ ImGui_ImplAllegro5_ProcessEvent(&ev);
+ if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
+ running = false;
+ if (ev.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
+ {
+ ImGui_ImplAllegro5_InvalidateDeviceObjects();
+ al_acknowledge_resize(display);
+ ImGui_ImplAllegro5_CreateDeviceObjects();
+ }
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplAllegro5_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ al_clear_to_color(al_map_rgba_f(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w));
+ ImGui_ImplAllegro5_RenderDrawData(ImGui::GetDrawData());
+ al_flip_display();
+ }
+
+ // Cleanup
+ ImGui_ImplAllegro5_Shutdown();
+ ImGui::DestroyContext();
+ al_destroy_event_queue(queue);
+ al_destroy_display(display);
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/CMakeLists.txt b/Client/ThirdParty/imgui/examples/example_android_opengl3/CMakeLists.txt
new file mode 100644
index 0000000..63531f4
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/CMakeLists.txt
@@ -0,0 +1,40 @@
+cmake_minimum_required(VERSION 3.6)
+
+project(ImGuiExample)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+add_library(${CMAKE_PROJECT_NAME} SHARED
+ ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_demo.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_draw.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_tables.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../imgui_widgets.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_android.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../backends/imgui_impl_opengl3.cpp
+ ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
+)
+
+set(CMAKE_SHARED_LINKER_FLAGS
+ "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate"
+)
+
+target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE
+ IMGUI_IMPL_OPENGL_ES3
+)
+
+target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/../..
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../backends
+ ${ANDROID_NDK}/sources/android/native_app_glue
+)
+
+target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE
+ android
+ EGL
+ GLESv3
+ log
+)
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/android/.gitignore b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/.gitignore
new file mode 100644
index 0000000..3c7a619
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/.gitignore
@@ -0,0 +1,12 @@
+.cxx
+.externalNativeBuild
+build/
+*.iml
+
+.idea
+.gradle
+local.properties
+
+# Android Studio puts a Gradle wrapper here, that we don't want:
+gradle/
+gradlew*
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/build.gradle b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/build.gradle
new file mode 100644
index 0000000..aa7f0ea
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/build.gradle
@@ -0,0 +1,34 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "30.0.3"
+ ndkVersion "21.4.7075529"
+ defaultConfig {
+ applicationId "imgui.example.android"
+ minSdkVersion 23
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "../../CMakeLists.txt"
+ }
+ }
+}
+repositories {
+ mavenCentral()
+}
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c4009e5
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="imgui.example.android">
+
+ <application
+ android:label="ImGuiExample"
+ android:allowBackup="false"
+ android:fullBackupContent="false"
+ android:hasCode="true">
+
+ <activity
+ android:name="imgui.example.android.MainActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:configChanges="orientation|keyboardHidden|screenSize">
+ <meta-data android:name="android.app.lib_name"
+ android:value="ImGuiExample" />
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/java/MainActivity.kt b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/java/MainActivity.kt
new file mode 100644
index 0000000..896a88c
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/app/src/main/java/MainActivity.kt
@@ -0,0 +1,40 @@
+package imgui.example.android
+
+import android.app.NativeActivity
+import android.os.Bundle
+import android.content.Context
+import android.view.inputmethod.InputMethodManager
+import android.view.KeyEvent
+import java.util.concurrent.LinkedBlockingQueue
+
+class MainActivity : NativeActivity() {
+ public override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ }
+
+ fun showSoftInput() {
+ val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ inputMethodManager.showSoftInput(this.window.decorView, 0)
+ }
+
+ fun hideSoftInput() {
+ val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ inputMethodManager.hideSoftInputFromWindow(this.window.decorView.windowToken, 0)
+ }
+
+ // Queue for the Unicode characters to be polled from native code (via pollUnicodeChar())
+ private var unicodeCharacterQueue: LinkedBlockingQueue<Int> = LinkedBlockingQueue()
+
+ // We assume dispatchKeyEvent() of the NativeActivity is actually called for every
+ // KeyEvent and not consumed by any View before it reaches here
+ override fun dispatchKeyEvent(event: KeyEvent): Boolean {
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ unicodeCharacterQueue.offer(event.getUnicodeChar(event.metaState))
+ }
+ return super.dispatchKeyEvent(event)
+ }
+
+ fun pollUnicodeChar(): Int {
+ return unicodeCharacterQueue.poll() ?: 0
+ }
+}
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/android/build.gradle b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/build.gradle
new file mode 100644
index 0000000..59f9c78
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/build.gradle
@@ -0,0 +1,24 @@
+buildscript {
+ ext.kotlin_version = '1.4.31'
+ repositories {
+ google()
+ mavenCentral()
+
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/android/settings.gradle b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/android/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/Client/ThirdParty/imgui/examples/example_android_opengl3/main.cpp b/Client/ThirdParty/imgui/examples/example_android_opengl3/main.cpp
new file mode 100644
index 0000000..5ab6903
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_android_opengl3/main.cpp
@@ -0,0 +1,369 @@
+// dear imgui: standalone example application for Android + OpenGL ES 3
+// If you are new to dear imgui, see examples/README.txt and documentation at the top of imgui.cpp.
+
+#include "imgui.h"
+#include "imgui_impl_android.h"
+#include "imgui_impl_opengl3.h"
+#include <android/log.h>
+#include <android_native_app_glue.h>
+#include <android/asset_manager.h>
+#include <EGL/egl.h>
+#include <GLES3/gl3.h>
+
+// Data
+static EGLDisplay g_EglDisplay = EGL_NO_DISPLAY;
+static EGLSurface g_EglSurface = EGL_NO_SURFACE;
+static EGLContext g_EglContext = EGL_NO_CONTEXT;
+static struct android_app* g_App = NULL;
+static bool g_Initialized = false;
+static char g_LogTag[] = "ImGuiExample";
+
+// Forward declarations of helper functions
+static int ShowSoftKeyboardInput();
+static int PollUnicodeChars();
+static int GetAssetData(const char* filename, void** out_data);
+
+void init(struct android_app* app)
+{
+ if (g_Initialized)
+ return;
+
+ g_App = app;
+ ANativeWindow_acquire(g_App->window);
+
+ // Initialize EGL
+ // This is mostly boilerplate code for EGL...
+ {
+ g_EglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (g_EglDisplay == EGL_NO_DISPLAY)
+ __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglGetDisplay(EGL_DEFAULT_DISPLAY) returned EGL_NO_DISPLAY");
+
+ if (eglInitialize(g_EglDisplay, 0, 0) != EGL_TRUE)
+ __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglInitialize() returned with an error");
+
+ const EGLint egl_attributes[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
+ EGLint num_configs = 0;
+ if (eglChooseConfig(g_EglDisplay, egl_attributes, nullptr, 0, &num_configs) != EGL_TRUE)
+ __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglChooseConfig() returned with an error");
+ if (num_configs == 0)
+ __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglChooseConfig() returned 0 matching config");
+
+ // Get the first matching config
+ EGLConfig egl_config;
+ eglChooseConfig(g_EglDisplay, egl_attributes, &egl_config, 1, &num_configs);
+ EGLint egl_format;
+ eglGetConfigAttrib(g_EglDisplay, egl_config, EGL_NATIVE_VISUAL_ID, &egl_format);
+ ANativeWindow_setBuffersGeometry(g_App->window, 0, 0, egl_format);
+
+ const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
+ g_EglContext = eglCreateContext(g_EglDisplay, egl_config, EGL_NO_CONTEXT, egl_context_attributes);
+
+ if (g_EglContext == EGL_NO_CONTEXT)
+ __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", "eglCreateContext() returned EGL_NO_CONTEXT");
+
+ g_EglSurface = eglCreateWindowSurface(g_EglDisplay, egl_config, g_App->window, NULL);
+ eglMakeCurrent(g_EglDisplay, g_EglSurface, g_EglSurface, g_EglContext);
+ }
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Disable loading/saving of .ini file from disk.
+ // FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android.
+ io.IniFilename = NULL;
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplAndroid_Init(g_App->window);
+ ImGui_ImplOpenGL3_Init("#version 300 es");
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ // - Android: The TTF files have to be placed into the assets/ directory (android/app/src/main/assets), we use our GetAssetData() helper to retrieve them.
+
+ // We load the default font with increased size to improve readability on many devices with "high" DPI.
+ // FIXME: Put some effort into DPI awareness.
+ // Important: when calling AddFontFromMemoryTTF(), ownership of font_data is transfered by Dear ImGui by default (deleted is handled by Dear ImGui), unless we set FontDataOwnedByAtlas=false in ImFontConfig
+ ImFontConfig font_cfg;
+ font_cfg.SizePixels = 22.0f;
+ io.Fonts->AddFontDefault(&font_cfg);
+ //void* font_data;
+ //int font_data_size;
+ //ImFont* font;
+ //font_data_size = GetAssetData("Roboto-Medium.ttf", &font_data);
+ //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
+ //IM_ASSERT(font != NULL);
+ //font_data_size = GetAssetData("Cousine-Regular.ttf", &font_data);
+ //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 15.0f);
+ //IM_ASSERT(font != NULL);
+ //font_data_size = GetAssetData("DroidSans.ttf", &font_data);
+ //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 16.0f);
+ //IM_ASSERT(font != NULL);
+ //font_data_size = GetAssetData("ProggyTiny.ttf", &font_data);
+ //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 10.0f);
+ //IM_ASSERT(font != NULL);
+ //font_data_size = GetAssetData("ArialUni.ttf", &font_data);
+ //font = io.Fonts->AddFontFromMemoryTTF(font_data, font_data_size, 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Arbitrary scale-up
+ // FIXME: Put some effort into DPI awareness
+ ImGui::GetStyle().ScaleAllSizes(3.0f);
+
+ g_Initialized = true;
+}
+
+void tick()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ if (g_EglDisplay == EGL_NO_DISPLAY)
+ return;
+
+ // Our state
+ static bool show_demo_window = true;
+ static bool show_another_window = false;
+ static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Poll Unicode characters via JNI
+ // FIXME: do not call this every frame because of JNI overhead
+ PollUnicodeChars();
+
+ // Open on-screen (soft) input if requested by Dear ImGui
+ static bool WantTextInputLast = false;
+ if (io.WantTextInput && !WantTextInputLast)
+ ShowSoftKeyboardInput();
+ WantTextInputLast = io.WantTextInput;
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplAndroid_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+ eglSwapBuffers(g_EglDisplay, g_EglSurface);
+}
+
+void shutdown()
+{
+ if (!g_Initialized)
+ return;
+
+ // Cleanup
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplAndroid_Shutdown();
+ ImGui::DestroyContext();
+
+ if (g_EglDisplay != EGL_NO_DISPLAY)
+ {
+ eglMakeCurrent(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+ if (g_EglContext != EGL_NO_CONTEXT)
+ eglDestroyContext(g_EglDisplay, g_EglContext);
+
+ if (g_EglSurface != EGL_NO_SURFACE)
+ eglDestroySurface(g_EglDisplay, g_EglSurface);
+
+ eglTerminate(g_EglDisplay);
+ }
+
+ g_EglDisplay = EGL_NO_DISPLAY;
+ g_EglContext = EGL_NO_CONTEXT;
+ g_EglSurface = EGL_NO_SURFACE;
+ ANativeWindow_release(g_App->window);
+
+ g_Initialized = false;
+}
+
+static void handleAppCmd(struct android_app* app, int32_t appCmd)
+{
+ switch (appCmd)
+ {
+ case APP_CMD_SAVE_STATE:
+ break;
+ case APP_CMD_INIT_WINDOW:
+ init(app);
+ break;
+ case APP_CMD_TERM_WINDOW:
+ shutdown();
+ break;
+ case APP_CMD_GAINED_FOCUS:
+ break;
+ case APP_CMD_LOST_FOCUS:
+ break;
+ }
+}
+
+static int32_t handleInputEvent(struct android_app* app, AInputEvent* inputEvent)
+{
+ return ImGui_ImplAndroid_HandleInputEvent(inputEvent);
+}
+
+void android_main(struct android_app* app)
+{
+ app->onAppCmd = handleAppCmd;
+ app->onInputEvent = handleInputEvent;
+
+ while (true)
+ {
+ int out_events;
+ struct android_poll_source* out_data;
+
+ // Poll all events. If the app is not visible, this loop blocks until g_Initialized == true.
+ while (ALooper_pollAll(g_Initialized ? 0 : -1, NULL, &out_events, (void**)&out_data) >= 0)
+ {
+ // Process one event
+ if (out_data != NULL)
+ out_data->process(app, out_data);
+
+ // Exit the app by returning from within the infinite loop
+ if (app->destroyRequested != 0)
+ {
+ // shutdown() should have been called already while processing the
+ // app command APP_CMD_TERM_WINDOW. But we play save here
+ if (!g_Initialized)
+ shutdown();
+
+ return;
+ }
+ }
+
+ // Initiate a new frame
+ tick();
+ }
+}
+
+// Unfortunately, there is no way to show the on-screen input from native code.
+// Therefore, we call ShowSoftKeyboardInput() of the main activity implemented in MainActivity.kt via JNI.
+static int ShowSoftKeyboardInput()
+{
+ JavaVM* java_vm = g_App->activity->vm;
+ JNIEnv* java_env = NULL;
+
+ jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
+ if (jni_return == JNI_ERR)
+ return -1;
+
+ jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
+ if (jni_return != JNI_OK)
+ return -2;
+
+ jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
+ if (native_activity_clazz == NULL)
+ return -3;
+
+ jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "showSoftInput", "()V");
+ if (method_id == NULL)
+ return -4;
+
+ java_env->CallVoidMethod(g_App->activity->clazz, method_id);
+
+ jni_return = java_vm->DetachCurrentThread();
+ if (jni_return != JNI_OK)
+ return -5;
+
+ return 0;
+}
+
+// Unfortunately, the native KeyEvent implementation has no getUnicodeChar() function.
+// Therefore, we implement the processing of KeyEvents in MainActivity.kt and poll
+// the resulting Unicode characters here via JNI and send them to Dear ImGui.
+static int PollUnicodeChars()
+{
+ JavaVM* java_vm = g_App->activity->vm;
+ JNIEnv* java_env = NULL;
+
+ jint jni_return = java_vm->GetEnv((void**)&java_env, JNI_VERSION_1_6);
+ if (jni_return == JNI_ERR)
+ return -1;
+
+ jni_return = java_vm->AttachCurrentThread(&java_env, NULL);
+ if (jni_return != JNI_OK)
+ return -2;
+
+ jclass native_activity_clazz = java_env->GetObjectClass(g_App->activity->clazz);
+ if (native_activity_clazz == NULL)
+ return -3;
+
+ jmethodID method_id = java_env->GetMethodID(native_activity_clazz, "pollUnicodeChar", "()I");
+ if (method_id == NULL)
+ return -4;
+
+ // Send the actual characters to Dear ImGui
+ ImGuiIO& io = ImGui::GetIO();
+ jint unicode_character;
+ while ((unicode_character = java_env->CallIntMethod(g_App->activity->clazz, method_id)) != 0)
+ io.AddInputCharacter(unicode_character);
+
+ jni_return = java_vm->DetachCurrentThread();
+ if (jni_return != JNI_OK)
+ return -5;
+
+ return 0;
+}
+
+// Helper to retrieve data placed into the assets/ directory (android/app/src/main/assets)
+static int GetAssetData(const char* filename, void** outData)
+{
+ int num_bytes = 0;
+ AAsset* asset_descriptor = AAssetManager_open(g_App->activity->assetManager, filename, AASSET_MODE_BUFFER);
+ if (asset_descriptor)
+ {
+ num_bytes = AAsset_getLength(asset_descriptor);
+ *outData = IM_ALLOC(num_bytes);
+ int64_t num_bytes_read = AAsset_read(asset_descriptor, *outData, num_bytes);
+ AAsset_close(asset_descriptor);
+ IM_ASSERT(num_bytes_read == num_bytes);
+ }
+ return num_bytes;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/README.md b/Client/ThirdParty/imgui/examples/example_apple_metal/README.md
new file mode 100644
index 0000000..c13df2f
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/README.md
@@ -0,0 +1,10 @@
+# iOS / OSX Metal example
+
+## Introduction
+
+This example shows how to integrate Dear ImGui with Metal. It is based on the "cross-platform" game template provided with Xcode as of Xcode 9.
+
+Consider basing your work off the example_glfw_metal/ or example_sdl_metal/ examples. They are better supported and will be portable unlike this one.
+
+
+
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj b/Client/ThirdParty/imgui/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..040fcd6
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/example_apple_metal.xcodeproj/project.pbxproj
@@ -0,0 +1,499 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
+ 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
+ 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
+ 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */; };
+ 8309BDA5253CCC070045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; };
+ 8309BDA8253CCC080045E2A1 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDA0253CCBC10045E2A1 /* main.mm */; };
+ 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */; };
+ 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */; };
+ 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */; };
+ 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */; };
+ 8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */; };
+ 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */; };
+ 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E420EB46B900295997 /* Metal.framework */; };
+ 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9E620EB46BD00295997 /* MetalKit.framework */; };
+ 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EA20EB471700295997 /* MetalKit.framework */; };
+ 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83BBE9EB20EB471700295997 /* Metal.framework */; };
+ 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; };
+ 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0120EB54E700295997 /* imgui_draw.cpp */; };
+ 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; };
+ 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0220EB54E700295997 /* imgui_demo.cpp */; };
+ 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; };
+ 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83BBEA0320EB54E700295997 /* imgui.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
+ 07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
+ 5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
+ 8307E7C420E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8307E7DA20E9F9C900473790 /* example_apple_metal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_apple_metal.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+ 8309BDA0253CCBC10045E2A1 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
+ 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_metal.mm; path = ../../backends/imgui_impl_metal.mm; sourceTree = "<group>"; };
+ 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../backends/imgui_impl_osx.mm; sourceTree = "<group>"; };
+ 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
+ 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
+ 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
+ 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainMenu.storyboard; sourceTree = "<group>"; };
+ 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-macOS.plist"; sourceTree = "<group>"; };
+ 83BBE9E420EB46B900295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/Metal.framework; sourceTree = DEVELOPER_DIR; };
+ 83BBE9E620EB46BD00295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/MetalKit.framework; sourceTree = DEVELOPER_DIR; };
+ 83BBE9E820EB46C100295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.4.sdk/System/Library/Frameworks/ModelIO.framework; sourceTree = DEVELOPER_DIR; };
+ 83BBE9EA20EB471700295997 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; };
+ 83BBE9EB20EB471700295997 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
+ 83BBE9EE20EB471C00295997 /* ModelIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ModelIO.framework; path = System/Library/Frameworks/ModelIO.framework; sourceTree = SDKROOT; };
+ 83BBEA0020EB54E700295997 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
+ 83BBEA0120EB54E700295997 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
+ 83BBEA0220EB54E700295997 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = "<group>"; };
+ 83BBEA0320EB54E700295997 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
+ 83BBEA0420EB54E700295997 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8307E7C120E9F9C900473790 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8309BD8F253CCAAA0045E2A1 /* UIKit.framework in Frameworks */,
+ 83BBE9E720EB46BD00295997 /* MetalKit.framework in Frameworks */,
+ 83BBE9E520EB46B900295997 /* Metal.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8307E7D720E9F9C900473790 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */,
+ 83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */,
+ 83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 8307E7B520E9F9C700473790 = {
+ isa = PBXGroup;
+ children = (
+ 83BBE9F020EB544400295997 /* imgui */,
+ 8309BD9E253CCBA70045E2A1 /* example */,
+ 8307E7C520E9F9C900473790 /* Products */,
+ 83BBE9E320EB46B800295997 /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ 8307E7C520E9F9C900473790 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8307E7C420E9F9C900473790 /* example_apple_metal.app */,
+ 8307E7DA20E9F9C900473790 /* example_apple_metal.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 8309BD9E253CCBA70045E2A1 /* example */ = {
+ isa = PBXGroup;
+ children = (
+ 8309BDF6253CDAAE0045E2A1 /* iOS */,
+ 8309BDF9253CDAAE0045E2A1 /* macOS */,
+ 8309BDA0253CCBC10045E2A1 /* main.mm */,
+ );
+ name = example;
+ sourceTree = "<group>";
+ };
+ 8309BDF6253CDAAE0045E2A1 /* iOS */ = {
+ isa = PBXGroup;
+ children = (
+ 8309BDF7253CDAAE0045E2A1 /* LaunchScreen.storyboard */,
+ 8309BDF8253CDAAE0045E2A1 /* Info-iOS.plist */,
+ );
+ path = iOS;
+ sourceTree = "<group>";
+ };
+ 8309BDF9253CDAAE0045E2A1 /* macOS */ = {
+ isa = PBXGroup;
+ children = (
+ 8309BDFA253CDAAE0045E2A1 /* MainMenu.storyboard */,
+ 8309BDFB253CDAAE0045E2A1 /* Info-macOS.plist */,
+ );
+ path = macOS;
+ sourceTree = "<group>";
+ };
+ 83BBE9E320EB46B800295997 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 8309BDC5253CCCFE0045E2A1 /* AppKit.framework */,
+ 8309BD8E253CCAAA0045E2A1 /* UIKit.framework */,
+ 83BBE9EE20EB471C00295997 /* ModelIO.framework */,
+ 83BBE9EB20EB471700295997 /* Metal.framework */,
+ 83BBE9EA20EB471700295997 /* MetalKit.framework */,
+ 83BBE9E820EB46C100295997 /* ModelIO.framework */,
+ 83BBE9E620EB46BD00295997 /* MetalKit.framework */,
+ 83BBE9E420EB46B900295997 /* Metal.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 83BBE9F020EB544400295997 /* imgui */ = {
+ isa = PBXGroup;
+ children = (
+ 5079822D257677DB0038A28D /* imgui_tables.cpp */,
+ 8309BDB5253CCC9D0045E2A1 /* imgui_impl_metal.mm */,
+ 8309BDB6253CCC9D0045E2A1 /* imgui_impl_osx.mm */,
+ 83BBEA0420EB54E700295997 /* imconfig.h */,
+ 83BBEA0320EB54E700295997 /* imgui.cpp */,
+ 83BBEA0020EB54E700295997 /* imgui.h */,
+ 83BBEA0220EB54E700295997 /* imgui_demo.cpp */,
+ 83BBEA0120EB54E700295997 /* imgui_draw.cpp */,
+ 07A82ED62139413C0078D120 /* imgui_internal.h */,
+ 07A82ED72139413C0078D120 /* imgui_widgets.cpp */,
+ );
+ name = imgui;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8307E7C320E9F9C900473790 /* example_apple_metal_ios */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8307E7F020E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_ios" */;
+ buildPhases = (
+ 8307E7C020E9F9C900473790 /* Sources */,
+ 8307E7C120E9F9C900473790 /* Frameworks */,
+ 8307E7C220E9F9C900473790 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = example_apple_metal_ios;
+ productName = "imguiex iOS";
+ productReference = 8307E7C420E9F9C900473790 /* example_apple_metal.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 8307E7D920E9F9C900473790 /* example_apple_metal_macos */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8307E7F320E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_macos" */;
+ buildPhases = (
+ 8307E7D620E9F9C900473790 /* Sources */,
+ 8307E7D720E9F9C900473790 /* Frameworks */,
+ 8307E7D820E9F9C900473790 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = example_apple_metal_macos;
+ productName = "imguiex macOS";
+ productReference = 8307E7DA20E9F9C900473790 /* example_apple_metal.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 8307E7B620E9F9C700473790 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1200;
+ ORGANIZATIONNAME = "Warren Moore";
+ TargetAttributes = {
+ 8307E7C320E9F9C900473790 = {
+ CreatedOnToolsVersion = 9.4.1;
+ ProvisioningStyle = Automatic;
+ };
+ 8307E7D920E9F9C900473790 = {
+ CreatedOnToolsVersion = 9.4.1;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 8307E7B920E9F9C700473790 /* Build configuration list for PBXProject "example_apple_metal" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 8307E7B520E9F9C700473790;
+ productRefGroup = 8307E7C520E9F9C900473790 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8307E7C320E9F9C900473790 /* example_apple_metal_ios */,
+ 8307E7D920E9F9C900473790 /* example_apple_metal_macos */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8307E7C220E9F9C900473790 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8309BDFC253CDAB30045E2A1 /* LaunchScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8307E7D820E9F9C900473790 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8309BE04253CDAB60045E2A1 /* MainMenu.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8307E7C020E9F9C900473790 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8309BDBB253CCCAD0045E2A1 /* imgui_impl_metal.mm in Sources */,
+ 83BBEA0920EB54E700295997 /* imgui.cpp in Sources */,
+ 83BBEA0720EB54E700295997 /* imgui_demo.cpp in Sources */,
+ 83BBEA0520EB54E700295997 /* imgui_draw.cpp in Sources */,
+ 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */,
+ 07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */,
+ 8309BDA5253CCC070045E2A1 /* main.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8307E7D620E9F9C900473790 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8309BDBE253CCCB60045E2A1 /* imgui_impl_metal.mm in Sources */,
+ 8309BDBF253CCCB60045E2A1 /* imgui_impl_osx.mm in Sources */,
+ 83BBEA0A20EB54E700295997 /* imgui.cpp in Sources */,
+ 83BBEA0820EB54E700295997 /* imgui_demo.cpp in Sources */,
+ 83BBEA0620EB54E700295997 /* imgui_draw.cpp in Sources */,
+ 5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */,
+ 07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */,
+ 8309BDA8253CCC080045E2A1 /* main.mm in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 8307E7EE20E9F9C900473790 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ };
+ name = Debug;
+ };
+ 8307E7EF20E9F9C900473790 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ };
+ name = Release;
+ };
+ 8307E7F120E9F9C900473790 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios";
+ PRODUCT_NAME = example_apple_metal;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
+ };
+ name = Debug;
+ };
+ 8307E7F220E9F9C900473790 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = "";
+ INFOPLIST_FILE = "$(SRCROOT)/iOS/Info-iOS.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-ios";
+ PRODUCT_NAME = example_apple_metal;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 8307E7F420E9F9C900473790 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "-";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = "";
+ INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos";
+ PRODUCT_NAME = example_apple_metal;
+ SDKROOT = macosx;
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
+ };
+ name = Debug;
+ };
+ 8307E7F520E9F9C900473790 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_IDENTITY = "-";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ DEVELOPMENT_TEAM = "";
+ INFOPLIST_FILE = "$(SRCROOT)/macOS/Info-macOS.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.apple-metal-macos";
+ PRODUCT_NAME = example_apple_metal;
+ SDKROOT = macosx;
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../**";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 8307E7B920E9F9C700473790 /* Build configuration list for PBXProject "example_apple_metal" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8307E7EE20E9F9C900473790 /* Debug */,
+ 8307E7EF20E9F9C900473790 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8307E7F020E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_ios" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8307E7F120E9F9C900473790 /* Debug */,
+ 8307E7F220E9F9C900473790 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8307E7F320E9F9C900473790 /* Build configuration list for PBXNativeTarget "example_apple_metal_macos" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8307E7F420E9F9C900473790 /* Debug */,
+ 8307E7F520E9F9C900473790 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 8307E7B620E9F9C700473790 /* Project object */;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/iOS/Info-iOS.plist b/Client/ThirdParty/imgui/examples/example_apple_metal/iOS/Info-iOS.plist
new file mode 100644
index 0000000..93ef078
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/iOS/Info-iOS.plist
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>imgui</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ <string>metal</string>
+ </array>
+ <key>UIRequiresFullScreen</key>
+ <true/>
+ <key>UIStatusBarHidden</key>
+ <true/>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+</dict>
+</plist>
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/iOS/LaunchScreen.storyboard b/Client/ThirdParty/imgui/examples/example_apple_metal/iOS/LaunchScreen.storyboard
new file mode 100644
index 0000000..12c52cf
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/iOS/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+ <device id="retina6_1" orientation="portrait" appearance="light"/>
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <scenes>
+ <!--View Controller-->
+ <scene sceneID="EHf-IW-A2E">
+ <objects>
+ <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+ <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+ <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
+ <color key="backgroundColor" red="0.27843137254901962" green="0.36078431372549019" blue="0.50196078431372548" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
+ </view>
+ </viewController>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="53" y="375"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/macOS/Info-macOS.plist b/Client/ThirdParty/imgui/examples/example_apple_metal/macOS/Info-macOS.plist
new file mode 100644
index 0000000..6f4a2b2
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/macOS/Info-macOS.plist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>imgui</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+ <key>NSMainStoryboardFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/macOS/MainMenu.storyboard b/Client/ThirdParty/imgui/examples/example_apple_metal/macOS/MainMenu.storyboard
new file mode 100644
index 0000000..38ad432
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/macOS/MainMenu.storyboard
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17156"/>
+ </dependencies>
+ <scenes>
+ <!--Application-->
+ <scene sceneID="JPo-4y-FX3">
+ <objects>
+ <application id="hnw-xV-0zn" sceneMemberID="viewController">
+ <menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+ <items>
+ <menuItem title="ImGui" id="1Xt-HY-uBw">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="ImGui" systemMenu="apple" id="uQy-DD-JDr">
+ <items>
+ <menuItem title="Services" id="NMo-om-nkz">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
+ <menuItem title="Hide" keyEquivalent="h" id="Olw-nP-bQN">
+ <connections>
+ <action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="Kd2-mp-pUS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+ <menuItem title="Quit" keyEquivalent="q" id="4sb-4s-VLi">
+ <connections>
+ <action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="View" id="H8h-7b-M4v">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="View" id="HyV-fh-RgO">
+ <items>
+ <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
+ <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
+ <connections>
+ <action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="aUF-d1-5bR">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+ <connections>
+ <action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="R4o-n2-Eq4">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ <connections>
+ <outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
+ </connections>
+ </application>
+ <customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
+ <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
+ <customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
+ </objects>
+ <point key="canvasLocation" x="-362" y="-38"/>
+ </scene>
+ </scenes>
+</document>
diff --git a/Client/ThirdParty/imgui/examples/example_apple_metal/main.mm b/Client/ThirdParty/imgui/examples/example_apple_metal/main.mm
new file mode 100644
index 0000000..5d4b771
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_metal/main.mm
@@ -0,0 +1,356 @@
+// Dear ImGui: standalone example application for OSX + Metal.
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#import <Foundation/Foundation.h>
+
+#if TARGET_OS_OSX
+#import <Cocoa/Cocoa.h>
+#else
+#import <UIKit/UIKit.h>
+#endif
+
+#import <Metal/Metal.h>
+#import <MetalKit/MetalKit.h>
+
+#include "imgui.h"
+#include "imgui_impl_metal.h"
+#if TARGET_OS_OSX
+#include "imgui_impl_osx.h"
+@interface AppViewController : NSViewController
+@end
+#else
+@interface AppViewController : UIViewController
+@end
+#endif
+
+@interface AppViewController () <MTKViewDelegate>
+@property (nonatomic, readonly) MTKView *mtkView;
+@property (nonatomic, strong) id <MTLDevice> device;
+@property (nonatomic, strong) id <MTLCommandQueue> commandQueue;
+@end
+
+//-----------------------------------------------------------------------------------
+// AppViewController
+//-----------------------------------------------------------------------------------
+
+@implementation AppViewController
+
+-(instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+
+ _device = MTLCreateSystemDefaultDevice();
+ _commandQueue = [_device newCommandQueue];
+
+ if (!self.device)
+ {
+ NSLog(@"Metal is not supported");
+ abort();
+ }
+
+ // Setup Dear ImGui context
+ // FIXME: This example doesn't have proper cleanup...
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Renderer backend
+ ImGui_ImplMetal_Init(_device);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.txt' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ return self;
+}
+
+-(MTKView *)mtkView
+{
+ return (MTKView *)self.view;
+}
+
+-(void)loadView
+{
+ self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)];
+}
+
+-(void)viewDidLoad
+{
+ [super viewDidLoad];
+
+ self.mtkView.device = self.device;
+ self.mtkView.delegate = self;
+
+#if TARGET_OS_OSX
+ // Add a tracking area in order to receive mouse events whenever the mouse is within the bounds of our view
+ NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect
+ options:NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
+ owner:self
+ userInfo:nil];
+ [self.view addTrackingArea:trackingArea];
+
+ // If we want to receive key events, we either need to be in the responder chain of the key view,
+ // or else we can install a local monitor. The consequence of this heavy-handed approach is that
+ // we receive events for all controls, not just Dear ImGui widgets. If we had native controls in our
+ // window, we'd want to be much more careful than just ingesting the complete event stream.
+ // To match the behavior of other backends, we pass every event down to the OS.
+ NSEventMask eventMask = NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged;
+ [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event)
+ {
+ ImGui_ImplOSX_HandleEvent(event, self.view);
+ return event;
+ }];
+
+ ImGui_ImplOSX_Init();
+
+#endif
+}
+
+-(void)drawInMTKView:(MTKView*)view
+{
+ ImGuiIO& io = ImGui::GetIO();
+ io.DisplaySize.x = view.bounds.size.width;
+ io.DisplaySize.y = view.bounds.size.height;
+
+#if TARGET_OS_OSX
+ CGFloat framebufferScale = view.window.screen.backingScaleFactor ?: NSScreen.mainScreen.backingScaleFactor;
+#else
+ CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale;
+#endif
+ io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale);
+
+ io.DeltaTime = 1 / float(view.preferredFramesPerSecond ?: 60);
+
+ id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
+
+ MTLRenderPassDescriptor* renderPassDescriptor = view.currentRenderPassDescriptor;
+ if (renderPassDescriptor == nil)
+ {
+ [commandBuffer commit];
+ return;
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplMetal_NewFrame(renderPassDescriptor);
+#if TARGET_OS_OSX
+ ImGui_ImplOSX_NewFrame(view);
+#endif
+ ImGui::NewFrame();
+
+ // Our state (make them static = more or less global) as a convenience to keep the example terse.
+ static bool show_demo_window = true;
+ static bool show_another_window = false;
+ static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+
+ renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
+ [renderEncoder pushDebugGroup:@"Dear ImGui rendering"];
+ ImGui_ImplMetal_RenderDrawData(draw_data, commandBuffer, renderEncoder);
+ [renderEncoder popDebugGroup];
+ [renderEncoder endEncoding];
+
+ // Present
+ [commandBuffer presentDrawable:view.currentDrawable];
+ [commandBuffer commit];
+}
+
+-(void)mtkView:(MTKView*)view drawableSizeWillChange:(CGSize)size
+{
+}
+
+//-----------------------------------------------------------------------------------
+// Input processing
+//-----------------------------------------------------------------------------------
+
+#if TARGET_OS_OSX
+
+// Forward Mouse/Keyboard events to Dear ImGui OSX backend.
+// Other events are registered via addLocalMonitorForEventsMatchingMask()
+-(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)rightMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)otherMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)rightMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)otherMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)mouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)mouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)rightMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)rightMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)otherMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)otherMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+-(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self.view); }
+
+#else
+
+// This touch mapping is super cheesy/hacky. We treat any touch on the screen
+// as if it were a depressed left mouse button, and we don't bother handling
+// multitouch correctly at all. This causes the "cursor" to behave very erratically
+// when there are multiple active touches. But for demo purposes, single-touch
+// interaction actually works surprisingly well.
+-(void)updateIOWithTouchEvent:(UIEvent *)event
+{
+ UITouch *anyTouch = event.allTouches.anyObject;
+ CGPoint touchLocation = [anyTouch locationInView:self.view];
+ ImGuiIO &io = ImGui::GetIO();
+ io.MousePos = ImVec2(touchLocation.x, touchLocation.y);
+
+ BOOL hasActiveTouch = NO;
+ for (UITouch *touch in event.allTouches)
+ {
+ if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
+ {
+ hasActiveTouch = YES;
+ break;
+ }
+ }
+ io.MouseDown[0] = hasActiveTouch;
+}
+
+-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
+-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
+-(void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
+-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self updateIOWithTouchEvent:event]; }
+
+#endif
+
+@end
+
+//-----------------------------------------------------------------------------------
+// AppDelegate
+//-----------------------------------------------------------------------------------
+
+#if TARGET_OS_OSX
+
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+@property (nonatomic, strong) NSWindow *window;
+@end
+
+@implementation AppDelegate
+
+-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
+{
+ return YES;
+}
+
+-(instancetype)init
+{
+ if (self = [super init])
+ {
+ NSViewController *rootViewController = [[AppViewController alloc] initWithNibName:nil bundle:nil];
+ self.window = [[NSWindow alloc] initWithContentRect:NSZeroRect
+ styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ self.window.contentViewController = rootViewController;
+ [self.window orderFront:self];
+ [self.window center];
+ [self.window becomeKeyWindow];
+ }
+ return self;
+}
+
+@end
+
+#else
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (strong, nonatomic) UIWindow *window;
+@end
+
+@implementation AppDelegate
+
+-(BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,id> *)launchOptions
+{
+ UIViewController *rootViewController = [[AppViewController alloc] init];
+ self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
+ self.window.rootViewController = rootViewController;
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+@end
+
+#endif
+
+//-----------------------------------------------------------------------------------
+// Application main() function
+//-----------------------------------------------------------------------------------
+
+#if TARGET_OS_OSX
+
+int main(int argc, const char * argv[])
+{
+ return NSApplicationMain(argc, argv);
+}
+
+#else
+
+int main(int argc, char * argv[])
+{
+ @autoreleasepool
+ {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
+
+#endif
diff --git a/Client/ThirdParty/imgui/examples/example_apple_opengl2/example_apple_opengl2.xcodeproj/project.pbxproj b/Client/ThirdParty/imgui/examples/example_apple_opengl2/example_apple_opengl2.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..82fb267
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_opengl2/example_apple_opengl2.xcodeproj/project.pbxproj
@@ -0,0 +1,328 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82EDA213941D00078D120 /* imgui_widgets.cpp */; };
+ 4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; };
+ 4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */; };
+ 4080A9AD20B0343C0036BA46 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */; };
+ 4080A9AE20B0343C0036BA46 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9A720B0343C0036BA46 /* imgui.cpp */; };
+ 4080A9AF20B0343C0036BA46 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */; };
+ 4080A9B020B0347A0036BA46 /* imgui_impl_osx.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */; };
+ 4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4080A9B220B034E40036BA46 /* Cocoa.framework */; };
+ 4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4080A9B420B034EA0036BA46 /* OpenGL.framework */; };
+ 50798230257677FD0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822F257677FC0038A28D /* imgui_tables.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 4080A96920B029B00036BA46 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 07A82EDA213941D00078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
+ 4080A96B20B029B00036BA46 /* example_osx_opengl2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl2; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
+ 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_impl_opengl2.cpp; path = ../../backends/imgui_impl_opengl2.cpp; sourceTree = "<group>"; };
+ 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = imgui_impl_osx.mm; path = ../../backends/imgui_impl_osx.mm; sourceTree = "<group>"; };
+ 4080A9A020B034280036BA46 /* imgui_impl_opengl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_opengl2.h; path = ../../backends/imgui_impl_opengl2.h; sourceTree = "<group>"; };
+ 4080A9A120B034280036BA46 /* imgui_impl_osx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_impl_osx.h; path = ../../backends/imgui_impl_osx.h; sourceTree = "<group>"; };
+ 4080A9A520B0343C0036BA46 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
+ 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../imgui_demo.cpp; sourceTree = "<group>"; };
+ 4080A9A720B0343C0036BA46 /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = "<group>"; };
+ 4080A9A820B0343C0036BA46 /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = "<group>"; };
+ 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = "<group>"; };
+ 4080A9AC20B0343C0036BA46 /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = "<group>"; };
+ 4080A9B220B034E40036BA46 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
+ 4080A9B420B034EA0036BA46 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
+ 5079822F257677FC0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 4080A96820B029B00036BA46 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */,
+ 4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 4080A96220B029B00036BA46 = {
+ isa = PBXGroup;
+ children = (
+ 5079822F257677FC0038A28D /* imgui_tables.cpp */,
+ 4080A9AC20B0343C0036BA46 /* imconfig.h */,
+ 4080A9A720B0343C0036BA46 /* imgui.cpp */,
+ 4080A9A820B0343C0036BA46 /* imgui.h */,
+ 07A82EDA213941D00078D120 /* imgui_widgets.cpp */,
+ 4080A9A620B0343C0036BA46 /* imgui_demo.cpp */,
+ 4080A9AA20B0343C0036BA46 /* imgui_draw.cpp */,
+ 4080A9A520B0343C0036BA46 /* imgui_internal.h */,
+ 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */,
+ 4080A9A020B034280036BA46 /* imgui_impl_opengl2.h */,
+ 4080A9A120B034280036BA46 /* imgui_impl_osx.h */,
+ 4080A99F20B034280036BA46 /* imgui_impl_osx.mm */,
+ 4080A98A20B02CD90036BA46 /* main.mm */,
+ 4080A96C20B029B00036BA46 /* Products */,
+ 4080A9B120B034E40036BA46 /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ 4080A96C20B029B00036BA46 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 4080A96B20B029B00036BA46 /* example_osx_opengl2 */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 4080A9B120B034E40036BA46 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 4080A9B420B034EA0036BA46 /* OpenGL.framework */,
+ 4080A9B220B034E40036BA46 /* Cocoa.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 4080A96A20B029B00036BA46 /* example_osx_opengl2 */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4080A97220B029B00036BA46 /* Build configuration list for PBXNativeTarget "example_osx_opengl2" */;
+ buildPhases = (
+ 4080A96720B029B00036BA46 /* Sources */,
+ 4080A96820B029B00036BA46 /* Frameworks */,
+ 4080A96920B029B00036BA46 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = example_osx_opengl2;
+ productName = example_osx_opengl2;
+ productReference = 4080A96B20B029B00036BA46 /* example_osx_opengl2 */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 4080A96320B029B00036BA46 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0930;
+ ORGANIZATIONNAME = ImGui;
+ TargetAttributes = {
+ 4080A96A20B029B00036BA46 = {
+ CreatedOnToolsVersion = 9.3.1;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 4080A96620B029B00036BA46 /* Build configuration list for PBXProject "example_apple_opengl2" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 4080A96220B029B00036BA46;
+ productRefGroup = 4080A96C20B029B00036BA46 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 4080A96A20B029B00036BA46 /* example_osx_opengl2 */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 4080A96720B029B00036BA46 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 4080A99820B02D340036BA46 /* main.mm in Sources */,
+ 4080A9AD20B0343C0036BA46 /* imgui_demo.cpp in Sources */,
+ 4080A9AF20B0343C0036BA46 /* imgui_draw.cpp in Sources */,
+ 4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */,
+ 4080A9B020B0347A0036BA46 /* imgui_impl_osx.mm in Sources */,
+ 4080A9AE20B0343C0036BA46 /* imgui.cpp in Sources */,
+ 50798230257677FD0038A28D /* imgui_tables.cpp in Sources */,
+ 07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 4080A97020B029B00036BA46 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 4080A97120B029B00036BA46 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.13;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 4080A97320B029B00036BA46 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = ../..;
+ };
+ name = Debug;
+ };
+ 4080A97420B029B00036BA46 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = ../..;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4080A96620B029B00036BA46 /* Build configuration list for PBXProject "example_apple_opengl2" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4080A97020B029B00036BA46 /* Debug */,
+ 4080A97120B029B00036BA46 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4080A97220B029B00036BA46 /* Build configuration list for PBXNativeTarget "example_osx_opengl2" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4080A97320B029B00036BA46 /* Debug */,
+ 4080A97420B029B00036BA46 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 4080A96320B029B00036BA46 /* Project object */;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_apple_opengl2/main.mm b/Client/ThirdParty/imgui/examples/example_apple_opengl2/main.mm
new file mode 100644
index 0000000..825c8a8
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_apple_opengl2/main.mm
@@ -0,0 +1,282 @@
+// Dear ImGui: standalone example application for OSX + OpenGL2, using legacy fixed pipeline
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#import <Cocoa/Cocoa.h>
+#import <OpenGL/gl.h>
+#import <OpenGL/glu.h>
+
+#include "imgui.h"
+#include "imgui_impl_opengl2.h"
+#include "imgui_impl_osx.h"
+
+//-----------------------------------------------------------------------------------
+// AppView
+//-----------------------------------------------------------------------------------
+
+@interface AppView : NSOpenGLView
+{
+ NSTimer* animationTimer;
+}
+@end
+
+@implementation AppView
+
+-(void)prepareOpenGL
+{
+ [super prepareOpenGL];
+
+#ifndef DEBUG
+ GLint swapInterval = 1;
+ [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
+ if (swapInterval == 0)
+ NSLog(@"Error: Cannot set swap interval.");
+#endif
+}
+
+-(void)initialize
+{
+ // Some events do not raise callbacks of AppView in some circumstances (for example when CMD key is held down).
+ // This monitor taps into global event stream and captures these events.
+ NSEventMask eventMask = NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged;
+ [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^NSEvent * _Nullable(NSEvent *event)
+ {
+ ImGui_ImplOSX_HandleEvent(event, self);
+ return event;
+ }];
+
+ // Setup Dear ImGui context
+ // FIXME: This example doesn't have proper cleanup...
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplOSX_Init();
+ ImGui_ImplOpenGL2_Init();
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.txt' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+}
+
+-(void)updateAndDrawDemoView
+{
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL2_NewFrame();
+ ImGui_ImplOSX_NewFrame(self);
+ ImGui::NewFrame();
+
+ // Our state (make them static = more or less global) as a convenience to keep the example terse.
+ static bool show_demo_window = true;
+ static bool show_another_window = false;
+ static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+
+ [[self openGLContext] makeCurrentContext];
+ GLsizei width = (GLsizei)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
+ GLsizei height = (GLsizei)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
+ glViewport(0, 0, width, height);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ ImGui_ImplOpenGL2_RenderDrawData(draw_data);
+
+ // Present
+ [[self openGLContext] flushBuffer];
+
+ if (!animationTimer)
+ animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES];
+}
+
+-(void)reshape { [[self openGLContext] update]; [self updateAndDrawDemoView]; }
+-(void)drawRect:(NSRect)bounds { [self updateAndDrawDemoView]; }
+-(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; }
+-(BOOL)acceptsFirstResponder { return (YES); }
+-(BOOL)becomeFirstResponder { return (YES); }
+-(BOOL)resignFirstResponder { return (YES); }
+-(void)dealloc { animationTimer = nil; }
+
+//-----------------------------------------------------------------------------------
+// Input processing
+//-----------------------------------------------------------------------------------
+
+// Forward Mouse/Keyboard events to Dear ImGui OSX backend.
+// Other events are registered via addLocalMonitorForEventsMatchingMask()
+-(void)mouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)rightMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)otherMouseDown:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)mouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)rightMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)otherMouseUp:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)mouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)mouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)rightMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)rightMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)otherMouseMoved:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)otherMouseDragged:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+-(void)scrollWheel:(NSEvent *)event { ImGui_ImplOSX_HandleEvent(event, self); }
+
+@end
+
+//-----------------------------------------------------------------------------------
+// AppDelegate
+//-----------------------------------------------------------------------------------
+
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+@property (nonatomic, readonly) NSWindow* window;
+@end
+
+@implementation AppDelegate
+@synthesize window = _window;
+
+-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
+{
+ return YES;
+}
+
+-(NSWindow*)window
+{
+ if (_window != nil)
+ return (_window);
+
+ NSRect viewRect = NSMakeRect(100.0, 100.0, 100.0 + 1280.0, 100 + 720.0);
+
+ _window = [[NSWindow alloc] initWithContentRect:viewRect styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable|NSWindowStyleMaskClosable backing:NSBackingStoreBuffered defer:YES];
+ [_window setTitle:@"Dear ImGui OSX+OpenGL2 Example"];
+ [_window setAcceptsMouseMovedEvents:YES];
+ [_window setOpaque:YES];
+ [_window makeKeyAndOrderFront:NSApp];
+
+ return (_window);
+}
+
+-(void)setupMenu
+{
+ NSMenu* mainMenuBar = [[NSMenu alloc] init];
+ NSMenu* appMenu;
+ NSMenuItem* menuItem;
+
+ appMenu = [[NSMenu alloc] initWithTitle:@"Dear ImGui OSX+OpenGL2 Example"];
+ menuItem = [appMenu addItemWithTitle:@"Quit Dear ImGui OSX+OpenGL2 Example" action:@selector(terminate:) keyEquivalent:@"q"];
+ [menuItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];
+
+ menuItem = [[NSMenuItem alloc] init];
+ [menuItem setSubmenu:appMenu];
+
+ [mainMenuBar addItem:menuItem];
+
+ appMenu = nil;
+ [NSApp setMainMenu:mainMenuBar];
+}
+
+-(void)dealloc
+{
+ _window = nil;
+}
+
+-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+ // Make the application a foreground application (else it won't receive keyboard events)
+ ProcessSerialNumber psn = {0, kCurrentProcess};
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+
+ // Menu
+ [self setupMenu];
+
+ NSOpenGLPixelFormatAttribute attrs[] =
+ {
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFADepthSize, 32,
+ 0
+ };
+
+ NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
+ AppView* view = [[AppView alloc] initWithFrame:self.window.frame pixelFormat:format];
+ format = nil;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
+ [view setWantsBestResolutionOpenGLSurface:YES];
+#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ [self.window setContentView:view];
+
+ if ([view openGLContext] == nil)
+ NSLog(@"No OpenGL Context!");
+
+ [view initialize];
+}
+
+@end
+
+//-----------------------------------------------------------------------------------
+// Application main() function
+//-----------------------------------------------------------------------------------
+
+int main(int argc, const char* argv[])
+{
+ @autoreleasepool
+ {
+ NSApp = [NSApplication sharedApplication];
+ AppDelegate* delegate = [[AppDelegate alloc] init];
+ [[NSApplication sharedApplication] setDelegate:delegate];
+ [NSApp run];
+ }
+ return NSApplicationMain(argc, argv);
+}
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/Makefile b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/Makefile
new file mode 100644
index 0000000..b2933e1
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/Makefile
@@ -0,0 +1,91 @@
+#
+# Makefile to use with emscripten
+# See https://emscripten.org/docs/getting_started/downloads.html
+# for installation instructions.
+#
+# This Makefile assumes you have loaded emscripten's environment.
+# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
+#
+# Running `make` will produce three files:
+# - web/index.html
+# - web/index.js
+# - web/index.wasm
+#
+# All three are needed to run the demo.
+
+CC = emcc
+CXX = em++
+WEB_DIR = web
+EXE = $(WEB_DIR)/index.html
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+CPPFLAGS =
+LDFLAGS =
+EMS =
+
+##---------------------------------------------------------------------
+## EMSCRIPTEN OPTIONS
+##---------------------------------------------------------------------
+
+# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
+EMS += -s USE_SDL=2
+EMS += -s DISABLE_EXCEPTION_CATCHING=1
+LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
+
+# Uncomment next line to fix possible rendering bugs with Emscripten version older then 1.39.0 (https://github.com/ocornut/imgui/issues/2877)
+#EMS += -s BINARYEN_TRAP_MODE=clamp
+#EMS += -s SAFE_HEAP=1 ## Adds overhead
+
+# Emscripten allows preloading a file or folder to be accessible at runtime.
+# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
+# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
+# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
+USE_FILE_SYSTEM ?= 0
+ifeq ($(USE_FILE_SYSTEM), 0)
+LDFLAGS += -s NO_FILESYSTEM=1
+CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
+endif
+ifeq ($(USE_FILE_SYSTEM), 1)
+LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
+endif
+
+##---------------------------------------------------------------------
+## FINAL BUILD FLAGS
+##---------------------------------------------------------------------
+
+CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+#CPPFLAGS += -g
+CPPFLAGS += -Wall -Wformat -Os $(EMS)
+LDFLAGS += --shell-file shell_minimal.html $(EMS)
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(EXE)
+
+$(WEB_DIR):
+ mkdir $@
+
+serve: all
+ python3 -m http.server -d $(WEB_DIR)
+
+$(EXE): $(OBJS) $(WEB_DIR)
+ $(CXX) -o $@ $(OBJS) $(LDFLAGS)
+
+clean:
+ rm -rf $(OBJS) $(WEB_DIR)
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/README.md b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/README.md
new file mode 100644
index 0000000..e2b19e4
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/README.md
@@ -0,0 +1,26 @@
+## How to Build
+
+- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
+
+- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
+
+- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
+
+- Then build using `make` while in the `example_emscripten_opengl3/` directory.
+
+## How to Run
+
+To run on a local machine:
+- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
+- Otherwise, generally you will need a local webserver:
+ - Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
+_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
+ - Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
+ - You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
+ - You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
+ - If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).
+
+## Obsolete features:
+
+- Emscripten 2.0 (August 2020) obsoleted the fastcomp backend, only llvm is supported.
+- Emscripten 1.39.0 (October 2019) obsoleted the `BINARYEN_TRAP_MODE=clamp` compilation flag which was required with version older than 1.39.0 to avoid rendering artefacts. See [#2877](https://github.com/ocornut/imgui/issues/2877) for details. If you use an older version, uncomment this line in the Makefile: `#EMS += -s BINARYEN_TRAP_MODE=clamp`
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/main.cpp b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/main.cpp
new file mode 100644
index 0000000..be338a8
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/main.cpp
@@ -0,0 +1,174 @@
+// Dear ImGui: standalone example application for Emscripten, using SDL2 + OpenGL3
+// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// This is mostly the same code as the SDL2 + OpenGL3 example, simply with the modifications needed to run on Emscripten.
+// It is possible to combine both code into a single source file that will compile properly on Desktop and using Emscripten.
+// See https://github.com/ocornut/imgui/pull/2492 as an example on how to do just that.
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_opengl3.h"
+#include <stdio.h>
+#include <emscripten.h>
+#include <SDL.h>
+#include <SDL_opengles2.h>
+
+// Emscripten requires to have full control over the main loop. We're going to store our SDL book-keeping variables globally.
+// Having a single function that acts as a loop prevents us to store state in the stack of said function. So we need some location for this.
+SDL_Window* g_Window = NULL;
+SDL_GLContext g_GLContext = NULL;
+
+// For clarity, our main loop code is declared at the end.
+static void main_loop(void*);
+
+int main(int, char**)
+{
+ // Setup SDL
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // For the browser using Emscripten, we are going to use WebGL1 with GL ES2. See the Makefile. for requirement details.
+ // It is very likely the generated file won't work in many browsers. Firefox is the only sure bet, but I have successfully
+ // run this code on Chrome for Android for example.
+ const char* glsl_version = "#version 100";
+ //const char* glsl_version = "#version 300 es";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+
+ // Create window with graphics context
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_DisplayMode current;
+ SDL_GetCurrentDisplayMode(0, &current);
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ g_Window = SDL_CreateWindow("Dear ImGui Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
+ g_GLContext = SDL_GL_CreateContext(g_Window);
+ if (!g_GLContext)
+ {
+ fprintf(stderr, "Failed to initialize WebGL context!\n");
+ return 1;
+ }
+ SDL_GL_SetSwapInterval(1); // Enable vsync
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
+ // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
+ io.IniFilename = NULL;
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForOpenGL(g_Window, g_GLContext);
+ ImGui_ImplOpenGL3_Init(glsl_version);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ // - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
+ //io.Fonts->AddFontDefault();
+#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
+ io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+#endif
+
+ // This function call won't return, and will engage in an infinite loop, processing events from the browser, and dispatching them.
+ emscripten_set_main_loop_arg(main_loop, NULL, 0, true);
+}
+
+static void main_loop(void* arg)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ IM_UNUSED(arg); // We can pass this argument as the second parameter of emscripten_set_main_loop_arg(), but we don't use that.
+
+ // Our state (make them static = more or less global) as a convenience to keep the example terse.
+ static bool show_demo_window = true;
+ static bool show_another_window = false;
+ static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ // Capture events here, based on io.WantCaptureMouse and io.WantCaptureKeyboard
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ SDL_GL_MakeCurrent(g_Window, g_GLContext);
+ glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+ SDL_GL_SwapWindow(g_Window);
+}
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/shell_minimal.html b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/shell_minimal.html
new file mode 100644
index 0000000..514385d
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_opengl3/shell_minimal.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
+ <title>Dear ImGui Emscripten example</title>
+ <style>
+ body { margin: 0; background-color: black }
+ .emscripten {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ margin: 0px;
+ border: 0;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ display: block;
+ image-rendering: optimizeSpeed;
+ image-rendering: -moz-crisp-edges;
+ image-rendering: -o-crisp-edges;
+ image-rendering: -webkit-optimize-contrast;
+ image-rendering: optimize-contrast;
+ image-rendering: crisp-edges;
+ image-rendering: pixelated;
+ -ms-interpolation-mode: nearest-neighbor;
+ }
+ </style>
+ </head>
+ <body>
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <script type='text/javascript'>
+ var Module = {
+ preRun: [],
+ postRun: [],
+ print: (function() {
+ return function(text) {
+ text = Array.prototype.slice.call(arguments).join(' ');
+ console.log(text);
+ };
+ })(),
+ printErr: function(text) {
+ text = Array.prototype.slice.call(arguments).join(' ');
+ console.error(text);
+ },
+ canvas: (function() {
+ var canvas = document.getElementById('canvas');
+ //canvas.addEventListener("webglcontextlost", function(e) { alert('FIXME: WebGL context lost, please reload the page'); e.preventDefault(); }, false);
+ return canvas;
+ })(),
+ setStatus: function(text) {
+ console.log("status: " + text);
+ },
+ monitorRunDependencies: function(left) {
+ // no run dependencies to log
+ }
+ };
+ window.onerror = function() {
+ console.log("onerror: " + event);
+ };
+ </script>
+ {{{ SCRIPT }}}
+ </body>
+</html>
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/Makefile b/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/Makefile
new file mode 100644
index 0000000..5c79f0c
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/Makefile
@@ -0,0 +1,88 @@
+#
+# Makefile to use with emscripten
+# See https://emscripten.org/docs/getting_started/downloads.html
+# for installation instructions.
+#
+# This Makefile assumes you have loaded emscripten's environment.
+# (On Windows, you may need to execute emsdk_env.bat or encmdprompt.bat ahead)
+#
+# Running `make` will produce three files:
+# - web/index.html (current stored in the repository)
+# - web/index.js
+# - web/index.wasm
+#
+# All three are needed to run the demo.
+
+CC = emcc
+CXX = em++
+WEB_DIR = web
+EXE = $(WEB_DIR)/index.js
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_wgpu.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+CPPFLAGS =
+LDFLAGS =
+EMS =
+
+##---------------------------------------------------------------------
+## EMSCRIPTEN OPTIONS
+##---------------------------------------------------------------------
+
+# ("EMS" options gets added to both CPPFLAGS and LDFLAGS, whereas some options are for linker only)
+EMS += -s DISABLE_EXCEPTION_CATCHING=1
+LDFLAGS += -s USE_GLFW=3 -s USE_WEBGPU=1
+LDFLAGS += -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=0 -s ASSERTIONS=1
+
+# Emscripten allows preloading a file or folder to be accessible at runtime.
+# The Makefile for this example project suggests embedding the misc/fonts/ folder into our application, it will then be accessible as "/fonts"
+# See documentation for more details: https://emscripten.org/docs/porting/files/packaging_files.html
+# (Default value is 0. Set to 1 to enable file-system and include the misc/fonts/ folder as part of the build.)
+USE_FILE_SYSTEM ?= 0
+ifeq ($(USE_FILE_SYSTEM), 0)
+LDFLAGS += -s NO_FILESYSTEM=1
+CPPFLAGS += -DIMGUI_DISABLE_FILE_FUNCTIONS
+endif
+ifeq ($(USE_FILE_SYSTEM), 1)
+LDFLAGS += --no-heap-copy --preload-file ../../misc/fonts@/fonts
+endif
+
+##---------------------------------------------------------------------
+## FINAL BUILD FLAGS
+##---------------------------------------------------------------------
+
+CPPFLAGS += -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+#CPPFLAGS += -g
+CPPFLAGS += -Wall -Wformat -Os $(EMS)
+#LDFLAGS += --shell-file shell_minimal.html
+LDFLAGS += $(EMS)
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(EXE)
+
+$(WEB_DIR):
+ mkdir $@
+
+serve: all
+ python3 -m http.server -d $(WEB_DIR)
+
+$(EXE): $(OBJS) $(WEB_DIR)
+ $(CXX) -o $@ $(OBJS) $(LDFLAGS)
+
+clean:
+ rm -f $(EXE) $(OBJS) $(WEB_DIR)/*.js $(WEB_DIR)/*.wasm $(WEB_DIR)/*.wasm.pre
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/README.md b/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/README.md
new file mode 100644
index 0000000..c4c4dec
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/README.md
@@ -0,0 +1,24 @@
+## How to Build
+
+- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
+
+- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
+
+- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
+
+- Then build using `make` while in the `example_emscripten_wgpu/` directory.
+
+- Requires recent Emscripten as WGPU is still a work-in-progress API.
+
+## How to Run
+
+To run on a local machine:
+- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
+- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
+- Otherwise, generally you will need a local webserver:
+ - Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
+_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
+ - Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
+ - You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
+ - You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
+ - If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).
diff --git a/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/main.cpp b/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/main.cpp
new file mode 100644
index 0000000..d11d906
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_emscripten_wgpu/main.cpp
@@ -0,0 +1,245 @@
+// Dear ImGui: standalone example application for Emscripten, using GLFW + WebGPU
+// (Emscripten is a C++-to-javascript compiler, used to publish executables for the web. See https://emscripten.org/)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_wgpu.h"
+#include <stdio.h>
+#include <emscripten.h>
+#include <emscripten/html5.h>
+#include <emscripten/html5_webgpu.h>
+#include <GLFW/glfw3.h>
+#include <webgpu/webgpu.h>
+#include <webgpu/webgpu_cpp.h>
+
+// Global WebGPU required states
+static WGPUDevice wgpu_device = NULL;
+static WGPUSurface wgpu_surface = NULL;
+static WGPUSwapChain wgpu_swap_chain = NULL;
+static int wgpu_swap_chain_width = 0;
+static int wgpu_swap_chain_height = 0;
+
+// States tracked across render frames
+static bool show_demo_window = true;
+static bool show_another_window = false;
+static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+// Forward declarations
+static bool init_wgpu();
+static void main_loop(void* window);
+static void print_glfw_error(int error, const char* description);
+static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*);
+
+int main(int, char**)
+{
+ glfwSetErrorCallback(print_glfw_error);
+ if (!glfwInit())
+ return 1;
+
+ // Make sure GLFW does not initialize any graphics context.
+ // This needs to be done explicitly later
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+
+ GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+WebGPU example", NULL, NULL);
+ if (!window)
+ {
+ glfwTerminate();
+ return 1;
+ }
+
+ // Initialize the WebGPU environment
+ if (!init_wgpu())
+ {
+ if (window)
+ glfwDestroyWindow(window);
+ glfwTerminate();
+ return 1;
+ }
+ glfwShowWindow(window);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
+ // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
+ io.IniFilename = NULL;
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForOther(window, true);
+ ImGui_ImplWGPU_Init(wgpu_device, 3, WGPUTextureFormat_RGBA8Unorm);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ // - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
+ //io.Fonts->AddFontDefault();
+#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
+ io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+#endif
+
+ // This function will directly return and exit the main function.
+ // Make sure that no required objects get cleaned up.
+ // This way we can use the browsers 'requestAnimationFrame' to control the rendering.
+ emscripten_set_main_loop_arg(main_loop, window, 0, false);
+
+ return 0;
+}
+
+static bool init_wgpu()
+{
+ wgpu_device = emscripten_webgpu_get_device();
+ if (!wgpu_device)
+ return false;
+
+ wgpuDeviceSetUncapturedErrorCallback(wgpu_device, print_wgpu_error, NULL);
+
+ // Use C++ wrapper due to misbehavior in Emscripten.
+ // Some offset computation for wgpuInstanceCreateSurface in JavaScript
+ // seem to be inline with struct alignments in the C++ structure
+ wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
+ html_surface_desc.selector = "#canvas";
+
+ wgpu::SurfaceDescriptor surface_desc = {};
+ surface_desc.nextInChain = &html_surface_desc;
+
+ // Use 'null' instance
+ wgpu::Instance instance = {};
+ wgpu_surface = instance.CreateSurface(&surface_desc).Release();
+
+ return true;
+}
+
+static void main_loop(void* window)
+{
+ glfwPollEvents();
+
+ int width, height;
+ glfwGetFramebufferSize((GLFWwindow*) window, &width, &height);
+
+ // React to changes in screen size
+ if (width != wgpu_swap_chain_width && height != wgpu_swap_chain_height)
+ {
+ ImGui_ImplWGPU_InvalidateDeviceObjects();
+
+ if (wgpu_swap_chain)
+ wgpuSwapChainRelease(wgpu_swap_chain);
+
+ wgpu_swap_chain_width = width;
+ wgpu_swap_chain_height = height;
+
+ WGPUSwapChainDescriptor swap_chain_desc = {};
+ swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
+ swap_chain_desc.format = WGPUTextureFormat_RGBA8Unorm;
+ swap_chain_desc.width = width;
+ swap_chain_desc.height = height;
+ swap_chain_desc.presentMode = WGPUPresentMode_Fifo;
+ wgpu_swap_chain = wgpuDeviceCreateSwapChain(wgpu_device, wgpu_surface, &swap_chain_desc);
+
+ ImGui_ImplWGPU_CreateDeviceObjects();
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplWGPU_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+
+ WGPURenderPassColorAttachment color_attachments = {};
+ color_attachments.loadOp = WGPULoadOp_Clear;
+ color_attachments.storeOp = WGPUStoreOp_Store;
+ color_attachments.clearColor = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
+ color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
+ WGPURenderPassDescriptor render_pass_desc = {};
+ render_pass_desc.colorAttachmentCount = 1;
+ render_pass_desc.colorAttachments = &color_attachments;
+ render_pass_desc.depthStencilAttachment = NULL;
+
+ WGPUCommandEncoderDescriptor enc_desc = {};
+ WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(wgpu_device, &enc_desc);
+
+ WGPURenderPassEncoder pass = wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
+ ImGui_ImplWGPU_RenderDrawData(ImGui::GetDrawData(), pass);
+ wgpuRenderPassEncoderEndPass(pass);
+
+ WGPUCommandBufferDescriptor cmd_buffer_desc = {};
+ WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
+ WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
+ wgpuQueueSubmit(queue, 1, &cmd_buffer);
+}
+
+static void print_glfw_error(int error, const char* description)
+{
+ printf("Glfw Error %d: %s\n", error, description);
+}
+
+static void print_wgpu_error(WGPUErrorType error_type, const char* message, void*)
+{
+ const char* error_type_lbl = "";
+ switch (error_type)
+ {
+ case WGPUErrorType_Validation: error_type_lbl = "Validation"; break;
+ case WGPUErrorType_OutOfMemory: error_type_lbl = "Out of memory"; break;
+ case WGPUErrorType_Unknown: error_type_lbl = "Unknown"; break;
+ case WGPUErrorType_DeviceLost: error_type_lbl = "Device lost"; break;
+ default: error_type_lbl = "Unknown";
+ }
+ printf("%s error: %s\n", error_type_lbl, message);
+}
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_metal/Makefile b/Client/ThirdParty/imgui/examples/example_glfw_metal/Makefile
new file mode 100644
index 0000000..a174bc8
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_metal/Makefile
@@ -0,0 +1,46 @@
+#
+# You will need GLFW (http://www.glfw.org):
+# brew install glfw
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_glfw_metal
+IMGUI_DIR = ../..
+SOURCES = main.mm
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_metal.mm
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+
+LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
+LIBS += -L/usr/local/lib -L/opt/homebrew/lib
+LIBS += -lglfw
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include
+CXXFLAGS += -Wall -Wformat
+CFLAGS = $(CXXFLAGS)
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:%.mm
+ $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.mm
+ $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_metal/main.mm b/Client/ThirdParty/imgui/examples/example_glfw_metal/main.mm
new file mode 100644
index 0000000..2776ba2
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_metal/main.mm
@@ -0,0 +1,172 @@
+// Dear ImGui: standalone example application for GLFW + Metal, using programmable pipeline
+// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_metal.h"
+#include <stdio.h>
+
+#define GLFW_INCLUDE_NONE
+#define GLFW_EXPOSE_NATIVE_COCOA
+#include <GLFW/glfw3.h>
+#include <GLFW/glfw3native.h>
+
+#import <Metal/Metal.h>
+#import <QuartzCore/QuartzCore.h>
+
+static void glfw_error_callback(int error, const char* description)
+{
+ fprintf(stderr, "Glfw Error %d: %s\n", error, description);
+}
+
+int main(int, char**)
+{
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.txt' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Setup window
+ glfwSetErrorCallback(glfw_error_callback);
+ if (!glfwInit())
+ return 1;
+
+ // Create window with graphics context
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+ GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Metal example", NULL, NULL);
+ if (window == NULL)
+ return 1;
+
+ id <MTLDevice> device = MTLCreateSystemDefaultDevice();
+ id <MTLCommandQueue> commandQueue = [device newCommandQueue];
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForOpenGL(window, true);
+ ImGui_ImplMetal_Init(device);
+
+ NSWindow *nswin = glfwGetCocoaWindow(window);
+ CAMetalLayer *layer = [CAMetalLayer layer];
+ layer.device = device;
+ layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ nswin.contentView.layer = layer;
+ nswin.contentView.wantsLayer = YES;
+
+ MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new];
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f};
+
+ // Main loop
+ while (!glfwWindowShouldClose(window))
+ {
+ @autoreleasepool
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ glfwPollEvents();
+
+ int width, height;
+ glfwGetFramebufferSize(window, &width, &height);
+ layer.drawableSize = CGSizeMake(width, height);
+ id<CAMetalDrawable> drawable = [layer nextDrawable];
+
+ id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
+ renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
+ renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
+ renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
+ renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
+ id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
+ [renderEncoder pushDebugGroup:@"ImGui demo"];
+
+ // Start the Dear ImGui frame
+ ImGui_ImplMetal_NewFrame(renderPassDescriptor);
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder);
+
+ [renderEncoder popDebugGroup];
+ [renderEncoder endEncoding];
+
+ [commandBuffer presentDrawable:drawable];
+ [commandBuffer commit];
+ }
+ }
+
+ // Cleanup
+ ImGui_ImplMetal_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl2/Makefile b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/Makefile
new file mode 100644
index 0000000..5c19a27
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/Makefile
@@ -0,0 +1,81 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# You will need GLFW (http://www.glfw.org):
+# Linux:
+# apt-get install libglfw-dev
+# Mac OS X:
+# brew install glfw
+# MSYS2:
+# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_glfw_opengl2
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ LIBS += -lGL `pkg-config --static --libs glfw3`
+
+ CXXFLAGS += `pkg-config --cflags glfw3`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
+ LIBS += -L/usr/local/lib -L/opt/local/lib -L/opt/homebrew/lib
+ #LIBS += -lglfw3
+ LIBS += -lglfw
+
+ CXXFLAGS += -I/usr/local/include -I/opt/local/include -I/opt/homebrew/include
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ LIBS += -lglfw3 -lgdi32 -lopengl32 -limm32
+
+ CXXFLAGS += `pkg-config --cflags glfw3`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
+
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl2/build_win32.bat b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/build_win32.bat
new file mode 100644
index 0000000..a0a75f9
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_glfw_opengl2
+@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj
new file mode 100644
index 0000000..faf6d9a
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9CDA7840-B7A5-496D-A527-E95571496D18}</ProjectGuid>
+ <RootNamespace>example_glfw_opengl2</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_glfw.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_opengl2.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_glfw.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl2.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj.filters
new file mode 100644
index 0000000..69b285d
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/example_glfw_opengl2.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{c336cfe3-f0c4-464c-9ef0-a9e17a7ff222}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_glfw.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_opengl2.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_glfw.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl2.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl2/main.cpp b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/main.cpp
new file mode 100644
index 0000000..ee785b1
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl2/main.cpp
@@ -0,0 +1,159 @@
+// Dear ImGui: standalone example application for GLFW + OpenGL2, using legacy fixed pipeline
+// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
+// **Prefer using the code in the example_glfw_opengl2/ folder**
+// See imgui_impl_glfw.cpp for details.
+
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_opengl2.h"
+#include <stdio.h>
+#ifdef __APPLE__
+#define GL_SILENCE_DEPRECATION
+#endif
+#include <GLFW/glfw3.h>
+
+// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
+// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
+// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
+#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
+#pragma comment(lib, "legacy_stdio_definitions")
+#endif
+
+static void glfw_error_callback(int error, const char* description)
+{
+ fprintf(stderr, "Glfw Error %d: %s\n", error, description);
+}
+
+int main(int, char**)
+{
+ // Setup window
+ glfwSetErrorCallback(glfw_error_callback);
+ if (!glfwInit())
+ return 1;
+ GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL2 example", NULL, NULL);
+ if (window == NULL)
+ return 1;
+ glfwMakeContextCurrent(window);
+ glfwSwapInterval(1); // Enable vsync
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForOpenGL(window, true);
+ ImGui_ImplOpenGL2_Init();
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ while (!glfwWindowShouldClose(window))
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ glfwPollEvents();
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL2_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ int display_w, display_h;
+ glfwGetFramebufferSize(window, &display_w, &display_h);
+ glViewport(0, 0, display_w, display_h);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
+ // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
+ //GLint last_program;
+ //glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
+ //glUseProgram(0);
+ ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
+ //glUseProgram(last_program);
+
+ glfwMakeContextCurrent(window);
+ glfwSwapBuffers(window);
+ }
+
+ // Cleanup
+ ImGui_ImplOpenGL2_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl3/Makefile b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/Makefile
new file mode 100644
index 0000000..672a705
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/Makefile
@@ -0,0 +1,89 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# You will need GLFW (http://www.glfw.org):
+# Linux:
+# apt-get install libglfw-dev
+# Mac OS X:
+# brew install glfw
+# MSYS2:
+# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_glfw_opengl3
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+LINUX_GL_LIBS = -lGL
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+##---------------------------------------------------------------------
+## OPENGL ES
+##---------------------------------------------------------------------
+
+## This assumes a GL ES library available in the system, e.g. libGLESv2.so
+# CXXFLAGS += -DIMGUI_IMPL_OPENGL_ES2
+# LINUX_GL_LIBS = -lGLESv2
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
+
+ CXXFLAGS += `pkg-config --cflags glfw3`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
+ LIBS += -L/usr/local/lib -L/opt/local/lib -L/opt/homebrew/lib
+ #LIBS += -lglfw3
+ LIBS += -lglfw
+
+ CXXFLAGS += -I/usr/local/include -I/opt/local/include -I/opt/homebrew/include
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ LIBS += -lglfw3 -lgdi32 -lopengl32 -limm32
+
+ CXXFLAGS += `pkg-config --cflags glfw3`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl3/build_win32.bat b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/build_win32.bat
new file mode 100644
index 0000000..4ba58d8
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_glfw_opengl3
+@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-32 glfw3.lib opengl32.lib gdi32.lib shell32.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj
new file mode 100644
index 0000000..7721c8f
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4a1fb5ea-22f5-42a8-ab92-1d2df5d47fb9}</ProjectGuid>
+ <RootNamespace>example_glfw_opengl3</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_glfw.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_opengl3.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_glfw.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3_loader.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj.filters
new file mode 100644
index 0000000..fd2f807
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/example_glfw_opengl3.vcxproj.filters
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_glfw.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_opengl3.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_glfw.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3_loader.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_opengl3/main.cpp b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/main.cpp
new file mode 100644
index 0000000..f8e8a02
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_opengl3/main.cpp
@@ -0,0 +1,172 @@
+// Dear ImGui: standalone example application for GLFW + OpenGL 3, using programmable pipeline
+// (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_opengl3.h"
+#include <stdio.h>
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+#include <GLES2/gl2.h>
+#endif
+#include <GLFW/glfw3.h> // Will drag system OpenGL headers
+
+// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
+// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
+// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
+#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
+#pragma comment(lib, "legacy_stdio_definitions")
+#endif
+
+static void glfw_error_callback(int error, const char* description)
+{
+ fprintf(stderr, "Glfw Error %d: %s\n", error, description);
+}
+
+int main(int, char**)
+{
+ // Setup window
+ glfwSetErrorCallback(glfw_error_callback);
+ if (!glfwInit())
+ return 1;
+
+ // Decide GL+GLSL versions
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+ // GL ES 2.0 + GLSL 100
+ const char* glsl_version = "#version 100";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+#elif defined(__APPLE__)
+ // GL 3.2 + GLSL 150
+ const char* glsl_version = "#version 150";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
+#else
+ // GL 3.0 + GLSL 130
+ const char* glsl_version = "#version 130";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
+ //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
+#endif
+
+ // Create window with graphics context
+ GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+OpenGL3 example", NULL, NULL);
+ if (window == NULL)
+ return 1;
+ glfwMakeContextCurrent(window);
+ glfwSwapInterval(1); // Enable vsync
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForOpenGL(window, true);
+ ImGui_ImplOpenGL3_Init(glsl_version);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ while (!glfwWindowShouldClose(window))
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ glfwPollEvents();
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ int display_w, display_h;
+ glfwGetFramebufferSize(window, &display_w, &display_h);
+ glViewport(0, 0, display_w, display_h);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+ glfwSwapBuffers(window);
+ }
+
+ // Cleanup
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_vulkan/CMakeLists.txt b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/CMakeLists.txt
new file mode 100644
index 0000000..05eab3b
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/CMakeLists.txt
@@ -0,0 +1,43 @@
+# Example usage:
+# mkdir build
+# cd build
+# cmake -g "Visual Studio 14 2015" ..
+
+cmake_minimum_required(VERSION 2.8)
+project(imgui_example_glfw_vulkan C CXX)
+
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
+endif()
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES")
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES")
+
+# GLFW
+set(GLFW_DIR ../../../glfw) # Set this to point to an up-to-date GLFW repo
+option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF)
+option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF)
+option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF)
+option(GLFW_INSTALL "Generate installation target" OFF)
+option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
+add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL)
+include_directories(${GLFW_DIR}/include)
+
+# Dear ImGui
+set(IMGUI_DIR ../../)
+include_directories(${IMGUI_DIR} ${IMGUI_DIR}/backends ..)
+
+# Libraries
+find_package(Vulkan REQUIRED)
+#find_library(VULKAN_LIBRARY
+ #NAMES vulkan vulkan-1)
+#set(LIBRARIES "glfw;${VULKAN_LIBRARY}")
+set(LIBRARIES "glfw;Vulkan::Vulkan")
+
+# Use vulkan headers from glfw:
+include_directories(${GLFW_DIR}/deps)
+
+file(GLOB sources *.cpp)
+
+add_executable(example_glfw_vulkan ${sources} ${IMGUI_DIR}/backends/imgui_impl_glfw.cpp ${IMGUI_DIR}/backends/imgui_impl_vulkan.cpp ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp ${IMGUI_DIR}/imgui_tables.cpp ${IMGUI_DIR}/imgui_widgets.cpp)
+target_link_libraries(example_glfw_vulkan ${LIBRARIES})
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win32.bat b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win32.bat
new file mode 100644
index 0000000..f49cbd7
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win32.bat
@@ -0,0 +1,14 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+
+@set OUT_EXE=example_glfw_vulkan
+@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include /I %VULKAN_SDK%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\lib32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+
+@set OUT_DIR=Release
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win64.bat b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win64.bat
new file mode 100644
index 0000000..893f296
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/build_win64.bat
@@ -0,0 +1,13 @@
+@REM Build for Visual Studio compiler. Run your copy of amd64/vcvars32.bat to setup 64-bit command-line compiler.
+
+@set INCLUDES=/I..\.. /I..\..\backends /I..\libs\glfw\include /I %VULKAN_SDK%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\backends\imgui_impl_glfw.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:..\libs\glfw\lib-vc2010-64 /libpath:%VULKAN_SDK%\lib glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+
+@set OUT_DIR=Release
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD /Ox /Oi %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj
new file mode 100644
index 0000000..34b3f21
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}</ProjectGuid>
+ <RootNamespace>example_glfw_vulkan</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib;..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;..\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;..\libs\glfw\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib;..\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;glfw3.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_glfw.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_vulkan.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_glfw.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_vulkan.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj.filters
new file mode 100644
index 0000000..adc3365
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/example_glfw_vulkan.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_glfw.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_vulkan.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_glfw.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_vulkan.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_glfw_vulkan/main.cpp b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/main.cpp
new file mode 100644
index 0000000..615f2ee
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glfw_vulkan/main.cpp
@@ -0,0 +1,558 @@
+// Dear ImGui: standalone example application for Glfw + Vulkan
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
+// You will use those if you want to use this rendering backend in your engine/app.
+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
+// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
+// Read comments in imgui_impl_vulkan.h.
+
+#include "imgui.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_vulkan.h"
+#include <stdio.h> // printf, fprintf
+#include <stdlib.h> // abort
+#define GLFW_INCLUDE_NONE
+#define GLFW_INCLUDE_VULKAN
+#include <GLFW/glfw3.h>
+#include <vulkan/vulkan.h>
+
+// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
+// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
+// Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
+#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
+#pragma comment(lib, "legacy_stdio_definitions")
+#endif
+
+//#define IMGUI_UNLIMITED_FRAME_RATE
+#ifdef _DEBUG
+#define IMGUI_VULKAN_DEBUG_REPORT
+#endif
+
+static VkAllocationCallbacks* g_Allocator = NULL;
+static VkInstance g_Instance = VK_NULL_HANDLE;
+static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
+static VkDevice g_Device = VK_NULL_HANDLE;
+static uint32_t g_QueueFamily = (uint32_t)-1;
+static VkQueue g_Queue = VK_NULL_HANDLE;
+static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
+static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
+static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
+
+static ImGui_ImplVulkanH_Window g_MainWindowData;
+static int g_MinImageCount = 2;
+static bool g_SwapChainRebuild = false;
+
+static void check_vk_result(VkResult err)
+{
+ if (err == 0)
+ return;
+ fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
+ if (err < 0)
+ abort();
+}
+
+#ifdef IMGUI_VULKAN_DEBUG_REPORT
+static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
+{
+ (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
+ fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
+ return VK_FALSE;
+}
+#endif // IMGUI_VULKAN_DEBUG_REPORT
+
+static void SetupVulkan(const char** extensions, uint32_t extensions_count)
+{
+ VkResult err;
+
+ // Create Vulkan Instance
+ {
+ VkInstanceCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ create_info.enabledExtensionCount = extensions_count;
+ create_info.ppEnabledExtensionNames = extensions;
+#ifdef IMGUI_VULKAN_DEBUG_REPORT
+ // Enabling validation layers
+ const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
+ create_info.enabledLayerCount = 1;
+ create_info.ppEnabledLayerNames = layers;
+
+ // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
+ const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
+ memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
+ extensions_ext[extensions_count] = "VK_EXT_debug_report";
+ create_info.enabledExtensionCount = extensions_count + 1;
+ create_info.ppEnabledExtensionNames = extensions_ext;
+
+ // Create Vulkan Instance
+ err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+ check_vk_result(err);
+ free(extensions_ext);
+
+ // Get the function pointer (required for any extensions)
+ auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
+ IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
+
+ // Setup the debug report callback
+ VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
+ debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+ debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ debug_report_ci.pfnCallback = debug_report;
+ debug_report_ci.pUserData = NULL;
+ err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
+ check_vk_result(err);
+#else
+ // Create Vulkan Instance without any debug feature
+ err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+ check_vk_result(err);
+ IM_UNUSED(g_DebugReport);
+#endif
+ }
+
+ // Select GPU
+ {
+ uint32_t gpu_count;
+ err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
+ check_vk_result(err);
+ IM_ASSERT(gpu_count > 0);
+
+ VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
+ err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
+ check_vk_result(err);
+
+ // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
+ // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
+ // dedicated GPUs) is out of scope of this sample.
+ int use_gpu = 0;
+ for (int i = 0; i < (int)gpu_count; i++)
+ {
+ VkPhysicalDeviceProperties properties;
+ vkGetPhysicalDeviceProperties(gpus[i], &properties);
+ if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+ {
+ use_gpu = i;
+ break;
+ }
+ }
+
+ g_PhysicalDevice = gpus[use_gpu];
+ free(gpus);
+ }
+
+ // Select graphics queue family
+ {
+ uint32_t count;
+ vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
+ VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
+ vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
+ for (uint32_t i = 0; i < count; i++)
+ if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+ {
+ g_QueueFamily = i;
+ break;
+ }
+ free(queues);
+ IM_ASSERT(g_QueueFamily != (uint32_t)-1);
+ }
+
+ // Create Logical Device (with 1 queue)
+ {
+ int device_extension_count = 1;
+ const char* device_extensions[] = { "VK_KHR_swapchain" };
+ const float queue_priority[] = { 1.0f };
+ VkDeviceQueueCreateInfo queue_info[1] = {};
+ queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queue_info[0].queueFamilyIndex = g_QueueFamily;
+ queue_info[0].queueCount = 1;
+ queue_info[0].pQueuePriorities = queue_priority;
+ VkDeviceCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
+ create_info.pQueueCreateInfos = queue_info;
+ create_info.enabledExtensionCount = device_extension_count;
+ create_info.ppEnabledExtensionNames = device_extensions;
+ err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
+ check_vk_result(err);
+ vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
+ }
+
+ // Create Descriptor Pool
+ {
+ VkDescriptorPoolSize pool_sizes[] =
+ {
+ { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
+ { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
+ { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
+ };
+ VkDescriptorPoolCreateInfo pool_info = {};
+ pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+ pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
+ pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
+ pool_info.pPoolSizes = pool_sizes;
+ err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
+ check_vk_result(err);
+ }
+}
+
+// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
+// Your real engine/app may not use them.
+static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
+{
+ wd->Surface = surface;
+
+ // Check for WSI support
+ VkBool32 res;
+ vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
+ if (res != VK_TRUE)
+ {
+ fprintf(stderr, "Error no WSI support on physical device 0\n");
+ exit(-1);
+ }
+
+ // Select Surface Format
+ const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
+ const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+
+ // Select Present Mode
+#ifdef IMGUI_UNLIMITED_FRAME_RATE
+ VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
+#else
+ VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
+#endif
+ wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
+ //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
+
+ // Create SwapChain, RenderPass, Framebuffer, etc.
+ IM_ASSERT(g_MinImageCount >= 2);
+ ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
+}
+
+static void CleanupVulkan()
+{
+ vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
+
+#ifdef IMGUI_VULKAN_DEBUG_REPORT
+ // Remove the debug report callback
+ auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
+ vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
+#endif // IMGUI_VULKAN_DEBUG_REPORT
+
+ vkDestroyDevice(g_Device, g_Allocator);
+ vkDestroyInstance(g_Instance, g_Allocator);
+}
+
+static void CleanupVulkanWindow()
+{
+ ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
+}
+
+static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
+{
+ VkResult err;
+
+ VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
+ VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+ err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
+ if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
+ {
+ g_SwapChainRebuild = true;
+ return;
+ }
+ check_vk_result(err);
+
+ ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
+ {
+ err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
+ check_vk_result(err);
+
+ err = vkResetFences(g_Device, 1, &fd->Fence);
+ check_vk_result(err);
+ }
+ {
+ err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
+ check_vk_result(err);
+ VkCommandBufferBeginInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
+ check_vk_result(err);
+ }
+ {
+ VkRenderPassBeginInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ info.renderPass = wd->RenderPass;
+ info.framebuffer = fd->Framebuffer;
+ info.renderArea.extent.width = wd->Width;
+ info.renderArea.extent.height = wd->Height;
+ info.clearValueCount = 1;
+ info.pClearValues = &wd->ClearValue;
+ vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ // Record dear imgui primitives into command buffer
+ ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
+
+ // Submit command buffer
+ vkCmdEndRenderPass(fd->CommandBuffer);
+ {
+ VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkSubmitInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ info.waitSemaphoreCount = 1;
+ info.pWaitSemaphores = &image_acquired_semaphore;
+ info.pWaitDstStageMask = &wait_stage;
+ info.commandBufferCount = 1;
+ info.pCommandBuffers = &fd->CommandBuffer;
+ info.signalSemaphoreCount = 1;
+ info.pSignalSemaphores = &render_complete_semaphore;
+
+ err = vkEndCommandBuffer(fd->CommandBuffer);
+ check_vk_result(err);
+ err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
+ check_vk_result(err);
+ }
+}
+
+static void FramePresent(ImGui_ImplVulkanH_Window* wd)
+{
+ if (g_SwapChainRebuild)
+ return;
+ VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+ VkPresentInfoKHR info = {};
+ info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ info.waitSemaphoreCount = 1;
+ info.pWaitSemaphores = &render_complete_semaphore;
+ info.swapchainCount = 1;
+ info.pSwapchains = &wd->Swapchain;
+ info.pImageIndices = &wd->FrameIndex;
+ VkResult err = vkQueuePresentKHR(g_Queue, &info);
+ if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
+ {
+ g_SwapChainRebuild = true;
+ return;
+ }
+ check_vk_result(err);
+ wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
+}
+
+static void glfw_error_callback(int error, const char* description)
+{
+ fprintf(stderr, "Glfw Error %d: %s\n", error, description);
+}
+
+int main(int, char**)
+{
+ // Setup GLFW window
+ glfwSetErrorCallback(glfw_error_callback);
+ if (!glfwInit())
+ return 1;
+
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+ GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Vulkan example", NULL, NULL);
+
+ // Setup Vulkan
+ if (!glfwVulkanSupported())
+ {
+ printf("GLFW: Vulkan Not Supported\n");
+ return 1;
+ }
+ uint32_t extensions_count = 0;
+ const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
+ SetupVulkan(extensions, extensions_count);
+
+ // Create Window Surface
+ VkSurfaceKHR surface;
+ VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &surface);
+ check_vk_result(err);
+
+ // Create Framebuffers
+ int w, h;
+ glfwGetFramebufferSize(window, &w, &h);
+ ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
+ SetupVulkanWindow(wd, surface, w, h);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForVulkan(window, true);
+ ImGui_ImplVulkan_InitInfo init_info = {};
+ init_info.Instance = g_Instance;
+ init_info.PhysicalDevice = g_PhysicalDevice;
+ init_info.Device = g_Device;
+ init_info.QueueFamily = g_QueueFamily;
+ init_info.Queue = g_Queue;
+ init_info.PipelineCache = g_PipelineCache;
+ init_info.DescriptorPool = g_DescriptorPool;
+ init_info.Allocator = g_Allocator;
+ init_info.MinImageCount = g_MinImageCount;
+ init_info.ImageCount = wd->ImageCount;
+ init_info.CheckVkResultFn = check_vk_result;
+ ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Upload Fonts
+ {
+ // Use any command queue
+ VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
+ VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
+
+ err = vkResetCommandPool(g_Device, command_pool, 0);
+ check_vk_result(err);
+ VkCommandBufferBeginInfo begin_info = {};
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ err = vkBeginCommandBuffer(command_buffer, &begin_info);
+ check_vk_result(err);
+
+ ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
+
+ VkSubmitInfo end_info = {};
+ end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ end_info.commandBufferCount = 1;
+ end_info.pCommandBuffers = &command_buffer;
+ err = vkEndCommandBuffer(command_buffer);
+ check_vk_result(err);
+ err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE);
+ check_vk_result(err);
+
+ err = vkDeviceWaitIdle(g_Device);
+ check_vk_result(err);
+ ImGui_ImplVulkan_DestroyFontUploadObjects();
+ }
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ while (!glfwWindowShouldClose(window))
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ glfwPollEvents();
+
+ // Resize swap chain?
+ if (g_SwapChainRebuild)
+ {
+ int width, height;
+ glfwGetFramebufferSize(window, &width, &height);
+ if (width > 0 && height > 0)
+ {
+ ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
+ ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
+ g_MainWindowData.FrameIndex = 0;
+ g_SwapChainRebuild = false;
+ }
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplVulkan_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+ const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
+ if (!is_minimized)
+ {
+ wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
+ wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
+ wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
+ wd->ClearValue.color.float32[3] = clear_color.w;
+ FrameRender(wd, draw_data);
+ FramePresent(wd);
+ }
+ }
+
+ // Cleanup
+ err = vkDeviceWaitIdle(g_Device);
+ check_vk_result(err);
+ ImGui_ImplVulkan_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupVulkanWindow();
+ CleanupVulkan();
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_glut_opengl2/Makefile b/Client/ThirdParty/imgui/examples/example_glut_opengl2/Makefile
new file mode 100644
index 0000000..a980f56
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glut_opengl2/Makefile
@@ -0,0 +1,75 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# Linux:
+# apt-get install freeglut3-dev
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_glut_opengl2
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glut.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ LIBS += -lGL -lglut
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ LIBS += -framework OpenGL -framework GLUT
+ LIBS += -L/usr/local/lib -L/opt/local/lib
+
+ CXXFLAGS += -I/usr/local/include -I/opt/local/include
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ LIBS += -lgdi32 -lopengl32 -limm32
+ifeq ($(shell pkg-config freeglut --exists 2> /dev/null && echo yes || echo no),yes)
+ CXXFLAGS += $(shell pkg-config freeglut --cflags)
+ LIBS += $(shell pkg-config freeglut --libs)
+else
+ LIBS += -lglut
+endif
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj b/Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj
new file mode 100644
index 0000000..4c9d00f
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F90D0333-5FB1-440D-918D-DD39A1B5187E}</ProjectGuid>
+ <RootNamespace>example_glut_opengl2</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(GLUT_ROOT_PATH)/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;freeglut.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(GLUT_ROOT_PATH)/lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;freeglut.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(GLUT_ROOT_PATH)/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;freeglut.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>$(GLUT_INCLUDE_DIR);..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(GLUT_ROOT_PATH)/lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;freeglut.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_glut.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_opengl2.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_glut.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl2.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj.filters
new file mode 100644
index 0000000..3c017ba
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glut_opengl2/example_glut_opengl2.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{c336cfe3-f0c4-464c-9ef0-a9e17a7ff222}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_glut.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_opengl2.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_glut.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl2.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_glut_opengl2/main.cpp b/Client/ThirdParty/imgui/examples/example_glut_opengl2/main.cpp
new file mode 100644
index 0000000..fed62b5
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_glut_opengl2/main.cpp
@@ -0,0 +1,155 @@
+// Dear ImGui: standalone example application for GLUT/FreeGLUT + OpenGL2, using legacy fixed pipeline
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
+// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
+// !!! Nowadays, prefer using GLFW or SDL instead!
+
+// On Windows, you can install Freeglut using vcpkg:
+// git clone https://github.com/Microsoft/vcpkg
+// cd vcpkg
+// bootstrap - vcpkg.bat
+// vcpkg install freeglut --triplet=x86-windows ; for win32
+// vcpkg install freeglut --triplet=x64-windows ; for win64
+// vcpkg integrate install ; register include and libs in Visual Studio
+
+#include "imgui.h"
+#include "imgui_impl_glut.h"
+#include "imgui_impl_opengl2.h"
+#ifdef __APPLE__
+ #include <GLUT/glut.h>
+#else
+ #include <GL/freeglut.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4505) // unreferenced local function has been removed
+#endif
+
+// Our state
+static bool show_demo_window = true;
+static bool show_another_window = false;
+static ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+void my_display_code()
+{
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+}
+
+void glut_display_func()
+{
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL2_NewFrame();
+ ImGui_ImplGLUT_NewFrame();
+
+ my_display_code();
+
+ // Rendering
+ ImGui::Render();
+ ImGuiIO& io = ImGui::GetIO();
+ glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code.
+ ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
+
+ glutSwapBuffers();
+ glutPostRedisplay();
+}
+
+// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+
+int main(int argc, char** argv)
+{
+ // Create GLUT window
+ glutInit(&argc, argv);
+#ifdef __FREEGLUT_EXT_H__
+ glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
+#endif
+ glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
+ glutInitWindowSize(1280, 720);
+ glutCreateWindow("Dear ImGui GLUT+OpenGL2 Example");
+
+ // Setup GLUT display function
+ // We will also call ImGui_ImplGLUT_InstallFuncs() to get all the other functions installed for us,
+ // otherwise it is possible to install our own functions and call the imgui_impl_glut.h functions ourselves.
+ glutDisplayFunc(glut_display_func);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGLUT_Init();
+ ImGui_ImplGLUT_InstallFuncs();
+ ImGui_ImplOpenGL2_Init();
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ glutMainLoop();
+
+ // Cleanup
+ ImGui_ImplOpenGL2_Shutdown();
+ ImGui_ImplGLUT_Shutdown();
+ ImGui::DestroyContext();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_marmalade/data/app.icf b/Client/ThirdParty/imgui/examples/example_marmalade/data/app.icf
new file mode 100644
index 0000000..fcd6585
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_marmalade/data/app.icf
@@ -0,0 +1,32 @@
+# This file is for configuration settings for your
+# application.
+#
+# The syntax is similar to windows .ini files ie
+#
+# [GroupName]
+# Setting = Value
+#
+# Which can be read by your application using
+# e.g s3eConfigGetString("GroupName", "Setting", string)
+#
+# All settings must be documented in .config.txt files.
+# New settings specific to this application should be
+# documented in app.config.txt
+#
+# Some conditional operations are also permitted, see the
+# S3E documentation for details.
+
+[S3E]
+MemSize=6000000
+MemSizeDebug=6000000
+DispFixRot=FixedLandscape
+
+# emulate iphone 5 resolution, change these settings to emulate other display resolution
+WinWidth=1136
+WinHeight=640
+
+[GX]
+DataCacheSize=131070
+
+[Util]
+#MemoryBreakpoint=1282
diff --git a/Client/ThirdParty/imgui/examples/example_marmalade/main.cpp b/Client/ThirdParty/imgui/examples/example_marmalade/main.cpp
new file mode 100644
index 0000000..e97cb53
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_marmalade/main.cpp
@@ -0,0 +1,124 @@
+// Dear ImGui: standalone example application for Marmalade
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// Copyright (C) 2015 by Giovanni Zito
+// This file is part of Dear ImGui
+
+#include "imgui.h"
+#include "imgui_impl_marmalade.h"
+#include <stdio.h>
+
+#include <s3eKeyboard.h>
+#include <s3ePointer.h>
+#include <IwGx.h>
+
+int main(int, char**)
+{
+ IwGxInit();
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_Marmalade_Init(true);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ while (true)
+ {
+ if (s3eDeviceCheckQuitRequest())
+ break;
+
+ // Poll and handle inputs
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ s3eKeyboardUpdate();
+ s3ePointerUpdate();
+
+ // Start the Dear ImGui frame
+ ImGui_Marmalade_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255);
+ IwGxClear();
+ ImGui_Marmalade_RenderDrawData(ImGui::GetDrawData());
+ IwGxSwapBuffers();
+
+ s3eDeviceYield(0);
+ }
+
+ // Cleanup
+ ImGui_Marmalade_Shutdown();
+ ImGui::DestroyContext();
+ IwGxTerminate();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_marmalade/marmalade_example.mkb b/Client/ThirdParty/imgui/examples/example_marmalade/marmalade_example.mkb
new file mode 100644
index 0000000..4e765f1
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_marmalade/marmalade_example.mkb
@@ -0,0 +1,47 @@
+#!/usr/bin/env mkb
+
+# ImGui - standalone example application for Marmalade
+# Copyright (C) 2015 by Giovanni Zito
+# This file is part of ImGui
+# https://github.com/ocornut/imgui
+
+define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
+define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
+define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS
+define _snprintf=snprintf
+
+options
+{
+ optimise-speed=1
+}
+
+includepaths
+{
+ ../..
+ ../../backends
+}
+
+subprojects
+{
+ iwgx
+}
+
+files
+{
+ (.)
+ ["imgui"]
+ ../../imgui.cpp
+ ../../imgui_demo.cpp
+ ../../imgui_draw.cpp
+ ../../imgui_tables.cpp
+ ../../imgui_widgets.cpp
+ ../../imconfig.h
+ ../../imgui.h
+ ../../imgui_internal.h
+
+ ["imgui","Marmalade backend"]
+ ../../backends/imgui_impl_marmalade.h
+ ../../backends/imgui_impl_marmalade.cpp
+ main.cpp
+
+}
diff --git a/Client/ThirdParty/imgui/examples/example_null/Makefile b/Client/ThirdParty/imgui/examples/example_null/Makefile
new file mode 100644
index 0000000..9208e8a
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_null/Makefile
@@ -0,0 +1,92 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# Important: This is a "null backend" application, with no visible output or interaction!
+# This is used for testing purpose and continuous integration, and has little use for end-user.
+#
+
+# Options
+WITH_EXTRA_WARNINGS ?= 0
+WITH_FREETYPE ?= 0
+
+EXE = example_null
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+
+CXXFLAGS += -I$(IMGUI_DIR)
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+# We use the WITH_EXTRA_WARNINGS flag on our CI setup to eagerly catch zealous warnings
+ifeq ($(WITH_EXTRA_WARNINGS), 1)
+ CXXFLAGS += -Wno-zero-as-null-pointer-constant -Wno-double-promotion -Wno-variadic-macros
+endif
+
+# We use the WITH_FREETYPE flag on our CI setup to test compiling misc/freetype/imgui_freetype.cpp
+# (only supported on Linux, and note that the imgui_freetype code currently won't be executed)
+ifeq ($(WITH_FREETYPE), 1)
+ SOURCES += $(IMGUI_DIR)/misc/freetype/imgui_freetype.cpp
+ CXXFLAGS += $(shell pkg-config --cflags freetype2)
+ LIBS += $(shell pkg-config --libs freetype2)
+endif
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ ifeq ($(WITH_EXTRA_WARNINGS), 1)
+ CXXFLAGS += -Wextra -Wpedantic
+ ifeq ($(shell $(CXX) -v 2>&1 | grep -c "clang version"), 1)
+ CXXFLAGS += -Wshadow -Wsign-conversion
+ endif
+ endif
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ ifeq ($(WITH_EXTRA_WARNINGS), 1)
+ CXXFLAGS += -Weverything -Wno-reserved-id-macro -Wno-c++98-compat-pedantic -Wno-padded -Wno-c++11-long-long -Wno-poison-system-directories
+ endif
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ ifeq ($(WITH_EXTRA_WARNINGS), 1)
+ CXXFLAGS += -Wextra -Wpedantic
+ endif
+ LIBS += -limm32
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/misc/freetype/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_null/build_win32.bat b/Client/ThirdParty/imgui/examples/example_null/build_win32.bat
new file mode 100644
index 0000000..0cdfdc9
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_null/build_win32.bat
@@ -0,0 +1,3 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+mkdir Debug
+cl /nologo /Zi /MD /I ..\.. %* *.cpp ..\..\*.cpp /FeDebug/example_null.exe /FoDebug/ /link gdi32.lib shell32.lib imm32.lib
diff --git a/Client/ThirdParty/imgui/examples/example_null/main.cpp b/Client/ThirdParty/imgui/examples/example_null/main.cpp
new file mode 100644
index 0000000..72381f0
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_null/main.cpp
@@ -0,0 +1,37 @@
+// dear imgui: "null" example application
+// (compile and link imgui, create context, run headless with NO INPUTS, NO GRAPHICS OUTPUT)
+// This is useful to test building, but you cannot interact with anything here!
+#include "imgui.h"
+#include <stdio.h>
+
+int main(int, char**)
+{
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Build atlas
+ unsigned char* tex_pixels = NULL;
+ int tex_w, tex_h;
+ io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
+
+ for (int n = 0; n < 20; n++)
+ {
+ printf("NewFrame() %d\n", n);
+ io.DisplaySize = ImVec2(1920, 1080);
+ io.DeltaTime = 1.0f / 60.0f;
+ ImGui::NewFrame();
+
+ static float f = 0.0f;
+ ImGui::Text("Hello, world!");
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+ ImGui::ShowDemoWindow(NULL);
+
+ ImGui::Render();
+ }
+
+ printf("DestroyContext()\n");
+ ImGui::DestroyContext();
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_directx11/build_win32.bat b/Client/ThirdParty/imgui/examples/example_sdl_directx11/build_win32.bat
new file mode 100644
index 0000000..b930827
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_directx11/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_sdl_directx11
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib shell32.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj b/Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj
new file mode 100644
index 0000000..ac636d2
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9E1987E3-1F19-45CA-B9C9-D31E791836D8}</ProjectGuid>
+ <RootNamespace>example_sdl_directx11</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <ProjectName>example_sdl_directx11</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_dx11.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_dx11.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters
new file mode 100644
index 0000000..15fc853
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_directx11/example_sdl_directx11.vcxproj.filters
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_dx11.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_dx11.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_directx11/main.cpp b/Client/ThirdParty/imgui/examples/example_sdl_directx11/main.cpp
new file mode 100644
index 0000000..fc51715
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_directx11/main.cpp
@@ -0,0 +1,230 @@
+// Dear ImGui: standalone example application for SDL2 + DirectX 11
+// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_dx11.h"
+#include <d3d11.h>
+#include <stdio.h>
+#include <SDL.h>
+#include <SDL_syswm.h>
+
+// Data
+static ID3D11Device* g_pd3dDevice = NULL;
+static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
+static IDXGISwapChain* g_pSwapChain = NULL;
+static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
+
+// Forward declarations of helper functions
+bool CreateDeviceD3D(HWND hWnd);
+void CleanupDeviceD3D();
+void CreateRenderTarget();
+void CleanupRenderTarget();
+
+// Main code
+int main(int, char**)
+{
+ // Setup SDL
+ // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
+ // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Setup window
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+DirectX11 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
+ SDL_SysWMinfo wmInfo;
+ SDL_VERSION(&wmInfo.version);
+ SDL_GetWindowWMInfo(window, &wmInfo);
+ HWND hwnd = (HWND)wmInfo.info.win.window;
+
+ // Initialize Direct3D
+ if (!CreateDeviceD3D(hwnd))
+ {
+ CleanupDeviceD3D();
+ return 1;
+ }
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForD3D(window);
+ ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
+ {
+ // Release all outstanding references to the swap chain's buffers before resizing.
+ CleanupRenderTarget();
+ g_pSwapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
+ CreateRenderTarget();
+ }
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplDX11_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
+ g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
+ g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
+ ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+
+ g_pSwapChain->Present(1, 0); // Present with vsync
+ //g_pSwapChain->Present(0, 0); // Present without vsync
+ }
+
+ // Cleanup
+ ImGui_ImplDX11_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupDeviceD3D();
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ return 0;
+}
+
+// Helper functions
+
+bool CreateDeviceD3D(HWND hWnd)
+{
+ // Setup swap chain
+ DXGI_SWAP_CHAIN_DESC sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = 2;
+ sd.BufferDesc.Width = 0;
+ sd.BufferDesc.Height = 0;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.OutputWindow = hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.Windowed = TRUE;
+ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ UINT createDeviceFlags = 0;
+ //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+ D3D_FEATURE_LEVEL featureLevel;
+ const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
+ if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
+ return false;
+
+ CreateRenderTarget();
+ return true;
+}
+
+void CleanupDeviceD3D()
+{
+ CleanupRenderTarget();
+ if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
+ if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
+ if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
+}
+
+void CreateRenderTarget()
+{
+ ID3D11Texture2D* pBackBuffer;
+ g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
+ g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
+ pBackBuffer->Release();
+}
+
+void CleanupRenderTarget()
+{
+ if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
+}
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_metal/Makefile b/Client/ThirdParty/imgui/examples/example_sdl_metal/Makefile
new file mode 100644
index 0000000..042bb04
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_metal/Makefile
@@ -0,0 +1,47 @@
+#
+# You will need SDL2 (http://www.libsdl.org):
+# brew install sdl2
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_sdl_metal
+IMGUI_DIR = ../..
+SOURCES = main.mm
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_metal.mm
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+
+LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
+LIBS += `sdl2-config --libs`
+LIBS += -L/usr/local/lib
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include
+CXXFLAGS += `sdl2-config --cflags`
+CXXFLAGS += -Wall -Wformat
+CFLAGS = $(CXXFLAGS)
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:%.mm
+ $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.mm
+ $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_metal/main.mm b/Client/ThirdParty/imgui/examples/example_sdl_metal/main.mm
new file mode 100644
index 0000000..caa86e6
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_metal/main.mm
@@ -0,0 +1,181 @@
+// Dear ImGui: standalone example application for SDL2 + Metal
+// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_metal.h"
+#include <stdio.h>
+#include <SDL.h>
+
+#import <Metal/Metal.h>
+#import <QuartzCore/QuartzCore.h>
+
+int main(int, char**)
+{
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.txt' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Setup SDL
+ // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
+ // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Inform SDL that we will be using metal for rendering. Without this hint initialization of metal renderer may fail.
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");
+
+ SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL+Metal example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ if (window == NULL)
+ {
+ printf("Error creating window: %s\n", SDL_GetError());
+ return -2;
+ }
+
+ SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+ if (renderer == NULL)
+ {
+ printf("Error creating renderer: %s\n", SDL_GetError());
+ return -3;
+ }
+
+ // Setup Platform/Renderer backends
+ CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_RenderGetMetalLayer(renderer);
+ layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ ImGui_ImplMetal_Init(layer.device);
+ ImGui_ImplSDL2_InitForMetal(window);
+
+ id<MTLCommandQueue> commandQueue = [layer.device newCommandQueue];
+ MTLRenderPassDescriptor* renderPassDescriptor = [MTLRenderPassDescriptor new];
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f};
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ @autoreleasepool
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+ done = true;
+ }
+
+ int width, height;
+ SDL_GetRendererOutputSize(renderer, &width, &height);
+ layer.drawableSize = CGSizeMake(width, height);
+ id<CAMetalDrawable> drawable = [layer nextDrawable];
+
+ id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer];
+ renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0] * clear_color[3], clear_color[1] * clear_color[3], clear_color[2] * clear_color[3], clear_color[3]);
+ renderPassDescriptor.colorAttachments[0].texture = drawable.texture;
+ renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
+ renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
+ id <MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
+ [renderEncoder pushDebugGroup:@"ImGui demo"];
+
+ // Start the Dear ImGui frame
+ ImGui_ImplMetal_NewFrame(renderPassDescriptor);
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder);
+
+ [renderEncoder popDebugGroup];
+ [renderEncoder endEncoding];
+
+ [commandBuffer presentDrawable:drawable];
+ [commandBuffer commit];
+ }
+ }
+
+ // Cleanup
+ ImGui_ImplMetal_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl2/Makefile b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/Makefile
new file mode 100644
index 0000000..92e0554
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/Makefile
@@ -0,0 +1,79 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# You will need SDL2 (http://www.libsdl.org):
+# Linux:
+# apt-get install libsdl2-dev
+# Mac OS X:
+# brew install sdl2
+# MSYS2:
+# pacman -S mingw-w64-i686-SDL2
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_sdl_opengl2
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl2.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ LIBS += -lGL -ldl `sdl2-config --libs`
+
+ CXXFLAGS += `sdl2-config --cflags`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
+ LIBS += -L/usr/local/lib -L/opt/local/lib
+
+ CXXFLAGS += `sdl2-config --cflags`
+ CXXFLAGS += -I/usr/local/include -I/opt/local/include
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
+
+ CXXFLAGS += `pkg-config --cflags sdl2`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl2/README.md b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/README.md
new file mode 100644
index 0000000..2bf4d03
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/README.md
@@ -0,0 +1,29 @@
+
+# How to Build
+
+- On Windows with Visual Studio's IDE
+
+Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) if necessary.
+
+- On Windows with Visual Studio's CLI
+
+```
+set SDL2_DIR=path_to_your_sdl2_folder
+cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl2.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
+# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries
+# or for 64-bit:
+cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl2.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
+```
+
+- On Linux and similar Unixes
+
+```
+c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL
+```
+
+- On Mac OS X
+
+```
+brew install sdl2
+c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl
+```
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl2/build_win32.bat b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/build_win32.bat
new file mode 100644
index 0000000..47529e2
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_sdl_opengl2
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib shell32.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj
new file mode 100644
index 0000000..d22a67b
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}</ProjectGuid>
+ <RootNamespace>example_sdl_opengl2</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_opengl2.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl2.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters
new file mode 100644
index 0000000..2253b86
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/example_sdl_opengl2.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_opengl2.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl2.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl2/main.cpp b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/main.cpp
new file mode 100644
index 0000000..a81f856
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl2/main.cpp
@@ -0,0 +1,157 @@
+// Dear ImGui: standalone example application for SDL2 + OpenGL
+// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)**
+// **Prefer using the code in the example_sdl_opengl3/ folder**
+// See imgui_impl_sdl.cpp for details.
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_opengl2.h"
+#include <stdio.h>
+#include <SDL.h>
+#include <SDL_opengl.h>
+
+// Main code
+int main(int, char**)
+{
+ // Setup SDL
+ // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
+ // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Setup window
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
+ SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+ SDL_GL_MakeCurrent(window, gl_context);
+ SDL_GL_SetSwapInterval(1); // Enable vsync
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
+ ImGui_ImplOpenGL2_Init();
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+ done = true;
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL2_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound
+ ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
+ SDL_GL_SwapWindow(window);
+ }
+
+ // Cleanup
+ ImGui_ImplOpenGL2_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ SDL_GL_DeleteContext(gl_context);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl3/Makefile b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/Makefile
new file mode 100644
index 0000000..1b8ab42
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/Makefile
@@ -0,0 +1,91 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# You will need SDL2 (http://www.libsdl.org):
+# Linux:
+# apt-get install libsdl2-dev
+# Mac OS X:
+# brew install sdl2
+# MSYS2:
+# pacman -S mingw-w64-i686-SDL2
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_sdl_opengl3
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+LINUX_GL_LIBS = -lGL
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+##---------------------------------------------------------------------
+## OPENGL ES
+##---------------------------------------------------------------------
+
+## This assumes a GL ES library available in the system, e.g. libGLESv2.so
+# CXXFLAGS += -DIMGUI_IMPL_OPENGL_ES2
+# LINUX_GL_LIBS = -lGLESv2
+## If you're on a Raspberry Pi and want to use the legacy drivers,
+## use the following instead:
+# LINUX_GL_LIBS = -L/opt/vc/lib -lbrcmGLESv2
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ LIBS += $(LINUX_GL_LIBS) -ldl `sdl2-config --libs`
+
+ CXXFLAGS += `sdl2-config --cflags`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
+ LIBS += -L/usr/local/lib -L/opt/local/lib
+
+ CXXFLAGS += `sdl2-config --cflags`
+ CXXFLAGS += -I/usr/local/include -I/opt/local/include
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
+
+ CXXFLAGS += `pkg-config --cflags sdl2`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl3/README.md b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/README.md
new file mode 100644
index 0000000..06d4b2d
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/README.md
@@ -0,0 +1,29 @@
+
+# How to Build
+
+- On Windows with Visual Studio's IDE
+
+Use the provided project file (.vcxproj). Add to solution (imgui_examples.sln) if necessary.
+
+- On Windows with Visual Studio's CLI
+
+```
+set SDL2_DIR=path_to_your_sdl2_folder
+cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
+# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries
+# or for 64-bit:
+cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_opengl3.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console
+```
+
+- On Linux and similar Unixes
+
+```
+c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -ldl
+```
+
+- On Mac OS X
+
+```
+brew install sdl2
+c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -framework CoreFoundation
+```
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl3/build_win32.bat b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/build_win32.bat
new file mode 100644
index 0000000..20851bf
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_sdl_opengl3
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib shell32.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj
new file mode 100644
index 0000000..ace041d
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BBAEB705-1669-40F3-8567-04CF6A991F4C}</ProjectGuid>
+ <RootNamespace>example_sdl_opengl3</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_opengl3.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3_loader.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters
new file mode 100644
index 0000000..c8dbeae
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/example_sdl_opengl3.vcxproj.filters
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_opengl3.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_opengl3_loader.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_opengl3/main.cpp b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/main.cpp
new file mode 100644
index 0000000..a7e7fc0
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_opengl3/main.cpp
@@ -0,0 +1,178 @@
+// Dear ImGui: standalone example application for SDL2 + OpenGL
+// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_opengl3.h"
+#include <stdio.h>
+#include <SDL.h>
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+#include <SDL_opengles2.h>
+#else
+#include <SDL_opengl.h>
+#endif
+
+// Main code
+int main(int, char**)
+{
+ // Setup SDL
+ // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
+ // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Decide GL+GLSL versions
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+ // GL ES 2.0 + GLSL 100
+ const char* glsl_version = "#version 100";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#elif defined(__APPLE__)
+ // GL 3.2 Core + GLSL 150
+ const char* glsl_version = "#version 150";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+#else
+ // GL 3.0 + GLSL 130
+ const char* glsl_version = "#version 130";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#endif
+
+ // Create window with graphics context
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
+ SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+ SDL_GL_MakeCurrent(window, gl_context);
+ SDL_GL_SetSwapInterval(1); // Enable vsync
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
+ ImGui_ImplOpenGL3_Init(glsl_version);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+ done = true;
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+ SDL_GL_SwapWindow(window);
+ }
+
+ // Cleanup
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ SDL_GL_DeleteContext(gl_context);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/Makefile b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/Makefile
new file mode 100644
index 0000000..5667789
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/Makefile
@@ -0,0 +1,79 @@
+#
+# Cross Platform Makefile
+# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
+#
+# You will need SDL2 (http://www.libsdl.org):
+# Linux:
+# apt-get install libsdl2-dev
+# Mac OS X:
+# brew install sdl2
+# MSYS2:
+# pacman -S mingw-w64-i686-SDL2
+#
+
+#CXX = g++
+#CXX = clang++
+
+EXE = example_sdl_sdlrenderer
+IMGUI_DIR = ../..
+SOURCES = main.cpp
+SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
+SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_sdlrenderer.cpp
+OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
+UNAME_S := $(shell uname -s)
+
+CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
+CXXFLAGS += -g -Wall -Wformat
+LIBS =
+
+##---------------------------------------------------------------------
+## BUILD FLAGS PER PLATFORM
+##---------------------------------------------------------------------
+
+ifeq ($(UNAME_S), Linux) #LINUX
+ ECHO_MESSAGE = "Linux"
+ LIBS += -lGL -ldl `sdl2-config --libs`
+
+ CXXFLAGS += `sdl2-config --cflags`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(UNAME_S), Darwin) #APPLE
+ ECHO_MESSAGE = "Mac OS X"
+ LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
+ LIBS += -L/usr/local/lib -L/opt/local/lib
+
+ CXXFLAGS += `sdl2-config --cflags`
+ CXXFLAGS += -I/usr/local/include -I/opt/local/include
+ CFLAGS = $(CXXFLAGS)
+endif
+
+ifeq ($(OS), Windows_NT)
+ ECHO_MESSAGE = "MinGW"
+ LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
+
+ CXXFLAGS += `pkg-config --cflags sdl2`
+ CFLAGS = $(CXXFLAGS)
+endif
+
+##---------------------------------------------------------------------
+## BUILD RULES
+##---------------------------------------------------------------------
+
+%.o:%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+%.o:$(IMGUI_DIR)/backends/%.cpp
+ $(CXX) $(CXXFLAGS) -c -o $@ $<
+
+all: $(EXE)
+ @echo Build complete for $(ECHO_MESSAGE)
+
+$(EXE): $(OBJS)
+ $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
+
+clean:
+ rm -f $(EXE) $(OBJS)
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/README.md b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/README.md
new file mode 100644
index 0000000..209f15a
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/README.md
@@ -0,0 +1,25 @@
+
+# How to Build
+
+- On Windows with Visual Studio's CLI
+
+```
+set SDL2_DIR=path_to_your_sdl2_folder
+cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_sdlrenderer.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /subsystem:console
+# ^^ include paths ^^ source files ^^ output exe ^^ output dir ^^ libraries
+# or for 64-bit:
+cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp /FeDebug/example_sdl_sdlrenderer.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x64 SDL2.lib SDL2main.lib /subsystem:console
+```
+
+- On Linux and similar Unixes
+
+```
+c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_sdlrenderer.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL
+```
+
+- On Mac OS X
+
+```
+brew install sdl2
+c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_sdlrenderer.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl
+```
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/build_win32.bat b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/build_win32.bat
new file mode 100644
index 0000000..6c1b5fd
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_sdl_sdlrenderer_
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_sdlrenderer.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj
new file mode 100644
index 0000000..4d502ab
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741}</ProjectGuid>
+ <RootNamespace>example_sdl_sdlrenderer</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%SDL2_DIR%\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_sdlrenderer.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_sdlrenderer.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters
new file mode 100644
index 0000000..01e98fc
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/example_sdl_sdlrenderer.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_sdlrenderer.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_sdlrenderer.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/main.cpp b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/main.cpp
new file mode 100644
index 0000000..aee4a78
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_sdlrenderer/main.cpp
@@ -0,0 +1,161 @@
+// Dear ImGui: standalone example application for SDL2 + SDL_Renderer
+// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.)
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
+// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
+// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_sdlrenderer.h"
+#include <stdio.h>
+#include <SDL.h>
+
+#if !SDL_VERSION_ATLEAST(2,0,17)
+#error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
+#endif
+
+// Main code
+int main(int, char**)
+{
+ // Setup SDL
+ // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
+ // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Setup window
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
+
+ // Setup SDL_Renderer instance
+ SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
+ if (renderer == NULL)
+ {
+ SDL_Log("Error creating SDL_Renderer!");
+ return false;
+ }
+ //SDL_RendererInfo info;
+ //SDL_GetRendererInfo(renderer, &info);
+ //SDL_Log("Current SDL_Renderer: %s", info.name);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForSDLRenderer(window);
+ ImGui_ImplSDLRenderer_Init(renderer);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+ done = true;
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplSDLRenderer_NewFrame();
+ ImGui_ImplSDL2_NewFrame(window);
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255));
+ SDL_RenderClear(renderer);
+ ImGui_ImplSDLRenderer_RenderDrawData(ImGui::GetDrawData());
+ SDL_RenderPresent(renderer);
+ }
+
+ // Cleanup
+ ImGui_ImplSDLRenderer_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_vulkan/build_win32.bat b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/build_win32.bat
new file mode 100644
index 0000000..21b5ea3
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/build_win32.bat
@@ -0,0 +1,10 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+
+@set OUT_EXE=example_sdl_vulkan
+@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I %VULKAN_SDK%\include
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 /libpath:%VULKAN_SDK%\lib32 SDL2.lib SDL2main.lib shell32.lib vulkan-1.lib
+
+@set OUT_DIR=Debug
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj
new file mode 100644
index 0000000..5cc3eab
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{BAE3D0B5-9695-4EB1-AD0F-75890EB4A3B3}</ProjectGuid>
+ <RootNamespace>example_sdl_vulkan</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib;%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>msvcrt.lib</IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib32;%SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%VULKAN_SDK%\include;%SDL2_DIR%\include;$(VcpkgCurrentInstalledDir)include\SDL2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%VULKAN_SDK%\lib;%SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>vulkan-1.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_vulkan.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_vulkan.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters
new file mode 100644
index 0000000..063a593
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/example_sdl_vulkan.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{20b90ce4-7fcb-4731-b9a0-075f875de82d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{f18ab499-84e1-499f-8eff-9754361e0e52}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_sdl.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_vulkan.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_sdl.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_vulkan.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_sdl_vulkan/main.cpp b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/main.cpp
new file mode 100644
index 0000000..2c01afe
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_sdl_vulkan/main.cpp
@@ -0,0 +1,559 @@
+// Dear ImGui: standalone example application for SDL2 + Vulkan
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
+// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
+// You will use those if you want to use this rendering backend in your engine/app.
+// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
+// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
+// Read comments in imgui_impl_vulkan.h.
+
+#include "imgui.h"
+#include "imgui_impl_sdl.h"
+#include "imgui_impl_vulkan.h"
+#include <stdio.h> // printf, fprintf
+#include <stdlib.h> // abort
+#include <SDL.h>
+#include <SDL_vulkan.h>
+#include <vulkan/vulkan.h>
+
+//#define IMGUI_UNLIMITED_FRAME_RATE
+#ifdef _DEBUG
+#define IMGUI_VULKAN_DEBUG_REPORT
+#endif
+
+static VkAllocationCallbacks* g_Allocator = NULL;
+static VkInstance g_Instance = VK_NULL_HANDLE;
+static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
+static VkDevice g_Device = VK_NULL_HANDLE;
+static uint32_t g_QueueFamily = (uint32_t)-1;
+static VkQueue g_Queue = VK_NULL_HANDLE;
+static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
+static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
+static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
+
+static ImGui_ImplVulkanH_Window g_MainWindowData;
+static uint32_t g_MinImageCount = 2;
+static bool g_SwapChainRebuild = false;
+
+static void check_vk_result(VkResult err)
+{
+ if (err == 0)
+ return;
+ fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
+ if (err < 0)
+ abort();
+}
+
+#ifdef IMGUI_VULKAN_DEBUG_REPORT
+static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
+{
+ (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
+ fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
+ return VK_FALSE;
+}
+#endif // IMGUI_VULKAN_DEBUG_REPORT
+
+static void SetupVulkan(const char** extensions, uint32_t extensions_count)
+{
+ VkResult err;
+
+ // Create Vulkan Instance
+ {
+ VkInstanceCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ create_info.enabledExtensionCount = extensions_count;
+ create_info.ppEnabledExtensionNames = extensions;
+#ifdef IMGUI_VULKAN_DEBUG_REPORT
+ // Enabling validation layers
+ const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
+ create_info.enabledLayerCount = 1;
+ create_info.ppEnabledLayerNames = layers;
+
+ // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
+ const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
+ memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
+ extensions_ext[extensions_count] = "VK_EXT_debug_report";
+ create_info.enabledExtensionCount = extensions_count + 1;
+ create_info.ppEnabledExtensionNames = extensions_ext;
+
+ // Create Vulkan Instance
+ err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+ check_vk_result(err);
+ free(extensions_ext);
+
+ // Get the function pointer (required for any extensions)
+ auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
+ IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
+
+ // Setup the debug report callback
+ VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
+ debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
+ debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ debug_report_ci.pfnCallback = debug_report;
+ debug_report_ci.pUserData = NULL;
+ err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
+ check_vk_result(err);
+#else
+ // Create Vulkan Instance without any debug feature
+ err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
+ check_vk_result(err);
+ IM_UNUSED(g_DebugReport);
+#endif
+ }
+
+ // Select GPU
+ {
+ uint32_t gpu_count;
+ err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
+ check_vk_result(err);
+ IM_ASSERT(gpu_count > 0);
+
+ VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
+ err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
+ check_vk_result(err);
+
+ // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
+ // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
+ // dedicated GPUs) is out of scope of this sample.
+ int use_gpu = 0;
+ for (int i = 0; i < (int)gpu_count; i++)
+ {
+ VkPhysicalDeviceProperties properties;
+ vkGetPhysicalDeviceProperties(gpus[i], &properties);
+ if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+ {
+ use_gpu = i;
+ break;
+ }
+ }
+
+ g_PhysicalDevice = gpus[use_gpu];
+ free(gpus);
+ }
+
+ // Select graphics queue family
+ {
+ uint32_t count;
+ vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
+ VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
+ vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
+ for (uint32_t i = 0; i < count; i++)
+ if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+ {
+ g_QueueFamily = i;
+ break;
+ }
+ free(queues);
+ IM_ASSERT(g_QueueFamily != (uint32_t)-1);
+ }
+
+ // Create Logical Device (with 1 queue)
+ {
+ int device_extension_count = 1;
+ const char* device_extensions[] = { "VK_KHR_swapchain" };
+ const float queue_priority[] = { 1.0f };
+ VkDeviceQueueCreateInfo queue_info[1] = {};
+ queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queue_info[0].queueFamilyIndex = g_QueueFamily;
+ queue_info[0].queueCount = 1;
+ queue_info[0].pQueuePriorities = queue_priority;
+ VkDeviceCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
+ create_info.pQueueCreateInfos = queue_info;
+ create_info.enabledExtensionCount = device_extension_count;
+ create_info.ppEnabledExtensionNames = device_extensions;
+ err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
+ check_vk_result(err);
+ vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
+ }
+
+ // Create Descriptor Pool
+ {
+ VkDescriptorPoolSize pool_sizes[] =
+ {
+ { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
+ { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
+ { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
+ };
+ VkDescriptorPoolCreateInfo pool_info = {};
+ pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
+ pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
+ pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
+ pool_info.pPoolSizes = pool_sizes;
+ err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
+ check_vk_result(err);
+ }
+}
+
+// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
+// Your real engine/app may not use them.
+static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
+{
+ wd->Surface = surface;
+
+ // Check for WSI support
+ VkBool32 res;
+ vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
+ if (res != VK_TRUE)
+ {
+ fprintf(stderr, "Error no WSI support on physical device 0\n");
+ exit(-1);
+ }
+
+ // Select Surface Format
+ const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
+ const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
+
+ // Select Present Mode
+#ifdef IMGUI_UNLIMITED_FRAME_RATE
+ VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
+#else
+ VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
+#endif
+ wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
+ //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
+
+ // Create SwapChain, RenderPass, Framebuffer, etc.
+ IM_ASSERT(g_MinImageCount >= 2);
+ ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
+}
+
+static void CleanupVulkan()
+{
+ vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
+
+#ifdef IMGUI_VULKAN_DEBUG_REPORT
+ // Remove the debug report callback
+ auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
+ vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
+#endif // IMGUI_VULKAN_DEBUG_REPORT
+
+ vkDestroyDevice(g_Device, g_Allocator);
+ vkDestroyInstance(g_Instance, g_Allocator);
+}
+
+static void CleanupVulkanWindow()
+{
+ ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
+}
+
+static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
+{
+ VkResult err;
+
+ VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
+ VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+ err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
+ if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
+ {
+ g_SwapChainRebuild = true;
+ return;
+ }
+ check_vk_result(err);
+
+ ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
+ {
+ err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
+ check_vk_result(err);
+
+ err = vkResetFences(g_Device, 1, &fd->Fence);
+ check_vk_result(err);
+ }
+ {
+ err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
+ check_vk_result(err);
+ VkCommandBufferBeginInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
+ check_vk_result(err);
+ }
+ {
+ VkRenderPassBeginInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ info.renderPass = wd->RenderPass;
+ info.framebuffer = fd->Framebuffer;
+ info.renderArea.extent.width = wd->Width;
+ info.renderArea.extent.height = wd->Height;
+ info.clearValueCount = 1;
+ info.pClearValues = &wd->ClearValue;
+ vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
+ }
+
+ // Record dear imgui primitives into command buffer
+ ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
+
+ // Submit command buffer
+ vkCmdEndRenderPass(fd->CommandBuffer);
+ {
+ VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkSubmitInfo info = {};
+ info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ info.waitSemaphoreCount = 1;
+ info.pWaitSemaphores = &image_acquired_semaphore;
+ info.pWaitDstStageMask = &wait_stage;
+ info.commandBufferCount = 1;
+ info.pCommandBuffers = &fd->CommandBuffer;
+ info.signalSemaphoreCount = 1;
+ info.pSignalSemaphores = &render_complete_semaphore;
+
+ err = vkEndCommandBuffer(fd->CommandBuffer);
+ check_vk_result(err);
+ err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
+ check_vk_result(err);
+ }
+}
+
+static void FramePresent(ImGui_ImplVulkanH_Window* wd)
+{
+ if (g_SwapChainRebuild)
+ return;
+ VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
+ VkPresentInfoKHR info = {};
+ info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ info.waitSemaphoreCount = 1;
+ info.pWaitSemaphores = &render_complete_semaphore;
+ info.swapchainCount = 1;
+ info.pSwapchains = &wd->Swapchain;
+ info.pImageIndices = &wd->FrameIndex;
+ VkResult err = vkQueuePresentKHR(g_Queue, &info);
+ if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
+ {
+ g_SwapChainRebuild = true;
+ return;
+ }
+ check_vk_result(err);
+ wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
+}
+
+int main(int, char**)
+{
+ // Setup SDL
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ // Setup window
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
+
+ // Setup Vulkan
+ uint32_t extensions_count = 0;
+ SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, NULL);
+ const char** extensions = new const char*[extensions_count];
+ SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, extensions);
+ SetupVulkan(extensions, extensions_count);
+ delete[] extensions;
+
+ // Create Window Surface
+ VkSurfaceKHR surface;
+ VkResult err;
+ if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
+ {
+ printf("Failed to create Vulkan surface.\n");
+ return 1;
+ }
+
+ // Create Framebuffers
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+ ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
+ SetupVulkanWindow(wd, surface, w, h);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForVulkan(window);
+ ImGui_ImplVulkan_InitInfo init_info = {};
+ init_info.Instance = g_Instance;
+ init_info.PhysicalDevice = g_PhysicalDevice;
+ init_info.Device = g_Device;
+ init_info.QueueFamily = g_QueueFamily;
+ init_info.Queue = g_Queue;
+ init_info.PipelineCache = g_PipelineCache;
+ init_info.DescriptorPool = g_DescriptorPool;
+ init_info.Allocator = g_Allocator;
+ init_info.MinImageCount = g_MinImageCount;
+ init_info.ImageCount = wd->ImageCount;
+ init_info.CheckVkResultFn = check_vk_result;
+ ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Upload Fonts
+ {
+ // Use any command queue
+ VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
+ VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
+
+ err = vkResetCommandPool(g_Device, command_pool, 0);
+ check_vk_result(err);
+ VkCommandBufferBeginInfo begin_info = {};
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ err = vkBeginCommandBuffer(command_buffer, &begin_info);
+ check_vk_result(err);
+
+ ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
+
+ VkSubmitInfo end_info = {};
+ end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ end_info.commandBufferCount = 1;
+ end_info.pCommandBuffers = &command_buffer;
+ err = vkEndCommandBuffer(command_buffer);
+ check_vk_result(err);
+ err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE);
+ check_vk_result(err);
+
+ err = vkDeviceWaitIdle(g_Device);
+ check_vk_result(err);
+ ImGui_ImplVulkan_DestroyFontUploadObjects();
+ }
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
+ done = true;
+ }
+
+ // Resize swap chain?
+ if (g_SwapChainRebuild)
+ {
+ int width, height;
+ SDL_GetWindowSize(window, &width, &height);
+ if (width > 0 && height > 0)
+ {
+ ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
+ ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
+ g_MainWindowData.FrameIndex = 0;
+ g_SwapChainRebuild = false;
+ }
+ }
+
+ // Start the Dear ImGui frame
+ ImGui_ImplVulkan_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+ const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
+ if (!is_minimized)
+ {
+ wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
+ wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
+ wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
+ wd->ClearValue.color.float32[3] = clear_color.w;
+ FrameRender(wd, draw_data);
+ FramePresent(wd);
+ }
+ }
+
+ // Cleanup
+ err = vkDeviceWaitIdle(g_Device);
+ check_vk_result(err);
+ ImGui_ImplVulkan_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupVulkanWindow();
+ CleanupVulkan();
+
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx10/build_win32.bat b/Client/ThirdParty/imgui/examples/example_win32_directx10/build_win32.bat
new file mode 100644
index 0000000..fd74223
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx10/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_win32_directx10
+@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\backends\imgui_impl_dx10.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d10.lib d3dcompiler.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj b/Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj
new file mode 100644
index 0000000..e71cb0a
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{345A953E-A004-4648-B442-DC5F9F11068C}</ProjectGuid>
+ <RootNamespace>example_win32_directx10</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>d3d10.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>d3d10.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>d3d10.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>d3d10.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_dx10.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_dx10.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj.filters
new file mode 100644
index 0000000..11ad8f9
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx10/example_win32_directx10.vcxproj.filters
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_dx10.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_dx10.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx10/main.cpp b/Client/ThirdParty/imgui/examples/example_win32_directx10/main.cpp
new file mode 100644
index 0000000..ad88d1e
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx10/main.cpp
@@ -0,0 +1,242 @@
+// Dear ImGui: standalone example application for DirectX 10
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_win32.h"
+#include "imgui_impl_dx10.h"
+#include <d3d10_1.h>
+#include <d3d10.h>
+#include <tchar.h>
+
+// Data
+static ID3D10Device* g_pd3dDevice = NULL;
+static IDXGISwapChain* g_pSwapChain = NULL;
+static ID3D10RenderTargetView* g_mainRenderTargetView = NULL;
+
+// Forward declarations of helper functions
+bool CreateDeviceD3D(HWND hWnd);
+void CleanupDeviceD3D();
+void CreateRenderTarget();
+void CleanupRenderTarget();
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Main code
+int main(int, char**)
+{
+ // Create application window
+ //ImGui_ImplWin32_EnableDpiAwareness();
+ WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
+ ::RegisterClassEx(&wc);
+ HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX10 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
+
+ // Initialize Direct3D
+ if (!CreateDeviceD3D(hwnd))
+ {
+ CleanupDeviceD3D();
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ return 1;
+ }
+
+ // Show the window
+ ::ShowWindow(hwnd, SW_SHOWDEFAULT);
+ ::UpdateWindow(hwnd);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplWin32_Init(hwnd);
+ ImGui_ImplDX10_Init(g_pd3dDevice);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle messages (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ MSG msg;
+ while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+ {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ if (msg.message == WM_QUIT)
+ done = true;
+ }
+ if (done)
+ break;
+
+ // Start the Dear ImGui frame
+ ImGui_ImplDX10_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
+ g_pd3dDevice->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
+ g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
+ ImGui_ImplDX10_RenderDrawData(ImGui::GetDrawData());
+
+ g_pSwapChain->Present(1, 0); // Present with vsync
+ //g_pSwapChain->Present(0, 0); // Present without vsync
+ }
+
+ ImGui_ImplDX10_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupDeviceD3D();
+ ::DestroyWindow(hwnd);
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+
+ return 0;
+}
+
+// Helper functions
+
+bool CreateDeviceD3D(HWND hWnd)
+{
+ // Setup swap chain
+ DXGI_SWAP_CHAIN_DESC sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = 2;
+ sd.BufferDesc.Width = 0;
+ sd.BufferDesc.Height = 0;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.OutputWindow = hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.Windowed = TRUE;
+ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ UINT createDeviceFlags = 0;
+ //createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
+ if (D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice) != S_OK)
+ return false;
+
+ CreateRenderTarget();
+ return true;
+}
+
+void CleanupDeviceD3D()
+{
+ CleanupRenderTarget();
+ if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
+ if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
+}
+
+void CreateRenderTarget()
+{
+ ID3D10Texture2D* pBackBuffer;
+ g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
+ g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
+ pBackBuffer->Release();
+}
+
+void CleanupRenderTarget()
+{
+ if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
+}
+
+// Forward declare message handler from imgui_impl_win32.cpp
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Win32 message handler
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
+ return true;
+
+ switch (msg)
+ {
+ case WM_SIZE:
+ if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
+ {
+ CleanupRenderTarget();
+ g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
+ CreateRenderTarget();
+ }
+ return 0;
+ case WM_SYSCOMMAND:
+ if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
+ return 0;
+ break;
+ case WM_DESTROY:
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ return ::DefWindowProc(hWnd, msg, wParam, lParam);
+}
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx11/build_win32.bat b/Client/ThirdParty/imgui/examples/example_win32_directx11/build_win32.bat
new file mode 100644
index 0000000..b1cf7d1
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx11/build_win32.bat
@@ -0,0 +1,9 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_win32_directx11
+@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
+
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj b/Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj
new file mode 100644
index 0000000..273d351
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9F316E83-5AE5-4939-A723-305A94F48005}</ProjectGuid>
+ <RootNamespace>example_win32_directx11</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>d3d11.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_dx11.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_dx11.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters
new file mode 100644
index 0000000..02cf18c
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx11/example_win32_directx11.vcxproj.filters
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{0587d7a3-f2ce-4d56-b84f-a0005d3bfce6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{08e36723-ce4f-4cff-9662-c40801cf1acf}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_dx11.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_dx11.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx11/main.cpp b/Client/ThirdParty/imgui/examples/example_win32_directx11/main.cpp
new file mode 100644
index 0000000..7f1b4b8
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx11/main.cpp
@@ -0,0 +1,246 @@
+// Dear ImGui: standalone example application for DirectX 11
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_win32.h"
+#include "imgui_impl_dx11.h"
+#include <d3d11.h>
+#include <tchar.h>
+
+// Data
+static ID3D11Device* g_pd3dDevice = NULL;
+static ID3D11DeviceContext* g_pd3dDeviceContext = NULL;
+static IDXGISwapChain* g_pSwapChain = NULL;
+static ID3D11RenderTargetView* g_mainRenderTargetView = NULL;
+
+// Forward declarations of helper functions
+bool CreateDeviceD3D(HWND hWnd);
+void CleanupDeviceD3D();
+void CreateRenderTarget();
+void CleanupRenderTarget();
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Main code
+int main(int, char**)
+{
+ // Create application window
+ //ImGui_ImplWin32_EnableDpiAwareness();
+ WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
+ ::RegisterClassEx(&wc);
+ HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX11 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
+
+ // Initialize Direct3D
+ if (!CreateDeviceD3D(hwnd))
+ {
+ CleanupDeviceD3D();
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ return 1;
+ }
+
+ // Show the window
+ ::ShowWindow(hwnd, SW_SHOWDEFAULT);
+ ::UpdateWindow(hwnd);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplWin32_Init(hwnd);
+ ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle messages (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ MSG msg;
+ while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+ {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ if (msg.message == WM_QUIT)
+ done = true;
+ }
+ if (done)
+ break;
+
+ // Start the Dear ImGui frame
+ ImGui_ImplDX11_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+ const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
+ g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL);
+ g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
+ ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+
+ g_pSwapChain->Present(1, 0); // Present with vsync
+ //g_pSwapChain->Present(0, 0); // Present without vsync
+ }
+
+ // Cleanup
+ ImGui_ImplDX11_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupDeviceD3D();
+ ::DestroyWindow(hwnd);
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+
+ return 0;
+}
+
+// Helper functions
+
+bool CreateDeviceD3D(HWND hWnd)
+{
+ // Setup swap chain
+ DXGI_SWAP_CHAIN_DESC sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = 2;
+ sd.BufferDesc.Width = 0;
+ sd.BufferDesc.Height = 0;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.OutputWindow = hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.Windowed = TRUE;
+ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ UINT createDeviceFlags = 0;
+ //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+ D3D_FEATURE_LEVEL featureLevel;
+ const D3D_FEATURE_LEVEL featureLevelArray[2] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, };
+ if (D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &featureLevel, &g_pd3dDeviceContext) != S_OK)
+ return false;
+
+ CreateRenderTarget();
+ return true;
+}
+
+void CleanupDeviceD3D()
+{
+ CleanupRenderTarget();
+ if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; }
+ if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; }
+ if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
+}
+
+void CreateRenderTarget()
+{
+ ID3D11Texture2D* pBackBuffer;
+ g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
+ g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView);
+ pBackBuffer->Release();
+}
+
+void CleanupRenderTarget()
+{
+ if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; }
+}
+
+// Forward declare message handler from imgui_impl_win32.cpp
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Win32 message handler
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
+ return true;
+
+ switch (msg)
+ {
+ case WM_SIZE:
+ if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
+ {
+ CleanupRenderTarget();
+ g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
+ CreateRenderTarget();
+ }
+ return 0;
+ case WM_SYSCOMMAND:
+ if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
+ return 0;
+ break;
+ case WM_DESTROY:
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ return ::DefWindowProc(hWnd, msg, wParam, lParam);
+}
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx12/build_win32.bat b/Client/ThirdParty/imgui/examples/example_win32_directx12/build_win32.bat
new file mode 100644
index 0000000..48dadb2
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx12/build_win32.bat
@@ -0,0 +1,9 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@REM Important: to build on 32-bit systems, the DX12 backends needs '#define ImTextureID ImU64', so we pass it here.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_win32_directx12
+@set INCLUDES=/I..\.. /I..\..\backends /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared"
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_dx12.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp
+@set LIBS=d3d12.lib d3dcompiler.lib dxgi.lib
+mkdir Debug
+cl /nologo /Zi /MD %INCLUDES% /D ImTextureID=ImU64 /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj b/Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj
new file mode 100644
index 0000000..3fed30d
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{b4cf9797-519d-4afe-a8f4-5141a6b521d3}</ProjectGuid>
+ <RootNamespace>example_win32_directx12</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>ImTextureID=ImU64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_dx12.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_dx12.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj.filters
new file mode 100644
index 0000000..91fc734
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx12/example_win32_directx12.vcxproj.filters
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{fb3d294f-51ec-478e-a627-25831c80fefd}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="sources">
+ <UniqueIdentifier>{4f33ddea-9910-456d-b868-4267eb3c2b19}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_dx12.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_dx12.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx12/main.cpp b/Client/ThirdParty/imgui/examples/example_win32_directx12/main.cpp
new file mode 100644
index 0000000..74bfef3
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx12/main.cpp
@@ -0,0 +1,464 @@
+// Dear ImGui: standalone example application for DirectX 12
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+// Important: to compile on 32-bit systems, the DirectX12 backend requires code to be compiled with '#define ImTextureID ImU64'.
+// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
+// This define is set in the example .vcxproj file and need to be replicated in your app or by adding it to your imconfig.h file.
+
+#include "imgui.h"
+#include "imgui_impl_win32.h"
+#include "imgui_impl_dx12.h"
+#include <d3d12.h>
+#include <dxgi1_4.h>
+#include <tchar.h>
+
+#ifdef _DEBUG
+#define DX12_ENABLE_DEBUG_LAYER
+#endif
+
+#ifdef DX12_ENABLE_DEBUG_LAYER
+#include <dxgidebug.h>
+#pragma comment(lib, "dxguid.lib")
+#endif
+
+struct FrameContext
+{
+ ID3D12CommandAllocator* CommandAllocator;
+ UINT64 FenceValue;
+};
+
+// Data
+static int const NUM_FRAMES_IN_FLIGHT = 3;
+static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {};
+static UINT g_frameIndex = 0;
+
+static int const NUM_BACK_BUFFERS = 3;
+static ID3D12Device* g_pd3dDevice = NULL;
+static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = NULL;
+static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL;
+static ID3D12CommandQueue* g_pd3dCommandQueue = NULL;
+static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL;
+static ID3D12Fence* g_fence = NULL;
+static HANDLE g_fenceEvent = NULL;
+static UINT64 g_fenceLastSignaledValue = 0;
+static IDXGISwapChain3* g_pSwapChain = NULL;
+static HANDLE g_hSwapChainWaitableObject = NULL;
+static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
+static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
+
+// Forward declarations of helper functions
+bool CreateDeviceD3D(HWND hWnd);
+void CleanupDeviceD3D();
+void CreateRenderTarget();
+void CleanupRenderTarget();
+void WaitForLastSubmittedFrame();
+FrameContext* WaitForNextFrameResources();
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Main code
+int main(int, char**)
+{
+ // Create application window
+ //ImGui_ImplWin32_EnableDpiAwareness();
+ WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
+ ::RegisterClassEx(&wc);
+ HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX12 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
+
+ // Initialize Direct3D
+ if (!CreateDeviceD3D(hwnd))
+ {
+ CleanupDeviceD3D();
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ return 1;
+ }
+
+ // Show the window
+ ::ShowWindow(hwnd, SW_SHOWDEFAULT);
+ ::UpdateWindow(hwnd);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplWin32_Init(hwnd);
+ ImGui_ImplDX12_Init(g_pd3dDevice, NUM_FRAMES_IN_FLIGHT,
+ DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap,
+ g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(),
+ g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle messages (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ MSG msg;
+ while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+ {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ if (msg.message == WM_QUIT)
+ done = true;
+ }
+ if (done)
+ break;
+
+ // Start the Dear ImGui frame
+ ImGui_ImplDX12_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::Render();
+
+ FrameContext* frameCtx = WaitForNextFrameResources();
+ UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
+ frameCtx->CommandAllocator->Reset();
+
+ D3D12_RESOURCE_BARRIER barrier = {};
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx];
+ barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
+ g_pd3dCommandList->Reset(frameCtx->CommandAllocator, NULL);
+ g_pd3dCommandList->ResourceBarrier(1, &barrier);
+
+ // Render Dear ImGui graphics
+ const float clear_color_with_alpha[4] = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
+ g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], clear_color_with_alpha, 0, NULL);
+ g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL);
+ g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap);
+ ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), g_pd3dCommandList);
+ barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
+ barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
+ g_pd3dCommandList->ResourceBarrier(1, &barrier);
+ g_pd3dCommandList->Close();
+
+ g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
+
+ g_pSwapChain->Present(1, 0); // Present with vsync
+ //g_pSwapChain->Present(0, 0); // Present without vsync
+
+ UINT64 fenceValue = g_fenceLastSignaledValue + 1;
+ g_pd3dCommandQueue->Signal(g_fence, fenceValue);
+ g_fenceLastSignaledValue = fenceValue;
+ frameCtx->FenceValue = fenceValue;
+ }
+
+ WaitForLastSubmittedFrame();
+
+ // Cleanup
+ ImGui_ImplDX12_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupDeviceD3D();
+ ::DestroyWindow(hwnd);
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+
+ return 0;
+}
+
+// Helper functions
+
+bool CreateDeviceD3D(HWND hWnd)
+{
+ // Setup swap chain
+ DXGI_SWAP_CHAIN_DESC1 sd;
+ {
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = NUM_BACK_BUFFERS;
+ sd.Width = 0;
+ sd.Height = 0;
+ sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ sd.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+ sd.Scaling = DXGI_SCALING_STRETCH;
+ sd.Stereo = FALSE;
+ }
+
+ // [DEBUG] Enable debug interface
+#ifdef DX12_ENABLE_DEBUG_LAYER
+ ID3D12Debug* pdx12Debug = NULL;
+ if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pdx12Debug))))
+ pdx12Debug->EnableDebugLayer();
+#endif
+
+ // Create device
+ D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
+ if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK)
+ return false;
+
+ // [DEBUG] Setup debug interface to break on any warnings/errors
+#ifdef DX12_ENABLE_DEBUG_LAYER
+ if (pdx12Debug != NULL)
+ {
+ ID3D12InfoQueue* pInfoQueue = NULL;
+ g_pd3dDevice->QueryInterface(IID_PPV_ARGS(&pInfoQueue));
+ pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true);
+ pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
+ pInfoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true);
+ pInfoQueue->Release();
+ pdx12Debug->Release();
+ }
+#endif
+
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC desc = {};
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
+ desc.NumDescriptors = NUM_BACK_BUFFERS;
+ desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
+ desc.NodeMask = 1;
+ if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK)
+ return false;
+
+ SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart();
+ for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
+ {
+ g_mainRenderTargetDescriptor[i] = rtvHandle;
+ rtvHandle.ptr += rtvDescriptorSize;
+ }
+ }
+
+ {
+ D3D12_DESCRIPTOR_HEAP_DESC desc = {};
+ desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
+ desc.NumDescriptors = 1;
+ desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+ if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK)
+ return false;
+ }
+
+ {
+ D3D12_COMMAND_QUEUE_DESC desc = {};
+ desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+ desc.NodeMask = 1;
+ if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK)
+ return false;
+ }
+
+ for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
+ if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK)
+ return false;
+
+ if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK ||
+ g_pd3dCommandList->Close() != S_OK)
+ return false;
+
+ if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK)
+ return false;
+
+ g_fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (g_fenceEvent == NULL)
+ return false;
+
+ {
+ IDXGIFactory4* dxgiFactory = NULL;
+ IDXGISwapChain1* swapChain1 = NULL;
+ if (CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)) != S_OK)
+ return false;
+ if (dxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &sd, NULL, NULL, &swapChain1) != S_OK)
+ return false;
+ if (swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)) != S_OK)
+ return false;
+ swapChain1->Release();
+ dxgiFactory->Release();
+ g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS);
+ g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
+ }
+
+ CreateRenderTarget();
+ return true;
+}
+
+void CleanupDeviceD3D()
+{
+ CleanupRenderTarget();
+ if (g_pSwapChain) { g_pSwapChain->SetFullscreenState(false, NULL); g_pSwapChain->Release(); g_pSwapChain = NULL; }
+ if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); }
+ for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++)
+ if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; }
+ if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; }
+ if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; }
+ if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = NULL; }
+ if (g_pd3dSrvDescHeap) { g_pd3dSrvDescHeap->Release(); g_pd3dSrvDescHeap = NULL; }
+ if (g_fence) { g_fence->Release(); g_fence = NULL; }
+ if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; }
+ if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
+
+#ifdef DX12_ENABLE_DEBUG_LAYER
+ IDXGIDebug1* pDebug = NULL;
+ if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&pDebug))))
+ {
+ pDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY);
+ pDebug->Release();
+ }
+#endif
+}
+
+void CreateRenderTarget()
+{
+ for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
+ {
+ ID3D12Resource* pBackBuffer = NULL;
+ g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
+ g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]);
+ g_mainRenderTargetResource[i] = pBackBuffer;
+ }
+}
+
+void CleanupRenderTarget()
+{
+ WaitForLastSubmittedFrame();
+
+ for (UINT i = 0; i < NUM_BACK_BUFFERS; i++)
+ if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; }
+}
+
+void WaitForLastSubmittedFrame()
+{
+ FrameContext* frameCtx = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT];
+
+ UINT64 fenceValue = frameCtx->FenceValue;
+ if (fenceValue == 0)
+ return; // No fence was signaled
+
+ frameCtx->FenceValue = 0;
+ if (g_fence->GetCompletedValue() >= fenceValue)
+ return;
+
+ g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
+ WaitForSingleObject(g_fenceEvent, INFINITE);
+}
+
+FrameContext* WaitForNextFrameResources()
+{
+ UINT nextFrameIndex = g_frameIndex + 1;
+ g_frameIndex = nextFrameIndex;
+
+ HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL };
+ DWORD numWaitableObjects = 1;
+
+ FrameContext* frameCtx = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT];
+ UINT64 fenceValue = frameCtx->FenceValue;
+ if (fenceValue != 0) // means no fence was signaled
+ {
+ frameCtx->FenceValue = 0;
+ g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
+ waitableObjects[1] = g_fenceEvent;
+ numWaitableObjects = 2;
+ }
+
+ WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
+
+ return frameCtx;
+}
+
+// Forward declare message handler from imgui_impl_win32.cpp
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Win32 message handler
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
+ return true;
+
+ switch (msg)
+ {
+ case WM_SIZE:
+ if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
+ {
+ WaitForLastSubmittedFrame();
+ CleanupRenderTarget();
+ HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT);
+ assert(SUCCEEDED(result) && "Failed to resize swapchain.");
+ CreateRenderTarget();
+ }
+ return 0;
+ case WM_SYSCOMMAND:
+ if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
+ return 0;
+ break;
+ case WM_DESTROY:
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ return ::DefWindowProc(hWnd, msg, wParam, lParam);
+}
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx9/build_win32.bat b/Client/ThirdParty/imgui/examples/example_win32_directx9/build_win32.bat
new file mode 100644
index 0000000..bbd4b13
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx9/build_win32.bat
@@ -0,0 +1,8 @@
+@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
+@set OUT_DIR=Debug
+@set OUT_EXE=example_win32_directx9
+@set INCLUDES=/I..\.. /I..\..\backends /I "%DXSDK_DIR%/Include"
+@set SOURCES=main.cpp ..\..\backends\imgui_impl_dx9.cpp ..\..\backends\imgui_impl_win32.cpp ..\..\imgui*.cpp
+@set LIBS=/LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d9.lib
+mkdir %OUT_DIR%
+cl /nologo /Zi /MD %INCLUDES% /D UNICODE /D _UNICODE %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS%
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj b/Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj
new file mode 100644
index 0000000..e01eca1
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4165A294-21F2-44CA-9B38-E3F935ABADF5}</ProjectGuid>
+ <RootNamespace>example_win32_directx9</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(ProjectDir)$(Configuration)\</OutDir>
+ <IntDir>$(ProjectDir)$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level4</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..;..\..\backends;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include;</AdditionalIncludeDirectories>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>$(DXSDK_DIR)/Lib/x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\imgui.cpp" />
+ <ClCompile Include="..\..\imgui_demo.cpp" />
+ <ClCompile Include="..\..\imgui_draw.cpp" />
+ <ClCompile Include="..\..\imgui_tables.cpp" />
+ <ClCompile Include="..\..\imgui_widgets.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_dx9.cpp" />
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp" />
+ <ClCompile Include="main.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h" />
+ <ClInclude Include="..\..\imgui.h" />
+ <ClInclude Include="..\..\imgui_internal.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_dx9.h" />
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\misc\debuggers\imgui.natvis" />
+ <None Include="..\README.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj.filters b/Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj.filters
new file mode 100644
index 0000000..9493970
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx9/example_win32_directx9.vcxproj.filters
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="sources">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="imgui">
+ <UniqueIdentifier>{a82cba23-9de0-45c2-b1e3-2eb1666702de}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_demo.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_draw.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_win32.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\backends\imgui_impl_dx9.cpp">
+ <Filter>sources</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_tables.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\imgui_widgets.cpp">
+ <Filter>imgui</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\imconfig.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\imgui_internal.h">
+ <Filter>imgui</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_win32.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\backends\imgui_impl_dx9.h">
+ <Filter>sources</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="..\README.txt" />
+ <None Include="..\..\misc\debuggers\imgui.natvis">
+ <Filter>sources</Filter>
+ </None>
+ </ItemGroup>
+</Project>
diff --git a/Client/ThirdParty/imgui/examples/example_win32_directx9/main.cpp b/Client/ThirdParty/imgui/examples/example_win32_directx9/main.cpp
new file mode 100644
index 0000000..bdcd8b3
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/example_win32_directx9/main.cpp
@@ -0,0 +1,236 @@
+// Dear ImGui: standalone example application for DirectX 9
+// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
+// Read online: https://github.com/ocornut/imgui/tree/master/docs
+
+#include "imgui.h"
+#include "imgui_impl_dx9.h"
+#include "imgui_impl_win32.h"
+#include <d3d9.h>
+#include <tchar.h>
+
+// Data
+static LPDIRECT3D9 g_pD3D = NULL;
+static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
+static D3DPRESENT_PARAMETERS g_d3dpp = {};
+
+// Forward declarations of helper functions
+bool CreateDeviceD3D(HWND hWnd);
+void CleanupDeviceD3D();
+void ResetDevice();
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Main code
+int main(int, char**)
+{
+ // Create application window
+ //ImGui_ImplWin32_EnableDpiAwareness();
+ WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL };
+ ::RegisterClassEx(&wc);
+ HWND hwnd = ::CreateWindow(wc.lpszClassName, _T("Dear ImGui DirectX9 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
+
+ // Initialize Direct3D
+ if (!CreateDeviceD3D(hwnd))
+ {
+ CleanupDeviceD3D();
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ return 1;
+ }
+
+ // Show the window
+ ::ShowWindow(hwnd, SW_SHOWDEFAULT);
+ ::UpdateWindow(hwnd);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+
+ // Setup Dear ImGui style
+ ImGui::StyleColorsDark();
+ //ImGui::StyleColorsClassic();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplWin32_Init(hwnd);
+ ImGui_ImplDX9_Init(g_pd3dDevice);
+
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != NULL);
+
+ // Our state
+ bool show_demo_window = true;
+ bool show_another_window = false;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+
+ // Main loop
+ bool done = false;
+ while (!done)
+ {
+ // Poll and handle messages (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ MSG msg;
+ while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
+ {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ if (msg.message == WM_QUIT)
+ done = true;
+ }
+ if (done)
+ break;
+
+ // Start the Dear ImGui frame
+ ImGui_ImplDX9_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+
+ // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ {
+ static float f = 0.0f;
+ static int counter = 0;
+
+ ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
+
+ ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
+ ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
+ ImGui::Checkbox("Another Window", &show_another_window);
+
+ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
+ ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
+
+ if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
+ counter++;
+ ImGui::SameLine();
+ ImGui::Text("counter = %d", counter);
+
+ ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
+ ImGui::End();
+ }
+
+ // 3. Show another simple window.
+ if (show_another_window)
+ {
+ ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
+ ImGui::Text("Hello from another window!");
+ if (ImGui::Button("Close Me"))
+ show_another_window = false;
+ ImGui::End();
+ }
+
+ // Rendering
+ ImGui::EndFrame();
+ g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+ D3DCOLOR clear_col_dx = D3DCOLOR_RGBA((int)(clear_color.x*clear_color.w*255.0f), (int)(clear_color.y*clear_color.w*255.0f), (int)(clear_color.z*clear_color.w*255.0f), (int)(clear_color.w*255.0f));
+ g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, clear_col_dx, 1.0f, 0);
+ if (g_pd3dDevice->BeginScene() >= 0)
+ {
+ ImGui::Render();
+ ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
+ g_pd3dDevice->EndScene();
+ }
+ HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
+
+ // Handle loss of D3D9 device
+ if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
+ ResetDevice();
+ }
+
+ ImGui_ImplDX9_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupDeviceD3D();
+ ::DestroyWindow(hwnd);
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+
+ return 0;
+}
+
+// Helper functions
+
+bool CreateDeviceD3D(HWND hWnd)
+{
+ if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL)
+ return false;
+
+ // Create the D3DDevice
+ ZeroMemory(&g_d3dpp, sizeof(g_d3dpp));
+ g_d3dpp.Windowed = TRUE;
+ g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ g_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Need to use an explicit format with alpha if needing per-pixel alpha composition.
+ g_d3dpp.EnableAutoDepthStencil = TRUE;
+ g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
+ g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // Present with vsync
+ //g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // Present without vsync, maximum unthrottled framerate
+ if (g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice) < 0)
+ return false;
+
+ return true;
+}
+
+void CleanupDeviceD3D()
+{
+ if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; }
+ if (g_pD3D) { g_pD3D->Release(); g_pD3D = NULL; }
+}
+
+void ResetDevice()
+{
+ ImGui_ImplDX9_InvalidateDeviceObjects();
+ HRESULT hr = g_pd3dDevice->Reset(&g_d3dpp);
+ if (hr == D3DERR_INVALIDCALL)
+ IM_ASSERT(0);
+ ImGui_ImplDX9_CreateDeviceObjects();
+}
+
+// Forward declare message handler from imgui_impl_win32.cpp
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+// Win32 message handler
+LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
+ return true;
+
+ switch (msg)
+ {
+ case WM_SIZE:
+ if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED)
+ {
+ g_d3dpp.BackBufferWidth = LOWORD(lParam);
+ g_d3dpp.BackBufferHeight = HIWORD(lParam);
+ ResetDevice();
+ }
+ return 0;
+ case WM_SYSCOMMAND:
+ if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu
+ return 0;
+ break;
+ case WM_DESTROY:
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ return ::DefWindowProc(hWnd, msg, wParam, lParam);
+}
diff --git a/Client/ThirdParty/imgui/examples/imgui_examples.sln b/Client/ThirdParty/imgui/examples/imgui_examples.sln
new file mode 100644
index 0000000..df1006d
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/imgui_examples.sln
@@ -0,0 +1,88 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx9", "example_win32_directx9\example_win32_directx9.vcxproj", "{4165A294-21F2-44CA-9B38-E3F935ABADF5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx10", "example_win32_directx10\example_win32_directx10.vcxproj", "{345A953E-A004-4648-B442-DC5F9F11068C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx11", "example_win32_directx11\example_win32_directx11.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_win32_directx12", "example_win32_directx12\example_win32_directx12.vcxproj", "{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_opengl2", "example_glfw_opengl2\example_glfw_opengl2.vcxproj", "{9CDA7840-B7A5-496D-A527-E95571496D18}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_opengl3", "example_glfw_opengl3\example_glfw_opengl3.vcxproj", "{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example_glfw_vulkan", "example_glfw_vulkan\example_glfw_vulkan.vcxproj", "{57E2DF5A-6FC8-45BB-99DD-91A18C646E80}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|Win32.Build.0 = Debug|Win32
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.ActiveCfg = Debug|x64
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Debug|x64.Build.0 = Debug|x64
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.ActiveCfg = Release|Win32
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|Win32.Build.0 = Release|Win32
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.ActiveCfg = Release|x64
+ {4165A294-21F2-44CA-9B38-E3F935ABADF5}.Release|x64.Build.0 = Release|x64
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Debug|Win32.Build.0 = Debug|Win32
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Debug|x64.ActiveCfg = Debug|x64
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Debug|x64.Build.0 = Debug|x64
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Release|Win32.ActiveCfg = Release|Win32
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Release|Win32.Build.0 = Release|Win32
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Release|x64.ActiveCfg = Release|x64
+ {345A953E-A004-4648-B442-DC5F9F11068C}.Release|x64.Build.0 = Release|x64
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|Win32.Build.0 = Debug|Win32
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.ActiveCfg = Debug|x64
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Debug|x64.Build.0 = Debug|x64
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.ActiveCfg = Release|Win32
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.Build.0 = Release|Win32
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64
+ {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.Build.0 = Debug|Win32
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.ActiveCfg = Debug|x64
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.Build.0 = Debug|x64
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.ActiveCfg = Release|Win32
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.Build.0 = Release|Win32
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.ActiveCfg = Release|x64
+ {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.Build.0 = Release|x64
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|Win32.Build.0 = Debug|Win32
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.ActiveCfg = Debug|x64
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Debug|x64.Build.0 = Debug|x64
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.ActiveCfg = Release|Win32
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|Win32.Build.0 = Release|Win32
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.ActiveCfg = Release|x64
+ {9CDA7840-B7A5-496D-A527-E95571496D18}.Release|x64.Build.0 = Release|x64
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.Build.0 = Debug|Win32
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.ActiveCfg = Debug|x64
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.Build.0 = Debug|x64
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.ActiveCfg = Release|Win32
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|Win32.Build.0 = Release|Win32
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.ActiveCfg = Release|x64
+ {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Release|x64.Build.0 = Release|x64
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|Win32.ActiveCfg = Debug|Win32
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|Win32.Build.0 = Debug|Win32
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|x64.ActiveCfg = Debug|x64
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Debug|x64.Build.0 = Debug|x64
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|Win32.ActiveCfg = Release|Win32
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|Win32.Build.0 = Release|Win32
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|x64.ActiveCfg = Release|x64
+ {57E2DF5A-6FC8-45BB-99DD-91A18C646E80}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Client/ThirdParty/imgui/examples/libs/glfw/COPYING.txt b/Client/ThirdParty/imgui/examples/libs/glfw/COPYING.txt
new file mode 100644
index 0000000..b30c701
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/glfw/COPYING.txt
@@ -0,0 +1,22 @@
+Copyright (c) 2002-2006 Marcus Geelnard
+Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would
+ be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+ distribution.
+
diff --git a/Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3.h b/Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3.h
new file mode 100644
index 0000000..f8ca3d6
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3.h
@@ -0,0 +1,4227 @@
+/*************************************************************************
+ * GLFW 3.2 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would
+ * be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ *************************************************************************/
+
+#ifndef _glfw3_h_
+#define _glfw3_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Doxygen documentation
+ *************************************************************************/
+
+/*! @file glfw3.h
+ * @brief The header of the GLFW 3 API.
+ *
+ * This is the header file of the GLFW 3 API. It defines all its types and
+ * declares all its functions.
+ *
+ * For more information about how to use this file, see @ref build_include.
+ */
+/*! @defgroup context Context reference
+ *
+ * This is the reference documentation for OpenGL and OpenGL ES context related
+ * functions. For more task-oriented information, see the @ref context_guide.
+ */
+/*! @defgroup vulkan Vulkan reference
+ *
+ * This is the reference documentation for Vulkan related functions and types.
+ * For more task-oriented information, see the @ref vulkan_guide.
+ */
+/*! @defgroup init Initialization, version and error reference
+ *
+ * This is the reference documentation for initialization and termination of
+ * the library, version management and error handling. For more task-oriented
+ * information, see the @ref intro_guide.
+ */
+/*! @defgroup input Input reference
+ *
+ * This is the reference documentation for input related functions and types.
+ * For more task-oriented information, see the @ref input_guide.
+ */
+/*! @defgroup monitor Monitor reference
+ *
+ * This is the reference documentation for monitor related functions and types.
+ * For more task-oriented information, see the @ref monitor_guide.
+ */
+/*! @defgroup window Window reference
+ *
+ * This is the reference documentation for window related functions and types,
+ * including creation, deletion and event polling. For more task-oriented
+ * information, see the @ref window_guide.
+ */
+
+
+/*************************************************************************
+ * Compiler- and platform-specific preprocessor work
+ *************************************************************************/
+
+/* If we are we on Windows, we want a single define for it.
+ */
+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
+ #define _WIN32
+#endif /* _WIN32 */
+
+/* It is customary to use APIENTRY for OpenGL function pointer declarations on
+ * all platforms. Additionally, the Windows OpenGL header needs APIENTRY.
+ */
+#ifndef APIENTRY
+ #ifdef _WIN32
+ #define APIENTRY __stdcall
+ #else
+ #define APIENTRY
+ #endif
+#endif /* APIENTRY */
+
+/* Some Windows OpenGL headers need this.
+ */
+#if !defined(WINGDIAPI) && defined(_WIN32)
+ #define WINGDIAPI __declspec(dllimport)
+ #define GLFW_WINGDIAPI_DEFINED
+#endif /* WINGDIAPI */
+
+/* Some Windows GLU headers need this.
+ */
+#if !defined(CALLBACK) && defined(_WIN32)
+ #define CALLBACK __stdcall
+ #define GLFW_CALLBACK_DEFINED
+#endif /* CALLBACK */
+
+/* Most Windows GLU headers need wchar_t.
+ * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h.
+ * Include it unconditionally to avoid surprising side-effects.
+ */
+#include <stddef.h>
+#include <stdint.h>
+
+/* Include the chosen client API headers.
+ */
+#if defined(__APPLE__)
+ #if defined(GLFW_INCLUDE_GLCOREARB)
+ #include <OpenGL/gl3.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <OpenGL/gl3ext.h>
+ #endif
+ #elif !defined(GLFW_INCLUDE_NONE)
+ #if !defined(GLFW_INCLUDE_GLEXT)
+ #define GL_GLEXT_LEGACY
+ #endif
+ #include <OpenGL/gl.h>
+ #endif
+ #if defined(GLFW_INCLUDE_GLU)
+ #include <OpenGL/glu.h>
+ #endif
+#else
+ #if defined(GLFW_INCLUDE_GLCOREARB)
+ #include <GL/glcorearb.h>
+ #elif defined(GLFW_INCLUDE_ES1)
+ #include <GLES/gl.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES/glext.h>
+ #endif
+ #elif defined(GLFW_INCLUDE_ES2)
+ #include <GLES2/gl2.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+ #elif defined(GLFW_INCLUDE_ES3)
+ #include <GLES3/gl3.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+ #elif defined(GLFW_INCLUDE_ES31)
+ #include <GLES3/gl31.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GLES2/gl2ext.h>
+ #endif
+ #elif defined(GLFW_INCLUDE_VULKAN)
+ #include <vulkan/vulkan.h>
+ #elif !defined(GLFW_INCLUDE_NONE)
+ #include <GL/gl.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+ #include <GL/glext.h>
+ #endif
+ #endif
+ #if defined(GLFW_INCLUDE_GLU)
+ #include <GL/glu.h>
+ #endif
+#endif
+
+#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)
+ /* GLFW_DLL must be defined by applications that are linking against the DLL
+ * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW
+ * configuration header when compiling the DLL version of the library.
+ */
+ #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined"
+#endif
+
+/* GLFWAPI is used to declare public API functions for export
+ * from the DLL / shared library / dynamic library.
+ */
+#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)
+ /* We are building GLFW as a Win32 DLL */
+ #define GLFWAPI __declspec(dllexport)
+#elif defined(_WIN32) && defined(GLFW_DLL)
+ /* We are calling GLFW as a Win32 DLL */
+ #define GLFWAPI __declspec(dllimport)
+#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
+ /* We are building GLFW as a shared / dynamic library */
+ #define GLFWAPI __attribute__((visibility("default")))
+#else
+ /* We are building or calling GLFW as a static library */
+ #define GLFWAPI
+#endif
+
+
+/*************************************************************************
+ * GLFW API tokens
+ *************************************************************************/
+
+/*! @name GLFW version macros
+ * @{ */
+/*! @brief The major version number of the GLFW library.
+ *
+ * This is incremented when the API is changed in non-compatible ways.
+ * @ingroup init
+ */
+#define GLFW_VERSION_MAJOR 3
+/*! @brief The minor version number of the GLFW library.
+ *
+ * This is incremented when features are added to the API but it remains
+ * backward-compatible.
+ * @ingroup init
+ */
+#define GLFW_VERSION_MINOR 2
+/*! @brief The revision number of the GLFW library.
+ *
+ * This is incremented when a bug fix release is made that does not contain any
+ * API changes.
+ * @ingroup init
+ */
+#define GLFW_VERSION_REVISION 0
+/*! @} */
+
+/*! @name Boolean values
+ * @{ */
+/*! @brief One.
+ *
+ * One. Seriously. You don't _need_ to use this symbol in your code. It's
+ * just semantic sugar for the number 1. You can use `1` or `true` or `_True`
+ * or `GL_TRUE` or whatever you want.
+ */
+#define GLFW_TRUE 1
+/*! @brief Zero.
+ *
+ * Zero. Seriously. You don't _need_ to use this symbol in your code. It's
+ * just just semantic sugar for the number 0. You can use `0` or `false` or
+ * `_False` or `GL_FALSE` or whatever you want.
+ */
+#define GLFW_FALSE 0
+/*! @} */
+
+/*! @name Key and button actions
+ * @{ */
+/*! @brief The key or mouse button was released.
+ *
+ * The key or mouse button was released.
+ *
+ * @ingroup input
+ */
+#define GLFW_RELEASE 0
+/*! @brief The key or mouse button was pressed.
+ *
+ * The key or mouse button was pressed.
+ *
+ * @ingroup input
+ */
+#define GLFW_PRESS 1
+/*! @brief The key was held down until it repeated.
+ *
+ * The key was held down until it repeated.
+ *
+ * @ingroup input
+ */
+#define GLFW_REPEAT 2
+/*! @} */
+
+/*! @defgroup keys Keyboard keys
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
+ * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60),
+ * but re-arranged to map to 7-bit ASCII for printable keys (function keys are
+ * put in the 256+ range).
+ *
+ * The naming of the key codes follow these rules:
+ * - The US keyboard layout is used
+ * - Names of printable alpha-numeric characters are used (e.g. "A", "R",
+ * "3", etc.)
+ * - For non-alphanumeric characters, Unicode:ish names are used (e.g.
+ * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not
+ * correspond to the Unicode standard (usually for brevity)
+ * - Keys that lack a clear US mapping are named "WORLD_x"
+ * - For non-printable keys, custom names are used (e.g. "F4",
+ * "BACKSPACE", etc.)
+ *
+ * @ingroup input
+ * @{
+ */
+
+/* The unknown key */
+#define GLFW_KEY_UNKNOWN -1
+
+/* Printable keys */
+#define GLFW_KEY_SPACE 32
+#define GLFW_KEY_APOSTROPHE 39 /* ' */
+#define GLFW_KEY_COMMA 44 /* , */
+#define GLFW_KEY_MINUS 45 /* - */
+#define GLFW_KEY_PERIOD 46 /* . */
+#define GLFW_KEY_SLASH 47 /* / */
+#define GLFW_KEY_0 48
+#define GLFW_KEY_1 49
+#define GLFW_KEY_2 50
+#define GLFW_KEY_3 51
+#define GLFW_KEY_4 52
+#define GLFW_KEY_5 53
+#define GLFW_KEY_6 54
+#define GLFW_KEY_7 55
+#define GLFW_KEY_8 56
+#define GLFW_KEY_9 57
+#define GLFW_KEY_SEMICOLON 59 /* ; */
+#define GLFW_KEY_EQUAL 61 /* = */
+#define GLFW_KEY_A 65
+#define GLFW_KEY_B 66
+#define GLFW_KEY_C 67
+#define GLFW_KEY_D 68
+#define GLFW_KEY_E 69
+#define GLFW_KEY_F 70
+#define GLFW_KEY_G 71
+#define GLFW_KEY_H 72
+#define GLFW_KEY_I 73
+#define GLFW_KEY_J 74
+#define GLFW_KEY_K 75
+#define GLFW_KEY_L 76
+#define GLFW_KEY_M 77
+#define GLFW_KEY_N 78
+#define GLFW_KEY_O 79
+#define GLFW_KEY_P 80
+#define GLFW_KEY_Q 81
+#define GLFW_KEY_R 82
+#define GLFW_KEY_S 83
+#define GLFW_KEY_T 84
+#define GLFW_KEY_U 85
+#define GLFW_KEY_V 86
+#define GLFW_KEY_W 87
+#define GLFW_KEY_X 88
+#define GLFW_KEY_Y 89
+#define GLFW_KEY_Z 90
+#define GLFW_KEY_LEFT_BRACKET 91 /* [ */
+#define GLFW_KEY_BACKSLASH 92 /* \ */
+#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
+#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
+#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
+#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
+
+/* Function keys */
+#define GLFW_KEY_ESCAPE 256
+#define GLFW_KEY_ENTER 257
+#define GLFW_KEY_TAB 258
+#define GLFW_KEY_BACKSPACE 259
+#define GLFW_KEY_INSERT 260
+#define GLFW_KEY_DELETE 261
+#define GLFW_KEY_RIGHT 262
+#define GLFW_KEY_LEFT 263
+#define GLFW_KEY_DOWN 264
+#define GLFW_KEY_UP 265
+#define GLFW_KEY_PAGE_UP 266
+#define GLFW_KEY_PAGE_DOWN 267
+#define GLFW_KEY_HOME 268
+#define GLFW_KEY_END 269
+#define GLFW_KEY_CAPS_LOCK 280
+#define GLFW_KEY_SCROLL_LOCK 281
+#define GLFW_KEY_NUM_LOCK 282
+#define GLFW_KEY_PRINT_SCREEN 283
+#define GLFW_KEY_PAUSE 284
+#define GLFW_KEY_F1 290
+#define GLFW_KEY_F2 291
+#define GLFW_KEY_F3 292
+#define GLFW_KEY_F4 293
+#define GLFW_KEY_F5 294
+#define GLFW_KEY_F6 295
+#define GLFW_KEY_F7 296
+#define GLFW_KEY_F8 297
+#define GLFW_KEY_F9 298
+#define GLFW_KEY_F10 299
+#define GLFW_KEY_F11 300
+#define GLFW_KEY_F12 301
+#define GLFW_KEY_F13 302
+#define GLFW_KEY_F14 303
+#define GLFW_KEY_F15 304
+#define GLFW_KEY_F16 305
+#define GLFW_KEY_F17 306
+#define GLFW_KEY_F18 307
+#define GLFW_KEY_F19 308
+#define GLFW_KEY_F20 309
+#define GLFW_KEY_F21 310
+#define GLFW_KEY_F22 311
+#define GLFW_KEY_F23 312
+#define GLFW_KEY_F24 313
+#define GLFW_KEY_F25 314
+#define GLFW_KEY_KP_0 320
+#define GLFW_KEY_KP_1 321
+#define GLFW_KEY_KP_2 322
+#define GLFW_KEY_KP_3 323
+#define GLFW_KEY_KP_4 324
+#define GLFW_KEY_KP_5 325
+#define GLFW_KEY_KP_6 326
+#define GLFW_KEY_KP_7 327
+#define GLFW_KEY_KP_8 328
+#define GLFW_KEY_KP_9 329
+#define GLFW_KEY_KP_DECIMAL 330
+#define GLFW_KEY_KP_DIVIDE 331
+#define GLFW_KEY_KP_MULTIPLY 332
+#define GLFW_KEY_KP_SUBTRACT 333
+#define GLFW_KEY_KP_ADD 334
+#define GLFW_KEY_KP_ENTER 335
+#define GLFW_KEY_KP_EQUAL 336
+#define GLFW_KEY_LEFT_SHIFT 340
+#define GLFW_KEY_LEFT_CONTROL 341
+#define GLFW_KEY_LEFT_ALT 342
+#define GLFW_KEY_LEFT_SUPER 343
+#define GLFW_KEY_RIGHT_SHIFT 344
+#define GLFW_KEY_RIGHT_CONTROL 345
+#define GLFW_KEY_RIGHT_ALT 346
+#define GLFW_KEY_RIGHT_SUPER 347
+#define GLFW_KEY_MENU 348
+
+#define GLFW_KEY_LAST GLFW_KEY_MENU
+
+/*! @} */
+
+/*! @defgroup mods Modifier key flags
+ *
+ * See [key input](@ref input_key) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+
+/*! @brief If this bit is set one or more Shift keys were held down.
+ */
+#define GLFW_MOD_SHIFT 0x0001
+/*! @brief If this bit is set one or more Control keys were held down.
+ */
+#define GLFW_MOD_CONTROL 0x0002
+/*! @brief If this bit is set one or more Alt keys were held down.
+ */
+#define GLFW_MOD_ALT 0x0004
+/*! @brief If this bit is set one or more Super keys were held down.
+ */
+#define GLFW_MOD_SUPER 0x0008
+
+/*! @} */
+
+/*! @defgroup buttons Mouse buttons
+ *
+ * See [mouse button input](@ref input_mouse_button) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_MOUSE_BUTTON_1 0
+#define GLFW_MOUSE_BUTTON_2 1
+#define GLFW_MOUSE_BUTTON_3 2
+#define GLFW_MOUSE_BUTTON_4 3
+#define GLFW_MOUSE_BUTTON_5 4
+#define GLFW_MOUSE_BUTTON_6 5
+#define GLFW_MOUSE_BUTTON_7 6
+#define GLFW_MOUSE_BUTTON_8 7
+#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
+#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
+#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
+#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
+/*! @} */
+
+/*! @defgroup joysticks Joysticks
+ *
+ * See [joystick input](@ref joystick) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+#define GLFW_JOYSTICK_1 0
+#define GLFW_JOYSTICK_2 1
+#define GLFW_JOYSTICK_3 2
+#define GLFW_JOYSTICK_4 3
+#define GLFW_JOYSTICK_5 4
+#define GLFW_JOYSTICK_6 5
+#define GLFW_JOYSTICK_7 6
+#define GLFW_JOYSTICK_8 7
+#define GLFW_JOYSTICK_9 8
+#define GLFW_JOYSTICK_10 9
+#define GLFW_JOYSTICK_11 10
+#define GLFW_JOYSTICK_12 11
+#define GLFW_JOYSTICK_13 12
+#define GLFW_JOYSTICK_14 13
+#define GLFW_JOYSTICK_15 14
+#define GLFW_JOYSTICK_16 15
+#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16
+/*! @} */
+
+/*! @defgroup errors Error codes
+ *
+ * See [error handling](@ref error_handling) for how these are used.
+ *
+ * @ingroup init
+ * @{ */
+/*! @brief GLFW has not been initialized.
+ *
+ * This occurs if a GLFW function was called that must not be called unless the
+ * library is [initialized](@ref intro_init).
+ *
+ * @analysis Application programmer error. Initialize GLFW before calling any
+ * function that requires initialization.
+ */
+#define GLFW_NOT_INITIALIZED 0x00010001
+/*! @brief No context is current for this thread.
+ *
+ * This occurs if a GLFW function was called that needs and operates on the
+ * current OpenGL or OpenGL ES context but no context is current on the calling
+ * thread. One such function is @ref glfwSwapInterval.
+ *
+ * @analysis Application programmer error. Ensure a context is current before
+ * calling functions that require a current context.
+ */
+#define GLFW_NO_CURRENT_CONTEXT 0x00010002
+/*! @brief One of the arguments to the function was an invalid enum value.
+ *
+ * One of the arguments to the function was an invalid enum value, for example
+ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref
+ * glfwGetWindowAttrib.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_INVALID_ENUM 0x00010003
+/*! @brief One of the arguments to the function was an invalid value.
+ *
+ * One of the arguments to the function was an invalid value, for example
+ * requesting a non-existent OpenGL or OpenGL ES version like 2.7.
+ *
+ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead
+ * result in a @ref GLFW_VERSION_UNAVAILABLE error.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_INVALID_VALUE 0x00010004
+/*! @brief A memory allocation failed.
+ *
+ * A memory allocation failed.
+ *
+ * @analysis A bug in GLFW or the underlying operating system. Report the bug
+ * to our [issue tracker](https://github.com/glfw/glfw/issues).
+ */
+#define GLFW_OUT_OF_MEMORY 0x00010005
+/*! @brief GLFW could not find support for the requested API on the system.
+ *
+ * GLFW could not find support for the requested API on the system.
+ *
+ * @analysis The installed graphics driver does not support the requested
+ * API, or does not support it via the chosen context creation backend.
+ * Below are a few examples.
+ *
+ * @par
+ * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only
+ * supports OpenGL ES via EGL, while Nvidia and Intel only support it via
+ * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa
+ * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary
+ * driver. Older graphics drivers do not support Vulkan.
+ */
+#define GLFW_API_UNAVAILABLE 0x00010006
+/*! @brief The requested OpenGL or OpenGL ES version is not available.
+ *
+ * The requested OpenGL or OpenGL ES version (including any requested context
+ * or framebuffer hints) is not available on this machine.
+ *
+ * @analysis The machine does not support your requirements. If your
+ * application is sufficiently flexible, downgrade your requirements and try
+ * again. Otherwise, inform the user that their machine does not match your
+ * requirements.
+ *
+ * @par
+ * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0
+ * comes out before the 4.x series gets that far, also fail with this error and
+ * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions
+ * will exist.
+ */
+#define GLFW_VERSION_UNAVAILABLE 0x00010007
+/*! @brief A platform-specific error occurred that does not match any of the
+ * more specific categories.
+ *
+ * A platform-specific error occurred that does not match any of the more
+ * specific categories.
+ *
+ * @analysis A bug or configuration error in GLFW, the underlying operating
+ * system or its drivers, or a lack of required resources. Report the issue to
+ * our [issue tracker](https://github.com/glfw/glfw/issues).
+ */
+#define GLFW_PLATFORM_ERROR 0x00010008
+/*! @brief The requested format is not supported or available.
+ *
+ * If emitted during window creation, the requested pixel format is not
+ * supported.
+ *
+ * If emitted when querying the clipboard, the contents of the clipboard could
+ * not be converted to the requested format.
+ *
+ * @analysis If emitted during window creation, one or more
+ * [hard constraints](@ref window_hints_hard) did not match any of the
+ * available pixel formats. If your application is sufficiently flexible,
+ * downgrade your requirements and try again. Otherwise, inform the user that
+ * their machine does not match your requirements.
+ *
+ * @par
+ * If emitted when querying the clipboard, ignore the error or report it to
+ * the user, as appropriate.
+ */
+#define GLFW_FORMAT_UNAVAILABLE 0x00010009
+/*! @brief The specified window does not have an OpenGL or OpenGL ES context.
+ *
+ * A window that does not have an OpenGL or OpenGL ES context was passed to
+ * a function that requires it to have one.
+ *
+ * @analysis Application programmer error. Fix the offending call.
+ */
+#define GLFW_NO_WINDOW_CONTEXT 0x0001000A
+/*! @} */
+
+#define GLFW_FOCUSED 0x00020001
+#define GLFW_ICONIFIED 0x00020002
+#define GLFW_RESIZABLE 0x00020003
+#define GLFW_VISIBLE 0x00020004
+#define GLFW_DECORATED 0x00020005
+#define GLFW_AUTO_ICONIFY 0x00020006
+#define GLFW_FLOATING 0x00020007
+#define GLFW_MAXIMIZED 0x00020008
+
+#define GLFW_RED_BITS 0x00021001
+#define GLFW_GREEN_BITS 0x00021002
+#define GLFW_BLUE_BITS 0x00021003
+#define GLFW_ALPHA_BITS 0x00021004
+#define GLFW_DEPTH_BITS 0x00021005
+#define GLFW_STENCIL_BITS 0x00021006
+#define GLFW_ACCUM_RED_BITS 0x00021007
+#define GLFW_ACCUM_GREEN_BITS 0x00021008
+#define GLFW_ACCUM_BLUE_BITS 0x00021009
+#define GLFW_ACCUM_ALPHA_BITS 0x0002100A
+#define GLFW_AUX_BUFFERS 0x0002100B
+#define GLFW_STEREO 0x0002100C
+#define GLFW_SAMPLES 0x0002100D
+#define GLFW_SRGB_CAPABLE 0x0002100E
+#define GLFW_REFRESH_RATE 0x0002100F
+#define GLFW_DOUBLEBUFFER 0x00021010
+
+#define GLFW_CLIENT_API 0x00022001
+#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002
+#define GLFW_CONTEXT_VERSION_MINOR 0x00022003
+#define GLFW_CONTEXT_REVISION 0x00022004
+#define GLFW_CONTEXT_ROBUSTNESS 0x00022005
+#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
+#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
+#define GLFW_OPENGL_PROFILE 0x00022008
+#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
+#define GLFW_CONTEXT_NO_ERROR 0x0002200A
+
+#define GLFW_NO_API 0
+#define GLFW_OPENGL_API 0x00030001
+#define GLFW_OPENGL_ES_API 0x00030002
+
+#define GLFW_NO_ROBUSTNESS 0
+#define GLFW_NO_RESET_NOTIFICATION 0x00031001
+#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002
+
+#define GLFW_OPENGL_ANY_PROFILE 0
+#define GLFW_OPENGL_CORE_PROFILE 0x00032001
+#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002
+
+#define GLFW_CURSOR 0x00033001
+#define GLFW_STICKY_KEYS 0x00033002
+#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
+
+#define GLFW_CURSOR_NORMAL 0x00034001
+#define GLFW_CURSOR_HIDDEN 0x00034002
+#define GLFW_CURSOR_DISABLED 0x00034003
+
+#define GLFW_ANY_RELEASE_BEHAVIOR 0
+#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
+#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
+
+/*! @defgroup shapes Standard cursor shapes
+ *
+ * See [standard cursor creation](@ref cursor_standard) for how these are used.
+ *
+ * @ingroup input
+ * @{ */
+
+/*! @brief The regular arrow cursor shape.
+ *
+ * The regular arrow cursor.
+ */
+#define GLFW_ARROW_CURSOR 0x00036001
+/*! @brief The text input I-beam cursor shape.
+ *
+ * The text input I-beam cursor shape.
+ */
+#define GLFW_IBEAM_CURSOR 0x00036002
+/*! @brief The crosshair shape.
+ *
+ * The crosshair shape.
+ */
+#define GLFW_CROSSHAIR_CURSOR 0x00036003
+/*! @brief The hand shape.
+ *
+ * The hand shape.
+ */
+#define GLFW_HAND_CURSOR 0x00036004
+/*! @brief The horizontal resize arrow shape.
+ *
+ * The horizontal resize arrow shape.
+ */
+#define GLFW_HRESIZE_CURSOR 0x00036005
+/*! @brief The vertical resize arrow shape.
+ *
+ * The vertical resize arrow shape.
+ */
+#define GLFW_VRESIZE_CURSOR 0x00036006
+/*! @} */
+
+#define GLFW_CONNECTED 0x00040001
+#define GLFW_DISCONNECTED 0x00040002
+
+#define GLFW_DONT_CARE -1
+
+
+/*************************************************************************
+ * GLFW API types
+ *************************************************************************/
+
+/*! @brief Client API function pointer type.
+ *
+ * Generic function pointer used for returning client API function pointers
+ * without forcing a cast from a regular pointer.
+ *
+ * @sa @ref context_glext
+ * @sa glfwGetProcAddress
+ *
+ * @since Added in version 3.0.
+
+ * @ingroup context
+ */
+typedef void (*GLFWglproc)(void);
+
+/*! @brief Vulkan API function pointer type.
+ *
+ * Generic function pointer used for returning Vulkan API function pointers
+ * without forcing a cast from a regular pointer.
+ *
+ * @sa @ref vulkan_proc
+ * @sa glfwGetInstanceProcAddress
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+typedef void (*GLFWvkproc)(void);
+
+/*! @brief Opaque monitor object.
+ *
+ * Opaque monitor object.
+ *
+ * @see @ref monitor_object
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWmonitor GLFWmonitor;
+
+/*! @brief Opaque window object.
+ *
+ * Opaque window object.
+ *
+ * @see @ref window_object
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef struct GLFWwindow GLFWwindow;
+
+/*! @brief Opaque cursor object.
+ *
+ * Opaque cursor object.
+ *
+ * @see @ref cursor_object
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup cursor
+ */
+typedef struct GLFWcursor GLFWcursor;
+
+/*! @brief The function signature for error callbacks.
+ *
+ * This is the function signature for error callback functions.
+ *
+ * @param[in] error An [error code](@ref errors).
+ * @param[in] description A UTF-8 encoded string describing the error.
+ *
+ * @sa @ref error_handling
+ * @sa glfwSetErrorCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+typedef void (* GLFWerrorfun)(int,const char*);
+
+/*! @brief The function signature for window position callbacks.
+ *
+ * This is the function signature for window position callback functions.
+ *
+ * @param[in] window The window that was moved.
+ * @param[in] xpos The new x-coordinate, in screen coordinates, of the
+ * upper-left corner of the client area of the window.
+ * @param[in] ypos The new y-coordinate, in screen coordinates, of the
+ * upper-left corner of the client area of the window.
+ *
+ * @sa @ref window_pos
+ * @sa glfwSetWindowPosCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
+
+/*! @brief The function signature for window resize callbacks.
+ *
+ * This is the function signature for window size callback functions.
+ *
+ * @param[in] window The window that was resized.
+ * @param[in] width The new width, in screen coordinates, of the window.
+ * @param[in] height The new height, in screen coordinates, of the window.
+ *
+ * @sa @ref window_size
+ * @sa glfwSetWindowSizeCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
+
+/*! @brief The function signature for window close callbacks.
+ *
+ * This is the function signature for window close callback functions.
+ *
+ * @param[in] window The window that the user attempted to close.
+ *
+ * @sa @ref window_close
+ * @sa glfwSetWindowCloseCallback
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowclosefun)(GLFWwindow*);
+
+/*! @brief The function signature for window content refresh callbacks.
+ *
+ * This is the function signature for window refresh callback functions.
+ *
+ * @param[in] window The window whose content needs to be refreshed.
+ *
+ * @sa @ref window_refresh
+ * @sa glfwSetWindowRefreshCallback
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
+
+/*! @brief The function signature for window focus/defocus callbacks.
+ *
+ * This is the function signature for window focus callback functions.
+ *
+ * @param[in] window The window that gained or lost input focus.
+ * @param[in] focused `GLFW_TRUE` if the window was given input focus, or
+ * `GLFW_FALSE` if it lost it.
+ *
+ * @sa @ref window_focus
+ * @sa glfwSetWindowFocusCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
+
+/*! @brief The function signature for window iconify/restore callbacks.
+ *
+ * This is the function signature for window iconify/restore callback
+ * functions.
+ *
+ * @param[in] window The window that was iconified or restored.
+ * @param[in] iconified `GLFW_TRUE` if the window was iconified, or
+ * `GLFW_FALSE` if it was restored.
+ *
+ * @sa @ref window_iconify
+ * @sa glfwSetWindowIconifyCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
+
+/*! @brief The function signature for framebuffer resize callbacks.
+ *
+ * This is the function signature for framebuffer resize callback
+ * functions.
+ *
+ * @param[in] window The window whose framebuffer was resized.
+ * @param[in] width The new width, in pixels, of the framebuffer.
+ * @param[in] height The new height, in pixels, of the framebuffer.
+ *
+ * @sa @ref window_fbsize
+ * @sa glfwSetFramebufferSizeCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
+
+/*! @brief The function signature for mouse button callbacks.
+ *
+ * This is the function signature for mouse button callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] button The [mouse button](@ref buttons) that was pressed or
+ * released.
+ * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_mouse_button
+ * @sa glfwSetMouseButtonCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle and modifier mask parameters.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
+
+/*! @brief The function signature for cursor position callbacks.
+ *
+ * This is the function signature for cursor position callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] xpos The new cursor x-coordinate, relative to the left edge of
+ * the client area.
+ * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
+ * client area.
+ *
+ * @sa @ref cursor_pos
+ * @sa glfwSetCursorPosCallback
+ *
+ * @since Added in version 3.0. Replaces `GLFWmouseposfun`.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
+
+/*! @brief The function signature for cursor enter/leave callbacks.
+ *
+ * This is the function signature for cursor enter/leave callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client
+ * area, or `GLFW_FALSE` if it left it.
+ *
+ * @sa @ref cursor_enter
+ * @sa glfwSetCursorEnterCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
+
+/*! @brief The function signature for scroll callbacks.
+ *
+ * This is the function signature for scroll callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] xoffset The scroll offset along the x-axis.
+ * @param[in] yoffset The scroll offset along the y-axis.
+ *
+ * @sa @ref scrolling
+ * @sa glfwSetScrollCallback
+ *
+ * @since Added in version 3.0. Replaces `GLFWmousewheelfun`.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
+
+/*! @brief The function signature for keyboard key callbacks.
+ *
+ * This is the function signature for keyboard key callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] key The [keyboard key](@ref keys) that was pressed or released.
+ * @param[in] scancode The system-specific scancode of the key.
+ * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_key
+ * @sa glfwSetKeyCallback
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle, scancode and modifier mask parameters.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);
+
+/*! @brief The function signature for Unicode character callbacks.
+ *
+ * This is the function signature for Unicode character callback functions.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the character.
+ *
+ * @sa @ref input_char
+ * @sa glfwSetCharCallback
+ *
+ * @since Added in version 2.4.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
+
+/*! @brief The function signature for Unicode character with modifiers
+ * callbacks.
+ *
+ * This is the function signature for Unicode character with modifiers callback
+ * functions. It is called for each input character, regardless of what
+ * modifier keys are held down.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the character.
+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ * held down.
+ *
+ * @sa @ref input_char
+ * @sa glfwSetCharModsCallback
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
+
+/*! @brief The function signature for file drop callbacks.
+ *
+ * This is the function signature for file drop callbacks.
+ *
+ * @param[in] window The window that received the event.
+ * @param[in] count The number of dropped files.
+ * @param[in] paths The UTF-8 encoded file and/or directory path names.
+ *
+ * @sa @ref path_drop
+ * @sa glfwSetDropCallback
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
+
+/*! @brief The function signature for monitor configuration callbacks.
+ *
+ * This is the function signature for monitor configuration callback functions.
+ *
+ * @param[in] monitor The monitor that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
+ *
+ * @sa @ref monitor_event
+ * @sa glfwSetMonitorCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
+
+/*! @brief The function signature for joystick configuration callbacks.
+ *
+ * This is the function signature for joystick configuration callback
+ * functions.
+ *
+ * @param[in] joy The joystick that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
+ *
+ * @sa @ref joystick_event
+ * @sa glfwSetJoystickCallback
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+typedef void (* GLFWjoystickfun)(int,int);
+
+/*! @brief Video mode type.
+ *
+ * This describes a single video mode.
+ *
+ * @sa @ref monitor_modes
+ * @sa glfwGetVideoMode glfwGetVideoModes
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added refresh rate member.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWvidmode
+{
+ /*! The width, in screen coordinates, of the video mode.
+ */
+ int width;
+ /*! The height, in screen coordinates, of the video mode.
+ */
+ int height;
+ /*! The bit depth of the red channel of the video mode.
+ */
+ int redBits;
+ /*! The bit depth of the green channel of the video mode.
+ */
+ int greenBits;
+ /*! The bit depth of the blue channel of the video mode.
+ */
+ int blueBits;
+ /*! The refresh rate, in Hz, of the video mode.
+ */
+ int refreshRate;
+} GLFWvidmode;
+
+/*! @brief Gamma ramp.
+ *
+ * This describes the gamma ramp for a monitor.
+ *
+ * @sa @ref monitor_gamma
+ * @sa glfwGetGammaRamp glfwSetGammaRamp
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+typedef struct GLFWgammaramp
+{
+ /*! An array of value describing the response of the red channel.
+ */
+ unsigned short* red;
+ /*! An array of value describing the response of the green channel.
+ */
+ unsigned short* green;
+ /*! An array of value describing the response of the blue channel.
+ */
+ unsigned short* blue;
+ /*! The number of elements in each array.
+ */
+ unsigned int size;
+} GLFWgammaramp;
+
+/*! @brief Image data.
+ *
+ * @sa @ref cursor_custom
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Removed format and bytes-per-pixel members.
+ */
+typedef struct GLFWimage
+{
+ /*! The width, in pixels, of this image.
+ */
+ int width;
+ /*! The height, in pixels, of this image.
+ */
+ int height;
+ /*! The pixel data of this image, arranged left-to-right, top-to-bottom.
+ */
+ unsigned char* pixels;
+} GLFWimage;
+
+
+/*************************************************************************
+ * GLFW API functions
+ *************************************************************************/
+
+/*! @brief Initializes the GLFW library.
+ *
+ * This function initializes the GLFW library. Before most GLFW functions can
+ * be used, GLFW must be initialized, and before an application terminates GLFW
+ * should be terminated in order to free any resources allocated during or
+ * after initialization.
+ *
+ * If this function fails, it calls @ref glfwTerminate before returning. If it
+ * succeeds, you should call @ref glfwTerminate before the application exits.
+ *
+ * Additional calls to this function after successful initialization but before
+ * termination will return `GLFW_TRUE` immediately.
+ *
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark @osx This function will change the current directory of the
+ * application to the `Contents/Resources` subdirectory of the application's
+ * bundle, if present. This can be disabled with a
+ * [compile-time option](@ref compile_options_osx).
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref intro_init
+ * @sa glfwTerminate
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI int glfwInit(void);
+
+/*! @brief Terminates the GLFW library.
+ *
+ * This function destroys all remaining windows and cursors, restores any
+ * modified gamma ramps and frees any other allocated resources. Once this
+ * function is called, you must again call @ref glfwInit successfully before
+ * you will be able to use most GLFW functions.
+ *
+ * If GLFW has been successfully initialized, this function should be called
+ * before the application exits. If initialization fails, there is no need to
+ * call this function, as it is called by @ref glfwInit before it returns
+ * failure.
+ *
+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @warning The contexts of any remaining windows must not be current on any
+ * other thread when this function is called.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref intro_init
+ * @sa glfwInit
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwTerminate(void);
+
+/*! @brief Retrieves the version of the GLFW library.
+ *
+ * This function retrieves the major, minor and revision numbers of the GLFW
+ * library. It is intended for when you are using GLFW as a shared library and
+ * want to ensure that you are using the minimum required version.
+ *
+ * Any or all of the version arguments may be `NULL`.
+ *
+ * @param[out] major Where to store the major version number, or `NULL`.
+ * @param[out] minor Where to store the minor version number, or `NULL`.
+ * @param[out] rev Where to store the revision number, or `NULL`.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref intro_version
+ * @sa glfwGetVersionString
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);
+
+/*! @brief Returns a string describing the compile-time configuration.
+ *
+ * This function returns the compile-time generated
+ * [version string](@ref intro_version_string) of the GLFW library binary. It
+ * describes the version, platform, compiler and any platform-specific
+ * compile-time options. It should not be confused with the OpenGL or OpenGL
+ * ES version string, queried with `glGetString`.
+ *
+ * __Do not use the version string__ to parse the GLFW library version. The
+ * @ref glfwGetVersion function provides the version of the running library
+ * binary in numerical format.
+ *
+ * @return The ASCII encoded GLFW version string.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @pointer_lifetime The returned string is static and compile-time generated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref intro_version
+ * @sa glfwGetVersion
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI const char* glfwGetVersionString(void);
+
+/*! @brief Sets the error callback.
+ *
+ * This function sets the error callback, which is called with an error code
+ * and a human-readable description each time a GLFW error occurs.
+ *
+ * The error callback is called on the thread where the error occurred. If you
+ * are using GLFW from multiple threads, your error callback needs to be
+ * written accordingly.
+ *
+ * Because the description string may have been generated specifically for that
+ * error, it is not guaranteed to be valid after the callback has returned. If
+ * you wish to use it after the callback returns, you need to make a copy.
+ *
+ * Once set, the error callback remains set even after the library has been
+ * terminated.
+ *
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set.
+ *
+ * @errors None.
+ *
+ * @remark This function may be called before @ref glfwInit.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref error_handling
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup init
+ */
+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);
+
+/*! @brief Returns the currently connected monitors.
+ *
+ * This function returns an array of handles for all currently connected
+ * monitors. The primary monitor is always first in the returned array. If no
+ * monitors were found, this function returns `NULL`.
+ *
+ * @param[out] count Where to store the number of monitors in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of monitor handles, or `NULL` if no monitors were found or
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * monitor configuration changes or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_monitors
+ * @sa @ref monitor_event
+ * @sa glfwGetPrimaryMonitor
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);
+
+/*! @brief Returns the primary monitor.
+ *
+ * This function returns the primary monitor. This is usually the monitor
+ * where elements like the task bar or global menu bar are located.
+ *
+ * @return The primary monitor, or `NULL` if no monitors were found or if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @remark The primary monitor is always first in the array returned by @ref
+ * glfwGetMonitors.
+ *
+ * @sa @ref monitor_monitors
+ * @sa glfwGetMonitors
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
+
+/*! @brief Returns the position of the monitor's viewport on the virtual screen.
+ *
+ * This function returns the position, in screen coordinates, of the upper-left
+ * corner of the specified monitor.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.
+ * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
+
+/*! @brief Returns the physical size of the monitor.
+ *
+ * This function returns the size, in millimetres, of the display area of the
+ * specified monitor.
+ *
+ * Some systems do not provide accurate monitor size information, either
+ * because the monitor
+ * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data)
+ * data is incorrect or because the driver does not report it accurately.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] widthMM Where to store the width, in millimetres, of the
+ * monitor's display area, or `NULL`.
+ * @param[out] heightMM Where to store the height, in millimetres, of the
+ * monitor's display area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @win32 calculates the returned physical size from the
+ * current resolution and system DPI instead of querying the monitor EDID data.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);
+
+/*! @brief Returns the name of the specified monitor.
+ *
+ * This function returns a human-readable name, encoded as UTF-8, of the
+ * specified monitor. The name typically reflects the make and model of the
+ * monitor and is not guaranteed to be unique among the connected monitors.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The UTF-8 encoded name of the monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_properties
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);
+
+/*! @brief Sets the monitor configuration callback.
+ *
+ * This function sets the monitor configuration callback, or removes the
+ * currently set callback. This is called when a monitor is connected to or
+ * disconnected from the system.
+ *
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_event
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun);
+
+/*! @brief Returns the available video modes for the specified monitor.
+ *
+ * This function returns an array of all video modes supported by the specified
+ * monitor. The returned array is sorted in ascending order, first by color
+ * bit depth (the sum of all channel depths) and then by resolution area (the
+ * product of width and height).
+ *
+ * @param[in] monitor The monitor to query.
+ * @param[out] count Where to store the number of video modes in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of video modes, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected, this function is called again for that monitor or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_modes
+ * @sa glfwGetVideoMode
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Changed to return an array of modes for a specific monitor.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count);
+
+/*! @brief Returns the current mode of the specified monitor.
+ *
+ * This function returns the current video mode of the specified monitor. If
+ * you have created a full screen window for that monitor, the return value
+ * will depend on whether that window is iconified.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The current mode of the monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified monitor is
+ * disconnected or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_modes
+ * @sa glfwGetVideoModes
+ *
+ * @since Added in version 3.0. Replaces `glfwGetDesktopMode`.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
+
+/*! @brief Generates a gamma ramp and sets it for the specified monitor.
+ *
+ * This function generates a 256-element gamma ramp from the specified exponent
+ * and then calls @ref glfwSetGammaRamp with it. The value must be a finite
+ * number greater than zero.
+ *
+ * @param[in] monitor The monitor whose gamma ramp to set.
+ * @param[in] gamma The desired exponent.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
+
+/*! @brief Returns the current gamma ramp for the specified monitor.
+ *
+ * This function returns the current gamma ramp of the specified monitor.
+ *
+ * @param[in] monitor The monitor to query.
+ * @return The current gamma ramp, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned structure and its arrays are allocated and
+ * freed by GLFW. You should not free them yourself. They are valid until the
+ * specified monitor is disconnected, this function is called again for that
+ * monitor or the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
+
+/*! @brief Sets the current gamma ramp for the specified monitor.
+ *
+ * This function sets the current gamma ramp for the specified monitor. The
+ * original gamma ramp for that monitor is saved by GLFW the first time this
+ * function is called and is restored by @ref glfwTerminate.
+ *
+ * @param[in] monitor The monitor whose gamma ramp to set.
+ * @param[in] ramp The gamma ramp to use.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark Gamma ramp sizes other than 256 are not supported by all platforms
+ * or graphics hardware.
+ *
+ * @remark @win32 The gamma ramp size must be 256.
+ *
+ * @pointer_lifetime The specified gamma ramp is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref monitor_gamma
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup monitor
+ */
+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);
+
+/*! @brief Resets all window hints to their default values.
+ *
+ * This function resets all window hints to their
+ * [default values](@ref window_hints_values).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa glfwWindowHint
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwDefaultWindowHints(void);
+
+/*! @brief Sets the specified window hint to the desired value.
+ *
+ * This function sets hints for the next call to @ref glfwCreateWindow. The
+ * hints, once set, retain their values until changed by a call to @ref
+ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is
+ * terminated.
+ *
+ * This function does not check whether the specified hint values are valid.
+ * If you set hints to invalid values this will instead be reported by the next
+ * call to @ref glfwCreateWindow.
+ *
+ * @param[in] hint The [window hint](@ref window_hints) to set.
+ * @param[in] value The new value of the window hint.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hints
+ * @sa glfwDefaultWindowHints
+ *
+ * @since Added in version 3.0. Replaces `glfwOpenWindowHint`.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWindowHint(int hint, int value);
+
+/*! @brief Creates a window and its associated context.
+ *
+ * This function creates a window and its associated OpenGL or OpenGL ES
+ * context. Most of the options controlling how the window and its context
+ * should be created are specified with [window hints](@ref window_hints).
+ *
+ * Successful creation does not change which context is current. Before you
+ * can use the newly created context, you need to
+ * [make it current](@ref context_current). For information about the `share`
+ * parameter, see @ref context_sharing.
+ *
+ * The created window, framebuffer and context may differ from what you
+ * requested, as not all parameters and hints are
+ * [hard constraints](@ref window_hints_hard). This includes the size of the
+ * window, especially for full screen windows. To query the actual attributes
+ * of the created window, framebuffer and context, see @ref
+ * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
+ *
+ * To create a full screen window, you need to specify the monitor the window
+ * will cover. If no monitor is specified, the window will be windowed mode.
+ * Unless you have a way for the user to choose a specific monitor, it is
+ * recommended that you pick the primary monitor. For more information on how
+ * to query connected monitors, see @ref monitor_monitors.
+ *
+ * For full screen windows, the specified size becomes the resolution of the
+ * window's _desired video mode_. As long as a full screen window is not
+ * iconified, the supported video mode most closely matching the desired video
+ * mode is set for the specified monitor. For more information about full
+ * screen windows, including the creation of so called _windowed full screen_
+ * or _borderless full screen_ windows, see @ref window_windowed_full_screen.
+ *
+ * By default, newly created windows use the placement recommended by the
+ * window system. To create the window at a specific position, make it
+ * initially invisible using the [GLFW_VISIBLE](@ref window_hints_wnd) window
+ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide)
+ * it.
+ *
+ * As long as at least one full screen window is not iconified, the screensaver
+ * is prohibited from starting.
+ *
+ * Window systems put limits on window sizes. Very large or very small window
+ * dimensions may be overridden by the window system on creation. Check the
+ * actual [size](@ref window_size) after creation.
+ *
+ * The [swap interval](@ref buffer_swap) is not set during window creation and
+ * the initial value may vary depending on driver settings and defaults.
+ *
+ * @param[in] width The desired width, in screen coordinates, of the window.
+ * This must be greater than zero.
+ * @param[in] height The desired height, in screen coordinates, of the window.
+ * This must be greater than zero.
+ * @param[in] title The initial, UTF-8 encoded window title.
+ * @param[in] monitor The monitor to use for full screen mode, or `NULL` for
+ * windowed mode.
+ * @param[in] share The window whose context to share resources with, or `NULL`
+ * to not share resources.
+ * @return The handle of the created window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref
+ * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @win32 Window creation will fail if the Microsoft GDI software
+ * OpenGL implementation is the only one available.
+ *
+ * @remark @win32 If the executable has an icon resource named `GLFW_ICON,`
+ * it will be set as the icon for the window. If no such icon is present, the
+ * `IDI_WINLOGO` icon will be used instead.
+ *
+ * @remark @win32 The context to share resources with must not be current on
+ * any other thread.
+ *
+ * @remark @osx The GLFW window has no icon, as it is not a document
+ * window, but the dock icon will be the same as the application bundle's icon.
+ * For more information on bundles, see the
+ * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
+ * in the Mac Developer Library.
+ *
+ * @remark @osx The first time a window is created the menu bar is populated
+ * with common commands like Hide, Quit and About. The About entry opens
+ * a minimal about dialog with information from the application's bundle. The
+ * menu bar can be disabled with a
+ * [compile-time option](@ref compile_options_osx).
+ *
+ * @remark @osx On OS X 10.10 and later the window frame will not be rendered
+ * at full resolution on Retina displays unless the `NSHighResolutionCapable`
+ * key is enabled in the application bundle's `Info.plist`. For more
+ * information, see
+ * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
+ * in the Mac Developer Library. The GLFW test and example programs use
+ * a custom `Info.plist` template for this, which can be found as
+ * `CMake/MacOSXBundleInfo.plist.in` in the source tree.
+ *
+ * @remark @x11 There is no mechanism for setting the window icon yet.
+ *
+ * @remark @x11 Some window managers will not respect the placement of
+ * initially hidden windows.
+ *
+ * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for
+ * a window to reach its requested state. This means you may not be able to
+ * query the final size, position or other attributes directly after window
+ * creation.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_creation
+ * @sa glfwDestroyWindow
+ *
+ * @since Added in version 3.0. Replaces `glfwOpenWindow`.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
+
+/*! @brief Destroys the specified window and its context.
+ *
+ * This function destroys the specified window and its context. On calling
+ * this function, no further callbacks will be called for that window.
+ *
+ * If the context of the specified window is current on the main thread, it is
+ * detached before being destroyed.
+ *
+ * @param[in] window The window to destroy.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @note The context of the specified window must not be current on any other
+ * thread when this function is called.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_creation
+ * @sa glfwCreateWindow
+ *
+ * @since Added in version 3.0. Replaces `glfwCloseWindow`.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwDestroyWindow(GLFWwindow* window);
+
+/*! @brief Checks the close flag of the specified window.
+ *
+ * This function returns the value of the close flag of the specified window.
+ *
+ * @param[in] window The window to query.
+ * @return The value of the close flag.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);
+
+/*! @brief Sets the close flag of the specified window.
+ *
+ * This function sets the value of the close flag of the specified window.
+ * This can be used to override the user's attempt to close the window, or
+ * to signal that it should be closed.
+ *
+ * @param[in] window The window whose flag to change.
+ * @param[in] value The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);
+
+/*! @brief Sets the title of the specified window.
+ *
+ * This function sets the window title, encoded as UTF-8, of the specified
+ * window.
+ *
+ * @param[in] window The window whose title to change.
+ * @param[in] title The UTF-8 encoded window title.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @osx The window title will not be updated until the next time you
+ * process events.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_title
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
+
+/*! @brief Sets the icon for the specified window.
+ *
+ * This function sets the icon of the specified window. If passed an array of
+ * candidate images, those of or closest to the sizes desired by the system are
+ * selected. If no images are specified, the window reverts to its default
+ * icon.
+ *
+ * The desired image sizes varies depending on platform and system settings.
+ * The selected images will be rescaled as needed. Good sizes include 16x16,
+ * 32x32 and 48x48.
+ *
+ * @param[in] window The window whose icon to set.
+ * @param[in] count The number of images in the specified array, or zero to
+ * revert to the default window icon.
+ * @param[in] images The images to create the icon from. This is ignored if
+ * count is zero.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified image data is copied before this function
+ * returns.
+ *
+ * @remark @osx The GLFW window has no icon, as it is not a document
+ * window, but the dock icon will be the same as the application bundle's icon.
+ * For more information on bundles, see the
+ * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)
+ * in the Mac Developer Library.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_icon
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
+
+/*! @brief Retrieves the position of the client area of the specified window.
+ *
+ * This function retrieves the position, in screen coordinates, of the
+ * upper-left corner of the client area of the specified window.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] window The window to query.
+ * @param[out] xpos Where to store the x-coordinate of the upper-left corner of
+ * the client area, or `NULL`.
+ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of
+ * the client area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ * @sa glfwSetWindowPos
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
+
+/*! @brief Sets the position of the client area of the specified window.
+ *
+ * This function sets the position, in screen coordinates, of the upper-left
+ * corner of the client area of the specified windowed mode window. If the
+ * window is a full screen window, this function does nothing.
+ *
+ * __Do not use this function__ to move an already visible window unless you
+ * have very good reasons for doing so, as it will confuse and annoy the user.
+ *
+ * The window manager may put limits on what positions are allowed. GLFW
+ * cannot and should not override these limits.
+ *
+ * @param[in] window The window to query.
+ * @param[in] xpos The x-coordinate of the upper-left corner of the client area.
+ * @param[in] ypos The y-coordinate of the upper-left corner of the client area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ * @sa glfwGetWindowPos
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
+
+/*! @brief Retrieves the size of the client area of the specified window.
+ *
+ * This function retrieves the size, in screen coordinates, of the client area
+ * of the specified window. If you wish to retrieve the size of the
+ * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose size to retrieve.
+ * @param[out] width Where to store the width, in screen coordinates, of the
+ * client area, or `NULL`.
+ * @param[out] height Where to store the height, in screen coordinates, of the
+ * client area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ * @sa glfwSetWindowSize
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
+
+/*! @brief Sets the size limits of the specified window.
+ *
+ * This function sets the size limits of the client area of the specified
+ * window. If the window is full screen, the size limits only take effect if
+ * once it is made windowed. If the window is not resizable, this function
+ * does nothing.
+ *
+ * The size limits are applied immediately to a windowed mode window and may
+ * cause it to be resized.
+ *
+ * @param[in] window The window to set limits for.
+ * @param[in] minwidth The minimum width, in screen coordinates, of the client
+ * area, or `GLFW_DONT_CARE`.
+ * @param[in] minheight The minimum height, in screen coordinates, of the
+ * client area, or `GLFW_DONT_CARE`.
+ * @param[in] maxwidth The maximum width, in screen coordinates, of the client
+ * area, or `GLFW_DONT_CARE`.
+ * @param[in] maxheight The maximum height, in screen coordinates, of the
+ * client area, or `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark If you set size limits and an aspect ratio that conflict, the
+ * results are undefined.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_sizelimits
+ * @sa glfwSetWindowAspectRatio
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
+
+/*! @brief Sets the aspect ratio of the specified window.
+ *
+ * This function sets the required aspect ratio of the client area of the
+ * specified window. If the window is full screen, the aspect ratio only takes
+ * effect once it is made windowed. If the window is not resizable, this
+ * function does nothing.
+ *
+ * The aspect ratio is specified as a numerator and a denominator and both
+ * values must be greater than zero. For example, the common 16:9 aspect ratio
+ * is specified as 16 and 9, respectively.
+ *
+ * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect
+ * ratio limit is disabled.
+ *
+ * The aspect ratio is applied immediately to a windowed mode window and may
+ * cause it to be resized.
+ *
+ * @param[in] window The window to set limits for.
+ * @param[in] numer The numerator of the desired aspect ratio, or
+ * `GLFW_DONT_CARE`.
+ * @param[in] denom The denominator of the desired aspect ratio, or
+ * `GLFW_DONT_CARE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark If you set size limits and an aspect ratio that conflict, the
+ * results are undefined.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_sizelimits
+ * @sa glfwSetWindowSizeLimits
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
+
+/*! @brief Sets the size of the client area of the specified window.
+ *
+ * This function sets the size, in screen coordinates, of the client area of
+ * the specified window.
+ *
+ * For full screen windows, this function updates the resolution of its desired
+ * video mode and switches to the video mode closest to it, without affecting
+ * the window's context. As the context is unaffected, the bit depths of the
+ * framebuffer remain unchanged.
+ *
+ * If you wish to update the refresh rate of the desired video mode in addition
+ * to its resolution, see @ref glfwSetWindowMonitor.
+ *
+ * The window manager may put limits on what sizes are allowed. GLFW cannot
+ * and should not override these limits.
+ *
+ * @param[in] window The window to resize.
+ * @param[in] width The desired width, in screen coordinates, of the window
+ * client area.
+ * @param[in] height The desired height, in screen coordinates, of the window
+ * client area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ * @sa glfwGetWindowSize
+ * @sa glfwSetWindowMonitor
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);
+
+/*! @brief Retrieves the size of the framebuffer of the specified window.
+ *
+ * This function retrieves the size, in pixels, of the framebuffer of the
+ * specified window. If you wish to retrieve the size of the window in screen
+ * coordinates, see @ref glfwGetWindowSize.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose framebuffer to query.
+ * @param[out] width Where to store the width, in pixels, of the framebuffer,
+ * or `NULL`.
+ * @param[out] height Where to store the height, in pixels, of the framebuffer,
+ * or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_fbsize
+ * @sa glfwSetFramebufferSizeCallback
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height);
+
+/*! @brief Retrieves the size of the frame of the window.
+ *
+ * This function retrieves the size, in screen coordinates, of each edge of the
+ * frame of the specified window. This size includes the title bar, if the
+ * window has one. The size of the frame may vary depending on the
+ * [window-related hints](@ref window_hints_wnd) used to create it.
+ *
+ * Because this function retrieves the size of each window frame edge and not
+ * the offset along a particular coordinate axis, the retrieved values will
+ * always be zero or positive.
+ *
+ * Any or all of the size arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` size arguments will be set to zero.
+ *
+ * @param[in] window The window whose frame size to query.
+ * @param[out] left Where to store the size, in screen coordinates, of the left
+ * edge of the window frame, or `NULL`.
+ * @param[out] top Where to store the size, in screen coordinates, of the top
+ * edge of the window frame, or `NULL`.
+ * @param[out] right Where to store the size, in screen coordinates, of the
+ * right edge of the window frame, or `NULL`.
+ * @param[out] bottom Where to store the size, in screen coordinates, of the
+ * bottom edge of the window frame, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);
+
+/*! @brief Iconifies the specified window.
+ *
+ * This function iconifies (minimizes) the specified window if it was
+ * previously restored. If the window is already iconified, this function does
+ * nothing.
+ *
+ * If the specified window is a full screen window, the original monitor
+ * resolution is restored until the window is restored.
+ *
+ * @param[in] window The window to iconify.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa glfwRestoreWindow
+ * @sa glfwMaximizeWindow
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
+
+/*! @brief Restores the specified window.
+ *
+ * This function restores the specified window if it was previously iconified
+ * (minimized) or maximized. If the window is already restored, this function
+ * does nothing.
+ *
+ * If the specified window is a full screen window, the resolution chosen for
+ * the window is restored on the selected monitor.
+ *
+ * @param[in] window The window to restore.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa glfwIconifyWindow
+ * @sa glfwMaximizeWindow
+ *
+ * @since Added in version 2.1.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwRestoreWindow(GLFWwindow* window);
+
+/*! @brief Maximizes the specified window.
+ *
+ * This function maximizes the specified window if it was previously not
+ * maximized. If the window is already maximized, this function does nothing.
+ *
+ * If the specified window is a full screen window, this function does nothing.
+ *
+ * @param[in] window The window to maximize.
+ *
+ * @par Thread Safety
+ * This function may only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ * @sa glfwIconifyWindow
+ * @sa glfwRestoreWindow
+ *
+ * @since Added in GLFW 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
+
+/*! @brief Makes the specified window visible.
+ *
+ * This function makes the specified window visible if it was previously
+ * hidden. If the window is already visible or is in full screen mode, this
+ * function does nothing.
+ *
+ * @param[in] window The window to make visible.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hide
+ * @sa glfwHideWindow
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwShowWindow(GLFWwindow* window);
+
+/*! @brief Hides the specified window.
+ *
+ * This function hides the specified window if it was previously visible. If
+ * the window is already hidden or is in full screen mode, this function does
+ * nothing.
+ *
+ * @param[in] window The window to hide.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_hide
+ * @sa glfwShowWindow
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwHideWindow(GLFWwindow* window);
+
+/*! @brief Brings the specified window to front and sets input focus.
+ *
+ * This function brings the specified window to front and sets input focus.
+ * The window should already be visible and not iconified.
+ *
+ * By default, both windowed and full screen mode windows are focused when
+ * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable
+ * this behavior.
+ *
+ * __Do not use this function__ to steal focus from other applications unless
+ * you are certain that is what the user wants. Focus stealing can be
+ * extremely disruptive.
+ *
+ * @param[in] window The window to give input focus.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_focus
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwFocusWindow(GLFWwindow* window);
+
+/*! @brief Returns the monitor that the window uses for full screen mode.
+ *
+ * This function returns the handle of the monitor that the specified window is
+ * in full screen on.
+ *
+ * @param[in] window The window to query.
+ * @return The monitor, or `NULL` if the window is in windowed mode or an error
+ * occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_monitor
+ * @sa glfwSetWindowMonitor
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
+
+/*! @brief Sets the mode, monitor, video mode and placement of a window.
+ *
+ * This function sets the monitor that the window uses for full screen mode or,
+ * if the monitor is `NULL`, makes it windowed mode.
+ *
+ * When setting a monitor, this function updates the width, height and refresh
+ * rate of the desired video mode and switches to the video mode closest to it.
+ * The window position is ignored when setting a monitor.
+ *
+ * When the monitor is `NULL`, the position, width and height are used to
+ * place the window client area. The refresh rate is ignored when no monitor
+ * is specified.
+ *
+ * If you only wish to update the resolution of a full screen window or the
+ * size of a windowed mode window, see @ref glfwSetWindowSize.
+ *
+ * When a window transitions from full screen to windowed mode, this function
+ * restores any previous window settings such as whether it is decorated,
+ * floating, resizable, has size or aspect ratio limits, etc..
+ *
+ * @param[in] window The window whose monitor, size or video mode to set.
+ * @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
+ * @param[in] xpos The desired x-coordinate of the upper-left corner of the
+ * client area.
+ * @param[in] ypos The desired y-coordinate of the upper-left corner of the
+ * client area.
+ * @param[in] width The desired with, in screen coordinates, of the client area
+ * or video mode.
+ * @param[in] height The desired height, in screen coordinates, of the client
+ * area or video mode.
+ * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_monitor
+ * @sa @ref window_full_screen
+ * @sa glfwGetWindowMonitor
+ * @sa glfwSetWindowSize
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
+
+/*! @brief Returns an attribute of the specified window.
+ *
+ * This function returns the value of an attribute of the specified window or
+ * its OpenGL or OpenGL ES context.
+ *
+ * @param[in] window The window to query.
+ * @param[in] attrib The [window attribute](@ref window_attribs) whose value to
+ * return.
+ * @return The value of the attribute, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark Framebuffer related hints are not window attributes. See @ref
+ * window_attribs_fb for more information.
+ *
+ * @remark Zero is a valid value for many window and context related
+ * attributes so you cannot use a return value of zero as an indication of
+ * errors. However, this function should not fail as long as it is passed
+ * valid arguments and the library has been [initialized](@ref intro_init).
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_attribs
+ *
+ * @since Added in version 3.0. Replaces `glfwGetWindowParam` and
+ * `glfwGetGLVersion`.
+ *
+ * @ingroup window
+ */
+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
+
+/*! @brief Sets the user pointer of the specified window.
+ *
+ * This function sets the user-defined pointer of the specified window. The
+ * current value is retained until the window is destroyed. The initial value
+ * is `NULL`.
+ *
+ * @param[in] window The window whose pointer to set.
+ * @param[in] pointer The new value.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_userptr
+ * @sa glfwGetWindowUserPointer
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);
+
+/*! @brief Returns the user pointer of the specified window.
+ *
+ * This function returns the current value of the user-defined pointer of the
+ * specified window. The initial value is `NULL`.
+ *
+ * @param[in] window The window whose pointer to return.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @sa @ref window_userptr
+ * @sa glfwSetWindowUserPointer
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
+
+/*! @brief Sets the position callback for the specified window.
+ *
+ * This function sets the position callback of the specified window, which is
+ * called when the window is moved. The callback is provided with the screen
+ * position of the upper-left corner of the client area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_pos
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun cbfun);
+
+/*! @brief Sets the size callback for the specified window.
+ *
+ * This function sets the size callback of the specified window, which is
+ * called when the window is resized. The callback is provided with the size,
+ * in screen coordinates, of the client area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_size
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbfun);
+
+/*! @brief Sets the close callback for the specified window.
+ *
+ * This function sets the close callback of the specified window, which is
+ * called when the user attempts to close the window, for example by clicking
+ * the close widget in the title bar.
+ *
+ * The close flag is set before this callback is called, but you can modify it
+ * at any time with @ref glfwSetWindowShouldClose.
+ *
+ * The close callback is not triggered by @ref glfwDestroyWindow.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @remark @osx Selecting Quit from the application menu will trigger the close
+ * callback for all windows.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_close
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun);
+
+/*! @brief Sets the refresh callback for the specified window.
+ *
+ * This function sets the refresh callback of the specified window, which is
+ * called when the client area of the window needs to be redrawn, for example
+ * if the window has been exposed after having been covered by another window.
+ *
+ * On compositing window systems such as Aero, Compiz or Aqua, where the window
+ * contents are saved off-screen, this callback may be called only very
+ * infrequently or never at all.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_refresh
+ *
+ * @since Added in version 2.5.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun cbfun);
+
+/*! @brief Sets the focus callback for the specified window.
+ *
+ * This function sets the focus callback of the specified window, which is
+ * called when the window gains or loses input focus.
+ *
+ * After the focus callback is called for a window that lost input focus,
+ * synthetic key and mouse button release events will be generated for all such
+ * that had been pressed. For more information, see @ref glfwSetKeyCallback
+ * and @ref glfwSetMouseButtonCallback.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_focus
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);
+
+/*! @brief Sets the iconify callback for the specified window.
+ *
+ * This function sets the iconification callback of the specified window, which
+ * is called when the window is iconified or restored.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_iconify
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);
+
+/*! @brief Sets the framebuffer resize callback for the specified window.
+ *
+ * This function sets the framebuffer resize callback of the specified window,
+ * which is called when the framebuffer of the specified window is resized.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref window_fbsize
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);
+
+/*! @brief Processes all pending events.
+ *
+ * This function processes only those events that are already in the event
+ * queue and then returns immediately. Processing events will cause the window
+ * and input callbacks associated with those events to be called.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * On some platforms, certain events are sent directly to the application
+ * without going through the event queue, causing callbacks to be called
+ * outside of a call to one of the event processing functions.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa glfwWaitEvents
+ * @sa glfwWaitEventsTimeout
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwPollEvents(void);
+
+/*! @brief Waits until events are queued and processes them.
+ *
+ * This function puts the calling thread to sleep until at least one event is
+ * available in the event queue. Once one or more events are available,
+ * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue
+ * are processed and the function then returns immediately. Processing events
+ * will cause the window and input callbacks associated with those events to be
+ * called.
+ *
+ * Since not all events are associated with callbacks, this function may return
+ * without a callback having been called even if you are monitoring all
+ * callbacks.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * On some platforms, certain callbacks may be called outside of a call to one
+ * of the event processing functions.
+ *
+ * If no windows exist, this function returns immediately. For synchronization
+ * of threads in applications that do not create windows, use your threading
+ * library of choice.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa glfwPollEvents
+ * @sa glfwWaitEventsTimeout
+ *
+ * @since Added in version 2.5.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWaitEvents(void);
+
+/*! @brief Waits with timeout until events are queued and processes them.
+ *
+ * This function puts the calling thread to sleep until at least one event is
+ * available in the event queue, or until the specified timeout is reached. If
+ * one or more events are available, it behaves exactly like @ref
+ * glfwPollEvents, i.e. the events in the queue are processed and the function
+ * then returns immediately. Processing events will cause the window and input
+ * callbacks associated with those events to be called.
+ *
+ * The timeout value must be a positive finite number.
+ *
+ * Since not all events are associated with callbacks, this function may return
+ * without a callback having been called even if you are monitoring all
+ * callbacks.
+ *
+ * On some platforms, a window move, resize or menu operation will cause event
+ * processing to block. This is due to how event processing is designed on
+ * those platforms. You can use the
+ * [window refresh callback](@ref window_refresh) to redraw the contents of
+ * your window when necessary during such operations.
+ *
+ * On some platforms, certain callbacks may be called outside of a call to one
+ * of the event processing functions.
+ *
+ * If no windows exist, this function returns immediately. For synchronization
+ * of threads in applications that do not create windows, use your threading
+ * library of choice.
+ *
+ * Event processing is not required for joystick input to work.
+ *
+ * @param[in] timeout The maximum amount of time, in seconds, to wait.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref events
+ * @sa glfwPollEvents
+ * @sa glfwWaitEvents
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwWaitEventsTimeout(double timeout);
+
+/*! @brief Posts an empty event to the event queue.
+ *
+ * This function posts an empty event from the current thread to the event
+ * queue, causing @ref glfwWaitEvents to return.
+ *
+ * If no windows exist, this function returns immediately. For synchronization
+ * of threads in applications that do not create windows, use your threading
+ * library of choice.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref events
+ * @sa glfwWaitEvents
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwPostEmptyEvent(void);
+
+/*! @brief Returns the value of an input option for the specified window.
+ *
+ * This function returns the value of an input option for the specified window.
+ * The mode must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
+ * `GLFW_STICKY_MOUSE_BUTTONS`.
+ *
+ * @param[in] window The window to query.
+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
+ * `GLFW_STICKY_MOUSE_BUTTONS`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa glfwSetInputMode
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
+
+/*! @brief Sets an input option for the specified window.
+ *
+ * This function sets an input mode option for the specified window. The mode
+ * must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
+ * `GLFW_STICKY_MOUSE_BUTTONS`.
+ *
+ * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
+ * modes:
+ * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.
+ * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client
+ * area of the window but does not restrict the cursor from leaving.
+ * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual
+ * and unlimited cursor movement. This is useful for implementing for
+ * example 3D camera controls.
+ *
+ * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
+ * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
+ * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`
+ * the next time it is called even if the key had been released before the
+ * call. This is useful when you are only interested in whether keys have been
+ * pressed but not when or in which order.
+ *
+ * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either
+ * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it.
+ * If sticky mouse buttons are enabled, a mouse button press will ensure that
+ * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even
+ * if the mouse button had been released before the call. This is useful when
+ * you are only interested in whether mouse buttons have been pressed but not
+ * when or in which order.
+ *
+ * @param[in] window The window whose input mode to set.
+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or
+ * `GLFW_STICKY_MOUSE_BUTTONS`.
+ * @param[in] value The new value of the specified input mode.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa glfwGetInputMode
+ *
+ * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
+
+/*! @brief Returns the localized name of the specified printable key.
+ *
+ * This function returns the localized name of the specified printable key.
+ * This is intended for displaying key bindings to the user.
+ *
+ * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise
+ * the scancode is ignored. If a non-printable key or (if the key is
+ * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is
+ * specified, this function returns `NULL`.
+ *
+ * This behavior allows you to pass in the arguments passed to the
+ * [key callback](@ref input_key) without modification.
+ *
+ * The printable keys are:
+ * - `GLFW_KEY_APOSTROPHE`
+ * - `GLFW_KEY_COMMA`
+ * - `GLFW_KEY_MINUS`
+ * - `GLFW_KEY_PERIOD`
+ * - `GLFW_KEY_SLASH`
+ * - `GLFW_KEY_SEMICOLON`
+ * - `GLFW_KEY_EQUAL`
+ * - `GLFW_KEY_LEFT_BRACKET`
+ * - `GLFW_KEY_RIGHT_BRACKET`
+ * - `GLFW_KEY_BACKSLASH`
+ * - `GLFW_KEY_WORLD_1`
+ * - `GLFW_KEY_WORLD_2`
+ * - `GLFW_KEY_0` to `GLFW_KEY_9`
+ * - `GLFW_KEY_A` to `GLFW_KEY_Z`
+ * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`
+ * - `GLFW_KEY_KP_DECIMAL`
+ * - `GLFW_KEY_KP_DIVIDE`
+ * - `GLFW_KEY_KP_MULTIPLY`
+ * - `GLFW_KEY_KP_SUBTRACT`
+ * - `GLFW_KEY_KP_ADD`
+ * - `GLFW_KEY_KP_EQUAL`
+ *
+ * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
+ * @param[in] scancode The scancode of the key to query.
+ * @return The localized name of the key, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetKeyName, or until the library is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key_name
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetKeyName(int key, int scancode);
+
+/*! @brief Returns the last reported state of a keyboard key for the specified
+ * window.
+ *
+ * This function returns the last state reported for the specified key to the
+ * specified window. The returned state is one of `GLFW_PRESS` or
+ * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to
+ * the key callback.
+ *
+ * If the `GLFW_STICKY_KEYS` input mode is enabled, this function returns
+ * `GLFW_PRESS` the first time you call it for a key that was pressed, even if
+ * that key has already been released.
+ *
+ * The key functions deal with physical keys, with [key tokens](@ref keys)
+ * named after their use on the standard US keyboard layout. If you want to
+ * input text, use the Unicode character callback instead.
+ *
+ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be
+ * used with this function.
+ *
+ * __Do not use this function__ to implement [text input](@ref input_char).
+ *
+ * @param[in] window The desired window.
+ * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is
+ * not a valid key for this function.
+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
+
+/*! @brief Returns the last reported state of a mouse button for the specified
+ * window.
+ *
+ * This function returns the last state reported for the specified mouse button
+ * to the specified window. The returned state is one of `GLFW_PRESS` or
+ * `GLFW_RELEASE`.
+ *
+ * If the `GLFW_STICKY_MOUSE_BUTTONS` input mode is enabled, this function
+ * `GLFW_PRESS` the first time you call it for a mouse button that was pressed,
+ * even if that mouse button has already been released.
+ *
+ * @param[in] window The desired window.
+ * @param[in] button The desired [mouse button](@ref buttons).
+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_ENUM.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_mouse_button
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
+
+/*! @brief Retrieves the position of the cursor relative to the client area of
+ * the window.
+ *
+ * This function returns the position of the cursor, in screen coordinates,
+ * relative to the upper-left corner of the client area of the specified
+ * window.
+ *
+ * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
+ * position is unbounded and limited only by the minimum and maximum values of
+ * a `double`.
+ *
+ * The coordinate can be converted to their integer equivalents with the
+ * `floor` function. Casting directly to an integer type works for positive
+ * coordinates, but fails for negative ones.
+ *
+ * Any or all of the position arguments may be `NULL`. If an error occurs, all
+ * non-`NULL` position arguments will be set to zero.
+ *
+ * @param[in] window The desired window.
+ * @param[out] xpos Where to store the cursor x-coordinate, relative to the
+ * left edge of the client area, or `NULL`.
+ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to
+ * top edge of the client area, or `NULL`.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ * @sa glfwSetCursorPos
+ *
+ * @since Added in version 3.0. Replaces `glfwGetMousePos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
+
+/*! @brief Sets the position of the cursor, relative to the client area of the
+ * window.
+ *
+ * This function sets the position, in screen coordinates, of the cursor
+ * relative to the upper-left corner of the client area of the specified
+ * window. The window must have input focus. If the window does not have
+ * input focus when this function is called, it fails silently.
+ *
+ * __Do not use this function__ to implement things like camera controls. GLFW
+ * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the
+ * cursor, transparently re-centers it and provides unconstrained cursor
+ * motion. See @ref glfwSetInputMode for more information.
+ *
+ * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is
+ * unconstrained and limited only by the minimum and maximum values of
+ * a `double`.
+ *
+ * @param[in] window The desired window.
+ * @param[in] xpos The desired x-coordinate, relative to the left edge of the
+ * client area.
+ * @param[in] ypos The desired y-coordinate, relative to the top edge of the
+ * client area.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for
+ * the window focus event to arrive. This means you may not be able to set the
+ * cursor position directly after window creation.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ * @sa glfwGetCursorPos
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMousePos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
+
+/*! @brief Creates a custom cursor.
+ *
+ * Creates a new custom cursor image that can be set for a window with @ref
+ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.
+ * Any remaining cursors are destroyed by @ref glfwTerminate.
+ *
+ * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+ * bits per channel. They are arranged canonically as packed sequential rows,
+ * starting from the top-left corner.
+ *
+ * The cursor hotspot is specified in pixels, relative to the upper-left corner
+ * of the cursor image. Like all other coordinate systems in GLFW, the X-axis
+ * points to the right and the Y-axis points down.
+ *
+ * @param[in] image The desired cursor image.
+ * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot.
+ * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.
+ * @return The handle of the created cursor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified image data is copied before this function
+ * returns.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa glfwDestroyCursor
+ * @sa glfwCreateStandardCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);
+
+/*! @brief Creates a cursor with a standard shape.
+ *
+ * Returns a cursor with a [standard shape](@ref shapes), that can be set for
+ * a window with @ref glfwSetCursor.
+ *
+ * @param[in] shape One of the [standard shapes](@ref shapes).
+ * @return A new cursor ready to use or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa glfwCreateCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
+
+/*! @brief Destroys a cursor.
+ *
+ * This function destroys a cursor previously created with @ref
+ * glfwCreateCursor. Any remaining cursors will be destroyed by @ref
+ * glfwTerminate.
+ *
+ * @param[in] cursor The cursor object to destroy.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @reentrancy This function must not be called from a callback.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ * @sa glfwCreateCursor
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
+
+/*! @brief Sets the cursor for the window.
+ *
+ * This function sets the cursor image to be used when the cursor is over the
+ * client area of the specified window. The set cursor will only be visible
+ * when the [cursor mode](@ref cursor_mode) of the window is
+ * `GLFW_CURSOR_NORMAL`.
+ *
+ * On some platforms, the set cursor may not be visible unless the window also
+ * has input focus.
+ *
+ * @param[in] window The window to set the cursor for.
+ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default
+ * arrow cursor.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_object
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
+
+/*! @brief Sets the key callback.
+ *
+ * This function sets the key callback of the specified window, which is called
+ * when a key is pressed, repeated or released.
+ *
+ * The key functions deal with physical keys, with layout independent
+ * [key tokens](@ref keys) named after their values in the standard US keyboard
+ * layout. If you want to input text, use the
+ * [character callback](@ref glfwSetCharCallback) instead.
+ *
+ * When a window loses input focus, it will generate synthetic key release
+ * events for all pressed keys. You can tell these events from user-generated
+ * events by the fact that the synthetic ones are generated after the focus
+ * loss event has been processed, i.e. after the
+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
+ *
+ * The scancode of a key is specific to that platform or sometimes even to that
+ * machine. Scancodes are intended to allow users to bind keys that don't have
+ * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their
+ * state is not saved and so it cannot be queried with @ref glfwGetKey.
+ *
+ * Sometimes GLFW needs to generate synthetic key events, in which case the
+ * scancode may be zero.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new key callback, or `NULL` to remove the currently
+ * set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_key
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
+
+/*! @brief Sets the Unicode character callback.
+ *
+ * This function sets the character callback of the specified window, which is
+ * called when a Unicode character is input.
+ *
+ * The character callback is intended for Unicode text input. As it deals with
+ * characters, it is keyboard layout dependent, whereas the
+ * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1
+ * to physical keys, as a key may produce zero, one or more characters. If you
+ * want to know whether a specific physical key was pressed or released, see
+ * the key callback instead.
+ *
+ * The character callback behaves as system text input normally does and will
+ * not be called if modifier keys are held down that would prevent normal text
+ * input on that platform, for example a Super (Command) key on OS X or Alt key
+ * on Windows. There is a
+ * [character with modifiers callback](@ref glfwSetCharModsCallback) that
+ * receives these events.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_char
+ *
+ * @since Added in version 2.4.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);
+
+/*! @brief Sets the Unicode character with modifiers callback.
+ *
+ * This function sets the character with modifiers callback of the specified
+ * window, which is called when a Unicode character is input regardless of what
+ * modifier keys are used.
+ *
+ * The character with modifiers callback is intended for implementing custom
+ * Unicode character input. For regular Unicode text input, see the
+ * [character callback](@ref glfwSetCharCallback). Like the character
+ * callback, the character with modifiers callback deals with characters and is
+ * keyboard layout dependent. Characters do not map 1:1 to physical keys, as
+ * a key may produce zero, one or more characters. If you want to know whether
+ * a specific physical key was pressed or released, see the
+ * [key callback](@ref glfwSetKeyCallback) instead.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or an
+ * error occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_char
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun);
+
+/*! @brief Sets the mouse button callback.
+ *
+ * This function sets the mouse button callback of the specified window, which
+ * is called when a mouse button is pressed or released.
+ *
+ * When a window loses input focus, it will generate synthetic mouse button
+ * release events for all pressed mouse buttons. You can tell these events
+ * from user-generated events by the fact that the synthetic ones are generated
+ * after the focus loss event has been processed, i.e. after the
+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref input_mouse_button
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter and return value.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun);
+
+/*! @brief Sets the cursor position callback.
+ *
+ * This function sets the cursor position callback of the specified window,
+ * which is called when the cursor is moved. The callback is provided with the
+ * position, in screen coordinates, relative to the upper-left corner of the
+ * client area of the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_pos
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun);
+
+/*! @brief Sets the cursor enter/exit callback.
+ *
+ * This function sets the cursor boundary crossing callback of the specified
+ * window, which is called when the cursor enters or leaves the client area of
+ * the window.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref cursor_enter
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun);
+
+/*! @brief Sets the scroll callback.
+ *
+ * This function sets the scroll callback of the specified window, which is
+ * called when a scrolling device is used, such as a mouse wheel or scrolling
+ * area of a touchpad.
+ *
+ * The scroll callback receives all scrolling input, like that from a mouse
+ * wheel or a touchpad scrolling area.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently
+ * set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref scrolling
+ *
+ * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun);
+
+/*! @brief Sets the file drop callback.
+ *
+ * This function sets the file drop callback of the specified window, which is
+ * called when one or more dragged files are dropped on the window.
+ *
+ * Because the path array and its strings may have been generated specifically
+ * for that event, they are not guaranteed to be valid after the callback has
+ * returned. If you wish to use them after the callback returns, you need to
+ * make a deep copy.
+ *
+ * @param[in] window The window whose callback to set.
+ * @param[in] cbfun The new file drop callback, or `NULL` to remove the
+ * currently set callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref path_drop
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
+
+/*! @brief Returns whether the specified joystick is present.
+ *
+ * This function returns whether the specified joystick is present.
+ *
+ * @param[in] joy The [joystick](@ref joysticks) to query.
+ * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick
+ *
+ * @since Added in version 3.0. Replaces `glfwGetJoystickParam`.
+ *
+ * @ingroup input
+ */
+GLFWAPI int glfwJoystickPresent(int joy);
+
+/*! @brief Returns the values of all axes of the specified joystick.
+ *
+ * This function returns the values of all axes of the specified joystick.
+ * Each element in the array is a value between -1.0 and 1.0.
+ *
+ * Querying a joystick slot with no device present is not an error, but will
+ * cause this function to return `NULL`. Call @ref glfwJoystickPresent to
+ * check device presence.
+ *
+ * @param[in] joy The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of axis values in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of axis values, or `NULL` if the joystick is not present.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, this function is called again for that joystick or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_axis
+ *
+ * @since Added in version 3.0. Replaces `glfwGetJoystickPos`.
+ *
+ * @ingroup input
+ */
+GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);
+
+/*! @brief Returns the state of all buttons of the specified joystick.
+ *
+ * This function returns the state of all buttons of the specified joystick.
+ * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
+ *
+ * Querying a joystick slot with no device present is not an error, but will
+ * cause this function to return `NULL`. Call @ref glfwJoystickPresent to
+ * check device presence.
+ *
+ * @param[in] joy The [joystick](@ref joysticks) to query.
+ * @param[out] count Where to store the number of button states in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of button states, or `NULL` if the joystick is not present.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, this function is called again for that joystick or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_button
+ *
+ * @since Added in version 2.2.
+ * @glfw3 Changed to return a dynamic array.
+ *
+ * @ingroup input
+ */
+GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);
+
+/*! @brief Returns the name of the specified joystick.
+ *
+ * This function returns the name, encoded as UTF-8, of the specified joystick.
+ * The returned string is allocated and freed by GLFW. You should not free it
+ * yourself.
+ *
+ * Querying a joystick slot with no device present is not an error, but will
+ * cause this function to return `NULL`. Call @ref glfwJoystickPresent to
+ * check device presence.
+ *
+ * @param[in] joy The [joystick](@ref joysticks) to query.
+ * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick
+ * is not present.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the specified joystick is
+ * disconnected, this function is called again for that joystick or the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_name
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetJoystickName(int joy);
+
+/*! @brief Sets the joystick configuration callback.
+ *
+ * This function sets the joystick configuration callback, or removes the
+ * currently set callback. This is called when a joystick is connected to or
+ * disconnected from the system.
+ *
+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set
+ * callback.
+ * @return The previously set callback, or `NULL` if no callback was set or the
+ * library had not been [initialized](@ref intro_init).
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref joystick_event
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
+
+/*! @brief Sets the clipboard to the specified string.
+ *
+ * This function sets the system clipboard to the specified, UTF-8 encoded
+ * string.
+ *
+ * @param[in] window The window that will own the clipboard contents.
+ * @param[in] string A UTF-8 encoded string.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The specified string is copied before this function
+ * returns.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa glfwGetClipboardString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
+
+/*! @brief Returns the contents of the clipboard as a string.
+ *
+ * This function returns the contents of the system clipboard, if it contains
+ * or is convertible to a UTF-8 encoded string. If the clipboard is empty or
+ * if its contents cannot be converted, `NULL` is returned and a @ref
+ * GLFW_FORMAT_UNAVAILABLE error is generated.
+ *
+ * @param[in] window The window that will request the clipboard contents.
+ * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`
+ * if an [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You
+ * should not free it yourself. It is valid until the next call to @ref
+ * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
+ * is terminated.
+ *
+ * @thread_safety This function must only be called from the main thread.
+ *
+ * @sa @ref clipboard
+ * @sa glfwSetClipboardString
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
+
+/*! @brief Returns the value of the GLFW timer.
+ *
+ * This function returns the value of the GLFW timer. Unless the timer has
+ * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW
+ * was initialized.
+ *
+ * The resolution of the timer is system dependent, but is usually on the order
+ * of a few micro- or nanoseconds. It uses the highest-resolution monotonic
+ * time source on each supported platform.
+ *
+ * @return The current value, in seconds, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread. Reading of the
+ * internal timer offset is not atomic.
+ *
+ * @sa @ref time
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup input
+ */
+GLFWAPI double glfwGetTime(void);
+
+/*! @brief Sets the GLFW timer.
+ *
+ * This function sets the value of the GLFW timer. It then continues to count
+ * up from that value. The value must be a positive finite number less than
+ * or equal to 18446744073.0, which is approximately 584.5 years.
+ *
+ * @param[in] time The new value, in seconds.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_INVALID_VALUE.
+ *
+ * @remark The upper limit of the timer is calculated as
+ * floor((2<sup>64</sup> - 1) / 10<sup>9</sup>) and is due to implementations
+ * storing nanoseconds in 64 bits. The limit may be increased in the future.
+ *
+ * @thread_safety This function may be called from any thread. Writing of the
+ * internal timer offset is not atomic.
+ *
+ * @sa @ref time
+ *
+ * @since Added in version 2.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI void glfwSetTime(double time);
+
+/*! @brief Returns the current value of the raw timer.
+ *
+ * This function returns the current value of the raw timer, measured in
+ * 1&nbsp;/&nbsp;frequency seconds. To get the frequency, call @ref
+ * glfwGetTimerFrequency.
+ *
+ * @return The value of the timer, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref time
+ * @sa glfwGetTimerFrequency
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI uint64_t glfwGetTimerValue(void);
+
+/*! @brief Returns the frequency, in Hz, of the raw timer.
+ *
+ * This function returns the frequency, in Hz, of the raw timer.
+ *
+ * @return The frequency of the timer, in Hz, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref time
+ * @sa glfwGetTimerValue
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup input
+ */
+GLFWAPI uint64_t glfwGetTimerFrequency(void);
+
+/*! @brief Makes the context of the specified window current for the calling
+ * thread.
+ *
+ * This function makes the OpenGL or OpenGL ES context of the specified window
+ * current on the calling thread. A context can only be made current on
+ * a single thread at a time and each thread can have only a single current
+ * context at a time.
+ *
+ * By default, making a context non-current implicitly forces a pipeline flush.
+ * On machines that support `GL_KHR_context_flush_control`, you can control
+ * whether a context performs this flush by setting the
+ * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint.
+ *
+ * The specified window must have an OpenGL or OpenGL ES context. Specifying
+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
+ * error.
+ *
+ * @param[in] window The window whose context to make current, or `NULL` to
+ * detach the current context.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_current
+ * @sa glfwGetCurrentContext
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);
+
+/*! @brief Returns the window whose context is current on the calling thread.
+ *
+ * This function returns the window whose OpenGL or OpenGL ES context is
+ * current on the calling thread.
+ *
+ * @return The window whose context is current, or `NULL` if no window's
+ * context is current.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_current
+ * @sa glfwMakeContextCurrent
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
+
+/*! @brief Swaps the front and back buffers of the specified window.
+ *
+ * This function swaps the front and back buffers of the specified window when
+ * rendering with OpenGL or OpenGL ES. If the swap interval is greater than
+ * zero, the GPU driver waits the specified number of screen updates before
+ * swapping the buffers.
+ *
+ * The specified window must have an OpenGL or OpenGL ES context. Specifying
+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT
+ * error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see `vkQueuePresentKHR` instead.
+ *
+ * @param[in] window The window whose buffers to swap.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark __EGL:__ The context of the specified window must be current on the
+ * calling thread.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref buffer_swap
+ * @sa glfwSwapInterval
+ *
+ * @since Added in version 1.0.
+ * @glfw3 Added window handle parameter.
+ *
+ * @ingroup window
+ */
+GLFWAPI void glfwSwapBuffers(GLFWwindow* window);
+
+/*! @brief Sets the swap interval for the current context.
+ *
+ * This function sets the swap interval for the current OpenGL or OpenGL ES
+ * context, i.e. the number of screen updates to wait from the time @ref
+ * glfwSwapBuffers was called before swapping the buffers and returning. This
+ * is sometimes called _vertical synchronization_, _vertical retrace
+ * synchronization_ or just _vsync_.
+ *
+ * Contexts that support either of the `WGL_EXT_swap_control_tear` and
+ * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals,
+ * which allow the driver to swap even if a frame arrives a little bit late.
+ * You can check for the presence of these extensions using @ref
+ * glfwExtensionSupported. For more information about swap tearing, see the
+ * extension specifications.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see the present mode of your swapchain instead.
+ *
+ * @param[in] interval The minimum number of screen updates to wait for
+ * until the buffers are swapped by @ref glfwSwapBuffers.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark This function is not called during context creation, leaving the
+ * swap interval set to whatever is the default on that platform. This is done
+ * because some swap interval extensions used by GLFW do not allow the swap
+ * interval to be reset to zero once it has been set to a non-zero value.
+ *
+ * @remark Some GPU drivers do not honor the requested swap interval, either
+ * because of a user setting that overrides the application's request or due to
+ * bugs in the driver.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref buffer_swap
+ * @sa glfwSwapBuffers
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI void glfwSwapInterval(int interval);
+
+/*! @brief Returns whether the specified extension is available.
+ *
+ * This function returns whether the specified
+ * [API extension](@ref context_glext) is supported by the current OpenGL or
+ * OpenGL ES context. It searches both for client API extension and context
+ * creation API extensions.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * As this functions retrieves and searches one or more extension strings each
+ * call, it is recommended that you cache its results if it is going to be used
+ * frequently. The extension strings will not change during the lifetime of
+ * a context, so there is no danger in doing this.
+ *
+ * This function does not apply to Vulkan. If you are using Vulkan, see @ref
+ * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties`
+ * and `vkEnumerateDeviceExtensionProperties` instead.
+ *
+ * @param[in] extension The ASCII encoded name of the extension.
+ * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
+ * otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref
+ * GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_glext
+ * @sa glfwGetProcAddress
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI int glfwExtensionSupported(const char* extension);
+
+/*! @brief Returns the address of the specified function for the current
+ * context.
+ *
+ * This function returns the address of the specified OpenGL or OpenGL ES
+ * [core or extension function](@ref context_glext), if it is supported
+ * by the current context.
+ *
+ * A context must be current on the calling thread. Calling this function
+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.
+ *
+ * This function does not apply to Vulkan. If you are rendering with Vulkan,
+ * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and
+ * `vkGetDeviceProcAddr` instead.
+ *
+ * @param[in] procname The ASCII encoded name of the function.
+ * @return The address of the function, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remark The address of a given function is not guaranteed to be the same
+ * between contexts.
+ *
+ * @remark This function may return a non-`NULL` address despite the
+ * associated version or extension not being available. Always check the
+ * context version or extension string first.
+ *
+ * @pointer_lifetime The returned function pointer is valid until the context
+ * is destroyed or the library is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref context_glext
+ * @sa glfwExtensionSupported
+ *
+ * @since Added in version 1.0.
+ *
+ * @ingroup context
+ */
+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
+
+/*! @brief Returns whether the Vulkan loader has been found.
+ *
+ * This function returns whether the Vulkan loader has been found. This check
+ * is performed by @ref glfwInit.
+ *
+ * The availability of a Vulkan loader does not by itself guarantee that window
+ * surface creation or even device creation is possible. Call @ref
+ * glfwGetRequiredInstanceExtensions to check whether the extensions necessary
+ * for Vulkan surface creation are available and @ref
+ * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of
+ * a physical device supports image presentation.
+ *
+ * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_support
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI int glfwVulkanSupported(void);
+
+/*! @brief Returns the Vulkan instance extensions required by GLFW.
+ *
+ * This function returns an array of names of Vulkan instance extensions required
+ * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the
+ * list will always contains `VK_KHR_surface`, so if you don't require any
+ * additional extensions you can pass this list directly to the
+ * `VkInstanceCreateInfo` struct.
+ *
+ * If Vulkan is not available on the machine, this function returns `NULL` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is available.
+ *
+ * If Vulkan is available but no set of extensions allowing window surface
+ * creation was found, this function returns `NULL`. You may still use Vulkan
+ * for off-screen rendering and compute work.
+ *
+ * @param[out] count Where to store the number of extensions in the returned
+ * array. This is set to zero if an error occurred.
+ * @return An array of ASCII encoded extension names, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_API_UNAVAILABLE.
+ *
+ * @remarks Additional extensions may be required by future versions of GLFW.
+ * You should check if any extensions you wish to enable are already in the
+ * returned array, as it is an error to specify an extension more than once in
+ * the `VkInstanceCreateInfo` struct.
+ *
+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You
+ * should not free it yourself. It is guaranteed to be valid only until the
+ * library is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_ext
+ * @sa glfwCreateWindowSurface
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count);
+
+#if defined(VK_VERSION_1_0)
+
+/*! @brief Returns the address of the specified Vulkan instance function.
+ *
+ * This function returns the address of the specified Vulkan core or extension
+ * function for the specified instance. If instance is set to `NULL` it can
+ * return any function exported from the Vulkan loader, including at least the
+ * following functions:
+ *
+ * - `vkEnumerateInstanceExtensionProperties`
+ * - `vkEnumerateInstanceLayerProperties`
+ * - `vkCreateInstance`
+ * - `vkGetInstanceProcAddr`
+ *
+ * If Vulkan is not available on the machine, this function returns `NULL` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is available.
+ *
+ * This function is equivalent to calling `vkGetInstanceProcAddr` with
+ * a platform-specific query of the Vulkan loader as a fallback.
+ *
+ * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve
+ * functions related to instance creation.
+ * @param[in] procname The ASCII encoded name of the function.
+ * @return The address of the function, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ * GLFW_API_UNAVAILABLE.
+ *
+ * @pointer_lifetime The returned function pointer is valid until the library
+ * is terminated.
+ *
+ * @thread_safety This function may be called from any thread.
+ *
+ * @sa @ref vulkan_proc
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname);
+
+/*! @brief Returns whether the specified queue family can present images.
+ *
+ * This function returns whether the specified queue family of the specified
+ * physical device supports presentation to the platform GLFW was built for.
+ *
+ * If Vulkan or the required window surface creation instance extensions are
+ * not available on the machine, or if the specified instance was not created
+ * with the required extensions, this function returns `GLFW_FALSE` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
+ * to check whether Vulkan is available and @ref
+ * glfwGetRequiredInstanceExtensions to check what instance extensions are
+ * required.
+ *
+ * @param[in] instance The instance that the physical device belongs to.
+ * @param[in] device The physical device that the queue family belongs to.
+ * @param[in] queuefamily The index of the queue family to query.
+ * @return `GLFW_TRUE` if the queue family supports presentation, or
+ * `GLFW_FALSE` otherwise.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @thread_safety This function may be called from any thread. For
+ * synchronization details of Vulkan objects, see the Vulkan specification.
+ *
+ * @sa @ref vulkan_present
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
+
+/*! @brief Creates a Vulkan surface for the specified window.
+ *
+ * This function creates a Vulkan surface for the specified window.
+ *
+ * If the Vulkan loader was not found at initialization, this function returns
+ * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE
+ * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was
+ * found.
+ *
+ * If the required window surface creation instance extensions are not
+ * available or if the specified instance was not created with these extensions
+ * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and
+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref
+ * glfwGetRequiredInstanceExtensions to check what instance extensions are
+ * required.
+ *
+ * The window surface must be destroyed before the specified Vulkan instance.
+ * It is the responsibility of the caller to destroy the window surface. GLFW
+ * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the
+ * surface.
+ *
+ * @param[in] instance The Vulkan instance to create the surface in.
+ * @param[in] window The window to create the surface for.
+ * @param[in] allocator The allocator to use, or `NULL` to use the default
+ * allocator.
+ * @param[out] surface Where to store the handle of the surface. This is set
+ * to `VK_NULL_HANDLE` if an error occurred.
+ * @return `VK_SUCCESS` if successful, or a Vulkan error code if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
+ *
+ * @remarks If an error occurs before the creation call is made, GLFW returns
+ * the Vulkan error code most appropriate for the error. Appropriate use of
+ * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
+ * eliminate almost all occurrences of these errors.
+ *
+ * @thread_safety This function may be called from any thread. For
+ * synchronization details of Vulkan objects, see the Vulkan specification.
+ *
+ * @sa @ref vulkan_surface
+ * @sa glfwGetRequiredInstanceExtensions
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup vulkan
+ */
+GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+
+#endif /*VK_VERSION_1_0*/
+
+
+/*************************************************************************
+ * Global definition cleanup
+ *************************************************************************/
+
+/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
+
+#ifdef GLFW_WINGDIAPI_DEFINED
+ #undef WINGDIAPI
+ #undef GLFW_WINGDIAPI_DEFINED
+#endif
+
+#ifdef GLFW_CALLBACK_DEFINED
+ #undef CALLBACK
+ #undef GLFW_CALLBACK_DEFINED
+#endif
+
+/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_h_ */
+
diff --git a/Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3native.h b/Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3native.h
new file mode 100644
index 0000000..9fa955e
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/glfw/include/GLFW/glfw3native.h
@@ -0,0 +1,456 @@
+/*************************************************************************
+ * GLFW 3.2 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would
+ * be appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ *************************************************************************/
+
+#ifndef _glfw3_native_h_
+#define _glfw3_native_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Doxygen documentation
+ *************************************************************************/
+
+/*! @file glfw3native.h
+ * @brief The header of the native access functions.
+ *
+ * This is the header file of the native access functions. See @ref native for
+ * more information.
+ */
+/*! @defgroup native Native access
+ *
+ * **By using the native access functions you assert that you know what you're
+ * doing and how to fix problems caused by using them. If you don't, you
+ * shouldn't be using them.**
+ *
+ * Before the inclusion of @ref glfw3native.h, you may define exactly one
+ * window system API macro and zero or more context creation API macros.
+ *
+ * The chosen backends must match those the library was compiled for. Failure
+ * to do this will cause a link-time error.
+ *
+ * The available window API macros are:
+ * * `GLFW_EXPOSE_NATIVE_WIN32`
+ * * `GLFW_EXPOSE_NATIVE_COCOA`
+ * * `GLFW_EXPOSE_NATIVE_X11`
+ * * `GLFW_EXPOSE_NATIVE_WAYLAND`
+ * * `GLFW_EXPOSE_NATIVE_MIR`
+ *
+ * The available context API macros are:
+ * * `GLFW_EXPOSE_NATIVE_WGL`
+ * * `GLFW_EXPOSE_NATIVE_NSGL`
+ * * `GLFW_EXPOSE_NATIVE_GLX`
+ * * `GLFW_EXPOSE_NATIVE_EGL`
+ *
+ * These macros select which of the native access functions that are declared
+ * and which platform-specific headers to include. It is then up your (by
+ * definition platform-specific) code to handle which of these should be
+ * defined.
+ */
+
+
+/*************************************************************************
+ * System headers and types
+ *************************************************************************/
+
+#if defined(GLFW_EXPOSE_NATIVE_WIN32)
+ // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
+ // example to allow applications to correctly declare a GL_ARB_debug_output
+ // callback) but windows.h assumes no one will define APIENTRY before it does
+ #undef APIENTRY
+ #include <windows.h>
+#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
+ #include <ApplicationServices/ApplicationServices.h>
+ #if defined(__OBJC__)
+ #import <Cocoa/Cocoa.h>
+ #else
+ typedef void* id;
+ #endif
+#elif defined(GLFW_EXPOSE_NATIVE_X11)
+ #include <X11/Xlib.h>
+ #include <X11/extensions/Xrandr.h>
+#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+ #include <wayland-client.h>
+#elif defined(GLFW_EXPOSE_NATIVE_MIR)
+ #include <mir_toolkit/mir_client_library.h>
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WGL)
+ /* WGL is declared by windows.h */
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_NSGL)
+ /* NSGL is declared by Cocoa.h */
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_GLX)
+ #include <GL/glx.h>
+#endif
+#if defined(GLFW_EXPOSE_NATIVE_EGL)
+ #include <EGL/egl.h>
+#endif
+
+
+/*************************************************************************
+ * Functions
+ *************************************************************************/
+
+#if defined(GLFW_EXPOSE_NATIVE_WIN32)
+/*! @brief Returns the adapter device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
+ * of the specified monitor, or `NULL` if an [error](@ref error_handling)
+ * occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the display device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded display device name (for example
+ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `HWND` of the specified window.
+ *
+ * @return The `HWND` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WGL)
+/*! @brief Returns the `HGLRC` of the specified window.
+ *
+ * @return The `HGLRC` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_COCOA)
+/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
+ *
+ * @return The `CGDirectDisplayID` of the specified monitor, or
+ * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `NSWindow` of the specified window.
+ *
+ * @return The `NSWindow` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_NSGL)
+/*! @brief Returns the `NSOpenGLContext` of the specified window.
+ *
+ * @return The `NSOpenGLContext` of the specified window, or `nil` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_X11)
+/*! @brief Returns the `Display` used by GLFW.
+ *
+ * @return The `Display` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI Display* glfwGetX11Display(void);
+
+/*! @brief Returns the `RRCrtc` of the specified monitor.
+ *
+ * @return The `RRCrtc` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the `RROutput` of the specified monitor.
+ *
+ * @return The `RROutput` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `Window` of the specified window.
+ *
+ * @return The `Window` of the specified window, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_GLX)
+/*! @brief Returns the `GLXContext` of the specified window.
+ *
+ * @return The `GLXContext` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
+
+/*! @brief Returns the `GLXWindow` of the specified window.
+ *
+ * @return The `GLXWindow` of the specified window, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+/*! @brief Returns the `struct wl_display*` used by GLFW.
+ *
+ * @return The `struct wl_display*` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
+
+/*! @brief Returns the `struct wl_output*` of the specified monitor.
+ *
+ * @return The `struct wl_output*` of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the main `struct wl_surface*` of the specified window.
+ *
+ * @return The main `struct wl_surface*` of the specified window, or `NULL` if
+ * an [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_MIR)
+/*! @brief Returns the `MirConnection*` used by GLFW.
+ *
+ * @return The `MirConnection*` used by GLFW, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI MirConnection* glfwGetMirDisplay(void);
+
+/*! @brief Returns the Mir output ID of the specified monitor.
+ *
+ * @return The Mir output ID of the specified monitor, or zero if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
+
+/*! @brief Returns the `MirSurface*` of the specified window.
+ *
+ * @return The `MirSurface*` of the specified window, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.2.
+ *
+ * @ingroup native
+ */
+GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
+#endif
+
+#if defined(GLFW_EXPOSE_NATIVE_EGL)
+/*! @brief Returns the `EGLDisplay` used by GLFW.
+ *
+ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
+
+/*! @brief Returns the `EGLContext` of the specified window.
+ *
+ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
+
+/*! @brief Returns the `EGLSurface` of the specified window.
+ *
+ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @thread_safety This function may be called from any thread. Access is not
+ * synchronized.
+ *
+ * @since Added in version 3.0.
+ *
+ * @ingroup native
+ */
+GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_native_h_ */
+
diff --git a/Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.lib
new file mode 100644
index 0000000..348abec
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-32/glfw3.lib
Binary files differ
diff --git a/Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.lib
new file mode 100644
index 0000000..768f308
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/glfw/lib-vc2010-64/glfw3.lib
Binary files differ
diff --git a/Client/ThirdParty/imgui/examples/libs/usynergy/README.txt b/Client/ThirdParty/imgui/examples/libs/usynergy/README.txt
new file mode 100644
index 0000000..c86b909
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/usynergy/README.txt
@@ -0,0 +1,8 @@
+
+uSynergy client -- Implementation for the embedded Synergy client library
+version 1.0.0, July 7th, 2012
+Copyright (c) 2012 Alex Evans
+
+This is a copy of the files once found at:
+ https://github.com/symless/synergy-core/tree/790d108a56ada9caad8e56ff777d444485a69da9/src/micro
+
diff --git a/Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.c b/Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.c
new file mode 100644
index 0000000..8dce47b
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.c
@@ -0,0 +1,636 @@
+/*
+uSynergy client -- Implementation for the embedded Synergy client library
+ version 1.0.0, July 7th, 2012
+
+Copyright (c) 2012 Alex Evans
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+*/
+#include "uSynergy.h"
+#include <stdio.h>
+#include <string.h>
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Internal helpers
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief Read 16 bit integer in network byte order and convert to native byte order
+**/
+static int16_t sNetToNative16(const unsigned char *value)
+{
+#ifdef USYNERGY_LITTLE_ENDIAN
+ return value[1] | (value[0] << 8);
+#else
+ return value[0] | (value[1] << 8);
+#endif
+}
+
+
+
+/**
+@brief Read 32 bit integer in network byte order and convert to native byte order
+**/
+static int32_t sNetToNative32(const unsigned char *value)
+{
+#ifdef USYNERGY_LITTLE_ENDIAN
+ return value[3] | (value[2] << 8) | (value[1] << 16) | (value[0] << 24);
+#else
+ return value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+#endif
+}
+
+
+
+/**
+@brief Trace text to client
+**/
+static void sTrace(uSynergyContext *context, const char* text)
+{
+ // Don't trace if we don't have a trace function
+ if (context->m_traceFunc != 0L)
+ context->m_traceFunc(context->m_cookie, text);
+}
+
+
+
+/**
+@brief Add string to reply packet
+**/
+static void sAddString(uSynergyContext *context, const char *string)
+{
+ size_t len = strlen(string);
+ memcpy(context->m_replyCur, string, len);
+ context->m_replyCur += len;
+}
+
+
+
+/**
+@brief Add uint8 to reply packet
+**/
+static void sAddUInt8(uSynergyContext *context, uint8_t value)
+{
+ *context->m_replyCur++ = value;
+}
+
+
+
+/**
+@brief Add uint16 to reply packet
+**/
+static void sAddUInt16(uSynergyContext *context, uint16_t value)
+{
+ uint8_t *reply = context->m_replyCur;
+ *reply++ = (uint8_t)(value >> 8);
+ *reply++ = (uint8_t)value;
+ context->m_replyCur = reply;
+}
+
+
+
+/**
+@brief Add uint32 to reply packet
+**/
+static void sAddUInt32(uSynergyContext *context, uint32_t value)
+{
+ uint8_t *reply = context->m_replyCur;
+ *reply++ = (uint8_t)(value >> 24);
+ *reply++ = (uint8_t)(value >> 16);
+ *reply++ = (uint8_t)(value >> 8);
+ *reply++ = (uint8_t)value;
+ context->m_replyCur = reply;
+}
+
+
+
+/**
+@brief Send reply packet
+**/
+static uSynergyBool sSendReply(uSynergyContext *context)
+{
+ // Set header size
+ uint8_t *reply_buf = context->m_replyBuffer;
+ uint32_t reply_len = (uint32_t)(context->m_replyCur - reply_buf); /* Total size of reply */
+ uint32_t body_len = reply_len - 4; /* Size of body */
+ uSynergyBool ret;
+ reply_buf[0] = (uint8_t)(body_len >> 24);
+ reply_buf[1] = (uint8_t)(body_len >> 16);
+ reply_buf[2] = (uint8_t)(body_len >> 8);
+ reply_buf[3] = (uint8_t)body_len;
+
+ // Send reply
+ ret = context->m_sendFunc(context->m_cookie, context->m_replyBuffer, reply_len);
+
+ // Reset reply buffer write pointer
+ context->m_replyCur = context->m_replyBuffer+4;
+ return ret;
+}
+
+
+
+/**
+@brief Call mouse callback after a mouse event
+**/
+static void sSendMouseCallback(uSynergyContext *context)
+{
+ // Skip if no callback is installed
+ if (context->m_mouseCallback == 0L)
+ return;
+
+ // Send callback
+ context->m_mouseCallback(context->m_cookie, context->m_mouseX, context->m_mouseY, context->m_mouseWheelX,
+ context->m_mouseWheelY, context->m_mouseButtonLeft, context->m_mouseButtonRight, context->m_mouseButtonMiddle);
+}
+
+
+
+/**
+@brief Send keyboard callback when a key has been pressed or released
+**/
+static void sSendKeyboardCallback(uSynergyContext *context, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat)
+{
+ // Skip if no callback is installed
+ if (context->m_keyboardCallback == 0L)
+ return;
+
+ // Send callback
+ context->m_keyboardCallback(context->m_cookie, key, modifiers, down, repeat);
+}
+
+
+
+/**
+@brief Send joystick callback
+**/
+static void sSendJoystickCallback(uSynergyContext *context, uint8_t joyNum)
+{
+ int8_t *sticks;
+
+ // Skip if no callback is installed
+ if (context->m_joystickCallback == 0L)
+ return;
+
+ // Send callback
+ sticks = context->m_joystickSticks[joyNum];
+ context->m_joystickCallback(context->m_cookie, joyNum, context->m_joystickButtons[joyNum], sticks[0], sticks[1], sticks[2], sticks[3]);
+}
+
+
+
+/**
+@brief Parse a single client message, update state, send callbacks and send replies
+**/
+#define USYNERGY_IS_PACKET(pkt_id) memcmp(message+4, pkt_id, 4)==0
+static void sProcessMessage(uSynergyContext *context, const uint8_t *message)
+{
+ // We have a packet!
+ if (memcmp(message+4, "Synergy", 7)==0)
+ {
+ // Welcome message
+ // kMsgHello = "Synergy%2i%2i"
+ // kMsgHelloBack = "Synergy%2i%2i%s"
+ sAddString(context, "Synergy");
+ sAddUInt16(context, USYNERGY_PROTOCOL_MAJOR);
+ sAddUInt16(context, USYNERGY_PROTOCOL_MINOR);
+ sAddUInt32(context, (uint32_t)strlen(context->m_clientName));
+ sAddString(context, context->m_clientName);
+ if (!sSendReply(context))
+ {
+ // Send reply failed, let's try to reconnect
+ sTrace(context, "SendReply failed, trying to reconnect in a second");
+ context->m_connected = USYNERGY_FALSE;
+ context->m_sleepFunc(context->m_cookie, 1000);
+ }
+ else
+ {
+ // Let's assume we're connected
+ char buffer[256+1];
+ sprintf(buffer, "Connected as client \"%s\"", context->m_clientName);
+ sTrace(context, buffer);
+ context->m_hasReceivedHello = USYNERGY_TRUE;
+ }
+ return;
+ }
+ else if (USYNERGY_IS_PACKET("QINF"))
+ {
+ // Screen info. Reply with DINF
+ // kMsgQInfo = "QINF"
+ // kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i"
+ uint16_t x = 0, y = 0, warp = 0;
+ sAddString(context, "DINF");
+ sAddUInt16(context, x);
+ sAddUInt16(context, y);
+ sAddUInt16(context, context->m_clientWidth);
+ sAddUInt16(context, context->m_clientHeight);
+ sAddUInt16(context, warp);
+ sAddUInt16(context, 0); // mx?
+ sAddUInt16(context, 0); // my?
+ sSendReply(context);
+ return;
+ }
+ else if (USYNERGY_IS_PACKET("CIAK"))
+ {
+ // Do nothing?
+ // kMsgCInfoAck = "CIAK"
+ return;
+ }
+ else if (USYNERGY_IS_PACKET("CROP"))
+ {
+ // Do nothing?
+ // kMsgCResetOptions = "CROP"
+ return;
+ }
+ else if (USYNERGY_IS_PACKET("CINN"))
+ {
+ // Screen enter. Reply with CNOP
+ // kMsgCEnter = "CINN%2i%2i%4i%2i"
+
+ // Obtain the Synergy sequence number
+ context->m_sequenceNumber = sNetToNative32(message + 12);
+ context->m_isCaptured = USYNERGY_TRUE;
+
+ // Call callback
+ if (context->m_screenActiveCallback != 0L)
+ context->m_screenActiveCallback(context->m_cookie, USYNERGY_TRUE);
+ }
+ else if (USYNERGY_IS_PACKET("COUT"))
+ {
+ // Screen leave
+ // kMsgCLeave = "COUT"
+ context->m_isCaptured = USYNERGY_FALSE;
+
+ // Call callback
+ if (context->m_screenActiveCallback != 0L)
+ context->m_screenActiveCallback(context->m_cookie, USYNERGY_FALSE);
+ }
+ else if (USYNERGY_IS_PACKET("DMDN"))
+ {
+ // Mouse down
+ // kMsgDMouseDown = "DMDN%1i"
+ char btn = message[8]-1;
+ if (btn==2)
+ context->m_mouseButtonRight = USYNERGY_TRUE;
+ else if (btn==1)
+ context->m_mouseButtonMiddle = USYNERGY_TRUE;
+ else
+ context->m_mouseButtonLeft = USYNERGY_TRUE;
+ sSendMouseCallback(context);
+ }
+ else if (USYNERGY_IS_PACKET("DMUP"))
+ {
+ // Mouse up
+ // kMsgDMouseUp = "DMUP%1i"
+ char btn = message[8]-1;
+ if (btn==2)
+ context->m_mouseButtonRight = USYNERGY_FALSE;
+ else if (btn==1)
+ context->m_mouseButtonMiddle = USYNERGY_FALSE;
+ else
+ context->m_mouseButtonLeft = USYNERGY_FALSE;
+ sSendMouseCallback(context);
+ }
+ else if (USYNERGY_IS_PACKET("DMMV"))
+ {
+ // Mouse move. Reply with CNOP
+ // kMsgDMouseMove = "DMMV%2i%2i"
+ context->m_mouseX = sNetToNative16(message+8);
+ context->m_mouseY = sNetToNative16(message+10);
+ sSendMouseCallback(context);
+ }
+ else if (USYNERGY_IS_PACKET("DMWM"))
+ {
+ // Mouse wheel
+ // kMsgDMouseWheel = "DMWM%2i%2i"
+ // kMsgDMouseWheel1_0 = "DMWM%2i"
+ context->m_mouseWheelX += sNetToNative16(message+8);
+ context->m_mouseWheelY += sNetToNative16(message+10);
+ sSendMouseCallback(context);
+ }
+ else if (USYNERGY_IS_PACKET("DKDN"))
+ {
+ // Key down
+ // kMsgDKeyDown = "DKDN%2i%2i%2i"
+ // kMsgDKeyDown1_0 = "DKDN%2i%2i"
+ //uint16_t id = sNetToNative16(message+8);
+ uint16_t mod = sNetToNative16(message+10);
+ uint16_t key = sNetToNative16(message+12);
+ sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_FALSE);
+ }
+ else if (USYNERGY_IS_PACKET("DKRP"))
+ {
+ // Key repeat
+ // kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"
+ // kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"
+ uint16_t mod = sNetToNative16(message+10);
+// uint16_t count = sNetToNative16(message+12);
+ uint16_t key = sNetToNative16(message+14);
+ sSendKeyboardCallback(context, key, mod, USYNERGY_TRUE, USYNERGY_TRUE);
+ }
+ else if (USYNERGY_IS_PACKET("DKUP"))
+ {
+ // Key up
+ // kMsgDKeyUp = "DKUP%2i%2i%2i"
+ // kMsgDKeyUp1_0 = "DKUP%2i%2i"
+ //uint16 id=Endian::sNetToNative(sbuf[4]);
+ uint16_t mod = sNetToNative16(message+10);
+ uint16_t key = sNetToNative16(message+12);
+ sSendKeyboardCallback(context, key, mod, USYNERGY_FALSE, USYNERGY_FALSE);
+ }
+ else if (USYNERGY_IS_PACKET("DGBT"))
+ {
+ // Joystick buttons
+ // kMsgDGameButtons = "DGBT%1i%2i";
+ uint8_t joy_num = message[8];
+ if (joy_num<USYNERGY_NUM_JOYSTICKS)
+ {
+ // Copy button state, then send callback
+ context->m_joystickButtons[joy_num] = (message[9] << 8) | message[10];
+ sSendJoystickCallback(context, joy_num);
+ }
+ }
+ else if (USYNERGY_IS_PACKET("DGST"))
+ {
+ // Joystick sticks
+ // kMsgDGameSticks = "DGST%1i%1i%1i%1i%1i";
+ uint8_t joy_num = message[8];
+ if (joy_num<USYNERGY_NUM_JOYSTICKS)
+ {
+ // Copy stick state, then send callback
+ memcpy(context->m_joystickSticks[joy_num], message+9, 4);
+ sSendJoystickCallback(context, joy_num);
+ }
+ }
+ else if (USYNERGY_IS_PACKET("DSOP"))
+ {
+ // Set options
+ // kMsgDSetOptions = "DSOP%4I"
+ }
+ else if (USYNERGY_IS_PACKET("CALV"))
+ {
+ // Keepalive, reply with CALV and then CNOP
+ // kMsgCKeepAlive = "CALV"
+ sAddString(context, "CALV");
+ sSendReply(context);
+ // now reply with CNOP
+ }
+ else if (USYNERGY_IS_PACKET("DCLP"))
+ {
+ // Clipboard message
+ // kMsgDClipboard = "DCLP%1i%4i%s"
+ //
+ // The clipboard message contains:
+ // 1 uint32: The size of the message
+ // 4 chars: The identifier ("DCLP")
+ // 1 uint8: The clipboard index
+ // 1 uint32: The sequence number. It's zero, because this message is always coming from the server?
+ // 1 uint32: The total size of the remaining 'string' (as per the Synergy %s string format (which is 1 uint32 for size followed by a char buffer (not necessarily null terminated)).
+ // 1 uint32: The number of formats present in the message
+ // And then 'number of formats' times the following:
+ // 1 uint32: The format of the clipboard data
+ // 1 uint32: The size n of the clipboard data
+ // n uint8: The clipboard data
+ const uint8_t * parse_msg = message+17;
+ uint32_t num_formats = sNetToNative32(parse_msg);
+ parse_msg += 4;
+ for (; num_formats; num_formats--)
+ {
+ // Parse clipboard format header
+ uint32_t format = sNetToNative32(parse_msg);
+ uint32_t size = sNetToNative32(parse_msg+4);
+ parse_msg += 8;
+
+ // Call callback
+ if (context->m_clipboardCallback)
+ context->m_clipboardCallback(context->m_cookie, format, parse_msg, size);
+
+ parse_msg += size;
+ }
+ }
+ else
+ {
+ // Unknown packet, could be any of these
+ // kMsgCNoop = "CNOP"
+ // kMsgCClose = "CBYE"
+ // kMsgCClipboard = "CCLP%1i%4i"
+ // kMsgCScreenSaver = "CSEC%1i"
+ // kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"
+ // kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"
+ // kMsgDMouseRelMove = "DMRM%2i%2i"
+ // kMsgEIncompatible = "EICV%2i%2i"
+ // kMsgEBusy = "EBSY"
+ // kMsgEUnknown = "EUNK"
+ // kMsgEBad = "EBAD"
+ char buffer[64];
+ sprintf(buffer, "Unknown packet '%c%c%c%c'", message[4], message[5], message[6], message[7]);
+ sTrace(context, buffer);
+ return;
+ }
+
+ // Reply with CNOP maybe?
+ sAddString(context, "CNOP");
+ sSendReply(context);
+}
+#undef USYNERGY_IS_PACKET
+
+
+
+/**
+@brief Mark context as being disconnected
+**/
+static void sSetDisconnected(uSynergyContext *context)
+{
+ context->m_connected = USYNERGY_FALSE;
+ context->m_hasReceivedHello = USYNERGY_FALSE;
+ context->m_isCaptured = USYNERGY_FALSE;
+ context->m_replyCur = context->m_replyBuffer + 4;
+ context->m_sequenceNumber = 0;
+}
+
+
+
+/**
+@brief Update a connected context
+**/
+static void sUpdateContext(uSynergyContext *context)
+{
+ /* Receive data (blocking) */
+ int receive_size = USYNERGY_RECEIVE_BUFFER_SIZE - context->m_receiveOfs;
+ int num_received = 0;
+ int packlen = 0;
+ if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer + context->m_receiveOfs, receive_size, &num_received) == USYNERGY_FALSE)
+ {
+ /* Receive failed, let's try to reconnect */
+ char buffer[128];
+ sprintf(buffer, "Receive failed (%d bytes asked, %d bytes received), trying to reconnect in a second", receive_size, num_received);
+ sTrace(context, buffer);
+ sSetDisconnected(context);
+ context->m_sleepFunc(context->m_cookie, 1000);
+ return;
+ }
+ context->m_receiveOfs += num_received;
+
+ /* If we didn't receive any data then we're probably still polling to get connected and
+ therefore not getting any data back. To avoid overloading the system with a Synergy
+ thread that would hammer on polling, we let it rest for a bit if there's no data. */
+ if (num_received == 0)
+ context->m_sleepFunc(context->m_cookie, 500);
+
+ /* Check for timeouts */
+ if (context->m_hasReceivedHello)
+ {
+ uint32_t cur_time = context->m_getTimeFunc();
+ if (num_received == 0)
+ {
+ /* Timeout after 2 secs of inactivity (we received no CALV) */
+ if ((cur_time - context->m_lastMessageTime) > USYNERGY_IDLE_TIMEOUT)
+ sSetDisconnected(context);
+ }
+ else
+ context->m_lastMessageTime = cur_time;
+ }
+
+ /* Eat packets */
+ for (;;)
+ {
+ /* Grab packet length and bail out if the packet goes beyond the end of the buffer */
+ packlen = sNetToNative32(context->m_receiveBuffer);
+ if (packlen+4 > context->m_receiveOfs)
+ break;
+
+ /* Process message */
+ sProcessMessage(context, context->m_receiveBuffer);
+
+ /* Move packet to front of buffer */
+ memmove(context->m_receiveBuffer, context->m_receiveBuffer+packlen+4, context->m_receiveOfs-packlen-4);
+ context->m_receiveOfs -= packlen+4;
+ }
+
+ /* Throw away over-sized packets */
+ if (packlen > USYNERGY_RECEIVE_BUFFER_SIZE)
+ {
+ /* Oversized packet, ditch tail end */
+ char buffer[128];
+ sprintf(buffer, "Oversized packet: '%c%c%c%c' (length %d)", context->m_receiveBuffer[4], context->m_receiveBuffer[5], context->m_receiveBuffer[6], context->m_receiveBuffer[7], packlen);
+ sTrace(context, buffer);
+ num_received = context->m_receiveOfs-4; // 4 bytes for the size field
+ while (num_received != packlen)
+ {
+ int buffer_left = packlen - num_received;
+ int to_receive = buffer_left < USYNERGY_RECEIVE_BUFFER_SIZE ? buffer_left : USYNERGY_RECEIVE_BUFFER_SIZE;
+ int ditch_received = 0;
+ if (context->m_receiveFunc(context->m_cookie, context->m_receiveBuffer, to_receive, &ditch_received) == USYNERGY_FALSE)
+ {
+ /* Receive failed, let's try to reconnect */
+ sTrace(context, "Receive failed, trying to reconnect in a second");
+ sSetDisconnected(context);
+ context->m_sleepFunc(context->m_cookie, 1000);
+ break;
+ }
+ else
+ {
+ num_received += ditch_received;
+ }
+ }
+ context->m_receiveOfs = 0;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Public interface
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief Initialize uSynergy context
+**/
+void uSynergyInit(uSynergyContext *context)
+{
+ /* Zero memory */
+ memset(context, 0, sizeof(uSynergyContext));
+
+ /* Initialize to default state */
+ sSetDisconnected(context);
+}
+
+
+/**
+@brief Update uSynergy
+**/
+void uSynergyUpdate(uSynergyContext *context)
+{
+ if (context->m_connected)
+ {
+ /* Update context, receive data, call callbacks */
+ sUpdateContext(context);
+ }
+ else
+ {
+ /* Try to connect */
+ if (context->m_connectFunc(context->m_cookie))
+ context->m_connected = USYNERGY_TRUE;
+ }
+}
+
+
+
+/**
+@brief Send clipboard data
+**/
+void uSynergySendClipboard(uSynergyContext *context, const char *text)
+{
+ // Calculate maximum size that will fit in a reply packet
+ uint32_t overhead_size = 4 + /* Message size */
+ 4 + /* Message ID */
+ 1 + /* Clipboard index */
+ 4 + /* Sequence number */
+ 4 + /* Rest of message size (because it's a Synergy string from here on) */
+ 4 + /* Number of clipboard formats */
+ 4 + /* Clipboard format */
+ 4; /* Clipboard data length */
+ uint32_t max_length = USYNERGY_REPLY_BUFFER_SIZE - overhead_size;
+
+ // Clip text to max length
+ uint32_t text_length = (uint32_t)strlen(text);
+ if (text_length > max_length)
+ {
+ char buffer[128];
+ sprintf(buffer, "Clipboard buffer too small, clipboard truncated at %d characters", max_length);
+ sTrace(context, buffer);
+ text_length = max_length;
+ }
+
+ // Assemble packet
+ sAddString(context, "DCLP");
+ sAddUInt8(context, 0); /* Clipboard index */
+ sAddUInt32(context, context->m_sequenceNumber);
+ sAddUInt32(context, 4+4+4+text_length); /* Rest of message size: numFormats, format, length, data */
+ sAddUInt32(context, 1); /* Number of formats (only text for now) */
+ sAddUInt32(context, USYNERGY_CLIPBOARD_FORMAT_TEXT);
+ sAddUInt32(context, text_length);
+ sAddString(context, text);
+ sSendReply(context);
+}
diff --git a/Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.h b/Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.h
new file mode 100644
index 0000000..cedc387
--- /dev/null
+++ b/Client/ThirdParty/imgui/examples/libs/usynergy/uSynergy.h
@@ -0,0 +1,420 @@
+/*
+uSynergy client -- Interface for the embedded Synergy client library
+ version 1.0.0, July 7th, 2012
+
+Copyright (C) 2012 Synergy Si Ltd.
+Copyright (c) 2012 Alex Evans
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+*/
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Configuration
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief Determine endianness
+**/
+#if defined(USYNERGY_LITTLE_ENDIAN) && defined(USYNERGY_BIG_ENDIAN)
+ /* Ambiguous: both endians specified */
+ #error "Can't define both USYNERGY_LITTLE_ENDIAN and USYNERGY_BIG_ENDIAN"
+#elif !defined(USYNERGY_LITTLE_ENDIAN) && !defined(USYNERGY_BIG_ENDIAN)
+ /* Attempt to auto detect */
+ #if defined(__LITTLE_ENDIAN__) || defined(LITTLE_ENDIAN) || (_BYTE_ORDER == _LITTLE_ENDIAN)
+ #define USYNERGY_LITTLE_ENDIAN
+ #elif defined(__BIG_ENDIAN__) || defined(BIG_ENDIAN) || (_BYTE_ORDER == _BIG_ENDIAN)
+ #define USYNERGY_BIG_ENDIAN
+ #else
+ #error "Can't detect endian-nes, please defined either USYNERGY_LITTLE_ENDIAN or USYNERGY_BIG_ENDIAN";
+ #endif
+#else
+ /* User-specified endian-nes, nothing to do for us */
+#endif
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Types and Constants
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief Boolean type
+**/
+typedef int uSynergyBool;
+#define USYNERGY_FALSE 0 /* False value */
+#define USYNERGY_TRUE 1 /* True value */
+
+
+/**
+@brief User context type
+
+The uSynergyCookie type is an opaque type that is used by uSynergy to communicate to the client. It is passed along to
+callback functions as context.
+**/
+typedef struct { int ignored; } * uSynergyCookie;
+
+
+
+/**
+@brief Clipboard types
+**/
+enum uSynergyClipboardFormat
+{
+ USYNERGY_CLIPBOARD_FORMAT_TEXT = 0, /* Text format, UTF-8, newline is LF */
+ USYNERGY_CLIPBOARD_FORMAT_BITMAP = 1, /* Bitmap format, BMP 24/32bpp, BI_RGB */
+ USYNERGY_CLIPBOARD_FORMAT_HTML = 2, /* HTML format, HTML fragment, UTF-8, newline is LF */
+};
+
+
+
+/**
+@brief Constants and limits
+**/
+#define USYNERGY_NUM_JOYSTICKS 4 /* Maximum number of supported joysticks */
+
+#define USYNERGY_PROTOCOL_MAJOR 1 /* Major protocol version */
+#define USYNERGY_PROTOCOL_MINOR 4 /* Minor protocol version */
+
+#define USYNERGY_IDLE_TIMEOUT 2000 /* Timeout in milliseconds before reconnecting */
+
+#define USYNERGY_TRACE_BUFFER_SIZE 1024 /* Maximum length of traced message */
+#define USYNERGY_REPLY_BUFFER_SIZE 1024 /* Maximum size of a reply packet */
+#define USYNERGY_RECEIVE_BUFFER_SIZE 4096 /* Maximum size of an incoming packet */
+
+
+
+/**
+@brief Keyboard constants
+**/
+#define USYNERGY_MODIFIER_SHIFT 0x0001 /* Shift key modifier */
+#define USYNERGY_MODIFIER_CTRL 0x0002 /* Ctrl key modifier */
+#define USYNERGY_MODIFIER_ALT 0x0004 /* Alt key modifier */
+#define USYNERGY_MODIFIER_META 0x0008 /* Meta key modifier */
+#define USYNERGY_MODIFIER_WIN 0x0010 /* Windows key modifier */
+#define USYNERGY_MODIFIER_ALT_GR 0x0020 /* AltGr key modifier */
+#define USYNERGY_MODIFIER_LEVEL5LOCK 0x0040 /* Level5Lock key modifier */
+#define USYNERGY_MODIFIER_CAPSLOCK 0x1000 /* CapsLock key modifier */
+#define USYNERGY_MODIFIER_NUMLOCK 0x2000 /* NumLock key modifier */
+#define USYNERGY_MODIFIER_SCROLLOCK 0x4000 /* ScrollLock key modifier */
+
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Functions and Callbacks
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief Connect function
+
+This function is called when uSynergy needs to connect to the host. It doesn't imply a network implementation or
+destination address, that must all be handled on the user side. The function should return USYNERGY_TRUE if a
+connection was established or USYNERGY_FALSE if it could not connect.
+
+When network errors occur (e.g. uSynergySend or uSynergyReceive fail) then the connect call will be called again
+so the implementation of the function must close any old connections and clean up resources before retrying.
+
+@param cookie Cookie supplied in the Synergy context
+**/
+typedef uSynergyBool (*uSynergyConnectFunc)(uSynergyCookie cookie);
+
+
+
+/**
+@brief Send function
+
+This function is called when uSynergy needs to send something over the default connection. It should return
+USYNERGY_TRUE if sending succeeded and USYNERGY_FALSE otherwise. This function should block until the send
+operation is completed.
+
+@param cookie Cookie supplied in the Synergy context
+@param buffer Address of buffer to send
+@param length Length of buffer to send
+**/
+typedef uSynergyBool (*uSynergySendFunc)(uSynergyCookie cookie, const uint8_t *buffer, int length);
+
+
+
+/**
+@brief Receive function
+
+This function is called when uSynergy needs to receive data from the default connection. It should return
+USYNERGY_TRUE if receiving data succeeded and USYNERGY_FALSE otherwise. This function should block until data
+has been received and wait for data to become available. If @a outLength is set to 0 upon completion it is
+assumed that the connection is alive, but still in a connecting state and needs time to settle.
+
+@param cookie Cookie supplied in the Synergy context
+@param buffer Address of buffer to receive data into
+@param maxLength Maximum amount of bytes to write into the receive buffer
+@param outLength Address of integer that receives the actual amount of bytes written into @a buffer
+**/
+typedef uSynergyBool (*uSynergyReceiveFunc)(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength);
+
+
+
+/**
+@brief Thread sleep function
+
+This function is called when uSynergy wants to suspend operation for a while before retrying an operation. It
+is mostly used when a socket times out or disconnect occurs to prevent uSynergy from continuously hammering a
+network connection in case the network is down.
+
+@param cookie Cookie supplied in the Synergy context
+@param timeMs Time to sleep the current thread (in milliseconds)
+**/
+typedef void (*uSynergySleepFunc)(uSynergyCookie cookie, int timeMs);
+
+
+
+/**
+@brief Get time function
+
+This function is called when uSynergy needs to know the current time. This is used to determine when timeouts
+have occured. The time base should be a cyclic millisecond time value.
+
+@returns Time value in milliseconds
+**/
+typedef uint32_t (*uSynergyGetTimeFunc)();
+
+
+
+/**
+@brief Trace function
+
+This function is called when uSynergy wants to trace something. It is optional to show these messages, but they
+are often useful when debugging. uSynergy only traces major events like connecting and disconnecting. Usually
+only a single trace is shown when the connection is established and no more trace are called.
+
+@param cookie Cookie supplied in the Synergy context
+@param text Text to be traced
+**/
+typedef void (*uSynergyTraceFunc)(uSynergyCookie cookie, const char *text);
+
+
+
+/**
+@brief Screen active callback
+
+This callback is called when Synergy makes the screen active or inactive. This
+callback is usually sent when the mouse enters or leaves the screen.
+
+@param cookie Cookie supplied in the Synergy context
+@param active Activation flag, 1 if the screen has become active, 0 if the screen has become inactive
+**/
+typedef void (*uSynergyScreenActiveCallback)(uSynergyCookie cookie, uSynergyBool active);
+
+
+
+/**
+@brief Mouse callback
+
+This callback is called when a mouse events happens. The mouse X and Y position,
+wheel and button state is communicated in the message. It's up to the user to
+interpret if this is a mouse up, down, double-click or other message.
+
+@param cookie Cookie supplied in the Synergy context
+@param x Mouse X position
+@param y Mouse Y position
+@param wheelX Mouse wheel X position
+@param wheelY Mouse wheel Y position
+@param buttonLeft Left button pressed status, 0 for released, 1 for pressed
+@param buttonMiddle Middle button pressed status, 0 for released, 1 for pressed
+@param buttonRight Right button pressed status, 0 for released, 1 for pressed
+**/
+typedef void (*uSynergyMouseCallback)(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle);
+
+
+
+/**
+@brief Key event callback
+
+This callback is called when a key is pressed or released.
+
+@param cookie Cookie supplied in the Synergy context
+@param key Key code of key that was pressed or released
+@param modifiers Status of modifier keys (alt, shift, etc.)
+@param down Down or up status, 1 is key is pressed down, 0 if key is released (up)
+@param repeat Repeat flag, 1 if the key is down because the key is repeating, 0 if the key is initially pressed by the user
+**/
+typedef void (*uSynergyKeyboardCallback)(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat);
+
+
+
+/**
+@brief Joystick event callback
+
+This callback is called when a joystick stick or button changes. It is possible that multiple callbacks are
+fired when different sticks or buttons change as these are individual messages in the packet stream. Each
+callback will contain all the valid state for the different axes and buttons. The last callback received will
+represent the most current joystick state.
+
+@param cookie Cookie supplied in the Synergy context
+@param joyNum Joystick number, always in the range [0 ... USYNERGY_NUM_JOYSTICKS>
+@param buttons Button pressed mask
+@param leftStickX Left stick X position, in range [-127 ... 127]
+@param leftStickY Left stick Y position, in range [-127 ... 127]
+@param rightStickX Right stick X position, in range [-127 ... 127]
+@param rightStickY Right stick Y position, in range [-127 ... 127]
+**/
+typedef void (*uSynergyJoystickCallback)(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY);
+
+
+
+/**
+@brief Clipboard event callback
+
+This callback is called when something is placed on the clipboard. Multiple callbacks may be fired for
+multiple clipboard formats if they are supported. The data provided is read-only and may not be modified
+by the application.
+
+@param cookie Cookie supplied in the Synergy context
+@param format Clipboard format
+@param data Memory area containing the clipboard raw data
+@param size Size of clipboard data
+**/
+typedef void (*uSynergyClipboardCallback)(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size);
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Context
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief uSynergy context
+**/
+typedef struct
+{
+ /* Mandatory configuration data, filled in by client */
+ uSynergyConnectFunc m_connectFunc; /* Connect function */
+ uSynergySendFunc m_sendFunc; /* Send data function */
+ uSynergyReceiveFunc m_receiveFunc; /* Receive data function */
+ uSynergySleepFunc m_sleepFunc; /* Thread sleep function */
+ uSynergyGetTimeFunc m_getTimeFunc; /* Get current time function */
+ const char* m_clientName; /* Name of Synergy Screen / Client */
+ uint16_t m_clientWidth; /* Width of screen */
+ uint16_t m_clientHeight; /* Height of screen */
+
+ /* Optional configuration data, filled in by client */
+ uSynergyCookie m_cookie; /* Cookie pointer passed to callback functions (can be NULL) */
+ uSynergyTraceFunc m_traceFunc; /* Function for tracing status (can be NULL) */
+ uSynergyScreenActiveCallback m_screenActiveCallback; /* Callback for entering and leaving screen */
+ uSynergyMouseCallback m_mouseCallback; /* Callback for mouse events */
+ uSynergyKeyboardCallback m_keyboardCallback; /* Callback for keyboard events */
+ uSynergyJoystickCallback m_joystickCallback; /* Callback for joystick events */
+ uSynergyClipboardCallback m_clipboardCallback; /* Callback for clipboard events */
+
+ /* State data, used internall by client, initialized by uSynergyInit() */
+ uSynergyBool m_connected; /* Is our socket connected? */
+ uSynergyBool m_hasReceivedHello; /* Have we received a 'Hello' from the server? */
+ uSynergyBool m_isCaptured; /* Is Synergy active (i.e. this client is receiving input messages?) */
+ uint32_t m_lastMessageTime; /* Time at which last message was received */
+ uint32_t m_sequenceNumber; /* Packet sequence number */
+ uint8_t m_receiveBuffer[USYNERGY_RECEIVE_BUFFER_SIZE]; /* Receive buffer */
+ int m_receiveOfs; /* Receive buffer offset */
+ uint8_t m_replyBuffer[USYNERGY_REPLY_BUFFER_SIZE]; /* Reply buffer */
+ uint8_t* m_replyCur; /* Write offset into reply buffer */
+ uint16_t m_mouseX; /* Mouse X position */
+ uint16_t m_mouseY; /* Mouse Y position */
+ int16_t m_mouseWheelX; /* Mouse wheel X position */
+ int16_t m_mouseWheelY; /* Mouse wheel Y position */
+ uSynergyBool m_mouseButtonLeft; /* Mouse left button */
+ uSynergyBool m_mouseButtonRight; /* Mouse right button */
+ uSynergyBool m_mouseButtonMiddle; /* Mouse middle button */
+ int8_t m_joystickSticks[USYNERGY_NUM_JOYSTICKS][4]; /* Joystick stick position in 2 axes for 2 sticks */
+ uint16_t m_joystickButtons[USYNERGY_NUM_JOYSTICKS]; /* Joystick button state */
+} uSynergyContext;
+
+
+
+//---------------------------------------------------------------------------------------------------------------------
+// Interface
+//---------------------------------------------------------------------------------------------------------------------
+
+
+
+/**
+@brief Initialize uSynergy context
+
+This function initializes @a context for use. Call this function directly after
+creating the context, before filling in any configuration data in it. Not calling
+this function will cause undefined behavior.
+
+@param context Context to be initialized
+**/
+extern void uSynergyInit(uSynergyContext *context);
+
+
+
+/**
+@brief Update uSynergy
+
+This function updates uSynergy and does the bulk of the work. It does connection management,
+receiving data, reconnecting after errors or timeouts and so on. It assumes that networking
+operations are blocking and it can suspend the current thread if it needs to wait. It is
+best practice to call uSynergyUpdate from a background thread so it is responsive.
+
+Because uSynergy relies mostly on blocking calls it will mostly stay in thread sleep state
+waiting for system mutexes and won't eat much memory.
+
+uSynergyUpdate doesn't do any memory allocations or have any side effects beyond those of
+the callbacks it calls.
+
+@param context Context to be updated
+**/
+extern void uSynergyUpdate(uSynergyContext *context);
+
+
+
+/**
+@brief Send clipboard data
+
+This function sets new clipboard data and sends it to the server. Use this function if
+your client cuts or copies data onto the clipboard that it needs to share with the
+server.
+
+Currently there is only support for plaintext, but HTML and image data could be
+supported with some effort.
+
+@param context Context to send clipboard data to
+@param text Text to set to the clipboard
+**/
+extern void uSynergySendClipboard(uSynergyContext *context, const char *text);
+
+
+
+#ifdef __cplusplus
+};
+#endif
diff --git a/Client/ThirdParty/imgui/imconfig.h b/Client/ThirdParty/imgui/imconfig.h
new file mode 100644
index 0000000..7082c55
--- /dev/null
+++ b/Client/ThirdParty/imgui/imconfig.h
@@ -0,0 +1,123 @@
+//-----------------------------------------------------------------------------
+// COMPILE-TIME OPTIONS FOR DEAR IMGUI
+// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
+// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
+//-----------------------------------------------------------------------------
+// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
+// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
+//-----------------------------------------------------------------------------
+// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
+// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
+// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
+// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+//---- Define assertion handler. Defaults to calling assert().
+// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
+//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
+//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
+
+//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
+// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
+// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
+// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
+//#define IMGUI_API __declspec( dllexport )
+//#define IMGUI_API __declspec( dllimport )
+
+//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
+//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+//---- Disable all of Dear ImGui or don't implement standard windows.
+// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
+//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
+//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
+//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger and other debug tools: ShowMetricsWindow() and ShowStackToolWindow() will be empty.
+
+//---- Don't implement some functions to reduce linkage requirements.
+//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
+//#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW)
+//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
+//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
+//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
+//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
+//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
+//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
+//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
+//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
+//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
+
+//---- Include imgui_user.h at the end of imgui.h as a convenience
+//#define IMGUI_INCLUDE_IMGUI_USER_H
+
+//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
+//#define IMGUI_USE_BGRA_PACKED_COLOR
+
+//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
+//#define IMGUI_USE_WCHAR32
+
+//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
+// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
+//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
+//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
+//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
+//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
+
+//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
+// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
+// #define IMGUI_USE_STB_SPRINTF
+
+//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
+// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
+// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
+//#define IMGUI_ENABLE_FREETYPE
+
+//---- Use stb_truetype to build and rasterize the font atlas (default)
+// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
+//#define IMGUI_ENABLE_STB_TRUETYPE
+
+//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
+// This will be inlined as part of ImVec2 and ImVec4 class declarations.
+/*
+#define IM_VEC2_CLASS_EXTRA \
+ ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
+ operator MyVec2() const { return MyVec2(x,y); }
+
+#define IM_VEC4_CLASS_EXTRA \
+ ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
+ operator MyVec4() const { return MyVec4(x,y,z,w); }
+*/
+
+//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
+// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
+// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
+// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
+//#define ImDrawIdx unsigned int
+
+//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
+//struct ImDrawList;
+//struct ImDrawCmd;
+//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
+//#define ImDrawCallback MyImDrawCallback
+
+//---- Debug Tools: Macro to break in Debugger
+// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
+//#define IM_DEBUG_BREAK IM_ASSERT(0)
+//#define IM_DEBUG_BREAK __debugbreak()
+
+//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
+// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
+// This adds a small runtime cost which is why it is not enabled by default.
+//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
+
+//---- Debug Tools: Enable slower asserts
+//#define IMGUI_DEBUG_PARANOID
+
+//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
+/*
+namespace ImGui
+{
+ void MyFunction(const char* name, const MyMatrix44& v);
+}
+*/
diff --git a/Client/ThirdParty/imgui/imgui.cpp b/Client/ThirdParty/imgui/imgui.cpp
new file mode 100644
index 0000000..8b6613e
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui.cpp
@@ -0,0 +1,12388 @@
+// dear imgui, v1.86 WIP
+// (main code and documentation)
+
+// Help:
+// - Read FAQ at http://dearimgui.org/faq
+// - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase.
+// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
+// Read imgui.cpp for details, links and comments.
+
+// Resources:
+// - FAQ http://dearimgui.org/faq
+// - Homepage & latest https://github.com/ocornut/imgui
+// - Releases & changelog https://github.com/ocornut/imgui/releases
+// - Gallery https://github.com/ocornut/imgui/issues/4451 (please post your screenshots/video there!)
+// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
+// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
+// - Issues & support https://github.com/ocornut/imgui/issues
+
+// Getting Started?
+// - For first-time users having issues compiling/linking/running or issues loading fonts:
+// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
+
+// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
+// See LICENSE.txt for copyright and licensing details (standard MIT License).
+// This library is free but needs your support to sustain development and maintenance.
+// Businesses: you can support continued development via invoiced technical support, maintenance and sponsoring contracts. Please reach out to "contact AT dearimgui.com".
+// Individuals: you can support continued development via donations. See docs/README or web page.
+
+// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library.
+// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without
+// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't
+// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you
+// to a better solution or official support for them.
+
+/*
+
+Index of this file:
+
+DOCUMENTATION
+
+- MISSION STATEMENT
+- END-USER GUIDE
+- PROGRAMMER GUIDE
+ - READ FIRST
+ - HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI
+ - GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
+ - HOW A SIMPLE APPLICATION MAY LOOK LIKE
+ - HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE
+ - USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
+- API BREAKING CHANGES (read me when you update!)
+- FREQUENTLY ASKED QUESTIONS (FAQ)
+ - Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer)
+
+CODE
+(search for "[SECTION]" in the code to find them)
+
+// [SECTION] INCLUDES
+// [SECTION] FORWARD DECLARATIONS
+// [SECTION] CONTEXT AND MEMORY ALLOCATORS
+// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
+// [SECTION] MISC HELPERS/UTILITIES (Geometry functions)
+// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions)
+// [SECTION] MISC HELPERS/UTILITIES (File functions)
+// [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
+// [SECTION] MISC HELPERS/UTILITIES (Color functions)
+// [SECTION] ImGuiStorage
+// [SECTION] ImGuiTextFilter
+// [SECTION] ImGuiTextBuffer
+// [SECTION] ImGuiListClipper
+// [SECTION] STYLING
+// [SECTION] RENDER HELPERS
+// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
+// [SECTION] ERROR CHECKING
+// [SECTION] LAYOUT
+// [SECTION] SCROLLING
+// [SECTION] TOOLTIPS
+// [SECTION] POPUPS
+// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
+// [SECTION] DRAG AND DROP
+// [SECTION] LOGGING/CAPTURING
+// [SECTION] SETTINGS
+// [SECTION] VIEWPORTS
+// [SECTION] PLATFORM DEPENDENT HELPERS
+// [SECTION] METRICS/DEBUGGER WINDOW
+// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL)
+
+*/
+
+//-----------------------------------------------------------------------------
+// DOCUMENTATION
+//-----------------------------------------------------------------------------
+
+/*
+
+ MISSION STATEMENT
+ =================
+
+ - Easy to use to create code-driven and data-driven tools.
+ - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools.
+ - Easy to hack and improve.
+ - Minimize setup and maintenance.
+ - Minimize state storage on user side.
+ - Portable, minimize dependencies, run on target (consoles, phones, etc.).
+ - Efficient runtime and memory consumption.
+
+ Designed for developers and content-creators, not the typical end-user! Some of the current weaknesses includes:
+
+ - Doesn't look fancy, doesn't animate.
+ - Limited layout features, intricate layouts are typically crafted in code.
+
+
+ END-USER GUIDE
+ ==============
+
+ - Double-click on title bar to collapse window.
+ - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
+ - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
+ - Click and drag on any empty space to move window.
+ - TAB/SHIFT+TAB to cycle through keyboard editable fields.
+ - CTRL+Click on a slider or drag box to input value as text.
+ - Use mouse wheel to scroll.
+ - Text editor:
+ - Hold SHIFT or use mouse to select text.
+ - CTRL+Left/Right to word jump.
+ - CTRL+Shift+Left/Right to select words.
+ - CTRL+A our Double-Click to select all.
+ - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/
+ - CTRL+Z,CTRL+Y to undo/redo.
+ - ESCAPE to revert text to its original value.
+ - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
+ - Controls are automatically adjusted for OSX to match standard OSX text editing operations.
+ - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard.
+ - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearimgui.org/controls_sheets
+
+
+ PROGRAMMER GUIDE
+ ================
+
+ READ FIRST
+ ----------
+ - Remember to check the wonderful Wiki (https://github.com/ocornut/imgui/wiki)
+ - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction or
+ destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, fewer bugs.
+ - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
+ - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
+ - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
+ You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in Wiki.
+ - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances.
+ For every application frame, your UI code will be called only once. This is in contrast to e.g. Unity's implementation of an IMGUI,
+ where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches.
+ - Our origin is on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right.
+ - This codebase is also optimized to yield decent performances with typical "Debug" builds settings.
+ - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected).
+ If you get an assert, read the messages and comments around the assert.
+ - C++: this is a very C-ish codebase: we don't rely on C++11, we don't include any C++ headers, and ImGui:: is a namespace.
+ - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types.
+ See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that.
+ However, imgui_internal.h can optionally export math operators for ImVec2/ImVec4, which we use in this codebase.
+ - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (avoid using it in your code!).
+
+
+ HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI
+ ----------------------------------------------
+ - Overwrite all the sources files except for imconfig.h (if you have modified your copy of imconfig.h)
+ - Or maintain your own branch where you have imconfig.h modified as a top-most commit which you can regularly rebase over "master".
+ - You can also use '#define IMGUI_USER_CONFIG "my_config_file.h" to redirect configuration to your own file.
+ - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes.
+ If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed
+ from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will
+ likely be a comment about it. Please report any issue to the GitHub page!
+ - To find out usage of old API, you can add '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in your configuration file.
+ - Try to keep your copy of Dear ImGui reasonably up to date.
+
+
+ GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
+ ---------------------------------------------------------------
+ - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library.
+ - In the majority of cases you should be able to use unmodified backends files available in the backends/ folder.
+ - Add the Dear ImGui source files + selected backend source files to your projects or using your preferred build system.
+ It is recommended you build and statically link the .cpp files as part of your project and NOT as a shared library (DLL).
+ - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating Dear ImGui types with your own maths types.
+ - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them.
+ - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide.
+ Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render"
+ phases of your own application. All rendering information is stored into command-lists that you will retrieve after calling ImGui::Render().
+ - Refer to the backends and demo applications in the examples/ folder for instruction on how to setup your code.
+ - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder.
+
+
+ HOW A SIMPLE APPLICATION MAY LOOK LIKE
+ --------------------------------------
+ EXHIBIT 1: USING THE EXAMPLE BACKENDS (= imgui_impl_XXX.cpp files from the backends/ folder).
+ The sub-folders in examples/ contain examples applications following this structure.
+
+ // Application init: create a dear imgui context, setup some options, load fonts
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+ // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
+ // TODO: Fill optional fields of the io structure later.
+ // TODO: Load TTF/OTF fonts if you don't want to use the default font.
+
+ // Initialize helper Platform and Renderer backends (here we are using imgui_impl_win32.cpp and imgui_impl_dx11.cpp)
+ ImGui_ImplWin32_Init(hwnd);
+ ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);
+
+ // Application main loop
+ while (true)
+ {
+ // Feed inputs to dear imgui, start new frame
+ ImGui_ImplDX11_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ // Any application code here
+ ImGui::Text("Hello, world!");
+
+ // Render dear imgui into screen
+ ImGui::Render();
+ ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+ g_pSwapChain->Present(1, 0);
+ }
+
+ // Shutdown
+ ImGui_ImplDX11_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ EXHIBIT 2: IMPLEMENTING CUSTOM BACKEND / CUSTOM ENGINE
+
+ // Application init: create a dear imgui context, setup some options, load fonts
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO();
+ // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls.
+ // TODO: Fill optional fields of the io structure later.
+ // TODO: Load TTF/OTF fonts if you don't want to use the default font.
+
+ // Build and load the texture atlas into a texture
+ // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer)
+ int width, height;
+ unsigned char* pixels = NULL;
+ io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
+
+ // At this point you've got the texture data and you need to upload that to your graphic system:
+ // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'.
+ // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ for details about ImTextureID.
+ MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32)
+ io.Fonts->SetTexID((void*)texture);
+
+ // Application main loop
+ while (true)
+ {
+ // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc.
+ // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform Backends)
+ io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds)
+ io.DisplaySize.x = 1920.0f; // set the current display width
+ io.DisplaySize.y = 1280.0f; // set the current display height here
+ io.MousePos = my_mouse_pos; // set the mouse position
+ io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states
+ io.MouseDown[1] = my_mouse_buttons[1];
+
+ // Call NewFrame(), after this point you can use ImGui::* functions anytime
+ // (So you want to try calling NewFrame() as early as you can in your main loop to be able to use Dear ImGui everywhere)
+ ImGui::NewFrame();
+
+ // Most of your application code here
+ ImGui::Text("Hello, world!");
+ MyGameUpdate(); // may use any Dear ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
+ MyGameRender(); // may use any Dear ImGui functions as well!
+
+ // Render dear imgui, swap buffers
+ // (You want to try calling EndFrame/Render as late as you can, to be able to use Dear ImGui in your own game rendering code)
+ ImGui::EndFrame();
+ ImGui::Render();
+ ImDrawData* draw_data = ImGui::GetDrawData();
+ MyImGuiRenderFunction(draw_data);
+ SwapBuffers();
+ }
+
+ // Shutdown
+ ImGui::DestroyContext();
+
+ To decide whether to dispatch mouse/keyboard inputs to Dear ImGui to the rest of your application,
+ you should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags!
+ Please read the FAQ and example applications for details about this!
+
+
+ HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE
+ ---------------------------------------------
+ The backends in impl_impl_XXX.cpp files contain many working implementations of a rendering function.
+
+ void void MyImGuiRenderFunction(ImDrawData* draw_data)
+ {
+ // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
+ // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
+ // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize
+ // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
+ for (int n = 0; n < draw_data->CmdListsCount; n++)
+ {
+ const ImDrawList* cmd_list = draw_data->CmdLists[n];
+ const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by Dear ImGui
+ const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by Dear ImGui
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
+ if (pcmd->UserCallback)
+ {
+ pcmd->UserCallback(cmd_list, pcmd);
+ }
+ else
+ {
+ // The texture for the draw call is specified by pcmd->GetTexID().
+ // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization.
+ MyEngineBindTexture((MyTexture*)pcmd->GetTexID());
+
+ // We are using scissoring to clip some objects. All low-level graphics API should support it.
+ // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches
+ // (some elements visible outside their bounds) but you can fix that once everything else works!
+ // - Clipping coordinates are provided in imgui coordinates space:
+ // - For a given viewport, draw_data->DisplayPos == viewport->Pos and draw_data->DisplaySize == viewport->Size
+ // - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainViewport()->Pos/Size instead of hardcoding those values.
+ // - In the interest of supporting multi-viewport applications (see 'docking' branch on github),
+ // always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
+ // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
+ ImVec2 pos = draw_data->DisplayPos;
+ MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y));
+
+ // Render 'pcmd->ElemCount/3' indexed triangles.
+ // By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices.
+ MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
+ }
+ idx_buffer += pcmd->ElemCount;
+ }
+ }
+ }
+
+
+ USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
+ ------------------------------------------
+ - The gamepad/keyboard navigation is fairly functional and keeps being improved.
+ - Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PS4, Switch, XB1) without a mouse!
+ - You can ask questions and report issues at https://github.com/ocornut/imgui/issues/787
+ - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
+ - Keyboard:
+ - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
+ NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
+ - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag
+ will be set. For more advanced uses, you may want to read from:
+ - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
+ - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used).
+ - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions.
+ Please reach out if you think the game vs navigation input sharing could be improved.
+ - Gamepad:
+ - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable.
+ - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame().
+ Note that io.NavInputs[] is cleared by EndFrame().
+ - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values:
+ 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks.
+ - We use a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone.
+ Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.).
+ - You can download PNG/PSD files depicting the gamepad controls for common controllers at: http://dearimgui.org/controls_sheets
+ - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo
+ to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved.
+ - Mouse:
+ - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback.
+ - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard.
+ - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag.
+ Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements.
+ When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved.
+ When that happens your backend NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the backends in examples/ do that.
+ (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse moving back and forth!)
+ (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want
+ to set a boolean to ignore your other external mouse positions until the external source is moved again.)
+
+
+ API BREAKING CHANGES
+ ====================
+
+ Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix.
+ Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code.
+ When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
+ You can read releases logs https://github.com/ocornut/imgui/releases for more details.
+
+ - 2021/11/04 (1.86) - removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges. Please open an issue if you think you really need this function.
+ - 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful.
+ - 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019):
+ - ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList()
+ - ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder
+ - 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID().
+ - if you are using official backends from the source tree: you have nothing to do.
+ - if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID().
+ - 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags.
+ - ImDrawCornerFlags_TopLeft -> use ImDrawFlags_RoundCornersTopLeft
+ - ImDrawCornerFlags_BotRight -> use ImDrawFlags_RoundCornersBottomRight
+ - ImDrawCornerFlags_None -> use ImDrawFlags_RoundCornersNone etc.
+ flags now sanely defaults to 0 instead of 0x0F, consistent with all other flags in the API.
+ breaking: the default with rounding > 0.0f is now "round all corners" vs old implicit "round no corners":
+ - rounding == 0.0f + flags == 0 --> meant no rounding --> unchanged (common use)
+ - rounding > 0.0f + flags != 0 --> meant rounding --> unchanged (common use)
+ - rounding == 0.0f + flags != 0 --> meant no rounding --> unchanged (unlikely use)
+ - rounding > 0.0f + flags == 0 --> meant no rounding --> BREAKING (unlikely use): will now round all corners --> use ImDrawFlags_RoundCornersNone or rounding == 0.0f.
+ this ONLY matters for hard coded use of 0 + rounding > 0.0f. Use of named ImDrawFlags_RoundCornersNone (new) or ImDrawCornerFlags_None (old) are ok.
+ the old ImDrawCornersFlags used awkward default values of ~0 or 0xF (4 lower bits set) to signify "round all corners" and we sometimes encouraged using them as shortcuts.
+ legacy path still support use of hard coded ~0 or any value from 0x1 or 0xF. They will behave the same with legacy paths enabled (will assert otherwise).
+ - 2021/03/11 (1.82) - removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018):
+ - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY()
+ - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing.
+ - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future.
+ - 2021/02/22 (1.82) - (*undone in 1.84*) win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'.
+ - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed.
+ - 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete).
+ - removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete).
+ - renamed ListBoxFooter() to EndListBox(). Kept inline redirection function (will obsolete).
+ - 2021/01/26 (1.81) - removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function. Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too. The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags.
+ - renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags.
+ - renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API.
+ - 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.63 (August 2018):
+ - ImGui::IsItemDeactivatedAfterChange() -> use ImGui::IsItemDeactivatedAfterEdit().
+ - ImGuiCol_ModalWindowDarkening -> use ImGuiCol_ModalWindowDimBg
+ - ImGuiInputTextCallback -> use ImGuiTextEditCallback
+ - ImGuiInputTextCallbackData -> use ImGuiTextEditCallbackData
+ - 2020/12/21 (1.80) - renamed ImDrawList::AddBezierCurve() to AddBezierCubic(), and PathBezierCurveTo() to PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete).
+ - 2020/12/04 (1.80) - added imgui_tables.cpp file! Manually constructed project files will need the new file added!
+ - 2020/11/18 (1.80) - renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* in prevision of incoming Tables API.
+ - 2020/11/03 (1.80) - renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature will apply to other data structures
+ - 2020/10/14 (1.80) - backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/.
+ - 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.60 (April 2018):
+ - io.RenderDrawListsFn pointer -> use ImGui::GetDrawData() value and call the render function of your backend
+ - ImGui::IsAnyWindowFocused() -> use ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)
+ - ImGui::IsAnyWindowHovered() -> use ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)
+ - ImGuiStyleVar_Count_ -> use ImGuiStyleVar_COUNT
+ - ImGuiMouseCursor_Count_ -> use ImGuiMouseCursor_COUNT
+ - removed redirecting functions names that were marked obsolete in 1.61 (May 2018):
+ - InputFloat (... int decimal_precision ...) -> use InputFloat (... const char* format ...) with format = "%.Xf" where X is your value for decimal_precision.
+ - same for InputFloat2()/InputFloat3()/InputFloat4() variants taking a `int decimal_precision` parameter.
+ - 2020/10/05 (1.79) - removed ImGuiListClipper: Renamed constructor parameters which created an ambiguous alternative to using the ImGuiListClipper::Begin() function, with misleading edge cases (note: imgui_memory_editor <0.40 from imgui_club/ used this old clipper API. Update your copy if needed).
+ - 2020/09/25 (1.79) - renamed ImGuiSliderFlags_ClampOnInput to ImGuiSliderFlags_AlwaysClamp. Kept redirection enum (will obsolete sooner because previous name was added recently).
+ - 2020/09/25 (1.79) - renamed style.TabMinWidthForUnselectedCloseButton to style.TabMinWidthForCloseButton.
+ - 2020/09/21 (1.79) - renamed OpenPopupContextItem() back to OpenPopupOnItemClick(), reverting the change from 1.77. For varieties of reason this is more self-explanatory.
+ - 2020/09/21 (1.79) - removed return value from OpenPopupOnItemClick() - returned true on mouse release on an item - because it is inconsistent with other popup APIs and makes others misleading. It's also and unnecessary: you can use IsWindowAppearing() after BeginPopup() for a similar result.
+ - 2020/09/17 (1.79) - removed ImFont::DisplayOffset in favor of ImFontConfig::GlyphOffset. DisplayOffset was applied after scaling and not very meaningful/useful outside of being needed by the default ProggyClean font. If you scaled this value after calling AddFontDefault(), this is now done automatically. It was also getting in the way of better font scaling, so let's get rid of it now!
+ - 2020/08/17 (1.78) - obsoleted use of the trailing 'float power=1.0f' parameter for DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(), DragFloatRange2(), DragScalar(), DragScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(), SliderScalar(), SliderScalarN(), VSliderFloat() and VSliderScalar().
+ replaced the 'float power=1.0f' argument with integer-based flags defaulting to 0 (as with all our flags).
+ worked out a backward-compatibility scheme so hopefully most C++ codebase should not be affected. in short, when calling those functions:
+ - if you omitted the 'power' parameter (likely!), you are not affected.
+ - if you set the 'power' parameter to 1.0f (same as previous default value): 1/ your compiler may warn on float>int conversion, 2/ everything else will work. 3/ you can replace the 1.0f value with 0 to fix the warning, and be technically correct.
+ - if you set the 'power' parameter to >1.0f (to enable non-linear editing): 1/ your compiler may warn on float>int conversion, 2/ code will assert at runtime, 3/ in case asserts are disabled, the code will not crash and enable the _Logarithmic flag. 4/ you can replace the >1.0f value with ImGuiSliderFlags_Logarithmic to fix the warning/assert and get a _similar_ effect as previous uses of power >1.0f.
+ see https://github.com/ocornut/imgui/issues/3361 for all details.
+ kept inline redirection functions (will obsolete) apart for: DragFloatRange2(), VSliderFloat(), VSliderScalar(). For those three the 'float power=1.0f' version was removed directly as they were most unlikely ever used.
+ for shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
+ - obsoleted use of v_min > v_max in DragInt, DragFloat, DragScalar to lock edits (introduced in 1.73, was not demoed nor documented very), will be replaced by a more generic ReadOnly feature. You may use the ImGuiSliderFlags_ReadOnly internal flag in the meantime.
+ - 2020/06/23 (1.77) - removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems.
+ - 2020/06/15 (1.77) - renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete). [NOTE: THIS WAS REVERTED IN 1.79]
+ - 2020/06/15 (1.77) - removed CalcItemRectClosestPoint() entry point which was made obsolete and asserting in December 2017.
+ - 2020/04/23 (1.77) - removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular().
+ - 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more.
+ - 2019/12/17 (1.75) - [undid this change in 1.76] made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead.
+ - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value.
+ - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017):
+ - ShowTestWindow() -> use ShowDemoWindow()
+ - IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow)
+ - IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)
+ - SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f)
+ - GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing()
+ - ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg
+ - ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding
+ - ImGuiTreeNodeFlags_AllowOverlapMode -> use ImGuiTreeNodeFlags_AllowItemOverlap
+ - IMGUI_DISABLE_TEST_WINDOWS -> use IMGUI_DISABLE_DEMO_WINDOWS
+ - 2019/12/08 (1.75) - obsoleted calling ImDrawList::PrimReserve() with a negative count (which was vaguely documented and rarely if ever used). Instead, we added an explicit PrimUnreserve() API.
+ - 2019/12/06 (1.75) - removed implicit default parameter to IsMouseDragging(int button = 0) to be consistent with other mouse functions (none of the other functions have it).
+ - 2019/11/21 (1.74) - ImFontAtlas::AddCustomRectRegular() now requires an ID larger than 0x110000 (instead of 0x10000) to conform with supporting Unicode planes 1-16 in a future update. ID below 0x110000 will now assert.
+ - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS to IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS for consistency.
+ - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_MATH_FUNCTIONS to IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS for consistency.
+ - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017):
+ - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed
+ - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows)
+ - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding()
+ - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f)
+ - ImFont::Glyph -> use ImFontGlyph
+ - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function.
+ if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix.
+ The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay).
+ If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you.
+ - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete).
+ - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete).
+ - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names, or see how they were implemented until 1.71.
+ - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have
+ overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering.
+ This optimization is disabled if the parent window has no visual output, because it appears to be the most common situation leading to the creation of overlapping child windows.
+ Please reach out if you are affected.
+ - 2019/05/13 (1.71) - renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
+ - 2019/05/11 (1.71) - changed io.AddInputCharacter(unsigned short c) signature to io.AddInputCharacter(unsigned int c).
+ - 2019/04/29 (1.70) - improved ImDrawList thick strokes (>1.0f) preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, they will appear thicker now.
+ - 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete).
+ - 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete).
+ - 2019/02/26 (1.69) - renamed ImGuiColorEditFlags_RGB/ImGuiColorEditFlags_HSV/ImGuiColorEditFlags_HEX to ImGuiColorEditFlags_DisplayRGB/ImGuiColorEditFlags_DisplayHSV/ImGuiColorEditFlags_DisplayHex. Kept redirection enums (will obsolete).
+ - 2019/02/14 (1.68) - made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). If for some reason your time step calculation gives you a zero value, replace it with an arbitrarily small value!
+ - 2019/02/01 (1.68) - removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already).
+ - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead!
+ - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete).
+ - 2018/12/20 (1.67) - made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable side-effects.
+ - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags.
+ - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files.
+ - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete).
+ - 2018/09/06 (1.65) - renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and stb_rect_pack.h to imstb_rectpack.h.
+ If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths.
+ - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427)
+ - 2018/08/31 (1.64) - added imgui_widgets.cpp file, extracted and moved widgets code out of imgui.cpp into imgui_widgets.cpp. Re-ordered some of the code remaining in imgui.cpp.
+ NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED.
+ Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions.
+ - 2018/08/22 (1.63) - renamed IsItemDeactivatedAfterChange() to IsItemDeactivatedAfterEdit() for consistency with new IsItemEdited() API. Kept redirection function (will obsolete soonish as IsItemDeactivatedAfterChange() is very recent).
+ - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete).
+ - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly).
+ - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges [update 1.67 renamed to ConfigWindowsResizeFromEdges] to enable the feature.
+ - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency.
+ - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time.
+ - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete).
+ - 2018/06/08 (1.62) - examples: the imgui_impl_XXX files have been split to separate platform (Win32, GLFW, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.).
+ old backends will still work as is, however prefer using the separated backends as they will be updated to support multi-viewports.
+ when adopting new backends follow the main.cpp code of your preferred examples/ folder to know which functions to call.
+ in particular, note that old backends called ImGui::NewFrame() at the end of their ImGui_ImplXXXX_NewFrame() function.
+ - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set.
+ - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details.
+ - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more.
+ If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format.
+ To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code.
+ If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them.
+ - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format",
+ consistent with other functions. Kept redirection functions (will obsolete).
+ - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value.
+ - 2018/03/20 (1.60) - renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some backend ahead of merging the Nav branch).
+ - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
+ - 2018/03/08 (1.60) - changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically.
+ - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums.
+ - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment.
+ - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display.
+ - 2018/02/07 (1.60) - reorganized context handling to be more explicit,
+ - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END.
+ - removed Shutdown() function, as DestroyContext() serve this purpose.
+ - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance.
+ - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts.
+ - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts.
+ - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths.
+ - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete).
+ - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete).
+ - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData.
+ - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side.
+ - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete).
+ - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags
+ - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame.
+ - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set.
+ - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete).
+ - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete).
+ - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete).
+ - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete).
+ - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete).
+ - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed.
+ - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up.
+ Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions.
+ - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency.
+ - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg.
+ - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding.
+ - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);
+ - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency.
+ - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it.
+ - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details.
+ removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting.
+ IsItemHoveredRect() --> IsItemHovered(ImGuiHoveredFlags_RectOnly)
+ IsMouseHoveringAnyWindow() --> IsWindowHovered(ImGuiHoveredFlags_AnyWindow)
+ IsMouseHoveringWindow() --> IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) [weird, old behavior]
+ - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
+ - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
+ - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete).
+ - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete).
+ - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your backend if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
+ - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)!
+ - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
+ - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
+ - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
+ - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.
+ - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame type.
+ - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.
+ - 2017/08/13 (1.51) - renamed ImGuiCol_Column to ImGuiCol_Separator, ImGuiCol_ColumnHovered to ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive to ImGuiCol_SeparatorActive. Kept redirection enums (will obsolete).
+ - 2017/08/11 (1.51) - renamed ImGuiSetCond_Always to ImGuiCond_Always, ImGuiSetCond_Once to ImGuiCond_Once, ImGuiSetCond_FirstUseEver to ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing to ImGuiCond_Appearing. Kept redirection enums (will obsolete).
+ - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
+ - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.
+ - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
+ - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0))'
+ - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
+ - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
+ - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
+ - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetID() and use it instead of passing string to BeginChild().
+ - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
+ - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
+ - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully, breakage should be minimal.
+ - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
+ If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you, otherwise if <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
+ This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color:
+ ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); }
+ If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.
+ - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
+ - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
+ - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).
+ - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDrawList::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.
+ - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref GitHub issue #337).
+ - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
+ - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
+ - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
+ - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
+ - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
+ - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
+ - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
+ GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.
+ GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out!
+ - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
+ - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project.
+ - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason
+ - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.
+ you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
+ - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
+ this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
+ - if you are using a vanilla copy of one of the imgui_impl_XXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.
+ - the signature of the io.RenderDrawListsFn handler has changed!
+ old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
+ new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
+ parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount'
+ ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new.
+ ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'.
+ - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.
+ - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
+ - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
+ - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
+ - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
+ - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
+ - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
+ - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely used. Sorry!
+ - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
+ - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
+ - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.
+ - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened.
+ - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
+ - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
+ - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
+ - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
+ - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
+ - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
+ - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
+ - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
+ - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
+ - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
+ - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
+ - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
+ - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
+ - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
+ - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
+ - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
+ - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
+ - 2015/01/11 (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
+ - old: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); [..Upload texture to GPU..];
+ - new: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); [..Upload texture to GPU..]; io.Fonts->SetTexID(YourTexIdentifier);
+ you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. It is now recommended that you sample the font texture with bilinear interpolation.
+ - 2015/01/11 (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to call io.Fonts->SetTexID()
+ - 2015/01/11 (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
+ - 2015/01/11 (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
+ - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
+ - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
+ - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
+ - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
+ - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly)
+ - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
+ - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
+ - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
+ - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
+ - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
+ - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes
+
+
+ FREQUENTLY ASKED QUESTIONS (FAQ)
+ ================================
+
+ Read all answers online:
+ https://www.dearimgui.org/faq or https://github.com/ocornut/imgui/blob/master/docs/FAQ.md (same url)
+ Read all answers locally (with a text editor or ideally a Markdown viewer):
+ docs/FAQ.md
+ Some answers are copied down here to facilitate searching in code.
+
+ Q&A: Basics
+ ===========
+
+ Q: Where is the documentation?
+ A: This library is poorly documented at the moment and expects the user to be acquainted with C/C++.
+ - Run the examples/ and explore them.
+ - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
+ - The demo covers most features of Dear ImGui, so you can read the code and see its output.
+ - See documentation and comments at the top of imgui.cpp + effectively imgui.h.
+ - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the
+ examples/ folder to explain how to integrate Dear ImGui with your own engine/application.
+ - The Wiki (https://github.com/ocornut/imgui/wiki) has many resources and links.
+ - The Glossary (https://github.com/ocornut/imgui/wiki/Glossary) page also may be useful.
+ - Your programming IDE is your friend, find the type or function declaration to find comments
+ associated with it.
+
+ Q: What is this library called?
+ Q: Which version should I get?
+ >> This library is called "Dear ImGui", please don't call it "ImGui" :)
+ >> See https://www.dearimgui.org/faq for details.
+
+ Q&A: Integration
+ ================
+
+ Q: How to get started?
+ A: Read 'PROGRAMMER GUIDE' above. Read examples/README.txt.
+
+ Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?
+ A: You should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags!
+ >> See https://www.dearimgui.org/faq for a fully detailed answer. You really want to read this.
+
+ Q. How can I enable keyboard controls?
+ Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
+ Q: I integrated Dear ImGui in my engine and little squares are showing instead of text...
+ Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...
+ Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...
+ >> See https://www.dearimgui.org/faq
+
+ Q&A: Usage
+ ----------
+
+ Q: About the ID Stack system..
+ - Why is my widget not reacting when I click on it?
+ - How can I have widgets with an empty label?
+ - How can I have multiple widgets with the same label?
+ - How can I have multiple windows with the same label?
+ Q: How can I display an image? What is ImTextureID, how does it works?
+ Q: How can I use my own math types instead of ImVec2/ImVec4?
+ Q: How can I interact with standard C++ types (such as std::string and std::vector)?
+ Q: How can I display custom shapes? (using low-level ImDrawList API)
+ >> See https://www.dearimgui.org/faq
+
+ Q&A: Fonts, Text
+ ================
+
+ Q: How should I handle DPI in my application?
+ Q: How can I load a different font than the default?
+ Q: How can I easily use icons in my application?
+ Q: How can I load multiple fonts?
+ Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
+ >> See https://www.dearimgui.org/faq and https://github.com/ocornut/imgui/edit/master/docs/FONTS.md
+
+ Q&A: Concerns
+ =============
+
+ Q: Who uses Dear ImGui?
+ Q: Can you create elaborate/serious tools with Dear ImGui?
+ Q: Can you reskin the look of Dear ImGui?
+ Q: Why using C++ (as opposed to C)?
+ >> See https://www.dearimgui.org/faq
+
+ Q&A: Community
+ ==============
+
+ Q: How can I help?
+ A: - Businesses: please reach out to "contact AT dearimgui.com" if you work in a place using Dear ImGui!
+ We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts.
+ This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people working on this project.
+ - Individuals: you can support continued development via PayPal donations. See README.
+ - If you are experienced with Dear ImGui and C++, look at the GitHub issues, look at the Wiki, read docs/TODO.txt
+ and see how you want to help and can help!
+ - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc.
+ You may post screenshot or links in the gallery threads. Visuals are ideal as they inspire other programmers.
+ But even without visuals, disclosing your use of dear imgui helps the library grow credibility, and help other teams and programmers with taking decisions.
+ - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on GitHub or privately).
+
+*/
+
+//-------------------------------------------------------------------------
+// [SECTION] INCLUDES
+//-------------------------------------------------------------------------
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DISABLE
+
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+// System includes
+#include <ctype.h> // toupper
+#include <stdio.h> // vsnprintf, sscanf, printf
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled
+#if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
+#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
+#endif
+
+// [Windows] OS specific includes (optional)
+#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
+#define IMGUI_DISABLE_WIN32_FUNCTIONS
+#endif
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#ifndef __MINGW32__
+#include <Windows.h> // _wfopen, OpenClipboard
+#else
+#include <windows.h>
+#endif
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have all Win32 functions
+#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
+#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
+#endif
+#endif
+
+// [Apple] OS specific includes
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
+#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
+#endif
+#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
+#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
+#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
+#endif
+
+// Clang/GCC warnings with -Weverything
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
+#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
+#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
+#pragma clang diagnostic ignored "-Wformat-pedantic" // warning: format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic.
+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type 'int'
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
+#elif defined(__GNUC__)
+// We disable -Wpragmas because GCC doesn't provide an has_warning equivalent and some forks/patches may not following the warning/version association.
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
+#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+
+// Debug options
+#define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL
+#define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window
+#define IMGUI_DEBUG_INI_SETTINGS 0 // Save additional comments in .ini file (particularly helps for Docking, but makes saving slower)
+
+// When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch.
+static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
+static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
+
+// Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend)
+static const float WINDOWS_HOVER_PADDING = 4.0f; // Extend outside window for hovering/resizing (maxxed with TouchPadding) and inside windows for borders. Affect FindHoveredWindow().
+static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
+static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 2.00f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
+
+//-------------------------------------------------------------------------
+// [SECTION] FORWARD DECLARATIONS
+//-------------------------------------------------------------------------
+
+static void SetCurrentWindow(ImGuiWindow* window);
+static void FindHoveredWindow();
+static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags);
+static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window);
+
+static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list);
+static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
+
+// Settings
+static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*);
+static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
+static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
+static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*);
+static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
+
+// Platform Dependents default implementation for IO functions
+static const char* GetClipboardTextFn_DefaultImpl(void* user_data);
+static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
+static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y);
+
+namespace ImGui
+{
+// Navigation
+static void NavUpdate();
+static void NavUpdateWindowing();
+static void NavUpdateWindowingOverlay();
+static void NavUpdateCancelRequest();
+static void NavUpdateCreateMoveRequest();
+static void NavUpdateCreateTabbingRequest();
+static float NavUpdatePageUpPageDown();
+static inline void NavUpdateAnyRequestFlag();
+static void NavUpdateCreateWrappingRequest();
+static void NavEndFrame();
+static bool NavScoreItem(ImGuiNavItemData* result);
+static void NavApplyItemToResult(ImGuiNavItemData* result);
+static void NavProcessItem();
+static void NavProcessItemForTabbingRequest(ImGuiID id);
+static ImVec2 NavCalcPreferredRefPos();
+static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
+static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
+static void NavRestoreLayer(ImGuiNavLayer layer);
+static void NavRestoreHighlightAfterMove();
+static int FindWindowFocusIndex(ImGuiWindow* window);
+
+// Error Checking and Debug Tools
+static void ErrorCheckNewFrameSanityChecks();
+static void ErrorCheckEndFrameSanityChecks();
+static void UpdateDebugToolItemPicker();
+static void UpdateDebugToolStackQueries();
+
+// Misc
+static void UpdateSettings();
+static void UpdateMouseInputs();
+static void UpdateMouseWheel();
+static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect);
+static void RenderWindowOuterBorders(ImGuiWindow* window);
+static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
+static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
+
+// Viewports
+static void UpdateViewportsNewFrame();
+
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] CONTEXT AND MEMORY ALLOCATORS
+//-----------------------------------------------------------------------------
+
+// DLL users:
+// - Heaps and globals are not shared across DLL boundaries!
+// - You will need to call SetCurrentContext() + SetAllocatorFunctions() for each static/DLL boundary you are calling from.
+// - Same applies for hot-reloading mechanisms that are reliant on reloading DLL (note that many hot-reloading mechanisms work without DLL).
+// - Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
+// - Confused? In a debugger: add GImGui to your watch window and notice how its value changes depending on your current location (which DLL boundary you are in).
+
+// Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL.
+// - ImGui::CreateContext() will automatically set this pointer if it is NULL.
+// Change to a different context by calling ImGui::SetCurrentContext().
+// - Important: Dear ImGui functions are not thread-safe because of this pointer.
+// If you want thread-safety to allow N threads to access N different contexts:
+// - Change this variable to use thread local storage so each thread can refer to a different context, in your imconfig.h:
+// struct ImGuiContext;
+// extern thread_local ImGuiContext* MyImGuiTLS;
+// #define GImGui MyImGuiTLS
+// And then define MyImGuiTLS in one of your cpp files. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword.
+// - Future development aims to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
+// - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from a different namespace.
+// - DLL users: read comments above.
+#ifndef GImGui
+ImGuiContext* GImGui = NULL;
+#endif
+
+// Memory Allocator functions. Use SetAllocatorFunctions() to change them.
+// - You probably don't want to modify that mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction.
+// - DLL users: read comments above.
+#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS
+static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); }
+static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); }
+#else
+static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; }
+static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); }
+#endif
+static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper;
+static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper;
+static void* GImAllocatorUserData = NULL;
+
+//-----------------------------------------------------------------------------
+// [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO)
+//-----------------------------------------------------------------------------
+
+ImGuiStyle::ImGuiStyle()
+{
+ Alpha = 1.0f; // Global alpha applies to everything in Dear ImGui.
+ DisabledAlpha = 0.60f; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha.
+ WindowPadding = ImVec2(8,8); // Padding within a window
+ WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
+ WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
+ WindowMinSize = ImVec2(32,32); // Minimum window size
+ WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
+ WindowMenuButtonPosition= ImGuiDir_Left; // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left.
+ ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
+ ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
+ PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
+ PopupBorderSize = 1.0f; // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested.
+ FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
+ FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
+ FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
+ ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
+ ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
+ CellPadding = ImVec2(4,2); // Padding within a table cell
+ TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
+ IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
+ ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
+ ScrollbarSize = 14.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
+ ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
+ GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
+ GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
+ LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
+ TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
+ TabBorderSize = 0.0f; // Thickness of border around tabs.
+ TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appears on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected.
+ ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
+ ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
+ SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
+ DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
+ DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
+ MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
+ AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU.
+ AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering.
+ AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.).
+ CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
+ CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
+
+ // Default theme
+ ImGui::StyleColorsDark(this);
+}
+
+// To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you.
+// Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times.
+void ImGuiStyle::ScaleAllSizes(float scale_factor)
+{
+ WindowPadding = ImFloor(WindowPadding * scale_factor);
+ WindowRounding = ImFloor(WindowRounding * scale_factor);
+ WindowMinSize = ImFloor(WindowMinSize * scale_factor);
+ ChildRounding = ImFloor(ChildRounding * scale_factor);
+ PopupRounding = ImFloor(PopupRounding * scale_factor);
+ FramePadding = ImFloor(FramePadding * scale_factor);
+ FrameRounding = ImFloor(FrameRounding * scale_factor);
+ ItemSpacing = ImFloor(ItemSpacing * scale_factor);
+ ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
+ CellPadding = ImFloor(CellPadding * scale_factor);
+ TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
+ IndentSpacing = ImFloor(IndentSpacing * scale_factor);
+ ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
+ ScrollbarSize = ImFloor(ScrollbarSize * scale_factor);
+ ScrollbarRounding = ImFloor(ScrollbarRounding * scale_factor);
+ GrabMinSize = ImFloor(GrabMinSize * scale_factor);
+ GrabRounding = ImFloor(GrabRounding * scale_factor);
+ LogSliderDeadzone = ImFloor(LogSliderDeadzone * scale_factor);
+ TabRounding = ImFloor(TabRounding * scale_factor);
+ TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImFloor(TabMinWidthForCloseButton * scale_factor) : FLT_MAX;
+ DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor);
+ DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor);
+ MouseCursorScale = ImFloor(MouseCursorScale * scale_factor);
+}
+
+ImGuiIO::ImGuiIO()
+{
+ // Most fields are initialized with zero
+ memset(this, 0, sizeof(*this));
+ IM_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); // Our pre-C++11 IM_STATIC_ASSERT() macros triggers warning on modern compilers so we don't use it here.
+
+ // Settings
+ ConfigFlags = ImGuiConfigFlags_None;
+ BackendFlags = ImGuiBackendFlags_None;
+ DisplaySize = ImVec2(-1.0f, -1.0f);
+ DeltaTime = 1.0f / 60.0f;
+ IniSavingRate = 5.0f;
+ IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same path as executables).
+ LogFilename = "imgui_log.txt";
+ MouseDoubleClickTime = 0.30f;
+ MouseDoubleClickMaxDist = 6.0f;
+ for (int i = 0; i < ImGuiKey_COUNT; i++)
+ KeyMap[i] = -1;
+ KeyRepeatDelay = 0.275f;
+ KeyRepeatRate = 0.050f;
+ UserData = NULL;
+
+ Fonts = NULL;
+ FontGlobalScale = 1.0f;
+ FontDefault = NULL;
+ FontAllowUserScaling = false;
+ DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
+
+ // Miscellaneous options
+ MouseDrawCursor = false;
+#ifdef __APPLE__
+ ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag
+#else
+ ConfigMacOSXBehaviors = false;
+#endif
+ ConfigInputTextCursorBlink = true;
+ ConfigWindowsResizeFromEdges = true;
+ ConfigWindowsMoveFromTitleBarOnly = false;
+ ConfigMemoryCompactTimer = 60.0f;
+
+ // Platform Functions
+ BackendPlatformName = BackendRendererName = NULL;
+ BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
+ GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
+ SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
+ ClipboardUserData = NULL;
+ ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
+ ImeWindowHandle = NULL;
+
+ // Input (NB: we already have memset zero the entire structure!)
+ MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
+ MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX);
+ MouseDragThreshold = 6.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
+ for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f;
+}
+
+// Pass in translated ASCII characters for text input.
+// - with glfw you can get those from the callback set in glfwSetCharCallback()
+// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
+void ImGuiIO::AddInputCharacter(unsigned int c)
+{
+ if (c != 0)
+ InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID);
+}
+
+// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so
+// we should save the high surrogate.
+void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c)
+{
+ if (c == 0 && InputQueueSurrogate == 0)
+ return;
+
+ if ((c & 0xFC00) == 0xD800) // High surrogate, must save
+ {
+ if (InputQueueSurrogate != 0)
+ InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
+ InputQueueSurrogate = c;
+ return;
+ }
+
+ ImWchar cp = c;
+ if (InputQueueSurrogate != 0)
+ {
+ if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate
+ {
+ InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID);
+ }
+ else
+ {
+#if IM_UNICODE_CODEPOINT_MAX == 0xFFFF
+ cp = IM_UNICODE_CODEPOINT_INVALID; // Codepoint will not fit in ImWchar
+#else
+ cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000);
+#endif
+ }
+
+ InputQueueSurrogate = 0;
+ }
+ InputQueueCharacters.push_back(cp);
+}
+
+void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
+{
+ while (*utf8_chars != 0)
+ {
+ unsigned int c = 0;
+ utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL);
+ if (c != 0)
+ InputQueueCharacters.push_back((ImWchar)c);
+ }
+}
+
+void ImGuiIO::ClearInputCharacters()
+{
+ InputQueueCharacters.resize(0);
+}
+
+void ImGuiIO::ClearInputKeys()
+{
+ memset(KeysDown, 0, sizeof(KeysDown));
+ for (int n = 0; n < IM_ARRAYSIZE(KeysDownDuration); n++)
+ KeysDownDuration[n] = KeysDownDurationPrev[n] = -1.0f;
+ KeyCtrl = KeyShift = KeyAlt = KeySuper = false;
+ KeyMods = KeyModsPrev = ImGuiKeyModFlags_None;
+ for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++)
+ NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f;
+}
+
+void ImGuiIO::AddFocusEvent(bool focused)
+{
+ // We intentionally overwrite this and process in NewFrame(), in order to give a chance
+ // to multi-viewports backends to queue AddFocusEvent(false),AddFocusEvent(true) in same frame.
+ AppFocusLost = !focused;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPERS/UTILITIES (Geometry functions)
+//-----------------------------------------------------------------------------
+
+ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments)
+{
+ IM_ASSERT(num_segments > 0); // Use ImBezierCubicClosestPointCasteljau()
+ ImVec2 p_last = p1;
+ ImVec2 p_closest;
+ float p_closest_dist2 = FLT_MAX;
+ float t_step = 1.0f / (float)num_segments;
+ for (int i_step = 1; i_step <= num_segments; i_step++)
+ {
+ ImVec2 p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step);
+ ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
+ float dist2 = ImLengthSqr(p - p_line);
+ if (dist2 < p_closest_dist2)
+ {
+ p_closest = p_line;
+ p_closest_dist2 = dist2;
+ }
+ p_last = p_current;
+ }
+ return p_closest;
+}
+
+// Closely mimics PathBezierToCasteljau() in imgui_draw.cpp
+static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
+{
+ float dx = x4 - x1;
+ float dy = y4 - y1;
+ float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
+ float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
+ d2 = (d2 >= 0) ? d2 : -d2;
+ d3 = (d3 >= 0) ? d3 : -d3;
+ if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
+ {
+ ImVec2 p_current(x4, y4);
+ ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p);
+ float dist2 = ImLengthSqr(p - p_line);
+ if (dist2 < p_closest_dist2)
+ {
+ p_closest = p_line;
+ p_closest_dist2 = dist2;
+ }
+ p_last = p_current;
+ }
+ else if (level < 10)
+ {
+ float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f;
+ float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f;
+ float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f;
+ float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f;
+ float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f;
+ float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f;
+ ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
+ ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
+ }
+}
+
+// tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationTol
+// Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically.
+ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol)
+{
+ IM_ASSERT(tess_tol > 0.0f);
+ ImVec2 p_last = p1;
+ ImVec2 p_closest;
+ float p_closest_dist2 = FLT_MAX;
+ ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, tess_tol, 0);
+ return p_closest;
+}
+
+ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
+{
+ ImVec2 ap = p - a;
+ ImVec2 ab_dir = b - a;
+ float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
+ if (dot < 0.0f)
+ return a;
+ float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y;
+ if (dot > ab_len_sqr)
+ return b;
+ return a + ab_dir * dot / ab_len_sqr;
+}
+
+bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
+{
+ bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
+ bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
+ bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
+ return ((b1 == b2) && (b2 == b3));
+}
+
+void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)
+{
+ ImVec2 v0 = b - a;
+ ImVec2 v1 = c - a;
+ ImVec2 v2 = p - a;
+ const float denom = v0.x * v1.y - v1.x * v0.y;
+ out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
+ out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
+ out_u = 1.0f - out_v - out_w;
+}
+
+ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
+{
+ ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
+ ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
+ ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
+ float dist2_ab = ImLengthSqr(p - proj_ab);
+ float dist2_bc = ImLengthSqr(p - proj_bc);
+ float dist2_ca = ImLengthSqr(p - proj_ca);
+ float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
+ if (m == dist2_ab)
+ return proj_ab;
+ if (m == dist2_bc)
+ return proj_bc;
+ return proj_ca;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions)
+//-----------------------------------------------------------------------------
+
+// Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more.
+int ImStricmp(const char* str1, const char* str2)
+{
+ int d;
+ while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
+ return d;
+}
+
+int ImStrnicmp(const char* str1, const char* str2, size_t count)
+{
+ int d = 0;
+ while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
+ return d;
+}
+
+void ImStrncpy(char* dst, const char* src, size_t count)
+{
+ if (count < 1)
+ return;
+ if (count > 1)
+ strncpy(dst, src, count - 1);
+ dst[count - 1] = 0;
+}
+
+char* ImStrdup(const char* str)
+{
+ size_t len = strlen(str);
+ void* buf = IM_ALLOC(len + 1);
+ return (char*)memcpy(buf, (const void*)str, len + 1);
+}
+
+char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
+{
+ size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1;
+ size_t src_size = strlen(src) + 1;
+ if (dst_buf_size < src_size)
+ {
+ IM_FREE(dst);
+ dst = (char*)IM_ALLOC(src_size);
+ if (p_dst_size)
+ *p_dst_size = src_size;
+ }
+ return (char*)memcpy(dst, (const void*)src, src_size);
+}
+
+const char* ImStrchrRange(const char* str, const char* str_end, char c)
+{
+ const char* p = (const char*)memchr(str, (int)c, str_end - str);
+ return p;
+}
+
+int ImStrlenW(const ImWchar* str)
+{
+ //return (int)wcslen((const wchar_t*)str); // FIXME-OPT: Could use this when wchar_t are 16-bit
+ int n = 0;
+ while (*str++) n++;
+ return n;
+}
+
+// Find end-of-line. Return pointer will point to either first \n, either str_end.
+const char* ImStreolRange(const char* str, const char* str_end)
+{
+ const char* p = (const char*)memchr(str, '\n', str_end - str);
+ return p ? p : str_end;
+}
+
+const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
+{
+ while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
+ buf_mid_line--;
+ return buf_mid_line;
+}
+
+const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
+{
+ if (!needle_end)
+ needle_end = needle + strlen(needle);
+
+ const char un0 = (char)toupper(*needle);
+ while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
+ {
+ if (toupper(*haystack) == un0)
+ {
+ const char* b = needle + 1;
+ for (const char* a = haystack + 1; b < needle_end; a++, b++)
+ if (toupper(*a) != toupper(*b))
+ break;
+ if (b == needle_end)
+ return haystack;
+ }
+ haystack++;
+ }
+ return NULL;
+}
+
+// Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible.
+void ImStrTrimBlanks(char* buf)
+{
+ char* p = buf;
+ while (p[0] == ' ' || p[0] == '\t') // Leading blanks
+ p++;
+ char* p_start = p;
+ while (*p != 0) // Find end of string
+ p++;
+ while (p > p_start && (p[-1] == ' ' || p[-1] == '\t')) // Trailing blanks
+ p--;
+ if (p_start != buf) // Copy memory if we had leading blanks
+ memmove(buf, p_start, p - p_start);
+ buf[p - p_start] = 0; // Zero terminate
+}
+
+const char* ImStrSkipBlank(const char* str)
+{
+ while (str[0] == ' ' || str[0] == '\t')
+ str++;
+ return str;
+}
+
+// A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size).
+// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm.
+// B) When buf==NULL vsnprintf() will return the output size.
+#ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
+
+// We support stb_sprintf which is much faster (see: https://github.com/nothings/stb/blob/master/stb_sprintf.h)
+// You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
+// and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are
+// designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.)
+#ifdef IMGUI_USE_STB_SPRINTF
+#define STB_SPRINTF_IMPLEMENTATION
+#include "stb_sprintf.h"
+#endif
+
+#if defined(_MSC_VER) && !defined(vsnprintf)
+#define vsnprintf _vsnprintf
+#endif
+
+int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+#ifdef IMGUI_USE_STB_SPRINTF
+ int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
+#else
+ int w = vsnprintf(buf, buf_size, fmt, args);
+#endif
+ va_end(args);
+ if (buf == NULL)
+ return w;
+ if (w == -1 || w >= (int)buf_size)
+ w = (int)buf_size - 1;
+ buf[w] = 0;
+ return w;
+}
+
+int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args)
+{
+#ifdef IMGUI_USE_STB_SPRINTF
+ int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
+#else
+ int w = vsnprintf(buf, buf_size, fmt, args);
+#endif
+ if (buf == NULL)
+ return w;
+ if (w == -1 || w >= (int)buf_size)
+ w = (int)buf_size - 1;
+ buf[w] = 0;
+ return w;
+}
+#endif // #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
+
+// CRC32 needs a 1KB lookup table (not cache friendly)
+// Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily:
+// - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe.
+static const ImU32 GCrc32LookupTable[256] =
+{
+ 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,
+ 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,
+ 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
+ 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,
+ 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,
+ 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
+ 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,
+ 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,
+ 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
+ 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,
+ 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,
+ 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
+ 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,
+ 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,
+ 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
+ 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D,
+};
+
+// Known size hash
+// It is ok to call ImHashData on a string with known length but the ### operator won't be supported.
+// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
+ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed)
+{
+ ImU32 crc = ~seed;
+ const unsigned char* data = (const unsigned char*)data_p;
+ const ImU32* crc32_lut = GCrc32LookupTable;
+ while (data_size-- != 0)
+ crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++];
+ return ~crc;
+}
+
+// Zero-terminated string hash, with support for ### to reset back to seed value
+// We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
+// Because this syntax is rarely used we are optimizing for the common case.
+// - If we reach ### in the string we discard the hash so far and reset to the seed.
+// - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build)
+// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
+ImGuiID ImHashStr(const char* data_p, size_t data_size, ImU32 seed)
+{
+ seed = ~seed;
+ ImU32 crc = seed;
+ const unsigned char* data = (const unsigned char*)data_p;
+ const ImU32* crc32_lut = GCrc32LookupTable;
+ if (data_size != 0)
+ {
+ while (data_size-- != 0)
+ {
+ unsigned char c = *data++;
+ if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#')
+ crc = seed;
+ crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
+ }
+ }
+ else
+ {
+ while (unsigned char c = *data++)
+ {
+ if (c == '#' && data[0] == '#' && data[1] == '#')
+ crc = seed;
+ crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
+ }
+ }
+ return ~crc;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPERS/UTILITIES (File functions)
+//-----------------------------------------------------------------------------
+
+// Default file functions
+#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
+
+ImFileHandle ImFileOpen(const char* filename, const char* mode)
+{
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__)
+ // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames.
+ // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32!
+ const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
+ const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
+ ImVector<ImWchar> buf;
+ buf.resize(filename_wsize + mode_wsize);
+ ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, (wchar_t*)&buf[0], filename_wsize);
+ ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, (wchar_t*)&buf[filename_wsize], mode_wsize);
+ return ::_wfopen((const wchar_t*)&buf[0], (const wchar_t*)&buf[filename_wsize]);
+#else
+ return fopen(filename, mode);
+#endif
+}
+
+// We should in theory be using fseeko()/ftello() with off_t and _fseeki64()/_ftelli64() with __int64, waiting for the PR that does that in a very portable pre-C++11 zero-warnings way.
+bool ImFileClose(ImFileHandle f) { return fclose(f) == 0; }
+ImU64 ImFileGetSize(ImFileHandle f) { long off = 0, sz = 0; return ((off = ftell(f)) != -1 && !fseek(f, 0, SEEK_END) && (sz = ftell(f)) != -1 && !fseek(f, off, SEEK_SET)) ? (ImU64)sz : (ImU64)-1; }
+ImU64 ImFileRead(void* data, ImU64 sz, ImU64 count, ImFileHandle f) { return fread(data, (size_t)sz, (size_t)count, f); }
+ImU64 ImFileWrite(const void* data, ImU64 sz, ImU64 count, ImFileHandle f) { return fwrite(data, (size_t)sz, (size_t)count, f); }
+#endif // #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
+
+// Helper: Load file content into memory
+// Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree()
+// This can't really be used with "rt" because fseek size won't match read size.
+void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size, int padding_bytes)
+{
+ IM_ASSERT(filename && mode);
+ if (out_file_size)
+ *out_file_size = 0;
+
+ ImFileHandle f;
+ if ((f = ImFileOpen(filename, mode)) == NULL)
+ return NULL;
+
+ size_t file_size = (size_t)ImFileGetSize(f);
+ if (file_size == (size_t)-1)
+ {
+ ImFileClose(f);
+ return NULL;
+ }
+
+ void* file_data = IM_ALLOC(file_size + padding_bytes);
+ if (file_data == NULL)
+ {
+ ImFileClose(f);
+ return NULL;
+ }
+ if (ImFileRead(file_data, 1, file_size, f) != file_size)
+ {
+ ImFileClose(f);
+ IM_FREE(file_data);
+ return NULL;
+ }
+ if (padding_bytes > 0)
+ memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes);
+
+ ImFileClose(f);
+ if (out_file_size)
+ *out_file_size = file_size;
+
+ return file_data;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPERS/UTILITIES (ImText* functions)
+//-----------------------------------------------------------------------------
+
+// Convert UTF-8 to 32-bit character, process single character input.
+// A nearly-branchless UTF-8 decoder, based on work of Christopher Wellons (https://github.com/skeeto/branchless-utf8).
+// We handle UTF-8 decoding error by skipping forward.
+int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
+{
+ static const char lengths[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 };
+ static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 };
+ static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 };
+ static const int shiftc[] = { 0, 18, 12, 6, 0 };
+ static const int shifte[] = { 0, 6, 4, 2, 0 };
+ int len = lengths[*(const unsigned char*)in_text >> 3];
+ int wanted = len + !len;
+
+ if (in_text_end == NULL)
+ in_text_end = in_text + wanted; // Max length, nulls will be taken into account.
+
+ // Copy at most 'len' bytes, stop copying at 0 or past in_text_end. Branch predictor does a good job here,
+ // so it is fast even with excessive branching.
+ unsigned char s[4];
+ s[0] = in_text + 0 < in_text_end ? in_text[0] : 0;
+ s[1] = in_text + 1 < in_text_end ? in_text[1] : 0;
+ s[2] = in_text + 2 < in_text_end ? in_text[2] : 0;
+ s[3] = in_text + 3 < in_text_end ? in_text[3] : 0;
+
+ // Assume a four-byte character and load four bytes. Unused bits are shifted out.
+ *out_char = (uint32_t)(s[0] & masks[len]) << 18;
+ *out_char |= (uint32_t)(s[1] & 0x3f) << 12;
+ *out_char |= (uint32_t)(s[2] & 0x3f) << 6;
+ *out_char |= (uint32_t)(s[3] & 0x3f) << 0;
+ *out_char >>= shiftc[len];
+
+ // Accumulate the various error conditions.
+ int e = 0;
+ e = (*out_char < mins[len]) << 6; // non-canonical encoding
+ e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half?
+ e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range?
+ e |= (s[1] & 0xc0) >> 2;
+ e |= (s[2] & 0xc0) >> 4;
+ e |= (s[3] ) >> 6;
+ e ^= 0x2a; // top two bits of each tail byte correct?
+ e >>= shifte[len];
+
+ if (e)
+ {
+ // No bytes are consumed when *in_text == 0 || in_text == in_text_end.
+ // One byte is consumed in case of invalid first byte of in_text.
+ // All available bytes (at most `len` bytes) are consumed on incomplete/invalid second to last bytes.
+ // Invalid or incomplete input may consume less bytes than wanted, therefore every byte has to be inspected in s.
+ wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]);
+ *out_char = IM_UNICODE_CODEPOINT_INVALID;
+ }
+
+ return wanted;
+}
+
+int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
+{
+ ImWchar* buf_out = buf;
+ ImWchar* buf_end = buf + buf_size;
+ while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c;
+ in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
+ if (c == 0)
+ break;
+ *buf_out++ = (ImWchar)c;
+ }
+ *buf_out = 0;
+ if (in_text_remaining)
+ *in_text_remaining = in_text;
+ return (int)(buf_out - buf);
+}
+
+int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
+{
+ int char_count = 0;
+ while ((!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c;
+ in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
+ if (c == 0)
+ break;
+ char_count++;
+ }
+ return char_count;
+}
+
+// Based on stb_to_utf8() from github.com/nothings/stb/
+static inline int ImTextCharToUtf8_inline(char* buf, int buf_size, unsigned int c)
+{
+ if (c < 0x80)
+ {
+ buf[0] = (char)c;
+ return 1;
+ }
+ if (c < 0x800)
+ {
+ if (buf_size < 2) return 0;
+ buf[0] = (char)(0xc0 + (c >> 6));
+ buf[1] = (char)(0x80 + (c & 0x3f));
+ return 2;
+ }
+ if (c < 0x10000)
+ {
+ if (buf_size < 3) return 0;
+ buf[0] = (char)(0xe0 + (c >> 12));
+ buf[1] = (char)(0x80 + ((c >> 6) & 0x3f));
+ buf[2] = (char)(0x80 + ((c ) & 0x3f));
+ return 3;
+ }
+ if (c <= 0x10FFFF)
+ {
+ if (buf_size < 4) return 0;
+ buf[0] = (char)(0xf0 + (c >> 18));
+ buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
+ buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
+ buf[3] = (char)(0x80 + ((c ) & 0x3f));
+ return 4;
+ }
+ // Invalid code point, the max unicode is 0x10FFFF
+ return 0;
+}
+
+const char* ImTextCharToUtf8(char out_buf[5], unsigned int c)
+{
+ int count = ImTextCharToUtf8_inline(out_buf, 5, c);
+ out_buf[count] = 0;
+ return out_buf;
+}
+
+// Not optimal but we very rarely use this function.
+int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end)
+{
+ unsigned int unused = 0;
+ return ImTextCharFromUtf8(&unused, in_text, in_text_end);
+}
+
+static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
+{
+ if (c < 0x80) return 1;
+ if (c < 0x800) return 2;
+ if (c < 0x10000) return 3;
+ if (c <= 0x10FFFF) return 4;
+ return 3;
+}
+
+int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
+{
+ char* buf_p = out_buf;
+ const char* buf_end = out_buf + out_buf_size;
+ while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c = (unsigned int)(*in_text++);
+ if (c < 0x80)
+ *buf_p++ = (char)c;
+ else
+ buf_p += ImTextCharToUtf8_inline(buf_p, (int)(buf_end - buf_p - 1), c);
+ }
+ *buf_p = 0;
+ return (int)(buf_p - out_buf);
+}
+
+int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
+{
+ int bytes_count = 0;
+ while ((!in_text_end || in_text < in_text_end) && *in_text)
+ {
+ unsigned int c = (unsigned int)(*in_text++);
+ if (c < 0x80)
+ bytes_count++;
+ else
+ bytes_count += ImTextCountUtf8BytesFromChar(c);
+ }
+ return bytes_count;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MISC HELPERS/UTILITIES (Color functions)
+// Note: The Convert functions are early design which are not consistent with other API.
+//-----------------------------------------------------------------------------
+
+IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b)
+{
+ float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f;
+ int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t);
+ int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t);
+ int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t);
+ return IM_COL32(r, g, b, 0xFF);
+}
+
+ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
+{
+ float s = 1.0f / 255.0f;
+ return ImVec4(
+ ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
+ ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
+ ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
+ ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
+}
+
+ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
+{
+ ImU32 out;
+ out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
+ out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
+ out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
+ out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
+ return out;
+}
+
+// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
+// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
+void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
+{
+ float K = 0.f;
+ if (g < b)
+ {
+ ImSwap(g, b);
+ K = -1.f;
+ }
+ if (r < g)
+ {
+ ImSwap(r, g);
+ K = -2.f / 6.f - K;
+ }
+
+ const float chroma = r - (g < b ? g : b);
+ out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f));
+ out_s = chroma / (r + 1e-20f);
+ out_v = r;
+}
+
+// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
+// also http://en.wikipedia.org/wiki/HSL_and_HSV
+void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
+{
+ if (s == 0.0f)
+ {
+ // gray
+ out_r = out_g = out_b = v;
+ return;
+ }
+
+ h = ImFmod(h, 1.0f) / (60.0f / 360.0f);
+ int i = (int)h;
+ float f = h - (float)i;
+ float p = v * (1.0f - s);
+ float q = v * (1.0f - s * f);
+ float t = v * (1.0f - s * (1.0f - f));
+
+ switch (i)
+ {
+ case 0: out_r = v; out_g = t; out_b = p; break;
+ case 1: out_r = q; out_g = v; out_b = p; break;
+ case 2: out_r = p; out_g = v; out_b = t; break;
+ case 3: out_r = p; out_g = q; out_b = v; break;
+ case 4: out_r = t; out_g = p; out_b = v; break;
+ case 5: default: out_r = v; out_g = p; out_b = q; break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiStorage
+// Helper: Key->value storage
+//-----------------------------------------------------------------------------
+
+// std::lower_bound but without the bullshit
+static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector<ImGuiStorage::ImGuiStoragePair>& data, ImGuiID key)
+{
+ ImGuiStorage::ImGuiStoragePair* first = data.Data;
+ ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size;
+ size_t count = (size_t)(last - first);
+ while (count > 0)
+ {
+ size_t count2 = count >> 1;
+ ImGuiStorage::ImGuiStoragePair* mid = first + count2;
+ if (mid->key < key)
+ {
+ first = ++mid;
+ count -= count2 + 1;
+ }
+ else
+ {
+ count = count2;
+ }
+ }
+ return first;
+}
+
+// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
+void ImGuiStorage::BuildSortByKey()
+{
+ struct StaticFunc
+ {
+ static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs)
+ {
+ // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that.
+ if (((const ImGuiStoragePair*)lhs)->key > ((const ImGuiStoragePair*)rhs)->key) return +1;
+ if (((const ImGuiStoragePair*)lhs)->key < ((const ImGuiStoragePair*)rhs)->key) return -1;
+ return 0;
+ }
+ };
+ if (Data.Size > 1)
+ ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), StaticFunc::PairCompareByID);
+}
+
+int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
+{
+ ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
+ if (it == Data.end() || it->key != key)
+ return default_val;
+ return it->val_i;
+}
+
+bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
+{
+ return GetInt(key, default_val ? 1 : 0) != 0;
+}
+
+float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
+{
+ ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
+ if (it == Data.end() || it->key != key)
+ return default_val;
+ return it->val_f;
+}
+
+void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
+{
+ ImGuiStoragePair* it = LowerBound(const_cast<ImVector<ImGuiStoragePair>&>(Data), key);
+ if (it == Data.end() || it->key != key)
+ return NULL;
+ return it->val_p;
+}
+
+// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
+int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
+{
+ ImGuiStoragePair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ it = Data.insert(it, ImGuiStoragePair(key, default_val));
+ return &it->val_i;
+}
+
+bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
+{
+ return (bool*)GetIntRef(key, default_val ? 1 : 0);
+}
+
+float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
+{
+ ImGuiStoragePair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ it = Data.insert(it, ImGuiStoragePair(key, default_val));
+ return &it->val_f;
+}
+
+void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
+{
+ ImGuiStoragePair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ it = Data.insert(it, ImGuiStoragePair(key, default_val));
+ return &it->val_p;
+}
+
+// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
+void ImGuiStorage::SetInt(ImGuiID key, int val)
+{
+ ImGuiStoragePair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ {
+ Data.insert(it, ImGuiStoragePair(key, val));
+ return;
+ }
+ it->val_i = val;
+}
+
+void ImGuiStorage::SetBool(ImGuiID key, bool val)
+{
+ SetInt(key, val ? 1 : 0);
+}
+
+void ImGuiStorage::SetFloat(ImGuiID key, float val)
+{
+ ImGuiStoragePair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ {
+ Data.insert(it, ImGuiStoragePair(key, val));
+ return;
+ }
+ it->val_f = val;
+}
+
+void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
+{
+ ImGuiStoragePair* it = LowerBound(Data, key);
+ if (it == Data.end() || it->key != key)
+ {
+ Data.insert(it, ImGuiStoragePair(key, val));
+ return;
+ }
+ it->val_p = val;
+}
+
+void ImGuiStorage::SetAllInt(int v)
+{
+ for (int i = 0; i < Data.Size; i++)
+ Data[i].val_i = v;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiTextFilter
+//-----------------------------------------------------------------------------
+
+// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
+ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
+{
+ if (default_filter)
+ {
+ ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
+ Build();
+ }
+ else
+ {
+ InputBuf[0] = 0;
+ CountGrep = 0;
+ }
+}
+
+bool ImGuiTextFilter::Draw(const char* label, float width)
+{
+ if (width != 0.0f)
+ ImGui::SetNextItemWidth(width);
+ bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
+ if (value_changed)
+ Build();
+ return value_changed;
+}
+
+void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRange>* out) const
+{
+ out->resize(0);
+ const char* wb = b;
+ const char* we = wb;
+ while (we < e)
+ {
+ if (*we == separator)
+ {
+ out->push_back(ImGuiTextRange(wb, we));
+ wb = we + 1;
+ }
+ we++;
+ }
+ if (wb != we)
+ out->push_back(ImGuiTextRange(wb, we));
+}
+
+void ImGuiTextFilter::Build()
+{
+ Filters.resize(0);
+ ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf));
+ input_range.split(',', &Filters);
+
+ CountGrep = 0;
+ for (int i = 0; i != Filters.Size; i++)
+ {
+ ImGuiTextRange& f = Filters[i];
+ while (f.b < f.e && ImCharIsBlankA(f.b[0]))
+ f.b++;
+ while (f.e > f.b && ImCharIsBlankA(f.e[-1]))
+ f.e--;
+ if (f.empty())
+ continue;
+ if (Filters[i].b[0] != '-')
+ CountGrep += 1;
+ }
+}
+
+bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
+{
+ if (Filters.empty())
+ return true;
+
+ if (text == NULL)
+ text = "";
+
+ for (int i = 0; i != Filters.Size; i++)
+ {
+ const ImGuiTextRange& f = Filters[i];
+ if (f.empty())
+ continue;
+ if (f.b[0] == '-')
+ {
+ // Subtract
+ if (ImStristr(text, text_end, f.b + 1, f.e) != NULL)
+ return false;
+ }
+ else
+ {
+ // Grep
+ if (ImStristr(text, text_end, f.b, f.e) != NULL)
+ return true;
+ }
+ }
+
+ // Implicit * grep
+ if (CountGrep == 0)
+ return true;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiTextBuffer
+//-----------------------------------------------------------------------------
+
+// On some platform vsnprintf() takes va_list by reference and modifies it.
+// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
+#ifndef va_copy
+#if defined(__GNUC__) || defined(__clang__)
+#define va_copy(dest, src) __builtin_va_copy(dest, src)
+#else
+#define va_copy(dest, src) (dest = src)
+#endif
+#endif
+
+char ImGuiTextBuffer::EmptyString[1] = { 0 };
+
+void ImGuiTextBuffer::append(const char* str, const char* str_end)
+{
+ int len = str_end ? (int)(str_end - str) : (int)strlen(str);
+
+ // Add zero-terminator the first time
+ const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
+ const int needed_sz = write_off + len;
+ if (write_off + len >= Buf.Capacity)
+ {
+ int new_capacity = Buf.Capacity * 2;
+ Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
+ }
+
+ Buf.resize(needed_sz);
+ memcpy(&Buf[write_off - 1], str, (size_t)len);
+ Buf[write_off - 1 + len] = 0;
+}
+
+void ImGuiTextBuffer::appendf(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ appendfv(fmt, args);
+ va_end(args);
+}
+
+// Helper: Text buffer for logging/accumulating text
+void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
+{
+ va_list args_copy;
+ va_copy(args_copy, args);
+
+ int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
+ if (len <= 0)
+ {
+ va_end(args_copy);
+ return;
+ }
+
+ // Add zero-terminator the first time
+ const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
+ const int needed_sz = write_off + len;
+ if (write_off + len >= Buf.Capacity)
+ {
+ int new_capacity = Buf.Capacity * 2;
+ Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity);
+ }
+
+ Buf.resize(needed_sz);
+ ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy);
+ va_end(args_copy);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiListClipper
+// This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed
+// the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO)
+//-----------------------------------------------------------------------------
+
+// FIXME-TABLE: This prevents us from using ImGuiListClipper _inside_ a table cell.
+// The problem we have is that without a Begin/End scheme for rows using the clipper is ambiguous.
+static bool GetSkipItemForListClipping()
+{
+ ImGuiContext& g = *GImGui;
+ return (g.CurrentTable ? g.CurrentTable->HostSkipItems : g.CurrentWindow->SkipItems);
+}
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+// Legacy helper to calculate coarse clipping of large list of evenly sized items.
+// This legacy API is not ideal because it assume we will return a single contiguous rectangle.
+// Prefer using ImGuiListClipper which can returns non-contiguous ranges.
+void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.LogEnabled)
+ {
+ // If logging is active, do not perform any clipping
+ *out_items_display_start = 0;
+ *out_items_display_end = items_count;
+ return;
+ }
+ if (GetSkipItemForListClipping())
+ {
+ *out_items_display_start = *out_items_display_end = 0;
+ return;
+ }
+
+ // We create the union of the ClipRect and the scoring rect which at worst should be 1 page away from ClipRect
+ // We don't include g.NavId's rectangle in there (unless g.NavJustMovedToId is set) because the rectangle enlargement can get costly.
+ ImRect rect = window->ClipRect;
+ if (g.NavMoveScoringItems)
+ rect.Add(g.NavScoringNoClipRect);
+ if (g.NavJustMovedToId && window->NavLastIds[0] == g.NavJustMovedToId)
+ rect.Add(WindowRectRelToAbs(window, window->NavRectRel[0])); // Could store and use NavJustMovedToRectRel
+
+ const ImVec2 pos = window->DC.CursorPos;
+ int start = (int)((rect.Min.y - pos.y) / items_height);
+ int end = (int)((rect.Max.y - pos.y) / items_height);
+
+ // When performing a navigation request, ensure we have one item extra in the direction we are moving to
+ // FIXME: Verify this works with tabbing
+ const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
+ if (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up)
+ start--;
+ if (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down)
+ end++;
+
+ start = ImClamp(start, 0, items_count);
+ end = ImClamp(end + 1, start, items_count);
+ *out_items_display_start = start;
+ *out_items_display_end = end;
+}
+#endif
+
+static void ImGuiListClipper_SortAndFuseRanges(ImVector<ImGuiListClipperRange>& ranges, int offset = 0)
+{
+ if (ranges.Size - offset <= 1)
+ return;
+
+ // Helper to order ranges and fuse them together if possible (bubble sort is fine as we are only sorting 2-3 entries)
+ for (int sort_end = ranges.Size - offset - 1; sort_end > 0; --sort_end)
+ for (int i = offset; i < sort_end + offset; ++i)
+ if (ranges[i].Min > ranges[i + 1].Min)
+ ImSwap(ranges[i], ranges[i + 1]);
+
+ // Now fuse ranges together as much as possible.
+ for (int i = 1 + offset; i < ranges.Size; i++)
+ {
+ IM_ASSERT(!ranges[i].PosToIndexConvert && !ranges[i - 1].PosToIndexConvert);
+ if (ranges[i - 1].Max < ranges[i].Min)
+ continue;
+ ranges[i - 1].Min = ImMin(ranges[i - 1].Min, ranges[i].Min);
+ ranges[i - 1].Max = ImMax(ranges[i - 1].Max, ranges[i].Max);
+ ranges.erase(ranges.Data + i);
+ i--;
+ }
+}
+
+static void ImGuiListClipper_SeekCursorAndSetupPrevLine(float pos_y, float line_height)
+{
+ // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor.
+ // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
+ // The clipper should probably have a final step to display the last item in a regular manner, maybe with an opt-out flag for data sets which may have costly seek?
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ float off_y = pos_y - window->DC.CursorPos.y;
+ window->DC.CursorPos.y = pos_y;
+ window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y - g.Style.ItemSpacing.y);
+ window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
+ window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
+ if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
+ columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
+ if (ImGuiTable* table = g.CurrentTable)
+ {
+ if (table->IsInsideRow)
+ ImGui::TableEndRow(table);
+ table->RowPosY2 = window->DC.CursorPos.y;
+ const int row_increase = (int)((off_y / line_height) + 0.5f);
+ //table->CurrentRow += row_increase; // Can't do without fixing TableEndRow()
+ table->RowBgColorCounter += row_increase;
+ }
+}
+
+static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int item_n)
+{
+ // StartPosY starts from ItemsFrozen hence the subtraction
+ ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
+ float pos_y = clipper->StartPosY + (item_n - data->ItemsFrozen) * clipper->ItemsHeight;
+ ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight);
+}
+
+ImGuiListClipper::ImGuiListClipper()
+{
+ memset(this, 0, sizeof(*this));
+ ItemsCount = -1;
+}
+
+ImGuiListClipper::~ImGuiListClipper()
+{
+ End();
+}
+
+// Use case A: Begin() called from constructor with items_height<0, then called again from Step() in StepNo 1
+// Use case B: Begin() called from constructor with items_height>0
+// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style.
+void ImGuiListClipper::Begin(int items_count, float items_height)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (ImGuiTable* table = g.CurrentTable)
+ if (table->IsInsideRow)
+ ImGui::TableEndRow(table);
+
+ StartPosY = window->DC.CursorPos.y;
+ ItemsHeight = items_height;
+ ItemsCount = items_count;
+ DisplayStart = -1;
+ DisplayEnd = 0;
+
+ // Acquire temporary buffer
+ if (++g.ClipperTempDataStacked > g.ClipperTempData.Size)
+ g.ClipperTempData.resize(g.ClipperTempDataStacked, ImGuiListClipperData());
+ ImGuiListClipperData* data = &g.ClipperTempData[g.ClipperTempDataStacked - 1];
+ data->Reset(this);
+ TempData = data;
+}
+
+void ImGuiListClipper::End()
+{
+ // In theory here we should assert that we are already at the right position, but it seems saner to just seek at the end and not assert/crash the user.
+ ImGuiContext& g = *GImGui;
+ if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0)
+ ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
+ ItemsCount = -1;
+
+ // Restore temporary buffer and fix back pointers which may be invalidated when nesting
+ if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
+ {
+ IM_ASSERT(data->ListClipper == this);
+ data->StepNo = data->Ranges.Size;
+ if (--g.ClipperTempDataStacked > 0)
+ {
+ data = &g.ClipperTempData[g.ClipperTempDataStacked - 1];
+ data->ListClipper->TempData = data;
+ }
+ TempData = NULL;
+ }
+}
+
+void ImGuiListClipper::ForceDisplayRangeByIndices(int item_min, int item_max)
+{
+ ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
+ IM_ASSERT(DisplayStart < 0); // Only allowed after Begin() and if there has not been a specified range yet.
+ IM_ASSERT(item_min <= item_max);
+ if (item_min < item_max)
+ data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_min, item_max));
+}
+
+bool ImGuiListClipper::Step()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiListClipperData* data = (ImGuiListClipperData*)TempData;
+
+ ImGuiTable* table = g.CurrentTable;
+ if (table && table->IsInsideRow)
+ ImGui::TableEndRow(table);
+
+ // No items
+ if (ItemsCount == 0 || GetSkipItemForListClipping())
+ {
+ End();
+ return false;
+ }
+
+ // While we are in frozen row state, keep displaying items one by one, unclipped
+ // FIXME: Could be stored as a table-agnostic state.
+ if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows)
+ {
+ DisplayStart = data->ItemsFrozen;
+ DisplayEnd = data->ItemsFrozen + 1;
+ data->ItemsFrozen++;
+ return true;
+ }
+
+ // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height)
+ bool calc_clipping = false;
+ if (data->StepNo == 0)
+ {
+ StartPosY = window->DC.CursorPos.y;
+ if (ItemsHeight <= 0.0f)
+ {
+ // Submit the first item (or range) so we can measure its height (generally the first range is 0..1)
+ data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1));
+ DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen);
+ DisplayEnd = ImMin(data->Ranges[0].Max, ItemsCount);
+ data->StepNo = 1;
+ return true;
+ }
+ calc_clipping = true; // If on the first step with known item height, calculate clipping.
+ }
+
+ // Step 1: Let the clipper infer height from first range
+ if (ItemsHeight <= 0.0f)
+ {
+ IM_ASSERT(data->StepNo == 1);
+ if (table)
+ {
+ const float pos_y1 = table->RowPosY1; // Using RowPosY1 instead of StartPosY to handle clipper straddling the frozen row
+ const float pos_y2 = table->RowPosY2; // Using RowPosY2 instead of CursorPos.y to take account of tallest cell.
+ ItemsHeight = pos_y2 - pos_y1;
+ window->DC.CursorPos.y = pos_y2;
+ }
+ else
+ {
+ ItemsHeight = (window->DC.CursorPos.y - StartPosY) / (float)(DisplayEnd - DisplayStart);
+ }
+ IM_ASSERT(ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");
+ calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards.
+ }
+
+ // Step 0 or 1: Calculate the actual ranges of visible elements.
+ const int already_submitted = DisplayEnd;
+ if (calc_clipping)
+ {
+ if (g.LogEnabled)
+ {
+ // If logging is active, do not perform any clipping
+ data->Ranges.push_back(ImGuiListClipperRange::FromIndices(0, ItemsCount));
+ }
+ else
+ {
+ // Add range selected to be included for navigation
+ const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
+ if (is_nav_request)
+ data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y, g.NavScoringNoClipRect.Max.y, 0, 0));
+ if (is_nav_request && (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && g.NavTabbingDir == -1)
+ data->Ranges.push_back(ImGuiListClipperRange::FromIndices(ItemsCount - 1, ItemsCount));
+
+ // Add focused/active item
+ ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]);
+ if (g.NavId != 0 && window->NavLastIds[0] == g.NavId)
+ data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0));
+
+ // Add visible range
+ const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
+ const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0;
+ data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max));
+ }
+
+ // Convert position ranges to item index ranges
+ // - Very important: when a starting position is after our maximum item, we set Min to (ItemsCount - 1). This allows us to handle most forms of wrapping.
+ // - Due to how Selectable extra padding they tend to be "unaligned" with exact unit in the item list,
+ // which with the flooring/ceiling tend to lead to 2 items instead of one being submitted.
+ for (int i = 0; i < data->Ranges.Size; i++)
+ if (data->Ranges[i].PosToIndexConvert)
+ {
+ data->Ranges[i].Min = ImClamp(already_submitted + (int)ImFloor((data->Ranges[i].Min - window->DC.CursorPos.y) / ItemsHeight) + data->Ranges[i].PosToIndexOffsetMin, already_submitted, ItemsCount - 1);
+ data->Ranges[i].Max = ImClamp(already_submitted + (int)ImCeil((data->Ranges[i].Max - window->DC.CursorPos.y) / ItemsHeight) + 0 + data->Ranges[i].PosToIndexOffsetMax, data->Ranges[i].Min + 1, ItemsCount);
+ data->Ranges[i].PosToIndexConvert = false;
+ }
+ ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo);
+ }
+
+ // Step 0+ (if item height is given in advance) or 1+: Display the next range in line.
+ if (data->StepNo < data->Ranges.Size)
+ {
+ DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted);
+ DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, ItemsCount);
+ if (DisplayStart > already_submitted) //-V1051
+ ImGuiListClipper_SeekCursorForItem(this, DisplayStart);
+ data->StepNo++;
+ return true;
+ }
+
+ // After the last step: Let the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd),
+ // Advance the cursor to the end of the list and then returns 'false' to end the loop.
+ if (ItemsCount < INT_MAX)
+ ImGuiListClipper_SeekCursorForItem(this, ItemsCount);
+ ItemsCount = -1;
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] STYLING
+//-----------------------------------------------------------------------------
+
+ImGuiStyle& ImGui::GetStyle()
+{
+ IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
+ return GImGui->Style;
+}
+
+ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
+{
+ ImGuiStyle& style = GImGui->Style;
+ ImVec4 c = style.Colors[idx];
+ c.w *= style.Alpha * alpha_mul;
+ return ColorConvertFloat4ToU32(c);
+}
+
+ImU32 ImGui::GetColorU32(const ImVec4& col)
+{
+ ImGuiStyle& style = GImGui->Style;
+ ImVec4 c = col;
+ c.w *= style.Alpha;
+ return ColorConvertFloat4ToU32(c);
+}
+
+const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
+{
+ ImGuiStyle& style = GImGui->Style;
+ return style.Colors[idx];
+}
+
+ImU32 ImGui::GetColorU32(ImU32 col)
+{
+ ImGuiStyle& style = GImGui->Style;
+ if (style.Alpha >= 1.0f)
+ return col;
+ ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
+ a = (ImU32)(a * style.Alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
+ return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
+}
+
+// FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32
+void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiColorMod backup;
+ backup.Col = idx;
+ backup.BackupValue = g.Style.Colors[idx];
+ g.ColorStack.push_back(backup);
+ g.Style.Colors[idx] = ColorConvertU32ToFloat4(col);
+}
+
+void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiColorMod backup;
+ backup.Col = idx;
+ backup.BackupValue = g.Style.Colors[idx];
+ g.ColorStack.push_back(backup);
+ g.Style.Colors[idx] = col;
+}
+
+void ImGui::PopStyleColor(int count)
+{
+ ImGuiContext& g = *GImGui;
+ while (count > 0)
+ {
+ ImGuiColorMod& backup = g.ColorStack.back();
+ g.Style.Colors[backup.Col] = backup.BackupValue;
+ g.ColorStack.pop_back();
+ count--;
+ }
+}
+
+struct ImGuiStyleVarInfo
+{
+ ImGuiDataType Type;
+ ImU32 Count;
+ ImU32 Offset;
+ void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
+};
+
+static const ImGuiStyleVarInfo GStyleVarInfo[] =
+{
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, CellPadding) }, // ImGuiStyleVar_CellPadding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
+ { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
+ { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
+};
+
+static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
+{
+ IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
+ IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
+ return &GStyleVarInfo[idx];
+}
+
+void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
+{
+ const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
+ if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
+ {
+ ImGuiContext& g = *GImGui;
+ float* pvar = (float*)var_info->GetVarPtr(&g.Style);
+ g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
+ *pvar = val;
+ return;
+ }
+ IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!");
+}
+
+void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
+{
+ const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
+ if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
+ {
+ ImGuiContext& g = *GImGui;
+ ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
+ g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
+ *pvar = val;
+ return;
+ }
+ IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!");
+}
+
+void ImGui::PopStyleVar(int count)
+{
+ ImGuiContext& g = *GImGui;
+ while (count > 0)
+ {
+ // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
+ ImGuiStyleMod& backup = g.StyleVarStack.back();
+ const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
+ void* data = info->GetVarPtr(&g.Style);
+ if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; }
+ else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
+ g.StyleVarStack.pop_back();
+ count--;
+ }
+}
+
+const char* ImGui::GetStyleColorName(ImGuiCol idx)
+{
+ // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1";
+ switch (idx)
+ {
+ case ImGuiCol_Text: return "Text";
+ case ImGuiCol_TextDisabled: return "TextDisabled";
+ case ImGuiCol_WindowBg: return "WindowBg";
+ case ImGuiCol_ChildBg: return "ChildBg";
+ case ImGuiCol_PopupBg: return "PopupBg";
+ case ImGuiCol_Border: return "Border";
+ case ImGuiCol_BorderShadow: return "BorderShadow";
+ case ImGuiCol_FrameBg: return "FrameBg";
+ case ImGuiCol_FrameBgHovered: return "FrameBgHovered";
+ case ImGuiCol_FrameBgActive: return "FrameBgActive";
+ case ImGuiCol_TitleBg: return "TitleBg";
+ case ImGuiCol_TitleBgActive: return "TitleBgActive";
+ case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed";
+ case ImGuiCol_MenuBarBg: return "MenuBarBg";
+ case ImGuiCol_ScrollbarBg: return "ScrollbarBg";
+ case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab";
+ case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
+ case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
+ case ImGuiCol_CheckMark: return "CheckMark";
+ case ImGuiCol_SliderGrab: return "SliderGrab";
+ case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
+ case ImGuiCol_Button: return "Button";
+ case ImGuiCol_ButtonHovered: return "ButtonHovered";
+ case ImGuiCol_ButtonActive: return "ButtonActive";
+ case ImGuiCol_Header: return "Header";
+ case ImGuiCol_HeaderHovered: return "HeaderHovered";
+ case ImGuiCol_HeaderActive: return "HeaderActive";
+ case ImGuiCol_Separator: return "Separator";
+ case ImGuiCol_SeparatorHovered: return "SeparatorHovered";
+ case ImGuiCol_SeparatorActive: return "SeparatorActive";
+ case ImGuiCol_ResizeGrip: return "ResizeGrip";
+ case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
+ case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
+ case ImGuiCol_Tab: return "Tab";
+ case ImGuiCol_TabHovered: return "TabHovered";
+ case ImGuiCol_TabActive: return "TabActive";
+ case ImGuiCol_TabUnfocused: return "TabUnfocused";
+ case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive";
+ case ImGuiCol_PlotLines: return "PlotLines";
+ case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
+ case ImGuiCol_PlotHistogram: return "PlotHistogram";
+ case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
+ case ImGuiCol_TableHeaderBg: return "TableHeaderBg";
+ case ImGuiCol_TableBorderStrong: return "TableBorderStrong";
+ case ImGuiCol_TableBorderLight: return "TableBorderLight";
+ case ImGuiCol_TableRowBg: return "TableRowBg";
+ case ImGuiCol_TableRowBgAlt: return "TableRowBgAlt";
+ case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
+ case ImGuiCol_DragDropTarget: return "DragDropTarget";
+ case ImGuiCol_NavHighlight: return "NavHighlight";
+ case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
+ case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
+ case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg";
+ }
+ IM_ASSERT(0);
+ return "Unknown";
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] RENDER HELPERS
+// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change,
+// we need a nicer separation between low-level functions and high-level functions relying on the ImGui context.
+// Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: context.
+//-----------------------------------------------------------------------------
+
+const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
+{
+ const char* text_display_end = text;
+ if (!text_end)
+ text_end = (const char*)-1;
+
+ while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
+ text_display_end++;
+ return text_display_end;
+}
+
+// Internal ImGui functions to render text
+// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
+void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // Hide anything after a '##' string
+ const char* text_display_end;
+ if (hide_text_after_hash)
+ {
+ text_display_end = FindRenderedTextEnd(text, text_end);
+ }
+ else
+ {
+ if (!text_end)
+ text_end = text + strlen(text); // FIXME-OPT
+ text_display_end = text_end;
+ }
+
+ if (text != text_display_end)
+ {
+ window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
+ if (g.LogEnabled)
+ LogRenderedText(&pos, text, text_display_end);
+ }
+}
+
+void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ if (!text_end)
+ text_end = text + strlen(text); // FIXME-OPT
+
+ if (text != text_end)
+ {
+ window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
+ if (g.LogEnabled)
+ LogRenderedText(&pos, text, text_end);
+ }
+}
+
+// Default clip_rect uses (pos_min,pos_max)
+// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
+void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
+{
+ // Perform CPU side clipping for single clipped element to avoid using scissor state
+ ImVec2 pos = pos_min;
+ const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);
+
+ const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
+ const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
+ bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
+ if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
+ need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
+
+ // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
+ if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
+ if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
+
+ // Render
+ if (need_clipping)
+ {
+ ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
+ draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
+ }
+ else
+ {
+ draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
+ }
+}
+
+void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
+{
+ // Hide anything after a '##' string
+ const char* text_display_end = FindRenderedTextEnd(text, text_end);
+ const int text_len = (int)(text_display_end - text);
+ if (text_len == 0)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
+ if (g.LogEnabled)
+ LogRenderedText(&pos_min, text, text_display_end);
+}
+
+
+// Another overly complex function until we reorganize everything into a nice all-in-one helper.
+// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
+// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
+void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
+{
+ ImGuiContext& g = *GImGui;
+ if (text_end_full == NULL)
+ text_end_full = FindRenderedTextEnd(text);
+ const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
+
+ //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255));
+ //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255));
+ //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255));
+ // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
+ if (text_size.x > pos_max.x - pos_min.x)
+ {
+ // Hello wo...
+ // | | |
+ // min max ellipsis_max
+ // <-> this is generally some padding value
+
+ const ImFont* font = draw_list->_Data->Font;
+ const float font_size = draw_list->_Data->FontSize;
+ const char* text_end_ellipsis = NULL;
+
+ ImWchar ellipsis_char = font->EllipsisChar;
+ int ellipsis_char_count = 1;
+ if (ellipsis_char == (ImWchar)-1)
+ {
+ ellipsis_char = font->DotChar;
+ ellipsis_char_count = 3;
+ }
+ const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
+
+ float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side
+ float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis
+
+ if (ellipsis_char_count > 1)
+ {
+ // Full ellipsis size without free spacing after it.
+ const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize);
+ ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots;
+ ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots;
+ }
+
+ // We can now claim the space between pos_max.x and ellipsis_max.x
+ const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f);
+ float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
+ if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
+ {
+ // Always display at least 1 character if there's no room for character + ellipsis
+ text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full);
+ text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
+ }
+ while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
+ {
+ // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text)
+ text_end_ellipsis--;
+ text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
+ }
+
+ // Render text, render ellipsis
+ RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
+ float ellipsis_x = pos_min.x + text_size_clipped_x;
+ if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x)
+ for (int i = 0; i < ellipsis_char_count; i++)
+ {
+ font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
+ ellipsis_x += ellipsis_glyph_width;
+ }
+ }
+ else
+ {
+ RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f));
+ }
+
+ if (g.LogEnabled)
+ LogRenderedText(&pos_min, text, text_end_full);
+}
+
+// Render a rectangle shaped with optional rounding and borders
+void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
+ const float border_size = g.Style.FrameBorderSize;
+ if (border && border_size > 0.0f)
+ {
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
+ }
+}
+
+void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ const float border_size = g.Style.FrameBorderSize;
+ if (border_size > 0.0f)
+ {
+ window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
+ window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
+ }
+}
+
+void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (id != g.NavId)
+ return;
+ if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw))
+ return;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->DC.NavHideHighlightOneFrame)
+ return;
+
+ float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding;
+ ImRect display_rect = bb;
+ display_rect.ClipWith(window->ClipRect);
+ if (flags & ImGuiNavHighlightFlags_TypeDefault)
+ {
+ const float THICKNESS = 2.0f;
+ const float DISTANCE = 3.0f + THICKNESS * 0.5f;
+ display_rect.Expand(ImVec2(DISTANCE, DISTANCE));
+ bool fully_visible = window->ClipRect.Contains(display_rect);
+ if (!fully_visible)
+ window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
+ window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), display_rect.Max - ImVec2(THICKNESS * 0.5f, THICKNESS * 0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, 0, THICKNESS);
+ if (!fully_visible)
+ window->DrawList->PopClipRect();
+ }
+ if (flags & ImGuiNavHighlightFlags_TypeThin)
+ {
+ window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, 1.0f);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
+//-----------------------------------------------------------------------------
+
+// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
+ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) : DrawListInst(NULL)
+{
+ memset(this, 0, sizeof(*this));
+ Name = ImStrdup(name);
+ NameBufLen = (int)strlen(name) + 1;
+ ID = ImHashStr(name);
+ IDStack.push_back(ID);
+ MoveId = GetID("#MOVE");
+ ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
+ ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
+ AutoFitFramesX = AutoFitFramesY = -1;
+ AutoPosLastDirection = ImGuiDir_None;
+ SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
+ SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
+ LastFrameActive = -1;
+ LastTimeActive = -1.0f;
+ FontWindowScale = 1.0f;
+ SettingsOffset = -1;
+ DrawList = &DrawListInst;
+ DrawList->_Data = &context->DrawListSharedData;
+ DrawList->_OwnerName = Name;
+}
+
+ImGuiWindow::~ImGuiWindow()
+{
+ IM_ASSERT(DrawList == &DrawListInst);
+ IM_DELETE(Name);
+ ColumnsStorage.clear_destruct();
+}
+
+ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
+ ImGui::KeepAliveID(id);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetID(const void* ptr)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
+ ImGui::KeepAliveID(id);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetID(int n)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHashData(&n, sizeof(n), seed);
+ ImGui::KeepAliveID(id);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetIDNoKeepAlive(const void* ptr)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL);
+ return id;
+}
+
+ImGuiID ImGuiWindow::GetIDNoKeepAlive(int n)
+{
+ ImGuiID seed = IDStack.back();
+ ImGuiID id = ImHashData(&n, sizeof(n), seed);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL);
+ return id;
+}
+
+// This is only used in rare/specific situations to manufacture an ID out of nowhere.
+ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs)
+{
+ ImGuiID seed = IDStack.back();
+ ImRect r_rel = ImGui::WindowRectAbsToRel(this, r_abs);
+ ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed);
+ ImGui::KeepAliveID(id);
+ return id;
+}
+
+static void SetCurrentWindow(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ g.CurrentWindow = window;
+ g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
+ if (window)
+ g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
+}
+
+void ImGui::GcCompactTransientMiscBuffers()
+{
+ ImGuiContext& g = *GImGui;
+ g.ItemFlagsStack.clear();
+ g.GroupStack.clear();
+ TableGcCompactSettings();
+}
+
+// Free up/compact internal window buffers, we can use this when a window becomes unused.
+// Not freed:
+// - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data)
+// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost.
+void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
+{
+ window->MemoryCompacted = true;
+ window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
+ window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
+ window->IDStack.clear();
+ window->DrawList->_ClearFreeMemory();
+ window->DC.ChildWindows.clear();
+ window->DC.ItemWidthStack.clear();
+ window->DC.TextWrapPosStack.clear();
+}
+
+void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window)
+{
+ // We stored capacity of the ImDrawList buffer to reduce growth-caused allocation/copy when awakening.
+ // The other buffers tends to amortize much faster.
+ window->MemoryCompacted = false;
+ window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity);
+ window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity);
+ window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0;
+}
+
+void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ g.ActiveIdIsJustActivated = (g.ActiveId != id);
+ if (g.ActiveIdIsJustActivated)
+ {
+ g.ActiveIdTimer = 0.0f;
+ g.ActiveIdHasBeenPressedBefore = false;
+ g.ActiveIdHasBeenEditedBefore = false;
+ g.ActiveIdMouseButton = -1;
+ if (id != 0)
+ {
+ g.LastActiveId = id;
+ g.LastActiveIdTimer = 0.0f;
+ }
+ }
+ g.ActiveId = id;
+ g.ActiveIdAllowOverlap = false;
+ g.ActiveIdNoClearOnFocusLoss = false;
+ g.ActiveIdWindow = window;
+ g.ActiveIdHasBeenEditedThisFrame = false;
+ if (id)
+ {
+ g.ActiveIdIsAlive = id;
+ g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
+ }
+
+ // Clear declaration of inputs claimed by the widget
+ // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet)
+ g.ActiveIdUsingMouseWheel = false;
+ g.ActiveIdUsingNavDirMask = 0x00;
+ g.ActiveIdUsingNavInputMask = 0x00;
+ g.ActiveIdUsingKeyInputMask = 0x00;
+}
+
+void ImGui::ClearActiveID()
+{
+ SetActiveID(0, NULL); // g.ActiveId = 0;
+}
+
+void ImGui::SetHoveredID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ g.HoveredId = id;
+ g.HoveredIdAllowOverlap = false;
+ g.HoveredIdUsingMouseWheel = false;
+ if (id != 0 && g.HoveredIdPreviousFrame != id)
+ g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
+}
+
+ImGuiID ImGui::GetHoveredID()
+{
+ ImGuiContext& g = *GImGui;
+ return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame;
+}
+
+void ImGui::KeepAliveID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId == id)
+ g.ActiveIdIsAlive = id;
+ if (g.ActiveIdPreviousFrame == id)
+ g.ActiveIdPreviousFrameIsAlive = true;
+}
+
+void ImGui::MarkItemEdited(ImGuiID id)
+{
+ // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
+ // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data.
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
+ IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out.
+ //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
+ g.ActiveIdHasBeenEditedThisFrame = true;
+ g.ActiveIdHasBeenEditedBefore = true;
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
+}
+
+static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
+{
+ // An active popup disable hovering on other windows (apart from its own children)
+ // FIXME-OPT: This could be cached/stored within the window.
+ ImGuiContext& g = *GImGui;
+ if (g.NavWindow)
+ if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
+ if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
+ {
+ // For the purpose of those flags we differentiate "standard popup" from "modal popup"
+ // NB: The order of those two tests is important because Modal windows are also Popups.
+ if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
+ return false;
+ if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ return false;
+ }
+ return true;
+}
+
+// This is roughly matching the behavior of internal-facing ItemHoverable()
+// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()
+// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
+bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.NavDisableMouseHover && !g.NavDisableHighlight)
+ {
+ if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
+ return false;
+ if (!IsItemFocused())
+ return false;
+ }
+ else
+ {
+ // Test for bounding box overlap, as updated as ItemAdd()
+ ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags;
+ if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
+ return false;
+ IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy)) == 0); // Flags not supported by this function
+
+ // Test if we are hovering the right window (our window could be behind another window)
+ // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851)
+ // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable
+ // to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was
+ // the test that has been running for a long while.
+ if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
+ if ((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0)
+ return false;
+
+ // Test if another item is active (e.g. being dragged)
+ if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
+ if (g.ActiveId != 0 && g.ActiveId != g.LastItemData.ID && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
+ return false;
+
+ // Test if interactions on this window are blocked by an active popup or modal.
+ // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here.
+ if (!IsWindowContentHoverable(window, flags))
+ return false;
+
+ // Test if the item is disabled
+ if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
+ return false;
+
+ // Special handling for calling after Begin() which represent the title bar or tab.
+ // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.
+ if (g.LastItemData.ID == window->MoveId && window->WriteAccessed)
+ return false;
+ }
+
+ return true;
+}
+
+// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
+bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap)
+ return false;
+
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.HoveredWindow != window)
+ return false;
+ if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap)
+ return false;
+ if (!IsMouseHoveringRect(bb.Min, bb.Max))
+ return false;
+ if (g.NavDisableMouseHover)
+ return false;
+ if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
+ {
+ g.HoveredIdDisabled = true;
+ return false;
+ }
+
+ // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level
+ // hover test in widgets code. We could also decide to split this function is two.
+ if (id != 0)
+ SetHoveredID(id);
+
+ // When disabled we'll return false but still set HoveredId
+ ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags);
+ if (item_flags & ImGuiItemFlags_Disabled)
+ {
+ // Release active id if turning disabled
+ if (g.ActiveId == id)
+ ClearActiveID();
+ g.HoveredIdDisabled = true;
+ return false;
+ }
+
+ if (id != 0)
+ {
+ // [DEBUG] Item Picker tool!
+ // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making
+ // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered
+ // items if we perform the test in ItemAdd(), but that would incur a small runtime cost.
+ // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd().
+ if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id)
+ GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255));
+ if (g.DebugItemPickerBreakId == id)
+ IM_DEBUG_BREAK();
+ }
+
+ return true;
+}
+
+bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!bb.Overlaps(window->ClipRect))
+ if (id == 0 || (id != g.ActiveId && id != g.NavId))
+ if (!g.LogEnabled)
+ return true;
+ return false;
+}
+
+float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
+{
+ if (wrap_pos_x < 0.0f)
+ return 0.0f;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (wrap_pos_x == 0.0f)
+ {
+ // We could decide to setup a default wrapping max point for auto-resizing windows,
+ // or have auto-wrap (with unspecified wrapping pos) behave as a ContentSize extending function?
+ //if (window->Hidden && (window->Flags & ImGuiWindowFlags_AlwaysAutoResize))
+ // wrap_pos_x = ImMax(window->WorkRect.Min.x + g.FontSize * 10.0f, window->WorkRect.Max.x);
+ //else
+ wrap_pos_x = window->WorkRect.Max.x;
+ }
+ else if (wrap_pos_x > 0.0f)
+ {
+ wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
+ }
+
+ return ImMax(wrap_pos_x - pos.x, 1.0f);
+}
+
+// IM_ALLOC() == ImGui::MemAlloc()
+void* ImGui::MemAlloc(size_t size)
+{
+ if (ImGuiContext* ctx = GImGui)
+ ctx->IO.MetricsActiveAllocations++;
+ return (*GImAllocatorAllocFunc)(size, GImAllocatorUserData);
+}
+
+// IM_FREE() == ImGui::MemFree()
+void ImGui::MemFree(void* ptr)
+{
+ if (ptr)
+ if (ImGuiContext* ctx = GImGui)
+ ctx->IO.MetricsActiveAllocations--;
+ return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
+}
+
+const char* ImGui::GetClipboardText()
+{
+ ImGuiContext& g = *GImGui;
+ return g.IO.GetClipboardTextFn ? g.IO.GetClipboardTextFn(g.IO.ClipboardUserData) : "";
+}
+
+void ImGui::SetClipboardText(const char* text)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.IO.SetClipboardTextFn)
+ g.IO.SetClipboardTextFn(g.IO.ClipboardUserData, text);
+}
+
+const char* ImGui::GetVersion()
+{
+ return IMGUI_VERSION;
+}
+
+// Internal state access - if you want to share Dear ImGui state between modules (e.g. DLL) or allocate it yourself
+// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module
+ImGuiContext* ImGui::GetCurrentContext()
+{
+ return GImGui;
+}
+
+void ImGui::SetCurrentContext(ImGuiContext* ctx)
+{
+#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
+ IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
+#else
+ GImGui = ctx;
+#endif
+}
+
+void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data)
+{
+ GImAllocatorAllocFunc = alloc_func;
+ GImAllocatorFreeFunc = free_func;
+ GImAllocatorUserData = user_data;
+}
+
+// This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space)
+void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data)
+{
+ *p_alloc_func = GImAllocatorAllocFunc;
+ *p_free_func = GImAllocatorFreeFunc;
+ *p_user_data = GImAllocatorUserData;
+}
+
+ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas)
+{
+ ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas);
+ if (GImGui == NULL)
+ SetCurrentContext(ctx);
+ Initialize(ctx);
+ return ctx;
+}
+
+void ImGui::DestroyContext(ImGuiContext* ctx)
+{
+ if (ctx == NULL)
+ ctx = GImGui;
+ Shutdown(ctx);
+ if (GImGui == ctx)
+ SetCurrentContext(NULL);
+ IM_DELETE(ctx);
+}
+
+// No specific ordering/dependency support, will see as needed
+ImGuiID ImGui::AddContextHook(ImGuiContext* ctx, const ImGuiContextHook* hook)
+{
+ ImGuiContext& g = *ctx;
+ IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_);
+ g.Hooks.push_back(*hook);
+ g.Hooks.back().HookId = ++g.HookIdNext;
+ return g.HookIdNext;
+}
+
+// Deferred removal, avoiding issue with changing vector while iterating it
+void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id)
+{
+ ImGuiContext& g = *ctx;
+ IM_ASSERT(hook_id != 0);
+ for (int n = 0; n < g.Hooks.Size; n++)
+ if (g.Hooks[n].HookId == hook_id)
+ g.Hooks[n].Type = ImGuiContextHookType_PendingRemoval_;
+}
+
+// Call context hooks (used by e.g. test engine)
+// We assume a small number of hooks so all stored in same array
+void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
+{
+ ImGuiContext& g = *ctx;
+ for (int n = 0; n < g.Hooks.Size; n++)
+ if (g.Hooks[n].Type == hook_type)
+ g.Hooks[n].Callback(&g, &g.Hooks[n]);
+}
+
+ImGuiIO& ImGui::GetIO()
+{
+ IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
+ return GImGui->IO;
+}
+
+// Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame()
+ImDrawData* ImGui::GetDrawData()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiViewportP* viewport = g.Viewports[0];
+ return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL;
+}
+
+double ImGui::GetTime()
+{
+ return GImGui->Time;
+}
+
+int ImGui::GetFrameCount()
+{
+ return GImGui->FrameCount;
+}
+
+static ImDrawList* GetViewportDrawList(ImGuiViewportP* viewport, size_t drawlist_no, const char* drawlist_name)
+{
+ // Create the draw list on demand, because they are not frequently used for all viewports
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->DrawLists));
+ ImDrawList* draw_list = viewport->DrawLists[drawlist_no];
+ if (draw_list == NULL)
+ {
+ draw_list = IM_NEW(ImDrawList)(&g.DrawListSharedData);
+ draw_list->_OwnerName = drawlist_name;
+ viewport->DrawLists[drawlist_no] = draw_list;
+ }
+
+ // Our ImDrawList system requires that there is always a command
+ if (viewport->DrawListsLastFrame[drawlist_no] != g.FrameCount)
+ {
+ draw_list->_ResetForNewFrame();
+ draw_list->PushTextureID(g.IO.Fonts->TexID);
+ draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
+ viewport->DrawListsLastFrame[drawlist_no] = g.FrameCount;
+ }
+ return draw_list;
+}
+
+ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport)
+{
+ return GetViewportDrawList((ImGuiViewportP*)viewport, 0, "##Background");
+}
+
+ImDrawList* ImGui::GetBackgroundDrawList()
+{
+ ImGuiContext& g = *GImGui;
+ return GetBackgroundDrawList(g.Viewports[0]);
+}
+
+ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport)
+{
+ return GetViewportDrawList((ImGuiViewportP*)viewport, 1, "##Foreground");
+}
+
+ImDrawList* ImGui::GetForegroundDrawList()
+{
+ ImGuiContext& g = *GImGui;
+ return GetForegroundDrawList(g.Viewports[0]);
+}
+
+ImDrawListSharedData* ImGui::GetDrawListSharedData()
+{
+ return &GImGui->DrawListSharedData;
+}
+
+void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
+{
+ // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows.
+ // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward.
+ // This is because we want ActiveId to be set even when the window is not permitted to move.
+ ImGuiContext& g = *GImGui;
+ FocusWindow(window);
+ SetActiveID(window->MoveId, window);
+ g.NavDisableHighlight = true;
+ g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
+ g.ActiveIdNoClearOnFocusLoss = true;
+ SetActiveIdUsingNavAndKeys();
+
+ bool can_move_window = true;
+ if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
+ can_move_window = false;
+ if (can_move_window)
+ g.MovingWindow = window;
+}
+
+// Handle mouse moving window
+// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
+// FIXME: We don't have strong guarantee that g.MovingWindow stay synched with g.ActiveId == g.MovingWindow->MoveId.
+// This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs,
+// but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other.
+void ImGui::UpdateMouseMovingWindowNewFrame()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.MovingWindow != NULL)
+ {
+ // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
+ // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency.
+ KeepAliveID(g.ActiveId);
+ IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow);
+ ImGuiWindow* moving_window = g.MovingWindow->RootWindow;
+ if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
+ {
+ ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
+ if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
+ {
+ MarkIniSettingsDirty(moving_window);
+ SetWindowPos(moving_window, pos, ImGuiCond_Always);
+ }
+ FocusWindow(g.MovingWindow);
+ }
+ else
+ {
+ g.MovingWindow = NULL;
+ ClearActiveID();
+ }
+ }
+ else
+ {
+ // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others.
+ if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId)
+ {
+ KeepAliveID(g.ActiveId);
+ if (!g.IO.MouseDown[0])
+ ClearActiveID();
+ }
+ }
+}
+
+// Initiate moving window when clicking on empty space or title bar.
+// Handle left-click and right-click focus.
+void ImGui::UpdateMouseMovingWindowEndFrame()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId != 0 || g.HoveredId != 0)
+ return;
+
+ // Unless we just made a window/popup appear
+ if (g.NavWindow && g.NavWindow->Appearing)
+ return;
+
+ // Click on empty space to focus window and start moving
+ // (after we're done with all our widgets)
+ if (g.IO.MouseClicked[0])
+ {
+ // Handle the edge case of a popup being closed while clicking in its empty space.
+ // If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
+ ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
+ const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel);
+
+ if (root_window != NULL && !is_closed_popup)
+ {
+ StartMouseMovingWindow(g.HoveredWindow); //-V595
+
+ // Cancel moving if clicked outside of title bar
+ if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar))
+ if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
+ g.MovingWindow = NULL;
+
+ // Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already)
+ if (g.HoveredIdDisabled)
+ g.MovingWindow = NULL;
+ }
+ else if (root_window == NULL && g.NavWindow != NULL && GetTopMostPopupModal() == NULL)
+ {
+ // Clicking on void disable focus
+ FocusWindow(NULL);
+ }
+ }
+
+ // With right mouse button we close popups without changing focus based on where the mouse is aimed
+ // Instead, focus will be restored to the window under the bottom-most closed popup.
+ // (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger)
+ if (g.IO.MouseClicked[1])
+ {
+ // Find the top-most window between HoveredWindow and the top-most Modal Window.
+ // This is where we can trim the popup stack.
+ ImGuiWindow* modal = GetTopMostPopupModal();
+ bool hovered_window_above_modal = g.HoveredWindow && (modal == NULL || IsWindowAbove(g.HoveredWindow, modal));
+ ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal, true);
+ }
+}
+
+static bool IsWindowActiveAndVisible(ImGuiWindow* window)
+{
+ return (window->Active) && (!window->Hidden);
+}
+
+static void ImGui::UpdateMouseInputs()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
+ if (IsMousePosValid(&g.IO.MousePos))
+ g.IO.MousePos = g.MouseLastValidPos = ImFloor(g.IO.MousePos);
+
+ // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
+ if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev))
+ g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
+ else
+ g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
+
+ // If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true.
+ if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)
+ g.NavDisableMouseHover = false;
+
+ g.IO.MousePosPrev = g.IO.MousePos;
+ for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
+ {
+ g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
+ g.IO.MouseClickedCount[i] = 0; // Will be filled below
+ g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
+ g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
+ g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
+ if (g.IO.MouseClicked[i])
+ {
+ bool is_repeated_click = false;
+ if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime)
+ {
+ ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
+ if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
+ is_repeated_click = true;
+ }
+ if (is_repeated_click)
+ g.IO.MouseClickedLastCount[i]++;
+ else
+ g.IO.MouseClickedLastCount[i] = 1;
+ g.IO.MouseClickedTime[i] = g.Time;
+ g.IO.MouseClickedPos[i] = g.IO.MousePos;
+ g.IO.MouseClickedCount[i] = g.IO.MouseClickedLastCount[i];
+ g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
+ g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
+ }
+ else if (g.IO.MouseDown[i])
+ {
+ // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold
+ ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
+ g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
+ g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
+ g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
+ }
+
+ // We provide io.MouseDoubleClicked[] as a legacy service
+ g.IO.MouseDoubleClicked[i] = (g.IO.MouseClickedCount[i] == 2);
+
+ // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation
+ if (g.IO.MouseClicked[i])
+ g.NavDisableMouseHover = false;
+ }
+}
+
+static void StartLockWheelingWindow(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.WheelingWindow == window)
+ return;
+ g.WheelingWindow = window;
+ g.WheelingWindowRefMousePos = g.IO.MousePos;
+ g.WheelingWindowTimer = WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER;
+}
+
+void ImGui::UpdateMouseWheel()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Reset the locked window if we move the mouse or after the timer elapses
+ if (g.WheelingWindow != NULL)
+ {
+ g.WheelingWindowTimer -= g.IO.DeltaTime;
+ if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) > g.IO.MouseDragThreshold * g.IO.MouseDragThreshold)
+ g.WheelingWindowTimer = 0.0f;
+ if (g.WheelingWindowTimer <= 0.0f)
+ {
+ g.WheelingWindow = NULL;
+ g.WheelingWindowTimer = 0.0f;
+ }
+ }
+
+ if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
+ return;
+
+ if ((g.ActiveId != 0 && g.ActiveIdUsingMouseWheel) || (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel))
+ return;
+
+ ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
+ if (!window || window->Collapsed)
+ return;
+
+ // Zoom / Scale window
+ // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned.
+ if (g.IO.MouseWheel != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
+ {
+ StartLockWheelingWindow(window);
+ const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
+ const float scale = new_font_scale / window->FontWindowScale;
+ window->FontWindowScale = new_font_scale;
+ if (window == window->RootWindow)
+ {
+ const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
+ SetWindowPos(window, window->Pos + offset, 0);
+ window->Size = ImFloor(window->Size * scale);
+ window->SizeFull = ImFloor(window->SizeFull * scale);
+ }
+ return;
+ }
+
+ // Mouse wheel scrolling
+ // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent
+ if (g.IO.KeyCtrl)
+ return;
+
+ // As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead
+ // (we avoid doing it on OSX as it the OS input layer handles this already)
+ const bool swap_axis = g.IO.KeyShift && !g.IO.ConfigMacOSXBehaviors;
+ const float wheel_y = swap_axis ? 0.0f : g.IO.MouseWheel;
+ const float wheel_x = swap_axis ? g.IO.MouseWheel : g.IO.MouseWheelH;
+
+ // Vertical Mouse Wheel scrolling
+ if (wheel_y != 0.0f)
+ {
+ StartLockWheelingWindow(window);
+ while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.y == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
+ window = window->ParentWindow;
+ if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
+ {
+ float max_step = window->InnerRect.GetHeight() * 0.67f;
+ float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step));
+ SetScrollY(window, window->Scroll.y - wheel_y * scroll_step);
+ }
+ }
+
+ // Horizontal Mouse Wheel scrolling, or Vertical Mouse Wheel w/ Shift held
+ if (wheel_x != 0.0f)
+ {
+ StartLockWheelingWindow(window);
+ while ((window->Flags & ImGuiWindowFlags_ChildWindow) && ((window->ScrollMax.x == 0.0f) || ((window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))))
+ window = window->ParentWindow;
+ if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
+ {
+ float max_step = window->InnerRect.GetWidth() * 0.67f;
+ float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step));
+ SetScrollX(window, window->Scroll.x - wheel_x * scroll_step);
+ }
+ }
+}
+
+// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
+void ImGui::UpdateHoveredWindowAndCaptureFlags()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+ g.WindowsHoverPadding = ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING));
+
+ // Find the window hovered by mouse:
+ // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
+ // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
+ // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
+ bool clear_hovered_windows = false;
+ FindHoveredWindow();
+
+ // Modal windows prevents mouse from hovering behind them.
+ ImGuiWindow* modal_window = GetTopMostPopupModal();
+ if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindow, modal_window, true))
+ clear_hovered_windows = true;
+
+ // Disabled mouse?
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
+ clear_hovered_windows = true;
+
+ // We track click ownership. When clicked outside of a window the click is owned by the application and
+ // won't report hovering nor request capture even while dragging over our windows afterward.
+ const bool has_open_popup = (g.OpenPopupStack.Size > 0);
+ const bool has_open_modal = (modal_window != NULL);
+ int mouse_earliest_down = -1;
+ bool mouse_any_down = false;
+ for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
+ {
+ if (io.MouseClicked[i])
+ {
+ io.MouseDownOwned[i] = (g.HoveredWindow != NULL) || has_open_popup;
+ io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow != NULL) || has_open_modal;
+ }
+ mouse_any_down |= io.MouseDown[i];
+ if (io.MouseDown[i])
+ if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down])
+ mouse_earliest_down = i;
+ }
+ const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down];
+ const bool mouse_avail_unless_popup_close = (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down];
+
+ // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
+ // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02)
+ const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
+ if (!mouse_avail && !mouse_dragging_extern_payload)
+ clear_hovered_windows = true;
+
+ if (clear_hovered_windows)
+ g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
+
+ // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to Dear ImGui only, false = dispatch mouse to Dear ImGui + underlying app)
+ // Update io.WantCaptureMouseAllowPopupClose (experimental) to give a chance for app to react to popup closure with a drag
+ if (g.WantCaptureMouseNextFrame != -1)
+ {
+ io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (g.WantCaptureMouseNextFrame != 0);
+ }
+ else
+ {
+ io.WantCaptureMouse = (mouse_avail && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup;
+ io.WantCaptureMouseUnlessPopupClose = (mouse_avail_unless_popup_close && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal;
+ }
+
+ // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to Dear ImGui only, false = dispatch keyboard info to Dear ImGui + underlying app)
+ if (g.WantCaptureKeyboardNextFrame != -1)
+ io.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
+ else
+ io.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
+ if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
+ io.WantCaptureKeyboard = true;
+
+ // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible
+ io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
+}
+
+ImGuiKeyModFlags ImGui::GetMergedKeyModFlags()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiKeyModFlags key_mod_flags = ImGuiKeyModFlags_None;
+ if (g.IO.KeyCtrl) { key_mod_flags |= ImGuiKeyModFlags_Ctrl; }
+ if (g.IO.KeyShift) { key_mod_flags |= ImGuiKeyModFlags_Shift; }
+ if (g.IO.KeyAlt) { key_mod_flags |= ImGuiKeyModFlags_Alt; }
+ if (g.IO.KeySuper) { key_mod_flags |= ImGuiKeyModFlags_Super; }
+ return key_mod_flags;
+}
+
+void ImGui::NewFrame()
+{
+ IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?");
+ ImGuiContext& g = *GImGui;
+
+ // Remove pending delete hooks before frame start.
+ // This deferred removal avoid issues of removal while iterating the hook vector
+ for (int n = g.Hooks.Size - 1; n >= 0; n--)
+ if (g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_)
+ g.Hooks.erase(&g.Hooks[n]);
+
+ CallContextHooks(&g, ImGuiContextHookType_NewFramePre);
+
+ // Check and assert for various common IO and Configuration mistakes
+ ErrorCheckNewFrameSanityChecks();
+
+ // Load settings on first frame, save settings when modified (after a delay)
+ UpdateSettings();
+
+ g.Time += g.IO.DeltaTime;
+ g.WithinFrameScope = true;
+ g.FrameCount += 1;
+ g.TooltipOverrideCount = 0;
+ g.WindowsActiveCount = 0;
+ g.MenusIdSubmittedThisFrame.resize(0);
+
+ // Calculate frame-rate for the user, as a purely luxurious feature
+ g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
+ g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
+ g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
+ g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(g.FramerateSecPerFrame));
+ g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)g.FramerateSecPerFrameCount)) : FLT_MAX;
+
+ UpdateViewportsNewFrame();
+
+ // Setup current font and draw list shared data
+ g.IO.Fonts->Locked = true;
+ SetCurrentFont(GetDefaultFont());
+ IM_ASSERT(g.Font->IsLoaded());
+ ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
+ for (int n = 0; n < g.Viewports.Size; n++)
+ virtual_space.Add(g.Viewports[n]->GetMainRect());
+ g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4();
+ g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol;
+ g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError);
+ g.DrawListSharedData.InitialFlags = ImDrawListFlags_None;
+ if (g.Style.AntiAliasedLines)
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines;
+ if (g.Style.AntiAliasedLinesUseTex && !(g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines))
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex;
+ if (g.Style.AntiAliasedFill)
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill;
+ if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)
+ g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset;
+
+ // Mark rendering data as invalid to prevent user who may have a handle on it to use it.
+ for (int n = 0; n < g.Viewports.Size; n++)
+ {
+ ImGuiViewportP* viewport = g.Viewports[n];
+ viewport->DrawDataP.Clear();
+ }
+
+ // Drag and drop keep the source ID alive so even if the source disappear our state is consistent
+ if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId)
+ KeepAliveID(g.DragDropPayload.SourceId);
+
+ // Update HoveredId data
+ if (!g.HoveredIdPreviousFrame)
+ g.HoveredIdTimer = 0.0f;
+ if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId))
+ g.HoveredIdNotActiveTimer = 0.0f;
+ if (g.HoveredId)
+ g.HoveredIdTimer += g.IO.DeltaTime;
+ if (g.HoveredId && g.ActiveId != g.HoveredId)
+ g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
+ g.HoveredIdPreviousFrame = g.HoveredId;
+ g.HoveredIdPreviousFrameUsingMouseWheel = g.HoveredIdUsingMouseWheel;
+ g.HoveredId = 0;
+ g.HoveredIdAllowOverlap = false;
+ g.HoveredIdUsingMouseWheel = false;
+ g.HoveredIdDisabled = false;
+
+ // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore)
+ if (g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
+ ClearActiveID();
+ if (g.ActiveId)
+ g.ActiveIdTimer += g.IO.DeltaTime;
+ g.LastActiveIdTimer += g.IO.DeltaTime;
+ g.ActiveIdPreviousFrame = g.ActiveId;
+ g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
+ g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore;
+ g.ActiveIdIsAlive = 0;
+ g.ActiveIdHasBeenEditedThisFrame = false;
+ g.ActiveIdPreviousFrameIsAlive = false;
+ g.ActiveIdIsJustActivated = false;
+ if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
+ g.TempInputId = 0;
+ if (g.ActiveId == 0)
+ {
+ g.ActiveIdUsingNavDirMask = 0x00;
+ g.ActiveIdUsingNavInputMask = 0x00;
+ g.ActiveIdUsingKeyInputMask = 0x00;
+ }
+
+ // Drag and drop
+ g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
+ g.DragDropAcceptIdCurr = 0;
+ g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
+ g.DragDropWithinSource = false;
+ g.DragDropWithinTarget = false;
+ g.DragDropHoldJustPressedId = 0;
+
+ // Close popups on focus lost (currently wip/opt-in)
+ //if (g.IO.AppFocusLost)
+ // ClosePopupsExceptModals();
+
+ // Clear buttons state when focus is lost
+ // (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)
+ if (g.IO.AppFocusLost)
+ {
+ g.IO.ClearInputKeys();
+ g.IO.AppFocusLost = false;
+ }
+
+ // Update keyboard input state
+ // Synchronize io.KeyMods with individual modifiers io.KeyXXX bools
+ g.IO.KeyMods = GetMergedKeyModFlags();
+ memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));
+ for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
+ g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f;
+
+ // Update gamepad/keyboard navigation
+ NavUpdate();
+
+ // Update mouse input state
+ UpdateMouseInputs();
+
+ // Find hovered window
+ // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame)
+ UpdateHoveredWindowAndCaptureFlags();
+
+ // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
+ UpdateMouseMovingWindowNewFrame();
+
+ // Background darkening/whitening
+ if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f))
+ g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f);
+ else
+ g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f);
+
+ g.MouseCursor = ImGuiMouseCursor_Arrow;
+ g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
+ g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
+
+ // Mouse wheel scrolling, scale
+ UpdateMouseWheel();
+
+ // Mark all windows as not visible and compact unused memory.
+ IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
+ const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ window->WasActive = window->Active;
+ window->BeginCount = 0;
+ window->Active = false;
+ window->WriteAccessed = false;
+
+ // Garbage collect transient buffers of recently unused windows
+ if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
+ GcCompactTransientWindowBuffers(window);
+ }
+
+ // Garbage collect transient buffers of recently unused tables
+ for (int i = 0; i < g.TablesLastTimeActive.Size; i++)
+ if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time)
+ TableGcCompactTransientBuffers(g.Tables.GetByIndex(i));
+ for (int i = 0; i < g.TablesTempData.Size; i++)
+ if (g.TablesTempData[i].LastTimeActive >= 0.0f && g.TablesTempData[i].LastTimeActive < memory_compact_start_time)
+ TableGcCompactTransientBuffers(&g.TablesTempData[i]);
+ if (g.GcCompactAll)
+ GcCompactTransientMiscBuffers();
+ g.GcCompactAll = false;
+
+ // Closing the focused window restore focus to the first active root window in descending z-order
+ if (g.NavWindow && !g.NavWindow->WasActive)
+ FocusTopMostWindowUnderOne(NULL, NULL);
+
+ // No window should be open at the beginning of the frame.
+ // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
+ g.CurrentWindowStack.resize(0);
+ g.BeginPopupStack.resize(0);
+ g.ItemFlagsStack.resize(0);
+ g.ItemFlagsStack.push_back(ImGuiItemFlags_None);
+ g.GroupStack.resize(0);
+
+ // [DEBUG] Update debug features
+ UpdateDebugToolItemPicker();
+ UpdateDebugToolStackQueries();
+
+ // Create implicit/fallback window - which we will only render it if the user has added something to it.
+ // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
+ // This fallback is particularly important as it avoid ImGui:: calls from crashing.
+ g.WithinFrameScopeWithImplicitWindow = true;
+ SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
+ Begin("Debug##Default");
+ IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true);
+
+ CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
+}
+
+void ImGui::Initialize(ImGuiContext* context)
+{
+ ImGuiContext& g = *context;
+ IM_ASSERT(!g.Initialized && !g.SettingsLoaded);
+
+ // Add .ini handle for ImGuiWindow type
+ {
+ ImGuiSettingsHandler ini_handler;
+ ini_handler.TypeName = "Window";
+ ini_handler.TypeHash = ImHashStr("Window");
+ ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll;
+ ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen;
+ ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine;
+ ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll;
+ ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll;
+ g.SettingsHandlers.push_back(ini_handler);
+ }
+
+ // Add .ini handle for ImGuiTable type
+ TableSettingsInstallHandler(context);
+
+ // Create default viewport
+ ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
+ g.Viewports.push_back(viewport);
+
+#ifdef IMGUI_HAS_DOCK
+#endif
+
+ g.Initialized = true;
+}
+
+// This function is merely here to free heap allocations.
+void ImGui::Shutdown(ImGuiContext* context)
+{
+ // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
+ ImGuiContext& g = *context;
+ if (g.IO.Fonts && g.FontAtlasOwnedByContext)
+ {
+ g.IO.Fonts->Locked = false;
+ IM_DELETE(g.IO.Fonts);
+ }
+ g.IO.Fonts = NULL;
+
+ // Cleanup of other data are conditional on actually having initialized Dear ImGui.
+ if (!g.Initialized)
+ return;
+
+ // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file)
+ if (g.SettingsLoaded && g.IO.IniFilename != NULL)
+ {
+ ImGuiContext* backup_context = GImGui;
+ SetCurrentContext(&g);
+ SaveIniSettingsToDisk(g.IO.IniFilename);
+ SetCurrentContext(backup_context);
+ }
+
+ CallContextHooks(&g, ImGuiContextHookType_Shutdown);
+
+ // Clear everything else
+ g.Windows.clear_delete();
+ g.WindowsFocusOrder.clear();
+ g.WindowsTempSortBuffer.clear();
+ g.CurrentWindow = NULL;
+ g.CurrentWindowStack.clear();
+ g.WindowsById.Clear();
+ g.NavWindow = NULL;
+ g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
+ g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
+ g.MovingWindow = NULL;
+ g.ColorStack.clear();
+ g.StyleVarStack.clear();
+ g.FontStack.clear();
+ g.OpenPopupStack.clear();
+ g.BeginPopupStack.clear();
+
+ g.Viewports.clear_delete();
+
+ g.TabBars.Clear();
+ g.CurrentTabBarStack.clear();
+ g.ShrinkWidthBuffer.clear();
+
+ g.ClipperTempData.clear_destruct();
+
+ g.Tables.Clear();
+ g.TablesTempData.clear_destruct();
+ g.DrawChannelsTempMergeBuffer.clear();
+
+ g.ClipboardHandlerData.clear();
+ g.MenusIdSubmittedThisFrame.clear();
+ g.InputTextState.ClearFreeMemory();
+
+ g.SettingsWindows.clear();
+ g.SettingsHandlers.clear();
+
+ if (g.LogFile)
+ {
+#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
+ if (g.LogFile != stdout)
+#endif
+ ImFileClose(g.LogFile);
+ g.LogFile = NULL;
+ }
+ g.LogBuffer.clear();
+
+ g.Initialized = false;
+}
+
+// FIXME: Add a more explicit sort order in the window structure.
+static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs)
+{
+ const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs;
+ const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs;
+ if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
+ return d;
+ if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
+ return d;
+ return (a->BeginOrderWithinParent - b->BeginOrderWithinParent);
+}
+
+static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
+{
+ out_sorted_windows->push_back(window);
+ if (window->Active)
+ {
+ int count = window->DC.ChildWindows.Size;
+ if (count > 1)
+ ImQsort(window->DC.ChildWindows.Data, (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);
+ for (int i = 0; i < count; i++)
+ {
+ ImGuiWindow* child = window->DC.ChildWindows[i];
+ if (child->Active)
+ AddWindowToSortBuffer(out_sorted_windows, child);
+ }
+ }
+}
+
+static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* draw_list)
+{
+ // Remove trailing command if unused.
+ // Technically we could return directly instead of popping, but this make things looks neat in Metrics/Debugger window as well.
+ draw_list->_PopUnusedDrawCmd();
+ if (draw_list->CmdBuffer.Size == 0)
+ return;
+
+ // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
+ // May trigger for you if you are using PrimXXX functions incorrectly.
+ IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
+ IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
+ if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset))
+ IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);
+
+ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
+ // If this assert triggers because you are drawing lots of stuff manually:
+ // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
+ // Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics/Debugger window to inspect draw list contents.
+ // - If you want large meshes with more than 64K vertices, you can either:
+ // (A) Handle the ImDrawCmd::VtxOffset value in your renderer backend, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
+ // Most example backends already support this from 1.71. Pre-1.71 backends won't.
+ // Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them.
+ // (B) Or handle 32-bit indices in your renderer backend, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
+ // Most example backends already support this. For example, the OpenGL example code detect index size at compile-time:
+ // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
+ // Your own engine or render API may use different parameters or function calls to specify index sizes.
+ // 2 and 4 bytes indices are generally supported by most graphics API.
+ // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
+ // the 64K limit to split your draw commands in multiple draw lists.
+ if (sizeof(ImDrawIdx) == 2)
+ IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
+
+ out_list->push_back(draw_list);
+}
+
+static void AddWindowToDrawData(ImGuiWindow* window, int layer)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiViewportP* viewport = g.Viewports[0];
+ g.IO.MetricsRenderWindows++;
+ AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[layer], window->DrawList);
+ for (int i = 0; i < window->DC.ChildWindows.Size; i++)
+ {
+ ImGuiWindow* child = window->DC.ChildWindows[i];
+ if (IsWindowActiveAndVisible(child)) // Clipped children may have been marked not active
+ AddWindowToDrawData(child, layer);
+ }
+}
+
+static inline int GetWindowDisplayLayer(ImGuiWindow* window)
+{
+ return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0;
+}
+
+// Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu)
+static inline void AddRootWindowToDrawData(ImGuiWindow* window)
+{
+ AddWindowToDrawData(window, GetWindowDisplayLayer(window));
+}
+
+void ImDrawDataBuilder::FlattenIntoSingleLayer()
+{
+ int n = Layers[0].Size;
+ int size = n;
+ for (int i = 1; i < IM_ARRAYSIZE(Layers); i++)
+ size += Layers[i].Size;
+ Layers[0].resize(size);
+ for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++)
+ {
+ ImVector<ImDrawList*>& layer = Layers[layer_n];
+ if (layer.empty())
+ continue;
+ memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
+ n += layer.Size;
+ layer.resize(0);
+ }
+}
+
+static void SetupViewportDrawData(ImGuiViewportP* viewport, ImVector<ImDrawList*>* draw_lists)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImDrawData* draw_data = &viewport->DrawDataP;
+ draw_data->Valid = true;
+ draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL;
+ draw_data->CmdListsCount = draw_lists->Size;
+ draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0;
+ draw_data->DisplayPos = viewport->Pos;
+ draw_data->DisplaySize = viewport->Size;
+ draw_data->FramebufferScale = io.DisplayFramebufferScale;
+ for (int n = 0; n < draw_lists->Size; n++)
+ {
+ draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size;
+ draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size;
+ }
+}
+
+// Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering.
+// - When using this function it is sane to ensure that float are perfectly rounded to integer values,
+// so that e.g. (int)(max.x-min.x) in user's render produce correct result.
+// - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect():
+// some frequently called functions which to modify both channels and clipping simultaneously tend to use the
+// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds.
+void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
+ window->ClipRect = window->DrawList->_ClipRectStack.back();
+}
+
+void ImGui::PopClipRect()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DrawList->PopClipRect();
+ window->ClipRect = window->DrawList->_ClipRectStack.back();
+}
+
+// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
+void ImGui::EndFrame()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Initialized);
+
+ // Don't process EndFrame() multiple times.
+ if (g.FrameCountEnded == g.FrameCount)
+ return;
+ IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?");
+
+ CallContextHooks(&g, ImGuiContextHookType_EndFramePre);
+
+ ErrorCheckEndFrameSanityChecks();
+
+ // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
+ if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f))
+ {
+ g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImePos.y);
+ g.PlatformImeLastPos = g.PlatformImePos;
+ }
+
+ // Hide implicit/fallback "Debug" window if it hasn't been used
+ g.WithinFrameScopeWithImplicitWindow = false;
+ if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
+ g.CurrentWindow->Active = false;
+ End();
+
+ // Update navigation: CTRL+Tab, wrap-around requests
+ NavEndFrame();
+
+ // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
+ if (g.DragDropActive)
+ {
+ bool is_delivered = g.DragDropPayload.Delivery;
+ bool is_elapsed = (g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) && ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(g.DragDropMouseButton));
+ if (is_delivered || is_elapsed)
+ ClearDragDrop();
+ }
+
+ // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing.
+ if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+ {
+ g.DragDropWithinSource = true;
+ SetTooltip("...");
+ g.DragDropWithinSource = false;
+ }
+
+ // End frame
+ g.WithinFrameScope = false;
+ g.FrameCountEnded = g.FrameCount;
+
+ // Initiate moving window + handle left-click and right-click focus
+ UpdateMouseMovingWindowEndFrame();
+
+ // Sort the window list so that all child windows are after their parent
+ // We cannot do that on FocusWindow() because children may not exist yet
+ g.WindowsTempSortBuffer.resize(0);
+ g.WindowsTempSortBuffer.reserve(g.Windows.Size);
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
+ continue;
+ AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window);
+ }
+
+ // This usually assert if there is a mismatch between the ImGuiWindowFlags_ChildWindow / ParentWindow values and DC.ChildWindows[] in parents, aka we've done something wrong.
+ IM_ASSERT(g.Windows.Size == g.WindowsTempSortBuffer.Size);
+ g.Windows.swap(g.WindowsTempSortBuffer);
+ g.IO.MetricsActiveWindows = g.WindowsActiveCount;
+
+ // Unlock font atlas
+ g.IO.Fonts->Locked = false;
+
+ // Clear Input data for next frame
+ g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f;
+ g.IO.InputQueueCharacters.resize(0);
+ g.IO.KeyModsPrev = g.IO.KeyMods; // doing it here is better than in NewFrame() as we'll tolerate backend writing to KeyMods. If we want to firmly disallow it we should detect it.
+ memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs));
+
+ CallContextHooks(&g, ImGuiContextHookType_EndFramePost);
+}
+
+// Prepare the data for rendering so you can call GetDrawData()
+// (As with anything within the ImGui:: namspace this doesn't touch your GPU or graphics API at all:
+// it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend)
+void ImGui::Render()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Initialized);
+
+ if (g.FrameCountEnded != g.FrameCount)
+ EndFrame();
+ g.FrameCountRendered = g.FrameCount;
+ g.IO.MetricsRenderWindows = 0;
+
+ CallContextHooks(&g, ImGuiContextHookType_RenderPre);
+
+ // Add background ImDrawList (for each active viewport)
+ for (int n = 0; n != g.Viewports.Size; n++)
+ {
+ ImGuiViewportP* viewport = g.Viewports[n];
+ viewport->DrawDataBuilder.Clear();
+ if (viewport->DrawLists[0] != NULL)
+ AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
+ }
+
+ // Add ImDrawList to render
+ ImGuiWindow* windows_to_render_top_most[2];
+ windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL;
+ windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL);
+ for (int n = 0; n != g.Windows.Size; n++)
+ {
+ ImGuiWindow* window = g.Windows[n];
+ IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'"
+ if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
+ AddRootWindowToDrawData(window);
+ }
+ for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++)
+ if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window
+ AddRootWindowToDrawData(windows_to_render_top_most[n]);
+
+ // Setup ImDrawData structures for end-user
+ g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0;
+ for (int n = 0; n < g.Viewports.Size; n++)
+ {
+ ImGuiViewportP* viewport = g.Viewports[n];
+ viewport->DrawDataBuilder.FlattenIntoSingleLayer();
+
+ // Draw software mouse cursor if requested by io.MouseDrawCursor flag
+ if (g.IO.MouseDrawCursor)
+ RenderMouseCursor(GetForegroundDrawList(viewport), g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48));
+
+ // Add foreground ImDrawList (for each active viewport)
+ if (viewport->DrawLists[1] != NULL)
+ AddDrawListToDrawData(&viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
+
+ SetupViewportDrawData(viewport, &viewport->DrawDataBuilder.Layers[0]);
+ ImDrawData* draw_data = &viewport->DrawDataP;
+ g.IO.MetricsRenderVertices += draw_data->TotalVtxCount;
+ g.IO.MetricsRenderIndices += draw_data->TotalIdxCount;
+ }
+
+ CallContextHooks(&g, ImGuiContextHookType_RenderPost);
+}
+
+// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
+// CalcTextSize("") should return ImVec2(0.0f, g.FontSize)
+ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
+{
+ ImGuiContext& g = *GImGui;
+
+ const char* text_display_end;
+ if (hide_text_after_double_hash)
+ text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string
+ else
+ text_display_end = text_end;
+
+ ImFont* font = g.Font;
+ const float font_size = g.FontSize;
+ if (text == text_display_end)
+ return ImVec2(0.0f, font_size);
+ ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);
+
+ // Round
+ // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out.
+ // FIXME: Investigate using ceilf or e.g.
+ // - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
+ // - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html
+ text_size.x = IM_FLOOR(text_size.x + 0.99999f);
+
+ return text_size;
+}
+
+// Find window given position, search front-to-back
+// FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programmatically
+// with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is
+// called, aka before the next Begin(). Moving window isn't affected.
+static void FindHoveredWindow()
+{
+ ImGuiContext& g = *GImGui;
+
+ ImGuiWindow* hovered_window = NULL;
+ ImGuiWindow* hovered_window_ignoring_moving_window = NULL;
+ if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
+ hovered_window = g.MovingWindow;
+
+ ImVec2 padding_regular = g.Style.TouchExtraPadding;
+ ImVec2 padding_for_resize = g.IO.ConfigWindowsResizeFromEdges ? g.WindowsHoverPadding : padding_regular;
+ for (int i = g.Windows.Size - 1; i >= 0; i--)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
+ if (!window->Active || window->Hidden)
+ continue;
+ if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
+ continue;
+
+ // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
+ ImRect bb(window->OuterRectClipped);
+ if (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize))
+ bb.Expand(padding_regular);
+ else
+ bb.Expand(padding_for_resize);
+ if (!bb.Contains(g.IO.MousePos))
+ continue;
+
+ // Support for one rectangular hole in any given window
+ // FIXME: Consider generalizing hit-testing override (with more generic data, callback, etc.) (#1512)
+ if (window->HitTestHoleSize.x != 0)
+ {
+ ImVec2 hole_pos(window->Pos.x + (float)window->HitTestHoleOffset.x, window->Pos.y + (float)window->HitTestHoleOffset.y);
+ ImVec2 hole_size((float)window->HitTestHoleSize.x, (float)window->HitTestHoleSize.y);
+ if (ImRect(hole_pos, hole_pos + hole_size).Contains(g.IO.MousePos))
+ continue;
+ }
+
+ if (hovered_window == NULL)
+ hovered_window = window;
+ IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
+ if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow))
+ hovered_window_ignoring_moving_window = window;
+ if (hovered_window && hovered_window_ignoring_moving_window)
+ break;
+ }
+
+ g.HoveredWindow = hovered_window;
+ g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
+}
+
+// Test if mouse cursor is hovering given rectangle
+// NB- Rectangle is clipped by our current clip setting
+// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
+bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Clip
+ ImRect rect_clipped(r_min, r_max);
+ if (clip)
+ rect_clipped.ClipWith(g.CurrentWindow->ClipRect);
+
+ // Expand for touch input
+ const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
+ if (!rect_for_touch.Contains(g.IO.MousePos))
+ return false;
+ return true;
+}
+
+int ImGui::GetKeyIndex(ImGuiKey imgui_key)
+{
+ IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
+ ImGuiContext& g = *GImGui;
+ return g.IO.KeyMap[imgui_key];
+}
+
+// Note that dear imgui doesn't know the semantic of each entry of io.KeysDown[]!
+// Use your own indices/enums according to how your backend/engine stored them into io.KeysDown[]!
+bool ImGui::IsKeyDown(int user_key_index)
+{
+ if (user_key_index < 0)
+ return false;
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ return g.IO.KeysDown[user_key_index];
+}
+
+// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime)
+// t1 = current time (e.g.: g.Time)
+// An event is triggered at:
+// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N
+int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate)
+{
+ if (t1 == 0.0f)
+ return 1;
+ if (t0 >= t1)
+ return 0;
+ if (repeat_rate <= 0.0f)
+ return (t0 < repeat_delay) && (t1 >= repeat_delay);
+ const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate);
+ const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate);
+ const int count = count_t1 - count_t0;
+ return count;
+}
+
+int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate)
+{
+ ImGuiContext& g = *GImGui;
+ if (key_index < 0)
+ return 0;
+ IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ const float t = g.IO.KeysDownDuration[key_index];
+ return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate);
+}
+
+bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
+{
+ ImGuiContext& g = *GImGui;
+ if (user_key_index < 0)
+ return false;
+ IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ const float t = g.IO.KeysDownDuration[user_key_index];
+ if (t == 0.0f)
+ return true;
+ if (repeat && t > g.IO.KeyRepeatDelay)
+ return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
+ return false;
+}
+
+bool ImGui::IsKeyReleased(int user_key_index)
+{
+ ImGuiContext& g = *GImGui;
+ if (user_key_index < 0) return false;
+ IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
+ return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index];
+}
+
+bool ImGui::IsMouseDown(ImGuiMouseButton button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseDown[button];
+}
+
+bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ const float t = g.IO.MouseDownDuration[button];
+ if (t == 0.0f)
+ return true;
+
+ if (repeat && t > g.IO.KeyRepeatDelay)
+ {
+ // FIXME: 2019/05/03: Our old repeat code was wrong here and led to doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
+ int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate * 0.50f);
+ if (amount > 0)
+ return true;
+ }
+ return false;
+}
+
+bool ImGui::IsMouseReleased(ImGuiMouseButton button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseReleased[button];
+}
+
+bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseClickedCount[button] == 2;
+}
+
+bool ImGui::IsMouseTripleClicked(ImGuiMouseButton button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ return g.IO.MouseClickedCount[button] == 3;
+}
+
+// Return if a mouse click/drag went past the given threshold. Valid to call during the MouseReleased frame.
+// [Internal] This doesn't test if the button is pressed
+bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ if (lock_threshold < 0.0f)
+ lock_threshold = g.IO.MouseDragThreshold;
+ return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
+}
+
+bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ if (!g.IO.MouseDown[button])
+ return false;
+ return IsMouseDragPastThreshold(button, lock_threshold);
+}
+
+ImVec2 ImGui::GetMousePos()
+{
+ ImGuiContext& g = *GImGui;
+ return g.IO.MousePos;
+}
+
+// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
+ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.BeginPopupStack.Size > 0)
+ return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos;
+ return g.IO.MousePos;
+}
+
+// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position.
+bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
+{
+ // The assert is only to silence a false-positive in XCode Static Analysis.
+ // Because GImGui is not dereferenced in every code path, the static analyzer assume that it may be NULL (which it doesn't for other functions).
+ IM_ASSERT(GImGui != NULL);
+ const float MOUSE_INVALID = -256000.0f;
+ ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos;
+ return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID;
+}
+
+bool ImGui::IsAnyMouseDown()
+{
+ ImGuiContext& g = *GImGui;
+ for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++)
+ if (g.IO.MouseDown[n])
+ return true;
+ return false;
+}
+
+// Return the delta from the initial clicking position while the mouse button is clicked or was just released.
+// This is locked and return 0.0f until the mouse moves past a distance threshold at least once.
+// NB: This is only valid if IsMousePosValid(). backends in theory should always keep mouse position valid when dragging even outside the client window.
+ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ if (lock_threshold < 0.0f)
+ lock_threshold = g.IO.MouseDragThreshold;
+ if (g.IO.MouseDown[button] || g.IO.MouseReleased[button])
+ if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
+ if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[button]))
+ return g.IO.MousePos - g.IO.MouseClickedPos[button];
+ return ImVec2(0.0f, 0.0f);
+}
+
+void ImGui::ResetMouseDragDelta(ImGuiMouseButton button)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
+ // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
+ g.IO.MouseClickedPos[button] = g.IO.MousePos;
+}
+
+ImGuiMouseCursor ImGui::GetMouseCursor()
+{
+ return GImGui->MouseCursor;
+}
+
+void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
+{
+ GImGui->MouseCursor = cursor_type;
+}
+
+void ImGui::CaptureKeyboardFromApp(bool capture)
+{
+ GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0;
+}
+
+void ImGui::CaptureMouseFromApp(bool capture)
+{
+ GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0;
+}
+
+bool ImGui::IsItemActive()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId)
+ return g.ActiveId == g.LastItemData.ID;
+ return false;
+}
+
+bool ImGui::IsItemActivated()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId)
+ if (g.ActiveId == g.LastItemData.ID && g.ActiveIdPreviousFrame != g.LastItemData.ID)
+ return true;
+ return false;
+}
+
+bool ImGui::IsItemDeactivated()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated)
+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0;
+ return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID);
+}
+
+bool ImGui::IsItemDeactivatedAfterEdit()
+{
+ ImGuiContext& g = *GImGui;
+ return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore));
+}
+
+// == GetItemID() == GetFocusID()
+bool ImGui::IsItemFocused()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.NavId != g.LastItemData.ID || g.NavId == 0)
+ return false;
+ return true;
+}
+
+// Important: this can be useful but it is NOT equivalent to the behavior of e.g.Button()!
+// Most widgets have specific reactions based on mouse-up/down state, mouse position etc.
+bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button)
+{
+ return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
+}
+
+bool ImGui::IsItemToggledOpen()
+{
+ ImGuiContext& g = *GImGui;
+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false;
+}
+
+bool ImGui::IsItemToggledSelection()
+{
+ ImGuiContext& g = *GImGui;
+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false;
+}
+
+bool ImGui::IsAnyItemHovered()
+{
+ ImGuiContext& g = *GImGui;
+ return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0;
+}
+
+bool ImGui::IsAnyItemActive()
+{
+ ImGuiContext& g = *GImGui;
+ return g.ActiveId != 0;
+}
+
+bool ImGui::IsAnyItemFocused()
+{
+ ImGuiContext& g = *GImGui;
+ return g.NavId != 0 && !g.NavDisableHighlight;
+}
+
+bool ImGui::IsItemVisible()
+{
+ ImGuiContext& g = *GImGui;
+ return g.CurrentWindow->ClipRect.Overlaps(g.LastItemData.Rect);
+}
+
+bool ImGui::IsItemEdited()
+{
+ ImGuiContext& g = *GImGui;
+ return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0;
+}
+
+// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
+// FIXME: Although this is exposed, its interaction and ideal idiom with using ImGuiButtonFlags_AllowItemOverlap flag are extremely confusing, need rework.
+void ImGui::SetItemAllowOverlap()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiID id = g.LastItemData.ID;
+ if (g.HoveredId == id)
+ g.HoveredIdAllowOverlap = true;
+ if (g.ActiveId == id)
+ g.ActiveIdAllowOverlap = true;
+}
+
+void ImGui::SetItemUsingMouseWheel()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiID id = g.LastItemData.ID;
+ if (g.HoveredId == id)
+ g.HoveredIdUsingMouseWheel = true;
+ if (g.ActiveId == id)
+ g.ActiveIdUsingMouseWheel = true;
+}
+
+void ImGui::SetActiveIdUsingNavAndKeys()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.ActiveId != 0);
+ g.ActiveIdUsingNavDirMask = ~(ImU32)0;
+ g.ActiveIdUsingNavInputMask = ~(ImU32)0;
+ g.ActiveIdUsingKeyInputMask = ~(ImU64)0;
+ NavMoveRequestCancel();
+}
+
+ImVec2 ImGui::GetItemRectMin()
+{
+ ImGuiContext& g = *GImGui;
+ return g.LastItemData.Rect.Min;
+}
+
+ImVec2 ImGui::GetItemRectMax()
+{
+ ImGuiContext& g = *GImGui;
+ return g.LastItemData.Rect.Max;
+}
+
+ImVec2 ImGui::GetItemRectSize()
+{
+ ImGuiContext& g = *GImGui;
+ return g.LastItemData.Rect.GetSize();
+}
+
+bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* parent_window = g.CurrentWindow;
+
+ flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow;
+ flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
+
+ // Size
+ const ImVec2 content_avail = GetContentRegionAvail();
+ ImVec2 size = ImFloor(size_arg);
+ const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
+ if (size.x <= 0.0f)
+ size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues)
+ if (size.y <= 0.0f)
+ size.y = ImMax(content_avail.y + size.y, 4.0f);
+ SetNextWindowSize(size);
+
+ // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value.
+ if (name)
+ ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%s/%s_%08X", parent_window->Name, name, id);
+ else
+ ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%s/%08X", parent_window->Name, id);
+
+ const float backup_border_size = g.Style.ChildBorderSize;
+ if (!border)
+ g.Style.ChildBorderSize = 0.0f;
+ bool ret = Begin(g.TempBuffer, NULL, flags);
+ g.Style.ChildBorderSize = backup_border_size;
+
+ ImGuiWindow* child_window = g.CurrentWindow;
+ child_window->ChildId = id;
+ child_window->AutoFitChildAxises = (ImS8)auto_fit_axises;
+
+ // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
+ // While this is not really documented/defined, it seems that the expected thing to do.
+ if (child_window->BeginCount == 1)
+ parent_window->DC.CursorPos = child_window->Pos;
+
+ // Process navigation-in immediately so NavInit can run on first frame
+ if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavHasScroll))
+ {
+ FocusWindow(child_window);
+ NavInitWindow(child_window, false);
+ SetActiveID(id + 1, child_window); // Steal ActiveId with another arbitrary id so that key-press won't activate child item
+ g.ActiveIdSource = ImGuiInputSource_Nav;
+ }
+ return ret;
+}
+
+bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
+}
+
+bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
+{
+ IM_ASSERT(id != 0);
+ return BeginChildEx(NULL, id, size_arg, border, extra_flags);
+}
+
+void ImGui::EndChild()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ IM_ASSERT(g.WithinEndChild == false);
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls
+
+ g.WithinEndChild = true;
+ if (window->BeginCount > 1)
+ {
+ End();
+ }
+ else
+ {
+ ImVec2 sz = window->Size;
+ if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
+ sz.x = ImMax(4.0f, sz.x);
+ if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
+ sz.y = ImMax(4.0f, sz.y);
+ End();
+
+ ImGuiWindow* parent_window = g.CurrentWindow;
+ ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
+ ItemSize(sz);
+ if ((window->DC.NavLayersActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
+ {
+ ItemAdd(bb, window->ChildId);
+ RenderNavHighlight(bb, window->ChildId);
+
+ // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
+ if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow)
+ RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
+ }
+ else
+ {
+ // Not navigable into
+ ItemAdd(bb, 0);
+ }
+ if (g.HoveredWindow == window)
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
+ }
+ g.WithinEndChild = false;
+ g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
+}
+
+// Helper to create a child window / scrolling region that looks like a normal widget frame.
+bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
+ PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
+ PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
+ PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
+ bool ret = BeginChild(id, size, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);
+ PopStyleVar(3);
+ PopStyleColor();
+ return ret;
+}
+
+void ImGui::EndChildFrame()
+{
+ EndChild();
+}
+
+static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
+{
+ window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
+ window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
+ window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
+}
+
+ImGuiWindow* ImGui::FindWindowByID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id);
+}
+
+ImGuiWindow* ImGui::FindWindowByName(const char* name)
+{
+ ImGuiID id = ImHashStr(name);
+ return FindWindowByID(id);
+}
+
+static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
+{
+ window->Pos = ImFloor(ImVec2(settings->Pos.x, settings->Pos.y));
+ if (settings->Size.x > 0 && settings->Size.y > 0)
+ window->Size = window->SizeFull = ImFloor(ImVec2(settings->Size.x, settings->Size.y));
+ window->Collapsed = settings->Collapsed;
+}
+
+static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ //IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags);
+
+ // Create window the first time
+ ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
+ window->Flags = flags;
+ g.WindowsById.SetVoidPtr(window->ID, window);
+
+ // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
+ const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
+ window->Pos = main_viewport->Pos + ImVec2(60, 60);
+
+ // User can disable loading and saving of settings. Tooltip and child windows also don't store settings.
+ if (!(flags & ImGuiWindowFlags_NoSavedSettings))
+ if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
+ {
+ // Retrieve settings from .ini file
+ window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
+ SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
+ ApplyWindowSettings(window, settings);
+ }
+ window->DC.CursorStartPos = window->DC.CursorMaxPos = window->Pos; // So first call to CalcContentSize() doesn't return crazy values
+
+ if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
+ {
+ window->AutoFitFramesX = window->AutoFitFramesY = 2;
+ window->AutoFitOnlyGrows = false;
+ }
+ else
+ {
+ if (window->Size.x <= 0.0f)
+ window->AutoFitFramesX = 2;
+ if (window->Size.y <= 0.0f)
+ window->AutoFitFramesY = 2;
+ window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
+ }
+
+ if (!(flags & ImGuiWindowFlags_ChildWindow))
+ {
+ g.WindowsFocusOrder.push_back(window);
+ window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
+ }
+
+ if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
+ g.Windows.push_front(window); // Quite slow but rare and only once
+ else
+ g.Windows.push_back(window);
+ return window;
+}
+
+static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& size_desired)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 new_size = size_desired;
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
+ {
+ // Using -1,-1 on either X/Y axis to preserve the current size.
+ ImRect cr = g.NextWindowData.SizeConstraintRect;
+ new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
+ new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
+ if (g.NextWindowData.SizeCallback)
+ {
+ ImGuiSizeCallbackData data;
+ data.UserData = g.NextWindowData.SizeCallbackUserData;
+ data.Pos = window->Pos;
+ data.CurrentSize = window->SizeFull;
+ data.DesiredSize = new_size;
+ g.NextWindowData.SizeCallback(&data);
+ new_size = data.DesiredSize;
+ }
+ new_size.x = IM_FLOOR(new_size.x);
+ new_size.y = IM_FLOOR(new_size.y);
+ }
+
+ // Minimum size
+ if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
+ {
+ ImGuiWindow* window_for_height = window;
+ const float decoration_up_height = window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight();
+ new_size = ImMax(new_size, g.Style.WindowMinSize);
+ new_size.y = ImMax(new_size.y, decoration_up_height + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows
+ }
+ return new_size;
+}
+
+static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal)
+{
+ bool preserve_old_content_sizes = false;
+ if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
+ preserve_old_content_sizes = true;
+ else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0)
+ preserve_old_content_sizes = true;
+ if (preserve_old_content_sizes)
+ {
+ *content_size_current = window->ContentSize;
+ *content_size_ideal = window->ContentSizeIdeal;
+ return;
+ }
+
+ content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_FLOOR(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
+ content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_FLOOR(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
+ content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_FLOOR(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x);
+ content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_FLOOR(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y);
+}
+
+static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
+ ImVec2 size_pad = window->WindowPadding * 2.0f;
+ ImVec2 size_desired = size_contents + size_pad + ImVec2(0.0f, decoration_up_height);
+ if (window->Flags & ImGuiWindowFlags_Tooltip)
+ {
+ // Tooltip always resize
+ return size_desired;
+ }
+ else
+ {
+ // Maximum window size is determined by the viewport size or monitor size
+ const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0;
+ const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0;
+ ImVec2 size_min = style.WindowMinSize;
+ if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups)
+ size_min = ImMin(size_min, ImVec2(4.0f, 4.0f));
+
+ // FIXME-VIEWPORT-WORKAREA: May want to use GetWorkSize() instead of Size depending on the type of windows?
+ ImVec2 avail_size = ImGui::GetMainViewport()->Size;
+ ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, avail_size - style.DisplaySafeAreaPadding * 2.0f));
+
+ // When the window cannot fit all contents (either because of constraints, either because screen is too small),
+ // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding.
+ ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
+ bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - 0.0f < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
+ bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - decoration_up_height < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
+ if (will_have_scrollbar_x)
+ size_auto_fit.y += style.ScrollbarSize;
+ if (will_have_scrollbar_y)
+ size_auto_fit.x += style.ScrollbarSize;
+ return size_auto_fit;
+ }
+}
+
+ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window)
+{
+ ImVec2 size_contents_current;
+ ImVec2 size_contents_ideal;
+ CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal);
+ ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal);
+ ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit);
+ return size_final;
+}
+
+static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags)
+{
+ if (flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup))
+ return ImGuiCol_PopupBg;
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ return ImGuiCol_ChildBg;
+ return ImGuiCol_WindowBg;
+}
+
+static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
+{
+ ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left
+ ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right
+ ImVec2 size_expected = pos_max - pos_min;
+ ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected);
+ *out_pos = pos_min;
+ if (corner_norm.x == 0.0f)
+ out_pos->x -= (size_constrained.x - size_expected.x);
+ if (corner_norm.y == 0.0f)
+ out_pos->y -= (size_constrained.y - size_expected.y);
+ *out_size = size_constrained;
+}
+
+// Data for resizing from corner
+struct ImGuiResizeGripDef
+{
+ ImVec2 CornerPosN;
+ ImVec2 InnerDir;
+ int AngleMin12, AngleMax12;
+};
+static const ImGuiResizeGripDef resize_grip_def[4] =
+{
+ { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 }, // Lower-right
+ { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 }, // Lower-left
+ { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 }, // Upper-left (Unused)
+ { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 } // Upper-right (Unused)
+};
+
+// Data for resizing from borders
+struct ImGuiResizeBorderDef
+{
+ ImVec2 InnerDir;
+ ImVec2 SegmentN1, SegmentN2;
+ float OuterAngle;
+};
+static const ImGuiResizeBorderDef resize_border_def[4] =
+{
+ { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f }, // Left
+ { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f }, // Right
+ { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f }, // Up
+ { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f } // Down
+};
+
+static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
+{
+ ImRect rect = window->Rect();
+ if (thickness == 0.0f)
+ rect.Max -= ImVec2(1, 1);
+ if (border_n == ImGuiDir_Left) { return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); }
+ if (border_n == ImGuiDir_Right) { return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding); }
+ if (border_n == ImGuiDir_Up) { return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness); }
+ if (border_n == ImGuiDir_Down) { return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness); }
+ IM_ASSERT(0);
+ return ImRect();
+}
+
+// 0..3: corners (Lower-right, Lower-left, Unused, Unused)
+ImGuiID ImGui::GetWindowResizeCornerID(ImGuiWindow* window, int n)
+{
+ IM_ASSERT(n >= 0 && n < 4);
+ ImGuiID id = window->ID;
+ id = ImHashStr("#RESIZE", 0, id);
+ id = ImHashData(&n, sizeof(int), id);
+ return id;
+}
+
+// Borders (Left, Right, Up, Down)
+ImGuiID ImGui::GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir)
+{
+ IM_ASSERT(dir >= 0 && dir < 4);
+ int n = (int)dir + 4;
+ ImGuiID id = window->ID;
+ id = ImHashStr("#RESIZE", 0, id);
+ id = ImHashData(&n, sizeof(int), id);
+ return id;
+}
+
+// Handle resize for: Resize Grips, Borders, Gamepad
+// Return true when using auto-fit (double click on resize grip)
+static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindowFlags flags = window->Flags;
+
+ if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
+ return false;
+ if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window.
+ return false;
+
+ bool ret_auto_fit = false;
+ const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0;
+ const float grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
+ const float grip_hover_inner_size = IM_FLOOR(grip_draw_size * 0.75f);
+ const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f;
+
+ ImVec2 pos_target(FLT_MAX, FLT_MAX);
+ ImVec2 size_target(FLT_MAX, FLT_MAX);
+
+ // Resize grips and borders are on layer 1
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
+
+ // Manual resize grips
+ PushID("#RESIZE");
+ for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
+ {
+ const ImGuiResizeGripDef& def = resize_grip_def[resize_grip_n];
+ const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, def.CornerPosN);
+
+ // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
+ bool hovered, held;
+ ImRect resize_rect(corner - def.InnerDir * grip_hover_outer_size, corner + def.InnerDir * grip_hover_inner_size);
+ if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x);
+ if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y);
+ ImGuiID resize_grip_id = window->GetID(resize_grip_n); // == GetWindowResizeCornerID()
+ ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
+ //GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
+ if (hovered || held)
+ g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
+
+ if (held && g.IO.MouseClickedCount[0] == 2 && resize_grip_n == 0)
+ {
+ // Manual auto-fit when double-clicking
+ size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
+ ret_auto_fit = true;
+ ClearActiveID();
+ }
+ else if (held)
+ {
+ // Resize from any of the four corners
+ // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
+ ImVec2 clamp_min = ImVec2(def.CornerPosN.x == 1.0f ? visibility_rect.Min.x : -FLT_MAX, def.CornerPosN.y == 1.0f ? visibility_rect.Min.y : -FLT_MAX);
+ ImVec2 clamp_max = ImVec2(def.CornerPosN.x == 0.0f ? visibility_rect.Max.x : +FLT_MAX, def.CornerPosN.y == 0.0f ? visibility_rect.Max.y : +FLT_MAX);
+ ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(def.InnerDir * grip_hover_outer_size, def.InnerDir * -grip_hover_inner_size, def.CornerPosN); // Corner of the window corresponding to our corner grip
+ corner_target = ImClamp(corner_target, clamp_min, clamp_max);
+ CalcResizePosSizeFromAnyCorner(window, corner_target, def.CornerPosN, &pos_target, &size_target);
+ }
+
+ // Only lower-left grip is visible before hovering/activating
+ if (resize_grip_n == 0 || held || hovered)
+ resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
+ }
+ for (int border_n = 0; border_n < resize_border_count; border_n++)
+ {
+ const ImGuiResizeBorderDef& def = resize_border_def[border_n];
+ const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y;
+
+ bool hovered, held;
+ ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING);
+ ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID()
+ ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
+ //GetForegroundDrawLists(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
+ if ((hovered && g.HoveredIdTimer > WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) || held)
+ {
+ g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS;
+ if (held)
+ *border_held = border_n;
+ }
+ if (held)
+ {
+ ImVec2 clamp_min(border_n == ImGuiDir_Right ? visibility_rect.Min.x : -FLT_MAX, border_n == ImGuiDir_Down ? visibility_rect.Min.y : -FLT_MAX);
+ ImVec2 clamp_max(border_n == ImGuiDir_Left ? visibility_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? visibility_rect.Max.y : +FLT_MAX);
+ ImVec2 border_target = window->Pos;
+ border_target[axis] = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
+ border_target = ImClamp(border_target, clamp_min, clamp_max);
+ CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target);
+ }
+ }
+ PopID();
+
+ // Restore nav layer
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+
+ // Navigation resize (keyboard/gamepad)
+ if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
+ {
+ ImVec2 nav_resize_delta;
+ if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift)
+ nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiInputReadMode_Down);
+ if (g.NavInputSource == ImGuiInputSource_Gamepad)
+ nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down);
+ if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f)
+ {
+ const float NAV_RESIZE_SPEED = 600.0f;
+ nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y));
+ nav_resize_delta = ImMax(nav_resize_delta, visibility_rect.Min - window->Pos - window->Size);
+ g.NavWindowingToggleLayer = false;
+ g.NavDisableMouseHover = true;
+ resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive);
+ // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
+ size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + nav_resize_delta);
+ }
+ }
+
+ // Apply back modified position/size to window
+ if (size_target.x != FLT_MAX)
+ {
+ window->SizeFull = size_target;
+ MarkIniSettingsDirty(window);
+ }
+ if (pos_target.x != FLT_MAX)
+ {
+ window->Pos = ImFloor(pos_target);
+ MarkIniSettingsDirty(window);
+ }
+
+ window->Size = window->SizeFull;
+ return ret_auto_fit;
+}
+
+static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& visibility_rect)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 size_for_clamping = window->Size;
+ if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
+ size_for_clamping.y = window->TitleBarHeight();
+ window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max);
+}
+
+static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ float rounding = window->WindowRounding;
+ float border_size = window->WindowBorderSize;
+ if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
+ window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
+
+ int border_held = window->ResizeBorderHeld;
+ if (border_held != -1)
+ {
+ const ImGuiResizeBorderDef& def = resize_border_def[border_held];
+ ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f);
+ window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
+ window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
+ window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), 0, ImMax(2.0f, border_size)); // Thicker than usual
+ }
+ if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
+ {
+ float y = window->Pos.y + window->TitleBarHeight() - 1;
+ window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), GetColorU32(ImGuiCol_Border), g.Style.FrameBorderSize);
+ }
+}
+
+// Draw background and borders
+// Draw and handle scrollbars
+void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ ImGuiWindowFlags flags = window->Flags;
+
+ // Ensure that ScrollBar doesn't read last frame's SkipItems
+ IM_ASSERT(window->BeginCount == 0);
+ window->SkipItems = false;
+
+ // Draw window + handle manual resize
+ // As we highlight the title bar when want_focus is set, multiple reappearing windows will have have their title bar highlighted on their reappearing frame.
+ const float window_rounding = window->WindowRounding;
+ const float window_border_size = window->WindowBorderSize;
+ if (window->Collapsed)
+ {
+ // Title bar only
+ float backup_border_size = style.FrameBorderSize;
+ g.Style.FrameBorderSize = window->WindowBorderSize;
+ ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
+ RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
+ g.Style.FrameBorderSize = backup_border_size;
+ }
+ else
+ {
+ // Window background
+ if (!(flags & ImGuiWindowFlags_NoBackground))
+ {
+ ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
+ bool override_alpha = false;
+ float alpha = 1.0f;
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha)
+ {
+ alpha = g.NextWindowData.BgAlphaVal;
+ override_alpha = true;
+ }
+ if (override_alpha)
+ bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
+ window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom);
+ }
+
+ // Title bar
+ if (!(flags & ImGuiWindowFlags_NoTitleBar))
+ {
+ ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
+ window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop);
+ }
+
+ // Menu bar
+ if (flags & ImGuiWindowFlags_MenuBar)
+ {
+ ImRect menu_bar_rect = window->MenuBarRect();
+ menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
+ window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop);
+ if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
+ window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
+ }
+
+ // Scrollbars
+ if (window->ScrollbarX)
+ Scrollbar(ImGuiAxis_X);
+ if (window->ScrollbarY)
+ Scrollbar(ImGuiAxis_Y);
+
+ // Render resize grips (after their input handling so we don't have a frame of latency)
+ if (!(flags & ImGuiWindowFlags_NoResize))
+ {
+ for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
+ {
+ const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
+ const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
+ window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)));
+ window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size)));
+ window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
+ window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
+ }
+ }
+
+ // Borders
+ RenderWindowOuterBorders(window);
+ }
+}
+
+// Render title text, collapse button, close button
+void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ ImGuiWindowFlags flags = window->Flags;
+
+ const bool has_close_button = (p_open != NULL);
+ const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
+
+ // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
+ // FIXME-NAV: Might want (or not?) to set the equivalent of ImGuiButtonFlags_NoNavFocus so that mouse clicks on standard title bar items don't necessarily set nav/keyboard ref?
+ const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
+ g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
+
+ // Layout buttons
+ // FIXME: Would be nice to generalize the subtleties expressed here into reusable code.
+ float pad_l = style.FramePadding.x;
+ float pad_r = style.FramePadding.x;
+ float button_sz = g.FontSize;
+ ImVec2 close_button_pos;
+ ImVec2 collapse_button_pos;
+ if (has_close_button)
+ {
+ pad_r += button_sz;
+ close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y);
+ }
+ if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
+ {
+ pad_r += button_sz;
+ collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y);
+ }
+ if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
+ {
+ collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l - style.FramePadding.x, title_bar_rect.Min.y);
+ pad_l += button_sz;
+ }
+
+ // Collapse button (submitting first so it gets priority when choosing a navigation init fallback)
+ if (has_collapse_button)
+ if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos))
+ window->WantCollapseToggle = true; // Defer actual collapsing to next frame as we are too far in the Begin() function
+
+ // Close button
+ if (has_close_button)
+ if (CloseButton(window->GetID("#CLOSE"), close_button_pos))
+ *p_open = false;
+
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+ g.CurrentItemFlags = item_flags_backup;
+
+ // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
+ // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code..
+ const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f;
+ const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
+
+ // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button,
+ // while uncentered title text will still reach edges correctly.
+ if (pad_l > style.FramePadding.x)
+ pad_l += g.Style.ItemInnerSpacing.x;
+ if (pad_r > style.FramePadding.x)
+ pad_r += g.Style.ItemInnerSpacing.x;
+ if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
+ {
+ float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f); // 0.0f on either edges, 1.0f on center
+ float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
+ pad_l = ImMax(pad_l, pad_extend * centerness);
+ pad_r = ImMax(pad_r, pad_extend * centerness);
+ }
+
+ ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y);
+ ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y);
+ if (flags & ImGuiWindowFlags_UnsavedDocument)
+ {
+ ImVec2 marker_pos;
+ marker_pos.x = ImClamp(layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x + text_size.x, layout_r.Min.x, layout_r.Max.x);
+ marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
+ if (marker_pos.x > layout_r.Min.x)
+ {
+ RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
+ clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f));
+ }
+ }
+ //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
+ //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
+ RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
+}
+
+void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
+{
+ window->ParentWindow = parent_window;
+ window->RootWindow = window->RootWindowPopupTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
+ if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
+ window->RootWindow = parent_window->RootWindow;
+ if (parent_window && (flags & ImGuiWindowFlags_Popup))
+ window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
+ if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)))
+ window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
+ while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened)
+ {
+ IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
+ window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
+ }
+}
+
+// Push a new Dear ImGui window to add widgets to.
+// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
+// - Begin/End can be called multiple times during the frame with the same window name to append content.
+// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
+// You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file.
+// - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned.
+// - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed.
+bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ IM_ASSERT(name != NULL && name[0] != '\0'); // Window name required
+ IM_ASSERT(g.WithinFrameScope); // Forgot to call ImGui::NewFrame()
+ IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet
+
+ // Find or create
+ ImGuiWindow* window = FindWindowByName(name);
+ const bool window_just_created = (window == NULL);
+ if (window_just_created)
+ window = CreateNewWindow(name, flags);
+
+ // Automatically disable manual moving/resizing when NoInputs is set
+ if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs)
+ flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
+
+ if (flags & ImGuiWindowFlags_NavFlattened)
+ IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow);
+
+ const int current_frame = g.FrameCount;
+ const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
+ window->IsFallbackWindow = (g.CurrentWindowStack.Size == 0 && g.WithinFrameScopeWithImplicitWindow);
+
+ // Update the Appearing flag
+ bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
+ if (flags & ImGuiWindowFlags_Popup)
+ {
+ ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
+ window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed
+ window_just_activated_by_user |= (window != popup_ref.Window);
+ }
+ window->Appearing = window_just_activated_by_user;
+ if (window->Appearing)
+ SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true);
+
+ // Update Flags, LastFrameActive, BeginOrderXXX fields
+ if (first_begin_of_the_frame)
+ {
+ window->Flags = (ImGuiWindowFlags)flags;
+ window->LastFrameActive = current_frame;
+ window->LastTimeActive = (float)g.Time;
+ window->BeginOrderWithinParent = 0;
+ window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++);
+ }
+ else
+ {
+ flags = window->Flags;
+ }
+
+ // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
+ ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window;
+ ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
+ IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
+
+ // We allow window memory to be compacted so recreate the base stack when needed.
+ if (window->IDStack.Size == 0)
+ window->IDStack.push_back(window->ID);
+
+ // Add to stack
+ // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
+ g.CurrentWindow = window;
+ ImGuiWindowStackData window_stack_data;
+ window_stack_data.Window = window;
+ window_stack_data.ParentLastItemDataBackup = g.LastItemData;
+ window_stack_data.StackSizesOnBegin.SetToCurrentState();
+ g.CurrentWindowStack.push_back(window_stack_data);
+ g.CurrentWindow = NULL;
+
+ if (flags & ImGuiWindowFlags_Popup)
+ {
+ ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
+ popup_ref.Window = window;
+ g.BeginPopupStack.push_back(popup_ref);
+ window->PopupId = popup_ref.PopupId;
+ }
+
+ // Update ->RootWindow and others pointers (before any possible call to FocusWindow)
+ if (first_begin_of_the_frame)
+ UpdateWindowParentAndRootLinks(window, flags, parent_window);
+
+ // Process SetNextWindow***() calls
+ // (FIXME: Consider splitting the HasXXX flags into X/Y components
+ bool window_pos_set_by_api = false;
+ bool window_size_x_set_by_api = false, window_size_y_set_by_api = false;
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos)
+ {
+ window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
+ if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f)
+ {
+ // May be processed on the next frame if this is our first frame and we are measuring size
+ // FIXME: Look into removing the branch so everything can go through this same code path for consistency.
+ window->SetWindowPosVal = g.NextWindowData.PosVal;
+ window->SetWindowPosPivot = g.NextWindowData.PosPivotVal;
+ window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+ }
+ else
+ {
+ SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
+ }
+ }
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)
+ {
+ window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
+ window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
+ SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
+ }
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll)
+ {
+ if (g.NextWindowData.ScrollVal.x >= 0.0f)
+ {
+ window->ScrollTarget.x = g.NextWindowData.ScrollVal.x;
+ window->ScrollTargetCenterRatio.x = 0.0f;
+ }
+ if (g.NextWindowData.ScrollVal.y >= 0.0f)
+ {
+ window->ScrollTarget.y = g.NextWindowData.ScrollVal.y;
+ window->ScrollTargetCenterRatio.y = 0.0f;
+ }
+ }
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
+ window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal;
+ else if (first_begin_of_the_frame)
+ window->ContentSizeExplicit = ImVec2(0.0f, 0.0f);
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
+ SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
+ FocusWindow(window);
+ if (window->Appearing)
+ SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
+
+ // When reusing window again multiple times a frame, just append content (don't need to setup again)
+ if (first_begin_of_the_frame)
+ {
+ // Initialize
+ const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345)
+ window->Active = true;
+ window->HasCloseButton = (p_open != NULL);
+ window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX);
+ window->IDStack.resize(1);
+ window->DrawList->_ResetForNewFrame();
+ window->DC.CurrentTableIdx = -1;
+
+ // Restore buffer capacity when woken from a compacted state, to avoid
+ if (window->MemoryCompacted)
+ GcAwakeTransientWindowBuffers(window);
+
+ // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged).
+ // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere.
+ bool window_title_visible_elsewhere = false;
+ if (g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB
+ window_title_visible_elsewhere = true;
+ if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
+ {
+ size_t buf_len = (size_t)window->NameBufLen;
+ window->Name = ImStrdupcpy(window->Name, &buf_len, name);
+ window->NameBufLen = (int)buf_len;
+ }
+
+ // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
+
+ // Update contents size from last frame for auto-fitting (or use explicit size)
+ const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0);
+ CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal);
+ if (window->HiddenFramesCanSkipItems > 0)
+ window->HiddenFramesCanSkipItems--;
+ if (window->HiddenFramesCannotSkipItems > 0)
+ window->HiddenFramesCannotSkipItems--;
+ if (window->HiddenFramesForRenderOnly > 0)
+ window->HiddenFramesForRenderOnly--;
+
+ // Hide new windows for one frame until they calculate their size
+ if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api))
+ window->HiddenFramesCannotSkipItems = 1;
+
+ // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
+ // We reset Size/ContentSize for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
+ if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
+ {
+ window->HiddenFramesCannotSkipItems = 1;
+ if (flags & ImGuiWindowFlags_AlwaysAutoResize)
+ {
+ if (!window_size_x_set_by_api)
+ window->Size.x = window->SizeFull.x = 0.f;
+ if (!window_size_y_set_by_api)
+ window->Size.y = window->SizeFull.y = 0.f;
+ window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f);
+ }
+ }
+
+ // SELECT VIEWPORT
+ // FIXME-VIEWPORT: In the docking/viewport branch, this is the point where we select the current viewport (which may affect the style)
+ SetCurrentWindow(window);
+
+ // LOCK BORDER SIZE AND PADDING FOR THE FRAME (so that altering them doesn't cause inconsistencies)
+
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ window->WindowBorderSize = style.ChildBorderSize;
+ else
+ window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
+ window->WindowPadding = style.WindowPadding;
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
+ window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
+
+ // Lock menu offset so size calculation can use it as menu-bar windows need a minimum size.
+ window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
+ window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
+
+ // Collapse window by double-clicking on title bar
+ // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
+ if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
+ {
+ // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar.
+ ImRect title_bar_rect = window->TitleBarRect();
+ if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseClickedCount[0] == 2)
+ window->WantCollapseToggle = true;
+ if (window->WantCollapseToggle)
+ {
+ window->Collapsed = !window->Collapsed;
+ MarkIniSettingsDirty(window);
+ }
+ }
+ else
+ {
+ window->Collapsed = false;
+ }
+ window->WantCollapseToggle = false;
+
+ // SIZE
+
+ // Calculate auto-fit size, handle automatic resize
+ const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal);
+ bool use_current_size_for_scrollbar_x = window_just_created;
+ bool use_current_size_for_scrollbar_y = window_just_created;
+ if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
+ {
+ // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
+ if (!window_size_x_set_by_api)
+ {
+ window->SizeFull.x = size_auto_fit.x;
+ use_current_size_for_scrollbar_x = true;
+ }
+ if (!window_size_y_set_by_api)
+ {
+ window->SizeFull.y = size_auto_fit.y;
+ use_current_size_for_scrollbar_y = true;
+ }
+ }
+ else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
+ {
+ // Auto-fit may only grow window during the first few frames
+ // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
+ if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
+ {
+ window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
+ use_current_size_for_scrollbar_x = true;
+ }
+ if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
+ {
+ window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
+ use_current_size_for_scrollbar_y = true;
+ }
+ if (!window->Collapsed)
+ MarkIniSettingsDirty(window);
+ }
+
+ // Apply minimum/maximum window size constraints and final size
+ window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull);
+ window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
+
+ // Decoration size
+ const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
+
+ // POSITION
+
+ // Popup latch its initial position, will position itself when it appears next frame
+ if (window_just_activated_by_user)
+ {
+ window->AutoPosLastDirection = ImGuiDir_None;
+ if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api) // FIXME: BeginPopup() could use SetNextWindowPos()
+ window->Pos = g.BeginPopupStack.back().OpenPopupPos;
+ }
+
+ // Position child window
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ {
+ IM_ASSERT(parent_window && parent_window->Active);
+ window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
+ parent_window->DC.ChildWindows.push_back(window);
+ if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip)
+ window->Pos = parent_window->DC.CursorPos;
+ }
+
+ const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0);
+ if (window_pos_with_pivot)
+ SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering)
+ else if ((flags & ImGuiWindowFlags_ChildMenu) != 0)
+ window->Pos = FindBestWindowPosForPopup(window);
+ else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize)
+ window->Pos = FindBestWindowPosForPopup(window);
+ else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
+ window->Pos = FindBestWindowPosForPopup(window);
+
+ // Calculate the range of allowed position for that window (to be movable and visible past safe area padding)
+ // When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect.
+ ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
+ ImRect viewport_rect(viewport->GetMainRect());
+ ImRect viewport_work_rect(viewport->GetWorkRect());
+ ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
+ ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding);
+
+ // Clamp position/size so window stays visible within its viewport or monitor
+ // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
+ if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
+ if (viewport_rect.GetWidth() > 0.0f && viewport_rect.GetHeight() > 0.0f)
+ ClampWindowRect(window, visibility_rect);
+ window->Pos = ImFloor(window->Pos);
+
+ // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
+ // Large values tend to lead to variety of artifacts and are not recommended.
+ window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
+
+ // For windows with title bar or menu bar, we clamp to FrameHeight(FontSize + FramePadding.y * 2.0f) to completely hide artifacts.
+ //if ((window->Flags & ImGuiWindowFlags_MenuBar) || !(window->Flags & ImGuiWindowFlags_NoTitleBar))
+ // window->WindowRounding = ImMin(window->WindowRounding, g.FontSize + style.FramePadding.y * 2.0f);
+
+ // Apply window focus (new and reactivated windows are moved to front)
+ bool want_focus = false;
+ if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
+ {
+ if (flags & ImGuiWindowFlags_Popup)
+ want_focus = true;
+ else if ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) == 0)
+ want_focus = true;
+ }
+
+ // Handle manual resize: Resize Grips, Borders, Gamepad
+ int border_held = -1;
+ ImU32 resize_grip_col[4] = {};
+ const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it.
+ const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
+ if (!window->Collapsed)
+ if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
+ use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true;
+ window->ResizeBorderHeld = (signed char)border_held;
+
+ // SCROLLBAR VISIBILITY
+
+ // Update scrollbar visibility (based on the Size that was effective during last frame or the auto-resized Size).
+ if (!window->Collapsed)
+ {
+ // When reading the current size we need to read it after size constraints have been applied.
+ // When we use InnerRect here we are intentionally reading last frame size, same for ScrollbarSizes values before we set them again.
+ ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - decoration_up_height);
+ ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + window->ScrollbarSizes;
+ ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
+ float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
+ float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
+ //bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons?
+ window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
+ window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
+ if (window->ScrollbarX && !window->ScrollbarY)
+ window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
+ window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
+ }
+
+ // UPDATE RECTANGLES (1- THOSE NOT AFFECTED BY SCROLLING)
+ // Update various regions. Variables they depends on should be set above in this function.
+ // We set this up after processing the resize grip so that our rectangles doesn't lag by a frame.
+
+ // Outer rectangle
+ // Not affected by window border size. Used by:
+ // - FindHoveredWindow() (w/ extra padding when border resize is enabled)
+ // - Begin() initial clipping rect for drawing window background and borders.
+ // - Begin() clipping whole child
+ const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
+ const ImRect outer_rect = window->Rect();
+ const ImRect title_bar_rect = window->TitleBarRect();
+ window->OuterRectClipped = outer_rect;
+ window->OuterRectClipped.ClipWith(host_rect);
+
+ // Inner rectangle
+ // Not affected by window border size. Used by:
+ // - InnerClipRect
+ // - ScrollToRectEx()
+ // - NavUpdatePageUpPageDown()
+ // - Scrollbar()
+ window->InnerRect.Min.x = window->Pos.x;
+ window->InnerRect.Min.y = window->Pos.y + decoration_up_height;
+ window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x;
+ window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y;
+
+ // Inner clipping rectangle.
+ // Will extend a little bit outside the normal work region.
+ // This is to allow e.g. Selectable or CollapsingHeader or some separators to cover that space.
+ // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
+ // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
+ // Affected by window/frame border size. Used by:
+ // - Begin() initial clip rect
+ float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
+ window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
+ window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size);
+ window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
+ window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize);
+ window->InnerClipRect.ClipWithFull(host_rect);
+
+ // Default item width. Make it proportional to window size if window manually resizes
+ if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
+ window->ItemWidthDefault = ImFloor(window->Size.x * 0.65f);
+ else
+ window->ItemWidthDefault = ImFloor(g.FontSize * 16.0f);
+
+ // SCROLLING
+
+ // Lock down maximum scrolling
+ // The value of ScrollMax are ahead from ScrollbarX/ScrollbarY which is intentionally using InnerRect from previous rect in order to accommodate
+ // for right/bottom aligned items without creating a scrollbar.
+ window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
+ window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
+
+ // Apply scrolling
+ window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window);
+ window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
+
+ // DRAWING
+
+ // Setup draw list and outer clipping rectangle
+ IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0);
+ window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
+ PushClipRect(host_rect.Min, host_rect.Max, false);
+
+ // Draw modal window background (darkens what is behind them, all viewports)
+ const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0;
+ const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow);
+ if (dim_bg_for_modal || dim_bg_for_window_list)
+ {
+ const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
+ window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col);
+ }
+
+ // Draw navigation selection/windowing rectangle background
+ if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim)
+ {
+ ImRect bb = window->Rect();
+ bb.Expand(g.FontSize);
+ if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway
+ window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding);
+ }
+
+ // Child windows can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call (since 1.71)
+ // When using overlapping child windows, this will break the assumption that child z-order is mapped to submission order.
+ // FIXME: User code may rely on explicit sorting of overlapping child window and would need to disable this somehow. Please get in contact if you are affected (github #4493)
+ {
+ bool render_decorations_in_parent = false;
+ if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip)
+ {
+ // - We test overlap with the previous child window only (testing all would end up being O(log N) not a good investment here)
+ // - We disable this when the parent window has zero vertices, which is a common pattern leading to laying out multiple overlapping childs
+ ImGuiWindow* previous_child = parent_window->DC.ChildWindows.Size >= 2 ? parent_window->DC.ChildWindows[parent_window->DC.ChildWindows.Size - 2] : NULL;
+ bool previous_child_overlapping = previous_child ? previous_child->Rect().Overlaps(window->Rect()) : false;
+ bool parent_is_empty = parent_window->DrawList->VtxBuffer.Size > 0;
+ if (window->DrawList->CmdBuffer.back().ElemCount == 0 && parent_is_empty && !previous_child_overlapping)
+ render_decorations_in_parent = true;
+ }
+ if (render_decorations_in_parent)
+ window->DrawList = parent_window->DrawList;
+
+ // Handle title bar, scrollbar, resize grips and resize borders
+ const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
+ const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
+ RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, resize_grip_count, resize_grip_col, resize_grip_draw_size);
+
+ if (render_decorations_in_parent)
+ window->DrawList = &window->DrawListInst;
+ }
+
+ // Draw navigation selection/windowing rectangle border
+ if (g.NavWindowingTargetAnim == window)
+ {
+ float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
+ ImRect bb = window->Rect();
+ bb.Expand(g.FontSize);
+ if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward
+ {
+ bb.Expand(-g.FontSize - 1.0f);
+ rounding = window->WindowRounding;
+ }
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, 0, 3.0f);
+ }
+
+ // UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING)
+
+ // Work rectangle.
+ // Affected by window padding and border size. Used by:
+ // - Columns() for right-most edge
+ // - TreeNode(), CollapsingHeader() for right-most edge
+ // - BeginTabBar() for right-most edge
+ const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar);
+ const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar);
+ const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x));
+ const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y));
+ window->WorkRect.Min.x = ImFloor(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize));
+ window->WorkRect.Min.y = ImFloor(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize));
+ window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x;
+ window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y;
+ window->ParentWorkRect = window->WorkRect;
+
+ // [LEGACY] Content Region
+ // FIXME-OBSOLETE: window->ContentRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
+ // Used by:
+ // - Mouse wheel scrolling + many other things
+ window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
+ window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + decoration_up_height;
+ window->ContentRegionRect.Max.x = window->ContentRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x));
+ window->ContentRegionRect.Max.y = window->ContentRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y));
+
+ // Setup drawing context
+ // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.)
+ window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
+ window->DC.GroupOffset.x = 0.0f;
+ window->DC.ColumnsOffset.x = 0.0f;
+ window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, decoration_up_height + window->WindowPadding.y - window->Scroll.y);
+ window->DC.CursorPos = window->DC.CursorStartPos;
+ window->DC.CursorPosPrevLine = window->DC.CursorPos;
+ window->DC.CursorMaxPos = window->DC.CursorStartPos;
+ window->DC.IdealMaxPos = window->DC.CursorStartPos;
+ window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
+ window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
+
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+ window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
+ window->DC.NavLayersActiveMaskNext = 0x00;
+ window->DC.NavHideHighlightOneFrame = false;
+ window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
+
+ window->DC.MenuBarAppending = false;
+ window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user);
+ window->DC.TreeDepth = 0;
+ window->DC.TreeJumpToParentOnPopMask = 0x00;
+ window->DC.ChildWindows.resize(0);
+ window->DC.StateStorage = &window->StateStorage;
+ window->DC.CurrentColumns = NULL;
+ window->DC.LayoutType = ImGuiLayoutType_Vertical;
+ window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
+
+ window->DC.ItemWidth = window->ItemWidthDefault;
+ window->DC.TextWrapPos = -1.0f; // disabled
+ window->DC.ItemWidthStack.resize(0);
+ window->DC.TextWrapPosStack.resize(0);
+
+ if (window->AutoFitFramesX > 0)
+ window->AutoFitFramesX--;
+ if (window->AutoFitFramesY > 0)
+ window->AutoFitFramesY--;
+
+ // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there)
+ if (want_focus)
+ {
+ FocusWindow(window);
+ NavInitWindow(window, false); // <-- this is in the way for us to be able to defer and sort reappearing FocusWindow() calls
+ }
+
+ // Title bar
+ if (!(flags & ImGuiWindowFlags_NoTitleBar))
+ RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open);
+
+ // Clear hit test shape every frame
+ window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
+
+ // Pressing CTRL+C while holding on a window copy its content to the clipboard
+ // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.
+ // Maybe we can support CTRL+C on every element?
+ /*
+ //if (g.NavWindow == window && g.ActiveId == 0)
+ if (g.ActiveId == window->MoveId)
+ if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
+ LogToClipboard();
+ */
+
+ // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
+ // This is useful to allow creating context menus on title bar only, etc.
+ g.LastItemData.ID = window->MoveId;
+ g.LastItemData.InFlags = g.CurrentItemFlags;
+ g.LastItemData.StatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
+ g.LastItemData.Rect = title_bar_rect;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
+ IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID);
+#endif
+ }
+ else
+ {
+ // Append
+ SetCurrentWindow(window);
+ }
+
+ // Pull/inherit current state
+ window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inherit from parent only // -V595
+
+ PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
+
+ // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
+ window->WriteAccessed = false;
+ window->BeginCount++;
+ g.NextWindowData.ClearFlags();
+
+ // Update visibility
+ if (first_begin_of_the_frame)
+ {
+ if (flags & ImGuiWindowFlags_ChildWindow)
+ {
+ // Child window can be out of sight and have "negative" clip windows.
+ // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar).
+ IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0);
+ if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) // FIXME: Doesn't make sense for ChildWindow??
+ {
+ const bool nav_request = (flags & ImGuiWindowFlags_NavFlattened) && (g.NavAnyRequest && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
+ if (!g.LogEnabled && !nav_request)
+ if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
+ window->HiddenFramesCanSkipItems = 1;
+ }
+
+ // Hide along with parent or if parent is collapsed
+ if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0))
+ window->HiddenFramesCanSkipItems = 1;
+ if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0))
+ window->HiddenFramesCannotSkipItems = 1;
+ }
+
+ // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point)
+ if (style.Alpha <= 0.0f)
+ window->HiddenFramesCanSkipItems = 1;
+
+ // Update the Hidden flag
+ window->Hidden = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0) || (window->HiddenFramesForRenderOnly > 0);
+
+ // Disable inputs for requested number of frames
+ if (window->DisableInputsFrames > 0)
+ {
+ window->DisableInputsFrames--;
+ window->Flags |= ImGuiWindowFlags_NoInputs;
+ }
+
+ // Update the SkipItems flag, used to early out of all items functions (no layout required)
+ bool skip_items = false;
+ if (window->Collapsed || !window->Active || window->Hidden)
+ if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0)
+ skip_items = true;
+ window->SkipItems = skip_items;
+ }
+
+ return !window->SkipItems;
+}
+
+void ImGui::End()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // Error checking: verify that user hasn't called End() too many times!
+ if (g.CurrentWindowStack.Size <= 1 && g.WithinFrameScopeWithImplicitWindow)
+ {
+ IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!");
+ return;
+ }
+ IM_ASSERT(g.CurrentWindowStack.Size > 0);
+
+ // Error checking: verify that user doesn't directly call End() on a child window.
+ if (window->Flags & ImGuiWindowFlags_ChildWindow)
+ IM_ASSERT_USER_ERROR(g.WithinEndChild, "Must call EndChild() and not End()!");
+
+ // Close anything that is open
+ if (window->DC.CurrentColumns)
+ EndColumns();
+ PopClipRect(); // Inner window clip rectangle
+
+ // Stop logging
+ if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
+ LogFinish();
+
+ // Pop from window stack
+ g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ g.BeginPopupStack.pop_back();
+ g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithCurrentState();
+ g.CurrentWindowStack.pop_back();
+ SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
+}
+
+void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(window == window->RootWindow);
+
+ const int cur_order = window->FocusOrder;
+ IM_ASSERT(g.WindowsFocusOrder[cur_order] == window);
+ if (g.WindowsFocusOrder.back() == window)
+ return;
+
+ const int new_order = g.WindowsFocusOrder.Size - 1;
+ for (int n = cur_order; n < new_order; n++)
+ {
+ g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1];
+ g.WindowsFocusOrder[n]->FocusOrder--;
+ IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n);
+ }
+ g.WindowsFocusOrder[new_order] = window;
+ window->FocusOrder = (short)new_order;
+}
+
+void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* current_front_window = g.Windows.back();
+ if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better)
+ return;
+ for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
+ if (g.Windows[i] == window)
+ {
+ memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*));
+ g.Windows[g.Windows.Size - 1] = window;
+ break;
+ }
+}
+
+void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.Windows[0] == window)
+ return;
+ for (int i = 0; i < g.Windows.Size; i++)
+ if (g.Windows[i] == window)
+ {
+ memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*));
+ g.Windows[0] = window;
+ break;
+ }
+}
+
+// Moving window to front of display and set focus (which happens to be back of our sorted list)
+void ImGui::FocusWindow(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+
+ if (g.NavWindow != window)
+ {
+ g.NavWindow = window;
+ if (window && g.NavDisableMouseHover)
+ g.NavMousePosDirty = true;
+ g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
+ g.NavFocusScopeId = 0;
+ g.NavIdIsAlive = false;
+ g.NavLayer = ImGuiNavLayer_Main;
+ g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false;
+ NavUpdateAnyRequestFlag();
+ //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
+ }
+
+ // Close popups if any
+ ClosePopupsOverWindow(window, false);
+
+ // Move the root window to the top of the pile
+ IM_ASSERT(window == NULL || window->RootWindow != NULL);
+ ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop
+ ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
+
+ // Steal active widgets. Some of the cases it triggers includes:
+ // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run.
+ // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId)
+ if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
+ if (!g.ActiveIdNoClearOnFocusLoss)
+ ClearActiveID();
+
+ // Passing NULL allow to disable keyboard focus
+ if (!window)
+ return;
+
+ // Bring to front
+ BringWindowToFocusFront(focus_front_window);
+ if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
+ BringWindowToDisplayFront(display_front_window);
+}
+
+void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window)
+{
+ ImGuiContext& g = *GImGui;
+ int start_idx = g.WindowsFocusOrder.Size - 1;
+ if (under_this_window != NULL)
+ {
+ // Aim at root window behind us, if we are in a child window that's our own root (see #4640)
+ int offset = -1;
+ while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
+ {
+ under_this_window = under_this_window->ParentWindow;
+ offset = 0;
+ }
+ start_idx = FindWindowFocusIndex(under_this_window) + offset;
+ }
+ for (int i = start_idx; i >= 0; i--)
+ {
+ // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
+ ImGuiWindow* window = g.WindowsFocusOrder[i];
+ IM_ASSERT(window == window->RootWindow);
+ if (window != ignore_window && window->WasActive)
+ if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
+ {
+ ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
+ FocusWindow(focus_window);
+ return;
+ }
+ }
+ FocusWindow(NULL);
+}
+
+// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
+void ImGui::SetCurrentFont(ImFont* font)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
+ IM_ASSERT(font->Scale > 0.0f);
+ g.Font = font;
+ g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale);
+ g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
+
+ ImFontAtlas* atlas = g.Font->ContainerAtlas;
+ g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
+ g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
+ g.DrawListSharedData.Font = g.Font;
+ g.DrawListSharedData.FontSize = g.FontSize;
+}
+
+void ImGui::PushFont(ImFont* font)
+{
+ ImGuiContext& g = *GImGui;
+ if (!font)
+ font = GetDefaultFont();
+ SetCurrentFont(font);
+ g.FontStack.push_back(font);
+ g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
+}
+
+void ImGui::PopFont()
+{
+ ImGuiContext& g = *GImGui;
+ g.CurrentWindow->DrawList->PopTextureID();
+ g.FontStack.pop_back();
+ SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back());
+}
+
+void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiItemFlags item_flags = g.CurrentItemFlags;
+ IM_ASSERT(item_flags == g.ItemFlagsStack.back());
+ if (enabled)
+ item_flags |= option;
+ else
+ item_flags &= ~option;
+ g.CurrentItemFlags = item_flags;
+ g.ItemFlagsStack.push_back(item_flags);
+}
+
+void ImGui::PopItemFlag()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack.
+ g.ItemFlagsStack.pop_back();
+ g.CurrentItemFlags = g.ItemFlagsStack.back();
+}
+
+// BeginDisabled()/EndDisabled()
+// - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
+// - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently.
+// - Feedback welcome at https://github.com/ocornut/imgui/issues/211
+// - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.
+// - Optimized shortcuts instead of PushStyleVar() + PushItemFlag()
+void ImGui::BeginDisabled(bool disabled)
+{
+ ImGuiContext& g = *GImGui;
+ bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
+ if (!was_disabled && disabled)
+ {
+ g.DisabledAlphaBackup = g.Style.Alpha;
+ g.Style.Alpha *= g.Style.DisabledAlpha; // PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * g.Style.DisabledAlpha);
+ }
+ if (was_disabled || disabled)
+ g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
+ g.ItemFlagsStack.push_back(g.CurrentItemFlags);
+ g.DisabledStackSize++;
+}
+
+void ImGui::EndDisabled()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.DisabledStackSize > 0);
+ g.DisabledStackSize--;
+ bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
+ //PopItemFlag();
+ g.ItemFlagsStack.pop_back();
+ g.CurrentItemFlags = g.ItemFlagsStack.back();
+ if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
+ g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();
+}
+
+// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
+void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus)
+{
+ PushItemFlag(ImGuiItemFlags_NoTabStop, !allow_keyboard_focus);
+}
+
+void ImGui::PopAllowKeyboardFocus()
+{
+ PopItemFlag();
+}
+
+void ImGui::PushButtonRepeat(bool repeat)
+{
+ PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat);
+}
+
+void ImGui::PopButtonRepeat()
+{
+ PopItemFlag();
+}
+
+void ImGui::PushTextWrapPos(float wrap_pos_x)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos);
+ window->DC.TextWrapPos = wrap_pos_x;
+}
+
+void ImGui::PopTextWrapPos()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.TextWrapPos = window->DC.TextWrapPosStack.back();
+ window->DC.TextWrapPosStack.pop_back();
+}
+
+static ImGuiWindow* GetCombinedRootWindow(ImGuiWindow* window, bool popup_hierarchy)
+{
+ ImGuiWindow* last_window = NULL;
+ while (last_window != window)
+ {
+ last_window = window;
+ window = window->RootWindow;
+ if (popup_hierarchy)
+ window = window->RootWindowPopupTree;
+ }
+ return window;
+}
+
+bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy)
+{
+ ImGuiWindow* window_root = GetCombinedRootWindow(window, popup_hierarchy);
+ if (window_root == potential_parent)
+ return true;
+ while (window != NULL)
+ {
+ if (window == potential_parent)
+ return true;
+ if (window == window_root) // end of chain
+ return false;
+ window = window->ParentWindow;
+ }
+ return false;
+}
+
+bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
+{
+ ImGuiContext& g = *GImGui;
+
+ // It would be saner to ensure that display layer is always reflected in the g.Windows[] order, which would likely requires altering all manipulations of that array
+ const int display_layer_delta = GetWindowDisplayLayer(potential_above) - GetWindowDisplayLayer(potential_below);
+ if (display_layer_delta != 0)
+ return display_layer_delta > 0;
+
+ for (int i = g.Windows.Size - 1; i >= 0; i--)
+ {
+ ImGuiWindow* candidate_window = g.Windows[i];
+ if (candidate_window == potential_above)
+ return true;
+ if (candidate_window == potential_below)
+ return false;
+ }
+ return false;
+}
+
+bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
+{
+ IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenDisabled)) == 0); // Flags not supported by this function
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* ref_window = g.HoveredWindow;
+ ImGuiWindow* cur_window = g.CurrentWindow;
+ if (ref_window == NULL)
+ return false;
+
+ if ((flags & ImGuiHoveredFlags_AnyWindow) == 0)
+ {
+ IM_ASSERT(cur_window); // Not inside a Begin()/End()
+ const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
+ if (flags & ImGuiHoveredFlags_RootWindow)
+ cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy);
+
+ bool result;
+ if (flags & ImGuiHoveredFlags_ChildWindows)
+ result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy);
+ else
+ result = (ref_window == cur_window);
+ if (!result)
+ return false;
+ }
+
+ if (!IsWindowContentHoverable(ref_window, flags))
+ return false;
+ if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId)
+ return false;
+ return true;
+}
+
+bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* ref_window = g.NavWindow;
+ ImGuiWindow* cur_window = g.CurrentWindow;
+
+ if (ref_window == NULL)
+ return false;
+ if (flags & ImGuiFocusedFlags_AnyWindow)
+ return true;
+ IM_ASSERT(cur_window); // Not inside a Begin()/End()
+
+ const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
+ if (flags & ImGuiHoveredFlags_RootWindow)
+ cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy);
+
+ if (flags & ImGuiHoveredFlags_ChildWindows)
+ return IsWindowChildOf(ref_window, cur_window, popup_hierarchy);
+ else
+ return (ref_window == cur_window);
+}
+
+// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
+// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically.
+// If you want a window to never be focused, you may use the e.g. NoInputs flag.
+bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
+{
+ return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
+}
+
+float ImGui::GetWindowWidth()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->Size.x;
+}
+
+float ImGui::GetWindowHeight()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->Size.y;
+}
+
+ImVec2 ImGui::GetWindowPos()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ return window->Pos;
+}
+
+void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
+{
+ // Test condition (NB: bit 0 is always true) and clear flags for next time
+ if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
+ return;
+
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+ window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
+
+ // Set
+ const ImVec2 old_pos = window->Pos;
+ window->Pos = ImFloor(pos);
+ ImVec2 offset = window->Pos - old_pos;
+ window->DC.CursorPos += offset; // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
+ window->DC.CursorMaxPos += offset; // And more importantly we need to offset CursorMaxPos/CursorStartPos this so ContentSize calculation doesn't get affected.
+ window->DC.IdealMaxPos += offset;
+ window->DC.CursorStartPos += offset;
+}
+
+void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ SetWindowPos(window, pos, cond);
+}
+
+void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond)
+{
+ if (ImGuiWindow* window = FindWindowByName(name))
+ SetWindowPos(window, pos, cond);
+}
+
+ImVec2 ImGui::GetWindowSize()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->Size;
+}
+
+void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond)
+{
+ // Test condition (NB: bit 0 is always true) and clear flags for next time
+ if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
+ return;
+
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+
+ // Set
+ if (size.x > 0.0f)
+ {
+ window->AutoFitFramesX = 0;
+ window->SizeFull.x = IM_FLOOR(size.x);
+ }
+ else
+ {
+ window->AutoFitFramesX = 2;
+ window->AutoFitOnlyGrows = false;
+ }
+ if (size.y > 0.0f)
+ {
+ window->AutoFitFramesY = 0;
+ window->SizeFull.y = IM_FLOOR(size.y);
+ }
+ else
+ {
+ window->AutoFitFramesY = 2;
+ window->AutoFitOnlyGrows = false;
+ }
+}
+
+void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond)
+{
+ SetWindowSize(GImGui->CurrentWindow, size, cond);
+}
+
+void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond)
+{
+ if (ImGuiWindow* window = FindWindowByName(name))
+ SetWindowSize(window, size, cond);
+}
+
+void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond)
+{
+ // Test condition (NB: bit 0 is always true) and clear flags for next time
+ if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
+ return;
+ window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
+
+ // Set
+ window->Collapsed = collapsed;
+}
+
+void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size)
+{
+ IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters
+ window->HitTestHoleSize = ImVec2ih(size);
+ window->HitTestHoleOffset = ImVec2ih(pos - window->Pos);
+}
+
+void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)
+{
+ SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
+}
+
+bool ImGui::IsWindowCollapsed()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->Collapsed;
+}
+
+bool ImGui::IsWindowAppearing()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->Appearing;
+}
+
+void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
+{
+ if (ImGuiWindow* window = FindWindowByName(name))
+ SetWindowCollapsed(window, collapsed, cond);
+}
+
+void ImGui::SetWindowFocus()
+{
+ FocusWindow(GImGui->CurrentWindow);
+}
+
+void ImGui::SetWindowFocus(const char* name)
+{
+ if (name)
+ {
+ if (ImGuiWindow* window = FindWindowByName(name))
+ FocusWindow(window);
+ }
+ else
+ {
+ FocusWindow(NULL);
+ }
+}
+
+void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos;
+ g.NextWindowData.PosVal = pos;
+ g.NextWindowData.PosPivotVal = pivot;
+ g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize;
+ g.NextWindowData.SizeVal = size;
+ g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
+ g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max);
+ g.NextWindowData.SizeCallback = custom_callback;
+ g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
+}
+
+// Content size = inner scrollable rectangle, padded with WindowPadding.
+// SetNextWindowContentSize(ImVec2(100,100) + ImGuiWindowFlags_AlwaysAutoResize will always allow submitting a 100x100 item.
+void ImGui::SetNextWindowContentSize(const ImVec2& size)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
+ g.NextWindowData.ContentSizeVal = ImFloor(size);
+}
+
+void ImGui::SetNextWindowScroll(const ImVec2& scroll)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll;
+ g.NextWindowData.ScrollVal = scroll;
+}
+
+void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags.
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed;
+ g.NextWindowData.CollapsedVal = collapsed;
+ g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
+}
+
+void ImGui::SetNextWindowFocus()
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
+}
+
+void ImGui::SetNextWindowBgAlpha(float alpha)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha;
+ g.NextWindowData.BgAlphaVal = alpha;
+}
+
+ImDrawList* ImGui::GetWindowDrawList()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ return window->DrawList;
+}
+
+ImFont* ImGui::GetFont()
+{
+ return GImGui->Font;
+}
+
+float ImGui::GetFontSize()
+{
+ return GImGui->FontSize;
+}
+
+ImVec2 ImGui::GetFontTexUvWhitePixel()
+{
+ return GImGui->DrawListSharedData.TexUvWhitePixel;
+}
+
+void ImGui::SetWindowFontScale(float scale)
+{
+ IM_ASSERT(scale > 0.0f);
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ window->FontWindowScale = scale;
+ g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
+}
+
+void ImGui::ActivateItem(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ g.NavNextActivateId = id;
+ g.NavNextActivateFlags = ImGuiActivateFlags_None;
+}
+
+void ImGui::PushFocusScope(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ g.FocusScopeStack.push_back(window->DC.NavFocusScopeIdCurrent);
+ window->DC.NavFocusScopeIdCurrent = id;
+}
+
+void ImGui::PopFocusScope()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ?
+ window->DC.NavFocusScopeIdCurrent = g.FocusScopeStack.back();
+ g.FocusScopeStack.pop_back();
+}
+
+void ImGui::SetKeyboardFocusHere(int offset)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(offset >= -1); // -1 is allowed but not below
+ g.NavWindow = window;
+ ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
+ NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_FocusApi, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
+ if (offset == -1)
+ {
+ NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
+ }
+ else
+ {
+ g.NavTabbingDir = 1;
+ g.NavTabbingCounter = offset + 1;
+ }
+}
+
+void ImGui::SetItemDefaultFocus()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!window->Appearing)
+ return;
+ if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResultId == 0) || g.NavLayer != window->DC.NavLayerCurrent)
+ return;
+
+ g.NavInitRequest = false;
+ g.NavInitResultId = g.LastItemData.ID;
+ g.NavInitResultRectRel = WindowRectAbsToRel(window, g.LastItemData.Rect);
+ NavUpdateAnyRequestFlag();
+
+ // Scroll could be done in NavInitRequestApplyResult() via a opt-in flag (we however don't want regular init requests to scroll)
+ if (!IsItemVisible())
+ ScrollToRectEx(window, g.LastItemData.Rect, ImGuiScrollFlags_None);
+}
+
+void ImGui::SetStateStorage(ImGuiStorage* tree)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ window->DC.StateStorage = tree ? tree : &window->StateStorage;
+}
+
+ImGuiStorage* ImGui::GetStateStorage()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->DC.StateStorage;
+}
+
+void ImGui::PushID(const char* str_id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiID id = window->GetIDNoKeepAlive(str_id);
+ window->IDStack.push_back(id);
+}
+
+void ImGui::PushID(const char* str_id_begin, const char* str_id_end)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiID id = window->GetIDNoKeepAlive(str_id_begin, str_id_end);
+ window->IDStack.push_back(id);
+}
+
+void ImGui::PushID(const void* ptr_id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiID id = window->GetIDNoKeepAlive(ptr_id);
+ window->IDStack.push_back(id);
+}
+
+void ImGui::PushID(int int_id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiID id = window->GetIDNoKeepAlive(int_id);
+ window->IDStack.push_back(id);
+}
+
+// Push a given id value ignoring the ID stack as a seed.
+void ImGui::PushOverrideID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.DebugHookIdInfo == id)
+ DebugHookIdInfo(id, ImGuiDataType_ID, NULL, NULL);
+ window->IDStack.push_back(id);
+}
+
+// Helper to avoid a common series of PushOverrideID -> GetID() -> PopID() call
+// (note that when using this pattern, TestEngine's "Stack Tool" will tend to not display the intermediate stack level.
+// for that to work we would need to do PushOverrideID() -> ItemAdd() -> PopID() which would alter widget code a little more)
+ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed)
+{
+ ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
+ KeepAliveID(id);
+ ImGuiContext& g = *GImGui;
+ if (g.DebugHookIdInfo == id)
+ DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
+ return id;
+}
+
+void ImGui::PopID()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window?
+ window->IDStack.pop_back();
+}
+
+ImGuiID ImGui::GetID(const char* str_id)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->GetID(str_id);
+}
+
+ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->GetID(str_id_begin, str_id_end);
+}
+
+ImGuiID ImGui::GetID(const void* ptr_id)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->GetID(ptr_id);
+}
+
+bool ImGui::IsRectVisible(const ImVec2& size)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
+}
+
+bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] ERROR CHECKING
+//-----------------------------------------------------------------------------
+
+// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui.
+// Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
+// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. your user code
+// may see different structures than what imgui.cpp sees, which is problematic.
+// We usually require settings to be in imconfig.h to make sure that they are accessible to all compilation units involved with Dear ImGui.
+bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx)
+{
+ bool error = false;
+ if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); }
+ if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); }
+ if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); }
+ if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); }
+ if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); }
+ if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); }
+ if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); }
+ return !error;
+}
+
+static void ImGui::ErrorCheckNewFrameSanityChecks()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Check user IM_ASSERT macro
+ // (IF YOU GET A WARNING OR COMPILE ERROR HERE: it means your assert macro is incorrectly defined!
+ // If your macro uses multiple statements, it NEEDS to be surrounded by a 'do { ... } while (0)' block.
+ // This is a common C/C++ idiom to allow multiple statements macros to be used in control flow blocks.)
+ // #define IM_ASSERT(EXPR) if (SomeCode(EXPR)) SomeMoreCode(); // Wrong!
+ // #define IM_ASSERT(EXPR) do { if (SomeCode(EXPR)) SomeMoreCode(); } while (0) // Correct!
+ if (true) IM_ASSERT(1); else IM_ASSERT(0);
+
+ // Check user data
+ // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument)
+ IM_ASSERT(g.Initialized);
+ IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!");
+ IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?");
+ IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!");
+ IM_ASSERT(g.IO.Fonts->IsBuilt() && "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()");
+ IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!");
+ IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!");
+ IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations
+ IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
+ IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
+ for (int n = 0; n < ImGuiKey_COUNT; n++)
+ IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
+
+ // Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP)
+ if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
+ IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation.");
+
+ // Check: the io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly.
+ if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors))
+ g.IO.ConfigWindowsResizeFromEdges = false;
+}
+
+static void ImGui::ErrorCheckEndFrameSanityChecks()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame()
+ // One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame().
+ // It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will
+ // send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs.
+ // We silently accommodate for this case by ignoring/ the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0),
+ // while still correctly asserting on mid-frame key press events.
+ const ImGuiKeyModFlags key_mod_flags = GetMergedKeyModFlags();
+ IM_ASSERT((key_mod_flags == 0 || g.IO.KeyMods == key_mod_flags) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
+ IM_UNUSED(key_mod_flags);
+
+ // Recover from errors
+ //ErrorCheckEndFrameRecover();
+
+ // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you
+ // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API).
+ if (g.CurrentWindowStack.Size != 1)
+ {
+ if (g.CurrentWindowStack.Size > 1)
+ {
+ IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?");
+ while (g.CurrentWindowStack.Size > 1)
+ End();
+ }
+ else
+ {
+ IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?");
+ }
+ }
+
+ IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!");
+}
+
+// Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls.
+// Must be called during or before EndFrame().
+// This is generally flawed as we are not necessarily End/Popping things in the right order.
+// FIXME: Can't recover from inside BeginTabItem/EndTabItem yet.
+// FIXME: Can't recover from interleaved BeginTabBar/Begin
+void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data)
+{
+ // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
+ ImGuiContext& g = *GImGui;
+ while (g.CurrentWindowStack.Size > 0) //-V1044
+ {
+ ErrorCheckEndWindowRecover(log_callback, user_data);
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.CurrentWindowStack.Size == 1)
+ {
+ IM_ASSERT(window->IsFallbackWindow);
+ break;
+ }
+ IM_ASSERT(window == g.CurrentWindow);
+ if (window->Flags & ImGuiWindowFlags_ChildWindow)
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name);
+ EndChild();
+ }
+ else
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name);
+ End();
+ }
+ }
+}
+
+// Must be called before End()/EndChild()
+void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data)
+{
+ ImGuiContext& g = *GImGui;
+ while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name);
+ EndTable();
+ }
+
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
+ IM_ASSERT(window != NULL);
+ while (g.CurrentTabBar != NULL) //-V1044
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
+ EndTabBar();
+ }
+ while (window->DC.TreeDepth > 0)
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
+ TreePop();
+ }
+ while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
+ EndGroup();
+ }
+ while (window->IDStack.Size > 1)
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
+ PopID();
+ }
+ while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
+ EndDisabled();
+ }
+ while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col));
+ PopStyleColor();
+ }
+ while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name);
+ PopItemFlag();
+ }
+ while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
+ PopStyleVar();
+ }
+ while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack) //-V1044
+ {
+ if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
+ PopFocusScope();
+ }
+}
+
+// Save current stack sizes for later compare
+void ImGuiStackSizes::SetToCurrentState()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ SizeOfIDStack = (short)window->IDStack.Size;
+ SizeOfColorStack = (short)g.ColorStack.Size;
+ SizeOfStyleVarStack = (short)g.StyleVarStack.Size;
+ SizeOfFontStack = (short)g.FontStack.Size;
+ SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
+ SizeOfGroupStack = (short)g.GroupStack.Size;
+ SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
+ SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
+ SizeOfDisabledStack = (short)g.DisabledStackSize;
+}
+
+// Compare to detect usage errors
+void ImGuiStackSizes::CompareWithCurrentState()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_UNUSED(window);
+
+ // Window stacks
+ // NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
+ IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!");
+
+ // Global stacks
+ // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
+ IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!");
+ IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
+ IM_ASSERT(SizeOfDisabledStack == g.DisabledStackSize && "BeginDisabled/EndDisabled Mismatch!");
+ IM_ASSERT(SizeOfItemFlagsStack >= g.ItemFlagsStack.Size && "PushItemFlag/PopItemFlag Mismatch!");
+ IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!");
+ IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!");
+ IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!");
+ IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!");
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] LAYOUT
+//-----------------------------------------------------------------------------
+// - ItemSize()
+// - ItemAdd()
+// - SameLine()
+// - GetCursorScreenPos()
+// - SetCursorScreenPos()
+// - GetCursorPos(), GetCursorPosX(), GetCursorPosY()
+// - SetCursorPos(), SetCursorPosX(), SetCursorPosY()
+// - GetCursorStartPos()
+// - Indent()
+// - Unindent()
+// - SetNextItemWidth()
+// - PushItemWidth()
+// - PushMultiItemsWidths()
+// - PopItemWidth()
+// - CalcItemWidth()
+// - CalcItemSize()
+// - GetTextLineHeight()
+// - GetTextLineHeightWithSpacing()
+// - GetFrameHeight()
+// - GetFrameHeightWithSpacing()
+// - GetContentRegionMax()
+// - GetContentRegionMaxAbs() [Internal]
+// - GetContentRegionAvail(),
+// - GetWindowContentRegionMin(), GetWindowContentRegionMax()
+// - BeginGroup()
+// - EndGroup()
+// Also see in imgui_widgets: tab bars, columns.
+//-----------------------------------------------------------------------------
+
+// Advance cursor given item size for layout.
+// Register minimum needed size so it can extend the bounding box used for auto-fit calculation.
+// See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different.
+void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ // We increase the height in this function to accommodate for baseline offset.
+ // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor,
+ // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect.
+ const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
+ const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y);
+
+ // Always align ourselves on pixel boundaries
+ //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
+ window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
+ window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y;
+ window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line
+ window->DC.CursorPos.y = IM_FLOOR(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y); // Next line
+ window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
+ window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
+ //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
+
+ window->DC.PrevLineSize.y = line_height;
+ window->DC.CurrLineSize.y = 0.0f;
+ window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y);
+ window->DC.CurrLineTextBaseOffset = 0.0f;
+
+ // Horizontal layout mode
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
+ SameLine();
+}
+
+void ImGui::ItemSize(const ImRect& bb, float text_baseline_y)
+{
+ ItemSize(bb.GetSize(), text_baseline_y);
+}
+
+// Declare item bounding box for clipping and interaction.
+// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
+// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
+bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // Set item data
+ // (DisplayRect is left untouched, made valid when ImGuiItemStatusFlags_HasDisplayRect is set)
+ g.LastItemData.ID = id;
+ g.LastItemData.Rect = bb;
+ g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb;
+ g.LastItemData.InFlags = g.CurrentItemFlags | extra_flags;
+ g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None;
+
+ // Directional navigation processing
+ if (id != 0)
+ {
+ // Runs prior to clipping early-out
+ // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
+ // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
+ // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
+ // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame.
+ // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able
+ // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
+ // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null.
+ // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere.
+ window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
+ if (g.NavId == id || g.NavAnyRequest)
+ if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
+ if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
+ NavProcessItem();
+
+ // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd()
+#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
+ if (id == g.DebugItemPickerBreakId)
+ {
+ IM_DEBUG_BREAK();
+ g.DebugItemPickerBreakId = 0;
+ }
+#endif
+ }
+ g.NextItemData.Flags = ImGuiNextItemDataFlags_None;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ if (id != 0)
+ IMGUI_TEST_ENGINE_ITEM_ADD(nav_bb_arg ? *nav_bb_arg : bb, id);
+#endif
+
+ // Clipping test
+ const bool is_clipped = IsClippedEx(bb, id);
+ if (is_clipped)
+ return false;
+ //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
+
+ // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
+ if (IsMouseHoveringRect(bb.Min, bb.Max))
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect;
+ return true;
+}
+
+// Gets back to previous line and continue with horizontal layout
+// offset_from_start_x == 0 : follow right after previous item
+// offset_from_start_x != 0 : align to specified x position (relative to window/group left)
+// spacing_w < 0 : use default spacing if pos_x == 0, no spacing if pos_x != 0
+// spacing_w >= 0 : enforce spacing amount
+void ImGui::SameLine(float offset_from_start_x, float spacing_w)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ if (offset_from_start_x != 0.0f)
+ {
+ if (spacing_w < 0.0f) spacing_w = 0.0f;
+ window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
+ window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
+ }
+ else
+ {
+ if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x;
+ window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
+ window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
+ }
+ window->DC.CurrLineSize = window->DC.PrevLineSize;
+ window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
+}
+
+ImVec2 ImGui::GetCursorScreenPos()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos;
+}
+
+void ImGui::SetCursorScreenPos(const ImVec2& pos)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos = pos;
+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
+}
+
+// User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.
+// Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'.
+ImVec2 ImGui::GetCursorPos()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos - window->Pos + window->Scroll;
+}
+
+float ImGui::GetCursorPosX()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
+}
+
+float ImGui::GetCursorPosY()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
+}
+
+void ImGui::SetCursorPos(const ImVec2& local_pos)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
+}
+
+void ImGui::SetCursorPosX(float x)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
+ window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);
+}
+
+void ImGui::SetCursorPosY(float y)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
+ window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);
+}
+
+ImVec2 ImGui::GetCursorStartPos()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CursorStartPos - window->Pos;
+}
+
+void ImGui::Indent(float indent_w)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
+ window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
+}
+
+void ImGui::Unindent(float indent_w)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
+ window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
+}
+
+// Affect large frame+labels widgets only.
+void ImGui::SetNextItemWidth(float item_width)
+{
+ ImGuiContext& g = *GImGui;
+ g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth;
+ g.NextItemData.Width = item_width;
+}
+
+// FIXME: Remove the == 0.0f behavior?
+void ImGui::PushItemWidth(float item_width)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width
+ window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
+ g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
+}
+
+void ImGui::PushMultiItemsWidths(int components, float w_full)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ const ImGuiStyle& style = g.Style;
+ const float w_item_one = ImMax(1.0f, IM_FLOOR((w_full - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components));
+ const float w_item_last = ImMax(1.0f, IM_FLOOR(w_full - (w_item_one + style.ItemInnerSpacing.x) * (components - 1)));
+ window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width
+ window->DC.ItemWidthStack.push_back(w_item_last);
+ for (int i = 0; i < components - 2; i++)
+ window->DC.ItemWidthStack.push_back(w_item_one);
+ window->DC.ItemWidth = (components == 1) ? w_item_last : w_item_one;
+ g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth;
+}
+
+void ImGui::PopItemWidth()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ window->DC.ItemWidth = window->DC.ItemWidthStack.back();
+ window->DC.ItemWidthStack.pop_back();
+}
+
+// Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth().
+// The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags()
+float ImGui::CalcItemWidth()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ float w;
+ if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
+ w = g.NextItemData.Width;
+ else
+ w = window->DC.ItemWidth;
+ if (w < 0.0f)
+ {
+ float region_max_x = GetContentRegionMaxAbs().x;
+ w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w);
+ }
+ w = IM_FLOOR(w);
+ return w;
+}
+
+// [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth().
+// Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical.
+// Note that only CalcItemWidth() is publicly exposed.
+// The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable)
+ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h)
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+
+ ImVec2 region_max;
+ if (size.x < 0.0f || size.y < 0.0f)
+ region_max = GetContentRegionMaxAbs();
+
+ if (size.x == 0.0f)
+ size.x = default_w;
+ else if (size.x < 0.0f)
+ size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x);
+
+ if (size.y == 0.0f)
+ size.y = default_h;
+ else if (size.y < 0.0f)
+ size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y);
+
+ return size;
+}
+
+float ImGui::GetTextLineHeight()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize;
+}
+
+float ImGui::GetTextLineHeightWithSpacing()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + g.Style.ItemSpacing.y;
+}
+
+float ImGui::GetFrameHeight()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + g.Style.FramePadding.y * 2.0f;
+}
+
+float ImGui::GetFrameHeightWithSpacing()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;
+}
+
+// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience!
+
+// FIXME: This is in window space (not screen space!).
+ImVec2 ImGui::GetContentRegionMax()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImVec2 mx = window->ContentRegionRect.Max - window->Pos;
+ if (window->DC.CurrentColumns || g.CurrentTable)
+ mx.x = window->WorkRect.Max.x - window->Pos.x;
+ return mx;
+}
+
+// [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features.
+ImVec2 ImGui::GetContentRegionMaxAbs()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImVec2 mx = window->ContentRegionRect.Max;
+ if (window->DC.CurrentColumns || g.CurrentTable)
+ mx.x = window->WorkRect.Max.x;
+ return mx;
+}
+
+ImVec2 ImGui::GetContentRegionAvail()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return GetContentRegionMaxAbs() - window->DC.CursorPos;
+}
+
+// In window space (not screen space!)
+ImVec2 ImGui::GetWindowContentRegionMin()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->ContentRegionRect.Min - window->Pos;
+}
+
+ImVec2 ImGui::GetWindowContentRegionMax()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->ContentRegionRect.Max - window->Pos;
+}
+
+// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
+// Groups are currently a mishmash of functionalities which should perhaps be clarified and separated.
+// FIXME-OPT: Could we safely early out on ->SkipItems?
+void ImGui::BeginGroup()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ g.GroupStack.resize(g.GroupStack.Size + 1);
+ ImGuiGroupData& group_data = g.GroupStack.back();
+ group_data.WindowID = window->ID;
+ group_data.BackupCursorPos = window->DC.CursorPos;
+ group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
+ group_data.BackupIndent = window->DC.Indent;
+ group_data.BackupGroupOffset = window->DC.GroupOffset;
+ group_data.BackupCurrLineSize = window->DC.CurrLineSize;
+ group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
+ group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
+ group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
+ group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
+ group_data.EmitItem = true;
+
+ window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
+ window->DC.Indent = window->DC.GroupOffset;
+ window->DC.CursorMaxPos = window->DC.CursorPos;
+ window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
+ if (g.LogEnabled)
+ g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
+}
+
+void ImGui::EndGroup()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(g.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls
+
+ ImGuiGroupData& group_data = g.GroupStack.back();
+ IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window?
+
+ ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos));
+
+ window->DC.CursorPos = group_data.BackupCursorPos;
+ window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
+ window->DC.Indent = group_data.BackupIndent;
+ window->DC.GroupOffset = group_data.BackupGroupOffset;
+ window->DC.CurrLineSize = group_data.BackupCurrLineSize;
+ window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
+ if (g.LogEnabled)
+ g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
+
+ if (!group_data.EmitItem)
+ {
+ g.GroupStack.pop_back();
+ return;
+ }
+
+ window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
+ ItemSize(group_bb.GetSize());
+ ItemAdd(group_bb, 0);
+
+ // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
+ // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
+ // Also if you grep for LastItemId you'll notice it is only used in that context.
+ // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.)
+ const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId;
+ const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true);
+ if (group_contains_curr_active_id)
+ g.LastItemData.ID = g.ActiveId;
+ else if (group_contains_prev_active_id)
+ g.LastItemData.ID = g.ActiveIdPreviousFrame;
+ g.LastItemData.Rect = group_bb;
+
+ // Forward Hovered flag
+ const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0;
+ if (group_contains_curr_hovered_id)
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
+
+ // Forward Edited flag
+ if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
+
+ // Forward Deactivated flag
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated;
+ if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame)
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated;
+
+ g.GroupStack.pop_back();
+ //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] SCROLLING
+//-----------------------------------------------------------------------------
+
+// Helper to snap on edges when aiming at an item very close to the edge,
+// So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling.
+// When we refactor the scrolling API this may be configurable with a flag?
+// Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default.
+static float CalcScrollEdgeSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio)
+{
+ if (target <= snap_min + snap_threshold)
+ return ImLerp(snap_min, target, center_ratio);
+ if (target >= snap_max - snap_threshold)
+ return ImLerp(target, snap_max, center_ratio);
+ return target;
+}
+
+static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
+{
+ ImVec2 scroll = window->Scroll;
+ if (window->ScrollTarget.x < FLT_MAX)
+ {
+ float decoration_total_width = window->ScrollbarSizes.x;
+ float center_x_ratio = window->ScrollTargetCenterRatio.x;
+ float scroll_target_x = window->ScrollTarget.x;
+ if (window->ScrollTargetEdgeSnapDist.x > 0.0f)
+ {
+ float snap_x_min = 0.0f;
+ float snap_x_max = window->ScrollMax.x + window->SizeFull.x - decoration_total_width;
+ scroll_target_x = CalcScrollEdgeSnap(scroll_target_x, snap_x_min, snap_x_max, window->ScrollTargetEdgeSnapDist.x, center_x_ratio);
+ }
+ scroll.x = scroll_target_x - center_x_ratio * (window->SizeFull.x - decoration_total_width);
+ }
+ if (window->ScrollTarget.y < FLT_MAX)
+ {
+ float decoration_total_height = window->TitleBarHeight() + window->MenuBarHeight() + window->ScrollbarSizes.y;
+ float center_y_ratio = window->ScrollTargetCenterRatio.y;
+ float scroll_target_y = window->ScrollTarget.y;
+ if (window->ScrollTargetEdgeSnapDist.y > 0.0f)
+ {
+ float snap_y_min = 0.0f;
+ float snap_y_max = window->ScrollMax.y + window->SizeFull.y - decoration_total_height;
+ scroll_target_y = CalcScrollEdgeSnap(scroll_target_y, snap_y_min, snap_y_max, window->ScrollTargetEdgeSnapDist.y, center_y_ratio);
+ }
+ scroll.y = scroll_target_y - center_y_ratio * (window->SizeFull.y - decoration_total_height);
+ }
+ scroll.x = IM_FLOOR(ImMax(scroll.x, 0.0f));
+ scroll.y = IM_FLOOR(ImMax(scroll.y, 0.0f));
+ if (!window->Collapsed && !window->SkipItems)
+ {
+ scroll.x = ImMin(scroll.x, window->ScrollMax.x);
+ scroll.y = ImMin(scroll.y, window->ScrollMax.y);
+ }
+ return scroll;
+}
+
+void ImGui::ScrollToItem(ImGuiScrollFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ScrollToRectEx(window, g.LastItemData.NavRect, flags);
+}
+
+void ImGui::ScrollToRect(ImGuiWindow* window, const ImRect& item_rect, ImGuiScrollFlags flags)
+{
+ ScrollToRectEx(window, item_rect, flags);
+}
+
+// Scroll to keep newly navigated item fully into view
+ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window, const ImRect& item_rect, ImGuiScrollFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImRect window_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1));
+ //GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
+
+ // Check that only one behavior is selected per axis
+ IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_));
+ IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_));
+
+ // Defaults
+ ImGuiScrollFlags in_flags = flags;
+ if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX)
+ flags |= ImGuiScrollFlags_KeepVisibleEdgeX;
+ if ((flags & ImGuiScrollFlags_MaskY_) == 0)
+ flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY;
+
+ const bool fully_visible_x = item_rect.Min.x >= window_rect.Min.x && item_rect.Max.x <= window_rect.Max.x;
+ const bool fully_visible_y = item_rect.Min.y >= window_rect.Min.y && item_rect.Max.y <= window_rect.Max.y;
+ const bool can_be_fully_visible_x = (item_rect.GetWidth() + g.Style.ItemSpacing.x * 2.0f) <= window_rect.GetWidth();
+ const bool can_be_fully_visible_y = (item_rect.GetHeight() + g.Style.ItemSpacing.y * 2.0f) <= window_rect.GetHeight();
+
+ if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x)
+ {
+ if (item_rect.Min.x < window_rect.Min.x || !can_be_fully_visible_x)
+ SetScrollFromPosX(window, item_rect.Min.x - g.Style.ItemSpacing.x - window->Pos.x, 0.0f);
+ else if (item_rect.Max.x >= window_rect.Max.x)
+ SetScrollFromPosX(window, item_rect.Max.x + g.Style.ItemSpacing.x - window->Pos.x, 1.0f);
+ }
+ else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) || (flags & ImGuiScrollFlags_AlwaysCenterX))
+ {
+ float target_x = can_be_fully_visible_x ? ImFloor((item_rect.Min.x + item_rect.Max.x - window->InnerRect.GetWidth()) * 0.5f) : item_rect.Min.x;
+ SetScrollFromPosX(window, target_x - window->Pos.x, 0.0f);
+ }
+
+ if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y)
+ {
+ if (item_rect.Min.y < window_rect.Min.y || !can_be_fully_visible_y)
+ SetScrollFromPosY(window, item_rect.Min.y - g.Style.ItemSpacing.y - window->Pos.y, 0.0f);
+ else if (item_rect.Max.y >= window_rect.Max.y)
+ SetScrollFromPosY(window, item_rect.Max.y + g.Style.ItemSpacing.y - window->Pos.y, 1.0f);
+ }
+ else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) || (flags & ImGuiScrollFlags_AlwaysCenterY))
+ {
+ float target_y = can_be_fully_visible_y ? ImFloor((item_rect.Min.y + item_rect.Max.y - window->InnerRect.GetHeight()) * 0.5f) : item_rect.Min.y;
+ SetScrollFromPosY(window, target_y - window->Pos.y, 0.0f);
+ }
+
+ ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
+ ImVec2 delta_scroll = next_scroll - window->Scroll;
+
+ // Also scroll parent window to keep us into view if necessary
+ if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow))
+ {
+ // FIXME-SCROLL: May be an option?
+ if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0)
+ in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX;
+ if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0)
+ in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY;
+ delta_scroll += ScrollToRectEx(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags);
+ }
+
+ return delta_scroll;
+}
+
+float ImGui::GetScrollX()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->Scroll.x;
+}
+
+float ImGui::GetScrollY()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->Scroll.y;
+}
+
+float ImGui::GetScrollMaxX()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->ScrollMax.x;
+}
+
+float ImGui::GetScrollMaxY()
+{
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->ScrollMax.y;
+}
+
+void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x)
+{
+ window->ScrollTarget.x = scroll_x;
+ window->ScrollTargetCenterRatio.x = 0.0f;
+ window->ScrollTargetEdgeSnapDist.x = 0.0f;
+}
+
+void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y)
+{
+ window->ScrollTarget.y = scroll_y;
+ window->ScrollTargetCenterRatio.y = 0.0f;
+ window->ScrollTargetEdgeSnapDist.y = 0.0f;
+}
+
+void ImGui::SetScrollX(float scroll_x)
+{
+ ImGuiContext& g = *GImGui;
+ SetScrollX(g.CurrentWindow, scroll_x);
+}
+
+void ImGui::SetScrollY(float scroll_y)
+{
+ ImGuiContext& g = *GImGui;
+ SetScrollY(g.CurrentWindow, scroll_y);
+}
+
+// Note that a local position will vary depending on initial scroll value,
+// This is a little bit confusing so bear with us:
+// - local_pos = (absolution_pos - window->Pos)
+// - So local_x/local_y are 0.0f for a position at the upper-left corner of a window,
+// and generally local_x/local_y are >(padding+decoration) && <(size-padding-decoration) when in the visible area.
+// - They mostly exists because of legacy API.
+// Following the rules above, when trying to work with scrolling code, consider that:
+// - SetScrollFromPosY(0.0f) == SetScrollY(0.0f + scroll.y) == has no effect!
+// - SetScrollFromPosY(-scroll.y) == SetScrollY(-scroll.y + scroll.y) == SetScrollY(0.0f) == reset scroll. Of course writing SetScrollY(0.0f) directly then makes more sense
+// We store a target position so centering and clamping can occur on the next frame when we are guaranteed to have a known window size
+void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio)
+{
+ IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f);
+ window->ScrollTarget.x = IM_FLOOR(local_x + window->Scroll.x); // Convert local position to scroll offset
+ window->ScrollTargetCenterRatio.x = center_x_ratio;
+ window->ScrollTargetEdgeSnapDist.x = 0.0f;
+}
+
+void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio)
+{
+ IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
+ const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); // FIXME: Would be nice to have a more standardized access to our scrollable/client rect;
+ local_y -= decoration_up_height;
+ window->ScrollTarget.y = IM_FLOOR(local_y + window->Scroll.y); // Convert local position to scroll offset
+ window->ScrollTargetCenterRatio.y = center_y_ratio;
+ window->ScrollTargetEdgeSnapDist.y = 0.0f;
+}
+
+void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio)
+{
+ ImGuiContext& g = *GImGui;
+ SetScrollFromPosX(g.CurrentWindow, local_x, center_x_ratio);
+}
+
+void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio)
+{
+ ImGuiContext& g = *GImGui;
+ SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio);
+}
+
+// center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item.
+void ImGui::SetScrollHereX(float center_x_ratio)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ float spacing_x = ImMax(window->WindowPadding.x, g.Style.ItemSpacing.x);
+ float target_pos_x = ImLerp(g.LastItemData.Rect.Min.x - spacing_x, g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio);
+ SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos
+
+ // Tweak: snap on edges when aiming at an item very close to the edge
+ window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x);
+}
+
+// center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item.
+void ImGui::SetScrollHereY(float center_y_ratio)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ float spacing_y = ImMax(window->WindowPadding.y, g.Style.ItemSpacing.y);
+ float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio);
+ SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos
+
+ // Tweak: snap on edges when aiming at an item very close to the edge
+ window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] TOOLTIPS
+//-----------------------------------------------------------------------------
+
+void ImGui::BeginTooltip()
+{
+ BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
+}
+
+void ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
+{
+ ImGuiContext& g = *GImGui;
+
+ if (g.DragDropWithinSource || g.DragDropWithinTarget)
+ {
+ // The default tooltip position is a little offset to give space to see the context menu (it's also clamped within the current viewport/monitor)
+ // In the context of a dragging tooltip we try to reduce that offset and we enforce following the cursor.
+ // Whatever we do we want to call SetNextWindowPos() to enforce a tooltip position and disable clipping the tooltip without our display area, like regular tooltip do.
+ //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding;
+ ImVec2 tooltip_pos = g.IO.MousePos + ImVec2(16 * g.Style.MouseCursorScale, 8 * g.Style.MouseCursorScale);
+ SetNextWindowPos(tooltip_pos);
+ SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f);
+ //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :(
+ tooltip_flags |= ImGuiTooltipFlags_OverridePreviousTooltip;
+ }
+
+ char window_name[16];
+ ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount);
+ if (tooltip_flags & ImGuiTooltipFlags_OverridePreviousTooltip)
+ if (ImGuiWindow* window = FindWindowByName(window_name))
+ if (window->Active)
+ {
+ // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
+ window->Hidden = true;
+ window->HiddenFramesCanSkipItems = 1; // FIXME: This may not be necessary?
+ ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
+ }
+ ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize;
+ Begin(window_name, NULL, flags | extra_window_flags);
+}
+
+void ImGui::EndTooltip()
+{
+ IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls
+ End();
+}
+
+void ImGui::SetTooltipV(const char* fmt, va_list args)
+{
+ BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None);
+ TextV(fmt, args);
+ EndTooltip();
+}
+
+void ImGui::SetTooltip(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ SetTooltipV(fmt, args);
+ va_end(args);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] POPUPS
+//-----------------------------------------------------------------------------
+
+// Supported flags: ImGuiPopupFlags_AnyPopupId, ImGuiPopupFlags_AnyPopupLevel
+bool ImGui::IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (popup_flags & ImGuiPopupFlags_AnyPopupId)
+ {
+ // Return true if any popup is open at the current BeginPopup() level of the popup stack
+ // This may be used to e.g. test for another popups already opened to handle popups priorities at the same level.
+ IM_ASSERT(id == 0);
+ if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
+ return g.OpenPopupStack.Size > 0;
+ else
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size;
+ }
+ else
+ {
+ if (popup_flags & ImGuiPopupFlags_AnyPopupLevel)
+ {
+ // Return true if the popup is open anywhere in the popup stack
+ for (int n = 0; n < g.OpenPopupStack.Size; n++)
+ if (g.OpenPopupStack[n].PopupId == id)
+ return true;
+ return false;
+ }
+ else
+ {
+ // Return true if the popup is open at the current BeginPopup() level of the popup stack (this is the most-common query)
+ return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id;
+ }
+ }
+}
+
+bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiID id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 : g.CurrentWindow->GetID(str_id);
+ if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) && id != 0)
+ IM_ASSERT(0 && "Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel."); // But non-string version is legal and used internally
+ return IsPopupOpen(id, popup_flags);
+}
+
+ImGuiWindow* ImGui::GetTopMostPopupModal()
+{
+ ImGuiContext& g = *GImGui;
+ for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--)
+ if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window)
+ if (popup->Flags & ImGuiWindowFlags_Modal)
+ return popup;
+ return NULL;
+}
+
+void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ OpenPopupEx(g.CurrentWindow->GetID(str_id), popup_flags);
+}
+
+void ImGui::OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags)
+{
+ OpenPopupEx(id, popup_flags);
+}
+
+// Mark popup as open (toggle toward open state).
+// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.
+// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
+// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
+void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* parent_window = g.CurrentWindow;
+ const int current_stack_size = g.BeginPopupStack.Size;
+
+ if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup)
+ if (IsPopupOpen(0u, ImGuiPopupFlags_AnyPopupId))
+ return;
+
+ ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack.
+ popup_ref.PopupId = id;
+ popup_ref.Window = NULL;
+ popup_ref.SourceWindow = g.NavWindow;
+ popup_ref.OpenFrameCount = g.FrameCount;
+ popup_ref.OpenParentId = parent_window->IDStack.back();
+ popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
+ popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
+
+ IMGUI_DEBUG_LOG_POPUP("OpenPopupEx(0x%08X)\n", id);
+ if (g.OpenPopupStack.Size < current_stack_size + 1)
+ {
+ g.OpenPopupStack.push_back(popup_ref);
+ }
+ else
+ {
+ // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui
+ // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing
+ // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand.
+ if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1)
+ {
+ g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
+ }
+ else
+ {
+ // Close child popups if any, then flag popup for open/reopen
+ ClosePopupToLevel(current_stack_size, false);
+ g.OpenPopupStack.push_back(popup_ref);
+ }
+
+ // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
+ // This is equivalent to what ClosePopupToLevel() does.
+ //if (g.OpenPopupStack[current_stack_size].PopupId == id)
+ // FocusWindow(parent_window);
+ }
+}
+
+// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
+// This function closes any popups that are over 'ref_window'.
+void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.OpenPopupStack.Size == 0)
+ return;
+
+ // Don't close our own child popup windows.
+ int popup_count_to_keep = 0;
+ if (ref_window)
+ {
+ // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow)
+ for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++)
+ {
+ ImGuiPopupData& popup = g.OpenPopupStack[popup_count_to_keep];
+ if (!popup.Window)
+ continue;
+ IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
+ if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)
+ continue;
+
+ // Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow)
+ // - With this stack of window, clicking/focusing Popup1 will close Popup2 and Popup3:
+ // Window -> Popup1 -> Popup2 -> Popup3
+ // - Each popups may contain child windows, which is why we compare ->RootWindow!
+ // Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
+ bool ref_window_is_descendent_of_popup = false;
+ for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
+ if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
+ if (popup_window->RootWindow == ref_window->RootWindow)
+ {
+ ref_window_is_descendent_of_popup = true;
+ break;
+ }
+ if (!ref_window_is_descendent_of_popup)
+ break;
+ }
+ }
+ if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
+ {
+ IMGUI_DEBUG_LOG_POPUP("ClosePopupsOverWindow(\"%s\") -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
+ ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup);
+ }
+}
+
+void ImGui::ClosePopupsExceptModals()
+{
+ ImGuiContext& g = *GImGui;
+
+ int popup_count_to_keep;
+ for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
+ {
+ ImGuiWindow* window = g.OpenPopupStack[popup_count_to_keep - 1].Window;
+ if (!window || window->Flags & ImGuiWindowFlags_Modal)
+ break;
+ }
+ if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
+ ClosePopupToLevel(popup_count_to_keep, true);
+}
+
+void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup)
+{
+ ImGuiContext& g = *GImGui;
+ IMGUI_DEBUG_LOG_POPUP("ClosePopupToLevel(%d), restore_focus_to_window_under_popup=%d\n", remaining, restore_focus_to_window_under_popup);
+ IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size);
+
+ // Trim open popup stack
+ ImGuiWindow* focus_window = g.OpenPopupStack[remaining].SourceWindow;
+ ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window;
+ g.OpenPopupStack.resize(remaining);
+
+ if (restore_focus_to_window_under_popup)
+ {
+ if (focus_window && !focus_window->WasActive && popup_window)
+ {
+ // Fallback
+ FocusTopMostWindowUnderOne(popup_window, NULL);
+ }
+ else
+ {
+ if (g.NavLayer == ImGuiNavLayer_Main && focus_window)
+ focus_window = NavRestoreLastChildNavWindow(focus_window);
+ FocusWindow(focus_window);
+ }
+ }
+}
+
+// Close the popup we have begin-ed into.
+void ImGui::CloseCurrentPopup()
+{
+ ImGuiContext& g = *GImGui;
+ int popup_idx = g.BeginPopupStack.Size - 1;
+ if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
+ return;
+
+ // Closing a menu closes its top-most parent popup (unless a modal)
+ while (popup_idx > 0)
+ {
+ ImGuiWindow* popup_window = g.OpenPopupStack[popup_idx].Window;
+ ImGuiWindow* parent_popup_window = g.OpenPopupStack[popup_idx - 1].Window;
+ bool close_parent = false;
+ if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu))
+ if (parent_popup_window == NULL || !(parent_popup_window->Flags & ImGuiWindowFlags_Modal))
+ close_parent = true;
+ if (!close_parent)
+ break;
+ popup_idx--;
+ }
+ IMGUI_DEBUG_LOG_POPUP("CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx);
+ ClosePopupToLevel(popup_idx, true);
+
+ // A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
+ // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window.
+ // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic.
+ if (ImGuiWindow* window = g.NavWindow)
+ window->DC.NavHideHighlightOneFrame = true;
+}
+
+// Attention! BeginPopup() adds default flags which BeginPopupEx()!
+bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (!IsPopupOpen(id, ImGuiPopupFlags_None))
+ {
+ g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
+ return false;
+ }
+
+ char name[20];
+ if (flags & ImGuiWindowFlags_ChildMenu)
+ ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
+ else
+ ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
+
+ flags |= ImGuiWindowFlags_Popup;
+ bool is_open = Begin(name, NULL, flags);
+ if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
+ EndPopup();
+
+ return is_open;
+}
+
+bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance
+ {
+ g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
+ return false;
+ }
+ flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings;
+ return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags);
+}
+
+// If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup.
+// Note that popup visibility status is owned by Dear ImGui (and manipulated with e.g. OpenPopup) so the actual value of *p_open is meaningless here.
+bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ const ImGuiID id = window->GetID(name);
+ if (!IsPopupOpen(id, ImGuiPopupFlags_None))
+ {
+ g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
+ return false;
+ }
+
+ // Center modal windows by default for increased visibility
+ // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves)
+ // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
+ if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0)
+ {
+ const ImGuiViewport* viewport = GetMainViewport();
+ SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f));
+ }
+
+ flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse;
+ const bool is_open = Begin(name, p_open, flags);
+ if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
+ {
+ EndPopup();
+ if (is_open)
+ ClosePopupToLevel(g.BeginPopupStack.Size, true);
+ return false;
+ }
+ return is_open;
+}
+
+void ImGui::EndPopup()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls
+ IM_ASSERT(g.BeginPopupStack.Size > 0);
+
+ // Make all menus and popups wrap around for now, may need to expose that policy (e.g. focus scope could include wrap/loop policy flags used by new move requests)
+ if (g.NavWindow == window)
+ NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
+
+ // Child-popups don't need to be laid out
+ IM_ASSERT(g.WithinEndChild == false);
+ if (window->Flags & ImGuiWindowFlags_ChildWindow)
+ g.WithinEndChild = true;
+ End();
+ g.WithinEndChild = false;
+}
+
+// Helper to open a popup if mouse button is released over the item
+// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup()
+void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
+ if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ {
+ ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
+ IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
+ OpenPopupEx(id, popup_flags);
+ }
+}
+
+// This is a helper to handle the simplest case of associating one named popup to one given widget.
+// - To create a popup associated to the last item, you generally want to pass a NULL value to str_id.
+// - To create a popup with a specific identifier, pass it in str_id.
+// - This is useful when using using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call.
+// - This is useful when multiple code locations may want to manipulate/open the same popup, given an explicit id.
+// - You may want to handle the whole on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters).
+// This is essentially the same as:
+// id = str_id ? GetID(str_id) : GetItemID();
+// OpenPopupOnItemClick(str_id);
+// return BeginPopup(id);
+// Which is essentially the same as:
+// id = str_id ? GetID(str_id) : GetItemID();
+// if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
+// OpenPopup(id);
+// return BeginPopup(id);
+// The main difference being that this is tweaked to avoid computing the ID twice.
+bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+ ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
+ IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
+ if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ OpenPopupEx(id, popup_flags);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
+}
+
+bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!str_id)
+ str_id = "window_context";
+ ImGuiID id = window->GetID(str_id);
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
+ if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
+ if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
+ OpenPopupEx(id, popup_flags);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
+}
+
+bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!str_id)
+ str_id = "void_context";
+ ImGuiID id = window->GetID(str_id);
+ int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_);
+ if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
+ if (GetTopMostPopupModal() == NULL)
+ OpenPopupEx(id, popup_flags);
+ return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
+}
+
+// r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.)
+// r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it.
+// (r_outer is usually equivalent to the viewport rectangle minus padding, but when multi-viewports are enabled and monitor
+// information are available, it may represent the entire platform monitor from the frame of reference of the current viewport.
+// this allows us to have tooltips/popups displayed out of the parent viewport.)
+ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy)
+{
+ ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size);
+ //GetForegroundDrawList()->AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255));
+ //GetForegroundDrawList()->AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255));
+
+ // Combo Box policy (we want a connecting edge)
+ if (policy == ImGuiPopupPositionPolicy_ComboBox)
+ {
+ const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up };
+ for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
+ {
+ const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
+ if (n != -1 && dir == *last_dir) // Already tried this direction?
+ continue;
+ ImVec2 pos;
+ if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default)
+ if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right
+ if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left
+ if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left
+ if (!r_outer.Contains(ImRect(pos, pos + size)))
+ continue;
+ *last_dir = dir;
+ return pos;
+ }
+ }
+
+ // Tooltip and Default popup policy
+ // (Always first try the direction we used on the last frame, if any)
+ if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default)
+ {
+ const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
+ for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
+ {
+ const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
+ if (n != -1 && dir == *last_dir) // Already tried this direction?
+ continue;
+
+ const float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
+ const float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
+
+ // If there not enough room on one axis, there's no point in positioning on a side on this axis (e.g. when not enough width, use a top/bottom position to maximize available width)
+ if (avail_w < size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
+ continue;
+ if (avail_h < size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
+ continue;
+
+ ImVec2 pos;
+ pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
+ pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
+
+ // Clamp top-left corner of popup
+ pos.x = ImMax(pos.x, r_outer.Min.x);
+ pos.y = ImMax(pos.y, r_outer.Min.y);
+
+ *last_dir = dir;
+ return pos;
+ }
+ }
+
+ // Fallback when not enough room:
+ *last_dir = ImGuiDir_None;
+
+ // For tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.
+ if (policy == ImGuiPopupPositionPolicy_Tooltip)
+ return ref_pos + ImVec2(2, 2);
+
+ // Otherwise try to keep within display
+ ImVec2 pos = ref_pos;
+ pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
+ pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
+ return pos;
+}
+
+// Note that this is used for popups, which can overlap the non work-area of individual viewports.
+ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ IM_UNUSED(window);
+ ImRect r_screen = ((ImGuiViewportP*)(void*)GetMainViewport())->GetMainRect();
+ ImVec2 padding = g.Style.DisplaySafeAreaPadding;
+ r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f));
+ return r_screen;
+}
+
+ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+
+ ImRect r_outer = GetPopupAllowedExtentRect(window);
+ if (window->Flags & ImGuiWindowFlags_ChildMenu)
+ {
+ // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds.
+ // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu.
+ IM_ASSERT(g.CurrentWindow == window);
+ ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2].Window;
+ float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x).
+ ImRect r_avoid;
+ if (parent_window->DC.MenuBarAppending)
+ r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindowData.PosConstraintAvoidRect field
+ else
+ r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);
+ return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
+ }
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ {
+ ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1);
+ return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
+ }
+ if (window->Flags & ImGuiWindowFlags_Tooltip)
+ {
+ // Position tooltip (always follows mouse)
+ float sc = g.Style.MouseCursorScale;
+ ImVec2 ref_pos = NavCalcPreferredRefPos();
+ ImRect r_avoid;
+ if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
+ r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
+ else
+ r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
+ return FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
+ }
+ IM_ASSERT(0);
+ return window->Pos;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
+//-----------------------------------------------------------------------------
+
+// FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked.
+// In our terminology those should be interchangeable. Those two functions are merely a legacy artifact, so at minimum naming should be clarified.
+void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindow != NULL);
+ IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
+ g.NavId = id;
+ g.NavLayer = nav_layer;
+ g.NavFocusScopeId = focus_scope_id;
+ g.NavWindow->NavLastIds[nav_layer] = id;
+ g.NavWindow->NavRectRel[nav_layer] = rect_rel;
+}
+
+void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(id != 0);
+
+ // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid.
+ // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text)
+ const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
+ if (g.NavWindow != window)
+ g.NavInitRequest = false;
+ g.NavWindow = window;
+ g.NavId = id;
+ g.NavLayer = nav_layer;
+ g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
+ window->NavLastIds[nav_layer] = id;
+ if (g.LastItemData.ID == id)
+ window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
+
+ if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ g.NavDisableMouseHover = true;
+ else
+ g.NavDisableHighlight = true;
+}
+
+ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy)
+{
+ if (ImFabs(dx) > ImFabs(dy))
+ return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left;
+ return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up;
+}
+
+static float inline NavScoreItemDistInterval(float a0, float a1, float b0, float b1)
+{
+ if (a1 < b0)
+ return a1 - b0;
+ if (b1 < a0)
+ return a0 - b1;
+ return 0.0f;
+}
+
+static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect)
+{
+ if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
+ {
+ r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y);
+ r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y);
+ }
+ else // FIXME: PageUp/PageDown are leaving move_dir == None
+ {
+ r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x);
+ r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x);
+ }
+}
+
+// Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
+static bool ImGui::NavScoreItem(ImGuiNavItemData* result)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.NavLayer != window->DC.NavLayerCurrent)
+ return false;
+
+ // FIXME: Those are not good variables names
+ ImRect cand = g.LastItemData.NavRect; // Current item nav rectangle
+ const ImRect curr = g.NavScoringRect; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width)
+ g.NavScoringDebugCount++;
+
+ // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
+ if (window->ParentWindow == g.NavWindow)
+ {
+ IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened);
+ if (!window->ClipRect.Overlaps(cand))
+ return false;
+ cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window
+ }
+
+ // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items)
+ // For example, this ensure that items in one column are not reached when moving vertically from items in another column.
+ NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect);
+
+ // Compute distance between boxes
+ // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed.
+ float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x);
+ float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items
+ if (dby != 0.0f && dbx != 0.0f)
+ dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f);
+ float dist_box = ImFabs(dbx) + ImFabs(dby);
+
+ // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter)
+ float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x);
+ float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y);
+ float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee)
+
+ // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance
+ ImGuiDir quadrant;
+ float dax = 0.0f, day = 0.0f, dist_axial = 0.0f;
+ if (dbx != 0.0f || dby != 0.0f)
+ {
+ // For non-overlapping boxes, use distance between boxes
+ dax = dbx;
+ day = dby;
+ dist_axial = dist_box;
+ quadrant = ImGetDirQuadrantFromDelta(dbx, dby);
+ }
+ else if (dcx != 0.0f || dcy != 0.0f)
+ {
+ // For overlapping boxes with different centers, use distance between centers
+ dax = dcx;
+ day = dcy;
+ dist_axial = dist_center;
+ quadrant = ImGetDirQuadrantFromDelta(dcx, dcy);
+ }
+ else
+ {
+ // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter)
+ quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
+ }
+
+#if IMGUI_DEBUG_NAV_SCORING
+ char buf[128];
+ if (IsMouseHoveringRect(cand.Min, cand.Max))
+ {
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]);
+ ImDrawList* draw_list = GetForegroundDrawList(window);
+ draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255,200,0,100));
+ draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200));
+ draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max + CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40,0,0,150));
+ draw_list->AddText(cand.Max, ~0U, buf);
+ }
+ else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate.
+ {
+ if (quadrant == g.NavMoveDir)
+ {
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center);
+ ImDrawList* draw_list = GetForegroundDrawList(window);
+ draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200));
+ draw_list->AddText(cand.Min, IM_COL32(255, 255, 255, 255), buf);
+ }
+ }
+#endif
+
+ // Is it in the quadrant we're interesting in moving to?
+ bool new_best = false;
+ const ImGuiDir move_dir = g.NavMoveDir;
+ if (quadrant == move_dir)
+ {
+ // Does it beat the current best candidate?
+ if (dist_box < result->DistBox)
+ {
+ result->DistBox = dist_box;
+ result->DistCenter = dist_center;
+ return true;
+ }
+ if (dist_box == result->DistBox)
+ {
+ // Try using distance between center points to break ties
+ if (dist_center < result->DistCenter)
+ {
+ result->DistCenter = dist_center;
+ new_best = true;
+ }
+ else if (dist_center == result->DistCenter)
+ {
+ // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items
+ // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index),
+ // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis.
+ if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance
+ new_best = true;
+ }
+ }
+ }
+
+ // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches
+ // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness)
+ // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too.
+ // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward.
+ // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option?
+ if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match
+ if (g.NavLayer == ImGuiNavLayer_Menu && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
+ if ((move_dir == ImGuiDir_Left && dax < 0.0f) || (move_dir == ImGuiDir_Right && dax > 0.0f) || (move_dir == ImGuiDir_Up && day < 0.0f) || (move_dir == ImGuiDir_Down && day > 0.0f))
+ {
+ result->DistAxial = dist_axial;
+ new_best = true;
+ }
+
+ return new_best;
+}
+
+static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ result->Window = window;
+ result->ID = g.LastItemData.ID;
+ result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
+ result->InFlags = g.LastItemData.InFlags;
+ result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
+}
+
+// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
+// This is called after LastItemData is set.
+static void ImGui::NavProcessItem()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ const ImGuiID id = g.LastItemData.ID;
+ const ImRect nav_bb = g.LastItemData.NavRect;
+ const ImGuiItemFlags item_flags = g.LastItemData.InFlags;
+
+ // Process Init Request
+ if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
+ {
+ // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback
+ const bool candidate_for_nav_default_focus = (item_flags & (ImGuiItemFlags_NoNavDefaultFocus | ImGuiItemFlags_Disabled)) == 0;
+ if (candidate_for_nav_default_focus || g.NavInitResultId == 0)
+ {
+ g.NavInitResultId = id;
+ g.NavInitResultRectRel = WindowRectAbsToRel(window, nav_bb);
+ }
+ if (candidate_for_nav_default_focus)
+ {
+ g.NavInitRequest = false; // Found a match, clear request
+ NavUpdateAnyRequestFlag();
+ }
+ }
+
+ // Process Move Request (scoring for navigation)
+ // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy)
+ if (g.NavMoveScoringItems)
+ {
+ const bool is_tab_stop = (item_flags & ImGuiItemFlags_Inputable) && (item_flags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
+ const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) != 0;
+ if (is_tabbing)
+ {
+ if (is_tab_stop || (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi))
+ NavProcessItemForTabbingRequest(id);
+ }
+ else if ((g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
+ {
+ ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
+ if (!is_tabbing)
+ {
+ if (NavScoreItem(result))
+ NavApplyItemToResult(result);
+
+ // Features like PageUp/PageDown need to maintain a separate score for the visible set of items.
+ const float VISIBLE_RATIO = 0.70f;
+ if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
+ if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
+ if (NavScoreItem(&g.NavMoveResultLocalVisible))
+ NavApplyItemToResult(&g.NavMoveResultLocalVisible);
+ }
+ }
+ }
+
+ // Update window-relative bounding box of navigated item
+ if (g.NavId == id)
+ {
+ g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
+ g.NavLayer = window->DC.NavLayerCurrent;
+ g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
+ g.NavIdIsAlive = true;
+ window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position)
+ }
+}
+
+// Handle "scoring" of an item for a tabbing/focusing request initiated by NavUpdateCreateTabbingRequest().
+// Note that SetKeyboardFocusHere() API calls are considered tabbing requests!
+// - Case 1: no nav/active id: set result to first eligible item, stop storing.
+// - Case 2: tab forward: on ref id set counter, on counter elapse store result
+// - Case 3: tab forward wrap: set result to first eligible item (preemptively), on ref id set counter, on next frame if counter hasn't elapsed store result. // FIXME-TABBING: Could be done as a next-frame forwarded request
+// - Case 4: tab backward: store all results, on ref id pick prev, stop storing
+// - Case 5: tab backward wrap: store all results, on ref id if no result keep storing until last // FIXME-TABBING: Could be done as next-frame forwarded requested
+void ImGui::NavProcessItemForTabbingRequest(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Always store in NavMoveResultLocal (unlike directional request which uses NavMoveResultOther on sibling/flattened windows)
+ ImGuiNavItemData* result = &g.NavMoveResultLocal;
+ if (g.NavTabbingDir == +1)
+ {
+ // Tab Forward or SetKeyboardFocusHere() with >= 0
+ if (g.NavTabbingResultFirst.ID == 0)
+ NavApplyItemToResult(&g.NavTabbingResultFirst);
+ if (--g.NavTabbingCounter == 0)
+ NavMoveRequestResolveWithLastItem(result);
+ else if (g.NavId == id)
+ g.NavTabbingCounter = 1;
+ }
+ else if (g.NavTabbingDir == -1)
+ {
+ // Tab Backward
+ if (g.NavId == id)
+ {
+ if (result->ID)
+ {
+ g.NavMoveScoringItems = false;
+ NavUpdateAnyRequestFlag();
+ }
+ }
+ else
+ {
+ NavApplyItemToResult(result);
+ }
+ }
+ else if (g.NavTabbingDir == 0)
+ {
+ // Tab Init
+ if (g.NavTabbingResultFirst.ID == 0)
+ NavMoveRequestResolveWithLastItem(&g.NavTabbingResultFirst);
+ }
+}
+
+bool ImGui::NavMoveRequestButNoResultYet()
+{
+ ImGuiContext& g = *GImGui;
+ return g.NavMoveScoringItems && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0;
+}
+
+// FIXME: ScoringRect is not set
+void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindow != NULL);
+
+ if (move_flags & ImGuiNavMoveFlags_Tabbing)
+ move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId;
+
+ g.NavMoveSubmitted = g.NavMoveScoringItems = true;
+ g.NavMoveDir = move_dir;
+ g.NavMoveDirForDebug = move_dir;
+ g.NavMoveClipDir = clip_dir;
+ g.NavMoveFlags = move_flags;
+ g.NavMoveScrollFlags = scroll_flags;
+ g.NavMoveForwardToNextFrame = false;
+ g.NavMoveKeyMods = g.IO.KeyMods;
+ g.NavTabbingCounter = 0;
+ g.NavMoveResultLocal.Clear();
+ g.NavMoveResultLocalVisible.Clear();
+ g.NavMoveResultOther.Clear();
+ NavUpdateAnyRequestFlag();
+}
+
+void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result)
+{
+ ImGuiContext& g = *GImGui;
+ g.NavMoveScoringItems = false; // Ensure request doesn't need more processing
+ NavApplyItemToResult(result);
+ NavUpdateAnyRequestFlag();
+}
+
+void ImGui::NavMoveRequestCancel()
+{
+ ImGuiContext& g = *GImGui;
+ g.NavMoveSubmitted = g.NavMoveScoringItems = false;
+ NavUpdateAnyRequestFlag();
+}
+
+// Forward will reuse the move request again on the next frame (generally with modifications done to it)
+void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavMoveForwardToNextFrame == false);
+ NavMoveRequestCancel();
+ g.NavMoveForwardToNextFrame = true;
+ g.NavMoveDir = move_dir;
+ g.NavMoveClipDir = clip_dir;
+ g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded;
+ g.NavMoveScrollFlags = scroll_flags;
+}
+
+// Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire
+// popup is assembled and in case of appended popups it is not clear which EndPopup() call is final.
+void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(wrap_flags != 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY
+ // In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it, NavEndFrame() will do the same test
+ if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main)
+ g.NavMoveFlags |= wrap_flags;
+}
+
+// FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0).
+// This way we could find the last focused window among our children. It would be much less confusing this way?
+static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
+{
+ ImGuiWindow* parent = nav_window;
+ while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
+ parent = parent->ParentWindow;
+ if (parent && parent != nav_window)
+ parent->NavLastChildNavWindow = nav_window;
+}
+
+// Restore the last focused child.
+// Call when we are expected to land on the Main Layer (0) after FocusWindow()
+static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
+{
+ if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
+ return window->NavLastChildNavWindow;
+ return window;
+}
+
+void ImGui::NavRestoreLayer(ImGuiNavLayer layer)
+{
+ ImGuiContext& g = *GImGui;
+ if (layer == ImGuiNavLayer_Main)
+ g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow);
+ ImGuiWindow* window = g.NavWindow;
+ if (window->NavLastIds[layer] != 0)
+ {
+ SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
+ }
+ else
+ {
+ g.NavLayer = layer;
+ NavInitWindow(window, true);
+ }
+}
+
+void ImGui::NavRestoreHighlightAfterMove()
+{
+ ImGuiContext& g = *GImGui;
+ g.NavDisableHighlight = false;
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
+}
+
+static inline void ImGui::NavUpdateAnyRequestFlag()
+{
+ ImGuiContext& g = *GImGui;
+ g.NavAnyRequest = g.NavMoveScoringItems || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
+ if (g.NavAnyRequest)
+ IM_ASSERT(g.NavWindow != NULL);
+}
+
+// This needs to be called before we submit any widget (aka in or before Begin)
+void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(window == g.NavWindow);
+
+ if (window->Flags & ImGuiWindowFlags_NoNavInputs)
+ {
+ g.NavId = g.NavFocusScopeId = 0;
+ return;
+ }
+
+ bool init_for_nav = false;
+ if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
+ init_for_nav = true;
+ IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer);
+ if (init_for_nav)
+ {
+ SetNavID(0, g.NavLayer, 0, ImRect());
+ g.NavInitRequest = true;
+ g.NavInitRequestFromMove = false;
+ g.NavInitResultId = 0;
+ g.NavInitResultRectRel = ImRect();
+ NavUpdateAnyRequestFlag();
+ }
+ else
+ {
+ g.NavId = window->NavLastIds[0];
+ g.NavFocusScopeId = 0;
+ }
+}
+
+static ImVec2 ImGui::NavCalcPreferredRefPos()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.NavWindow;
+ if (g.NavDisableHighlight || !g.NavDisableMouseHover || !window)
+ {
+ // Mouse (we need a fallback in case the mouse becomes invalid after being used)
+ if (IsMousePosValid(&g.IO.MousePos))
+ return g.IO.MousePos;
+ return g.MouseLastValidPos;
+ }
+ else
+ {
+ // When navigation is active and mouse is disabled, pick a position around the bottom left of the currently navigated item
+ // Take account of upcoming scrolling (maybe set mouse pos should be done in EndFrame?)
+ ImRect rect_rel = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]);
+ if (window->LastFrameActive != g.FrameCount && (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX))
+ {
+ ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window);
+ rect_rel.Translate(window->Scroll - next_scroll);
+ }
+ ImVec2 pos = ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
+ ImGuiViewport* viewport = GetMainViewport();
+ return ImFloor(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta.
+ }
+}
+
+float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode)
+{
+ ImGuiContext& g = *GImGui;
+ if (mode == ImGuiInputReadMode_Down)
+ return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user)
+
+ const float t = g.IO.NavInputsDownDuration[n];
+ if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input.
+ return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f);
+ if (t < 0.0f)
+ return 0.0f;
+ if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input.
+ return (t == 0.0f) ? 1.0f : 0.0f;
+ if (mode == ImGuiInputReadMode_Repeat)
+ return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.80f);
+ if (mode == ImGuiInputReadMode_RepeatSlow)
+ return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f);
+ if (mode == ImGuiInputReadMode_RepeatFast)
+ return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f);
+ return 0.0f;
+}
+
+ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor)
+{
+ ImVec2 delta(0.0f, 0.0f);
+ if (dir_sources & ImGuiNavDirSourceFlags_RawKeyboard)
+ delta += ImVec2((float)IsKeyDown(GetKeyIndex(ImGuiKey_RightArrow)) - (float)IsKeyDown(GetKeyIndex(ImGuiKey_LeftArrow)), (float)IsKeyDown(GetKeyIndex(ImGuiKey_DownArrow)) - (float)IsKeyDown(GetKeyIndex(ImGuiKey_UpArrow)));
+ if (dir_sources & ImGuiNavDirSourceFlags_Keyboard)
+ delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode));
+ if (dir_sources & ImGuiNavDirSourceFlags_PadDPad)
+ delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode));
+ if (dir_sources & ImGuiNavDirSourceFlags_PadLStick)
+ delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode));
+ if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow))
+ delta *= slow_factor;
+ if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast))
+ delta *= fast_factor;
+ return delta;
+}
+
+static void ImGui::NavUpdate()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+
+ io.WantSetMousePos = false;
+ //if (g.NavScoringDebugCount > 0) IMGUI_DEBUG_LOG("NavScoringDebugCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.NavScoringDebugCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest);
+
+ // Set input source as Gamepad when buttons are pressed (as some features differs when used with Gamepad vs Keyboard)
+ // (do it before we map Keyboard input!)
+ const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
+ const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
+ if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad)
+ {
+ if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNavInput_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs[ImGuiNavInput_Menu] > 0.0f
+ || io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGuiNavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.NavInputs[ImGuiNavInput_DpadDown] > 0.0f)
+ g.NavInputSource = ImGuiInputSource_Gamepad;
+ }
+
+ // Update Keyboard->Nav inputs mapping
+ if (nav_keyboard_active)
+ {
+ #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } while (0)
+ NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate );
+ NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input );
+ NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel );
+ NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ );
+ NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_);
+ NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ );
+ NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ );
+ if (io.KeyCtrl)
+ io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
+ if (io.KeyShift)
+ io.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
+ #undef NAV_MAP_KEY
+ }
+ memcpy(io.NavInputsDownDurationPrev, io.NavInputsDownDuration, sizeof(io.NavInputsDownDuration));
+ for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++)
+ io.NavInputsDownDuration[i] = (io.NavInputs[i] > 0.0f) ? (io.NavInputsDownDuration[i] < 0.0f ? 0.0f : io.NavInputsDownDuration[i] + io.DeltaTime) : -1.0f;
+
+ // Process navigation init request (select first/default focus)
+ if (g.NavInitResultId != 0)
+ NavInitRequestApplyResult();
+ g.NavInitRequest = false;
+ g.NavInitRequestFromMove = false;
+ g.NavInitResultId = 0;
+ g.NavJustMovedToId = 0;
+
+ // Process navigation move request
+ if (g.NavMoveSubmitted)
+ NavMoveRequestApplyResult();
+ g.NavTabbingCounter = 0;
+ g.NavMoveSubmitted = g.NavMoveScoringItems = false;
+
+ // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling)
+ bool set_mouse_pos = false;
+ if (g.NavMousePosDirty && g.NavIdIsAlive)
+ if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow)
+ set_mouse_pos = true;
+ g.NavMousePosDirty = false;
+ IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu);
+
+ // Store our return window (for returning from Menu Layer to Main Layer) and clear it as soon as we step back in our own Layer 0
+ if (g.NavWindow)
+ NavSaveLastChildNavWindowIntoParent(g.NavWindow);
+ if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == ImGuiNavLayer_Main)
+ g.NavWindow->NavLastChildNavWindow = NULL;
+
+ // Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.)
+ NavUpdateWindowing();
+
+ // Set output flags for user application
+ io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs);
+ io.NavVisible = (io.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL);
+
+ // Process NavCancel input (to close a popup, get back to parent, clear focus)
+ NavUpdateCancelRequest();
+
+ // Process manual activation request
+ g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavActivateInputId = 0;
+ g.NavActivateFlags = ImGuiActivateFlags_None;
+ if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+ {
+ bool activate_down = IsNavInputDown(ImGuiNavInput_Activate);
+ bool input_down = IsNavInputDown(ImGuiNavInput_Input);
+ bool activate_pressed = activate_down && IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed);
+ bool input_pressed = input_down && IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
+ if (g.ActiveId == 0 && activate_pressed)
+ {
+ g.NavActivateId = g.NavId;
+ g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
+ }
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed)
+ {
+ g.NavActivateInputId = g.NavId;
+ g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
+ }
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down)
+ g.NavActivateDownId = g.NavId;
+ if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed)
+ g.NavActivatePressedId = g.NavId;
+ }
+ if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
+ g.NavDisableHighlight = true;
+ if (g.NavActivateId != 0)
+ IM_ASSERT(g.NavActivateDownId == g.NavActivateId);
+
+ // Process programmatic activation request
+ // FIXME-NAV: Those should eventually be queued (unlike focus they don't cancel each others)
+ if (g.NavNextActivateId != 0)
+ {
+ if (g.NavNextActivateFlags & ImGuiActivateFlags_PreferInput)
+ g.NavActivateInputId = g.NavNextActivateId;
+ else
+ g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavNextActivateId;
+ g.NavActivateFlags = g.NavNextActivateFlags;
+ }
+ g.NavNextActivateId = 0;
+
+ // Process move requests
+ NavUpdateCreateMoveRequest();
+ if (g.NavMoveDir == ImGuiDir_None)
+ NavUpdateCreateTabbingRequest();
+ NavUpdateAnyRequestFlag();
+ g.NavIdIsAlive = false;
+
+ // Scrolling
+ if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget)
+ {
+ // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
+ ImGuiWindow* window = g.NavWindow;
+ const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
+ const ImGuiDir move_dir = g.NavMoveDir;
+ if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && move_dir != ImGuiDir_None)
+ {
+ if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
+ SetScrollX(window, ImFloor(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
+ if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
+ SetScrollY(window, ImFloor(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
+ }
+
+ // *Normal* Manual scroll with NavScrollXXX keys
+ // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
+ ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f);
+ if (scroll_dir.x != 0.0f && window->ScrollbarX)
+ SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
+ if (scroll_dir.y != 0.0f)
+ SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
+ }
+
+ // Always prioritize mouse highlight if navigation is disabled
+ if (!nav_keyboard_active && !nav_gamepad_active)
+ {
+ g.NavDisableHighlight = true;
+ g.NavDisableMouseHover = set_mouse_pos = false;
+ }
+
+ // Update mouse position if requested
+ // (This will take into account the possibility that a Scroll was queued in the window to offset our absolute mouse position before scroll has been applied)
+ if (set_mouse_pos && (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
+ {
+ io.MousePos = io.MousePosPrev = NavCalcPreferredRefPos();
+ io.WantSetMousePos = true;
+ //IMGUI_DEBUG_LOG("SetMousePos: (%.1f,%.1f)\n", io.MousePos.x, io.MousePos.y);
+ }
+
+ // [DEBUG]
+ g.NavScoringDebugCount = 0;
+#if IMGUI_DEBUG_NAV_RECTS
+ if (g.NavWindow)
+ {
+ ImDrawList* draw_list = GetForegroundDrawList(g.NavWindow);
+ if (1) { for (int layer = 0; layer < 2; layer++) { ImRect r = WindowRectRelToAbs(g.NavWindow, g.NavWindow->NavRectRel[layer]); draw_list->AddRect(r.Min, r.Max, IM_COL32(255,200,0,255)); } } // [DEBUG]
+ if (1) { ImU32 col = (!g.NavWindow->Hidden) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); draw_list->AddCircleFilled(p, 3.0f, col); draw_list->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
+ }
+#endif
+}
+
+void ImGui::NavInitRequestApplyResult()
+{
+ // In very rare cases g.NavWindow may be null (e.g. clearing focus after requesting an init request, which does happen when releasing Alt while clicking on void)
+ ImGuiContext& g = *GImGui;
+ if (!g.NavWindow)
+ return;
+
+ // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
+ // FIXME-NAV: On _NavFlattened windows, g.NavWindow will only be updated during subsequent frame. Not a problem currently.
+ IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name);
+ SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
+ g.NavIdIsAlive = true; // Mark as alive from previous frame as we got a result
+ if (g.NavInitRequestFromMove)
+ NavRestoreHighlightAfterMove();
+}
+
+void ImGui::NavUpdateCreateMoveRequest()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+ ImGuiWindow* window = g.NavWindow;
+
+ if (g.NavMoveForwardToNextFrame && window != NULL)
+ {
+ // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
+ // (preserve most state, which were already set by the NavMoveRequestForward() function)
+ IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None);
+ IM_ASSERT(g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded);
+ IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir);
+ }
+ else
+ {
+ // Initiate directional inputs request
+ g.NavMoveDir = ImGuiDir_None;
+ g.NavMoveFlags = ImGuiNavMoveFlags_None;
+ g.NavMoveScrollFlags = ImGuiScrollFlags_None;
+ if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
+ {
+ const ImGuiInputReadMode read_mode = ImGuiInputReadMode_Repeat;
+ if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && (IsNavInputTest(ImGuiNavInput_DpadLeft, read_mode) || IsNavInputTest(ImGuiNavInput_KeyLeft_, read_mode))) { g.NavMoveDir = ImGuiDir_Left; }
+ if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && (IsNavInputTest(ImGuiNavInput_DpadRight, read_mode) || IsNavInputTest(ImGuiNavInput_KeyRight_, read_mode))) { g.NavMoveDir = ImGuiDir_Right; }
+ if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && (IsNavInputTest(ImGuiNavInput_DpadUp, read_mode) || IsNavInputTest(ImGuiNavInput_KeyUp_, read_mode))) { g.NavMoveDir = ImGuiDir_Up; }
+ if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && (IsNavInputTest(ImGuiNavInput_DpadDown, read_mode) || IsNavInputTest(ImGuiNavInput_KeyDown_, read_mode))) { g.NavMoveDir = ImGuiDir_Down; }
+ }
+ g.NavMoveClipDir = g.NavMoveDir;
+ g.NavScoringNoClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
+ }
+
+ // Update PageUp/PageDown/Home/End scroll
+ // FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
+ const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
+ float scoring_rect_offset_y = 0.0f;
+ if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active)
+ scoring_rect_offset_y = NavUpdatePageUpPageDown();
+ if (scoring_rect_offset_y != 0.0f)
+ {
+ g.NavScoringNoClipRect = window->InnerRect;
+ g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y);
+ }
+
+ // [DEBUG] Always send a request
+#if IMGUI_DEBUG_NAV_SCORING
+ if (io.KeyCtrl && IsKeyPressedMap(ImGuiKey_C))
+ g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3);
+ if (io.KeyCtrl && g.NavMoveDir == ImGuiDir_None)
+ {
+ g.NavMoveDir = g.NavMoveDirForDebug;
+ g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult;
+ }
+#endif
+
+ // Submit
+ g.NavMoveForwardToNextFrame = false;
+ if (g.NavMoveDir != ImGuiDir_None)
+ NavMoveRequestSubmit(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags);
+
+ // Moving with no reference triggers a init request (will be used as a fallback if the direction fails to find a match)
+ if (g.NavMoveSubmitted && g.NavId == 0)
+ {
+ IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", g.NavWindow->Name, g.NavLayer);
+ g.NavInitRequest = g.NavInitRequestFromMove = true;
+ g.NavInitResultId = 0;
+ g.NavDisableHighlight = false;
+ }
+
+ // When using gamepad, we project the reference nav bounding box into window visible area.
+ // This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative
+ // (can't focus a visible object like we can with the mouse).
+ if (g.NavMoveSubmitted && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main && window != NULL)
+ {
+ ImRect window_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)));
+ if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
+ {
+ IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n");
+ float pad = window->CalcFontSize() * 0.5f;
+ window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
+ window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel);
+ g.NavId = g.NavFocusScopeId = 0;
+ }
+ }
+
+ // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items)
+ ImRect scoring_rect;
+ if (window != NULL)
+ {
+ ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? window->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0);
+ scoring_rect = WindowRectRelToAbs(window, nav_rect_rel);
+ scoring_rect.TranslateY(scoring_rect_offset_y);
+ scoring_rect.Min.x = ImMin(scoring_rect.Min.x + 1.0f, scoring_rect.Max.x);
+ scoring_rect.Max.x = scoring_rect.Min.x;
+ IM_ASSERT(!scoring_rect.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous ImFabs() calls in NavScoreItem().
+ //GetForegroundDrawList()->AddRect(scoring_rect.Min, scoring_rect.Max, IM_COL32(255,200,0,255)); // [DEBUG]
+ //if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG]
+ }
+ g.NavScoringRect = scoring_rect;
+ g.NavScoringNoClipRect.Add(scoring_rect);
+}
+
+void ImGui::NavUpdateCreateTabbingRequest()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.NavWindow;
+ IM_ASSERT(g.NavMoveDir == ImGuiDir_None);
+ if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs))
+ return;
+
+ const bool tab_pressed = IsKeyPressedMap(ImGuiKey_Tab, true) && !IsActiveIdUsingKey(ImGuiKey_Tab) && !g.IO.KeyCtrl && !g.IO.KeyAlt;
+ if (!tab_pressed)
+ return;
+
+ // Initiate tabbing request
+ // (this is ALWAYS ENABLED, regardless of ImGuiConfigFlags_NavEnableKeyboard flag!)
+ // Initially this was designed to use counters and modulo arithmetic, but that could not work with unsubmitted items (list clipper). Instead we use a strategy close to other move requests.
+ // See NavProcessItemForTabbingRequest() for a description of the various forward/backward tabbing cases with and without wrapping.
+ //// FIXME: We use (g.ActiveId == 0) but (g.NavDisableHighlight == false) might be righter once we can tab through anything
+ g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
+ ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
+ ImGuiDir clip_dir = (g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
+ NavMoveRequestSubmit(ImGuiDir_None, clip_dir, ImGuiNavMoveFlags_Tabbing, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
+ g.NavTabbingResultFirst.Clear();
+ g.NavTabbingCounter = -1;
+}
+
+// Apply result from previous frame navigation directional move request. Always called from NavUpdate()
+void ImGui::NavMoveRequestApplyResult()
+{
+ ImGuiContext& g = *GImGui;
+#if IMGUI_DEBUG_NAV_SCORING
+ if (g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult) // [DEBUG] Scoring all items in NavWindow at all times
+ return;
+#endif
+
+ // Select which result to use
+ ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : (g.NavMoveResultOther.ID != 0) ? &g.NavMoveResultOther : NULL;
+
+ // Tabbing forward wrap
+ if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
+ if ((g.NavTabbingCounter == 1 || g.NavTabbingDir == 0) && g.NavTabbingResultFirst.ID)
+ result = &g.NavTabbingResultFirst;
+
+ // In a situation when there is no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result)
+ if (result == NULL)
+ {
+ if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
+ g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
+ if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
+ NavRestoreHighlightAfterMove();
+ return;
+ }
+
+ // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
+ if (g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
+ if (g.NavMoveResultLocalVisible.ID != 0 && g.NavMoveResultLocalVisible.ID != g.NavId)
+ result = &g.NavMoveResultLocalVisible;
+
+ // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
+ if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
+ if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
+ result = &g.NavMoveResultOther;
+ IM_ASSERT(g.NavWindow && result->Window);
+
+ // Scroll to keep newly navigated item fully into view.
+ if (g.NavLayer == ImGuiNavLayer_Main)
+ {
+ if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY)
+ {
+ // FIXME: Should remove this
+ float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
+ SetScrollY(result->Window, scroll_target);
+ }
+ else
+ {
+ ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel);
+ ScrollToRectEx(result->Window, rect_abs, g.NavMoveScrollFlags);
+ }
+ }
+
+ g.NavWindow = result->Window;
+ if (g.ActiveId != result->ID)
+ ClearActiveID();
+ if (g.NavId != result->ID)
+ {
+ // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId)
+ g.NavJustMovedToId = result->ID;
+ g.NavJustMovedToFocusScopeId = result->FocusScopeId;
+ g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
+ }
+
+ // Focus
+ IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name);
+ SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel);
+
+ // Tabbing: Activates Inputable or Focus non-Inputable
+ if ((g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && (result->InFlags & ImGuiItemFlags_Inputable))
+ {
+ g.NavNextActivateId = result->ID;
+ g.NavNextActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState;
+ g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
+ }
+
+ // Activate
+ if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
+ {
+ g.NavNextActivateId = result->ID;
+ g.NavNextActivateFlags = ImGuiActivateFlags_None;
+ }
+
+ // Enable nav highlight
+ if ((g.NavMoveFlags & ImGuiNavMoveFlags_DontSetNavHighlight) == 0)
+ NavRestoreHighlightAfterMove();
+}
+
+// Process NavCancel input (to close a popup, get back to parent, clear focus)
+// FIXME: In order to support e.g. Escape to clear a selection we'll need:
+// - either to store the equivalent of ActiveIdUsingKeyInputMask for a FocusScope and test for it.
+// - either to move most/all of those tests to the epilogue/end functions of the scope they are dealing with (e.g. exit child window in EndChild()) or in EndFrame(), to allow an earlier intercept
+static void ImGui::NavUpdateCancelRequest()
+{
+ ImGuiContext& g = *GImGui;
+ if (!IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed))
+ return;
+
+ IMGUI_DEBUG_LOG_NAV("[nav] ImGuiNavInput_Cancel\n");
+ if (g.ActiveId != 0)
+ {
+ if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel))
+ ClearActiveID();
+ }
+ else if (g.NavLayer != ImGuiNavLayer_Main)
+ {
+ // Leave the "menu" layer
+ NavRestoreLayer(ImGuiNavLayer_Main);
+ NavRestoreHighlightAfterMove();
+ }
+ else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
+ {
+ // Exit child window
+ ImGuiWindow* child_window = g.NavWindow;
+ ImGuiWindow* parent_window = g.NavWindow->ParentWindow;
+ IM_ASSERT(child_window->ChildId != 0);
+ ImRect child_rect = child_window->Rect();
+ FocusWindow(parent_window);
+ SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_rect));
+ NavRestoreHighlightAfterMove();
+ }
+ else if (g.OpenPopupStack.Size > 0)
+ {
+ // Close open popup/menu
+ if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
+ ClosePopupToLevel(g.OpenPopupStack.Size - 1, true);
+ }
+ else
+ {
+ // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
+ if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
+ g.NavWindow->NavLastIds[0] = 0;
+ g.NavId = g.NavFocusScopeId = 0;
+ }
+}
+
+// Handle PageUp/PageDown/Home/End keys
+// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
+// FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference
+// FIXME-NAV: how to get Home/End to aim at the beginning/end of a 2D grid?
+static float ImGui::NavUpdatePageUpPageDown()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+
+ ImGuiWindow* window = g.NavWindow;
+ if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL)
+ return 0.0f;
+
+ const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActiveIdUsingKey(ImGuiKey_PageUp);
+ const bool page_down_held = IsKeyDown(io.KeyMap[ImGuiKey_PageDown]) && !IsActiveIdUsingKey(ImGuiKey_PageDown);
+ const bool home_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_Home]) && !IsActiveIdUsingKey(ImGuiKey_Home);
+ const bool end_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End);
+ if (page_up_held == page_down_held && home_pressed == end_pressed) // Proceed if either (not both) are pressed, otherwise early out
+ return 0.0f;
+
+ if (g.NavLayer != ImGuiNavLayer_Main)
+ NavRestoreLayer(ImGuiNavLayer_Main);
+
+ if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll)
+ {
+ // Fallback manual-scroll when window has no navigable item
+ if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
+ SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
+ else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
+ SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
+ else if (home_pressed)
+ SetScrollY(window, 0.0f);
+ else if (end_pressed)
+ SetScrollY(window, window->ScrollMax.y);
+ }
+ else
+ {
+ ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
+ const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
+ float nav_scoring_rect_offset_y = 0.0f;
+ if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
+ {
+ nav_scoring_rect_offset_y = -page_offset_y;
+ g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
+ g.NavMoveClipDir = ImGuiDir_Up;
+ g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
+ }
+ else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true))
+ {
+ nav_scoring_rect_offset_y = +page_offset_y;
+ g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
+ g.NavMoveClipDir = ImGuiDir_Down;
+ g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
+ }
+ else if (home_pressed)
+ {
+ // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y
+ // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdgeY flag, we don't scroll immediately to avoid scrolling happening before nav result.
+ // Preserve current horizontal position if we have any.
+ nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f;
+ if (nav_rect_rel.IsInverted())
+ nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
+ g.NavMoveDir = ImGuiDir_Down;
+ g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
+ // FIXME-NAV: MoveClipDir left to _None, intentional?
+ }
+ else if (end_pressed)
+ {
+ nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y;
+ if (nav_rect_rel.IsInverted())
+ nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
+ g.NavMoveDir = ImGuiDir_Up;
+ g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY;
+ // FIXME-NAV: MoveClipDir left to _None, intentional?
+ }
+ return nav_scoring_rect_offset_y;
+ }
+ return 0.0f;
+}
+
+static void ImGui::NavEndFrame()
+{
+ ImGuiContext& g = *GImGui;
+
+ // Show CTRL+TAB list window
+ if (g.NavWindowingTarget != NULL)
+ NavUpdateWindowingOverlay();
+
+ // Perform wrap-around in menus
+ // FIXME-NAV: Wrap may need to apply a weight bias on the other axis. e.g. 4x4 grid with 2 last items missing on last item won't handle LoopY/WrapY correctly.
+ // FIXME-NAV: Wrap (not Loop) support could be handled by the scoring function and then WrapX would function without an extra frame.
+ const ImGuiNavMoveFlags wanted_flags = ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY;
+ if (g.NavWindow && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & wanted_flags) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
+ NavUpdateCreateWrappingRequest();
+}
+
+static void ImGui::NavUpdateCreateWrappingRequest()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.NavWindow;
+
+ bool do_forward = false;
+ ImRect bb_rel = window->NavRectRel[g.NavLayer];
+ ImGuiDir clip_dir = g.NavMoveDir;
+ const ImGuiNavMoveFlags move_flags = g.NavMoveFlags;
+ if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
+ {
+ bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x;
+ if (move_flags & ImGuiNavMoveFlags_WrapX)
+ {
+ bb_rel.TranslateY(-bb_rel.GetHeight()); // Previous row
+ clip_dir = ImGuiDir_Up;
+ }
+ do_forward = true;
+ }
+ if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
+ {
+ bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x;
+ if (move_flags & ImGuiNavMoveFlags_WrapX)
+ {
+ bb_rel.TranslateY(+bb_rel.GetHeight()); // Next row
+ clip_dir = ImGuiDir_Down;
+ }
+ do_forward = true;
+ }
+ if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
+ {
+ bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y;
+ if (move_flags & ImGuiNavMoveFlags_WrapY)
+ {
+ bb_rel.TranslateX(-bb_rel.GetWidth()); // Previous column
+ clip_dir = ImGuiDir_Left;
+ }
+ do_forward = true;
+ }
+ if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
+ {
+ bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y;
+ if (move_flags & ImGuiNavMoveFlags_WrapY)
+ {
+ bb_rel.TranslateX(+bb_rel.GetWidth()); // Next column
+ clip_dir = ImGuiDir_Right;
+ }
+ do_forward = true;
+ }
+ if (!do_forward)
+ return;
+ window->NavRectRel[g.NavLayer] = bb_rel;
+ NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
+}
+
+static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ IM_UNUSED(g);
+ int order = window->FocusOrder;
+ IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking)
+ IM_ASSERT(g.WindowsFocusOrder[order] == window);
+ return order;
+}
+
+static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
+{
+ ImGuiContext& g = *GImGui;
+ for (int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir)
+ if (ImGui::IsWindowNavFocusable(g.WindowsFocusOrder[i]))
+ return g.WindowsFocusOrder[i];
+ return NULL;
+}
+
+static void NavUpdateWindowingHighlightWindow(int focus_change_dir)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindowingTarget);
+ if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)
+ return;
+
+ const int i_current = ImGui::FindWindowFocusIndex(g.NavWindowingTarget);
+ ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir);
+ if (!window_target)
+ window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir);
+ if (window_target) // Don't reset windowing target if there's a single window in the list
+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target;
+ g.NavWindowingToggleLayer = false;
+}
+
+// Windowing management mode
+// Keyboard: CTRL+Tab (change focus/move/resize), Alt (toggle menu layer)
+// Gamepad: Hold Menu/Square (change focus/move/resize), Tap Menu/Square (toggle menu layer)
+static void ImGui::NavUpdateWindowing()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+
+ ImGuiWindow* apply_focus_window = NULL;
+ bool apply_toggle_layer = false;
+
+ ImGuiWindow* modal_window = GetTopMostPopupModal();
+ bool allow_windowing = (modal_window == NULL);
+ if (!allow_windowing)
+ g.NavWindowingTarget = NULL;
+
+ // Fade out
+ if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL)
+ {
+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f);
+ if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f)
+ g.NavWindowingTargetAnim = NULL;
+ }
+
+ // Start CTRL+Tab or Square+L/R window selection
+ const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowingTarget && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed);
+ const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && io.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab);
+ if (start_windowing_with_gamepad || start_windowing_with_keyboard)
+ if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
+ {
+ g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow;
+ g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f;
+ g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer
+ g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
+ }
+
+ // Gamepad update
+ g.NavWindowingTimer += io.DeltaTime;
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad)
+ {
+ // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise
+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f));
+
+ // Select window to focus
+ const int focus_change_dir = (int)IsNavInputTest(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputTest(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow);
+ if (focus_change_dir != 0)
+ {
+ NavUpdateWindowingHighlightWindow(focus_change_dir);
+ g.NavWindowingHighlightAlpha = 1.0f;
+ }
+
+ // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered top-most)
+ if (!IsNavInputDown(ImGuiNavInput_Menu))
+ {
+ g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore.
+ if (g.NavWindowingToggleLayer && g.NavWindow)
+ apply_toggle_layer = true;
+ else if (!g.NavWindowingToggleLayer)
+ apply_focus_window = g.NavWindowingTarget;
+ g.NavWindowingTarget = NULL;
+ }
+ }
+
+ // Keyboard: Focus
+ if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard)
+ {
+ // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise
+ g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f
+ if (IsKeyPressedMap(ImGuiKey_Tab, true))
+ NavUpdateWindowingHighlightWindow(io.KeyShift ? +1 : -1);
+ if (!io.KeyCtrl)
+ apply_focus_window = g.NavWindowingTarget;
+ }
+
+ // Keyboard: Press and Release ALT to toggle menu layer
+ // - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggling menu layer.
+ // - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway.
+ const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
+ if (nav_keyboard_active && io.KeyMods == ImGuiKeyModFlags_Alt && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) == 0)
+ {
+ g.NavWindowingToggleLayer = true;
+ g.NavInputSource = ImGuiInputSource_Keyboard;
+ }
+ if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard)
+ {
+ // We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370)
+ // We cancel toggling nav layer when other modifiers are pressed. (See #4439)
+ if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper)
+ g.NavWindowingToggleLayer = false;
+
+ // Apply layer toggle on release
+ // Important: we don't assume that Alt was previously held in order to handle loss of focus when backend calls io.AddFocusEvent(false)
+ // Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss.
+ if (!(io.KeyMods & ImGuiKeyModFlags_Alt) && (io.KeyModsPrev & ImGuiKeyModFlags_Alt) && g.NavWindowingToggleLayer)
+ if (g.ActiveId == 0 || g.ActiveIdAllowOverlap)
+ if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev))
+ apply_toggle_layer = true;
+ if (!io.KeyAlt)
+ g.NavWindowingToggleLayer = false;
+ }
+
+ // Move window
+ if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove))
+ {
+ ImVec2 move_delta;
+ if (g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift)
+ move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_RawKeyboard, ImGuiInputReadMode_Down);
+ if (g.NavInputSource == ImGuiInputSource_Gamepad)
+ move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down);
+ if (move_delta.x != 0.0f || move_delta.y != 0.0f)
+ {
+ const float NAV_MOVE_SPEED = 800.0f;
+ const float move_speed = ImFloor(NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well
+ ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow;
+ SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always);
+ MarkIniSettingsDirty(moving_window);
+ g.NavDisableMouseHover = true;
+ }
+ }
+
+ // Apply final focus
+ if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow))
+ {
+ ClearActiveID();
+ NavRestoreHighlightAfterMove();
+ apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window);
+ ClosePopupsOverWindow(apply_focus_window, false);
+ FocusWindow(apply_focus_window);
+ if (apply_focus_window->NavLastIds[0] == 0)
+ NavInitWindow(apply_focus_window, false);
+
+ // If the window has ONLY a menu layer (no main layer), select it directly
+ // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame,
+ // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since
+ // the target window as already been previewed once.
+ // FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases,
+ // we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask*
+ // won't be valid.
+ if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu))
+ g.NavLayer = ImGuiNavLayer_Menu;
+ }
+ if (apply_focus_window)
+ g.NavWindowingTarget = NULL;
+
+ // Apply menu/layer toggle
+ if (apply_toggle_layer && g.NavWindow)
+ {
+ ClearActiveID();
+
+ // Move to parent menu if necessary
+ ImGuiWindow* new_nav_window = g.NavWindow;
+ while (new_nav_window->ParentWindow
+ && (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0
+ && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
+ && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
+ new_nav_window = new_nav_window->ParentWindow;
+ if (new_nav_window != g.NavWindow)
+ {
+ ImGuiWindow* old_nav_window = g.NavWindow;
+ FocusWindow(new_nav_window);
+ new_nav_window->NavLastChildNavWindow = old_nav_window;
+ }
+
+ // Toggle layer
+ const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main;
+ if (new_nav_layer != g.NavLayer)
+ {
+ // Reinitialize navigation when entering menu bar with the Alt key (FIXME: could be a properly of the layer?)
+ if (new_nav_layer == ImGuiNavLayer_Menu)
+ g.NavWindow->NavLastIds[new_nav_layer] = 0;
+ NavRestoreLayer(new_nav_layer);
+ NavRestoreHighlightAfterMove();
+ }
+ }
+}
+
+// Window has already passed the IsWindowNavFocusable()
+static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
+{
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ return "(Popup)";
+ if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0)
+ return "(Main menu bar)";
+ return "(Untitled)";
+}
+
+// Overlay displayed when using CTRL+TAB. Called by EndFrame().
+void ImGui::NavUpdateWindowingOverlay()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.NavWindowingTarget != NULL);
+
+ if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY)
+ return;
+
+ if (g.NavWindowingListWindow == NULL)
+ g.NavWindowingListWindow = FindWindowByName("###NavWindowingList");
+ const ImGuiViewport* viewport = GetMainViewport();
+ SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
+ SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
+ PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f);
+ Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
+ for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
+ {
+ ImGuiWindow* window = g.WindowsFocusOrder[n];
+ IM_ASSERT(window != NULL); // Fix static analyzers
+ if (!IsWindowNavFocusable(window))
+ continue;
+ const char* label = window->Name;
+ if (label == FindRenderedTextEnd(label))
+ label = GetFallbackWindowNameForWindowingList(window);
+ Selectable(label, g.NavWindowingTarget == window);
+ }
+ End();
+ PopStyleVar();
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] DRAG AND DROP
+//-----------------------------------------------------------------------------
+
+void ImGui::ClearDragDrop()
+{
+ ImGuiContext& g = *GImGui;
+ g.DragDropActive = false;
+ g.DragDropPayload.Clear();
+ g.DragDropAcceptFlags = ImGuiDragDropFlags_None;
+ g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0;
+ g.DragDropAcceptIdCurrRectSurface = FLT_MAX;
+ g.DragDropAcceptFrameCount = -1;
+
+ g.DragDropPayloadBufHeap.clear();
+ memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
+}
+
+// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource()
+// If the item has an identifier:
+// - This assume/require the item to be activated (typically via ButtonBehavior).
+// - Therefore if you want to use this with a mouse button other than left mouse button, it is up to the item itself to activate with another button.
+// - We then pull and use the mouse button that was used to activate the item and use it to carry on the drag.
+// If the item has no identifier:
+// - Currently always assume left mouse button.
+bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // FIXME-DRAGDROP: While in the common-most "drag from non-zero active id" case we can tell the mouse button,
+ // in both SourceExtern and id==0 cases we may requires something else (explicit flags or some heuristic).
+ ImGuiMouseButton mouse_button = ImGuiMouseButton_Left;
+
+ bool source_drag_active = false;
+ ImGuiID source_id = 0;
+ ImGuiID source_parent_id = 0;
+ if (!(flags & ImGuiDragDropFlags_SourceExtern))
+ {
+ source_id = g.LastItemData.ID;
+ if (source_id != 0)
+ {
+ // Common path: items with ID
+ if (g.ActiveId != source_id)
+ return false;
+ if (g.ActiveIdMouseButton != -1)
+ mouse_button = g.ActiveIdMouseButton;
+ if (g.IO.MouseDown[mouse_button] == false || window->SkipItems)
+ return false;
+ g.ActiveIdAllowOverlap = false;
+ }
+ else
+ {
+ // Uncommon path: items without ID
+ if (g.IO.MouseDown[mouse_button] == false || window->SkipItems)
+ return false;
+ if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window))
+ return false;
+
+ // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
+ // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag.
+ if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
+ {
+ IM_ASSERT(0);
+ return false;
+ }
+
+ // Magic fallback to handle items with no assigned ID, e.g. Text(), Image()
+ // We build a throwaway ID based on current ID stack + relative AABB of items in window.
+ // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZINGG OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
+ // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
+ // Rely on keeping other window->LastItemXXX fields intact.
+ source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
+ bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id);
+ if (is_hovered && g.IO.MouseClicked[mouse_button])
+ {
+ SetActiveID(source_id, window);
+ FocusWindow(window);
+ }
+ if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
+ g.ActiveIdAllowOverlap = is_hovered;
+ }
+ if (g.ActiveId != source_id)
+ return false;
+ source_parent_id = window->IDStack.back();
+ source_drag_active = IsMouseDragging(mouse_button);
+
+ // Disable navigation and key inputs while dragging + cancel existing request if any
+ SetActiveIdUsingNavAndKeys();
+ }
+ else
+ {
+ window = NULL;
+ source_id = ImHashStr("#SourceExtern");
+ source_drag_active = true;
+ }
+
+ if (source_drag_active)
+ {
+ if (!g.DragDropActive)
+ {
+ IM_ASSERT(source_id != 0);
+ ClearDragDrop();
+ ImGuiPayload& payload = g.DragDropPayload;
+ payload.SourceId = source_id;
+ payload.SourceParentId = source_parent_id;
+ g.DragDropActive = true;
+ g.DragDropSourceFlags = flags;
+ g.DragDropMouseButton = mouse_button;
+ if (payload.SourceId == g.ActiveId)
+ g.ActiveIdNoClearOnFocusLoss = true;
+ }
+ g.DragDropSourceFrameCount = g.FrameCount;
+ g.DragDropWithinSource = true;
+
+ if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+ {
+ // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit)
+ // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents.
+ BeginTooltip();
+ if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip))
+ {
+ ImGuiWindow* tooltip_window = g.CurrentWindow;
+ tooltip_window->Hidden = tooltip_window->SkipItems = true;
+ tooltip_window->HiddenFramesCanSkipItems = 1;
+ }
+ }
+
+ if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
+ g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
+
+ return true;
+ }
+ return false;
+}
+
+void ImGui::EndDragDropSource()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.DragDropActive);
+ IM_ASSERT(g.DragDropWithinSource && "Not after a BeginDragDropSource()?");
+
+ if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip))
+ EndTooltip();
+
+ // Discard the drag if have not called SetDragDropPayload()
+ if (g.DragDropPayload.DataFrameCount == -1)
+ ClearDragDrop();
+ g.DragDropWithinSource = false;
+}
+
+// Use 'cond' to choose to submit payload on drag start or every frame
+bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiPayload& payload = g.DragDropPayload;
+ if (cond == 0)
+ cond = ImGuiCond_Always;
+
+ IM_ASSERT(type != NULL);
+ IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
+ IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
+ IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
+ IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
+
+ if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
+ {
+ // Copy payload
+ ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
+ g.DragDropPayloadBufHeap.resize(0);
+ if (data_size > sizeof(g.DragDropPayloadBufLocal))
+ {
+ // Store in heap
+ g.DragDropPayloadBufHeap.resize((int)data_size);
+ payload.Data = g.DragDropPayloadBufHeap.Data;
+ memcpy(payload.Data, data, data_size);
+ }
+ else if (data_size > 0)
+ {
+ // Store locally
+ memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
+ payload.Data = g.DragDropPayloadBufLocal;
+ memcpy(payload.Data, data, data_size);
+ }
+ else
+ {
+ payload.Data = NULL;
+ }
+ payload.DataSize = (int)data_size;
+ }
+ payload.DataFrameCount = g.FrameCount;
+
+ return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1);
+}
+
+bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.DragDropActive)
+ return false;
+
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
+ if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
+ return false;
+ IM_ASSERT(id != 0);
+ if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
+ return false;
+ if (window->SkipItems)
+ return false;
+
+ IM_ASSERT(g.DragDropWithinTarget == false);
+ g.DragDropTargetRect = bb;
+ g.DragDropTargetId = id;
+ g.DragDropWithinTarget = true;
+ return true;
+}
+
+// We don't use BeginDragDropTargetCustom() and duplicate its code because:
+// 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them.
+// 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can.
+// Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case)
+bool ImGui::BeginDragDropTarget()
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.DragDropActive)
+ return false;
+
+ ImGuiWindow* window = g.CurrentWindow;
+ if (!(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect))
+ return false;
+ ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
+ if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow || window->SkipItems)
+ return false;
+
+ const ImRect& display_rect = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? g.LastItemData.DisplayRect : g.LastItemData.Rect;
+ ImGuiID id = g.LastItemData.ID;
+ if (id == 0)
+ id = window->GetIDFromRectangle(display_rect);
+ if (g.DragDropPayload.SourceId == id)
+ return false;
+
+ IM_ASSERT(g.DragDropWithinTarget == false);
+ g.DragDropTargetRect = display_rect;
+ g.DragDropTargetId = id;
+ g.DragDropWithinTarget = true;
+ return true;
+}
+
+bool ImGui::IsDragDropPayloadBeingAccepted()
+{
+ ImGuiContext& g = *GImGui;
+ return g.DragDropActive && g.DragDropAcceptIdPrev != 0;
+}
+
+const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiPayload& payload = g.DragDropPayload;
+ IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ?
+ IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ?
+ if (type != NULL && !payload.IsDataType(type))
+ return NULL;
+
+ // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints.
+ // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function!
+ const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId);
+ ImRect r = g.DragDropTargetRect;
+ float r_surface = r.GetWidth() * r.GetHeight();
+ if (r_surface <= g.DragDropAcceptIdCurrRectSurface)
+ {
+ g.DragDropAcceptFlags = flags;
+ g.DragDropAcceptIdCurr = g.DragDropTargetId;
+ g.DragDropAcceptIdCurrRectSurface = r_surface;
+ }
+
+ // Render default drop visuals
+ // FIXME-DRAGDROP: Settle on a proper default visuals for drop target.
+ payload.Preview = was_accepted_previously;
+ flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame)
+ if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview)
+ window->DrawList->AddRect(r.Min - ImVec2(3.5f,3.5f), r.Max + ImVec2(3.5f, 3.5f), GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f);
+
+ g.DragDropAcceptFrameCount = g.FrameCount;
+ payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()
+ if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
+ return NULL;
+
+ return &payload;
+}
+
+const ImGuiPayload* ImGui::GetDragDropPayload()
+{
+ ImGuiContext& g = *GImGui;
+ return g.DragDropActive ? &g.DragDropPayload : NULL;
+}
+
+// We don't really use/need this now, but added it for the sake of consistency and because we might need it later.
+void ImGui::EndDragDropTarget()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.DragDropActive);
+ IM_ASSERT(g.DragDropWithinTarget);
+ g.DragDropWithinTarget = false;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] LOGGING/CAPTURING
+//-----------------------------------------------------------------------------
+// All text output from the interface can be captured into tty/file/clipboard.
+// By default, tree nodes are automatically opened during logging.
+//-----------------------------------------------------------------------------
+
+// Pass text data straight to log (without being displayed)
+static inline void LogTextV(ImGuiContext& g, const char* fmt, va_list args)
+{
+ if (g.LogFile)
+ {
+ g.LogBuffer.Buf.resize(0);
+ g.LogBuffer.appendfv(fmt, args);
+ ImFileWrite(g.LogBuffer.c_str(), sizeof(char), (ImU64)g.LogBuffer.size(), g.LogFile);
+ }
+ else
+ {
+ g.LogBuffer.appendfv(fmt, args);
+ }
+}
+
+void ImGui::LogText(const char* fmt, ...)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ va_list args;
+ va_start(args, fmt);
+ LogTextV(g, fmt, args);
+ va_end(args);
+}
+
+void ImGui::LogTextV(const char* fmt, va_list args)
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ LogTextV(g, fmt, args);
+}
+
+// Internal version that takes a position to decide on newline placement and pad items according to their depth.
+// We split text into individual lines to add current tree level padding
+// FIXME: This code is a little complicated perhaps, considering simplifying the whole system.
+void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const char* prefix = g.LogNextPrefix;
+ const char* suffix = g.LogNextSuffix;
+ g.LogNextPrefix = g.LogNextSuffix = NULL;
+
+ if (!text_end)
+ text_end = FindRenderedTextEnd(text, text_end);
+
+ const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + g.Style.FramePadding.y + 1);
+ if (ref_pos)
+ g.LogLinePosY = ref_pos->y;
+ if (log_new_line)
+ {
+ LogText(IM_NEWLINE);
+ g.LogLineFirstItem = true;
+ }
+
+ if (prefix)
+ LogRenderedText(ref_pos, prefix, prefix + strlen(prefix)); // Calculate end ourself to ensure "##" are included here.
+
+ // Re-adjust padding if we have popped out of our starting depth
+ if (g.LogDepthRef > window->DC.TreeDepth)
+ g.LogDepthRef = window->DC.TreeDepth;
+ const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef);
+
+ const char* text_remaining = text;
+ for (;;)
+ {
+ // Split the string. Each new line (after a '\n') is followed by indentation corresponding to the current depth of our log entry.
+ // We don't add a trailing \n yet to allow a subsequent item on the same line to be captured.
+ const char* line_start = text_remaining;
+ const char* line_end = ImStreolRange(line_start, text_end);
+ const bool is_last_line = (line_end == text_end);
+ if (line_start != line_end || !is_last_line)
+ {
+ const int line_length = (int)(line_end - line_start);
+ const int indentation = g.LogLineFirstItem ? tree_depth * 4 : 1;
+ LogText("%*s%.*s", indentation, "", line_length, line_start);
+ g.LogLineFirstItem = false;
+ if (*line_end == '\n')
+ {
+ LogText(IM_NEWLINE);
+ g.LogLineFirstItem = true;
+ }
+ }
+ if (is_last_line)
+ break;
+ text_remaining = line_end + 1;
+ }
+
+ if (suffix)
+ LogRenderedText(ref_pos, suffix, suffix + strlen(suffix));
+}
+
+// Start logging/capturing text output
+void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(g.LogEnabled == false);
+ IM_ASSERT(g.LogFile == NULL);
+ IM_ASSERT(g.LogBuffer.empty());
+ g.LogEnabled = true;
+ g.LogType = type;
+ g.LogNextPrefix = g.LogNextSuffix = NULL;
+ g.LogDepthRef = window->DC.TreeDepth;
+ g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
+ g.LogLinePosY = FLT_MAX;
+ g.LogLineFirstItem = true;
+}
+
+// Important: doesn't copy underlying data, use carefully (prefix/suffix must be in scope at the time of the next LogRenderedText)
+void ImGui::LogSetNextTextDecoration(const char* prefix, const char* suffix)
+{
+ ImGuiContext& g = *GImGui;
+ g.LogNextPrefix = prefix;
+ g.LogNextSuffix = suffix;
+}
+
+void ImGui::LogToTTY(int auto_open_depth)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+ IM_UNUSED(auto_open_depth);
+#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
+ LogBegin(ImGuiLogType_TTY, auto_open_depth);
+ g.LogFile = stdout;
+#endif
+}
+
+// Start logging/capturing text output to given file
+void ImGui::LogToFile(int auto_open_depth, const char* filename)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+
+ // FIXME: We could probably open the file in text mode "at", however note that clipboard/buffer logging will still
+ // be subject to outputting OS-incompatible carriage return if within strings the user doesn't use IM_NEWLINE.
+ // By opening the file in binary mode "ab" we have consistent output everywhere.
+ if (!filename)
+ filename = g.IO.LogFilename;
+ if (!filename || !filename[0])
+ return;
+ ImFileHandle f = ImFileOpen(filename, "ab");
+ if (!f)
+ {
+ IM_ASSERT(0);
+ return;
+ }
+
+ LogBegin(ImGuiLogType_File, auto_open_depth);
+ g.LogFile = f;
+}
+
+// Start logging/capturing text output to clipboard
+void ImGui::LogToClipboard(int auto_open_depth)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+ LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
+}
+
+void ImGui::LogToBuffer(int auto_open_depth)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled)
+ return;
+ LogBegin(ImGuiLogType_Buffer, auto_open_depth);
+}
+
+void ImGui::LogFinish()
+{
+ ImGuiContext& g = *GImGui;
+ if (!g.LogEnabled)
+ return;
+
+ LogText(IM_NEWLINE);
+ switch (g.LogType)
+ {
+ case ImGuiLogType_TTY:
+#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
+ fflush(g.LogFile);
+#endif
+ break;
+ case ImGuiLogType_File:
+ ImFileClose(g.LogFile);
+ break;
+ case ImGuiLogType_Buffer:
+ break;
+ case ImGuiLogType_Clipboard:
+ if (!g.LogBuffer.empty())
+ SetClipboardText(g.LogBuffer.begin());
+ break;
+ case ImGuiLogType_None:
+ IM_ASSERT(0);
+ break;
+ }
+
+ g.LogEnabled = false;
+ g.LogType = ImGuiLogType_None;
+ g.LogFile = NULL;
+ g.LogBuffer.clear();
+}
+
+// Helper to display logging buttons
+// FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!)
+void ImGui::LogButtons()
+{
+ ImGuiContext& g = *GImGui;
+
+ PushID("LogButtons");
+#ifndef IMGUI_DISABLE_TTY_FUNCTIONS
+ const bool log_to_tty = Button("Log To TTY"); SameLine();
+#else
+ const bool log_to_tty = false;
+#endif
+ const bool log_to_file = Button("Log To File"); SameLine();
+ const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
+ PushAllowKeyboardFocus(false);
+ SetNextItemWidth(80.0f);
+ SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL);
+ PopAllowKeyboardFocus();
+ PopID();
+
+ // Start logging at the end of the function so that the buttons don't appear in the log
+ if (log_to_tty)
+ LogToTTY();
+ if (log_to_file)
+ LogToFile();
+ if (log_to_clipboard)
+ LogToClipboard();
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] SETTINGS
+//-----------------------------------------------------------------------------
+// - UpdateSettings() [Internal]
+// - MarkIniSettingsDirty() [Internal]
+// - CreateNewWindowSettings() [Internal]
+// - FindWindowSettings() [Internal]
+// - FindOrCreateWindowSettings() [Internal]
+// - FindSettingsHandler() [Internal]
+// - ClearIniSettings() [Internal]
+// - LoadIniSettingsFromDisk()
+// - LoadIniSettingsFromMemory()
+// - SaveIniSettingsToDisk()
+// - SaveIniSettingsToMemory()
+// - WindowSettingsHandler_***() [Internal]
+//-----------------------------------------------------------------------------
+
+// Called by NewFrame()
+void ImGui::UpdateSettings()
+{
+ // Load settings on first frame (if not explicitly loaded manually before)
+ ImGuiContext& g = *GImGui;
+ if (!g.SettingsLoaded)
+ {
+ IM_ASSERT(g.SettingsWindows.empty());
+ if (g.IO.IniFilename)
+ LoadIniSettingsFromDisk(g.IO.IniFilename);
+ g.SettingsLoaded = true;
+ }
+
+ // Save settings (with a delay after the last modification, so we don't spam disk too much)
+ if (g.SettingsDirtyTimer > 0.0f)
+ {
+ g.SettingsDirtyTimer -= g.IO.DeltaTime;
+ if (g.SettingsDirtyTimer <= 0.0f)
+ {
+ if (g.IO.IniFilename != NULL)
+ SaveIniSettingsToDisk(g.IO.IniFilename);
+ else
+ g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves.
+ g.SettingsDirtyTimer = 0.0f;
+ }
+ }
+}
+
+void ImGui::MarkIniSettingsDirty()
+{
+ ImGuiContext& g = *GImGui;
+ if (g.SettingsDirtyTimer <= 0.0f)
+ g.SettingsDirtyTimer = g.IO.IniSavingRate;
+}
+
+void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
+{
+ ImGuiContext& g = *GImGui;
+ if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
+ if (g.SettingsDirtyTimer <= 0.0f)
+ g.SettingsDirtyTimer = g.IO.IniSavingRate;
+}
+
+ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
+{
+ ImGuiContext& g = *GImGui;
+
+#if !IMGUI_DEBUG_INI_SETTINGS
+ // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
+ // Preserve the full string when IMGUI_DEBUG_INI_SETTINGS is set to make .ini inspection easier.
+ if (const char* p = strstr(name, "###"))
+ name = p;
+#endif
+ const size_t name_len = strlen(name);
+
+ // Allocate chunk
+ const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1;
+ ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size);
+ IM_PLACEMENT_NEW(settings) ImGuiWindowSettings();
+ settings->ID = ImHashStr(name, name_len);
+ memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator
+
+ return settings;
+}
+
+ImGuiWindowSettings* ImGui::FindWindowSettings(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
+ if (settings->ID == id)
+ return settings;
+ return NULL;
+}
+
+ImGuiWindowSettings* ImGui::FindOrCreateWindowSettings(const char* name)
+{
+ if (ImGuiWindowSettings* settings = FindWindowSettings(ImHashStr(name)))
+ return settings;
+ return CreateNewWindowSettings(name);
+}
+
+ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiID type_hash = ImHashStr(type_name);
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ if (g.SettingsHandlers[handler_n].TypeHash == type_hash)
+ return &g.SettingsHandlers[handler_n];
+ return NULL;
+}
+
+void ImGui::ClearIniSettings()
+{
+ ImGuiContext& g = *GImGui;
+ g.SettingsIniData.clear();
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ if (g.SettingsHandlers[handler_n].ClearAllFn)
+ g.SettingsHandlers[handler_n].ClearAllFn(&g, &g.SettingsHandlers[handler_n]);
+}
+
+void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
+{
+ size_t file_data_size = 0;
+ char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size);
+ if (!file_data)
+ return;
+ LoadIniSettingsFromMemory(file_data, (size_t)file_data_size);
+ IM_FREE(file_data);
+}
+
+// Zero-tolerance, no error reporting, cheap .ini parsing
+void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Initialized);
+ //IM_ASSERT(!g.WithinFrameScope && "Cannot be called between NewFrame() and EndFrame()");
+ //IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0);
+
+ // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
+ // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
+ if (ini_size == 0)
+ ini_size = strlen(ini_data);
+ g.SettingsIniData.Buf.resize((int)ini_size + 1);
+ char* const buf = g.SettingsIniData.Buf.Data;
+ char* const buf_end = buf + ini_size;
+ memcpy(buf, ini_data, ini_size);
+ buf_end[0] = 0;
+
+ // Call pre-read handlers
+ // Some types will clear their data (e.g. dock information) some types will allow merge/override (window)
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ if (g.SettingsHandlers[handler_n].ReadInitFn)
+ g.SettingsHandlers[handler_n].ReadInitFn(&g, &g.SettingsHandlers[handler_n]);
+
+ void* entry_data = NULL;
+ ImGuiSettingsHandler* entry_handler = NULL;
+
+ char* line_end = NULL;
+ for (char* line = buf; line < buf_end; line = line_end + 1)
+ {
+ // Skip new lines markers, then find end of the line
+ while (*line == '\n' || *line == '\r')
+ line++;
+ line_end = line;
+ while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
+ line_end++;
+ line_end[0] = 0;
+ if (line[0] == ';')
+ continue;
+ if (line[0] == '[' && line_end > line && line_end[-1] == ']')
+ {
+ // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code.
+ line_end[-1] = 0;
+ const char* name_end = line_end - 1;
+ const char* type_start = line + 1;
+ char* type_end = (char*)(void*)ImStrchrRange(type_start, name_end, ']');
+ const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL;
+ if (!type_end || !name_start)
+ continue;
+ *type_end = 0; // Overwrite first ']'
+ name_start++; // Skip second '['
+ entry_handler = FindSettingsHandler(type_start);
+ entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL;
+ }
+ else if (entry_handler != NULL && entry_data != NULL)
+ {
+ // Let type handler parse the line
+ entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
+ }
+ }
+ g.SettingsLoaded = true;
+
+ // [DEBUG] Restore untouched copy so it can be browsed in Metrics (not strictly necessary)
+ memcpy(buf, ini_data, ini_size);
+
+ // Call post-read handlers
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ if (g.SettingsHandlers[handler_n].ApplyAllFn)
+ g.SettingsHandlers[handler_n].ApplyAllFn(&g, &g.SettingsHandlers[handler_n]);
+}
+
+void ImGui::SaveIniSettingsToDisk(const char* ini_filename)
+{
+ ImGuiContext& g = *GImGui;
+ g.SettingsDirtyTimer = 0.0f;
+ if (!ini_filename)
+ return;
+
+ size_t ini_data_size = 0;
+ const char* ini_data = SaveIniSettingsToMemory(&ini_data_size);
+ ImFileHandle f = ImFileOpen(ini_filename, "wt");
+ if (!f)
+ return;
+ ImFileWrite(ini_data, sizeof(char), ini_data_size, f);
+ ImFileClose(f);
+}
+
+// Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer
+const char* ImGui::SaveIniSettingsToMemory(size_t* out_size)
+{
+ ImGuiContext& g = *GImGui;
+ g.SettingsDirtyTimer = 0.0f;
+ g.SettingsIniData.Buf.resize(0);
+ g.SettingsIniData.Buf.push_back(0);
+ for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++)
+ {
+ ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n];
+ handler->WriteAllFn(&g, handler, &g.SettingsIniData);
+ }
+ if (out_size)
+ *out_size = (size_t)g.SettingsIniData.size();
+ return g.SettingsIniData.c_str();
+}
+
+static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
+{
+ ImGuiContext& g = *ctx;
+ for (int i = 0; i != g.Windows.Size; i++)
+ g.Windows[i]->SettingsOffset = -1;
+ g.SettingsWindows.clear();
+}
+
+static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
+{
+ ImGuiWindowSettings* settings = ImGui::FindOrCreateWindowSettings(name);
+ ImGuiID id = settings->ID;
+ *settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry
+ settings->ID = id;
+ settings->WantApply = true;
+ return (void*)settings;
+}
+
+static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line)
+{
+ ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
+ int x, y;
+ int i;
+ if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((short)x, (short)y); }
+ else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); }
+ else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
+}
+
+// Apply to existing windows (if any)
+static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
+{
+ ImGuiContext& g = *ctx;
+ for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
+ if (settings->WantApply)
+ {
+ if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID))
+ ApplyWindowSettings(window, settings);
+ settings->WantApply = false;
+ }
+}
+
+static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
+{
+ // Gather data from windows that were active during this session
+ // (if a window wasn't opened in this session we preserve its settings)
+ ImGuiContext& g = *ctx;
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* window = g.Windows[i];
+ if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
+ continue;
+
+ ImGuiWindowSettings* settings = (window->SettingsOffset != -1) ? g.SettingsWindows.ptr_from_offset(window->SettingsOffset) : ImGui::FindWindowSettings(window->ID);
+ if (!settings)
+ {
+ settings = ImGui::CreateNewWindowSettings(window->Name);
+ window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings);
+ }
+ IM_ASSERT(settings->ID == window->ID);
+ settings->Pos = ImVec2ih(window->Pos);
+ settings->Size = ImVec2ih(window->SizeFull);
+
+ settings->Collapsed = window->Collapsed;
+ }
+
+ // Write to text buffer
+ buf->reserve(buf->size() + g.SettingsWindows.size() * 6); // ballpark reserve
+ for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
+ {
+ const char* settings_name = settings->GetName();
+ buf->appendf("[%s][%s]\n", handler->TypeName, settings_name);
+ buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
+ buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y);
+ buf->appendf("Collapsed=%d\n", settings->Collapsed);
+ buf->append("\n");
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] VIEWPORTS, PLATFORM WINDOWS
+//-----------------------------------------------------------------------------
+// - GetMainViewport()
+// - UpdateViewportsNewFrame() [Internal]
+// (this section is more complete in the 'docking' branch)
+//-----------------------------------------------------------------------------
+
+ImGuiViewport* ImGui::GetMainViewport()
+{
+ ImGuiContext& g = *GImGui;
+ return g.Viewports[0];
+}
+
+// Update viewports and monitor infos
+static void ImGui::UpdateViewportsNewFrame()
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(g.Viewports.Size == 1);
+
+ // Update main viewport with current platform position.
+ // FIXME-VIEWPORT: Size is driven by backend/user code for backward-compatibility but we should aim to make this more consistent.
+ ImGuiViewportP* main_viewport = g.Viewports[0];
+ main_viewport->Flags = ImGuiViewportFlags_IsPlatformWindow | ImGuiViewportFlags_OwnedByApp;
+ main_viewport->Pos = ImVec2(0.0f, 0.0f);
+ main_viewport->Size = g.IO.DisplaySize;
+
+ for (int n = 0; n < g.Viewports.Size; n++)
+ {
+ ImGuiViewportP* viewport = g.Viewports[n];
+
+ // Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again.
+ viewport->WorkOffsetMin = viewport->BuildWorkOffsetMin;
+ viewport->WorkOffsetMax = viewport->BuildWorkOffsetMax;
+ viewport->BuildWorkOffsetMin = viewport->BuildWorkOffsetMax = ImVec2(0.0f, 0.0f);
+ viewport->UpdateWorkRect();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] DOCKING
+//-----------------------------------------------------------------------------
+
+// (this section is filled in the 'docking' branch)
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] PLATFORM DEPENDENT HELPERS
+//-----------------------------------------------------------------------------
+
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS)
+
+#ifdef _MSC_VER
+#pragma comment(lib, "user32")
+#pragma comment(lib, "kernel32")
+#endif
+
+// Win32 clipboard implementation
+// We use g.ClipboardHandlerData for temporary storage to ensure it is freed on Shutdown()
+static const char* GetClipboardTextFn_DefaultImpl(void*)
+{
+ ImGuiContext& g = *GImGui;
+ g.ClipboardHandlerData.clear();
+ if (!::OpenClipboard(NULL))
+ return NULL;
+ HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
+ if (wbuf_handle == NULL)
+ {
+ ::CloseClipboard();
+ return NULL;
+ }
+ if (const WCHAR* wbuf_global = (const WCHAR*)::GlobalLock(wbuf_handle))
+ {
+ int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL);
+ g.ClipboardHandlerData.resize(buf_len);
+ ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, g.ClipboardHandlerData.Data, buf_len, NULL, NULL);
+ }
+ ::GlobalUnlock(wbuf_handle);
+ ::CloseClipboard();
+ return g.ClipboardHandlerData.Data;
+}
+
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
+{
+ if (!::OpenClipboard(NULL))
+ return;
+ const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0);
+ HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(WCHAR));
+ if (wbuf_handle == NULL)
+ {
+ ::CloseClipboard();
+ return;
+ }
+ WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle);
+ ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length);
+ ::GlobalUnlock(wbuf_handle);
+ ::EmptyClipboard();
+ if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
+ ::GlobalFree(wbuf_handle);
+ ::CloseClipboard();
+}
+
+#elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS)
+
+#include <Carbon/Carbon.h> // Use old API to avoid need for separate .mm file
+static PasteboardRef main_clipboard = 0;
+
+// OSX clipboard implementation
+// If you enable this you will need to add '-framework ApplicationServices' to your linker command-line!
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
+{
+ if (!main_clipboard)
+ PasteboardCreate(kPasteboardClipboard, &main_clipboard);
+ PasteboardClear(main_clipboard);
+ CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, strlen(text));
+ if (cf_data)
+ {
+ PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), cf_data, 0);
+ CFRelease(cf_data);
+ }
+}
+
+static const char* GetClipboardTextFn_DefaultImpl(void*)
+{
+ if (!main_clipboard)
+ PasteboardCreate(kPasteboardClipboard, &main_clipboard);
+ PasteboardSynchronize(main_clipboard);
+
+ ItemCount item_count = 0;
+ PasteboardGetItemCount(main_clipboard, &item_count);
+ for (ItemCount i = 0; i < item_count; i++)
+ {
+ PasteboardItemID item_id = 0;
+ PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
+ CFArrayRef flavor_type_array = 0;
+ PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array);
+ for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++)
+ {
+ CFDataRef cf_data;
+ if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR("public.utf8-plain-text"), &cf_data) == noErr)
+ {
+ ImGuiContext& g = *GImGui;
+ g.ClipboardHandlerData.clear();
+ int length = (int)CFDataGetLength(cf_data);
+ g.ClipboardHandlerData.resize(length + 1);
+ CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8*)g.ClipboardHandlerData.Data);
+ g.ClipboardHandlerData[length] = 0;
+ CFRelease(cf_data);
+ return g.ClipboardHandlerData.Data;
+ }
+ }
+ }
+ return NULL;
+}
+
+#else
+
+// Local Dear ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers.
+static const char* GetClipboardTextFn_DefaultImpl(void*)
+{
+ ImGuiContext& g = *GImGui;
+ return g.ClipboardHandlerData.empty() ? NULL : g.ClipboardHandlerData.begin();
+}
+
+static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
+{
+ ImGuiContext& g = *GImGui;
+ g.ClipboardHandlerData.clear();
+ const char* text_end = text + strlen(text);
+ g.ClipboardHandlerData.resize((int)(text_end - text) + 1);
+ memcpy(&g.ClipboardHandlerData[0], text, (size_t)(text_end - text));
+ g.ClipboardHandlerData[(int)(text_end - text)] = 0;
+}
+
+#endif
+
+// Win32 API IME support (for Asian languages, etc.)
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
+
+#include <imm.h>
+#ifdef _MSC_VER
+#pragma comment(lib, "imm32")
+#endif
+
+static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
+{
+ // Notify OS Input Method Editor of text input position
+ ImGuiIO& io = ImGui::GetIO();
+ if (HWND hwnd = (HWND)io.ImeWindowHandle)
+ if (HIMC himc = ::ImmGetContext(hwnd))
+ {
+ COMPOSITIONFORM cf;
+ cf.ptCurrentPos.x = x;
+ cf.ptCurrentPos.y = y;
+ cf.dwStyle = CFS_FORCE_POSITION;
+ ::ImmSetCompositionWindow(himc, &cf);
+ ::ImmReleaseContext(hwnd, himc);
+ }
+}
+
+#else
+
+static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] METRICS/DEBUGGER WINDOW
+//-----------------------------------------------------------------------------
+// - RenderViewportThumbnail() [Internal]
+// - RenderViewportsThumbnails() [Internal]
+// - MetricsHelpMarker() [Internal]
+// - ShowMetricsWindow()
+// - DebugNodeColumns() [Internal]
+// - DebugNodeDrawList() [Internal]
+// - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal]
+// - DebugNodeStorage() [Internal]
+// - DebugNodeTabBar() [Internal]
+// - DebugNodeViewport() [Internal]
+// - DebugNodeWindow() [Internal]
+// - DebugNodeWindowSettings() [Internal]
+// - DebugNodeWindowsList() [Internal]
+//-----------------------------------------------------------------------------
+
+#ifndef IMGUI_DISABLE_METRICS_WINDOW
+
+void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ ImVec2 scale = bb.GetSize() / viewport->Size;
+ ImVec2 off = bb.Min - viewport->Pos * scale;
+ float alpha_mul = 1.0f;
+ window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f));
+ for (int i = 0; i != g.Windows.Size; i++)
+ {
+ ImGuiWindow* thumb_window = g.Windows[i];
+ if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow))
+ continue;
+
+ ImRect thumb_r = thumb_window->Rect();
+ ImRect title_r = thumb_window->TitleBarRect();
+ thumb_r = ImRect(ImFloor(off + thumb_r.Min * scale), ImFloor(off + thumb_r.Max * scale));
+ title_r = ImRect(ImFloor(off + title_r.Min * scale), ImFloor(off + ImVec2(title_r.Max.x, title_r.Min.y) * scale) + ImVec2(0,5)); // Exaggerate title bar height
+ thumb_r.ClipWithFull(bb);
+ title_r.ClipWithFull(bb);
+ const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight);
+ window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
+ window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
+ window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
+ window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
+ }
+ draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
+}
+
+static void RenderViewportsThumbnails()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports.
+ float SCALE = 1.0f / 8.0f;
+ ImRect bb_full(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
+ for (int n = 0; n < g.Viewports.Size; n++)
+ bb_full.Add(g.Viewports[n]->GetMainRect());
+ ImVec2 p = window->DC.CursorPos;
+ ImVec2 off = p - bb_full.Min * SCALE;
+ for (int n = 0; n < g.Viewports.Size; n++)
+ {
+ ImGuiViewportP* viewport = g.Viewports[n];
+ ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
+ ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
+ }
+ ImGui::Dummy(bb_full.GetSize() * SCALE);
+}
+
+// Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds.
+static void MetricsHelpMarker(const char* desc)
+{
+ ImGui::TextDisabled("(?)");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
+ ImGui::TextUnformatted(desc);
+ ImGui::PopTextWrapPos();
+ ImGui::EndTooltip();
+ }
+}
+
+#ifndef IMGUI_DISABLE_DEMO_WINDOWS
+namespace ImGui { void ShowFontAtlas(ImFontAtlas* atlas); }
+#endif
+
+void ImGui::ShowMetricsWindow(bool* p_open)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+ ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
+ if (cfg->ShowStackTool)
+ ShowStackToolWindow(&cfg->ShowStackTool);
+
+ if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1)
+ {
+ End();
+ return;
+ }
+
+ // Basic info
+ Text("Dear ImGui %s", GetVersion());
+ Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
+ Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3);
+ Text("%d visible windows, %d active allocations", io.MetricsRenderWindows, io.MetricsActiveAllocations);
+ //SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; }
+
+ Separator();
+
+ // Debugging enums
+ enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type
+ const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentIdeal", "ContentRegionRect" };
+ enum { TRT_OuterRect, TRT_InnerRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsWorkRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentFrozen, TRT_ColumnsContentUnfrozen, TRT_Count }; // Tables Rect Type
+ const char* trt_rects_names[TRT_Count] = { "OuterRect", "InnerRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsWorkRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentFrozen", "ColumnsContentUnfrozen" };
+ if (cfg->ShowWindowsRectsType < 0)
+ cfg->ShowWindowsRectsType = WRT_WorkRect;
+ if (cfg->ShowTablesRectsType < 0)
+ cfg->ShowTablesRectsType = TRT_WorkRect;
+
+ struct Funcs
+ {
+ static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n)
+ {
+ if (rect_type == TRT_OuterRect) { return table->OuterRect; }
+ else if (rect_type == TRT_InnerRect) { return table->InnerRect; }
+ else if (rect_type == TRT_WorkRect) { return table->WorkRect; }
+ else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; }
+ else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; }
+ else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; }
+ else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); }
+ else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); }
+ else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
+ else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate
+ else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }
+ else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }
+ else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); }
+ IM_ASSERT(0);
+ return ImRect();
+ }
+
+ static ImRect GetWindowRect(ImGuiWindow* window, int rect_type)
+ {
+ if (rect_type == WRT_OuterRect) { return window->Rect(); }
+ else if (rect_type == WRT_OuterRectClipped) { return window->OuterRectClipped; }
+ else if (rect_type == WRT_InnerRect) { return window->InnerRect; }
+ else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; }
+ else if (rect_type == WRT_WorkRect) { return window->WorkRect; }
+ else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); }
+ else if (rect_type == WRT_ContentIdeal) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSizeIdeal); }
+ else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; }
+ IM_ASSERT(0);
+ return ImRect();
+ }
+ };
+
+ // Tools
+ if (TreeNode("Tools"))
+ {
+ // Stack Tool is your best friend!
+ Checkbox("Show stack tool", &cfg->ShowStackTool);
+ SameLine();
+ MetricsHelpMarker("You can also call ImGui::ShowStackToolWindow() from your code.");
+
+ Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder);
+ Checkbox("Show windows rectangles", &cfg->ShowWindowsRects);
+ SameLine();
+ SetNextItemWidth(GetFontSize() * 12);
+ cfg->ShowWindowsRects |= Combo("##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count);
+ if (cfg->ShowWindowsRects && g.NavWindow != NULL)
+ {
+ BulletText("'%s':", g.NavWindow->Name);
+ Indent();
+ for (int rect_n = 0; rect_n < WRT_Count; rect_n++)
+ {
+ ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n);
+ Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]);
+ }
+ Unindent();
+ }
+
+ Checkbox("Show tables rectangles", &cfg->ShowTablesRects);
+ SameLine();
+ SetNextItemWidth(GetFontSize() * 12);
+ cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
+ if (cfg->ShowTablesRects && g.NavWindow != NULL)
+ {
+ for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
+ {
+ ImGuiTable* table = g.Tables.TryGetMapData(table_n);
+ if (table == NULL || table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow))
+ continue;
+
+ BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
+ if (IsItemHovered())
+ GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
+ Indent();
+ char buf[128];
+ for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
+ {
+ if (rect_n >= TRT_ColumnsRect)
+ {
+ if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect)
+ continue;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
+ Selectable(buf);
+ if (IsItemHovered())
+ GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
+ }
+ }
+ else
+ {
+ ImRect r = Funcs::GetTableRect(table, rect_n, -1);
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
+ Selectable(buf);
+ if (IsItemHovered())
+ GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
+ }
+ }
+ Unindent();
+ }
+ }
+
+ // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted.
+ if (Button("Item Picker.."))
+ DebugStartItemPicker();
+ SameLine();
+ MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash.");
+
+ TreePop();
+ }
+
+ // Windows
+ DebugNodeWindowsList(&g.Windows, "Windows");
+ //DebugNodeWindowsList(&g.WindowsFocusOrder, "WindowsFocusOrder");
+
+ // DrawLists
+ int drawlist_count = 0;
+ for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++)
+ drawlist_count += g.Viewports[viewport_i]->DrawDataBuilder.GetDrawListCount();
+ if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count))
+ {
+ Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
+ Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
+ for (int viewport_i = 0; viewport_i < g.Viewports.Size; viewport_i++)
+ {
+ ImGuiViewportP* viewport = g.Viewports[viewport_i];
+ for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++)
+ for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[layer_i].Size; draw_list_i++)
+ DebugNodeDrawList(NULL, viewport->DrawDataBuilder.Layers[layer_i][draw_list_i], "DrawList");
+ }
+ TreePop();
+ }
+
+ // Viewports
+ if (TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size))
+ {
+ Indent(GetTreeNodeToLabelSpacing());
+ RenderViewportsThumbnails();
+ Unindent(GetTreeNodeToLabelSpacing());
+ for (int i = 0; i < g.Viewports.Size; i++)
+ DebugNodeViewport(g.Viewports[i]);
+ TreePop();
+ }
+
+ // Details for Popups
+ if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size))
+ {
+ for (int i = 0; i < g.OpenPopupStack.Size; i++)
+ {
+ ImGuiWindow* window = g.OpenPopupStack[i].Window;
+ BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : "");
+ }
+ TreePop();
+ }
+
+ // Details for TabBars
+ if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetAliveCount()))
+ {
+ for (int n = 0; n < g.TabBars.GetMapSize(); n++)
+ if (ImGuiTabBar* tab_bar = g.TabBars.TryGetMapData(n))
+ {
+ PushID(tab_bar);
+ DebugNodeTabBar(tab_bar, "TabBar");
+ PopID();
+ }
+ TreePop();
+ }
+
+ // Details for Tables
+ if (TreeNode("Tables", "Tables (%d)", g.Tables.GetAliveCount()))
+ {
+ for (int n = 0; n < g.Tables.GetMapSize(); n++)
+ if (ImGuiTable* table = g.Tables.TryGetMapData(n))
+ DebugNodeTable(table);
+ TreePop();
+ }
+
+ // Details for Fonts
+#ifndef IMGUI_DISABLE_DEMO_WINDOWS
+ ImFontAtlas* atlas = g.IO.Fonts;
+ if (TreeNode("Fonts", "Fonts (%d)", atlas->Fonts.Size))
+ {
+ ShowFontAtlas(atlas);
+ TreePop();
+ }
+#endif
+
+ // Details for Docking
+#ifdef IMGUI_HAS_DOCK
+ if (TreeNode("Docking"))
+ {
+ TreePop();
+ }
+#endif // #ifdef IMGUI_HAS_DOCK
+
+ // Settings
+ if (TreeNode("Settings"))
+ {
+ if (SmallButton("Clear"))
+ ClearIniSettings();
+ SameLine();
+ if (SmallButton("Save to memory"))
+ SaveIniSettingsToMemory();
+ SameLine();
+ if (SmallButton("Save to disk"))
+ SaveIniSettingsToDisk(g.IO.IniFilename);
+ SameLine();
+ if (g.IO.IniFilename)
+ Text("\"%s\"", g.IO.IniFilename);
+ else
+ TextUnformatted("<NULL>");
+ Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer);
+ if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size))
+ {
+ for (int n = 0; n < g.SettingsHandlers.Size; n++)
+ BulletText("%s", g.SettingsHandlers[n].TypeName);
+ TreePop();
+ }
+ if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
+ {
+ for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings))
+ DebugNodeWindowSettings(settings);
+ TreePop();
+ }
+
+ if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
+ {
+ for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
+ DebugNodeTableSettings(settings);
+ TreePop();
+ }
+
+#ifdef IMGUI_HAS_DOCK
+#endif // #ifdef IMGUI_HAS_DOCK
+
+ if (TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size()))
+ {
+ InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly);
+ TreePop();
+ }
+ TreePop();
+ }
+
+ // Misc Details
+ if (TreeNode("Internal state"))
+ {
+ const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
+
+ Text("WINDOWING");
+ Indent();
+ Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
+ Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindow->Name : "NULL");
+ Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL");
+ Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL");
+ Unindent();
+
+ Text("ITEMS");
+ Indent();
+ Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]);
+ Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
+ Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInputMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdUsingNavInputMask, g.ActiveIdUsingKeyInputMask);
+ Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame
+ Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
+ Unindent();
+
+ Text("NAV,FOCUS");
+ Indent();
+ Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL");
+ Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer);
+ Text("NavInputSource: %s", input_source_names[g.NavInputSource]);
+ Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
+ Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId);
+ Text("NavActivateFlags: %04X", g.NavActivateFlags);
+ Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
+ Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
+ Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL");
+ Unindent();
+
+ TreePop();
+ }
+
+ // Overlay: Display windows Rectangles and Begin Order
+ if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder)
+ {
+ for (int n = 0; n < g.Windows.Size; n++)
+ {
+ ImGuiWindow* window = g.Windows[n];
+ if (!window->WasActive)
+ continue;
+ ImDrawList* draw_list = GetForegroundDrawList(window);
+ if (cfg->ShowWindowsRects)
+ {
+ ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType);
+ draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
+ }
+ if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow))
+ {
+ char buf[32];
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
+ float font_size = GetFontSize();
+ draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
+ draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf);
+ }
+ }
+ }
+
+ // Overlay: Display Tables Rectangles
+ if (cfg->ShowTablesRects)
+ {
+ for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++)
+ {
+ ImGuiTable* table = g.Tables.TryGetMapData(table_n);
+ if (table == NULL || table->LastFrameActive < g.FrameCount - 1)
+ continue;
+ ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
+ if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
+ {
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
+ ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
+ float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
+ draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
+ }
+ }
+ else
+ {
+ ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1);
+ draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
+ }
+ }
+ }
+
+#ifdef IMGUI_HAS_DOCK
+ // Overlay: Display Docking info
+ if (show_docking_nodes && g.IO.KeyCtrl)
+ {
+ }
+#endif // #ifdef IMGUI_HAS_DOCK
+
+ End();
+}
+
+// [DEBUG] List fonts in a font atlas and display its texture
+void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
+{
+ for (int i = 0; i < atlas->Fonts.Size; i++)
+ {
+ ImFont* font = atlas->Fonts[i];
+ PushID(font);
+ DebugNodeFont(font);
+ PopID();
+ }
+ if (TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
+ {
+ ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
+ ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
+ Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col);
+ TreePop();
+ }
+}
+
+// [DEBUG] Display contents of Columns
+void ImGui::DebugNodeColumns(ImGuiOldColumns* columns)
+{
+ if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
+ return;
+ BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX);
+ for (int column_n = 0; column_n < columns->Columns.Size; column_n++)
+ BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, GetColumnOffsetFromNorm(columns, columns->Columns[column_n].OffsetNorm));
+ TreePop();
+}
+
+// [DEBUG] Display contents of ImDrawList
+void ImGui::DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
+ int cmd_count = draw_list->CmdBuffer.Size;
+ if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL)
+ cmd_count--;
+ bool node_open = TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count);
+ if (draw_list == GetWindowDrawList())
+ {
+ SameLine();
+ TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered)
+ if (node_open)
+ TreePop();
+ return;
+ }
+
+ ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list
+ if (window && IsItemHovered())
+ fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
+ if (!node_open)
+ return;
+
+ if (window && !window->WasActive)
+ TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!");
+
+ for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++)
+ {
+ if (pcmd->UserCallback)
+ {
+ BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData);
+ continue;
+ }
+
+ char buf[300];
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex 0x%p, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)",
+ pcmd->ElemCount / 3, (void*)(intptr_t)pcmd->TextureId,
+ pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w);
+ bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf);
+ if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list)
+ DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes);
+ if (!pcmd_node_open)
+ continue;
+
+ // Calculate approximate coverage area (touched pixel count)
+ // This will be in pixels squared as long there's no post-scaling happening to the renderer output.
+ const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL;
+ const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset;
+ float total_area = 0.0f;
+ for (unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; )
+ {
+ ImVec2 triangle[3];
+ for (int n = 0; n < 3; n++, idx_n++)
+ triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos;
+ total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]);
+ }
+
+ // Display vertex information summary. Hover to get all triangles drawn in wire-frame
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area);
+ Selectable(buf);
+ if (IsItemHovered() && fg_draw_list)
+ DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false);
+
+ // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted.
+ ImGuiListClipper clipper;
+ clipper.Begin(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible.
+ while (clipper.Step())
+ for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++)
+ {
+ char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf);
+ ImVec2 triangle[3];
+ for (int n = 0; n < 3; n++, idx_i++)
+ {
+ const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i];
+ triangle[n] = v.pos;
+ buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n",
+ (n == 0) ? "Vert:" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col);
+ }
+
+ Selectable(buf, false);
+ if (fg_draw_list && IsItemHovered())
+ {
+ ImDrawListFlags backup_flags = fg_draw_list->Flags;
+ fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
+ fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
+ fg_draw_list->Flags = backup_flags;
+ }
+ }
+ TreePop();
+ }
+ TreePop();
+}
+
+// [DEBUG] Display mesh/aabb of a ImDrawCmd
+void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb)
+{
+ IM_ASSERT(show_mesh || show_aabb);
+
+ // Draw wire-frame version of all triangles
+ ImRect clip_rect = draw_cmd->ClipRect;
+ ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX);
+ ImDrawListFlags backup_flags = out_draw_list->Flags;
+ out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
+ for (unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; )
+ {
+ ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; // We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list
+ ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset;
+
+ ImVec2 triangle[3];
+ for (int n = 0; n < 3; n++, idx_n++)
+ vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
+ if (show_mesh)
+ out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles
+ }
+ // Draw bounding boxes
+ if (show_aabb)
+ {
+ out_draw_list->AddRect(ImFloor(clip_rect.Min), ImFloor(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU
+ out_draw_list->AddRect(ImFloor(vtxs_rect.Min), ImFloor(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles
+ }
+ out_draw_list->Flags = backup_flags;
+}
+
+// [DEBUG] Display details for a single font, called by ShowStyleEditor().
+void ImGui::DebugNodeFont(ImFont* font)
+{
+ bool opened = TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
+ font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
+ SameLine();
+ if (SmallButton("Set as default"))
+ GetIO().FontDefault = font;
+ if (!opened)
+ return;
+
+ // Display preview text
+ PushFont(font);
+ Text("The quick brown fox jumps over the lazy dog");
+ PopFont();
+
+ // Display details
+ SetNextItemWidth(GetFontSize() * 8);
+ DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");
+ SameLine(); MetricsHelpMarker(
+ "Note than the default embedded font is NOT meant to be scaled.\n\n"
+ "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
+ "You may oversample them to get some flexibility with scaling. "
+ "You can also render at multiple sizes and select which one to use at runtime.\n\n"
+ "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
+ Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
+ char c_str[5];
+ Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
+ Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
+ const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface);
+ Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
+ for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
+ if (font->ConfigData)
+ if (const ImFontConfig* cfg = &font->ConfigData[config_i])
+ BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
+ config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
+
+ // Display all glyphs of the fonts in separate pages of 256 characters
+ if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
+ {
+ ImDrawList* draw_list = GetWindowDrawList();
+ const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
+ const float cell_size = font->FontSize * 1;
+ const float cell_spacing = GetStyle().ItemSpacing.y;
+ for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
+ {
+ // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)
+ // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT
+ // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here)
+ if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
+ {
+ base += 4096 - 256;
+ continue;
+ }
+
+ int count = 0;
+ for (unsigned int n = 0; n < 256; n++)
+ if (font->FindGlyphNoFallback((ImWchar)(base + n)))
+ count++;
+ if (count <= 0)
+ continue;
+ if (!TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
+ continue;
+
+ // Draw a 16x16 grid of glyphs
+ ImVec2 base_pos = GetCursorScreenPos();
+ for (unsigned int n = 0; n < 256; n++)
+ {
+ // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions
+ // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.
+ ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
+ ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
+ const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
+ draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
+ if (glyph)
+ font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
+ if (glyph && IsMouseHoveringRect(cell_p1, cell_p2))
+ {
+ BeginTooltip();
+ Text("Codepoint: U+%04X", base + n);
+ Separator();
+ Text("Visible: %d", glyph->Visible);
+ Text("AdvanceX: %.1f", glyph->AdvanceX);
+ Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
+ Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
+ EndTooltip();
+ }
+ }
+ Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
+ TreePop();
+ }
+ TreePop();
+ }
+ TreePop();
+}
+
+// [DEBUG] Display contents of ImGuiStorage
+void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label)
+{
+ if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes()))
+ return;
+ for (int n = 0; n < storage->Data.Size; n++)
+ {
+ const ImGuiStorage::ImGuiStoragePair& p = storage->Data[n];
+ BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer.
+ }
+ TreePop();
+}
+
+// [DEBUG] Display contents of ImGuiTabBar
+void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
+{
+ // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings.
+ char buf[256];
+ char* p = buf;
+ const char* buf_end = buf + IM_ARRAYSIZE(buf);
+ const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2);
+ p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
+ p += ImFormatString(p, buf_end - p, " { ");
+ for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ p += ImFormatString(p, buf_end - p, "%s'%s'",
+ tab_n > 0 ? ", " : "", (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???");
+ }
+ p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } ");
+ if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
+ bool open = TreeNode(label, "%s", buf);
+ if (!is_active) { PopStyleColor(); }
+ if (is_active && IsItemHovered())
+ {
+ ImDrawList* draw_list = GetForegroundDrawList();
+ draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
+ draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
+ draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
+ }
+ if (open)
+ {
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ PushID(tab);
+ if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2);
+ if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine();
+ Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f",
+ tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???", tab->Offset, tab->Width, tab->ContentWidth);
+ PopID();
+ }
+ TreePop();
+ }
+}
+
+void ImGui::DebugNodeViewport(ImGuiViewportP* viewport)
+{
+ SetNextItemOpen(true, ImGuiCond_Once);
+ if (TreeNode("viewport0", "Viewport #%d", 0))
+ {
+ ImGuiWindowFlags flags = viewport->Flags;
+ BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f",
+ viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y,
+ viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y);
+ BulletText("Flags: 0x%04X =%s%s%s", viewport->Flags,
+ (flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "",
+ (flags & ImGuiViewportFlags_IsPlatformMonitor) ? " IsPlatformMonitor" : "",
+ (flags & ImGuiViewportFlags_OwnedByApp) ? " OwnedByApp" : "");
+ for (int layer_i = 0; layer_i < IM_ARRAYSIZE(viewport->DrawDataBuilder.Layers); layer_i++)
+ for (int draw_list_i = 0; draw_list_i < viewport->DrawDataBuilder.Layers[layer_i].Size; draw_list_i++)
+ DebugNodeDrawList(NULL, viewport->DrawDataBuilder.Layers[layer_i][draw_list_i], "DrawList");
+ TreePop();
+ }
+}
+
+void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
+{
+ if (window == NULL)
+ {
+ BulletText("%s: NULL", label);
+ return;
+ }
+
+ ImGuiContext& g = *GImGui;
+ const bool is_active = window->WasActive;
+ ImGuiTreeNodeFlags tree_node_flags = (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None;
+ if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
+ const bool open = TreeNodeEx(label, tree_node_flags, "%s '%s'%s", label, window->Name, is_active ? "" : " *Inactive*");
+ if (!is_active) { PopStyleColor(); }
+ if (IsItemHovered() && is_active)
+ GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
+ if (!open)
+ return;
+
+ if (window->MemoryCompacted)
+ TextDisabled("Note: some memory buffers have been compacted/freed.");
+
+ ImGuiWindowFlags flags = window->Flags;
+ DebugNodeDrawList(window, window->DrawList, "DrawList");
+ BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y, window->ContentSizeIdeal.x, window->ContentSizeIdeal.y);
+ BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
+ (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "",
+ (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "",
+ (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : "");
+ BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : "");
+ BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
+ BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
+ for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
+ {
+ ImRect r = window->NavRectRel[layer];
+ if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y)
+ {
+ BulletText("NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
+ continue;
+ }
+ BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y);
+ if (IsItemHovered())
+ GetForegroundDrawList(window)->AddRect(r.Min + window->Pos, r.Max + window->Pos, IM_COL32(255, 255, 0, 255));
+ }
+ BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
+ if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
+ if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
+ if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
+ if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
+ {
+ for (int n = 0; n < window->ColumnsStorage.Size; n++)
+ DebugNodeColumns(&window->ColumnsStorage[n]);
+ TreePop();
+ }
+ DebugNodeStorage(&window->StateStorage, "Storage");
+ TreePop();
+}
+
+void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings)
+{
+ Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d",
+ settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed);
+}
+
+void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label)
+{
+ if (!TreeNode(label, "%s (%d)", label, windows->Size))
+ return;
+ Text("(In front-to-back order:)");
+ for (int i = windows->Size - 1; i >= 0; i--) // Iterate front to back
+ {
+ PushID((*windows)[i]);
+ DebugNodeWindow((*windows)[i], "Window");
+ PopID();
+ }
+ TreePop();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL)
+//-----------------------------------------------------------------------------
+
+// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack.
+void ImGui::UpdateDebugToolItemPicker()
+{
+ ImGuiContext& g = *GImGui;
+ g.DebugItemPickerBreakId = 0;
+ if (!g.DebugItemPickerActive)
+ return;
+
+ const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
+ SetMouseCursor(ImGuiMouseCursor_Hand);
+ if (IsKeyPressedMap(ImGuiKey_Escape))
+ g.DebugItemPickerActive = false;
+ if (IsMouseClicked(0) && hovered_id)
+ {
+ g.DebugItemPickerBreakId = hovered_id;
+ g.DebugItemPickerActive = false;
+ }
+ SetNextWindowBgAlpha(0.60f);
+ BeginTooltip();
+ Text("HoveredId: 0x%08X", hovered_id);
+ Text("Press ESC to abort picking.");
+ TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!");
+ EndTooltip();
+}
+
+// [DEBUG] Stack Tool: update queries. Called by NewFrame()
+void ImGui::UpdateDebugToolStackQueries()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiStackTool* tool = &g.DebugStackTool;
+
+ // Clear hook when stack tool is not visible
+ g.DebugHookIdInfo = 0;
+ if (g.FrameCount != tool->LastActiveFrame + 1)
+ return;
+
+ // Update queries. The steps are: -1: query Stack, >= 0: query each stack item
+ // We can only perform 1 ID Info query every frame. This is designed so the GetID() tests are cheap and constant-time
+ const ImGuiID query_id = g.HoveredIdPreviousFrame ? g.HoveredIdPreviousFrame : g.ActiveId;
+ if (tool->QueryId != query_id)
+ {
+ tool->QueryId = query_id;
+ tool->StackLevel = -1;
+ tool->Results.resize(0);
+ }
+ if (query_id == 0)
+ return;
+
+ // Advance to next stack level when we got our result, or after 2 frames (in case we never get a result)
+ int stack_level = tool->StackLevel;
+ if (stack_level >= 0 && stack_level < tool->Results.Size)
+ if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2)
+ tool->StackLevel++;
+
+ // Update hook
+ stack_level = tool->StackLevel;
+ if (stack_level == -1)
+ g.DebugHookIdInfo = query_id;
+ if (stack_level >= 0 && stack_level < tool->Results.Size)
+ {
+ g.DebugHookIdInfo = tool->Results[stack_level].ID;
+ tool->Results[stack_level].QueryFrameCount++;
+ }
+}
+
+// [DEBUG] Stack tool: hooks called by GetID() family functions
+void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiStackTool* tool = &g.DebugStackTool;
+
+ // Step 0: stack query
+ // This assume that the ID was computed with the current ID stack, which tends to be the case for our widget.
+ if (tool->StackLevel == -1)
+ {
+ tool->StackLevel++;
+ tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo());
+ for (int n = 0; n < window->IDStack.Size + 1; n++)
+ tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] : id;
+ return;
+ }
+
+ // Step 1+: query for individual level
+ IM_ASSERT(tool->StackLevel >= 0);
+ if (tool->StackLevel != window->IDStack.Size)
+ return;
+ ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel];
+ IM_ASSERT(info->ID == id && info->QueryFrameCount > 0);
+
+ int data_len;
+ switch (data_type)
+ {
+ case ImGuiDataType_S32:
+ ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%d", (int)(intptr_t)data_id);
+ break;
+ case ImGuiDataType_String:
+ data_len = data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)strlen((const char*)data_id);
+ ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "\"%.*s\"", data_len, (const char*)data_id);
+ break;
+ case ImGuiDataType_Pointer:
+ ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "(void*)0x%p", data_id);
+ break;
+ case ImGuiDataType_ID:
+ if (info->Desc[0] == 0) // PushOverrideID() is often used to avoid hashing twice, which would lead to 2 calls to DebugHookIdInfo(). We prioritize the first one.
+ ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "0x%08X [override]", id);
+ break;
+ default:
+ IM_ASSERT(0);
+ }
+ info->QuerySuccess = true;
+}
+
+// Stack Tool: Display UI
+void ImGui::ShowStackToolWindow(bool* p_open)
+{
+ if (!Begin("Dear ImGui Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1)
+ {
+ End();
+ return;
+ }
+
+ // Display hovered/active status
+ ImGuiContext& g = *GImGui;
+ const ImGuiID hovered_id = g.HoveredIdPreviousFrame;
+ const ImGuiID active_id = g.ActiveId;
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ Text("HoveredId: 0x%08X (\"%s\"), ActiveId: 0x%08X (\"%s\")", hovered_id, hovered_id ? ImGuiTestEngine_FindItemDebugLabel(&g, hovered_id) : "", active_id, active_id ? ImGuiTestEngine_FindItemDebugLabel(&g, active_id) : "");
+#else
+ Text("HoveredId: 0x%08X, ActiveId: 0x%08X", hovered_id, active_id);
+#endif
+ SameLine();
+ MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details.");
+
+ // Display decorated stack
+ ImGuiStackTool* tool = &g.DebugStackTool;
+ tool->LastActiveFrame = g.FrameCount;
+ if (tool->Results.Size > 0 && BeginTable("##table", 3, ImGuiTableFlags_Borders))
+ {
+ const float id_width = CalcTextSize("0xDDDDDDDD").x;
+ TableSetupColumn("Seed", ImGuiTableColumnFlags_WidthFixed, id_width);
+ TableSetupColumn("PushID", ImGuiTableColumnFlags_WidthStretch);
+ TableSetupColumn("Result", ImGuiTableColumnFlags_WidthFixed, id_width);
+ TableHeadersRow();
+ for (int n = 0; n < tool->Results.Size; n++)
+ {
+ ImGuiStackLevelInfo* info = &tool->Results[n];
+ TableNextColumn();
+ Text("0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0);
+
+ TableNextColumn();
+ ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? FindWindowByID(info->ID) : NULL;
+ if (window) // Source: window name (because the root ID don't call GetID() and so doesn't get hooked)
+ Text("\"%s\" [window]", window->Name);
+ else if (info->QuerySuccess) // Source: GetID() hooks (prioritize over ItemInfo() because we frequently use patterns like: PushID(str), Button("") where they both have same id)
+ TextUnformatted(info->Desc);
+ else if (tool->StackLevel >= tool->Results.Size) // Only start using fallback below when all queries are done, so during queries we don't flickering ??? markers.
+ {
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ if (const char* label = ImGuiTestEngine_FindItemDebugLabel(&g, info->ID)) // Source: ImGuiTestEngine's ItemInfo()
+ Text("??? \"%s\"", label);
+ else
+#endif
+ TextUnformatted("???");
+ }
+
+ TableNextColumn();
+ Text("0x%08X", info->ID);
+ if (n == tool->Results.Size - 1)
+ TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header));
+ }
+ EndTable();
+ }
+ End();
+}
+
+#else
+
+void ImGui::ShowMetricsWindow(bool*) {}
+void ImGui::ShowFontAtlas(ImFontAtlas*) {}
+void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
+void ImGui::DebugNodeDrawList(ImGuiWindow*, const ImDrawList*, const char*) {}
+void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
+void ImGui::DebugNodeFont(ImFont*) {}
+void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
+void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
+void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
+void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
+void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*, const char*) {}
+void ImGui::DebugNodeViewport(ImGuiViewportP*) {}
+
+void ImGui::ShowStackToolWindow(bool*) {}
+void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {}
+void ImGui::UpdateDebugToolItemPicker() {}
+void ImGui::UpdateDebugToolStackQueries() {}
+
+#endif // #ifndef IMGUI_DISABLE_METRICS_WINDOW
+
+//-----------------------------------------------------------------------------
+
+// Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed.
+// Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github.
+#ifdef IMGUI_INCLUDE_IMGUI_USER_INL
+#include "imgui_user.inl"
+#endif
+
+//-----------------------------------------------------------------------------
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imgui.h b/Client/ThirdParty/imgui/imgui.h
new file mode 100644
index 0000000..49218b0
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui.h
@@ -0,0 +1,2916 @@
+// dear imgui, v1.86 WIP
+// (headers)
+
+// Help:
+// - Read FAQ at http://dearimgui.org/faq
+// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
+// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
+// Read imgui.cpp for details, links and comments.
+
+// Resources:
+// - FAQ http://dearimgui.org/faq
+// - Homepage & latest https://github.com/ocornut/imgui
+// - Releases & changelog https://github.com/ocornut/imgui/releases
+// - Gallery https://github.com/ocornut/imgui/issues/4451 (please post your screenshots/video there!)
+// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
+// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
+// - Issues & support https://github.com/ocornut/imgui/issues
+
+// Getting Started?
+// - For first-time users having issues compiling/linking/running or issues loading fonts:
+// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
+
+/*
+
+Index of this file:
+// [SECTION] Header mess
+// [SECTION] Forward declarations and basic types
+// [SECTION] Dear ImGui end-user API functions
+// [SECTION] Flags & Enumerations
+// [SECTION] Helpers: Memory allocations macros, ImVector<>
+// [SECTION] ImGuiStyle
+// [SECTION] ImGuiIO
+// [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs)
+// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
+// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
+// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
+// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
+// [SECTION] Obsolete functions and types
+
+*/
+
+#pragma once
+
+// Configuration file with compile-time options (edit imconfig.h or '#define IMGUI_USER_CONFIG "myfilename.h" from your build system')
+#ifdef IMGUI_USER_CONFIG
+#include IMGUI_USER_CONFIG
+#endif
+#if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H)
+#include "imconfig.h"
+#endif
+
+#ifndef IMGUI_DISABLE
+
+//-----------------------------------------------------------------------------
+// [SECTION] Header mess
+//-----------------------------------------------------------------------------
+
+// Includes
+#include <float.h> // FLT_MIN, FLT_MAX
+#include <stdarg.h> // va_list, va_start, va_end
+#include <stddef.h> // ptrdiff_t, NULL
+#include <string.h> // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp
+
+// Version
+// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
+#define IMGUI_VERSION "1.86 WIP"
+#define IMGUI_VERSION_NUM 18511
+#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
+#define IMGUI_HAS_TABLE
+
+// Define attributes of all API symbols declarations (e.g. for DLL under Windows)
+// IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default backends files (imgui_impl_xxx.h)
+// Using dear imgui via a shared library is not recommended, because we don't guarantee backward nor forward ABI compatibility (also function call overhead, as dear imgui is a call-heavy API)
+#ifndef IMGUI_API
+#define IMGUI_API
+#endif
+#ifndef IMGUI_IMPL_API
+#define IMGUI_IMPL_API IMGUI_API
+#endif
+
+// Helper Macros
+#ifndef IM_ASSERT
+#include <assert.h>
+#define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h
+#endif
+#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers!
+#define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds.
+#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100)
+#define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11
+#else
+#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro.
+#endif
+
+// Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions.
+#if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__)
+#define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1)))
+#define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0)))
+#elif !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__))
+#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1)))
+#define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0)))
+#else
+#define IM_FMTARGS(FMT)
+#define IM_FMTLIST(FMT)
+#endif
+
+// Disable some of MSVC most aggressive Debug runtime checks in function header/footer (used in some simple/low-level functions)
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(IMGUI_DEBUG_PARANOID)
+#define IM_MSVC_RUNTIME_CHECKS_OFF __pragma(runtime_checks("",off)) __pragma(check_stack(off)) __pragma(strict_gs_check(push,off))
+#define IM_MSVC_RUNTIME_CHECKS_RESTORE __pragma(runtime_checks("",restore)) __pragma(check_stack()) __pragma(strict_gs_check(pop))
+#else
+#define IM_MSVC_RUNTIME_CHECKS_OFF
+#define IM_MSVC_RUNTIME_CHECKS_RESTORE
+#endif
+
+// Warnings
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
+#endif
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+#if __has_warning("-Wzero-as-null-pointer-constant")
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
+#endif
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] Forward declarations and basic types
+//-----------------------------------------------------------------------------
+
+// Forward declarations
+struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit()
+struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback)
+struct ImDrawData; // All draw command lists required to render the frame + pos/size coordinates to use for the projection matrix.
+struct ImDrawList; // A single draw command list (generally one per window, conceptually you may see this as a dynamic "mesh" builder)
+struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself)
+struct ImDrawListSplitter; // Helper to split a draw list into different layers which can be drawn into out of order, then flattened back.
+struct ImDrawVert; // A single vertex (pos + uv + col = 20 bytes by default. Override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT)
+struct ImFont; // Runtime data for a single font within a parent ImFontAtlas
+struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader
+struct ImFontBuilderIO; // Opaque interface to a font builder (stb_truetype or FreeType).
+struct ImFontConfig; // Configuration data when adding a font or merging fonts
+struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset)
+struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data
+struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using)
+struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h)
+struct ImGuiIO; // Main configuration and I/O between your application and ImGui
+struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
+struct ImGuiListClipper; // Helper to manually clip large list of items
+struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
+struct ImGuiPayload; // User data payload for drag and drop operations
+struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
+struct ImGuiStorage; // Helper for key->value storage
+struct ImGuiStyle; // Runtime data for styling/colors
+struct ImGuiTableSortSpecs; // Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
+struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table
+struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder)
+struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]")
+struct ImGuiViewport; // A Platform Window (always only one in 'master' branch), in the future may represent Platform Monitor
+
+// Enums/Flags (declared as int for compatibility with old C++, to allow using as flags without overhead, and to not pollute the top of this file)
+// - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists!
+// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
+// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
+typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling
+typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions
+typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type
+typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction
+typedef int ImGuiKey; // -> enum ImGuiKey_ // Enum: A key identifier (ImGui-side enum)
+typedef int ImGuiNavInput; // -> enum ImGuiNavInput_ // Enum: An input identifier for navigation
+typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle)
+typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor identifier
+typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A sorting direction (ascending or descending)
+typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling
+typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
+typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions
+typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance
+typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build
+typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags
+typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton()
+typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc.
+typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags
+typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo()
+typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload()
+typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused()
+typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
+typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
+typedef int ImGuiKeyModFlags; // -> enum ImGuiKeyModFlags_ // Flags: for io.KeyMods (Ctrl/Shift/Alt/Super)
+typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
+typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
+typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
+typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
+typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem()
+typedef int ImGuiTableFlags; // -> enum ImGuiTableFlags_ // Flags: For BeginTable()
+typedef int ImGuiTableColumnFlags; // -> enum ImGuiTableColumnFlags_// Flags: For TableSetupColumn()
+typedef int ImGuiTableRowFlags; // -> enum ImGuiTableRowFlags_ // Flags: For TableNextRow()
+typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader()
+typedef int ImGuiViewportFlags; // -> enum ImGuiViewportFlags_ // Flags: for ImGuiViewport
+typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild()
+
+// ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type]
+// - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file.
+// - This can be whatever to you want it to be! read the FAQ about ImTextureID for details.
+#ifndef ImTextureID
+typedef void* ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that)
+#endif
+
+// ImDrawIdx: vertex index. [Compile-time configurable type]
+// - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended).
+// - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file.
+#ifndef ImDrawIdx
+typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends)
+#endif
+
+// Scalar data types
+typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string)
+typedef signed char ImS8; // 8-bit signed integer
+typedef unsigned char ImU8; // 8-bit unsigned integer
+typedef signed short ImS16; // 16-bit signed integer
+typedef unsigned short ImU16; // 16-bit unsigned integer
+typedef signed int ImS32; // 32-bit signed integer == int
+typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors)
+#if defined(_MSC_VER) && !defined(__clang__)
+typedef signed __int64 ImS64; // 64-bit signed integer (pre and post C++11 with Visual Studio)
+typedef unsigned __int64 ImU64; // 64-bit unsigned integer (pre and post C++11 with Visual Studio)
+#elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100)
+#include <stdint.h>
+typedef int64_t ImS64; // 64-bit signed integer (pre C++11)
+typedef uint64_t ImU64; // 64-bit unsigned integer (pre C++11)
+#else
+typedef signed long long ImS64; // 64-bit signed integer (post C++11)
+typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11)
+#endif
+
+// Character types
+// (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display)
+typedef unsigned short ImWchar16; // A single decoded U16 character/code point. We encode them as multi bytes UTF-8 when used in strings.
+typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings.
+#ifdef IMGUI_USE_WCHAR32 // ImWchar [configurable type: override in imconfig.h with '#define IMGUI_USE_WCHAR32' to support Unicode planes 1-16]
+typedef ImWchar32 ImWchar;
+#else
+typedef ImWchar16 ImWchar;
+#endif
+
+// Callback and functions types
+typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText()
+typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints()
+typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()
+typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions()
+
+// ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type]
+// This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type.
+IM_MSVC_RUNTIME_CHECKS_OFF
+struct ImVec2
+{
+ float x, y;
+ ImVec2() { x = y = 0.0f; }
+ ImVec2(float _x, float _y) { x = _x; y = _y; }
+ float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine.
+ float& operator[] (size_t idx) { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine.
+#ifdef IM_VEC2_CLASS_EXTRA
+ IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2.
+#endif
+};
+
+// ImVec4: 4D vector used to store clipping rectangles, colors etc. [Compile-time configurable type]
+struct ImVec4
+{
+ float x, y, z, w;
+ ImVec4() { x = y = z = w = 0.0f; }
+ ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
+#ifdef IM_VEC4_CLASS_EXTRA
+ IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4.
+#endif
+};
+IM_MSVC_RUNTIME_CHECKS_RESTORE
+
+//-----------------------------------------------------------------------------
+// [SECTION] Dear ImGui end-user API functions
+// (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!)
+//-----------------------------------------------------------------------------
+
+namespace ImGui
+{
+ // Context creation and access
+ // - Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between contexts.
+ // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
+ // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for details.
+ IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL);
+ IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context
+ IMGUI_API ImGuiContext* GetCurrentContext();
+ IMGUI_API void SetCurrentContext(ImGuiContext* ctx);
+
+ // Main
+ IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags)
+ IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleCol(), PushStyleVar() to modify style mid-frame!
+ IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame().
+ IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all!
+ IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData().
+ IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render.
+
+ // Demo, Debug, Information
+ IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application!
+ IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc.
+ IMGUI_API void ShowStackToolWindow(bool* p_open = NULL); // create Stack Tool window. hover items with mouse to query information about the source of their unique ID.
+ IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information.
+ IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style)
+ IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles.
+ IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts.
+ IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls).
+ IMGUI_API const char* GetVersion(); // get the compiled version string e.g. "1.80 WIP" (essentially the value for IMGUI_VERSION from the compiled version of imgui.cpp)
+
+ // Styles
+ IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style (default)
+ IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font
+ IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // classic imgui style
+
+ // Windows
+ // - Begin() = push window to the stack and start appending to it. End() = pop window from the stack.
+ // - Passing 'bool* p_open != NULL' shows a window-closing widget in the upper-right corner of the window,
+ // which clicking will set the boolean to false when clicked.
+ // - You may append multiple times to the same window during the same frame by calling Begin()/End() pairs multiple times.
+ // Some information such as 'flags' or 'p_open' will only be considered by the first call to Begin().
+ // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting
+ // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value!
+ // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
+ // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function
+ // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
+ // - Note that the bottom of window stack always contains a window called "Debug".
+ IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);
+ IMGUI_API void End();
+
+ // Child Windows
+ // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child.
+ // - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400).
+ // - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window.
+ // Always call a matching EndChild() for each BeginChild() call, regardless of its return value.
+ // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
+ // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function
+ // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
+ IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
+ IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
+ IMGUI_API void EndChild();
+
+ // Windows Utilities
+ // - 'current window' = the window we are appending into while inside a Begin()/End() block. 'next window' = next window we will Begin() into.
+ IMGUI_API bool IsWindowAppearing();
+ IMGUI_API bool IsWindowCollapsed();
+ IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options.
+ IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ!
+ IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the current window, to append your own drawing primitives
+ IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList API)
+ IMGUI_API ImVec2 GetWindowSize(); // get current window size
+ IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x)
+ IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y)
+
+ // Window manipulation
+ // - Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin).
+ IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
+ IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()
+ IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints.
+ IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin()
+ IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin()
+ IMGUI_API void SetNextWindowFocus(); // set next window to be focused / top-most. call before Begin()
+ IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily override the Alpha component of ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground.
+ IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects.
+ IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects.
+ IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed().
+ IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus().
+ IMGUI_API void SetWindowFontScale(float scale); // [OBSOLETE] set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes().
+ IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position.
+ IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis.
+ IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state
+ IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus.
+
+ // Content region
+ // - Retrieve available space from a given point. GetContentRegionAvail() is frequently useful.
+ // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion)
+ IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos()
+ IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates
+ IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min for the full window (roughly (0,0)-Scroll), in window coordinates
+ IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max for the full window (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates
+
+ // Windows Scrolling
+ IMGUI_API float GetScrollX(); // get scrolling amount [0 .. GetScrollMaxX()]
+ IMGUI_API float GetScrollY(); // get scrolling amount [0 .. GetScrollMaxY()]
+ IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0 .. GetScrollMaxX()]
+ IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0 .. GetScrollMaxY()]
+ IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.x - WindowSize.x - DecorationsSize.x
+ IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.y - WindowSize.y - DecorationsSize.y
+ IMGUI_API void SetScrollHereX(float center_x_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_x_ratio=0.0: left, 0.5: center, 1.0: right. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead.
+ IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead.
+ IMGUI_API void SetScrollFromPosX(float local_x, float center_x_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position.
+ IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position.
+
+ // Parameters stacks (shared)
+ IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font
+ IMGUI_API void PopFont();
+ IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); // modify a style color. always use this if you modify the style after NewFrame().
+ IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col);
+ IMGUI_API void PopStyleColor(int count = 1);
+ IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame().
+ IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame().
+ IMGUI_API void PopStyleVar(int count = 1);
+ IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // == tab stop enable. Allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
+ IMGUI_API void PopAllowKeyboardFocus();
+ IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
+ IMGUI_API void PopButtonRepeat();
+
+ // Parameters stacks (current window)
+ IMGUI_API void PushItemWidth(float item_width); // push width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side).
+ IMGUI_API void PopItemWidth();
+ IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side)
+ IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions.
+ IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // push word-wrapping position for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space
+ IMGUI_API void PopTextWrapPos();
+
+ // Style read access
+ // - Use the style editor (ShowStyleEditor() function) to interactively see what the colors are)
+ IMGUI_API ImFont* GetFont(); // get current font
+ IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied
+ IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API
+ IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList
+ IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList
+ IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList
+ IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in.
+
+ // Cursor / Layout
+ // - By "cursor" we mean the current output position.
+ // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down.
+ // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceding widget.
+ // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API:
+ // Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos()
+ // Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions.
+ IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator.
+ IMGUI_API void SameLine(float offset_from_start_x=0.0f, float spacing=-1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates.
+ IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in an horizontal-layout context.
+ IMGUI_API void Spacing(); // add vertical spacing.
+ IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size. unlike InvisibleButton(), Dummy() won't take the mouse click or be navigable into.
+ IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by indent_w, or style.IndentSpacing if indent_w <= 0
+ IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by indent_w, or style.IndentSpacing if indent_w <= 0
+ IMGUI_API void BeginGroup(); // lock horizontal starting position
+ IMGUI_API void EndGroup(); // unlock horizontal starting position + capture the whole group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
+ IMGUI_API ImVec2 GetCursorPos(); // cursor position in window coordinates (relative to window position)
+ IMGUI_API float GetCursorPosX(); // (some functions are using window-relative coordinates, such as: GetCursorPos, GetCursorStartPos, GetContentRegionMax, GetWindowContentRegion* etc.
+ IMGUI_API float GetCursorPosY(); // other functions such as GetCursorScreenPos or everything in ImDrawList::
+ IMGUI_API void SetCursorPos(const ImVec2& local_pos); // are using the main, absolute coordinate system.
+ IMGUI_API void SetCursorPosX(float local_x); // GetWindowPos() + GetCursorPos() == GetCursorScreenPos() etc.)
+ IMGUI_API void SetCursorPosY(float local_y); //
+ IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position in window coordinates
+ IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates (useful to work with ImDrawList API). generally top-left == GetMainViewport()->Pos == (0,0) in single viewport mode, and bottom-right == GetMainViewport()->Pos+Size == io.DisplaySize in single-viewport mode.
+ IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates
+ IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item)
+ IMGUI_API float GetTextLineHeight(); // ~ FontSize
+ IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text)
+ IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2
+ IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets)
+
+ // ID stack/scopes
+ // Read the FAQ (docs/FAQ.md or http://dearimgui.org/faq) for more details about how ID are handled in dear imgui.
+ // - Those questions are answered and impacted by understanding of the ID stack system:
+ // - "Q: Why is my widget not reacting when I click on it?"
+ // - "Q: How can I have widgets with an empty label?"
+ // - "Q: How can I have multiple widgets with the same label?"
+ // - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely
+ // want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them.
+ // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others.
+ // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID,
+ // whereas "str_id" denote a string that is only used as an ID and not normally displayed.
+ IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string).
+ IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string).
+ IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer).
+ IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer).
+ IMGUI_API void PopID(); // pop from the ID stack.
+ IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself
+ IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end);
+ IMGUI_API ImGuiID GetID(const void* ptr_id);
+
+ // Widgets: Text
+ IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text.
+ IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text
+ IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1);
+ IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
+ IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor();
+ IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1);
+ IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize().
+ IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1);
+ IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets
+ IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text()
+ IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1);
+
+ // Widgets: Main
+ // - Most widgets return true when the value has been changed or when pressed/selected
+ // - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state.
+ IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0, 0)); // button
+ IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text
+ IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size, ImGuiButtonFlags flags = 0); // flexible button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.)
+ IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape
+ IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0));
+ IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding
+ IMGUI_API bool Checkbox(const char* label, bool* v);
+ IMGUI_API bool CheckboxFlags(const char* label, int* flags, int flags_value);
+ IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value);
+ IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; }
+ IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer
+ IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL);
+ IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses
+
+ // Widgets: Combo Box
+ // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items.
+ // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created.
+ IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
+ IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true!
+ IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1);
+ IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0"
+ IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1);
+
+ // Widgets: Drag Sliders
+ // - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp.
+ // - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x
+ // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
+ // - Format string may also be set to NULL or use the default format ("%f" or "%d").
+ // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision).
+ // - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used.
+ // - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum.
+ // - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them.
+ // - Legacy: Pre-1.78 there are DragXXX() function signatures that takes a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument.
+ // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361
+ IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound
+ IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound
+ IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL, ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
+ IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
+
+ // Widgets: Regular Sliders
+ // - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp.
+ // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc.
+ // - Format string may also be set to NULL or use the default format ("%f" or "%d").
+ // - Legacy: Pre-1.78 there are SliderXXX() function signatures that takes a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument.
+ // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361
+ IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display.
+ IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "%.0f deg", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0);
+ IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0);
+ IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0);
+ IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0);
+
+ // Widgets: Input with Keyboard
+ // - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp.
+ // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc.
+ IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
+ IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
+
+ // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.)
+ // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible.
+ // - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x
+ IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
+ IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0);
+ IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
+ IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);
+ IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed.
+ IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.
+
+ // Widgets: Trees
+ // - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents.
+ IMGUI_API bool TreeNode(const char* label);
+ IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet().
+ IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // "
+ IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2);
+ IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0);
+ IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);
+ IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3);
+ IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);
+ IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3);
+ IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired.
+ IMGUI_API void TreePush(const void* ptr_id = NULL); // "
+ IMGUI_API void TreePop(); // ~ Unindent()+PopId()
+ IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode
+ IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop().
+ IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header.
+ IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
+
+ // Widgets: Selectables
+ // - A selectable highlights when hovered, and can display another color when selected.
+ // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous.
+ IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height
+ IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper.
+
+ // Widgets: List Boxes
+ // - This is essentially a thin wrapper to using BeginChild/EndChild with some stylistic changes.
+ // - The BeginListBox()/EndListBox() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() or any items.
+ // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
+ // - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth
+ // - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items
+ IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region
+ IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true!
+ IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
+ IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1);
+
+ // Widgets: Data Plotting
+ // - Consider using ImPlot (https://github.com/epezent/implot) which is much better!
+ IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
+ IMGUI_API void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0));
+ IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
+ IMGUI_API void PlotHistogram(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0));
+
+ // Widgets: Value() Helpers.
+ // - Those are merely shortcut to calling Text() with a format string. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace)
+ IMGUI_API void Value(const char* prefix, bool b);
+ IMGUI_API void Value(const char* prefix, int v);
+ IMGUI_API void Value(const char* prefix, unsigned int v);
+ IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL);
+
+ // Widgets: Menus
+ // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar.
+ // - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it.
+ // - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it.
+ // - Not that MenuItem() keyboardshortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment.
+ IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window).
+ IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true!
+ IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar.
+ IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true!
+ IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true!
+ IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true!
+ IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated.
+ IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL
+
+ // Tooltips
+ // - Tooltip are windows following the mouse. They do not take focus away.
+ IMGUI_API void BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items).
+ IMGUI_API void EndTooltip();
+ IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip().
+ IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
+
+ // Popups, Modals
+ // - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
+ // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
+ // - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls.
+ // - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time.
+ // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
+ // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack.
+ // This is sometimes leading to confusing mistakes. May rework this in the future.
+
+ // Popups: begin/end functions
+ // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards. ImGuiWindowFlags are forwarded to the window.
+ // - BeginPopupModal(): block every interactions behind the window, cannot be closed by user, add a dimming background, has a title bar.
+ IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it.
+ IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it.
+ IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
+
+ // Popups: open/close functions
+ // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options.
+ // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
+ // - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually.
+ // - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options).
+ // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup().
+ // - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened.
+ IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!).
+ IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks
+ IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
+ IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.
+
+ // Popups: open+begin combined functions helpers
+ // - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking.
+ // - They are convenient to easily create context menus, hence the name.
+ // - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future.
+ // - IMPORTANT: we exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter, so if you add other flags remember to re-add the ImGuiPopupFlags_MouseButtonRight.
+ IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp!
+ IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window.
+ IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows).
+
+ // Popups: query functions
+ // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack.
+ // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack.
+ // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open.
+ IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open.
+
+ // Tables
+ // [BETA API] API may evolve slightly! If you use this, please update to the next version when it comes out!
+ // - Full-featured replacement for old Columns API.
+ // - See Demo->Tables for demo code.
+ // - See top of imgui_tables.cpp for general commentary.
+ // - See ImGuiTableFlags_ and ImGuiTableColumnFlags_ enums for a description of available flags.
+ // The typical call flow is:
+ // - 1. Call BeginTable().
+ // - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults.
+ // - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows.
+ // - 4. Optionally call TableHeadersRow() to submit a header row. Names are pulled from TableSetupColumn() data.
+ // - 5. Populate contents:
+ // - In most situations you can use TableNextRow() + TableSetColumnIndex(N) to start appending into a column.
+ // - If you are using tables as a sort of grid, where every columns is holding the same type of contents,
+ // you may prefer using TableNextColumn() instead of TableNextRow() + TableSetColumnIndex().
+ // TableNextColumn() will automatically wrap-around into the next row if needed.
+ // - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column!
+ // - Summary of possible call flow:
+ // --------------------------------------------------------------------------------------------------------
+ // TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK
+ // TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK
+ // TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row!
+ // TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear!
+ // --------------------------------------------------------------------------------------------------------
+ // - 5. Call EndTable()
+ IMGUI_API bool BeginTable(const char* str_id, int column, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f);
+ IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true!
+ IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row.
+ IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible.
+ IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
+
+ // Tables: Headers & Columns declaration
+ // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc.
+ // - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column.
+ // Headers are required to perform: reordering, sorting, and opening the context menu.
+ // The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
+ // - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
+ // some advanced use cases (e.g. adding custom widgets in header row).
+ // - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled.
+ IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
+ IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
+ IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu
+ IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
+
+ // Tables: Sorting
+ // - Call TableGetSortSpecs() to retrieve latest sort specs for the table. NULL when not sorting.
+ // - When 'SpecsDirty == true' you should sort your data. It will be true when sorting specs have changed
+ // since last call, or the first time. Make sure to set 'SpecsDirty = false' after sorting, else you may
+ // wastefully sort your data every frame!
+ // - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable().
+ IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
+
+ // Tables: Miscellaneous functions
+ // - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index.
+ IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable)
+ IMGUI_API int TableGetColumnIndex(); // return current column index.
+ IMGUI_API int TableGetRowIndex(); // return current row index.
+ IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
+ IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column.
+ IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change user accessible enabled/disabled state of a column. Set to false to hide the column. User can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
+ IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details.
+
+ // Legacy Columns API (prefer using Tables!)
+ // - You can also use SameLine(pos_x) to mimic simplified columns.
+ IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true);
+ IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished
+ IMGUI_API int GetColumnIndex(); // get current column index
+ IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column
+ IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column
+ IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f
+ IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column
+ IMGUI_API int GetColumnsCount();
+
+ // Tab Bars, Tabs
+ IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar
+ IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true!
+ IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0); // create a Tab. Returns true if the Tab is selected.
+ IMGUI_API void EndTabItem(); // only call EndTabItem() if BeginTabItem() returns true!
+ IMGUI_API bool TabItemButton(const char* label, ImGuiTabItemFlags flags = 0); // create a Tab behaving like a button. return true when clicked. cannot be selected in the tab bar.
+ IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name.
+
+ // Logging/Capture
+ // - All text output from the interface can be captured into tty/file/clipboard. By default, tree nodes are automatically opened during logging.
+ IMGUI_API void LogToTTY(int auto_open_depth = -1); // start logging to tty (stdout)
+ IMGUI_API void LogToFile(int auto_open_depth = -1, const char* filename = NULL); // start logging to file
+ IMGUI_API void LogToClipboard(int auto_open_depth = -1); // start logging to OS clipboard
+ IMGUI_API void LogFinish(); // stop logging (close file, etc.)
+ IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard
+ IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed)
+ IMGUI_API void LogTextV(const char* fmt, va_list args) IM_FMTLIST(1);
+
+ // Drag and Drop
+ // - On source items, call BeginDragDropSource(), if it returns true also call SetDragDropPayload() + EndDragDropSource().
+ // - On target candidates, call BeginDragDropTarget(), if it returns true also call AcceptDragDropPayload() + EndDragDropTarget().
+ // - If you stop calling BeginDragDropSource() the payload is preserved however it won't have a preview tooltip (we currently display a fallback "..." tooltip, see #1725)
+ // - An item can be both drag source and drop target.
+ IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call after submitting an item which may be dragged. when this return true, you can call SetDragDropPayload() + EndDragDropSource()
+ IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui.
+ IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true!
+ IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget()
+ IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released.
+ IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true!
+ IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. may return NULL. use ImGuiPayload::IsDataType() to test for the payload type.
+
+ // Disabling [BETA API]
+ // - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)
+ // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled)
+ // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it.
+ IMGUI_API void BeginDisabled(bool disabled = true);
+ IMGUI_API void EndDisabled();
+
+ // Clipping
+ // - Mouse hovering is affected by ImGui::PushClipRect() calls, unlike direct calls to ImDrawList::PushClipRect() which are render only.
+ IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect);
+ IMGUI_API void PopClipRect();
+
+ // Focus, Activation
+ // - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item"
+ IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window.
+ IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
+
+ // Item/Widgets Utilities and Query Functions
+ // - Most of the functions are referring to the previous Item that has been submitted.
+ // - See Demo Window under "Widgets->Querying Status" for an interactive visualization of most of those functions.
+ IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options.
+ IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false)
+ IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation?
+ IMGUI_API bool IsItemClicked(ImGuiMouseButton mouse_button = 0); // is the last item hovered and mouse clicked on? (**) == IsMouseClicked(mouse_button) && IsItemHovered()Important. (**) this it NOT equivalent to the behavior of e.g. Button(). Read comments in function definition.
+ IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling)
+ IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets.
+ IMGUI_API bool IsItemActivated(); // was the last item just made active (item was previously inactive).
+ IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing.
+ IMGUI_API bool IsItemDeactivatedAfterEdit(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item).
+ IMGUI_API bool IsItemToggledOpen(); // was the last item open state toggled? set by TreeNode().
+ IMGUI_API bool IsAnyItemHovered(); // is any item hovered?
+ IMGUI_API bool IsAnyItemActive(); // is any item active?
+ IMGUI_API bool IsAnyItemFocused(); // is any item focused?
+ IMGUI_API ImVec2 GetItemRectMin(); // get upper-left bounding rectangle of the last item (screen space)
+ IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space)
+ IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
+ IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.
+
+ // Viewports
+ // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
+ // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports.
+ // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode.
+ IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. This can never be NULL.
+
+ // Miscellaneous Utilities
+ IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped.
+ IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side.
+ IMGUI_API double GetTime(); // get global imgui time. incremented by io.DeltaTime every frame.
+ IMGUI_API int GetFrameCount(); // get global imgui frame count. incremented by 1 every frame.
+ IMGUI_API ImDrawList* GetBackgroundDrawList(); // this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents.
+ IMGUI_API ImDrawList* GetForegroundDrawList(); // this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents.
+ IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); // you may use this when creating your own ImDrawList instances.
+ IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.).
+ IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it)
+ IMGUI_API ImGuiStorage* GetStateStorage();
+ IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame
+ IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window)
+
+ // Text Utilities
+ IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
+
+ // Color Utilities
+ IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in);
+ IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in);
+ IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v);
+ IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b);
+
+ // Inputs Utilities: Keyboard
+ // - For 'int user_key_index' you can use your own indices/enums according to how your backend/engine stored them in io.KeysDown[].
+ // - We don't know the meaning of those value. You can use GetKeyIndex() to map a ImGuiKey_ value into the user index.
+ IMGUI_API int GetKeyIndex(ImGuiKey imgui_key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key]
+ IMGUI_API bool IsKeyDown(int user_key_index); // is key being held. == io.KeysDown[user_key_index].
+ IMGUI_API bool IsKeyPressed(int user_key_index, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate
+ IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down)?
+ IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate
+ IMGUI_API void CaptureKeyboardFromApp(bool want_capture_keyboard_value = true); // attention: misleading name! manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard_value"; after the next NewFrame() call.
+
+ // Inputs Utilities: Mouse
+ // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
+ // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
+ // - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold')
+ IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held?
+ IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down)
+ IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down)
+ IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? (note that a double-click will also report IsMouseClicked() == true)
+ IMGUI_API bool IsMouseTripleClicked(ImGuiMouseButton button); // did mouse button triple-clicked? (note that a triple-click will also report IsMouseClicked() == true)
+ IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
+ IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
+ IMGUI_API bool IsAnyMouseDown(); // is any mouse button held?
+ IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls
+ IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves)
+ IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold)
+ IMGUI_API ImVec2 GetMouseDragDelta(ImGuiMouseButton button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold)
+ IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); //
+ IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you
+ IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired cursor type
+ IMGUI_API void CaptureMouseFromApp(bool want_capture_mouse_value = true); // attention: misleading name! manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse_value;" after the next NewFrame() call.
+
+ // Clipboard Utilities
+ // - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard.
+ IMGUI_API const char* GetClipboardText();
+ IMGUI_API void SetClipboardText(const char* text);
+
+ // Settings/.Ini Utilities
+ // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini").
+ // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually.
+ // - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables).
+ IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename).
+ IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source.
+ IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext).
+ IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
+
+ // Debug Utilities
+ // - This is used by the IMGUI_CHECKVERSION() macro.
+ IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
+
+ // Memory Allocators
+ // - Those functions are not reliant on the current context.
+ // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
+ // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
+ IMGUI_API void SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data = NULL);
+ IMGUI_API void GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data);
+ IMGUI_API void* MemAlloc(size_t size);
+ IMGUI_API void MemFree(void* ptr);
+
+} // namespace ImGui
+
+//-----------------------------------------------------------------------------
+// [SECTION] Flags & Enumerations
+//-----------------------------------------------------------------------------
+
+// Flags for ImGui::Begin()
+enum ImGuiWindowFlags_
+{
+ ImGuiWindowFlags_None = 0,
+ ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar
+ ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip
+ ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window
+ ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically)
+ ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set.
+ ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it
+ ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame
+ ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f).
+ ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file
+ ImGuiWindowFlags_NoMouseInputs = 1 << 9, // Disable catching mouse, hovering test with pass through.
+ ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar
+ ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section.
+ ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state
+ ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programmatically giving it focus)
+ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y)
+ ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
+ ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)
+ ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window
+ ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB)
+ ImGuiWindowFlags_UnsavedDocument = 1 << 20, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
+ ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
+ ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse,
+ ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
+
+ // [Internal]
+ ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
+ ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild()
+ ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip()
+ ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup()
+ ImGuiWindowFlags_Modal = 1 << 27, // Don't use! For internal use by BeginPopupModal()
+ ImGuiWindowFlags_ChildMenu = 1 << 28 // Don't use! For internal use by BeginMenu()
+
+ // [Obsolete]
+ //ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // --> Set io.ConfigWindowsResizeFromEdges=true and make sure mouse cursors are supported by backend (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)
+};
+
+// Flags for ImGui::InputText()
+enum ImGuiInputTextFlags_
+{
+ ImGuiInputTextFlags_None = 0,
+ ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/
+ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef
+ ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z
+ ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs
+ ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus
+ ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function.
+ ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Callback on pressing TAB (for completion handling)
+ ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling)
+ ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer.
+ ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+ ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field
+ ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter).
+ ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally
+ ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode
+ ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode
+ ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*'
+ ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
+ ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
+ ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
+ ImGuiInputTextFlags_CallbackEdit = 1 << 19 // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
+
+ // Obsolete names (will be removed soon)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
+#endif
+};
+
+// Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*()
+enum ImGuiTreeNodeFlags_
+{
+ ImGuiTreeNodeFlags_None = 0,
+ ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
+ ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader)
+ ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one
+ ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
+ ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
+ ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
+ ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node
+ ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open.
+ ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
+ ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow
+ ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
+ ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line. In the future we may refactor the hit system to be front-to-back, allowing natural overlaps and then this can become the default.
+ ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area).
+ ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
+ //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
+ ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog
+};
+
+// Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions.
+// - To be backward compatible with older API which took an 'int mouse_button = 1' argument, we need to treat
+// small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags.
+// It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags.
+// - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0.
+// IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter
+// and want to another another flag, you need to pass in the ImGuiPopupFlags_MouseButtonRight flag.
+// - Multiple buttons currently cannot be combined/or-ed in those functions (we could allow it later).
+enum ImGuiPopupFlags_
+{
+ ImGuiPopupFlags_None = 0,
+ ImGuiPopupFlags_MouseButtonLeft = 0, // For BeginPopupContext*(): open on Left Mouse release. Guaranteed to always be == 0 (same as ImGuiMouseButton_Left)
+ ImGuiPopupFlags_MouseButtonRight = 1, // For BeginPopupContext*(): open on Right Mouse release. Guaranteed to always be == 1 (same as ImGuiMouseButton_Right)
+ ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle)
+ ImGuiPopupFlags_MouseButtonMask_ = 0x1F,
+ ImGuiPopupFlags_MouseButtonDefault_ = 1,
+ ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack
+ ImGuiPopupFlags_NoOpenOverItems = 1 << 6, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space
+ ImGuiPopupFlags_AnyPopupId = 1 << 7, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup.
+ ImGuiPopupFlags_AnyPopupLevel = 1 << 8, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level)
+ ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel
+};
+
+// Flags for ImGui::Selectable()
+enum ImGuiSelectableFlags_
+{
+ ImGuiSelectableFlags_None = 0,
+ ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window
+ ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column)
+ ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
+ ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text
+ ImGuiSelectableFlags_AllowItemOverlap = 1 << 4 // (WIP) Hit testing to allow subsequent widgets to overlap this one
+};
+
+// Flags for ImGui::BeginCombo()
+enum ImGuiComboFlags_
+{
+ ImGuiComboFlags_None = 0,
+ ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default
+ ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo()
+ ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default)
+ ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible
+ ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible
+ ImGuiComboFlags_NoArrowButton = 1 << 5, // Display on the preview box without the square arrow button
+ ImGuiComboFlags_NoPreview = 1 << 6, // Display only a square arrow button
+ ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest
+};
+
+// Flags for ImGui::BeginTabBar()
+enum ImGuiTabBarFlags_
+{
+ ImGuiTabBarFlags_None = 0,
+ ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list
+ ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear
+ ImGuiTabBarFlags_TabListPopupButton = 1 << 2, // Disable buttons to open the tab list popup
+ ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
+ ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, // Disable scrolling buttons (apply when fitting policy is ImGuiTabBarFlags_FittingPolicyScroll)
+ ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab
+ ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit
+ ImGuiTabBarFlags_FittingPolicyScroll = 1 << 7, // Add scroll buttons when tabs don't fit
+ ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll,
+ ImGuiTabBarFlags_FittingPolicyDefault_ = ImGuiTabBarFlags_FittingPolicyResizeDown
+};
+
+// Flags for ImGui::BeginTabItem()
+enum ImGuiTabItemFlags_
+{
+ ImGuiTabItemFlags_None = 0,
+ ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
+ ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem()
+ ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
+ ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
+ ImGuiTabItemFlags_NoTooltip = 1 << 4, // Disable tooltip for the given tab
+ ImGuiTabItemFlags_NoReorder = 1 << 5, // Disable reordering this tab or having another tab cross over this tab
+ ImGuiTabItemFlags_Leading = 1 << 6, // Enforce the tab position to the left of the tab bar (after the tab list popup button)
+ ImGuiTabItemFlags_Trailing = 1 << 7 // Enforce the tab position to the right of the tab bar (before the scrolling buttons)
+};
+
+// Flags for ImGui::BeginTable()
+// [BETA API] API may evolve slightly! If you use this, please update to the next version when it comes out!
+// - Important! Sizing policies have complex and subtle side effects, more so than you would expect.
+// Read comments/demos carefully + experiment with live demos to get acquainted with them.
+// - The DEFAULT sizing policies are:
+// - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize.
+// - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off.
+// - When ScrollX is off:
+// - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight.
+// - Columns sizing policy allowed: Stretch (default), Fixed/Auto.
+// - Fixed Columns will generally obtain their requested width (unless the table cannot fit them all).
+// - Stretch Columns will share the remaining width.
+// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors.
+// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
+// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing).
+// - When ScrollX is on:
+// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed
+// - Columns sizing policy allowed: Fixed/Auto mostly.
+// - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed.
+// - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop.
+// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable().
+// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again.
+// - Read on documentation at the top of imgui_tables.cpp for details.
+enum ImGuiTableFlags_
+{
+ // Features
+ ImGuiTableFlags_None = 0,
+ ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
+ ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
+ ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
+ ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
+ ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file.
+ ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
+ // Decorations
+ ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
+ ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
+ ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom.
+ ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns.
+ ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides.
+ ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders.
+ ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders.
+ ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders.
+ ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders.
+ ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders.
+ ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appears in Headers). -> May move to style
+ ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style
+ // Sizing Policy (read above for defaults)
+ ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width.
+ ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible.
+ ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths.
+ ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn().
+ // Sizing Extra Options
+ ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
+ ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.
+ ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable.
+ ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
+ // Clipping
+ ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().
+ // Padding
+ ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outer-most padding. Generally desirable if you have headers.
+ ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outer-most padding.
+ ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
+ // Scrolling
+ ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this create a child window, ScrollY is currently generally recommended when using ScrollX.
+ ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
+ // Sorting
+ ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
+ ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
+
+ // [Internal] Combinations and masks
+ ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame
+
+ // Obsolete names (will be removed soon)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ //, ImGuiTableFlags_ColumnsWidthFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_ColumnsWidthStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2020/12
+ //, ImGuiTableFlags_SizingPolicyFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingPolicyStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2021/01
+#endif
+};
+
+// Flags for ImGui::TableSetupColumn()
+enum ImGuiTableColumnFlags_
+{
+ // Input configuration flags
+ ImGuiTableColumnFlags_None = 0,
+ ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state)
+ ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column.
+ ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column.
+ ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).
+ ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).
+ ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
+ ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
+ ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
+ ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command).
+ ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).
+ ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction.
+ ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction.
+ ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit label for this column. Convenient for some small columns. Name will still appear in context menu.
+ ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width.
+ ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default).
+ ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column.
+ ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0).
+ ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored.
+
+ // Output status flags, read-only via TableGetColumnFlags()
+ ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.
+ ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling.
+ ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs
+ ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse
+
+ // [Internal] Combinations and masks
+ ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed,
+ ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable,
+ ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered,
+ ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30 // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge)
+
+ // Obsolete names (will be removed soon)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ //ImGuiTableColumnFlags_WidthAuto = ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, // Column will not stretch and keep resizing based on submitted contents.
+#endif
+};
+
+// Flags for ImGui::TableNextRow()
+enum ImGuiTableRowFlags_
+{
+ ImGuiTableRowFlags_None = 0,
+ ImGuiTableRowFlags_Headers = 1 << 0 // Identify header row (set default background color + width of its contents accounted different for auto column width)
+};
+
+// Enum for ImGui::TableSetBgColor()
+// Background colors are rendering in 3 layers:
+// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set.
+// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set.
+// - Layer 2: draw with CellBg color if set.
+// The purpose of the two row/columns layers is to let you decide if a background color changes should override or blend with the existing color.
+// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows.
+// If you set the color of RowBg0 target, your color will override the existing RowBg0 color.
+// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color.
+enum ImGuiTableBgTarget_
+{
+ ImGuiTableBgTarget_None = 0,
+ ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used)
+ ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking)
+ ImGuiTableBgTarget_CellBg = 3 // Set cell background color (top-most color)
+};
+
+// Flags for ImGui::IsWindowFocused()
+enum ImGuiFocusedFlags_
+{
+ ImGuiFocusedFlags_None = 0,
+ ImGuiFocusedFlags_ChildWindows = 1 << 0, // Return true if any children of the window is focused
+ ImGuiFocusedFlags_RootWindow = 1 << 1, // Test from root window (top most parent of the current hierarchy)
+ ImGuiFocusedFlags_AnyWindow = 1 << 2, // Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ!
+ ImGuiFocusedFlags_NoPopupHierarchy = 1 << 3, // Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow)
+ //ImGuiFocusedFlags_DockHierarchy = 1 << 4, // Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with _ChildWindows or _RootWindow)
+ ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows
+};
+
+// Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered()
+// Note: if you are trying to check whether your mouse should be dispatched to Dear ImGui or to your app, you should use 'io.WantCaptureMouse' instead! Please read the FAQ!
+// Note: windows with the ImGuiWindowFlags_NoInputs flag are ignored by IsWindowHovered() calls.
+enum ImGuiHoveredFlags_
+{
+ ImGuiHoveredFlags_None = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
+ ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered
+ ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy)
+ ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered
+ ImGuiHoveredFlags_NoPopupHierarchy = 1 << 3, // IsWindowHovered() only: Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow)
+ //ImGuiHoveredFlags_DockHierarchy = 1 << 4, // IsWindowHovered() only: Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with _ChildWindows or _RootWindow)
+ ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 5, // Return true even if a popup window is normally blocking access to this item/window
+ //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 6, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet.
+ ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
+ ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 8, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window
+ ImGuiHoveredFlags_AllowWhenDisabled = 1 << 9, // IsItemHovered() only: Return true even if the item is disabled
+ ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
+ ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows
+};
+
+// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload()
+enum ImGuiDragDropFlags_
+{
+ ImGuiDragDropFlags_None = 0,
+ // BeginDragDropSource() flags
+ ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior.
+ ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return false, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item.
+ ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item.
+ ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit.
+ ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of dear imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously.
+ ImGuiDragDropFlags_SourceAutoExpirePayload = 1 << 5, // Automatically expire the payload if the source cease to be submitted (otherwise payloads are persisting while being dragged)
+ // AcceptDragDropPayload() flags
+ ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered.
+ ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target.
+ ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site.
+ ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery.
+};
+
+// Standard Drag and Drop payload types. You can define you own payload types using short strings. Types starting with '_' are defined by Dear ImGui.
+#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type.
+#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type.
+
+// A primary data type
+enum ImGuiDataType_
+{
+ ImGuiDataType_S8, // signed char / char (with sensible compilers)
+ ImGuiDataType_U8, // unsigned char
+ ImGuiDataType_S16, // short
+ ImGuiDataType_U16, // unsigned short
+ ImGuiDataType_S32, // int
+ ImGuiDataType_U32, // unsigned int
+ ImGuiDataType_S64, // long long / __int64
+ ImGuiDataType_U64, // unsigned long long / unsigned __int64
+ ImGuiDataType_Float, // float
+ ImGuiDataType_Double, // double
+ ImGuiDataType_COUNT
+};
+
+// A cardinal direction
+enum ImGuiDir_
+{
+ ImGuiDir_None = -1,
+ ImGuiDir_Left = 0,
+ ImGuiDir_Right = 1,
+ ImGuiDir_Up = 2,
+ ImGuiDir_Down = 3,
+ ImGuiDir_COUNT
+};
+
+// A sorting direction
+enum ImGuiSortDirection_
+{
+ ImGuiSortDirection_None = 0,
+ ImGuiSortDirection_Ascending = 1, // Ascending = 0->9, A->Z etc.
+ ImGuiSortDirection_Descending = 2 // Descending = 9->0, Z->A etc.
+};
+
+// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array
+enum ImGuiKey_
+{
+ ImGuiKey_Tab,
+ ImGuiKey_LeftArrow,
+ ImGuiKey_RightArrow,
+ ImGuiKey_UpArrow,
+ ImGuiKey_DownArrow,
+ ImGuiKey_PageUp,
+ ImGuiKey_PageDown,
+ ImGuiKey_Home,
+ ImGuiKey_End,
+ ImGuiKey_Insert,
+ ImGuiKey_Delete,
+ ImGuiKey_Backspace,
+ ImGuiKey_Space,
+ ImGuiKey_Enter,
+ ImGuiKey_Escape,
+ ImGuiKey_KeyPadEnter,
+ ImGuiKey_A, // for text edit CTRL+A: select all
+ ImGuiKey_C, // for text edit CTRL+C: copy
+ ImGuiKey_V, // for text edit CTRL+V: paste
+ ImGuiKey_X, // for text edit CTRL+X: cut
+ ImGuiKey_Y, // for text edit CTRL+Y: redo
+ ImGuiKey_Z, // for text edit CTRL+Z: undo
+ ImGuiKey_COUNT
+};
+
+// To test io.KeyMods (which is a combination of individual fields io.KeyCtrl, io.KeyShift, io.KeyAlt set by user/backend)
+enum ImGuiKeyModFlags_
+{
+ ImGuiKeyModFlags_None = 0,
+ ImGuiKeyModFlags_Ctrl = 1 << 0,
+ ImGuiKeyModFlags_Shift = 1 << 1,
+ ImGuiKeyModFlags_Alt = 1 << 2,
+ ImGuiKeyModFlags_Super = 1 << 3
+};
+
+// Gamepad/Keyboard navigation
+// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDown[] + io.KeyMap[] arrays.
+// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Backend: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame().
+// Read instructions in imgui.cpp for more details. Download PNG/PSD at http://dearimgui.org/controls_sheets.
+enum ImGuiNavInput_
+{
+ // Gamepad Mapping
+ ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Cross (PS4), A (Xbox), A (Switch), Space (Keyboard)
+ ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Circle (PS4), B (Xbox), B (Switch), Escape (Keyboard)
+ ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard)
+ ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard)
+ ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard)
+ ImGuiNavInput_DpadRight, //
+ ImGuiNavInput_DpadUp, //
+ ImGuiNavInput_DpadDown, //
+ ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down
+ ImGuiNavInput_LStickRight, //
+ ImGuiNavInput_LStickUp, //
+ ImGuiNavInput_LStickDown, //
+ ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch)
+ ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch)
+ ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch)
+ ImGuiNavInput_TweakFast, // faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch)
+
+ // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them.
+ // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeysDown[] instead of io.NavInputs[].
+ ImGuiNavInput_KeyLeft_, // move left // = Arrow keys
+ ImGuiNavInput_KeyRight_, // move right
+ ImGuiNavInput_KeyUp_, // move up
+ ImGuiNavInput_KeyDown_, // move down
+ ImGuiNavInput_COUNT,
+ ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyLeft_
+};
+
+// Configuration flags stored in io.ConfigFlags. Set by user/application.
+enum ImGuiConfigFlags_
+{
+ ImGuiConfigFlags_None = 0,
+ ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeysDown[].
+ ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui backend to fill io.NavInputs[]. Backend also needs to set ImGuiBackendFlags_HasGamepad.
+ ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth.
+ ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set.
+ ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information set by the backend.
+ ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
+
+ // User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core Dear ImGui)
+ ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware.
+ ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse.
+};
+
+// Backend capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom backend.
+enum ImGuiBackendFlags_
+{
+ ImGuiBackendFlags_None = 0,
+ ImGuiBackendFlags_HasGamepad = 1 << 0, // Backend Platform supports gamepad and currently has one connected.
+ ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Backend Platform supports honoring GetMouseCursor() value to change the OS cursor shape.
+ ImGuiBackendFlags_HasSetMousePos = 1 << 2, // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set).
+ ImGuiBackendFlags_RendererHasVtxOffset = 1 << 3 // Backend Renderer supports ImDrawCmd::VtxOffset. This enables output of large meshes (64K+ vertices) while still using 16-bit indices.
+};
+
+// Enumeration for PushStyleColor() / PopStyleColor()
+enum ImGuiCol_
+{
+ ImGuiCol_Text,
+ ImGuiCol_TextDisabled,
+ ImGuiCol_WindowBg, // Background of normal windows
+ ImGuiCol_ChildBg, // Background of child windows
+ ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows
+ ImGuiCol_Border,
+ ImGuiCol_BorderShadow,
+ ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input
+ ImGuiCol_FrameBgHovered,
+ ImGuiCol_FrameBgActive,
+ ImGuiCol_TitleBg,
+ ImGuiCol_TitleBgActive,
+ ImGuiCol_TitleBgCollapsed,
+ ImGuiCol_MenuBarBg,
+ ImGuiCol_ScrollbarBg,
+ ImGuiCol_ScrollbarGrab,
+ ImGuiCol_ScrollbarGrabHovered,
+ ImGuiCol_ScrollbarGrabActive,
+ ImGuiCol_CheckMark,
+ ImGuiCol_SliderGrab,
+ ImGuiCol_SliderGrabActive,
+ ImGuiCol_Button,
+ ImGuiCol_ButtonHovered,
+ ImGuiCol_ButtonActive,
+ ImGuiCol_Header, // Header* colors are used for CollapsingHeader, TreeNode, Selectable, MenuItem
+ ImGuiCol_HeaderHovered,
+ ImGuiCol_HeaderActive,
+ ImGuiCol_Separator,
+ ImGuiCol_SeparatorHovered,
+ ImGuiCol_SeparatorActive,
+ ImGuiCol_ResizeGrip,
+ ImGuiCol_ResizeGripHovered,
+ ImGuiCol_ResizeGripActive,
+ ImGuiCol_Tab,
+ ImGuiCol_TabHovered,
+ ImGuiCol_TabActive,
+ ImGuiCol_TabUnfocused,
+ ImGuiCol_TabUnfocusedActive,
+ ImGuiCol_PlotLines,
+ ImGuiCol_PlotLinesHovered,
+ ImGuiCol_PlotHistogram,
+ ImGuiCol_PlotHistogramHovered,
+ ImGuiCol_TableHeaderBg, // Table header background
+ ImGuiCol_TableBorderStrong, // Table outer and header borders (prefer using Alpha=1.0 here)
+ ImGuiCol_TableBorderLight, // Table inner borders (prefer using Alpha=1.0 here)
+ ImGuiCol_TableRowBg, // Table row background (even rows)
+ ImGuiCol_TableRowBgAlt, // Table row background (odd rows)
+ ImGuiCol_TextSelectedBg,
+ ImGuiCol_DragDropTarget,
+ ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item
+ ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
+ ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active
+ ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active
+ ImGuiCol_COUNT
+};
+
+// Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure.
+// - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code.
+// During initialization or between frames, feel free to just poke into ImGuiStyle directly.
+// - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description.
+// In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
+// With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
+// - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type.
+enum ImGuiStyleVar_
+{
+ // Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions)
+ ImGuiStyleVar_Alpha, // float Alpha
+ ImGuiStyleVar_DisabledAlpha, // float DisabledAlpha
+ ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding
+ ImGuiStyleVar_WindowRounding, // float WindowRounding
+ ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize
+ ImGuiStyleVar_WindowMinSize, // ImVec2 WindowMinSize
+ ImGuiStyleVar_WindowTitleAlign, // ImVec2 WindowTitleAlign
+ ImGuiStyleVar_ChildRounding, // float ChildRounding
+ ImGuiStyleVar_ChildBorderSize, // float ChildBorderSize
+ ImGuiStyleVar_PopupRounding, // float PopupRounding
+ ImGuiStyleVar_PopupBorderSize, // float PopupBorderSize
+ ImGuiStyleVar_FramePadding, // ImVec2 FramePadding
+ ImGuiStyleVar_FrameRounding, // float FrameRounding
+ ImGuiStyleVar_FrameBorderSize, // float FrameBorderSize
+ ImGuiStyleVar_ItemSpacing, // ImVec2 ItemSpacing
+ ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ItemInnerSpacing
+ ImGuiStyleVar_IndentSpacing, // float IndentSpacing
+ ImGuiStyleVar_CellPadding, // ImVec2 CellPadding
+ ImGuiStyleVar_ScrollbarSize, // float ScrollbarSize
+ ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding
+ ImGuiStyleVar_GrabMinSize, // float GrabMinSize
+ ImGuiStyleVar_GrabRounding, // float GrabRounding
+ ImGuiStyleVar_TabRounding, // float TabRounding
+ ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
+ ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
+ ImGuiStyleVar_COUNT
+};
+
+// Flags for InvisibleButton() [extended in imgui_internal.h]
+enum ImGuiButtonFlags_
+{
+ ImGuiButtonFlags_None = 0,
+ ImGuiButtonFlags_MouseButtonLeft = 1 << 0, // React on left mouse button (default)
+ ImGuiButtonFlags_MouseButtonRight = 1 << 1, // React on right mouse button
+ ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
+
+ // [Internal]
+ ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle,
+ ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft
+};
+
+// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
+enum ImGuiColorEditFlags_
+{
+ ImGuiColorEditFlags_None = 0,
+ ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (will only read 3 components from the input pointer).
+ ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on color square.
+ ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview.
+ ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable color square preview next to the inputs. (e.g. to show only the inputs)
+ ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview color square).
+ ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview.
+ ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker).
+ ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead.
+ ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source.
+ ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default)
+
+ // User Options (right-click on widget to change some of them).
+ ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
+ ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque.
+ ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque.
+ ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
+ ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex.
+ ImGuiColorEditFlags_DisplayHSV = 1 << 21, // [Display] // "
+ ImGuiColorEditFlags_DisplayHex = 1 << 22, // [Display] // "
+ ImGuiColorEditFlags_Uint8 = 1 << 23, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255.
+ ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
+ ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [Picker] // ColorPicker: bar for Hue, rectangle for Sat/Value.
+ ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [Picker] // ColorPicker: wheel for Hue, triangle for Sat/Value.
+ ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format.
+ ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format.
+
+ // Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to
+ // override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup.
+ ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,
+
+ // [Internal] Masks
+ ImGuiColorEditFlags_DisplayMask_ = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex,
+ ImGuiColorEditFlags_DataTypeMask_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float,
+ ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar,
+ ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69]
+#endif
+};
+
+// Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
+// We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them.
+enum ImGuiSliderFlags_
+{
+ ImGuiSliderFlags_None = 0,
+ ImGuiSliderFlags_AlwaysClamp = 1 << 4, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
+ ImGuiSliderFlags_Logarithmic = 1 << 5, // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits.
+ ImGuiSliderFlags_NoRoundToFormat = 1 << 6, // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits)
+ ImGuiSliderFlags_NoInput = 1 << 7, // Disable CTRL+Click or Enter key allowing to input text directly into the widget
+ ImGuiSliderFlags_InvalidMask_ = 0x7000000F // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed.
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiSliderFlags_ClampOnInput = ImGuiSliderFlags_AlwaysClamp // [renamed in 1.79]
+#endif
+};
+
+// Identify a mouse button.
+// Those values are guaranteed to be stable and we frequently use 0/1 directly. Named enums provided for convenience.
+enum ImGuiMouseButton_
+{
+ ImGuiMouseButton_Left = 0,
+ ImGuiMouseButton_Right = 1,
+ ImGuiMouseButton_Middle = 2,
+ ImGuiMouseButton_COUNT = 5
+};
+
+// Enumeration for GetMouseCursor()
+// User code may request backend to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here
+enum ImGuiMouseCursor_
+{
+ ImGuiMouseCursor_None = -1,
+ ImGuiMouseCursor_Arrow = 0,
+ ImGuiMouseCursor_TextInput, // When hovering over InputText, etc.
+ ImGuiMouseCursor_ResizeAll, // (Unused by Dear ImGui functions)
+ ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border
+ ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column
+ ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window
+ ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window
+ ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks)
+ ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle.
+ ImGuiMouseCursor_COUNT
+};
+
+// Enumeration for ImGui::SetWindow***(), SetNextWindow***(), SetNextItem***() functions
+// Represent a condition.
+// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always.
+enum ImGuiCond_
+{
+ ImGuiCond_None = 0, // No condition (always set the variable), same as _Always
+ ImGuiCond_Always = 1 << 0, // No condition (always set the variable)
+ ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call will succeed)
+ ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file)
+ ImGuiCond_Appearing = 1 << 3 // Set the variable if the object/window is appearing after being hidden/inactive (or the first time)
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Helpers: Memory allocations macros, ImVector<>
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// IM_MALLOC(), IM_FREE(), IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE()
+// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
+// Defining a custom placement new() with a custom parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
+//-----------------------------------------------------------------------------
+
+struct ImNewWrapper {};
+inline void* operator new(size_t, ImNewWrapper, void* ptr) { return ptr; }
+inline void operator delete(void*, ImNewWrapper, void*) {} // This is only required so we can use the symmetrical new()
+#define IM_ALLOC(_SIZE) ImGui::MemAlloc(_SIZE)
+#define IM_FREE(_PTR) ImGui::MemFree(_PTR)
+#define IM_PLACEMENT_NEW(_PTR) new(ImNewWrapper(), _PTR)
+#define IM_NEW(_TYPE) new(ImNewWrapper(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE
+template<typename T> void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } }
+
+//-----------------------------------------------------------------------------
+// ImVector<>
+// Lightweight std::vector<>-like class to avoid dragging dependencies (also, some implementations of STL with debug enabled are absurdly slow, we bypass it so our code runs fast in debug).
+//-----------------------------------------------------------------------------
+// - You generally do NOT need to care or use this ever. But we need to make it available in imgui.h because some of our public structures are relying on it.
+// - We use std-like naming convention here, which is a little unusual for this codebase.
+// - Important: clear() frees memory, resize(0) keep the allocated buffer. We use resize(0) a lot to intentionally recycle allocated buffers across frames and amortize our costs.
+// - Important: our implementation does NOT call C++ constructors/destructors, we treat everything as raw data! This is intentional but be extra mindful of that,
+// Do NOT use this class as a std::vector replacement in your own code! Many of the structures used by dear imgui can be safely initialized by a zero-memset.
+//-----------------------------------------------------------------------------
+
+IM_MSVC_RUNTIME_CHECKS_OFF
+template<typename T>
+struct ImVector
+{
+ int Size;
+ int Capacity;
+ T* Data;
+
+ // Provide standard typedefs but we don't use them ourselves.
+ typedef T value_type;
+ typedef value_type* iterator;
+ typedef const value_type* const_iterator;
+
+ // Constructors, destructor
+ inline ImVector() { Size = Capacity = 0; Data = NULL; }
+ inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); }
+ inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
+ inline ~ImVector() { if (Data) IM_FREE(Data); } // Important: does not destruct anything
+
+ inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } // Important: does not destruct anything
+ inline void clear_delete() { for (int n = 0; n < Size; n++) IM_DELETE(Data[n]); clear(); } // Important: never called automatically! always explicit.
+ inline void clear_destruct() { for (int n = 0; n < Size; n++) Data[n].~T(); clear(); } // Important: never called automatically! always explicit.
+
+ inline bool empty() const { return Size == 0; }
+ inline int size() const { return Size; }
+ inline int size_in_bytes() const { return Size * (int)sizeof(T); }
+ inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); }
+ inline int capacity() const { return Capacity; }
+ inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
+ inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; }
+
+ inline T* begin() { return Data; }
+ inline const T* begin() const { return Data; }
+ inline T* end() { return Data + Size; }
+ inline const T* end() const { return Data + Size; }
+ inline T& front() { IM_ASSERT(Size > 0); return Data[0]; }
+ inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; }
+ inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; }
+ inline const T& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; }
+ inline void swap(ImVector<T>& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; T* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; }
+
+ inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity / 2) : 8; return new_capacity > sz ? new_capacity : sz; }
+ inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }
+ inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; }
+ inline void shrink(int new_size) { IM_ASSERT(new_size <= Size); Size = new_size; } // Resize a vector to a smaller size, guaranteed not to cause a reallocation
+ inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)IM_ALLOC((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); IM_FREE(Data); } Data = new_data; Capacity = new_capacity; }
+
+ // NB: It is illegal to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden.
+ inline void push_back(const T& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; }
+ inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
+ inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); }
+ inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
+ inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; }
+ inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
+ inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
+ inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; }
+ inline T* find(const T& v) { T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; }
+ inline const T* find(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; }
+ inline bool find_erase(const T& v) { const T* it = find(v); if (it < Data + Size) { erase(it); return true; } return false; }
+ inline bool find_erase_unsorted(const T& v) { const T* it = find(v); if (it < Data + Size) { erase_unsorted(it); return true; } return false; }
+ inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; return (int)off; }
+};
+IM_MSVC_RUNTIME_CHECKS_RESTORE
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiStyle
+//-----------------------------------------------------------------------------
+// You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame().
+// During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values,
+// and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors.
+//-----------------------------------------------------------------------------
+
+struct ImGuiStyle
+{
+ float Alpha; // Global alpha applies to everything in Dear ImGui.
+ float DisabledAlpha; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha.
+ ImVec2 WindowPadding; // Padding within a window.
+ float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
+ float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints().
+ ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
+ ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left.
+ float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows.
+ float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding)
+ float PopupBorderSize; // Thickness of border around popup/tooltip windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets).
+ float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets).
+ float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
+ ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines.
+ ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label).
+ ImVec2 CellPadding; // Padding within a table cell
+ ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
+ float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
+ float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
+ float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar.
+ float ScrollbarRounding; // Radius of grab corners for scrollbar.
+ float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.
+ float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
+ float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero.
+ float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
+ float TabBorderSize; // Thickness of border around tabs.
+ float TabMinWidthForCloseButton; // Minimum width for close button to appears on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected.
+ ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
+ ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
+ ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
+ ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
+ ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly!
+ float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later.
+ bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
+ bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering. Latched at the beginning of the frame (copied to ImDrawList).
+ bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList).
+ float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.
+ float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry.
+ ImVec4 Colors[ImGuiCol_COUNT];
+
+ IMGUI_API ImGuiStyle();
+ IMGUI_API void ScaleAllSizes(float scale_factor);
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiIO
+//-----------------------------------------------------------------------------
+// Communicate most settings and inputs/outputs to Dear ImGui using this structure.
+// Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage.
+//-----------------------------------------------------------------------------
+
+struct ImGuiIO
+{
+ //------------------------------------------------------------------
+ // Configuration (fill once) // Default value
+ //------------------------------------------------------------------
+
+ ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc.
+ ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend.
+ ImVec2 DisplaySize; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size)
+ float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds.
+ float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds.
+ const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions.
+ const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified).
+ float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
+ float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
+ float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
+ int KeyMap[ImGuiKey_COUNT]; // <unset> // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state.
+ float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
+ float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
+ void* UserData; // = NULL // Store your own data for retrieval by callbacks.
+
+ ImFontAtlas*Fonts; // <auto> // Font atlas: load, rasterize and pack one or more fonts into a single texture.
+ float FontGlobalScale; // = 1.0f // Global scale all fonts
+ bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel.
+ ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0].
+ ImVec2 DisplayFramebufferScale; // = (1, 1) // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale.
+
+ // Miscellaneous options
+ bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
+ bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
+ bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
+ bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
+ bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
+ bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
+ float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
+
+ //------------------------------------------------------------------
+ // Platform Functions
+ // (the imgui_impl_xxxx backend files are setting those up for you)
+ //------------------------------------------------------------------
+
+ // Optional: Platform/Renderer backend name (informational only! will be displayed in About Window) + User data for backend/wrappers to store their own stuff.
+ const char* BackendPlatformName; // = NULL
+ const char* BackendRendererName; // = NULL
+ void* BackendPlatformUserData; // = NULL // User data for platform backend
+ void* BackendRendererUserData; // = NULL // User data for renderer backend
+ void* BackendLanguageUserData; // = NULL // User data for non C++ programming language backend
+
+ // Optional: Access OS clipboard
+ // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures)
+ const char* (*GetClipboardTextFn)(void* user_data);
+ void (*SetClipboardTextFn)(void* user_data, const char* text);
+ void* ClipboardUserData;
+
+ // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows)
+ // (default to use native imm32 api on Windows)
+ void (*ImeSetInputScreenPosFn)(int x, int y);
+ void* ImeWindowHandle; // = NULL // (Windows) Set this to your HWND to get automatic IME cursor positioning.
+
+ //------------------------------------------------------------------
+ // Input - Fill before calling NewFrame()
+ //------------------------------------------------------------------
+
+ ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.)
+ bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API.
+ float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
+ float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all backends.
+ bool KeyCtrl; // Keyboard modifier pressed: Control
+ bool KeyShift; // Keyboard modifier pressed: Shift
+ bool KeyAlt; // Keyboard modifier pressed: Alt
+ bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows
+ bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys).
+ float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs. Cleared back to zero by EndFrame(). Keyboard keys will be auto-mapped and be written here by NewFrame().
+
+ // Functions
+ IMGUI_API void AddInputCharacter(unsigned int c); // Queue new character input
+ IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue new character input from an UTF-16 character, it can be a surrogate
+ IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue new characters input from an UTF-8 string
+ IMGUI_API void AddFocusEvent(bool focused); // Notifies Dear ImGui when hosting platform windows lose or gain input focus
+ IMGUI_API void ClearInputCharacters(); // [Internal] Clear the text input buffer manually
+ IMGUI_API void ClearInputKeys(); // [Internal] Release all keys
+
+ //------------------------------------------------------------------
+ // Output - Updated by NewFrame() or EndFrame()/Render()
+ // (when reading from the io.WantCaptureMouse, io.WantCaptureKeyboard flags to dispatch your inputs, it is
+ // generally easier and more correct to use their state BEFORE calling NewFrame(). See FAQ for details!)
+ //------------------------------------------------------------------
+
+ bool WantCaptureMouse; // Set when Dear ImGui will use mouse inputs, in this case do not dispatch them to your main game/application (either way, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.).
+ bool WantCaptureKeyboard; // Set when Dear ImGui will use keyboard inputs, in this case do not dispatch them to your main game/application (either way, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.).
+ bool WantTextInput; // Mobile/console: when set, you may display an on-screen keyboard. This is set by Dear ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active).
+ bool WantSetMousePos; // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled.
+ bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!
+ bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
+ bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
+ float Framerate; // Rough estimate of application framerate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames.
+ int MetricsRenderVertices; // Vertices output during last call to Render()
+ int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3
+ int MetricsRenderWindows; // Number of visible windows
+ int MetricsActiveWindows; // Number of active windows
+ int MetricsActiveAllocations; // Number of active allocations, updated by MemAlloc/MemFree based on current context. May be off if you have multiple imgui contexts.
+ ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta.
+
+ //------------------------------------------------------------------
+ // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
+ //------------------------------------------------------------------
+
+ bool WantCaptureMouseUnlessPopupClose;// Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
+ ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame()
+ ImGuiKeyModFlags KeyModsPrev; // Previous key mods
+ ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
+ ImVec2 MouseClickedPos[5]; // Position at time of clicking
+ double MouseClickedTime[5]; // Time of last click (used to figure out double-click)
+ bool MouseClicked[5]; // Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0)
+ bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2)
+ ImU16 MouseClickedCount[5]; // == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down
+ ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done.
+ bool MouseReleased[5]; // Mouse button went from Down to !Down
+ bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
+ bool MouseDownOwnedUnlessPopupClose[5];//Track if button was clicked inside a dear imgui window.
+ float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
+ float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
+ ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point
+ float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point
+ float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed)
+ float KeysDownDurationPrev[512]; // Previous duration the key has been down
+ float NavInputsDownDuration[ImGuiNavInput_COUNT];
+ float NavInputsDownDurationPrev[ImGuiNavInput_COUNT];
+ float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui.
+ bool AppFocusLost;
+ ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16
+ ImVector<ImWchar> InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper.
+
+ IMGUI_API ImGuiIO();
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Misc data structures
+//-----------------------------------------------------------------------------
+
+// Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used.
+// The callback function should return 0 by default.
+// Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details)
+// - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
+// - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration
+// - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB
+// - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows
+// - ImGuiInputTextFlags_CallbackCharFilter: Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+// - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow.
+struct ImGuiInputTextCallbackData
+{
+ ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
+ ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
+ void* UserData; // What user passed to InputText() // Read-only
+
+ // Arguments for the different callback events
+ // - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary.
+ // - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state.
+ ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0;
+ ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History]
+ char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
+ int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length()
+ int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1
+ bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always]
+ int CursorPos; // // Read-write // [Completion,History,Always]
+ int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection)
+ int SelectionEnd; // // Read-write // [Completion,History,Always]
+
+ // Helper functions for text manipulation.
+ // Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection.
+ IMGUI_API ImGuiInputTextCallbackData();
+ IMGUI_API void DeleteChars(int pos, int bytes_count);
+ IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL);
+ void SelectAll() { SelectionStart = 0; SelectionEnd = BufTextLen; }
+ void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; }
+ bool HasSelection() const { return SelectionStart != SelectionEnd; }
+};
+
+// Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin().
+// NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough.
+struct ImGuiSizeCallbackData
+{
+ void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints()
+ ImVec2 Pos; // Read-only. Window position, for reference.
+ ImVec2 CurrentSize; // Read-only. Current window size.
+ ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing.
+};
+
+// Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload()
+struct ImGuiPayload
+{
+ // Members
+ void* Data; // Data (copied and owned by dear imgui)
+ int DataSize; // Data size
+
+ // [Internal]
+ ImGuiID SourceId; // Source item id
+ ImGuiID SourceParentId; // Source parent id (if available)
+ int DataFrameCount; // Data timestamp
+ char DataType[32 + 1]; // Data type tag (short user-supplied string, 32 characters max)
+ bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets)
+ bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item.
+
+ ImGuiPayload() { Clear(); }
+ void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; }
+ bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; }
+ bool IsPreview() const { return Preview; }
+ bool IsDelivery() const { return Delivery; }
+};
+
+// Sorting specification for one column of a table (sizeof == 12 bytes)
+struct ImGuiTableColumnSortSpecs
+{
+ ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
+ ImS16 ColumnIndex; // Index of the column
+ ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
+ ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending (you can use this or SortSign, whichever is more convenient for your sort function)
+
+ ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); }
+};
+
+// Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
+// Obtained by calling TableGetSortSpecs().
+// When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time.
+// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame!
+struct ImGuiTableSortSpecs
+{
+ const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array.
+ int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled.
+ bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag.
+
+ ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, ImColor)
+//-----------------------------------------------------------------------------
+
+// Helper: Unicode defines
+#define IM_UNICODE_CODEPOINT_INVALID 0xFFFD // Invalid Unicode code point (standard value).
+#ifdef IMGUI_USE_WCHAR32
+#define IM_UNICODE_CODEPOINT_MAX 0x10FFFF // Maximum Unicode code point supported by this build.
+#else
+#define IM_UNICODE_CODEPOINT_MAX 0xFFFF // Maximum Unicode code point supported by this build.
+#endif
+
+// Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame.
+// Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame");
+struct ImGuiOnceUponAFrame
+{
+ ImGuiOnceUponAFrame() { RefFrame = -1; }
+ mutable int RefFrame;
+ operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; }
+};
+
+// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
+struct ImGuiTextFilter
+{
+ IMGUI_API ImGuiTextFilter(const char* default_filter = "");
+ IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build
+ IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const;
+ IMGUI_API void Build();
+ void Clear() { InputBuf[0] = 0; Build(); }
+ bool IsActive() const { return !Filters.empty(); }
+
+ // [Internal]
+ struct ImGuiTextRange
+ {
+ const char* b;
+ const char* e;
+
+ ImGuiTextRange() { b = e = NULL; }
+ ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; }
+ bool empty() const { return b == e; }
+ IMGUI_API void split(char separator, ImVector<ImGuiTextRange>* out) const;
+ };
+ char InputBuf[256];
+ ImVector<ImGuiTextRange>Filters;
+ int CountGrep;
+};
+
+// Helper: Growable text buffer for logging/accumulating text
+// (this could be called 'ImGuiTextBuilder' / 'ImGuiStringBuilder')
+struct ImGuiTextBuffer
+{
+ ImVector<char> Buf;
+ IMGUI_API static char EmptyString[1];
+
+ ImGuiTextBuffer() { }
+ inline char operator[](int i) const { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; }
+ const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; }
+ const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator
+ int size() const { return Buf.Size ? Buf.Size - 1 : 0; }
+ bool empty() const { return Buf.Size <= 1; }
+ void clear() { Buf.clear(); }
+ void reserve(int capacity) { Buf.reserve(capacity); }
+ const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; }
+ IMGUI_API void append(const char* str, const char* str_end = NULL);
+ IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2);
+ IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2);
+};
+
+// Helper: Key->Value storage
+// Typically you don't have to worry about this since a storage is held within each Window.
+// We use it to e.g. store collapse state for a tree (Int 0/1)
+// This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame)
+// You can use it as custom user storage for temporary values. Declare your own storage if, for example:
+// - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state).
+// - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient)
+// Types are NOT stored, so it is up to you to make sure your Key don't collide with different types.
+struct ImGuiStorage
+{
+ // [Internal]
+ struct ImGuiStoragePair
+ {
+ ImGuiID key;
+ union { int val_i; float val_f; void* val_p; };
+ ImGuiStoragePair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; }
+ ImGuiStoragePair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; }
+ ImGuiStoragePair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; }
+ };
+
+ ImVector<ImGuiStoragePair> Data;
+
+ // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N)
+ // - Set***() functions find pair, insertion on demand if missing.
+ // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair.
+ void Clear() { Data.clear(); }
+ IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const;
+ IMGUI_API void SetInt(ImGuiID key, int val);
+ IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const;
+ IMGUI_API void SetBool(ImGuiID key, bool val);
+ IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const;
+ IMGUI_API void SetFloat(ImGuiID key, float val);
+ IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL
+ IMGUI_API void SetVoidPtr(ImGuiID key, void* val);
+
+ // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set.
+ // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
+ // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct)
+ // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar;
+ IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0);
+ IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false);
+ IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f);
+ IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL);
+
+ // Use on your own storage if you know only integer are being stored (open/close all tree nodes)
+ IMGUI_API void SetAllInt(int val);
+
+ // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
+ IMGUI_API void BuildSortByKey();
+};
+
+// Helper: Manually clip large list of items.
+// If you have lots evenly spaced items and you have a random access to the list, you can perform coarse
+// clipping based on visibility to only submit items that are in view.
+// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.
+// (Dear ImGui already clip items based on their bounds but: it needs to first layout the item to do so, and generally
+// fetching/submitting your own data incurs additional cost. Coarse clipping using ImGuiListClipper allows you to easily
+// scale using lists with tens of thousands of items without a problem)
+// Usage:
+// ImGuiListClipper clipper;
+// clipper.Begin(1000); // We have 1000 elements, evenly spaced.
+// while (clipper.Step())
+// for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+// ImGui::Text("line number %d", i);
+// Generally what happens is:
+// - Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not.
+// - User code submit that one element.
+// - Clipper can measure the height of the first element
+// - Clipper calculate the actual range of elements to display based on the current clipping rectangle, position the cursor before the first visible element.
+// - User code submit visible elements.
+// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
+struct ImGuiListClipper
+{
+ int DisplayStart; // First item to display, updated by each call to Step()
+ int DisplayEnd; // End of items to display (exclusive)
+ int ItemsCount; // [Internal] Number of items
+ float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
+ float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
+ void* TempData; // [Internal] Internal data
+
+ // items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step)
+ // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
+ IMGUI_API ImGuiListClipper();
+ IMGUI_API ~ImGuiListClipper();
+ IMGUI_API void Begin(int items_count, float items_height = -1.0f);
+ IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
+ IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
+
+ // Call ForceDisplayRangeByIndices() before first call to Step() if you need a range of items to be displayed regardless of visibility.
+ IMGUI_API void ForceDisplayRangeByIndices(int item_min, int item_max); // item_max is exclusive e.g. use (42, 42+1) to make item 42 always visible BUT due to alignment/padding of certain items it is likely that an extra item may be included on either end of the display range.
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
+#endif
+};
+
+// Helpers macros to generate 32-bit encoded colors
+#ifdef IMGUI_USE_BGRA_PACKED_COLOR
+#define IM_COL32_R_SHIFT 16
+#define IM_COL32_G_SHIFT 8
+#define IM_COL32_B_SHIFT 0
+#define IM_COL32_A_SHIFT 24
+#define IM_COL32_A_MASK 0xFF000000
+#else
+#define IM_COL32_R_SHIFT 0
+#define IM_COL32_G_SHIFT 8
+#define IM_COL32_B_SHIFT 16
+#define IM_COL32_A_SHIFT 24
+#define IM_COL32_A_MASK 0xFF000000
+#endif
+#define IM_COL32(R,G,B,A) (((ImU32)(A)<<IM_COL32_A_SHIFT) | ((ImU32)(B)<<IM_COL32_B_SHIFT) | ((ImU32)(G)<<IM_COL32_G_SHIFT) | ((ImU32)(R)<<IM_COL32_R_SHIFT))
+#define IM_COL32_WHITE IM_COL32(255,255,255,255) // Opaque white = 0xFFFFFFFF
+#define IM_COL32_BLACK IM_COL32(0,0,0,255) // Opaque black
+#define IM_COL32_BLACK_TRANS IM_COL32(0,0,0,0) // Transparent black = 0x00000000
+
+// Helper: ImColor() implicitly converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
+// Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API.
+// **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. MAY OBSOLETE.
+// **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed.
+struct ImColor
+{
+ ImVec4 Value;
+
+ ImColor() { Value.x = Value.y = Value.z = Value.w = 0.0f; }
+ ImColor(int r, int g, int b, int a = 255) { float sc = 1.0f / 255.0f; Value.x = (float)r * sc; Value.y = (float)g * sc; Value.z = (float)b * sc; Value.w = (float)a * sc; }
+ ImColor(ImU32 rgba) { float sc = 1.0f / 255.0f; Value.x = (float)((rgba >> IM_COL32_R_SHIFT) & 0xFF) * sc; Value.y = (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * sc; Value.z = (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * sc; Value.w = (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * sc; }
+ ImColor(float r, float g, float b, float a = 1.0f) { Value.x = r; Value.y = g; Value.z = b; Value.w = a; }
+ ImColor(const ImVec4& col) { Value = col; }
+ inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); }
+ inline operator ImVec4() const { return Value; }
+
+ // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers.
+ inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; }
+ static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData)
+// Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList.
+//-----------------------------------------------------------------------------
+
+// The maximum line width to bake anti-aliased textures for. Build atlas with ImFontAtlasFlags_NoBakedLines to disable baking.
+#ifndef IM_DRAWLIST_TEX_LINES_WIDTH_MAX
+#define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (63)
+#endif
+
+// ImDrawCallback: Draw callbacks for advanced uses [configurable type: override in imconfig.h]
+// NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering,
+// you can poke into the draw list for that! Draw callback may be useful for example to:
+// A) Change your GPU render state,
+// B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc.
+// The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }'
+// If you want to override the signature of ImDrawCallback, you can simply use e.g. '#define ImDrawCallback MyDrawCallback' (in imconfig.h) + update rendering backend accordingly.
+#ifndef ImDrawCallback
+typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);
+#endif
+
+// Special Draw callback value to request renderer backend to reset the graphics/render state.
+// The renderer backend needs to handle this special value, otherwise it will crash trying to call a function at this address.
+// This is useful for example if you submitted callbacks which you know have altered the render state and you want it to be restored.
+// It is not done by default because they are many perfectly useful way of altering render state for imgui contents (e.g. changing shader/blending settings before an Image call).
+#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-1)
+
+// Typically, 1 command = 1 GPU draw call (unless command is a callback)
+// - VtxOffset/IdxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled,
+// those fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
+// Pre-1.71 backends will typically ignore the VtxOffset/IdxOffset fields.
+// - The ClipRect/TextureId/VtxOffset fields must be contiguous as we memcmp() them together (this is asserted for).
+struct ImDrawCmd
+{
+ ImVec4 ClipRect; // 4*4 // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates
+ ImTextureID TextureId; // 4-8 // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas.
+ unsigned int VtxOffset; // 4 // Start offset in vertex buffer. ImGuiBackendFlags_RendererHasVtxOffset: always 0, otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices.
+ unsigned int IdxOffset; // 4 // Start offset in index buffer. Always equal to sum of ElemCount drawn so far.
+ unsigned int ElemCount; // 4 // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[].
+ ImDrawCallback UserCallback; // 4-8 // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally.
+ void* UserCallbackData; // 4-8 // The draw callback code can access this.
+
+ ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
+
+ // Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature)
+ inline ImTextureID GetTexID() const { return TextureId; }
+};
+
+// Vertex layout
+#ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT
+struct ImDrawVert
+{
+ ImVec2 pos;
+ ImVec2 uv;
+ ImU32 col;
+};
+#else
+// You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h
+// The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine.
+// The type has to be described within the macro (you can either declare the struct or use a typedef). This is because ImVec2/ImU32 are likely not declared a the time you'd want to set your type up.
+// NOTE: IMGUI DOESN'T CLEAR THE STRUCTURE AND DOESN'T CALL A CONSTRUCTOR SO ANY CUSTOM FIELD WILL BE UNINITIALIZED. IF YOU ADD EXTRA FIELDS (SUCH AS A 'Z' COORDINATES) YOU WILL NEED TO CLEAR THEM DURING RENDER OR TO IGNORE THEM.
+IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT;
+#endif
+
+// [Internal] For use by ImDrawList
+struct ImDrawCmdHeader
+{
+ ImVec4 ClipRect;
+ ImTextureID TextureId;
+ unsigned int VtxOffset;
+};
+
+// [Internal] For use by ImDrawListSplitter
+struct ImDrawChannel
+{
+ ImVector<ImDrawCmd> _CmdBuffer;
+ ImVector<ImDrawIdx> _IdxBuffer;
+};
+
+
+// Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order.
+// This is used by the Columns/Tables API, so items of each column can be batched together in a same draw call.
+struct ImDrawListSplitter
+{
+ int _Current; // Current channel number (0)
+ int _Count; // Number of active channels (1+)
+ ImVector<ImDrawChannel> _Channels; // Draw channels (not resized down so _Count might be < Channels.Size)
+
+ inline ImDrawListSplitter() { memset(this, 0, sizeof(*this)); }
+ inline ~ImDrawListSplitter() { ClearFreeMemory(); }
+ inline void Clear() { _Current = 0; _Count = 1; } // Do not clear Channels[] so our allocations are reused next frame
+ IMGUI_API void ClearFreeMemory();
+ IMGUI_API void Split(ImDrawList* draw_list, int count);
+ IMGUI_API void Merge(ImDrawList* draw_list);
+ IMGUI_API void SetCurrentChannel(ImDrawList* draw_list, int channel_idx);
+};
+
+// Flags for ImDrawList functions
+// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused)
+enum ImDrawFlags_
+{
+ ImDrawFlags_None = 0,
+ ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
+ ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
+ ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
+ ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
+ ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
+ ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
+ ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
+ ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
+ ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
+ ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
+ ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
+ ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
+ ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone
+};
+
+// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
+// It is however possible to temporarily alter flags between calls to ImDrawList:: functions.
+enum ImDrawListFlags_
+{
+ ImDrawListFlags_None = 0,
+ ImDrawListFlags_AntiAliasedLines = 1 << 0, // Enable anti-aliased lines/borders (*2 the number of triangles for 1.0f wide line or lines thin enough to be drawn using textures, otherwise *3 the number of triangles)
+ ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering.
+ ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
+ ImDrawListFlags_AllowVtxOffset = 1 << 3 // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
+};
+
+// Draw command list
+// This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame,
+// all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering.
+// Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to
+// access the current window draw list and draw custom primitives.
+// You can interleave normal ImGui:: calls and adding primitives to the current draw list.
+// In single viewport mode, top-left is == GetMainViewport()->Pos (generally 0,0), bottom-right is == GetMainViewport()->Pos+Size (generally io.DisplaySize).
+// You are totally free to apply whatever transformation matrix to want to the data (depending on the use of the transformation you may want to apply it to ClipRect as well!)
+// Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects.
+struct ImDrawList
+{
+ // This is what you have to render
+ ImVector<ImDrawCmd> CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback.
+ ImVector<ImDrawIdx> IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those
+ ImVector<ImDrawVert> VtxBuffer; // Vertex buffer.
+ ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive.
+
+ // [Internal, used while building lists]
+ unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0.
+ const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context)
+ const char* _OwnerName; // Pointer to owner window's name for debugging
+ ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
+ ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much)
+ ImVector<ImVec4> _ClipRectStack; // [Internal]
+ ImVector<ImTextureID> _TextureIdStack; // [Internal]
+ ImVector<ImVec2> _Path; // [Internal] current path building
+ ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back().
+ ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
+ float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
+
+ // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui)
+ ImDrawList(const ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; }
+
+ ~ImDrawList() { _ClearFreeMemory(); }
+ IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
+ IMGUI_API void PushClipRectFullScreen();
+ IMGUI_API void PopClipRect();
+ IMGUI_API void PushTextureID(ImTextureID texture_id);
+ IMGUI_API void PopTextureID();
+ inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); }
+ inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); }
+
+ // Primitives
+ // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners.
+ // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred).
+ // In older versions (until Dear ImGui 1.77) the AddCircle functions defaulted to num_segments == 12.
+ // In future versions we will use textures to provide cheaper and higher-quality circles.
+ // Use AddNgon() and AddNgonFilled() functions if you need to guaranteed a specific number of sides.
+ IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f);
+ IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size)
+ IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
+ IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
+ IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f);
+ IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col);
+ IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f);
+ IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col);
+ IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f);
+ IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0);
+ IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f);
+ IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments);
+ IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
+ IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
+ IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
+ IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order.
+ IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points)
+ IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points)
+
+ // Image primitives
+ // - Read FAQ to understand what ImTextureID is.
+ // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle.
+ // - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture.
+ IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE);
+ IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE);
+ IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0);
+
+ // Stateful path API, add points then finish with PathFillConvex() or PathStroke()
+ inline void PathClear() { _Path.Size = 0; }
+ inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); }
+ inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
+ inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } // Note: Anti-aliased filling requires points to be in clockwise order.
+ inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
+ IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
+ IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
+ IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points)
+ IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points)
+ IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0);
+
+ // Advanced
+ IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles.
+ IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
+ IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer.
+
+ // Advanced: Channels
+ // - Use to split render into layers. By switching channels to can render out-of-order (e.g. submit FG primitives before BG primitives)
+ // - Use to minimize draw calls (e.g. if going back-and-forth between multiple clipping rectangles, prefer to append into separate channels then merge at the end)
+ // - FIXME-OBSOLETE: This API shouldn't have been in ImDrawList in the first place!
+ // Prefer using your own persistent instance of ImDrawListSplitter as you can stack them.
+ // Using the ImDrawList::ChannelsXXXX you cannot stack a split over another.
+ inline void ChannelsSplit(int count) { _Splitter.Split(this, count); }
+ inline void ChannelsMerge() { _Splitter.Merge(this); }
+ inline void ChannelsSetCurrent(int n) { _Splitter.SetCurrentChannel(this, n); }
+
+ // Advanced: Primitives allocations
+ // - We render triangles (three vertices)
+ // - All primitives needs to be reserved via PrimReserve() beforehand.
+ IMGUI_API void PrimReserve(int idx_count, int vtx_count);
+ IMGUI_API void PrimUnreserve(int idx_count, int vtx_count);
+ IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles)
+ IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col);
+ IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col);
+ inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; }
+ inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; }
+ inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); }
+ inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); }
+#endif
+
+ // [Internal helpers]
+ IMGUI_API void _ResetForNewFrame();
+ IMGUI_API void _ClearFreeMemory();
+ IMGUI_API void _PopUnusedDrawCmd();
+ IMGUI_API void _TryMergeDrawCmds();
+ IMGUI_API void _OnChangedClipRect();
+ IMGUI_API void _OnChangedTextureID();
+ IMGUI_API void _OnChangedVtxOffset();
+ IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const;
+ IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step);
+ IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments);
+};
+
+// All draw data to render a Dear ImGui frame
+// (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose,
+// as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList)
+struct ImDrawData
+{
+ bool Valid; // Only valid after Render() is called and before the next NewFrame() is called.
+ int CmdListsCount; // Number of ImDrawList* to render
+ int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size
+ int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size
+ ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here.
+ ImVec2 DisplayPos; // Top-left position of the viewport to render (== top-left of the orthogonal projection matrix to use) (== GetMainViewport()->Pos for the main viewport, == (0.0) in most single-viewport applications)
+ ImVec2 DisplaySize; // Size of the viewport to render (== GetMainViewport()->Size for the main viewport, == io.DisplaySize in most single-viewport applications)
+ ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display.
+
+ // Functions
+ ImDrawData() { Clear(); }
+ void Clear() { memset(this, 0, sizeof(*this)); } // The ImDrawList are owned by ImGuiContext!
+ IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
+ IMGUI_API void ScaleClipRects(const ImVec2& fb_scale); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than Dear ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont)
+//-----------------------------------------------------------------------------
+
+struct ImFontConfig
+{
+ void* FontData; // // TTF/OTF data
+ int FontDataSize; // // TTF/OTF data size
+ bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
+ int FontNo; // 0 // Index of font within TTF/OTF file
+ float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height).
+ int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal so you can reduce this to 2 to save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
+ int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis.
+ bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
+ ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
+ ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input.
+ const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
+ float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
+ float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs
+ bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
+ unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
+ float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
+ ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
+
+ // [Internal]
+ char Name[40]; // Name (strictly to ease debugging)
+ ImFont* DstFont;
+
+ IMGUI_API ImFontConfig();
+};
+
+// Hold rendering data for one glyph.
+// (Note: some language parsers may fail to convert the 31+1 bitfield members, in this case maybe drop store a single u32 or we can rework this)
+struct ImFontGlyph
+{
+ unsigned int Colored : 1; // Flag to indicate glyph is colored and should generally ignore tinting (make it usable with no shift on little-endian as this is used in loops)
+ unsigned int Visible : 1; // Flag to indicate glyph has no visible pixels (e.g. space). Allow early out when rendering.
+ unsigned int Codepoint : 30; // 0x0000..0x10FFFF
+ float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in)
+ float X0, Y0, X1, Y1; // Glyph corners
+ float U0, V0, U1, V1; // Texture coordinates
+};
+
+// Helper to build glyph ranges from text/string data. Feed your application strings/characters to it then call BuildRanges().
+// This is essentially a tightly packed of vector of 64k booleans = 8KB storage.
+struct ImFontGlyphRangesBuilder
+{
+ ImVector<ImU32> UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used)
+
+ ImFontGlyphRangesBuilder() { Clear(); }
+ inline void Clear() { int size_in_bytes = (IM_UNICODE_CODEPOINT_MAX + 1) / 8; UsedChars.resize(size_in_bytes / (int)sizeof(ImU32)); memset(UsedChars.Data, 0, (size_t)size_in_bytes); }
+ inline bool GetBit(size_t n) const { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array
+ inline void SetBit(size_t n) { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array
+ inline void AddChar(ImWchar c) { SetBit(c); } // Add character
+ IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added)
+ IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext
+ IMGUI_API void BuildRanges(ImVector<ImWchar>* out_ranges); // Output new ranges
+};
+
+// See ImFontAtlas::AddCustomRectXXX functions.
+struct ImFontAtlasCustomRect
+{
+ unsigned short Width, Height; // Input // Desired rectangle dimension
+ unsigned short X, Y; // Output // Packed position in Atlas
+ unsigned int GlyphID; // Input // For custom font glyphs only (ID < 0x110000)
+ float GlyphAdvanceX; // Input // For custom font glyphs only: glyph xadvance
+ ImVec2 GlyphOffset; // Input // For custom font glyphs only: glyph display offset
+ ImFont* Font; // Input // For custom font glyphs only: target font
+ ImFontAtlasCustomRect() { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; }
+ bool IsPacked() const { return X != 0xFFFF; }
+};
+
+// Flags for ImFontAtlas build
+enum ImFontAtlasFlags_
+{
+ ImFontAtlasFlags_None = 0,
+ ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two
+ ImFontAtlasFlags_NoMouseCursors = 1 << 1, // Don't build software mouse cursors into the atlas (save a little texture memory)
+ ImFontAtlasFlags_NoBakedLines = 1 << 2 // Don't build thick line textures into the atlas (save a little texture memory). The AntiAliasedLinesUseTex features uses them, otherwise they will be rendered using polygons (more expensive for CPU/GPU).
+};
+
+// Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding:
+// - One or more fonts.
+// - Custom graphics data needed to render the shapes needed by Dear ImGui.
+// - Mouse cursor shapes for software cursor rendering (unless setting 'Flags |= ImFontAtlasFlags_NoMouseCursors' in the font atlas).
+// It is the user-code responsibility to setup/build the atlas, then upload the pixel data into a texture accessible by your graphics api.
+// - Optionally, call any of the AddFont*** functions. If you don't call any, the default font embedded in the code will be loaded for you.
+// - Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
+// - Upload the pixels data into a texture within your graphics system (see imgui_impl_xxxx.cpp examples)
+// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
+// This value will be passed back to you during rendering to identify the texture. Read FAQ entry about ImTextureID for more details.
+// Common pitfalls:
+// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the
+// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
+// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
+// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
+// - Even though many functions are suffixed with "TTF", OTF data is supported just as well.
+// - This is an old API and it is currently awkward for those and and various other reasons! We will address them in the future!
+struct ImFontAtlas
+{
+ IMGUI_API ImFontAtlas();
+ IMGUI_API ~ImFontAtlas();
+ IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg);
+ IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL);
+ IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL);
+ IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
+ IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
+ IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
+ IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
+ IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory.
+ IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates).
+ IMGUI_API void Clear(); // Clear all input and output.
+
+ // Build atlas, retrieve pixel data.
+ // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
+ // The pitch is always = Width * BytesPerPixels (1 or 4)
+ // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into
+ // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste.
+ IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions.
+ IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel
+ IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel
+ bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't built texture but effectively we should check TexID != 0 except that would be backend dependent...
+ void SetTexID(ImTextureID id) { TexID = id; }
+
+ //-------------------------------------------
+ // Glyph Ranges
+ //-------------------------------------------
+
+ // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list)
+ // NB: Make sure that your string are UTF-8 and NOT in your local code page. In C++11, you can create UTF-8 string literal using the u8"Hello world" syntax. See FAQ for details.
+ // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data.
+ IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin
+ IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters
+ IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 2999 Ideographs
+ IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs
+ IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese
+ IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters
+ IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters
+ IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietnamese characters
+
+ //-------------------------------------------
+ // [BETA] Custom Rectangles/Glyphs API
+ //-------------------------------------------
+
+ // You can request arbitrary rectangles to be packed into the atlas, for your own purposes.
+ // - After calling Build(), you can query the rectangle position and render your pixels.
+ // - If you render colored output, set 'atlas->TexPixelsUseColors = true' as this may help some backends decide of prefered texture format.
+ // - You can also request your rectangles to be mapped as font glyph (given a font + Unicode point),
+ // so you can render e.g. custom colorful icons and use them as regular glyphs.
+ // - Read docs/FONTS.md for more details about using colorful icons.
+ // - Note: this API may be redesigned later in order to support multi-monitor varying DPI settings.
+ IMGUI_API int AddCustomRectRegular(int width, int height);
+ IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0, 0));
+ ImFontAtlasCustomRect* GetCustomRectByIndex(int index) { IM_ASSERT(index >= 0); return &CustomRects[index]; }
+
+ // [Internal]
+ IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const;
+ IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]);
+
+ //-------------------------------------------
+ // Members
+ //-------------------------------------------
+
+ ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_)
+ ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure.
+ int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
+ int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0.
+ bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert.
+
+ // [Internal]
+ // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you.
+ bool TexReady; // Set when texture was built matching current font input
+ bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format.
+ unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight
+ unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4
+ int TexWidth; // Texture width calculated during Build().
+ int TexHeight; // Texture height calculated during Build().
+ ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight)
+ ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel
+ ImVector<ImFont*> Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font.
+ ImVector<ImFontAtlasCustomRect> CustomRects; // Rectangles for packing custom texture data into the atlas.
+ ImVector<ImFontConfig> ConfigData; // Configuration data
+ ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines
+
+ // [Internal] Font builder
+ const ImFontBuilderIO* FontBuilderIO; // Opaque interface to a font builder (default to stb_truetype, can be changed to use FreeType by defining IMGUI_ENABLE_FREETYPE).
+ unsigned int FontBuilderFlags; // Shared flags (for all fonts) for custom font builder. THIS IS BUILD IMPLEMENTATION DEPENDENT. Per-font override is also available in ImFontConfig.
+
+ // [Internal] Packing data
+ int PackIdMouseCursors; // Custom texture rectangle ID for white pixel and mouse cursors
+ int PackIdLines; // Custom texture rectangle ID for baked anti-aliased lines
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+
+ //typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+
+#endif
+};
+
+// Font runtime data and rendering
+// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32().
+struct ImFont
+{
+ // Members: Hot ~20/24 bytes (for CalcTextSize)
+ ImVector<float> IndexAdvanceX; // 12-16 // out // // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this this info, and are often bottleneck in large UI).
+ float FallbackAdvanceX; // 4 // out // = FallbackGlyph->AdvanceX
+ float FontSize; // 4 // in // // Height of characters/line, set during loading (don't change after loading)
+
+ // Members: Hot ~28/40 bytes (for CalcTextSize + render loop)
+ ImVector<ImWchar> IndexLookup; // 12-16 // out // // Sparse. Index glyphs by Unicode code-point.
+ ImVector<ImFontGlyph> Glyphs; // 12-16 // out // // All glyphs.
+ const ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar)
+
+ // Members: Cold ~32/40 bytes
+ ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into
+ const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData
+ short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
+ ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found.
+ ImWchar EllipsisChar; // 2 // out // = '...' // Character used for ellipsis rendering.
+ ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found)
+ bool DirtyLookupTables; // 1 // out //
+ float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
+ float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
+ int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
+ ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
+
+ // Methods
+ IMGUI_API ImFont();
+ IMGUI_API ~ImFont();
+ IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const;
+ IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c) const;
+ float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; }
+ bool IsLoaded() const { return ContainerAtlas != NULL; }
+ const char* GetDebugName() const { return ConfigData ? ConfigData->Name : "<unknown>"; }
+
+ // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.
+ // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable.
+ IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8
+ IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const;
+ IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const;
+ IMGUI_API void RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const;
+
+ // [Internal] Don't use!
+ IMGUI_API void BuildLookupTable();
+ IMGUI_API void ClearOutputData();
+ IMGUI_API void GrowIndex(int new_size);
+ IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x);
+ IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built.
+ IMGUI_API void SetGlyphVisible(ImWchar c, bool visible);
+ IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Viewports
+//-----------------------------------------------------------------------------
+
+// Flags stored in ImGuiViewport::Flags, giving indications to the platform backends.
+enum ImGuiViewportFlags_
+{
+ ImGuiViewportFlags_None = 0,
+ ImGuiViewportFlags_IsPlatformWindow = 1 << 0, // Represent a Platform Window
+ ImGuiViewportFlags_IsPlatformMonitor = 1 << 1, // Represent a Platform Monitor (unused yet)
+ ImGuiViewportFlags_OwnedByApp = 1 << 2 // Platform Window: is created/managed by the application (rather than a dear imgui backend)
+};
+
+// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
+// - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports.
+// - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode.
+// - About Main Area vs Work Area:
+// - Main Area = entire viewport.
+// - Work Area = entire viewport minus sections used by main menu bars (for platform windows), or by task bar (for platform monitor).
+// - Windows are generally trying to stay within the Work Area of their host viewport.
+struct ImGuiViewport
+{
+ ImGuiViewportFlags Flags; // See ImGuiViewportFlags_
+ ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates)
+ ImVec2 Size; // Main Area: Size of the viewport.
+ ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos)
+ ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size)
+
+ ImGuiViewport() { memset(this, 0, sizeof(*this)); }
+
+ // Helpers
+ ImVec2 GetCenter() const { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }
+ ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Obsolete functions and types
+// (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details)
+// Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead.
+//-----------------------------------------------------------------------------
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+namespace ImGui
+{
+ // OBSOLETED in 1.86 (from November 2021)
+ IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper.
+ // OBSOLETED in 1.85 (from August 2021)
+ static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; }
+ // OBSOLETED in 1.81 (from February 2021)
+ IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items
+ static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); }
+ static inline void ListBoxFooter() { EndListBox(); }
+ // OBSOLETED in 1.79 (from August 2020)
+ static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry!
+ // OBSOLETED in 1.78 (from June 2020)
+ // Old drag/sliders functions that took a 'float power = 1.0' argument instead of flags.
+ // For shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`.
+ IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power);
+ IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power);
+ static inline bool DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power); }
+ static inline bool DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power); }
+ static inline bool DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power); }
+ static inline bool DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power); }
+ IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power);
+ IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format, float power);
+ static inline bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power); }
+ static inline bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); }
+ static inline bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); }
+ static inline bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); }
+ // OBSOLETED in 1.77 (from June 2020)
+ static inline bool BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mb, bool over_items) { return BeginPopupContextWindow(str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); }
+ // OBSOLETED in 1.72 (from April 2019)
+ static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); }
+ // OBSOLETED in 1.71 (from June 2019)
+ static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); }
+ // OBSOLETED in 1.70 (from May 2019)
+ static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }
+
+ // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
+ //static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // OBSOLETED in 1.69 (from Mar 2019)
+ //static inline void SetScrollHere(float ratio = 0.5f) { SetScrollHereY(ratio); } // OBSOLETED in 1.66 (from Nov 2018)
+ //static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); } // OBSOLETED in 1.63 (from Aug 2018)
+ //static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } // OBSOLETED in 1.60 (from Apr 2018)
+ //static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.60 (between Dec 2017 and Apr 2018)
+ //static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
+ //static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
+ //static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
+ //static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
+ //static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017)
+}
+
+// OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect()
+typedef ImDrawFlags ImDrawCornerFlags;
+enum ImDrawCornerFlags_
+{
+ ImDrawCornerFlags_None = ImDrawFlags_RoundCornersNone, // Was == 0 prior to 1.82, this is now == ImDrawFlags_RoundCornersNone which is != 0 and not implicit
+ ImDrawCornerFlags_TopLeft = ImDrawFlags_RoundCornersTopLeft, // Was == 0x01 (1 << 0) prior to 1.82. Order matches ImDrawFlags_NoRoundCorner* flag (we exploit this internally).
+ ImDrawCornerFlags_TopRight = ImDrawFlags_RoundCornersTopRight, // Was == 0x02 (1 << 1) prior to 1.82.
+ ImDrawCornerFlags_BotLeft = ImDrawFlags_RoundCornersBottomLeft, // Was == 0x04 (1 << 2) prior to 1.82.
+ ImDrawCornerFlags_BotRight = ImDrawFlags_RoundCornersBottomRight, // Was == 0x08 (1 << 3) prior to 1.82.
+ ImDrawCornerFlags_All = ImDrawFlags_RoundCornersAll, // Was == 0x0F prior to 1.82
+ ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight,
+ ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight,
+ ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft,
+ ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight
+};
+
+#endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+//-----------------------------------------------------------------------------
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h)
+#ifdef IMGUI_INCLUDE_IMGUI_USER_H
+#include "imgui_user.h"
+#endif
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imgui_demo.cpp b/Client/ThirdParty/imgui/imgui_demo.cpp
new file mode 100644
index 0000000..91bfb2d
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui_demo.cpp
@@ -0,0 +1,7849 @@
+// dear imgui, v1.86 WIP
+// (demo code)
+
+// Help:
+// - Read FAQ at http://dearimgui.org/faq
+// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
+// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
+// Read imgui.cpp for more details, documentation and comments.
+// Get the latest version at https://github.com/ocornut/imgui
+
+// Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
+// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other
+// coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available
+// debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone
+// in your team, likely leading you to poorer usage of the library.
+// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
+// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
+// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
+// In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
+// Thank you,
+// -Your beloved friend, imgui_demo.cpp (which you won't delete)
+
+// Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
+// In this demo code, we frequently use 'static' variables inside functions. A static variable persists across calls,
+// so it is essentially like a global variable but declared inside the scope of the function. We do this as a way to
+// gather code and data in the same place, to make the demo source code faster to read, faster to write, and smaller
+// in size. It also happens to be a convenient way of storing simple UI related information as long as your function
+// doesn't need to be reentrant or used in multiple threads. This might be a pattern you will want to use in your code,
+// but most of the real data you would be editing is likely going to be stored outside your functions.
+
+// The Demo code in this file is designed to be easy to copy-and-paste into your application!
+// Because of this:
+// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
+// - We try to declare static variables in the local scope, as close as possible to the code using them.
+// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
+// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
+// by imgui_internal.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
+// and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
+// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
+
+// Navigating this file:
+// - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
+// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
+
+/*
+
+Index of this file:
+
+// [SECTION] Forward Declarations, Helpers
+// [SECTION] Demo Window / ShowDemoWindow()
+// - sub section: ShowDemoWindowWidgets()
+// - sub section: ShowDemoWindowLayout()
+// - sub section: ShowDemoWindowPopups()
+// - sub section: ShowDemoWindowTables()
+// - sub section: ShowDemoWindowMisc()
+// [SECTION] About Window / ShowAboutWindow()
+// [SECTION] Style Editor / ShowStyleEditor()
+// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
+// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
+// [SECTION] Example App: Debug Log / ShowExampleAppLog()
+// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
+// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
+// [SECTION] Example App: Long Text / ShowExampleAppLongText()
+// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
+// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
+// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
+// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
+// [SECTION] Example App: Manipulating window titles / ShowExampleAppWindowTitles()
+// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
+// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DISABLE
+
+// System includes
+#include <ctype.h> // toupper
+#include <limits.h> // INT_MIN, INT_MAX
+#include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
+#include <stdio.h> // vsnprintf, sscanf, printf
+#include <stdlib.h> // NULL, malloc, free, atoi
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
+#endif
+
+// Clang/GCC warnings with -Weverything
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning: 'xx' is deprecated: The POSIX name for this.. // for strdup used in demo code (so user can copy & paste the code)
+#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type
+#pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal
+#pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
+#pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used // we define snprintf/vsnprintf on Windows so they are available, but not always used.
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
+#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
+#pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure)
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wmisleading-indentation" // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
+#endif
+
+// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
+#ifdef _WIN32
+#define IM_NEWLINE "\r\n"
+#else
+#define IM_NEWLINE "\n"
+#endif
+
+// Helpers
+#if defined(_MSC_VER) && !defined(snprintf)
+#define snprintf _snprintf
+#endif
+#if defined(_MSC_VER) && !defined(vsnprintf)
+#define vsnprintf _vsnprintf
+#endif
+
+// Format specifiers, printing 64-bit hasn't been decently standardized...
+// In a real application you should be using PRId64 and PRIu64 from <inttypes.h> (non-windows) and on Windows define them yourself.
+#ifdef _MSC_VER
+#define IM_PRId64 "I64d"
+#define IM_PRIu64 "I64u"
+#else
+#define IM_PRId64 "lld"
+#define IM_PRIu64 "llu"
+#endif
+
+// Helpers macros
+// We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
+// but making an exception here as those are largely simplifying code...
+// In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
+#define IM_MIN(A, B) (((A) < (B)) ? (A) : (B))
+#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B))
+#define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
+
+// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
+#ifndef IMGUI_CDECL
+#ifdef _MSC_VER
+#define IMGUI_CDECL __cdecl
+#else
+#define IMGUI_CDECL
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] Forward Declarations, Helpers
+//-----------------------------------------------------------------------------
+
+#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
+
+// Forward Declarations
+static void ShowExampleAppDocuments(bool* p_open);
+static void ShowExampleAppMainMenuBar();
+static void ShowExampleAppConsole(bool* p_open);
+static void ShowExampleAppLog(bool* p_open);
+static void ShowExampleAppLayout(bool* p_open);
+static void ShowExampleAppPropertyEditor(bool* p_open);
+static void ShowExampleAppLongText(bool* p_open);
+static void ShowExampleAppAutoResize(bool* p_open);
+static void ShowExampleAppConstrainedResize(bool* p_open);
+static void ShowExampleAppSimpleOverlay(bool* p_open);
+static void ShowExampleAppFullscreen(bool* p_open);
+static void ShowExampleAppWindowTitles(bool* p_open);
+static void ShowExampleAppCustomRendering(bool* p_open);
+static void ShowExampleMenuFile();
+
+// Helper to display a little (?) mark which shows a tooltip when hovered.
+// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
+static void HelpMarker(const char* desc)
+{
+ ImGui::TextDisabled("(?)");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
+ ImGui::TextUnformatted(desc);
+ ImGui::PopTextWrapPos();
+ ImGui::EndTooltip();
+ }
+}
+
+// Helper to wire demo markers located in code to a interactive browser
+typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section, void* user_data);
+extern ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback;
+extern void* GImGuiDemoMarkerCallbackUserData;
+ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback = NULL;
+void* GImGuiDemoMarkerCallbackUserData = NULL;
+#define IMGUI_DEMO_MARKER(section) do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0)
+
+// Helper to display basic user controls.
+void ImGui::ShowUserGuide()
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui::BulletText("Double-click on title bar to collapse window.");
+ ImGui::BulletText(
+ "Click and drag on lower corner to resize window\n"
+ "(double-click to auto fit window to its contents).");
+ ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
+ ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
+ ImGui::BulletText("CTRL+Tab to select a window.");
+ if (io.FontAllowUserScaling)
+ ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
+ ImGui::BulletText("While inputing text:\n");
+ ImGui::Indent();
+ ImGui::BulletText("CTRL+Left/Right to word jump.");
+ ImGui::BulletText("CTRL+A or double-click to select all.");
+ ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
+ ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
+ ImGui::BulletText("ESCAPE to revert.");
+ ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
+ ImGui::Unindent();
+ ImGui::BulletText("With keyboard navigation enabled:");
+ ImGui::Indent();
+ ImGui::BulletText("Arrow keys to navigate.");
+ ImGui::BulletText("Space to activate a widget.");
+ ImGui::BulletText("Return to input text into a widget.");
+ ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window.");
+ ImGui::BulletText("Alt to jump to the menu layer of a window.");
+ ImGui::Unindent();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Demo Window / ShowDemoWindow()
+//-----------------------------------------------------------------------------
+// - ShowDemoWindowWidgets()
+// - ShowDemoWindowLayout()
+// - ShowDemoWindowPopups()
+// - ShowDemoWindowTables()
+// - ShowDemoWindowColumns()
+// - ShowDemoWindowMisc()
+//-----------------------------------------------------------------------------
+
+// We split the contents of the big ShowDemoWindow() function into smaller functions
+// (because the link time of very large functions grow non-linearly)
+static void ShowDemoWindowWidgets();
+static void ShowDemoWindowLayout();
+static void ShowDemoWindowPopups();
+static void ShowDemoWindowTables();
+static void ShowDemoWindowColumns();
+static void ShowDemoWindowMisc();
+
+// Demonstrate most Dear ImGui features (this is big function!)
+// You may execute this function to experiment with the UI and understand what it does.
+// You may then search for keywords in the code when you are interested by a specific feature.
+void ImGui::ShowDemoWindow(bool* p_open)
+{
+ // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
+ // Most ImGui functions would normally just crash if the context is missing.
+ IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing dear imgui context. Refer to examples app!");
+
+ // Examples Apps (accessible from the "Examples" menu)
+ static bool show_app_main_menu_bar = false;
+ static bool show_app_documents = false;
+
+ static bool show_app_console = false;
+ static bool show_app_log = false;
+ static bool show_app_layout = false;
+ static bool show_app_property_editor = false;
+ static bool show_app_long_text = false;
+ static bool show_app_auto_resize = false;
+ static bool show_app_constrained_resize = false;
+ static bool show_app_simple_overlay = false;
+ static bool show_app_fullscreen = false;
+ static bool show_app_window_titles = false;
+ static bool show_app_custom_rendering = false;
+
+ if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
+ if (show_app_documents) ShowExampleAppDocuments(&show_app_documents);
+
+ if (show_app_console) ShowExampleAppConsole(&show_app_console);
+ if (show_app_log) ShowExampleAppLog(&show_app_log);
+ if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
+ if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
+ if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
+ if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
+ if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
+ if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
+ if (show_app_fullscreen) ShowExampleAppFullscreen(&show_app_fullscreen);
+ if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles);
+ if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
+
+ // Dear ImGui Apps (accessible from the "Tools" menu)
+ static bool show_app_metrics = false;
+ static bool show_app_stack_tool = false;
+ static bool show_app_style_editor = false;
+ static bool show_app_about = false;
+
+ if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); }
+ if (show_app_stack_tool) { ImGui::ShowStackToolWindow(&show_app_stack_tool); }
+ if (show_app_about) { ImGui::ShowAboutWindow(&show_app_about); }
+ if (show_app_style_editor)
+ {
+ ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor);
+ ImGui::ShowStyleEditor();
+ ImGui::End();
+ }
+
+ // Demonstrate the various window flags. Typically you would just use the default!
+ static bool no_titlebar = false;
+ static bool no_scrollbar = false;
+ static bool no_menu = false;
+ static bool no_move = false;
+ static bool no_resize = false;
+ static bool no_collapse = false;
+ static bool no_close = false;
+ static bool no_nav = false;
+ static bool no_background = false;
+ static bool no_bring_to_front = false;
+ static bool unsaved_document = false;
+
+ ImGuiWindowFlags window_flags = 0;
+ if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
+ if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
+ if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
+ if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
+ if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
+ if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
+ if (no_nav) window_flags |= ImGuiWindowFlags_NoNav;
+ if (no_background) window_flags |= ImGuiWindowFlags_NoBackground;
+ if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
+ if (unsaved_document) window_flags |= ImGuiWindowFlags_UnsavedDocument;
+ if (no_close) p_open = NULL; // Don't pass our bool* to Begin
+
+ // We specify a default position/size in case there's no data in the .ini file.
+ // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
+ const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
+ ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
+
+ // Main body of the Demo window starts here.
+ if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
+ {
+ // Early out if the window is collapsed, as an optimization.
+ ImGui::End();
+ return;
+ }
+
+ // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
+
+ // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
+ //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);
+
+ // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
+ ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
+
+ // Menu Bar
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("Menu"))
+ {
+ IMGUI_DEMO_MARKER("Menu/File");
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Examples"))
+ {
+ IMGUI_DEMO_MARKER("Menu/Examples");
+ ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
+ ImGui::MenuItem("Console", NULL, &show_app_console);
+ ImGui::MenuItem("Log", NULL, &show_app_log);
+ ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
+ ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
+ ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
+ ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
+ ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
+ ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
+ ImGui::MenuItem("Fullscreen window", NULL, &show_app_fullscreen);
+ ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
+ ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
+ ImGui::MenuItem("Documents", NULL, &show_app_documents);
+ ImGui::EndMenu();
+ }
+ //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar!
+ if (ImGui::BeginMenu("Tools"))
+ {
+ IMGUI_DEMO_MARKER("Menu/Tools");
+#ifndef IMGUI_DISABLE_METRICS_WINDOW
+ ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics);
+ ImGui::MenuItem("Stack Tool", NULL, &show_app_stack_tool);
+#endif
+ ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
+ ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+
+ ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
+ ImGui::Spacing();
+
+ IMGUI_DEMO_MARKER("Help");
+ if (ImGui::CollapsingHeader("Help"))
+ {
+ ImGui::Text("ABOUT THIS DEMO:");
+ ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
+ ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
+ ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
+ "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
+ ImGui::Separator();
+
+ ImGui::Text("PROGRAMMER GUIDE:");
+ ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
+ ImGui::BulletText("See comments in imgui.cpp.");
+ ImGui::BulletText("See example applications in the examples/ folder.");
+ ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/");
+ ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
+ ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
+ ImGui::Separator();
+
+ ImGui::Text("USER GUIDE:");
+ ImGui::ShowUserGuide();
+ }
+
+ IMGUI_DEMO_MARKER("Configuration");
+ if (ImGui::CollapsingHeader("Configuration"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+
+ if (ImGui::TreeNode("Configuration##2"))
+ {
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
+ ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
+ ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
+ ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
+ ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
+ ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
+ {
+ // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
+ if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
+ {
+ ImGui::SameLine();
+ ImGui::Text("<<PRESS SPACE TO DISABLE>>");
+ }
+ if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
+ io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
+ }
+ ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
+ ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
+ ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
+ ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)");
+ ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
+ ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
+ ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
+ ImGui::SameLine(); HelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
+ ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
+ ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
+ ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
+ ImGui::Text("Also see Style->Rendering for rendering options.");
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+
+ IMGUI_DEMO_MARKER("Configuration/Backend Flags");
+ if (ImGui::TreeNode("Backend Flags"))
+ {
+ HelpMarker(
+ "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
+ "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
+
+ // Make a local copy to avoid modifying actual backend flags.
+ ImGuiBackendFlags backend_flags = io.BackendFlags;
+ ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", &backend_flags, ImGuiBackendFlags_HasGamepad);
+ ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &backend_flags, ImGuiBackendFlags_HasMouseCursors);
+ ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", &backend_flags, ImGuiBackendFlags_HasSetMousePos);
+ ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+
+ IMGUI_DEMO_MARKER("Configuration/Style");
+ if (ImGui::TreeNode("Style"))
+ {
+ HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
+ ImGui::ShowStyleEditor();
+ ImGui::TreePop();
+ ImGui::Separator();
+ }
+
+ IMGUI_DEMO_MARKER("Configuration/Capture, Logging");
+ if (ImGui::TreeNode("Capture/Logging"))
+ {
+ HelpMarker(
+ "The logging API redirects all text output so you can easily capture the content of "
+ "a window or a block. Tree nodes can be automatically expanded.\n"
+ "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
+ ImGui::LogButtons();
+
+ HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.");
+ if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
+ {
+ ImGui::LogToClipboard();
+ ImGui::LogText("Hello, world!");
+ ImGui::LogFinish();
+ }
+ ImGui::TreePop();
+ }
+ }
+
+ IMGUI_DEMO_MARKER("Window options");
+ if (ImGui::CollapsingHeader("Window options"))
+ {
+ if (ImGui::BeginTable("split", 3))
+ {
+ ImGui::TableNextColumn(); ImGui::Checkbox("No titlebar", &no_titlebar);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No scrollbar", &no_scrollbar);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No menu", &no_menu);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No move", &no_move);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No resize", &no_resize);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No collapse", &no_collapse);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No close", &no_close);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background);
+ ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front);
+ ImGui::TableNextColumn(); ImGui::Checkbox("Unsaved document", &unsaved_document);
+ ImGui::EndTable();
+ }
+ }
+
+ // All demo contents
+ ShowDemoWindowWidgets();
+ ShowDemoWindowLayout();
+ ShowDemoWindowPopups();
+ ShowDemoWindowTables();
+ ShowDemoWindowMisc();
+
+ // End of ShowDemoWindow()
+ ImGui::PopItemWidth();
+ ImGui::End();
+}
+
+static void ShowDemoWindowWidgets()
+{
+ IMGUI_DEMO_MARKER("Widgets");
+ if (!ImGui::CollapsingHeader("Widgets"))
+ return;
+
+ static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom
+ if (disable_all)
+ ImGui::BeginDisabled();
+
+ IMGUI_DEMO_MARKER("Widgets/Basic");
+ if (ImGui::TreeNode("Basic"))
+ {
+ IMGUI_DEMO_MARKER("Widgets/Basic/Button");
+ static int clicked = 0;
+ if (ImGui::Button("Button"))
+ clicked++;
+ if (clicked & 1)
+ {
+ ImGui::SameLine();
+ ImGui::Text("Thanks for clicking me!");
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Basic/Checkbox");
+ static bool check = true;
+ ImGui::Checkbox("checkbox", &check);
+
+ IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton");
+ static int e = 0;
+ ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
+ ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
+ ImGui::RadioButton("radio c", &e, 2);
+
+ // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
+ IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Colored)");
+ for (int i = 0; i < 7; i++)
+ {
+ if (i > 0)
+ ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
+ ImGui::Button("Click");
+ ImGui::PopStyleColor(3);
+ ImGui::PopID();
+ }
+
+ // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
+ // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
+ // See 'Demo->Layout->Text Baseline Alignment' for details.
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("Hold to repeat:");
+ ImGui::SameLine();
+
+ // Arrow buttons with Repeater
+ IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)");
+ static int counter = 0;
+ float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
+ ImGui::PushButtonRepeat(true);
+ if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
+ ImGui::SameLine(0.0f, spacing);
+ if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
+ ImGui::PopButtonRepeat();
+ ImGui::SameLine();
+ ImGui::Text("%d", counter);
+
+ IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
+ ImGui::Text("Hover over me");
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("I am a tooltip");
+
+ ImGui::SameLine();
+ ImGui::Text("- or me");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::Text("I am a fancy tooltip");
+ static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
+ ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
+ ImGui::EndTooltip();
+ }
+
+ ImGui::Separator();
+ ImGui::LabelText("label", "Value");
+
+ {
+ // Using the _simplified_ one-liner Combo() api here
+ // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
+ IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
+ static int item_current = 0;
+ ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
+ ImGui::SameLine(); HelpMarker(
+ "Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
+ }
+
+ {
+ // To wire InputText() with std::string or any other custom string type,
+ // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
+ IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
+ static char str0[128] = "Hello, world!";
+ ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
+ ImGui::SameLine(); HelpMarker(
+ "USER:\n"
+ "Hold SHIFT or use mouse to select text.\n"
+ "CTRL+Left/Right to word jump.\n"
+ "CTRL+A or double-click to select all.\n"
+ "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
+ "CTRL+Z,CTRL+Y undo/redo.\n"
+ "ESCAPE to revert.\n\n"
+ "PROGRAMMER:\n"
+ "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
+ "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
+ "in imgui_demo.cpp).");
+
+ static char str1[128] = "";
+ ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
+
+ IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
+ static int i0 = 123;
+ ImGui::InputInt("input int", &i0);
+ ImGui::SameLine(); HelpMarker(
+ "You can apply arithmetic operators +,*,/ on numerical values.\n"
+ " e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
+ "Use +- to subtract.");
+
+ static float f0 = 0.001f;
+ ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
+
+ static double d0 = 999999.00000001;
+ ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
+
+ static float f1 = 1.e10f;
+ ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
+ ImGui::SameLine(); HelpMarker(
+ "You can input value using the scientific notation,\n"
+ " e.g. \"1e+8\" becomes \"100000000\".");
+
+ static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
+ ImGui::InputFloat3("input float3", vec4a);
+ }
+
+ {
+ IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat");
+ static int i1 = 50, i2 = 42;
+ ImGui::DragInt("drag int", &i1, 1);
+ ImGui::SameLine(); HelpMarker(
+ "Click and drag to edit value.\n"
+ "Hold SHIFT/ALT for faster/slower edit.\n"
+ "Double-click or CTRL+click to input value.");
+
+ ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
+
+ static float f1 = 1.00f, f2 = 0.0067f;
+ ImGui::DragFloat("drag float", &f1, 0.005f);
+ ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
+ }
+
+ {
+ IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat");
+ static int i1 = 0;
+ ImGui::SliderInt("slider int", &i1, -1, 3);
+ ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
+
+ static float f1 = 0.123f, f2 = 0.0f;
+ ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
+ ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic);
+
+ IMGUI_DEMO_MARKER("Widgets/Basic/SliderAngle");
+ static float angle = 0.0f;
+ ImGui::SliderAngle("slider angle", &angle);
+
+ // Using the format string to display a name instead of an integer.
+ // Here we completely omit '%d' from the format string, so it'll only display a name.
+ // This technique can also be used with DragInt().
+ IMGUI_DEMO_MARKER("Widgets/Basic/Slider (enum)");
+ enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
+ static int elem = Element_Fire;
+ const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
+ const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
+ ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name);
+ ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
+ }
+
+ {
+ IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4");
+ static float col1[3] = { 1.0f, 0.0f, 0.2f };
+ static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
+ ImGui::ColorEdit3("color 1", col1);
+ ImGui::SameLine(); HelpMarker(
+ "Click on the color square to open a color picker.\n"
+ "Click and hold to use drag and drop.\n"
+ "Right-click on the color square to show options.\n"
+ "CTRL+click on individual component to input value.\n");
+
+ ImGui::ColorEdit4("color 2", col2);
+ }
+
+ {
+ // Using the _simplified_ one-liner ListBox() api here
+ // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
+ IMGUI_DEMO_MARKER("Widgets/Basic/ListBox");
+ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
+ static int item_current = 1;
+ ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
+ ImGui::SameLine(); HelpMarker(
+ "Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
+ }
+
+ ImGui::TreePop();
+ }
+
+ // Testing ImGuiOnceUponAFrame helper.
+ //static ImGuiOnceUponAFrame once;
+ //for (int i = 0; i < 5; i++)
+ // if (once)
+ // ImGui::Text("This will be displayed only once.");
+
+ IMGUI_DEMO_MARKER("Widgets/Trees");
+ if (ImGui::TreeNode("Trees"))
+ {
+ IMGUI_DEMO_MARKER("Widgets/Trees/Basic trees");
+ if (ImGui::TreeNode("Basic trees"))
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ // Use SetNextItemOpen() so set the default state of a node to be open. We could
+ // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
+ if (i == 0)
+ ImGui::SetNextItemOpen(true, ImGuiCond_Once);
+
+ if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
+ {
+ ImGui::Text("blah blah");
+ ImGui::SameLine();
+ if (ImGui::SmallButton("button")) {}
+ ImGui::TreePop();
+ }
+ }
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Trees/Advanced, with Selectable nodes");
+ if (ImGui::TreeNode("Advanced, with Selectable nodes"))
+ {
+ HelpMarker(
+ "This is a more typical looking tree with selectable nodes.\n"
+ "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
+ static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
+ static bool align_label_with_current_x_position = false;
+ static bool test_drag_and_drop = false;
+ ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
+ ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
+ ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
+ ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
+ ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
+ ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
+ ImGui::Text("Hello!");
+ if (align_label_with_current_x_position)
+ ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
+
+ // 'selection_mask' is dumb representation of what may be user-side selection state.
+ // You may retain selection state inside or outside your objects in whatever format you see fit.
+ // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
+ /// of the loop. May be a pointer to your own node type, etc.
+ static int selection_mask = (1 << 2);
+ int node_clicked = -1;
+ for (int i = 0; i < 6; i++)
+ {
+ // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
+ // To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection.
+ ImGuiTreeNodeFlags node_flags = base_flags;
+ const bool is_selected = (selection_mask & (1 << i)) != 0;
+ if (is_selected)
+ node_flags |= ImGuiTreeNodeFlags_Selected;
+ if (i < 3)
+ {
+ // Items 0..2 are Tree Node
+ bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
+ if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
+ node_clicked = i;
+ if (test_drag_and_drop && ImGui::BeginDragDropSource())
+ {
+ ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
+ ImGui::Text("This is a drag and drop source");
+ ImGui::EndDragDropSource();
+ }
+ if (node_open)
+ {
+ ImGui::BulletText("Blah blah\nBlah Blah");
+ ImGui::TreePop();
+ }
+ }
+ else
+ {
+ // Items 3..5 are Tree Leaves
+ // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
+ // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
+ node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
+ ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
+ if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
+ node_clicked = i;
+ if (test_drag_and_drop && ImGui::BeginDragDropSource())
+ {
+ ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
+ ImGui::Text("This is a drag and drop source");
+ ImGui::EndDragDropSource();
+ }
+ }
+ }
+ if (node_clicked != -1)
+ {
+ // Update selection state
+ // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
+ if (ImGui::GetIO().KeyCtrl)
+ selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
+ else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
+ selection_mask = (1 << node_clicked); // Click to single-select
+ }
+ if (align_label_with_current_x_position)
+ ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Collapsing Headers");
+ if (ImGui::TreeNode("Collapsing Headers"))
+ {
+ static bool closable_group = true;
+ ImGui::Checkbox("Show 2nd header", &closable_group);
+ if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None))
+ {
+ ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
+ for (int i = 0; i < 5; i++)
+ ImGui::Text("Some content %d", i);
+ }
+ if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
+ {
+ ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
+ for (int i = 0; i < 5; i++)
+ ImGui::Text("More content %d", i);
+ }
+ /*
+ if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
+ ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
+ */
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Bullets");
+ if (ImGui::TreeNode("Bullets"))
+ {
+ ImGui::BulletText("Bullet point 1");
+ ImGui::BulletText("Bullet point 2\nOn multiple lines");
+ if (ImGui::TreeNode("Tree node"))
+ {
+ ImGui::BulletText("Another bullet point");
+ ImGui::TreePop();
+ }
+ ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
+ ImGui::Bullet(); ImGui::SmallButton("Button");
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Text");
+ if (ImGui::TreeNode("Text"))
+ {
+ IMGUI_DEMO_MARKER("Widgets/Text/Colored Text");
+ if (ImGui::TreeNode("Colorful Text"))
+ {
+ // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
+ ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
+ ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
+ ImGui::TextDisabled("Disabled");
+ ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Text/Word Wrapping");
+ if (ImGui::TreeNode("Word Wrapping"))
+ {
+ // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
+ ImGui::TextWrapped(
+ "This text should automatically wrap on the edge of the window. The current implementation "
+ "for text wrapping follows simple rules suitable for English and possibly other languages.");
+ ImGui::Spacing();
+
+ static float wrap_width = 200.0f;
+ ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
+
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+ for (int n = 0; n < 2; n++)
+ {
+ ImGui::Text("Test paragraph %d:", n);
+ ImVec2 pos = ImGui::GetCursorScreenPos();
+ ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
+ ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
+ ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
+ if (n == 0)
+ ImGui::Text("The lazy dog is a good dog. This paragraph should fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
+ else
+ ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
+
+ // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
+ draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
+ draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255));
+ ImGui::PopTextWrapPos();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Text/UTF-8 Text");
+ if (ImGui::TreeNode("UTF-8 Text"))
+ {
+ // UTF-8 test with Japanese characters
+ // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
+ // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
+ // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
+ // can save your source files as 'UTF-8 without signature').
+ // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
+ // CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
+ // Don't do this in your application! Please use u8"text in any language" in your application!
+ // Note that characters values are preserved even by InputText() if the font cannot be displayed,
+ // so you can safely copy & paste garbled characters into another application.
+ ImGui::TextWrapped(
+ "CJK text will only appears if the font was loaded with the appropriate CJK character ranges. "
+ "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
+ "Read docs/FONTS.md for details.");
+ ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
+ ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
+ static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
+ //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
+ ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Images");
+ if (ImGui::TreeNode("Images"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ ImGui::TextWrapped(
+ "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
+ "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
+ "Hover the texture for a zoomed view!");
+
+ // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
+ // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
+ // will be passed to the rendering backend via the ImDrawCmd structure.
+ // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top
+ // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
+ // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
+ // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
+ // More:
+ // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
+ // to ImGui::Image(), and gather width/height through your own functions, etc.
+ // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
+ // it will help you debug issues if you are confused about it.
+ // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
+ // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
+ // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
+ ImTextureID my_tex_id = io.Fonts->TexID;
+ float my_tex_w = (float)io.Fonts->TexWidth;
+ float my_tex_h = (float)io.Fonts->TexHeight;
+ {
+ ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
+ ImVec2 pos = ImGui::GetCursorScreenPos();
+ ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
+ ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
+ ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
+ ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
+ ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ float region_sz = 32.0f;
+ float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
+ float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
+ float zoom = 4.0f;
+ if (region_x < 0.0f) { region_x = 0.0f; }
+ else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
+ if (region_y < 0.0f) { region_y = 0.0f; }
+ else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
+ ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
+ ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
+ ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
+ ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
+ ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
+ ImGui::EndTooltip();
+ }
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
+ ImGui::TextWrapped("And now some textured buttons..");
+ static int pressed_count = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ ImGui::PushID(i);
+ int frame_padding = -1 + i; // -1 == uses default padding (style.FramePadding)
+ ImVec2 size = ImVec2(32.0f, 32.0f); // Size of the image we want to make visible
+ ImVec2 uv0 = ImVec2(0.0f, 0.0f); // UV coordinates for lower-left
+ ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);// UV coordinates for (32,32) in our texture
+ ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Black background
+ ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
+ if (ImGui::ImageButton(my_tex_id, size, uv0, uv1, frame_padding, bg_col, tint_col))
+ pressed_count += 1;
+ ImGui::PopID();
+ ImGui::SameLine();
+ }
+ ImGui::NewLine();
+ ImGui::Text("Pressed %d times.", pressed_count);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Combo");
+ if (ImGui::TreeNode("Combo"))
+ {
+ // Expose flags as checkbox for the demo
+ static ImGuiComboFlags flags = 0;
+ ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);
+ ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
+ if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton))
+ flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both
+ if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview))
+ flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
+
+ // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
+ // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
+ // stored in the object itself, etc.)
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
+ static int item_current_idx = 0; // Here we store our selection data as an index.
+ const char* combo_preview_value = items[item_current_idx]; // Pass in the preview value visible before opening the combo (it could be anything)
+ if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+ {
+ const bool is_selected = (item_current_idx == n);
+ if (ImGui::Selectable(items[n], is_selected))
+ item_current_idx = n;
+
+ // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
+ if (is_selected)
+ ImGui::SetItemDefaultFocus();
+ }
+ ImGui::EndCombo();
+ }
+
+ // Simplified one-liner Combo() API, using values packed in a single constant string
+ // This is a convenience for when the selection set is small and known at compile-time.
+ static int item_current_2 = 0;
+ ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
+
+ // Simplified one-liner Combo() using an array of const char*
+ // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
+ static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
+ ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
+
+ // Simplified one-liner Combo() using an accessor function
+ struct Funcs { static bool ItemGetter(void* data, int n, const char** out_str) { *out_str = ((const char**)data)[n]; return true; } };
+ static int item_current_4 = 0;
+ ImGui::Combo("combo 4 (function)", &item_current_4, &Funcs::ItemGetter, items, IM_ARRAYSIZE(items));
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/List Boxes");
+ if (ImGui::TreeNode("List boxes"))
+ {
+ // Using the generic BeginListBox() API, you have full control over how to display the combo contents.
+ // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
+ // stored in the object itself, etc.)
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
+ static int item_current_idx = 0; // Here we store our selection data as an index.
+ if (ImGui::BeginListBox("listbox 1"))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+ {
+ const bool is_selected = (item_current_idx == n);
+ if (ImGui::Selectable(items[n], is_selected))
+ item_current_idx = n;
+
+ // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
+ if (is_selected)
+ ImGui::SetItemDefaultFocus();
+ }
+ ImGui::EndListBox();
+ }
+
+ // Custom size: use all width, 5 items tall
+ ImGui::Text("Full-width:");
+ if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(items); n++)
+ {
+ const bool is_selected = (item_current_idx == n);
+ if (ImGui::Selectable(items[n], is_selected))
+ item_current_idx = n;
+
+ // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
+ if (is_selected)
+ ImGui::SetItemDefaultFocus();
+ }
+ ImGui::EndListBox();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Selectables");
+ if (ImGui::TreeNode("Selectables"))
+ {
+ // Selectable() has 2 overloads:
+ // - The one taking "bool selected" as a read-only selection information.
+ // When Selectable() has been clicked it returns true and you can alter selection state accordingly.
+ // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
+ // The earlier is more flexible, as in real application your selection may be stored in many different ways
+ // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
+ IMGUI_DEMO_MARKER("Widgets/Selectables/Basic");
+ if (ImGui::TreeNode("Basic"))
+ {
+ static bool selection[5] = { false, true, false, false, false };
+ ImGui::Selectable("1. I am selectable", &selection[0]);
+ ImGui::Selectable("2. I am selectable", &selection[1]);
+ ImGui::Text("(I am not selectable)");
+ ImGui::Selectable("4. I am selectable", &selection[3]);
+ if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
+ if (ImGui::IsMouseDoubleClicked(0))
+ selection[4] = !selection[4];
+ ImGui::TreePop();
+ }
+ IMGUI_DEMO_MARKER("Widgets/Selectables/Single Selection");
+ if (ImGui::TreeNode("Selection State: Single Selection"))
+ {
+ static int selected = -1;
+ for (int n = 0; n < 5; n++)
+ {
+ char buf[32];
+ sprintf(buf, "Object %d", n);
+ if (ImGui::Selectable(buf, selected == n))
+ selected = n;
+ }
+ ImGui::TreePop();
+ }
+ IMGUI_DEMO_MARKER("Widgets/Selectables/Multiple Selection");
+ if (ImGui::TreeNode("Selection State: Multiple Selection"))
+ {
+ HelpMarker("Hold CTRL and click to select multiple items.");
+ static bool selection[5] = { false, false, false, false, false };
+ for (int n = 0; n < 5; n++)
+ {
+ char buf[32];
+ sprintf(buf, "Object %d", n);
+ if (ImGui::Selectable(buf, selection[n]))
+ {
+ if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
+ memset(selection, 0, sizeof(selection));
+ selection[n] ^= 1;
+ }
+ }
+ ImGui::TreePop();
+ }
+ IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more text into the same line");
+ if (ImGui::TreeNode("Rendering more text into the same line"))
+ {
+ // Using the Selectable() override that takes "bool* p_selected" parameter,
+ // this function toggle your bool value automatically.
+ static bool selected[3] = { false, false, false };
+ ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
+ ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
+ ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
+ ImGui::TreePop();
+ }
+ IMGUI_DEMO_MARKER("Widgets/Selectables/In columns");
+ if (ImGui::TreeNode("In columns"))
+ {
+ static bool selected[10] = {};
+
+ if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ char label[32];
+ sprintf(label, "Item %d", i);
+ ImGui::TableNextColumn();
+ ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap
+ }
+ ImGui::EndTable();
+ }
+ ImGui::Spacing();
+ if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ char label[32];
+ sprintf(label, "Item %d", i);
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns);
+ ImGui::TableNextColumn();
+ ImGui::Text("Some other contents");
+ ImGui::TableNextColumn();
+ ImGui::Text("123456");
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+ IMGUI_DEMO_MARKER("Widgets/Selectables/Grid");
+ if (ImGui::TreeNode("Grid"))
+ {
+ static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
+
+ // Add in a bit of silly fun...
+ const float time = (float)ImGui::GetTime();
+ const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected...
+ if (winning_state)
+ ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f)));
+
+ for (int y = 0; y < 4; y++)
+ for (int x = 0; x < 4; x++)
+ {
+ if (x > 0)
+ ImGui::SameLine();
+ ImGui::PushID(y * 4 + x);
+ if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50)))
+ {
+ // Toggle clicked cell + toggle neighbors
+ selected[y][x] ^= 1;
+ if (x > 0) { selected[y][x - 1] ^= 1; }
+ if (x < 3) { selected[y][x + 1] ^= 1; }
+ if (y > 0) { selected[y - 1][x] ^= 1; }
+ if (y < 3) { selected[y + 1][x] ^= 1; }
+ }
+ ImGui::PopID();
+ }
+
+ if (winning_state)
+ ImGui::PopStyleVar();
+ ImGui::TreePop();
+ }
+ IMGUI_DEMO_MARKER("Widgets/Selectables/Alignment");
+ if (ImGui::TreeNode("Alignment"))
+ {
+ HelpMarker(
+ "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
+ "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
+ "left-align otherwise it becomes difficult to layout multiple items on a same line");
+ static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
+ for (int y = 0; y < 3; y++)
+ {
+ for (int x = 0; x < 3; x++)
+ {
+ ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
+ char name[32];
+ sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
+ if (x > 0) ImGui::SameLine();
+ ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
+ ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
+ ImGui::PopStyleVar();
+ }
+ }
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ // To wire InputText() with std::string or any other custom string type,
+ // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
+ IMGUI_DEMO_MARKER("Widgets/Text Input");
+ if (ImGui::TreeNode("Text Input"))
+ {
+ IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input");
+ if (ImGui::TreeNode("Multi-line Text Input"))
+ {
+ // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
+ // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
+ static char text[1024 * 16] =
+ "/*\n"
+ " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
+ " the hexadecimal encoding of one offending instruction,\n"
+ " more formally, the invalid operand with locked CMPXCHG8B\n"
+ " instruction bug, is a design flaw in the majority of\n"
+ " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
+ " processors (all in the P5 microarchitecture).\n"
+ "*/\n\n"
+ "label:\n"
+ "\tlock cmpxchg8b eax\n";
+
+ static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
+ HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include <string> in here)");
+ ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
+ ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
+ ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
+ ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Text Input/Filtered Text Input");
+ if (ImGui::TreeNode("Filtered Text Input"))
+ {
+ struct TextFilters
+ {
+ // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i'
+ static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
+ {
+ if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
+ return 0;
+ return 1;
+ }
+ };
+
+ static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
+ static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
+ static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
+ static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
+ static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
+ static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Text Input/Password input");
+ if (ImGui::TreeNode("Password Input"))
+ {
+ static char password[64] = "password123";
+ ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
+ ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
+ ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
+ ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNode("Completion, History, Edit Callbacks"))
+ {
+ struct Funcs
+ {
+ static int MyCallback(ImGuiInputTextCallbackData* data)
+ {
+ if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
+ {
+ data->InsertChars(data->CursorPos, "..");
+ }
+ else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
+ {
+ if (data->EventKey == ImGuiKey_UpArrow)
+ {
+ data->DeleteChars(0, data->BufTextLen);
+ data->InsertChars(0, "Pressed Up!");
+ data->SelectAll();
+ }
+ else if (data->EventKey == ImGuiKey_DownArrow)
+ {
+ data->DeleteChars(0, data->BufTextLen);
+ data->InsertChars(0, "Pressed Down!");
+ data->SelectAll();
+ }
+ }
+ else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
+ {
+ // Toggle casing of first character
+ char c = data->Buf[0];
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
+ data->BufDirty = true;
+
+ // Increment a counter
+ int* p_int = (int*)data->UserData;
+ *p_int = *p_int + 1;
+ }
+ return 0;
+ }
+ };
+ static char buf1[64];
+ ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
+ ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
+
+ static char buf2[64];
+ ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
+ ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
+
+ static char buf3[64];
+ static int edit_count = 0;
+ ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
+ ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edits + count edits.");
+ ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Text Input/Resize Callback");
+ if (ImGui::TreeNode("Resize Callback"))
+ {
+ // To wire InputText() with std::string or any other custom string type,
+ // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
+ // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
+ HelpMarker(
+ "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
+ "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
+ struct Funcs
+ {
+ static int MyResizeCallback(ImGuiInputTextCallbackData* data)
+ {
+ if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
+ {
+ ImVector<char>* my_str = (ImVector<char>*)data->UserData;
+ IM_ASSERT(my_str->begin() == data->Buf);
+ my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
+ data->Buf = my_str->begin();
+ }
+ return 0;
+ }
+
+ // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
+ // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
+ static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
+ {
+ IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
+ return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str);
+ }
+ };
+
+ // For this demo we are using ImVector as a string container.
+ // Note that because we need to store a terminating zero character, our size/capacity are 1 more
+ // than usually reported by a typical string class.
+ static ImVector<char> my_str;
+ if (my_str.empty())
+ my_str.push_back(0);
+ Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
+ ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
+ ImGui::TreePop();
+ }
+
+ ImGui::TreePop();
+ }
+
+ // Tabs
+ IMGUI_DEMO_MARKER("Widgets/Tabs");
+ if (ImGui::TreeNode("Tabs"))
+ {
+ IMGUI_DEMO_MARKER("Widgets/Tabs/Basic");
+ if (ImGui::TreeNode("Basic"))
+ {
+ ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
+ if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
+ {
+ if (ImGui::BeginTabItem("Avocado"))
+ {
+ ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("Broccoli"))
+ {
+ ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("Cucumber"))
+ {
+ ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Tabs/Advanced & Close Button");
+ if (ImGui::TreeNode("Advanced & Close Button"))
+ {
+ // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
+ static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable);
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
+ if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
+ tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
+ if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
+ tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
+ if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
+ tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
+
+ // Tab Bar
+ const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
+ static bool opened[4] = { true, true, true, true }; // Persistent user state
+ for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
+ {
+ if (n > 0) { ImGui::SameLine(); }
+ ImGui::Checkbox(names[n], &opened[n]);
+ }
+
+ // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
+ // the underlying bool will be set to false when the tab is closed.
+ if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
+ if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
+ {
+ ImGui::Text("This is the %s tab!", names[n]);
+ if (n & 1)
+ ImGui::Text("I am an odd tab.");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Tabs/TabItemButton & Leading-Trailing flags");
+ if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags"))
+ {
+ static ImVector<int> active_tabs;
+ static int next_tab_id = 0;
+ if (next_tab_id == 0) // Initialize with some default tabs
+ for (int i = 0; i < 3; i++)
+ active_tabs.push_back(next_tab_id++);
+
+ // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
+ // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
+ // but they tend to make more sense together)
+ static bool show_leading_button = true;
+ static bool show_trailing_button = true;
+ ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
+ ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
+
+ // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
+ static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
+ ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
+ if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
+ tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
+ if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
+ tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
+
+ if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
+ {
+ // Demo a Leading TabItemButton(): click the "?" button to open a menu
+ if (show_leading_button)
+ if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
+ ImGui::OpenPopup("MyHelpMenu");
+ if (ImGui::BeginPopup("MyHelpMenu"))
+ {
+ ImGui::Selectable("Hello!");
+ ImGui::EndPopup();
+ }
+
+ // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+")
+ // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
+ if (show_trailing_button)
+ if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
+ active_tabs.push_back(next_tab_id++); // Add new tab
+
+ // Submit our regular tabs
+ for (int n = 0; n < active_tabs.Size; )
+ {
+ bool open = true;
+ char name[16];
+ snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
+ if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
+ {
+ ImGui::Text("This is the %s tab!", name);
+ ImGui::EndTabItem();
+ }
+
+ if (!open)
+ active_tabs.erase(active_tabs.Data + n);
+ else
+ n++;
+ }
+
+ ImGui::EndTabBar();
+ }
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+
+ // Plot/Graph widgets are not very good.
+ // Consider using a third-party library such as ImPlot: https://github.com/epezent/implot
+ // (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions)
+ IMGUI_DEMO_MARKER("Widgets/Plotting");
+ if (ImGui::TreeNode("Plotting"))
+ {
+ static bool animate = true;
+ ImGui::Checkbox("Animate", &animate);
+
+ // Plot as lines and plot as histogram
+ IMGUI_DEMO_MARKER("Widgets/Plotting/PlotLines, PlotHistogram");
+ static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
+ ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
+ ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
+
+ // Fill an array of contiguous float values to plot
+ // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
+ // and the sizeof() of your structure in the "stride" parameter.
+ static float values[90] = {};
+ static int values_offset = 0;
+ static double refresh_time = 0.0;
+ if (!animate || refresh_time == 0.0)
+ refresh_time = ImGui::GetTime();
+ while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
+ {
+ static float phase = 0.0f;
+ values[values_offset] = cosf(phase);
+ values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
+ phase += 0.10f * values_offset;
+ refresh_time += 1.0f / 60.0f;
+ }
+
+ // Plots can display overlay texts
+ // (in this example, we will display an average value)
+ {
+ float average = 0.0f;
+ for (int n = 0; n < IM_ARRAYSIZE(values); n++)
+ average += values[n];
+ average /= (float)IM_ARRAYSIZE(values);
+ char overlay[32];
+ sprintf(overlay, "avg %f", average);
+ ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
+ }
+
+ // Use functions to generate output
+ // FIXME: This is rather awkward because current plot API only pass in indices.
+ // We probably want an API passing floats and user provide sample rate/count.
+ struct Funcs
+ {
+ static float Sin(void*, int i) { return sinf(i * 0.1f); }
+ static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
+ };
+ static int func_type = 0, display_count = 70;
+ ImGui::Separator();
+ ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
+ ImGui::Combo("func", &func_type, "Sin\0Saw\0");
+ ImGui::SameLine();
+ ImGui::SliderInt("Sample count", &display_count, 1, 400);
+ float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
+ ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
+ ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
+ ImGui::Separator();
+
+ // Animate a simple progress bar
+ IMGUI_DEMO_MARKER("Widgets/Plotting/ProgressBar");
+ static float progress = 0.0f, progress_dir = 1.0f;
+ if (animate)
+ {
+ progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
+ if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
+ if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
+ }
+
+ // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
+ // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
+ ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
+ ImGui::Text("Progress Bar");
+
+ float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
+ char buf[32];
+ sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
+ ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Color");
+ if (ImGui::TreeNode("Color/Picker Widgets"))
+ {
+ static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
+
+ static bool alpha_preview = true;
+ static bool alpha_half_preview = false;
+ static bool drag_and_drop = true;
+ static bool options_menu = true;
+ static bool hdr = false;
+ ImGui::Checkbox("With Alpha Preview", &alpha_preview);
+ ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
+ ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
+ ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
+ ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
+ ImGuiColorEditFlags misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit");
+ ImGui::Text("Color widget:");
+ ImGui::SameLine(); HelpMarker(
+ "Click on the color square to open a color picker.\n"
+ "CTRL+click on individual component to input value.\n");
+ ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)");
+ ImGui::Text("Color widget HSV with Alpha:");
+ ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags);
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)");
+ ImGui::Text("Color widget with Float Display:");
+ ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)");
+ ImGui::Text("Color button with Picker:");
+ ImGui::SameLine(); HelpMarker(
+ "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
+ "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
+ "be used for the tooltip and picker popup.");
+ ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)");
+ ImGui::Text("Color button with Custom Picker Popup:");
+
+ // Generate a default palette. The palette will persist and can be edited.
+ static bool saved_palette_init = true;
+ static ImVec4 saved_palette[32] = {};
+ if (saved_palette_init)
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
+ {
+ ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
+ saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
+ saved_palette[n].w = 1.0f; // Alpha
+ }
+ saved_palette_init = false;
+ }
+
+ static ImVec4 backup_color;
+ bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
+ ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
+ open_popup |= ImGui::Button("Palette");
+ if (open_popup)
+ {
+ ImGui::OpenPopup("mypicker");
+ backup_color = color;
+ }
+ if (ImGui::BeginPopup("mypicker"))
+ {
+ ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
+ ImGui::Separator();
+ ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
+ ImGui::SameLine();
+
+ ImGui::BeginGroup(); // Lock X position
+ ImGui::Text("Current");
+ ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
+ ImGui::Text("Previous");
+ if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
+ color = backup_color;
+ ImGui::Separator();
+ ImGui::Text("Palette");
+ for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
+ {
+ ImGui::PushID(n);
+ if ((n % 8) != 0)
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
+
+ ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
+ if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
+ color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
+
+ // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
+ // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
+ if (ImGui::BeginDragDropTarget())
+ {
+ if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
+ memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
+ if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
+ memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
+ ImGui::EndDragDropTarget();
+ }
+
+ ImGui::PopID();
+ }
+ ImGui::EndGroup();
+ ImGui::EndPopup();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)");
+ ImGui::Text("Color button only:");
+ static bool no_border = false;
+ ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
+ ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
+
+ IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker");
+ ImGui::Text("Color picker:");
+ static bool alpha = true;
+ static bool alpha_bar = true;
+ static bool side_preview = true;
+ static bool ref_color = false;
+ static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
+ static int display_mode = 0;
+ static int picker_mode = 0;
+ ImGui::Checkbox("With Alpha", &alpha);
+ ImGui::Checkbox("With Alpha Bar", &alpha_bar);
+ ImGui::Checkbox("With Side Preview", &side_preview);
+ if (side_preview)
+ {
+ ImGui::SameLine();
+ ImGui::Checkbox("With Ref Color", &ref_color);
+ if (ref_color)
+ {
+ ImGui::SameLine();
+ ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
+ }
+ }
+ ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
+ ImGui::SameLine(); HelpMarker(
+ "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
+ "but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
+ "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
+ ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
+ ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
+ ImGuiColorEditFlags flags = misc_flags;
+ if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
+ if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
+ if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
+ if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
+ if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
+ if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays
+ if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB; // Override display mode
+ if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
+ if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
+ ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
+
+ ImGui::Text("Set defaults in code:");
+ ImGui::SameLine(); HelpMarker(
+ "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
+ "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
+ "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
+ "encouraging you to persistently save values that aren't forward-compatible.");
+ if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
+ ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
+ if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
+ ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
+
+ // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
+ static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
+ ImGui::Spacing();
+ ImGui::Text("HSV encoded colors");
+ ImGui::SameLine(); HelpMarker(
+ "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
+ "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
+ "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
+ ImGui::Text("Color widget with InputHSV:");
+ ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
+ ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
+ ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f);
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags");
+ if (ImGui::TreeNode("Drag/Slider Flags"))
+ {
+ // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
+ static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
+ ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
+ ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
+ ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
+ ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
+ ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
+ ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
+ ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
+ ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
+
+ // Drags
+ static float drag_f = 0.5f;
+ static int drag_i = 50;
+ ImGui::Text("Underlying float value: %f", drag_f);
+ ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags);
+ ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
+ ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
+ ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
+ ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
+
+ // Sliders
+ static float slider_f = 0.5f;
+ static int slider_i = 50;
+ ImGui::Text("Underlying float value: %f", slider_f);
+ ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags);
+ ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags);
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Range Widgets");
+ if (ImGui::TreeNode("Range Widgets"))
+ {
+ static float begin = 10, end = 90;
+ static int begin_i = 100, end_i = 1000;
+ ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp);
+ ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units");
+ ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Data Types");
+ if (ImGui::TreeNode("Data Types"))
+ {
+ // DragScalar/InputScalar/SliderScalar functions allow various data types
+ // - signed/unsigned
+ // - 8/16/32/64-bits
+ // - integer/float/double
+ // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
+ // to pass the type, and passing all arguments by pointer.
+ // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
+ // In practice, if you frequently use a given type that is not covered by the normal API entry points,
+ // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
+ // and then pass their address to the generic function. For example:
+ // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
+ // {
+ // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
+ // }
+
+ // Setup limits (as helper variables so we can take their address, as explained above)
+ // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
+ #ifndef LLONG_MIN
+ ImS64 LLONG_MIN = -9223372036854775807LL - 1;
+ ImS64 LLONG_MAX = 9223372036854775807LL;
+ ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
+ #endif
+ const char s8_zero = 0, s8_one = 1, s8_fifty = 50, s8_min = -128, s8_max = 127;
+ const ImU8 u8_zero = 0, u8_one = 1, u8_fifty = 50, u8_min = 0, u8_max = 255;
+ const short s16_zero = 0, s16_one = 1, s16_fifty = 50, s16_min = -32768, s16_max = 32767;
+ const ImU16 u16_zero = 0, u16_one = 1, u16_fifty = 50, u16_min = 0, u16_max = 65535;
+ const ImS32 s32_zero = 0, s32_one = 1, s32_fifty = 50, s32_min = INT_MIN/2, s32_max = INT_MAX/2, s32_hi_a = INT_MAX/2 - 100, s32_hi_b = INT_MAX/2;
+ const ImU32 u32_zero = 0, u32_one = 1, u32_fifty = 50, u32_min = 0, u32_max = UINT_MAX/2, u32_hi_a = UINT_MAX/2 - 100, u32_hi_b = UINT_MAX/2;
+ const ImS64 s64_zero = 0, s64_one = 1, s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2, s64_hi_a = LLONG_MAX/2 - 100, s64_hi_b = LLONG_MAX/2;
+ const ImU64 u64_zero = 0, u64_one = 1, u64_fifty = 50, u64_min = 0, u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2;
+ const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
+ const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
+
+ // State
+ static char s8_v = 127;
+ static ImU8 u8_v = 255;
+ static short s16_v = 32767;
+ static ImU16 u16_v = 65535;
+ static ImS32 s32_v = -1;
+ static ImU32 u32_v = (ImU32)-1;
+ static ImS64 s64_v = -1;
+ static ImU64 u64_v = (ImU64)-1;
+ static float f32_v = 0.123f;
+ static double f64_v = 90000.01234567890123456789;
+
+ const float drag_speed = 0.2f;
+ static bool drag_clamp = false;
+ IMGUI_DEMO_MARKER("Widgets/Data Types/Drags");
+ ImGui::Text("Drags:");
+ ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
+ ImGui::SameLine(); HelpMarker(
+ "As with every widgets in dear imgui, we never modify values unless there is a user interaction.\n"
+ "You can override the clamping limits by using CTRL+Click to input a value.");
+ ImGui::DragScalar("drag s8", ImGuiDataType_S8, &s8_v, drag_speed, drag_clamp ? &s8_zero : NULL, drag_clamp ? &s8_fifty : NULL);
+ ImGui::DragScalar("drag u8", ImGuiDataType_U8, &u8_v, drag_speed, drag_clamp ? &u8_zero : NULL, drag_clamp ? &u8_fifty : NULL, "%u ms");
+ ImGui::DragScalar("drag s16", ImGuiDataType_S16, &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
+ ImGui::DragScalar("drag u16", ImGuiDataType_U16, &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
+ ImGui::DragScalar("drag s32", ImGuiDataType_S32, &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
+ ImGui::DragScalar("drag u32", ImGuiDataType_U32, &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
+ ImGui::DragScalar("drag s64", ImGuiDataType_S64, &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
+ ImGui::DragScalar("drag u64", ImGuiDataType_U64, &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
+ ImGui::DragScalar("drag float", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f");
+ ImGui::DragScalar("drag float log", ImGuiDataType_Float, &f32_v, 0.005f, &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic);
+ ImGui::DragScalar("drag double", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL, "%.10f grams");
+ ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
+
+ IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders");
+ ImGui::Text("Sliders");
+ ImGui::SliderScalar("slider s8 full", ImGuiDataType_S8, &s8_v, &s8_min, &s8_max, "%d");
+ ImGui::SliderScalar("slider u8 full", ImGuiDataType_U8, &u8_v, &u8_min, &u8_max, "%u");
+ ImGui::SliderScalar("slider s16 full", ImGuiDataType_S16, &s16_v, &s16_min, &s16_max, "%d");
+ ImGui::SliderScalar("slider u16 full", ImGuiDataType_U16, &u16_v, &u16_min, &u16_max, "%u");
+ ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32, &s32_v, &s32_zero, &s32_fifty,"%d");
+ ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32, &s32_v, &s32_hi_a, &s32_hi_b, "%d");
+ ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32, &s32_v, &s32_min, &s32_max, "%d");
+ ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32, &u32_v, &u32_zero, &u32_fifty,"%u");
+ ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32, &u32_v, &u32_hi_a, &u32_hi_b, "%u");
+ ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32, &u32_v, &u32_min, &u32_max, "%u");
+ ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64, &s64_v, &s64_zero, &s64_fifty,"%" IM_PRId64);
+ ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64, &s64_v, &s64_hi_a, &s64_hi_b, "%" IM_PRId64);
+ ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64, &s64_v, &s64_min, &s64_max, "%" IM_PRId64);
+ ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64, &u64_v, &u64_zero, &u64_fifty,"%" IM_PRIu64 " ms");
+ ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64, &u64_v, &u64_hi_a, &u64_hi_b, "%" IM_PRIu64 " ms");
+ ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64, &u64_v, &u64_min, &u64_max, "%" IM_PRIu64 " ms");
+ ImGui::SliderScalar("slider float low", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one);
+ ImGui::SliderScalar("slider float low log", ImGuiDataType_Float, &f32_v, &f32_zero, &f32_one, "%.10f", ImGuiSliderFlags_Logarithmic);
+ ImGui::SliderScalar("slider float high", ImGuiDataType_Float, &f32_v, &f32_lo_a, &f32_hi_a, "%e");
+ ImGui::SliderScalar("slider double low", ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f grams");
+ ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one, "%.10f", ImGuiSliderFlags_Logarithmic);
+ ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
+
+ ImGui::Text("Sliders (reverse)");
+ ImGui::SliderScalar("slider s8 reverse", ImGuiDataType_S8, &s8_v, &s8_max, &s8_min, "%d");
+ ImGui::SliderScalar("slider u8 reverse", ImGuiDataType_U8, &u8_v, &u8_max, &u8_min, "%u");
+ ImGui::SliderScalar("slider s32 reverse", ImGuiDataType_S32, &s32_v, &s32_fifty, &s32_zero, "%d");
+ ImGui::SliderScalar("slider u32 reverse", ImGuiDataType_U32, &u32_v, &u32_fifty, &u32_zero, "%u");
+ ImGui::SliderScalar("slider s64 reverse", ImGuiDataType_S64, &s64_v, &s64_fifty, &s64_zero, "%" IM_PRId64);
+ ImGui::SliderScalar("slider u64 reverse", ImGuiDataType_U64, &u64_v, &u64_fifty, &u64_zero, "%" IM_PRIu64 " ms");
+
+ IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs");
+ static bool inputs_step = true;
+ ImGui::Text("Inputs");
+ ImGui::Checkbox("Show step buttons", &inputs_step);
+ ImGui::InputScalar("input s8", ImGuiDataType_S8, &s8_v, inputs_step ? &s8_one : NULL, NULL, "%d");
+ ImGui::InputScalar("input u8", ImGuiDataType_U8, &u8_v, inputs_step ? &u8_one : NULL, NULL, "%u");
+ ImGui::InputScalar("input s16", ImGuiDataType_S16, &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d");
+ ImGui::InputScalar("input u16", ImGuiDataType_U16, &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u");
+ ImGui::InputScalar("input s32", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
+ ImGui::InputScalar("input s32 hex", ImGuiDataType_S32, &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
+ ImGui::InputScalar("input u32", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
+ ImGui::InputScalar("input u32 hex", ImGuiDataType_U32, &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
+ ImGui::InputScalar("input s64", ImGuiDataType_S64, &s64_v, inputs_step ? &s64_one : NULL);
+ ImGui::InputScalar("input u64", ImGuiDataType_U64, &u64_v, inputs_step ? &u64_one : NULL);
+ ImGui::InputScalar("input float", ImGuiDataType_Float, &f32_v, inputs_step ? &f32_one : NULL);
+ ImGui::InputScalar("input double", ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets");
+ if (ImGui::TreeNode("Multi-component Widgets"))
+ {
+ static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
+ static int vec4i[4] = { 1, 5, 100, 255 };
+
+ ImGui::InputFloat2("input float2", vec4f);
+ ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
+ ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
+ ImGui::InputInt2("input int2", vec4i);
+ ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
+ ImGui::SliderInt2("slider int2", vec4i, 0, 255);
+ ImGui::Spacing();
+
+ ImGui::InputFloat3("input float3", vec4f);
+ ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
+ ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
+ ImGui::InputInt3("input int3", vec4i);
+ ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
+ ImGui::SliderInt3("slider int3", vec4i, 0, 255);
+ ImGui::Spacing();
+
+ ImGui::InputFloat4("input float4", vec4f);
+ ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
+ ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
+ ImGui::InputInt4("input int4", vec4i);
+ ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
+ ImGui::SliderInt4("slider int4", vec4i, 0, 255);
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Vertical Sliders");
+ if (ImGui::TreeNode("Vertical Sliders"))
+ {
+ const float spacing = 4;
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
+
+ static int int_value = 0;
+ ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
+ ImGui::SameLine();
+
+ static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
+ ImGui::PushID("set1");
+ for (int i = 0; i < 7; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
+ ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
+ ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
+ if (ImGui::IsItemActive() || ImGui::IsItemHovered())
+ ImGui::SetTooltip("%.3f", values[i]);
+ ImGui::PopStyleColor(4);
+ ImGui::PopID();
+ }
+ ImGui::PopID();
+
+ ImGui::SameLine();
+ ImGui::PushID("set2");
+ static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
+ const int rows = 3;
+ const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
+ for (int nx = 0; nx < 4; nx++)
+ {
+ if (nx > 0) ImGui::SameLine();
+ ImGui::BeginGroup();
+ for (int ny = 0; ny < rows; ny++)
+ {
+ ImGui::PushID(nx * rows + ny);
+ ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
+ if (ImGui::IsItemActive() || ImGui::IsItemHovered())
+ ImGui::SetTooltip("%.3f", values2[nx]);
+ ImGui::PopID();
+ }
+ ImGui::EndGroup();
+ }
+ ImGui::PopID();
+
+ ImGui::SameLine();
+ ImGui::PushID("set3");
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
+ ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
+ ImGui::PopStyleVar();
+ ImGui::PopID();
+ }
+ ImGui::PopID();
+ ImGui::PopStyleVar();
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Drag and drop");
+ if (ImGui::TreeNode("Drag and Drop"))
+ {
+ IMGUI_DEMO_MARKER("Widgets/Drag and drop/Standard widgets");
+ if (ImGui::TreeNode("Drag and drop in standard widgets"))
+ {
+ // ColorEdit widgets automatically act as drag source and drag target.
+ // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
+ // to allow your own widgets to use colors in their drag and drop interaction.
+ // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
+ HelpMarker("You can drag from the color squares.");
+ static float col1[3] = { 1.0f, 0.0f, 0.2f };
+ static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
+ ImGui::ColorEdit3("color 1", col1);
+ ImGui::ColorEdit4("color 2", col2);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Drag and drop/Copy-swap items");
+ if (ImGui::TreeNode("Drag and drop to copy/swap items"))
+ {
+ enum Mode
+ {
+ Mode_Copy,
+ Mode_Move,
+ Mode_Swap
+ };
+ static int mode = 0;
+ if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
+ if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
+ if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
+ static const char* names[9] =
+ {
+ "Bobby", "Beatrice", "Betty",
+ "Brianna", "Barry", "Bernard",
+ "Bibi", "Blaine", "Bryn"
+ };
+ for (int n = 0; n < IM_ARRAYSIZE(names); n++)
+ {
+ ImGui::PushID(n);
+ if ((n % 3) != 0)
+ ImGui::SameLine();
+ ImGui::Button(names[n], ImVec2(60, 60));
+
+ // Our buttons are both drag sources and drag targets here!
+ if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
+ {
+ // Set payload to carry the index of our item (could be anything)
+ ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));
+
+ // Display preview (could be anything, e.g. when dragging an image we could decide to display
+ // the filename and a small preview of the image, etc.)
+ if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }
+ if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
+ if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
+ ImGui::EndDragDropSource();
+ }
+ if (ImGui::BeginDragDropTarget())
+ {
+ if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
+ {
+ IM_ASSERT(payload->DataSize == sizeof(int));
+ int payload_n = *(const int*)payload->Data;
+ if (mode == Mode_Copy)
+ {
+ names[n] = names[payload_n];
+ }
+ if (mode == Mode_Move)
+ {
+ names[n] = names[payload_n];
+ names[payload_n] = "";
+ }
+ if (mode == Mode_Swap)
+ {
+ const char* tmp = names[n];
+ names[n] = names[payload_n];
+ names[payload_n] = tmp;
+ }
+ }
+ ImGui::EndDragDropTarget();
+ }
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)");
+ if (ImGui::TreeNode("Drag to reorder items (simple)"))
+ {
+ // Simple reordering
+ HelpMarker(
+ "We don't use the drag and drop api at all here! "
+ "Instead we query when the item is held but not hovered, and order items accordingly.");
+ static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
+ for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
+ {
+ const char* item = item_names[n];
+ ImGui::Selectable(item);
+
+ if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
+ {
+ int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
+ if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
+ {
+ item_names[n] = item_names[n_next];
+ item_names[n_next] = item;
+ ImGui::ResetMouseDragDelta();
+ }
+ }
+ }
+ ImGui::TreePop();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)");
+ if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)"))
+ {
+ // Select an item type
+ const char* item_names[] =
+ {
+ "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",
+ "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
+ };
+ static int item_type = 4;
+ static bool item_disabled = false;
+ ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
+ ImGui::SameLine();
+ HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
+ ImGui::Checkbox("Item Disabled", &item_disabled);
+
+ // Submit selected item item so we can query their status in the code following it.
+ bool ret = false;
+ static bool b = false;
+ static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
+ static char str[16] = {};
+ if (item_disabled)
+ ImGui::BeginDisabled(true);
+ if (item_type == 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
+ if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); } // Testing button
+ if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)
+ if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); } // Testing checkbox
+ if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); } // Testing basic item
+ if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing)
+ if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); } // Testing +/- buttons on scalar input
+ if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
+ if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
+ if (item_type == 9) { ret = ImGui::Selectable("ITEM: Selectable"); } // Testing selectable item
+ if (item_type == 10){ ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
+ if (item_type == 11){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node
+ if (item_type == 12){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
+ if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
+ if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
+
+ // Display the values of IsItemHovered() and other common item state functions.
+ // Note that the ImGuiHoveredFlags_XXX flags can be combined.
+ // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
+ // we query every state in a single call to avoid storing them and to simplify the code.
+ ImGui::BulletText(
+ "Return value = %d\n"
+ "IsItemFocused() = %d\n"
+ "IsItemHovered() = %d\n"
+ "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
+ "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
+ "IsItemHovered(_AllowWhenOverlapped) = %d\n"
+ "IsItemHovered(_AllowWhenDisabled) = %d\n"
+ "IsItemHovered(_RectOnly) = %d\n"
+ "IsItemActive() = %d\n"
+ "IsItemEdited() = %d\n"
+ "IsItemActivated() = %d\n"
+ "IsItemDeactivated() = %d\n"
+ "IsItemDeactivatedAfterEdit() = %d\n"
+ "IsItemVisible() = %d\n"
+ "IsItemClicked() = %d\n"
+ "IsItemToggledOpen() = %d\n"
+ "GetItemRectMin() = (%.1f, %.1f)\n"
+ "GetItemRectMax() = (%.1f, %.1f)\n"
+ "GetItemRectSize() = (%.1f, %.1f)",
+ ret,
+ ImGui::IsItemFocused(),
+ ImGui::IsItemHovered(),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled),
+ ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
+ ImGui::IsItemActive(),
+ ImGui::IsItemEdited(),
+ ImGui::IsItemActivated(),
+ ImGui::IsItemDeactivated(),
+ ImGui::IsItemDeactivatedAfterEdit(),
+ ImGui::IsItemVisible(),
+ ImGui::IsItemClicked(),
+ ImGui::IsItemToggledOpen(),
+ ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
+ ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
+ ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
+ );
+
+ if (item_disabled)
+ ImGui::EndDisabled();
+
+ char buf[1] = "";
+ ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly);
+ ImGui::SameLine();
+ HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status.");
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Widgets/Querying Window Status (Focused,Hovered etc.)");
+ if (ImGui::TreeNode("Querying Window Status (Focused/Hovered etc.)"))
+ {
+ static bool embed_all_inside_a_child_window = false;
+ ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window);
+ if (embed_all_inside_a_child_window)
+ ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true);
+
+ // Testing IsWindowFocused() function with its various flags.
+ ImGui::BulletText(
+ "IsWindowFocused() = %d\n"
+ "IsWindowFocused(_ChildWindows) = %d\n"
+ "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n"
+ "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
+ "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
+ "IsWindowFocused(_RootWindow) = %d\n"
+ "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n"
+ "IsWindowFocused(_AnyWindow) = %d\n",
+ ImGui::IsWindowFocused(),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
+
+ // Testing IsWindowHovered() function with its various flags.
+ ImGui::BulletText(
+ "IsWindowHovered() = %d\n"
+ "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
+ "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
+ "IsWindowHovered(_ChildWindows) = %d\n"
+ "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n"
+ "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
+ "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
+ "IsWindowHovered(_RootWindow) = %d\n"
+ "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n"
+ "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
+ "IsWindowHovered(_AnyWindow) = %d\n",
+ ImGui::IsWindowHovered(),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
+
+ ImGui::BeginChild("child", ImVec2(0, 50), true);
+ ImGui::Text("This is another child window for testing the _ChildWindows flag.");
+ ImGui::EndChild();
+ if (embed_all_inside_a_child_window)
+ ImGui::EndChild();
+
+ // Calling IsItemHovered() after begin returns the hovered status of the title bar.
+ // This is useful in particular if you want to create a context menu associated to the title bar of a window.
+ static bool test_window = false;
+ ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
+ if (test_window)
+ {
+ ImGui::Begin("Title bar Hovered/Active tests", &test_window);
+ if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
+ {
+ if (ImGui::MenuItem("Close")) { test_window = false; }
+ ImGui::EndPopup();
+ }
+ ImGui::Text(
+ "IsItemHovered() after begin = %d (== is title bar hovered)\n"
+ "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
+ ImGui::IsItemHovered(), ImGui::IsItemActive());
+ ImGui::End();
+ }
+
+ ImGui::TreePop();
+ }
+
+ // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd:
+ // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space)
+ if (disable_all)
+ ImGui::EndDisabled();
+
+ IMGUI_DEMO_MARKER("Widgets/Disable Block");
+ if (ImGui::TreeNode("Disable block"))
+ {
+ ImGui::Checkbox("Disable entire section above", &disable_all);
+ ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section.");
+ ImGui::TreePop();
+ }
+}
+
+static void ShowDemoWindowLayout()
+{
+ IMGUI_DEMO_MARKER("Layout");
+ if (!ImGui::CollapsingHeader("Layout & Scrolling"))
+ return;
+
+ IMGUI_DEMO_MARKER("Layout/Child windows");
+ if (ImGui::TreeNode("Child windows"))
+ {
+ HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
+ static bool disable_mouse_wheel = false;
+ static bool disable_menu = false;
+ ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
+ ImGui::Checkbox("Disable Menu", &disable_menu);
+
+ // Child 1: no border, enable horizontal scrollbar
+ {
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
+ if (disable_mouse_wheel)
+ window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
+ ImGui::BeginChild("ChildL", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 260), false, window_flags);
+ for (int i = 0; i < 100; i++)
+ ImGui::Text("%04d: scrollable region", i);
+ ImGui::EndChild();
+ }
+
+ ImGui::SameLine();
+
+ // Child 2: rounded border
+ {
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
+ if (disable_mouse_wheel)
+ window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
+ if (!disable_menu)
+ window_flags |= ImGuiWindowFlags_MenuBar;
+ ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
+ ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
+ if (!disable_menu && ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("Menu"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+ if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ char buf[32];
+ sprintf(buf, "%03d", i);
+ ImGui::TableNextColumn();
+ ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
+ }
+ ImGui::EndTable();
+ }
+ ImGui::EndChild();
+ ImGui::PopStyleVar();
+ }
+
+ ImGui::Separator();
+
+ // Demonstrate a few extra things
+ // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
+ // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
+ // You can also call SetNextWindowPos() to position the child window. The parent window will effectively
+ // layout from this position.
+ // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
+ // the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
+ {
+ static int offset_x = 0;
+ ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
+ ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
+
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
+ ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
+ ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
+ for (int n = 0; n < 50; n++)
+ ImGui::Text("Some test %d", n);
+ ImGui::EndChild();
+ bool child_is_hovered = ImGui::IsItemHovered();
+ ImVec2 child_rect_min = ImGui::GetItemRectMin();
+ ImVec2 child_rect_max = ImGui::GetItemRectMax();
+ ImGui::PopStyleColor();
+ ImGui::Text("Hovered: %d", child_is_hovered);
+ ImGui::Text("Rect of child window is: (%.0f,%.0f) (%.0f,%.0f)", child_rect_min.x, child_rect_min.y, child_rect_max.x, child_rect_max.y);
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Layout/Widgets Width");
+ if (ImGui::TreeNode("Widgets Width"))
+ {
+ static float f = 0.0f;
+ static bool show_indented_items = true;
+ ImGui::Checkbox("Show indented items", &show_indented_items);
+
+ // Use SetNextItemWidth() to set the width of a single upcoming item.
+ // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
+ // In real code use you'll probably want to choose width values that are proportional to your font size
+ // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
+
+ ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
+ ImGui::SameLine(); HelpMarker("Fixed width.");
+ ImGui::PushItemWidth(100);
+ ImGui::DragFloat("float##1b", &f);
+ if (show_indented_items)
+ {
+ ImGui::Indent();
+ ImGui::DragFloat("float (indented)##1b", &f);
+ ImGui::Unindent();
+ }
+ ImGui::PopItemWidth();
+
+ ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
+ ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
+ ImGui::PushItemWidth(-100);
+ ImGui::DragFloat("float##2a", &f);
+ if (show_indented_items)
+ {
+ ImGui::Indent();
+ ImGui::DragFloat("float (indented)##2b", &f);
+ ImGui::Unindent();
+ }
+ ImGui::PopItemWidth();
+
+ ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
+ ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
+ ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
+ ImGui::DragFloat("float##3a", &f);
+ if (show_indented_items)
+ {
+ ImGui::Indent();
+ ImGui::DragFloat("float (indented)##3b", &f);
+ ImGui::Unindent();
+ }
+ ImGui::PopItemWidth();
+
+ ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
+ ImGui::SameLine(); HelpMarker("Align to right edge minus half");
+ ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
+ ImGui::DragFloat("float##4a", &f);
+ if (show_indented_items)
+ {
+ ImGui::Indent();
+ ImGui::DragFloat("float (indented)##4b", &f);
+ ImGui::Unindent();
+ }
+ ImGui::PopItemWidth();
+
+ // Demonstrate using PushItemWidth to surround three items.
+ // Calling SetNextItemWidth() before each of them would have the same effect.
+ ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)");
+ ImGui::SameLine(); HelpMarker("Align to right edge");
+ ImGui::PushItemWidth(-FLT_MIN);
+ ImGui::DragFloat("##float5a", &f);
+ if (show_indented_items)
+ {
+ ImGui::Indent();
+ ImGui::DragFloat("float (indented)##5b", &f);
+ ImGui::Unindent();
+ }
+ ImGui::PopItemWidth();
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout");
+ if (ImGui::TreeNode("Basic Horizontal Layout"))
+ {
+ ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
+
+ // Text
+ IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine");
+ ImGui::Text("Two items: Hello"); ImGui::SameLine();
+ ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
+
+ // Adjust spacing
+ ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
+ ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
+
+ // Button
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("Normal buttons"); ImGui::SameLine();
+ ImGui::Button("Banana"); ImGui::SameLine();
+ ImGui::Button("Apple"); ImGui::SameLine();
+ ImGui::Button("Corniflower");
+
+ // Button
+ ImGui::Text("Small buttons"); ImGui::SameLine();
+ ImGui::SmallButton("Like this one"); ImGui::SameLine();
+ ImGui::Text("can fit within a text block.");
+
+ // Aligned to arbitrary position. Easy/cheap column.
+ IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (with offset)");
+ ImGui::Text("Aligned");
+ ImGui::SameLine(150); ImGui::Text("x=150");
+ ImGui::SameLine(300); ImGui::Text("x=300");
+ ImGui::Text("Aligned");
+ ImGui::SameLine(150); ImGui::SmallButton("x=150");
+ ImGui::SameLine(300); ImGui::SmallButton("x=300");
+
+ // Checkbox
+ IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (more)");
+ static bool c1 = false, c2 = false, c3 = false, c4 = false;
+ ImGui::Checkbox("My", &c1); ImGui::SameLine();
+ ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
+ ImGui::Checkbox("Is", &c3); ImGui::SameLine();
+ ImGui::Checkbox("Rich", &c4);
+
+ // Various
+ static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
+ ImGui::PushItemWidth(80);
+ const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
+ static int item = -1;
+ ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
+ ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
+ ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
+ ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
+ ImGui::PopItemWidth();
+
+ ImGui::PushItemWidth(80);
+ ImGui::Text("Lists:");
+ static int selection[4] = { 0, 1, 2, 3 };
+ for (int i = 0; i < 4; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::PushID(i);
+ ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
+ ImGui::PopID();
+ //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
+ }
+ ImGui::PopItemWidth();
+
+ // Dummy
+ IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Dummy");
+ ImVec2 button_sz(40, 40);
+ ImGui::Button("A", button_sz); ImGui::SameLine();
+ ImGui::Dummy(button_sz); ImGui::SameLine();
+ ImGui::Button("B", button_sz);
+
+ // Manually wrapping
+ // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
+ IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Manual wrapping");
+ ImGui::Text("Manual wrapping:");
+ ImGuiStyle& style = ImGui::GetStyle();
+ int buttons_count = 20;
+ float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
+ for (int n = 0; n < buttons_count; n++)
+ {
+ ImGui::PushID(n);
+ ImGui::Button("Box", button_sz);
+ float last_button_x2 = ImGui::GetItemRectMax().x;
+ float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
+ if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
+ ImGui::SameLine();
+ ImGui::PopID();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Layout/Groups");
+ if (ImGui::TreeNode("Groups"))
+ {
+ HelpMarker(
+ "BeginGroup() basically locks the horizontal position for new line. "
+ "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
+ "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
+ ImGui::BeginGroup();
+ {
+ ImGui::BeginGroup();
+ ImGui::Button("AAA");
+ ImGui::SameLine();
+ ImGui::Button("BBB");
+ ImGui::SameLine();
+ ImGui::BeginGroup();
+ ImGui::Button("CCC");
+ ImGui::Button("DDD");
+ ImGui::EndGroup();
+ ImGui::SameLine();
+ ImGui::Button("EEE");
+ ImGui::EndGroup();
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("First group hovered");
+ }
+ // Capture the group size and create widgets using the same size
+ ImVec2 size = ImGui::GetItemRectSize();
+ const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
+ ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
+
+ ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
+ ImGui::SameLine();
+ ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
+ ImGui::EndGroup();
+ ImGui::SameLine();
+
+ ImGui::Button("LEVERAGE\nBUZZWORD", size);
+ ImGui::SameLine();
+
+ if (ImGui::BeginListBox("List", size))
+ {
+ ImGui::Selectable("Selected", true);
+ ImGui::Selectable("Not Selected", false);
+ ImGui::EndListBox();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Layout/Text Baseline Alignment");
+ if (ImGui::TreeNode("Text Baseline Alignment"))
+ {
+ {
+ ImGui::BulletText("Text baseline:");
+ ImGui::SameLine(); HelpMarker(
+ "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
+ "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
+ ImGui::Indent();
+
+ ImGui::Text("KO Blahblah"); ImGui::SameLine();
+ ImGui::Button("Some framed item"); ImGui::SameLine();
+ HelpMarker("Baseline of button will look misaligned with text..");
+
+ // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
+ // (because we don't know what's coming after the Text() statement, we need to move the text baseline
+ // down by FramePadding.y ahead of time)
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("OK Blahblah"); ImGui::SameLine();
+ ImGui::Button("Some framed item"); ImGui::SameLine();
+ HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
+
+ // SmallButton() uses the same vertical padding as Text
+ ImGui::Button("TEST##1"); ImGui::SameLine();
+ ImGui::Text("TEST"); ImGui::SameLine();
+ ImGui::SmallButton("TEST##2");
+
+ // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
+ ImGui::AlignTextToFramePadding();
+ ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
+ ImGui::Button("Item##1"); ImGui::SameLine();
+ ImGui::Text("Item"); ImGui::SameLine();
+ ImGui::SmallButton("Item##2"); ImGui::SameLine();
+ ImGui::Button("Item##3");
+
+ ImGui::Unindent();
+ }
+
+ ImGui::Spacing();
+
+ {
+ ImGui::BulletText("Multi-line text:");
+ ImGui::Indent();
+ ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("Banana");
+
+ ImGui::Text("Banana"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("One\nTwo\nThree");
+
+ ImGui::Button("HOP##1"); ImGui::SameLine();
+ ImGui::Text("Banana"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("Banana");
+
+ ImGui::Button("HOP##2"); ImGui::SameLine();
+ ImGui::Text("Hello\nWorld"); ImGui::SameLine();
+ ImGui::Text("Banana");
+ ImGui::Unindent();
+ }
+
+ ImGui::Spacing();
+
+ {
+ ImGui::BulletText("Misc items:");
+ ImGui::Indent();
+
+ // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
+ ImGui::Button("80x80", ImVec2(80, 80));
+ ImGui::SameLine();
+ ImGui::Button("50x50", ImVec2(50, 50));
+ ImGui::SameLine();
+ ImGui::Button("Button()");
+ ImGui::SameLine();
+ ImGui::SmallButton("SmallButton()");
+
+ // Tree
+ const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
+ ImGui::Button("Button##1");
+ ImGui::SameLine(0.0f, spacing);
+ if (ImGui::TreeNode("Node##1"))
+ {
+ // Placeholder tree data
+ for (int i = 0; i < 6; i++)
+ ImGui::BulletText("Item %d..", i);
+ ImGui::TreePop();
+ }
+
+ // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
+ // Otherwise you can use SmallButton() (smaller fit).
+ ImGui::AlignTextToFramePadding();
+
+ // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
+ // other contents below the node.
+ bool node_open = ImGui::TreeNode("Node##2");
+ ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
+ if (node_open)
+ {
+ // Placeholder tree data
+ for (int i = 0; i < 6; i++)
+ ImGui::BulletText("Item %d..", i);
+ ImGui::TreePop();
+ }
+
+ // Bullet
+ ImGui::Button("Button##3");
+ ImGui::SameLine(0.0f, spacing);
+ ImGui::BulletText("Bullet text");
+
+ ImGui::AlignTextToFramePadding();
+ ImGui::BulletText("Node");
+ ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
+ ImGui::Unindent();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Layout/Scrolling");
+ if (ImGui::TreeNode("Scrolling"))
+ {
+ // Vertical scroll functions
+ IMGUI_DEMO_MARKER("Layout/Scrolling/Vertical");
+ HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
+
+ static int track_item = 50;
+ static bool enable_track = true;
+ static bool enable_extra_decorations = false;
+ static float scroll_to_off_px = 0.0f;
+ static float scroll_to_pos_px = 200.0f;
+
+ ImGui::Checkbox("Decoration", &enable_extra_decorations);
+
+ ImGui::Checkbox("Track", &enable_track);
+ ImGui::PushItemWidth(100);
+ ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
+
+ bool scroll_to_off = ImGui::Button("Scroll Offset");
+ ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
+
+ bool scroll_to_pos = ImGui::Button("Scroll To Pos");
+ ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
+ ImGui::PopItemWidth();
+
+ if (scroll_to_off || scroll_to_pos)
+ enable_track = false;
+
+ ImGuiStyle& style = ImGui::GetStyle();
+ float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
+ if (child_w < 1.0f)
+ child_w = 1.0f;
+ ImGui::PushID("##VerticalScrolling");
+ for (int i = 0; i < 5; i++)
+ {
+ if (i > 0) ImGui::SameLine();
+ ImGui::BeginGroup();
+ const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
+ ImGui::TextUnformatted(names[i]);
+
+ const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
+ const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
+ const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags);
+ if (ImGui::BeginMenuBar())
+ {
+ ImGui::TextUnformatted("abc");
+ ImGui::EndMenuBar();
+ }
+ if (scroll_to_off)
+ ImGui::SetScrollY(scroll_to_off_px);
+ if (scroll_to_pos)
+ ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
+ if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
+ {
+ for (int item = 0; item < 100; item++)
+ {
+ if (enable_track && item == track_item)
+ {
+ ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
+ ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
+ }
+ else
+ {
+ ImGui::Text("Item %d", item);
+ }
+ }
+ }
+ float scroll_y = ImGui::GetScrollY();
+ float scroll_max_y = ImGui::GetScrollMaxY();
+ ImGui::EndChild();
+ ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
+ ImGui::EndGroup();
+ }
+ ImGui::PopID();
+
+ // Horizontal scroll functions
+ IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal");
+ ImGui::Spacing();
+ HelpMarker(
+ "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
+ "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
+ "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
+ "equivalent SetScrollFromPosY(+1) wouldn't.");
+ ImGui::PushID("##HorizontalScrolling");
+ for (int i = 0; i < 5; i++)
+ {
+ float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
+ ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
+ ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
+ bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags);
+ if (scroll_to_off)
+ ImGui::SetScrollX(scroll_to_off_px);
+ if (scroll_to_pos)
+ ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
+ if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
+ {
+ for (int item = 0; item < 100; item++)
+ {
+ if (item > 0)
+ ImGui::SameLine();
+ if (enable_track && item == track_item)
+ {
+ ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
+ ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
+ }
+ else
+ {
+ ImGui::Text("Item %d", item);
+ }
+ }
+ }
+ float scroll_x = ImGui::GetScrollX();
+ float scroll_max_x = ImGui::GetScrollMaxX();
+ ImGui::EndChild();
+ ImGui::SameLine();
+ const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
+ ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
+ ImGui::Spacing();
+ }
+ ImGui::PopID();
+
+ // Miscellaneous Horizontal Scrolling Demo
+ IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal (more)");
+ HelpMarker(
+ "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
+ "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
+ static int lines = 7;
+ ImGui::SliderInt("Lines", &lines, 1, 15);
+ ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
+ ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
+ ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar);
+ for (int line = 0; line < lines; line++)
+ {
+ // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
+ // If you want to create your own time line for a real application you may be better off manipulating
+ // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
+ // yourself. You may also want to use the lower-level ImDrawList API.
+ int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
+ for (int n = 0; n < num_buttons; n++)
+ {
+ if (n > 0) ImGui::SameLine();
+ ImGui::PushID(n + line * 1000);
+ char num_buf[16];
+ sprintf(num_buf, "%d", n);
+ const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
+ float hue = n * 0.05f;
+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
+ ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
+ ImGui::PopStyleColor(3);
+ ImGui::PopID();
+ }
+ }
+ float scroll_x = ImGui::GetScrollX();
+ float scroll_max_x = ImGui::GetScrollMaxX();
+ ImGui::EndChild();
+ ImGui::PopStyleVar(2);
+ float scroll_x_delta = 0.0f;
+ ImGui::SmallButton("<<");
+ if (ImGui::IsItemActive())
+ scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
+ ImGui::SameLine();
+ ImGui::Text("Scroll from code"); ImGui::SameLine();
+ ImGui::SmallButton(">>");
+ if (ImGui::IsItemActive())
+ scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
+ ImGui::SameLine();
+ ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
+ if (scroll_x_delta != 0.0f)
+ {
+ // Demonstrate a trick: you can use Begin to set yourself in the context of another window
+ // (here we are already out of your child window)
+ ImGui::BeginChild("scrolling");
+ ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
+ ImGui::EndChild();
+ }
+ ImGui::Spacing();
+
+ static bool show_horizontal_contents_size_demo_window = false;
+ ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
+
+ if (show_horizontal_contents_size_demo_window)
+ {
+ static bool show_h_scrollbar = true;
+ static bool show_button = true;
+ static bool show_tree_nodes = true;
+ static bool show_text_wrapped = false;
+ static bool show_columns = true;
+ static bool show_tab_bar = true;
+ static bool show_child = false;
+ static bool explicit_content_size = false;
+ static float contents_size_x = 300.0f;
+ if (explicit_content_size)
+ ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
+ ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
+ IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window");
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
+ HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
+ ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
+ ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten)
+ ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width
+ ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
+ ImGui::Checkbox("Columns", &show_columns); // Will use contents size
+ ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size
+ ImGui::Checkbox("Child", &show_child); // Will grow and use contents size
+ ImGui::Checkbox("Explicit content size", &explicit_content_size);
+ ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
+ if (explicit_content_size)
+ {
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(100);
+ ImGui::DragFloat("##csx", &contents_size_x);
+ ImVec2 p = ImGui::GetCursorScreenPos();
+ ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
+ ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
+ ImGui::Dummy(ImVec2(0, 10));
+ }
+ ImGui::PopStyleVar(2);
+ ImGui::Separator();
+ if (show_button)
+ {
+ ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
+ }
+ if (show_tree_nodes)
+ {
+ bool open = true;
+ if (ImGui::TreeNode("this is a tree node"))
+ {
+ if (ImGui::TreeNode("another one of those tree node..."))
+ {
+ ImGui::Text("Some tree contents");
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::CollapsingHeader("CollapsingHeader", &open);
+ }
+ if (show_text_wrapped)
+ {
+ ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
+ }
+ if (show_columns)
+ {
+ ImGui::Text("Tables:");
+ if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
+ {
+ for (int n = 0; n < 4; n++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
+ }
+ ImGui::EndTable();
+ }
+ ImGui::Text("Columns:");
+ ImGui::Columns(4);
+ for (int n = 0; n < 4; n++)
+ {
+ ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
+ ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ }
+ if (show_tab_bar && ImGui::BeginTabBar("Hello"))
+ {
+ if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
+ if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
+ if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
+ if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
+ ImGui::EndTabBar();
+ }
+ if (show_child)
+ {
+ ImGui::BeginChild("child", ImVec2(0, 0), true);
+ ImGui::EndChild();
+ }
+ ImGui::End();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Layout/Clipping");
+ if (ImGui::TreeNode("Clipping"))
+ {
+ static ImVec2 size(100.0f, 100.0f);
+ static ImVec2 offset(30.0f, 30.0f);
+ ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
+ ImGui::TextWrapped("(Click and drag to scroll)");
+
+ for (int n = 0; n < 3; n++)
+ {
+ if (n > 0)
+ ImGui::SameLine();
+ ImGui::PushID(n);
+ ImGui::BeginGroup(); // Lock X position
+
+ ImGui::InvisibleButton("##empty", size);
+ if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
+ {
+ offset.x += ImGui::GetIO().MouseDelta.x;
+ offset.y += ImGui::GetIO().MouseDelta.y;
+ }
+ const ImVec2 p0 = ImGui::GetItemRectMin();
+ const ImVec2 p1 = ImGui::GetItemRectMax();
+ const char* text_str = "Line 1 hello\nLine 2 clip me!";
+ const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+
+ switch (n)
+ {
+ case 0:
+ HelpMarker(
+ "Using ImGui::PushClipRect():\n"
+ "Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
+ "(use this if you want your clipping rectangle to affect interactions)");
+ ImGui::PushClipRect(p0, p1, true);
+ draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
+ draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
+ ImGui::PopClipRect();
+ break;
+ case 1:
+ HelpMarker(
+ "Using ImDrawList::PushClipRect():\n"
+ "Will alter ImDrawList rendering only.\n"
+ "(use this as a shortcut if you are only using ImDrawList calls)");
+ draw_list->PushClipRect(p0, p1, true);
+ draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
+ draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
+ draw_list->PopClipRect();
+ break;
+ case 2:
+ HelpMarker(
+ "Using ImDrawList::AddText() with a fine ClipRect:\n"
+ "Will alter only this specific ImDrawList::AddText() rendering.\n"
+ "(this is often used internally to avoid altering the clipping rectangle and minimize draw calls)");
+ ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
+ draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
+ draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
+ break;
+ }
+ ImGui::EndGroup();
+ ImGui::PopID();
+ }
+
+ ImGui::TreePop();
+ }
+}
+
+static void ShowDemoWindowPopups()
+{
+ IMGUI_DEMO_MARKER("Popups");
+ if (!ImGui::CollapsingHeader("Popups & Modal windows"))
+ return;
+
+ // The properties of popups windows are:
+ // - They block normal mouse hovering detection outside them. (*)
+ // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
+ // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as
+ // we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup().
+ // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even
+ // when normally blocked by a popup.
+ // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close
+ // popups at any time.
+
+ // Typical use for regular windows:
+ // bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End();
+ // Typical use for popups:
+ // if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
+
+ // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
+ // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
+
+ IMGUI_DEMO_MARKER("Popups/Popups");
+ if (ImGui::TreeNode("Popups"))
+ {
+ ImGui::TextWrapped(
+ "When a popup is active, it inhibits interacting with windows that are behind the popup. "
+ "Clicking outside the popup closes it.");
+
+ static int selected_fish = -1;
+ const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
+ static bool toggles[] = { true, false, false, false, false };
+
+ // Simple selection popup (if you want to show the current selection inside the Button itself,
+ // you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
+ if (ImGui::Button("Select.."))
+ ImGui::OpenPopup("my_select_popup");
+ ImGui::SameLine();
+ ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
+ if (ImGui::BeginPopup("my_select_popup"))
+ {
+ ImGui::Text("Aquarium");
+ ImGui::Separator();
+ for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+ if (ImGui::Selectable(names[i]))
+ selected_fish = i;
+ ImGui::EndPopup();
+ }
+
+ // Showing a menu with toggles
+ if (ImGui::Button("Toggle.."))
+ ImGui::OpenPopup("my_toggle_popup");
+ if (ImGui::BeginPopup("my_toggle_popup"))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+ ImGui::MenuItem(names[i], "", &toggles[i]);
+ if (ImGui::BeginMenu("Sub-menu"))
+ {
+ ImGui::MenuItem("Click me");
+ ImGui::EndMenu();
+ }
+
+ ImGui::Separator();
+ ImGui::Text("Tooltip here");
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("I am a tooltip over a popup");
+
+ if (ImGui::Button("Stacked Popup"))
+ ImGui::OpenPopup("another popup");
+ if (ImGui::BeginPopup("another popup"))
+ {
+ for (int i = 0; i < IM_ARRAYSIZE(names); i++)
+ ImGui::MenuItem(names[i], "", &toggles[i]);
+ if (ImGui::BeginMenu("Sub-menu"))
+ {
+ ImGui::MenuItem("Click me");
+ if (ImGui::Button("Stacked Popup"))
+ ImGui::OpenPopup("another popup");
+ if (ImGui::BeginPopup("another popup"))
+ {
+ ImGui::Text("I am the last one here.");
+ ImGui::EndPopup();
+ }
+ ImGui::EndMenu();
+ }
+ ImGui::EndPopup();
+ }
+ ImGui::EndPopup();
+ }
+
+ // Call the more complete ShowExampleMenuFile which we use in various places of this demo
+ if (ImGui::Button("File Menu.."))
+ ImGui::OpenPopup("my_file_popup");
+ if (ImGui::BeginPopup("my_file_popup"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndPopup();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Popups/Context menus");
+ if (ImGui::TreeNode("Context menus"))
+ {
+ HelpMarker("\"Context\" functions are simple helpers to associate a Popup to a given Item or Window identifier.");
+
+ // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
+ // if (id == 0)
+ // id = GetItemID(); // Use last item id
+ // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
+ // OpenPopup(id);
+ // return BeginPopup(id);
+ // For advanced advanced uses you may want to replicate and customize this code.
+ // See more details in BeginPopupContextItem().
+
+ // Example 1
+ // When used after an item that has an ID (e.g. Button), we can skip providing an ID to BeginPopupContextItem(),
+ // and BeginPopupContextItem() will use the last item ID as the popup ID.
+ {
+ const char* names[5] = { "Label1", "Label2", "Label3", "Label4", "Label5" };
+ for (int n = 0; n < 5; n++)
+ {
+ ImGui::Selectable(names[n]);
+ if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id
+ {
+ ImGui::Text("This a popup for \"%s\"!", names[n]);
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+ if (ImGui::IsItemHovered())
+ ImGui::SetTooltip("Right-click to open popup");
+ }
+ }
+
+ // Example 2
+ // Popup on a Text() element which doesn't have an identifier: we need to provide an identifier to BeginPopupContextItem().
+ // Using an explicit identifier is also convenient if you want to activate the popups from different locations.
+ {
+ HelpMarker("Text() elements don't have stable identifiers so we need to provide one.");
+ static float value = 0.5f;
+ ImGui::Text("Value = %.3f <-- (1) right-click this value", value);
+ if (ImGui::BeginPopupContextItem("my popup"))
+ {
+ if (ImGui::Selectable("Set to zero")) value = 0.0f;
+ if (ImGui::Selectable("Set to PI")) value = 3.1415f;
+ ImGui::SetNextItemWidth(-FLT_MIN);
+ ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
+ ImGui::EndPopup();
+ }
+
+ // We can also use OpenPopupOnItemClick() to toggle the visibility of a given popup.
+ // Here we make it that right-clicking this other text element opens the same popup as above.
+ // The popup itself will be submitted by the code above.
+ ImGui::Text("(2) Or right-click this text");
+ ImGui::OpenPopupOnItemClick("my popup", ImGuiPopupFlags_MouseButtonRight);
+
+ // Back to square one: manually open the same popup.
+ if (ImGui::Button("(3) Or click this button"))
+ ImGui::OpenPopup("my popup");
+ }
+
+ // Example 3
+ // When using BeginPopupContextItem() with an implicit identifier (NULL == use last item ID),
+ // we need to make sure your item identifier is stable.
+ // In this example we showcase altering the item label while preserving its identifier, using the ### operator (see FAQ).
+ {
+ HelpMarker("Showcase using a popup ID linked to item ID, with the item having a changing label + stable ID using the ### operator.");
+ static char name[32] = "Label1";
+ char buf[64];
+ sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
+ ImGui::Button(buf);
+ if (ImGui::BeginPopupContextItem())
+ {
+ ImGui::Text("Edit name:");
+ ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+ ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Popups/Modals");
+ if (ImGui::TreeNode("Modals"))
+ {
+ ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside.");
+
+ if (ImGui::Button("Delete.."))
+ ImGui::OpenPopup("Delete?");
+
+ // Always center this window when appearing
+ ImVec2 center = ImGui::GetMainViewport()->GetCenter();
+ ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
+
+ if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
+ ImGui::Separator();
+
+ //static int unused_i = 0;
+ //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0");
+
+ static bool dont_ask_me_next_time = false;
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
+ ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
+ ImGui::PopStyleVar();
+
+ if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
+ ImGui::SetItemDefaultFocus();
+ ImGui::SameLine();
+ if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
+ ImGui::EndPopup();
+ }
+
+ if (ImGui::Button("Stacked modals.."))
+ ImGui::OpenPopup("Stacked 1");
+ if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
+ {
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ if (ImGui::MenuItem("Some menu item")) {}
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+ ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
+
+ // Testing behavior of widgets stacking their own regular popups over the modal.
+ static int item = 1;
+ static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
+ ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
+ ImGui::ColorEdit4("color", color);
+
+ if (ImGui::Button("Add another modal.."))
+ ImGui::OpenPopup("Stacked 2");
+
+ // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which
+ // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value
+ // of the bool actually doesn't matter here.
+ bool unused_open = true;
+ if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
+ {
+ ImGui::Text("Hello from Stacked The Second!");
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Popups/Menus inside a regular window");
+ if (ImGui::TreeNode("Menus inside a regular window"))
+ {
+ ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
+ ImGui::Separator();
+
+ // Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the
+ // parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block
+ // to make them two different menusets. If we don't, opening any popup above and hovering our menu here would
+ // open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it,
+ // which is the desired behavior for regular menus.
+ ImGui::PushID("foo");
+ ImGui::MenuItem("Menu item", "CTRL+M");
+ if (ImGui::BeginMenu("Menu inside a regular window"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::PopID();
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+}
+
+// Dummy data structure that we use for the Table demo.
+// (pre-C++11 doesn't allow us to instantiate ImVector<MyItem> template if this structure if defined inside the demo function)
+namespace
+{
+// We are passing our own identifier to TableSetupColumn() to facilitate identifying columns in the sorting code.
+// This identifier will be passed down into ImGuiTableSortSpec::ColumnUserID.
+// But it is possible to omit the user id parameter of TableSetupColumn() and just use the column index instead! (ImGuiTableSortSpec::ColumnIndex)
+// If you don't use sorting, you will generally never care about giving column an ID!
+enum MyItemColumnID
+{
+ MyItemColumnID_ID,
+ MyItemColumnID_Name,
+ MyItemColumnID_Action,
+ MyItemColumnID_Quantity,
+ MyItemColumnID_Description
+};
+
+struct MyItem
+{
+ int ID;
+ const char* Name;
+ int Quantity;
+
+ // We have a problem which is affecting _only this demo_ and should not affect your code:
+ // As we don't rely on std:: or other third-party library to compile dear imgui, we only have reliable access to qsort(),
+ // however qsort doesn't allow passing user data to comparing function.
+ // As a workaround, we are storing the sort specs in a static/global for the comparing function to access.
+ // In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global.
+ // We could technically call ImGui::TableGetSortSpecs() in CompareWithSortSpecs(), but considering that this function is called
+ // very often by the sorting algorithm it would be a little wasteful.
+ static const ImGuiTableSortSpecs* s_current_sort_specs;
+
+ // Compare function to be used by qsort()
+ static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
+ {
+ const MyItem* a = (const MyItem*)lhs;
+ const MyItem* b = (const MyItem*)rhs;
+ for (int n = 0; n < s_current_sort_specs->SpecsCount; n++)
+ {
+ // Here we identify columns using the ColumnUserID value that we ourselves passed to TableSetupColumn()
+ // We could also choose to identify columns based on their index (sort_spec->ColumnIndex), which is simpler!
+ const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n];
+ int delta = 0;
+ switch (sort_spec->ColumnUserID)
+ {
+ case MyItemColumnID_ID: delta = (a->ID - b->ID); break;
+ case MyItemColumnID_Name: delta = (strcmp(a->Name, b->Name)); break;
+ case MyItemColumnID_Quantity: delta = (a->Quantity - b->Quantity); break;
+ case MyItemColumnID_Description: delta = (strcmp(a->Name, b->Name)); break;
+ default: IM_ASSERT(0); break;
+ }
+ if (delta > 0)
+ return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1;
+ if (delta < 0)
+ return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
+ }
+
+ // qsort() is instable so always return a way to differenciate items.
+ // Your own compare function may want to avoid fallback on implicit sort specs e.g. a Name compare if it wasn't already part of the sort specs.
+ return (a->ID - b->ID);
+ }
+};
+const ImGuiTableSortSpecs* MyItem::s_current_sort_specs = NULL;
+}
+
+// Make the UI compact because there are so many fields
+static void PushStyleCompact()
+{
+ ImGuiStyle& style = ImGui::GetStyle();
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
+}
+
+static void PopStyleCompact()
+{
+ ImGui::PopStyleVar(2);
+}
+
+// Show a combo box with a choice of sizing policies
+static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
+{
+ struct EnumDesc { ImGuiTableFlags Value; const char* Name; const char* Tooltip; };
+ static const EnumDesc policies[] =
+ {
+ { ImGuiTableFlags_None, "Default", "Use default sizing policy:\n- ImGuiTableFlags_SizingFixedFit if ScrollX is on or if host window has ImGuiWindowFlags_AlwaysAutoResize.\n- ImGuiTableFlags_SizingStretchSame otherwise." },
+ { ImGuiTableFlags_SizingFixedFit, "ImGuiTableFlags_SizingFixedFit", "Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width." },
+ { ImGuiTableFlags_SizingFixedSame, "ImGuiTableFlags_SizingFixedSame", "Columns are all the same width, matching the maximum contents width.\nImplicitly disable ImGuiTableFlags_Resizable and enable ImGuiTableFlags_NoKeepColumnsVisible." },
+ { ImGuiTableFlags_SizingStretchProp, "ImGuiTableFlags_SizingStretchProp", "Columns default to _WidthStretch with weights proportional to their widths." },
+ { ImGuiTableFlags_SizingStretchSame, "ImGuiTableFlags_SizingStretchSame", "Columns default to _WidthStretch with same weights." }
+ };
+ int idx;
+ for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++)
+ if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_))
+ break;
+ const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
+ if (ImGui::BeginCombo("Sizing Policy", preview_text))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(policies); n++)
+ if (ImGui::Selectable(policies[n].Name, idx == n))
+ *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value;
+ ImGui::EndCombo();
+ }
+ ImGui::SameLine();
+ ImGui::TextDisabled("(?)");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
+ for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
+ {
+ ImGui::Separator();
+ ImGui::Text("%s:", policies[m].Name);
+ ImGui::Separator();
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().IndentSpacing * 0.5f);
+ ImGui::TextUnformatted(policies[m].Tooltip);
+ }
+ ImGui::PopTextWrapPos();
+ ImGui::EndTooltip();
+ }
+}
+
+static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
+{
+ ImGui::CheckboxFlags("_Disabled", p_flags, ImGuiTableColumnFlags_Disabled); ImGui::SameLine(); HelpMarker("Master disable flag (also hide from context menu)");
+ ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide);
+ ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort);
+ if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch))
+ *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch);
+ if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed))
+ *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed);
+ ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize);
+ ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder);
+ ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide);
+ ImGui::CheckboxFlags("_NoClip", p_flags, ImGuiTableColumnFlags_NoClip);
+ ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort);
+ ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending);
+ ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending);
+ ImGui::CheckboxFlags("_NoHeaderLabel", p_flags, ImGuiTableColumnFlags_NoHeaderLabel);
+ ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth);
+ ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending);
+ ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending);
+ ImGui::CheckboxFlags("_IndentEnable", p_flags, ImGuiTableColumnFlags_IndentEnable); ImGui::SameLine(); HelpMarker("Default for column 0");
+ ImGui::CheckboxFlags("_IndentDisable", p_flags, ImGuiTableColumnFlags_IndentDisable); ImGui::SameLine(); HelpMarker("Default for column >0");
+}
+
+static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags)
+{
+ ImGui::CheckboxFlags("_IsEnabled", &flags, ImGuiTableColumnFlags_IsEnabled);
+ ImGui::CheckboxFlags("_IsVisible", &flags, ImGuiTableColumnFlags_IsVisible);
+ ImGui::CheckboxFlags("_IsSorted", &flags, ImGuiTableColumnFlags_IsSorted);
+ ImGui::CheckboxFlags("_IsHovered", &flags, ImGuiTableColumnFlags_IsHovered);
+}
+
+static void ShowDemoWindowTables()
+{
+ //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
+ IMGUI_DEMO_MARKER("Tables");
+ if (!ImGui::CollapsingHeader("Tables & Columns"))
+ return;
+
+ // Using those as a base value to create width/height that are factor of the size of our font
+ const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
+ const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
+
+ ImGui::PushID("Tables");
+
+ int open_action = -1;
+ if (ImGui::Button("Open all"))
+ open_action = 1;
+ ImGui::SameLine();
+ if (ImGui::Button("Close all"))
+ open_action = 0;
+ ImGui::SameLine();
+
+ // Options
+ static bool disable_indent = false;
+ ImGui::Checkbox("Disable tree indentation", &disable_indent);
+ ImGui::SameLine();
+ HelpMarker("Disable the indenting of tree nodes so demo tables can use the full window width.");
+ ImGui::Separator();
+ if (disable_indent)
+ ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
+
+ // About Styling of tables
+ // Most settings are configured on a per-table basis via the flags passed to BeginTable() and TableSetupColumns APIs.
+ // There are however a few settings that a shared and part of the ImGuiStyle structure:
+ // style.CellPadding // Padding within each cell
+ // style.Colors[ImGuiCol_TableHeaderBg] // Table header background
+ // style.Colors[ImGuiCol_TableBorderStrong] // Table outer and header borders
+ // style.Colors[ImGuiCol_TableBorderLight] // Table inner borders
+ // style.Colors[ImGuiCol_TableRowBg] // Table row background when ImGuiTableFlags_RowBg is enabled (even rows)
+ // style.Colors[ImGuiCol_TableRowBgAlt] // Table row background when ImGuiTableFlags_RowBg is enabled (odds rows)
+
+ // Demos
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Basic");
+ if (ImGui::TreeNode("Basic"))
+ {
+ // Here we will showcase three different ways to output a table.
+ // They are very simple variations of a same thing!
+
+ // [Method 1] Using TableNextRow() to create a new row, and TableSetColumnIndex() to select the column.
+ // In many situations, this is the most flexible and easy to use pattern.
+ HelpMarker("Using TableNextRow() + calling TableSetColumnIndex() _before_ each cell, in a loop.");
+ if (ImGui::BeginTable("table1", 3))
+ {
+ for (int row = 0; row < 4; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Row %d Column %d", row, column);
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ // [Method 2] Using TableNextColumn() called multiple times, instead of using a for loop + TableSetColumnIndex().
+ // This is generally more convenient when you have code manually submitting the contents of each columns.
+ HelpMarker("Using TableNextRow() + calling TableNextColumn() _before_ each cell, manually.");
+ if (ImGui::BeginTable("table2", 3))
+ {
+ for (int row = 0; row < 4; row++)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::Text("Row %d", row);
+ ImGui::TableNextColumn();
+ ImGui::Text("Some contents");
+ ImGui::TableNextColumn();
+ ImGui::Text("123.456");
+ }
+ ImGui::EndTable();
+ }
+
+ // [Method 3] We call TableNextColumn() _before_ each cell. We never call TableNextRow(),
+ // as TableNextColumn() will automatically wrap around and create new roes as needed.
+ // This is generally more convenient when your cells all contains the same type of data.
+ HelpMarker(
+ "Only using TableNextColumn(), which tends to be convenient for tables where every cells contains the same type of contents.\n"
+ "This is also more similar to the old NextColumn() function of the Columns API, and provided to facilitate the Columns->Tables API transition.");
+ if (ImGui::BeginTable("table3", 3))
+ {
+ for (int item = 0; item < 14; item++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Item %d", item);
+ }
+ ImGui::EndTable();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Borders, background");
+ if (ImGui::TreeNode("Borders, background"))
+ {
+ // Expose a few Borders related flags interactively
+ enum ContentsType { CT_Text, CT_FillButton };
+ static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
+ static bool display_headers = false;
+ static int contents_type = CT_Text;
+
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
+ ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterH");
+ ImGui::Indent();
+
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
+ ImGui::Indent();
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
+ ImGui::Unindent();
+
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
+ ImGui::Indent();
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
+ ImGui::Unindent();
+
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags, ImGuiTableFlags_BordersOuter);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags, ImGuiTableFlags_BordersInner);
+ ImGui::Unindent();
+
+ ImGui::AlignTextToFramePadding(); ImGui::Text("Cell contents:");
+ ImGui::SameLine(); ImGui::RadioButton("Text", &contents_type, CT_Text);
+ ImGui::SameLine(); ImGui::RadioButton("FillButton", &contents_type, CT_FillButton);
+ ImGui::Checkbox("Display headers", &display_headers);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appears in Headers");
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table1", 3, flags))
+ {
+ // Display headers so we can inspect their interaction with borders.
+ // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them too much. See other sections for details)
+ if (display_headers)
+ {
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+ ImGui::TableHeadersRow();
+ }
+
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ char buf[32];
+ sprintf(buf, "Hello %d,%d", column, row);
+ if (contents_type == CT_Text)
+ ImGui::TextUnformatted(buf);
+ else if (contents_type)
+ ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Resizable, stretch");
+ if (ImGui::TreeNode("Resizable, stretch"))
+ {
+ // By default, if we don't enable ScrollX the sizing policy for each columns is "Stretch"
+ // Each columns maintain a sizing weight, and they will occupy all available width.
+ static ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
+ ImGui::SameLine(); HelpMarker("Using the _Resizable flag automatically enables the _BordersInnerV flag as well, this is why the resize borders are still showing when unchecking this.");
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table1", 3, flags))
+ {
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Hello %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Resizable, fixed");
+ if (ImGui::TreeNode("Resizable, fixed"))
+ {
+ // Here we use ImGuiTableFlags_SizingFixedFit (even though _ScrollX is not set)
+ // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small)
+ // If there is not enough available width to fit all columns, they will however be resized down.
+ // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings
+ HelpMarker(
+ "Using _Resizable + _SizingFixedFit flags.\n"
+ "Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n"
+ "Double-click a column border to auto-fit the column to its contents.");
+ PushStyleCompact();
+ static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table1", 3, flags))
+ {
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Hello %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Resizable, mixed");
+ if (ImGui::TreeNode("Resizable, mixed"))
+ {
+ HelpMarker(
+ "Using TableSetupColumn() to alter resizing policy on a per-column basis.\n\n"
+ "When combining Fixed and Stretch columns, generally you only want one, maybe two trailing columns to use _WidthStretch.");
+ static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
+
+ if (ImGui::BeginTable("table1", 3, flags))
+ {
+ ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
+ ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
+ ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthStretch);
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("%s %d,%d", (column == 2) ? "Stretch" : "Fixed", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ if (ImGui::BeginTable("table2", 6, flags))
+ {
+ ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
+ ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
+ ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_DefaultHide);
+ ImGui::TableSetupColumn("DDD", ImGuiTableColumnFlags_WidthStretch);
+ ImGui::TableSetupColumn("EEE", ImGuiTableColumnFlags_WidthStretch);
+ ImGui::TableSetupColumn("FFF", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_DefaultHide);
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 6; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("%s %d,%d", (column >= 3) ? "Stretch" : "Fixed", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Reorderable, hideable, with headers");
+ if (ImGui::TreeNode("Reorderable, hideable, with headers"))
+ {
+ HelpMarker(
+ "Click and drag column headers to reorder columns.\n\n"
+ "Right-click on a header to open a context menu.");
+ static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers)");
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table1", 3, flags))
+ {
+ // Submit columns name with TableSetupColumn() and call TableHeadersRow() to create a row with a header in each column.
+ // (Later we will show how TableSetupColumn() has other uses, optional flags, sizing weight etc.)
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 6; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Hello %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ // Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column)
+ if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f)))
+ {
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 6; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Fixed %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Padding");
+ if (ImGui::TreeNode("Padding"))
+ {
+ // First example: showcase use of padding flags and effect of BorderOuterV/BorderInnerV on X padding.
+ // We don't expose BorderOuterH/BorderInnerH here because they have no effect on X padding.
+ HelpMarker(
+ "We often want outer padding activated when any using features which makes the edges of a column visible:\n"
+ "e.g.:\n"
+ "- BorderOuterV\n"
+ "- any form of row selection\n"
+ "Because of this, activating BorderOuterV sets the default to PadOuterX. Using PadOuterX or NoPadOuterX you can override the default.\n\n"
+ "Actual padding values are using style.CellPadding.\n\n"
+ "In this demo we don't show horizontal borders to emphasis how they don't affect default horizontal padding.");
+
+ static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags1, ImGuiTableFlags_PadOuterX);
+ ImGui::SameLine(); HelpMarker("Enable outer-most padding (default if ImGuiTableFlags_BordersOuterV is set)");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags1, ImGuiTableFlags_NoPadOuterX);
+ ImGui::SameLine(); HelpMarker("Disable outer-most padding (default if ImGuiTableFlags_BordersOuterV is not set)");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags1, ImGuiTableFlags_NoPadInnerX);
+ ImGui::SameLine(); HelpMarker("Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off)");
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags1, ImGuiTableFlags_BordersOuterV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags1, ImGuiTableFlags_BordersInnerV);
+ static bool show_headers = false;
+ ImGui::Checkbox("show_headers", &show_headers);
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table_padding", 3, flags1))
+ {
+ if (show_headers)
+ {
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+ ImGui::TableHeadersRow();
+ }
+
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ if (row == 0)
+ {
+ ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
+ }
+ else
+ {
+ char buf[32];
+ sprintf(buf, "Hello %d,%d", column, row);
+ ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
+ }
+ //if (ImGui::TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered)
+ // ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, IM_COL32(0, 100, 0, 255));
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ // Second example: set style.CellPadding to (0.0) or a custom value.
+ // FIXME-TABLE: Vertical border effectively not displayed the same way as horizontal one...
+ HelpMarker("Setting style.CellPadding to (0,0) or a custom value.");
+ static ImGuiTableFlags flags2 = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
+ static ImVec2 cell_padding(0.0f, 0.0f);
+ static bool show_widget_frame_bg = true;
+
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags2, ImGuiTableFlags_Borders);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags2, ImGuiTableFlags_BordersH);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags2, ImGuiTableFlags_BordersV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags2, ImGuiTableFlags_BordersInner);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags2, ImGuiTableFlags_BordersOuter);
+ ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags2, ImGuiTableFlags_RowBg);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags2, ImGuiTableFlags_Resizable);
+ ImGui::Checkbox("show_widget_frame_bg", &show_widget_frame_bg);
+ ImGui::SliderFloat2("CellPadding", &cell_padding.x, 0.0f, 10.0f, "%.0f");
+ PopStyleCompact();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cell_padding);
+ if (ImGui::BeginTable("table_padding_2", 3, flags2))
+ {
+ static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells
+ static bool init = true;
+ if (!show_widget_frame_bg)
+ ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
+ for (int cell = 0; cell < 3 * 5; cell++)
+ {
+ ImGui::TableNextColumn();
+ if (init)
+ strcpy(text_bufs[cell], "edit me");
+ ImGui::SetNextItemWidth(-FLT_MIN);
+ ImGui::PushID(cell);
+ ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell]));
+ ImGui::PopID();
+ }
+ if (!show_widget_frame_bg)
+ ImGui::PopStyleColor();
+ init = false;
+ ImGui::EndTable();
+ }
+ ImGui::PopStyleVar();
+
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Explicit widths");
+ if (ImGui::TreeNode("Sizing policies"))
+ {
+ static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags1, ImGuiTableFlags_NoHostExtendX);
+ PopStyleCompact();
+
+ static ImGuiTableFlags sizing_policy_flags[4] = { ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp, ImGuiTableFlags_SizingStretchSame };
+ for (int table_n = 0; table_n < 4; table_n++)
+ {
+ ImGui::PushID(table_n);
+ ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 30);
+ EditTableSizingFlags(&sizing_policy_flags[table_n]);
+
+ // To make it easier to understand the different sizing policy,
+ // For each policy: we display one table where the columns have equal contents width, and one where the columns have different contents width.
+ if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1))
+ {
+ for (int row = 0; row < 3; row++)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn(); ImGui::Text("Oh dear");
+ ImGui::TableNextColumn(); ImGui::Text("Oh dear");
+ ImGui::TableNextColumn(); ImGui::Text("Oh dear");
+ }
+ ImGui::EndTable();
+ }
+ if (ImGui::BeginTable("table2", 3, sizing_policy_flags[table_n] | flags1))
+ {
+ for (int row = 0; row < 3; row++)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn(); ImGui::Text("AAAA");
+ ImGui::TableNextColumn(); ImGui::Text("BBBBBBBB");
+ ImGui::TableNextColumn(); ImGui::Text("CCCCCCCCCCCC");
+ }
+ ImGui::EndTable();
+ }
+ ImGui::PopID();
+ }
+
+ ImGui::Spacing();
+ ImGui::TextUnformatted("Advanced");
+ ImGui::SameLine();
+ HelpMarker("This section allows you to interact and see the effect of various sizing policies depending on whether Scroll is enabled and the contents of your columns.");
+
+ enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
+ static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
+ static int contents_type = CT_ShowWidth;
+ static int column_count = 3;
+
+ PushStyleCompact();
+ ImGui::PushID("Advanced");
+ ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
+ EditTableSizingFlags(&flags);
+ ImGui::Combo("Contents", &contents_type, "Show width\0Short Text\0Long Text\0Button\0Fill Button\0InputText\0");
+ if (contents_type == CT_FillButton)
+ {
+ ImGui::SameLine();
+ HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width.");
+ }
+ ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
+ ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
+ ImGui::PopItemWidth();
+ ImGui::PopID();
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table2", column_count, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 7)))
+ {
+ for (int cell = 0; cell < 10 * column_count; cell++)
+ {
+ ImGui::TableNextColumn();
+ int column = ImGui::TableGetColumnIndex();
+ int row = ImGui::TableGetRowIndex();
+
+ ImGui::PushID(cell);
+ char label[32];
+ static char text_buf[32] = "";
+ sprintf(label, "Hello %d,%d", column, row);
+ switch (contents_type)
+ {
+ case CT_ShortText: ImGui::TextUnformatted(label); break;
+ case CT_LongText: ImGui::Text("Some %s text %d,%d\nOver two lines..", column == 0 ? "long" : "longeeer", column, row); break;
+ case CT_ShowWidth: ImGui::Text("W: %.1f", ImGui::GetContentRegionAvail().x); break;
+ case CT_Button: ImGui::Button(label); break;
+ case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
+ case CT_InputText: ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
+ }
+ ImGui::PopID();
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Vertical scrolling, with clipping");
+ if (ImGui::TreeNode("Vertical scrolling, with clipping"))
+ {
+ HelpMarker("Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\nWe also demonstrate using ImGuiListClipper to virtualize the submission of many items.");
+ static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
+
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
+ PopStyleCompact();
+
+ // When using ScrollX or ScrollY we need to specify a size for our table container!
+ // Otherwise by default the table will fit all available space, like a BeginChild() call.
+ ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
+ if (ImGui::BeginTable("table_scrolly", 3, flags, outer_size))
+ {
+ ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
+ ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
+ ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
+ ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
+ ImGui::TableHeadersRow();
+
+ // Demonstrate using clipper for large vertical lists
+ ImGuiListClipper clipper;
+ clipper.Begin(1000);
+ while (clipper.Step())
+ {
+ for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Hello %d,%d", column, row);
+ }
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Horizontal scrolling");
+ if (ImGui::TreeNode("Horizontal scrolling"))
+ {
+ HelpMarker(
+ "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, "
+ "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n"
+ "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX,"
+ "because the container window won't automatically extend vertically to fix contents (this may be improved in future versions).");
+ static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
+ static int freeze_cols = 1;
+ static int freeze_rows = 1;
+
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
+ ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
+ ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
+ ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
+ ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
+ PopStyleCompact();
+
+ // When using ScrollX or ScrollY we need to specify a size for our table container!
+ // Otherwise by default the table will fit all available space, like a BeginChild() call.
+ ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
+ if (ImGui::BeginTable("table_scrollx", 7, flags, outer_size))
+ {
+ ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
+ ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of TableSetupScrollFreeze()
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+ ImGui::TableSetupColumn("Four");
+ ImGui::TableSetupColumn("Five");
+ ImGui::TableSetupColumn("Six");
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 20; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 7; column++)
+ {
+ // Both TableNextColumn() and TableSetColumnIndex() return true when a column is visible or performing width measurement.
+ // Because here we know that:
+ // - A) all our columns are contributing the same to row height
+ // - B) column 0 is always visible,
+ // We only always submit this one column and can skip others.
+ // More advanced per-column clipping behaviors may benefit from polling the status flags via TableGetColumnFlags().
+ if (!ImGui::TableSetColumnIndex(column) && column > 0)
+ continue;
+ if (column == 0)
+ ImGui::Text("Line %d", row);
+ else
+ ImGui::Text("Hello world %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ ImGui::Spacing();
+ ImGui::TextUnformatted("Stretch + ScrollX");
+ ImGui::SameLine();
+ HelpMarker(
+ "Showcase using Stretch columns + ScrollX together: "
+ "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
+ "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
+ static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
+ static float inner_width = 1000.0f;
+ PushStyleCompact();
+ ImGui::PushID("flags3");
+ ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
+ ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
+ ImGui::PopItemWidth();
+ ImGui::PopID();
+ PopStyleCompact();
+ if (ImGui::BeginTable("table2", 7, flags2, outer_size, inner_width))
+ {
+ for (int cell = 0; cell < 20 * 7; cell++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Hello world %d,%d", ImGui::TableGetColumnIndex(), ImGui::TableGetRowIndex());
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Columns flags");
+ if (ImGui::TreeNode("Columns flags"))
+ {
+ // Create a first table just to show all the options/flags we want to make visible in our example!
+ const int column_count = 3;
+ const char* column_names[column_count] = { "One", "Two", "Three" };
+ static ImGuiTableColumnFlags column_flags[column_count] = { ImGuiTableColumnFlags_DefaultSort, ImGuiTableColumnFlags_None, ImGuiTableColumnFlags_DefaultHide };
+ static ImGuiTableColumnFlags column_flags_out[column_count] = { 0, 0, 0 }; // Output from TableGetColumnFlags()
+
+ if (ImGui::BeginTable("table_columns_flags_checkboxes", column_count, ImGuiTableFlags_None))
+ {
+ PushStyleCompact();
+ for (int column = 0; column < column_count; column++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::PushID(column);
+ ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation
+ ImGui::Text("'%s'", column_names[column]);
+ ImGui::Spacing();
+ ImGui::Text("Input flags:");
+ EditTableColumnsFlags(&column_flags[column]);
+ ImGui::Spacing();
+ ImGui::Text("Output flags:");
+ ShowTableColumnsStatusFlags(column_flags_out[column]);
+ ImGui::PopID();
+ }
+ PopStyleCompact();
+ ImGui::EndTable();
+ }
+
+ // Create the real table we care about for the example!
+ // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in
+ // a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down)
+ const ImGuiTableFlags flags
+ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
+ | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
+ | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable;
+ ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 9);
+ if (ImGui::BeginTable("table_columns_flags", column_count, flags, outer_size))
+ {
+ for (int column = 0; column < column_count; column++)
+ ImGui::TableSetupColumn(column_names[column], column_flags[column]);
+ ImGui::TableHeadersRow();
+ for (int column = 0; column < column_count; column++)
+ column_flags_out[column] = ImGui::TableGetColumnFlags(column);
+ float indent_step = (float)((int)TEXT_BASE_WIDTH / 2);
+ for (int row = 0; row < 8; row++)
+ {
+ ImGui::Indent(indent_step); // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags.
+ ImGui::TableNextRow();
+ for (int column = 0; column < column_count; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("%s %s", (column == 0) ? "Indented" : "Hello", ImGui::TableGetColumnName(column));
+ }
+ }
+ ImGui::Unindent(indent_step * 8.0f);
+
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Columns widths");
+ if (ImGui::TreeNode("Columns widths"))
+ {
+ HelpMarker("Using TableSetupColumn() to setup default width.");
+
+ static ImGuiTableFlags flags1 = ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBodyUntilResize;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags1, ImGuiTableFlags_NoBordersInBodyUntilResize);
+ PopStyleCompact();
+ if (ImGui::BeginTable("table1", 3, flags1))
+ {
+ // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
+ ImGui::TableSetupColumn("one", ImGuiTableColumnFlags_WidthFixed, 100.0f); // Default to 100.0f
+ ImGui::TableSetupColumn("two", ImGuiTableColumnFlags_WidthFixed, 200.0f); // Default to 200.0f
+ ImGui::TableSetupColumn("three", ImGuiTableColumnFlags_WidthFixed); // Default to auto
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 4; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ if (row == 0)
+ ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
+ else
+ ImGui::Text("Hello %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ HelpMarker("Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, fixed columns with set width may still be shrunk down if there's not enough space in the host.");
+
+ static ImGuiTableFlags flags2 = ImGuiTableFlags_None;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags2, ImGuiTableFlags_NoKeepColumnsVisible);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags2, ImGuiTableFlags_BordersInnerV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags2, ImGuiTableFlags_BordersOuterV);
+ PopStyleCompact();
+ if (ImGui::BeginTable("table2", 4, flags2))
+ {
+ // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
+ ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
+ ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
+ ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f);
+ ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 4; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ if (row == 0)
+ ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
+ else
+ ImGui::Text("Hello %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Nested tables");
+ if (ImGui::TreeNode("Nested tables"))
+ {
+ HelpMarker("This demonstrate embedding a table into another table cell.");
+
+ if (ImGui::BeginTable("table_nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
+ {
+ ImGui::TableSetupColumn("A0");
+ ImGui::TableSetupColumn("A1");
+ ImGui::TableHeadersRow();
+
+ ImGui::TableNextColumn();
+ ImGui::Text("A0 Row 0");
+ {
+ float rows_height = TEXT_BASE_HEIGHT * 2;
+ if (ImGui::BeginTable("table_nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
+ {
+ ImGui::TableSetupColumn("B0");
+ ImGui::TableSetupColumn("B1");
+ ImGui::TableHeadersRow();
+
+ ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
+ ImGui::TableNextColumn();
+ ImGui::Text("B0 Row 0");
+ ImGui::TableNextColumn();
+ ImGui::Text("B1 Row 0");
+ ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
+ ImGui::TableNextColumn();
+ ImGui::Text("B0 Row 1");
+ ImGui::TableNextColumn();
+ ImGui::Text("B1 Row 1");
+
+ ImGui::EndTable();
+ }
+ }
+ ImGui::TableNextColumn(); ImGui::Text("A1 Row 0");
+ ImGui::TableNextColumn(); ImGui::Text("A0 Row 1");
+ ImGui::TableNextColumn(); ImGui::Text("A1 Row 1");
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Row height");
+ if (ImGui::TreeNode("Row height"))
+ {
+ HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would requires a unique clipping rectangle per row.");
+ if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerV))
+ {
+ for (int row = 0; row < 10; row++)
+ {
+ float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row);
+ ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height);
+ ImGui::TableNextColumn();
+ ImGui::Text("min_row_height = %.2f", min_row_height);
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Outer size");
+ if (ImGui::TreeNode("Outer size"))
+ {
+ // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY
+ // Important to that note how the two flags have slightly different behaviors!
+ ImGui::Text("Using NoHostExtendX and NoHostExtendY:");
+ PushStyleCompact();
+ static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX;
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
+ ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
+ ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.");
+ PopStyleCompact();
+
+ ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f);
+ if (ImGui::BeginTable("table1", 3, flags, outer_size))
+ {
+ for (int row = 0; row < 10; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Cell %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::SameLine();
+ ImGui::Text("Hello!");
+
+ ImGui::Spacing();
+
+ ImGui::Text("Using explicit size:");
+ if (ImGui::BeginTable("table2", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
+ {
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Cell %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::SameLine();
+ if (ImGui::BeginTable("table3", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
+ {
+ for (int row = 0; row < 3; row++)
+ {
+ ImGui::TableNextRow(0, TEXT_BASE_HEIGHT * 1.5f);
+ for (int column = 0; column < 3; column++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Cell %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Background color");
+ if (ImGui::TreeNode("Background color"))
+ {
+ static ImGuiTableFlags flags = ImGuiTableFlags_RowBg;
+ static int row_bg_type = 1;
+ static int row_bg_target = 1;
+ static int cell_bg_type = 1;
+
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
+ ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
+ ImGui::SameLine(); HelpMarker("ImGuiTableFlags_RowBg automatically sets RowBg0 to alternative colors pulled from the Style.");
+ ImGui::Combo("row bg type", (int*)&row_bg_type, "None\0Red\0Gradient\0");
+ ImGui::Combo("row bg target", (int*)&row_bg_target, "RowBg0\0RowBg1\0"); ImGui::SameLine(); HelpMarker("Target RowBg0 to override the alternating odd/even colors,\nTarget RowBg1 to blend with them.");
+ ImGui::Combo("cell bg type", (int*)&cell_bg_type, "None\0Blue\0"); ImGui::SameLine(); HelpMarker("We are colorizing cells to B1->C2 here.");
+ IM_ASSERT(row_bg_type >= 0 && row_bg_type <= 2);
+ IM_ASSERT(row_bg_target >= 0 && row_bg_target <= 1);
+ IM_ASSERT(cell_bg_type >= 0 && cell_bg_type <= 1);
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table1", 5, flags))
+ {
+ for (int row = 0; row < 6; row++)
+ {
+ ImGui::TableNextRow();
+
+ // Demonstrate setting a row background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBgX, ...)'
+ // We use a transparent color so we can see the one behind in case our target is RowBg1 and RowBg0 was already targeted by the ImGuiTableFlags_RowBg flag.
+ if (row_bg_type != 0)
+ {
+ ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.65f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.65f)); // Flat or Gradient?
+ ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color);
+ }
+
+ // Fill cells
+ for (int column = 0; column < 5; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("%c%c", 'A' + row, '0' + column);
+
+ // Change background of Cells B1->C2
+ // Demonstrate setting a cell background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ...)'
+ // (the CellBg color will be blended over the RowBg and ColumnBg colors)
+ // We can also pass a column number as a third parameter to TableSetBgColor() and do this outside the column loop.
+ if (row >= 1 && row <= 2 && column >= 1 && column <= 2 && cell_bg_type == 1)
+ {
+ ImU32 cell_bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 0.65f));
+ ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, cell_bg_color);
+ }
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Tree view");
+ if (ImGui::TreeNode("Tree view"))
+ {
+ static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
+
+ if (ImGui::BeginTable("3ways", 3, flags))
+ {
+ // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
+ ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
+ ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f);
+ ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f);
+ ImGui::TableHeadersRow();
+
+ // Simple storage to output a dummy file-system.
+ struct MyTreeNode
+ {
+ const char* Name;
+ const char* Type;
+ int Size;
+ int ChildIdx;
+ int ChildCount;
+ static void DisplayNode(const MyTreeNode* node, const MyTreeNode* all_nodes)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ const bool is_folder = (node->ChildCount > 0);
+ if (is_folder)
+ {
+ bool open = ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_SpanFullWidth);
+ ImGui::TableNextColumn();
+ ImGui::TextDisabled("--");
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted(node->Type);
+ if (open)
+ {
+ for (int child_n = 0; child_n < node->ChildCount; child_n++)
+ DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes);
+ ImGui::TreePop();
+ }
+ }
+ else
+ {
+ ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth);
+ ImGui::TableNextColumn();
+ ImGui::Text("%d", node->Size);
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted(node->Type);
+ }
+ }
+ };
+ static const MyTreeNode nodes[] =
+ {
+ { "Root", "Folder", -1, 1, 3 }, // 0
+ { "Music", "Folder", -1, 4, 2 }, // 1
+ { "Textures", "Folder", -1, 6, 3 }, // 2
+ { "desktop.ini", "System file", 1024, -1,-1 }, // 3
+ { "File1_a.wav", "Audio file", 123000, -1,-1 }, // 4
+ { "File1_b.wav", "Audio file", 456000, -1,-1 }, // 5
+ { "Image001.png", "Image file", 203128, -1,-1 }, // 6
+ { "Copy of Image001.png", "Image file", 203256, -1,-1 }, // 7
+ { "Copy of Image001 (Final2).png","Image file", 203512, -1,-1 }, // 8
+ };
+
+ MyTreeNode::DisplayNode(&nodes[0], nodes);
+
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Item width");
+ if (ImGui::TreeNode("Item width"))
+ {
+ HelpMarker(
+ "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n"
+ "Note that on auto-resizing non-resizable fixed columns, querying the content width for e.g. right-alignment doesn't make sense.");
+ if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders))
+ {
+ ImGui::TableSetupColumn("small");
+ ImGui::TableSetupColumn("half");
+ ImGui::TableSetupColumn("right-align");
+ ImGui::TableHeadersRow();
+
+ for (int row = 0; row < 3; row++)
+ {
+ ImGui::TableNextRow();
+ if (row == 0)
+ {
+ // Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
+ ImGui::TableSetColumnIndex(0);
+ ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
+ ImGui::TableSetColumnIndex(1);
+ ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
+ ImGui::TableSetColumnIndex(2);
+ ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
+ }
+
+ // Draw our contents
+ static float dummy_f = 0.0f;
+ ImGui::PushID(row);
+ ImGui::TableSetColumnIndex(0);
+ ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
+ ImGui::TableSetColumnIndex(1);
+ ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
+ ImGui::TableSetColumnIndex(2);
+ ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f);
+ ImGui::PopID();
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ // Demonstrate using TableHeader() calls instead of TableHeadersRow()
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Custom headers");
+ if (ImGui::TreeNode("Custom headers"))
+ {
+ const int COLUMNS_COUNT = 3;
+ if (ImGui::BeginTable("table_custom_headers", COLUMNS_COUNT, ImGuiTableFlags_Borders | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
+ {
+ ImGui::TableSetupColumn("Apricot");
+ ImGui::TableSetupColumn("Banana");
+ ImGui::TableSetupColumn("Cherry");
+
+ // Dummy entire-column selection storage
+ // FIXME: It would be nice to actually demonstrate full-featured selection using those checkbox.
+ static bool column_selected[3] = {};
+
+ // Instead of calling TableHeadersRow() we'll submit custom headers ourselves
+ ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
+ for (int column = 0; column < COLUMNS_COUNT; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn()
+ ImGui::PushID(column);
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
+ ImGui::Checkbox("##checkall", &column_selected[column]);
+ ImGui::PopStyleVar();
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
+ ImGui::TableHeader(column_name);
+ ImGui::PopID();
+ }
+
+ for (int row = 0; row < 5; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < 3; column++)
+ {
+ char buf[32];
+ sprintf(buf, "Cell %d,%d", column, row);
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Selectable(buf, column_selected[column]);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ // Demonstrate creating custom context menus inside columns, while playing it nice with context menus provided by TableHeadersRow()/TableHeader()
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Context menus");
+ if (ImGui::TreeNode("Context menus"))
+ {
+ HelpMarker("By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\nUsing ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body.");
+ static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody;
+
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags1, ImGuiTableFlags_ContextMenuInBody);
+ PopStyleCompact();
+
+ // Context Menus: first example
+ // [1.1] Right-click on the TableHeadersRow() line to open the default table context menu.
+ // [1.2] Right-click in columns also open the default table context menu (if ImGuiTableFlags_ContextMenuInBody is set)
+ const int COLUMNS_COUNT = 3;
+ if (ImGui::BeginTable("table_context_menu", COLUMNS_COUNT, flags1))
+ {
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+
+ // [1.1]] Right-click on the TableHeadersRow() line to open the default table context menu.
+ ImGui::TableHeadersRow();
+
+ // Submit dummy contents
+ for (int row = 0; row < 4; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < COLUMNS_COUNT; column++)
+ {
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Cell %d,%d", column, row);
+ }
+ }
+ ImGui::EndTable();
+ }
+
+ // Context Menus: second example
+ // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
+ // [2.2] Right-click on the ".." to open a custom popup
+ // [2.3] Right-click in columns to open another custom popup
+ HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body).");
+ ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
+ if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2))
+ {
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+
+ // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
+ ImGui::TableHeadersRow();
+ for (int row = 0; row < 4; row++)
+ {
+ ImGui::TableNextRow();
+ for (int column = 0; column < COLUMNS_COUNT; column++)
+ {
+ // Submit dummy contents
+ ImGui::TableSetColumnIndex(column);
+ ImGui::Text("Cell %d,%d", column, row);
+ ImGui::SameLine();
+
+ // [2.2] Right-click on the ".." to open a custom popup
+ ImGui::PushID(row * COLUMNS_COUNT + column);
+ ImGui::SmallButton("..");
+ if (ImGui::BeginPopupContextItem())
+ {
+ ImGui::Text("This is the popup for Button(\"..\") in Cell %d,%d", column, row);
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+ ImGui::PopID();
+ }
+ }
+
+ // [2.3] Right-click anywhere in columns to open another custom popup
+ // (instead of testing for !IsAnyItemHovered() we could also call OpenPopup() with ImGuiPopupFlags_NoOpenOverExistingPopup
+ // to manage popup priority as the popups triggers, here "are we hovering a column" are overlapping)
+ int hovered_column = -1;
+ for (int column = 0; column < COLUMNS_COUNT + 1; column++)
+ {
+ ImGui::PushID(column);
+ if (ImGui::TableGetColumnFlags(column) & ImGuiTableColumnFlags_IsHovered)
+ hovered_column = column;
+ if (hovered_column == column && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(1))
+ ImGui::OpenPopup("MyPopup");
+ if (ImGui::BeginPopup("MyPopup"))
+ {
+ if (column == COLUMNS_COUNT)
+ ImGui::Text("This is a custom popup for unused space after the last column.");
+ else
+ ImGui::Text("This is a custom popup for Column %d", column);
+ if (ImGui::Button("Close"))
+ ImGui::CloseCurrentPopup();
+ ImGui::EndPopup();
+ }
+ ImGui::PopID();
+ }
+
+ ImGui::EndTable();
+ ImGui::Text("Hovered column: %d", hovered_column);
+ }
+ ImGui::TreePop();
+ }
+
+ // Demonstrate creating multiple tables with the same ID
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Synced instances");
+ if (ImGui::TreeNode("Synced instances"))
+ {
+ HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc.");
+ for (int n = 0; n < 3; n++)
+ {
+ char buf[32];
+ sprintf(buf, "Synced Table %d", n);
+ bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen);
+ if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings))
+ {
+ ImGui::TableSetupColumn("One");
+ ImGui::TableSetupColumn("Two");
+ ImGui::TableSetupColumn("Three");
+ ImGui::TableHeadersRow();
+ for (int cell = 0; cell < 9; cell++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("this cell %d", cell);
+ }
+ ImGui::EndTable();
+ }
+ }
+ ImGui::TreePop();
+ }
+
+ // Demonstrate using Sorting facilities
+ // This is a simplified version of the "Advanced" example, where we mostly focus on the code necessary to handle sorting.
+ // Note that the "Advanced" example also showcase manually triggering a sort (e.g. if item quantities have been modified)
+ static const char* template_items_names[] =
+ {
+ "Banana", "Apple", "Cherry", "Watermelon", "Grapefruit", "Strawberry", "Mango",
+ "Kiwi", "Orange", "Pineapple", "Blueberry", "Plum", "Coconut", "Pear", "Apricot"
+ };
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Sorting");
+ if (ImGui::TreeNode("Sorting"))
+ {
+ // Create item list
+ static ImVector<MyItem> items;
+ if (items.Size == 0)
+ {
+ items.resize(50, MyItem());
+ for (int n = 0; n < items.Size; n++)
+ {
+ const int template_n = n % IM_ARRAYSIZE(template_items_names);
+ MyItem& item = items[n];
+ item.ID = n;
+ item.Name = template_items_names[template_n];
+ item.Quantity = (n * n - n) % 20; // Assign default quantities
+ }
+ }
+
+ // Options
+ static ImGuiTableFlags flags =
+ ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
+ | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody
+ | ImGuiTableFlags_ScrollY;
+ PushStyleCompact();
+ ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
+ ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
+ ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
+ ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
+ PopStyleCompact();
+
+ if (ImGui::BeginTable("table_sorting", 4, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 15), 0.0f))
+ {
+ // Declare columns
+ // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
+ // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
+ // Demonstrate using a mixture of flags among available sort-related flags:
+ // - ImGuiTableColumnFlags_DefaultSort
+ // - ImGuiTableColumnFlags_NoSort / ImGuiTableColumnFlags_NoSortAscending / ImGuiTableColumnFlags_NoSortDescending
+ // - ImGuiTableColumnFlags_PreferSortAscending / ImGuiTableColumnFlags_PreferSortDescending
+ ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_ID);
+ ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name);
+ ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action);
+ ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Quantity);
+ ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible
+ ImGui::TableHeadersRow();
+
+ // Sort our data if sort specs have been changed!
+ if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs())
+ if (sorts_specs->SpecsDirty)
+ {
+ MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function.
+ if (items.Size > 1)
+ qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
+ MyItem::s_current_sort_specs = NULL;
+ sorts_specs->SpecsDirty = false;
+ }
+
+ // Demonstrate using clipper for large vertical lists
+ ImGuiListClipper clipper;
+ clipper.Begin(items.Size);
+ while (clipper.Step())
+ for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
+ {
+ // Display a data item
+ MyItem* item = &items[row_n];
+ ImGui::PushID(item->ID);
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ ImGui::Text("%04d", item->ID);
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted(item->Name);
+ ImGui::TableNextColumn();
+ ImGui::SmallButton("None");
+ ImGui::TableNextColumn();
+ ImGui::Text("%d", item->Quantity);
+ ImGui::PopID();
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+
+ // In this example we'll expose most table flags and settings.
+ // For specific flags and settings refer to the corresponding section for more detailed explanation.
+ // This section is mostly useful to experiment with combining certain flags or settings with each others.
+ //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // [DEBUG]
+ if (open_action != -1)
+ ImGui::SetNextItemOpen(open_action != 0);
+ IMGUI_DEMO_MARKER("Tables/Advanced");
+ if (ImGui::TreeNode("Advanced"))
+ {
+ static ImGuiTableFlags flags =
+ ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable
+ | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
+ | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody
+ | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
+ | ImGuiTableFlags_SizingFixedFit;
+
+ enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow };
+ static int contents_type = CT_SelectableSpanRow;
+ const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable", "Selectable (span row)" };
+ static int freeze_cols = 1;
+ static int freeze_rows = 1;
+ static int items_count = IM_ARRAYSIZE(template_items_names) * 2;
+ static ImVec2 outer_size_value = ImVec2(0.0f, TEXT_BASE_HEIGHT * 12);
+ static float row_min_height = 0.0f; // Auto
+ static float inner_width_with_scroll = 0.0f; // Auto-extend
+ static bool outer_size_enabled = true;
+ static bool show_headers = true;
+ static bool show_wrapped_text = false;
+ //static ImGuiTextFilter filter;
+ //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // FIXME-TABLE: Enabling this results in initial clipped first pass on table which tend to affects column sizing
+ if (ImGui::TreeNode("Options"))
+ {
+ // Make the UI compact because there are so many fields
+ PushStyleCompact();
+ ImGui::PushItemWidth(TEXT_BASE_WIDTH * 28.0f);
+
+ if (ImGui::TreeNodeEx("Features:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_Sortable", &flags, ImGuiTableFlags_Sortable);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoSavedSettings", &flags, ImGuiTableFlags_NoSavedSettings);
+ ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags, ImGuiTableFlags_ContextMenuInBody);
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNodeEx("Decorations:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
+ ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appears in Headers");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers)");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ EditTableSizingFlags(&flags);
+ ImGui::SameLine(); HelpMarker("In the Advanced demo we override the policy of each column so those table-wide settings have less effect that typical.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
+ ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
+ ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
+ ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
+ ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
+ ImGui::SameLine(); HelpMarker("Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with ScrollFreeze options.");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNodeEx("Padding:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags, ImGuiTableFlags_PadOuterX);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags, ImGuiTableFlags_NoPadOuterX);
+ ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags, ImGuiTableFlags_NoPadInnerX);
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNodeEx("Scrolling:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
+ ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
+ ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
+ ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNodeEx("Sorting:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
+ ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
+ ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
+ ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
+ ImGui::TreePop();
+ }
+
+ if (ImGui::TreeNodeEx("Other:", ImGuiTreeNodeFlags_DefaultOpen))
+ {
+ ImGui::Checkbox("show_headers", &show_headers);
+ ImGui::Checkbox("show_wrapped_text", &show_wrapped_text);
+
+ ImGui::DragFloat2("##OuterSize", &outer_size_value.x);
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
+ ImGui::Checkbox("outer_size", &outer_size_enabled);
+ ImGui::SameLine();
+ HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set):\n"
+ "- The table is output directly in the parent window.\n"
+ "- OuterSize.x < 0.0f will right-align the table.\n"
+ "- OuterSize.x = 0.0f will narrow fit the table unless there are any Stretch column.\n"
+ "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set).");
+
+ // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
+ // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled.
+ ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
+
+ ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
+ ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
+
+ ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999);
+ ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names));
+ //filter.Draw("filter");
+ ImGui::TreePop();
+ }
+
+ ImGui::PopItemWidth();
+ PopStyleCompact();
+ ImGui::Spacing();
+ ImGui::TreePop();
+ }
+
+ // Update item list if we changed the number of items
+ static ImVector<MyItem> items;
+ static ImVector<int> selection;
+ static bool items_need_sort = false;
+ if (items.Size != items_count)
+ {
+ items.resize(items_count, MyItem());
+ for (int n = 0; n < items_count; n++)
+ {
+ const int template_n = n % IM_ARRAYSIZE(template_items_names);
+ MyItem& item = items[n];
+ item.ID = n;
+ item.Name = template_items_names[template_n];
+ item.Quantity = (template_n == 3) ? 10 : (template_n == 4) ? 20 : 0; // Assign default quantities
+ }
+ }
+
+ const ImDrawList* parent_draw_list = ImGui::GetWindowDrawList();
+ const int parent_draw_list_draw_cmd_count = parent_draw_list->CmdBuffer.Size;
+ ImVec2 table_scroll_cur, table_scroll_max; // For debug display
+ const ImDrawList* table_draw_list = NULL; // "
+
+ // Submit table
+ const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f;
+ if (ImGui::BeginTable("table_advanced", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
+ {
+ // Declare columns
+ // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
+ // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
+ ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, 0.0f, MyItemColumnID_ID);
+ ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name);
+ ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action);
+ ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, 0.0f, MyItemColumnID_Quantity);
+ ImGui::TableSetupColumn("Description", (flags & ImGuiTableFlags_NoHostExtendX) ? 0 : ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Description);
+ ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort);
+ ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
+
+ // Sort our data if sort specs have been changed!
+ ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs();
+ if (sorts_specs && sorts_specs->SpecsDirty)
+ items_need_sort = true;
+ if (sorts_specs && items_need_sort && items.Size > 1)
+ {
+ MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function.
+ qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
+ MyItem::s_current_sort_specs = NULL;
+ sorts_specs->SpecsDirty = false;
+ }
+ items_need_sort = false;
+
+ // Take note of whether we are currently sorting based on the Quantity field,
+ // we will use this to trigger sorting when we know the data of this column has been modified.
+ const bool sorts_specs_using_quantity = (ImGui::TableGetColumnFlags(3) & ImGuiTableColumnFlags_IsSorted) != 0;
+
+ // Show headers
+ if (show_headers)
+ ImGui::TableHeadersRow();
+
+ // Show data
+ // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here?
+ ImGui::PushButtonRepeat(true);
+#if 1
+ // Demonstrate using clipper for large vertical lists
+ ImGuiListClipper clipper;
+ clipper.Begin(items.Size);
+ while (clipper.Step())
+ {
+ for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
+#else
+ // Without clipper
+ {
+ for (int row_n = 0; row_n < items.Size; row_n++)
+#endif
+ {
+ MyItem* item = &items[row_n];
+ //if (!filter.PassFilter(item->Name))
+ // continue;
+
+ const bool item_is_selected = selection.contains(item->ID);
+ ImGui::PushID(item->ID);
+ ImGui::TableNextRow(ImGuiTableRowFlags_None, row_min_height);
+
+ // For the demo purpose we can select among different type of items submitted in the first column
+ ImGui::TableSetColumnIndex(0);
+ char label[32];
+ sprintf(label, "%04d", item->ID);
+ if (contents_type == CT_Text)
+ ImGui::TextUnformatted(label);
+ else if (contents_type == CT_Button)
+ ImGui::Button(label);
+ else if (contents_type == CT_SmallButton)
+ ImGui::SmallButton(label);
+ else if (contents_type == CT_FillButton)
+ ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f));
+ else if (contents_type == CT_Selectable || contents_type == CT_SelectableSpanRow)
+ {
+ ImGuiSelectableFlags selectable_flags = (contents_type == CT_SelectableSpanRow) ? ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap : ImGuiSelectableFlags_None;
+ if (ImGui::Selectable(label, item_is_selected, selectable_flags, ImVec2(0, row_min_height)))
+ {
+ if (ImGui::GetIO().KeyCtrl)
+ {
+ if (item_is_selected)
+ selection.find_erase_unsorted(item->ID);
+ else
+ selection.push_back(item->ID);
+ }
+ else
+ {
+ selection.clear();
+ selection.push_back(item->ID);
+ }
+ }
+ }
+
+ if (ImGui::TableSetColumnIndex(1))
+ ImGui::TextUnformatted(item->Name);
+
+ // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity,
+ // and we are currently sorting on the column showing the Quantity.
+ // To avoid triggering a sort while holding the button, we only trigger it when the button has been released.
+ // You will probably need a more advanced system in your code if you want to automatically sort when a specific entry changes.
+ if (ImGui::TableSetColumnIndex(2))
+ {
+ if (ImGui::SmallButton("Chop")) { item->Quantity += 1; }
+ if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
+ ImGui::SameLine();
+ if (ImGui::SmallButton("Eat")) { item->Quantity -= 1; }
+ if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
+ }
+
+ if (ImGui::TableSetColumnIndex(3))
+ ImGui::Text("%d", item->Quantity);
+
+ ImGui::TableSetColumnIndex(4);
+ if (show_wrapped_text)
+ ImGui::TextWrapped("Lorem ipsum dolor sit amet");
+ else
+ ImGui::Text("Lorem ipsum dolor sit amet");
+
+ if (ImGui::TableSetColumnIndex(5))
+ ImGui::Text("1234");
+
+ ImGui::PopID();
+ }
+ }
+ ImGui::PopButtonRepeat();
+
+ // Store some info to display debug details below
+ table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
+ table_scroll_max = ImVec2(ImGui::GetScrollMaxX(), ImGui::GetScrollMaxY());
+ table_draw_list = ImGui::GetWindowDrawList();
+ ImGui::EndTable();
+ }
+ static bool show_debug_details = false;
+ ImGui::Checkbox("Debug details", &show_debug_details);
+ if (show_debug_details && table_draw_list)
+ {
+ ImGui::SameLine(0.0f, 0.0f);
+ const int table_draw_list_draw_cmd_count = table_draw_list->CmdBuffer.Size;
+ if (table_draw_list == parent_draw_list)
+ ImGui::Text(": DrawCmd: +%d (in same window)",
+ table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count);
+ else
+ ImGui::Text(": DrawCmd: +%d (in child window), Scroll: (%.f/%.f) (%.f/%.f)",
+ table_draw_list_draw_cmd_count - 1, table_scroll_cur.x, table_scroll_max.x, table_scroll_cur.y, table_scroll_max.y);
+ }
+ ImGui::TreePop();
+ }
+
+ ImGui::PopID();
+
+ ShowDemoWindowColumns();
+
+ if (disable_indent)
+ ImGui::PopStyleVar();
+}
+
+// Demonstrate old/legacy Columns API!
+// [2020: Columns are under-featured and not maintained. Prefer using the more flexible and powerful BeginTable() API!]
+static void ShowDemoWindowColumns()
+{
+ IMGUI_DEMO_MARKER("Columns (legacy API)");
+ bool open = ImGui::TreeNode("Legacy Columns API");
+ ImGui::SameLine();
+ HelpMarker("Columns() is an old API! Prefer using the more flexible and powerful BeginTable() API!");
+ if (!open)
+ return;
+
+ // Basic columns
+ IMGUI_DEMO_MARKER("Columns (legacy API)/Basic");
+ if (ImGui::TreeNode("Basic"))
+ {
+ ImGui::Text("Without border:");
+ ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border
+ ImGui::Separator();
+ for (int n = 0; n < 14; n++)
+ {
+ char label[32];
+ sprintf(label, "Item %d", n);
+ if (ImGui::Selectable(label)) {}
+ //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
+ ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ ImGui::Separator();
+
+ ImGui::Text("With border:");
+ ImGui::Columns(4, "mycolumns"); // 4-ways, with border
+ ImGui::Separator();
+ ImGui::Text("ID"); ImGui::NextColumn();
+ ImGui::Text("Name"); ImGui::NextColumn();
+ ImGui::Text("Path"); ImGui::NextColumn();
+ ImGui::Text("Hovered"); ImGui::NextColumn();
+ ImGui::Separator();
+ const char* names[3] = { "One", "Two", "Three" };
+ const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
+ static int selected = -1;
+ for (int i = 0; i < 3; i++)
+ {
+ char label[32];
+ sprintf(label, "%04d", i);
+ if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
+ selected = i;
+ bool hovered = ImGui::IsItemHovered();
+ ImGui::NextColumn();
+ ImGui::Text(names[i]); ImGui::NextColumn();
+ ImGui::Text(paths[i]); ImGui::NextColumn();
+ ImGui::Text("%d", hovered); ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Columns (legacy API)/Borders");
+ if (ImGui::TreeNode("Borders"))
+ {
+ // NB: Future columns API should allow automatic horizontal borders.
+ static bool h_borders = true;
+ static bool v_borders = true;
+ static int columns_count = 4;
+ const int lines_count = 3;
+ ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
+ ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
+ if (columns_count < 2)
+ columns_count = 2;
+ ImGui::SameLine();
+ ImGui::Checkbox("horizontal", &h_borders);
+ ImGui::SameLine();
+ ImGui::Checkbox("vertical", &v_borders);
+ ImGui::Columns(columns_count, NULL, v_borders);
+ for (int i = 0; i < columns_count * lines_count; i++)
+ {
+ if (h_borders && ImGui::GetColumnIndex() == 0)
+ ImGui::Separator();
+ ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
+ ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
+ ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
+ ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
+ ImGui::Text("Long text that is likely to clip");
+ ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
+ ImGui::NextColumn();
+ }
+ ImGui::Columns(1);
+ if (h_borders)
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ // Create multiple items in a same cell before switching to next column
+ IMGUI_DEMO_MARKER("Columns (legacy API)/Mixed items");
+ if (ImGui::TreeNode("Mixed items"))
+ {
+ ImGui::Columns(3, "mixed");
+ ImGui::Separator();
+
+ ImGui::Text("Hello");
+ ImGui::Button("Banana");
+ ImGui::NextColumn();
+
+ ImGui::Text("ImGui");
+ ImGui::Button("Apple");
+ static float foo = 1.0f;
+ ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
+ ImGui::Text("An extra line here.");
+ ImGui::NextColumn();
+
+ ImGui::Text("Sailor");
+ ImGui::Button("Corniflower");
+ static float bar = 1.0f;
+ ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
+ ImGui::NextColumn();
+
+ if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+ if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+ if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ // Word wrapping
+ IMGUI_DEMO_MARKER("Columns (legacy API)/Word-wrapping");
+ if (ImGui::TreeNode("Word-wrapping"))
+ {
+ ImGui::Columns(2, "word-wrapping");
+ ImGui::Separator();
+ ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
+ ImGui::TextWrapped("Hello Left");
+ ImGui::NextColumn();
+ ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
+ ImGui::TextWrapped("Hello Right");
+ ImGui::Columns(1);
+ ImGui::Separator();
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Columns (legacy API)/Horizontal Scrolling");
+ if (ImGui::TreeNode("Horizontal Scrolling"))
+ {
+ ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
+ ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
+ ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar);
+ ImGui::Columns(10);
+
+ // Also demonstrate using clipper for large vertical lists
+ int ITEMS_COUNT = 2000;
+ ImGuiListClipper clipper;
+ clipper.Begin(ITEMS_COUNT);
+ while (clipper.Step())
+ {
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ for (int j = 0; j < 10; j++)
+ {
+ ImGui::Text("Line %d Column %d...", i, j);
+ ImGui::NextColumn();
+ }
+ }
+ ImGui::Columns(1);
+ ImGui::EndChild();
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Columns (legacy API)/Tree");
+ if (ImGui::TreeNode("Tree"))
+ {
+ ImGui::Columns(2, "tree", true);
+ for (int x = 0; x < 3; x++)
+ {
+ bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
+ ImGui::NextColumn();
+ ImGui::Text("Node contents");
+ ImGui::NextColumn();
+ if (open1)
+ {
+ for (int y = 0; y < 3; y++)
+ {
+ bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
+ ImGui::NextColumn();
+ ImGui::Text("Node contents");
+ if (open2)
+ {
+ ImGui::Text("Even more contents");
+ if (ImGui::TreeNode("Tree in column"))
+ {
+ ImGui::Text("The quick brown fox jumps over the lazy dog");
+ ImGui::TreePop();
+ }
+ }
+ ImGui::NextColumn();
+ if (open2)
+ ImGui::TreePop();
+ }
+ ImGui::TreePop();
+ }
+ }
+ ImGui::Columns(1);
+ ImGui::TreePop();
+ }
+
+ ImGui::TreePop();
+}
+
+static void ShowDemoWindowMisc()
+{
+ IMGUI_DEMO_MARKER("Filtering");
+ if (ImGui::CollapsingHeader("Filtering"))
+ {
+ // Helper class to easy setup a text filter.
+ // You may want to implement a more feature-full filtering scheme in your own application.
+ static ImGuiTextFilter filter;
+ ImGui::Text("Filter usage:\n"
+ " \"\" display all lines\n"
+ " \"xxx\" display lines containing \"xxx\"\n"
+ " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
+ " \"-xxx\" hide lines containing \"xxx\"");
+ filter.Draw();
+ const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
+ for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
+ if (filter.PassFilter(lines[i]))
+ ImGui::BulletText("%s", lines[i]);
+ }
+
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus");
+ if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+
+ // Display ImGuiIO output flags
+ ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
+ ImGui::Text("WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
+ ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
+ ImGui::Text("WantTextInput: %d", io.WantTextInput);
+ ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
+ ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
+
+ // Display Mouse state
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Mouse State");
+ if (ImGui::TreeNode("Mouse State"))
+ {
+ if (ImGui::IsMousePosValid())
+ ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
+ else
+ ImGui::Text("Mouse pos: <INVALID>");
+ ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
+
+ int count = IM_ARRAYSIZE(io.MouseDown);
+ ImGui::Text("Mouse down:"); for (int i = 0; i < count; i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
+ ImGui::Text("Mouse clicked:"); for (int i = 0; i < count; i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text(" - clicked double:"); for (int i = 0; i < count; i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text(" - clicked triple:"); for (int i = 0; i < count; i++) if (ImGui::IsMouseTripleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text(" - clicked count:"); for (int i = 0; i < count; i++) if (io.MouseClickedCount[i]) { ImGui::SameLine(); ImGui::Text("b%d (%d)", i, io.MouseClickedCount[i]); }
+ //ImGui::Text(" - last count:"); for (int i = 0; i < count; i++) if (io.MouseClickedLastCount[i]) { ImGui::SameLine(); ImGui::Text("b%d (%d)", i, io.MouseClickedLastCount[i]); }
+
+ ImGui::Text("Mouse released:"); for (int i = 0; i < count; i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
+ ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
+ ImGui::Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused
+ ImGui::TreePop();
+ }
+
+ // Display Keyboard/Mouse state
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Keyboard & Navigation State");
+ if (ImGui::TreeNode("Keyboard & Navigation State"))
+ {
+ ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
+ ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
+ ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
+ ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
+ ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
+
+ ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); }
+ ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
+
+ ImGui::Button("Hovering me sets the\nkeyboard capture flag");
+ if (ImGui::IsItemHovered())
+ ImGui::CaptureKeyboardFromApp(true);
+ ImGui::SameLine();
+ ImGui::Button("Holding me clears the\nthe keyboard capture flag");
+ if (ImGui::IsItemActive())
+ ImGui::CaptureKeyboardFromApp(false);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Tabbing");
+ if (ImGui::TreeNode("Tabbing"))
+ {
+ ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
+ static char buf[32] = "hello";
+ ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
+ ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
+ ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
+ ImGui::PushAllowKeyboardFocus(false);
+ ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
+ ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
+ ImGui::PopAllowKeyboardFocus();
+ ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Focus from code");
+ if (ImGui::TreeNode("Focus from code"))
+ {
+ bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
+ bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
+ bool focus_3 = ImGui::Button("Focus on 3");
+ int has_focus = 0;
+ static char buf[128] = "click on a button to set focus";
+
+ if (focus_1) ImGui::SetKeyboardFocusHere();
+ ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
+ if (ImGui::IsItemActive()) has_focus = 1;
+
+ if (focus_2) ImGui::SetKeyboardFocusHere();
+ ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
+ if (ImGui::IsItemActive()) has_focus = 2;
+
+ ImGui::PushAllowKeyboardFocus(false);
+ if (focus_3) ImGui::SetKeyboardFocusHere();
+ ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
+ if (ImGui::IsItemActive()) has_focus = 3;
+ ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
+ ImGui::PopAllowKeyboardFocus();
+
+ if (has_focus)
+ ImGui::Text("Item with focus: %d", has_focus);
+ else
+ ImGui::Text("Item with focus: <none>");
+
+ // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
+ static float f3[3] = { 0.0f, 0.0f, 0.0f };
+ int focus_ahead = -1;
+ if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
+ if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
+ if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
+ if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
+ ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
+
+ ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Dragging");
+ if (ImGui::TreeNode("Dragging"))
+ {
+ ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
+ for (int button = 0; button < 3; button++)
+ {
+ ImGui::Text("IsMouseDragging(%d):", button);
+ ImGui::Text(" w/ default threshold: %d,", ImGui::IsMouseDragging(button));
+ ImGui::Text(" w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f));
+ ImGui::Text(" w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f));
+ }
+
+ ImGui::Button("Drag Me");
+ if (ImGui::IsItemActive())
+ ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
+
+ // Drag operations gets "unlocked" when the mouse has moved past a certain threshold
+ // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher
+ // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta().
+ ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
+ ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
+ ImVec2 mouse_delta = io.MouseDelta;
+ ImGui::Text("GetMouseDragDelta(0):");
+ ImGui::Text(" w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y);
+ ImGui::Text(" w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y);
+ ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y);
+ ImGui::TreePop();
+ }
+
+ IMGUI_DEMO_MARKER("Inputs, Navigation & Focus/Mouse cursors");
+ if (ImGui::TreeNode("Mouse cursors"))
+ {
+ const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
+ IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
+
+ ImGuiMouseCursor current = ImGui::GetMouseCursor();
+ ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
+ ImGui::Text("Hover to see mouse cursors:");
+ ImGui::SameLine(); HelpMarker(
+ "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. "
+ "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, "
+ "otherwise your backend needs to handle it.");
+ for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
+ {
+ char label[32];
+ sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
+ ImGui::Bullet(); ImGui::Selectable(label, false);
+ if (ImGui::IsItemHovered())
+ ImGui::SetMouseCursor(i);
+ }
+ ImGui::TreePop();
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] About Window / ShowAboutWindow()
+// Access from Dear ImGui Demo -> Tools -> About
+//-----------------------------------------------------------------------------
+
+void ImGui::ShowAboutWindow(bool* p_open)
+{
+ if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::End();
+ return;
+ }
+ IMGUI_DEMO_MARKER("Tools/About Dear ImGui");
+ ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
+ ImGui::Separator();
+ ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
+ ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
+
+ static bool show_config_info = false;
+ ImGui::Checkbox("Config/Build Information", &show_config_info);
+ if (show_config_info)
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ ImGuiStyle& style = ImGui::GetStyle();
+
+ bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
+ ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
+ ImGui::BeginChildFrame(ImGui::GetID("cfg_infos"), child_size, ImGuiWindowFlags_NoMove);
+ if (copy_to_clipboard)
+ {
+ ImGui::LogToClipboard();
+ ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub
+ }
+
+ ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
+ ImGui::Separator();
+ ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
+ ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
+#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_FILE_FUNCTIONS
+ ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
+#endif
+#ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
+ ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
+#endif
+#ifdef IMGUI_USE_BGRA_PACKED_COLOR
+ ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
+#endif
+#ifdef _WIN32
+ ImGui::Text("define: _WIN32");
+#endif
+#ifdef _WIN64
+ ImGui::Text("define: _WIN64");
+#endif
+#ifdef __linux__
+ ImGui::Text("define: __linux__");
+#endif
+#ifdef __APPLE__
+ ImGui::Text("define: __APPLE__");
+#endif
+#ifdef _MSC_VER
+ ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
+#endif
+#ifdef _MSVC_LANG
+ ImGui::Text("define: _MSVC_LANG=%d", (int)_MSVC_LANG);
+#endif
+#ifdef __MINGW32__
+ ImGui::Text("define: __MINGW32__");
+#endif
+#ifdef __MINGW64__
+ ImGui::Text("define: __MINGW64__");
+#endif
+#ifdef __GNUC__
+ ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
+#endif
+#ifdef __clang_version__
+ ImGui::Text("define: __clang_version__=%s", __clang_version__);
+#endif
+ ImGui::Separator();
+ ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
+ ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
+ ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) ImGui::Text(" NavEnableKeyboard");
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) ImGui::Text(" NavEnableGamepad");
+ if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) ImGui::Text(" NavEnableSetMousePos");
+ if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard) ImGui::Text(" NavNoCaptureKeyboard");
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) ImGui::Text(" NoMouse");
+ if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) ImGui::Text(" NoMouseCursorChange");
+ if (io.MouseDrawCursor) ImGui::Text("io.MouseDrawCursor");
+ if (io.ConfigMacOSXBehaviors) ImGui::Text("io.ConfigMacOSXBehaviors");
+ if (io.ConfigInputTextCursorBlink) ImGui::Text("io.ConfigInputTextCursorBlink");
+ if (io.ConfigWindowsResizeFromEdges) ImGui::Text("io.ConfigWindowsResizeFromEdges");
+ if (io.ConfigWindowsMoveFromTitleBarOnly) ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
+ if (io.ConfigMemoryCompactTimer >= 0.0f) ImGui::Text("io.ConfigMemoryCompactTimer = %.1f", io.ConfigMemoryCompactTimer);
+ ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
+ if (io.BackendFlags & ImGuiBackendFlags_HasGamepad) ImGui::Text(" HasGamepad");
+ if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) ImGui::Text(" HasMouseCursors");
+ if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos) ImGui::Text(" HasSetMousePos");
+ if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) ImGui::Text(" RendererHasVtxOffset");
+ ImGui::Separator();
+ ImGui::Text("io.Fonts: %d fonts, Flags: 0x%08X, TexSize: %d,%d", io.Fonts->Fonts.Size, io.Fonts->Flags, io.Fonts->TexWidth, io.Fonts->TexHeight);
+ ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
+ ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
+ ImGui::Separator();
+ ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
+ ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
+ ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
+ ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
+ ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
+ ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
+ ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
+
+ if (copy_to_clipboard)
+ {
+ ImGui::LogText("\n```\n");
+ ImGui::LogFinish();
+ }
+ ImGui::EndChildFrame();
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Style Editor / ShowStyleEditor()
+//-----------------------------------------------------------------------------
+// - ShowFontSelector()
+// - ShowStyleSelector()
+// - ShowStyleEditor()
+//-----------------------------------------------------------------------------
+
+// Forward declare ShowFontAtlas() which isn't worth putting in public API yet
+namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); }
+
+// Demo helper function to select among loaded fonts.
+// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
+void ImGui::ShowFontSelector(const char* label)
+{
+ ImGuiIO& io = ImGui::GetIO();
+ ImFont* font_current = ImGui::GetFont();
+ if (ImGui::BeginCombo(label, font_current->GetDebugName()))
+ {
+ for (int n = 0; n < io.Fonts->Fonts.Size; n++)
+ {
+ ImFont* font = io.Fonts->Fonts[n];
+ ImGui::PushID((void*)font);
+ if (ImGui::Selectable(font->GetDebugName(), font == font_current))
+ io.FontDefault = font;
+ ImGui::PopID();
+ }
+ ImGui::EndCombo();
+ }
+ ImGui::SameLine();
+ HelpMarker(
+ "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
+ "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
+ "- Read FAQ and docs/FONTS.md for more details.\n"
+ "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
+}
+
+// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
+// Here we use the simplified Combo() api that packs items into a single literal string.
+// Useful for quick combo boxes where the choices are known locally.
+bool ImGui::ShowStyleSelector(const char* label)
+{
+ static int style_idx = -1;
+ if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
+ {
+ switch (style_idx)
+ {
+ case 0: ImGui::StyleColorsDark(); break;
+ case 1: ImGui::StyleColorsLight(); break;
+ case 2: ImGui::StyleColorsClassic(); break;
+ }
+ return true;
+ }
+ return false;
+}
+
+void ImGui::ShowStyleEditor(ImGuiStyle* ref)
+{
+ IMGUI_DEMO_MARKER("Tools/Style Editor");
+ // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
+ // (without a reference style pointer, we will use one compared locally as a reference)
+ ImGuiStyle& style = ImGui::GetStyle();
+ static ImGuiStyle ref_saved_style;
+
+ // Default to using internal storage as reference
+ static bool init = true;
+ if (init && ref == NULL)
+ ref_saved_style = style;
+ init = false;
+ if (ref == NULL)
+ ref = &ref_saved_style;
+
+ ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
+
+ if (ImGui::ShowStyleSelector("Colors##Selector"))
+ ref_saved_style = style;
+ ImGui::ShowFontSelector("Fonts##Selector");
+
+ // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f)
+ if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
+ style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
+ { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } }
+ ImGui::SameLine();
+ { bool border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &border)) { style.FrameBorderSize = border ? 1.0f : 0.0f; } }
+ ImGui::SameLine();
+ { bool border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &border)) { style.PopupBorderSize = border ? 1.0f : 0.0f; } }
+
+ // Save/Revert button
+ if (ImGui::Button("Save Ref"))
+ *ref = ref_saved_style = style;
+ ImGui::SameLine();
+ if (ImGui::Button("Revert Ref"))
+ style = *ref;
+ ImGui::SameLine();
+ HelpMarker(
+ "Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
+ "Use \"Export\" below to save them somewhere.");
+
+ ImGui::Separator();
+
+ if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
+ {
+ if (ImGui::BeginTabItem("Sizes"))
+ {
+ ImGui::Text("Main");
+ ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
+ ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
+ ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
+ ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
+ ImGui::Text("Borders");
+ ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
+ ImGui::Text("Rounding");
+ ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
+ ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
+ ImGui::Text("Alignment");
+ ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
+ int window_menu_button_position = style.WindowMenuButtonPosition + 1;
+ if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
+ style.WindowMenuButtonPosition = window_menu_button_position - 1;
+ ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
+ ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
+ ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
+ ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
+ ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
+ ImGui::Text("Safe Area Padding");
+ ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
+ ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Colors"))
+ {
+ static int output_dest = 0;
+ static bool output_only_modified = true;
+ if (ImGui::Button("Export"))
+ {
+ if (output_dest == 0)
+ ImGui::LogToClipboard();
+ else
+ ImGui::LogToTTY();
+ ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const ImVec4& col = style.Colors[i];
+ const char* name = ImGui::GetStyleColorName(i);
+ if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
+ ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
+ name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
+ }
+ ImGui::LogFinish();
+ }
+ ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
+ ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
+
+ static ImGuiTextFilter filter;
+ filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
+
+ static ImGuiColorEditFlags alpha_flags = 0;
+ if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
+ if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
+ if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
+ HelpMarker(
+ "In the color list:\n"
+ "Left-click on color square to open color picker,\n"
+ "Right-click to open edit options menu.");
+
+ ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
+ ImGui::PushItemWidth(-160);
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const char* name = ImGui::GetStyleColorName(i);
+ if (!filter.PassFilter(name))
+ continue;
+ ImGui::PushID(i);
+ ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
+ if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
+ {
+ // Tips: in a real user application, you may want to merge and use an icon font into the main font,
+ // so instead of "Save"/"Revert" you'd use icons!
+ // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
+ }
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
+ ImGui::TextUnformatted(name);
+ ImGui::PopID();
+ }
+ ImGui::PopItemWidth();
+ ImGui::EndChild();
+
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Fonts"))
+ {
+ ImGuiIO& io = ImGui::GetIO();
+ ImFontAtlas* atlas = io.Fonts;
+ HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
+ ImGui::ShowFontAtlas(atlas);
+
+ // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
+ // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
+ const float MIN_SCALE = 0.3f;
+ const float MAX_SCALE = 2.0f;
+ HelpMarker(
+ "Those are old settings provided for convenience.\n"
+ "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, "
+ "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
+ "Using those settings here will give you poor quality results.");
+ static float window_scale = 1.0f;
+ ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
+ if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
+ ImGui::SetWindowFontScale(window_scale);
+ ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
+ ImGui::PopItemWidth();
+
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Rendering"))
+ {
+ ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
+ ImGui::SameLine();
+ HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
+
+ ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
+ ImGui::SameLine();
+ HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
+
+ ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
+ ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
+ ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
+ if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
+
+ // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
+ ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
+ if (ImGui::IsItemActive())
+ {
+ ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
+ ImGui::BeginTooltip();
+ ImGui::TextUnformatted("(R = radius, N = number of segments)");
+ ImGui::Spacing();
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+ const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x;
+ for (int n = 0; n < 8; n++)
+ {
+ const float RAD_MIN = 5.0f;
+ const float RAD_MAX = 70.0f;
+ const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
+
+ ImGui::BeginGroup();
+
+ ImGui::Text("R: %.f\nN: %d", rad, draw_list->_CalcCircleAutoSegmentCount(rad));
+
+ const float canvas_width = IM_MAX(min_widget_width, rad * 2.0f);
+ const float offset_x = floorf(canvas_width * 0.5f);
+ const float offset_y = floorf(RAD_MAX);
+
+ const ImVec2 p1 = ImGui::GetCursorScreenPos();
+ draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
+ ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
+
+ /*
+ const ImVec2 p2 = ImGui::GetCursorScreenPos();
+ draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
+ ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
+ */
+
+ ImGui::EndGroup();
+ ImGui::SameLine();
+ }
+ ImGui::EndTooltip();
+ }
+ ImGui::SameLine();
+ HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically.");
+
+ ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
+ ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Additional alpha multiplier for disabled items (multiply over current value of Alpha).");
+ ImGui::PopItemWidth();
+
+ ImGui::EndTabItem();
+ }
+
+ ImGui::EndTabBar();
+ }
+
+ ImGui::PopItemWidth();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
+//-----------------------------------------------------------------------------
+// - ShowExampleAppMainMenuBar()
+// - ShowExampleMenuFile()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a "main" fullscreen menu bar and populating it.
+// Note the difference between BeginMainMenuBar() and BeginMenuBar():
+// - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!)
+// - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
+static void ShowExampleAppMainMenuBar()
+{
+ if (ImGui::BeginMainMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ if (ImGui::BeginMenu("Edit"))
+ {
+ if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
+ if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
+ ImGui::Separator();
+ if (ImGui::MenuItem("Cut", "CTRL+X")) {}
+ if (ImGui::MenuItem("Copy", "CTRL+C")) {}
+ if (ImGui::MenuItem("Paste", "CTRL+V")) {}
+ ImGui::EndMenu();
+ }
+ ImGui::EndMainMenuBar();
+ }
+}
+
+// Note that shortcuts are currently provided for display only
+// (future version will add explicit flags to BeginMenu() to request processing shortcuts)
+static void ShowExampleMenuFile()
+{
+ IMGUI_DEMO_MARKER("Examples/Menu");
+ ImGui::MenuItem("(demo menu)", NULL, false, false);
+ if (ImGui::MenuItem("New")) {}
+ if (ImGui::MenuItem("Open", "Ctrl+O")) {}
+ if (ImGui::BeginMenu("Open Recent"))
+ {
+ ImGui::MenuItem("fish_hat.c");
+ ImGui::MenuItem("fish_hat.inl");
+ ImGui::MenuItem("fish_hat.h");
+ if (ImGui::BeginMenu("More.."))
+ {
+ ImGui::MenuItem("Hello");
+ ImGui::MenuItem("Sailor");
+ if (ImGui::BeginMenu("Recurse.."))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenu();
+ }
+ if (ImGui::MenuItem("Save", "Ctrl+S")) {}
+ if (ImGui::MenuItem("Save As..")) {}
+
+ ImGui::Separator();
+ IMGUI_DEMO_MARKER("Examples/Menu/Options");
+ if (ImGui::BeginMenu("Options"))
+ {
+ static bool enabled = true;
+ ImGui::MenuItem("Enabled", "", &enabled);
+ ImGui::BeginChild("child", ImVec2(0, 60), true);
+ for (int i = 0; i < 10; i++)
+ ImGui::Text("Scrolling Text %d", i);
+ ImGui::EndChild();
+ static float f = 0.5f;
+ static int n = 0;
+ ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
+ ImGui::InputFloat("Input", &f, 0.1f);
+ ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
+ ImGui::EndMenu();
+ }
+
+ IMGUI_DEMO_MARKER("Examples/Menu/Colors");
+ if (ImGui::BeginMenu("Colors"))
+ {
+ float sz = ImGui::GetTextLineHeight();
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
+ {
+ const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
+ ImVec2 p = ImGui::GetCursorScreenPos();
+ ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
+ ImGui::Dummy(ImVec2(sz, sz));
+ ImGui::SameLine();
+ ImGui::MenuItem(name);
+ }
+ ImGui::EndMenu();
+ }
+
+ // Here we demonstrate appending again to the "Options" menu (which we already created above)
+ // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice.
+ // In a real code-base using it would make senses to use this feature from very different code locations.
+ if (ImGui::BeginMenu("Options")) // <-- Append!
+ {
+ IMGUI_DEMO_MARKER("Examples/Menu/Append to an existing menu");
+ static bool b = true;
+ ImGui::Checkbox("SomeOption", &b);
+ ImGui::EndMenu();
+ }
+
+ if (ImGui::BeginMenu("Disabled", false)) // Disabled
+ {
+ IM_ASSERT(0);
+ }
+ if (ImGui::MenuItem("Checked", NULL, true)) {}
+ if (ImGui::MenuItem("Quit", "Alt+F4")) {}
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
+// For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
+struct ExampleAppConsole
+{
+ char InputBuf[256];
+ ImVector<char*> Items;
+ ImVector<const char*> Commands;
+ ImVector<char*> History;
+ int HistoryPos; // -1: new line, 0..History.Size-1 browsing history.
+ ImGuiTextFilter Filter;
+ bool AutoScroll;
+ bool ScrollToBottom;
+
+ ExampleAppConsole()
+ {
+ IMGUI_DEMO_MARKER("Examples/Console");
+ ClearLog();
+ memset(InputBuf, 0, sizeof(InputBuf));
+ HistoryPos = -1;
+
+ // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches.
+ Commands.push_back("HELP");
+ Commands.push_back("HISTORY");
+ Commands.push_back("CLEAR");
+ Commands.push_back("CLASSIFY");
+ AutoScroll = true;
+ ScrollToBottom = false;
+ AddLog("Welcome to Dear ImGui!");
+ }
+ ~ExampleAppConsole()
+ {
+ ClearLog();
+ for (int i = 0; i < History.Size; i++)
+ free(History[i]);
+ }
+
+ // Portable helpers
+ static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
+ static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
+ static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
+ static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
+
+ void ClearLog()
+ {
+ for (int i = 0; i < Items.Size; i++)
+ free(Items[i]);
+ Items.clear();
+ }
+
+ void AddLog(const char* fmt, ...) IM_FMTARGS(2)
+ {
+ // FIXME-OPT
+ char buf[1024];
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
+ buf[IM_ARRAYSIZE(buf)-1] = 0;
+ va_end(args);
+ Items.push_back(Strdup(buf));
+ }
+
+ void Draw(const char* title, bool* p_open)
+ {
+ ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin(title, p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
+ // So e.g. IsItemHovered() will return true when hovering the title bar.
+ // Here we create a context menu only available from the title bar.
+ if (ImGui::BeginPopupContextItem())
+ {
+ if (ImGui::MenuItem("Close Console"))
+ *p_open = false;
+ ImGui::EndPopup();
+ }
+
+ ImGui::TextWrapped(
+ "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate "
+ "implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
+ ImGui::TextWrapped("Enter 'HELP' for help.");
+
+ // TODO: display items starting from the bottom
+
+ if (ImGui::SmallButton("Add Debug Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); }
+ ImGui::SameLine();
+ if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); }
+ ImGui::SameLine();
+ if (ImGui::SmallButton("Clear")) { ClearLog(); }
+ ImGui::SameLine();
+ bool copy_to_clipboard = ImGui::SmallButton("Copy");
+ //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
+
+ ImGui::Separator();
+
+ // Options menu
+ if (ImGui::BeginPopup("Options"))
+ {
+ ImGui::Checkbox("Auto-scroll", &AutoScroll);
+ ImGui::EndPopup();
+ }
+
+ // Options, Filter
+ if (ImGui::Button("Options"))
+ ImGui::OpenPopup("Options");
+ ImGui::SameLine();
+ Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
+ ImGui::Separator();
+
+ // Reserve enough left-over height for 1 separator + 1 input text
+ const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
+ ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar);
+ if (ImGui::BeginPopupContextWindow())
+ {
+ if (ImGui::Selectable("Clear")) ClearLog();
+ ImGui::EndPopup();
+ }
+
+ // Display every line as a separate entry so we can change their color or add custom widgets.
+ // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
+ // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
+ // to only process visible items. The clipper will automatically measure the height of your first item and then
+ // "seek" to display only items in the visible area.
+ // To use the clipper we can replace your standard loop:
+ // for (int i = 0; i < Items.Size; i++)
+ // With:
+ // ImGuiListClipper clipper;
+ // clipper.Begin(Items.Size);
+ // while (clipper.Step())
+ // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ // - That your items are evenly spaced (same height)
+ // - That you have cheap random access to your elements (you can access them given their index,
+ // without processing all the ones before)
+ // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
+ // We would need random-access on the post-filtered list.
+ // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
+ // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
+ // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
+ // to improve this example code!
+ // If your items are of variable height:
+ // - Split them into same height items would be simpler and facilitate random-seeking into your list.
+ // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
+ if (copy_to_clipboard)
+ ImGui::LogToClipboard();
+ for (int i = 0; i < Items.Size; i++)
+ {
+ const char* item = Items[i];
+ if (!Filter.PassFilter(item))
+ continue;
+
+ // Normally you would store more information in your item than just a string.
+ // (e.g. make Items[] an array of structure, store color/type etc.)
+ ImVec4 color;
+ bool has_color = false;
+ if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
+ else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
+ if (has_color)
+ ImGui::PushStyleColor(ImGuiCol_Text, color);
+ ImGui::TextUnformatted(item);
+ if (has_color)
+ ImGui::PopStyleColor();
+ }
+ if (copy_to_clipboard)
+ ImGui::LogFinish();
+
+ if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
+ ImGui::SetScrollHereY(1.0f);
+ ScrollToBottom = false;
+
+ ImGui::PopStyleVar();
+ ImGui::EndChild();
+ ImGui::Separator();
+
+ // Command-line
+ bool reclaim_focus = false;
+ ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
+ if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
+ {
+ char* s = InputBuf;
+ Strtrim(s);
+ if (s[0])
+ ExecCommand(s);
+ strcpy(s, "");
+ reclaim_focus = true;
+ }
+
+ // Auto-focus on window apparition
+ ImGui::SetItemDefaultFocus();
+ if (reclaim_focus)
+ ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
+
+ ImGui::End();
+ }
+
+ void ExecCommand(const char* command_line)
+ {
+ AddLog("# %s\n", command_line);
+
+ // Insert into history. First find match and delete it so it can be pushed to the back.
+ // This isn't trying to be smart or optimal.
+ HistoryPos = -1;
+ for (int i = History.Size - 1; i >= 0; i--)
+ if (Stricmp(History[i], command_line) == 0)
+ {
+ free(History[i]);
+ History.erase(History.begin() + i);
+ break;
+ }
+ History.push_back(Strdup(command_line));
+
+ // Process command
+ if (Stricmp(command_line, "CLEAR") == 0)
+ {
+ ClearLog();
+ }
+ else if (Stricmp(command_line, "HELP") == 0)
+ {
+ AddLog("Commands:");
+ for (int i = 0; i < Commands.Size; i++)
+ AddLog("- %s", Commands[i]);
+ }
+ else if (Stricmp(command_line, "HISTORY") == 0)
+ {
+ int first = History.Size - 10;
+ for (int i = first > 0 ? first : 0; i < History.Size; i++)
+ AddLog("%3d: %s\n", i, History[i]);
+ }
+ else
+ {
+ AddLog("Unknown command: '%s'\n", command_line);
+ }
+
+ // On command input, we scroll to bottom even if AutoScroll==false
+ ScrollToBottom = true;
+ }
+
+ // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks
+ static int TextEditCallbackStub(ImGuiInputTextCallbackData* data)
+ {
+ ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
+ return console->TextEditCallback(data);
+ }
+
+ int TextEditCallback(ImGuiInputTextCallbackData* data)
+ {
+ //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
+ switch (data->EventFlag)
+ {
+ case ImGuiInputTextFlags_CallbackCompletion:
+ {
+ // Example of TEXT COMPLETION
+
+ // Locate beginning of current word
+ const char* word_end = data->Buf + data->CursorPos;
+ const char* word_start = word_end;
+ while (word_start > data->Buf)
+ {
+ const char c = word_start[-1];
+ if (c == ' ' || c == '\t' || c == ',' || c == ';')
+ break;
+ word_start--;
+ }
+
+ // Build a list of candidates
+ ImVector<const char*> candidates;
+ for (int i = 0; i < Commands.Size; i++)
+ if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
+ candidates.push_back(Commands[i]);
+
+ if (candidates.Size == 0)
+ {
+ // No match
+ AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
+ }
+ else if (candidates.Size == 1)
+ {
+ // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
+ data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
+ data->InsertChars(data->CursorPos, candidates[0]);
+ data->InsertChars(data->CursorPos, " ");
+ }
+ else
+ {
+ // Multiple matches. Complete as much as we can..
+ // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches.
+ int match_len = (int)(word_end - word_start);
+ for (;;)
+ {
+ int c = 0;
+ bool all_candidates_matches = true;
+ for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
+ if (i == 0)
+ c = toupper(candidates[i][match_len]);
+ else if (c == 0 || c != toupper(candidates[i][match_len]))
+ all_candidates_matches = false;
+ if (!all_candidates_matches)
+ break;
+ match_len++;
+ }
+
+ if (match_len > 0)
+ {
+ data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
+ data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
+ }
+
+ // List matches
+ AddLog("Possible matches:\n");
+ for (int i = 0; i < candidates.Size; i++)
+ AddLog("- %s\n", candidates[i]);
+ }
+
+ break;
+ }
+ case ImGuiInputTextFlags_CallbackHistory:
+ {
+ // Example of HISTORY
+ const int prev_history_pos = HistoryPos;
+ if (data->EventKey == ImGuiKey_UpArrow)
+ {
+ if (HistoryPos == -1)
+ HistoryPos = History.Size - 1;
+ else if (HistoryPos > 0)
+ HistoryPos--;
+ }
+ else if (data->EventKey == ImGuiKey_DownArrow)
+ {
+ if (HistoryPos != -1)
+ if (++HistoryPos >= History.Size)
+ HistoryPos = -1;
+ }
+
+ // A better implementation would preserve the data on the current input line along with cursor position.
+ if (prev_history_pos != HistoryPos)
+ {
+ const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
+ data->DeleteChars(0, data->BufTextLen);
+ data->InsertChars(0, history_str);
+ }
+ }
+ }
+ return 0;
+ }
+};
+
+static void ShowExampleAppConsole(bool* p_open)
+{
+ static ExampleAppConsole console;
+ console.Draw("Example: Console", p_open);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Debug Log / ShowExampleAppLog()
+//-----------------------------------------------------------------------------
+
+// Usage:
+// static ExampleAppLog my_log;
+// my_log.AddLog("Hello %d world\n", 123);
+// my_log.Draw("title");
+struct ExampleAppLog
+{
+ ImGuiTextBuffer Buf;
+ ImGuiTextFilter Filter;
+ ImVector<int> LineOffsets; // Index to lines offset. We maintain this with AddLog() calls.
+ bool AutoScroll; // Keep scrolling if already at the bottom.
+
+ ExampleAppLog()
+ {
+ AutoScroll = true;
+ Clear();
+ }
+
+ void Clear()
+ {
+ Buf.clear();
+ LineOffsets.clear();
+ LineOffsets.push_back(0);
+ }
+
+ void AddLog(const char* fmt, ...) IM_FMTARGS(2)
+ {
+ int old_size = Buf.size();
+ va_list args;
+ va_start(args, fmt);
+ Buf.appendfv(fmt, args);
+ va_end(args);
+ for (int new_size = Buf.size(); old_size < new_size; old_size++)
+ if (Buf[old_size] == '\n')
+ LineOffsets.push_back(old_size + 1);
+ }
+
+ void Draw(const char* title, bool* p_open = NULL)
+ {
+ if (!ImGui::Begin(title, p_open))
+ {
+ ImGui::End();
+ return;
+ }
+
+ // Options menu
+ if (ImGui::BeginPopup("Options"))
+ {
+ ImGui::Checkbox("Auto-scroll", &AutoScroll);
+ ImGui::EndPopup();
+ }
+
+ // Main window
+ if (ImGui::Button("Options"))
+ ImGui::OpenPopup("Options");
+ ImGui::SameLine();
+ bool clear = ImGui::Button("Clear");
+ ImGui::SameLine();
+ bool copy = ImGui::Button("Copy");
+ ImGui::SameLine();
+ Filter.Draw("Filter", -100.0f);
+
+ ImGui::Separator();
+ ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
+
+ if (clear)
+ Clear();
+ if (copy)
+ ImGui::LogToClipboard();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ const char* buf = Buf.begin();
+ const char* buf_end = Buf.end();
+ if (Filter.IsActive())
+ {
+ // In this example we don't use the clipper when Filter is enabled.
+ // This is because we don't have a random access on the result on our filter.
+ // A real application processing logs with ten of thousands of entries may want to store the result of
+ // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
+ for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
+ {
+ const char* line_start = buf + LineOffsets[line_no];
+ const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
+ if (Filter.PassFilter(line_start, line_end))
+ ImGui::TextUnformatted(line_start, line_end);
+ }
+ }
+ else
+ {
+ // The simplest and easy way to display the entire buffer:
+ // ImGui::TextUnformatted(buf_begin, buf_end);
+ // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
+ // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
+ // within the visible area.
+ // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
+ // on your side is recommended. Using ImGuiListClipper requires
+ // - A) random access into your data
+ // - B) items all being the same height,
+ // both of which we can handle since we an array pointing to the beginning of each line of text.
+ // When using the filter (in the block of code above) we don't have random access into the data to display
+ // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
+ // it possible (and would be recommended if you want to search through tens of thousands of entries).
+ ImGuiListClipper clipper;
+ clipper.Begin(LineOffsets.Size);
+ while (clipper.Step())
+ {
+ for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
+ {
+ const char* line_start = buf + LineOffsets[line_no];
+ const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
+ ImGui::TextUnformatted(line_start, line_end);
+ }
+ }
+ clipper.End();
+ }
+ ImGui::PopStyleVar();
+
+ if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
+ ImGui::SetScrollHereY(1.0f);
+
+ ImGui::EndChild();
+ ImGui::End();
+ }
+};
+
+// Demonstrate creating a simple log window with basic filtering.
+static void ShowExampleAppLog(bool* p_open)
+{
+ static ExampleAppLog log;
+
+ // For the demo: add a debug button _BEFORE_ the normal log window contents
+ // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
+ // Most of the contents of the window will be added by the log.Draw() call.
+ ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Example: Log", p_open);
+ IMGUI_DEMO_MARKER("Examples/Log");
+ if (ImGui::SmallButton("[Debug] Add 5 entries"))
+ {
+ static int counter = 0;
+ const char* categories[3] = { "info", "warn", "error" };
+ const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
+ for (int n = 0; n < 5; n++)
+ {
+ const char* category = categories[counter % IM_ARRAYSIZE(categories)];
+ const char* word = words[counter % IM_ARRAYSIZE(words)];
+ log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
+ ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
+ counter++;
+ }
+ }
+ ImGui::End();
+
+ // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
+ log.Draw("Example: Log", p_open);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
+//-----------------------------------------------------------------------------
+
+// Demonstrate create a window with multiple child windows.
+static void ShowExampleAppLayout(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
+ if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
+ {
+ IMGUI_DEMO_MARKER("Examples/Simple layout");
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ if (ImGui::MenuItem("Close")) *p_open = false;
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+
+ // Left
+ static int selected = 0;
+ {
+ ImGui::BeginChild("left pane", ImVec2(150, 0), true);
+ for (int i = 0; i < 100; i++)
+ {
+ // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav
+ char label[128];
+ sprintf(label, "MyObject %d", i);
+ if (ImGui::Selectable(label, selected == i))
+ selected = i;
+ }
+ ImGui::EndChild();
+ }
+ ImGui::SameLine();
+
+ // Right
+ {
+ ImGui::BeginGroup();
+ ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
+ ImGui::Text("MyObject: %d", selected);
+ ImGui::Separator();
+ if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
+ {
+ if (ImGui::BeginTabItem("Description"))
+ {
+ ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
+ ImGui::EndTabItem();
+ }
+ if (ImGui::BeginTabItem("Details"))
+ {
+ ImGui::Text("ID: 0123456789");
+ ImGui::EndTabItem();
+ }
+ ImGui::EndTabBar();
+ }
+ ImGui::EndChild();
+ if (ImGui::Button("Revert")) {}
+ ImGui::SameLine();
+ if (ImGui::Button("Save")) {}
+ ImGui::EndGroup();
+ }
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
+//-----------------------------------------------------------------------------
+
+static void ShowPlaceholderObject(const char* prefix, int uid)
+{
+ // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
+ ImGui::PushID(uid);
+
+ // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high.
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0);
+ ImGui::AlignTextToFramePadding();
+ bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
+ ImGui::TableSetColumnIndex(1);
+ ImGui::Text("my sailor is rich");
+
+ if (node_open)
+ {
+ static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f };
+ for (int i = 0; i < 8; i++)
+ {
+ ImGui::PushID(i); // Use field index as identifier.
+ if (i < 2)
+ {
+ ShowPlaceholderObject("Child", 424242);
+ }
+ else
+ {
+ // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0);
+ ImGui::AlignTextToFramePadding();
+ ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet;
+ ImGui::TreeNodeEx("Field", flags, "Field_%d", i);
+
+ ImGui::TableSetColumnIndex(1);
+ ImGui::SetNextItemWidth(-FLT_MIN);
+ if (i >= 5)
+ ImGui::InputFloat("##value", &placeholder_members[i], 1.0f);
+ else
+ ImGui::DragFloat("##value", &placeholder_members[i], 0.01f);
+ ImGui::NextColumn();
+ }
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+}
+
+// Demonstrate create a simple property editor.
+static void ShowExampleAppPropertyEditor(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin("Example: Property editor", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+ IMGUI_DEMO_MARKER("Examples/Property Editor");
+
+ HelpMarker(
+ "This example shows how you may implement a property editor using two columns.\n"
+ "All objects/fields data are dummies here.\n"
+ "Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n"
+ "your cursor horizontally instead of using the Columns() API.");
+
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
+ if (ImGui::BeginTable("split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable))
+ {
+ // Iterate placeholder objects (all the same data)
+ for (int obj_i = 0; obj_i < 4; obj_i++)
+ {
+ ShowPlaceholderObject("Object", obj_i);
+ //ImGui::Separator();
+ }
+ ImGui::EndTable();
+ }
+ ImGui::PopStyleVar();
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Long Text / ShowExampleAppLongText()
+//-----------------------------------------------------------------------------
+
+// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
+static void ShowExampleAppLongText(bool* p_open)
+{
+ ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
+ if (!ImGui::Begin("Example: Long text display", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+ IMGUI_DEMO_MARKER("Examples/Long text display");
+
+ static int test_type = 0;
+ static ImGuiTextBuffer log;
+ static int lines = 0;
+ ImGui::Text("Printing unusually long amount of text.");
+ ImGui::Combo("Test type", &test_type,
+ "Single call to TextUnformatted()\0"
+ "Multiple calls to Text(), clipped\0"
+ "Multiple calls to Text(), not clipped (slow)\0");
+ ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
+ if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
+ ImGui::SameLine();
+ if (ImGui::Button("Add 1000 lines"))
+ {
+ for (int i = 0; i < 1000; i++)
+ log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
+ lines += 1000;
+ }
+ ImGui::BeginChild("Log");
+ switch (test_type)
+ {
+ case 0:
+ // Single call to TextUnformatted() with a big buffer
+ ImGui::TextUnformatted(log.begin(), log.end());
+ break;
+ case 1:
+ {
+ // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ ImGuiListClipper clipper;
+ clipper.Begin(lines);
+ while (clipper.Step())
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
+ ImGui::PopStyleVar();
+ break;
+ }
+ case 2:
+ // Multiple calls to Text(), not clipped (slow)
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ for (int i = 0; i < lines; i++)
+ ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
+ ImGui::PopStyleVar();
+ break;
+ }
+ ImGui::EndChild();
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a window which gets auto-resized according to its content.
+static void ShowExampleAppAutoResize(bool* p_open)
+{
+ if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::End();
+ return;
+ }
+ IMGUI_DEMO_MARKER("Examples/Auto-resizing window");
+
+ static int lines = 10;
+ ImGui::TextUnformatted(
+ "Window will resize every-frame to the size of its content.\n"
+ "Note that you probably don't want to query the window size to\n"
+ "output your content because that would create a feedback loop.");
+ ImGui::SliderInt("Number of lines", &lines, 1, 20);
+ for (int i = 0; i < lines; i++)
+ ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a window with custom resize constraints.
+static void ShowExampleAppConstrainedResize(bool* p_open)
+{
+ struct CustomConstraints
+ {
+ // Helper functions to demonstrate programmatic constraints
+ static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y); }
+ static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
+ };
+
+ const char* test_desc[] =
+ {
+ "Resize vertical only",
+ "Resize horizontal only",
+ "Width > 100, Height > 100",
+ "Width 400-500",
+ "Height 400-500",
+ "Custom: Always Square",
+ "Custom: Fixed Steps (100)",
+ };
+
+ static bool auto_resize = false;
+ static int type = 0;
+ static int display_lines = 10;
+ if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
+ if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
+ if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
+ if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500
+ if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500
+ if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
+ if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
+
+ ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
+ if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
+ {
+ IMGUI_DEMO_MARKER("Examples/Constrained Resizing window");
+ if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
+ if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
+ if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
+ ImGui::SetNextItemWidth(200);
+ ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
+ ImGui::SetNextItemWidth(200);
+ ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
+ ImGui::Checkbox("Auto-resize", &auto_resize);
+ for (int i = 0; i < display_lines; i++)
+ ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a simple static window with no decoration
+// + a context-menu to choose which corner of the screen to use.
+static void ShowExampleAppSimpleOverlay(bool* p_open)
+{
+ static int corner = 0;
+ ImGuiIO& io = ImGui::GetIO();
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
+ if (corner != -1)
+ {
+ const float PAD = 10.0f;
+ const ImGuiViewport* viewport = ImGui::GetMainViewport();
+ ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
+ ImVec2 work_size = viewport->WorkSize;
+ ImVec2 window_pos, window_pos_pivot;
+ window_pos.x = (corner & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
+ window_pos.y = (corner & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
+ window_pos_pivot.x = (corner & 1) ? 1.0f : 0.0f;
+ window_pos_pivot.y = (corner & 2) ? 1.0f : 0.0f;
+ ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
+ window_flags |= ImGuiWindowFlags_NoMove;
+ }
+ ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
+ if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
+ {
+ IMGUI_DEMO_MARKER("Examples/Simple Overlay");
+ ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
+ ImGui::Separator();
+ if (ImGui::IsMousePosValid())
+ ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
+ else
+ ImGui::Text("Mouse Position: <invalid>");
+ if (ImGui::BeginPopupContextWindow())
+ {
+ if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
+ if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
+ if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
+ if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
+ if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
+ if (p_open && ImGui::MenuItem("Close")) *p_open = false;
+ ImGui::EndPopup();
+ }
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
+//-----------------------------------------------------------------------------
+
+// Demonstrate creating a window covering the entire screen/viewport
+static void ShowExampleAppFullscreen(bool* p_open)
+{
+ static bool use_work_area = true;
+ static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
+
+ // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
+ // Based on your use case you may want one of the other.
+ const ImGuiViewport* viewport = ImGui::GetMainViewport();
+ ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
+ ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
+
+ if (ImGui::Begin("Example: Fullscreen window", p_open, flags))
+ {
+ ImGui::Checkbox("Use work area instead of main area", &use_work_area);
+ ImGui::SameLine();
+ HelpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference.");
+
+ ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground);
+ ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration);
+ ImGui::Indent();
+ ImGui::CheckboxFlags("ImGuiWindowFlags_NoTitleBar", &flags, ImGuiWindowFlags_NoTitleBar);
+ ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse);
+ ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar);
+ ImGui::Unindent();
+
+ if (p_open && ImGui::Button("Close this window"))
+ *p_open = false;
+ }
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
+//-----------------------------------------------------------------------------
+
+// Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
+// This apply to all regular items as well.
+// Read FAQ section "How can I have multiple widgets with the same label?" for details.
+static void ShowExampleAppWindowTitles(bool*)
+{
+ const ImGuiViewport* viewport = ImGui::GetMainViewport();
+ const ImVec2 base_pos = viewport->Pos;
+
+ // By default, Windows are uniquely identified by their title.
+ // You can use the "##" and "###" markers to manipulate the display/ID.
+
+ // Using "##" to display same title but have unique identifier.
+ ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 100), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Same title as another window##1");
+ IMGUI_DEMO_MARKER("Examples/Manipulating window titles");
+ ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
+ ImGui::End();
+
+ ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 200), ImGuiCond_FirstUseEver);
+ ImGui::Begin("Same title as another window##2");
+ ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
+ ImGui::End();
+
+ // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
+ char buf[128];
+ sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
+ ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 300), ImGuiCond_FirstUseEver);
+ ImGui::Begin(buf);
+ ImGui::Text("This window has a changing title.");
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
+//-----------------------------------------------------------------------------
+
+// Demonstrate using the low-level ImDrawList to draw custom shapes.
+static void ShowExampleAppCustomRendering(bool* p_open)
+{
+ if (!ImGui::Begin("Example: Custom rendering", p_open))
+ {
+ ImGui::End();
+ return;
+ }
+ IMGUI_DEMO_MARKER("Examples/Custom Rendering");
+
+ // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
+ // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
+ // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not
+ // exposed outside (to avoid messing with your types) In this example we are not using the maths operators!
+
+ if (ImGui::BeginTabBar("##TabBar"))
+ {
+ if (ImGui::BeginTabItem("Primitives"))
+ {
+ ImGui::PushItemWidth(-ImGui::GetFontSize() * 15);
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+
+ // Draw gradients
+ // (note that those are currently exacerbating our sRGB/Linear issues)
+ // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well..
+ ImGui::Text("Gradients");
+ ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
+ {
+ ImVec2 p0 = ImGui::GetCursorScreenPos();
+ ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
+ ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
+ ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
+ draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
+ ImGui::InvisibleButton("##gradient1", gradient_size);
+ }
+ {
+ ImVec2 p0 = ImGui::GetCursorScreenPos();
+ ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
+ ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
+ ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
+ draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
+ ImGui::InvisibleButton("##gradient2", gradient_size);
+ }
+
+ // Draw a bunch of primitives
+ ImGui::Text("All primitives");
+ static float sz = 36.0f;
+ static float thickness = 3.0f;
+ static int ngon_sides = 6;
+ static bool circle_segments_override = false;
+ static int circle_segments_override_v = 12;
+ static bool curve_segments_override = false;
+ static int curve_segments_override_v = 8;
+ static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
+ ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f");
+ ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
+ ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
+ ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
+ circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 40);
+ ImGui::Checkbox("##curvessegmentoverride", &curve_segments_override);
+ ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
+ curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40);
+ ImGui::ColorEdit4("Color", &colf.x);
+
+ const ImVec2 p = ImGui::GetCursorScreenPos();
+ const ImU32 col = ImColor(colf);
+ const float spacing = 10.0f;
+ const ImDrawFlags corners_tl_br = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight;
+ const float rounding = sz / 5.0f;
+ const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
+ const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
+ float x = p.x + 4.0f;
+ float y = p.y + 4.0f;
+ for (int n = 0; n < 2; n++)
+ {
+ // First line uses a thickness of 1.0f, second line uses the configurable thickness
+ float th = (n == 0) ? 1.0f : thickness;
+ draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon
+ draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners
+ draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
+ draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
+ //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
+ draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
+ draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
+ draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
+
+ // Quadratic Bezier Curve (3 control points)
+ ImVec2 cp3[3] = { ImVec2(x, y + sz * 0.6f), ImVec2(x + sz * 0.5f, y - sz * 0.4f), ImVec2(x + sz, y + sz) };
+ draw_list->AddBezierQuadratic(cp3[0], cp3[1], cp3[2], col, th, curve_segments); x += sz + spacing;
+
+ // Cubic Bezier Curve (4 control points)
+ ImVec2 cp4[4] = { ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz) };
+ draw_list->AddBezierCubic(cp4[0], cp4[1], cp4[2], cp4[3], col, th, curve_segments);
+
+ x = p.x + 4;
+ y += sz + spacing;
+ }
+ draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides); x += sz + spacing; // N-gon
+ draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments); x += sz + spacing; // Circle
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col); x += sz + spacing; // Square
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f); x += sz + spacing; // Square with all rounded corners
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br); x += sz + spacing; // Square with two rounded corners
+ draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col); x += sz + spacing; // Triangle
+ //draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col); x += sz + spacing; // Horizontal line (faster than AddLine, but only handle integer thickness)
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col); x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness)
+ draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col); x += sz; // Pixel (faster than AddLine)
+ draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x + sz, y + sz), IM_COL32(0, 0, 0, 255), IM_COL32(255, 0, 0, 255), IM_COL32(255, 255, 0, 255), IM_COL32(0, 255, 0, 255));
+
+ ImGui::Dummy(ImVec2((sz + spacing) * 10.2f, (sz + spacing) * 3.0f));
+ ImGui::PopItemWidth();
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("Canvas"))
+ {
+ static ImVector<ImVec2> points;
+ static ImVec2 scrolling(0.0f, 0.0f);
+ static bool opt_enable_grid = true;
+ static bool opt_enable_context_menu = true;
+ static bool adding_line = false;
+
+ ImGui::Checkbox("Enable grid", &opt_enable_grid);
+ ImGui::Checkbox("Enable context menu", &opt_enable_context_menu);
+ ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
+
+ // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
+ // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
+ // To use a child window instead we could use, e.g:
+ // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Disable padding
+ // ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255)); // Set a background color
+ // ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_NoMove);
+ // ImGui::PopStyleColor();
+ // ImGui::PopStyleVar();
+ // [...]
+ // ImGui::EndChild();
+
+ // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
+ ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
+ ImVec2 canvas_sz = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
+ if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
+ if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f;
+ ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
+
+ // Draw border and background color
+ ImGuiIO& io = ImGui::GetIO();
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+ draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
+ draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
+
+ // This will catch our interactions
+ ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
+ const bool is_hovered = ImGui::IsItemHovered(); // Hovered
+ const bool is_active = ImGui::IsItemActive(); // Held
+ const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin
+ const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
+
+ // Add first and second point
+ if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
+ {
+ points.push_back(mouse_pos_in_canvas);
+ points.push_back(mouse_pos_in_canvas);
+ adding_line = true;
+ }
+ if (adding_line)
+ {
+ points.back() = mouse_pos_in_canvas;
+ if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
+ adding_line = false;
+ }
+
+ // Pan (we use a zero mouse threshold when there's no context menu)
+ // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
+ const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
+ if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan))
+ {
+ scrolling.x += io.MouseDelta.x;
+ scrolling.y += io.MouseDelta.y;
+ }
+
+ // Context menu (under default mouse threshold)
+ ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
+ if (opt_enable_context_menu && ImGui::IsMouseReleased(ImGuiMouseButton_Right) && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
+ ImGui::OpenPopupOnItemClick("context");
+ if (ImGui::BeginPopup("context"))
+ {
+ if (adding_line)
+ points.resize(points.size() - 2);
+ adding_line = false;
+ if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); }
+ if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); }
+ ImGui::EndPopup();
+ }
+
+ // Draw grid + all lines in the canvas
+ draw_list->PushClipRect(canvas_p0, canvas_p1, true);
+ if (opt_enable_grid)
+ {
+ const float GRID_STEP = 64.0f;
+ for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
+ draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40));
+ for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
+ draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40));
+ }
+ for (int n = 0; n < points.Size; n += 2)
+ draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
+ draw_list->PopClipRect();
+
+ ImGui::EndTabItem();
+ }
+
+ if (ImGui::BeginTabItem("BG/FG draw lists"))
+ {
+ static bool draw_bg = true;
+ static bool draw_fg = true;
+ ImGui::Checkbox("Draw in Background draw list", &draw_bg);
+ ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
+ ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
+ ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
+ ImVec2 window_pos = ImGui::GetWindowPos();
+ ImVec2 window_size = ImGui::GetWindowSize();
+ ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
+ if (draw_bg)
+ ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
+ if (draw_fg)
+ ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
+ ImGui::EndTabItem();
+ }
+
+ ImGui::EndTabBar();
+ }
+
+ ImGui::End();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
+//-----------------------------------------------------------------------------
+
+// Simplified structure to mimic a Document model
+struct MyDocument
+{
+ const char* Name; // Document title
+ bool Open; // Set when open (we keep an array of all available documents to simplify demo code!)
+ bool OpenPrev; // Copy of Open from last update.
+ bool Dirty; // Set when the document has been modified
+ bool WantClose; // Set when the document
+ ImVec4 Color; // An arbitrary variable associated to the document
+
+ MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
+ {
+ Name = name;
+ Open = OpenPrev = open;
+ Dirty = false;
+ WantClose = false;
+ Color = color;
+ }
+ void DoOpen() { Open = true; }
+ void DoQueueClose() { WantClose = true; }
+ void DoForceClose() { Open = false; Dirty = false; }
+ void DoSave() { Dirty = false; }
+
+ // Display placeholder contents for the Document
+ static void DisplayContents(MyDocument* doc)
+ {
+ ImGui::PushID(doc);
+ ImGui::Text("Document \"%s\"", doc->Name);
+ ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
+ ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
+ ImGui::PopStyleColor();
+ if (ImGui::Button("Modify", ImVec2(100, 0)))
+ doc->Dirty = true;
+ ImGui::SameLine();
+ if (ImGui::Button("Save", ImVec2(100, 0)))
+ doc->DoSave();
+ ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
+ ImGui::PopID();
+ }
+
+ // Display context menu for the Document
+ static void DisplayContextMenu(MyDocument* doc)
+ {
+ if (!ImGui::BeginPopupContextItem())
+ return;
+
+ char buf[256];
+ sprintf(buf, "Save %s", doc->Name);
+ if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
+ doc->DoSave();
+ if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
+ doc->DoQueueClose();
+ ImGui::EndPopup();
+ }
+};
+
+struct ExampleAppDocuments
+{
+ ImVector<MyDocument> Documents;
+
+ ExampleAppDocuments()
+ {
+ Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
+ Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
+ Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
+ Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
+ Documents.push_back(MyDocument("A Rather Long Title", false));
+ Documents.push_back(MyDocument("Some Document", false));
+ }
+};
+
+// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
+// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
+// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
+// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
+// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
+// give the impression of a flicker for one frame.
+// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
+// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
+static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
+{
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (!doc->Open && doc->OpenPrev)
+ ImGui::SetTabItemClosed(doc->Name);
+ doc->OpenPrev = doc->Open;
+ }
+}
+
+void ShowExampleAppDocuments(bool* p_open)
+{
+ static ExampleAppDocuments app;
+
+ // Options
+ static bool opt_reorderable = true;
+ static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
+
+ bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
+ if (!window_contents_visible)
+ {
+ ImGui::End();
+ return;
+ }
+
+ // Menu
+ if (ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("File"))
+ {
+ int open_count = 0;
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ open_count += app.Documents[doc_n].Open ? 1 : 0;
+
+ if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
+ {
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (!doc->Open)
+ if (ImGui::MenuItem(doc->Name))
+ doc->DoOpen();
+ }
+ ImGui::EndMenu();
+ }
+ if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ app.Documents[doc_n].DoQueueClose();
+ if (ImGui::MenuItem("Exit", "Alt+F4")) {}
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+
+ // [Debug] List documents with one checkbox for each
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (doc_n > 0)
+ ImGui::SameLine();
+ ImGui::PushID(doc);
+ if (ImGui::Checkbox(doc->Name, &doc->Open))
+ if (!doc->Open)
+ doc->DoForceClose();
+ ImGui::PopID();
+ }
+
+ ImGui::Separator();
+
+ // About the ImGuiWindowFlags_UnsavedDocument / ImGuiTabItemFlags_UnsavedDocument flags.
+ // They have multiple effects:
+ // - Display a dot next to the title.
+ // - Tab is selected when clicking the X close button.
+ // - Closure is not assumed (will wait for user to stop submitting the tab).
+ // Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
+ // We need to assume closure by default otherwise waiting for "lack of submission" on the next frame would leave an empty
+ // hole for one-frame, both in the tab-bar and in tab-contents when closing a tab/window.
+ // The rarely used SetTabItemClosed() function is a way to notify of programmatic closure to avoid the one-frame hole.
+
+ // Submit Tab Bar and Tabs
+ {
+ ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
+ if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
+ {
+ if (opt_reorderable)
+ NotifyOfDocumentsClosedElsewhere(app);
+
+ // [DEBUG] Stress tests
+ //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
+ //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
+
+ // Submit Tabs
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (!doc->Open)
+ continue;
+
+ ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
+ bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
+
+ // Cancel attempt to close when unsaved add to save queue so we can display a popup.
+ if (!doc->Open && doc->Dirty)
+ {
+ doc->Open = true;
+ doc->DoQueueClose();
+ }
+
+ MyDocument::DisplayContextMenu(doc);
+ if (visible)
+ {
+ MyDocument::DisplayContents(doc);
+ ImGui::EndTabItem();
+ }
+ }
+
+ ImGui::EndTabBar();
+ }
+ }
+
+ // Update closing queue
+ static ImVector<MyDocument*> close_queue;
+ if (close_queue.empty())
+ {
+ // Close queue is locked once we started a popup
+ for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
+ {
+ MyDocument* doc = &app.Documents[doc_n];
+ if (doc->WantClose)
+ {
+ doc->WantClose = false;
+ close_queue.push_back(doc);
+ }
+ }
+ }
+
+ // Display closing confirmation UI
+ if (!close_queue.empty())
+ {
+ int close_queue_unsaved_documents = 0;
+ for (int n = 0; n < close_queue.Size; n++)
+ if (close_queue[n]->Dirty)
+ close_queue_unsaved_documents++;
+
+ if (close_queue_unsaved_documents == 0)
+ {
+ // Close documents when all are unsaved
+ for (int n = 0; n < close_queue.Size; n++)
+ close_queue[n]->DoForceClose();
+ close_queue.clear();
+ }
+ else
+ {
+ if (!ImGui::IsPopupOpen("Save?"))
+ ImGui::OpenPopup("Save?");
+ if (ImGui::BeginPopupModal("Save?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
+ {
+ ImGui::Text("Save change to the following items?");
+ float item_height = ImGui::GetTextLineHeightWithSpacing();
+ if (ImGui::BeginChildFrame(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height)))
+ {
+ for (int n = 0; n < close_queue.Size; n++)
+ if (close_queue[n]->Dirty)
+ ImGui::Text("%s", close_queue[n]->Name);
+ ImGui::EndChildFrame();
+ }
+
+ ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
+ if (ImGui::Button("Yes", button_size))
+ {
+ for (int n = 0; n < close_queue.Size; n++)
+ {
+ if (close_queue[n]->Dirty)
+ close_queue[n]->DoSave();
+ close_queue[n]->DoForceClose();
+ }
+ close_queue.clear();
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("No", button_size))
+ {
+ for (int n = 0; n < close_queue.Size; n++)
+ close_queue[n]->DoForceClose();
+ close_queue.clear();
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button("Cancel", button_size))
+ {
+ close_queue.clear();
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::EndPopup();
+ }
+ }
+ }
+
+ ImGui::End();
+}
+
+// End of Demo code
+#else
+
+void ImGui::ShowAboutWindow(bool*) {}
+void ImGui::ShowDemoWindow(bool*) {}
+void ImGui::ShowUserGuide() {}
+void ImGui::ShowStyleEditor(ImGuiStyle*) {}
+
+#endif
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imgui_draw.cpp b/Client/ThirdParty/imgui/imgui_draw.cpp
new file mode 100644
index 0000000..809c849
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui_draw.cpp
@@ -0,0 +1,4179 @@
+// dear imgui, v1.86 WIP
+// (drawing and font code)
+
+/*
+
+Index of this file:
+
+// [SECTION] STB libraries implementation
+// [SECTION] Style functions
+// [SECTION] ImDrawList
+// [SECTION] ImDrawListSplitter
+// [SECTION] ImDrawData
+// [SECTION] Helpers ShadeVertsXXX functions
+// [SECTION] ImFontConfig
+// [SECTION] ImFontAtlas
+// [SECTION] ImFontAtlas glyph ranges helpers
+// [SECTION] ImFontGlyphRangesBuilder
+// [SECTION] ImFont
+// [SECTION] ImGui Internal Render Helpers
+// [SECTION] Decompression code
+// [SECTION] Default font data (ProggyClean.ttf)
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DISABLE
+
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+
+#include "imgui_internal.h"
+#ifdef IMGUI_ENABLE_FREETYPE
+#include "misc/freetype/imgui_freetype.h"
+#endif
+
+#include <stdio.h> // vsnprintf, sscanf, printf
+#if !defined(alloca)
+#if defined(__GLIBC__) || defined(__sun) || defined(__APPLE__) || defined(__NEWLIB__)
+#include <alloca.h> // alloca (glibc uses <alloca.h>. Note that Cygwin may have _WIN32 defined, so the order matters here)
+#elif defined(_WIN32)
+#include <malloc.h> // alloca
+#if !defined(alloca)
+#define alloca _alloca // for clang with MS Codegen
+#endif
+#else
+#include <stdlib.h> // alloca
+#endif
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#pragma warning (disable: 6255) // [Static Analyzer] _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead.
+#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
+#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
+#endif
+
+// Clang/GCC warnings with -Weverything
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
+#endif
+#if __has_warning("-Walloca")
+#pragma clang diagnostic ignored "-Walloca" // warning: use of function '__builtin_alloca' is discouraged
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
+#pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
+#pragma clang diagnostic ignored "-Wcomma" // warning: possible misuse of comma operator here
+#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
+#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
+#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
+#pragma GCC diagnostic ignored "-Wstack-protector" // warning: stack protector not protecting local variables: variable length buffer
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+
+//-------------------------------------------------------------------------
+// [SECTION] STB libraries implementation
+//-------------------------------------------------------------------------
+
+// Compile time options:
+//#define IMGUI_STB_NAMESPACE ImStb
+//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
+//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
+//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
+//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
+
+#ifdef IMGUI_STB_NAMESPACE
+namespace IMGUI_STB_NAMESPACE
+{
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration
+#pragma warning (disable: 6011) // (stb_rectpack) Dereferencing NULL pointer 'cur->next'.
+#pragma warning (disable: 6385) // (stb_truetype) Reading invalid data from 'buffer': the readable size is '_Old_3`kernel_width' bytes, but '3' bytes may be read.
+#pragma warning (disable: 28182) // (stb_rectpack) Dereferencing NULL pointer. 'cur' contains the same NULL value as 'cur->next' did.
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wmissing-prototypes"
+#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
+#pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier
+#endif
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits]
+#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
+#endif
+
+#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
+#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in another compilation unit
+#define STBRP_STATIC
+#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0)
+#define STBRP_SORT ImQsort
+#define STB_RECT_PACK_IMPLEMENTATION
+#endif
+#ifdef IMGUI_STB_RECT_PACK_FILENAME
+#include IMGUI_STB_RECT_PACK_FILENAME
+#else
+#include "imstb_rectpack.h"
+#endif
+#endif
+
+#ifdef IMGUI_ENABLE_STB_TRUETYPE
+#ifndef STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
+#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in another compilation unit
+#define STBTT_malloc(x,u) ((void)(u), IM_ALLOC(x))
+#define STBTT_free(x,u) ((void)(u), IM_FREE(x))
+#define STBTT_assert(x) do { IM_ASSERT(x); } while(0)
+#define STBTT_fmod(x,y) ImFmod(x,y)
+#define STBTT_sqrt(x) ImSqrt(x)
+#define STBTT_pow(x,y) ImPow(x,y)
+#define STBTT_fabs(x) ImFabs(x)
+#define STBTT_ifloor(x) ((int)ImFloorSigned(x))
+#define STBTT_iceil(x) ((int)ImCeil(x))
+#define STBTT_STATIC
+#define STB_TRUETYPE_IMPLEMENTATION
+#else
+#define STBTT_DEF extern
+#endif
+#ifdef IMGUI_STB_TRUETYPE_FILENAME
+#include IMGUI_STB_TRUETYPE_FILENAME
+#else
+#include "imstb_truetype.h"
+#endif
+#endif
+#endif // IMGUI_ENABLE_STB_TRUETYPE
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+
+#ifdef IMGUI_STB_NAMESPACE
+} // namespace ImStb
+using namespace IMGUI_STB_NAMESPACE;
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] Style functions
+//-----------------------------------------------------------------------------
+
+void ImGui::StyleColorsDark(ImGuiStyle* dst)
+{
+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+ ImVec4* colors = style->Colors;
+
+ colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+ colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
+ colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
+ colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
+ colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f);
+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f);
+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
+ colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
+ colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
+ colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];
+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
+ colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f);
+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+ colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
+ colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
+ colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
+ colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
+ colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
+ colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f);
+ colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); // Prefer using Alpha=1.0 here
+ colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); // Prefer using Alpha=1.0 here
+ colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
+ colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
+ colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
+ colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
+ colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
+}
+
+void ImGui::StyleColorsClassic(ImGuiStyle* dst)
+{
+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+ ImVec4* colors = style->Colors;
+
+ colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
+ colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
+ colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f);
+ colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
+ colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);
+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f);
+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f);
+ colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);
+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);
+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);
+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);
+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
+ colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
+ colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
+ colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f);
+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.48f, 0.71f, 0.79f);
+ colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.54f, 0.80f, 1.00f);
+ colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
+ colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
+ colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f);
+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
+ colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
+ colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
+ colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
+ colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
+ colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
+ colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
+ colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
+ colors[ImGuiCol_TableHeaderBg] = ImVec4(0.27f, 0.27f, 0.38f, 1.00f);
+ colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.45f, 1.00f); // Prefer using Alpha=1.0 here
+ colors[ImGuiCol_TableBorderLight] = ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here
+ colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
+ colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
+ colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
+ colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
+ colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
+}
+
+// Those light colors are better suited with a thicker font than the default one + FrameBorder
+void ImGui::StyleColorsLight(ImGuiStyle* dst)
+{
+ ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
+ ImVec4* colors = style->Colors;
+
+ colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
+ colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
+ colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f);
+ colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f);
+ colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f);
+ colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
+ colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f);
+ colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);
+ colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f);
+ colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
+ colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f);
+ colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f);
+ colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
+ colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
+ colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
+ colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
+ colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
+ colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
+ colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
+ colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
+ colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
+ colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f);
+ colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f);
+ colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f);
+ colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f);
+ colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
+ colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+ colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
+ colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
+ colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
+ colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
+ colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
+ colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
+ colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
+ colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f);
+ colors[ImGuiCol_TableHeaderBg] = ImVec4(0.78f, 0.87f, 0.98f, 1.00f);
+ colors[ImGuiCol_TableBorderStrong] = ImVec4(0.57f, 0.57f, 0.64f, 1.00f); // Prefer using Alpha=1.0 here
+ colors[ImGuiCol_TableBorderLight] = ImVec4(0.68f, 0.68f, 0.74f, 1.00f); // Prefer using Alpha=1.0 here
+ colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
+ colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f);
+ colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
+ colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
+ colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
+ colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
+ colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);
+ colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImDrawList
+//-----------------------------------------------------------------------------
+
+ImDrawListSharedData::ImDrawListSharedData()
+{
+ memset(this, 0, sizeof(*this));
+ for (int i = 0; i < IM_ARRAYSIZE(ArcFastVtx); i++)
+ {
+ const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx);
+ ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a));
+ }
+ ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
+}
+
+void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
+{
+ if (CircleSegmentMaxError == max_error)
+ return;
+
+ IM_ASSERT(max_error > 0.0f);
+ CircleSegmentMaxError = max_error;
+ for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++)
+ {
+ const float radius = (float)i;
+ CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : 0);
+ }
+ ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
+}
+
+// Initialize before use in a new frame. We always have a command ready in the buffer.
+void ImDrawList::_ResetForNewFrame()
+{
+ // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory.
+ // (those should be IM_STATIC_ASSERT() in theory but with our pre C++11 setup the whole check doesn't compile with GCC)
+ IM_ASSERT(IM_OFFSETOF(ImDrawCmd, ClipRect) == 0);
+ IM_ASSERT(IM_OFFSETOF(ImDrawCmd, TextureId) == sizeof(ImVec4));
+ IM_ASSERT(IM_OFFSETOF(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID));
+
+ CmdBuffer.resize(0);
+ IdxBuffer.resize(0);
+ VtxBuffer.resize(0);
+ Flags = _Data->InitialFlags;
+ memset(&_CmdHeader, 0, sizeof(_CmdHeader));
+ _VtxCurrentIdx = 0;
+ _VtxWritePtr = NULL;
+ _IdxWritePtr = NULL;
+ _ClipRectStack.resize(0);
+ _TextureIdStack.resize(0);
+ _Path.resize(0);
+ _Splitter.Clear();
+ CmdBuffer.push_back(ImDrawCmd());
+ _FringeScale = 1.0f;
+}
+
+void ImDrawList::_ClearFreeMemory()
+{
+ CmdBuffer.clear();
+ IdxBuffer.clear();
+ VtxBuffer.clear();
+ Flags = ImDrawListFlags_None;
+ _VtxCurrentIdx = 0;
+ _VtxWritePtr = NULL;
+ _IdxWritePtr = NULL;
+ _ClipRectStack.clear();
+ _TextureIdStack.clear();
+ _Path.clear();
+ _Splitter.ClearFreeMemory();
+}
+
+ImDrawList* ImDrawList::CloneOutput() const
+{
+ ImDrawList* dst = IM_NEW(ImDrawList(_Data));
+ dst->CmdBuffer = CmdBuffer;
+ dst->IdxBuffer = IdxBuffer;
+ dst->VtxBuffer = VtxBuffer;
+ dst->Flags = Flags;
+ return dst;
+}
+
+void ImDrawList::AddDrawCmd()
+{
+ ImDrawCmd draw_cmd;
+ draw_cmd.ClipRect = _CmdHeader.ClipRect; // Same as calling ImDrawCmd_HeaderCopy()
+ draw_cmd.TextureId = _CmdHeader.TextureId;
+ draw_cmd.VtxOffset = _CmdHeader.VtxOffset;
+ draw_cmd.IdxOffset = IdxBuffer.Size;
+
+ IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
+ CmdBuffer.push_back(draw_cmd);
+}
+
+// Pop trailing draw command (used before merging or presenting to user)
+// Note that this leaves the ImDrawList in a state unfit for further commands, as most code assume that CmdBuffer.Size > 0 && CmdBuffer.back().UserCallback == NULL
+void ImDrawList::_PopUnusedDrawCmd()
+{
+ if (CmdBuffer.Size == 0)
+ return;
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount == 0 && curr_cmd->UserCallback == NULL)
+ CmdBuffer.pop_back();
+}
+
+void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
+{
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
+ if (curr_cmd->ElemCount != 0)
+ {
+ AddDrawCmd();
+ curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ }
+ curr_cmd->UserCallback = callback;
+ curr_cmd->UserCallbackData = callback_data;
+
+ AddDrawCmd(); // Force a new command after us (see comment below)
+}
+
+// Compare ClipRect, TextureId and VtxOffset with a single memcmp()
+#define ImDrawCmd_HeaderSize (IM_OFFSETOF(ImDrawCmd, VtxOffset) + sizeof(unsigned int))
+#define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset
+#define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset
+
+// Try to merge two last draw commands
+void ImDrawList::_TryMergeDrawCmds()
+{
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ ImDrawCmd* prev_cmd = curr_cmd - 1;
+ if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL)
+ {
+ prev_cmd->ElemCount += curr_cmd->ElemCount;
+ CmdBuffer.pop_back();
+ }
+}
+
+// Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.
+// The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.
+void ImDrawList::_OnChangedClipRect()
+{
+ // If current command is used with different settings we need to add a new command
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0)
+ {
+ AddDrawCmd();
+ return;
+ }
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
+
+ // Try to merge with previous command if it matches, else use current command
+ ImDrawCmd* prev_cmd = curr_cmd - 1;
+ if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL)
+ {
+ CmdBuffer.pop_back();
+ return;
+ }
+
+ curr_cmd->ClipRect = _CmdHeader.ClipRect;
+}
+
+void ImDrawList::_OnChangedTextureID()
+{
+ // If current command is used with different settings we need to add a new command
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId)
+ {
+ AddDrawCmd();
+ return;
+ }
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
+
+ // Try to merge with previous command if it matches, else use current command
+ ImDrawCmd* prev_cmd = curr_cmd - 1;
+ if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && prev_cmd->UserCallback == NULL)
+ {
+ CmdBuffer.pop_back();
+ return;
+ }
+
+ curr_cmd->TextureId = _CmdHeader.TextureId;
+}
+
+void ImDrawList::_OnChangedVtxOffset()
+{
+ // We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this.
+ _VtxCurrentIdx = 0;
+ ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ //IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349
+ if (curr_cmd->ElemCount != 0)
+ {
+ AddDrawCmd();
+ return;
+ }
+ IM_ASSERT(curr_cmd->UserCallback == NULL);
+ curr_cmd->VtxOffset = _CmdHeader.VtxOffset;
+}
+
+int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
+{
+ // Automatic segment count
+ const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy
+ if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
+ return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
+ else
+ return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
+}
+
+// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
+void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect)
+{
+ ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);
+ if (intersect_with_current_clip_rect)
+ {
+ ImVec4 current = _CmdHeader.ClipRect;
+ if (cr.x < current.x) cr.x = current.x;
+ if (cr.y < current.y) cr.y = current.y;
+ if (cr.z > current.z) cr.z = current.z;
+ if (cr.w > current.w) cr.w = current.w;
+ }
+ cr.z = ImMax(cr.x, cr.z);
+ cr.w = ImMax(cr.y, cr.w);
+
+ _ClipRectStack.push_back(cr);
+ _CmdHeader.ClipRect = cr;
+ _OnChangedClipRect();
+}
+
+void ImDrawList::PushClipRectFullScreen()
+{
+ PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w));
+}
+
+void ImDrawList::PopClipRect()
+{
+ _ClipRectStack.pop_back();
+ _CmdHeader.ClipRect = (_ClipRectStack.Size == 0) ? _Data->ClipRectFullscreen : _ClipRectStack.Data[_ClipRectStack.Size - 1];
+ _OnChangedClipRect();
+}
+
+void ImDrawList::PushTextureID(ImTextureID texture_id)
+{
+ _TextureIdStack.push_back(texture_id);
+ _CmdHeader.TextureId = texture_id;
+ _OnChangedTextureID();
+}
+
+void ImDrawList::PopTextureID()
+{
+ _TextureIdStack.pop_back();
+ _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1];
+ _OnChangedTextureID();
+}
+
+// Reserve space for a number of vertices and indices.
+// You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or
+// submit the intermediate results. PrimUnreserve() can be used to release unused allocations.
+void ImDrawList::PrimReserve(int idx_count, int vtx_count)
+{
+ // Large mesh support (when enabled)
+ IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0);
+ if (sizeof(ImDrawIdx) == 2 && (_VtxCurrentIdx + vtx_count >= (1 << 16)) && (Flags & ImDrawListFlags_AllowVtxOffset))
+ {
+ // FIXME: In theory we should be testing that vtx_count <64k here.
+ // In practice, RenderText() relies on reserving ahead for a worst case scenario so it is currently useful for us
+ // to not make that check until we rework the text functions to handle clipping and large horizontal lines better.
+ _CmdHeader.VtxOffset = VtxBuffer.Size;
+ _OnChangedVtxOffset();
+ }
+
+ ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ draw_cmd->ElemCount += idx_count;
+
+ int vtx_buffer_old_size = VtxBuffer.Size;
+ VtxBuffer.resize(vtx_buffer_old_size + vtx_count);
+ _VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size;
+
+ int idx_buffer_old_size = IdxBuffer.Size;
+ IdxBuffer.resize(idx_buffer_old_size + idx_count);
+ _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size;
+}
+
+// Release the a number of reserved vertices/indices from the end of the last reservation made with PrimReserve().
+void ImDrawList::PrimUnreserve(int idx_count, int vtx_count)
+{
+ IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0);
+
+ ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+ draw_cmd->ElemCount -= idx_count;
+ VtxBuffer.shrink(VtxBuffer.Size - vtx_count);
+ IdxBuffer.shrink(IdxBuffer.Size - idx_count);
+}
+
+// Fully unrolled with inline call to keep our debug builds decently fast.
+void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col)
+{
+ ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel);
+ ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
+ _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
+ _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
+ _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+ _VtxCurrentIdx += 4;
+ _IdxWritePtr += 6;
+}
+
+void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col)
+{
+ ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y);
+ ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
+ _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
+ _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
+ _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+ _VtxCurrentIdx += 4;
+ _IdxWritePtr += 6;
+}
+
+void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)
+{
+ ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
+ _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2);
+ _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3);
+ _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+ _VtxCurrentIdx += 4;
+ _IdxWritePtr += 6;
+}
+
+// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds.
+// - Those macros expects l-values and need to be used as their own statement.
+// - Those macros are intentionally not surrounded by the 'do {} while (0)' idiom because even that translates to runtime with debug compilers.
+#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } (void)0
+#define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)
+#define IM_FIXNORMAL2F(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } (void)0
+
+// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
+// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
+void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
+{
+ if (points_count < 2)
+ return;
+
+ const bool closed = (flags & ImDrawFlags_Closed) != 0;
+ const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
+ const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
+ const bool thick_line = (thickness > _FringeScale);
+
+ if (Flags & ImDrawListFlags_AntiAliasedLines)
+ {
+ // Anti-aliased stroke
+ const float AA_SIZE = _FringeScale;
+ const ImU32 col_trans = col & ~IM_COL32_A_MASK;
+
+ // Thicknesses <1.0 should behave like thickness 1.0
+ thickness = ImMax(thickness, 1.0f);
+ const int integer_thickness = (int)thickness;
+ const float fractional_thickness = thickness - integer_thickness;
+
+ // Do we want to draw this line using a texture?
+ // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved.
+ // - If AA_SIZE is not 1.0f we cannot use the texture path.
+ const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f);
+
+ // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off
+ IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines));
+
+ const int idx_count = use_texture ? (count * 6) : (thick_line ? count * 18 : count * 12);
+ const int vtx_count = use_texture ? (points_count * 2) : (thick_line ? points_count * 4 : points_count * 3);
+ PrimReserve(idx_count, vtx_count);
+
+ // Temporary buffer
+ // The first <points_count> items are normals at each line point, then after that there are either 2 or 4 temp points for each line point
+ ImVec2* temp_normals = (ImVec2*)alloca(points_count * ((use_texture || !thick_line) ? 3 : 5) * sizeof(ImVec2)); //-V630
+ ImVec2* temp_points = temp_normals + points_count;
+
+ // Calculate normals (tangents) for each line segment
+ for (int i1 = 0; i1 < count; i1++)
+ {
+ const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
+ float dx = points[i2].x - points[i1].x;
+ float dy = points[i2].y - points[i1].y;
+ IM_NORMALIZE2F_OVER_ZERO(dx, dy);
+ temp_normals[i1].x = dy;
+ temp_normals[i1].y = -dx;
+ }
+ if (!closed)
+ temp_normals[points_count - 1] = temp_normals[points_count - 2];
+
+ // If we are drawing a one-pixel-wide line without a texture, or a textured line of any width, we only need 2 or 3 vertices per point
+ if (use_texture || !thick_line)
+ {
+ // [PATH 1] Texture-based lines (thick or non-thick)
+ // [PATH 2] Non texture-based lines (non-thick)
+
+ // The width of the geometry we need to draw - this is essentially <thickness> pixels for the line itself, plus "one pixel" for AA.
+ // - In the texture-based path, we don't use AA_SIZE here because the +1 is tied to the generated texture
+ // (see ImFontAtlasBuildRenderLinesTexData() function), and so alternate values won't work without changes to that code.
+ // - In the non texture-based paths, we would allow AA_SIZE to potentially be != 1.0f with a patch (e.g. fringe_scale patch to
+ // allow scaling geometry while preserving one-screen-pixel AA fringe).
+ const float half_draw_size = use_texture ? ((thickness * 0.5f) + 1) : AA_SIZE;
+
+ // If line is not closed, the first and last points need to be generated differently as there are no normals to blend
+ if (!closed)
+ {
+ temp_points[0] = points[0] + temp_normals[0] * half_draw_size;
+ temp_points[1] = points[0] - temp_normals[0] * half_draw_size;
+ temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * half_draw_size;
+ temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * half_draw_size;
+ }
+
+ // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges
+ // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps)
+ // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
+ unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment
+ for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment
+ {
+ const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; // i2 is the second point of the line segment
+ const unsigned int idx2 = ((i1 + 1) == points_count) ? _VtxCurrentIdx : (idx1 + (use_texture ? 2 : 3)); // Vertex index for end of segment
+
+ // Average normals
+ float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
+ float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f;
+ IM_FIXNORMAL2F(dm_x, dm_y);
+ dm_x *= half_draw_size; // dm_x, dm_y are offset to the outer edge of the AA area
+ dm_y *= half_draw_size;
+
+ // Add temporary vertexes for the outer edges
+ ImVec2* out_vtx = &temp_points[i2 * 2];
+ out_vtx[0].x = points[i2].x + dm_x;
+ out_vtx[0].y = points[i2].y + dm_y;
+ out_vtx[1].x = points[i2].x - dm_x;
+ out_vtx[1].y = points[i2].y - dm_y;
+
+ if (use_texture)
+ {
+ // Add indices for two triangles
+ _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 1); // Right tri
+ _IdxWritePtr[3] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[4] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Left tri
+ _IdxWritePtr += 6;
+ }
+ else
+ {
+ // Add indexes for four triangles
+ _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); // Right tri 1
+ _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Right tri 2
+ _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); // Left tri 1
+ _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); // Left tri 2
+ _IdxWritePtr += 12;
+ }
+
+ idx1 = idx2;
+ }
+
+ // Add vertexes for each point on the line
+ if (use_texture)
+ {
+ // If we're using textures we only need to emit the left/right edge vertices
+ ImVec4 tex_uvs = _Data->TexUvLines[integer_thickness];
+ /*if (fractional_thickness != 0.0f) // Currently always zero when use_texture==false!
+ {
+ const ImVec4 tex_uvs_1 = _Data->TexUvLines[integer_thickness + 1];
+ tex_uvs.x = tex_uvs.x + (tex_uvs_1.x - tex_uvs.x) * fractional_thickness; // inlined ImLerp()
+ tex_uvs.y = tex_uvs.y + (tex_uvs_1.y - tex_uvs.y) * fractional_thickness;
+ tex_uvs.z = tex_uvs.z + (tex_uvs_1.z - tex_uvs.z) * fractional_thickness;
+ tex_uvs.w = tex_uvs.w + (tex_uvs_1.w - tex_uvs.w) * fractional_thickness;
+ }*/
+ ImVec2 tex_uv0(tex_uvs.x, tex_uvs.y);
+ ImVec2 tex_uv1(tex_uvs.z, tex_uvs.w);
+ for (int i = 0; i < points_count; i++)
+ {
+ _VtxWritePtr[0].pos = temp_points[i * 2 + 0]; _VtxWritePtr[0].uv = tex_uv0; _VtxWritePtr[0].col = col; // Left-side outer edge
+ _VtxWritePtr[1].pos = temp_points[i * 2 + 1]; _VtxWritePtr[1].uv = tex_uv1; _VtxWritePtr[1].col = col; // Right-side outer edge
+ _VtxWritePtr += 2;
+ }
+ }
+ else
+ {
+ // If we're not using a texture, we need the center vertex as well
+ for (int i = 0; i < points_count; i++)
+ {
+ _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; // Center of line
+ _VtxWritePtr[1].pos = temp_points[i * 2 + 0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans; // Left-side outer edge
+ _VtxWritePtr[2].pos = temp_points[i * 2 + 1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans; // Right-side outer edge
+ _VtxWritePtr += 3;
+ }
+ }
+ }
+ else
+ {
+ // [PATH 2] Non texture-based lines (thick): we need to draw the solid line core and thus require four vertices per point
+ const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
+
+ // If line is not closed, the first and last points need to be generated differently as there are no normals to blend
+ if (!closed)
+ {
+ const int points_last = points_count - 1;
+ temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE);
+ temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness);
+ temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness);
+ temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE);
+ temp_points[points_last * 4 + 0] = points[points_last] + temp_normals[points_last] * (half_inner_thickness + AA_SIZE);
+ temp_points[points_last * 4 + 1] = points[points_last] + temp_normals[points_last] * (half_inner_thickness);
+ temp_points[points_last * 4 + 2] = points[points_last] - temp_normals[points_last] * (half_inner_thickness);
+ temp_points[points_last * 4 + 3] = points[points_last] - temp_normals[points_last] * (half_inner_thickness + AA_SIZE);
+ }
+
+ // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges
+ // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps)
+ // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
+ unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment
+ for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment
+ {
+ const int i2 = (i1 + 1) == points_count ? 0 : (i1 + 1); // i2 is the second point of the line segment
+ const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : (idx1 + 4); // Vertex index for end of segment
+
+ // Average normals
+ float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
+ float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f;
+ IM_FIXNORMAL2F(dm_x, dm_y);
+ float dm_out_x = dm_x * (half_inner_thickness + AA_SIZE);
+ float dm_out_y = dm_y * (half_inner_thickness + AA_SIZE);
+ float dm_in_x = dm_x * half_inner_thickness;
+ float dm_in_y = dm_y * half_inner_thickness;
+
+ // Add temporary vertices
+ ImVec2* out_vtx = &temp_points[i2 * 4];
+ out_vtx[0].x = points[i2].x + dm_out_x;
+ out_vtx[0].y = points[i2].y + dm_out_y;
+ out_vtx[1].x = points[i2].x + dm_in_x;
+ out_vtx[1].y = points[i2].y + dm_in_y;
+ out_vtx[2].x = points[i2].x - dm_in_x;
+ out_vtx[2].y = points[i2].y - dm_in_y;
+ out_vtx[3].x = points[i2].x - dm_out_x;
+ out_vtx[3].y = points[i2].y - dm_out_y;
+
+ // Add indexes
+ _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2);
+ _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 1);
+ _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0);
+ _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1);
+ _IdxWritePtr[12] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[13] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[14] = (ImDrawIdx)(idx1 + 3);
+ _IdxWritePtr[15] = (ImDrawIdx)(idx1 + 3); _IdxWritePtr[16] = (ImDrawIdx)(idx2 + 3); _IdxWritePtr[17] = (ImDrawIdx)(idx2 + 2);
+ _IdxWritePtr += 18;
+
+ idx1 = idx2;
+ }
+
+ // Add vertices
+ for (int i = 0; i < points_count; i++)
+ {
+ _VtxWritePtr[0].pos = temp_points[i * 4 + 0]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col_trans;
+ _VtxWritePtr[1].pos = temp_points[i * 4 + 1]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos = temp_points[i * 4 + 2]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos = temp_points[i * 4 + 3]; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col_trans;
+ _VtxWritePtr += 4;
+ }
+ }
+ _VtxCurrentIdx += (ImDrawIdx)vtx_count;
+ }
+ else
+ {
+ // [PATH 4] Non texture-based, Non anti-aliased lines
+ const int idx_count = count * 6;
+ const int vtx_count = count * 4; // FIXME-OPT: Not sharing edges
+ PrimReserve(idx_count, vtx_count);
+
+ for (int i1 = 0; i1 < count; i1++)
+ {
+ const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
+ const ImVec2& p1 = points[i1];
+ const ImVec2& p2 = points[i2];
+
+ float dx = p2.x - p1.x;
+ float dy = p2.y - p1.y;
+ IM_NORMALIZE2F_OVER_ZERO(dx, dy);
+ dx *= (thickness * 0.5f);
+ dy *= (thickness * 0.5f);
+
+ _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col;
+ _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col;
+ _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col;
+ _VtxWritePtr += 4;
+
+ _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2);
+ _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3);
+ _IdxWritePtr += 6;
+ _VtxCurrentIdx += 4;
+ }
+ }
+}
+
+// We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds.
+void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
+{
+ if (points_count < 3)
+ return;
+
+ const ImVec2 uv = _Data->TexUvWhitePixel;
+
+ if (Flags & ImDrawListFlags_AntiAliasedFill)
+ {
+ // Anti-aliased Fill
+ const float AA_SIZE = _FringeScale;
+ const ImU32 col_trans = col & ~IM_COL32_A_MASK;
+ const int idx_count = (points_count - 2)*3 + points_count * 6;
+ const int vtx_count = (points_count * 2);
+ PrimReserve(idx_count, vtx_count);
+
+ // Add indexes for fill
+ unsigned int vtx_inner_idx = _VtxCurrentIdx;
+ unsigned int vtx_outer_idx = _VtxCurrentIdx + 1;
+ for (int i = 2; i < points_count; i++)
+ {
+ _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + ((i - 1) << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (i << 1));
+ _IdxWritePtr += 3;
+ }
+
+ // Compute normals
+ ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); //-V630
+ for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
+ {
+ const ImVec2& p0 = points[i0];
+ const ImVec2& p1 = points[i1];
+ float dx = p1.x - p0.x;
+ float dy = p1.y - p0.y;
+ IM_NORMALIZE2F_OVER_ZERO(dx, dy);
+ temp_normals[i0].x = dy;
+ temp_normals[i0].y = -dx;
+ }
+
+ for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
+ {
+ // Average normals
+ const ImVec2& n0 = temp_normals[i0];
+ const ImVec2& n1 = temp_normals[i1];
+ float dm_x = (n0.x + n1.x) * 0.5f;
+ float dm_y = (n0.y + n1.y) * 0.5f;
+ IM_FIXNORMAL2F(dm_x, dm_y);
+ dm_x *= AA_SIZE * 0.5f;
+ dm_y *= AA_SIZE * 0.5f;
+
+ // Add vertices
+ _VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner
+ _VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer
+ _VtxWritePtr += 2;
+
+ // Add indexes for fringes
+ _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
+ _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
+ _IdxWritePtr += 6;
+ }
+ _VtxCurrentIdx += (ImDrawIdx)vtx_count;
+ }
+ else
+ {
+ // Non Anti-aliased Fill
+ const int idx_count = (points_count - 2)*3;
+ const int vtx_count = points_count;
+ PrimReserve(idx_count, vtx_count);
+ for (int i = 0; i < vtx_count; i++)
+ {
+ _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col;
+ _VtxWritePtr++;
+ }
+ for (int i = 2; i < points_count; i++)
+ {
+ _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + i - 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + i);
+ _IdxWritePtr += 3;
+ }
+ _VtxCurrentIdx += (ImDrawIdx)vtx_count;
+ }
+}
+
+void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step)
+{
+ if (radius <= 0.0f)
+ {
+ _Path.push_back(center);
+ return;
+ }
+
+ // Calculate arc auto segment step size
+ if (a_step <= 0)
+ a_step = IM_DRAWLIST_ARCFAST_SAMPLE_MAX / _CalcCircleAutoSegmentCount(radius);
+
+ // Make sure we never do steps larger than one quarter of the circle
+ a_step = ImClamp(a_step, 1, IM_DRAWLIST_ARCFAST_TABLE_SIZE / 4);
+
+ const int sample_range = ImAbs(a_max_sample - a_min_sample);
+ const int a_next_step = a_step;
+
+ int samples = sample_range + 1;
+ bool extra_max_sample = false;
+ if (a_step > 1)
+ {
+ samples = sample_range / a_step + 1;
+ const int overstep = sample_range % a_step;
+
+ if (overstep > 0)
+ {
+ extra_max_sample = true;
+ samples++;
+
+ // When we have overstep to avoid awkwardly looking one long line and one tiny one at the end,
+ // distribute first step range evenly between them by reducing first step size.
+ if (sample_range > 0)
+ a_step -= (a_step - overstep) / 2;
+ }
+ }
+
+ _Path.resize(_Path.Size + samples);
+ ImVec2* out_ptr = _Path.Data + (_Path.Size - samples);
+
+ int sample_index = a_min_sample;
+ if (sample_index < 0 || sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX)
+ {
+ sample_index = sample_index % IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ if (sample_index < 0)
+ sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ }
+
+ if (a_max_sample >= a_min_sample)
+ {
+ for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step)
+ {
+ // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more
+ if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX)
+ sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+
+ const ImVec2 s = _Data->ArcFastVtx[sample_index];
+ out_ptr->x = center.x + s.x * radius;
+ out_ptr->y = center.y + s.y * radius;
+ out_ptr++;
+ }
+ }
+ else
+ {
+ for (int a = a_min_sample; a >= a_max_sample; a -= a_step, sample_index -= a_step, a_step = a_next_step)
+ {
+ // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more
+ if (sample_index < 0)
+ sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+
+ const ImVec2 s = _Data->ArcFastVtx[sample_index];
+ out_ptr->x = center.x + s.x * radius;
+ out_ptr->y = center.y + s.y * radius;
+ out_ptr++;
+ }
+ }
+
+ if (extra_max_sample)
+ {
+ int normalized_max_sample = a_max_sample % IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ if (normalized_max_sample < 0)
+ normalized_max_sample += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+
+ const ImVec2 s = _Data->ArcFastVtx[normalized_max_sample];
+ out_ptr->x = center.x + s.x * radius;
+ out_ptr->y = center.y + s.y * radius;
+ out_ptr++;
+ }
+
+ IM_ASSERT_PARANOID(_Path.Data + _Path.Size == out_ptr);
+}
+
+void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
+{
+ if (radius <= 0.0f)
+ {
+ _Path.push_back(center);
+ return;
+ }
+
+ // Note that we are adding a point at both a_min and a_max.
+ // If you are trying to draw a full closed circle you don't want the overlapping points!
+ _Path.reserve(_Path.Size + (num_segments + 1));
+ for (int i = 0; i <= num_segments; i++)
+ {
+ const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);
+ _Path.push_back(ImVec2(center.x + ImCos(a) * radius, center.y + ImSin(a) * radius));
+ }
+}
+
+// 0: East, 3: South, 6: West, 9: North, 12: East
+void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12)
+{
+ if (radius <= 0.0f)
+ {
+ _Path.push_back(center);
+ return;
+ }
+ _PathArcToFastEx(center, radius, a_min_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, a_max_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, 0);
+}
+
+void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments)
+{
+ if (radius <= 0.0f)
+ {
+ _Path.push_back(center);
+ return;
+ }
+
+ if (num_segments > 0)
+ {
+ _PathArcToN(center, radius, a_min, a_max, num_segments);
+ return;
+ }
+
+ // Automatic segment count
+ if (radius <= _Data->ArcFastRadiusCutoff)
+ {
+ const bool a_is_reverse = a_max < a_min;
+
+ // We are going to use precomputed values for mid samples.
+ // Determine first and last sample in lookup table that belong to the arc.
+ const float a_min_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f);
+ const float a_max_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f);
+
+ const int a_min_sample = a_is_reverse ? (int)ImFloorSigned(a_min_sample_f) : (int)ImCeil(a_min_sample_f);
+ const int a_max_sample = a_is_reverse ? (int)ImCeil(a_max_sample_f) : (int)ImFloorSigned(a_max_sample_f);
+ const int a_mid_samples = a_is_reverse ? ImMax(a_min_sample - a_max_sample, 0) : ImMax(a_max_sample - a_min_sample, 0);
+
+ const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
+ const bool a_emit_start = (a_min_segment_angle - a_min) != 0.0f;
+ const bool a_emit_end = (a_max - a_max_segment_angle) != 0.0f;
+
+ _Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0)));
+ if (a_emit_start)
+ _Path.push_back(ImVec2(center.x + ImCos(a_min) * radius, center.y + ImSin(a_min) * radius));
+ if (a_mid_samples > 0)
+ _PathArcToFastEx(center, radius, a_min_sample, a_max_sample, 0);
+ if (a_emit_end)
+ _Path.push_back(ImVec2(center.x + ImCos(a_max) * radius, center.y + ImSin(a_max) * radius));
+ }
+ else
+ {
+ const float arc_length = ImAbs(a_max - a_min);
+ const int circle_segment_count = _CalcCircleAutoSegmentCount(radius);
+ const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length));
+ _PathArcToN(center, radius, a_min, a_max, arc_segment_count);
+ }
+}
+
+ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t)
+{
+ float u = 1.0f - t;
+ float w1 = u * u * u;
+ float w2 = 3 * u * u * t;
+ float w3 = 3 * u * t * t;
+ float w4 = t * t * t;
+ return ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x, w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y);
+}
+
+ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t)
+{
+ float u = 1.0f - t;
+ float w1 = u * u;
+ float w2 = 2 * u * t;
+ float w3 = t * t;
+ return ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x, w1 * p1.y + w2 * p2.y + w3 * p3.y);
+}
+
+// Closely mimics ImBezierCubicClosestPointCasteljau() in imgui.cpp
+static void PathBezierCubicCurveToCasteljau(ImVector<ImVec2>* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
+{
+ float dx = x4 - x1;
+ float dy = y4 - y1;
+ float d2 = (x2 - x4) * dy - (y2 - y4) * dx;
+ float d3 = (x3 - x4) * dy - (y3 - y4) * dx;
+ d2 = (d2 >= 0) ? d2 : -d2;
+ d3 = (d3 >= 0) ? d3 : -d3;
+ if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
+ {
+ path->push_back(ImVec2(x4, y4));
+ }
+ else if (level < 10)
+ {
+ float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f;
+ float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f;
+ float x34 = (x3 + x4) * 0.5f, y34 = (y3 + y4) * 0.5f;
+ float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f;
+ float x234 = (x23 + x34) * 0.5f, y234 = (y23 + y34) * 0.5f;
+ float x1234 = (x123 + x234) * 0.5f, y1234 = (y123 + y234) * 0.5f;
+ PathBezierCubicCurveToCasteljau(path, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
+ PathBezierCubicCurveToCasteljau(path, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
+ }
+}
+
+static void PathBezierQuadraticCurveToCasteljau(ImVector<ImVec2>* path, float x1, float y1, float x2, float y2, float x3, float y3, float tess_tol, int level)
+{
+ float dx = x3 - x1, dy = y3 - y1;
+ float det = (x2 - x3) * dy - (y2 - y3) * dx;
+ if (det * det * 4.0f < tess_tol * (dx * dx + dy * dy))
+ {
+ path->push_back(ImVec2(x3, y3));
+ }
+ else if (level < 10)
+ {
+ float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f;
+ float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f;
+ float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f;
+ PathBezierQuadraticCurveToCasteljau(path, x1, y1, x12, y12, x123, y123, tess_tol, level + 1);
+ PathBezierQuadraticCurveToCasteljau(path, x123, y123, x23, y23, x3, y3, tess_tol, level + 1);
+ }
+}
+
+void ImDrawList::PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments)
+{
+ ImVec2 p1 = _Path.back();
+ if (num_segments == 0)
+ {
+ PathBezierCubicCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); // Auto-tessellated
+ }
+ else
+ {
+ float t_step = 1.0f / (float)num_segments;
+ for (int i_step = 1; i_step <= num_segments; i_step++)
+ _Path.push_back(ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step));
+ }
+}
+
+void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments)
+{
+ ImVec2 p1 = _Path.back();
+ if (num_segments == 0)
+ {
+ PathBezierQuadraticCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, _Data->CurveTessellationTol, 0);// Auto-tessellated
+ }
+ else
+ {
+ float t_step = 1.0f / (float)num_segments;
+ for (int i_step = 1; i_step <= num_segments; i_step++)
+ _Path.push_back(ImBezierQuadraticCalc(p1, p2, p3, t_step * i_step));
+ }
+}
+
+IM_STATIC_ASSERT(ImDrawFlags_RoundCornersTopLeft == (1 << 4));
+static inline ImDrawFlags FixRectCornerFlags(ImDrawFlags flags)
+{
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ // Legacy Support for hard coded ~0 (used to be a suggested equivalent to ImDrawCornerFlags_All)
+ // ~0 --> ImDrawFlags_RoundCornersAll or 0
+ if (flags == ~0)
+ return ImDrawFlags_RoundCornersAll;
+
+ // Legacy Support for hard coded 0x01 to 0x0F (matching 15 out of 16 old flags combinations)
+ // 0x01 --> ImDrawFlags_RoundCornersTopLeft (VALUE 0x01 OVERLAPS ImDrawFlags_Closed but ImDrawFlags_Closed is never valid in this path!)
+ // 0x02 --> ImDrawFlags_RoundCornersTopRight
+ // 0x03 --> ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight
+ // 0x04 --> ImDrawFlags_RoundCornersBotLeft
+ // 0x05 --> ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBotLeft
+ // ...
+ // 0x0F --> ImDrawFlags_RoundCornersAll or 0
+ // (See all values in ImDrawCornerFlags_)
+ if (flags >= 0x01 && flags <= 0x0F)
+ return (flags << 4);
+
+ // We cannot support hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'
+#endif
+
+ // If this triggers, please update your code replacing hardcoded values with new ImDrawFlags_RoundCorners* values.
+ // Note that ImDrawFlags_Closed (== 0x01) is an invalid flag for AddRect(), AddRectFilled(), PathRect() etc...
+ IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!");
+
+ if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
+ flags |= ImDrawFlags_RoundCornersAll;
+
+ return flags;
+}
+
+void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags)
+{
+ flags = FixRectCornerFlags(flags);
+ rounding = ImMin(rounding, ImFabs(b.x - a.x) * ( ((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f ) - 1.0f);
+ rounding = ImMin(rounding, ImFabs(b.y - a.y) * ( ((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f ) - 1.0f);
+
+ if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
+ {
+ PathLineTo(a);
+ PathLineTo(ImVec2(b.x, a.y));
+ PathLineTo(b);
+ PathLineTo(ImVec2(a.x, b.y));
+ }
+ else
+ {
+ const float rounding_tl = (flags & ImDrawFlags_RoundCornersTopLeft) ? rounding : 0.0f;
+ const float rounding_tr = (flags & ImDrawFlags_RoundCornersTopRight) ? rounding : 0.0f;
+ const float rounding_br = (flags & ImDrawFlags_RoundCornersBottomRight) ? rounding : 0.0f;
+ const float rounding_bl = (flags & ImDrawFlags_RoundCornersBottomLeft) ? rounding : 0.0f;
+ PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);
+ PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);
+ PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);
+ PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6);
+ }
+}
+
+void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+ PathLineTo(p1 + ImVec2(0.5f, 0.5f));
+ PathLineTo(p2 + ImVec2(0.5f, 0.5f));
+ PathStroke(col, 0, thickness);
+}
+
+// p_min = upper-left, p_max = lower-right
+// Note we don't render 1 pixels sized rectangles properly.
+void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+ if (Flags & ImDrawListFlags_AntiAliasedLines)
+ PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
+ else
+ PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes.
+ PathStroke(col, ImDrawFlags_Closed, thickness);
+}
+
+void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+ if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
+ {
+ PrimReserve(6, 4);
+ PrimRect(p_min, p_max, col);
+ }
+ else
+ {
+ PathRect(p_min, p_max, rounding, flags);
+ PathFillConvex(col);
+ }
+}
+
+// p_min = upper-left, p_max = lower-right
+void ImDrawList::AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
+{
+ if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
+ return;
+
+ const ImVec2 uv = _Data->TexUvWhitePixel;
+ PrimReserve(6, 4);
+ PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2));
+ PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3));
+ PrimWriteVtx(p_min, uv, col_upr_left);
+ PrimWriteVtx(ImVec2(p_max.x, p_min.y), uv, col_upr_right);
+ PrimWriteVtx(p_max, uv, col_bot_right);
+ PrimWriteVtx(ImVec2(p_min.x, p_max.y), uv, col_bot_left);
+}
+
+void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(p1);
+ PathLineTo(p2);
+ PathLineTo(p3);
+ PathLineTo(p4);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
+}
+
+void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(p1);
+ PathLineTo(p2);
+ PathLineTo(p3);
+ PathLineTo(p4);
+ PathFillConvex(col);
+}
+
+void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(p1);
+ PathLineTo(p2);
+ PathLineTo(p3);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
+}
+
+void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(p1);
+ PathLineTo(p2);
+ PathLineTo(p3);
+ PathFillConvex(col);
+}
+
+void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f)
+ return;
+
+ if (num_segments <= 0)
+ {
+ // Use arc with automatic segment count
+ _PathArcToFastEx(center, radius - 0.5f, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX, 0);
+ _Path.Size--;
+ }
+ else
+ {
+ // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes)
+ num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX);
+
+ // Because we are filling a closed shape we remove 1 from the count of segments/points
+ const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
+ PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
+ }
+
+ PathStroke(col, ImDrawFlags_Closed, thickness);
+}
+
+void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
+{
+ if ((col & IM_COL32_A_MASK) == 0 || radius <= 0.0f)
+ return;
+
+ if (num_segments <= 0)
+ {
+ // Use arc with automatic segment count
+ _PathArcToFastEx(center, radius, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX, 0);
+ _Path.Size--;
+ }
+ else
+ {
+ // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes)
+ num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX);
+
+ // Because we are filling a closed shape we remove 1 from the count of segments/points
+ const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
+ PathArcTo(center, radius, 0.0f, a_max, num_segments - 1);
+ }
+
+ PathFillConvex(col);
+}
+
+// Guaranteed to honor 'num_segments'
+void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness)
+{
+ if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2)
+ return;
+
+ // Because we are filling a closed shape we remove 1 from the count of segments/points
+ const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
+ PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
+ PathStroke(col, ImDrawFlags_Closed, thickness);
+}
+
+// Guaranteed to honor 'num_segments'
+void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
+{
+ if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2)
+ return;
+
+ // Because we are filling a closed shape we remove 1 from the count of segments/points
+ const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
+ PathArcTo(center, radius, 0.0f, a_max, num_segments - 1);
+ PathFillConvex(col);
+}
+
+// Cubic Bezier takes 4 controls points
+void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(p1);
+ PathBezierCubicCurveTo(p2, p3, p4, num_segments);
+ PathStroke(col, 0, thickness);
+}
+
+// Quadratic Bezier takes 3 controls points
+void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ PathLineTo(p1);
+ PathBezierQuadraticCurveTo(p2, p3, num_segments);
+ PathStroke(col, 0, thickness);
+}
+
+void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ if (text_end == NULL)
+ text_end = text_begin + strlen(text_begin);
+ if (text_begin == text_end)
+ return;
+
+ // Pull default font/size from the shared ImDrawListSharedData instance
+ if (font == NULL)
+ font = _Data->Font;
+ if (font_size == 0.0f)
+ font_size = _Data->FontSize;
+
+ IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
+
+ ImVec4 clip_rect = _CmdHeader.ClipRect;
+ if (cpu_fine_clip_rect)
+ {
+ clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x);
+ clip_rect.y = ImMax(clip_rect.y, cpu_fine_clip_rect->y);
+ clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z);
+ clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);
+ }
+ font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);
+}
+
+void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)
+{
+ AddText(NULL, 0.0f, pos, col, text_begin, text_end);
+}
+
+void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
+ if (push_texture_id)
+ PushTextureID(user_texture_id);
+
+ PrimReserve(6, 4);
+ PrimRectUV(p_min, p_max, uv_min, uv_max, col);
+
+ if (push_texture_id)
+ PopTextureID();
+}
+
+void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, const ImVec2& uv4, ImU32 col)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
+ if (push_texture_id)
+ PushTextureID(user_texture_id);
+
+ PrimReserve(6, 4);
+ PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col);
+
+ if (push_texture_id)
+ PopTextureID();
+}
+
+void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags)
+{
+ if ((col & IM_COL32_A_MASK) == 0)
+ return;
+
+ flags = FixRectCornerFlags(flags);
+ if (rounding <= 0.0f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
+ {
+ AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col);
+ return;
+ }
+
+ const bool push_texture_id = user_texture_id != _CmdHeader.TextureId;
+ if (push_texture_id)
+ PushTextureID(user_texture_id);
+
+ int vert_start_idx = VtxBuffer.Size;
+ PathRect(p_min, p_max, rounding, flags);
+ PathFillConvex(col);
+ int vert_end_idx = VtxBuffer.Size;
+ ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true);
+
+ if (push_texture_id)
+ PopTextureID();
+}
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImDrawListSplitter
+//-----------------------------------------------------------------------------
+// FIXME: This may be a little confusing, trying to be a little too low-level/optimal instead of just doing vector swap..
+//-----------------------------------------------------------------------------
+
+void ImDrawListSplitter::ClearFreeMemory()
+{
+ for (int i = 0; i < _Channels.Size; i++)
+ {
+ if (i == _Current)
+ memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again
+ _Channels[i]._CmdBuffer.clear();
+ _Channels[i]._IdxBuffer.clear();
+ }
+ _Current = 0;
+ _Count = 1;
+ _Channels.clear();
+}
+
+void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count)
+{
+ IM_UNUSED(draw_list);
+ IM_ASSERT(_Current == 0 && _Count <= 1 && "Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter.");
+ int old_channels_count = _Channels.Size;
+ if (old_channels_count < channels_count)
+ {
+ _Channels.reserve(channels_count); // Avoid over reserving since this is likely to stay stable
+ _Channels.resize(channels_count);
+ }
+ _Count = channels_count;
+
+ // Channels[] (24/32 bytes each) hold storage that we'll swap with draw_list->_CmdBuffer/_IdxBuffer
+ // The content of Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to.
+ // When we switch to the next channel, we'll copy draw_list->_CmdBuffer/_IdxBuffer into Channels[0] and then Channels[1] into draw_list->CmdBuffer/_IdxBuffer
+ memset(&_Channels[0], 0, sizeof(ImDrawChannel));
+ for (int i = 1; i < channels_count; i++)
+ {
+ if (i >= old_channels_count)
+ {
+ IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel();
+ }
+ else
+ {
+ _Channels[i]._CmdBuffer.resize(0);
+ _Channels[i]._IdxBuffer.resize(0);
+ }
+ }
+}
+
+void ImDrawListSplitter::Merge(ImDrawList* draw_list)
+{
+ // Note that we never use or rely on _Channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
+ if (_Count <= 1)
+ return;
+
+ SetCurrentChannel(draw_list, 0);
+ draw_list->_PopUnusedDrawCmd();
+
+ // Calculate our final buffer sizes. Also fix the incorrect IdxOffset values in each command.
+ int new_cmd_buffer_count = 0;
+ int new_idx_buffer_count = 0;
+ ImDrawCmd* last_cmd = (_Count > 0 && draw_list->CmdBuffer.Size > 0) ? &draw_list->CmdBuffer.back() : NULL;
+ int idx_offset = last_cmd ? last_cmd->IdxOffset + last_cmd->ElemCount : 0;
+ for (int i = 1; i < _Count; i++)
+ {
+ ImDrawChannel& ch = _Channels[i];
+
+ // Equivalent of PopUnusedDrawCmd() for this channel's cmdbuffer and except we don't need to test for UserCallback.
+ if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0)
+ ch._CmdBuffer.pop_back();
+
+ if (ch._CmdBuffer.Size > 0 && last_cmd != NULL)
+ {
+ ImDrawCmd* next_cmd = &ch._CmdBuffer[0];
+ if (ImDrawCmd_HeaderCompare(last_cmd, next_cmd) == 0 && last_cmd->UserCallback == NULL && next_cmd->UserCallback == NULL)
+ {
+ // Merge previous channel last draw command with current channel first draw command if matching.
+ last_cmd->ElemCount += next_cmd->ElemCount;
+ idx_offset += next_cmd->ElemCount;
+ ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges.
+ }
+ }
+ if (ch._CmdBuffer.Size > 0)
+ last_cmd = &ch._CmdBuffer.back();
+ new_cmd_buffer_count += ch._CmdBuffer.Size;
+ new_idx_buffer_count += ch._IdxBuffer.Size;
+ for (int cmd_n = 0; cmd_n < ch._CmdBuffer.Size; cmd_n++)
+ {
+ ch._CmdBuffer.Data[cmd_n].IdxOffset = idx_offset;
+ idx_offset += ch._CmdBuffer.Data[cmd_n].ElemCount;
+ }
+ }
+ draw_list->CmdBuffer.resize(draw_list->CmdBuffer.Size + new_cmd_buffer_count);
+ draw_list->IdxBuffer.resize(draw_list->IdxBuffer.Size + new_idx_buffer_count);
+
+ // Write commands and indices in order (they are fairly small structures, we don't copy vertices only indices)
+ ImDrawCmd* cmd_write = draw_list->CmdBuffer.Data + draw_list->CmdBuffer.Size - new_cmd_buffer_count;
+ ImDrawIdx* idx_write = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size - new_idx_buffer_count;
+ for (int i = 1; i < _Count; i++)
+ {
+ ImDrawChannel& ch = _Channels[i];
+ if (int sz = ch._CmdBuffer.Size) { memcpy(cmd_write, ch._CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; }
+ if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; }
+ }
+ draw_list->_IdxWritePtr = idx_write;
+
+ // Ensure there's always a non-callback draw command trailing the command-buffer
+ if (draw_list->CmdBuffer.Size == 0 || draw_list->CmdBuffer.back().UserCallback != NULL)
+ draw_list->AddDrawCmd();
+
+ // If current command is used with different settings we need to add a new command
+ ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
+ if (curr_cmd->ElemCount == 0)
+ ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
+ else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
+ draw_list->AddDrawCmd();
+
+ _Count = 1;
+}
+
+void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
+{
+ IM_ASSERT(idx >= 0 && idx < _Count);
+ if (_Current == idx)
+ return;
+
+ // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap()
+ memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer));
+ memcpy(&_Channels.Data[_Current]._IdxBuffer, &draw_list->IdxBuffer, sizeof(draw_list->IdxBuffer));
+ _Current = idx;
+ memcpy(&draw_list->CmdBuffer, &_Channels.Data[idx]._CmdBuffer, sizeof(draw_list->CmdBuffer));
+ memcpy(&draw_list->IdxBuffer, &_Channels.Data[idx]._IdxBuffer, sizeof(draw_list->IdxBuffer));
+ draw_list->_IdxWritePtr = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size;
+
+ // If current command is used with different settings we need to add a new command
+ ImDrawCmd* curr_cmd = (draw_list->CmdBuffer.Size == 0) ? NULL : &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1];
+ if (curr_cmd == NULL)
+ draw_list->AddDrawCmd();
+ else if (curr_cmd->ElemCount == 0)
+ ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset
+ else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0)
+ draw_list->AddDrawCmd();
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImDrawData
+//-----------------------------------------------------------------------------
+
+// For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
+void ImDrawData::DeIndexAllBuffers()
+{
+ ImVector<ImDrawVert> new_vtx_buffer;
+ TotalVtxCount = TotalIdxCount = 0;
+ for (int i = 0; i < CmdListsCount; i++)
+ {
+ ImDrawList* cmd_list = CmdLists[i];
+ if (cmd_list->IdxBuffer.empty())
+ continue;
+ new_vtx_buffer.resize(cmd_list->IdxBuffer.Size);
+ for (int j = 0; j < cmd_list->IdxBuffer.Size; j++)
+ new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]];
+ cmd_list->VtxBuffer.swap(new_vtx_buffer);
+ cmd_list->IdxBuffer.resize(0);
+ TotalVtxCount += cmd_list->VtxBuffer.Size;
+ }
+}
+
+// Helper to scale the ClipRect field of each ImDrawCmd.
+// Use if your final output buffer is at a different scale than draw_data->DisplaySize,
+// or if there is a difference between your window resolution and framebuffer resolution.
+void ImDrawData::ScaleClipRects(const ImVec2& fb_scale)
+{
+ for (int i = 0; i < CmdListsCount; i++)
+ {
+ ImDrawList* cmd_list = CmdLists[i];
+ for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
+ {
+ ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i];
+ cmd->ClipRect = ImVec4(cmd->ClipRect.x * fb_scale.x, cmd->ClipRect.y * fb_scale.y, cmd->ClipRect.z * fb_scale.x, cmd->ClipRect.w * fb_scale.y);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Helpers ShadeVertsXXX functions
+//-----------------------------------------------------------------------------
+
+// Generic linear color gradient, write to RGB fields, leave A untouched.
+void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)
+{
+ ImVec2 gradient_extent = gradient_p1 - gradient_p0;
+ float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent);
+ ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx;
+ ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx;
+ const int col0_r = (int)(col0 >> IM_COL32_R_SHIFT) & 0xFF;
+ const int col0_g = (int)(col0 >> IM_COL32_G_SHIFT) & 0xFF;
+ const int col0_b = (int)(col0 >> IM_COL32_B_SHIFT) & 0xFF;
+ const int col_delta_r = ((int)(col1 >> IM_COL32_R_SHIFT) & 0xFF) - col0_r;
+ const int col_delta_g = ((int)(col1 >> IM_COL32_G_SHIFT) & 0xFF) - col0_g;
+ const int col_delta_b = ((int)(col1 >> IM_COL32_B_SHIFT) & 0xFF) - col0_b;
+ for (ImDrawVert* vert = vert_start; vert < vert_end; vert++)
+ {
+ float d = ImDot(vert->pos - gradient_p0, gradient_extent);
+ float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
+ int r = (int)(col0_r + col_delta_r * t);
+ int g = (int)(col0_g + col_delta_g * t);
+ int b = (int)(col0_b + col_delta_b * t);
+ vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK);
+ }
+}
+
+// Distribute UV over (a, b) rectangle
+void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp)
+{
+ const ImVec2 size = b - a;
+ const ImVec2 uv_size = uv_b - uv_a;
+ const ImVec2 scale = ImVec2(
+ size.x != 0.0f ? (uv_size.x / size.x) : 0.0f,
+ size.y != 0.0f ? (uv_size.y / size.y) : 0.0f);
+
+ ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx;
+ ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx;
+ if (clamp)
+ {
+ const ImVec2 min = ImMin(uv_a, uv_b);
+ const ImVec2 max = ImMax(uv_a, uv_b);
+ for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
+ vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max);
+ }
+ else
+ {
+ for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
+ vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontConfig
+//-----------------------------------------------------------------------------
+
+ImFontConfig::ImFontConfig()
+{
+ memset(this, 0, sizeof(*this));
+ FontDataOwnedByAtlas = true;
+ OversampleH = 3; // FIXME: 2 may be a better default?
+ OversampleV = 1;
+ GlyphMaxAdvanceX = FLT_MAX;
+ RasterizerMultiply = 1.0f;
+ EllipsisChar = (ImWchar)-1;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontAtlas
+//-----------------------------------------------------------------------------
+
+// A work of art lies ahead! (. = white layer, X = black layer, others are blank)
+// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes.
+// (This is used when io.MouseDrawCursor = true)
+const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 122; // Actual texture will be 2 times that + 1 spacing.
+const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27;
+static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] =
+{
+ "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX - XX XX "
+ "..- -X.....X- X.X - X.X -X.....X - X.....X- X..X -X..X X..X"
+ "--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X -X...X X...X"
+ "X - X.X - X.....X - X.....X -X...X - X...X- X..X - X...X X...X "
+ "XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X - X...X...X "
+ "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX - X.....X "
+ "X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX - X...X "
+ "X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX - X.X "
+ "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X - X...X "
+ "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X- X.....X "
+ "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X- X...X...X "
+ "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X- X...X X...X "
+ "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X-X...X X...X"
+ "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X-X..X X..X"
+ "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X- XX XX "
+ "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X--------------"
+ "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X - "
+ "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X - "
+ "X.X X..X - -X.......X- X.......X - XX XX - - X..........X - "
+ "XX X..X - - X.....X - X.....X - X.X X.X - - X........X - "
+ " X..X - - X...X - X...X - X..X X..X - - X........X - "
+ " XX - - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX - "
+ "------------- - X - X -X.....................X- ------------------- "
+ " ----------------------------------- X...XXXXXXXXXXXXX...X - "
+ " - X..X X..X - "
+ " - X.X X.X - "
+ " - XX XX - "
+};
+
+static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] =
+{
+ // Pos ........ Size ......... Offset ......
+ { ImVec2( 0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow
+ { ImVec2(13,0), ImVec2( 7,16), ImVec2( 1, 8) }, // ImGuiMouseCursor_TextInput
+ { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll
+ { ImVec2(21,0), ImVec2( 9,23), ImVec2( 4,11) }, // ImGuiMouseCursor_ResizeNS
+ { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 4) }, // ImGuiMouseCursor_ResizeEW
+ { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW
+ { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE
+ { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand
+ { ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed
+};
+
+ImFontAtlas::ImFontAtlas()
+{
+ memset(this, 0, sizeof(*this));
+ TexGlyphPadding = 1;
+ PackIdMouseCursors = PackIdLines = -1;
+}
+
+ImFontAtlas::~ImFontAtlas()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ Clear();
+}
+
+void ImFontAtlas::ClearInputData()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ for (int i = 0; i < ConfigData.Size; i++)
+ if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas)
+ {
+ IM_FREE(ConfigData[i].FontData);
+ ConfigData[i].FontData = NULL;
+ }
+
+ // When clearing this we lose access to the font name and other information used to build the font.
+ for (int i = 0; i < Fonts.Size; i++)
+ if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size)
+ {
+ Fonts[i]->ConfigData = NULL;
+ Fonts[i]->ConfigDataCount = 0;
+ }
+ ConfigData.clear();
+ CustomRects.clear();
+ PackIdMouseCursors = PackIdLines = -1;
+ // Important: we leave TexReady untouched
+}
+
+void ImFontAtlas::ClearTexData()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ if (TexPixelsAlpha8)
+ IM_FREE(TexPixelsAlpha8);
+ if (TexPixelsRGBA32)
+ IM_FREE(TexPixelsRGBA32);
+ TexPixelsAlpha8 = NULL;
+ TexPixelsRGBA32 = NULL;
+ TexPixelsUseColors = false;
+ // Important: we leave TexReady untouched
+}
+
+void ImFontAtlas::ClearFonts()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ Fonts.clear_delete();
+ TexReady = false;
+}
+
+void ImFontAtlas::Clear()
+{
+ ClearInputData();
+ ClearTexData();
+ ClearFonts();
+}
+
+void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
+{
+ // Build atlas on demand
+ if (TexPixelsAlpha8 == NULL)
+ Build();
+
+ *out_pixels = TexPixelsAlpha8;
+ if (out_width) *out_width = TexWidth;
+ if (out_height) *out_height = TexHeight;
+ if (out_bytes_per_pixel) *out_bytes_per_pixel = 1;
+}
+
+void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
+{
+ // Convert to RGBA32 format on demand
+ // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp
+ if (!TexPixelsRGBA32)
+ {
+ unsigned char* pixels = NULL;
+ GetTexDataAsAlpha8(&pixels, NULL, NULL);
+ if (pixels)
+ {
+ TexPixelsRGBA32 = (unsigned int*)IM_ALLOC((size_t)TexWidth * (size_t)TexHeight * 4);
+ const unsigned char* src = pixels;
+ unsigned int* dst = TexPixelsRGBA32;
+ for (int n = TexWidth * TexHeight; n > 0; n--)
+ *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));
+ }
+ }
+
+ *out_pixels = (unsigned char*)TexPixelsRGBA32;
+ if (out_width) *out_width = TexWidth;
+ if (out_height) *out_height = TexHeight;
+ if (out_bytes_per_pixel) *out_bytes_per_pixel = 4;
+}
+
+ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);
+ IM_ASSERT(font_cfg->SizePixels > 0.0f);
+
+ // Create new font
+ if (!font_cfg->MergeMode)
+ Fonts.push_back(IM_NEW(ImFont));
+ else
+ IM_ASSERT(!Fonts.empty() && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
+
+ ConfigData.push_back(*font_cfg);
+ ImFontConfig& new_font_cfg = ConfigData.back();
+ if (new_font_cfg.DstFont == NULL)
+ new_font_cfg.DstFont = Fonts.back();
+ if (!new_font_cfg.FontDataOwnedByAtlas)
+ {
+ new_font_cfg.FontData = IM_ALLOC(new_font_cfg.FontDataSize);
+ new_font_cfg.FontDataOwnedByAtlas = true;
+ memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);
+ }
+
+ if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1)
+ new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar;
+
+ // Invalidate texture
+ TexReady = false;
+ ClearTexData();
+ return new_font_cfg.DstFont;
+}
+
+// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
+static unsigned int stb_decompress_length(const unsigned char* input);
+static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length);
+static const char* GetDefaultCompressedFontDataTTFBase85();
+static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; }
+static void Decode85(const unsigned char* src, unsigned char* dst)
+{
+ while (*src)
+ {
+ unsigned int tmp = Decode85Byte(src[0]) + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4]))));
+ dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness.
+ src += 5;
+ dst += 4;
+ }
+}
+
+// Load embedded ProggyClean.ttf at size 13, disable oversampling
+ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
+{
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ if (!font_cfg_template)
+ {
+ font_cfg.OversampleH = font_cfg.OversampleV = 1;
+ font_cfg.PixelSnapH = true;
+ }
+ if (font_cfg.SizePixels <= 0.0f)
+ font_cfg.SizePixels = 13.0f * 1.0f;
+ if (font_cfg.Name[0] == '\0')
+ ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels);
+ font_cfg.EllipsisChar = (ImWchar)0x0085;
+ font_cfg.GlyphOffset.y = 1.0f * IM_FLOOR(font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units
+
+ const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
+ const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault();
+ ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges);
+ return font;
+}
+
+ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ size_t data_size = 0;
+ void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0);
+ if (!data)
+ {
+ IM_ASSERT_USER_ERROR(0, "Could not load font file!");
+ return NULL;
+ }
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ if (font_cfg.Name[0] == '\0')
+ {
+ // Store a short copy of filename into into the font name for convenience
+ const char* p;
+ for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
+ ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels);
+ }
+ return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
+}
+
+// NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
+ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ IM_ASSERT(font_cfg.FontData == NULL);
+ font_cfg.FontData = ttf_data;
+ font_cfg.FontDataSize = ttf_size;
+ font_cfg.SizePixels = size_pixels > 0.0f ? size_pixels : font_cfg.SizePixels;
+ if (glyph_ranges)
+ font_cfg.GlyphRanges = glyph_ranges;
+ return AddFont(&font_cfg);
+}
+
+ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
+{
+ const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data);
+ unsigned char* buf_decompressed_data = (unsigned char*)IM_ALLOC(buf_decompressed_size);
+ stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);
+
+ ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
+ IM_ASSERT(font_cfg.FontData == NULL);
+ font_cfg.FontDataOwnedByAtlas = true;
+ return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges);
+}
+
+ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)
+{
+ int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
+ void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size);
+ Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
+ ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
+ IM_FREE(compressed_ttf);
+ return font;
+}
+
+int ImFontAtlas::AddCustomRectRegular(int width, int height)
+{
+ IM_ASSERT(width > 0 && width <= 0xFFFF);
+ IM_ASSERT(height > 0 && height <= 0xFFFF);
+ ImFontAtlasCustomRect r;
+ r.Width = (unsigned short)width;
+ r.Height = (unsigned short)height;
+ CustomRects.push_back(r);
+ return CustomRects.Size - 1; // Return index
+}
+
+int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset)
+{
+#ifdef IMGUI_USE_WCHAR32
+ IM_ASSERT(id <= IM_UNICODE_CODEPOINT_MAX);
+#endif
+ IM_ASSERT(font != NULL);
+ IM_ASSERT(width > 0 && width <= 0xFFFF);
+ IM_ASSERT(height > 0 && height <= 0xFFFF);
+ ImFontAtlasCustomRect r;
+ r.Width = (unsigned short)width;
+ r.Height = (unsigned short)height;
+ r.GlyphID = id;
+ r.GlyphAdvanceX = advance_x;
+ r.GlyphOffset = offset;
+ r.Font = font;
+ CustomRects.push_back(r);
+ return CustomRects.Size - 1; // Return index
+}
+
+void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const
+{
+ IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates
+ IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed
+ *out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y);
+ *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y);
+}
+
+bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2])
+{
+ if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT)
+ return false;
+ if (Flags & ImFontAtlasFlags_NoMouseCursors)
+ return false;
+
+ IM_ASSERT(PackIdMouseCursors != -1);
+ ImFontAtlasCustomRect* r = GetCustomRectByIndex(PackIdMouseCursors);
+ ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r->X, (float)r->Y);
+ ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1];
+ *out_size = size;
+ *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2];
+ out_uv_border[0] = (pos) * TexUvScale;
+ out_uv_border[1] = (pos + size) * TexUvScale;
+ pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W + 1;
+ out_uv_fill[0] = (pos) * TexUvScale;
+ out_uv_fill[1] = (pos + size) * TexUvScale;
+ return true;
+}
+
+bool ImFontAtlas::Build()
+{
+ IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
+
+ // Default font is none are specified
+ if (ConfigData.Size == 0)
+ AddFontDefault();
+
+ // Select builder
+ // - Note that we do not reassign to atlas->FontBuilderIO, since it is likely to point to static data which
+ // may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are
+ // using a hot-reloading scheme that messes up static data, store your own instance of ImFontBuilderIO somewhere
+ // and point to it instead of pointing directly to return value of the GetBuilderXXX functions.
+ const ImFontBuilderIO* builder_io = FontBuilderIO;
+ if (builder_io == NULL)
+ {
+#ifdef IMGUI_ENABLE_FREETYPE
+ builder_io = ImGuiFreeType::GetBuilderForFreeType();
+#elif defined(IMGUI_ENABLE_STB_TRUETYPE)
+ builder_io = ImFontAtlasGetBuilderForStbTruetype();
+#else
+ IM_ASSERT(0); // Invalid Build function
+#endif
+ }
+
+ // Build
+ return builder_io->FontBuilder_Build(this);
+}
+
+void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor)
+{
+ for (unsigned int i = 0; i < 256; i++)
+ {
+ unsigned int value = (unsigned int)(i * in_brighten_factor);
+ out_table[i] = value > 255 ? 255 : (value & 0xFF);
+ }
+}
+
+void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride)
+{
+ unsigned char* data = pixels + x + y * stride;
+ for (int j = h; j > 0; j--, data += stride)
+ for (int i = 0; i < w; i++)
+ data[i] = table[data[i]];
+}
+
+#ifdef IMGUI_ENABLE_STB_TRUETYPE
+// Temporary data for one source font (multiple source fonts can be merged into one destination ImFont)
+// (C++03 doesn't allow instancing ImVector<> with function-local types so we declare the type here.)
+struct ImFontBuildSrcData
+{
+ stbtt_fontinfo FontInfo;
+ stbtt_pack_range PackRange; // Hold the list of codepoints to pack (essentially points to Codepoints.Data)
+ stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position.
+ stbtt_packedchar* PackedChars; // Output glyphs
+ const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF)
+ int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[]
+ int GlyphsHighest; // Highest requested codepoint
+ int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font)
+ ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB)
+ ImVector<int> GlyphsList; // Glyph codepoints list (flattened version of GlyphsMap)
+};
+
+// Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont)
+struct ImFontBuildDstData
+{
+ int SrcCount; // Number of source fonts targeting this destination font.
+ int GlyphsHighest;
+ int GlyphsCount;
+ ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font.
+};
+
+static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector<int>* out)
+{
+ IM_ASSERT(sizeof(in->Storage.Data[0]) == sizeof(int));
+ const ImU32* it_begin = in->Storage.begin();
+ const ImU32* it_end = in->Storage.end();
+ for (const ImU32* it = it_begin; it < it_end; it++)
+ if (ImU32 entries_32 = *it)
+ for (ImU32 bit_n = 0; bit_n < 32; bit_n++)
+ if (entries_32 & ((ImU32)1 << bit_n))
+ out->push_back((int)(((it - it_begin) << 5) + bit_n));
+}
+
+static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
+{
+ IM_ASSERT(atlas->ConfigData.Size > 0);
+
+ ImFontAtlasBuildInit(atlas);
+
+ // Clear atlas
+ atlas->TexID = (ImTextureID)NULL;
+ atlas->TexWidth = atlas->TexHeight = 0;
+ atlas->TexUvScale = ImVec2(0.0f, 0.0f);
+ atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
+ atlas->ClearTexData();
+
+ // Temporary storage for building
+ ImVector<ImFontBuildSrcData> src_tmp_array;
+ ImVector<ImFontBuildDstData> dst_tmp_array;
+ src_tmp_array.resize(atlas->ConfigData.Size);
+ dst_tmp_array.resize(atlas->Fonts.Size);
+ memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes());
+ memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes());
+
+ // 1. Initialize font loading structure, check font data validity
+ for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++)
+ {
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));
+
+ // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices)
+ src_tmp.DstIndex = -1;
+ for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++)
+ if (cfg.DstFont == atlas->Fonts[output_i])
+ src_tmp.DstIndex = output_i;
+ if (src_tmp.DstIndex == -1)
+ {
+ IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array?
+ return false;
+ }
+ // Initialize helper structure for font loading and verify that the TTF/OTF data is correct
+ const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo);
+ IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found.");
+ if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset))
+ return false;
+
+ // Measure highest codepoints
+ ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
+ src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
+ for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
+ src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]);
+ dst_tmp.SrcCount++;
+ dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest);
+ }
+
+ // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs.
+ int total_glyphs_count = 0;
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
+ src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1);
+ if (dst_tmp.GlyphsSet.Storage.empty())
+ dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1);
+
+ for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
+ for (unsigned int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++)
+ {
+ if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option for MergeMode (e.g. MergeOverwrite==true)
+ continue;
+ if (!stbtt_FindGlyphIndex(&src_tmp.FontInfo, codepoint)) // It is actually in the font?
+ continue;
+
+ // Add to avail set/counters
+ src_tmp.GlyphsCount++;
+ dst_tmp.GlyphsCount++;
+ src_tmp.GlyphsSet.SetBit(codepoint);
+ dst_tmp.GlyphsSet.SetBit(codepoint);
+ total_glyphs_count++;
+ }
+ }
+
+ // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another)
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount);
+ UnpackBitVectorToFlatIndexList(&src_tmp.GlyphsSet, &src_tmp.GlyphsList);
+ src_tmp.GlyphsSet.Clear();
+ IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount);
+ }
+ for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++)
+ dst_tmp_array[dst_i].GlyphsSet.Clear();
+ dst_tmp_array.clear();
+
+ // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
+ // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity)
+ ImVector<stbrp_rect> buf_rects;
+ ImVector<stbtt_packedchar> buf_packedchars;
+ buf_rects.resize(total_glyphs_count);
+ buf_packedchars.resize(total_glyphs_count);
+ memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes());
+ memset(buf_packedchars.Data, 0, (size_t)buf_packedchars.size_in_bytes());
+
+ // 4. Gather glyphs sizes so we can pack them in our virtual canvas.
+ int total_surface = 0;
+ int buf_rects_out_n = 0;
+ int buf_packedchars_out_n = 0;
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ src_tmp.Rects = &buf_rects[buf_rects_out_n];
+ src_tmp.PackedChars = &buf_packedchars[buf_packedchars_out_n];
+ buf_rects_out_n += src_tmp.GlyphsCount;
+ buf_packedchars_out_n += src_tmp.GlyphsCount;
+
+ // Convert our ranges in the format stb_truetype wants
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ src_tmp.PackRange.font_size = cfg.SizePixels;
+ src_tmp.PackRange.first_unicode_codepoint_in_range = 0;
+ src_tmp.PackRange.array_of_unicode_codepoints = src_tmp.GlyphsList.Data;
+ src_tmp.PackRange.num_chars = src_tmp.GlyphsList.Size;
+ src_tmp.PackRange.chardata_for_range = src_tmp.PackedChars;
+ src_tmp.PackRange.h_oversample = (unsigned char)cfg.OversampleH;
+ src_tmp.PackRange.v_oversample = (unsigned char)cfg.OversampleV;
+
+ // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects)
+ const float scale = (cfg.SizePixels > 0) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels);
+ const int padding = atlas->TexGlyphPadding;
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++)
+ {
+ int x0, y0, x1, y1;
+ const int glyph_index_in_font = stbtt_FindGlyphIndex(&src_tmp.FontInfo, src_tmp.GlyphsList[glyph_i]);
+ IM_ASSERT(glyph_index_in_font != 0);
+ stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * cfg.OversampleH, scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1);
+ src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + padding + cfg.OversampleH - 1);
+ src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + padding + cfg.OversampleV - 1);
+ total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h;
+ }
+ }
+
+ // We need a width for the skyline algorithm, any width!
+ // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
+ // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface.
+ const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1;
+ atlas->TexHeight = 0;
+ if (atlas->TexDesiredWidth > 0)
+ atlas->TexWidth = atlas->TexDesiredWidth;
+ else
+ atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512;
+
+ // 5. Start packing
+ // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
+ const int TEX_HEIGHT_MAX = 1024 * 32;
+ stbtt_pack_context spc = {};
+ stbtt_PackBegin(&spc, NULL, atlas->TexWidth, TEX_HEIGHT_MAX, 0, atlas->TexGlyphPadding, NULL);
+ ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info);
+
+ // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point.
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ stbrp_pack_rects((stbrp_context*)spc.pack_info, src_tmp.Rects, src_tmp.GlyphsCount);
+
+ // Extend texture height and mark missing glyphs as non-packed so we won't render them.
+ // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?)
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
+ if (src_tmp.Rects[glyph_i].was_packed)
+ atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h);
+ }
+
+ // 7. Allocate texture
+ atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
+ atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
+ atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
+ memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
+ spc.pixels = atlas->TexPixelsAlpha8;
+ spc.height = atlas->TexHeight;
+
+ // 8. Render/rasterize font characters into the texture
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ stbtt_PackFontRangesRenderIntoRects(&spc, &src_tmp.FontInfo, &src_tmp.PackRange, 1, src_tmp.Rects);
+
+ // Apply multiply operator
+ if (cfg.RasterizerMultiply != 1.0f)
+ {
+ unsigned char multiply_table[256];
+ ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply);
+ stbrp_rect* r = &src_tmp.Rects[0];
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++, r++)
+ if (r->was_packed)
+ ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, atlas->TexPixelsAlpha8, r->x, r->y, r->w, r->h, atlas->TexWidth * 1);
+ }
+ src_tmp.Rects = NULL;
+ }
+
+ // End packing
+ stbtt_PackEnd(&spc);
+ buf_rects.clear();
+
+ // 9. Setup ImFont and glyphs for runtime
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcData& src_tmp = src_tmp_array[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ // When merging fonts with MergeMode=true:
+ // - We can have multiple input fonts writing into a same destination font.
+ // - dst_font->ConfigData is != from cfg which is our source configuration.
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ ImFont* dst_font = cfg.DstFont;
+
+ const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels);
+ int unscaled_ascent, unscaled_descent, unscaled_line_gap;
+ stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap);
+
+ const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1));
+ const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1));
+ ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
+ const float font_off_x = cfg.GlyphOffset.x;
+ const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
+
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
+ {
+ // Register glyph
+ const int codepoint = src_tmp.GlyphsList[glyph_i];
+ const stbtt_packedchar& pc = src_tmp.PackedChars[glyph_i];
+ stbtt_aligned_quad q;
+ float unused_x = 0.0f, unused_y = 0.0f;
+ stbtt_GetPackedQuad(src_tmp.PackedChars, atlas->TexWidth, atlas->TexHeight, glyph_i, &unused_x, &unused_y, &q, 0);
+ dst_font->AddGlyph(&cfg, (ImWchar)codepoint, q.x0 + font_off_x, q.y0 + font_off_y, q.x1 + font_off_x, q.y1 + font_off_y, q.s0, q.t0, q.s1, q.t1, pc.xadvance);
+ }
+ }
+
+ // Cleanup
+ src_tmp_array.clear_destruct();
+
+ ImFontAtlasBuildFinish(atlas);
+ return true;
+}
+
+const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype()
+{
+ static ImFontBuilderIO io;
+ io.FontBuilder_Build = ImFontAtlasBuildWithStbTruetype;
+ return &io;
+}
+
+#endif // IMGUI_ENABLE_STB_TRUETYPE
+
+void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent)
+{
+ if (!font_config->MergeMode)
+ {
+ font->ClearOutputData();
+ font->FontSize = font_config->SizePixels;
+ font->ConfigData = font_config;
+ font->ConfigDataCount = 0;
+ font->ContainerAtlas = atlas;
+ font->Ascent = ascent;
+ font->Descent = descent;
+ }
+ font->ConfigDataCount++;
+}
+
+void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque)
+{
+ stbrp_context* pack_context = (stbrp_context*)stbrp_context_opaque;
+ IM_ASSERT(pack_context != NULL);
+
+ ImVector<ImFontAtlasCustomRect>& user_rects = atlas->CustomRects;
+ IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong.
+
+ ImVector<stbrp_rect> pack_rects;
+ pack_rects.resize(user_rects.Size);
+ memset(pack_rects.Data, 0, (size_t)pack_rects.size_in_bytes());
+ for (int i = 0; i < user_rects.Size; i++)
+ {
+ pack_rects[i].w = user_rects[i].Width;
+ pack_rects[i].h = user_rects[i].Height;
+ }
+ stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size);
+ for (int i = 0; i < pack_rects.Size; i++)
+ if (pack_rects[i].was_packed)
+ {
+ user_rects[i].X = pack_rects[i].x;
+ user_rects[i].Y = pack_rects[i].y;
+ IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);
+ atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);
+ }
+}
+
+void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value)
+{
+ IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth);
+ IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight);
+ unsigned char* out_pixel = atlas->TexPixelsAlpha8 + x + (y * atlas->TexWidth);
+ for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w)
+ for (int off_x = 0; off_x < w; off_x++)
+ out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : 0x00;
+}
+
+void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value)
+{
+ IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth);
+ IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight);
+ unsigned int* out_pixel = atlas->TexPixelsRGBA32 + x + (y * atlas->TexWidth);
+ for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w)
+ for (int off_x = 0; off_x < w; off_x++)
+ out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : IM_COL32_BLACK_TRANS;
+}
+
+static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
+{
+ ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors);
+ IM_ASSERT(r->IsPacked());
+
+ const int w = atlas->TexWidth;
+ if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
+ {
+ // Render/copy pixels
+ IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
+ const int x_for_white = r->X;
+ const int x_for_black = r->X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1;
+ if (atlas->TexPixelsAlpha8 != NULL)
+ {
+ ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF);
+ ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF);
+ }
+ else
+ {
+ ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', IM_COL32_WHITE);
+ ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', IM_COL32_WHITE);
+ }
+ }
+ else
+ {
+ // Render 4 white pixels
+ IM_ASSERT(r->Width == 2 && r->Height == 2);
+ const int offset = (int)r->X + (int)r->Y * w;
+ if (atlas->TexPixelsAlpha8 != NULL)
+ {
+ atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
+ }
+ else
+ {
+ atlas->TexPixelsRGBA32[offset] = atlas->TexPixelsRGBA32[offset + 1] = atlas->TexPixelsRGBA32[offset + w] = atlas->TexPixelsRGBA32[offset + w + 1] = IM_COL32_WHITE;
+ }
+ }
+ atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y);
+}
+
+static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas)
+{
+ if (atlas->Flags & ImFontAtlasFlags_NoBakedLines)
+ return;
+
+ // This generates a triangular shape in the texture, with the various line widths stacked on top of each other to allow interpolation between them
+ ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdLines);
+ IM_ASSERT(r->IsPacked());
+ for (unsigned int n = 0; n < IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row
+ {
+ // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle
+ unsigned int y = n;
+ unsigned int line_width = n;
+ unsigned int pad_left = (r->Width - line_width) / 2;
+ unsigned int pad_right = r->Width - (pad_left + line_width);
+
+ // Write each slice
+ IM_ASSERT(pad_left + line_width + pad_right == r->Width && y < r->Height); // Make sure we're inside the texture bounds before we start writing pixels
+ if (atlas->TexPixelsAlpha8 != NULL)
+ {
+ unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)];
+ for (unsigned int i = 0; i < pad_left; i++)
+ *(write_ptr + i) = 0x00;
+
+ for (unsigned int i = 0; i < line_width; i++)
+ *(write_ptr + pad_left + i) = 0xFF;
+
+ for (unsigned int i = 0; i < pad_right; i++)
+ *(write_ptr + pad_left + line_width + i) = 0x00;
+ }
+ else
+ {
+ unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)];
+ for (unsigned int i = 0; i < pad_left; i++)
+ *(write_ptr + i) = IM_COL32_BLACK_TRANS;
+
+ for (unsigned int i = 0; i < line_width; i++)
+ *(write_ptr + pad_left + i) = IM_COL32_WHITE;
+
+ for (unsigned int i = 0; i < pad_right; i++)
+ *(write_ptr + pad_left + line_width + i) = IM_COL32_BLACK_TRANS;
+ }
+
+ // Calculate UVs for this line
+ ImVec2 uv0 = ImVec2((float)(r->X + pad_left - 1), (float)(r->Y + y)) * atlas->TexUvScale;
+ ImVec2 uv1 = ImVec2((float)(r->X + pad_left + line_width + 1), (float)(r->Y + y + 1)) * atlas->TexUvScale;
+ float half_v = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts
+ atlas->TexUvLines[n] = ImVec4(uv0.x, half_v, uv1.x, half_v);
+ }
+}
+
+// Note: this is called / shared by both the stb_truetype and the FreeType builder
+void ImFontAtlasBuildInit(ImFontAtlas* atlas)
+{
+ // Register texture region for mouse cursors or standard white pixels
+ if (atlas->PackIdMouseCursors < 0)
+ {
+ if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
+ atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
+ else
+ atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(2, 2);
+ }
+
+ // Register texture region for thick lines
+ // The +2 here is to give space for the end caps, whilst height +1 is to accommodate the fact we have a zero-width row
+ if (atlas->PackIdLines < 0)
+ {
+ if (!(atlas->Flags & ImFontAtlasFlags_NoBakedLines))
+ atlas->PackIdLines = atlas->AddCustomRectRegular(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1);
+ }
+}
+
+// This is called/shared by both the stb_truetype and the FreeType builder.
+void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
+{
+ // Render into our custom data blocks
+ IM_ASSERT(atlas->TexPixelsAlpha8 != NULL || atlas->TexPixelsRGBA32 != NULL);
+ ImFontAtlasBuildRenderDefaultTexData(atlas);
+ ImFontAtlasBuildRenderLinesTexData(atlas);
+
+ // Register custom rectangle glyphs
+ for (int i = 0; i < atlas->CustomRects.Size; i++)
+ {
+ const ImFontAtlasCustomRect* r = &atlas->CustomRects[i];
+ if (r->Font == NULL || r->GlyphID == 0)
+ continue;
+
+ // Will ignore ImFontConfig settings: GlyphMinAdvanceX, GlyphMinAdvanceY, GlyphExtraSpacing, PixelSnapH
+ IM_ASSERT(r->Font->ContainerAtlas == atlas);
+ ImVec2 uv0, uv1;
+ atlas->CalcCustomRectUV(r, &uv0, &uv1);
+ r->Font->AddGlyph(NULL, (ImWchar)r->GlyphID, r->GlyphOffset.x, r->GlyphOffset.y, r->GlyphOffset.x + r->Width, r->GlyphOffset.y + r->Height, uv0.x, uv0.y, uv1.x, uv1.y, r->GlyphAdvanceX);
+ }
+
+ // Build all fonts lookup tables
+ for (int i = 0; i < atlas->Fonts.Size; i++)
+ if (atlas->Fonts[i]->DirtyLookupTables)
+ atlas->Fonts[i]->BuildLookupTable();
+
+ atlas->TexReady = true;
+}
+
+// Retrieve list of range (2 int per range, values are inclusive)
+const ImWchar* ImFontAtlas::GetGlyphRangesDefault()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesKorean()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3131, 0x3163, // Korean alphabets
+ 0xAC00, 0xD7A3, // Korean characters
+ 0xFFFD, 0xFFFD, // Invalid
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x2000, 0x206F, // General Punctuation
+ 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
+ 0x31F0, 0x31FF, // Katakana Phonetic Extensions
+ 0xFF00, 0xFFEF, // Half-width characters
+ 0xFFFD, 0xFFFD, // Invalid
+ 0x4e00, 0x9FAF, // CJK Ideograms
+ 0,
+ };
+ return &ranges[0];
+}
+
+static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short* accumulative_offsets, int accumulative_offsets_count, ImWchar* out_ranges)
+{
+ for (int n = 0; n < accumulative_offsets_count; n++, out_ranges += 2)
+ {
+ out_ranges[0] = out_ranges[1] = (ImWchar)(base_codepoint + accumulative_offsets[n]);
+ base_codepoint += accumulative_offsets[n];
+ }
+ out_ranges[0] = 0;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] ImFontAtlas glyph ranges helpers
+//-------------------------------------------------------------------------
+
+const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon()
+{
+ // Store 2500 regularly used characters for Simplified Chinese.
+ // Sourced from https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E7%8E%B0%E4%BB%A3%E6%B1%89%E8%AF%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E8%A1%A8
+ // This table covers 97.97% of all characters used during the month in July, 1987.
+ // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
+ // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.)
+ static const short accumulative_offsets_from_0x4E00[] =
+ {
+ 0,1,2,4,1,1,1,1,2,1,3,2,1,2,2,1,1,1,1,1,5,2,1,2,3,3,3,2,2,4,1,1,1,2,1,5,2,3,1,2,1,2,1,1,2,1,1,2,2,1,4,1,1,1,1,5,10,1,2,19,2,1,2,1,2,1,2,1,2,
+ 1,5,1,6,3,2,1,2,2,1,1,1,4,8,5,1,1,4,1,1,3,1,2,1,5,1,2,1,1,1,10,1,1,5,2,4,6,1,4,2,2,2,12,2,1,1,6,1,1,1,4,1,1,4,6,5,1,4,2,2,4,10,7,1,1,4,2,4,
+ 2,1,4,3,6,10,12,5,7,2,14,2,9,1,1,6,7,10,4,7,13,1,5,4,8,4,1,1,2,28,5,6,1,1,5,2,5,20,2,2,9,8,11,2,9,17,1,8,6,8,27,4,6,9,20,11,27,6,68,2,2,1,1,
+ 1,2,1,2,2,7,6,11,3,3,1,1,3,1,2,1,1,1,1,1,3,1,1,8,3,4,1,5,7,2,1,4,4,8,4,2,1,2,1,1,4,5,6,3,6,2,12,3,1,3,9,2,4,3,4,1,5,3,3,1,3,7,1,5,1,1,1,1,2,
+ 3,4,5,2,3,2,6,1,1,2,1,7,1,7,3,4,5,15,2,2,1,5,3,22,19,2,1,1,1,1,2,5,1,1,1,6,1,1,12,8,2,9,18,22,4,1,1,5,1,16,1,2,7,10,15,1,1,6,2,4,1,2,4,1,6,
+ 1,1,3,2,4,1,6,4,5,1,2,1,1,2,1,10,3,1,3,2,1,9,3,2,5,7,2,19,4,3,6,1,1,1,1,1,4,3,2,1,1,1,2,5,3,1,1,1,2,2,1,1,2,1,1,2,1,3,1,1,1,3,7,1,4,1,1,2,1,
+ 1,2,1,2,4,4,3,8,1,1,1,2,1,3,5,1,3,1,3,4,6,2,2,14,4,6,6,11,9,1,15,3,1,28,5,2,5,5,3,1,3,4,5,4,6,14,3,2,3,5,21,2,7,20,10,1,2,19,2,4,28,28,2,3,
+ 2,1,14,4,1,26,28,42,12,40,3,52,79,5,14,17,3,2,2,11,3,4,6,3,1,8,2,23,4,5,8,10,4,2,7,3,5,1,1,6,3,1,2,2,2,5,28,1,1,7,7,20,5,3,29,3,17,26,1,8,4,
+ 27,3,6,11,23,5,3,4,6,13,24,16,6,5,10,25,35,7,3,2,3,3,14,3,6,2,6,1,4,2,3,8,2,1,1,3,3,3,4,1,1,13,2,2,4,5,2,1,14,14,1,2,2,1,4,5,2,3,1,14,3,12,
+ 3,17,2,16,5,1,2,1,8,9,3,19,4,2,2,4,17,25,21,20,28,75,1,10,29,103,4,1,2,1,1,4,2,4,1,2,3,24,2,2,2,1,1,2,1,3,8,1,1,1,2,1,1,3,1,1,1,6,1,5,3,1,1,
+ 1,3,4,1,1,5,2,1,5,6,13,9,16,1,1,1,1,3,2,3,2,4,5,2,5,2,2,3,7,13,7,2,2,1,1,1,1,2,3,3,2,1,6,4,9,2,1,14,2,14,2,1,18,3,4,14,4,11,41,15,23,15,23,
+ 176,1,3,4,1,1,1,1,5,3,1,2,3,7,3,1,1,2,1,2,4,4,6,2,4,1,9,7,1,10,5,8,16,29,1,1,2,2,3,1,3,5,2,4,5,4,1,1,2,2,3,3,7,1,6,10,1,17,1,44,4,6,2,1,1,6,
+ 5,4,2,10,1,6,9,2,8,1,24,1,2,13,7,8,8,2,1,4,1,3,1,3,3,5,2,5,10,9,4,9,12,2,1,6,1,10,1,1,7,7,4,10,8,3,1,13,4,3,1,6,1,3,5,2,1,2,17,16,5,2,16,6,
+ 1,4,2,1,3,3,6,8,5,11,11,1,3,3,2,4,6,10,9,5,7,4,7,4,7,1,1,4,2,1,3,6,8,7,1,6,11,5,5,3,24,9,4,2,7,13,5,1,8,82,16,61,1,1,1,4,2,2,16,10,3,8,1,1,
+ 6,4,2,1,3,1,1,1,4,3,8,4,2,2,1,1,1,1,1,6,3,5,1,1,4,6,9,2,1,1,1,2,1,7,2,1,6,1,5,4,4,3,1,8,1,3,3,1,3,2,2,2,2,3,1,6,1,2,1,2,1,3,7,1,8,2,1,2,1,5,
+ 2,5,3,5,10,1,2,1,1,3,2,5,11,3,9,3,5,1,1,5,9,1,2,1,5,7,9,9,8,1,3,3,3,6,8,2,3,2,1,1,32,6,1,2,15,9,3,7,13,1,3,10,13,2,14,1,13,10,2,1,3,10,4,15,
+ 2,15,15,10,1,3,9,6,9,32,25,26,47,7,3,2,3,1,6,3,4,3,2,8,5,4,1,9,4,2,2,19,10,6,2,3,8,1,2,2,4,2,1,9,4,4,4,6,4,8,9,2,3,1,1,1,1,3,5,5,1,3,8,4,6,
+ 2,1,4,12,1,5,3,7,13,2,5,8,1,6,1,2,5,14,6,1,5,2,4,8,15,5,1,23,6,62,2,10,1,1,8,1,2,2,10,4,2,2,9,2,1,1,3,2,3,1,5,3,3,2,1,3,8,1,1,1,11,3,1,1,4,
+ 3,7,1,14,1,2,3,12,5,2,5,1,6,7,5,7,14,11,1,3,1,8,9,12,2,1,11,8,4,4,2,6,10,9,13,1,1,3,1,5,1,3,2,4,4,1,18,2,3,14,11,4,29,4,2,7,1,3,13,9,2,2,5,
+ 3,5,20,7,16,8,5,72,34,6,4,22,12,12,28,45,36,9,7,39,9,191,1,1,1,4,11,8,4,9,2,3,22,1,1,1,1,4,17,1,7,7,1,11,31,10,2,4,8,2,3,2,1,4,2,16,4,32,2,
+ 3,19,13,4,9,1,5,2,14,8,1,1,3,6,19,6,5,1,16,6,2,10,8,5,1,2,3,1,5,5,1,11,6,6,1,3,3,2,6,3,8,1,1,4,10,7,5,7,7,5,8,9,2,1,3,4,1,1,3,1,3,3,2,6,16,
+ 1,4,6,3,1,10,6,1,3,15,2,9,2,10,25,13,9,16,6,2,2,10,11,4,3,9,1,2,6,6,5,4,30,40,1,10,7,12,14,33,6,3,6,7,3,1,3,1,11,14,4,9,5,12,11,49,18,51,31,
+ 140,31,2,2,1,5,1,8,1,10,1,4,4,3,24,1,10,1,3,6,6,16,3,4,5,2,1,4,2,57,10,6,22,2,22,3,7,22,6,10,11,36,18,16,33,36,2,5,5,1,1,1,4,10,1,4,13,2,7,
+ 5,2,9,3,4,1,7,43,3,7,3,9,14,7,9,1,11,1,1,3,7,4,18,13,1,14,1,3,6,10,73,2,2,30,6,1,11,18,19,13,22,3,46,42,37,89,7,3,16,34,2,2,3,9,1,7,1,1,1,2,
+ 2,4,10,7,3,10,3,9,5,28,9,2,6,13,7,3,1,3,10,2,7,2,11,3,6,21,54,85,2,1,4,2,2,1,39,3,21,2,2,5,1,1,1,4,1,1,3,4,15,1,3,2,4,4,2,3,8,2,20,1,8,7,13,
+ 4,1,26,6,2,9,34,4,21,52,10,4,4,1,5,12,2,11,1,7,2,30,12,44,2,30,1,1,3,6,16,9,17,39,82,2,2,24,7,1,7,3,16,9,14,44,2,1,2,1,2,3,5,2,4,1,6,7,5,3,
+ 2,6,1,11,5,11,2,1,18,19,8,1,3,24,29,2,1,3,5,2,2,1,13,6,5,1,46,11,3,5,1,1,5,8,2,10,6,12,6,3,7,11,2,4,16,13,2,5,1,1,2,2,5,2,28,5,2,23,10,8,4,
+ 4,22,39,95,38,8,14,9,5,1,13,5,4,3,13,12,11,1,9,1,27,37,2,5,4,4,63,211,95,2,2,2,1,3,5,2,1,1,2,2,1,1,1,3,2,4,1,2,1,1,5,2,2,1,1,2,3,1,3,1,1,1,
+ 3,1,4,2,1,3,6,1,1,3,7,15,5,3,2,5,3,9,11,4,2,22,1,6,3,8,7,1,4,28,4,16,3,3,25,4,4,27,27,1,4,1,2,2,7,1,3,5,2,28,8,2,14,1,8,6,16,25,3,3,3,14,3,
+ 3,1,1,2,1,4,6,3,8,4,1,1,1,2,3,6,10,6,2,3,18,3,2,5,5,4,3,1,5,2,5,4,23,7,6,12,6,4,17,11,9,5,1,1,10,5,12,1,1,11,26,33,7,3,6,1,17,7,1,5,12,1,11,
+ 2,4,1,8,14,17,23,1,2,1,7,8,16,11,9,6,5,2,6,4,16,2,8,14,1,11,8,9,1,1,1,9,25,4,11,19,7,2,15,2,12,8,52,7,5,19,2,16,4,36,8,1,16,8,24,26,4,6,2,9,
+ 5,4,36,3,28,12,25,15,37,27,17,12,59,38,5,32,127,1,2,9,17,14,4,1,2,1,1,8,11,50,4,14,2,19,16,4,17,5,4,5,26,12,45,2,23,45,104,30,12,8,3,10,2,2,
+ 3,3,1,4,20,7,2,9,6,15,2,20,1,3,16,4,11,15,6,134,2,5,59,1,2,2,2,1,9,17,3,26,137,10,211,59,1,2,4,1,4,1,1,1,2,6,2,3,1,1,2,3,2,3,1,3,4,4,2,3,3,
+ 1,4,3,1,7,2,2,3,1,2,1,3,3,3,2,2,3,2,1,3,14,6,1,3,2,9,6,15,27,9,34,145,1,1,2,1,1,1,1,2,1,1,1,1,2,2,2,3,1,2,1,1,1,2,3,5,8,3,5,2,4,1,3,2,2,2,12,
+ 4,1,1,1,10,4,5,1,20,4,16,1,15,9,5,12,2,9,2,5,4,2,26,19,7,1,26,4,30,12,15,42,1,6,8,172,1,1,4,2,1,1,11,2,2,4,2,1,2,1,10,8,1,2,1,4,5,1,2,5,1,8,
+ 4,1,3,4,2,1,6,2,1,3,4,1,2,1,1,1,1,12,5,7,2,4,3,1,1,1,3,3,6,1,2,2,3,3,3,2,1,2,12,14,11,6,6,4,12,2,8,1,7,10,1,35,7,4,13,15,4,3,23,21,28,52,5,
+ 26,5,6,1,7,10,2,7,53,3,2,1,1,1,2,163,532,1,10,11,1,3,3,4,8,2,8,6,2,2,23,22,4,2,2,4,2,1,3,1,3,3,5,9,8,2,1,2,8,1,10,2,12,21,20,15,105,2,3,1,1,
+ 3,2,3,1,1,2,5,1,4,15,11,19,1,1,1,1,5,4,5,1,1,2,5,3,5,12,1,2,5,1,11,1,1,15,9,1,4,5,3,26,8,2,1,3,1,1,15,19,2,12,1,2,5,2,7,2,19,2,20,6,26,7,5,
+ 2,2,7,34,21,13,70,2,128,1,1,2,1,1,2,1,1,3,2,2,2,15,1,4,1,3,4,42,10,6,1,49,85,8,1,2,1,1,4,4,2,3,6,1,5,7,4,3,211,4,1,2,1,2,5,1,2,4,2,2,6,5,6,
+ 10,3,4,48,100,6,2,16,296,5,27,387,2,2,3,7,16,8,5,38,15,39,21,9,10,3,7,59,13,27,21,47,5,21,6
+ };
+ static ImWchar base_ranges[] = // not zero-terminated
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x2000, 0x206F, // General Punctuation
+ 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
+ 0x31F0, 0x31FF, // Katakana Phonetic Extensions
+ 0xFF00, 0xFFEF, // Half-width characters
+ 0xFFFD, 0xFFFD // Invalid
+ };
+ static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 };
+ if (!full_ranges[0])
+ {
+ memcpy(full_ranges, base_ranges, sizeof(base_ranges));
+ UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
+ }
+ return &full_ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
+{
+ // 2999 ideograms code points for Japanese
+ // - 2136 Joyo (meaning "for regular use" or "for common use") Kanji code points
+ // - 863 Jinmeiyo (meaning "for personal name") Kanji code points
+ // - Sourced from the character information database of the Information-technology Promotion Agency, Japan
+ // - https://mojikiban.ipa.go.jp/mji/
+ // - Available under the terms of the Creative Commons Attribution-ShareAlike 2.1 Japan (CC BY-SA 2.1 JP).
+ // - https://creativecommons.org/licenses/by-sa/2.1/jp/deed.en
+ // - https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode
+ // - You can generate this code by the script at:
+ // - https://github.com/vaiorabbit/everyday_use_kanji
+ // - References:
+ // - List of Joyo Kanji
+ // - (Official list by the Agency for Cultural Affairs) https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kakuki/14/tosin02/index.html
+ // - (Wikipedia) https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji
+ // - List of Jinmeiyo Kanji
+ // - (Official list by the Ministry of Justice) http://www.moj.go.jp/MINJI/minji86.html
+ // - (Wikipedia) https://en.wikipedia.org/wiki/Jinmeiy%C5%8D_kanji
+ // - Missing 1 Joyo Kanji: U+20B9F (Kun'yomi: Shikaru, On'yomi: Shitsu,shichi), see https://github.com/ocornut/imgui/pull/3627 for details.
+ // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters.
+ // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.)
+ static const short accumulative_offsets_from_0x4E00[] =
+ {
+ 0,1,2,4,1,1,1,1,2,1,3,3,2,2,1,5,3,5,7,5,6,1,2,1,7,2,6,3,1,8,1,1,4,1,1,18,2,11,2,6,2,1,2,1,5,1,2,1,3,1,2,1,2,3,3,1,1,2,3,1,1,1,12,7,9,1,4,5,1,
+ 1,2,1,10,1,1,9,2,2,4,5,6,9,3,1,1,1,1,9,3,18,5,2,2,2,2,1,6,3,7,1,1,1,1,2,2,4,2,1,23,2,10,4,3,5,2,4,10,2,4,13,1,6,1,9,3,1,1,6,6,7,6,3,1,2,11,3,
+ 2,2,3,2,15,2,2,5,4,3,6,4,1,2,5,2,12,16,6,13,9,13,2,1,1,7,16,4,7,1,19,1,5,1,2,2,7,7,8,2,6,5,4,9,18,7,4,5,9,13,11,8,15,2,1,1,1,2,1,2,2,1,2,2,8,
+ 2,9,3,3,1,1,4,4,1,1,1,4,9,1,4,3,5,5,2,7,5,3,4,8,2,1,13,2,3,3,1,14,1,1,4,5,1,3,6,1,5,2,1,1,3,3,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1,1,1,1,12,3,3,9,5,
+ 2,6,1,5,6,1,2,3,18,2,4,14,4,1,3,6,1,1,6,3,5,5,3,2,2,2,2,12,3,1,4,2,3,2,3,11,1,7,4,1,2,1,3,17,1,9,1,24,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,2,4,15,1,
+ 1,2,1,1,2,1,5,2,5,20,2,5,9,1,10,8,7,6,1,1,1,1,1,1,6,2,1,2,8,1,1,1,1,5,1,1,3,1,1,1,1,3,1,1,12,4,1,3,1,1,1,1,1,10,3,1,7,5,13,1,2,3,4,6,1,1,30,
+ 2,9,9,1,15,38,11,3,1,8,24,7,1,9,8,10,2,1,9,31,2,13,6,2,9,4,49,5,2,15,2,1,10,2,1,1,1,2,2,6,15,30,35,3,14,18,8,1,16,10,28,12,19,45,38,1,3,2,3,
+ 13,2,1,7,3,6,5,3,4,3,1,5,7,8,1,5,3,18,5,3,6,1,21,4,24,9,24,40,3,14,3,21,3,2,1,2,4,2,3,1,15,15,6,5,1,1,3,1,5,6,1,9,7,3,3,2,1,4,3,8,21,5,16,4,
+ 5,2,10,11,11,3,6,3,2,9,3,6,13,1,2,1,1,1,1,11,12,6,6,1,4,2,6,5,2,1,1,3,3,6,13,3,1,1,5,1,2,3,3,14,2,1,2,2,2,5,1,9,5,1,1,6,12,3,12,3,4,13,2,14,
+ 2,8,1,17,5,1,16,4,2,2,21,8,9,6,23,20,12,25,19,9,38,8,3,21,40,25,33,13,4,3,1,4,1,2,4,1,2,5,26,2,1,1,2,1,3,6,2,1,1,1,1,1,1,2,3,1,1,1,9,2,3,1,1,
+ 1,3,6,3,2,1,1,6,6,1,8,2,2,2,1,4,1,2,3,2,7,3,2,4,1,2,1,2,2,1,1,1,1,1,3,1,2,5,4,10,9,4,9,1,1,1,1,1,1,5,3,2,1,6,4,9,6,1,10,2,31,17,8,3,7,5,40,1,
+ 7,7,1,6,5,2,10,7,8,4,15,39,25,6,28,47,18,10,7,1,3,1,1,2,1,1,1,3,3,3,1,1,1,3,4,2,1,4,1,3,6,10,7,8,6,2,2,1,3,3,2,5,8,7,9,12,2,15,1,1,4,1,2,1,1,
+ 1,3,2,1,3,3,5,6,2,3,2,10,1,4,2,8,1,1,1,11,6,1,21,4,16,3,1,3,1,4,2,3,6,5,1,3,1,1,3,3,4,6,1,1,10,4,2,7,10,4,7,4,2,9,4,3,1,1,1,4,1,8,3,4,1,3,1,
+ 6,1,4,2,1,4,7,2,1,8,1,4,5,1,1,2,2,4,6,2,7,1,10,1,1,3,4,11,10,8,21,4,6,1,3,5,2,1,2,28,5,5,2,3,13,1,2,3,1,4,2,1,5,20,3,8,11,1,3,3,3,1,8,10,9,2,
+ 10,9,2,3,1,1,2,4,1,8,3,6,1,7,8,6,11,1,4,29,8,4,3,1,2,7,13,1,4,1,6,2,6,12,12,2,20,3,2,3,6,4,8,9,2,7,34,5,1,18,6,1,1,4,4,5,7,9,1,2,2,4,3,4,1,7,
+ 2,2,2,6,2,3,25,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,5,3,4,4,3,2,1,1,4,1,2,1,1,3,1,11,1,6,3,1,7,3,6,2,8,8,6,9,3,4,11,3,2,10,12,2,5,11,1,6,4,5,
+ 3,1,8,5,4,6,6,3,5,1,1,3,2,1,2,2,6,17,12,1,10,1,6,12,1,6,6,19,9,6,16,1,13,4,4,15,7,17,6,11,9,15,12,6,7,2,1,2,2,15,9,3,21,4,6,49,18,7,3,2,3,1,
+ 6,8,2,2,6,2,9,1,3,6,4,4,1,2,16,2,5,2,1,6,2,3,5,3,1,2,5,1,2,1,9,3,1,8,6,4,8,11,3,1,1,1,1,3,1,13,8,4,1,3,2,2,1,4,1,11,1,5,2,1,5,2,5,8,6,1,1,7,
+ 4,3,8,3,2,7,2,1,5,1,5,2,4,7,6,2,8,5,1,11,4,5,3,6,18,1,2,13,3,3,1,21,1,1,4,1,4,1,1,1,8,1,2,2,7,1,2,4,2,2,9,2,1,1,1,4,3,6,3,12,5,1,1,1,5,6,3,2,
+ 4,8,2,2,4,2,7,1,8,9,5,2,3,2,1,3,2,13,7,14,6,5,1,1,2,1,4,2,23,2,1,1,6,3,1,4,1,15,3,1,7,3,9,14,1,3,1,4,1,1,5,8,1,3,8,3,8,15,11,4,14,4,4,2,5,5,
+ 1,7,1,6,14,7,7,8,5,15,4,8,6,5,6,2,1,13,1,20,15,11,9,2,5,6,2,11,2,6,2,5,1,5,8,4,13,19,25,4,1,1,11,1,34,2,5,9,14,6,2,2,6,1,1,14,1,3,14,13,1,6,
+ 12,21,14,14,6,32,17,8,32,9,28,1,2,4,11,8,3,1,14,2,5,15,1,1,1,1,3,6,4,1,3,4,11,3,1,1,11,30,1,5,1,4,1,5,8,1,1,3,2,4,3,17,35,2,6,12,17,3,1,6,2,
+ 1,1,12,2,7,3,3,2,1,16,2,8,3,6,5,4,7,3,3,8,1,9,8,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,4,3,7,5,8,3,3,3,3,3,3,1,23,10,3,1,2,2,6,3,1,16,1,16,
+ 22,3,10,4,11,6,9,7,7,3,6,2,2,2,4,10,2,1,1,2,8,7,1,6,4,1,3,3,3,5,10,12,12,2,3,12,8,15,1,1,16,6,6,1,5,9,11,4,11,4,2,6,12,1,17,5,13,1,4,9,5,1,11,
+ 2,1,8,1,5,7,28,8,3,5,10,2,17,3,38,22,1,2,18,12,10,4,38,18,1,4,44,19,4,1,8,4,1,12,1,4,31,12,1,14,7,75,7,5,10,6,6,13,3,2,11,11,3,2,5,28,15,6,18,
+ 18,5,6,4,3,16,1,7,18,7,36,3,5,3,1,7,1,9,1,10,7,2,4,2,6,2,9,7,4,3,32,12,3,7,10,2,23,16,3,1,12,3,31,4,11,1,3,8,9,5,1,30,15,6,12,3,2,2,11,19,9,
+ 14,2,6,2,3,19,13,17,5,3,3,25,3,14,1,1,1,36,1,3,2,19,3,13,36,9,13,31,6,4,16,34,2,5,4,2,3,3,5,1,1,1,4,3,1,17,3,2,3,5,3,1,3,2,3,5,6,3,12,11,1,3,
+ 1,2,26,7,12,7,2,14,3,3,7,7,11,25,25,28,16,4,36,1,2,1,6,2,1,9,3,27,17,4,3,4,13,4,1,3,2,2,1,10,4,2,4,6,3,8,2,1,18,1,1,24,2,2,4,33,2,3,63,7,1,6,
+ 40,7,3,4,4,2,4,15,18,1,16,1,1,11,2,41,14,1,3,18,13,3,2,4,16,2,17,7,15,24,7,18,13,44,2,2,3,6,1,1,7,5,1,7,1,4,3,3,5,10,8,2,3,1,8,1,1,27,4,2,1,
+ 12,1,2,1,10,6,1,6,7,5,2,3,7,11,5,11,3,6,6,2,3,15,4,9,1,1,2,1,2,11,2,8,12,8,5,4,2,3,1,5,2,2,1,14,1,12,11,4,1,11,17,17,4,3,2,5,5,7,3,1,5,9,9,8,
+ 2,5,6,6,13,13,2,1,2,6,1,2,2,49,4,9,1,2,10,16,7,8,4,3,2,23,4,58,3,29,1,14,19,19,11,11,2,7,5,1,3,4,6,2,18,5,12,12,17,17,3,3,2,4,1,6,2,3,4,3,1,
+ 1,1,1,5,1,1,9,1,3,1,3,6,1,8,1,1,2,6,4,14,3,1,4,11,4,1,3,32,1,2,4,13,4,1,2,4,2,1,3,1,11,1,4,2,1,4,4,6,3,5,1,6,5,7,6,3,23,3,5,3,5,3,3,13,3,9,10,
+ 1,12,10,2,3,18,13,7,160,52,4,2,2,3,2,14,5,4,12,4,6,4,1,20,4,11,6,2,12,27,1,4,1,2,2,7,4,5,2,28,3,7,25,8,3,19,3,6,10,2,2,1,10,2,5,4,1,3,4,1,5,
+ 3,2,6,9,3,6,2,16,3,3,16,4,5,5,3,2,1,2,16,15,8,2,6,21,2,4,1,22,5,8,1,1,21,11,2,1,11,11,19,13,12,4,2,3,2,3,6,1,8,11,1,4,2,9,5,2,1,11,2,9,1,1,2,
+ 14,31,9,3,4,21,14,4,8,1,7,2,2,2,5,1,4,20,3,3,4,10,1,11,9,8,2,1,4,5,14,12,14,2,17,9,6,31,4,14,1,20,13,26,5,2,7,3,6,13,2,4,2,19,6,2,2,18,9,3,5,
+ 12,12,14,4,6,2,3,6,9,5,22,4,5,25,6,4,8,5,2,6,27,2,35,2,16,3,7,8,8,6,6,5,9,17,2,20,6,19,2,13,3,1,1,1,4,17,12,2,14,7,1,4,18,12,38,33,2,10,1,1,
+ 2,13,14,17,11,50,6,33,20,26,74,16,23,45,50,13,38,33,6,6,7,4,4,2,1,3,2,5,8,7,8,9,3,11,21,9,13,1,3,10,6,7,1,2,2,18,5,5,1,9,9,2,68,9,19,13,2,5,
+ 1,4,4,7,4,13,3,9,10,21,17,3,26,2,1,5,2,4,5,4,1,7,4,7,3,4,2,1,6,1,1,20,4,1,9,2,2,1,3,3,2,3,2,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,3,2,10,3,5,3,4,4,
+ 3,4,16,1,6,1,10,2,4,2,1,1,2,10,11,2,2,3,1,24,31,4,10,10,2,5,12,16,164,15,4,16,7,9,15,19,17,1,2,1,1,5,1,1,1,1,1,3,1,4,3,1,3,1,3,1,2,1,1,3,3,7,
+ 2,8,1,2,2,2,1,3,4,3,7,8,12,92,2,10,3,1,3,14,5,25,16,42,4,7,7,4,2,21,5,27,26,27,21,25,30,31,2,1,5,13,3,22,5,6,6,11,9,12,1,5,9,7,5,5,22,60,3,5,
+ 13,1,1,8,1,1,3,3,2,1,9,3,3,18,4,1,2,3,7,6,3,1,2,3,9,1,3,1,3,2,1,3,1,1,1,2,1,11,3,1,6,9,1,3,2,3,1,2,1,5,1,1,4,3,4,1,2,2,4,4,1,7,2,1,2,2,3,5,13,
+ 18,3,4,14,9,9,4,16,3,7,5,8,2,6,48,28,3,1,1,4,2,14,8,2,9,2,1,15,2,4,3,2,10,16,12,8,7,1,1,3,1,1,1,2,7,4,1,6,4,38,39,16,23,7,15,15,3,2,12,7,21,
+ 37,27,6,5,4,8,2,10,8,8,6,5,1,2,1,3,24,1,16,17,9,23,10,17,6,1,51,55,44,13,294,9,3,6,2,4,2,2,15,1,1,1,13,21,17,68,14,8,9,4,1,4,9,3,11,7,1,1,1,
+ 5,6,3,2,1,1,1,2,3,8,1,2,2,4,1,5,5,2,1,4,3,7,13,4,1,4,1,3,1,1,1,5,5,10,1,6,1,5,2,1,5,2,4,1,4,5,7,3,18,2,9,11,32,4,3,3,2,4,7,11,16,9,11,8,13,38,
+ 32,8,4,2,1,1,2,1,2,4,4,1,1,1,4,1,21,3,11,1,16,1,1,6,1,3,2,4,9,8,57,7,44,1,3,3,13,3,10,1,1,7,5,2,7,21,47,63,3,15,4,7,1,16,1,1,2,8,2,3,42,15,4,
+ 1,29,7,22,10,3,78,16,12,20,18,4,67,11,5,1,3,15,6,21,31,32,27,18,13,71,35,5,142,4,10,1,2,50,19,33,16,35,37,16,19,27,7,1,133,19,1,4,8,7,20,1,4,
+ 4,1,10,3,1,6,1,2,51,5,40,15,24,43,22928,11,1,13,154,70,3,1,1,7,4,10,1,2,1,1,2,1,2,1,2,2,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,
+ 3,2,1,1,1,1,2,1,1,
+ };
+ static ImWchar base_ranges[] = // not zero-terminated
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana
+ 0x31F0, 0x31FF, // Katakana Phonetic Extensions
+ 0xFF00, 0xFFEF, // Half-width characters
+ 0xFFFD, 0xFFFD // Invalid
+ };
+ static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 };
+ if (!full_ranges[0])
+ {
+ memcpy(full_ranges, base_ranges, sizeof(base_ranges));
+ UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges));
+ }
+ return &full_ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin + Latin Supplement
+ 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement
+ 0x2DE0, 0x2DFF, // Cyrillic Extended-A
+ 0xA640, 0xA69F, // Cyrillic Extended-B
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesThai()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin
+ 0x2010, 0x205E, // Punctuations
+ 0x0E00, 0x0E7F, // Thai
+ 0,
+ };
+ return &ranges[0];
+}
+
+const ImWchar* ImFontAtlas::GetGlyphRangesVietnamese()
+{
+ static const ImWchar ranges[] =
+ {
+ 0x0020, 0x00FF, // Basic Latin
+ 0x0102, 0x0103,
+ 0x0110, 0x0111,
+ 0x0128, 0x0129,
+ 0x0168, 0x0169,
+ 0x01A0, 0x01A1,
+ 0x01AF, 0x01B0,
+ 0x1EA0, 0x1EF9,
+ 0,
+ };
+ return &ranges[0];
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontGlyphRangesBuilder
+//-----------------------------------------------------------------------------
+
+void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
+{
+ while (text_end ? (text < text_end) : *text)
+ {
+ unsigned int c = 0;
+ int c_len = ImTextCharFromUtf8(&c, text, text_end);
+ text += c_len;
+ if (c_len == 0)
+ break;
+ AddChar((ImWchar)c);
+ }
+}
+
+void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges)
+{
+ for (; ranges[0]; ranges += 2)
+ for (ImWchar c = ranges[0]; c <= ranges[1]; c++)
+ AddChar(c);
+}
+
+void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
+{
+ const int max_codepoint = IM_UNICODE_CODEPOINT_MAX;
+ for (int n = 0; n <= max_codepoint; n++)
+ if (GetBit(n))
+ {
+ out_ranges->push_back((ImWchar)n);
+ while (n < max_codepoint && GetBit(n + 1))
+ n++;
+ out_ranges->push_back((ImWchar)n);
+ }
+ out_ranges->push_back(0);
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFont
+//-----------------------------------------------------------------------------
+
+ImFont::ImFont()
+{
+ FontSize = 0.0f;
+ FallbackAdvanceX = 0.0f;
+ FallbackChar = (ImWchar)-1;
+ EllipsisChar = (ImWchar)-1;
+ DotChar = (ImWchar)-1;
+ FallbackGlyph = NULL;
+ ContainerAtlas = NULL;
+ ConfigData = NULL;
+ ConfigDataCount = 0;
+ DirtyLookupTables = false;
+ Scale = 1.0f;
+ Ascent = Descent = 0.0f;
+ MetricsTotalSurface = 0;
+ memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap));
+}
+
+ImFont::~ImFont()
+{
+ ClearOutputData();
+}
+
+void ImFont::ClearOutputData()
+{
+ FontSize = 0.0f;
+ FallbackAdvanceX = 0.0f;
+ Glyphs.clear();
+ IndexAdvanceX.clear();
+ IndexLookup.clear();
+ FallbackGlyph = NULL;
+ ContainerAtlas = NULL;
+ DirtyLookupTables = true;
+ Ascent = Descent = 0.0f;
+ MetricsTotalSurface = 0;
+}
+
+static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_chars, int candidate_chars_count)
+{
+ for (int n = 0; n < candidate_chars_count; n++)
+ if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL)
+ return candidate_chars[n];
+ return (ImWchar)-1;
+}
+
+void ImFont::BuildLookupTable()
+{
+ int max_codepoint = 0;
+ for (int i = 0; i != Glyphs.Size; i++)
+ max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint);
+
+ // Build lookup table
+ IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved
+ IndexAdvanceX.clear();
+ IndexLookup.clear();
+ DirtyLookupTables = false;
+ memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap));
+ GrowIndex(max_codepoint + 1);
+ for (int i = 0; i < Glyphs.Size; i++)
+ {
+ int codepoint = (int)Glyphs[i].Codepoint;
+ IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX;
+ IndexLookup[codepoint] = (ImWchar)i;
+
+ // Mark 4K page as used
+ const int page_n = codepoint / 4096;
+ Used4kPagesMap[page_n >> 3] |= 1 << (page_n & 7);
+ }
+
+ // Create a glyph to handle TAB
+ // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?)
+ if (FindGlyph((ImWchar)' '))
+ {
+ if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times (FIXME: Flaky)
+ Glyphs.resize(Glyphs.Size + 1);
+ ImFontGlyph& tab_glyph = Glyphs.back();
+ tab_glyph = *FindGlyph((ImWchar)' ');
+ tab_glyph.Codepoint = '\t';
+ tab_glyph.AdvanceX *= IM_TABSIZE;
+ IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX;
+ IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size - 1);
+ }
+
+ // Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons)
+ SetGlyphVisible((ImWchar)' ', false);
+ SetGlyphVisible((ImWchar)'\t', false);
+
+ // Ellipsis character is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis).
+ // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character.
+ // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots.
+ const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 };
+ const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
+ if (EllipsisChar == (ImWchar)-1)
+ EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));
+ if (DotChar == (ImWchar)-1)
+ DotChar = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
+
+ // Setup fallback character
+ const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };
+ FallbackGlyph = FindGlyphNoFallback(FallbackChar);
+ if (FallbackGlyph == NULL)
+ {
+ FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars));
+ FallbackGlyph = FindGlyphNoFallback(FallbackChar);
+ if (FallbackGlyph == NULL)
+ {
+ FallbackGlyph = &Glyphs.back();
+ FallbackChar = (ImWchar)FallbackGlyph->Codepoint;
+ }
+ }
+
+ FallbackAdvanceX = FallbackGlyph->AdvanceX;
+ for (int i = 0; i < max_codepoint + 1; i++)
+ if (IndexAdvanceX[i] < 0.0f)
+ IndexAdvanceX[i] = FallbackAdvanceX;
+}
+
+// API is designed this way to avoid exposing the 4K page size
+// e.g. use with IsGlyphRangeUnused(0, 255)
+bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last)
+{
+ unsigned int page_begin = (c_begin / 4096);
+ unsigned int page_last = (c_last / 4096);
+ for (unsigned int page_n = page_begin; page_n <= page_last; page_n++)
+ if ((page_n >> 3) < sizeof(Used4kPagesMap))
+ if (Used4kPagesMap[page_n >> 3] & (1 << (page_n & 7)))
+ return false;
+ return true;
+}
+
+void ImFont::SetGlyphVisible(ImWchar c, bool visible)
+{
+ if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)c))
+ glyph->Visible = visible ? 1 : 0;
+}
+
+void ImFont::GrowIndex(int new_size)
+{
+ IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size);
+ if (new_size <= IndexLookup.Size)
+ return;
+ IndexAdvanceX.resize(new_size, -1.0f);
+ IndexLookup.resize(new_size, (ImWchar)-1);
+}
+
+// x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero.
+// Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis).
+// 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font.
+void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x)
+{
+ if (cfg != NULL)
+ {
+ // Clamp & recenter if needed
+ const float advance_x_original = advance_x;
+ advance_x = ImClamp(advance_x, cfg->GlyphMinAdvanceX, cfg->GlyphMaxAdvanceX);
+ if (advance_x != advance_x_original)
+ {
+ float char_off_x = cfg->PixelSnapH ? ImFloor((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f;
+ x0 += char_off_x;
+ x1 += char_off_x;
+ }
+
+ // Snap to pixel
+ if (cfg->PixelSnapH)
+ advance_x = IM_ROUND(advance_x);
+
+ // Bake spacing
+ advance_x += cfg->GlyphExtraSpacing.x;
+ }
+
+ Glyphs.resize(Glyphs.Size + 1);
+ ImFontGlyph& glyph = Glyphs.back();
+ glyph.Codepoint = (unsigned int)codepoint;
+ glyph.Visible = (x0 != x1) && (y0 != y1);
+ glyph.Colored = false;
+ glyph.X0 = x0;
+ glyph.Y0 = y0;
+ glyph.X1 = x1;
+ glyph.Y1 = y1;
+ glyph.U0 = u0;
+ glyph.V0 = v0;
+ glyph.U1 = u1;
+ glyph.V1 = v1;
+ glyph.AdvanceX = advance_x;
+
+ // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round)
+ // We use (U1-U0)*TexWidth instead of X1-X0 to account for oversampling.
+ float pad = ContainerAtlas->TexGlyphPadding + 0.99f;
+ DirtyLookupTables = true;
+ MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + pad) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + pad);
+}
+
+void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
+{
+ IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function.
+ unsigned int index_size = (unsigned int)IndexLookup.Size;
+
+ if (dst < index_size && IndexLookup.Data[dst] == (ImWchar)-1 && !overwrite_dst) // 'dst' already exists
+ return;
+ if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op
+ return;
+
+ GrowIndex(dst + 1);
+ IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (ImWchar)-1;
+ IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f;
+}
+
+const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
+{
+ if (c >= (size_t)IndexLookup.Size)
+ return FallbackGlyph;
+ const ImWchar i = IndexLookup.Data[c];
+ if (i == (ImWchar)-1)
+ return FallbackGlyph;
+ return &Glyphs.Data[i];
+}
+
+const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const
+{
+ if (c >= (size_t)IndexLookup.Size)
+ return NULL;
+ const ImWchar i = IndexLookup.Data[c];
+ if (i == (ImWchar)-1)
+ return NULL;
+ return &Glyphs.Data[i];
+}
+
+const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
+{
+ // Simple word-wrapping for English, not full-featured. Please submit failing cases!
+ // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
+
+ // For references, possible wrap point marked with ^
+ // "aaa bbb, ccc,ddd. eee fff. ggg!"
+ // ^ ^ ^ ^ ^__ ^ ^
+
+ // List of hardcoded separators: .,;!?'"
+
+ // Skip extra blanks after a line returns (that includes not counting them in width computation)
+ // e.g. "Hello world" --> "Hello" "World"
+
+ // Cut words that cannot possibly fit within one line.
+ // e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish"
+
+ float line_width = 0.0f;
+ float word_width = 0.0f;
+ float blank_width = 0.0f;
+ wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters
+
+ const char* word_end = text;
+ const char* prev_word_end = NULL;
+ bool inside_word = true;
+
+ const char* s = text;
+ while (s < text_end)
+ {
+ unsigned int c = (unsigned int)*s;
+ const char* next_s;
+ if (c < 0x80)
+ next_s = s + 1;
+ else
+ next_s = s + ImTextCharFromUtf8(&c, s, text_end);
+ if (c == 0)
+ break;
+
+ if (c < 32)
+ {
+ if (c == '\n')
+ {
+ line_width = word_width = blank_width = 0.0f;
+ inside_word = true;
+ s = next_s;
+ continue;
+ }
+ if (c == '\r')
+ {
+ s = next_s;
+ continue;
+ }
+ }
+
+ const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX);
+ if (ImCharIsBlankW(c))
+ {
+ if (inside_word)
+ {
+ line_width += blank_width;
+ blank_width = 0.0f;
+ word_end = s;
+ }
+ blank_width += char_width;
+ inside_word = false;
+ }
+ else
+ {
+ word_width += char_width;
+ if (inside_word)
+ {
+ word_end = next_s;
+ }
+ else
+ {
+ prev_word_end = word_end;
+ line_width += word_width + blank_width;
+ word_width = blank_width = 0.0f;
+ }
+
+ // Allow wrapping after punctuation.
+ inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"');
+ }
+
+ // We ignore blank width at the end of the line (they can be skipped)
+ if (line_width + word_width > wrap_width)
+ {
+ // Words that cannot possibly fit within an entire line will be cut anywhere.
+ if (word_width < wrap_width)
+ s = prev_word_end ? prev_word_end : word_end;
+ break;
+ }
+
+ s = next_s;
+ }
+
+ return s;
+}
+
+ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const
+{
+ if (!text_end)
+ text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this.
+
+ const float line_height = size;
+ const float scale = size / FontSize;
+
+ ImVec2 text_size = ImVec2(0, 0);
+ float line_width = 0.0f;
+
+ const bool word_wrap_enabled = (wrap_width > 0.0f);
+ const char* word_wrap_eol = NULL;
+
+ const char* s = text_begin;
+ while (s < text_end)
+ {
+ if (word_wrap_enabled)
+ {
+ // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
+ if (!word_wrap_eol)
+ {
+ word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width);
+ if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
+ word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
+ }
+
+ if (s >= word_wrap_eol)
+ {
+ if (text_size.x < line_width)
+ text_size.x = line_width;
+ text_size.y += line_height;
+ line_width = 0.0f;
+ word_wrap_eol = NULL;
+
+ // Wrapping skips upcoming blanks
+ while (s < text_end)
+ {
+ const char c = *s;
+ if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
+ }
+ continue;
+ }
+ }
+
+ // Decode and advance source
+ const char* prev_s = s;
+ unsigned int c = (unsigned int)*s;
+ if (c < 0x80)
+ {
+ s += 1;
+ }
+ else
+ {
+ s += ImTextCharFromUtf8(&c, s, text_end);
+ if (c == 0) // Malformed UTF-8?
+ break;
+ }
+
+ if (c < 32)
+ {
+ if (c == '\n')
+ {
+ text_size.x = ImMax(text_size.x, line_width);
+ text_size.y += line_height;
+ line_width = 0.0f;
+ continue;
+ }
+ if (c == '\r')
+ continue;
+ }
+
+ const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * scale;
+ if (line_width + char_width >= max_width)
+ {
+ s = prev_s;
+ break;
+ }
+
+ line_width += char_width;
+ }
+
+ if (text_size.x < line_width)
+ text_size.x = line_width;
+
+ if (line_width > 0 || text_size.y == 0.0f)
+ text_size.y += line_height;
+
+ if (remaining)
+ *remaining = s;
+
+ return text_size;
+}
+
+// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
+void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const
+{
+ const ImFontGlyph* glyph = FindGlyph(c);
+ if (!glyph || !glyph->Visible)
+ return;
+ if (glyph->Colored)
+ col |= ~IM_COL32_A_MASK;
+ float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
+ pos.x = IM_FLOOR(pos.x);
+ pos.y = IM_FLOOR(pos.y);
+ draw_list->PrimReserve(6, 4);
+ draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
+}
+
+// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
+void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
+{
+ if (!text_end)
+ text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
+
+ // Align to be pixel perfect
+ pos.x = IM_FLOOR(pos.x);
+ pos.y = IM_FLOOR(pos.y);
+ float x = pos.x;
+ float y = pos.y;
+ if (y > clip_rect.w)
+ return;
+
+ const float scale = size / FontSize;
+ const float line_height = FontSize * scale;
+ const bool word_wrap_enabled = (wrap_width > 0.0f);
+ const char* word_wrap_eol = NULL;
+
+ // Fast-forward to first visible line
+ const char* s = text_begin;
+ if (y + line_height < clip_rect.y && !word_wrap_enabled)
+ while (y + line_height < clip_rect.y && s < text_end)
+ {
+ s = (const char*)memchr(s, '\n', text_end - s);
+ s = s ? s + 1 : text_end;
+ y += line_height;
+ }
+
+ // For large text, scan for the last visible line in order to avoid over-reserving in the call to PrimReserve()
+ // Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer without a newline will likely crash atm)
+ if (text_end - s > 10000 && !word_wrap_enabled)
+ {
+ const char* s_end = s;
+ float y_end = y;
+ while (y_end < clip_rect.w && s_end < text_end)
+ {
+ s_end = (const char*)memchr(s_end, '\n', text_end - s_end);
+ s_end = s_end ? s_end + 1 : text_end;
+ y_end += line_height;
+ }
+ text_end = s_end;
+ }
+ if (s == text_end)
+ return;
+
+ // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)
+ const int vtx_count_max = (int)(text_end - s) * 4;
+ const int idx_count_max = (int)(text_end - s) * 6;
+ const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;
+ draw_list->PrimReserve(idx_count_max, vtx_count_max);
+
+ ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
+ ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
+ unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
+
+ const ImU32 col_untinted = col | ~IM_COL32_A_MASK;
+
+ while (s < text_end)
+ {
+ if (word_wrap_enabled)
+ {
+ // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
+ if (!word_wrap_eol)
+ {
+ word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x));
+ if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
+ word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
+ }
+
+ if (s >= word_wrap_eol)
+ {
+ x = pos.x;
+ y += line_height;
+ word_wrap_eol = NULL;
+
+ // Wrapping skips upcoming blanks
+ while (s < text_end)
+ {
+ const char c = *s;
+ if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
+ }
+ continue;
+ }
+ }
+
+ // Decode and advance source
+ unsigned int c = (unsigned int)*s;
+ if (c < 0x80)
+ {
+ s += 1;
+ }
+ else
+ {
+ s += ImTextCharFromUtf8(&c, s, text_end);
+ if (c == 0) // Malformed UTF-8?
+ break;
+ }
+
+ if (c < 32)
+ {
+ if (c == '\n')
+ {
+ x = pos.x;
+ y += line_height;
+ if (y > clip_rect.w)
+ break; // break out of main loop
+ continue;
+ }
+ if (c == '\r')
+ continue;
+ }
+
+ const ImFontGlyph* glyph = FindGlyph((ImWchar)c);
+ if (glyph == NULL)
+ continue;
+
+ float char_width = glyph->AdvanceX * scale;
+ if (glyph->Visible)
+ {
+ // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w
+ float x1 = x + glyph->X0 * scale;
+ float x2 = x + glyph->X1 * scale;
+ float y1 = y + glyph->Y0 * scale;
+ float y2 = y + glyph->Y1 * scale;
+ if (x1 <= clip_rect.z && x2 >= clip_rect.x)
+ {
+ // Render a character
+ float u1 = glyph->U0;
+ float v1 = glyph->V0;
+ float u2 = glyph->U1;
+ float v2 = glyph->V1;
+
+ // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.
+ if (cpu_fine_clip)
+ {
+ if (x1 < clip_rect.x)
+ {
+ u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1);
+ x1 = clip_rect.x;
+ }
+ if (y1 < clip_rect.y)
+ {
+ v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1);
+ y1 = clip_rect.y;
+ }
+ if (x2 > clip_rect.z)
+ {
+ u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1);
+ x2 = clip_rect.z;
+ }
+ if (y2 > clip_rect.w)
+ {
+ v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1);
+ y2 = clip_rect.w;
+ }
+ if (y1 >= y2)
+ {
+ x += char_width;
+ continue;
+ }
+ }
+
+ // Support for untinted glyphs
+ ImU32 glyph_col = glyph->Colored ? col_untinted : col;
+
+ // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:
+ {
+ idx_write[0] = (ImDrawIdx)(vtx_current_idx); idx_write[1] = (ImDrawIdx)(vtx_current_idx+1); idx_write[2] = (ImDrawIdx)(vtx_current_idx+2);
+ idx_write[3] = (ImDrawIdx)(vtx_current_idx); idx_write[4] = (ImDrawIdx)(vtx_current_idx+2); idx_write[5] = (ImDrawIdx)(vtx_current_idx+3);
+ vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1;
+ vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = glyph_col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1;
+ vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = glyph_col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2;
+ vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = glyph_col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2;
+ vtx_write += 4;
+ vtx_current_idx += 4;
+ idx_write += 6;
+ }
+ }
+ }
+ x += char_width;
+ }
+
+ // Give back unused vertices (clipped ones, blanks) ~ this is essentially a PrimUnreserve() action.
+ draw_list->VtxBuffer.Size = (int)(vtx_write - draw_list->VtxBuffer.Data); // Same as calling shrink()
+ draw_list->IdxBuffer.Size = (int)(idx_write - draw_list->IdxBuffer.Data);
+ draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
+ draw_list->_VtxWritePtr = vtx_write;
+ draw_list->_IdxWritePtr = idx_write;
+ draw_list->_VtxCurrentIdx = vtx_current_idx;
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGui Internal Render Helpers
+//-----------------------------------------------------------------------------
+// Vaguely redesigned to stop accessing ImGui global state:
+// - RenderArrow()
+// - RenderBullet()
+// - RenderCheckMark()
+// - RenderMouseCursor()
+// - RenderArrowPointingAt()
+// - RenderRectFilledRangeH()
+// - RenderRectFilledWithHole()
+//-----------------------------------------------------------------------------
+// Function in need of a redesign (legacy mess)
+// - RenderColorRectWithAlphaCheckerboard()
+//-----------------------------------------------------------------------------
+
+// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state
+void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale)
+{
+ const float h = draw_list->_Data->FontSize * 1.00f;
+ float r = h * 0.40f * scale;
+ ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale);
+
+ ImVec2 a, b, c;
+ switch (dir)
+ {
+ case ImGuiDir_Up:
+ case ImGuiDir_Down:
+ if (dir == ImGuiDir_Up) r = -r;
+ a = ImVec2(+0.000f, +0.750f) * r;
+ b = ImVec2(-0.866f, -0.750f) * r;
+ c = ImVec2(+0.866f, -0.750f) * r;
+ break;
+ case ImGuiDir_Left:
+ case ImGuiDir_Right:
+ if (dir == ImGuiDir_Left) r = -r;
+ a = ImVec2(+0.750f, +0.000f) * r;
+ b = ImVec2(-0.750f, +0.866f) * r;
+ c = ImVec2(-0.750f, -0.866f) * r;
+ break;
+ case ImGuiDir_None:
+ case ImGuiDir_COUNT:
+ IM_ASSERT(0);
+ break;
+ }
+ draw_list->AddTriangleFilled(center + a, center + b, center + c, col);
+}
+
+void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col)
+{
+ draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8);
+}
+
+void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz)
+{
+ float thickness = ImMax(sz / 5.0f, 1.0f);
+ sz -= thickness * 0.5f;
+ pos += ImVec2(thickness * 0.25f, thickness * 0.25f);
+
+ float third = sz / 3.0f;
+ float bx = pos.x + third;
+ float by = pos.y + sz - third * 0.5f;
+ draw_list->PathLineTo(ImVec2(bx - third, by - third));
+ draw_list->PathLineTo(ImVec2(bx, by));
+ draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f));
+ draw_list->PathStroke(col, 0, thickness);
+}
+
+void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow)
+{
+ if (mouse_cursor == ImGuiMouseCursor_None)
+ return;
+ IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT);
+
+ ImFontAtlas* font_atlas = draw_list->_Data->Font->ContainerAtlas;
+ ImVec2 offset, size, uv[4];
+ if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
+ {
+ pos -= offset;
+ ImTextureID tex_id = font_atlas->TexID;
+ draw_list->PushTextureID(tex_id);
+ draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
+ draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
+ draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border);
+ draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill);
+ draw_list->PopTextureID();
+ }
+}
+
+// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.
+void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col)
+{
+ switch (direction)
+ {
+ case ImGuiDir_Left: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return;
+ case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return;
+ case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return;
+ case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return;
+ case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings
+ }
+}
+
+static inline float ImAcos01(float x)
+{
+ if (x <= 0.0f) return IM_PI * 0.5f;
+ if (x >= 1.0f) return 0.0f;
+ return ImAcos(x);
+ //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do.
+}
+
+// FIXME: Cleanup and move code to ImDrawList.
+void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding)
+{
+ if (x_end_norm == x_start_norm)
+ return;
+ if (x_start_norm > x_end_norm)
+ ImSwap(x_start_norm, x_end_norm);
+
+ ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y);
+ ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y);
+ if (rounding == 0.0f)
+ {
+ draw_list->AddRectFilled(p0, p1, col, 0.0f);
+ return;
+ }
+
+ rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding);
+ const float inv_rounding = 1.0f / rounding;
+ const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding);
+ const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding);
+ const float half_pi = IM_PI * 0.5f; // We will == compare to this because we know this is the exact value ImAcos01 can return.
+ const float x0 = ImMax(p0.x, rect.Min.x + rounding);
+ if (arc0_b == arc0_e)
+ {
+ draw_list->PathLineTo(ImVec2(x0, p1.y));
+ draw_list->PathLineTo(ImVec2(x0, p0.y));
+ }
+ else if (arc0_b == 0.0f && arc0_e == half_pi)
+ {
+ draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL
+ draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR
+ }
+ else
+ {
+ draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL
+ draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR
+ }
+ if (p1.x > rect.Min.x + rounding)
+ {
+ const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding);
+ const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding);
+ const float x1 = ImMin(p1.x, rect.Max.x - rounding);
+ if (arc1_b == arc1_e)
+ {
+ draw_list->PathLineTo(ImVec2(x1, p0.y));
+ draw_list->PathLineTo(ImVec2(x1, p1.y));
+ }
+ else if (arc1_b == 0.0f && arc1_e == half_pi)
+ {
+ draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR
+ draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3); // BR
+ }
+ else
+ {
+ draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR
+ draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR
+ }
+ }
+ draw_list->PathFillConvex(col);
+}
+
+void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding)
+{
+ const bool fill_L = (inner.Min.x > outer.Min.x);
+ const bool fill_R = (inner.Max.x < outer.Max.x);
+ const bool fill_U = (inner.Min.y > outer.Min.y);
+ const bool fill_D = (inner.Max.y < outer.Max.y);
+ if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft));
+ if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight));
+ if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight));
+ if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight));
+ if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopLeft);
+ if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopRight);
+ if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomLeft);
+ if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomRight);
+}
+
+// Helper for ColorPicker4()
+// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
+// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether.
+// FIXME: uses ImGui::GetColorU32
+void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, ImDrawFlags flags)
+{
+ if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
+ flags = ImDrawFlags_RoundCornersDefault_;
+ if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
+ {
+ ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
+ ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
+ draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
+
+ int yi = 0;
+ for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++)
+ {
+ float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);
+ if (y2 <= y1)
+ continue;
+ for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
+ {
+ float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
+ if (x2 <= x1)
+ continue;
+ ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone;
+ if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; }
+ if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; }
+
+ // Combine flags
+ cell_flags = (flags == ImDrawFlags_RoundCornersNone || cell_flags == ImDrawFlags_RoundCornersNone) ? ImDrawFlags_RoundCornersNone : (cell_flags & flags);
+ draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding, cell_flags);
+ }
+ }
+ }
+ else
+ {
+ draw_list->AddRectFilled(p_min, p_max, col, rounding, flags);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Decompression code
+//-----------------------------------------------------------------------------
+// Compressed with stb_compress() then converted to a C array and encoded as base85.
+// Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file.
+// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
+// Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h
+//-----------------------------------------------------------------------------
+
+static unsigned int stb_decompress_length(const unsigned char *input)
+{
+ return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
+}
+
+static unsigned char *stb__barrier_out_e, *stb__barrier_out_b;
+static const unsigned char *stb__barrier_in_b;
+static unsigned char *stb__dout;
+static void stb__match(const unsigned char *data, unsigned int length)
+{
+ // INVERSE of memmove... write each byte before copying the next...
+ IM_ASSERT(stb__dout + length <= stb__barrier_out_e);
+ if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; }
+ if (data < stb__barrier_out_b) { stb__dout = stb__barrier_out_e+1; return; }
+ while (length--) *stb__dout++ = *data++;
+}
+
+static void stb__lit(const unsigned char *data, unsigned int length)
+{
+ IM_ASSERT(stb__dout + length <= stb__barrier_out_e);
+ if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; }
+ if (data < stb__barrier_in_b) { stb__dout = stb__barrier_out_e+1; return; }
+ memcpy(stb__dout, data, length);
+ stb__dout += length;
+}
+
+#define stb__in2(x) ((i[x] << 8) + i[(x)+1])
+#define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1))
+#define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1))
+
+static const unsigned char *stb_decompress_token(const unsigned char *i)
+{
+ if (*i >= 0x20) { // use fewer if's for cases that expand small
+ if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2;
+ else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3;
+ else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
+ } else { // more ifs for cases that expand large, since overhead is amortized
+ if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4;
+ else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5;
+ else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
+ else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
+ else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5;
+ else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6;
+ }
+ return i;
+}
+
+static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
+{
+ const unsigned long ADLER_MOD = 65521;
+ unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
+ unsigned long blocklen = buflen % 5552;
+
+ unsigned long i;
+ while (buflen) {
+ for (i=0; i + 7 < blocklen; i += 8) {
+ s1 += buffer[0], s2 += s1;
+ s1 += buffer[1], s2 += s1;
+ s1 += buffer[2], s2 += s1;
+ s1 += buffer[3], s2 += s1;
+ s1 += buffer[4], s2 += s1;
+ s1 += buffer[5], s2 += s1;
+ s1 += buffer[6], s2 += s1;
+ s1 += buffer[7], s2 += s1;
+
+ buffer += 8;
+ }
+
+ for (; i < blocklen; ++i)
+ s1 += *buffer++, s2 += s1;
+
+ s1 %= ADLER_MOD, s2 %= ADLER_MOD;
+ buflen -= blocklen;
+ blocklen = 5552;
+ }
+ return (unsigned int)(s2 << 16) + (unsigned int)s1;
+}
+
+static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/)
+{
+ if (stb__in4(0) != 0x57bC0000) return 0;
+ if (stb__in4(4) != 0) return 0; // error! stream is > 4GB
+ const unsigned int olen = stb_decompress_length(i);
+ stb__barrier_in_b = i;
+ stb__barrier_out_e = output + olen;
+ stb__barrier_out_b = output;
+ i += 16;
+
+ stb__dout = output;
+ for (;;) {
+ const unsigned char *old_i = i;
+ i = stb_decompress_token(i);
+ if (i == old_i) {
+ if (*i == 0x05 && i[1] == 0xfa) {
+ IM_ASSERT(stb__dout == output + olen);
+ if (stb__dout != output + olen) return 0;
+ if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2))
+ return 0;
+ return olen;
+ } else {
+ IM_ASSERT(0); /* NOTREACHED */
+ return 0;
+ }
+ }
+ IM_ASSERT(stb__dout <= output + olen);
+ if (stb__dout > output + olen)
+ return 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Default font data (ProggyClean.ttf)
+//-----------------------------------------------------------------------------
+// ProggyClean.ttf
+// Copyright (c) 2004, 2005 Tristan Grimmer
+// MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
+// Download and more information at http://upperbounds.net
+//-----------------------------------------------------------------------------
+// File: 'ProggyClean.ttf' (41208 bytes)
+// Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding).
+// The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size.
+//-----------------------------------------------------------------------------
+static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] =
+ "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
+ "2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
+ "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
+ "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
+ "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
+ "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
+ "tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
+ "ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
+ "x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
+ "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
+ "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
+ "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
+ "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
+ "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
+ "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
+ "%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
+ "OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
+ "h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
+ "o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
+ "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
+ "sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
+ "eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
+ "M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
+ "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
+ "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
+ "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
+ "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
+ "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
+ "nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
+ "7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
+ ")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
+ "D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
+ "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
+ "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
+ "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
+ "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
+ "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
+ ".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
+ "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
+ "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
+ "@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
+ "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
+ "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
+ "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
+ "6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
+ "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
+ ":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
+ "tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
+ "$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
+ ":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
+ "7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
+ "u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
+ "LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
+ ":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
+ "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
+ "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
+ "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
+ "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
+ "9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
+ "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
+ "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
+ "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
+ "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
+ "0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
+ "+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
+ "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
+ "?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
+ "Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
+ ">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
+ "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
+ "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
+ "Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
+ "MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
+ "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
+ "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
+ "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
+ "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
+ ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
+ "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
+ "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
+ "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
+ "/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
+ "m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
+ "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
+ "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
+ "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
+
+static const char* GetDefaultCompressedFontDataTTFBase85()
+{
+ return proggy_clean_ttf_compressed_data_base85;
+}
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imgui_internal.h b/Client/ThirdParty/imgui/imgui_internal.h
new file mode 100644
index 0000000..4ff3379
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui_internal.h
@@ -0,0 +1,2841 @@
+// dear imgui, v1.86 WIP
+// (internal structures/api)
+
+// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
+// Set:
+// #define IMGUI_DEFINE_MATH_OPERATORS
+// To implement maths operators for ImVec2 (disabled by default to not collide with using IM_VEC2_CLASS_EXTRA along with your own math types+operators)
+
+/*
+
+Index of this file:
+
+// [SECTION] Header mess
+// [SECTION] Forward declarations
+// [SECTION] Context pointer
+// [SECTION] STB libraries includes
+// [SECTION] Macros
+// [SECTION] Generic helpers
+// [SECTION] ImDrawList support
+// [SECTION] Widgets support: flags, enums, data structures
+// [SECTION] Clipper support
+// [SECTION] Navigation support
+// [SECTION] Columns support
+// [SECTION] Multi-select support
+// [SECTION] Docking support
+// [SECTION] Viewport support
+// [SECTION] Settings support
+// [SECTION] Metrics, Debug tools
+// [SECTION] Generic context hooks
+// [SECTION] ImGuiContext (main imgui context)
+// [SECTION] ImGuiWindowTempData, ImGuiWindow
+// [SECTION] Tab bar, Tab item support
+// [SECTION] Table support
+// [SECTION] ImGui internal API
+// [SECTION] ImFontAtlas internal API
+// [SECTION] Test Engine specific hooks (imgui_test_engine)
+
+*/
+
+#pragma once
+#ifndef IMGUI_DISABLE
+
+//-----------------------------------------------------------------------------
+// [SECTION] Header mess
+//-----------------------------------------------------------------------------
+
+#ifndef IMGUI_VERSION
+#include "imgui.h"
+#endif
+
+#include <stdio.h> // FILE*, sscanf
+#include <stdlib.h> // NULL, malloc, free, qsort, atoi, atof
+#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
+#include <limits.h> // INT_MIN, INT_MAX
+
+// Enable SSE intrinsics if available
+#if (defined __SSE__ || defined __x86_64__ || defined _M_X64) && !defined(IMGUI_DISABLE_SSE)
+#define IMGUI_ENABLE_SSE
+#include <immintrin.h>
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
+#pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
+#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
+#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
+#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
+#endif
+#endif
+
+// Clang/GCC warnings with -Weverything
+#if defined(__clang__)
+#pragma clang diagnostic push
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx'
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok, for ImFloorSigned()
+#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
+#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
+#pragma clang diagnostic ignored "-Wold-style-cast"
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
+#pragma clang diagnostic ignored "-Wdouble-promotion"
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
+#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn'
+#elif defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+
+// Legacy defines
+#ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Renamed in 1.74
+#error Use IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
+#endif
+#ifdef IMGUI_DISABLE_MATH_FUNCTIONS // Renamed in 1.74
+#error Use IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
+#endif
+
+// Enable stb_truetype by default unless FreeType is enabled.
+// You can compile with both by defining both IMGUI_ENABLE_FREETYPE and IMGUI_ENABLE_STB_TRUETYPE together.
+#ifndef IMGUI_ENABLE_FREETYPE
+#define IMGUI_ENABLE_STB_TRUETYPE
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] Forward declarations
+//-----------------------------------------------------------------------------
+
+struct ImBitVector; // Store 1-bit per value
+struct ImRect; // An axis-aligned rectangle (2 points)
+struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
+struct ImDrawListSharedData; // Data shared between all ImDrawList instances
+struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
+struct ImGuiContext; // Main Dear ImGui context
+struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
+struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
+struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup()
+struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
+struct ImGuiLastItemData; // Status storage for last submitted items
+struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
+struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
+struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
+struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
+struct ImGuiNextItemData; // Storage for SetNextItem** functions
+struct ImGuiOldColumnData; // Storage data for a single column for legacy Columns() api
+struct ImGuiOldColumns; // Storage data for a columns set for legacy Columns() api
+struct ImGuiPopupData; // Storage for current popup stack
+struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file
+struct ImGuiStackSizes; // Storage of stack sizes for debugging/asserting
+struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it
+struct ImGuiTabBar; // Storage for a tab bar
+struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
+struct ImGuiTable; // Storage for a table
+struct ImGuiTableColumn; // Storage for one column of a table
+struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
+struct ImGuiTableSettings; // Storage for a table .ini settings
+struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
+struct ImGuiWindow; // Storage for one window
+struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
+struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
+
+// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
+typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
+typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
+typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
+typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
+typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
+typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
+typedef int ImGuiNavDirSourceFlags; // -> enum ImGuiNavDirSourceFlags_ // Flags: for GetNavInputAmount2d()
+typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests
+typedef int ImGuiNextItemDataFlags; // -> enum ImGuiNextItemDataFlags_ // Flags: for SetNextItemXXX() functions
+typedef int ImGuiNextWindowDataFlags; // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions
+typedef int ImGuiScrollFlags; // -> enum ImGuiScrollFlags_ // Flags: for ScrollToItem() and navigation requests
+typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for SeparatorEx()
+typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
+typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
+
+typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
+
+//-----------------------------------------------------------------------------
+// [SECTION] Context pointer
+// See implementation of this variable in imgui.cpp for comments and details.
+//-----------------------------------------------------------------------------
+
+#ifndef GImGui
+extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
+#endif
+
+//-------------------------------------------------------------------------
+// [SECTION] STB libraries includes
+//-------------------------------------------------------------------------
+
+namespace ImStb
+{
+
+#undef STB_TEXTEDIT_STRING
+#undef STB_TEXTEDIT_CHARTYPE
+#define STB_TEXTEDIT_STRING ImGuiInputTextState
+#define STB_TEXTEDIT_CHARTYPE ImWchar
+#define STB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f)
+#define STB_TEXTEDIT_UNDOSTATECOUNT 99
+#define STB_TEXTEDIT_UNDOCHARCOUNT 999
+#include "imstb_textedit.h"
+
+} // namespace ImStb
+
+//-----------------------------------------------------------------------------
+// [SECTION] Macros
+//-----------------------------------------------------------------------------
+
+// Debug Logging
+#ifndef IMGUI_DEBUG_LOG
+#define IMGUI_DEBUG_LOG(_FMT,...) printf("[%05d] " _FMT, GImGui->FrameCount, __VA_ARGS__)
+#endif
+
+// Debug Logging for selected systems. Remove the '((void)0) //' to enable.
+//#define IMGUI_DEBUG_LOG_POPUP IMGUI_DEBUG_LOG // Enable log
+//#define IMGUI_DEBUG_LOG_NAV IMGUI_DEBUG_LOG // Enable log
+#define IMGUI_DEBUG_LOG_POPUP(...) ((void)0) // Disable log
+#define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log
+
+// Static Asserts
+#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100)
+#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "")
+#else
+#define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1]
+#endif
+
+// "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much.
+// We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code.
+//#define IMGUI_DEBUG_PARANOID
+#ifdef IMGUI_DEBUG_PARANOID
+#define IM_ASSERT_PARANOID(_EXPR) IM_ASSERT(_EXPR)
+#else
+#define IM_ASSERT_PARANOID(_EXPR)
+#endif
+
+// Error handling
+// Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults.
+#ifndef IM_ASSERT_USER_ERROR
+#define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && _MSG) // Recoverable User Error
+#endif
+
+// Misc Macros
+#define IM_PI 3.14159265358979323846f
+#ifdef _WIN32
+#define IM_NEWLINE "\r\n" // Play it nice with Windows users (Update: since 2018-05, Notepad finally appears to support Unix-style carriage returns!)
+#else
+#define IM_NEWLINE "\n"
+#endif
+#define IM_TABSIZE (4)
+#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + (_ALIGN - 1)) & ~(_ALIGN - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
+#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
+#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
+#define IM_FLOOR(_VAL) ((float)(int)(_VAL)) // ImFloor() is not inlined in MSVC debug builds
+#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) //
+
+// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
+#ifdef _MSC_VER
+#define IMGUI_CDECL __cdecl
+#else
+#define IMGUI_CDECL
+#endif
+
+// Warnings
+#if defined(_MSC_VER) && !defined(__clang__)
+#define IM_MSVC_WARNING_SUPPRESS(XXXX) __pragma(warning(suppress: XXXX))
+#else
+#define IM_MSVC_WARNING_SUPPRESS(XXXX)
+#endif
+
+// Debug Tools
+// Use 'Metrics/Debugger->Tools->Item Picker' to break into the call-stack of a specific item.
+// This will call IM_DEBUG_BREAK() which you may redefine yourself. See https://github.com/scottt/debugbreak for more reference.
+#ifndef IM_DEBUG_BREAK
+#if defined (_MSC_VER)
+#define IM_DEBUG_BREAK() __debugbreak()
+#elif defined(__clang__)
+#define IM_DEBUG_BREAK() __builtin_debugtrap()
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03")
+#elif defined(__GNUC__) && defined(__thumb__)
+#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
+#elif defined(__GNUC__) defined(__arm__) && !defined(__thumb__)
+#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0");
+#else
+#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
+#endif
+#endif // #ifndef IM_DEBUG_BREAK
+
+//-----------------------------------------------------------------------------
+// [SECTION] Generic helpers
+// Note that the ImXXX helpers functions are lower-level than ImGui functions.
+// ImGui functions or the ImGui context are never called/used from other ImXXX functions.
+//-----------------------------------------------------------------------------
+// - Helpers: Hashing
+// - Helpers: Sorting
+// - Helpers: Bit manipulation
+// - Helpers: String, Formatting
+// - Helpers: UTF-8 <> wchar conversions
+// - Helpers: ImVec2/ImVec4 operators
+// - Helpers: Maths
+// - Helpers: Geometry
+// - Helper: ImVec1
+// - Helper: ImVec2ih
+// - Helper: ImRect
+// - Helper: ImBitArray
+// - Helper: ImBitVector
+// - Helper: ImSpan<>, ImSpanAllocator<>
+// - Helper: ImPool<>
+// - Helper: ImChunkStream<>
+//-----------------------------------------------------------------------------
+
+// Helpers: Hashing
+IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImU32 seed = 0);
+IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImU32 seed = 0);
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+static inline ImGuiID ImHash(const void* data, int size, ImU32 seed = 0) { return size ? ImHashData(data, (size_t)size, seed) : ImHashStr((const char*)data, 0, seed); } // [moved to ImHashStr/ImHashData in 1.68]
+#endif
+
+// Helpers: Sorting
+#define ImQsort qsort
+
+// Helpers: Color Blending
+IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b);
+
+// Helpers: Bit manipulation
+static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; }
+static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; }
+static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; }
+
+// Helpers: String, Formatting
+IMGUI_API int ImStricmp(const char* str1, const char* str2);
+IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count);
+IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count);
+IMGUI_API char* ImStrdup(const char* str);
+IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str);
+IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c);
+IMGUI_API int ImStrlenW(const ImWchar* str);
+IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line
+IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
+IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
+IMGUI_API void ImStrTrimBlanks(char* str);
+IMGUI_API const char* ImStrSkipBlank(const char* str);
+IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3);
+IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3);
+IMGUI_API const char* ImParseFormatFindStart(const char* format);
+IMGUI_API const char* ImParseFormatFindEnd(const char* format);
+IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, size_t buf_size);
+IMGUI_API int ImParseFormatPrecision(const char* format, int default_value);
+static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; }
+static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; }
+
+// Helpers: UTF-8 <> wchar conversions
+IMGUI_API const char* ImTextCharToUtf8(char out_buf[5], unsigned int c); // return out_buf
+IMGUI_API int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count
+IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count
+IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count
+IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count)
+IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8
+IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8
+
+// Helpers: ImVec2/ImVec4 operators
+// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)
+// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself.
+#ifdef IMGUI_DEFINE_MATH_OPERATORS
+IM_MSVC_RUNTIME_CHECKS_OFF
+static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
+static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
+static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
+static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
+static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
+static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
+static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
+static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
+static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; }
+static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; }
+static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; }
+static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; }
+static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
+static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
+static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
+IM_MSVC_RUNTIME_CHECKS_RESTORE
+#endif
+
+// Helpers: File System
+#ifdef IMGUI_DISABLE_FILE_FUNCTIONS
+#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
+typedef void* ImFileHandle;
+static inline ImFileHandle ImFileOpen(const char*, const char*) { return NULL; }
+static inline bool ImFileClose(ImFileHandle) { return false; }
+static inline ImU64 ImFileGetSize(ImFileHandle) { return (ImU64)-1; }
+static inline ImU64 ImFileRead(void*, ImU64, ImU64, ImFileHandle) { return 0; }
+static inline ImU64 ImFileWrite(const void*, ImU64, ImU64, ImFileHandle) { return 0; }
+#endif
+#ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
+typedef FILE* ImFileHandle;
+IMGUI_API ImFileHandle ImFileOpen(const char* filename, const char* mode);
+IMGUI_API bool ImFileClose(ImFileHandle file);
+IMGUI_API ImU64 ImFileGetSize(ImFileHandle file);
+IMGUI_API ImU64 ImFileRead(void* data, ImU64 size, ImU64 count, ImFileHandle file);
+IMGUI_API ImU64 ImFileWrite(const void* data, ImU64 size, ImU64 count, ImFileHandle file);
+#else
+#define IMGUI_DISABLE_TTY_FUNCTIONS // Can't use stdout, fflush if we are not using default file functions
+#endif
+IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size = NULL, int padding_bytes = 0);
+
+// Helpers: Maths
+IM_MSVC_RUNTIME_CHECKS_OFF
+// - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy)
+#ifndef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
+#define ImFabs(X) fabsf(X)
+#define ImSqrt(X) sqrtf(X)
+#define ImFmod(X, Y) fmodf((X), (Y))
+#define ImCos(X) cosf(X)
+#define ImSin(X) sinf(X)
+#define ImAcos(X) acosf(X)
+#define ImAtan2(Y, X) atan2f((Y), (X))
+#define ImAtof(STR) atof(STR)
+//#define ImFloorStd(X) floorf(X) // We use our own, see ImFloor() and ImFloorSigned()
+#define ImCeil(X) ceilf(X)
+static inline float ImPow(float x, float y) { return powf(x, y); } // DragBehaviorT/SliderBehaviorT uses ImPow with either float/double and need the precision
+static inline double ImPow(double x, double y) { return pow(x, y); }
+static inline float ImLog(float x) { return logf(x); } // DragBehaviorT/SliderBehaviorT uses ImLog with either float/double and need the precision
+static inline double ImLog(double x) { return log(x); }
+static inline int ImAbs(int x) { return x < 0 ? -x : x; }
+static inline float ImAbs(float x) { return fabsf(x); }
+static inline double ImAbs(double x) { return fabs(x); }
+static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument
+static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : ((x > 0.0) ? 1.0 : 0.0); }
+#ifdef IMGUI_ENABLE_SSE
+static inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }
+#else
+static inline float ImRsqrt(float x) { return 1.0f / sqrtf(x); }
+#endif
+static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
+#endif
+// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double
+// (Exceptionally using templates here but we could also redefine them for those types)
+template<typename T> static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
+template<typename T> static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
+template<typename T> static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
+template<typename T> static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); }
+template<typename T> static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
+template<typename T> static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
+template<typename T> static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
+// - Misc maths helpers
+static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); }
+static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); }
+static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); }
+static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); }
+static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); }
+static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); }
+static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
+static inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); }
+static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
+static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; }
+static inline float ImFloor(float f) { return (float)(int)(f); }
+static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
+static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
+static inline int ImModPositive(int a, int b) { return (a + b) % b; }
+static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
+static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
+static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; }
+static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
+IM_MSVC_RUNTIME_CHECKS_RESTORE
+
+// Helpers: Geometry
+IMGUI_API ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t);
+IMGUI_API ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments); // For curves with explicit number of segments
+IMGUI_API ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol);// For auto-tessellated curves you can use tess_tol = style.CurveTessellationTol
+IMGUI_API ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t);
+IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p);
+IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
+IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p);
+IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w);
+inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; }
+IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy);
+
+// Helper: ImVec1 (1D vector)
+// (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches)
+IM_MSVC_RUNTIME_CHECKS_OFF
+struct ImVec1
+{
+ float x;
+ ImVec1() { x = 0.0f; }
+ ImVec1(float _x) { x = _x; }
+};
+
+// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
+struct ImVec2ih
+{
+ short x, y;
+ ImVec2ih() { x = y = 0; }
+ ImVec2ih(short _x, short _y) { x = _x; y = _y; }
+ explicit ImVec2ih(const ImVec2& rhs) { x = (short)rhs.x; y = (short)rhs.y; }
+};
+
+// Helper: ImRect (2D axis aligned bounding-box)
+// NB: we can't rely on ImVec2 math operators being available here!
+struct IMGUI_API ImRect
+{
+ ImVec2 Min; // Upper-left
+ ImVec2 Max; // Lower-right
+
+ ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
+ ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
+ ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
+ ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
+
+ ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); }
+ ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
+ float GetWidth() const { return Max.x - Min.x; }
+ float GetHeight() const { return Max.y - Min.y; }
+ float GetArea() const { return (Max.x - Min.x) * (Max.y - Min.y); }
+ ImVec2 GetTL() const { return Min; } // Top-left
+ ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right
+ ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left
+ ImVec2 GetBR() const { return Max; } // Bottom-right
+ bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; }
+ bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; }
+ bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
+ void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; }
+ void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; }
+ void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
+ void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
+ void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; }
+ void TranslateX(float dx) { Min.x += dx; Max.x += dx; }
+ void TranslateY(float dy) { Min.y += dy; Max.y += dy; }
+ void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display.
+ void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
+ void Floor() { Min.x = IM_FLOOR(Min.x); Min.y = IM_FLOOR(Min.y); Max.x = IM_FLOOR(Max.x); Max.y = IM_FLOOR(Max.y); }
+ bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
+ ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
+};
+IM_MSVC_RUNTIME_CHECKS_RESTORE
+
+// Helper: ImBitArray
+inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; }
+inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; }
+inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; }
+inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on range [n..n2)
+{
+ n2--;
+ while (n <= n2)
+ {
+ int a_mod = (n & 31);
+ int b_mod = (n2 > (n | 31) ? 31 : (n2 & 31)) + 1;
+ ImU32 mask = (ImU32)(((ImU64)1 << b_mod) - 1) & ~(ImU32)(((ImU64)1 << a_mod) - 1);
+ arr[n >> 5] |= mask;
+ n = (n + 32) & ~31;
+ }
+}
+
+// Helper: ImBitArray class (wrapper over ImBitArray functions)
+// Store 1-bit per value.
+template<int BITCOUNT>
+struct IMGUI_API ImBitArray
+{
+ ImU32 Storage[(BITCOUNT + 31) >> 5];
+ ImBitArray() { ClearAllBits(); }
+ void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
+ void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
+ bool TestBit(int n) const { IM_ASSERT(n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
+ void SetBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArraySetBit(Storage, n); }
+ void ClearBit(int n) { IM_ASSERT(n < BITCOUNT); ImBitArrayClearBit(Storage, n); }
+ void SetBitRange(int n, int n2) { ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2)
+};
+
+// Helper: ImBitVector
+// Store 1-bit per value.
+struct IMGUI_API ImBitVector
+{
+ ImVector<ImU32> Storage;
+ void Create(int sz) { Storage.resize((sz + 31) >> 5); memset(Storage.Data, 0, (size_t)Storage.Size * sizeof(Storage.Data[0])); }
+ void Clear() { Storage.clear(); }
+ bool TestBit(int n) const { IM_ASSERT(n < (Storage.Size << 5)); return ImBitArrayTestBit(Storage.Data, n); }
+ void SetBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArraySetBit(Storage.Data, n); }
+ void ClearBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArrayClearBit(Storage.Data, n); }
+};
+
+// Helper: ImSpan<>
+// Pointing to a span of data we don't own.
+template<typename T>
+struct ImSpan
+{
+ T* Data;
+ T* DataEnd;
+
+ // Constructors, destructor
+ inline ImSpan() { Data = DataEnd = NULL; }
+ inline ImSpan(T* data, int size) { Data = data; DataEnd = data + size; }
+ inline ImSpan(T* data, T* data_end) { Data = data; DataEnd = data_end; }
+
+ inline void set(T* data, int size) { Data = data; DataEnd = data + size; }
+ inline void set(T* data, T* data_end) { Data = data; DataEnd = data_end; }
+ inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); }
+ inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); }
+ inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
+ inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
+
+ inline T* begin() { return Data; }
+ inline const T* begin() const { return Data; }
+ inline T* end() { return DataEnd; }
+ inline const T* end() const { return DataEnd; }
+
+ // Utilities
+ inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < DataEnd); const ptrdiff_t off = it - Data; return (int)off; }
+};
+
+// Helper: ImSpanAllocator<>
+// Facilitate storing multiple chunks into a single large block (the "arena")
+// - Usage: call Reserve() N times, allocate GetArenaSizeInBytes() worth, pass it to SetArenaBasePtr(), call GetSpan() N times to retrieve the aligned ranges.
+template<int CHUNKS>
+struct ImSpanAllocator
+{
+ char* BasePtr;
+ int CurrOff;
+ int CurrIdx;
+ int Offsets[CHUNKS];
+ int Sizes[CHUNKS];
+
+ ImSpanAllocator() { memset(this, 0, sizeof(*this)); }
+ inline void Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; }
+ inline int GetArenaSizeInBytes() { return CurrOff; }
+ inline void SetArenaBasePtr(void* base_ptr) { BasePtr = (char*)base_ptr; }
+ inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n]); }
+ inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n] + Sizes[n]); }
+ template<typename T>
+ inline void GetSpan(int n, ImSpan<T>* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); }
+};
+
+// Helper: ImPool<>
+// Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer,
+// Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object.
+typedef int ImPoolIdx;
+template<typename T>
+struct IMGUI_API ImPool
+{
+ ImVector<T> Buf; // Contiguous data
+ ImGuiStorage Map; // ID->Index
+ ImPoolIdx FreeIdx; // Next free idx to use
+ ImPoolIdx AliveCount; // Number of active/alive items (for display purpose)
+
+ ImPool() { FreeIdx = AliveCount = 0; }
+ ~ImPool() { Clear(); }
+ T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; }
+ T* GetByIndex(ImPoolIdx n) { return &Buf[n]; }
+ ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); }
+ T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); }
+ bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); }
+ void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = AliveCount = 0; }
+ T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); AliveCount++; return &Buf[idx]; }
+ void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); }
+ void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); AliveCount--; }
+ void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); }
+
+ // To iterate a ImPool: for (int n = 0; n < pool.GetMapSize(); n++) if (T* t = pool.TryGetMapData(n)) { ... }
+ // Can be avoided if you know .Remove() has never been called on the pool, or AliveCount == GetMapSize()
+ int GetAliveCount() const { return AliveCount; } // Number of active/alive items in the pool (for display purpose)
+ int GetBufSize() const { return Buf.Size; }
+ int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere
+ T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); }
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ int GetSize() { return GetMapSize(); } // For ImPlot: should use GetMapSize() from (IMGUI_VERSION_NUM >= 18304)
+#endif
+};
+
+// Helper: ImChunkStream<>
+// Build and iterate a contiguous stream of variable-sized structures.
+// This is used by Settings to store persistent data while reducing allocation count.
+// We store the chunk size first, and align the final size on 4 bytes boundaries.
+// The tedious/zealous amount of casting is to avoid -Wcast-align warnings.
+template<typename T>
+struct IMGUI_API ImChunkStream
+{
+ ImVector<char> Buf;
+
+ void clear() { Buf.clear(); }
+ bool empty() const { return Buf.Size == 0; }
+ int size() const { return Buf.Size; }
+ T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = IM_MEMALIGN(HDR_SZ + sz, 4u); int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); }
+ T* begin() { size_t HDR_SZ = 4; if (!Buf.Data) return NULL; return (T*)(void*)(Buf.Data + HDR_SZ); }
+ T* next_chunk(T* p) { size_t HDR_SZ = 4; IM_ASSERT(p >= begin() && p < end()); p = (T*)(void*)((char*)(void*)p + chunk_size(p)); if (p == (T*)(void*)((char*)end() + HDR_SZ)) return (T*)0; IM_ASSERT(p < end()); return p; }
+ int chunk_size(const T* p) { return ((const int*)p)[-1]; }
+ T* end() { return (T*)(void*)(Buf.Data + Buf.Size); }
+ int offset_from_ptr(const T* p) { IM_ASSERT(p >= begin() && p < end()); const ptrdiff_t off = (const char*)p - Buf.Data; return (int)off; }
+ T* ptr_from_offset(int off) { IM_ASSERT(off >= 4 && off < Buf.Size); return (T*)(void*)(Buf.Data + off); }
+ void swap(ImChunkStream<T>& rhs) { rhs.Buf.swap(Buf); }
+
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImDrawList support
+//-----------------------------------------------------------------------------
+
+// ImDrawList: Helper function to calculate a circle's segment count given its radius and a "maximum error" value.
+// Estimation of number of circle segment based on error is derived using method described in https://stackoverflow.com/a/2244088/15194693
+// Number of segments (N) is calculated using equation:
+// N = ceil ( pi / acos(1 - error / r) ) where r > 0, error <= r
+// Our equation is significantly simpler that one in the post thanks for choosing segment that is
+// perpendicular to X axis. Follow steps in the article from this starting condition and you will
+// will get this result.
+//
+// Rendering circles with an odd number of segments, while mathematically correct will produce
+// asymmetrical results on the raster grid. Therefore we're rounding N to next even number (7->8, 8->8, 9->10 etc.)
+//
+#define IM_ROUNDUP_TO_EVEN(_V) ((((_V) + 1) / 2) * 2)
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 4
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp(IM_ROUNDUP_TO_EVEN((int)ImCeil(IM_PI / ImAcos(1 - ImMin((_MAXERROR), (_RAD)) / (_RAD)))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX)
+
+// Raw equation from IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC rewritten for 'r' and 'error'.
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(_N,_MAXERROR) ((_MAXERROR) / (1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))))
+#define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_ERROR(_N,_RAD) ((1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))) / (_RAD))
+
+// ImDrawList: Lookup table size for adaptive arc drawing, cover full circle.
+#ifndef IM_DRAWLIST_ARCFAST_TABLE_SIZE
+#define IM_DRAWLIST_ARCFAST_TABLE_SIZE 48 // Number of samples in lookup table.
+#endif
+#define IM_DRAWLIST_ARCFAST_SAMPLE_MAX IM_DRAWLIST_ARCFAST_TABLE_SIZE // Sample index _PathArcToFastEx() for 360 angle.
+
+// Data shared between all ImDrawList instances
+// You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure.
+struct IMGUI_API ImDrawListSharedData
+{
+ ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
+ ImFont* Font; // Current/default font (optional, for simplified AddText overload)
+ float FontSize; // Current/default font size (optional, for simplified AddText overload)
+ float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
+ float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
+ ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
+ ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
+
+ // [Internal] Lookup tables
+ ImVec2 ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle.
+ float ArcFastRadiusCutoff; // Cutoff radius after which arc drawing will fallback to slower PathArcTo()
+ ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead)
+ const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas
+
+ ImDrawListSharedData();
+ void SetCircleTessellationMaxError(float max_error);
+};
+
+struct ImDrawDataBuilder
+{
+ ImVector<ImDrawList*> Layers[2]; // Global layers for: regular, tooltip
+
+ void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); }
+ void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); }
+ int GetDrawListCount() const { int count = 0; for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) count += Layers[n].Size; return count; }
+ IMGUI_API void FlattenIntoSingleLayer();
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Widgets support: flags, enums, data structures
+//-----------------------------------------------------------------------------
+
+// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().
+// This is going to be exposed in imgui.h when stabilized enough.
+enum ImGuiItemFlags_
+{
+ ImGuiItemFlags_None = 0,
+ ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing (FIXME: should merge with _NoNav)
+ ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings.
+ ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211
+ ImGuiItemFlags_NoNav = 1 << 3, // false // Disable keyboard/gamepad directional navigation (FIXME: should merge with _NoTabStop)
+ ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items)
+ ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window
+ ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
+ ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
+ ImGuiItemFlags_Inputable = 1 << 8 // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature.
+};
+
+// Storage for LastItem data
+enum ImGuiItemStatusFlags_
+{
+ ImGuiItemStatusFlags_None = 0,
+ ImGuiItemStatusFlags_HoveredRect = 1 << 0, // Mouse position is within item rectangle (does NOT mean that the window is in correct z-order and can be hovered!, this is only one part of the most-common IsItemHovered test)
+ ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // g.LastItemData.DisplayRect is valid
+ ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
+ ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected", only state changes, in order to easily handle clipping with less issues.
+ ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state.
+ ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
+ ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
+ ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing.
+ ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8 // Set when the Focusable item just got focused by Tabbing (FIXME: to be removed soon)
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ , // [imgui_tests only]
+ ImGuiItemStatusFlags_Openable = 1 << 20, //
+ ImGuiItemStatusFlags_Opened = 1 << 21, //
+ ImGuiItemStatusFlags_Checkable = 1 << 22, //
+ ImGuiItemStatusFlags_Checked = 1 << 23 //
+#endif
+};
+
+// Extend ImGuiInputTextFlags_
+enum ImGuiInputTextFlagsPrivate_
+{
+ // [Internal]
+ ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
+ ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data
+ ImGuiInputTextFlags_MergedItem = 1 << 28 // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
+};
+
+// Extend ImGuiButtonFlags_
+enum ImGuiButtonFlagsPrivate_
+{
+ ImGuiButtonFlags_PressedOnClick = 1 << 4, // return true on click (mouse down event)
+ ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, // [Default] return true on click + release on same item <-- this is what the majority of Button are using
+ ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 6, // return true on click + release even if the release event is not done while hovering the item
+ ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release)
+ ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release)
+ ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
+ ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat
+ ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
+ ImGuiButtonFlags_AllowItemOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap()
+ ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED]
+ //ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled
+ ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
+ ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held
+ ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only)
+ ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated
+ ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item
+ ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold,
+ ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease
+};
+
+// Extend ImGuiComboFlags_
+enum ImGuiComboFlagsPrivate_
+{
+ ImGuiComboFlags_CustomPreview = 1 << 20 // enable BeginComboPreview()
+};
+
+// Extend ImGuiSliderFlags_
+enum ImGuiSliderFlagsPrivate_
+{
+ ImGuiSliderFlags_Vertical = 1 << 20, // Should this slider be orientated vertically?
+ ImGuiSliderFlags_ReadOnly = 1 << 21
+};
+
+// Extend ImGuiSelectableFlags_
+enum ImGuiSelectableFlagsPrivate_
+{
+ // NB: need to be in sync with last value of ImGuiSelectableFlags_
+ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20,
+ ImGuiSelectableFlags_SelectOnNav = 1 << 21, // (WIP) Auto-select when moved into. This is not exposed in public API as to handle multi-select and modifiers we will need user to explicitly control focus scope. May be replaced with a BeginSelection() API.
+ ImGuiSelectableFlags_SelectOnClick = 1 << 22, // Override button behavior to react on Click (default is Click+Release)
+ ImGuiSelectableFlags_SelectOnRelease = 1 << 23, // Override button behavior to react on Release (default is Click+Release)
+ ImGuiSelectableFlags_SpanAvailWidth = 1 << 24, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus)
+ ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 25, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow.
+ ImGuiSelectableFlags_SetNavIdOnHover = 1 << 26, // Set Nav/Focus ID on mouse hover (used by MenuItem)
+ ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 27 // Disable padding each side with ItemSpacing * 0.5f
+};
+
+// Extend ImGuiTreeNodeFlags_
+enum ImGuiTreeNodeFlagsPrivate_
+{
+ ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20
+};
+
+enum ImGuiSeparatorFlags_
+{
+ ImGuiSeparatorFlags_None = 0,
+ ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
+ ImGuiSeparatorFlags_Vertical = 1 << 1,
+ ImGuiSeparatorFlags_SpanAllColumns = 1 << 2
+};
+
+enum ImGuiTextFlags_
+{
+ ImGuiTextFlags_None = 0,
+ ImGuiTextFlags_NoWidthForLargeClippedText = 1 << 0
+};
+
+enum ImGuiTooltipFlags_
+{
+ ImGuiTooltipFlags_None = 0,
+ ImGuiTooltipFlags_OverridePreviousTooltip = 1 << 0 // Override will clear/ignore previously submitted tooltip (defaults to append)
+};
+
+// FIXME: this is in development, not exposed/functional as a generic feature yet.
+// Horizontal/Vertical enums are fixed to 0/1 so they may be used to index ImVec2
+enum ImGuiLayoutType_
+{
+ ImGuiLayoutType_Horizontal = 0,
+ ImGuiLayoutType_Vertical = 1
+};
+
+enum ImGuiLogType
+{
+ ImGuiLogType_None = 0,
+ ImGuiLogType_TTY,
+ ImGuiLogType_File,
+ ImGuiLogType_Buffer,
+ ImGuiLogType_Clipboard
+};
+
+// X/Y enums are fixed to 0/1 so they may be used to index ImVec2
+enum ImGuiAxis
+{
+ ImGuiAxis_None = -1,
+ ImGuiAxis_X = 0,
+ ImGuiAxis_Y = 1
+};
+
+enum ImGuiPlotType
+{
+ ImGuiPlotType_Lines,
+ ImGuiPlotType_Histogram
+};
+
+enum ImGuiInputSource
+{
+ ImGuiInputSource_None = 0,
+ ImGuiInputSource_Mouse,
+ ImGuiInputSource_Keyboard,
+ ImGuiInputSource_Gamepad,
+ ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
+ ImGuiInputSource_Clipboard, // Currently only used by InputText()
+ ImGuiInputSource_COUNT
+};
+
+// FIXME-NAV: Clarify/expose various repeat delay/rate
+enum ImGuiInputReadMode
+{
+ ImGuiInputReadMode_Down,
+ ImGuiInputReadMode_Pressed,
+ ImGuiInputReadMode_Released,
+ ImGuiInputReadMode_Repeat,
+ ImGuiInputReadMode_RepeatSlow,
+ ImGuiInputReadMode_RepeatFast
+};
+
+enum ImGuiPopupPositionPolicy
+{
+ ImGuiPopupPositionPolicy_Default,
+ ImGuiPopupPositionPolicy_ComboBox,
+ ImGuiPopupPositionPolicy_Tooltip
+};
+
+struct ImGuiDataTypeTempStorage
+{
+ ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
+};
+
+// Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo().
+struct ImGuiDataTypeInfo
+{
+ size_t Size; // Size in bytes
+ const char* Name; // Short descriptive name for the type, for debugging
+ const char* PrintFmt; // Default printf format for the type
+ const char* ScanFmt; // Default scanf format for the type
+};
+
+// Extend ImGuiDataType_
+enum ImGuiDataTypePrivate_
+{
+ ImGuiDataType_String = ImGuiDataType_COUNT + 1,
+ ImGuiDataType_Pointer,
+ ImGuiDataType_ID
+};
+
+// Stacked color modifier, backup of modified data so we can restore it
+struct ImGuiColorMod
+{
+ ImGuiCol Col;
+ ImVec4 BackupValue;
+};
+
+// Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable.
+struct ImGuiStyleMod
+{
+ ImGuiStyleVar VarIdx;
+ union { int BackupInt[2]; float BackupFloat[2]; };
+ ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; }
+ ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; }
+ ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; }
+};
+
+// Storage data for BeginComboPreview()/EndComboPreview()
+struct IMGUI_API ImGuiComboPreviewData
+{
+ ImRect PreviewRect;
+ ImVec2 BackupCursorPos;
+ ImVec2 BackupCursorMaxPos;
+ ImVec2 BackupCursorPosPrevLine;
+ float BackupPrevLineTextBaseOffset;
+ ImGuiLayoutType BackupLayout;
+
+ ImGuiComboPreviewData() { memset(this, 0, sizeof(*this)); }
+};
+
+// Stacked storage data for BeginGroup()/EndGroup()
+struct IMGUI_API ImGuiGroupData
+{
+ ImGuiID WindowID;
+ ImVec2 BackupCursorPos;
+ ImVec2 BackupCursorMaxPos;
+ ImVec1 BackupIndent;
+ ImVec1 BackupGroupOffset;
+ ImVec2 BackupCurrLineSize;
+ float BackupCurrLineTextBaseOffset;
+ ImGuiID BackupActiveIdIsAlive;
+ bool BackupActiveIdPreviousFrameIsAlive;
+ bool BackupHoveredIdIsAlive;
+ bool EmitItem;
+};
+
+// Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper.
+struct IMGUI_API ImGuiMenuColumns
+{
+ ImU32 TotalWidth;
+ ImU32 NextTotalWidth;
+ ImU16 Spacing;
+ ImU16 OffsetIcon; // Always zero for now
+ ImU16 OffsetLabel; // Offsets are locked in Update()
+ ImU16 OffsetShortcut;
+ ImU16 OffsetMark;
+ ImU16 Widths[4]; // Width of: Icon, Label, Shortcut, Mark (accumulators for current frame)
+
+ ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); }
+ void Update(float spacing, bool window_reappearing);
+ float DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark);
+ void CalcNextTotalWidth(bool update_offsets);
+};
+
+// Internal state of the currently focused/edited text input box
+// For a given item ID, access with ImGui::GetInputTextState()
+struct IMGUI_API ImGuiInputTextState
+{
+ ImGuiID ID; // widget id owning the text state
+ int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not.
+ ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
+ ImVector<char> TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity.
+ ImVector<char> InitialTextA; // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
+ bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument)
+ int BufCapacityA; // end-user buffer capacity
+ float ScrollX; // horizontal scrolling/offset
+ ImStb::STB_TexteditState Stb; // state for stb_textedit.h
+ float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately
+ bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
+ bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
+ bool Edited; // edited this frame
+ ImGuiInputTextFlags Flags; // copy of InputText() flags
+
+ ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
+ void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
+ void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
+ int GetUndoAvailCount() const { return Stb.undostate.undo_point; }
+ int GetRedoAvailCount() const { return STB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; }
+ void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
+
+ // Cursor & Selection
+ void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking
+ void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); }
+ bool HasSelection() const { return Stb.select_start != Stb.select_end; }
+ void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; }
+ int GetCursorPos() const { return Stb.cursor; }
+ int GetSelectionStart() const { return Stb.select_start; }
+ int GetSelectionEnd() const { return Stb.select_end; }
+ void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; }
+};
+
+// Storage for current popup stack
+struct ImGuiPopupData
+{
+ ImGuiID PopupId; // Set on OpenPopup()
+ ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
+ ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup
+ int OpenFrameCount; // Set on OpenPopup()
+ ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
+ ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
+ ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
+
+ ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; }
+};
+
+enum ImGuiNextWindowDataFlags_
+{
+ ImGuiNextWindowDataFlags_None = 0,
+ ImGuiNextWindowDataFlags_HasPos = 1 << 0,
+ ImGuiNextWindowDataFlags_HasSize = 1 << 1,
+ ImGuiNextWindowDataFlags_HasContentSize = 1 << 2,
+ ImGuiNextWindowDataFlags_HasCollapsed = 1 << 3,
+ ImGuiNextWindowDataFlags_HasSizeConstraint = 1 << 4,
+ ImGuiNextWindowDataFlags_HasFocus = 1 << 5,
+ ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6,
+ ImGuiNextWindowDataFlags_HasScroll = 1 << 7
+};
+
+// Storage for SetNexWindow** functions
+struct ImGuiNextWindowData
+{
+ ImGuiNextWindowDataFlags Flags;
+ ImGuiCond PosCond;
+ ImGuiCond SizeCond;
+ ImGuiCond CollapsedCond;
+ ImVec2 PosVal;
+ ImVec2 PosPivotVal;
+ ImVec2 SizeVal;
+ ImVec2 ContentSizeVal;
+ ImVec2 ScrollVal;
+ bool CollapsedVal;
+ ImRect SizeConstraintRect;
+ ImGuiSizeCallback SizeCallback;
+ void* SizeCallbackUserData;
+ float BgAlphaVal; // Override background alpha
+ ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?)
+
+ ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); }
+ inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; }
+};
+
+enum ImGuiNextItemDataFlags_
+{
+ ImGuiNextItemDataFlags_None = 0,
+ ImGuiNextItemDataFlags_HasWidth = 1 << 0,
+ ImGuiNextItemDataFlags_HasOpen = 1 << 1
+};
+
+struct ImGuiNextItemData
+{
+ ImGuiNextItemDataFlags Flags;
+ float Width; // Set by SetNextItemWidth()
+ ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging)
+ ImGuiCond OpenCond;
+ bool OpenVal; // Set by SetNextItemOpen()
+
+ ImGuiNextItemData() { memset(this, 0, sizeof(*this)); }
+ inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; } // Also cleared manually by ItemAdd()!
+};
+
+// Status storage for the last submitted item
+struct ImGuiLastItemData
+{
+ ImGuiID ID;
+ ImGuiItemFlags InFlags; // See ImGuiItemFlags_
+ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_
+ ImRect Rect; // Full rectangle
+ ImRect NavRect; // Navigation scoring rectangle (not displayed)
+ ImRect DisplayRect; // Display rectangle (only if ImGuiItemStatusFlags_HasDisplayRect is set)
+
+ ImGuiLastItemData() { memset(this, 0, sizeof(*this)); }
+};
+
+struct IMGUI_API ImGuiStackSizes
+{
+ short SizeOfIDStack;
+ short SizeOfColorStack;
+ short SizeOfStyleVarStack;
+ short SizeOfFontStack;
+ short SizeOfFocusScopeStack;
+ short SizeOfGroupStack;
+ short SizeOfItemFlagsStack;
+ short SizeOfBeginPopupStack;
+ short SizeOfDisabledStack;
+
+ ImGuiStackSizes() { memset(this, 0, sizeof(*this)); }
+ void SetToCurrentState();
+ void CompareWithCurrentState();
+};
+
+// Data saved for each window pushed into the stack
+struct ImGuiWindowStackData
+{
+ ImGuiWindow* Window;
+ ImGuiLastItemData ParentLastItemDataBackup;
+ ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting
+};
+
+struct ImGuiShrinkWidthItem
+{
+ int Index;
+ float Width;
+};
+
+struct ImGuiPtrOrIndex
+{
+ void* Ptr; // Either field can be set, not both. e.g. Dock node tab bars are loose while BeginTabBar() ones are in a pool.
+ int Index; // Usually index in a main pool.
+
+ ImGuiPtrOrIndex(void* ptr) { Ptr = ptr; Index = -1; }
+ ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Clipper support
+//-----------------------------------------------------------------------------
+
+struct ImGuiListClipperRange
+{
+ int Min;
+ int Max;
+ bool PosToIndexConvert; // Begin/End are absolute position (will be converted to indices later)
+ ImS8 PosToIndexOffsetMin; // Add to Min after converting to indices
+ ImS8 PosToIndexOffsetMax; // Add to Min after converting to indices
+
+ static ImGuiListClipperRange FromIndices(int min, int max) { ImGuiListClipperRange r = { min, max, false, 0, 0 }; return r; }
+ static ImGuiListClipperRange FromPositions(float y1, float y2, int off_min, int off_max) { ImGuiListClipperRange r = { (int)y1, (int)y2, true, (ImS8)off_min, (ImS8)off_max }; return r; }
+};
+
+// Temporary clipper data, buffers shared/reused between instances
+struct ImGuiListClipperData
+{
+ ImGuiListClipper* ListClipper;
+ int StepNo;
+ int ItemsFrozen;
+ ImVector<ImGuiListClipperRange> Ranges;
+
+ ImGuiListClipperData() { memset(this, 0, sizeof(*this)); }
+ void Reset(ImGuiListClipper* clipper) { ListClipper = clipper; StepNo = ItemsFrozen = 0; Ranges.resize(0); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Navigation support
+//-----------------------------------------------------------------------------
+
+enum ImGuiActivateFlags_
+{
+ ImGuiActivateFlags_None = 0,
+ ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default if keyboard is available.
+ ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default if keyboard is not available.
+ ImGuiActivateFlags_TryToPreserveState = 1 << 2 // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
+};
+
+// Early work-in-progress API for ScrollToItem()
+enum ImGuiScrollFlags_
+{
+ ImGuiScrollFlags_None = 0,
+ ImGuiScrollFlags_KeepVisibleEdgeX = 1 << 0, // If item is not visible: scroll as little as possible on X axis to bring item back into view [default for X axis]
+ ImGuiScrollFlags_KeepVisibleEdgeY = 1 << 1, // If item is not visible: scroll as little as possible on Y axis to bring item back into view [default for Y axis for windows that are already visible]
+ ImGuiScrollFlags_KeepVisibleCenterX = 1 << 2, // If item is not visible: scroll to make the item centered on X axis [rarely used]
+ ImGuiScrollFlags_KeepVisibleCenterY = 1 << 3, // If item is not visible: scroll to make the item centered on Y axis
+ ImGuiScrollFlags_AlwaysCenterX = 1 << 4, // Always center the result item on X axis [rarely used]
+ ImGuiScrollFlags_AlwaysCenterY = 1 << 5, // Always center the result item on Y axis [default for Y axis for appearing window)
+ ImGuiScrollFlags_NoScrollParent = 1 << 6, // Disable forwarding scrolling to parent window if required to keep item/rect visible (only scroll window the function was applied to).
+ ImGuiScrollFlags_MaskX_ = ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleCenterX | ImGuiScrollFlags_AlwaysCenterX,
+ ImGuiScrollFlags_MaskY_ = ImGuiScrollFlags_KeepVisibleEdgeY | ImGuiScrollFlags_KeepVisibleCenterY | ImGuiScrollFlags_AlwaysCenterY
+};
+
+enum ImGuiNavHighlightFlags_
+{
+ ImGuiNavHighlightFlags_None = 0,
+ ImGuiNavHighlightFlags_TypeDefault = 1 << 0,
+ ImGuiNavHighlightFlags_TypeThin = 1 << 1,
+ ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse.
+ ImGuiNavHighlightFlags_NoRounding = 1 << 3
+};
+
+enum ImGuiNavDirSourceFlags_
+{
+ ImGuiNavDirSourceFlags_None = 0,
+ ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), faciliate use of some functions before we can unify nav and keys
+ ImGuiNavDirSourceFlags_Keyboard = 1 << 1,
+ ImGuiNavDirSourceFlags_PadDPad = 1 << 2,
+ ImGuiNavDirSourceFlags_PadLStick = 1 << 3
+};
+
+enum ImGuiNavMoveFlags_
+{
+ ImGuiNavMoveFlags_None = 0,
+ ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side
+ ImGuiNavMoveFlags_LoopY = 1 << 1,
+ ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left)
+ ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness
+ ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place)
+ ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown)
+ ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
+ ImGuiNavMoveFlags_Forwarded = 1 << 7,
+ ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result
+ ImGuiNavMoveFlags_FocusApi = 1 << 9,
+ ImGuiNavMoveFlags_Tabbing = 1 << 10, // == Focus + Activate if item is Inputable + DontChangeNavHighlight
+ ImGuiNavMoveFlags_Activate = 1 << 11,
+ ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 12 // Do not alter the visible state of keyboard vs mouse nav highlight
+};
+
+enum ImGuiNavLayer
+{
+ ImGuiNavLayer_Main = 0, // Main scrolling layer
+ ImGuiNavLayer_Menu = 1, // Menu layer (access with Alt/ImGuiNavInput_Menu)
+ ImGuiNavLayer_COUNT
+};
+
+struct ImGuiNavItemData
+{
+ ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window)
+ ImGuiID ID; // Init,Move // Best candidate item ID
+ ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID
+ ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space
+ ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags
+ float DistBox; // Move // Best candidate box distance to current NavId
+ float DistCenter; // Move // Best candidate center distance to current NavId
+ float DistAxial; // Move // Best candidate axial distance to current NavId
+
+ ImGuiNavItemData() { Clear(); }
+ void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Columns support
+//-----------------------------------------------------------------------------
+
+// Flags for internal's BeginColumns(). Prefix using BeginTable() nowadays!
+enum ImGuiOldColumnFlags_
+{
+ ImGuiOldColumnFlags_None = 0,
+ ImGuiOldColumnFlags_NoBorder = 1 << 0, // Disable column dividers
+ ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers
+ ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns
+ ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window
+ ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove.
+
+ // Obsolete names (will be removed)
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ , ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None,
+ ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder,
+ ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize,
+ ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths,
+ ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow,
+ ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize
+#endif
+};
+
+struct ImGuiOldColumnData
+{
+ float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right)
+ float OffsetNormBeforeResize;
+ ImGuiOldColumnFlags Flags; // Not exposed
+ ImRect ClipRect;
+
+ ImGuiOldColumnData() { memset(this, 0, sizeof(*this)); }
+};
+
+struct ImGuiOldColumns
+{
+ ImGuiID ID;
+ ImGuiOldColumnFlags Flags;
+ bool IsFirstFrame;
+ bool IsBeingResized;
+ int Current;
+ int Count;
+ float OffMinX, OffMaxX; // Offsets from HostWorkRect.Min.x
+ float LineMinY, LineMaxY;
+ float HostCursorPosY; // Backup of CursorPos at the time of BeginColumns()
+ float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns()
+ ImRect HostInitialClipRect; // Backup of ClipRect at the time of BeginColumns()
+ ImRect HostBackupClipRect; // Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground()
+ ImRect HostBackupParentWorkRect;//Backup of WorkRect at the time of BeginColumns()
+ ImVector<ImGuiOldColumnData> Columns;
+ ImDrawListSplitter Splitter;
+
+ ImGuiOldColumns() { memset(this, 0, sizeof(*this)); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Multi-select support
+//-----------------------------------------------------------------------------
+
+#ifdef IMGUI_HAS_MULTI_SELECT
+// <this is filled in 'range_select' branch>
+#endif // #ifdef IMGUI_HAS_MULTI_SELECT
+
+//-----------------------------------------------------------------------------
+// [SECTION] Docking support
+//-----------------------------------------------------------------------------
+
+#ifdef IMGUI_HAS_DOCK
+// <this is filled in 'docking' branch>
+#endif // #ifdef IMGUI_HAS_DOCK
+
+//-----------------------------------------------------------------------------
+// [SECTION] Viewport support
+//-----------------------------------------------------------------------------
+
+// ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!)
+// Every instance of ImGuiViewport is in fact a ImGuiViewportP.
+struct ImGuiViewportP : public ImGuiViewport
+{
+ int DrawListsLastFrame[2]; // Last frame number the background (0) and foreground (1) draw lists were used
+ ImDrawList* DrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
+ ImDrawData DrawDataP;
+ ImDrawDataBuilder DrawDataBuilder;
+
+ ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!)
+ ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height).
+ ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f.
+ ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f.
+
+ ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; }
+ ~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); }
+
+ // Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect)
+ ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_min.y); }
+ ImVec2 CalcWorkRectSize(const ImVec2& off_min, const ImVec2& off_max) const { return ImVec2(ImMax(0.0f, Size.x - off_min.x + off_max.x), ImMax(0.0f, Size.y - off_min.y + off_max.y)); }
+ void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields
+
+ // Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry)
+ ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
+ ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
+ ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkOffsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkOffsetMin, BuildWorkOffsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Settings support
+//-----------------------------------------------------------------------------
+
+// Windows data saved in imgui.ini file
+// Because we never destroy or rename ImGuiWindowSettings, we can store the names in a separate buffer easily.
+// (this is designed to be stored in a ImChunkStream buffer, with the variable-length Name following our structure)
+struct ImGuiWindowSettings
+{
+ ImGuiID ID;
+ ImVec2ih Pos;
+ ImVec2ih Size;
+ bool Collapsed;
+ bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
+
+ ImGuiWindowSettings() { memset(this, 0, sizeof(*this)); }
+ char* GetName() { return (char*)(this + 1); }
+};
+
+struct ImGuiSettingsHandler
+{
+ const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
+ ImGuiID TypeHash; // == ImHashStr(TypeName)
+ void (*ClearAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Clear all settings data
+ void (*ReadInitFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called before reading (in registration order)
+ void* (*ReadOpenFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); // Read: Called when entering into a new ini entry e.g. "[Window][Name]"
+ void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry
+ void (*ApplyAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called after reading (in registration order)
+ void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf'
+ void* UserData;
+
+ ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Metrics, Debug Tools
+//-----------------------------------------------------------------------------
+
+struct ImGuiMetricsConfig
+{
+ bool ShowStackTool;
+ bool ShowWindowsRects;
+ bool ShowWindowsBeginOrder;
+ bool ShowTablesRects;
+ bool ShowDrawCmdMesh;
+ bool ShowDrawCmdBoundingBoxes;
+ int ShowWindowsRectsType;
+ int ShowTablesRectsType;
+
+ ImGuiMetricsConfig()
+ {
+ ShowStackTool = false;
+ ShowWindowsRects = false;
+ ShowWindowsBeginOrder = false;
+ ShowTablesRects = false;
+ ShowDrawCmdMesh = true;
+ ShowDrawCmdBoundingBoxes = true;
+ ShowWindowsRectsType = -1;
+ ShowTablesRectsType = -1;
+ }
+};
+
+struct ImGuiStackLevelInfo
+{
+ ImGuiID ID;
+ ImS8 QueryFrameCount; // >= 1: Query in progress
+ bool QuerySuccess; // Obtained result from DebugHookIdInfo()
+ char Desc[58]; // Arbitrarily sized buffer to hold a result (FIXME: could replace Results[] with a chunk stream?)
+
+ ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); }
+};
+
+// State for Stack tool queries
+struct ImGuiStackTool
+{
+ int LastActiveFrame;
+ int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level
+ ImGuiID QueryId; // ID to query details for
+ ImVector<ImGuiStackLevelInfo> Results;
+
+ ImGuiStackTool() { memset(this, 0, sizeof(*this)); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Generic context hooks
+//-----------------------------------------------------------------------------
+
+typedef void (*ImGuiContextHookCallback)(ImGuiContext* ctx, ImGuiContextHook* hook);
+enum ImGuiContextHookType { ImGuiContextHookType_NewFramePre, ImGuiContextHookType_NewFramePost, ImGuiContextHookType_EndFramePre, ImGuiContextHookType_EndFramePost, ImGuiContextHookType_RenderPre, ImGuiContextHookType_RenderPost, ImGuiContextHookType_Shutdown, ImGuiContextHookType_PendingRemoval_ };
+
+struct ImGuiContextHook
+{
+ ImGuiID HookId; // A unique ID assigned by AddContextHook()
+ ImGuiContextHookType Type;
+ ImGuiID Owner;
+ ImGuiContextHookCallback Callback;
+ void* UserData;
+
+ ImGuiContextHook() { memset(this, 0, sizeof(*this)); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiContext (main imgui context)
+//-----------------------------------------------------------------------------
+
+struct ImGuiContext
+{
+ bool Initialized;
+ bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it.
+ ImGuiIO IO;
+ ImGuiStyle Style;
+ ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
+ float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
+ float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
+ ImDrawListSharedData DrawListSharedData;
+ double Time;
+ int FrameCount;
+ int FrameCountEnded;
+ int FrameCountRendered;
+ bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame()
+ bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed
+ bool WithinEndChild; // Set within EndChild()
+ bool GcCompactAll; // Request full GC
+ bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log()
+ void* TestEngine; // Test engine user data
+
+ // Windows state
+ ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
+ ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front.
+ ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child
+ ImVector<ImGuiWindowStackData> CurrentWindowStack;
+ ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
+ int WindowsActiveCount; // Number of unique windows submitted by frame
+ ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING)
+ ImGuiWindow* CurrentWindow; // Window being drawn into
+ ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
+ ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
+ ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow.
+ ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
+ ImVec2 WheelingWindowRefMousePos;
+ float WheelingWindowTimer;
+
+ // Item/widgets state and tracking information
+ ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line]
+ ImGuiID HoveredId; // Hovered widget, filled during the frame
+ ImGuiID HoveredIdPreviousFrame;
+ bool HoveredIdAllowOverlap;
+ bool HoveredIdUsingMouseWheel; // Hovered widget will use mouse wheel. Blocks scrolling the underlying window.
+ bool HoveredIdPreviousFrameUsingMouseWheel;
+ bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
+ float HoveredIdTimer; // Measure contiguous hovering time
+ float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
+ ImGuiID ActiveId; // Active widget
+ ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
+ float ActiveIdTimer;
+ bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
+ bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
+ bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused.
+ bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
+ bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
+ bool ActiveIdHasBeenEditedThisFrame;
+ bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window.
+ ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
+ ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs.
+ ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array.
+ ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior)
+ ImGuiWindow* ActiveIdWindow;
+ ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard)
+ int ActiveIdMouseButton;
+ ImGuiID ActiveIdPreviousFrame;
+ bool ActiveIdPreviousFrameIsAlive;
+ bool ActiveIdPreviousFrameHasBeenEditedBefore;
+ ImGuiWindow* ActiveIdPreviousFrameWindow;
+ ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
+ float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
+
+ // Next window/item data
+ ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
+ ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions
+ ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd)
+ ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions
+
+ // Shared stacks
+ ImVector<ImGuiColorMod> ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin()
+ ImVector<ImGuiStyleMod> StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin()
+ ImVector<ImFont*> FontStack; // Stack for PushFont()/PopFont() - inherited by Begin()
+ ImVector<ImGuiID> FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - not inherited by Begin(), unless child window
+ ImVector<ImGuiItemFlags>ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin()
+ ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
+ ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
+ ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
+
+ // Viewports
+ ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
+
+ // Gamepad/keyboard Navigation
+ ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow'
+ ImGuiID NavId; // Focused item for navigation
+ ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set)
+ ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem()
+ ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0
+ ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0
+ ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
+ ImGuiActivateFlags NavActivateFlags;
+ ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
+ ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
+ ImGuiKeyModFlags NavJustMovedToKeyMods;
+ ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
+ ImGuiActivateFlags NavNextActivateFlags;
+ ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
+ ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
+ bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
+ bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
+ bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
+ bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again.
+
+ // Navigation: Init & Move Requests
+ bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd()
+ bool NavInitRequest; // Init request for appearing window to select first item
+ bool NavInitRequestFromMove;
+ ImGuiID NavInitResultId; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called)
+ ImRect NavInitResultRectRel; // Init request result rectangle (relative to parent window)
+ bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame()
+ bool NavMoveScoringItems; // Move request submitted, still scoring incoming items
+ bool NavMoveForwardToNextFrame;
+ ImGuiNavMoveFlags NavMoveFlags;
+ ImGuiScrollFlags NavMoveScrollFlags;
+ ImGuiKeyModFlags NavMoveKeyMods;
+ ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down)
+ ImGuiDir NavMoveDirForDebug;
+ ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
+ ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
+ ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted
+ int NavScoringDebugCount; // Metrics for debugging
+ int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id
+ int NavTabbingCounter; // >0 when counting items for tabbing
+ ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
+ ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
+ ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
+ ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy
+
+ // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
+ ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
+ ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it.
+ ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents
+ float NavWindowingTimer;
+ float NavWindowingHighlightAlpha;
+ bool NavWindowingToggleLayer;
+
+ // Render
+ float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
+ ImGuiMouseCursor MouseCursor;
+
+ // Drag and Drop
+ bool DragDropActive;
+ bool DragDropWithinSource; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag source.
+ bool DragDropWithinTarget; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag target.
+ ImGuiDragDropFlags DragDropSourceFlags;
+ int DragDropSourceFrameCount;
+ int DragDropMouseButton;
+ ImGuiPayload DragDropPayload;
+ ImRect DragDropTargetRect; // Store rectangle of current target candidate (we favor small targets when overlapping)
+ ImGuiID DragDropTargetId;
+ ImGuiDragDropFlags DragDropAcceptFlags;
+ float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface)
+ ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload)
+ ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets)
+ int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source
+ ImGuiID DragDropHoldJustPressedId; // Set when holding a payload just made ButtonBehavior() return a press.
+ ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly, ImGuiPayload only holds pointer+size
+ unsigned char DragDropPayloadBufLocal[16]; // Local buffer for small payloads
+
+ // Clipper
+ int ClipperTempDataStacked;
+ ImVector<ImGuiListClipperData> ClipperTempData;
+
+ // Table
+ ImGuiTable* CurrentTable;
+ int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size)
+ ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting)
+ ImPool<ImGuiTable> Tables; // Persistent table data
+ ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC)
+ ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer;
+
+ // Tab bars
+ ImGuiTabBar* CurrentTabBar;
+ ImPool<ImGuiTabBar> TabBars;
+ ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
+ ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
+
+ // Widget state
+ ImVec2 MouseLastValidPos;
+ ImGuiInputTextState InputTextState;
+ ImFont InputTextPasswordFont;
+ ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc.
+ ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
+ float ColorEditLastHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips
+ float ColorEditLastSat; // Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips
+ ImU32 ColorEditLastColor; // RGB value with alpha set to 0.
+ ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker.
+ ImGuiComboPreviewData ComboPreviewData;
+ float SliderCurrentAccum; // Accumulated slider delta when using navigation controls.
+ bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it?
+ bool DragCurrentAccumDirty;
+ float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
+ float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
+ float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
+ float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled()
+ short DisabledStackSize;
+ short TooltipOverrideCount;
+ float TooltipSlowDelay; // Time before slow tooltips appears (FIXME: This is temporary until we merge in tooltip timer+priority work)
+ ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined
+ ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once
+
+ // Platform support
+ ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor
+ ImVec2 PlatformImeLastPos;
+ char PlatformLocaleDecimalPoint; // '.' or *localeconv()->decimal_point
+
+ // Settings
+ bool SettingsLoaded;
+ float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero
+ ImGuiTextBuffer SettingsIniData; // In memory .ini settings
+ ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
+ ImChunkStream<ImGuiWindowSettings> SettingsWindows; // ImGuiWindow .ini settings entries
+ ImChunkStream<ImGuiTableSettings> SettingsTables; // ImGuiTable .ini settings entries
+ ImVector<ImGuiContextHook> Hooks; // Hooks for extensions (e.g. test engine)
+ ImGuiID HookIdNext; // Next available HookId
+
+ // Capture/Logging
+ bool LogEnabled; // Currently capturing
+ ImGuiLogType LogType; // Capture target
+ ImFileHandle LogFile; // If != NULL log to stdout/ file
+ ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
+ const char* LogNextPrefix;
+ const char* LogNextSuffix;
+ float LogLinePosY;
+ bool LogLineFirstItem;
+ int LogDepthRef;
+ int LogDepthToExpand;
+ int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call.
+
+ // Debug Tools
+ bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
+ ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID
+ ImGuiMetricsConfig DebugMetricsConfig;
+ ImGuiStackTool DebugStackTool;
+
+ // Misc
+ float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds.
+ int FramerateSecPerFrameIdx;
+ int FramerateSecPerFrameCount;
+ float FramerateSecPerFrameAccum;
+ int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags
+ int WantCaptureKeyboardNextFrame;
+ int WantTextInputNextFrame;
+ char TempBuffer[1024 * 3 + 1]; // Temporary text buffer
+
+ ImGuiContext(ImFontAtlas* shared_font_atlas)
+ {
+ Initialized = false;
+ FontAtlasOwnedByContext = shared_font_atlas ? false : true;
+ Font = NULL;
+ FontSize = FontBaseSize = 0.0f;
+ IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
+ Time = 0.0f;
+ FrameCount = 0;
+ FrameCountEnded = FrameCountRendered = -1;
+ WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false;
+ GcCompactAll = false;
+ TestEngineHookItems = false;
+ TestEngine = NULL;
+
+ WindowsActiveCount = 0;
+ CurrentWindow = NULL;
+ HoveredWindow = NULL;
+ HoveredWindowUnderMovingWindow = NULL;
+ MovingWindow = NULL;
+ WheelingWindow = NULL;
+ WheelingWindowTimer = 0.0f;
+
+ DebugHookIdInfo = 0;
+ HoveredId = HoveredIdPreviousFrame = 0;
+ HoveredIdAllowOverlap = false;
+ HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;
+ HoveredIdDisabled = false;
+ HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
+ ActiveId = 0;
+ ActiveIdIsAlive = 0;
+ ActiveIdTimer = 0.0f;
+ ActiveIdIsJustActivated = false;
+ ActiveIdAllowOverlap = false;
+ ActiveIdNoClearOnFocusLoss = false;
+ ActiveIdHasBeenPressedBefore = false;
+ ActiveIdHasBeenEditedBefore = false;
+ ActiveIdHasBeenEditedThisFrame = false;
+ ActiveIdUsingMouseWheel = false;
+ ActiveIdUsingNavDirMask = 0x00;
+ ActiveIdUsingNavInputMask = 0x00;
+ ActiveIdUsingKeyInputMask = 0x00;
+ ActiveIdClickOffset = ImVec2(-1, -1);
+ ActiveIdWindow = NULL;
+ ActiveIdSource = ImGuiInputSource_None;
+ ActiveIdMouseButton = -1;
+ ActiveIdPreviousFrame = 0;
+ ActiveIdPreviousFrameIsAlive = false;
+ ActiveIdPreviousFrameHasBeenEditedBefore = false;
+ ActiveIdPreviousFrameWindow = NULL;
+ LastActiveId = 0;
+ LastActiveIdTimer = 0.0f;
+
+ CurrentItemFlags = ImGuiItemFlags_None;
+
+ NavWindow = NULL;
+ NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
+ NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
+ NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
+ NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
+ NavInputSource = ImGuiInputSource_None;
+ NavLayer = ImGuiNavLayer_Main;
+ NavIdIsAlive = false;
+ NavMousePosDirty = false;
+ NavDisableHighlight = true;
+ NavDisableMouseHover = false;
+ NavAnyRequest = false;
+ NavInitRequest = false;
+ NavInitRequestFromMove = false;
+ NavInitResultId = 0;
+ NavMoveSubmitted = false;
+ NavMoveScoringItems = false;
+ NavMoveForwardToNextFrame = false;
+ NavMoveFlags = ImGuiNavMoveFlags_None;
+ NavMoveScrollFlags = ImGuiScrollFlags_None;
+ NavMoveKeyMods = ImGuiKeyModFlags_None;
+ NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
+ NavScoringDebugCount = 0;
+ NavTabbingDir = 0;
+ NavTabbingCounter = 0;
+
+ NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
+ NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
+ NavWindowingToggleLayer = false;
+
+ DimBgRatio = 0.0f;
+ MouseCursor = ImGuiMouseCursor_Arrow;
+
+ DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
+ DragDropSourceFlags = ImGuiDragDropFlags_None;
+ DragDropSourceFrameCount = -1;
+ DragDropMouseButton = -1;
+ DragDropTargetId = 0;
+ DragDropAcceptFlags = ImGuiDragDropFlags_None;
+ DragDropAcceptIdCurrRectSurface = 0.0f;
+ DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0;
+ DragDropAcceptFrameCount = -1;
+ DragDropHoldJustPressedId = 0;
+ memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
+
+ ClipperTempDataStacked = 0;
+
+ CurrentTable = NULL;
+ TablesTempDataStacked = 0;
+ CurrentTabBar = NULL;
+
+ TempInputId = 0;
+ ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
+ ColorEditLastHue = ColorEditLastSat = 0.0f;
+ ColorEditLastColor = 0;
+ SliderCurrentAccum = 0.0f;
+ SliderCurrentAccumDirty = false;
+ DragCurrentAccumDirty = false;
+ DragCurrentAccum = 0.0f;
+ DragSpeedDefaultRatio = 1.0f / 100.0f;
+ DisabledAlphaBackup = 0.0f;
+ DisabledStackSize = 0;
+ ScrollbarClickDeltaToGrabCenter = 0.0f;
+ TooltipOverrideCount = 0;
+ TooltipSlowDelay = 0.50f;
+
+ PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX);
+ PlatformLocaleDecimalPoint = '.';
+
+ SettingsLoaded = false;
+ SettingsDirtyTimer = 0.0f;
+ HookIdNext = 0;
+
+ LogEnabled = false;
+ LogType = ImGuiLogType_None;
+ LogNextPrefix = LogNextSuffix = NULL;
+ LogFile = NULL;
+ LogLinePosY = FLT_MAX;
+ LogLineFirstItem = false;
+ LogDepthRef = 0;
+ LogDepthToExpand = LogDepthToExpandDefault = 2;
+
+ DebugItemPickerActive = false;
+ DebugItemPickerBreakId = 0;
+
+ memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
+ FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
+ FramerateSecPerFrameAccum = 0.0f;
+ WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
+ memset(TempBuffer, 0, sizeof(TempBuffer));
+ }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGuiWindowTempData, ImGuiWindow
+//-----------------------------------------------------------------------------
+
+// Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow.
+// (That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered..)
+// (This doesn't need a constructor because we zero-clear it as part of ImGuiWindow and all frame-temporary data are setup on Begin)
+struct IMGUI_API ImGuiWindowTempData
+{
+ // Layout
+ ImVec2 CursorPos; // Current emitting position, in absolute coordinates.
+ ImVec2 CursorPosPrevLine;
+ ImVec2 CursorStartPos; // Initial position after Begin(), generally ~ window position + WindowPadding.
+ ImVec2 CursorMaxPos; // Used to implicitly calculate ContentSize at the beginning of next frame, for scrolling range and auto-resize. Always growing during the frame.
+ ImVec2 IdealMaxPos; // Used to implicitly calculate ContentSizeIdeal at the beginning of next frame, for auto-resize only. Always growing during the frame.
+ ImVec2 CurrLineSize;
+ ImVec2 PrevLineSize;
+ float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added).
+ float PrevLineTextBaseOffset;
+ ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
+ ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
+ ImVec1 GroupOffset;
+
+ // Keyboard/Gamepad navigation
+ ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
+ short NavLayersActiveMask; // Which layers have been written to (result from previous frame)
+ short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame)
+ ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending
+ bool NavHideHighlightOneFrame;
+ bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f)
+
+ // Miscellaneous
+ bool MenuBarAppending; // FIXME: Remove this
+ ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs.
+ ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement
+ int TreeDepth; // Current tree depth.
+ ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary.
+ ImVector<ImGuiWindow*> ChildWindows;
+ ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state)
+ ImGuiOldColumns* CurrentColumns; // Current columns set
+ int CurrentTableIdx; // Current table index (into g.Tables)
+ ImGuiLayoutType LayoutType;
+ ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
+
+ // Local parameters stacks
+ // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
+ float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window).
+ float TextWrapPos; // Current text wrap pos.
+ ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth)
+ ImVector<float> TextWrapPosStack; // Store text wrap pos to restore (attention: .back() is not == TextWrapPos)
+};
+
+// Storage for one window
+struct IMGUI_API ImGuiWindow
+{
+ char* Name; // Window name, owned by the window.
+ ImGuiID ID; // == ImHashStr(Name)
+ ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_
+ ImVec2 Pos; // Position (always rounded-up to nearest pixel)
+ ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
+ ImVec2 SizeFull; // Size when non collapsed
+ ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding.
+ ImVec2 ContentSizeIdeal;
+ ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize().
+ ImVec2 WindowPadding; // Window padding at the time of Begin().
+ float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc.
+ float WindowBorderSize; // Window border size at the time of Begin().
+ int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)!
+ ImGuiID MoveId; // == window->GetID("#MOVE")
+ ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window)
+ ImVec2 Scroll;
+ ImVec2 ScrollMax;
+ ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
+ ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
+ ImVec2 ScrollTargetEdgeSnapDist; // 0.0f = no snapping, >0.0f snapping threshold
+ ImVec2 ScrollbarSizes; // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar.
+ bool ScrollbarX, ScrollbarY; // Are scrollbars visible?
+ bool Active; // Set to true on Begin(), unless Collapsed
+ bool WasActive;
+ bool WriteAccessed; // Set to true when any widget access the current window
+ bool Collapsed; // Set when collapsing window to become only title-bar
+ bool WantCollapseToggle;
+ bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
+ bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
+ bool Hidden; // Do not display (== HiddenFrames*** > 0)
+ bool IsFallbackWindow; // Set on the "Debug##Default" window.
+ bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
+ signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
+ short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
+ short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
+ short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
+ short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
+ ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
+ ImS8 AutoFitFramesX, AutoFitFramesY;
+ ImS8 AutoFitChildAxises;
+ bool AutoFitOnlyGrows;
+ ImGuiDir AutoPosLastDirection;
+ ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames
+ ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size
+ ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only
+ ImS8 DisableInputsFrames; // Disable window interactions for N frames
+ ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use.
+ ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use.
+ ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use.
+ ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
+ ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0, 0) when positioning from top-left corner; ImVec2(0.5f, 0.5f) for centering; ImVec2(1, 1) for bottom right.
+
+ ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure)
+ ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
+
+ // The best way to understand what those rectangles are is to use the 'Metrics->Tools->Show Windows Rectangles' viewer.
+ // The main 'OuterRect', omitted as a field, is window->Rect().
+ ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window.
+ ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar)
+ ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect.
+ ImRect WorkRect; // Initially covers the whole scrolling region. Reduced by containers e.g columns/tables when active. Shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentRegionRect over time (from 1.71+ onward).
+ ImRect ParentWorkRect; // Backup of WorkRect before entering a container such as columns/tables. Used by e.g. SpanAllColumns functions to easily access. Stacked containers are responsible for maintaining this. // FIXME-WORKRECT: Could be a stack?
+ ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back().
+ ImRect ContentRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on.
+ ImVec2ih HitTestHoleSize; // Define an optional rectangular hole where mouse will pass-through the window.
+ ImVec2ih HitTestHoleOffset;
+
+ int LastFrameActive; // Last frame number the window was Active.
+ float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there)
+ float ItemWidthDefault;
+ ImGuiStorage StateStorage;
+ ImVector<ImGuiOldColumns> ColumnsStorage;
+ float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale()
+ int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back)
+
+ ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer)
+ ImDrawList DrawListInst;
+ ImGuiWindow* ParentWindow; // If we are a child _or_ popup _or_ docked window, this is pointing to our parent. Otherwise NULL.
+ ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. Doesn't cross through popups/dock nodes.
+ ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child.
+ ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
+ ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag.
+
+ ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.)
+ ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1)
+ ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space
+
+ int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy
+ int MemoryDrawListVtxCapacity;
+ bool MemoryCompacted; // Set when window extraneous data have been garbage collected
+
+public:
+ ImGuiWindow(ImGuiContext* context, const char* name);
+ ~ImGuiWindow();
+
+ ImGuiID GetID(const char* str, const char* str_end = NULL);
+ ImGuiID GetID(const void* ptr);
+ ImGuiID GetID(int n);
+ ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL);
+ ImGuiID GetIDNoKeepAlive(const void* ptr);
+ ImGuiID GetIDNoKeepAlive(int n);
+ ImGuiID GetIDFromRectangle(const ImRect& r_abs);
+
+ // We don't use g.FontSize because the window may be != g.CurrentWidow.
+ ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
+ float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
+ float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; }
+ ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
+ float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; }
+ ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Tab bar, Tab item support
+//-----------------------------------------------------------------------------
+
+// Extend ImGuiTabBarFlags_
+enum ImGuiTabBarFlagsPrivate_
+{
+ ImGuiTabBarFlags_DockNode = 1 << 20, // Part of a dock node [we don't use this in the master branch but it facilitate branch syncing to keep this around]
+ ImGuiTabBarFlags_IsFocused = 1 << 21,
+ ImGuiTabBarFlags_SaveSettings = 1 << 22 // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs
+};
+
+// Extend ImGuiTabItemFlags_
+enum ImGuiTabItemFlagsPrivate_
+{
+ ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing,
+ ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout)
+ ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button
+};
+
+// Storage for one active tab item (sizeof() 40 bytes)
+struct ImGuiTabItem
+{
+ ImGuiID ID;
+ ImGuiTabItemFlags Flags;
+ int LastFrameVisible;
+ int LastFrameSelected; // This allows us to infer an ordered list of the last activated tabs with little maintenance
+ float Offset; // Position relative to beginning of tab
+ float Width; // Width currently displayed
+ float ContentWidth; // Width of label, stored during BeginTabItem() call
+ ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames
+ ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable
+ ImS16 IndexDuringLayout; // Index only used during TabBarLayout()
+ bool WantClose; // Marked as closed by SetTabItemClosed()
+
+ ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; }
+};
+
+// Storage for a tab bar (sizeof() 152 bytes)
+struct ImGuiTabBar
+{
+ ImVector<ImGuiTabItem> Tabs;
+ ImGuiTabBarFlags Flags;
+ ImGuiID ID; // Zero for tab-bars used by docking
+ ImGuiID SelectedTabId; // Selected tab/window
+ ImGuiID NextSelectedTabId; // Next selected tab/window. Will also trigger a scrolling animation
+ ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview)
+ int CurrFrameVisible;
+ int PrevFrameVisible;
+ ImRect BarRect;
+ float CurrTabsContentsHeight;
+ float PrevTabsContentsHeight; // Record the height of contents submitted below the tab bar
+ float WidthAllTabs; // Actual width of all tabs (locked during layout)
+ float WidthAllTabsIdeal; // Ideal width if all tabs were visible and not clipped
+ float ScrollingAnim;
+ float ScrollingTarget;
+ float ScrollingTargetDistToVisibility;
+ float ScrollingSpeed;
+ float ScrollingRectMinX;
+ float ScrollingRectMaxX;
+ ImGuiID ReorderRequestTabId;
+ ImS16 ReorderRequestOffset;
+ ImS8 BeginCount;
+ bool WantLayout;
+ bool VisibleTabWasSubmitted;
+ bool TabsAddedNew; // Set to true when a new tab item or button has been added to the tab bar during last frame
+ ImS16 TabsActiveCount; // Number of tabs submitted this frame.
+ ImS16 LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem()
+ float ItemSpacingY;
+ ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar()
+ ImVec2 BackupCursorPos;
+ ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer.
+
+ ImGuiTabBar();
+ int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_ptr(tab); }
+ const char* GetTabName(const ImGuiTabItem* tab) const
+ {
+ IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < TabsNames.Buf.Size);
+ return TabsNames.Buf.Data + tab->NameOffset;
+ }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] Table support
+//-----------------------------------------------------------------------------
+
+#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
+#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
+#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableSetupDrawChannels()
+
+// Our current column maximum is 64 but we may raise that in the future.
+typedef ImS8 ImGuiTableColumnIdx;
+typedef ImU8 ImGuiTableDrawChannelIdx;
+
+// [Internal] sizeof() ~ 104
+// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
+// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping.
+// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped".
+struct ImGuiTableColumn
+{
+ ImGuiTableColumnFlags Flags; // Flags after some patching (not directly same as provided by user). See ImGuiTableColumnFlags_
+ float WidthGiven; // Final/actual width visible == (MaxX - MinX), locked in TableUpdateLayout(). May be > WidthRequest to honor minimum width, may be < WidthRequest to honor shrinking columns down in tight space.
+ float MinX; // Absolute positions
+ float MaxX;
+ float WidthRequest; // Master width absolute value when !(Flags & _WidthStretch). When Stretch this is derived every frame from StretchWeight in TableUpdateLayout()
+ float WidthAuto; // Automatic width
+ float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially.
+ float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_).
+ ImRect ClipRect; // Clipping rectangle for the column
+ ImGuiID UserID; // Optional, value passed to TableSetupColumn()
+ float WorkMinX; // Contents region min ~(MinX + CellPaddingX + CellSpacingX1) == cursor start position when entering column
+ float WorkMaxX; // Contents region max ~(MaxX - CellPaddingX - CellSpacingX2)
+ float ItemWidth; // Current item width for the column, preserved across rows
+ float ContentMaxXFrozen; // Contents maximum position for frozen rows (apart from headers), from which we can infer content width.
+ float ContentMaxXUnfrozen;
+ float ContentMaxXHeadersUsed; // Contents maximum position for headers rows (regardless of freezing). TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls
+ float ContentMaxXHeadersIdeal;
+ ImS16 NameOffset; // Offset into parent ColumnsNames[]
+ ImGuiTableColumnIdx DisplayOrder; // Index within Table's IndexToDisplayOrder[] (column may be reordered by users)
+ ImGuiTableColumnIdx IndexWithinEnabledSet; // Index within enabled/visible set (<= IndexToDisplayOrder)
+ ImGuiTableColumnIdx PrevEnabledColumn; // Index of prev enabled/visible column within Columns[], -1 if first enabled/visible column
+ ImGuiTableColumnIdx NextEnabledColumn; // Index of next enabled/visible column within Columns[], -1 if last enabled/visible column
+ ImGuiTableColumnIdx SortOrder; // Index of this column within sort specs, -1 if not sorting on this column, 0 for single-sort, may be >0 on multi-sort
+ ImGuiTableDrawChannelIdx DrawChannelCurrent; // Index within DrawSplitter.Channels[]
+ ImGuiTableDrawChannelIdx DrawChannelFrozen; // Draw channels for frozen rows (often headers)
+ ImGuiTableDrawChannelIdx DrawChannelUnfrozen; // Draw channels for unfrozen rows
+ bool IsEnabled; // IsUserEnabled && (Flags & ImGuiTableColumnFlags_Disabled) == 0
+ bool IsUserEnabled; // Is the column not marked Hidden by the user? (unrelated to being off view, e.g. clipped by scrolling).
+ bool IsUserEnabledNextFrame;
+ bool IsVisibleX; // Is actually in view (e.g. overlapping the host window clipping rectangle, not scrolled).
+ bool IsVisibleY;
+ bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.
+ bool IsSkipItems; // Do we want item submissions to this column to be completely ignored (no layout will happen).
+ bool IsPreserveWidthAuto;
+ ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte
+ ImU8 AutoFitQueue; // Queue of 8 values for the next 8 frames to request auto-fit
+ ImU8 CannotSkipItemsQueue; // Queue of 8 values for the next 8 frames to disable Clipped/SkipItem
+ ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
+ ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3)
+ ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each)
+ ImU8 SortDirectionsAvailList; // Ordered of available sort directions (2-bits each)
+
+ ImGuiTableColumn()
+ {
+ memset(this, 0, sizeof(*this));
+ StretchWeight = WidthRequest = -1.0f;
+ NameOffset = -1;
+ DisplayOrder = IndexWithinEnabledSet = -1;
+ PrevEnabledColumn = NextEnabledColumn = -1;
+ SortOrder = -1;
+ SortDirection = ImGuiSortDirection_None;
+ DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU8)-1;
+ }
+};
+
+// Transient cell data stored per row.
+// sizeof() ~ 6
+struct ImGuiTableCellData
+{
+ ImU32 BgColor; // Actual color
+ ImGuiTableColumnIdx Column; // Column number
+};
+
+// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
+struct IMGUI_API ImGuiTable
+{
+ ImGuiID ID;
+ ImGuiTableFlags Flags;
+ void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[]
+ ImGuiTableTempData* TempData; // Transient data while table is active. Point within g.CurrentTableStack[]
+ ImSpan<ImGuiTableColumn> Columns; // Point within RawData[]
+ ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1)
+ ImSpan<ImGuiTableCellData> RowCellData; // Point within RawData[]. Store cells background requests for current row.
+ ImU64 EnabledMaskByDisplayOrder; // Column DisplayOrder -> IsEnabled map
+ ImU64 EnabledMaskByIndex; // Column Index -> IsEnabled map (== not hidden by user/api) in a format adequate for iterating column without touching cold data
+ ImU64 VisibleMaskByIndex; // Column Index -> IsVisibleX|IsVisibleY map (== not hidden by user/api && not hidden by scrolling/cliprect)
+ ImU64 RequestOutputMaskByIndex; // Column Index -> IsVisible || AutoFit (== expect user to submit items)
+ ImGuiTableFlags SettingsLoadedFlags; // Which data were loaded from the .ini file (e.g. when order is not altered we won't save order)
+ int SettingsOffset; // Offset in g.SettingsTables
+ int LastFrameActive;
+ int ColumnsCount; // Number of columns declared in BeginTable()
+ int CurrentRow;
+ int CurrentColumn;
+ ImS16 InstanceCurrent; // Count of BeginTable() calls with same ID in the same frame (generally 0). This is a little bit similar to BeginCount for a window, but multiple table with same ID look are multiple tables, they are just synched.
+ ImS16 InstanceInteracted; // Mark which instance (generally 0) of the same ID is being interacted with
+ float RowPosY1;
+ float RowPosY2;
+ float RowMinHeight; // Height submitted to TableNextRow()
+ float RowTextBaseline;
+ float RowIndentOffsetX;
+ ImGuiTableRowFlags RowFlags : 16; // Current row flags, see ImGuiTableRowFlags_
+ ImGuiTableRowFlags LastRowFlags : 16;
+ int RowBgColorCounter; // Counter for alternating background colors (can be fast-forwarded by e.g clipper), not same as CurrentRow because header rows typically don't increase this.
+ ImU32 RowBgColor[2]; // Background color override for current row.
+ ImU32 BorderColorStrong;
+ ImU32 BorderColorLight;
+ float BorderX1;
+ float BorderX2;
+ float HostIndentX;
+ float MinColumnWidth;
+ float OuterPaddingX;
+ float CellPaddingX; // Padding from each borders
+ float CellPaddingY;
+ float CellSpacingX1; // Spacing between non-bordered cells
+ float CellSpacingX2;
+ float LastOuterHeight; // Outer height from last frame
+ float LastFirstRowHeight; // Height of first row from last frame
+ float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details.
+ float ColumnsGivenWidth; // Sum of current column width
+ float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window
+ float ResizedColumnNextWidth;
+ float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table.
+ float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
+ ImRect OuterRect; // Note: for non-scrolling table, OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable().
+ ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is
+ ImRect WorkRect;
+ ImRect InnerClipRect;
+ ImRect BgClipRect; // We use this to cpu-clip cell background color fill
+ ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
+ ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
+ ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
+ ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
+ ImGuiWindow* OuterWindow; // Parent window for the table
+ ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
+ ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
+ ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
+ ImGuiTableColumnSortSpecs SortSpecsSingle;
+ ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
+ ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
+ ImGuiTableColumnIdx SortSpecsCount;
+ ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
+ ImGuiTableColumnIdx ColumnsEnabledFixedCount; // Number of enabled columns (<= ColumnsCount)
+ ImGuiTableColumnIdx DeclColumnsCount; // Count calls to TableSetupColumn()
+ ImGuiTableColumnIdx HoveredColumnBody; // Index of column whose visible region is being hovered. Important: == ColumnsCount when hovering empty region after the right-most column!
+ ImGuiTableColumnIdx HoveredColumnBorder; // Index of column whose right-border is being hovered (for resizing).
+ ImGuiTableColumnIdx AutoFitSingleColumn; // Index of single column requesting auto-fit.
+ ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0.
+ ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame.
+ ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held.
+ ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared)
+ ImGuiTableColumnIdx ReorderColumnDir; // -1 or +1
+ ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column.
+ ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column.
+ ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column.
+ ImGuiTableColumnIdx RightMostStretchedColumn; // Index of right-most stretched column.
+ ImGuiTableColumnIdx ContextPopupColumn; // Column right-clicked on, of -1 if opening context menu from a neutral/empty spot
+ ImGuiTableColumnIdx FreezeRowsRequest; // Requested frozen rows count
+ ImGuiTableColumnIdx FreezeRowsCount; // Actual frozen row count (== FreezeRowsRequest, or == 0 when no scrolling offset)
+ ImGuiTableColumnIdx FreezeColumnsRequest; // Requested frozen columns count
+ ImGuiTableColumnIdx FreezeColumnsCount; // Actual frozen columns count (== FreezeColumnsRequest, or == 0 when no scrolling offset)
+ ImGuiTableColumnIdx RowCellDataCurrent; // Index of current RowCellData[] entry in current row
+ ImGuiTableDrawChannelIdx DummyDrawChannel; // Redirect non-visible columns here.
+ ImGuiTableDrawChannelIdx Bg2DrawChannelCurrent; // For Selectable() and other widgets drawing across columns after the freezing line. Index within DrawSplitter.Channels[]
+ ImGuiTableDrawChannelIdx Bg2DrawChannelUnfrozen;
+ bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row.
+ bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow().
+ bool IsInitializing;
+ bool IsSortSpecsDirty;
+ bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
+ bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
+ bool IsSettingsRequestLoad;
+ bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data.
+ bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
+ bool IsResetAllRequest;
+ bool IsResetDisplayOrderRequest;
+ bool IsUnfrozenRows; // Set when we got past the frozen row.
+ bool IsDefaultSizingPolicy; // Set if user didn't explicitly set a sizing policy in BeginTable()
+ bool MemoryCompacted;
+ bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis
+
+ ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; }
+ ~ImGuiTable() { IM_FREE(RawData); }
+};
+
+// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
+// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
+// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
+struct IMGUI_API ImGuiTableTempData
+{
+ int TableIndex; // Index in g.Tables.Buf[] pool
+ float LastTimeActive; // Last timestamp this structure was used
+
+ ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
+ ImDrawListSplitter DrawSplitter;
+
+ ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
+ ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
+ ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
+ ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
+ ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
+ ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
+ float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
+ int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
+
+ ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
+};
+
+// sizeof() ~ 12
+struct ImGuiTableColumnSettings
+{
+ float WidthOrWeight;
+ ImGuiID UserID;
+ ImGuiTableColumnIdx Index;
+ ImGuiTableColumnIdx DisplayOrder;
+ ImGuiTableColumnIdx SortOrder;
+ ImU8 SortDirection : 2;
+ ImU8 IsEnabled : 1; // "Visible" in ini file
+ ImU8 IsStretch : 1;
+
+ ImGuiTableColumnSettings()
+ {
+ WidthOrWeight = 0.0f;
+ UserID = 0;
+ Index = -1;
+ DisplayOrder = SortOrder = -1;
+ SortDirection = ImGuiSortDirection_None;
+ IsEnabled = 1;
+ IsStretch = 0;
+ }
+};
+
+// This is designed to be stored in a single ImChunkStream (1 header followed by N ImGuiTableColumnSettings, etc.)
+struct ImGuiTableSettings
+{
+ ImGuiID ID; // Set to 0 to invalidate/delete the setting
+ ImGuiTableFlags SaveFlags; // Indicate data we want to save using the Resizable/Reorderable/Sortable/Hideable flags (could be using its own flags..)
+ float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
+ ImGuiTableColumnIdx ColumnsCount;
+ ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher
+ bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
+
+ ImGuiTableSettings() { memset(this, 0, sizeof(*this)); }
+ ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
+};
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImGui internal API
+// No guarantee of forward compatibility here!
+//-----------------------------------------------------------------------------
+
+namespace ImGui
+{
+ // Windows
+ // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window)
+ // If this ever crash because g.CurrentWindow is NULL it means that either
+ // - ImGui::NewFrame() has never been called, which is illegal.
+ // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal.
+ inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; }
+ inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; }
+ IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id);
+ IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
+ IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
+ IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
+ IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy);
+ IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below);
+ IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
+ IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
+ IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);
+ IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);
+ IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
+ inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
+ inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
+
+ // Windows: Display Order and Focus Order
+ IMGUI_API void FocusWindow(ImGuiWindow* window);
+ IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window);
+ IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
+ IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
+ IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
+
+ // Fonts, drawing
+ IMGUI_API void SetCurrentFont(ImFont* font);
+ inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
+ inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches.
+ IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents.
+ IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents.
+
+ // Init
+ IMGUI_API void Initialize(ImGuiContext* context);
+ IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
+
+ // NewFrame
+ IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
+ IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
+ IMGUI_API void UpdateMouseMovingWindowNewFrame();
+ IMGUI_API void UpdateMouseMovingWindowEndFrame();
+
+ // Generic context hooks
+ IMGUI_API ImGuiID AddContextHook(ImGuiContext* context, const ImGuiContextHook* hook);
+ IMGUI_API void RemoveContextHook(ImGuiContext* context, ImGuiID hook_to_remove);
+ IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type);
+
+ // Settings
+ IMGUI_API void MarkIniSettingsDirty();
+ IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
+ IMGUI_API void ClearIniSettings();
+ IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name);
+ IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);
+ IMGUI_API ImGuiWindowSettings* FindOrCreateWindowSettings(const char* name);
+ IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
+
+ // Scrolling
+ IMGUI_API void SetNextWindowScroll(const ImVec2& scroll); // Use -1.0f on one axis to leave as-is
+ IMGUI_API void SetScrollX(ImGuiWindow* window, float scroll_x);
+ IMGUI_API void SetScrollY(ImGuiWindow* window, float scroll_y);
+ IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio);
+ IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio);
+
+ // Early work-in-progress API (ScrollToItem() will become public)
+ IMGUI_API void ScrollToItem(ImGuiScrollFlags flags = 0);
+ IMGUI_API void ScrollToRect(ImGuiWindow* window, const ImRect& rect, ImGuiScrollFlags flags = 0);
+ IMGUI_API ImVec2 ScrollToRectEx(ImGuiWindow* window, const ImRect& rect, ImGuiScrollFlags flags = 0);
+//#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ inline void ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& rect) { ScrollToRect(window, rect, ImGuiScrollFlags_KeepVisibleEdgeY); }
+//#endif
+
+ // Basic Accessors
+ inline ImGuiID GetItemID() { ImGuiContext& g = *GImGui; return g.LastItemData.ID; } // Get ID of last item (~~ often same ImGui::GetID(label) beforehand)
+ inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; }
+ inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; }
+ inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
+ inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
+ IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
+ IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
+ IMGUI_API void ClearActiveID();
+ IMGUI_API ImGuiID GetHoveredID();
+ IMGUI_API void SetHoveredID(ImGuiID id);
+ IMGUI_API void KeepAliveID(ImGuiID id);
+ IMGUI_API void MarkItemEdited(ImGuiID id); // Mark data associated to given item as "edited", used by IsItemDeactivatedAfterEdit() function.
+ IMGUI_API void PushOverrideID(ImGuiID id); // Push given value as-is at the top of the ID stack (whereas PushID combines old and new hashes)
+ IMGUI_API ImGuiID GetIDWithSeed(const char* str_id_begin, const char* str_id_end, ImGuiID seed);
+
+ // Basic Helpers for widget code
+ IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);
+ IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f);
+ IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
+ IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
+ IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
+ IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
+ IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
+ IMGUI_API void PushMultiItemsWidths(int components, float width_full);
+ IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
+ IMGUI_API ImVec2 GetContentRegionMaxAbs();
+ IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
+
+ // Parameter stacks
+ IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
+ IMGUI_API void PopItemFlag();
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ // Currently refactoring focus/nav/tabbing system
+ // If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
+ // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
+ // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
+ // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP)
+ // Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()
+ inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd()
+ inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
+#endif
+
+ // Logging/Capture
+ IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
+ IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer
+ IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL);
+ IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix);
+
+ // Popups, Modals, Tooltips
+ IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags);
+ IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
+ IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
+ IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
+ IMGUI_API void ClosePopupsExceptModals();
+ IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
+ IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
+ IMGUI_API void BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
+ IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
+ IMGUI_API ImGuiWindow* GetTopMostPopupModal();
+ IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
+ IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
+
+ // Menus
+ IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
+ IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true);
+ IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true);
+
+ // Combos
+ IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags);
+ IMGUI_API bool BeginComboPreview();
+ IMGUI_API void EndComboPreview();
+
+ // Gamepad/Keyboard Navigation
+ IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
+ IMGUI_API void NavInitRequestApplyResult();
+ IMGUI_API bool NavMoveRequestButNoResultYet();
+ IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
+ IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
+ IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
+ IMGUI_API void NavMoveRequestCancel();
+ IMGUI_API void NavMoveRequestApplyResult();
+ IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
+ IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode);
+ IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
+ IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
+ IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
+ IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
+
+ // Focus Scope (WIP)
+ // This is generally used to identify a selection set (multiple of which may be in the same window), as selection
+ // patterns generally need to react (e.g. clear selection) when landing on an item of the set.
+ IMGUI_API void PushFocusScope(ImGuiID id);
+ IMGUI_API void PopFocusScope();
+ inline ImGuiID GetFocusedFocusScope() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } // Focus scope which is actually active
+ inline ImGuiID GetFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.NavFocusScopeIdCurrent; } // Focus scope we are outputting into, set by PushFocusScope()
+
+ // Inputs
+ // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
+ IMGUI_API void SetItemUsingMouseWheel();
+ IMGUI_API void SetActiveIdUsingNavAndKeys();
+ inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
+ inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; }
+ inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; }
+ IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f);
+ inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { ImGuiContext& g = *GImGui; const int key_index = g.IO.KeyMap[key]; return (key_index >= 0) ? IsKeyPressed(key_index, repeat) : false; }
+ inline bool IsNavInputDown(ImGuiNavInput n) { ImGuiContext& g = *GImGui; return g.IO.NavInputs[n] > 0.0f; }
+ inline bool IsNavInputTest(ImGuiNavInput n, ImGuiInputReadMode rm) { return (GetNavInputAmount(n, rm) > 0.0f); }
+ IMGUI_API ImGuiKeyModFlags GetMergedKeyModFlags();
+
+ // Drag and Drop
+ IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id);
+ IMGUI_API void ClearDragDrop();
+ IMGUI_API bool IsDragDropPayloadBeingAccepted();
+
+ // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
+ IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
+ IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
+ IMGUI_API void EndColumns(); // close columns
+ IMGUI_API void PushColumnClipRect(int column_index);
+ IMGUI_API void PushColumnsBackground();
+ IMGUI_API void PopColumnsBackground();
+ IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
+ IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
+ IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm);
+ IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset);
+
+ // Tables: Candidates for public API
+ IMGUI_API void TableOpenContextMenu(int column_n = -1);
+ IMGUI_API void TableSetColumnWidth(int column_n, float width);
+ IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
+ IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
+ IMGUI_API float TableGetHeaderRowHeight();
+ IMGUI_API void TablePushBackgroundChannel();
+ IMGUI_API void TablePopBackgroundChannel();
+
+ // Tables: Internals
+ inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
+ IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
+ IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
+ IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count);
+ IMGUI_API void TableBeginApplyRequests(ImGuiTable* table);
+ IMGUI_API void TableSetupDrawChannels(ImGuiTable* table);
+ IMGUI_API void TableUpdateLayout(ImGuiTable* table);
+ IMGUI_API void TableUpdateBorders(ImGuiTable* table);
+ IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
+ IMGUI_API void TableDrawBorders(ImGuiTable* table);
+ IMGUI_API void TableDrawContextMenu(ImGuiTable* table);
+ IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
+ IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
+ IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
+ IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
+ IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column);
+ IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column);
+ IMGUI_API void TableBeginRow(ImGuiTable* table);
+ IMGUI_API void TableEndRow(ImGuiTable* table);
+ IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n);
+ IMGUI_API void TableEndCell(ImGuiTable* table);
+ IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
+ IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
+ IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0);
+ IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n);
+ IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
+ IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
+ IMGUI_API void TableRemove(ImGuiTable* table);
+ IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
+ IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
+ IMGUI_API void TableGcCompactSettings();
+
+ // Tables: Settings
+ IMGUI_API void TableLoadSettings(ImGuiTable* table);
+ IMGUI_API void TableSaveSettings(ImGuiTable* table);
+ IMGUI_API void TableResetSettings(ImGuiTable* table);
+ IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
+ IMGUI_API void TableSettingsInstallHandler(ImGuiContext* context);
+ IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
+ IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
+
+ // Tab Bars
+ IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
+ IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
+ IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
+ IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
+ IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset);
+ IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, ImVec2 mouse_pos);
+ IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar);
+ IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags);
+ IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button);
+ IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col);
+ IMGUI_API void TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped);
+
+ // Render helpers
+ // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.
+ // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally)
+ IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
+ IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
+ IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
+ IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
+ IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known);
+ IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
+ IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
+ IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
+ IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight
+ IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text.
+
+ // Render helpers (those functions don't access any ImGui state!)
+ IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f);
+ IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col);
+ IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz);
+ IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow);
+ IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
+ IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
+ IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect inner, ImU32 col, float rounding);
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ // [1.71: 2019/06/07: Updating prototypes of some of the internal functions. Leaving those for reference for a short while]
+ inline void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale=1.0f) { ImGuiWindow* window = GetCurrentWindow(); RenderArrow(window->DrawList, pos, GetColorU32(ImGuiCol_Text), dir, scale); }
+ inline void RenderBullet(ImVec2 pos) { ImGuiWindow* window = GetCurrentWindow(); RenderBullet(window->DrawList, pos, GetColorU32(ImGuiCol_Text)); }
+#endif
+
+ // Widgets
+ IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
+ IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0);
+ IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos);
+ IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos);
+ IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
+ IMGUI_API void Scrollbar(ImGuiAxis axis);
+ IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawFlags flags);
+ IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col);
+ IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis);
+ IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
+ IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
+ IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir);
+ IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags);
+ IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
+ IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value);
+
+ // Widgets low-level behaviors
+ IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
+ IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags);
+ IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
+ IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f);
+ IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL);
+ IMGUI_API bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0); // Consume previous SetNextItemOpen() data, if any. May return true when logging
+ IMGUI_API void TreePushOverrideID(ImGuiID id);
+
+ // Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
+ // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
+ // e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); "
+ template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
+ template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
+ template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags);
+ template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
+ template<typename T, typename SIGNED_T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
+ template<typename T> IMGUI_API bool CheckboxFlagsT(const char* label, T* flags, T flags_value);
+
+ // Data type helpers
+ IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type);
+ IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format);
+ IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2);
+ IMGUI_API bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format);
+ IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2);
+ IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max);
+
+ // InputText
+ IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags);
+ IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
+ inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); }
+ inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
+
+ // Color
+ IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags);
+ IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags);
+ IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags);
+
+ // Plot
+ IMGUI_API int PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size);
+
+ // Shade functions (write over already created vertices)
+ IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
+ IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp);
+
+ // Garbage collection
+ IMGUI_API void GcCompactTransientMiscBuffers();
+ IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window);
+ IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window);
+
+ // Debug Tools
+ IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
+ IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL);
+ inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); }
+ inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; }
+
+ IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas);
+ IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end);
+ IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns);
+ IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, const ImDrawList* draw_list, const char* label);
+ IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
+ IMGUI_API void DebugNodeFont(ImFont* font);
+ IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
+ IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
+ IMGUI_API void DebugNodeTable(ImGuiTable* table);
+ IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
+ IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
+ IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
+ IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);
+ IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport);
+ IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb);
+
+} // namespace ImGui
+
+
+//-----------------------------------------------------------------------------
+// [SECTION] ImFontAtlas internal API
+//-----------------------------------------------------------------------------
+
+// This structure is likely to evolve as we add support for incremental atlas updates
+struct ImFontBuilderIO
+{
+ bool (*FontBuilder_Build)(ImFontAtlas* atlas);
+};
+
+// Helper for font builder
+IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype();
+IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas);
+IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent);
+IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque);
+IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas);
+IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value);
+IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value);
+IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor);
+IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride);
+
+//-----------------------------------------------------------------------------
+// [SECTION] Test Engine specific hooks (imgui_test_engine)
+//-----------------------------------------------------------------------------
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
+extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags);
+extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...);
+extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiID id);
+
+#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box
+#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
+#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
+#else
+#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imgui_tables.cpp b/Client/ThirdParty/imgui/imgui_tables.cpp
new file mode 100644
index 0000000..1c61180
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui_tables.cpp
@@ -0,0 +1,4049 @@
+// dear imgui, v1.86 WIP
+// (tables and columns code)
+
+/*
+
+Index of this file:
+
+// [SECTION] Commentary
+// [SECTION] Header mess
+// [SECTION] Tables: Main code
+// [SECTION] Tables: Simple accessors
+// [SECTION] Tables: Row changes
+// [SECTION] Tables: Columns changes
+// [SECTION] Tables: Columns width management
+// [SECTION] Tables: Drawing
+// [SECTION] Tables: Sorting
+// [SECTION] Tables: Headers
+// [SECTION] Tables: Context Menu
+// [SECTION] Tables: Settings (.ini data)
+// [SECTION] Tables: Garbage Collection
+// [SECTION] Tables: Debugging
+// [SECTION] Columns, BeginColumns, EndColumns, etc.
+
+*/
+
+// Navigating this file:
+// - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
+// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
+
+//-----------------------------------------------------------------------------
+// [SECTION] Commentary
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Typical tables call flow: (root level is generally public API):
+//-----------------------------------------------------------------------------
+// - BeginTable() user begin into a table
+// | BeginChild() - (if ScrollX/ScrollY is set)
+// | TableBeginInitMemory() - first time table is used
+// | TableResetSettings() - on settings reset
+// | TableLoadSettings() - on settings load
+// | TableBeginApplyRequests() - apply queued resizing/reordering/hiding requests
+// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame)
+// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width
+// - TableSetupColumn() user submit columns details (optional)
+// - TableSetupScrollFreeze() user submit scroll freeze information (optional)
+//-----------------------------------------------------------------------------
+// - TableUpdateLayout() [Internal] followup to BeginTable(): setup everything: widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow().
+// | TableSetupDrawChannels() - setup ImDrawList channels
+// | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission
+// | TableDrawContextMenu() - draw right-click context menu
+//-----------------------------------------------------------------------------
+// - TableHeadersRow() or TableHeader() user submit a headers row (optional)
+// | TableSortSpecsClickColumn() - when left-clicked: alter sort order and sort direction
+// | TableOpenContextMenu() - when right-clicked: trigger opening of the default context menu
+// - TableGetSortSpecs() user queries updated sort specs (optional, generally after submitting headers)
+// - TableNextRow() user begin into a new row (also automatically called by TableHeadersRow())
+// | TableEndRow() - finish existing row
+// | TableBeginRow() - add a new row
+// - TableSetColumnIndex() / TableNextColumn() user begin into a cell
+// | TableEndCell() - close existing column/cell
+// | TableBeginCell() - enter into current column/cell
+// - [...] user emit contents
+//-----------------------------------------------------------------------------
+// - EndTable() user ends the table
+// | TableDrawBorders() - draw outer borders, inner vertical borders
+// | TableMergeDrawChannels() - merge draw channels if clipping isn't required
+// | EndChild() - (if ScrollX/ScrollY is set)
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// TABLE SIZING
+//-----------------------------------------------------------------------------
+// (Read carefully because this is subtle but it does make sense!)
+//-----------------------------------------------------------------------------
+// About 'outer_size':
+// Its meaning needs to differ slightly depending on if we are using ScrollX/ScrollY flags.
+// Default value is ImVec2(0.0f, 0.0f).
+// X
+// - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge.
+// - outer_size.x > 0.0f -> Set Fixed width.
+// Y with ScrollX/ScrollY disabled: we output table directly in current window
+// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful is parent window can vertically scroll.
+// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set)
+// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set)
+// Y with ScrollX/ScrollY enabled: using a child window for scrolling
+// - outer_size.y < 0.0f -> Bottom-align. Not meaningful is parent window can vertically scroll.
+// - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window.
+// - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis.
+//-----------------------------------------------------------------------------
+// Outer size is also affected by the NoHostExtendX/NoHostExtendY flags.
+// Important to that note how the two flags have slightly different behaviors!
+// - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
+// - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible.
+// In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height.
+// This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not easily noticeable)
+//-----------------------------------------------------------------------------
+// About 'inner_width':
+// With ScrollX disabled:
+// - inner_width -> *ignored*
+// With ScrollX enabled:
+// - inner_width < 0.0f -> *illegal* fit in known width (right align from outer_size.x) <-- weird
+// - inner_width = 0.0f -> fit in outer_width: Fixed size columns will take space they need (if avail, otherwise shrink down), Stretch columns becomes Fixed columns.
+// - inner_width > 0.0f -> override scrolling width, generally to be larger than outer_size.x. Fixed column take space they need (if avail, otherwise shrink down), Stretch columns share remaining space!
+//-----------------------------------------------------------------------------
+// Details:
+// - If you want to use Stretch columns with ScrollX, you generally need to specify 'inner_width' otherwise the concept
+// of "available space" doesn't make sense.
+// - Even if not really useful, we allow 'inner_width < outer_size.x' for consistency and to facilitate understanding
+// of what the value does.
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// COLUMNS SIZING POLICIES
+//-----------------------------------------------------------------------------
+// About overriding column sizing policy and width/weight with TableSetupColumn():
+// We use a default parameter of 'init_width_or_weight == -1'.
+// - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic
+// - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom
+// - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f
+// - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom
+// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f)
+// and you can fit a 100.0f wide item in it without clipping and with full padding.
+//-----------------------------------------------------------------------------
+// About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag)
+// - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width
+// - with Table policy ImGuiTableFlags_SizingFixedSame --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is max of all contents width
+// - with Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is 1.0f
+// - with Table policy ImGuiTableFlags_SizingStretchWeight --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is proportional to contents
+// Default Width and default Weight can be overridden when calling TableSetupColumn().
+//-----------------------------------------------------------------------------
+// About mixing Fixed/Auto and Stretch columns together:
+// - the typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
+// - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place!
+// that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in.
+// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents.
+// - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths.
+//-----------------------------------------------------------------------------
+// About using column width:
+// If a column is manual resizable or has a width specified with TableSetupColumn():
+// - you may use GetContentRegionAvail().x to query the width available in a given column.
+// - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width.
+// If the column is not resizable and has no width specified with TableSetupColumn():
+// - its width will be automatic and be set to the max of items submitted.
+// - therefore you generally cannot have ALL items of the columns use e.g. SetNextItemWidth(-FLT_MIN).
+// - but if the column has one or more items of known/fixed size, this will become the reference width used by SetNextItemWidth(-FLT_MIN).
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// TABLES CLIPPING/CULLING
+//-----------------------------------------------------------------------------
+// About clipping/culling of Rows in Tables:
+// - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows.
+// ImGuiListClipper is reliant on the fact that rows are of equal height.
+// See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper.
+// - Note that auto-resizing columns don't play well with using the clipper.
+// By default a table with _ScrollX but without _Resizable will have column auto-resize.
+// So, if you want to use the clipper, make sure to either enable _Resizable, either setup columns width explicitly with _WidthFixed.
+//-----------------------------------------------------------------------------
+// About clipping/culling of Columns in Tables:
+// - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing
+// width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know
+// it is not going to contribute to row height.
+// In many situations, you may skip submitting contents for every column but one (e.g. the first one).
+// - Case A: column is not hidden by user, and at least partially in sight (most common case).
+// - Case B: column is clipped / out of sight (because of scrolling or parent ClipRect): TableNextColumn() return false as a hint but we still allow layout output.
+// - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.).
+//
+// [A] [B] [C]
+// TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() return false, user can skip submitting items but only if the column doesn't contribute to row height.
+// SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output.
+// ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way.
+// ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway).
+//
+// - We need to distinguish those cases because non-hidden columns that are clipped outside of scrolling bounds should still contribute their height to the row.
+// However, in the majority of cases, the contribution to row height is the same for all columns, or the tallest cells are known by the programmer.
+//-----------------------------------------------------------------------------
+// About clipping/culling of whole Tables:
+// - Scrolling tables with a known outer size can be clipped earlier as BeginTable() will return false.
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// [SECTION] Header mess
+//-----------------------------------------------------------------------------
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DISABLE
+
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+// System includes
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
+#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
+#endif
+#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
+#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
+#endif
+
+// Clang/GCC warnings with -Weverything
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
+#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_')
+#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+
+//-----------------------------------------------------------------------------
+// [SECTION] Tables: Main code
+//-----------------------------------------------------------------------------
+// - TableFixFlags() [Internal]
+// - TableFindByID() [Internal]
+// - BeginTable()
+// - BeginTableEx() [Internal]
+// - TableBeginInitMemory() [Internal]
+// - TableBeginApplyRequests() [Internal]
+// - TableSetupColumnFlags() [Internal]
+// - TableUpdateLayout() [Internal]
+// - TableUpdateBorders() [Internal]
+// - EndTable()
+// - TableSetupColumn()
+// - TableSetupScrollFreeze()
+//-----------------------------------------------------------------------------
+
+// Configuration
+static const int TABLE_DRAW_CHANNEL_BG0 = 0;
+static const int TABLE_DRAW_CHANNEL_BG2_FROZEN = 1;
+static const int TABLE_DRAW_CHANNEL_NOCLIP = 2; // When using ImGuiTableFlags_NoClip (this becomes the last visible channel)
+static const float TABLE_BORDER_SIZE = 1.0f; // FIXME-TABLE: Currently hard-coded because of clipping assumptions with outer borders rendering.
+static const float TABLE_RESIZE_SEPARATOR_HALF_THICKNESS = 4.0f; // Extend outside inner borders.
+static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f; // Delay/timer before making the hover feedback (color+cursor) visible because tables/columns tends to be more cramped.
+
+// Helper
+inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window)
+{
+ // Adjust flags: set default sizing policy
+ if ((flags & ImGuiTableFlags_SizingMask_) == 0)
+ flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_SizingFixedFit : ImGuiTableFlags_SizingStretchSame;
+
+ // Adjust flags: enable NoKeepColumnsVisible when using ImGuiTableFlags_SizingFixedSame
+ if ((flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
+ flags |= ImGuiTableFlags_NoKeepColumnsVisible;
+
+ // Adjust flags: enforce borders when resizable
+ if (flags & ImGuiTableFlags_Resizable)
+ flags |= ImGuiTableFlags_BordersInnerV;
+
+ // Adjust flags: disable NoHostExtendX/NoHostExtendY if we have any scrolling going on
+ if (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY))
+ flags &= ~(ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_NoHostExtendY);
+
+ // Adjust flags: NoBordersInBodyUntilResize takes priority over NoBordersInBody
+ if (flags & ImGuiTableFlags_NoBordersInBodyUntilResize)
+ flags &= ~ImGuiTableFlags_NoBordersInBody;
+
+ // Adjust flags: disable saved settings if there's nothing to save
+ if ((flags & (ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable)) == 0)
+ flags |= ImGuiTableFlags_NoSavedSettings;
+
+ // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set)
+ if (outer_window->RootWindow->Flags & ImGuiWindowFlags_NoSavedSettings)
+ flags |= ImGuiTableFlags_NoSavedSettings;
+
+ return flags;
+}
+
+ImGuiTable* ImGui::TableFindByID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ return g.Tables.GetByKey(id);
+}
+
+// Read about "TABLE SIZING" at the top of this file.
+bool ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width)
+{
+ ImGuiID id = GetID(str_id);
+ return BeginTableEx(str_id, id, columns_count, flags, outer_size, inner_width);
+}
+
+bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* outer_window = GetCurrentWindow();
+ if (outer_window->SkipItems) // Consistent with other tables + beneficial side effect that assert on miscalling EndTable() will be more visible.
+ return false;
+
+ // Sanity checks
+ IM_ASSERT(columns_count > 0 && columns_count <= IMGUI_TABLE_MAX_COLUMNS && "Only 1..64 columns allowed!");
+ if (flags & ImGuiTableFlags_ScrollX)
+ IM_ASSERT(inner_width >= 0.0f);
+
+ // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping rules may evolve.
+ const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
+ const ImVec2 avail_size = GetContentRegionAvail();
+ ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
+ ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size);
+ if (use_child_window && IsClippedEx(outer_rect, 0))
+ {
+ ItemSize(outer_rect);
+ return false;
+ }
+
+ // Acquire storage for the table
+ ImGuiTable* table = g.Tables.GetOrAddByKey(id);
+ const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
+ const ImGuiID instance_id = id + instance_no;
+ const ImGuiTableFlags table_last_flags = table->Flags;
+ if (instance_no > 0)
+ IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
+
+ // Acquire temporary buffers
+ const int table_idx = g.Tables.GetIndex(table);
+ if (++g.TablesTempDataStacked > g.TablesTempData.Size)
+ g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData());
+ ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1];
+ temp_data->TableIndex = table_idx;
+ table->DrawSplitter = &table->TempData->DrawSplitter;
+ table->DrawSplitter->Clear();
+
+ // Fix flags
+ table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0;
+ flags = TableFixFlags(flags, outer_window);
+
+ // Initialize
+ table->ID = id;
+ table->Flags = flags;
+ table->InstanceCurrent = (ImS16)instance_no;
+ table->LastFrameActive = g.FrameCount;
+ table->OuterWindow = table->InnerWindow = outer_window;
+ table->ColumnsCount = columns_count;
+ table->IsLayoutLocked = false;
+ table->InnerWidth = inner_width;
+ temp_data->UserOuterSize = outer_size;
+
+ // When not using a child window, WorkRect.Max will grow as we append contents.
+ if (use_child_window)
+ {
+ // Ensure no vertical scrollbar appears if we only want horizontal one, to make flag consistent
+ // (we have no other way to disable vertical scrollbar of a window while keeping the horizontal one showing)
+ ImVec2 override_content_size(FLT_MAX, FLT_MAX);
+ if ((flags & ImGuiTableFlags_ScrollX) && !(flags & ImGuiTableFlags_ScrollY))
+ override_content_size.y = FLT_MIN;
+
+ // Ensure specified width (when not specified, Stretched columns will act as if the width == OuterWidth and
+ // never lead to any scrolling). We don't handle inner_width < 0.0f, we could potentially use it to right-align
+ // based on the right side of the child window work rect, which would require knowing ahead if we are going to
+ // have decoration taking horizontal spaces (typically a vertical scrollbar).
+ if ((flags & ImGuiTableFlags_ScrollX) && inner_width > 0.0f)
+ override_content_size.x = inner_width;
+
+ if (override_content_size.x != FLT_MAX || override_content_size.y != FLT_MAX)
+ SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f));
+
+ // Reset scroll if we are reactivating it
+ if ((table_last_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
+ SetNextWindowScroll(ImVec2(0.0f, 0.0f));
+
+ // Create scrolling region (without border and zero window padding)
+ ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None;
+ BeginChildEx(name, instance_id, outer_rect.GetSize(), false, child_flags);
+ table->InnerWindow = g.CurrentWindow;
+ table->WorkRect = table->InnerWindow->WorkRect;
+ table->OuterRect = table->InnerWindow->Rect();
+ table->InnerRect = table->InnerWindow->InnerRect;
+ IM_ASSERT(table->InnerWindow->WindowPadding.x == 0.0f && table->InnerWindow->WindowPadding.y == 0.0f && table->InnerWindow->WindowBorderSize == 0.0f);
+ }
+ else
+ {
+ // For non-scrolling tables, WorkRect == OuterRect == InnerRect.
+ // But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable().
+ table->WorkRect = table->OuterRect = table->InnerRect = outer_rect;
+ }
+
+ // Push a standardized ID for both child-using and not-child-using tables
+ PushOverrideID(instance_id);
+
+ // Backup a copy of host window members we will modify
+ ImGuiWindow* inner_window = table->InnerWindow;
+ table->HostIndentX = inner_window->DC.Indent.x;
+ table->HostClipRect = inner_window->ClipRect;
+ table->HostSkipItems = inner_window->SkipItems;
+ temp_data->HostBackupWorkRect = inner_window->WorkRect;
+ temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
+ temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
+ temp_data->HostBackupPrevLineSize = inner_window->DC.PrevLineSize;
+ temp_data->HostBackupCurrLineSize = inner_window->DC.CurrLineSize;
+ temp_data->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
+ temp_data->HostBackupItemWidth = outer_window->DC.ItemWidth;
+ temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
+ inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
+
+ // Padding and Spacing
+ // - None ........Content..... Pad .....Content........
+ // - PadOuter | Pad ..Content..... Pad .....Content.. Pad |
+ // - PadInner ........Content.. Pad | Pad ..Content........
+ // - PadOuter+PadInner | Pad ..Content.. Pad | Pad ..Content.. Pad |
+ const bool pad_outer_x = (flags & ImGuiTableFlags_NoPadOuterX) ? false : (flags & ImGuiTableFlags_PadOuterX) ? true : (flags & ImGuiTableFlags_BordersOuterV) != 0;
+ const bool pad_inner_x = (flags & ImGuiTableFlags_NoPadInnerX) ? false : true;
+ const float inner_spacing_for_border = (flags & ImGuiTableFlags_BordersInnerV) ? TABLE_BORDER_SIZE : 0.0f;
+ const float inner_spacing_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) == 0) ? g.Style.CellPadding.x : 0.0f;
+ const float inner_padding_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) != 0) ? g.Style.CellPadding.x : 0.0f;
+ table->CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border;
+ table->CellSpacingX2 = inner_spacing_explicit;
+ table->CellPaddingX = inner_padding_explicit;
+ table->CellPaddingY = g.Style.CellPadding.y;
+
+ const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
+ const float outer_padding_explicit = pad_outer_x ? g.Style.CellPadding.x : 0.0f;
+ table->OuterPaddingX = (outer_padding_for_border + outer_padding_explicit) - table->CellPaddingX;
+
+ table->CurrentColumn = -1;
+ table->CurrentRow = -1;
+ table->RowBgColorCounter = 0;
+ table->LastRowFlags = ImGuiTableRowFlags_None;
+ table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect;
+ table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width
+ table->InnerClipRect.ClipWithFull(table->HostClipRect);
+ table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y;
+
+ table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
+ table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
+ table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any
+ table->FreezeColumnsRequest = table->FreezeColumnsCount = 0;
+ table->IsUnfrozenRows = true;
+ table->DeclColumnsCount = 0;
+
+ // Using opaque colors facilitate overlapping elements of the grid
+ table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
+ table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight);
+
+ // Make table current
+ g.CurrentTable = table;
+ outer_window->DC.CurrentTableIdx = table_idx;
+ if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
+ inner_window->DC.CurrentTableIdx = table_idx;
+
+ if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
+ table->IsResetDisplayOrderRequest = true;
+
+ // Mark as used
+ if (table_idx >= g.TablesLastTimeActive.Size)
+ g.TablesLastTimeActive.resize(table_idx + 1, -1.0f);
+ g.TablesLastTimeActive[table_idx] = (float)g.Time;
+ temp_data->LastTimeActive = (float)g.Time;
+ table->MemoryCompacted = false;
+
+ // Setup memory buffer (clear data if columns count changed)
+ ImGuiTableColumn* old_columns_to_preserve = NULL;
+ void* old_columns_raw_data = NULL;
+ const int old_columns_count = table->Columns.size();
+ if (old_columns_count != 0 && old_columns_count != columns_count)
+ {
+ // Attempt to preserve width on column count change (#4046)
+ old_columns_to_preserve = table->Columns.Data;
+ old_columns_raw_data = table->RawData;
+ table->RawData = NULL;
+ }
+ if (table->RawData == NULL)
+ {
+ TableBeginInitMemory(table, columns_count);
+ table->IsInitializing = table->IsSettingsRequestLoad = true;
+ }
+ if (table->IsResetAllRequest)
+ TableResetSettings(table);
+ if (table->IsInitializing)
+ {
+ // Initialize
+ table->SettingsOffset = -1;
+ table->IsSortSpecsDirty = true;
+ table->InstanceInteracted = -1;
+ table->ContextPopupColumn = -1;
+ table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1;
+ table->AutoFitSingleColumn = -1;
+ table->HoveredColumnBody = table->HoveredColumnBorder = -1;
+ for (int n = 0; n < columns_count; n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[n];
+ if (old_columns_to_preserve && n < old_columns_count)
+ {
+ // FIXME: We don't attempt to preserve column order in this path.
+ *column = old_columns_to_preserve[n];
+ }
+ else
+ {
+ float width_auto = column->WidthAuto;
+ *column = ImGuiTableColumn();
+ column->WidthAuto = width_auto;
+ column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
+ column->IsEnabled = column->IsUserEnabled = column->IsUserEnabledNextFrame = true;
+ }
+ column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
+ }
+ }
+ if (old_columns_raw_data)
+ IM_FREE(old_columns_raw_data);
+
+ // Load settings
+ if (table->IsSettingsRequestLoad)
+ TableLoadSettings(table);
+
+ // Handle DPI/font resize
+ // This is designed to facilitate DPI changes with the assumption that e.g. style.CellPadding has been scaled as well.
+ // It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition.
+ // FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory.
+ // This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path.
+ const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ?
+ if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit)
+ {
+ const float scale_factor = new_ref_scale_unit / table->RefScale;
+ //IMGUI_DEBUG_LOG("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor);
+ for (int n = 0; n < columns_count; n++)
+ table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor;
+ }
+ table->RefScale = new_ref_scale_unit;
+
+ // Disable output until user calls TableNextRow() or TableNextColumn() leading to the TableUpdateLayout() call..
+ // This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user.
+ // Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
+ inner_window->SkipItems = true;
+
+ // Clear names
+ // At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn()
+ if (table->ColumnsNames.Buf.Size > 0)
+ table->ColumnsNames.Buf.resize(0);
+
+ // Apply queued resizing/reordering/hiding requests
+ TableBeginApplyRequests(table);
+
+ return true;
+}
+
+// For reference, the average total _allocation count_ for a table is:
+// + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables)
+// + 1 (for table->RawData allocated below)
+// + 1 (for table->ColumnsNames, if names are used)
+// Shared allocations per number of nested tables
+// + 1 (for table->Splitter._Channels)
+// + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels)
+// Where active_channels_count is variable but often == columns_count or columns_count + 1, see TableSetupDrawChannels() for details.
+// Unused channels don't perform their +2 allocations.
+void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count)
+{
+ // Allocate single buffer for our arrays
+ ImSpanAllocator<3> span_allocator;
+ span_allocator.Reserve(0, columns_count * sizeof(ImGuiTableColumn));
+ span_allocator.Reserve(1, columns_count * sizeof(ImGuiTableColumnIdx));
+ span_allocator.Reserve(2, columns_count * sizeof(ImGuiTableCellData), 4);
+ table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes());
+ memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes());
+ span_allocator.SetArenaBasePtr(table->RawData);
+ span_allocator.GetSpan(0, &table->Columns);
+ span_allocator.GetSpan(1, &table->DisplayOrderToIndex);
+ span_allocator.GetSpan(2, &table->RowCellData);
+}
+
+// Apply queued resizing/reordering/hiding requests
+void ImGui::TableBeginApplyRequests(ImGuiTable* table)
+{
+ // Handle resizing request
+ // (We process this at the first TableBegin of the frame)
+ // FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling?
+ if (table->InstanceCurrent == 0)
+ {
+ if (table->ResizedColumn != -1 && table->ResizedColumnNextWidth != FLT_MAX)
+ TableSetColumnWidth(table->ResizedColumn, table->ResizedColumnNextWidth);
+ table->LastResizedColumn = table->ResizedColumn;
+ table->ResizedColumnNextWidth = FLT_MAX;
+ table->ResizedColumn = -1;
+
+ // Process auto-fit for single column, which is a special case for stretch columns and fixed columns with FixedSame policy.
+ // FIXME-TABLE: Would be nice to redistribute available stretch space accordingly to other weights, instead of giving it all to siblings.
+ if (table->AutoFitSingleColumn != -1)
+ {
+ TableSetColumnWidth(table->AutoFitSingleColumn, table->Columns[table->AutoFitSingleColumn].WidthAuto);
+ table->AutoFitSingleColumn = -1;
+ }
+ }
+
+ // Handle reordering request
+ // Note: we don't clear ReorderColumn after handling the request.
+ if (table->InstanceCurrent == 0)
+ {
+ if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1)
+ table->ReorderColumn = -1;
+ table->HeldHeaderColumn = -1;
+ if (table->ReorderColumn != -1 && table->ReorderColumnDir != 0)
+ {
+ // We need to handle reordering across hidden columns.
+ // In the configuration below, moving C to the right of E will lead to:
+ // ... C [D] E ---> ... [D] E C (Column name/index)
+ // ... 2 3 4 ... 2 3 4 (Display order)
+ const int reorder_dir = table->ReorderColumnDir;
+ IM_ASSERT(reorder_dir == -1 || reorder_dir == +1);
+ IM_ASSERT(table->Flags & ImGuiTableFlags_Reorderable);
+ ImGuiTableColumn* src_column = &table->Columns[table->ReorderColumn];
+ ImGuiTableColumn* dst_column = &table->Columns[(reorder_dir == -1) ? src_column->PrevEnabledColumn : src_column->NextEnabledColumn];
+ IM_UNUSED(dst_column);
+ const int src_order = src_column->DisplayOrder;
+ const int dst_order = dst_column->DisplayOrder;
+ src_column->DisplayOrder = (ImGuiTableColumnIdx)dst_order;
+ for (int order_n = src_order + reorder_dir; order_n != dst_order + reorder_dir; order_n += reorder_dir)
+ table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir;
+ IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir);
+
+ // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[],
+ // rebuild the later from the former.
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n;
+ table->ReorderColumnDir = 0;
+ table->IsSettingsDirty = true;
+ }
+ }
+
+ // Handle display order reset request
+ if (table->IsResetDisplayOrderRequest)
+ {
+ for (int n = 0; n < table->ColumnsCount; n++)
+ table->DisplayOrderToIndex[n] = table->Columns[n].DisplayOrder = (ImGuiTableColumnIdx)n;
+ table->IsResetDisplayOrderRequest = false;
+ table->IsSettingsDirty = true;
+ }
+}
+
+// Adjust flags: default width mode + stretch columns are not allowed when auto extending
+static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in)
+{
+ ImGuiTableColumnFlags flags = flags_in;
+
+ // Sizing Policy
+ if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
+ {
+ const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
+ if (table_sizing_policy == ImGuiTableFlags_SizingFixedFit || table_sizing_policy == ImGuiTableFlags_SizingFixedSame)
+ flags |= ImGuiTableColumnFlags_WidthFixed;
+ else
+ flags |= ImGuiTableColumnFlags_WidthStretch;
+ }
+ else
+ {
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used.
+ }
+
+ // Resize
+ if ((table->Flags & ImGuiTableFlags_Resizable) == 0)
+ flags |= ImGuiTableColumnFlags_NoResize;
+
+ // Sorting
+ if ((flags & ImGuiTableColumnFlags_NoSortAscending) && (flags & ImGuiTableColumnFlags_NoSortDescending))
+ flags |= ImGuiTableColumnFlags_NoSort;
+
+ // Indentation
+ if ((flags & ImGuiTableColumnFlags_IndentMask_) == 0)
+ flags |= (table->Columns.index_from_ptr(column) == 0) ? ImGuiTableColumnFlags_IndentEnable : ImGuiTableColumnFlags_IndentDisable;
+
+ // Alignment
+ //if ((flags & ImGuiTableColumnFlags_AlignMask_) == 0)
+ // flags |= ImGuiTableColumnFlags_AlignCenter;
+ //IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_AlignMask_)); // Check that only 1 of each set is used.
+
+ // Preserve status flags
+ column->Flags = flags | (column->Flags & ImGuiTableColumnFlags_StatusMask_);
+
+ // Build an ordered list of available sort directions
+ column->SortDirectionsAvailCount = column->SortDirectionsAvailMask = column->SortDirectionsAvailList = 0;
+ if (table->Flags & ImGuiTableFlags_Sortable)
+ {
+ int count = 0, mask = 0, list = 0;
+ if ((flags & ImGuiTableColumnFlags_PreferSortAscending) != 0 && (flags & ImGuiTableColumnFlags_NoSortAscending) == 0) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << (count << 1); count++; }
+ if ((flags & ImGuiTableColumnFlags_PreferSortDescending) != 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; }
+ if ((flags & ImGuiTableColumnFlags_PreferSortAscending) == 0 && (flags & ImGuiTableColumnFlags_NoSortAscending) == 0) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << (count << 1); count++; }
+ if ((flags & ImGuiTableColumnFlags_PreferSortDescending) == 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; }
+ if ((table->Flags & ImGuiTableFlags_SortTristate) || count == 0) { mask |= 1 << ImGuiSortDirection_None; count++; }
+ column->SortDirectionsAvailList = (ImU8)list;
+ column->SortDirectionsAvailMask = (ImU8)mask;
+ column->SortDirectionsAvailCount = (ImU8)count;
+ ImGui::TableFixColumnSortDirection(table, column);
+ }
+}
+
+// Layout columns for the frame. This is in essence the followup to BeginTable().
+// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first.
+// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns.
+// Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns?
+void ImGui::TableUpdateLayout(ImGuiTable* table)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(table->IsLayoutLocked == false);
+
+ const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
+ table->IsDefaultDisplayOrder = true;
+ table->ColumnsEnabledCount = 0;
+ table->EnabledMaskByIndex = 0x00;
+ table->EnabledMaskByDisplayOrder = 0x00;
+ table->LeftMostEnabledColumn = -1;
+ table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
+
+ // [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns. Count fixed/stretch columns.
+ // Process columns in their visible orders as we are building the Prev/Next indices.
+ int count_fixed = 0; // Number of columns that have fixed sizing policies
+ int count_stretch = 0; // Number of columns that have stretch sizing policies
+ int prev_visible_column_idx = -1;
+ bool has_auto_fit_request = false;
+ bool has_resizable = false;
+ float stretch_sum_width_auto = 0.0f;
+ float fixed_max_width_auto = 0.0f;
+ for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
+ {
+ const int column_n = table->DisplayOrderToIndex[order_n];
+ if (column_n != order_n)
+ table->IsDefaultDisplayOrder = false;
+ ImGuiTableColumn* column = &table->Columns[column_n];
+
+ // Clear column setup if not submitted by user. Currently we make it mandatory to call TableSetupColumn() every frame.
+ // It would easily work without but we're not ready to guarantee it since e.g. names need resubmission anyway.
+ // We take a slight shortcut but in theory we could be calling TableSetupColumn() here with dummy values, it should yield the same effect.
+ if (table->DeclColumnsCount <= column_n)
+ {
+ TableSetupColumnFlags(table, column, ImGuiTableColumnFlags_None);
+ column->NameOffset = -1;
+ column->UserID = 0;
+ column->InitStretchWeightOrWidth = -1.0f;
+ }
+
+ // Update Enabled state, mark settings and sort specs dirty
+ if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide))
+ column->IsUserEnabledNextFrame = true;
+ if (column->IsUserEnabled != column->IsUserEnabledNextFrame)
+ {
+ column->IsUserEnabled = column->IsUserEnabledNextFrame;
+ table->IsSettingsDirty = true;
+ }
+ column->IsEnabled = column->IsUserEnabled && (column->Flags & ImGuiTableColumnFlags_Disabled) == 0;
+
+ if (column->SortOrder != -1 && !column->IsEnabled)
+ table->IsSortSpecsDirty = true;
+ if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti))
+ table->IsSortSpecsDirty = true;
+
+ // Auto-fit unsized columns
+ const bool start_auto_fit = (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? (column->WidthRequest < 0.0f) : (column->StretchWeight < 0.0f);
+ if (start_auto_fit)
+ column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames
+
+ if (!column->IsEnabled)
+ {
+ column->IndexWithinEnabledSet = -1;
+ continue;
+ }
+
+ // Mark as enabled and link to previous/next enabled column
+ column->PrevEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx;
+ column->NextEnabledColumn = -1;
+ if (prev_visible_column_idx != -1)
+ table->Columns[prev_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n;
+ else
+ table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n;
+ column->IndexWithinEnabledSet = table->ColumnsEnabledCount++;
+ table->EnabledMaskByIndex |= (ImU64)1 << column_n;
+ table->EnabledMaskByDisplayOrder |= (ImU64)1 << column->DisplayOrder;
+ prev_visible_column_idx = column_n;
+ IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
+
+ // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
+ // Combine width from regular rows + width from headers unless requested not to.
+ if (!column->IsPreserveWidthAuto)
+ column->WidthAuto = TableGetColumnWidthAuto(table, column);
+
+ // Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto)
+ const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0;
+ if (column_is_resizable)
+ has_resizable = true;
+ if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f && !column_is_resizable)
+ column->WidthAuto = column->InitStretchWeightOrWidth;
+
+ if (column->AutoFitQueue != 0x00)
+ has_auto_fit_request = true;
+ if (column->Flags & ImGuiTableColumnFlags_WidthStretch)
+ {
+ stretch_sum_width_auto += column->WidthAuto;
+ count_stretch++;
+ }
+ else
+ {
+ fixed_max_width_auto = ImMax(fixed_max_width_auto, column->WidthAuto);
+ count_fixed++;
+ }
+ }
+ if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
+ table->IsSortSpecsDirty = true;
+ table->RightMostEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx;
+ IM_ASSERT(table->LeftMostEnabledColumn >= 0 && table->RightMostEnabledColumn >= 0);
+
+ // [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible
+ // to avoid the column fitting having to wait until the first visible frame of the child container (may or not be a good thing).
+ // FIXME-TABLE: for always auto-resizing columns may not want to do that all the time.
+ if (has_auto_fit_request && table->OuterWindow != table->InnerWindow)
+ table->InnerWindow->SkipItems = false;
+ if (has_auto_fit_request)
+ table->IsSettingsDirty = true;
+
+ // [Part 3] Fix column flags and record a few extra information.
+ float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding.
+ float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns.
+ table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
+ continue;
+ ImGuiTableColumn* column = &table->Columns[column_n];
+
+ const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0;
+ if (column->Flags & ImGuiTableColumnFlags_WidthFixed)
+ {
+ // Apply same widths policy
+ float width_auto = column->WidthAuto;
+ if (table_sizing_policy == ImGuiTableFlags_SizingFixedSame && (column->AutoFitQueue != 0x00 || !column_is_resizable))
+ width_auto = fixed_max_width_auto;
+
+ // Apply automatic width
+ // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
+ if (column->AutoFitQueue != 0x00)
+ column->WidthRequest = width_auto;
+ else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)))
+ column->WidthRequest = width_auto;
+
+ // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
+ // (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
+ // large height (= first frame scrollbar display very off + clipper would skip lots of items).
+ // This is merely making the side-effect less extreme, but doesn't properly fixes it.
+ // FIXME: Move this to ->WidthGiven to avoid temporary lossyless?
+ // FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller.
+ if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto)
+ column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale?
+ sum_width_requests += column->WidthRequest;
+ }
+ else
+ {
+ // Initialize stretch weight
+ if (column->AutoFitQueue != 0x00 || column->StretchWeight < 0.0f || !column_is_resizable)
+ {
+ if (column->InitStretchWeightOrWidth > 0.0f)
+ column->StretchWeight = column->InitStretchWeightOrWidth;
+ else if (table_sizing_policy == ImGuiTableFlags_SizingStretchProp)
+ column->StretchWeight = (column->WidthAuto / stretch_sum_width_auto) * count_stretch;
+ else
+ column->StretchWeight = 1.0f;
+ }
+
+ stretch_sum_weights += column->StretchWeight;
+ if (table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder > column->DisplayOrder)
+ table->LeftMostStretchedColumn = (ImGuiTableColumnIdx)column_n;
+ if (table->RightMostStretchedColumn == -1 || table->Columns[table->RightMostStretchedColumn].DisplayOrder < column->DisplayOrder)
+ table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n;
+ }
+ column->IsPreserveWidthAuto = false;
+ sum_width_requests += table->CellPaddingX * 2.0f;
+ }
+ table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed;
+
+ // [Part 4] Apply final widths based on requested widths
+ const ImRect work_rect = table->WorkRect;
+ const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
+ const float width_avail = ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth();
+ const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests;
+ float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
+ table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
+ continue;
+ ImGuiTableColumn* column = &table->Columns[column_n];
+
+ // Allocate width for stretched/weighted columns (StretchWeight gets converted into WidthRequest)
+ if (column->Flags & ImGuiTableColumnFlags_WidthStretch)
+ {
+ float weight_ratio = column->StretchWeight / stretch_sum_weights;
+ column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, table->MinColumnWidth) + 0.01f);
+ width_remaining_for_stretched_columns -= column->WidthRequest;
+ }
+
+ // [Resize Rule 1] The right-most Visible column is not resizable if there is at least one Stretch column
+ // See additional comments in TableSetColumnWidth().
+ if (column->NextEnabledColumn == -1 && table->LeftMostStretchedColumn != -1)
+ column->Flags |= ImGuiTableColumnFlags_NoDirectResize_;
+
+ // Assign final width, record width in case we will need to shrink
+ column->WidthGiven = ImFloor(ImMax(column->WidthRequest, table->MinColumnWidth));
+ table->ColumnsGivenWidth += column->WidthGiven;
+ }
+
+ // [Part 5] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
+ // Using right-to-left distribution (more likely to match resizing cursor).
+ if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths))
+ for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--)
+ {
+ if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
+ continue;
+ ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]];
+ if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch))
+ continue;
+ column->WidthRequest += 1.0f;
+ column->WidthGiven += 1.0f;
+ width_remaining_for_stretched_columns -= 1.0f;
+ }
+
+ table->HoveredColumnBody = -1;
+ table->HoveredColumnBorder = -1;
+ const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight));
+ const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0);
+
+ // [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
+ // Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping.
+ int visible_n = 0;
+ bool offset_x_frozen = (table->FreezeColumnsCount > 0);
+ float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
+ ImRect host_clip_rect = table->InnerClipRect;
+ //host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2;
+ table->VisibleMaskByIndex = 0x00;
+ table->RequestOutputMaskByIndex = 0x00;
+ for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
+ {
+ const int column_n = table->DisplayOrderToIndex[order_n];
+ ImGuiTableColumn* column = &table->Columns[column_n];
+
+ column->NavLayerCurrent = (ImS8)((table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main);
+
+ if (offset_x_frozen && table->FreezeColumnsCount == visible_n)
+ {
+ offset_x += work_rect.Min.x - table->OuterRect.Min.x;
+ offset_x_frozen = false;
+ }
+
+ // Clear status flags
+ column->Flags &= ~ImGuiTableColumnFlags_StatusMask_;
+
+ if ((table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)) == 0)
+ {
+ // Hidden column: clear a few fields and we are done with it for the remainder of the function.
+ // We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper.
+ column->MinX = column->MaxX = column->WorkMinX = column->ClipRect.Min.x = column->ClipRect.Max.x = offset_x;
+ column->WidthGiven = 0.0f;
+ column->ClipRect.Min.y = work_rect.Min.y;
+ column->ClipRect.Max.y = FLT_MAX;
+ column->ClipRect.ClipWithFull(host_clip_rect);
+ column->IsVisibleX = column->IsVisibleY = column->IsRequestOutput = false;
+ column->IsSkipItems = true;
+ column->ItemWidth = 1.0f;
+ continue;
+ }
+
+ // Detect hovered column
+ if (is_hovering_table && g.IO.MousePos.x >= column->ClipRect.Min.x && g.IO.MousePos.x < column->ClipRect.Max.x)
+ table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n;
+
+ // Lock start position
+ column->MinX = offset_x;
+
+ // Lock width based on start position and minimum/maximum width for this position
+ float max_width = TableGetMaxColumnWidth(table, column_n);
+ column->WidthGiven = ImMin(column->WidthGiven, max_width);
+ column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth));
+ column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
+
+ // Lock other positions
+ // - ClipRect.Min.x: Because merging draw commands doesn't compare min boundaries, we make ClipRect.Min.x match left bounds to be consistent regardless of merging.
+ // - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column.
+ // - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow.
+ // - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter.
+ column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
+ column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
+ column->ItemWidth = ImFloor(column->WidthGiven * 0.65f);
+ column->ClipRect.Min.x = column->MinX;
+ column->ClipRect.Min.y = work_rect.Min.y;
+ column->ClipRect.Max.x = column->MaxX; //column->WorkMaxX;
+ column->ClipRect.Max.y = FLT_MAX;
+ column->ClipRect.ClipWithFull(host_clip_rect);
+
+ // Mark column as Clipped (not in sight)
+ // Note that scrolling tables (where inner_window != outer_window) handle Y clipped earlier in BeginTable() so IsVisibleY really only applies to non-scrolling tables.
+ // FIXME-TABLE: Because InnerClipRect.Max.y is conservatively ==outer_window->ClipRect.Max.y, we never can mark columns _Above_ the scroll line as not IsVisibleY.
+ // Taking advantage of LastOuterHeight would yield good results there...
+ // FIXME-TABLE: Y clipping is disabled because it effectively means not submitting will reduce contents width which is fed to outer_window->DC.CursorMaxPos.x,
+ // and this may be used (e.g. typically by outer_window using AlwaysAutoResize or outer_window's horizontal scrollbar, but could be something else).
+ // Possible solution to preserve last known content width for clipped column. Test 'table_reported_size' fails when enabling Y clipping and window is resized small.
+ column->IsVisibleX = (column->ClipRect.Max.x > column->ClipRect.Min.x);
+ column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y);
+ const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY;
+ if (is_visible)
+ table->VisibleMaskByIndex |= ((ImU64)1 << column_n);
+
+ // Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output.
+ column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0;
+ if (column->IsRequestOutput)
+ table->RequestOutputMaskByIndex |= ((ImU64)1 << column_n);
+
+ // Mark column as SkipItems (ignoring all items/layout)
+ column->IsSkipItems = !column->IsEnabled || table->HostSkipItems;
+ if (column->IsSkipItems)
+ IM_ASSERT(!is_visible);
+
+ // Update status flags
+ column->Flags |= ImGuiTableColumnFlags_IsEnabled;
+ if (is_visible)
+ column->Flags |= ImGuiTableColumnFlags_IsVisible;
+ if (column->SortOrder != -1)
+ column->Flags |= ImGuiTableColumnFlags_IsSorted;
+ if (table->HoveredColumnBody == column_n)
+ column->Flags |= ImGuiTableColumnFlags_IsHovered;
+
+ // Alignment
+ // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in
+ // many cases (to be able to honor this we might be able to store a log of cells width, per row, for
+ // visible rows, but nav/programmatic scroll would have visible artifacts.)
+ //if (column->Flags & ImGuiTableColumnFlags_AlignRight)
+ // column->WorkMinX = ImMax(column->WorkMinX, column->MaxX - column->ContentWidthRowsUnfrozen);
+ //else if (column->Flags & ImGuiTableColumnFlags_AlignCenter)
+ // column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f);
+
+ // Reset content width variables
+ column->ContentMaxXFrozen = column->ContentMaxXUnfrozen = column->WorkMinX;
+ column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX;
+
+ // Don't decrement auto-fit counters until container window got a chance to submit its items
+ if (table->HostSkipItems == false)
+ {
+ column->AutoFitQueue >>= 1;
+ column->CannotSkipItemsQueue >>= 1;
+ }
+
+ if (visible_n < table->FreezeColumnsCount)
+ host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x);
+
+ offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
+ visible_n++;
+ }
+
+ // [Part 7] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it)
+ // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either
+ // because of using _WidthAuto/_WidthStretch). This will hide the resizing option from the context menu.
+ const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
+ if (is_hovering_table && table->HoveredColumnBody == -1)
+ {
+ if (g.IO.MousePos.x >= unused_x1)
+ table->HoveredColumnBody = (ImGuiTableColumnIdx)table->ColumnsCount;
+ }
+ if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable))
+ table->Flags &= ~ImGuiTableFlags_Resizable;
+
+ // [Part 8] Lock actual OuterRect/WorkRect right-most position.
+ // This is done late to handle the case of fixed-columns tables not claiming more widths that they need.
+ // Because of this we are careful with uses of WorkRect and InnerClipRect before this point.
+ if (table->RightMostStretchedColumn != -1)
+ table->Flags &= ~ImGuiTableFlags_NoHostExtendX;
+ if (table->Flags & ImGuiTableFlags_NoHostExtendX)
+ {
+ table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1;
+ table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1);
+ }
+ table->InnerWindow->ParentWorkRect = table->WorkRect;
+ table->BorderX1 = table->InnerClipRect.Min.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : -1.0f);
+ table->BorderX2 = table->InnerClipRect.Max.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : +1.0f);
+
+ // [Part 9] Allocate draw channels and setup background cliprect
+ TableSetupDrawChannels(table);
+
+ // [Part 10] Hit testing on borders
+ if (table->Flags & ImGuiTableFlags_Resizable)
+ TableUpdateBorders(table);
+ table->LastFirstRowHeight = 0.0f;
+ table->IsLayoutLocked = true;
+ table->IsUsingHeaders = false;
+
+ // [Part 11] Context menu
+ if (table->IsContextPopupOpen && table->InstanceCurrent == table->InstanceInteracted)
+ {
+ const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID);
+ if (BeginPopupEx(context_menu_id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings))
+ {
+ TableDrawContextMenu(table);
+ EndPopup();
+ }
+ else
+ {
+ table->IsContextPopupOpen = false;
+ }
+ }
+
+ // [Part 13] Sanitize and build sort specs before we have a change to use them for display.
+ // This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change)
+ if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable))
+ TableSortSpecsBuild(table);
+
+ // Initial state
+ ImGuiWindow* inner_window = table->InnerWindow;
+ if (table->Flags & ImGuiTableFlags_NoClip)
+ table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
+ else
+ inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false);
+}
+
+// Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
+// - Set table->HoveredColumnBorder with a short delay/timer to reduce feedback noise
+// - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize widgets
+// overlapping the same area.
+void ImGui::TableUpdateBorders(ImGuiTable* table)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(table->Flags & ImGuiTableFlags_Resizable);
+
+ // At this point OuterRect height may be zero or under actual final height, so we rely on temporal coherency and
+ // use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not
+ // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
+ // Actual columns highlight/render will be performed in EndTable() and not be affected.
+ const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
+ const float hit_y1 = table->OuterRect.Min.y;
+ const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table->LastOuterHeight);
+ const float hit_y2_head = hit_y1 + table->LastFirstRowHeight;
+
+ for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
+ {
+ if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
+ continue;
+
+ const int column_n = table->DisplayOrderToIndex[order_n];
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_))
+ continue;
+
+ // ImGuiTableFlags_NoBordersInBodyUntilResize will be honored in TableDrawBorders()
+ const float border_y2_hit = (table->Flags & ImGuiTableFlags_NoBordersInBody) ? hit_y2_head : hit_y2_body;
+ if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false)
+ continue;
+
+ if (!column->IsVisibleX && table->LastResizedColumn != column_n)
+ continue;
+
+ ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent);
+ ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit);
+ //GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100));
+ KeepAliveID(column_id);
+
+ bool hovered = false, held = false;
+ bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_NoNavFocus);
+ if (pressed && IsMouseDoubleClicked(0))
+ {
+ TableSetColumnWidthAutoSingle(table, column_n);
+ ClearActiveID();
+ held = hovered = false;
+ }
+ if (held)
+ {
+ if (table->LastResizedColumn == -1)
+ table->ResizeLockMinContentsX2 = table->RightMostEnabledColumn != -1 ? table->Columns[table->RightMostEnabledColumn].MaxX : -FLT_MAX;
+ table->ResizedColumn = (ImGuiTableColumnIdx)column_n;
+ table->InstanceInteracted = table->InstanceCurrent;
+ }
+ if ((hovered && g.HoveredIdTimer > TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER) || held)
+ {
+ table->HoveredColumnBorder = (ImGuiTableColumnIdx)column_n;
+ SetMouseCursor(ImGuiMouseCursor_ResizeEW);
+ }
+ }
+}
+
+void ImGui::EndTable()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!");
+
+ // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some
+ // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border)
+ //IM_ASSERT(table->IsLayoutLocked && "Table unused: never called TableNextRow(), is that the intent?");
+
+ // If the user never got to call TableNextRow() or TableNextColumn(), we call layout ourselves to ensure all our
+ // code paths are consistent (instead of just hoping that TableBegin/TableEnd will work), get borders drawn, etc.
+ if (!table->IsLayoutLocked)
+ TableUpdateLayout(table);
+
+ const ImGuiTableFlags flags = table->Flags;
+ ImGuiWindow* inner_window = table->InnerWindow;
+ ImGuiWindow* outer_window = table->OuterWindow;
+ ImGuiTableTempData* temp_data = table->TempData;
+ IM_ASSERT(inner_window == g.CurrentWindow);
+ IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
+
+ if (table->IsInsideRow)
+ TableEndRow(table);
+
+ // Context menu in columns body
+ if (flags & ImGuiTableFlags_ContextMenuInBody)
+ if (table->HoveredColumnBody != -1 && !IsAnyItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
+ TableOpenContextMenu((int)table->HoveredColumnBody);
+
+ // Finalize table height
+ inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
+ inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
+ inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
+ const float inner_content_max_y = table->RowPosY2;
+ IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y);
+ if (inner_window != outer_window)
+ inner_window->DC.CursorMaxPos.y = inner_content_max_y;
+ else if (!(flags & ImGuiTableFlags_NoHostExtendY))
+ table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height
+ table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y);
+ table->LastOuterHeight = table->OuterRect.GetHeight();
+
+ // Setup inner scrolling range
+ // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y,
+ // but since the later is likely to be impossible to do we'd rather update both axises together.
+ if (table->Flags & ImGuiTableFlags_ScrollX)
+ {
+ const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
+ float max_pos_x = table->InnerWindow->DC.CursorMaxPos.x;
+ if (table->RightMostEnabledColumn != -1)
+ max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
+ if (table->ResizedColumn != -1)
+ max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
+ table->InnerWindow->DC.CursorMaxPos.x = max_pos_x;
+ }
+
+ // Pop clipping rect
+ if (!(flags & ImGuiTableFlags_NoClip))
+ inner_window->DrawList->PopClipRect();
+ inner_window->ClipRect = inner_window->DrawList->_ClipRectStack.back();
+
+ // Draw borders
+ if ((flags & ImGuiTableFlags_Borders) != 0)
+ TableDrawBorders(table);
+
+#if 0
+ // Strip out dummy channel draw calls
+ // We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out)
+ // Pros: remove draw calls which will have no effect. since they'll have zero-size cliprect they may be early out anyway.
+ // Cons: making it harder for users watching metrics/debugger to spot the wasted vertices.
+ if (table->DummyDrawChannel != (ImGuiTableColumnIdx)-1)
+ {
+ ImDrawChannel* dummy_channel = &table->DrawSplitter._Channels[table->DummyDrawChannel];
+ dummy_channel->_CmdBuffer.resize(0);
+ dummy_channel->_IdxBuffer.resize(0);
+ }
+#endif
+
+ // Flatten channels and merge draw calls
+ ImDrawListSplitter* splitter = table->DrawSplitter;
+ splitter->SetCurrentChannel(inner_window->DrawList, 0);
+ if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
+ TableMergeDrawChannels(table);
+ splitter->Merge(inner_window->DrawList);
+
+ // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable()
+ const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
+ table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ if (table->EnabledMaskByIndex & ((ImU64)1 << column_n))
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize))
+ table->ColumnsAutoFitWidth += column->WidthRequest;
+ else
+ table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, column);
+ }
+
+ // Update scroll
+ if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window)
+ {
+ inner_window->Scroll.x = 0.0f;
+ }
+ else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent)
+ {
+ // When releasing a column being resized, scroll to keep the resulting column in sight
+ const float neighbor_width_to_keep_visible = table->MinColumnWidth + table->CellPaddingX * 2.0f;
+ ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn];
+ if (column->MaxX < table->InnerClipRect.Min.x)
+ SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x - neighbor_width_to_keep_visible, 1.0f);
+ else if (column->MaxX > table->InnerClipRect.Max.x)
+ SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x + neighbor_width_to_keep_visible, 1.0f);
+ }
+
+ // Apply resizing/dragging at the end of the frame
+ if (table->ResizedColumn != -1 && table->InstanceCurrent == table->InstanceInteracted)
+ {
+ ImGuiTableColumn* column = &table->Columns[table->ResizedColumn];
+ const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + TABLE_RESIZE_SEPARATOR_HALF_THICKNESS);
+ const float new_width = ImFloor(new_x2 - column->MinX - table->CellSpacingX1 - table->CellPaddingX * 2.0f);
+ table->ResizedColumnNextWidth = new_width;
+ }
+
+ // Pop from id stack
+ IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
+ IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
+ PopID();
+
+ // Restore window data that we modified
+ const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos;
+ inner_window->WorkRect = temp_data->HostBackupWorkRect;
+ inner_window->ParentWorkRect = temp_data->HostBackupParentWorkRect;
+ inner_window->SkipItems = table->HostSkipItems;
+ outer_window->DC.CursorPos = table->OuterRect.Min;
+ outer_window->DC.ItemWidth = temp_data->HostBackupItemWidth;
+ outer_window->DC.ItemWidthStack.Size = temp_data->HostBackupItemWidthStackSize;
+ outer_window->DC.ColumnsOffset = temp_data->HostBackupColumnsOffset;
+
+ // Layout in outer window
+ // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding
+ // CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414)
+ if (inner_window != outer_window)
+ {
+ EndChild();
+ }
+ else
+ {
+ ItemSize(table->OuterRect.GetSize());
+ ItemAdd(table->OuterRect, 0);
+ }
+
+ // Override declared contents width/height to enable auto-resize while not needlessly adding a scrollbar
+ if (table->Flags & ImGuiTableFlags_NoHostExtendX)
+ {
+ // FIXME-TABLE: Could we remove this section?
+ // ColumnsAutoFitWidth may be one frame ahead here since for Fixed+NoResize is calculated from latest contents
+ IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0);
+ outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth);
+ }
+ else if (temp_data->UserOuterSize.x <= 0.0f)
+ {
+ const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f;
+ outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
+ outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
+ }
+ else
+ {
+ outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x);
+ }
+ if (temp_data->UserOuterSize.y <= 0.0f)
+ {
+ const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f;
+ outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
+ outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y));
+ }
+ else
+ {
+ // OuterRect.Max.y may already have been pushed downward from the initial value (unless ImGuiTableFlags_NoHostExtendY is set)
+ outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, table->OuterRect.Max.y);
+ }
+
+ // Save settings
+ if (table->IsSettingsDirty)
+ TableSaveSettings(table);
+ table->IsInitializing = false;
+
+ // Clear or restore current table, if any
+ IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
+ IM_ASSERT(g.TablesTempDataStacked > 0);
+ temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
+ g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
+ if (g.CurrentTable)
+ {
+ g.CurrentTable->TempData = temp_data;
+ g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter;
+ }
+ outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
+}
+
+// See "COLUMN SIZING POLICIES" comments at the top of this file
+// If (init_width_or_weight <= 0.0f) it is ignored
+void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!");
+ IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!");
+ IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
+ if (table->DeclColumnsCount >= table->ColumnsCount)
+ {
+ IM_ASSERT_USER_ERROR(table->DeclColumnsCount < table->ColumnsCount, "Called TableSetupColumn() too many times!");
+ return;
+ }
+
+ ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];
+ table->DeclColumnsCount++;
+
+ // Assert when passing a width or weight if policy is entirely left to default, to avoid storing width into weight and vice-versa.
+ // Give a grace to users of ImGuiTableFlags_ScrollX.
+ if (table->IsDefaultSizingPolicy && (flags & ImGuiTableColumnFlags_WidthMask_) == 0 && (flags & ImGuiTableFlags_ScrollX) == 0)
+ IM_ASSERT(init_width_or_weight <= 0.0f && "Can only specify width/weight if sizing policy is set explicitly in either Table or Column.");
+
+ // When passing a width automatically enforce WidthFixed policy
+ // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable)
+ if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f)
+ if ((table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || (table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
+ flags |= ImGuiTableColumnFlags_WidthFixed;
+
+ TableSetupColumnFlags(table, column, flags);
+ column->UserID = user_id;
+ flags = column->Flags;
+
+ // Initialize defaults
+ column->InitStretchWeightOrWidth = init_width_or_weight;
+ if (table->IsInitializing)
+ {
+ // Init width or weight
+ if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f)
+ {
+ if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f)
+ column->WidthRequest = init_width_or_weight;
+ if (flags & ImGuiTableColumnFlags_WidthStretch)
+ column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f;
+
+ // Disable auto-fit if an explicit width/weight has been specified
+ if (init_width_or_weight > 0.0f)
+ column->AutoFitQueue = 0x00;
+ }
+
+ // Init default visibility/sort state
+ if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0)
+ column->IsUserEnabled = column->IsUserEnabledNextFrame = false;
+ if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0)
+ {
+ column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs.
+ column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending);
+ }
+ }
+
+ // Store name (append with zero-terminator in contiguous buffer)
+ column->NameOffset = -1;
+ if (label != NULL && label[0] != 0)
+ {
+ column->NameOffset = (ImS16)table->ColumnsNames.size();
+ table->ColumnsNames.append(label, label + strlen(label) + 1);
+ }
+}
+
+// [Public]
+void ImGui::TableSetupScrollFreeze(int columns, int rows)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!");
+ IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!");
+ IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS);
+ IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit
+
+ table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)ImMin(columns, table->ColumnsCount) : 0;
+ table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0;
+ table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0;
+ table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
+ table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
+
+ // Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered.
+ // FIXME-TABLE: This work for preserving 2143 into 21|43. How about 4321 turning into 21|43? (preserve relative order in each section)
+ for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++)
+ {
+ int order_n = table->DisplayOrderToIndex[column_n];
+ if (order_n != column_n && order_n >= table->FreezeColumnsRequest)
+ {
+ ImSwap(table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder, table->Columns[table->DisplayOrderToIndex[column_n]].DisplayOrder);
+ ImSwap(table->DisplayOrderToIndex[order_n], table->DisplayOrderToIndex[column_n]);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// [SECTION] Tables: Simple accessors
+//-----------------------------------------------------------------------------
+// - TableGetColumnCount()
+// - TableGetColumnName()
+// - TableGetColumnName() [Internal]
+// - TableSetColumnEnabled()
+// - TableGetColumnFlags()
+// - TableGetCellBgRect() [Internal]
+// - TableGetColumnResizeID() [Internal]
+// - TableGetHoveredColumn() [Internal]
+// - TableSetBgColor()
+//-----------------------------------------------------------------------------
+
+int ImGui::TableGetColumnCount()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ return table ? table->ColumnsCount : 0;
+}
+
+const char* ImGui::TableGetColumnName(int column_n)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return NULL;
+ if (column_n < 0)
+ column_n = table->CurrentColumn;
+ return TableGetColumnName(table, column_n);
+}
+
+const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n)
+{
+ if (table->IsLayoutLocked == false && column_n >= table->DeclColumnsCount)
+ return ""; // NameOffset is invalid at this point
+ const ImGuiTableColumn* column = &table->Columns[column_n];
+ if (column->NameOffset == -1)
+ return "";
+ return &table->ColumnsNames.Buf[column->NameOffset];
+}
+
+// Change user accessible enabled/disabled state of a column (often perceived as "showing/hiding" from users point of view)
+// Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
+// - Require table to have the ImGuiTableFlags_Hideable flag because we are manipulating user accessible state.
+// - Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable().
+// - For the getter you can test (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled) != 0.
+// - Alternative: the ImGuiTableColumnFlags_Disabled is an overriding/master disable flag which will also hide the column from context menu.
+void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL);
+ if (!table)
+ return;
+ IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above
+ if (column_n < 0)
+ column_n = table->CurrentColumn;
+ IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ column->IsUserEnabledNextFrame = enabled;
+}
+
+// We allow querying for an extra column in order to poll the IsHovered state of the right-most section
+ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return ImGuiTableColumnFlags_None;
+ if (column_n < 0)
+ column_n = table->CurrentColumn;
+ if (column_n == table->ColumnsCount)
+ return (table->HoveredColumnBody == column_n) ? ImGuiTableColumnFlags_IsHovered : ImGuiTableColumnFlags_None;
+ return table->Columns[column_n].Flags;
+}
+
+// Return the cell rectangle based on currently known height.
+// - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations.
+// The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it.
+// - Important: if ImGuiTableFlags_PadOuterX is set but ImGuiTableFlags_PadInnerX is not set, the outer-most left and right
+// columns report a small offset so their CellBgRect can extend up to the outer border.
+ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n)
+{
+ const ImGuiTableColumn* column = &table->Columns[column_n];
+ float x1 = column->MinX;
+ float x2 = column->MaxX;
+ if (column->PrevEnabledColumn == -1)
+ x1 -= table->CellSpacingX1;
+ if (column->NextEnabledColumn == -1)
+ x2 += table->CellSpacingX2;
+ return ImRect(x1, table->RowPosY1, x2, table->RowPosY2);
+}
+
+// Return the resizing ID for the right-side of the given column.
+ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no)
+{
+ IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
+ ImGuiID id = table->ID + 1 + (instance_no * table->ColumnsCount) + column_n;
+ return id;
+}
+
+// Return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
+int ImGui::TableGetHoveredColumn()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return -1;
+ return (int)table->HoveredColumnBody;
+}
+
+void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(target != ImGuiTableBgTarget_None);
+
+ if (color == IM_COL32_DISABLE)
+ color = 0;
+
+ // We cannot draw neither the cell or row background immediately as we don't know the row height at this point in time.
+ switch (target)
+ {
+ case ImGuiTableBgTarget_CellBg:
+ {
+ if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard
+ return;
+ if (column_n == -1)
+ column_n = table->CurrentColumn;
+ if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0)
+ return;
+ if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n)
+ table->RowCellDataCurrent++;
+ ImGuiTableCellData* cell_data = &table->RowCellData[table->RowCellDataCurrent];
+ cell_data->BgColor = color;
+ cell_data->Column = (ImGuiTableColumnIdx)column_n;
+ break;
+ }
+ case ImGuiTableBgTarget_RowBg0:
+ case ImGuiTableBgTarget_RowBg1:
+ {
+ if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard
+ return;
+ IM_ASSERT(column_n == -1);
+ int bg_idx = (target == ImGuiTableBgTarget_RowBg1) ? 1 : 0;
+ table->RowBgColor[bg_idx] = color;
+ break;
+ }
+ default:
+ IM_ASSERT(0);
+ }
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Row changes
+//-------------------------------------------------------------------------
+// - TableGetRowIndex()
+// - TableNextRow()
+// - TableBeginRow() [Internal]
+// - TableEndRow() [Internal]
+//-------------------------------------------------------------------------
+
+// [Public] Note: for row coloring we use ->RowBgColorCounter which is the same value without counting header rows
+int ImGui::TableGetRowIndex()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return 0;
+ return table->CurrentRow;
+}
+
+// [Public] Starts into the first cell of a new row
+void ImGui::TableNextRow(ImGuiTableRowFlags row_flags, float row_min_height)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+
+ if (!table->IsLayoutLocked)
+ TableUpdateLayout(table);
+ if (table->IsInsideRow)
+ TableEndRow(table);
+
+ table->LastRowFlags = table->RowFlags;
+ table->RowFlags = row_flags;
+ table->RowMinHeight = row_min_height;
+ TableBeginRow(table);
+
+ // We honor min_row_height requested by user, but cannot guarantee per-row maximum height,
+ // because that would essentially require a unique clipping rectangle per-cell.
+ table->RowPosY2 += table->CellPaddingY * 2.0f;
+ table->RowPosY2 = ImMax(table->RowPosY2, table->RowPosY1 + row_min_height);
+
+ // Disable output until user calls TableNextColumn()
+ table->InnerWindow->SkipItems = true;
+}
+
+// [Internal] Called by TableNextRow()
+void ImGui::TableBeginRow(ImGuiTable* table)
+{
+ ImGuiWindow* window = table->InnerWindow;
+ IM_ASSERT(!table->IsInsideRow);
+
+ // New row
+ table->CurrentRow++;
+ table->CurrentColumn = -1;
+ table->RowBgColor[0] = table->RowBgColor[1] = IM_COL32_DISABLE;
+ table->RowCellDataCurrent = -1;
+ table->IsInsideRow = true;
+
+ // Begin frozen rows
+ float next_y1 = table->RowPosY2;
+ if (table->CurrentRow == 0 && table->FreezeRowsCount > 0)
+ next_y1 = window->DC.CursorPos.y = table->OuterRect.Min.y;
+
+ table->RowPosY1 = table->RowPosY2 = next_y1;
+ table->RowTextBaseline = 0.0f;
+ table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent
+ window->DC.PrevLineTextBaseOffset = 0.0f;
+ window->DC.CursorMaxPos.y = next_y1;
+
+ // Making the header BG color non-transparent will allow us to overlay it multiple times when handling smooth dragging.
+ if (table->RowFlags & ImGuiTableRowFlags_Headers)
+ {
+ TableSetBgColor(ImGuiTableBgTarget_RowBg0, GetColorU32(ImGuiCol_TableHeaderBg));
+ if (table->CurrentRow == 0)
+ table->IsUsingHeaders = true;
+ }
+}
+
+// [Internal] Called by TableNextRow()
+void ImGui::TableEndRow(ImGuiTable* table)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(window == table->InnerWindow);
+ IM_ASSERT(table->IsInsideRow);
+
+ if (table->CurrentColumn != -1)
+ TableEndCell(table);
+
+ // Logging
+ if (g.LogEnabled)
+ LogRenderedText(NULL, "|");
+
+ // Position cursor at the bottom of our row so it can be used for e.g. clipping calculation. However it is
+ // likely that the next call to TableBeginCell() will reposition the cursor to take account of vertical padding.
+ window->DC.CursorPos.y = table->RowPosY2;
+
+ // Row background fill
+ const float bg_y1 = table->RowPosY1;
+ const float bg_y2 = table->RowPosY2;
+ const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount);
+ const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest);
+ if (table->CurrentRow == 0)
+ table->LastFirstRowHeight = bg_y2 - bg_y1;
+
+ const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y);
+ if (is_visible)
+ {
+ // Decide of background color for the row
+ ImU32 bg_col0 = 0;
+ ImU32 bg_col1 = 0;
+ if (table->RowBgColor[0] != IM_COL32_DISABLE)
+ bg_col0 = table->RowBgColor[0];
+ else if (table->Flags & ImGuiTableFlags_RowBg)
+ bg_col0 = GetColorU32((table->RowBgColorCounter & 1) ? ImGuiCol_TableRowBgAlt : ImGuiCol_TableRowBg);
+ if (table->RowBgColor[1] != IM_COL32_DISABLE)
+ bg_col1 = table->RowBgColor[1];
+
+ // Decide of top border color
+ ImU32 border_col = 0;
+ const float border_size = TABLE_BORDER_SIZE;
+ if (table->CurrentRow > 0 || table->InnerWindow == table->OuterWindow)
+ if (table->Flags & ImGuiTableFlags_BordersInnerH)
+ border_col = (table->LastRowFlags & ImGuiTableRowFlags_Headers) ? table->BorderColorStrong : table->BorderColorLight;
+
+ const bool draw_cell_bg_color = table->RowCellDataCurrent >= 0;
+ const bool draw_strong_bottom_border = unfreeze_rows_actual;
+ if ((bg_col0 | bg_col1 | border_col) != 0 || draw_strong_bottom_border || draw_cell_bg_color)
+ {
+ // In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is
+ // always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
+ if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
+ window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4();
+ table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
+ }
+
+ // Draw row background
+ // We soft/cpu clip this so all backgrounds and borders can share the same clipping rectangle
+ if (bg_col0 || bg_col1)
+ {
+ ImRect row_rect(table->WorkRect.Min.x, bg_y1, table->WorkRect.Max.x, bg_y2);
+ row_rect.ClipWith(table->BgClipRect);
+ if (bg_col0 != 0 && row_rect.Min.y < row_rect.Max.y)
+ window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col0);
+ if (bg_col1 != 0 && row_rect.Min.y < row_rect.Max.y)
+ window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col1);
+ }
+
+ // Draw cell background color
+ if (draw_cell_bg_color)
+ {
+ ImGuiTableCellData* cell_data_end = &table->RowCellData[table->RowCellDataCurrent];
+ for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++)
+ {
+ const ImGuiTableColumn* column = &table->Columns[cell_data->Column];
+ ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column);
+ cell_bg_rect.ClipWith(table->BgClipRect);
+ cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped
+ cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX);
+ window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
+ }
+ }
+
+ // Draw top border
+ if (border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y)
+ window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), border_col, border_size);
+
+ // Draw bottom border at the row unfreezing mark (always strong)
+ if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y)
+ window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size);
+ }
+
+ // End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
+ // We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and
+ // get the new cursor position.
+ if (unfreeze_rows_request)
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ column->NavLayerCurrent = (ImS8)((column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main);
+ }
+ if (unfreeze_rows_actual)
+ {
+ IM_ASSERT(table->IsUnfrozenRows == false);
+ table->IsUnfrozenRows = true;
+
+ // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
+ float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
+ table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
+ table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
+ table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
+ IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
+
+ float row_height = table->RowPosY2 - table->RowPosY1;
+ table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
+ table->RowPosY1 = table->RowPosY2 - row_height;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ column->DrawChannelCurrent = column->DrawChannelUnfrozen;
+ column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y;
+ }
+
+ // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
+ SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect);
+ table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent);
+ }
+
+ if (!(table->RowFlags & ImGuiTableRowFlags_Headers))
+ table->RowBgColorCounter++;
+ table->IsInsideRow = false;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Columns changes
+//-------------------------------------------------------------------------
+// - TableGetColumnIndex()
+// - TableSetColumnIndex()
+// - TableNextColumn()
+// - TableBeginCell() [Internal]
+// - TableEndCell() [Internal]
+//-------------------------------------------------------------------------
+
+int ImGui::TableGetColumnIndex()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return 0;
+ return table->CurrentColumn;
+}
+
+// [Public] Append into a specific column
+bool ImGui::TableSetColumnIndex(int column_n)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return false;
+
+ if (table->CurrentColumn != column_n)
+ {
+ if (table->CurrentColumn != -1)
+ TableEndCell(table);
+ IM_ASSERT(column_n >= 0 && table->ColumnsCount);
+ TableBeginCell(table, column_n);
+ }
+
+ // Return whether the column is visible. User may choose to skip submitting items based on this return value,
+ // however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
+ return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0;
+}
+
+// [Public] Append into the next column, wrap and create a new row when already on last column
+bool ImGui::TableNextColumn()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (!table)
+ return false;
+
+ if (table->IsInsideRow && table->CurrentColumn + 1 < table->ColumnsCount)
+ {
+ if (table->CurrentColumn != -1)
+ TableEndCell(table);
+ TableBeginCell(table, table->CurrentColumn + 1);
+ }
+ else
+ {
+ TableNextRow();
+ TableBeginCell(table, 0);
+ }
+
+ // Return whether the column is visible. User may choose to skip submitting items based on this return value,
+ // however they shouldn't skip submitting for columns that may have the tallest contribution to row height.
+ int column_n = table->CurrentColumn;
+ return (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n)) != 0;
+}
+
+
+// [Internal] Called by TableSetColumnIndex()/TableNextColumn()
+// This is called very frequently, so we need to be mindful of unnecessary overhead.
+// FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns.
+void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
+{
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ ImGuiWindow* window = table->InnerWindow;
+ table->CurrentColumn = column_n;
+
+ // Start position is roughly ~~ CellRect.Min + CellPadding + Indent
+ float start_x = column->WorkMinX;
+ if (column->Flags & ImGuiTableColumnFlags_IndentEnable)
+ start_x += table->RowIndentOffsetX; // ~~ += window.DC.Indent.x - table->HostIndentX, except we locked it for the row.
+
+ window->DC.CursorPos.x = start_x;
+ window->DC.CursorPos.y = table->RowPosY1 + table->CellPaddingY;
+ window->DC.CursorMaxPos.x = window->DC.CursorPos.x;
+ window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT
+ window->DC.CurrLineTextBaseOffset = table->RowTextBaseline;
+ window->DC.NavLayerCurrent = (ImGuiNavLayer)column->NavLayerCurrent;
+
+ window->WorkRect.Min.y = window->DC.CursorPos.y;
+ window->WorkRect.Min.x = column->WorkMinX;
+ window->WorkRect.Max.x = column->WorkMaxX;
+ window->DC.ItemWidth = column->ItemWidth;
+
+ // To allow ImGuiListClipper to function we propagate our row height
+ if (!column->IsEnabled)
+ window->DC.CursorPos.y = ImMax(window->DC.CursorPos.y, table->RowPosY2);
+
+ window->SkipItems = column->IsSkipItems;
+ if (column->IsSkipItems)
+ {
+ ImGuiContext& g = *GImGui;
+ g.LastItemData.ID = 0;
+ g.LastItemData.StatusFlags = 0;
+ }
+
+ if (table->Flags & ImGuiTableFlags_NoClip)
+ {
+ // FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed.
+ table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
+ //IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP);
+ }
+ else
+ {
+ // FIXME-TABLE: Could avoid this if draw channel is dummy channel?
+ SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
+ table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
+ }
+
+ // Logging
+ ImGuiContext& g = *GImGui;
+ if (g.LogEnabled && !column->IsSkipItems)
+ {
+ LogRenderedText(&window->DC.CursorPos, "|");
+ g.LogLinePosY = FLT_MAX;
+ }
+}
+
+// [Internal] Called by TableNextRow()/TableSetColumnIndex()/TableNextColumn()
+void ImGui::TableEndCell(ImGuiTable* table)
+{
+ ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
+ ImGuiWindow* window = table->InnerWindow;
+
+ // Report maximum position so we can infer content size per column.
+ float* p_max_pos_x;
+ if (table->RowFlags & ImGuiTableRowFlags_Headers)
+ p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call
+ else
+ p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
+ *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
+ table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
+ column->ItemWidth = window->DC.ItemWidth;
+
+ // Propagate text baseline for the entire row
+ // FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one.
+ table->RowTextBaseline = ImMax(table->RowTextBaseline, window->DC.PrevLineTextBaseOffset);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Columns width management
+//-------------------------------------------------------------------------
+// - TableGetMaxColumnWidth() [Internal]
+// - TableGetColumnWidthAuto() [Internal]
+// - TableSetColumnWidth()
+// - TableSetColumnWidthAutoSingle() [Internal]
+// - TableSetColumnWidthAutoAll() [Internal]
+// - TableUpdateColumnsWeightFromWidth() [Internal]
+//-------------------------------------------------------------------------
+
+// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
+float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
+{
+ const ImGuiTableColumn* column = &table->Columns[column_n];
+ float max_width = FLT_MAX;
+ const float min_column_distance = table->MinColumnWidth + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2;
+ if (table->Flags & ImGuiTableFlags_ScrollX)
+ {
+ // Frozen columns can't reach beyond visible width else scrolling will naturally break.
+ // (we use DisplayOrder as within a set of multiple frozen column reordering is possible)
+ if (column->DisplayOrder < table->FreezeColumnsRequest)
+ {
+ max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX;
+ max_width = max_width - table->OuterPaddingX - table->CellPaddingX - table->CellSpacingX2;
+ }
+ }
+ else if ((table->Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0)
+ {
+ // If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make
+ // sure they are all visible. Because of this we also know that all of the columns will always fit in
+ // table->WorkRect and therefore in table->InnerRect (because ScrollX is off)
+ // FIXME-TABLE: This is solved incorrectly but also quite a difficult problem to fix as we also want ClipRect width to match.
+ // See "table_width_distrib" and "table_width_keep_visible" tests
+ max_width = table->WorkRect.Max.x - (table->ColumnsEnabledCount - column->IndexWithinEnabledSet - 1) * min_column_distance - column->MinX;
+ //max_width -= table->CellSpacingX1;
+ max_width -= table->CellSpacingX2;
+ max_width -= table->CellPaddingX * 2.0f;
+ max_width -= table->OuterPaddingX;
+ }
+ return max_width;
+}
+
+// Note this is meant to be stored in column->WidthAuto, please generally use the WidthAuto field
+float ImGui::TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column)
+{
+ const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX;
+ const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX;
+ float width_auto = content_width_body;
+ if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth))
+ width_auto = ImMax(width_auto, content_width_headers);
+
+ // Non-resizable fixed columns preserve their requested width
+ if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f)
+ if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize))
+ width_auto = column->InitStretchWeightOrWidth;
+
+ return ImMax(width_auto, table->MinColumnWidth);
+}
+
+// 'width' = inner column width, without padding
+void ImGui::TableSetColumnWidth(int column_n, float width)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL && table->IsLayoutLocked == false);
+ IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
+ ImGuiTableColumn* column_0 = &table->Columns[column_n];
+ float column_0_width = width;
+
+ // Apply constraints early
+ // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
+ IM_ASSERT(table->MinColumnWidth > 0.0f);
+ const float min_width = table->MinColumnWidth;
+ const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n));
+ column_0_width = ImClamp(column_0_width, min_width, max_width);
+ if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width)
+ return;
+
+ //IMGUI_DEBUG_LOG("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthGiven, column_0_width);
+ ImGuiTableColumn* column_1 = (column_0->NextEnabledColumn != -1) ? &table->Columns[column_0->NextEnabledColumn] : NULL;
+
+ // In this surprisingly not simple because of how we support mixing Fixed and multiple Stretch columns.
+ // - All fixed: easy.
+ // - All stretch: easy.
+ // - One or more fixed + one stretch: easy.
+ // - One or more fixed + more than one stretch: tricky.
+ // Qt when manual resize is enabled only support a single _trailing_ stretch column.
+
+ // When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1.
+ // FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user.
+ // Scenarios:
+ // - F1 F2 F3 resize from F1| or F2| --> ok: alter ->WidthRequested of Fixed column. Subsequent columns will be offset.
+ // - F1 F2 F3 resize from F3| --> ok: alter ->WidthRequested of Fixed column. If active, ScrollX extent can be altered.
+ // - F1 F2 W3 resize from F1| or F2| --> ok: alter ->WidthRequested of Fixed column. If active, ScrollX extent can be altered, but it doesn't make much sense as the Stretch column will always be minimal size.
+ // - F1 F2 W3 resize from W3| --> ok: no-op (disabled by Resize Rule 1)
+ // - W1 W2 W3 resize from W1| or W2| --> ok
+ // - W1 W2 W3 resize from W3| --> ok: no-op (disabled by Resize Rule 1)
+ // - W1 F2 F3 resize from F3| --> ok: no-op (disabled by Resize Rule 1)
+ // - W1 F2 resize from F2| --> ok: no-op (disabled by Resize Rule 1)
+ // - W1 W2 F3 resize from W1| or W2| --> ok
+ // - W1 F2 W3 resize from W1| or F2| --> ok
+ // - F1 W2 F3 resize from W2| --> ok
+ // - F1 W3 F2 resize from W3| --> ok
+ // - W1 F2 F3 resize from W1| --> ok: equivalent to resizing |F2. F3 will not move.
+ // - W1 F2 F3 resize from F2| --> ok
+ // All resizes from a Wx columns are locking other columns.
+
+ // Possible improvements:
+ // - W1 W2 W3 resize W1| --> to not be stuck, both W2 and W3 would stretch down. Seems possible to fix. Would be most beneficial to simplify resize of all-weighted columns.
+ // - W3 F1 F2 resize W3| --> to not be stuck past F1|, both F1 and F2 would need to stretch down, which would be lossy or ambiguous. Seems hard to fix.
+
+ // [Resize Rule 1] Can't resize from right of right-most visible column if there is any Stretch column. Implemented in TableUpdateLayout().
+
+ // If we have all Fixed columns OR resizing a Fixed column that doesn't come after a Stretch one, we can do an offsetting resize.
+ // This is the preferred resize path
+ if (column_0->Flags & ImGuiTableColumnFlags_WidthFixed)
+ if (!column_1 || table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder >= column_0->DisplayOrder)
+ {
+ column_0->WidthRequest = column_0_width;
+ table->IsSettingsDirty = true;
+ return;
+ }
+
+ // We can also use previous column if there's no next one (this is used when doing an auto-fit on the right-most stretch column)
+ if (column_1 == NULL)
+ column_1 = (column_0->PrevEnabledColumn != -1) ? &table->Columns[column_0->PrevEnabledColumn] : NULL;
+ if (column_1 == NULL)
+ return;
+
+ // Resizing from right-side of a Stretch column before a Fixed column forward sizing to left-side of fixed column.
+ // (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b)
+ float column_1_width = ImMax(column_1->WidthRequest - (column_0_width - column_0->WidthRequest), min_width);
+ column_0_width = column_0->WidthRequest + column_1->WidthRequest - column_1_width;
+ IM_ASSERT(column_0_width > 0.0f && column_1_width > 0.0f);
+ column_0->WidthRequest = column_0_width;
+ column_1->WidthRequest = column_1_width;
+ if ((column_0->Flags | column_1->Flags) & ImGuiTableColumnFlags_WidthStretch)
+ TableUpdateColumnsWeightFromWidth(table);
+ table->IsSettingsDirty = true;
+}
+
+// Disable clipping then auto-fit, will take 2 frames
+// (we don't take a shortcut for unclipped columns to reduce inconsistencies when e.g. resizing multiple columns)
+void ImGui::TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n)
+{
+ // Single auto width uses auto-fit
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (!column->IsEnabled)
+ return;
+ column->CannotSkipItemsQueue = (1 << 0);
+ table->AutoFitSingleColumn = (ImGuiTableColumnIdx)column_n;
+}
+
+void ImGui::TableSetColumnWidthAutoAll(ImGuiTable* table)
+{
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (!column->IsEnabled && !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) // Cannot reset weight of hidden stretch column
+ continue;
+ column->CannotSkipItemsQueue = (1 << 0);
+ column->AutoFitQueue = (1 << 1);
+ }
+}
+
+void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
+{
+ IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1);
+
+ // Measure existing quantity
+ float visible_weight = 0.0f;
+ float visible_width = 0.0f;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (!column->IsEnabled || !(column->Flags & ImGuiTableColumnFlags_WidthStretch))
+ continue;
+ IM_ASSERT(column->StretchWeight > 0.0f);
+ visible_weight += column->StretchWeight;
+ visible_width += column->WidthRequest;
+ }
+ IM_ASSERT(visible_weight > 0.0f && visible_width > 0.0f);
+
+ // Apply new weights
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (!column->IsEnabled || !(column->Flags & ImGuiTableColumnFlags_WidthStretch))
+ continue;
+ column->StretchWeight = (column->WidthRequest / visible_width) * visible_weight;
+ IM_ASSERT(column->StretchWeight > 0.0f);
+ }
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Drawing
+//-------------------------------------------------------------------------
+// - TablePushBackgroundChannel() [Internal]
+// - TablePopBackgroundChannel() [Internal]
+// - TableSetupDrawChannels() [Internal]
+// - TableMergeDrawChannels() [Internal]
+// - TableDrawBorders() [Internal]
+//-------------------------------------------------------------------------
+
+// Bg2 is used by Selectable (and possibly other widgets) to render to the background.
+// Unlike our Bg0/1 channel which we uses for RowBg/CellBg/Borders and where we guarantee all shapes to be CPU-clipped, the Bg2 channel being widgets-facing will rely on regular ClipRect.
+void ImGui::TablePushBackgroundChannel()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiTable* table = g.CurrentTable;
+
+ // Optimization: avoid SetCurrentChannel() + PushClipRect()
+ table->HostBackupInnerClipRect = window->ClipRect;
+ SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd);
+ table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
+}
+
+void ImGui::TablePopBackgroundChannel()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiTable* table = g.CurrentTable;
+ ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
+
+ // Optimization: avoid PopClipRect() + SetCurrentChannel()
+ SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect);
+ table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
+}
+
+// Allocate draw channels. Called by TableUpdateLayout()
+// - We allocate them following storage order instead of display order so reordering columns won't needlessly
+// increase overall dormant memory cost.
+// - We isolate headers draw commands in their own channels instead of just altering clip rects.
+// This is in order to facilitate merging of draw commands.
+// - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of channels.
+// - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other
+// channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged.
+// - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for
+// horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4).
+// Draw channel allocation (before merging):
+// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call)
+// - Clip --> 2+D+N channels
+// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero)
+// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero)
+// Where D is 1 if any column is clipped or hidden (dummy channel) otherwise 0.
+void ImGui::TableSetupDrawChannels(ImGuiTable* table)
+{
+ const int freeze_row_multiplier = (table->FreezeRowsCount > 0) ? 2 : 1;
+ const int channels_for_row = (table->Flags & ImGuiTableFlags_NoClip) ? 1 : table->ColumnsEnabledCount;
+ const int channels_for_bg = 1 + 1 * freeze_row_multiplier;
+ const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || table->VisibleMaskByIndex != table->EnabledMaskByIndex) ? +1 : 0;
+ const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy;
+ table->DrawSplitter->Split(table->InnerWindow->DrawList, channels_total);
+ table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1);
+ table->Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN;
+ table->Bg2DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)((table->FreezeRowsCount > 0) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN);
+
+ int draw_channel_current = 2;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (column->IsVisibleX && column->IsVisibleY)
+ {
+ column->DrawChannelFrozen = (ImGuiTableDrawChannelIdx)(draw_channel_current);
+ column->DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)(draw_channel_current + (table->FreezeRowsCount > 0 ? channels_for_row + 1 : 0));
+ if (!(table->Flags & ImGuiTableFlags_NoClip))
+ draw_channel_current++;
+ }
+ else
+ {
+ column->DrawChannelFrozen = column->DrawChannelUnfrozen = table->DummyDrawChannel;
+ }
+ column->DrawChannelCurrent = column->DrawChannelFrozen;
+ }
+
+ // Initial draw cmd starts with a BgClipRect that matches the one of its host, to facilitate merge draw commands by default.
+ // All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect.
+ // (This technically isn't part of setting up draw channels, but is reasonably related to be done here)
+ table->BgClipRect = table->InnerClipRect;
+ table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect;
+ table->Bg2ClipRectForDrawCmd = table->HostClipRect;
+ IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
+}
+
+// This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable().
+// For simplicity we call it TableMergeDrawChannels() but in fact it only reorder channels + overwrite ClipRect,
+// actual merging is done by table->DrawSplitter.Merge() which is called right after TableMergeDrawChannels().
+//
+// Columns where the contents didn't stray off their local clip rectangle can be merged. To achieve
+// this we merge their clip rect and make them contiguous in the channel list, so they can be merged
+// by the call to DrawSplitter.Merge() following to the call to this function.
+// We reorder draw commands by arranging them into a maximum of 4 distinct groups:
+//
+// 1 group: 2 groups: 2 groups: 4 groups:
+// [ 0. ] no freeze [ 0. ] row freeze [ 01 ] col freeze [ 01 ] row+col freeze
+// [ .. ] or no scroll [ 2. ] and v-scroll [ .. ] and h-scroll [ 23 ] and v+h-scroll
+//
+// Each column itself can use 1 channel (row freeze disabled) or 2 channels (row freeze enabled).
+// When the contents of a column didn't stray off its limit, we move its channels into the corresponding group
+// based on its position (within frozen rows/columns groups or not).
+// At the end of the operation our 1-4 groups will each have a ImDrawCmd using the same ClipRect.
+// This function assume that each column are pointing to a distinct draw channel,
+// otherwise merge_group->ChannelsCount will not match set bit count of merge_group->ChannelsMask.
+//
+// Column channels will not be merged into one of the 1-4 groups in the following cases:
+// - The contents stray off its clipping rectangle (we only compare the MaxX value, not the MinX value).
+// Direct ImDrawList calls won't be taken into account by default, if you use them make sure the ImGui:: bounds
+// matches, by e.g. calling SetCursorScreenPos().
+// - The channel uses more than one draw command itself. We drop all our attempt at merging stuff here..
+// we could do better but it's going to be rare and probably not worth the hassle.
+// Columns for which the draw channel(s) haven't been merged with other will use their own ImDrawCmd.
+//
+// This function is particularly tricky to understand.. take a breath.
+void ImGui::TableMergeDrawChannels(ImGuiTable* table)
+{
+ ImGuiContext& g = *GImGui;
+ ImDrawListSplitter* splitter = table->DrawSplitter;
+ const bool has_freeze_v = (table->FreezeRowsCount > 0);
+ const bool has_freeze_h = (table->FreezeColumnsCount > 0);
+ IM_ASSERT(splitter->_Current == 0);
+
+ // Track which groups we are going to attempt to merge, and which channels goes into each group.
+ struct MergeGroup
+ {
+ ImRect ClipRect;
+ int ChannelsCount;
+ ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask;
+
+ MergeGroup() { ChannelsCount = 0; }
+ };
+ int merge_group_mask = 0x00;
+ MergeGroup merge_groups[4];
+
+ // 1. Scan channels and take note of those which can be merged
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0)
+ continue;
+ ImGuiTableColumn* column = &table->Columns[column_n];
+
+ const int merge_group_sub_count = has_freeze_v ? 2 : 1;
+ for (int merge_group_sub_n = 0; merge_group_sub_n < merge_group_sub_count; merge_group_sub_n++)
+ {
+ const int channel_no = (merge_group_sub_n == 0) ? column->DrawChannelFrozen : column->DrawChannelUnfrozen;
+
+ // Don't attempt to merge if there are multiple draw calls within the column
+ ImDrawChannel* src_channel = &splitter->_Channels[channel_no];
+ if (src_channel->_CmdBuffer.Size > 0 && src_channel->_CmdBuffer.back().ElemCount == 0)
+ src_channel->_CmdBuffer.pop_back();
+ if (src_channel->_CmdBuffer.Size != 1)
+ continue;
+
+ // Find out the width of this merge group and check if it will fit in our column
+ // (note that we assume that rendering didn't stray on the left direction. we should need a CursorMinPos to detect it)
+ if (!(column->Flags & ImGuiTableColumnFlags_NoClip))
+ {
+ float content_max_x;
+ if (!has_freeze_v)
+ content_max_x = ImMax(column->ContentMaxXUnfrozen, column->ContentMaxXHeadersUsed); // No row freeze
+ else if (merge_group_sub_n == 0)
+ content_max_x = ImMax(column->ContentMaxXFrozen, column->ContentMaxXHeadersUsed); // Row freeze: use width before freeze
+ else
+ content_max_x = column->ContentMaxXUnfrozen; // Row freeze: use width after freeze
+ if (content_max_x > column->ClipRect.Max.x)
+ continue;
+ }
+
+ const int merge_group_n = (has_freeze_h && column_n < table->FreezeColumnsCount ? 0 : 1) + (has_freeze_v && merge_group_sub_n == 0 ? 0 : 2);
+ IM_ASSERT(channel_no < IMGUI_TABLE_MAX_DRAW_CHANNELS);
+ MergeGroup* merge_group = &merge_groups[merge_group_n];
+ if (merge_group->ChannelsCount == 0)
+ merge_group->ClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
+ merge_group->ChannelsMask.SetBit(channel_no);
+ merge_group->ChannelsCount++;
+ merge_group->ClipRect.Add(src_channel->_CmdBuffer[0].ClipRect);
+ merge_group_mask |= (1 << merge_group_n);
+ }
+
+ // Invalidate current draw channel
+ // (we don't clear DrawChannelFrozen/DrawChannelUnfrozen solely to facilitate debugging/later inspection of data)
+ column->DrawChannelCurrent = (ImGuiTableDrawChannelIdx)-1;
+ }
+
+ // [DEBUG] Display merge groups
+#if 0
+ if (g.IO.KeyShift)
+ for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
+ {
+ MergeGroup* merge_group = &merge_groups[merge_group_n];
+ if (merge_group->ChannelsCount == 0)
+ continue;
+ char buf[32];
+ ImFormatString(buf, 32, "MG%d:%d", merge_group_n, merge_group->ChannelsCount);
+ ImVec2 text_pos = merge_group->ClipRect.Min + ImVec2(4, 4);
+ ImVec2 text_size = CalcTextSize(buf, NULL);
+ GetForegroundDrawList()->AddRectFilled(text_pos, text_pos + text_size, IM_COL32(0, 0, 0, 255));
+ GetForegroundDrawList()->AddText(text_pos, IM_COL32(255, 255, 0, 255), buf, NULL);
+ GetForegroundDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 255, 0, 255));
+ }
+#endif
+
+ // 2. Rewrite channel list in our preferred order
+ if (merge_group_mask != 0)
+ {
+ // We skip channel 0 (Bg0/Bg1) and 1 (Bg2 frozen) from the shuffling since they won't move - see channels allocation in TableSetupDrawChannels().
+ const int LEADING_DRAW_CHANNELS = 2;
+ g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized
+ ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data;
+ ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> remaining_mask; // We need 132-bit of storage
+ remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count);
+ remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen);
+ IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN);
+ int remaining_count = splitter->_Count - (has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS);
+ //ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect;
+ ImRect host_rect = table->HostClipRect;
+ for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
+ {
+ if (int merge_channels_count = merge_groups[merge_group_n].ChannelsCount)
+ {
+ MergeGroup* merge_group = &merge_groups[merge_group_n];
+ ImRect merge_clip_rect = merge_group->ClipRect;
+
+ // Extend outer-most clip limits to match those of host, so draw calls can be merged even if
+ // outer-most columns have some outer padding offsetting them from their parent ClipRect.
+ // The principal cases this is dealing with are:
+ // - On a same-window table (not scrolling = single group), all fitting columns ClipRect -> will extend and match host ClipRect -> will merge
+ // - Columns can use padding and have left-most ClipRect.Min.x and right-most ClipRect.Max.x != from host ClipRect -> will extend and match host ClipRect -> will merge
+ // FIXME-TABLE FIXME-WORKRECT: We are wasting a merge opportunity on tables without scrolling if column doesn't fit
+ // within host clip rect, solely because of the half-padding difference between window->WorkRect and window->InnerClipRect.
+ if ((merge_group_n & 1) == 0 || !has_freeze_h)
+ merge_clip_rect.Min.x = ImMin(merge_clip_rect.Min.x, host_rect.Min.x);
+ if ((merge_group_n & 2) == 0 || !has_freeze_v)
+ merge_clip_rect.Min.y = ImMin(merge_clip_rect.Min.y, host_rect.Min.y);
+ if ((merge_group_n & 1) != 0)
+ merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x);
+ if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0)
+ merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y);
+#if 0
+ GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f);
+ GetOverlayDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200));
+ GetOverlayDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200));
+#endif
+ remaining_count -= merge_group->ChannelsCount;
+ for (int n = 0; n < IM_ARRAYSIZE(remaining_mask.Storage); n++)
+ remaining_mask.Storage[n] &= ~merge_group->ChannelsMask.Storage[n];
+ for (int n = 0; n < splitter->_Count && merge_channels_count != 0; n++)
+ {
+ // Copy + overwrite new clip rect
+ if (!merge_group->ChannelsMask.TestBit(n))
+ continue;
+ merge_group->ChannelsMask.ClearBit(n);
+ merge_channels_count--;
+
+ ImDrawChannel* channel = &splitter->_Channels[n];
+ IM_ASSERT(channel->_CmdBuffer.Size == 1 && merge_clip_rect.Contains(ImRect(channel->_CmdBuffer[0].ClipRect)));
+ channel->_CmdBuffer[0].ClipRect = merge_clip_rect.ToVec4();
+ memcpy(dst_tmp++, channel, sizeof(ImDrawChannel));
+ }
+ }
+
+ // Make sure Bg2DrawChannelUnfrozen appears in the middle of our groups (whereas Bg0/Bg1 and Bg2 frozen are fixed to 0 and 1)
+ if (merge_group_n == 1 && has_freeze_v)
+ memcpy(dst_tmp++, &splitter->_Channels[table->Bg2DrawChannelUnfrozen], sizeof(ImDrawChannel));
+ }
+
+ // Append unmergeable channels that we didn't reorder at the end of the list
+ for (int n = 0; n < splitter->_Count && remaining_count != 0; n++)
+ {
+ if (!remaining_mask.TestBit(n))
+ continue;
+ ImDrawChannel* channel = &splitter->_Channels[n];
+ memcpy(dst_tmp++, channel, sizeof(ImDrawChannel));
+ remaining_count--;
+ }
+ IM_ASSERT(dst_tmp == g.DrawChannelsTempMergeBuffer.Data + g.DrawChannelsTempMergeBuffer.Size);
+ memcpy(splitter->_Channels.Data + LEADING_DRAW_CHANNELS, g.DrawChannelsTempMergeBuffer.Data, (splitter->_Count - LEADING_DRAW_CHANNELS) * sizeof(ImDrawChannel));
+ }
+}
+
+// FIXME-TABLE: This is a mess, need to redesign how we render borders (as some are also done in TableEndRow)
+void ImGui::TableDrawBorders(ImGuiTable* table)
+{
+ ImGuiWindow* inner_window = table->InnerWindow;
+ if (!table->OuterWindow->ClipRect.Overlaps(table->OuterRect))
+ return;
+
+ ImDrawList* inner_drawlist = inner_window->DrawList;
+ table->DrawSplitter->SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0);
+ inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
+
+ // Draw inner border and resizing feedback
+ const float border_size = TABLE_BORDER_SIZE;
+ const float draw_y1 = table->InnerRect.Min.y;
+ const float draw_y2_body = table->InnerRect.Max.y;
+ const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1;
+ if (table->Flags & ImGuiTableFlags_BordersInnerV)
+ {
+ for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
+ {
+ if (!(table->EnabledMaskByDisplayOrder & ((ImU64)1 << order_n)))
+ continue;
+
+ const int column_n = table->DisplayOrderToIndex[order_n];
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ const bool is_hovered = (table->HoveredColumnBorder == column_n);
+ const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent);
+ const bool is_resizable = (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) == 0;
+ const bool is_frozen_separator = (table->FreezeColumnsCount == order_n + 1);
+ if (column->MaxX > table->InnerClipRect.Max.x && !is_resized)
+ continue;
+
+ // Decide whether right-most column is visible
+ if (column->NextEnabledColumn == -1 && !is_resizable)
+ if ((table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || (table->Flags & ImGuiTableFlags_NoHostExtendX))
+ continue;
+ if (column->MaxX <= column->ClipRect.Min.x) // FIXME-TABLE FIXME-STYLE: Assume BorderSize==1, this is problematic if we want to increase the border size..
+ continue;
+
+ // Draw in outer window so right-most column won't be clipped
+ // Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling.
+ ImU32 col;
+ float draw_y2;
+ if (is_hovered || is_resized || is_frozen_separator)
+ {
+ draw_y2 = draw_y2_body;
+ col = is_resized ? GetColorU32(ImGuiCol_SeparatorActive) : is_hovered ? GetColorU32(ImGuiCol_SeparatorHovered) : table->BorderColorStrong;
+ }
+ else
+ {
+ draw_y2 = (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) ? draw_y2_head : draw_y2_body;
+ col = (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) ? table->BorderColorStrong : table->BorderColorLight;
+ }
+
+ if (draw_y2 > draw_y1)
+ inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), col, border_size);
+ }
+ }
+
+ // Draw outer border
+ // FIXME: could use AddRect or explicit VLine/HLine helper?
+ if (table->Flags & ImGuiTableFlags_BordersOuter)
+ {
+ // Display outer border offset by 1 which is a simple way to display it without adding an extra draw call
+ // (Without the offset, in outer_window it would be rendered behind cells, because child windows are above their
+ // parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part
+ // of it in inner window, and the part that's over scrollbars in the outer window..)
+ // Either solution currently won't allow us to use a larger border size: the border would clipped.
+ const ImRect outer_border = table->OuterRect;
+ const ImU32 outer_col = table->BorderColorStrong;
+ if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
+ {
+ inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size);
+ }
+ else if (table->Flags & ImGuiTableFlags_BordersOuterV)
+ {
+ inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
+ inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
+ }
+ else if (table->Flags & ImGuiTableFlags_BordersOuterH)
+ {
+ inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
+ inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
+ }
+ }
+ if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
+ {
+ // Draw bottom-most row border
+ const float border_y = table->RowPosY2;
+ if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
+ inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
+ }
+
+ inner_drawlist->PopClipRect();
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Sorting
+//-------------------------------------------------------------------------
+// - TableGetSortSpecs()
+// - TableFixColumnSortDirection() [Internal]
+// - TableGetColumnNextSortDirection() [Internal]
+// - TableSetColumnSortDirection() [Internal]
+// - TableSortSpecsSanitize() [Internal]
+// - TableSortSpecsBuild() [Internal]
+//-------------------------------------------------------------------------
+
+// Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set)
+// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since
+// last call, or the first time.
+// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()!
+ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL);
+
+ if (!(table->Flags & ImGuiTableFlags_Sortable))
+ return NULL;
+
+ // Require layout (in case TableHeadersRow() hasn't been called) as it may alter IsSortSpecsDirty in some paths.
+ if (!table->IsLayoutLocked)
+ TableUpdateLayout(table);
+
+ TableSortSpecsBuild(table);
+
+ return &table->SortSpecs;
+}
+
+static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n)
+{
+ IM_ASSERT(n < column->SortDirectionsAvailCount);
+ return (column->SortDirectionsAvailList >> (n << 1)) & 0x03;
+}
+
+// Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending)
+void ImGui::TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column)
+{
+ if (column->SortOrder == -1 || (column->SortDirectionsAvailMask & (1 << column->SortDirection)) != 0)
+ return;
+ column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0);
+ table->IsSortSpecsDirty = true;
+}
+
+// Calculate next sort direction that would be set after clicking the column
+// - If the PreferSortDescending flag is set, we will default to a Descending direction on the first click.
+// - Note that the PreferSortAscending flag is never checked, it is essentially the default and therefore a no-op.
+IM_STATIC_ASSERT(ImGuiSortDirection_None == 0 && ImGuiSortDirection_Ascending == 1 && ImGuiSortDirection_Descending == 2);
+ImGuiSortDirection ImGui::TableGetColumnNextSortDirection(ImGuiTableColumn* column)
+{
+ IM_ASSERT(column->SortDirectionsAvailCount > 0);
+ if (column->SortOrder == -1)
+ return TableGetColumnAvailSortDirection(column, 0);
+ for (int n = 0; n < 3; n++)
+ if (column->SortDirection == TableGetColumnAvailSortDirection(column, n))
+ return TableGetColumnAvailSortDirection(column, (n + 1) % column->SortDirectionsAvailCount);
+ IM_ASSERT(0);
+ return ImGuiSortDirection_None;
+}
+
+// Note that the NoSortAscending/NoSortDescending flags are processed in TableSortSpecsSanitize(), and they may change/revert
+// the value of SortDirection. We could technically also do it here but it would be unnecessary and duplicate code.
+void ImGui::TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+
+ if (!(table->Flags & ImGuiTableFlags_SortMulti))
+ append_to_sort_specs = false;
+ if (!(table->Flags & ImGuiTableFlags_SortTristate))
+ IM_ASSERT(sort_direction != ImGuiSortDirection_None);
+
+ ImGuiTableColumnIdx sort_order_max = 0;
+ if (append_to_sort_specs)
+ for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
+ sort_order_max = ImMax(sort_order_max, table->Columns[other_column_n].SortOrder);
+
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ column->SortDirection = (ImU8)sort_direction;
+ if (column->SortDirection == ImGuiSortDirection_None)
+ column->SortOrder = -1;
+ else if (column->SortOrder == -1 || !append_to_sort_specs)
+ column->SortOrder = append_to_sort_specs ? sort_order_max + 1 : 0;
+
+ for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
+ {
+ ImGuiTableColumn* other_column = &table->Columns[other_column_n];
+ if (other_column != column && !append_to_sort_specs)
+ other_column->SortOrder = -1;
+ TableFixColumnSortDirection(table, other_column);
+ }
+ table->IsSettingsDirty = true;
+ table->IsSortSpecsDirty = true;
+}
+
+void ImGui::TableSortSpecsSanitize(ImGuiTable* table)
+{
+ IM_ASSERT(table->Flags & ImGuiTableFlags_Sortable);
+
+ // Clear SortOrder from hidden column and verify that there's no gap or duplicate.
+ int sort_order_count = 0;
+ ImU64 sort_order_mask = 0x00;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (column->SortOrder != -1 && !column->IsEnabled)
+ column->SortOrder = -1;
+ if (column->SortOrder == -1)
+ continue;
+ sort_order_count++;
+ sort_order_mask |= ((ImU64)1 << column->SortOrder);
+ IM_ASSERT(sort_order_count < (int)sizeof(sort_order_mask) * 8);
+ }
+
+ const bool need_fix_linearize = ((ImU64)1 << sort_order_count) != (sort_order_mask + 1);
+ const bool need_fix_single_sort_order = (sort_order_count > 1) && !(table->Flags & ImGuiTableFlags_SortMulti);
+ if (need_fix_linearize || need_fix_single_sort_order)
+ {
+ ImU64 fixed_mask = 0x00;
+ for (int sort_n = 0; sort_n < sort_order_count; sort_n++)
+ {
+ // Fix: Rewrite sort order fields if needed so they have no gap or duplicate.
+ // (e.g. SortOrder 0 disappeared, SortOrder 1..2 exists --> rewrite then as SortOrder 0..1)
+ int column_with_smallest_sort_order = -1;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ if ((fixed_mask & ((ImU64)1 << (ImU64)column_n)) == 0 && table->Columns[column_n].SortOrder != -1)
+ if (column_with_smallest_sort_order == -1 || table->Columns[column_n].SortOrder < table->Columns[column_with_smallest_sort_order].SortOrder)
+ column_with_smallest_sort_order = column_n;
+ IM_ASSERT(column_with_smallest_sort_order != -1);
+ fixed_mask |= ((ImU64)1 << column_with_smallest_sort_order);
+ table->Columns[column_with_smallest_sort_order].SortOrder = (ImGuiTableColumnIdx)sort_n;
+
+ // Fix: Make sure only one column has a SortOrder if ImGuiTableFlags_MultiSortable is not set.
+ if (need_fix_single_sort_order)
+ {
+ sort_order_count = 1;
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ if (column_n != column_with_smallest_sort_order)
+ table->Columns[column_n].SortOrder = -1;
+ break;
+ }
+ }
+ }
+
+ // Fallback default sort order (if no column had the ImGuiTableColumnFlags_DefaultSort flag)
+ if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (column->IsEnabled && !(column->Flags & ImGuiTableColumnFlags_NoSort))
+ {
+ sort_order_count = 1;
+ column->SortOrder = 0;
+ column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0);
+ break;
+ }
+ }
+
+ table->SortSpecsCount = (ImGuiTableColumnIdx)sort_order_count;
+}
+
+void ImGui::TableSortSpecsBuild(ImGuiTable* table)
+{
+ bool dirty = table->IsSortSpecsDirty;
+ if (dirty)
+ {
+ TableSortSpecsSanitize(table);
+ table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);
+ table->SortSpecs.SpecsDirty = true; // Mark as dirty for user
+ table->IsSortSpecsDirty = false; // Mark as not dirty for us
+ }
+
+ // Write output
+ ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
+ if (dirty && sort_specs != NULL)
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (column->SortOrder == -1)
+ continue;
+ IM_ASSERT(column->SortOrder < table->SortSpecsCount);
+ ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder];
+ sort_spec->ColumnUserID = column->UserID;
+ sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
+ sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
+ sort_spec->SortDirection = column->SortDirection;
+ }
+
+ table->SortSpecs.Specs = sort_specs;
+ table->SortSpecs.SpecsCount = table->SortSpecsCount;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Headers
+//-------------------------------------------------------------------------
+// - TableGetHeaderRowHeight() [Internal]
+// - TableHeadersRow()
+// - TableHeader()
+//-------------------------------------------------------------------------
+
+float ImGui::TableGetHeaderRowHeight()
+{
+ // Caring for a minor edge case:
+ // Calculate row height, for the unlikely case that some labels may be taller than others.
+ // If we didn't do that, uneven header height would highlight but smaller one before the tallest wouldn't catch input for all height.
+ // In your custom header row you may omit this all together and just call TableNextRow() without a height...
+ float row_height = GetTextLineHeight();
+ int columns_count = TableGetColumnCount();
+ for (int column_n = 0; column_n < columns_count; column_n++)
+ {
+ ImGuiTableColumnFlags flags = TableGetColumnFlags(column_n);
+ if ((flags & ImGuiTableColumnFlags_IsEnabled) && !(flags & ImGuiTableColumnFlags_NoHeaderLabel))
+ row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y);
+ }
+ row_height += GetStyle().CellPadding.y * 2.0f;
+ return row_height;
+}
+
+// [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
+// The intent is that advanced users willing to create customized headers would not need to use this helper
+// and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets.
+// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this.
+// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy.
+// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public.
+void ImGui::TableHeadersRow()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!");
+
+ // Layout if not already done (this is automatically done by TableNextRow, we do it here solely to facilitate stepping in debugger as it is frequent to step in TableUpdateLayout)
+ if (!table->IsLayoutLocked)
+ TableUpdateLayout(table);
+
+ // Open row
+ const float row_y1 = GetCursorScreenPos().y;
+ const float row_height = TableGetHeaderRowHeight();
+ TableNextRow(ImGuiTableRowFlags_Headers, row_height);
+ if (table->HostSkipItems) // Merely an optimization, you may skip in your own code.
+ return;
+
+ const int columns_count = TableGetColumnCount();
+ for (int column_n = 0; column_n < columns_count; column_n++)
+ {
+ if (!TableSetColumnIndex(column_n))
+ continue;
+
+ // Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them)
+ // - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide
+ // - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier.
+ const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n);
+ PushID(table->InstanceCurrent * table->ColumnsCount + column_n);
+ TableHeader(name);
+ PopID();
+ }
+
+ // Allow opening popup from the right-most section after the last column.
+ ImVec2 mouse_pos = ImGui::GetMousePos();
+ if (IsMouseReleased(1) && TableGetHoveredColumn() == columns_count)
+ if (mouse_pos.y >= row_y1 && mouse_pos.y < row_y1 + row_height)
+ TableOpenContextMenu(-1); // Will open a non-column-specific popup.
+}
+
+// Emit a column header (text + optional sort order)
+// We cpu-clip text here so that all columns headers can be merged into a same draw call.
+// Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader()
+void ImGui::TableHeader(const char* label)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ ImGuiTable* table = g.CurrentTable;
+ IM_ASSERT(table != NULL && "Need to call TableHeader() after BeginTable()!");
+ IM_ASSERT(table->CurrentColumn != -1);
+ const int column_n = table->CurrentColumn;
+ ImGuiTableColumn* column = &table->Columns[column_n];
+
+ // Label
+ if (label == NULL)
+ label = "";
+ const char* label_end = FindRenderedTextEnd(label);
+ ImVec2 label_size = CalcTextSize(label, label_end, true);
+ ImVec2 label_pos = window->DC.CursorPos;
+
+ // If we already got a row height, there's use that.
+ // FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect?
+ ImRect cell_r = TableGetCellBgRect(table, column_n);
+ float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f);
+
+ // Calculate ideal size for sort order arrow
+ float w_arrow = 0.0f;
+ float w_sort_text = 0.0f;
+ char sort_order_suf[4] = "";
+ const float ARROW_SCALE = 0.65f;
+ if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
+ {
+ w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);
+ if (column->SortOrder > 0)
+ {
+ ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
+ w_sort_text = g.Style.ItemInnerSpacing.x + CalcTextSize(sort_order_suf).x;
+ }
+ }
+
+ // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering for merging.
+ float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow;
+ column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, column->WorkMaxX);
+ column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x);
+
+ // Keep header highlighted when context menu is open.
+ const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent);
+ ImGuiID id = window->GetID(label);
+ ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f));
+ ItemSize(ImVec2(0.0f, label_height)); // Don't declare unclipped width, it'll be fed ContentMaxPosHeadersIdeal
+ if (!ItemAdd(bb, id))
+ return;
+
+ //GetForegroundDrawList()->AddRect(cell_r.Min, cell_r.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG]
+ //GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG]
+
+ // Using AllowItemOverlap mode because we cover the whole cell, and we want user to be able to submit subsequent items.
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_AllowItemOverlap);
+ if (g.ActiveId != id)
+ SetItemAllowOverlap();
+ if (held || hovered || selected)
+ {
+ const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+ //RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
+ TableSetBgColor(ImGuiTableBgTarget_CellBg, col, table->CurrentColumn);
+ }
+ else
+ {
+ // Submit single cell bg color in the case we didn't submit a full header row
+ if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0)
+ TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn);
+ }
+ RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
+ if (held)
+ table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n;
+ window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f;
+
+ // Drag and drop to re-order columns.
+ // FIXME-TABLE: Scroll request while reordering a column and it lands out of the scrolling zone.
+ if (held && (table->Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging(0) && !g.DragDropActive)
+ {
+ // While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x
+ table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
+ table->InstanceInteracted = table->InstanceCurrent;
+
+ // We don't reorder: through the frozen<>unfrozen line, or through a column that is marked with ImGuiTableColumnFlags_NoReorder.
+ if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < cell_r.Min.x)
+ if (ImGuiTableColumn* prev_column = (column->PrevEnabledColumn != -1) ? &table->Columns[column->PrevEnabledColumn] : NULL)
+ if (!((column->Flags | prev_column->Flags) & ImGuiTableColumnFlags_NoReorder))
+ if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (prev_column->IndexWithinEnabledSet < table->FreezeColumnsRequest))
+ table->ReorderColumnDir = -1;
+ if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > cell_r.Max.x)
+ if (ImGuiTableColumn* next_column = (column->NextEnabledColumn != -1) ? &table->Columns[column->NextEnabledColumn] : NULL)
+ if (!((column->Flags | next_column->Flags) & ImGuiTableColumnFlags_NoReorder))
+ if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (next_column->IndexWithinEnabledSet < table->FreezeColumnsRequest))
+ table->ReorderColumnDir = +1;
+ }
+
+ // Sort order arrow
+ const float ellipsis_max = cell_r.Max.x - w_arrow - w_sort_text;
+ if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
+ {
+ if (column->SortOrder != -1)
+ {
+ float x = ImMax(cell_r.Min.x, cell_r.Max.x - w_arrow - w_sort_text);
+ float y = label_pos.y;
+ if (column->SortOrder > 0)
+ {
+ PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_Text, 0.70f));
+ RenderText(ImVec2(x + g.Style.ItemInnerSpacing.x, y), sort_order_suf);
+ PopStyleColor();
+ x += w_sort_text;
+ }
+ RenderArrow(window->DrawList, ImVec2(x, y), GetColorU32(ImGuiCol_Text), column->SortDirection == ImGuiSortDirection_Ascending ? ImGuiDir_Up : ImGuiDir_Down, ARROW_SCALE);
+ }
+
+ // Handle clicking on column header to adjust Sort Order
+ if (pressed && table->ReorderColumn != column_n)
+ {
+ ImGuiSortDirection sort_direction = TableGetColumnNextSortDirection(column);
+ TableSetColumnSortDirection(column_n, sort_direction, g.IO.KeyShift);
+ }
+ }
+
+ // Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will
+ // be merged into a single draw call.
+ //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
+ RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
+
+ const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
+ if (text_clipped && hovered && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay)
+ SetTooltip("%.*s", (int)(label_end - label), label);
+
+ // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
+ if (IsMouseReleased(1) && IsItemHovered())
+ TableOpenContextMenu(column_n);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Context Menu
+//-------------------------------------------------------------------------
+// - TableOpenContextMenu() [Internal]
+// - TableDrawContextMenu() [Internal]
+//-------------------------------------------------------------------------
+
+// Use -1 to open menu not specific to a given column.
+void ImGui::TableOpenContextMenu(int column_n)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTable* table = g.CurrentTable;
+ if (column_n == -1 && table->CurrentColumn != -1) // When called within a column automatically use this one (for consistency)
+ column_n = table->CurrentColumn;
+ if (column_n == table->ColumnsCount) // To facilitate using with TableGetHoveredColumn()
+ column_n = -1;
+ IM_ASSERT(column_n >= -1 && column_n < table->ColumnsCount);
+ if (table->Flags & (ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
+ {
+ table->IsContextPopupOpen = true;
+ table->ContextPopupColumn = (ImGuiTableColumnIdx)column_n;
+ table->InstanceInteracted = table->InstanceCurrent;
+ const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID);
+ OpenPopupEx(context_menu_id, ImGuiPopupFlags_None);
+ }
+}
+
+// Output context menu into current window (generally a popup)
+// FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data?
+void ImGui::TableDrawContextMenu(ImGuiTable* table)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ bool want_separator = false;
+ const int column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1;
+ ImGuiTableColumn* column = (column_n != -1) ? &table->Columns[column_n] : NULL;
+
+ // Sizing
+ if (table->Flags & ImGuiTableFlags_Resizable)
+ {
+ if (column != NULL)
+ {
+ const bool can_resize = !(column->Flags & ImGuiTableColumnFlags_NoResize) && column->IsEnabled;
+ if (MenuItem("Size column to fit###SizeOne", NULL, false, can_resize))
+ TableSetColumnWidthAutoSingle(table, column_n);
+ }
+
+ const char* size_all_desc;
+ if (table->ColumnsEnabledFixedCount == table->ColumnsEnabledCount && (table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame)
+ size_all_desc = "Size all columns to fit###SizeAll"; // All fixed
+ else
+ size_all_desc = "Size all columns to default###SizeAll"; // All stretch or mixed
+ if (MenuItem(size_all_desc, NULL))
+ TableSetColumnWidthAutoAll(table);
+ want_separator = true;
+ }
+
+ // Ordering
+ if (table->Flags & ImGuiTableFlags_Reorderable)
+ {
+ if (MenuItem("Reset order", NULL, false, !table->IsDefaultDisplayOrder))
+ table->IsResetDisplayOrderRequest = true;
+ want_separator = true;
+ }
+
+ // Reset all (should work but seems unnecessary/noisy to expose?)
+ //if (MenuItem("Reset all"))
+ // table->IsResetAllRequest = true;
+
+ // Sorting
+ // (modify TableOpenContextMenu() to add _Sortable flag if enabling this)
+#if 0
+ if ((table->Flags & ImGuiTableFlags_Sortable) && column != NULL && (column->Flags & ImGuiTableColumnFlags_NoSort) == 0)
+ {
+ if (want_separator)
+ Separator();
+ want_separator = true;
+
+ bool append_to_sort_specs = g.IO.KeyShift;
+ if (MenuItem("Sort in Ascending Order", NULL, column->SortOrder != -1 && column->SortDirection == ImGuiSortDirection_Ascending, (column->Flags & ImGuiTableColumnFlags_NoSortAscending) == 0))
+ TableSetColumnSortDirection(table, column_n, ImGuiSortDirection_Ascending, append_to_sort_specs);
+ if (MenuItem("Sort in Descending Order", NULL, column->SortOrder != -1 && column->SortDirection == ImGuiSortDirection_Descending, (column->Flags & ImGuiTableColumnFlags_NoSortDescending) == 0))
+ TableSetColumnSortDirection(table, column_n, ImGuiSortDirection_Descending, append_to_sort_specs);
+ }
+#endif
+
+ // Hiding / Visibility
+ if (table->Flags & ImGuiTableFlags_Hideable)
+ {
+ if (want_separator)
+ Separator();
+ want_separator = true;
+
+ PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true);
+ for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
+ {
+ ImGuiTableColumn* other_column = &table->Columns[other_column_n];
+ if (other_column->Flags & ImGuiTableColumnFlags_Disabled)
+ continue;
+
+ const char* name = TableGetColumnName(table, other_column_n);
+ if (name == NULL || name[0] == 0)
+ name = "<Unknown>";
+
+ // Make sure we can't hide the last active column
+ bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;
+ if (other_column->IsUserEnabled && table->ColumnsEnabledCount <= 1)
+ menu_item_active = false;
+ if (MenuItem(name, NULL, other_column->IsUserEnabled, menu_item_active))
+ other_column->IsUserEnabledNextFrame = !other_column->IsUserEnabled;
+ }
+ PopItemFlag();
+ }
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Settings (.ini data)
+//-------------------------------------------------------------------------
+// FIXME: The binding/finding/creating flow are too confusing.
+//-------------------------------------------------------------------------
+// - TableSettingsInit() [Internal]
+// - TableSettingsCalcChunkSize() [Internal]
+// - TableSettingsCreate() [Internal]
+// - TableSettingsFindByID() [Internal]
+// - TableGetBoundSettings() [Internal]
+// - TableResetSettings()
+// - TableSaveSettings() [Internal]
+// - TableLoadSettings() [Internal]
+// - TableSettingsHandler_ClearAll() [Internal]
+// - TableSettingsHandler_ApplyAll() [Internal]
+// - TableSettingsHandler_ReadOpen() [Internal]
+// - TableSettingsHandler_ReadLine() [Internal]
+// - TableSettingsHandler_WriteAll() [Internal]
+// - TableSettingsInstallHandler() [Internal]
+//-------------------------------------------------------------------------
+// [Init] 1: TableSettingsHandler_ReadXXXX() Load and parse .ini file into TableSettings.
+// [Main] 2: TableLoadSettings() When table is created, bind Table to TableSettings, serialize TableSettings data into Table.
+// [Main] 3: TableSaveSettings() When table properties are modified, serialize Table data into bound or new TableSettings, mark .ini as dirty.
+// [Main] 4: TableSettingsHandler_WriteAll() When .ini file is dirty (which can come from other source), save TableSettings into .ini file.
+//-------------------------------------------------------------------------
+
+// Clear and initialize empty settings instance
+static void TableSettingsInit(ImGuiTableSettings* settings, ImGuiID id, int columns_count, int columns_count_max)
+{
+ IM_PLACEMENT_NEW(settings) ImGuiTableSettings();
+ ImGuiTableColumnSettings* settings_column = settings->GetColumnSettings();
+ for (int n = 0; n < columns_count_max; n++, settings_column++)
+ IM_PLACEMENT_NEW(settings_column) ImGuiTableColumnSettings();
+ settings->ID = id;
+ settings->ColumnsCount = (ImGuiTableColumnIdx)columns_count;
+ settings->ColumnsCountMax = (ImGuiTableColumnIdx)columns_count_max;
+ settings->WantApply = true;
+}
+
+static size_t TableSettingsCalcChunkSize(int columns_count)
+{
+ return sizeof(ImGuiTableSettings) + (size_t)columns_count * sizeof(ImGuiTableColumnSettings);
+}
+
+ImGuiTableSettings* ImGui::TableSettingsCreate(ImGuiID id, int columns_count)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiTableSettings* settings = g.SettingsTables.alloc_chunk(TableSettingsCalcChunkSize(columns_count));
+ TableSettingsInit(settings, id, columns_count, columns_count);
+ return settings;
+}
+
+// Find existing settings
+ImGuiTableSettings* ImGui::TableSettingsFindByID(ImGuiID id)
+{
+ // FIXME-OPT: Might want to store a lookup map for this?
+ ImGuiContext& g = *GImGui;
+ for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
+ if (settings->ID == id)
+ return settings;
+ return NULL;
+}
+
+// Get settings for a given table, NULL if none
+ImGuiTableSettings* ImGui::TableGetBoundSettings(ImGuiTable* table)
+{
+ if (table->SettingsOffset != -1)
+ {
+ ImGuiContext& g = *GImGui;
+ ImGuiTableSettings* settings = g.SettingsTables.ptr_from_offset(table->SettingsOffset);
+ IM_ASSERT(settings->ID == table->ID);
+ if (settings->ColumnsCountMax >= table->ColumnsCount)
+ return settings; // OK
+ settings->ID = 0; // Invalidate storage, we won't fit because of a count change
+ }
+ return NULL;
+}
+
+// Restore initial state of table (with or without saved settings)
+void ImGui::TableResetSettings(ImGuiTable* table)
+{
+ table->IsInitializing = table->IsSettingsDirty = true;
+ table->IsResetAllRequest = false;
+ table->IsSettingsRequestLoad = false; // Don't reload from ini
+ table->SettingsLoadedFlags = ImGuiTableFlags_None; // Mark as nothing loaded so our initialized data becomes authoritative
+}
+
+void ImGui::TableSaveSettings(ImGuiTable* table)
+{
+ table->IsSettingsDirty = false;
+ if (table->Flags & ImGuiTableFlags_NoSavedSettings)
+ return;
+
+ // Bind or create settings data
+ ImGuiContext& g = *GImGui;
+ ImGuiTableSettings* settings = TableGetBoundSettings(table);
+ if (settings == NULL)
+ {
+ settings = TableSettingsCreate(table->ID, table->ColumnsCount);
+ table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings);
+ }
+ settings->ColumnsCount = (ImGuiTableColumnIdx)table->ColumnsCount;
+
+ // Serialize ImGuiTable/ImGuiTableColumn into ImGuiTableSettings/ImGuiTableColumnSettings
+ IM_ASSERT(settings->ID == table->ID);
+ IM_ASSERT(settings->ColumnsCount == table->ColumnsCount && settings->ColumnsCountMax >= settings->ColumnsCount);
+ ImGuiTableColumn* column = table->Columns.Data;
+ ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings();
+
+ bool save_ref_scale = false;
+ settings->SaveFlags = ImGuiTableFlags_None;
+ for (int n = 0; n < table->ColumnsCount; n++, column++, column_settings++)
+ {
+ const float width_or_weight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? column->StretchWeight : column->WidthRequest;
+ column_settings->WidthOrWeight = width_or_weight;
+ column_settings->Index = (ImGuiTableColumnIdx)n;
+ column_settings->DisplayOrder = column->DisplayOrder;
+ column_settings->SortOrder = column->SortOrder;
+ column_settings->SortDirection = column->SortDirection;
+ column_settings->IsEnabled = column->IsUserEnabled;
+ column_settings->IsStretch = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0;
+ if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0)
+ save_ref_scale = true;
+
+ // We skip saving some data in the .ini file when they are unnecessary to restore our state.
+ // Note that fixed width where initial width was derived from auto-fit will always be saved as InitStretchWeightOrWidth will be 0.0f.
+ // FIXME-TABLE: We don't have logic to easily compare SortOrder to DefaultSortOrder yet so it's always saved when present.
+ if (width_or_weight != column->InitStretchWeightOrWidth)
+ settings->SaveFlags |= ImGuiTableFlags_Resizable;
+ if (column->DisplayOrder != n)
+ settings->SaveFlags |= ImGuiTableFlags_Reorderable;
+ if (column->SortOrder != -1)
+ settings->SaveFlags |= ImGuiTableFlags_Sortable;
+ if (column->IsUserEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0))
+ settings->SaveFlags |= ImGuiTableFlags_Hideable;
+ }
+ settings->SaveFlags &= table->Flags;
+ settings->RefScale = save_ref_scale ? table->RefScale : 0.0f;
+
+ MarkIniSettingsDirty();
+}
+
+void ImGui::TableLoadSettings(ImGuiTable* table)
+{
+ ImGuiContext& g = *GImGui;
+ table->IsSettingsRequestLoad = false;
+ if (table->Flags & ImGuiTableFlags_NoSavedSettings)
+ return;
+
+ // Bind settings
+ ImGuiTableSettings* settings;
+ if (table->SettingsOffset == -1)
+ {
+ settings = TableSettingsFindByID(table->ID);
+ if (settings == NULL)
+ return;
+ if (settings->ColumnsCount != table->ColumnsCount) // Allow settings if columns count changed. We could otherwise decide to return...
+ table->IsSettingsDirty = true;
+ table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings);
+ }
+ else
+ {
+ settings = TableGetBoundSettings(table);
+ }
+
+ table->SettingsLoadedFlags = settings->SaveFlags;
+ table->RefScale = settings->RefScale;
+
+ // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn
+ ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings();
+ ImU64 display_order_mask = 0;
+ for (int data_n = 0; data_n < settings->ColumnsCount; data_n++, column_settings++)
+ {
+ int column_n = column_settings->Index;
+ if (column_n < 0 || column_n >= table->ColumnsCount)
+ continue;
+
+ ImGuiTableColumn* column = &table->Columns[column_n];
+ if (settings->SaveFlags & ImGuiTableFlags_Resizable)
+ {
+ if (column_settings->IsStretch)
+ column->StretchWeight = column_settings->WidthOrWeight;
+ else
+ column->WidthRequest = column_settings->WidthOrWeight;
+ column->AutoFitQueue = 0x00;
+ }
+ if (settings->SaveFlags & ImGuiTableFlags_Reorderable)
+ column->DisplayOrder = column_settings->DisplayOrder;
+ else
+ column->DisplayOrder = (ImGuiTableColumnIdx)column_n;
+ display_order_mask |= (ImU64)1 << column->DisplayOrder;
+ column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled;
+ column->SortOrder = column_settings->SortOrder;
+ column->SortDirection = column_settings->SortDirection;
+ }
+
+ // Validate and fix invalid display order data
+ const ImU64 expected_display_order_mask = (settings->ColumnsCount == 64) ? ~0 : ((ImU64)1 << settings->ColumnsCount) - 1;
+ if (display_order_mask != expected_display_order_mask)
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ table->Columns[column_n].DisplayOrder = (ImGuiTableColumnIdx)column_n;
+
+ // Rebuild index
+ for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
+ table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n;
+}
+
+static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
+{
+ ImGuiContext& g = *ctx;
+ for (int i = 0; i != g.Tables.GetMapSize(); i++)
+ if (ImGuiTable* table = g.Tables.TryGetMapData(i))
+ table->SettingsOffset = -1;
+ g.SettingsTables.clear();
+}
+
+// Apply to existing windows (if any)
+static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*)
+{
+ ImGuiContext& g = *ctx;
+ for (int i = 0; i != g.Tables.GetMapSize(); i++)
+ if (ImGuiTable* table = g.Tables.TryGetMapData(i))
+ {
+ table->IsSettingsRequestLoad = true;
+ table->SettingsOffset = -1;
+ }
+}
+
+static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name)
+{
+ ImGuiID id = 0;
+ int columns_count = 0;
+ if (sscanf(name, "0x%08X,%d", &id, &columns_count) < 2)
+ return NULL;
+
+ if (ImGuiTableSettings* settings = ImGui::TableSettingsFindByID(id))
+ {
+ if (settings->ColumnsCountMax >= columns_count)
+ {
+ TableSettingsInit(settings, id, columns_count, settings->ColumnsCountMax); // Recycle
+ return settings;
+ }
+ settings->ID = 0; // Invalidate storage, we won't fit because of a count change
+ }
+ return ImGui::TableSettingsCreate(id, columns_count);
+}
+
+static void TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line)
+{
+ // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v"
+ ImGuiTableSettings* settings = (ImGuiTableSettings*)entry;
+ float f = 0.0f;
+ int column_n = 0, r = 0, n = 0;
+
+ if (sscanf(line, "RefScale=%f", &f) == 1) { settings->RefScale = f; return; }
+
+ if (sscanf(line, "Column %d%n", &column_n, &r) == 1)
+ {
+ if (column_n < 0 || column_n >= settings->ColumnsCount)
+ return;
+ line = ImStrSkipBlank(line + r);
+ char c = 0;
+ ImGuiTableColumnSettings* column = settings->GetColumnSettings() + column_n;
+ column->Index = (ImGuiTableColumnIdx)column_n;
+ if (sscanf(line, "UserID=0x%08X%n", (ImU32*)&n, &r)==1) { line = ImStrSkipBlank(line + r); column->UserID = (ImGuiID)n; }
+ if (sscanf(line, "Width=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = (float)n; column->IsStretch = 0; settings->SaveFlags |= ImGuiTableFlags_Resizable; }
+ if (sscanf(line, "Weight=%f%n", &f, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = f; column->IsStretch = 1; settings->SaveFlags |= ImGuiTableFlags_Resizable; }
+ if (sscanf(line, "Visible=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->IsEnabled = (ImU8)n; settings->SaveFlags |= ImGuiTableFlags_Hideable; }
+ if (sscanf(line, "Order=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->DisplayOrder = (ImGuiTableColumnIdx)n; settings->SaveFlags |= ImGuiTableFlags_Reorderable; }
+ if (sscanf(line, "Sort=%d%c%n", &n, &c, &r) == 2) { line = ImStrSkipBlank(line + r); column->SortOrder = (ImGuiTableColumnIdx)n; column->SortDirection = (c == '^') ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; settings->SaveFlags |= ImGuiTableFlags_Sortable; }
+ }
+}
+
+static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
+{
+ ImGuiContext& g = *ctx;
+ for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
+ {
+ if (settings->ID == 0) // Skip ditched settings
+ continue;
+
+ // TableSaveSettings() may clear some of those flags when we establish that the data can be stripped
+ // (e.g. Order was unchanged)
+ const bool save_size = (settings->SaveFlags & ImGuiTableFlags_Resizable) != 0;
+ const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0;
+ const bool save_order = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0;
+ const bool save_sort = (settings->SaveFlags & ImGuiTableFlags_Sortable) != 0;
+ if (!save_size && !save_visible && !save_order && !save_sort)
+ continue;
+
+ buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve
+ buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount);
+ if (settings->RefScale != 0.0f)
+ buf->appendf("RefScale=%g\n", settings->RefScale);
+ ImGuiTableColumnSettings* column = settings->GetColumnSettings();
+ for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++)
+ {
+ // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v"
+ bool save_column = column->UserID != 0 || save_size || save_visible || save_order || (save_sort && column->SortOrder != -1);
+ if (!save_column)
+ continue;
+ buf->appendf("Column %-2d", column_n);
+ if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID);
+ if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight);
+ if (save_size && !column->IsStretch) buf->appendf(" Width=%d", (int)column->WidthOrWeight);
+ if (save_visible) buf->appendf(" Visible=%d", column->IsEnabled);
+ if (save_order) buf->appendf(" Order=%d", column->DisplayOrder);
+ if (save_sort && column->SortOrder != -1) buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^');
+ buf->append("\n");
+ }
+ buf->append("\n");
+ }
+}
+
+void ImGui::TableSettingsInstallHandler(ImGuiContext* context)
+{
+ ImGuiContext& g = *context;
+ ImGuiSettingsHandler ini_handler;
+ ini_handler.TypeName = "Table";
+ ini_handler.TypeHash = ImHashStr("Table");
+ ini_handler.ClearAllFn = TableSettingsHandler_ClearAll;
+ ini_handler.ReadOpenFn = TableSettingsHandler_ReadOpen;
+ ini_handler.ReadLineFn = TableSettingsHandler_ReadLine;
+ ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll;
+ ini_handler.WriteAllFn = TableSettingsHandler_WriteAll;
+ g.SettingsHandlers.push_back(ini_handler);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Garbage Collection
+//-------------------------------------------------------------------------
+// - TableRemove() [Internal]
+// - TableGcCompactTransientBuffers() [Internal]
+// - TableGcCompactSettings() [Internal]
+//-------------------------------------------------------------------------
+
+// Remove Table (currently only used by TestEngine)
+void ImGui::TableRemove(ImGuiTable* table)
+{
+ //IMGUI_DEBUG_LOG("TableRemove() id=0x%08X\n", table->ID);
+ ImGuiContext& g = *GImGui;
+ int table_idx = g.Tables.GetIndex(table);
+ //memset(table->RawData.Data, 0, table->RawData.size_in_bytes());
+ //memset(table, 0, sizeof(ImGuiTable));
+ g.Tables.Remove(table->ID, table);
+ g.TablesLastTimeActive[table_idx] = -1.0f;
+}
+
+// Free up/compact internal Table buffers for when it gets unused
+void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
+{
+ //IMGUI_DEBUG_LOG("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID);
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(table->MemoryCompacted == false);
+ table->SortSpecs.Specs = NULL;
+ table->SortSpecsMulti.clear();
+ table->IsSortSpecsDirty = true; // FIXME: shouldn't have to leak into user performing a sort
+ table->ColumnsNames.clear();
+ table->MemoryCompacted = true;
+ for (int n = 0; n < table->ColumnsCount; n++)
+ table->Columns[n].NameOffset = -1;
+ g.TablesLastTimeActive[g.Tables.GetIndex(table)] = -1.0f;
+}
+
+void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data)
+{
+ temp_data->DrawSplitter.ClearFreeMemory();
+ temp_data->LastTimeActive = -1.0f;
+}
+
+// Compact and remove unused settings data (currently only used by TestEngine)
+void ImGui::TableGcCompactSettings()
+{
+ ImGuiContext& g = *GImGui;
+ int required_memory = 0;
+ for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
+ if (settings->ID != 0)
+ required_memory += (int)TableSettingsCalcChunkSize(settings->ColumnsCount);
+ if (required_memory == g.SettingsTables.Buf.Size)
+ return;
+ ImChunkStream<ImGuiTableSettings> new_chunk_stream;
+ new_chunk_stream.Buf.reserve(required_memory);
+ for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
+ if (settings->ID != 0)
+ memcpy(new_chunk_stream.alloc_chunk(TableSettingsCalcChunkSize(settings->ColumnsCount)), settings, TableSettingsCalcChunkSize(settings->ColumnsCount));
+ g.SettingsTables.swap(new_chunk_stream);
+}
+
+
+//-------------------------------------------------------------------------
+// [SECTION] Tables: Debugging
+//-------------------------------------------------------------------------
+// - DebugNodeTable() [Internal]
+//-------------------------------------------------------------------------
+
+#ifndef IMGUI_DISABLE_METRICS_WINDOW
+
+static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_policy)
+{
+ sizing_policy &= ImGuiTableFlags_SizingMask_;
+ if (sizing_policy == ImGuiTableFlags_SizingFixedFit) { return "FixedFit"; }
+ if (sizing_policy == ImGuiTableFlags_SizingFixedSame) { return "FixedSame"; }
+ if (sizing_policy == ImGuiTableFlags_SizingStretchProp) { return "StretchProp"; }
+ if (sizing_policy == ImGuiTableFlags_SizingStretchSame) { return "StretchSame"; }
+ return "N/A";
+}
+
+void ImGui::DebugNodeTable(ImGuiTable* table)
+{
+ char buf[512];
+ char* p = buf;
+ const char* buf_end = buf + IM_ARRAYSIZE(buf);
+ const bool is_active = (table->LastFrameActive >= ImGui::GetFrameCount() - 2); // Note that fully clipped early out scrolling tables will appear as inactive here.
+ ImFormatString(p, buf_end - p, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*");
+ if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
+ bool open = TreeNode(table, "%s", buf);
+ if (!is_active) { PopStyleColor(); }
+ if (IsItemHovered())
+ GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
+ if (IsItemVisible() && table->HoveredColumnBody != -1)
+ GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
+ if (!open)
+ return;
+ bool clear_settings = SmallButton("Clear settings");
+ BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
+ BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
+ BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX);
+ BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder);
+ BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn);
+ //BulletText("BgDrawChannels: %d/%d", 0, table->BgDrawChannelUnfrozen);
+ float sum_weights = 0.0f;
+ for (int n = 0; n < table->ColumnsCount; n++)
+ if (table->Columns[n].Flags & ImGuiTableColumnFlags_WidthStretch)
+ sum_weights += table->Columns[n].StretchWeight;
+ for (int n = 0; n < table->ColumnsCount; n++)
+ {
+ ImGuiTableColumn* column = &table->Columns[n];
+ const char* name = TableGetColumnName(table, n);
+ ImFormatString(buf, IM_ARRAYSIZE(buf),
+ "Column %d order %d '%s': offset %+.2f to %+.2f%s\n"
+ "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n"
+ "WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n"
+ "MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n"
+ "ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n"
+ "Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s..",
+ n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "",
+ column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen,
+ column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f,
+ column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x,
+ column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX,
+ column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags,
+ (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "",
+ (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "",
+ (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : "");
+ Bullet();
+ Selectable(buf);
+ if (IsItemHovered())
+ {
+ ImRect r(column->MinX, table->OuterRect.Min.y, column->MaxX, table->OuterRect.Max.y);
+ GetForegroundDrawList()->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255));
+ }
+ }
+ if (ImGuiTableSettings* settings = TableGetBoundSettings(table))
+ DebugNodeTableSettings(settings);
+ if (clear_settings)
+ table->IsResetAllRequest = true;
+ TreePop();
+}
+
+void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings)
+{
+ if (!TreeNode((void*)(intptr_t)settings->ID, "Settings 0x%08X (%d columns)", settings->ID, settings->ColumnsCount))
+ return;
+ BulletText("SaveFlags: 0x%08X", settings->SaveFlags);
+ BulletText("ColumnsCount: %d (max %d)", settings->ColumnsCount, settings->ColumnsCountMax);
+ for (int n = 0; n < settings->ColumnsCount; n++)
+ {
+ ImGuiTableColumnSettings* column_settings = &settings->GetColumnSettings()[n];
+ ImGuiSortDirection sort_dir = (column_settings->SortOrder != -1) ? (ImGuiSortDirection)column_settings->SortDirection : ImGuiSortDirection_None;
+ BulletText("Column %d Order %d SortOrder %d %s Vis %d %s %7.3f UserID 0x%08X",
+ n, column_settings->DisplayOrder, column_settings->SortOrder,
+ (sort_dir == ImGuiSortDirection_Ascending) ? "Asc" : (sort_dir == ImGuiSortDirection_Descending) ? "Des" : "---",
+ column_settings->IsEnabled, column_settings->IsStretch ? "Weight" : "Width ", column_settings->WidthOrWeight, column_settings->UserID);
+ }
+ TreePop();
+}
+
+#else // #ifndef IMGUI_DISABLE_METRICS_WINDOW
+
+void ImGui::DebugNodeTable(ImGuiTable*) {}
+void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {}
+
+#endif
+
+
+//-------------------------------------------------------------------------
+// [SECTION] Columns, BeginColumns, EndColumns, etc.
+// (This is a legacy API, prefer using BeginTable/EndTable!)
+//-------------------------------------------------------------------------
+// FIXME: sizing is lossy when columns width is very small (default width may turn negative etc.)
+//-------------------------------------------------------------------------
+// - SetWindowClipRectBeforeSetChannel() [Internal]
+// - GetColumnIndex()
+// - GetColumnsCount()
+// - GetColumnOffset()
+// - GetColumnWidth()
+// - SetColumnOffset()
+// - SetColumnWidth()
+// - PushColumnClipRect() [Internal]
+// - PushColumnsBackground() [Internal]
+// - PopColumnsBackground() [Internal]
+// - FindOrCreateColumns() [Internal]
+// - GetColumnsID() [Internal]
+// - BeginColumns()
+// - NextColumn()
+// - EndColumns()
+// - Columns()
+//-------------------------------------------------------------------------
+
+// [Internal] Small optimization to avoid calls to PopClipRect/SetCurrentChannel/PushClipRect in sequences,
+// they would meddle many times with the underlying ImDrawCmd.
+// Instead, we do a preemptive overwrite of clipping rectangle _without_ altering the command-buffer and let
+// the subsequent single call to SetCurrentChannel() does it things once.
+void ImGui::SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect)
+{
+ ImVec4 clip_rect_vec4 = clip_rect.ToVec4();
+ window->ClipRect = clip_rect;
+ window->DrawList->_CmdHeader.ClipRect = clip_rect_vec4;
+ window->DrawList->_ClipRectStack.Data[window->DrawList->_ClipRectStack.Size - 1] = clip_rect_vec4;
+}
+
+int ImGui::GetColumnIndex()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0;
+}
+
+int ImGui::GetColumnsCount()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1;
+}
+
+float ImGui::GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm)
+{
+ return offset_norm * (columns->OffMaxX - columns->OffMinX);
+}
+
+float ImGui::GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset)
+{
+ return offset / (columns->OffMaxX - columns->OffMinX);
+}
+
+static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f;
+
+static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index)
+{
+ // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing
+ // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT(column_index > 0); // We are not supposed to drag column 0.
+ IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index));
+
+ float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x;
+ x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing);
+ if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths))
+ x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing);
+
+ return x;
+}
+
+float ImGui::GetColumnOffset(int column_index)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ if (columns == NULL)
+ return 0.0f;
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ IM_ASSERT(column_index < columns->Columns.Size);
+
+ const float t = columns->Columns[column_index].OffsetNorm;
+ const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t);
+ return x_offset;
+}
+
+static float GetColumnWidthEx(ImGuiOldColumns* columns, int column_index, bool before_resize = false)
+{
+ if (column_index < 0)
+ column_index = columns->Current;
+
+ float offset_norm;
+ if (before_resize)
+ offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize;
+ else
+ offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm;
+ return ImGui::GetColumnOffsetFromNorm(columns, offset_norm);
+}
+
+float ImGui::GetColumnWidth(int column_index)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ if (columns == NULL)
+ return GetContentRegionAvail().x;
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ return GetColumnOffsetFromNorm(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm);
+}
+
+void ImGui::SetColumnOffset(int column_index, float offset)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ IM_ASSERT(columns != NULL);
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ IM_ASSERT(column_index < columns->Columns.Size);
+
+ const bool preserve_width = !(columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths) && (column_index < columns->Count - 1);
+ const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
+
+ if (!(columns->Flags & ImGuiOldColumnFlags_NoForceWithinWindow))
+ offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
+ columns->Columns[column_index].OffsetNorm = GetColumnNormFromOffset(columns, offset - columns->OffMinX);
+
+ if (preserve_width)
+ SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
+}
+
+void ImGui::SetColumnWidth(int column_index, float width)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ IM_ASSERT(columns != NULL);
+
+ if (column_index < 0)
+ column_index = columns->Current;
+ SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width);
+}
+
+void ImGui::PushColumnClipRect(int column_index)
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ if (column_index < 0)
+ column_index = columns->Current;
+
+ ImGuiOldColumnData* column = &columns->Columns[column_index];
+ PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false);
+}
+
+// Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns)
+void ImGui::PushColumnsBackground()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ if (columns->Count == 1)
+ return;
+
+ // Optimization: avoid SetCurrentChannel() + PushClipRect()
+ columns->HostBackupClipRect = window->ClipRect;
+ SetWindowClipRectBeforeSetChannel(window, columns->HostInitialClipRect);
+ columns->Splitter.SetCurrentChannel(window->DrawList, 0);
+}
+
+void ImGui::PopColumnsBackground()
+{
+ ImGuiWindow* window = GetCurrentWindowRead();
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ if (columns->Count == 1)
+ return;
+
+ // Optimization: avoid PopClipRect() + SetCurrentChannel()
+ SetWindowClipRectBeforeSetChannel(window, columns->HostBackupClipRect);
+ columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
+}
+
+ImGuiOldColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id)
+{
+ // We have few columns per window so for now we don't need bother much with turning this into a faster lookup.
+ for (int n = 0; n < window->ColumnsStorage.Size; n++)
+ if (window->ColumnsStorage[n].ID == id)
+ return &window->ColumnsStorage[n];
+
+ window->ColumnsStorage.push_back(ImGuiOldColumns());
+ ImGuiOldColumns* columns = &window->ColumnsStorage.back();
+ columns->ID = id;
+ return columns;
+}
+
+ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+
+ // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget.
+ // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer.
+ PushID(0x11223347 + (str_id ? 0 : columns_count));
+ ImGuiID id = window->GetID(str_id ? str_id : "columns");
+ PopID();
+
+ return id;
+}
+
+void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ IM_ASSERT(columns_count >= 1);
+ IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported
+
+ // Acquire storage for the columns set
+ ImGuiID id = GetColumnsID(str_id, columns_count);
+ ImGuiOldColumns* columns = FindOrCreateColumns(window, id);
+ IM_ASSERT(columns->ID == id);
+ columns->Current = 0;
+ columns->Count = columns_count;
+ columns->Flags = flags;
+ window->DC.CurrentColumns = columns;
+
+ columns->HostCursorPosY = window->DC.CursorPos.y;
+ columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
+ columns->HostInitialClipRect = window->ClipRect;
+ columns->HostBackupParentWorkRect = window->ParentWorkRect;
+ window->ParentWorkRect = window->WorkRect;
+
+ // Set state for first column
+ // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect
+ const float column_padding = g.Style.ItemSpacing.x;
+ const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize));
+ const float max_1 = window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f);
+ const float max_2 = window->WorkRect.Max.x + half_clip_extend_x;
+ columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f);
+ columns->OffMaxX = ImMax(ImMin(max_1, max_2) - window->Pos.x, columns->OffMinX + 1.0f);
+ columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
+
+ // Clear data if columns count changed
+ if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1)
+ columns->Columns.resize(0);
+
+ // Initialize default widths
+ columns->IsFirstFrame = (columns->Columns.Size == 0);
+ if (columns->Columns.Size == 0)
+ {
+ columns->Columns.reserve(columns_count + 1);
+ for (int n = 0; n < columns_count + 1; n++)
+ {
+ ImGuiOldColumnData column;
+ column.OffsetNorm = n / (float)columns_count;
+ columns->Columns.push_back(column);
+ }
+ }
+
+ for (int n = 0; n < columns_count; n++)
+ {
+ // Compute clipping rectangle
+ ImGuiOldColumnData* column = &columns->Columns[n];
+ float clip_x1 = IM_ROUND(window->Pos.x + GetColumnOffset(n));
+ float clip_x2 = IM_ROUND(window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
+ column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX);
+ column->ClipRect.ClipWithFull(window->ClipRect);
+ }
+
+ if (columns->Count > 1)
+ {
+ columns->Splitter.Split(window->DrawList, 1 + columns->Count);
+ columns->Splitter.SetCurrentChannel(window->DrawList, 1);
+ PushColumnClipRect(0);
+ }
+
+ // We don't generally store Indent.x inside ColumnsOffset because it may be manipulated by the user.
+ float offset_0 = GetColumnOffset(columns->Current);
+ float offset_1 = GetColumnOffset(columns->Current + 1);
+ float width = offset_1 - offset_0;
+ PushItemWidth(width * 0.65f);
+ window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f);
+ window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+ window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding;
+}
+
+void ImGui::NextColumn()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems || window->DC.CurrentColumns == NULL)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+
+ if (columns->Count == 1)
+ {
+ window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+ IM_ASSERT(columns->Current == 0);
+ return;
+ }
+
+ // Next column
+ if (++columns->Current == columns->Count)
+ columns->Current = 0;
+
+ PopItemWidth();
+
+ // Optimization: avoid PopClipRect() + SetCurrentChannel() + PushClipRect()
+ // (which would needlessly attempt to update commands in the wrong channel, then pop or overwrite them),
+ ImGuiOldColumnData* column = &columns->Columns[columns->Current];
+ SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
+ columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1);
+
+ const float column_padding = g.Style.ItemSpacing.x;
+ columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
+ if (columns->Current > 0)
+ {
+ // Columns 1+ ignore IndentX (by canceling it out)
+ // FIXME-COLUMNS: Unnecessary, could be locked?
+ window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding;
+ }
+ else
+ {
+ // New row/line: column 0 honor IndentX.
+ window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f);
+ columns->LineMinY = columns->LineMaxY;
+ }
+ window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+ window->DC.CursorPos.y = columns->LineMinY;
+ window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
+ window->DC.CurrLineTextBaseOffset = 0.0f;
+
+ // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup.
+ float offset_0 = GetColumnOffset(columns->Current);
+ float offset_1 = GetColumnOffset(columns->Current + 1);
+ float width = offset_1 - offset_0;
+ PushItemWidth(width * 0.65f);
+ window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding;
+}
+
+void ImGui::EndColumns()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ IM_ASSERT(columns != NULL);
+
+ PopItemWidth();
+ if (columns->Count > 1)
+ {
+ PopClipRect();
+ columns->Splitter.Merge(window->DrawList);
+ }
+
+ const ImGuiOldColumnFlags flags = columns->Flags;
+ columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
+ window->DC.CursorPos.y = columns->LineMaxY;
+ if (!(flags & ImGuiOldColumnFlags_GrowParentContentsSize))
+ window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent
+
+ // Draw columns borders and handle resize
+ // The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy
+ bool is_being_resized = false;
+ if (!(flags & ImGuiOldColumnFlags_NoBorder) && !window->SkipItems)
+ {
+ // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.
+ const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y);
+ const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y);
+ int dragging_column = -1;
+ for (int n = 1; n < columns->Count; n++)
+ {
+ ImGuiOldColumnData* column = &columns->Columns[n];
+ float x = window->Pos.x + GetColumnOffset(n);
+ const ImGuiID column_id = columns->ID + ImGuiID(n);
+ const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH;
+ const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2));
+ KeepAliveID(column_id);
+ if (IsClippedEx(column_hit_rect, column_id)) // FIXME: Can be removed or replaced with a lower-level test
+ continue;
+
+ bool hovered = false, held = false;
+ if (!(flags & ImGuiOldColumnFlags_NoResize))
+ {
+ ButtonBehavior(column_hit_rect, column_id, &hovered, &held);
+ if (hovered || held)
+ g.MouseCursor = ImGuiMouseCursor_ResizeEW;
+ if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize))
+ dragging_column = n;
+ }
+
+ // Draw column
+ const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
+ const float xi = IM_FLOOR(x);
+ window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
+ }
+
+ // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
+ if (dragging_column != -1)
+ {
+ if (!columns->IsBeingResized)
+ for (int n = 0; n < columns->Count + 1; n++)
+ columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm;
+ columns->IsBeingResized = is_being_resized = true;
+ float x = GetDraggedColumnOffset(columns, dragging_column);
+ SetColumnOffset(dragging_column, x);
+ }
+ }
+ columns->IsBeingResized = is_being_resized;
+
+ window->WorkRect = window->ParentWorkRect;
+ window->ParentWorkRect = columns->HostBackupParentWorkRect;
+ window->DC.CurrentColumns = NULL;
+ window->DC.ColumnsOffset.x = 0.0f;
+ window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
+}
+
+void ImGui::Columns(int columns_count, const char* id, bool border)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ IM_ASSERT(columns_count >= 1);
+
+ ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder);
+ //flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior
+ ImGuiOldColumns* columns = window->DC.CurrentColumns;
+ if (columns != NULL && columns->Count == columns_count && columns->Flags == flags)
+ return;
+
+ if (columns != NULL)
+ EndColumns();
+
+ if (columns_count != 1)
+ BeginColumns(id, columns_count, flags);
+}
+
+//-------------------------------------------------------------------------
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imgui_widgets.cpp b/Client/ThirdParty/imgui/imgui_widgets.cpp
new file mode 100644
index 0000000..a6f3195
--- /dev/null
+++ b/Client/ThirdParty/imgui/imgui_widgets.cpp
@@ -0,0 +1,8247 @@
+// dear imgui, v1.86 WIP
+// (widgets code)
+
+/*
+
+Index of this file:
+
+// [SECTION] Forward Declarations
+// [SECTION] Widgets: Text, etc.
+// [SECTION] Widgets: Main (Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.)
+// [SECTION] Widgets: Low-level Layout helpers (Spacing, Dummy, NewLine, Separator, etc.)
+// [SECTION] Widgets: ComboBox
+// [SECTION] Data Type and Data Formatting Helpers
+// [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
+// [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
+// [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
+// [SECTION] Widgets: InputText, InputTextMultiline
+// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
+// [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
+// [SECTION] Widgets: Selectable
+// [SECTION] Widgets: ListBox
+// [SECTION] Widgets: PlotLines, PlotHistogram
+// [SECTION] Widgets: Value helpers
+// [SECTION] Widgets: MenuItem, BeginMenu, EndMenu, etc.
+// [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
+// [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
+// [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc.
+
+*/
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include "imgui.h"
+#ifndef IMGUI_DISABLE
+
+#ifndef IMGUI_DEFINE_MATH_OPERATORS
+#define IMGUI_DEFINE_MATH_OPERATORS
+#endif
+#include "imgui_internal.h"
+
+// System includes
+#include <ctype.h> // toupper
+#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
+#include <stddef.h> // intptr_t
+#else
+#include <stdint.h> // intptr_t
+#endif
+
+//-------------------------------------------------------------------------
+// Warnings
+//-------------------------------------------------------------------------
+
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
+#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
+#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
+#endif
+#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
+#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
+#endif
+
+// Clang/GCC warnings with -Weverything
+#if defined(__clang__)
+#if __has_warning("-Wunknown-warning-option")
+#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
+#endif
+#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
+#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
+#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok.
+#pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
+#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
+#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
+#pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double.
+#pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_')
+#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
+#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
+#elif defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
+#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
+#endif
+
+//-------------------------------------------------------------------------
+// Data
+//-------------------------------------------------------------------------
+
+// Widgets
+static const float DRAGDROP_HOLD_TO_OPEN_TIMER = 0.70f; // Time for drag-hold to activate items accepting the ImGuiButtonFlags_PressedOnDragDropHold button behavior.
+static const float DRAG_MOUSE_THRESHOLD_FACTOR = 0.50f; // Multiplier for the default value of io.MouseDragThreshold to make DragFloat/DragInt react faster to mouse drags.
+
+// Those MIN/MAX values are not define because we need to point to them
+static const signed char IM_S8_MIN = -128;
+static const signed char IM_S8_MAX = 127;
+static const unsigned char IM_U8_MIN = 0;
+static const unsigned char IM_U8_MAX = 0xFF;
+static const signed short IM_S16_MIN = -32768;
+static const signed short IM_S16_MAX = 32767;
+static const unsigned short IM_U16_MIN = 0;
+static const unsigned short IM_U16_MAX = 0xFFFF;
+static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000);
+static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF)
+static const ImU32 IM_U32_MIN = 0;
+static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF)
+#ifdef LLONG_MIN
+static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll);
+static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll);
+#else
+static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1;
+static const ImS64 IM_S64_MAX = 9223372036854775807LL;
+#endif
+static const ImU64 IM_U64_MIN = 0;
+#ifdef ULLONG_MAX
+static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull);
+#else
+static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
+#endif
+
+//-------------------------------------------------------------------------
+// [SECTION] Forward Declarations
+//-------------------------------------------------------------------------
+
+// For InputTextEx()
+static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source);
+static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
+static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Text, etc.
+//-------------------------------------------------------------------------
+// - TextEx() [Internal]
+// - TextUnformatted()
+// - Text()
+// - TextV()
+// - TextColored()
+// - TextColoredV()
+// - TextDisabled()
+// - TextDisabledV()
+// - TextWrapped()
+// - TextWrappedV()
+// - LabelText()
+// - LabelTextV()
+// - BulletText()
+// - BulletTextV()
+//-------------------------------------------------------------------------
+
+void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ImGuiContext& g = *GImGui;
+
+ // Accept null ranges
+ if (text == text_end)
+ text = text_end = "";
+
+ // Calculate length
+ const char* text_begin = text;
+ if (text_end == NULL)
+ text_end = text + strlen(text); // FIXME-OPT
+
+ const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
+ const float wrap_pos_x = window->DC.TextWrapPos;
+ const bool wrap_enabled = (wrap_pos_x >= 0.0f);
+ if (text_end - text > 2000 && !wrap_enabled)
+ {
+ // Long text!
+ // Perform manual coarse clipping to optimize for long multi-line text
+ // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
+ // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
+ // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
+ const char* line = text;
+ const float line_height = GetTextLineHeight();
+ ImVec2 text_size(0, 0);
+
+ // Lines to skip (can't skip when logging text)
+ ImVec2 pos = text_pos;
+ if (!g.LogEnabled)
+ {
+ int lines_skippable = (int)((window->ClipRect.Min.y - text_pos.y) / line_height);
+ if (lines_skippable > 0)
+ {
+ int lines_skipped = 0;
+ while (line < text_end && lines_skipped < lines_skippable)
+ {
+ const char* line_end = (const char*)memchr(line, '\n', text_end - line);
+ if (!line_end)
+ line_end = text_end;
+ if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
+ text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
+ line = line_end + 1;
+ lines_skipped++;
+ }
+ pos.y += lines_skipped * line_height;
+ }
+ }
+
+ // Lines to render
+ if (line < text_end)
+ {
+ ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
+ while (line < text_end)
+ {
+ if (IsClippedEx(line_rect, 0))
+ break;
+
+ const char* line_end = (const char*)memchr(line, '\n', text_end - line);
+ if (!line_end)
+ line_end = text_end;
+ text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
+ RenderText(pos, line, line_end, false);
+ line = line_end + 1;
+ line_rect.Min.y += line_height;
+ line_rect.Max.y += line_height;
+ pos.y += line_height;
+ }
+
+ // Count remaining lines
+ int lines_skipped = 0;
+ while (line < text_end)
+ {
+ const char* line_end = (const char*)memchr(line, '\n', text_end - line);
+ if (!line_end)
+ line_end = text_end;
+ if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0)
+ text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x);
+ line = line_end + 1;
+ lines_skipped++;
+ }
+ pos.y += lines_skipped * line_height;
+ }
+ text_size.y = (pos - text_pos).y;
+
+ ImRect bb(text_pos, text_pos + text_size);
+ ItemSize(text_size, 0.0f);
+ ItemAdd(bb, 0);
+ }
+ else
+ {
+ const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
+ const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
+
+ ImRect bb(text_pos, text_pos + text_size);
+ ItemSize(text_size, 0.0f);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Render (we don't hide text after ## in this end-user function)
+ RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
+ }
+}
+
+void ImGui::TextUnformatted(const char* text, const char* text_end)
+{
+ TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
+}
+
+void ImGui::Text(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextV(fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextV(const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ // FIXME-OPT: Handle the %s shortcut?
+ ImGuiContext& g = *GImGui;
+ const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ TextEx(g.TempBuffer, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
+}
+
+void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextColoredV(col, fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
+{
+ PushStyleColor(ImGuiCol_Text, col);
+ if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
+ TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
+ else
+ TextV(fmt, args);
+ PopStyleColor();
+}
+
+void ImGui::TextDisabled(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextDisabledV(fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextDisabledV(const char* fmt, va_list args)
+{
+ ImGuiContext& g = *GImGui;
+ PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
+ if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
+ TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
+ else
+ TextV(fmt, args);
+ PopStyleColor();
+}
+
+void ImGui::TextWrapped(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ TextWrappedV(fmt, args);
+ va_end(args);
+}
+
+void ImGui::TextWrappedV(const char* fmt, va_list args)
+{
+ ImGuiContext& g = *GImGui;
+ bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
+ if (need_backup)
+ PushTextWrapPos(0.0f);
+ if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
+ TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
+ else
+ TextV(fmt, args);
+ if (need_backup)
+ PopTextWrapPos();
+}
+
+void ImGui::LabelText(const char* label, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ LabelTextV(label, fmt, args);
+ va_end(args);
+}
+
+// Add a label+text combo aligned to other label+value widgets
+void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const float w = CalcItemWidth();
+
+ const char* value_text_begin = &g.TempBuffer[0];
+ const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ const ImVec2 pos = window->DC.CursorPos;
+ const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2));
+ const ImRect total_bb(pos, pos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), ImMax(value_size.y, label_size.y) + style.FramePadding.y * 2));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, 0))
+ return;
+
+ // Render
+ RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f));
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
+}
+
+void ImGui::BulletText(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ BulletTextV(fmt, args);
+ va_end(args);
+}
+
+// Text with a little bullet aligned to the typical tree node.
+void ImGui::BulletTextV(const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ const char* text_begin = g.TempBuffer;
+ const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
+ const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding
+ ImVec2 pos = window->DC.CursorPos;
+ pos.y += window->DC.CurrLineTextBaseOffset;
+ ItemSize(total_size, 0.0f);
+ const ImRect bb(pos, pos + total_size);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Render
+ ImU32 text_col = GetColorU32(ImGuiCol_Text);
+ RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col);
+ RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Main
+//-------------------------------------------------------------------------
+// - ButtonBehavior() [Internal]
+// - Button()
+// - SmallButton()
+// - InvisibleButton()
+// - ArrowButton()
+// - CloseButton() [Internal]
+// - CollapseButton() [Internal]
+// - GetWindowScrollbarID() [Internal]
+// - GetWindowScrollbarRect() [Internal]
+// - Scrollbar() [Internal]
+// - ScrollbarEx() [Internal]
+// - Image()
+// - ImageButton()
+// - Checkbox()
+// - CheckboxFlagsT() [Internal]
+// - CheckboxFlags()
+// - RadioButton()
+// - ProgressBar()
+// - Bullet()
+//-------------------------------------------------------------------------
+
+// The ButtonBehavior() function is key to many interactions and used by many/most widgets.
+// Because we handle so many cases (keyboard/gamepad navigation, drag and drop) and many specific behavior (via ImGuiButtonFlags_),
+// this code is a little complex.
+// By far the most common path is interacting with the Mouse using the default ImGuiButtonFlags_PressedOnClickRelease button behavior.
+// See the series of events below and the corresponding state reported by dear imgui:
+//------------------------------------------------------------------------------------------------------------------------------------------------
+// with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
+// Frame N+0 (mouse is outside bb) - - - - - -
+// Frame N+1 (mouse moves inside bb) - true - - - -
+// Frame N+2 (mouse button is down) - true true true - true
+// Frame N+3 (mouse button is down) - true true - - -
+// Frame N+4 (mouse moves outside bb) - - true - - -
+// Frame N+5 (mouse moves inside bb) - true true - - -
+// Frame N+6 (mouse button is released) true true - - true -
+// Frame N+7 (mouse button is released) - true - - - -
+// Frame N+8 (mouse moves outside bb) - - - - - -
+//------------------------------------------------------------------------------------------------------------------------------------------------
+// with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
+// Frame N+2 (mouse button is down) true true true true - true
+// Frame N+3 (mouse button is down) - true true - - -
+// Frame N+6 (mouse button is released) - true - - true -
+// Frame N+7 (mouse button is released) - true - - - -
+//------------------------------------------------------------------------------------------------------------------------------------------------
+// with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
+// Frame N+2 (mouse button is down) - true - - - true
+// Frame N+3 (mouse button is down) - true - - - -
+// Frame N+6 (mouse button is released) true true - - - -
+// Frame N+7 (mouse button is released) - true - - - -
+//------------------------------------------------------------------------------------------------------------------------------------------------
+// with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked()
+// Frame N+0 (mouse button is down) - true - - - true
+// Frame N+1 (mouse button is down) - true - - - -
+// Frame N+2 (mouse button is released) - true - - - -
+// Frame N+3 (mouse button is released) - true - - - -
+// Frame N+4 (mouse button is down) true true true true - true
+// Frame N+5 (mouse button is down) - true true - - -
+// Frame N+6 (mouse button is released) - true - - true -
+// Frame N+7 (mouse button is released) - true - - - -
+//------------------------------------------------------------------------------------------------------------------------------------------------
+// Note that some combinations are supported,
+// - PressedOnDragDropHold can generally be associated with any flag.
+// - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported.
+//------------------------------------------------------------------------------------------------------------------------------------------------
+// The behavior of the return-value changes when ImGuiButtonFlags_Repeat is set:
+// Repeat+ Repeat+ Repeat+ Repeat+
+// PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick
+//-------------------------------------------------------------------------------------------------------------------------------------------------
+// Frame N+0 (mouse button is down) - true - true
+// ... - - - -
+// Frame N + RepeatDelay true true - true
+// ... - - - -
+// Frame N + RepeatDelay + RepeatRate*N true true - true
+//-------------------------------------------------------------------------------------------------------------------------------------------------
+
+bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ // Default only reacts to left mouse button
+ if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0)
+ flags |= ImGuiButtonFlags_MouseButtonDefault_;
+
+ // Default behavior requires click + release inside bounding box
+ if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0)
+ flags |= ImGuiButtonFlags_PressedOnDefault_;
+
+ ImGuiWindow* backup_hovered_window = g.HoveredWindow;
+ const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window;
+ if (flatten_hovered_children)
+ g.HoveredWindow = window;
+
+#ifdef IMGUI_ENABLE_TEST_ENGINE
+ if (id != 0 && g.LastItemData.ID != id)
+ IMGUI_TEST_ENGINE_ITEM_ADD(bb, id);
+#endif
+
+ bool pressed = false;
+ bool hovered = ItemHoverable(bb, id);
+
+ // Drag source doesn't report as hovered
+ if (hovered && g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover))
+ hovered = false;
+
+ // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button
+ if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers))
+ if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
+ {
+ hovered = true;
+ SetHoveredID(id);
+ if (g.HoveredIdTimer - g.IO.DeltaTime <= DRAGDROP_HOLD_TO_OPEN_TIMER && g.HoveredIdTimer >= DRAGDROP_HOLD_TO_OPEN_TIMER)
+ {
+ pressed = true;
+ g.DragDropHoldJustPressedId = id;
+ FocusWindow(window);
+ }
+ }
+
+ if (flatten_hovered_children)
+ g.HoveredWindow = backup_hovered_window;
+
+ // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one.
+ if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0))
+ hovered = false;
+
+ // Mouse handling
+ if (hovered)
+ {
+ if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt))
+ {
+ // Poll buttons
+ int mouse_button_clicked = -1;
+ int mouse_button_released = -1;
+ if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseClicked[0]) { mouse_button_clicked = 0; }
+ else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseClicked[1]) { mouse_button_clicked = 1; }
+ else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseClicked[2]) { mouse_button_clicked = 2; }
+ if ((flags & ImGuiButtonFlags_MouseButtonLeft) && g.IO.MouseReleased[0]) { mouse_button_released = 0; }
+ else if ((flags & ImGuiButtonFlags_MouseButtonRight) && g.IO.MouseReleased[1]) { mouse_button_released = 1; }
+ else if ((flags & ImGuiButtonFlags_MouseButtonMiddle) && g.IO.MouseReleased[2]) { mouse_button_released = 2; }
+
+ if (mouse_button_clicked != -1 && g.ActiveId != id)
+ {
+ if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere))
+ {
+ SetActiveID(id, window);
+ g.ActiveIdMouseButton = mouse_button_clicked;
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ SetFocusID(id, window);
+ FocusWindow(window);
+ }
+ if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2))
+ {
+ pressed = true;
+ if (flags & ImGuiButtonFlags_NoHoldingActiveId)
+ ClearActiveID();
+ else
+ SetActiveID(id, window); // Hold on ID
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ SetFocusID(id, window);
+ g.ActiveIdMouseButton = mouse_button_clicked;
+ FocusWindow(window);
+ }
+ }
+ if ((flags & ImGuiButtonFlags_PressedOnRelease) && mouse_button_released != -1)
+ {
+ // Repeat mode trumps on release behavior
+ const bool has_repeated_at_least_once = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay;
+ if (!has_repeated_at_least_once)
+ pressed = true;
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ SetFocusID(id, window);
+ ClearActiveID();
+ }
+
+ // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above).
+ // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings.
+ if (g.ActiveId == id && (flags & ImGuiButtonFlags_Repeat))
+ if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, true))
+ pressed = true;
+ }
+
+ if (pressed)
+ g.NavDisableHighlight = true;
+ }
+
+ // Gamepad/Keyboard navigation
+ // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse.
+ if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId))
+ if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus))
+ hovered = true;
+ if (g.NavActivateDownId == id)
+ {
+ bool nav_activated_by_code = (g.NavActivateId == id);
+ bool nav_activated_by_inputs = IsNavInputTest(ImGuiNavInput_Activate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed);
+ if (nav_activated_by_code || nav_activated_by_inputs)
+ {
+ // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
+ pressed = true;
+ SetActiveID(id, window);
+ g.ActiveIdSource = ImGuiInputSource_Nav;
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ SetFocusID(id, window);
+ }
+ }
+
+ // Process while held
+ bool held = false;
+ if (g.ActiveId == id)
+ {
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse)
+ {
+ if (g.ActiveIdIsJustActivated)
+ g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
+
+ const int mouse_button = g.ActiveIdMouseButton;
+ IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
+ if (g.IO.MouseDown[mouse_button])
+ {
+ held = true;
+ }
+ else
+ {
+ bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0;
+ bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0;
+ if ((release_in || release_anywhere) && !g.DragDropActive)
+ {
+ // Report as pressed when releasing the mouse (this is the most common path)
+ bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseReleased[mouse_button] && g.IO.MouseClickedLastCount[mouse_button] == 2;
+ bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps <on release>
+ if (!is_double_click_release && !is_repeating_already)
+ pressed = true;
+ }
+ ClearActiveID();
+ }
+ if (!(flags & ImGuiButtonFlags_NoNavFocus))
+ g.NavDisableHighlight = true;
+ }
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ {
+ // When activated using Nav, we hold on the ActiveID until activation button is released
+ if (g.NavActivateDownId != id)
+ ClearActiveID();
+ }
+ if (pressed)
+ g.ActiveIdHasBeenPressedBefore = true;
+ }
+
+ if (out_hovered) *out_hovered = hovered;
+ if (out_held) *out_held = held;
+
+ return pressed;
+}
+
+bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ ImVec2 pos = window->DC.CursorPos;
+ if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
+ pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y;
+ ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
+
+ const ImRect bb(pos, pos + size);
+ ItemSize(size, style.FramePadding.y);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
+ flags |= ImGuiButtonFlags_Repeat;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
+
+ // Render
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ RenderNavHighlight(bb, id);
+ RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
+
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("[", "]");
+ RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
+
+ // Automatically close popups
+ //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
+ // CloseCurrentPopup();
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return pressed;
+}
+
+bool ImGui::Button(const char* label, const ImVec2& size_arg)
+{
+ return ButtonEx(label, size_arg, ImGuiButtonFlags_None);
+}
+
+// Small buttons fits within text without additional vertical spacing.
+bool ImGui::SmallButton(const char* label)
+{
+ ImGuiContext& g = *GImGui;
+ float backup_padding_y = g.Style.FramePadding.y;
+ g.Style.FramePadding.y = 0.0f;
+ bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine);
+ g.Style.FramePadding.y = backup_padding_y;
+ return pressed;
+}
+
+// Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack.
+// Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id)
+bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiButtonFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size.
+ IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f);
+
+ const ImGuiID id = window->GetID(str_id);
+ ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(size);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
+
+ return pressed;
+}
+
+bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiID id = window->GetID(str_id);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ const float default_size = GetFrameHeight();
+ ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
+ flags |= ImGuiButtonFlags_Repeat;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
+
+ // Render
+ const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ const ImU32 text_col = GetColorU32(ImGuiCol_Text);
+ RenderNavHighlight(bb, id);
+ RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
+ RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir);
+
+ return pressed;
+}
+
+bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
+{
+ float sz = GetFrameHeight();
+ return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None);
+}
+
+// Button to close a window
+bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825)
+ // This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible?
+ const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
+ ImRect bb_interact = bb;
+ const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea();
+ if (area_to_visible_ratio < 1.5f)
+ bb_interact.Expand(ImFloor(bb_interact.GetSize() * -0.25f));
+
+ // Tweak 2: We intentionally allow interaction when clipped so that a mechanical Alt,Right,Activate sequence can always close a window.
+ // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
+ bool is_clipped = !ItemAdd(bb_interact, id);
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb_interact, id, &hovered, &held);
+ if (is_clipped)
+ return pressed;
+
+ // Render
+ // FIXME: Clarify this mess
+ ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
+ ImVec2 center = bb.GetCenter();
+ if (hovered)
+ window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
+
+ float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
+ ImU32 cross_col = GetColorU32(ImGuiCol_Text);
+ center -= ImVec2(0.5f, 0.5f);
+ window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f);
+ window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f);
+
+ return pressed;
+}
+
+bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
+ ItemAdd(bb, id);
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
+
+ // Render
+ ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ ImU32 text_col = GetColorU32(ImGuiCol_Text);
+ ImVec2 center = bb.GetCenter();
+ if (hovered || held)
+ window->DrawList->AddCircleFilled(center/*+ ImVec2(0.0f, -0.5f)*/, g.FontSize * 0.5f + 1.0f, bg_col, 12);
+ RenderArrow(window->DrawList, bb.Min + g.Style.FramePadding, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f);
+
+ // Switch to moving the window after mouse is moved beyond the initial drag threshold
+ if (IsItemActive() && IsMouseDragging(0))
+ StartMouseMovingWindow(window);
+
+ return pressed;
+}
+
+ImGuiID ImGui::GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis)
+{
+ return window->GetIDNoKeepAlive(axis == ImGuiAxis_X ? "#SCROLLX" : "#SCROLLY");
+}
+
+// Return scrollbar rectangle, must only be called for corresponding axis if window->ScrollbarX/Y is set.
+ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis)
+{
+ const ImRect outer_rect = window->Rect();
+ const ImRect inner_rect = window->InnerRect;
+ const float border_size = window->WindowBorderSize;
+ const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar)
+ IM_ASSERT(scrollbar_size > 0.0f);
+ if (axis == ImGuiAxis_X)
+ return ImRect(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x, outer_rect.Max.y);
+ else
+ return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, outer_rect.Max.x, inner_rect.Max.y);
+}
+
+void ImGui::Scrollbar(ImGuiAxis axis)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const ImGuiID id = GetWindowScrollbarID(window, axis);
+ KeepAliveID(id);
+
+ // Calculate scrollbar bounding box
+ ImRect bb = GetWindowScrollbarRect(window, axis);
+ ImDrawFlags rounding_corners = ImDrawFlags_RoundCornersNone;
+ if (axis == ImGuiAxis_X)
+ {
+ rounding_corners |= ImDrawFlags_RoundCornersBottomLeft;
+ if (!window->ScrollbarY)
+ rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
+ }
+ else
+ {
+ if ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar))
+ rounding_corners |= ImDrawFlags_RoundCornersTopRight;
+ if (!window->ScrollbarX)
+ rounding_corners |= ImDrawFlags_RoundCornersBottomRight;
+ }
+ float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
+ float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
+ ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners);
+}
+
+// Vertical/Horizontal scrollbar
+// The entire piece of code below is rather confusing because:
+// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
+// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
+// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
+// Still, the code should probably be made simpler..
+bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ const float bb_frame_width = bb_frame.GetWidth();
+ const float bb_frame_height = bb_frame.GetHeight();
+ if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f)
+ return false;
+
+ // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab)
+ float alpha = 1.0f;
+ if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f)
+ alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f));
+ if (alpha <= 0.0f)
+ return false;
+
+ const ImGuiStyle& style = g.Style;
+ const bool allow_interaction = (alpha >= 1.0f);
+
+ ImRect bb = bb_frame;
+ bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
+
+ // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
+ const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight();
+
+ // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
+ // But we maintain a minimum size in pixel to allow for the user to still aim inside.
+ IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
+ const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f);
+ const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
+ const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
+
+ // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
+ bool held = false;
+ bool hovered = false;
+ ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
+
+ float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v);
+ float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
+ float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space
+ if (held && allow_interaction && grab_h_norm < 1.0f)
+ {
+ float scrollbar_pos_v = bb.Min[axis];
+ float mouse_pos_v = g.IO.MousePos[axis];
+
+ // Click position in scrollbar normalized space (0.0f->1.0f)
+ const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
+ SetHoveredID(id);
+
+ bool seek_absolute = false;
+ if (g.ActiveIdIsJustActivated)
+ {
+ // On initial click calculate the distance between mouse and the center of the grab
+ seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm);
+ if (seek_absolute)
+ g.ScrollbarClickDeltaToGrabCenter = 0.0f;
+ else
+ g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
+ }
+
+ // Apply scroll (p_scroll_v will generally point on one member of window->Scroll)
+ // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
+ const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
+ *p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
+
+ // Update values for rendering
+ scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
+ grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
+
+ // Update distance to grab now that we have seeked and saturated
+ if (seek_absolute)
+ g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
+ }
+
+ // Render
+ const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg);
+ const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
+ window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, flags);
+ ImRect grab_rect;
+ if (axis == ImGuiAxis_X)
+ grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);
+ else
+ grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels);
+ window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
+
+ return held;
+}
+
+void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ if (border_col.w > 0.0f)
+ bb.Max += ImVec2(2, 2);
+ ItemSize(bb);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ if (border_col.w > 0.0f)
+ {
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f);
+ window->DrawList->AddImage(user_texture_id, bb.Min + ImVec2(1, 1), bb.Max - ImVec2(1, 1), uv0, uv1, GetColorU32(tint_col));
+ }
+ else
+ {
+ window->DrawList->AddImage(user_texture_id, bb.Min, bb.Max, uv0, uv1, GetColorU32(tint_col));
+ }
+}
+
+// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
+// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
+bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size + padding * 2);
+ ItemSize(bb);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+
+ // Render
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ RenderNavHighlight(bb, id);
+ RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding));
+ if (bg_col.w > 0.0f)
+ window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col));
+ window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
+
+ return pressed;
+}
+
+// frame_padding < 0: uses FramePadding from style (default)
+// frame_padding = 0: no framing
+// frame_padding > 0: set framing size
+bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ // Default to using texture ID as ID. User can still push string/integer prefixes.
+ PushID((void*)(intptr_t)user_texture_id);
+ const ImGuiID id = window->GetID("#image");
+ PopID();
+
+ const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float)frame_padding, (float)frame_padding) : g.Style.FramePadding;
+ return ImageButtonEx(id, user_texture_id, size, uv0, uv1, padding, bg_col, tint_col);
+}
+
+bool ImGui::Checkbox(const char* label, bool* v)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ const float square_sz = GetFrameHeight();
+ const ImVec2 pos = window->DC.CursorPos;
+ const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id))
+ {
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
+ return false;
+ }
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
+ if (pressed)
+ {
+ *v = !(*v);
+ MarkItemEdited(id);
+ }
+
+ const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
+ RenderNavHighlight(total_bb, id);
+ RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
+ ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
+ bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0;
+ if (mixed_value)
+ {
+ // Undocumented tristate/mixed/indeterminate checkbox (#2644)
+ // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox)
+ ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)));
+ window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding);
+ }
+ else if (*v)
+ {
+ const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
+ RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f);
+ }
+
+ ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
+ if (g.LogEnabled)
+ LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
+ if (label_size.x > 0.0f)
+ RenderText(label_pos, label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
+ return pressed;
+}
+
+template<typename T>
+bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
+{
+ bool all_on = (*flags & flags_value) == flags_value;
+ bool any_on = (*flags & flags_value) != 0;
+ bool pressed;
+ if (!all_on && any_on)
+ {
+ ImGuiContext& g = *GImGui;
+ ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
+ g.CurrentItemFlags |= ImGuiItemFlags_MixedValue;
+ pressed = Checkbox(label, &all_on);
+ g.CurrentItemFlags = backup_item_flags;
+ }
+ else
+ {
+ pressed = Checkbox(label, &all_on);
+
+ }
+ if (pressed)
+ {
+ if (all_on)
+ *flags |= flags_value;
+ else
+ *flags &= ~flags_value;
+ }
+ return pressed;
+}
+
+bool ImGui::CheckboxFlags(const char* label, int* flags, int flags_value)
+{
+ return CheckboxFlagsT(label, flags, flags_value);
+}
+
+bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value)
+{
+ return CheckboxFlagsT(label, flags, flags_value);
+}
+
+bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value)
+{
+ return CheckboxFlagsT(label, flags, flags_value);
+}
+
+bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value)
+{
+ return CheckboxFlagsT(label, flags, flags_value);
+}
+
+bool ImGui::RadioButton(const char* label, bool active)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ const float square_sz = GetFrameHeight();
+ const ImVec2 pos = window->DC.CursorPos;
+ const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz));
+ const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id))
+ return false;
+
+ ImVec2 center = check_bb.GetCenter();
+ center.x = IM_ROUND(center.x);
+ center.y = IM_ROUND(center.y);
+ const float radius = (square_sz - 1.0f) * 0.5f;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
+ if (pressed)
+ MarkItemEdited(id);
+
+ RenderNavHighlight(total_bb, id);
+ window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
+ if (active)
+ {
+ const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f));
+ window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark), 16);
+ }
+
+ if (style.FrameBorderSize > 0.0f)
+ {
+ window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), 16, style.FrameBorderSize);
+ window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), 16, style.FrameBorderSize);
+ }
+
+ ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y);
+ if (g.LogEnabled)
+ LogRenderedText(&label_pos, active ? "(x)" : "( )");
+ if (label_size.x > 0.0f)
+ RenderText(label_pos, label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return pressed;
+}
+
+// FIXME: This would work nicely if it was a public template, e.g. 'template<T> RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it..
+bool ImGui::RadioButton(const char* label, int* v, int v_button)
+{
+ const bool pressed = RadioButton(label, *v == v_button);
+ if (pressed)
+ *v = v_button;
+ return pressed;
+}
+
+// size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size
+void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ ImVec2 pos = window->DC.CursorPos;
+ ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f);
+ ImRect bb(pos, pos + size);
+ ItemSize(size, style.FramePadding.y);
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Render
+ fraction = ImSaturate(fraction);
+ RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
+ bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
+ const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);
+ RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
+
+ // Default displaying the fraction as percentage string, but user can override it
+ char overlay_buf[32];
+ if (!overlay)
+ {
+ ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f);
+ overlay = overlay_buf;
+ }
+
+ ImVec2 overlay_size = CalcTextSize(overlay, NULL);
+ if (overlay_size.x > 0.0f)
+ RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb);
+}
+
+void ImGui::Bullet()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize);
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
+ ItemSize(bb);
+ if (!ItemAdd(bb, 0))
+ {
+ SameLine(0, style.FramePadding.x * 2);
+ return;
+ }
+
+ // Render and stay on same line
+ ImU32 text_col = GetColorU32(ImGuiCol_Text);
+ RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f), text_col);
+ SameLine(0, style.FramePadding.x * 2.0f);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Low-level Layout helpers
+//-------------------------------------------------------------------------
+// - Spacing()
+// - Dummy()
+// - NewLine()
+// - AlignTextToFramePadding()
+// - SeparatorEx() [Internal]
+// - Separator()
+// - SplitterBehavior() [Internal]
+// - ShrinkWidths() [Internal]
+//-------------------------------------------------------------------------
+
+void ImGui::Spacing()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ItemSize(ImVec2(0, 0));
+}
+
+void ImGui::Dummy(const ImVec2& size)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(size);
+ ItemAdd(bb, 0);
+}
+
+void ImGui::NewLine()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiLayoutType backup_layout_type = window->DC.LayoutType;
+ window->DC.LayoutType = ImGuiLayoutType_Vertical;
+ if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
+ ItemSize(ImVec2(0, 0));
+ else
+ ItemSize(ImVec2(0.0f, g.FontSize));
+ window->DC.LayoutType = backup_layout_type;
+}
+
+void ImGui::AlignTextToFramePadding()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2);
+ window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y);
+}
+
+// Horizontal/vertical separating line
+void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
+
+ float thickness_draw = 1.0f;
+ float thickness_layout = 0.0f;
+ if (flags & ImGuiSeparatorFlags_Vertical)
+ {
+ // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
+ float y1 = window->DC.CursorPos.y;
+ float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y;
+ const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2));
+ ItemSize(ImVec2(thickness_layout, 0.0f));
+ if (!ItemAdd(bb, 0))
+ return;
+
+ // Draw
+ window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
+ if (g.LogEnabled)
+ LogText(" |");
+ }
+ else if (flags & ImGuiSeparatorFlags_Horizontal)
+ {
+ // Horizontal Separator
+ float x1 = window->Pos.x;
+ float x2 = window->Pos.x + window->Size.x;
+
+ // FIXME-WORKRECT: old hack (#205) until we decide of consistent behavior with WorkRect/Indent and Separator
+ if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID)
+ x1 += window->DC.Indent.x;
+
+ ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
+ if (columns)
+ PushColumnsBackground();
+
+ // We don't provide our width to the layout so that it doesn't get feed back into AutoFit
+ const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
+ ItemSize(ImVec2(0.0f, thickness_layout));
+ const bool item_visible = ItemAdd(bb, 0);
+ if (item_visible)
+ {
+ // Draw
+ window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator));
+ if (g.LogEnabled)
+ LogRenderedText(&bb.Min, "--------------------------------\n");
+
+ }
+ if (columns)
+ {
+ PopColumnsBackground();
+ columns->LineMinY = window->DC.CursorPos.y;
+ }
+ }
+}
+
+void ImGui::Separator()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ // Those flags should eventually be overridable by the user
+ ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
+ flags |= ImGuiSeparatorFlags_SpanAllColumns;
+ SeparatorEx(flags);
+}
+
+// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
+bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
+ g.CurrentItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
+ bool item_add = ItemAdd(bb, id);
+ g.CurrentItemFlags = item_flags_backup;
+ if (!item_add)
+ return false;
+
+ bool hovered, held;
+ ImRect bb_interact = bb;
+ bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
+ ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);
+ if (hovered)
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; // for IsItemHovered(), because bb_interact is larger than bb
+ if (g.ActiveId != id)
+ SetItemAllowOverlap();
+
+ if (held || (hovered && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay))
+ SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW);
+
+ ImRect bb_render = bb;
+ if (held)
+ {
+ ImVec2 mouse_delta_2d = g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min;
+ float mouse_delta = (axis == ImGuiAxis_Y) ? mouse_delta_2d.y : mouse_delta_2d.x;
+
+ // Minimum pane size
+ float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1);
+ float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2);
+ if (mouse_delta < -size_1_maximum_delta)
+ mouse_delta = -size_1_maximum_delta;
+ if (mouse_delta > size_2_maximum_delta)
+ mouse_delta = size_2_maximum_delta;
+
+ // Apply resize
+ if (mouse_delta != 0.0f)
+ {
+ if (mouse_delta < 0.0f)
+ IM_ASSERT(*size1 + mouse_delta >= min_size1);
+ if (mouse_delta > 0.0f)
+ IM_ASSERT(*size2 - mouse_delta >= min_size2);
+ *size1 += mouse_delta;
+ *size2 -= mouse_delta;
+ bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
+ MarkItemEdited(id);
+ }
+ }
+
+ // Render
+ const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
+ window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, 0.0f);
+
+ return held;
+}
+
+static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs)
+{
+ const ImGuiShrinkWidthItem* a = (const ImGuiShrinkWidthItem*)lhs;
+ const ImGuiShrinkWidthItem* b = (const ImGuiShrinkWidthItem*)rhs;
+ if (int d = (int)(b->Width - a->Width))
+ return d;
+ return (b->Index - a->Index);
+}
+
+// Shrink excess width from a set of item, by removing width from the larger items first.
+// Set items Width to -1.0f to disable shrinking this item.
+void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess)
+{
+ if (count == 1)
+ {
+ if (items[0].Width >= 0.0f)
+ items[0].Width = ImMax(items[0].Width - width_excess, 1.0f);
+ return;
+ }
+ ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer);
+ int count_same_width = 1;
+ while (width_excess > 0.0f && count_same_width < count)
+ {
+ while (count_same_width < count && items[0].Width <= items[count_same_width].Width)
+ count_same_width++;
+ float max_width_to_remove_per_item = (count_same_width < count && items[count_same_width].Width >= 0.0f) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f);
+ if (max_width_to_remove_per_item <= 0.0f)
+ break;
+ float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item);
+ for (int item_n = 0; item_n < count_same_width; item_n++)
+ items[item_n].Width -= width_to_remove_per_item;
+ width_excess -= width_to_remove_per_item * count_same_width;
+ }
+
+ // Round width and redistribute remainder left-to-right (could make it an option of the function?)
+ // Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator.
+ width_excess = 0.0f;
+ for (int n = 0; n < count; n++)
+ {
+ float width_rounded = ImFloor(items[n].Width);
+ width_excess += items[n].Width - width_rounded;
+ items[n].Width = width_rounded;
+ }
+ if (width_excess > 0.0f)
+ for (int n = 0; n < count; n++)
+ if (items[n].Index < (int)(width_excess + 0.01f))
+ items[n].Width += 1.0f;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: ComboBox
+//-------------------------------------------------------------------------
+// - CalcMaxPopupHeightFromItemCount() [Internal]
+// - BeginCombo()
+// - BeginComboPopup() [Internal]
+// - EndCombo()
+// - BeginComboPreview() [Internal]
+// - EndComboPreview() [Internal]
+// - Combo()
+//-------------------------------------------------------------------------
+
+static float CalcMaxPopupHeightFromItemCount(int items_count)
+{
+ ImGuiContext& g = *GImGui;
+ if (items_count <= 0)
+ return FLT_MAX;
+ return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
+}
+
+bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+
+ ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags;
+ g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
+ if (window->SkipItems)
+ return false;
+
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
+
+ const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth();
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
+ const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id, &bb))
+ return false;
+
+ // Open on click
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+ const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id);
+ bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);
+ if (pressed && !popup_open)
+ {
+ OpenPopupEx(popup_id, ImGuiPopupFlags_None);
+ popup_open = true;
+ }
+
+ // Render shape
+ const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
+ RenderNavHighlight(bb, id);
+ if (!(flags & ImGuiComboFlags_NoPreview))
+ window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
+ if (!(flags & ImGuiComboFlags_NoArrowButton))
+ {
+ ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
+ ImU32 text_col = GetColorU32(ImGuiCol_Text);
+ window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
+ if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x)
+ RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
+ }
+ RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);
+
+ // Custom preview
+ if (flags & ImGuiComboFlags_CustomPreview)
+ {
+ g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
+ IM_ASSERT(preview_value == NULL || preview_value[0] == 0);
+ preview_value = NULL;
+ }
+
+ // Render preview and label
+ if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
+ {
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("{", "}");
+ RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL);
+ }
+ if (label_size.x > 0)
+ RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label);
+
+ if (!popup_open)
+ return false;
+
+ g.NextWindowData.Flags = backup_next_window_data_flags;
+ return BeginComboPopup(popup_id, bb, flags);
+}
+
+bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if (!IsPopupOpen(popup_id, ImGuiPopupFlags_None))
+ {
+ g.NextWindowData.ClearFlags();
+ return false;
+ }
+
+ // Set popup size
+ float w = bb.GetWidth();
+ if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)
+ {
+ g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
+ }
+ else
+ {
+ if ((flags & ImGuiComboFlags_HeightMask_) == 0)
+ flags |= ImGuiComboFlags_HeightRegular;
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one
+ int popup_max_height_in_items = -1;
+ if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
+ else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
+ else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
+ SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
+ }
+
+ // This is essentially a specialized version of BeginPopupEx()
+ char name[16];
+ ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth
+
+ // Set position given a custom constraint (peak into expected window size so we can position it)
+ // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function?
+ // FIXME: This might be moved to Begin() or at least around the same spot where Tooltips and other Popups are calling FindBestWindowPosForPopupEx()?
+ if (ImGuiWindow* popup_window = FindWindowByName(name))
+ if (popup_window->WasActive)
+ {
+ // Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us.
+ ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window);
+ popup_window->AutoPosLastDirection = (flags & ImGuiComboFlags_PopupAlignLeft) ? ImGuiDir_Left : ImGuiDir_Down; // Left = "Below, Toward Left", Down = "Below, Toward Right (default)"
+ ImRect r_outer = GetPopupAllowedExtentRect(popup_window);
+ ImVec2 pos = FindBestWindowPosForPopupEx(bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, bb, ImGuiPopupPositionPolicy_ComboBox);
+ SetNextWindowPos(pos);
+ }
+
+ // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx()
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove;
+ PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y)); // Horizontally align ourselves with the framed text
+ bool ret = Begin(name, NULL, window_flags);
+ PopStyleVar();
+ if (!ret)
+ {
+ EndPopup();
+ IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
+ return false;
+ }
+ return true;
+}
+
+void ImGui::EndCombo()
+{
+ EndPopup();
+}
+
+// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements
+// (Experimental, see GitHub issues: #1658, #4168)
+bool ImGui::BeginComboPreview()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
+
+ if (window->SkipItems || !window->ClipRect.Overlaps(g.LastItemData.Rect)) // FIXME: Because we don't have a ImGuiItemStatusFlags_Visible flag to test last ItemAdd() result
+ return false;
+ IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag?
+ if (!window->ClipRect.Contains(preview_data->PreviewRect)) // Narrower test (optional)
+ return false;
+
+ // FIXME: This could be contained in a PushWorkRect() api
+ preview_data->BackupCursorPos = window->DC.CursorPos;
+ preview_data->BackupCursorMaxPos = window->DC.CursorMaxPos;
+ preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
+ preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
+ preview_data->BackupLayout = window->DC.LayoutType;
+ window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding;
+ window->DC.CursorMaxPos = window->DC.CursorPos;
+ window->DC.LayoutType = ImGuiLayoutType_Horizontal;
+ PushClipRect(preview_data->PreviewRect.Min, preview_data->PreviewRect.Max, true);
+
+ return true;
+}
+
+void ImGui::EndComboPreview()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
+
+ // FIXME: Using CursorMaxPos approximation instead of correct AABB which we will store in ImDrawCmd in the future
+ ImDrawList* draw_list = window->DrawList;
+ if (window->DC.CursorMaxPos.x < preview_data->PreviewRect.Max.x && window->DC.CursorMaxPos.y < preview_data->PreviewRect.Max.y)
+ if (draw_list->CmdBuffer.Size > 1) // Unlikely case that the PushClipRect() didn't create a command
+ {
+ draw_list->_CmdHeader.ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 2].ClipRect;
+ draw_list->_TryMergeDrawCmds();
+ }
+ PopClipRect();
+ window->DC.CursorPos = preview_data->BackupCursorPos;
+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos);
+ window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine;
+ window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset;
+ window->DC.LayoutType = preview_data->BackupLayout;
+ preview_data->PreviewRect = ImRect();
+}
+
+// Getter for the old Combo() API: const char*[]
+static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
+{
+ const char* const* items = (const char* const*)data;
+ if (out_text)
+ *out_text = items[idx];
+ return true;
+}
+
+// Getter for the old Combo() API: "item1\0item2\0item3\0"
+static bool Items_SingleStringGetter(void* data, int idx, const char** out_text)
+{
+ // FIXME-OPT: we could pre-compute the indices to fasten this. But only 1 active combo means the waste is limited.
+ const char* items_separated_by_zeros = (const char*)data;
+ int items_count = 0;
+ const char* p = items_separated_by_zeros;
+ while (*p)
+ {
+ if (idx == items_count)
+ break;
+ p += strlen(p) + 1;
+ items_count++;
+ }
+ if (!*p)
+ return false;
+ if (out_text)
+ *out_text = p;
+ return true;
+}
+
+// Old API, prefer using BeginCombo() nowadays if you can.
+bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Call the getter to obtain the preview string which is a parameter to BeginCombo()
+ const char* preview_value = NULL;
+ if (*current_item >= 0 && *current_item < items_count)
+ items_getter(data, *current_item, &preview_value);
+
+ // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here.
+ if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint))
+ SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
+
+ if (!BeginCombo(label, preview_value, ImGuiComboFlags_None))
+ return false;
+
+ // Display items
+ // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed)
+ bool value_changed = false;
+ for (int i = 0; i < items_count; i++)
+ {
+ PushID(i);
+ const bool item_selected = (i == *current_item);
+ const char* item_text;
+ if (!items_getter(data, i, &item_text))
+ item_text = "*Unknown item*";
+ if (Selectable(item_text, item_selected))
+ {
+ value_changed = true;
+ *current_item = i;
+ }
+ if (item_selected)
+ SetItemDefaultFocus();
+ PopID();
+ }
+
+ EndCombo();
+
+ if (value_changed)
+ MarkItemEdited(g.LastItemData.ID);
+
+ return value_changed;
+}
+
+// Combo box helper allowing to pass an array of strings.
+bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items)
+{
+ const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items);
+ return value_changed;
+}
+
+// Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0"
+bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items)
+{
+ int items_count = 0;
+ const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open
+ while (*p)
+ {
+ p += strlen(p) + 1;
+ items_count++;
+ }
+ bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items);
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Data Type and Data Formatting Helpers [Internal]
+//-------------------------------------------------------------------------
+// - PatchFormatStringFloatToInt()
+// - DataTypeGetInfo()
+// - DataTypeFormatString()
+// - DataTypeApplyOp()
+// - DataTypeApplyOpFromText()
+// - DataTypeClamp()
+// - GetMinimumStepAtDecimalPrecision
+// - RoundScalarWithFormat<>()
+//-------------------------------------------------------------------------
+
+static const ImGuiDataTypeInfo GDataTypeInfo[] =
+{
+ { sizeof(char), "S8", "%d", "%d" }, // ImGuiDataType_S8
+ { sizeof(unsigned char), "U8", "%u", "%u" },
+ { sizeof(short), "S16", "%d", "%d" }, // ImGuiDataType_S16
+ { sizeof(unsigned short), "U16", "%u", "%u" },
+ { sizeof(int), "S32", "%d", "%d" }, // ImGuiDataType_S32
+ { sizeof(unsigned int), "U32", "%u", "%u" },
+#ifdef _MSC_VER
+ { sizeof(ImS64), "S64", "%I64d","%I64d" }, // ImGuiDataType_S64
+ { sizeof(ImU64), "U64", "%I64u","%I64u" },
+#else
+ { sizeof(ImS64), "S64", "%lld", "%lld" }, // ImGuiDataType_S64
+ { sizeof(ImU64), "U64", "%llu", "%llu" },
+#endif
+ { sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
+ { sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double
+};
+IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
+
+// FIXME-LEGACY: Prior to 1.61 our DragInt() function internally used floats and because of this the compile-time default value for format was "%.0f".
+// Even though we changed the compile-time default, we expect users to have carried %f around, which would break the display of DragInt() calls.
+// To honor backward compatibility we are rewriting the format string, unless IMGUI_DISABLE_OBSOLETE_FUNCTIONS is enabled. What could possibly go wrong?!
+static const char* PatchFormatStringFloatToInt(const char* fmt)
+{
+ if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '0' && fmt[3] == 'f' && fmt[4] == 0) // Fast legacy path for "%.0f" which is expected to be the most common case.
+ return "%d";
+ const char* fmt_start = ImParseFormatFindStart(fmt); // Find % (if any, and ignore %%)
+ const char* fmt_end = ImParseFormatFindEnd(fmt_start); // Find end of format specifier, which itself is an exercise of confidence/recklessness (because snprintf is dependent on libc or user).
+ if (fmt_end > fmt_start && fmt_end[-1] == 'f')
+ {
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ if (fmt_start == fmt && fmt_end[0] == 0)
+ return "%d";
+ ImGuiContext& g = *GImGui;
+ ImFormatString(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), "%.*s%%d%s", (int)(fmt_start - fmt), fmt, fmt_end); // Honor leading and trailing decorations, but lose alignment/precision.
+ return g.TempBuffer;
+#else
+ IM_ASSERT(0 && "DragInt(): Invalid format string!"); // Old versions used a default parameter of "%.0f", please replace with e.g. "%d"
+#endif
+ }
+ return fmt;
+}
+
+const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type)
+{
+ IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
+ return &GDataTypeInfo[data_type];
+}
+
+int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format)
+{
+ // Signedness doesn't matter when pushing integer arguments
+ if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32)
+ return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data);
+ if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
+ return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data);
+ if (data_type == ImGuiDataType_Float)
+ return ImFormatString(buf, buf_size, format, *(const float*)p_data);
+ if (data_type == ImGuiDataType_Double)
+ return ImFormatString(buf, buf_size, format, *(const double*)p_data);
+ if (data_type == ImGuiDataType_S8)
+ return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data);
+ if (data_type == ImGuiDataType_U8)
+ return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data);
+ if (data_type == ImGuiDataType_S16)
+ return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data);
+ if (data_type == ImGuiDataType_U16)
+ return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data);
+ IM_ASSERT(0);
+ return 0;
+}
+
+void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg1, const void* arg2)
+{
+ IM_ASSERT(op == '+' || op == '-');
+ switch (data_type)
+ {
+ case ImGuiDataType_S8:
+ if (op == '+') { *(ImS8*)output = ImAddClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); }
+ if (op == '-') { *(ImS8*)output = ImSubClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); }
+ return;
+ case ImGuiDataType_U8:
+ if (op == '+') { *(ImU8*)output = ImAddClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); }
+ if (op == '-') { *(ImU8*)output = ImSubClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); }
+ return;
+ case ImGuiDataType_S16:
+ if (op == '+') { *(ImS16*)output = ImAddClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); }
+ if (op == '-') { *(ImS16*)output = ImSubClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); }
+ return;
+ case ImGuiDataType_U16:
+ if (op == '+') { *(ImU16*)output = ImAddClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); }
+ if (op == '-') { *(ImU16*)output = ImSubClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); }
+ return;
+ case ImGuiDataType_S32:
+ if (op == '+') { *(ImS32*)output = ImAddClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); }
+ if (op == '-') { *(ImS32*)output = ImSubClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); }
+ return;
+ case ImGuiDataType_U32:
+ if (op == '+') { *(ImU32*)output = ImAddClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); }
+ if (op == '-') { *(ImU32*)output = ImSubClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); }
+ return;
+ case ImGuiDataType_S64:
+ if (op == '+') { *(ImS64*)output = ImAddClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); }
+ if (op == '-') { *(ImS64*)output = ImSubClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); }
+ return;
+ case ImGuiDataType_U64:
+ if (op == '+') { *(ImU64*)output = ImAddClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); }
+ if (op == '-') { *(ImU64*)output = ImSubClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); }
+ return;
+ case ImGuiDataType_Float:
+ if (op == '+') { *(float*)output = *(const float*)arg1 + *(const float*)arg2; }
+ if (op == '-') { *(float*)output = *(const float*)arg1 - *(const float*)arg2; }
+ return;
+ case ImGuiDataType_Double:
+ if (op == '+') { *(double*)output = *(const double*)arg1 + *(const double*)arg2; }
+ if (op == '-') { *(double*)output = *(const double*)arg1 - *(const double*)arg2; }
+ return;
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+}
+
+// User can input math operators (e.g. +100) to edit a numerical values.
+// NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess..
+bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* p_data, const char* format)
+{
+ while (ImCharIsBlankA(*buf))
+ buf++;
+
+ // We don't support '-' op because it would conflict with inputing negative value.
+ // Instead you can use +-100 to subtract from an existing value
+ char op = buf[0];
+ if (op == '+' || op == '*' || op == '/')
+ {
+ buf++;
+ while (ImCharIsBlankA(*buf))
+ buf++;
+ }
+ else
+ {
+ op = 0;
+ }
+ if (!buf[0])
+ return false;
+
+ // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all.
+ const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type);
+ ImGuiDataTypeTempStorage data_backup;
+ memcpy(&data_backup, p_data, type_info->Size);
+
+ if (format == NULL)
+ format = type_info->ScanFmt;
+
+ // FIXME-LEGACY: The aim is to remove those operators and write a proper expression evaluator at some point..
+ int arg1i = 0;
+ if (data_type == ImGuiDataType_S32)
+ {
+ int* v = (int*)p_data;
+ int arg0i = *v;
+ float arg1f = 0.0f;
+ if (op && sscanf(initial_value_buf, format, &arg0i) < 1)
+ return false;
+ // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision
+ if (op == '+') { if (sscanf(buf, "%d", &arg1i)) *v = (int)(arg0i + arg1i); } // Add (use "+-" to subtract)
+ else if (op == '*') { if (sscanf(buf, "%f", &arg1f)) *v = (int)(arg0i * arg1f); } // Multiply
+ else if (op == '/') { if (sscanf(buf, "%f", &arg1f) && arg1f != 0.0f) *v = (int)(arg0i / arg1f); } // Divide
+ else { if (sscanf(buf, format, &arg1i) == 1) *v = arg1i; } // Assign constant
+ }
+ else if (data_type == ImGuiDataType_Float)
+ {
+ // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in
+ format = "%f";
+ float* v = (float*)p_data;
+ float arg0f = *v, arg1f = 0.0f;
+ if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
+ return false;
+ if (sscanf(buf, format, &arg1f) < 1)
+ return false;
+ if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
+ else if (op == '*') { *v = arg0f * arg1f; } // Multiply
+ else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
+ else { *v = arg1f; } // Assign constant
+ }
+ else if (data_type == ImGuiDataType_Double)
+ {
+ format = "%lf"; // scanf differentiate float/double unlike printf which forces everything to double because of ellipsis
+ double* v = (double*)p_data;
+ double arg0f = *v, arg1f = 0.0;
+ if (op && sscanf(initial_value_buf, format, &arg0f) < 1)
+ return false;
+ if (sscanf(buf, format, &arg1f) < 1)
+ return false;
+ if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract)
+ else if (op == '*') { *v = arg0f * arg1f; } // Multiply
+ else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide
+ else { *v = arg1f; } // Assign constant
+ }
+ else if (data_type == ImGuiDataType_U32 || data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64)
+ {
+ // All other types assign constant
+ // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
+ if (sscanf(buf, format, p_data) < 1)
+ return false;
+ }
+ else
+ {
+ // Small types need a 32-bit buffer to receive the result from scanf()
+ int v32;
+ if (sscanf(buf, format, &v32) < 1)
+ return false;
+ if (data_type == ImGuiDataType_S8)
+ *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
+ else if (data_type == ImGuiDataType_U8)
+ *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX);
+ else if (data_type == ImGuiDataType_S16)
+ *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX);
+ else if (data_type == ImGuiDataType_U16)
+ *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX);
+ else
+ IM_ASSERT(0);
+ }
+
+ return memcmp(&data_backup, p_data, type_info->Size) != 0;
+}
+
+template<typename T>
+static int DataTypeCompareT(const T* lhs, const T* rhs)
+{
+ if (*lhs < *rhs) return -1;
+ if (*lhs > *rhs) return +1;
+ return 0;
+}
+
+int ImGui::DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2)
+{
+ switch (data_type)
+ {
+ case ImGuiDataType_S8: return DataTypeCompareT<ImS8 >((const ImS8* )arg_1, (const ImS8* )arg_2);
+ case ImGuiDataType_U8: return DataTypeCompareT<ImU8 >((const ImU8* )arg_1, (const ImU8* )arg_2);
+ case ImGuiDataType_S16: return DataTypeCompareT<ImS16 >((const ImS16* )arg_1, (const ImS16* )arg_2);
+ case ImGuiDataType_U16: return DataTypeCompareT<ImU16 >((const ImU16* )arg_1, (const ImU16* )arg_2);
+ case ImGuiDataType_S32: return DataTypeCompareT<ImS32 >((const ImS32* )arg_1, (const ImS32* )arg_2);
+ case ImGuiDataType_U32: return DataTypeCompareT<ImU32 >((const ImU32* )arg_1, (const ImU32* )arg_2);
+ case ImGuiDataType_S64: return DataTypeCompareT<ImS64 >((const ImS64* )arg_1, (const ImS64* )arg_2);
+ case ImGuiDataType_U64: return DataTypeCompareT<ImU64 >((const ImU64* )arg_1, (const ImU64* )arg_2);
+ case ImGuiDataType_Float: return DataTypeCompareT<float >((const float* )arg_1, (const float* )arg_2);
+ case ImGuiDataType_Double: return DataTypeCompareT<double>((const double*)arg_1, (const double*)arg_2);
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+ return 0;
+}
+
+template<typename T>
+static bool DataTypeClampT(T* v, const T* v_min, const T* v_max)
+{
+ // Clamp, both sides are optional, return true if modified
+ if (v_min && *v < *v_min) { *v = *v_min; return true; }
+ if (v_max && *v > *v_max) { *v = *v_max; return true; }
+ return false;
+}
+
+bool ImGui::DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max)
+{
+ switch (data_type)
+ {
+ case ImGuiDataType_S8: return DataTypeClampT<ImS8 >((ImS8* )p_data, (const ImS8* )p_min, (const ImS8* )p_max);
+ case ImGuiDataType_U8: return DataTypeClampT<ImU8 >((ImU8* )p_data, (const ImU8* )p_min, (const ImU8* )p_max);
+ case ImGuiDataType_S16: return DataTypeClampT<ImS16 >((ImS16* )p_data, (const ImS16* )p_min, (const ImS16* )p_max);
+ case ImGuiDataType_U16: return DataTypeClampT<ImU16 >((ImU16* )p_data, (const ImU16* )p_min, (const ImU16* )p_max);
+ case ImGuiDataType_S32: return DataTypeClampT<ImS32 >((ImS32* )p_data, (const ImS32* )p_min, (const ImS32* )p_max);
+ case ImGuiDataType_U32: return DataTypeClampT<ImU32 >((ImU32* )p_data, (const ImU32* )p_min, (const ImU32* )p_max);
+ case ImGuiDataType_S64: return DataTypeClampT<ImS64 >((ImS64* )p_data, (const ImS64* )p_min, (const ImS64* )p_max);
+ case ImGuiDataType_U64: return DataTypeClampT<ImU64 >((ImU64* )p_data, (const ImU64* )p_min, (const ImU64* )p_max);
+ case ImGuiDataType_Float: return DataTypeClampT<float >((float* )p_data, (const float* )p_min, (const float* )p_max);
+ case ImGuiDataType_Double: return DataTypeClampT<double>((double*)p_data, (const double*)p_min, (const double*)p_max);
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+ return false;
+}
+
+static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
+{
+ static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f };
+ if (decimal_precision < 0)
+ return FLT_MIN;
+ return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision);
+}
+
+template<typename TYPE>
+static const char* ImAtoi(const char* src, TYPE* output)
+{
+ int negative = 0;
+ if (*src == '-') { negative = 1; src++; }
+ if (*src == '+') { src++; }
+ TYPE v = 0;
+ while (*src >= '0' && *src <= '9')
+ v = (v * 10) + (*src++ - '0');
+ *output = negative ? -v : v;
+ return src;
+}
+
+// Sanitize format
+// - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi
+// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi.
+static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size)
+{
+ IM_UNUSED(fmt_out_size);
+ const char* fmt_end = ImParseFormatFindEnd(fmt);
+ IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
+ while (fmt < fmt_end)
+ {
+ char c = *(fmt++);
+ if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
+ *(fmt_out++) = c;
+ }
+ *fmt_out = 0; // Zero-terminate
+}
+
+template<typename TYPE, typename SIGNEDTYPE>
+TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v)
+{
+ const char* fmt_start = ImParseFormatFindStart(format);
+ if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string
+ return v;
+
+ // Sanitize format
+ char fmt_sanitized[32];
+ SanitizeFormatString(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized));
+ fmt_start = fmt_sanitized;
+
+ // Format value with our rounding, and read back
+ char v_str[64];
+ ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v);
+ const char* p = v_str;
+ while (*p == ' ')
+ p++;
+ if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
+ v = (TYPE)ImAtof(p);
+ else
+ ImAtoi(p, (SIGNEDTYPE*)&v);
+ return v;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc.
+//-------------------------------------------------------------------------
+// - DragBehaviorT<>() [Internal]
+// - DragBehavior() [Internal]
+// - DragScalar()
+// - DragScalarN()
+// - DragFloat()
+// - DragFloat2()
+// - DragFloat3()
+// - DragFloat4()
+// - DragFloatRange2()
+// - DragInt()
+// - DragInt2()
+// - DragInt3()
+// - DragInt4()
+// - DragIntRange2()
+//-------------------------------------------------------------------------
+
+// This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls)
+template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
+bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
+ const bool is_clamped = (v_min < v_max);
+ const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
+ const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
+
+ // Default tweak speed
+ if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX))
+ v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio);
+
+ // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings
+ float adjust_delta = 0.0f;
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
+ {
+ adjust_delta = g.IO.MouseDelta[axis];
+ if (g.IO.KeyAlt)
+ adjust_delta *= 1.0f / 100.0f;
+ if (g.IO.KeyShift)
+ adjust_delta *= 10.0f;
+ }
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ {
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
+ adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis];
+ v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
+ }
+ adjust_delta *= v_speed;
+
+ // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter.
+ if (axis == ImGuiAxis_Y)
+ adjust_delta = -adjust_delta;
+
+ // For logarithmic use our range is effectively 0..1 so scale the delta into that range
+ if (is_logarithmic && (v_max - v_min < FLT_MAX) && ((v_max - v_min) > 0.000001f)) // Epsilon to avoid /0
+ adjust_delta /= (float)(v_max - v_min);
+
+ // Clear current value on activation
+ // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300.
+ bool is_just_activated = g.ActiveIdIsJustActivated;
+ bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f));
+ if (is_just_activated || is_already_past_limits_and_pushing_outward)
+ {
+ g.DragCurrentAccum = 0.0f;
+ g.DragCurrentAccumDirty = false;
+ }
+ else if (adjust_delta != 0.0f)
+ {
+ g.DragCurrentAccum += adjust_delta;
+ g.DragCurrentAccumDirty = true;
+ }
+
+ if (!g.DragCurrentAccumDirty)
+ return false;
+
+ TYPE v_cur = *v;
+ FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f;
+
+ float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true
+ const float zero_deadzone_halfsize = 0.0f; // Drag widgets have no deadzone (as it doesn't make sense)
+ if (is_logarithmic)
+ {
+ // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound.
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
+ logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
+
+ // Convert to parametric space, apply delta, convert back
+ float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+ float v_new_parametric = v_old_parametric + g.DragCurrentAccum;
+ v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+ v_old_ref_for_accum_remainder = v_old_parametric;
+ }
+ else
+ {
+ v_cur += (SIGNEDTYPE)g.DragCurrentAccum;
+ }
+
+ // Round to user desired precision based on format string
+ if (!(flags & ImGuiSliderFlags_NoRoundToFormat))
+ v_cur = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_cur);
+
+ // Preserve remainder after rounding has been applied. This also allow slow tweaking of values.
+ g.DragCurrentAccumDirty = false;
+ if (is_logarithmic)
+ {
+ // Convert to parametric space, apply delta, convert back
+ float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+ g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder);
+ }
+ else
+ {
+ g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v);
+ }
+
+ // Lose zero sign for float/double
+ if (v_cur == (TYPE)-0)
+ v_cur = (TYPE)0;
+
+ // Clamp values (+ handle overflow/wrap-around for integer types)
+ if (*v != v_cur && is_clamped)
+ {
+ if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_floating_point))
+ v_cur = v_min;
+ if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_floating_point))
+ v_cur = v_max;
+ }
+
+ // Apply result
+ if (*v == v_cur)
+ return false;
+ *v = v_cur;
+ return true;
+}
+
+bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
+{
+ // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert.
+ IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
+
+ ImGuiContext& g = *GImGui;
+ if (g.ActiveId == id)
+ {
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
+ ClearActiveID();
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
+ ClearActiveID();
+ }
+ if (g.ActiveId != id)
+ return false;
+ if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
+ return false;
+
+ switch (data_type)
+ {
+ case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
+ case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
+ case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT<ImS32, ImS32, float>(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
+ case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT<ImU32, ImS32, float>(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
+ case ImGuiDataType_S32: return DragBehaviorT<ImS32, ImS32, float >(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, flags);
+ case ImGuiDataType_U32: return DragBehaviorT<ImU32, ImS32, float >(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, flags);
+ case ImGuiDataType_S64: return DragBehaviorT<ImS64, ImS64, double>(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, flags);
+ case ImGuiDataType_U64: return DragBehaviorT<ImU64, ImS64, double>(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, flags);
+ case ImGuiDataType_Float: return DragBehaviorT<float, float, float >(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, flags);
+ case ImGuiDataType_Double: return DragBehaviorT<double,double,double>(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, flags);
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+ return false;
+}
+
+// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional.
+// Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
+bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
+ return false;
+
+ // Default format string when passing NULL
+ if (format == NULL)
+ format = DataTypeGetInfo(data_type)->PrintFmt;
+ else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.)
+ format = PatchFormatStringFloatToInt(format);
+
+ // Tabbing or CTRL-clicking on Drag turns it into an InputText
+ const bool hovered = ItemHoverable(frame_bb, id);
+ bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
+ if (!temp_input_is_active)
+ {
+ const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
+ const bool clicked = (hovered && g.IO.MouseClicked[0]);
+ const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2);
+ if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id)
+ {
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ if (temp_input_allowed)
+ if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id)
+ temp_input_is_active = true;
+ }
+
+ // Experimental: simple click (without moving) turns Drag into an InputText
+ if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active)
+ if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
+ {
+ g.NavActivateId = g.NavActivateInputId = id;
+ g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
+ temp_input_is_active = true;
+ }
+ }
+
+ if (temp_input_is_active)
+ {
+ // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set
+ const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0 && (p_min == NULL || p_max == NULL || DataTypeCompare(data_type, p_min, p_max) < 0);
+ return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL);
+ }
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);
+
+ // Drag behavior
+ const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, flags);
+ if (value_changed)
+ MarkItemEdited(id);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("{", "}");
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return value_changed;
+}
+
+bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ PushMultiItemsWidths(components, CalcItemWidth());
+ size_t type_size = GDataTypeInfo[data_type].Size;
+ for (int i = 0; i < components; i++)
+ {
+ PushID(i);
+ if (i > 0)
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, flags);
+ PopID();
+ PopItemWidth();
+ p_data = (void*)((char*)p_data + type_size);
+ }
+ PopID();
+
+ const char* label_end = FindRenderedTextEnd(label);
+ if (label != label_end)
+ {
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ TextEx(label, label_end);
+ }
+
+ EndGroup();
+ return value_changed;
+}
+
+bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags);
+}
+
+// NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this.
+bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ PushID(label);
+ BeginGroup();
+ PushMultiItemsWidths(2, CalcItemWidth());
+
+ float min_min = (v_min >= v_max) ? -FLT_MAX : v_min;
+ float min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max);
+ ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0);
+ bool value_changed = DragScalar("##min", ImGuiDataType_Float, v_current_min, v_speed, &min_min, &min_max, format, min_flags);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+
+ float max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min);
+ float max_max = (v_min >= v_max) ? FLT_MAX : v_max;
+ ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0);
+ value_changed |= DragScalar("##max", ImGuiDataType_Float, v_current_max, v_speed, &max_min, &max_max, format_max ? format_max : format, max_flags);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+
+ TextEx(label, FindRenderedTextEnd(label));
+ EndGroup();
+ PopID();
+
+ return value_changed;
+}
+
+// NB: v_speed is float to allow adjusting the drag speed with more precision
+bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format, flags);
+}
+
+// NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this.
+bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ PushID(label);
+ BeginGroup();
+ PushMultiItemsWidths(2, CalcItemWidth());
+
+ int min_min = (v_min >= v_max) ? INT_MIN : v_min;
+ int min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max);
+ ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0);
+ bool value_changed = DragInt("##min", v_current_min, v_speed, min_min, min_max, format, min_flags);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+
+ int max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min);
+ int max_max = (v_min >= v_max) ? INT_MAX : v_max;
+ ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0);
+ value_changed |= DragInt("##max", v_current_max, v_speed, max_min, max_max, format_max ? format_max : format, max_flags);
+ PopItemWidth();
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+
+ TextEx(label, FindRenderedTextEnd(label));
+ EndGroup();
+ PopID();
+
+ return value_changed;
+}
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+// Obsolete versions with power parameter. See https://github.com/ocornut/imgui/issues/3361 for details.
+bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
+{
+ ImGuiSliderFlags drag_flags = ImGuiSliderFlags_None;
+ if (power != 1.0f)
+ {
+ IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
+ IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds
+ drag_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths
+ }
+ return DragScalar(label, data_type, p_data, v_speed, p_min, p_max, format, drag_flags);
+}
+
+bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power)
+{
+ ImGuiSliderFlags drag_flags = ImGuiSliderFlags_None;
+ if (power != 1.0f)
+ {
+ IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
+ IM_ASSERT(p_min != NULL && p_max != NULL); // When using a power curve the drag needs to have known bounds
+ drag_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths
+ }
+ return DragScalarN(label, data_type, p_data, components, v_speed, p_min, p_max, format, drag_flags);
+}
+
+#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc.
+//-------------------------------------------------------------------------
+// - ScaleRatioFromValueT<> [Internal]
+// - ScaleValueFromRatioT<> [Internal]
+// - SliderBehaviorT<>() [Internal]
+// - SliderBehavior() [Internal]
+// - SliderScalar()
+// - SliderScalarN()
+// - SliderFloat()
+// - SliderFloat2()
+// - SliderFloat3()
+// - SliderFloat4()
+// - SliderAngle()
+// - SliderInt()
+// - SliderInt2()
+// - SliderInt3()
+// - SliderInt4()
+// - VSliderScalar()
+// - VSliderFloat()
+// - VSliderInt()
+//-------------------------------------------------------------------------
+
+// Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT)
+template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
+float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
+{
+ if (v_min == v_max)
+ return 0.0f;
+ IM_UNUSED(data_type);
+
+ const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
+ if (is_logarithmic)
+ {
+ bool flipped = v_max < v_min;
+
+ if (flipped) // Handle the case where the range is backwards
+ ImSwap(v_min, v_max);
+
+ // Fudge min/max to avoid getting close to log(0)
+ FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
+ FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max;
+
+ // Awkward special cases - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon)
+ if ((v_min == 0.0f) && (v_max < 0.0f))
+ v_min_fudged = -logarithmic_zero_epsilon;
+ else if ((v_max == 0.0f) && (v_min < 0.0f))
+ v_max_fudged = -logarithmic_zero_epsilon;
+
+ float result;
+
+ if (v_clamped <= v_min_fudged)
+ result = 0.0f; // Workaround for values that are in-range but below our fudge
+ else if (v_clamped >= v_max_fudged)
+ result = 1.0f; // Workaround for values that are in-range but above our fudge
+ else if ((v_min * v_max) < 0.0f) // Range crosses zero, so split into two portions
+ {
+ float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine)
+ float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
+ float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize;
+ if (v == 0.0f)
+ result = zero_point_center; // Special case for exactly zero
+ else if (v < 0.0f)
+ result = (1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(-v_min_fudged / logarithmic_zero_epsilon))) * zero_point_snap_L;
+ else
+ result = zero_point_snap_R + ((float)(ImLog((FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(v_max_fudged / logarithmic_zero_epsilon)) * (1.0f - zero_point_snap_R));
+ }
+ else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider
+ result = 1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / -v_max_fudged) / ImLog(-v_min_fudged / -v_max_fudged));
+ else
+ result = (float)(ImLog((FLOATTYPE)v_clamped / v_min_fudged) / ImLog(v_max_fudged / v_min_fudged));
+
+ return flipped ? (1.0f - result) : result;
+ }
+
+ // Linear slider
+ return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min));
+}
+
+// Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT)
+template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
+TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
+{
+ if (v_min == v_max)
+ return v_min;
+ const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
+
+ TYPE result;
+ if (is_logarithmic)
+ {
+ // We special-case the extents because otherwise our fudging can lead to "mathematically correct" but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value
+ if (t <= 0.0f)
+ result = v_min;
+ else if (t >= 1.0f)
+ result = v_max;
+ else
+ {
+ bool flipped = v_max < v_min; // Check if range is "backwards"
+
+ // Fudge min/max to avoid getting silly results close to zero
+ FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
+ FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max;
+
+ if (flipped)
+ ImSwap(v_min_fudged, v_max_fudged);
+
+ // Awkward special case - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon)
+ if ((v_max == 0.0f) && (v_min < 0.0f))
+ v_max_fudged = -logarithmic_zero_epsilon;
+
+ float t_with_flip = flipped ? (1.0f - t) : t; // t, but flipped if necessary to account for us flipping the range
+
+ if ((v_min * v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts
+ {
+ float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min); // The zero point in parametric space
+ float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize;
+ float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize;
+ if (t_with_flip >= zero_point_snap_L && t_with_flip <= zero_point_snap_R)
+ result = (TYPE)0.0f; // Special case to make getting exactly zero possible (the epsilon prevents it otherwise)
+ else if (t_with_flip < zero_point_center)
+ result = (TYPE)-(logarithmic_zero_epsilon * ImPow(-v_min_fudged / logarithmic_zero_epsilon, (FLOATTYPE)(1.0f - (t_with_flip / zero_point_snap_L))));
+ else
+ result = (TYPE)(logarithmic_zero_epsilon * ImPow(v_max_fudged / logarithmic_zero_epsilon, (FLOATTYPE)((t_with_flip - zero_point_snap_R) / (1.0f - zero_point_snap_R))));
+ }
+ else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider
+ result = (TYPE)-(-v_max_fudged * ImPow(-v_min_fudged / -v_max_fudged, (FLOATTYPE)(1.0f - t_with_flip)));
+ else
+ result = (TYPE)(v_min_fudged * ImPow(v_max_fudged / v_min_fudged, (FLOATTYPE)t_with_flip));
+ }
+ }
+ else
+ {
+ // Linear slider
+ if (is_floating_point)
+ {
+ result = ImLerp(v_min, v_max, t);
+ }
+ else
+ {
+ // - For integer values we want the clicking position to match the grab box so we round above
+ // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property..
+ // - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64
+ // range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits.
+ if (t < 1.0)
+ {
+ FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t;
+ result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5)));
+ }
+ else
+ {
+ result = v_max;
+ }
+ }
+ }
+
+ return result;
+}
+
+// FIXME: Move more of the code into SliderBehavior()
+template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
+bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb)
+{
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
+ const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
+ const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
+
+ const float grab_padding = 2.0f;
+ const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
+ float grab_sz = style.GrabMinSize;
+ SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
+ if (!is_floating_point && v_range >= 0) // v_range < 0 may happen on integer overflows
+ grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit
+ grab_sz = ImMin(grab_sz, slider_sz);
+ const float slider_usable_sz = slider_sz - grab_sz;
+ const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f;
+ const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f;
+
+ float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true
+ float zero_deadzone_halfsize = 0.0f; // Only valid when is_logarithmic is true
+ if (is_logarithmic)
+ {
+ // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound.
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
+ logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
+ zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f);
+ }
+
+ // Process interacting with the slider
+ bool value_changed = false;
+ if (g.ActiveId == id)
+ {
+ bool set_new_value = false;
+ float clicked_t = 0.0f;
+ if (g.ActiveIdSource == ImGuiInputSource_Mouse)
+ {
+ if (!g.IO.MouseDown[0])
+ {
+ ClearActiveID();
+ }
+ else
+ {
+ const float mouse_abs_pos = g.IO.MousePos[axis];
+ clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f;
+ if (axis == ImGuiAxis_Y)
+ clicked_t = 1.0f - clicked_t;
+ set_new_value = true;
+ }
+ }
+ else if (g.ActiveIdSource == ImGuiInputSource_Nav)
+ {
+ if (g.ActiveIdIsJustActivated)
+ {
+ g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation
+ g.SliderCurrentAccumDirty = false;
+ }
+
+ const ImVec2 input_delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f);
+ float input_delta = (axis == ImGuiAxis_X) ? input_delta2.x : -input_delta2.y;
+ if (input_delta != 0.0f)
+ {
+ const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
+ if (decimal_precision > 0)
+ {
+ input_delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
+ if (IsNavInputDown(ImGuiNavInput_TweakSlow))
+ input_delta /= 10.0f;
+ }
+ else
+ {
+ if ((v_range >= -100.0f && v_range <= 100.0f) || IsNavInputDown(ImGuiNavInput_TweakSlow))
+ input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / (float)v_range; // Gamepad/keyboard tweak speeds in integer steps
+ else
+ input_delta /= 100.0f;
+ }
+ if (IsNavInputDown(ImGuiNavInput_TweakFast))
+ input_delta *= 10.0f;
+
+ g.SliderCurrentAccum += input_delta;
+ g.SliderCurrentAccumDirty = true;
+ }
+
+ float delta = g.SliderCurrentAccum;
+ if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
+ {
+ ClearActiveID();
+ }
+ else if (g.SliderCurrentAccumDirty)
+ {
+ clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+
+ if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits
+ {
+ set_new_value = false;
+ g.SliderCurrentAccum = 0.0f; // If pushing up against the limits, don't continue to accumulate
+ }
+ else
+ {
+ set_new_value = true;
+ float old_clicked_t = clicked_t;
+ clicked_t = ImSaturate(clicked_t + delta);
+
+ // Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator
+ TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+ if (!(flags & ImGuiSliderFlags_NoRoundToFormat))
+ v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new);
+ float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+
+ if (delta > 0)
+ g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta);
+ else
+ g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta);
+ }
+
+ g.SliderCurrentAccumDirty = false;
+ }
+ }
+
+ if (set_new_value)
+ {
+ TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+
+ // Round to user desired precision based on format string
+ if (!(flags & ImGuiSliderFlags_NoRoundToFormat))
+ v_new = RoundScalarWithFormatT<TYPE, SIGNEDTYPE>(format, data_type, v_new);
+
+ // Apply result
+ if (*v != v_new)
+ {
+ *v = v_new;
+ value_changed = true;
+ }
+ }
+ }
+
+ if (slider_sz < 1.0f)
+ {
+ *out_grab_bb = ImRect(bb.Min, bb.Min);
+ }
+ else
+ {
+ // Output grab position so it can be displayed by the caller
+ float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
+ if (axis == ImGuiAxis_Y)
+ grab_t = 1.0f - grab_t;
+ const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
+ if (axis == ImGuiAxis_X)
+ *out_grab_bb = ImRect(grab_pos - grab_sz * 0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz * 0.5f, bb.Max.y - grab_padding);
+ else
+ *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f);
+ }
+
+ return value_changed;
+}
+
+// For 32-bit and larger types, slider bounds are limited to half the natural type range.
+// So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok.
+// It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders.
+bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb)
+{
+ // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert.
+ IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
+
+ ImGuiContext& g = *GImGui;
+ if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
+ return false;
+
+ switch (data_type)
+ {
+ case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; }
+ case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; }
+ case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT<ImS32, ImS32, float>(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; }
+ case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT<ImU32, ImS32, float>(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; }
+ case ImGuiDataType_S32:
+ IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN / 2 && *(const ImS32*)p_max <= IM_S32_MAX / 2);
+ return SliderBehaviorT<ImS32, ImS32, float >(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, flags, out_grab_bb);
+ case ImGuiDataType_U32:
+ IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX / 2);
+ return SliderBehaviorT<ImU32, ImS32, float >(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, flags, out_grab_bb);
+ case ImGuiDataType_S64:
+ IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN / 2 && *(const ImS64*)p_max <= IM_S64_MAX / 2);
+ return SliderBehaviorT<ImS64, ImS64, double>(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, flags, out_grab_bb);
+ case ImGuiDataType_U64:
+ IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX / 2);
+ return SliderBehaviorT<ImU64, ImS64, double>(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, flags, out_grab_bb);
+ case ImGuiDataType_Float:
+ IM_ASSERT(*(const float*)p_min >= -FLT_MAX / 2.0f && *(const float*)p_max <= FLT_MAX / 2.0f);
+ return SliderBehaviorT<float, float, float >(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, flags, out_grab_bb);
+ case ImGuiDataType_Double:
+ IM_ASSERT(*(const double*)p_min >= -DBL_MAX / 2.0f && *(const double*)p_max <= DBL_MAX / 2.0f);
+ return SliderBehaviorT<double, double, double>(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, flags, out_grab_bb);
+ case ImGuiDataType_COUNT: break;
+ }
+ IM_ASSERT(0);
+ return false;
+}
+
+// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required.
+// Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
+bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ const float w = CalcItemWidth();
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0))
+ return false;
+
+ // Default format string when passing NULL
+ if (format == NULL)
+ format = DataTypeGetInfo(data_type)->PrintFmt;
+ else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.)
+ format = PatchFormatStringFloatToInt(format);
+
+ // Tabbing or CTRL-clicking on Slider turns it into an input box
+ const bool hovered = ItemHoverable(frame_bb, id);
+ bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
+ if (!temp_input_is_active)
+ {
+ const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
+ const bool clicked = (hovered && g.IO.MouseClicked[0]);
+ if (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id)
+ {
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ if (temp_input_allowed && (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id))
+ temp_input_is_active = true;
+ }
+ }
+
+ if (temp_input_is_active)
+ {
+ // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set
+ const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0;
+ return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL);
+ }
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
+
+ // Slider behavior
+ ImRect grab_bb;
+ const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags, &grab_bb);
+ if (value_changed)
+ MarkItemEdited(id);
+
+ // Render grab
+ if (grab_bb.Max.x > grab_bb.Min.x)
+ window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("{", "}");
+ RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return value_changed;
+}
+
+// Add multiple sliders on 1 line for compact edition of multiple components
+bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ PushMultiItemsWidths(components, CalcItemWidth());
+ size_t type_size = GDataTypeInfo[data_type].Size;
+ for (int i = 0; i < components; i++)
+ {
+ PushID(i);
+ if (i > 0)
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, flags);
+ PopID();
+ PopItemWidth();
+ v = (void*)((char*)v + type_size);
+ }
+ PopID();
+
+ const char* label_end = FindRenderedTextEnd(label);
+ if (label != label_end)
+ {
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ TextEx(label, label_end);
+ }
+
+ EndGroup();
+ return value_changed;
+}
+
+bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags)
+{
+ if (format == NULL)
+ format = "%.0f deg";
+ float v_deg = (*v_rad) * 360.0f / (2 * IM_PI);
+ bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, flags);
+ *v_rad = v_deg * (2 * IM_PI) / 360.0f;
+ return value_changed;
+}
+
+bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+
+ ItemSize(bb, style.FramePadding.y);
+ if (!ItemAdd(frame_bb, id))
+ return false;
+
+ // Default format string when passing NULL
+ if (format == NULL)
+ format = DataTypeGetInfo(data_type)->PrintFmt;
+ else if (data_type == ImGuiDataType_S32 && strcmp(format, "%d") != 0) // (FIXME-LEGACY: Patch old "%.0f" format string to use "%d", read function more details.)
+ format = PatchFormatStringFloatToInt(format);
+
+ const bool hovered = ItemHoverable(frame_bb, id);
+ if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavActivateInputId == id)
+ {
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+ }
+
+ // Draw frame
+ const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding);
+
+ // Slider behavior
+ ImRect grab_bb;
+ const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags | ImGuiSliderFlags_Vertical, &grab_bb);
+ if (value_changed)
+ MarkItemEdited(id);
+
+ // Render grab
+ if (grab_bb.Max.y > grab_bb.Min.y)
+ window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
+
+ // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
+ // For the vertical slider we allow centered text to overlap the frame padding
+ char value_buf[64];
+ const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format);
+ RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ return value_changed;
+}
+
+bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, flags);
+}
+
+bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags)
+{
+ return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format, flags);
+}
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+// Obsolete versions with power parameter. See https://github.com/ocornut/imgui/issues/3361 for details.
+bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power)
+{
+ ImGuiSliderFlags slider_flags = ImGuiSliderFlags_None;
+ if (power != 1.0f)
+ {
+ IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
+ slider_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths
+ }
+ return SliderScalar(label, data_type, p_data, p_min, p_max, format, slider_flags);
+}
+
+bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power)
+{
+ ImGuiSliderFlags slider_flags = ImGuiSliderFlags_None;
+ if (power != 1.0f)
+ {
+ IM_ASSERT(power == 1.0f && "Call function with ImGuiSliderFlags_Logarithmic flags instead of using the old 'float power' function!");
+ slider_flags |= ImGuiSliderFlags_Logarithmic; // Fallback for non-asserting paths
+ }
+ return SliderScalarN(label, data_type, v, components, v_min, v_max, format, slider_flags);
+}
+
+#endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc.
+//-------------------------------------------------------------------------
+// - ImParseFormatFindStart() [Internal]
+// - ImParseFormatFindEnd() [Internal]
+// - ImParseFormatTrimDecorations() [Internal]
+// - ImParseFormatPrecision() [Internal]
+// - TempInputTextScalar() [Internal]
+// - InputScalar()
+// - InputScalarN()
+// - InputFloat()
+// - InputFloat2()
+// - InputFloat3()
+// - InputFloat4()
+// - InputInt()
+// - InputInt2()
+// - InputInt3()
+// - InputInt4()
+// - InputDouble()
+//-------------------------------------------------------------------------
+
+// We don't use strchr() because our strings are usually very short and often start with '%'
+const char* ImParseFormatFindStart(const char* fmt)
+{
+ while (char c = fmt[0])
+ {
+ if (c == '%' && fmt[1] != '%')
+ return fmt;
+ else if (c == '%')
+ fmt++;
+ fmt++;
+ }
+ return fmt;
+}
+
+const char* ImParseFormatFindEnd(const char* fmt)
+{
+ // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format.
+ if (fmt[0] != '%')
+ return fmt;
+ const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A'));
+ const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a'));
+ for (char c; (c = *fmt) != 0; fmt++)
+ {
+ if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0)
+ return fmt + 1;
+ if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0)
+ return fmt + 1;
+ }
+ return fmt;
+}
+
+// Extract the format out of a format string with leading or trailing decorations
+// fmt = "blah blah" -> return fmt
+// fmt = "%.3f" -> return fmt
+// fmt = "hello %.3f" -> return fmt + 6
+// fmt = "%.3f hello" -> return buf written with "%.3f"
+const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_size)
+{
+ const char* fmt_start = ImParseFormatFindStart(fmt);
+ if (fmt_start[0] != '%')
+ return fmt;
+ const char* fmt_end = ImParseFormatFindEnd(fmt_start);
+ if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data.
+ return fmt_start;
+ ImStrncpy(buf, fmt_start, ImMin((size_t)(fmt_end - fmt_start) + 1, buf_size));
+ return buf;
+}
+
+// Parse display precision back from the display format string
+// FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed.
+int ImParseFormatPrecision(const char* fmt, int default_precision)
+{
+ fmt = ImParseFormatFindStart(fmt);
+ if (fmt[0] != '%')
+ return default_precision;
+ fmt++;
+ while (*fmt >= '0' && *fmt <= '9')
+ fmt++;
+ int precision = INT_MAX;
+ if (*fmt == '.')
+ {
+ fmt = ImAtoi<int>(fmt + 1, &precision);
+ if (precision < 0 || precision > 99)
+ precision = default_precision;
+ }
+ if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation
+ precision = -1;
+ if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX)
+ precision = -1;
+ return (precision == INT_MAX) ? default_precision : precision;
+}
+
+// Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets)
+// FIXME: Facilitate using this in variety of other situations.
+bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags)
+{
+ // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
+ // We clear ActiveID on the first frame to allow the InputText() taking it back.
+ ImGuiContext& g = *GImGui;
+ const bool init = (g.TempInputId != id);
+ if (init)
+ ClearActiveID();
+
+ g.CurrentWindow->DC.CursorPos = bb.Min;
+ bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
+ if (init)
+ {
+ // First frame we started displaying the InputText widget, we expect it to take the active id.
+ IM_ASSERT(g.ActiveId == id);
+ g.TempInputId = g.ActiveId;
+ }
+ return value_changed;
+}
+
+// Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set!
+// This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility.
+// However this may not be ideal for all uses, as some user code may break on out of bound values.
+bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max)
+{
+ ImGuiContext& g = *GImGui;
+
+ char fmt_buf[32];
+ char data_buf[32];
+ format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf));
+ DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format);
+ ImStrTrimBlanks(data_buf);
+
+ ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited;
+ flags |= ((data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) ? ImGuiInputTextFlags_CharsScientific : ImGuiInputTextFlags_CharsDecimal);
+ bool value_changed = false;
+ if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags))
+ {
+ // Backup old value
+ size_t data_type_size = DataTypeGetInfo(data_type)->Size;
+ ImGuiDataTypeTempStorage data_backup;
+ memcpy(&data_backup, p_data, data_type_size);
+
+ // Apply new value (or operations) then clamp
+ DataTypeApplyOpFromText(data_buf, g.InputTextState.InitialTextA.Data, data_type, p_data, NULL);
+ if (p_clamp_min || p_clamp_max)
+ {
+ if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
+ ImSwap(p_clamp_min, p_clamp_max);
+ DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max);
+ }
+
+ // Only mark as edited if new value is different
+ value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
+ if (value_changed)
+ MarkItemEdited(id);
+ }
+ return value_changed;
+}
+
+// Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional.
+// Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
+bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+
+ if (format == NULL)
+ format = DataTypeGetInfo(data_type)->PrintFmt;
+
+ char buf[64];
+ DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
+
+ bool value_changed = false;
+ if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
+ flags |= ImGuiInputTextFlags_CharsDecimal;
+ flags |= ImGuiInputTextFlags_AutoSelectAll;
+ flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
+
+ if (p_step != NULL)
+ {
+ const float button_size = GetFrameHeight();
+
+ BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
+ PushID(label);
+ SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
+ if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
+ value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
+
+ // Step buttons
+ const ImVec2 backup_frame_padding = style.FramePadding;
+ style.FramePadding.x = style.FramePadding.y;
+ ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups;
+ if (flags & ImGuiInputTextFlags_ReadOnly)
+ BeginDisabled();
+ SameLine(0, style.ItemInnerSpacing.x);
+ if (ButtonEx("-", ImVec2(button_size, button_size), button_flags))
+ {
+ DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
+ value_changed = true;
+ }
+ SameLine(0, style.ItemInnerSpacing.x);
+ if (ButtonEx("+", ImVec2(button_size, button_size), button_flags))
+ {
+ DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
+ value_changed = true;
+ }
+ if (flags & ImGuiInputTextFlags_ReadOnly)
+ EndDisabled();
+
+ const char* label_end = FindRenderedTextEnd(label);
+ if (label != label_end)
+ {
+ SameLine(0, style.ItemInnerSpacing.x);
+ TextEx(label, label_end);
+ }
+ style.FramePadding = backup_frame_padding;
+
+ PopID();
+ EndGroup();
+ }
+ else
+ {
+ if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
+ value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
+ }
+ if (value_changed)
+ MarkItemEdited(g.LastItemData.ID);
+
+ return value_changed;
+}
+
+bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ bool value_changed = false;
+ BeginGroup();
+ PushID(label);
+ PushMultiItemsWidths(components, CalcItemWidth());
+ size_t type_size = GDataTypeInfo[data_type].Size;
+ for (int i = 0; i < components; i++)
+ {
+ PushID(i);
+ if (i > 0)
+ SameLine(0, g.Style.ItemInnerSpacing.x);
+ value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags);
+ PopID();
+ PopItemWidth();
+ p_data = (void*)((char*)p_data + type_size);
+ }
+ PopID();
+
+ const char* label_end = FindRenderedTextEnd(label);
+ if (label != label_end)
+ {
+ SameLine(0.0f, g.Style.ItemInnerSpacing.x);
+ TextEx(label, label_end);
+ }
+
+ EndGroup();
+ return value_changed;
+}
+
+bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ flags |= ImGuiInputTextFlags_CharsScientific;
+ return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags);
+}
+
+bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags);
+}
+
+bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags)
+{
+ // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes.
+ const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d";
+ return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step > 0 ? &step : NULL), (void*)(step_fast > 0 ? &step_fast : NULL), format, flags);
+}
+
+bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags);
+}
+
+bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags);
+}
+
+bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags)
+{
+ return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags);
+}
+
+bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags)
+{
+ flags |= ImGuiInputTextFlags_CharsScientific;
+ return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint
+//-------------------------------------------------------------------------
+// - InputText()
+// - InputTextWithHint()
+// - InputTextMultiline()
+// - InputTextEx() [Internal]
+//-------------------------------------------------------------------------
+
+bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
+ return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
+}
+
+bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
+}
+
+bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
+ return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
+}
+
+static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
+{
+ int line_count = 0;
+ const char* s = text_begin;
+ while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding
+ if (c == '\n')
+ line_count++;
+ s--;
+ if (s[0] != '\n' && s[0] != '\r')
+ line_count++;
+ *out_text_end = s;
+ return line_count;
+}
+
+static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line)
+{
+ ImGuiContext& g = *GImGui;
+ ImFont* font = g.Font;
+ const float line_height = g.FontSize;
+ const float scale = line_height / font->FontSize;
+
+ ImVec2 text_size = ImVec2(0, 0);
+ float line_width = 0.0f;
+
+ const ImWchar* s = text_begin;
+ while (s < text_end)
+ {
+ unsigned int c = (unsigned int)(*s++);
+ if (c == '\n')
+ {
+ text_size.x = ImMax(text_size.x, line_width);
+ text_size.y += line_height;
+ line_width = 0.0f;
+ if (stop_on_new_line)
+ break;
+ continue;
+ }
+ if (c == '\r')
+ continue;
+
+ const float char_width = font->GetCharAdvance((ImWchar)c) * scale;
+ line_width += char_width;
+ }
+
+ if (text_size.x < line_width)
+ text_size.x = line_width;
+
+ if (out_offset)
+ *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n
+
+ if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n
+ text_size.y += line_height;
+
+ if (remaining)
+ *remaining = s;
+
+ return text_size;
+}
+
+// Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar)
+namespace ImStb
+{
+
+static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; }
+static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { return obj->TextW[idx]; }
+static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
+static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
+static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
+static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
+{
+ const ImWchar* text = obj->TextW.Data;
+ const ImWchar* text_remaining = NULL;
+ const ImVec2 size = InputTextCalcTextSizeW(text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true);
+ r->x0 = 0.0f;
+ r->x1 = size.x;
+ r->baseline_y_delta = size.y;
+ r->ymin = 0.0f;
+ r->ymax = size.y;
+ r->num_chars = (int)(text_remaining - (text + line_start_idx));
+}
+
+// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
+static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; }
+static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
+static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; }
+static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
+static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
+static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
+#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
+#ifdef __APPLE__ // FIXME: Move setting to IO structure
+#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_MAC
+#else
+#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_WIN
+#endif
+
+static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
+{
+ ImWchar* dst = obj->TextW.Data + pos;
+
+ // We maintain our buffer length in both UTF-8 and wchar formats
+ obj->Edited = true;
+ obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
+ obj->CurLenW -= n;
+
+ // Offset remaining text (FIXME-OPT: Use memmove)
+ const ImWchar* src = obj->TextW.Data + pos + n;
+ while (ImWchar c = *src++)
+ *dst++ = c;
+ *dst = '\0';
+}
+
+static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ImWchar* new_text, int new_text_len)
+{
+ const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
+ const int text_len = obj->CurLenW;
+ IM_ASSERT(pos <= text_len);
+
+ const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len);
+ if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA))
+ return false;
+
+ // Grow internal buffer if needed
+ if (new_text_len + text_len + 1 > obj->TextW.Size)
+ {
+ if (!is_resizable)
+ return false;
+ IM_ASSERT(text_len < obj->TextW.Size);
+ obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1);
+ }
+
+ ImWchar* text = obj->TextW.Data;
+ if (pos != text_len)
+ memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar));
+ memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar));
+
+ obj->Edited = true;
+ obj->CurLenW += new_text_len;
+ obj->CurLenA += new_text_len_utf8;
+ obj->TextW[obj->CurLenW] = '\0';
+
+ return true;
+}
+
+// We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols)
+#define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left
+#define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right
+#define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up
+#define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down
+#define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line
+#define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line
+#define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text
+#define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text
+#define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor
+#define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor
+#define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo
+#define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo
+#define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word
+#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
+#define STB_TEXTEDIT_K_PGUP 0x20000E // keyboard input to move cursor up a page
+#define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page
+#define STB_TEXTEDIT_K_SHIFT 0x400000
+
+#define STB_TEXTEDIT_IMPLEMENTATION
+#include "imstb_textedit.h"
+
+// stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling
+// the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
+static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len)
+{
+ stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
+ ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
+ if (text_len <= 0)
+ return;
+ if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len))
+ {
+ state->cursor = text_len;
+ state->has_preferred_x = 0;
+ return;
+ }
+ IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace()
+}
+
+} // namespace ImStb
+
+void ImGuiInputTextState::OnKeyPressed(int key)
+{
+ stb_textedit_key(this, &Stb, key);
+ CursorFollow = true;
+ CursorAnimReset();
+}
+
+ImGuiInputTextCallbackData::ImGuiInputTextCallbackData()
+{
+ memset(this, 0, sizeof(*this));
+}
+
+// Public API to manipulate UTF-8 text
+// We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar)
+// FIXME: The existence of this rarely exercised code path is a bit of a nuisance.
+void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count)
+{
+ IM_ASSERT(pos + bytes_count <= BufTextLen);
+ char* dst = Buf + pos;
+ const char* src = Buf + pos + bytes_count;
+ while (char c = *src++)
+ *dst++ = c;
+ *dst = '\0';
+
+ if (CursorPos >= pos + bytes_count)
+ CursorPos -= bytes_count;
+ else if (CursorPos >= pos)
+ CursorPos = pos;
+ SelectionStart = SelectionEnd = CursorPos;
+ BufDirty = true;
+ BufTextLen -= bytes_count;
+}
+
+void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end)
+{
+ const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0;
+ const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text);
+ if (new_text_len + BufTextLen >= BufSize)
+ {
+ if (!is_resizable)
+ return;
+
+ // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!)
+ ImGuiContext& g = *GImGui;
+ ImGuiInputTextState* edit_state = &g.InputTextState;
+ IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
+ IM_ASSERT(Buf == edit_state->TextA.Data);
+ int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
+ edit_state->TextA.reserve(new_buf_size + 1);
+ Buf = edit_state->TextA.Data;
+ BufSize = edit_state->BufCapacityA = new_buf_size;
+ }
+
+ if (BufTextLen != pos)
+ memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos));
+ memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
+ Buf[BufTextLen + new_text_len] = '\0';
+
+ if (CursorPos >= pos)
+ CursorPos += new_text_len;
+ SelectionStart = SelectionEnd = CursorPos;
+ BufDirty = true;
+ BufTextLen += new_text_len;
+}
+
+// Return false to discard a character.
+static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source)
+{
+ IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard);
+ unsigned int c = *p_char;
+
+ // Filter non-printable (NB: isprint is unreliable! see #2467)
+ bool apply_named_filters = true;
+ if (c < 0x20)
+ {
+ bool pass = false;
+ pass |= (c == '\n' && (flags & ImGuiInputTextFlags_Multiline));
+ pass |= (c == '\t' && (flags & ImGuiInputTextFlags_AllowTabInput));
+ if (!pass)
+ return false;
+ apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted.
+ }
+
+ if (input_source != ImGuiInputSource_Clipboard)
+ {
+ // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817)
+ if (c == 127)
+ return false;
+
+ // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME)
+ if (c >= 0xE000 && c <= 0xF8FF)
+ return false;
+ }
+
+ // Filter Unicode ranges we are not handling in this build
+ if (c > IM_UNICODE_CODEPOINT_MAX)
+ return false;
+
+ // Generic named filters
+ if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)))
+ {
+ // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'.
+ // The standard mandate that programs starts in the "C" locale where the decimal point is '.'.
+ // We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point.
+ // Change the default decimal_point with:
+ // ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point;
+ // Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions.
+ ImGuiContext& g = *GImGui;
+ const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint;
+
+ // Allow 0-9 . - + * /
+ if (flags & ImGuiInputTextFlags_CharsDecimal)
+ if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/'))
+ return false;
+
+ // Allow 0-9 . - + * / e E
+ if (flags & ImGuiInputTextFlags_CharsScientific)
+ if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E'))
+ return false;
+
+ // Allow 0-9 a-F A-F
+ if (flags & ImGuiInputTextFlags_CharsHexadecimal)
+ if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F'))
+ return false;
+
+ // Turn a-z into A-Z
+ if (flags & ImGuiInputTextFlags_CharsUppercase)
+ if (c >= 'a' && c <= 'z')
+ *p_char = (c += (unsigned int)('A' - 'a'));
+
+ if (flags & ImGuiInputTextFlags_CharsNoBlank)
+ if (ImCharIsBlankW(c))
+ return false;
+ }
+
+ // Custom callback filter
+ if (flags & ImGuiInputTextFlags_CallbackCharFilter)
+ {
+ ImGuiInputTextCallbackData callback_data;
+ memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
+ callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
+ callback_data.EventChar = (ImWchar)c;
+ callback_data.Flags = flags;
+ callback_data.UserData = user_data;
+ if (callback(&callback_data) != 0)
+ return false;
+ *p_char = callback_data.EventChar;
+ if (!callback_data.EventChar)
+ return false;
+ }
+
+ return true;
+}
+
+// Edit a string of text
+// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
+// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
+// Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator.
+// - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect.
+// - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h
+// (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are
+// doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188)
+bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ IM_ASSERT(buf != NULL && buf_size >= 0);
+ IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys)
+ IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key)
+
+ ImGuiContext& g = *GImGui;
+ ImGuiIO& io = g.IO;
+ const ImGuiStyle& style = g.Style;
+
+ const bool RENDER_SELECTION_WHEN_INACTIVE = false;
+ const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0;
+ const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0;
+ const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
+ const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
+ const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0;
+ if (is_resizable)
+ IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
+
+ if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
+ BeginGroup();
+ const ImGuiID id = window->GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line
+ const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
+
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
+ const ImRect total_bb(frame_bb.Min, frame_bb.Min + total_size);
+
+ ImGuiWindow* draw_window = window;
+ ImVec2 inner_size = frame_size;
+ ImGuiItemStatusFlags item_status_flags = 0;
+ if (is_multiline)
+ {
+ ImVec2 backup_pos = window->DC.CursorPos;
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
+ {
+ EndGroup();
+ return false;
+ }
+ item_status_flags = g.LastItemData.StatusFlags;
+ window->DC.CursorPos = backup_pos;
+
+ // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug.
+ // FIXME-NAV: Pressing NavActivate will trigger general child activation right before triggering our own below. Harmless but bizarre.
+ PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
+ PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
+ PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
+ bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove);
+ PopStyleVar(2);
+ PopStyleColor();
+ if (!child_visible)
+ {
+ EndChild();
+ EndGroup();
+ return false;
+ }
+ draw_window = g.CurrentWindow; // Child window
+ draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
+ draw_window->DC.CursorPos += style.FramePadding;
+ inner_size.x -= draw_window->ScrollbarSizes.x;
+ }
+ else
+ {
+ // Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!(flags & ImGuiInputTextFlags_MergedItem))
+ if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
+ return false;
+ item_status_flags = g.LastItemData.StatusFlags;
+ }
+ const bool hovered = ItemHoverable(frame_bb, id);
+ if (hovered)
+ g.MouseCursor = ImGuiMouseCursor_TextInput;
+
+ // We are only allowed to access the state if we are already the active widget.
+ ImGuiInputTextState* state = GetInputTextState(id);
+
+ const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
+ const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
+
+ const bool user_clicked = hovered && io.MouseClicked[0];
+ const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
+ const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
+ bool clear_active_id = false;
+ bool select_all = false;
+
+ float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
+
+ const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
+ const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing);
+ const bool init_state = (init_make_active || user_scroll_active);
+ if ((init_state && g.ActiveId != id) || init_changed_specs)
+ {
+ // Access state even if we don't own it yet.
+ state = &g.InputTextState;
+ state->CursorAnimReset();
+
+ // Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
+ // From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
+ const int buf_len = (int)strlen(buf);
+ state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
+ memcpy(state->InitialTextA.Data, buf, buf_len + 1);
+
+ // Start edition
+ const char* buf_end = NULL;
+ state->TextW.resize(buf_size + 1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data is always pointing to at least an empty string.
+ state->TextA.resize(0);
+ state->TextAIsValid = false; // TextA is not valid yet (we will display buf until then)
+ state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, buf_size, buf, NULL, &buf_end);
+ state->CurLenA = (int)(buf_end - buf); // We can't get the result from ImStrncpy() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8.
+
+ // Preserve cursor position and undo/redo stack if we come back to same widget
+ // FIXME: For non-readonly widgets we might be able to require that TextAIsValid && TextA == buf ? (untested) and discard undo stack if user buffer has changed.
+ const bool recycle_state = (state->ID == id && !init_changed_specs);
+ if (recycle_state)
+ {
+ // Recycle existing cursor/selection/undo stack but clamp position
+ // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler.
+ state->CursorClamp();
+ }
+ else
+ {
+ state->ID = id;
+ state->ScrollX = 0.0f;
+ stb_textedit_initialize_state(&state->Stb, !is_multiline);
+ }
+
+ if (!is_multiline)
+ {
+ if (flags & ImGuiInputTextFlags_AutoSelectAll)
+ select_all = true;
+ if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState)))
+ select_all = true;
+ if (input_requested_by_tabbing || (user_clicked && io.KeyCtrl))
+ select_all = true;
+ }
+
+ if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
+ state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
+ }
+
+ if (g.ActiveId != id && init_make_active)
+ {
+ IM_ASSERT(state && state->ID == id);
+ SetActiveID(id, window);
+ SetFocusID(id, window);
+ FocusWindow(window);
+
+ // Declare our inputs
+ IM_ASSERT(ImGuiNavInput_COUNT < 32);
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
+ if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory))
+ g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down);
+ g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);
+ g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Home) | ((ImU64)1 << ImGuiKey_End);
+ if (is_multiline)
+ g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_PageUp) | ((ImU64)1 << ImGuiKey_PageDown);
+ if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
+ g.ActiveIdUsingKeyInputMask |= ((ImU64)1 << ImGuiKey_Tab);
+ }
+
+ // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function)
+ if (g.ActiveId == id && state == NULL)
+ ClearActiveID();
+
+ // Release focus when we click outside
+ if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560
+ clear_active_id = true;
+
+ // Lock the decision of whether we are going to take the path displaying the cursor or selection
+ const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
+ bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
+ bool value_changed = false;
+ bool enter_pressed = false;
+
+ // When read-only we always use the live data passed to the function
+ // FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :(
+ if (is_readonly && state != NULL && (render_cursor || render_selection))
+ {
+ const char* buf_end = NULL;
+ state->TextW.resize(buf_size + 1);
+ state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, buf, NULL, &buf_end);
+ state->CurLenA = (int)(buf_end - buf);
+ state->CursorClamp();
+ render_selection &= state->HasSelection();
+ }
+
+ // Select the buffer to render.
+ const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid;
+ const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0);
+
+ // Password pushes a temporary font with only a fallback glyph
+ if (is_password && !is_displaying_hint)
+ {
+ const ImFontGlyph* glyph = g.Font->FindGlyph('*');
+ ImFont* password_font = &g.InputTextPasswordFont;
+ password_font->FontSize = g.Font->FontSize;
+ password_font->Scale = g.Font->Scale;
+ password_font->Ascent = g.Font->Ascent;
+ password_font->Descent = g.Font->Descent;
+ password_font->ContainerAtlas = g.Font->ContainerAtlas;
+ password_font->FallbackGlyph = glyph;
+ password_font->FallbackAdvanceX = glyph->AdvanceX;
+ IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty());
+ PushFont(password_font);
+ }
+
+ // Process mouse inputs and character inputs
+ int backup_current_text_length = 0;
+ if (g.ActiveId == id)
+ {
+ IM_ASSERT(state != NULL);
+ backup_current_text_length = state->CurLenA;
+ state->Edited = false;
+ state->BufCapacityA = buf_size;
+ state->Flags = flags;
+
+ // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
+ // Down the line we should have a cleaner library-wide concept of Selected vs Active.
+ g.ActiveIdAllowOverlap = !io.MouseDown[0];
+ g.WantTextInputNextFrame = 1;
+
+ // Edit in progress
+ const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
+ const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
+
+ const bool is_osx = io.ConfigMacOSXBehaviors;
+ if (select_all)
+ {
+ state->SelectAll();
+ state->SelectedAllMouseLock = true;
+ }
+ else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift)
+ {
+ stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
+ const int multiclick_count = (io.MouseClickedCount[0] - 2);
+ if ((multiclick_count % 2) == 0)
+ {
+ // Double-click: Select word
+ // We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
+ // FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
+ const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n';
+ if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol)
+ state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
+ //state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
+ if (!STB_TEXT_HAS_SELECTION(&state->Stb))
+ ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb);
+ state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor);
+ state->Stb.select_end = state->Stb.cursor;
+ ImStb::stb_textedit_clamp(state, &state->Stb);
+ }
+ else
+ {
+ // Triple-click: Select line
+ const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n';
+ state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART);
+ state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT);
+ state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT);
+ if (!is_eol && is_multiline)
+ {
+ ImSwap(state->Stb.select_start, state->Stb.select_end);
+ state->Stb.cursor = state->Stb.select_end;
+ }
+ state->CursorFollow = false;
+ }
+ state->CursorAnimReset();
+ }
+ else if (io.MouseClicked[0] && !state->SelectedAllMouseLock)
+ {
+ // FIXME: unselect on late click could be done release?
+ if (hovered)
+ {
+ stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
+ state->CursorAnimReset();
+ }
+ }
+ else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
+ {
+ stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y);
+ state->CursorAnimReset();
+ state->CursorFollow = true;
+ }
+ if (state->SelectedAllMouseLock && !io.MouseDown[0])
+ state->SelectedAllMouseLock = false;
+
+ // It is ill-defined whether the backend needs to send a \t character when pressing the TAB keys.
+ // Win32 and GLFW naturally do it but not SDL.
+ const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper);
+ if ((flags & ImGuiInputTextFlags_AllowTabInput) && IsKeyPressedMap(ImGuiKey_Tab) && !ignore_char_inputs && !io.KeyShift && !is_readonly)
+ if (!io.InputQueueCharacters.contains('\t'))
+ {
+ unsigned int c = '\t'; // Insert TAB
+ if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
+ state->OnKeyPressed((int)c);
+ }
+
+ // Process regular text input (before we check for Return because using some IME will effectively send a Return?)
+ // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters.
+ if (io.InputQueueCharacters.Size > 0)
+ {
+ if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav)
+ for (int n = 0; n < io.InputQueueCharacters.Size; n++)
+ {
+ // Insert character if they pass filtering
+ unsigned int c = (unsigned int)io.InputQueueCharacters[n];
+ if (c == '\t' && io.KeyShift)
+ continue;
+ if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
+ state->OnKeyPressed((int)c);
+ }
+
+ // Consume characters
+ io.InputQueueCharacters.resize(0);
+ }
+ }
+
+ // Process other shortcuts/key-presses
+ bool cancel_edit = false;
+ if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id)
+ {
+ IM_ASSERT(state != NULL);
+ IM_ASSERT(io.KeyMods == GetMergedKeyModFlags() && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); // We rarely do this check, but if anything let's do it here.
+
+ const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1);
+ state->Stb.row_count_per_page = row_count_per_page;
+
+ const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
+ const bool is_osx = io.ConfigMacOSXBehaviors;
+ const bool is_osx_shift_shortcut = is_osx && (io.KeyMods == (ImGuiKeyModFlags_Super | ImGuiKeyModFlags_Shift));
+ const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
+ const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
+ const bool is_ctrl_key_only = (io.KeyMods == ImGuiKeyModFlags_Ctrl);
+ const bool is_shift_key_only = (io.KeyMods == ImGuiKeyModFlags_Shift);
+ const bool is_shortcut_key = g.IO.ConfigMacOSXBehaviors ? (io.KeyMods == ImGuiKeyModFlags_Super) : (io.KeyMods == ImGuiKeyModFlags_Ctrl);
+
+ const bool is_cut = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection());
+ const bool is_copy = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection());
+ const bool is_paste = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_readonly;
+ const bool is_undo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Z)) && !is_readonly && is_undoable);
+ const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable;
+
+ // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
+ const bool is_validate_enter = IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter);
+ const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) && !IsKeyPressedMap(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed);
+ const bool is_cancel = IsKeyPressedMap(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed);
+
+ if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; }
+ else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
+ else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
+ else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
+ {
+ if (!state->HasSelection())
+ {
+ if (is_wordmove_key_down)
+ state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT);
+ else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl)
+ state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT);
+ }
+ state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
+ }
+ else if (is_validate_enter)
+ {
+ bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
+ if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
+ {
+ enter_pressed = clear_active_id = true;
+ }
+ else if (!is_readonly)
+ {
+ unsigned int c = '\n'; // Insert new line
+ if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
+ state->OnKeyPressed((int)c);
+ }
+ }
+ else if (is_validate_nav)
+ {
+ IM_ASSERT(!is_validate_enter);
+ enter_pressed = clear_active_id = true;
+ }
+ else if (is_cancel)
+ {
+ clear_active_id = cancel_edit = true;
+ }
+ else if (is_undo || is_redo)
+ {
+ state->OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO);
+ state->ClearSelection();
+ }
+ else if (is_shortcut_key && IsKeyPressedMap(ImGuiKey_A))
+ {
+ state->SelectAll();
+ state->CursorFollow = true;
+ }
+ else if (is_cut || is_copy)
+ {
+ // Cut, Copy
+ if (io.SetClipboardTextFn)
+ {
+ const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0;
+ const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW;
+ const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
+ char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char));
+ ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
+ SetClipboardText(clipboard_data);
+ MemFree(clipboard_data);
+ }
+ if (is_cut)
+ {
+ if (!state->HasSelection())
+ state->SelectAll();
+ state->CursorFollow = true;
+ stb_textedit_cut(state, &state->Stb);
+ }
+ }
+ else if (is_paste)
+ {
+ if (const char* clipboard = GetClipboardText())
+ {
+ // Filter pasted buffer
+ const int clipboard_len = (int)strlen(clipboard);
+ ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar));
+ int clipboard_filtered_len = 0;
+ for (const char* s = clipboard; *s; )
+ {
+ unsigned int c;
+ s += ImTextCharFromUtf8(&c, s, NULL);
+ if (c == 0)
+ break;
+ if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard))
+ continue;
+ clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
+ }
+ clipboard_filtered[clipboard_filtered_len] = 0;
+ if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation
+ {
+ stb_textedit_paste(state, &state->Stb, clipboard_filtered, clipboard_filtered_len);
+ state->CursorFollow = true;
+ }
+ MemFree(clipboard_filtered);
+ }
+ }
+
+ // Update render selection flag after events have been handled, so selection highlight can be displayed during the same frame.
+ render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
+ }
+
+ // Process callbacks and apply result back to user's buffer.
+ const char* apply_new_text = NULL;
+ int apply_new_text_length = 0;
+ if (g.ActiveId == id)
+ {
+ IM_ASSERT(state != NULL);
+ if (cancel_edit)
+ {
+ // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
+ if (!is_readonly && strcmp(buf, state->InitialTextA.Data) != 0)
+ {
+ // Push records into the undo stack so we can CTRL+Z the revert operation itself
+ apply_new_text = state->InitialTextA.Data;
+ apply_new_text_length = state->InitialTextA.Size - 1;
+ ImVector<ImWchar> w_text;
+ if (apply_new_text_length > 0)
+ {
+ w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1);
+ ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length);
+ }
+ stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0);
+ }
+ }
+
+ // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.
+ // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail.
+ // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
+ bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
+ if (apply_edit_back_to_user_buffer)
+ {
+ // Apply new value immediately - copy modified buffer back
+ // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
+ // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect.
+ // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks.
+ if (!is_readonly)
+ {
+ state->TextAIsValid = true;
+ state->TextA.resize(state->TextW.Size * 4 + 1);
+ ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL);
+ }
+
+ // User callback
+ if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
+ {
+ IM_ASSERT(callback != NULL);
+
+ // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
+ ImGuiInputTextFlags event_flag = 0;
+ ImGuiKey event_key = ImGuiKey_COUNT;
+ if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && IsKeyPressedMap(ImGuiKey_Tab))
+ {
+ event_flag = ImGuiInputTextFlags_CallbackCompletion;
+ event_key = ImGuiKey_Tab;
+ }
+ else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_UpArrow))
+ {
+ event_flag = ImGuiInputTextFlags_CallbackHistory;
+ event_key = ImGuiKey_UpArrow;
+ }
+ else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressedMap(ImGuiKey_DownArrow))
+ {
+ event_flag = ImGuiInputTextFlags_CallbackHistory;
+ event_key = ImGuiKey_DownArrow;
+ }
+ else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->Edited)
+ {
+ event_flag = ImGuiInputTextFlags_CallbackEdit;
+ }
+ else if (flags & ImGuiInputTextFlags_CallbackAlways)
+ {
+ event_flag = ImGuiInputTextFlags_CallbackAlways;
+ }
+
+ if (event_flag)
+ {
+ ImGuiInputTextCallbackData callback_data;
+ memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
+ callback_data.EventFlag = event_flag;
+ callback_data.Flags = flags;
+ callback_data.UserData = callback_user_data;
+
+ char* callback_buf = is_readonly ? buf : state->TextA.Data;
+ callback_data.EventKey = event_key;
+ callback_data.Buf = callback_buf;
+ callback_data.BufTextLen = state->CurLenA;
+ callback_data.BufSize = state->BufCapacityA;
+ callback_data.BufDirty = false;
+
+ // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
+ ImWchar* text = state->TextW.Data;
+ const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor);
+ const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start);
+ const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end);
+
+ // Call user code
+ callback(&callback_data);
+
+ // Read back what user may have modified
+ IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
+ IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
+ IM_ASSERT(callback_data.Flags == flags);
+ const bool buf_dirty = callback_data.BufDirty;
+ if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; }
+ if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); }
+ if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); }
+ if (buf_dirty)
+ {
+ IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
+ if (callback_data.BufTextLen > backup_current_text_length && is_resizable)
+ state->TextW.resize(state->TextW.Size + (callback_data.BufTextLen - backup_current_text_length));
+ state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, callback_data.Buf, NULL);
+ state->CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
+ state->CursorAnimReset();
+ }
+ }
+ }
+
+ // Will copy result string if modified
+ if (!is_readonly && strcmp(state->TextA.Data, buf) != 0)
+ {
+ apply_new_text = state->TextA.Data;
+ apply_new_text_length = state->CurLenA;
+ }
+ }
+
+ // Clear temporary user storage
+ state->Flags = ImGuiInputTextFlags_None;
+ }
+
+ // Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
+ if (apply_new_text != NULL)
+ {
+ // We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
+ // of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
+ // without any storage on user's side.
+ IM_ASSERT(apply_new_text_length >= 0);
+ if (is_resizable)
+ {
+ ImGuiInputTextCallbackData callback_data;
+ callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
+ callback_data.Flags = flags;
+ callback_data.Buf = buf;
+ callback_data.BufTextLen = apply_new_text_length;
+ callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
+ callback_data.UserData = callback_user_data;
+ callback(&callback_data);
+ buf = callback_data.Buf;
+ buf_size = callback_data.BufSize;
+ apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
+ IM_ASSERT(apply_new_text_length <= buf_size);
+ }
+ //IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length);
+
+ // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
+ ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
+ value_changed = true;
+ }
+
+ // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
+ if (clear_active_id && g.ActiveId == id)
+ ClearActiveID();
+
+ // Render frame
+ if (!is_multiline)
+ {
+ RenderNavHighlight(frame_bb, id);
+ RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
+ }
+
+ const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + inner_size.x, frame_bb.Min.y + inner_size.y); // Not using frame_bb.Max because we have adjusted size
+ ImVec2 draw_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding;
+ ImVec2 text_size(0.0f, 0.0f);
+
+ // Set upper limit of single-line InputTextEx() at 2 million characters strings. The current pathological worst case is a long line
+ // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
+ // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
+ const int buf_display_max_length = 2 * 1024 * 1024;
+ const char* buf_display = buf_display_from_state ? state->TextA.Data : buf; //-V595
+ const char* buf_display_end = NULL; // We have specialized paths below for setting the length
+ if (is_displaying_hint)
+ {
+ buf_display = hint;
+ buf_display_end = hint + strlen(hint);
+ }
+
+ // Render text. We currently only render selection when the widget is active or while scrolling.
+ // FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive.
+ if (render_cursor || render_selection)
+ {
+ IM_ASSERT(state != NULL);
+ if (!is_displaying_hint)
+ buf_display_end = buf_display + state->CurLenA;
+
+ // Render text (with cursor and selection)
+ // This is going to be messy. We need to:
+ // - Display the text (this alone can be more easily clipped)
+ // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation)
+ // - Measure text height (for scrollbar)
+ // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort)
+ // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8.
+ const ImWchar* text_begin = state->TextW.Data;
+ ImVec2 cursor_offset, select_start_offset;
+
+ {
+ // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions.
+ const ImWchar* searches_input_ptr[2] = { NULL, NULL };
+ int searches_result_line_no[2] = { -1000, -1000 };
+ int searches_remaining = 0;
+ if (render_cursor)
+ {
+ searches_input_ptr[0] = text_begin + state->Stb.cursor;
+ searches_result_line_no[0] = -1;
+ searches_remaining++;
+ }
+ if (render_selection)
+ {
+ searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end);
+ searches_result_line_no[1] = -1;
+ searches_remaining++;
+ }
+
+ // Iterate all lines to find our line numbers
+ // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
+ searches_remaining += is_multiline ? 1 : 0;
+ int line_count = 0;
+ //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) // FIXME-OPT: Could use this when wchar_t are 16-bit
+ for (const ImWchar* s = text_begin; *s != 0; s++)
+ if (*s == '\n')
+ {
+ line_count++;
+ if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; }
+ if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; }
+ }
+ line_count++;
+ if (searches_result_line_no[0] == -1)
+ searches_result_line_no[0] = line_count;
+ if (searches_result_line_no[1] == -1)
+ searches_result_line_no[1] = line_count;
+
+ // Calculate 2d position by finding the beginning of the line and measuring distance
+ cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
+ cursor_offset.y = searches_result_line_no[0] * g.FontSize;
+ if (searches_result_line_no[1] >= 0)
+ {
+ select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
+ select_start_offset.y = searches_result_line_no[1] * g.FontSize;
+ }
+
+ // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)
+ if (is_multiline)
+ text_size = ImVec2(inner_size.x, line_count * g.FontSize);
+ }
+
+ // Scroll
+ if (render_cursor && state->CursorFollow)
+ {
+ // Horizontal scroll in chunks of quarter width
+ if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll))
+ {
+ const float scroll_increment_x = inner_size.x * 0.25f;
+ const float visible_width = inner_size.x - style.FramePadding.x;
+ if (cursor_offset.x < state->ScrollX)
+ state->ScrollX = IM_FLOOR(ImMax(0.0f, cursor_offset.x - scroll_increment_x));
+ else if (cursor_offset.x - visible_width >= state->ScrollX)
+ state->ScrollX = IM_FLOOR(cursor_offset.x - visible_width + scroll_increment_x);
+ }
+ else
+ {
+ state->ScrollX = 0.0f;
+ }
+
+ // Vertical scroll
+ if (is_multiline)
+ {
+ // Test if cursor is vertically visible
+ if (cursor_offset.y - g.FontSize < scroll_y)
+ scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
+ else if (cursor_offset.y - inner_size.y >= scroll_y)
+ scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f;
+ const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f);
+ scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y);
+ draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag
+ draw_window->Scroll.y = scroll_y;
+ }
+
+ state->CursorFollow = false;
+ }
+
+ // Draw selection
+ const ImVec2 draw_scroll = ImVec2(state->ScrollX, 0.0f);
+ if (render_selection)
+ {
+ const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end);
+ const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end);
+
+ ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
+ float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
+ float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
+ ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll;
+ for (const ImWchar* p = text_selected_begin; p < text_selected_end; )
+ {
+ if (rect_pos.y > clip_rect.w + g.FontSize)
+ break;
+ if (rect_pos.y < clip_rect.y)
+ {
+ //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bit
+ //p = p ? p + 1 : text_selected_end;
+ while (p < text_selected_end)
+ if (*p++ == '\n')
+ break;
+ }
+ else
+ {
+ ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
+ if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
+ ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
+ rect.ClipWith(clip_rect);
+ if (rect.Overlaps(clip_rect))
+ draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
+ }
+ rect_pos.x = draw_pos.x - draw_scroll.x;
+ rect_pos.y += g.FontSize;
+ }
+ }
+
+ // We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash.
+ if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
+ {
+ ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
+ draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
+ }
+
+ // Draw blinking cursor
+ if (render_cursor)
+ {
+ state->CursorAnim += io.DeltaTime;
+ bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
+ ImVec2 cursor_screen_pos = ImFloor(draw_pos + cursor_offset - draw_scroll);
+ ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
+ if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
+ draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
+
+ // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
+ if (!is_readonly)
+ g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
+ }
+ }
+ else
+ {
+ // Render text only (no selection, no cursor)
+ if (is_multiline)
+ text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width
+ else if (!is_displaying_hint && g.ActiveId == id)
+ buf_display_end = buf_display + state->CurLenA;
+ else if (!is_displaying_hint)
+ buf_display_end = buf_display + strlen(buf_display);
+
+ if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
+ {
+ ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
+ draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
+ }
+ }
+
+ if (is_password && !is_displaying_hint)
+ PopFont();
+
+ if (is_multiline)
+ {
+ Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y));
+ EndChild();
+ EndGroup();
+ }
+
+ // Log as text
+ if (g.LogEnabled && (!is_password || is_displaying_hint))
+ {
+ LogSetNextTextDecoration("{", "}");
+ LogRenderedText(&draw_pos, buf_display, buf_display_end);
+ }
+
+ if (label_size.x > 0)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
+
+ if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
+ MarkItemEdited(id);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
+ return enter_pressed;
+ else
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
+//-------------------------------------------------------------------------
+// - ColorEdit3()
+// - ColorEdit4()
+// - ColorPicker3()
+// - RenderColorRectWithAlphaCheckerboard() [Internal]
+// - ColorPicker4()
+// - ColorButton()
+// - SetColorEditOptions()
+// - ColorTooltip() [Internal]
+// - ColorEditOptionsPopup() [Internal]
+// - ColorPickerOptionsPopup() [Internal]
+//-------------------------------------------------------------------------
+
+bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags)
+{
+ return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha);
+}
+
+// ColorEdit supports RGB and HSV inputs. In case of RGB input resulting color may have undefined hue and/or saturation.
+// Since widget displays both RGB and HSV values we must preserve hue and saturation to prevent these values resetting.
+static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V)
+{
+ // This check is optional. Suppose we have two color widgets side by side, both widgets display different colors, but both colors have hue and/or saturation undefined.
+ // With color check: hue/saturation is preserved in one widget. Editing color in one widget would reset hue/saturation in another one.
+ // Without color check: common hue/saturation would be displayed in all widgets that have hue/saturation undefined.
+ // g.ColorEditLastColor is stored as ImU32 RGB value: this essentially gives us color equality check with reduced precision.
+ // Tiny external color changes would not be detected and this check would still pass. This is OK, since we only restore hue/saturation _only_ if they are undefined,
+ // therefore this change flipping hue/saturation from undefined to a very tiny value would still be represented in color picker.
+ ImGuiContext& g = *GImGui;
+ if (g.ColorEditLastColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
+ return;
+
+ // When S == 0, H is undefined.
+ // When H == 1 it wraps around to 0.
+ if (*S == 0.0f || (*H == 0.0f && g.ColorEditLastHue == 1))
+ *H = g.ColorEditLastHue;
+
+ // When V == 0, S is undefined.
+ if (*V == 0.0f)
+ *S = g.ColorEditLastSat;
+}
+
+// Edit colors components (each component in 0.0f..1.0f range).
+// See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
+// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item.
+bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const float square_sz = GetFrameHeight();
+ const float w_full = CalcItemWidth();
+ const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x);
+ const float w_inputs = w_full - w_button;
+ const char* label_display_end = FindRenderedTextEnd(label);
+ g.NextItemData.ClearFlags();
+
+ BeginGroup();
+ PushID(label);
+
+ // If we're not showing any slider there's no point in doing any HSV conversions
+ const ImGuiColorEditFlags flags_untouched = flags;
+ if (flags & ImGuiColorEditFlags_NoInputs)
+ flags = (flags & (~ImGuiColorEditFlags_DisplayMask_)) | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoOptions;
+
+ // Context menu: display and modify options (before defaults are applied)
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ ColorEditOptionsPopup(col, flags);
+
+ // Read stored options
+ if (!(flags & ImGuiColorEditFlags_DisplayMask_))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_);
+ if (!(flags & ImGuiColorEditFlags_DataTypeMask_))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_);
+ if (!(flags & ImGuiColorEditFlags_PickerMask_))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_);
+ if (!(flags & ImGuiColorEditFlags_InputMask_))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_);
+ flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
+
+ const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0;
+ const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0;
+ const int components = alpha ? 4 : 3;
+
+ // Convert to the formats we need
+ float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f };
+ if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB))
+ ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
+ else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV))
+ {
+ // Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
+ ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
+ ColorEditRestoreHS(col, &f[0], &f[1], &f[2]);
+ }
+ int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) };
+
+ bool value_changed = false;
+ bool value_changed_as_float = false;
+
+ const ImVec2 pos = window->DC.CursorPos;
+ const float inputs_offset_x = (style.ColorButtonPosition == ImGuiDir_Left) ? w_button : 0.0f;
+ window->DC.CursorPos.x = pos.x + inputs_offset_x;
+
+ if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
+ {
+ // RGB/HSV 0..255 Sliders
+ const float w_item_one = ImMax(1.0f, IM_FLOOR((w_inputs - (style.ItemInnerSpacing.x) * (components - 1)) / (float)components));
+ const float w_item_last = ImMax(1.0f, IM_FLOOR(w_inputs - (w_item_one + style.ItemInnerSpacing.x) * (components - 1)));
+
+ const bool hide_prefix = (w_item_one <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x);
+ static const char* ids[4] = { "##X", "##Y", "##Z", "##W" };
+ static const char* fmt_table_int[3][4] =
+ {
+ { "%3d", "%3d", "%3d", "%3d" }, // Short display
+ { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA
+ { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA
+ };
+ static const char* fmt_table_float[3][4] =
+ {
+ { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display
+ { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA
+ { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA
+ };
+ const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1;
+
+ for (int n = 0; n < components; n++)
+ {
+ if (n > 0)
+ SameLine(0, style.ItemInnerSpacing.x);
+ SetNextItemWidth((n + 1 < components) ? w_item_one : w_item_last);
+
+ // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0.
+ if (flags & ImGuiColorEditFlags_Float)
+ {
+ value_changed |= DragFloat(ids[n], &f[n], 1.0f / 255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]);
+ value_changed_as_float |= value_changed;
+ }
+ else
+ {
+ value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]);
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+ }
+ }
+ else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0)
+ {
+ // RGB Hexadecimal Input
+ char buf[64];
+ if (alpha)
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255));
+ else
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255));
+ SetNextItemWidth(w_inputs);
+ if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase))
+ {
+ value_changed = true;
+ char* p = buf;
+ while (*p == '#' || ImCharIsBlankA(*p))
+ p++;
+ i[0] = i[1] = i[2] = 0;
+ i[3] = 0xFF; // alpha default to 255 is not parsed by scanf (e.g. inputting #FFFFFF omitting alpha)
+ int r;
+ if (alpha)
+ r = sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
+ else
+ r = sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
+ IM_UNUSED(r); // Fixes C6031: Return value ignored: 'sscanf'.
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+ }
+
+ ImGuiWindow* picker_active_window = NULL;
+ if (!(flags & ImGuiColorEditFlags_NoSmallPreview))
+ {
+ const float button_offset_x = ((flags & ImGuiColorEditFlags_NoInputs) || (style.ColorButtonPosition == ImGuiDir_Left)) ? 0.0f : w_inputs + style.ItemInnerSpacing.x;
+ window->DC.CursorPos = ImVec2(pos.x + button_offset_x, pos.y);
+
+ const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f);
+ if (ColorButton("##ColorButton", col_v4, flags))
+ {
+ if (!(flags & ImGuiColorEditFlags_NoPicker))
+ {
+ // Store current color and open a picker
+ g.ColorPickerRef = col_v4;
+ OpenPopup("picker");
+ SetNextWindowPos(g.LastItemData.Rect.GetBL() + ImVec2(-1, style.ItemSpacing.y));
+ }
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+
+ if (BeginPopup("picker"))
+ {
+ picker_active_window = g.CurrentWindow;
+ if (label != label_display_end)
+ {
+ TextEx(label, label_display_end);
+ Spacing();
+ }
+ ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
+ ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
+ SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
+ value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
+ EndPopup();
+ }
+ }
+
+ if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel))
+ {
+ const float text_offset_x = (flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x;
+ window->DC.CursorPos = ImVec2(pos.x + text_offset_x, pos.y + style.FramePadding.y);
+ TextEx(label, label_display_end);
+ }
+
+ // Convert back
+ if (value_changed && picker_active_window == NULL)
+ {
+ if (!value_changed_as_float)
+ for (int n = 0; n < 4; n++)
+ f[n] = i[n] / 255.0f;
+ if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB))
+ {
+ g.ColorEditLastHue = f[0];
+ g.ColorEditLastSat = f[1];
+ ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]);
+ g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0));
+ }
+ if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV))
+ ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]);
+
+ col[0] = f[0];
+ col[1] = f[1];
+ col[2] = f[2];
+ if (alpha)
+ col[3] = f[3];
+ }
+
+ PopID();
+ EndGroup();
+
+ // Drag and Drop Target
+ // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test.
+ if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget())
+ {
+ bool accepted_drag_drop = false;
+ if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
+ {
+ memcpy((float*)col, payload->Data, sizeof(float) * 3); // Preserve alpha if any //-V512
+ value_changed = accepted_drag_drop = true;
+ }
+ if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
+ {
+ memcpy((float*)col, payload->Data, sizeof(float) * components);
+ value_changed = accepted_drag_drop = true;
+ }
+
+ // Drag-drop payloads are always RGB
+ if (accepted_drag_drop && (flags & ImGuiColorEditFlags_InputHSV))
+ ColorConvertRGBtoHSV(col[0], col[1], col[2], col[0], col[1], col[2]);
+ EndDragDropTarget();
+ }
+
+ // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4().
+ if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)
+ g.LastItemData.ID = g.ActiveId;
+
+ if (value_changed)
+ MarkItemEdited(g.LastItemData.ID);
+
+ return value_changed;
+}
+
+bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags)
+{
+ float col4[4] = { col[0], col[1], col[2], 1.0f };
+ if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha))
+ return false;
+ col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2];
+ return true;
+}
+
+// Helper for ColorPicker4()
+static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha)
+{
+ ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha);
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8));
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8));
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8));
+ ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8));
+}
+
+// Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
+// (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.)
+// FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..)
+// FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0)
+bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImDrawList* draw_list = window->DrawList;
+ ImGuiStyle& style = g.Style;
+ ImGuiIO& io = g.IO;
+
+ const float width = CalcItemWidth();
+ g.NextItemData.ClearFlags();
+
+ PushID(label);
+ BeginGroup();
+
+ if (!(flags & ImGuiColorEditFlags_NoSidePreview))
+ flags |= ImGuiColorEditFlags_NoSmallPreview;
+
+ // Context menu: display and store options.
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ ColorPickerOptionsPopup(col, flags);
+
+ // Read stored options
+ if (!(flags & ImGuiColorEditFlags_PickerMask_))
+ flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;
+ if (!(flags & ImGuiColorEditFlags_InputMask_))
+ flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
+
+ // Setup
+ int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
+ bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha);
+ ImVec2 picker_pos = window->DC.CursorPos;
+ float square_sz = GetFrameHeight();
+ float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars
+ float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box
+ float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x;
+ float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x;
+ float bars_triangles_half_sz = IM_FLOOR(bars_width * 0.20f);
+
+ float backup_initial_col[4];
+ memcpy(backup_initial_col, col, components * sizeof(float));
+
+ float wheel_thickness = sv_picker_size * 0.08f;
+ float wheel_r_outer = sv_picker_size * 0.50f;
+ float wheel_r_inner = wheel_r_outer - wheel_thickness;
+ ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f);
+
+ // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
+ float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
+ ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
+ ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
+ ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
+
+ float H = col[0], S = col[1], V = col[2];
+ float R = col[0], G = col[1], B = col[2];
+ if (flags & ImGuiColorEditFlags_InputRGB)
+ {
+ // Hue is lost when converting from greyscale rgb (saturation=0). Restore it.
+ ColorConvertRGBtoHSV(R, G, B, H, S, V);
+ ColorEditRestoreHS(col, &H, &S, &V);
+ }
+ else if (flags & ImGuiColorEditFlags_InputHSV)
+ {
+ ColorConvertHSVtoRGB(H, S, V, R, G, B);
+ }
+
+ bool value_changed = false, value_changed_h = false, value_changed_sv = false;
+
+ PushItemFlag(ImGuiItemFlags_NoNav, true);
+ if (flags & ImGuiColorEditFlags_PickerHueWheel)
+ {
+ // Hue wheel + SV triangle logic
+ InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size));
+ if (IsItemActive())
+ {
+ ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center;
+ ImVec2 current_off = g.IO.MousePos - wheel_center;
+ float initial_dist2 = ImLengthSqr(initial_off);
+ if (initial_dist2 >= (wheel_r_inner - 1) * (wheel_r_inner - 1) && initial_dist2 <= (wheel_r_outer + 1) * (wheel_r_outer + 1))
+ {
+ // Interactive with Hue wheel
+ H = ImAtan2(current_off.y, current_off.x) / IM_PI * 0.5f;
+ if (H < 0.0f)
+ H += 1.0f;
+ value_changed = value_changed_h = true;
+ }
+ float cos_hue_angle = ImCos(-H * 2.0f * IM_PI);
+ float sin_hue_angle = ImSin(-H * 2.0f * IM_PI);
+ if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
+ {
+ // Interacting with SV triangle
+ ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle);
+ if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated))
+ current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated);
+ float uu, vv, ww;
+ ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww);
+ V = ImClamp(1.0f - vv, 0.0001f, 1.0f);
+ S = ImClamp(uu / V, 0.0001f, 1.0f);
+ value_changed = value_changed_sv = true;
+ }
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+ }
+ else if (flags & ImGuiColorEditFlags_PickerHueBar)
+ {
+ // SV rectangle logic
+ InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size));
+ if (IsItemActive())
+ {
+ S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1));
+ V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
+
+ // Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square.
+ if (g.ColorEditLastColor == ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)))
+ H = g.ColorEditLastHue;
+ value_changed = value_changed_sv = true;
+ }
+ if (!(flags & ImGuiColorEditFlags_NoOptions))
+ OpenPopupOnItemClick("context");
+
+ // Hue bar logic
+ SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y));
+ InvisibleButton("hue", ImVec2(bars_width, sv_picker_size));
+ if (IsItemActive())
+ {
+ H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
+ value_changed = value_changed_h = true;
+ }
+ }
+
+ // Alpha bar logic
+ if (alpha_bar)
+ {
+ SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y));
+ InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size));
+ if (IsItemActive())
+ {
+ col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1));
+ value_changed = true;
+ }
+ }
+ PopItemFlag(); // ImGuiItemFlags_NoNav
+
+ if (!(flags & ImGuiColorEditFlags_NoSidePreview))
+ {
+ SameLine(0, style.ItemInnerSpacing.x);
+ BeginGroup();
+ }
+
+ if (!(flags & ImGuiColorEditFlags_NoLabel))
+ {
+ const char* label_display_end = FindRenderedTextEnd(label);
+ if (label != label_display_end)
+ {
+ if ((flags & ImGuiColorEditFlags_NoSidePreview))
+ SameLine(0, style.ItemInnerSpacing.x);
+ TextEx(label, label_display_end);
+ }
+ }
+
+ if (!(flags & ImGuiColorEditFlags_NoSidePreview))
+ {
+ PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
+ ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
+ if ((flags & ImGuiColorEditFlags_NoLabel))
+ Text("Current");
+
+ ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip;
+ ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2));
+ if (ref_col != NULL)
+ {
+ Text("Original");
+ ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]);
+ if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)))
+ {
+ memcpy(col, ref_col, components * sizeof(float));
+ value_changed = true;
+ }
+ }
+ PopItemFlag();
+ EndGroup();
+ }
+
+ // Convert back color to RGB
+ if (value_changed_h || value_changed_sv)
+ {
+ if (flags & ImGuiColorEditFlags_InputRGB)
+ {
+ ColorConvertHSVtoRGB(H, S, V, col[0], col[1], col[2]);
+ g.ColorEditLastHue = H;
+ g.ColorEditLastSat = S;
+ g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0));
+ }
+ else if (flags & ImGuiColorEditFlags_InputHSV)
+ {
+ col[0] = H;
+ col[1] = S;
+ col[2] = V;
+ }
+ }
+
+ // R,G,B and H,S,V slider color editor
+ bool value_changed_fix_hue_wrap = false;
+ if ((flags & ImGuiColorEditFlags_NoInputs) == 0)
+ {
+ PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x);
+ ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf;
+ ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker;
+ if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags_DisplayMask_) == 0)
+ if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB))
+ {
+ // FIXME: Hackily differentiating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget.
+ // For the later we don't want to run the hue-wrap canceling code. If you are well versed in HSV picker please provide your input! (See #2050)
+ value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap);
+ value_changed = true;
+ }
+ if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags_DisplayMask_) == 0)
+ value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV);
+ if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags_DisplayMask_) == 0)
+ value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex);
+ PopItemWidth();
+ }
+
+ // Try to cancel hue wrap (after ColorEdit4 call), if any
+ if (value_changed_fix_hue_wrap && (flags & ImGuiColorEditFlags_InputRGB))
+ {
+ float new_H, new_S, new_V;
+ ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V);
+ if (new_H <= 0 && H > 0)
+ {
+ if (new_V <= 0 && V != new_V)
+ ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]);
+ else if (new_S <= 0)
+ ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]);
+ }
+ }
+
+ if (value_changed)
+ {
+ if (flags & ImGuiColorEditFlags_InputRGB)
+ {
+ R = col[0];
+ G = col[1];
+ B = col[2];
+ ColorConvertRGBtoHSV(R, G, B, H, S, V);
+ ColorEditRestoreHS(col, &H, &S, &V); // Fix local Hue as display below will use it immediately.
+ }
+ else if (flags & ImGuiColorEditFlags_InputHSV)
+ {
+ H = col[0];
+ S = col[1];
+ V = col[2];
+ ColorConvertHSVtoRGB(H, S, V, R, G, B);
+ }
+ }
+
+ const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha);
+ const ImU32 col_black = IM_COL32(0,0,0,style_alpha8);
+ const ImU32 col_white = IM_COL32(255,255,255,style_alpha8);
+ const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8);
+ const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) };
+
+ ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z);
+ ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f);
+ ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!!
+
+ ImVec2 sv_cursor_pos;
+
+ if (flags & ImGuiColorEditFlags_PickerHueWheel)
+ {
+ // Render Hue Wheel
+ const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out).
+ const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12);
+ for (int n = 0; n < 6; n++)
+ {
+ const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps;
+ const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
+ const int vert_start_idx = draw_list->VtxBuffer.Size;
+ draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
+ draw_list->PathStroke(col_white, 0, wheel_thickness);
+ const int vert_end_idx = draw_list->VtxBuffer.Size;
+
+ // Paint colors over existing vertices
+ ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner);
+ ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner);
+ ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n + 1]);
+ }
+
+ // Render Cursor + preview on Hue Wheel
+ float cos_hue_angle = ImCos(H * 2.0f * IM_PI);
+ float sin_hue_angle = ImSin(H * 2.0f * IM_PI);
+ ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f);
+ float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f;
+ int hue_cursor_segments = ImClamp((int)(hue_cursor_rad / 1.4f), 9, 32);
+ draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
+ draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
+ draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
+
+ // Render SV triangle (rotated according to hue)
+ ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
+ ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle);
+ ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle);
+ ImVec2 uv_white = GetFontTexUvWhitePixel();
+ draw_list->PrimReserve(6, 6);
+ draw_list->PrimVtx(tra, uv_white, hue_color32);
+ draw_list->PrimVtx(trb, uv_white, hue_color32);
+ draw_list->PrimVtx(trc, uv_white, col_white);
+ draw_list->PrimVtx(tra, uv_white, 0);
+ draw_list->PrimVtx(trb, uv_white, col_black);
+ draw_list->PrimVtx(trc, uv_white, 0);
+ draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f);
+ sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V));
+ }
+ else if (flags & ImGuiColorEditFlags_PickerHueBar)
+ {
+ // Render SV Square
+ draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white);
+ draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black);
+ RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f);
+ sv_cursor_pos.x = ImClamp(IM_ROUND(picker_pos.x + ImSaturate(S) * sv_picker_size), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much
+ sv_cursor_pos.y = ImClamp(IM_ROUND(picker_pos.y + ImSaturate(1 - V) * sv_picker_size), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2);
+
+ // Render Hue Bar
+ for (int i = 0; i < 6; ++i)
+ draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]);
+ float bar0_line_y = IM_ROUND(picker_pos.y + H * sv_picker_size);
+ RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f);
+ RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
+ }
+
+ // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range)
+ float sv_cursor_rad = value_changed_sv ? 10.0f : 6.0f;
+ draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, 12);
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, 12);
+ draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, 12);
+
+ // Render alpha bar
+ if (alpha_bar)
+ {
+ float alpha = ImSaturate(col[3]);
+ ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size);
+ RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f));
+ draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK);
+ float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size);
+ RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f);
+ RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha);
+ }
+
+ EndGroup();
+
+ if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0)
+ value_changed = false;
+ if (value_changed)
+ MarkItemEdited(g.LastItemData.ID);
+
+ PopID();
+
+ return value_changed;
+}
+
+// A little color square. Return true when clicked.
+// FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip.
+// 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip.
+// Note that 'col' may be encoded in HSV if ImGuiColorEditFlags_InputHSV is set.
+bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, ImVec2 size)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiID id = window->GetID(desc_id);
+ float default_size = GetFrameHeight();
+ if (size.x == 0.0f)
+ size.x = default_size;
+ if (size.y == 0.0f)
+ size.y = default_size;
+ const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
+ ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f);
+ if (!ItemAdd(bb, id))
+ return false;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held);
+
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf);
+
+ ImVec4 col_rgb = col;
+ if (flags & ImGuiColorEditFlags_InputHSV)
+ ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z);
+
+ ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f);
+ float grid_step = ImMin(size.x, size.y) / 2.99f;
+ float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f);
+ ImRect bb_inner = bb;
+ float off = 0.0f;
+ if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
+ {
+ off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts.
+ bb_inner.Expand(off);
+ }
+ if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f)
+ {
+ float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f);
+ RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawFlags_RoundCornersRight);
+ window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft);
+ }
+ else
+ {
+ // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha
+ ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha;
+ if (col_source.w < 1.0f)
+ RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding);
+ else
+ window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding);
+ }
+ RenderNavHighlight(bb, id);
+ if ((flags & ImGuiColorEditFlags_NoBorder) == 0)
+ {
+ if (g.Style.FrameBorderSize > 0.0f)
+ RenderFrameBorder(bb.Min, bb.Max, rounding);
+ else
+ window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
+ }
+
+ // Drag and Drop Source
+ // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test.
+ if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource())
+ {
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once);
+ else
+ SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once);
+ ColorButton(desc_id, col, flags);
+ SameLine();
+ TextEx("Color");
+ EndDragDropSource();
+ }
+
+ // Tooltip
+ if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
+ ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
+
+ return pressed;
+}
+
+// Initialize/override default color options
+void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0)
+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_;
+ if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0)
+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_;
+ if ((flags & ImGuiColorEditFlags_PickerMask_) == 0)
+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_;
+ if ((flags & ImGuiColorEditFlags_InputMask_) == 0)
+ flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_;
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected
+ IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected
+ g.ColorEditOptions = flags;
+}
+
+// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
+void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+
+ BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None);
+ const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
+ if (text_end > text)
+ {
+ TextEx(text, text_end);
+ Separator();
+ }
+
+ ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2);
+ ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
+ int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
+ ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz);
+ SameLine();
+ if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_))
+ {
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]);
+ else
+ Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]);
+ }
+ else if (flags & ImGuiColorEditFlags_InputHSV)
+ {
+ if (flags & ImGuiColorEditFlags_NoAlpha)
+ Text("H: %.3f, S: %.3f, V: %.3f", col[0], col[1], col[2]);
+ else
+ Text("H: %.3f, S: %.3f, V: %.3f, A: %.3f", col[0], col[1], col[2], col[3]);
+ }
+ EndTooltip();
+}
+
+void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
+{
+ bool allow_opt_inputs = !(flags & ImGuiColorEditFlags_DisplayMask_);
+ bool allow_opt_datatype = !(flags & ImGuiColorEditFlags_DataTypeMask_);
+ if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context"))
+ return;
+ ImGuiContext& g = *GImGui;
+ ImGuiColorEditFlags opts = g.ColorEditOptions;
+ if (allow_opt_inputs)
+ {
+ if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB;
+ if (RadioButton("HSV", (opts & ImGuiColorEditFlags_DisplayHSV) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHSV;
+ if (RadioButton("Hex", (opts & ImGuiColorEditFlags_DisplayHex) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHex;
+ }
+ if (allow_opt_datatype)
+ {
+ if (allow_opt_inputs) Separator();
+ if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Uint8;
+ if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Float;
+ }
+
+ if (allow_opt_inputs || allow_opt_datatype)
+ Separator();
+ if (Button("Copy as..", ImVec2(-1, 0)))
+ OpenPopup("Copy");
+ if (BeginPopup("Copy"))
+ {
+ int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
+ char buf[64];
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ if (!(flags & ImGuiColorEditFlags_NoAlpha))
+ {
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca);
+ if (Selectable(buf))
+ SetClipboardText(buf);
+ }
+ EndPopup();
+ }
+
+ g.ColorEditOptions = opts;
+ EndPopup();
+}
+
+void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags)
+{
+ bool allow_opt_picker = !(flags & ImGuiColorEditFlags_PickerMask_);
+ bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar);
+ if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context"))
+ return;
+ ImGuiContext& g = *GImGui;
+ if (allow_opt_picker)
+ {
+ ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
+ PushItemWidth(picker_size.x);
+ for (int picker_type = 0; picker_type < 2; picker_type++)
+ {
+ // Draw small/thumbnail version of each picker type (over an invisible button for selection)
+ if (picker_type > 0) Separator();
+ PushID(picker_type);
+ ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoSidePreview | (flags & ImGuiColorEditFlags_NoAlpha);
+ if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar;
+ if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
+ ImVec2 backup_pos = GetCursorScreenPos();
+ if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
+ g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_);
+ SetCursorScreenPos(backup_pos);
+ ImVec4 previewing_ref_col;
+ memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));
+ ColorPicker4("##previewing_picker", &previewing_ref_col.x, picker_flags);
+ PopID();
+ }
+ PopItemWidth();
+ }
+ if (allow_opt_alpha_bar)
+ {
+ if (allow_opt_picker) Separator();
+ CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
+ }
+ EndPopup();
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
+//-------------------------------------------------------------------------
+// - TreeNode()
+// - TreeNodeV()
+// - TreeNodeEx()
+// - TreeNodeExV()
+// - TreeNodeBehavior() [Internal]
+// - TreePush()
+// - TreePop()
+// - GetTreeNodeToLabelSpacing()
+// - SetNextItemOpen()
+// - CollapsingHeader()
+//-------------------------------------------------------------------------
+
+bool ImGui::TreeNode(const char* str_id, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(str_id, 0, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(ptr_id, 0, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNode(const char* label)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+ return TreeNodeBehavior(window->GetID(label), 0, label, NULL);
+}
+
+bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args)
+{
+ return TreeNodeExV(str_id, 0, fmt, args);
+}
+
+bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args)
+{
+ return TreeNodeExV(ptr_id, 0, fmt, args);
+}
+
+bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ return TreeNodeBehavior(window->GetID(label), flags, label, NULL);
+}
+
+bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(str_id, flags, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ bool is_open = TreeNodeExV(ptr_id, flags, fmt, args);
+ va_end(args);
+ return is_open;
+}
+
+bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ return TreeNodeBehavior(window->GetID(str_id), flags, g.TempBuffer, label_end);
+}
+
+bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const char* label_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
+ return TreeNodeBehavior(window->GetID(ptr_id), flags, g.TempBuffer, label_end);
+}
+
+bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
+{
+ if (flags & ImGuiTreeNodeFlags_Leaf)
+ return true;
+
+ // We only write to the tree storage if the user clicks (or explicitly use the SetNextItemOpen function)
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ ImGuiStorage* storage = window->DC.StateStorage;
+
+ bool is_open;
+ if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
+ {
+ if (g.NextItemData.OpenCond & ImGuiCond_Always)
+ {
+ is_open = g.NextItemData.OpenVal;
+ storage->SetInt(id, is_open);
+ }
+ else
+ {
+ // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently.
+ const int stored_value = storage->GetInt(id, -1);
+ if (stored_value == -1)
+ {
+ is_open = g.NextItemData.OpenVal;
+ storage->SetInt(id, is_open);
+ }
+ else
+ {
+ is_open = stored_value != 0;
+ }
+ }
+ }
+ else
+ {
+ is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0;
+ }
+
+ // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior).
+ // NB- If we are above max depth we still allow manually opened nodes to be logged.
+ if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && (window->DC.TreeDepth - g.LogDepthRef) < g.LogDepthToExpand)
+ is_open = true;
+
+ return is_open;
+}
+
+bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
+ const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y));
+
+ if (!label_end)
+ label_end = FindRenderedTextEnd(label);
+ const ImVec2 label_size = CalcTextSize(label, label_end, false);
+
+ // We vertically grow up to current line height up the typical widget height.
+ const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2);
+ ImRect frame_bb;
+ frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
+ frame_bb.Min.y = window->DC.CursorPos.y;
+ frame_bb.Max.x = window->WorkRect.Max.x;
+ frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
+ if (display_frame)
+ {
+ // Framed header expand a little outside the default padding, to the edge of InnerClipRect
+ // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f)
+ frame_bb.Min.x -= IM_FLOOR(window->WindowPadding.x * 0.5f - 1.0f);
+ frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
+ }
+
+ const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapser arrow width + Spacing
+ const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
+ const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapser
+ ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
+ ItemSize(ImVec2(text_width, frame_height), padding.y);
+
+ // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
+ ImRect interact_bb = frame_bb;
+ if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0)
+ interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f;
+
+ // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
+ // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
+ // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
+ const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
+ bool is_open = TreeNodeBehaviorIsOpen(id, flags);
+ if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
+ window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
+
+ bool item_add = ItemAdd(interact_bb, id);
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
+ g.LastItemData.DisplayRect = frame_bb;
+
+ if (!item_add)
+ {
+ if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
+ TreePushOverrideID(id);
+ IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
+ return is_open;
+ }
+
+ ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None;
+ if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
+ button_flags |= ImGuiButtonFlags_AllowItemOverlap;
+ if (!is_leaf)
+ button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
+
+ // We allow clicking on the arrow section with keyboard modifiers held, in order to easily
+ // allow browsing a tree while preserving selection with code implementing multi-selection patterns.
+ // When clicking on the rest of the tree node we always disallow keyboard modifiers.
+ const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x;
+ const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
+ const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
+ if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
+ button_flags |= ImGuiButtonFlags_NoKeyModifiers;
+
+ // Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags.
+ // Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support.
+ // - Single-click on label = Toggle on MouseUp (default, when _OpenOnArrow=0)
+ // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=0)
+ // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=1)
+ // - Double-click on label = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1)
+ // - Double-click on arrow = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1 and _OpenOnArrow=0)
+ // It is rather standard that arrow click react on Down rather than Up.
+ // We set ImGuiButtonFlags_PressedOnClickRelease on OpenOnDoubleClick because we want the item to be active on the initial MouseDown in order for drag and drop to work.
+ if (is_mouse_x_over_arrow)
+ button_flags |= ImGuiButtonFlags_PressedOnClick;
+ else if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
+ button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
+ else
+ button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
+
+ bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
+ const bool was_selected = selected;
+
+ bool hovered, held;
+ bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags);
+ bool toggled = false;
+ if (!is_leaf)
+ {
+ if (pressed && g.DragDropHoldJustPressedId != id)
+ {
+ if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id))
+ toggled = true;
+ if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
+ toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
+ if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2)
+ toggled = true;
+ }
+ else if (pressed && g.DragDropHoldJustPressedId == id)
+ {
+ IM_ASSERT(button_flags & ImGuiButtonFlags_PressedOnDragDropHold);
+ if (!is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again.
+ toggled = true;
+ }
+
+ if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open)
+ {
+ toggled = true;
+ NavMoveRequestCancel();
+ }
+ if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority?
+ {
+ toggled = true;
+ NavMoveRequestCancel();
+ }
+
+ if (toggled)
+ {
+ is_open = !is_open;
+ window->DC.StateStorage->SetInt(id, is_open);
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledOpen;
+ }
+ }
+ if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
+ SetItemAllowOverlap();
+
+ // In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger.
+ if (selected != was_selected) //-V547
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
+
+ // Render
+ const ImU32 text_col = GetColorU32(ImGuiCol_Text);
+ ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin;
+ if (display_frame)
+ {
+ // Framed type
+ const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+ RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
+ RenderNavHighlight(frame_bb, id, nav_highlight_flags);
+ if (flags & ImGuiTreeNodeFlags_Bullet)
+ RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
+ else if (!is_leaf)
+ RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
+ else // Leaf without bullet, left-adjusted text
+ text_pos.x -= text_offset_x;
+ if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
+ frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
+
+ if (g.LogEnabled)
+ LogSetNextTextDecoration("###", "###");
+ RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
+ }
+ else
+ {
+ // Unframed typed for tree nodes
+ if (hovered || selected)
+ {
+ const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+ RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
+ }
+ RenderNavHighlight(frame_bb, id, nav_highlight_flags);
+ if (flags & ImGuiTreeNodeFlags_Bullet)
+ RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
+ else if (!is_leaf)
+ RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
+ if (g.LogEnabled)
+ LogSetNextTextDecoration(">", NULL);
+ RenderText(text_pos, label, label_end, false);
+ }
+
+ if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
+ TreePushOverrideID(id);
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
+ return is_open;
+}
+
+void ImGui::TreePush(const char* str_id)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ Indent();
+ window->DC.TreeDepth++;
+ PushID(str_id);
+}
+
+void ImGui::TreePush(const void* ptr_id)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ Indent();
+ window->DC.TreeDepth++;
+ PushID(ptr_id);
+}
+
+void ImGui::TreePushOverrideID(ImGuiID id)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ Indent();
+ window->DC.TreeDepth++;
+ PushOverrideID(id);
+}
+
+void ImGui::TreePop()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ Unindent();
+
+ window->DC.TreeDepth--;
+ ImU32 tree_depth_mask = (1 << window->DC.TreeDepth);
+
+ // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled)
+ if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet())
+ if (g.NavIdIsAlive && (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask))
+ {
+ SetNavID(window->IDStack.back(), g.NavLayer, 0, ImRect());
+ NavMoveRequestCancel();
+ }
+ window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1;
+
+ IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
+ PopID();
+}
+
+// Horizontal distance preceding label when using TreeNode() or Bullet()
+float ImGui::GetTreeNodeToLabelSpacing()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize + (g.Style.FramePadding.x * 2.0f);
+}
+
+// Set next TreeNode/CollapsingHeader open state.
+void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.CurrentWindow->SkipItems)
+ return;
+ g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen;
+ g.NextItemData.OpenVal = is_open;
+ g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always;
+}
+
+// CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag).
+// This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode().
+bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label);
+}
+
+// p_visible == NULL : regular collapsing header
+// p_visible != NULL && *p_visible == true : show a small close button on the corner of the header, clicking the button will set *p_visible = false
+// p_visible != NULL && *p_visible == false : do not show the header at all
+// Do not mistake this with the Open state of the header itself, which you can adjust with SetNextItemOpen() or ImGuiTreeNodeFlags_DefaultOpen.
+bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ if (p_visible && !*p_visible)
+ return false;
+
+ ImGuiID id = window->GetID(label);
+ flags |= ImGuiTreeNodeFlags_CollapsingHeader;
+ if (p_visible)
+ flags |= ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton;
+ bool is_open = TreeNodeBehavior(id, flags, label);
+ if (p_visible != NULL)
+ {
+ // Create a small overlapping close button
+ // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
+ // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow.
+ ImGuiContext& g = *GImGui;
+ ImGuiLastItemData last_item_backup = g.LastItemData;
+ float button_size = g.FontSize;
+ float button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);
+ float button_y = g.LastItemData.Rect.Min.y;
+ ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id);
+ if (CloseButton(close_button_id, ImVec2(button_x, button_y)))
+ *p_visible = false;
+ g.LastItemData = last_item_backup;
+ }
+
+ return is_open;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Selectable
+//-------------------------------------------------------------------------
+// - Selectable()
+//-------------------------------------------------------------------------
+
+// Tip: pass a non-visible label (e.g. "##hello") then you can use the space to draw other text or image.
+// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
+// With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags.
+// FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
+bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+
+ // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
+ ImGuiID id = window->GetID(label);
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+ ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
+ ImVec2 pos = window->DC.CursorPos;
+ pos.y += window->DC.CurrLineTextBaseOffset;
+ ItemSize(size, 0.0f);
+
+ // Fill horizontal space
+ // We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitly right-aligned sizes not visibly match other widgets.
+ const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0;
+ const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x;
+ const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x;
+ if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth))
+ size.x = ImMax(label_size.x, max_x - min_x);
+
+ // Text stays at the submission position, but bounding box may be extended on both sides
+ const ImVec2 text_min = pos;
+ const ImVec2 text_max(min_x + size.x, pos.y + size.y);
+
+ // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
+ ImRect bb(min_x, pos.y, text_max.x, text_max.y);
+ if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0)
+ {
+ const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x;
+ const float spacing_y = style.ItemSpacing.y;
+ const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
+ const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
+ bb.Min.x -= spacing_L;
+ bb.Min.y -= spacing_U;
+ bb.Max.x += (spacing_x - spacing_L);
+ bb.Max.y += (spacing_y - spacing_U);
+ }
+ //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); }
+
+ // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackground for every Selectable..
+ const float backup_clip_rect_min_x = window->ClipRect.Min.x;
+ const float backup_clip_rect_max_x = window->ClipRect.Max.x;
+ if (span_all_columns)
+ {
+ window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
+ window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
+ }
+
+ const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0;
+ const bool item_add = ItemAdd(bb, id, NULL, disabled_item ? ImGuiItemFlags_Disabled : ImGuiItemFlags_None);
+ if (span_all_columns)
+ {
+ window->ClipRect.Min.x = backup_clip_rect_min_x;
+ window->ClipRect.Max.x = backup_clip_rect_max_x;
+ }
+
+ if (!item_add)
+ return false;
+
+ const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
+ if (disabled_item && !disabled_global) // Only testing this as an optimization
+ BeginDisabled();
+
+ // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only,
+ // which would be advantageous since most selectable are not selected.
+ if (span_all_columns && window->DC.CurrentColumns)
+ PushColumnsBackground();
+ else if (span_all_columns && g.CurrentTable)
+ TablePushBackgroundChannel();
+
+ // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
+ ImGuiButtonFlags button_flags = 0;
+ if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; }
+ if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; }
+ if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; }
+ if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }
+ if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; }
+
+ const bool was_selected = selected;
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
+
+ // Auto-select when moved into
+ // - This will be more fully fleshed in the range-select branch
+ // - This is not exposed as it won't nicely work with some user side handling of shift/control
+ // - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons
+ // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())
+ // - (2) usage will fail with clipped items
+ // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
+ if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent)
+ if (g.NavJustMovedToId == id)
+ selected = pressed = true;
+
+ // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
+ if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
+ {
+ if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
+ {
+ SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
+ g.NavDisableHighlight = true;
+ }
+ }
+ if (pressed)
+ MarkItemEdited(id);
+
+ if (flags & ImGuiSelectableFlags_AllowItemOverlap)
+ SetItemAllowOverlap();
+
+ // In this branch, Selectable() cannot toggle the selection so this will never trigger.
+ if (selected != was_selected) //-V547
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
+
+ // Render
+ if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld))
+ hovered = true;
+ if (hovered || selected)
+ {
+ const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
+ RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
+ }
+ RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
+
+ if (span_all_columns && window->DC.CurrentColumns)
+ PopColumnsBackground();
+ else if (span_all_columns && g.CurrentTable)
+ TablePopBackgroundChannel();
+
+ RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
+
+ // Automatically close popups
+ if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.LastItemData.InFlags & ImGuiItemFlags_SelectableDontClosePopup))
+ CloseCurrentPopup();
+
+ if (disabled_item && !disabled_global)
+ EndDisabled();
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ return pressed; //-V1020
+}
+
+bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
+{
+ if (Selectable(label, *p_selected, flags, size_arg))
+ {
+ *p_selected = !*p_selected;
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: ListBox
+//-------------------------------------------------------------------------
+// - BeginListBox()
+// - EndListBox()
+// - ListBox()
+//-------------------------------------------------------------------------
+
+// Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty"
+// Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height).
+bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = GetID(label);
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ // Size default to hold ~7.25 items.
+ // Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
+ ImVec2 size = ImFloor(CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f));
+ ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y));
+ ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
+ ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
+ g.NextItemData.ClearFlags();
+
+ if (!IsRectVisible(bb.Min, bb.Max))
+ {
+ ItemSize(bb.GetSize(), style.FramePadding.y);
+ ItemAdd(bb, 0, &frame_bb);
+ return false;
+ }
+
+ // FIXME-OPT: We could omit the BeginGroup() if label_size.x but would need to omit the EndGroup() as well.
+ BeginGroup();
+ if (label_size.x > 0.0f)
+ {
+ ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y);
+ RenderText(label_pos, label);
+ window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size);
+ }
+
+ BeginChildFrame(id, frame_bb.GetSize());
+ return true;
+}
+
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+// OBSOLETED in 1.81 (from February 2021)
+bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
+{
+ // If height_in_items == -1, default height is maximum 7.
+ ImGuiContext& g = *GImGui;
+ float height_in_items_f = (height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f;
+ ImVec2 size;
+ size.x = 0.0f;
+ size.y = GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f;
+ return BeginListBox(label, size);
+}
+#endif
+
+void ImGui::EndListBox()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?");
+ IM_UNUSED(window);
+
+ EndChildFrame();
+ EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label
+}
+
+bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items)
+{
+ const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items);
+ return value_changed;
+}
+
+// This is merely a helper around BeginListBox(), EndListBox().
+// Considering using those directly to submit custom data or store selection differently.
+bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int height_in_items)
+{
+ ImGuiContext& g = *GImGui;
+
+ // Calculate size from "height_in_items"
+ if (height_in_items < 0)
+ height_in_items = ImMin(items_count, 7);
+ float height_in_items_f = height_in_items + 0.25f;
+ ImVec2 size(0.0f, ImFloor(GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f));
+
+ if (!BeginListBox(label, size))
+ return false;
+
+ // Assume all items have even height (= 1 line of text). If you need items of different height,
+ // you can create a custom version of ListBox() in your code without using the clipper.
+ bool value_changed = false;
+ ImGuiListClipper clipper;
+ clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
+ while (clipper.Step())
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ {
+ const char* item_text;
+ if (!items_getter(data, i, &item_text))
+ item_text = "*Unknown item*";
+
+ PushID(i);
+ const bool item_selected = (i == *current_item);
+ if (Selectable(item_text, item_selected))
+ {
+ *current_item = i;
+ value_changed = true;
+ }
+ if (item_selected)
+ SetItemDefaultFocus();
+ PopID();
+ }
+ EndListBox();
+
+ if (value_changed)
+ MarkItemEdited(g.LastItemData.ID);
+
+ return value_changed;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: PlotLines, PlotHistogram
+//-------------------------------------------------------------------------
+// - PlotEx() [Internal]
+// - PlotLines()
+// - PlotHistogram()
+//-------------------------------------------------------------------------
+// Plot/Graph widgets are not very good.
+// Consider writing your own, or using a third-party one, see:
+// - ImPlot https://github.com/epezent/implot
+// - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
+//-------------------------------------------------------------------------
+
+int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return -1;
+
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+
+ const ImVec2 label_size = CalcTextSize(label, NULL, true);
+ if (frame_size.x == 0.0f)
+ frame_size.x = CalcItemWidth();
+ if (frame_size.y == 0.0f)
+ frame_size.y = label_size.y + (style.FramePadding.y * 2);
+
+ const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
+ const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding);
+ const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0));
+ ItemSize(total_bb, style.FramePadding.y);
+ if (!ItemAdd(total_bb, 0, &frame_bb))
+ return -1;
+ const bool hovered = ItemHoverable(frame_bb, id);
+
+ // Determine scale from values if not specified
+ if (scale_min == FLT_MAX || scale_max == FLT_MAX)
+ {
+ float v_min = FLT_MAX;
+ float v_max = -FLT_MAX;
+ for (int i = 0; i < values_count; i++)
+ {
+ const float v = values_getter(data, i);
+ if (v != v) // Ignore NaN values
+ continue;
+ v_min = ImMin(v_min, v);
+ v_max = ImMax(v_max, v);
+ }
+ if (scale_min == FLT_MAX)
+ scale_min = v_min;
+ if (scale_max == FLT_MAX)
+ scale_max = v_max;
+ }
+
+ RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
+
+ const int values_count_min = (plot_type == ImGuiPlotType_Lines) ? 2 : 1;
+ int idx_hovered = -1;
+ if (values_count >= values_count_min)
+ {
+ int res_w = ImMin((int)frame_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
+ int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0);
+
+ // Tooltip on hover
+ if (hovered && inner_bb.Contains(g.IO.MousePos))
+ {
+ const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
+ const int v_idx = (int)(t * item_count);
+ IM_ASSERT(v_idx >= 0 && v_idx < values_count);
+
+ const float v0 = values_getter(data, (v_idx + values_offset) % values_count);
+ const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count);
+ if (plot_type == ImGuiPlotType_Lines)
+ SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx + 1, v1);
+ else if (plot_type == ImGuiPlotType_Histogram)
+ SetTooltip("%d: %8.4g", v_idx, v0);
+ idx_hovered = v_idx;
+ }
+
+ const float t_step = 1.0f / (float)res_w;
+ const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min));
+
+ float v0 = values_getter(data, (0 + values_offset) % values_count);
+ float t0 = 0.0f;
+ ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle
+ float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (1 + scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands
+
+ const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram);
+ const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered);
+
+ for (int n = 0; n < res_w; n++)
+ {
+ const float t1 = t0 + t_step;
+ const int v1_idx = (int)(t0 * item_count + 0.5f);
+ IM_ASSERT(v1_idx >= 0 && v1_idx < values_count);
+ const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count);
+ const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) );
+
+ // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
+ ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
+ ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
+ if (plot_type == ImGuiPlotType_Lines)
+ {
+ window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
+ }
+ else if (plot_type == ImGuiPlotType_Histogram)
+ {
+ if (pos1.x >= pos0.x + 2.0f)
+ pos1.x -= 1.0f;
+ window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
+ }
+
+ t0 = t1;
+ tp0 = tp1;
+ }
+ }
+
+ // Text overlay
+ if (overlay_text)
+ RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f));
+
+ if (label_size.x > 0.0f)
+ RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
+
+ // Return hovered index or -1 if none are hovered.
+ // This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx().
+ return idx_hovered;
+}
+
+struct ImGuiPlotArrayGetterData
+{
+ const float* Values;
+ int Stride;
+
+ ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; }
+};
+
+static float Plot_ArrayGetter(void* data, int idx)
+{
+ ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data;
+ const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride);
+ return v;
+}
+
+void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
+{
+ ImGuiPlotArrayGetterData data(values, stride);
+ PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
+{
+ PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
+{
+ ImGuiPlotArrayGetterData data(values, stride);
+ PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size)
+{
+ PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Value helpers
+// Those is not very useful, legacy API.
+//-------------------------------------------------------------------------
+// - Value()
+//-------------------------------------------------------------------------
+
+void ImGui::Value(const char* prefix, bool b)
+{
+ Text("%s: %s", prefix, (b ? "true" : "false"));
+}
+
+void ImGui::Value(const char* prefix, int v)
+{
+ Text("%s: %d", prefix, v);
+}
+
+void ImGui::Value(const char* prefix, unsigned int v)
+{
+ Text("%s: %d", prefix, v);
+}
+
+void ImGui::Value(const char* prefix, float v, const char* float_format)
+{
+ if (float_format)
+ {
+ char fmt[64];
+ ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format);
+ Text(fmt, prefix, v);
+ }
+ else
+ {
+ Text("%s: %.3f", prefix, v);
+ }
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] MenuItem, BeginMenu, EndMenu, etc.
+//-------------------------------------------------------------------------
+// - ImGuiMenuColumns [Internal]
+// - BeginMenuBar()
+// - EndMenuBar()
+// - BeginMainMenuBar()
+// - EndMainMenuBar()
+// - BeginMenu()
+// - EndMenu()
+// - MenuItemEx() [Internal]
+// - MenuItem()
+//-------------------------------------------------------------------------
+
+// Helpers for internal use
+void ImGuiMenuColumns::Update(float spacing, bool window_reappearing)
+{
+ if (window_reappearing)
+ memset(Widths, 0, sizeof(Widths));
+ Spacing = (ImU16)spacing;
+ CalcNextTotalWidth(true);
+ memset(Widths, 0, sizeof(Widths));
+ TotalWidth = NextTotalWidth;
+ NextTotalWidth = 0;
+}
+
+void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets)
+{
+ ImU16 offset = 0;
+ bool want_spacing = false;
+ for (int i = 0; i < IM_ARRAYSIZE(Widths); i++)
+ {
+ ImU16 width = Widths[i];
+ if (want_spacing && width > 0)
+ offset += Spacing;
+ want_spacing |= (width > 0);
+ if (update_offsets)
+ {
+ if (i == 1) { OffsetLabel = offset; }
+ if (i == 2) { OffsetShortcut = offset; }
+ if (i == 3) { OffsetMark = offset; }
+ }
+ offset += width;
+ }
+ NextTotalWidth = offset;
+}
+
+float ImGuiMenuColumns::DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark)
+{
+ Widths[0] = ImMax(Widths[0], (ImU16)w_icon);
+ Widths[1] = ImMax(Widths[1], (ImU16)w_label);
+ Widths[2] = ImMax(Widths[2], (ImU16)w_shortcut);
+ Widths[3] = ImMax(Widths[3], (ImU16)w_mark);
+ CalcNextTotalWidth(false);
+ return (float)ImMax(TotalWidth, NextTotalWidth);
+}
+
+// FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere..
+// Currently the main responsibility of this function being to setup clip-rect + horizontal layout + menu navigation layer.
+// Ideally we also want this to be responsible for claiming space out of the main window scrolling rectangle, in which case ImGuiWindowFlags_MenuBar will become unnecessary.
+// Then later the same system could be used for multiple menu-bars, scrollbars, side-bars.
+bool ImGui::BeginMenuBar()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+ if (!(window->Flags & ImGuiWindowFlags_MenuBar))
+ return false;
+
+ IM_ASSERT(!window->DC.MenuBarAppending);
+ BeginGroup(); // Backup position on layer 0 // FIXME: Misleading to use a group for that backup/restore
+ PushID("##menubar");
+
+ // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
+ // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy.
+ ImRect bar_rect = window->MenuBarRect();
+ ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y));
+ clip_rect.ClipWith(window->OuterRectClipped);
+ PushClipRect(clip_rect.Min, clip_rect.Max, false);
+
+ // We overwrite CursorMaxPos because BeginGroup sets it to CursorPos (essentially the .EmitItem hack in EndMenuBar() would need something analogous here, maybe a BeginGroupEx() with flags).
+ window->DC.CursorPos = window->DC.CursorMaxPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y);
+ window->DC.LayoutType = ImGuiLayoutType_Horizontal;
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
+ window->DC.MenuBarAppending = true;
+ AlignTextToFramePadding();
+ return true;
+}
+
+void ImGui::EndMenuBar()
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return;
+ ImGuiContext& g = *GImGui;
+
+ // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings.
+ if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu))
+ {
+ // Try to find out if the request is for one of our child menu
+ ImGuiWindow* nav_earliest_child = g.NavWindow;
+ while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu))
+ nav_earliest_child = nav_earliest_child->ParentWindow;
+ if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0)
+ {
+ // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
+ // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering)
+ const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
+ IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check
+ FocusWindow(window);
+ SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
+ g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
+ g.NavDisableMouseHover = g.NavMousePosDirty = true;
+ NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat
+ }
+ }
+
+ IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'"
+ IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar);
+ IM_ASSERT(window->DC.MenuBarAppending);
+ PopClipRect();
+ PopID();
+ window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
+ g.GroupStack.back().EmitItem = false;
+ EndGroup(); // Restore position on layer 0
+ window->DC.LayoutType = ImGuiLayoutType_Vertical;
+ window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
+ window->DC.MenuBarAppending = false;
+}
+
+// Important: calling order matters!
+// FIXME: Somehow overlapping with docking tech.
+// FIXME: The "rect-cut" aspect of this could be formalized into a lower-level helper (rect-cut: https://halt.software/dead-simple-layouts)
+bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags)
+{
+ IM_ASSERT(dir != ImGuiDir_None);
+
+ ImGuiWindow* bar_window = FindWindowByName(name);
+ if (bar_window == NULL || bar_window->BeginCount == 0)
+ {
+ // Calculate and set window size/position
+ ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)(viewport_p ? viewport_p : GetMainViewport());
+ ImRect avail_rect = viewport->GetBuildWorkRect();
+ ImGuiAxis axis = (dir == ImGuiDir_Up || dir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
+ ImVec2 pos = avail_rect.Min;
+ if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
+ pos[axis] = avail_rect.Max[axis] - axis_size;
+ ImVec2 size = avail_rect.GetSize();
+ size[axis] = axis_size;
+ SetNextWindowPos(pos);
+ SetNextWindowSize(size);
+
+ // Report our size into work area (for next frame) using actual window size
+ if (dir == ImGuiDir_Up || dir == ImGuiDir_Left)
+ viewport->BuildWorkOffsetMin[axis] += axis_size;
+ else if (dir == ImGuiDir_Down || dir == ImGuiDir_Right)
+ viewport->BuildWorkOffsetMax[axis] -= axis_size;
+ }
+
+ window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
+ PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+ PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint
+ bool is_open = Begin(name, NULL, window_flags);
+ PopStyleVar(2);
+
+ return is_open;
+}
+
+bool ImGui::BeginMainMenuBar()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
+
+ // For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
+ // FIXME: This could be generalized as an opt-in way to clamp window->DC.CursorStartPos to avoid SafeArea?
+ // FIXME: Consider removing support for safe area down the line... it's messy. Nowadays consoles have support for TV calibration in OS settings.
+ g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
+ ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
+ float height = GetFrameHeight();
+ bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags);
+ g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
+
+ if (is_open)
+ BeginMenuBar();
+ else
+ End();
+ return is_open;
+}
+
+void ImGui::EndMainMenuBar()
+{
+ EndMenuBar();
+
+ // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window
+ // FIXME: With this strategy we won't be able to restore a NULL focus.
+ ImGuiContext& g = *GImGui;
+ if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest)
+ FocusTopMostWindowUnderOne(g.NavWindow, NULL);
+
+ End();
+}
+
+bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = window->GetID(label);
+ bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
+
+ // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
+ ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
+ if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
+ flags |= ImGuiWindowFlags_ChildWindow;
+
+ // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
+ // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame.
+ // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used.
+ if (g.MenusIdSubmittedThisFrame.contains(id))
+ {
+ if (menu_is_open)
+ menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
+ else
+ g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values
+ return menu_is_open;
+ }
+
+ // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu
+ g.MenusIdSubmittedThisFrame.push_back(id);
+
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+ bool pressed;
+ bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
+ ImGuiWindow* backed_nav_window = g.NavWindow;
+ if (menuset_is_open)
+ g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
+
+ // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
+ // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
+ // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering.
+ ImVec2 popup_pos, pos = window->DC.CursorPos;
+ PushID(label);
+ if (!enabled)
+ BeginDisabled();
+ const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
+ {
+ // Menu inside an horizontal menu bar
+ // Selectable extend their highlight by half ItemSpacing in each direction.
+ // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
+ popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
+ window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
+ float w = label_size.x;
+ ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
+ pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups, ImVec2(w, 0.0f));
+ RenderText(text_pos, label);
+ PopStyleVar();
+ window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
+ }
+ else
+ {
+ // Menu inside a regular/vertical menu
+ // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
+ // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
+ popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
+ float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
+ float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
+ float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
+ float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
+ ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
+ pressed = Selectable("", menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
+ RenderText(text_pos, label);
+ if (icon_w > 0.0f)
+ RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
+ RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
+ }
+ if (!enabled)
+ EndDisabled();
+
+ const bool hovered = (g.HoveredId == id) && enabled;
+ if (menuset_is_open)
+ g.NavWindow = backed_nav_window;
+
+ bool want_open = false;
+ bool want_close = false;
+ if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
+ {
+ // Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu
+ // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
+ bool moving_toward_other_child_menu = false;
+ ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL;
+ if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar))
+ {
+ float ref_unit = g.FontSize; // FIXME-DPI
+ ImRect next_window_rect = child_menu_window->Rect();
+ ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
+ ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
+ ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
+ float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // add a bit of extra slack.
+ ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues (FIXME: ??)
+ tb.y = ta.y + ImMax((tb.y - extra) - ta.y, -ref_unit * 8.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
+ tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +ref_unit * 8.0f);
+ moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
+ //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_other_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
+ }
+ if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu)
+ want_close = true;
+
+ // Open
+ if (!menu_is_open && pressed) // Click/activate to open
+ want_open = true;
+ else if (!menu_is_open && hovered && !moving_toward_other_child_menu) // Hover to open
+ want_open = true;
+ if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
+ {
+ want_open = true;
+ NavMoveRequestCancel();
+ }
+ }
+ else
+ {
+ // Menu bar
+ if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it
+ {
+ want_close = true;
+ want_open = menu_is_open = false;
+ }
+ else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others
+ {
+ want_open = true;
+ }
+ else if (g.NavId == id && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
+ {
+ want_open = true;
+ NavMoveRequestCancel();
+ }
+ }
+
+ if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
+ want_close = true;
+ if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None))
+ ClosePopupToLevel(g.BeginPopupStack.Size, true);
+
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
+ PopID();
+
+ if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
+ {
+ // Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
+ OpenPopup(label);
+ return false;
+ }
+
+ menu_is_open |= want_open;
+ if (want_open)
+ OpenPopup(label);
+
+ if (menu_is_open)
+ {
+ SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos.
+ menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
+ }
+ else
+ {
+ g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
+ }
+
+ return menu_is_open;
+}
+
+bool ImGui::BeginMenu(const char* label, bool enabled)
+{
+ return BeginMenuEx(label, NULL, enabled);
+}
+
+void ImGui::EndMenu()
+{
+ // Nav: When a left move request _within our child menu_ failed, close ourselves (the _parent_ menu).
+ // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs.
+ // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction.
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical)
+ if (g.NavWindow && (g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow == window)
+ {
+ ClosePopupToLevel(g.BeginPopupStack.Size, true);
+ NavMoveRequestCancel();
+ }
+
+ EndPopup();
+}
+
+bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled)
+{
+ ImGuiWindow* window = GetCurrentWindow();
+ if (window->SkipItems)
+ return false;
+
+ ImGuiContext& g = *GImGui;
+ ImGuiStyle& style = g.Style;
+ ImVec2 pos = window->DC.CursorPos;
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
+ // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
+ bool pressed;
+ PushID(label);
+ if (!enabled)
+ BeginDisabled();
+ const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
+ const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
+ if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
+ {
+ // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
+ // Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
+ float w = label_size.x;
+ window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
+ ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
+ PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
+ pressed = Selectable("", selected, flags, ImVec2(w, 0.0f));
+ PopStyleVar();
+ RenderText(text_pos, label);
+ window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
+ }
+ else
+ {
+ // Menu item inside a vertical menu
+ // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
+ // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
+ float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
+ float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
+ float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
+ float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
+ float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
+ pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
+ RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
+ if (icon_w > 0.0f)
+ RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
+ if (shortcut_w > 0.0f)
+ {
+ PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
+ RenderText(pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false);
+ PopStyleColor();
+ }
+ if (selected)
+ RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
+ }
+ IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
+ if (!enabled)
+ EndDisabled();
+ PopID();
+
+ return pressed;
+}
+
+bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled)
+{
+ return MenuItemEx(label, NULL, shortcut, selected, enabled);
+}
+
+bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled)
+{
+ if (MenuItemEx(label, NULL, shortcut, p_selected ? *p_selected : false, enabled))
+ {
+ if (p_selected)
+ *p_selected = !*p_selected;
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: BeginTabBar, EndTabBar, etc.
+//-------------------------------------------------------------------------
+// - BeginTabBar()
+// - BeginTabBarEx() [Internal]
+// - EndTabBar()
+// - TabBarLayout() [Internal]
+// - TabBarCalcTabID() [Internal]
+// - TabBarCalcMaxTabWidth() [Internal]
+// - TabBarFindTabById() [Internal]
+// - TabBarRemoveTab() [Internal]
+// - TabBarCloseTab() [Internal]
+// - TabBarScrollClamp() [Internal]
+// - TabBarScrollToTab() [Internal]
+// - TabBarQueueChangeTabOrder() [Internal]
+// - TabBarScrollingButtons() [Internal]
+// - TabBarTabListPopupButton() [Internal]
+//-------------------------------------------------------------------------
+
+struct ImGuiTabBarSection
+{
+ int TabCount; // Number of tabs in this section.
+ float Width; // Sum of width of tabs in this section (after shrinking down)
+ float Spacing; // Horizontal spacing at the end of the section.
+
+ ImGuiTabBarSection() { memset(this, 0, sizeof(*this)); }
+};
+
+namespace ImGui
+{
+ static void TabBarLayout(ImGuiTabBar* tab_bar);
+ static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label);
+ static float TabBarCalcMaxTabWidth();
+ static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
+ static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections);
+ static ImGuiTabItem* TabBarScrollingButtons(ImGuiTabBar* tab_bar);
+ static ImGuiTabItem* TabBarTabListPopupButton(ImGuiTabBar* tab_bar);
+}
+
+ImGuiTabBar::ImGuiTabBar()
+{
+ memset(this, 0, sizeof(*this));
+ CurrFrameVisible = PrevFrameVisible = -1;
+ LastTabItemIdx = -1;
+}
+
+static inline int TabItemGetSectionIdx(const ImGuiTabItem* tab)
+{
+ return (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
+}
+
+static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs)
+{
+ const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
+ const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
+ const int a_section = TabItemGetSectionIdx(a);
+ const int b_section = TabItemGetSectionIdx(b);
+ if (a_section != b_section)
+ return a_section - b_section;
+ return (int)(a->IndexDuringLayout - b->IndexDuringLayout);
+}
+
+static int IMGUI_CDECL TabItemComparerByBeginOrder(const void* lhs, const void* rhs)
+{
+ const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
+ const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
+ return (int)(a->BeginOrder - b->BeginOrder);
+}
+
+static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref)
+{
+ ImGuiContext& g = *GImGui;
+ return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index);
+}
+
+static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar)
+{
+ ImGuiContext& g = *GImGui;
+ if (g.TabBars.Contains(tab_bar))
+ return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar));
+ return ImGuiPtrOrIndex(tab_bar);
+}
+
+bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ ImGuiID id = window->GetID(str_id);
+ ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id);
+ ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2);
+ tab_bar->ID = id;
+ return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused);
+}
+
+bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImGuiTabBarFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ if ((flags & ImGuiTabBarFlags_DockNode) == 0)
+ PushOverrideID(tab_bar->ID);
+
+ // Add to stack
+ g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar));
+ g.CurrentTabBar = tab_bar;
+
+ // Append with multiple BeginTabBar()/EndTabBar() pairs.
+ tab_bar->BackupCursorPos = window->DC.CursorPos;
+ if (tab_bar->CurrFrameVisible == g.FrameCount)
+ {
+ window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY);
+ tab_bar->BeginCount++;
+ return true;
+ }
+
+ // Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable
+ if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable)))
+ if (tab_bar->Tabs.Size > 1)
+ ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
+ tab_bar->TabsAddedNew = false;
+
+ // Flags
+ if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
+ flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
+
+ tab_bar->Flags = flags;
+ tab_bar->BarRect = tab_bar_bb;
+ tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab()
+ tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
+ tab_bar->CurrFrameVisible = g.FrameCount;
+ tab_bar->PrevTabsContentsHeight = tab_bar->CurrTabsContentsHeight;
+ tab_bar->CurrTabsContentsHeight = 0.0f;
+ tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
+ tab_bar->FramePadding = g.Style.FramePadding;
+ tab_bar->TabsActiveCount = 0;
+ tab_bar->BeginCount = 1;
+
+ // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
+ window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY);
+
+ // Draw separator
+ const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive);
+ const float y = tab_bar->BarRect.Max.y - 1.0f;
+ {
+ const float separator_min_x = tab_bar->BarRect.Min.x - IM_FLOOR(window->WindowPadding.x * 0.5f);
+ const float separator_max_x = tab_bar->BarRect.Max.x + IM_FLOOR(window->WindowPadding.x * 0.5f);
+ window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
+ }
+ return true;
+}
+
+void ImGui::EndTabBar()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ ImGuiTabBar* tab_bar = g.CurrentTabBar;
+ if (tab_bar == NULL)
+ {
+ IM_ASSERT_USER_ERROR(tab_bar != NULL, "Mismatched BeginTabBar()/EndTabBar()!");
+ return;
+ }
+
+ // Fallback in case no TabItem have been submitted
+ if (tab_bar->WantLayout)
+ TabBarLayout(tab_bar);
+
+ // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed().
+ const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
+ if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing)
+ {
+ tab_bar->CurrTabsContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, tab_bar->CurrTabsContentsHeight);
+ window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->CurrTabsContentsHeight;
+ }
+ else
+ {
+ window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->PrevTabsContentsHeight;
+ }
+ if (tab_bar->BeginCount > 1)
+ window->DC.CursorPos = tab_bar->BackupCursorPos;
+
+ if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
+ PopID();
+
+ g.CurrentTabBarStack.pop_back();
+ g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
+}
+
+// This is called only once a frame before by the first call to ItemTab()
+// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
+static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
+{
+ ImGuiContext& g = *GImGui;
+ tab_bar->WantLayout = false;
+
+ // Garbage collect by compacting list
+ // Detect if we need to sort out tab list (e.g. in rare case where a tab changed section)
+ int tab_dst_n = 0;
+ bool need_sort_by_section = false;
+ ImGuiTabBarSection sections[3]; // Layout sections: Leading, Central, Trailing
+ for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n];
+ if (tab->LastFrameVisible < tab_bar->PrevFrameVisible || tab->WantClose)
+ {
+ // Remove tab
+ if (tab_bar->VisibleTabId == tab->ID) { tab_bar->VisibleTabId = 0; }
+ if (tab_bar->SelectedTabId == tab->ID) { tab_bar->SelectedTabId = 0; }
+ if (tab_bar->NextSelectedTabId == tab->ID) { tab_bar->NextSelectedTabId = 0; }
+ continue;
+ }
+ if (tab_dst_n != tab_src_n)
+ tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n];
+
+ tab = &tab_bar->Tabs[tab_dst_n];
+ tab->IndexDuringLayout = (ImS16)tab_dst_n;
+
+ // We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another)
+ int curr_tab_section_n = TabItemGetSectionIdx(tab);
+ if (tab_dst_n > 0)
+ {
+ ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1];
+ int prev_tab_section_n = TabItemGetSectionIdx(prev_tab);
+ if (curr_tab_section_n == 0 && prev_tab_section_n != 0)
+ need_sort_by_section = true;
+ if (prev_tab_section_n == 2 && curr_tab_section_n != 2)
+ need_sort_by_section = true;
+ }
+
+ sections[curr_tab_section_n].TabCount++;
+ tab_dst_n++;
+ }
+ if (tab_bar->Tabs.Size != tab_dst_n)
+ tab_bar->Tabs.resize(tab_dst_n);
+
+ if (need_sort_by_section)
+ ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerBySection);
+
+ // Calculate spacing between sections
+ sections[0].Spacing = sections[0].TabCount > 0 && (sections[1].TabCount + sections[2].TabCount) > 0 ? g.Style.ItemInnerSpacing.x : 0.0f;
+ sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f;
+
+ // Setup next selected tab
+ ImGuiID scroll_to_tab_id = 0;
+ if (tab_bar->NextSelectedTabId)
+ {
+ tab_bar->SelectedTabId = tab_bar->NextSelectedTabId;
+ tab_bar->NextSelectedTabId = 0;
+ scroll_to_tab_id = tab_bar->SelectedTabId;
+ }
+
+ // Process order change request (we could probably process it when requested but it's just saner to do it in a single spot).
+ if (tab_bar->ReorderRequestTabId != 0)
+ {
+ if (TabBarProcessReorder(tab_bar))
+ if (tab_bar->ReorderRequestTabId == tab_bar->SelectedTabId)
+ scroll_to_tab_id = tab_bar->ReorderRequestTabId;
+ tab_bar->ReorderRequestTabId = 0;
+ }
+
+ // Tab List Popup (will alter tab_bar->BarRect and therefore the available width!)
+ const bool tab_list_popup_button = (tab_bar->Flags & ImGuiTabBarFlags_TabListPopupButton) != 0;
+ if (tab_list_popup_button)
+ if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar)) // NB: Will alter BarRect.Min.x!
+ scroll_to_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
+
+ // Leading/Trailing tabs will be shrink only if central one aren't visible anymore, so layout the shrink data as: leading, trailing, central
+ // (whereas our tabs are stored as: leading, central, trailing)
+ int shrink_buffer_indexes[3] = { 0, sections[0].TabCount + sections[2].TabCount, sections[0].TabCount };
+ g.ShrinkWidthBuffer.resize(tab_bar->Tabs.Size);
+
+ // Compute ideal tabs widths + store them into shrink buffer
+ ImGuiTabItem* most_recently_selected_tab = NULL;
+ int curr_section_n = -1;
+ bool found_selected_tab_id = false;
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible);
+
+ if ((most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected) && !(tab->Flags & ImGuiTabItemFlags_Button))
+ most_recently_selected_tab = tab;
+ if (tab->ID == tab_bar->SelectedTabId)
+ found_selected_tab_id = true;
+ if (scroll_to_tab_id == 0 && g.NavJustMovedToId == tab->ID)
+ scroll_to_tab_id = tab->ID;
+
+ // Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
+ // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
+ // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
+ const char* tab_name = tab_bar->GetTabName(tab);
+ const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true;
+ tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x;
+
+ int section_n = TabItemGetSectionIdx(tab);
+ ImGuiTabBarSection* section = &sections[section_n];
+ section->Width += tab->ContentWidth + (section_n == curr_section_n ? g.Style.ItemInnerSpacing.x : 0.0f);
+ curr_section_n = section_n;
+
+ // Store data so we can build an array sorted by width if we need to shrink tabs down
+ IM_MSVC_WARNING_SUPPRESS(6385);
+ int shrink_buffer_index = shrink_buffer_indexes[section_n]++;
+ g.ShrinkWidthBuffer[shrink_buffer_index].Index = tab_n;
+ g.ShrinkWidthBuffer[shrink_buffer_index].Width = tab->ContentWidth;
+
+ IM_ASSERT(tab->ContentWidth > 0.0f);
+ tab->Width = tab->ContentWidth;
+ }
+
+ // Compute total ideal width (used for e.g. auto-resizing a window)
+ tab_bar->WidthAllTabsIdeal = 0.0f;
+ for (int section_n = 0; section_n < 3; section_n++)
+ tab_bar->WidthAllTabsIdeal += sections[section_n].Width + sections[section_n].Spacing;
+
+ // Horizontal scrolling buttons
+ // (note that TabBarScrollButtons() will alter BarRect.Max.x)
+ if ((tab_bar->WidthAllTabsIdeal > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll))
+ if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar))
+ {
+ scroll_to_tab_id = scroll_and_select_tab->ID;
+ if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0)
+ tab_bar->SelectedTabId = scroll_to_tab_id;
+ }
+
+ // Shrink widths if full tabs don't fit in their allocated space
+ float section_0_w = sections[0].Width + sections[0].Spacing;
+ float section_1_w = sections[1].Width + sections[1].Spacing;
+ float section_2_w = sections[2].Width + sections[2].Spacing;
+ bool central_section_is_visible = (section_0_w + section_2_w) < tab_bar->BarRect.GetWidth();
+ float width_excess;
+ if (central_section_is_visible)
+ width_excess = ImMax(section_1_w - (tab_bar->BarRect.GetWidth() - section_0_w - section_2_w), 0.0f); // Excess used to shrink central section
+ else
+ width_excess = (section_0_w + section_2_w) - tab_bar->BarRect.GetWidth(); // Excess used to shrink leading/trailing section
+
+ // With ImGuiTabBarFlags_FittingPolicyScroll policy, we will only shrink leading/trailing if the central section is not visible anymore
+ if (width_excess > 0.0f && ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown) || !central_section_is_visible))
+ {
+ int shrink_data_count = (central_section_is_visible ? sections[1].TabCount : sections[0].TabCount + sections[2].TabCount);
+ int shrink_data_offset = (central_section_is_visible ? sections[0].TabCount + sections[2].TabCount : 0);
+ ShrinkWidths(g.ShrinkWidthBuffer.Data + shrink_data_offset, shrink_data_count, width_excess);
+
+ // Apply shrunk values into tabs and sections
+ for (int tab_n = shrink_data_offset; tab_n < shrink_data_offset + shrink_data_count; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index];
+ float shrinked_width = IM_FLOOR(g.ShrinkWidthBuffer[tab_n].Width);
+ if (shrinked_width < 0.0f)
+ continue;
+
+ int section_n = TabItemGetSectionIdx(tab);
+ sections[section_n].Width -= (tab->Width - shrinked_width);
+ tab->Width = shrinked_width;
+ }
+ }
+
+ // Layout all active tabs
+ int section_tab_index = 0;
+ float tab_offset = 0.0f;
+ tab_bar->WidthAllTabs = 0.0f;
+ for (int section_n = 0; section_n < 3; section_n++)
+ {
+ ImGuiTabBarSection* section = &sections[section_n];
+ if (section_n == 2)
+ tab_offset = ImMin(ImMax(0.0f, tab_bar->BarRect.GetWidth() - section->Width), tab_offset);
+
+ for (int tab_n = 0; tab_n < section->TabCount; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n];
+ tab->Offset = tab_offset;
+ tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f);
+ }
+ tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f);
+ tab_offset += section->Spacing;
+ section_tab_index += section->TabCount;
+ }
+
+ // If we have lost the selected tab, select the next most recently active one
+ if (found_selected_tab_id == false)
+ tab_bar->SelectedTabId = 0;
+ if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
+ scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
+
+ // Lock in visible tab
+ tab_bar->VisibleTabId = tab_bar->SelectedTabId;
+ tab_bar->VisibleTabWasSubmitted = false;
+
+ // Update scrolling
+ if (scroll_to_tab_id != 0)
+ TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
+ tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
+ tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
+ if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
+ {
+ // Scrolling speed adjust itself so we can always reach our target in 1/3 seconds.
+ // Teleport if we are aiming far off the visible line
+ tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontSize);
+ tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f);
+ const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontSize);
+ tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed);
+ }
+ else
+ {
+ tab_bar->ScrollingSpeed = 0.0f;
+ }
+ tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing;
+ tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing;
+
+ // Clear name buffers
+ if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
+ tab_bar->TabsNames.Buf.resize(0);
+
+ // Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame)
+ ImGuiWindow* window = g.CurrentWindow;
+ window->DC.CursorPos = tab_bar->BarRect.Min;
+ ItemSize(ImVec2(tab_bar->WidthAllTabs, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
+ window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, tab_bar->BarRect.Min.x + tab_bar->WidthAllTabsIdeal);
+}
+
+// Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.
+static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
+{
+ if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
+ {
+ ImGuiID id = ImHashStr(label);
+ KeepAliveID(id);
+ return id;
+ }
+ else
+ {
+ ImGuiWindow* window = GImGui->CurrentWindow;
+ return window->GetID(label);
+ }
+}
+
+static float ImGui::TabBarCalcMaxTabWidth()
+{
+ ImGuiContext& g = *GImGui;
+ return g.FontSize * 20.0f;
+}
+
+ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
+{
+ if (tab_id != 0)
+ for (int n = 0; n < tab_bar->Tabs.Size; n++)
+ if (tab_bar->Tabs[n].ID == tab_id)
+ return &tab_bar->Tabs[n];
+ return NULL;
+}
+
+// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
+void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
+{
+ if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
+ tab_bar->Tabs.erase(tab);
+ if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; }
+ if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; }
+ if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; }
+}
+
+// Called on manual closure attempt
+void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
+{
+ IM_ASSERT(!(tab->Flags & ImGuiTabItemFlags_Button));
+ if (!(tab->Flags & ImGuiTabItemFlags_UnsavedDocument))
+ {
+ // This will remove a frame of lag for selecting another tab on closure.
+ // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure
+ tab->WantClose = true;
+ if (tab_bar->VisibleTabId == tab->ID)
+ {
+ tab->LastFrameVisible = -1;
+ tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0;
+ }
+ }
+ else
+ {
+ // Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
+ if (tab_bar->VisibleTabId != tab->ID)
+ tab_bar->NextSelectedTabId = tab->ID;
+ }
+}
+
+static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling)
+{
+ scrolling = ImMin(scrolling, tab_bar->WidthAllTabs - tab_bar->BarRect.GetWidth());
+ return ImMax(scrolling, 0.0f);
+}
+
+// Note: we may scroll to tab that are not selected! e.g. using keyboard arrow keys
+static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections)
+{
+ ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
+ if (tab == NULL)
+ return;
+ if (tab->Flags & ImGuiTabItemFlags_SectionMask_)
+ return;
+
+ ImGuiContext& g = *GImGui;
+ float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
+ int order = tab_bar->GetTabOrder(tab);
+
+ // Scrolling happens only in the central section (leading/trailing sections are not scrolling)
+ // FIXME: This is all confusing.
+ float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
+
+ // We make all tabs positions all relative Sections[0].Width to make code simpler
+ float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f);
+ float tab_x2 = tab->Offset - sections[0].Width + tab->Width + (order + 1 < tab_bar->Tabs.Size - sections[2].TabCount ? margin : 1.0f);
+ tab_bar->ScrollingTargetDistToVisibility = 0.0f;
+ if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= scrollable_width))
+ {
+ // Scroll to the left
+ tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f);
+ tab_bar->ScrollingTarget = tab_x1;
+ }
+ else if (tab_bar->ScrollingTarget < tab_x2 - scrollable_width)
+ {
+ // Scroll to the right
+ tab_bar->ScrollingTargetDistToVisibility = ImMax((tab_x1 - scrollable_width) - tab_bar->ScrollingAnim, 0.0f);
+ tab_bar->ScrollingTarget = tab_x2 - scrollable_width;
+ }
+}
+
+void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
+{
+ IM_ASSERT(offset != 0);
+ IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
+ tab_bar->ReorderRequestTabId = tab->ID;
+ tab_bar->ReorderRequestOffset = (ImS16)offset;
+}
+
+void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
+{
+ ImGuiContext& g = *GImGui;
+ IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
+ if ((tab_bar->Flags & ImGuiTabBarFlags_Reorderable) == 0)
+ return;
+
+ const bool is_central_section = (src_tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
+ const float bar_offset = tab_bar->BarRect.Min.x - (is_central_section ? tab_bar->ScrollingTarget : 0);
+
+ // Count number of contiguous tabs we are crossing over
+ const int dir = (bar_offset + src_tab->Offset) > mouse_pos.x ? -1 : +1;
+ const int src_idx = tab_bar->Tabs.index_from_ptr(src_tab);
+ int dst_idx = src_idx;
+ for (int i = src_idx; i >= 0 && i < tab_bar->Tabs.Size; i += dir)
+ {
+ // Reordered tabs must share the same section
+ const ImGuiTabItem* dst_tab = &tab_bar->Tabs[i];
+ if (dst_tab->Flags & ImGuiTabItemFlags_NoReorder)
+ break;
+ if ((dst_tab->Flags & ImGuiTabItemFlags_SectionMask_) != (src_tab->Flags & ImGuiTabItemFlags_SectionMask_))
+ break;
+ dst_idx = i;
+
+ // Include spacing after tab, so when mouse cursor is between tabs we would not continue checking further tabs that are not hovered.
+ const float x1 = bar_offset + dst_tab->Offset - g.Style.ItemInnerSpacing.x;
+ const float x2 = bar_offset + dst_tab->Offset + dst_tab->Width + g.Style.ItemInnerSpacing.x;
+ //GetForegroundDrawList()->AddRect(ImVec2(x1, tab_bar->BarRect.Min.y), ImVec2(x2, tab_bar->BarRect.Max.y), IM_COL32(255, 0, 0, 255));
+ if ((dir < 0 && mouse_pos.x > x1) || (dir > 0 && mouse_pos.x < x2))
+ break;
+ }
+
+ if (dst_idx != src_idx)
+ TabBarQueueReorder(tab_bar, src_tab, dst_idx - src_idx);
+}
+
+bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
+{
+ ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId);
+ if (tab1 == NULL || (tab1->Flags & ImGuiTabItemFlags_NoReorder))
+ return false;
+
+ //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
+ int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
+ if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
+ return false;
+
+ // Reordered tabs must share the same section
+ // (Note: TabBarQueueReorderFromMousePos() also has a similar test but since we allow direct calls to TabBarQueueReorder() we do it here too)
+ ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
+ if (tab2->Flags & ImGuiTabItemFlags_NoReorder)
+ return false;
+ if ((tab1->Flags & ImGuiTabItemFlags_SectionMask_) != (tab2->Flags & ImGuiTabItemFlags_SectionMask_))
+ return false;
+
+ ImGuiTabItem item_tmp = *tab1;
+ ImGuiTabItem* src_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 + 1 : tab2;
+ ImGuiTabItem* dst_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 : tab2 + 1;
+ const int move_count = (tab_bar->ReorderRequestOffset > 0) ? tab_bar->ReorderRequestOffset : -tab_bar->ReorderRequestOffset;
+ memmove(dst_tab, src_tab, move_count * sizeof(ImGuiTabItem));
+ *tab2 = item_tmp;
+
+ if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
+ MarkIniSettingsDirty();
+ return true;
+}
+
+static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f);
+ const float scrolling_buttons_width = arrow_button_size.x * 2.0f;
+
+ const ImVec2 backup_cursor_pos = window->DC.CursorPos;
+ //window->DrawList->AddRect(ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y), ImVec2(tab_bar->BarRect.Max.x, tab_bar->BarRect.Max.y), IM_COL32(255,0,0,255));
+
+ int select_dir = 0;
+ ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
+ arrow_col.w *= 0.5f;
+
+ PushStyleColor(ImGuiCol_Text, arrow_col);
+ PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
+ const float backup_repeat_delay = g.IO.KeyRepeatDelay;
+ const float backup_repeat_rate = g.IO.KeyRepeatRate;
+ g.IO.KeyRepeatDelay = 0.250f;
+ g.IO.KeyRepeatRate = 0.200f;
+ float x = ImMax(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.x - scrolling_buttons_width);
+ window->DC.CursorPos = ImVec2(x, tab_bar->BarRect.Min.y);
+ if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
+ select_dir = -1;
+ window->DC.CursorPos = ImVec2(x + arrow_button_size.x, tab_bar->BarRect.Min.y);
+ if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat))
+ select_dir = +1;
+ PopStyleColor(2);
+ g.IO.KeyRepeatRate = backup_repeat_rate;
+ g.IO.KeyRepeatDelay = backup_repeat_delay;
+
+ ImGuiTabItem* tab_to_scroll_to = NULL;
+ if (select_dir != 0)
+ if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
+ {
+ int selected_order = tab_bar->GetTabOrder(tab_item);
+ int target_order = selected_order + select_dir;
+
+ // Skip tab item buttons until another tab item is found or end is reached
+ while (tab_to_scroll_to == NULL)
+ {
+ // If we are at the end of the list, still scroll to make our tab visible
+ tab_to_scroll_to = &tab_bar->Tabs[(target_order >= 0 && target_order < tab_bar->Tabs.Size) ? target_order : selected_order];
+
+ // Cross through buttons
+ // (even if first/last item is a button, return it so we can update the scroll)
+ if (tab_to_scroll_to->Flags & ImGuiTabItemFlags_Button)
+ {
+ target_order += select_dir;
+ selected_order += select_dir;
+ tab_to_scroll_to = (target_order < 0 || target_order >= tab_bar->Tabs.Size) ? tab_to_scroll_to : NULL;
+ }
+ }
+ }
+ window->DC.CursorPos = backup_cursor_pos;
+ tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f;
+
+ return tab_to_scroll_to;
+}
+
+static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+
+ // We use g.Style.FramePadding.y to match the square ArrowButton size
+ const float tab_list_popup_button_width = g.FontSize + g.Style.FramePadding.y;
+ const ImVec2 backup_cursor_pos = window->DC.CursorPos;
+ window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y);
+ tab_bar->BarRect.Min.x += tab_list_popup_button_width;
+
+ ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text];
+ arrow_col.w *= 0.5f;
+ PushStyleColor(ImGuiCol_Text, arrow_col);
+ PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
+ bool open = BeginCombo("##v", NULL, ImGuiComboFlags_NoPreview | ImGuiComboFlags_HeightLargest);
+ PopStyleColor(2);
+
+ ImGuiTabItem* tab_to_select = NULL;
+ if (open)
+ {
+ for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
+ if (tab->Flags & ImGuiTabItemFlags_Button)
+ continue;
+
+ const char* tab_name = tab_bar->GetTabName(tab);
+ if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
+ tab_to_select = tab;
+ }
+ EndCombo();
+ }
+
+ window->DC.CursorPos = backup_cursor_pos;
+ return tab_to_select;
+}
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: BeginTabItem, EndTabItem, etc.
+//-------------------------------------------------------------------------
+// - BeginTabItem()
+// - EndTabItem()
+// - TabItemButton()
+// - TabItemEx() [Internal]
+// - SetTabItemClosed()
+// - TabItemCalcSize() [Internal]
+// - TabItemBackground() [Internal]
+// - TabItemLabelAndCloseButton() [Internal]
+//-------------------------------------------------------------------------
+
+bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ ImGuiTabBar* tab_bar = g.CurrentTabBar;
+ if (tab_bar == NULL)
+ {
+ IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!");
+ return false;
+ }
+ IM_ASSERT(!(flags & ImGuiTabItemFlags_Button)); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead!
+
+ bool ret = TabItemEx(tab_bar, label, p_open, flags);
+ if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
+ {
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
+ PushOverrideID(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label)
+ }
+ return ret;
+}
+
+void ImGui::EndTabItem()
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return;
+
+ ImGuiTabBar* tab_bar = g.CurrentTabBar;
+ if (tab_bar == NULL)
+ {
+ IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
+ return;
+ }
+ IM_ASSERT(tab_bar->LastTabItemIdx >= 0);
+ ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx];
+ if (!(tab->Flags & ImGuiTabItemFlags_NoPushId))
+ PopID();
+}
+
+bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags)
+{
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ ImGuiTabBar* tab_bar = g.CurrentTabBar;
+ if (tab_bar == NULL)
+ {
+ IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
+ return false;
+ }
+ return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder);
+}
+
+bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)
+{
+ // Layout whole tab bar if not already done
+ if (tab_bar->WantLayout)
+ TabBarLayout(tab_bar);
+
+ ImGuiContext& g = *GImGui;
+ ImGuiWindow* window = g.CurrentWindow;
+ if (window->SkipItems)
+ return false;
+
+ const ImGuiStyle& style = g.Style;
+ const ImGuiID id = TabBarCalcTabID(tab_bar, label);
+
+ // If the user called us with *p_open == false, we early out and don't render.
+ // We make a call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID.
+ IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
+ if (p_open && !*p_open)
+ {
+ ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus);
+ return false;
+ }
+
+ IM_ASSERT(!p_open || !(flags & ImGuiTabItemFlags_Button));
+ IM_ASSERT((flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)); // Can't use both Leading and Trailing
+
+ // Store into ImGuiTabItemFlags_NoCloseButton, also honor ImGuiTabItemFlags_NoCloseButton passed by user (although not documented)
+ if (flags & ImGuiTabItemFlags_NoCloseButton)
+ p_open = NULL;
+ else if (p_open == NULL)
+ flags |= ImGuiTabItemFlags_NoCloseButton;
+
+ // Calculate tab contents size
+ ImVec2 size = TabItemCalcSize(label, p_open != NULL);
+
+ // Acquire tab data
+ ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id);
+ bool tab_is_new = false;
+ if (tab == NULL)
+ {
+ tab_bar->Tabs.push_back(ImGuiTabItem());
+ tab = &tab_bar->Tabs.back();
+ tab->ID = id;
+ tab->Width = size.x;
+ tab_bar->TabsAddedNew = true;
+ tab_is_new = true;
+ }
+ tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab);
+ tab->ContentWidth = size.x;
+ tab->BeginOrder = tab_bar->TabsActiveCount++;
+
+ const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
+ const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;
+ const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount);
+ const bool is_tab_button = (flags & ImGuiTabItemFlags_Button) != 0;
+ tab->LastFrameVisible = g.FrameCount;
+ tab->Flags = flags;
+
+ // Append name with zero-terminator
+ tab->NameOffset = (ImS32)tab_bar->TabsNames.size();
+ tab_bar->TabsNames.append(label, label + strlen(label) + 1);
+
+ // Update selected tab
+ if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
+ if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
+ if (!is_tab_button)
+ tab_bar->NextSelectedTabId = id; // New tabs gets activated
+ if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // SetSelected can only be passed on explicit tab bar
+ if (!is_tab_button)
+ tab_bar->NextSelectedTabId = id;
+
+ // Lock visibility
+ // (Note: tab_contents_visible != tab_selected... because CTRL+TAB operations may preview some tabs without selecting them!)
+ bool tab_contents_visible = (tab_bar->VisibleTabId == id);
+ if (tab_contents_visible)
+ tab_bar->VisibleTabWasSubmitted = true;
+
+ // On the very first frame of a tab bar we let first tab contents be visible to minimize appearing glitches
+ if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing)
+ if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs))
+ tab_contents_visible = true;
+
+ // Note that tab_is_new is not necessarily the same as tab_appearing! When a tab bar stops being submitted
+ // and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'.
+ if (tab_appearing && (!tab_bar_appearing || tab_is_new))
+ {
+ ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus);
+ if (is_tab_button)
+ return false;
+ return tab_contents_visible;
+ }
+
+ if (tab_bar->SelectedTabId == id)
+ tab->LastFrameSelected = g.FrameCount;
+
+ // Backup current layout position
+ const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
+
+ // Layout
+ const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
+ size.x = tab->Width;
+ if (is_central_section)
+ window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
+ else
+ window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f);
+ ImVec2 pos = window->DC.CursorPos;
+ ImRect bb(pos, pos + size);
+
+ // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
+ const bool want_clip_rect = is_central_section && (bb.Min.x < tab_bar->ScrollingRectMinX || bb.Max.x > tab_bar->ScrollingRectMaxX);
+ if (want_clip_rect)
+ PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->ScrollingRectMinX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true);
+
+ ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos;
+ ItemSize(bb.GetSize(), style.FramePadding.y);
+ window->DC.CursorMaxPos = backup_cursor_max_pos;
+
+ if (!ItemAdd(bb, id))
+ {
+ if (want_clip_rect)
+ PopClipRect();
+ window->DC.CursorPos = backup_main_cursor_pos;
+ return tab_contents_visible;
+ }
+
+ // Click to Select a tab
+ ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowItemOverlap);
+ if (g.DragDropActive)
+ button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
+ bool hovered, held;
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
+ if (pressed && !is_tab_button)
+ tab_bar->NextSelectedTabId = id;
+
+ // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
+ if (g.ActiveId != id)
+ SetItemAllowOverlap();
+
+ // Drag and drop: re-order tabs
+ if (held && !tab_appearing && IsMouseDragging(0))
+ {
+ if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable))
+ {
+ // While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x
+ if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
+ {
+ TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
+ }
+ else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
+ {
+ TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
+ }
+ }
+ }
+
+#if 0
+ if (hovered && g.HoveredIdNotActiveTimer > TOOLTIP_DELAY && bb.GetWidth() < tab->ContentWidth)
+ {
+ // Enlarge tab display when hovering
+ bb.Max.x = bb.Min.x + IM_FLOOR(ImLerp(bb.GetWidth(), tab->ContentWidth, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f)));
+ display_draw_list = GetForegroundDrawList(window);
+ TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive));
+ }
+#endif
+
+ // Render tab shape
+ ImDrawList* display_draw_list = window->DrawList;
+ const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabUnfocused));
+ TabItemBackground(display_draw_list, bb, flags, tab_col);
+ RenderNavHighlight(bb, id);
+
+ // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
+ const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
+ if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
+ if (!is_tab_button)
+ tab_bar->NextSelectedTabId = id;
+
+ if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
+ flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
+
+ // Render tab label, process close button
+ const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0;
+ bool just_closed;
+ bool text_clipped;
+ TabItemLabelAndCloseButton(display_draw_list, bb, flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped);
+ if (just_closed && p_open != NULL)
+ {
+ *p_open = false;
+ TabBarCloseTab(tab_bar, tab);
+ }
+
+ // Restore main window position so user can draw there
+ if (want_clip_rect)
+ PopClipRect();
+ window->DC.CursorPos = backup_main_cursor_pos;
+
+ // Tooltip
+ // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok)
+ // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores)
+ // FIXME: This is a mess.
+ // FIXME: We may want disabled tab to still display the tooltip?
+ if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered())
+ if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
+ SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
+
+ IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected
+ if (is_tab_button)
+ return pressed;
+ return tab_contents_visible;
+}
+
+// [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed.
+// To use it to need to call the function SetTabItemClosed() between BeginTabBar() and EndTabBar().
+// Tabs closed by the close button will automatically be flagged to avoid this issue.
+void ImGui::SetTabItemClosed(const char* label)
+{
+ ImGuiContext& g = *GImGui;
+ bool is_within_manual_tab_bar = g.CurrentTabBar && !(g.CurrentTabBar->Flags & ImGuiTabBarFlags_DockNode);
+ if (is_within_manual_tab_bar)
+ {
+ ImGuiTabBar* tab_bar = g.CurrentTabBar;
+ ImGuiID tab_id = TabBarCalcTabID(tab_bar, label);
+ if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
+ tab->WantClose = true; // Will be processed by next call to TabBarLayout()
+ }
+}
+
+ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+ ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f);
+ if (has_close_button)
+ size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle.
+ else
+ size.x += g.Style.FramePadding.x + 1.0f;
+ return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y);
+}
+
+void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col)
+{
+ // While rendering tabs, we trim 1 pixel off the top of our bounding box so they can fit within a regular frame height while looking "detached" from it.
+ ImGuiContext& g = *GImGui;
+ const float width = bb.GetWidth();
+ IM_UNUSED(flags);
+ IM_ASSERT(width > 0.0f);
+ const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f));
+ const float y1 = bb.Min.y + 1.0f;
+ const float y2 = bb.Max.y - 1.0f;
+ draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
+ draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
+ draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
+ draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
+ draw_list->PathFillConvex(col);
+ if (g.Style.TabBorderSize > 0.0f)
+ {
+ draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
+ draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
+ draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
+ draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
+ draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize);
+ }
+}
+
+// Render text label (with custom clipping) + Unsaved Document marker + Close Button logic
+// We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter.
+void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped)
+{
+ ImGuiContext& g = *GImGui;
+ ImVec2 label_size = CalcTextSize(label, NULL, true);
+
+ if (out_just_closed)
+ *out_just_closed = false;
+ if (out_text_clipped)
+ *out_text_clipped = false;
+
+ if (bb.GetWidth() <= 1.0f)
+ return;
+
+ // In Style V2 we'll have full override of all colors per state (e.g. focused, selected)
+ // But right now if you want to alter text color of tabs this is what you need to do.
+#if 0
+ const float backup_alpha = g.Style.Alpha;
+ if (!is_contents_visible)
+ g.Style.Alpha *= 0.7f;
+#endif
+
+ // Render text label (with clipping + alpha gradient) + unsaved marker
+ ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
+ ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
+
+ // Return clipped state ignoring the close button
+ if (out_text_clipped)
+ {
+ *out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x;
+ //draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255));
+ }
+
+ const float button_sz = g.FontSize;
+ const ImVec2 button_pos(ImMax(bb.Min.x, bb.Max.x - frame_padding.x * 2.0f - button_sz), bb.Min.y);
+
+ // Close Button & Unsaved Marker
+ // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap()
+ // 'hovered' will be true when hovering the Tab but NOT when hovering the close button
+ // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button
+ // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false
+ bool close_button_pressed = false;
+ bool close_button_visible = false;
+ if (close_button_id != 0)
+ if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton))
+ if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id)
+ close_button_visible = true;
+ bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x);
+
+ if (close_button_visible)
+ {
+ ImGuiLastItemData last_item_backup = g.LastItemData;
+ PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding);
+ if (CloseButton(close_button_id, button_pos))
+ close_button_pressed = true;
+ PopStyleVar();
+ g.LastItemData = last_item_backup;
+
+ // Close with middle mouse button
+ if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2))
+ close_button_pressed = true;
+ }
+ else if (unsaved_marker_visible)
+ {
+ const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz) + g.Style.FramePadding * 2.0f);
+ RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text));
+ }
+
+ // This is all rather complicated
+ // (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position)
+ // FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist..
+ float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;
+ if (close_button_visible || unsaved_marker_visible)
+ {
+ text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f);
+ text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;
+ ellipsis_max_x = text_pixel_clip_bb.Max.x;
+ }
+ RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
+
+#if 0
+ if (!is_contents_visible)
+ g.Style.Alpha = backup_alpha;
+#endif
+
+ if (out_just_closed)
+ *out_just_closed = close_button_pressed;
+}
+
+
+#endif // #ifndef IMGUI_DISABLE
diff --git a/Client/ThirdParty/imgui/imstb_rectpack.h b/Client/ThirdParty/imgui/imstb_rectpack.h
new file mode 100644
index 0000000..3958952
--- /dev/null
+++ b/Client/ThirdParty/imgui/imstb_rectpack.h
@@ -0,0 +1,639 @@
+// [DEAR IMGUI]
+// This is a slightly modified version of stb_rect_pack.h 1.00.
+// Those changes would need to be pushed into nothings/stb:
+// - Added STBRP__CDECL
+// Grep for [DEAR IMGUI] to find the changes.
+
+// stb_rect_pack.h - v1.00 - public domain - rectangle packing
+// Sean Barrett 2014
+//
+// Useful for e.g. packing rectangular textures into an atlas.
+// Does not do rotation.
+//
+// Not necessarily the awesomest packing method, but better than
+// the totally naive one in stb_truetype (which is primarily what
+// this is meant to replace).
+//
+// Has only had a few tests run, may have issues.
+//
+// More docs to come.
+//
+// No memory allocations; uses qsort() and assert() from stdlib.
+// Can override those by defining STBRP_SORT and STBRP_ASSERT.
+//
+// This library currently uses the Skyline Bottom-Left algorithm.
+//
+// Please note: better rectangle packers are welcome! Please
+// implement them to the same API, but with a different init
+// function.
+//
+// Credits
+//
+// Library
+// Sean Barrett
+// Minor features
+// Martins Mozeiko
+// github:IntellectualKitty
+//
+// Bugfixes / warning fixes
+// Jeremy Jaussaud
+// Fabian Giesen
+//
+// Version history:
+//
+// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
+// 0.99 (2019-02-07) warning fixes
+// 0.11 (2017-03-03) return packing success/fail result
+// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
+// 0.09 (2016-08-27) fix compiler warnings
+// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
+// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
+// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
+// 0.05: added STBRP_ASSERT to allow replacing assert
+// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
+// 0.01: initial release
+//
+// LICENSE
+//
+// See end of file for license information.
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// INCLUDE SECTION
+//
+
+#ifndef STB_INCLUDE_STB_RECT_PACK_H
+#define STB_INCLUDE_STB_RECT_PACK_H
+
+#define STB_RECT_PACK_VERSION 1
+
+#ifdef STBRP_STATIC
+#define STBRP_DEF static
+#else
+#define STBRP_DEF extern
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct stbrp_context stbrp_context;
+typedef struct stbrp_node stbrp_node;
+typedef struct stbrp_rect stbrp_rect;
+
+#ifdef STBRP_LARGE_RECTS
+typedef int stbrp_coord;
+#else
+typedef unsigned short stbrp_coord;
+#endif
+
+STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
+// Assign packed locations to rectangles. The rectangles are of type
+// 'stbrp_rect' defined below, stored in the array 'rects', and there
+// are 'num_rects' many of them.
+//
+// Rectangles which are successfully packed have the 'was_packed' flag
+// set to a non-zero value and 'x' and 'y' store the minimum location
+// on each axis (i.e. bottom-left in cartesian coordinates, top-left
+// if you imagine y increasing downwards). Rectangles which do not fit
+// have the 'was_packed' flag set to 0.
+//
+// You should not try to access the 'rects' array from another thread
+// while this function is running, as the function temporarily reorders
+// the array while it executes.
+//
+// To pack into another rectangle, you need to call stbrp_init_target
+// again. To continue packing into the same rectangle, you can call
+// this function again. Calling this multiple times with multiple rect
+// arrays will probably produce worse packing results than calling it
+// a single time with the full rectangle array, but the option is
+// available.
+//
+// The function returns 1 if all of the rectangles were successfully
+// packed and 0 otherwise.
+
+struct stbrp_rect
+{
+ // reserved for your use:
+ int id;
+
+ // input:
+ stbrp_coord w, h;
+
+ // output:
+ stbrp_coord x, y;
+ int was_packed; // non-zero if valid packing
+
+}; // 16 bytes, nominally
+
+
+STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
+// Initialize a rectangle packer to:
+// pack a rectangle that is 'width' by 'height' in dimensions
+// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
+//
+// You must call this function every time you start packing into a new target.
+//
+// There is no "shutdown" function. The 'nodes' memory must stay valid for
+// the following stbrp_pack_rects() call (or calls), but can be freed after
+// the call (or calls) finish.
+//
+// Note: to guarantee best results, either:
+// 1. make sure 'num_nodes' >= 'width'
+// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
+//
+// If you don't do either of the above things, widths will be quantized to multiples
+// of small integers to guarantee the algorithm doesn't run out of temporary storage.
+//
+// If you do #2, then the non-quantized algorithm will be used, but the algorithm
+// may run out of temporary storage and be unable to pack some rectangles.
+
+STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
+// Optionally call this function after init but before doing any packing to
+// change the handling of the out-of-temp-memory scenario, described above.
+// If you call init again, this will be reset to the default (false).
+
+
+STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
+// Optionally select which packing heuristic the library should use. Different
+// heuristics will produce better/worse results for different data sets.
+// If you call init again, this will be reset to the default.
+
+enum
+{
+ STBRP_HEURISTIC_Skyline_default=0,
+ STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
+ STBRP_HEURISTIC_Skyline_BF_sortHeight
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// the details of the following structures don't matter to you, but they must
+// be visible so you can handle the memory allocations for them
+
+struct stbrp_node
+{
+ stbrp_coord x,y;
+ stbrp_node *next;
+};
+
+struct stbrp_context
+{
+ int width;
+ int height;
+ int align;
+ int init_mode;
+ int heuristic;
+ int num_nodes;
+ stbrp_node *active_head;
+ stbrp_node *free_head;
+ stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// IMPLEMENTATION SECTION
+//
+
+#ifdef STB_RECT_PACK_IMPLEMENTATION
+#ifndef STBRP_SORT
+#include <stdlib.h>
+#define STBRP_SORT qsort
+#endif
+
+#ifndef STBRP_ASSERT
+#include <assert.h>
+#define STBRP_ASSERT assert
+#endif
+
+// [DEAR IMGUI] Added STBRP__CDECL
+#ifdef _MSC_VER
+#define STBRP__NOTUSED(v) (void)(v)
+#define STBRP__CDECL __cdecl
+#else
+#define STBRP__NOTUSED(v) (void)sizeof(v)
+#define STBRP__CDECL
+#endif
+
+enum
+{
+ STBRP__INIT_skyline = 1
+};
+
+STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
+{
+ switch (context->init_mode) {
+ case STBRP__INIT_skyline:
+ STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
+ context->heuristic = heuristic;
+ break;
+ default:
+ STBRP_ASSERT(0);
+ }
+}
+
+STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
+{
+ if (allow_out_of_mem)
+ // if it's ok to run out of memory, then don't bother aligning them;
+ // this gives better packing, but may fail due to OOM (even though
+ // the rectangles easily fit). @TODO a smarter approach would be to only
+ // quantize once we've hit OOM, then we could get rid of this parameter.
+ context->align = 1;
+ else {
+ // if it's not ok to run out of memory, then quantize the widths
+ // so that num_nodes is always enough nodes.
+ //
+ // I.e. num_nodes * align >= width
+ // align >= width / num_nodes
+ // align = ceil(width/num_nodes)
+
+ context->align = (context->width + context->num_nodes-1) / context->num_nodes;
+ }
+}
+
+STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
+{
+ int i;
+#ifndef STBRP_LARGE_RECTS
+ STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
+#endif
+
+ for (i=0; i < num_nodes-1; ++i)
+ nodes[i].next = &nodes[i+1];
+ nodes[i].next = NULL;
+ context->init_mode = STBRP__INIT_skyline;
+ context->heuristic = STBRP_HEURISTIC_Skyline_default;
+ context->free_head = &nodes[0];
+ context->active_head = &context->extra[0];
+ context->width = width;
+ context->height = height;
+ context->num_nodes = num_nodes;
+ stbrp_setup_allow_out_of_mem(context, 0);
+
+ // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
+ context->extra[0].x = 0;
+ context->extra[0].y = 0;
+ context->extra[0].next = &context->extra[1];
+ context->extra[1].x = (stbrp_coord) width;
+#ifdef STBRP_LARGE_RECTS
+ context->extra[1].y = (1<<30);
+#else
+ context->extra[1].y = 65535;
+#endif
+ context->extra[1].next = NULL;
+}
+
+// find minimum y position if it starts at x1
+static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
+{
+ stbrp_node *node = first;
+ int x1 = x0 + width;
+ int min_y, visited_width, waste_area;
+
+ STBRP__NOTUSED(c);
+
+ STBRP_ASSERT(first->x <= x0);
+
+ #if 0
+ // skip in case we're past the node
+ while (node->next->x <= x0)
+ ++node;
+ #else
+ STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
+ #endif
+
+ STBRP_ASSERT(node->x <= x0);
+
+ min_y = 0;
+ waste_area = 0;
+ visited_width = 0;
+ while (node->x < x1) {
+ if (node->y > min_y) {
+ // raise min_y higher.
+ // we've accounted for all waste up to min_y,
+ // but we'll now add more waste for everything we've visted
+ waste_area += visited_width * (node->y - min_y);
+ min_y = node->y;
+ // the first time through, visited_width might be reduced
+ if (node->x < x0)
+ visited_width += node->next->x - x0;
+ else
+ visited_width += node->next->x - node->x;
+ } else {
+ // add waste area
+ int under_width = node->next->x - node->x;
+ if (under_width + visited_width > width)
+ under_width = width - visited_width;
+ waste_area += under_width * (min_y - node->y);
+ visited_width += under_width;
+ }
+ node = node->next;
+ }
+
+ *pwaste = waste_area;
+ return min_y;
+}
+
+typedef struct
+{
+ int x,y;
+ stbrp_node **prev_link;
+} stbrp__findresult;
+
+static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
+{
+ int best_waste = (1<<30), best_x, best_y = (1 << 30);
+ stbrp__findresult fr;
+ stbrp_node **prev, *node, *tail, **best = NULL;
+
+ // align to multiple of c->align
+ width = (width + c->align - 1);
+ width -= width % c->align;
+ STBRP_ASSERT(width % c->align == 0);
+
+ // if it can't possibly fit, bail immediately
+ if (width > c->width || height > c->height) {
+ fr.prev_link = NULL;
+ fr.x = fr.y = 0;
+ return fr;
+ }
+
+ node = c->active_head;
+ prev = &c->active_head;
+ while (node->x + width <= c->width) {
+ int y,waste;
+ y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
+ if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
+ // bottom left
+ if (y < best_y) {
+ best_y = y;
+ best = prev;
+ }
+ } else {
+ // best-fit
+ if (y + height <= c->height) {
+ // can only use it if it first vertically
+ if (y < best_y || (y == best_y && waste < best_waste)) {
+ best_y = y;
+ best_waste = waste;
+ best = prev;
+ }
+ }
+ }
+ prev = &node->next;
+ node = node->next;
+ }
+
+ best_x = (best == NULL) ? 0 : (*best)->x;
+
+ // if doing best-fit (BF), we also have to try aligning right edge to each node position
+ //
+ // e.g, if fitting
+ //
+ // ____________________
+ // |____________________|
+ //
+ // into
+ //
+ // | |
+ // | ____________|
+ // |____________|
+ //
+ // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
+ //
+ // This makes BF take about 2x the time
+
+ if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
+ tail = c->active_head;
+ node = c->active_head;
+ prev = &c->active_head;
+ // find first node that's admissible
+ while (tail->x < width)
+ tail = tail->next;
+ while (tail) {
+ int xpos = tail->x - width;
+ int y,waste;
+ STBRP_ASSERT(xpos >= 0);
+ // find the left position that matches this
+ while (node->next->x <= xpos) {
+ prev = &node->next;
+ node = node->next;
+ }
+ STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
+ y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
+ if (y + height <= c->height) {
+ if (y <= best_y) {
+ if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
+ best_x = xpos;
+ STBRP_ASSERT(y <= best_y);
+ best_y = y;
+ best_waste = waste;
+ best = prev;
+ }
+ }
+ }
+ tail = tail->next;
+ }
+ }
+
+ fr.prev_link = best;
+ fr.x = best_x;
+ fr.y = best_y;
+ return fr;
+}
+
+static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
+{
+ // find best position according to heuristic
+ stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
+ stbrp_node *node, *cur;
+
+ // bail if:
+ // 1. it failed
+ // 2. the best node doesn't fit (we don't always check this)
+ // 3. we're out of memory
+ if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
+ res.prev_link = NULL;
+ return res;
+ }
+
+ // on success, create new node
+ node = context->free_head;
+ node->x = (stbrp_coord) res.x;
+ node->y = (stbrp_coord) (res.y + height);
+
+ context->free_head = node->next;
+
+ // insert the new node into the right starting point, and
+ // let 'cur' point to the remaining nodes needing to be
+ // stiched back in
+
+ cur = *res.prev_link;
+ if (cur->x < res.x) {
+ // preserve the existing one, so start testing with the next one
+ stbrp_node *next = cur->next;
+ cur->next = node;
+ cur = next;
+ } else {
+ *res.prev_link = node;
+ }
+
+ // from here, traverse cur and free the nodes, until we get to one
+ // that shouldn't be freed
+ while (cur->next && cur->next->x <= res.x + width) {
+ stbrp_node *next = cur->next;
+ // move the current node to the free list
+ cur->next = context->free_head;
+ context->free_head = cur;
+ cur = next;
+ }
+
+ // stitch the list back in
+ node->next = cur;
+
+ if (cur->x < res.x + width)
+ cur->x = (stbrp_coord) (res.x + width);
+
+#ifdef _DEBUG
+ cur = context->active_head;
+ while (cur->x < context->width) {
+ STBRP_ASSERT(cur->x < cur->next->x);
+ cur = cur->next;
+ }
+ STBRP_ASSERT(cur->next == NULL);
+
+ {
+ int count=0;
+ cur = context->active_head;
+ while (cur) {
+ cur = cur->next;
+ ++count;
+ }
+ cur = context->free_head;
+ while (cur) {
+ cur = cur->next;
+ ++count;
+ }
+ STBRP_ASSERT(count == context->num_nodes+2);
+ }
+#endif
+
+ return res;
+}
+
+// [DEAR IMGUI] Added STBRP__CDECL
+static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
+{
+ const stbrp_rect *p = (const stbrp_rect *) a;
+ const stbrp_rect *q = (const stbrp_rect *) b;
+ if (p->h > q->h)
+ return -1;
+ if (p->h < q->h)
+ return 1;
+ return (p->w > q->w) ? -1 : (p->w < q->w);
+}
+
+// [DEAR IMGUI] Added STBRP__CDECL
+static int STBRP__CDECL rect_original_order(const void *a, const void *b)
+{
+ const stbrp_rect *p = (const stbrp_rect *) a;
+ const stbrp_rect *q = (const stbrp_rect *) b;
+ return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
+}
+
+#ifdef STBRP_LARGE_RECTS
+#define STBRP__MAXVAL 0xffffffff
+#else
+#define STBRP__MAXVAL 0xffff
+#endif
+
+STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
+{
+ int i, all_rects_packed = 1;
+
+ // we use the 'was_packed' field internally to allow sorting/unsorting
+ for (i=0; i < num_rects; ++i) {
+ rects[i].was_packed = i;
+ }
+
+ // sort according to heuristic
+ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
+
+ for (i=0; i < num_rects; ++i) {
+ if (rects[i].w == 0 || rects[i].h == 0) {
+ rects[i].x = rects[i].y = 0; // empty rect needs no space
+ } else {
+ stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
+ if (fr.prev_link) {
+ rects[i].x = (stbrp_coord) fr.x;
+ rects[i].y = (stbrp_coord) fr.y;
+ } else {
+ rects[i].x = rects[i].y = STBRP__MAXVAL;
+ }
+ }
+ }
+
+ // unsort
+ STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
+
+ // set was_packed flags and all_rects_packed status
+ for (i=0; i < num_rects; ++i) {
+ rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
+ if (!rects[i].was_packed)
+ all_rects_packed = 0;
+ }
+
+ // return the all_rects_packed status
+ return all_rects_packed;
+}
+#endif
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/Client/ThirdParty/imgui/imstb_textedit.h b/Client/ThirdParty/imgui/imstb_textedit.h
new file mode 100644
index 0000000..2c635b2
--- /dev/null
+++ b/Client/ThirdParty/imgui/imstb_textedit.h
@@ -0,0 +1,1449 @@
+// [DEAR IMGUI]
+// This is a slightly modified version of stb_textedit.h 1.13.
+// Those changes would need to be pushed into nothings/stb:
+// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
+// Grep for [DEAR IMGUI] to find the changes.
+
+// stb_textedit.h - v1.13 - public domain - Sean Barrett
+// Development of this library was sponsored by RAD Game Tools
+//
+// This C header file implements the guts of a multi-line text-editing
+// widget; you implement display, word-wrapping, and low-level string
+// insertion/deletion, and stb_textedit will map user inputs into
+// insertions & deletions, plus updates to the cursor position,
+// selection state, and undo state.
+//
+// It is intended for use in games and other systems that need to build
+// their own custom widgets and which do not have heavy text-editing
+// requirements (this library is not recommended for use for editing large
+// texts, as its performance does not scale and it has limited undo).
+//
+// Non-trivial behaviors are modelled after Windows text controls.
+//
+//
+// LICENSE
+//
+// See end of file for license information.
+//
+//
+// DEPENDENCIES
+//
+// Uses the C runtime function 'memmove', which you can override
+// by defining STB_TEXTEDIT_memmove before the implementation.
+// Uses no other functions. Performs no runtime allocations.
+//
+//
+// VERSION HISTORY
+//
+// 1.13 (2019-02-07) fix bug in undo size management
+// 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash
+// 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield
+// 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual
+// 1.9 (2016-08-27) customizable move-by-word
+// 1.8 (2016-04-02) better keyboard handling when mouse button is down
+// 1.7 (2015-09-13) change y range handling in case baseline is non-0
+// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
+// 1.5 (2014-09-10) add support for secondary keys for OS X
+// 1.4 (2014-08-17) fix signed/unsigned warnings
+// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
+// 1.2 (2014-05-27) fix some RAD types that had crept into the new code
+// 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE )
+// 1.0 (2012-07-26) improve documentation, initial public release
+// 0.3 (2012-02-24) bugfixes, single-line mode; insert mode
+// 0.2 (2011-11-28) fixes to undo/redo
+// 0.1 (2010-07-08) initial version
+//
+// ADDITIONAL CONTRIBUTORS
+//
+// Ulf Winklemann: move-by-word in 1.1
+// Fabian Giesen: secondary key inputs in 1.5
+// Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6
+//
+// Bugfixes:
+// Scott Graham
+// Daniel Keller
+// Omar Cornut
+// Dan Thompson
+//
+// USAGE
+//
+// This file behaves differently depending on what symbols you define
+// before including it.
+//
+//
+// Header-file mode:
+//
+// If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this,
+// it will operate in "header file" mode. In this mode, it declares a
+// single public symbol, STB_TexteditState, which encapsulates the current
+// state of a text widget (except for the string, which you will store
+// separately).
+//
+// To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a
+// primitive type that defines a single character (e.g. char, wchar_t, etc).
+//
+// To save space or increase undo-ability, you can optionally define the
+// following things that are used by the undo system:
+//
+// STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position
+// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
+// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
+//
+// If you don't define these, they are set to permissive types and
+// moderate sizes. The undo system does no memory allocations, so
+// it grows STB_TexteditState by the worst-case storage which is (in bytes):
+//
+// [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATE_COUNT
+// + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHAR_COUNT
+//
+//
+// Implementation mode:
+//
+// If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it
+// will compile the implementation of the text edit widget, depending
+// on a large number of symbols which must be defined before the include.
+//
+// The implementation is defined only as static functions. You will then
+// need to provide your own APIs in the same file which will access the
+// static functions.
+//
+// The basic concept is that you provide a "string" object which
+// behaves like an array of characters. stb_textedit uses indices to
+// refer to positions in the string, implicitly representing positions
+// in the displayed textedit. This is true for both plain text and
+// rich text; even with rich text stb_truetype interacts with your
+// code as if there was an array of all the displayed characters.
+//
+// Symbols that must be the same in header-file and implementation mode:
+//
+// STB_TEXTEDIT_CHARTYPE the character type
+// STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position
+// STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow
+// STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer
+//
+// Symbols you must define for implementation mode:
+//
+// STB_TEXTEDIT_STRING the type of object representing a string being edited,
+// typically this is a wrapper object with other data you need
+//
+// STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1))
+// STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters
+// starting from character #n (see discussion below)
+// STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character
+// to the xpos of the i+1'th char for a line of characters
+// starting at character #n (i.e. accounts for kerning
+// with previous char)
+// STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character
+// (return type is int, -1 means not valid to insert)
+// STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based
+// STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize
+// as manually wordwrapping for end-of-line positioning
+//
+// STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i
+// STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*)
+//
+// STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key
+//
+// STB_TEXTEDIT_K_LEFT keyboard input to move cursor left
+// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
+// STB_TEXTEDIT_K_UP keyboard input to move cursor up
+// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
+// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
+// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
+// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
+// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
+// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
+// STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END
+// STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor
+// STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor
+// STB_TEXTEDIT_K_UNDO keyboard input to perform undo
+// STB_TEXTEDIT_K_REDO keyboard input to perform redo
+//
+// Optional:
+// STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode
+// STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'),
+// required for default WORDLEFT/WORDRIGHT handlers
+// STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to
+// STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to
+// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT
+// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT
+// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line
+// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line
+// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
+// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
+//
+// Keyboard input must be encoded as a single integer value; e.g. a character code
+// and some bitflags that represent shift states. to simplify the interface, SHIFT must
+// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
+// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
+//
+// You can encode other things, such as CONTROL or ALT, in additional bits, and
+// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
+// my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN
+// bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit,
+// and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the
+// API below. The control keys will only match WM_KEYDOWN events because of the
+// keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN
+// bit so it only decodes WM_CHAR events.
+//
+// STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed
+// row of characters assuming they start on the i'th character--the width and
+// the height and the number of characters consumed. This allows this library
+// to traverse the entire layout incrementally. You need to compute word-wrapping
+// here.
+//
+// Each textfield keeps its own insert mode state, which is not how normal
+// applications work. To keep an app-wide insert mode, update/copy the
+// "insert_mode" field of STB_TexteditState before/after calling API functions.
+//
+// API
+//
+// void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
+//
+// void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+// void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
+// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
+//
+// Each of these functions potentially updates the string and updates the
+// state.
+//
+// initialize_state:
+// set the textedit state to a known good default state when initially
+// constructing the textedit.
+//
+// click:
+// call this with the mouse x,y on a mouse down; it will update the cursor
+// and reset the selection start/end to the cursor point. the x,y must
+// be relative to the text widget, with (0,0) being the top left.
+//
+// drag:
+// call this with the mouse x,y on a mouse drag/up; it will update the
+// cursor and the selection end point
+//
+// cut:
+// call this to delete the current selection; returns true if there was
+// one. you should FIRST copy the current selection to the system paste buffer.
+// (To copy, just copy the current selection out of the string yourself.)
+//
+// paste:
+// call this to paste text at the current cursor point or over the current
+// selection if there is one.
+//
+// key:
+// call this for keyboard inputs sent to the textfield. you can use it
+// for "key down" events or for "translated" key events. if you need to
+// do both (as in Win32), or distinguish Unicode characters from control
+// inputs, set a high bit to distinguish the two; then you can define the
+// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
+// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
+// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
+// anything other type you wante before including.
+//
+//
+// When rendering, you can read the cursor position and selection state from
+// the STB_TexteditState.
+//
+//
+// Notes:
+//
+// This is designed to be usable in IMGUI, so it allows for the possibility of
+// running in an IMGUI that has NOT cached the multi-line layout. For this
+// reason, it provides an interface that is compatible with computing the
+// layout incrementally--we try to make sure we make as few passes through
+// as possible. (For example, to locate the mouse pointer in the text, we
+// could define functions that return the X and Y positions of characters
+// and binary search Y and then X, but if we're doing dynamic layout this
+// will run the layout algorithm many times, so instead we manually search
+// forward in one pass. Similar logic applies to e.g. up-arrow and
+// down-arrow movement.)
+//
+// If it's run in a widget that *has* cached the layout, then this is less
+// efficient, but it's not horrible on modern computers. But you wouldn't
+// want to edit million-line files with it.
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////
+//// Header-file mode
+////
+////
+
+#ifndef INCLUDE_STB_TEXTEDIT_H
+#define INCLUDE_STB_TEXTEDIT_H
+
+////////////////////////////////////////////////////////////////////////
+//
+// STB_TexteditState
+//
+// Definition of STB_TexteditState which you should store
+// per-textfield; it includes cursor position, selection state,
+// and undo state.
+//
+
+#ifndef STB_TEXTEDIT_UNDOSTATECOUNT
+#define STB_TEXTEDIT_UNDOSTATECOUNT 99
+#endif
+#ifndef STB_TEXTEDIT_UNDOCHARCOUNT
+#define STB_TEXTEDIT_UNDOCHARCOUNT 999
+#endif
+#ifndef STB_TEXTEDIT_CHARTYPE
+#define STB_TEXTEDIT_CHARTYPE int
+#endif
+#ifndef STB_TEXTEDIT_POSITIONTYPE
+#define STB_TEXTEDIT_POSITIONTYPE int
+#endif
+
+typedef struct
+{
+ // private data
+ STB_TEXTEDIT_POSITIONTYPE where;
+ STB_TEXTEDIT_POSITIONTYPE insert_length;
+ STB_TEXTEDIT_POSITIONTYPE delete_length;
+ int char_storage;
+} StbUndoRecord;
+
+typedef struct
+{
+ // private data
+ StbUndoRecord undo_rec [STB_TEXTEDIT_UNDOSTATECOUNT];
+ STB_TEXTEDIT_CHARTYPE undo_char[STB_TEXTEDIT_UNDOCHARCOUNT];
+ short undo_point, redo_point;
+ int undo_char_point, redo_char_point;
+} StbUndoState;
+
+typedef struct
+{
+ /////////////////////
+ //
+ // public data
+ //
+
+ int cursor;
+ // position of the text cursor within the string
+
+ int select_start; // selection start point
+ int select_end;
+ // selection start and end point in characters; if equal, no selection.
+ // note that start may be less than or greater than end (e.g. when
+ // dragging the mouse, start is where the initial click was, and you
+ // can drag in either direction)
+
+ unsigned char insert_mode;
+ // each textfield keeps its own insert mode state. to keep an app-wide
+ // insert mode, copy this value in/out of the app state
+
+ int row_count_per_page;
+ // page size in number of row.
+ // this value MUST be set to >0 for pageup or pagedown in multilines documents.
+
+ /////////////////////
+ //
+ // private data
+ //
+ unsigned char cursor_at_end_of_line; // not implemented yet
+ unsigned char initialized;
+ unsigned char has_preferred_x;
+ unsigned char single_line;
+ unsigned char padding1, padding2, padding3;
+ float preferred_x; // this determines where the cursor up/down tries to seek to along x
+ StbUndoState undostate;
+} STB_TexteditState;
+
+
+////////////////////////////////////////////////////////////////////////
+//
+// StbTexteditRow
+//
+// Result of layout query, used by stb_textedit to determine where
+// the text in each row is.
+
+// result of layout query
+typedef struct
+{
+ float x0,x1; // starting x location, end x location (allows for align=right, etc)
+ float baseline_y_delta; // position of baseline relative to previous row's baseline
+ float ymin,ymax; // height of row above and below baseline
+ int num_chars;
+} StbTexteditRow;
+#endif //INCLUDE_STB_TEXTEDIT_H
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////
+//// Implementation mode
+////
+////
+
+
+// implementation isn't include-guarded, since it might have indirectly
+// included just the "header" portion
+#ifdef STB_TEXTEDIT_IMPLEMENTATION
+
+#ifndef STB_TEXTEDIT_memmove
+#include <string.h>
+#define STB_TEXTEDIT_memmove memmove
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Mouse input handling
+//
+
+// traverse the layout to locate the nearest character to a display position
+static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
+{
+ StbTexteditRow r;
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ float base_y = 0, prev_x;
+ int i=0, k;
+
+ r.x0 = r.x1 = 0;
+ r.ymin = r.ymax = 0;
+ r.num_chars = 0;
+
+ // search rows to find one that straddles 'y'
+ while (i < n) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, i);
+ if (r.num_chars <= 0)
+ return n;
+
+ if (i==0 && y < base_y + r.ymin)
+ return 0;
+
+ if (y < base_y + r.ymax)
+ break;
+
+ i += r.num_chars;
+ base_y += r.baseline_y_delta;
+ }
+
+ // below all text, return 'after' last character
+ if (i >= n)
+ return n;
+
+ // check if it's before the beginning of the line
+ if (x < r.x0)
+ return i;
+
+ // check if it's before the end of the line
+ if (x < r.x1) {
+ // search characters in row for one that straddles 'x'
+ prev_x = r.x0;
+ for (k=0; k < r.num_chars; ++k) {
+ float w = STB_TEXTEDIT_GETWIDTH(str, i, k);
+ if (x < prev_x+w) {
+ if (x < prev_x+w/2)
+ return k+i;
+ else
+ return k+i+1;
+ }
+ prev_x += w;
+ }
+ // shouldn't happen, but if it does, fall through to end-of-line case
+ }
+
+ // if the last character is a newline, return that. otherwise return 'after' the last character
+ if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE)
+ return i+r.num_chars-1;
+ else
+ return i+r.num_chars;
+}
+
+// API click: on mouse down, move the cursor to the clicked location, and reset the selection
+static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+{
+ // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
+ // goes off the top or bottom of the text
+ if( state->single_line )
+ {
+ StbTexteditRow r;
+ STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
+ y = r.ymin;
+ }
+
+ state->cursor = stb_text_locate_coord(str, x, y);
+ state->select_start = state->cursor;
+ state->select_end = state->cursor;
+ state->has_preferred_x = 0;
+}
+
+// API drag: on mouse drag, move the cursor and selection endpoint to the clicked location
+static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
+{
+ int p = 0;
+
+ // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse
+ // goes off the top or bottom of the text
+ if( state->single_line )
+ {
+ StbTexteditRow r;
+ STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
+ y = r.ymin;
+ }
+
+ if (state->select_start == state->select_end)
+ state->select_start = state->cursor;
+
+ p = stb_text_locate_coord(str, x, y);
+ state->cursor = state->select_end = p;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Keyboard input handling
+//
+
+// forward declarations
+static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
+static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state);
+static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length);
+static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length);
+static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length);
+
+typedef struct
+{
+ float x,y; // position of n'th character
+ float height; // height of line
+ int first_char, length; // first char of row, and length
+ int prev_first; // first char of previous row
+} StbFindState;
+
+// find the x/y location of a character, and remember info about the previous row in
+// case we get a move-up event (for page up, we'll have to rescan)
+static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_STRING *str, int n, int single_line)
+{
+ StbTexteditRow r;
+ int prev_start = 0;
+ int z = STB_TEXTEDIT_STRINGLEN(str);
+ int i=0, first;
+
+ if (n == z) {
+ // if it's at the end, then find the last line -- simpler than trying to
+ // explicitly handle this case in the regular code
+ if (single_line) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, 0);
+ find->y = 0;
+ find->first_char = 0;
+ find->length = z;
+ find->height = r.ymax - r.ymin;
+ find->x = r.x1;
+ } else {
+ find->y = 0;
+ find->x = 0;
+ find->height = 1;
+ while (i < z) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, i);
+ prev_start = i;
+ i += r.num_chars;
+ }
+ find->first_char = i;
+ find->length = 0;
+ find->prev_first = prev_start;
+ }
+ return;
+ }
+
+ // search rows to find the one that straddles character n
+ find->y = 0;
+
+ for(;;) {
+ STB_TEXTEDIT_LAYOUTROW(&r, str, i);
+ if (n < i + r.num_chars)
+ break;
+ prev_start = i;
+ i += r.num_chars;
+ find->y += r.baseline_y_delta;
+ }
+
+ find->first_char = first = i;
+ find->length = r.num_chars;
+ find->height = r.ymax - r.ymin;
+ find->prev_first = prev_start;
+
+ // now scan to find xpos
+ find->x = r.x0;
+ for (i=0; first+i < n; ++i)
+ find->x += STB_TEXTEDIT_GETWIDTH(str, first, i);
+}
+
+#define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
+
+// make the selection/cursor state valid if client altered the string
+static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ if (state->select_start > n) state->select_start = n;
+ if (state->select_end > n) state->select_end = n;
+ // if clamping forced them to be equal, move the cursor to match
+ if (state->select_start == state->select_end)
+ state->cursor = state->select_start;
+ }
+ if (state->cursor > n) state->cursor = n;
+}
+
+// delete characters while updating undo
+static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len)
+{
+ stb_text_makeundo_delete(str, state, where, len);
+ STB_TEXTEDIT_DELETECHARS(str, where, len);
+ state->has_preferred_x = 0;
+}
+
+// delete the section
+static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ stb_textedit_clamp(str, state);
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ if (state->select_start < state->select_end) {
+ stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start);
+ state->select_end = state->cursor = state->select_start;
+ } else {
+ stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end);
+ state->select_start = state->cursor = state->select_end;
+ }
+ state->has_preferred_x = 0;
+ }
+}
+
+// canoncialize the selection so start <= end
+static void stb_textedit_sortselection(STB_TexteditState *state)
+{
+ if (state->select_end < state->select_start) {
+ int temp = state->select_end;
+ state->select_end = state->select_start;
+ state->select_start = temp;
+ }
+}
+
+// move cursor to first character of selection
+static void stb_textedit_move_to_first(STB_TexteditState *state)
+{
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ stb_textedit_sortselection(state);
+ state->cursor = state->select_start;
+ state->select_end = state->select_start;
+ state->has_preferred_x = 0;
+ }
+}
+
+// move cursor to last character of selection
+static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ stb_textedit_sortselection(state);
+ stb_textedit_clamp(str, state);
+ state->cursor = state->select_end;
+ state->select_start = state->select_end;
+ state->has_preferred_x = 0;
+ }
+}
+
+#ifdef STB_TEXTEDIT_IS_SPACE
+static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
+{
+ return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1;
+}
+
+#ifndef STB_TEXTEDIT_MOVEWORDLEFT
+static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str, int c )
+{
+ --c; // always move at least one character
+ while( c >= 0 && !is_word_boundary( str, c ) )
+ --c;
+
+ if( c < 0 )
+ c = 0;
+
+ return c;
+}
+#define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous
+#endif
+
+#ifndef STB_TEXTEDIT_MOVEWORDRIGHT
+static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int c )
+{
+ const int len = STB_TEXTEDIT_STRINGLEN(str);
+ ++c; // always move at least one character
+ while( c < len && !is_word_boundary( str, c ) )
+ ++c;
+
+ if( c > len )
+ c = len;
+
+ return c;
+}
+#define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next
+#endif
+
+#endif
+
+// update selection and cursor to match each other
+static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
+{
+ if (!STB_TEXT_HAS_SELECTION(state))
+ state->select_start = state->select_end = state->cursor;
+ else
+ state->cursor = state->select_end;
+}
+
+// API cut: delete selection
+static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ if (STB_TEXT_HAS_SELECTION(state)) {
+ stb_textedit_delete_selection(str,state); // implicitly clamps
+ state->has_preferred_x = 0;
+ return 1;
+ }
+ return 0;
+}
+
+// API paste: replace existing selection with passed-in text
+static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
+{
+ // if there's a selection, the paste should delete it
+ stb_textedit_clamp(str, state);
+ stb_textedit_delete_selection(str,state);
+ // try to insert the characters
+ if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
+ stb_text_makeundo_insert(state, state->cursor, len);
+ state->cursor += len;
+ state->has_preferred_x = 0;
+ return 1;
+ }
+ // [DEAR IMGUI]
+ //// remove the undo since we didn't actually insert the characters
+ //if (state->undostate.undo_point)
+ // --state->undostate.undo_point;
+ // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details)
+ return 0;
+}
+
+#ifndef STB_TEXTEDIT_KEYTYPE
+#define STB_TEXTEDIT_KEYTYPE int
+#endif
+
+// API key: process a keyboard input
+static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
+{
+retry:
+ switch (key) {
+ default: {
+ int c = STB_TEXTEDIT_KEYTOTEXT(key);
+ if (c > 0) {
+ STB_TEXTEDIT_CHARTYPE ch = (STB_TEXTEDIT_CHARTYPE) c;
+
+ // can't add newline in single-line mode
+ if (c == '\n' && state->single_line)
+ break;
+
+ if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
+ stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
+ STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
+ if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
+ ++state->cursor;
+ state->has_preferred_x = 0;
+ }
+ } else {
+ stb_textedit_delete_selection(str,state); // implicitly clamps
+ if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
+ stb_text_makeundo_insert(state, state->cursor, 1);
+ ++state->cursor;
+ state->has_preferred_x = 0;
+ }
+ }
+ }
+ break;
+ }
+
+#ifdef STB_TEXTEDIT_K_INSERT
+ case STB_TEXTEDIT_K_INSERT:
+ state->insert_mode = !state->insert_mode;
+ break;
+#endif
+
+ case STB_TEXTEDIT_K_UNDO:
+ stb_text_undo(str, state);
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_REDO:
+ stb_text_redo(str, state);
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_LEFT:
+ // if currently there's a selection, move cursor to start of selection
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_first(state);
+ else
+ if (state->cursor > 0)
+ --state->cursor;
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_RIGHT:
+ // if currently there's a selection, move cursor to end of selection
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_last(str, state);
+ else
+ ++state->cursor;
+ stb_textedit_clamp(str, state);
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_clamp(str, state);
+ stb_textedit_prep_selection_at_cursor(state);
+ // move selection left
+ if (state->select_end > 0)
+ --state->select_end;
+ state->cursor = state->select_end;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_MOVEWORDLEFT
+ case STB_TEXTEDIT_K_WORDLEFT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_first(state);
+ else {
+ state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
+ stb_textedit_clamp( str, state );
+ }
+ break;
+
+ case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT:
+ if( !STB_TEXT_HAS_SELECTION( state ) )
+ stb_textedit_prep_selection_at_cursor(state);
+
+ state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor);
+ state->select_end = state->cursor;
+
+ stb_textedit_clamp( str, state );
+ break;
+#endif
+
+#ifdef STB_TEXTEDIT_MOVEWORDRIGHT
+ case STB_TEXTEDIT_K_WORDRIGHT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_last(str, state);
+ else {
+ state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
+ stb_textedit_clamp( str, state );
+ }
+ break;
+
+ case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT:
+ if( !STB_TEXT_HAS_SELECTION( state ) )
+ stb_textedit_prep_selection_at_cursor(state);
+
+ state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor);
+ state->select_end = state->cursor;
+
+ stb_textedit_clamp( str, state );
+ break;
+#endif
+
+ case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_prep_selection_at_cursor(state);
+ // move selection right
+ ++state->select_end;
+ stb_textedit_clamp(str, state);
+ state->cursor = state->select_end;
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_DOWN:
+ case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
+ case STB_TEXTEDIT_K_PGDOWN:
+ case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
+ StbFindState find;
+ StbTexteditRow row;
+ int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
+ int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
+ int row_count = is_page ? state->row_count_per_page : 1;
+
+ if (!is_page && state->single_line) {
+ // on windows, up&down in single-line behave like left&right
+ key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
+ goto retry;
+ }
+
+ if (sel)
+ stb_textedit_prep_selection_at_cursor(state);
+ else if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_last(str, state);
+
+ // compute current position of cursor point
+ stb_textedit_clamp(str, state);
+ stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
+
+ for (j = 0; j < row_count; ++j) {
+ float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
+ int start = find.first_char + find.length;
+
+ if (find.length == 0)
+ break;
+
+ // [DEAR IMGUI]
+ // going down while being on the last line shouldn't bring us to that line end
+ if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
+ break;
+
+ // now find character position down a row
+ state->cursor = start;
+ STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
+ x = row.x0;
+ for (i=0; i < row.num_chars; ++i) {
+ float dx = STB_TEXTEDIT_GETWIDTH(str, start, i);
+ #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
+ if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
+ break;
+ #endif
+ x += dx;
+ if (x > goal_x)
+ break;
+ ++state->cursor;
+ }
+ stb_textedit_clamp(str, state);
+
+ state->has_preferred_x = 1;
+ state->preferred_x = goal_x;
+
+ if (sel)
+ state->select_end = state->cursor;
+
+ // go to next line
+ find.first_char = find.first_char + find.length;
+ find.length = row.num_chars;
+ }
+ break;
+ }
+
+ case STB_TEXTEDIT_K_UP:
+ case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
+ case STB_TEXTEDIT_K_PGUP:
+ case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
+ StbFindState find;
+ StbTexteditRow row;
+ int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
+ int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
+ int row_count = is_page ? state->row_count_per_page : 1;
+
+ if (!is_page && state->single_line) {
+ // on windows, up&down become left&right
+ key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
+ goto retry;
+ }
+
+ if (sel)
+ stb_textedit_prep_selection_at_cursor(state);
+ else if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_move_to_first(state);
+
+ // compute current position of cursor point
+ stb_textedit_clamp(str, state);
+ stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
+
+ for (j = 0; j < row_count; ++j) {
+ float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
+
+ // can only go up if there's a previous row
+ if (find.prev_first == find.first_char)
+ break;
+
+ // now find character position up a row
+ state->cursor = find.prev_first;
+ STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
+ x = row.x0;
+ for (i=0; i < row.num_chars; ++i) {
+ float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i);
+ #ifdef STB_TEXTEDIT_GETWIDTH_NEWLINE
+ if (dx == STB_TEXTEDIT_GETWIDTH_NEWLINE)
+ break;
+ #endif
+ x += dx;
+ if (x > goal_x)
+ break;
+ ++state->cursor;
+ }
+ stb_textedit_clamp(str, state);
+
+ state->has_preferred_x = 1;
+ state->preferred_x = goal_x;
+
+ if (sel)
+ state->select_end = state->cursor;
+
+ // go to previous line
+ // (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
+ prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
+ while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
+ --prev_scan;
+ find.first_char = find.prev_first;
+ find.prev_first = prev_scan;
+ }
+ break;
+ }
+
+ case STB_TEXTEDIT_K_DELETE:
+ case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_delete_selection(str, state);
+ else {
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ if (state->cursor < n)
+ stb_textedit_delete(str, state, state->cursor, 1);
+ }
+ state->has_preferred_x = 0;
+ break;
+
+ case STB_TEXTEDIT_K_BACKSPACE:
+ case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT:
+ if (STB_TEXT_HAS_SELECTION(state))
+ stb_textedit_delete_selection(str, state);
+ else {
+ stb_textedit_clamp(str, state);
+ if (state->cursor > 0) {
+ stb_textedit_delete(str, state, state->cursor-1, 1);
+ --state->cursor;
+ }
+ }
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTSTART2
+ case STB_TEXTEDIT_K_TEXTSTART2:
+#endif
+ case STB_TEXTEDIT_K_TEXTSTART:
+ state->cursor = state->select_start = state->select_end = 0;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTEND2
+ case STB_TEXTEDIT_K_TEXTEND2:
+#endif
+ case STB_TEXTEDIT_K_TEXTEND:
+ state->cursor = STB_TEXTEDIT_STRINGLEN(str);
+ state->select_start = state->select_end = 0;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTSTART2
+ case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_prep_selection_at_cursor(state);
+ state->cursor = state->select_end = 0;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_TEXTEND2
+ case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_prep_selection_at_cursor(state);
+ state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
+ state->has_preferred_x = 0;
+ break;
+
+
+#ifdef STB_TEXTEDIT_K_LINESTART2
+ case STB_TEXTEDIT_K_LINESTART2:
+#endif
+ case STB_TEXTEDIT_K_LINESTART:
+ stb_textedit_clamp(str, state);
+ stb_textedit_move_to_first(state);
+ if (state->single_line)
+ state->cursor = 0;
+ else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
+ --state->cursor;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_LINEEND2
+ case STB_TEXTEDIT_K_LINEEND2:
+#endif
+ case STB_TEXTEDIT_K_LINEEND: {
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ stb_textedit_clamp(str, state);
+ stb_textedit_move_to_first(state);
+ if (state->single_line)
+ state->cursor = n;
+ else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
+ ++state->cursor;
+ state->has_preferred_x = 0;
+ break;
+ }
+
+#ifdef STB_TEXTEDIT_K_LINESTART2
+ case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT:
+ stb_textedit_clamp(str, state);
+ stb_textedit_prep_selection_at_cursor(state);
+ if (state->single_line)
+ state->cursor = 0;
+ else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE)
+ --state->cursor;
+ state->select_end = state->cursor;
+ state->has_preferred_x = 0;
+ break;
+
+#ifdef STB_TEXTEDIT_K_LINEEND2
+ case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
+#endif
+ case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
+ int n = STB_TEXTEDIT_STRINGLEN(str);
+ stb_textedit_clamp(str, state);
+ stb_textedit_prep_selection_at_cursor(state);
+ if (state->single_line)
+ state->cursor = n;
+ else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE)
+ ++state->cursor;
+ state->select_end = state->cursor;
+ state->has_preferred_x = 0;
+ break;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Undo processing
+//
+// @OPTIMIZE: the undo/redo buffer should be circular
+
+static void stb_textedit_flush_redo(StbUndoState *state)
+{
+ state->redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
+ state->redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
+}
+
+// discard the oldest entry in the undo list
+static void stb_textedit_discard_undo(StbUndoState *state)
+{
+ if (state->undo_point > 0) {
+ // if the 0th undo state has characters, clean those up
+ if (state->undo_rec[0].char_storage >= 0) {
+ int n = state->undo_rec[0].insert_length, i;
+ // delete n characters from all other records
+ state->undo_char_point -= n;
+ STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
+ for (i=0; i < state->undo_point; ++i)
+ if (state->undo_rec[i].char_storage >= 0)
+ state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it
+ }
+ --state->undo_point;
+ STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
+ }
+}
+
+// discard the oldest entry in the redo list--it's bad if this
+// ever happens, but because undo & redo have to store the actual
+// characters in different cases, the redo character buffer can
+// fill up even though the undo buffer didn't
+static void stb_textedit_discard_redo(StbUndoState *state)
+{
+ int k = STB_TEXTEDIT_UNDOSTATECOUNT-1;
+
+ if (state->redo_point <= k) {
+ // if the k'th undo state has characters, clean those up
+ if (state->undo_rec[k].char_storage >= 0) {
+ int n = state->undo_rec[k].insert_length, i;
+ // move the remaining redo character data to the end of the buffer
+ state->redo_char_point += n;
+ STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
+ // adjust the position of all the other records to account for above memmove
+ for (i=state->redo_point; i < k; ++i)
+ if (state->undo_rec[i].char_storage >= 0)
+ state->undo_rec[i].char_storage += n;
+ }
+ // now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
+ // [DEAR IMGUI]
+ size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
+ const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
+ const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
+ IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin);
+ IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end);
+ STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size);
+
+ // now move redo_point to point to the new one
+ ++state->redo_point;
+ }
+}
+
+static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)
+{
+ // any time we create a new undo record, we discard redo
+ stb_textedit_flush_redo(state);
+
+ // if we have no free records, we have to make room, by sliding the
+ // existing records down
+ if (state->undo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
+ stb_textedit_discard_undo(state);
+
+ // if the characters to store won't possibly fit in the buffer, we can't undo
+ if (numchars > STB_TEXTEDIT_UNDOCHARCOUNT) {
+ state->undo_point = 0;
+ state->undo_char_point = 0;
+ return NULL;
+ }
+
+ // if we don't have enough free characters in the buffer, we have to make room
+ while (state->undo_char_point + numchars > STB_TEXTEDIT_UNDOCHARCOUNT)
+ stb_textedit_discard_undo(state);
+
+ return &state->undo_rec[state->undo_point++];
+}
+
+static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len)
+{
+ StbUndoRecord *r = stb_text_create_undo_record(state, insert_len);
+ if (r == NULL)
+ return NULL;
+
+ r->where = pos;
+ r->insert_length = (STB_TEXTEDIT_POSITIONTYPE) insert_len;
+ r->delete_length = (STB_TEXTEDIT_POSITIONTYPE) delete_len;
+
+ if (insert_len == 0) {
+ r->char_storage = -1;
+ return NULL;
+ } else {
+ r->char_storage = state->undo_char_point;
+ state->undo_char_point += insert_len;
+ return &state->undo_char[r->char_storage];
+ }
+}
+
+static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ StbUndoState *s = &state->undostate;
+ StbUndoRecord u, *r;
+ if (s->undo_point == 0)
+ return;
+
+ // we need to do two things: apply the undo record, and create a redo record
+ u = s->undo_rec[s->undo_point-1];
+ r = &s->undo_rec[s->redo_point-1];
+ r->char_storage = -1;
+
+ r->insert_length = u.delete_length;
+ r->delete_length = u.insert_length;
+ r->where = u.where;
+
+ if (u.delete_length) {
+ // if the undo record says to delete characters, then the redo record will
+ // need to re-insert the characters that get deleted, so we need to store
+ // them.
+
+ // there are three cases:
+ // there's enough room to store the characters
+ // characters stored for *redoing* don't leave room for redo
+ // characters stored for *undoing* don't leave room for redo
+ // if the last is true, we have to bail
+
+ if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
+ // the undo records take up too much character space; there's no space to store the redo characters
+ r->insert_length = 0;
+ } else {
+ int i;
+
+ // there's definitely room to store the characters eventually
+ while (s->undo_char_point + u.delete_length > s->redo_char_point) {
+ // should never happen:
+ if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
+ return;
+ // there's currently not enough room, so discard a redo record
+ stb_textedit_discard_redo(s);
+ }
+ r = &s->undo_rec[s->redo_point-1];
+
+ r->char_storage = s->redo_char_point - u.delete_length;
+ s->redo_char_point = s->redo_char_point - u.delete_length;
+
+ // now save the characters
+ for (i=0; i < u.delete_length; ++i)
+ s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);
+ }
+
+ // now we can carry out the deletion
+ STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
+ }
+
+ // check type of recorded action:
+ if (u.insert_length) {
+ // easy case: was a deletion, so we need to insert n characters
+ STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
+ s->undo_char_point -= u.insert_length;
+ }
+
+ state->cursor = u.where + u.insert_length;
+
+ s->undo_point--;
+ s->redo_point--;
+}
+
+static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
+{
+ StbUndoState *s = &state->undostate;
+ StbUndoRecord *u, r;
+ if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
+ return;
+
+ // we need to do two things: apply the redo record, and create an undo record
+ u = &s->undo_rec[s->undo_point];
+ r = s->undo_rec[s->redo_point];
+
+ // we KNOW there must be room for the undo record, because the redo record
+ // was derived from an undo record
+
+ u->delete_length = r.insert_length;
+ u->insert_length = r.delete_length;
+ u->where = r.where;
+ u->char_storage = -1;
+
+ if (r.delete_length) {
+ // the redo record requires us to delete characters, so the undo record
+ // needs to store the characters
+
+ if (s->undo_char_point + u->insert_length > s->redo_char_point) {
+ u->insert_length = 0;
+ u->delete_length = 0;
+ } else {
+ int i;
+ u->char_storage = s->undo_char_point;
+ s->undo_char_point = s->undo_char_point + u->insert_length;
+
+ // now save the characters
+ for (i=0; i < u->insert_length; ++i)
+ s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i);
+ }
+
+ STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length);
+ }
+
+ if (r.insert_length) {
+ // easy case: need to insert n characters
+ STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length);
+ s->redo_char_point += r.insert_length;
+ }
+
+ state->cursor = r.where + r.insert_length;
+
+ s->undo_point++;
+ s->redo_point++;
+}
+
+static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length)
+{
+ stb_text_createundo(&state->undostate, where, 0, length);
+}
+
+static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length)
+{
+ int i;
+ STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0);
+ if (p) {
+ for (i=0; i < length; ++i)
+ p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
+ }
+}
+
+static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length)
+{
+ int i;
+ STB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length);
+ if (p) {
+ for (i=0; i < old_length; ++i)
+ p[i] = STB_TEXTEDIT_GETCHAR(str, where+i);
+ }
+}
+
+// reset the state to default
+static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line)
+{
+ state->undostate.undo_point = 0;
+ state->undostate.undo_char_point = 0;
+ state->undostate.redo_point = STB_TEXTEDIT_UNDOSTATECOUNT;
+ state->undostate.redo_char_point = STB_TEXTEDIT_UNDOCHARCOUNT;
+ state->select_end = state->select_start = 0;
+ state->cursor = 0;
+ state->has_preferred_x = 0;
+ state->preferred_x = 0;
+ state->cursor_at_end_of_line = 0;
+ state->initialized = 1;
+ state->single_line = (unsigned char) is_single_line;
+ state->insert_mode = 0;
+ state->row_count_per_page = 0;
+}
+
+// API initialize
+static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line)
+{
+ stb_textedit_clear_state(state, is_single_line);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+
+static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len)
+{
+ return stb_textedit_paste_internal(str, state, (STB_TEXTEDIT_CHARTYPE *) ctext, len);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif//STB_TEXTEDIT_IMPLEMENTATION
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/Client/ThirdParty/imgui/imstb_truetype.h b/Client/ThirdParty/imgui/imstb_truetype.h
new file mode 100644
index 0000000..48c2026
--- /dev/null
+++ b/Client/ThirdParty/imgui/imstb_truetype.h
@@ -0,0 +1,4903 @@
+// [DEAR IMGUI]
+// This is a slightly modified version of stb_truetype.h 1.20.
+// Mostly fixing for compiler and static analyzer warnings.
+// Grep for [DEAR IMGUI] to find the changes.
+
+// stb_truetype.h - v1.20 - public domain
+// authored from 2009-2016 by Sean Barrett / RAD Game Tools
+//
+// This library processes TrueType files:
+// parse files
+// extract glyph metrics
+// extract glyph shapes
+// render glyphs to one-channel bitmaps with antialiasing (box filter)
+// render glyphs to one-channel SDF bitmaps (signed-distance field/function)
+//
+// Todo:
+// non-MS cmaps
+// crashproof on bad data
+// hinting? (no longer patented)
+// cleartype-style AA?
+// optimize: use simple memory allocator for intermediates
+// optimize: build edge-list directly from curves
+// optimize: rasterize directly from curves?
+//
+// ADDITIONAL CONTRIBUTORS
+//
+// Mikko Mononen: compound shape support, more cmap formats
+// Tor Andersson: kerning, subpixel rendering
+// Dougall Johnson: OpenType / Type 2 font handling
+// Daniel Ribeiro Maciel: basic GPOS-based kerning
+//
+// Misc other:
+// Ryan Gordon
+// Simon Glass
+// github:IntellectualKitty
+// Imanol Celaya
+// Daniel Ribeiro Maciel
+//
+// Bug/warning reports/fixes:
+// "Zer" on mollyrocket Fabian "ryg" Giesen
+// Cass Everitt Martins Mozeiko
+// stoiko (Haemimont Games) Cap Petschulat
+// Brian Hook Omar Cornut
+// Walter van Niftrik github:aloucks
+// David Gow Peter LaValle
+// David Given Sergey Popov
+// Ivan-Assen Ivanov Giumo X. Clanjor
+// Anthony Pesch Higor Euripedes
+// Johan Duparc Thomas Fields
+// Hou Qiming Derek Vinyard
+// Rob Loach Cort Stratton
+// Kenney Phillis Jr. github:oyvindjam
+// Brian Costabile github:vassvik
+//
+// VERSION HISTORY
+//
+// 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics()
+// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod
+// 1.18 (2018-01-29) add missing function
+// 1.17 (2017-07-23) make more arguments const; doc fix
+// 1.16 (2017-07-12) SDF support
+// 1.15 (2017-03-03) make more arguments const
+// 1.14 (2017-01-16) num-fonts-in-TTC function
+// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
+// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
+// 1.11 (2016-04-02) fix unused-variable warning
+// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
+// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
+// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
+// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
+// variant PackFontRanges to pack and render in separate phases;
+// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
+// fixed an assert() bug in the new rasterizer
+// replace assert() with STBTT_assert() in new rasterizer
+//
+// Full history can be found at the end of this file.
+//
+// LICENSE
+//
+// See end of file for license information.
+//
+// USAGE
+//
+// Include this file in whatever places need to refer to it. In ONE C/C++
+// file, write:
+// #define STB_TRUETYPE_IMPLEMENTATION
+// before the #include of this file. This expands out the actual
+// implementation into that C/C++ file.
+//
+// To make the implementation private to the file that generates the implementation,
+// #define STBTT_STATIC
+//
+// Simple 3D API (don't ship this, but it's fine for tools and quick start)
+// stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture
+// stbtt_GetBakedQuad() -- compute quad to draw for a given char
+//
+// Improved 3D API (more shippable):
+// #include "stb_rect_pack.h" -- optional, but you really want it
+// stbtt_PackBegin()
+// stbtt_PackSetOversampling() -- for improved quality on small fonts
+// stbtt_PackFontRanges() -- pack and renders
+// stbtt_PackEnd()
+// stbtt_GetPackedQuad()
+//
+// "Load" a font file from a memory buffer (you have to keep the buffer loaded)
+// stbtt_InitFont()
+// stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections
+// stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections
+//
+// Render a unicode codepoint to a bitmap
+// stbtt_GetCodepointBitmap() -- allocates and returns a bitmap
+// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
+// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
+//
+// Character advance/positioning
+// stbtt_GetCodepointHMetrics()
+// stbtt_GetFontVMetrics()
+// stbtt_GetFontVMetricsOS2()
+// stbtt_GetCodepointKernAdvance()
+//
+// Starting with version 1.06, the rasterizer was replaced with a new,
+// faster and generally-more-precise rasterizer. The new rasterizer more
+// accurately measures pixel coverage for anti-aliasing, except in the case
+// where multiple shapes overlap, in which case it overestimates the AA pixel
+// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If
+// this turns out to be a problem, you can re-enable the old rasterizer with
+// #define STBTT_RASTERIZER_VERSION 1
+// which will incur about a 15% speed hit.
+//
+// ADDITIONAL DOCUMENTATION
+//
+// Immediately after this block comment are a series of sample programs.
+//
+// After the sample programs is the "header file" section. This section
+// includes documentation for each API function.
+//
+// Some important concepts to understand to use this library:
+//
+// Codepoint
+// Characters are defined by unicode codepoints, e.g. 65 is
+// uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is
+// the hiragana for "ma".
+//
+// Glyph
+// A visual character shape (every codepoint is rendered as
+// some glyph)
+//
+// Glyph index
+// A font-specific integer ID representing a glyph
+//
+// Baseline
+// Glyph shapes are defined relative to a baseline, which is the
+// bottom of uppercase characters. Characters extend both above
+// and below the baseline.
+//
+// Current Point
+// As you draw text to the screen, you keep track of a "current point"
+// which is the origin of each character. The current point's vertical
+// position is the baseline. Even "baked fonts" use this model.
+//
+// Vertical Font Metrics
+// The vertical qualities of the font, used to vertically position
+// and space the characters. See docs for stbtt_GetFontVMetrics.
+//
+// Font Size in Pixels or Points
+// The preferred interface for specifying font sizes in stb_truetype
+// is to specify how tall the font's vertical extent should be in pixels.
+// If that sounds good enough, skip the next paragraph.
+//
+// Most font APIs instead use "points", which are a common typographic
+// measurement for describing font size, defined as 72 points per inch.
+// stb_truetype provides a point API for compatibility. However, true
+// "per inch" conventions don't make much sense on computer displays
+// since different monitors have different number of pixels per
+// inch. For example, Windows traditionally uses a convention that
+// there are 96 pixels per inch, thus making 'inch' measurements have
+// nothing to do with inches, and thus effectively defining a point to
+// be 1.333 pixels. Additionally, the TrueType font data provides
+// an explicit scale factor to scale a given font's glyphs to points,
+// but the author has observed that this scale factor is often wrong
+// for non-commercial fonts, thus making fonts scaled in points
+// according to the TrueType spec incoherently sized in practice.
+//
+// DETAILED USAGE:
+//
+// Scale:
+// Select how high you want the font to be, in points or pixels.
+// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute
+// a scale factor SF that will be used by all other functions.
+//
+// Baseline:
+// You need to select a y-coordinate that is the baseline of where
+// your text will appear. Call GetFontBoundingBox to get the baseline-relative
+// bounding box for all characters. SF*-y0 will be the distance in pixels
+// that the worst-case character could extend above the baseline, so if
+// you want the top edge of characters to appear at the top of the
+// screen where y=0, then you would set the baseline to SF*-y0.
+//
+// Current point:
+// Set the current point where the first character will appear. The
+// first character could extend left of the current point; this is font
+// dependent. You can either choose a current point that is the leftmost
+// point and hope, or add some padding, or check the bounding box or
+// left-side-bearing of the first character to be displayed and set
+// the current point based on that.
+//
+// Displaying a character:
+// Compute the bounding box of the character. It will contain signed values
+// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1,
+// then the character should be displayed in the rectangle from
+// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1).
+//
+// Advancing for the next character:
+// Call GlyphHMetrics, and compute 'current_point += SF * advance'.
+//
+//
+// ADVANCED USAGE
+//
+// Quality:
+//
+// - Use the functions with Subpixel at the end to allow your characters
+// to have subpixel positioning. Since the font is anti-aliased, not
+// hinted, this is very import for quality. (This is not possible with
+// baked fonts.)
+//
+// - Kerning is now supported, and if you're supporting subpixel rendering
+// then kerning is worth using to give your text a polished look.
+//
+// Performance:
+//
+// - Convert Unicode codepoints to glyph indexes and operate on the glyphs;
+// if you don't do this, stb_truetype is forced to do the conversion on
+// every call.
+//
+// - There are a lot of memory allocations. We should modify it to take
+// a temp buffer and allocate from the temp buffer (without freeing),
+// should help performance a lot.
+//
+// NOTES
+//
+// The system uses the raw data found in the .ttf file without changing it
+// and without building auxiliary data structures. This is a bit inefficient
+// on little-endian systems (the data is big-endian), but assuming you're
+// caching the bitmaps or glyph shapes this shouldn't be a big deal.
+//
+// It appears to be very hard to programmatically determine what font a
+// given file is in a general way. I provide an API for this, but I don't
+// recommend it.
+//
+//
+// SOURCE STATISTICS (based on v0.6c, 2050 LOC)
+//
+// Documentation & header file 520 LOC \___ 660 LOC documentation
+// Sample code 140 LOC /
+// Truetype parsing 620 LOC ---- 620 LOC TrueType
+// Software rasterization 240 LOC \.
+// Curve tessellation 120 LOC \__ 550 LOC Bitmap creation
+// Bitmap management 100 LOC /
+// Baked bitmap interface 70 LOC /
+// Font name matching & access 150 LOC ---- 150
+// C runtime library abstraction 60 LOC ---- 60
+//
+//
+// PERFORMANCE MEASUREMENTS FOR 1.06:
+//
+// 32-bit 64-bit
+// Previous release: 8.83 s 7.68 s
+// Pool allocations: 7.72 s 6.34 s
+// Inline sort : 6.54 s 5.65 s
+// New rasterizer : 5.63 s 5.00 s
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+////
+//// SAMPLE PROGRAMS
+////
+//
+// Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless
+//
+#if 0
+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
+#include "stb_truetype.h"
+
+unsigned char ttf_buffer[1<<20];
+unsigned char temp_bitmap[512*512];
+
+stbtt_bakedchar cdata[96]; // ASCII 32..126 is 95 glyphs
+GLuint ftex;
+
+void my_stbtt_initfont(void)
+{
+ fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb"));
+ stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); // no guarantee this fits!
+ // can free ttf_buffer at this point
+ glGenTextures(1, &ftex);
+ glBindTexture(GL_TEXTURE_2D, ftex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
+ // can free temp_bitmap at this point
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+}
+
+void my_stbtt_print(float x, float y, char *text)
+{
+ // assume orthographic projection with units = screen pixels, origin at top left
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, ftex);
+ glBegin(GL_QUADS);
+ while (*text) {
+ if (*text >= 32 && *text < 128) {
+ stbtt_aligned_quad q;
+ stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9
+ glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y0);
+ glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y0);
+ glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y1);
+ glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y1);
+ }
+ ++text;
+ }
+ glEnd();
+}
+#endif
+//
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Complete program (this compiles): get a single bitmap, print as ASCII art
+//
+#if 0
+#include <stdio.h>
+#define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation
+#include "stb_truetype.h"
+
+char ttf_buffer[1<<25];
+
+int main(int argc, char **argv)
+{
+ stbtt_fontinfo font;
+ unsigned char *bitmap;
+ int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20);
+
+ fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb"));
+
+ stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0));
+ bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0);
+
+ for (j=0; j < h; ++j) {
+ for (i=0; i < w; ++i)
+ putchar(" .:ioVM@"[bitmap[j*w+i]>>5]);
+ putchar('\n');
+ }
+ return 0;
+}
+#endif
+//
+// Output:
+//
+// .ii.
+// @@@@@@.
+// V@Mio@@o
+// :i. V@V
+// :oM@@M
+// :@@@MM@M
+// @@o o@M
+// :@@. M@M
+// @@@o@@@@
+// :M@@V:@@.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// Complete program: print "Hello World!" banner, with bugs
+//
+#if 0
+char buffer[24<<20];
+unsigned char screen[20][79];
+
+int main(int arg, char **argv)
+{
+ stbtt_fontinfo font;
+ int i,j,ascent,baseline,ch=0;
+ float scale, xpos=2; // leave a little padding in case the character extends left
+ char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness
+
+ fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
+ stbtt_InitFont(&font, buffer, 0);
+
+ scale = stbtt_ScaleForPixelHeight(&font, 15);
+ stbtt_GetFontVMetrics(&font, &ascent,0,0);
+ baseline = (int) (ascent*scale);
+
+ while (text[ch]) {
+ int advance,lsb,x0,y0,x1,y1;
+ float x_shift = xpos - (float) floor(xpos);
+ stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb);
+ stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1);
+ stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]);
+ // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong
+ // because this API is really for baking character bitmaps into textures. if you want to render
+ // a sequence of characters, you really need to render each bitmap to a temp buffer, then
+ // "alpha blend" that into the working buffer
+ xpos += (advance * scale);
+ if (text[ch+1])
+ xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]);
+ ++ch;
+ }
+
+ for (j=0; j < 20; ++j) {
+ for (i=0; i < 78; ++i)
+ putchar(" .:ioVM@"[screen[j][i]>>5]);
+ putchar('\n');
+ }
+
+ return 0;
+}
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+////
+//// INTEGRATION WITH YOUR CODEBASE
+////
+//// The following sections allow you to supply alternate definitions
+//// of C library functions used by stb_truetype, e.g. if you don't
+//// link with the C runtime library.
+
+#ifdef STB_TRUETYPE_IMPLEMENTATION
+ // #define your own (u)stbtt_int8/16/32 before including to override this
+ #ifndef stbtt_uint8
+ typedef unsigned char stbtt_uint8;
+ typedef signed char stbtt_int8;
+ typedef unsigned short stbtt_uint16;
+ typedef signed short stbtt_int16;
+ typedef unsigned int stbtt_uint32;
+ typedef signed int stbtt_int32;
+ #endif
+
+ typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1];
+ typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1];
+
+ // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h
+ #ifndef STBTT_ifloor
+ #include <math.h>
+ #define STBTT_ifloor(x) ((int) floor(x))
+ #define STBTT_iceil(x) ((int) ceil(x))
+ #endif
+
+ #ifndef STBTT_sqrt
+ #include <math.h>
+ #define STBTT_sqrt(x) sqrt(x)
+ #define STBTT_pow(x,y) pow(x,y)
+ #endif
+
+ #ifndef STBTT_fmod
+ #include <math.h>
+ #define STBTT_fmod(x,y) fmod(x,y)
+ #endif
+
+ #ifndef STBTT_cos
+ #include <math.h>
+ #define STBTT_cos(x) cos(x)
+ #define STBTT_acos(x) acos(x)
+ #endif
+
+ #ifndef STBTT_fabs
+ #include <math.h>
+ #define STBTT_fabs(x) fabs(x)
+ #endif
+
+ // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
+ #ifndef STBTT_malloc
+ #include <stdlib.h>
+ #define STBTT_malloc(x,u) ((void)(u),malloc(x))
+ #define STBTT_free(x,u) ((void)(u),free(x))
+ #endif
+
+ #ifndef STBTT_assert
+ #include <assert.h>
+ #define STBTT_assert(x) assert(x)
+ #endif
+
+ #ifndef STBTT_strlen
+ #include <string.h>
+ #define STBTT_strlen(x) strlen(x)
+ #endif
+
+ #ifndef STBTT_memcpy
+ #include <string.h>
+ #define STBTT_memcpy memcpy
+ #define STBTT_memset memset
+ #endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+////
+//// INTERFACE
+////
+////
+
+#ifndef __STB_INCLUDE_STB_TRUETYPE_H__
+#define __STB_INCLUDE_STB_TRUETYPE_H__
+
+#ifdef STBTT_STATIC
+#define STBTT_DEF static
+#else
+#define STBTT_DEF extern
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// private structure
+typedef struct
+{
+ unsigned char *data;
+ int cursor;
+ int size;
+} stbtt__buf;
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// TEXTURE BAKING API
+//
+// If you use this API, you only have to call two functions ever.
+//
+
+typedef struct
+{
+ unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
+ float xoff,yoff,xadvance;
+} stbtt_bakedchar;
+
+STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
+ float pixel_height, // height of font in pixels
+ unsigned char *pixels, int pw, int ph, // bitmap to be filled in
+ int first_char, int num_chars, // characters to bake
+ stbtt_bakedchar *chardata); // you allocate this, it's num_chars long
+// if return is positive, the first unused row of the bitmap
+// if return is negative, returns the negative of the number of characters that fit
+// if return is 0, no characters fit and no rows were used
+// This uses a very crappy packing.
+
+typedef struct
+{
+ float x0,y0,s0,t0; // top-left
+ float x1,y1,s1,t1; // bottom-right
+} stbtt_aligned_quad;
+
+STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above
+ int char_index, // character to display
+ float *xpos, float *ypos, // pointers to current position in screen pixel space
+ stbtt_aligned_quad *q, // output: quad to draw
+ int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier
+// Call GetBakedQuad with char_index = 'character - first_char', and it
+// creates the quad you need to draw and advances the current position.
+//
+// The coordinate system used assumes y increases downwards.
+//
+// Characters will extend both above and below the current position;
+// see discussion of "BASELINE" above.
+//
+// It's inefficient; you might want to c&p it and optimize it.
+
+STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap);
+// Query the font vertical metrics without having to create a font first.
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// NEW TEXTURE BAKING API
+//
+// This provides options for packing multiple fonts into one atlas, not
+// perfectly but better than nothing.
+
+typedef struct
+{
+ unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap
+ float xoff,yoff,xadvance;
+ float xoff2,yoff2;
+} stbtt_packedchar;
+
+typedef struct stbtt_pack_context stbtt_pack_context;
+typedef struct stbtt_fontinfo stbtt_fontinfo;
+#ifndef STB_RECT_PACK_VERSION
+typedef struct stbrp_rect stbrp_rect;
+#endif
+
+STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context);
+// Initializes a packing context stored in the passed-in stbtt_pack_context.
+// Future calls using this context will pack characters into the bitmap passed
+// in here: a 1-channel bitmap that is width * height. stride_in_bytes is
+// the distance from one row to the next (or 0 to mean they are packed tightly
+// together). "padding" is the amount of padding to leave between each
+// character (normally you want '1' for bitmaps you'll use as textures with
+// bilinear filtering).
+//
+// Returns 0 on failure, 1 on success.
+
+STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc);
+// Cleans up the packing context and frees all memory.
+
+#define STBTT_POINT_SIZE(x) (-(x))
+
+STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
+ int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range);
+// Creates character bitmaps from the font_index'th font found in fontdata (use
+// font_index=0 if you don't know what that is). It creates num_chars_in_range
+// bitmaps for characters with unicode values starting at first_unicode_char_in_range
+// and increasing. Data for how to render them is stored in chardata_for_range;
+// pass these to stbtt_GetPackedQuad to get back renderable quads.
+//
+// font_size is the full height of the character from ascender to descender,
+// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
+// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
+// and pass that result as 'font_size':
+// ..., 20 , ... // font max minus min y is 20 pixels tall
+// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
+
+typedef struct
+{
+ float font_size;
+ int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint
+ int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints
+ int num_chars;
+ stbtt_packedchar *chardata_for_range; // output
+ unsigned char h_oversample, v_oversample; // don't set these, they're used internally
+} stbtt_pack_range;
+
+STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges);
+// Creates character bitmaps from multiple ranges of characters stored in
+// ranges. This will usually create a better-packed bitmap than multiple
+// calls to stbtt_PackFontRange. Note that you can call this multiple
+// times within a single PackBegin/PackEnd.
+
+STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample);
+// Oversampling a font increases the quality by allowing higher-quality subpixel
+// positioning, and is especially valuable at smaller text sizes.
+//
+// This function sets the amount of oversampling for all following calls to
+// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given
+// pack context. The default (no oversampling) is achieved by h_oversample=1
+// and v_oversample=1. The total number of pixels required is
+// h_oversample*v_oversample larger than the default; for example, 2x2
+// oversampling requires 4x the storage of 1x1. For best results, render
+// oversampled textures with bilinear filtering. Look at the readme in
+// stb/tests/oversample for information about oversampled fonts
+//
+// To use with PackFontRangesGather etc., you must set it before calls
+// call to PackFontRangesGatherRects.
+
+STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip);
+// If skip != 0, this tells stb_truetype to skip any codepoints for which
+// there is no corresponding glyph. If skip=0, which is the default, then
+// codepoints without a glyph recived the font's "missing character" glyph,
+// typically an empty box by convention.
+
+STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above
+ int char_index, // character to display
+ float *xpos, float *ypos, // pointers to current position in screen pixel space
+ stbtt_aligned_quad *q, // output: quad to draw
+ int align_to_integer);
+
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
+STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects);
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects);
+// Calling these functions in sequence is roughly equivalent to calling
+// stbtt_PackFontRanges(). If you more control over the packing of multiple
+// fonts, or if you want to pack custom data into a font texture, take a look
+// at the source to of stbtt_PackFontRanges() and create a custom version
+// using these functions, e.g. call GatherRects multiple times,
+// building up a single array of rects, then call PackRects once,
+// then call RenderIntoRects repeatedly. This may result in a
+// better packing than calling PackFontRanges multiple times
+// (or it may not).
+
+// this is an opaque structure that you shouldn't mess with which holds
+// all the context needed from PackBegin to PackEnd.
+struct stbtt_pack_context {
+ void *user_allocator_context;
+ void *pack_info;
+ int width;
+ int height;
+ int stride_in_bytes;
+ int padding;
+ int skip_missing;
+ unsigned int h_oversample, v_oversample;
+ unsigned char *pixels;
+ void *nodes;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// FONT LOADING
+//
+//
+
+STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data);
+// This function will determine the number of fonts in a font file. TrueType
+// collection (.ttc) files may contain multiple fonts, while TrueType font
+// (.ttf) files only contain one font. The number of fonts can be used for
+// indexing with the previous function where the index is between zero and one
+// less than the total fonts. If an error occurs, -1 is returned.
+
+STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
+// Each .ttf/.ttc file may have more than one font. Each font has a sequential
+// index number starting from 0. Call this function to get the font offset for
+// a given index; it returns -1 if the index is out of range. A regular .ttf
+// file will only define one font and it always be at offset 0, so it will
+// return '0' for index 0, and -1 for all other indices.
+
+// The following structure is defined publicly so you can declare one on
+// the stack or as a global or etc, but you should treat it as opaque.
+struct stbtt_fontinfo
+{
+ void * userdata;
+ unsigned char * data; // pointer to .ttf file
+ int fontstart; // offset of start of font
+
+ int numGlyphs; // number of glyphs, needed for range checking
+
+ int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf
+ int index_map; // a cmap mapping for our chosen character encoding
+ int indexToLocFormat; // format needed to map from glyph index to glyph
+
+ stbtt__buf cff; // cff font data
+ stbtt__buf charstrings; // the charstring index
+ stbtt__buf gsubrs; // global charstring subroutines index
+ stbtt__buf subrs; // private charstring subroutines index
+ stbtt__buf fontdicts; // array of font dicts
+ stbtt__buf fdselect; // map from glyph to fontdict
+};
+
+STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
+// Given an offset into the file that defines a font, this function builds
+// the necessary cached info for the rest of the system. You must allocate
+// the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't
+// need to do anything special to free it, because the contents are pure
+// value data with no additional data structures. Returns 0 on failure.
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// CHARACTER TO GLYPH-INDEX CONVERSIOn
+
+STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint);
+// If you're going to perform multiple operations on the same character
+// and you want a speed-up, call this function with the character you're
+// going to process, then use glyph-based functions instead of the
+// codepoint-based functions.
+// Returns 0 if the character codepoint is not defined in the font.
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// CHARACTER PROPERTIES
+//
+
+STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels);
+// computes a scale factor to produce a font whose "height" is 'pixels' tall.
+// Height is measured as the distance from the highest ascender to the lowest
+// descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics
+// and computing:
+// scale = pixels / (ascent - descent)
+// so if you prefer to measure height by the ascent only, use a similar calculation.
+
+STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels);
+// computes a scale factor to produce a font whose EM size is mapped to
+// 'pixels' tall. This is probably what traditional APIs compute, but
+// I'm not positive.
+
+STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap);
+// ascent is the coordinate above the baseline the font extends; descent
+// is the coordinate below the baseline the font extends (i.e. it is typically negative)
+// lineGap is the spacing between one row's descent and the next row's ascent...
+// so you should advance the vertical position by "*ascent - *descent + *lineGap"
+// these are expressed in unscaled coordinates, so you must multiply by
+// the scale factor for a given size
+
+STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap);
+// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2
+// table (specific to MS/Windows TTF files).
+//
+// Returns 1 on success (table present), 0 on failure.
+
+STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1);
+// the bounding box around all possible characters
+
+STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing);
+// leftSideBearing is the offset from the current horizontal position to the left edge of the character
+// advanceWidth is the offset from the current horizontal position to the next horizontal position
+// these are expressed in unscaled coordinates
+
+STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2);
+// an additional amount to add to the 'advance' value between ch1 and ch2
+
+STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1);
+// Gets the bounding box of the visible part of the glyph, in unscaled coordinates
+
+STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing);
+STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2);
+STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
+// as above, but takes one or more glyph indices for greater efficiency
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// GLYPH SHAPES (you probably don't need these, but they have to go before
+// the bitmaps for C declaration-order reasons)
+//
+
+#ifndef STBTT_vmove // you can predefine these to use different values (but why?)
+ enum {
+ STBTT_vmove=1,
+ STBTT_vline,
+ STBTT_vcurve,
+ STBTT_vcubic
+ };
+#endif
+
+#ifndef stbtt_vertex // you can predefine this to use different values
+ // (we share this with other code at RAD)
+ #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file
+ typedef struct
+ {
+ stbtt_vertex_type x,y,cx,cy,cx1,cy1;
+ unsigned char type,padding;
+ } stbtt_vertex;
+#endif
+
+STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index);
+// returns non-zero if nothing is drawn for this glyph
+
+STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices);
+STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices);
+// returns # of vertices and fills *vertices with the pointer to them
+// these are expressed in "unscaled" coordinates
+//
+// The shape is a series of contours. Each one starts with
+// a STBTT_moveto, then consists of a series of mixed
+// STBTT_lineto and STBTT_curveto segments. A lineto
+// draws a line from previous endpoint to its x,y; a curveto
+// draws a quadratic bezier from previous endpoint to
+// its x,y, using cx,cy as the bezier control point.
+
+STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices);
+// frees the data allocated above
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// BITMAP RENDERING
+//
+
+STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata);
+// frees the bitmap allocated below
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
+// allocates a large-enough single-channel 8bpp bitmap and renders the
+// specified character/glyph at the specified scale into it, with
+// antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque).
+// *width & *height are filled out with the width & height of the bitmap,
+// which is stored left-to-right, top-to-bottom.
+//
+// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
+// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
+// shift for the character
+
+STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
+// the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap
+// in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap
+// is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the
+// width and height and positioning info for it first.
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint);
+// same as stbtt_MakeCodepointBitmap, but you can specify a subpixel
+// shift for the character
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint);
+// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering
+// is performed (see stbtt_PackSetOversampling)
+
+STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
+// get the bbox of the bitmap centered around the glyph origin; so the
+// bitmap width is ix1-ix0, height is iy1-iy0, and location to place
+// the bitmap top left is (leftSideBearing*scale,iy0).
+// (Note that the bitmap uses y-increases-down, but the shape uses
+// y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.)
+
+STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
+// same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel
+// shift for the character
+
+// the following functions are equivalent to the above functions, but operate
+// on glyph indices instead of Unicode codepoints (for efficiency)
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph);
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph);
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph);
+STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1);
+STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1);
+
+
+// @TODO: don't expose this structure
+typedef struct
+{
+ int w,h,stride;
+ unsigned char *pixels;
+} stbtt__bitmap;
+
+// rasterize a shape with quadratic beziers into a bitmap
+STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
+ float flatness_in_pixels, // allowable error of curve in pixels
+ stbtt_vertex *vertices, // array of vertices defining shape
+ int num_verts, // number of vertices in above array
+ float scale_x, float scale_y, // scale applied to input vertices
+ float shift_x, float shift_y, // translation applied to input vertices
+ int x_off, int y_off, // another translation applied to input
+ int invert, // if non-zero, vertically flip shape
+ void *userdata); // context for to STBTT_MALLOC
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Signed Distance Function (or Field) rendering
+
+STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata);
+// frees the SDF bitmap allocated below
+
+STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
+STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff);
+// These functions compute a discretized SDF field for a single character, suitable for storing
+// in a single-channel texture, sampling with bilinear filtering, and testing against
+// larger than some threshold to produce scalable fonts.
+// info -- the font
+// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap
+// glyph/codepoint -- the character to generate the SDF for
+// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0),
+// which allows effects like bit outlines
+// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character)
+// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale)
+// if positive, > onedge_value is inside; if negative, < onedge_value is inside
+// width,height -- output height & width of the SDF bitmap (including padding)
+// xoff,yoff -- output origin of the character
+// return value -- a 2D array of bytes 0..255, width*height in size
+//
+// pixel_dist_scale & onedge_value are a scale & bias that allows you to make
+// optimal use of the limited 0..255 for your application, trading off precision
+// and special effects. SDF values outside the range 0..255 are clamped to 0..255.
+//
+// Example:
+// scale = stbtt_ScaleForPixelHeight(22)
+// padding = 5
+// onedge_value = 180
+// pixel_dist_scale = 180/5.0 = 36.0
+//
+// This will create an SDF bitmap in which the character is about 22 pixels
+// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled
+// shape, sample the SDF at each pixel and fill the pixel if the SDF value
+// is greater than or equal to 180/255. (You'll actually want to antialias,
+// which is beyond the scope of this example.) Additionally, you can compute
+// offset outlines (e.g. to stroke the character border inside & outside,
+// or only outside). For example, to fill outside the character up to 3 SDF
+// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above
+// choice of variables maps a range from 5 pixels outside the shape to
+// 2 pixels inside the shape to 0..255; this is intended primarily for apply
+// outside effects only (the interior range is needed to allow proper
+// antialiasing of the font at *smaller* sizes)
+//
+// The function computes the SDF analytically at each SDF pixel, not by e.g.
+// building a higher-res bitmap and approximating it. In theory the quality
+// should be as high as possible for an SDF of this size & representation, but
+// unclear if this is true in practice (perhaps building a higher-res bitmap
+// and computing from that can allow drop-out prevention).
+//
+// The algorithm has not been optimized at all, so expect it to be slow
+// if computing lots of characters or very large sizes.
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Finding the right font...
+//
+// You should really just solve this offline, keep your own tables
+// of what font is what, and don't try to get it out of the .ttf file.
+// That's because getting it out of the .ttf file is really hard, because
+// the names in the file can appear in many possible encodings, in many
+// possible languages, and e.g. if you need a case-insensitive comparison,
+// the details of that depend on the encoding & language in a complex way
+// (actually underspecified in truetype, but also gigantic).
+//
+// But you can use the provided functions in two possible ways:
+// stbtt_FindMatchingFont() will use *case-sensitive* comparisons on
+// unicode-encoded names to try to find the font you want;
+// you can run this before calling stbtt_InitFont()
+//
+// stbtt_GetFontNameString() lets you get any of the various strings
+// from the file yourself and do your own comparisons on them.
+// You have to have called stbtt_InitFont() first.
+
+
+STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags);
+// returns the offset (not index) of the font that matches, or -1 if none
+// if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold".
+// if you use any other flag, use a font name like "Arial"; this checks
+// the 'macStyle' header field; i don't know if fonts set this consistently
+#define STBTT_MACSTYLE_DONTCARE 0
+#define STBTT_MACSTYLE_BOLD 1
+#define STBTT_MACSTYLE_ITALIC 2
+#define STBTT_MACSTYLE_UNDERSCORE 4
+#define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0
+
+STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2);
+// returns 1/0 whether the first string interpreted as utf8 is identical to
+// the second string interpreted as big-endian utf16... useful for strings from next func
+
+STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID);
+// returns the string (which may be big-endian double byte, e.g. for unicode)
+// and puts the length in bytes in *length.
+//
+// some of the values for the IDs are below; for more see the truetype spec:
+// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
+// http://www.microsoft.com/typography/otspec/name.htm
+
+enum { // platformID
+ STBTT_PLATFORM_ID_UNICODE =0,
+ STBTT_PLATFORM_ID_MAC =1,
+ STBTT_PLATFORM_ID_ISO =2,
+ STBTT_PLATFORM_ID_MICROSOFT =3
+};
+
+enum { // encodingID for STBTT_PLATFORM_ID_UNICODE
+ STBTT_UNICODE_EID_UNICODE_1_0 =0,
+ STBTT_UNICODE_EID_UNICODE_1_1 =1,
+ STBTT_UNICODE_EID_ISO_10646 =2,
+ STBTT_UNICODE_EID_UNICODE_2_0_BMP=3,
+ STBTT_UNICODE_EID_UNICODE_2_0_FULL=4
+};
+
+enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT
+ STBTT_MS_EID_SYMBOL =0,
+ STBTT_MS_EID_UNICODE_BMP =1,
+ STBTT_MS_EID_SHIFTJIS =2,
+ STBTT_MS_EID_UNICODE_FULL =10
+};
+
+enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes
+ STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4,
+ STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5,
+ STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6,
+ STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7
+};
+
+enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID...
+ // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs
+ STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410,
+ STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411,
+ STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412,
+ STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419,
+ STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409,
+ STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D
+};
+
+enum { // languageID for STBTT_PLATFORM_ID_MAC
+ STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11,
+ STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23,
+ STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32,
+ STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 ,
+ STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 ,
+ STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33,
+ STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __STB_INCLUDE_STB_TRUETYPE_H__
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+////
+//// IMPLEMENTATION
+////
+////
+
+#ifdef STB_TRUETYPE_IMPLEMENTATION
+
+#ifndef STBTT_MAX_OVERSAMPLE
+#define STBTT_MAX_OVERSAMPLE 8
+#endif
+
+#if STBTT_MAX_OVERSAMPLE > 255
+#error "STBTT_MAX_OVERSAMPLE cannot be > 255"
+#endif
+
+typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1];
+
+#ifndef STBTT_RASTERIZER_VERSION
+#define STBTT_RASTERIZER_VERSION 2
+#endif
+
+#ifdef _MSC_VER
+#define STBTT__NOTUSED(v) (void)(v)
+#else
+#define STBTT__NOTUSED(v) (void)sizeof(v)
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+//
+// stbtt__buf helpers to parse data from file
+//
+
+static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
+{
+ if (b->cursor >= b->size)
+ return 0;
+ return b->data[b->cursor++];
+}
+
+static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
+{
+ if (b->cursor >= b->size)
+ return 0;
+ return b->data[b->cursor];
+}
+
+static void stbtt__buf_seek(stbtt__buf *b, int o)
+{
+ STBTT_assert(!(o > b->size || o < 0));
+ b->cursor = (o > b->size || o < 0) ? b->size : o;
+}
+
+static void stbtt__buf_skip(stbtt__buf *b, int o)
+{
+ stbtt__buf_seek(b, b->cursor + o);
+}
+
+static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
+{
+ stbtt_uint32 v = 0;
+ int i;
+ STBTT_assert(n >= 1 && n <= 4);
+ for (i = 0; i < n; i++)
+ v = (v << 8) | stbtt__buf_get8(b);
+ return v;
+}
+
+static stbtt__buf stbtt__new_buf(const void *p, size_t size)
+{
+ stbtt__buf r;
+ STBTT_assert(size < 0x40000000);
+ r.data = (stbtt_uint8*) p;
+ r.size = (int) size;
+ r.cursor = 0;
+ return r;
+}
+
+#define stbtt__buf_get16(b) stbtt__buf_get((b), 2)
+#define stbtt__buf_get32(b) stbtt__buf_get((b), 4)
+
+static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
+{
+ stbtt__buf r = stbtt__new_buf(NULL, 0);
+ if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r;
+ r.data = b->data + o;
+ r.size = s;
+ return r;
+}
+
+static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
+{
+ int count, start, offsize;
+ start = b->cursor;
+ count = stbtt__buf_get16(b);
+ if (count) {
+ offsize = stbtt__buf_get8(b);
+ STBTT_assert(offsize >= 1 && offsize <= 4);
+ stbtt__buf_skip(b, offsize * count);
+ stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1);
+ }
+ return stbtt__buf_range(b, start, b->cursor - start);
+}
+
+static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
+{
+ int b0 = stbtt__buf_get8(b);
+ if (b0 >= 32 && b0 <= 246) return b0 - 139;
+ else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108;
+ else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108;
+ else if (b0 == 28) return stbtt__buf_get16(b);
+ else if (b0 == 29) return stbtt__buf_get32(b);
+ STBTT_assert(0);
+ return 0;
+}
+
+static void stbtt__cff_skip_operand(stbtt__buf *b) {
+ int v, b0 = stbtt__buf_peek8(b);
+ STBTT_assert(b0 >= 28);
+ if (b0 == 30) {
+ stbtt__buf_skip(b, 1);
+ while (b->cursor < b->size) {
+ v = stbtt__buf_get8(b);
+ if ((v & 0xF) == 0xF || (v >> 4) == 0xF)
+ break;
+ }
+ } else {
+ stbtt__cff_int(b);
+ }
+}
+
+static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
+{
+ stbtt__buf_seek(b, 0);
+ while (b->cursor < b->size) {
+ int start = b->cursor, end, op;
+ while (stbtt__buf_peek8(b) >= 28)
+ stbtt__cff_skip_operand(b);
+ end = b->cursor;
+ op = stbtt__buf_get8(b);
+ if (op == 12) op = stbtt__buf_get8(b) | 0x100;
+ if (op == key) return stbtt__buf_range(b, start, end-start);
+ }
+ return stbtt__buf_range(b, 0, 0);
+}
+
+static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out)
+{
+ int i;
+ stbtt__buf operands = stbtt__dict_get(b, key);
+ for (i = 0; i < outcount && operands.cursor < operands.size; i++)
+ out[i] = stbtt__cff_int(&operands);
+}
+
+static int stbtt__cff_index_count(stbtt__buf *b)
+{
+ stbtt__buf_seek(b, 0);
+ return stbtt__buf_get16(b);
+}
+
+static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
+{
+ int count, offsize, start, end;
+ stbtt__buf_seek(&b, 0);
+ count = stbtt__buf_get16(&b);
+ offsize = stbtt__buf_get8(&b);
+ STBTT_assert(i >= 0 && i < count);
+ STBTT_assert(offsize >= 1 && offsize <= 4);
+ stbtt__buf_skip(&b, i*offsize);
+ start = stbtt__buf_get(&b, offsize);
+ end = stbtt__buf_get(&b, offsize);
+ return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// accessors to parse data from file
+//
+
+// on platforms that don't allow misaligned reads, if we want to allow
+// truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE
+
+#define ttBYTE(p) (* (stbtt_uint8 *) (p))
+#define ttCHAR(p) (* (stbtt_int8 *) (p))
+#define ttFixed(p) ttLONG(p)
+
+static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
+static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
+static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
+static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; }
+
+#define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
+#define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3])
+
+static int stbtt__isfont(stbtt_uint8 *font)
+{
+ // check the version number
+ if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1
+ if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this!
+ if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF
+ if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0
+ if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts
+ return 0;
+}
+
+// @OPTIMIZE: binary search
+static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag)
+{
+ stbtt_int32 num_tables = ttUSHORT(data+fontstart+4);
+ stbtt_uint32 tabledir = fontstart + 12;
+ stbtt_int32 i;
+ for (i=0; i < num_tables; ++i) {
+ stbtt_uint32 loc = tabledir + 16*i;
+ if (stbtt_tag(data+loc+0, tag))
+ return ttULONG(data+loc+8);
+ }
+ return 0;
+}
+
+static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index)
+{
+ // if it's just a font, there's only one valid index
+ if (stbtt__isfont(font_collection))
+ return index == 0 ? 0 : -1;
+
+ // check if it's a TTC
+ if (stbtt_tag(font_collection, "ttcf")) {
+ // version 1?
+ if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
+ stbtt_int32 n = ttLONG(font_collection+8);
+ if (index >= n)
+ return -1;
+ return ttULONG(font_collection+12+index*4);
+ }
+ }
+ return -1;
+}
+
+static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
+{
+ // if it's just a font, there's only one valid font
+ if (stbtt__isfont(font_collection))
+ return 1;
+
+ // check if it's a TTC
+ if (stbtt_tag(font_collection, "ttcf")) {
+ // version 1?
+ if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) {
+ return ttLONG(font_collection+8);
+ }
+ }
+ return 0;
+}
+
+static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
+{
+ stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 };
+ stbtt__buf pdict;
+ stbtt__dict_get_ints(&fontdict, 18, 2, private_loc);
+ if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0);
+ pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]);
+ stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff);
+ if (!subrsoff) return stbtt__new_buf(NULL, 0);
+ stbtt__buf_seek(&cff, private_loc[1]+subrsoff);
+ return stbtt__cff_get_index(&cff);
+}
+
+static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart)
+{
+ stbtt_uint32 cmap, t;
+ stbtt_int32 i,numTables;
+
+ info->data = data;
+ info->fontstart = fontstart;
+ info->cff = stbtt__new_buf(NULL, 0);
+
+ cmap = stbtt__find_table(data, fontstart, "cmap"); // required
+ info->loca = stbtt__find_table(data, fontstart, "loca"); // required
+ info->head = stbtt__find_table(data, fontstart, "head"); // required
+ info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required
+ info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required
+ info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required
+ info->kern = stbtt__find_table(data, fontstart, "kern"); // not required
+ info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required
+
+ if (!cmap || !info->head || !info->hhea || !info->hmtx)
+ return 0;
+ if (info->glyf) {
+ // required for truetype
+ if (!info->loca) return 0;
+ } else {
+ // initialization for CFF / Type2 fonts (OTF)
+ stbtt__buf b, topdict, topdictidx;
+ stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0;
+ stbtt_uint32 cff;
+
+ cff = stbtt__find_table(data, fontstart, "CFF ");
+ if (!cff) return 0;
+
+ info->fontdicts = stbtt__new_buf(NULL, 0);
+ info->fdselect = stbtt__new_buf(NULL, 0);
+
+ // @TODO this should use size from table (not 512MB)
+ info->cff = stbtt__new_buf(data+cff, 512*1024*1024);
+ b = info->cff;
+
+ // read the header
+ stbtt__buf_skip(&b, 2);
+ stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize
+
+ // @TODO the name INDEX could list multiple fonts,
+ // but we just use the first one.
+ stbtt__cff_get_index(&b); // name INDEX
+ topdictidx = stbtt__cff_get_index(&b);
+ topdict = stbtt__cff_index_get(topdictidx, 0);
+ stbtt__cff_get_index(&b); // string INDEX
+ info->gsubrs = stbtt__cff_get_index(&b);
+
+ stbtt__dict_get_ints(&topdict, 17, 1, &charstrings);
+ stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype);
+ stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff);
+ stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff);
+ info->subrs = stbtt__get_subrs(b, topdict);
+
+ // we only support Type 2 charstrings
+ if (cstype != 2) return 0;
+ if (charstrings == 0) return 0;
+
+ if (fdarrayoff) {
+ // looks like a CID font
+ if (!fdselectoff) return 0;
+ stbtt__buf_seek(&b, fdarrayoff);
+ info->fontdicts = stbtt__cff_get_index(&b);
+ info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff);
+ }
+
+ stbtt__buf_seek(&b, charstrings);
+ info->charstrings = stbtt__cff_get_index(&b);
+ }
+
+ t = stbtt__find_table(data, fontstart, "maxp");
+ if (t)
+ info->numGlyphs = ttUSHORT(data+t+4);
+ else
+ info->numGlyphs = 0xffff;
+
+ // find a cmap encoding table we understand *now* to avoid searching
+ // later. (todo: could make this installable)
+ // the same regardless of glyph.
+ numTables = ttUSHORT(data + cmap + 2);
+ info->index_map = 0;
+ for (i=0; i < numTables; ++i) {
+ stbtt_uint32 encoding_record = cmap + 4 + 8 * i;
+ // find an encoding we understand:
+ switch(ttUSHORT(data+encoding_record)) {
+ case STBTT_PLATFORM_ID_MICROSOFT:
+ switch (ttUSHORT(data+encoding_record+2)) {
+ case STBTT_MS_EID_UNICODE_BMP:
+ case STBTT_MS_EID_UNICODE_FULL:
+ // MS/Unicode
+ info->index_map = cmap + ttULONG(data+encoding_record+4);
+ break;
+ }
+ break;
+ case STBTT_PLATFORM_ID_UNICODE:
+ // Mac/iOS has these
+ // all the encodingIDs are unicode, so we don't bother to check it
+ info->index_map = cmap + ttULONG(data+encoding_record+4);
+ break;
+ }
+ }
+ if (info->index_map == 0)
+ return 0;
+
+ info->indexToLocFormat = ttUSHORT(data+info->head + 50);
+ return 1;
+}
+
+STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint)
+{
+ stbtt_uint8 *data = info->data;
+ stbtt_uint32 index_map = info->index_map;
+
+ stbtt_uint16 format = ttUSHORT(data + index_map + 0);
+ if (format == 0) { // apple byte encoding
+ stbtt_int32 bytes = ttUSHORT(data + index_map + 2);
+ if (unicode_codepoint < bytes-6)
+ return ttBYTE(data + index_map + 6 + unicode_codepoint);
+ return 0;
+ } else if (format == 6) {
+ stbtt_uint32 first = ttUSHORT(data + index_map + 6);
+ stbtt_uint32 count = ttUSHORT(data + index_map + 8);
+ if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count)
+ return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2);
+ return 0;
+ } else if (format == 2) {
+ STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean
+ return 0;
+ } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges
+ stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1;
+ stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1;
+ stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10);
+ stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1;
+
+ // do a binary search of the segments
+ stbtt_uint32 endCount = index_map + 14;
+ stbtt_uint32 search = endCount;
+
+ if (unicode_codepoint > 0xffff)
+ return 0;
+
+ // they lie from endCount .. endCount + segCount
+ // but searchRange is the nearest power of two, so...
+ if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2))
+ search += rangeShift*2;
+
+ // now decrement to bias correctly to find smallest
+ search -= 2;
+ while (entrySelector) {
+ stbtt_uint16 end;
+ searchRange >>= 1;
+ end = ttUSHORT(data + search + searchRange*2);
+ if (unicode_codepoint > end)
+ search += searchRange*2;
+ --entrySelector;
+ }
+ search += 2;
+
+ {
+ stbtt_uint16 offset, start;
+ stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1);
+
+ STBTT_assert(unicode_codepoint <= ttUSHORT(data + endCount + 2*item));
+ start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
+ if (unicode_codepoint < start)
+ return 0;
+
+ offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
+ if (offset == 0)
+ return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
+
+ return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
+ }
+ } else if (format == 12 || format == 13) {
+ stbtt_uint32 ngroups = ttULONG(data+index_map+12);
+ stbtt_int32 low,high;
+ low = 0; high = (stbtt_int32)ngroups;
+ // Binary search the right group.
+ while (low < high) {
+ stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high
+ stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12);
+ stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4);
+ if ((stbtt_uint32) unicode_codepoint < start_char)
+ high = mid;
+ else if ((stbtt_uint32) unicode_codepoint > end_char)
+ low = mid+1;
+ else {
+ stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8);
+ if (format == 12)
+ return start_glyph + unicode_codepoint-start_char;
+ else // format == 13
+ return start_glyph;
+ }
+ }
+ return 0; // not found
+ }
+ // @TODO
+ STBTT_assert(0);
+ return 0;
+}
+
+STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices)
+{
+ return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices);
+}
+
+static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy)
+{
+ v->type = type;
+ v->x = (stbtt_int16) x;
+ v->y = (stbtt_int16) y;
+ v->cx = (stbtt_int16) cx;
+ v->cy = (stbtt_int16) cy;
+}
+
+static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index)
+{
+ int g1,g2;
+
+ STBTT_assert(!info->cff.size);
+
+ if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range
+ if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format
+
+ if (info->indexToLocFormat == 0) {
+ g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
+ g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
+ } else {
+ g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4);
+ g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4);
+ }
+
+ return g1==g2 ? -1 : g1; // if length is 0, return -1
+}
+
+static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1);
+
+STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
+{
+ if (info->cff.size) {
+ stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1);
+ } else {
+ int g = stbtt__GetGlyfOffset(info, glyph_index);
+ if (g < 0) return 0;
+
+ if (x0) *x0 = ttSHORT(info->data + g + 2);
+ if (y0) *y0 = ttSHORT(info->data + g + 4);
+ if (x1) *x1 = ttSHORT(info->data + g + 6);
+ if (y1) *y1 = ttSHORT(info->data + g + 8);
+ }
+ return 1;
+}
+
+STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1)
+{
+ return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1);
+}
+
+STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index)
+{
+ stbtt_int16 numberOfContours;
+ int g;
+ if (info->cff.size)
+ return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0;
+ g = stbtt__GetGlyfOffset(info, glyph_index);
+ if (g < 0) return 1;
+ numberOfContours = ttSHORT(info->data + g);
+ return numberOfContours == 0;
+}
+
+static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off,
+ stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy)
+{
+ if (start_off) {
+ if (was_off)
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy);
+ } else {
+ if (was_off)
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy);
+ else
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0);
+ }
+ return num_vertices;
+}
+
+static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
+{
+ stbtt_int16 numberOfContours;
+ stbtt_uint8 *endPtsOfContours;
+ stbtt_uint8 *data = info->data;
+ stbtt_vertex *vertices=0;
+ int num_vertices=0;
+ int g = stbtt__GetGlyfOffset(info, glyph_index);
+
+ *pvertices = NULL;
+
+ if (g < 0) return 0;
+
+ numberOfContours = ttSHORT(data + g);
+
+ if (numberOfContours > 0) {
+ stbtt_uint8 flags=0,flagcount;
+ stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
+ stbtt_int32 x,y,cx,cy,sx,sy, scx,scy;
+ stbtt_uint8 *points;
+ endPtsOfContours = (data + g + 10);
+ ins = ttUSHORT(data + g + 10 + numberOfContours * 2);
+ points = data + g + 10 + numberOfContours * 2 + 2 + ins;
+
+ n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2);
+
+ m = n + 2*numberOfContours; // a loose bound on how many vertices we might need
+ vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata);
+ if (vertices == 0)
+ return 0;
+
+ next_move = 0;
+ flagcount=0;
+
+ // in first pass, we load uninterpreted data into the allocated array
+ // above, shifted to the end of the array so we won't overwrite it when
+ // we create our final data starting from the front
+
+ off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated
+
+ // first load flags
+
+ for (i=0; i < n; ++i) {
+ if (flagcount == 0) {
+ flags = *points++;
+ if (flags & 8)
+ flagcount = *points++;
+ } else
+ --flagcount;
+ vertices[off+i].type = flags;
+ }
+
+ // now load x coordinates
+ x=0;
+ for (i=0; i < n; ++i) {
+ flags = vertices[off+i].type;
+ if (flags & 2) {
+ stbtt_int16 dx = *points++;
+ x += (flags & 16) ? dx : -dx; // ???
+ } else {
+ if (!(flags & 16)) {
+ x = x + (stbtt_int16) (points[0]*256 + points[1]);
+ points += 2;
+ }
+ }
+ vertices[off+i].x = (stbtt_int16) x;
+ }
+
+ // now load y coordinates
+ y=0;
+ for (i=0; i < n; ++i) {
+ flags = vertices[off+i].type;
+ if (flags & 4) {
+ stbtt_int16 dy = *points++;
+ y += (flags & 32) ? dy : -dy; // ???
+ } else {
+ if (!(flags & 32)) {
+ y = y + (stbtt_int16) (points[0]*256 + points[1]);
+ points += 2;
+ }
+ }
+ vertices[off+i].y = (stbtt_int16) y;
+ }
+
+ // now convert them to our format
+ num_vertices=0;
+ sx = sy = cx = cy = scx = scy = 0;
+ for (i=0; i < n; ++i) {
+ flags = vertices[off+i].type;
+ x = (stbtt_int16) vertices[off+i].x;
+ y = (stbtt_int16) vertices[off+i].y;
+
+ if (next_move == i) {
+ if (i != 0)
+ num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
+
+ // now start the new one
+ start_off = !(flags & 1);
+ if (start_off) {
+ // if we start off with an off-curve point, then when we need to find a point on the curve
+ // where we can start, and we need to save some state for when we wraparound.
+ scx = x;
+ scy = y;
+ if (!(vertices[off+i+1].type & 1)) {
+ // next point is also a curve point, so interpolate an on-point curve
+ sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1;
+ sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1;
+ } else {
+ // otherwise just use the next point as our start point
+ sx = (stbtt_int32) vertices[off+i+1].x;
+ sy = (stbtt_int32) vertices[off+i+1].y;
+ ++i; // we're using point i+1 as the starting point, so skip it
+ }
+ } else {
+ sx = x;
+ sy = y;
+ }
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0);
+ was_off = 0;
+ next_move = 1 + ttUSHORT(endPtsOfContours+j*2);
+ ++j;
+ } else {
+ if (!(flags & 1)) { // if it's a curve
+ if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
+ cx = x;
+ cy = y;
+ was_off = 1;
+ } else {
+ if (was_off)
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy);
+ else
+ stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0);
+ was_off = 0;
+ }
+ }
+ }
+ num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
+ } else if (numberOfContours == -1) {
+ // Compound shapes.
+ int more = 1;
+ stbtt_uint8 *comp = data + g + 10;
+ num_vertices = 0;
+ vertices = 0;
+ while (more) {
+ stbtt_uint16 flags, gidx;
+ int comp_num_verts = 0, i;
+ stbtt_vertex *comp_verts = 0, *tmp = 0;
+ float mtx[6] = {1,0,0,1,0,0}, m, n;
+
+ flags = ttSHORT(comp); comp+=2;
+ gidx = ttSHORT(comp); comp+=2;
+
+ if (flags & 2) { // XY values
+ if (flags & 1) { // shorts
+ mtx[4] = ttSHORT(comp); comp+=2;
+ mtx[5] = ttSHORT(comp); comp+=2;
+ } else {
+ mtx[4] = ttCHAR(comp); comp+=1;
+ mtx[5] = ttCHAR(comp); comp+=1;
+ }
+ }
+ else {
+ // @TODO handle matching point
+ STBTT_assert(0);
+ }
+ if (flags & (1<<3)) { // WE_HAVE_A_SCALE
+ mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[1] = mtx[2] = 0;
+ } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE
+ mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[1] = mtx[2] = 0;
+ mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
+ } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO
+ mtx[0] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[1] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[2] = ttSHORT(comp)/16384.0f; comp+=2;
+ mtx[3] = ttSHORT(comp)/16384.0f; comp+=2;
+ }
+
+ // Find transformation scales.
+ m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
+ n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
+
+ // Get indexed glyph.
+ comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts);
+ if (comp_num_verts > 0) {
+ // Transform vertices.
+ for (i = 0; i < comp_num_verts; ++i) {
+ stbtt_vertex* v = &comp_verts[i];
+ stbtt_vertex_type x,y;
+ x=v->x; y=v->y;
+ v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
+ v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
+ x=v->cx; y=v->cy;
+ v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
+ v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
+ }
+ // Append vertices.
+ tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata);
+ if (!tmp) {
+ if (vertices) STBTT_free(vertices, info->userdata);
+ if (comp_verts) STBTT_free(comp_verts, info->userdata);
+ return 0;
+ }
+ if (num_vertices > 0) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); //-V595
+ STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex));
+ if (vertices) STBTT_free(vertices, info->userdata);
+ vertices = tmp;
+ STBTT_free(comp_verts, info->userdata);
+ num_vertices += comp_num_verts;
+ }
+ // More components ?
+ more = flags & (1<<5);
+ }
+ } else if (numberOfContours < 0) {
+ // @TODO other compound variations?
+ STBTT_assert(0);
+ } else {
+ // numberOfCounters == 0, do nothing
+ }
+
+ *pvertices = vertices;
+ return num_vertices;
+}
+
+typedef struct
+{
+ int bounds;
+ int started;
+ float first_x, first_y;
+ float x, y;
+ stbtt_int32 min_x, max_x, min_y, max_y;
+
+ stbtt_vertex *pvertices;
+ int num_vertices;
+} stbtt__csctx;
+
+#define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0}
+
+static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y)
+{
+ if (x > c->max_x || !c->started) c->max_x = x;
+ if (y > c->max_y || !c->started) c->max_y = y;
+ if (x < c->min_x || !c->started) c->min_x = x;
+ if (y < c->min_y || !c->started) c->min_y = y;
+ c->started = 1;
+}
+
+static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1)
+{
+ if (c->bounds) {
+ stbtt__track_vertex(c, x, y);
+ if (type == STBTT_vcubic) {
+ stbtt__track_vertex(c, cx, cy);
+ stbtt__track_vertex(c, cx1, cy1);
+ }
+ } else {
+ stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy);
+ c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1;
+ c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1;
+ }
+ c->num_vertices++;
+}
+
+static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
+{
+ if (ctx->first_x != ctx->x || ctx->first_y != ctx->y)
+ stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0);
+}
+
+static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
+{
+ stbtt__csctx_close_shape(ctx);
+ ctx->first_x = ctx->x = ctx->x + dx;
+ ctx->first_y = ctx->y = ctx->y + dy;
+ stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
+}
+
+static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
+{
+ ctx->x += dx;
+ ctx->y += dy;
+ stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0);
+}
+
+static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3)
+{
+ float cx1 = ctx->x + dx1;
+ float cy1 = ctx->y + dy1;
+ float cx2 = cx1 + dx2;
+ float cy2 = cy1 + dy2;
+ ctx->x = cx2 + dx3;
+ ctx->y = cy2 + dy3;
+ stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2);
+}
+
+static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
+{
+ int count = stbtt__cff_index_count(&idx);
+ int bias = 107;
+ if (count >= 33900)
+ bias = 32768;
+ else if (count >= 1240)
+ bias = 1131;
+ n += bias;
+ if (n < 0 || n >= count)
+ return stbtt__new_buf(NULL, 0);
+ return stbtt__cff_index_get(idx, n);
+}
+
+static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index)
+{
+ stbtt__buf fdselect = info->fdselect;
+ int nranges, start, end, v, fmt, fdselector = -1, i;
+
+ stbtt__buf_seek(&fdselect, 0);
+ fmt = stbtt__buf_get8(&fdselect);
+ if (fmt == 0) {
+ // untested
+ stbtt__buf_skip(&fdselect, glyph_index);
+ fdselector = stbtt__buf_get8(&fdselect);
+ } else if (fmt == 3) {
+ nranges = stbtt__buf_get16(&fdselect);
+ start = stbtt__buf_get16(&fdselect);
+ for (i = 0; i < nranges; i++) {
+ v = stbtt__buf_get8(&fdselect);
+ end = stbtt__buf_get16(&fdselect);
+ if (glyph_index >= start && glyph_index < end) {
+ fdselector = v;
+ break;
+ }
+ start = end;
+ }
+ }
+ if (fdselector == -1) stbtt__new_buf(NULL, 0);
+ return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector));
+}
+
+static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c)
+{
+ int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0;
+ int has_subrs = 0, clear_stack;
+ float s[48];
+ stbtt__buf subr_stack[10], subrs = info->subrs, b;
+ float f;
+
+#define STBTT__CSERR(s) (0)
+
+ // this currently ignores the initial width value, which isn't needed if we have hmtx
+ b = stbtt__cff_index_get(info->charstrings, glyph_index);
+ while (b.cursor < b.size) {
+ i = 0;
+ clear_stack = 1;
+ b0 = stbtt__buf_get8(&b);
+ switch (b0) {
+ // @TODO implement hinting
+ case 0x13: // hintmask
+ case 0x14: // cntrmask
+ if (in_header)
+ maskbits += (sp / 2); // implicit "vstem"
+ in_header = 0;
+ stbtt__buf_skip(&b, (maskbits + 7) / 8);
+ break;
+
+ case 0x01: // hstem
+ case 0x03: // vstem
+ case 0x12: // hstemhm
+ case 0x17: // vstemhm
+ maskbits += (sp / 2);
+ break;
+
+ case 0x15: // rmoveto
+ in_header = 0;
+ if (sp < 2) return STBTT__CSERR("rmoveto stack");
+ stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]);
+ break;
+ case 0x04: // vmoveto
+ in_header = 0;
+ if (sp < 1) return STBTT__CSERR("vmoveto stack");
+ stbtt__csctx_rmove_to(c, 0, s[sp-1]);
+ break;
+ case 0x16: // hmoveto
+ in_header = 0;
+ if (sp < 1) return STBTT__CSERR("hmoveto stack");
+ stbtt__csctx_rmove_to(c, s[sp-1], 0);
+ break;
+
+ case 0x05: // rlineto
+ if (sp < 2) return STBTT__CSERR("rlineto stack");
+ for (; i + 1 < sp; i += 2)
+ stbtt__csctx_rline_to(c, s[i], s[i+1]);
+ break;
+
+ // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical
+ // starting from a different place.
+
+ case 0x07: // vlineto
+ if (sp < 1) return STBTT__CSERR("vlineto stack");
+ goto vlineto;
+ case 0x06: // hlineto
+ if (sp < 1) return STBTT__CSERR("hlineto stack");
+ for (;;) {
+ if (i >= sp) break;
+ stbtt__csctx_rline_to(c, s[i], 0);
+ i++;
+ vlineto:
+ if (i >= sp) break;
+ stbtt__csctx_rline_to(c, 0, s[i]);
+ i++;
+ }
+ break;
+
+ case 0x1F: // hvcurveto
+ if (sp < 4) return STBTT__CSERR("hvcurveto stack");
+ goto hvcurveto;
+ case 0x1E: // vhcurveto
+ if (sp < 4) return STBTT__CSERR("vhcurveto stack");
+ for (;;) {
+ if (i + 3 >= sp) break;
+ stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f);
+ i += 4;
+ hvcurveto:
+ if (i + 3 >= sp) break;
+ stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]);
+ i += 4;
+ }
+ break;
+
+ case 0x08: // rrcurveto
+ if (sp < 6) return STBTT__CSERR("rcurveline stack");
+ for (; i + 5 < sp; i += 6)
+ stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
+ break;
+
+ case 0x18: // rcurveline
+ if (sp < 8) return STBTT__CSERR("rcurveline stack");
+ for (; i + 5 < sp - 2; i += 6)
+ stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
+ if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack");
+ stbtt__csctx_rline_to(c, s[i], s[i+1]);
+ break;
+
+ case 0x19: // rlinecurve
+ if (sp < 8) return STBTT__CSERR("rlinecurve stack");
+ for (; i + 1 < sp - 6; i += 2)
+ stbtt__csctx_rline_to(c, s[i], s[i+1]);
+ if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack");
+ stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]);
+ break;
+
+ case 0x1A: // vvcurveto
+ case 0x1B: // hhcurveto
+ if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack");
+ f = 0.0;
+ if (sp & 1) { f = s[i]; i++; }
+ for (; i + 3 < sp; i += 4) {
+ if (b0 == 0x1B)
+ stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0);
+ else
+ stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]);
+ f = 0.0;
+ }
+ break;
+
+ case 0x0A: // callsubr
+ if (!has_subrs) {
+ if (info->fdselect.size)
+ subrs = stbtt__cid_get_glyph_subrs(info, glyph_index);
+ has_subrs = 1;
+ }
+ // fallthrough
+ case 0x1D: // callgsubr
+ if (sp < 1) return STBTT__CSERR("call(g|)subr stack");
+ v = (int) s[--sp];
+ if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit");
+ subr_stack[subr_stack_height++] = b;
+ b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v);
+ if (b.size == 0) return STBTT__CSERR("subr not found");
+ b.cursor = 0;
+ clear_stack = 0;
+ break;
+
+ case 0x0B: // return
+ if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr");
+ b = subr_stack[--subr_stack_height];
+ clear_stack = 0;
+ break;
+
+ case 0x0E: // endchar
+ stbtt__csctx_close_shape(c);
+ return 1;
+
+ case 0x0C: { // two-byte escape
+ float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6;
+ float dx, dy;
+ int b1 = stbtt__buf_get8(&b);
+ switch (b1) {
+ // @TODO These "flex" implementations ignore the flex-depth and resolution,
+ // and always draw beziers.
+ case 0x22: // hflex
+ if (sp < 7) return STBTT__CSERR("hflex stack");
+ dx1 = s[0];
+ dx2 = s[1];
+ dy2 = s[2];
+ dx3 = s[3];
+ dx4 = s[4];
+ dx5 = s[5];
+ dx6 = s[6];
+ stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0);
+ stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0);
+ break;
+
+ case 0x23: // flex
+ if (sp < 13) return STBTT__CSERR("flex stack");
+ dx1 = s[0];
+ dy1 = s[1];
+ dx2 = s[2];
+ dy2 = s[3];
+ dx3 = s[4];
+ dy3 = s[5];
+ dx4 = s[6];
+ dy4 = s[7];
+ dx5 = s[8];
+ dy5 = s[9];
+ dx6 = s[10];
+ dy6 = s[11];
+ //fd is s[12]
+ stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
+ stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
+ break;
+
+ case 0x24: // hflex1
+ if (sp < 9) return STBTT__CSERR("hflex1 stack");
+ dx1 = s[0];
+ dy1 = s[1];
+ dx2 = s[2];
+ dy2 = s[3];
+ dx3 = s[4];
+ dx4 = s[5];
+ dx5 = s[6];
+ dy5 = s[7];
+ dx6 = s[8];
+ stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0);
+ stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5));
+ break;
+
+ case 0x25: // flex1
+ if (sp < 11) return STBTT__CSERR("flex1 stack");
+ dx1 = s[0];
+ dy1 = s[1];
+ dx2 = s[2];
+ dy2 = s[3];
+ dx3 = s[4];
+ dy3 = s[5];
+ dx4 = s[6];
+ dy4 = s[7];
+ dx5 = s[8];
+ dy5 = s[9];
+ dx6 = dy6 = s[10];
+ dx = dx1+dx2+dx3+dx4+dx5;
+ dy = dy1+dy2+dy3+dy4+dy5;
+ if (STBTT_fabs(dx) > STBTT_fabs(dy))
+ dy6 = -dy;
+ else
+ dx6 = -dx;
+ stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3);
+ stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6);
+ break;
+
+ default:
+ return STBTT__CSERR("unimplemented");
+ }
+ } break;
+
+ default:
+ if (b0 != 255 && b0 != 28 && (b0 < 32 || b0 > 254)) //-V560
+ return STBTT__CSERR("reserved operator");
+
+ // push immediate
+ if (b0 == 255) {
+ f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000;
+ } else {
+ stbtt__buf_skip(&b, -1);
+ f = (float)(stbtt_int16)stbtt__cff_int(&b);
+ }
+ if (sp >= 48) return STBTT__CSERR("push stack overflow");
+ s[sp++] = f;
+ clear_stack = 0;
+ break;
+ }
+ if (clear_stack) sp = 0;
+ }
+ return STBTT__CSERR("no endchar");
+
+#undef STBTT__CSERR
+}
+
+static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
+{
+ // runs the charstring twice, once to count and once to output (to avoid realloc)
+ stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1);
+ stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0);
+ if (stbtt__run_charstring(info, glyph_index, &count_ctx)) {
+ *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata);
+ output_ctx.pvertices = *pvertices;
+ if (stbtt__run_charstring(info, glyph_index, &output_ctx)) {
+ STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices);
+ return output_ctx.num_vertices;
+ }
+ }
+ *pvertices = NULL;
+ return 0;
+}
+
+static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1)
+{
+ stbtt__csctx c = STBTT__CSCTX_INIT(1);
+ int r = stbtt__run_charstring(info, glyph_index, &c);
+ if (x0) *x0 = r ? c.min_x : 0;
+ if (y0) *y0 = r ? c.min_y : 0;
+ if (x1) *x1 = r ? c.max_x : 0;
+ if (y1) *y1 = r ? c.max_y : 0;
+ return r ? c.num_vertices : 0;
+}
+
+STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices)
+{
+ if (!info->cff.size)
+ return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices);
+ else
+ return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices);
+}
+
+STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing)
+{
+ stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34);
+ if (glyph_index < numOfLongHorMetrics) {
+ if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index);
+ if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
+ } else {
+ if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
+ if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
+ }
+}
+
+static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
+{
+ stbtt_uint8 *data = info->data + info->kern;
+ stbtt_uint32 needle, straw;
+ int l, r, m;
+
+ // we only look at the first table. it must be 'horizontal' and format 0.
+ if (!info->kern)
+ return 0;
+ if (ttUSHORT(data+2) < 1) // number of tables, need at least 1
+ return 0;
+ if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format
+ return 0;
+
+ l = 0;
+ r = ttUSHORT(data+10) - 1;
+ needle = glyph1 << 16 | glyph2;
+ while (l <= r) {
+ m = (l + r) >> 1;
+ straw = ttULONG(data+18+(m*6)); // note: unaligned read
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else
+ return ttSHORT(data+22+(m*6));
+ }
+ return 0;
+}
+
+static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph)
+{
+ stbtt_uint16 coverageFormat = ttUSHORT(coverageTable);
+ switch(coverageFormat) {
+ case 1: {
+ stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2);
+
+ // Binary search.
+ stbtt_int32 l=0, r=glyphCount-1, m;
+ int straw, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *glyphArray = coverageTable + 4;
+ stbtt_uint16 glyphID;
+ m = (l + r) >> 1;
+ glyphID = ttUSHORT(glyphArray + 2 * m);
+ straw = glyphID;
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else {
+ return m;
+ }
+ }
+ } break;
+
+ case 2: {
+ stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2);
+ stbtt_uint8 *rangeArray = coverageTable + 4;
+
+ // Binary search.
+ stbtt_int32 l=0, r=rangeCount-1, m;
+ int strawStart, strawEnd, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *rangeRecord;
+ m = (l + r) >> 1;
+ rangeRecord = rangeArray + 6 * m;
+ strawStart = ttUSHORT(rangeRecord);
+ strawEnd = ttUSHORT(rangeRecord + 2);
+ if (needle < strawStart)
+ r = m - 1;
+ else if (needle > strawEnd)
+ l = m + 1;
+ else {
+ stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4);
+ return startCoverageIndex + glyph - strawStart;
+ }
+ }
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ } break;
+ }
+
+ return -1;
+}
+
+static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph)
+{
+ stbtt_uint16 classDefFormat = ttUSHORT(classDefTable);
+ switch(classDefFormat)
+ {
+ case 1: {
+ stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2);
+ stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4);
+ stbtt_uint8 *classDef1ValueArray = classDefTable + 6;
+
+ if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount)
+ return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID));
+
+ // [DEAR IMGUI] Commented to fix static analyzer warning
+ //classDefTable = classDef1ValueArray + 2 * glyphCount;
+ } break;
+
+ case 2: {
+ stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2);
+ stbtt_uint8 *classRangeRecords = classDefTable + 4;
+
+ // Binary search.
+ stbtt_int32 l=0, r=classRangeCount-1, m;
+ int strawStart, strawEnd, needle=glyph;
+ while (l <= r) {
+ stbtt_uint8 *classRangeRecord;
+ m = (l + r) >> 1;
+ classRangeRecord = classRangeRecords + 6 * m;
+ strawStart = ttUSHORT(classRangeRecord);
+ strawEnd = ttUSHORT(classRangeRecord + 2);
+ if (needle < strawStart)
+ r = m - 1;
+ else if (needle > strawEnd)
+ l = m + 1;
+ else
+ return (stbtt_int32)ttUSHORT(classRangeRecord + 4);
+ }
+
+ // [DEAR IMGUI] Commented to fix static analyzer warning
+ //classDefTable = classRangeRecords + 6 * classRangeCount;
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ } break;
+ }
+
+ return -1;
+}
+
+// Define to STBTT_assert(x) if you want to break on unimplemented formats.
+#define STBTT_GPOS_TODO_assert(x)
+
+static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2)
+{
+ stbtt_uint16 lookupListOffset;
+ stbtt_uint8 *lookupList;
+ stbtt_uint16 lookupCount;
+ stbtt_uint8 *data;
+ stbtt_int32 i;
+
+ if (!info->gpos) return 0;
+
+ data = info->data + info->gpos;
+
+ if (ttUSHORT(data+0) != 1) return 0; // Major version 1
+ if (ttUSHORT(data+2) != 0) return 0; // Minor version 0
+
+ lookupListOffset = ttUSHORT(data+8);
+ lookupList = data + lookupListOffset;
+ lookupCount = ttUSHORT(lookupList);
+
+ for (i=0; i<lookupCount; ++i) {
+ stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i);
+ stbtt_uint8 *lookupTable = lookupList + lookupOffset;
+
+ stbtt_uint16 lookupType = ttUSHORT(lookupTable);
+ stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4);
+ stbtt_uint8 *subTableOffsets = lookupTable + 6;
+ switch(lookupType) {
+ case 2: { // Pair Adjustment Positioning Subtable
+ stbtt_int32 sti;
+ for (sti=0; sti<subTableCount; sti++) {
+ stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti);
+ stbtt_uint8 *table = lookupTable + subtableOffset;
+ stbtt_uint16 posFormat = ttUSHORT(table);
+ stbtt_uint16 coverageOffset = ttUSHORT(table + 2);
+ stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1);
+ if (coverageIndex == -1) continue;
+
+ switch (posFormat) {
+ case 1: {
+ stbtt_int32 l, r, m;
+ int straw, needle;
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+ stbtt_int32 valueRecordPairSizeInBytes = 2;
+ stbtt_uint16 pairSetCount = ttUSHORT(table + 8);
+ stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex);
+ stbtt_uint8 *pairValueTable = table + pairPosOffset;
+ stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable);
+ stbtt_uint8 *pairValueArray = pairValueTable + 2;
+ // TODO: Support more formats.
+ STBTT_GPOS_TODO_assert(valueFormat1 == 4);
+ if (valueFormat1 != 4) return 0;
+ STBTT_GPOS_TODO_assert(valueFormat2 == 0);
+ if (valueFormat2 != 0) return 0;
+
+ STBTT_assert(coverageIndex < pairSetCount);
+ STBTT__NOTUSED(pairSetCount);
+
+ needle=glyph2;
+ r=pairValueCount-1;
+ l=0;
+
+ // Binary search.
+ while (l <= r) {
+ stbtt_uint16 secondGlyph;
+ stbtt_uint8 *pairValue;
+ m = (l + r) >> 1;
+ pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m;
+ secondGlyph = ttUSHORT(pairValue);
+ straw = secondGlyph;
+ if (needle < straw)
+ r = m - 1;
+ else if (needle > straw)
+ l = m + 1;
+ else {
+ stbtt_int16 xAdvance = ttSHORT(pairValue + 2);
+ return xAdvance;
+ }
+ }
+ } break;
+
+ case 2: {
+ stbtt_uint16 valueFormat1 = ttUSHORT(table + 4);
+ stbtt_uint16 valueFormat2 = ttUSHORT(table + 6);
+
+ stbtt_uint16 classDef1Offset = ttUSHORT(table + 8);
+ stbtt_uint16 classDef2Offset = ttUSHORT(table + 10);
+ int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1);
+ int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2);
+
+ stbtt_uint16 class1Count = ttUSHORT(table + 12);
+ stbtt_uint16 class2Count = ttUSHORT(table + 14);
+ STBTT_assert(glyph1class < class1Count);
+ STBTT_assert(glyph2class < class2Count);
+
+ // TODO: Support more formats.
+ STBTT_GPOS_TODO_assert(valueFormat1 == 4);
+ if (valueFormat1 != 4) return 0;
+ STBTT_GPOS_TODO_assert(valueFormat2 == 0);
+ if (valueFormat2 != 0) return 0;
+
+ if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) {
+ stbtt_uint8 *class1Records = table + 16;
+ stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count);
+ stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class);
+ return xAdvance;
+ }
+ } break;
+
+ default: {
+ // There are no other cases.
+ STBTT_assert(0);
+ break;
+ } // [DEAR IMGUI] removed ;
+ }
+ }
+ break;
+ } // [DEAR IMGUI] removed ;
+
+ default:
+ // TODO: Implement other stuff.
+ break;
+ }
+ }
+
+ return 0;
+}
+
+STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2)
+{
+ int xAdvance = 0;
+
+ if (info->gpos)
+ xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2);
+
+ if (info->kern)
+ xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2);
+
+ return xAdvance;
+}
+
+STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2)
+{
+ if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs
+ return 0;
+ return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2));
+}
+
+STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing)
+{
+ stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing);
+}
+
+STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap)
+{
+ if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4);
+ if (descent) *descent = ttSHORT(info->data+info->hhea + 6);
+ if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8);
+}
+
+STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap)
+{
+ int tab = stbtt__find_table(info->data, info->fontstart, "OS/2");
+ if (!tab)
+ return 0;
+ if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68);
+ if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70);
+ if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72);
+ return 1;
+}
+
+STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1)
+{
+ *x0 = ttSHORT(info->data + info->head + 36);
+ *y0 = ttSHORT(info->data + info->head + 38);
+ *x1 = ttSHORT(info->data + info->head + 40);
+ *y1 = ttSHORT(info->data + info->head + 42);
+}
+
+STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height)
+{
+ int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6);
+ return (float) height / fheight;
+}
+
+STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels)
+{
+ int unitsPerEm = ttUSHORT(info->data + info->head + 18);
+ return pixels / unitsPerEm;
+}
+
+STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
+{
+ STBTT_free(v, info->userdata);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// antialiasing software rasterizer
+//
+
+STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
+ if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
+ // e.g. space character
+ if (ix0) *ix0 = 0;
+ if (iy0) *iy0 = 0;
+ if (ix1) *ix1 = 0;
+ if (iy1) *iy1 = 0;
+ } else {
+ // move to integral bboxes (treating pixels as little squares, what pixels get touched)?
+ if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x);
+ if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y);
+ if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x);
+ if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y);
+ }
+}
+
+STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
+}
+
+STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1);
+}
+
+STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
+{
+ stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Rasterizer
+
+typedef struct stbtt__hheap_chunk
+{
+ struct stbtt__hheap_chunk *next;
+} stbtt__hheap_chunk;
+
+typedef struct stbtt__hheap
+{
+ struct stbtt__hheap_chunk *head;
+ void *first_free;
+ int num_remaining_in_head_chunk;
+} stbtt__hheap;
+
+static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata)
+{
+ if (hh->first_free) {
+ void *p = hh->first_free;
+ hh->first_free = * (void **) p;
+ return p;
+ } else {
+ if (hh->num_remaining_in_head_chunk == 0) {
+ int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
+ stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata);
+ if (c == NULL)
+ return NULL;
+ c->next = hh->head;
+ hh->head = c;
+ hh->num_remaining_in_head_chunk = count;
+ }
+ --hh->num_remaining_in_head_chunk;
+ return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk;
+ }
+}
+
+static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
+{
+ *(void **) p = hh->first_free;
+ hh->first_free = p;
+}
+
+static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
+{
+ stbtt__hheap_chunk *c = hh->head;
+ while (c) {
+ stbtt__hheap_chunk *n = c->next;
+ STBTT_free(c, userdata);
+ c = n;
+ }
+}
+
+typedef struct stbtt__edge {
+ float x0,y0, x1,y1;
+ int invert;
+} stbtt__edge;
+
+
+typedef struct stbtt__active_edge
+{
+ struct stbtt__active_edge *next;
+ #if STBTT_RASTERIZER_VERSION==1
+ int x,dx;
+ float ey;
+ int direction;
+ #elif STBTT_RASTERIZER_VERSION==2
+ float fx,fdx,fdy;
+ float direction;
+ float sy;
+ float ey;
+ #else
+ #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+ #endif
+} stbtt__active_edge;
+
+#if STBTT_RASTERIZER_VERSION == 1
+#define STBTT_FIXSHIFT 10
+#define STBTT_FIX (1 << STBTT_FIXSHIFT)
+#define STBTT_FIXMASK (STBTT_FIX-1)
+
+static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
+{
+ stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
+ float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
+ STBTT_assert(z != NULL);
+ if (!z) return z;
+
+ // round dx down to avoid overshooting
+ if (dxdy < 0)
+ z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy);
+ else
+ z->dx = STBTT_ifloor(STBTT_FIX * dxdy);
+
+ z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount
+ z->x -= off_x * STBTT_FIX;
+
+ z->ey = e->y1;
+ z->next = 0;
+ z->direction = e->invert ? 1 : -1;
+ return z;
+}
+#elif STBTT_RASTERIZER_VERSION == 2
+static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata)
+{
+ stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
+ float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
+ STBTT_assert(z != NULL);
+ //STBTT_assert(e->y0 <= start_point);
+ if (!z) return z;
+ z->fdx = dxdy;
+ z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
+ z->fx = e->x0 + dxdy * (start_point - e->y0);
+ z->fx -= off_x;
+ z->direction = e->invert ? 1.0f : -1.0f;
+ z->sy = e->y0;
+ z->ey = e->y1;
+ z->next = 0;
+ return z;
+}
+#else
+#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#endif
+
+#if STBTT_RASTERIZER_VERSION == 1
+// note: this routine clips fills that extend off the edges... ideally this
+// wouldn't happen, but it could happen if the truetype glyph bounding boxes
+// are wrong, or if the user supplies a too-small bitmap
+static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight)
+{
+ // non-zero winding fill
+ int x0=0, w=0;
+
+ while (e) {
+ if (w == 0) {
+ // if we're currently at zero, we need to record the edge start point
+ x0 = e->x; w += e->direction;
+ } else {
+ int x1 = e->x; w += e->direction;
+ // if we went to zero, we need to draw
+ if (w == 0) {
+ int i = x0 >> STBTT_FIXSHIFT;
+ int j = x1 >> STBTT_FIXSHIFT;
+
+ if (i < len && j >= 0) {
+ if (i == j) {
+ // x0,x1 are the same pixel, so compute combined coverage
+ scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT);
+ } else {
+ if (i >= 0) // add antialiasing for x0
+ scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT);
+ else
+ i = -1; // clip
+
+ if (j < len) // add antialiasing for x1
+ scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT);
+ else
+ j = len; // clip
+
+ for (++i; i < j; ++i) // fill pixels between x0 and x1
+ scanline[i] = scanline[i] + (stbtt_uint8) max_weight;
+ }
+ }
+ }
+ }
+
+ e = e->next;
+ }
+}
+
+static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
+{
+ stbtt__hheap hh = { 0, 0, 0 };
+ stbtt__active_edge *active = NULL;
+ int y,j=0;
+ int max_weight = (255 / vsubsample); // weight per vertical scanline
+ int s; // vertical subsample index
+ unsigned char scanline_data[512], *scanline;
+
+ if (result->w > 512)
+ scanline = (unsigned char *) STBTT_malloc(result->w, userdata);
+ else
+ scanline = scanline_data;
+
+ y = off_y * vsubsample;
+ e[n].y0 = (off_y + result->h) * (float) vsubsample + 1;
+
+ while (j < result->h) {
+ STBTT_memset(scanline, 0, result->w);
+ for (s=0; s < vsubsample; ++s) {
+ // find center of pixel for this scanline
+ float scan_y = y + 0.5f;
+ stbtt__active_edge **step = &active;
+
+ // update all active edges;
+ // remove all active edges that terminate before the center of this scanline
+ while (*step) {
+ stbtt__active_edge * z = *step;
+ if (z->ey <= scan_y) {
+ *step = z->next; // delete from list
+ STBTT_assert(z->direction);
+ z->direction = 0;
+ stbtt__hheap_free(&hh, z);
+ } else {
+ z->x += z->dx; // advance to position for current scanline
+ step = &((*step)->next); // advance through list
+ }
+ }
+
+ // resort the list if needed
+ for(;;) {
+ int changed=0;
+ step = &active;
+ while (*step && (*step)->next) {
+ if ((*step)->x > (*step)->next->x) {
+ stbtt__active_edge *t = *step;
+ stbtt__active_edge *q = t->next;
+
+ t->next = q->next;
+ q->next = t;
+ *step = q;
+ changed = 1;
+ }
+ step = &(*step)->next;
+ }
+ if (!changed) break;
+ }
+
+ // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
+ while (e->y0 <= scan_y) {
+ if (e->y1 > scan_y) {
+ stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
+ if (z != NULL) {
+ // find insertion point
+ if (active == NULL)
+ active = z;
+ else if (z->x < active->x) {
+ // insert at front
+ z->next = active;
+ active = z;
+ } else {
+ // find thing to insert AFTER
+ stbtt__active_edge *p = active;
+ while (p->next && p->next->x < z->x)
+ p = p->next;
+ // at this point, p->next->x is NOT < z->x
+ z->next = p->next;
+ p->next = z;
+ }
+ }
+ }
+ ++e;
+ }
+
+ // now process all active edges in XOR fashion
+ if (active)
+ stbtt__fill_active_edges(scanline, result->w, active, max_weight);
+
+ ++y;
+ }
+ STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w);
+ ++j;
+ }
+
+ stbtt__hheap_cleanup(&hh, userdata);
+
+ if (scanline != scanline_data)
+ STBTT_free(scanline, userdata);
+}
+
+#elif STBTT_RASTERIZER_VERSION == 2
+
+// the edge passed in here does not cross the vertical line at x or the vertical line at x+1
+// (i.e. it has already been clipped to those)
+static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1)
+{
+ if (y0 == y1) return;
+ STBTT_assert(y0 < y1);
+ STBTT_assert(e->sy <= e->ey);
+ if (y0 > e->ey) return;
+ if (y1 < e->sy) return;
+ if (y0 < e->sy) {
+ x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
+ y0 = e->sy;
+ }
+ if (y1 > e->ey) {
+ x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
+ y1 = e->ey;
+ }
+
+ if (x0 == x)
+ STBTT_assert(x1 <= x+1);
+ else if (x0 == x+1)
+ STBTT_assert(x1 >= x);
+ else if (x0 <= x)
+ STBTT_assert(x1 <= x);
+ else if (x0 >= x+1)
+ STBTT_assert(x1 >= x+1);
+ else
+ STBTT_assert(x1 >= x && x1 <= x+1);
+
+ if (x0 <= x && x1 <= x)
+ scanline[x] += e->direction * (y1-y0);
+ else if (x0 >= x+1 && x1 >= x+1)
+ ;
+ else {
+ STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
+ scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position
+ }
+}
+
+static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top)
+{
+ float y_bottom = y_top+1;
+
+ while (e) {
+ // brute force every pixel
+
+ // compute intersection points with top & bottom
+ STBTT_assert(e->ey >= y_top);
+
+ if (e->fdx == 0) {
+ float x0 = e->fx;
+ if (x0 < len) {
+ if (x0 >= 0) {
+ stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
+ stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
+ } else {
+ stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
+ }
+ }
+ } else {
+ float x0 = e->fx;
+ float dx = e->fdx;
+ float xb = x0 + dx;
+ float x_top, x_bottom;
+ float sy0,sy1;
+ float dy = e->fdy;
+ STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
+
+ // compute endpoints of line segment clipped to this scanline (if the
+ // line segment starts on this scanline. x0 is the intersection of the
+ // line with y_top, but that may be off the line segment.
+ if (e->sy > y_top) {
+ x_top = x0 + dx * (e->sy - y_top);
+ sy0 = e->sy;
+ } else {
+ x_top = x0;
+ sy0 = y_top;
+ }
+ if (e->ey < y_bottom) {
+ x_bottom = x0 + dx * (e->ey - y_top);
+ sy1 = e->ey;
+ } else {
+ x_bottom = xb;
+ sy1 = y_bottom;
+ }
+
+ if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
+ // from here on, we don't have to range check x values
+
+ if ((int) x_top == (int) x_bottom) {
+ float height;
+ // simple case, only spans one pixel
+ int x = (int) x_top;
+ height = sy1 - sy0;
+ STBTT_assert(x >= 0 && x < len);
+ scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
+ scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
+ } else {
+ int x,x1,x2;
+ float y_crossing, step, sign, area;
+ // covers 2+ pixels
+ if (x_top > x_bottom) {
+ // flip scanline vertically; signed area is the same
+ float t;
+ sy0 = y_bottom - (sy0 - y_top);
+ sy1 = y_bottom - (sy1 - y_top);
+ t = sy0, sy0 = sy1, sy1 = t;
+ t = x_bottom, x_bottom = x_top, x_top = t;
+ dx = -dx;
+ dy = -dy;
+ t = x0, x0 = xb, xb = t;
+ // [DEAR IMGUI] Fix static analyzer warning
+ (void)dx; // [ImGui: fix static analyzer warning]
+ }
+
+ x1 = (int) x_top;
+ x2 = (int) x_bottom;
+ // compute intersection with y axis at x1+1
+ y_crossing = (x1+1 - x0) * dy + y_top;
+
+ sign = e->direction;
+ // area of the rectangle covered from y0..y_crossing
+ area = sign * (y_crossing-sy0);
+ // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
+ scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
+
+ step = sign * dy;
+ for (x = x1+1; x < x2; ++x) {
+ scanline[x] += area + step/2;
+ area += step;
+ }
+ y_crossing += dy * (x2 - (x1+1));
+
+ STBTT_assert(STBTT_fabs(area) <= 1.01f);
+
+ scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
+
+ scanline_fill[x2] += sign * (sy1-sy0);
+ }
+ } else {
+ // if edge goes outside of box we're drawing, we require
+ // clipping logic. since this does not match the intended use
+ // of this library, we use a different, very slow brute
+ // force implementation
+ int x;
+ for (x=0; x < len; ++x) {
+ // cases:
+ //
+ // there can be up to two intersections with the pixel. any intersection
+ // with left or right edges can be handled by splitting into two (or three)
+ // regions. intersections with top & bottom do not necessitate case-wise logic.
+ //
+ // the old way of doing this found the intersections with the left & right edges,
+ // then used some simple logic to produce up to three segments in sorted order
+ // from top-to-bottom. however, this had a problem: if an x edge was epsilon
+ // across the x border, then the corresponding y position might not be distinct
+ // from the other y segment, and it might ignored as an empty segment. to avoid
+ // that, we need to explicitly produce segments based on x positions.
+
+ // rename variables to clearly-defined pairs
+ float y0 = y_top;
+ float x1 = (float) (x);
+ float x2 = (float) (x+1);
+ float x3 = xb;
+ float y3 = y_bottom;
+
+ // x = e->x + e->dx * (y-y_top)
+ // (y-y_top) = (x - e->x) / e->dx
+ // y = (x - e->x) / e->dx + y_top
+ float y1 = (x - x0) / dx + y_top;
+ float y2 = (x+1 - x0) / dx + y_top;
+
+ if (x0 < x1 && x3 > x2) { // three segments descending down-right
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
+ } else if (x3 < x1 && x0 > x2) { // three segments descending down-left
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
+ } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
+ } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1);
+ stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3);
+ } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
+ } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2);
+ stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
+ } else { // one segment
+ stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3);
+ }
+ }
+ }
+ }
+ e = e->next;
+ }
+}
+
+// directly AA rasterize edges w/o supersampling
+static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
+{
+ stbtt__hheap hh = { 0, 0, 0 };
+ stbtt__active_edge *active = NULL;
+ int y,j=0, i;
+ float scanline_data[129], *scanline, *scanline2;
+
+ STBTT__NOTUSED(vsubsample);
+
+ if (result->w > 64)
+ scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
+ else
+ scanline = scanline_data;
+
+ scanline2 = scanline + result->w;
+
+ y = off_y;
+ e[n].y0 = (float) (off_y + result->h) + 1;
+
+ while (j < result->h) {
+ // find center of pixel for this scanline
+ float scan_y_top = y + 0.0f;
+ float scan_y_bottom = y + 1.0f;
+ stbtt__active_edge **step = &active;
+
+ STBTT_memset(scanline , 0, result->w*sizeof(scanline[0]));
+ STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0]));
+
+ // update all active edges;
+ // remove all active edges that terminate before the top of this scanline
+ while (*step) {
+ stbtt__active_edge * z = *step;
+ if (z->ey <= scan_y_top) {
+ *step = z->next; // delete from list
+ STBTT_assert(z->direction);
+ z->direction = 0;
+ stbtt__hheap_free(&hh, z);
+ } else {
+ step = &((*step)->next); // advance through list
+ }
+ }
+
+ // insert all edges that start before the bottom of this scanline
+ while (e->y0 <= scan_y_bottom) {
+ if (e->y0 != e->y1) {
+ stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
+ if (z != NULL) {
+ if (j == 0 && off_y != 0) {
+ if (z->ey < scan_y_top) {
+ // this can happen due to subpixel positioning and some kind of fp rounding error i think
+ z->ey = scan_y_top;
+ }
+ }
+ STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds
+ // insert at front
+ z->next = active;
+ active = z;
+ }
+ }
+ ++e;
+ }
+
+ // now process all active edges
+ if (active)
+ stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
+
+ {
+ float sum = 0;
+ for (i=0; i < result->w; ++i) {
+ float k;
+ int m;
+ sum += scanline2[i];
+ k = scanline[i] + sum;
+ k = (float) STBTT_fabs(k)*255 + 0.5f;
+ m = (int) k;
+ if (m > 255) m = 255;
+ result->pixels[j*result->stride + i] = (unsigned char) m;
+ }
+ }
+ // advance all the edges
+ step = &active;
+ while (*step) {
+ stbtt__active_edge *z = *step;
+ z->fx += z->fdx; // advance to position for current scanline
+ step = &((*step)->next); // advance through list
+ }
+
+ ++y;
+ ++j;
+ }
+
+ stbtt__hheap_cleanup(&hh, userdata);
+
+ if (scanline != scanline_data)
+ STBTT_free(scanline, userdata);
+}
+#else
+#error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#endif
+
+#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0)
+
+static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
+{
+ int i,j;
+ for (i=1; i < n; ++i) {
+ stbtt__edge t = p[i], *a = &t;
+ j = i;
+ while (j > 0) {
+ stbtt__edge *b = &p[j-1];
+ int c = STBTT__COMPARE(a,b);
+ if (!c) break;
+ p[j] = p[j-1];
+ --j;
+ }
+ if (i != j)
+ p[j] = t;
+ }
+}
+
+static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
+{
+ /* threshold for transitioning to insertion sort */
+ while (n > 12) {
+ stbtt__edge t;
+ int c01,c12,c,m,i,j;
+
+ /* compute median of three */
+ m = n >> 1;
+ c01 = STBTT__COMPARE(&p[0],&p[m]);
+ c12 = STBTT__COMPARE(&p[m],&p[n-1]);
+ /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
+ if (c01 != c12) {
+ /* otherwise, we'll need to swap something else to middle */
+ int z;
+ c = STBTT__COMPARE(&p[0],&p[n-1]);
+ /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
+ /* 0<mid && mid>n: 0>n => 0; 0<n => n */
+ z = (c == c12) ? 0 : n-1;
+ t = p[z];
+ p[z] = p[m];
+ p[m] = t;
+ }
+ /* now p[m] is the median-of-three */
+ /* swap it to the beginning so it won't move around */
+ t = p[0];
+ p[0] = p[m];
+ p[m] = t;
+
+ /* partition loop */
+ i=1;
+ j=n-1;
+ for(;;) {
+ /* handling of equality is crucial here */
+ /* for sentinels & efficiency with duplicates */
+ for (;;++i) {
+ if (!STBTT__COMPARE(&p[i], &p[0])) break;
+ }
+ for (;;--j) {
+ if (!STBTT__COMPARE(&p[0], &p[j])) break;
+ }
+ /* make sure we haven't crossed */
+ if (i >= j) break;
+ t = p[i];
+ p[i] = p[j];
+ p[j] = t;
+
+ ++i;
+ --j;
+ }
+ /* recurse on smaller side, iterate on larger */
+ if (j < (n-i)) {
+ stbtt__sort_edges_quicksort(p,j);
+ p = p+i;
+ n = n-i;
+ } else {
+ stbtt__sort_edges_quicksort(p+i, n-i);
+ n = j;
+ }
+ }
+}
+
+static void stbtt__sort_edges(stbtt__edge *p, int n)
+{
+ stbtt__sort_edges_quicksort(p, n);
+ stbtt__sort_edges_ins_sort(p, n);
+}
+
+typedef struct
+{
+ float x,y;
+} stbtt__point;
+
+static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata)
+{
+ float y_scale_inv = invert ? -scale_y : scale_y;
+ stbtt__edge *e;
+ int n,i,j,k,m;
+#if STBTT_RASTERIZER_VERSION == 1
+ int vsubsample = result->h < 8 ? 15 : 5;
+#elif STBTT_RASTERIZER_VERSION == 2
+ int vsubsample = 1;
+#else
+ #error "Unrecognized value of STBTT_RASTERIZER_VERSION"
+#endif
+ // vsubsample should divide 255 evenly; otherwise we won't reach full opacity
+
+ // now we have to blow out the windings into explicit edge lists
+ n = 0;
+ for (i=0; i < windings; ++i)
+ n += wcount[i];
+
+ e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel
+ if (e == 0) return;
+ n = 0;
+
+ m=0;
+ for (i=0; i < windings; ++i) {
+ stbtt__point *p = pts + m;
+ m += wcount[i];
+ j = wcount[i]-1;
+ for (k=0; k < wcount[i]; j=k++) {
+ int a=k,b=j;
+ // skip the edge if horizontal
+ if (p[j].y == p[k].y)
+ continue;
+ // add edge from j to k to the list
+ e[n].invert = 0;
+ if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
+ e[n].invert = 1;
+ a=j,b=k;
+ }
+ e[n].x0 = p[a].x * scale_x + shift_x;
+ e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample;
+ e[n].x1 = p[b].x * scale_x + shift_x;
+ e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample;
+ ++n;
+ }
+ }
+
+ // now sort the edges by their highest point (should snap to integer, and then by x)
+ //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare);
+ stbtt__sort_edges(e, n);
+
+ // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule
+ stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata);
+
+ STBTT_free(e, userdata);
+}
+
+static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
+{
+ if (!points) return; // during first pass, it's unallocated
+ points[n].x = x;
+ points[n].y = y;
+}
+
+// tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching
+static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n)
+{
+ // midpoint
+ float mx = (x0 + 2*x1 + x2)/4;
+ float my = (y0 + 2*y1 + y2)/4;
+ // versus directly drawn line
+ float dx = (x0+x2)/2 - mx;
+ float dy = (y0+y2)/2 - my;
+ if (n > 16) // 65536 segments on one curve better be enough!
+ return 1;
+ if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA
+ stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
+ stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
+ } else {
+ stbtt__add_point(points, *num_points,x2,y2);
+ *num_points = *num_points+1;
+ }
+ return 1;
+}
+
+static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n)
+{
+ // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough
+ float dx0 = x1-x0;
+ float dy0 = y1-y0;
+ float dx1 = x2-x1;
+ float dy1 = y2-y1;
+ float dx2 = x3-x2;
+ float dy2 = y3-y2;
+ float dx = x3-x0;
+ float dy = y3-y0;
+ float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2));
+ float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy);
+ float flatness_squared = longlen*longlen-shortlen*shortlen;
+
+ if (n > 16) // 65536 segments on one curve better be enough!
+ return;
+
+ if (flatness_squared > objspace_flatness_squared) {
+ float x01 = (x0+x1)/2;
+ float y01 = (y0+y1)/2;
+ float x12 = (x1+x2)/2;
+ float y12 = (y1+y2)/2;
+ float x23 = (x2+x3)/2;
+ float y23 = (y2+y3)/2;
+
+ float xa = (x01+x12)/2;
+ float ya = (y01+y12)/2;
+ float xb = (x12+x23)/2;
+ float yb = (y12+y23)/2;
+
+ float mx = (xa+xb)/2;
+ float my = (ya+yb)/2;
+
+ stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1);
+ stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1);
+ } else {
+ stbtt__add_point(points, *num_points,x3,y3);
+ *num_points = *num_points+1;
+ }
+}
+
+// returns number of contours
+static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata)
+{
+ stbtt__point *points=0;
+ int num_points=0;
+
+ float objspace_flatness_squared = objspace_flatness * objspace_flatness;
+ int i,n=0,start=0, pass;
+
+ // count how many "moves" there are to get the contour count
+ for (i=0; i < num_verts; ++i)
+ if (vertices[i].type == STBTT_vmove)
+ ++n;
+
+ *num_contours = n;
+ if (n == 0) return 0;
+
+ *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata);
+
+ if (*contour_lengths == 0) {
+ *num_contours = 0;
+ return 0;
+ }
+
+ // make two passes through the points so we don't need to realloc
+ for (pass=0; pass < 2; ++pass) {
+ float x=0,y=0;
+ if (pass == 1) {
+ points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata);
+ if (points == NULL) goto error;
+ }
+ num_points = 0;
+ n= -1;
+ for (i=0; i < num_verts; ++i) {
+ switch (vertices[i].type) {
+ case STBTT_vmove:
+ // start the next contour
+ if (n >= 0)
+ (*contour_lengths)[n] = num_points - start;
+ ++n;
+ start = num_points;
+
+ x = vertices[i].x, y = vertices[i].y;
+ stbtt__add_point(points, num_points++, x,y);
+ break;
+ case STBTT_vline:
+ x = vertices[i].x, y = vertices[i].y;
+ stbtt__add_point(points, num_points++, x, y);
+ break;
+ case STBTT_vcurve:
+ stbtt__tesselate_curve(points, &num_points, x,y,
+ vertices[i].cx, vertices[i].cy,
+ vertices[i].x, vertices[i].y,
+ objspace_flatness_squared, 0);
+ x = vertices[i].x, y = vertices[i].y;
+ break;
+ case STBTT_vcubic:
+ stbtt__tesselate_cubic(points, &num_points, x,y,
+ vertices[i].cx, vertices[i].cy,
+ vertices[i].cx1, vertices[i].cy1,
+ vertices[i].x, vertices[i].y,
+ objspace_flatness_squared, 0);
+ x = vertices[i].x, y = vertices[i].y;
+ break;
+ }
+ }
+ (*contour_lengths)[n] = num_points - start;
+ }
+
+ return points;
+error:
+ STBTT_free(points, userdata);
+ STBTT_free(*contour_lengths, userdata);
+ *contour_lengths = 0;
+ *num_contours = 0;
+ return NULL;
+}
+
+STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata)
+{
+ float scale = scale_x > scale_y ? scale_y : scale_x;
+ int winding_count = 0;
+ int *winding_lengths = NULL;
+ stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata);
+ if (windings) {
+ stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata);
+ STBTT_free(winding_lengths, userdata);
+ STBTT_free(windings, userdata);
+ }
+}
+
+STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
+{
+ STBTT_free(bitmap, userdata);
+}
+
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff)
+{
+ int ix0,iy0,ix1,iy1;
+ stbtt__bitmap gbm;
+ stbtt_vertex *vertices;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
+
+ if (scale_x == 0) scale_x = scale_y;
+ if (scale_y == 0) {
+ if (scale_x == 0) {
+ STBTT_free(vertices, info->userdata);
+ return NULL;
+ }
+ scale_y = scale_x;
+ }
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1);
+
+ // now we get the size
+ gbm.w = (ix1 - ix0);
+ gbm.h = (iy1 - iy0);
+ gbm.pixels = NULL; // in case we error
+
+ if (width ) *width = gbm.w;
+ if (height) *height = gbm.h;
+ if (xoff ) *xoff = ix0;
+ if (yoff ) *yoff = iy0;
+
+ if (gbm.w && gbm.h) {
+ gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata);
+ if (gbm.pixels) {
+ gbm.stride = gbm.w;
+
+ stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata);
+ }
+ }
+ STBTT_free(vertices, info->userdata);
+ return gbm.pixels;
+}
+
+STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff);
+}
+
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph)
+{
+ int ix0,iy0;
+ stbtt_vertex *vertices;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices);
+ stbtt__bitmap gbm;
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0);
+ gbm.pixels = output;
+ gbm.w = out_w;
+ gbm.h = out_h;
+ gbm.stride = out_stride;
+
+ if (gbm.w && gbm.h)
+ stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata);
+
+ STBTT_free(vertices, info->userdata);
+}
+
+STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph)
+{
+ stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph);
+}
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff);
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint)
+{
+ stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint));
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint)
+{
+ stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint));
+}
+
+STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff);
+}
+
+STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint)
+{
+ stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// bitmap baking
+//
+// This is SUPER-CRAPPY packing to keep source code small
+
+static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf)
+ float pixel_height, // height of font in pixels
+ unsigned char *pixels, int pw, int ph, // bitmap to be filled in
+ int first_char, int num_chars, // characters to bake
+ stbtt_bakedchar *chardata)
+{
+ float scale;
+ int x,y,bottom_y, i;
+ stbtt_fontinfo f;
+ f.userdata = NULL;
+ if (!stbtt_InitFont(&f, data, offset))
+ return -1;
+ STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
+ x=y=1;
+ bottom_y = 1;
+
+ scale = stbtt_ScaleForPixelHeight(&f, pixel_height);
+
+ for (i=0; i < num_chars; ++i) {
+ int advance, lsb, x0,y0,x1,y1,gw,gh;
+ int g = stbtt_FindGlyphIndex(&f, first_char + i);
+ stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb);
+ stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1);
+ gw = x1-x0;
+ gh = y1-y0;
+ if (x + gw + 1 >= pw)
+ y = bottom_y, x = 1; // advance to next row
+ if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row
+ return -i;
+ STBTT_assert(x+gw < pw);
+ STBTT_assert(y+gh < ph);
+ stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g);
+ chardata[i].x0 = (stbtt_int16) x;
+ chardata[i].y0 = (stbtt_int16) y;
+ chardata[i].x1 = (stbtt_int16) (x + gw);
+ chardata[i].y1 = (stbtt_int16) (y + gh);
+ chardata[i].xadvance = scale * advance;
+ chardata[i].xoff = (float) x0;
+ chardata[i].yoff = (float) y0;
+ x = x + gw + 1;
+ if (y+gh+1 > bottom_y)
+ bottom_y = y+gh+1;
+ }
+ return bottom_y;
+}
+
+STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule)
+{
+ float d3d_bias = opengl_fillrule ? 0 : -0.5f;
+ float ipw = 1.0f / pw, iph = 1.0f / ph;
+ const stbtt_bakedchar *b = chardata + char_index;
+ int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f);
+ int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f);
+
+ q->x0 = round_x + d3d_bias;
+ q->y0 = round_y + d3d_bias;
+ q->x1 = round_x + b->x1 - b->x0 + d3d_bias;
+ q->y1 = round_y + b->y1 - b->y0 + d3d_bias;
+
+ q->s0 = b->x0 * ipw;
+ q->t0 = b->y0 * iph;
+ q->s1 = b->x1 * ipw;
+ q->t1 = b->y1 * iph;
+
+ *xpos += b->xadvance;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// rectangle packing replacement routines if you don't have stb_rect_pack.h
+//
+
+#ifndef STB_RECT_PACK_VERSION
+
+typedef int stbrp_coord;
+
+////////////////////////////////////////////////////////////////////////////////////
+// //
+// //
+// COMPILER WARNING ?!?!? //
+// //
+// //
+// if you get a compile warning due to these symbols being defined more than //
+// once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" //
+// //
+////////////////////////////////////////////////////////////////////////////////////
+
+typedef struct
+{
+ int width,height;
+ int x,y,bottom_y;
+} stbrp_context;
+
+typedef struct
+{
+ unsigned char x;
+} stbrp_node;
+
+struct stbrp_rect
+{
+ stbrp_coord x,y;
+ int id,w,h,was_packed;
+};
+
+static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes)
+{
+ con->width = pw;
+ con->height = ph;
+ con->x = 0;
+ con->y = 0;
+ con->bottom_y = 0;
+ STBTT__NOTUSED(nodes);
+ STBTT__NOTUSED(num_nodes);
+}
+
+static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects)
+{
+ int i;
+ for (i=0; i < num_rects; ++i) {
+ if (con->x + rects[i].w > con->width) {
+ con->x = 0;
+ con->y = con->bottom_y;
+ }
+ if (con->y + rects[i].h > con->height)
+ break;
+ rects[i].x = con->x;
+ rects[i].y = con->y;
+ rects[i].was_packed = 1;
+ con->x += rects[i].w;
+ if (con->y + rects[i].h > con->bottom_y)
+ con->bottom_y = con->y + rects[i].h;
+ }
+ for ( ; i < num_rects; ++i)
+ rects[i].was_packed = 0;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// bitmap baking
+//
+// This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If
+// stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy.
+
+STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context)
+{
+ stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context);
+ int num_nodes = pw - padding;
+ stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context);
+
+ if (context == NULL || nodes == NULL) {
+ if (context != NULL) STBTT_free(context, alloc_context);
+ if (nodes != NULL) STBTT_free(nodes , alloc_context);
+ return 0;
+ }
+
+ spc->user_allocator_context = alloc_context;
+ spc->width = pw;
+ spc->height = ph;
+ spc->pixels = pixels;
+ spc->pack_info = context;
+ spc->nodes = nodes;
+ spc->padding = padding;
+ spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw;
+ spc->h_oversample = 1;
+ spc->v_oversample = 1;
+ spc->skip_missing = 0;
+
+ stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
+
+ if (pixels)
+ STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
+
+ return 1;
+}
+
+STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc)
+{
+ STBTT_free(spc->nodes , spc->user_allocator_context);
+ STBTT_free(spc->pack_info, spc->user_allocator_context);
+}
+
+STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample)
+{
+ STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE);
+ STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE);
+ if (h_oversample <= STBTT_MAX_OVERSAMPLE)
+ spc->h_oversample = h_oversample;
+ if (v_oversample <= STBTT_MAX_OVERSAMPLE)
+ spc->v_oversample = v_oversample;
+}
+
+STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip)
+{
+ spc->skip_missing = skip;
+}
+
+#define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1)
+
+static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
+{
+ unsigned char buffer[STBTT_MAX_OVERSAMPLE];
+ int safe_w = w - kernel_width;
+ int j;
+ STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
+ for (j=0; j < h; ++j) {
+ int i;
+ unsigned int total;
+ STBTT_memset(buffer, 0, kernel_width);
+
+ total = 0;
+
+ // make kernel_width a constant in common cases so compiler can optimize out the divide
+ switch (kernel_width) {
+ case 2:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 2);
+ }
+ break;
+ case 3:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 3);
+ }
+ break;
+ case 4:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 4);
+ }
+ break;
+ case 5:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / 5);
+ }
+ break;
+ default:
+ for (i=0; i <= safe_w; ++i) {
+ total += pixels[i] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i];
+ pixels[i] = (unsigned char) (total / kernel_width);
+ }
+ break;
+ }
+
+ for (; i < w; ++i) {
+ STBTT_assert(pixels[i] == 0);
+ total -= buffer[i & STBTT__OVER_MASK];
+ pixels[i] = (unsigned char) (total / kernel_width);
+ }
+
+ pixels += stride_in_bytes;
+ }
+}
+
+static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width)
+{
+ unsigned char buffer[STBTT_MAX_OVERSAMPLE];
+ int safe_h = h - kernel_width;
+ int j;
+ STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
+ for (j=0; j < w; ++j) {
+ int i;
+ unsigned int total;
+ STBTT_memset(buffer, 0, kernel_width);
+
+ total = 0;
+
+ // make kernel_width a constant in common cases so compiler can optimize out the divide
+ switch (kernel_width) {
+ case 2:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
+ }
+ break;
+ case 3:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
+ }
+ break;
+ case 4:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
+ }
+ break;
+ case 5:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
+ }
+ break;
+ default:
+ for (i=0; i <= safe_h; ++i) {
+ total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK];
+ buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
+ }
+ break;
+ }
+
+ for (; i < h; ++i) {
+ STBTT_assert(pixels[i*stride_in_bytes] == 0);
+ total -= buffer[i & STBTT__OVER_MASK];
+ pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width);
+ }
+
+ pixels += 1;
+ }
+}
+
+static float stbtt__oversample_shift(int oversample)
+{
+ if (!oversample)
+ return 0.0f;
+
+ // The prefilter is a box filter of width "oversample",
+ // which shifts phase by (oversample - 1)/2 pixels in
+ // oversampled space. We want to shift in the opposite
+ // direction to counter this.
+ return (float)-(oversample - 1) / (2.0f * (float)oversample);
+}
+
+// rects array must be big enough to accommodate all characters in the given ranges
+STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
+{
+ int i,j,k;
+
+ k=0;
+ for (i=0; i < num_ranges; ++i) {
+ float fh = ranges[i].font_size;
+ float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
+ ranges[i].h_oversample = (unsigned char) spc->h_oversample;
+ ranges[i].v_oversample = (unsigned char) spc->v_oversample;
+ for (j=0; j < ranges[i].num_chars; ++j) {
+ int x0,y0,x1,y1;
+ int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
+ int glyph = stbtt_FindGlyphIndex(info, codepoint);
+ if (glyph == 0 && spc->skip_missing) {
+ rects[k].w = rects[k].h = 0;
+ } else {
+ stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ 0,0,
+ &x0,&y0,&x1,&y1);
+ rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1);
+ rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1);
+ }
+ ++k;
+ }
+ }
+
+ return k;
+}
+
+STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph)
+{
+ stbtt_MakeGlyphBitmapSubpixel(info,
+ output,
+ out_w - (prefilter_x - 1),
+ out_h - (prefilter_y - 1),
+ out_stride,
+ scale_x,
+ scale_y,
+ shift_x,
+ shift_y,
+ glyph);
+
+ if (prefilter_x > 1)
+ stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x);
+
+ if (prefilter_y > 1)
+ stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y);
+
+ *sub_x = stbtt__oversample_shift(prefilter_x);
+ *sub_y = stbtt__oversample_shift(prefilter_y);
+}
+
+// rects array must be big enough to accommodate all characters in the given ranges
+STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects)
+{
+ int i,j,k, return_value = 1;
+
+ // save current values
+ int old_h_over = spc->h_oversample;
+ int old_v_over = spc->v_oversample;
+
+ k = 0;
+ for (i=0; i < num_ranges; ++i) {
+ float fh = ranges[i].font_size;
+ float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh);
+ float recip_h,recip_v,sub_x,sub_y;
+ spc->h_oversample = ranges[i].h_oversample;
+ spc->v_oversample = ranges[i].v_oversample;
+ recip_h = 1.0f / spc->h_oversample;
+ recip_v = 1.0f / spc->v_oversample;
+ sub_x = stbtt__oversample_shift(spc->h_oversample);
+ sub_y = stbtt__oversample_shift(spc->v_oversample);
+ for (j=0; j < ranges[i].num_chars; ++j) {
+ stbrp_rect *r = &rects[k];
+ if (r->was_packed && r->w != 0 && r->h != 0) {
+ stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
+ int advance, lsb, x0,y0,x1,y1;
+ int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
+ int glyph = stbtt_FindGlyphIndex(info, codepoint);
+ stbrp_coord pad = (stbrp_coord) spc->padding;
+
+ // pad on left and top
+ r->x += pad;
+ r->y += pad;
+ r->w -= pad;
+ r->h -= pad;
+ stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
+ stbtt_GetGlyphBitmapBox(info, glyph,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ &x0,&y0,&x1,&y1);
+ stbtt_MakeGlyphBitmapSubpixel(info,
+ spc->pixels + r->x + r->y*spc->stride_in_bytes,
+ r->w - spc->h_oversample+1,
+ r->h - spc->v_oversample+1,
+ spc->stride_in_bytes,
+ scale * spc->h_oversample,
+ scale * spc->v_oversample,
+ 0,0,
+ glyph);
+
+ if (spc->h_oversample > 1)
+ stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
+ r->w, r->h, spc->stride_in_bytes,
+ spc->h_oversample);
+
+ if (spc->v_oversample > 1)
+ stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
+ r->w, r->h, spc->stride_in_bytes,
+ spc->v_oversample);
+
+ bc->x0 = (stbtt_int16) r->x;
+ bc->y0 = (stbtt_int16) r->y;
+ bc->x1 = (stbtt_int16) (r->x + r->w);
+ bc->y1 = (stbtt_int16) (r->y + r->h);
+ bc->xadvance = scale * advance;
+ bc->xoff = (float) x0 * recip_h + sub_x;
+ bc->yoff = (float) y0 * recip_v + sub_y;
+ bc->xoff2 = (x0 + r->w) * recip_h + sub_x;
+ bc->yoff2 = (y0 + r->h) * recip_v + sub_y;
+ } else {
+ return_value = 0; // if any fail, report failure
+ }
+
+ ++k;
+ }
+ }
+
+ // restore original values
+ spc->h_oversample = old_h_over;
+ spc->v_oversample = old_v_over;
+
+ return return_value;
+}
+
+STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects)
+{
+ stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects);
+}
+
+STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
+{
+ stbtt_fontinfo info;
+ int i,j,n, return_value; // [DEAR IMGUI] removed = 1
+ //stbrp_context *context = (stbrp_context *) spc->pack_info;
+ stbrp_rect *rects;
+
+ // flag all characters as NOT packed
+ for (i=0; i < num_ranges; ++i)
+ for (j=0; j < ranges[i].num_chars; ++j)
+ ranges[i].chardata_for_range[j].x0 =
+ ranges[i].chardata_for_range[j].y0 =
+ ranges[i].chardata_for_range[j].x1 =
+ ranges[i].chardata_for_range[j].y1 = 0;
+
+ n = 0;
+ for (i=0; i < num_ranges; ++i)
+ n += ranges[i].num_chars;
+
+ rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context);
+ if (rects == NULL)
+ return 0;
+
+ info.userdata = spc->user_allocator_context;
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
+
+ n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
+
+ stbtt_PackFontRangesPackRects(spc, rects, n);
+
+ return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects);
+
+ STBTT_free(rects, spc->user_allocator_context);
+ return return_value;
+}
+
+STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size,
+ int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range)
+{
+ stbtt_pack_range range;
+ range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range;
+ range.array_of_unicode_codepoints = NULL;
+ range.num_chars = num_chars_in_range;
+ range.chardata_for_range = chardata_for_range;
+ range.font_size = font_size;
+ return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1);
+}
+
+STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap)
+{
+ int i_ascent, i_descent, i_lineGap;
+ float scale;
+ stbtt_fontinfo info;
+ stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index));
+ scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size);
+ stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap);
+ *ascent = (float) i_ascent * scale;
+ *descent = (float) i_descent * scale;
+ *lineGap = (float) i_lineGap * scale;
+}
+
+STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer)
+{
+ float ipw = 1.0f / pw, iph = 1.0f / ph;
+ const stbtt_packedchar *b = chardata + char_index;
+
+ if (align_to_integer) {
+ float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f);
+ float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f);
+ q->x0 = x;
+ q->y0 = y;
+ q->x1 = x + b->xoff2 - b->xoff;
+ q->y1 = y + b->yoff2 - b->yoff;
+ } else {
+ q->x0 = *xpos + b->xoff;
+ q->y0 = *ypos + b->yoff;
+ q->x1 = *xpos + b->xoff2;
+ q->y1 = *ypos + b->yoff2;
+ }
+
+ q->s0 = b->x0 * ipw;
+ q->t0 = b->y0 * iph;
+ q->s1 = b->x1 * ipw;
+ q->t1 = b->y1 * iph;
+
+ *xpos += b->xadvance;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// sdf computation
+//
+
+#define STBTT_min(a,b) ((a) < (b) ? (a) : (b))
+#define STBTT_max(a,b) ((a) < (b) ? (b) : (a))
+
+static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2])
+{
+ float q0perp = q0[1]*ray[0] - q0[0]*ray[1];
+ float q1perp = q1[1]*ray[0] - q1[0]*ray[1];
+ float q2perp = q2[1]*ray[0] - q2[0]*ray[1];
+ float roperp = orig[1]*ray[0] - orig[0]*ray[1];
+
+ float a = q0perp - 2*q1perp + q2perp;
+ float b = q1perp - q0perp;
+ float c = q0perp - roperp;
+
+ float s0 = 0., s1 = 0.;
+ int num_s = 0;
+
+ if (a != 0.0) {
+ float discr = b*b - a*c;
+ if (discr > 0.0) {
+ float rcpna = -1 / a;
+ float d = (float) STBTT_sqrt(discr);
+ s0 = (b+d) * rcpna;
+ s1 = (b-d) * rcpna;
+ if (s0 >= 0.0 && s0 <= 1.0)
+ num_s = 1;
+ if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) {
+ if (num_s == 0) s0 = s1;
+ ++num_s;
+ }
+ }
+ } else {
+ // 2*b*s + c = 0
+ // s = -c / (2*b)
+ s0 = c / (-2 * b);
+ if (s0 >= 0.0 && s0 <= 1.0)
+ num_s = 1;
+ }
+
+ if (num_s == 0)
+ return 0;
+ else {
+ float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]);
+ float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2;
+
+ float q0d = q0[0]*rayn_x + q0[1]*rayn_y;
+ float q1d = q1[0]*rayn_x + q1[1]*rayn_y;
+ float q2d = q2[0]*rayn_x + q2[1]*rayn_y;
+ float rod = orig[0]*rayn_x + orig[1]*rayn_y;
+
+ float q10d = q1d - q0d;
+ float q20d = q2d - q0d;
+ float q0rd = q0d - rod;
+
+ hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d;
+ hits[0][1] = a*s0+b;
+
+ if (num_s > 1) {
+ hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d;
+ hits[1][1] = a*s1+b;
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+}
+
+static int equal(float *a, float *b)
+{
+ return (a[0] == b[0] && a[1] == b[1]);
+}
+
+static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts)
+{
+ int i;
+ float orig[2], ray[2] = { 1, 0 };
+ float y_frac;
+ int winding = 0;
+
+ orig[0] = x;
+ //orig[1] = y; // [DEAR IMGUI] commented double assignment
+
+ // make sure y never passes through a vertex of the shape
+ y_frac = (float) STBTT_fmod(y, 1.0f);
+ if (y_frac < 0.01f)
+ y += 0.01f;
+ else if (y_frac > 0.99f)
+ y -= 0.01f;
+ orig[1] = y;
+
+ // test a ray from (-infinity,y) to (x,y)
+ for (i=0; i < nverts; ++i) {
+ if (verts[i].type == STBTT_vline) {
+ int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y;
+ int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y;
+ if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
+ float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
+ if (x_inter < x)
+ winding += (y0 < y1) ? 1 : -1;
+ }
+ }
+ if (verts[i].type == STBTT_vcurve) {
+ int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ;
+ int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy;
+ int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ;
+ int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2));
+ int by = STBTT_max(y0,STBTT_max(y1,y2));
+ if (y > ay && y < by && x > ax) {
+ float q0[2],q1[2],q2[2];
+ float hits[2][2];
+ q0[0] = (float)x0;
+ q0[1] = (float)y0;
+ q1[0] = (float)x1;
+ q1[1] = (float)y1;
+ q2[0] = (float)x2;
+ q2[1] = (float)y2;
+ if (equal(q0,q1) || equal(q1,q2)) {
+ x0 = (int)verts[i-1].x;
+ y0 = (int)verts[i-1].y;
+ x1 = (int)verts[i ].x;
+ y1 = (int)verts[i ].y;
+ if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) {
+ float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0;
+ if (x_inter < x)
+ winding += (y0 < y1) ? 1 : -1;
+ }
+ } else {
+ int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits);
+ if (num_hits >= 1)
+ if (hits[0][0] < 0)
+ winding += (hits[0][1] < 0 ? -1 : 1);
+ if (num_hits >= 2)
+ if (hits[1][0] < 0)
+ winding += (hits[1][1] < 0 ? -1 : 1);
+ }
+ }
+ }
+ }
+ return winding;
+}
+
+static float stbtt__cuberoot( float x )
+{
+ if (x<0)
+ return -(float) STBTT_pow(-x,1.0f/3.0f);
+ else
+ return (float) STBTT_pow( x,1.0f/3.0f);
+}
+
+// x^3 + c*x^2 + b*x + a = 0
+static int stbtt__solve_cubic(float a, float b, float c, float* r)
+{
+ float s = -a / 3;
+ float p = b - a*a / 3;
+ float q = a * (2*a*a - 9*b) / 27 + c;
+ float p3 = p*p*p;
+ float d = q*q + 4*p3 / 27;
+ if (d >= 0) {
+ float z = (float) STBTT_sqrt(d);
+ float u = (-q + z) / 2;
+ float v = (-q - z) / 2;
+ u = stbtt__cuberoot(u);
+ v = stbtt__cuberoot(v);
+ r[0] = s + u + v;
+ return 1;
+ } else {
+ float u = (float) STBTT_sqrt(-p/3);
+ float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
+ float m = (float) STBTT_cos(v);
+ float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
+ r[0] = s + u * 2 * m;
+ r[1] = s - u * (m + n);
+ r[2] = s - u * (m - n);
+
+ //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
+ //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
+ //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
+ return 3;
+ }
+}
+
+STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
+{
+ float scale_x = scale, scale_y = scale;
+ int ix0,iy0,ix1,iy1;
+ int w,h;
+ unsigned char *data;
+
+ // if one scale is 0, use same scale for both
+ if (scale_x == 0) scale_x = scale_y;
+ if (scale_y == 0) {
+ if (scale_x == 0) return NULL; // if both scales are 0, return NULL
+ scale_y = scale_x;
+ }
+
+ stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1);
+
+ // if empty, return NULL
+ if (ix0 == ix1 || iy0 == iy1)
+ return NULL;
+
+ ix0 -= padding;
+ iy0 -= padding;
+ ix1 += padding;
+ iy1 += padding;
+
+ w = (ix1 - ix0);
+ h = (iy1 - iy0);
+
+ if (width ) *width = w;
+ if (height) *height = h;
+ if (xoff ) *xoff = ix0;
+ if (yoff ) *yoff = iy0;
+
+ // invert for y-downwards bitmaps
+ scale_y = -scale_y;
+
+ {
+ int x,y,i,j;
+ float *precompute;
+ stbtt_vertex *verts;
+ int num_verts = stbtt_GetGlyphShape(info, glyph, &verts);
+ data = (unsigned char *) STBTT_malloc(w * h, info->userdata);
+ precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata);
+
+ for (i=0,j=num_verts-1; i < num_verts; j=i++) {
+ if (verts[i].type == STBTT_vline) {
+ float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
+ float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
+ float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
+ precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
+ } else if (verts[i].type == STBTT_vcurve) {
+ float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
+ float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
+ float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
+ float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
+ float len2 = bx*bx + by*by;
+ if (len2 != 0.0f)
+ precompute[i] = 1.0f / (bx*bx + by*by);
+ else
+ precompute[i] = 0.0f;
+ } else
+ precompute[i] = 0.0f;
+ }
+
+ for (y=iy0; y < iy1; ++y) {
+ for (x=ix0; x < ix1; ++x) {
+ float val;
+ float min_dist = 999999.0f;
+ float sx = (float) x + 0.5f;
+ float sy = (float) y + 0.5f;
+ float x_gspace = (sx / scale_x);
+ float y_gspace = (sy / scale_y);
+
+ int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path
+
+ for (i=0; i < num_verts; ++i) {
+ float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
+
+ // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve
+ float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy);
+ if (dist2 < min_dist*min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+
+ if (verts[i].type == STBTT_vline) {
+ float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y;
+
+ // coarse culling against bbox
+ //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist &&
+ // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist)
+ float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i];
+ STBTT_assert(i != 0);
+ if (dist < min_dist) {
+ // check position along line
+ // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0)
+ // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy)
+ float dx = x1-x0, dy = y1-y0;
+ float px = x0-sx, py = y0-sy;
+ // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy
+ // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve
+ float t = -(px*dx + py*dy) / (dx*dx + dy*dy);
+ if (t >= 0.0f && t <= 1.0f)
+ min_dist = dist;
+ }
+ } else if (verts[i].type == STBTT_vcurve) {
+ float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y;
+ float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y;
+ float box_x0 = STBTT_min(STBTT_min(x0,x1),x2);
+ float box_y0 = STBTT_min(STBTT_min(y0,y1),y2);
+ float box_x1 = STBTT_max(STBTT_max(x0,x1),x2);
+ float box_y1 = STBTT_max(STBTT_max(y0,y1),y2);
+ // coarse culling against bbox to avoid computing cubic unnecessarily
+ if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) {
+ int num=0;
+ float ax = x1-x0, ay = y1-y0;
+ float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
+ float mx = x0 - sx, my = y0 - sy;
+ float res[3],px,py,t,it;
+ float a_inv = precompute[i];
+ if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula
+ float a = 3*(ax*bx + ay*by);
+ float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
+ float c = mx*ax+my*ay;
+ if (a == 0.0) { // if a is 0, it's linear
+ if (b != 0.0) {
+ res[num++] = -c/b;
+ }
+ } else {
+ float discriminant = b*b - 4*a*c;
+ if (discriminant < 0)
+ num = 0;
+ else {
+ float root = (float) STBTT_sqrt(discriminant);
+ res[0] = (-b - root)/(2*a);
+ res[1] = (-b + root)/(2*a);
+ num = 2; // don't bother distinguishing 1-solution case, as code below will still work
+ }
+ }
+ } else {
+ float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point
+ float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv;
+ float d = (mx*ax+my*ay) * a_inv;
+ num = stbtt__solve_cubic(b, c, d, res);
+ }
+ if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) {
+ t = res[0], it = 1.0f - t;
+ px = it*it*x0 + 2*t*it*x1 + t*t*x2;
+ py = it*it*y0 + 2*t*it*y1 + t*t*y2;
+ dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+ }
+ if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) {
+ t = res[1], it = 1.0f - t;
+ px = it*it*x0 + 2*t*it*x1 + t*t*x2;
+ py = it*it*y0 + 2*t*it*y1 + t*t*y2;
+ dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+ }
+ if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) {
+ t = res[2], it = 1.0f - t;
+ px = it*it*x0 + 2*t*it*x1 + t*t*x2;
+ py = it*it*y0 + 2*t*it*y1 + t*t*y2;
+ dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy);
+ if (dist2 < min_dist * min_dist)
+ min_dist = (float) STBTT_sqrt(dist2);
+ }
+ }
+ }
+ }
+ if (winding == 0)
+ min_dist = -min_dist; // if outside the shape, value is negative
+ val = onedge_value + pixel_dist_scale * min_dist;
+ if (val < 0)
+ val = 0;
+ else if (val > 255)
+ val = 255;
+ data[(y-iy0)*w+(x-ix0)] = (unsigned char) val;
+ }
+ }
+ STBTT_free(precompute, info->userdata);
+ STBTT_free(verts, info->userdata);
+ }
+ return data;
+}
+
+STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff)
+{
+ return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff);
+}
+
+STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata)
+{
+ STBTT_free(bitmap, userdata);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// font name matching -- recommended not to use this
+//
+
+// check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string
+static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2)
+{
+ stbtt_int32 i=0;
+
+ // convert utf16 to utf8 and compare the results while converting
+ while (len2) {
+ stbtt_uint16 ch = s2[0]*256 + s2[1];
+ if (ch < 0x80) {
+ if (i >= len1) return -1;
+ if (s1[i++] != ch) return -1;
+ } else if (ch < 0x800) {
+ if (i+1 >= len1) return -1;
+ if (s1[i++] != 0xc0 + (ch >> 6)) return -1;
+ if (s1[i++] != 0x80 + (ch & 0x3f)) return -1;
+ } else if (ch >= 0xd800 && ch < 0xdc00) {
+ stbtt_uint32 c;
+ stbtt_uint16 ch2 = s2[2]*256 + s2[3];
+ if (i+3 >= len1) return -1;
+ c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000;
+ if (s1[i++] != 0xf0 + (c >> 18)) return -1;
+ if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1;
+ if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1;
+ if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1;
+ s2 += 2; // plus another 2 below
+ len2 -= 2;
+ } else if (ch >= 0xdc00 && ch < 0xe000) {
+ return -1;
+ } else {
+ if (i+2 >= len1) return -1;
+ if (s1[i++] != 0xe0 + (ch >> 12)) return -1;
+ if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1;
+ if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1;
+ }
+ s2 += 2;
+ len2 -= 2;
+ }
+ return i;
+}
+
+static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2)
+{
+ return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2);
+}
+
+// returns results in whatever encoding you request... but note that 2-byte encodings
+// will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare
+STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID)
+{
+ stbtt_int32 i,count,stringOffset;
+ stbtt_uint8 *fc = font->data;
+ stbtt_uint32 offset = font->fontstart;
+ stbtt_uint32 nm = stbtt__find_table(fc, offset, "name");
+ if (!nm) return NULL;
+
+ count = ttUSHORT(fc+nm+2);
+ stringOffset = nm + ttUSHORT(fc+nm+4);
+ for (i=0; i < count; ++i) {
+ stbtt_uint32 loc = nm + 6 + 12 * i;
+ if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2)
+ && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) {
+ *length = ttUSHORT(fc+loc+8);
+ return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10));
+ }
+ }
+ return NULL;
+}
+
+static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id)
+{
+ stbtt_int32 i;
+ stbtt_int32 count = ttUSHORT(fc+nm+2);
+ stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4);
+
+ for (i=0; i < count; ++i) {
+ stbtt_uint32 loc = nm + 6 + 12 * i;
+ stbtt_int32 id = ttUSHORT(fc+loc+6);
+ if (id == target_id) {
+ // find the encoding
+ stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4);
+
+ // is this a Unicode encoding?
+ if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) {
+ stbtt_int32 slen = ttUSHORT(fc+loc+8);
+ stbtt_int32 off = ttUSHORT(fc+loc+10);
+
+ // check if there's a prefix match
+ stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen);
+ if (matchlen >= 0) {
+ // check for target_id+1 immediately following, with same encoding & language
+ if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) {
+ slen = ttUSHORT(fc+loc+12+8);
+ off = ttUSHORT(fc+loc+12+10);
+ if (slen == 0) {
+ if (matchlen == nlen)
+ return 1;
+ } else if (matchlen < nlen && name[matchlen] == ' ') {
+ ++matchlen;
+ if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen))
+ return 1;
+ }
+ } else {
+ // if nothing immediately following
+ if (matchlen == nlen)
+ return 1;
+ }
+ }
+ }
+
+ // @TODO handle other encodings
+ }
+ }
+ return 0;
+}
+
+static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags)
+{
+ stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name);
+ stbtt_uint32 nm,hd;
+ if (!stbtt__isfont(fc+offset)) return 0;
+
+ // check italics/bold/underline flags in macStyle...
+ if (flags) {
+ hd = stbtt__find_table(fc, offset, "head");
+ if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0;
+ }
+
+ nm = stbtt__find_table(fc, offset, "name");
+ if (!nm) return 0;
+
+ if (flags) {
+ // if we checked the macStyle flags, then just check the family and ignore the subfamily
+ if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
+ } else {
+ if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1;
+ if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1;
+ }
+
+ return 0;
+}
+
+static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags)
+{
+ stbtt_int32 i;
+ for (i=0;;++i) {
+ stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i);
+ if (off < 0) return off;
+ if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags))
+ return off;
+ }
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+
+STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
+ float pixel_height, unsigned char *pixels, int pw, int ph,
+ int first_char, int num_chars, stbtt_bakedchar *chardata)
+{
+ return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata);
+}
+
+STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index)
+{
+ return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index);
+}
+
+STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
+{
+ return stbtt_GetNumberOfFonts_internal((unsigned char *) data);
+}
+
+STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset)
+{
+ return stbtt_InitFont_internal(info, (unsigned char *) data, offset);
+}
+
+STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags)
+{
+ return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags);
+}
+
+STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2)
+{
+ return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2);
+}
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif // STB_TRUETYPE_IMPLEMENTATION
+
+
+// FULL VERSION HISTORY
+//
+// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod
+// 1.18 (2018-01-29) add missing function
+// 1.17 (2017-07-23) make more arguments const; doc fix
+// 1.16 (2017-07-12) SDF support
+// 1.15 (2017-03-03) make more arguments const
+// 1.14 (2017-01-16) num-fonts-in-TTC function
+// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts
+// 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual
+// 1.11 (2016-04-02) fix unused-variable warning
+// 1.10 (2016-04-02) allow user-defined fabs() replacement
+// fix memory leak if fontsize=0.0
+// fix warning from duplicate typedef
+// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
+// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
+// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
+// allow PackFontRanges to pack and render in separate phases;
+// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
+// fixed an assert() bug in the new rasterizer
+// replace assert() with STBTT_assert() in new rasterizer
+// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine)
+// also more precise AA rasterizer, except if shapes overlap
+// remove need for STBTT_sort
+// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC
+// 1.04 (2015-04-15) typo in example
+// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes
+// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++
+// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match
+// non-oversampled; STBTT_POINT_SIZE for packed case only
+// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling
+// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg)
+// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID
+// 0.8b (2014-07-07) fix a warning
+// 0.8 (2014-05-25) fix a few more warnings
+// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back
+// 0.6c (2012-07-24) improve documentation
+// 0.6b (2012-07-20) fix a few more warnings
+// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels,
+// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty
+// 0.5 (2011-12-09) bugfixes:
+// subpixel glyph renderer computed wrong bounding box
+// first vertex of shape can be off-curve (FreeSans)
+// 0.4b (2011-12-03) fixed an error in the font baking example
+// 0.4 (2011-12-01) kerning, subpixel rendering (tor)
+// bugfixes for:
+// codepoint-to-glyph conversion using table fmt=12
+// codepoint-to-glyph conversion using table fmt=4
+// stbtt_GetBakedQuad with non-square texture (Zer)
+// updated Hello World! sample to use kerning and subpixel
+// fixed some warnings
+// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM)
+// userdata, malloc-from-userdata, non-zero fill (stb)
+// 0.2 (2009-03-11) Fix unsigned/signed char warnings
+// 0.1 (2009-03-09) First public release
+//
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+------------------------------------------------------------------------------
+*/
diff --git a/Client/ThirdParty/imgui/misc/README.txt b/Client/ThirdParty/imgui/misc/README.txt
new file mode 100644
index 0000000..b4ce89f
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/README.txt
@@ -0,0 +1,23 @@
+
+misc/cpp/
+ InputText() wrappers for C++ standard library (STL) type: std::string.
+ This is also an example of how you may wrap your own similar types.
+
+misc/debuggers/
+ Helper files for popular debuggers.
+ With the .natvis file, types like ImVector<> will be displayed nicely in Visual Studio debugger.
+
+misc/fonts/
+ Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts).
+ Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code.
+ Suggested fonts and links.
+
+misc/freetype/
+ Font atlas builder/rasterizer using FreeType instead of stb_truetype.
+ Benefit from better FreeType rasterization, in particular for small fonts.
+
+misc/single_file/
+ Single-file header stub.
+ We use this to validate compiling all *.cpp files in a same compilation unit.
+ Users of that technique (also called "Unity builds") can generally provide this themselves,
+ so we don't really recommend you use this in your projects.
diff --git a/Client/ThirdParty/imgui/misc/cpp/README.txt b/Client/ThirdParty/imgui/misc/cpp/README.txt
new file mode 100644
index 0000000..4291590
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/cpp/README.txt
@@ -0,0 +1,13 @@
+
+imgui_stdlib.h + imgui_stdlib.cpp
+ InputText() wrappers for C++ standard library (STL) type: std::string.
+ This is also an example of how you may wrap your own similar types.
+
+imgui_scoped.h
+ [Experimental, not currently in main repository]
+ Additional header file with some RAII-style wrappers for common Dear ImGui functions.
+ Try by merging: https://github.com/ocornut/imgui/pull/2197
+ Discuss at: https://github.com/ocornut/imgui/issues/2096
+
+See more C++ related extension on Wiki
+ https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
diff --git a/Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.cpp b/Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.cpp
new file mode 100644
index 0000000..cb1fe17
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.cpp
@@ -0,0 +1,76 @@
+// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
+// This is also an example of how you may wrap your own similar types.
+
+// Compatibility:
+// - std::string support is only guaranteed to work from C++11.
+// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
+
+// Changelog:
+// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
+
+#include "imgui.h"
+#include "imgui_stdlib.h"
+
+struct InputTextCallback_UserData
+{
+ std::string* Str;
+ ImGuiInputTextCallback ChainCallback;
+ void* ChainCallbackUserData;
+};
+
+static int InputTextCallback(ImGuiInputTextCallbackData* data)
+{
+ InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData;
+ if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
+ {
+ // Resize string callback
+ // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want.
+ std::string* str = user_data->Str;
+ IM_ASSERT(data->Buf == str->c_str());
+ str->resize(data->BufTextLen);
+ data->Buf = (char*)str->c_str();
+ }
+ else if (user_data->ChainCallback)
+ {
+ // Forward to user callback, if any
+ data->UserData = user_data->ChainCallbackUserData;
+ return user_data->ChainCallback(data);
+ }
+ return 0;
+}
+
+bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
+ flags |= ImGuiInputTextFlags_CallbackResize;
+
+ InputTextCallback_UserData cb_user_data;
+ cb_user_data.Str = str;
+ cb_user_data.ChainCallback = callback;
+ cb_user_data.ChainCallbackUserData = user_data;
+ return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
+}
+
+bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
+ flags |= ImGuiInputTextFlags_CallbackResize;
+
+ InputTextCallback_UserData cb_user_data;
+ cb_user_data.Str = str;
+ cb_user_data.ChainCallback = callback;
+ cb_user_data.ChainCallbackUserData = user_data;
+ return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data);
+}
+
+bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
+{
+ IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
+ flags |= ImGuiInputTextFlags_CallbackResize;
+
+ InputTextCallback_UserData cb_user_data;
+ cb_user_data.Str = str;
+ cb_user_data.ChainCallback = callback;
+ cb_user_data.ChainCallbackUserData = user_data;
+ return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
+}
diff --git a/Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.h b/Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.h
new file mode 100644
index 0000000..f860b0c
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/cpp/imgui_stdlib.h
@@ -0,0 +1,22 @@
+// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
+// This is also an example of how you may wrap your own similar types.
+
+// Compatibility:
+// - std::string support is only guaranteed to work from C++11.
+// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
+
+// Changelog:
+// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
+
+#pragma once
+
+#include <string>
+
+namespace ImGui
+{
+ // ImGui::InputText() with std::string
+ // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
+ IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+ IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
+}
diff --git a/Client/ThirdParty/imgui/misc/debuggers/README.txt b/Client/ThirdParty/imgui/misc/debuggers/README.txt
new file mode 100644
index 0000000..3f4ba83
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/debuggers/README.txt
@@ -0,0 +1,16 @@
+
+HELPER FILES FOR POPULAR DEBUGGERS
+
+imgui.gdb
+ GDB: disable stepping into trivial functions.
+ (read comments inside file for details)
+
+imgui.natstepfilter
+ Visual Studio Debugger: disable stepping into trivial functions.
+ (read comments inside file for details)
+
+imgui.natvis
+ Visual Studio Debugger: describe Dear ImGui types for better display.
+ With this, types like ImVector<> will be displayed nicely in the debugger.
+ (read comments inside file for details)
+
diff --git a/Client/ThirdParty/imgui/misc/debuggers/imgui.gdb b/Client/ThirdParty/imgui/misc/debuggers/imgui.gdb
new file mode 100644
index 0000000..000ff6e
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/debuggers/imgui.gdb
@@ -0,0 +1,12 @@
+# GDB configuration to aid debugging experience
+
+# To enable these customizations edit $HOME/.gdbinit (or ./.gdbinit if local gdbinit is enabled) and add:
+# add-auto-load-safe-path /path/to/imgui.gdb
+# source /path/to/imgui.gdb
+#
+# More Information at:
+# * https://sourceware.org/gdb/current/onlinedocs/gdb/gdbinit-man.html
+# * https://sourceware.org/gdb/current/onlinedocs/gdb/Init-File-in-the-Current-Directory.html#Init-File-in-the-Current-Directory
+
+# Disable stepping into trivial functions
+skip -rfunction Im(Vec2|Vec4|Strv|Vector|Span)::.+
diff --git a/Client/ThirdParty/imgui/misc/debuggers/imgui.natstepfilter b/Client/ThirdParty/imgui/misc/debuggers/imgui.natstepfilter
new file mode 100644
index 0000000..efd1957
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/debuggers/imgui.natstepfilter
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+.natstepfilter file for Visual Studio debugger.
+Purpose: instruct debugger to skip some functions when using StepInto (F11)
+
+To enable:
+* copy in %USERPROFILE%\Documents\Visual Studio XXXX\Visualizers (current user)
+* or copy in %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers (all users)
+If you have multiple VS version installed, the version that matters is the one you are using the IDE/debugger of (not the compiling toolset).
+This is supported since Visual Studio 2012.
+
+Unfortunately, unlike .natvis files, it isn't yet possible to include this file in your project :(
+You may upvote this: https://developercommunity.visualstudio.com/t/allow-natstepfilter-and-natjmc-to-be-included-as-p/561718
+
+More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2019#BKMK_C___Just_My_Code
+-->
+
+<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
+
+ <!-- Disable stepping into trivial functions -->
+ <Function>
+ <Name>(ImVec2|ImVec4|ImStrv)::.+</Name>
+ <Action>NoStepInto</Action>
+ </Function>
+ <Function>
+ <Name>(ImVector|ImSpan).*::operator.+</Name>
+ <Action>NoStepInto</Action>
+ </Function>
+
+</StepFilter>
diff --git a/Client/ThirdParty/imgui/misc/debuggers/imgui.natvis b/Client/ThirdParty/imgui/misc/debuggers/imgui.natvis
new file mode 100644
index 0000000..13b6360
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/debuggers/imgui.natvis
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+.natvis file for Visual Studio debugger.
+Purpose: provide nicer views on data types used by Dear ImGui.
+
+To enable:
+* include file in your VS project (most recommended: not intrusive and always kept up to date!)
+* or copy in %USERPROFILE%\Documents\Visual Studio XXXX\Visualizers (current user)
+* or copy in %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers (all users)
+
+More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019
+-->
+
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+
+<Type Name="ImVector&lt;*&gt;">
+ <DisplayString>{{Size={Size} Capacity={Capacity}}}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>Size</Size>
+ <ValuePointer>Data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+</Type>
+
+<Type Name="ImSpan&lt;*&gt;">
+ <DisplayString>{{Size={DataEnd-Data} }}</DisplayString>
+ <Expand>
+ <ArrayItems>
+ <Size>DataEnd-Data</Size>
+ <ValuePointer>Data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+</Type>
+
+<Type Name="ImVec2">
+ <DisplayString>{{x={x,g} y={y,g}}}</DisplayString>
+</Type>
+
+<Type Name="ImVec4">
+ <DisplayString>{{x={x,g} y={y,g} z={z,g} w={w,g}}}</DisplayString>
+</Type>
+
+<Type Name="ImRect">
+ <DisplayString>{{Min=({Min.x,g} {Min.y,g}) Max=({Max.x,g} {Max.y,g}) Size=({Max.x-Min.x,g} {Max.y-Min.y,g})}}</DisplayString>
+ <Expand>
+ <Item Name="Min">Min</Item>
+ <Item Name="Max">Max</Item>
+ <Item Name="[Width]">Max.x - Min.x</Item>
+ <Item Name="[Height]">Max.y - Min.y</Item>
+ </Expand>
+</Type>
+
+<Type Name="ImGuiWindow">
+ <DisplayString>{{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags &amp; 0x01000000)?1:0,d} Popup {(Flags &amp; 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}}</DisplayString>
+</Type>
+
+</AutoVisualizer>
diff --git a/Client/ThirdParty/imgui/misc/fonts/Cousine-Regular.ttf b/Client/ThirdParty/imgui/misc/fonts/Cousine-Regular.ttf
new file mode 100644
index 0000000..70a0bf9
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/Cousine-Regular.ttf
Binary files differ
diff --git a/Client/ThirdParty/imgui/misc/fonts/DroidSans.ttf b/Client/ThirdParty/imgui/misc/fonts/DroidSans.ttf
new file mode 100644
index 0000000..767c63a
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/DroidSans.ttf
Binary files differ
diff --git a/Client/ThirdParty/imgui/misc/fonts/Karla-Regular.ttf b/Client/ThirdParty/imgui/misc/fonts/Karla-Regular.ttf
new file mode 100644
index 0000000..81b3de6
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/Karla-Regular.ttf
Binary files differ
diff --git a/Client/ThirdParty/imgui/misc/fonts/ProggyClean.ttf b/Client/ThirdParty/imgui/misc/fonts/ProggyClean.ttf
new file mode 100644
index 0000000..0270cdf
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/ProggyClean.ttf
Binary files differ
diff --git a/Client/ThirdParty/imgui/misc/fonts/ProggyTiny.ttf b/Client/ThirdParty/imgui/misc/fonts/ProggyTiny.ttf
new file mode 100644
index 0000000..1c4312c
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/ProggyTiny.ttf
Binary files differ
diff --git a/Client/ThirdParty/imgui/misc/fonts/Roboto-Medium.ttf b/Client/ThirdParty/imgui/misc/fonts/Roboto-Medium.ttf
new file mode 100644
index 0000000..39c63d7
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/Roboto-Medium.ttf
Binary files differ
diff --git a/Client/ThirdParty/imgui/misc/fonts/binary_to_compressed_c.cpp b/Client/ThirdParty/imgui/misc/fonts/binary_to_compressed_c.cpp
new file mode 100644
index 0000000..441c8f6
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/fonts/binary_to_compressed_c.cpp
@@ -0,0 +1,385 @@
+// dear imgui
+// (binary_to_compressed_c.cpp)
+// Helper tool to turn a file into a C array, if you want to embed font data in your source code.
+
+// The data is first compressed with stb_compress() to reduce source code size,
+// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
+// (If we used 32-bit constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent)
+// Note that even with compression, the output array is likely to be bigger than the binary file..
+// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
+
+// Build with, e.g:
+// # cl.exe binary_to_compressed_c.cpp
+// # g++ binary_to_compressed_c.cpp
+// # clang++ binary_to_compressed_c.cpp
+// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
+
+// Usage:
+// binary_to_compressed_c.exe [-base85] [-nocompress] <inputfile> <symbolname>
+// Usage example:
+// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp
+// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp
+
+#define _CRT_SECURE_NO_WARNINGS
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+// stb_compress* from stb.h - declaration
+typedef unsigned int stb_uint;
+typedef unsigned char stb_uchar;
+stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len);
+
+static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression);
+
+int main(int argc, char** argv)
+{
+ if (argc < 3)
+ {
+ printf("Syntax: %s [-base85] [-nocompress] <inputfile> <symbolname>\n", argv[0]);
+ return 0;
+ }
+
+ int argn = 1;
+ bool use_base85_encoding = false;
+ bool use_compression = true;
+ if (argv[argn][0] == '-')
+ {
+ if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; }
+ else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
+ else
+ {
+ fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]);
+ return 1;
+ }
+ }
+
+ bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression);
+ if (!ret)
+ fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
+ return ret ? 0 : 1;
+}
+
+char Encode85Byte(unsigned int x)
+{
+ x = (x % 85) + 35;
+ return (x >= '\\') ? x + 1 : x;
+}
+
+bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression)
+{
+ // Read file
+ FILE* f = fopen(filename, "rb");
+ if (!f) return false;
+ int data_sz;
+ if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; }
+ char* data = new char[data_sz + 4];
+ if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; }
+ memset((void*)(((char*)data) + data_sz), 0, 4);
+ fclose(f);
+
+ // Compress
+ int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess
+ char* compressed = use_compression ? new char[maxlen] : data;
+ int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz;
+ if (use_compression)
+ memset(compressed + compressed_sz, 0, maxlen - compressed_sz);
+
+ // Output as Base85 encoded
+ FILE* out = stdout;
+ fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
+ fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
+ const char* compressed_str = use_compression ? "compressed_" : "";
+ if (use_base85_encoding)
+ {
+ fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
+ char prev_c = 0;
+ for (int src_i = 0; src_i < compressed_sz; src_i += 4)
+ {
+ // This is made a little more complicated by the fact that ??X sequences are interpreted as trigraphs by old C/C++ compilers. So we need to escape pairs of ??.
+ unsigned int d = *(unsigned int*)(compressed + src_i);
+ for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85)
+ {
+ char c = Encode85Byte(d);
+ fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c);
+ prev_c = c;
+ }
+ if ((src_i % 112) == 112 - 4)
+ fprintf(out, "\"\n \"");
+ }
+ fprintf(out, "\";\n\n");
+ }
+ else
+ {
+ fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz);
+ fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
+ int column = 0;
+ for (int i = 0; i < compressed_sz; i += 4)
+ {
+ unsigned int d = *(unsigned int*)(compressed + i);
+ if ((column++ % 12) == 0)
+ fprintf(out, "\n 0x%08x, ", d);
+ else
+ fprintf(out, "0x%08x, ", d);
+ }
+ fprintf(out, "\n};\n\n");
+ }
+
+ // Cleanup
+ delete[] data;
+ if (use_compression)
+ delete[] compressed;
+ return true;
+}
+
+// stb_compress* from stb.h - definition
+
+//////////////////// compressor ///////////////////////
+
+static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen)
+{
+ const unsigned long ADLER_MOD = 65521;
+ unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
+ unsigned long blocklen, i;
+
+ blocklen = buflen % 5552;
+ while (buflen) {
+ for (i=0; i + 7 < blocklen; i += 8) {
+ s1 += buffer[0], s2 += s1;
+ s1 += buffer[1], s2 += s1;
+ s1 += buffer[2], s2 += s1;
+ s1 += buffer[3], s2 += s1;
+ s1 += buffer[4], s2 += s1;
+ s1 += buffer[5], s2 += s1;
+ s1 += buffer[6], s2 += s1;
+ s1 += buffer[7], s2 += s1;
+
+ buffer += 8;
+ }
+
+ for (; i < blocklen; ++i)
+ s1 += *buffer++, s2 += s1;
+
+ s1 %= ADLER_MOD, s2 %= ADLER_MOD;
+ buflen -= blocklen;
+ blocklen = 5552;
+ }
+ return (s2 << 16) + s1;
+}
+
+static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
+{
+ stb_uint i;
+ for (i=0; i < maxlen; ++i)
+ if (m1[i] != m2[i]) return i;
+ return i;
+}
+
+// simple implementation that just takes the source data in a big block
+
+static stb_uchar *stb__out;
+static FILE *stb__outfile;
+static stb_uint stb__outbytes;
+
+static void stb__write(unsigned char v)
+{
+ fputc(v, stb__outfile);
+ ++stb__outbytes;
+}
+
+//#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v)))
+#define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0)
+
+static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); }
+static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
+static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); }
+
+static void outliterals(stb_uchar *in, int numlit)
+{
+ while (numlit > 65536) {
+ outliterals(in,65536);
+ in += 65536;
+ numlit -= 65536;
+ }
+
+ if (numlit == 0) ;
+ else if (numlit <= 32) stb_out (0x000020 + numlit-1);
+ else if (numlit <= 2048) stb_out2(0x000800 + numlit-1);
+ else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1);
+
+ if (stb__out) {
+ memcpy(stb__out,in,numlit);
+ stb__out += numlit;
+ } else
+ fwrite(in, 1, numlit, stb__outfile);
+}
+
+static int stb__window = 0x40000; // 256K
+
+static int stb_not_crap(int best, int dist)
+{
+ return ((best > 2 && dist <= 0x00100)
+ || (best > 5 && dist <= 0x04000)
+ || (best > 7 && dist <= 0x80000));
+}
+
+static stb_uint stb__hashsize = 32768;
+
+// note that you can play with the hashing functions all you
+// want without needing to change the decompressor
+#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
+#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
+#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
+
+static unsigned int stb__running_adler;
+
+static int stb_compress_chunk(stb_uchar *history,
+ stb_uchar *start,
+ stb_uchar *end,
+ int length,
+ int *pending_literals,
+ stb_uchar **chash,
+ stb_uint mask)
+{
+ (void)history;
+ int window = stb__window;
+ stb_uint match_max;
+ stb_uchar *lit_start = start - *pending_literals;
+ stb_uchar *q = start;
+
+#define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
+
+ // stop short of the end so we don't scan off the end doing
+ // the hashing; this means we won't compress the last few bytes
+ // unless they were part of something longer
+ while (q < start+length && q+12 < end) {
+ int m;
+ stb_uint h1,h2,h3,h4, h;
+ stb_uchar *t;
+ int best = 2, dist=0;
+
+ if (q+65536 > end)
+ match_max = end-q;
+ else
+ match_max = 65536;
+
+#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
+
+#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
+ if (p ? dist != q-t : 1) \
+ if ((m = stb_matchlen(t, q, match_max)) > best) \
+ if (stb__nc(m,q-(t))) \
+ best = m, dist = q - (t)
+
+ // rather than search for all matches, only try 4 candidate locations,
+ // chosen based on 4 different hash functions of different lengths.
+ // this strategy is inspired by LZO; hashing is unrolled here using the
+ // 'hc' macro
+ h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
+ t = chash[h1]; if (t) STB__TRY(t,0);
+ h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
+ h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
+ h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
+ h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
+ h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
+ t = chash[h4]; if (t) STB__TRY(t,1);
+
+ // because we use a shared hash table, can only update it
+ // _after_ we've probed all of them
+ chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
+
+ if (best > 2)
+ assert(dist > 0);
+
+ // see if our best match qualifies
+ if (best < 3) { // fast path literals
+ ++q;
+ } else if (best > 2 && best <= 0x80 && dist <= 0x100) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out(0x80 + best-1);
+ stb_out(dist-1);
+ } else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out2(0x4000 + dist-1);
+ stb_out(best-1);
+ } else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out3(0x180000 + dist-1);
+ stb_out(best-1);
+ } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ stb_out3(0x100000 + dist-1);
+ stb_out2(best-1);
+ } else if (best > 9 && dist <= 0x1000000) {
+ if (best > 65536) best = 65536;
+ outliterals(lit_start, q-lit_start); lit_start = (q += best);
+ if (best <= 0x100) {
+ stb_out(0x06);
+ stb_out3(dist-1);
+ stb_out(best-1);
+ } else {
+ stb_out(0x04);
+ stb_out3(dist-1);
+ stb_out2(best-1);
+ }
+ } else { // fallback literals if no match was a balanced tradeoff
+ ++q;
+ }
+ }
+
+ // if we didn't get all the way, add the rest to literals
+ if (q-start < length)
+ q = start+length;
+
+ // the literals are everything from lit_start to q
+ *pending_literals = (q - lit_start);
+
+ stb__running_adler = stb_adler32(stb__running_adler, start, q - start);
+ return q - start;
+}
+
+static int stb_compress_inner(stb_uchar *input, stb_uint length)
+{
+ int literals = 0;
+ stb_uint len,i;
+
+ stb_uchar **chash;
+ chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
+ if (chash == NULL) return 0; // failure
+ for (i=0; i < stb__hashsize; ++i)
+ chash[i] = NULL;
+
+ // stream signature
+ stb_out(0x57); stb_out(0xbc);
+ stb_out2(0);
+
+ stb_out4(0); // 64-bit length requires 32-bit leading 0
+ stb_out4(length);
+ stb_out4(stb__window);
+
+ stb__running_adler = 1;
+
+ len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
+ assert(len == length);
+
+ outliterals(input+length - literals, literals);
+
+ free(chash);
+
+ stb_out2(0x05fa); // end opcode
+
+ stb_out4(stb__running_adler);
+
+ return 1; // success
+}
+
+stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
+{
+ stb__out = out;
+ stb__outfile = NULL;
+
+ stb_compress_inner(input, length);
+
+ return stb__out - out;
+}
diff --git a/Client/ThirdParty/imgui/misc/freetype/README.md b/Client/ThirdParty/imgui/misc/freetype/README.md
new file mode 100644
index 0000000..f7d7bab
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/freetype/README.md
@@ -0,0 +1,37 @@
+# imgui_freetype
+
+Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer).
+<br>by @vuhdo, @mikesart, @ocornut.
+
+### Usage
+
+1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`).
+2. Add imgui_freetype.h/cpp alongside your project files.
+3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file
+
+### About Gamma Correct Blending
+
+FreeType assumes blending in linear space rather than gamma space.
+See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph).
+For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
+The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking).
+
+### Testbed for toying with settings (for developers)
+
+See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad
+
+### Known issues
+
+- Oversampling settins are ignored but also not so much necessary with the higher quality rendering.
+
+### Comparaison
+
+Small, thin anti-aliased fonts are typically benefiting a lots from Freetype's hinting:
+![comparing_font_rasterizers](https://user-images.githubusercontent.com/8225057/107550178-fef87f00-6bd0-11eb-8d09-e2edb2f0ccfc.gif)
+
+### Colorful glyphs/emojis
+
+You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain colorful glyphs. See
+["Using Colorful Glyphs/Emojis"](https://github.com/ocornut/imgui/edit/master/docs/FONTS.md#using-colorful-glyphsemojis) section of FONTS.md.
+
+![colored glyphs](https://user-images.githubusercontent.com/8225057/106171241-9dc4ba80-6191-11eb-8a69-ca1467b206d1.png)
diff --git a/Client/ThirdParty/imgui/misc/freetype/imgui_freetype.cpp b/Client/ThirdParty/imgui/misc/freetype/imgui_freetype.cpp
new file mode 100644
index 0000000..a72ec8c
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/freetype/imgui_freetype.cpp
@@ -0,0 +1,779 @@
+// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder)
+// (code)
+
+// Get the latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
+// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained since 2019 by @ocornut.
+
+// CHANGELOG
+// (minor and older changes stripped away, please see git history for details)
+// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
+// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
+// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
+// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
+// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
+// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
+// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
+// 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
+// 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
+// 2019/01/10: re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
+// 2018/06/08: added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX.
+// 2018/02/04: moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club)
+// 2018/01/22: fix for addition of ImFontAtlas::TexUvscale member.
+// 2017/10/22: minor inconsequential change to match change in master (removed an unnecessary statement).
+// 2017/09/26: fixes for imgui internal changes.
+// 2017/08/26: cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply.
+// 2017/08/16: imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks.
+
+// About Gamma Correct Blending:
+// - FreeType assumes blending in linear space rather than gamma space.
+// - See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph
+// - For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
+// - The default dear imgui styles will be impacted by this change (alpha values will need tweaking).
+
+// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
+
+#include "imgui_freetype.h"
+#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*,
+#include <stdint.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H // <freetype/freetype.h>
+#include FT_MODULE_H // <freetype/ftmodapi.h>
+#include FT_GLYPH_H // <freetype/ftglyph.h>
+#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
+
+#ifdef _MSC_VER
+#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
+#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
+#endif
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
+#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
+#endif
+
+//-------------------------------------------------------------------------
+// Data
+//-------------------------------------------------------------------------
+
+// Default memory allocators
+static void* ImGuiFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); }
+static void ImGuiFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
+
+// Current memory allocators
+static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFreeTypeDefaultAllocFunc;
+static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
+static void* GImGuiFreeTypeAllocatorUserData = NULL;
+
+//-------------------------------------------------------------------------
+// Code
+//-------------------------------------------------------------------------
+
+namespace
+{
+ // Glyph metrics:
+ // --------------
+ //
+ // xmin xmax
+ // | |
+ // |<-------- width -------->|
+ // | |
+ // | +-------------------------+----------------- ymax
+ // | | ggggggggg ggggg | ^ ^
+ // | | g:::::::::ggg::::g | | |
+ // | | g:::::::::::::::::g | | |
+ // | | g::::::ggggg::::::gg | | |
+ // | | g:::::g g:::::g | | |
+ // offsetX -|-------->| g:::::g g:::::g | offsetY |
+ // | | g:::::g g:::::g | | |
+ // | | g::::::g g:::::g | | |
+ // | | g:::::::ggggg:::::g | | |
+ // | | g::::::::::::::::g | | height
+ // | | gg::::::::::::::g | | |
+ // baseline ---*---------|---- gggggggg::::::g-----*-------- |
+ // / | | g:::::g | |
+ // origin | | gggggg g:::::g | |
+ // | | g:::::gg gg:::::g | |
+ // | | g::::::ggg:::::::g | |
+ // | | gg:::::::::::::g | |
+ // | | ggg::::::ggg | |
+ // | | gggggg | v
+ // | +-------------------------+----------------- ymin
+ // | |
+ // |------------- advanceX ----------->|
+
+ // A structure that describe a glyph.
+ struct GlyphInfo
+ {
+ int Width; // Glyph's width in pixels.
+ int Height; // Glyph's height in pixels.
+ FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph.
+ FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0.
+ float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
+ bool IsColored; // The glyph is colored
+ };
+
+ // Font parameters and metrics.
+ struct FontInfo
+ {
+ uint32_t PixelHeight; // Size this font was generated with.
+ float Ascender; // The pixel extents above the baseline in pixels (typically positive).
+ float Descender; // The extents below the baseline in pixels (typically negative).
+ float LineSpacing; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate.
+ float LineGap; // The spacing in pixels between one row's descent and the next row's ascent.
+ float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font.
+ };
+
+ // FreeType glyph rasterizer.
+ // NB: No ctor/dtor, explicitly call Init()/Shutdown()
+ struct FreeTypeFont
+ {
+ bool InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime.
+ void CloseFont();
+ void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size
+ const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
+ const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
+ void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
+ ~FreeTypeFont() { CloseFont(); }
+
+ // [Internals]
+ FontInfo Info; // Font descriptor of the current font.
+ FT_Face Face;
+ unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
+ FT_Int32 LoadFlags;
+ FT_Render_Mode RenderMode;
+ };
+
+ // From SDL_ttf: Handy routines for converting from fixed point
+ #define FT_CEIL(X) (((X + 63) & -64) / 64)
+
+ bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags)
+ {
+ FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face);
+ if (error != 0)
+ return false;
+ error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE);
+ if (error != 0)
+ return false;
+
+ // Convert to FreeType flags (NB: Bold and Oblique are processed separately)
+ UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags;
+
+ LoadFlags = 0;
+ if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0)
+ LoadFlags |= FT_LOAD_NO_BITMAP;
+
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting)
+ LoadFlags |= FT_LOAD_NO_HINTING;
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint)
+ LoadFlags |= FT_LOAD_NO_AUTOHINT;
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_ForceAutoHint)
+ LoadFlags |= FT_LOAD_FORCE_AUTOHINT;
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_LightHinting)
+ LoadFlags |= FT_LOAD_TARGET_LIGHT;
+ else if (UserFlags & ImGuiFreeTypeBuilderFlags_MonoHinting)
+ LoadFlags |= FT_LOAD_TARGET_MONO;
+ else
+ LoadFlags |= FT_LOAD_TARGET_NORMAL;
+
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_Monochrome)
+ RenderMode = FT_RENDER_MODE_MONO;
+ else
+ RenderMode = FT_RENDER_MODE_NORMAL;
+
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
+ LoadFlags |= FT_LOAD_COLOR;
+
+ memset(&Info, 0, sizeof(Info));
+ SetPixelHeight((uint32_t)cfg.SizePixels);
+
+ return true;
+ }
+
+ void FreeTypeFont::CloseFont()
+ {
+ if (Face)
+ {
+ FT_Done_Face(Face);
+ Face = NULL;
+ }
+ }
+
+ void FreeTypeFont::SetPixelHeight(int pixel_height)
+ {
+ // Vuhdo: I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
+ // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
+ // NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result.
+ FT_Size_RequestRec req;
+ req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
+ req.width = 0;
+ req.height = (uint32_t)pixel_height * 64;
+ req.horiResolution = 0;
+ req.vertResolution = 0;
+ FT_Request_Size(Face, &req);
+
+ // Update font info
+ FT_Size_Metrics metrics = Face->size->metrics;
+ Info.PixelHeight = (uint32_t)pixel_height;
+ Info.Ascender = (float)FT_CEIL(metrics.ascender);
+ Info.Descender = (float)FT_CEIL(metrics.descender);
+ Info.LineSpacing = (float)FT_CEIL(metrics.height);
+ Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender);
+ Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance);
+ }
+
+ const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint)
+ {
+ uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint);
+ if (glyph_index == 0)
+ return NULL;
+
+ // If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts.
+ // - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076
+ // - https://github.com/ocornut/imgui/issues/4567
+ // - https://github.com/ocornut/imgui/issues/4566
+ // You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version.
+ FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags);
+ if (error)
+ return NULL;
+
+ // Need an outline for this to work
+ FT_GlyphSlot slot = Face->glyph;
+ IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
+
+ // Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
+ FT_GlyphSlot_Embolden(slot);
+ if (UserFlags & ImGuiFreeTypeBuilderFlags_Oblique)
+ {
+ FT_GlyphSlot_Oblique(slot);
+ //FT_BBox bbox;
+ //FT_Outline_Get_BBox(&slot->outline, &bbox);
+ //slot->metrics.width = bbox.xMax - bbox.xMin;
+ //slot->metrics.height = bbox.yMax - bbox.yMin;
+ }
+
+ return &slot->metrics;
+ }
+
+ const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info)
+ {
+ FT_GlyphSlot slot = Face->glyph;
+ FT_Error error = FT_Render_Glyph(slot, RenderMode);
+ if (error != 0)
+ return NULL;
+
+ FT_Bitmap* ft_bitmap = &Face->glyph->bitmap;
+ out_glyph_info->Width = (int)ft_bitmap->width;
+ out_glyph_info->Height = (int)ft_bitmap->rows;
+ out_glyph_info->OffsetX = Face->glyph->bitmap_left;
+ out_glyph_info->OffsetY = -Face->glyph->bitmap_top;
+ out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x);
+ out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA);
+
+ return ft_bitmap;
+ }
+
+ void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
+ {
+ IM_ASSERT(ft_bitmap != NULL);
+ const uint32_t w = ft_bitmap->width;
+ const uint32_t h = ft_bitmap->rows;
+ const uint8_t* src = ft_bitmap->buffer;
+ const uint32_t src_pitch = ft_bitmap->pitch;
+
+ switch (ft_bitmap->pixel_mode)
+ {
+ case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel.
+ {
+ if (multiply_table == NULL)
+ {
+ for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
+ for (uint32_t x = 0; x < w; x++)
+ dst[x] = IM_COL32(255, 255, 255, src[x]);
+ }
+ else
+ {
+ for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
+ for (uint32_t x = 0; x < w; x++)
+ dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]);
+ }
+ break;
+ }
+ case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
+ {
+ uint8_t color0 = multiply_table ? multiply_table[0] : 0;
+ uint8_t color1 = multiply_table ? multiply_table[255] : 255;
+ for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
+ {
+ uint8_t bits = 0;
+ const uint8_t* bits_ptr = src;
+ for (uint32_t x = 0; x < w; x++, bits <<= 1)
+ {
+ if ((x & 7) == 0)
+ bits = *bits_ptr++;
+ dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0);
+ }
+ }
+ break;
+ }
+ case FT_PIXEL_MODE_BGRA:
+ {
+ // FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good.
+ #define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
+ if (multiply_table == NULL)
+ {
+ for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
+ for (uint32_t x = 0; x < w; x++)
+ {
+ uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
+ dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a);
+ }
+ }
+ else
+ {
+ for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
+ {
+ for (uint32_t x = 0; x < w; x++)
+ {
+ uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
+ dst[x] = IM_COL32(multiply_table[DE_MULTIPLY(r, a)], multiply_table[DE_MULTIPLY(g, a)], multiply_table[DE_MULTIPLY(b, a)], multiply_table[a]);
+ }
+ }
+ }
+ #undef DE_MULTIPLY
+ break;
+ }
+ default:
+ IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
+ }
+ }
+}
+
+#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
+#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
+#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0)
+#define STBRP_STATIC
+#define STB_RECT_PACK_IMPLEMENTATION
+#endif
+#ifdef IMGUI_STB_RECT_PACK_FILENAME
+#include IMGUI_STB_RECT_PACK_FILENAME
+#else
+#include "imstb_rectpack.h"
+#endif
+#endif
+
+struct ImFontBuildSrcGlyphFT
+{
+ GlyphInfo Info;
+ uint32_t Codepoint;
+ unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
+
+ ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); }
+};
+
+struct ImFontBuildSrcDataFT
+{
+ FreeTypeFont Font;
+ stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position.
+ const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF)
+ int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[]
+ int GlyphsHighest; // Highest requested codepoint
+ int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font)
+ ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB)
+ ImVector<ImFontBuildSrcGlyphFT> GlyphsList;
+};
+
+// Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont)
+struct ImFontBuildDstDataFT
+{
+ int SrcCount; // Number of source fonts targeting this destination font.
+ int GlyphsHighest;
+ int GlyphsCount;
+ ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font.
+};
+
+bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags)
+{
+ IM_ASSERT(atlas->ConfigData.Size > 0);
+
+ ImFontAtlasBuildInit(atlas);
+
+ // Clear atlas
+ atlas->TexID = (ImTextureID)NULL;
+ atlas->TexWidth = atlas->TexHeight = 0;
+ atlas->TexUvScale = ImVec2(0.0f, 0.0f);
+ atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
+ atlas->ClearTexData();
+
+ // Temporary storage for building
+ bool src_load_color = false;
+ ImVector<ImFontBuildSrcDataFT> src_tmp_array;
+ ImVector<ImFontBuildDstDataFT> dst_tmp_array;
+ src_tmp_array.resize(atlas->ConfigData.Size);
+ dst_tmp_array.resize(atlas->Fonts.Size);
+ memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes());
+ memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes());
+
+ // 1. Initialize font loading structure, check font data validity
+ for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++)
+ {
+ ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ FreeTypeFont& font_face = src_tmp.Font;
+ IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));
+
+ // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices)
+ src_tmp.DstIndex = -1;
+ for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++)
+ if (cfg.DstFont == atlas->Fonts[output_i])
+ src_tmp.DstIndex = output_i;
+ IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array?
+ if (src_tmp.DstIndex == -1)
+ return false;
+
+ // Load font
+ if (!font_face.InitFont(ft_library, cfg, extra_flags))
+ return false;
+
+ // Measure highest codepoints
+ src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0;
+ ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
+ src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
+ for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
+ src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]);
+ dst_tmp.SrcCount++;
+ dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest);
+ }
+
+ // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs.
+ int total_glyphs_count = 0;
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
+ ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
+ src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1);
+ if (dst_tmp.GlyphsSet.Storage.empty())
+ dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1);
+
+ for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
+ for (int codepoint = src_range[0]; codepoint <= (int)src_range[1]; codepoint++)
+ {
+ if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
+ continue;
+ uint32_t glyph_index = FT_Get_Char_Index(src_tmp.Font.Face, codepoint); // It is actually in the font? (FIXME-OPT: We are not storing the glyph_index..)
+ if (glyph_index == 0)
+ continue;
+
+ // Add to avail set/counters
+ src_tmp.GlyphsCount++;
+ dst_tmp.GlyphsCount++;
+ src_tmp.GlyphsSet.SetBit(codepoint);
+ dst_tmp.GlyphsSet.SetBit(codepoint);
+ total_glyphs_count++;
+ }
+ }
+
+ // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another)
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
+ src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount);
+
+ IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(ImU32));
+ const ImU32* it_begin = src_tmp.GlyphsSet.Storage.begin();
+ const ImU32* it_end = src_tmp.GlyphsSet.Storage.end();
+ for (const ImU32* it = it_begin; it < it_end; it++)
+ if (ImU32 entries_32 = *it)
+ for (ImU32 bit_n = 0; bit_n < 32; bit_n++)
+ if (entries_32 & ((ImU32)1 << bit_n))
+ {
+ ImFontBuildSrcGlyphFT src_glyph;
+ src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n);
+ //src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it..
+ src_tmp.GlyphsList.push_back(src_glyph);
+ }
+ src_tmp.GlyphsSet.Clear();
+ IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount);
+ }
+ for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++)
+ dst_tmp_array[dst_i].GlyphsSet.Clear();
+ dst_tmp_array.clear();
+
+ // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
+ // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity)
+ ImVector<stbrp_rect> buf_rects;
+ buf_rects.resize(total_glyphs_count);
+ memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes());
+
+ // Allocate temporary rasterization data buffers.
+ // We could not find a way to retrieve accurate glyph size without rendering them.
+ // (e.g. slot->metrics->width not always matching bitmap->width, especially considering the Oblique transform)
+ // We allocate in chunks of 256 KB to not waste too much extra memory ahead. Hopefully users of FreeType won't find the temporary allocations.
+ const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024;
+ int buf_bitmap_current_used_bytes = 0;
+ ImVector<unsigned char*> buf_bitmap_buffers;
+ buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
+
+ // 4. Gather glyphs sizes so we can pack them in our virtual canvas.
+ // 8. Render/rasterize font characters into the texture
+ int total_surface = 0;
+ int buf_rects_out_n = 0;
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ src_tmp.Rects = &buf_rects[buf_rects_out_n];
+ buf_rects_out_n += src_tmp.GlyphsCount;
+
+ // Compute multiply table if requested
+ const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f);
+ unsigned char multiply_table[256];
+ if (multiply_enabled)
+ ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply);
+
+ // Gather the sizes of all rectangles we will need to pack
+ const int padding = atlas->TexGlyphPadding;
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++)
+ {
+ ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
+
+ const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint);
+ if (metrics == NULL)
+ continue;
+
+ // Render glyph into a bitmap (currently held by FreeType)
+ const FT_Bitmap* ft_bitmap = src_tmp.Font.RenderGlyphAndGetInfo(&src_glyph.Info);
+ if (ft_bitmap == NULL)
+ continue;
+
+ // Allocate new temporary chunk if needed
+ const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4;
+ if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
+ {
+ buf_bitmap_current_used_bytes = 0;
+ buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
+ }
+
+ // Blit rasterized pixels to our temporary buffer and keep a pointer to it.
+ src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes);
+ buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
+ src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : NULL);
+
+ src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding);
+ src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding);
+ total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h;
+ }
+ }
+
+ // We need a width for the skyline algorithm, any width!
+ // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
+ // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface.
+ const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1;
+ atlas->TexHeight = 0;
+ if (atlas->TexDesiredWidth > 0)
+ atlas->TexWidth = atlas->TexDesiredWidth;
+ else
+ atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512;
+
+ // 5. Start packing
+ // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
+ const int TEX_HEIGHT_MAX = 1024 * 32;
+ const int num_nodes_for_packing_algorithm = atlas->TexWidth - atlas->TexGlyphPadding;
+ ImVector<stbrp_node> pack_nodes;
+ pack_nodes.resize(num_nodes_for_packing_algorithm);
+ stbrp_context pack_context;
+ stbrp_init_target(&pack_context, atlas->TexWidth, TEX_HEIGHT_MAX, pack_nodes.Data, pack_nodes.Size);
+ ImFontAtlasBuildPackCustomRects(atlas, &pack_context);
+
+ // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point.
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ stbrp_pack_rects(&pack_context, src_tmp.Rects, src_tmp.GlyphsCount);
+
+ // Extend texture height and mark missing glyphs as non-packed so we won't render them.
+ // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?)
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
+ if (src_tmp.Rects[glyph_i].was_packed)
+ atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h);
+ }
+
+ // 7. Allocate texture
+ atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
+ atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
+ if (src_load_color)
+ {
+ size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 4;
+ atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(tex_size);
+ memset(atlas->TexPixelsRGBA32, 0, tex_size);
+ }
+ else
+ {
+ size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 1;
+ atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(tex_size);
+ memset(atlas->TexPixelsAlpha8, 0, tex_size);
+ }
+
+ // 8. Copy rasterized font characters back into the main texture
+ // 9. Setup ImFont and glyphs for runtime
+ bool tex_use_colors = false;
+ for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
+ {
+ ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
+ if (src_tmp.GlyphsCount == 0)
+ continue;
+
+ // When merging fonts with MergeMode=true:
+ // - We can have multiple input fonts writing into a same destination font.
+ // - dst_font->ConfigData is != from cfg which is our source configuration.
+ ImFontConfig& cfg = atlas->ConfigData[src_i];
+ ImFont* dst_font = cfg.DstFont;
+
+ const float ascent = src_tmp.Font.Info.Ascender;
+ const float descent = src_tmp.Font.Info.Descender;
+ ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
+ const float font_off_x = cfg.GlyphOffset.x;
+ const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
+
+ const int padding = atlas->TexGlyphPadding;
+ for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
+ {
+ ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
+ stbrp_rect& pack_rect = src_tmp.Rects[glyph_i];
+ IM_ASSERT(pack_rect.was_packed);
+ if (pack_rect.w == 0 && pack_rect.h == 0)
+ continue;
+
+ GlyphInfo& info = src_glyph.Info;
+ IM_ASSERT(info.Width + padding <= pack_rect.w);
+ IM_ASSERT(info.Height + padding <= pack_rect.h);
+ const int tx = pack_rect.x + padding;
+ const int ty = pack_rect.y + padding;
+
+ // Register glyph
+ float x0 = info.OffsetX + font_off_x;
+ float y0 = info.OffsetY + font_off_y;
+ float x1 = x0 + info.Width;
+ float y1 = y0 + info.Height;
+ float u0 = (tx) / (float)atlas->TexWidth;
+ float v0 = (ty) / (float)atlas->TexHeight;
+ float u1 = (tx + info.Width) / (float)atlas->TexWidth;
+ float v1 = (ty + info.Height) / (float)atlas->TexHeight;
+ dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
+
+ ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
+ IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
+ if (src_glyph.Info.IsColored)
+ dst_glyph->Colored = tex_use_colors = true;
+
+ // Blit from temporary buffer to final texture
+ size_t blit_src_stride = (size_t)src_glyph.Info.Width;
+ size_t blit_dst_stride = (size_t)atlas->TexWidth;
+ unsigned int* blit_src = src_glyph.BitmapData;
+ if (atlas->TexPixelsAlpha8 != NULL)
+ {
+ unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
+ for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
+ for (int x = 0; x < info.Width; x++)
+ blit_dst[x] = (unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF);
+ }
+ else
+ {
+ unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx;
+ for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
+ for (int x = 0; x < info.Width; x++)
+ blit_dst[x] = blit_src[x];
+ }
+ }
+
+ src_tmp.Rects = NULL;
+ }
+ atlas->TexPixelsUseColors = tex_use_colors;
+
+ // Cleanup
+ for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
+ IM_FREE(buf_bitmap_buffers[buf_i]);
+ src_tmp_array.clear_destruct();
+
+ ImFontAtlasBuildFinish(atlas);
+
+ return true;
+}
+
+// FreeType memory allocation callbacks
+static void* FreeType_Alloc(FT_Memory /*memory*/, long size)
+{
+ return GImGuiFreeTypeAllocFunc((size_t)size, GImGuiFreeTypeAllocatorUserData);
+}
+
+static void FreeType_Free(FT_Memory /*memory*/, void* block)
+{
+ GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
+}
+
+static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block)
+{
+ // Implement realloc() as we don't ask user to provide it.
+ if (block == NULL)
+ return GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData);
+
+ if (new_size == 0)
+ {
+ GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
+ return NULL;
+ }
+
+ if (new_size > cur_size)
+ {
+ void* new_block = GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData);
+ memcpy(new_block, block, (size_t)cur_size);
+ GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
+ return new_block;
+ }
+
+ return block;
+}
+
+static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
+{
+ // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html
+ FT_MemoryRec_ memory_rec = {};
+ memory_rec.user = NULL;
+ memory_rec.alloc = &FreeType_Alloc;
+ memory_rec.free = &FreeType_Free;
+ memory_rec.realloc = &FreeType_Realloc;
+
+ // https://www.freetype.org/freetype2/docs/reference/ft2-module_management.html#FT_New_Library
+ FT_Library ft_library;
+ FT_Error error = FT_New_Library(&memory_rec, &ft_library);
+ if (error != 0)
+ return false;
+
+ // If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
+ FT_Add_Default_Modules(ft_library);
+
+ bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
+ FT_Done_Library(ft_library);
+
+ return ret;
+}
+
+const ImFontBuilderIO* ImGuiFreeType::GetBuilderForFreeType()
+{
+ static ImFontBuilderIO io;
+ io.FontBuilder_Build = ImFontAtlasBuildWithFreeType;
+ return &io;
+}
+
+void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
+{
+ GImGuiFreeTypeAllocFunc = alloc_func;
+ GImGuiFreeTypeFreeFunc = free_func;
+ GImGuiFreeTypeAllocatorUserData = user_data;
+}
diff --git a/Client/ThirdParty/imgui/misc/freetype/imgui_freetype.h b/Client/ThirdParty/imgui/misc/freetype/imgui_freetype.h
new file mode 100644
index 0000000..713e463
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/freetype/imgui_freetype.h
@@ -0,0 +1,50 @@
+// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder)
+// (headers)
+
+#pragma once
+
+#include "imgui.h" // IMGUI_API
+
+// Forward declarations
+struct ImFontAtlas;
+struct ImFontBuilderIO;
+
+// Hinting greatly impacts visuals (and glyph sizes).
+// - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
+// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h
+// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
+// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
+// You can set those flags globaly in ImFontAtlas::FontBuilderFlags
+// You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags
+enum ImGuiFreeTypeBuilderFlags
+{
+ ImGuiFreeTypeBuilderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
+ ImGuiFreeTypeBuilderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter.
+ ImGuiFreeTypeBuilderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
+ ImGuiFreeTypeBuilderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
+ ImGuiFreeTypeBuilderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
+ ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
+ ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
+ ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
+ ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
+ ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs
+};
+
+namespace ImGuiFreeType
+{
+ // This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'.
+ // If you need to dynamically select between multiple builders:
+ // - you can manually assign this builder with 'atlas->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()'
+ // - prefer deep-copying this into your own ImFontBuilderIO instance if you use hot-reloading that messes up static data.
+ IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType();
+
+ // Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()
+ // However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired.
+ IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
+
+ // Obsolete names (will be removed soon)
+ // Prefer using '#define IMGUI_ENABLE_FREETYPE'
+#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
+ static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
+#endif
+}
diff --git a/Client/ThirdParty/imgui/misc/single_file/imgui_single_file.h b/Client/ThirdParty/imgui/misc/single_file/imgui_single_file.h
new file mode 100644
index 0000000..6c1fb36
--- /dev/null
+++ b/Client/ThirdParty/imgui/misc/single_file/imgui_single_file.h
@@ -0,0 +1,18 @@
+// dear imgui: single-file wrapper include
+// We use this to validate compiling all *.cpp files in a same compilation unit.
+// Users of that technique (also called "Unity builds") can generally provide this themselves,
+// so we don't really recommend you use this in your projects.
+
+// Do this:
+// #define IMGUI_IMPLEMENTATION
+// Before you include this file in *one* C++ file to create the implementation.
+// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit.
+#include "../../imgui.h"
+
+#ifdef IMGUI_IMPLEMENTATION
+#include "../../imgui.cpp"
+#include "../../imgui_demo.cpp"
+#include "../../imgui_draw.cpp"
+#include "../../imgui_tables.cpp"
+#include "../../imgui_widgets.cpp"
+#endif
diff --git a/Client/ThirdParty/json/json.hpp b/Client/ThirdParty/json/json.hpp
new file mode 100644
index 0000000..5800976
--- /dev/null
+++ b/Client/ThirdParty/json/json.hpp
@@ -0,0 +1,26750 @@
+/*
+ __ _____ _____ _____
+ __| | __| | | | JSON for Modern C++
+| | |__ | | | | | | version 3.10.4
+|_____|_____|_____|_|___| https://github.com/nlohmann/json
+
+Licensed under the MIT License <http://opensource.org/licenses/MIT>.
+SPDX-License-Identifier: MIT
+Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef INCLUDE_NLOHMANN_JSON_HPP_
+#define INCLUDE_NLOHMANN_JSON_HPP_
+
+#define NLOHMANN_JSON_VERSION_MAJOR 3
+#define NLOHMANN_JSON_VERSION_MINOR 10
+#define NLOHMANN_JSON_VERSION_PATCH 4
+
+#include <algorithm> // all_of, find, for_each
+#include <cstddef> // nullptr_t, ptrdiff_t, size_t
+#include <functional> // hash, less
+#include <initializer_list> // initializer_list
+#ifndef JSON_NO_IO
+ #include <iosfwd> // istream, ostream
+#endif // JSON_NO_IO
+#include <iterator> // random_access_iterator_tag
+#include <memory> // unique_ptr
+#include <numeric> // accumulate
+#include <string> // string, stoi, to_string
+#include <utility> // declval, forward, move, pair, swap
+#include <vector> // vector
+
+// #include <nlohmann/adl_serializer.hpp>
+
+
+#include <type_traits>
+#include <utility>
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+
+#include <algorithm> // transform
+#include <array> // array
+#include <forward_list> // forward_list
+#include <iterator> // inserter, front_inserter, end
+#include <map> // map
+#include <string> // string
+#include <tuple> // tuple, make_tuple
+#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
+#include <unordered_map> // unordered_map
+#include <utility> // pair, declval
+#include <valarray> // valarray
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+
+#include <exception> // exception
+#include <stdexcept> // runtime_error
+#include <string> // to_string
+#include <vector> // vector
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t
+#include <string> // string
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////////////
+// JSON type enumeration //
+///////////////////////////
+
+/*!
+@brief the JSON type enumeration
+
+This enumeration collects the different JSON types. It is internally used to
+distinguish the stored values, and the functions @ref basic_json::is_null(),
+@ref basic_json::is_object(), @ref basic_json::is_array(),
+@ref basic_json::is_string(), @ref basic_json::is_boolean(),
+@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
+@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
+@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
+@ref basic_json::is_structured() rely on it.
+
+@note There are three enumeration entries (number_integer, number_unsigned, and
+number_float), because the library distinguishes these three types for numbers:
+@ref basic_json::number_unsigned_t is used for unsigned integers,
+@ref basic_json::number_integer_t is used for signed integers, and
+@ref basic_json::number_float_t is used for floating-point numbers or to
+approximate integers which do not fit in the limits of their respective type.
+
+@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
+value with the default value for a given type
+
+@since version 1.0.0
+*/
+enum class value_t : std::uint8_t
+{
+ null, ///< null value
+ object, ///< object (unordered set of name/value pairs)
+ array, ///< array (ordered collection of values)
+ string, ///< string value
+ boolean, ///< boolean value
+ number_integer, ///< number value (signed integer)
+ number_unsigned, ///< number value (unsigned integer)
+ number_float, ///< number value (floating-point)
+ binary, ///< binary array (ordered collection of bytes)
+ discarded ///< discarded by the parser callback function
+};
+
+/*!
+@brief comparison operator for JSON types
+
+Returns an ordering that is similar to Python:
+- order: null < boolean < number < object < array < string < binary
+- furthermore, each type is not smaller than itself
+- discarded values are not comparable
+- binary is represented as a b"" string in python and directly comparable to a
+ string; however, making a binary array directly comparable with a string would
+ be surprising behavior in a JSON file.
+
+@since version 1.0.0
+*/
+inline bool operator<(const value_t lhs, const value_t rhs) noexcept
+{
+ static constexpr std::array<std::uint8_t, 9> order = {{
+ 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
+ 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
+ 6 /* binary */
+ }
+ };
+
+ const auto l_index = static_cast<std::size_t>(lhs);
+ const auto r_index = static_cast<std::size_t>(rhs);
+ return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
+}
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+
+#include <string>
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+#include <utility> // declval, pair
+// #include <nlohmann/thirdparty/hedley/hedley.hpp>
+
+
+/* Hedley - https://nemequ.github.io/hedley
+ * Created by Evan Nemerson <evan@nemerson.com>
+ *
+ * To the extent possible under law, the author(s) have dedicated all
+ * copyright and related and neighboring rights to this software to
+ * the public domain worldwide. This software is distributed without
+ * any warranty.
+ *
+ * For details, see <http://creativecommons.org/publicdomain/zero/1.0/>.
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
+#if defined(JSON_HEDLEY_VERSION)
+ #undef JSON_HEDLEY_VERSION
+#endif
+#define JSON_HEDLEY_VERSION 15
+
+#if defined(JSON_HEDLEY_STRINGIFY_EX)
+ #undef JSON_HEDLEY_STRINGIFY_EX
+#endif
+#define JSON_HEDLEY_STRINGIFY_EX(x) #x
+
+#if defined(JSON_HEDLEY_STRINGIFY)
+ #undef JSON_HEDLEY_STRINGIFY
+#endif
+#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
+
+#if defined(JSON_HEDLEY_CONCAT_EX)
+ #undef JSON_HEDLEY_CONCAT_EX
+#endif
+#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
+
+#if defined(JSON_HEDLEY_CONCAT)
+ #undef JSON_HEDLEY_CONCAT
+#endif
+#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
+
+#if defined(JSON_HEDLEY_CONCAT3_EX)
+ #undef JSON_HEDLEY_CONCAT3_EX
+#endif
+#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
+
+#if defined(JSON_HEDLEY_CONCAT3)
+ #undef JSON_HEDLEY_CONCAT3
+#endif
+#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
+
+#if defined(JSON_HEDLEY_VERSION_ENCODE)
+ #undef JSON_HEDLEY_VERSION_ENCODE
+#endif
+#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
+ #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
+ #undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
+
+#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
+ #undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#endif
+#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
+
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+ #undef JSON_HEDLEY_GNUC_VERSION
+#endif
+#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
+ #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#elif defined(__GNUC__)
+ #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
+ #undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GNUC_VERSION)
+ #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION)
+ #undef JSON_HEDLEY_MSVC_VERSION
+#endif
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
+ #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
+#elif defined(_MSC_FULL_VER) && !defined(__ICL)
+ #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
+#elif defined(_MSC_VER) && !defined(__ICL)
+ #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
+ #undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#endif
+#if !defined(JSON_HEDLEY_MSVC_VERSION)
+ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
+#else
+ #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+ #undef JSON_HEDLEY_INTEL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
+ #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
+#elif defined(__INTEL_COMPILER) && !defined(__ICL)
+ #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
+ #undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_VERSION)
+ #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
+ #undef JSON_HEDLEY_INTEL_CL_VERSION
+#endif
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
+ #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
+#endif
+
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
+ #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
+ #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION)
+ #undef JSON_HEDLEY_PGI_VERSION
+#endif
+#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
+ #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
+#endif
+
+#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
+ #undef JSON_HEDLEY_PGI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PGI_VERSION)
+ #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+ #undef JSON_HEDLEY_SUNPRO_VERSION
+#endif
+#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
+ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
+#elif defined(__SUNPRO_C)
+ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
+#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
+ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
+#elif defined(__SUNPRO_CC)
+ #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
+ #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_SUNPRO_VERSION)
+ #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+ #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#endif
+#if defined(__EMSCRIPTEN__)
+ #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
+#endif
+
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
+ #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
+ #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION)
+ #undef JSON_HEDLEY_ARM_VERSION
+#endif
+#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
+ #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
+#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
+ #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
+#endif
+
+#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
+ #undef JSON_HEDLEY_ARM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_ARM_VERSION)
+ #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION)
+ #undef JSON_HEDLEY_IBM_VERSION
+#endif
+#if defined(__ibmxl__)
+ #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
+#elif defined(__xlC__) && defined(__xlC_ver__)
+ #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
+#elif defined(__xlC__)
+ #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
+#endif
+
+#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
+ #undef JSON_HEDLEY_IBM_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IBM_VERSION)
+ #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION)
+ #undef JSON_HEDLEY_TI_VERSION
+#endif
+#if \
+ defined(__TI_COMPILER_VERSION__) && \
+ ( \
+ defined(__TMS470__) || defined(__TI_ARM__) || \
+ defined(__MSP430__) || \
+ defined(__TMS320C2000__) \
+ )
+#if (__TI_COMPILER_VERSION__ >= 16000000)
+ #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+#endif
+
+#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_VERSION)
+ #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
+ #undef JSON_HEDLEY_TI_CL2000_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
+ #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
+ #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL430_VERSION)
+ #undef JSON_HEDLEY_TI_CL430_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
+ #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL430_VERSION)
+ #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
+ #undef JSON_HEDLEY_TI_ARMCL_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
+ #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
+ #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
+ #undef JSON_HEDLEY_TI_CL6X_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
+ #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
+ #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
+ #undef JSON_HEDLEY_TI_CL7X_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
+ #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
+ #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
+ #undef JSON_HEDLEY_TI_CLPRU_VERSION
+#endif
+#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
+ #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
+ #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
+ #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+ #undef JSON_HEDLEY_CRAY_VERSION
+#endif
+#if defined(_CRAYC)
+ #if defined(_RELEASE_PATCHLEVEL)
+ #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
+ #else
+ #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
+ #endif
+#endif
+
+#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
+ #undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_CRAY_VERSION)
+ #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION)
+ #undef JSON_HEDLEY_IAR_VERSION
+#endif
+#if defined(__IAR_SYSTEMS_ICC__)
+ #if __VER__ > 1000
+ #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
+ #else
+ #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
+ #endif
+#endif
+
+#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
+ #undef JSON_HEDLEY_IAR_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_IAR_VERSION)
+ #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+ #undef JSON_HEDLEY_TINYC_VERSION
+#endif
+#if defined(__TINYC__)
+ #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
+ #undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_TINYC_VERSION)
+ #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION)
+ #undef JSON_HEDLEY_DMC_VERSION
+#endif
+#if defined(__DMC__)
+ #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
+#endif
+
+#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
+ #undef JSON_HEDLEY_DMC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_DMC_VERSION)
+ #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+ #undef JSON_HEDLEY_COMPCERT_VERSION
+#endif
+#if defined(__COMPCERT_VERSION__)
+ #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
+#endif
+
+#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
+ #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_COMPCERT_VERSION)
+ #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+ #undef JSON_HEDLEY_PELLES_VERSION
+#endif
+#if defined(__POCC__)
+ #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
+#endif
+
+#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
+ #undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_PELLES_VERSION)
+ #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
+ #undef JSON_HEDLEY_MCST_LCC_VERSION
+#endif
+#if defined(__LCC__) && defined(__LCC_MINOR__)
+ #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
+#endif
+
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
+ #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
+ #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION)
+ #undef JSON_HEDLEY_GCC_VERSION
+#endif
+#if \
+ defined(JSON_HEDLEY_GNUC_VERSION) && \
+ !defined(__clang__) && \
+ !defined(JSON_HEDLEY_INTEL_VERSION) && \
+ !defined(JSON_HEDLEY_PGI_VERSION) && \
+ !defined(JSON_HEDLEY_ARM_VERSION) && \
+ !defined(JSON_HEDLEY_CRAY_VERSION) && \
+ !defined(JSON_HEDLEY_TI_VERSION) && \
+ !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
+ !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
+ !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
+ !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
+ !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
+ !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
+ !defined(__COMPCERT__) && \
+ !defined(JSON_HEDLEY_MCST_LCC_VERSION)
+ #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
+#endif
+
+#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
+ #undef JSON_HEDLEY_GCC_VERSION_CHECK
+#endif
+#if defined(JSON_HEDLEY_GCC_VERSION)
+ #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
+#else
+ #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
+ #undef JSON_HEDLEY_HAS_ATTRIBUTE
+#endif
+#if \
+ defined(__has_attribute) && \
+ ( \
+ (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
+ )
+# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
+#else
+# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
+ #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+ #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
+ #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#endif
+#if defined(__has_attribute)
+ #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+#else
+ #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
+ #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#endif
+#if \
+ defined(__has_cpp_attribute) && \
+ defined(__cplusplus) && \
+ (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
+ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
+#else
+ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
+ #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#endif
+#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
+ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#elif \
+ !defined(JSON_HEDLEY_PGI_VERSION) && \
+ !defined(JSON_HEDLEY_IAR_VERSION) && \
+ (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
+ (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
+ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
+#else
+ #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
+ #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+ #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
+ #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#endif
+#if defined(__has_cpp_attribute) && defined(__cplusplus)
+ #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
+#else
+ #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_BUILTIN)
+ #undef JSON_HEDLEY_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+ #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
+#else
+ #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
+ #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+ #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
+ #undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#endif
+#if defined(__has_builtin)
+ #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
+#else
+ #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_FEATURE)
+ #undef JSON_HEDLEY_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+ #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
+#else
+ #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
+ #undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+ #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
+ #undef JSON_HEDLEY_GCC_HAS_FEATURE
+#endif
+#if defined(__has_feature)
+ #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
+#else
+ #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_EXTENSION)
+ #undef JSON_HEDLEY_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+ #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
+#else
+ #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
+ #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+ #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
+ #undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#endif
+#if defined(__has_extension)
+ #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
+#else
+ #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
+ #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+ #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
+#else
+ #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
+ #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+ #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
+ #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#endif
+#if defined(__has_declspec_attribute)
+ #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
+#else
+ #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_HAS_WARNING)
+ #undef JSON_HEDLEY_HAS_WARNING
+#endif
+#if defined(__has_warning)
+ #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
+#else
+ #define JSON_HEDLEY_HAS_WARNING(warning) (0)
+#endif
+
+#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
+ #undef JSON_HEDLEY_GNUC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+ #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+ #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
+ #undef JSON_HEDLEY_GCC_HAS_WARNING
+#endif
+#if defined(__has_warning)
+ #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
+#else
+ #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if \
+ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+ defined(__clang__) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
+ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
+ (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
+ #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+ #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
+#else
+ #define JSON_HEDLEY_PRAGMA(value)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
+ #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#endif
+#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
+ #undef JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+#if defined(__clang__)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
+ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
+ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
+ #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
+#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
+ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
+#elif \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
+ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
+ #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
+#else
+ #define JSON_HEDLEY_DIAGNOSTIC_PUSH
+ #define JSON_HEDLEY_DIAGNOSTIC_POP
+#endif
+
+/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
+ HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#endif
+#if defined(__cplusplus)
+# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
+# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
+# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
+# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+ _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
+ _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
+ xpr \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# else
+# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+ _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
+ xpr \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# endif
+# else
+# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
+ xpr \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# endif
+# endif
+#endif
+#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
+#endif
+
+#if defined(JSON_HEDLEY_CONST_CAST)
+ #undef JSON_HEDLEY_CONST_CAST
+#endif
+#if defined(__cplusplus)
+# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
+#elif \
+ JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
+ ((T) (expr)); \
+ JSON_HEDLEY_DIAGNOSTIC_POP \
+ }))
+#else
+# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_REINTERPRET_CAST)
+ #undef JSON_HEDLEY_REINTERPRET_CAST
+#endif
+#if defined(__cplusplus)
+ #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
+#else
+ #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_CAST)
+ #undef JSON_HEDLEY_STATIC_CAST
+#endif
+#if defined(__cplusplus)
+ #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
+#else
+ #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
+#endif
+
+#if defined(JSON_HEDLEY_CPP_CAST)
+ #undef JSON_HEDLEY_CPP_CAST
+#endif
+#if defined(__cplusplus)
+# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
+# define JSON_HEDLEY_CPP_CAST(T, expr) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
+ ((T) (expr)) \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
+# define JSON_HEDLEY_CPP_CAST(T, expr) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("diag_suppress=Pe137") \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# else
+# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
+# endif
+#else
+# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
+ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
+#elif \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
+#else
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
+ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
+#elif \
+ JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
+#else
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
+ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
+#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
+#elif \
+ JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
+#else
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
+ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
+#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#else
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#endif
+
+#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
+ #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
+#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
+#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
+#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
+#else
+ #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#endif
+
+#if defined(JSON_HEDLEY_DEPRECATED)
+ #undef JSON_HEDLEY_DEPRECATED
+#endif
+#if defined(JSON_HEDLEY_DEPRECATED_FOR)
+ #undef JSON_HEDLEY_DEPRECATED_FOR
+#endif
+#if \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
+#elif \
+ (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
+#elif defined(__cplusplus) && (__cplusplus >= 201402L)
+ #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
+#elif \
+ JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+ #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+ JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
+#else
+ #define JSON_HEDLEY_DEPRECATED(since)
+ #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
+#endif
+
+#if defined(JSON_HEDLEY_UNAVAILABLE)
+ #undef JSON_HEDLEY_UNAVAILABLE
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
+#else
+ #define JSON_HEDLEY_UNAVAILABLE(available_since)
+#endif
+
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
+ #undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#endif
+#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
+ #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
+#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
+#elif defined(_Check_return_) /* SAL */
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
+#else
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT
+ #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
+#endif
+
+#if defined(JSON_HEDLEY_SENTINEL)
+ #undef JSON_HEDLEY_SENTINEL
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
+#else
+ #define JSON_HEDLEY_SENTINEL(position)
+#endif
+
+#if defined(JSON_HEDLEY_NO_RETURN)
+ #undef JSON_HEDLEY_NO_RETURN
+#endif
+#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_NO_RETURN __noreturn
+#elif \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+ #define JSON_HEDLEY_NO_RETURN _Noreturn
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+ #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
+#elif \
+ JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+ #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+ #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+ #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+ #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+ #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
+#else
+ #define JSON_HEDLEY_NO_RETURN
+#endif
+
+#if defined(JSON_HEDLEY_NO_ESCAPE)
+ #undef JSON_HEDLEY_NO_ESCAPE
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
+ #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
+#else
+ #define JSON_HEDLEY_NO_ESCAPE
+#endif
+
+#if defined(JSON_HEDLEY_UNREACHABLE)
+ #undef JSON_HEDLEY_UNREACHABLE
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
+ #undef JSON_HEDLEY_UNREACHABLE_RETURN
+#endif
+#if defined(JSON_HEDLEY_ASSUME)
+ #undef JSON_HEDLEY_ASSUME
+#endif
+#if \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
+#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
+ #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
+#elif \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
+ #if defined(__cplusplus)
+ #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
+ #else
+ #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
+ #endif
+#endif
+#if \
+ (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
+ JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
+#elif defined(JSON_HEDLEY_ASSUME)
+ #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
+#endif
+#if !defined(JSON_HEDLEY_ASSUME)
+ #if defined(JSON_HEDLEY_UNREACHABLE)
+ #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
+ #else
+ #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
+ #endif
+#endif
+#if defined(JSON_HEDLEY_UNREACHABLE)
+ #if \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
+ #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
+ #else
+ #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
+ #endif
+#else
+ #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
+#endif
+#if !defined(JSON_HEDLEY_UNREACHABLE)
+ #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
+#endif
+
+JSON_HEDLEY_DIAGNOSTIC_PUSH
+#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
+ #pragma clang diagnostic ignored "-Wpedantic"
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
+ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+#endif
+#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
+ #if defined(__clang__)
+ #pragma clang diagnostic ignored "-Wvariadic-macros"
+ #elif defined(JSON_HEDLEY_GCC_VERSION)
+ #pragma GCC diagnostic ignored "-Wvariadic-macros"
+ #endif
+#endif
+#if defined(JSON_HEDLEY_NON_NULL)
+ #undef JSON_HEDLEY_NON_NULL
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+ #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
+#else
+ #define JSON_HEDLEY_NON_NULL(...)
+#endif
+JSON_HEDLEY_DIAGNOSTIC_POP
+
+#if defined(JSON_HEDLEY_PRINTF_FORMAT)
+ #undef JSON_HEDLEY_PRINTF_FORMAT
+#endif
+#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
+ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
+#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
+ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
+#elif \
+ JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
+ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
+#else
+ #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
+#endif
+
+#if defined(JSON_HEDLEY_CONSTEXPR)
+ #undef JSON_HEDLEY_CONSTEXPR
+#endif
+#if defined(__cplusplus)
+ #if __cplusplus >= 201103L
+ #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
+ #endif
+#endif
+#if !defined(JSON_HEDLEY_CONSTEXPR)
+ #define JSON_HEDLEY_CONSTEXPR
+#endif
+
+#if defined(JSON_HEDLEY_PREDICT)
+ #undef JSON_HEDLEY_PREDICT
+#endif
+#if defined(JSON_HEDLEY_LIKELY)
+ #undef JSON_HEDLEY_LIKELY
+#endif
+#if defined(JSON_HEDLEY_UNLIKELY)
+ #undef JSON_HEDLEY_UNLIKELY
+#endif
+#if defined(JSON_HEDLEY_UNPREDICTABLE)
+ #undef JSON_HEDLEY_UNPREDICTABLE
+#endif
+#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
+ #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
+#endif
+#if \
+ (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
+# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
+# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
+# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
+# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
+#elif \
+ (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
+ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
+ (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
+# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
+ (__extension__ ({ \
+ double hedley_probability_ = (probability); \
+ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
+ }))
+# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
+ (__extension__ ({ \
+ double hedley_probability_ = (probability); \
+ ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
+ }))
+# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
+# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
+#else
+# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
+# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
+# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
+# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
+# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
+#endif
+#if !defined(JSON_HEDLEY_UNPREDICTABLE)
+ #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
+#endif
+
+#if defined(JSON_HEDLEY_MALLOC)
+ #undef JSON_HEDLEY_MALLOC
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+ #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_MALLOC __declspec(restrict)
+#else
+ #define JSON_HEDLEY_MALLOC
+#endif
+
+#if defined(JSON_HEDLEY_PURE)
+ #undef JSON_HEDLEY_PURE
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+# define JSON_HEDLEY_PURE __attribute__((__pure__))
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
+#elif defined(__cplusplus) && \
+ ( \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
+ )
+# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
+#else
+# define JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_CONST)
+ #undef JSON_HEDLEY_CONST
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_CONST __attribute__((__const__))
+#elif \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
+ #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
+#else
+ #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
+#endif
+
+#if defined(JSON_HEDLEY_RESTRICT)
+ #undef JSON_HEDLEY_RESTRICT
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
+ #define JSON_HEDLEY_RESTRICT restrict
+#elif \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
+ JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
+ defined(__clang__) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_RESTRICT __restrict
+#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
+ #define JSON_HEDLEY_RESTRICT _Restrict
+#else
+ #define JSON_HEDLEY_RESTRICT
+#endif
+
+#if defined(JSON_HEDLEY_INLINE)
+ #undef JSON_HEDLEY_INLINE
+#endif
+#if \
+ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+ (defined(__cplusplus) && (__cplusplus >= 199711L))
+ #define JSON_HEDLEY_INLINE inline
+#elif \
+ defined(JSON_HEDLEY_GCC_VERSION) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
+ #define JSON_HEDLEY_INLINE __inline__
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_INLINE __inline
+#else
+ #define JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_ALWAYS_INLINE)
+ #undef JSON_HEDLEY_ALWAYS_INLINE
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
+#elif defined(__cplusplus) && \
+ ( \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
+ )
+# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
+#else
+# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_NEVER_INLINE)
+ #undef JSON_HEDLEY_NEVER_INLINE
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
+ JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
+ (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
+ (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
+ (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
+ JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
+ JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
+ JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
+ #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
+ #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
+#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
+ #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+ #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
+#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
+ #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
+ #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
+#else
+ #define JSON_HEDLEY_NEVER_INLINE
+#endif
+
+#if defined(JSON_HEDLEY_PRIVATE)
+ #undef JSON_HEDLEY_PRIVATE
+#endif
+#if defined(JSON_HEDLEY_PUBLIC)
+ #undef JSON_HEDLEY_PUBLIC
+#endif
+#if defined(JSON_HEDLEY_IMPORT)
+ #undef JSON_HEDLEY_IMPORT
+#endif
+#if defined(_WIN32) || defined(__CYGWIN__)
+# define JSON_HEDLEY_PRIVATE
+# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
+# define JSON_HEDLEY_IMPORT __declspec(dllimport)
+#else
+# if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+ JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+ ( \
+ defined(__TI_EABI__) && \
+ ( \
+ (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
+ ) \
+ ) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
+# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
+# else
+# define JSON_HEDLEY_PRIVATE
+# define JSON_HEDLEY_PUBLIC
+# endif
+# define JSON_HEDLEY_IMPORT extern
+#endif
+
+#if defined(JSON_HEDLEY_NO_THROW)
+ #undef JSON_HEDLEY_NO_THROW
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
+ #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
+#else
+ #define JSON_HEDLEY_NO_THROW
+#endif
+
+#if defined(JSON_HEDLEY_FALL_THROUGH)
+ #undef JSON_HEDLEY_FALL_THROUGH
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
+ #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
+#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
+ #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
+#elif defined(__fallthrough) /* SAL */
+ #define JSON_HEDLEY_FALL_THROUGH __fallthrough
+#else
+ #define JSON_HEDLEY_FALL_THROUGH
+#endif
+
+#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
+ #undef JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+#if \
+ JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
+#elif defined(_Ret_notnull_) /* SAL */
+ #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
+#else
+ #define JSON_HEDLEY_RETURNS_NON_NULL
+#endif
+
+#if defined(JSON_HEDLEY_ARRAY_PARAM)
+ #undef JSON_HEDLEY_ARRAY_PARAM
+#endif
+#if \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__STDC_NO_VLA__) && \
+ !defined(__cplusplus) && \
+ !defined(JSON_HEDLEY_PGI_VERSION) && \
+ !defined(JSON_HEDLEY_TINYC_VERSION)
+ #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
+#else
+ #define JSON_HEDLEY_ARRAY_PARAM(name)
+#endif
+
+#if defined(JSON_HEDLEY_IS_CONSTANT)
+ #undef JSON_HEDLEY_IS_CONSTANT
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
+ #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#endif
+/* JSON_HEDLEY_IS_CONSTEXPR_ is for
+ HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+ #undef JSON_HEDLEY_IS_CONSTEXPR_
+#endif
+#if \
+ JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+ JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
+ (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
+ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+ JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
+ #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
+#endif
+#if !defined(__cplusplus)
+# if \
+ JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
+ JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
+ JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
+#if defined(__INTPTR_TYPE__)
+ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
+#else
+ #include <stdint.h>
+ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
+#endif
+# elif \
+ ( \
+ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
+ !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
+ !defined(JSON_HEDLEY_PGI_VERSION) && \
+ !defined(JSON_HEDLEY_IAR_VERSION)) || \
+ (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
+ JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
+ JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
+#if defined(__INTPTR_TYPE__)
+ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
+#else
+ #include <stdint.h>
+ #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
+#endif
+# elif \
+ defined(JSON_HEDLEY_GCC_VERSION) || \
+ defined(JSON_HEDLEY_INTEL_VERSION) || \
+ defined(JSON_HEDLEY_TINYC_VERSION) || \
+ defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
+ JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
+ defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
+ defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
+ defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
+ defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
+ defined(__clang__)
+# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
+ sizeof(void) != \
+ sizeof(*( \
+ 1 ? \
+ ((void*) ((expr) * 0L) ) : \
+((struct { char v[sizeof(void) * 2]; } *) 1) \
+ ) \
+ ) \
+ )
+# endif
+#endif
+#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
+ #if !defined(JSON_HEDLEY_IS_CONSTANT)
+ #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
+ #endif
+ #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
+#else
+ #if !defined(JSON_HEDLEY_IS_CONSTANT)
+ #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
+ #endif
+ #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
+#endif
+
+#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
+ #undef JSON_HEDLEY_BEGIN_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_END_C_DECLS)
+ #undef JSON_HEDLEY_END_C_DECLS
+#endif
+#if defined(JSON_HEDLEY_C_DECL)
+ #undef JSON_HEDLEY_C_DECL
+#endif
+#if defined(__cplusplus)
+ #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
+ #define JSON_HEDLEY_END_C_DECLS }
+ #define JSON_HEDLEY_C_DECL extern "C"
+#else
+ #define JSON_HEDLEY_BEGIN_C_DECLS
+ #define JSON_HEDLEY_END_C_DECLS
+ #define JSON_HEDLEY_C_DECL
+#endif
+
+#if defined(JSON_HEDLEY_STATIC_ASSERT)
+ #undef JSON_HEDLEY_STATIC_ASSERT
+#endif
+#if \
+ !defined(__cplusplus) && ( \
+ (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
+ (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
+ JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
+ defined(_Static_assert) \
+ )
+# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
+#elif \
+ (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
+#else
+# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
+#endif
+
+#if defined(JSON_HEDLEY_NULL)
+ #undef JSON_HEDLEY_NULL
+#endif
+#if defined(__cplusplus)
+ #if __cplusplus >= 201103L
+ #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
+ #elif defined(NULL)
+ #define JSON_HEDLEY_NULL NULL
+ #else
+ #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
+ #endif
+#elif defined(NULL)
+ #define JSON_HEDLEY_NULL NULL
+#else
+ #define JSON_HEDLEY_NULL ((void*) 0)
+#endif
+
+#if defined(JSON_HEDLEY_MESSAGE)
+ #undef JSON_HEDLEY_MESSAGE
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+# define JSON_HEDLEY_MESSAGE(msg) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+ JSON_HEDLEY_PRAGMA(message msg) \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
+#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
+# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
+#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
+# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
+# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+# define JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_WARNING)
+ #undef JSON_HEDLEY_WARNING
+#endif
+#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
+# define JSON_HEDLEY_WARNING(msg) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
+ JSON_HEDLEY_PRAGMA(clang warning msg) \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+#elif \
+ JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
+ JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
+ JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
+# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
+#elif \
+ JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
+#else
+# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
+#endif
+
+#if defined(JSON_HEDLEY_REQUIRE)
+ #undef JSON_HEDLEY_REQUIRE
+#endif
+#if defined(JSON_HEDLEY_REQUIRE_MSG)
+ #undef JSON_HEDLEY_REQUIRE_MSG
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
+# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
+# define JSON_HEDLEY_REQUIRE(expr) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+ __attribute__((diagnose_if(!(expr), #expr, "error"))) \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
+ __attribute__((diagnose_if(!(expr), msg, "error"))) \
+ JSON_HEDLEY_DIAGNOSTIC_POP
+# else
+# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
+# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
+# endif
+#else
+# define JSON_HEDLEY_REQUIRE(expr)
+# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS)
+ #undef JSON_HEDLEY_FLAGS
+#endif
+#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
+ #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
+#else
+ #define JSON_HEDLEY_FLAGS
+#endif
+
+#if defined(JSON_HEDLEY_FLAGS_CAST)
+ #undef JSON_HEDLEY_FLAGS_CAST
+#endif
+#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
+# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
+ JSON_HEDLEY_DIAGNOSTIC_PUSH \
+ _Pragma("warning(disable:188)") \
+ ((T) (expr)); \
+ JSON_HEDLEY_DIAGNOSTIC_POP \
+ }))
+#else
+# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
+#endif
+
+#if defined(JSON_HEDLEY_EMPTY_BASES)
+ #undef JSON_HEDLEY_EMPTY_BASES
+#endif
+#if \
+ (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
+ JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
+ #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
+#else
+ #define JSON_HEDLEY_EMPTY_BASES
+#endif
+
+/* Remaining macros are deprecated. */
+
+#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
+ #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#endif
+#if defined(__clang__)
+ #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
+#else
+ #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
+#endif
+
+#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
+ #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
+ #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
+ #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#endif
+#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
+ #undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
+ #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#endif
+#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
+ #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#endif
+#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
+
+#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
+ #undef JSON_HEDLEY_CLANG_HAS_WARNING
+#endif
+#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
+
+#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+
+#include <type_traits>
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename ...Ts> struct make_void
+{
+ using type = void;
+};
+template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
+} // namespace detail
+} // namespace nlohmann
+
+
+// https://en.cppreference.com/w/cpp/experimental/is_detected
+namespace nlohmann
+{
+namespace detail
+{
+struct nonesuch
+{
+ nonesuch() = delete;
+ ~nonesuch() = delete;
+ nonesuch(nonesuch const&) = delete;
+ nonesuch(nonesuch const&&) = delete;
+ void operator=(nonesuch const&) = delete;
+ void operator=(nonesuch&&) = delete;
+};
+
+template<class Default,
+ class AlwaysVoid,
+ template<class...> class Op,
+ class... Args>
+struct detector
+{
+ using value_t = std::false_type;
+ using type = Default;
+};
+
+template<class Default, template<class...> class Op, class... Args>
+struct detector<Default, void_t<Op<Args...>>, Op, Args...>
+{
+ using value_t = std::true_type;
+ using type = Op<Args...>;
+};
+
+template<template<class...> class Op, class... Args>
+using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
+
+template<template<class...> class Op, class... Args>
+struct is_detected_lazy : is_detected<Op, Args...> { };
+
+template<template<class...> class Op, class... Args>
+using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or = detector<Default, void, Op, Args...>;
+
+template<class Default, template<class...> class Op, class... Args>
+using detected_or_t = typename detected_or<Default, Op, Args...>::type;
+
+template<class Expected, template<class...> class Op, class... Args>
+using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
+
+template<class To, template<class...> class Op, class... Args>
+using is_detected_convertible =
+ std::is_convertible<detected_t<Op, Args...>, To>;
+} // namespace detail
+} // namespace nlohmann
+
+
+// This file contains all internal macro definitions
+// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
+
+// exclude unsupported compilers
+#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
+ #if defined(__clang__)
+ #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
+ #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+ #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
+ #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
+ #endif
+ #endif
+#endif
+
+// C++ language standard detection
+// if the user manually specified the used c++ version this is skipped
+#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
+ #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
+ #define JSON_HAS_CPP_20
+ #define JSON_HAS_CPP_17
+ #define JSON_HAS_CPP_14
+ #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
+ #define JSON_HAS_CPP_17
+ #define JSON_HAS_CPP_14
+ #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
+ #define JSON_HAS_CPP_14
+ #endif
+ // the cpp 11 flag is always specified because it is the minimal required version
+ #define JSON_HAS_CPP_11
+#endif
+
+// disable documentation warnings on clang
+#if defined(__clang__)
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wdocumentation"
+ #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
+#endif
+
+// allow to disable exceptions
+#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
+ #define JSON_THROW(exception) throw exception
+ #define JSON_TRY try
+ #define JSON_CATCH(exception) catch(exception)
+ #define JSON_INTERNAL_CATCH(exception) catch(exception)
+#else
+ #include <cstdlib>
+ #define JSON_THROW(exception) std::abort()
+ #define JSON_TRY if(true)
+ #define JSON_CATCH(exception) if(false)
+ #define JSON_INTERNAL_CATCH(exception) if(false)
+#endif
+
+// override exception macros
+#if defined(JSON_THROW_USER)
+ #undef JSON_THROW
+ #define JSON_THROW JSON_THROW_USER
+#endif
+#if defined(JSON_TRY_USER)
+ #undef JSON_TRY
+ #define JSON_TRY JSON_TRY_USER
+#endif
+#if defined(JSON_CATCH_USER)
+ #undef JSON_CATCH
+ #define JSON_CATCH JSON_CATCH_USER
+ #undef JSON_INTERNAL_CATCH
+ #define JSON_INTERNAL_CATCH JSON_CATCH_USER
+#endif
+#if defined(JSON_INTERNAL_CATCH_USER)
+ #undef JSON_INTERNAL_CATCH
+ #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
+#endif
+
+// allow to override assert
+#if !defined(JSON_ASSERT)
+ #include <cassert> // assert
+ #define JSON_ASSERT(x) assert(x)
+#endif
+
+// allow to access some private functions (needed by the test suite)
+#if defined(JSON_TESTS_PRIVATE)
+ #define JSON_PRIVATE_UNLESS_TESTED public
+#else
+ #define JSON_PRIVATE_UNLESS_TESTED private
+#endif
+
+/*!
+@brief macro to briefly define a mapping between an enum and JSON
+@def NLOHMANN_JSON_SERIALIZE_ENUM
+@since version 3.4.0
+*/
+#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
+ template<typename BasicJsonType> \
+ inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
+ { \
+ static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
+ static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
+ auto it = std::find_if(std::begin(m), std::end(m), \
+ [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
+ { \
+ return ej_pair.first == e; \
+ }); \
+ j = ((it != std::end(m)) ? it : std::begin(m))->second; \
+ } \
+ template<typename BasicJsonType> \
+ inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
+ { \
+ static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
+ static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
+ auto it = std::find_if(std::begin(m), std::end(m), \
+ [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
+ { \
+ return ej_pair.second == j; \
+ }); \
+ e = ((it != std::end(m)) ? it : std::begin(m))->first; \
+ }
+
+// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
+// may be removed in the future once the class is split.
+
+#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
+ template<template<typename, typename, typename...> class ObjectType, \
+ template<typename, typename...> class ArrayType, \
+ class StringType, class BooleanType, class NumberIntegerType, \
+ class NumberUnsignedType, class NumberFloatType, \
+ template<typename> class AllocatorType, \
+ template<typename, typename = void> class JSONSerializer, \
+ class BinaryType>
+
+#define NLOHMANN_BASIC_JSON_TPL \
+ basic_json<ObjectType, ArrayType, StringType, BooleanType, \
+ NumberIntegerType, NumberUnsignedType, NumberFloatType, \
+ AllocatorType, JSONSerializer, BinaryType>
+
+// Macros to simplify conversion from/to types
+
+#define NLOHMANN_JSON_EXPAND( x ) x
+#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
+#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
+ NLOHMANN_JSON_PASTE64, \
+ NLOHMANN_JSON_PASTE63, \
+ NLOHMANN_JSON_PASTE62, \
+ NLOHMANN_JSON_PASTE61, \
+ NLOHMANN_JSON_PASTE60, \
+ NLOHMANN_JSON_PASTE59, \
+ NLOHMANN_JSON_PASTE58, \
+ NLOHMANN_JSON_PASTE57, \
+ NLOHMANN_JSON_PASTE56, \
+ NLOHMANN_JSON_PASTE55, \
+ NLOHMANN_JSON_PASTE54, \
+ NLOHMANN_JSON_PASTE53, \
+ NLOHMANN_JSON_PASTE52, \
+ NLOHMANN_JSON_PASTE51, \
+ NLOHMANN_JSON_PASTE50, \
+ NLOHMANN_JSON_PASTE49, \
+ NLOHMANN_JSON_PASTE48, \
+ NLOHMANN_JSON_PASTE47, \
+ NLOHMANN_JSON_PASTE46, \
+ NLOHMANN_JSON_PASTE45, \
+ NLOHMANN_JSON_PASTE44, \
+ NLOHMANN_JSON_PASTE43, \
+ NLOHMANN_JSON_PASTE42, \
+ NLOHMANN_JSON_PASTE41, \
+ NLOHMANN_JSON_PASTE40, \
+ NLOHMANN_JSON_PASTE39, \
+ NLOHMANN_JSON_PASTE38, \
+ NLOHMANN_JSON_PASTE37, \
+ NLOHMANN_JSON_PASTE36, \
+ NLOHMANN_JSON_PASTE35, \
+ NLOHMANN_JSON_PASTE34, \
+ NLOHMANN_JSON_PASTE33, \
+ NLOHMANN_JSON_PASTE32, \
+ NLOHMANN_JSON_PASTE31, \
+ NLOHMANN_JSON_PASTE30, \
+ NLOHMANN_JSON_PASTE29, \
+ NLOHMANN_JSON_PASTE28, \
+ NLOHMANN_JSON_PASTE27, \
+ NLOHMANN_JSON_PASTE26, \
+ NLOHMANN_JSON_PASTE25, \
+ NLOHMANN_JSON_PASTE24, \
+ NLOHMANN_JSON_PASTE23, \
+ NLOHMANN_JSON_PASTE22, \
+ NLOHMANN_JSON_PASTE21, \
+ NLOHMANN_JSON_PASTE20, \
+ NLOHMANN_JSON_PASTE19, \
+ NLOHMANN_JSON_PASTE18, \
+ NLOHMANN_JSON_PASTE17, \
+ NLOHMANN_JSON_PASTE16, \
+ NLOHMANN_JSON_PASTE15, \
+ NLOHMANN_JSON_PASTE14, \
+ NLOHMANN_JSON_PASTE13, \
+ NLOHMANN_JSON_PASTE12, \
+ NLOHMANN_JSON_PASTE11, \
+ NLOHMANN_JSON_PASTE10, \
+ NLOHMANN_JSON_PASTE9, \
+ NLOHMANN_JSON_PASTE8, \
+ NLOHMANN_JSON_PASTE7, \
+ NLOHMANN_JSON_PASTE6, \
+ NLOHMANN_JSON_PASTE5, \
+ NLOHMANN_JSON_PASTE4, \
+ NLOHMANN_JSON_PASTE3, \
+ NLOHMANN_JSON_PASTE2, \
+ NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
+#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
+#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
+#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
+#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
+#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
+#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
+#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
+#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
+#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
+#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
+#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
+#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
+#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
+#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
+#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
+#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
+#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
+#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
+#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
+#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
+#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
+#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
+#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
+#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
+#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
+#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
+#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
+#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
+#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
+#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
+#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
+#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
+#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
+#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
+#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
+#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
+#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
+#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
+#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
+#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
+#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
+#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
+#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
+#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
+#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
+#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
+#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
+#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
+#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
+#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
+#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
+#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
+#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
+#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
+#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
+#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
+#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
+#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
+#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
+#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
+#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
+#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
+#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
+
+#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
+#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
+
+/*!
+@brief macro
+@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
+@since version 3.9.0
+*/
+#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
+ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+ friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
+
+/*!
+@brief macro
+@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
+@since version 3.9.0
+*/
+#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
+ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
+ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
+
+
+// inspired from https://stackoverflow.com/a/26745591
+// allows to call any std function as if (e.g. with begin):
+// using std::begin; begin(x);
+//
+// it allows using the detected idiom to retrieve the return type
+// of such an expression
+#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
+ namespace detail { \
+ using std::std_name; \
+ \
+ template<typename... T> \
+ using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
+ } \
+ \
+ namespace detail2 { \
+ struct std_name##_tag \
+ { \
+ }; \
+ \
+ template<typename... T> \
+ std_name##_tag std_name(T&&...); \
+ \
+ template<typename... T> \
+ using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
+ \
+ template<typename... T> \
+ struct would_call_std_##std_name \
+ { \
+ static constexpr auto const value = ::nlohmann::detail:: \
+ is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
+ }; \
+ } /* namespace detail2 */ \
+ \
+ template<typename... T> \
+ struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
+ { \
+ }
+
+#ifndef JSON_USE_IMPLICIT_CONVERSIONS
+ #define JSON_USE_IMPLICIT_CONVERSIONS 1
+#endif
+
+#if JSON_USE_IMPLICIT_CONVERSIONS
+ #define JSON_EXPLICIT
+#else
+ #define JSON_EXPLICIT explicit
+#endif
+
+#ifndef JSON_DIAGNOSTICS
+ #define JSON_DIAGNOSTICS 0
+#endif
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/*!
+@brief replace all occurrences of a substring by another string
+
+@param[in,out] s the string to manipulate; changed so that all
+ occurrences of @a f are replaced with @a t
+@param[in] f the substring to replace with @a t
+@param[in] t the string to replace @a f
+
+@pre The search string @a f must not be empty. **This precondition is
+enforced with an assertion.**
+
+@since version 2.0.0
+*/
+inline void replace_substring(std::string& s, const std::string& f,
+ const std::string& t)
+{
+ JSON_ASSERT(!f.empty());
+ for (auto pos = s.find(f); // find first occurrence of f
+ pos != std::string::npos; // make sure f was found
+ s.replace(pos, f.size(), t), // replace with t, and
+ pos = s.find(f, pos + t.size())) // find next occurrence of f
+ {}
+}
+
+/*!
+ * @brief string escaping as described in RFC 6901 (Sect. 4)
+ * @param[in] s string to escape
+ * @return escaped string
+ *
+ * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
+ */
+inline std::string escape(std::string s)
+{
+ replace_substring(s, "~", "~0");
+ replace_substring(s, "/", "~1");
+ return s;
+}
+
+/*!
+ * @brief string unescaping as described in RFC 6901 (Sect. 4)
+ * @param[in] s string to unescape
+ * @return unescaped string
+ *
+ * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
+ */
+static void unescape(std::string& s)
+{
+ replace_substring(s, "~1", "/");
+ replace_substring(s, "~0", "~");
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+
+#include <cstddef> // size_t
+
+namespace nlohmann
+{
+namespace detail
+{
+/// struct to capture the start position of the current token
+struct position_t
+{
+ /// the total number of characters read
+ std::size_t chars_read_total = 0;
+ /// the number of characters read in the current line
+ std::size_t chars_read_current_line = 0;
+ /// the number of lines read
+ std::size_t lines_read = 0;
+
+ /// conversion to size_t to preserve SAX interface
+ constexpr operator size_t() const
+ {
+ return chars_read_total;
+ }
+};
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+////////////////
+// exceptions //
+////////////////
+
+/*!
+@brief general exception of the @ref basic_json class
+
+This class is an extension of `std::exception` objects with a member @a id for
+exception ids. It is used as the base class for all exceptions thrown by the
+@ref basic_json class. This class can hence be used as "wildcard" to catch
+exceptions.
+
+Subclasses:
+- @ref parse_error for exceptions indicating a parse error
+- @ref invalid_iterator for exceptions indicating errors with iterators
+- @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+- @ref out_of_range for exceptions indicating access out of the defined range
+- @ref other_error for exceptions indicating other library errors
+
+@internal
+@note To have nothrow-copy-constructible exceptions, we internally use
+ `std::runtime_error` which can cope with arbitrary-length error messages.
+ Intermediate strings are built with static functions and then passed to
+ the actual constructor.
+@endinternal
+
+@liveexample{The following code shows how arbitrary library exceptions can be
+caught.,exception}
+
+@since version 3.0.0
+*/
+class exception : public std::exception
+{
+ public:
+ /// returns the explanatory string
+ const char* what() const noexcept override
+ {
+ return m.what();
+ }
+
+ /// the id of the exception
+ const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
+
+ protected:
+ JSON_HEDLEY_NON_NULL(3)
+ exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
+
+ static std::string name(const std::string& ename, int id_)
+ {
+ return "[json.exception." + ename + "." + std::to_string(id_) + "] ";
+ }
+
+ template<typename BasicJsonType>
+ static std::string diagnostics(const BasicJsonType& leaf_element)
+ {
+#if JSON_DIAGNOSTICS
+ std::vector<std::string> tokens;
+ for (const auto* current = &leaf_element; current->m_parent != nullptr; current = current->m_parent)
+ {
+ switch (current->m_parent->type())
+ {
+ case value_t::array:
+ {
+ for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
+ {
+ if (&current->m_parent->m_value.array->operator[](i) == current)
+ {
+ tokens.emplace_back(std::to_string(i));
+ break;
+ }
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ for (const auto& element : *current->m_parent->m_value.object)
+ {
+ if (&element.second == current)
+ {
+ tokens.emplace_back(element.first.c_str());
+ break;
+ }
+ }
+ break;
+ }
+
+ case value_t::null: // LCOV_EXCL_LINE
+ case value_t::string: // LCOV_EXCL_LINE
+ case value_t::boolean: // LCOV_EXCL_LINE
+ case value_t::number_integer: // LCOV_EXCL_LINE
+ case value_t::number_unsigned: // LCOV_EXCL_LINE
+ case value_t::number_float: // LCOV_EXCL_LINE
+ case value_t::binary: // LCOV_EXCL_LINE
+ case value_t::discarded: // LCOV_EXCL_LINE
+ default: // LCOV_EXCL_LINE
+ break; // LCOV_EXCL_LINE
+ }
+ }
+
+ if (tokens.empty())
+ {
+ return "";
+ }
+
+ return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
+ [](const std::string & a, const std::string & b)
+ {
+ return a + "/" + detail::escape(b);
+ }) + ") ";
+#else
+ static_cast<void>(leaf_element);
+ return "";
+#endif
+ }
+
+ private:
+ /// an exception object as storage for error messages
+ std::runtime_error m;
+};
+
+/*!
+@brief exception indicating a parse error
+
+This exception is thrown by the library when a parse error occurs. Parse errors
+can occur during the deserialization of JSON text, CBOR, MessagePack, as well
+as when using JSON Patch.
+
+Member @a byte holds the byte index of the last read character in the input
+file.
+
+Exceptions have ids 1xx.
+
+name / id | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position.
+json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
+json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
+json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects.
+json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
+json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`.
+json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
+json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
+json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number.
+json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
+json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
+json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
+json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet).
+json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed.
+
+@note For an input with n bytes, 1 is the index of the first character and n+1
+ is the index of the terminating null byte or the end of file. This also
+ holds true when reading a byte vector (CBOR or MessagePack).
+
+@liveexample{The following code shows how a `parse_error` exception can be
+caught.,parse_error}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class parse_error : public exception
+{
+ public:
+ /*!
+ @brief create a parse error exception
+ @param[in] id_ the id of the exception
+ @param[in] pos the position where the error occurred (or with
+ chars_read_total=0 if the position cannot be
+ determined)
+ @param[in] what_arg the explanatory string
+ @return parse_error object
+ */
+ template<typename BasicJsonType>
+ static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const BasicJsonType& context)
+ {
+ std::string w = exception::name("parse_error", id_) + "parse error" +
+ position_string(pos) + ": " + exception::diagnostics(context) + what_arg;
+ return {id_, pos.chars_read_total, w.c_str()};
+ }
+
+ template<typename BasicJsonType>
+ static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const BasicJsonType& context)
+ {
+ std::string w = exception::name("parse_error", id_) + "parse error" +
+ (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") +
+ ": " + exception::diagnostics(context) + what_arg;
+ return {id_, byte_, w.c_str()};
+ }
+
+ /*!
+ @brief byte index of the parse error
+
+ The byte index of the last read character in the input file.
+
+ @note For an input with n bytes, 1 is the index of the first character and
+ n+1 is the index of the terminating null byte or the end of file.
+ This also holds true when reading a byte vector (CBOR or MessagePack).
+ */
+ const std::size_t byte;
+
+ private:
+ parse_error(int id_, std::size_t byte_, const char* what_arg)
+ : exception(id_, what_arg), byte(byte_) {}
+
+ static std::string position_string(const position_t& pos)
+ {
+ return " at line " + std::to_string(pos.lines_read + 1) +
+ ", column " + std::to_string(pos.chars_read_current_line);
+ }
+};
+
+/*!
+@brief exception indicating errors with iterators
+
+This exception is thrown if iterators passed to a library function do not match
+the expected semantics.
+
+Exceptions have ids 2xx.
+
+name / id | example message | description
+----------------------------------- | --------------- | -------------------------
+json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
+json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
+json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
+json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
+json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
+json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
+json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
+json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
+json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to.
+json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container.
+json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered.
+json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
+
+@liveexample{The following code shows how an `invalid_iterator` exception can be
+caught.,invalid_iterator}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class invalid_iterator : public exception
+{
+ public:
+ template<typename BasicJsonType>
+ static invalid_iterator create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ {
+ std::string w = exception::name("invalid_iterator", id_) + exception::diagnostics(context) + what_arg;
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ invalid_iterator(int id_, const char* what_arg)
+ : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating executing a member function with a wrong type
+
+This exception is thrown in case of a type error; that is, a library function is
+executed on a JSON value whose type does not match the expected semantics.
+
+Exceptions have ids 3xx.
+
+name / id | example message | description
+----------------------------- | --------------- | -------------------------
+json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
+json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
+json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
+json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
+json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
+json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
+json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types.
+json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
+json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types.
+json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types.
+json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types.
+json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types.
+json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
+json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers.
+json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
+json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. |
+json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) |
+
+@liveexample{The following code shows how a `type_error` exception can be
+caught.,type_error}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class type_error : public exception
+{
+ public:
+ template<typename BasicJsonType>
+ static type_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ {
+ std::string w = exception::name("type_error", id_) + exception::diagnostics(context) + what_arg;
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating access out of the defined range
+
+This exception is thrown in case a library function is called on an input
+parameter that exceeds the expected range, for instance in case of array
+indices or nonexisting object keys.
+
+Exceptions have ids 4xx.
+
+name / id | example message | description
+------------------------------- | --------------- | -------------------------
+json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1.
+json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it.
+json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object.
+json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved.
+json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
+json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF.
+json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) |
+json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. |
+json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string |
+
+@liveexample{The following code shows how an `out_of_range` exception can be
+caught.,out_of_range}
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa - @ref other_error for exceptions indicating other library errors
+
+@since version 3.0.0
+*/
+class out_of_range : public exception
+{
+ public:
+ template<typename BasicJsonType>
+ static out_of_range create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ {
+ std::string w = exception::name("out_of_range", id_) + exception::diagnostics(context) + what_arg;
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+
+/*!
+@brief exception indicating other library errors
+
+This exception is thrown in case of errors that cannot be classified with the
+other exception types.
+
+Exceptions have ids 5xx.
+
+name / id | example message | description
+------------------------------ | --------------- | -------------------------
+json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
+
+@sa - @ref exception for the base class of the library exceptions
+@sa - @ref parse_error for exceptions indicating a parse error
+@sa - @ref invalid_iterator for exceptions indicating errors with iterators
+@sa - @ref type_error for exceptions indicating executing a member function with
+ a wrong type
+@sa - @ref out_of_range for exceptions indicating access out of the defined range
+
+@liveexample{The following code shows how an `other_error` exception can be
+caught.,other_error}
+
+@since version 3.0.0
+*/
+class other_error : public exception
+{
+ public:
+ template<typename BasicJsonType>
+ static other_error create(int id_, const std::string& what_arg, const BasicJsonType& context)
+ {
+ std::string w = exception::name("other_error", id_) + exception::diagnostics(context) + what_arg;
+ return {id_, w.c_str()};
+ }
+
+ private:
+ JSON_HEDLEY_NON_NULL(3)
+ other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+#include <cstddef> // size_t
+#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
+#include <utility> // index_sequence, make_index_sequence, index_sequence_for
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+template<typename T>
+using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+#ifdef JSON_HAS_CPP_14
+
+// the following utilities are natively available in C++14
+using std::enable_if_t;
+using std::index_sequence;
+using std::make_index_sequence;
+using std::index_sequence_for;
+
+#else
+
+// alias templates to reduce boilerplate
+template<bool B, typename T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
+// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
+
+//// START OF CODE FROM GOOGLE ABSEIL
+
+// integer_sequence
+//
+// Class template representing a compile-time integer sequence. An instantiation
+// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
+// type through its template arguments (which is a common need when
+// working with C++11 variadic templates). `absl::integer_sequence` is designed
+// to be a drop-in replacement for C++14's `std::integer_sequence`.
+//
+// Example:
+//
+// template< class T, T... Ints >
+// void user_function(integer_sequence<T, Ints...>);
+//
+// int main()
+// {
+// // user_function's `T` will be deduced to `int` and `Ints...`
+// // will be deduced to `0, 1, 2, 3, 4`.
+// user_function(make_integer_sequence<int, 5>());
+// }
+template <typename T, T... Ints>
+struct integer_sequence
+{
+ using value_type = T;
+ static constexpr std::size_t size() noexcept
+ {
+ return sizeof...(Ints);
+ }
+};
+
+// index_sequence
+//
+// A helper template for an `integer_sequence` of `size_t`,
+// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
+// `std::index_sequence`.
+template <size_t... Ints>
+using index_sequence = integer_sequence<size_t, Ints...>;
+
+namespace utility_internal
+{
+
+template <typename Seq, size_t SeqSize, size_t Rem>
+struct Extend;
+
+// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
+{
+ using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
+};
+
+template <typename T, T... Ints, size_t SeqSize>
+struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
+{
+ using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
+};
+
+// Recursion helper for 'make_integer_sequence<T, N>'.
+// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
+template <typename T, size_t N>
+struct Gen
+{
+ using type =
+ typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
+};
+
+template <typename T>
+struct Gen<T, 0>
+{
+ using type = integer_sequence<T>;
+};
+
+} // namespace utility_internal
+
+// Compile-time sequences of integers
+
+// make_integer_sequence
+//
+// This template alias is equivalent to
+// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
+// replacement for C++14's `std::make_integer_sequence`.
+template <typename T, T N>
+using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
+
+// make_index_sequence
+//
+// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
+// and is designed to be a drop-in replacement for C++14's
+// `std::make_index_sequence`.
+template <size_t N>
+using make_index_sequence = make_integer_sequence<size_t, N>;
+
+// index_sequence_for
+//
+// Converts a typename pack into an index sequence of the same length, and
+// is designed to be a drop-in replacement for C++14's
+// `std::index_sequence_for()`
+template <typename... Ts>
+using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
+
+//// END OF CODE FROM GOOGLE ABSEIL
+
+#endif
+
+// dispatch utility (taken from ranges-v3)
+template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
+template<> struct priority_tag<0> {};
+
+// taken from ranges-v3
+template<typename T>
+struct static_const
+{
+ static constexpr T value{};
+};
+
+template<typename T>
+constexpr T static_const<T>::value;
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+// dispatching helper struct
+template <class T> struct identity_tag {};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+#include <limits> // numeric_limits
+#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
+#include <utility> // declval
+#include <tuple> // tuple
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+
+#include <iterator> // random_access_iterator_tag
+
+// #include <nlohmann/detail/meta/void_t.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename It, typename = void>
+struct iterator_types {};
+
+template<typename It>
+struct iterator_types <
+ It,
+ void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
+ typename It::reference, typename It::iterator_category >>
+{
+ using difference_type = typename It::difference_type;
+ using value_type = typename It::value_type;
+ using pointer = typename It::pointer;
+ using reference = typename It::reference;
+ using iterator_category = typename It::iterator_category;
+};
+
+// This is required as some compilers implement std::iterator_traits in a way that
+// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
+template<typename T, typename = void>
+struct iterator_traits
+{
+};
+
+template<typename T>
+struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
+ : iterator_types<T>
+{
+};
+
+template<typename T>
+struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
+{
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = T;
+ using difference_type = ptrdiff_t;
+ using pointer = T*;
+ using reference = T&;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/call_std/begin.hpp>
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/call_std/end.hpp>
+
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
+#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+#include <cstdint> // int64_t, uint64_t
+#include <map> // map
+#include <memory> // allocator
+#include <string> // string
+#include <vector> // vector
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+/*!
+@brief default JSONSerializer template argument
+
+This serializer ignores the template arguments and uses ADL
+([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
+for serialization.
+*/
+template<typename T = void, typename SFINAE = void>
+struct adl_serializer;
+
+template<template<typename U, typename V, typename... Args> class ObjectType =
+ std::map,
+ template<typename U, typename... Args> class ArrayType = std::vector,
+ class StringType = std::string, class BooleanType = bool,
+ class NumberIntegerType = std::int64_t,
+ class NumberUnsignedType = std::uint64_t,
+ class NumberFloatType = double,
+ template<typename U> class AllocatorType = std::allocator,
+ template<typename T, typename SFINAE = void> class JSONSerializer =
+ adl_serializer,
+ class BinaryType = std::vector<std::uint8_t>>
+class basic_json;
+
+/*!
+@brief JSON Pointer
+
+A JSON pointer defines a string syntax for identifying a specific value
+within a JSON document. It can be used with functions `at` and
+`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
+
+@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
+
+@since version 2.0.0
+*/
+template<typename BasicJsonType>
+class json_pointer;
+
+/*!
+@brief default JSON class
+
+This type is the default specialization of the @ref basic_json class which
+uses the standard template types.
+
+@since version 1.0.0
+*/
+using json = basic_json<>;
+
+template<class Key, class T, class IgnoredLess, class Allocator>
+struct ordered_map;
+
+/*!
+@brief ordered JSON class
+
+This type preserves the insertion order of object keys.
+
+@since version 3.9.0
+*/
+using ordered_json = basic_json<nlohmann::ordered_map>;
+
+} // namespace nlohmann
+
+#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
+
+
+namespace nlohmann
+{
+/*!
+@brief detail namespace with internal helper functions
+
+This namespace collects functions that should not be exposed,
+implementations of some @ref basic_json methods, and meta-programming helpers.
+
+@since version 2.1.0
+*/
+namespace detail
+{
+/////////////
+// helpers //
+/////////////
+
+// Note to maintainers:
+//
+// Every trait in this file expects a non CV-qualified type.
+// The only exceptions are in the 'aliases for detected' section
+// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
+//
+// In this case, T has to be properly CV-qualified to constraint the function arguments
+// (e.g. to_json(BasicJsonType&, const T&))
+
+template<typename> struct is_basic_json : std::false_type {};
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
+
+//////////////////////
+// json_ref helpers //
+//////////////////////
+
+template<typename>
+class json_ref;
+
+template<typename>
+struct is_json_ref : std::false_type {};
+
+template<typename T>
+struct is_json_ref<json_ref<T>> : std::true_type {};
+
+//////////////////////////
+// aliases for detected //
+//////////////////////////
+
+template<typename T>
+using mapped_type_t = typename T::mapped_type;
+
+template<typename T>
+using key_type_t = typename T::key_type;
+
+template<typename T>
+using value_type_t = typename T::value_type;
+
+template<typename T>
+using difference_type_t = typename T::difference_type;
+
+template<typename T>
+using pointer_t = typename T::pointer;
+
+template<typename T>
+using reference_t = typename T::reference;
+
+template<typename T>
+using iterator_category_t = typename T::iterator_category;
+
+template<typename T, typename... Args>
+using to_json_function = decltype(T::to_json(std::declval<Args>()...));
+
+template<typename T, typename... Args>
+using from_json_function = decltype(T::from_json(std::declval<Args>()...));
+
+template<typename T, typename U>
+using get_template_function = decltype(std::declval<T>().template get<U>());
+
+// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
+template<typename BasicJsonType, typename T, typename = void>
+struct has_from_json : std::false_type {};
+
+// trait checking if j.get<T> is valid
+// use this trait instead of std::is_constructible or std::is_convertible,
+// both rely on, or make use of implicit conversions, and thus fail when T
+// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
+template <typename BasicJsonType, typename T>
+struct is_getable
+{
+ static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
+};
+
+template<typename BasicJsonType, typename T>
+struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+ using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+ static constexpr bool value =
+ is_detected_exact<void, from_json_function, serializer,
+ const BasicJsonType&, T&>::value;
+};
+
+// This trait checks if JSONSerializer<T>::from_json(json const&) exists
+// this overload is used for non-default-constructible user-defined-types
+template<typename BasicJsonType, typename T, typename = void>
+struct has_non_default_from_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+ using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+ static constexpr bool value =
+ is_detected_exact<T, from_json_function, serializer,
+ const BasicJsonType&>::value;
+};
+
+// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
+// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
+template<typename BasicJsonType, typename T, typename = void>
+struct has_to_json : std::false_type {};
+
+template<typename BasicJsonType, typename T>
+struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
+{
+ using serializer = typename BasicJsonType::template json_serializer<T, void>;
+
+ static constexpr bool value =
+ is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
+ T>::value;
+};
+
+
+///////////////////
+// is_ functions //
+///////////////////
+
+// https://en.cppreference.com/w/cpp/types/conjunction
+template<class...> struct conjunction : std::true_type { };
+template<class B1> struct conjunction<B1> : B1 { };
+template<class B1, class... Bn>
+struct conjunction<B1, Bn...>
+: std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
+
+// https://en.cppreference.com/w/cpp/types/negation
+template<class B> struct negation : std::integral_constant < bool, !B::value > { };
+
+// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
+// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
+// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
+template <typename T>
+struct is_default_constructible : std::is_default_constructible<T> {};
+
+template <typename T1, typename T2>
+struct is_default_constructible<std::pair<T1, T2>>
+ : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
+
+template <typename T1, typename T2>
+struct is_default_constructible<const std::pair<T1, T2>>
+ : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
+
+template <typename... Ts>
+struct is_default_constructible<std::tuple<Ts...>>
+ : conjunction<is_default_constructible<Ts>...> {};
+
+template <typename... Ts>
+struct is_default_constructible<const std::tuple<Ts...>>
+ : conjunction<is_default_constructible<Ts>...> {};
+
+
+template <typename T, typename... Args>
+struct is_constructible : std::is_constructible<T, Args...> {};
+
+template <typename T1, typename T2>
+struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
+
+template <typename T1, typename T2>
+struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
+
+template <typename... Ts>
+struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
+
+template <typename... Ts>
+struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
+
+
+template<typename T, typename = void>
+struct is_iterator_traits : std::false_type {};
+
+template<typename T>
+struct is_iterator_traits<iterator_traits<T>>
+{
+ private:
+ using traits = iterator_traits<T>;
+
+ public:
+ static constexpr auto value =
+ is_detected<value_type_t, traits>::value &&
+ is_detected<difference_type_t, traits>::value &&
+ is_detected<pointer_t, traits>::value &&
+ is_detected<iterator_category_t, traits>::value &&
+ is_detected<reference_t, traits>::value;
+};
+
+template<typename T>
+struct is_range
+{
+ private:
+ using t_ref = typename std::add_lvalue_reference<T>::type;
+
+ using iterator = detected_t<result_of_begin, t_ref>;
+ using sentinel = detected_t<result_of_end, t_ref>;
+
+ // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
+ // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
+ // but reimplementing these would be too much work, as a lot of other concepts are used underneath
+ static constexpr auto is_iterator_begin =
+ is_iterator_traits<iterator_traits<iterator>>::value;
+
+ public:
+ static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
+};
+
+template<typename R>
+using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
+
+template<typename T>
+using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
+
+// The following implementation of is_complete_type is taken from
+// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
+// and is written by Xiang Fan who agreed to using it in this library.
+
+template<typename T, typename = void>
+struct is_complete_type : std::false_type {};
+
+template<typename T>
+struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
+
+template<typename BasicJsonType, typename CompatibleObjectType,
+ typename = void>
+struct is_compatible_object_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type_impl <
+ BasicJsonType, CompatibleObjectType,
+ enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
+ is_detected<key_type_t, CompatibleObjectType>::value >>
+{
+ using object_t = typename BasicJsonType::object_t;
+
+ // macOS's is_constructible does not play well with nonesuch...
+ static constexpr bool value =
+ is_constructible<typename object_t::key_type,
+ typename CompatibleObjectType::key_type>::value &&
+ is_constructible<typename object_t::mapped_type,
+ typename CompatibleObjectType::mapped_type>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type
+ : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+ typename = void>
+struct is_constructible_object_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type_impl <
+ BasicJsonType, ConstructibleObjectType,
+ enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
+ is_detected<key_type_t, ConstructibleObjectType>::value >>
+{
+ using object_t = typename BasicJsonType::object_t;
+
+ static constexpr bool value =
+ (is_default_constructible<ConstructibleObjectType>::value &&
+ (std::is_move_assignable<ConstructibleObjectType>::value ||
+ std::is_copy_assignable<ConstructibleObjectType>::value) &&
+ (is_constructible<typename ConstructibleObjectType::key_type,
+ typename object_t::key_type>::value &&
+ std::is_same <
+ typename object_t::mapped_type,
+ typename ConstructibleObjectType::mapped_type >::value)) ||
+ (has_from_json<BasicJsonType,
+ typename ConstructibleObjectType::mapped_type>::value ||
+ has_non_default_from_json <
+ BasicJsonType,
+ typename ConstructibleObjectType::mapped_type >::value);
+};
+
+template<typename BasicJsonType, typename ConstructibleObjectType>
+struct is_constructible_object_type
+ : is_constructible_object_type_impl<BasicJsonType,
+ ConstructibleObjectType> {};
+
+template<typename BasicJsonType, typename CompatibleStringType>
+struct is_compatible_string_type
+{
+ static constexpr auto value =
+ is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
+};
+
+template<typename BasicJsonType, typename ConstructibleStringType>
+struct is_constructible_string_type
+{
+ static constexpr auto value =
+ is_constructible<ConstructibleStringType,
+ typename BasicJsonType::string_t>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
+struct is_compatible_array_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type_impl <
+ BasicJsonType, CompatibleArrayType,
+ enable_if_t <
+ is_detected<iterator_t, CompatibleArrayType>::value&&
+ is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
+// special case for types like std::filesystem::path whose iterator's value_type are themselves
+// c.f. https://github.com/nlohmann/json/pull/3073
+ !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
+{
+ static constexpr bool value =
+ is_constructible<BasicJsonType,
+ range_value_t<CompatibleArrayType>>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type
+ : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
+struct is_constructible_array_type_impl : std::false_type {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+ BasicJsonType, ConstructibleArrayType,
+ enable_if_t<std::is_same<ConstructibleArrayType,
+ typename BasicJsonType::value_type>::value >>
+ : std::true_type {};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type_impl <
+ BasicJsonType, ConstructibleArrayType,
+ enable_if_t < !std::is_same<ConstructibleArrayType,
+ typename BasicJsonType::value_type>::value&&
+ !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
+ is_default_constructible<ConstructibleArrayType>::value&&
+(std::is_move_assignable<ConstructibleArrayType>::value ||
+ std::is_copy_assignable<ConstructibleArrayType>::value)&&
+is_detected<iterator_t, ConstructibleArrayType>::value&&
+is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
+is_detected<range_value_t, ConstructibleArrayType>::value&&
+// special case for types like std::filesystem::path whose iterator's value_type are themselves
+// c.f. https://github.com/nlohmann/json/pull/3073
+!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
+ is_complete_type <
+ detected_t<range_value_t, ConstructibleArrayType >>::value >>
+{
+ using value_type = range_value_t<ConstructibleArrayType>;
+
+ static constexpr bool value =
+ std::is_same<value_type,
+ typename BasicJsonType::array_t::value_type>::value ||
+ has_from_json<BasicJsonType,
+ value_type>::value ||
+ has_non_default_from_json <
+ BasicJsonType,
+ value_type >::value;
+};
+
+template<typename BasicJsonType, typename ConstructibleArrayType>
+struct is_constructible_array_type
+ : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType,
+ typename = void>
+struct is_compatible_integer_type_impl : std::false_type {};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type_impl <
+ RealIntegerType, CompatibleNumberIntegerType,
+ enable_if_t < std::is_integral<RealIntegerType>::value&&
+ std::is_integral<CompatibleNumberIntegerType>::value&&
+ !std::is_same<bool, CompatibleNumberIntegerType>::value >>
+{
+ // is there an assert somewhere on overflows?
+ using RealLimits = std::numeric_limits<RealIntegerType>;
+ using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
+
+ static constexpr auto value =
+ is_constructible<RealIntegerType,
+ CompatibleNumberIntegerType>::value &&
+ CompatibleLimits::is_integer &&
+ RealLimits::is_signed == CompatibleLimits::is_signed;
+};
+
+template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type
+ : is_compatible_integer_type_impl<RealIntegerType,
+ CompatibleNumberIntegerType> {};
+
+template<typename BasicJsonType, typename CompatibleType, typename = void>
+struct is_compatible_type_impl: std::false_type {};
+
+template<typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type_impl <
+ BasicJsonType, CompatibleType,
+ enable_if_t<is_complete_type<CompatibleType>::value >>
+{
+ static constexpr bool value =
+ has_to_json<BasicJsonType, CompatibleType>::value;
+};
+
+template<typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type
+ : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
+
+template<typename T1, typename T2>
+struct is_constructible_tuple : std::false_type {};
+
+template<typename T1, typename... Args>
+struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
+
+// a naive helper to check if a type is an ordered_map (exploits the fact that
+// ordered_map inherits capacity() from std::vector)
+template <typename T>
+struct is_ordered_map
+{
+ using one = char;
+
+ struct two
+ {
+ char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ };
+
+ template <typename C> static one test( decltype(&C::capacity) ) ;
+ template <typename C> static two test(...);
+
+ enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+};
+
+// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
+template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
+T conditional_static_cast(U value)
+{
+ return static_cast<T>(value);
+}
+
+template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
+T conditional_static_cast(U value)
+{
+ return value;
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#ifdef JSON_HAS_CPP_17
+ #include <filesystem>
+#endif
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
+ {
+ JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j));
+ }
+ n = nullptr;
+}
+
+// overloads for basic_json template parameters
+template < typename BasicJsonType, typename ArithmeticType,
+ enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
+ !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+ int > = 0 >
+void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
+{
+ switch (static_cast<value_t>(j))
+ {
+ case value_t::number_unsigned:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+ break;
+ }
+ case value_t::number_integer:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+ break;
+ }
+ case value_t::number_float:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+ break;
+ }
+
+ case value_t::null:
+ case value_t::object:
+ case value_t::array:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+ }
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
+ {
+ JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j));
+ }
+ b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+ {
+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ }
+ s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template <
+ typename BasicJsonType, typename ConstructibleStringType,
+ enable_if_t <
+ is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value&&
+ !std::is_same<typename BasicJsonType::string_t,
+ ConstructibleStringType>::value,
+ int > = 0 >
+void from_json(const BasicJsonType& j, ConstructibleStringType& s)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+ {
+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ }
+
+ s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
+{
+ get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
+{
+ get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
+{
+ get_arithmetic_value(j, val);
+}
+
+template<typename BasicJsonType, typename EnumType,
+ enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void from_json(const BasicJsonType& j, EnumType& e)
+{
+ typename std::underlying_type<EnumType>::type val;
+ get_arithmetic_value(j, val);
+ e = static_cast<EnumType>(val);
+}
+
+// forward_list doesn't have an insert method
+template<typename BasicJsonType, typename T, typename Allocator,
+ enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+ l.clear();
+ std::transform(j.rbegin(), j.rend(),
+ std::front_inserter(l), [](const BasicJsonType & i)
+ {
+ return i.template get<T>();
+ });
+}
+
+// valarray doesn't have an insert method
+template<typename BasicJsonType, typename T,
+ enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
+void from_json(const BasicJsonType& j, std::valarray<T>& l)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+ l.resize(j.size());
+ std::transform(j.begin(), j.end(), std::begin(l),
+ [](const BasicJsonType & elem)
+ {
+ return elem.template get<T>();
+ });
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+-> decltype(j.template get<T>(), void())
+{
+ for (std::size_t i = 0; i < N; ++i)
+ {
+ arr[i] = j.at(i).template get<T>();
+ }
+}
+
+template<typename BasicJsonType>
+void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
+{
+ arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
+}
+
+template<typename BasicJsonType, typename T, std::size_t N>
+auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
+ priority_tag<2> /*unused*/)
+-> decltype(j.template get<T>(), void())
+{
+ for (std::size_t i = 0; i < N; ++i)
+ {
+ arr[i] = j.at(i).template get<T>();
+ }
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType,
+ enable_if_t<
+ std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
+ int> = 0>
+auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
+-> decltype(
+ arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
+ j.template get<typename ConstructibleArrayType::value_type>(),
+ void())
+{
+ using std::end;
+
+ ConstructibleArrayType ret;
+ ret.reserve(j.size());
+ std::transform(j.begin(), j.end(),
+ std::inserter(ret, end(ret)), [](const BasicJsonType & i)
+ {
+ // get<BasicJsonType>() returns *this, this won't call a from_json
+ // method when value_type is BasicJsonType
+ return i.template get<typename ConstructibleArrayType::value_type>();
+ });
+ arr = std::move(ret);
+}
+
+template<typename BasicJsonType, typename ConstructibleArrayType,
+ enable_if_t<
+ std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
+ int> = 0>
+void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
+ priority_tag<0> /*unused*/)
+{
+ using std::end;
+
+ ConstructibleArrayType ret;
+ std::transform(
+ j.begin(), j.end(), std::inserter(ret, end(ret)),
+ [](const BasicJsonType & i)
+ {
+ // get<BasicJsonType>() returns *this, this won't call a from_json
+ // method when value_type is BasicJsonType
+ return i.template get<typename ConstructibleArrayType::value_type>();
+ });
+ arr = std::move(ret);
+}
+
+template < typename BasicJsonType, typename ConstructibleArrayType,
+ enable_if_t <
+ is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
+ !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
+ !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
+ !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
+ !is_basic_json<ConstructibleArrayType>::value,
+ int > = 0 >
+auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
+-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
+j.template get<typename ConstructibleArrayType::value_type>(),
+void())
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+
+ from_json_array_impl(j, arr, priority_tag<3> {});
+}
+
+template < typename BasicJsonType, typename T, std::size_t... Idx >
+std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
+ identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
+{
+ return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
+}
+
+template < typename BasicJsonType, typename T, std::size_t N >
+auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
+-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+
+ return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
+}
+
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
+ {
+ JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j));
+ }
+
+ bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
+}
+
+template<typename BasicJsonType, typename ConstructibleObjectType,
+ enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
+void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
+ {
+ JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j));
+ }
+
+ ConstructibleObjectType ret;
+ const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
+ using value_type = typename ConstructibleObjectType::value_type;
+ std::transform(
+ inner_object->begin(), inner_object->end(),
+ std::inserter(ret, ret.begin()),
+ [](typename BasicJsonType::object_t::value_type const & p)
+ {
+ return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
+ });
+ obj = std::move(ret);
+}
+
+// overload for arithmetic types, not chosen for basic_json template arguments
+// (BooleanType, etc..); note: Is it really necessary to provide explicit
+// overloads for boolean_t etc. in case of a custom BooleanType which is not
+// an arithmetic type?
+template < typename BasicJsonType, typename ArithmeticType,
+ enable_if_t <
+ std::is_arithmetic<ArithmeticType>::value&&
+ !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
+ !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
+ !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
+ !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
+ int > = 0 >
+void from_json(const BasicJsonType& j, ArithmeticType& val)
+{
+ switch (static_cast<value_t>(j))
+ {
+ case value_t::number_unsigned:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
+ break;
+ }
+ case value_t::number_integer:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
+ break;
+ }
+ case value_t::number_float:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
+ break;
+ }
+ case value_t::boolean:
+ {
+ val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
+ break;
+ }
+
+ case value_t::null:
+ case value_t::object:
+ case value_t::array:
+ case value_t::string:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j));
+ }
+}
+
+template<typename BasicJsonType, typename... Args, std::size_t... Idx>
+std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
+{
+ return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
+}
+
+template < typename BasicJsonType, class A1, class A2 >
+std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
+{
+ return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
+ std::forward<BasicJsonType>(j).at(1).template get<A2>()};
+}
+
+template<typename BasicJsonType, typename A1, typename A2>
+void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
+{
+ p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
+}
+
+template<typename BasicJsonType, typename... Args>
+std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
+{
+ return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
+}
+
+template<typename BasicJsonType, typename... Args>
+void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
+{
+ t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
+}
+
+template<typename BasicJsonType, typename TupleRelated>
+auto from_json(BasicJsonType&& j, TupleRelated&& t)
+-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+
+ return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
+}
+
+template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
+ typename = enable_if_t < !std::is_constructible <
+ typename BasicJsonType::string_t, Key >::value >>
+void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+ m.clear();
+ for (const auto& p : j)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+ }
+ m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+ }
+}
+
+template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
+ typename = enable_if_t < !std::is_constructible <
+ typename BasicJsonType::string_t, Key >::value >>
+void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j));
+ }
+ m.clear();
+ for (const auto& p : j)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
+ {
+ JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j));
+ }
+ m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
+ }
+}
+
+#ifdef JSON_HAS_CPP_17
+template<typename BasicJsonType>
+void from_json(const BasicJsonType& j, std::filesystem::path& p)
+{
+ if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
+ {
+ JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j));
+ }
+ p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
+}
+#endif
+
+struct from_json_fn
+{
+ template<typename BasicJsonType, typename T>
+ auto operator()(const BasicJsonType& j, T&& val) const
+ noexcept(noexcept(from_json(j, std::forward<T>(val))))
+ -> decltype(from_json(j, std::forward<T>(val)))
+ {
+ return from_json(j, std::forward<T>(val));
+ }
+};
+} // namespace detail
+
+/// namespace to hold default `from_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
+{
+constexpr const auto& from_json = detail::static_const<detail::from_json_fn>::value; // NOLINT(misc-definitions-in-headers)
+} // namespace
+} // namespace nlohmann
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+
+#include <algorithm> // copy
+#include <iterator> // begin, end
+#include <string> // string
+#include <tuple> // tuple, get
+#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
+#include <utility> // move, forward, declval, pair
+#include <valarray> // valarray
+#include <vector> // vector
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+
+#include <cstddef> // size_t
+#include <iterator> // input_iterator_tag
+#include <string> // string, to_string
+#include <tuple> // tuple_size, get, tuple_element
+#include <utility> // move
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename string_type>
+void int_to_string( string_type& target, std::size_t value )
+{
+ // For ADL
+ using std::to_string;
+ target = to_string(value);
+}
+template<typename IteratorType> class iteration_proxy_value
+{
+ public:
+ using difference_type = std::ptrdiff_t;
+ using value_type = iteration_proxy_value;
+ using pointer = value_type * ;
+ using reference = value_type & ;
+ using iterator_category = std::input_iterator_tag;
+ using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
+
+ private:
+ /// the iterator
+ IteratorType anchor;
+ /// an index for arrays (used to create key names)
+ std::size_t array_index = 0;
+ /// last stringified array index
+ mutable std::size_t array_index_last = 0;
+ /// a string representation of the array index
+ mutable string_type array_index_str = "0";
+ /// an empty string (to return a reference for primitive values)
+ const string_type empty_str{};
+
+ public:
+ explicit iteration_proxy_value(IteratorType it) noexcept
+ : anchor(std::move(it))
+ {}
+
+ /// dereference operator (needed for range-based for)
+ iteration_proxy_value& operator*()
+ {
+ return *this;
+ }
+
+ /// increment operator (needed for range-based for)
+ iteration_proxy_value& operator++()
+ {
+ ++anchor;
+ ++array_index;
+
+ return *this;
+ }
+
+ /// equality operator (needed for InputIterator)
+ bool operator==(const iteration_proxy_value& o) const
+ {
+ return anchor == o.anchor;
+ }
+
+ /// inequality operator (needed for range-based for)
+ bool operator!=(const iteration_proxy_value& o) const
+ {
+ return anchor != o.anchor;
+ }
+
+ /// return key of the iterator
+ const string_type& key() const
+ {
+ JSON_ASSERT(anchor.m_object != nullptr);
+
+ switch (anchor.m_object->type())
+ {
+ // use integer array index as key
+ case value_t::array:
+ {
+ if (array_index != array_index_last)
+ {
+ int_to_string( array_index_str, array_index );
+ array_index_last = array_index;
+ }
+ return array_index_str;
+ }
+
+ // use key from the object
+ case value_t::object:
+ return anchor.key();
+
+ // use an empty key for all primitive types
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ return empty_str;
+ }
+ }
+
+ /// return value of the iterator
+ typename IteratorType::reference value() const
+ {
+ return anchor.value();
+ }
+};
+
+/// proxy class for the items() function
+template<typename IteratorType> class iteration_proxy
+{
+ private:
+ /// the container to iterate
+ typename IteratorType::reference container;
+
+ public:
+ /// construct iteration proxy from a container
+ explicit iteration_proxy(typename IteratorType::reference cont) noexcept
+ : container(cont) {}
+
+ /// return iterator begin (needed for range-based for)
+ iteration_proxy_value<IteratorType> begin() noexcept
+ {
+ return iteration_proxy_value<IteratorType>(container.begin());
+ }
+
+ /// return iterator end (needed for range-based for)
+ iteration_proxy_value<IteratorType> end() noexcept
+ {
+ return iteration_proxy_value<IteratorType>(container.end());
+ }
+};
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
+{
+ return i.key();
+}
+// Structured Bindings Support
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
+auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
+{
+ return i.value();
+}
+} // namespace detail
+} // namespace nlohmann
+
+// The Addition to the STD Namespace is required to add
+// Structured Bindings Support to the iteration_proxy_value class
+// For further reference see https://blog.tartanllama.xyz/structured-bindings/
+// And see https://github.com/nlohmann/json/pull/1391
+namespace std
+{
+#if defined(__clang__)
+ // Fix: https://github.com/nlohmann/json/issues/1401
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wmismatched-tags"
+#endif
+template<typename IteratorType>
+class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
+ : public std::integral_constant<std::size_t, 2> {};
+
+template<std::size_t N, typename IteratorType>
+class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
+{
+ public:
+ using type = decltype(
+ get<N>(std::declval <
+ ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
+};
+#if defined(__clang__)
+ #pragma clang diagnostic pop
+#endif
+} // namespace std
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+#ifdef JSON_HAS_CPP_17
+ #include <filesystem>
+#endif
+
+namespace nlohmann
+{
+namespace detail
+{
+//////////////////
+// constructors //
+//////////////////
+
+/*
+ * Note all external_constructor<>::construct functions need to call
+ * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
+ * allocated value (e.g., a string). See bug issue
+ * https://github.com/nlohmann/json/issues/2865 for more information.
+ */
+
+template<value_t> struct external_constructor;
+
+template<>
+struct external_constructor<value_t::boolean>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::boolean;
+ j.m_value = b;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::string>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::string;
+ j.m_value = s;
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::string;
+ j.m_value = std::move(s);
+ j.assert_invariant();
+ }
+
+ template < typename BasicJsonType, typename CompatibleStringType,
+ enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
+ int > = 0 >
+ static void construct(BasicJsonType& j, const CompatibleStringType& str)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::string;
+ j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::binary>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::binary;
+ j.m_value = typename BasicJsonType::binary_t(b);
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::binary;
+ j.m_value = typename BasicJsonType::binary_t(std::move(b));
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::number_float>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::number_float;
+ j.m_value = val;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::number_unsigned>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::number_unsigned;
+ j.m_value = val;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::number_integer>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::number_integer;
+ j.m_value = val;
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::array>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::array;
+ j.m_value = arr;
+ j.set_parents();
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::array;
+ j.m_value = std::move(arr);
+ j.set_parents();
+ j.assert_invariant();
+ }
+
+ template < typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
+ int > = 0 >
+ static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
+ {
+ using std::begin;
+ using std::end;
+
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::array;
+ j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
+ j.set_parents();
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const std::vector<bool>& arr)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::array;
+ j.m_value = value_t::array;
+ j.m_value.array->reserve(arr.size());
+ for (const bool x : arr)
+ {
+ j.m_value.array->push_back(x);
+ j.set_parent(j.m_value.array->back());
+ }
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+ static void construct(BasicJsonType& j, const std::valarray<T>& arr)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::array;
+ j.m_value = value_t::array;
+ j.m_value.array->resize(arr.size());
+ if (arr.size() > 0)
+ {
+ std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
+ }
+ j.set_parents();
+ j.assert_invariant();
+ }
+};
+
+template<>
+struct external_constructor<value_t::object>
+{
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::object;
+ j.m_value = obj;
+ j.set_parents();
+ j.assert_invariant();
+ }
+
+ template<typename BasicJsonType>
+ static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+ {
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::object;
+ j.m_value = std::move(obj);
+ j.set_parents();
+ j.assert_invariant();
+ }
+
+ template < typename BasicJsonType, typename CompatibleObjectType,
+ enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
+ static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
+ {
+ using std::begin;
+ using std::end;
+
+ j.m_value.destroy(j.m_type);
+ j.m_type = value_t::object;
+ j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
+ j.set_parents();
+ j.assert_invariant();
+ }
+};
+
+/////////////
+// to_json //
+/////////////
+
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
+void to_json(BasicJsonType& j, T b) noexcept
+{
+ external_constructor<value_t::boolean>::construct(j, b);
+}
+
+template<typename BasicJsonType, typename CompatibleString,
+ enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
+void to_json(BasicJsonType& j, const CompatibleString& s)
+{
+ external_constructor<value_t::string>::construct(j, s);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
+{
+ external_constructor<value_t::string>::construct(j, std::move(s));
+}
+
+template<typename BasicJsonType, typename FloatType,
+ enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
+void to_json(BasicJsonType& j, FloatType val) noexcept
+{
+ external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
+ enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
+{
+ external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
+}
+
+template<typename BasicJsonType, typename CompatibleNumberIntegerType,
+ enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
+void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
+{
+ external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
+}
+
+template<typename BasicJsonType, typename EnumType,
+ enable_if_t<std::is_enum<EnumType>::value, int> = 0>
+void to_json(BasicJsonType& j, EnumType e) noexcept
+{
+ using underlying_type = typename std::underlying_type<EnumType>::type;
+ external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const std::vector<bool>& e)
+{
+ external_constructor<value_t::array>::construct(j, e);
+}
+
+template < typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t < is_compatible_array_type<BasicJsonType,
+ CompatibleArrayType>::value&&
+ !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
+ !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
+ !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
+ !is_basic_json<CompatibleArrayType>::value,
+ int > = 0 >
+void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
+{
+ external_constructor<value_t::array>::construct(j, arr);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
+{
+ external_constructor<value_t::binary>::construct(j, bin);
+}
+
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
+void to_json(BasicJsonType& j, const std::valarray<T>& arr)
+{
+ external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
+{
+ external_constructor<value_t::array>::construct(j, std::move(arr));
+}
+
+template < typename BasicJsonType, typename CompatibleObjectType,
+ enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
+void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
+{
+ external_constructor<value_t::object>::construct(j, obj);
+}
+
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
+{
+ external_constructor<value_t::object>::construct(j, std::move(obj));
+}
+
+template <
+ typename BasicJsonType, typename T, std::size_t N,
+ enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
+ const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ int > = 0 >
+void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+{
+ external_constructor<value_t::array>::construct(j, arr);
+}
+
+template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
+void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
+{
+ j = { p.first, p.second };
+}
+
+// for https://github.com/nlohmann/json/pull/1134
+template<typename BasicJsonType, typename T,
+ enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
+void to_json(BasicJsonType& j, const T& b)
+{
+ j = { {b.key(), b.value()} };
+}
+
+template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
+void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
+{
+ j = { std::get<Idx>(t)... };
+}
+
+template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
+void to_json(BasicJsonType& j, const T& t)
+{
+ to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
+}
+
+#ifdef JSON_HAS_CPP_17
+template<typename BasicJsonType>
+void to_json(BasicJsonType& j, const std::filesystem::path& p)
+{
+ j = p.string();
+}
+#endif
+
+struct to_json_fn
+{
+ template<typename BasicJsonType, typename T>
+ auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
+ -> decltype(to_json(j, std::forward<T>(val)), void())
+ {
+ return to_json(j, std::forward<T>(val));
+ }
+};
+} // namespace detail
+
+/// namespace to hold default `to_json` function
+/// to see why this is required:
+/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
+namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
+{
+constexpr const auto& to_json = detail::static_const<detail::to_json_fn>::value; // NOLINT(misc-definitions-in-headers)
+} // namespace
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/identity_tag.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+
+template<typename ValueType, typename>
+struct adl_serializer
+{
+ /*!
+ @brief convert a JSON value to any value type
+
+ This function is usually called by the `get()` function of the
+ @ref basic_json class (either explicit or via conversion operators).
+
+ @note This function is chosen for default-constructible value types.
+
+ @param[in] j JSON value to read from
+ @param[in,out] val value to write to
+ */
+ template<typename BasicJsonType, typename TargetType = ValueType>
+ static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
+ noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
+ -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
+ {
+ ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
+ }
+
+ /*!
+ @brief convert a JSON value to any value type
+
+ This function is usually called by the `get()` function of the
+ @ref basic_json class (either explicit or via conversion operators).
+
+ @note This function is chosen for value types which are not default-constructible.
+
+ @param[in] j JSON value to read from
+
+ @return copy of the JSON value, converted to @a ValueType
+ */
+ template<typename BasicJsonType, typename TargetType = ValueType>
+ static auto from_json(BasicJsonType && j) noexcept(
+ noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
+ -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
+ {
+ return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
+ }
+
+ /*!
+ @brief convert any value type to a JSON value
+
+ This function is usually called by the constructors of the @ref basic_json
+ class.
+
+ @param[in,out] j JSON value to write to
+ @param[in] val value to read from
+ */
+ template<typename BasicJsonType, typename TargetType = ValueType>
+ static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
+ noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
+ -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
+ {
+ ::nlohmann::to_json(j, std::forward<TargetType>(val));
+ }
+};
+} // namespace nlohmann
+
+// #include <nlohmann/byte_container_with_subtype.hpp>
+
+
+#include <cstdint> // uint8_t, uint64_t
+#include <tuple> // tie
+#include <utility> // move
+
+namespace nlohmann
+{
+
+/*!
+@brief an internal type for a backed binary type
+
+This type extends the template parameter @a BinaryType provided to `basic_json`
+with a subtype used by BSON and MessagePack. This type exists so that the user
+does not have to specify a type themselves with a specific naming scheme in
+order to override the binary type.
+
+@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
+ default)
+
+@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.10.0.
+*/
+template<typename BinaryType>
+class byte_container_with_subtype : public BinaryType
+{
+ public:
+ /// the type of the underlying container
+ using container_type = BinaryType;
+ /// the type of the subtype
+ using subtype_type = std::uint64_t;
+
+ byte_container_with_subtype() noexcept(noexcept(container_type()))
+ : container_type()
+ {}
+
+ byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
+ : container_type(b)
+ {}
+
+ byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
+ : container_type(std::move(b))
+ {}
+
+ byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
+ : container_type(b)
+ , m_subtype(subtype_)
+ , m_has_subtype(true)
+ {}
+
+ byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
+ : container_type(std::move(b))
+ , m_subtype(subtype_)
+ , m_has_subtype(true)
+ {}
+
+ bool operator==(const byte_container_with_subtype& rhs) const
+ {
+ return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
+ std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
+ }
+
+ bool operator!=(const byte_container_with_subtype& rhs) const
+ {
+ return !(rhs == *this);
+ }
+
+ /*!
+ @brief sets the binary subtype
+
+ Sets the binary subtype of the value, also flags a binary JSON value as
+ having a subtype, which has implications for serialization.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @sa see @ref subtype() -- return the binary subtype
+ @sa see @ref clear_subtype() -- clears the binary subtype
+ @sa see @ref has_subtype() -- returns whether or not the binary value has a
+ subtype
+
+ @since version 3.8.0
+ */
+ void set_subtype(subtype_type subtype_) noexcept
+ {
+ m_subtype = subtype_;
+ m_has_subtype = true;
+ }
+
+ /*!
+ @brief return the binary subtype
+
+ Returns the numerical subtype of the value if it has a subtype. If it does
+ not have a subtype, this function will return subtype_type(-1) as a sentinel
+ value.
+
+ @return the numerical subtype of the binary value
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @sa see @ref set_subtype() -- sets the binary subtype
+ @sa see @ref clear_subtype() -- clears the binary subtype
+ @sa see @ref has_subtype() -- returns whether or not the binary value has a
+ subtype
+
+ @since version 3.8.0; fixed return value to properly return
+ subtype_type(-1) as documented in version 3.10.0
+ */
+ constexpr subtype_type subtype() const noexcept
+ {
+ return m_has_subtype ? m_subtype : subtype_type(-1);
+ }
+
+ /*!
+ @brief return whether the value has a subtype
+
+ @return whether the value has a subtype
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @sa see @ref subtype() -- return the binary subtype
+ @sa see @ref set_subtype() -- sets the binary subtype
+ @sa see @ref clear_subtype() -- clears the binary subtype
+
+ @since version 3.8.0
+ */
+ constexpr bool has_subtype() const noexcept
+ {
+ return m_has_subtype;
+ }
+
+ /*!
+ @brief clears the binary subtype
+
+ Clears the binary subtype and flags the value as not having a subtype, which
+ has implications for serialization; for instance MessagePack will prefer the
+ bin family over the ext family.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @sa see @ref subtype() -- return the binary subtype
+ @sa see @ref set_subtype() -- sets the binary subtype
+ @sa see @ref has_subtype() -- returns whether or not the binary value has a
+ subtype
+
+ @since version 3.8.0
+ */
+ void clear_subtype() noexcept
+ {
+ m_subtype = 0;
+ m_has_subtype = false;
+ }
+
+ private:
+ subtype_type m_subtype = 0;
+ bool m_has_subtype = false;
+};
+
+} // namespace nlohmann
+
+// #include <nlohmann/detail/conversions/from_json.hpp>
+
+// #include <nlohmann/detail/conversions/to_json.hpp>
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/hash.hpp>
+
+
+#include <cstdint> // uint8_t
+#include <cstddef> // size_t
+#include <functional> // hash
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+// boost::hash_combine
+inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
+{
+ seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
+ return seed;
+}
+
+/*!
+@brief hash a JSON value
+
+The hash function tries to rely on std::hash where possible. Furthermore, the
+type of the JSON value is taken into account to have different hash values for
+null, 0, 0U, and false, etc.
+
+@tparam BasicJsonType basic_json specialization
+@param j JSON value to hash
+@return hash value of j
+*/
+template<typename BasicJsonType>
+std::size_t hash(const BasicJsonType& j)
+{
+ using string_t = typename BasicJsonType::string_t;
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+
+ const auto type = static_cast<std::size_t>(j.type());
+ switch (j.type())
+ {
+ case BasicJsonType::value_t::null:
+ case BasicJsonType::value_t::discarded:
+ {
+ return combine(type, 0);
+ }
+
+ case BasicJsonType::value_t::object:
+ {
+ auto seed = combine(type, j.size());
+ for (const auto& element : j.items())
+ {
+ const auto h = std::hash<string_t> {}(element.key());
+ seed = combine(seed, h);
+ seed = combine(seed, hash(element.value()));
+ }
+ return seed;
+ }
+
+ case BasicJsonType::value_t::array:
+ {
+ auto seed = combine(type, j.size());
+ for (const auto& element : j)
+ {
+ seed = combine(seed, hash(element));
+ }
+ return seed;
+ }
+
+ case BasicJsonType::value_t::string:
+ {
+ const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
+ return combine(type, h);
+ }
+
+ case BasicJsonType::value_t::boolean:
+ {
+ const auto h = std::hash<bool> {}(j.template get<bool>());
+ return combine(type, h);
+ }
+
+ case BasicJsonType::value_t::number_integer:
+ {
+ const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
+ return combine(type, h);
+ }
+
+ case BasicJsonType::value_t::number_unsigned:
+ {
+ const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
+ return combine(type, h);
+ }
+
+ case BasicJsonType::value_t::number_float:
+ {
+ const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
+ return combine(type, h);
+ }
+
+ case BasicJsonType::value_t::binary:
+ {
+ auto seed = combine(type, j.get_binary().size());
+ const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
+ seed = combine(seed, h);
+ seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
+ for (const auto byte : j.get_binary())
+ {
+ seed = combine(seed, std::hash<std::uint8_t> {}(byte));
+ }
+ return seed;
+ }
+
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ return 0; // LCOV_EXCL_LINE
+ }
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+
+#include <algorithm> // generate_n
+#include <array> // array
+#include <cmath> // ldexp
+#include <cstddef> // size_t
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstdio> // snprintf
+#include <cstring> // memcpy
+#include <iterator> // back_inserter
+#include <limits> // numeric_limits
+#include <string> // char_traits, string
+#include <utility> // make_pair, move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+
+#include <array> // array
+#include <cstddef> // size_t
+#include <cstring> // strlen
+#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
+#include <memory> // shared_ptr, make_shared, addressof
+#include <numeric> // accumulate
+#include <string> // string, char_traits
+#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
+#include <utility> // pair, declval
+
+#ifndef JSON_NO_IO
+ #include <cstdio> // FILE *
+ #include <istream> // istream
+#endif // JSON_NO_IO
+
+// #include <nlohmann/detail/iterators/iterator_traits.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// the supported input formats
+enum class input_format_t { json, cbor, msgpack, ubjson, bson };
+
+////////////////////
+// input adapters //
+////////////////////
+
+#ifndef JSON_NO_IO
+/*!
+Input adapter for stdio file access. This adapter read only 1 byte and do not use any
+ buffer. This adapter is a very low level adapter.
+*/
+class file_input_adapter
+{
+ public:
+ using char_type = char;
+
+ JSON_HEDLEY_NON_NULL(2)
+ explicit file_input_adapter(std::FILE* f) noexcept
+ : m_file(f)
+ {}
+
+ // make class move-only
+ file_input_adapter(const file_input_adapter&) = delete;
+ file_input_adapter(file_input_adapter&&) noexcept = default;
+ file_input_adapter& operator=(const file_input_adapter&) = delete;
+ file_input_adapter& operator=(file_input_adapter&&) = delete;
+ ~file_input_adapter() = default;
+
+ std::char_traits<char>::int_type get_character() noexcept
+ {
+ return std::fgetc(m_file);
+ }
+
+ private:
+ /// the file pointer to read from
+ std::FILE* m_file;
+};
+
+
+/*!
+Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
+beginning of input. Does not support changing the underlying std::streambuf
+in mid-input. Maintains underlying std::istream and std::streambuf to support
+subsequent use of standard std::istream operations to process any input
+characters following those used in parsing the JSON input. Clears the
+std::istream flags; any input errors (e.g., EOF) will be detected by the first
+subsequent call for input from the std::istream.
+*/
+class input_stream_adapter
+{
+ public:
+ using char_type = char;
+
+ ~input_stream_adapter()
+ {
+ // clear stream flags; we use underlying streambuf I/O, do not
+ // maintain ifstream flags, except eof
+ if (is != nullptr)
+ {
+ is->clear(is->rdstate() & std::ios::eofbit);
+ }
+ }
+
+ explicit input_stream_adapter(std::istream& i)
+ : is(&i), sb(i.rdbuf())
+ {}
+
+ // delete because of pointer members
+ input_stream_adapter(const input_stream_adapter&) = delete;
+ input_stream_adapter& operator=(input_stream_adapter&) = delete;
+ input_stream_adapter& operator=(input_stream_adapter&&) = delete;
+
+ input_stream_adapter(input_stream_adapter&& rhs) noexcept
+ : is(rhs.is), sb(rhs.sb)
+ {
+ rhs.is = nullptr;
+ rhs.sb = nullptr;
+ }
+
+ // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
+ // ensure that std::char_traits<char>::eof() and the character 0xFF do not
+ // end up as the same value, eg. 0xFFFFFFFF.
+ std::char_traits<char>::int_type get_character()
+ {
+ auto res = sb->sbumpc();
+ // set eof manually, as we don't use the istream interface.
+ if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
+ {
+ is->clear(is->rdstate() | std::ios::eofbit);
+ }
+ return res;
+ }
+
+ private:
+ /// the associated input stream
+ std::istream* is = nullptr;
+ std::streambuf* sb = nullptr;
+};
+#endif // JSON_NO_IO
+
+// General-purpose iterator-based adapter. It might not be as fast as
+// theoretically possible for some containers, but it is extremely versatile.
+template<typename IteratorType>
+class iterator_input_adapter
+{
+ public:
+ using char_type = typename std::iterator_traits<IteratorType>::value_type;
+
+ iterator_input_adapter(IteratorType first, IteratorType last)
+ : current(std::move(first)), end(std::move(last))
+ {}
+
+ typename std::char_traits<char_type>::int_type get_character()
+ {
+ if (JSON_HEDLEY_LIKELY(current != end))
+ {
+ auto result = std::char_traits<char_type>::to_int_type(*current);
+ std::advance(current, 1);
+ return result;
+ }
+
+ return std::char_traits<char_type>::eof();
+ }
+
+ private:
+ IteratorType current;
+ IteratorType end;
+
+ template<typename BaseInputAdapter, size_t T>
+ friend struct wide_string_input_helper;
+
+ bool empty() const
+ {
+ return current == end;
+ }
+};
+
+
+template<typename BaseInputAdapter, size_t T>
+struct wide_string_input_helper;
+
+template<typename BaseInputAdapter>
+struct wide_string_input_helper<BaseInputAdapter, 4>
+{
+ // UTF-32
+ static void fill_buffer(BaseInputAdapter& input,
+ std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+ size_t& utf8_bytes_index,
+ size_t& utf8_bytes_filled)
+ {
+ utf8_bytes_index = 0;
+
+ if (JSON_HEDLEY_UNLIKELY(input.empty()))
+ {
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const auto wc = input.get_character();
+
+ // UTF-32 to UTF-8 encoding
+ if (wc < 0x80)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
+ utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+ utf8_bytes_filled = 2;
+ }
+ else if (wc <= 0xFFFF)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
+ utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+ utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+ utf8_bytes_filled = 3;
+ }
+ else if (wc <= 0x10FFFF)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
+ utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
+ utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+ utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+ utf8_bytes_filled = 4;
+ }
+ else
+ {
+ // unknown character
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+ utf8_bytes_filled = 1;
+ }
+ }
+ }
+};
+
+template<typename BaseInputAdapter>
+struct wide_string_input_helper<BaseInputAdapter, 2>
+{
+ // UTF-16
+ static void fill_buffer(BaseInputAdapter& input,
+ std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
+ size_t& utf8_bytes_index,
+ size_t& utf8_bytes_filled)
+ {
+ utf8_bytes_index = 0;
+
+ if (JSON_HEDLEY_UNLIKELY(input.empty()))
+ {
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const auto wc = input.get_character();
+
+ // UTF-16 to UTF-8 encoding
+ if (wc < 0x80)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
+ utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+ utf8_bytes_filled = 2;
+ }
+ else if (0xD800 > wc || wc >= 0xE000)
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
+ utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
+ utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
+ utf8_bytes_filled = 3;
+ }
+ else
+ {
+ if (JSON_HEDLEY_UNLIKELY(!input.empty()))
+ {
+ const auto wc2 = static_cast<unsigned int>(input.get_character());
+ const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
+ utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
+ utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
+ utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
+ utf8_bytes_filled = 4;
+ }
+ else
+ {
+ utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
+ utf8_bytes_filled = 1;
+ }
+ }
+ }
+ }
+};
+
+// Wraps another input apdater to convert wide character types into individual bytes.
+template<typename BaseInputAdapter, typename WideCharType>
+class wide_string_input_adapter
+{
+ public:
+ using char_type = char;
+
+ wide_string_input_adapter(BaseInputAdapter base)
+ : base_adapter(base) {}
+
+ typename std::char_traits<char>::int_type get_character() noexcept
+ {
+ // check if buffer needs to be filled
+ if (utf8_bytes_index == utf8_bytes_filled)
+ {
+ fill_buffer<sizeof(WideCharType)>();
+
+ JSON_ASSERT(utf8_bytes_filled > 0);
+ JSON_ASSERT(utf8_bytes_index == 0);
+ }
+
+ // use buffer
+ JSON_ASSERT(utf8_bytes_filled > 0);
+ JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
+ return utf8_bytes[utf8_bytes_index++];
+ }
+
+ private:
+ BaseInputAdapter base_adapter;
+
+ template<size_t T>
+ void fill_buffer()
+ {
+ wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
+ }
+
+ /// a buffer for UTF-8 bytes
+ std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
+
+ /// index to the utf8_codes array for the next valid byte
+ std::size_t utf8_bytes_index = 0;
+ /// number of valid bytes in the utf8_codes array
+ std::size_t utf8_bytes_filled = 0;
+};
+
+
+template<typename IteratorType, typename Enable = void>
+struct iterator_input_adapter_factory
+{
+ using iterator_type = IteratorType;
+ using char_type = typename std::iterator_traits<iterator_type>::value_type;
+ using adapter_type = iterator_input_adapter<iterator_type>;
+
+ static adapter_type create(IteratorType first, IteratorType last)
+ {
+ return adapter_type(std::move(first), std::move(last));
+ }
+};
+
+template<typename T>
+struct is_iterator_of_multibyte
+{
+ using value_type = typename std::iterator_traits<T>::value_type;
+ enum
+ {
+ value = sizeof(value_type) > 1
+ };
+};
+
+template<typename IteratorType>
+struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
+{
+ using iterator_type = IteratorType;
+ using char_type = typename std::iterator_traits<iterator_type>::value_type;
+ using base_adapter_type = iterator_input_adapter<iterator_type>;
+ using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
+
+ static adapter_type create(IteratorType first, IteratorType last)
+ {
+ return adapter_type(base_adapter_type(std::move(first), std::move(last)));
+ }
+};
+
+// General purpose iterator-based input
+template<typename IteratorType>
+typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
+{
+ using factory_type = iterator_input_adapter_factory<IteratorType>;
+ return factory_type::create(first, last);
+}
+
+// Convenience shorthand from container to iterator
+// Enables ADL on begin(container) and end(container)
+// Encloses the using declarations in namespace for not to leak them to outside scope
+
+namespace container_input_adapter_factory_impl
+{
+
+using std::begin;
+using std::end;
+
+template<typename ContainerType, typename Enable = void>
+struct container_input_adapter_factory {};
+
+template<typename ContainerType>
+struct container_input_adapter_factory< ContainerType,
+ void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
+ {
+ using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
+
+ static adapter_type create(const ContainerType& container)
+{
+ return input_adapter(begin(container), end(container));
+}
+ };
+
+} // namespace container_input_adapter_factory_impl
+
+template<typename ContainerType>
+typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
+{
+ return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
+}
+
+#ifndef JSON_NO_IO
+// Special cases with fast paths
+inline file_input_adapter input_adapter(std::FILE* file)
+{
+ return file_input_adapter(file);
+}
+
+inline input_stream_adapter input_adapter(std::istream& stream)
+{
+ return input_stream_adapter(stream);
+}
+
+inline input_stream_adapter input_adapter(std::istream&& stream)
+{
+ return input_stream_adapter(stream);
+}
+#endif // JSON_NO_IO
+
+using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
+
+// Null-delimited strings, and the like.
+template < typename CharT,
+ typename std::enable_if <
+ std::is_pointer<CharT>::value&&
+ !std::is_array<CharT>::value&&
+ std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
+ sizeof(typename std::remove_pointer<CharT>::type) == 1,
+ int >::type = 0 >
+contiguous_bytes_input_adapter input_adapter(CharT b)
+{
+ auto length = std::strlen(reinterpret_cast<const char*>(b));
+ const auto* ptr = reinterpret_cast<const char*>(b);
+ return input_adapter(ptr, ptr + length);
+}
+
+template<typename T, std::size_t N>
+auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+{
+ return input_adapter(array, array + N);
+}
+
+// This class only handles inputs of input_buffer_adapter type.
+// It's required so that expressions like {ptr, len} can be implicitly casted
+// to the correct adapter.
+class span_input_adapter
+{
+ public:
+ template < typename CharT,
+ typename std::enable_if <
+ std::is_pointer<CharT>::value&&
+ std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
+ sizeof(typename std::remove_pointer<CharT>::type) == 1,
+ int >::type = 0 >
+ span_input_adapter(CharT b, std::size_t l)
+ : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
+
+ template<class IteratorType,
+ typename std::enable_if<
+ std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
+ int>::type = 0>
+ span_input_adapter(IteratorType first, IteratorType last)
+ : ia(input_adapter(first, last)) {}
+
+ contiguous_bytes_input_adapter&& get()
+ {
+ return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
+ }
+
+ private:
+ contiguous_bytes_input_adapter ia;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+
+#include <cstddef>
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+
+/*!
+@brief SAX interface
+
+This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
+Each function is called in different situations while the input is parsed. The
+boolean return value informs the parser whether to continue processing the
+input.
+*/
+template<typename BasicJsonType>
+struct json_sax
+{
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+
+ /*!
+ @brief a null value was read
+ @return whether parsing should proceed
+ */
+ virtual bool null() = 0;
+
+ /*!
+ @brief a boolean value was read
+ @param[in] val boolean value
+ @return whether parsing should proceed
+ */
+ virtual bool boolean(bool val) = 0;
+
+ /*!
+ @brief an integer number was read
+ @param[in] val integer value
+ @return whether parsing should proceed
+ */
+ virtual bool number_integer(number_integer_t val) = 0;
+
+ /*!
+ @brief an unsigned integer number was read
+ @param[in] val unsigned integer value
+ @return whether parsing should proceed
+ */
+ virtual bool number_unsigned(number_unsigned_t val) = 0;
+
+ /*!
+ @brief an floating-point number was read
+ @param[in] val floating-point value
+ @param[in] s raw token value
+ @return whether parsing should proceed
+ */
+ virtual bool number_float(number_float_t val, const string_t& s) = 0;
+
+ /*!
+ @brief a string was read
+ @param[in] val string value
+ @return whether parsing should proceed
+ @note It is safe to move the passed string.
+ */
+ virtual bool string(string_t& val) = 0;
+
+ /*!
+ @brief a binary string was read
+ @param[in] val binary value
+ @return whether parsing should proceed
+ @note It is safe to move the passed binary.
+ */
+ virtual bool binary(binary_t& val) = 0;
+
+ /*!
+ @brief the beginning of an object was read
+ @param[in] elements number of object elements or -1 if unknown
+ @return whether parsing should proceed
+ @note binary formats may report the number of elements
+ */
+ virtual bool start_object(std::size_t elements) = 0;
+
+ /*!
+ @brief an object key was read
+ @param[in] val object key
+ @return whether parsing should proceed
+ @note It is safe to move the passed string.
+ */
+ virtual bool key(string_t& val) = 0;
+
+ /*!
+ @brief the end of an object was read
+ @return whether parsing should proceed
+ */
+ virtual bool end_object() = 0;
+
+ /*!
+ @brief the beginning of an array was read
+ @param[in] elements number of array elements or -1 if unknown
+ @return whether parsing should proceed
+ @note binary formats may report the number of elements
+ */
+ virtual bool start_array(std::size_t elements) = 0;
+
+ /*!
+ @brief the end of an array was read
+ @return whether parsing should proceed
+ */
+ virtual bool end_array() = 0;
+
+ /*!
+ @brief a parse error occurred
+ @param[in] position the position in the input where the error occurs
+ @param[in] last_token the last read token
+ @param[in] ex an exception object describing the error
+ @return whether parsing should proceed (must return false)
+ */
+ virtual bool parse_error(std::size_t position,
+ const std::string& last_token,
+ const detail::exception& ex) = 0;
+
+ json_sax() = default;
+ json_sax(const json_sax&) = default;
+ json_sax(json_sax&&) noexcept = default;
+ json_sax& operator=(const json_sax&) = default;
+ json_sax& operator=(json_sax&&) noexcept = default;
+ virtual ~json_sax() = default;
+};
+
+
+namespace detail
+{
+/*!
+@brief SAX implementation to create a JSON value from SAX events
+
+This class implements the @ref json_sax interface and processes the SAX events
+to create a JSON value which makes it basically a DOM parser. The structure or
+hierarchy of the JSON value is managed by the stack `ref_stack` which contains
+a pointer to the respective array or object for each recursion depth.
+
+After successful parsing, the value that is passed by reference to the
+constructor contains the parsed value.
+
+@tparam BasicJsonType the JSON type
+*/
+template<typename BasicJsonType>
+class json_sax_dom_parser
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+
+ /*!
+ @param[in,out] r reference to a JSON value that is manipulated while
+ parsing
+ @param[in] allow_exceptions_ whether parse errors yield exceptions
+ */
+ explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
+ : root(r), allow_exceptions(allow_exceptions_)
+ {}
+
+ // make class move-only
+ json_sax_dom_parser(const json_sax_dom_parser&) = delete;
+ json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
+ json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ ~json_sax_dom_parser() = default;
+
+ bool null()
+ {
+ handle_value(nullptr);
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_integer(number_integer_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t& /*unused*/)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool string(string_t& val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool binary(binary_t& val)
+ {
+ handle_value(std::move(val));
+ return true;
+ }
+
+ bool start_object(std::size_t len)
+ {
+ ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
+
+ if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+ }
+
+ return true;
+ }
+
+ bool key(string_t& val)
+ {
+ // add null at given key and store the reference for later
+ object_element = &(ref_stack.back()->m_value.object->operator[](val));
+ return true;
+ }
+
+ bool end_object()
+ {
+ ref_stack.back()->set_parents();
+ ref_stack.pop_back();
+ return true;
+ }
+
+ bool start_array(std::size_t len)
+ {
+ ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
+
+ if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+ }
+
+ return true;
+ }
+
+ bool end_array()
+ {
+ ref_stack.back()->set_parents();
+ ref_stack.pop_back();
+ return true;
+ }
+
+ template<class Exception>
+ bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+ const Exception& ex)
+ {
+ errored = true;
+ static_cast<void>(ex);
+ if (allow_exceptions)
+ {
+ JSON_THROW(ex);
+ }
+ return false;
+ }
+
+ constexpr bool is_errored() const
+ {
+ return errored;
+ }
+
+ private:
+ /*!
+ @invariant If the ref stack is empty, then the passed value will be the new
+ root.
+ @invariant If the ref stack contains a value, then it is an array or an
+ object to which we can add elements
+ */
+ template<typename Value>
+ JSON_HEDLEY_RETURNS_NON_NULL
+ BasicJsonType* handle_value(Value&& v)
+ {
+ if (ref_stack.empty())
+ {
+ root = BasicJsonType(std::forward<Value>(v));
+ return &root;
+ }
+
+ JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
+
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
+ return &(ref_stack.back()->m_value.array->back());
+ }
+
+ JSON_ASSERT(ref_stack.back()->is_object());
+ JSON_ASSERT(object_element);
+ *object_element = BasicJsonType(std::forward<Value>(v));
+ return object_element;
+ }
+
+ /// the parsed JSON value
+ BasicJsonType& root;
+ /// stack to model hierarchy of values
+ std::vector<BasicJsonType*> ref_stack {};
+ /// helper to hold the reference for the next object element
+ BasicJsonType* object_element = nullptr;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+};
+
+template<typename BasicJsonType>
+class json_sax_dom_callback_parser
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+ using parser_callback_t = typename BasicJsonType::parser_callback_t;
+ using parse_event_t = typename BasicJsonType::parse_event_t;
+
+ json_sax_dom_callback_parser(BasicJsonType& r,
+ const parser_callback_t cb,
+ const bool allow_exceptions_ = true)
+ : root(r), callback(cb), allow_exceptions(allow_exceptions_)
+ {
+ keep_stack.push_back(true);
+ }
+
+ // make class move-only
+ json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
+ json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
+ json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ ~json_sax_dom_callback_parser() = default;
+
+ bool null()
+ {
+ handle_value(nullptr);
+ return true;
+ }
+
+ bool boolean(bool val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_integer(number_integer_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool number_float(number_float_t val, const string_t& /*unused*/)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool string(string_t& val)
+ {
+ handle_value(val);
+ return true;
+ }
+
+ bool binary(binary_t& val)
+ {
+ handle_value(std::move(val));
+ return true;
+ }
+
+ bool start_object(std::size_t len)
+ {
+ // check callback for object start
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
+ keep_stack.push_back(keep);
+
+ auto val = handle_value(BasicJsonType::value_t::object, true);
+ ref_stack.push_back(val.second);
+
+ // check object limit
+ if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back()));
+ }
+
+ return true;
+ }
+
+ bool key(string_t& val)
+ {
+ BasicJsonType k = BasicJsonType(val);
+
+ // check callback for key
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
+ key_keep_stack.push_back(keep);
+
+ // add discarded value at given key and store the reference for later
+ if (keep && ref_stack.back())
+ {
+ object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
+ }
+
+ return true;
+ }
+
+ bool end_object()
+ {
+ if (ref_stack.back())
+ {
+ if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
+ {
+ // discard object
+ *ref_stack.back() = discarded;
+ }
+ else
+ {
+ ref_stack.back()->set_parents();
+ }
+ }
+
+ JSON_ASSERT(!ref_stack.empty());
+ JSON_ASSERT(!keep_stack.empty());
+ ref_stack.pop_back();
+ keep_stack.pop_back();
+
+ if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
+ {
+ // remove discarded value
+ for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
+ {
+ if (it->is_discarded())
+ {
+ ref_stack.back()->erase(it);
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ bool start_array(std::size_t len)
+ {
+ const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
+ keep_stack.push_back(keep);
+
+ auto val = handle_value(BasicJsonType::value_t::array, true);
+ ref_stack.push_back(val.second);
+
+ // check array limit
+ if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size()))
+ {
+ JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back()));
+ }
+
+ return true;
+ }
+
+ bool end_array()
+ {
+ bool keep = true;
+
+ if (ref_stack.back())
+ {
+ keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
+ if (keep)
+ {
+ ref_stack.back()->set_parents();
+ }
+ else
+ {
+ // discard array
+ *ref_stack.back() = discarded;
+ }
+ }
+
+ JSON_ASSERT(!ref_stack.empty());
+ JSON_ASSERT(!keep_stack.empty());
+ ref_stack.pop_back();
+ keep_stack.pop_back();
+
+ // remove discarded value
+ if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->pop_back();
+ }
+
+ return true;
+ }
+
+ template<class Exception>
+ bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
+ const Exception& ex)
+ {
+ errored = true;
+ static_cast<void>(ex);
+ if (allow_exceptions)
+ {
+ JSON_THROW(ex);
+ }
+ return false;
+ }
+
+ constexpr bool is_errored() const
+ {
+ return errored;
+ }
+
+ private:
+ /*!
+ @param[in] v value to add to the JSON value we build during parsing
+ @param[in] skip_callback whether we should skip calling the callback
+ function; this is required after start_array() and
+ start_object() SAX events, because otherwise we would call the
+ callback function with an empty array or object, respectively.
+
+ @invariant If the ref stack is empty, then the passed value will be the new
+ root.
+ @invariant If the ref stack contains a value, then it is an array or an
+ object to which we can add elements
+
+ @return pair of boolean (whether value should be kept) and pointer (to the
+ passed value in the ref_stack hierarchy; nullptr if not kept)
+ */
+ template<typename Value>
+ std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
+ {
+ JSON_ASSERT(!keep_stack.empty());
+
+ // do not handle this value if we know it would be added to a discarded
+ // container
+ if (!keep_stack.back())
+ {
+ return {false, nullptr};
+ }
+
+ // create value
+ auto value = BasicJsonType(std::forward<Value>(v));
+
+ // check callback
+ const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
+
+ // do not handle this value if we just learnt it shall be discarded
+ if (!keep)
+ {
+ return {false, nullptr};
+ }
+
+ if (ref_stack.empty())
+ {
+ root = std::move(value);
+ return {true, &root};
+ }
+
+ // skip this value if we already decided to skip the parent
+ // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
+ if (!ref_stack.back())
+ {
+ return {false, nullptr};
+ }
+
+ // we now only expect arrays and objects
+ JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
+
+ // array
+ if (ref_stack.back()->is_array())
+ {
+ ref_stack.back()->m_value.array->emplace_back(std::move(value));
+ return {true, &(ref_stack.back()->m_value.array->back())};
+ }
+
+ // object
+ JSON_ASSERT(ref_stack.back()->is_object());
+ // check if we should store an element for the current key
+ JSON_ASSERT(!key_keep_stack.empty());
+ const bool store_element = key_keep_stack.back();
+ key_keep_stack.pop_back();
+
+ if (!store_element)
+ {
+ return {false, nullptr};
+ }
+
+ JSON_ASSERT(object_element);
+ *object_element = std::move(value);
+ return {true, object_element};
+ }
+
+ /// the parsed JSON value
+ BasicJsonType& root;
+ /// stack to model hierarchy of values
+ std::vector<BasicJsonType*> ref_stack {};
+ /// stack to manage which values to keep
+ std::vector<bool> keep_stack {};
+ /// stack to manage which object keys to keep
+ std::vector<bool> key_keep_stack {};
+ /// helper to hold the reference for the next object element
+ BasicJsonType* object_element = nullptr;
+ /// whether a syntax error occurred
+ bool errored = false;
+ /// callback function
+ const parser_callback_t callback = nullptr;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+ /// a discarded value for the callback
+ BasicJsonType discarded = BasicJsonType::value_t::discarded;
+};
+
+template<typename BasicJsonType>
+class json_sax_acceptor
+{
+ public:
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+
+ bool null()
+ {
+ return true;
+ }
+
+ bool boolean(bool /*unused*/)
+ {
+ return true;
+ }
+
+ bool number_integer(number_integer_t /*unused*/)
+ {
+ return true;
+ }
+
+ bool number_unsigned(number_unsigned_t /*unused*/)
+ {
+ return true;
+ }
+
+ bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
+ {
+ return true;
+ }
+
+ bool string(string_t& /*unused*/)
+ {
+ return true;
+ }
+
+ bool binary(binary_t& /*unused*/)
+ {
+ return true;
+ }
+
+ bool start_object(std::size_t /*unused*/ = std::size_t(-1))
+ {
+ return true;
+ }
+
+ bool key(string_t& /*unused*/)
+ {
+ return true;
+ }
+
+ bool end_object()
+ {
+ return true;
+ }
+
+ bool start_array(std::size_t /*unused*/ = std::size_t(-1))
+ {
+ return true;
+ }
+
+ bool end_array()
+ {
+ return true;
+ }
+
+ bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
+ {
+ return false;
+ }
+};
+} // namespace detail
+
+} // namespace nlohmann
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+
+#include <array> // array
+#include <clocale> // localeconv
+#include <cstddef> // size_t
+#include <cstdio> // snprintf
+#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
+#include <initializer_list> // initializer_list
+#include <string> // char_traits, string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/position_t.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////
+// lexer //
+///////////
+
+template<typename BasicJsonType>
+class lexer_base
+{
+ public:
+ /// token types for the parser
+ enum class token_type
+ {
+ uninitialized, ///< indicating the scanner is uninitialized
+ literal_true, ///< the `true` literal
+ literal_false, ///< the `false` literal
+ literal_null, ///< the `null` literal
+ value_string, ///< a string -- use get_string() for actual value
+ value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value
+ value_integer, ///< a signed integer -- use get_number_integer() for actual value
+ value_float, ///< an floating point number -- use get_number_float() for actual value
+ begin_array, ///< the character for array begin `[`
+ begin_object, ///< the character for object begin `{`
+ end_array, ///< the character for array end `]`
+ end_object, ///< the character for object end `}`
+ name_separator, ///< the name separator `:`
+ value_separator, ///< the value separator `,`
+ parse_error, ///< indicating a parse error
+ end_of_input, ///< indicating the end of the input buffer
+ literal_or_value ///< a literal or the begin of a value (only for diagnostics)
+ };
+
+ /// return name of values of type token_type (only used for errors)
+ JSON_HEDLEY_RETURNS_NON_NULL
+ JSON_HEDLEY_CONST
+ static const char* token_type_name(const token_type t) noexcept
+ {
+ switch (t)
+ {
+ case token_type::uninitialized:
+ return "<uninitialized>";
+ case token_type::literal_true:
+ return "true literal";
+ case token_type::literal_false:
+ return "false literal";
+ case token_type::literal_null:
+ return "null literal";
+ case token_type::value_string:
+ return "string literal";
+ case token_type::value_unsigned:
+ case token_type::value_integer:
+ case token_type::value_float:
+ return "number literal";
+ case token_type::begin_array:
+ return "'['";
+ case token_type::begin_object:
+ return "'{'";
+ case token_type::end_array:
+ return "']'";
+ case token_type::end_object:
+ return "'}'";
+ case token_type::name_separator:
+ return "':'";
+ case token_type::value_separator:
+ return "','";
+ case token_type::parse_error:
+ return "<parse error>";
+ case token_type::end_of_input:
+ return "end of input";
+ case token_type::literal_or_value:
+ return "'[', '{', or a literal";
+ // LCOV_EXCL_START
+ default: // catch non-enum values
+ return "unknown token";
+ // LCOV_EXCL_STOP
+ }
+ }
+};
+/*!
+@brief lexical analysis
+
+This class organizes the lexical analysis during JSON deserialization.
+*/
+template<typename BasicJsonType, typename InputAdapterType>
+class lexer : public lexer_base<BasicJsonType>
+{
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using char_type = typename InputAdapterType::char_type;
+ using char_int_type = typename std::char_traits<char_type>::int_type;
+
+ public:
+ using token_type = typename lexer_base<BasicJsonType>::token_type;
+
+ explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
+ : ia(std::move(adapter))
+ , ignore_comments(ignore_comments_)
+ , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
+ {}
+
+ // delete because of pointer members
+ lexer(const lexer&) = delete;
+ lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ lexer& operator=(lexer&) = delete;
+ lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ ~lexer() = default;
+
+ private:
+ /////////////////////
+ // locales
+ /////////////////////
+
+ /// return the locale-dependent decimal point
+ JSON_HEDLEY_PURE
+ static char get_decimal_point() noexcept
+ {
+ const auto* loc = localeconv();
+ JSON_ASSERT(loc != nullptr);
+ return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
+ }
+
+ /////////////////////
+ // scan functions
+ /////////////////////
+
+ /*!
+ @brief get codepoint from 4 hex characters following `\u`
+
+ For input "\u c1 c2 c3 c4" the codepoint is:
+ (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
+ = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
+
+ Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
+ must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
+ conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
+ between the ASCII value of the character and the desired integer value.
+
+ @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
+ non-hex character)
+ */
+ int get_codepoint()
+ {
+ // this function only makes sense after reading `\u`
+ JSON_ASSERT(current == 'u');
+ int codepoint = 0;
+
+ const auto factors = { 12u, 8u, 4u, 0u };
+ for (const auto factor : factors)
+ {
+ get();
+
+ if (current >= '0' && current <= '9')
+ {
+ codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
+ }
+ else if (current >= 'A' && current <= 'F')
+ {
+ codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
+ }
+ else if (current >= 'a' && current <= 'f')
+ {
+ codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
+ return codepoint;
+ }
+
+ /*!
+ @brief check if the next byte(s) are inside a given range
+
+ Adds the current byte and, for each passed range, reads a new byte and
+ checks if it is inside the range. If a violation was detected, set up an
+ error message and return false. Otherwise, return true.
+
+ @param[in] ranges list of integers; interpreted as list of pairs of
+ inclusive lower and upper bound, respectively
+
+ @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
+ 1, 2, or 3 pairs. This precondition is enforced by an assertion.
+
+ @return true if and only if no range violation was detected
+ */
+ bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
+ {
+ JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
+ add(current);
+
+ for (auto range = ranges.begin(); range != ranges.end(); ++range)
+ {
+ get();
+ if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
+ {
+ add(current);
+ }
+ else
+ {
+ error_message = "invalid string: ill-formed UTF-8 byte";
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /*!
+ @brief scan a string literal
+
+ This function scans a string according to Sect. 7 of RFC 8259. While
+ scanning, bytes are escaped and copied into buffer token_buffer. Then the
+ function returns successfully, token_buffer is *not* null-terminated (as it
+ may contain \0 bytes), and token_buffer.size() is the number of bytes in the
+ string.
+
+ @return token_type::value_string if string could be successfully scanned,
+ token_type::parse_error otherwise
+
+ @note In case of errors, variable error_message contains a textual
+ description.
+ */
+ token_type scan_string()
+ {
+ // reset token_buffer (ignore opening quote)
+ reset();
+
+ // we entered the function by reading an open quote
+ JSON_ASSERT(current == '\"');
+
+ while (true)
+ {
+ // get next character
+ switch (get())
+ {
+ // end of file while parsing string
+ case std::char_traits<char_type>::eof():
+ {
+ error_message = "invalid string: missing closing quote";
+ return token_type::parse_error;
+ }
+
+ // closing quote
+ case '\"':
+ {
+ return token_type::value_string;
+ }
+
+ // escapes
+ case '\\':
+ {
+ switch (get())
+ {
+ // quotation mark
+ case '\"':
+ add('\"');
+ break;
+ // reverse solidus
+ case '\\':
+ add('\\');
+ break;
+ // solidus
+ case '/':
+ add('/');
+ break;
+ // backspace
+ case 'b':
+ add('\b');
+ break;
+ // form feed
+ case 'f':
+ add('\f');
+ break;
+ // line feed
+ case 'n':
+ add('\n');
+ break;
+ // carriage return
+ case 'r':
+ add('\r');
+ break;
+ // tab
+ case 't':
+ add('\t');
+ break;
+
+ // unicode escapes
+ case 'u':
+ {
+ const int codepoint1 = get_codepoint();
+ int codepoint = codepoint1; // start with codepoint1
+
+ if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
+ {
+ error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+ return token_type::parse_error;
+ }
+
+ // check if code point is a high surrogate
+ if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
+ {
+ // expect next \uxxxx entry
+ if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
+ {
+ const int codepoint2 = get_codepoint();
+
+ if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
+ {
+ error_message = "invalid string: '\\u' must be followed by 4 hex digits";
+ return token_type::parse_error;
+ }
+
+ // check if codepoint2 is a low surrogate
+ if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
+ {
+ // overwrite codepoint
+ codepoint = static_cast<int>(
+ // high surrogate occupies the most significant 22 bits
+ (static_cast<unsigned int>(codepoint1) << 10u)
+ // low surrogate occupies the least significant 15 bits
+ + static_cast<unsigned int>(codepoint2)
+ // there is still the 0xD800, 0xDC00 and 0x10000 noise
+ // in the result so we have to subtract with:
+ // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
+ - 0x35FDC00u);
+ }
+ else
+ {
+ error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
+ return token_type::parse_error;
+ }
+ }
+ else
+ {
+ error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
+ return token_type::parse_error;
+ }
+ }
+ else
+ {
+ if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
+ {
+ error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
+ return token_type::parse_error;
+ }
+ }
+
+ // result of the above calculation yields a proper codepoint
+ JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
+
+ // translate codepoint into bytes
+ if (codepoint < 0x80)
+ {
+ // 1-byte characters: 0xxxxxxx (ASCII)
+ add(static_cast<char_int_type>(codepoint));
+ }
+ else if (codepoint <= 0x7FF)
+ {
+ // 2-byte characters: 110xxxxx 10xxxxxx
+ add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
+ add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+ }
+ else if (codepoint <= 0xFFFF)
+ {
+ // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
+ add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
+ add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+ add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+ }
+ else
+ {
+ // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
+ add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
+ add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
+ add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
+ }
+
+ break;
+ }
+
+ // other characters after escape
+ default:
+ error_message = "invalid string: forbidden character after backslash";
+ return token_type::parse_error;
+ }
+
+ break;
+ }
+
+ // invalid control characters
+ case 0x00:
+ {
+ error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
+ return token_type::parse_error;
+ }
+
+ case 0x01:
+ {
+ error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
+ return token_type::parse_error;
+ }
+
+ case 0x02:
+ {
+ error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
+ return token_type::parse_error;
+ }
+
+ case 0x03:
+ {
+ error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
+ return token_type::parse_error;
+ }
+
+ case 0x04:
+ {
+ error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
+ return token_type::parse_error;
+ }
+
+ case 0x05:
+ {
+ error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
+ return token_type::parse_error;
+ }
+
+ case 0x06:
+ {
+ error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
+ return token_type::parse_error;
+ }
+
+ case 0x07:
+ {
+ error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
+ return token_type::parse_error;
+ }
+
+ case 0x08:
+ {
+ error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
+ return token_type::parse_error;
+ }
+
+ case 0x09:
+ {
+ error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
+ return token_type::parse_error;
+ }
+
+ case 0x0A:
+ {
+ error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
+ return token_type::parse_error;
+ }
+
+ case 0x0B:
+ {
+ error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
+ return token_type::parse_error;
+ }
+
+ case 0x0C:
+ {
+ error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
+ return token_type::parse_error;
+ }
+
+ case 0x0D:
+ {
+ error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
+ return token_type::parse_error;
+ }
+
+ case 0x0E:
+ {
+ error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
+ return token_type::parse_error;
+ }
+
+ case 0x0F:
+ {
+ error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
+ return token_type::parse_error;
+ }
+
+ case 0x10:
+ {
+ error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
+ return token_type::parse_error;
+ }
+
+ case 0x11:
+ {
+ error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
+ return token_type::parse_error;
+ }
+
+ case 0x12:
+ {
+ error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
+ return token_type::parse_error;
+ }
+
+ case 0x13:
+ {
+ error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
+ return token_type::parse_error;
+ }
+
+ case 0x14:
+ {
+ error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
+ return token_type::parse_error;
+ }
+
+ case 0x15:
+ {
+ error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
+ return token_type::parse_error;
+ }
+
+ case 0x16:
+ {
+ error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
+ return token_type::parse_error;
+ }
+
+ case 0x17:
+ {
+ error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
+ return token_type::parse_error;
+ }
+
+ case 0x18:
+ {
+ error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
+ return token_type::parse_error;
+ }
+
+ case 0x19:
+ {
+ error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
+ return token_type::parse_error;
+ }
+
+ case 0x1A:
+ {
+ error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
+ return token_type::parse_error;
+ }
+
+ case 0x1B:
+ {
+ error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
+ return token_type::parse_error;
+ }
+
+ case 0x1C:
+ {
+ error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
+ return token_type::parse_error;
+ }
+
+ case 0x1D:
+ {
+ error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
+ return token_type::parse_error;
+ }
+
+ case 0x1E:
+ {
+ error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
+ return token_type::parse_error;
+ }
+
+ case 0x1F:
+ {
+ error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
+ return token_type::parse_error;
+ }
+
+ // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
+ case 0x20:
+ case 0x21:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0x3B:
+ case 0x3C:
+ case 0x3D:
+ case 0x3E:
+ case 0x3F:
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B:
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78:
+ case 0x79:
+ case 0x7A:
+ case 0x7B:
+ case 0x7C:
+ case 0x7D:
+ case 0x7E:
+ case 0x7F:
+ {
+ add(current);
+ break;
+ }
+
+ // U+0080..U+07FF: bytes C2..DF 80..BF
+ case 0xC2:
+ case 0xC3:
+ case 0xC4:
+ case 0xC5:
+ case 0xC6:
+ case 0xC7:
+ case 0xC8:
+ case 0xC9:
+ case 0xCA:
+ case 0xCB:
+ case 0xCC:
+ case 0xCD:
+ case 0xCE:
+ case 0xCF:
+ case 0xD0:
+ case 0xD1:
+ case 0xD2:
+ case 0xD3:
+ case 0xD4:
+ case 0xD5:
+ case 0xD6:
+ case 0xD7:
+ case 0xD8:
+ case 0xD9:
+ case 0xDA:
+ case 0xDB:
+ case 0xDC:
+ case 0xDD:
+ case 0xDE:
+ case 0xDF:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
+ case 0xE0:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
+ // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
+ case 0xE1:
+ case 0xE2:
+ case 0xE3:
+ case 0xE4:
+ case 0xE5:
+ case 0xE6:
+ case 0xE7:
+ case 0xE8:
+ case 0xE9:
+ case 0xEA:
+ case 0xEB:
+ case 0xEC:
+ case 0xEE:
+ case 0xEF:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+D000..U+D7FF: bytes ED 80..9F 80..BF
+ case 0xED:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
+ case 0xF0:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
+ case 0xF1:
+ case 0xF2:
+ case 0xF3:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
+ case 0xF4:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
+ {
+ return token_type::parse_error;
+ }
+ break;
+ }
+
+ // remaining bytes (80..C1 and F5..FF) are ill-formed
+ default:
+ {
+ error_message = "invalid string: ill-formed UTF-8 byte";
+ return token_type::parse_error;
+ }
+ }
+ }
+ }
+
+ /*!
+ * @brief scan a comment
+ * @return whether comment could be scanned successfully
+ */
+ bool scan_comment()
+ {
+ switch (get())
+ {
+ // single-line comments skip input until a newline or EOF is read
+ case '/':
+ {
+ while (true)
+ {
+ switch (get())
+ {
+ case '\n':
+ case '\r':
+ case std::char_traits<char_type>::eof():
+ case '\0':
+ return true;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // multi-line comments skip input until */ is read
+ case '*':
+ {
+ while (true)
+ {
+ switch (get())
+ {
+ case std::char_traits<char_type>::eof():
+ case '\0':
+ {
+ error_message = "invalid comment; missing closing '*/'";
+ return false;
+ }
+
+ case '*':
+ {
+ switch (get())
+ {
+ case '/':
+ return true;
+
+ default:
+ {
+ unget();
+ continue;
+ }
+ }
+ }
+
+ default:
+ continue;
+ }
+ }
+ }
+
+ // unexpected character after reading '/'
+ default:
+ {
+ error_message = "invalid comment; expecting '/' or '*' after '/'";
+ return false;
+ }
+ }
+ }
+
+ JSON_HEDLEY_NON_NULL(2)
+ static void strtof(float& f, const char* str, char** endptr) noexcept
+ {
+ f = std::strtof(str, endptr);
+ }
+
+ JSON_HEDLEY_NON_NULL(2)
+ static void strtof(double& f, const char* str, char** endptr) noexcept
+ {
+ f = std::strtod(str, endptr);
+ }
+
+ JSON_HEDLEY_NON_NULL(2)
+ static void strtof(long double& f, const char* str, char** endptr) noexcept
+ {
+ f = std::strtold(str, endptr);
+ }
+
+ /*!
+ @brief scan a number literal
+
+ This function scans a string according to Sect. 6 of RFC 8259.
+
+ The function is realized with a deterministic finite state machine derived
+ from the grammar described in RFC 8259. Starting in state "init", the
+ input is read and used to determined the next state. Only state "done"
+ accepts the number. State "error" is a trap state to model errors. In the
+ table below, "anything" means any character but the ones listed before.
+
+ state | 0 | 1-9 | e E | + | - | . | anything
+ ---------|----------|----------|----------|---------|---------|----------|-----------
+ init | zero | any1 | [error] | [error] | minus | [error] | [error]
+ minus | zero | any1 | [error] | [error] | [error] | [error] | [error]
+ zero | done | done | exponent | done | done | decimal1 | done
+ any1 | any1 | any1 | exponent | done | done | decimal1 | done
+ decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error]
+ decimal2 | decimal2 | decimal2 | exponent | done | done | done | done
+ exponent | any2 | any2 | [error] | sign | sign | [error] | [error]
+ sign | any2 | any2 | [error] | [error] | [error] | [error] | [error]
+ any2 | any2 | any2 | done | done | done | done | done
+
+ The state machine is realized with one label per state (prefixed with
+ "scan_number_") and `goto` statements between them. The state machine
+ contains cycles, but any cycle can be left when EOF is read. Therefore,
+ the function is guaranteed to terminate.
+
+ During scanning, the read bytes are stored in token_buffer. This string is
+ then converted to a signed integer, an unsigned integer, or a
+ floating-point number.
+
+ @return token_type::value_unsigned, token_type::value_integer, or
+ token_type::value_float if number could be successfully scanned,
+ token_type::parse_error otherwise
+
+ @note The scanner is independent of the current locale. Internally, the
+ locale's decimal point is used instead of `.` to work with the
+ locale-dependent converters.
+ */
+ token_type scan_number() // lgtm [cpp/use-of-goto]
+ {
+ // reset token_buffer to store the number's bytes
+ reset();
+
+ // the type of the parsed number; initially set to unsigned; will be
+ // changed if minus sign, decimal point or exponent is read
+ token_type number_type = token_type::value_unsigned;
+
+ // state (init): we just found out we need to scan a number
+ switch (current)
+ {
+ case '-':
+ {
+ add(current);
+ goto scan_number_minus;
+ }
+
+ case '0':
+ {
+ add(current);
+ goto scan_number_zero;
+ }
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any1;
+ }
+
+ // all other characters are rejected outside scan_number()
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+
+scan_number_minus:
+ // state: we just parsed a leading minus sign
+ number_type = token_type::value_integer;
+ switch (get())
+ {
+ case '0':
+ {
+ add(current);
+ goto scan_number_zero;
+ }
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any1;
+ }
+
+ default:
+ {
+ error_message = "invalid number; expected digit after '-'";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_zero:
+ // state: we just parse a zero (maybe with a leading minus sign)
+ switch (get())
+ {
+ case '.':
+ {
+ add(decimal_point_char);
+ goto scan_number_decimal1;
+ }
+
+ case 'e':
+ case 'E':
+ {
+ add(current);
+ goto scan_number_exponent;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_any1:
+ // state: we just parsed a number 0-9 (maybe with a leading minus sign)
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any1;
+ }
+
+ case '.':
+ {
+ add(decimal_point_char);
+ goto scan_number_decimal1;
+ }
+
+ case 'e':
+ case 'E':
+ {
+ add(current);
+ goto scan_number_exponent;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_decimal1:
+ // state: we just parsed a decimal point
+ number_type = token_type::value_float;
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_decimal2;
+ }
+
+ default:
+ {
+ error_message = "invalid number; expected digit after '.'";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_decimal2:
+ // we just parsed at least one number after a decimal point
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_decimal2;
+ }
+
+ case 'e':
+ case 'E':
+ {
+ add(current);
+ goto scan_number_exponent;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_exponent:
+ // we just parsed an exponent
+ number_type = token_type::value_float;
+ switch (get())
+ {
+ case '+':
+ case '-':
+ {
+ add(current);
+ goto scan_number_sign;
+ }
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any2;
+ }
+
+ default:
+ {
+ error_message =
+ "invalid number; expected '+', '-', or digit after exponent";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_sign:
+ // we just parsed an exponent sign
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any2;
+ }
+
+ default:
+ {
+ error_message = "invalid number; expected digit after exponent sign";
+ return token_type::parse_error;
+ }
+ }
+
+scan_number_any2:
+ // we just parsed a number after the exponent or exponent sign
+ switch (get())
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ add(current);
+ goto scan_number_any2;
+ }
+
+ default:
+ goto scan_number_done;
+ }
+
+scan_number_done:
+ // unget the character after the number (we only read it to know that
+ // we are done scanning a number)
+ unget();
+
+ char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ errno = 0;
+
+ // try to parse integers first and fall back to floats
+ if (number_type == token_type::value_unsigned)
+ {
+ const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
+
+ // we checked the number format before
+ JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+ if (errno == 0)
+ {
+ value_unsigned = static_cast<number_unsigned_t>(x);
+ if (value_unsigned == x)
+ {
+ return token_type::value_unsigned;
+ }
+ }
+ }
+ else if (number_type == token_type::value_integer)
+ {
+ const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
+
+ // we checked the number format before
+ JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+ if (errno == 0)
+ {
+ value_integer = static_cast<number_integer_t>(x);
+ if (value_integer == x)
+ {
+ return token_type::value_integer;
+ }
+ }
+ }
+
+ // this code is reached if we parse a floating-point number or if an
+ // integer conversion above failed
+ strtof(value_float, token_buffer.data(), &endptr);
+
+ // we checked the number format before
+ JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
+
+ return token_type::value_float;
+ }
+
+ /*!
+ @param[in] literal_text the literal text to expect
+ @param[in] length the length of the passed literal text
+ @param[in] return_type the token type to return on success
+ */
+ JSON_HEDLEY_NON_NULL(2)
+ token_type scan_literal(const char_type* literal_text, const std::size_t length,
+ token_type return_type)
+ {
+ JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
+ for (std::size_t i = 1; i < length; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
+ {
+ error_message = "invalid literal";
+ return token_type::parse_error;
+ }
+ }
+ return return_type;
+ }
+
+ /////////////////////
+ // input management
+ /////////////////////
+
+ /// reset token_buffer; current character is beginning of token
+ void reset() noexcept
+ {
+ token_buffer.clear();
+ token_string.clear();
+ token_string.push_back(std::char_traits<char_type>::to_char_type(current));
+ }
+
+ /*
+ @brief get next character from the input
+
+ This function provides the interface to the used input adapter. It does
+ not throw in case the input reached EOF, but returns a
+ `std::char_traits<char>::eof()` in that case. Stores the scanned characters
+ for use in error messages.
+
+ @return character read from the input
+ */
+ char_int_type get()
+ {
+ ++position.chars_read_total;
+ ++position.chars_read_current_line;
+
+ if (next_unget)
+ {
+ // just reset the next_unget variable and work with current
+ next_unget = false;
+ }
+ else
+ {
+ current = ia.get_character();
+ }
+
+ if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
+ {
+ token_string.push_back(std::char_traits<char_type>::to_char_type(current));
+ }
+
+ if (current == '\n')
+ {
+ ++position.lines_read;
+ position.chars_read_current_line = 0;
+ }
+
+ return current;
+ }
+
+ /*!
+ @brief unget current character (read it again on next get)
+
+ We implement unget by setting variable next_unget to true. The input is not
+ changed - we just simulate ungetting by modifying chars_read_total,
+ chars_read_current_line, and token_string. The next call to get() will
+ behave as if the unget character is read again.
+ */
+ void unget()
+ {
+ next_unget = true;
+
+ --position.chars_read_total;
+
+ // in case we "unget" a newline, we have to also decrement the lines_read
+ if (position.chars_read_current_line == 0)
+ {
+ if (position.lines_read > 0)
+ {
+ --position.lines_read;
+ }
+ }
+ else
+ {
+ --position.chars_read_current_line;
+ }
+
+ if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
+ {
+ JSON_ASSERT(!token_string.empty());
+ token_string.pop_back();
+ }
+ }
+
+ /// add a character to token_buffer
+ void add(char_int_type c)
+ {
+ token_buffer.push_back(static_cast<typename string_t::value_type>(c));
+ }
+
+ public:
+ /////////////////////
+ // value getters
+ /////////////////////
+
+ /// return integer value
+ constexpr number_integer_t get_number_integer() const noexcept
+ {
+ return value_integer;
+ }
+
+ /// return unsigned integer value
+ constexpr number_unsigned_t get_number_unsigned() const noexcept
+ {
+ return value_unsigned;
+ }
+
+ /// return floating-point value
+ constexpr number_float_t get_number_float() const noexcept
+ {
+ return value_float;
+ }
+
+ /// return current string value (implicitly resets the token; useful only once)
+ string_t& get_string()
+ {
+ return token_buffer;
+ }
+
+ /////////////////////
+ // diagnostics
+ /////////////////////
+
+ /// return position of last read token
+ constexpr position_t get_position() const noexcept
+ {
+ return position;
+ }
+
+ /// return the last read token (for errors only). Will never contain EOF
+ /// (an arbitrary value that is not a valid char value, often -1), because
+ /// 255 may legitimately occur. May contain NUL, which should be escaped.
+ std::string get_token_string() const
+ {
+ // escape control characters
+ std::string result;
+ for (const auto c : token_string)
+ {
+ if (static_cast<unsigned char>(c) <= '\x1F')
+ {
+ // escape control characters
+ std::array<char, 9> cs{{}};
+ (std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ result += cs.data();
+ }
+ else
+ {
+ // add character as is
+ result.push_back(static_cast<std::string::value_type>(c));
+ }
+ }
+
+ return result;
+ }
+
+ /// return syntax error message
+ JSON_HEDLEY_RETURNS_NON_NULL
+ constexpr const char* get_error_message() const noexcept
+ {
+ return error_message;
+ }
+
+ /////////////////////
+ // actual scanner
+ /////////////////////
+
+ /*!
+ @brief skip the UTF-8 byte order mark
+ @return true iff there is no BOM or the correct BOM has been skipped
+ */
+ bool skip_bom()
+ {
+ if (get() == 0xEF)
+ {
+ // check if we completely parse the BOM
+ return get() == 0xBB && get() == 0xBF;
+ }
+
+ // the first character is not the beginning of the BOM; unget it to
+ // process is later
+ unget();
+ return true;
+ }
+
+ void skip_whitespace()
+ {
+ do
+ {
+ get();
+ }
+ while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
+ }
+
+ token_type scan()
+ {
+ // initially, skip the BOM
+ if (position.chars_read_total == 0 && !skip_bom())
+ {
+ error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
+ return token_type::parse_error;
+ }
+
+ // read next character and ignore whitespace
+ skip_whitespace();
+
+ // ignore comments
+ while (ignore_comments && current == '/')
+ {
+ if (!scan_comment())
+ {
+ return token_type::parse_error;
+ }
+
+ // skip following whitespace
+ skip_whitespace();
+ }
+
+ switch (current)
+ {
+ // structural characters
+ case '[':
+ return token_type::begin_array;
+ case ']':
+ return token_type::end_array;
+ case '{':
+ return token_type::begin_object;
+ case '}':
+ return token_type::end_object;
+ case ':':
+ return token_type::name_separator;
+ case ',':
+ return token_type::value_separator;
+
+ // literals
+ case 't':
+ {
+ std::array<char_type, 4> true_literal = {{char_type('t'), char_type('r'), char_type('u'), char_type('e')}};
+ return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
+ }
+ case 'f':
+ {
+ std::array<char_type, 5> false_literal = {{char_type('f'), char_type('a'), char_type('l'), char_type('s'), char_type('e')}};
+ return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
+ }
+ case 'n':
+ {
+ std::array<char_type, 4> null_literal = {{char_type('n'), char_type('u'), char_type('l'), char_type('l')}};
+ return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
+ }
+
+ // string
+ case '\"':
+ return scan_string();
+
+ // number
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return scan_number();
+
+ // end of input (the null byte is needed when parsing from
+ // string literals)
+ case '\0':
+ case std::char_traits<char_type>::eof():
+ return token_type::end_of_input;
+
+ // error
+ default:
+ error_message = "invalid literal";
+ return token_type::parse_error;
+ }
+ }
+
+ private:
+ /// input adapter
+ InputAdapterType ia;
+
+ /// whether comments should be ignored (true) or signaled as errors (false)
+ const bool ignore_comments = false;
+
+ /// the current character
+ char_int_type current = std::char_traits<char_type>::eof();
+
+ /// whether the next get() call should just return current
+ bool next_unget = false;
+
+ /// the start position of the current token
+ position_t position {};
+
+ /// raw input token string (for error messages)
+ std::vector<char_type> token_string {};
+
+ /// buffer for variable-length tokens (numbers, strings)
+ string_t token_buffer {};
+
+ /// a description of occurred lexer errors
+ const char* error_message = "";
+
+ // number values
+ number_integer_t value_integer = 0;
+ number_unsigned_t value_unsigned = 0;
+ number_float_t value_float = 0;
+
+ /// the decimal point
+ const char_int_type decimal_point_char = '.';
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+
+#include <cstdint> // size_t
+#include <utility> // declval
+#include <string> // string
+
+// #include <nlohmann/detail/meta/detected.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename T>
+using null_function_t = decltype(std::declval<T&>().null());
+
+template<typename T>
+using boolean_function_t =
+ decltype(std::declval<T&>().boolean(std::declval<bool>()));
+
+template<typename T, typename Integer>
+using number_integer_function_t =
+ decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
+
+template<typename T, typename Unsigned>
+using number_unsigned_function_t =
+ decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
+
+template<typename T, typename Float, typename String>
+using number_float_function_t = decltype(std::declval<T&>().number_float(
+ std::declval<Float>(), std::declval<const String&>()));
+
+template<typename T, typename String>
+using string_function_t =
+ decltype(std::declval<T&>().string(std::declval<String&>()));
+
+template<typename T, typename Binary>
+using binary_function_t =
+ decltype(std::declval<T&>().binary(std::declval<Binary&>()));
+
+template<typename T>
+using start_object_function_t =
+ decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
+
+template<typename T, typename String>
+using key_function_t =
+ decltype(std::declval<T&>().key(std::declval<String&>()));
+
+template<typename T>
+using end_object_function_t = decltype(std::declval<T&>().end_object());
+
+template<typename T>
+using start_array_function_t =
+ decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
+
+template<typename T>
+using end_array_function_t = decltype(std::declval<T&>().end_array());
+
+template<typename T, typename Exception>
+using parse_error_function_t = decltype(std::declval<T&>().parse_error(
+ std::declval<std::size_t>(), std::declval<const std::string&>(),
+ std::declval<const Exception&>()));
+
+template<typename SAX, typename BasicJsonType>
+struct is_sax
+{
+ private:
+ static_assert(is_basic_json<BasicJsonType>::value,
+ "BasicJsonType must be of type basic_json<...>");
+
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+ using exception_t = typename BasicJsonType::exception;
+
+ public:
+ static constexpr bool value =
+ is_detected_exact<bool, null_function_t, SAX>::value &&
+ is_detected_exact<bool, boolean_function_t, SAX>::value &&
+ is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
+ is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
+ is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
+ is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
+ is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
+ is_detected_exact<bool, start_object_function_t, SAX>::value &&
+ is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
+ is_detected_exact<bool, end_object_function_t, SAX>::value &&
+ is_detected_exact<bool, start_array_function_t, SAX>::value &&
+ is_detected_exact<bool, end_array_function_t, SAX>::value &&
+ is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
+};
+
+template<typename SAX, typename BasicJsonType>
+struct is_sax_static_asserts
+{
+ private:
+ static_assert(is_basic_json<BasicJsonType>::value,
+ "BasicJsonType must be of type basic_json<...>");
+
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+ using exception_t = typename BasicJsonType::exception;
+
+ public:
+ static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
+ "Missing/invalid function: bool null()");
+ static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+ "Missing/invalid function: bool boolean(bool)");
+ static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
+ "Missing/invalid function: bool boolean(bool)");
+ static_assert(
+ is_detected_exact<bool, number_integer_function_t, SAX,
+ number_integer_t>::value,
+ "Missing/invalid function: bool number_integer(number_integer_t)");
+ static_assert(
+ is_detected_exact<bool, number_unsigned_function_t, SAX,
+ number_unsigned_t>::value,
+ "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
+ static_assert(is_detected_exact<bool, number_float_function_t, SAX,
+ number_float_t, string_t>::value,
+ "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
+ static_assert(
+ is_detected_exact<bool, string_function_t, SAX, string_t>::value,
+ "Missing/invalid function: bool string(string_t&)");
+ static_assert(
+ is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
+ "Missing/invalid function: bool binary(binary_t&)");
+ static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
+ "Missing/invalid function: bool start_object(std::size_t)");
+ static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
+ "Missing/invalid function: bool key(string_t&)");
+ static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
+ "Missing/invalid function: bool end_object()");
+ static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
+ "Missing/invalid function: bool start_array(std::size_t)");
+ static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
+ "Missing/invalid function: bool end_array()");
+ static_assert(
+ is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
+ "Missing/invalid function: bool parse_error(std::size_t, const "
+ "std::string&, const exception&)");
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/// how to treat CBOR tags
+enum class cbor_tag_handler_t
+{
+ error, ///< throw a parse_error exception in case of a tag
+ ignore, ///< ignore tags
+ store ///< store tags as binary type
+};
+
+/*!
+@brief determine system byte order
+
+@return true if and only if system's byte order is little endian
+
+@note from https://stackoverflow.com/a/1001328/266378
+*/
+static inline bool little_endianness(int num = 1) noexcept
+{
+ return *reinterpret_cast<char*>(&num) == 1;
+}
+
+
+///////////////////
+// binary reader //
+///////////////////
+
+/*!
+@brief deserialization of CBOR, MessagePack, and UBJSON values
+*/
+template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
+class binary_reader
+{
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+ using json_sax_t = SAX;
+ using char_type = typename InputAdapterType::char_type;
+ using char_int_type = typename std::char_traits<char_type>::int_type;
+
+ public:
+ /*!
+ @brief create a binary reader
+
+ @param[in] adapter input adapter to read from
+ */
+ explicit binary_reader(InputAdapterType&& adapter) noexcept : ia(std::move(adapter))
+ {
+ (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+ }
+
+ // make class move-only
+ binary_reader(const binary_reader&) = delete;
+ binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ binary_reader& operator=(const binary_reader&) = delete;
+ binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
+ ~binary_reader() = default;
+
+ /*!
+ @param[in] format the binary format to parse
+ @param[in] sax_ a SAX event processor
+ @param[in] strict whether to expect the input to be consumed completed
+ @param[in] tag_handler how to treat CBOR tags
+
+ @return whether parsing was successful
+ */
+ JSON_HEDLEY_NON_NULL(3)
+ bool sax_parse(const input_format_t format,
+ json_sax_t* sax_,
+ const bool strict = true,
+ const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+ {
+ sax = sax_;
+ bool result = false;
+
+ switch (format)
+ {
+ case input_format_t::bson:
+ result = parse_bson_internal();
+ break;
+
+ case input_format_t::cbor:
+ result = parse_cbor_internal(true, tag_handler);
+ break;
+
+ case input_format_t::msgpack:
+ result = parse_msgpack_internal();
+ break;
+
+ case input_format_t::ubjson:
+ result = parse_ubjson_internal();
+ break;
+
+ case input_format_t::json: // LCOV_EXCL_LINE
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+
+ // strict mode: next byte must be EOF
+ if (result && strict)
+ {
+ if (format == input_format_t::ubjson)
+ {
+ get_ignore_noop();
+ }
+ else
+ {
+ get();
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
+ {
+ return sax->parse_error(chars_read, get_token_string(),
+ parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), BasicJsonType()));
+ }
+ }
+
+ return result;
+ }
+
+ private:
+ //////////
+ // BSON //
+ //////////
+
+ /*!
+ @brief Reads in a BSON-object and passes it to the SAX-parser.
+ @return whether a valid BSON-value was passed to the SAX parser
+ */
+ bool parse_bson_internal()
+ {
+ std::int32_t document_size{};
+ get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
+ {
+ return false;
+ }
+
+ return sax->end_object();
+ }
+
+ /*!
+ @brief Parses a C-style string from the BSON input.
+ @param[in,out] result A reference to the string variable where the read
+ string is to be stored.
+ @return `true` if the \x00-byte indicating the end of the string was
+ encountered before the EOF; false` indicates an unexpected EOF.
+ */
+ bool get_bson_cstr(string_t& result)
+ {
+ auto out = std::back_inserter(result);
+ while (true)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
+ {
+ return false;
+ }
+ if (current == 0x00)
+ {
+ return true;
+ }
+ *out++ = static_cast<typename string_t::value_type>(current);
+ }
+ }
+
+ /*!
+ @brief Parses a zero-terminated string of length @a len from the BSON
+ input.
+ @param[in] len The length (including the zero-byte at the end) of the
+ string to be read.
+ @param[in,out] result A reference to the string variable where the read
+ string is to be stored.
+ @tparam NumberType The type of the length @a len
+ @pre len >= 1
+ @return `true` if the string was successfully parsed
+ */
+ template<typename NumberType>
+ bool get_bson_string(const NumberType len, string_t& result)
+ {
+ if (JSON_HEDLEY_UNLIKELY(len < 1))
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), BasicJsonType()));
+ }
+
+ return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
+ }
+
+ /*!
+ @brief Parses a byte array input of length @a len from the BSON input.
+ @param[in] len The length of the byte array to be read.
+ @param[in,out] result A reference to the binary variable where the read
+ array is to be stored.
+ @tparam NumberType The type of the length @a len
+ @pre len >= 0
+ @return `true` if the byte array was successfully parsed
+ */
+ template<typename NumberType>
+ bool get_bson_binary(const NumberType len, binary_t& result)
+ {
+ if (JSON_HEDLEY_UNLIKELY(len < 0))
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), BasicJsonType()));
+ }
+
+ // All BSON binary values have a subtype
+ std::uint8_t subtype{};
+ get_number<std::uint8_t>(input_format_t::bson, subtype);
+ result.set_subtype(subtype);
+
+ return get_binary(input_format_t::bson, len, result);
+ }
+
+ /*!
+ @brief Read a BSON document element of the given @a element_type.
+ @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
+ @param[in] element_type_parse_position The position in the input stream,
+ where the `element_type` was read.
+ @warning Not all BSON element types are supported yet. An unsupported
+ @a element_type will give rise to a parse_error.114:
+ Unsupported BSON record type 0x...
+ @return whether a valid BSON-object/array was passed to the SAX parser
+ */
+ bool parse_bson_element_internal(const char_int_type element_type,
+ const std::size_t element_type_parse_position)
+ {
+ switch (element_type)
+ {
+ case 0x01: // double
+ {
+ double number{};
+ return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ case 0x02: // string
+ {
+ std::int32_t len{};
+ string_t value;
+ return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
+ }
+
+ case 0x03: // object
+ {
+ return parse_bson_internal();
+ }
+
+ case 0x04: // array
+ {
+ return parse_bson_array();
+ }
+
+ case 0x05: // binary
+ {
+ std::int32_t len{};
+ binary_t value;
+ return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
+ }
+
+ case 0x08: // boolean
+ {
+ return sax->boolean(get() != 0);
+ }
+
+ case 0x0A: // null
+ {
+ return sax->null();
+ }
+
+ case 0x10: // int32
+ {
+ std::int32_t value{};
+ return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
+ }
+
+ case 0x12: // int64
+ {
+ std::int64_t value{};
+ return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
+ }
+
+ default: // anything else not supported (yet)
+ {
+ std::array<char, 3> cr{{}};
+ (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @brief Read a BSON element list (as specified in the BSON-spec)
+
+ The same binary layout is used for objects and arrays, hence it must be
+ indicated with the argument @a is_array which one is expected
+ (true --> array, false --> object).
+
+ @param[in] is_array Determines if the element list being read is to be
+ treated as an object (@a is_array == false), or as an
+ array (@a is_array == true).
+ @return whether a valid BSON-object/array was passed to the SAX parser
+ */
+ bool parse_bson_element_list(const bool is_array)
+ {
+ string_t key;
+
+ while (auto element_type = get())
+ {
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
+ {
+ return false;
+ }
+
+ const std::size_t element_type_parse_position = chars_read;
+ if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
+ {
+ return false;
+ }
+
+ if (!is_array && !sax->key(key))
+ {
+ return false;
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
+ {
+ return false;
+ }
+
+ // get_bson_cstr only appends
+ key.clear();
+ }
+
+ return true;
+ }
+
+ /*!
+ @brief Reads an array from the BSON input and passes it to the SAX-parser.
+ @return whether a valid BSON-array was passed to the SAX parser
+ */
+ bool parse_bson_array()
+ {
+ std::int32_t document_size{};
+ get_number<std::int32_t, true>(input_format_t::bson, document_size);
+
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
+ {
+ return false;
+ }
+
+ return sax->end_array();
+ }
+
+ //////////
+ // CBOR //
+ //////////
+
+ /*!
+ @param[in] get_char whether a new character should be retrieved from the
+ input (true) or whether the last read character should
+ be considered instead (false)
+ @param[in] tag_handler how CBOR tags should be treated
+
+ @return whether a valid CBOR value was passed to the SAX parser
+ */
+ bool parse_cbor_internal(const bool get_char,
+ const cbor_tag_handler_t tag_handler)
+ {
+ switch (get_char ? get() : current)
+ {
+ // EOF
+ case std::char_traits<char_type>::eof():
+ return unexpect_eof(input_format_t::cbor, "value");
+
+ // Integer 0x00..0x17 (0..23)
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+ case 0x18: // Unsigned integer (one-byte uint8_t follows)
+ {
+ std::uint8_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+ }
+
+ case 0x19: // Unsigned integer (two-byte uint16_t follows)
+ {
+ std::uint16_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+ }
+
+ case 0x1A: // Unsigned integer (four-byte uint32_t follows)
+ {
+ std::uint32_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+ }
+
+ case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
+ {
+ std::uint64_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
+ }
+
+ // Negative integer -1-0x00..-1-0x17 (-1..-24)
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
+
+ case 0x38: // Negative integer (one-byte uint8_t follows)
+ {
+ std::uint8_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+ }
+
+ case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
+ {
+ std::uint16_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+ }
+
+ case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
+ {
+ std::uint32_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
+ }
+
+ case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
+ {
+ std::uint64_t number{};
+ return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
+ - static_cast<number_integer_t>(number));
+ }
+
+ // Binary data (0x00..0x17 bytes follow)
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B:
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58: // Binary data (one-byte uint8_t for n follows)
+ case 0x59: // Binary data (two-byte uint16_t for n follow)
+ case 0x5A: // Binary data (four-byte uint32_t for n follow)
+ case 0x5B: // Binary data (eight-byte uint64_t for n follow)
+ case 0x5F: // Binary data (indefinite length)
+ {
+ binary_t b;
+ return get_cbor_binary(b) && sax->binary(b);
+ }
+
+ // UTF-8 string (0x00..0x17 bytes follow)
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+ case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+ case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+ case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+ case 0x7F: // UTF-8 string (indefinite length)
+ {
+ string_t s;
+ return get_cbor_string(s) && sax->string(s);
+ }
+
+ // array (0x00..0x17 data items follow)
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ case 0x8D:
+ case 0x8E:
+ case 0x8F:
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+
+ case 0x98: // array (one-byte uint8_t for n follows)
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0x99: // array (two-byte uint16_t for n follow)
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0x9A: // array (four-byte uint32_t for n follow)
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0x9B: // array (eight-byte uint64_t for n follow)
+ {
+ std::uint64_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_array(detail::conditional_static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0x9F: // array (indefinite length)
+ return get_cbor_array(std::size_t(-1), tag_handler);
+
+ // map (0x00..0x17 pairs of data items follow)
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF:
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
+
+ case 0xB8: // map (one-byte uint8_t for n follows)
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0xB9: // map (two-byte uint16_t for n follow)
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0xBA: // map (four-byte uint32_t for n follow)
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0xBB: // map (eight-byte uint64_t for n follow)
+ {
+ std::uint64_t len{};
+ return get_number(input_format_t::cbor, len) && get_cbor_object(detail::conditional_static_cast<std::size_t>(len), tag_handler);
+ }
+
+ case 0xBF: // map (indefinite length)
+ return get_cbor_object(std::size_t(-1), tag_handler);
+
+ case 0xC6: // tagged item
+ case 0xC7:
+ case 0xC8:
+ case 0xC9:
+ case 0xCA:
+ case 0xCB:
+ case 0xCC:
+ case 0xCD:
+ case 0xCE:
+ case 0xCF:
+ case 0xD0:
+ case 0xD1:
+ case 0xD2:
+ case 0xD3:
+ case 0xD4:
+ case 0xD8: // tagged item (1 bytes follow)
+ case 0xD9: // tagged item (2 bytes follow)
+ case 0xDA: // tagged item (4 bytes follow)
+ case 0xDB: // tagged item (8 bytes follow)
+ {
+ switch (tag_handler)
+ {
+ case cbor_tag_handler_t::error:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ }
+
+ case cbor_tag_handler_t::ignore:
+ {
+ // ignore binary subtype
+ switch (current)
+ {
+ case 0xD8:
+ {
+ std::uint8_t subtype_to_ignore{};
+ get_number(input_format_t::cbor, subtype_to_ignore);
+ break;
+ }
+ case 0xD9:
+ {
+ std::uint16_t subtype_to_ignore{};
+ get_number(input_format_t::cbor, subtype_to_ignore);
+ break;
+ }
+ case 0xDA:
+ {
+ std::uint32_t subtype_to_ignore{};
+ get_number(input_format_t::cbor, subtype_to_ignore);
+ break;
+ }
+ case 0xDB:
+ {
+ std::uint64_t subtype_to_ignore{};
+ get_number(input_format_t::cbor, subtype_to_ignore);
+ break;
+ }
+ default:
+ break;
+ }
+ return parse_cbor_internal(true, tag_handler);
+ }
+
+ case cbor_tag_handler_t::store:
+ {
+ binary_t b;
+ // use binary subtype and store in binary container
+ switch (current)
+ {
+ case 0xD8:
+ {
+ std::uint8_t subtype{};
+ get_number(input_format_t::cbor, subtype);
+ b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+ break;
+ }
+ case 0xD9:
+ {
+ std::uint16_t subtype{};
+ get_number(input_format_t::cbor, subtype);
+ b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+ break;
+ }
+ case 0xDA:
+ {
+ std::uint32_t subtype{};
+ get_number(input_format_t::cbor, subtype);
+ b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+ break;
+ }
+ case 0xDB:
+ {
+ std::uint64_t subtype{};
+ get_number(input_format_t::cbor, subtype);
+ b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
+ break;
+ }
+ default:
+ return parse_cbor_internal(true, tag_handler);
+ }
+ get();
+ return get_cbor_binary(b) && sax->binary(b);
+ }
+
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ return false; // LCOV_EXCL_LINE
+ }
+ }
+
+ case 0xF4: // false
+ return sax->boolean(false);
+
+ case 0xF5: // true
+ return sax->boolean(true);
+
+ case 0xF6: // null
+ return sax->null();
+
+ case 0xF9: // Half-Precision Float (two-byte IEEE 754)
+ {
+ const auto byte1_raw = get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
+ {
+ return false;
+ }
+ const auto byte2_raw = get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
+ {
+ return false;
+ }
+
+ const auto byte1 = static_cast<unsigned char>(byte1_raw);
+ const auto byte2 = static_cast<unsigned char>(byte2_raw);
+
+ // code from RFC 7049, Appendix D, Figure 3:
+ // As half-precision floating-point numbers were only added
+ // to IEEE 754 in 2008, today's programming platforms often
+ // still only have limited support for them. It is very
+ // easy to include at least decoding support for them even
+ // without such support. An example of a small decoder for
+ // half-precision floating-point numbers in the C language
+ // is shown in Fig. 3.
+ const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
+ const double val = [&half]
+ {
+ const int exp = (half >> 10u) & 0x1Fu;
+ const unsigned int mant = half & 0x3FFu;
+ JSON_ASSERT(0 <= exp&& exp <= 32);
+ JSON_ASSERT(mant <= 1024);
+ switch (exp)
+ {
+ case 0:
+ return std::ldexp(mant, -24);
+ case 31:
+ return (mant == 0)
+ ? std::numeric_limits<double>::infinity()
+ : std::numeric_limits<double>::quiet_NaN();
+ default:
+ return std::ldexp(mant + 1024, exp - 25);
+ }
+ }();
+ return sax->number_float((half & 0x8000u) != 0
+ ? static_cast<number_float_t>(-val)
+ : static_cast<number_float_t>(val), "");
+ }
+
+ case 0xFA: // Single-Precision Float (four-byte IEEE 754)
+ {
+ float number{};
+ return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
+ {
+ double number{};
+ return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ default: // anything else (0xFF is handled inside the other types)
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @brief reads a CBOR string
+
+ This function first reads starting bytes to determine the expected
+ string length and then copies this number of bytes into a string.
+ Additionally, CBOR's strings with indefinite lengths are supported.
+
+ @param[out] result created string
+
+ @return whether string creation completed
+ */
+ bool get_cbor_string(string_t& result)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
+ {
+ return false;
+ }
+
+ switch (current)
+ {
+ // UTF-8 string (0x00..0x17 bytes follow)
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ {
+ return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+ }
+
+ case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+ }
+
+ case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+ }
+
+ case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+ }
+
+ case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
+ {
+ std::uint64_t len{};
+ return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
+ }
+
+ case 0x7F: // UTF-8 string (indefinite length)
+ {
+ while (get() != 0xFF)
+ {
+ string_t chunk;
+ if (!get_cbor_string(chunk))
+ {
+ return false;
+ }
+ result.append(chunk);
+ }
+ return true;
+ }
+
+ default:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @brief reads a CBOR byte array
+
+ This function first reads starting bytes to determine the expected
+ byte array length and then copies this number of bytes into the byte array.
+ Additionally, CBOR's byte arrays with indefinite lengths are supported.
+
+ @param[out] result created byte array
+
+ @return whether byte array creation completed
+ */
+ bool get_cbor_binary(binary_t& result)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
+ {
+ return false;
+ }
+
+ switch (current)
+ {
+ // Binary data (0x00..0x17 bytes follow)
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B:
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ {
+ return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
+ }
+
+ case 0x58: // Binary data (one-byte uint8_t for n follows)
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::cbor, len) &&
+ get_binary(input_format_t::cbor, len, result);
+ }
+
+ case 0x59: // Binary data (two-byte uint16_t for n follow)
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::cbor, len) &&
+ get_binary(input_format_t::cbor, len, result);
+ }
+
+ case 0x5A: // Binary data (four-byte uint32_t for n follow)
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::cbor, len) &&
+ get_binary(input_format_t::cbor, len, result);
+ }
+
+ case 0x5B: // Binary data (eight-byte uint64_t for n follow)
+ {
+ std::uint64_t len{};
+ return get_number(input_format_t::cbor, len) &&
+ get_binary(input_format_t::cbor, len, result);
+ }
+
+ case 0x5F: // Binary data (indefinite length)
+ {
+ while (get() != 0xFF)
+ {
+ binary_t chunk;
+ if (!get_cbor_binary(chunk))
+ {
+ return false;
+ }
+ result.insert(result.end(), chunk.begin(), chunk.end());
+ }
+ return true;
+ }
+
+ default:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @param[in] len the length of the array or std::size_t(-1) for an
+ array of indefinite size
+ @param[in] tag_handler how CBOR tags should be treated
+ @return whether array creation completed
+ */
+ bool get_cbor_array(const std::size_t len,
+ const cbor_tag_handler_t tag_handler)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
+ {
+ return false;
+ }
+
+ if (len != std::size_t(-1))
+ {
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ while (get() != 0xFF)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
+ {
+ return false;
+ }
+ }
+ }
+
+ return sax->end_array();
+ }
+
+ /*!
+ @param[in] len the length of the object or std::size_t(-1) for an
+ object of indefinite size
+ @param[in] tag_handler how CBOR tags should be treated
+ @return whether object creation completed
+ */
+ bool get_cbor_object(const std::size_t len,
+ const cbor_tag_handler_t tag_handler)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
+ {
+ return false;
+ }
+
+ if (len != 0)
+ {
+ string_t key;
+ if (len != std::size_t(-1))
+ {
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+ else
+ {
+ while (get() != 0xFF)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+ }
+
+ return sax->end_object();
+ }
+
+ /////////////
+ // MsgPack //
+ /////////////
+
+ /*!
+ @return whether a valid MessagePack value was passed to the SAX parser
+ */
+ bool parse_msgpack_internal()
+ {
+ switch (get())
+ {
+ // EOF
+ case std::char_traits<char_type>::eof():
+ return unexpect_eof(input_format_t::msgpack, "value");
+
+ // positive fixint
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0A:
+ case 0x0B:
+ case 0x0C:
+ case 0x0D:
+ case 0x0E:
+ case 0x0F:
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1A:
+ case 0x1B:
+ case 0x1C:
+ case 0x1D:
+ case 0x1E:
+ case 0x1F:
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ case 0x28:
+ case 0x29:
+ case 0x2A:
+ case 0x2B:
+ case 0x2C:
+ case 0x2D:
+ case 0x2E:
+ case 0x2F:
+ case 0x30:
+ case 0x31:
+ case 0x32:
+ case 0x33:
+ case 0x34:
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ case 0x38:
+ case 0x39:
+ case 0x3A:
+ case 0x3B:
+ case 0x3C:
+ case 0x3D:
+ case 0x3E:
+ case 0x3F:
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4A:
+ case 0x4B:
+ case 0x4C:
+ case 0x4D:
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ case 0x78:
+ case 0x79:
+ case 0x7A:
+ case 0x7B:
+ case 0x7C:
+ case 0x7D:
+ case 0x7E:
+ case 0x7F:
+ return sax->number_unsigned(static_cast<number_unsigned_t>(current));
+
+ // fixmap
+ case 0x80:
+ case 0x81:
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ case 0x8D:
+ case 0x8E:
+ case 0x8F:
+ return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+ // fixarray
+ case 0x90:
+ case 0x91:
+ case 0x92:
+ case 0x93:
+ case 0x94:
+ case 0x95:
+ case 0x96:
+ case 0x97:
+ case 0x98:
+ case 0x99:
+ case 0x9A:
+ case 0x9B:
+ case 0x9C:
+ case 0x9D:
+ case 0x9E:
+ case 0x9F:
+ return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
+
+ // fixstr
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF:
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF:
+ case 0xD9: // str 8
+ case 0xDA: // str 16
+ case 0xDB: // str 32
+ {
+ string_t s;
+ return get_msgpack_string(s) && sax->string(s);
+ }
+
+ case 0xC0: // nil
+ return sax->null();
+
+ case 0xC2: // false
+ return sax->boolean(false);
+
+ case 0xC3: // true
+ return sax->boolean(true);
+
+ case 0xC4: // bin 8
+ case 0xC5: // bin 16
+ case 0xC6: // bin 32
+ case 0xC7: // ext 8
+ case 0xC8: // ext 16
+ case 0xC9: // ext 32
+ case 0xD4: // fixext 1
+ case 0xD5: // fixext 2
+ case 0xD6: // fixext 4
+ case 0xD7: // fixext 8
+ case 0xD8: // fixext 16
+ {
+ binary_t b;
+ return get_msgpack_binary(b) && sax->binary(b);
+ }
+
+ case 0xCA: // float 32
+ {
+ float number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ case 0xCB: // float 64
+ {
+ double number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ case 0xCC: // uint 8
+ {
+ std::uint8_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+ }
+
+ case 0xCD: // uint 16
+ {
+ std::uint16_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+ }
+
+ case 0xCE: // uint 32
+ {
+ std::uint32_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+ }
+
+ case 0xCF: // uint 64
+ {
+ std::uint64_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
+ }
+
+ case 0xD0: // int 8
+ {
+ std::int8_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+ }
+
+ case 0xD1: // int 16
+ {
+ std::int16_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+ }
+
+ case 0xD2: // int 32
+ {
+ std::int32_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+ }
+
+ case 0xD3: // int 64
+ {
+ std::int64_t number{};
+ return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
+ }
+
+ case 0xDC: // array 16
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
+ }
+
+ case 0xDD: // array 32
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
+ }
+
+ case 0xDE: // map 16
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
+ }
+
+ case 0xDF: // map 32
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
+ }
+
+ // negative fixint
+ case 0xE0:
+ case 0xE1:
+ case 0xE2:
+ case 0xE3:
+ case 0xE4:
+ case 0xE5:
+ case 0xE6:
+ case 0xE7:
+ case 0xE8:
+ case 0xE9:
+ case 0xEA:
+ case 0xEB:
+ case 0xEC:
+ case 0xED:
+ case 0xEE:
+ case 0xEF:
+ case 0xF0:
+ case 0xF1:
+ case 0xF2:
+ case 0xF3:
+ case 0xF4:
+ case 0xF5:
+ case 0xF6:
+ case 0xF7:
+ case 0xF8:
+ case 0xF9:
+ case 0xFA:
+ case 0xFB:
+ case 0xFC:
+ case 0xFD:
+ case 0xFE:
+ case 0xFF:
+ return sax->number_integer(static_cast<std::int8_t>(current));
+
+ default: // anything else
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @brief reads a MessagePack string
+
+ This function first reads starting bytes to determine the expected
+ string length and then copies this number of bytes into a string.
+
+ @param[out] result created string
+
+ @return whether string creation completed
+ */
+ bool get_msgpack_string(string_t& result)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
+ {
+ return false;
+ }
+
+ switch (current)
+ {
+ // fixstr
+ case 0xA0:
+ case 0xA1:
+ case 0xA2:
+ case 0xA3:
+ case 0xA4:
+ case 0xA5:
+ case 0xA6:
+ case 0xA7:
+ case 0xA8:
+ case 0xA9:
+ case 0xAA:
+ case 0xAB:
+ case 0xAC:
+ case 0xAD:
+ case 0xAE:
+ case 0xAF:
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF:
+ {
+ return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
+ }
+
+ case 0xD9: // str 8
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+ }
+
+ case 0xDA: // str 16
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+ }
+
+ case 0xDB: // str 32
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
+ }
+
+ default:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @brief reads a MessagePack byte array
+
+ This function first reads starting bytes to determine the expected
+ byte array length and then copies this number of bytes into a byte array.
+
+ @param[out] result created byte array
+
+ @return whether byte array creation completed
+ */
+ bool get_msgpack_binary(binary_t& result)
+ {
+ // helper function to set the subtype
+ auto assign_and_return_true = [&result](std::int8_t subtype)
+ {
+ result.set_subtype(static_cast<std::uint8_t>(subtype));
+ return true;
+ };
+
+ switch (current)
+ {
+ case 0xC4: // bin 8
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::msgpack, len) &&
+ get_binary(input_format_t::msgpack, len, result);
+ }
+
+ case 0xC5: // bin 16
+ {
+ std::uint16_t len{};
+ return get_number(input_format_t::msgpack, len) &&
+ get_binary(input_format_t::msgpack, len, result);
+ }
+
+ case 0xC6: // bin 32
+ {
+ std::uint32_t len{};
+ return get_number(input_format_t::msgpack, len) &&
+ get_binary(input_format_t::msgpack, len, result);
+ }
+
+ case 0xC7: // ext 8
+ {
+ std::uint8_t len{};
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, len) &&
+ get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, len, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xC8: // ext 16
+ {
+ std::uint16_t len{};
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, len) &&
+ get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, len, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xC9: // ext 32
+ {
+ std::uint32_t len{};
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, len) &&
+ get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, len, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xD4: // fixext 1
+ {
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, 1, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xD5: // fixext 2
+ {
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, 2, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xD6: // fixext 4
+ {
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, 4, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xD7: // fixext 8
+ {
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, 8, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ case 0xD8: // fixext 16
+ {
+ std::int8_t subtype{};
+ return get_number(input_format_t::msgpack, subtype) &&
+ get_binary(input_format_t::msgpack, 16, result) &&
+ assign_and_return_true(subtype);
+ }
+
+ default: // LCOV_EXCL_LINE
+ return false; // LCOV_EXCL_LINE
+ }
+ }
+
+ /*!
+ @param[in] len the length of the array
+ @return whether array creation completed
+ */
+ bool get_msgpack_array(const std::size_t len)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
+ {
+ return false;
+ }
+
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
+ {
+ return false;
+ }
+ }
+
+ return sax->end_array();
+ }
+
+ /*!
+ @param[in] len the length of the object
+ @return whether object creation completed
+ */
+ bool get_msgpack_object(const std::size_t len)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
+ {
+ return false;
+ }
+
+ string_t key;
+ for (std::size_t i = 0; i < len; ++i)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
+ {
+ return false;
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+
+ return sax->end_object();
+ }
+
+ ////////////
+ // UBJSON //
+ ////////////
+
+ /*!
+ @param[in] get_char whether a new character should be retrieved from the
+ input (true, default) or whether the last read
+ character should be considered instead
+
+ @return whether a valid UBJSON value was passed to the SAX parser
+ */
+ bool parse_ubjson_internal(const bool get_char = true)
+ {
+ return get_ubjson_value(get_char ? get_ignore_noop() : current);
+ }
+
+ /*!
+ @brief reads a UBJSON string
+
+ This function is either called after reading the 'S' byte explicitly
+ indicating a string, or in case of an object key where the 'S' byte can be
+ left out.
+
+ @param[out] result created string
+ @param[in] get_char whether a new character should be retrieved from the
+ input (true, default) or whether the last read
+ character should be considered instead
+
+ @return whether string creation completed
+ */
+ bool get_ubjson_string(string_t& result, const bool get_char = true)
+ {
+ if (get_char)
+ {
+ get(); // TODO(niels): may we ignore N here?
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
+ {
+ return false;
+ }
+
+ switch (current)
+ {
+ case 'U':
+ {
+ std::uint8_t len{};
+ return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ }
+
+ case 'i':
+ {
+ std::int8_t len{};
+ return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ }
+
+ case 'I':
+ {
+ std::int16_t len{};
+ return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ }
+
+ case 'l':
+ {
+ std::int32_t len{};
+ return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ }
+
+ case 'L':
+ {
+ std::int64_t len{};
+ return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result);
+ }
+
+ default:
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), BasicJsonType()));
+ }
+ }
+
+ /*!
+ @param[out] result determined size
+ @return whether size determination completed
+ */
+ bool get_ubjson_size_value(std::size_t& result)
+ {
+ switch (get_ignore_noop())
+ {
+ case 'U':
+ {
+ std::uint8_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'i':
+ {
+ std::int8_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
+ return true;
+ }
+
+ case 'I':
+ {
+ std::int16_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'l':
+ {
+ std::int32_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ case 'L':
+ {
+ std::int64_t number{};
+ if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number)))
+ {
+ return false;
+ }
+ result = static_cast<std::size_t>(number);
+ return true;
+ }
+
+ default:
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @brief determine the type and size for a container
+
+ In the optimized UBJSON format, a type and a size can be provided to allow
+ for a more compact representation.
+
+ @param[out] result pair of the size and the type
+
+ @return whether pair creation completed
+ */
+ bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result)
+ {
+ result.first = string_t::npos; // size
+ result.second = 0; // type
+
+ get_ignore_noop();
+
+ if (current == '$')
+ {
+ result.second = get(); // must not ignore 'N', because 'N' maybe the type
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type")))
+ {
+ return false;
+ }
+
+ get_ignore_noop();
+ if (JSON_HEDLEY_UNLIKELY(current != '#'))
+ {
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value")))
+ {
+ return false;
+ }
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), BasicJsonType()));
+ }
+
+ return get_ubjson_size_value(result.first);
+ }
+
+ if (current == '#')
+ {
+ return get_ubjson_size_value(result.first);
+ }
+
+ return true;
+ }
+
+ /*!
+ @param prefix the previously read or set type prefix
+ @return whether value creation completed
+ */
+ bool get_ubjson_value(const char_int_type prefix)
+ {
+ switch (prefix)
+ {
+ case std::char_traits<char_type>::eof(): // EOF
+ return unexpect_eof(input_format_t::ubjson, "value");
+
+ case 'T': // true
+ return sax->boolean(true);
+ case 'F': // false
+ return sax->boolean(false);
+
+ case 'Z': // null
+ return sax->null();
+
+ case 'U':
+ {
+ std::uint8_t number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number);
+ }
+
+ case 'i':
+ {
+ std::int8_t number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ }
+
+ case 'I':
+ {
+ std::int16_t number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ }
+
+ case 'l':
+ {
+ std::int32_t number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ }
+
+ case 'L':
+ {
+ std::int64_t number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_integer(number);
+ }
+
+ case 'd':
+ {
+ float number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ case 'D':
+ {
+ double number{};
+ return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast<number_float_t>(number), "");
+ }
+
+ case 'H':
+ {
+ return get_ubjson_high_precision_number();
+ }
+
+ case 'C': // char
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char")))
+ {
+ return false;
+ }
+ if (JSON_HEDLEY_UNLIKELY(current > 127))
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), BasicJsonType()));
+ }
+ string_t s(1, static_cast<typename string_t::value_type>(current));
+ return sax->string(s);
+ }
+
+ case 'S': // string
+ {
+ string_t s;
+ return get_ubjson_string(s) && sax->string(s);
+ }
+
+ case '[': // array
+ return get_ubjson_array();
+
+ case '{': // object
+ return get_ubjson_object();
+
+ default: // anything else
+ {
+ auto last_token = get_token_string();
+ return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), BasicJsonType()));
+ }
+ }
+ }
+
+ /*!
+ @return whether array creation completed
+ */
+ bool get_ubjson_array()
+ {
+ std::pair<std::size_t, char_int_type> size_and_type;
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
+ {
+ return false;
+ }
+
+ if (size_and_type.first != string_t::npos)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
+ {
+ return false;
+ }
+
+ if (size_and_type.second != 0)
+ {
+ if (size_and_type.second != 'N')
+ {
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ while (current != ']')
+ {
+ if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
+ {
+ return false;
+ }
+ get_ignore_noop();
+ }
+ }
+
+ return sax->end_array();
+ }
+
+ /*!
+ @return whether object creation completed
+ */
+ bool get_ubjson_object()
+ {
+ std::pair<std::size_t, char_int_type> size_and_type;
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
+ {
+ return false;
+ }
+
+ string_t key;
+ if (size_and_type.first != string_t::npos)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
+ {
+ return false;
+ }
+
+ if (size_and_type.second != 0)
+ {
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < size_and_type.first; ++i)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+ {
+ return false;
+ }
+ key.clear();
+ }
+ }
+ }
+ else
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ while (current != '}')
+ {
+ if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
+ {
+ return false;
+ }
+ if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
+ {
+ return false;
+ }
+ get_ignore_noop();
+ key.clear();
+ }
+ }
+
+ return sax->end_object();
+ }
+
+ // Note, no reader for UBJSON binary types is implemented because they do
+ // not exist
+
+ bool get_ubjson_high_precision_number()
+ {
+ // get size of following number string
+ std::size_t size{};
+ auto res = get_ubjson_size_value(size);
+ if (JSON_HEDLEY_UNLIKELY(!res))
+ {
+ return res;
+ }
+
+ // get number string
+ std::vector<char> number_vector;
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number")))
+ {
+ return false;
+ }
+ number_vector.push_back(static_cast<char>(current));
+ }
+
+ // parse number string
+ using ia_type = decltype(detail::input_adapter(number_vector));
+ auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
+ const auto result_number = number_lexer.scan();
+ const auto number_string = number_lexer.get_token_string();
+ const auto result_remainder = number_lexer.scan();
+
+ using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
+
+ if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
+ {
+ return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
+ }
+
+ switch (result_number)
+ {
+ case token_type::value_integer:
+ return sax->number_integer(number_lexer.get_number_integer());
+ case token_type::value_unsigned:
+ return sax->number_unsigned(number_lexer.get_number_unsigned());
+ case token_type::value_float:
+ return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
+ case token_type::uninitialized:
+ case token_type::literal_true:
+ case token_type::literal_false:
+ case token_type::literal_null:
+ case token_type::value_string:
+ case token_type::begin_array:
+ case token_type::begin_object:
+ case token_type::end_array:
+ case token_type::end_object:
+ case token_type::name_separator:
+ case token_type::value_separator:
+ case token_type::parse_error:
+ case token_type::end_of_input:
+ case token_type::literal_or_value:
+ default:
+ return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), BasicJsonType()));
+ }
+ }
+
+ ///////////////////////
+ // Utility functions //
+ ///////////////////////
+
+ /*!
+ @brief get next character from the input
+
+ This function provides the interface to the used input adapter. It does
+ not throw in case the input reached EOF, but returns a -'ve valued
+ `std::char_traits<char_type>::eof()` in that case.
+
+ @return character read from the input
+ */
+ char_int_type get()
+ {
+ ++chars_read;
+ return current = ia.get_character();
+ }
+
+ /*!
+ @return character read from the input after ignoring all 'N' entries
+ */
+ char_int_type get_ignore_noop()
+ {
+ do
+ {
+ get();
+ }
+ while (current == 'N');
+
+ return current;
+ }
+
+ /*
+ @brief read a number from the input
+
+ @tparam NumberType the type of the number
+ @param[in] format the current format (for diagnostics)
+ @param[out] result number of type @a NumberType
+
+ @return whether conversion completed
+
+ @note This function needs to respect the system's endianness, because
+ bytes in CBOR, MessagePack, and UBJSON are stored in network order
+ (big endian) and therefore need reordering on little endian systems.
+ */
+ template<typename NumberType, bool InputIsLittleEndian = false>
+ bool get_number(const input_format_t format, NumberType& result)
+ {
+ // step 1: read input into array with system's byte order
+ std::array<std::uint8_t, sizeof(NumberType)> vec{};
+ for (std::size_t i = 0; i < sizeof(NumberType); ++i)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
+ {
+ return false;
+ }
+
+ // reverse byte order prior to conversion if necessary
+ if (is_little_endian != InputIsLittleEndian)
+ {
+ vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
+ }
+ else
+ {
+ vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
+ }
+ }
+
+ // step 2: convert array into number of type T and return
+ std::memcpy(&result, vec.data(), sizeof(NumberType));
+ return true;
+ }
+
+ /*!
+ @brief create a string by reading characters from the input
+
+ @tparam NumberType the type of the number
+ @param[in] format the current format (for diagnostics)
+ @param[in] len number of characters to read
+ @param[out] result string created by reading @a len bytes
+
+ @return whether string creation completed
+
+ @note We can not reserve @a len bytes for the result, because @a len
+ may be too large. Usually, @ref unexpect_eof() detects the end of
+ the input before we run out of string memory.
+ */
+ template<typename NumberType>
+ bool get_string(const input_format_t format,
+ const NumberType len,
+ string_t& result)
+ {
+ bool success = true;
+ for (NumberType i = 0; i < len; i++)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
+ {
+ success = false;
+ break;
+ }
+ result.push_back(static_cast<typename string_t::value_type>(current));
+ }
+ return success;
+ }
+
+ /*!
+ @brief create a byte array by reading bytes from the input
+
+ @tparam NumberType the type of the number
+ @param[in] format the current format (for diagnostics)
+ @param[in] len number of bytes to read
+ @param[out] result byte array created by reading @a len bytes
+
+ @return whether byte array creation completed
+
+ @note We can not reserve @a len bytes for the result, because @a len
+ may be too large. Usually, @ref unexpect_eof() detects the end of
+ the input before we run out of memory.
+ */
+ template<typename NumberType>
+ bool get_binary(const input_format_t format,
+ const NumberType len,
+ binary_t& result)
+ {
+ bool success = true;
+ for (NumberType i = 0; i < len; i++)
+ {
+ get();
+ if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
+ {
+ success = false;
+ break;
+ }
+ result.push_back(static_cast<std::uint8_t>(current));
+ }
+ return success;
+ }
+
+ /*!
+ @param[in] format the current format (for diagnostics)
+ @param[in] context further context information (for diagnostics)
+ @return whether the last read character is not EOF
+ */
+ JSON_HEDLEY_NON_NULL(3)
+ bool unexpect_eof(const input_format_t format, const char* context) const
+ {
+ if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
+ {
+ return sax->parse_error(chars_read, "<end of file>",
+ parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), BasicJsonType()));
+ }
+ return true;
+ }
+
+ /*!
+ @return a string representation of the last read byte
+ */
+ std::string get_token_string() const
+ {
+ std::array<char, 3> cr{{}};
+ (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ return std::string{cr.data()};
+ }
+
+ /*!
+ @param[in] format the current format
+ @param[in] detail a detailed error message
+ @param[in] context further context information
+ @return a message string to use in the parse_error exceptions
+ */
+ std::string exception_message(const input_format_t format,
+ const std::string& detail,
+ const std::string& context) const
+ {
+ std::string error_msg = "syntax error while parsing ";
+
+ switch (format)
+ {
+ case input_format_t::cbor:
+ error_msg += "CBOR";
+ break;
+
+ case input_format_t::msgpack:
+ error_msg += "MessagePack";
+ break;
+
+ case input_format_t::ubjson:
+ error_msg += "UBJSON";
+ break;
+
+ case input_format_t::bson:
+ error_msg += "BSON";
+ break;
+
+ case input_format_t::json: // LCOV_EXCL_LINE
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+
+ return error_msg + " " + context + ": " + detail;
+ }
+
+ private:
+ /// input adapter
+ InputAdapterType ia;
+
+ /// the current character
+ char_int_type current = std::char_traits<char_type>::eof();
+
+ /// the number of characters read
+ std::size_t chars_read = 0;
+
+ /// whether we can assume little endianness
+ const bool is_little_endian = little_endianness();
+
+ /// the SAX parser
+ json_sax_t* sax = nullptr;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/input/parser.hpp>
+
+
+#include <cmath> // isfinite
+#include <cstdint> // uint8_t
+#include <functional> // function
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/input/input_adapters.hpp>
+
+// #include <nlohmann/detail/input/json_sax.hpp>
+
+// #include <nlohmann/detail/input/lexer.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/is_sax.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+////////////
+// parser //
+////////////
+
+enum class parse_event_t : std::uint8_t
+{
+ /// the parser read `{` and started to process a JSON object
+ object_start,
+ /// the parser read `}` and finished processing a JSON object
+ object_end,
+ /// the parser read `[` and started to process a JSON array
+ array_start,
+ /// the parser read `]` and finished processing a JSON array
+ array_end,
+ /// the parser read a key of a value in an object
+ key,
+ /// the parser finished reading a JSON value
+ value
+};
+
+template<typename BasicJsonType>
+using parser_callback_t =
+ std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
+
+/*!
+@brief syntax analysis
+
+This class implements a recursive descent parser.
+*/
+template<typename BasicJsonType, typename InputAdapterType>
+class parser
+{
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using string_t = typename BasicJsonType::string_t;
+ using lexer_t = lexer<BasicJsonType, InputAdapterType>;
+ using token_type = typename lexer_t::token_type;
+
+ public:
+ /// a parser reading from an input adapter
+ explicit parser(InputAdapterType&& adapter,
+ const parser_callback_t<BasicJsonType> cb = nullptr,
+ const bool allow_exceptions_ = true,
+ const bool skip_comments = false)
+ : callback(cb)
+ , m_lexer(std::move(adapter), skip_comments)
+ , allow_exceptions(allow_exceptions_)
+ {
+ // read first token
+ get_token();
+ }
+
+ /*!
+ @brief public parser interface
+
+ @param[in] strict whether to expect the last token to be EOF
+ @param[in,out] result parsed JSON value
+
+ @throw parse_error.101 in case of an unexpected token
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+ */
+ void parse(const bool strict, BasicJsonType& result)
+ {
+ if (callback)
+ {
+ json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
+ sax_parse_internal(&sdp);
+
+ // in strict mode, input must be completely read
+ if (strict && (get_token() != token_type::end_of_input))
+ {
+ sdp.parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(),
+ exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ }
+
+ // in case of an error, return discarded value
+ if (sdp.is_errored())
+ {
+ result = value_t::discarded;
+ return;
+ }
+
+ // set top-level value to null if it was discarded by the callback
+ // function
+ if (result.is_discarded())
+ {
+ result = nullptr;
+ }
+ }
+ else
+ {
+ json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
+ sax_parse_internal(&sdp);
+
+ // in strict mode, input must be completely read
+ if (strict && (get_token() != token_type::end_of_input))
+ {
+ sdp.parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ }
+
+ // in case of an error, return discarded value
+ if (sdp.is_errored())
+ {
+ result = value_t::discarded;
+ return;
+ }
+ }
+
+ result.assert_invariant();
+ }
+
+ /*!
+ @brief public accept interface
+
+ @param[in] strict whether to expect the last token to be EOF
+ @return whether the input is a proper JSON text
+ */
+ bool accept(const bool strict = true)
+ {
+ json_sax_acceptor<BasicJsonType> sax_acceptor;
+ return sax_parse(&sax_acceptor, strict);
+ }
+
+ template<typename SAX>
+ JSON_HEDLEY_NON_NULL(2)
+ bool sax_parse(SAX* sax, const bool strict = true)
+ {
+ (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
+ const bool result = sax_parse_internal(sax);
+
+ // strict mode: next byte must be EOF
+ if (result && strict && (get_token() != token_type::end_of_input))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), BasicJsonType()));
+ }
+
+ return result;
+ }
+
+ private:
+ template<typename SAX>
+ JSON_HEDLEY_NON_NULL(2)
+ bool sax_parse_internal(SAX* sax)
+ {
+ // stack to remember the hierarchy of structured values we are parsing
+ // true = array; false = object
+ std::vector<bool> states;
+ // value to avoid a goto (see comment where set to true)
+ bool skip_to_state_evaluation = false;
+
+ while (true)
+ {
+ if (!skip_to_state_evaluation)
+ {
+ // invariant: get_token() was called before each iteration
+ switch (last_token)
+ {
+ case token_type::begin_object:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ // closing } -> we are done
+ if (get_token() == token_type::end_object)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ // parse key
+ if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+ }
+ if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
+ {
+ return false;
+ }
+
+ // parse separator (:)
+ if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+ }
+
+ // remember we are now inside an object
+ states.push_back(false);
+
+ // parse values
+ get_token();
+ continue;
+ }
+
+ case token_type::begin_array:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1))))
+ {
+ return false;
+ }
+
+ // closing ] -> we are done
+ if (get_token() == token_type::end_array)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ // remember we are now inside an array
+ states.push_back(true);
+
+ // parse values (no need to call get_token)
+ continue;
+ }
+
+ case token_type::value_float:
+ {
+ const auto res = m_lexer.get_number_float();
+
+ if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", BasicJsonType()));
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
+ {
+ return false;
+ }
+
+ break;
+ }
+
+ case token_type::literal_false:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::literal_null:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->null()))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::literal_true:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::value_integer:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::value_string:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::value_unsigned:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
+ {
+ return false;
+ }
+ break;
+ }
+
+ case token_type::parse_error:
+ {
+ // using "uninitialized" to avoid "expected" message
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), BasicJsonType()));
+ }
+
+ case token_type::uninitialized:
+ case token_type::end_array:
+ case token_type::end_object:
+ case token_type::name_separator:
+ case token_type::value_separator:
+ case token_type::end_of_input:
+ case token_type::literal_or_value:
+ default: // the last token was unexpected
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), BasicJsonType()));
+ }
+ }
+ }
+ else
+ {
+ skip_to_state_evaluation = false;
+ }
+
+ // we reached this line after we successfully parsed a value
+ if (states.empty())
+ {
+ // empty stack: we reached the end of the hierarchy: done
+ return true;
+ }
+
+ if (states.back()) // array
+ {
+ // comma -> next value
+ if (get_token() == token_type::value_separator)
+ {
+ // parse a new value
+ get_token();
+ continue;
+ }
+
+ // closing ]
+ if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
+ {
+ return false;
+ }
+
+ // We are done with this array. Before we can parse a
+ // new value, we need to evaluate the new state first.
+ // By setting skip_to_state_evaluation to false, we
+ // are effectively jumping to the beginning of this if.
+ JSON_ASSERT(!states.empty());
+ states.pop_back();
+ skip_to_state_evaluation = true;
+ continue;
+ }
+
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), BasicJsonType()));
+ }
+
+ // states.back() is false -> object
+
+ // comma -> next value
+ if (get_token() == token_type::value_separator)
+ {
+ // parse key
+ if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), BasicJsonType()));
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
+ {
+ return false;
+ }
+
+ // parse separator (:)
+ if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
+ {
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), BasicJsonType()));
+ }
+
+ // parse values
+ get_token();
+ continue;
+ }
+
+ // closing }
+ if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
+ {
+ if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
+ {
+ return false;
+ }
+
+ // We are done with this object. Before we can parse a
+ // new value, we need to evaluate the new state first.
+ // By setting skip_to_state_evaluation to false, we
+ // are effectively jumping to the beginning of this if.
+ JSON_ASSERT(!states.empty());
+ states.pop_back();
+ skip_to_state_evaluation = true;
+ continue;
+ }
+
+ return sax->parse_error(m_lexer.get_position(),
+ m_lexer.get_token_string(),
+ parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), BasicJsonType()));
+ }
+ }
+
+ /// get next token from lexer
+ token_type get_token()
+ {
+ return last_token = m_lexer.scan();
+ }
+
+ std::string exception_message(const token_type expected, const std::string& context)
+ {
+ std::string error_msg = "syntax error ";
+
+ if (!context.empty())
+ {
+ error_msg += "while parsing " + context + " ";
+ }
+
+ error_msg += "- ";
+
+ if (last_token == token_type::parse_error)
+ {
+ error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" +
+ m_lexer.get_token_string() + "'";
+ }
+ else
+ {
+ error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token));
+ }
+
+ if (expected != token_type::uninitialized)
+ {
+ error_msg += "; expected " + std::string(lexer_t::token_type_name(expected));
+ }
+
+ return error_msg;
+ }
+
+ private:
+ /// callback function
+ const parser_callback_t<BasicJsonType> callback = nullptr;
+ /// the type of the last read token
+ token_type last_token = token_type::uninitialized;
+ /// the lexer
+ lexer_t m_lexer;
+ /// whether to throw exceptions in case of errors
+ const bool allow_exceptions = true;
+};
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+
+#include <cstddef> // ptrdiff_t
+#include <limits> // numeric_limits
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/*
+@brief an iterator for primitive JSON types
+
+This class models an iterator for primitive JSON types (boolean, number,
+string). It's only purpose is to allow the iterator/const_iterator classes
+to "iterate" over primitive values. Internally, the iterator is modeled by
+a `difference_type` variable. Value begin_value (`0`) models the begin,
+end_value (`1`) models past the end.
+*/
+class primitive_iterator_t
+{
+ private:
+ using difference_type = std::ptrdiff_t;
+ static constexpr difference_type begin_value = 0;
+ static constexpr difference_type end_value = begin_value + 1;
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ /// iterator as signed integer type
+ difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
+
+ public:
+ constexpr difference_type get_value() const noexcept
+ {
+ return m_it;
+ }
+
+ /// set iterator to a defined beginning
+ void set_begin() noexcept
+ {
+ m_it = begin_value;
+ }
+
+ /// set iterator to a defined past the end
+ void set_end() noexcept
+ {
+ m_it = end_value;
+ }
+
+ /// return whether the iterator can be dereferenced
+ constexpr bool is_begin() const noexcept
+ {
+ return m_it == begin_value;
+ }
+
+ /// return whether the iterator is at end
+ constexpr bool is_end() const noexcept
+ {
+ return m_it == end_value;
+ }
+
+ friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+ {
+ return lhs.m_it == rhs.m_it;
+ }
+
+ friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+ {
+ return lhs.m_it < rhs.m_it;
+ }
+
+ primitive_iterator_t operator+(difference_type n) noexcept
+ {
+ auto result = *this;
+ result += n;
+ return result;
+ }
+
+ friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+ {
+ return lhs.m_it - rhs.m_it;
+ }
+
+ primitive_iterator_t& operator++() noexcept
+ {
+ ++m_it;
+ return *this;
+ }
+
+ primitive_iterator_t const operator++(int) noexcept // NOLINT(readability-const-return-type)
+ {
+ auto result = *this;
+ ++m_it;
+ return result;
+ }
+
+ primitive_iterator_t& operator--() noexcept
+ {
+ --m_it;
+ return *this;
+ }
+
+ primitive_iterator_t const operator--(int) noexcept // NOLINT(readability-const-return-type)
+ {
+ auto result = *this;
+ --m_it;
+ return result;
+ }
+
+ primitive_iterator_t& operator+=(difference_type n) noexcept
+ {
+ m_it += n;
+ return *this;
+ }
+
+ primitive_iterator_t& operator-=(difference_type n) noexcept
+ {
+ m_it -= n;
+ return *this;
+ }
+};
+} // namespace detail
+} // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/*!
+@brief an iterator value
+
+@note This structure could easily be a union, but MSVC currently does not allow
+unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
+*/
+template<typename BasicJsonType> struct internal_iterator
+{
+ /// iterator for JSON objects
+ typename BasicJsonType::object_t::iterator object_iterator {};
+ /// iterator for JSON arrays
+ typename BasicJsonType::array_t::iterator array_iterator {};
+ /// generic iterator for all other types
+ primitive_iterator_t primitive_iterator {};
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/iter_impl.hpp>
+
+
+#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
+#include <type_traits> // conditional, is_const, remove_const
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/iterators/internal_iterator.hpp>
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+// forward declare, to be able to friend it later on
+template<typename IteratorType> class iteration_proxy;
+template<typename IteratorType> class iteration_proxy_value;
+
+/*!
+@brief a template for a bidirectional iterator for the @ref basic_json class
+This class implements a both iterators (iterator and const_iterator) for the
+@ref basic_json class.
+@note An iterator is called *initialized* when a pointer to a JSON value has
+ been set (e.g., by a constructor or a copy assignment). If the iterator is
+ default-constructed, it is *uninitialized* and most methods are undefined.
+ **The library uses assertions to detect calls on uninitialized iterators.**
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+ The iterator that can be moved can be moved in both directions (i.e.
+ incremented and decremented).
+@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
+ iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
+*/
+template<typename BasicJsonType>
+class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+{
+ /// the iterator with BasicJsonType of different const-ness
+ using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
+ /// allow basic_json to access private members
+ friend other_iter_impl;
+ friend BasicJsonType;
+ friend iteration_proxy<iter_impl>;
+ friend iteration_proxy_value<iter_impl>;
+
+ using object_t = typename BasicJsonType::object_t;
+ using array_t = typename BasicJsonType::array_t;
+ // make sure BasicJsonType is basic_json or const basic_json
+ static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
+ "iter_impl only accepts (const) basic_json");
+
+ public:
+
+ /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
+ /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
+ /// A user-defined iterator should provide publicly accessible typedefs named
+ /// iterator_category, value_type, difference_type, pointer, and reference.
+ /// Note that value_type is required to be non-const, even for constant iterators.
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ /// the type of the values when the iterator is dereferenced
+ using value_type = typename BasicJsonType::value_type;
+ /// a type to represent differences between iterators
+ using difference_type = typename BasicJsonType::difference_type;
+ /// defines a pointer to the type iterated over (value_type)
+ using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
+ typename BasicJsonType::const_pointer,
+ typename BasicJsonType::pointer>::type;
+ /// defines a reference to the type iterated over (value_type)
+ using reference =
+ typename std::conditional<std::is_const<BasicJsonType>::value,
+ typename BasicJsonType::const_reference,
+ typename BasicJsonType::reference>::type;
+
+ iter_impl() = default;
+ ~iter_impl() = default;
+ iter_impl(iter_impl&&) noexcept = default;
+ iter_impl& operator=(iter_impl&&) noexcept = default;
+
+ /*!
+ @brief constructor for a given JSON instance
+ @param[in] object pointer to a JSON object for this iterator
+ @pre object != nullptr
+ @post The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ explicit iter_impl(pointer object) noexcept : m_object(object)
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ m_it.object_iterator = typename object_t::iterator();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_it.array_iterator = typename array_t::iterator();
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ m_it.primitive_iterator = primitive_iterator_t();
+ break;
+ }
+ }
+ }
+
+ /*!
+ @note The conventional copy constructor and copy assignment are implicitly
+ defined. Combined with the following converting constructor and
+ assignment, they support: (1) copy from iterator to iterator, (2)
+ copy from const iterator to const iterator, and (3) conversion from
+ iterator to const iterator. However conversion from const iterator
+ to iterator is not defined.
+ */
+
+ /*!
+ @brief const copy constructor
+ @param[in] other const iterator to copy from
+ @note This copy constructor had to be defined explicitly to circumvent a bug
+ occurring on msvc v19.0 compiler (VS 2015) debug build. For more
+ information refer to: https://github.com/nlohmann/json/issues/1608
+ */
+ iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
+ : m_object(other.m_object), m_it(other.m_it)
+ {}
+
+ /*!
+ @brief converting assignment
+ @param[in] other const iterator to copy from
+ @return const/non-const iterator
+ @note It is not checked whether @a other is initialized.
+ */
+ iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
+ {
+ if (&other != this)
+ {
+ m_object = other.m_object;
+ m_it = other.m_it;
+ }
+ return *this;
+ }
+
+ /*!
+ @brief converting constructor
+ @param[in] other non-const iterator to copy from
+ @note It is not checked whether @a other is initialized.
+ */
+ iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
+ : m_object(other.m_object), m_it(other.m_it)
+ {}
+
+ /*!
+ @brief converting assignment
+ @param[in] other non-const iterator to copy from
+ @return const/non-const iterator
+ @note It is not checked whether @a other is initialized.
+ */
+ iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
+ {
+ m_object = other.m_object;
+ m_it = other.m_it;
+ return *this;
+ }
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ /*!
+ @brief set the iterator to the first value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ void set_begin() noexcept
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ m_it.object_iterator = m_object->m_value.object->begin();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_it.array_iterator = m_object->m_value.array->begin();
+ break;
+ }
+
+ case value_t::null:
+ {
+ // set to end so begin()==end() is true: null is empty
+ m_it.primitive_iterator.set_end();
+ break;
+ }
+
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ m_it.primitive_iterator.set_begin();
+ break;
+ }
+ }
+ }
+
+ /*!
+ @brief set the iterator past the last value
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ void set_end() noexcept
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ m_it.object_iterator = m_object->m_value.object->end();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_it.array_iterator = m_object->m_value.array->end();
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ m_it.primitive_iterator.set_end();
+ break;
+ }
+ }
+ }
+
+ public:
+ /*!
+ @brief return a reference to the value pointed to by the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ reference operator*() const
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
+ return m_it.object_iterator->second;
+ }
+
+ case value_t::array:
+ {
+ JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
+ return *m_it.array_iterator;
+ }
+
+ case value_t::null:
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+ {
+ return *m_object;
+ }
+
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ }
+ }
+ }
+
+ /*!
+ @brief dereference the iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ pointer operator->() const
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
+ return &(m_it.object_iterator->second);
+ }
+
+ case value_t::array:
+ {
+ JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
+ return &*m_it.array_iterator;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
+ {
+ return m_object;
+ }
+
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ }
+ }
+ }
+
+ /*!
+ @brief post-increment (it++)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl const operator++(int) // NOLINT(readability-const-return-type)
+ {
+ auto result = *this;
+ ++(*this);
+ return result;
+ }
+
+ /*!
+ @brief pre-increment (++it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator++()
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ std::advance(m_it.object_iterator, 1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ std::advance(m_it.array_iterator, 1);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ ++m_it.primitive_iterator;
+ break;
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ @brief post-decrement (it--)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl const operator--(int) // NOLINT(readability-const-return-type)
+ {
+ auto result = *this;
+ --(*this);
+ return result;
+ }
+
+ /*!
+ @brief pre-decrement (--it)
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator--()
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ {
+ std::advance(m_it.object_iterator, -1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ std::advance(m_it.array_iterator, -1);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ --m_it.primitive_iterator;
+ break;
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ @brief comparison: equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
+ bool operator==(const IterImpl& other) const
+ {
+ // if objects are not the same, the comparison is undefined
+ if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+ }
+
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ return (m_it.object_iterator == other.m_it.object_iterator);
+
+ case value_t::array:
+ return (m_it.array_iterator == other.m_it.array_iterator);
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ return (m_it.primitive_iterator == other.m_it.primitive_iterator);
+ }
+ }
+
+ /*!
+ @brief comparison: not equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
+ bool operator!=(const IterImpl& other) const
+ {
+ return !operator==(other);
+ }
+
+ /*!
+ @brief comparison: smaller
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator<(const iter_impl& other) const
+ {
+ // if objects are not the same, the comparison is undefined
+ if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object));
+ }
+
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object));
+
+ case value_t::array:
+ return (m_it.array_iterator < other.m_it.array_iterator);
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ return (m_it.primitive_iterator < other.m_it.primitive_iterator);
+ }
+ }
+
+ /*!
+ @brief comparison: less than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator<=(const iter_impl& other) const
+ {
+ return !other.operator < (*this);
+ }
+
+ /*!
+ @brief comparison: greater than
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator>(const iter_impl& other) const
+ {
+ return !operator<=(other);
+ }
+
+ /*!
+ @brief comparison: greater than or equal
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ bool operator>=(const iter_impl& other) const
+ {
+ return !operator<(other);
+ }
+
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator+=(difference_type i)
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+
+ case value_t::array:
+ {
+ std::advance(m_it.array_iterator, i);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ m_it.primitive_iterator += i;
+ break;
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl& operator-=(difference_type i)
+ {
+ return operator+=(-i);
+ }
+
+ /*!
+ @brief add to iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl operator+(difference_type i) const
+ {
+ auto result = *this;
+ result += i;
+ return result;
+ }
+
+ /*!
+ @brief addition of distance and iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ friend iter_impl operator+(difference_type i, const iter_impl& it)
+ {
+ auto result = it;
+ result += i;
+ return result;
+ }
+
+ /*!
+ @brief subtract from iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ iter_impl operator-(difference_type i) const
+ {
+ auto result = *this;
+ result -= i;
+ return result;
+ }
+
+ /*!
+ @brief return difference
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ difference_type operator-(const iter_impl& other) const
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object));
+
+ case value_t::array:
+ return m_it.array_iterator - other.m_it.array_iterator;
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ return m_it.primitive_iterator - other.m_it.primitive_iterator;
+ }
+ }
+
+ /*!
+ @brief access to successor
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ reference operator[](difference_type n) const
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ switch (m_object->m_type)
+ {
+ case value_t::object:
+ JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object));
+
+ case value_t::array:
+ return *std::next(m_it.array_iterator, n);
+
+ case value_t::null:
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
+ {
+ return *m_object;
+ }
+
+ JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object));
+ }
+ }
+ }
+
+ /*!
+ @brief return the key of an object iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ const typename object_t::key_type& key() const
+ {
+ JSON_ASSERT(m_object != nullptr);
+
+ if (JSON_HEDLEY_LIKELY(m_object->is_object()))
+ {
+ return m_it.object_iterator->first;
+ }
+
+ JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object));
+ }
+
+ /*!
+ @brief return the value of an iterator
+ @pre The iterator is initialized; i.e. `m_object != nullptr`.
+ */
+ reference value() const
+ {
+ return operator*();
+ }
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ /// associated JSON instance
+ pointer m_object = nullptr;
+ /// the actual iterator of the associated instance
+ internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
+
+// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
+
+
+#include <cstddef> // ptrdiff_t
+#include <iterator> // reverse_iterator
+#include <utility> // declval
+
+namespace nlohmann
+{
+namespace detail
+{
+//////////////////////
+// reverse_iterator //
+//////////////////////
+
+/*!
+@brief a template for a reverse iterator class
+
+@tparam Base the base iterator type to reverse. Valid types are @ref
+iterator (to create @ref reverse_iterator) and @ref const_iterator (to
+create @ref const_reverse_iterator).
+
+@requirement The class satisfies the following concept requirements:
+-
+[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
+ The iterator that can be moved can be moved in both directions (i.e.
+ incremented and decremented).
+- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
+ It is possible to write to the pointed-to element (only if @a Base is
+ @ref iterator).
+
+@since version 1.0.0
+*/
+template<typename Base>
+class json_reverse_iterator : public std::reverse_iterator<Base>
+{
+ public:
+ using difference_type = std::ptrdiff_t;
+ /// shortcut to the reverse iterator adapter
+ using base_iterator = std::reverse_iterator<Base>;
+ /// the reference type for the pointed-to element
+ using reference = typename Base::reference;
+
+ /// create reverse iterator from iterator
+ explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
+ : base_iterator(it) {}
+
+ /// create reverse iterator from base class
+ explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
+
+ /// post-increment (it++)
+ json_reverse_iterator const operator++(int) // NOLINT(readability-const-return-type)
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
+ }
+
+ /// pre-increment (++it)
+ json_reverse_iterator& operator++()
+ {
+ return static_cast<json_reverse_iterator&>(base_iterator::operator++());
+ }
+
+ /// post-decrement (it--)
+ json_reverse_iterator const operator--(int) // NOLINT(readability-const-return-type)
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
+ }
+
+ /// pre-decrement (--it)
+ json_reverse_iterator& operator--()
+ {
+ return static_cast<json_reverse_iterator&>(base_iterator::operator--());
+ }
+
+ /// add to iterator
+ json_reverse_iterator& operator+=(difference_type i)
+ {
+ return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
+ }
+
+ /// add to iterator
+ json_reverse_iterator operator+(difference_type i) const
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
+ }
+
+ /// subtract from iterator
+ json_reverse_iterator operator-(difference_type i) const
+ {
+ return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
+ }
+
+ /// return difference
+ difference_type operator-(const json_reverse_iterator& other) const
+ {
+ return base_iterator(*this) - base_iterator(other);
+ }
+
+ /// access to successor
+ reference operator[](difference_type n) const
+ {
+ return *(this->operator+(n));
+ }
+
+ /// return the key of an object iterator
+ auto key() const -> decltype(std::declval<Base>().key())
+ {
+ auto it = --this->base();
+ return it.key();
+ }
+
+ /// return the value of an iterator
+ reference value() const
+ {
+ auto it = --this->base();
+ return it.operator * ();
+ }
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
+
+// #include <nlohmann/detail/json_pointer.hpp>
+
+
+#include <algorithm> // all_of
+#include <cctype> // isdigit
+#include <limits> // max
+#include <numeric> // accumulate
+#include <string> // string
+#include <utility> // move
+#include <vector> // vector
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+template<typename BasicJsonType>
+class json_pointer
+{
+ // allow basic_json to access private members
+ NLOHMANN_BASIC_JSON_TPL_DECLARATION
+ friend class basic_json;
+
+ public:
+ /*!
+ @brief create JSON pointer
+
+ Create a JSON pointer according to the syntax described in
+ [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3).
+
+ @param[in] s string representing the JSON pointer; if omitted, the empty
+ string is assumed which references the whole JSON value
+
+ @throw parse_error.107 if the given JSON pointer @a s is nonempty and does
+ not begin with a slash (`/`); see example below
+
+ @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is
+ not followed by `0` (representing `~`) or `1` (representing `/`); see
+ example below
+
+ @liveexample{The example shows the construction several valid JSON pointers
+ as well as the exceptional behavior.,json_pointer}
+
+ @since version 2.0.0
+ */
+ explicit json_pointer(const std::string& s = "")
+ : reference_tokens(split(s))
+ {}
+
+ /*!
+ @brief return a string representation of the JSON pointer
+
+ @invariant For each JSON pointer `ptr`, it holds:
+ @code {.cpp}
+ ptr == json_pointer(ptr.to_string());
+ @endcode
+
+ @return a string representation of the JSON pointer
+
+ @liveexample{The example shows the result of `to_string`.,json_pointer__to_string}
+
+ @since version 2.0.0
+ */
+ std::string to_string() const
+ {
+ return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
+ std::string{},
+ [](const std::string & a, const std::string & b)
+ {
+ return a + "/" + detail::escape(b);
+ });
+ }
+
+ /// @copydoc to_string()
+ operator std::string() const
+ {
+ return to_string();
+ }
+
+ /*!
+ @brief append another JSON pointer at the end of this JSON pointer
+
+ @param[in] ptr JSON pointer to append
+ @return JSON pointer with @a ptr appended
+
+ @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+ @complexity Linear in the length of @a ptr.
+
+ @sa see @ref operator/=(std::string) to append a reference token
+ @sa see @ref operator/=(std::size_t) to append an array index
+ @sa see @ref operator/(const json_pointer&, const json_pointer&) for a binary operator
+
+ @since version 3.6.0
+ */
+ json_pointer& operator/=(const json_pointer& ptr)
+ {
+ reference_tokens.insert(reference_tokens.end(),
+ ptr.reference_tokens.begin(),
+ ptr.reference_tokens.end());
+ return *this;
+ }
+
+ /*!
+ @brief append an unescaped reference token at the end of this JSON pointer
+
+ @param[in] token reference token to append
+ @return JSON pointer with @a token appended without escaping @a token
+
+ @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+ @complexity Amortized constant.
+
+ @sa see @ref operator/=(const json_pointer&) to append a JSON pointer
+ @sa see @ref operator/=(std::size_t) to append an array index
+ @sa see @ref operator/(const json_pointer&, std::size_t) for a binary operator
+
+ @since version 3.6.0
+ */
+ json_pointer& operator/=(std::string token)
+ {
+ push_back(std::move(token));
+ return *this;
+ }
+
+ /*!
+ @brief append an array index at the end of this JSON pointer
+
+ @param[in] array_idx array index to append
+ @return JSON pointer with @a array_idx appended
+
+ @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add}
+
+ @complexity Amortized constant.
+
+ @sa see @ref operator/=(const json_pointer&) to append a JSON pointer
+ @sa see @ref operator/=(std::string) to append a reference token
+ @sa see @ref operator/(const json_pointer&, std::string) for a binary operator
+
+ @since version 3.6.0
+ */
+ json_pointer& operator/=(std::size_t array_idx)
+ {
+ return *this /= std::to_string(array_idx);
+ }
+
+ /*!
+ @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
+
+ @param[in] lhs JSON pointer
+ @param[in] rhs JSON pointer
+ @return a new JSON pointer with @a rhs appended to @a lhs
+
+ @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+ @complexity Linear in the length of @a lhs and @a rhs.
+
+ @sa see @ref operator/=(const json_pointer&) to append a JSON pointer
+
+ @since version 3.6.0
+ */
+ friend json_pointer operator/(const json_pointer& lhs,
+ const json_pointer& rhs)
+ {
+ return json_pointer(lhs) /= rhs;
+ }
+
+ /*!
+ @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
+
+ @param[in] ptr JSON pointer
+ @param[in] token reference token
+ @return a new JSON pointer with unescaped @a token appended to @a ptr
+
+ @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+ @complexity Linear in the length of @a ptr.
+
+ @sa see @ref operator/=(std::string) to append a reference token
+
+ @since version 3.6.0
+ */
+ friend json_pointer operator/(const json_pointer& ptr, std::string token) // NOLINT(performance-unnecessary-value-param)
+ {
+ return json_pointer(ptr) /= std::move(token);
+ }
+
+ /*!
+ @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
+
+ @param[in] ptr JSON pointer
+ @param[in] array_idx array index
+ @return a new JSON pointer with @a array_idx appended to @a ptr
+
+ @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary}
+
+ @complexity Linear in the length of @a ptr.
+
+ @sa see @ref operator/=(std::size_t) to append an array index
+
+ @since version 3.6.0
+ */
+ friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx)
+ {
+ return json_pointer(ptr) /= array_idx;
+ }
+
+ /*!
+ @brief returns the parent of this JSON pointer
+
+ @return parent of this JSON pointer; in case this JSON pointer is the root,
+ the root itself is returned
+
+ @complexity Linear in the length of the JSON pointer.
+
+ @liveexample{The example shows the result of `parent_pointer` for different
+ JSON Pointers.,json_pointer__parent_pointer}
+
+ @since version 3.6.0
+ */
+ json_pointer parent_pointer() const
+ {
+ if (empty())
+ {
+ return *this;
+ }
+
+ json_pointer res = *this;
+ res.pop_back();
+ return res;
+ }
+
+ /*!
+ @brief remove last reference token
+
+ @pre not `empty()`
+
+ @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}
+
+ @complexity Constant.
+
+ @throw out_of_range.405 if JSON pointer has no parent
+
+ @since version 3.6.0
+ */
+ void pop_back()
+ {
+ if (JSON_HEDLEY_UNLIKELY(empty()))
+ {
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ }
+
+ reference_tokens.pop_back();
+ }
+
+ /*!
+ @brief return last reference token
+
+ @pre not `empty()`
+ @return last reference token
+
+ @liveexample{The example shows the usage of `back`.,json_pointer__back}
+
+ @complexity Constant.
+
+ @throw out_of_range.405 if JSON pointer has no parent
+
+ @since version 3.6.0
+ */
+ const std::string& back() const
+ {
+ if (JSON_HEDLEY_UNLIKELY(empty()))
+ {
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ }
+
+ return reference_tokens.back();
+ }
+
+ /*!
+ @brief append an unescaped token at the end of the reference pointer
+
+ @param[in] token token to add
+
+ @complexity Amortized constant.
+
+ @liveexample{The example shows the result of `push_back` for different
+ JSON Pointers.,json_pointer__push_back}
+
+ @since version 3.6.0
+ */
+ void push_back(const std::string& token)
+ {
+ reference_tokens.push_back(token);
+ }
+
+ /// @copydoc push_back(const std::string&)
+ void push_back(std::string&& token)
+ {
+ reference_tokens.push_back(std::move(token));
+ }
+
+ /*!
+ @brief return whether pointer points to the root document
+
+ @return true iff the JSON pointer points to the root document
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @liveexample{The example shows the result of `empty` for different JSON
+ Pointers.,json_pointer__empty}
+
+ @since version 3.6.0
+ */
+ bool empty() const noexcept
+ {
+ return reference_tokens.empty();
+ }
+
+ private:
+ /*!
+ @param[in] s reference token to be converted into an array index
+
+ @return integer representation of @a s
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index begins not with a digit
+ @throw out_of_range.404 if string @a s could not be converted to an integer
+ @throw out_of_range.410 if an array index exceeds size_type
+ */
+ static typename BasicJsonType::size_type array_index(const std::string& s)
+ {
+ using size_type = typename BasicJsonType::size_type;
+
+ // error condition (cf. RFC 6901, Sect. 4)
+ if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
+ {
+ JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", BasicJsonType()));
+ }
+
+ // error condition (cf. RFC 6901, Sect. 4)
+ if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
+ {
+ JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", BasicJsonType()));
+ }
+
+ std::size_t processed_chars = 0;
+ unsigned long long res = 0; // NOLINT(runtime/int)
+ JSON_TRY
+ {
+ res = std::stoull(s, &processed_chars);
+ }
+ JSON_CATCH(std::out_of_range&)
+ {
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+ }
+
+ // check if the string was completely read
+ if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size()))
+ {
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", BasicJsonType()));
+ }
+
+ // only triggered on special platforms (like 32bit), see also
+ // https://github.com/nlohmann/json/pull/2203
+ if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
+ {
+ JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", BasicJsonType())); // LCOV_EXCL_LINE
+ }
+
+ return static_cast<size_type>(res);
+ }
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ json_pointer top() const
+ {
+ if (JSON_HEDLEY_UNLIKELY(empty()))
+ {
+ JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", BasicJsonType()));
+ }
+
+ json_pointer result = *this;
+ result.reference_tokens = {reference_tokens[0]};
+ return result;
+ }
+
+ private:
+ /*!
+ @brief create and return a reference to the pointed to value
+
+ @complexity Linear in the number of reference tokens.
+
+ @throw parse_error.109 if array index is not a number
+ @throw type_error.313 if value cannot be unflattened
+ */
+ BasicJsonType& get_and_create(BasicJsonType& j) const
+ {
+ auto* result = &j;
+
+ // in case no reference tokens exist, return a reference to the JSON value
+ // j which will be overwritten by a primitive value
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (result->type())
+ {
+ case detail::value_t::null:
+ {
+ if (reference_token == "0")
+ {
+ // start a new array if reference token is 0
+ result = &result->operator[](0);
+ }
+ else
+ {
+ // start a new object otherwise
+ result = &result->operator[](reference_token);
+ }
+ break;
+ }
+
+ case detail::value_t::object:
+ {
+ // create an entry in the object
+ result = &result->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ // create an entry in the array
+ result = &result->operator[](array_index(reference_token));
+ break;
+ }
+
+ /*
+ The following code is only reached if there exists a reference
+ token _and_ the current value is primitive. In this case, we have
+ an error situation, because primitive values may only occur as
+ single value; that is, with an empty list of reference tokens.
+ */
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j));
+ }
+ }
+
+ return *result;
+ }
+
+ /*!
+ @brief return a reference to the pointed to value
+
+ @note This version does not throw if a value is not present, but tries to
+ create nested values instead. For instance, calling this function
+ with pointer `"/this/that"` on a null value is equivalent to calling
+ `operator[]("this").operator[]("that")` on that value, effectively
+ changing the null value to an object.
+
+ @param[in] ptr a JSON value
+
+ @return reference to the JSON value pointed to by the JSON pointer
+
+ @complexity Linear in the length of the JSON pointer.
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ BasicJsonType& get_unchecked(BasicJsonType* ptr) const
+ {
+ for (const auto& reference_token : reference_tokens)
+ {
+ // convert null values to arrays or objects before continuing
+ if (ptr->is_null())
+ {
+ // check if reference token is a number
+ const bool nums =
+ std::all_of(reference_token.begin(), reference_token.end(),
+ [](const unsigned char x)
+ {
+ return std::isdigit(x);
+ });
+
+ // change value to array for numbers or "-" or to object otherwise
+ *ptr = (nums || reference_token == "-")
+ ? detail::value_t::array
+ : detail::value_t::object;
+ }
+
+ switch (ptr->type())
+ {
+ case detail::value_t::object:
+ {
+ // use unchecked object access
+ ptr = &ptr->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (reference_token == "-")
+ {
+ // explicitly treat "-" as index beyond the end
+ ptr = &ptr->operator[](ptr->m_value.array->size());
+ }
+ else
+ {
+ // convert array index to number; unchecked access
+ ptr = &ptr->operator[](array_index(reference_token));
+ }
+ break;
+ }
+
+ case detail::value_t::null:
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ }
+ }
+
+ return *ptr;
+ }
+
+ /*!
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ BasicJsonType& get_checked(BasicJsonType* ptr) const
+ {
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->type())
+ {
+ case detail::value_t::object:
+ {
+ // note: at performs range check
+ ptr = &ptr->at(reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+ {
+ // "-" always fails the range check
+ JSON_THROW(detail::out_of_range::create(402,
+ "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+ ") is out of range", *ptr));
+ }
+
+ // note: at performs range check
+ ptr = &ptr->at(array_index(reference_token));
+ break;
+ }
+
+ case detail::value_t::null:
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ }
+ }
+
+ return *ptr;
+ }
+
+ /*!
+ @brief return a const reference to the pointed to value
+
+ @param[in] ptr a JSON value
+
+ @return const reference to the JSON value pointed to by the JSON
+ pointer
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
+ {
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->type())
+ {
+ case detail::value_t::object:
+ {
+ // use unchecked object access
+ ptr = &ptr->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+ {
+ // "-" cannot be used for const access
+ JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr));
+ }
+
+ // use unchecked array access
+ ptr = &ptr->operator[](array_index(reference_token));
+ break;
+ }
+
+ case detail::value_t::null:
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ }
+ }
+
+ return *ptr;
+ }
+
+ /*!
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+ */
+ const BasicJsonType& get_checked(const BasicJsonType* ptr) const
+ {
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->type())
+ {
+ case detail::value_t::object:
+ {
+ // note: at performs range check
+ ptr = &ptr->at(reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+ {
+ // "-" always fails the range check
+ JSON_THROW(detail::out_of_range::create(402,
+ "array index '-' (" + std::to_string(ptr->m_value.array->size()) +
+ ") is out of range", *ptr));
+ }
+
+ // note: at performs range check
+ ptr = &ptr->at(array_index(reference_token));
+ break;
+ }
+
+ case detail::value_t::null:
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr));
+ }
+ }
+
+ return *ptr;
+ }
+
+ /*!
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ */
+ bool contains(const BasicJsonType* ptr) const
+ {
+ for (const auto& reference_token : reference_tokens)
+ {
+ switch (ptr->type())
+ {
+ case detail::value_t::object:
+ {
+ if (!ptr->contains(reference_token))
+ {
+ // we did not find the key in the object
+ return false;
+ }
+
+ ptr = &ptr->operator[](reference_token);
+ break;
+ }
+
+ case detail::value_t::array:
+ {
+ if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
+ {
+ // "-" always fails the range check
+ return false;
+ }
+ if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
+ {
+ // invalid char
+ return false;
+ }
+ if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
+ {
+ if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
+ {
+ // first char should be between '1' and '9'
+ return false;
+ }
+ for (std::size_t i = 1; i < reference_token.size(); i++)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
+ {
+ // other char should be between '0' and '9'
+ return false;
+ }
+ }
+ }
+
+ const auto idx = array_index(reference_token);
+ if (idx >= ptr->size())
+ {
+ // index out of range
+ return false;
+ }
+
+ ptr = &ptr->operator[](idx);
+ break;
+ }
+
+ case detail::value_t::null:
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ {
+ // we do not expect primitive values if there is still a
+ // reference token to process
+ return false;
+ }
+ }
+ }
+
+ // no reference token left means we found a primitive value
+ return true;
+ }
+
+ /*!
+ @brief split the string input to reference tokens
+
+ @note This function is only called by the json_pointer constructor.
+ All exceptions below are documented there.
+
+ @throw parse_error.107 if the pointer is not empty or begins with '/'
+ @throw parse_error.108 if character '~' is not followed by '0' or '1'
+ */
+ static std::vector<std::string> split(const std::string& reference_string)
+ {
+ std::vector<std::string> result;
+
+ // special case: empty reference string -> no reference tokens
+ if (reference_string.empty())
+ {
+ return result;
+ }
+
+ // check if nonempty reference string begins with slash
+ if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
+ {
+ JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", BasicJsonType()));
+ }
+
+ // extract the reference tokens:
+ // - slash: position of the last read slash (or end of string)
+ // - start: position after the previous slash
+ for (
+ // search for the first slash after the first character
+ std::size_t slash = reference_string.find_first_of('/', 1),
+ // set the beginning of the first reference token
+ start = 1;
+ // we can stop if start == 0 (if slash == std::string::npos)
+ start != 0;
+ // set the beginning of the next reference token
+ // (will eventually be 0 if slash == std::string::npos)
+ start = (slash == std::string::npos) ? 0 : slash + 1,
+ // find next slash
+ slash = reference_string.find_first_of('/', start))
+ {
+ // use the text between the beginning of the reference token
+ // (start) and the last slash (slash).
+ auto reference_token = reference_string.substr(start, slash - start);
+
+ // check reference tokens are properly escaped
+ for (std::size_t pos = reference_token.find_first_of('~');
+ pos != std::string::npos;
+ pos = reference_token.find_first_of('~', pos + 1))
+ {
+ JSON_ASSERT(reference_token[pos] == '~');
+
+ // ~ must be followed by 0 or 1
+ if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
+ (reference_token[pos + 1] != '0' &&
+ reference_token[pos + 1] != '1')))
+ {
+ JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", BasicJsonType()));
+ }
+ }
+
+ // finally, store the reference token
+ detail::unescape(reference_token);
+ result.push_back(reference_token);
+ }
+
+ return result;
+ }
+
+ private:
+ /*!
+ @param[in] reference_string the reference string to the current value
+ @param[in] value the value to consider
+ @param[in,out] result the result object to insert values to
+
+ @note Empty objects or arrays are flattened to `null`.
+ */
+ static void flatten(const std::string& reference_string,
+ const BasicJsonType& value,
+ BasicJsonType& result)
+ {
+ switch (value.type())
+ {
+ case detail::value_t::array:
+ {
+ if (value.m_value.array->empty())
+ {
+ // flatten empty array as null
+ result[reference_string] = nullptr;
+ }
+ else
+ {
+ // iterate array and use index as reference string
+ for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
+ {
+ flatten(reference_string + "/" + std::to_string(i),
+ value.m_value.array->operator[](i), result);
+ }
+ }
+ break;
+ }
+
+ case detail::value_t::object:
+ {
+ if (value.m_value.object->empty())
+ {
+ // flatten empty object as null
+ result[reference_string] = nullptr;
+ }
+ else
+ {
+ // iterate object and use keys as reference string
+ for (const auto& element : *value.m_value.object)
+ {
+ flatten(reference_string + "/" + detail::escape(element.first), element.second, result);
+ }
+ }
+ break;
+ }
+
+ case detail::value_t::null:
+ case detail::value_t::string:
+ case detail::value_t::boolean:
+ case detail::value_t::number_integer:
+ case detail::value_t::number_unsigned:
+ case detail::value_t::number_float:
+ case detail::value_t::binary:
+ case detail::value_t::discarded:
+ default:
+ {
+ // add primitive value with its reference string
+ result[reference_string] = value;
+ break;
+ }
+ }
+ }
+
+ /*!
+ @param[in] value flattened JSON
+
+ @return unflattened JSON
+
+ @throw parse_error.109 if array index is not a number
+ @throw type_error.314 if value is not an object
+ @throw type_error.315 if object values are not primitive
+ @throw type_error.313 if value cannot be unflattened
+ */
+ static BasicJsonType
+ unflatten(const BasicJsonType& value)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
+ {
+ JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value));
+ }
+
+ BasicJsonType result;
+
+ // iterate the JSON object values
+ for (const auto& element : *value.m_value.object)
+ {
+ if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
+ {
+ JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second));
+ }
+
+ // assign value to reference pointed to by JSON pointer; Note that if
+ // the JSON pointer is "" (i.e., points to the whole value), function
+ // get_and_create returns a reference to result itself. An assignment
+ // will then create a primitive value.
+ json_pointer(element.first).get_and_create(result) = element.second;
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief compares two JSON pointers for equality
+
+ @param[in] lhs JSON pointer to compare
+ @param[in] rhs JSON pointer to compare
+ @return whether @a lhs is equal to @a rhs
+
+ @complexity Linear in the length of the JSON pointer
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+ */
+ friend bool operator==(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept
+ {
+ return lhs.reference_tokens == rhs.reference_tokens;
+ }
+
+ /*!
+ @brief compares two JSON pointers for inequality
+
+ @param[in] lhs JSON pointer to compare
+ @param[in] rhs JSON pointer to compare
+ @return whether @a lhs is not equal @a rhs
+
+ @complexity Linear in the length of the JSON pointer
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+ */
+ friend bool operator!=(json_pointer const& lhs,
+ json_pointer const& rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ /// the reference tokens
+ std::vector<std::string> reference_tokens;
+};
+} // namespace nlohmann
+
+// #include <nlohmann/detail/json_ref.hpp>
+
+
+#include <initializer_list>
+#include <utility>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+template<typename BasicJsonType>
+class json_ref
+{
+ public:
+ using value_type = BasicJsonType;
+
+ json_ref(value_type&& value)
+ : owned_value(std::move(value))
+ {}
+
+ json_ref(const value_type& value)
+ : value_ref(&value)
+ {}
+
+ json_ref(std::initializer_list<json_ref> init)
+ : owned_value(init)
+ {}
+
+ template <
+ class... Args,
+ enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
+ json_ref(Args && ... args)
+ : owned_value(std::forward<Args>(args)...)
+ {}
+
+ // class should be movable only
+ json_ref(json_ref&&) noexcept = default;
+ json_ref(const json_ref&) = delete;
+ json_ref& operator=(const json_ref&) = delete;
+ json_ref& operator=(json_ref&&) = delete;
+ ~json_ref() = default;
+
+ value_type moved_or_copied() const
+ {
+ if (value_ref == nullptr)
+ {
+ return std::move(owned_value);
+ }
+ return *value_ref;
+ }
+
+ value_type const& operator*() const
+ {
+ return value_ref ? *value_ref : owned_value;
+ }
+
+ value_type const* operator->() const
+ {
+ return &** this;
+ }
+
+ private:
+ mutable value_type owned_value = nullptr;
+ value_type const* value_ref = nullptr;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/string_escape.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/meta/type_traits.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+
+#include <algorithm> // reverse
+#include <array> // array
+#include <cmath> // isnan, isinf
+#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
+#include <cstring> // memcpy
+#include <limits> // numeric_limits
+#include <string> // string
+#include <utility> // move
+
+// #include <nlohmann/detail/input/binary_reader.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+
+#include <algorithm> // copy
+#include <cstddef> // size_t
+#include <iterator> // back_inserter
+#include <memory> // shared_ptr, make_shared
+#include <string> // basic_string
+#include <vector> // vector
+
+#ifndef JSON_NO_IO
+ #include <ios> // streamsize
+ #include <ostream> // basic_ostream
+#endif // JSON_NO_IO
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+/// abstract output adapter interface
+template<typename CharType> struct output_adapter_protocol
+{
+ virtual void write_character(CharType c) = 0;
+ virtual void write_characters(const CharType* s, std::size_t length) = 0;
+ virtual ~output_adapter_protocol() = default;
+
+ output_adapter_protocol() = default;
+ output_adapter_protocol(const output_adapter_protocol&) = default;
+ output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
+ output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
+ output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
+};
+
+/// a type to simplify interfaces
+template<typename CharType>
+using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
+
+/// output adapter for byte vectors
+template<typename CharType, typename AllocatorType = std::allocator<CharType>>
+class output_vector_adapter : public output_adapter_protocol<CharType>
+{
+ public:
+ explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
+ : v(vec)
+ {}
+
+ void write_character(CharType c) override
+ {
+ v.push_back(c);
+ }
+
+ JSON_HEDLEY_NON_NULL(2)
+ void write_characters(const CharType* s, std::size_t length) override
+ {
+ std::copy(s, s + length, std::back_inserter(v));
+ }
+
+ private:
+ std::vector<CharType, AllocatorType>& v;
+};
+
+#ifndef JSON_NO_IO
+/// output adapter for output streams
+template<typename CharType>
+class output_stream_adapter : public output_adapter_protocol<CharType>
+{
+ public:
+ explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
+ : stream(s)
+ {}
+
+ void write_character(CharType c) override
+ {
+ stream.put(c);
+ }
+
+ JSON_HEDLEY_NON_NULL(2)
+ void write_characters(const CharType* s, std::size_t length) override
+ {
+ stream.write(s, static_cast<std::streamsize>(length));
+ }
+
+ private:
+ std::basic_ostream<CharType>& stream;
+};
+#endif // JSON_NO_IO
+
+/// output adapter for basic_string
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_string_adapter : public output_adapter_protocol<CharType>
+{
+ public:
+ explicit output_string_adapter(StringType& s) noexcept
+ : str(s)
+ {}
+
+ void write_character(CharType c) override
+ {
+ str.push_back(c);
+ }
+
+ JSON_HEDLEY_NON_NULL(2)
+ void write_characters(const CharType* s, std::size_t length) override
+ {
+ str.append(s, length);
+ }
+
+ private:
+ StringType& str;
+};
+
+template<typename CharType, typename StringType = std::basic_string<CharType>>
+class output_adapter
+{
+ public:
+ template<typename AllocatorType = std::allocator<CharType>>
+ output_adapter(std::vector<CharType, AllocatorType>& vec)
+ : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
+
+#ifndef JSON_NO_IO
+ output_adapter(std::basic_ostream<CharType>& s)
+ : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
+#endif // JSON_NO_IO
+
+ output_adapter(StringType& s)
+ : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
+
+ operator output_adapter_t<CharType>()
+ {
+ return oa;
+ }
+
+ private:
+ output_adapter_t<CharType> oa = nullptr;
+};
+} // namespace detail
+} // namespace nlohmann
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// binary writer //
+///////////////////
+
+/*!
+@brief serialization to CBOR and MessagePack values
+*/
+template<typename BasicJsonType, typename CharType>
+class binary_writer
+{
+ using string_t = typename BasicJsonType::string_t;
+ using binary_t = typename BasicJsonType::binary_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+
+ public:
+ /*!
+ @brief create a binary writer
+
+ @param[in] adapter output adapter to write to
+ */
+ explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
+ {
+ JSON_ASSERT(oa);
+ }
+
+ /*!
+ @param[in] j JSON value to serialize
+ @pre j.type() == value_t::object
+ */
+ void write_bson(const BasicJsonType& j)
+ {
+ switch (j.type())
+ {
+ case value_t::object:
+ {
+ write_bson_object(*j.m_value.object);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::array:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));
+ }
+ }
+ }
+
+ /*!
+ @param[in] j JSON value to serialize
+ */
+ void write_cbor(const BasicJsonType& j)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ oa->write_character(to_char_type(0xF6));
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ oa->write_character(j.m_value.boolean
+ ? to_char_type(0xF5)
+ : to_char_type(0xF4));
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // CBOR does not differentiate between positive signed
+ // integers and unsigned integers. Therefore, we used the
+ // code from the value_t::number_unsigned case here.
+ if (j.m_value.number_integer <= 0x17)
+ {
+ write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0x18));
+ write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0x19));
+ write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0x1A));
+ write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+ }
+ else
+ {
+ oa->write_character(to_char_type(0x1B));
+ write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+ }
+ }
+ else
+ {
+ // The conversions below encode the sign in the first
+ // byte, and the value is converted to a positive number.
+ const auto positive_number = -1 - j.m_value.number_integer;
+ if (j.m_value.number_integer >= -24)
+ {
+ write_number(static_cast<std::uint8_t>(0x20 + positive_number));
+ }
+ else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0x38));
+ write_number(static_cast<std::uint8_t>(positive_number));
+ }
+ else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0x39));
+ write_number(static_cast<std::uint16_t>(positive_number));
+ }
+ else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0x3A));
+ write_number(static_cast<std::uint32_t>(positive_number));
+ }
+ else
+ {
+ oa->write_character(to_char_type(0x3B));
+ write_number(static_cast<std::uint64_t>(positive_number));
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned <= 0x17)
+ {
+ write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0x18));
+ write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0x19));
+ write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0x1A));
+ write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
+ }
+ else
+ {
+ oa->write_character(to_char_type(0x1B));
+ write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
+ }
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ if (std::isnan(j.m_value.number_float))
+ {
+ // NaN is 0xf97e00 in CBOR
+ oa->write_character(to_char_type(0xF9));
+ oa->write_character(to_char_type(0x7E));
+ oa->write_character(to_char_type(0x00));
+ }
+ else if (std::isinf(j.m_value.number_float))
+ {
+ // Infinity is 0xf97c00, -Infinity is 0xf9fc00
+ oa->write_character(to_char_type(0xf9));
+ oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
+ oa->write_character(to_char_type(0x00));
+ }
+ else
+ {
+ write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
+ }
+ break;
+ }
+
+ case value_t::string:
+ {
+ // step 1: write control byte and the string length
+ const auto N = j.m_value.string->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<std::uint8_t>(0x60 + N));
+ }
+ else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0x78));
+ write_number(static_cast<std::uint8_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0x79));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0x7A));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ oa->write_character(to_char_type(0x7B));
+ write_number(static_cast<std::uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write the string
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+ j.m_value.string->size());
+ break;
+ }
+
+ case value_t::array:
+ {
+ // step 1: write control byte and the array size
+ const auto N = j.m_value.array->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<std::uint8_t>(0x80 + N));
+ }
+ else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0x98));
+ write_number(static_cast<std::uint8_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0x99));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0x9A));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ oa->write_character(to_char_type(0x9B));
+ write_number(static_cast<std::uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.array)
+ {
+ write_cbor(el);
+ }
+ break;
+ }
+
+ case value_t::binary:
+ {
+ if (j.m_value.binary->has_subtype())
+ {
+ if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ write_number(static_cast<std::uint8_t>(0xd8));
+ write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
+ }
+ else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ write_number(static_cast<std::uint8_t>(0xd9));
+ write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
+ }
+ else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ write_number(static_cast<std::uint8_t>(0xda));
+ write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
+ }
+ else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ write_number(static_cast<std::uint8_t>(0xdb));
+ write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
+ }
+ }
+
+ // step 1: write control byte and the binary array size
+ const auto N = j.m_value.binary->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<std::uint8_t>(0x40 + N));
+ }
+ else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0x58));
+ write_number(static_cast<std::uint8_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0x59));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0x5A));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ oa->write_character(to_char_type(0x5B));
+ write_number(static_cast<std::uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write each element
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+ N);
+
+ break;
+ }
+
+ case value_t::object:
+ {
+ // step 1: write control byte and the object size
+ const auto N = j.m_value.object->size();
+ if (N <= 0x17)
+ {
+ write_number(static_cast<std::uint8_t>(0xA0 + N));
+ }
+ else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ oa->write_character(to_char_type(0xB8));
+ write_number(static_cast<std::uint8_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ oa->write_character(to_char_type(0xB9));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ oa->write_character(to_char_type(0xBA));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+ // LCOV_EXCL_START
+ else if (N <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ oa->write_character(to_char_type(0xBB));
+ write_number(static_cast<std::uint64_t>(N));
+ }
+ // LCOV_EXCL_STOP
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.object)
+ {
+ write_cbor(el.first);
+ write_cbor(el.second);
+ }
+ break;
+ }
+
+ case value_t::discarded:
+ default:
+ break;
+ }
+ }
+
+ /*!
+ @param[in] j JSON value to serialize
+ */
+ void write_msgpack(const BasicJsonType& j)
+ {
+ switch (j.type())
+ {
+ case value_t::null: // nil
+ {
+ oa->write_character(to_char_type(0xC0));
+ break;
+ }
+
+ case value_t::boolean: // true and false
+ {
+ oa->write_character(j.m_value.boolean
+ ? to_char_type(0xC3)
+ : to_char_type(0xC2));
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ if (j.m_value.number_integer >= 0)
+ {
+ // MessagePack does not differentiate between positive
+ // signed integers and unsigned integers. Therefore, we used
+ // the code from the value_t::number_unsigned case here.
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ // uint 8
+ oa->write_character(to_char_type(0xCC));
+ write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ // uint 16
+ oa->write_character(to_char_type(0xCD));
+ write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ // uint 32
+ oa->write_character(to_char_type(0xCE));
+ write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ // uint 64
+ oa->write_character(to_char_type(0xCF));
+ write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+ }
+ }
+ else
+ {
+ if (j.m_value.number_integer >= -32)
+ {
+ // negative fixnum
+ write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
+ j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+ {
+ // int 8
+ oa->write_character(to_char_type(0xD0));
+ write_number(static_cast<std::int8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
+ j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+ {
+ // int 16
+ oa->write_character(to_char_type(0xD1));
+ write_number(static_cast<std::int16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
+ j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+ {
+ // int 32
+ oa->write_character(to_char_type(0xD2));
+ write_number(static_cast<std::int32_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
+ j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+ {
+ // int 64
+ oa->write_character(to_char_type(0xD3));
+ write_number(static_cast<std::int64_t>(j.m_value.number_integer));
+ }
+ }
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned < 128)
+ {
+ // positive fixnum
+ write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ // uint 8
+ oa->write_character(to_char_type(0xCC));
+ write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ // uint 16
+ oa->write_character(to_char_type(0xCD));
+ write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ // uint 32
+ oa->write_character(to_char_type(0xCE));
+ write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
+ }
+ else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
+ {
+ // uint 64
+ oa->write_character(to_char_type(0xCF));
+ write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
+ }
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
+ break;
+ }
+
+ case value_t::string:
+ {
+ // step 1: write control byte and the string length
+ const auto N = j.m_value.string->size();
+ if (N <= 31)
+ {
+ // fixstr
+ write_number(static_cast<std::uint8_t>(0xA0 | N));
+ }
+ else if (N <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ // str 8
+ oa->write_character(to_char_type(0xD9));
+ write_number(static_cast<std::uint8_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ // str 16
+ oa->write_character(to_char_type(0xDA));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ // str 32
+ oa->write_character(to_char_type(0xDB));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+
+ // step 2: write the string
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+ j.m_value.string->size());
+ break;
+ }
+
+ case value_t::array:
+ {
+ // step 1: write control byte and the array size
+ const auto N = j.m_value.array->size();
+ if (N <= 15)
+ {
+ // fixarray
+ write_number(static_cast<std::uint8_t>(0x90 | N));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ // array 16
+ oa->write_character(to_char_type(0xDC));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ // array 32
+ oa->write_character(to_char_type(0xDD));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.array)
+ {
+ write_msgpack(el);
+ }
+ break;
+ }
+
+ case value_t::binary:
+ {
+ // step 0: determine if the binary type has a set subtype to
+ // determine whether or not to use the ext or fixext types
+ const bool use_ext = j.m_value.binary->has_subtype();
+
+ // step 1: write control byte and the byte string length
+ const auto N = j.m_value.binary->size();
+ if (N <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ std::uint8_t output_type{};
+ bool fixed = true;
+ if (use_ext)
+ {
+ switch (N)
+ {
+ case 1:
+ output_type = 0xD4; // fixext 1
+ break;
+ case 2:
+ output_type = 0xD5; // fixext 2
+ break;
+ case 4:
+ output_type = 0xD6; // fixext 4
+ break;
+ case 8:
+ output_type = 0xD7; // fixext 8
+ break;
+ case 16:
+ output_type = 0xD8; // fixext 16
+ break;
+ default:
+ output_type = 0xC7; // ext 8
+ fixed = false;
+ break;
+ }
+
+ }
+ else
+ {
+ output_type = 0xC4; // bin 8
+ fixed = false;
+ }
+
+ oa->write_character(to_char_type(output_type));
+ if (!fixed)
+ {
+ write_number(static_cast<std::uint8_t>(N));
+ }
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ std::uint8_t output_type = use_ext
+ ? 0xC8 // ext 16
+ : 0xC5; // bin 16
+
+ oa->write_character(to_char_type(output_type));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ std::uint8_t output_type = use_ext
+ ? 0xC9 // ext 32
+ : 0xC6; // bin 32
+
+ oa->write_character(to_char_type(output_type));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+
+ // step 1.5: if this is an ext type, write the subtype
+ if (use_ext)
+ {
+ write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
+ }
+
+ // step 2: write the byte string
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+ N);
+
+ break;
+ }
+
+ case value_t::object:
+ {
+ // step 1: write control byte and the object size
+ const auto N = j.m_value.object->size();
+ if (N <= 15)
+ {
+ // fixmap
+ write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
+ }
+ else if (N <= (std::numeric_limits<std::uint16_t>::max)())
+ {
+ // map 16
+ oa->write_character(to_char_type(0xDE));
+ write_number(static_cast<std::uint16_t>(N));
+ }
+ else if (N <= (std::numeric_limits<std::uint32_t>::max)())
+ {
+ // map 32
+ oa->write_character(to_char_type(0xDF));
+ write_number(static_cast<std::uint32_t>(N));
+ }
+
+ // step 2: write each element
+ for (const auto& el : *j.m_value.object)
+ {
+ write_msgpack(el.first);
+ write_msgpack(el.second);
+ }
+ break;
+ }
+
+ case value_t::discarded:
+ default:
+ break;
+ }
+ }
+
+ /*!
+ @param[in] j JSON value to serialize
+ @param[in] use_count whether to use '#' prefixes (optimized format)
+ @param[in] use_type whether to use '$' prefixes (optimized format)
+ @param[in] add_prefix whether prefixes need to be used for this value
+ */
+ void write_ubjson(const BasicJsonType& j, const bool use_count,
+ const bool use_type, const bool add_prefix = true)
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('Z'));
+ }
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ if (add_prefix)
+ {
+ oa->write_character(j.m_value.boolean
+ ? to_char_type('T')
+ : to_char_type('F'));
+ }
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix);
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix);
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix);
+ break;
+ }
+
+ case value_t::string:
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('S'));
+ }
+ write_number_with_ubjson_prefix(j.m_value.string->size(), true);
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
+ j.m_value.string->size());
+ break;
+ }
+
+ case value_t::array:
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('['));
+ }
+
+ bool prefix_required = true;
+ if (use_type && !j.m_value.array->empty())
+ {
+ JSON_ASSERT(use_count);
+ const CharType first_prefix = ubjson_prefix(j.front());
+ const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
+ [this, first_prefix](const BasicJsonType & v)
+ {
+ return ubjson_prefix(v) == first_prefix;
+ });
+
+ if (same_prefix)
+ {
+ prefix_required = false;
+ oa->write_character(to_char_type('$'));
+ oa->write_character(first_prefix);
+ }
+ }
+
+ if (use_count)
+ {
+ oa->write_character(to_char_type('#'));
+ write_number_with_ubjson_prefix(j.m_value.array->size(), true);
+ }
+
+ for (const auto& el : *j.m_value.array)
+ {
+ write_ubjson(el, use_count, use_type, prefix_required);
+ }
+
+ if (!use_count)
+ {
+ oa->write_character(to_char_type(']'));
+ }
+
+ break;
+ }
+
+ case value_t::binary:
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('['));
+ }
+
+ if (use_type && !j.m_value.binary->empty())
+ {
+ JSON_ASSERT(use_count);
+ oa->write_character(to_char_type('$'));
+ oa->write_character('U');
+ }
+
+ if (use_count)
+ {
+ oa->write_character(to_char_type('#'));
+ write_number_with_ubjson_prefix(j.m_value.binary->size(), true);
+ }
+
+ if (use_type)
+ {
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(j.m_value.binary->data()),
+ j.m_value.binary->size());
+ }
+ else
+ {
+ for (size_t i = 0; i < j.m_value.binary->size(); ++i)
+ {
+ oa->write_character(to_char_type('U'));
+ oa->write_character(j.m_value.binary->data()[i]);
+ }
+ }
+
+ if (!use_count)
+ {
+ oa->write_character(to_char_type(']'));
+ }
+
+ break;
+ }
+
+ case value_t::object:
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('{'));
+ }
+
+ bool prefix_required = true;
+ if (use_type && !j.m_value.object->empty())
+ {
+ JSON_ASSERT(use_count);
+ const CharType first_prefix = ubjson_prefix(j.front());
+ const bool same_prefix = std::all_of(j.begin(), j.end(),
+ [this, first_prefix](const BasicJsonType & v)
+ {
+ return ubjson_prefix(v) == first_prefix;
+ });
+
+ if (same_prefix)
+ {
+ prefix_required = false;
+ oa->write_character(to_char_type('$'));
+ oa->write_character(first_prefix);
+ }
+ }
+
+ if (use_count)
+ {
+ oa->write_character(to_char_type('#'));
+ write_number_with_ubjson_prefix(j.m_value.object->size(), true);
+ }
+
+ for (const auto& el : *j.m_value.object)
+ {
+ write_number_with_ubjson_prefix(el.first.size(), true);
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(el.first.c_str()),
+ el.first.size());
+ write_ubjson(el.second, use_count, use_type, prefix_required);
+ }
+
+ if (!use_count)
+ {
+ oa->write_character(to_char_type('}'));
+ }
+
+ break;
+ }
+
+ case value_t::discarded:
+ default:
+ break;
+ }
+ }
+
+ private:
+ //////////
+ // BSON //
+ //////////
+
+ /*!
+ @return The size of a BSON document entry header, including the id marker
+ and the entry name size (and its null-terminator).
+ */
+ static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
+ {
+ const auto it = name.find(static_cast<typename string_t::value_type>(0));
+ if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
+ {
+ JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j));
+ static_cast<void>(j);
+ }
+
+ return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
+ }
+
+ /*!
+ @brief Writes the given @a element_type and @a name to the output adapter
+ */
+ void write_bson_entry_header(const string_t& name,
+ const std::uint8_t element_type)
+ {
+ oa->write_character(to_char_type(element_type)); // boolean
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(name.c_str()),
+ name.size() + 1u);
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and boolean value @a value
+ */
+ void write_bson_boolean(const string_t& name,
+ const bool value)
+ {
+ write_bson_entry_header(name, 0x08);
+ oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and double value @a value
+ */
+ void write_bson_double(const string_t& name,
+ const double value)
+ {
+ write_bson_entry_header(name, 0x01);
+ write_number<double, true>(value);
+ }
+
+ /*!
+ @return The size of the BSON-encoded string in @a value
+ */
+ static std::size_t calc_bson_string_size(const string_t& value)
+ {
+ return sizeof(std::int32_t) + value.size() + 1ul;
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and string value @a value
+ */
+ void write_bson_string(const string_t& name,
+ const string_t& value)
+ {
+ write_bson_entry_header(name, 0x02);
+
+ write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size() + 1ul));
+ oa->write_characters(
+ reinterpret_cast<const CharType*>(value.c_str()),
+ value.size() + 1);
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and null value
+ */
+ void write_bson_null(const string_t& name)
+ {
+ write_bson_entry_header(name, 0x0A);
+ }
+
+ /*!
+ @return The size of the BSON-encoded integer @a value
+ */
+ static std::size_t calc_bson_integer_size(const std::int64_t value)
+ {
+ return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
+ ? sizeof(std::int32_t)
+ : sizeof(std::int64_t);
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and integer @a value
+ */
+ void write_bson_integer(const string_t& name,
+ const std::int64_t value)
+ {
+ if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
+ {
+ write_bson_entry_header(name, 0x10); // int32
+ write_number<std::int32_t, true>(static_cast<std::int32_t>(value));
+ }
+ else
+ {
+ write_bson_entry_header(name, 0x12); // int64
+ write_number<std::int64_t, true>(static_cast<std::int64_t>(value));
+ }
+ }
+
+ /*!
+ @return The size of the BSON-encoded unsigned integer in @a j
+ */
+ static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
+ {
+ return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+ ? sizeof(std::int32_t)
+ : sizeof(std::int64_t);
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and unsigned @a value
+ */
+ void write_bson_unsigned(const string_t& name,
+ const BasicJsonType& j)
+ {
+ if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+ {
+ write_bson_entry_header(name, 0x10 /* int32 */);
+ write_number<std::int32_t, true>(static_cast<std::int32_t>(j.m_value.number_unsigned));
+ }
+ else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+ {
+ write_bson_entry_header(name, 0x12 /* int64 */);
+ write_number<std::int64_t, true>(static_cast<std::int64_t>(j.m_value.number_unsigned));
+ }
+ else
+ {
+ JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j));
+ }
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and object @a value
+ */
+ void write_bson_object_entry(const string_t& name,
+ const typename BasicJsonType::object_t& value)
+ {
+ write_bson_entry_header(name, 0x03); // object
+ write_bson_object(value);
+ }
+
+ /*!
+ @return The size of the BSON-encoded array @a value
+ */
+ static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
+ {
+ std::size_t array_index = 0ul;
+
+ const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
+ {
+ return result + calc_bson_element_size(std::to_string(array_index++), el);
+ });
+
+ return sizeof(std::int32_t) + embedded_document_size + 1ul;
+ }
+
+ /*!
+ @return The size of the BSON-encoded binary array @a value
+ */
+ static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
+ {
+ return sizeof(std::int32_t) + value.size() + 1ul;
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and array @a value
+ */
+ void write_bson_array(const string_t& name,
+ const typename BasicJsonType::array_t& value)
+ {
+ write_bson_entry_header(name, 0x04); // array
+ write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_array_size(value)));
+
+ std::size_t array_index = 0ul;
+
+ for (const auto& el : value)
+ {
+ write_bson_element(std::to_string(array_index++), el);
+ }
+
+ oa->write_character(to_char_type(0x00));
+ }
+
+ /*!
+ @brief Writes a BSON element with key @a name and binary value @a value
+ */
+ void write_bson_binary(const string_t& name,
+ const binary_t& value)
+ {
+ write_bson_entry_header(name, 0x05);
+
+ write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
+ write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : std::uint8_t(0x00));
+
+ oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
+ }
+
+ /*!
+ @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
+ @return The calculated size for the BSON document entry for @a j with the given @a name.
+ */
+ static std::size_t calc_bson_element_size(const string_t& name,
+ const BasicJsonType& j)
+ {
+ const auto header_size = calc_bson_entry_header_size(name, j);
+ switch (j.type())
+ {
+ case value_t::object:
+ return header_size + calc_bson_object_size(*j.m_value.object);
+
+ case value_t::array:
+ return header_size + calc_bson_array_size(*j.m_value.array);
+
+ case value_t::binary:
+ return header_size + calc_bson_binary_size(*j.m_value.binary);
+
+ case value_t::boolean:
+ return header_size + 1ul;
+
+ case value_t::number_float:
+ return header_size + 8ul;
+
+ case value_t::number_integer:
+ return header_size + calc_bson_integer_size(j.m_value.number_integer);
+
+ case value_t::number_unsigned:
+ return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
+
+ case value_t::string:
+ return header_size + calc_bson_string_size(*j.m_value.string);
+
+ case value_t::null:
+ return header_size + 0ul;
+
+ // LCOV_EXCL_START
+ case value_t::discarded:
+ default:
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
+ return 0ul;
+ // LCOV_EXCL_STOP
+ }
+ }
+
+ /*!
+ @brief Serializes the JSON value @a j to BSON and associates it with the
+ key @a name.
+ @param name The name to associate with the JSON entity @a j within the
+ current BSON document
+ */
+ void write_bson_element(const string_t& name,
+ const BasicJsonType& j)
+ {
+ switch (j.type())
+ {
+ case value_t::object:
+ return write_bson_object_entry(name, *j.m_value.object);
+
+ case value_t::array:
+ return write_bson_array(name, *j.m_value.array);
+
+ case value_t::binary:
+ return write_bson_binary(name, *j.m_value.binary);
+
+ case value_t::boolean:
+ return write_bson_boolean(name, j.m_value.boolean);
+
+ case value_t::number_float:
+ return write_bson_double(name, j.m_value.number_float);
+
+ case value_t::number_integer:
+ return write_bson_integer(name, j.m_value.number_integer);
+
+ case value_t::number_unsigned:
+ return write_bson_unsigned(name, j);
+
+ case value_t::string:
+ return write_bson_string(name, *j.m_value.string);
+
+ case value_t::null:
+ return write_bson_null(name);
+
+ // LCOV_EXCL_START
+ case value_t::discarded:
+ default:
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
+ return;
+ // LCOV_EXCL_STOP
+ }
+ }
+
+ /*!
+ @brief Calculates the size of the BSON serialization of the given
+ JSON-object @a j.
+ @param[in] value JSON value to serialize
+ @pre value.type() == value_t::object
+ */
+ static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
+ {
+ std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0),
+ [](size_t result, const typename BasicJsonType::object_t::value_type & el)
+ {
+ return result += calc_bson_element_size(el.first, el.second);
+ });
+
+ return sizeof(std::int32_t) + document_size + 1ul;
+ }
+
+ /*!
+ @param[in] value JSON value to serialize
+ @pre value.type() == value_t::object
+ */
+ void write_bson_object(const typename BasicJsonType::object_t& value)
+ {
+ write_number<std::int32_t, true>(static_cast<std::int32_t>(calc_bson_object_size(value)));
+
+ for (const auto& el : value)
+ {
+ write_bson_element(el.first, el.second);
+ }
+
+ oa->write_character(to_char_type(0x00));
+ }
+
+ //////////
+ // CBOR //
+ //////////
+
+ static constexpr CharType get_cbor_float_prefix(float /*unused*/)
+ {
+ return to_char_type(0xFA); // Single-Precision Float
+ }
+
+ static constexpr CharType get_cbor_float_prefix(double /*unused*/)
+ {
+ return to_char_type(0xFB); // Double-Precision Float
+ }
+
+ /////////////
+ // MsgPack //
+ /////////////
+
+ static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
+ {
+ return to_char_type(0xCA); // float 32
+ }
+
+ static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
+ {
+ return to_char_type(0xCB); // float 64
+ }
+
+ ////////////
+ // UBJSON //
+ ////////////
+
+ // UBJSON: write number (floating point)
+ template<typename NumberType, typename std::enable_if<
+ std::is_floating_point<NumberType>::value, int>::type = 0>
+ void write_number_with_ubjson_prefix(const NumberType n,
+ const bool add_prefix)
+ {
+ if (add_prefix)
+ {
+ oa->write_character(get_ubjson_float_prefix(n));
+ }
+ write_number(n);
+ }
+
+ // UBJSON: write number (unsigned integer)
+ template<typename NumberType, typename std::enable_if<
+ std::is_unsigned<NumberType>::value, int>::type = 0>
+ void write_number_with_ubjson_prefix(const NumberType n,
+ const bool add_prefix)
+ {
+ if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('i')); // int8
+ }
+ write_number(static_cast<std::uint8_t>(n));
+ }
+ else if (n <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('U')); // uint8
+ }
+ write_number(static_cast<std::uint8_t>(n));
+ }
+ else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('I')); // int16
+ }
+ write_number(static_cast<std::int16_t>(n));
+ }
+ else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('l')); // int32
+ }
+ write_number(static_cast<std::int32_t>(n));
+ }
+ else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('L')); // int64
+ }
+ write_number(static_cast<std::int64_t>(n));
+ }
+ else
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('H')); // high-precision number
+ }
+
+ const auto number = BasicJsonType(n).dump();
+ write_number_with_ubjson_prefix(number.size(), true);
+ for (std::size_t i = 0; i < number.size(); ++i)
+ {
+ oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
+ }
+ }
+ }
+
+ // UBJSON: write number (signed integer)
+ template < typename NumberType, typename std::enable_if <
+ std::is_signed<NumberType>::value&&
+ !std::is_floating_point<NumberType>::value, int >::type = 0 >
+ void write_number_with_ubjson_prefix(const NumberType n,
+ const bool add_prefix)
+ {
+ if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('i')); // int8
+ }
+ write_number(static_cast<std::int8_t>(n));
+ }
+ else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('U')); // uint8
+ }
+ write_number(static_cast<std::uint8_t>(n));
+ }
+ else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('I')); // int16
+ }
+ write_number(static_cast<std::int16_t>(n));
+ }
+ else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('l')); // int32
+ }
+ write_number(static_cast<std::int32_t>(n));
+ }
+ else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('L')); // int64
+ }
+ write_number(static_cast<std::int64_t>(n));
+ }
+ // LCOV_EXCL_START
+ else
+ {
+ if (add_prefix)
+ {
+ oa->write_character(to_char_type('H')); // high-precision number
+ }
+
+ const auto number = BasicJsonType(n).dump();
+ write_number_with_ubjson_prefix(number.size(), true);
+ for (std::size_t i = 0; i < number.size(); ++i)
+ {
+ oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
+ }
+ }
+ // LCOV_EXCL_STOP
+ }
+
+ /*!
+ @brief determine the type prefix of container values
+ */
+ CharType ubjson_prefix(const BasicJsonType& j) const noexcept
+ {
+ switch (j.type())
+ {
+ case value_t::null:
+ return 'Z';
+
+ case value_t::boolean:
+ return j.m_value.boolean ? 'T' : 'F';
+
+ case value_t::number_integer:
+ {
+ if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
+ {
+ return 'i';
+ }
+ if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
+ {
+ return 'U';
+ }
+ if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
+ {
+ return 'I';
+ }
+ if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
+ {
+ return 'l';
+ }
+ if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
+ {
+ return 'L';
+ }
+ // anything else is treated as high-precision number
+ return 'H'; // LCOV_EXCL_LINE
+ }
+
+ case value_t::number_unsigned:
+ {
+ if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
+ {
+ return 'i';
+ }
+ if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
+ {
+ return 'U';
+ }
+ if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
+ {
+ return 'I';
+ }
+ if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
+ {
+ return 'l';
+ }
+ if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
+ {
+ return 'L';
+ }
+ // anything else is treated as high-precision number
+ return 'H'; // LCOV_EXCL_LINE
+ }
+
+ case value_t::number_float:
+ return get_ubjson_float_prefix(j.m_value.number_float);
+
+ case value_t::string:
+ return 'S';
+
+ case value_t::array: // fallthrough
+ case value_t::binary:
+ return '[';
+
+ case value_t::object:
+ return '{';
+
+ case value_t::discarded:
+ default: // discarded values
+ return 'N';
+ }
+ }
+
+ static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
+ {
+ return 'd'; // float 32
+ }
+
+ static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
+ {
+ return 'D'; // float 64
+ }
+
+ ///////////////////////
+ // Utility functions //
+ ///////////////////////
+
+ /*
+ @brief write a number to output input
+ @param[in] n number of type @a NumberType
+ @tparam NumberType the type of the number
+ @tparam OutputIsLittleEndian Set to true if output data is
+ required to be little endian
+
+ @note This function needs to respect the system's endianness, because bytes
+ in CBOR, MessagePack, and UBJSON are stored in network order (big
+ endian) and therefore need reordering on little endian systems.
+ */
+ template<typename NumberType, bool OutputIsLittleEndian = false>
+ void write_number(const NumberType n)
+ {
+ // step 1: write number to array of length NumberType
+ std::array<CharType, sizeof(NumberType)> vec{};
+ std::memcpy(vec.data(), &n, sizeof(NumberType));
+
+ // step 2: write array to output (with possible reordering)
+ if (is_little_endian != OutputIsLittleEndian)
+ {
+ // reverse byte order prior to conversion if necessary
+ std::reverse(vec.begin(), vec.end());
+ }
+
+ oa->write_characters(vec.data(), sizeof(NumberType));
+ }
+
+ void write_compact_float(const number_float_t n, detail::input_format_t format)
+ {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
+ static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
+ static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
+ {
+ oa->write_character(format == detail::input_format_t::cbor
+ ? get_cbor_float_prefix(static_cast<float>(n))
+ : get_msgpack_float_prefix(static_cast<float>(n)));
+ write_number(static_cast<float>(n));
+ }
+ else
+ {
+ oa->write_character(format == detail::input_format_t::cbor
+ ? get_cbor_float_prefix(n)
+ : get_msgpack_float_prefix(n));
+ write_number(n);
+ }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+ }
+
+ public:
+ // The following to_char_type functions are implement the conversion
+ // between uint8_t and CharType. In case CharType is not unsigned,
+ // such a conversion is required to allow values greater than 128.
+ // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
+ template < typename C = CharType,
+ enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
+ static constexpr CharType to_char_type(std::uint8_t x) noexcept
+ {
+ return *reinterpret_cast<char*>(&x);
+ }
+
+ template < typename C = CharType,
+ enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
+ static CharType to_char_type(std::uint8_t x) noexcept
+ {
+ static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
+ static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
+ CharType result;
+ std::memcpy(&result, &x, sizeof(x));
+ return result;
+ }
+
+ template<typename C = CharType,
+ enable_if_t<std::is_unsigned<C>::value>* = nullptr>
+ static constexpr CharType to_char_type(std::uint8_t x) noexcept
+ {
+ return x;
+ }
+
+ template < typename InputCharType, typename C = CharType,
+ enable_if_t <
+ std::is_signed<C>::value &&
+ std::is_signed<char>::value &&
+ std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
+ > * = nullptr >
+ static constexpr CharType to_char_type(InputCharType x) noexcept
+ {
+ return x;
+ }
+
+ private:
+ /// whether we can assume little endianness
+ const bool is_little_endian = little_endianness();
+
+ /// the output
+ output_adapter_t<CharType> oa = nullptr;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/output/serializer.hpp>
+
+
+#include <algorithm> // reverse, remove, fill, find, none_of
+#include <array> // array
+#include <clocale> // localeconv, lconv
+#include <cmath> // labs, isfinite, isnan, signbit
+#include <cstddef> // size_t, ptrdiff_t
+#include <cstdint> // uint8_t
+#include <cstdio> // snprintf
+#include <limits> // numeric_limits
+#include <string> // string, char_traits
+#include <iomanip> // setfill, setw
+#include <sstream> // stringstream
+#include <type_traits> // is_same
+#include <utility> // move
+
+// #include <nlohmann/detail/conversions/to_chars.hpp>
+
+
+#include <array> // array
+#include <cmath> // signbit, isfinite
+#include <cstdint> // intN_t, uintN_t
+#include <cstring> // memcpy, memmove
+#include <limits> // numeric_limits
+#include <type_traits> // conditional
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+
+/*!
+@brief implements the Grisu2 algorithm for binary to decimal floating-point
+conversion.
+
+This implementation is a slightly modified version of the reference
+implementation which may be obtained from
+http://florian.loitsch.com/publications (bench.tar.gz).
+
+The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
+
+For a detailed description of the algorithm see:
+
+[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
+ Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
+ Language Design and Implementation, PLDI 2010
+[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
+ Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
+ Design and Implementation, PLDI 1996
+*/
+namespace dtoa_impl
+{
+
+template<typename Target, typename Source>
+Target reinterpret_bits(const Source source)
+{
+ static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
+
+ Target target;
+ std::memcpy(&target, &source, sizeof(Source));
+ return target;
+}
+
+struct diyfp // f * 2^e
+{
+ static constexpr int kPrecision = 64; // = q
+
+ std::uint64_t f = 0;
+ int e = 0;
+
+ constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
+
+ /*!
+ @brief returns x - y
+ @pre x.e == y.e and x.f >= y.f
+ */
+ static diyfp sub(const diyfp& x, const diyfp& y) noexcept
+ {
+ JSON_ASSERT(x.e == y.e);
+ JSON_ASSERT(x.f >= y.f);
+
+ return {x.f - y.f, x.e};
+ }
+
+ /*!
+ @brief returns x * y
+ @note The result is rounded. (Only the upper q bits are returned.)
+ */
+ static diyfp mul(const diyfp& x, const diyfp& y) noexcept
+ {
+ static_assert(kPrecision == 64, "internal error");
+
+ // Computes:
+ // f = round((x.f * y.f) / 2^q)
+ // e = x.e + y.e + q
+
+ // Emulate the 64-bit * 64-bit multiplication:
+ //
+ // p = u * v
+ // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
+ // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
+ // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
+ // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
+ // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
+ // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
+ // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
+ //
+ // (Since Q might be larger than 2^32 - 1)
+ //
+ // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
+ //
+ // (Q_hi + H does not overflow a 64-bit int)
+ //
+ // = p_lo + 2^64 p_hi
+
+ const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
+ const std::uint64_t u_hi = x.f >> 32u;
+ const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
+ const std::uint64_t v_hi = y.f >> 32u;
+
+ const std::uint64_t p0 = u_lo * v_lo;
+ const std::uint64_t p1 = u_lo * v_hi;
+ const std::uint64_t p2 = u_hi * v_lo;
+ const std::uint64_t p3 = u_hi * v_hi;
+
+ const std::uint64_t p0_hi = p0 >> 32u;
+ const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
+ const std::uint64_t p1_hi = p1 >> 32u;
+ const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
+ const std::uint64_t p2_hi = p2 >> 32u;
+
+ std::uint64_t Q = p0_hi + p1_lo + p2_lo;
+
+ // The full product might now be computed as
+ //
+ // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
+ // p_lo = p0_lo + (Q << 32)
+ //
+ // But in this particular case here, the full p_lo is not required.
+ // Effectively we only need to add the highest bit in p_lo to p_hi (and
+ // Q_hi + 1 does not overflow).
+
+ Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
+
+ const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
+
+ return {h, x.e + y.e + 64};
+ }
+
+ /*!
+ @brief normalize x such that the significand is >= 2^(q-1)
+ @pre x.f != 0
+ */
+ static diyfp normalize(diyfp x) noexcept
+ {
+ JSON_ASSERT(x.f != 0);
+
+ while ((x.f >> 63u) == 0)
+ {
+ x.f <<= 1u;
+ x.e--;
+ }
+
+ return x;
+ }
+
+ /*!
+ @brief normalize x such that the result has the exponent E
+ @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
+ */
+ static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
+ {
+ const int delta = x.e - target_exponent;
+
+ JSON_ASSERT(delta >= 0);
+ JSON_ASSERT(((x.f << delta) >> delta) == x.f);
+
+ return {x.f << delta, target_exponent};
+ }
+};
+
+struct boundaries
+{
+ diyfp w;
+ diyfp minus;
+ diyfp plus;
+};
+
+/*!
+Compute the (normalized) diyfp representing the input number 'value' and its
+boundaries.
+
+@pre value must be finite and positive
+*/
+template<typename FloatType>
+boundaries compute_boundaries(FloatType value)
+{
+ JSON_ASSERT(std::isfinite(value));
+ JSON_ASSERT(value > 0);
+
+ // Convert the IEEE representation into a diyfp.
+ //
+ // If v is denormal:
+ // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
+ // If v is normalized:
+ // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
+
+ static_assert(std::numeric_limits<FloatType>::is_iec559,
+ "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
+
+ constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
+ constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
+ constexpr int kMinExp = 1 - kBias;
+ constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
+
+ using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
+
+ const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
+ const std::uint64_t E = bits >> (kPrecision - 1);
+ const std::uint64_t F = bits & (kHiddenBit - 1);
+
+ const bool is_denormal = E == 0;
+ const diyfp v = is_denormal
+ ? diyfp(F, kMinExp)
+ : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
+
+ // Compute the boundaries m- and m+ of the floating-point value
+ // v = f * 2^e.
+ //
+ // Determine v- and v+, the floating-point predecessor and successor if v,
+ // respectively.
+ //
+ // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
+ // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
+ //
+ // v+ = v + 2^e
+ //
+ // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
+ // between m- and m+ round to v, regardless of how the input rounding
+ // algorithm breaks ties.
+ //
+ // ---+-------------+-------------+-------------+-------------+--- (A)
+ // v- m- v m+ v+
+ //
+ // -----------------+------+------+-------------+-------------+--- (B)
+ // v- m- v m+ v+
+
+ const bool lower_boundary_is_closer = F == 0 && E > 1;
+ const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
+ const diyfp m_minus = lower_boundary_is_closer
+ ? diyfp(4 * v.f - 1, v.e - 2) // (B)
+ : diyfp(2 * v.f - 1, v.e - 1); // (A)
+
+ // Determine the normalized w+ = m+.
+ const diyfp w_plus = diyfp::normalize(m_plus);
+
+ // Determine w- = m- such that e_(w-) = e_(w+).
+ const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
+
+ return {diyfp::normalize(v), w_minus, w_plus};
+}
+
+// Given normalized diyfp w, Grisu needs to find a (normalized) cached
+// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
+// within a certain range [alpha, gamma] (Definition 3.2 from [1])
+//
+// alpha <= e = e_c + e_w + q <= gamma
+//
+// or
+//
+// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
+// <= f_c * f_w * 2^gamma
+//
+// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
+//
+// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
+//
+// or
+//
+// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
+//
+// The choice of (alpha,gamma) determines the size of the table and the form of
+// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
+// in practice:
+//
+// The idea is to cut the number c * w = f * 2^e into two parts, which can be
+// processed independently: An integral part p1, and a fractional part p2:
+//
+// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
+// = (f div 2^-e) + (f mod 2^-e) * 2^e
+// = p1 + p2 * 2^e
+//
+// The conversion of p1 into decimal form requires a series of divisions and
+// modulos by (a power of) 10. These operations are faster for 32-bit than for
+// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
+// achieved by choosing
+//
+// -e >= 32 or e <= -32 := gamma
+//
+// In order to convert the fractional part
+//
+// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
+//
+// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
+// d[-i] are extracted in order:
+//
+// (10 * p2) div 2^-e = d[-1]
+// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
+//
+// The multiplication by 10 must not overflow. It is sufficient to choose
+//
+// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
+//
+// Since p2 = f mod 2^-e < 2^-e,
+//
+// -e <= 60 or e >= -60 := alpha
+
+constexpr int kAlpha = -60;
+constexpr int kGamma = -32;
+
+struct cached_power // c = f * 2^e ~= 10^k
+{
+ std::uint64_t f;
+ int e;
+ int k;
+};
+
+/*!
+For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
+power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
+satisfies (Definition 3.2 from [1])
+
+ alpha <= e_c + e + q <= gamma.
+*/
+inline cached_power get_cached_power_for_binary_exponent(int e)
+{
+ // Now
+ //
+ // alpha <= e_c + e + q <= gamma (1)
+ // ==> f_c * 2^alpha <= c * 2^e * 2^q
+ //
+ // and since the c's are normalized, 2^(q-1) <= f_c,
+ //
+ // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
+ // ==> 2^(alpha - e - 1) <= c
+ //
+ // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
+ //
+ // k = ceil( log_10( 2^(alpha - e - 1) ) )
+ // = ceil( (alpha - e - 1) * log_10(2) )
+ //
+ // From the paper:
+ // "In theory the result of the procedure could be wrong since c is rounded,
+ // and the computation itself is approximated [...]. In practice, however,
+ // this simple function is sufficient."
+ //
+ // For IEEE double precision floating-point numbers converted into
+ // normalized diyfp's w = f * 2^e, with q = 64,
+ //
+ // e >= -1022 (min IEEE exponent)
+ // -52 (p - 1)
+ // -52 (p - 1, possibly normalize denormal IEEE numbers)
+ // -11 (normalize the diyfp)
+ // = -1137
+ //
+ // and
+ //
+ // e <= +1023 (max IEEE exponent)
+ // -52 (p - 1)
+ // -11 (normalize the diyfp)
+ // = 960
+ //
+ // This binary exponent range [-1137,960] results in a decimal exponent
+ // range [-307,324]. One does not need to store a cached power for each
+ // k in this range. For each such k it suffices to find a cached power
+ // such that the exponent of the product lies in [alpha,gamma].
+ // This implies that the difference of the decimal exponents of adjacent
+ // table entries must be less than or equal to
+ //
+ // floor( (gamma - alpha) * log_10(2) ) = 8.
+ //
+ // (A smaller distance gamma-alpha would require a larger table.)
+
+ // NB:
+ // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
+
+ constexpr int kCachedPowersMinDecExp = -300;
+ constexpr int kCachedPowersDecStep = 8;
+
+ static constexpr std::array<cached_power, 79> kCachedPowers =
+ {
+ {
+ { 0xAB70FE17C79AC6CA, -1060, -300 },
+ { 0xFF77B1FCBEBCDC4F, -1034, -292 },
+ { 0xBE5691EF416BD60C, -1007, -284 },
+ { 0x8DD01FAD907FFC3C, -980, -276 },
+ { 0xD3515C2831559A83, -954, -268 },
+ { 0x9D71AC8FADA6C9B5, -927, -260 },
+ { 0xEA9C227723EE8BCB, -901, -252 },
+ { 0xAECC49914078536D, -874, -244 },
+ { 0x823C12795DB6CE57, -847, -236 },
+ { 0xC21094364DFB5637, -821, -228 },
+ { 0x9096EA6F3848984F, -794, -220 },
+ { 0xD77485CB25823AC7, -768, -212 },
+ { 0xA086CFCD97BF97F4, -741, -204 },
+ { 0xEF340A98172AACE5, -715, -196 },
+ { 0xB23867FB2A35B28E, -688, -188 },
+ { 0x84C8D4DFD2C63F3B, -661, -180 },
+ { 0xC5DD44271AD3CDBA, -635, -172 },
+ { 0x936B9FCEBB25C996, -608, -164 },
+ { 0xDBAC6C247D62A584, -582, -156 },
+ { 0xA3AB66580D5FDAF6, -555, -148 },
+ { 0xF3E2F893DEC3F126, -529, -140 },
+ { 0xB5B5ADA8AAFF80B8, -502, -132 },
+ { 0x87625F056C7C4A8B, -475, -124 },
+ { 0xC9BCFF6034C13053, -449, -116 },
+ { 0x964E858C91BA2655, -422, -108 },
+ { 0xDFF9772470297EBD, -396, -100 },
+ { 0xA6DFBD9FB8E5B88F, -369, -92 },
+ { 0xF8A95FCF88747D94, -343, -84 },
+ { 0xB94470938FA89BCF, -316, -76 },
+ { 0x8A08F0F8BF0F156B, -289, -68 },
+ { 0xCDB02555653131B6, -263, -60 },
+ { 0x993FE2C6D07B7FAC, -236, -52 },
+ { 0xE45C10C42A2B3B06, -210, -44 },
+ { 0xAA242499697392D3, -183, -36 },
+ { 0xFD87B5F28300CA0E, -157, -28 },
+ { 0xBCE5086492111AEB, -130, -20 },
+ { 0x8CBCCC096F5088CC, -103, -12 },
+ { 0xD1B71758E219652C, -77, -4 },
+ { 0x9C40000000000000, -50, 4 },
+ { 0xE8D4A51000000000, -24, 12 },
+ { 0xAD78EBC5AC620000, 3, 20 },
+ { 0x813F3978F8940984, 30, 28 },
+ { 0xC097CE7BC90715B3, 56, 36 },
+ { 0x8F7E32CE7BEA5C70, 83, 44 },
+ { 0xD5D238A4ABE98068, 109, 52 },
+ { 0x9F4F2726179A2245, 136, 60 },
+ { 0xED63A231D4C4FB27, 162, 68 },
+ { 0xB0DE65388CC8ADA8, 189, 76 },
+ { 0x83C7088E1AAB65DB, 216, 84 },
+ { 0xC45D1DF942711D9A, 242, 92 },
+ { 0x924D692CA61BE758, 269, 100 },
+ { 0xDA01EE641A708DEA, 295, 108 },
+ { 0xA26DA3999AEF774A, 322, 116 },
+ { 0xF209787BB47D6B85, 348, 124 },
+ { 0xB454E4A179DD1877, 375, 132 },
+ { 0x865B86925B9BC5C2, 402, 140 },
+ { 0xC83553C5C8965D3D, 428, 148 },
+ { 0x952AB45CFA97A0B3, 455, 156 },
+ { 0xDE469FBD99A05FE3, 481, 164 },
+ { 0xA59BC234DB398C25, 508, 172 },
+ { 0xF6C69A72A3989F5C, 534, 180 },
+ { 0xB7DCBF5354E9BECE, 561, 188 },
+ { 0x88FCF317F22241E2, 588, 196 },
+ { 0xCC20CE9BD35C78A5, 614, 204 },
+ { 0x98165AF37B2153DF, 641, 212 },
+ { 0xE2A0B5DC971F303A, 667, 220 },
+ { 0xA8D9D1535CE3B396, 694, 228 },
+ { 0xFB9B7CD9A4A7443C, 720, 236 },
+ { 0xBB764C4CA7A44410, 747, 244 },
+ { 0x8BAB8EEFB6409C1A, 774, 252 },
+ { 0xD01FEF10A657842C, 800, 260 },
+ { 0x9B10A4E5E9913129, 827, 268 },
+ { 0xE7109BFBA19C0C9D, 853, 276 },
+ { 0xAC2820D9623BF429, 880, 284 },
+ { 0x80444B5E7AA7CF85, 907, 292 },
+ { 0xBF21E44003ACDD2D, 933, 300 },
+ { 0x8E679C2F5E44FF8F, 960, 308 },
+ { 0xD433179D9C8CB841, 986, 316 },
+ { 0x9E19DB92B4E31BA9, 1013, 324 },
+ }
+ };
+
+ // This computation gives exactly the same results for k as
+ // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
+ // for |e| <= 1500, but doesn't require floating-point operations.
+ // NB: log_10(2) ~= 78913 / 2^18
+ JSON_ASSERT(e >= -1500);
+ JSON_ASSERT(e <= 1500);
+ const int f = kAlpha - e - 1;
+ const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
+
+ const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
+ JSON_ASSERT(index >= 0);
+ JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
+
+ const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
+ JSON_ASSERT(kAlpha <= cached.e + e + 64);
+ JSON_ASSERT(kGamma >= cached.e + e + 64);
+
+ return cached;
+}
+
+/*!
+For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
+For n == 0, returns 1 and sets pow10 := 1.
+*/
+inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
+{
+ // LCOV_EXCL_START
+ if (n >= 1000000000)
+ {
+ pow10 = 1000000000;
+ return 10;
+ }
+ // LCOV_EXCL_STOP
+ if (n >= 100000000)
+ {
+ pow10 = 100000000;
+ return 9;
+ }
+ if (n >= 10000000)
+ {
+ pow10 = 10000000;
+ return 8;
+ }
+ if (n >= 1000000)
+ {
+ pow10 = 1000000;
+ return 7;
+ }
+ if (n >= 100000)
+ {
+ pow10 = 100000;
+ return 6;
+ }
+ if (n >= 10000)
+ {
+ pow10 = 10000;
+ return 5;
+ }
+ if (n >= 1000)
+ {
+ pow10 = 1000;
+ return 4;
+ }
+ if (n >= 100)
+ {
+ pow10 = 100;
+ return 3;
+ }
+ if (n >= 10)
+ {
+ pow10 = 10;
+ return 2;
+ }
+
+ pow10 = 1;
+ return 1;
+}
+
+inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
+ std::uint64_t rest, std::uint64_t ten_k)
+{
+ JSON_ASSERT(len >= 1);
+ JSON_ASSERT(dist <= delta);
+ JSON_ASSERT(rest <= delta);
+ JSON_ASSERT(ten_k > 0);
+
+ // <--------------------------- delta ---->
+ // <---- dist --------->
+ // --------------[------------------+-------------------]--------------
+ // M- w M+
+ //
+ // ten_k
+ // <------>
+ // <---- rest ---->
+ // --------------[------------------+----+--------------]--------------
+ // w V
+ // = buf * 10^k
+ //
+ // ten_k represents a unit-in-the-last-place in the decimal representation
+ // stored in buf.
+ // Decrement buf by ten_k while this takes buf closer to w.
+
+ // The tests are written in this order to avoid overflow in unsigned
+ // integer arithmetic.
+
+ while (rest < dist
+ && delta - rest >= ten_k
+ && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
+ {
+ JSON_ASSERT(buf[len - 1] != '0');
+ buf[len - 1]--;
+ rest += ten_k;
+ }
+}
+
+/*!
+Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
+M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
+*/
+inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
+ diyfp M_minus, diyfp w, diyfp M_plus)
+{
+ static_assert(kAlpha >= -60, "internal error");
+ static_assert(kGamma <= -32, "internal error");
+
+ // Generates the digits (and the exponent) of a decimal floating-point
+ // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
+ // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
+ //
+ // <--------------------------- delta ---->
+ // <---- dist --------->
+ // --------------[------------------+-------------------]--------------
+ // M- w M+
+ //
+ // Grisu2 generates the digits of M+ from left to right and stops as soon as
+ // V is in [M-,M+].
+
+ JSON_ASSERT(M_plus.e >= kAlpha);
+ JSON_ASSERT(M_plus.e <= kGamma);
+
+ std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
+ std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
+
+ // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
+ //
+ // M+ = f * 2^e
+ // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
+ // = ((p1 ) * 2^-e + (p2 )) * 2^e
+ // = p1 + p2 * 2^e
+
+ const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
+
+ auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
+ std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
+
+ // 1)
+ //
+ // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
+
+ JSON_ASSERT(p1 > 0);
+
+ std::uint32_t pow10{};
+ const int k = find_largest_pow10(p1, pow10);
+
+ // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
+ //
+ // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
+ // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
+ //
+ // M+ = p1 + p2 * 2^e
+ // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
+ // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
+ // = d[k-1] * 10^(k-1) + ( rest) * 2^e
+ //
+ // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
+ //
+ // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
+ //
+ // but stop as soon as
+ //
+ // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
+
+ int n = k;
+ while (n > 0)
+ {
+ // Invariants:
+ // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
+ // pow10 = 10^(n-1) <= p1 < 10^n
+ //
+ const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
+ const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
+ //
+ // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
+ // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
+ //
+ JSON_ASSERT(d <= 9);
+ buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+ //
+ // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
+ //
+ p1 = r;
+ n--;
+ //
+ // M+ = buffer * 10^n + (p1 + p2 * 2^e)
+ // pow10 = 10^n
+ //
+
+ // Now check if enough digits have been generated.
+ // Compute
+ //
+ // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
+ //
+ // Note:
+ // Since rest and delta share the same exponent e, it suffices to
+ // compare the significands.
+ const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
+ if (rest <= delta)
+ {
+ // V = buffer * 10^n, with M- <= V <= M+.
+
+ decimal_exponent += n;
+
+ // We may now just stop. But instead look if the buffer could be
+ // decremented to bring V closer to w.
+ //
+ // pow10 = 10^n is now 1 ulp in the decimal representation V.
+ // The rounding procedure works with diyfp's with an implicit
+ // exponent of e.
+ //
+ // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
+ //
+ const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
+ grisu2_round(buffer, length, dist, delta, rest, ten_n);
+
+ return;
+ }
+
+ pow10 /= 10;
+ //
+ // pow10 = 10^(n-1) <= p1 < 10^n
+ // Invariants restored.
+ }
+
+ // 2)
+ //
+ // The digits of the integral part have been generated:
+ //
+ // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
+ // = buffer + p2 * 2^e
+ //
+ // Now generate the digits of the fractional part p2 * 2^e.
+ //
+ // Note:
+ // No decimal point is generated: the exponent is adjusted instead.
+ //
+ // p2 actually represents the fraction
+ //
+ // p2 * 2^e
+ // = p2 / 2^-e
+ // = d[-1] / 10^1 + d[-2] / 10^2 + ...
+ //
+ // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
+ //
+ // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
+ // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
+ //
+ // using
+ //
+ // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
+ // = ( d) * 2^-e + ( r)
+ //
+ // or
+ // 10^m * p2 * 2^e = d + r * 2^e
+ //
+ // i.e.
+ //
+ // M+ = buffer + p2 * 2^e
+ // = buffer + 10^-m * (d + r * 2^e)
+ // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
+ //
+ // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
+
+ JSON_ASSERT(p2 > delta);
+
+ int m = 0;
+ for (;;)
+ {
+ // Invariant:
+ // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
+ // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
+ // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
+ // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
+ //
+ JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
+ p2 *= 10;
+ const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
+ const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
+ //
+ // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
+ // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
+ // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
+ //
+ JSON_ASSERT(d <= 9);
+ buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
+ //
+ // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
+ //
+ p2 = r;
+ m++;
+ //
+ // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
+ // Invariant restored.
+
+ // Check if enough digits have been generated.
+ //
+ // 10^-m * p2 * 2^e <= delta * 2^e
+ // p2 * 2^e <= 10^m * delta * 2^e
+ // p2 <= 10^m * delta
+ delta *= 10;
+ dist *= 10;
+ if (p2 <= delta)
+ {
+ break;
+ }
+ }
+
+ // V = buffer * 10^-m, with M- <= V <= M+.
+
+ decimal_exponent -= m;
+
+ // 1 ulp in the decimal representation is now 10^-m.
+ // Since delta and dist are now scaled by 10^m, we need to do the
+ // same with ulp in order to keep the units in sync.
+ //
+ // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
+ //
+ const std::uint64_t ten_m = one.f;
+ grisu2_round(buffer, length, dist, delta, p2, ten_m);
+
+ // By construction this algorithm generates the shortest possible decimal
+ // number (Loitsch, Theorem 6.2) which rounds back to w.
+ // For an input number of precision p, at least
+ //
+ // N = 1 + ceil(p * log_10(2))
+ //
+ // decimal digits are sufficient to identify all binary floating-point
+ // numbers (Matula, "In-and-Out conversions").
+ // This implies that the algorithm does not produce more than N decimal
+ // digits.
+ //
+ // N = 17 for p = 53 (IEEE double precision)
+ // N = 9 for p = 24 (IEEE single precision)
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline void grisu2(char* buf, int& len, int& decimal_exponent,
+ diyfp m_minus, diyfp v, diyfp m_plus)
+{
+ JSON_ASSERT(m_plus.e == m_minus.e);
+ JSON_ASSERT(m_plus.e == v.e);
+
+ // --------(-----------------------+-----------------------)-------- (A)
+ // m- v m+
+ //
+ // --------------------(-----------+-----------------------)-------- (B)
+ // m- v m+
+ //
+ // First scale v (and m- and m+) such that the exponent is in the range
+ // [alpha, gamma].
+
+ const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
+
+ const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
+
+ // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
+ const diyfp w = diyfp::mul(v, c_minus_k);
+ const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
+ const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
+
+ // ----(---+---)---------------(---+---)---------------(---+---)----
+ // w- w w+
+ // = c*m- = c*v = c*m+
+ //
+ // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
+ // w+ are now off by a small amount.
+ // In fact:
+ //
+ // w - v * 10^k < 1 ulp
+ //
+ // To account for this inaccuracy, add resp. subtract 1 ulp.
+ //
+ // --------+---[---------------(---+---)---------------]---+--------
+ // w- M- w M+ w+
+ //
+ // Now any number in [M-, M+] (bounds included) will round to w when input,
+ // regardless of how the input rounding algorithm breaks ties.
+ //
+ // And digit_gen generates the shortest possible such number in [M-, M+].
+ // Note that this does not mean that Grisu2 always generates the shortest
+ // possible number in the interval (m-, m+).
+ const diyfp M_minus(w_minus.f + 1, w_minus.e);
+ const diyfp M_plus (w_plus.f - 1, w_plus.e );
+
+ decimal_exponent = -cached.k; // = -(-k) = k
+
+ grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
+}
+
+/*!
+v = buf * 10^decimal_exponent
+len is the length of the buffer (number of decimal digits)
+The buffer must be large enough, i.e. >= max_digits10.
+*/
+template<typename FloatType>
+JSON_HEDLEY_NON_NULL(1)
+void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
+{
+ static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
+ "internal error: not enough precision");
+
+ JSON_ASSERT(std::isfinite(value));
+ JSON_ASSERT(value > 0);
+
+ // If the neighbors (and boundaries) of 'value' are always computed for double-precision
+ // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
+ // decimal representations are not exactly "short".
+ //
+ // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
+ // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
+ // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars'
+ // does.
+ // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
+ // representation using the corresponding std::from_chars function recovers value exactly". That
+ // indicates that single precision floating-point numbers should be recovered using
+ // 'std::strtof'.
+ //
+ // NB: If the neighbors are computed for single-precision numbers, there is a single float
+ // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
+ // value is off by 1 ulp.
+#if 0
+ const boundaries w = compute_boundaries(static_cast<double>(value));
+#else
+ const boundaries w = compute_boundaries(value);
+#endif
+
+ grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
+}
+
+/*!
+@brief appends a decimal representation of e to buf
+@return a pointer to the element following the exponent.
+@pre -1000 < e < 1000
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* append_exponent(char* buf, int e)
+{
+ JSON_ASSERT(e > -1000);
+ JSON_ASSERT(e < 1000);
+
+ if (e < 0)
+ {
+ e = -e;
+ *buf++ = '-';
+ }
+ else
+ {
+ *buf++ = '+';
+ }
+
+ auto k = static_cast<std::uint32_t>(e);
+ if (k < 10)
+ {
+ // Always print at least two digits in the exponent.
+ // This is for compatibility with printf("%g").
+ *buf++ = '0';
+ *buf++ = static_cast<char>('0' + k);
+ }
+ else if (k < 100)
+ {
+ *buf++ = static_cast<char>('0' + k / 10);
+ k %= 10;
+ *buf++ = static_cast<char>('0' + k);
+ }
+ else
+ {
+ *buf++ = static_cast<char>('0' + k / 100);
+ k %= 100;
+ *buf++ = static_cast<char>('0' + k / 10);
+ k %= 10;
+ *buf++ = static_cast<char>('0' + k);
+ }
+
+ return buf;
+}
+
+/*!
+@brief prettify v = buf * 10^decimal_exponent
+
+If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
+notation. Otherwise it will be printed in exponential notation.
+
+@pre min_exp < 0
+@pre max_exp > 0
+*/
+JSON_HEDLEY_NON_NULL(1)
+JSON_HEDLEY_RETURNS_NON_NULL
+inline char* format_buffer(char* buf, int len, int decimal_exponent,
+ int min_exp, int max_exp)
+{
+ JSON_ASSERT(min_exp < 0);
+ JSON_ASSERT(max_exp > 0);
+
+ const int k = len;
+ const int n = len + decimal_exponent;
+
+ // v = buf * 10^(n-k)
+ // k is the length of the buffer (number of decimal digits)
+ // n is the position of the decimal point relative to the start of the buffer.
+
+ if (k <= n && n <= max_exp)
+ {
+ // digits[000]
+ // len <= max_exp + 2
+
+ std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
+ // Make it look like a floating-point number (#362, #378)
+ buf[n + 0] = '.';
+ buf[n + 1] = '0';
+ return buf + (static_cast<size_t>(n) + 2);
+ }
+
+ if (0 < n && n <= max_exp)
+ {
+ // dig.its
+ // len <= max_digits10 + 1
+
+ JSON_ASSERT(k > n);
+
+ std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
+ buf[n] = '.';
+ return buf + (static_cast<size_t>(k) + 1U);
+ }
+
+ if (min_exp < n && n <= 0)
+ {
+ // 0.[000]digits
+ // len <= 2 + (-min_exp - 1) + max_digits10
+
+ std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
+ buf[0] = '0';
+ buf[1] = '.';
+ std::memset(buf + 2, '0', static_cast<size_t>(-n));
+ return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
+ }
+
+ if (k == 1)
+ {
+ // dE+123
+ // len <= 1 + 5
+
+ buf += 1;
+ }
+ else
+ {
+ // d.igitsE+123
+ // len <= max_digits10 + 1 + 5
+
+ std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
+ buf[1] = '.';
+ buf += 1 + static_cast<size_t>(k);
+ }
+
+ *buf++ = 'e';
+ return append_exponent(buf, n - 1);
+}
+
+} // namespace dtoa_impl
+
+/*!
+@brief generates a decimal representation of the floating-point number value in [first, last).
+
+The format of the resulting decimal representation is similar to printf's %g
+format. Returns an iterator pointing past-the-end of the decimal representation.
+
+@note The input number must be finite, i.e. NaN's and Inf's are not supported.
+@note The buffer must be large enough.
+@note The result is NOT null-terminated.
+*/
+template<typename FloatType>
+JSON_HEDLEY_NON_NULL(1, 2)
+JSON_HEDLEY_RETURNS_NON_NULL
+char* to_chars(char* first, const char* last, FloatType value)
+{
+ static_cast<void>(last); // maybe unused - fix warning
+ JSON_ASSERT(std::isfinite(value));
+
+ // Use signbit(value) instead of (value < 0) since signbit works for -0.
+ if (std::signbit(value))
+ {
+ value = -value;
+ *first++ = '-';
+ }
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ if (value == 0) // +-0
+ {
+ *first++ = '0';
+ // Make it look like a floating-point number (#362, #378)
+ *first++ = '.';
+ *first++ = '0';
+ return first;
+ }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+
+ JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
+
+ // Compute v = buffer * 10^decimal_exponent.
+ // The decimal digits are stored in the buffer, which needs to be interpreted
+ // as an unsigned decimal integer.
+ // len is the length of the buffer, i.e. the number of decimal digits.
+ int len = 0;
+ int decimal_exponent = 0;
+ dtoa_impl::grisu2(first, len, decimal_exponent, value);
+
+ JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
+
+ // Format the buffer like printf("%.*g", prec, value)
+ constexpr int kMinExp = -4;
+ // Use digits10 here to increase compatibility with version 2.
+ constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
+
+ JSON_ASSERT(last - first >= kMaxExp + 2);
+ JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
+ JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
+
+ return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
+}
+
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/exceptions.hpp>
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
+// #include <nlohmann/detail/output/binary_writer.hpp>
+
+// #include <nlohmann/detail/output/output_adapters.hpp>
+
+// #include <nlohmann/detail/value_t.hpp>
+
+
+namespace nlohmann
+{
+namespace detail
+{
+///////////////////
+// serialization //
+///////////////////
+
+/// how to treat decoding errors
+enum class error_handler_t
+{
+ strict, ///< throw a type_error exception in case of invalid UTF-8
+ replace, ///< replace invalid UTF-8 sequences with U+FFFD
+ ignore ///< ignore invalid UTF-8 sequences
+};
+
+template<typename BasicJsonType>
+class serializer
+{
+ using string_t = typename BasicJsonType::string_t;
+ using number_float_t = typename BasicJsonType::number_float_t;
+ using number_integer_t = typename BasicJsonType::number_integer_t;
+ using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using binary_char_t = typename BasicJsonType::binary_t::value_type;
+ static constexpr std::uint8_t UTF8_ACCEPT = 0;
+ static constexpr std::uint8_t UTF8_REJECT = 1;
+
+ public:
+ /*!
+ @param[in] s output stream to serialize to
+ @param[in] ichar indentation character to use
+ @param[in] error_handler_ how to react on decoding errors
+ */
+ serializer(output_adapter_t<char> s, const char ichar,
+ error_handler_t error_handler_ = error_handler_t::strict)
+ : o(std::move(s))
+ , loc(std::localeconv())
+ , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
+ , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
+ , indent_char(ichar)
+ , indent_string(512, indent_char)
+ , error_handler(error_handler_)
+ {}
+
+ // delete because of pointer members
+ serializer(const serializer&) = delete;
+ serializer& operator=(const serializer&) = delete;
+ serializer(serializer&&) = delete;
+ serializer& operator=(serializer&&) = delete;
+ ~serializer() = default;
+
+ /*!
+ @brief internal implementation of the serialization function
+
+ This function is called by the public member function dump and organizes
+ the serialization internally. The indentation level is propagated as
+ additional parameter. In case of arrays and objects, the function is
+ called recursively.
+
+ - strings and object keys are escaped using `escape_string()`
+ - integer numbers are converted implicitly via `operator<<`
+ - floating-point numbers are converted to a string using `"%g"` format
+ - binary values are serialized as objects containing the subtype and the
+ byte array
+
+ @param[in] val value to serialize
+ @param[in] pretty_print whether the output shall be pretty-printed
+ @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+ in the output are escaped with `\uXXXX` sequences, and the result consists
+ of ASCII characters only.
+ @param[in] indent_step the indent level
+ @param[in] current_indent the current indent level (only used internally)
+ */
+ void dump(const BasicJsonType& val,
+ const bool pretty_print,
+ const bool ensure_ascii,
+ const unsigned int indent_step,
+ const unsigned int current_indent = 0)
+ {
+ switch (val.m_type)
+ {
+ case value_t::object:
+ {
+ if (val.m_value.object->empty())
+ {
+ o->write_characters("{}", 2);
+ return;
+ }
+
+ if (pretty_print)
+ {
+ o->write_characters("{\n", 2);
+
+ // variable to hold indentation for recursive calls
+ const auto new_indent = current_indent + indent_step;
+ if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+ {
+ indent_string.resize(indent_string.size() * 2, ' ');
+ }
+
+ // first n-1 elements
+ auto i = val.m_value.object->cbegin();
+ for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+ {
+ o->write_characters(indent_string.c_str(), new_indent);
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\": ", 3);
+ dump(i->second, true, ensure_ascii, indent_step, new_indent);
+ o->write_characters(",\n", 2);
+ }
+
+ // last element
+ JSON_ASSERT(i != val.m_value.object->cend());
+ JSON_ASSERT(std::next(i) == val.m_value.object->cend());
+ o->write_characters(indent_string.c_str(), new_indent);
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\": ", 3);
+ dump(i->second, true, ensure_ascii, indent_step, new_indent);
+
+ o->write_character('\n');
+ o->write_characters(indent_string.c_str(), current_indent);
+ o->write_character('}');
+ }
+ else
+ {
+ o->write_character('{');
+
+ // first n-1 elements
+ auto i = val.m_value.object->cbegin();
+ for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
+ {
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\":", 2);
+ dump(i->second, false, ensure_ascii, indent_step, current_indent);
+ o->write_character(',');
+ }
+
+ // last element
+ JSON_ASSERT(i != val.m_value.object->cend());
+ JSON_ASSERT(std::next(i) == val.m_value.object->cend());
+ o->write_character('\"');
+ dump_escaped(i->first, ensure_ascii);
+ o->write_characters("\":", 2);
+ dump(i->second, false, ensure_ascii, indent_step, current_indent);
+
+ o->write_character('}');
+ }
+
+ return;
+ }
+
+ case value_t::array:
+ {
+ if (val.m_value.array->empty())
+ {
+ o->write_characters("[]", 2);
+ return;
+ }
+
+ if (pretty_print)
+ {
+ o->write_characters("[\n", 2);
+
+ // variable to hold indentation for recursive calls
+ const auto new_indent = current_indent + indent_step;
+ if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+ {
+ indent_string.resize(indent_string.size() * 2, ' ');
+ }
+
+ // first n-1 elements
+ for (auto i = val.m_value.array->cbegin();
+ i != val.m_value.array->cend() - 1; ++i)
+ {
+ o->write_characters(indent_string.c_str(), new_indent);
+ dump(*i, true, ensure_ascii, indent_step, new_indent);
+ o->write_characters(",\n", 2);
+ }
+
+ // last element
+ JSON_ASSERT(!val.m_value.array->empty());
+ o->write_characters(indent_string.c_str(), new_indent);
+ dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
+
+ o->write_character('\n');
+ o->write_characters(indent_string.c_str(), current_indent);
+ o->write_character(']');
+ }
+ else
+ {
+ o->write_character('[');
+
+ // first n-1 elements
+ for (auto i = val.m_value.array->cbegin();
+ i != val.m_value.array->cend() - 1; ++i)
+ {
+ dump(*i, false, ensure_ascii, indent_step, current_indent);
+ o->write_character(',');
+ }
+
+ // last element
+ JSON_ASSERT(!val.m_value.array->empty());
+ dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
+
+ o->write_character(']');
+ }
+
+ return;
+ }
+
+ case value_t::string:
+ {
+ o->write_character('\"');
+ dump_escaped(*val.m_value.string, ensure_ascii);
+ o->write_character('\"');
+ return;
+ }
+
+ case value_t::binary:
+ {
+ if (pretty_print)
+ {
+ o->write_characters("{\n", 2);
+
+ // variable to hold indentation for recursive calls
+ const auto new_indent = current_indent + indent_step;
+ if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
+ {
+ indent_string.resize(indent_string.size() * 2, ' ');
+ }
+
+ o->write_characters(indent_string.c_str(), new_indent);
+
+ o->write_characters("\"bytes\": [", 10);
+
+ if (!val.m_value.binary->empty())
+ {
+ for (auto i = val.m_value.binary->cbegin();
+ i != val.m_value.binary->cend() - 1; ++i)
+ {
+ dump_integer(*i);
+ o->write_characters(", ", 2);
+ }
+ dump_integer(val.m_value.binary->back());
+ }
+
+ o->write_characters("],\n", 3);
+ o->write_characters(indent_string.c_str(), new_indent);
+
+ o->write_characters("\"subtype\": ", 11);
+ if (val.m_value.binary->has_subtype())
+ {
+ dump_integer(val.m_value.binary->subtype());
+ }
+ else
+ {
+ o->write_characters("null", 4);
+ }
+ o->write_character('\n');
+ o->write_characters(indent_string.c_str(), current_indent);
+ o->write_character('}');
+ }
+ else
+ {
+ o->write_characters("{\"bytes\":[", 10);
+
+ if (!val.m_value.binary->empty())
+ {
+ for (auto i = val.m_value.binary->cbegin();
+ i != val.m_value.binary->cend() - 1; ++i)
+ {
+ dump_integer(*i);
+ o->write_character(',');
+ }
+ dump_integer(val.m_value.binary->back());
+ }
+
+ o->write_characters("],\"subtype\":", 12);
+ if (val.m_value.binary->has_subtype())
+ {
+ dump_integer(val.m_value.binary->subtype());
+ o->write_character('}');
+ }
+ else
+ {
+ o->write_characters("null}", 5);
+ }
+ }
+ return;
+ }
+
+ case value_t::boolean:
+ {
+ if (val.m_value.boolean)
+ {
+ o->write_characters("true", 4);
+ }
+ else
+ {
+ o->write_characters("false", 5);
+ }
+ return;
+ }
+
+ case value_t::number_integer:
+ {
+ dump_integer(val.m_value.number_integer);
+ return;
+ }
+
+ case value_t::number_unsigned:
+ {
+ dump_integer(val.m_value.number_unsigned);
+ return;
+ }
+
+ case value_t::number_float:
+ {
+ dump_float(val.m_value.number_float);
+ return;
+ }
+
+ case value_t::discarded:
+ {
+ o->write_characters("<discarded>", 11);
+ return;
+ }
+
+ case value_t::null:
+ {
+ o->write_characters("null", 4);
+ return;
+ }
+
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+ }
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ /*!
+ @brief dump escaped string
+
+ Escape a string by replacing certain special characters by a sequence of an
+ escape character (backslash) and another character and other control
+ characters by a sequence of "\u" followed by a four-digit hex
+ representation. The escaped string is written to output stream @a o.
+
+ @param[in] s the string to escape
+ @param[in] ensure_ascii whether to escape non-ASCII characters with
+ \uXXXX sequences
+
+ @complexity Linear in the length of string @a s.
+ */
+ void dump_escaped(const string_t& s, const bool ensure_ascii)
+ {
+ std::uint32_t codepoint{};
+ std::uint8_t state = UTF8_ACCEPT;
+ std::size_t bytes = 0; // number of bytes written to string_buffer
+
+ // number of bytes written at the point of the last valid byte
+ std::size_t bytes_after_last_accept = 0;
+ std::size_t undumped_chars = 0;
+
+ for (std::size_t i = 0; i < s.size(); ++i)
+ {
+ const auto byte = static_cast<std::uint8_t>(s[i]);
+
+ switch (decode(state, codepoint, byte))
+ {
+ case UTF8_ACCEPT: // decode found a new code point
+ {
+ switch (codepoint)
+ {
+ case 0x08: // backspace
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = 'b';
+ break;
+ }
+
+ case 0x09: // horizontal tab
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = 't';
+ break;
+ }
+
+ case 0x0A: // newline
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = 'n';
+ break;
+ }
+
+ case 0x0C: // formfeed
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = 'f';
+ break;
+ }
+
+ case 0x0D: // carriage return
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = 'r';
+ break;
+ }
+
+ case 0x22: // quotation mark
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = '\"';
+ break;
+ }
+
+ case 0x5C: // reverse solidus
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = '\\';
+ break;
+ }
+
+ default:
+ {
+ // escape control characters (0x00..0x1F) or, if
+ // ensure_ascii parameter is used, non-ASCII characters
+ if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
+ {
+ if (codepoint <= 0xFFFF)
+ {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
+ static_cast<std::uint16_t>(codepoint));
+ bytes += 6;
+ }
+ else
+ {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
+ static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
+ static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
+ bytes += 12;
+ }
+ }
+ else
+ {
+ // copy byte to buffer (all previous bytes
+ // been copied have in default case above)
+ string_buffer[bytes++] = s[i];
+ }
+ break;
+ }
+ }
+
+ // write buffer and reset index; there must be 13 bytes
+ // left, as this is the maximal number of bytes to be
+ // written ("\uxxxx\uxxxx\0") for one code point
+ if (string_buffer.size() - bytes < 13)
+ {
+ o->write_characters(string_buffer.data(), bytes);
+ bytes = 0;
+ }
+
+ // remember the byte position of this accept
+ bytes_after_last_accept = bytes;
+ undumped_chars = 0;
+ break;
+ }
+
+ case UTF8_REJECT: // decode found invalid UTF-8 byte
+ {
+ switch (error_handler)
+ {
+ case error_handler_t::strict:
+ {
+ std::stringstream ss;
+ ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (byte | 0);
+ JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str(), BasicJsonType()));
+ }
+
+ case error_handler_t::ignore:
+ case error_handler_t::replace:
+ {
+ // in case we saw this character the first time, we
+ // would like to read it again, because the byte
+ // may be OK for itself, but just not OK for the
+ // previous sequence
+ if (undumped_chars > 0)
+ {
+ --i;
+ }
+
+ // reset length buffer to the last accepted index;
+ // thus removing/ignoring the invalid characters
+ bytes = bytes_after_last_accept;
+
+ if (error_handler == error_handler_t::replace)
+ {
+ // add a replacement character
+ if (ensure_ascii)
+ {
+ string_buffer[bytes++] = '\\';
+ string_buffer[bytes++] = 'u';
+ string_buffer[bytes++] = 'f';
+ string_buffer[bytes++] = 'f';
+ string_buffer[bytes++] = 'f';
+ string_buffer[bytes++] = 'd';
+ }
+ else
+ {
+ string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
+ string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
+ string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
+ }
+
+ // write buffer and reset index; there must be 13 bytes
+ // left, as this is the maximal number of bytes to be
+ // written ("\uxxxx\uxxxx\0") for one code point
+ if (string_buffer.size() - bytes < 13)
+ {
+ o->write_characters(string_buffer.data(), bytes);
+ bytes = 0;
+ }
+
+ bytes_after_last_accept = bytes;
+ }
+
+ undumped_chars = 0;
+
+ // continue processing the string
+ state = UTF8_ACCEPT;
+ break;
+ }
+
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+ break;
+ }
+
+ default: // decode found yet incomplete multi-byte code point
+ {
+ if (!ensure_ascii)
+ {
+ // code point will not be escaped - copy byte to buffer
+ string_buffer[bytes++] = s[i];
+ }
+ ++undumped_chars;
+ break;
+ }
+ }
+ }
+
+ // we finished processing the string
+ if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
+ {
+ // write buffer
+ if (bytes > 0)
+ {
+ o->write_characters(string_buffer.data(), bytes);
+ }
+ }
+ else
+ {
+ // we finish reading, but do not accept: string was incomplete
+ switch (error_handler)
+ {
+ case error_handler_t::strict:
+ {
+ std::stringstream ss;
+ ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (static_cast<std::uint8_t>(s.back()) | 0);
+ JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str(), BasicJsonType()));
+ }
+
+ case error_handler_t::ignore:
+ {
+ // write all accepted bytes
+ o->write_characters(string_buffer.data(), bytes_after_last_accept);
+ break;
+ }
+
+ case error_handler_t::replace:
+ {
+ // write all accepted bytes
+ o->write_characters(string_buffer.data(), bytes_after_last_accept);
+ // add a replacement character
+ if (ensure_ascii)
+ {
+ o->write_characters("\\ufffd", 6);
+ }
+ else
+ {
+ o->write_characters("\xEF\xBF\xBD", 3);
+ }
+ break;
+ }
+
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+ }
+ }
+
+ private:
+ /*!
+ @brief count digits
+
+ Count the number of decimal (base 10) digits for an input unsigned integer.
+
+ @param[in] x unsigned integer number to count its digits
+ @return number of decimal digits
+ */
+ inline unsigned int count_digits(number_unsigned_t x) noexcept
+ {
+ unsigned int n_digits = 1;
+ for (;;)
+ {
+ if (x < 10)
+ {
+ return n_digits;
+ }
+ if (x < 100)
+ {
+ return n_digits + 1;
+ }
+ if (x < 1000)
+ {
+ return n_digits + 2;
+ }
+ if (x < 10000)
+ {
+ return n_digits + 3;
+ }
+ x = x / 10000u;
+ n_digits += 4;
+ }
+ }
+
+ /*!
+ @brief dump an integer
+
+ Dump a given integer to output stream @a o. Works internally with
+ @a number_buffer.
+
+ @param[in] x integer number (signed or unsigned) to dump
+ @tparam NumberType either @a number_integer_t or @a number_unsigned_t
+ */
+ template < typename NumberType, detail::enable_if_t <
+ std::is_integral<NumberType>::value ||
+ std::is_same<NumberType, number_unsigned_t>::value ||
+ std::is_same<NumberType, number_integer_t>::value ||
+ std::is_same<NumberType, binary_char_t>::value,
+ int > = 0 >
+ void dump_integer(NumberType x)
+ {
+ static constexpr std::array<std::array<char, 2>, 100> digits_to_99
+ {
+ {
+ {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
+ {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
+ {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
+ {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
+ {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
+ {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
+ {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
+ {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
+ {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
+ {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
+ }
+ };
+
+ // special case for "0"
+ if (x == 0)
+ {
+ o->write_character('0');
+ return;
+ }
+
+ // use a pointer to fill the buffer
+ auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+
+ const bool is_negative = std::is_signed<NumberType>::value && !(x >= 0); // see issue #755
+ number_unsigned_t abs_value;
+
+ unsigned int n_chars{};
+
+ if (is_negative)
+ {
+ *buffer_ptr = '-';
+ abs_value = remove_sign(static_cast<number_integer_t>(x));
+
+ // account one more byte for the minus sign
+ n_chars = 1 + count_digits(abs_value);
+ }
+ else
+ {
+ abs_value = static_cast<number_unsigned_t>(x);
+ n_chars = count_digits(abs_value);
+ }
+
+ // spare 1 byte for '\0'
+ JSON_ASSERT(n_chars < number_buffer.size() - 1);
+
+ // jump to the end to generate the string from backward
+ // so we later avoid reversing the result
+ buffer_ptr += n_chars;
+
+ // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
+ // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
+ while (abs_value >= 100)
+ {
+ const auto digits_index = static_cast<unsigned>((abs_value % 100));
+ abs_value /= 100;
+ *(--buffer_ptr) = digits_to_99[digits_index][1];
+ *(--buffer_ptr) = digits_to_99[digits_index][0];
+ }
+
+ if (abs_value >= 10)
+ {
+ const auto digits_index = static_cast<unsigned>(abs_value);
+ *(--buffer_ptr) = digits_to_99[digits_index][1];
+ *(--buffer_ptr) = digits_to_99[digits_index][0];
+ }
+ else
+ {
+ *(--buffer_ptr) = static_cast<char>('0' + abs_value);
+ }
+
+ o->write_characters(number_buffer.data(), n_chars);
+ }
+
+ /*!
+ @brief dump a floating-point number
+
+ Dump a given floating-point number to output stream @a o. Works internally
+ with @a number_buffer.
+
+ @param[in] x floating-point number to dump
+ */
+ void dump_float(number_float_t x)
+ {
+ // NaN / inf
+ if (!std::isfinite(x))
+ {
+ o->write_characters("null", 4);
+ return;
+ }
+
+ // If number_float_t is an IEEE-754 single or double precision number,
+ // use the Grisu2 algorithm to produce short numbers which are
+ // guaranteed to round-trip, using strtof and strtod, resp.
+ //
+ // NB: The test below works if <long double> == <double>.
+ static constexpr bool is_ieee_single_or_double
+ = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
+ (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
+
+ dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
+ }
+
+ void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
+ {
+ auto* begin = number_buffer.data();
+ auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
+
+ o->write_characters(begin, static_cast<size_t>(end - begin));
+ }
+
+ void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
+ {
+ // get number of digits for a float -> text -> float round-trip
+ static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
+
+ // the actual conversion
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
+ std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
+
+ // negative value indicates an error
+ JSON_ASSERT(len > 0);
+ // check if buffer was large enough
+ JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
+
+ // erase thousands separator
+ if (thousands_sep != '\0')
+ {
+ // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
+ const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
+ std::fill(end, number_buffer.end(), '\0');
+ JSON_ASSERT((end - number_buffer.begin()) <= len);
+ len = (end - number_buffer.begin());
+ }
+
+ // convert decimal point to '.'
+ if (decimal_point != '\0' && decimal_point != '.')
+ {
+ // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
+ const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
+ if (dec_pos != number_buffer.end())
+ {
+ *dec_pos = '.';
+ }
+ }
+
+ o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
+
+ // determine if need to append ".0"
+ const bool value_is_int_like =
+ std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
+ [](char c)
+ {
+ return c == '.' || c == 'e';
+ });
+
+ if (value_is_int_like)
+ {
+ o->write_characters(".0", 2);
+ }
+ }
+
+ /*!
+ @brief check whether a string is UTF-8 encoded
+
+ The function checks each byte of a string whether it is UTF-8 encoded. The
+ result of the check is stored in the @a state parameter. The function must
+ be called initially with state 0 (accept). State 1 means the string must
+ be rejected, because the current byte is not allowed. If the string is
+ completely processed, but the state is non-zero, the string ended
+ prematurely; that is, the last byte indicated more bytes should have
+ followed.
+
+ @param[in,out] state the state of the decoding
+ @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT)
+ @param[in] byte next byte to decode
+ @return new state
+
+ @note The function has been edited: a std::array is used.
+
+ @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
+ @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+ */
+ static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
+ {
+ static const std::array<std::uint8_t, 400> utf8d =
+ {
+ {
+ 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, // 00..1F
+ 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, // 20..3F
+ 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, // 40..5F
+ 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, // 60..7F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
+ 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
+ 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
+ 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
+ 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
+ 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
+ 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
+ 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
+ }
+ };
+
+ JSON_ASSERT(byte < utf8d.size());
+ const std::uint8_t type = utf8d[byte];
+
+ codep = (state != UTF8_ACCEPT)
+ ? (byte & 0x3fu) | (codep << 6u)
+ : (0xFFu >> type) & (byte);
+
+ std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
+ JSON_ASSERT(index < 400);
+ state = utf8d[index];
+ return state;
+ }
+
+ /*
+ * Overload to make the compiler happy while it is instantiating
+ * dump_integer for number_unsigned_t.
+ * Must never be called.
+ */
+ number_unsigned_t remove_sign(number_unsigned_t x)
+ {
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ return x; // LCOV_EXCL_LINE
+ }
+
+ /*
+ * Helper function for dump_integer
+ *
+ * This function takes a negative signed integer and returns its absolute
+ * value as unsigned integer. The plus/minus shuffling is necessary as we can
+ * not directly remove the sign of an arbitrary signed integer as the
+ * absolute values of INT_MIN and INT_MAX are usually not the same. See
+ * #1708 for details.
+ */
+ inline number_unsigned_t remove_sign(number_integer_t x) noexcept
+ {
+ JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
+ return static_cast<number_unsigned_t>(-(x + 1)) + 1;
+ }
+
+ private:
+ /// the output of the serializer
+ output_adapter_t<char> o = nullptr;
+
+ /// a (hopefully) large enough character buffer
+ std::array<char, 64> number_buffer{{}};
+
+ /// the locale
+ const std::lconv* loc = nullptr;
+ /// the locale's thousand separator character
+ const char thousands_sep = '\0';
+ /// the locale's decimal point character
+ const char decimal_point = '\0';
+
+ /// string buffer
+ std::array<char, 512> string_buffer{{}};
+
+ /// the indentation character
+ const char indent_char;
+ /// the indentation string
+ string_t indent_string;
+
+ /// error_handler how to react on decoding errors
+ const error_handler_t error_handler;
+};
+} // namespace detail
+} // namespace nlohmann
+
+// #include <nlohmann/detail/value_t.hpp>
+
+// #include <nlohmann/json_fwd.hpp>
+
+// #include <nlohmann/ordered_map.hpp>
+
+
+#include <functional> // less
+#include <initializer_list> // initializer_list
+#include <iterator> // input_iterator_tag, iterator_traits
+#include <memory> // allocator
+#include <stdexcept> // for out_of_range
+#include <type_traits> // enable_if, is_convertible
+#include <utility> // pair
+#include <vector> // vector
+
+// #include <nlohmann/detail/macro_scope.hpp>
+
+
+namespace nlohmann
+{
+
+/// ordered_map: a minimal map-like container that preserves insertion order
+/// for use within nlohmann::basic_json<ordered_map>
+template <class Key, class T, class IgnoredLess = std::less<Key>,
+ class Allocator = std::allocator<std::pair<const Key, T>>>
+ struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
+{
+ using key_type = Key;
+ using mapped_type = T;
+ using Container = std::vector<std::pair<const Key, T>, Allocator>;
+ using typename Container::iterator;
+ using typename Container::const_iterator;
+ using typename Container::size_type;
+ using typename Container::value_type;
+
+ // Explicit constructors instead of `using Container::Container`
+ // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
+ ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {}
+ template <class It>
+ ordered_map(It first, It last, const Allocator& alloc = Allocator())
+ : Container{first, last, alloc} {}
+ ordered_map(std::initializer_list<T> init, const Allocator& alloc = Allocator() )
+ : Container{init, alloc} {}
+
+ std::pair<iterator, bool> emplace(const key_type& key, T&& t)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ return {it, false};
+ }
+ }
+ Container::emplace_back(key, t);
+ return {--this->end(), true};
+ }
+
+ T& operator[](const Key& key)
+ {
+ return emplace(key, T{}).first->second;
+ }
+
+ const T& operator[](const Key& key) const
+ {
+ return at(key);
+ }
+
+ T& at(const Key& key)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ return it->second;
+ }
+ }
+
+ JSON_THROW(std::out_of_range("key not found"));
+ }
+
+ const T& at(const Key& key) const
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ return it->second;
+ }
+ }
+
+ JSON_THROW(std::out_of_range("key not found"));
+ }
+
+ size_type erase(const Key& key)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ // Since we cannot move const Keys, re-construct them in place
+ for (auto next = it; ++next != this->end(); ++it)
+ {
+ it->~value_type(); // Destroy but keep allocation
+ new (&*it) value_type{std::move(*next)};
+ }
+ Container::pop_back();
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ iterator erase(iterator pos)
+ {
+ return erase(pos, std::next(pos));
+ }
+
+ iterator erase(iterator first, iterator last)
+ {
+ const auto elements_affected = std::distance(first, last);
+ const auto offset = std::distance(Container::begin(), first);
+
+ // This is the start situation. We need to delete elements_affected
+ // elements (3 in this example: e, f, g), and need to return an
+ // iterator past the last deleted element (h in this example).
+ // Note that offset is the distance from the start of the vector
+ // to first. We will need this later.
+
+ // [ a, b, c, d, e, f, g, h, i, j ]
+ // ^ ^
+ // first last
+
+ // Since we cannot move const Keys, we re-construct them in place.
+ // We start at first and re-construct (viz. copy) the elements from
+ // the back of the vector. Example for first iteration:
+
+ // ,--------.
+ // v | destroy e and re-construct with h
+ // [ a, b, c, d, e, f, g, h, i, j ]
+ // ^ ^
+ // it it + elements_affected
+
+ for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
+ {
+ it->~value_type(); // destroy but keep allocation
+ new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
+ }
+
+ // [ a, b, c, d, h, i, j, h, i, j ]
+ // ^ ^
+ // first last
+
+ // remove the unneeded elements at the end of the vector
+ Container::resize(this->size() - static_cast<size_type>(elements_affected));
+
+ // [ a, b, c, d, h, i, j ]
+ // ^ ^
+ // first last
+
+ // first is now pointing past the last deleted element, but we cannot
+ // use this iterator, because it may have been invalidated by the
+ // resize call. Instead, we can return begin() + offset.
+ return Container::begin() + offset;
+ }
+
+ size_type count(const Key& key) const
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ iterator find(const Key& key)
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ return it;
+ }
+ }
+ return Container::end();
+ }
+
+ const_iterator find(const Key& key) const
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == key)
+ {
+ return it;
+ }
+ }
+ return Container::end();
+ }
+
+ std::pair<iterator, bool> insert( value_type&& value )
+ {
+ return emplace(value.first, std::move(value.second));
+ }
+
+ std::pair<iterator, bool> insert( const value_type& value )
+ {
+ for (auto it = this->begin(); it != this->end(); ++it)
+ {
+ if (it->first == value.first)
+ {
+ return {it, false};
+ }
+ }
+ Container::push_back(value);
+ return {--this->end(), true};
+ }
+
+ template<typename InputIt>
+ using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
+ std::input_iterator_tag>::value>::type;
+
+ template<typename InputIt, typename = require_input_iter<InputIt>>
+ void insert(InputIt first, InputIt last)
+ {
+ for (auto it = first; it != last; ++it)
+ {
+ insert(*it);
+ }
+ }
+};
+
+} // namespace nlohmann
+
+
+#if defined(JSON_HAS_CPP_17)
+ #include <string_view>
+#endif
+
+/*!
+@brief namespace for Niels Lohmann
+@see https://github.com/nlohmann
+@since version 1.0.0
+*/
+namespace nlohmann
+{
+
+/*!
+@brief a class to store JSON values
+
+@tparam ObjectType type for JSON objects (`std::map` by default; will be used
+in @ref object_t)
+@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used
+in @ref array_t)
+@tparam StringType type for JSON strings and object keys (`std::string` by
+default; will be used in @ref string_t)
+@tparam BooleanType type for JSON booleans (`bool` by default; will be used
+in @ref boolean_t)
+@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by
+default; will be used in @ref number_integer_t)
+@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c
+`uint64_t` by default; will be used in @ref number_unsigned_t)
+@tparam NumberFloatType type for JSON floating-point numbers (`double` by
+default; will be used in @ref number_float_t)
+@tparam BinaryType type for packed binary data for compatibility with binary
+serialization formats (`std::vector<std::uint8_t>` by default; will be used in
+@ref binary_t)
+@tparam AllocatorType type of the allocator to use (`std::allocator` by
+default)
+@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
+and `from_json()` (@ref adl_serializer by default)
+
+@requirement The class satisfies the following concept requirements:
+- Basic
+ - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible):
+ JSON values can be default constructed. The result will be a JSON null
+ value.
+ - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible):
+ A JSON value can be constructed from an rvalue argument.
+ - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible):
+ A JSON value can be copy-constructed from an lvalue expression.
+ - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable):
+ A JSON value van be assigned from an rvalue argument.
+ - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable):
+ A JSON value can be copy-assigned from an lvalue expression.
+ - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible):
+ JSON values can be destructed.
+- Layout
+ - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType):
+ JSON values have
+ [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout):
+ All non-static data members are private and standard layout types, the
+ class has no virtual functions or (virtual) base classes.
+- Library-wide
+ - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable):
+ JSON values can be compared with `==`, see @ref
+ operator==(const_reference,const_reference).
+ - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable):
+ JSON values can be compared with `<`, see @ref
+ operator<(const_reference,const_reference).
+ - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable):
+ Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of
+ other compatible types, using unqualified function call @ref swap().
+ - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer):
+ JSON values can be compared against `std::nullptr_t` objects which are used
+ to model the `null` value.
+- Container
+ - [Container](https://en.cppreference.com/w/cpp/named_req/Container):
+ JSON values can be used like STL containers and provide iterator access.
+ - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer);
+ JSON values can be used like STL containers and provide reverse iterator
+ access.
+
+@invariant The member variables @a m_value and @a m_type have the following
+relationship:
+- If `m_type == value_t::object`, then `m_value.object != nullptr`.
+- If `m_type == value_t::array`, then `m_value.array != nullptr`.
+- If `m_type == value_t::string`, then `m_value.string != nullptr`.
+The invariants are checked by member function assert_invariant().
+
+@internal
+@note ObjectType trick from https://stackoverflow.com/a/9860911
+@endinternal
+
+@see [RFC 8259: The JavaScript Object Notation (JSON) Data Interchange
+Format](https://tools.ietf.org/html/rfc8259)
+
+@since version 1.0.0
+
+@nosubgrouping
+*/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
+{
+ private:
+ template<detail::value_t> friend struct detail::external_constructor;
+ friend ::nlohmann::json_pointer<basic_json>;
+
+ template<typename BasicJsonType, typename InputType>
+ friend class ::nlohmann::detail::parser;
+ friend ::nlohmann::detail::serializer<basic_json>;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::iter_impl;
+ template<typename BasicJsonType, typename CharType>
+ friend class ::nlohmann::detail::binary_writer;
+ template<typename BasicJsonType, typename InputType, typename SAX>
+ friend class ::nlohmann::detail::binary_reader;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::json_sax_dom_parser;
+ template<typename BasicJsonType>
+ friend class ::nlohmann::detail::json_sax_dom_callback_parser;
+ friend class ::nlohmann::detail::exception;
+
+ /// workaround type for MSVC
+ using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ // convenience aliases for types residing in namespace detail;
+ using lexer = ::nlohmann::detail::lexer_base<basic_json>;
+
+ template<typename InputAdapterType>
+ static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
+ InputAdapterType adapter,
+ detail::parser_callback_t<basic_json>cb = nullptr,
+ const bool allow_exceptions = true,
+ const bool ignore_comments = false
+ )
+ {
+ return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
+ std::move(cb), allow_exceptions, ignore_comments);
+ }
+
+ private:
+ using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
+ template<typename BasicJsonType>
+ using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
+ template<typename BasicJsonType>
+ using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
+ template<typename Iterator>
+ using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
+ template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
+
+ template<typename CharType>
+ using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
+
+ template<typename InputType>
+ using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
+ template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ using serializer = ::nlohmann::detail::serializer<basic_json>;
+
+ public:
+ using value_t = detail::value_t;
+ /// JSON Pointer, see @ref nlohmann::json_pointer
+ using json_pointer = ::nlohmann::json_pointer<basic_json>;
+ template<typename T, typename SFINAE>
+ using json_serializer = JSONSerializer<T, SFINAE>;
+ /// how to treat decoding errors
+ using error_handler_t = detail::error_handler_t;
+ /// how to treat CBOR tags
+ using cbor_tag_handler_t = detail::cbor_tag_handler_t;
+ /// helper type for initializer lists of basic_json values
+ using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
+
+ using input_format_t = detail::input_format_t;
+ /// SAX interface type, see @ref nlohmann::json_sax
+ using json_sax_t = json_sax<basic_json>;
+
+ ////////////////
+ // exceptions //
+ ////////////////
+
+ /// @name exceptions
+ /// Classes to implement user-defined exceptions.
+ /// @{
+
+ /// @copydoc detail::exception
+ using exception = detail::exception;
+ /// @copydoc detail::parse_error
+ using parse_error = detail::parse_error;
+ /// @copydoc detail::invalid_iterator
+ using invalid_iterator = detail::invalid_iterator;
+ /// @copydoc detail::type_error
+ using type_error = detail::type_error;
+ /// @copydoc detail::out_of_range
+ using out_of_range = detail::out_of_range;
+ /// @copydoc detail::other_error
+ using other_error = detail::other_error;
+
+ /// @}
+
+
+ /////////////////////
+ // container types //
+ /////////////////////
+
+ /// @name container types
+ /// The canonic container types to use @ref basic_json like any other STL
+ /// container.
+ /// @{
+
+ /// the type of elements in a basic_json container
+ using value_type = basic_json;
+
+ /// the type of an element reference
+ using reference = value_type&;
+ /// the type of an element const reference
+ using const_reference = const value_type&;
+
+ /// a type to represent differences between iterators
+ using difference_type = std::ptrdiff_t;
+ /// a type to represent container sizes
+ using size_type = std::size_t;
+
+ /// the allocator type
+ using allocator_type = AllocatorType<basic_json>;
+
+ /// the type of an element pointer
+ using pointer = typename std::allocator_traits<allocator_type>::pointer;
+ /// the type of an element const pointer
+ using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
+
+ /// an iterator for a basic_json container
+ using iterator = iter_impl<basic_json>;
+ /// a const iterator for a basic_json container
+ using const_iterator = iter_impl<const basic_json>;
+ /// a reverse iterator for a basic_json container
+ using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
+ /// a const reverse iterator for a basic_json container
+ using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
+
+ /// @}
+
+
+ /*!
+ @brief returns the allocator associated with the container
+ */
+ static allocator_type get_allocator()
+ {
+ return allocator_type();
+ }
+
+ /*!
+ @brief returns version information on the library
+
+ This function returns a JSON object with information about the library,
+ including the version number and information on the platform and compiler.
+
+ @return JSON object holding version information
+ key | description
+ ----------- | ---------------
+ `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version).
+ `copyright` | The copyright line for the library as string.
+ `name` | The name of the library as string.
+ `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`.
+ `url` | The URL of the project as string.
+ `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string).
+
+ @liveexample{The following code shows an example output of the `meta()`
+ function.,meta}
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @complexity Constant.
+
+ @since 2.1.0
+ */
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json meta()
+ {
+ basic_json result;
+
+ result["copyright"] = "(C) 2013-2021 Niels Lohmann";
+ result["name"] = "JSON for Modern C++";
+ result["url"] = "https://github.com/nlohmann/json";
+ result["version"]["string"] =
+ std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." +
+ std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." +
+ std::to_string(NLOHMANN_JSON_VERSION_PATCH);
+ result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
+ result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
+ result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
+
+#ifdef _WIN32
+ result["platform"] = "win32";
+#elif defined __linux__
+ result["platform"] = "linux";
+#elif defined __APPLE__
+ result["platform"] = "apple";
+#elif defined __unix__
+ result["platform"] = "unix";
+#else
+ result["platform"] = "unknown";
+#endif
+
+#if defined(__ICC) || defined(__INTEL_COMPILER)
+ result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
+#elif defined(__clang__)
+ result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
+#elif defined(__GNUC__) || defined(__GNUG__)
+ result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}};
+#elif defined(__HP_cc) || defined(__HP_aCC)
+ result["compiler"] = "hp"
+#elif defined(__IBMCPP__)
+ result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
+#elif defined(_MSC_VER)
+ result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
+#elif defined(__PGI)
+ result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
+#elif defined(__SUNPRO_CC)
+ result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
+#else
+ result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
+#endif
+
+#ifdef __cplusplus
+ result["compiler"]["c++"] = std::to_string(__cplusplus);
+#else
+ result["compiler"]["c++"] = "unknown";
+#endif
+ return result;
+ }
+
+
+ ///////////////////////////
+ // JSON value data types //
+ ///////////////////////////
+
+ /// @name JSON value data types
+ /// The data types to store a JSON value. These types are derived from
+ /// the template arguments passed to class @ref basic_json.
+ /// @{
+
+#if defined(JSON_HAS_CPP_14)
+ // Use transparent comparator if possible, combined with perfect forwarding
+ // on find() and count() calls prevents unnecessary string construction.
+ using object_comparator_t = std::less<>;
+#else
+ using object_comparator_t = std::less<StringType>;
+#endif
+
+ /*!
+ @brief a type for an object
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON objects as follows:
+ > An object is an unordered collection of zero or more name/value pairs,
+ > where a name is a string and a value is a string, number, boolean, null,
+ > object, or array.
+
+ To store objects in C++, a type is defined by the template parameters
+ described below.
+
+ @tparam ObjectType the container to store objects (e.g., `std::map` or
+ `std::unordered_map`)
+ @tparam StringType the type of the keys or names (e.g., `std::string`).
+ The comparison function `std::less<StringType>` is used to order elements
+ inside the container.
+ @tparam AllocatorType the allocator to use for objects (e.g.,
+ `std::allocator`)
+
+ #### Default type
+
+ With the default values for @a ObjectType (`std::map`), @a StringType
+ (`std::string`), and @a AllocatorType (`std::allocator`), the default
+ value for @a object_t is:
+
+ @code {.cpp}
+ std::map<
+ std::string, // key_type
+ basic_json, // value_type
+ std::less<std::string>, // key_compare
+ std::allocator<std::pair<const std::string, basic_json>> // allocator_type
+ >
+ @endcode
+
+ #### Behavior
+
+ The choice of @a object_t influences the behavior of the JSON class. With
+ the default type, objects have the following behavior:
+
+ - When all names are unique, objects will be interoperable in the sense
+ that all software implementations receiving that object will agree on
+ the name-value mappings.
+ - When the names within an object are not unique, it is unspecified which
+ one of the values for a given key will be chosen. For instance,
+ `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or
+ `{"key": 2}`.
+ - Internally, name/value pairs are stored in lexicographical order of the
+ names. Objects will also be serialized (see @ref dump) in this order.
+ For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored
+ and serialized as `{"a": 2, "b": 1}`.
+ - When comparing objects, the order of the name/value pairs is irrelevant.
+ This makes objects interoperable in the sense that they will not be
+ affected by these differences. For instance, `{"b": 1, "a": 2}` and
+ `{"a": 2, "b": 1}` will be treated as equal.
+
+ #### Limits
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+ > An implementation may set limits on the maximum depth of nesting.
+
+ In this class, the object's limit of nesting is not explicitly constrained.
+ However, a maximum depth of nesting may be introduced by the compiler or
+ runtime environment. A theoretical limit can be queried by calling the
+ @ref max_size function of a JSON object.
+
+ #### Storage
+
+ Objects are stored as pointers in a @ref basic_json type. That is, for any
+ access to object values, a pointer of type `object_t*` must be
+ dereferenced.
+
+ @sa see @ref array_t -- type for an array value
+
+ @since version 1.0.0
+
+ @note The order name/value pairs are added to the object is *not*
+ preserved by the library. Therefore, iterating an object may return
+ name/value pairs in a different order than they were originally stored. In
+ fact, keys will be traversed in alphabetical order as `std::map` with
+ `std::less` is used by default. Please note this behavior conforms to [RFC
+ 8259](https://tools.ietf.org/html/rfc8259), because any order implements the
+ specified "unordered" nature of JSON objects.
+ */
+ using object_t = ObjectType<StringType,
+ basic_json,
+ object_comparator_t,
+ AllocatorType<std::pair<const StringType,
+ basic_json>>>;
+
+ /*!
+ @brief a type for an array
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON arrays as follows:
+ > An array is an ordered sequence of zero or more values.
+
+ To store objects in C++, a type is defined by the template parameters
+ explained below.
+
+ @tparam ArrayType container type to store arrays (e.g., `std::vector` or
+ `std::list`)
+ @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`)
+
+ #### Default type
+
+ With the default values for @a ArrayType (`std::vector`) and @a
+ AllocatorType (`std::allocator`), the default value for @a array_t is:
+
+ @code {.cpp}
+ std::vector<
+ basic_json, // value_type
+ std::allocator<basic_json> // allocator_type
+ >
+ @endcode
+
+ #### Limits
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+ > An implementation may set limits on the maximum depth of nesting.
+
+ In this class, the array's limit of nesting is not explicitly constrained.
+ However, a maximum depth of nesting may be introduced by the compiler or
+ runtime environment. A theoretical limit can be queried by calling the
+ @ref max_size function of a JSON array.
+
+ #### Storage
+
+ Arrays are stored as pointers in a @ref basic_json type. That is, for any
+ access to array values, a pointer of type `array_t*` must be dereferenced.
+
+ @sa see @ref object_t -- type for an object value
+
+ @since version 1.0.0
+ */
+ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
+
+ /*!
+ @brief a type for a string
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) describes JSON strings as follows:
+ > A string is a sequence of zero or more Unicode characters.
+
+ To store objects in C++, a type is defined by the template parameter
+ described below. Unicode values are split by the JSON class into
+ byte-sized characters during deserialization.
+
+ @tparam StringType the container to store strings (e.g., `std::string`).
+ Note this container is used for keys/names in objects, see @ref object_t.
+
+ #### Default type
+
+ With the default values for @a StringType (`std::string`), the default
+ value for @a string_t is:
+
+ @code {.cpp}
+ std::string
+ @endcode
+
+ #### Encoding
+
+ Strings are stored in UTF-8 encoding. Therefore, functions like
+ `std::string::size()` or `std::string::length()` return the number of
+ bytes in the string rather than the number of characters or glyphs.
+
+ #### String comparison
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) states:
+ > Software implementations are typically required to test names of object
+ > members for equality. Implementations that transform the textual
+ > representation into sequences of Unicode code units and then perform the
+ > comparison numerically, code unit by code unit, are interoperable in the
+ > sense that implementations will agree in all cases on equality or
+ > inequality of two strings. For example, implementations that compare
+ > strings with escaped characters unconverted may incorrectly find that
+ > `"a\\b"` and `"a\u005Cb"` are not equal.
+
+ This implementation is interoperable as it does compare strings code unit
+ by code unit.
+
+ #### Storage
+
+ String values are stored as pointers in a @ref basic_json type. That is,
+ for any access to string values, a pointer of type `string_t*` must be
+ dereferenced.
+
+ @since version 1.0.0
+ */
+ using string_t = StringType;
+
+ /*!
+ @brief a type for a boolean
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) implicitly describes a boolean as a
+ type which differentiates the two literals `true` and `false`.
+
+ To store objects in C++, a type is defined by the template parameter @a
+ BooleanType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a BooleanType (`bool`), the default value for
+ @a boolean_t is:
+
+ @code {.cpp}
+ bool
+ @endcode
+
+ #### Storage
+
+ Boolean values are stored directly inside a @ref basic_json type.
+
+ @since version 1.0.0
+ */
+ using boolean_t = BooleanType;
+
+ /*!
+ @brief a type for a number (integer)
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows:
+ > The representation of numbers is similar to that used in most
+ > programming languages. A number is represented in base 10 using decimal
+ > digits. It contains an integer component that may be prefixed with an
+ > optional minus sign, which may be followed by a fraction part and/or an
+ > exponent part. Leading zeros are not allowed. (...) Numeric values that
+ > cannot be represented in the grammar below (such as Infinity and NaN)
+ > are not permitted.
+
+ This description includes both integer and floating-point numbers.
+ However, C++ allows more precise storage if it is known whether the number
+ is a signed integer, an unsigned integer or a floating-point number.
+ Therefore, three different types, @ref number_integer_t, @ref
+ number_unsigned_t and @ref number_float_t are used.
+
+ To store integer numbers in C++, a type is defined by the template
+ parameter @a NumberIntegerType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a NumberIntegerType (`int64_t`), the default
+ value for @a number_integer_t is:
+
+ @code {.cpp}
+ int64_t
+ @endcode
+
+ #### Default behavior
+
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in integer literals lead to an interpretation as octal
+ number. Internally, the value will be stored as decimal number. For
+ instance, the C++ integer literal `010` will be serialized to `8`.
+ During deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+
+ #### Limits
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+ > An implementation may set limits on the range and precision of numbers.
+
+ When the default type is used, the maximal integer number that can be
+ stored is `9223372036854775807` (INT64_MAX) and the minimal integer number
+ that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers
+ that are out of range will yield over/underflow when used in a
+ constructor. During deserialization, too large or small integer numbers
+ will be automatically be stored as @ref number_unsigned_t or @ref
+ number_float_t.
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
+ > Note that when such software is used, numbers that are integers and are
+ > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+ > that implementations will agree exactly on their numeric values.
+
+ As this range is a subrange of the exactly supported range [INT64_MIN,
+ INT64_MAX], this class's integer type is interoperable.
+
+ #### Storage
+
+ Integer number values are stored directly inside a @ref basic_json type.
+
+ @sa see @ref number_float_t -- type for number values (floating-point)
+
+ @sa see @ref number_unsigned_t -- type for number values (unsigned integer)
+
+ @since version 1.0.0
+ */
+ using number_integer_t = NumberIntegerType;
+
+ /*!
+ @brief a type for a number (unsigned)
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows:
+ > The representation of numbers is similar to that used in most
+ > programming languages. A number is represented in base 10 using decimal
+ > digits. It contains an integer component that may be prefixed with an
+ > optional minus sign, which may be followed by a fraction part and/or an
+ > exponent part. Leading zeros are not allowed. (...) Numeric values that
+ > cannot be represented in the grammar below (such as Infinity and NaN)
+ > are not permitted.
+
+ This description includes both integer and floating-point numbers.
+ However, C++ allows more precise storage if it is known whether the number
+ is a signed integer, an unsigned integer or a floating-point number.
+ Therefore, three different types, @ref number_integer_t, @ref
+ number_unsigned_t and @ref number_float_t are used.
+
+ To store unsigned integer numbers in C++, a type is defined by the
+ template parameter @a NumberUnsignedType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a NumberUnsignedType (`uint64_t`), the
+ default value for @a number_unsigned_t is:
+
+ @code {.cpp}
+ uint64_t
+ @endcode
+
+ #### Default behavior
+
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in integer literals lead to an interpretation as octal
+ number. Internally, the value will be stored as decimal number. For
+ instance, the C++ integer literal `010` will be serialized to `8`.
+ During deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+
+ #### Limits
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) specifies:
+ > An implementation may set limits on the range and precision of numbers.
+
+ When the default type is used, the maximal integer number that can be
+ stored is `18446744073709551615` (UINT64_MAX) and the minimal integer
+ number that can be stored is `0`. Integer numbers that are out of range
+ will yield over/underflow when used in a constructor. During
+ deserialization, too large or small integer numbers will be automatically
+ be stored as @ref number_integer_t or @ref number_float_t.
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) further states:
+ > Note that when such software is used, numbers that are integers and are
+ > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense
+ > that implementations will agree exactly on their numeric values.
+
+ As this range is a subrange (when considered in conjunction with the
+ number_integer_t type) of the exactly supported range [0, UINT64_MAX],
+ this class's integer type is interoperable.
+
+ #### Storage
+
+ Integer number values are stored directly inside a @ref basic_json type.
+
+ @sa see @ref number_float_t -- type for number values (floating-point)
+ @sa see @ref number_integer_t -- type for number values (integer)
+
+ @since version 2.0.0
+ */
+ using number_unsigned_t = NumberUnsignedType;
+
+ /*!
+ @brief a type for a number (floating-point)
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) describes numbers as follows:
+ > The representation of numbers is similar to that used in most
+ > programming languages. A number is represented in base 10 using decimal
+ > digits. It contains an integer component that may be prefixed with an
+ > optional minus sign, which may be followed by a fraction part and/or an
+ > exponent part. Leading zeros are not allowed. (...) Numeric values that
+ > cannot be represented in the grammar below (such as Infinity and NaN)
+ > are not permitted.
+
+ This description includes both integer and floating-point numbers.
+ However, C++ allows more precise storage if it is known whether the number
+ is a signed integer, an unsigned integer or a floating-point number.
+ Therefore, three different types, @ref number_integer_t, @ref
+ number_unsigned_t and @ref number_float_t are used.
+
+ To store floating-point numbers in C++, a type is defined by the template
+ parameter @a NumberFloatType which chooses the type to use.
+
+ #### Default type
+
+ With the default values for @a NumberFloatType (`double`), the default
+ value for @a number_float_t is:
+
+ @code {.cpp}
+ double
+ @endcode
+
+ #### Default behavior
+
+ - The restrictions about leading zeros is not enforced in C++. Instead,
+ leading zeros in floating-point literals will be ignored. Internally,
+ the value will be stored as decimal number. For instance, the C++
+ floating-point literal `01.2` will be serialized to `1.2`. During
+ deserialization, leading zeros yield an error.
+ - Not-a-number (NaN) values will be serialized to `null`.
+
+ #### Limits
+
+ [RFC 8259](https://tools.ietf.org/html/rfc8259) states:
+ > This specification allows implementations to set limits on the range and
+ > precision of numbers accepted. Since software that implements IEEE
+ > 754-2008 binary64 (double precision) numbers is generally available and
+ > widely used, good interoperability can be achieved by implementations
+ > that expect no more precision or range than these provide, in the sense
+ > that implementations will approximate JSON numbers within the expected
+ > precision.
+
+ This implementation does exactly follow this approach, as it uses double
+ precision floating-point numbers. Note values smaller than
+ `-1.79769313486232e+308` and values greater than `1.79769313486232e+308`
+ will be stored as NaN internally and be serialized to `null`.
+
+ #### Storage
+
+ Floating-point number values are stored directly inside a @ref basic_json
+ type.
+
+ @sa see @ref number_integer_t -- type for number values (integer)
+
+ @sa see @ref number_unsigned_t -- type for number values (unsigned integer)
+
+ @since version 1.0.0
+ */
+ using number_float_t = NumberFloatType;
+
+ /*!
+ @brief a type for a packed binary type
+
+ This type is a type designed to carry binary data that appears in various
+ serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and
+ BSON's generic binary subtype. This type is NOT a part of standard JSON and
+ exists solely for compatibility with these binary types. As such, it is
+ simply defined as an ordered sequence of zero or more byte values.
+
+ Additionally, as an implementation detail, the subtype of the binary data is
+ carried around as a `std::uint8_t`, which is compatible with both of the
+ binary data formats that use binary subtyping, (though the specific
+ numbering is incompatible with each other, and it is up to the user to
+ translate between them).
+
+ [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type
+ as:
+ > Major type 2: a byte string. The string's length in bytes is represented
+ > following the rules for positive integers (major type 0).
+
+ [MessagePack's documentation on the bin type
+ family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family)
+ describes this type as:
+ > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes
+ > in addition to the size of the byte array.
+
+ [BSON's specifications](http://bsonspec.org/spec.html) describe several
+ binary types; however, this type is intended to represent the generic binary
+ type which has the description:
+ > Generic binary subtype - This is the most commonly used binary subtype and
+ > should be the 'default' for drivers and tools.
+
+ None of these impose any limitations on the internal representation other
+ than the basic unit of storage be some type of array whose parts are
+ decomposable into bytes.
+
+ The default representation of this binary format is a
+ `std::vector<std::uint8_t>`, which is a very common way to represent a byte
+ array in modern C++.
+
+ #### Default type
+
+ The default values for @a BinaryType is `std::vector<std::uint8_t>`
+
+ #### Storage
+
+ Binary Arrays are stored as pointers in a @ref basic_json type. That is,
+ for any access to array values, a pointer of the type `binary_t*` must be
+ dereferenced.
+
+ #### Notes on subtypes
+
+ - CBOR
+ - Binary values are represented as byte strings. Subtypes are serialized
+ as tagged values.
+ - MessagePack
+ - If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
+ or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
+ is used. For other sizes, the ext family (ext8, ext16, ext32) is used.
+ The subtype is then added as signed 8-bit integer.
+ - If no subtype is given, the bin family (bin8, bin16, bin32) is used.
+ - BSON
+ - If a subtype is given, it is used and added as unsigned 8-bit integer.
+ - If no subtype is given, the generic binary subtype 0x00 is used.
+
+ @sa see @ref binary -- create a binary array
+
+ @since version 3.8.0
+ */
+ using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
+ /// @}
+
+ private:
+
+ /// helper for exception-safe object creation
+ template<typename T, typename... Args>
+ JSON_HEDLEY_RETURNS_NON_NULL
+ static T* create(Args&& ... args)
+ {
+ AllocatorType<T> alloc;
+ using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
+
+ auto deleter = [&](T * obj)
+ {
+ AllocatorTraits::deallocate(alloc, obj, 1);
+ };
+ std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
+ AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
+ JSON_ASSERT(obj != nullptr);
+ return obj.release();
+ }
+
+ ////////////////////////
+ // JSON value storage //
+ ////////////////////////
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ /*!
+ @brief a JSON value
+
+ The actual storage for a JSON value of the @ref basic_json class. This
+ union combines the different storage types for the JSON value types
+ defined in @ref value_t.
+
+ JSON type | value_t type | used type
+ --------- | --------------- | ------------------------
+ object | object | pointer to @ref object_t
+ array | array | pointer to @ref array_t
+ string | string | pointer to @ref string_t
+ boolean | boolean | @ref boolean_t
+ number | number_integer | @ref number_integer_t
+ number | number_unsigned | @ref number_unsigned_t
+ number | number_float | @ref number_float_t
+ binary | binary | pointer to @ref binary_t
+ null | null | *no value is stored*
+
+ @note Variable-length types (objects, arrays, and strings) are stored as
+ pointers. The size of the union should not exceed 64 bits if the default
+ value types are used.
+
+ @since version 1.0.0
+ */
+ union json_value
+ {
+ /// object (stored with pointer to save storage)
+ object_t* object;
+ /// array (stored with pointer to save storage)
+ array_t* array;
+ /// string (stored with pointer to save storage)
+ string_t* string;
+ /// binary (stored with pointer to save storage)
+ binary_t* binary;
+ /// boolean
+ boolean_t boolean;
+ /// number (integer)
+ number_integer_t number_integer;
+ /// number (unsigned integer)
+ number_unsigned_t number_unsigned;
+ /// number (floating-point)
+ number_float_t number_float;
+
+ /// default constructor (for null values)
+ json_value() = default;
+ /// constructor for booleans
+ json_value(boolean_t v) noexcept : boolean(v) {}
+ /// constructor for numbers (integer)
+ json_value(number_integer_t v) noexcept : number_integer(v) {}
+ /// constructor for numbers (unsigned)
+ json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
+ /// constructor for numbers (floating-point)
+ json_value(number_float_t v) noexcept : number_float(v) {}
+ /// constructor for empty values of a given type
+ json_value(value_t t)
+ {
+ switch (t)
+ {
+ case value_t::object:
+ {
+ object = create<object_t>();
+ break;
+ }
+
+ case value_t::array:
+ {
+ array = create<array_t>();
+ break;
+ }
+
+ case value_t::string:
+ {
+ string = create<string_t>("");
+ break;
+ }
+
+ case value_t::binary:
+ {
+ binary = create<binary_t>();
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ boolean = boolean_t(false);
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ number_integer = number_integer_t(0);
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ number_unsigned = number_unsigned_t(0);
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ number_float = number_float_t(0.0);
+ break;
+ }
+
+ case value_t::null:
+ {
+ object = nullptr; // silence warning, see #821
+ break;
+ }
+
+ case value_t::discarded:
+ default:
+ {
+ object = nullptr; // silence warning, see #821
+ if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
+ {
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.10.4", basic_json())); // LCOV_EXCL_LINE
+ }
+ break;
+ }
+ }
+ }
+
+ /// constructor for strings
+ json_value(const string_t& value) : string(create<string_t>(value)) {}
+
+ /// constructor for rvalue strings
+ json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
+
+ /// constructor for objects
+ json_value(const object_t& value) : object(create<object_t>(value)) {}
+
+ /// constructor for rvalue objects
+ json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
+
+ /// constructor for arrays
+ json_value(const array_t& value) : array(create<array_t>(value)) {}
+
+ /// constructor for rvalue arrays
+ json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
+
+ /// constructor for binary arrays
+ json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
+
+ /// constructor for rvalue binary arrays
+ json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
+
+ /// constructor for binary arrays (internal type)
+ json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
+
+ /// constructor for rvalue binary arrays (internal type)
+ json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
+
+ void destroy(value_t t)
+ {
+ if (t == value_t::array || t == value_t::object)
+ {
+ // flatten the current json_value to a heap-allocated stack
+ std::vector<basic_json> stack;
+
+ // move the top-level items to stack
+ if (t == value_t::array)
+ {
+ stack.reserve(array->size());
+ std::move(array->begin(), array->end(), std::back_inserter(stack));
+ }
+ else
+ {
+ stack.reserve(object->size());
+ for (auto&& it : *object)
+ {
+ stack.push_back(std::move(it.second));
+ }
+ }
+
+ while (!stack.empty())
+ {
+ // move the last item to local variable to be processed
+ basic_json current_item(std::move(stack.back()));
+ stack.pop_back();
+
+ // if current_item is array/object, move
+ // its children to the stack to be processed later
+ if (current_item.is_array())
+ {
+ std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
+
+ current_item.m_value.array->clear();
+ }
+ else if (current_item.is_object())
+ {
+ for (auto&& it : *current_item.m_value.object)
+ {
+ stack.push_back(std::move(it.second));
+ }
+
+ current_item.m_value.object->clear();
+ }
+
+ // it's now safe that current_item get destructed
+ // since it doesn't have any children
+ }
+ }
+
+ switch (t)
+ {
+ case value_t::object:
+ {
+ AllocatorType<object_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
+ break;
+ }
+
+ case value_t::array:
+ {
+ AllocatorType<array_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
+ break;
+ }
+
+ case value_t::string:
+ {
+ AllocatorType<string_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
+ break;
+ }
+
+ case value_t::binary:
+ {
+ AllocatorType<binary_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::discarded:
+ default:
+ {
+ break;
+ }
+ }
+ }
+ };
+
+ private:
+ /*!
+ @brief checks the class invariants
+
+ This function asserts the class invariants. It needs to be called at the
+ end of every constructor to make sure that created objects respect the
+ invariant. Furthermore, it has to be called each time the type of a JSON
+ value is changed, because the invariant expresses a relationship between
+ @a m_type and @a m_value.
+
+ Furthermore, the parent relation is checked for arrays and objects: If
+ @a check_parents true and the value is an array or object, then the
+ container's elements must have the current value as parent.
+
+ @param[in] check_parents whether the parent relation should be checked.
+ The value is true by default and should only be set to false
+ during destruction of objects when the invariant does not
+ need to hold.
+ */
+ void assert_invariant(bool check_parents = true) const noexcept
+ {
+ JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
+ JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
+ JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
+ JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
+
+#if JSON_DIAGNOSTICS
+ JSON_TRY
+ {
+ // cppcheck-suppress assertWithSideEffect
+ JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
+ {
+ return j.m_parent == this;
+ }));
+ }
+ JSON_CATCH(...) {} // LCOV_EXCL_LINE
+#endif
+ static_cast<void>(check_parents);
+ }
+
+ void set_parents()
+ {
+#if JSON_DIAGNOSTICS
+ switch (m_type)
+ {
+ case value_t::array:
+ {
+ for (auto& element : *m_value.array)
+ {
+ element.m_parent = this;
+ }
+ break;
+ }
+
+ case value_t::object:
+ {
+ for (auto& element : *m_value.object)
+ {
+ element.second.m_parent = this;
+ }
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ break;
+ }
+#endif
+ }
+
+ iterator set_parents(iterator it, typename iterator::difference_type count)
+ {
+#if JSON_DIAGNOSTICS
+ for (typename iterator::difference_type i = 0; i < count; ++i)
+ {
+ (it + i)->m_parent = this;
+ }
+#else
+ static_cast<void>(count);
+#endif
+ return it;
+ }
+
+ reference set_parent(reference j, std::size_t old_capacity = std::size_t(-1))
+ {
+#if JSON_DIAGNOSTICS
+ if (old_capacity != std::size_t(-1))
+ {
+ // see https://github.com/nlohmann/json/issues/2838
+ JSON_ASSERT(type() == value_t::array);
+ if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
+ {
+ // capacity has changed: update all parents
+ set_parents();
+ return j;
+ }
+ }
+
+ // ordered_json uses a vector internally, so pointers could have
+ // been invalidated; see https://github.com/nlohmann/json/issues/2962
+#ifdef JSON_HEDLEY_MSVC_VERSION
+#pragma warning(push )
+#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
+#endif
+ if (detail::is_ordered_map<object_t>::value)
+ {
+ set_parents();
+ return j;
+ }
+#ifdef JSON_HEDLEY_MSVC_VERSION
+#pragma warning( pop )
+#endif
+
+ j.m_parent = this;
+#else
+ static_cast<void>(j);
+ static_cast<void>(old_capacity);
+#endif
+ return j;
+ }
+
+ public:
+ //////////////////////////
+ // JSON parser callback //
+ //////////////////////////
+
+ /*!
+ @brief parser event types
+
+ The parser callback distinguishes the following events:
+ - `object_start`: the parser read `{` and started to process a JSON object
+ - `key`: the parser read a key of a value in an object
+ - `object_end`: the parser read `}` and finished processing a JSON object
+ - `array_start`: the parser read `[` and started to process a JSON array
+ - `array_end`: the parser read `]` and finished processing a JSON array
+ - `value`: the parser finished reading a JSON value
+
+ @image html callback_events.png "Example when certain parse events are triggered"
+
+ @sa see @ref parser_callback_t for more information and examples
+ */
+ using parse_event_t = detail::parse_event_t;
+
+ /*!
+ @brief per-element parser callback type
+
+ With a parser callback function, the result of parsing a JSON text can be
+ influenced. When passed to @ref parse, it is called on certain events
+ (passed as @ref parse_event_t via parameter @a event) with a set recursion
+ depth @a depth and context JSON value @a parsed. The return value of the
+ callback function is a boolean indicating whether the element that emitted
+ the callback shall be kept or not.
+
+ We distinguish six scenarios (determined by the event type) in which the
+ callback function can be called. The following table describes the values
+ of the parameters @a depth, @a event, and @a parsed.
+
+ parameter @a event | description | parameter @a depth | parameter @a parsed
+ ------------------ | ----------- | ------------------ | -------------------
+ parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded
+ parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key
+ parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object
+ parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded
+ parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array
+ parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value
+
+ @image html callback_events.png "Example when certain parse events are triggered"
+
+ Discarding a value (i.e., returning `false`) has different effects
+ depending on the context in which function was called:
+
+ - Discarded values in structured types are skipped. That is, the parser
+ will behave as if the discarded value was never read.
+ - In case a value outside a structured type is skipped, it is replaced
+ with `null`. This case happens if the top-level element is skipped.
+
+ @param[in] depth the depth of the recursion during parsing
+
+ @param[in] event an event of type parse_event_t indicating the context in
+ the callback function has been called
+
+ @param[in,out] parsed the current intermediate parse result; note that
+ writing to this value has no effect for parse_event_t::key events
+
+ @return Whether the JSON value which called the function during parsing
+ should be kept (`true`) or not (`false`). In the latter case, it is either
+ skipped completely or replaced by an empty discarded object.
+
+ @sa see @ref parse for examples
+
+ @since version 1.0.0
+ */
+ using parser_callback_t = detail::parser_callback_t<basic_json>;
+
+ //////////////////
+ // constructors //
+ //////////////////
+
+ /// @name constructors and destructors
+ /// Constructors of class @ref basic_json, copy/move constructor, copy
+ /// assignment, static functions creating objects, and the destructor.
+ /// @{
+
+ /*!
+ @brief create an empty value with a given type
+
+ Create an empty JSON value with a given type. The value will be default
+ initialized with an empty value which depends on the type:
+
+ Value type | initial value
+ ----------- | -------------
+ null | `null`
+ boolean | `false`
+ string | `""`
+ number | `0`
+ object | `{}`
+ array | `[]`
+ binary | empty array
+
+ @param[in] v the type of the value to create
+
+ @complexity Constant.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @liveexample{The following code shows the constructor for different @ref
+ value_t values,basic_json__value_t}
+
+ @sa see @ref clear() -- restores the postcondition of this constructor
+
+ @since version 1.0.0
+ */
+ basic_json(const value_t v)
+ : m_type(v), m_value(v)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a null object
+
+ Create a `null` JSON value. It either takes a null pointer as parameter
+ (explicitly creating `null`) or no parameter (implicitly creating `null`).
+ The passed null pointer itself is not read -- it is only used to choose
+ the right constructor.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this constructor never throws
+ exceptions.
+
+ @liveexample{The following code shows the constructor with and without a
+ null pointer parameter.,basic_json__nullptr_t}
+
+ @since version 1.0.0
+ */
+ basic_json(std::nullptr_t = nullptr) noexcept
+ : basic_json(value_t::null)
+ {
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a JSON value
+
+ This is a "catch all" constructor for all compatible JSON types; that is,
+ types for which a `to_json()` method exists. The constructor forwards the
+ parameter @a val to that method (to `json_serializer<U>::to_json` method
+ with `U = uncvref_t<CompatibleType>`, to be exact).
+
+ Template type @a CompatibleType includes, but is not limited to, the
+ following types:
+ - **arrays**: @ref array_t and all kinds of compatible containers such as
+ `std::vector`, `std::deque`, `std::list`, `std::forward_list`,
+ `std::array`, `std::valarray`, `std::set`, `std::unordered_set`,
+ `std::multiset`, and `std::unordered_multiset` with a `value_type` from
+ which a @ref basic_json value can be constructed.
+ - **objects**: @ref object_t and all kinds of compatible associative
+ containers such as `std::map`, `std::unordered_map`, `std::multimap`,
+ and `std::unordered_multimap` with a `key_type` compatible to
+ @ref string_t and a `value_type` from which a @ref basic_json value can
+ be constructed.
+ - **strings**: @ref string_t, string literals, and all compatible string
+ containers can be used.
+ - **numbers**: @ref number_integer_t, @ref number_unsigned_t,
+ @ref number_float_t, and all convertible number types such as `int`,
+ `size_t`, `int64_t`, `float` or `double` can be used.
+ - **boolean**: @ref boolean_t / `bool` can be used.
+ - **binary**: @ref binary_t / `std::vector<std::uint8_t>` may be used,
+ unfortunately because string literals cannot be distinguished from binary
+ character arrays by the C++ type system, all types compatible with `const
+ char*` will be directed to the string constructor instead. This is both
+ for backwards compatibility, and due to the fact that a binary type is not
+ a standard JSON type.
+
+ See the examples below.
+
+ @tparam CompatibleType a type such that:
+ - @a CompatibleType is not derived from `std::istream`,
+ - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move
+ constructors),
+ - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments)
+ - @a CompatibleType is not a @ref basic_json nested type (e.g.,
+ @ref json_pointer, @ref iterator, etc ...)
+ - `json_serializer<U>` has a `to_json(basic_json_t&, CompatibleType&&)` method
+
+ @tparam U = `uncvref_t<CompatibleType>`
+
+ @param[in] val the value to be forwarded to the respective constructor
+
+ @complexity Usually linear in the size of the passed @a val, also
+ depending on the implementation of the called `to_json()`
+ method.
+
+ @exceptionsafety Depends on the called constructor. For types directly
+ supported by the library (i.e., all types for which no `to_json()` function
+ was provided), strong guarantee holds: if an exception is thrown, there are
+ no changes to any JSON value.
+
+ @liveexample{The following code shows the constructor with several
+ compatible types.,basic_json__CompatibleType}
+
+ @since version 2.1.0
+ */
+ template < typename CompatibleType,
+ typename U = detail::uncvref_t<CompatibleType>,
+ detail::enable_if_t <
+ !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
+ basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
+ JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
+ std::forward<CompatibleType>(val))))
+ {
+ JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
+ set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a JSON value from an existing one
+
+ This is a constructor for existing @ref basic_json types.
+ It does not hijack copy/move constructors, since the parameter has different
+ template arguments than the current ones.
+
+ The constructor tries to convert the internal @ref m_value of the parameter.
+
+ @tparam BasicJsonType a type such that:
+ - @a BasicJsonType is a @ref basic_json type.
+ - @a BasicJsonType has different template arguments than @ref basic_json_t.
+
+ @param[in] val the @ref basic_json value to be converted.
+
+ @complexity Usually linear in the size of the passed @a val, also
+ depending on the implementation of the called `to_json()`
+ method.
+
+ @exceptionsafety Depends on the called constructor. For types directly
+ supported by the library (i.e., all types for which no `to_json()` function
+ was provided), strong guarantee holds: if an exception is thrown, there are
+ no changes to any JSON value.
+
+ @since version 3.2.0
+ */
+ template < typename BasicJsonType,
+ detail::enable_if_t <
+ detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
+ basic_json(const BasicJsonType& val)
+ {
+ using other_boolean_t = typename BasicJsonType::boolean_t;
+ using other_number_float_t = typename BasicJsonType::number_float_t;
+ using other_number_integer_t = typename BasicJsonType::number_integer_t;
+ using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
+ using other_string_t = typename BasicJsonType::string_t;
+ using other_object_t = typename BasicJsonType::object_t;
+ using other_array_t = typename BasicJsonType::array_t;
+ using other_binary_t = typename BasicJsonType::binary_t;
+
+ switch (val.type())
+ {
+ case value_t::boolean:
+ JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
+ break;
+ case value_t::number_float:
+ JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
+ break;
+ case value_t::number_integer:
+ JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
+ break;
+ case value_t::number_unsigned:
+ JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
+ break;
+ case value_t::string:
+ JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
+ break;
+ case value_t::object:
+ JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
+ break;
+ case value_t::array:
+ JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
+ break;
+ case value_t::binary:
+ JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
+ break;
+ case value_t::null:
+ *this = nullptr;
+ break;
+ case value_t::discarded:
+ m_type = value_t::discarded;
+ break;
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+ set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief create a container (array or object) from an initializer list
+
+ Creates a JSON value of type array or object from the passed initializer
+ list @a init. In case @a type_deduction is `true` (default), the type of
+ the JSON value to be created is deducted from the initializer list @a init
+ according to the following rules:
+
+ 1. If the list is empty, an empty JSON object value `{}` is created.
+ 2. If the list consists of pairs whose first element is a string, a JSON
+ object value is created where the first elements of the pairs are
+ treated as keys and the second elements are as values.
+ 3. In all other cases, an array is created.
+
+ The rules aim to create the best fit between a C++ initializer list and
+ JSON values. The rationale is as follows:
+
+ 1. The empty initializer list is written as `{}` which is exactly an empty
+ JSON object.
+ 2. C++ has no way of describing mapped types other than to list a list of
+ pairs. As JSON requires that keys must be of type string, rule 2 is the
+ weakest constraint one can pose on initializer lists to interpret them
+ as an object.
+ 3. In all other cases, the initializer list could not be interpreted as
+ JSON object type, so interpreting it as JSON array type is safe.
+
+ With the rules described above, the following JSON values cannot be
+ expressed by an initializer list:
+
+ - the empty array (`[]`): use @ref array(initializer_list_t)
+ with an empty initializer list in this case
+ - arrays whose elements satisfy rule 2: use @ref
+ array(initializer_list_t) with the same initializer list
+ in this case
+
+ @note When used without parentheses around an empty initializer list, @ref
+ basic_json() is called instead of this function, yielding the JSON null
+ value.
+
+ @param[in] init initializer list with JSON values
+
+ @param[in] type_deduction internal parameter; when set to `true`, the type
+ of the JSON value is deducted from the initializer list @a init; when set
+ to `false`, the type provided via @a manual_type is forced. This mode is
+ used by the functions @ref array(initializer_list_t) and
+ @ref object(initializer_list_t).
+
+ @param[in] manual_type internal parameter; when @a type_deduction is set
+ to `false`, the created JSON value will use the provided type (only @ref
+ value_t::array and @ref value_t::object are valid); when @a type_deduction
+ is set to `true`, this parameter has no effect
+
+ @throw type_error.301 if @a type_deduction is `false`, @a manual_type is
+ `value_t::object`, but @a init contains an element which is not a pair
+ whose first element is a string. In this case, the constructor could not
+ create an object. If @a type_deduction would have be `true`, an array
+ would have been created. See @ref object(initializer_list_t)
+ for an example.
+
+ @complexity Linear in the size of the initializer list @a init.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @liveexample{The example below shows how JSON values are created from
+ initializer lists.,basic_json__list_init_t}
+
+ @sa see @ref array(initializer_list_t) -- create a JSON array
+ value from an initializer list
+ @sa see @ref object(initializer_list_t) -- create a JSON object
+ value from an initializer list
+
+ @since version 1.0.0
+ */
+ basic_json(initializer_list_t init,
+ bool type_deduction = true,
+ value_t manual_type = value_t::array)
+ {
+ // check if each element is an array with two elements whose first
+ // element is a string
+ bool is_an_object = std::all_of(init.begin(), init.end(),
+ [](const detail::json_ref<basic_json>& element_ref)
+ {
+ return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
+ });
+
+ // adjust type if type deduction is not wanted
+ if (!type_deduction)
+ {
+ // if array is wanted, do not create an object though possible
+ if (manual_type == value_t::array)
+ {
+ is_an_object = false;
+ }
+
+ // if object is wanted but impossible, throw an exception
+ if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
+ {
+ JSON_THROW(type_error::create(301, "cannot create object from initializer list", basic_json()));
+ }
+ }
+
+ if (is_an_object)
+ {
+ // the initializer list is a list of pairs -> create object
+ m_type = value_t::object;
+ m_value = value_t::object;
+
+ for (auto& element_ref : init)
+ {
+ auto element = element_ref.moved_or_copied();
+ m_value.object->emplace(
+ std::move(*((*element.m_value.array)[0].m_value.string)),
+ std::move((*element.m_value.array)[1]));
+ }
+ }
+ else
+ {
+ // the initializer list describes an array -> create array
+ m_type = value_t::array;
+ m_value.array = create<array_t>(init.begin(), init.end());
+ }
+
+ set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief explicitly create a binary array (without subtype)
+
+ Creates a JSON binary array value from a given binary container. Binary
+ values are part of various binary formats, such as CBOR, MessagePack, and
+ BSON. This constructor is used to create a value for serialization to those
+ formats.
+
+ @note Note, this function exists because of the difficulty in correctly
+ specifying the correct template overload in the standard value ctor, as both
+ JSON arrays and JSON binary arrays are backed with some form of a
+ `std::vector`. Because JSON binary arrays are a non-standard extension it
+ was decided that it would be best to prevent automatic initialization of a
+ binary array type, for backwards compatibility and so it does not happen on
+ accident.
+
+ @param[in] init container containing bytes to use as binary type
+
+ @return JSON binary array value
+
+ @complexity Linear in the size of @a init.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @since version 3.8.0
+ */
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json binary(const typename binary_t::container_type& init)
+ {
+ auto res = basic_json();
+ res.m_type = value_t::binary;
+ res.m_value = init;
+ return res;
+ }
+
+ /*!
+ @brief explicitly create a binary array (with subtype)
+
+ Creates a JSON binary array value from a given binary container. Binary
+ values are part of various binary formats, such as CBOR, MessagePack, and
+ BSON. This constructor is used to create a value for serialization to those
+ formats.
+
+ @note Note, this function exists because of the difficulty in correctly
+ specifying the correct template overload in the standard value ctor, as both
+ JSON arrays and JSON binary arrays are backed with some form of a
+ `std::vector`. Because JSON binary arrays are a non-standard extension it
+ was decided that it would be best to prevent automatic initialization of a
+ binary array type, for backwards compatibility and so it does not happen on
+ accident.
+
+ @param[in] init container containing bytes to use as binary type
+ @param[in] subtype subtype to use in MessagePack and BSON
+
+ @return JSON binary array value
+
+ @complexity Linear in the size of @a init.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @since version 3.8.0
+ */
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
+ {
+ auto res = basic_json();
+ res.m_type = value_t::binary;
+ res.m_value = binary_t(init, subtype);
+ return res;
+ }
+
+ /// @copydoc binary(const typename binary_t::container_type&)
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json binary(typename binary_t::container_type&& init)
+ {
+ auto res = basic_json();
+ res.m_type = value_t::binary;
+ res.m_value = std::move(init);
+ return res;
+ }
+
+ /// @copydoc binary(const typename binary_t::container_type&, typename binary_t::subtype_type)
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
+ {
+ auto res = basic_json();
+ res.m_type = value_t::binary;
+ res.m_value = binary_t(std::move(init), subtype);
+ return res;
+ }
+
+ /*!
+ @brief explicitly create an array from an initializer list
+
+ Creates a JSON array value from a given initializer list. That is, given a
+ list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the
+ initializer list is empty, the empty array `[]` is created.
+
+ @note This function is only needed to express two edge cases that cannot
+ be realized with the initializer list constructor (@ref
+ basic_json(initializer_list_t, bool, value_t)). These cases
+ are:
+ 1. creating an array whose elements are all pairs whose first element is a
+ string -- in this case, the initializer list constructor would create an
+ object, taking the first elements as keys
+ 2. creating an empty array -- passing the empty initializer list to the
+ initializer list constructor yields an empty object
+
+ @param[in] init initializer list with JSON values to create an array from
+ (optional)
+
+ @return JSON array value
+
+ @complexity Linear in the size of @a init.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @liveexample{The following code shows an example for the `array`
+ function.,array}
+
+ @sa see @ref basic_json(initializer_list_t, bool, value_t) --
+ create a JSON value from an initializer list
+ @sa see @ref object(initializer_list_t) -- create a JSON object
+ value from an initializer list
+
+ @since version 1.0.0
+ */
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json array(initializer_list_t init = {})
+ {
+ return basic_json(init, false, value_t::array);
+ }
+
+ /*!
+ @brief explicitly create an object from an initializer list
+
+ Creates a JSON object value from a given initializer list. The initializer
+ lists elements must be pairs, and their first elements must be strings. If
+ the initializer list is empty, the empty object `{}` is created.
+
+ @note This function is only added for symmetry reasons. In contrast to the
+ related function @ref array(initializer_list_t), there are
+ no cases which can only be expressed by this function. That is, any
+ initializer list @a init can also be passed to the initializer list
+ constructor @ref basic_json(initializer_list_t, bool, value_t).
+
+ @param[in] init initializer list to create an object from (optional)
+
+ @return JSON object value
+
+ @throw type_error.301 if @a init is not a list of pairs whose first
+ elements are strings. In this case, no object can be created. When such a
+ value is passed to @ref basic_json(initializer_list_t, bool, value_t),
+ an array would have been created from the passed initializer list @a init.
+ See example below.
+
+ @complexity Linear in the size of @a init.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @liveexample{The following code shows an example for the `object`
+ function.,object}
+
+ @sa see @ref basic_json(initializer_list_t, bool, value_t) --
+ create a JSON value from an initializer list
+ @sa see @ref array(initializer_list_t) -- create a JSON array
+ value from an initializer list
+
+ @since version 1.0.0
+ */
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json object(initializer_list_t init = {})
+ {
+ return basic_json(init, false, value_t::object);
+ }
+
+ /*!
+ @brief construct an array with count copies of given value
+
+ Constructs a JSON array value by creating @a cnt copies of a passed value.
+ In case @a cnt is `0`, an empty array is created.
+
+ @param[in] cnt the number of JSON copies of @a val to create
+ @param[in] val the JSON value to copy
+
+ @post `std::distance(begin(),end()) == cnt` holds.
+
+ @complexity Linear in @a cnt.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @liveexample{The following code shows examples for the @ref
+ basic_json(size_type\, const basic_json&)
+ constructor.,basic_json__size_type_basic_json}
+
+ @since version 1.0.0
+ */
+ basic_json(size_type cnt, const basic_json& val)
+ : m_type(value_t::array)
+ {
+ m_value.array = create<array_t>(cnt, val);
+ set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief construct a JSON container given an iterator range
+
+ Constructs the JSON value with the contents of the range `[first, last)`.
+ The semantics depends on the different types a JSON value can have:
+ - In case of a null type, invalid_iterator.206 is thrown.
+ - In case of other primitive types (number, boolean, or string), @a first
+ must be `begin()` and @a last must be `end()`. In this case, the value is
+ copied. Otherwise, invalid_iterator.204 is thrown.
+ - In case of structured types (array, object), the constructor behaves as
+ similar versions for `std::vector` or `std::map`; that is, a JSON array
+ or object is constructed from the values in the range.
+
+ @tparam InputIT an input iterator type (@ref iterator or @ref
+ const_iterator)
+
+ @param[in] first begin of the range to copy from (included)
+ @param[in] last end of the range to copy from (excluded)
+
+ @pre Iterators @a first and @a last must be initialized. **This
+ precondition is enforced with an assertion (see warning).** If
+ assertions are switched off, a violation of this precondition yields
+ undefined behavior.
+
+ @pre Range `[first, last)` is valid. Usually, this precondition cannot be
+ checked efficiently. Only certain edge cases are detected; see the
+ description of the exceptions below. A violation of this precondition
+ yields undefined behavior.
+
+ @warning A precondition is enforced with a runtime assertion that will
+ result in calling `std::abort` if this precondition is not met.
+ Assertions can be disabled by defining `NDEBUG` at compile time.
+ See https://en.cppreference.com/w/cpp/error/assert for more
+ information.
+
+ @throw invalid_iterator.201 if iterators @a first and @a last are not
+ compatible (i.e., do not belong to the same JSON value). In this case,
+ the range `[first, last)` is undefined.
+ @throw invalid_iterator.204 if iterators @a first and @a last belong to a
+ primitive type (number, boolean, or string), but @a first does not point
+ to the first element any more. In this case, the range `[first, last)` is
+ undefined. See example code below.
+ @throw invalid_iterator.206 if iterators @a first and @a last belong to a
+ null value. In this case, the range `[first, last)` is undefined.
+
+ @complexity Linear in distance between @a first and @a last.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @liveexample{The example below shows several ways to create JSON values by
+ specifying a subrange with iterators.,basic_json__InputIt_InputIt}
+
+ @since version 1.0.0
+ */
+ template < class InputIT, typename std::enable_if <
+ std::is_same<InputIT, typename basic_json_t::iterator>::value ||
+ std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
+ basic_json(InputIT first, InputIT last)
+ {
+ JSON_ASSERT(first.m_object != nullptr);
+ JSON_ASSERT(last.m_object != nullptr);
+
+ // make sure iterator fits the current value
+ if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", basic_json()));
+ }
+
+ // copy type from first iterator
+ m_type = first.m_object->m_type;
+
+ // check if iterator range is complete for primitive values
+ switch (m_type)
+ {
+ case value_t::boolean:
+ case value_t::number_float:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::string:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
+ || !last.m_it.primitive_iterator.is_end()))
+ {
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range", *first.m_object));
+ }
+ break;
+ }
+
+ case value_t::null:
+ case value_t::object:
+ case value_t::array:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ break;
+ }
+
+ switch (m_type)
+ {
+ case value_t::number_integer:
+ {
+ m_value.number_integer = first.m_object->m_value.number_integer;
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ m_value.number_unsigned = first.m_object->m_value.number_unsigned;
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ m_value.number_float = first.m_object->m_value.number_float;
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ m_value.boolean = first.m_object->m_value.boolean;
+ break;
+ }
+
+ case value_t::string:
+ {
+ m_value = *first.m_object->m_value.string;
+ break;
+ }
+
+ case value_t::object:
+ {
+ m_value.object = create<object_t>(first.m_it.object_iterator,
+ last.m_it.object_iterator);
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_value.array = create<array_t>(first.m_it.array_iterator,
+ last.m_it.array_iterator);
+ break;
+ }
+
+ case value_t::binary:
+ {
+ m_value = *first.m_object->m_value.binary;
+ break;
+ }
+
+ case value_t::null:
+ case value_t::discarded:
+ default:
+ JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), *first.m_object));
+ }
+
+ set_parents();
+ assert_invariant();
+ }
+
+
+ ///////////////////////////////////////
+ // other constructors and destructor //
+ ///////////////////////////////////////
+
+ template<typename JsonRef,
+ detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
+ std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
+ basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
+
+ /*!
+ @brief copy constructor
+
+ Creates a copy of a given JSON value.
+
+ @param[in] other the JSON value to copy
+
+ @post `*this == other`
+
+ @complexity Linear in the size of @a other.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes to any JSON value.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is linear.
+ - As postcondition, it holds: `other == basic_json(other)`.
+
+ @liveexample{The following code shows an example for the copy
+ constructor.,basic_json__basic_json}
+
+ @since version 1.0.0
+ */
+ basic_json(const basic_json& other)
+ : m_type(other.m_type)
+ {
+ // check of passed value is valid
+ other.assert_invariant();
+
+ switch (m_type)
+ {
+ case value_t::object:
+ {
+ m_value = *other.m_value.object;
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_value = *other.m_value.array;
+ break;
+ }
+
+ case value_t::string:
+ {
+ m_value = *other.m_value.string;
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ m_value = other.m_value.boolean;
+ break;
+ }
+
+ case value_t::number_integer:
+ {
+ m_value = other.m_value.number_integer;
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ m_value = other.m_value.number_unsigned;
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ m_value = other.m_value.number_float;
+ break;
+ }
+
+ case value_t::binary:
+ {
+ m_value = *other.m_value.binary;
+ break;
+ }
+
+ case value_t::null:
+ case value_t::discarded:
+ default:
+ break;
+ }
+
+ set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief move constructor
+
+ Move constructor. Constructs a JSON value with the contents of the given
+ value @a other using move semantics. It "steals" the resources from @a
+ other and leaves it as JSON null value.
+
+ @param[in,out] other value to move to this object
+
+ @post `*this` has the same value as @a other before the call.
+ @post @a other is a JSON null value.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this constructor never throws
+ exceptions.
+
+ @requirement This function helps `basic_json` satisfying the
+ [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible)
+ requirements.
+
+ @liveexample{The code below shows the move constructor explicitly called
+ via std::move.,basic_json__moveconstructor}
+
+ @since version 1.0.0
+ */
+ basic_json(basic_json&& other) noexcept
+ : m_type(std::move(other.m_type)),
+ m_value(std::move(other.m_value))
+ {
+ // check that passed value is valid
+ other.assert_invariant(false);
+
+ // invalidate payload
+ other.m_type = value_t::null;
+ other.m_value = {};
+
+ set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief copy assignment
+
+ Copy assignment operator. Copies a JSON value via the "copy and swap"
+ strategy: It is expressed in terms of the copy constructor, destructor,
+ and the `swap()` member function.
+
+ @param[in] other value to copy from
+
+ @complexity Linear.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is linear.
+
+ @liveexample{The code below shows and example for the copy assignment. It
+ creates a copy of value `a` which is then swapped with `b`. Finally\, the
+ copy of `a` (which is the null value after the swap) is
+ destroyed.,basic_json__copyassignment}
+
+ @since version 1.0.0
+ */
+ basic_json& operator=(basic_json other) noexcept (
+ std::is_nothrow_move_constructible<value_t>::value&&
+ std::is_nothrow_move_assignable<value_t>::value&&
+ std::is_nothrow_move_constructible<json_value>::value&&
+ std::is_nothrow_move_assignable<json_value>::value
+ )
+ {
+ // check that passed value is valid
+ other.assert_invariant();
+
+ using std::swap;
+ swap(m_type, other.m_type);
+ swap(m_value, other.m_value);
+
+ set_parents();
+ assert_invariant();
+ return *this;
+ }
+
+ /*!
+ @brief destructor
+
+ Destroys the JSON value and frees all allocated memory.
+
+ @complexity Linear.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is linear.
+ - All stored elements are destroyed and all memory is freed.
+
+ @since version 1.0.0
+ */
+ ~basic_json() noexcept
+ {
+ assert_invariant(false);
+ m_value.destroy(m_type);
+ }
+
+ /// @}
+
+ public:
+ ///////////////////////
+ // object inspection //
+ ///////////////////////
+
+ /// @name object inspection
+ /// Functions to inspect the type of a JSON value.
+ /// @{
+
+ /*!
+ @brief serialization
+
+ Serialization function for JSON values. The function tries to mimic
+ Python's `json.dumps()` function, and currently supports its @a indent
+ and @a ensure_ascii parameters.
+
+ @param[in] indent If indent is nonnegative, then array elements and object
+ members will be pretty-printed with that indent level. An indent level of
+ `0` will only insert newlines. `-1` (the default) selects the most compact
+ representation.
+ @param[in] indent_char The character to use for indentation if @a indent is
+ greater than `0`. The default is ` ` (space).
+ @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
+ in the output are escaped with `\uXXXX` sequences, and the result consists
+ of ASCII characters only.
+ @param[in] error_handler how to react on decoding errors; there are three
+ possible values: `strict` (throws and exception in case a decoding error
+ occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
+ and `ignore` (ignore invalid UTF-8 sequences during serialization; all
+ bytes are copied to the output unchanged).
+
+ @return string containing the serialization of the JSON value
+
+ @throw type_error.316 if a string stored inside the JSON value is not
+ UTF-8 encoded and @a error_handler is set to strict
+
+ @note Binary values are serialized as object containing two keys:
+ - "bytes": an array of bytes as integers
+ - "subtype": the subtype as integer or "null" if the binary has no subtype
+
+ @complexity Linear.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @liveexample{The following example shows the effect of different @a indent\,
+ @a indent_char\, and @a ensure_ascii parameters to the result of the
+ serialization.,dump}
+
+ @see https://docs.python.org/2/library/json.html#json.dump
+
+ @since version 1.0.0; indentation character @a indent_char, option
+ @a ensure_ascii and exceptions added in version 3.0.0; error
+ handlers added in version 3.4.0; serialization of binary values added
+ in version 3.8.0.
+ */
+ string_t dump(const int indent = -1,
+ const char indent_char = ' ',
+ const bool ensure_ascii = false,
+ const error_handler_t error_handler = error_handler_t::strict) const
+ {
+ string_t result;
+ serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
+
+ if (indent >= 0)
+ {
+ s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
+ }
+ else
+ {
+ s.dump(*this, false, ensure_ascii, 0);
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief return the type of the JSON value (explicit)
+
+ Return the type of the JSON value as a value from the @ref value_t
+ enumeration.
+
+ @return the type of the JSON value
+ Value type | return value
+ ------------------------- | -------------------------
+ null | value_t::null
+ boolean | value_t::boolean
+ string | value_t::string
+ number (integer) | value_t::number_integer
+ number (unsigned integer) | value_t::number_unsigned
+ number (floating-point) | value_t::number_float
+ object | value_t::object
+ array | value_t::array
+ binary | value_t::binary
+ discarded | value_t::discarded
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `type()` for all JSON
+ types.,type}
+
+ @sa see @ref operator value_t() -- return the type of the JSON value (implicit)
+ @sa see @ref type_name() -- return the type as string
+
+ @since version 1.0.0
+ */
+ constexpr value_t type() const noexcept
+ {
+ return m_type;
+ }
+
+ /*!
+ @brief return whether type is primitive
+
+ This function returns true if and only if the JSON type is primitive
+ (string, number, boolean, or null).
+
+ @return `true` if type is primitive (string, number, boolean, or null),
+ `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_primitive()` for all JSON
+ types.,is_primitive}
+
+ @sa see @ref is_structured() -- returns whether JSON value is structured
+ @sa see @ref is_null() -- returns whether JSON value is `null`
+ @sa see @ref is_string() -- returns whether JSON value is a string
+ @sa see @ref is_boolean() -- returns whether JSON value is a boolean
+ @sa see @ref is_number() -- returns whether JSON value is a number
+ @sa see @ref is_binary() -- returns whether JSON value is a binary array
+
+ @since version 1.0.0
+ */
+ constexpr bool is_primitive() const noexcept
+ {
+ return is_null() || is_string() || is_boolean() || is_number() || is_binary();
+ }
+
+ /*!
+ @brief return whether type is structured
+
+ This function returns true if and only if the JSON type is structured
+ (array or object).
+
+ @return `true` if type is structured (array or object), `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_structured()` for all JSON
+ types.,is_structured}
+
+ @sa see @ref is_primitive() -- returns whether value is primitive
+ @sa see @ref is_array() -- returns whether value is an array
+ @sa see @ref is_object() -- returns whether value is an object
+
+ @since version 1.0.0
+ */
+ constexpr bool is_structured() const noexcept
+ {
+ return is_array() || is_object();
+ }
+
+ /*!
+ @brief return whether value is null
+
+ This function returns true if and only if the JSON value is null.
+
+ @return `true` if type is null, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_null()` for all JSON
+ types.,is_null}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_null() const noexcept
+ {
+ return m_type == value_t::null;
+ }
+
+ /*!
+ @brief return whether value is a boolean
+
+ This function returns true if and only if the JSON value is a boolean.
+
+ @return `true` if type is boolean, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_boolean()` for all JSON
+ types.,is_boolean}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_boolean() const noexcept
+ {
+ return m_type == value_t::boolean;
+ }
+
+ /*!
+ @brief return whether value is a number
+
+ This function returns true if and only if the JSON value is a number. This
+ includes both integer (signed and unsigned) and floating-point values.
+
+ @return `true` if type is number (regardless whether integer, unsigned
+ integer or floating-type), `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number()` for all JSON
+ types.,is_number}
+
+ @sa see @ref is_number_integer() -- check if value is an integer or unsigned
+ integer number
+ @sa see @ref is_number_unsigned() -- check if value is an unsigned integer
+ number
+ @sa see @ref is_number_float() -- check if value is a floating-point number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_number() const noexcept
+ {
+ return is_number_integer() || is_number_float();
+ }
+
+ /*!
+ @brief return whether value is an integer number
+
+ This function returns true if and only if the JSON value is a signed or
+ unsigned integer number. This excludes floating-point values.
+
+ @return `true` if type is an integer or unsigned integer number, `false`
+ otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number_integer()` for all
+ JSON types.,is_number_integer}
+
+ @sa see @ref is_number() -- check if value is a number
+ @sa see @ref is_number_unsigned() -- check if value is an unsigned integer
+ number
+ @sa see @ref is_number_float() -- check if value is a floating-point number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_number_integer() const noexcept
+ {
+ return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
+ }
+
+ /*!
+ @brief return whether value is an unsigned integer number
+
+ This function returns true if and only if the JSON value is an unsigned
+ integer number. This excludes floating-point and signed integer values.
+
+ @return `true` if type is an unsigned integer number, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number_unsigned()` for all
+ JSON types.,is_number_unsigned}
+
+ @sa see @ref is_number() -- check if value is a number
+ @sa see @ref is_number_integer() -- check if value is an integer or unsigned
+ integer number
+ @sa see @ref is_number_float() -- check if value is a floating-point number
+
+ @since version 2.0.0
+ */
+ constexpr bool is_number_unsigned() const noexcept
+ {
+ return m_type == value_t::number_unsigned;
+ }
+
+ /*!
+ @brief return whether value is a floating-point number
+
+ This function returns true if and only if the JSON value is a
+ floating-point number. This excludes signed and unsigned integer values.
+
+ @return `true` if type is a floating-point number, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_number_float()` for all
+ JSON types.,is_number_float}
+
+ @sa see @ref is_number() -- check if value is number
+ @sa see @ref is_number_integer() -- check if value is an integer number
+ @sa see @ref is_number_unsigned() -- check if value is an unsigned integer
+ number
+
+ @since version 1.0.0
+ */
+ constexpr bool is_number_float() const noexcept
+ {
+ return m_type == value_t::number_float;
+ }
+
+ /*!
+ @brief return whether value is an object
+
+ This function returns true if and only if the JSON value is an object.
+
+ @return `true` if type is object, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_object()` for all JSON
+ types.,is_object}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_object() const noexcept
+ {
+ return m_type == value_t::object;
+ }
+
+ /*!
+ @brief return whether value is an array
+
+ This function returns true if and only if the JSON value is an array.
+
+ @return `true` if type is array, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_array()` for all JSON
+ types.,is_array}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_array() const noexcept
+ {
+ return m_type == value_t::array;
+ }
+
+ /*!
+ @brief return whether value is a string
+
+ This function returns true if and only if the JSON value is a string.
+
+ @return `true` if type is string, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_string()` for all JSON
+ types.,is_string}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_string() const noexcept
+ {
+ return m_type == value_t::string;
+ }
+
+ /*!
+ @brief return whether value is a binary array
+
+ This function returns true if and only if the JSON value is a binary array.
+
+ @return `true` if type is binary array, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_binary()` for all JSON
+ types.,is_binary}
+
+ @since version 3.8.0
+ */
+ constexpr bool is_binary() const noexcept
+ {
+ return m_type == value_t::binary;
+ }
+
+ /*!
+ @brief return whether value is discarded
+
+ This function returns true if and only if the JSON value was discarded
+ during parsing with a callback function (see @ref parser_callback_t).
+
+ @note This function will always be `false` for JSON values after parsing.
+ That is, discarded values can only occur during parsing, but will be
+ removed when inside a structured value or replaced by null in other cases.
+
+ @return `true` if type is discarded, `false` otherwise.
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies `is_discarded()` for all JSON
+ types.,is_discarded}
+
+ @since version 1.0.0
+ */
+ constexpr bool is_discarded() const noexcept
+ {
+ return m_type == value_t::discarded;
+ }
+
+ /*!
+ @brief return the type of the JSON value (implicit)
+
+ Implicitly return the type of the JSON value as a value from the @ref
+ value_t enumeration.
+
+ @return the type of the JSON value
+
+ @complexity Constant.
+
+ @exceptionsafety No-throw guarantee: this member function never throws
+ exceptions.
+
+ @liveexample{The following code exemplifies the @ref value_t operator for
+ all JSON types.,operator__value_t}
+
+ @sa see @ref type() -- return the type of the JSON value (explicit)
+ @sa see @ref type_name() -- return the type as string
+
+ @since version 1.0.0
+ */
+ constexpr operator value_t() const noexcept
+ {
+ return m_type;
+ }
+
+ /// @}
+
+ private:
+ //////////////////
+ // value access //
+ //////////////////
+
+ /// get a boolean (explicit)
+ boolean_t get_impl(boolean_t* /*unused*/) const
+ {
+ if (JSON_HEDLEY_LIKELY(is_boolean()))
+ {
+ return m_value.boolean;
+ }
+
+ JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this));
+ }
+
+ /// get a pointer to the value (object)
+ object_t* get_impl_ptr(object_t* /*unused*/) noexcept
+ {
+ return is_object() ? m_value.object : nullptr;
+ }
+
+ /// get a pointer to the value (object)
+ constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
+ {
+ return is_object() ? m_value.object : nullptr;
+ }
+
+ /// get a pointer to the value (array)
+ array_t* get_impl_ptr(array_t* /*unused*/) noexcept
+ {
+ return is_array() ? m_value.array : nullptr;
+ }
+
+ /// get a pointer to the value (array)
+ constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
+ {
+ return is_array() ? m_value.array : nullptr;
+ }
+
+ /// get a pointer to the value (string)
+ string_t* get_impl_ptr(string_t* /*unused*/) noexcept
+ {
+ return is_string() ? m_value.string : nullptr;
+ }
+
+ /// get a pointer to the value (string)
+ constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
+ {
+ return is_string() ? m_value.string : nullptr;
+ }
+
+ /// get a pointer to the value (boolean)
+ boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
+ {
+ return is_boolean() ? &m_value.boolean : nullptr;
+ }
+
+ /// get a pointer to the value (boolean)
+ constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
+ {
+ return is_boolean() ? &m_value.boolean : nullptr;
+ }
+
+ /// get a pointer to the value (integer number)
+ number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
+ {
+ return is_number_integer() ? &m_value.number_integer : nullptr;
+ }
+
+ /// get a pointer to the value (integer number)
+ constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
+ {
+ return is_number_integer() ? &m_value.number_integer : nullptr;
+ }
+
+ /// get a pointer to the value (unsigned number)
+ number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
+ {
+ return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+ }
+
+ /// get a pointer to the value (unsigned number)
+ constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
+ {
+ return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
+ }
+
+ /// get a pointer to the value (floating-point number)
+ number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
+ {
+ return is_number_float() ? &m_value.number_float : nullptr;
+ }
+
+ /// get a pointer to the value (floating-point number)
+ constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
+ {
+ return is_number_float() ? &m_value.number_float : nullptr;
+ }
+
+ /// get a pointer to the value (binary)
+ binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
+ {
+ return is_binary() ? m_value.binary : nullptr;
+ }
+
+ /// get a pointer to the value (binary)
+ constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
+ {
+ return is_binary() ? m_value.binary : nullptr;
+ }
+
+ /*!
+ @brief helper function to implement get_ref()
+
+ This function helps to implement get_ref() without code duplication for
+ const and non-const overloads
+
+ @tparam ThisType will be deduced as `basic_json` or `const basic_json`
+
+ @throw type_error.303 if ReferenceType does not match underlying value
+ type of the current JSON
+ */
+ template<typename ReferenceType, typename ThisType>
+ static ReferenceType get_ref_impl(ThisType& obj)
+ {
+ // delegate the call to get_ptr<>()
+ auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
+
+ if (JSON_HEDLEY_LIKELY(ptr != nullptr))
+ {
+ return *ptr;
+ }
+
+ JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj));
+ }
+
+ public:
+ /// @name value access
+ /// Direct access to the stored value of a JSON value.
+ /// @{
+
+ /*!
+ @brief get a pointer value (implicit)
+
+ Implicit pointer access to the internally stored JSON value. No copies are
+ made.
+
+ @warning Writing data to the pointee of the result yields an undefined
+ state.
+
+ @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+ object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+ @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
+ assertion.
+
+ @return pointer to the internally stored JSON value if the requested
+ pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how pointers to internal values of a
+ JSON value can be requested. Note that no type conversions are made and a
+ `nullptr` is returned if the value and the requested pointer type does not
+ match.,get_ptr}
+
+ @since version 1.0.0
+ */
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
+ auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+ {
+ // delegate the call to get_impl_ptr<>()
+ return get_impl_ptr(static_cast<PointerType>(nullptr));
+ }
+
+ /*!
+ @brief get a pointer value (implicit)
+ @copydoc get_ptr()
+ */
+ template < typename PointerType, typename std::enable_if <
+ std::is_pointer<PointerType>::value&&
+ std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
+ constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
+ {
+ // delegate the call to get_impl_ptr<>() const
+ return get_impl_ptr(static_cast<PointerType>(nullptr));
+ }
+
+ private:
+ /*!
+ @brief get a value (explicit)
+
+ Explicit type conversion between the JSON value and a compatible value
+ which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+ and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+ The value is converted by calling the @ref json_serializer<ValueType>
+ `from_json()` method.
+
+ The function is equivalent to executing
+ @code {.cpp}
+ ValueType ret;
+ JSONSerializer<ValueType>::from_json(*this, ret);
+ return ret;
+ @endcode
+
+ This overloads is chosen if:
+ - @a ValueType is not @ref basic_json,
+ - @ref json_serializer<ValueType> has a `from_json()` method of the form
+ `void from_json(const basic_json&, ValueType&)`, and
+ - @ref json_serializer<ValueType> does not have a `from_json()` method of
+ the form `ValueType from_json(const basic_json&)`
+
+ @tparam ValueType the returned value type
+
+ @return copy of the JSON value, converted to @a ValueType
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+ @liveexample{The example below shows several conversions from JSON values
+ to other types. There a few things to note: (1) Floating-point numbers can
+ be converted to integers\, (2) A JSON array can be converted to a standard
+ `std::vector<short>`\, (3) A JSON object can be converted to C++
+ associative containers such as `std::unordered_map<std::string\,
+ json>`.,get__ValueType_const}
+
+ @since version 2.1.0
+ */
+ template < typename ValueType,
+ detail::enable_if_t <
+ detail::is_default_constructible<ValueType>::value&&
+ detail::has_from_json<basic_json_t, ValueType>::value,
+ int > = 0 >
+ ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
+ JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
+ {
+ auto ret = ValueType();
+ JSONSerializer<ValueType>::from_json(*this, ret);
+ return ret;
+ }
+
+ /*!
+ @brief get a value (explicit); special case
+
+ Explicit type conversion between the JSON value and a compatible value
+ which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
+ and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
+ The value is converted by calling the @ref json_serializer<ValueType>
+ `from_json()` method.
+
+ The function is equivalent to executing
+ @code {.cpp}
+ return JSONSerializer<ValueType>::from_json(*this);
+ @endcode
+
+ This overloads is chosen if:
+ - @a ValueType is not @ref basic_json and
+ - @ref json_serializer<ValueType> has a `from_json()` method of the form
+ `ValueType from_json(const basic_json&)`
+
+ @note If @ref json_serializer<ValueType> has both overloads of
+ `from_json()`, this one is chosen.
+
+ @tparam ValueType the returned value type
+
+ @return copy of the JSON value, converted to @a ValueType
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+ @since version 2.1.0
+ */
+ template < typename ValueType,
+ detail::enable_if_t <
+ detail::has_non_default_from_json<basic_json_t, ValueType>::value,
+ int > = 0 >
+ ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
+ JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
+ {
+ return JSONSerializer<ValueType>::from_json(*this);
+ }
+
+ /*!
+ @brief get special-case overload
+
+ This overloads converts the current @ref basic_json in a different
+ @ref basic_json type
+
+ @tparam BasicJsonType == @ref basic_json
+
+ @return a copy of *this, converted into @a BasicJsonType
+
+ @complexity Depending on the implementation of the called `from_json()`
+ method.
+
+ @since version 3.2.0
+ */
+ template < typename BasicJsonType,
+ detail::enable_if_t <
+ detail::is_basic_json<BasicJsonType>::value,
+ int > = 0 >
+ BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
+ {
+ return *this;
+ }
+
+ /*!
+ @brief get special-case overload
+
+ This overloads avoids a lot of template boilerplate, it can be seen as the
+ identity method
+
+ @tparam BasicJsonType == @ref basic_json
+
+ @return a copy of *this
+
+ @complexity Constant.
+
+ @since version 2.1.0
+ */
+ template<typename BasicJsonType,
+ detail::enable_if_t<
+ std::is_same<BasicJsonType, basic_json_t>::value,
+ int> = 0>
+ basic_json get_impl(detail::priority_tag<3> /*unused*/) const
+ {
+ return *this;
+ }
+
+ /*!
+ @brief get a pointer value (explicit)
+ @copydoc get()
+ */
+ template<typename PointerType,
+ detail::enable_if_t<
+ std::is_pointer<PointerType>::value,
+ int> = 0>
+ constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
+ -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
+ {
+ // delegate the call to get_ptr
+ return get_ptr<PointerType>();
+ }
+
+ public:
+ /*!
+ @brief get a (pointer) value (explicit)
+
+ Performs explicit type conversion between the JSON value and a compatible value if required.
+
+ - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
+ No copies are made.
+
+ - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
+ from the current @ref basic_json.
+
+ - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
+ method.
+
+ @tparam ValueTypeCV the provided value type
+ @tparam ValueType the returned value type
+
+ @return copy of the JSON value, converted to @tparam ValueType if necessary
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
+
+ @since version 2.1.0
+ */
+ template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
+#if defined(JSON_HAS_CPP_14)
+ constexpr
+#endif
+ auto get() const noexcept(
+ noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
+ -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
+ {
+ // we cannot static_assert on ValueTypeCV being non-const, because
+ // there is support for get<const basic_json_t>(), which is why we
+ // still need the uncvref
+ static_assert(!std::is_reference<ValueTypeCV>::value,
+ "get() cannot be used with reference types, you might want to use get_ref()");
+ return get_impl<ValueType>(detail::priority_tag<4> {});
+ }
+
+ /*!
+ @brief get a pointer value (explicit)
+
+ Explicit pointer access to the internally stored JSON value. No copies are
+ made.
+
+ @warning The pointer becomes invalid if the underlying JSON object
+ changes.
+
+ @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
+ object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
+ @ref number_unsigned_t, or @ref number_float_t.
+
+ @return pointer to the internally stored JSON value if the requested
+ pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how pointers to internal values of a
+ JSON value can be requested. Note that no type conversions are made and a
+ `nullptr` is returned if the value and the requested pointer type does not
+ match.,get__PointerType}
+
+ @sa see @ref get_ptr() for explicit pointer-member access
+
+ @since version 1.0.0
+ */
+ template<typename PointerType, typename std::enable_if<
+ std::is_pointer<PointerType>::value, int>::type = 0>
+ auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
+ {
+ // delegate the call to get_ptr
+ return get_ptr<PointerType>();
+ }
+
+ /*!
+ @brief get a value (explicit)
+
+ Explicit type conversion between the JSON value and a compatible value.
+ The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
+ `from_json()` method.
+
+ The function is equivalent to executing
+ @code {.cpp}
+ ValueType v;
+ JSONSerializer<ValueType>::from_json(*this, v);
+ @endcode
+
+ This overloads is chosen if:
+ - @a ValueType is not @ref basic_json,
+ - @ref json_serializer<ValueType> has a `from_json()` method of the form
+ `void from_json(const basic_json&, ValueType&)`, and
+
+ @tparam ValueType the input parameter type.
+
+ @return the input parameter, allowing chaining calls.
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+ @liveexample{The example below shows several conversions from JSON values
+ to other types. There a few things to note: (1) Floating-point numbers can
+ be converted to integers\, (2) A JSON array can be converted to a standard
+ `std::vector<short>`\, (3) A JSON object can be converted to C++
+ associative containers such as `std::unordered_map<std::string\,
+ json>`.,get_to}
+
+ @since version 3.3.0
+ */
+ template < typename ValueType,
+ detail::enable_if_t <
+ !detail::is_basic_json<ValueType>::value&&
+ detail::has_from_json<basic_json_t, ValueType>::value,
+ int > = 0 >
+ ValueType & get_to(ValueType& v) const noexcept(noexcept(
+ JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
+ {
+ JSONSerializer<ValueType>::from_json(*this, v);
+ return v;
+ }
+
+ // specialization to allow to call get_to with a basic_json value
+ // see https://github.com/nlohmann/json/issues/2175
+ template<typename ValueType,
+ detail::enable_if_t <
+ detail::is_basic_json<ValueType>::value,
+ int> = 0>
+ ValueType & get_to(ValueType& v) const
+ {
+ v = *this;
+ return v;
+ }
+
+ template <
+ typename T, std::size_t N,
+ typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ detail::enable_if_t <
+ detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
+ Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
+ noexcept(noexcept(JSONSerializer<Array>::from_json(
+ std::declval<const basic_json_t&>(), v)))
+ {
+ JSONSerializer<Array>::from_json(*this, v);
+ return v;
+ }
+
+ /*!
+ @brief get a reference value (implicit)
+
+ Implicit reference access to the internally stored JSON value. No copies
+ are made.
+
+ @warning Writing data to the referee of the result yields an undefined
+ state.
+
+ @tparam ReferenceType reference type; must be a reference to @ref array_t,
+ @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or
+ @ref number_float_t. Enforced by static assertion.
+
+ @return reference to the internally stored JSON value if the requested
+ reference type @a ReferenceType fits to the JSON value; throws
+ type_error.303 otherwise
+
+ @throw type_error.303 in case passed type @a ReferenceType is incompatible
+ with the stored JSON value; see example below
+
+ @complexity Constant.
+
+ @liveexample{The example shows several calls to `get_ref()`.,get_ref}
+
+ @since version 1.1.0
+ */
+ template<typename ReferenceType, typename std::enable_if<
+ std::is_reference<ReferenceType>::value, int>::type = 0>
+ ReferenceType get_ref()
+ {
+ // delegate call to get_ref_impl
+ return get_ref_impl<ReferenceType>(*this);
+ }
+
+ /*!
+ @brief get a reference value (implicit)
+ @copydoc get_ref()
+ */
+ template < typename ReferenceType, typename std::enable_if <
+ std::is_reference<ReferenceType>::value&&
+ std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
+ ReferenceType get_ref() const
+ {
+ // delegate call to get_ref_impl
+ return get_ref_impl<ReferenceType>(*this);
+ }
+
+ /*!
+ @brief get a value (implicit)
+
+ Implicit type conversion between the JSON value and a compatible value.
+ The call is realized by calling @ref get() const.
+
+ @tparam ValueType non-pointer type compatible to the JSON value, for
+ instance `int` for JSON integer numbers, `bool` for JSON booleans, or
+ `std::vector` types for JSON arrays. The character type of @ref string_t
+ as well as an initializer list of this type is excluded to avoid
+ ambiguities as these types implicitly convert to `std::string`.
+
+ @return copy of the JSON value, converted to type @a ValueType
+
+ @throw type_error.302 in case passed type @a ValueType is incompatible
+ to the JSON value type (e.g., the JSON value is of type boolean, but a
+ string is requested); see example below
+
+ @complexity Linear in the size of the JSON value.
+
+ @liveexample{The example below shows several conversions from JSON values
+ to other types. There a few things to note: (1) Floating-point numbers can
+ be converted to integers\, (2) A JSON array can be converted to a standard
+ `std::vector<short>`\, (3) A JSON object can be converted to C++
+ associative containers such as `std::unordered_map<std::string\,
+ json>`.,operator__ValueType}
+
+ @since version 1.0.0
+ */
+ template < typename ValueType, typename std::enable_if <
+ detail::conjunction <
+ detail::negation<std::is_pointer<ValueType>>,
+ detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
+ detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
+ detail::negation<detail::is_basic_json<ValueType>>,
+ detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
+
+#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
+ detail::negation<std::is_same<ValueType, std::string_view>>,
+#endif
+ detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
+ >::value, int >::type = 0 >
+ JSON_EXPLICIT operator ValueType() const
+ {
+ // delegate the call to get<>() const
+ return get<ValueType>();
+ }
+
+ /*!
+ @return reference to the binary value
+
+ @throw type_error.302 if the value is not binary
+
+ @sa see @ref is_binary() to check if the value is binary
+
+ @since version 3.8.0
+ */
+ binary_t& get_binary()
+ {
+ if (!is_binary())
+ {
+ JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+ }
+
+ return *get_ptr<binary_t*>();
+ }
+
+ /// @copydoc get_binary()
+ const binary_t& get_binary() const
+ {
+ if (!is_binary())
+ {
+ JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this));
+ }
+
+ return *get_ptr<const binary_t*>();
+ }
+
+ /// @}
+
+
+ ////////////////////
+ // element access //
+ ////////////////////
+
+ /// @name element access
+ /// Access to the JSON value.
+ /// @{
+
+ /*!
+ @brief access specified array element with bounds checking
+
+ Returns a reference to the element at specified location @a idx, with
+ bounds checking.
+
+ @param[in] idx index of the element to access
+
+ @return reference to the element at index @a idx
+
+ @throw type_error.304 if the JSON value is not an array; in this case,
+ calling `at` with an index makes no sense. See example below.
+ @throw out_of_range.401 if the index @a idx is out of range of the array;
+ that is, `idx >= size()`. See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
+ @since version 1.0.0
+
+ @liveexample{The example below shows how array elements can be read and
+ written using `at()`. It also demonstrates the different exceptions that
+ can be thrown.,at__size_type}
+ */
+ reference at(size_type idx)
+ {
+ // at only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ JSON_TRY
+ {
+ return set_parent(m_value.array->at(idx));
+ }
+ JSON_CATCH (std::out_of_range&)
+ {
+ // create better exception explanation
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ }
+ }
+ else
+ {
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief access specified array element with bounds checking
+
+ Returns a const reference to the element at specified location @a idx,
+ with bounds checking.
+
+ @param[in] idx index of the element to access
+
+ @return const reference to the element at index @a idx
+
+ @throw type_error.304 if the JSON value is not an array; in this case,
+ calling `at` with an index makes no sense. See example below.
+ @throw out_of_range.401 if the index @a idx is out of range of the array;
+ that is, `idx >= size()`. See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
+ @since version 1.0.0
+
+ @liveexample{The example below shows how array elements can be read using
+ `at()`. It also demonstrates the different exceptions that can be thrown.,
+ at__size_type_const}
+ */
+ const_reference at(size_type idx) const
+ {
+ // at only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ JSON_TRY
+ {
+ return m_value.array->at(idx);
+ }
+ JSON_CATCH (std::out_of_range&)
+ {
+ // create better exception explanation
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ }
+ }
+ else
+ {
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief access specified object element with bounds checking
+
+ Returns a reference to the element at with specified key @a key, with
+ bounds checking.
+
+ @param[in] key key of the element to access
+
+ @return reference to the element at key @a key
+
+ @throw type_error.304 if the JSON value is not an object; in this case,
+ calling `at` with a key makes no sense. See example below.
+ @throw out_of_range.403 if the key @a key is is not stored in the object;
+ that is, `find(key) == end()`. See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Logarithmic in the size of the container.
+
+ @sa see @ref operator[](const typename object_t::key_type&) for unchecked
+ access by reference
+ @sa see @ref value() for access by value with a default value
+
+ @since version 1.0.0
+
+ @liveexample{The example below shows how object elements can be read and
+ written using `at()`. It also demonstrates the different exceptions that
+ can be thrown.,at__object_t_key_type}
+ */
+ reference at(const typename object_t::key_type& key)
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ JSON_TRY
+ {
+ return set_parent(m_value.object->at(key));
+ }
+ JSON_CATCH (std::out_of_range&)
+ {
+ // create better exception explanation
+ JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
+ }
+ }
+ else
+ {
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief access specified object element with bounds checking
+
+ Returns a const reference to the element at with specified key @a key,
+ with bounds checking.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @throw type_error.304 if the JSON value is not an object; in this case,
+ calling `at` with a key makes no sense. See example below.
+ @throw out_of_range.403 if the key @a key is is not stored in the object;
+ that is, `find(key) == end()`. See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Logarithmic in the size of the container.
+
+ @sa see @ref operator[](const typename object_t::key_type&) for unchecked
+ access by reference
+ @sa see @ref value() for access by value with a default value
+
+ @since version 1.0.0
+
+ @liveexample{The example below shows how object elements can be read using
+ `at()`. It also demonstrates the different exceptions that can be thrown.,
+ at__object_t_key_type_const}
+ */
+ const_reference at(const typename object_t::key_type& key) const
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ JSON_TRY
+ {
+ return m_value.object->at(key);
+ }
+ JSON_CATCH (std::out_of_range&)
+ {
+ // create better exception explanation
+ JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this));
+ }
+ }
+ else
+ {
+ JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief access specified array element
+
+ Returns a reference to the element at specified location @a idx.
+
+ @note If @a idx is beyond the range of the array (i.e., `idx >= size()`),
+ then the array is silently filled up with `null` values to make `idx` a
+ valid reference to the last stored element.
+
+ @param[in] idx index of the element to access
+
+ @return reference to the element at index @a idx
+
+ @throw type_error.305 if the JSON value is not an array or null; in that
+ cases, using the [] operator with an index makes no sense.
+
+ @complexity Constant if @a idx is in the range of the array. Otherwise
+ linear in `idx - size()`.
+
+ @liveexample{The example below shows how array elements can be read and
+ written using `[]` operator. Note the addition of `null`
+ values.,operatorarray__size_type}
+
+ @since version 1.0.0
+ */
+ reference operator[](size_type idx)
+ {
+ // implicitly convert null value to an empty array
+ if (is_null())
+ {
+ m_type = value_t::array;
+ m_value.array = create<array_t>();
+ assert_invariant();
+ }
+
+ // operator[] only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ // fill up array with null values if given idx is outside range
+ if (idx >= m_value.array->size())
+ {
+#if JSON_DIAGNOSTICS
+ // remember array size & capacity before resizing
+ const auto old_size = m_value.array->size();
+ const auto old_capacity = m_value.array->capacity();
+#endif
+ m_value.array->resize(idx + 1);
+
+#if JSON_DIAGNOSTICS
+ if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
+ {
+ // capacity has changed: update all parents
+ set_parents();
+ }
+ else
+ {
+ // set parent for values added above
+ set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
+ }
+#endif
+ assert_invariant();
+ }
+
+ return m_value.array->operator[](idx);
+ }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief access specified array element
+
+ Returns a const reference to the element at specified location @a idx.
+
+ @param[in] idx index of the element to access
+
+ @return const reference to the element at index @a idx
+
+ @throw type_error.305 if the JSON value is not an array; in that case,
+ using the [] operator with an index makes no sense.
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how array elements can be read using
+ the `[]` operator.,operatorarray__size_type_const}
+
+ @since version 1.0.0
+ */
+ const_reference operator[](size_type idx) const
+ {
+ // const operator[] only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ return m_value.array->operator[](idx);
+ }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief access specified object element
+
+ Returns a reference to the element at with specified key @a key.
+
+ @note If @a key is not found in the object, then it is silently added to
+ the object and filled with a `null` value to make `key` a valid reference.
+ In case the value was `null` before, it is converted to an object.
+
+ @param[in] key key of the element to access
+
+ @return reference to the element at key @a key
+
+ @throw type_error.305 if the JSON value is not an object or null; in that
+ cases, using the [] operator with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read and
+ written using the `[]` operator.,operatorarray__key_type}
+
+ @sa see @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa see @ref value() for access by value with a default value
+
+ @since version 1.0.0
+ */
+ reference operator[](const typename object_t::key_type& key)
+ {
+ // implicitly convert null value to an empty object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value.object = create<object_t>();
+ assert_invariant();
+ }
+
+ // operator[] only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ return set_parent(m_value.object->operator[](key));
+ }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief read-only access specified object element
+
+ Returns a const reference to the element at with specified key @a key. No
+ bounds checking is performed.
+
+ @warning If the element with key @a key does not exist, the behavior is
+ undefined.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @pre The element with key @a key must exist. **This precondition is
+ enforced with an assertion.**
+
+ @throw type_error.305 if the JSON value is not an object; in that case,
+ using the [] operator with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read using
+ the `[]` operator.,operatorarray__key_type_const}
+
+ @sa see @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa see @ref value() for access by value with a default value
+
+ @since version 1.0.0
+ */
+ const_reference operator[](const typename object_t::key_type& key) const
+ {
+ // const operator[] only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
+ return m_value.object->find(key)->second;
+ }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief access specified object element
+
+ Returns a reference to the element at with specified key @a key.
+
+ @note If @a key is not found in the object, then it is silently added to
+ the object and filled with a `null` value to make `key` a valid reference.
+ In case the value was `null` before, it is converted to an object.
+
+ @param[in] key key of the element to access
+
+ @return reference to the element at key @a key
+
+ @throw type_error.305 if the JSON value is not an object or null; in that
+ cases, using the [] operator with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read and
+ written using the `[]` operator.,operatorarray__key_type}
+
+ @sa see @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa see @ref value() for access by value with a default value
+
+ @since version 1.1.0
+ */
+ template<typename T>
+ JSON_HEDLEY_NON_NULL(2)
+ reference operator[](T* key)
+ {
+ // implicitly convert null to object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value = value_t::object;
+ assert_invariant();
+ }
+
+ // at only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ return set_parent(m_value.object->operator[](key));
+ }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief read-only access specified object element
+
+ Returns a const reference to the element at with specified key @a key. No
+ bounds checking is performed.
+
+ @warning If the element with key @a key does not exist, the behavior is
+ undefined.
+
+ @param[in] key key of the element to access
+
+ @return const reference to the element at key @a key
+
+ @pre The element with key @a key must exist. **This precondition is
+ enforced with an assertion.**
+
+ @throw type_error.305 if the JSON value is not an object; in that case,
+ using the [] operator with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be read using
+ the `[]` operator.,operatorarray__key_type_const}
+
+ @sa see @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa see @ref value() for access by value with a default value
+
+ @since version 1.1.0
+ */
+ template<typename T>
+ JSON_HEDLEY_NON_NULL(2)
+ const_reference operator[](T* key) const
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ JSON_ASSERT(m_value.object->find(key) != m_value.object->end());
+ return m_value.object->find(key)->second;
+ }
+
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief access specified object element with default value
+
+ Returns either a copy of an object's element at the specified key @a key
+ or a given default value if no element with key @a key exists.
+
+ The function is basically equivalent to executing
+ @code {.cpp}
+ try {
+ return at(key);
+ } catch(out_of_range) {
+ return default_value;
+ }
+ @endcode
+
+ @note Unlike @ref at(const typename object_t::key_type&), this function
+ does not throw if the given key @a key was not found.
+
+ @note Unlike @ref operator[](const typename object_t::key_type& key), this
+ function does not implicitly add an element to the position defined by @a
+ key. This function is furthermore also applicable to const objects.
+
+ @param[in] key key of the element to access
+ @param[in] default_value the value to return if @a key is not found
+
+ @tparam ValueType type compatible to JSON values, for instance `int` for
+ JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+ JSON arrays. Note the type of the expected value at @a key and the default
+ value @a default_value must be compatible.
+
+ @return copy of the element at key @a key or @a default_value if @a key
+ is not found
+
+ @throw type_error.302 if @a default_value does not match the type of the
+ value at @a key
+ @throw type_error.306 if the JSON value is not an object; in that case,
+ using `value()` with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be queried
+ with a default value.,basic_json__value}
+
+ @sa see @ref at(const typename object_t::key_type&) for access by reference
+ with range checking
+ @sa see @ref operator[](const typename object_t::key_type&) for unchecked
+ access by reference
+
+ @since version 1.0.0
+ */
+ // using std::is_convertible in a std::enable_if will fail when using explicit conversions
+ template < class ValueType, typename std::enable_if <
+ detail::is_getable<basic_json_t, ValueType>::value
+ && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
+ ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ // if key is found, return value and given default value otherwise
+ const auto it = find(key);
+ if (it != end())
+ {
+ return it->template get<ValueType>();
+ }
+
+ return default_value;
+ }
+
+ JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief overload for a default value of type const char*
+ @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const
+ */
+ string_t value(const typename object_t::key_type& key, const char* default_value) const
+ {
+ return value(key, string_t(default_value));
+ }
+
+ /*!
+ @brief access specified object element via JSON Pointer with default value
+
+ Returns either a copy of an object's element at the specified key @a key
+ or a given default value if no element with key @a key exists.
+
+ The function is basically equivalent to executing
+ @code {.cpp}
+ try {
+ return at(ptr);
+ } catch(out_of_range) {
+ return default_value;
+ }
+ @endcode
+
+ @note Unlike @ref at(const json_pointer&), this function does not throw
+ if the given key @a key was not found.
+
+ @param[in] ptr a JSON pointer to the element to access
+ @param[in] default_value the value to return if @a ptr found no value
+
+ @tparam ValueType type compatible to JSON values, for instance `int` for
+ JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for
+ JSON arrays. Note the type of the expected value at @a key and the default
+ value @a default_value must be compatible.
+
+ @return copy of the element at key @a key or @a default_value if @a key
+ is not found
+
+ @throw type_error.302 if @a default_value does not match the type of the
+ value at @a ptr
+ @throw type_error.306 if the JSON value is not an object; in that case,
+ using `value()` with a key makes no sense.
+
+ @complexity Logarithmic in the size of the container.
+
+ @liveexample{The example below shows how object elements can be queried
+ with a default value.,basic_json__value_ptr}
+
+ @sa see @ref operator[](const json_pointer&) for unchecked access by reference
+
+ @since version 2.0.2
+ */
+ template<class ValueType, typename std::enable_if<
+ detail::is_getable<basic_json_t, ValueType>::value, int>::type = 0>
+ ValueType value(const json_pointer& ptr, const ValueType& default_value) const
+ {
+ // at only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ // if pointer resolves a value, return it or use default value
+ JSON_TRY
+ {
+ return ptr.get_checked(this).template get<ValueType>();
+ }
+ JSON_INTERNAL_CATCH (out_of_range&)
+ {
+ return default_value;
+ }
+ }
+
+ JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief overload for a default value of type const char*
+ @copydoc basic_json::value(const json_pointer&, ValueType) const
+ */
+ JSON_HEDLEY_NON_NULL(3)
+ string_t value(const json_pointer& ptr, const char* default_value) const
+ {
+ return value(ptr, string_t(default_value));
+ }
+
+ /*!
+ @brief access the first element
+
+ Returns a reference to the first element in the container. For a JSON
+ container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
+
+ @return In case of a structured type (array or object), a reference to the
+ first element is returned. In case of number, string, boolean, or binary
+ values, a reference to the value is returned.
+
+ @complexity Constant.
+
+ @pre The JSON value must not be `null` (would throw `std::out_of_range`)
+ or an empty array or object (undefined behavior, **guarded by
+ assertions**).
+ @post The JSON value remains unchanged.
+
+ @throw invalid_iterator.214 when called on `null` value
+
+ @liveexample{The following code shows an example for `front()`.,front}
+
+ @sa see @ref back() -- access the last element
+
+ @since version 1.0.0
+ */
+ reference front()
+ {
+ return *begin();
+ }
+
+ /*!
+ @copydoc basic_json::front()
+ */
+ const_reference front() const
+ {
+ return *cbegin();
+ }
+
+ /*!
+ @brief access the last element
+
+ Returns a reference to the last element in the container. For a JSON
+ container `c`, the expression `c.back()` is equivalent to
+ @code {.cpp}
+ auto tmp = c.end();
+ --tmp;
+ return *tmp;
+ @endcode
+
+ @return In case of a structured type (array or object), a reference to the
+ last element is returned. In case of number, string, boolean, or binary
+ values, a reference to the value is returned.
+
+ @complexity Constant.
+
+ @pre The JSON value must not be `null` (would throw `std::out_of_range`)
+ or an empty array or object (undefined behavior, **guarded by
+ assertions**).
+ @post The JSON value remains unchanged.
+
+ @throw invalid_iterator.214 when called on a `null` value. See example
+ below.
+
+ @liveexample{The following code shows an example for `back()`.,back}
+
+ @sa see @ref front() -- access the first element
+
+ @since version 1.0.0
+ */
+ reference back()
+ {
+ auto tmp = end();
+ --tmp;
+ return *tmp;
+ }
+
+ /*!
+ @copydoc basic_json::back()
+ */
+ const_reference back() const
+ {
+ auto tmp = cend();
+ --tmp;
+ return *tmp;
+ }
+
+ /*!
+ @brief remove element given an iterator
+
+ Removes the element specified by iterator @a pos. The iterator @a pos must
+ be valid and dereferenceable. Thus the `end()` iterator (which is valid,
+ but is not dereferenceable) cannot be used as a value for @a pos.
+
+ If called on a primitive type other than `null`, the resulting JSON value
+ will be `null`.
+
+ @param[in] pos iterator to the element to remove
+ @return Iterator following the last removed element. If the iterator @a
+ pos refers to the last element, the `end()` iterator is returned.
+
+ @tparam IteratorType an @ref iterator or @ref const_iterator
+
+ @post Invalidates iterators and references at or after the point of the
+ erase, including the `end()` iterator.
+
+ @throw type_error.307 if called on a `null` value; example: `"cannot use
+ erase() with null"`
+ @throw invalid_iterator.202 if called on an iterator which does not belong
+ to the current JSON value; example: `"iterator does not fit current
+ value"`
+ @throw invalid_iterator.205 if called on a primitive type with invalid
+ iterator (i.e., any iterator which is not `begin()`); example: `"iterator
+ out of range"`
+
+ @complexity The complexity depends on the type:
+ - objects: amortized constant
+ - arrays: linear in distance between @a pos and the end of the container
+ - strings and binary: linear in the length of the member
+ - other types: constant
+
+ @liveexample{The example shows the result of `erase()` for different JSON
+ types.,erase__IteratorType}
+
+ @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in
+ the given range
+ @sa see @ref erase(const typename object_t::key_type&) -- removes the element
+ from an object at the given key
+ @sa see @ref erase(const size_type) -- removes the element from an array at
+ the given index
+
+ @since version 1.0.0
+ */
+ template < class IteratorType, typename std::enable_if <
+ std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
+ = 0 >
+ IteratorType erase(IteratorType pos)
+ {
+ // make sure iterator fits the current value
+ if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ }
+
+ IteratorType result = end();
+
+ switch (m_type)
+ {
+ case value_t::boolean:
+ case value_t::number_float:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::string:
+ case value_t::binary:
+ {
+ if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
+ {
+ JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this));
+ }
+
+ if (is_string())
+ {
+ AllocatorType<string_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+ m_value.string = nullptr;
+ }
+ else if (is_binary())
+ {
+ AllocatorType<binary_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
+ m_value.binary = nullptr;
+ }
+
+ m_type = value_t::null;
+ assert_invariant();
+ break;
+ }
+
+ case value_t::object:
+ {
+ result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
+ break;
+ }
+
+ case value_t::array:
+ {
+ result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::discarded:
+ default:
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief remove elements given an iterator range
+
+ Removes the element specified by the range `[first; last)`. The iterator
+ @a first does not need to be dereferenceable if `first == last`: erasing
+ an empty range is a no-op.
+
+ If called on a primitive type other than `null`, the resulting JSON value
+ will be `null`.
+
+ @param[in] first iterator to the beginning of the range to remove
+ @param[in] last iterator past the end of the range to remove
+ @return Iterator following the last removed element. If the iterator @a
+ second refers to the last element, the `end()` iterator is returned.
+
+ @tparam IteratorType an @ref iterator or @ref const_iterator
+
+ @post Invalidates iterators and references at or after the point of the
+ erase, including the `end()` iterator.
+
+ @throw type_error.307 if called on a `null` value; example: `"cannot use
+ erase() with null"`
+ @throw invalid_iterator.203 if called on iterators which does not belong
+ to the current JSON value; example: `"iterators do not fit current value"`
+ @throw invalid_iterator.204 if called on a primitive type with invalid
+ iterators (i.e., if `first != begin()` and `last != end()`); example:
+ `"iterators out of range"`
+
+ @complexity The complexity depends on the type:
+ - objects: `log(size()) + std::distance(first, last)`
+ - arrays: linear in the distance between @a first and @a last, plus linear
+ in the distance between @a last and end of the container
+ - strings and binary: linear in the length of the member
+ - other types: constant
+
+ @liveexample{The example shows the result of `erase()` for different JSON
+ types.,erase__IteratorType_IteratorType}
+
+ @sa see @ref erase(IteratorType) -- removes the element at a given position
+ @sa see @ref erase(const typename object_t::key_type&) -- removes the element
+ from an object at the given key
+ @sa see @ref erase(const size_type) -- removes the element from an array at
+ the given index
+
+ @since version 1.0.0
+ */
+ template < class IteratorType, typename std::enable_if <
+ std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
+ std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int >::type
+ = 0 >
+ IteratorType erase(IteratorType first, IteratorType last)
+ {
+ // make sure iterator fits the current value
+ if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this));
+ }
+
+ IteratorType result = end();
+
+ switch (m_type)
+ {
+ case value_t::boolean:
+ case value_t::number_float:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::string:
+ case value_t::binary:
+ {
+ if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
+ || !last.m_it.primitive_iterator.is_end()))
+ {
+ JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this));
+ }
+
+ if (is_string())
+ {
+ AllocatorType<string_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
+ m_value.string = nullptr;
+ }
+ else if (is_binary())
+ {
+ AllocatorType<binary_t> alloc;
+ std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
+ m_value.binary = nullptr;
+ }
+
+ m_type = value_t::null;
+ assert_invariant();
+ break;
+ }
+
+ case value_t::object:
+ {
+ result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
+ last.m_it.object_iterator);
+ break;
+ }
+
+ case value_t::array:
+ {
+ result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
+ last.m_it.array_iterator);
+ break;
+ }
+
+ case value_t::null:
+ case value_t::discarded:
+ default:
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief remove element from a JSON object given a key
+
+ Removes elements from a JSON object with the key value @a key.
+
+ @param[in] key value of the elements to remove
+
+ @return Number of elements removed. If @a ObjectType is the default
+ `std::map` type, the return value will always be `0` (@a key was not
+ found) or `1` (@a key was found).
+
+ @post References and iterators to the erased elements are invalidated.
+ Other references and iterators are not affected.
+
+ @throw type_error.307 when called on a type other than JSON object;
+ example: `"cannot use erase() with null"`
+
+ @complexity `log(size()) + count(key)`
+
+ @liveexample{The example shows the effect of `erase()`.,erase__key_type}
+
+ @sa see @ref erase(IteratorType) -- removes the element at a given position
+ @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in
+ the given range
+ @sa see @ref erase(const size_type) -- removes the element from an array at
+ the given index
+
+ @since version 1.0.0
+ */
+ size_type erase(const typename object_t::key_type& key)
+ {
+ // this erase only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ return m_value.object->erase(key);
+ }
+
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief remove element from a JSON array given an index
+
+ Removes element from a JSON array at the index @a idx.
+
+ @param[in] idx index of the element to remove
+
+ @throw type_error.307 when called on a type other than JSON object;
+ example: `"cannot use erase() with null"`
+ @throw out_of_range.401 when `idx >= size()`; example: `"array index 17
+ is out of range"`
+
+ @complexity Linear in distance between @a idx and the end of the container.
+
+ @liveexample{The example shows the effect of `erase()`.,erase__size_type}
+
+ @sa see @ref erase(IteratorType) -- removes the element at a given position
+ @sa see @ref erase(IteratorType, IteratorType) -- removes the elements in
+ the given range
+ @sa see @ref erase(const typename object_t::key_type&) -- removes the element
+ from an object at the given key
+
+ @since version 1.0.0
+ */
+ void erase(const size_type idx)
+ {
+ // this erase only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ if (JSON_HEDLEY_UNLIKELY(idx >= size()))
+ {
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this));
+ }
+
+ m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
+ }
+ else
+ {
+ JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /// @}
+
+
+ ////////////
+ // lookup //
+ ////////////
+
+ /// @name lookup
+ /// @{
+
+ /*!
+ @brief find an element in a JSON object
+
+ Finds an element in a JSON object with key equivalent to @a key. If the
+ element is not found or the JSON value is not an object, end() is
+ returned.
+
+ @note This method always returns @ref end() when executed on a JSON type
+ that is not an object.
+
+ @param[in] key key value of the element to search for.
+
+ @return Iterator to an element with key equivalent to @a key. If no such
+ element is found or the JSON value is not an object, past-the-end (see
+ @ref end()) iterator is returned.
+
+ @complexity Logarithmic in the size of the JSON object.
+
+ @liveexample{The example shows how `find()` is used.,find__key_type}
+
+ @sa see @ref contains(KeyT&&) const -- checks whether a key exists
+
+ @since version 1.0.0
+ */
+ template<typename KeyT>
+ iterator find(KeyT&& key)
+ {
+ auto result = end();
+
+ if (is_object())
+ {
+ result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief find an element in a JSON object
+ @copydoc find(KeyT&&)
+ */
+ template<typename KeyT>
+ const_iterator find(KeyT&& key) const
+ {
+ auto result = cend();
+
+ if (is_object())
+ {
+ result.m_it.object_iterator = m_value.object->find(std::forward<KeyT>(key));
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief returns the number of occurrences of a key in a JSON object
+
+ Returns the number of elements with key @a key. If ObjectType is the
+ default `std::map` type, the return value will always be `0` (@a key was
+ not found) or `1` (@a key was found).
+
+ @note This method always returns `0` when executed on a JSON type that is
+ not an object.
+
+ @param[in] key key value of the element to count
+
+ @return Number of elements with key @a key. If the JSON value is not an
+ object, the return value will be `0`.
+
+ @complexity Logarithmic in the size of the JSON object.
+
+ @liveexample{The example shows how `count()` is used.,count}
+
+ @since version 1.0.0
+ */
+ template<typename KeyT>
+ size_type count(KeyT&& key) const
+ {
+ // return 0 for all nonobject types
+ return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
+ }
+
+ /*!
+ @brief check the existence of an element in a JSON object
+
+ Check whether an element exists in a JSON object with key equivalent to
+ @a key. If the element is not found or the JSON value is not an object,
+ false is returned.
+
+ @note This method always returns false when executed on a JSON type
+ that is not an object.
+
+ @param[in] key key value to check its existence.
+
+ @return true if an element with specified @a key exists. If no such
+ element with such key is found or the JSON value is not an object,
+ false is returned.
+
+ @complexity Logarithmic in the size of the JSON object.
+
+ @liveexample{The following code shows an example for `contains()`.,contains}
+
+ @sa see @ref find(KeyT&&) -- returns an iterator to an object element
+ @sa see @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer
+
+ @since version 3.6.0
+ */
+ template < typename KeyT, typename std::enable_if <
+ !std::is_same<typename std::decay<KeyT>::type, json_pointer>::value, int >::type = 0 >
+ bool contains(KeyT && key) const
+ {
+ return is_object() && m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
+ }
+
+ /*!
+ @brief check the existence of an element in a JSON object given a JSON pointer
+
+ Check whether the given JSON pointer @a ptr can be resolved in the current
+ JSON value.
+
+ @note This method can be executed on any JSON value type.
+
+ @param[in] ptr JSON pointer to check its existence.
+
+ @return true if the JSON pointer can be resolved to a stored value, false
+ otherwise.
+
+ @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`.
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+
+ @complexity Logarithmic in the size of the JSON object.
+
+ @liveexample{The following code shows an example for `contains()`.,contains_json_pointer}
+
+ @sa see @ref contains(KeyT &&) const -- checks the existence of a key
+
+ @since version 3.7.0
+ */
+ bool contains(const json_pointer& ptr) const
+ {
+ return ptr.contains(this);
+ }
+
+ /// @}
+
+
+ ///////////////
+ // iterators //
+ ///////////////
+
+ /// @name iterators
+ /// @{
+
+ /*!
+ @brief returns an iterator to the first element
+
+ Returns an iterator to the first element.
+
+ @image html range-begin-end.svg "Illustration from cppreference.com"
+
+ @return iterator to the first element
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+
+ @liveexample{The following code shows an example for `begin()`.,begin}
+
+ @sa see @ref cbegin() -- returns a const iterator to the beginning
+ @sa see @ref end() -- returns an iterator to the end
+ @sa see @ref cend() -- returns a const iterator to the end
+
+ @since version 1.0.0
+ */
+ iterator begin() noexcept
+ {
+ iterator result(this);
+ result.set_begin();
+ return result;
+ }
+
+ /*!
+ @copydoc basic_json::cbegin()
+ */
+ const_iterator begin() const noexcept
+ {
+ return cbegin();
+ }
+
+ /*!
+ @brief returns a const iterator to the first element
+
+ Returns a const iterator to the first element.
+
+ @image html range-begin-end.svg "Illustration from cppreference.com"
+
+ @return const iterator to the first element
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `const_cast<const basic_json&>(*this).begin()`.
+
+ @liveexample{The following code shows an example for `cbegin()`.,cbegin}
+
+ @sa see @ref begin() -- returns an iterator to the beginning
+ @sa see @ref end() -- returns an iterator to the end
+ @sa see @ref cend() -- returns a const iterator to the end
+
+ @since version 1.0.0
+ */
+ const_iterator cbegin() const noexcept
+ {
+ const_iterator result(this);
+ result.set_begin();
+ return result;
+ }
+
+ /*!
+ @brief returns an iterator to one past the last element
+
+ Returns an iterator to one past the last element.
+
+ @image html range-begin-end.svg "Illustration from cppreference.com"
+
+ @return iterator one past the last element
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+
+ @liveexample{The following code shows an example for `end()`.,end}
+
+ @sa see @ref cend() -- returns a const iterator to the end
+ @sa see @ref begin() -- returns an iterator to the beginning
+ @sa see @ref cbegin() -- returns a const iterator to the beginning
+
+ @since version 1.0.0
+ */
+ iterator end() noexcept
+ {
+ iterator result(this);
+ result.set_end();
+ return result;
+ }
+
+ /*!
+ @copydoc basic_json::cend()
+ */
+ const_iterator end() const noexcept
+ {
+ return cend();
+ }
+
+ /*!
+ @brief returns a const iterator to one past the last element
+
+ Returns a const iterator to one past the last element.
+
+ @image html range-begin-end.svg "Illustration from cppreference.com"
+
+ @return const iterator one past the last element
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `const_cast<const basic_json&>(*this).end()`.
+
+ @liveexample{The following code shows an example for `cend()`.,cend}
+
+ @sa see @ref end() -- returns an iterator to the end
+ @sa see @ref begin() -- returns an iterator to the beginning
+ @sa see @ref cbegin() -- returns a const iterator to the beginning
+
+ @since version 1.0.0
+ */
+ const_iterator cend() const noexcept
+ {
+ const_iterator result(this);
+ result.set_end();
+ return result;
+ }
+
+ /*!
+ @brief returns an iterator to the reverse-beginning
+
+ Returns an iterator to the reverse-beginning; that is, the last element.
+
+ @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `reverse_iterator(end())`.
+
+ @liveexample{The following code shows an example for `rbegin()`.,rbegin}
+
+ @sa see @ref crbegin() -- returns a const reverse iterator to the beginning
+ @sa see @ref rend() -- returns a reverse iterator to the end
+ @sa see @ref crend() -- returns a const reverse iterator to the end
+
+ @since version 1.0.0
+ */
+ reverse_iterator rbegin() noexcept
+ {
+ return reverse_iterator(end());
+ }
+
+ /*!
+ @copydoc basic_json::crbegin()
+ */
+ const_reverse_iterator rbegin() const noexcept
+ {
+ return crbegin();
+ }
+
+ /*!
+ @brief returns an iterator to the reverse-end
+
+ Returns an iterator to the reverse-end; that is, one before the first
+ element.
+
+ @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `reverse_iterator(begin())`.
+
+ @liveexample{The following code shows an example for `rend()`.,rend}
+
+ @sa see @ref crend() -- returns a const reverse iterator to the end
+ @sa see @ref rbegin() -- returns a reverse iterator to the beginning
+ @sa see @ref crbegin() -- returns a const reverse iterator to the beginning
+
+ @since version 1.0.0
+ */
+ reverse_iterator rend() noexcept
+ {
+ return reverse_iterator(begin());
+ }
+
+ /*!
+ @copydoc basic_json::crend()
+ */
+ const_reverse_iterator rend() const noexcept
+ {
+ return crend();
+ }
+
+ /*!
+ @brief returns a const reverse iterator to the last element
+
+ Returns a const iterator to the reverse-beginning; that is, the last
+ element.
+
+ @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `const_cast<const basic_json&>(*this).rbegin()`.
+
+ @liveexample{The following code shows an example for `crbegin()`.,crbegin}
+
+ @sa see @ref rbegin() -- returns a reverse iterator to the beginning
+ @sa see @ref rend() -- returns a reverse iterator to the end
+ @sa see @ref crend() -- returns a const reverse iterator to the end
+
+ @since version 1.0.0
+ */
+ const_reverse_iterator crbegin() const noexcept
+ {
+ return const_reverse_iterator(cend());
+ }
+
+ /*!
+ @brief returns a const reverse iterator to one before the first
+
+ Returns a const reverse iterator to the reverse-end; that is, one before
+ the first element.
+
+ @image html range-rbegin-rend.svg "Illustration from cppreference.com"
+
+ @complexity Constant.
+
+ @requirement This function helps `basic_json` satisfying the
+ [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `const_cast<const basic_json&>(*this).rend()`.
+
+ @liveexample{The following code shows an example for `crend()`.,crend}
+
+ @sa see @ref rend() -- returns a reverse iterator to the end
+ @sa see @ref rbegin() -- returns a reverse iterator to the beginning
+ @sa see @ref crbegin() -- returns a const reverse iterator to the beginning
+
+ @since version 1.0.0
+ */
+ const_reverse_iterator crend() const noexcept
+ {
+ return const_reverse_iterator(cbegin());
+ }
+
+ public:
+ /*!
+ @brief wrapper to access iterator member functions in range-based for
+
+ This function allows to access @ref iterator::key() and @ref
+ iterator::value() during range-based for loops. In these loops, a
+ reference to the JSON values is returned, so there is no access to the
+ underlying iterator.
+
+ For loop without iterator_wrapper:
+
+ @code{cpp}
+ for (auto it = j_object.begin(); it != j_object.end(); ++it)
+ {
+ std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+ }
+ @endcode
+
+ Range-based for loop without iterator proxy:
+
+ @code{cpp}
+ for (auto it : j_object)
+ {
+ // "it" is of type json::reference and has no key() member
+ std::cout << "value: " << it << '\n';
+ }
+ @endcode
+
+ Range-based for loop with iterator proxy:
+
+ @code{cpp}
+ for (auto it : json::iterator_wrapper(j_object))
+ {
+ std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+ }
+ @endcode
+
+ @note When iterating over an array, `key()` will return the index of the
+ element as string (see example).
+
+ @param[in] ref reference to a JSON value
+ @return iteration proxy object wrapping @a ref with an interface to use in
+ range-based for loops
+
+ @liveexample{The following code shows how the wrapper is used,iterator_wrapper}
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
+ @note The name of this function is not yet final and may change in the
+ future.
+
+ @deprecated This stream operator is deprecated and will be removed in
+ future 4.0.0 of the library. Please use @ref items() instead;
+ that is, replace `json::iterator_wrapper(j)` with `j.items()`.
+ */
+ JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
+ static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
+ {
+ return ref.items();
+ }
+
+ /*!
+ @copydoc iterator_wrapper(reference)
+ */
+ JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
+ static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
+ {
+ return ref.items();
+ }
+
+ /*!
+ @brief helper to access iterator member functions in range-based for
+
+ This function allows to access @ref iterator::key() and @ref
+ iterator::value() during range-based for loops. In these loops, a
+ reference to the JSON values is returned, so there is no access to the
+ underlying iterator.
+
+ For loop without `items()` function:
+
+ @code{cpp}
+ for (auto it = j_object.begin(); it != j_object.end(); ++it)
+ {
+ std::cout << "key: " << it.key() << ", value:" << it.value() << '\n';
+ }
+ @endcode
+
+ Range-based for loop without `items()` function:
+
+ @code{cpp}
+ for (auto it : j_object)
+ {
+ // "it" is of type json::reference and has no key() member
+ std::cout << "value: " << it << '\n';
+ }
+ @endcode
+
+ Range-based for loop with `items()` function:
+
+ @code{cpp}
+ for (auto& el : j_object.items())
+ {
+ std::cout << "key: " << el.key() << ", value:" << el.value() << '\n';
+ }
+ @endcode
+
+ The `items()` function also allows to use
+ [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding)
+ (C++17):
+
+ @code{cpp}
+ for (auto& [key, val] : j_object.items())
+ {
+ std::cout << "key: " << key << ", value:" << val << '\n';
+ }
+ @endcode
+
+ @note When iterating over an array, `key()` will return the index of the
+ element as string (see example). For primitive types (e.g., numbers),
+ `key()` returns an empty string.
+
+ @warning Using `items()` on temporary objects is dangerous. Make sure the
+ object's lifetime exceeds the iteration. See
+ <https://github.com/nlohmann/json/issues/2040> for more
+ information.
+
+ @return iteration proxy object wrapping @a ref with an interface to use in
+ range-based for loops
+
+ @liveexample{The following code shows how the function is used.,items}
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
+ @since version 3.1.0, structured bindings support since 3.5.0.
+ */
+ iteration_proxy<iterator> items() noexcept
+ {
+ return iteration_proxy<iterator>(*this);
+ }
+
+ /*!
+ @copydoc items()
+ */
+ iteration_proxy<const_iterator> items() const noexcept
+ {
+ return iteration_proxy<const_iterator>(*this);
+ }
+
+ /// @}
+
+
+ //////////////
+ // capacity //
+ //////////////
+
+ /// @name capacity
+ /// @{
+
+ /*!
+ @brief checks whether the container is empty.
+
+ Checks if a JSON value has no elements (i.e. whether its @ref size is `0`).
+
+ @return The return value depends on the different types and is
+ defined as follows:
+ Value type | return value
+ ----------- | -------------
+ null | `true`
+ boolean | `false`
+ string | `false`
+ number | `false`
+ binary | `false`
+ object | result of function `object_t::empty()`
+ array | result of function `array_t::empty()`
+
+ @liveexample{The following code uses `empty()` to check if a JSON
+ object contains any elements.,empty}
+
+ @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+ the Container concept; that is, their `empty()` functions have constant
+ complexity.
+
+ @iterators No changes.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @note This function does not return whether a string stored as JSON value
+ is empty - it returns whether the JSON container itself is empty which is
+ false in the case of a string.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `begin() == end()`.
+
+ @sa see @ref size() -- returns the number of elements
+
+ @since version 1.0.0
+ */
+ bool empty() const noexcept
+ {
+ switch (m_type)
+ {
+ case value_t::null:
+ {
+ // null values are empty
+ return true;
+ }
+
+ case value_t::array:
+ {
+ // delegate call to array_t::empty()
+ return m_value.array->empty();
+ }
+
+ case value_t::object:
+ {
+ // delegate call to object_t::empty()
+ return m_value.object->empty();
+ }
+
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ // all other types are nonempty
+ return false;
+ }
+ }
+ }
+
+ /*!
+ @brief returns the number of elements
+
+ Returns the number of elements in a JSON value.
+
+ @return The return value depends on the different types and is
+ defined as follows:
+ Value type | return value
+ ----------- | -------------
+ null | `0`
+ boolean | `1`
+ string | `1`
+ number | `1`
+ binary | `1`
+ object | result of function object_t::size()
+ array | result of function array_t::size()
+
+ @liveexample{The following code calls `size()` on the different value
+ types.,size}
+
+ @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+ the Container concept; that is, their size() functions have constant
+ complexity.
+
+ @iterators No changes.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @note This function does not return the length of a string stored as JSON
+ value - it returns the number of elements in the JSON value which is 1 in
+ the case of a string.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of `std::distance(begin(), end())`.
+
+ @sa see @ref empty() -- checks whether the container is empty
+ @sa see @ref max_size() -- returns the maximal number of elements
+
+ @since version 1.0.0
+ */
+ size_type size() const noexcept
+ {
+ switch (m_type)
+ {
+ case value_t::null:
+ {
+ // null values are empty
+ return 0;
+ }
+
+ case value_t::array:
+ {
+ // delegate call to array_t::size()
+ return m_value.array->size();
+ }
+
+ case value_t::object:
+ {
+ // delegate call to object_t::size()
+ return m_value.object->size();
+ }
+
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ // all other types have size 1
+ return 1;
+ }
+ }
+ }
+
+ /*!
+ @brief returns the maximum possible number of elements
+
+ Returns the maximum number of elements a JSON value is able to hold due to
+ system or library implementation limitations, i.e. `std::distance(begin(),
+ end())` for the JSON value.
+
+ @return The return value depends on the different types and is
+ defined as follows:
+ Value type | return value
+ ----------- | -------------
+ null | `0` (same as `size()`)
+ boolean | `1` (same as `size()`)
+ string | `1` (same as `size()`)
+ number | `1` (same as `size()`)
+ binary | `1` (same as `size()`)
+ object | result of function `object_t::max_size()`
+ array | result of function `array_t::max_size()`
+
+ @liveexample{The following code calls `max_size()` on the different value
+ types. Note the output is implementation specific.,max_size}
+
+ @complexity Constant, as long as @ref array_t and @ref object_t satisfy
+ the Container concept; that is, their `max_size()` functions have constant
+ complexity.
+
+ @iterators No changes.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @requirement This function helps `basic_json` satisfying the
+ [Container](https://en.cppreference.com/w/cpp/named_req/Container)
+ requirements:
+ - The complexity is constant.
+ - Has the semantics of returning `b.size()` where `b` is the largest
+ possible JSON value.
+
+ @sa see @ref size() -- returns the number of elements
+
+ @since version 1.0.0
+ */
+ size_type max_size() const noexcept
+ {
+ switch (m_type)
+ {
+ case value_t::array:
+ {
+ // delegate call to array_t::max_size()
+ return m_value.array->max_size();
+ }
+
+ case value_t::object:
+ {
+ // delegate call to object_t::max_size()
+ return m_value.object->max_size();
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ // all other types have max_size() == size()
+ return size();
+ }
+ }
+ }
+
+ /// @}
+
+
+ ///////////////
+ // modifiers //
+ ///////////////
+
+ /// @name modifiers
+ /// @{
+
+ /*!
+ @brief clears the contents
+
+ Clears the content of a JSON value and resets it to the default value as
+ if @ref basic_json(value_t) would have been called with the current value
+ type from @ref type():
+
+ Value type | initial value
+ ----------- | -------------
+ null | `null`
+ boolean | `false`
+ string | `""`
+ number | `0`
+ binary | An empty byte vector
+ object | `{}`
+ array | `[]`
+
+ @post Has the same effect as calling
+ @code {.cpp}
+ *this = basic_json(type());
+ @endcode
+
+ @liveexample{The example below shows the effect of `clear()` to different
+ JSON types.,clear}
+
+ @complexity Linear in the size of the JSON value.
+
+ @iterators All iterators, pointers and references related to this container
+ are invalidated.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @sa see @ref basic_json(value_t) -- constructor that creates an object with the
+ same value than calling `clear()`
+
+ @since version 1.0.0
+ */
+ void clear() noexcept
+ {
+ switch (m_type)
+ {
+ case value_t::number_integer:
+ {
+ m_value.number_integer = 0;
+ break;
+ }
+
+ case value_t::number_unsigned:
+ {
+ m_value.number_unsigned = 0;
+ break;
+ }
+
+ case value_t::number_float:
+ {
+ m_value.number_float = 0.0;
+ break;
+ }
+
+ case value_t::boolean:
+ {
+ m_value.boolean = false;
+ break;
+ }
+
+ case value_t::string:
+ {
+ m_value.string->clear();
+ break;
+ }
+
+ case value_t::binary:
+ {
+ m_value.binary->clear();
+ break;
+ }
+
+ case value_t::array:
+ {
+ m_value.array->clear();
+ break;
+ }
+
+ case value_t::object:
+ {
+ m_value.object->clear();
+ break;
+ }
+
+ case value_t::null:
+ case value_t::discarded:
+ default:
+ break;
+ }
+ }
+
+ /*!
+ @brief add an object to an array
+
+ Appends the given element @a val to the end of the JSON value. If the
+ function is called on a JSON null value, an empty array is created before
+ appending @a val.
+
+ @param[in] val the value to add to the JSON array
+
+ @throw type_error.308 when called on a type other than JSON array or
+ null; example: `"cannot use push_back() with number"`
+
+ @complexity Amortized constant.
+
+ @liveexample{The example shows how `push_back()` and `+=` can be used to
+ add elements to a JSON array. Note how the `null` value was silently
+ converted to a JSON array.,push_back}
+
+ @since version 1.0.0
+ */
+ void push_back(basic_json&& val)
+ {
+ // push_back only works for null objects or arrays
+ if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+ {
+ JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ }
+
+ // transform null object into an array
+ if (is_null())
+ {
+ m_type = value_t::array;
+ m_value = value_t::array;
+ assert_invariant();
+ }
+
+ // add element to array (move semantics)
+ const auto old_capacity = m_value.array->capacity();
+ m_value.array->push_back(std::move(val));
+ set_parent(m_value.array->back(), old_capacity);
+ // if val is moved from, basic_json move constructor marks it null so we do not call the destructor
+ }
+
+ /*!
+ @brief add an object to an array
+ @copydoc push_back(basic_json&&)
+ */
+ reference operator+=(basic_json&& val)
+ {
+ push_back(std::move(val));
+ return *this;
+ }
+
+ /*!
+ @brief add an object to an array
+ @copydoc push_back(basic_json&&)
+ */
+ void push_back(const basic_json& val)
+ {
+ // push_back only works for null objects or arrays
+ if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+ {
+ JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ }
+
+ // transform null object into an array
+ if (is_null())
+ {
+ m_type = value_t::array;
+ m_value = value_t::array;
+ assert_invariant();
+ }
+
+ // add element to array
+ const auto old_capacity = m_value.array->capacity();
+ m_value.array->push_back(val);
+ set_parent(m_value.array->back(), old_capacity);
+ }
+
+ /*!
+ @brief add an object to an array
+ @copydoc push_back(basic_json&&)
+ */
+ reference operator+=(const basic_json& val)
+ {
+ push_back(val);
+ return *this;
+ }
+
+ /*!
+ @brief add an object to an object
+
+ Inserts the given element @a val to the JSON object. If the function is
+ called on a JSON null value, an empty object is created before inserting
+ @a val.
+
+ @param[in] val the value to add to the JSON object
+
+ @throw type_error.308 when called on a type other than JSON object or
+ null; example: `"cannot use push_back() with number"`
+
+ @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+ @liveexample{The example shows how `push_back()` and `+=` can be used to
+ add elements to a JSON object. Note how the `null` value was silently
+ converted to a JSON object.,push_back__object_t__value}
+
+ @since version 1.0.0
+ */
+ void push_back(const typename object_t::value_type& val)
+ {
+ // push_back only works for null objects or objects
+ if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
+ {
+ JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this));
+ }
+
+ // transform null object into an object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value = value_t::object;
+ assert_invariant();
+ }
+
+ // add element to object
+ auto res = m_value.object->insert(val);
+ set_parent(res.first->second);
+ }
+
+ /*!
+ @brief add an object to an object
+ @copydoc push_back(const typename object_t::value_type&)
+ */
+ reference operator+=(const typename object_t::value_type& val)
+ {
+ push_back(val);
+ return *this;
+ }
+
+ /*!
+ @brief add an object to an object
+
+ This function allows to use `push_back` with an initializer list. In case
+
+ 1. the current value is an object,
+ 2. the initializer list @a init contains only two elements, and
+ 3. the first element of @a init is a string,
+
+ @a init is converted into an object element and added using
+ @ref push_back(const typename object_t::value_type&). Otherwise, @a init
+ is converted to a JSON value and added using @ref push_back(basic_json&&).
+
+ @param[in] init an initializer list
+
+ @complexity Linear in the size of the initializer list @a init.
+
+ @note This function is required to resolve an ambiguous overload error,
+ because pairs like `{"key", "value"}` can be both interpreted as
+ `object_t::value_type` or `std::initializer_list<basic_json>`, see
+ https://github.com/nlohmann/json/issues/235 for more information.
+
+ @liveexample{The example shows how initializer lists are treated as
+ objects when possible.,push_back__initializer_list}
+ */
+ void push_back(initializer_list_t init)
+ {
+ if (is_object() && init.size() == 2 && (*init.begin())->is_string())
+ {
+ basic_json&& key = init.begin()->moved_or_copied();
+ push_back(typename object_t::value_type(
+ std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
+ }
+ else
+ {
+ push_back(basic_json(init));
+ }
+ }
+
+ /*!
+ @brief add an object to an object
+ @copydoc push_back(initializer_list_t)
+ */
+ reference operator+=(initializer_list_t init)
+ {
+ push_back(init);
+ return *this;
+ }
+
+ /*!
+ @brief add an object to an array
+
+ Creates a JSON value from the passed parameters @a args to the end of the
+ JSON value. If the function is called on a JSON null value, an empty array
+ is created before appending the value created from @a args.
+
+ @param[in] args arguments to forward to a constructor of @ref basic_json
+ @tparam Args compatible types to create a @ref basic_json object
+
+ @return reference to the inserted element
+
+ @throw type_error.311 when called on a type other than JSON array or
+ null; example: `"cannot use emplace_back() with number"`
+
+ @complexity Amortized constant.
+
+ @liveexample{The example shows how `push_back()` can be used to add
+ elements to a JSON array. Note how the `null` value was silently converted
+ to a JSON array.,emplace_back}
+
+ @since version 2.0.8, returns reference since 3.7.0
+ */
+ template<class... Args>
+ reference emplace_back(Args&& ... args)
+ {
+ // emplace_back only works for null objects or arrays
+ if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
+ {
+ JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this));
+ }
+
+ // transform null object into an array
+ if (is_null())
+ {
+ m_type = value_t::array;
+ m_value = value_t::array;
+ assert_invariant();
+ }
+
+ // add element to array (perfect forwarding)
+ const auto old_capacity = m_value.array->capacity();
+ m_value.array->emplace_back(std::forward<Args>(args)...);
+ return set_parent(m_value.array->back(), old_capacity);
+ }
+
+ /*!
+ @brief add an object to an object if key does not exist
+
+ Inserts a new element into a JSON object constructed in-place with the
+ given @a args if there is no element with the key in the container. If the
+ function is called on a JSON null value, an empty object is created before
+ appending the value created from @a args.
+
+ @param[in] args arguments to forward to a constructor of @ref basic_json
+ @tparam Args compatible types to create a @ref basic_json object
+
+ @return a pair consisting of an iterator to the inserted element, or the
+ already-existing element if no insertion happened, and a bool
+ denoting whether the insertion took place.
+
+ @throw type_error.311 when called on a type other than JSON object or
+ null; example: `"cannot use emplace() with number"`
+
+ @complexity Logarithmic in the size of the container, O(log(`size()`)).
+
+ @liveexample{The example shows how `emplace()` can be used to add elements
+ to a JSON object. Note how the `null` value was silently converted to a
+ JSON object. Further note how no value is added if there was already one
+ value stored with the same key.,emplace}
+
+ @since version 2.0.8
+ */
+ template<class... Args>
+ std::pair<iterator, bool> emplace(Args&& ... args)
+ {
+ // emplace only works for null objects or arrays
+ if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
+ {
+ JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this));
+ }
+
+ // transform null object into an object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value = value_t::object;
+ assert_invariant();
+ }
+
+ // add element to array (perfect forwarding)
+ auto res = m_value.object->emplace(std::forward<Args>(args)...);
+ set_parent(res.first->second);
+
+ // create result iterator and set iterator to the result of emplace
+ auto it = begin();
+ it.m_it.object_iterator = res.first;
+
+ // return pair of iterator and boolean
+ return {it, res.second};
+ }
+
+ /// Helper for insertion of an iterator
+ /// @note: This uses std::distance to support GCC 4.8,
+ /// see https://github.com/nlohmann/json/pull/1257
+ template<typename... Args>
+ iterator insert_iterator(const_iterator pos, Args&& ... args)
+ {
+ iterator result(this);
+ JSON_ASSERT(m_value.array != nullptr);
+
+ auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
+ m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
+ result.m_it.array_iterator = m_value.array->begin() + insert_pos;
+
+ // This could have been written as:
+ // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
+ // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
+
+ set_parents();
+ return result;
+ }
+
+ /*!
+ @brief inserts element
+
+ Inserts element @a val before iterator @a pos.
+
+ @param[in] pos iterator before which the content will be inserted; may be
+ the end() iterator
+ @param[in] val element to insert
+ @return iterator pointing to the inserted @a val.
+
+ @throw type_error.309 if called on JSON values other than arrays;
+ example: `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
+
+ @complexity Constant plus linear in the distance between @a pos and end of
+ the container.
+
+ @liveexample{The example shows how `insert()` is used.,insert}
+
+ @since version 1.0.0
+ */
+ iterator insert(const_iterator pos, const basic_json& val)
+ {
+ // insert only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ // check if iterator pos fits to this JSON value
+ if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ }
+
+ // insert to array and return iterator
+ return insert_iterator(pos, val);
+ }
+
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief inserts element
+ @copydoc insert(const_iterator, const basic_json&)
+ */
+ iterator insert(const_iterator pos, basic_json&& val)
+ {
+ return insert(pos, val);
+ }
+
+ /*!
+ @brief inserts elements
+
+ Inserts @a cnt copies of @a val before iterator @a pos.
+
+ @param[in] pos iterator before which the content will be inserted; may be
+ the end() iterator
+ @param[in] cnt number of copies of @a val to insert
+ @param[in] val element to insert
+ @return iterator pointing to the first element inserted, or @a pos if
+ `cnt==0`
+
+ @throw type_error.309 if called on JSON values other than arrays; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
+
+ @complexity Linear in @a cnt plus linear in the distance between @a pos
+ and end of the container.
+
+ @liveexample{The example shows how `insert()` is used.,insert__count}
+
+ @since version 1.0.0
+ */
+ iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
+ {
+ // insert only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ // check if iterator pos fits to this JSON value
+ if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ }
+
+ // insert to array and return iterator
+ return insert_iterator(pos, cnt, val);
+ }
+
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ }
+
+ /*!
+ @brief inserts elements
+
+ Inserts elements from range `[first, last)` before iterator @a pos.
+
+ @param[in] pos iterator before which the content will be inserted; may be
+ the end() iterator
+ @param[in] first begin of the range of elements to insert
+ @param[in] last end of the range of elements to insert
+
+ @throw type_error.309 if called on JSON values other than arrays; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
+ @throw invalid_iterator.210 if @a first and @a last do not belong to the
+ same JSON value; example: `"iterators do not fit"`
+ @throw invalid_iterator.211 if @a first or @a last are iterators into
+ container for which insert is called; example: `"passed iterators may not
+ belong to container"`
+
+ @return iterator pointing to the first element inserted, or @a pos if
+ `first==last`
+
+ @complexity Linear in `std::distance(first, last)` plus linear in the
+ distance between @a pos and end of the container.
+
+ @liveexample{The example shows how `insert()` is used.,insert__range}
+
+ @since version 1.0.0
+ */
+ iterator insert(const_iterator pos, const_iterator first, const_iterator last)
+ {
+ // insert only works for arrays
+ if (JSON_HEDLEY_UNLIKELY(!is_array()))
+ {
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ }
+
+ // check if iterator pos fits to this JSON value
+ if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ }
+
+ // check if range iterators belong to the same JSON object
+ if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
+ {
+ JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this));
+ }
+
+ // insert to array and return iterator
+ return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
+ }
+
+ /*!
+ @brief inserts elements
+
+ Inserts elements from initializer list @a ilist before iterator @a pos.
+
+ @param[in] pos iterator before which the content will be inserted; may be
+ the end() iterator
+ @param[in] ilist initializer list to insert the values from
+
+ @throw type_error.309 if called on JSON values other than arrays; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if @a pos is not an iterator of *this;
+ example: `"iterator does not fit current value"`
+
+ @return iterator pointing to the first element inserted, or @a pos if
+ `ilist` is empty
+
+ @complexity Linear in `ilist.size()` plus linear in the distance between
+ @a pos and end of the container.
+
+ @liveexample{The example shows how `insert()` is used.,insert__ilist}
+
+ @since version 1.0.0
+ */
+ iterator insert(const_iterator pos, initializer_list_t ilist)
+ {
+ // insert only works for arrays
+ if (JSON_HEDLEY_UNLIKELY(!is_array()))
+ {
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ }
+
+ // check if iterator pos fits to this JSON value
+ if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this));
+ }
+
+ // insert to array and return iterator
+ return insert_iterator(pos, ilist.begin(), ilist.end());
+ }
+
+ /*!
+ @brief inserts elements
+
+ Inserts elements from range `[first, last)`.
+
+ @param[in] first begin of the range of elements to insert
+ @param[in] last end of the range of elements to insert
+
+ @throw type_error.309 if called on JSON values other than objects; example:
+ `"cannot use insert() with string"`
+ @throw invalid_iterator.202 if iterator @a first or @a last does does not
+ point to an object; example: `"iterators first and last must point to
+ objects"`
+ @throw invalid_iterator.210 if @a first and @a last do not belong to the
+ same JSON value; example: `"iterators do not fit"`
+
+ @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number
+ of elements to insert.
+
+ @liveexample{The example shows how `insert()` is used.,insert__range_object}
+
+ @since version 3.0.0
+ */
+ void insert(const_iterator first, const_iterator last)
+ {
+ // insert only works for objects
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
+ {
+ JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this));
+ }
+
+ // check if range iterators belong to the same JSON object
+ if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ }
+
+ // passed iterators must belong to objects
+ if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
+ {
+ JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this));
+ }
+
+ m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
+ }
+
+ /*!
+ @brief updates a JSON object from another object, overwriting existing keys
+
+ Inserts all values from JSON object @a j and overwrites existing keys.
+
+ @param[in] j JSON object to read values from
+ @param[in] merge_objects when true, existing keys are not overwritten, but
+ contents of objects are merged recursively
+ (default: false)
+
+ @throw type_error.312 if called on JSON values other than objects; example:
+ `"cannot use update() with string"`
+
+ @complexity O(N*log(size() + N)), where N is the number of elements to
+ insert.
+
+ @liveexample{The example shows how `update()` is used.,update}
+
+ @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+ @since version 3.0.0, `merge_objects` parameter added in 3.10.4.
+ */
+ void update(const_reference j, bool merge_objects = false)
+ {
+ update(j.begin(), j.end(), merge_objects);
+ }
+
+ /*!
+ @brief updates a JSON object from another object, overwriting existing keys
+
+ Inserts all values from from range `[first, last)` and overwrites existing
+ keys.
+
+ @param[in] first begin of the range of elements to insert
+ @param[in] last end of the range of elements to insert
+ @param[in] merge_objects when true, existing keys are not overwritten, but
+ contents of objects are merged recursively
+ (default: false)
+
+ @throw type_error.312 if called on JSON values other than objects; example:
+ `"cannot use update() with string"`
+ @throw type_error.312 if iterator @a first or @a last does does not
+ point to an object; example: `"cannot use update() with string"`
+ @throw invalid_iterator.210 if @a first and @a last do not belong to the
+ same JSON value; example: `"iterators do not fit"`
+
+ @complexity O(N*log(size() + N)), where N is the number of elements to
+ insert.
+
+ @liveexample{The example shows how `update()` is used__range.,update}
+
+ @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update
+
+ @since version 3.0.0, `merge_objects` parameter added in 3.10.4.
+ */
+ void update(const_iterator first, const_iterator last, bool merge_objects = false)
+ {
+ // implicitly convert null value to an empty object
+ if (is_null())
+ {
+ m_type = value_t::object;
+ m_value.object = create<object_t>();
+ assert_invariant();
+ }
+
+ if (JSON_HEDLEY_UNLIKELY(!is_object()))
+ {
+ JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this));
+ }
+
+ // check if range iterators belong to the same JSON object
+ if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
+ {
+ JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this));
+ }
+
+ // passed iterators must belong to objects
+ if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
+ {
+ JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(first.m_object->type_name()), *first.m_object));
+ }
+
+ for (auto it = first; it != last; ++it)
+ {
+ if (merge_objects && it.value().is_object())
+ {
+ auto it2 = m_value.object->find(it.key());
+ if (it2 != m_value.object->end())
+ {
+ it2->second.update(it.value(), true);
+ continue;
+ }
+ }
+ m_value.object->operator[](it.key()) = it.value();
+#if JSON_DIAGNOSTICS
+ m_value.object->operator[](it.key()).m_parent = this;
+#endif
+ }
+ }
+
+ /*!
+ @brief exchanges the values
+
+ Exchanges the contents of the JSON value with those of @a other. Does not
+ invoke any move, copy, or swap operations on individual elements. All
+ iterators and references remain valid. The past-the-end iterator is
+ invalidated.
+
+ @param[in,out] other JSON value to exchange the contents with
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how JSON values can be swapped with
+ `swap()`.,swap__reference}
+
+ @since version 1.0.0
+ */
+ void swap(reference other) noexcept (
+ std::is_nothrow_move_constructible<value_t>::value&&
+ std::is_nothrow_move_assignable<value_t>::value&&
+ std::is_nothrow_move_constructible<json_value>::value&&
+ std::is_nothrow_move_assignable<json_value>::value
+ )
+ {
+ std::swap(m_type, other.m_type);
+ std::swap(m_value, other.m_value);
+
+ set_parents();
+ other.set_parents();
+ assert_invariant();
+ }
+
+ /*!
+ @brief exchanges the values
+
+ Exchanges the contents of the JSON value from @a left with those of @a right. Does not
+ invoke any move, copy, or swap operations on individual elements. All
+ iterators and references remain valid. The past-the-end iterator is
+ invalidated. implemented as a friend function callable via ADL.
+
+ @param[in,out] left JSON value to exchange the contents with
+ @param[in,out] right JSON value to exchange the contents with
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how JSON values can be swapped with
+ `swap()`.,swap__reference}
+
+ @since version 1.0.0
+ */
+ friend void swap(reference left, reference right) noexcept (
+ std::is_nothrow_move_constructible<value_t>::value&&
+ std::is_nothrow_move_assignable<value_t>::value&&
+ std::is_nothrow_move_constructible<json_value>::value&&
+ std::is_nothrow_move_assignable<json_value>::value
+ )
+ {
+ left.swap(right);
+ }
+
+ /*!
+ @brief exchanges the values
+
+ Exchanges the contents of a JSON array with those of @a other. Does not
+ invoke any move, copy, or swap operations on individual elements. All
+ iterators and references remain valid. The past-the-end iterator is
+ invalidated.
+
+ @param[in,out] other array to exchange the contents with
+
+ @throw type_error.310 when JSON value is not an array; example: `"cannot
+ use swap() with string"`
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how arrays can be swapped with
+ `swap()`.,swap__array_t}
+
+ @since version 1.0.0
+ */
+ void swap(array_t& other) // NOLINT(bugprone-exception-escape)
+ {
+ // swap only works for arrays
+ if (JSON_HEDLEY_LIKELY(is_array()))
+ {
+ std::swap(*(m_value.array), other);
+ }
+ else
+ {
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief exchanges the values
+
+ Exchanges the contents of a JSON object with those of @a other. Does not
+ invoke any move, copy, or swap operations on individual elements. All
+ iterators and references remain valid. The past-the-end iterator is
+ invalidated.
+
+ @param[in,out] other object to exchange the contents with
+
+ @throw type_error.310 when JSON value is not an object; example:
+ `"cannot use swap() with string"`
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how objects can be swapped with
+ `swap()`.,swap__object_t}
+
+ @since version 1.0.0
+ */
+ void swap(object_t& other) // NOLINT(bugprone-exception-escape)
+ {
+ // swap only works for objects
+ if (JSON_HEDLEY_LIKELY(is_object()))
+ {
+ std::swap(*(m_value.object), other);
+ }
+ else
+ {
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief exchanges the values
+
+ Exchanges the contents of a JSON string with those of @a other. Does not
+ invoke any move, copy, or swap operations on individual elements. All
+ iterators and references remain valid. The past-the-end iterator is
+ invalidated.
+
+ @param[in,out] other string to exchange the contents with
+
+ @throw type_error.310 when JSON value is not a string; example: `"cannot
+ use swap() with boolean"`
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how strings can be swapped with
+ `swap()`.,swap__string_t}
+
+ @since version 1.0.0
+ */
+ void swap(string_t& other) // NOLINT(bugprone-exception-escape)
+ {
+ // swap only works for strings
+ if (JSON_HEDLEY_LIKELY(is_string()))
+ {
+ std::swap(*(m_value.string), other);
+ }
+ else
+ {
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /*!
+ @brief exchanges the values
+
+ Exchanges the contents of a JSON string with those of @a other. Does not
+ invoke any move, copy, or swap operations on individual elements. All
+ iterators and references remain valid. The past-the-end iterator is
+ invalidated.
+
+ @param[in,out] other binary to exchange the contents with
+
+ @throw type_error.310 when JSON value is not a string; example: `"cannot
+ use swap() with boolean"`
+
+ @complexity Constant.
+
+ @liveexample{The example below shows how strings can be swapped with
+ `swap()`.,swap__binary_t}
+
+ @since version 3.8.0
+ */
+ void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
+ {
+ // swap only works for strings
+ if (JSON_HEDLEY_LIKELY(is_binary()))
+ {
+ std::swap(*(m_value.binary), other);
+ }
+ else
+ {
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /// @copydoc swap(binary_t&)
+ void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
+ {
+ // swap only works for strings
+ if (JSON_HEDLEY_LIKELY(is_binary()))
+ {
+ std::swap(*(m_value.binary), other);
+ }
+ else
+ {
+ JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this));
+ }
+ }
+
+ /// @}
+
+ public:
+ //////////////////////////////////////////
+ // lexicographical comparison operators //
+ //////////////////////////////////////////
+
+ /// @name lexicographical comparison operators
+ /// @{
+
+ /*!
+ @brief comparison: equal
+
+ Compares two JSON values for equality according to the following rules:
+ - Two JSON values are equal if (1) they are from the same type and (2)
+ their stored values are the same according to their respective
+ `operator==`.
+ - Integer and floating-point numbers are automatically converted before
+ comparison. Note that two NaN values are always treated as unequal.
+ - Two JSON null values are equal.
+
+ @note Floating-point inside JSON values numbers are compared with
+ `json::number_float_t::operator==` which is `double::operator==` by
+ default. To compare floating-point while respecting an epsilon, an alternative
+ [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39)
+ could be used, for instance
+ @code {.cpp}
+ template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
+ inline bool is_same(T a, T b, T epsilon = std::numeric_limits<T>::epsilon()) noexcept
+ {
+ return std::abs(a - b) <= epsilon;
+ }
+ @endcode
+ Or you can self-defined operator equal function like this:
+ @code {.cpp}
+ bool my_equal(const_reference lhs, const_reference rhs) {
+ const auto lhs_type lhs.type();
+ const auto rhs_type rhs.type();
+ if (lhs_type == rhs_type) {
+ switch(lhs_type)
+ // self_defined case
+ case value_t::number_float:
+ return std::abs(lhs - rhs) <= std::numeric_limits<float>::epsilon();
+ // other cases remain the same with the original
+ ...
+ }
+ ...
+ }
+ @endcode
+
+ @note NaN values never compare equal to themselves or to other NaN values.
+
+ @param[in] lhs first JSON value to consider
+ @param[in] rhs second JSON value to consider
+ @return whether the values @a lhs and @a rhs are equal
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @complexity Linear.
+
+ @liveexample{The example demonstrates comparing several JSON
+ types.,operator__equal}
+
+ @since version 1.0.0
+ */
+ friend bool operator==(const_reference lhs, const_reference rhs) noexcept
+ {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+#endif
+ const auto lhs_type = lhs.type();
+ const auto rhs_type = rhs.type();
+
+ if (lhs_type == rhs_type)
+ {
+ switch (lhs_type)
+ {
+ case value_t::array:
+ return *lhs.m_value.array == *rhs.m_value.array;
+
+ case value_t::object:
+ return *lhs.m_value.object == *rhs.m_value.object;
+
+ case value_t::null:
+ return true;
+
+ case value_t::string:
+ return *lhs.m_value.string == *rhs.m_value.string;
+
+ case value_t::boolean:
+ return lhs.m_value.boolean == rhs.m_value.boolean;
+
+ case value_t::number_integer:
+ return lhs.m_value.number_integer == rhs.m_value.number_integer;
+
+ case value_t::number_unsigned:
+ return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
+
+ case value_t::number_float:
+ return lhs.m_value.number_float == rhs.m_value.number_float;
+
+ case value_t::binary:
+ return *lhs.m_value.binary == *rhs.m_value.binary;
+
+ case value_t::discarded:
+ default:
+ return false;
+ }
+ }
+ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
+ {
+ return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
+ }
+ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
+ {
+ return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
+ }
+ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
+ {
+ return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
+ }
+ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
+ {
+ return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
+ }
+ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
+ {
+ return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
+ }
+ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
+ {
+ return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+ }
+
+ return false;
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
+ }
+
+ /*!
+ @brief comparison: equal
+ @copydoc operator==(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
+ {
+ return lhs == basic_json(rhs);
+ }
+
+ /*!
+ @brief comparison: equal
+ @copydoc operator==(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
+ {
+ return basic_json(lhs) == rhs;
+ }
+
+ /*!
+ @brief comparison: not equal
+
+ Compares two JSON values for inequality by calculating `not (lhs == rhs)`.
+
+ @param[in] lhs first JSON value to consider
+ @param[in] rhs second JSON value to consider
+ @return whether the values @a lhs and @a rhs are not equal
+
+ @complexity Linear.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @liveexample{The example demonstrates comparing several JSON
+ types.,operator__notequal}
+
+ @since version 1.0.0
+ */
+ friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ /*!
+ @brief comparison: not equal
+ @copydoc operator!=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
+ {
+ return lhs != basic_json(rhs);
+ }
+
+ /*!
+ @brief comparison: not equal
+ @copydoc operator!=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
+ {
+ return basic_json(lhs) != rhs;
+ }
+
+ /*!
+ @brief comparison: less than
+
+ Compares whether one JSON value @a lhs is less than another JSON value @a
+ rhs according to the following rules:
+ - If @a lhs and @a rhs have the same type, the values are compared using
+ the default `<` operator.
+ - Integer and floating-point numbers are automatically converted before
+ comparison
+ - In case @a lhs and @a rhs have different types, the values are ignored
+ and the order of the types is considered, see
+ @ref operator<(const value_t, const value_t).
+
+ @param[in] lhs first JSON value to consider
+ @param[in] rhs second JSON value to consider
+ @return whether @a lhs is less than @a rhs
+
+ @complexity Linear.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @liveexample{The example demonstrates comparing several JSON
+ types.,operator__less}
+
+ @since version 1.0.0
+ */
+ friend bool operator<(const_reference lhs, const_reference rhs) noexcept
+ {
+ const auto lhs_type = lhs.type();
+ const auto rhs_type = rhs.type();
+
+ if (lhs_type == rhs_type)
+ {
+ switch (lhs_type)
+ {
+ case value_t::array:
+ // note parentheses are necessary, see
+ // https://github.com/nlohmann/json/issues/1530
+ return (*lhs.m_value.array) < (*rhs.m_value.array);
+
+ case value_t::object:
+ return (*lhs.m_value.object) < (*rhs.m_value.object);
+
+ case value_t::null:
+ return false;
+
+ case value_t::string:
+ return (*lhs.m_value.string) < (*rhs.m_value.string);
+
+ case value_t::boolean:
+ return (lhs.m_value.boolean) < (rhs.m_value.boolean);
+
+ case value_t::number_integer:
+ return (lhs.m_value.number_integer) < (rhs.m_value.number_integer);
+
+ case value_t::number_unsigned:
+ return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned);
+
+ case value_t::number_float:
+ return (lhs.m_value.number_float) < (rhs.m_value.number_float);
+
+ case value_t::binary:
+ return (*lhs.m_value.binary) < (*rhs.m_value.binary);
+
+ case value_t::discarded:
+ default:
+ return false;
+ }
+ }
+ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)
+ {
+ return static_cast<number_float_t>(lhs.m_value.number_integer) < rhs.m_value.number_float;
+ }
+ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)
+ {
+ return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_integer);
+ }
+ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)
+ {
+ return static_cast<number_float_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_float;
+ }
+ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)
+ {
+ return lhs.m_value.number_float < static_cast<number_float_t>(rhs.m_value.number_unsigned);
+ }
+ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)
+ {
+ return lhs.m_value.number_integer < static_cast<number_integer_t>(rhs.m_value.number_unsigned);
+ }
+ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)
+ {
+ return static_cast<number_integer_t>(lhs.m_value.number_unsigned) < rhs.m_value.number_integer;
+ }
+
+ // We only reach this line if we cannot compare values. In that case,
+ // we compare types. Note we have to call the operator explicitly,
+ // because MSVC has problems otherwise.
+ return operator<(lhs_type, rhs_type);
+ }
+
+ /*!
+ @brief comparison: less than
+ @copydoc operator<(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
+ {
+ return lhs < basic_json(rhs);
+ }
+
+ /*!
+ @brief comparison: less than
+ @copydoc operator<(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
+ {
+ return basic_json(lhs) < rhs;
+ }
+
+ /*!
+ @brief comparison: less than or equal
+
+ Compares whether one JSON value @a lhs is less than or equal to another
+ JSON value by calculating `not (rhs < lhs)`.
+
+ @param[in] lhs first JSON value to consider
+ @param[in] rhs second JSON value to consider
+ @return whether @a lhs is less than or equal to @a rhs
+
+ @complexity Linear.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @liveexample{The example demonstrates comparing several JSON
+ types.,operator__greater}
+
+ @since version 1.0.0
+ */
+ friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
+ {
+ return !(rhs < lhs);
+ }
+
+ /*!
+ @brief comparison: less than or equal
+ @copydoc operator<=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
+ {
+ return lhs <= basic_json(rhs);
+ }
+
+ /*!
+ @brief comparison: less than or equal
+ @copydoc operator<=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
+ {
+ return basic_json(lhs) <= rhs;
+ }
+
+ /*!
+ @brief comparison: greater than
+
+ Compares whether one JSON value @a lhs is greater than another
+ JSON value by calculating `not (lhs <= rhs)`.
+
+ @param[in] lhs first JSON value to consider
+ @param[in] rhs second JSON value to consider
+ @return whether @a lhs is greater than to @a rhs
+
+ @complexity Linear.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @liveexample{The example demonstrates comparing several JSON
+ types.,operator__lessequal}
+
+ @since version 1.0.0
+ */
+ friend bool operator>(const_reference lhs, const_reference rhs) noexcept
+ {
+ return !(lhs <= rhs);
+ }
+
+ /*!
+ @brief comparison: greater than
+ @copydoc operator>(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
+ {
+ return lhs > basic_json(rhs);
+ }
+
+ /*!
+ @brief comparison: greater than
+ @copydoc operator>(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
+ {
+ return basic_json(lhs) > rhs;
+ }
+
+ /*!
+ @brief comparison: greater than or equal
+
+ Compares whether one JSON value @a lhs is greater than or equal to another
+ JSON value by calculating `not (lhs < rhs)`.
+
+ @param[in] lhs first JSON value to consider
+ @param[in] rhs second JSON value to consider
+ @return whether @a lhs is greater than or equal to @a rhs
+
+ @complexity Linear.
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @liveexample{The example demonstrates comparing several JSON
+ types.,operator__greaterequal}
+
+ @since version 1.0.0
+ */
+ friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
+ {
+ return !(lhs < rhs);
+ }
+
+ /*!
+ @brief comparison: greater than or equal
+ @copydoc operator>=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
+ {
+ return lhs >= basic_json(rhs);
+ }
+
+ /*!
+ @brief comparison: greater than or equal
+ @copydoc operator>=(const_reference, const_reference)
+ */
+ template<typename ScalarType, typename std::enable_if<
+ std::is_scalar<ScalarType>::value, int>::type = 0>
+ friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
+ {
+ return basic_json(lhs) >= rhs;
+ }
+
+ /// @}
+
+ ///////////////////
+ // serialization //
+ ///////////////////
+
+ /// @name serialization
+ /// @{
+#ifndef JSON_NO_IO
+ /*!
+ @brief serialize to stream
+
+ Serialize the given JSON value @a j to the output stream @a o. The JSON
+ value will be serialized using the @ref dump member function.
+
+ - The indentation of the output can be controlled with the member variable
+ `width` of the output stream @a o. For instance, using the manipulator
+ `std::setw(4)` on @a o sets the indentation level to `4` and the
+ serialization result is the same as calling `dump(4)`.
+
+ - The indentation character can be controlled with the member variable
+ `fill` of the output stream @a o. For instance, the manipulator
+ `std::setfill('\\t')` sets indentation to use a tab character rather than
+ the default space character.
+
+ @param[in,out] o stream to serialize to
+ @param[in] j JSON value to serialize
+
+ @return the stream @a o
+
+ @throw type_error.316 if a string stored inside the JSON value is not
+ UTF-8 encoded
+
+ @complexity Linear.
+
+ @liveexample{The example below shows the serialization with different
+ parameters to `width` to adjust the indentation level.,operator_serialize}
+
+ @since version 1.0.0; indentation character added in version 3.0.0
+ */
+ friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
+ {
+ // read width member and use it as indentation parameter if nonzero
+ const bool pretty_print = o.width() > 0;
+ const auto indentation = pretty_print ? o.width() : 0;
+
+ // reset width to 0 for subsequent calls to this stream
+ o.width(0);
+
+ // do the actual serialization
+ serializer s(detail::output_adapter<char>(o), o.fill());
+ s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
+ return o;
+ }
+
+ /*!
+ @brief serialize to stream
+ @deprecated This stream operator is deprecated and will be removed in
+ future 4.0.0 of the library. Please use
+ @ref operator<<(std::ostream&, const basic_json&)
+ instead; that is, replace calls like `j >> o;` with `o << j;`.
+ @since version 1.0.0; deprecated since version 3.0.0
+ */
+ JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
+ friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
+ {
+ return o << j;
+ }
+#endif // JSON_NO_IO
+ /// @}
+
+
+ /////////////////////
+ // deserialization //
+ /////////////////////
+
+ /// @name deserialization
+ /// @{
+
+ /*!
+ @brief deserialize from a compatible input
+
+ @tparam InputType A compatible input, for instance
+ - an std::istream object
+ - a FILE pointer
+ - a C-style array of characters
+ - a pointer to a null-terminated string of single byte characters
+ - an object obj for which begin(obj) and end(obj) produces a valid pair of
+ iterators.
+
+ @param[in] i input to read from
+ @param[in] cb a parser callback function of type @ref parser_callback_t
+ which is used to control the deserialization by filtering unwanted values
+ (optional)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+ @param[in] ignore_comments whether comments should be ignored and treated
+ like whitespace (true) or yield a parse error (true); (optional, false by
+ default)
+
+ @return deserialized JSON value; in case of a parse error and
+ @a allow_exceptions set to `false`, the return value will be
+ value_t::discarded.
+
+ @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+ of input; expected string literal""`
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the parser callback function
+ @a cb or reading from the input @a i has a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from an array.,parse__array__parser_callback_t}
+
+ @liveexample{The example below demonstrates the `parse()` function with
+ and without callback function.,parse__string__parser_callback_t}
+
+ @liveexample{The example below demonstrates the `parse()` function with
+ and without callback function.,parse__istream__parser_callback_t}
+
+ @liveexample{The example below demonstrates the `parse()` function reading
+ from a contiguous container.,parse__contiguouscontainer__parser_callback_t}
+
+ @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to
+ ignore comments.
+ */
+ template<typename InputType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json parse(InputType&& i,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions = true,
+ const bool ignore_comments = false)
+ {
+ basic_json result;
+ parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
+ return result;
+ }
+
+ /*!
+ @brief deserialize from a pair of character iterators
+
+ The value_type of the iterator must be a integral type with size of 1, 2 or
+ 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32.
+
+ @param[in] first iterator to start of character range
+ @param[in] last iterator to end of character range
+ @param[in] cb a parser callback function of type @ref parser_callback_t
+ which is used to control the deserialization by filtering unwanted values
+ (optional)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+ @param[in] ignore_comments whether comments should be ignored and treated
+ like whitespace (true) or yield a parse error (true); (optional, false by
+ default)
+
+ @return deserialized JSON value; in case of a parse error and
+ @a allow_exceptions set to `false`, the return value will be
+ value_t::discarded.
+
+ @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+ of input; expected string literal""`
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+ */
+ template<typename IteratorType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json parse(IteratorType first,
+ IteratorType last,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions = true,
+ const bool ignore_comments = false)
+ {
+ basic_json result;
+ parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
+ return result;
+ }
+
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
+ static basic_json parse(detail::span_input_adapter&& i,
+ const parser_callback_t cb = nullptr,
+ const bool allow_exceptions = true,
+ const bool ignore_comments = false)
+ {
+ basic_json result;
+ parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
+ return result;
+ }
+
+ /*!
+ @brief check if the input is valid JSON
+
+ Unlike the @ref parse(InputType&&, const parser_callback_t,const bool)
+ function, this function neither throws an exception in case of invalid JSON
+ input (i.e., a parse error) nor creates diagnostic information.
+
+ @tparam InputType A compatible input, for instance
+ - an std::istream object
+ - a FILE pointer
+ - a C-style array of characters
+ - a pointer to a null-terminated string of single byte characters
+ - an object obj for which begin(obj) and end(obj) produces a valid pair of
+ iterators.
+
+ @param[in] i input to read from
+ @param[in] ignore_comments whether comments should be ignored and treated
+ like whitespace (true) or yield a parse error (true); (optional, false by
+ default)
+
+ @return Whether the input read from @a i is valid JSON.
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `accept()` function reading
+ from a string.,accept__string}
+ */
+ template<typename InputType>
+ static bool accept(InputType&& i,
+ const bool ignore_comments = false)
+ {
+ return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
+ }
+
+ template<typename IteratorType>
+ static bool accept(IteratorType first, IteratorType last,
+ const bool ignore_comments = false)
+ {
+ return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
+ }
+
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
+ static bool accept(detail::span_input_adapter&& i,
+ const bool ignore_comments = false)
+ {
+ return parser(i.get(), nullptr, false, ignore_comments).accept(true);
+ }
+
+ /*!
+ @brief generate SAX events
+
+ The SAX event lister must follow the interface of @ref json_sax.
+
+ This function reads from a compatible input. Examples are:
+ - an std::istream object
+ - a FILE pointer
+ - a C-style array of characters
+ - a pointer to a null-terminated string of single byte characters
+ - an object obj for which begin(obj) and end(obj) produces a valid pair of
+ iterators.
+
+ @param[in] i input to read from
+ @param[in,out] sax SAX event listener
+ @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON)
+ @param[in] strict whether the input has to be consumed completely
+ @param[in] ignore_comments whether comments should be ignored and treated
+ like whitespace (true) or yield a parse error (true); (optional, false by
+ default); only applies to the JSON file format.
+
+ @return return value of the last processed SAX event
+
+ @throw parse_error.101 if a parse error occurs; example: `""unexpected end
+ of input; expected string literal""`
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser. The complexity can be higher if the SAX consumer @a sax has
+ a super-linear complexity.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below demonstrates the `sax_parse()` function
+ reading from string and processing the events with a user-defined SAX
+ event consumer.,sax_parse}
+
+ @since version 3.2.0
+ */
+ template <typename InputType, typename SAX>
+ JSON_HEDLEY_NON_NULL(2)
+ static bool sax_parse(InputType&& i, SAX* sax,
+ input_format_t format = input_format_t::json,
+ const bool strict = true,
+ const bool ignore_comments = false)
+ {
+ auto ia = detail::input_adapter(std::forward<InputType>(i));
+ return format == input_format_t::json
+ ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+ : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+ }
+
+ template<class IteratorType, class SAX>
+ JSON_HEDLEY_NON_NULL(3)
+ static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
+ input_format_t format = input_format_t::json,
+ const bool strict = true,
+ const bool ignore_comments = false)
+ {
+ auto ia = detail::input_adapter(std::move(first), std::move(last));
+ return format == input_format_t::json
+ ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+ : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+ }
+
+ template <typename SAX>
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
+ JSON_HEDLEY_NON_NULL(2)
+ static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
+ input_format_t format = input_format_t::json,
+ const bool strict = true,
+ const bool ignore_comments = false)
+ {
+ auto ia = i.get();
+ return format == input_format_t::json
+ // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+ ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
+ // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+ : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia)).sax_parse(format, sax, strict);
+ }
+#ifndef JSON_NO_IO
+ /*!
+ @brief deserialize from stream
+ @deprecated This stream operator is deprecated and will be removed in
+ version 4.0.0 of the library. Please use
+ @ref operator>>(std::istream&, basic_json&)
+ instead; that is, replace calls like `j << i;` with `i >> j;`.
+ @since version 1.0.0; deprecated since version 3.0.0
+ */
+ JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
+ friend std::istream& operator<<(basic_json& j, std::istream& i)
+ {
+ return operator>>(i, j);
+ }
+
+ /*!
+ @brief deserialize from stream
+
+ Deserializes an input stream to a JSON value.
+
+ @param[in,out] i input stream to read a serialized JSON value from
+ @param[in,out] j JSON value to write the deserialized input to
+
+ @throw parse_error.101 in case of an unexpected token
+ @throw parse_error.102 if to_unicode fails or surrogate error
+ @throw parse_error.103 if to_unicode fails
+
+ @complexity Linear in the length of the input. The parser is a predictive
+ LL(1) parser.
+
+ @note A UTF-8 byte order mark is silently ignored.
+
+ @liveexample{The example below shows how a JSON value is constructed by
+ reading a serialization from a stream.,operator_deserialize}
+
+ @sa parse(std::istream&, const parser_callback_t) for a variant with a
+ parser callback function to filter values while parsing
+
+ @since version 1.0.0
+ */
+ friend std::istream& operator>>(std::istream& i, basic_json& j)
+ {
+ parser(detail::input_adapter(i)).parse(false, j);
+ return i;
+ }
+#endif // JSON_NO_IO
+ /// @}
+
+ ///////////////////////////
+ // convenience functions //
+ ///////////////////////////
+
+ /*!
+ @brief return the type as string
+
+ Returns the type name as string to be used in error messages - usually to
+ indicate that a function was called on a wrong JSON type.
+
+ @return a string representation of a the @a m_type member:
+ Value type | return value
+ ----------- | -------------
+ null | `"null"`
+ boolean | `"boolean"`
+ string | `"string"`
+ number | `"number"` (for all number types)
+ object | `"object"`
+ array | `"array"`
+ binary | `"binary"`
+ discarded | `"discarded"`
+
+ @exceptionsafety No-throw guarantee: this function never throws exceptions.
+
+ @complexity Constant.
+
+ @liveexample{The following code exemplifies `type_name()` for all JSON
+ types.,type_name}
+
+ @sa see @ref type() -- return the type of the JSON value
+ @sa see @ref operator value_t() -- return the type of the JSON value (implicit)
+
+ @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept`
+ since 3.0.0
+ */
+ JSON_HEDLEY_RETURNS_NON_NULL
+ const char* type_name() const noexcept
+ {
+ {
+ switch (m_type)
+ {
+ case value_t::null:
+ return "null";
+ case value_t::object:
+ return "object";
+ case value_t::array:
+ return "array";
+ case value_t::string:
+ return "string";
+ case value_t::boolean:
+ return "boolean";
+ case value_t::binary:
+ return "binary";
+ case value_t::discarded:
+ return "discarded";
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ default:
+ return "number";
+ }
+ }
+ }
+
+
+ JSON_PRIVATE_UNLESS_TESTED:
+ //////////////////////
+ // member variables //
+ //////////////////////
+
+ /// the type of the current element
+ value_t m_type = value_t::null;
+
+ /// the value of the current element
+ json_value m_value = {};
+
+#if JSON_DIAGNOSTICS
+ /// a pointer to a parent value (for debugging purposes)
+ basic_json* m_parent = nullptr;
+#endif
+
+ //////////////////////////////////////////
+ // binary serialization/deserialization //
+ //////////////////////////////////////////
+
+ /// @name binary serialization/deserialization support
+ /// @{
+
+ public:
+ /*!
+ @brief create a CBOR serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
+ Binary Object Representation) serialization format. CBOR is a binary
+ serialization format which aims to be more compact than JSON itself, yet
+ more efficient to parse.
+
+ The library uses the following mapping from JSON values types to
+ CBOR types according to the CBOR specification (RFC 7049):
+
+ JSON value type | value/range | CBOR type | first byte
+ --------------- | ------------------------------------------ | ---------------------------------- | ---------------
+ null | `null` | Null | 0xF6
+ boolean | `true` | True | 0xF5
+ boolean | `false` | False | 0xF4
+ number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B
+ number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A
+ number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39
+ number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38
+ number_integer | -24..-1 | Negative integer | 0x20..0x37
+ number_integer | 0..23 | Integer | 0x00..0x17
+ number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18
+ number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
+ number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
+ number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
+ number_unsigned | 0..23 | Integer | 0x00..0x17
+ number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18
+ number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19
+ number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A
+ number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B
+ number_float | *any value representable by a float* | Single-Precision Float | 0xFA
+ number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB
+ string | *length*: 0..23 | UTF-8 string | 0x60..0x77
+ string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78
+ string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79
+ string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A
+ string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B
+ array | *size*: 0..23 | array | 0x80..0x97
+ array | *size*: 23..255 | array (1 byte follow) | 0x98
+ array | *size*: 256..65535 | array (2 bytes follow) | 0x99
+ array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A
+ array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B
+ object | *size*: 0..23 | map | 0xA0..0xB7
+ object | *size*: 23..255 | map (1 byte follow) | 0xB8
+ object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
+ object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
+ object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
+ binary | *size*: 0..23 | byte string | 0x40..0x57
+ binary | *size*: 23..255 | byte string (1 byte follow) | 0x58
+ binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59
+ binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
+ binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
+
+ Binary values with subtype are mapped to tagged values (0xD8..0xDB)
+ depending on the subtype, followed by a byte string, see "binary" cells
+ in the table above.
+
+ @note The mapping is **complete** in the sense that any JSON value type
+ can be converted to a CBOR value.
+
+ @note If NaN or Infinity are stored inside a JSON number, they are
+ serialized properly. This behavior differs from the @ref dump()
+ function which serializes NaN or Infinity to `null`.
+
+ @note The following CBOR types are not used in the conversion:
+ - UTF-8 strings terminated by "break" (0x7F)
+ - arrays terminated by "break" (0x9F)
+ - maps terminated by "break" (0xBF)
+ - byte strings terminated by "break" (0x5F)
+ - date/time (0xC0..0xC1)
+ - bignum (0xC2..0xC3)
+ - decimal fraction (0xC4)
+ - bigfloat (0xC5)
+ - expected conversions (0xD5..0xD7)
+ - simple values (0xE0..0xF3, 0xF8)
+ - undefined (0xF7)
+ - half-precision floats (0xF9)
+ - break (0xFF)
+
+ @param[in] j JSON value to serialize
+ @return CBOR serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in CBOR format.,to_cbor}
+
+ @sa http://cbor.io
+ @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+ analogous deserialization
+ @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
+ @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+ related UBJSON format
+
+ @since version 2.0.9; compact representation of floating-point numbers
+ since version 3.8.0
+ */
+ static std::vector<std::uint8_t> to_cbor(const basic_json& j)
+ {
+ std::vector<std::uint8_t> result;
+ to_cbor(j, result);
+ return result;
+ }
+
+ static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+ {
+ binary_writer<std::uint8_t>(o).write_cbor(j);
+ }
+
+ static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
+ {
+ binary_writer<char>(o).write_cbor(j);
+ }
+
+ /*!
+ @brief create a MessagePack serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the MessagePack
+ serialization format. MessagePack is a binary serialization format which
+ aims to be more compact than JSON itself, yet more efficient to parse.
+
+ The library uses the following mapping from JSON values types to
+ MessagePack types according to the MessagePack specification:
+
+ JSON value type | value/range | MessagePack type | first byte
+ --------------- | --------------------------------- | ---------------- | ----------
+ null | `null` | nil | 0xC0
+ boolean | `true` | true | 0xC3
+ boolean | `false` | false | 0xC2
+ number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3
+ number_integer | -2147483648..-32769 | int32 | 0xD2
+ number_integer | -32768..-129 | int16 | 0xD1
+ number_integer | -128..-33 | int8 | 0xD0
+ number_integer | -32..-1 | negative fixint | 0xE0..0xFF
+ number_integer | 0..127 | positive fixint | 0x00..0x7F
+ number_integer | 128..255 | uint 8 | 0xCC
+ number_integer | 256..65535 | uint 16 | 0xCD
+ number_integer | 65536..4294967295 | uint 32 | 0xCE
+ number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF
+ number_unsigned | 0..127 | positive fixint | 0x00..0x7F
+ number_unsigned | 128..255 | uint 8 | 0xCC
+ number_unsigned | 256..65535 | uint 16 | 0xCD
+ number_unsigned | 65536..4294967295 | uint 32 | 0xCE
+ number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF
+ number_float | *any value representable by a float* | float 32 | 0xCA
+ number_float | *any value NOT representable by a float* | float 64 | 0xCB
+ string | *length*: 0..31 | fixstr | 0xA0..0xBF
+ string | *length*: 32..255 | str 8 | 0xD9
+ string | *length*: 256..65535 | str 16 | 0xDA
+ string | *length*: 65536..4294967295 | str 32 | 0xDB
+ array | *size*: 0..15 | fixarray | 0x90..0x9F
+ array | *size*: 16..65535 | array 16 | 0xDC
+ array | *size*: 65536..4294967295 | array 32 | 0xDD
+ object | *size*: 0..15 | fix map | 0x80..0x8F
+ object | *size*: 16..65535 | map 16 | 0xDE
+ object | *size*: 65536..4294967295 | map 32 | 0xDF
+ binary | *size*: 0..255 | bin 8 | 0xC4
+ binary | *size*: 256..65535 | bin 16 | 0xC5
+ binary | *size*: 65536..4294967295 | bin 32 | 0xC6
+
+ @note The mapping is **complete** in the sense that any JSON value type
+ can be converted to a MessagePack value.
+
+ @note The following values can **not** be converted to a MessagePack value:
+ - strings with more than 4294967295 bytes
+ - byte strings with more than 4294967295 bytes
+ - arrays with more than 4294967295 elements
+ - objects with more than 4294967295 elements
+
+ @note Any MessagePack output created @ref to_msgpack can be successfully
+ parsed by @ref from_msgpack.
+
+ @note If NaN or Infinity are stored inside a JSON number, they are
+ serialized properly. This behavior differs from the @ref dump()
+ function which serializes NaN or Infinity to `null`.
+
+ @param[in] j JSON value to serialize
+ @return MessagePack serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in MessagePack format.,to_msgpack}
+
+ @sa http://msgpack.org
+ @sa see @ref from_msgpack for the analogous deserialization
+ @sa see @ref to_cbor(const basic_json& for the related CBOR format
+ @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+ related UBJSON format
+
+ @since version 2.0.9
+ */
+ static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
+ {
+ std::vector<std::uint8_t> result;
+ to_msgpack(j, result);
+ return result;
+ }
+
+ static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+ {
+ binary_writer<std::uint8_t>(o).write_msgpack(j);
+ }
+
+ static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
+ {
+ binary_writer<char>(o).write_msgpack(j);
+ }
+
+ /*!
+ @brief create a UBJSON serialization of a given JSON value
+
+ Serializes a given JSON value @a j to a byte vector using the UBJSON
+ (Universal Binary JSON) serialization format. UBJSON aims to be more compact
+ than JSON itself, yet more efficient to parse.
+
+ The library uses the following mapping from JSON values types to
+ UBJSON types according to the UBJSON specification:
+
+ JSON value type | value/range | UBJSON type | marker
+ --------------- | --------------------------------- | ----------- | ------
+ null | `null` | null | `Z`
+ boolean | `true` | true | `T`
+ boolean | `false` | false | `F`
+ number_integer | -9223372036854775808..-2147483649 | int64 | `L`
+ number_integer | -2147483648..-32769 | int32 | `l`
+ number_integer | -32768..-129 | int16 | `I`
+ number_integer | -128..127 | int8 | `i`
+ number_integer | 128..255 | uint8 | `U`
+ number_integer | 256..32767 | int16 | `I`
+ number_integer | 32768..2147483647 | int32 | `l`
+ number_integer | 2147483648..9223372036854775807 | int64 | `L`
+ number_unsigned | 0..127 | int8 | `i`
+ number_unsigned | 128..255 | uint8 | `U`
+ number_unsigned | 256..32767 | int16 | `I`
+ number_unsigned | 32768..2147483647 | int32 | `l`
+ number_unsigned | 2147483648..9223372036854775807 | int64 | `L`
+ number_unsigned | 2147483649..18446744073709551615 | high-precision | `H`
+ number_float | *any value* | float64 | `D`
+ string | *with shortest length indicator* | string | `S`
+ array | *see notes on optimized format* | array | `[`
+ object | *see notes on optimized format* | map | `{`
+
+ @note The mapping is **complete** in the sense that any JSON value type
+ can be converted to a UBJSON value.
+
+ @note The following values can **not** be converted to a UBJSON value:
+ - strings with more than 9223372036854775807 bytes (theoretical)
+
+ @note The following markers are not used in the conversion:
+ - `Z`: no-op values are not created.
+ - `C`: single-byte strings are serialized with `S` markers.
+
+ @note Any UBJSON output created @ref to_ubjson can be successfully parsed
+ by @ref from_ubjson.
+
+ @note If NaN or Infinity are stored inside a JSON number, they are
+ serialized properly. This behavior differs from the @ref dump()
+ function which serializes NaN or Infinity to `null`.
+
+ @note The optimized formats for containers are supported: Parameter
+ @a use_size adds size information to the beginning of a container and
+ removes the closing marker. Parameter @a use_type further checks
+ whether all elements of a container have the same type and adds the
+ type marker to the beginning of the container. The @a use_type
+ parameter must only be used together with @a use_size = true. Note
+ that @a use_size = true alone may result in larger representations -
+ the benefit of this parameter is that the receiving side is
+ immediately informed on the number of elements of the container.
+
+ @note If the JSON data contains the binary type, the value stored is a list
+ of integers, as suggested by the UBJSON documentation. In particular,
+ this means that serialization and the deserialization of a JSON
+ containing binary values into UBJSON and back will result in a
+ different JSON object.
+
+ @param[in] j JSON value to serialize
+ @param[in] use_size whether to add size annotations to container types
+ @param[in] use_type whether to add type annotations to container types
+ (must be combined with @a use_size = true)
+ @return UBJSON serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in UBJSON format.,to_ubjson}
+
+ @sa http://ubjson.org
+ @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the
+ analogous deserialization
+ @sa see @ref to_cbor(const basic_json& for the related CBOR format
+ @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
+
+ @since version 3.1.0
+ */
+ static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
+ const bool use_size = false,
+ const bool use_type = false)
+ {
+ std::vector<std::uint8_t> result;
+ to_ubjson(j, result, use_size, use_type);
+ return result;
+ }
+
+ static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
+ const bool use_size = false, const bool use_type = false)
+ {
+ binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
+ }
+
+ static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
+ const bool use_size = false, const bool use_type = false)
+ {
+ binary_writer<char>(o).write_ubjson(j, use_size, use_type);
+ }
+
+
+ /*!
+ @brief Serializes the given JSON object `j` to BSON and returns a vector
+ containing the corresponding BSON-representation.
+
+ BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are
+ stored as a single entity (a so-called document).
+
+ The library uses the following mapping from JSON values types to BSON types:
+
+ JSON value type | value/range | BSON type | marker
+ --------------- | --------------------------------- | ----------- | ------
+ null | `null` | null | 0x0A
+ boolean | `true`, `false` | boolean | 0x08
+ number_integer | -9223372036854775808..-2147483649 | int64 | 0x12
+ number_integer | -2147483648..2147483647 | int32 | 0x10
+ number_integer | 2147483648..9223372036854775807 | int64 | 0x12
+ number_unsigned | 0..2147483647 | int32 | 0x10
+ number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12
+ number_unsigned | 9223372036854775808..18446744073709551615| -- | --
+ number_float | *any value* | double | 0x01
+ string | *any value* | string | 0x02
+ array | *any value* | document | 0x04
+ object | *any value* | document | 0x03
+ binary | *any value* | binary | 0x05
+
+ @warning The mapping is **incomplete**, since only JSON-objects (and things
+ contained therein) can be serialized to BSON.
+ Also, integers larger than 9223372036854775807 cannot be serialized to BSON,
+ and the keys may not contain U+0000, since they are serialized a
+ zero-terminated c-strings.
+
+ @throw out_of_range.407 if `j.is_number_unsigned() && j.get<std::uint64_t>() > 9223372036854775807`
+ @throw out_of_range.409 if a key in `j` contains a NULL (U+0000)
+ @throw type_error.317 if `!j.is_object()`
+
+ @pre The input `j` is required to be an object: `j.is_object() == true`.
+
+ @note Any BSON output created via @ref to_bson can be successfully parsed
+ by @ref from_bson.
+
+ @param[in] j JSON value to serialize
+ @return BSON serialization as byte vector
+
+ @complexity Linear in the size of the JSON value @a j.
+
+ @liveexample{The example shows the serialization of a JSON value to a byte
+ vector in BSON format.,to_bson}
+
+ @sa http://bsonspec.org/spec.html
+ @sa see @ref from_bson(detail::input_adapter&&, const bool strict) for the
+ analogous deserialization
+ @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+ related UBJSON format
+ @sa see @ref to_cbor(const basic_json&) for the related CBOR format
+ @sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
+ */
+ static std::vector<std::uint8_t> to_bson(const basic_json& j)
+ {
+ std::vector<std::uint8_t> result;
+ to_bson(j, result);
+ return result;
+ }
+
+ /*!
+ @brief Serializes the given JSON object `j` to BSON and forwards the
+ corresponding BSON-representation to the given output_adapter `o`.
+ @param j The JSON object to convert to BSON.
+ @param o The output adapter that receives the binary BSON representation.
+ @pre The input `j` shall be an object: `j.is_object() == true`
+ @sa see @ref to_bson(const basic_json&)
+ */
+ static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
+ {
+ binary_writer<std::uint8_t>(o).write_bson(j);
+ }
+
+ /*!
+ @copydoc to_bson(const basic_json&, detail::output_adapter<std::uint8_t>)
+ */
+ static void to_bson(const basic_json& j, detail::output_adapter<char> o)
+ {
+ binary_writer<char>(o).write_bson(j);
+ }
+
+
+ /*!
+ @brief create a JSON value from an input in CBOR format
+
+ Deserializes a given input @a i to a JSON value using the CBOR (Concise
+ Binary Object Representation) serialization format.
+
+ The library maps CBOR types to JSON value types as follows:
+
+ CBOR type | JSON value type | first byte
+ ---------------------- | --------------- | ----------
+ Integer | number_unsigned | 0x00..0x17
+ Unsigned integer | number_unsigned | 0x18
+ Unsigned integer | number_unsigned | 0x19
+ Unsigned integer | number_unsigned | 0x1A
+ Unsigned integer | number_unsigned | 0x1B
+ Negative integer | number_integer | 0x20..0x37
+ Negative integer | number_integer | 0x38
+ Negative integer | number_integer | 0x39
+ Negative integer | number_integer | 0x3A
+ Negative integer | number_integer | 0x3B
+ Byte string | binary | 0x40..0x57
+ Byte string | binary | 0x58
+ Byte string | binary | 0x59
+ Byte string | binary | 0x5A
+ Byte string | binary | 0x5B
+ UTF-8 string | string | 0x60..0x77
+ UTF-8 string | string | 0x78
+ UTF-8 string | string | 0x79
+ UTF-8 string | string | 0x7A
+ UTF-8 string | string | 0x7B
+ UTF-8 string | string | 0x7F
+ array | array | 0x80..0x97
+ array | array | 0x98
+ array | array | 0x99
+ array | array | 0x9A
+ array | array | 0x9B
+ array | array | 0x9F
+ map | object | 0xA0..0xB7
+ map | object | 0xB8
+ map | object | 0xB9
+ map | object | 0xBA
+ map | object | 0xBB
+ map | object | 0xBF
+ False | `false` | 0xF4
+ True | `true` | 0xF5
+ Null | `null` | 0xF6
+ Half-Precision Float | number_float | 0xF9
+ Single-Precision Float | number_float | 0xFA
+ Double-Precision Float | number_float | 0xFB
+
+ @warning The mapping is **incomplete** in the sense that not all CBOR
+ types can be converted to a JSON value. The following CBOR types
+ are not supported and will yield parse errors (parse_error.112):
+ - date/time (0xC0..0xC1)
+ - bignum (0xC2..0xC3)
+ - decimal fraction (0xC4)
+ - bigfloat (0xC5)
+ - expected conversions (0xD5..0xD7)
+ - simple values (0xE0..0xF3, 0xF8)
+ - undefined (0xF7)
+
+ @warning CBOR allows map keys of any type, whereas JSON only allows
+ strings as keys in object values. Therefore, CBOR maps with keys
+ other than UTF-8 strings are rejected (parse_error.113).
+
+ @note Any CBOR output created @ref to_cbor can be successfully parsed by
+ @ref from_cbor.
+
+ @param[in] i an input in CBOR format convertible to an input adapter
+ @param[in] strict whether to expect the input to be consumed until EOF
+ (true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+ @param[in] tag_handler how to treat CBOR tags (optional, error by default)
+
+ @return deserialized JSON value; in case of a parse error and
+ @a allow_exceptions set to `false`, the return value will be
+ value_t::discarded.
+
+ @throw parse_error.110 if the given input ends prematurely or the end of
+ file was not reached when @a strict was set to true
+ @throw parse_error.112 if unsupported features from CBOR were
+ used in the given input @a v or if the input is not valid CBOR
+ @throw parse_error.113 if a string was expected as map key, but not found
+
+ @complexity Linear in the size of the input @a i.
+
+ @liveexample{The example shows the deserialization of a byte vector in CBOR
+ format to a JSON value.,from_cbor}
+
+ @sa http://cbor.io
+ @sa see @ref to_cbor(const basic_json&) for the analogous serialization
+ @sa see @ref from_msgpack(InputType&&, const bool, const bool) for the
+ related MessagePack format
+ @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the
+ related UBJSON format
+
+ @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+ consume input adapters, removed start_index parameter, and added
+ @a strict parameter since 3.0.0; added @a allow_exceptions parameter
+ since 3.2.0; added @a tag_handler parameter since 3.9.0.
+ */
+ template<typename InputType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_cbor(InputType&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true,
+ const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::forward<InputType>(i));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ /*!
+ @copydoc from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t)
+ */
+ template<typename IteratorType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_cbor(IteratorType first, IteratorType last,
+ const bool strict = true,
+ const bool allow_exceptions = true,
+ const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::move(first), std::move(last));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ template<typename T>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
+ static basic_json from_cbor(const T* ptr, std::size_t len,
+ const bool strict = true,
+ const bool allow_exceptions = true,
+ const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+ {
+ return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
+ }
+
+
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
+ static basic_json from_cbor(detail::span_input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true,
+ const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = i.get();
+ // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ /*!
+ @brief create a JSON value from an input in MessagePack format
+
+ Deserializes a given input @a i to a JSON value using the MessagePack
+ serialization format.
+
+ The library maps MessagePack types to JSON value types as follows:
+
+ MessagePack type | JSON value type | first byte
+ ---------------- | --------------- | ----------
+ positive fixint | number_unsigned | 0x00..0x7F
+ fixmap | object | 0x80..0x8F
+ fixarray | array | 0x90..0x9F
+ fixstr | string | 0xA0..0xBF
+ nil | `null` | 0xC0
+ false | `false` | 0xC2
+ true | `true` | 0xC3
+ float 32 | number_float | 0xCA
+ float 64 | number_float | 0xCB
+ uint 8 | number_unsigned | 0xCC
+ uint 16 | number_unsigned | 0xCD
+ uint 32 | number_unsigned | 0xCE
+ uint 64 | number_unsigned | 0xCF
+ int 8 | number_integer | 0xD0
+ int 16 | number_integer | 0xD1
+ int 32 | number_integer | 0xD2
+ int 64 | number_integer | 0xD3
+ str 8 | string | 0xD9
+ str 16 | string | 0xDA
+ str 32 | string | 0xDB
+ array 16 | array | 0xDC
+ array 32 | array | 0xDD
+ map 16 | object | 0xDE
+ map 32 | object | 0xDF
+ bin 8 | binary | 0xC4
+ bin 16 | binary | 0xC5
+ bin 32 | binary | 0xC6
+ ext 8 | binary | 0xC7
+ ext 16 | binary | 0xC8
+ ext 32 | binary | 0xC9
+ fixext 1 | binary | 0xD4
+ fixext 2 | binary | 0xD5
+ fixext 4 | binary | 0xD6
+ fixext 8 | binary | 0xD7
+ fixext 16 | binary | 0xD8
+ negative fixint | number_integer | 0xE0-0xFF
+
+ @note Any MessagePack output created @ref to_msgpack can be successfully
+ parsed by @ref from_msgpack.
+
+ @param[in] i an input in MessagePack format convertible to an input
+ adapter
+ @param[in] strict whether to expect the input to be consumed until EOF
+ (true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value; in case of a parse error and
+ @a allow_exceptions set to `false`, the return value will be
+ value_t::discarded.
+
+ @throw parse_error.110 if the given input ends prematurely or the end of
+ file was not reached when @a strict was set to true
+ @throw parse_error.112 if unsupported features from MessagePack were
+ used in the given input @a i or if the input is not valid MessagePack
+ @throw parse_error.113 if a string was expected as map key, but not found
+
+ @complexity Linear in the size of the input @a i.
+
+ @liveexample{The example shows the deserialization of a byte vector in
+ MessagePack format to a JSON value.,from_msgpack}
+
+ @sa http://msgpack.org
+ @sa see @ref to_msgpack(const basic_json&) for the analogous serialization
+ @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+ related CBOR format
+ @sa see @ref from_ubjson(InputType&&, const bool, const bool) for
+ the related UBJSON format
+ @sa see @ref from_bson(InputType&&, const bool, const bool) for
+ the related BSON format
+
+ @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
+ consume input adapters, removed start_index parameter, and added
+ @a strict parameter since 3.0.0; added @a allow_exceptions parameter
+ since 3.2.0
+ */
+ template<typename InputType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_msgpack(InputType&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::forward<InputType>(i));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ /*!
+ @copydoc from_msgpack(InputType&&, const bool, const bool)
+ */
+ template<typename IteratorType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_msgpack(IteratorType first, IteratorType last,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::move(first), std::move(last));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+
+ template<typename T>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
+ static basic_json from_msgpack(const T* ptr, std::size_t len,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
+ }
+
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
+ static basic_json from_msgpack(detail::span_input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = i.get();
+ // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+
+ /*!
+ @brief create a JSON value from an input in UBJSON format
+
+ Deserializes a given input @a i to a JSON value using the UBJSON (Universal
+ Binary JSON) serialization format.
+
+ The library maps UBJSON types to JSON value types as follows:
+
+ UBJSON type | JSON value type | marker
+ ----------- | --------------------------------------- | ------
+ no-op | *no value, next value is read* | `N`
+ null | `null` | `Z`
+ false | `false` | `F`
+ true | `true` | `T`
+ float32 | number_float | `d`
+ float64 | number_float | `D`
+ uint8 | number_unsigned | `U`
+ int8 | number_integer | `i`
+ int16 | number_integer | `I`
+ int32 | number_integer | `l`
+ int64 | number_integer | `L`
+ high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H'
+ string | string | `S`
+ char | string | `C`
+ array | array (optimized values are supported) | `[`
+ object | object (optimized values are supported) | `{`
+
+ @note The mapping is **complete** in the sense that any UBJSON value can
+ be converted to a JSON value.
+
+ @param[in] i an input in UBJSON format convertible to an input adapter
+ @param[in] strict whether to expect the input to be consumed until EOF
+ (true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value; in case of a parse error and
+ @a allow_exceptions set to `false`, the return value will be
+ value_t::discarded.
+
+ @throw parse_error.110 if the given input ends prematurely or the end of
+ file was not reached when @a strict was set to true
+ @throw parse_error.112 if a parse error occurs
+ @throw parse_error.113 if a string could not be parsed successfully
+
+ @complexity Linear in the size of the input @a i.
+
+ @liveexample{The example shows the deserialization of a byte vector in
+ UBJSON format to a JSON value.,from_ubjson}
+
+ @sa http://ubjson.org
+ @sa see @ref to_ubjson(const basic_json&, const bool, const bool) for the
+ analogous serialization
+ @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+ related CBOR format
+ @sa see @ref from_msgpack(InputType&&, const bool, const bool) for
+ the related MessagePack format
+ @sa see @ref from_bson(InputType&&, const bool, const bool) for
+ the related BSON format
+
+ @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
+ */
+ template<typename InputType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_ubjson(InputType&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::forward<InputType>(i));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ /*!
+ @copydoc from_ubjson(InputType&&, const bool, const bool)
+ */
+ template<typename IteratorType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_ubjson(IteratorType first, IteratorType last,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::move(first), std::move(last));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ template<typename T>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
+ static basic_json from_ubjson(const T* ptr, std::size_t len,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
+ }
+
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
+ static basic_json from_ubjson(detail::span_input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = i.get();
+ // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+
+ /*!
+ @brief Create a JSON value from an input in BSON format
+
+ Deserializes a given input @a i to a JSON value using the BSON (Binary JSON)
+ serialization format.
+
+ The library maps BSON record types to JSON value types as follows:
+
+ BSON type | BSON marker byte | JSON value type
+ --------------- | ---------------- | ---------------------------
+ double | 0x01 | number_float
+ string | 0x02 | string
+ document | 0x03 | object
+ array | 0x04 | array
+ binary | 0x05 | binary
+ undefined | 0x06 | still unsupported
+ ObjectId | 0x07 | still unsupported
+ boolean | 0x08 | boolean
+ UTC Date-Time | 0x09 | still unsupported
+ null | 0x0A | null
+ Regular Expr. | 0x0B | still unsupported
+ DB Pointer | 0x0C | still unsupported
+ JavaScript Code | 0x0D | still unsupported
+ Symbol | 0x0E | still unsupported
+ JavaScript Code | 0x0F | still unsupported
+ int32 | 0x10 | number_integer
+ Timestamp | 0x11 | still unsupported
+ 128-bit decimal float | 0x13 | still unsupported
+ Max Key | 0x7F | still unsupported
+ Min Key | 0xFF | still unsupported
+
+ @warning The mapping is **incomplete**. The unsupported mappings
+ are indicated in the table above.
+
+ @param[in] i an input in BSON format convertible to an input adapter
+ @param[in] strict whether to expect the input to be consumed until EOF
+ (true by default)
+ @param[in] allow_exceptions whether to throw exceptions in case of a
+ parse error (optional, true by default)
+
+ @return deserialized JSON value; in case of a parse error and
+ @a allow_exceptions set to `false`, the return value will be
+ value_t::discarded.
+
+ @throw parse_error.114 if an unsupported BSON record type is encountered
+
+ @complexity Linear in the size of the input @a i.
+
+ @liveexample{The example shows the deserialization of a byte vector in
+ BSON format to a JSON value.,from_bson}
+
+ @sa http://bsonspec.org/spec.html
+ @sa see @ref to_bson(const basic_json&) for the analogous serialization
+ @sa see @ref from_cbor(InputType&&, const bool, const bool, const cbor_tag_handler_t) for the
+ related CBOR format
+ @sa see @ref from_msgpack(InputType&&, const bool, const bool) for
+ the related MessagePack format
+ @sa see @ref from_ubjson(InputType&&, const bool, const bool) for the
+ related UBJSON format
+ */
+ template<typename InputType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_bson(InputType&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::forward<InputType>(i));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ /*!
+ @copydoc from_bson(InputType&&, const bool, const bool)
+ */
+ template<typename IteratorType>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json from_bson(IteratorType first, IteratorType last,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = detail::input_adapter(std::move(first), std::move(last));
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+
+ template<typename T>
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
+ static basic_json from_bson(const T* ptr, std::size_t len,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ return from_bson(ptr, ptr + len, strict, allow_exceptions);
+ }
+
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
+ static basic_json from_bson(detail::span_input_adapter&& i,
+ const bool strict = true,
+ const bool allow_exceptions = true)
+ {
+ basic_json result;
+ detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
+ auto ia = i.get();
+ // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
+ const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict);
+ return res ? result : basic_json(value_t::discarded);
+ }
+ /// @}
+
+ //////////////////////////
+ // JSON Pointer support //
+ //////////////////////////
+
+ /// @name JSON Pointer functions
+ /// @{
+
+ /*!
+ @brief access specified element via JSON Pointer
+
+ Uses a JSON pointer to retrieve a reference to the respective JSON value.
+ No bound checking is performed. Similar to @ref operator[](const typename
+ object_t::key_type&), `null` values are created in arrays and objects if
+ necessary.
+
+ In particular:
+ - If the JSON pointer points to an object key that does not exist, it
+ is created an filled with a `null` value before a reference to it
+ is returned.
+ - If the JSON pointer points to an array index that does not exist, it
+ is created an filled with a `null` value before a reference to it
+ is returned. All indices between the current maximum and the given
+ index are also filled with `null`.
+ - The special value `-` is treated as a synonym for the index past the
+ end.
+
+ @param[in] ptr a JSON pointer
+
+ @return reference to the element pointed to by @a ptr
+
+ @complexity Constant.
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+
+ @liveexample{The behavior is shown in the example.,operatorjson_pointer}
+
+ @since version 2.0.0
+ */
+ reference operator[](const json_pointer& ptr)
+ {
+ return ptr.get_unchecked(this);
+ }
+
+ /*!
+ @brief access specified element via JSON Pointer
+
+ Uses a JSON pointer to retrieve a reference to the respective JSON value.
+ No bound checking is performed. The function does not change the JSON
+ value; no `null` values are created. In particular, the special value
+ `-` yields an exception.
+
+ @param[in] ptr JSON pointer to the desired element
+
+ @return const reference to the element pointed to by @a ptr
+
+ @complexity Constant.
+
+ @throw parse_error.106 if an array index begins with '0'
+ @throw parse_error.109 if an array index was not a number
+ @throw out_of_range.402 if the array index '-' is used
+ @throw out_of_range.404 if the JSON pointer can not be resolved
+
+ @liveexample{The behavior is shown in the example.,operatorjson_pointer_const}
+
+ @since version 2.0.0
+ */
+ const_reference operator[](const json_pointer& ptr) const
+ {
+ return ptr.get_unchecked(this);
+ }
+
+ /*!
+ @brief access specified element via JSON Pointer
+
+ Returns a reference to the element at with specified JSON pointer @a ptr,
+ with bounds checking.
+
+ @param[in] ptr JSON pointer to the desired element
+
+ @return reference to the element pointed to by @a ptr
+
+ @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+ begins with '0'. See example below.
+
+ @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+ is not a number. See example below.
+
+ @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+ is out of range. See example below.
+
+ @throw out_of_range.402 if the array index '-' is used in the passed JSON
+ pointer @a ptr. As `at` provides checked access (and no elements are
+ implicitly inserted), the index '-' is always invalid. See example below.
+
+ @throw out_of_range.403 if the JSON pointer describes a key of an object
+ which cannot be found. See example below.
+
+ @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+ See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
+ @since version 2.0.0
+
+ @liveexample{The behavior is shown in the example.,at_json_pointer}
+ */
+ reference at(const json_pointer& ptr)
+ {
+ return ptr.get_checked(this);
+ }
+
+ /*!
+ @brief access specified element via JSON Pointer
+
+ Returns a const reference to the element at with specified JSON pointer @a
+ ptr, with bounds checking.
+
+ @param[in] ptr JSON pointer to the desired element
+
+ @return reference to the element pointed to by @a ptr
+
+ @throw parse_error.106 if an array index in the passed JSON pointer @a ptr
+ begins with '0'. See example below.
+
+ @throw parse_error.109 if an array index in the passed JSON pointer @a ptr
+ is not a number. See example below.
+
+ @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr
+ is out of range. See example below.
+
+ @throw out_of_range.402 if the array index '-' is used in the passed JSON
+ pointer @a ptr. As `at` provides checked access (and no elements are
+ implicitly inserted), the index '-' is always invalid. See example below.
+
+ @throw out_of_range.403 if the JSON pointer describes a key of an object
+ which cannot be found. See example below.
+
+ @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved.
+ See example below.
+
+ @exceptionsafety Strong guarantee: if an exception is thrown, there are no
+ changes in the JSON value.
+
+ @complexity Constant.
+
+ @since version 2.0.0
+
+ @liveexample{The behavior is shown in the example.,at_json_pointer_const}
+ */
+ const_reference at(const json_pointer& ptr) const
+ {
+ return ptr.get_checked(this);
+ }
+
+ /*!
+ @brief return flattened JSON value
+
+ The function creates a JSON object whose keys are JSON pointers (see [RFC
+ 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all
+ primitive. The original JSON value can be restored using the @ref
+ unflatten() function.
+
+ @return an object that maps JSON pointers to primitive values
+
+ @note Empty objects and arrays are flattened to `null` and will not be
+ reconstructed correctly by the @ref unflatten() function.
+
+ @complexity Linear in the size the JSON value.
+
+ @liveexample{The following code shows how a JSON object is flattened to an
+ object whose keys consist of JSON pointers.,flatten}
+
+ @sa see @ref unflatten() for the reverse function
+
+ @since version 2.0.0
+ */
+ basic_json flatten() const
+ {
+ basic_json result(value_t::object);
+ json_pointer::flatten("", *this, result);
+ return result;
+ }
+
+ /*!
+ @brief unflatten a previously flattened JSON value
+
+ The function restores the arbitrary nesting of a JSON value that has been
+ flattened before using the @ref flatten() function. The JSON value must
+ meet certain constraints:
+ 1. The value must be an object.
+ 2. The keys must be JSON pointers (see
+ [RFC 6901](https://tools.ietf.org/html/rfc6901))
+ 3. The mapped values must be primitive JSON types.
+
+ @return the original JSON from a flattened version
+
+ @note Empty objects and arrays are flattened by @ref flatten() to `null`
+ values and can not unflattened to their original type. Apart from
+ this example, for a JSON value `j`, the following is always true:
+ `j == j.flatten().unflatten()`.
+
+ @complexity Linear in the size the JSON value.
+
+ @throw type_error.314 if value is not an object
+ @throw type_error.315 if object values are not primitive
+
+ @liveexample{The following code shows how a flattened JSON object is
+ unflattened into the original nested JSON object.,unflatten}
+
+ @sa see @ref flatten() for the reverse function
+
+ @since version 2.0.0
+ */
+ basic_json unflatten() const
+ {
+ return json_pointer::unflatten(*this);
+ }
+
+ /// @}
+
+ //////////////////////////
+ // JSON Patch functions //
+ //////////////////////////
+
+ /// @name JSON Patch functions
+ /// @{
+
+ /*!
+ @brief applies a JSON patch
+
+ [JSON Patch](http://jsonpatch.com) defines a JSON document structure for
+ expressing a sequence of operations to apply to a JSON) document. With
+ this function, a JSON Patch is applied to the current JSON value by
+ executing all operations from the patch.
+
+ @param[in] json_patch JSON patch document
+ @return patched document
+
+ @note The application of a patch is atomic: Either all operations succeed
+ and the patched document is returned or an exception is thrown. In
+ any case, the original value is not changed: the patch is applied
+ to a copy of the value.
+
+ @throw parse_error.104 if the JSON patch does not consist of an array of
+ objects
+
+ @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory
+ attributes are missing); example: `"operation add must have member path"`
+
+ @throw out_of_range.401 if an array index is out of range.
+
+ @throw out_of_range.403 if a JSON pointer inside the patch could not be
+ resolved successfully in the current JSON value; example: `"key baz not
+ found"`
+
+ @throw out_of_range.405 if JSON pointer has no parent ("add", "remove",
+ "move")
+
+ @throw other_error.501 if "test" operation was unsuccessful
+
+ @complexity Linear in the size of the JSON value and the length of the
+ JSON patch. As usually only a fraction of the JSON value is affected by
+ the patch, the complexity can usually be neglected.
+
+ @liveexample{The following code shows how a JSON patch is applied to a
+ value.,patch}
+
+ @sa see @ref diff -- create a JSON patch by comparing two JSON values
+
+ @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
+ @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901)
+
+ @since version 2.0.0
+ */
+ basic_json patch(const basic_json& json_patch) const
+ {
+ // make a working copy to apply the patch to
+ basic_json result = *this;
+
+ // the valid JSON Patch operations
+ enum class patch_operations {add, remove, replace, move, copy, test, invalid};
+
+ const auto get_op = [](const std::string & op)
+ {
+ if (op == "add")
+ {
+ return patch_operations::add;
+ }
+ if (op == "remove")
+ {
+ return patch_operations::remove;
+ }
+ if (op == "replace")
+ {
+ return patch_operations::replace;
+ }
+ if (op == "move")
+ {
+ return patch_operations::move;
+ }
+ if (op == "copy")
+ {
+ return patch_operations::copy;
+ }
+ if (op == "test")
+ {
+ return patch_operations::test;
+ }
+
+ return patch_operations::invalid;
+ };
+
+ // wrapper for "add" operation; add value at ptr
+ const auto operation_add = [&result](json_pointer & ptr, basic_json val)
+ {
+ // adding to the root of the target document means replacing it
+ if (ptr.empty())
+ {
+ result = val;
+ return;
+ }
+
+ // make sure the top element of the pointer exists
+ json_pointer top_pointer = ptr.top();
+ if (top_pointer != ptr)
+ {
+ result.at(top_pointer);
+ }
+
+ // get reference to parent of JSON pointer ptr
+ const auto last_path = ptr.back();
+ ptr.pop_back();
+ basic_json& parent = result[ptr];
+
+ switch (parent.m_type)
+ {
+ case value_t::null:
+ case value_t::object:
+ {
+ // use operator[] to add value
+ parent[last_path] = val;
+ break;
+ }
+
+ case value_t::array:
+ {
+ if (last_path == "-")
+ {
+ // special case: append to back
+ parent.push_back(val);
+ }
+ else
+ {
+ const auto idx = json_pointer::array_index(last_path);
+ if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
+ {
+ // avoid undefined behavior
+ JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent));
+ }
+
+ // default case: insert add offset
+ parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
+ }
+ break;
+ }
+
+ // if there exists a parent it cannot be primitive
+ case value_t::string: // LCOV_EXCL_LINE
+ case value_t::boolean: // LCOV_EXCL_LINE
+ case value_t::number_integer: // LCOV_EXCL_LINE
+ case value_t::number_unsigned: // LCOV_EXCL_LINE
+ case value_t::number_float: // LCOV_EXCL_LINE
+ case value_t::binary: // LCOV_EXCL_LINE
+ case value_t::discarded: // LCOV_EXCL_LINE
+ default: // LCOV_EXCL_LINE
+ JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
+ }
+ };
+
+ // wrapper for "remove" operation; remove value at ptr
+ const auto operation_remove = [this, &result](json_pointer & ptr)
+ {
+ // get reference to parent of JSON pointer ptr
+ const auto last_path = ptr.back();
+ ptr.pop_back();
+ basic_json& parent = result.at(ptr);
+
+ // remove child
+ if (parent.is_object())
+ {
+ // perform range check
+ auto it = parent.find(last_path);
+ if (JSON_HEDLEY_LIKELY(it != parent.end()))
+ {
+ parent.erase(it);
+ }
+ else
+ {
+ JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this));
+ }
+ }
+ else if (parent.is_array())
+ {
+ // note erase performs range check
+ parent.erase(json_pointer::array_index(last_path));
+ }
+ };
+
+ // type check: top level value must be an array
+ if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
+ {
+ JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch));
+ }
+
+ // iterate and apply the operations
+ for (const auto& val : json_patch)
+ {
+ // wrapper to get a value for an operation
+ const auto get_value = [&val](const std::string & op,
+ const std::string & member,
+ bool string_type) -> basic_json &
+ {
+ // find value
+ auto it = val.m_value.object->find(member);
+
+ // context-sensitive error message
+ const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'";
+
+ // check if desired value is present
+ if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
+ {
+ // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
+ JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val));
+ }
+
+ // check if result is of type string
+ if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
+ {
+ // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
+ JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val));
+ }
+
+ // no error: return value
+ return it->second;
+ };
+
+ // type check: every element of the array must be an object
+ if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
+ {
+ JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val));
+ }
+
+ // collect mandatory members
+ const auto op = get_value("op", "op", true).template get<std::string>();
+ const auto path = get_value(op, "path", true).template get<std::string>();
+ json_pointer ptr(path);
+
+ switch (get_op(op))
+ {
+ case patch_operations::add:
+ {
+ operation_add(ptr, get_value("add", "value", false));
+ break;
+ }
+
+ case patch_operations::remove:
+ {
+ operation_remove(ptr);
+ break;
+ }
+
+ case patch_operations::replace:
+ {
+ // the "path" location must exist - use at()
+ result.at(ptr) = get_value("replace", "value", false);
+ break;
+ }
+
+ case patch_operations::move:
+ {
+ const auto from_path = get_value("move", "from", true).template get<std::string>();
+ json_pointer from_ptr(from_path);
+
+ // the "from" location must exist - use at()
+ basic_json v = result.at(from_ptr);
+
+ // The move operation is functionally identical to a
+ // "remove" operation on the "from" location, followed
+ // immediately by an "add" operation at the target
+ // location with the value that was just removed.
+ operation_remove(from_ptr);
+ operation_add(ptr, v);
+ break;
+ }
+
+ case patch_operations::copy:
+ {
+ const auto from_path = get_value("copy", "from", true).template get<std::string>();
+ const json_pointer from_ptr(from_path);
+
+ // the "from" location must exist - use at()
+ basic_json v = result.at(from_ptr);
+
+ // The copy is functionally identical to an "add"
+ // operation at the target location using the value
+ // specified in the "from" member.
+ operation_add(ptr, v);
+ break;
+ }
+
+ case patch_operations::test:
+ {
+ bool success = false;
+ JSON_TRY
+ {
+ // check if "value" matches the one at "path"
+ // the "path" location must exist - use at()
+ success = (result.at(ptr) == get_value("test", "value", false));
+ }
+ JSON_INTERNAL_CATCH (out_of_range&)
+ {
+ // ignore out of range errors: success remains false
+ }
+
+ // throw an exception if test fails
+ if (JSON_HEDLEY_UNLIKELY(!success))
+ {
+ JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val));
+ }
+
+ break;
+ }
+
+ case patch_operations::invalid:
+ default:
+ {
+ // op must be "add", "remove", "replace", "move", "copy", or
+ // "test"
+ JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /*!
+ @brief creates a diff as a JSON patch
+
+ Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can
+ be changed into the value @a target by calling @ref patch function.
+
+ @invariant For two JSON values @a source and @a target, the following code
+ yields always `true`:
+ @code {.cpp}
+ source.patch(diff(source, target)) == target;
+ @endcode
+
+ @note Currently, only `remove`, `add`, and `replace` operations are
+ generated.
+
+ @param[in] source JSON value to compare from
+ @param[in] target JSON value to compare against
+ @param[in] path helper value to create JSON pointers
+
+ @return a JSON patch to convert the @a source to @a target
+
+ @complexity Linear in the lengths of @a source and @a target.
+
+ @liveexample{The following code shows how a JSON patch is created as a
+ diff for two JSON values.,diff}
+
+ @sa see @ref patch -- apply a JSON patch
+ @sa see @ref merge_patch -- apply a JSON Merge Patch
+
+ @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902)
+
+ @since version 2.0.0
+ */
+ JSON_HEDLEY_WARN_UNUSED_RESULT
+ static basic_json diff(const basic_json& source, const basic_json& target,
+ const std::string& path = "")
+ {
+ // the patch
+ basic_json result(value_t::array);
+
+ // if the values are the same, return empty patch
+ if (source == target)
+ {
+ return result;
+ }
+
+ if (source.type() != target.type())
+ {
+ // different types: replace value
+ result.push_back(
+ {
+ {"op", "replace"}, {"path", path}, {"value", target}
+ });
+ return result;
+ }
+
+ switch (source.type())
+ {
+ case value_t::array:
+ {
+ // first pass: traverse common elements
+ std::size_t i = 0;
+ while (i < source.size() && i < target.size())
+ {
+ // recursive call to compare array values at index i
+ auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
+ result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+ ++i;
+ }
+
+ // i now reached the end of at least one array
+ // in a second pass, traverse the remaining elements
+
+ // remove my remaining elements
+ const auto end_index = static_cast<difference_type>(result.size());
+ while (i < source.size())
+ {
+ // add operations in reverse order to avoid invalid
+ // indices
+ result.insert(result.begin() + end_index, object(
+ {
+ {"op", "remove"},
+ {"path", path + "/" + std::to_string(i)}
+ }));
+ ++i;
+ }
+
+ // add other remaining elements
+ while (i < target.size())
+ {
+ result.push_back(
+ {
+ {"op", "add"},
+ {"path", path + "/-"},
+ {"value", target[i]}
+ });
+ ++i;
+ }
+
+ break;
+ }
+
+ case value_t::object:
+ {
+ // first pass: traverse this object's elements
+ for (auto it = source.cbegin(); it != source.cend(); ++it)
+ {
+ // escape the key name to be used in a JSON patch
+ const auto path_key = path + "/" + detail::escape(it.key());
+
+ if (target.find(it.key()) != target.end())
+ {
+ // recursive call to compare object values at key it
+ auto temp_diff = diff(it.value(), target[it.key()], path_key);
+ result.insert(result.end(), temp_diff.begin(), temp_diff.end());
+ }
+ else
+ {
+ // found a key that is not in o -> remove it
+ result.push_back(object(
+ {
+ {"op", "remove"}, {"path", path_key}
+ }));
+ }
+ }
+
+ // second pass: traverse other object's elements
+ for (auto it = target.cbegin(); it != target.cend(); ++it)
+ {
+ if (source.find(it.key()) == source.end())
+ {
+ // found a key that is not in this -> add it
+ const auto path_key = path + "/" + detail::escape(it.key());
+ result.push_back(
+ {
+ {"op", "add"}, {"path", path_key},
+ {"value", it.value()}
+ });
+ }
+ }
+
+ break;
+ }
+
+ case value_t::null:
+ case value_t::string:
+ case value_t::boolean:
+ case value_t::number_integer:
+ case value_t::number_unsigned:
+ case value_t::number_float:
+ case value_t::binary:
+ case value_t::discarded:
+ default:
+ {
+ // both primitive type: replace value
+ result.push_back(
+ {
+ {"op", "replace"}, {"path", path}, {"value", target}
+ });
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /// @}
+
+ ////////////////////////////////
+ // JSON Merge Patch functions //
+ ////////////////////////////////
+
+ /// @name JSON Merge Patch functions
+ /// @{
+
+ /*!
+ @brief applies a JSON Merge Patch
+
+ The merge patch format is primarily intended for use with the HTTP PATCH
+ method as a means of describing a set of modifications to a target
+ resource's content. This function applies a merge patch to the current
+ JSON value.
+
+ The function implements the following algorithm from Section 2 of
+ [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396):
+
+ ```
+ define MergePatch(Target, Patch):
+ if Patch is an Object:
+ if Target is not an Object:
+ Target = {} // Ignore the contents and set it to an empty Object
+ for each Name/Value pair in Patch:
+ if Value is null:
+ if Name exists in Target:
+ remove the Name/Value pair from Target
+ else:
+ Target[Name] = MergePatch(Target[Name], Value)
+ return Target
+ else:
+ return Patch
+ ```
+
+ Thereby, `Target` is the current object; that is, the patch is applied to
+ the current value.
+
+ @param[in] apply_patch the patch to apply
+
+ @complexity Linear in the lengths of @a patch.
+
+ @liveexample{The following code shows how a JSON Merge Patch is applied to
+ a JSON document.,merge_patch}
+
+ @sa see @ref patch -- apply a JSON patch
+ @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396)
+
+ @since version 3.0.0
+ */
+ void merge_patch(const basic_json& apply_patch)
+ {
+ if (apply_patch.is_object())
+ {
+ if (!is_object())
+ {
+ *this = object();
+ }
+ for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
+ {
+ if (it.value().is_null())
+ {
+ erase(it.key());
+ }
+ else
+ {
+ operator[](it.key()).merge_patch(it.value());
+ }
+ }
+ }
+ else
+ {
+ *this = apply_patch;
+ }
+ }
+
+ /// @}
+};
+
+/*!
+@brief user-defined to_string function for JSON values
+
+This function implements a user-defined to_string for JSON objects.
+
+@param[in] j a JSON object
+@return a std::string object
+*/
+
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
+{
+ return j.dump();
+}
+} // namespace nlohmann
+
+///////////////////////
+// nonmember support //
+///////////////////////
+
+namespace std // NOLINT(cert-dcl58-cpp)
+{
+
+/// hash value for JSON objects
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
+{
+ /*!
+ @brief return a hash value for a JSON object
+
+ @since version 1.0.0, extended for arbitrary basic_json types in 3.10.5.
+ */
+ std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
+ {
+ return nlohmann::detail::hash(j);
+ }
+};
+
+/// specialization for std::less<value_t>
+/// @note: do not remove the space after '<',
+/// see https://github.com/nlohmann/json/pull/679
+template<>
+struct less< ::nlohmann::detail::value_t>
+{
+ /*!
+ @brief compare two value_t enum values
+ @since version 3.0.0
+ */
+ bool operator()(nlohmann::detail::value_t lhs,
+ nlohmann::detail::value_t rhs) const noexcept
+ {
+ return nlohmann::detail::operator<(lhs, rhs);
+ }
+};
+
+// C++20 prohibit function specialization in the std namespace.
+#ifndef JSON_HAS_CPP_20
+
+/*!
+@brief exchanges the values of two JSON objects
+
+@since version 1.0.0, extended for arbitrary basic_json types in 3.10.5.
+*/
+NLOHMANN_BASIC_JSON_TPL_DECLARATION
+inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name)
+ is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression)
+ is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
+{
+ j1.swap(j2);
+}
+
+#endif
+
+} // namespace std
+
+/*!
+@brief user-defined string literal for JSON values
+
+This operator implements a user-defined string literal for JSON objects. It
+can be used by adding `"_json"` to a string literal and returns a JSON object
+if no parse error occurred.
+
+@param[in] s a string representation of a JSON object
+@param[in] n the length of string @a s
+@return a JSON object
+
+@since version 1.0.0
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json operator "" _json(const char* s, std::size_t n)
+{
+ return nlohmann::json::parse(s, s + n);
+}
+
+/*!
+@brief user-defined string literal for JSON pointer
+
+This operator implements a user-defined string literal for JSON Pointers. It
+can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
+object if no parse error occurred.
+
+@param[in] s a string representation of a JSON Pointer
+@param[in] n the length of string @a s
+@return a JSON pointer object
+
+@since version 2.0.0
+*/
+JSON_HEDLEY_NON_NULL(1)
+inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
+{
+ return nlohmann::json::json_pointer(std::string(s, n));
+}
+
+// #include <nlohmann/detail/macro_unscope.hpp>
+
+
+// restore clang diagnostic settings
+#if defined(__clang__)
+ #pragma clang diagnostic pop
+#endif
+
+// clean up
+#undef JSON_ASSERT
+#undef JSON_INTERNAL_CATCH
+#undef JSON_CATCH
+#undef JSON_THROW
+#undef JSON_TRY
+#undef JSON_PRIVATE_UNLESS_TESTED
+#undef JSON_HAS_CPP_11
+#undef JSON_HAS_CPP_14
+#undef JSON_HAS_CPP_17
+#undef JSON_HAS_CPP_20
+#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
+#undef NLOHMANN_BASIC_JSON_TPL
+#undef JSON_EXPLICIT
+#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
+
+// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
+
+
+#undef JSON_HEDLEY_ALWAYS_INLINE
+#undef JSON_HEDLEY_ARM_VERSION
+#undef JSON_HEDLEY_ARM_VERSION_CHECK
+#undef JSON_HEDLEY_ARRAY_PARAM
+#undef JSON_HEDLEY_ASSUME
+#undef JSON_HEDLEY_BEGIN_C_DECLS
+#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
+#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
+#undef JSON_HEDLEY_CLANG_HAS_FEATURE
+#undef JSON_HEDLEY_CLANG_HAS_WARNING
+#undef JSON_HEDLEY_COMPCERT_VERSION
+#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
+#undef JSON_HEDLEY_CONCAT
+#undef JSON_HEDLEY_CONCAT3
+#undef JSON_HEDLEY_CONCAT3_EX
+#undef JSON_HEDLEY_CONCAT_EX
+#undef JSON_HEDLEY_CONST
+#undef JSON_HEDLEY_CONSTEXPR
+#undef JSON_HEDLEY_CONST_CAST
+#undef JSON_HEDLEY_CPP_CAST
+#undef JSON_HEDLEY_CRAY_VERSION
+#undef JSON_HEDLEY_CRAY_VERSION_CHECK
+#undef JSON_HEDLEY_C_DECL
+#undef JSON_HEDLEY_DEPRECATED
+#undef JSON_HEDLEY_DEPRECATED_FOR
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
+#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
+#undef JSON_HEDLEY_DIAGNOSTIC_POP
+#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
+#undef JSON_HEDLEY_DMC_VERSION
+#undef JSON_HEDLEY_DMC_VERSION_CHECK
+#undef JSON_HEDLEY_EMPTY_BASES
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
+#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
+#undef JSON_HEDLEY_END_C_DECLS
+#undef JSON_HEDLEY_FLAGS
+#undef JSON_HEDLEY_FLAGS_CAST
+#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_BUILTIN
+#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GCC_HAS_EXTENSION
+#undef JSON_HEDLEY_GCC_HAS_FEATURE
+#undef JSON_HEDLEY_GCC_HAS_WARNING
+#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
+#undef JSON_HEDLEY_GCC_VERSION
+#undef JSON_HEDLEY_GCC_VERSION_CHECK
+#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
+#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
+#undef JSON_HEDLEY_GNUC_HAS_FEATURE
+#undef JSON_HEDLEY_GNUC_HAS_WARNING
+#undef JSON_HEDLEY_GNUC_VERSION
+#undef JSON_HEDLEY_GNUC_VERSION_CHECK
+#undef JSON_HEDLEY_HAS_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_BUILTIN
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
+#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
+#undef JSON_HEDLEY_HAS_EXTENSION
+#undef JSON_HEDLEY_HAS_FEATURE
+#undef JSON_HEDLEY_HAS_WARNING
+#undef JSON_HEDLEY_IAR_VERSION
+#undef JSON_HEDLEY_IAR_VERSION_CHECK
+#undef JSON_HEDLEY_IBM_VERSION
+#undef JSON_HEDLEY_IBM_VERSION_CHECK
+#undef JSON_HEDLEY_IMPORT
+#undef JSON_HEDLEY_INLINE
+#undef JSON_HEDLEY_INTEL_CL_VERSION
+#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
+#undef JSON_HEDLEY_INTEL_VERSION
+#undef JSON_HEDLEY_INTEL_VERSION_CHECK
+#undef JSON_HEDLEY_IS_CONSTANT
+#undef JSON_HEDLEY_IS_CONSTEXPR_
+#undef JSON_HEDLEY_LIKELY
+#undef JSON_HEDLEY_MALLOC
+#undef JSON_HEDLEY_MCST_LCC_VERSION
+#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
+#undef JSON_HEDLEY_MESSAGE
+#undef JSON_HEDLEY_MSVC_VERSION
+#undef JSON_HEDLEY_MSVC_VERSION_CHECK
+#undef JSON_HEDLEY_NEVER_INLINE
+#undef JSON_HEDLEY_NON_NULL
+#undef JSON_HEDLEY_NO_ESCAPE
+#undef JSON_HEDLEY_NO_RETURN
+#undef JSON_HEDLEY_NO_THROW
+#undef JSON_HEDLEY_NULL
+#undef JSON_HEDLEY_PELLES_VERSION
+#undef JSON_HEDLEY_PELLES_VERSION_CHECK
+#undef JSON_HEDLEY_PGI_VERSION
+#undef JSON_HEDLEY_PGI_VERSION_CHECK
+#undef JSON_HEDLEY_PREDICT
+#undef JSON_HEDLEY_PRINTF_FORMAT
+#undef JSON_HEDLEY_PRIVATE
+#undef JSON_HEDLEY_PUBLIC
+#undef JSON_HEDLEY_PURE
+#undef JSON_HEDLEY_REINTERPRET_CAST
+#undef JSON_HEDLEY_REQUIRE
+#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
+#undef JSON_HEDLEY_REQUIRE_MSG
+#undef JSON_HEDLEY_RESTRICT
+#undef JSON_HEDLEY_RETURNS_NON_NULL
+#undef JSON_HEDLEY_SENTINEL
+#undef JSON_HEDLEY_STATIC_ASSERT
+#undef JSON_HEDLEY_STATIC_CAST
+#undef JSON_HEDLEY_STRINGIFY
+#undef JSON_HEDLEY_STRINGIFY_EX
+#undef JSON_HEDLEY_SUNPRO_VERSION
+#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
+#undef JSON_HEDLEY_TINYC_VERSION
+#undef JSON_HEDLEY_TINYC_VERSION_CHECK
+#undef JSON_HEDLEY_TI_ARMCL_VERSION
+#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL2000_VERSION
+#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL430_VERSION
+#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL6X_VERSION
+#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CL7X_VERSION
+#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
+#undef JSON_HEDLEY_TI_CLPRU_VERSION
+#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
+#undef JSON_HEDLEY_TI_VERSION
+#undef JSON_HEDLEY_TI_VERSION_CHECK
+#undef JSON_HEDLEY_UNAVAILABLE
+#undef JSON_HEDLEY_UNLIKELY
+#undef JSON_HEDLEY_UNPREDICTABLE
+#undef JSON_HEDLEY_UNREACHABLE
+#undef JSON_HEDLEY_UNREACHABLE_RETURN
+#undef JSON_HEDLEY_VERSION
+#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
+#undef JSON_HEDLEY_VERSION_DECODE_MINOR
+#undef JSON_HEDLEY_VERSION_DECODE_REVISION
+#undef JSON_HEDLEY_VERSION_ENCODE
+#undef JSON_HEDLEY_WARNING
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT
+#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
+#undef JSON_HEDLEY_FALL_THROUGH
+
+
+
+#endif // INCLUDE_NLOHMANN_JSON_HPP_
diff --git a/Documents/设计/~$设计.xlsx b/Documents/设计/~$设计.xlsx
new file mode 100644
index 0000000..6e8f159
--- /dev/null
+++ b/Documents/设计/~$设计.xlsx
Binary files differ
diff --git a/Documents/设计/设计.xlsx b/Documents/设计/设计.xlsx
new file mode 100644
index 0000000..aa2b56a
--- /dev/null
+++ b/Documents/设计/设计.xlsx
Binary files differ